From 47db2ff19ba9694608e57a129acd3c814905effa Mon Sep 17 00:00:00 2001 From: Taylor Otwell Date: Tue, 20 Sep 2011 21:28:19 -0500 Subject: [PATCH] refactoring, added uri class. --- application/config/aliases.php | 1 + application/libraries/.gitignore | 0 changelog.md | 8 + laravel/arr.php | 6 +- laravel/cache/drivers/apc.php | 59 ++++- laravel/config/container.php | 383 +++++++++++++++---------------- laravel/core.php | 15 +- laravel/facades.php | 1 + laravel/file.php | 2 +- laravel/form.php | 2 +- laravel/loader.php | 61 ++++- laravel/request.php | 128 ++++++----- laravel/routing/loader.php | 9 - laravel/routing/route.php | 12 +- laravel/session/manager.php | 5 +- laravel/uri.php | 141 ++++++++++++ 16 files changed, 548 insertions(+), 285 deletions(-) delete mode 100644 application/libraries/.gitignore create mode 100644 laravel/uri.php diff --git a/application/config/aliases.php b/application/config/aliases.php index 58d33a60..548b80d7 100644 --- a/application/config/aliases.php +++ b/application/config/aliases.php @@ -41,6 +41,7 @@ 'Loader' => 'Laravel\\Facades\\Loader', 'Messages' => 'Laravel\\Validation\\Messages', 'Package' => 'Laravel\\Facades\\Package', + 'URI' => 'Laravel\\Facades\\URI', 'URL' => 'Laravel\\Facades\\URL', 'Redirect' => 'Laravel\\Facades\\Redirect', 'Request' => 'Laravel\\Facades\\Request', diff --git a/application/libraries/.gitignore b/application/libraries/.gitignore deleted file mode 100644 index e69de29b..00000000 diff --git a/changelog.md b/changelog.md index 66580658..19700181 100644 --- a/changelog.md +++ b/changelog.md @@ -1,5 +1,13 @@ # Laravel Change Log +## Version 1.5.9 + +- Fixed bug in Eloquent relationship loading. + +### Upgrading from 1.5.8 + +- Replace **system** directory. + ## Version 1.5.8 - Fixed bug in form class that prevent name attributes from being set properly. diff --git a/laravel/arr.php b/laravel/arr.php index af2d6407..61a0e1fb 100644 --- a/laravel/arr.php +++ b/laravel/arr.php @@ -1,5 +1,7 @@ apc = $apc; $this->key = $key; - $this->proxy = $proxy; } /** @@ -50,7 +87,7 @@ public function has($key) */ protected function retrieve($key) { - if ( ! is_null($cache = $this->proxy->apc_fetch($this->key.$key))) return $cache; + if ( ! is_null($cache = $this->apc->fetch($this->key.$key))) return $cache; } /** @@ -63,7 +100,7 @@ protected function retrieve($key) */ public function put($key, $value, $minutes) { - $this->proxy->apc_store($this->key.$key, $value, $minutes * 60); + $this->apc->store($this->key.$key, $value, $minutes * 60); } /** @@ -74,7 +111,7 @@ public function put($key, $value, $minutes) */ public function forget($key) { - $this->proxy->apc_delete($this->key.$key); + $this->apc->delete($this->key.$key); } } \ No newline at end of file diff --git a/laravel/config/container.php b/laravel/config/container.php index cc179d80..754f649d 100644 --- a/laravel/config/container.php +++ b/laravel/config/container.php @@ -4,23 +4,23 @@ /* |-------------------------------------------------------------------------- - | Laravel Components + | Core Laravel Components |-------------------------------------------------------------------------- */ - 'laravel.asset' => array('singleton' => true, 'resolver' => function($container) + 'laravel.asset' => array('singleton' => true, 'resolver' => function($c) { - return new Asset($container->resolve('laravel.html')); + return new Asset($c->resolve('laravel.html')); }), - 'laravel.auth' => array('singleton' => true, 'resolver' => function($container) + 'laravel.auth' => array('singleton' => true, 'resolver' => function($c) { - return new Security\Auth($container->resolve('laravel.config'), $container->resolve('laravel.session')); + return new Security\Auth($c->resolve('laravel.config'), $c->resolve('laravel.session')); }), - 'laravel.config' => array('singleton' => true, 'resolver' => function($container) + 'laravel.config' => array('singleton' => true, 'resolver' => function($c) { $paths = array(SYS_CONFIG_PATH, CONFIG_PATH); @@ -33,11 +33,9 @@ }), - 'laravel.crypter' => array('resolver' => function($container) + 'laravel.crypter' => array('resolver' => function($c) { - $key = $container->resolve('laravel.config')->get('application.key'); - - return new Security\Crypter(MCRYPT_RIJNDAEL_256, 'cbc', $key); + return new Security\Crypter(MCRYPT_RIJNDAEL_256, 'cbc', $c->resolve('laravel.config')->get('application.key')); }), @@ -47,132 +45,244 @@ }), - 'laravel.database' => array('singleton' => true, 'resolver' => function($container) + 'laravel.database' => array('singleton' => true, 'resolver' => function($c) { - return new Database\Manager($container->resolve('laravel.config')); + return new Database\Manager($c->resolve('laravel.config')); }), - 'laravel.download' => array('singleton' => true, 'resolver' => function($container) + 'laravel.download' => array('singleton' => true, 'resolver' => function($c) { - return new Download($container->resolve('laravel.file')); + return new Download($c->resolve('laravel.file')); }), - 'laravel.file' => array('singleton' => true, 'resolver' => function($container) + 'laravel.file' => array('singleton' => true, 'resolver' => function($c) { - return new File($container->resolve('laravel.config')->get('mimes')); + return new File($c->resolve('laravel.config')->get('mimes')); }), - 'laravel.form' => array('singleton' => true, 'resolver' => function($container) + 'laravel.form' => array('singleton' => true, 'resolver' => function($c) { - list($request, $html, $url) = array( - $container->resolve('laravel.request'), - $container->resolve('laravel.html'), - $container->resolve('laravel.url'), - ); - - return new Form($request, $html, $url); + return new Form($c->resolve('laravel.request'), $c->resolve('laravel.html'), $c->resolve('laravel.url')); }), - 'laravel.hasher' => array('singleton' => true, 'resolver' => function($container) + 'laravel.hasher' => array('singleton' => true, 'resolver' => function($c) { return new Security\Hashing\Bcrypt(8, false); }), - 'laravel.html' => array('singleton' => true, 'resolver' => function($container) + 'laravel.html' => array('singleton' => true, 'resolver' => function($c) { - return new HTML($container->resolve('laravel.url'), $container->resolve('laravel.config')->get('application.encoding')); + return new HTML($c->resolve('laravel.url'), $c->resolve('laravel.config')->get('application.encoding')); }), - 'laravel.input' => array('singleton' => true, 'resolver' => function($container) + 'laravel.input' => array('singleton' => true, 'resolver' => function($c) { - $request = $container->resolve('laravel.request'); + list($file, $cookie, $input, $files) = array( + $c->resolve('laravel.file'), + $c->resolve('laravel.cookie'), + $c->resolve('laravel.input.array'), + $_FILES, + ); + return new Input($file, $cookie, $input, $files); + }), + + + 'laravel.input.array' => array('singleton' => true, 'resolver' => function($c) + { $input = array(); - if ($request->method() == 'GET') + switch ($c->resolve('laravel.request')->method()) { - $input = $_GET; - } - elseif ($request->method() == 'POST') - { - $input = $_POST; - } - elseif ($request->method() == 'PUT' or $request->method == 'DELETE') - { - ($request->spoofed()) ? $input = $_POST : parse_str(file_get_contents('php://input'), $input); + case 'GET': + $input = $_GET; + break; + + case 'POST': + $input = $_POST; + break; + + case 'PUT': + case 'DELETE': + if ($c->resolve('laravel.request')->spoofed()) + { + $input = $_POST; + } + else + { + parse_str(file_get_contents('php://input'), $input); + } } - unset($input['_REQUEST_METHOD']); + unset($input[Request::spoofer]); - return new Input($container->resolve('laravel.file'), $container->resolve('laravel.cookie'), $input, $_FILES); + return $input; }), - 'laravel.lang' => array('singleton' => true, 'resolver' => function($container) + 'laravel.lang' => array('singleton' => true, 'resolver' => function($c) { require_once SYS_PATH.'lang'.EXT; - return new Lang_Factory($container->resolve('laravel.config'), array(SYS_LANG_PATH, LANG_PATH)); + return new Lang_Factory($c->resolve('laravel.config'), array(SYS_LANG_PATH, LANG_PATH)); }), - 'laravel.loader' => array('singleton' => true, 'resolver' => function($container) + 'laravel.loader' => array('singleton' => true, 'resolver' => function($c) { require_once SYS_PATH.'loader'.EXT; - $aliases = $container->resolve('laravel.config')->get('aliases'); + $aliases = $c->resolve('laravel.config')->get('aliases'); - return new Loader(array(BASE_PATH, APP_PATH.'models/', APP_PATH.'libraries/'), $aliases); + return new Loader(array(BASE_PATH, APP_PATH.'models/', APP_PATH), $aliases); }), - 'laravel.package' => array('singleton' => true, 'resolver' => function() + 'laravel.redirect' => array('singleton' => true, 'resolver' => function($c) { - return new Package(PACKAGE_PATH); + return new Redirect($c->resolve('laravel.url')); }), - 'laravel.redirect' => array('singleton' => true, 'resolver' => function($container) + 'laravel.request' => array('singleton' => true, 'resolver' => function($c) { - return new Redirect($container->resolve('laravel.url')); + return new Request($c->resolve('laravel.uri')->get(), $_SERVER, $_POST); }), - 'laravel.request' => array('singleton' => true, 'resolver' => function($container) - { - return new Request($_SERVER, $_POST, $container->resolve('laravel.config')->get('application.url')); - }), - - - 'laravel.response' => array('singleton' => true, 'resolver' => function($container) + 'laravel.response' => array('singleton' => true, 'resolver' => function($c) { require_once SYS_PATH.'response'.EXT; - return new Response_Factory($container->resolve('laravel.view'), $container->resolve('laravel.file')); + return new Response_Factory($c->resolve('laravel.view'), $c->resolve('laravel.file')); }), + 'laravel.uri' => array('singleton' => true, 'resolver' => function($c) + { + return new URI($_SERVER, $c->resolve('laravel.config')->get('application.url')); + }), + + + 'laravel.url' => array('singleton' => true, 'resolver' => function($c) + { + list($router, $request, $base, $index) = array( + $c->resolve('laravel.routing.router'), + $c->resolve('laravel.request'), + $c->resolve('laravel.config')->get('application.url'), + $c->resolve('laravel.config')->get('application.index'), + ); + + return new URL($router, $base, $index, $request->secure()); + }), + + + 'laravel.validator' => array('singleton' => true, 'resolver' => function($c) + { + require_once SYS_PATH.'validation/validator'.EXT; + + return new Validation\Validator_Factory($c->resolve('laravel.lang')); + }), + + + 'laravel.view' => array('singleton' => true, 'resolver' => function($c) + { + require_once SYS_PATH.'view'.EXT; + + return new View_Factory(new View_Composer(require APP_PATH.'composers'.EXT), VIEW_PATH); + }), + + /* + |-------------------------------------------------------------------------- + | Laravel Routing Components + |-------------------------------------------------------------------------- + */ + 'laravel.routing.router' => array('singleton' => true, 'resolver' => function($c) { return new Routing\Router($c->resolve('laravel.routing.loader'), CONTROLLER_PATH); }), - 'laravel.routing.loader' => array('singleton' => true, 'resolver' => function($container) + 'laravel.routing.loader' => array('singleton' => true, 'resolver' => function($c) { return new Routing\Loader(APP_PATH, ROUTE_PATH); }), - 'laravel.routing.caller' => array('resolver' => function($container) + 'laravel.routing.caller' => array('resolver' => function($c) { - return new Routing\Caller($container, require APP_PATH.'filters'.EXT, CONTROLLER_PATH); + return new Routing\Caller($c, require APP_PATH.'filters'.EXT, CONTROLLER_PATH); + }), + + /* + |-------------------------------------------------------------------------- + | Laravel Caching Components + |-------------------------------------------------------------------------- + */ + + 'laravel.cache' => array('singleton' => true, 'resolver' => function($c) + { + return new Cache\Manager($c, $c->resolve('laravel.config')->get('cache.driver')); + }), + + + 'laravel.cache.apc' => array('resolver' => function($c) + { + require_once SYS_PATH.'cache/drivers/apc'.EXT; + + $key = $c->resolve('laravel.config')->get('cache.key'); + + return new Cache\Drivers\APC(new Cache\Drivers\APC_Engine, $key); + }), + + + 'laravel.cache.file' => array('resolver' => function($c) + { + return new Cache\Drivers\File($c->resolve('laravel.file'), CACHE_PATH); + }), + + + 'laravel.cache.memcached' => array('resolver' => function($c) + { + $key = $c->resolve('laravel.config')->get('cache.key'); + + return new Cache\Drivers\Memcached($c->resolve('laravel.cache.memcache.connection'), $key); + }), + + + 'laravel.cache.memcache.connection' => array('singleton' => true, 'resolver' => function($c) + { + $memcache = new \Memcache; + + foreach ($c->resolve('laravel.config')->get('cache.servers') as $server) + { + $memcache->addServer($server['host'], $server['port'], true, $server['weight']); + } + + if ($memcache->getVersion() === false) + { + throw new \Exception('Could not establish memcached connection. Please verify your memcached configuration.'); + } + + return $memcache; + }), + + /* + |-------------------------------------------------------------------------- + | Laravel Session Components + |-------------------------------------------------------------------------- + */ + + 'laravel.session.id' => array('singleton' => true, 'resolver' => function($c) + { + return $c->resolve('laravel.cookie')->get('laravel_session'); }), @@ -192,164 +302,35 @@ }), - 'laravel.url' => array('singleton' => true, 'resolver' => function($container) + 'laravel.session.apc' => array('resolver' => function($c) { - list($request, $base, $index) = array( - $container->resolve('laravel.request'), - $container->resolve('laravel.config')->get('application.url'), - $container->resolve('laravel.config')->get('application.index'), - ); - - return new URL($container->resolve('laravel.routing.router'), $base, $index, $request->secure()); + return new Session\Drivers\APC($c->resolve('laravel.cache.apc')); }), - 'laravel.validator' => array('singleton' => true, 'resolver' => function($container) + 'laravel.session.cookie' => array('resolver' => function($c) { - require_once SYS_PATH.'validation/validator'.EXT; + $cookies = $c->resolve('laravel.cookie'); - return new Validation\Validator_Factory($container->resolve('laravel.lang')); + return new Session\Drivers\Cookie($c->resolve('laravel.crypter'), $cookies); }), - 'laravel.view' => array('singleton' => true, 'resolver' => function($container) + 'laravel.session.database' => array('resolver' => function($c) { - require_once SYS_PATH.'view'.EXT; - - return new View_Factory($container->resolve('laravel.view.composer'), VIEW_PATH); + return new Session\Drivers\Database($c->resolve('laravel.database')->connection()); }), - 'laravel.view.composer' => array('resolver' => function($container) + 'laravel.session.file' => array('resolver' => function($c) { - return new View_Composer(require APP_PATH.'composers'.EXT); - }), - - /* - |-------------------------------------------------------------------------- - | Laravel Cookie Session Components - |-------------------------------------------------------------------------- - */ - - 'laravel.session.cookie' => array('resolver' => function($container) - { - $cookies = $container->resolve('laravel.cookie'); - - $config = $container->resolve('laravel.config')->get('session'); - - return new Session\Drivers\Cookie($container->resolve('laravel.crypter'), $cookies); - }), - - /* - |-------------------------------------------------------------------------- - | Laravel Database Session Components - |-------------------------------------------------------------------------- - */ - - 'laravel.session.database' => array('resolver' => function($container) - { - $table = $container->resolve('laravel.config')->get('session.table'); - - return new Session\Drivers\Database($container->resolve('laravel.database')->connection()); - }), - - /* - |-------------------------------------------------------------------------- - | Laravel Cache Manager - |-------------------------------------------------------------------------- - */ - - 'laravel.cache' => array('singleton' => true, 'resolver' => function($container) - { - return new Cache\Manager($container, $container->resolve('laravel.config')->get('cache.driver')); - }), - - /* - |-------------------------------------------------------------------------- - | Laravel File Cache & Session Components - |-------------------------------------------------------------------------- - */ - - 'laravel.cache.file' => array('resolver' => function($container) - { - return new Cache\Drivers\File($container->resolve('laravel.file'), CACHE_PATH); + return new Session\Drivers\File($c->resolve('laravel.file'), SESSION_PATH); }), - 'laravel.session.file' => array('resolver' => function($container) + 'laravel.session.memcached' => array('resolver' => function($c) { - return new Session\Drivers\File($container->resolve('laravel.file'), SESSION_PATH); - }), - - /* - |-------------------------------------------------------------------------- - | Laravel APC Cache & Session Components - |-------------------------------------------------------------------------- - */ - - 'laravel.cache.apc' => array('resolver' => function($container) - { - return new Cache\Drivers\APC(new Proxy, $container->resolve('laravel.config')->get('cache.key')); - }), - - - 'laravel.session.id' => array('singleton' => true, 'resolver' => function($container) - { - return $container->resolve('laravel.cookie')->get('laravel_session'); - }), - - - 'laravel.session.apc' => array('resolver' => function($container) - { - $lifetime = $container->resolve('laravel.config')->get('session.lifetime'); - - return new Session\Drivers\APC($container->resolve('laravel.cache.apc')); - }), - - /* - |-------------------------------------------------------------------------- - | Laravel Memcached Cache & Session Components - |-------------------------------------------------------------------------- - */ - - 'laravel.cache.memcached' => array('resolver' => function($container) - { - $connection = $container->resolve('laravel.cache.memcache.connection'); - - $key = $container->resolve('laravel.config')->get('cache.key'); - - return new Cache\Drivers\Memcached($connection, $key); - }), - - - 'laravel.session.memcached' => array('resolver' => function($container) - { - $lifetime = $container->resolve('laravel.config')->get('session.lifetime'); - - return new Session\Drivers\Memcached($container->resolve('laravel.cache.memcached')); - }), - - - 'laravel.cache.memcache.connection' => array('singleton' => true, 'resolver' => function($container) - { - if ( ! class_exists('Memcache')) - { - throw new \Exception('Attempting to use Memcached, but the Memcache PHP extension is not installed on this server.'); - } - - $memcache = new \Memcache; - - foreach ($container->resolve('laravel.config')->get('cache.servers') as $server) - { - $memcache->addServer($server['host'], $server['port'], true, $server['weight']); - } - - if ($memcache->getVersion() === false) - { - throw new \Exception('Memcached is configured. However, no connections could be made. Please verify your memcached configuration.'); - } - - return $memcache; + return new Session\Drivers\Memcached($c->resolve('laravel.cache.memcached')); }), ); \ No newline at end of file diff --git a/laravel/core.php b/laravel/core.php index 7962a561..f79fdd4d 100644 --- a/laravel/core.php +++ b/laravel/core.php @@ -69,4 +69,17 @@ // -------------------------------------------------------------- // Set the application environment configuration option. // -------------------------------------------------------------- -$container->resolve('laravel.config')->set('application.env', $env); \ No newline at end of file +$container->resolve('laravel.config')->set('application.env', $env); + +// -------------------------------------------------------------- +// Define some convenient global functions. +// -------------------------------------------------------------- +function e($value) +{ + return IoC::container()->resolve('laravel.html')->entities($value); +} + +function __($key, $replacements = array(), $language = null) +{ + return IoC::container()->resolve('laravel.lang')->line($key, $replacements, $language); +} \ No newline at end of file diff --git a/laravel/facades.php b/laravel/facades.php index 80901b11..1ba4a6b3 100644 --- a/laravel/facades.php +++ b/laravel/facades.php @@ -52,6 +52,7 @@ class Redirect extends Facade { public static $resolve = 'laravel.redirect'; } class Request extends Facade { public static $resolve = 'laravel.request'; } class Response extends Facade { public static $resolve = 'laravel.response'; } class Session extends Facade { public static $resolve = 'laravel.session'; } +class URI extends Facade { public static $resolve = 'laravel.uri'; } class URL extends Facade { public static $resolve = 'laravel.url'; } class Validator extends Facade { public static $resolve = 'laravel.validator'; } class View extends Facade { public static $resolve = 'laravel.view'; } \ No newline at end of file diff --git a/laravel/file.php b/laravel/file.php index 06afeef7..72095804 100644 --- a/laravel/file.php +++ b/laravel/file.php @@ -79,7 +79,7 @@ public function append($path, $data) */ public function delete($path) { - @unlink($path); + if ($this->exists($path)) @unlink($path); } /** diff --git a/laravel/form.php b/laravel/form.php index 1082b7f5..63695f47 100644 --- a/laravel/form.php +++ b/laravel/form.php @@ -81,7 +81,7 @@ public function open($action = null, $method = 'POST', $attributes = array(), $h $attributes['accept-charset'] = $this->html->encoding; } - $append = ($method == 'PUT' or $method == 'DELETE') ? $this->hidden('_REQUEST_METHOD', $method) : ''; + $append = ($method == 'PUT' or $method == 'DELETE') ? $this->hidden(Request::spoofer, $method) : ''; return 'html->attributes($attributes).'>'.$append.PHP_EOL; } diff --git a/laravel/loader.php b/laravel/loader.php index b6586d45..96e27d15 100644 --- a/laravel/loader.php +++ b/laravel/loader.php @@ -7,14 +7,14 @@ class Loader { * * @var array */ - public $paths; + protected $paths; /** * The class aliases defined for the application. * * @var array */ - public $aliases; + protected $aliases; /** * Create a new class loader instance. @@ -37,8 +37,12 @@ public function __construct($paths, $aliases) */ public function load($class) { + // All Laravel core classes follow a namespace to directory convention. So, we will + // replace all of the namespace slashes with directory slashes. $file = strtolower(str_replace('\\', '/', $class)); + // First, we'll check to determine if an alias exists. If it does, we will define the + // alias and bail out. Aliases are defined for most developer used core classes. if (array_key_exists($class, $this->aliases)) return class_alias($this->aliases[$class], $class); foreach ($this->paths as $path) @@ -52,4 +56,57 @@ public function load($class) } } + /** + * Register a class alias with the auto-loader. + * + * Note: Aliases are lazy-loaded, so the aliased class will not be included until it is needed. + * + * + * // Register an alias for the "SwiftMailer\Transport" class + * Loader::alias('Transport', 'SwiftMailer\\Transport'); + * + * + * @param string $alias + * @param string $class + * @return void + */ + public function alias($alias, $class) + { + $this->aliases[$alias] = $class; + } + + /** + * Register a path with the auto-loader. + * + * The registered path will be searched when auto-loading classes. + * + * + * // Register a path to be searched by the auto-loader + * Loader::path('path/to/files'); + * + * + * @param string $path + * @return void + */ + public function path($path) + { + $this->paths[] = rtrim($path, '/').'/'; + } + + /** + * Remove an alias from the auto-loader's alias registrations. + * + * + * // Remove the "Transport" alias from the registered aliases + * Loader::forget_alias('Transport'); + * + * + * @param string $alias + * @return void + */ + public function forget_alias($alias) + { + unset($this->aliases[$alias]); + } + } \ No newline at end of file diff --git a/laravel/request.php b/laravel/request.php index 9d99a3f3..d431f033 100644 --- a/laravel/request.php +++ b/laravel/request.php @@ -2,12 +2,19 @@ class Request { + /** + * The URI for the current request. + * + * @var string + */ + protected $uri; + /** * The $_SERVER array for the request. * * @var array */ - public $server; + protected $server; /** * The $_POST array for the request. @@ -16,23 +23,6 @@ class Request { */ protected $post; - /** - * The base URL of the application. - * - * @var string - */ - protected $url; - - /** - * The request URI. - * - * After determining the URI once, this property will be set and returned - * on subsequent requests for the URI. - * - * @var string - */ - protected $uri; - /** * The route handling the current request. * @@ -40,17 +30,24 @@ class Request { */ public $route; + /** + * The request data key that is used to indicate the spoofed request method. + * + * @var string + */ + const spoofer = '__spoofer'; + /** * Create a new request instance. * + * @param string $uri * @param array $server * @param array $post - * @param string $url * @return void */ - public function __construct($server, $post, $url) + public function __construct($uri, $server, $post) { - $this->url = $url; + $this->uri = $uri; $this->post = $post; $this->server = $server; } @@ -69,32 +66,7 @@ public function __construct($server, $post, $url) */ public function uri() { - if ( ! is_null($this->uri)) return $this->uri; - - if (isset($this->server['PATH_INFO'])) - { - $uri = $this->server['PATH_INFO']; - } - elseif (isset($this->server['REQUEST_URI'])) - { - $uri = parse_url($this->server['REQUEST_URI'], PHP_URL_PATH); - } - else - { - throw new \Exception('Unable to determine the request URI.'); - } - - if ($uri === false) - { - throw new \Exception('Malformed request URI. Request terminated.'); - } - - foreach (array(parse_url($this->url, PHP_URL_PATH), '/index.php') as $value) - { - $uri = (strpos($uri, $value) === 0) ? substr($uri, strlen($value)) : $uri; - } - - return $this->uri = (($uri = trim($uri, '/')) == '') ? '/' : $uri; + return $this->uri; } /** @@ -102,6 +74,14 @@ public function uri() * * The format is determined by essentially taking the "extension" of the URI. * + * + * // Returns "html" for a request to "/user/profile" + * $format = Request::format(); + * + * // Returns "json" for a request to "/user/profile.json" + * $format = Request::format(); + * + * * @return string */ public function format() @@ -120,27 +100,62 @@ public function format() */ public function method() { - return ($this->spoofed()) ? $this->post['_REQUEST_METHOD'] : $this->server['REQUEST_METHOD']; + return ($this->spoofed()) ? $this->post[Request::spoofer] : $this->server['REQUEST_METHOD']; + } + + /** + * Get an item from the $_SERVER array. + * + * Like most array retrieval methods, a default value may be specified. + * + * + * // Get an item from the $_SERVER array + * $value = Request::server('http_x_requested_for'); + * + * // Get an item from the $_SERVER array or return a default value + * $value = Request::server('http_x_requested_for', '127.0.0.1'); + * + * + * @param string $key + * @param mixed $default + * @return string + */ + public function server($key = null, $default = null) + { + return Arr::get($this->server, strtoupper($key), $default); } /** * Determine if the request method is being spoofed by a hidden Form element. * - * Hidden elements are used to spoof PUT and DELETE requests since they are not supported by HTML forms. + * Hidden elements are used to spoof PUT and DELETE requests since they are not supported + * by HTML forms. If the request is being spoofed, Laravel considers the spoofed request + * method the actual request method throughout the framework. * * @return bool */ public function spoofed() { - return is_array($this->post) and array_key_exists('REQUEST_METHOD', $this->post); + return is_array($this->post) and array_key_exists(Request::spoofer, $this->post); } /** * Get the requestor's IP address. * + * A default may be passed and will be returned in the event the IP can't be determined + * + * + * // Get the requestor's IP address + * $ip = Request::ip(); + * + * // Get the requestor's IP address or return a default value + * $ip = Request::ip('127.0.0.1'); + * + * + * @param mixed $default * @return string */ - public function ip() + public function ip($default = '0.0.0.0') { if (isset($this->server['HTTP_X_FORWARDED_FOR'])) { @@ -154,11 +169,16 @@ public function ip() { return $this->server['REMOTE_ADDR']; } + + return ($default instanceof \Closure) ? call_user_func($default) : $default; } /** * Get the HTTP protocol for the request. * + * This method will return either "https" or "http", depending on whether HTTPS + * is being used for the current request. + * * @return string */ public function protocol() @@ -167,17 +187,17 @@ public function protocol() } /** - * Determine if the request is using HTTPS. + * Determine if the current request is using HTTPS. * * @return bool */ public function secure() { - return ($this->protocol() == 'https'); + return $this->protocol() == 'https'; } /** - * Determine if the request is an AJAX request. + * Determine if the current request is an AJAX request. * * @return bool */ diff --git a/laravel/routing/loader.php b/laravel/routing/loader.php index c10a351b..d52f760c 100644 --- a/laravel/routing/loader.php +++ b/laravel/routing/loader.php @@ -72,14 +72,6 @@ protected function nested($segments) { return require $path; } - - // Even if we didn't find a matching file for the segment, we still want to - // check for a "routes.php" file which could handle the root route and any - // routes that are impossible to handle in an explicitly named file. - if (file_exists($path = str_replace('.php', '/routes.php', $path))) - { - return require $path; - } } return array(); @@ -99,7 +91,6 @@ public function everything() $routes = array(); - // First we will check for the base routes file in the application directory. if (file_exists($path = $this->base.'routes'.EXT)) { $routes = array_merge($routes, require $path); diff --git a/laravel/routing/route.php b/laravel/routing/route.php index 149a87bc..b724cce9 100644 --- a/laravel/routing/route.php +++ b/laravel/routing/route.php @@ -99,7 +99,10 @@ public function call() // route is delegating the responsibility for handling the request to a controller. elseif (is_array($this->callback)) { - $callback = Arr::first($this->callback, function($key, $value) {return $key == 'delegate' or $value instanceof Closure;}); + $callback = Arr::first($this->callback, function($key, $value) + { + return $key == 'delegate' or $value instanceof Closure; + }); return ($callback instanceof Closure) ? call_user_func_array($callback, $this->parameters) : new Delegate($callback); } @@ -121,7 +124,12 @@ public function call() */ public function filters($name) { - return (is_array($this->callback) and isset($this->callback[$name])) ? explode(', ', $this->callback[$name]) : array(); + if (is_array($this->callback) and isset($this->callback[$name])) + { + return explode(', ', $this->callback[$name]); + } + + return array(); } /** diff --git a/laravel/session/manager.php b/laravel/session/manager.php index 3c1b2db0..5b78f22b 100644 --- a/laravel/session/manager.php +++ b/laravel/session/manager.php @@ -65,7 +65,10 @@ public function payload($config) // are generated per session to protect against Cross-Site Request Forgery attacks on // the application. It is up to the developer to take advantage of them using the token // methods on the Form class and the "csrf" route filter. - if ( ! $payload->has('csrf_token')) $payload->put('csrf_token', Str::random(16)); + if ( ! $payload->has('csrf_token')) + { + $payload->put('csrf_token', Str::random(16)); + } return $payload; } diff --git a/laravel/uri.php b/laravel/uri.php new file mode 100644 index 00000000..6ec82420 --- /dev/null +++ b/laravel/uri.php @@ -0,0 +1,141 @@ +url = $url; + $this->server = $server; + } + + /** + * Get the URI for the current request. + * + * @return string + */ + public function get() + { + if ( ! is_null($this->uri)) return $this->uri; + + if (($uri = $this->from_server()) === false) + { + throw new \Exception('Malformed request URI. Request terminated.'); + } + + return $this->uri = $this->format($this->clean($uri)); + } + + /** + * Get a given URI segment from the URI for the current request. + * + * + * // Get the first segment from the request URI + * $first = Request::uri()->segment(1); + * + * // Get the second segment or return a default value if it doesn't exist + * $second = Request::uri()->segment(2, 'Taylor'); + * + * // Get all of the segments for the request URI + * $segments = Request::uri()->segment(); + * + * + * @param int $segment + * @param mixed $default + * @return string + */ + public function segment($segment = null, $default = null) + { + $segments = Arr::without(explode('/', $this->detect()), array('')); + + if ( ! is_null($segment)) $segment = $segment - 1; + + return Arr::get($segments, $segment, $default); + } + + /** + * Get the request URI from the $_SERVER array. + * + * @return string + */ + protected function from_server() + { + // If the PATH_INFO $_SERVER element is set, we will use since it contains + // the request URI formatted perfectly for Laravel's routing engine. + if (isset($this->server['PATH_INFO'])) + { + return $this->server['PATH_INFO']; + } + + // If the REQUEST_URI is set, we need to extract the URL path since this + // should return the URI formatted in a manner similar to PATH_INFO. + elseif (isset($this->server['REQUEST_URI'])) + { + return parse_url($this->server['REQUEST_URI'], PHP_URL_PATH); + } + + throw new \Exception('Unable to determine the request URI.'); + } + + /** + * Remove extraneous segments from the URI such as the URL and index page. + * + * These segments need to be removed since they will cause problems in the + * routing engine if they are present in the URI. + * + * @param string $uri + * @return string + */ + protected function clean($uri) + { + foreach (array(parse_url($this->url, PHP_URL_PATH), '/index.php') as $value) + { + $uri = (strpos($uri, $value) === 0) ? substr($uri, strlen($value)) : $uri; + } + + return $uri; + } + + /** + * Format the URI. + * + * If the request URI is empty, a single forward slash will be returned. + * + * @param string $uri + * @return string + */ + protected function format($uri) + { + return (($uri = trim($uri, '/')) == '') ? '/' : $uri; + } + +} \ No newline at end of file