Namespaces

  • Nette
    • Application
      • Diagnostics
      • Responses
      • Routers
      • UI
    • Caching
      • Storages
    • ComponentModel
    • Config
      • Extensions
    • Database
      • Diagnostics
      • Drivers
      • Reflection
      • Table
    • DI
      • Diagnostics
    • Diagnostics
    • Forms
      • Controls
      • Rendering
    • Http
    • Iterators
    • Latte
      • Macros
    • Loaders
    • Localization
    • Mail
    • Reflection
    • Security
      • Diagnostics
    • Templating
    • Utils
      • PhpGenerator
  • NetteModule
  • None
  • PHP

Classes

  • Application
  • PresenterFactory
  • Request

Interfaces

  • IPresenter
  • IPresenterFactory
  • IResponse
  • IRouter

Exceptions

  • AbortException
  • ApplicationException
  • BadRequestException
  • ForbiddenRequestException
  • InvalidPresenterException
  • Overview
  • Namespace
  • Class
  • Tree
  1: <?php
  2: 
  3: /**
  4:  * This file is part of the Nette Framework (http://nette.org)
  5:  *
  6:  * Copyright (c) 2004 David Grudl (http://davidgrudl.com)
  7:  *
  8:  * For the full copyright and license information, please view
  9:  * the file license.txt that was distributed with this source code.
 10:  */
 11: 
 12: namespace Nette\Application;
 13: 
 14: use Nette;
 15: 
 16: 
 17: 
 18: /**
 19:  * Front Controller.
 20:  *
 21:  * @author     David Grudl
 22:  *
 23:  * @property-read array $requests
 24:  * @property-read IPresenter $presenter
 25:  * @property-read IRouter $router
 26:  * @property-read IPresenterFactory $presenterFactory
 27:  */
 28: class Application extends Nette\Object
 29: {
 30:     /** @var int */
 31:     public static $maxLoop = 20;
 32: 
 33:     /** @var bool enable fault barrier? */
 34:     public $catchExceptions;
 35: 
 36:     /** @var string */
 37:     public $errorPresenter;
 38: 
 39:     /** @var array of function(Application $sender); Occurs before the application loads presenter */
 40:     public $onStartup;
 41: 
 42:     /** @var array of function(Application $sender, \Exception $e = NULL); Occurs before the application shuts down */
 43:     public $onShutdown;
 44: 
 45:     /** @var array of function(Application $sender, Request $request); Occurs when a new request is ready for dispatch */
 46:     public $onRequest;
 47: 
 48:     /** @var array of function(Application $sender, IResponse $response); Occurs when a new response is received */
 49:     public $onResponse;
 50: 
 51:     /** @var array of function(Application $sender, \Exception $e); Occurs when an unhandled exception occurs in the application */
 52:     public $onError;
 53: 
 54:     /** @deprecated */
 55:     public $allowedMethods;
 56: 
 57:     /** @var array of Request */
 58:     private $requests = array();
 59: 
 60:     /** @var IPresenter */
 61:     private $presenter;
 62: 
 63:     /** @var Nette\Http\IRequest */
 64:     private $httpRequest;
 65: 
 66:     /** @var Nette\Http\IResponse */
 67:     private $httpResponse;
 68: 
 69:     /** @var Nette\Http\Session */
 70:     private $session;
 71: 
 72:     /** @var IPresenterFactory */
 73:     private $presenterFactory;
 74: 
 75:     /** @var IRouter */
 76:     private $router;
 77: 
 78: 
 79: 
 80:     public function __construct(IPresenterFactory $presenterFactory, IRouter $router, Nette\Http\IRequest $httpRequest,
 81:         Nette\Http\IResponse $httpResponse, Nette\Http\Session $session)
 82:     {
 83:         $this->httpRequest = $httpRequest;
 84:         $this->httpResponse = $httpResponse;
 85:         $this->session = $session;
 86:         $this->presenterFactory = $presenterFactory;
 87:         $this->router = $router;
 88:     }
 89: 
 90: 
 91: 
 92:     /**
 93:      * Dispatch a HTTP request to a front controller.
 94:      * @return void
 95:      */
 96:     public function run()
 97:     {
 98:         $request = NULL;
 99:         $repeatedError = FALSE;
100:         do {
101:             try {
102:                 if (count($this->requests) > self::$maxLoop) {
103:                     throw new ApplicationException('Too many loops detected in application life cycle.');
104:                 }
105: 
106:                 if (!$request) {
107:                     $this->onStartup($this);
108: 
109:                     $request = $this->router->match($this->httpRequest);
110:                     if (!$request instanceof Request) {
111:                         $request = NULL;
112:                         throw new BadRequestException('No route for HTTP request.');
113:                     }
114: 
115:                     if (strcasecmp($request->getPresenterName(), $this->errorPresenter) === 0) {
116:                         throw new BadRequestException('Invalid request. Presenter is not achievable.');
117:                     }
118:                 }
119: 
120:                 $this->requests[] = $request;
121:                 $this->onRequest($this, $request);
122: 
123:                 // Instantiate presenter
124:                 $presenterName = $request->getPresenterName();
125:                 try {
126:                     $this->presenter = $this->presenterFactory->createPresenter($presenterName);
127:                 } catch (InvalidPresenterException $e) {
128:                     throw new BadRequestException($e->getMessage(), 404, $e);
129:                 }
130: 
131:                 $this->presenterFactory->getPresenterClass($presenterName);
132:                 $request->setPresenterName($presenterName);
133:                 $request->freeze();
134: 
135:                 // Execute presenter
136:                 $response = $this->presenter->run($request);
137:                 if ($response) {
138:                     $this->onResponse($this, $response);
139:                 }
140: 
141:                 // Send response
142:                 if ($response instanceof Responses\ForwardResponse) {
143:                     $request = $response->getRequest();
144:                     continue;
145: 
146:                 } elseif ($response instanceof IResponse) {
147:                     $response->send($this->httpRequest, $this->httpResponse);
148:                 }
149:                 break;
150: 
151:             } catch (\Exception $e) {
152:                 // fault barrier
153:                 $this->onError($this, $e);
154: 
155:                 if (!$this->catchExceptions) {
156:                     $this->onShutdown($this, $e);
157:                     throw $e;
158:                 }
159: 
160:                 if ($repeatedError) {
161:                     $e = new ApplicationException('An error occurred while executing error-presenter', 0, $e);
162:                 }
163: 
164:                 if (!$this->httpResponse->isSent()) {
165:                     $this->httpResponse->setCode($e instanceof BadRequestException ? $e->getCode() : 500);
166:                 }
167: 
168:                 if (!$repeatedError && $this->errorPresenter) {
169:                     $repeatedError = TRUE;
170:                     if ($this->presenter instanceof UI\Presenter) {
171:                         try {
172:                             $this->presenter->forward(":$this->errorPresenter:", array('exception' => $e));
173:                         } catch (AbortException $foo) {
174:                             $request = $this->presenter->getLastCreatedRequest();
175:                         }
176:                     } else {
177:                         $request = new Request(
178:                             $this->errorPresenter,
179:                             Request::FORWARD,
180:                             array('exception' => $e)
181:                         );
182:                     }
183:                     // continue
184: 
185:                 } else { // default error handler
186:                     if ($e instanceof BadRequestException) {
187:                         $code = $e->getCode();
188:                     } else {
189:                         $code = 500;
190:                         Nette\Diagnostics\Debugger::log($e, Nette\Diagnostics\Debugger::ERROR);
191:                     }
192:                     require __DIR__ . '/templates/error.phtml';
193:                     break;
194:                 }
195:             }
196:         } while (1);
197: 
198:         $this->onShutdown($this, isset($e) ? $e : NULL);
199:     }
200: 
201: 
202: 
203:     /**
204:      * Returns all processed requests.
205:      * @return array of Request
206:      */
207:     final public function getRequests()
208:     {
209:         return $this->requests;
210:     }
211: 
212: 
213: 
214:     /**
215:      * Returns current presenter.
216:      * @return IPresenter
217:      */
218:     final public function getPresenter()
219:     {
220:         return $this->presenter;
221:     }
222: 
223: 
224: 
225:     /********************* services ****************d*g**/
226: 
227: 
228: 
229:     /**
230:      * Returns router.
231:      * @return IRouter
232:      */
233:     public function getRouter()
234:     {
235:         return $this->router;
236:     }
237: 
238: 
239: 
240:     /**
241:      * Returns presenter factory.
242:      * @return IPresenterFactory
243:      */
244:     public function getPresenterFactory()
245:     {
246:         return $this->presenterFactory;
247:     }
248: 
249: 
250: 
251:     /********************* request serialization ****************d*g**/
252: 
253: 
254: 
255:     /**
256:      * Stores current request to session.
257:      * @param  mixed  optional expiration time
258:      * @return string key
259:      */
260:     public function storeRequest($expiration = '+ 10 minutes')
261:     {
262:         $session = $this->session->getSection('Nette.Application/requests');
263:         do {
264:             $key = Nette\Utils\Strings::random(5);
265:         } while (isset($session[$key]));
266: 
267:         $session[$key] = end($this->requests);
268:         $session->setExpiration($expiration, $key);
269:         return $key;
270:     }
271: 
272: 
273: 
274:     /**
275:      * Restores current request to session.
276:      * @param  string key
277:      * @return void
278:      */
279:     public function restoreRequest($key)
280:     {
281:         $session = $this->session->getSection('Nette.Application/requests');
282:         if (isset($session[$key])) {
283:             $request = clone $session[$key];
284:             unset($session[$key]);
285:             $request->setFlag(Request::RESTORED, TRUE);
286:             $this->presenter->sendResponse(new Responses\ForwardResponse($request));
287:         }
288:     }
289: 
290: }
291: 
Nette Framework 2.0beta2 API API documentation generated by ApiGen 2.3.0