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