|  |  |  | @ -1,4 +1,6 @@ | 
			
		
	
		
			
				
					|  |  |  |  | <?php | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | declare(strict_types=1); | 
			
		
	
		
			
				
					|  |  |  |  | /** | 
			
		
	
		
			
				
					|  |  |  |  |  * Flight: An extensible micro-framework. | 
			
		
	
		
			
				
					|  |  |  |  |  * | 
			
		
	
	
		
			
				
					|  |  |  | @ -8,8 +10,15 @@ | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | namespace flight; | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | use flight\core\Loader; | 
			
		
	
		
			
				
					|  |  |  |  | use ErrorException; | 
			
		
	
		
			
				
					|  |  |  |  | use Exception; | 
			
		
	
		
			
				
					|  |  |  |  | use flight\core\Dispatcher; | 
			
		
	
		
			
				
					|  |  |  |  | use flight\core\Loader; | 
			
		
	
		
			
				
					|  |  |  |  | use flight\net\Request; | 
			
		
	
		
			
				
					|  |  |  |  | use flight\net\Response; | 
			
		
	
		
			
				
					|  |  |  |  | use flight\net\Router; | 
			
		
	
		
			
				
					|  |  |  |  | use flight\template\View; | 
			
		
	
		
			
				
					|  |  |  |  | use Throwable; | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | /** | 
			
		
	
		
			
				
					|  |  |  |  |  * The Engine class contains the core functionality of the framework. | 
			
		
	
	
		
			
				
					|  |  |  | @ -17,23 +26,21 @@ use flight\core\Dispatcher; | 
			
		
	
		
			
				
					|  |  |  |  |  * and generating an HTTP response. | 
			
		
	
		
			
				
					|  |  |  |  |  * | 
			
		
	
		
			
				
					|  |  |  |  |  * Core methods | 
			
		
	
		
			
				
					|  |  |  |  |  * | 
			
		
	
		
			
				
					|  |  |  |  |  * @method void start() Starts engine | 
			
		
	
		
			
				
					|  |  |  |  |  * @method void stop() Stops framework and outputs current response | 
			
		
	
		
			
				
					|  |  |  |  |  * @method void halt(int $code = 200, string $message = '') Stops processing and returns a given response. | 
			
		
	
		
			
				
					|  |  |  |  |  * | 
			
		
	
		
			
				
					|  |  |  |  |  * | 
			
		
	
		
			
				
					|  |  |  |  |  * Routing | 
			
		
	
		
			
				
					|  |  |  |  |  * @method void route(string $pattern, callable $callback, bool $pass_route = false) Routes a URL to a callback function. | 
			
		
	
		
			
				
					|  |  |  |  |  * @method \flight\net\Router router() Gets router | 
			
		
	
		
			
				
					|  |  |  |  |  * @method Router router() Gets router | 
			
		
	
		
			
				
					|  |  |  |  |  * | 
			
		
	
		
			
				
					|  |  |  |  |  * Views | 
			
		
	
		
			
				
					|  |  |  |  |  * @method void render(string $file, array $data = null, string $key = null) Renders template | 
			
		
	
		
			
				
					|  |  |  |  |  * @method \flight\template\View view() Gets current view | 
			
		
	
		
			
				
					|  |  |  |  |  * @method View view() Gets current view | 
			
		
	
		
			
				
					|  |  |  |  |  * | 
			
		
	
		
			
				
					|  |  |  |  |  * Request-response | 
			
		
	
		
			
				
					|  |  |  |  |  * @method \flight\net\Request request() Gets current request | 
			
		
	
		
			
				
					|  |  |  |  |  * @method \flight\net\Response response() Gets current response | 
			
		
	
		
			
				
					|  |  |  |  |  * @method void error(\Exception $e) Sends an HTTP 500 response for any errors. | 
			
		
	
		
			
				
					|  |  |  |  |  * @method Request request() Gets current request | 
			
		
	
		
			
				
					|  |  |  |  |  * @method Response response() Gets current response | 
			
		
	
		
			
				
					|  |  |  |  |  * @method void error(Exception $e) Sends an HTTP 500 response for any errors. | 
			
		
	
		
			
				
					|  |  |  |  |  * @method void notFound() Sends an HTTP 404 response when a URL is not found. | 
			
		
	
		
			
				
					|  |  |  |  |  * @method void redirect(string $url, int $code = 303)  Redirects the current request to another URL. | 
			
		
	
		
			
				
					|  |  |  |  |  * @method void json(mixed $data, int $code = 200, bool $encode = true, string $charset = 'utf-8', int $option = 0) Sends a JSON response. | 
			
		
	
	
		
			
				
					|  |  |  | @ -43,33 +50,29 @@ use flight\core\Dispatcher; | 
			
		
	
		
			
				
					|  |  |  |  |  * @method void etag($id, string $type = 'strong') Handles ETag HTTP caching. | 
			
		
	
		
			
				
					|  |  |  |  |  * @method void lastModified(int $time) Handles last modified HTTP caching. | 
			
		
	
		
			
				
					|  |  |  |  |  */ | 
			
		
	
		
			
				
					|  |  |  |  | class Engine { | 
			
		
	
		
			
				
					|  |  |  |  | class Engine | 
			
		
	
		
			
				
					|  |  |  |  | { | 
			
		
	
		
			
				
					|  |  |  |  |     /** | 
			
		
	
		
			
				
					|  |  |  |  |      * Stored variables. | 
			
		
	
		
			
				
					|  |  |  |  |      * | 
			
		
	
		
			
				
					|  |  |  |  |      * @var array | 
			
		
	
		
			
				
					|  |  |  |  |      */ | 
			
		
	
		
			
				
					|  |  |  |  |     protected $vars; | 
			
		
	
		
			
				
					|  |  |  |  |     protected array $vars; | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     /** | 
			
		
	
		
			
				
					|  |  |  |  |      * Class loader. | 
			
		
	
		
			
				
					|  |  |  |  |      * | 
			
		
	
		
			
				
					|  |  |  |  |      * @var Loader | 
			
		
	
		
			
				
					|  |  |  |  |      */ | 
			
		
	
		
			
				
					|  |  |  |  |     protected $loader; | 
			
		
	
		
			
				
					|  |  |  |  |     protected Loader $loader; | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     /** | 
			
		
	
		
			
				
					|  |  |  |  |      * Event dispatcher. | 
			
		
	
		
			
				
					|  |  |  |  |      * | 
			
		
	
		
			
				
					|  |  |  |  |      * @var Dispatcher | 
			
		
	
		
			
				
					|  |  |  |  |      */ | 
			
		
	
		
			
				
					|  |  |  |  |     protected $dispatcher; | 
			
		
	
		
			
				
					|  |  |  |  |     protected Dispatcher $dispatcher; | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     /** | 
			
		
	
		
			
				
					|  |  |  |  |      * Constructor. | 
			
		
	
		
			
				
					|  |  |  |  |      */ | 
			
		
	
		
			
				
					|  |  |  |  |     public function __construct() { | 
			
		
	
		
			
				
					|  |  |  |  |         $this->vars = array(); | 
			
		
	
		
			
				
					|  |  |  |  |     public function __construct() | 
			
		
	
		
			
				
					|  |  |  |  |     { | 
			
		
	
		
			
				
					|  |  |  |  |         $this->vars = []; | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |         $this->loader = new Loader(); | 
			
		
	
		
			
				
					|  |  |  |  |         $this->dispatcher = new Dispatcher(); | 
			
		
	
	
		
			
				
					|  |  |  | @ -82,18 +85,21 @@ class Engine { | 
			
		
	
		
			
				
					|  |  |  |  |      * | 
			
		
	
		
			
				
					|  |  |  |  |      * @param string $name   Method name | 
			
		
	
		
			
				
					|  |  |  |  |      * @param array  $params Method parameters | 
			
		
	
		
			
				
					|  |  |  |  |      * | 
			
		
	
		
			
				
					|  |  |  |  |      *@throws Exception | 
			
		
	
		
			
				
					|  |  |  |  |      * | 
			
		
	
		
			
				
					|  |  |  |  |      * @return mixed Callback results | 
			
		
	
		
			
				
					|  |  |  |  |      * @throws \Exception | 
			
		
	
		
			
				
					|  |  |  |  |      */ | 
			
		
	
		
			
				
					|  |  |  |  |     public function __call($name, $params) { | 
			
		
	
		
			
				
					|  |  |  |  |     public function __call(string $name, array $params) | 
			
		
	
		
			
				
					|  |  |  |  |     { | 
			
		
	
		
			
				
					|  |  |  |  |         $callback = $this->dispatcher->get($name); | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |         if (is_callable($callback)) { | 
			
		
	
		
			
				
					|  |  |  |  |         if (\is_callable($callback)) { | 
			
		
	
		
			
				
					|  |  |  |  |             return $this->dispatcher->run($name, $params); | 
			
		
	
		
			
				
					|  |  |  |  |         } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |         if (!$this->loader->get($name)) { | 
			
		
	
		
			
				
					|  |  |  |  |             throw new \Exception("{$name} must be a mapped method."); | 
			
		
	
		
			
				
					|  |  |  |  |             throw new Exception("{$name} must be a mapped method."); | 
			
		
	
		
			
				
					|  |  |  |  |         } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |         $shared = (!empty($params)) ? (bool) $params[0] : true; | 
			
		
	
	
		
			
				
					|  |  |  | @ -101,17 +107,18 @@ class Engine { | 
			
		
	
		
			
				
					|  |  |  |  |         return $this->loader->load($name, $shared); | 
			
		
	
		
			
				
					|  |  |  |  |     } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     /*** Core Methods ***/ | 
			
		
	
		
			
				
					|  |  |  |  |     // Core Methods | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     /** | 
			
		
	
		
			
				
					|  |  |  |  |      * Initializes the framework. | 
			
		
	
		
			
				
					|  |  |  |  |      */ | 
			
		
	
		
			
				
					|  |  |  |  |     public function init() { | 
			
		
	
		
			
				
					|  |  |  |  |     public function init(): void | 
			
		
	
		
			
				
					|  |  |  |  |     { | 
			
		
	
		
			
				
					|  |  |  |  |         static $initialized = false; | 
			
		
	
		
			
				
					|  |  |  |  |         $self = $this; | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |         if ($initialized) { | 
			
		
	
		
			
				
					|  |  |  |  |             $this->vars = array(); | 
			
		
	
		
			
				
					|  |  |  |  |             $this->vars = []; | 
			
		
	
		
			
				
					|  |  |  |  |             $this->loader->reset(); | 
			
		
	
		
			
				
					|  |  |  |  |             $this->dispatcher->reset(); | 
			
		
	
		
			
				
					|  |  |  |  |         } | 
			
		
	
	
		
			
				
					|  |  |  | @ -120,18 +127,18 @@ class Engine { | 
			
		
	
		
			
				
					|  |  |  |  |         $this->loader->register('request', '\flight\net\Request'); | 
			
		
	
		
			
				
					|  |  |  |  |         $this->loader->register('response', '\flight\net\Response'); | 
			
		
	
		
			
				
					|  |  |  |  |         $this->loader->register('router', '\flight\net\Router'); | 
			
		
	
		
			
				
					|  |  |  |  |         $this->loader->register('view', '\flight\template\View', array(), function($view) use ($self) { | 
			
		
	
		
			
				
					|  |  |  |  |         $this->loader->register('view', '\flight\template\View', [], function ($view) use ($self) { | 
			
		
	
		
			
				
					|  |  |  |  |             $view->path = $self->get('flight.views.path'); | 
			
		
	
		
			
				
					|  |  |  |  |             $view->extension = $self->get('flight.views.extension'); | 
			
		
	
		
			
				
					|  |  |  |  |         }); | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |         // Register framework methods | 
			
		
	
		
			
				
					|  |  |  |  |         $methods = array( | 
			
		
	
		
			
				
					|  |  |  |  |         $methods = [ | 
			
		
	
		
			
				
					|  |  |  |  |             'start', 'stop', 'route', 'halt', 'error', 'notFound', | 
			
		
	
		
			
				
					|  |  |  |  |             'render','redirect','etag','lastModified','json','jsonp' | 
			
		
	
		
			
				
					|  |  |  |  |         ); | 
			
		
	
		
			
				
					|  |  |  |  |             'render', 'redirect', 'etag', 'lastModified', 'json', 'jsonp', | 
			
		
	
		
			
				
					|  |  |  |  |         ]; | 
			
		
	
		
			
				
					|  |  |  |  |         foreach ($methods as $name) { | 
			
		
	
		
			
				
					|  |  |  |  |             $this->dispatcher->set($name, array($this, '_'.$name)); | 
			
		
	
		
			
				
					|  |  |  |  |             $this->dispatcher->set($name, [$this, '_' . $name]); | 
			
		
	
		
			
				
					|  |  |  |  |         } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |         // Default configuration settings | 
			
		
	
	
		
			
				
					|  |  |  | @ -147,8 +154,8 @@ class Engine { | 
			
		
	
		
			
				
					|  |  |  |  |         $this->before('start', function () use ($self) { | 
			
		
	
		
			
				
					|  |  |  |  |             // Enable error handling | 
			
		
	
		
			
				
					|  |  |  |  |             if ($self->get('flight.handle_errors')) { | 
			
		
	
		
			
				
					|  |  |  |  |                 set_error_handler(array($self, 'handleError')); | 
			
		
	
		
			
				
					|  |  |  |  |                 set_exception_handler(array($self, 'handleException')); | 
			
		
	
		
			
				
					|  |  |  |  |                 set_error_handler([$self, 'handleError']); | 
			
		
	
		
			
				
					|  |  |  |  |                 set_exception_handler([$self, 'handleException']); | 
			
		
	
		
			
				
					|  |  |  |  |             } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |             // Set case-sensitivity | 
			
		
	
	
		
			
				
					|  |  |  | @ -167,20 +174,23 @@ class Engine { | 
			
		
	
		
			
				
					|  |  |  |  |      * @param int $errstr  Error string | 
			
		
	
		
			
				
					|  |  |  |  |      * @param int $errfile Error file name | 
			
		
	
		
			
				
					|  |  |  |  |      * @param int $errline Error file line number | 
			
		
	
		
			
				
					|  |  |  |  |      * @throws \ErrorException | 
			
		
	
		
			
				
					|  |  |  |  |      * | 
			
		
	
		
			
				
					|  |  |  |  |      * @throws ErrorException | 
			
		
	
		
			
				
					|  |  |  |  |      */ | 
			
		
	
		
			
				
					|  |  |  |  |     public function handleError($errno, $errstr, $errfile, $errline) { | 
			
		
	
		
			
				
					|  |  |  |  |     public function handleError(int $errno, int $errstr, int $errfile, int $errline) | 
			
		
	
		
			
				
					|  |  |  |  |     { | 
			
		
	
		
			
				
					|  |  |  |  |         if ($errno & error_reporting()) { | 
			
		
	
		
			
				
					|  |  |  |  |             throw new \ErrorException($errstr, $errno, 0, $errfile, $errline); | 
			
		
	
		
			
				
					|  |  |  |  |             throw new ErrorException($errstr, $errno, 0, $errfile, $errline); | 
			
		
	
		
			
				
					|  |  |  |  |         } | 
			
		
	
		
			
				
					|  |  |  |  |     } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     /** | 
			
		
	
		
			
				
					|  |  |  |  |      * Custom exception handler. Logs exceptions. | 
			
		
	
		
			
				
					|  |  |  |  |      * | 
			
		
	
		
			
				
					|  |  |  |  |      * @param \Exception $e Thrown exception | 
			
		
	
		
			
				
					|  |  |  |  |      * @param Exception $e Thrown exception | 
			
		
	
		
			
				
					|  |  |  |  |      */ | 
			
		
	
		
			
				
					|  |  |  |  |     public function handleException($e) { | 
			
		
	
		
			
				
					|  |  |  |  |     public function handleException($e): void | 
			
		
	
		
			
				
					|  |  |  |  |     { | 
			
		
	
		
			
				
					|  |  |  |  |         if ($this->get('flight.log_errors')) { | 
			
		
	
		
			
				
					|  |  |  |  |             error_log($e->getMessage()); | 
			
		
	
		
			
				
					|  |  |  |  |         } | 
			
		
	
	
		
			
				
					|  |  |  | @ -193,11 +203,13 @@ class Engine { | 
			
		
	
		
			
				
					|  |  |  |  |      * | 
			
		
	
		
			
				
					|  |  |  |  |      * @param string   $name     Method name | 
			
		
	
		
			
				
					|  |  |  |  |      * @param callback $callback Callback function | 
			
		
	
		
			
				
					|  |  |  |  |      * @throws \Exception If trying to map over a framework method | 
			
		
	
		
			
				
					|  |  |  |  |      * | 
			
		
	
		
			
				
					|  |  |  |  |      * @throws Exception If trying to map over a framework method | 
			
		
	
		
			
				
					|  |  |  |  |      */ | 
			
		
	
		
			
				
					|  |  |  |  |     public function map($name, $callback) { | 
			
		
	
		
			
				
					|  |  |  |  |     public function map(string $name, callable $callback): void | 
			
		
	
		
			
				
					|  |  |  |  |     { | 
			
		
	
		
			
				
					|  |  |  |  |         if (method_exists($this, $name)) { | 
			
		
	
		
			
				
					|  |  |  |  |             throw new \Exception('Cannot override an existing framework method.'); | 
			
		
	
		
			
				
					|  |  |  |  |             throw new Exception('Cannot override an existing framework method.'); | 
			
		
	
		
			
				
					|  |  |  |  |         } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |         $this->dispatcher->set($name, $callback); | 
			
		
	
	
		
			
				
					|  |  |  | @ -209,12 +221,14 @@ class Engine { | 
			
		
	
		
			
				
					|  |  |  |  |      * @param string        $name     Method name | 
			
		
	
		
			
				
					|  |  |  |  |      * @param string        $class    Class name | 
			
		
	
		
			
				
					|  |  |  |  |      * @param array         $params   Class initialization parameters | 
			
		
	
		
			
				
					|  |  |  |  |      * @param callback $callback Function to call after object instantiation | 
			
		
	
		
			
				
					|  |  |  |  |      * @throws \Exception If trying to map over a framework method | 
			
		
	
		
			
				
					|  |  |  |  |      * @param callable|null $callback $callback Function to call after object instantiation | 
			
		
	
		
			
				
					|  |  |  |  |      * | 
			
		
	
		
			
				
					|  |  |  |  |      * @throws Exception If trying to map over a framework method | 
			
		
	
		
			
				
					|  |  |  |  |      */ | 
			
		
	
		
			
				
					|  |  |  |  |     public function register($name, $class, array $params = array(), $callback = null) { | 
			
		
	
		
			
				
					|  |  |  |  |     public function register(string $name, string $class, array $params = [], ?callable $callback = null): void | 
			
		
	
		
			
				
					|  |  |  |  |     { | 
			
		
	
		
			
				
					|  |  |  |  |         if (method_exists($this, $name)) { | 
			
		
	
		
			
				
					|  |  |  |  |             throw new \Exception('Cannot override an existing framework method.'); | 
			
		
	
		
			
				
					|  |  |  |  |             throw new Exception('Cannot override an existing framework method.'); | 
			
		
	
		
			
				
					|  |  |  |  |         } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |         $this->loader->register($name, $class, $params, $callback); | 
			
		
	
	
		
			
				
					|  |  |  | @ -226,7 +240,8 @@ class Engine { | 
			
		
	
		
			
				
					|  |  |  |  |      * @param string   $name     Method name | 
			
		
	
		
			
				
					|  |  |  |  |      * @param callback $callback Callback function | 
			
		
	
		
			
				
					|  |  |  |  |      */ | 
			
		
	
		
			
				
					|  |  |  |  |     public function before($name, $callback) { | 
			
		
	
		
			
				
					|  |  |  |  |     public function before(string $name, callable $callback): void | 
			
		
	
		
			
				
					|  |  |  |  |     { | 
			
		
	
		
			
				
					|  |  |  |  |         $this->dispatcher->hook($name, 'before', $callback); | 
			
		
	
		
			
				
					|  |  |  |  |     } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
	
		
			
				
					|  |  |  | @ -236,35 +251,40 @@ class Engine { | 
			
		
	
		
			
				
					|  |  |  |  |      * @param string   $name     Method name | 
			
		
	
		
			
				
					|  |  |  |  |      * @param callback $callback Callback function | 
			
		
	
		
			
				
					|  |  |  |  |      */ | 
			
		
	
		
			
				
					|  |  |  |  |     public function after($name, $callback) { | 
			
		
	
		
			
				
					|  |  |  |  |     public function after(string $name, callable $callback): void | 
			
		
	
		
			
				
					|  |  |  |  |     { | 
			
		
	
		
			
				
					|  |  |  |  |         $this->dispatcher->hook($name, 'after', $callback); | 
			
		
	
		
			
				
					|  |  |  |  |     } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     /** | 
			
		
	
		
			
				
					|  |  |  |  |      * Gets a variable. | 
			
		
	
		
			
				
					|  |  |  |  |      * | 
			
		
	
		
			
				
					|  |  |  |  |      * @param string $key Key | 
			
		
	
		
			
				
					|  |  |  |  |      * @return mixed | 
			
		
	
		
			
				
					|  |  |  |  |      * @param string|null $key Key | 
			
		
	
		
			
				
					|  |  |  |  |      * | 
			
		
	
		
			
				
					|  |  |  |  |      * @return array|mixed|null | 
			
		
	
		
			
				
					|  |  |  |  |      */ | 
			
		
	
		
			
				
					|  |  |  |  |     public function get($key = null) { | 
			
		
	
		
			
				
					|  |  |  |  |         if ($key === null) return $this->vars; | 
			
		
	
		
			
				
					|  |  |  |  |     public function get(?string $key = null) | 
			
		
	
		
			
				
					|  |  |  |  |     { | 
			
		
	
		
			
				
					|  |  |  |  |         if (null === $key) { | 
			
		
	
		
			
				
					|  |  |  |  |             return $this->vars; | 
			
		
	
		
			
				
					|  |  |  |  |         } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |         return isset($this->vars[$key]) ? $this->vars[$key] : null; | 
			
		
	
		
			
				
					|  |  |  |  |         return $this->vars[$key] ?? null; | 
			
		
	
		
			
				
					|  |  |  |  |     } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     /** | 
			
		
	
		
			
				
					|  |  |  |  |      * Sets a variable. | 
			
		
	
		
			
				
					|  |  |  |  |      * | 
			
		
	
		
			
				
					|  |  |  |  |      * @param mixed      $key   Key | 
			
		
	
		
			
				
					|  |  |  |  |      * @param string $value Value | 
			
		
	
		
			
				
					|  |  |  |  |      * @param mixed|null $value Value | 
			
		
	
		
			
				
					|  |  |  |  |      */ | 
			
		
	
		
			
				
					|  |  |  |  |     public function set($key, $value = null) { | 
			
		
	
		
			
				
					|  |  |  |  |         if (is_array($key) || is_object($key)) { | 
			
		
	
		
			
				
					|  |  |  |  |     public function set($key, $value = null): void | 
			
		
	
		
			
				
					|  |  |  |  |     { | 
			
		
	
		
			
				
					|  |  |  |  |         if (\is_array($key) || \is_object($key)) { | 
			
		
	
		
			
				
					|  |  |  |  |             foreach ($key as $k => $v) { | 
			
		
	
		
			
				
					|  |  |  |  |                 $this->vars[$k] = $v; | 
			
		
	
		
			
				
					|  |  |  |  |             } | 
			
		
	
		
			
				
					|  |  |  |  |         } | 
			
		
	
		
			
				
					|  |  |  |  |         else { | 
			
		
	
		
			
				
					|  |  |  |  |         } else { | 
			
		
	
		
			
				
					|  |  |  |  |             $this->vars[$key] = $value; | 
			
		
	
		
			
				
					|  |  |  |  |         } | 
			
		
	
		
			
				
					|  |  |  |  |     } | 
			
		
	
	
		
			
				
					|  |  |  | @ -273,22 +293,24 @@ class Engine { | 
			
		
	
		
			
				
					|  |  |  |  |      * Checks if a variable has been set. | 
			
		
	
		
			
				
					|  |  |  |  |      * | 
			
		
	
		
			
				
					|  |  |  |  |      * @param string $key Key | 
			
		
	
		
			
				
					|  |  |  |  |      * | 
			
		
	
		
			
				
					|  |  |  |  |      * @return bool Variable status | 
			
		
	
		
			
				
					|  |  |  |  |      */ | 
			
		
	
		
			
				
					|  |  |  |  |     public function has($key) { | 
			
		
	
		
			
				
					|  |  |  |  |     public function has(string $key): bool | 
			
		
	
		
			
				
					|  |  |  |  |     { | 
			
		
	
		
			
				
					|  |  |  |  |         return isset($this->vars[$key]); | 
			
		
	
		
			
				
					|  |  |  |  |     } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     /** | 
			
		
	
		
			
				
					|  |  |  |  |      * Unsets a variable. If no key is passed in, clear all variables. | 
			
		
	
		
			
				
					|  |  |  |  |      * | 
			
		
	
		
			
				
					|  |  |  |  |      * @param string $key Key | 
			
		
	
		
			
				
					|  |  |  |  |      * @param string|null $key Key | 
			
		
	
		
			
				
					|  |  |  |  |      */ | 
			
		
	
		
			
				
					|  |  |  |  |     public function clear($key = null) { | 
			
		
	
		
			
				
					|  |  |  |  |         if (is_null($key)) { | 
			
		
	
		
			
				
					|  |  |  |  |             $this->vars = array(); | 
			
		
	
		
			
				
					|  |  |  |  |         } | 
			
		
	
		
			
				
					|  |  |  |  |         else { | 
			
		
	
		
			
				
					|  |  |  |  |     public function clear(?string $key = null): void | 
			
		
	
		
			
				
					|  |  |  |  |     { | 
			
		
	
		
			
				
					|  |  |  |  |         if (null === $key) { | 
			
		
	
		
			
				
					|  |  |  |  |             $this->vars = []; | 
			
		
	
		
			
				
					|  |  |  |  |         } else { | 
			
		
	
		
			
				
					|  |  |  |  |             unset($this->vars[$key]); | 
			
		
	
		
			
				
					|  |  |  |  |         } | 
			
		
	
		
			
				
					|  |  |  |  |     } | 
			
		
	
	
		
			
				
					|  |  |  | @ -298,17 +320,20 @@ class Engine { | 
			
		
	
		
			
				
					|  |  |  |  |      * | 
			
		
	
		
			
				
					|  |  |  |  |      * @param string $dir Directory path | 
			
		
	
		
			
				
					|  |  |  |  |      */ | 
			
		
	
		
			
				
					|  |  |  |  |     public function path($dir) { | 
			
		
	
		
			
				
					|  |  |  |  |     public function path(string $dir): void | 
			
		
	
		
			
				
					|  |  |  |  |     { | 
			
		
	
		
			
				
					|  |  |  |  |         $this->loader->addDirectory($dir); | 
			
		
	
		
			
				
					|  |  |  |  |     } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     /*** Extensible Methods ***/ | 
			
		
	
		
			
				
					|  |  |  |  |     // Extensible Methods | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     /** | 
			
		
	
		
			
				
					|  |  |  |  |      * Starts the framework. | 
			
		
	
		
			
				
					|  |  |  |  |      * @throws \Exception | 
			
		
	
		
			
				
					|  |  |  |  |      * | 
			
		
	
		
			
				
					|  |  |  |  |      * @throws Exception | 
			
		
	
		
			
				
					|  |  |  |  |      */ | 
			
		
	
		
			
				
					|  |  |  |  |     public function _start() { | 
			
		
	
		
			
				
					|  |  |  |  |     public function _start(): void | 
			
		
	
		
			
				
					|  |  |  |  |     { | 
			
		
	
		
			
				
					|  |  |  |  |         $dispatched = false; | 
			
		
	
		
			
				
					|  |  |  |  |         $self = $this; | 
			
		
	
		
			
				
					|  |  |  |  |         $request = $this->request(); | 
			
		
	
	
		
			
				
					|  |  |  | @ -345,7 +370,9 @@ class Engine { | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |             $dispatched = true; | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |             if (!$continue) break; | 
			
		
	
		
			
				
					|  |  |  |  |             if (!$continue) { | 
			
		
	
		
			
				
					|  |  |  |  |                 break; | 
			
		
	
		
			
				
					|  |  |  |  |             } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |             $router->next(); | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
	
		
			
				
					|  |  |  | @ -360,14 +387,16 @@ class Engine { | 
			
		
	
		
			
				
					|  |  |  |  |     /** | 
			
		
	
		
			
				
					|  |  |  |  |      * Stops the framework and outputs the current response. | 
			
		
	
		
			
				
					|  |  |  |  |      * | 
			
		
	
		
			
				
					|  |  |  |  |      * @param int $code HTTP status code | 
			
		
	
		
			
				
					|  |  |  |  |      * @throws \Exception | 
			
		
	
		
			
				
					|  |  |  |  |      * @param int|null $code HTTP status code | 
			
		
	
		
			
				
					|  |  |  |  |      * | 
			
		
	
		
			
				
					|  |  |  |  |      * @throws Exception | 
			
		
	
		
			
				
					|  |  |  |  |      */ | 
			
		
	
		
			
				
					|  |  |  |  |     public function _stop($code = null) { | 
			
		
	
		
			
				
					|  |  |  |  |     public function _stop(?int $code = null): void | 
			
		
	
		
			
				
					|  |  |  |  |     { | 
			
		
	
		
			
				
					|  |  |  |  |         $response = $this->response(); | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |         if (!$response->sent()) { | 
			
		
	
		
			
				
					|  |  |  |  |             if ($code !== null) { | 
			
		
	
		
			
				
					|  |  |  |  |             if (null !== $code) { | 
			
		
	
		
			
				
					|  |  |  |  |                 $response->status($code); | 
			
		
	
		
			
				
					|  |  |  |  |             } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
	
		
			
				
					|  |  |  | @ -382,9 +411,10 @@ class Engine { | 
			
		
	
		
			
				
					|  |  |  |  |      * | 
			
		
	
		
			
				
					|  |  |  |  |      * @param string   $pattern    URL pattern to match | 
			
		
	
		
			
				
					|  |  |  |  |      * @param callback $callback   Callback function | 
			
		
	
		
			
				
					|  |  |  |  |      * @param boolean $pass_route Pass the matching route object to the callback | 
			
		
	
		
			
				
					|  |  |  |  |      * @param bool     $pass_route Pass the matching route object to the callback | 
			
		
	
		
			
				
					|  |  |  |  |      */ | 
			
		
	
		
			
				
					|  |  |  |  |     public function _route($pattern, $callback, $pass_route = false) { | 
			
		
	
		
			
				
					|  |  |  |  |     public function _route(string $pattern, callable $callback, bool $pass_route = false): void | 
			
		
	
		
			
				
					|  |  |  |  |     { | 
			
		
	
		
			
				
					|  |  |  |  |         $this->router()->map($pattern, $callback, $pass_route); | 
			
		
	
		
			
				
					|  |  |  |  |     } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
	
		
			
				
					|  |  |  | @ -394,7 +424,8 @@ class Engine { | 
			
		
	
		
			
				
					|  |  |  |  |      * @param int    $code    HTTP status code | 
			
		
	
		
			
				
					|  |  |  |  |      * @param string $message Response message | 
			
		
	
		
			
				
					|  |  |  |  |      */ | 
			
		
	
		
			
				
					|  |  |  |  |     public function _halt($code = 200, $message = '') { | 
			
		
	
		
			
				
					|  |  |  |  |     public function _halt(int $code = 200, string $message = ''): void | 
			
		
	
		
			
				
					|  |  |  |  |     { | 
			
		
	
		
			
				
					|  |  |  |  |         $this->response() | 
			
		
	
		
			
				
					|  |  |  |  |             ->clear() | 
			
		
	
		
			
				
					|  |  |  |  |             ->status($code) | 
			
		
	
	
		
			
				
					|  |  |  | @ -406,9 +437,10 @@ class Engine { | 
			
		
	
		
			
				
					|  |  |  |  |     /** | 
			
		
	
		
			
				
					|  |  |  |  |      * Sends an HTTP 500 response for any errors. | 
			
		
	
		
			
				
					|  |  |  |  |      * | 
			
		
	
		
			
				
					|  |  |  |  |      * @param \Exception|\Throwable $e Thrown exception | 
			
		
	
		
			
				
					|  |  |  |  |      * @param Exception|Throwable $e Thrown exception | 
			
		
	
		
			
				
					|  |  |  |  |      */ | 
			
		
	
		
			
				
					|  |  |  |  |     public function _error($e) { | 
			
		
	
		
			
				
					|  |  |  |  |     public function _error($e): void | 
			
		
	
		
			
				
					|  |  |  |  |     { | 
			
		
	
		
			
				
					|  |  |  |  |         $msg = sprintf('<h1>500 Internal Server Error</h1>' . | 
			
		
	
		
			
				
					|  |  |  |  |             '<h3>%s (%s)</h3>' . | 
			
		
	
		
			
				
					|  |  |  |  |             '<pre>%s</pre>', | 
			
		
	
	
		
			
				
					|  |  |  | @ -423,10 +455,9 @@ class Engine { | 
			
		
	
		
			
				
					|  |  |  |  |                 ->status(500) | 
			
		
	
		
			
				
					|  |  |  |  |                 ->write($msg) | 
			
		
	
		
			
				
					|  |  |  |  |                 ->send(); | 
			
		
	
		
			
				
					|  |  |  |  |         } | 
			
		
	
		
			
				
					|  |  |  |  |         catch (\Throwable $t) { // PHP 7.0+ | 
			
		
	
		
			
				
					|  |  |  |  |         } catch (Throwable $t) { // PHP 7.0+ | 
			
		
	
		
			
				
					|  |  |  |  |             exit($msg); | 
			
		
	
		
			
				
					|  |  |  |  |         } catch(\Exception $e) { // PHP < 7 | 
			
		
	
		
			
				
					|  |  |  |  |         } catch (Exception $e) { // PHP < 7 | 
			
		
	
		
			
				
					|  |  |  |  |             exit($msg); | 
			
		
	
		
			
				
					|  |  |  |  |         } | 
			
		
	
		
			
				
					|  |  |  |  |     } | 
			
		
	
	
		
			
				
					|  |  |  | @ -434,7 +465,8 @@ class Engine { | 
			
		
	
		
			
				
					|  |  |  |  |     /** | 
			
		
	
		
			
				
					|  |  |  |  |      * Sends an HTTP 404 response when a URL is not found. | 
			
		
	
		
			
				
					|  |  |  |  |      */ | 
			
		
	
		
			
				
					|  |  |  |  |     public function _notFound() { | 
			
		
	
		
			
				
					|  |  |  |  |     public function _notFound(): void | 
			
		
	
		
			
				
					|  |  |  |  |     { | 
			
		
	
		
			
				
					|  |  |  |  |         $this->response() | 
			
		
	
		
			
				
					|  |  |  |  |             ->clear() | 
			
		
	
		
			
				
					|  |  |  |  |             ->status(404) | 
			
		
	
	
		
			
				
					|  |  |  | @ -452,15 +484,16 @@ class Engine { | 
			
		
	
		
			
				
					|  |  |  |  |      * @param string $url  URL | 
			
		
	
		
			
				
					|  |  |  |  |      * @param int    $code HTTP status code | 
			
		
	
		
			
				
					|  |  |  |  |      */ | 
			
		
	
		
			
				
					|  |  |  |  |     public function _redirect($url, $code = 303) { | 
			
		
	
		
			
				
					|  |  |  |  |     public function _redirect(string $url, int $code = 303): void | 
			
		
	
		
			
				
					|  |  |  |  |     { | 
			
		
	
		
			
				
					|  |  |  |  |         $base = $this->get('flight.base_url'); | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |         if ($base === null) { | 
			
		
	
		
			
				
					|  |  |  |  |         if (null === $base) { | 
			
		
	
		
			
				
					|  |  |  |  |             $base = $this->request()->base; | 
			
		
	
		
			
				
					|  |  |  |  |         } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |         // Append base url to redirect url | 
			
		
	
		
			
				
					|  |  |  |  |         if ($base != '/' && strpos($url, '://') === false) { | 
			
		
	
		
			
				
					|  |  |  |  |         if ('/' != $base && false === strpos($url, '://')) { | 
			
		
	
		
			
				
					|  |  |  |  |             $url = $base . preg_replace('#/+#', '/', '/' . $url); | 
			
		
	
		
			
				
					|  |  |  |  |         } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
	
		
			
				
					|  |  |  | @ -475,15 +508,16 @@ class Engine { | 
			
		
	
		
			
				
					|  |  |  |  |      * Renders a template. | 
			
		
	
		
			
				
					|  |  |  |  |      * | 
			
		
	
		
			
				
					|  |  |  |  |      * @param string      $file Template file | 
			
		
	
		
			
				
					|  |  |  |  |      * @param array $data Template data | 
			
		
	
		
			
				
					|  |  |  |  |      * @param string $key View variable name | 
			
		
	
		
			
				
					|  |  |  |  |      * @throws \Exception | 
			
		
	
		
			
				
					|  |  |  |  |      * @param array|null  $data Template data | 
			
		
	
		
			
				
					|  |  |  |  |      * @param string|null $key  View variable name | 
			
		
	
		
			
				
					|  |  |  |  |      * | 
			
		
	
		
			
				
					|  |  |  |  |      * @throws Exception | 
			
		
	
		
			
				
					|  |  |  |  |      */ | 
			
		
	
		
			
				
					|  |  |  |  |     public function _render($file, $data = null, $key = null) { | 
			
		
	
		
			
				
					|  |  |  |  |         if ($key !== null) { | 
			
		
	
		
			
				
					|  |  |  |  |     public function _render(string $file, ?array $data = null, ?string $key = null): void | 
			
		
	
		
			
				
					|  |  |  |  |     { | 
			
		
	
		
			
				
					|  |  |  |  |         if (null !== $key) { | 
			
		
	
		
			
				
					|  |  |  |  |             $this->view()->set($key, $this->view()->fetch($file, $data)); | 
			
		
	
		
			
				
					|  |  |  |  |         } | 
			
		
	
		
			
				
					|  |  |  |  |         else { | 
			
		
	
		
			
				
					|  |  |  |  |         } else { | 
			
		
	
		
			
				
					|  |  |  |  |             $this->view()->render($file, $data); | 
			
		
	
		
			
				
					|  |  |  |  |         } | 
			
		
	
		
			
				
					|  |  |  |  |     } | 
			
		
	
	
		
			
				
					|  |  |  | @ -496,15 +530,16 @@ class Engine { | 
			
		
	
		
			
				
					|  |  |  |  |      * @param bool   $encode  Whether to perform JSON encoding | 
			
		
	
		
			
				
					|  |  |  |  |      * @param string $charset Charset | 
			
		
	
		
			
				
					|  |  |  |  |      * @param int    $option  Bitmask Json constant such as JSON_HEX_QUOT | 
			
		
	
		
			
				
					|  |  |  |  |      * @throws \Exception | 
			
		
	
		
			
				
					|  |  |  |  |      * | 
			
		
	
		
			
				
					|  |  |  |  |      * @throws Exception | 
			
		
	
		
			
				
					|  |  |  |  |      */ | 
			
		
	
		
			
				
					|  |  |  |  |     public function _json( | 
			
		
	
		
			
				
					|  |  |  |  |         $data, | 
			
		
	
		
			
				
					|  |  |  |  |         $code = 200, | 
			
		
	
		
			
				
					|  |  |  |  |         $encode = true, | 
			
		
	
		
			
				
					|  |  |  |  |         $charset = 'utf-8', | 
			
		
	
		
			
				
					|  |  |  |  |         $option = 0 | 
			
		
	
		
			
				
					|  |  |  |  |     ) { | 
			
		
	
		
			
				
					|  |  |  |  |         int $code = 200, | 
			
		
	
		
			
				
					|  |  |  |  |         bool $encode = true, | 
			
		
	
		
			
				
					|  |  |  |  |         string $charset = 'utf-8', | 
			
		
	
		
			
				
					|  |  |  |  |         int $option = 0 | 
			
		
	
		
			
				
					|  |  |  |  |     ): void { | 
			
		
	
		
			
				
					|  |  |  |  |         $json = ($encode) ? json_encode($data, $option) : $data; | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |         $this->response() | 
			
		
	
	
		
			
				
					|  |  |  | @ -523,16 +558,17 @@ class Engine { | 
			
		
	
		
			
				
					|  |  |  |  |      * @param bool   $encode  Whether to perform JSON encoding | 
			
		
	
		
			
				
					|  |  |  |  |      * @param string $charset Charset | 
			
		
	
		
			
				
					|  |  |  |  |      * @param int    $option  Bitmask Json constant such as JSON_HEX_QUOT | 
			
		
	
		
			
				
					|  |  |  |  |      * @throws \Exception | 
			
		
	
		
			
				
					|  |  |  |  |      * | 
			
		
	
		
			
				
					|  |  |  |  |      * @throws Exception | 
			
		
	
		
			
				
					|  |  |  |  |      */ | 
			
		
	
		
			
				
					|  |  |  |  |     public function _jsonp( | 
			
		
	
		
			
				
					|  |  |  |  |         $data, | 
			
		
	
		
			
				
					|  |  |  |  |         $param = 'jsonp', | 
			
		
	
		
			
				
					|  |  |  |  |         $code = 200, | 
			
		
	
		
			
				
					|  |  |  |  |         $encode = true, | 
			
		
	
		
			
				
					|  |  |  |  |         $charset = 'utf-8', | 
			
		
	
		
			
				
					|  |  |  |  |         $option = 0 | 
			
		
	
		
			
				
					|  |  |  |  |     ) { | 
			
		
	
		
			
				
					|  |  |  |  |         string $param = 'jsonp', | 
			
		
	
		
			
				
					|  |  |  |  |         int $code = 200, | 
			
		
	
		
			
				
					|  |  |  |  |         bool $encode = true, | 
			
		
	
		
			
				
					|  |  |  |  |         string $charset = 'utf-8', | 
			
		
	
		
			
				
					|  |  |  |  |         int $option = 0 | 
			
		
	
		
			
				
					|  |  |  |  |     ): void { | 
			
		
	
		
			
				
					|  |  |  |  |         $json = ($encode) ? json_encode($data, $option) : $data; | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |         $callback = $this->request()->query[$param]; | 
			
		
	
	
		
			
				
					|  |  |  | @ -550,8 +586,9 @@ class Engine { | 
			
		
	
		
			
				
					|  |  |  |  |      * @param string $id   ETag identifier | 
			
		
	
		
			
				
					|  |  |  |  |      * @param string $type ETag type | 
			
		
	
		
			
				
					|  |  |  |  |      */ | 
			
		
	
		
			
				
					|  |  |  |  |     public function _etag($id, $type = 'strong') { | 
			
		
	
		
			
				
					|  |  |  |  |         $id = (($type === 'weak') ? 'W/' : '').$id; | 
			
		
	
		
			
				
					|  |  |  |  |     public function _etag(string $id, string $type = 'strong'): void | 
			
		
	
		
			
				
					|  |  |  |  |     { | 
			
		
	
		
			
				
					|  |  |  |  |         $id = (('weak' === $type) ? 'W/' : '') . $id; | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |         $this->response()->header('ETag', $id); | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
	
		
			
				
					|  |  |  | @ -566,7 +603,8 @@ class Engine { | 
			
		
	
		
			
				
					|  |  |  |  |      * | 
			
		
	
		
			
				
					|  |  |  |  |      * @param int $time Unix timestamp | 
			
		
	
		
			
				
					|  |  |  |  |      */ | 
			
		
	
		
			
				
					|  |  |  |  |     public function _lastModified($time) { | 
			
		
	
		
			
				
					|  |  |  |  |     public function _lastModified(int $time): void | 
			
		
	
		
			
				
					|  |  |  |  |     { | 
			
		
	
		
			
				
					|  |  |  |  |         $this->response()->header('Last-Modified', gmdate('D, d M Y H:i:s \G\M\T', $time)); | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |         if (isset($_SERVER['HTTP_IF_MODIFIED_SINCE']) && | 
			
		
	
	
		
			
				
					|  |  |  | 
 |