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