From 1e49001dfc264ca863c3dea4e05c6ef71027fc3a Mon Sep 17 00:00:00 2001 From: Taylor Otwell Date: Fri, 26 Aug 2011 21:42:04 -0500 Subject: [PATCH] continued ioc refactoring. --- application/config/database.php | 19 +++ application/config/error.php | 37 +----- application/filters.php | 7 +- application/routes.php | 4 +- laravel/application.php | 76 +++++++++++ laravel/asset.php | 14 +- laravel/bootstrap/constants.php | 33 +++++ laravel/bootstrap/core.php | 46 +++++++ laravel/cache/apc.php | 18 ++- laravel/cache/file.php | 19 ++- laravel/cache/manager.php | 51 ++++++-- laravel/cache/memcached.php | 17 ++- laravel/config.php | 38 +++--- laravel/config/container.php | 131 ++++++++++++------- laravel/{ioc.php => container.php} | 69 ++++------ laravel/controller.php | 18 ++- laravel/database/eloquent/model.php | 2 - laravel/database/manager.php | 51 ++++++-- laravel/database/query.php | 5 - laravel/download.php | 37 ------ laravel/error.php | 26 ---- laravel/exception/examiner.php | 25 ++-- laravel/file.php | 60 ++++----- laravel/form.php | 193 +++++++++++++++------------ laravel/html.php | 114 +++++++++------- laravel/input.php | 25 +--- laravel/laravel.php | 182 ++++++++++++-------------- laravel/loader.php | 33 +++-- laravel/package.php | 12 +- laravel/request.php | 130 +++++++++++-------- laravel/response.php | 113 ++++++++++++---- laravel/routing/handler.php | 194 ---------------------------- laravel/routing/route.php | 192 ++++++++++++++++++++++++++- laravel/routing/router.php | 22 +++- laravel/session/apc.php | 14 +- laravel/session/cookie.php | 19 +-- laravel/session/database.php | 14 +- laravel/session/driver.php | 86 ++++++++---- laravel/session/file.php | 19 ++- laravel/session/manager.php | 45 +------ laravel/session/memcached.php | 14 +- laravel/url.php | 49 ++++--- laravel/view.php | 159 +++++++++++++---------- public/index.php | 2 +- 44 files changed, 1388 insertions(+), 1046 deletions(-) create mode 100644 laravel/application.php create mode 100644 laravel/bootstrap/constants.php create mode 100644 laravel/bootstrap/core.php rename laravel/{ioc.php => container.php} (72%) delete mode 100644 laravel/download.php delete mode 100644 laravel/error.php delete mode 100644 laravel/routing/handler.php diff --git a/application/config/database.php b/application/config/database.php index d8109118..aee44d85 100644 --- a/application/config/database.php +++ b/application/config/database.php @@ -2,6 +2,25 @@ return array( + /* + |-------------------------------------------------------------------------- + | Database Manager Auto Load + |-------------------------------------------------------------------------- + | + | Determines if the database manager will be loaded one every request. + | + | By default, the database manager is loaded on every request and set on + | a property of the application instance. However, if you will not be using + | any of the Laravel database facilities, you may set this to "false". + | + | Loading the database manager does not create database connections. The + | connections are only established once you request a connection from the + | database manager instance. + | + */ + + 'autoload' => true, + /* |-------------------------------------------------------------------------- | Default Database Connection diff --git a/application/config/error.php b/application/config/error.php index 4a0896da..32d82e93 100644 --- a/application/config/error.php +++ b/application/config/error.php @@ -4,36 +4,7 @@ /* |-------------------------------------------------------------------------- - | Error Detail - |-------------------------------------------------------------------------- - | - | Detailed error messages contain information about the file in which - | an error occurs, a stack trace, and a snapshot of the source code - | in which the error occured. - | - | If your application is in production, consider turning off error details - | for enhanced security and user experience. - | - */ - - 'detail' => true, - - /* - |-------------------------------------------------------------------------- - | Error Logging - |-------------------------------------------------------------------------- - | - | Error Logging will use the "logger" function defined below to log error - | messages, which gives you complete freedom to determine how error - | messages are logged. Enjoy the flexibility. - | - */ - - 'log' => false, - - /* - |-------------------------------------------------------------------------- - | Error Logger + | Error Handler |-------------------------------------------------------------------------- | | Because of the various ways of managing error logging, you get complete @@ -50,11 +21,11 @@ | */ - 'logger' => function($severity, $message, $trace) + 'handler' => function($exception) { - $file = IoC::resolve('laravel.file'); + var_dump($exception); - $file->append(STORAGE_PATH.'log.txt', date('Y-m-d H:i:s').' '.$severity.' - '.$message.PHP_EOL); + exit(1); }, ); \ No newline at end of file diff --git a/application/filters.php b/application/filters.php index ef07e5da..ffaba762 100644 --- a/application/filters.php +++ b/application/filters.php @@ -1,5 +1,8 @@ function(Laravel\Request $request) + 'before' => function(Application $application) { // Do stuff before every request to your application. }, - 'after' => function(Laravel\Request $request, Laravel\Response $response) + 'after' => function(Application $application, Response $response) { // Do stuff after every request to your application. }, diff --git a/application/routes.php b/application/routes.php index 2f1372c8..05f95ef5 100644 --- a/application/routes.php +++ b/application/routes.php @@ -37,9 +37,9 @@ | */ - 'GET /' => function($request) + 'GET /' => function($application) { - return View::make('home.index'); + return $application->view->make('home.index'); }, ); \ No newline at end of file diff --git a/laravel/application.php b/laravel/application.php new file mode 100644 index 00000000..c3f3c2a2 --- /dev/null +++ b/laravel/application.php @@ -0,0 +1,76 @@ +container->registered('laravel.'.$key)) + { + return $this->container->resolve('laravel.'.$key); + } + elseif ($this->container->registered($key)) + { + return $this->container->resolve($key); + } + + throw new \Exception("Attempting to access undefined property [$key] on application instance."); + } + +} \ No newline at end of file diff --git a/laravel/asset.php b/laravel/asset.php index 9f4cec97..eaf5c0b1 100644 --- a/laravel/asset.php +++ b/laravel/asset.php @@ -33,7 +33,7 @@ public static function container($container = 'default') { if ( ! isset(static::$containers[$container])) { - static::$containers[$container] = new Asset_Container($container, new File); + static::$containers[$container] = new Asset_Container($container); } return static::$containers[$container]; @@ -78,13 +78,6 @@ class Asset_Container { */ public $assets = array(); - /** - * The file manager instance. - * - * @var File - */ - private $file; - /** * Create a new asset container instance. * @@ -92,10 +85,9 @@ class Asset_Container { * @param File $file * @return void */ - public function __construct($name, File $file) + public function __construct($name) { $this->name = $name; - $this->file = $file; } /** @@ -125,7 +117,7 @@ public function __construct($name, File $file) */ public function add($name, $source, $dependencies = array(), $attributes = array()) { - $type = ($this->file->extension($source) == 'css') ? 'style' : 'script'; + $type = (pathinfo($source, PATHINFO_EXTENSION) == 'css') ? 'style' : 'script'; return call_user_func(array($this, $type), $name, $source, $dependencies, $attributes); } diff --git a/laravel/bootstrap/constants.php b/laravel/bootstrap/constants.php new file mode 100644 index 00000000..fc572aa5 --- /dev/null +++ b/laravel/bootstrap/constants.php @@ -0,0 +1,33 @@ +config = new Config; + +$paths = array(BASE_PATH, APP_PATH.'models/', APP_PATH.'libraries/'); + +$application->loader = new Loader($application->config->get('aliases'), $paths); + +spl_autoload_register(array($application->loader, 'load')); + +unset($paths); + +// -------------------------------------------------------------- +// Bootstrap the IoC container. +// -------------------------------------------------------------- +require SYS_PATH.'container'.EXT; + +$application->container = new Container($application->config->get('container')); + +// -------------------------------------------------------------- +// Register the core application components in the container. +// -------------------------------------------------------------- +$application->container->instance('laravel.application', $application); + +$application->container->instance('laravel.config', $application->config); + +$application->container->instance('laravel.loader', $application->loader); + +// -------------------------------------------------------------- +// Set the global IoC container instance for emergency use. +// -------------------------------------------------------------- +IoC::$container = $application->container; \ No newline at end of file diff --git a/laravel/cache/apc.php b/laravel/cache/apc.php index 08ca44c4..f6e34d17 100644 --- a/laravel/cache/apc.php +++ b/laravel/cache/apc.php @@ -1,7 +1,5 @@ apc = $apc; + $this->key = $key; } /** @@ -90,7 +96,7 @@ public function has($key) */ protected function retrieve($key) { - return ( ! is_null($cache = $this->apc->get(Config::get('cache.key').$key))) ? $cache : null; + return ( ! is_null($cache = $this->apc->get($this->key.$key))) ? $cache : null; } /** @@ -108,7 +114,7 @@ protected function retrieve($key) */ public function put($key, $value, $minutes) { - $this->apc->put(Config::get('cache.key').$key, $value, $minutes * 60); + $this->apc->put($this->key.$key, $value, $minutes * 60); } /** @@ -119,7 +125,7 @@ public function put($key, $value, $minutes) */ public function forget($key) { - $this->apc->forget(Config::get('cache.key').$key); + $this->apc->forget($this->key.$key); } } \ No newline at end of file diff --git a/laravel/cache/file.php b/laravel/cache/file.php index 91f33d92..8dcb0971 100644 --- a/laravel/cache/file.php +++ b/laravel/cache/file.php @@ -9,15 +9,24 @@ class File extends Driver { */ private $file; + /** + * The path to which the cache files should be written. + * + * @var string + */ + private $path; + /** * Create a new File cache driver instance. * * @param Laravel\File $file + * @param string $path * @return void */ - public function __construct(\Laravel\File $file) + public function __construct(\Laravel\File $file, $path) { $this->file = $file; + $this->path = $path; } /** @@ -44,9 +53,9 @@ public function has($key) */ protected function retrieve($key) { - if ( ! $this->file->exists(CACHE_PATH.$key)) return null; + if ( ! $this->file->exists($this->path.$key)) return null; - if (time() >= substr($cache = $this->file->get(CACHE_PATH.$key), 0, 10)) + if (time() >= substr($cache = $this->file->get($this->path.$key), 0, 10)) { return $this->forget($key); } @@ -69,7 +78,7 @@ protected function retrieve($key) */ public function put($key, $value, $minutes) { - $this->file->put(CACHE_PATH.$key, (time() + ($minutes * 60)).serialize($value)); + $this->file->put($this->path.$key, (time() + ($minutes * 60)).serialize($value)); } /** @@ -80,7 +89,7 @@ public function put($key, $value, $minutes) */ public function forget($key) { - $this->file->delete(CACHE_PATH.$key); + $this->file->delete($this->path.$key); } } \ No newline at end of file diff --git a/laravel/cache/manager.php b/laravel/cache/manager.php index 51041a7a..665bdccc 100644 --- a/laravel/cache/manager.php +++ b/laravel/cache/manager.php @@ -1,7 +1,6 @@ default = $default; + $this->container = $container; + } /** * Get a cache driver instance. @@ -20,30 +45,30 @@ class Manager { * * * // Get the default cache driver - * $driver = Cache::driver(); + * $driver = $application->cache->driver(); * * // Get the APC cache driver - * $apc = Cache::driver('apc'); + * $apc = $application->cache->driver('apc'); * * * @param string $driver * @return Cache\Driver */ - public static function driver($driver = null) + public function driver($driver = null) { - if (is_null($driver)) $driver = Config::get('cache.driver'); + if (is_null($driver)) $driver = $this->default; - if ( ! array_key_exists($driver, static::$drivers)) + if ( ! array_key_exists($driver, $this->drivers)) { if ( ! in_array($driver, array('apc', 'file', 'memcached'))) { throw new \Exception("Cache driver [$driver] is not supported."); } - return static::$drivers[$driver] = IoC::container()->resolve('laravel.cache.'.$driver); + return $this->drivers[$driver] = $this->container->resolve('laravel.cache.'.$driver); } - return static::$drivers[$driver]; + return $this->drivers[$driver]; } /** @@ -54,12 +79,12 @@ public static function driver($driver = null) * * * // Get an item from the default cache driver - * $name = Cache::get('name'); + * $name = $application->cache->get('name'); * */ - public static function __callStatic($method, $parameters) + public function __call($method, $parameters) { - return call_user_func_array(array(static::driver(), $method), $parameters); + return call_user_func_array(array($this->driver(), $method), $parameters); } } \ No newline at end of file diff --git a/laravel/cache/memcached.php b/laravel/cache/memcached.php index 41df1315..f06c2042 100644 --- a/laravel/cache/memcached.php +++ b/laravel/cache/memcached.php @@ -1,5 +1,6 @@ key = $key; $this->memcache = $memcache; } @@ -46,7 +55,7 @@ public function has($key) */ protected function retrieve($key) { - return (($cache = $this->memcache->get(Config::get('cache.key').$key)) !== false) ? $cache : null; + return (($cache = $this->memcache->get($this->key.$key)) !== false) ? $cache : null; } /** @@ -64,7 +73,7 @@ protected function retrieve($key) */ public function put($key, $value, $minutes) { - $this->memcache->set(Config::get('cache.key').$key, $value, 0, $minutes * 60); + $this->memcache->set($this->key.$key, $value, 0, $minutes * 60); } /** @@ -75,7 +84,7 @@ public function put($key, $value, $minutes) */ public function forget($key) { - $this->memcache->delete(Config::get('cache.key').$key); + $this->memcache->delete($this->key.$key); } } \ No newline at end of file diff --git a/laravel/config.php b/laravel/config.php index fa3d992a..dc8bf284 100644 --- a/laravel/config.php +++ b/laravel/config.php @@ -9,7 +9,7 @@ class Config { * * @var array */ - public static $items = array(); + public $items = array(); /** * Determine if a configuration item or file exists. @@ -25,9 +25,9 @@ class Config { * @param string $key * @return bool */ - public static function has($key) + public function has($key) { - return ! is_null(static::get($key)); + return ! is_null($this->get($key)); } /** @@ -52,18 +52,18 @@ public static function has($key) * @param string $default * @return array */ - public static function get($key, $default = null) + public function get($key, $default = null) { - list($file, $key) = static::parse($key); + list($file, $key) = $this->parse($key); - if ( ! static::load($file)) + if ( ! $this->load($file)) { return ($default instanceof \Closure) ? call_user_func($default) : $default; } - if (is_null($key)) return static::$items[$file]; + if (is_null($key)) return $this->items[$file]; - return Arr::get(static::$items[$file], $key, $default); + return Arr::get($this->items[$file], $key, $default); } /** @@ -87,13 +87,13 @@ public static function get($key, $default = null) * @param mixed $value * @return void */ - public static function set($key, $value) + public function set($key, $value) { - list($file, $key) = static::parse($key); + list($file, $key) = $this->parse($key); - static::load($file); + $this->load($file); - (is_null($key)) ? Arr::set(static::$items, $file, $value) : Arr::set(static::$items[$file], $key, $value); + (is_null($key)) ? Arr::set($this->items, $file, $value) : Arr::set($this->items[$file], $key, $value); } /** @@ -104,7 +104,7 @@ public static function set($key, $value) * @param string $key * @return array */ - private static function parse($key) + private function parse($key) { $segments = explode('.', $key); @@ -119,23 +119,23 @@ private static function parse($key) * @param string $file * @return bool */ - private static function load($file) + private function load($file) { - if (isset(static::$items[$file])) return true; + if (isset($this->items[$file])) return true; $config = array(); - foreach (static::paths() as $directory) + foreach ($this->paths() as $directory) { $config = (file_exists($path = $directory.$file.EXT)) ? array_merge($config, require $path) : $config; } if (count($config) > 0) { - static::$items[$file] = $config; + $this->items[$file] = $config; } - return isset(static::$items[$file]); + return isset($this->items[$file]); } /** @@ -149,7 +149,7 @@ private static function load($file) * * @return array */ - private static function paths() + private function paths() { $paths = array(SYS_CONFIG_PATH, CONFIG_PATH); diff --git a/laravel/config/container.php b/laravel/config/container.php index e9404605..d510e67f 100644 --- a/laravel/config/container.php +++ b/laravel/config/container.php @@ -8,36 +8,73 @@ |-------------------------------------------------------------------------- */ - 'laravel.file' => array('singleton' => true, 'resolver' => function() + 'laravel.file' => array('singleton' => true, 'resolver' => function($container) { - return new File; + return new File($container->resolve('laravel.config')->get('mimes')); }), - /* - |-------------------------------------------------------------------------- - | Laravel View Components - |-------------------------------------------------------------------------- - */ - 'laravel.composers' => array('singleton' => true, 'resolver' => function() + 'laravel.form' => array('singleton' => true, 'resolver' => function($container) { - return require APP_PATH.'composers'.EXT; + $request = $container->resolve('laravel.request'); + + $html = $container->resolve('laravel.html'); + + $url = $container->resolve('laravel.url'); + + $token = ($container->registered('laravel.session.driver')) ? $container->resolve('laravel.session.driver')->get('csrf_token') : null; + + return new Form($request, $html, $url, $token); }), - /* - |-------------------------------------------------------------------------- - | Laravel Routing Components - |-------------------------------------------------------------------------- - */ - 'laravel.routing.router' => array('singleton' => true, 'resolver' => function($container) + 'laravel.html' => array('singleton' => true, 'resolver' => function($container) { - return new Routing\Router($container->resolve('laravel.request'), require APP_PATH.'routes'.EXT); + $encoding = $container->resolve('laravel.config')->get('application.encoding'); + + return new HTML($container->resolve('laravel.url'), $encoding); }), - 'laravel.routing.handler' => array('resolver' => function($container) + + 'laravel.package' => array('singleton' => true, 'resolver' => function() { - return new Routing\Handler($container->resolve('laravel.request'), require APP_PATH.'filters'.EXT); + return new Package; + }), + + + 'laravel.responder' => array('singleton' => true, 'resolver' => function($container) + { + require_once SYS_PATH.'response'.PHP; + + return new Response_Factory($container->resolve('laravel.view'), $container->resolve('laravel.file')); + }), + + + 'laravel.router' => array('singleton' => true, 'resolver' => function($container) + { + return new Routing\Router($container->resolve('laravel.request'), require APP_PATH.'routes'.EXT, CONTROLLER_PATH); + }), + + + 'laravel.url' => array('singleton' => true, 'resolver' => function($container) + { + $config = $container->resolve('laravel.config'); + + $request = $container->resolve('laravel.request'); + + $base = $config->get('application.url'); + + $index = $config->get('application.index'); + + return new URL($container->resolve('laravel.router'), $base, $index, $request->secure); + }), + + + 'laravel.view' => array('singleton' => true, 'resolver' => function() + { + require_once SYS_PATH.'view'.EXT; + + return new View_Factory(require APP_PATH.'composers'.EXT, VIEW_PATH); }), /* @@ -53,22 +90,12 @@ return new Security\Auth(Session\Manager::driver(), $hasher); }), + 'laravel.security.hashing.engine' => array('resolver' => function() { return new Security\Hashing\BCrypt(10, false); }), - /* - |-------------------------------------------------------------------------- - | Laravel Session Components - |-------------------------------------------------------------------------- - */ - - 'laravel.session.driver' => array('resolver' => function() - { - return Session\Manager::driver(); - }), - /* |-------------------------------------------------------------------------- | Laravel Cookie Session Components @@ -77,7 +104,11 @@ 'laravel.session.cookie' => array('resolver' => function($container) { - return new Session\Cookie(Security\Crypter::make(), $container->resolve('laravel.request')->input->cookies); + $cookies = $container->resolve('laravel.request')->input->cookies; + + $config = $container->resolve('laravel.config')->get('session'); + + return new Session\Cookie(Security\Crypter::make(), $cookies, $config); }), /* @@ -88,12 +119,9 @@ 'laravel.session.database' => array('resolver' => function($container) { - return new Session\Database($container->resolve('laravel.session.database.connection')); - }), + $table = $container->resolve('laravel.config')->get('session.table'); - 'laravel.session.database.connection' => array('resolver' => function() - { - return Database\Manager::connection(); + return new Session\Database($container->resolve('laravel.database.manager')->connection(), $table); }), /* @@ -102,14 +130,15 @@ |-------------------------------------------------------------------------- */ - 'laravel.cache.file' => array('resolver' => function() + 'laravel.cache.file' => array('resolver' => function($container) { - return new Cache\File(new File); + return new Cache\File($container->resolve('laravel.file'), CACHE_PATH); }), - 'laravel.session.file' => array('resolver' => function() + + 'laravel.session.file' => array('resolver' => function($container) { - return new Session\File(new File); + return new Session\File($container->resolve('laravel.file'), SESSION_PATH); }), /* @@ -120,17 +149,15 @@ 'laravel.cache.apc' => array('resolver' => function($container) { - return new Cache\APC($container->resolve('laravel.cache.apc_engine')); + return new Cache\APC(new Cache\APC_Engine, $container->resolve('laravel.config')->get('cache.key')); }), - 'laravel.cache.apc_engine' => array('resolver' => function() - { - return new Cache\APC_Engine; - }), 'laravel.session.apc' => array('resolver' => function($container) { - return new Session\APC($container->resolve('laravel.cache.apc')); + $lifetime = $container->resolve('laravel.config')->get('session.lifetime'); + + return new Session\APC($container->resolve('laravel.cache.apc'), $lifetime); }), /* @@ -141,15 +168,23 @@ 'laravel.cache.memcached' => array('resolver' => function($container) { - return new Cache\Memcached($container->resolve('laravel.memcache')); + $connection = $container->resolve('laravel.cache.memcache.connection'); + + $key = $container->resolve('laravel.config')->get('cache.key'); + + return new Cache\Memcached($connection, $key); }), + 'laravel.session.memcached' => array('resolver' => function($container) { - return new Session\Memcached($container->resolve('laravel.cache.memcached')); + $lifetime = $container->resolve('laravel.config')->get('session.lifetime'); + + return new Session\Memcached($container->resolve('laravel.cache.memcached'), $lifetime); }), - 'laravel.memcache' => array('singleton' => true, 'resolver' => function() + + 'laravel.cache.memcache.connection' => array('singleton' => true, 'resolver' => function() { if ( ! class_exists('Memcache')) { diff --git a/laravel/ioc.php b/laravel/container.php similarity index 72% rename from laravel/ioc.php rename to laravel/container.php index a4e43fbd..2f33d6b9 100644 --- a/laravel/ioc.php +++ b/laravel/container.php @@ -3,68 +3,33 @@ class IoC { /** - * The available IoC containers. + * The active container instance. * - * @var array + * @var Container */ - public static $containers = array(); + public static $container; /** - * Bootstrap the default container and register the dependencies. + * Get the active container instance. * - * @param array $dependencies - * @return void - */ - public static function bootstrap($dependencies) - { - $container = static::container(); - - foreach ($dependencies as $key => $value) - { - $container->register($key, $value['resolver'], (isset($value['singleton'])) ? $value['singleton'] : false); - } - } - - /** - * Get a container instance. - * - * If no container name is specified, the default container will be returned. - * - * - * // Get the default container instance - * $container = IoC::container(); - * - * // Get a specific container instance - * $container = IoC::container('models'); - * - * - * @param string $container * @return Container */ - public static function container($container = 'default') + public static function container() { - if ( ! array_key_exists($container, static::$containers)) - { - static::$containers[$container] = new Container; - } - - return static::$containers[$container]; + return static::$container; } /** - * Magic Method for passing methods to the default container. + * Magic Method for calling methods on the active container instance. * * - * // Resolve an object from the default container - * $user = IoC::resolve('user'); - * - * // Equivalent method of resolving using the container method - * $user = IoC::container()->resolve('user'); + * // Get the request registered in the container + * $request = IoC::resolve('laravel.request'); * */ public static function __callStatic($method, $parameters) { - return call_user_func_array(array(static::container(), $method), $parameters); + return call_user_func_array(array(static::$container, $method), $parameters); } } @@ -85,6 +50,20 @@ class Container { */ private $resolvers = array(); + /** + * Create a new IoC container instance. + * + * @param array $dependencies + * @return void + */ + public function __construct($dependencies = array()) + { + foreach ($dependencies as $key => $value) + { + $this->register($key, $value['resolver'], (isset($value['singleton'])) ? $value['singleton'] : false); + } + } + /** * Register a dependency and its resolver. * diff --git a/laravel/controller.php b/laravel/controller.php index cb4d7547..48359f27 100644 --- a/laravel/controller.php +++ b/laravel/controller.php @@ -8,14 +8,26 @@ abstract class Controller { * If a value is returned by the method, it will be halt the request process * and will be considered the response to the request. * - * @param Request $request * @return mixed */ - public function before($request) {} + public function before() {} + + /** + * Magic Method for getting items from the application instance. + */ + public function __get($key) + { + $application = IoC::resolve('laravel.application'); + + return $application->$key; + } /** * Magic Method to handle calls to undefined functions on the controller. */ - public function __call($method, $parameters) { return new Error('404'); } + public function __call($method, $parameters) + { + return IoC::resolve('laravel.application')->responder->error('404'); + } } \ No newline at end of file diff --git a/laravel/database/eloquent/model.php b/laravel/database/eloquent/model.php index 3ed36f27..9fd7a148 100644 --- a/laravel/database/eloquent/model.php +++ b/laravel/database/eloquent/model.php @@ -1,8 +1,6 @@ config = $config; + $this->default = $default; + } /** * Get a database connection. If no database name is specified, the default @@ -28,23 +51,23 @@ class Manager { * @param string $connection * @return Database\Connection */ - public static function connection($connection = null) + public function connection($connection = null) { - if (is_null($connection)) $connection = Config::get('database.default'); + if (is_null($connection)) $connection = $this->default; - if ( ! array_key_exists($connection, static::$connections)) + if ( ! array_key_exists($connection, $this->connections)) { - if (is_null($config = Config::get('database.connections.'.$connection))) + if ( ! isset($this->config[$connection])) { throw new \Exception("Database connection [$connection] is not defined."); } - $connector = Connector\Factory::make($config); + $connector = Connector\Factory::make($this->config[$connection]); - static::$connections[$connection] = new Connection($connection, $config, $connector); + static::$connections[$connection] = new Connection($connection, $this->config[$connection], $connector); } - return static::$connections[$connection]; + return $this->connections[$connection]; } /** @@ -67,9 +90,9 @@ public static function connection($connection = null) * @param string $connection * @return Database\Query */ - public static function table($table, $connection = null) + public function table($table, $connection = null) { - return static::connection($connection)->table($table); + return $this->connection($connection)->table($table); } /** @@ -85,9 +108,9 @@ public static function table($table, $connection = null) * $results = DB::connection()->query('select * from users'); * */ - public static function __callStatic($method, $parameters) + public function __call($method, $parameters) { - return call_user_func_array(array(static::connection(), $method), $parameters); + return call_user_func_array(array($this->connection(), $method), $parameters); } } \ No newline at end of file diff --git a/laravel/database/query.php b/laravel/database/query.php index 71f9bdbc..803c3880 100644 --- a/laravel/database/query.php +++ b/laravel/database/query.php @@ -1,10 +1,5 @@ - * // Return a download response for a given file - * return new Download('path/to/image.jpg'); - * - * // Return a download response for a given file and assign a name - * return new Download('path/to/image.jpg', 'you.jpg'); - * - * - * @param string $path - * @param string $name - */ - public function __construct($path, $name = null) - { - if (is_null($name)) $name = basename($path); - - $file = IoC::container()->resolve('laravel.file'); - - parent::__construct($file->get($path)); - - $this->header('Content-Description', 'File Transfer'); - $this->header('Content-Type', $file->mime($file->extension($path))); - $this->header('Content-Disposition', 'attachment; filename="'.$name.'"'); - $this->header('Content-Transfer-Encoding', 'binary'); - $this->header('Expires', 0); - $this->header('Cache-Control', 'must-revalidate, post-check=0, pre-check=0'); - $this->header('Pragma', 'public'); - $this->header('Content-Length', $file->size($path)); - } - -} \ No newline at end of file diff --git a/laravel/error.php b/laravel/error.php deleted file mode 100644 index 28242e2a..00000000 --- a/laravel/error.php +++ /dev/null @@ -1,26 +0,0 @@ - - * // Return a 404 error response - * return new Error('404'); - * - * - * @param int $code - * @param array $data - * @return void - */ - public function __construct($code, $data = array()) - { - return parent::__construct(View::make('error/'.$code, $data), $code); - } - -} \ No newline at end of file diff --git a/laravel/exception/examiner.php b/laravel/exception/examiner.php index d6778c5e..e83df500 100644 --- a/laravel/exception/examiner.php +++ b/laravel/exception/examiner.php @@ -11,13 +11,6 @@ class Examiner { */ public $exception; - /** - * The file manager instance. - * - * @var File - */ - private $file; - /** * Human-readable error levels and descriptions. * @@ -43,13 +36,11 @@ class Examiner { * Create a new exception examiner instance. * * @param Exception $exception - * @param File $file * @return void */ - public function __construct($exception, File $file) + public function __construct($exception) { $this->exception = $exception; - $this->file = $file; } /** @@ -89,7 +80,19 @@ public function message() */ public function context() { - return $this->file->snapshot($this->exception->getFile(), $this->exception->getLine()); + list($path, $line) = array($this->exception->getFile(), $this->exception->getLine()); + + if ( ! file_exists($path)) return array(); + + $file = file($path, FILE_IGNORE_NEW_LINES); + + array_unshift($file, ''); + + $start = $line - 5; + + $length = ($line - $start) + 5 + 1; + + return array_slice($file, ($start > 0) ? $start : 0, ($length > 0) ? $length : 0, true); } /** diff --git a/laravel/file.php b/laravel/file.php index 6ae6b91f..27e14600 100644 --- a/laravel/file.php +++ b/laravel/file.php @@ -2,6 +2,24 @@ class File { + /** + * All of the MIME types understood by the manager. + * + * @var array + */ + private $mimes; + + /** + * Create a new file manager instance. + * + * @param array $mimes + * @return void + */ + public function __construct($mimes) + { + $this->mimes = $mimes; + } + /** * Determine if a file exists. * @@ -103,36 +121,6 @@ public function modified($path) return filemtime($path); } - /** - * Get the lines surrounding a given line in a file. - * - * The amount of padding with which to surround the line may also be specified. - * - * - * // Get lines 10 - 20 of the "routes.php" file - * $lines = $file->snapshot(APP_PATH.'routes'.EXT, 15, 5); - * - * - * @param string $path - * @param int $line - * @param int $padding - * @return array - */ - public function snapshot($path, $line, $padding = 5) - { - if ( ! file_exists($path)) return array(); - - $file = file($path, FILE_IGNORE_NEW_LINES); - - array_unshift($file, ''); - - $start = $line - $padding; - - $length = ($line - $start) + $padding + 1; - - return array_slice($file, ($start > 0) ? $start : 0, ($length > 0) ? $length : 0, true); - } - /** * Get a file MIME type by extension. * @@ -149,11 +137,9 @@ public function snapshot($path, $line, $padding = 5) */ public function mime($extension, $default = 'application/octet-stream') { - $mimes = Config::get('mimes'); + if ( ! array_key_exists($extension, $this->mimes)) return $default; - if ( ! array_key_exists($extension, $mimes)) return $default; - - return (is_array($mimes[$extension])) ? $mimes[$extension][0] : $mimes[$extension]; + return (is_array($this->mimes[$extension])) ? $this->mimes[$extension][0] : $this->mimes[$extension]; } /** @@ -173,16 +159,14 @@ public function mime($extension, $default = 'application/octet-stream') */ public function is($extension, $path) { - $mimes = Config::get('mimes'); - - if ( ! array_key_exists($extension, $mimes)) + if ( ! array_key_exists($extension, $this->mimes)) { throw new \Exception("File extension [$extension] is unknown. Cannot determine file type."); } $mime = finfo_file(finfo_open(FILEINFO_MIME_TYPE), $path); - return (is_array($mimes[$extension])) ? in_array($mime, $mimes[$extension]) : $mime === $mimes[$extension]; + return (is_array($this->mimes[$extension])) ? in_array($mime, $this->mimes[$extension]) : $mime === $this->mimes[$extension]; } } \ No newline at end of file diff --git a/laravel/form.php b/laravel/form.php index c9d6310b..2331f6be 100644 --- a/laravel/form.php +++ b/laravel/form.php @@ -2,6 +2,34 @@ class Form { + /** + * The request instance. + * + * @var Request + */ + private $request; + + /** + * The HTML writer instance. + * + * @var HTML + */ + private $html; + + /** + * The URL generator instance. + * + * @var URL + */ + private $url; + + /** + * The CSRF token for the session. + * + * @var string + */ + public $token; + /** * All of the label names that have been created. * @@ -10,7 +38,22 @@ class Form { * * @var array */ - private static $labels = array(); + private $labels = array(); + + /** + * Create a new form writer instance. + * + * @param Request $request + * @param string $token + * @return void + */ + public function __construct(Request $request, HTML $html, URL $url, $token) + { + $this->url = $url; + $this->html = $html; + $this->token = $token; + $this->request = $request; + } /** * Open a HTML form. @@ -36,18 +79,18 @@ class Form { * @param bool $https * @return string */ - public static function open($action = null, $method = 'POST', $attributes = array(), $https = false) + public function open($action = null, $method = 'POST', $attributes = array(), $https = false) { - list($attributes['action'], $attributes['method']) = array(static::action($action, $https), static::method($method)); + list($attributes['action'], $attributes['method']) = array($this->action($action, $https), $this->method($method)); if ( ! array_key_exists('accept-charset', $attributes)) { $attributes['accept-charset'] = Config::get('application.encoding'); } - $append = ($method == 'PUT' or $method == 'DELETE') ? static::hidden('REQUEST_METHOD', $method) : ''; + $append = ($method == 'PUT' or $method == 'DELETE') ? $this->hidden('REQUEST_METHOD', $method) : ''; - return ''.$append.PHP_EOL; + return 'html->attributes($attributes).'>'.$append.PHP_EOL; } /** @@ -59,7 +102,7 @@ public static function open($action = null, $method = 'POST', $attributes = arra * @param string $method * @return string */ - private static function method($method) + private function method($method) { return strtoupper(($method == 'PUT' or $method == 'DELETE') ? 'POST' : $method); } @@ -73,11 +116,9 @@ private static function method($method) * @param bool $https * @return string */ - private static function action($action, $https) + private function action($action, $https) { - $request = IoC::container()->resolve('laravel.request'); - - return HTML::entities(URL::to(((is_null($action)) ? $request->uri() : $action), $https)); + return $this->html->entities($this->url->to(((is_null($action)) ? $this->request->uri : $action), $https)); } /** @@ -88,9 +129,9 @@ private static function action($action, $https) * @param array $attributes * @return string */ - public static function open_secure($action = null, $method = 'POST', $attributes = array()) + public function open_secure($action = null, $method = 'POST', $attributes = array()) { - return static::open($action, $method, $attributes, true); + return $this->open($action, $method, $attributes, true); } /** @@ -102,11 +143,11 @@ public static function open_secure($action = null, $method = 'POST', $attributes * @param bool $https * @return string */ - public static function open_for_files($action = null, $method = 'POST', $attributes = array(), $https = false) + public function open_for_files($action = null, $method = 'POST', $attributes = array(), $https = false) { $attributes['enctype'] = 'multipart/form-data'; - return static::open($action, $method, $attributes, $https); + return $this->open($action, $method, $attributes, $https); } /** @@ -117,9 +158,9 @@ public static function open_for_files($action = null, $method = 'POST', $attribu * @param array $attributes * @return string */ - public static function open_secure_for_files($action = null, $method = 'POST', $attributes = array()) + public function open_secure_for_files($action = null, $method = 'POST', $attributes = array()) { - return static::open_for_files($action, $method, $attributes, true); + return $this->open_for_files($action, $method, $attributes, true); } /** @@ -127,7 +168,7 @@ public static function open_secure_for_files($action = null, $method = 'POST', $ * * @return string */ - public static function close() + public function close() { return ''; } @@ -137,21 +178,9 @@ public static function close() * * @return string */ - public static function token() + public function token() { - $driver = IoC::container()->resolve('laravel.session.driver'); - - return static::input('hidden', 'csrf_token', static::raw_token($driver)); - } - - /** - * Retrieve the current CSRF token. - * - * @return string - */ - public static function raw_token() - { - return IoC::container()->resolve('laravel.session.driver')->get('csrf_token'); + return $this->input('hidden', 'csrf_token', $this->token); } /** @@ -166,11 +195,11 @@ public static function raw_token() * @param array $attributes * @return string */ - public static function label($name, $value, $attributes = array()) + public function label($name, $value, $attributes = array()) { - static::$labels[] = $name; + $this->labels[] = $name; - return ''.PHP_EOL; + return ''.PHP_EOL; } /** @@ -192,11 +221,11 @@ public static function label($name, $value, $attributes = array()) * @param array $attributes * @return string */ - public static function input($type, $name, $value = null, $attributes = array()) + public function input($type, $name, $value = null, $attributes = array()) { - $id = static::id($name, $attributes); + $id = $this->id($name, $attributes); - return ''.PHP_EOL; + return 'html->attributes(array_merge($attributes, compact('type', 'name', 'value', 'id'))).'>'.PHP_EOL; } /** @@ -207,9 +236,9 @@ public static function input($type, $name, $value = null, $attributes = array()) * @param array $attributes * @return string */ - public static function text($name, $value = null, $attributes = array()) + public function text($name, $value = null, $attributes = array()) { - return static::input('text', $name, $value, $attributes); + return $this->input('text', $name, $value, $attributes); } /** @@ -219,9 +248,9 @@ public static function text($name, $value = null, $attributes = array()) * @param array $attributes * @return string */ - public static function password($name, $attributes = array()) + public function password($name, $attributes = array()) { - return static::input('password', $name, null, $attributes); + return $this->input('password', $name, null, $attributes); } /** @@ -232,9 +261,9 @@ public static function password($name, $attributes = array()) * @param array $attributes * @return string */ - public static function hidden($name, $value = null, $attributes = array()) + public function hidden($name, $value = null, $attributes = array()) { - return static::input('hidden', $name, $value, $attributes); + return $this->input('hidden', $name, $value, $attributes); } /** @@ -245,9 +274,9 @@ public static function hidden($name, $value = null, $attributes = array()) * @param array $attributes * @return string */ - public static function search($name, $value = null, $attributes = array()) + public function search($name, $value = null, $attributes = array()) { - return static::input('search', $name, $value, $attributes); + return $this->input('search', $name, $value, $attributes); } /** @@ -258,9 +287,9 @@ public static function search($name, $value = null, $attributes = array()) * @param array $attributes * @return string */ - public static function email($name, $value = null, $attributes = array()) + public function email($name, $value = null, $attributes = array()) { - return static::input('email', $name, $value, $attributes); + return $this->input('email', $name, $value, $attributes); } /** @@ -270,10 +299,10 @@ public static function email($name, $value = null, $attributes = array()) * @param string $value * @param array $attributes * @return string - */ - public static function telephone($name, $value = null, $attributes = array()) + */ + public function telephone($name, $value = null, $attributes = array()) { - return static::input('tel', $name, $value, $attributes); + return $this->input('tel', $name, $value, $attributes); } /** @@ -284,9 +313,9 @@ public static function telephone($name, $value = null, $attributes = array()) * @param array $attributes * @return string */ - public static function url($name, $value = null, $attributes = array()) + public function url($name, $value = null, $attributes = array()) { - return static::input('url', $name, $value, $attributes); + return $this->input('url', $name, $value, $attributes); } /** @@ -297,9 +326,9 @@ public static function url($name, $value = null, $attributes = array()) * @param array $attributes * @return string */ - public static function number($name, $value = null, $attributes = array()) + public function number($name, $value = null, $attributes = array()) { - return static::input('number', $name, $value, $attributes); + return $this->input('number', $name, $value, $attributes); } /** @@ -309,9 +338,9 @@ public static function number($name, $value = null, $attributes = array()) * @param array $attributes * @return string */ - public static function file($name, $attributes = array()) + public function file($name, $attributes = array()) { - return static::input('file', $name, null, $attributes); + return $this->input('file', $name, null, $attributes); } /** @@ -322,15 +351,15 @@ public static function file($name, $attributes = array()) * @param array $attributes * @return string */ - public static function textarea($name, $value = '', $attributes = array()) + public function textarea($name, $value = '', $attributes = array()) { - $attributes = array_merge($attributes, array('id' => static::id($name, $attributes), 'name' => $name)); + $attributes = array_merge($attributes, array('id' => $this->id($name, $attributes), 'name' => $name)); if ( ! isset($attributes['rows'])) $attributes['rows'] = 10; if ( ! isset($attributes['cols'])) $attributes['cols'] = 50; - return ''.HTML::entities($value).''.PHP_EOL; + return 'html->attributes($attributes).'>'.$this->html->entities($value).''.PHP_EOL; } /** @@ -347,20 +376,20 @@ public static function textarea($name, $value = '', $attributes = array()) * @param array $attributes * @return string */ - public static function select($name, $options = array(), $selected = null, $attributes = array()) + public function select($name, $options = array(), $selected = null, $attributes = array()) { - $attributes = array_merge($attributes, array('id' => static::id($name, $attributes), 'name' => $name)); + $attributes = array_merge($attributes, array('id' => $this->id($name, $attributes), 'name' => $name)); $html = array(); foreach ($options as $value => $display) { - $option_attributes = array('value' => HTML::entities($value), 'selected' => ($value == $selected) ? 'selected' : null); + $option_attributes = array('value' => $this->html->entities($value), 'selected' => ($value == $selected) ? 'selected' : null); - $html[] = ''.HTML::entities($display).''; + $html[] = 'html->attributes($option_attributes).'>'.$this->html->entities($display).''; } - return ''.implode('', $html).''.PHP_EOL; + return 'html->attributes($attributes).'>'.implode('', $html).''.PHP_EOL; } /** @@ -372,9 +401,9 @@ public static function select($name, $options = array(), $selected = null, $attr * @param array $attributes * @return string */ - public static function checkbox($name, $value = null, $checked = false, $attributes = array()) + public function checkbox($name, $value = null, $checked = false, $attributes = array()) { - return static::checkable('checkbox', $name, $value, $checked, $attributes); + return $this->checkable('checkbox', $name, $value, $checked, $attributes); } /** @@ -386,9 +415,9 @@ public static function checkbox($name, $value = null, $checked = false, $attribu * @param array $attributes * @return string */ - public static function radio($name, $value = null, $checked = false, $attributes = array()) + public function radio($name, $value = null, $checked = false, $attributes = array()) { - return static::checkable('radio', $name, $value, $checked, $attributes); + return $this->checkable('radio', $name, $value, $checked, $attributes); } /** @@ -401,11 +430,11 @@ public static function radio($name, $value = null, $checked = false, $attributes * @param array $attributes * @return string */ - private static function checkable($type, $name, $value, $checked, $attributes) + private function checkable($type, $name, $value, $checked, $attributes) { - $attributes = array_merge($attributes, array('id' => static::id($name, $attributes), 'checked' => ($checked) ? 'checked' : null)); + $attributes = array_merge($attributes, array('id' => $this->id($name, $attributes), 'checked' => ($checked) ? 'checked' : null)); - return static::input($type, $name, $value, $attributes); + return $this->input($type, $name, $value, $attributes); } /** @@ -415,9 +444,9 @@ private static function checkable($type, $name, $value, $checked, $attributes) * @param array $attributes * @return string */ - public static function submit($value, $attributes = array()) + public function submit($value, $attributes = array()) { - return static::input('submit', null, $value, $attributes); + return $this->input('submit', null, $value, $attributes); } /** @@ -427,9 +456,9 @@ public static function submit($value, $attributes = array()) * @param array $attributes * @return string */ - public static function reset($value, $attributes = array()) + public function reset($value, $attributes = array()) { - return static::input('reset', null, $value, $attributes); + return $this->input('reset', null, $value, $attributes); } /** @@ -439,11 +468,11 @@ public static function reset($value, $attributes = array()) * @param array $attributes * @return string */ - public static function image($url, $name = null, $attributes = array()) + public function image($url, $name = null, $attributes = array()) { - $attributes['src'] = URL::to_asset($url); + $attributes['src'] = $this->url->to_asset($url); - return static::input('image', $name, null, $attributes); + return $this->input('image', $name, null, $attributes); } /** @@ -454,9 +483,9 @@ public static function image($url, $name = null, $attributes = array()) * @param array $attributes * @return string */ - public static function button($value, $attributes = array()) + public function button($value, $attributes = array()) { - return ''.HTML::entities($value).''.PHP_EOL; + return 'html->attributes($attributes).'>'.$this->html->entities($value).''.PHP_EOL; } /** @@ -469,11 +498,11 @@ public static function button($value, $attributes = array()) * @param array $attributes * @return mixed */ - private static function id($name, $attributes) + private function id($name, $attributes) { if (array_key_exists('id', $attributes)) return $attributes['id']; - if (in_array($name, static::$labels)) return $name; + if (in_array($name, $this->labels)) return $name; } } \ No newline at end of file diff --git a/laravel/html.php b/laravel/html.php index 1e6421f1..ca40e78e 100644 --- a/laravel/html.php +++ b/laravel/html.php @@ -2,6 +2,32 @@ class HTML { + /** + * The encoding being used by the application. + * + * @var string + */ + private $encoding; + + /** + * The URL generator instance. + * + * @var URL + */ + private $url; + + /** + * Create a new HTML writer instance. + * + * @param string $encoding + * @return void + */ + public function __construct(URL $url, $encoding) + { + $this->url = $url; + $this->encoding = $encoding; + } + /** * Convert HTML characters to entities. * @@ -10,9 +36,9 @@ class HTML { * @param string $value * @return string */ - public static function entities($value) + public function entities($value) { - return htmlentities($value, ENT_QUOTES, Config::get('application.encoding'), false); + return htmlentities($value, ENT_QUOTES, $this->encoding, false); } /** @@ -22,11 +48,11 @@ public static function entities($value) * @param array $attributes * @return string */ - public static function script($url, $attributes = array()) + public function script($url, $attributes = array()) { - $url = static::entities(URL::to_asset($url)); + $url = $this->entities($this->url->to_asset($url)); - return ''.PHP_EOL; + return ''.PHP_EOL; } /** @@ -36,13 +62,13 @@ public static function script($url, $attributes = array()) * @param array $attributes * @return string */ - public static function style($url, $attributes = array()) + public function style($url, $attributes = array()) { if ( ! array_key_exists('media', $attributes)) $attributes['media'] = 'all'; $attributes = array_merge($attributes, array('rel' => 'stylesheet', 'type' => 'text/css')); - return ''.PHP_EOL; + return 'attributes($attributes).'>'.PHP_EOL; } /** @@ -52,9 +78,9 @@ public static function style($url, $attributes = array()) * @param array $attributes * @return string */ - public static function span($value, $attributes = array()) + public function span($value, $attributes = array()) { - return ''.static::entities($value).''; + return 'attributes($attributes).'>'.$this->entities($value).''; } /** @@ -67,11 +93,11 @@ public static function span($value, $attributes = array()) * @param bool $asset * @return string */ - public static function link($url, $title, $attributes = array(), $https = false, $asset = false) + public function link($url, $title, $attributes = array(), $https = false, $asset = false) { - $url = static::entities(URL::to($url, $https, $asset)); + $url = $this->entities($this->url->to($url, $https, $asset)); - return ''.static::entities($title).''; + return 'attributes($attributes).'>'.$this->entities($title).''; } /** @@ -82,9 +108,9 @@ public static function link($url, $title, $attributes = array(), $https = false, * @param array $attributes * @return string */ - public static function link_to_secure($url, $title, $attributes = array()) + public function link_to_secure($url, $title, $attributes = array()) { - return static::link($url, $title, $attributes, true); + return $this->link($url, $title, $attributes, true); } /** @@ -95,9 +121,9 @@ public static function link_to_secure($url, $title, $attributes = array()) * @param array $attributes * @return string */ - public static function link_to_asset($url, $title, $attributes = array(), $https = false) + public function link_to_asset($url, $title, $attributes = array(), $https = false) { - return static::link($url, $title, $attributes, $https, true); + return $this->link($url, $title, $attributes, $https, true); } /** @@ -108,9 +134,9 @@ public static function link_to_asset($url, $title, $attributes = array(), $https * @param array $attributes * @return string */ - public static function link_to_secure_asset($url, $title, $attributes = array()) + public function link_to_secure_asset($url, $title, $attributes = array()) { - return static::link_to_asset($url, $title, $attributes, true); + return $this->link_to_asset($url, $title, $attributes, true); } /** @@ -132,9 +158,9 @@ public static function link_to_secure_asset($url, $title, $attributes = array()) * @param array $attributes * @return string */ - public static function link_to_route($name, $title, $parameters = array(), $attributes = array(), $https = false) + public function link_to_route($name, $title, $parameters = array(), $attributes = array(), $https = false) { - return static::link(URL::to_route($name, $parameters, $https), $title, $attributes); + return $this->link($this->url->to_route($name, $parameters, $https), $title, $attributes); } /** @@ -146,9 +172,9 @@ public static function link_to_route($name, $title, $parameters = array(), $attr * @param array $attributes * @return string */ - public static function link_to_secure_route($name, $title, $parameters = array(), $attributes = array()) + public function link_to_secure_route($name, $title, $parameters = array(), $attributes = array()) { - return static::link_to_route($name, $title, $parameters, $attributes, true); + return $this->link_to_route($name, $title, $parameters, $attributes, true); } /** @@ -161,15 +187,15 @@ public static function link_to_secure_route($name, $title, $parameters = array() * @param array $attributes * @return string */ - public static function mailto($email, $title = null, $attributes = array()) + public function mailto($email, $title = null, $attributes = array()) { - $email = static::email($email); + $email = $this->email($email); if (is_null($title)) $title = $email; $email = 'mailto:'.$email; - return ''.static::entities($title).''; + return 'attributes($attributes).'>'.$this->entities($title).''; } /** @@ -178,9 +204,9 @@ public static function mailto($email, $title = null, $attributes = array()) * @param string $email * @return string */ - public static function email($email) + public function email($email) { - return str_replace('@', '@', static::obfuscate($email)); + return str_replace('@', '@', $this->obfuscate($email)); } /** @@ -191,11 +217,11 @@ public static function email($email) * @param array $attributes * @return string */ - public static function image($url, $alt = '', $attributes = array()) + public function image($url, $alt = '', $attributes = array()) { - $attributes['alt'] = static::entities($alt); + $attributes['alt'] = $this->entities($alt); - return ''; + return 'attributes($attributes).'>'; } /** @@ -205,9 +231,9 @@ public static function image($url, $alt = '', $attributes = array()) * @param array $attributes * @return string */ - public static function ol($list, $attributes = array()) + public function ol($list, $attributes = array()) { - return static::list_elements('ol', $list, $attributes); + return $this->list_elements('ol', $list, $attributes); } /** @@ -217,9 +243,9 @@ public static function ol($list, $attributes = array()) * @param array $attributes * @return string */ - public static function ul($list, $attributes = array()) + public function ul($list, $attributes = array()) { - return static::list_elements('ul', $list, $attributes); + return $this->list_elements('ul', $list, $attributes); } /** @@ -230,16 +256,16 @@ public static function ul($list, $attributes = array()) * @param array $attributes * @return string */ - private static function list_elements($type, $list, $attributes = array()) + private function list_elements($type, $list, $attributes = array()) { $html = ''; foreach ($list as $key => $value) { - $html .= (is_array($value)) ? static::list_elements($type, $value) : '
  • '.static::entities($value).'
  • '; + $html .= (is_array($value)) ? $this->list_elements($type, $value) : '
  • '.$this->entities($value).'
  • '; } - return '<'.$type.static::attributes($attributes).'>'.$html.''; + return '<'.$type.$this->attributes($attributes).'>'.$html.''; } /** @@ -248,7 +274,7 @@ private static function list_elements($type, $list, $attributes = array()) * @param array $attributes * @return string */ - public static function attributes($attributes) + public function attributes($attributes) { $html = array(); @@ -260,7 +286,7 @@ public static function attributes($attributes) if ( ! is_null($value)) { - $html[] = $key.'="'.static::entities($value).'"'; + $html[] = $key.'="'.$this->entities($value).'"'; } } @@ -273,7 +299,7 @@ public static function attributes($attributes) * @param string $value * @return string */ - public static function obfuscate($value) + public function obfuscate($value) { $safe = ''; @@ -313,23 +339,23 @@ public static function obfuscate($value) * echo HTML::link_to_profile('Profile', array('taylor')); * */ - public static function __callStatic($method, $parameters) + public function __call($method, $parameters) { if (strpos($method, 'link_to_secure_') === 0) { array_unshift($parameters, substr($method, 15)); - return forward_static_call_array('HTML::link_to_secure_route', $parameters); + return call_user_func_array(array($this, 'link_to_secure_route'), $parameters); } if (strpos($method, 'link_to_') === 0) { array_unshift($parameters, substr($method, 8)); - return forward_static_call_array('HTML::link_to_route', $parameters); + return call_user_func_array(array($this, 'link_to_route'), $parameters); } - throw new \Exception("Static method [$method] is not defined on the HTML class."); + throw new \Exception("Method [$method] is not defined on the HTML class."); } } \ No newline at end of file diff --git a/laravel/input.php b/laravel/input.php index 588642d6..60c46eb9 100644 --- a/laravel/input.php +++ b/laravel/input.php @@ -7,7 +7,7 @@ class Input { * * @var array */ - public $input; + private $input; /** * The $_GET array for the request. @@ -40,33 +40,16 @@ class Input { /** * Create a new Input instance. * - * @param string $method - * @param bool $spoofed - * @param array $get - * @param array $post + * @param array $input * @param array $files * @param Cookie $cookies * @return void */ - public function __construct($method, $spoofed, $get, $post, $files, Cookie $cookies) + public function __construct($input, $files, Cookie $cookies) { - $this->get = $get; - $this->post = $post; + $this->input = $input; $this->files = $files; $this->cookies = $cookies; - - if ($method == 'GET') - { - $this->input = $this->get; - } - elseif ($method == 'POST') - { - $this->input = $this->post; - } - elseif ($method == 'PUT' or $method == 'DELETE') - { - ($spoofed) ? $this->input = $this->post : parse_str(file_get_contents('php://input'), $this->input); - } } /** diff --git a/laravel/laravel.php b/laravel/laravel.php index 3032a8c6..ddbac127 100644 --- a/laravel/laravel.php +++ b/laravel/laravel.php @@ -1,57 +1,14 @@ handle(); + call_user_func($application->config->get('error.handler'), $e); }); -set_error_handler(function($number, $error, $file, $line) use ($error_dependencies) +set_error_handler(function($number, $error, $file, $line) use ($application) { - call_user_func($error_dependencies); + $exception = new \ErrorException($error, $number, 0, $file, $line); - $e = new \ErrorException($error, $number, 0, $file, $line); - - Exception\Handler::make(new Exception\Examiner($e, new File))->handle(); + call_user_func($application->config->get('error.handler'), $exception); }); -register_shutdown_function(function() use ($error_dependencies) +register_shutdown_function(function() use ($application) { if ( ! is_null($error = error_get_last())) { - call_user_func($error_dependencies); + $exception = new \ErrorException($error['message'], $error['type'], 0, $error['file'], $error['line']); - $e = new \ErrorException($error['message'], $error['type'], 0, $error['file'], $error['line']); - - Exception\Handler::make(new Exception\Examiner($e, new File))->handle(); + call_user_func($application->config->get('error.handler'), $exception); } }); // -------------------------------------------------------------- // Set the default timezone. // -------------------------------------------------------------- -date_default_timezone_set(Config::get('application.timezone')); - -// -------------------------------------------------------------- -// Load all of the core routing and response classes. -// -------------------------------------------------------------- -require SYS_PATH.'input'.EXT; -require SYS_PATH.'request'.EXT; -require SYS_PATH.'response'.EXT; -require SYS_PATH.'routing/route'.EXT; -require SYS_PATH.'routing/router'.EXT; -require SYS_PATH.'routing/handler'.EXT; +date_default_timezone_set($application->config->get('application.timezone')); // -------------------------------------------------------------- // Initialize the request instance for the request. // -------------------------------------------------------------- -$request = new Request($_SERVER); +$application->request = new Request($_SERVER, $application->config->get('application.url')); -IoC::container()->instance('laravel.request', $request); +$application->container->instance('laravel.request', $application->request); // -------------------------------------------------------------- // Hydrate the input for the current request. // -------------------------------------------------------------- -$request->input = new Input($request->method(), $request->is_spoofed(), $_GET, $_POST, $_FILES, new Cookie($_COOKIE)); +$input = array(); + +if ($application->request->method == 'GET') +{ + $input = $_GET; +} +elseif ($application->request->method == 'POST') +{ + $input = $_POST; +} +elseif ($application->request->method == 'PUT' or $application->request->method == 'DELETE') +{ + ($application->request->spoofed) ? $input = $_POST : parse_str(file_get_contents('php://input'), $input); +} + +$application->input = new Input($input, $_FILES, new Cookie($_COOKIE)); + +$application->container->instance('laravel.input', $application->input); // -------------------------------------------------------------- -// Load the session. +// Load the cache manager. // -------------------------------------------------------------- -if (Config::get('session.driver') != '') +$application->cache = new Cache\Manager($application->container, $application->config->get('cache.driver')); + +$application->container->instance('laravel.cache.manager', $application->cache); + +// -------------------------------------------------------------- +// Load the database manager. +// -------------------------------------------------------------- +if ($application->config->get('database.autoload')) { - Session\Manager::driver()->start($request->input->cookies->get('laravel_session')); + $connections = $application->config->get('database.connections'); + + $application->database = new Database\Manager($connections, $application->config->get('database.default')); + + $application->container->instance('laravel.database.manager', $application->database); + + unset($connections); +} + +// -------------------------------------------------------------- +// Load the session and session manager. +// -------------------------------------------------------------- +if ($application->config->get('session.driver') !== '') +{ + $application->session = Session\Manager::driver($application->container, $application->config->get('session.driver')); + + $application->container->instance('laravel.session.driver', $application->session); + + $application->session->start($application->input->cookies->get('laravel_session'), $application->config->get('session.lifetime')); } // -------------------------------------------------------------- // Load the packages that are in the auto-loaded packages array. // -------------------------------------------------------------- -if (count(Config::get('application.packages')) > 0) -{ - require SYS_PATH.'package'.EXT; +$packages = $application->config->get('application.packages'); - Package::load(Config::get('application.packages')); +if (count($packages) > 0) +{ + $application->package->load($packages); } +unset($packages); + // -------------------------------------------------------------- // Route the request and get the response from the route. // -------------------------------------------------------------- -$route = IoC::container()->resolve('laravel.routing.router')->route(); +$route = $application->container->resolve('laravel.router')->route(); -$response = ( ! is_null($route)) ? IoC::container()->resolve('laravel.routing.handler')->handle($route) : new Error('404'); +if ( ! is_null($route)) +{ + $route->filters = require APP_PATH.'filters'.EXT; + + $response = $route->call($application); +} +else +{ + $response = new Error('404'); +} // -------------------------------------------------------------- // Stringify the response. @@ -158,18 +145,9 @@ // -------------------------------------------------------------- // Close the session. // -------------------------------------------------------------- -if (Config::get('session.driver') != '') +if ( ! is_null($application->session)) { - $driver = Session\Manager::driver(); - - $driver->flash('laravel_old_input', $request->input->get()); - - $driver->close($request->input->cookies); - - if ($driver instanceof Session\Sweeper and mt_rand(1, 100) <= 2) - { - $driver->sweep(time() - (Config::get('session.lifetime') * 60)); - } + $application->session->close($application->input, $application->config->get('session')); } // -------------------------------------------------------------- diff --git a/laravel/loader.php b/laravel/loader.php index 6d0c9e30..ebc4f6c2 100644 --- a/laravel/loader.php +++ b/laravel/loader.php @@ -7,27 +7,24 @@ class Loader { * * @var array */ - public static $paths = array(BASE_PATH); + public $paths; /** * All of the class aliases. * * @var array */ - public static $aliases = array(); + public $aliases; /** * Bootstrap the auto-loader. * - * @param array $aliases - * @param array $paths * @return void */ - public static function bootstrap($aliases, $paths) + public function __construct($aliases, $paths) { - static::$aliases = $aliases; - - foreach ($paths as $path) { static::register_path($path); } + $this->paths = $paths; + $this->aliases = $aliases; } /** @@ -39,16 +36,16 @@ public static function bootstrap($aliases, $paths) * @param string $class * @return void */ - public static function load($class) + public function load($class) { $file = strtolower(str_replace('\\', '/', $class)); - if (array_key_exists($class, static::$aliases)) + if (array_key_exists($class, $this->aliases)) { - return class_alias(static::$aliases[$class], $class); + return class_alias($this->aliases[$class], $class); } - foreach (static::$paths as $directory) + foreach ($this->paths as $directory) { if (file_exists($path = $directory.$file.EXT)) { @@ -67,9 +64,9 @@ public static function load($class) * @param string $path * @return void */ - public static function register_path($path) + public function register_path($path) { - static::$paths[] = rtrim($path, '/').'/'; + $this->paths[] = rtrim($path, '/').'/'; } /** @@ -78,9 +75,9 @@ public static function register_path($path) * @param array $alias * @return void */ - public static function register_alias($alias) + public function register_alias($alias) { - static::$aliases = array_merge(static::$aliases, $alias); + $this->aliases = array_merge($this->aliases, $alias); } /** @@ -89,9 +86,9 @@ public static function register_alias($alias) * @param string $alias * @return void */ - public static function forget_alias($alias) + public function forget_alias($alias) { - unset(static::$aliases[$alias]); + unset($this->aliases[$alias]); } } \ No newline at end of file diff --git a/laravel/package.php b/laravel/package.php index 361f8bdc..f77beb81 100644 --- a/laravel/package.php +++ b/laravel/package.php @@ -7,7 +7,7 @@ class Package { * * @var array */ - public static $loaded = array(); + public $loaded = array(); /** * Load a package or set of packages. @@ -26,16 +26,16 @@ class Package { * @param string $path * @return void */ - public static function load($packages, $path = PACKAGE_PATH) + public function load($packages, $path = PACKAGE_PATH) { foreach ((array) $packages as $package) { - if ( ! static::loaded($package) and file_exists($bootstrap = $path.$package.'/bootstrap'.EXT)) + if ( ! $this->loaded($package) and file_exists($bootstrap = $path.$package.'/bootstrap'.EXT)) { require $bootstrap; } - static::$loaded[] = $package; + $this->loaded[] = $package; } } @@ -50,9 +50,9 @@ public static function load($packages, $path = PACKAGE_PATH) * @param string $package * @return bool */ - public static function loaded($package) + public function loaded($package) { - return array_key_exists($package, static::$loaded); + return array_key_exists($package, $this->loaded); } } \ No newline at end of file diff --git a/laravel/request.php b/laravel/request.php index 7ac16db5..3dfcb6d4 100644 --- a/laravel/request.php +++ b/laravel/request.php @@ -3,18 +3,46 @@ class Request { /** - * The request instance for the current request. + * The request URI. * - * @var Request + * @var string */ - private static $active; + public $uri; /** - * The $_SERVER array for the request. + * The request method (GET, POST, PUT, or DELETE). * - * @var array + * @var string */ - private $server; + public $method; + + /** + * Indicates if the request method is being spoofed by a hidden form element. + * + * @var bool + */ + public $spoofed; + + /** + * The requestor's IP address. + * + * @var string + */ + public $ip; + + /** + * Indicates if the request is using HTTPS. + * + * @var bool + */ + public $secure; + + /** + * Indicates if the request is an AJAX request. + * + * @var bool + */ + public $ajax; /** * The input instance for the request. @@ -23,6 +51,13 @@ class Request { */ public $input; + /** + * The $_SERVER array for the request. + * + * @var array + */ + public $server; + /** * The route handling the current request. * @@ -30,45 +65,40 @@ class Request { */ public $route; - /** - * The request URI. - * - * @var string - */ - private $uri; - /** * Create a new request instance. * - * @param array $server + * @param array $server + * @param string $url * @return void */ - public function __construct($server) + public function __construct($server, $url) { $this->server = $server; - static::$active = $this; + $this->uri = $this->uri($url); + + foreach (array('method', 'spoofed', 'ip', 'secure', 'ajax') as $item) + { + $this->$item = $this->$item(); + } } /** - * Get the request instance for the current request. + * Determine the request URI. * - * @return Request - */ - public static function active() - { - return static::$active; - } - - /** - * Get the raw request URI. + * The request URI will be trimmed to remove to the application URL and application index file. + * If the request is to the root of the application, the URI will be set to a forward slash. * + * If the $_SERVER "PATH_INFO" variable is available, it will be used; otherwise, we will try + * to determine the URI using the REQUEST_URI variable. If neither are available, an exception + * will be thrown by the method. + * + * @param string $url * @return string */ - public function uri() + private function uri($url) { - if ( ! is_null($this->uri)) return $this->uri; - if (isset($this->server['PATH_INFO'])) { $uri = $this->server['PATH_INFO']; @@ -84,36 +114,26 @@ public function uri() if ($uri === false) throw new \Exception('Malformed request URI. Request terminated.'); - return $this->uri = $this->remove_from_uri($uri, array(parse_url(Config::get('application.url'), PHP_URL_PATH), '/index.php')); - } - - /** - * Remove an array of values from the beginning from a URI. - * - * @param string $uri - * @param array $values - * @return string - */ - private function remove_from_uri($uri, $values) - { - foreach ($values as $value) + foreach (array(parse_url($url, PHP_URL_PATH), '/index.php') as $value) { $uri = (strpos($uri, $value) === 0) ? substr($uri, strlen($value)) : $uri; } - - return $uri; + + return (($uri = trim($uri, '/')) == '') ? '/' : $uri; } /** * Get the request method. * - * Note: If the request method is being spoofed, the spoofed method will be returned. + * Typically, this will be the value of the REQUEST_METHOD $_SERVER variable. + * However, when the request is being spoofed by a hidden form value, the request + * method will be stored in the $_POST array. * * @return string */ - public function method() + private function method() { - return ($this->is_spoofed()) ? $_POST['REQUEST_METHOD'] : $this->server['REQUEST_METHOD']; + return ($this->spoofed()) ? $_POST['REQUEST_METHOD'] : $this->server['REQUEST_METHOD']; } /** @@ -123,7 +143,7 @@ public function method() * * @return bool */ - public function is_spoofed() + private function spoofed() { return is_array($_POST) and array_key_exists('REQUEST_METHOD', $_POST); } @@ -133,7 +153,7 @@ public function is_spoofed() * * @return string */ - public function ip() + private function ip() { if (isset($this->server['HTTP_X_FORWARDED_FOR'])) { @@ -150,11 +170,11 @@ public function ip() } /** - * Get the HTTP protocol for the request (http or https). + * Get the HTTP protocol for the request. * * @return string */ - public function protocol() + private function protocol() { return (isset($this->server['HTTPS']) and $this->server['HTTPS'] !== 'off') ? 'https' : 'http'; } @@ -164,7 +184,7 @@ public function protocol() * * @return bool */ - public function is_secure() + private function secure() { return ($this->protocol() == 'https'); } @@ -174,9 +194,11 @@ public function is_secure() * * @return bool */ - public function is_ajax() + private function ajax() { - return (isset($this->server['HTTP_X_REQUESTED_WITH']) and strtolower($this->server['HTTP_X_REQUESTED_WITH']) === 'xmlhttprequest'); + if ( ! isset($this->server['HTTP_X_REQUESTED_WITH'])) return false; + + return strtolower($this->server['HTTP_X_REQUESTED_WITH']) === 'xmlhttprequest'; } /** diff --git a/laravel/response.php b/laravel/response.php index 15f6d63a..22a9a0da 100644 --- a/laravel/response.php +++ b/laravel/response.php @@ -1,17 +1,102 @@ view = $view; + $this->file = $file; + } + + /** + * Create a new response instance. + * + * @param mixed $content + * @param int $status + * @return Response + */ + public function make($content, $status = 200) + { + return new Response($content, $status); + } + + /** + * Create a new download response instance. + * + * + * // Return a download response for a given file + * return new Download('path/to/image.jpg'); + * + * // Return a download response for a given file and assign a name + * return new Download('path/to/image.jpg', 'you.jpg'); + * + * + * @param string $path + * @param string $name + * @return Response + */ + public function download($path, $name = null) + { + if (is_null($name)) $name = basename($path); + + $response = new Response($this->file->get($path)); + + $response->header('Content-Description', 'File Transfer'); + $response->header('Content-Type', $this->file->mime($this->file->extension($path))); + $response->header('Content-Disposition', 'attachment; filename="'.$name.'"'); + $response->header('Content-Transfer-Encoding', 'binary'); + $response->header('Expires', 0); + $response->header('Cache-Control', 'must-revalidate, post-check=0, pre-check=0'); + $response->header('Pragma', 'public'); + $response->header('Content-Length', $this->file->size($path)); + + return $response; + } + + /** + * Create a new error response instance. + * + * The response status code will be set using the specified code. + * + * Note: The specified error code should correspond to a view in your views/error directory. + * + * + * // Return a 404 error response + * return new Error('404'); + * + * + * @param int $code + * @param array $data + * @return void + */ + public function error($code, $data = array()) + { + return new Response($this->view->make('error/'.$code, $data), $code); + } } -class Response implements Renderable { +class Response { /** * The content of the response. @@ -100,30 +185,14 @@ public function __construct($content, $status = 200) $this->status = $status; } - /** - * Factory for creating new response instances. - * - * @param string $content - * @param int $status - * @return Response - */ - public static function make($content, $status = 200) - { - return new static($content, $status); - } - /** * Get the evaluated string contents of the response. * - * If the content implements the Renderable interface, the render method will be called - * on the content and the result will be returned. Otherwise, the content will be cast - * to a string and returned. - * * @return string */ public function render() { - return ($this->content instanceof Renderable) ? $this->content->render() : (string) $this->content; + return ($this->content instanceof View) ? $this->content->render() : (string) $this->content; } /** diff --git a/laravel/routing/handler.php b/laravel/routing/handler.php deleted file mode 100644 index 677b7a66..00000000 --- a/laravel/routing/handler.php +++ /dev/null @@ -1,194 +0,0 @@ -request = $request; - $this->filters = $filters; - } - - /** - * Execute a given route and return the response. - * - * @param Route $route - * @return Response - */ - public function handle(Route $route) - { - $this->validate($route); - - if ( ! is_null($response = $this->filter(array_merge($route->before(), array('before')), array($this->request), true))) - { - return $this->finish($route, $response); - } - - $closure = ( ! $route->callback instanceof Closure) ? $this->find_route_closure($route) : $route->callback; - - if ( ! is_null($closure)) return $this->handle_closure($route, $closure); - - return $this->finish($route, new Error('404')); - } - - /** - * Validate that a given route is callable. - * - * @param Route $route - * @return void - */ - protected function validate(Route $route) - { - if ( ! $route->callback instanceof Closure and ! is_array($route->callback)) - { - throw new \Exception('Invalid route defined for URI ['.$route->key.']'); - } - } - - /** - * Extract the route closure from the route. - * - * If a "do" index is specified on the callback, that is the handler. - * Otherwise, we will return the first callable array value. - * - * @param Route $route - * @return Closure - */ - protected function find_route_closure(Route $route) - { - if (isset($route->callback['do'])) return $route->callback['do']; - - foreach ($route->callback as $value) { if ($value instanceof Closure) return $value; } - } - - /** - * Handle a route closure. - * - * @param Route $route - * @param Closure $closure - * @return mixed - */ - protected function handle_closure(Route $route, Closure $closure) - { - array_unshift($route->parameters, $this->request); - - $response = call_user_func_array($closure, $route->parameters); - - if (is_array($response)) - { - $response = $this->delegate($response[0], $response[1], $route->parameters); - } - - return $this->finish($route, $response); - } - - /** - * Handle the delegation of a route to a controller method. - * - * @param string $controller - * @param string $method - * @param array $parameters - * @return Response - */ - protected function delegate($controller, $method, $parameters) - { - if ( ! file_exists($path = CONTROLLER_PATH.strtolower(str_replace('.', '/', $controller)).EXT)) - { - throw new \Exception("Controller [$controller] is not defined."); - } - - require $path; - - $controller = $this->resolve($controller); - - $response = ($method == 'before' or strncmp($method, '_', 1) === 0) ? new Error('404') : $controller->before($this->request); - - return (is_null($response)) ? call_user_func_array(array($controller, $method), $parameters) : $response; - } - - /** - * Resolve a controller name to a controller instance. - * - * @param string $controller - * @return Controller - */ - protected function resolve($controller) - { - if (IoC::container()->registered('controllers.'.$controller)) - { - return IoC::container()->resolve('controllers.'.$controller); - } - - $controller = str_replace(' ', '_', ucwords(str_replace('.', ' ', $controller))).'_Controller'; - - return new $controller; - } - - /** - * Call a filter or set of filters. - * - * @param array $filters - * @param array $parameters - * @param bool $override - * @return mixed - */ - protected function filter($filters, $parameters = array(), $override = false) - { - foreach ((array) $filters as $filter) - { - if ( ! isset($this->filters[$filter])) continue; - - $response = call_user_func_array($this->filters[$filter], $parameters); - - // "Before" filters may override the request cycle. For example, an authentication - // filter may redirect a user to a login view if they are not logged in. Because of - // this, we will return the first filter response if overriding is enabled. - if ( ! is_null($response) and $override) return $response; - } - } - - /** - * Finish the route handling for the request. - * - * The route response will be converted to a Response instance and the "after" filters - * defined for the route will be executed. - * - * @param Route $route - * @param mixed $response - * @return Response - */ - protected function finish(Route $route, $response) - { - if ( ! $response instanceof Response) $response = new Response($response); - - $this->filter(array_merge($route->after(), array('after')), array($this->request, $response)); - - return $response; - } - -} \ No newline at end of file diff --git a/laravel/routing/route.php b/laravel/routing/route.php index b3450203..352ca955 100644 --- a/laravel/routing/route.php +++ b/laravel/routing/route.php @@ -1,5 +1,10 @@ key = $key; $this->callback = $callback; $this->parameters = $parameters; + $this->controller_path = $controller_path; + } + + /** + * Execute the route for a given request to the application and return the response. + * + * @param Application $application + * @return Response + */ + public function call(Application $application) + { + $this->validate(); + + if ( ! is_null($response = $this->filter(array_merge($this->before(), array('before')), array($application), true))) + { + return $this->finish($application, $response); + } + + $closure = ( ! $this->callback instanceof Closure) ? $this->find_route_closure() : $this->callback; + + if ( ! is_null($closure)) return $this->handle_closure($application, $closure); + + return $this->finish($application, $application->responder->error('404')); + } + + /** + * Validate that a given route is callable. + * + * @return void + */ + protected function validate() + { + if ( ! $this->callback instanceof Closure and ! is_array($this->callback)) + { + throw new \Exception('Invalid route defined for URI ['.$this->key.']'); + } + } + + /** + * Extract the route closure from the route. + * + * If a "do" index is specified on the callback, that is the handler. + * Otherwise, we will return the first callable array value. + * + * @return Closure + */ + protected function find_route_closure() + { + if (isset($this->callback['do'])) return $this->callback['do']; + + foreach ($this->callback as $value) { if ($value instanceof Closure) return $value; } + } + + /** + * Handle a route closure. + * + * @param Route $route + * @param Closure $closure + * @return mixed + */ + protected function handle_closure(Application $application, Closure $closure) + { + array_unshift($this->parameters, $application); + + $response = call_user_func_array($closure, $this->parameters); + + if (is_array($response)) + { + $response = $this->delegate($application, $response[0], $response[1], $this->parameters); + } + + return $this->finish($application, $response); + } + + /** + * Handle the delegation of a route to a controller method. + * + * @param Application $application + * @param string $controller + * @param string $method + * @param array $parameters + * @return Response + */ + protected function delegate(Application $application, $controller, $method, $parameters) + { + if ( ! file_exists($path = $this->controller_path.strtolower(str_replace('.', '/', $controller)).EXT)) + { + throw new \Exception("Controller [$controller] is not defined."); + } + + require $path; + + $controller = $this->resolve($application->container, $controller); + + if ($method == 'before' or strncmp($method, '_', 1) === 0) + { + $response = $application->responder->error('404'); + } + else + { + $response = $controller->before(); + } + + return (is_null($response)) ? call_user_func_array(array($controller, $method), $parameters) : $response; + } + + /** + * Resolve a controller name to a controller instance. + * + * @param Container $container + * @param string $controller + * @return Controller + */ + protected function resolve(Container $container, $controller) + { + if ($container->registered('controllers.'.$controller)) + { + return $container->resolve('controllers.'.$controller); + } + + $controller = str_replace(' ', '_', ucwords(str_replace('.', ' ', $controller))).'_Controller'; + + return new $controller; + } + + /** + * Finish the route handling for the request. + * + * The route response will be converted to a Response instance and the "after" filters + * defined for the route will be executed. + * + * @param Route $route + * @param mixed $response + * @return Response + */ + protected function finish(Application $application, $response) + { + if ( ! $response instanceof Response) $response = new Response($response); + + $this->filter(array_merge($this->after(), array('after')), array($application, $response)); + + return $response; + } + + /** + * Call a filter or set of filters. + * + * @param array $filters + * @param array $parameters + * @param bool $override + * @return mixed + */ + protected function filter($filters, $parameters = array(), $override = false) + { + foreach ((array) $filters as $filter) + { + if ( ! isset($this->filters[$filter])) continue; + + $response = call_user_func_array($this->filters[$filter], $parameters); + + // "Before" filters may override the request cycle. For example, an authentication + // filter may redirect a user to a login view if they are not logged in. Because of + // this, we will return the first filter response if overriding is enabled. + if ( ! is_null($response) and $override) return $response; + } } /** diff --git a/laravel/routing/router.php b/laravel/routing/router.php index 30c0cefc..715d2007 100644 --- a/laravel/routing/router.php +++ b/laravel/routing/router.php @@ -25,6 +25,13 @@ class Router { */ protected $names = array(); + /** + * The path the application controllers. + * + * @var string + */ + protected $controller_path; + /** * Create a new router for a request method and URI. * @@ -32,10 +39,11 @@ class Router { * @param array $routes * @return void */ - public function __construct(Request $request, $routes) + public function __construct(Request $request, $routes, $controller_path) { $this->routes = $routes; $this->request = $request; + $this->controller_path = $controller_path; } /** @@ -84,13 +92,13 @@ public function route() { // Put the request method and URI in route form. Routes begin with // the request method and a forward slash. - $destination = $this->request->method().' /'.trim($this->request->uri(), '/'); + $destination = $this->request->method.' /'.trim($this->request->uri, '/'); // Check for a literal route match first. If we find one, there is // no need to spin through all of the routes. if (isset($this->routes[$destination])) { - return $this->request->route = new Route($destination, $this->routes[$destination]); + return $this->request->route = new Route($destination, $this->routes[$destination], array(), $this->controller_path); } foreach ($this->routes as $keys => $callback) @@ -103,7 +111,7 @@ public function route() { if (preg_match('#^'.$this->translate_wildcards($key).'$#', $destination)) { - return $this->request->route = new Route($keys, $callback, $this->parameters($destination, $key)); + return $this->request->route = new Route($keys, $callback, $this->parameters($destination, $key), $this->controller_path); } } } @@ -121,7 +129,7 @@ public function route() */ protected function route_to_controller() { - $segments = explode('/', trim($this->request->uri(), '/')); + $segments = explode('/', trim($this->request->uri, '/')); if ( ! is_null($key = $this->controller_key($segments))) { @@ -145,7 +153,7 @@ protected function route_to_controller() // were they to code the controller delegation manually. $callback = function() use ($controller, $method) { return array($controller, $method); }; - return new Route($controller, $callback, $segments); + return new Route($controller, $callback, $segments, $this->controller_path); } } @@ -165,7 +173,7 @@ protected function controller_key($segments) // matching controller. Once we find it, we will return those routes. foreach (array_reverse($segments, true) as $key => $value) { - if (file_exists($path = CONTROLLER_PATH.implode('/', array_slice($segments, 0, $key + 1)).EXT)) + if (file_exists($path = $this->controller_path.implode('/', array_slice($segments, 0, $key + 1)).EXT)) { return $key + 1; } diff --git a/laravel/session/apc.php b/laravel/session/apc.php index 3e37d001..24344abe 100644 --- a/laravel/session/apc.php +++ b/laravel/session/apc.php @@ -1,7 +1,5 @@ apc = $apc; + $this->lifetime = $lifetime; } /** @@ -43,7 +49,7 @@ protected function load($id) */ protected function save() { - $this->apc->put($this->session['id'], $this->session, Config::get('session.lifetime')); + $this->apc->put($this->session['id'], $this->session, $this->lifetime); } /** diff --git a/laravel/session/cookie.php b/laravel/session/cookie.php index 01997912..e576a2c4 100644 --- a/laravel/session/cookie.php +++ b/laravel/session/cookie.php @@ -1,6 +1,5 @@ cookie = $cookie; + $this->config = $config; $this->crypter = $crypter; - - if (Config::get('application.key') == '') - { - throw new \Exception("You must set an application key before using the Cookie session driver."); - } } /** @@ -63,7 +66,7 @@ protected function save() { if ( ! headers_sent()) { - extract(Config::get('session')); + extract($this->config); $payload = $this->crypter->encrypt(serialize($this->session)); diff --git a/laravel/session/database.php b/laravel/session/database.php index 3a28fc9e..49756a42 100644 --- a/laravel/session/database.php +++ b/laravel/session/database.php @@ -1,6 +1,5 @@ table = $table; $this->connection = $connection; } @@ -90,7 +98,7 @@ public function sweep($expiration) */ private function table() { - return $this->connection->table(Config::get('session.table')); + return $this->connection->table($this->table); } } \ No newline at end of file diff --git a/laravel/session/driver.php b/laravel/session/driver.php index 82db3426..3025dbcf 100644 --- a/laravel/session/driver.php +++ b/laravel/session/driver.php @@ -1,7 +1,7 @@ session = ( ! is_null($id)) ? $this->load($id) : null; - if (is_null($this->session) or (time() - $this->session['last_activity']) > (Config::get('session.lifetime') * 60)) + if (is_null($this->session) or (time() - $this->session['last_activity']) > ($lifetime * 60)) { $this->session = array('id' => Str::random(40), 'data' => array()); } @@ -117,11 +118,13 @@ public function get($key, $default = null) * * @param string $key * @param mixed $value - * @return void + * @return Driver */ public function put($key, $value) { $this->session['data'][$key] = $value; + + return $this; } /** @@ -137,11 +140,13 @@ public function put($key, $value) * * @param string $key * @param mixed $value - * @return void + * @return Driver */ public function flash($key, $value) { $this->put(':new:'.$key, $value); + + return $this; } /** @@ -153,7 +158,7 @@ public function flash($key, $value) * * * @param string $key - * @return void + * @return Driver */ public function forget($key) { @@ -188,59 +193,94 @@ public function regenerate() * The session will be stored in persistant storage and the session cookie will be * session cookie will be sent to the browser. * - * @param Laravel\Cookie $cookie + * The input of the current request will also be flashed to the session so it is + * available for the next request via the "old" method on the input class. + * + * @param Laravel\Input $input + * @param array $config * @return void */ - public function close(\Laravel\Cookie $cookie) + public function close(Input $input, $config) { - $this->age_flash(); + $this->flash('laravel_old_input', $input->get())->age(); $this->save(); - $this->write_cookie($cookie); + $this->write_cookie($input->cookies, $config); + + if ($this instanceof Sweeper and mt_rand(1, 100) <= 2) + { + $this->sweep(time() - ($config['lifetime'] * 60)); + } } /** * Age the session flash data. * + * To age the data, we will forget all of the old keys and then rewrite the newly + * flashed items to have old keys, which will be available for the next request. + * * @return void */ - public function age_flash() + protected function age() { foreach ($this->session['data'] as $key => $value) { if (strpos($key, ':old:') === 0) $this->forget($key); } - foreach ($this->session['data'] as $key => $value) - { - if (strpos($key, ':new:') === 0) - { - $this->put(':old:'.substr($key, 5), $value); + $session = $this->session['data']; - $this->forget($key); - } - } + $this->session['data'] = array_combine(str_replace(':new:', ':old:', array_keys($session)), array_values($session)); } /** * Write the session cookie. * + * All of the session cookie configuration options are stored in the session + * configuration file. The cookie will only be written if the headers have not + * already been sent to the browser. + * * @param Laravel\Cookie $cookie + * @param array $config * @return void */ - protected function write_cookie(\Laravel\Cookie $cookie) + protected function write_cookie(Cookie $cookies, $config) { if ( ! headers_sent()) { - $config = Config::get('session'); - extract($config); $minutes = ($expire_on_close) ? 0 : $lifetime; - $cookie->put('laravel_session', $this->session['id'], $minutes, $path, $domain, $https, $http_only); + $cookies->put('laravel_session', $this->session['id'], $minutes, $path, $domain, $https, $http_only); } } + /** + * Magic Method for retrieving items from the session. + * + * + * // Get the "name" item from the session + * $name = $application->session->name; + * + */ + public function __get($key) + { + return $this->get($key); + } + + /** + * Magic Method for writings items to the session. + * + * + * // Write "Fred" to the session "name" item + * $application->session->name = 'Fred'; + * + */ + public function __set($key, $value) + { + $this->put($key, $value); + } + } \ No newline at end of file diff --git a/laravel/session/file.php b/laravel/session/file.php index 055913bb..c027b16b 100644 --- a/laravel/session/file.php +++ b/laravel/session/file.php @@ -9,15 +9,24 @@ class File extends Driver implements Sweeper { */ private $file; + /** + * The path to which the session files should be written. + * + * @var string + */ + private $path; + /** * Create a new File session driver instance. * * @param Laravel\File $file + * @param string $path * @return void */ - public function __construct(\Laravel\File $file) + public function __construct(\Laravel\File $file, $path) { $this->file = $file; + $this->path = $path; } /** @@ -31,7 +40,7 @@ public function __construct(\Laravel\File $file) */ protected function load($id) { - if ($this->file->exists($path = SESSION_PATH.$id)) return unserialize($this->file->get($path)); + if ($this->file->exists($path = $this->path.$id)) return unserialize($this->file->get($path)); } /** @@ -41,7 +50,7 @@ protected function load($id) */ protected function save() { - $this->file->put(SESSION_PATH.$this->session['id'], serialize($this->session), LOCK_EX); + $this->file->put($this->path.$this->session['id'], serialize($this->session), LOCK_EX); } /** @@ -51,7 +60,7 @@ protected function save() */ protected function delete() { - $this->file->delete(SESSION_PATH.$this->session['id']); + $this->file->delete($this->path.$this->session['id']); } /** @@ -62,7 +71,7 @@ protected function delete() */ public function sweep($expiration) { - foreach (glob(SESSION_PATH.'*') as $file) + foreach (glob($this->path.'*') as $file) { if ($this->file->type($file) == 'file' and $this->file->modified($file) < $expiration) $this->file->delete($file); } diff --git a/laravel/session/manager.php b/laravel/session/manager.php index 4bc03977..df126cd4 100644 --- a/laravel/session/manager.php +++ b/laravel/session/manager.php @@ -1,17 +1,10 @@ resolve('laravel.session.'.$driver); - } - - throw new \Exception("Session driver [$driver] is not supported."); + return $container->resolve('laravel.session.'.$driver); } - return static::$driver; - } - - /** - * Pass all other methods to the default session driver. - * - * By dynamically passing these method calls to the default driver, the developer is - * able to use with a convenient API when working with the session. - * - * - * // Get an item from the default session driver - * $name = Session::get('name'); - * - * // Equivalent call using the driver method - * $name = Session::driver()->get('name'); - * - */ - public static function __callStatic($method, $parameters) - { - return call_user_func_array(array(static::driver(), $method), $parameters); + throw new \Exception("Session driver [$driver] is not supported."); } } \ No newline at end of file diff --git a/laravel/session/memcached.php b/laravel/session/memcached.php index 21ad9099..9771eb57 100644 --- a/laravel/session/memcached.php +++ b/laravel/session/memcached.php @@ -1,7 +1,5 @@ lifetime = $lifetime; $this->memcached = $memcached; } @@ -43,7 +49,7 @@ protected function load($id) */ protected function save() { - $this->memcached->put($this->session['id'], $this->session, Config::get('session.lifetime')); + $this->memcached->put($this->session['id'], $this->session, $this->lifetime); } /** diff --git a/laravel/url.php b/laravel/url.php index 9c926cef..db535b0c 100644 --- a/laravel/url.php +++ b/laravel/url.php @@ -2,6 +2,23 @@ class URL { + /** + * Create a new URL writer instance. + * + * @param Router $router + * @param string $base + * @param string $index + * @param bool $https + * @return void + */ + public function __construct(Routing\Router $router, $base, $index, $https) + { + $this->base = $base; + $this->https = $https; + $this->index = $index; + $this->router = $router; + } + /** * Generate an application URL. * @@ -16,11 +33,11 @@ class URL { * @param bool $https * @return string */ - public static function to($url = '', $https = false) + public function to($url = '', $https = false) { if (filter_var($url, FILTER_VALIDATE_URL) !== false) return $url; - $base = Config::get('application.url').'/'.Config::get('application.index'); + $base = $this->base.'/'.$this->index; if ($https) $base = preg_replace('~http://~', 'https://', $base, 1); @@ -38,9 +55,9 @@ public static function to($url = '', $https = false) * @param string $url * @return string */ - public static function to_secure($url = '') + public function to_secure($url = '') { - return static::to($url, true); + return $this->to($url, true); } /** @@ -61,11 +78,11 @@ public static function to_secure($url = '') * @param bool $https * @return string */ - public static function to_asset($url, $https = null) + public function to_asset($url, $https = null) { - if (is_null($https)) $https = IoC::resolve('laravel.request')->is_secure(); + if (is_null($https)) $https = $this->https; - return str_replace('index.php/', '', static::to($url, $https)); + return str_replace('index.php/', '', $this->to($url, $https)); } /** @@ -89,11 +106,9 @@ public static function to_asset($url, $https = null) * @param bool $https * @return string */ - public static function to_route($name, $parameters = array(), $https = false) + public function to_route($name, $parameters = array(), $https = false) { - $router = IoC::container()->resolve('laravel.routing.router'); - - if ( ! is_null($route = $router->find($name))) + if ( ! is_null($route = $this->router->find($name))) { $uris = explode(', ', key($route)); @@ -104,7 +119,7 @@ public static function to_route($name, $parameters = array(), $https = false) $uri = preg_replace('/\(.+?\)/', $parameter, $uri, 1); } - return static::to(str_replace(array('/(:any?)', '/(:num?)'), '', $uri), $https); + return $this->to(str_replace(array('/(:any?)', '/(:num?)'), '', $uri), $https); } throw new \Exception("Error generating named route for route [$name]. Route is not defined."); @@ -122,9 +137,9 @@ public static function to_route($name, $parameters = array(), $https = false) * @param array $parameters * @return string */ - public static function to_secure_route($name, $parameters = array()) + public function to_secure_route($name, $parameters = array()) { - return static::to_route($name, $parameters, true); + return $this->to_route($name, $parameters, true); } /** @@ -169,18 +184,18 @@ public static function slug($title, $separator = '-') * $url = URL::to_profile(array('fred')); * */ - public static function __callStatic($method, $parameters) + public function __call($method, $parameters) { $parameters = (isset($parameters[0])) ? $parameters[0] : array(); if (strpos($method, 'to_secure_') === 0) { - return static::to_route(substr($method, 10), $parameters, true); + return $this->to_route(substr($method, 10), $parameters, true); } if (strpos($method, 'to_') === 0) { - return static::to_route(substr($method, 3), $parameters); + return $this->to_route(substr($method, 3), $parameters); } throw new \Exception("Method [$method] is not defined on the URL class."); diff --git a/laravel/view.php b/laravel/view.php index a2190a8e..93d0f0f1 100644 --- a/laravel/view.php +++ b/laravel/view.php @@ -1,6 +1,74 @@ path = $path; + $this->composers = $composers; + } + + /** + * Create a new view instance. + * + * @param string $view + * @param array $data + * @return View + */ + public function make($view, $data = array()) + { + return new View($view, $this->path, $data, $this->composers, $this); + } + + /** + * Create a new view instance from a view name. + * + * @param string $name + * @param array $data + * @return View + */ + protected function of($name, $data = array()) + { + foreach ($this->composers as $key => $value) + { + if ($name === $value or (isset($value['name']) and $name === $value['name'])) + { + return new View($key, $this->path, $data, $this->composers, $this); + } + } + + throw new \Exception("Named view [$name] is not defined."); + } + + /** + * Magic Method for handling the dynamic creation of named views. + * + * + * // Create an instance of the "login" named view + * $view = View::of_login(); + * + * // Create an instance of the "login" named view and bind data to the view + * $view = View::of_login(array('name' => 'Fred')); + * + */ + public function __call($method, $parameters) + { + if (strpos($method, 'of_') === 0) + { + return $this->of(substr($method, 3), Arr::get($parameters, 0, array())); + } + } + +} + +class View { /** * The name of the view. @@ -14,14 +82,28 @@ class View implements Renderable { * * @var string */ - protected $path; + public $path; /** * The view data. * * @var array */ - public $data = array(); + public $data; + + /** + * The view composers defined for the application. + * + * @var array $composers + */ + protected $composers; + + /** + * The view factory instance, which is used to create sub-views. + * + * @var View_Factory + */ + protected $factory; /** * Create a new view instance. @@ -29,12 +111,15 @@ class View implements Renderable { * @param string $view * @param array $data * @param string $path + * @param array $composers * @return void */ - public function __construct($view, $data = array(), $path = VIEW_PATH) + public function __construct($view, $path, $data, $composers, $factory) { $this->view = $view; $this->data = $data; + $this->factory = $factory; + $this->composers = $composers; $this->path = $path.str_replace('.', '/', $view).EXT; if ( ! file_exists($this->path)) @@ -43,41 +128,6 @@ public function __construct($view, $data = array(), $path = VIEW_PATH) } } - /** - * Create a new view instance. - * - * @param string $view - * @param array $data - * @param string $path - * @return View - */ - public static function make($view, $data = array(), $path = VIEW_PATH) - { - return new static($view, $data, $path); - } - - /** - * Create a new view instance from a view name. - * - * @param string $name - * @param array $data - * @return View - */ - protected static function of($name, $data = array()) - { - $composers = IoC::container()->resolve('laravel.composers'); - - foreach ($composers as $key => $value) - { - if ($name === $value or (isset($value['name']) and $name === $value['name'])) - { - return new static($key, $data); - } - } - - throw new \Exception("Named view [$name] is not defined."); - } - /** * Call the composer for the view instance. * @@ -85,11 +135,9 @@ protected static function of($name, $data = array()) */ protected function compose() { - $composers = IoC::container()->resolve('laravel.composers'); - - if (isset($composers[$this->view])) + if (isset($this->composers[$this->view])) { - foreach ((array) $composers[$this->view] as $key => $value) + foreach ((array) $this->composers[$this->view] as $key => $value) { if ($value instanceof \Closure) return call_user_func($value, $this); } @@ -110,7 +158,7 @@ public function render() foreach ($this->data as &$data) { - if ($data instanceof Renderable) $data = $data->render(); + if ($data instanceof View or $data instanceof Response) $data = $data->render(); } ob_start() and extract($this->data, EXTR_SKIP); @@ -121,7 +169,7 @@ public function render() } catch (\Exception $e) { - Exception\Handler::make(new Exception\Examiner($e, new File))->handle(); + Exception\Handler::make(new Exception\Examiner($e))->handle(); } return ob_get_clean(); @@ -145,7 +193,7 @@ public function render() */ public function partial($key, $view, $data = array()) { - return $this->with($key, new static($view, $data)); + return $this->with($key, $this->factory->make($view, $data)); } /** @@ -168,25 +216,6 @@ public function with($key, $value) return $this; } - /** - * Magic Method for handling the dynamic creation of named views. - * - * - * // Create an instance of the "login" named view - * $view = View::of_login(); - * - * // Create an instance of the "login" named view and bind data to the view - * $view = View::of_login(array('name' => 'Fred')); - * - */ - public static function __callStatic($method, $parameters) - { - if (strpos($method, 'of_') === 0) - { - return static::of(substr($method, 3), Arr::get($parameters, 0, array())); - } - } - /** * Magic Method for getting items from the view data. */ diff --git a/public/index.php b/public/index.php index e0868e92..19a2f0a5 100644 --- a/public/index.php +++ b/public/index.php @@ -36,4 +36,4 @@ | 3... 2... 1... Lift-off! |-------------------------------------------------------------------------- */ -require $laravel.'/laravel.php'; +require $laravel.'/laravel.php'; \ No newline at end of file