From e2f1dc99bbf39d48bc0c793673366cc0e6751e39 Mon Sep 17 00:00:00 2001 From: Mike Cao Date: Wed, 7 Dec 2011 05:03:51 +0000 Subject: [PATCH] Major refactoring, implemented namespaces --- flight/Flight.php | 316 ++++++++------------------------- flight/core/Dispatcher.php | 171 ++++++++++++++++++ flight/core/Loader.php | 173 ++++++++++++++++++ flight/{ => net}/Request.php | 50 +++++- flight/{ => net}/Response.php | 10 +- flight/{ => net}/Router.php | 64 ++++--- flight/{ => template}/View.php | 70 ++++---- 7 files changed, 543 insertions(+), 311 deletions(-) create mode 100644 flight/core/Dispatcher.php create mode 100644 flight/core/Loader.php rename flight/{ => net}/Request.php (55%) rename flight/{ => net}/Response.php (95%) rename flight/{ => net}/Router.php (77%) rename flight/{ => template}/View.php (71%) diff --git a/flight/Flight.php b/flight/Flight.php index f831016..3cab8b8 100644 --- a/flight/Flight.php +++ b/flight/Flight.php @@ -5,6 +5,15 @@ * @copyright Copyright (c) 2011, Mike Cao * @license http://www.opensource.org/licenses/mit-license.php */ + +include __DIR__.'/core/Loader.php'; +include __DIR__.'/core/Dispatcher.php'; + +/** + * The Flight class represents the framework itself. It is responsible + * loading an HTTP request, running the assigned services, and generating + * an HTTP response. + */ class Flight { /** * Stored variables. @@ -14,39 +23,18 @@ class Flight { protected static $vars = array(); /** - * Registered classes. - * - * @var array - */ - protected static $classes = array(); - - /** - * Mapped methods. - * - * @var array - */ - protected static $methods = array(); - - /** - * Method filters. - * - * @var array - */ - protected static $filters = array(); - - /** - * Class instances. + * Class loader. * - * @var array + * @var object */ - protected static $instances = array(); + protected static $loader; /** - * Autoload directories. + * Event dispatcher. * - * @var array + * @var object */ - protected static $dirs = array(); + protected static $dispatcher; // Don't allow object instantiation private function __construct() {} @@ -60,28 +48,15 @@ class Flight { * @param array $args Method parameters */ public static function __callStatic($name, $params) { - // Check if call is mapped to a method - if (isset(self::$methods[$name]) || method_exists(__CLASS__, '_'.$name)) { - $method = self::$methods[$name] ?: array(__CLASS__, '_'.$name); - - // Run pre-filters - if (!empty(self::$filters['before'][$name])) { - self::filter(self::$filters['before'][$name], $params); - } + $callback = self::$dispatcher->get($name); - // Run requested method - $output = self::execute($method, $params); - - // Run post-filters - if (!empty(self::$filters['after'][$name])) { - self::filter(self::$filters['after'][$name], $output); - } - - return $output; + if (is_callable($callback)) { + return self::$dispatcher->run($name, $params); } - // Otherwise try to autoload class - return self::load($name, (!empty($params)) ? (bool)$params[0] : true); + $shared = (!empty($params)) ? (bool)$params[0] : true; + + return self::$loader->load($name, $shared); } /** @@ -95,7 +70,7 @@ class Flight { throw new Exception('Cannot override an existing framework method.'); } - self::$methods[$name] = $callback; + self::$dispatcher->set($name, $callback); } /** @@ -111,40 +86,7 @@ class Flight { throw new Exception('Cannot override an existing framework method.'); } - unset(self::$instances[$class]); - - self::$classes[$name] = array($class, $params, $callback); - } - - /** - * Loads a registered class. - * - * @param string $name Method name - * @param bool $shared Shared instance - */ - public static function load($name, $shared = true) { - if (isset(self::$classes[$name])) { - list($class, $params, $callback) = self::$classes[$name]; - - $do_callback = ($callback && (!$shared || !isset(self::$instances[$class]))); - - $obj = ($shared) ? - self::getInstance($class, $params) : - self::getClass($class, $params); - - if ($do_callback) { - $ref = array(&$obj); - self::execute($callback, $ref); - } - - return $obj; - } - - $class = ucfirst($name); - - return ($shared) ? - self::getInstance($class) : - self::getClass($class); + self::$loader->register($name, $class, $params, $callback); } /** @@ -154,7 +96,7 @@ class Flight { * @param callback $callback Callback function */ public static function before($name, $callback) { - self::$filters['before'][$name][] = $callback; + self::$dispatcher->hook($name, 'before', $callback); } /** @@ -164,130 +106,18 @@ class Flight { * @param callback $callback Callback function */ public static function after($name, $callback) { - self::$filters['after'][$name][] = $callback; - } - - /** - * Executes a callback function. - * - * @param callback $callback Callback function - * @param array $params Function parameters - * @return mixed Function results - */ - public static function execute($callback, array &$params = array()) { - if (is_callable($callback)) { - return is_array($callback) ? - self::invokeMethod($callback, $params) : - self::callFunction($callback, $params); - } - } - - /** - * Executes a chain of method filters. - * - * @param array $filters Chain of filters - * @param reference $data Method parameters or method output - */ - public static function filter($filters, &$data) { - $params = array(&$data); - foreach ($filters as $callback) { - $continue = self::execute($callback, $params); - if ($continue === false) break; - } - } - - /** - * Calls a function. - * - * @param string $func Name of function to call - * @param array $params Function parameters - */ - public static function callFunction($func, array &$params = array()) { - switch (count($params)) { - case 0: - return $func(); - case 1: - return $func($params[0]); - case 2: - return $func($params[0], $params[1]); - case 3: - return $func($params[0], $params[1], $params[2]); - case 4: - return $func($params[0], $params[1], $params[2], $params[3]); - case 5: - return $func($params[0], $params[1], $params[2], $params[3], $params[4]); - default: - return call_user_func_array($func, $params); - } + self::$dispatcher->hook($name, 'after', $callback); } /** - * Invokes a method. + * Adds a path for class autoloading. * - * @param mixed $func Class method - * @param array $params Class method parameters + * @param string $dir Directory path */ - public static function invokeMethod($func, array &$params = array()) { - list($class, $method) = $func; - - switch (count($params)) { - case 0: - return $class::$method(); - case 1: - return $class::$method($params[0]); - case 2: - return $class::$method($params[0], $params[1]); - case 3: - return $class::$method($params[0], $params[1], $params[2]); - case 4: - return $class::$method($params[0], $params[1], $params[2], $params[3]); - case 5: - return $class::$method($params[0], $params[1], $params[2], $params[3], $params[4]); - default: - return call_user_func_array($func, $params); - } + public static function path($dir) { + self::$loader->addDirectory($dir); } - /** - * Gets a single instance of a class. - * - * @param string $class Class name - * @param array $params Class initialization parameters - */ - public static function getInstance($class, array $params = array()) { - if (!isset(self::$instances[$class])) { - self::$instances[$class] = self::getClass($class, $params); - } - - return self::$instances[$class]; - } - - /** - * Gets a class object. - * - * @param string $class Class name - * @param array $params Class initialization parameters - */ - public static function getClass($class, array $params = array()) { - switch (count($params)) { - case 0: - return new $class(); - case 1: - return new $class($params[0]); - case 2: - return new $class($params[0], $params[1]); - case 3: - return new $class($params[0], $params[1], $params[2]); - case 4: - return new $class($params[0], $params[1], $params[2], $params[3]); - case 5: - return new $class($params[0], $params[1], $params[2], $params[3], $params[4]); - default: - $refClass = new ReflectionClass($class); - return $refClass->newInstanceArgs($params); - } - } - /** * Gets a variable. * @@ -317,12 +147,12 @@ class Flight { } /** - * Checks if a variable exists. + * Checks if a variable has been set. * * @param string $key Key * @return bool Variable status */ - public static function exists($key) { + public static function has($key) { return isset(self::$vars[$key]); } @@ -347,9 +177,6 @@ class Flight { static $initialized = false; if (!$initialized) { - // Register autoloader - spl_autoload_register(array(__CLASS__, 'autoload')); - // Handle errors internally set_error_handler(array(__CLASS__, 'handleError')); @@ -369,6 +196,29 @@ class Flight { $_COOKIE = array_map($func, $_COOKIE); } + // Load core components + self::$loader = new \flight\core\Loader(); + self::$dispatcher = new \flight\core\Dispatcher(); + + // Register default components + self::$loader->addDirectory(dirname(__DIR__)); + self::$loader->register('request', '\flight\net\Request'); + self::$loader->register('response', '\flight\net\Response'); + self::$loader->register('router', '\flight\net\Router'); + self::$loader->register('view', '\flight\template\View', array(), function($view){ + $view->path = Flight::get('flight.views.path') ?: './views'; + }); + + // Register framework methods + $methods = array( + 'start','stop','route','halt','error','notFound', + 'render','redirect','etag','lastModified','json' + ); + + foreach ($methods as $name) { + self::$dispatcher->set($name, array(__CLASS__, '_'.$name)); + } + // Enable output buffering ob_start(); @@ -376,27 +226,6 @@ class Flight { } } - /** - * Autoloads classes. - * - * @param string $class Class name - */ - public static function autoload($class) { - $file = str_replace('\\', '/', str_replace('_', '/', $class)).'.php'; - $base = (strpos($file, '/') === false) ? __DIR__ : (self::get('flight.lib.path') ?: '.'); - - if (file_exists($base.'/'.$file)) { - require $base.'/'.$file; - } - else { - $loaders = spl_autoload_functions(); - $last = array_pop($loaders); - if (is_array($last) && $last[0] == __CLASS__ && $last[1] == __FUNCTION__) { - throw new Exception('Unable to load file: '.$base.'/'.$file); - } - } - } - /** * Custom error handler. */ @@ -414,7 +243,6 @@ class Flight { static::error($e); } catch (Exception $ex) { - error_log($ex->getMessage()); exit( '

500 Internal Server Error

'. '

'.$ex->getMessage().'

'. @@ -424,26 +252,17 @@ class Flight { } /** - * Routes a URL to a callback function. - * - * @param string $pattern URL pattern to match - * @param callback $callback Callback function - */ - public static function _route($pattern, $callback) { - self::router()->map($pattern, $callback); - } - - /** - * Start the framework. + * Starts the framework. */ public static function _start() { // Route the request - $result = self::router()->route(self::request()); + $callback = self::router()->route(self::request()); - if ($result !== false) { - list($callback, $params) = $result; - - self::execute($callback, array_values($params)); + if ($callback !== false) { + self::$dispatcher->execute( + $callback, + array_values(self::request()->params) + ); } else { self::notFound(); @@ -467,6 +286,16 @@ class Flight { ->send(); } + /** + * Routes a URL to a callback function. + * + * @param string $pattern URL pattern to match + * @param callback $callback Callback function + */ + public static function _route($pattern, $callback) { + self::router()->map($pattern, $callback); + } + /** * Stops processing and returns a given response. * @@ -487,7 +316,6 @@ class Flight { * @param object $ex Exception */ public static function _error(Exception $e) { - error_log($e->getMessage()); self::response(false) ->status(500) ->write( @@ -584,6 +412,6 @@ class Flight { } } -// Initialize framework on include +// Initialize the framework on include Flight::init(); ?> diff --git a/flight/core/Dispatcher.php b/flight/core/Dispatcher.php new file mode 100644 index 0000000..4829562 --- /dev/null +++ b/flight/core/Dispatcher.php @@ -0,0 +1,171 @@ + + * @license http://www.opensource.org/licenses/mit-license.php + */ + +namespace flight\core; + +/** + * The Dispatcher class is responsible for dispatching events. Events + * are simply aliases for class methods or functions. The Dispatcher + * allows you to hook other function to an event that can modify the + * input parameters and/or the output. + */ +class Dispatcher { + /** + * Mapped events. + * + * @var array + */ + protected $events = array(); + + /** + * Method filters. + * + * @var array + */ + protected $filters = array(); + + public function __construct() {} + + /** + * Dispatches an event. + * + * @param string $name Event name + * @param array $params Callback parameters + */ + public function run($name, $params) { + $output = ''; + + // Run pre-filters + if (!empty($this->filters[$name]['before'])) { + $this->filter($this->filters[$name]['before'], $params, $output); + } + + // Run requested method + $output = $this->execute($this->get($name), $params); + + // Run post-filters + if (!empty($this->filters[$name]['after'])) { + $this->filter($this->filters[$name]['after'], $params, $output); + } + + return $output; + } + + /** + * Assigns a callback to an event. + * + * @param string $name Event name + * @param callback $callback Callback function + */ + public function set($name, $callback) { + $this->events[$name] = $callback; + } + + /** + * Gets an assigned callback. + * + * @param string $name Event name + * @param callback $callback Callback function + */ + public function get($name) { + return $this->events[$name]; + } + + /** + * Hooks a callback to an event. + * + * @param string $event Event name + * @param string $type Filter type + * @param callback $callback Callback function + */ + public function hook($name, $type, $callback) { + $this->filters[$name][$type][] = $callback; + } + + /** + * Executes a chain of method filters. + * + * @param array $filters Chain of filters + * @param reference $data Method parameters or method output + */ + public function filter($filters, &$params, &$output) { + $args = array(&$params, &$output); + foreach ($filters as $callback) { + $continue = $this->execute($callback, $args); + if ($continue === false) break; + } + } + + /** + * Executes a callback function. + * + * @param callback $callback Callback function + * @param array $params Function parameters + * @return mixed Function results + */ + public static function execute($callback, array &$params = array()) { + if (is_callable($callback)) { + return is_array($callback) ? + self::invokeMethod($callback, $params) : + self::callFunction($callback, $params); + } + } + + /** + * Calls a function. + * + * @param string $func Name of function to call + * @param array $params Function parameters + */ + public static function callFunction($func, array &$params = array()) { + switch (count($params)) { + case 0: + return $func(); + case 1: + return $func($params[0]); + case 2: + return $func($params[0], $params[1]); + case 3: + return $func($params[0], $params[1], $params[2]); + case 4: + return $func($params[0], $params[1], $params[2], $params[3]); + case 5: + return $func($params[0], $params[1], $params[2], $params[3], $params[4]); + default: + return call_user_func_array($func, $params); + } + } + + /** + * Invokes a method. + * + * @param mixed $func Class method + * @param array $params Class method parameters + */ + public static function invokeMethod($func, array &$params = array()) { + list($class, $method) = $func; + + switch (count($params)) { + case 0: + return $class::$method(); + case 1: + return $class::$method($params[0]); + case 2: + return $class::$method($params[0], $params[1]); + case 3: + return $class::$method($params[0], $params[1], $params[2]); + case 4: + return $class::$method($params[0], $params[1], $params[2], $params[3]); + case 5: + return $class::$method($params[0], $params[1], $params[2], $params[3], $params[4]); + default: + return call_user_func_array($func, $params); + } + } +} +?> diff --git a/flight/core/Loader.php b/flight/core/Loader.php new file mode 100644 index 0000000..1ba5841 --- /dev/null +++ b/flight/core/Loader.php @@ -0,0 +1,173 @@ + + * @license http://www.opensource.org/licenses/mit-license.php + */ + +namespace flight\core; + +/** + * The Loader class is resonsible for loading objects. It maintains + * a list of reusable class instances and can generate a new class + * instances with custom initialization parameters. It also performs + * class autoloading. + */ +class Loader { + /** + * Registered classes. + * + * @var array + */ + protected $classes = array(); + + /** + * Class instances. + * + * @var array + */ + protected $instances = array(); + + /** + * Autoload directories. + * + * @var array + */ + protected $dirs = array(); + + /** + * Constructor. Enables autoloading. + */ + public function __construct() { + spl_autoload_register(array(__CLASS__, 'autoload')); + } + + /** + * Registers a class. + * + * @param string $name Registry name + * @param string $class Class name + * @param array $params Class initialization parameters + * @param callback $callback Function to call after object instantiation + */ + public function register($name, $class, array $params = array(), $callback = null) { + unset($this->instances[$class]); + + $this->classes[$name] = array($class, $params, $callback); + } + + /** + * Unregisters a class. + * + * @param string $name Registry name + */ + public function unregister($name) { + unset($this->classes[$name]); + } + + /** + * Loads a registered class. + * + * @param string $name Method name + * @param bool $shared Shared instance + */ + public function load($name, $shared = true) { + if (isset($this->classes[$name])) { + list($class, $params, $callback) = $this->classes[$name]; + + $do_callback = ($callback && (!$shared || !isset($this->instances[$class]))); + + $obj = ($shared) ? + $this->getInstance($class, $params) : + $this->newInstance($class, $params); + + if ($do_callback) { + $ref = array(&$obj); + call_user_func_array($callback, $ref); + } + + return $obj; + } + + $class = ucfirst($name); + + return ($shared) ? + $this->getInstance($class) : + $this->newInstance($class); + } + + /** + * Gets a single instance of a class. + * + * @param string $class Class name + * @param array $params Class initialization parameters + */ + public function getInstance($class, array $params = array()) { + if (!isset($this->instances[$class])) { + $this->instances[$class] = $this->newInstance($class, $params); + } + + return $this->instances[$class]; + } + + /** + * Gets a new instance of a class. + * + * @param string $class Class name + * @param array $params Class initialization parameters + */ + public function newInstance($class, array $params = array()) { + switch (count($params)) { + case 0: + return new $class(); + case 1: + return new $class($params[0]); + case 2: + return new $class($params[0], $params[1]); + case 3: + return new $class($params[0], $params[1], $params[2]); + case 4: + return new $class($params[0], $params[1], $params[2], $params[3]); + case 5: + return new $class($params[0], $params[1], $params[2], $params[3], $params[4]); + default: + $refClass = new ReflectionClass($class); + return $refClass->newInstanceArgs($params); + } + } + + /** + * Adds a directory for autoloading classes. + * + * @param string $dir Directory path + */ + public function addDirectory($dir) { + $this->dirs[] = $dir; + } + + /** + * Autoloads classes. + * + * @param string $class Class name + */ + public function autoload($class) { + $class_file = str_replace('\\', '/', str_replace('_', '/', $class)).'.php'; + $dirs = array_merge($this->dirs, array(__DIR__, '.')); + + foreach ($dirs as $dir) { + $file = $dir.'/'.$class_file; + if (file_exists($file)) { + require $file; + return; + } + } + + // Allow other autoloaders to run before raising an error + $loader = array_pop(spl_autoload_functions()); + if (is_array($loader) && $loader[0] == __CLASS__ && $loader[1] == __FUNCTION__) { + throw new Exception('Unable to load file: '.$class_file); + } + } +} +?> diff --git a/flight/Request.php b/flight/net/Request.php similarity index 55% rename from flight/Request.php rename to flight/net/Request.php index ff0109f..3084ba5 100644 --- a/flight/Request.php +++ b/flight/net/Request.php @@ -5,6 +5,33 @@ * @copyright Copyright (c) 2011, Mike Cao * @license http://www.opensource.org/licenses/mit-license.php */ + +namespace flight\net; + +/** + * The Request class represents an HTTP request. Data from + * all the super globals $_GET, $_POST, $_COOKIE, and $_FILES + * are stored and accessible via the Request object. + * + * The default request properties are: + * url - The URL being requested + * base - The parent subdirectory of the URL + * method - The request method (GET, POST, PUT, DELETE) + * referrer - The referrer URL + * ip - IP address of the client + * ajax - Whether the request is an AJAX request + * scheme - The server protocol (http, https) + * user_agent - Browser information + * body - Raw data from the request body + * type - The content type + * length - The content length + * query - Query string parameters + * data - Post parameters + * cookies - Cookie parameters + * files - Uploaded files + * params - Matched URL parameters from the router + * matched - Matched URL patter from the router + */ class Request { /** * Constructor. @@ -26,14 +53,16 @@ class Request { 'body' => file_get_contents('php://input'), 'type' => $_SERVER['CONTENT_TYPE'], 'length' => $_SERVER['CONTENT_LENGTH'], - 'query' => array(), - 'data' => $_POST, - 'cookies' => $_COOKIE, - 'files' => $_FILES + 'query' => (object)$_GET, + 'data' => (object)$_POST, + 'cookies' => (object)$_COOKIE, + 'files' => (object)$_FILES, + 'params' => array(), + 'matched' => null ); } - self::init($config); + $this->init($config); } /** @@ -43,7 +72,7 @@ class Request { */ public function init($properties) { foreach ($properties as $name => $value) { - $this->{$name} = $value; + $this->$name = $value; } if ($this->base != '/' && strpos($this->url, $this->base) === 0) { @@ -54,14 +83,19 @@ class Request { $this->url = '/'; } else { - $this->query = self::parseQuery($this->url); + $query = self::parseQuery($this->url); + $this->query = (object)$query; + $_GET = $query; } } /** * Parse query parameters from a URL. + * + * @param string $url URL string + * @return array Query parameters */ - public function parseQuery($url) { + public static function parseQuery($url) { $params = array(); $args = parse_url($url); diff --git a/flight/Response.php b/flight/net/Response.php similarity index 95% rename from flight/Response.php rename to flight/net/Response.php index 30edd81..1da1ad5 100644 --- a/flight/Response.php +++ b/flight/net/Response.php @@ -5,6 +5,14 @@ * @copyright Copyright (c) 2011, Mike Cao * @license http://www.opensource.org/licenses/mit-license.php */ + +namespace flight\net; + +/** + * The Response class represents an HTTP response. The object + * contains the response headers, HTTP status code, and response + * body. + */ class Response { protected $headers = array(); protected $status = 200; @@ -68,7 +76,7 @@ class Response { } } else { - throw new Exception('Invalid status code.'); + throw new \Exception('Invalid status code.'); } return $this; diff --git a/flight/Router.php b/flight/net/Router.php similarity index 77% rename from flight/Router.php rename to flight/net/Router.php index a80d6b5..4f35dd6 100644 --- a/flight/Router.php +++ b/flight/net/Router.php @@ -5,6 +5,14 @@ * @copyright Copyright (c) 2011, Mike Cao * @license http://www.opensource.org/licenses/mit-license.php */ + +namespace flight\net; + +/** + * The Router class is responsible for routing an HTTP request to + * an assigned callback function. The Router tries to match the + * requested URL against a series of URL patterns. + */ class Router { /** * Mapped routes. @@ -13,6 +21,22 @@ class Router { */ protected $routes = array(); + /** + * Gets mapped routes. + * + * @return array Array of routes + */ + public function getRoutes() { + return $this->routes; + } + + /** + * Resets the router. + */ + public function clear() { + $this->routes = array(); + } + /** * Maps a URL pattern to a callback function. * @@ -36,10 +60,9 @@ class Router { * Tries to match a requst to a route. Also parses named parameters in the url. * * @param string $pattern URL pattern - * @param string $url Request URL - * @param array $params Named URL parameters + * @param object $request Request object */ - public function match($pattern, $url, array &$params = array()) { + public function match($pattern, $request) { $ids = array(); // Build the regex for matching @@ -60,10 +83,13 @@ class Router { )).'\/?(?:\?.*)?$/i'; // Attempt to match route and named parameters - if (preg_match($regex, $url, $matches)) { + if (preg_match($regex, $request->url, $matches)) { if (!empty($ids)) { - $params = array_intersect_key($matches, $ids); + $request->params = array_intersect_key($matches, $ids); } + + $request->matched = $pattern; + return true; } @@ -74,35 +100,21 @@ class Router { * Routes the current request. * * @param object $request Request object + * @return callable Matched callback function */ - public function route(&$request) { - $params = array(); + public function route(Request $request) { + $request->matched = null; + $request->params = array(); + $routes = ($this->routes[$request->method] ?: array()) + ($this->routes['*'] ?: array()); foreach ($routes as $pattern => $callback) { - if ($pattern === '*' || $request->url === $pattern || self::match($pattern, $request->url, $params)) { - $request->matched = $pattern; - return array($callback, $params); + if ($pattern === '*' || $request->url === $pattern || self::match($pattern, $request)) { + return $callback; } } return false; } - - /** - * Gets mapped routes. - * - * @return array Array of routes - */ - public function getRoutes() { - return $this->routes; - } - - /** - * Resets the router. - */ - public function clear() { - $this->routes = array(); - } } ?> diff --git a/flight/View.php b/flight/template/View.php similarity index 71% rename from flight/View.php rename to flight/template/View.php index 005a5c4..c940417 100644 --- a/flight/View.php +++ b/flight/template/View.php @@ -5,18 +5,36 @@ * @copyright Copyright (c) 2011, Mike Cao * @license http://www.opensource.org/licenses/mit-license.php */ + +namespace flight\template; + +/** + * The View class represents output to be displayed. It provides + * methods for managing view data and inserts the data into + * view templates upon rendering. + */ class View { + /** + * Locaton of view templates. + * + * @var string + */ public $path; - public $template; - public $data = array(); + + /** + * View variables. + * + * @var array + */ + protected $data = array(); /** * Constructor. * * @param string $path Path to templates directory */ - public function __construct($path = null) { - $this->path = $path ?: (Flight::get('flight.views.path') ?: './views'); + public function __construct($path = '.') { + $this->path = $path; } /** @@ -53,7 +71,7 @@ class View { * @param string $key Key */ public function has($key) { - return !empty($this->data[$key]); + return !isset($this->data[$key]); } /** @@ -77,7 +95,7 @@ class View { * @param array $data Template data */ public function render($file, $data = null) { - $this->template = (substr($file, -4) == '.php') ? $file : $file.'.php'; + $template = $this->getTemplate($file); if (is_array($data)) { $this->data = array_merge($this->data, $data); @@ -85,13 +103,11 @@ class View { extract($this->data); - $file = $this->path.'/'.$this->template; - - if (!file_exists($file)) { - throw new Exception("Template file not found: $file."); + if (!file_exists($template)) { + throw new \Exception("Template file not found: $template."); } - include $file; + include $template; } /** @@ -111,16 +127,6 @@ class View { return $output; } - /** - * Displays escaped output. - * - * @param string $str String to escape - * @return string Escaped string - */ - public function e($str) { - echo htmlentities($str); - } - /** * Checks if a template file exists. * @@ -128,27 +134,27 @@ class View { * @return bool Template file exists */ public function exists($file) { - return file_exists($this->path.'/'.((substr($file, -4) == '.php') ? $file : $file.'.php')); + return file_exists($this->getTemplate($file)); } /** - * Loads and executes view helper functions. + * Gets the full path to a template file. * - * @param string $name Function name - * @param array $params Function parameters + * @param string $file Template file + * @return string Template file location */ - public function __call($name, $params) { - return Flight::invokeMethod(array('Flight', $name), $params); + public function getTemplate($file) { + return $this->path.'/'.((substr($file, -4) == '.php') ? $file : $file.'.php'); } /** - * Loads view helper classes. + * Displays escaped output. * - * @param string $name Class name - * @return object Class instance + * @param string $str String to escape + * @return string Escaped string */ - public function __get($name) { - return Flight::load($name); + public function e($str) { + echo htmlentities($str); } } ?>