Commit 5b85edb2 authored by Taylor Otwell's avatar Taylor Otwell

more 2.0 changes

parent 73b1cb78
<?php namespace Laravel;
if (Config::get('session.driver') == '')
{
throw new \Exception("You must specify a session driver before using the Auth class.");
}
class Auth {
/**
......@@ -17,7 +12,14 @@ class Auth {
*
* @var object
*/
public static $user;
public $user;
/**
* The session driver being used by the Auth instance.
*
* @var Session\Driver
*/
protected $session;
/**
* The key used to store the user ID in the session.
......@@ -26,15 +28,26 @@ class Auth {
*/
protected static $key = 'laravel_user_id';
/**
* Create a new Auth class instance.
*
* @param Session\Driver $session_driver
* @return void
*/
public function __construct(Session\Driver $driver)
{
$this->session = $driver;
}
/**
* Determine if the current user of the application is authenticated.
*
* @see login()
* @return bool
*/
public static function check()
public function check()
{
return ! is_null(static::user());
return ! is_null($this->user());
}
/**
......@@ -50,14 +63,14 @@ class Auth {
*
* @return object
*/
public static function user()
public function user()
{
if (is_null(static::$user) and Session::has(static::$key))
if (is_null($this->user) and $this->session->has(static::$key))
{
static::$user = call_user_func(Config::get('auth.by_id'), Session::get(static::$key));
$this->user = call_user_func(Config::get('auth.by_id'), $this->session->get(static::$key));
}
return static::$user;
return $this->user;
}
/**
......@@ -80,13 +93,13 @@ class Auth {
* @param string $password
* @return bool
*/
public static function login($username, $password)
public function login($username, $password)
{
if ( ! is_null($user = call_user_func(Config::get('auth.by_username'), $username)))
{
if (Hash::check($password, $user->password))
{
static::remember($user);
$this->remember($user);
return true;
}
......@@ -107,11 +120,11 @@ class Auth {
* @param object $user
* @return void
*/
public static function remember($user)
public function remember($user)
{
static::$user = $user;
$this->user = $user;
Session::put(static::$key, $user->id);
$this->session->put(static::$key, $user->id);
}
/**
......@@ -122,11 +135,29 @@ class Auth {
*
* @return void
*/
public static function logout()
public function logout()
{
static::$user = null;
$this->user = null;
$this->session->forget(static::$key);
}
Session::forget(static::$key);
/**
* Pass all other methods to a generic Auth instance.
*
* This provides a convenient API for working with the default Auth configuration.
*
* <code>
* // Get the current user of your application
* $user = Auth::user();
*
* // Equivalent call using make method
* $user = Auth::make()->user();
* </code>
*/
public static function __callStatic($method, $parameters)
{
return call_user_func_array(array(new static(Session::driver()), $method), $parameters);
}
}
\ No newline at end of file
......@@ -52,7 +52,7 @@ class Cache {
}
/**
* Pass all other methods to the default driver.
* Pass all other methods to the default cache driver.
*
* Passing method calls to the driver instance provides a convenient API for the developer
* when always using the default cache driver.
......
......@@ -4,23 +4,57 @@ use Laravel\Config;
class APC extends Driver {
/**
* Determine if an item exists in the cache.
*
* <code>
* // Determine if the "name" item exists in the cache
* $exists = Cache::driver()->has('name');
* </code>
*
* @param string $key
* @return bool
*/
public function has($key)
{
return ( ! is_null($this->get($key)));
}
public function get($key, $default = null)
/**
* Retrieve an item from the cache driver.
*
* @param string $key
* @return mixed
*/
protected function retrieve($key)
{
$item = ( ! is_null($cache = apc_fetch(Config::get('cache.key').$key))) ? $cache : null;
return $this->prepare($item, $default);
return ( ! is_null($cache = apc_fetch(Config::get('cache.key').$key))) ? $cache : null;
}
/**
* Write an item to the cache for a given number of minutes.
*
* <code>
* // Write the "name" item to the cache for 30 minutes
* Cache::driver()->put('name', 'Fred', 30);
* </code>
*
* @param string $key
* @param mixed $value
* @param int $minutes
* @return void
*/
public function put($key, $value, $minutes)
{
apc_store(Config::get('cache.key').$key, $value, $minutes * 60);
}
/**
* Delete an item from the cache.
*
* @param string $key
* @return void
*/
public function forget($key)
{
apc_delete(Config::get('cache.key').$key);
......
......@@ -5,6 +5,11 @@ abstract class Driver {
/**
* Determine if an item exists in the cache.
*
* <code>
* // Determine if the "name" item exists in the cache
* $exists = Cache::driver()->has('name');
* </code>
*
* @param string $key
* @return bool
*/
......@@ -29,26 +34,28 @@ abstract class Driver {
* @param string $driver
* @return mixed
*/
abstract public function get($key, $default = null);
public function get($key, $default = null)
{
if ( ! is_null($item = $this->retrieve($key))) return $item;
return (is_callable($default)) ? call_user_func($default) : $default;
}
/**
* Prepare the cache item for returning to the requestor.
*
* If the item is NULL, the default will be returned.
* Retrieve an item from the cache driver.
*
* @param mixed $item
* @param mixed $default
* @param string $key
* @return mixed
*/
protected function prepare($item, $default)
{
if ( ! is_null($item)) return $item;
return (is_callable($default)) ? call_user_func($default) : $default;
}
abstract protected function retrieve($key);
/**
* Write an item to the cache.
* Write an item to the cache for a given number of minutes.
*
* <code>
* // Write the "name" item to the cache for 30 minutes
* Cache::driver()->put('name', 'Fred', 30);
* </code>
*
* @param string $key
* @param mixed $value
......@@ -73,7 +80,7 @@ abstract class Driver {
*/
public function remember($key, $value, $minutes)
{
if ( ! is_null($item = $this->get($key, null, $driver))) return $item;
if ( ! is_null($item = $this->get($key, null))) return $item;
$default = is_callable($default) ? call_user_func($default) : $default;
......
......@@ -2,37 +2,64 @@
class File extends Driver {
/**
* Determine if an item exists in the cache.
*
* <code>
* // Determine if the "name" item exists in the cache
* $exists = Cache::driver()->has('name');
* </code>
*
* @param string $key
* @return bool
*/
public function has($key)
{
return ( ! is_null($this->get($key)));
}
public function get($key, $default = null)
/**
* Retrieve an item from the cache driver.
*
* @param string $key
* @return mixed
*/
protected function retrieve($key)
{
if ( ! file_exists(CACHE_PATH.$key))
{
return $this->prepare(null, $default);
}
if ( ! file_exists(CACHE_PATH.$key)) return null;
$cache = file_get_contents(CACHE_PATH.$key);
// The cache expiration date is stored as a UNIX timestamp at the beginning
// of the cache file. We'll extract it out and check it here.
if (time() >= substr($cache, 0, 10))
if (time() >= substr($cache = file_get_contents(CACHE_PATH.$key), 0, 10))
{
$this->forget($key);
return $this->prepare(null, $default);
return $this->forget($key);
}
return $this->prepare(unserialize(substr($cache, 10)), $default);
return unserialize(substr($cache, 10));
}
/**
* Write an item to the cache for a given number of minutes.
*
* <code>
* // Write the "name" item to the cache for 30 minutes
* Cache::driver()->put('name', 'Fred', 30);
* </code>
*
* @param string $key
* @param mixed $value
* @param int $minutes
* @return void
*/
public function put($key, $value, $minutes)
{
file_put_contents(CACHE_PATH.$key, (time() + ($minutes * 60)).serialize($value), LOCK_EX);
}
/**
* Delete an item from the cache.
*
* @param string $key
* @return void
*/
public function forget($key)
{
@unlink(CACHE_PATH.$key);
......
......@@ -5,23 +5,57 @@ use Laravel\Memcached as Mem;
class Memcached extends Driver {
/**
* Determine if an item exists in the cache.
*
* <code>
* // Determine if the "name" item exists in the cache
* $exists = Cache::driver()->has('name');
* </code>
*
* @param string $key
* @return bool
*/
public function has($key)
{
return ( ! is_null($this->get($key)));
}
public function get($key, $default = null)
/**
* Retrieve an item from the cache driver.
*
* @param string $key
* @return mixed
*/
protected function retrieve($key)
{
$item = (($cache = Mem::instance()->get(Config::get('cache.key').$key)) !== false) ? $cache : null;
return $this->prepare($item, $default);
return (($cache = Mem::instance()->get(Config::get('cache.key').$key)) !== false) ? $cache : null;
}
/**
* Write an item to the cache for a given number of minutes.
*
* <code>
* // Write the "name" item to the cache for 30 minutes
* Cache::driver()->put('name', 'Fred', 30);
* </code>
*
* @param string $key
* @param mixed $value
* @param int $minutes
* @return void
*/
public function put($key, $value, $minutes)
{
Mem::instance()->set(Config::get('cache.key').$key, $value, 0, $minutes * 60);
}
/**
* Delete an item from the cache.
*
* @param string $key
* @return void
*/
public function forget($key)
{
Mem::instance()->delete(Config::get('cache.key').$key);
......
......@@ -136,7 +136,7 @@ class Config {
foreach (static::paths($module, $file) as $directory)
{
if (file_exists($path = $directory.$file.EXT)) $config = array_merge($config, require $path);
$config = (file_exists($path = $directory.$file.EXT)) ? array_merge($config, require $path) : $config;
}
if (count($config) > 0) static::$items[$module][$file] = $config;
......@@ -150,9 +150,9 @@ class Config {
* The paths returned by this method paths will be searched by the load method when merging
* configuration files, meaning the configuration files will cascade in this order.
*
* By default, the system configuration directory will be searched first, followed by the configuration
* configuration directory for the active module. Next, any environment specific configuration
* directories are searched.
* By default, the base configuration directory will be searched first, followed by the configuration
* directory for the active module. Next, any environment specific configuration directories
* will be searched.
*
* @param string $module
* @param string $file
......@@ -160,6 +160,8 @@ class Config {
*/
private static function paths($module, $file)
{
$module = str_replace('.', '/', $module);
$paths = array(CONFIG_PATH, Module::path($module).'config/');
if (isset($_SERVER['LARAVEL_ENV']))
......
......@@ -16,17 +16,31 @@ class Crypter {
*/
public $mode;
/**
* The encryption key.
*
* @var string
*/
public $key;
/**
* Create a new Crypter instance.
*
* @param string $cipher
* @param string $mode
* @param string $key
* @return void
*/
public function __construct($cipher = 'rijndael-256', $mode = 'cbc')
public function __construct($cipher, $mode, $key)
{
$this->cipher = $cipher;
$this->mode = $mode;
$this->key = $key;
if (trim((string) $this->key) === '')
{
throw new \Exception('The encryption class can not be used without an encryption key.');
}
}
/**
......@@ -34,11 +48,12 @@ class Crypter {
*
* @param string $cipher
* @param string $mode
* @param string $key
* @return Crypt
*/
public static function make($cipher = 'rijndael-256', $mode = 'cbc')
public static function make($cipher = MCRYPT_RIJNDAEL_256, $mode = 'cbc', $key = null)
{
return new static($cipher, $mode);
return new static($cipher, $mode, (is_null($key)) ? Config::get('application.key') : $key);
}
/**
......@@ -51,7 +66,7 @@ class Crypter {
{
$iv = mcrypt_create_iv($this->iv_size(), $this->randomizer());
return base64_encode($iv.mcrypt_encrypt($this->cipher, $this->key(), $value, $this->mode, $iv));
return base64_encode($iv.mcrypt_encrypt($this->cipher, $this->key, $value, $this->mode, $iv));
}
/**
......@@ -88,19 +103,7 @@ class Crypter {
list($iv, $value) = array(substr($value, 0, $this->iv_size()), substr($value, $this->iv_size()));
return rtrim(mcrypt_decrypt($this->cipher, $this->key(), $value, $this->mode, $iv), "\0");
}
/**
* Get the application key from the application configuration file.
*
* @return string
*/
private function key()
{
if ( ! is_null($key = Config::get('application.key')) and $key !== '') return $key;
throw new \Exception("The encryption class can not be used without an encryption key.");
return rtrim(mcrypt_decrypt($this->cipher, $this->key, $value, $this->mode, $iv), "\0");
}
/**
......
......@@ -15,6 +15,14 @@ class DB {
*
* Note: Database connections are managed as singletons.
*
* <code>
* // Get the default database connection
* $connection = DB::connection();
*
* // Get a specific database connection
* $connection = DB::connection('mysql');
* </code>
*
* @param string $connection
* @return DB\Connection
*/
......@@ -29,7 +37,9 @@ class DB {
throw new \Exception("Database connection [$connection] is not defined.");
}
static::$connections[$connection] = new DB\Connection($connection, (object) $config, new DB\Connector);
$connector = DB\Connector\Factory::make($config['driver']);
static::$connections[$connection] = DB\Connection\Factory::make($connection, $config, $connector);
}
return static::$connections[$connection];
......@@ -38,6 +48,19 @@ class DB {
/**
* Begin a fluent query against a table.
*
* This method primarily serves as a short-cut to the $connection->table() method.
*
* <code>
* // Begin a fluent query against the "users" table
* $query = DB::table('users');
*
* // Equivalent call using the connection table method.
* $query = DB::connection()->table('users');
*
* // Begin a fluent query against the "users" table for a specific connection
* $query = DB::table('users', 'mysql');
* </code>
*
* @param string $table
* @param string $connection
* @return DB\Query
......@@ -49,6 +72,16 @@ class DB {
/**
* Magic Method for calling methods on the default database connection.
*
* This provides a convenient API for querying or examining the default database connection.
*
* <code>
* // Run a query against the default database connection
* $results = DB::query('select * from users');
*
* // Equivalent call using the connection instance
* $results = DB::connection()->query('select * from users');
* </code>
*/
public static function __callStatic($method, $parameters)
{
......
......@@ -30,19 +30,60 @@ class Connection {
*/
public $queries = array();
/**
* The database connector instance.
*
* @var Connector
*/
protected $connector;
/**
* Create a new Connection instance.
*
* @param string $name
* @param object $config
* @param array $config
* @param Connector $connector
* @return void
*/
public function __construct($name, $config, $connector)
public function __construct($name, $config, Connector $connector)
{
$this->name = $name;
$this->config = $config;
$this->pdo = $connector->connect($this->config);
$this->connector = $connector;
}
/**
* Establish the PDO connection for the connection instance.
*
* @return void
*/
protected function connect()
{
$this->pdo = $this->connector->connect($this->config);
}
/**
* Determine if a PDO connection has been established for the connection.
*
* @return bool
*/
protected function connected()
{
return ! is_null($this->pdo);
}
/**
* Execute a SQL query against the connection and return a scalar result.
*
* @param string $sql
* @param array $bindings
* @return mixed
*/
public function scalar($sql, $bindings = array())
{
$result = (array) $this->first($sql, $bindings);
return (strpos(strtolower($sql), 'select count') === 0) ? (int) reset($result) : (float) reset($result);
}
/**
......@@ -69,26 +110,38 @@ class Connection {
*
* @param string $sql
* @param array $bindings
* @return array
* @return mixed
*/
public function query($sql, $bindings = array())
{
$this->queries[] = $sql;
if ( ! $this->connected()) $this->connect();
$this->queries[] = compact('sql', 'bindings');
$query = $this->pdo->prepare($sql);
return $this->execute($this->pdo->prepare($sql), $bindings);
}
$result = $query->execute($bindings);
/**
* Execute a prepared PDO statement and return the appropriate results.
*
* @param PDOStatement $statement
* @param array $results
* @return mixed
*/
protected function execute(\PDOStatement $statement, $bindings)
{
$result = $statement->execute($bindings);
if (strpos(strtoupper($sql), 'SELECT') === 0)
if (strpos(strtoupper($statement->queryString), 'SELECT') === 0)
{
return $query->fetchAll(\PDO::FETCH_CLASS, 'stdClass');
return $statement->fetchAll(\PDO::FETCH_CLASS, 'stdClass');
}
elseif (strpos(strtoupper($sql), 'UPDATE') === 0 or strpos(strtoupper($sql), 'DELETE') === 0)
elseif (strpos(strtoupper($statement->queryString), 'INSERT') === 0)
{
return $query->rowCount();
return $result;
}
return $result;
return $statement->rowCount();
}
/**
......@@ -99,19 +152,7 @@ class Connection {
*/
public function table($table)
{
return new Query($table, $this);
}
/**
* Get the keyword identifier wrapper for the connection.
*
* @return string
*/
public function wrapper()
{
if (array_key_exists('wrap', $this->config) and $this->config['wrap'] === false) return '';
return ($this->driver() == 'mysql') ? '`' : '"';
return Query\Factory::make($table, $this);
}
/**
......@@ -121,6 +162,8 @@ class Connection {
*/
public function driver()
{
if ( ! $this->connected()) $this->connect();
return $this->pdo->getAttribute(\PDO::ATTR_DRIVER_NAME);
}
......@@ -134,4 +177,11 @@ class Connection {
return (array_key_exists('prefix', $this->config)) ? $this->config['prefix'] : '';
}
/**
* Get the keyword identifier wrapper for the connection.
*
* @return string
*/
public function wrapper() { return '"'; }
}
\ No newline at end of file
<?php namespace Laravel\DB\Connection;
use Laravel\DB\Connector;
use Laravel\DB\Connection;
class Factory {
/**
* Get a connnection instance.
*
* The connection instance created depends on the driver being used.
*
* @param string $connection
* @param object $config
* @param Connector $connector
* @return Connection
*/
public static function make($connection, $config, Connector $connector)
{
switch ($config['driver'])
{
case 'mysql':
return new MySQL($connection, $config, $connector);
default:
return new Connection($connection, $config, $connector);
}
}
}
\ No newline at end of file
<?php namespace Laravel\DB\Connection;
use Laravel\DB\Connection;
class MySQL extends Connection {
/**
* Get the keyword identifier wrapper for the connection.
*
* MySQL uses a non-standard wrapper
*
* @return string
*/
public function wrapper() { return '`'; }
}
\ No newline at end of file
<?php namespace Laravel\DB;
use Laravel\Config;
class Connector {
abstract class Connector {
/**
* The PDO connection options.
......@@ -10,99 +8,19 @@ class Connector {
* @var array
*/
public $options = array(
\PDO::ATTR_CASE => \PDO::CASE_LOWER,
\PDO::ATTR_ERRMODE => \PDO::ERRMODE_EXCEPTION,
\PDO::ATTR_ORACLE_NULLS => \PDO::NULL_NATURAL,
\PDO::ATTR_STRINGIFY_FETCHES => false,
\PDO::ATTR_EMULATE_PREPARES => false,
\PDO::ATTR_CASE => \PDO::CASE_LOWER,
\PDO::ATTR_ERRMODE => \PDO::ERRMODE_EXCEPTION,
\PDO::ATTR_ORACLE_NULLS => \PDO::NULL_NATURAL,
\PDO::ATTR_STRINGIFY_FETCHES => false,
\PDO::ATTR_EMULATE_PREPARES => false,
);
/**
* Establish a PDO database connection.
*
* @param object $connection
* @return PDO
*/
public function connect($config)
{
switch ($config->driver)
{
case 'sqlite':
return $this->connect_to_sqlite($config);
case 'mysql':
case 'pgsql':
return $this->connect_to_server($config);
default:
return $this->connect_to_generic($config);
}
throw new \Exception('Database driver '.$config->driver.' is not supported.');
}
/**
* Establish a PDO connection to a SQLite database.
*
* SQLite database paths can be specified either relative to the application/db
* directory, or as an absolute path to any location on the file system. In-memory
* databases are also supported.
*
* @param object $config
* @return PDO
*/
private function connect_to_sqlite($config)
{
if ($config->database == ':memory:')
{
return new \PDO('sqlite::memory:', null, null, $this->options);
}
elseif (file_exists($path = DATABASE_PATH.$config->database.'.sqlite'))
{
return new \PDO('sqlite:'.$path, null, null, $this->options);
}
elseif (file_exists($config->database))
{
return new \PDO('sqlite:'.$config->database, null, null, $this->options);
}
throw new \Exception("SQLite database [".$config->database."] could not be found.");
}
/**
* Connect to a MySQL or PostgreSQL database server.
*
* @param object $config
* @return PDO
*/
private function connect_to_server($config)
{
$dsn = $config->driver.':host='.$config->host.';dbname='.$config->database;
if (isset($config->port))
{
$dsn .= ';port='.$config->port;
}
$connection = new \PDO($dsn, $config->username, $config->password, $this->options);
if (isset($config->charset))
{
$connection->prepare("SET NAMES '".$config->charset."'")->execute();
}
return $connection;
}
/**
* Connect to a generic data source.
*
* @param object $config
* @param array $config
* @return PDO
*/
private function connect_to_generic($config)
{
return new \PDO($config->driver.':'.$config->dsn, $config->username, $config->password, $this->options);
}
abstract public function connect($config);
}
\ No newline at end of file
<?php namespace Laravel\DB\Connector;
class Factory {
/**
* Create a new database connector instance for a given driver.
*
* @param string $driver
* @return Connector
*/
public static function make($driver)
{
switch ($driver)
{
case 'sqlite':
return new SQLite;
case 'mysql':
return new MySQL;
case 'postgres':
return new Postgres;
default:
return new Generic;
}
}
}
\ No newline at end of file
<?php namespace Laravel\DB\Connector;
use Laravel\DB\Connector;
class Generic extends Connector {
/**
* Establish a PDO database connection.
*
* @param array $config
* @return PDO
*/
public function connect($config)
{
return new \PDO($config['driver'].':'.$config['dsn'], $config['username'], $config['password'], $this->options);
}
}
\ No newline at end of file
<?php namespace Laravel\DB\Connector;
use Laravel\DB\Connector;
class MySQL extends Connector {
/**
* Establish a PDO database connection.
*
* @param array $config
* @return PDO
*/
public function connect($config)
{
$dsn = $config['driver'].':host='.$config['host'].';dbname='.$config['database'];
if (isset($config['port']))
{
$dsn .= ';port='.$config['port'];
}
$connection = new \PDO($dsn, $config['username'], $config['password'], $this->options);
if (isset($config['charset']))
{
$connection->prepare("SET NAMES '".$config['charset']."'")->execute();
}
return $connection;
}
}
\ No newline at end of file
<?php namespace Laravel\DB\Connector;
use Laravel\DB\Connector;
class MySQL extends Connector {
/**
* Establish a PDO database connection.
*
* @param array $config
* @return PDO
*/
public function connect($config)
{
$dsn = $config['driver'].':host='.$config['host'].';dbname='.$config['database'];
if (isset($config['port']))
{
$dsn .= ';port='.$config['port'];
}
$connection = new \PDO($dsn, $config['username'], $config['password'], $this->options);
if (isset($config['charset']))
{
$connection->prepare("SET NAMES '".$config['charset']."'")->execute();
}
return $connection;
}
}
\ No newline at end of file
<?php namespace Laravel\DB\Connector;
use Laravel\DB\Connector;
class SQLite extends Connector {
/**
* Establish a PDO database connection.
*
* @param array $config
* @return PDO
*/
public function connect($config)
{
if ($config['database'] == ':memory:')
{
return new \PDO('sqlite::memory:', null, null, $this->options);
}
elseif (file_exists($path = DATABASE_PATH.$config['database'].'.sqlite'))
{
return new \PDO('sqlite:'.$path, null, null, $this->options);
}
elseif (file_exists($config['database']))
{
return new \PDO('sqlite:'.$config['database'], null, null, $this->options);
}
throw new \Exception("SQLite database [".$config['database']."] could not be found.");
}
}
\ No newline at end of file
<?php namespace System\DB\Eloquent;
<?php namespace Laravel\DB\Eloquent;
class Hydrator {
......
<?php namespace System\DB\Eloquent;
<?php namespace Laravel\DB\Eloquent;
use System\DB;
use System\Str;
use System\Config;
use System\Inflector;
use System\Paginator;
use Laravel\DB;
use Laravel\Str;
use Laravel\Config;
use Laravel\Inflector;
use Laravel\Paginator;
abstract class Model {
......
......@@ -83,7 +83,7 @@ class Query {
* @param Connection $connection
* @return void
*/
public function __construct($table, $connection)
public function __construct($table, Connection $connection)
{
$this->table = $table;
$this->connection = $connection;
......@@ -97,7 +97,7 @@ class Query {
* @param Connection $connection
* @return Query
*/
public static function table($table, $connection)
public static function table($table, Connection $connection)
{
return new static($table, $connection);
}
......@@ -579,18 +579,7 @@ class Query {
*/
public function insert_get_id($values)
{
$sql = $this->compile_insert($values);
if ($this->connection->driver() == 'pgsql')
{
$query = $this->connection->pdo->prepare($sql.' RETURNING '.$this->wrap('id'));
$query->execute(array_values($values));
return $query->fetch(\PDO::FETCH_CLASS, 'stdClass')->id;
}
$this->connection->query($sql, array_values($values));
$this->connection->query($this->compile_insert($values), array_values($values));
return $this->connection->pdo->lastInsertId();
}
......
<?php namespace Laravel\DB\Query;
use Laravel\DB\Query;
use Laravel\DB\Connection;
class Factory {
/**
* Create a new query instance for a given driver.
*
* @param string $table
* @param Connection $connection
* @return Query
*/
public static function make($table, Connection $connection)
{
switch ($connection->driver())
{
case 'postgres':
return new Postgres($table, $connection);
default:
return new Query($table, $connection);
}
}
}
\ No newline at end of file
<?php namespace Laravel\DB\Query;
use Laravel\DB\Query;
class Postgres extends Query {
/**
* Execute an INSERT statement and get the insert ID.
*
* @param array $values
* @return int
*/
public function insert_get_id($values)
{
$sql = $this->compile_insert($values);
$query = $this->connection->pdo->prepare($sql.' RETURNING '.$this->wrap('id'));
$query->execute(array_values($values));
return $query->fetch(\PDO::FETCH_CLASS, 'stdClass')->id;
}
}
\ No newline at end of file
......@@ -8,14 +8,14 @@ define('EXT', '.php');
// --------------------------------------------------------------
// Define the core framework paths.
// --------------------------------------------------------------
define('BASE_PATH', realpath(str_replace('laravel', '', $system)).'/');
define('BASE_PATH', realpath(str_replace('laravel', '', $laravel)).'/');
define('MODULE_PATH', realpath($modules).'/');
define('PACKAGE_PATH', realpath($packages).'/');
define('PUBLIC_PATH', realpath($public).'/');
define('STORAGE_PATH', realpath($storage).'/');
define('SYS_PATH', realpath($system).'/');
define('SYS_PATH', realpath($laravel).'/');
unset($system, $config, $modules, $packages, $public, $storage);
unset($laravel, $config, $modules, $packages, $public, $storage);
// --------------------------------------------------------------
// Define various other framework paths.
......@@ -70,6 +70,11 @@ error_reporting(E_ALL | E_STRICT);
ini_set('display_errors', 'Off');
// --------------------------------------------------------------
// Set the default timezone.
// --------------------------------------------------------------
date_default_timezone_set(Config::get('application.timezone'));
// --------------------------------------------------------------
// Register the error / exception handlers.
// --------------------------------------------------------------
......@@ -107,19 +112,27 @@ register_shutdown_function(function() use ($error_dependencies)
});
// --------------------------------------------------------------
// Set the default timezone.
// Determine the module that should handle the request.
// --------------------------------------------------------------
date_default_timezone_set(Config::get('application.timezone'));
require SYS_PATH.'request'.EXT;
$segments = explode('/', Request::uri());
define('ACTIVE_MODULE', (array_key_exists($segments[0], Module::$modules)) ? $segments[0] : DEFAULT_MODULE);
// --------------------------------------------------------------
// Determine the path to the root of the active module.
// --------------------------------------------------------------
define('ACTIVE_MODULE_PATH', Module::path(ACTIVE_MODULE));
// --------------------------------------------------------------
// Load the session.
// --------------------------------------------------------------
if (Config::get('session.driver') != '') Session::load(Cookie::get('laravel_session'));
if (Config::get('session.driver') != '') Session::driver()->start(Cookie::get('laravel_session'));
// --------------------------------------------------------------
// Load all of the core routing classes.
// --------------------------------------------------------------
require SYS_PATH.'request'.EXT;
require SYS_PATH.'response'.EXT;
require SYS_PATH.'routing/route'.EXT;
require SYS_PATH.'routing/router'.EXT;
......@@ -136,18 +149,6 @@ if (count(Config::get('application.packages')) > 0)
Package::load(Config::get('application.packages'));
}
// --------------------------------------------------------------
// Determine the module that should handle the request.
// --------------------------------------------------------------
$segments = explode('/', Request::uri());
define('ACTIVE_MODULE', (array_key_exists($segments[0], Module::$modules)) ? $segments[0] : DEFAULT_MODULE);
// --------------------------------------------------------------
// Determine the path to the root of the active module.
// --------------------------------------------------------------
define('ACTIVE_MODULE_PATH', Module::path(ACTIVE_MODULE));
// --------------------------------------------------------------
// Register the filters for the default module.
// --------------------------------------------------------------
......@@ -201,7 +202,19 @@ $response->content = (string) $response->content;
// --------------------------------------------------------------
// Close the session.
// --------------------------------------------------------------
if (Config::get('session.driver') != '') Session::close();
if (Config::get('session.driver') != '')
{
$driver = Session::driver();
$driver->flash('laravel_old_input', Input::get());
$driver->close();
if ($driver instanceof Session\Sweeper and mt_rand(1, 100) <= 2)
{
$driver->sweep(time() - (Config::get('session.lifetime') * 60));
}
}
// --------------------------------------------------------------
// Send the response to the browser.
......
......@@ -76,32 +76,39 @@ class Loader {
}
/**
* Load a class that is stored in a module.
* Search the active modules for a given file.
*
* @param string $file
* @return void
*/
private static function load_from_module($file)
{
// Since all module models and libraries must be namespaced to the
// module name, we'll extract the module name from the file.
$module = substr($file, 0, strpos($file, '/'));
if (is_null($module = static::module_path($file))) return;
if (in_array($module, Module::$modules))
{
$module = MODULE_PATH.$module.'/';
// Slice the module name off of the filename. Even though module libraries
// and models are namespaced under the module, there will obviously not be
// a folder matching that namespace in the libraries or models directory.
$file = substr($file, strlen($module));
// Slice the module name off of the filename. Even though module libraries
// and models are namespaced under the module, there will obviously not be
// a folder matching that namespace in the libraries or models directories
// of the module. Slicing it off will allow us to make a clean search for
// the relevant class file.
$file = substr($file, strpos($file, '/') + 1);
foreach (array(MODULE_PATH.$module.'/models', MODULE_PATH.$module.'/libraries') as $directory)
{
if (file_exists($path = $directory.'/'.$file.EXT)) return require $path;
}
}
foreach (array($module.'models', $module.'libraries') as $directory)
{
if (file_exists($path = $directory.'/'.$file.EXT)) return require $path;
}
/**
* Search the module paths for a match on the file.
*
* The file namespace should correspond to a directory within the module directory.
*
* @param string $file
* @return string
*/
private static function module_path($file)
{
foreach (Module::$modules as $key => $module)
{
if (strpos($file, $module) === 0) return $module;
}
}
......
......@@ -42,6 +42,8 @@ class Module {
{
$module = (strpos($key, '::') !== false) ? substr($key, 0, strpos($key, ':')) : DEFAULT_MODULE;
$module = str_replace('.', '/', $module);
if ($module !== DEFAULT_MODULE) $key = substr($key, strpos($key, ':') + 2);
return array($module, $key);
......@@ -50,9 +52,7 @@ class Module {
/**
* Get the path for a given module.
*
* If the module exists in the module array as a key, that means a path other than
* the default path has been specified for the module. Otherwise, the module directory
* is assumed to have the same name as the module.
* Once the path has been determined, it will be cached by the class for quick access.
*
* @param string $module
* @return string
......@@ -65,10 +65,6 @@ class Module {
{
return static::$paths[$module] = MODULE_PATH.$module.'/';
}
elseif (array_key_exists($module, static::$modules))
{
return static::$paths[$module] = MODULE_PATH.static::$modules[$module].'/';
}
}
/**
......
......@@ -9,16 +9,13 @@ class Session {
*/
public static $driver;
/**
* The session payload, which contains the session ID, data and last activity timestamp.
*
* @var array
*/
public static $session = array();
/**
* Get the session driver.
*
* The session driver returned will be the driver specified in the session configuration
* file. Only one session driver may be active for a given request, so the driver will
* be managed as a singleton.
*
* @return Session\Driver
*/
public static function driver()
......@@ -51,188 +48,22 @@ class Session {
}
/**
* Load a user session by ID.
*
* @param string $id
* @return void
*/
public static function load($id)
{
static::$session = ( ! is_null($id)) ? static::driver()->load($id) : null;
if (static::invalid(static::$session))
{
static::$session = array('id' => Str::random(40), 'data' => array());
}
if ( ! static::has('csrf_token'))
{
static::put('csrf_token', Str::random(16));
}
static::$session['last_activity'] = time();
}
/**
* Determine if a session is valid.
*
* A session is considered valid if it exists and has not expired.
*
* @param array $session
* @return bool
*/
private static function invalid($session)
{
return is_null($session) or (time() - $session['last_activity']) > (Config::get('session.lifetime') * 60);
}
/**
* Determine if the session or flash data contains an item.
* Pass all other methods to the default session driver.
*
* @param string $key
* @return bool
*/
public static function has($key)
{
return ( ! is_null(static::get($key)));
}
/**
* Get an item from the session or flash data.
* 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.
*
* @param string $key
* @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 is_callable($default) ? 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.
*
* @param string $key
* @param mixed $value
* @return void
*/
public static function flash($key, $value)
{
static::put(':new:'.$key, $value);
}
/**
* Remove an item from the session.
* <code>
* // Get an item from the default session driver
* $name = Session::get('name');
*
* @param string $key
* @return void
* // Equivalent call using the driver method
* $name = Session::driver()->get('name');
* </code>
*/
public static function forget($key)
public static function __callStatic($method, $parameters)
{
unset(static::$session['data'][$key]);
}
/**
* Remove all items from the session.
*
* @return void
*/
public static function flush()
{
static::$session['data'] = array();
}
/**
* Regenerate the session ID.
*
* @return void
*/
public static function regenerate()
{
static::driver()->delete(static::$session['id']);
static::$session['id'] = Str::random(40);
}
/**
* Close the session.
*
* The session will be stored in persistant storage and the session cookie will be
* session cookie will be sent to the browser. The old input data will also be
* stored in the session flash data.
*
* @return void
*/
public static function close()
{
static::flash('laravel_old_input', Input::get());
static::age_flash();
static::driver()->save(static::$session);
static::write_cookie();
if (mt_rand(1, 100) <= 2 and static::driver() instanceof Session\Sweeper)
{
static::driver()->sweep(time() - (Config::get('session.lifetime') * 60));
}
}
/**
* Age the session flash data.
*
* @return void
*/
private static function age_flash()
{
foreach (static::$session['data'] as $key => $value)
{
if (strpos($key, ':old:') === 0) static::forget($key);
}
foreach (static::$session['data'] as $key => $value)
{
if (strpos($key, ':new:') === 0)
{
static::put(':old:'.substr($key, 5), $value);
static::forget($key);
}
}
}
/**
* Write the session cookie.
*
* @return void
*/
private static function write_cookie()
{
if ( ! headers_sent())
{
extract(Config::get('session'));
$minutes = ($expire_on_close) ? 0 : $lifetime;
Cookie::put('laravel_session', static::$session['id'], $minutes, $path, $domain, $https, $http_only);
}
return call_user_func_array(array(static::driver(), $method), $parameters);
}
}
\ No newline at end of file
......@@ -3,39 +3,21 @@
use Laravel\Cache;
use Laravel\Config;
class APC implements Driver {
class APC extends Driver {
/**
* Load a session by ID.
*
* @param string $id
* @return array
*/
public function load($id)
protected function load($id)
{
return Cache::driver('apc')->get($id);
}
/**
* Save a session.
*
* @param array $session
* @return void
*/
public function save($session)
protected function save()
{
Cache::driver('apc')->put($session['id'], $session, Config::get('session.lifetime'));
Cache::driver('apc')->put($this->session['id'], $this->session, Config::get('session.lifetime'));
}
/**
* Delete a session by ID.
*
* @param string $id
* @return void
*/
public function delete($id)
protected function delete()
{
Cache::driver('apc')->forget($id);
Cache::driver('apc')->forget($this->session['id']);
}
}
\ No newline at end of file
......@@ -3,7 +3,7 @@
use Laravel\Config;
use Laravel\Crypter;
class Cookie implements Driver {
class Cookie extends Driver {
/**
* The Crypter instance.
......@@ -27,13 +27,7 @@ class Cookie implements Driver {
}
}
/**
* Load a session by ID.
*
* @param string $id
* @return array
*/
public function load($id)
protected function load($id)
{
if (\System\Cookie::has('session_payload'))
{
......@@ -41,31 +35,19 @@ class Cookie implements Driver {
}
}
/**
* Save a session.
*
* @param array $session
* @return void
*/
public function save($session)
protected function save()
{
if ( ! headers_sent())
{
extract(Config::get('session'));
$payload = $this->crypter->encrypt(serialize($session));
$payload = $this->crypter->encrypt(serialize($this->session));
\System\Cookie::put('session_payload', $payload, $lifetime, $path, $domain, $https, $http_only);
}
}
/**
* Delete a session by ID.
*
* @param string $id
* @return void
*/
public function delete($id)
protected function delete()
{
\System\Cookie::forget('session_payload');
}
......
......@@ -2,15 +2,9 @@
use Laravel\Config;
class DB implements Driver, Sweeper {
class DB extends Driver implements Sweeper {
/**
* Load a session by ID.
*
* @param string $id
* @return array
*/
public function load($id)
protected function load($id)
{
$session = $this->table()->find($id);
......@@ -24,40 +18,22 @@ class DB implements Driver, Sweeper {
}
}
/**
* Save a session.
*
* @param array $session
* @return void
*/
public function save($session)
protected function save()
{
$this->delete($session['id']);
$this->delete($this->session['id']);
$this->table()->insert(array(
'id' => $session['id'],
'last_activity' => $session['last_activity'],
'data' => serialize($session['data'])
'id' => $this->session['id'],
'last_activity' => $this->session['last_activity'],
'data' => serialize($this->session['data'])
));
}
/**
* Delete a session by ID.
*
* @param string $id
* @return void
*/
public function delete($id)
protected function delete()
{
$this->table()->delete($id);
$this->table()->delete($this->session['id']);
}
/**
* Delete all expired sessions.
*
* @param int $expiration
* @return void
*/
public function sweep($expiration)
{
$this->table()->where('last_activity', '<', $expiration)->delete();
......
<?php namespace Laravel\Session;
interface Driver {
use Laravel\Str;
use Laravel\Config;
use Laravel\Cookie;
abstract class Driver {
/**
* The session payload, which contains the session ID, data and last activity timestamp.
*
* @var array
*/
public $session = array();
/**
* Load the session for a given session ID.
*
* The session will be checked for validity and necessary data. For example, if the session
* does not have a CSRF token, a token will be generated for the session.
*
* If the session has expired, a new, empty session will be generated.
*
* @param string $id
* @return void
*/
public function start($id)
{
$this->session = ( ! is_null($id)) ? $this->load($id) : null;
if (is_null($this->session) or (time() - $this->session['last_activity']) > (Config::get('session.lifetime') * 60))
{
$this->session = array('id' => Str::random(40), 'data' => array());
}
if ( ! $this->has('csrf_token')) $this->put('csrf_token', Str::random(16));
$this->session['last_activity'] = time();
}
/**
* Load a session by ID.
*
* The session will be retrieved from persistant storage and returned as an array.
* The array contains the session ID, last activity UNIX timestamp, and session data.
*
* @param string $id
* @return array
*/
public function load($id);
abstract protected function load($id);
/**
* Save a session.
* Delete the session from persistant storage.
*
* @param array $session
* @return void
*/
public function save($session);
abstract protected function delete();
/**
* Delete a session by ID.
* Save the session to persistant storage.
*
* @param string $id
* @return void
*/
public function delete($id);
abstract protected function save();
/**
* Determine if the session or flash data contains an item.
*
* <code>
* // Determine if "name" item exists in the session
* $exists = Session::driver()->has('name');
* </code>
*
* @param string $key
* @return bool
*/
public function has($key)
{
return ( ! is_null($this->get($key)));
}
/**
* Get an item from the session.
*
* A default value may also be specified, and will be returned in the requested
* item does not exist in the session.
*
* <code>
* // Get the "name" item from the session
* $name = Session::driver()->get('name');
*
* // Get the "name" item from the session or return "Fred"
* $name = Session::driver()->get('name', 'Fred');
* </code>
*
* @param string $key
* @param mixed $default
* @return mixed
*/
public function get($key, $default = null)
{
foreach (array($key, ':old:'.$key, ':new:'.$key) as $possibility)
{
if (array_key_exists($possibility, $this->session['data'])) return $this->session['data'][$possibility];
}
return is_callable($default) ? call_user_func($default) : $default;
}
/**
* Write an item to the session.
*
* <code>
* // Write the "name" item to the session
* Session::driver()->put('name', 'Fred');
* </code>
*
* @param string $key
* @param mixed $value
* @return void
*/
public function put($key, $value)
{
$this->session['data'][$key] = $value;
}
/**
* Write an item to the session flash data.
*
* Flash data only exists for the next request. After that, it will be removed from
* the session. Flash data is useful for temporary status or welcome messages.
*
* <code>
* // Write the "name" item to the session flash data
* Session::driver()->flash('name', 'Fred');
* </code>
*
* @param string $key
* @param mixed $value
* @return void
*/
public function flash($key, $value)
{
$this->put(':new:'.$key, $value);
}
/**
* Remove an item from the session.
*
* <code>
* // Remove the "name" item from the session
* Session::driver()->forget('name');
* </code>
*
* @param string $key
* @return void
*/
public function forget($key)
{
unset($this->session['data'][$key]);
}
/**
* Remove all items from the session.
*
* @return void
*/
public function flush()
{
$this->session['data'] = array();
}
/**
* Regenerate the session ID.
*
* @return void
*/
public function regenerate()
{
$this->delete();
$this->session['id'] = Str::random(40);
}
/**
* Close the session.
*
* The session will be stored in persistant storage and the session cookie will be
* session cookie will be sent to the browser.
*
* @return void
*/
public function close()
{
$this->age_flash();
$this->save();
$this->write_cookie();
}
/**
* Age the session flash data.
*
* @return void
*/
public function age_flash()
{
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);
$this->forget($key);
}
}
}
/**
* Write the session cookie.
*
* @return void
*/
protected function write_cookie()
{
if ( ! headers_sent())
{
extract(Config::get('session'));
$minutes = ($expire_on_close) ? 0 : $lifetime;
Cookie::put('laravel_session', $this->session['id'], $minutes, $path, $domain, $https, $http_only);
}
}
}
\ No newline at end of file
<?php namespace Laravel\Session;
class File implements Driver, Sweeper {
class File extends Driver implements Sweeper {
/**
* Load a session by ID.
*
* @param string $id
* @return array
*/
public function load($id)
protected function load($id)
{
if (file_exists($path = SESSION_PATH.$id)) return unserialize(file_get_contents($path));
}
/**
* Save a session.
*
* @param array $session
* @return void
*/
public function save($session)
protected function save()
{
file_put_contents(SESSION_PATH.$session['id'], serialize($session), LOCK_EX);
file_put_contents(SESSION_PATH.$this->session['id'], serialize($this->session), LOCK_EX);
}
/**
* Delete a session by ID.
*
* @param string $id
* @return void
*/
public function delete($id)
protected function delete()
{
@unlink(SESSION_PATH.$id);
@unlink(SESSION_PATH.$this->session['id']);
}
/**
* Delete all expired sessions.
*
* @param int $expiration
* @return void
*/
public function sweep($expiration)
{
foreach (glob(SESSION_PATH.'*') as $file)
......
......@@ -3,39 +3,21 @@
use Laravel\Cache;
use Laravel\Config;
class Memcached implements Driver {
class Memcached extends Driver {
/**
* Load a session by ID.
*
* @param string $id
* @return array
*/
public function load($id)
protected function load($id)
{
return Cache::driver('memcached')->get($id);
}
/**
* Save a session.
*
* @param array $session
* @return void
*/
public function save($session)
protected function save()
{
Cache::driver('memcached')->put($session['id'], $session, Config::get('session.lifetime'));
Cache::driver('memcached')->put($this->session['id'], $this->session, Config::get('session.lifetime'));
}
/**
* Delete a session by ID.
*
* @param string $id
* @return void
*/
public function delete($id)
protected function delete()
{
Cache::driver('memcached')->forget($id);
Cache::driver('memcached')->forget($this->session['id']);
}
}
\ No newline at end of file
......@@ -3,7 +3,7 @@
interface Sweeper {
/**
* Delete all expired sessions.
* Delete all expired sessions from persistant storage.
*
* @param int $expiration
* @return void
......
......@@ -8,37 +8,49 @@
* @link http://laravel.com
*/
// --------------------------------------------------------------
// The active modules for this Laravel installation.
// --------------------------------------------------------------
$active = array();
// --------------------------------------------------------------
// The path to the Laravel directory.
// --------------------------------------------------------------
$system = '../laravel';
// --------------------------------------------------------------
// The path to the packages directory.
// --------------------------------------------------------------
/*
|--------------------------------------------------------------------------
| Active Modules
|--------------------------------------------------------------------------
|
| Modules are a convenient way to organize your application into logical
| components. Each module may have its own libraries, models, routes,
| views, language files, and configuration.
|
| Here you may specify which modules are active for your application.
| This simply gives Laravel an easy way to know which directories to
| check when auto-loading your classes, routes, and views.
|
*/
$active = array();
/*
|--------------------------------------------------------------------------
| Installation Paths
|--------------------------------------------------------------------------
|
| Here you may specify the location of the various Laravel framework
| directories for your installation.
|
| Of course, these are already set to the proper default values, so you do
| not need to change them if you have not modified the directory structure.
|
*/
$laravel = '../laravel';
$packages = '../packages';
// --------------------------------------------------------------
// The path to the modules directory.
// --------------------------------------------------------------
$modules = '../modules';
// --------------------------------------------------------------
// The path to the storage directory.
// --------------------------------------------------------------
$storage = '../storage';
// --------------------------------------------------------------
// The path to the public directory.
// --------------------------------------------------------------
$public = __DIR__;
// --------------------------------------------------------------
// Launch Laravel.
// --------------------------------------------------------------
require $system.'/laravel.php';
\ No newline at end of file
/*
|--------------------------------------------------------------------------
| 3... 2... 1... Lift-off!
|--------------------------------------------------------------------------
*/
require $laravel.'/laravel.php';
\ 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