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