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