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