Commit 6cb79e66 authored by Taylor Otwell's avatar Taylor Otwell

refactoring

parent d1c5aea2
<?php
return array(
/*
|--------------------------------------------------------------------------
| Class Aliases
|--------------------------------------------------------------------------
|
| Here, you can specify any class aliases that you would like registered
| when Laravel loads. Aliases are lazy-loaded, so add as many as you want.
|
| Aliases make it more convenient to use namespaced classes. Instead of
| referring to the class using its full namespace, you may simply use
| the alias defined here.
|
| We have already aliased common Laravel classes to make your life easier.
|
*/
'Arr' => 'Laravel\\Arr',
'Asset' => 'Laravel\\Asset',
'Auth' => 'Laravel\\Security\\Auth',
'Benchmark' => 'Laravel\\Benchmark',
'Cache' => 'Laravel\\Cache',
'Config' => 'Laravel\\Config',
'Controller' => 'Laravel\\Controller',
'Cookie' => 'Laravel\\Cookie',
'Crypter' => 'Laravel\\Security\\Crypter',
'DB' => 'Laravel\\Database\\Manager',
'Eloquent' => 'Laravel\\Database\\Eloquent\\Model',
'File' => 'Laravel\\File',
'Form' => 'Laravel\\Form',
'Hasher' => 'Laravel\\Security\\Hasher',
'HTML' => 'Laravel\\HTML',
'Inflector' => 'Laravel\\Inflector',
'Input' => 'Laravel\\Input',
'IoC' => 'Laravel\\IoC',
'Lang' => 'Laravel\\Lang',
'Loader' => 'Laravel\\Loader',
'Messages' => 'Laravel\\Validation\\Messages',
'Package' => 'Laravel\\Facades\\Package',
'URI' => 'Laravel\\URI',
'URL' => 'Laravel\\URL',
'Redirect' => 'Laravel\\Redirect',
'Request' => 'Laravel\\Request',
'Response' => 'Laravel\\Response',
'Session' => 'Laravel\\Facades\\Session',
'Str' => 'Laravel\\Str',
'Validator' => 'Laravel\\Validation\\Validator',
'View' => 'Laravel\\View',
);
\ No newline at end of file
...@@ -29,39 +29,42 @@ return array( ...@@ -29,39 +29,42 @@ return array(
/* /*
|-------------------------------------------------------------------------- |--------------------------------------------------------------------------
| Application Language | Application Key
|-------------------------------------------------------------------------- |--------------------------------------------------------------------------
| |
| The default language of your application. This language will be used by | The application key should be a random, 32 character string.
| Lang library as the default language when doing string localization. |
| This key is used by the encryption and cookie classes to generate secure
| encrypted strings and hashes. It is extremely important that this key
| remain secret and should not be shared with anyone.
| |
*/ */
'language' => 'en', 'key' => '',
/* /*
|-------------------------------------------------------------------------- |--------------------------------------------------------------------------
| Application Timezone | Application Character Encoding
|-------------------------------------------------------------------------- |--------------------------------------------------------------------------
| |
| The default timezone of your application. This timezone will be used when | The default character encoding used by your application. This is the
| Laravel needs a date, such as when writing to a log file. | character encoding that will be used by the Str, Text, and Form classes.
| |
*/ */
'timezone' => 'UTC', 'encoding' => 'UTF-8',
/* /*
|-------------------------------------------------------------------------- |--------------------------------------------------------------------------
| Application Character Encoding | Application Language
|-------------------------------------------------------------------------- |--------------------------------------------------------------------------
| |
| The default character encoding used by your application. This is the | The default language of your application. This language will be used by
| character encoding that will be used by the Str, Text, and Form classes. | Lang library as the default language when doing string localization.
| |
*/ */
'encoding' => 'UTF-8', 'language' => 'en',
/* /*
|-------------------------------------------------------------------------- |--------------------------------------------------------------------------
...@@ -82,19 +85,6 @@ return array( ...@@ -82,19 +85,6 @@ return array(
'packages' => array(), 'packages' => array(),
/*
|--------------------------------------------------------------------------
| Application Key
|--------------------------------------------------------------------------
|
| Your application key should be a 32 character string that is totally
| random and secret. This key is used by the encryption class to generate
| secure, encrypted strings.
|
*/
'key' => '',
/* /*
|-------------------------------------------------------------------------- |--------------------------------------------------------------------------
| SSL Link Generation | SSL Link Generation
...@@ -112,4 +102,66 @@ return array( ...@@ -112,4 +102,66 @@ return array(
'ssl' => true, 'ssl' => true,
/*
|--------------------------------------------------------------------------
| Application Timezone
|--------------------------------------------------------------------------
|
| The default timezone of your application. This timezone will be used when
| Laravel needs a date, such as when writing to a log file.
|
*/
'timezone' => 'UTC',
/*
|--------------------------------------------------------------------------
| Class Aliases
|--------------------------------------------------------------------------
|
| Here, you can specify any class aliases that you would like registered
| when Laravel loads. Aliases are lazy-loaded, so add as many as you want.
|
| Aliases make it more convenient to use namespaced classes. Instead of
| referring to the class using its full namespace, you may simply use
| the alias defined here.
|
| We have already aliased common Laravel classes to make your life easier.
|
*/
'aliases' => array(
'Arr' => 'Laravel\\Arr',
'Asset' => 'Laravel\\Asset',
'Auth' => 'Laravel\\Security\\Auth',
'Benchmark' => 'Laravel\\Benchmark',
'Cache' => 'Laravel\\Cache',
'Config' => 'Laravel\\Config',
'Controller' => 'Laravel\\Controller',
'Cookie' => 'Laravel\\Cookie',
'Crypter' => 'Laravel\\Security\\Crypter',
'DB' => 'Laravel\\Database\\Manager',
'Eloquent' => 'Laravel\\Database\\Eloquent\\Model',
'File' => 'Laravel\\File',
'Form' => 'Laravel\\Form',
'Hasher' => 'Laravel\\Security\\Hasher',
'HTML' => 'Laravel\\HTML',
'Inflector' => 'Laravel\\Inflector',
'Input' => 'Laravel\\Input',
'IoC' => 'Laravel\\IoC',
'Lang' => 'Laravel\\Lang',
'Loader' => 'Laravel\\Loader',
'Messages' => 'Laravel\\Validation\\Messages',
'Package' => 'Laravel\\Facades\\Package',
'URI' => 'Laravel\\URI',
'URL' => 'Laravel\\URL',
'Redirect' => 'Laravel\\Redirect',
'Request' => 'Laravel\\Request',
'Response' => 'Laravel\\Response',
'Session' => 'Laravel\\Session\\Manager',
'Str' => 'Laravel\\Str',
'Validator' => 'Laravel\\Validation\\Validator',
'View' => 'Laravel\\View',
),
); );
\ No newline at end of file
...@@ -30,7 +30,7 @@ define('BLADE_EXT', '.blade.php'); ...@@ -30,7 +30,7 @@ define('BLADE_EXT', '.blade.php');
* These are typically classes that are used by the auto-loader or * These are typically classes that are used by the auto-loader or
* configuration classes, and therefore cannot be auto-loaded. * configuration classes, and therefore cannot be auto-loaded.
*/ */
require SYS_PATH.'facades'.EXT; //require SYS_PATH.'facades'.EXT;
require SYS_PATH.'config'.EXT; require SYS_PATH.'config'.EXT;
require SYS_PATH.'loader'.EXT; require SYS_PATH.'loader'.EXT;
require SYS_PATH.'arr'.EXT; require SYS_PATH.'arr'.EXT;
...@@ -51,18 +51,34 @@ if (isset($_SERVER['LARAVEL_ENV'])) ...@@ -51,18 +51,34 @@ if (isset($_SERVER['LARAVEL_ENV']))
* let them fall through the Config loader. This will allow us to * let them fall through the Config loader. This will allow us to
* load these files faster for each request. * load these files faster for each request.
*/ */
foreach (array('application', 'session', 'aliases') as $file) foreach (array('application', 'session') as $file)
{ {
$config = require CONFIG_PATH.$file.EXT; $config = require CONFIG_PATH.$file.EXT;
if (isset($_SERVER['LARAVEL_ENV'])) if (isset($_SERVER['LARAVEL_ENV']) and file_exists($path = ENV_CONFIG_PATH.$file.EXT))
{ {
$config = array_merge($config, require ENV_CONFIG_PATH.$file.EXT); $config = array_merge($config, require $path);
} }
Config::$items[$file] = $config; Config::$items[$file] = $config;
} }
/**
* Load the container configuration into the Config class. We load
* this file manually to avoid the overhead of Config::load.
*/
Config::$items['container'] = require SYS_CONFIG_PATH.'container'.EXT;
if (file_exists($path = CONFIG_PATH.'container'.EXT))
{
Config::$items['container'] = array_merge(Config::$items['container'], require $path);
}
if (isset($_SERVER['LARAVEL_ENV']) and file_exists($path = ENV_CONFIG_PATH.'container'.EXT))
{
Config::$items['container'] = array_merge(Config::$items['container'], require $path);
}
/** /**
* Bootstrap the application inversion of control (IoC) container. * Bootstrap the application inversion of control (IoC) container.
* The container provides the convenient resolution of objects and * The container provides the convenient resolution of objects and
...@@ -71,7 +87,7 @@ foreach (array('application', 'session', 'aliases') as $file) ...@@ -71,7 +87,7 @@ foreach (array('application', 'session', 'aliases') as $file)
*/ */
require SYS_PATH.'container'.EXT; require SYS_PATH.'container'.EXT;
$container = new Container(Config::get('container')); $container = new Container(Config::$items['container']);
IoC::$container = $container; IoC::$container = $container;
...@@ -82,7 +98,7 @@ IoC::$container = $container; ...@@ -82,7 +98,7 @@ IoC::$container = $container;
*/ */
spl_autoload_register(array('Laravel\\Loader', 'load')); spl_autoload_register(array('Laravel\\Loader', 'load'));
Loader::$aliases = Config::get('aliases'); Loader::$aliases = Config::$items['application']['aliases'];
/** /**
* Define a few convenient global functions. * Define a few convenient global functions.
......
...@@ -132,9 +132,6 @@ class Config { ...@@ -132,9 +132,6 @@ class Config {
} }
} }
// If configuration options were actually found, they will be loaded into the
// array containing all of the options for all files. The array is keyed by the
// configuration file name.
if (count($config) > 0) static::$items[$file] = $config; if (count($config) > 0) static::$items[$file] = $config;
return isset(static::$items[$file]); return isset(static::$items[$file]);
......
...@@ -24,7 +24,7 @@ abstract class Controller { ...@@ -24,7 +24,7 @@ abstract class Controller {
*/ */
public function filters($name) public function filters($name)
{ {
return $this->$name; return (array) $this->$name;
} }
/** /**
...@@ -47,10 +47,6 @@ abstract class Controller { ...@@ -47,10 +47,6 @@ abstract class Controller {
return $container->resolve('controllers.'.$controller); return $container->resolve('controllers.'.$controller);
} }
// If the controller was not registered in the container, we will instantiate
// an instance of the controller manually. All controllers are suffixed with
// "_Controller" to avoid namespacing. Allowing controllers to exist in the
// global namespace gives the developer a convenient API for using the framework.
$controller = str_replace(' ', '_', ucwords(str_replace('.', ' ', $controller))).'_Controller'; $controller = str_replace(' ', '_', ucwords(str_replace('.', ' ', $controller))).'_Controller';
return new $controller; return new $controller;
......
<?php namespace Laravel; <?php namespace Laravel; use Closure;
if (trim(Config::get('application.key')) === '')
{
throw new \Exception('The cookie class may not be used without an application key.');
}
class Cookie { class Cookie {
...@@ -22,7 +27,27 @@ class Cookie { ...@@ -22,7 +27,27 @@ class Cookie {
*/ */
public static function get($name, $default = null) public static function get($name, $default = null)
{ {
return Arr::get($_COOKIE, $name, $default); $value = Arr::get($_COOKIE, $name);
if ( ! is_null($value))
{
// All Laravel managed cookies are prefixed with a fingerprint hash.
// The hash serves to verify that the contents of the cookie have not
// been modified by the user. We can verify the integrity of the cookie
// by extracting the value and re-hashing it, then comparing that hash
// against the hash stored in the cookie.
if (isset($value[40]) and $value[40] === '~')
{
list($hash, $value) = explode('~', $value, 2);
if (static::hash($name, $value) === $hash)
{
return $value;
}
}
}
return ($default instanceof Closure) ? call_user_func($default) : $default;
} }
/** /**
...@@ -65,11 +90,25 @@ class Cookie { ...@@ -65,11 +90,25 @@ class Cookie {
if ($minutes < 0) unset($_COOKIE[$name]); if ($minutes < 0) unset($_COOKIE[$name]);
// Since PHP needs the cookie lifetime in seconds, we will calculate it here.
// A "0" lifetime means the cookie expires when the browser closes.
$time = ($minutes !== 0) ? time() + ($minutes * 60) : 0; $time = ($minutes !== 0) ? time() + ($minutes * 60) : 0;
return setcookie($name, $value, $time, $path, $domain, $secure, $http_only); return setcookie($name, static::hash($name, $value).'~'.$value, $time, $path, $domain, $secure, $http_only);
}
/**
* Generate a cookie hash.
*
* Cookie salts are used to verify that the contents of the cookie have not
* been modified by the user, since they serve as a fingerprint of the cookie
* contents. The application key is used to salt the salts.
*
* @param string $name
* @param string $value
* @return string
*/
protected static function hash($name, $value)
{
return sha1($name.$value.Config::get('application.key'));
} }
/** /**
......
<?php namespace Laravel\Facades;
use Laravel\IoC;
/**
* The Laravel framework makes thorough use of dependency injection assisted by an application
* inversion of control container. This allows for great flexibility, easy testing, and better
* architecture. However, most PHP framework users may be used to accessing classes through
* a variety of static methods. Laravel provides "facades" to simulate this behavior while
* still using heavy dependency injection.
*
* Each class that is commonly used by the developer has a corresponding facade defined in
* this file. All of the various facades inherit from the abstract Facade class, which only
* has a single __callStatic magic method. The facade simply resolves the requested class
* out of the IoC container and calls the appropriate method.
*/
abstract class Facade {
/**
* Magic Method for passing methods to a class registered in the IoC container.
* This provides a convenient method of accessing functions on classes that
* could not otherwise be accessed staticly.
*
* Facades allow Laravel to still have a high level of dependency injection
* and testability while still accomodating the common desire to conveniently
* use classes via static methods.
*/
public static function __callStatic($method, $parameters)
{
return call_user_func_array(array(IoC::container()->resolve(static::$resolve), $method), $parameters);
}
}
class Session extends Facade { public static $resolve = 'laravel.session'; }
\ No newline at end of file
...@@ -80,7 +80,7 @@ class Form { ...@@ -80,7 +80,7 @@ class Form {
*/ */
protected static function action($action, $https) protected static function action($action, $https)
{ {
return HTML::entities(URL::to(((is_null($action)) ? URI::get() : $action), $https)); return HTML::entities(URL::to(((is_null($action)) ? Request::uri() : $action), $https));
} }
/** /**
...@@ -157,7 +157,7 @@ class Form { ...@@ -157,7 +157,7 @@ class Form {
throw new \Exception("A session driver must be specified before using CSRF tokens."); throw new \Exception("A session driver must be specified before using CSRF tokens.");
} }
return IoC::container()->core('session')->get('csrf_token'); return Session\Manager::$payload->get('csrf_token');
} }
/** /**
......
...@@ -136,7 +136,9 @@ class Inflector { ...@@ -136,7 +136,9 @@ class Inflector {
{ {
$irregular = array_flip(static::$irregular); $irregular = array_flip(static::$irregular);
return static::$plural_cache[$value] = static::inflect($value, static::$plural_cache, $irregular, static::$plural); $plural = static::inflect($value, static::$plural_cache, $irregular, static::$plural);
return static::$plural_cache[$value] = $plural;
} }
/** /**
...@@ -147,7 +149,9 @@ class Inflector { ...@@ -147,7 +149,9 @@ class Inflector {
*/ */
public static function singular($value) public static function singular($value)
{ {
return static::$singular_cache[$value] = static::inflect($value, static::$singular_cache, static::$irregular, static::$singular); $singular = static::inflect($value, static::$singular_cache, static::$irregular, static::$singular);
return static::$singular_cache[$value] = $singular;
} }
/** /**
......
...@@ -107,9 +107,7 @@ class Input { ...@@ -107,9 +107,7 @@ class Input {
throw new \Exception('A session driver must be specified in order to access old input.'); throw new \Exception('A session driver must be specified in order to access old input.');
} }
$driver = IoC::container()->core('session'); return Arr::get(Session\Manager::$payload->get(Input::old_input, array()), $key, $default);
return Arr::get($driver->get(Input::old_input, array()), $key, $default);
} }
/** /**
......
<?php return array( <?php
/* return array(
|--------------------------------------------------------------------------
| Pagination Elements
|--------------------------------------------------------------------------
|
| These simple language lines provide the text for the Paginator class.
| Each line corresponds with an element of the pagination links generated
| by the class, and may be changed freely by the developer.
|
*/
'first' => 'First', 'first' => 'First',
'previous' => '&larr; Previous', 'previous' => '&larr; Previous',
......
...@@ -2,21 +2,10 @@ ...@@ -2,21 +2,10 @@
return array( return array(
/*
|--------------------------------------------------------------------------
| Validation Error Messages
|--------------------------------------------------------------------------
|
| These error messages will be used by the Validator class if no other
| messages are provided by the developer. They may be overriden by the
| developer in the application language directory.
|
*/
"accepted" => "The :attribute must be accepted.", "accepted" => "The :attribute must be accepted.",
"active_url" => "The :attribute is not an active URL.", "active_url" => "The :attribute is not a valid URL.",
"alpha" => "The :attribute may only contain letters.", "alpha" => "The :attribute may only contain letters.",
"alpha_dash" => "The :attribute may only contain letters, numbers, dashes, and underscores.", "alpha_dash" => "The :attribute may only contain letters, numbers, and dashes.",
"alpha_num" => "The :attribute may only contain letters and numbers.", "alpha_num" => "The :attribute may only contain letters and numbers.",
"between" => "The :attribute must be between :min - :max.", "between" => "The :attribute must be between :min - :max.",
"confirmed" => "The :attribute confirmation does not match.", "confirmed" => "The :attribute confirmation does not match.",
...@@ -34,16 +23,6 @@ return array( ...@@ -34,16 +23,6 @@ return array(
"unique" => "The :attribute has already been taken.", "unique" => "The :attribute has already been taken.",
"url" => "The :attribute format is invalid.", "url" => "The :attribute format is invalid.",
/*
|--------------------------------------------------------------------------
| Validation Units
|--------------------------------------------------------------------------
|
| The following words are appended to the "size" messages when applicable,
| such as when validating string lengths or the size of file uploads.
|
*/
"characters" => "characters", "characters" => "characters",
"kilobytes" => "kilobytes", "kilobytes" => "kilobytes",
......
...@@ -17,25 +17,24 @@ require SYS_PATH.'bootstrap/errors'.EXT; ...@@ -17,25 +17,24 @@ require SYS_PATH.'bootstrap/errors'.EXT;
/** /**
* Set the application's default timezone. * Set the application's default timezone.
*/ */
date_default_timezone_set(Config::get('application.timezone')); date_default_timezone_set(Config::$items['application']['timezone']);
/** /**
* Load the session and session manager instance. The session * Load the session and session manager instance. The session
* payload will be registered in the IoC container as an instance * payload will be registered in the IoC container as an instance
* so it can be retrieved easily throughout the application. * so it can be retrieved easily throughout the application.
*/ */
if (Config::get('session.driver') !== '') if (Config::$items['session']['driver'] !== '')
{ {
$session = $container->core('session.manager'); $session = $container->core('session.manager');
$container->instance('laravel.session', $session->payload(Config::get('session'))); Session\Manager::$payload = $session->payload(Config::$items['session']);
} }
/** /**
* Manually load some core classes that are used on every request * Manually load some core classes that are used on every request
* This allows to avoid using the loader for these classes. * This allows to avoid using the loader for these classes.
*/ */
require SYS_PATH.'uri'.EXT;
require SYS_PATH.'request'.EXT; require SYS_PATH.'request'.EXT;
require SYS_PATH.'routing/route'.EXT; require SYS_PATH.'routing/route'.EXT;
require SYS_PATH.'routing/router'.EXT; require SYS_PATH.'routing/router'.EXT;
...@@ -81,7 +80,7 @@ Input::set($input); ...@@ -81,7 +80,7 @@ Input::set($input);
* instance. If no route is found, the 404 response will be returned * instance. If no route is found, the 404 response will be returned
* to the browser. * to the browser.
*/ */
list($method, $uri) = array(Request::method(), URI::get()); list($method, $uri) = array(Request::method(), Request::uri());
$route = $container->core('routing.router')->route($method, $uri); $route = $container->core('routing.router')->route($method, $uri);
...@@ -112,7 +111,7 @@ if (isset($session)) ...@@ -112,7 +111,7 @@ if (isset($session))
{ {
$flash = array(Input::old_input => Input::get()); $flash = array(Input::old_input => Input::get());
$session->close($container->core('session'), Config::get('session'), $flash); $session->close(Session\Manager::$payload, Config::$items['session'], $flash);
} }
/** /**
......
...@@ -242,7 +242,7 @@ class Paginator { ...@@ -242,7 +242,7 @@ class Paginator {
// We will assume the page links should use HTTPS if the current request // We will assume the page links should use HTTPS if the current request
// is also using HTTPS. Since pagination links automatically point to // is also using HTTPS. Since pagination links automatically point to
// the current URI, this makes pretty good sense. // the current URI, this makes pretty good sense.
list($uri, $secure) = array(URI::get(), Request::secure()); list($uri, $secure) = array(Request::uri(), Request::secure());
return HTML::link($uri.$this->appendage($element, $page), $text, array('class' => $class), $secure); return HTML::link($uri.$this->appendage($element, $page), $text, array('class' => $class), $secure);
} }
......
...@@ -61,7 +61,7 @@ class Redirect extends Response { ...@@ -61,7 +61,7 @@ class Redirect extends Response {
throw new \Exception('A session driver must be set before setting flash data.'); throw new \Exception('A session driver must be set before setting flash data.');
} }
IoC::container()->core('session')->flash($key, $value); Session\Manager::$payload->flash($key, $value);
return $this; return $this;
} }
......
...@@ -9,6 +9,13 @@ class Request { ...@@ -9,6 +9,13 @@ class Request {
*/ */
public static $route; public static $route;
/**
* The request URI for the current request.
*
* @var string
*/
protected static $uri;
/** /**
* The request data key that is used to indicate a spoofed request method. * The request data key that is used to indicate a spoofed request method.
* *
...@@ -25,7 +32,49 @@ class Request { ...@@ -25,7 +32,49 @@ class Request {
*/ */
public static function uri() public static function uri()
{ {
return URI::get(); if ( ! is_null(static::$uri)) return static::$uri;
// Sniff the request URI out of the $_SERVER array. The PATH_IFNO
// variable contains the URI without the base URL or index page,
// so we will use that if possible, otherwise we will parse the
// URI out of the REQUEST_URI element.
if (isset($_SERVER['PATH_INFO']))
{
$uri = $_SERVER['PATH_INFO'];
}
if (isset($_SERVER['REQUEST_URI']))
{
$uri = parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH);
if ($uri === false)
{
throw new \Exception("Invalid request URI. Request terminated.");
}
}
else
{
throw new \Exception("Unable to determine the request URI.");
}
// Remove the application URL and the application index page from
// the request URI. Both of these elements will interfere with the
// routing engine and are extraneous, so they will be removed.
$base = parse_url(Config::$items['application']['url'], PHP_URL_PATH);
if (strpos($uri, $base) === 0)
{
$uri = substr($uri, strlen($base));
}
if (strpos($uri, '/index.php') === 0)
{
$uri = substr($uri, 10);
}
// Request URIs to the root of the application will be returned
// as a single forward slash. Otherwise, the request URI will be
// returned without leading or trailing slashes.
return static::$uri = (($uri = trim($uri, '/')) == '') ? '/' : $uri;
} }
/** /**
...@@ -37,7 +86,7 @@ class Request { ...@@ -37,7 +86,7 @@ class Request {
*/ */
public static function format() public static function format()
{ {
return (($extension = pathinfo(URI::get(), PATHINFO_EXTENSION)) !== '') ? $extension : 'html'; return (($extension = pathinfo(static::uri(), PATHINFO_EXTENSION)) !== '') ? $extension : 'html';
} }
/** /**
......
...@@ -123,7 +123,7 @@ class Route { ...@@ -123,7 +123,7 @@ class Route {
{ {
if (is_array($this->callback) and isset($this->callback[$name])) if (is_array($this->callback) and isset($this->callback[$name]))
{ {
return $this->callback[$name]; return (array) $this->callback[$name];
} }
return array(); return array();
......
...@@ -196,7 +196,10 @@ class Router { ...@@ -196,7 +196,10 @@ class Router {
*/ */
protected function provides($callback) protected function provides($callback)
{ {
return (is_array($callback) and isset($callback['provides'])) ? explode(', ', $callback['provides']) : null; if (is_array($callback) and isset($callback['provides']))
{
return (is_string($provides = $callback['provides'])) ? explode('|', $provides) : $provides;
}
} }
/** /**
......
<?php namespace Laravel\Security; <?php namespace Laravel\Security;
use Laravel\IoC; use Laravel\IoC;
use Laravel\Str;
use Laravel\Config; use Laravel\Config;
use Laravel\Cookie; use Laravel\Cookie;
use Laravel\Session\Payload; use Laravel\Session\Manager as Session;
class Auth { class Auth {
...@@ -41,8 +42,11 @@ class Auth { ...@@ -41,8 +42,11 @@ class Auth {
/** /**
* Get the current user of the application. * Get the current user of the application.
* *
* If the current user is not authenticated, null will be returned. This method * This method will call the "user" closure in the authentication configuration file.
* will call the "user" closure in the authentication configuration file. * If the user is not authenticated, null will be returned.
*
* If no user exists in the session, the method will check for a "remember me"
* cookie and attempt to login the user based on the value of that cookie.
* *
* <code> * <code>
* // Get the current user of the application * // Get the current user of the application
...@@ -58,11 +62,8 @@ class Auth { ...@@ -58,11 +62,8 @@ class Auth {
{ {
if ( ! is_null(static::$user)) return static::$user; if ( ! is_null(static::$user)) return static::$user;
static::$user = call_user_func(Config::get('auth.user'), IoC::container()->core('session')->get(Auth::user_key)); static::$user = call_user_func(Config::get('auth.user'), Session::$payload->get(Auth::user_key));
// If no user was returned by the closure, and a "remember me" cookie exists,
// we will attempt to login the user using the ID that is encrypted into the
// cookie value by the "remember" method.
if (is_null(static::$user) and ! is_null($cookie = Cookie::get(Auth::remember_key))) if (is_null(static::$user) and ! is_null($cookie = Cookie::get(Auth::remember_key)))
{ {
static::$user = static::recall($cookie); static::$user = static::recall($cookie);
...@@ -79,12 +80,11 @@ class Auth { ...@@ -79,12 +80,11 @@ class Auth {
*/ */
protected static function recall($cookie) protected static function recall($cookie)
{ {
// The decrypted value of the remember cookie contains the ID and username. $cookie = explode('|', Crypter::decrypt($cookie));
// We will extract them out and pass the ID to the "user" closure to attempt
// to login the user. If a user is returned, their ID will be stored in
// the session like normal and the user will be considered logged in.
$cookie = explode('|', $cookie);
// If there are not at least two elements in the array, the decrypted value
// is not valid and we wil just bail out of the method since the cookie may
// have been tampered with and should not be considered trustworthy.
if (count($cookie) < 2) return; if (count($cookie) < 2) return;
list($id, $username, $config) = array($cookie[0], $cookie[1], Config::get('auth')); list($id, $username, $config) = array($cookie[0], $cookie[1], Config::get('auth'));
...@@ -92,16 +92,16 @@ class Auth { ...@@ -92,16 +92,16 @@ class Auth {
if ( ! is_null($user = call_user_func($config['user'], $id)) and $user->{$config['username']} === $username) if ( ! is_null($user = call_user_func($config['user'], $id)) and $user->{$config['username']} === $username)
{ {
static::login($user); static::login($user);
}
return $user; return $user;
} }
}
/** /**
* Attempt to log a user into the application. * Attempt to log a user into the application.
* *
* If the given credentials are valid, the user will be logged into the application * If the given credentials are valid, the user will be logged into the application
* and their user ID will be stored in the session data. * and their user ID will be stored in the session via the "login" method.
* *
* The user may also be "remembered". When this option is set, the user will be * The user may also be "remembered". When this option is set, the user will be
* automatically logged into the application for one year via an encrypted cookie * automatically logged into the application for one year via an encrypted cookie
...@@ -119,7 +119,7 @@ class Auth { ...@@ -119,7 +119,7 @@ class Auth {
if ( ! is_null($user = call_user_func($config['attempt'], $username, $password, $config))) if ( ! is_null($user = call_user_func($config['attempt'], $username, $password, $config)))
{ {
static::login($user, $remember); static::login($user, $config, $remember);
return true; return true;
} }
...@@ -140,20 +140,21 @@ class Auth { ...@@ -140,20 +140,21 @@ class Auth {
{ {
static::$user = $user; static::$user = $user;
if ($remember) static::remember($user->id); if ($remember) static::remember($user->id, $user->{Config::get('auth.username')});
IoC::container()->core('session')->put(Auth::user_key, $user->id); Session::$payload->put(Auth::user_key, $user->id);
} }
/** /**
* Set a cookie so that users are "remembered" and don't need to login. * Set a cookie so that users are "remembered" and don't need to login.
* *
* @param string $id * @param string $id
* @param string $username
* @return void * @return void
*/ */
protected static function remember($id) protected static function remember($id, $username)
{ {
$cookie = Crypter::encrypt($id.'|'.Str::random(40)); $cookie = Crypter::encrypt($id.'|'.$username.'|'.Str::random(40));
// This method assumes the "remember me" cookie should have the same configuration // This method assumes the "remember me" cookie should have the same configuration
// as the session cookie. Since this cookie, like the session cookie, should be // as the session cookie. Since this cookie, like the session cookie, should be
...@@ -167,6 +168,8 @@ class Auth { ...@@ -167,6 +168,8 @@ class Auth {
* Log the current user out of the application. * Log the current user out of the application.
* *
* The "logout" closure in the authenciation configuration file will be called. * The "logout" closure in the authenciation configuration file will be called.
* All authentication cookies will be deleted and the user ID will be removed
* from the session.
* *
* @return void * @return void
*/ */
...@@ -180,7 +183,7 @@ class Auth { ...@@ -180,7 +183,7 @@ class Auth {
Cookie::forget(Auth::remember_key); Cookie::forget(Auth::remember_key);
IoC::container()->core('session')->forget(Auth::user_key); Session::$payload->forget(Auth::user_key);
} }
} }
\ No newline at end of file
<?php namespace Laravel\Security; <?php namespace Laravel\Security; use Laravel\Config;
use Laravel\Config;
if (trim(Config::get('application.key')) === '') if (trim(Config::get('application.key')) === '')
{ {
throw new \Exception('The encryption class may not be used without an encryption key.'); throw new \Exception('The encryption class may not be used without an application key.');
} }
class Crypter { class Crypter {
......
...@@ -28,6 +28,13 @@ class Manager { ...@@ -28,6 +28,13 @@ class Manager {
*/ */
private $exists = true; private $exists = true;
/**
* The current session payload.
*
* @var Payload
*/
public static $payload;
/** /**
* Create a new session manager instance. * Create a new session manager instance.
* *
...@@ -107,4 +114,25 @@ class Manager { ...@@ -107,4 +114,25 @@ class Manager {
} }
} }
/**
* Dynamically pass methods to the current session payload.
*
* <code>
* // Retrieve an item from the session payload
* $name = Session::get('name');
*
* // Write an item to the sessin payload
* Session::put('name', 'Taylor');
* </code>
*/
public static function __callStatic($method, $parameters)
{
if ( ! is_null(static::$payload))
{
return call_user_func_array(array(static::$payload, $method), $parameters);
}
throw new \Exception("Call to undefined method [$method] on Session class.");
}
} }
\ No newline at end of file
<?php namespace Laravel;
class URI {
/**
* The URI for the current request.
*
* This property will be set after the URI is detected for the first time.
*
* @var string
*/
protected static $uri;
/**
* Determine the 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.
*
* @return string
*/
public static function get()
{
if ( ! is_null(static::$uri)) return static::$uri;
if (($uri = static::from_server()) === false)
{
throw new \Exception('Malformed request URI. Request terminated.');
}
return static::$uri = static::format(static::clean($uri));
}
/**
* Get a given URI segment from the URI for the current request.
*
* <code>
* // Get the first URI segment for the request
* $first = URI::segment(1);
*
* // Return a default value if the URI segment doesn't exist
* $segment = URI::segment(3, 'Default');
* </code>
*
* @param int $segment
* @param mixed $default
* @return string
*/
public static function segment($segment = null, $default = null)
{
$segments = Arr::without(explode('/', static::get()), 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 static 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($_SERVER['PATH_INFO']))
{
return $_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($_SERVER['REQUEST_URI']))
{
return parse_url($_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 static function clean($uri)
{
foreach (array(parse_url(Config::get('application.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 static function format($uri)
{
return (($uri = trim($uri, '/')) == '') ? '/' : $uri;
}
}
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment