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