1: <?php
2:
3: 4: 5: 6: 7: 8: 9: 10: 11:
12:
13:
14:
15: 16: 17: 18: 19: 20:
21: class NApplication extends NObject
22: {
23:
24: public static $maxLoop = 20;
25:
26:
27: public $defaultServices = array(
28: 'Nette\\Application\\IRouter' => 'NMultiRouter',
29: 'Nette\\Application\\IPresenterLoader' => array(__CLASS__, 'createPresenterLoader'),
30: );
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 $onError;
49:
50:
51: public $allowedMethods = array('GET', 'POST', 'HEAD', 'PUT', 'DELETE');
52:
53:
54: private $requests = array();
55:
56:
57: private $presenter;
58:
59:
60: private $serviceLocator;
61:
62:
63:
64: 65: 66: 67:
68: public function run()
69: {
70: $httpRequest = $this->getHttpRequest();
71: $httpResponse = $this->getHttpResponse();
72:
73: $httpRequest->setEncoding('UTF-8');
74: $httpResponse->setHeader('X-Powered-By', 'Nette Framework');
75:
76: if (NEnvironment::getVariable('baseUri') === NULL) {
77: NEnvironment::setVariable('baseUri', $httpRequest->getUri()->getBasePath());
78: }
79:
80:
81: $session = $this->getSession();
82: if (!$session->isStarted() && $session->exists()) {
83: $session->start();
84: }
85:
86:
87: if ($this->allowedMethods) {
88: $method = $httpRequest->getMethod();
89: if (!in_array($method, $this->allowedMethods, TRUE)) {
90: $httpResponse->setCode(IHttpResponse::S501_NOT_IMPLEMENTED);
91: $httpResponse->setHeader('Allow', implode(',', $this->allowedMethods));
92: echo '<h1>Method ' . htmlSpecialChars($method) . ' is not implemented</h1>';
93: return;
94: }
95: }
96:
97:
98: $request = NULL;
99: $repeatedError = FALSE;
100: do {
101: try {
102: if (count($this->requests) > self::$maxLoop) {
103: throw new NApplicationException('Too many loops detected in application life cycle.');
104: }
105:
106: if (!$request) {
107: $this->onStartup($this);
108:
109:
110: $router = $this->getRouter();
111: if ($router instanceof NMultiRouter && !count($router)) {
112: $router[] = new NSimpleRouter(array(
113: 'presenter' => 'Default',
114: 'action' => 'default',
115: ));
116: }
117:
118:
119: $request = $router->match($httpRequest);
120: if (!($request instanceof NPresenterRequest)) {
121: $request = NULL;
122: throw new NBadRequestException('No route for HTTP request.');
123: }
124:
125: if (strcasecmp($request->getPresenterName(), $this->errorPresenter) === 0) {
126: throw new NBadRequestException('Invalid request.');
127: }
128: }
129:
130: $this->requests[] = $request;
131: $this->onRequest($this, $request);
132:
133:
134: $presenter = $request->getPresenterName();
135: try {
136: $class = $this->getPresenterLoader()->getPresenterClass($presenter);
137: $request->setPresenterName($presenter);
138: } catch (NInvalidPresenterException $e) {
139: throw new NBadRequestException($e->getMessage(), 404, $e);
140: }
141: $request->freeze();
142:
143:
144: $this->presenter = new $class;
145: $response = $this->presenter->run($request);
146:
147:
148: if ($response instanceof NForwardingResponse) {
149: $request = $response->getRequest();
150: continue;
151:
152: } elseif ($response instanceof IPresenterResponse) {
153: $response->send();
154: }
155: break;
156:
157: } catch (Exception $e) {
158:
159: if ($this->catchExceptions === NULL) {
160: $this->catchExceptions = NEnvironment::isProduction();
161: }
162:
163: $this->onError($this, $e);
164:
165: if (!$this->catchExceptions) {
166: $this->onShutdown($this, $e);
167: throw $e;
168: }
169:
170: if ($repeatedError) {
171: $e = new NApplicationException('An error occured while executing error-presenter', 0, $e);
172: }
173:
174: if (!$httpResponse->isSent()) {
175: $httpResponse->setCode($e instanceof NBadRequestException ? $e->getCode() : 500);
176: }
177:
178: if (!$repeatedError && $this->errorPresenter) {
179: $repeatedError = TRUE;
180: $request = new NPresenterRequest(
181: $this->errorPresenter,
182: NPresenterRequest::FORWARD,
183: array('exception' => $e)
184: );
185:
186:
187: } else {
188: echo "<meta name='robots' content='noindex'>\n\n";
189: if ($e instanceof NBadRequestException) {
190: echo "<title>404 Not Found</title>\n\n<h1>Not Found</h1>\n\n<p>The requested URL was not found on this server.</p>";
191:
192: } else {
193: NDebug::processException($e, FALSE);
194: echo "<title>500 Internal Server Error</title>\n\n<h1>Server Error</h1>\n\n",
195: "<p>The server encountered an internal error and was unable to complete your request. Please try again later.</p>";
196: }
197: echo "\n\n<hr>\n<small><i>Nette Framework</i></small>";
198: break;
199: }
200: }
201: } while (1);
202:
203: $this->onShutdown($this, isset($e) ? $e : NULL);
204: }
205:
206:
207:
208: 209: 210: 211:
212: final public function getRequests()
213: {
214: return $this->requests;
215: }
216:
217:
218:
219: 220: 221: 222:
223: final public function getPresenter()
224: {
225: return $this->presenter;
226: }
227:
228:
229:
230:
231:
232:
233:
234: 235: 236: 237:
238: final public function getServiceLocator()
239: {
240: if ($this->serviceLocator === NULL) {
241: $this->serviceLocator = new NServiceLocator(NEnvironment::getServiceLocator());
242:
243: foreach ($this->defaultServices as $name => $service) {
244: if (!$this->serviceLocator->hasService($name)) {
245: $this->serviceLocator->addService($name, $service);
246: }
247: }
248: }
249: return $this->serviceLocator;
250: }
251:
252:
253:
254: 255: 256: 257: 258: 259:
260: final public function getService($name, array $options = NULL)
261: {
262: return $this->getServiceLocator()->getService($name, $options);
263: }
264:
265:
266:
267: 268: 269: 270:
271: public function getRouter()
272: {
273: return $this->getServiceLocator()->getService('Nette\\Application\\IRouter');
274: }
275:
276:
277:
278: 279: 280: 281: 282:
283: public function setRouter(IRouter $router)
284: {
285: $this->getServiceLocator()->addService('Nette\\Application\\IRouter', $router);
286: return $this;
287: }
288:
289:
290:
291: 292: 293: 294:
295: public function getPresenterLoader()
296: {
297: return $this->getServiceLocator()->getService('Nette\\Application\\IPresenterLoader');
298: }
299:
300:
301:
302:
303:
304:
305:
306: 307: 308:
309: public static function createPresenterLoader()
310: {
311: return new NPresenterLoader(NEnvironment::getVariable('appDir'));
312: }
313:
314:
315:
316:
317:
318:
319:
320: 321: 322: 323: 324:
325: public function storeRequest($expiration = '+ 10 minutes')
326: {
327: $session = $this->getSession('Nette.Application/requests');
328: do {
329: $key = substr(md5(lcg_value()), 0, 4);
330: } while (isset($session[$key]));
331:
332: $session[$key] = end($this->requests);
333: $session->setExpiration($expiration, $key);
334: return $key;
335: }
336:
337:
338:
339: 340: 341: 342: 343:
344: public function restoreRequest($key)
345: {
346: $session = $this->getSession('Nette.Application/requests');
347: if (isset($session[$key])) {
348: $request = clone $session[$key];
349: unset($session[$key]);
350: $request->setFlag(NPresenterRequest::RESTORED, TRUE);
351: $this->presenter->terminate(new NForwardingResponse($request));
352: }
353: }
354:
355:
356:
357:
358:
359:
360:
361: 362: 363:
364: protected function getHttpRequest()
365: {
366: return NEnvironment::getHttpRequest();
367: }
368:
369:
370:
371: 372: 373:
374: protected function getHttpResponse()
375: {
376: return NEnvironment::getHttpResponse();
377: }
378:
379:
380:
381: 382: 383:
384: protected function getSession($namespace = NULL)
385: {
386: return NEnvironment::getSession($namespace);
387: }
388:
389: }
390: