1: <?php
2:
3: 4: 5: 6: 7: 8: 9: 10:
11:
12: namespace Nette\Application;
13:
14: use Nette;
15:
16:
17: 18: 19: 20: 21: 22: 23: 24: 25: 26:
27: class Application extends Nette\Object
28: {
29:
30: public static $maxLoop = 20;
31:
32:
33: public $catchExceptions;
34:
35:
36: public $errorPresenter;
37:
38:
39: public $onStartup;
40:
41:
42: public $onShutdown;
43:
44:
45: public $onRequest;
46:
47:
48: public $onResponse;
49:
50:
51: public $onError;
52:
53:
54: public $allowedMethods;
55:
56:
57: private $requests = array();
58:
59:
60: private $presenter;
61:
62:
63: private $httpRequest;
64:
65:
66: private $httpResponse;
67:
68:
69: private $presenterFactory;
70:
71:
72: private $router;
73:
74:
75: public function __construct(IPresenterFactory $presenterFactory, IRouter $router, Nette\Http\IRequest $httpRequest, Nette\Http\IResponse $httpResponse)
76: {
77: $this->httpRequest = $httpRequest;
78: $this->httpResponse = $httpResponse;
79: $this->presenterFactory = $presenterFactory;
80: $this->router = $router;
81: }
82:
83:
84: 85: 86: 87:
88: public function run()
89: {
90: $request = NULL;
91: $repeatedError = FALSE;
92: do {
93: try {
94: if (count($this->requests) > self::$maxLoop) {
95: throw new ApplicationException('Too many loops detected in application life cycle.');
96: }
97:
98: if (!$request) {
99: $this->onStartup($this);
100:
101: $request = $this->router->match($this->httpRequest);
102: if (!$request instanceof Request) {
103: $request = NULL;
104: throw new BadRequestException('No route for HTTP request.');
105: }
106:
107: if (strcasecmp($request->getPresenterName(), $this->errorPresenter) === 0) {
108: throw new BadRequestException('Invalid request. Presenter is not achievable.');
109: }
110: }
111:
112: $this->requests[] = $request;
113: $this->onRequest($this, $request);
114:
115:
116: $presenterName = $request->getPresenterName();
117: try {
118: $this->presenter = $this->presenterFactory->createPresenter($presenterName);
119: } catch (InvalidPresenterException $e) {
120: throw new BadRequestException($e->getMessage(), 404, $e);
121: }
122:
123: $this->presenterFactory->getPresenterClass($presenterName);
124: $request->setPresenterName($presenterName);
125: $request->freeze();
126:
127:
128: $response = $this->presenter->run($request);
129: if ($response) {
130: $this->onResponse($this, $response);
131: }
132:
133:
134: if ($response instanceof Responses\ForwardResponse) {
135: $request = $response->getRequest();
136: continue;
137:
138: } elseif ($response instanceof IResponse) {
139: $response->send($this->httpRequest, $this->httpResponse);
140: }
141: break;
142:
143: } catch (\Exception $e) {
144:
145: $this->onError($this, $e);
146:
147: if (!$this->catchExceptions) {
148: $this->onShutdown($this, $e);
149: throw $e;
150: }
151:
152: if ($repeatedError) {
153: $e = new ApplicationException('An error occurred while executing error-presenter', 0, $e);
154: }
155:
156: if (!$this->httpResponse->isSent()) {
157: $this->httpResponse->setCode($e instanceof BadRequestException ? $e->getCode() : 500);
158: }
159:
160: if (!$repeatedError && $this->errorPresenter) {
161: $repeatedError = TRUE;
162: if ($this->presenter instanceof UI\Presenter) {
163: try {
164: $this->presenter->forward(":$this->errorPresenter:", array('exception' => $e));
165: } catch (AbortException $foo) {
166: $request = $this->presenter->getLastCreatedRequest();
167: }
168: } else {
169: $request = new Request(
170: $this->errorPresenter,
171: Request::FORWARD,
172: array('exception' => $e)
173: );
174: }
175:
176:
177: } else {
178: if ($e instanceof BadRequestException) {
179: $code = $e->getCode();
180: } else {
181: $code = 500;
182: Nette\Diagnostics\Debugger::log($e, Nette\Diagnostics\Debugger::ERROR);
183: }
184: require __DIR__ . '/templates/error.phtml';
185: break;
186: }
187: }
188: } while (1);
189:
190: $this->onShutdown($this, isset($e) ? $e : NULL);
191: }
192:
193:
194: 195: 196: 197:
198: final public function getRequests()
199: {
200: return $this->requests;
201: }
202:
203:
204: 205: 206: 207:
208: final public function getPresenter()
209: {
210: return $this->presenter;
211: }
212:
213:
214:
215:
216:
217: 218: 219: 220:
221: public function getRouter()
222: {
223: return $this->router;
224: }
225:
226:
227: 228: 229: 230:
231: public function getPresenterFactory()
232: {
233: return $this->presenterFactory;
234: }
235:
236:
237:
238:
239:
240:
241: function storeRequest($expiration = '+ 10 minutes')
242: {
243: return $this->presenter->storeRequest($expiration);
244: }
245:
246:
247: function restoreRequest($key)
248: {
249: return $this->presenter->restoreRequest($key);
250: }
251:
252: }
253: