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 $onResponse;
45:
46:
47: public $onError;
48:
49:
50: public $allowedMethods;
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: $request = NULL;
87: $repeatedError = FALSE;
88: do {
89: try {
90: if (count($this->requests) > self::$maxLoop) {
91: throw new ApplicationException('Too many loops detected in application life cycle.');
92: }
93:
94: if (!$request) {
95: $this->onStartup($this);
96:
97: $request = $this->router->match($this->httpRequest);
98: if (!$request instanceof Request) {
99: $request = NULL;
100: throw new BadRequestException('No route for HTTP request.');
101: }
102:
103: if (strcasecmp($request->getPresenterName(), $this->errorPresenter) === 0) {
104: throw new BadRequestException('Invalid request. Presenter is not achievable.');
105: }
106: }
107:
108: $this->requests[] = $request;
109: $this->onRequest($this, $request);
110:
111:
112: $presenterName = $request->getPresenterName();
113: try {
114: $this->presenter = $this->presenterFactory->createPresenter($presenterName);
115: } catch (InvalidPresenterException $e) {
116: throw new BadRequestException($e->getMessage(), 404, $e);
117: }
118:
119: $this->presenterFactory->getPresenterClass($presenterName);
120: $request->setPresenterName($presenterName);
121: $request->freeze();
122:
123:
124: $response = $this->presenter->run($request);
125: if ($response) {
126: $this->onResponse($this, $response);
127: }
128:
129:
130: if ($response instanceof Responses\ForwardResponse) {
131: $request = $response->getRequest();
132: continue;
133:
134: } elseif ($response instanceof IResponse) {
135: $response->send($this->httpRequest, $this->httpResponse);
136: }
137: break;
138:
139: } catch (\Exception $e) {
140:
141: $this->onError($this, $e);
142:
143: if (!$this->catchExceptions) {
144: $this->onShutdown($this, $e);
145: throw $e;
146: }
147:
148: if ($repeatedError) {
149: $e = new ApplicationException('An error occurred while executing error-presenter', 0, $e);
150: }
151:
152: if (!$this->httpResponse->isSent()) {
153: $this->httpResponse->setCode($e instanceof BadRequestException ? $e->getCode() : 500);
154: }
155:
156: if (!$repeatedError && $this->errorPresenter) {
157: $repeatedError = TRUE;
158: if ($this->presenter instanceof UI\Presenter) {
159: try {
160: $this->presenter->forward(":$this->errorPresenter:", array('exception' => $e));
161: } catch (AbortException $foo) {
162: $request = $this->presenter->getLastCreatedRequest();
163: }
164: } else {
165: $request = new Request(
166: $this->errorPresenter,
167: Request::FORWARD,
168: array('exception' => $e)
169: );
170: }
171:
172:
173: } else {
174: if ($e instanceof BadRequestException) {
175: $code = $e->getCode();
176: } else {
177: $code = 500;
178: Nette\Diagnostics\Debugger::log($e, Nette\Diagnostics\Debugger::ERROR);
179: }
180: require __DIR__ . '/templates/error.phtml';
181: break;
182: }
183: }
184: } while (1);
185:
186: $this->onShutdown($this, isset($e) ? $e : NULL);
187: }
188:
189:
190: 191: 192: 193:
194: public function getRequests()
195: {
196: return $this->requests;
197: }
198:
199:
200: 201: 202: 203:
204: public function getPresenter()
205: {
206: return $this->presenter;
207: }
208:
209:
210:
211:
212:
213: 214: 215: 216:
217: public function getRouter()
218: {
219: return $this->router;
220: }
221:
222:
223: 224: 225: 226:
227: public function getPresenterFactory()
228: {
229: return $this->presenterFactory;
230: }
231:
232:
233:
234:
235:
236:
237: function storeRequest($expiration = '+ 10 minutes')
238: {
239: return $this->presenter->storeRequest($expiration);
240: }
241:
242:
243: function restoreRequest($key)
244: {
245: return $this->presenter->restoreRequest($key);
246: }
247:
248: }
249: