From 6048d20921116e8c2ff5664c6458abe9c2836c5b Mon Sep 17 00:00:00 2001 From: Taylor Otwell Date: Tue, 1 Nov 2011 23:11:08 -0500 Subject: [PATCH] refactoring the session class. --- application/config/application.php | 4 +- application/config/session.php | 2 +- laravel/bootstrap/core.php | 1 - laravel/config/container.php | 6 - laravel/facades.php | 4 +- laravel/form.php | 2 +- laravel/input.php | 6 +- laravel/laravel.php | 16 +- laravel/redirect.php | 2 +- laravel/security/auth.php | 2 +- laravel/session.php | 258 +++++++++++++++++++++++++++++ laravel/session/payload.php | 101 ++++++----- 12 files changed, 317 insertions(+), 87 deletions(-) create mode 100644 laravel/session.php diff --git a/application/config/application.php b/application/config/application.php index e7c9b9ba..9611d1d3 100644 --- a/application/config/application.php +++ b/application/config/application.php @@ -40,7 +40,7 @@ | */ - 'key' => '', + 'key' => 'SomethingElse', /* |-------------------------------------------------------------------------- @@ -135,7 +135,7 @@ 'Redis' => 'Laravel\\Redis', 'Request' => 'Laravel\\Request', 'Response' => 'Laravel\\Response', - 'Session' => 'Laravel\\Facades\\Session', + 'Session' => 'Laravel\\Session', 'Str' => 'Laravel\\Str', 'Validator' => 'Laravel\\Validation\\Validator', 'View' => 'Laravel\\View', diff --git a/application/config/session.php b/application/config/session.php index c72a3dd4..790b284b 100644 --- a/application/config/session.php +++ b/application/config/session.php @@ -16,7 +16,7 @@ | */ - 'driver' => '', + 'driver' => 'apc', /* |-------------------------------------------------------------------------- diff --git a/laravel/bootstrap/core.php b/laravel/bootstrap/core.php index 0af85bbd..64823780 100644 --- a/laravel/bootstrap/core.php +++ b/laravel/bootstrap/core.php @@ -51,7 +51,6 @@ */ require SYS_PATH.'arr'.EXT; require SYS_PATH.'config'.EXT; -require SYS_PATH.'facades'.EXT; require SYS_PATH.'container'.EXT; require SYS_PATH.'autoloader'.EXT; diff --git a/laravel/config/container.php b/laravel/config/container.php index f1d405d3..983d6980 100644 --- a/laravel/config/container.php +++ b/laravel/config/container.php @@ -2,12 +2,6 @@ return array( - 'laravel.autoloader' => array('singleton' => true, 'resolver' => function($c) - { - return new Autoloader(Config::$items['application']['aliases']); - }), - - 'laravel.routing.router' => array('singleton' => true, 'resolver' => function($c) { return new Routing\Router($c->core('routing.loader'), CONTROLLER_PATH); diff --git a/laravel/facades.php b/laravel/facades.php index 4f7d2cbb..5ccfa889 100644 --- a/laravel/facades.php +++ b/laravel/facades.php @@ -57,6 +57,4 @@ public static function __callStatic($method, $parameters) } } -} - -class Session extends Facade { public static $resolve = 'laravel.session'; } \ No newline at end of file +} \ No newline at end of file diff --git a/laravel/form.php b/laravel/form.php index b02ae842..18868e84 100644 --- a/laravel/form.php +++ b/laravel/form.php @@ -159,7 +159,7 @@ public static function raw_token() throw new \Exception("A session driver must be specified before using CSRF tokens."); } - return IoC::container()->core('session')->get('csrf_token'); + return Session::get('csrf_token'); } /** diff --git a/laravel/input.php b/laravel/input.php index 92980482..95e88223 100644 --- a/laravel/input.php +++ b/laravel/input.php @@ -70,7 +70,7 @@ public static function get($key = null, $default = null) */ public static function flash() { - IoC::container()->core('session')->flash(Input::old_input, static::get()); + Session::flash(Input::old_input, static::get()); } /** @@ -106,9 +106,7 @@ public static function old($key = null, $default = null) throw new \Exception('A session driver must be specified in order to access old input.'); } - $session = IoC::container()->core('session'); - - return Arr::get($session->get(Input::old_input, array()), $key, $default); + return Arr::get(Session::get(Input::old_input, array()), $key, $default); } /** diff --git a/laravel/laravel.php b/laravel/laravel.php index 495e2a14..6dca887e 100644 --- a/laravel/laravel.php +++ b/laravel/laravel.php @@ -26,21 +26,9 @@ */ if (Config::$items['session']['driver'] !== '') { - require SYS_PATH.'cookie'.EXT; - require SYS_PATH.'session/payload'.EXT; - $driver = IoC::container()->core('session.'.Config::$items['session']['driver']); - if ( ! is_null($id = Cookie::get(Config::$items['session']['cookie']))) - { - $payload = new Session\Payload($driver->load($id)); - } - else - { - $payload = new Session\Payload; - } - - IoC::container()->instance('laravel.session', $payload); + Session::start($driver); } /** @@ -129,7 +117,7 @@ */ if (Config::$items['session']['driver'] !== '') { - IoC::container()->core('session')->save($driver); + Session::save($driver); } /** diff --git a/laravel/redirect.php b/laravel/redirect.php index 92f76432..4a49ae5c 100644 --- a/laravel/redirect.php +++ b/laravel/redirect.php @@ -61,7 +61,7 @@ public function with($key, $value) throw new \Exception('A session driver must be set before setting flash data.'); } - IoC::container()->core('session')->flash($key, $value); + Session::flash($key, $value); return $this; } diff --git a/laravel/security/auth.php b/laravel/security/auth.php index f580ebf3..3bbf1dbe 100644 --- a/laravel/security/auth.php +++ b/laravel/security/auth.php @@ -3,7 +3,7 @@ use Laravel\Str; use Laravel\Config; use Laravel\Cookie; -use Laravel\Session\Manager as Session; +use Laravel\Session; class Auth { diff --git a/laravel/session.php b/laravel/session.php new file mode 100644 index 00000000..adf4bdc5 --- /dev/null +++ b/laravel/session.php @@ -0,0 +1,258 @@ +load($id); + } + + if (static::invalid()) + { + static::$exists = false; + + // A CSRF token is stored in every session. The token is used by the + // Form class and the "csrf" filter to protect the application from + // cross-site request forgery attacks. The token is simply a long, + // random string which should be posted with each request. + $token = Str::random(40); + + static::$session = array('id' => Str::random(40), 'data' => compact('token')); + } + } + + /** + * Deteremine if the session payload instance is valid. + * + * The session is considered valid if it exists and has not expired. + * + * @return bool + */ + protected static function invalid() + { + $lifetime = Config::$items['session']['lifetime']; + + return is_null(static::$session) or (time() - static::$session['last_activity'] > ($lifetime * 60)); + } + + /** + * Determine if the session or flash data contains an item. + * + * @param string $key + * @return bool + */ + public static function has($key) + { + return ( ! is_null(static::get($key))); + } + + /** + * Get an item from the session. + * + * The session flash data will also be checked for the requested item. + * + * + * // Get an item from the session + * $name = Session::get('name'); + * + * // Return a default value if the item doesn't exist + * $name = Session::get('name', 'Taylor'); + * + * + * @param string $key + * @param mixed $default + * @return mixed + */ + public static function get($key, $default = null) + { + foreach (array($key, ':old:'.$key, ':new:'.$key) as $possibility) + { + if (array_key_exists($possibility, static::$session['data'])) + { + return static::$session['data'][$possibility]; + } + } + + return ($default instanceof Closure) ? call_user_func($default) : $default; + } + + /** + * Write an item to the session. + * + * @param string $key + * @param mixed $value + * @return void + */ + public static function put($key, $value) + { + static::$session['data'][$key] = $value; + } + + /** + * Write an item to the session flash data. + * + * Flash data only exists for the next request to the application. + * + * @param string $key + * @param mixed $value + * @return void + */ + public static function flash($key, $value) + { + static::put(':new:'.$key, $value); + } + + /** + * Keep all of the session flash data from expiring at the end of the request. + * + * @return void + */ + public static function reflash() + { + static::keep(array_keys(static::$session['data'])); + } + + /** + * Keep a session flash item from expiring at the end of the request. + * + * @param string|array $key + * @return void + */ + public static function keep($keys) + { + foreach ((array) $keys as $key) static::flash($key, static::get($key)); + } + + /** + * Remove an item from the session data. + * + * @param string $key + * @return Driver + */ + public static function forget($key) + { + unset(static::$session['data'][$key]); + } + + /** + * Remove all of the items from the session. + * + * @return void + */ + public static function flush() + { + static::$session['data'] = array(); + } + + /** + * Assign a new, random ID to the session. + * + * @return void + */ + public static function regenerate() + { + static::$session['id'] = Str::random(40); + + static::$exists = false; + } + + /** + * Store the session payload in storage. + * + * @param Driver $driver + * @return void + */ + public static function save(Driver $driver) + { + static::$session['last_activity'] = time(); + + static::age(); + + $config = Config::$items['session']; + + // To keep the session persistence code clean, session drivers are + // responsible for the storage of the session array to the various + // available persistent storage mechanisms. + $driver->save(static::$session, $config, static::$exists); + + static::cookie(); + + // Some session drivers implement the Sweeper interface, meaning that they + // must clean up expired sessions manually. If the driver is a sweeper, we + // need to determine if garbage collection should be run for the request. + // Since garbage collection can be expensive, the probability of it + // occuring is controlled by the "sweepage" configuration option. + if ($driver instanceof Sweeper and (mt_rand(1, $config['sweepage'][1]) <= $config['sweepage'][0])) + { + $driver->sweep(time() - ($config['lifetime'] * 60)); + } + } + + /** + * Age the session flash data. + * + * Session flash data is only available during the request in which it + * was flashed, and the request after that. To "age" the data, we will + * remove all of the :old: items and re-address the new items. + * + * @return void + */ + protected static function age() + { + foreach (static::$session['data'] as $key => $value) + { + if (strpos($key, ':old:') === 0) static::forget($key); + } + + // Now that all of the "old" keys have been removed from the session data, + // we can re-address all of the newly flashed keys to have old addresses. + // The array_combine method uses the first array for keys, and the second + // array for values to construct a single array from both. + $keys = str_replace(':new:', ':old:', array_keys(static::$session['data'])); + + static::$session['data'] = array_combine($keys, array_values(static::$session['data'])); + } + + /** + * Send the session ID cookie to the browser. + * + * @return void + */ + protected static function cookie() + { + $config = Config::$items['session']; + + extract($config, EXTR_SKIP); + + $minutes = ( ! $expire_on_close) ? $lifetime : 0; + + Cookie::put($cookie, static::$session['id'], $minutes, $path, $domain, $secure); + } + +} \ No newline at end of file diff --git a/laravel/session/payload.php b/laravel/session/payload.php index 7ec80510..74ec3100 100644 --- a/laravel/session/payload.php +++ b/laravel/session/payload.php @@ -6,35 +6,38 @@ use Laravel\Session\Drivers\Driver; use Laravel\Session\Drivers\Sweeper; -class Payload { +class Session { /** * The session array that is stored by the driver. * * @var array */ - protected $session; + protected static $session; /** * Indicates if the session already exists in storage. * * @var bool */ - protected $exists = true; + protected static $exists = true; /** - * Create a new session payload instance. + * Start the session handling for the current request. * - * @param array $session + * @param Driver $driver * @return void */ - public function __construct($session = null) + public static function start(Driver $driver) { - $this->session = $session; - - if ($this->invalid()) + if ( ! is_null($id = Cookie::get(Config::$items['session']['cookie']))) { - $this->exists = false; + static::$session = $driver->load($id); + } + + if (static::invalid()) + { + static::$exists = false; // A CSRF token is stored in every session. The token is used by the // Form class and the "csrf" filter to protect the application from @@ -42,7 +45,7 @@ public function __construct($session = null) // random string which should be posted with each request. $token = Str::random(40); - $this->session = array('id' => Str::random(40), 'data' => compact('token')); + static::$session = array('id' => Str::random(40), 'data' => compact('token')); } } @@ -53,11 +56,11 @@ public function __construct($session = null) * * @return bool */ - protected function invalid() + protected static function invalid() { $lifetime = Config::$items['session']['lifetime']; - return is_null($this->session) or (time() - $this->last_activity > ($lifetime * 60)); + return is_null(static::$session) or (time() - static::$session['last_activity'] > ($lifetime * 60)); } /** @@ -66,9 +69,9 @@ protected function invalid() * @param string $key * @return bool */ - public function has($key) + public static function has($key) { - return ( ! is_null($this->get($key))); + return ( ! is_null(static::get($key))); } /** @@ -88,13 +91,13 @@ public function has($key) * @param mixed $default * @return mixed */ - public function get($key, $default = null) + public static function get($key, $default = null) { foreach (array($key, ':old:'.$key, ':new:'.$key) as $possibility) { - if (array_key_exists($possibility, $this->session['data'])) + if (array_key_exists($possibility, static::$session['data'])) { - return $this->session['data'][$possibility]; + return static::$session['data'][$possibility]; } } @@ -108,9 +111,9 @@ public function get($key, $default = null) * @param mixed $value * @return void */ - public function put($key, $value) + public static function put($key, $value) { - $this->session['data'][$key] = $value; + static::$session['data'][$key] = $value; } /** @@ -122,9 +125,9 @@ public function put($key, $value) * @param mixed $value * @return void */ - public function flash($key, $value) + public static function flash($key, $value) { - $this->put(':new:'.$key, $value); + static::put(':new:'.$key, $value); } /** @@ -132,9 +135,9 @@ public function flash($key, $value) * * @return void */ - public function reflash() + public static function reflash() { - $this->keep(array_keys($this->session['data'])); + static::keep(array_keys(static::$session['data'])); } /** @@ -143,9 +146,9 @@ public function reflash() * @param string|array $key * @return void */ - public function keep($keys) + public static function keep($keys) { - foreach ((array) $keys as $key) $this->flash($key, $this->get($key)); + foreach ((array) $keys as $key) static::flash($key, static::get($key)); } /** @@ -154,9 +157,9 @@ public function keep($keys) * @param string $key * @return Driver */ - public function forget($key) + public static function forget($key) { - unset($this->session['data'][$key]); + unset(static::$session['data'][$key]); } /** @@ -164,9 +167,9 @@ public function forget($key) * * @return void */ - public function flush() + public static function flush() { - $this->session['data'] = array(); + static::$session['data'] = array(); } /** @@ -174,11 +177,11 @@ public function flush() * * @return void */ - public function regenerate() + public static function regenerate() { - $this->session['id'] = Str::random(40); + static::$session['id'] = Str::random(40); - $this->exists = false; + static::$exists = false; } /** @@ -187,20 +190,20 @@ public function regenerate() * @param Driver $driver * @return void */ - public function save(Driver $driver) + public static function save(Driver $driver) { - $this->session['last_activity'] = time(); + static::$session['last_activity'] = time(); - $this->age(); + static::age(); $config = Config::$items['session']; // To keep the session persistence code clean, session drivers are // responsible for the storage of the session array to the various // available persistent storage mechanisms. - $driver->save($this->session, $config, $this->exists); + $driver->save(static::$session, $config, static::$exists); - $this->cookie(); + static::cookie(); // Some session drivers implement the Sweeper interface, meaning that they // must clean up expired sessions manually. If the driver is a sweeper, we @@ -222,20 +225,20 @@ public function save(Driver $driver) * * @return void */ - protected function age() + protected static function age() { - foreach ($this->session['data'] as $key => $value) + foreach (static::$session['data'] as $key => $value) { - if (strpos($key, ':old:') === 0) $this->forget($key); + if (strpos($key, ':old:') === 0) static::forget($key); } // Now that all of the "old" keys have been removed from the session data, // we can re-address all of the newly flashed keys to have old addresses. // The array_combine method uses the first array for keys, and the second // array for values to construct a single array from both. - $keys = str_replace(':new:', ':old:', array_keys($this->session['data'])); + $keys = str_replace(':new:', ':old:', array_keys(static::$session['data'])); - $this->session['data'] = array_combine($keys, array_values($this->session['data'])); + static::$session['data'] = array_combine($keys, array_values(static::$session['data'])); } /** @@ -243,21 +246,13 @@ protected function age() * * @return void */ - protected function cookie() + protected static function cookie() { $config = Config::$items['session']; $minutes = ( ! $config['expire_on_close']) ? $config['lifetime'] : 0; - Cookie::put($cookie, $this->id, $minutes, $config['path'], $config['domain'], $config['secure']); - } - - /** - * Dynamically retrieve items from the session array. - */ - public function __get($key) - { - return (isset($this->session[$key])) ? $this->session[$key] : $this->get($key); + Cookie::put($cookie, static::$session['id'], $minutes, $config['path'], $config['domain'], $config['secure']); } } \ No newline at end of file