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