initial commit of laravel!

This commit is contained in:
Taylor Otwell
2011-06-08 23:45:08 -05:00
commit a188d62105
70 changed files with 6942 additions and 0 deletions

135
system/auth.php Normal file
View File

@@ -0,0 +1,135 @@
<?php namespace System;
class Auth {
/**
* The current user of the application.
*
* @var object
*/
public static $user;
/**
* The key used to store the user ID in the session.
*
* @var string
*/
private static $key = 'laravel_user_id';
/**
* Determine if the current user of the application is authenticated.
*
* @return bool
*/
public static function check()
{
return ( ! is_null(static::user()));
}
/**
* Get the current user of the application.
*
* @return object
*/
public static function user()
{
// -----------------------------------------------------
// Verify that sessions are enabled.
// -----------------------------------------------------
if (Config::get('session.driver') == '')
{
throw new \Exception("You must specify a session driver before using the Auth class.");
}
// -----------------------------------------------------
// Get the authentication model.
// -----------------------------------------------------
$model = static::model();
// -----------------------------------------------------
// Load the user using the ID stored in the session.
// -----------------------------------------------------
if (is_null(static::$user) and Session::has(static::$key))
{
static::$user = $model::find(Session::get(static::$key));
}
return static::$user;
}
/**
* Attempt to login a user.
*
* @param string $username
* @param string $password
*/
public static function login($username, $password)
{
// -----------------------------------------------------
// Get the authentication model.
// -----------------------------------------------------
$model = static::model();
// -----------------------------------------------------
// Get the user by username.
// -----------------------------------------------------
$user = $model::where(Config::get('auth.username'), '=', $username)->first();
if ( ! is_null($user))
{
// -----------------------------------------------------
// Hash the password.
// -----------------------------------------------------
$password = (isset($user->salt)) ? Hash::make($password, $user->salt)->value : sha1($password);
// -----------------------------------------------------
// Verify that the passwords match.
// -----------------------------------------------------
if ($user->password == $password)
{
// -----------------------------------------------------
// Set the user property.
// -----------------------------------------------------
static::$user = $user;
// -----------------------------------------------------
// Store the user ID in the session.
// -----------------------------------------------------
Session::put(static::$key, $user->id);
return true;
}
}
return false;
}
/**
* Logout the current user of the application.
*
* @return void
*/
public static function logout()
{
// -----------------------------------------------------
// Remove the user ID from the session.
// -----------------------------------------------------
Session::forget(static::$key);
// -----------------------------------------------------
// Clear the current user variable.
// -----------------------------------------------------
static::$user = null;
}
/**
* Get the authentication model.
*
* @return string
*/
private static function model()
{
return '\\'.Config::get('auth.model');
}
}

49
system/benchmark.php Normal file
View File

@@ -0,0 +1,49 @@
<?php namespace System;
class Benchmark {
/**
* Benchmark starting times.
*
* @var array
*/
public static $marks = array();
/**
* Start a benchmark.
*
* @param string $name
* @return void
*/
public static function start($name)
{
static::$marks[$name] = microtime(true);
}
/**
* Get the elapsed time in milliseconds since starting a benchmark.
*
* @param string $name
* @return float
*/
public static function check($name)
{
if (array_key_exists($name, static::$marks))
{
return number_format((microtime(true) - static::$marks[$name]) * 1000, 2);
}
return 0.0;
}
/**
* Get the total memory usage in megabytes.
*
* @return float
*/
public static function memory()
{
return number_format(memory_get_usage() / 1024 / 1024, 2);
}
}

47
system/cache.php Normal file
View File

@@ -0,0 +1,47 @@
<?php namespace System;
class Cache {
/**
* The active cache drivers.
*
* @var Cache\Driver
*/
private static $drivers = array();
/**
* Get the cache driver instance.
*
* @param string $driver
* @return Cache\Driver
*/
public static function driver($driver = null)
{
if ( ! array_key_exists($driver, static::$drivers))
{
// --------------------------------------------------
// If no driver was specified, use the default.
// --------------------------------------------------
if (is_null($driver))
{
$driver = Config::get('cache.driver');
}
// --------------------------------------------------
// Create the cache driver.
// --------------------------------------------------
static::$drivers[$driver] = Cache\Factory::make($driver);
}
return static::$drivers[$driver];
}
/**
* Pass all other methods to the default driver.
*/
public static function __callStatic($method, $parameters)
{
return call_user_func_array(array(static::driver(), $method), $parameters);
}
}

40
system/cache/driver.php vendored Normal file
View File

@@ -0,0 +1,40 @@
<?php namespace System\Cache;
interface Driver {
/**
* Determine if an item exists in the cache.
*
* @param string $key
* @return bool
*/
public function has($key);
/**
* Get an item from the cache.
*
* @param string $key
* @param mixed $default
* @return mixed
*/
public function get($key, $default = null);
/**
* Write an item to the cache.
*
* @param string $key
* @param mixed $value
* @param int $minutes
* @return void
*/
public function put($key, $value, $minutes);
/**
* Delete an item from the cache.
*
* @param string $key
* @return void
*/
public function forget($key);
}

95
system/cache/driver/file.php vendored Normal file
View File

@@ -0,0 +1,95 @@
<?php namespace System\Cache\Driver;
class File implements \System\Cache\Driver {
/**
* All of the loaded cache items.
*
* @var array
*/
private $items = array();
/**
* Determine if an item exists in the cache.
*
* @param string $key
* @return bool
*/
public function has($key)
{
return ( ! is_null($this->get($key)));
}
/**
* Get an item from the cache.
*
* @param string $key
* @param mixed $default
* @return mixed
*/
public function get($key, $default = null)
{
// --------------------------------------------------
// If the item has already been loaded, return it.
// --------------------------------------------------
if (array_key_exists($key, $this->items))
{
return $this->items[$key];
}
// --------------------------------------------------
// Verify that the cache file exists.
// --------------------------------------------------
if ( ! file_exists(APP_PATH.'cache/'.$key))
{
return $default;
}
// --------------------------------------------------
// Read the contents of the cache file.
// --------------------------------------------------
$cache = file_get_contents(APP_PATH.'cache/'.$key);
// --------------------------------------------------
// Has the cache expired? The UNIX expiration time
// is stored at the beginning of the file.
// --------------------------------------------------
if (time() >= substr($cache, 0, 10))
{
$this->forget($key);
return $default;
}
return $this->items[$key] = unserialize(substr($cache, 10));
}
/**
* Write an item to the cache.
*
* @param string $key
* @param mixed $value
* @param int $minutes
* @return void
*/
public function put($key, $value, $minutes)
{
// --------------------------------------------------
// The expiration time is stored as a UNIX timestamp
// at the beginning of the cache file.
// --------------------------------------------------
file_put_contents(APP_PATH.'cache/'.$key, (time() + ($minutes * 60)).serialize($value), LOCK_EX);
}
/**
* Delete an item from the cache.
*
* @param string $key
* @return void
*/
public function forget($key)
{
@unlink(APP_PATH.'cache/'.$key);
}
}

80
system/cache/driver/memcached.php vendored Normal file
View File

@@ -0,0 +1,80 @@
<?php namespace System\Cache\Driver;
class Memcached implements \System\Cache\Driver {
/**
* All of the loaded cache items.
*
* @var array
*/
private $items = array();
/**
* Determine if an item exists in the cache.
*
* @param string $key
* @return bool
*/
public function has($key)
{
return ( ! is_null($this->get($key)));
}
/**
* Get an item from the cache.
*
* @param string $key
* @param mixed $default
* @return mixed
*/
public function get($key, $default = null)
{
// --------------------------------------------------
// If the item has already been loaded, return it.
// --------------------------------------------------
if (array_key_exists($key, $this->items))
{
return $this->items[$key];
}
// --------------------------------------------------
// Attempt to the get the item from cache.
// --------------------------------------------------
$cache = \System\Memcached::instance()->get(\System\Config::get('cache.key').$key);
// --------------------------------------------------
// Verify that the item was retrieved.
// --------------------------------------------------
if ($cache === false)
{
return $default;
}
return $this->items[$key] = $cache;
}
/**
* Write an item to the cache.
*
* @param string $key
* @param mixed $value
* @param int $minutes
* @return void
*/
public function put($key, $value, $minutes)
{
\System\Memcached::instance()->set(\System\Config::get('cache.key').$key, $value, 0, $minutes * 60);
}
/**
* Delete an item from the cache.
*
* @param string $key
* @return void
*/
public function forget($key)
{
\System\Memcached::instance()->delete(\System\Config::get('cache.key').$key);
}
}

26
system/cache/factory.php vendored Normal file
View File

@@ -0,0 +1,26 @@
<?php namespace System\Cache;
class Factory {
/**
* Create a cache driver instance.
*
* @param string $driver
* @return Driver
*/
public static function make($driver)
{
switch ($driver)
{
case 'file':
return new Driver\File;
case 'memcached':
return new Driver\Memcached;
default:
throw new \Exception("Cache driver [$driver] is not supported.");
}
}
}

118
system/config.php Normal file
View File

@@ -0,0 +1,118 @@
<?php namespace System;
class Config {
/**
* All of the loaded configuration items.
*
* @var array
*/
private static $items = array();
/**
* Get a configuration item.
*
* @param string $key
* @return mixed
*/
public static function get($key)
{
// ---------------------------------------------
// Parse the configuration key.
// ---------------------------------------------
list($file, $key) = static::parse($key);
// ---------------------------------------------
// Load the configuration file.
// ---------------------------------------------
static::load($file);
// ---------------------------------------------
// Return the requested item.
// ---------------------------------------------
return (array_key_exists($key, static::$items[$file])) ? static::$items[$file][$key] : null;
}
/**
* Set a configuration item.
*
* @param string $key
* @param mixed $value
* @return void
*/
public static function set($file, $value)
{
// ---------------------------------------------
// Parse the configuration key.
// ---------------------------------------------
list($file, $key) = static::parse($key);
// ---------------------------------------------
// Load the configuration file.
// ---------------------------------------------
static::load($file);
// ---------------------------------------------
// Set the item's value.
// ---------------------------------------------
static::$items[$file][$key] = $value;
}
/**
* Parse a configuration key.
*
* @param string $key
* @return array
*/
private static function parse($key)
{
// ---------------------------------------------
// Get the key segments.
// ---------------------------------------------
$segments = explode('.', $key);
// ---------------------------------------------
// Validate the key format.
// ---------------------------------------------
if (count($segments) < 2)
{
throw new \Exception("Invalid configuration key [$key].");
}
// ---------------------------------------------
// Return the file and item name.
// ---------------------------------------------
return array($segments[0], implode('.', array_slice($segments, 1)));
}
/**
* Load all of the configuration items.
*
* @param string $file
* @return void
*/
public static function load($file)
{
// ---------------------------------------------
// If the file has already been loaded, bail.
// ---------------------------------------------
if (array_key_exists($file, static::$items))
{
return;
}
// ---------------------------------------------
// Verify that the configuration file exists.
// ---------------------------------------------
if ( ! file_exists($path = APP_PATH.'config/'.$file.EXT))
{
throw new \Exception("Configuration file [$file] does not exist.");
}
// ---------------------------------------------
// Load the configuration file.
// ---------------------------------------------
static::$items[$file] = require $path;
}
}

78
system/cookie.php Normal file
View File

@@ -0,0 +1,78 @@
<?php namespace System;
class Cookie {
/**
* Determine if a cookie exists.
*
* @param string $key
* @return bool
*/
public static function has($key)
{
return ( ! is_null(static::get($key)));
}
/**
* Get the value of a cookie.
*
* @param string $key
* @param mixed $default
* @return string
*/
public static function get($key, $default = null)
{
return (array_key_exists($key, $_COOKIE)) ? $_COOKIE[$key] : $default;
}
/**
* Set a "permanent" cookie. The cookie will last 5 years.
*
* @param string $key
* @param string $value
* @param string $path
* @param string $domain
* @param bool $secure
* @return bool
*/
public static function forever($key, $value, $path = '/', $domain = null, $secure = false)
{
return static::put($key, $value, 2628000, $path, $domain, $secure);
}
/**
* Set the value of a cookie.
*
* @param string $key
* @param string $value
* @param int $minutes
* @param string $path
* @param string $domain
* @param bool $secure
* @return bool
*/
public static function put($key, $value, $minutes = 0, $path = '/', $domain = null, $secure = false)
{
// ----------------------------------------------------------
// If the lifetime is less than zero, delete the cookie.
// ----------------------------------------------------------
if ($minutes < 0)
{
unset($_COOKIE[$key]);
}
return setcookie($key, $value, ($minutes != 0) ? time() + ($minutes * 60) : 0, $path, $domain, $secure);
}
/**
* Delete a cookie.
*
* @param string $key
* @return bool
*/
public static function forget($key)
{
return static::put($key, null, -60);
}
}

132
system/crypt.php Normal file
View File

@@ -0,0 +1,132 @@
<?php namespace System;
class Crypt {
/**
* The encryption cipher.
*
* @var string
*/
public static $cipher = 'rijndael-256';
/**
* The encryption mode.
*
* @var string
*/
public static $mode = 'cbc';
/**
* Encrypt a value using the MCrypt library.
*
* @param string $value
* @return string
*/
public static function encrypt($value)
{
// -----------------------------------------------------
// Determine the input vector source.
// -----------------------------------------------------
if (defined('MCRYPT_DEV_URANDOM'))
{
$random = MCRYPT_DEV_URANDOM;
}
elseif (defined('MCRYPT_DEV_RANDOM'))
{
$random = MCRYPT_DEV_RANDOM;
}
else
{
$random = MCRYPT_RAND;
}
// -----------------------------------------------------
// The system random number generator must be seeded.
// -----------------------------------------------------
if ($random === MCRYPT_RAND)
{
mt_srand();
}
// -----------------------------------------------------
// Create the input vector.
// -----------------------------------------------------
$iv = mcrypt_create_iv(static::iv_size(), $random);
// -----------------------------------------------------
// Encrypt the value using MCrypt.
// -----------------------------------------------------
$value = mcrypt_encrypt(static::$cipher, static::key(), $value, static::$mode, $iv);
// -----------------------------------------------------
// Use base64 encoding to get a string value.
// -----------------------------------------------------
return base64_encode($iv.$value);
}
/**
* Decrypt a value using the MCrypt library.
*
* @param string $value
* @return string
*/
public static function decrypt($value)
{
// -----------------------------------------------------
// Decode the base64 value.
// -----------------------------------------------------
$value = base64_decode($value, true);
// -----------------------------------------------------
// Validate the base64 conversion.
// -----------------------------------------------------
if ( ! $value)
{
throw new \Exception('Decryption error. Input value is not valid base64 data.');
}
// -----------------------------------------------------
// Extract the input vector from the value.
// -----------------------------------------------------
$iv = substr($value, 0, static::iv_size());
// -----------------------------------------------------
// Remove the input vector from the value.
// -----------------------------------------------------
$value = substr($value, static::iv_size());
// -----------------------------------------------------
// Decrypt the value using MCrypt.
// -----------------------------------------------------
return rtrim(mcrypt_decrypt(static::$cipher, static::key(), $value, static::$mode, $iv), "\0");
}
/**
* Get the application key.
*
* @return string
*/
private static function key()
{
// -----------------------------------------------------
// Validate the application key.
// -----------------------------------------------------
if (is_null($key = Config::get('application.key')) or $key == '')
{
throw new \Exception("The encryption class can not be used without an encryption key.");
}
return $key;
}
/**
* Get the input vector size for the cipher and mode.
*
* @return int
*/
private static function iv_size()
{
return mcrypt_get_iv_size(static::$cipher, static::$mode);
}
}

111
system/db.php Normal file
View File

@@ -0,0 +1,111 @@
<?php namespace System;
class DB {
/**
* The active database connections.
*
* @var array
*/
private static $connections = array();
/**
* Get a database connection.
*
* @param string $connection
* @return PDO
*/
public static function connection($connection = null)
{
// ---------------------------------------------------
// If no connection was given, use the default.
// ---------------------------------------------------
if (is_null($connection))
{
$connection = Config::get('db.default');
}
// ---------------------------------------------------
// If we have already established this connection,
// simply return the existing connection.
// ---------------------------------------------------
if ( ! array_key_exists($connection, static::$connections))
{
// ---------------------------------------------------
// Get the database configurations.
// ---------------------------------------------------
$config = Config::get('db.connections');
// ---------------------------------------------------
// Verify the connection has been defined.
// ---------------------------------------------------
if ( ! array_key_exists($connection, $config))
{
throw new \Exception("Database connection [$connection] is not defined.");
}
// ---------------------------------------------------
// Establish the database connection.
// ---------------------------------------------------
static::$connections[$connection] = DB\Connector::connect((object) $config[$connection]);
}
return static::$connections[$connection];
}
/**
* Execute a SQL query against the connection.
*
* @param string $sql
* @param array $bindings
* @param string $connection
* @return mixed
*/
public static function query($sql, $bindings = array(), $connection = null)
{
// ---------------------------------------------------
// Create a new PDO statement from the SQL.
// ---------------------------------------------------
$query = static::connection($connection)->prepare($sql);
// ---------------------------------------------------
// Execute the query with the bindings.
// ---------------------------------------------------
$result = $query->execute($bindings);
// ---------------------------------------------------
// For SELECT statements, return the results in an
// array of stdClasses.
//
// For UPDATE and DELETE statements, return the number
// or rows affected by the query.
//
// For INSERT statements, return a boolean.
// ---------------------------------------------------
if (strpos(Str::upper($sql), 'SELECT') === 0)
{
return $query->fetchAll(\PDO::FETCH_CLASS, 'stdClass');
}
elseif (strpos(Str::upper($sql), 'UPDATE') === 0 or strpos(Str::upper($sql), 'DELETE') === 0)
{
return $query->rowCount();
}
else
{
return $result;
}
}
/**
* Begin a fluent query against a table.
*
* @param string $table
* @param string $connection
* @return Query
*/
public static function table($table, $connection = null)
{
return new DB\Query($table, $connection);
}
}

58
system/db/connector.php Normal file
View File

@@ -0,0 +1,58 @@
<?php namespace System\DB;
class Connector {
/**
* The PDO connection options.
*
* @var array
*/
public static $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,
);
/**
* Establish a PDO database connection.
*
* @param object $config
* @return PDO
*/
public static function connect($config)
{
// ---------------------------------------------------
// Establish a SQLite PDO connection.
// ---------------------------------------------------
if ($config->driver == 'sqlite')
{
return new \PDO('sqlite:'.APP_PATH.'db/'.$config->database.'.sqlite', null, null, static::$options);
}
// ---------------------------------------------------
// Establish a MySQL or Postgres PDO connection.
// ---------------------------------------------------
elseif ($config->driver == 'mysql' or $config->driver == 'pgsql')
{
$connection = new \PDO($config->driver.':host='.$config->host.';dbname='.$config->database, $config->username, $config->password, static::$options);
// ---------------------------------------------------
// Set the correct character set.
// ---------------------------------------------------
if (isset($config->charset))
{
$connection->prepare("SET NAMES '".$config->charset."'")->execute();
}
return $connection;
}
// ---------------------------------------------------
// If the driver isn't supported, bail out.
// ---------------------------------------------------
else
{
throw new \Exception('Database driver '.$config->driver.' is not supported.');
}
}
}

353
system/db/eloquent.php Normal file
View File

@@ -0,0 +1,353 @@
<?php namespace System\DB;
abstract class Eloquent {
/**
* Indicates if the model exists in the database.
*
* @var bool
*/
public $exists = false;
/**
* The model attributes.
*
* @var array
*/
public $attributes = array();
/**
* The model's dirty attributes.
*
* @var array
*/
public $dirty = array();
/**
* The model's ignored attributes.
*
* Ignored attributes will not be saved to the database, and
* are primarily used to hold relationships.
*
* @var array
*/
public $ignore = array();
/**
* The relationships that should be eagerly loaded.
*
* @var array
*/
public $includes = array();
/**
* The relationship type the model is currently resolving.
*
* @var string
*/
public $relating;
/**
* The foreign key of the "relating" relationship.
*
* @var string
*/
public $relating_key;
/**
* The table name of the model being resolved. Used during many-to-many eager loading.
*
* @var string
*/
public $relating_table;
/**
* The model query instance.
*
* @var Query
*/
public $query;
/**
* Create a new model instance and set the relationships
* that should be eagerly loaded.
*
* @return mixed
*/
public static function with()
{
// -----------------------------------------------------
// Create a new model instance.
// -----------------------------------------------------
$model = Eloquent\Factory::make(get_called_class());
// -----------------------------------------------------
// Set the eager relationships.
// -----------------------------------------------------
$model->includes = func_get_args();
return $model;
}
/**
* Get a model by the primary key.
*
* @param int $id
* @return mixed
*/
public static function find($id)
{
return Eloquent\Factory::make(get_called_class())->where('id', '=', $id)->first();
}
/**
* Get an array of models from the database.
*
* @return array
*/
private function _get()
{
return Eloquent\Hydrate::from($this);
}
/**
* Get the first model result
*
* @return mixed
*/
private function _first()
{
// -----------------------------------------------------
// Load the hydrated models.
// -----------------------------------------------------
$results = Eloquent\Hydrate::from($this->take(1));
// -----------------------------------------------------
// Return the first result.
// -----------------------------------------------------
if (count($results) > 0)
{
reset($results);
return current($results);
}
}
/**
* Retrieve the query for a 1:1 relationship.
*
* @param string $model
* @return mixed
*/
public function has_one($model)
{
return Eloquent\Relate::has_one($model, $this);
}
/**
* Retrieve the query for a 1:* relationship.
*
* @param string $model
* @return mixed
*/
public function has_many($model)
{
return Eloquent\Relate::has_many($model, $this);
}
/**
* Retrieve the query for a 1:1 belonging relationship.
*
* @param string $model
* @return mixed
*/
public function belongs_to($model)
{
// -----------------------------------------------------
// Get the calling function name.
// -----------------------------------------------------
list(, $caller) = debug_backtrace(false);
return Eloquent\Relate::belongs_to($caller, $model, $this);
}
/**
* Retrieve the query for a *:* relationship.
*
* @param string $model
* @return mixed
*/
public function has_many_and_belongs_to($model)
{
return Eloquent\Relate::has_many_and_belongs_to($model, $this);
}
/**
* Save the model to the database.
*
* @return void
*/
public function save()
{
Eloquent\Warehouse::store($this);
}
/**
* Magic method for retrieving model attributes.
*/
public function __get($key)
{
// -----------------------------------------------------
// Check the ignored attributes first.
// -----------------------------------------------------
if (array_key_exists($key, $this->ignore))
{
return $this->ignore[$key];
}
// -----------------------------------------------------
// Is the attribute actually a relationship?
// -----------------------------------------------------
if (method_exists($this, $key))
{
// -----------------------------------------------------
// Get the query / model for the relationship.
// -----------------------------------------------------
$model = $this->$key();
// -----------------------------------------------------
// Return the relationship results.
// -----------------------------------------------------
return ($this->relating == 'has_one' or $this->relating == 'belongs_to')
? $this->ignore[$key] = $model->first()
: $this->ignore[$key] = $model->get();
}
// -----------------------------------------------------
// Check the "regular" attributes.
// -----------------------------------------------------
return (array_key_exists($key, $this->attributes)) ? $this->attributes[$key] : null;
}
/**
* Magic Method for setting model attributes.
*/
public function __set($key, $value)
{
// -----------------------------------------------------
// Is the key actually a relationship?
// -----------------------------------------------------
if (method_exists($this, $key))
{
$this->ignore[$key] = $value;
}
else
{
// -----------------------------------------------------
// Add the value to the attributes.
// -----------------------------------------------------
$this->attributes[$key] = $value;
$this->dirty[$key] = $value;
}
}
/**
* Magic Method for determining if a model attribute is set.
*/
public function __isset($key)
{
return (array_key_exists($key, $this->attributes) or array_key_exists($key, $this->ignore));
}
/**
* Magic Method for unsetting model attributes.
*/
public function __unset($key)
{
unset($this->attributes[$key]);
unset($this->ignore[$key]);
unset($this->dirty[$key]);
}
/**
* Magic Method for handling dynamic method calls.
*/
public function __call($method, $parameters)
{
// -----------------------------------------------------
// Is the "get" method being called?
// -----------------------------------------------------
if ($method == 'get')
{
return $this->_get();
}
// -----------------------------------------------------
// Is the "first" method being called?
// -----------------------------------------------------
if ($method == 'first')
{
return $this->_first();
}
// -----------------------------------------------------
// If the method is an aggregate function, just return
// the aggregate value from the query.
// -----------------------------------------------------
if (in_array($method, array('count', 'sum', 'min', 'max', 'avg')))
{
return call_user_func_array(array($this->query, $method), $parameters);
}
// -----------------------------------------------------
// Pass the method call to the query instance.
// -----------------------------------------------------
call_user_func_array(array($this->query, $method), $parameters);
return $this;
}
/**
* Magic Method for handling dynamic static method calls.
*/
public static function __callStatic($method, $parameters)
{
// -----------------------------------------------------
// Create a new model instance.
// -----------------------------------------------------
$model = Eloquent\Factory::make(get_called_class());
// -----------------------------------------------------
// Do we need to return the entire table?
// -----------------------------------------------------
if ($method == 'get')
{
return $model->_get();
}
// -----------------------------------------------------
// Do we need to return the first model from the table?
// -----------------------------------------------------
if ($method == 'first')
{
return $model->_first();
}
// -----------------------------------------------------
// If the method is an aggregate function, just return
// the aggregate value from the query.
// -----------------------------------------------------
if (in_array($method, array('count', 'sum', 'min', 'max', 'avg')))
{
return call_user_func_array(array($model->query, $method), $parameters);
}
// -----------------------------------------------------
// Pass the method call to the query instance.
// -----------------------------------------------------
call_user_func_array(array($model->query, $method), $parameters);
return $model;
}
}

View File

@@ -0,0 +1,26 @@
<?php namespace System\DB\Eloquent;
class Factory {
/**
* Factory for creating new model instances.
*
* @param string $class
* @return object
*/
public static function make($class)
{
// -----------------------------------------------------
// Create a new model instance.
// -----------------------------------------------------
$model = new $class;
// -----------------------------------------------------
// Set the active query instance on the model.
// -----------------------------------------------------
$model->query = \System\DB\Query::table(Meta::table($class));
return $model;
}
}

View File

@@ -0,0 +1,272 @@
<?php namespace System\DB\Eloquent;
class Hydrate {
/**
* Load the array of hydrated models.
*
* @param object $eloquent
* @return array
*/
public static function from($eloquent)
{
// -----------------------------------------------------
// Load the base models.
// -----------------------------------------------------
$results = static::base(get_class($eloquent), $eloquent->query->get());
// -----------------------------------------------------
// Load all of the eager relationships.
// -----------------------------------------------------
if (count($results) > 0)
{
foreach ($eloquent->includes as $include)
{
// -----------------------------------------------------
// Verify the relationship is defined.
// -----------------------------------------------------
if ( ! method_exists($eloquent, $include))
{
throw new \Exception("Attempting to eager load [$include], but the relationship is not defined.");
}
// -----------------------------------------------------
// Eagerly load the relationship.
// -----------------------------------------------------
static::eagerly($eloquent, $include, $results);
}
}
return $results;
}
/**
* Hydrate the base models for a query.
*
* @param string $class
* @param array $models
* @return array
*/
private static function base($class, $models)
{
// -----------------------------------------------------
// Initialize the hydrated model array.
// -----------------------------------------------------
$results = array();
// -----------------------------------------------------
// Hydrate the models from the results.
// -----------------------------------------------------
foreach ($models as $model)
{
// -----------------------------------------------------
// Instantiate a new model instance.
// -----------------------------------------------------
$result = new $class;
// -----------------------------------------------------
// Set the model's attributes.
// -----------------------------------------------------
$result->attributes = (array) $model;
// -----------------------------------------------------
// Indicate that the model already exists.
// -----------------------------------------------------
$result->exists = true;
// -----------------------------------------------------
// Add the hydrated model to the array of models.
// The array is keyed by the primary keys of the models.
// -----------------------------------------------------
$results[$result->id] = $result;
}
return $results;
}
/**
* Eagerly load a relationship.
*
* @param object $eloquent
* @param string $include
* @param array $results
* @return void
*/
private static function eagerly($eloquent, $include, &$results)
{
// -----------------------------------------------------
// Get the relationship Eloquent model.
//
// We spoof the "belongs_to" key to allow the query
// to be fetched without any problems.
// -----------------------------------------------------
$eloquent->attributes[$spoof = $include.'_id'] = 0;
$model = $eloquent->$include();
unset($eloquent->attributes[$spoof]);
// -----------------------------------------------------
// Reset the WHERE clause on the query.
// -----------------------------------------------------
$model->query->where = 'WHERE 1 = 1';
// -----------------------------------------------------
// Reset the bindings on the query.
// -----------------------------------------------------
$model->query->bindings = array();
// -----------------------------------------------------
// Initialize the relationship on the parent models.
// -----------------------------------------------------
foreach ($results as &$result)
{
$result->ignore[$include] = (strpos($eloquent->relating, 'has_many') === 0) ? array() : null;
}
// -----------------------------------------------------
// Eagerly load a 1:1 or 1:* relationship.
// -----------------------------------------------------
if ($eloquent->relating == 'has_one' or $eloquent->relating == 'has_many')
{
static::eagerly_load_one_or_many($eloquent->relating_key, $eloquent->relating, $include, $model, $results);
}
// -----------------------------------------------------
// Eagerly load a 1:1 (belonging) relationship.
// -----------------------------------------------------
elseif ($eloquent->relating == 'belongs_to')
{
static::eagerly_load_belonging($eloquent->relating_key, $include, $model, $results);
}
// -----------------------------------------------------
// Eagerly load a *:* relationship.
// -----------------------------------------------------
else
{
static::eagerly_load_many_to_many($eloquent->relating_key, $eloquent->relating_table, strtolower(get_class($eloquent)).'_id', $include, $model, $results);
}
}
/**
* Eagerly load a 1:1 or 1:* relationship.
*
* @param string $relating_key
* @param string $relating
* @param string $include
* @param object $model
* @param array $results
* @return void
*/
private static function eagerly_load_one_or_many($relating_key, $relating, $include, $model, &$results)
{
// -----------------------------------------------------
// Get the related models.
// -----------------------------------------------------
$inclusions = $model->where_in($relating_key, array_keys($results))->get();
// -----------------------------------------------------
// Match the child models with their parent.
// -----------------------------------------------------
foreach ($inclusions as $key => $inclusion)
{
if ($relating == 'has_one')
{
$results[$inclusion->$relating_key]->ignore[$include] = $inclusion;
}
else
{
$results[$inclusion->$relating_key]->ignore[$include][$inclusion->id] = $inclusion;
}
}
}
/**
* Eagerly load a 1:1 belonging relationship.
*
* @param string $relating_key
* @param string $include
* @param object $model
* @param array $results
* @return void
*/
private static function eagerly_load_belonging($relating_key, $include, $model, &$results)
{
// -----------------------------------------------------
// Gather the keys from the parent models.
// -----------------------------------------------------
$keys = array();
foreach ($results as &$result)
{
$keys[] = $result->$relating_key;
}
// -----------------------------------------------------
// Get the related models.
// -----------------------------------------------------
$inclusions = $model->where_in('id', array_unique($keys))->get();
// -----------------------------------------------------
// Match the child models with their parent.
// -----------------------------------------------------
foreach ($results as &$result)
{
$result->ignore[$include] = $inclusions[$result->$relating_key];
}
}
/**
* Eagerly load a many-to-many relationship.
*
* @param string $relating_key
* @param string $relating_table
* @param string $foreign_key
* @param string $include
* @param object $model
* @param array $results
* @return void
*/
private static function eagerly_load_many_to_many($relating_key, $relating_table, $foreign_key, $include, $model, &$results)
{
// -----------------------------------------------------
// Reset the SELECT clause.
// -----------------------------------------------------
$model->query->select = null;
// -----------------------------------------------------
// Retrieve the raw results as stdClasses.
//
// We also add the foreign key to the select which will allow us
// to match the models back to their parents.
// -----------------------------------------------------
$inclusions = $model->query->where_in($relating_key, array_keys($results))->get(Meta::table(get_class($model)).'.*', $relating_table.'.'.$foreign_key);
// -----------------------------------------------------
// Get the class name of the related model.
// -----------------------------------------------------
$class = get_class($model);
// -----------------------------------------------------
// Create the related models.
// -----------------------------------------------------
foreach ($inclusions as $inclusion)
{
$related = new $class;
$related->exists = true;
$related->attributes = (array) $inclusion;
// -----------------------------------------------------
// Remove the foreign key from the attributes since it
// was only added to the query to help us match the models.
// -----------------------------------------------------
unset($related->attributes[$foreign_key]);
// -----------------------------------------------------
// Add the related model to the parent model's array.
// -----------------------------------------------------
$results[$inclusion->$foreign_key]->ignore[$include][$inclusion->id] = $related;
}
}
}

View File

@@ -0,0 +1,24 @@
<?php namespace System\DB\Eloquent;
class Meta {
/**
* Get the table name for a model.
*
* @param string $class
* @return string
*/
public static function table($class)
{
// -----------------------------------------------------
// Check for a table name override.
// -----------------------------------------------------
if (property_exists($class, 'table'))
{
return $class::$table;
}
return \System\Str::lower(\System\Inflector::plural($class));
}
}

View File

@@ -0,0 +1,132 @@
<?php namespace System\DB\Eloquent;
class Relate {
/**
* Retrieve the query for a 1:1 relationship.
*
* @param string $model
* @param object $eloquent
* @return mixed
*/
public static function has_one($model, $eloquent)
{
// -----------------------------------------------------
// Set the relating type.
// -----------------------------------------------------
$eloquent->relating = __FUNCTION__;
// -----------------------------------------------------
// Return the Eloquent model.
// -----------------------------------------------------
return static::has_one_or_many($model, $eloquent);
}
/**
* Retrieve the query for a 1:* relationship.
*
* @param string $model
* @param object $eloquent
* @return mixed
*/
public static function has_many($model, $eloquent)
{
// -----------------------------------------------------
// Set the relating type.
// -----------------------------------------------------
$eloquent->relating = __FUNCTION__;
// -----------------------------------------------------
// Return the Eloquent model.
// -----------------------------------------------------
return static::has_one_or_many($model, $eloquent);
}
/**
* Retrieve the query for a 1:1 or 1:* relationship.
*
* @param string $model
* @param object $eloquent
* @return mixed
*/
private static function has_one_or_many($model, $eloquent)
{
// -----------------------------------------------------
// Set the relating key.
// -----------------------------------------------------
$eloquent->relating_key = \System\Str::lower(get_class($eloquent)).'_id';
return Factory::make($model)->where($eloquent->relating_key, '=', $eloquent->id);
}
/**
* Retrieve the query for a 1:1 belonging relationship.
*
* @param array $caller
* @param string $model
* @param object $eloquent
* @return mixed
*/
public static function belongs_to($caller, $model, $eloquent)
{
// -----------------------------------------------------
// Set the relating type.
// -----------------------------------------------------
$eloquent->relating = __FUNCTION__;
// -----------------------------------------------------
// Set the relating key.
// -----------------------------------------------------
$eloquent->relating_key = $caller['function'].'_id';
// -----------------------------------------------------
// Return the Eloquent model.
// -----------------------------------------------------
return Factory::make($model)->where('id', '=', $eloquent->attributes[$eloquent->relating_key]);
}
/**
* Retrieve the query for a *:* relationship.
*
* @param string $model
* @param object $eloquent
* @return mixed
*/
public static function has_many_and_belongs_to($model, $eloquent)
{
// -----------------------------------------------------
// Get the models involved in the relationship.
// -----------------------------------------------------
$models = array(\System\Str::lower($model), \System\Str::lower(get_class($eloquent)));
// -----------------------------------------------------
// Sort the model names involved in the relationship.
// -----------------------------------------------------
sort($models);
// -----------------------------------------------------
// Get the intermediate table name, which is the names
// of the two related models alphabetized.
// -----------------------------------------------------
$eloquent->relating_table = implode('_', $models);
// -----------------------------------------------------
// Set the relating type.
// -----------------------------------------------------
$eloquent->relating = __FUNCTION__;
// -----------------------------------------------------
// Set the relating key.
// -----------------------------------------------------
$eloquent->relating_key = $eloquent->relating_table.'.'.\System\Str::lower(get_class($eloquent)).'_id';
// -----------------------------------------------------
// Return the Eloquent model.
// -----------------------------------------------------
return Factory::make($model)
->select(Meta::table($model).'.*')
->join($eloquent->relating_table, Meta::table($model).'.id', '=', $eloquent->relating_table.'.'.\System\Str::lower($model).'_id')
->where($eloquent->relating_key, '=', $eloquent->id);
}
}

View File

@@ -0,0 +1,66 @@
<?php namespace System\DB\Eloquent;
class Warehouse {
/**
* Save an Eloquent model to the database.
*
* @param object $eloquent
* @return void
*/
public static function store($eloquent)
{
// -----------------------------------------------------
// Get the model name.
// -----------------------------------------------------
$model = get_class($eloquent);
// -----------------------------------------------------
// Get a fresh query instance for the model.
// -----------------------------------------------------
$eloquent->query = \System\DB\Query::table(Meta::table($model));
// -----------------------------------------------------
// Set the activity timestamps.
// -----------------------------------------------------
if (property_exists($model, 'timestamps') and $model::$timestamps)
{
static::timestamp($eloquent);
}
// -----------------------------------------------------
// If the model exists in the database, update it.
// Otherwise, insert the model and set the ID.
// -----------------------------------------------------
if ($eloquent->exists)
{
return $eloquent->query->where('id', '=', $eloquent->attributes['id'])->update($eloquent->dirty);
}
else
{
$eloquent->attributes['id'] = $eloquent->query->insert_get_id($eloquent->attributes);
}
// -----------------------------------------------------
// Set the existence flag to true.
// -----------------------------------------------------
$eloquent->exists = true;
}
/**
* Set the activity timestamps on a model.
*
* @param object $eloquent
* @return void
*/
private static function timestamp($eloquent)
{
$eloquent->updated_at = date('Y-m-d H:i:s');
if ( ! $eloquent->exists)
{
$eloquent->created_at = $eloquent->updated_at;
}
}
}

593
system/db/query.php Normal file
View File

@@ -0,0 +1,593 @@
<?php namespace System\DB;
class Query {
/**
* The database connection name.
*
* @var string
*/
private $connection;
/**
* The SELECT clause.
*
* @var string
*/
public $select;
/**
* Indicates if the query should return distinct results.
*
* @var bool
*/
public $distinct = false;
/**
* The FROM clause.
*
* @var string
*/
public $from;
/**
* The table name.
*
* @var string
*/
public $table;
/**
* The WHERE clause.
*
* @var string
*/
public $where = 'WHERE 1 = 1';
/**
* The ORDER BY columns.
*
* @var array
*/
public $orderings = array();
/**
* The LIMIT value.
*
* @var int
*/
public $limit;
/**
* The OFFSET value.
*
* @var int
*/
public $offset;
/**
* The query value bindings.
*
* @var array
*/
public $bindings = array();
/**
* Create a new query instance.
*
* @param string $table
* @param string $connection
* @return void
*/
public function __construct($table, $connection = null)
{
// ---------------------------------------------------
// Set the database connection name.
// ---------------------------------------------------
$this->connection = (is_null($connection)) ? \System\Config::get('db.default') : $connection;
// ---------------------------------------------------
// Build the FROM clause.
// ---------------------------------------------------
$this->from = 'FROM '.$this->wrap($this->table = $table);
}
/**
* Create a new query instance.
*
* @param string $table
* @param string $connection
* @return Query
*/
public static function table($table, $connection = null)
{
return new static($table, $connection);
}
/**
* Force the query to return distinct results.
*
* @return Query
*/
public function distinct()
{
$this->distinct = true;
return $this;
}
/**
* Add columns to the SELECT clause.
*
* @return Query
*/
public function select()
{
// ---------------------------------------------------
// Handle DISTINCT selections.
// ---------------------------------------------------
$this->select = ($this->distinct) ? 'SELECT DISTINCT ' : 'SELECT ';
// ---------------------------------------------------
// Wrap all of the columns in keyword identifiers.
// ---------------------------------------------------
$this->select .= implode(', ', array_map(array($this, 'wrap'), func_get_args()));
return $this;
}
/**
* Add a join to the query.
*
* @param string $table
* @param string $column1
* @param string $operator
* @param string $column2
* @param string $type
* @return Query
*/
public function join($table, $column1, $operator, $column2, $type = 'INNER')
{
$this->from .= ' '.$type.' JOIN '.$this->wrap($table).' ON '.$this->wrap($column1).' '.$operator.' '.$this->wrap($column2);
return $this;
}
/**
* Add a left join to the query.
*
* @param string $table
* @param string $column1
* @param string $operator
* @param string $column2
* @return Query
*/
public function left_join($table, $column1, $operator, $column2)
{
return $this->join($table, $column1, $operator, $column2, 'LEFT');
}
/**
* Add a raw where condition to the query.
*
* @param string $where
* @param array $bindings
* @param string $connector
* @return Query
*/
public function raw_where($where, $bindings = array(), $connector = 'AND')
{
$this->where .= ' '.$connector.' '.$where;
$this->bindings = array_merge($this->bindings, $bindings);
return $this;
}
/**
* Add a raw or where condition to the query.
*
* @param string $where
* @param array $bindings
* @return Query
*/
public function raw_or_where($where, $bindings = array())
{
return $this->raw_where($where, $bindings, 'OR');
}
/**
* Add a where condition to the query.
*
* @param string $column
* @param string $operator
* @param mixed $value
* @param string $connector
* @return Query
*/
public function where($column, $operator, $value, $connector = 'AND')
{
$this->where .= ' '.$connector.' '.$this->wrap($column).' '.$operator.' ?';
$this->bindings[] = $value;
return $this;
}
/**
* Add an or where condition to the query.
*
* @param string $column
* @param string $operator
* @param mixed $value
* @return Query
*/
public function or_where($column, $operator, $value)
{
return $this->where($column, $operator, $value, 'OR');
}
/**
* Add a where in condition to the query.
*
* @param string $column
* @param array $values
* @param string $connector
* @return Query
*/
public function where_in($column, $values, $connector = 'AND')
{
$this->where .= ' '.$connector.' '.$this->wrap($column).' IN ('.$this->parameterize($values).')';
$this->bindings = array_merge($this->bindings, $values);
return $this;
}
/**
* Add an or where in condition to the query.
*
* @param string $column
* @param array $values
* @return Query
*/
public function or_where_in($column, $values)
{
return $this->where_in($column, $values, 'OR');
}
/**
* Add a where not in condition to the query.
*
* @param string $column
* @param array $values
* @param string $connector
* @return Query
*/
public function where_not_in($column, $values, $connector = 'AND')
{
$this->where .= ' '.$connector.' '.$this->wrap($column).' NOT IN ('.$this->parameterize($values).')';
$this->bindings = array_merge($this->bindings, $values);
return $this;
}
/**
* Add an or where not in condition to the query.
*
* @param string $column
* @param array $values
* @return Query
*/
public function or_where_not_in($column, $values)
{
return $this->where_not_in($column, $values, 'OR');
}
/**
* Add a where null condition to the query.
*
* @param string $column
* @param string $connector
* @return Query
*/
public function where_null($column, $connector = 'AND')
{
$this->where .= ' '.$connector.' '.$this->wrap($column).' IS NULL';
return $this;
}
/**
* Add an or where null condition to the query.
*
* @param string $column
* @return Query
*/
public function or_where_null($column)
{
return $this->where_null($column, 'OR');
}
/**
* Add a where not null condition to the query.
*
* @param string $column
* @param string $connector
* @return Query
*/
public function where_not_null($column, $connector = 'AND')
{
$this->where .= ' '.$connector.' '.$this->wrap($column).' IS NOT NULL';
return $this;
}
/**
* Add an or where not null condition to the query.
*
* @param string $column
* @return Query
*/
public function or_where_not_null($column)
{
return $this->where_not_null($column, 'OR');
}
/**
* Add an ordering to the query.
*
* @param string $column
* @param string $direction
* @return Query
*/
public function order_by($column, $direction)
{
$this->orderings[] = $this->wrap($column).' '.\System\Str::upper($direction);
return $this;
}
/**
* Set the query offset.
*
* @param int $value
* @return Query
*/
public function skip($value)
{
$this->offset = $value;
return $this;
}
/**
* Set the query limit.
*
* @param int $value
* @return Query
*/
public function take($value)
{
$this->limit = $value;
return $this;
}
/**
* Find a record by the primary key.
*
* @param int $id
* @return object
*/
public function find($id)
{
// ---------------------------------------------------
// Set the primary key.
// ---------------------------------------------------
$this->where('id', '=', $id);
// ---------------------------------------------------
// Get the first result.
// ---------------------------------------------------
return $this->first();
}
/**
* Execute the query as a SELECT statement and return the first result.
*
* @return object
*/
public function first()
{
return (count($results = call_user_func_array(array($this->take(1), 'get'), func_get_args())) > 0) ? $results[0] : null;
}
/**
* Execute the query as a SELECT statement.
*
* @return array
*/
public function get()
{
// ---------------------------------------------------
// Initialize the SELECT clause if it's null.
// ---------------------------------------------------
if (is_null($this->select))
{
call_user_func_array(array($this, 'select'), (count(func_get_args()) > 0) ? func_get_args() : array('*'));
}
return \System\DB::query(Query\Compiler::select($this), $this->bindings, $this->connection);
}
/**
* Get an aggregate value.
*
* @param string $aggregate
* @param string $column
* @return mixed
*/
private function aggregate($aggregator, $column)
{
// ---------------------------------------------------
// Build the SELECT clause.
// ---------------------------------------------------
$this->select = 'SELECT '.$aggregator.'('.$this->wrap($column).') AS '.$this->wrap('aggregate');
// ---------------------------------------------------
// Execute the statement.
// ---------------------------------------------------
$results = \System\DB::query(Query\Compiler::select($this), $this->bindings);
return $results[0]->aggregate;
}
/**
* Execute an INSERT statement.
*
* @param array $values
* @return bool
*/
public function insert($values)
{
return \System\DB::query(Query\Compiler::insert($this, $values), array_values($values), $this->connection);
}
/**
* Execute an INSERT statement and get the insert ID.
*
* @param array $values
* @return int
*/
public function insert_get_id($values)
{
// ---------------------------------------------------
// Compile the SQL statement.
// ---------------------------------------------------
$sql = Query\Compiler::insert($this, $values);
// ---------------------------------------------------
// The Postgres PDO implementation does not cleanly
// implement the last insert ID function. So, we'll
// use the RETURNING clause available in Postgres.
// ---------------------------------------------------
if (\System\DB::connection($this->connection)->getAttribute(\PDO::ATTR_DRIVER_NAME) == 'pgsql')
{
// ---------------------------------------------------
// Add the RETURNING clause to the SQL.
// ---------------------------------------------------
$sql .= ' RETURNING '.$this->wrap('id');
// ---------------------------------------------------
// Prepare the PDO statement.
// ---------------------------------------------------
$query = \System\DB::connection($this->connection)->prepare($sql);
// ---------------------------------------------------
// Execute the PDO statement.
// ---------------------------------------------------
$query->execute(array_values($values));
// ---------------------------------------------------
// Fetch the insert ID from the results.
// ---------------------------------------------------
$result = $query->fetch(\PDO::FETCH_ASSOC);
return $result['id'];
}
// ---------------------------------------------------
// When using MySQL or SQLite, we can just use the PDO
// last insert ID function.
// ---------------------------------------------------
else
{
// ---------------------------------------------------
// Execute the statement.
// ---------------------------------------------------
\System\DB::query($sql, array_values($values), $this->connection);
// ---------------------------------------------------
// Get the last insert ID.
// ---------------------------------------------------
return \System\DB::connection($this->connection)->lastInsertId();
}
}
/**
* Execute the query as an UPDATE statement.
*
* @param array $values
* @return bool
*/
public function update($values)
{
return \System\DB::query(Query\Compiler::update($this, $values), array_merge(array_values($values), $this->bindings), $this->connection);
}
/**
* Execute the query as a DELETE statement.
*
* @param int $id
* @return bool
*/
public function delete($id = null)
{
// ---------------------------------------------------
// Set the primary key.
// ---------------------------------------------------
if ( ! is_null($id))
{
$this->where('id', '=', $id);
}
// ---------------------------------------------------
// Execute the statement.
// ---------------------------------------------------
return \System\DB::query(Query\Compiler::delete($this), $this->bindings, $this->connection);
}
/**
* Wrap a value in keyword identifiers.
*
* @param string $value
* @param string $wrap
* @return string
*/
public function wrap($value, $wrap = '"')
{
// ---------------------------------------------------
// If the application is using MySQL, we need to use
// a non-standard keyword identifier.
// ---------------------------------------------------
if (\System\DB::connection($this->connection)->getAttribute(\PDO::ATTR_DRIVER_NAME) == 'mysql')
{
$wrap = '`';
}
// ---------------------------------------------------
// Wrap the element in keyword identifiers.
// ---------------------------------------------------
return implode('.', array_map(function($segment) use ($wrap) {return ($segment != '*') ? $wrap.$segment.$wrap : $segment;}, explode('.', $value)));
}
/**
* Create query parameters from an array of values.
*
* @param array $values
* @return string
*/
public function parameterize($values)
{
return implode(', ', array_fill(0, count($values), '?'));
}
/**
* Magic Method for handling dynamic functions.
*/
public function __call($method, $parameters)
{
// ---------------------------------------------------
// Handle any of the aggregate functions.
// ---------------------------------------------------
if (in_array($method, array('count', 'min', 'max', 'avg', 'sum')))
{
return ($method == 'count') ? $this->aggregate(\System\Str::upper($method), '*') : $this->aggregate(\System\Str::upper($method), $parameters[0]);
}
else
{
throw new \Exception("Method [$method] is not defined on the Query class.");
}
}
}

View File

@@ -0,0 +1,116 @@
<?php namespace System\DB\Query;
class Compiler {
/**
* Build a SQL SELECT statement.
*
* @param Query $query
* @return string
*/
public static function select($query)
{
// ---------------------------------------------------
// Add the SELECT, FROM, and WHERE clauses.
// ---------------------------------------------------
$sql = $query->select.' '.$query->from.' '.$query->where;
// ---------------------------------------------------
// Add the ORDER BY clause.
// ---------------------------------------------------
if (count($query->orderings) > 0)
{
$sql .= ' ORDER BY '.implode(', ', $query->orderings);
}
// ---------------------------------------------------
// Add the LIMIT.
// ---------------------------------------------------
if ( ! is_null($query->limit))
{
$sql .= ' LIMIT '.$query->limit;
}
// ---------------------------------------------------
// Add the OFFSET.
// ---------------------------------------------------
if ( ! is_null($query->offset))
{
$sql .= ' OFFSET '.$query->offset;
}
return $sql;
}
/**
* Build a SQL INSERT statement.
*
* @param Query $query
* @param array $values
* @return string
*/
public static function insert($query, $values)
{
// ---------------------------------------------------
// Start the query. Add the table name.
// ---------------------------------------------------
$sql = 'INSERT INTO '.$query->table.' (';
// ---------------------------------------------------
// Wrap each column name in keyword identifiers.
// ---------------------------------------------------
$columns = array();
foreach (array_keys($values) as $column)
{
$columns[] = $query->wrap($column);
}
// ---------------------------------------------------
// Concatenate the column names and values.
// ---------------------------------------------------
return $sql .= implode(', ', $columns).') VALUES ('.$query->parameterize($values).')';
}
/**
* Build a SQL UPDATE statement.
*
* @param Query $query
* @param array $values
* @return string
*/
public static function update($query, $values)
{
// ---------------------------------------------------
// Start the query. Add the table name.
// ---------------------------------------------------
$sql = 'UPDATE '.$query->table.' SET ';
// ---------------------------------------------------
// Wrap each column name in keyword identifiers.
// ---------------------------------------------------
$columns = array();
foreach (array_keys($values) as $column)
{
$columns[] = $query->wrap($column).' = ?';
}
// ---------------------------------------------------
// Concatenate the column names and the WHERE clause.
// ---------------------------------------------------
return $sql .= implode(', ', $columns).' '.$query->where;
}
/**
* Build a SQL DELETE statement.
*
* @param Query $query
* @return string
*/
public static function delete($query)
{
return 'DELETE FROM '.$query->wrap($query->table).' '.$query->where;
}
}

145
system/download.php Normal file
View File

@@ -0,0 +1,145 @@
<?php namespace System;
class Download {
/**
* Extensions and their matching MIME types.
*
* @var array
*/
public static $mimes = array(
'hqx' => 'application/mac-binhex40',
'cpt' => 'application/mac-compactpro',
'csv' => 'text/x-comma-separated-values',
'bin' => 'application/macbinary',
'dms' => 'application/octet-stream',
'lha' => 'application/octet-stream',
'lzh' => 'application/octet-stream',
'exe' => 'application/octet-stream',
'class' => 'application/octet-stream',
'psd' => 'application/x-photoshop',
'so' => 'application/octet-stream',
'sea' => 'application/octet-stream',
'dll' => 'application/octet-stream',
'oda' => 'application/oda',
'pdf' => 'application/pdf',
'ai' => 'application/postscript',
'eps' => 'application/postscript',
'ps' => 'application/postscript',
'smi' => 'application/smil',
'smil' => 'application/smil',
'mif' => 'application/vnd.mif',
'xls' => 'application/excel',
'ppt' => 'application/powerpoint',
'wbxml' => 'application/wbxml',
'wmlc' => 'application/wmlc',
'dcr' => 'application/x-director',
'dir' => 'application/x-director',
'dxr' => 'application/x-director',
'dvi' => 'application/x-dvi',
'gtar' => 'application/x-gtar',
'gz' => 'application/x-gzip',
'php' => 'application/x-httpd-php',
'php4' => 'application/x-httpd-php',
'php3' => 'application/x-httpd-php',
'phtml' => 'application/x-httpd-php',
'phps' => 'application/x-httpd-php-source',
'js' => 'application/x-javascript',
'swf' => 'application/x-shockwave-flash',
'sit' => 'application/x-stuffit',
'tar' => 'application/x-tar',
'tgz' => 'application/x-tar',
'xhtml' => 'application/xhtml+xml',
'xht' => 'application/xhtml+xml',
'zip' => 'application/x-zip',
'mid' => 'audio/midi',
'midi' => 'audio/midi',
'mpga' => 'audio/mpeg',
'mp2' => 'audio/mpeg',
'mp3' => 'audio/mpeg',
'aif' => 'audio/x-aiff',
'aiff' => 'audio/x-aiff',
'aifc' => 'audio/x-aiff',
'ram' => 'audio/x-pn-realaudio',
'rm' => 'audio/x-pn-realaudio',
'rpm' => 'audio/x-pn-realaudio-plugin',
'ra' => 'audio/x-realaudio',
'rv' => 'video/vnd.rn-realvideo',
'wav' => 'audio/x-wav',
'bmp' => 'image/bmp',
'gif' => 'image/gif',
'jpeg' => 'image/jpeg',
'jpg' => 'image/jpeg',
'jpe' => 'image/jpeg',
'png' => 'image/png',
'tiff' => 'image/tiff',
'tif' => 'image/tiff',
'css' => 'text/css',
'html' => 'text/html',
'htm' => 'text/html',
'shtml' => 'text/html',
'txt' => 'text/plain',
'text' => 'text/plain',
'log' => 'text/plain',
'rtx' => 'text/richtext',
'rtf' => 'text/rtf',
'xml' => 'text/xml',
'xsl' => 'text/xml',
'mpeg' => 'video/mpeg',
'mpg' => 'video/mpeg',
'mpe' => 'video/mpeg',
'qt' => 'video/quicktime',
'mov' => 'video/quicktime',
'avi' => 'video/x-msvideo',
'movie' => 'video/x-sgi-movie',
'doc' => 'application/msword',
'docx' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
'xlsx' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
'word' => 'application/msword',
'xl' => 'application/excel',
'eml' => 'message/rfc822'
);
/**
* Create a download response.
*
* @param string $path
* @param string $name
* @return Response
*/
public static function file($path, $name = null)
{
// -------------------------------------------------
// If no name was specified, just use the basename.
// -------------------------------------------------
if (is_null($name))
{
$name = basename($path);
}
// -------------------------------------------------
// Set the headers to force the download to occur.
// -------------------------------------------------
return Response::make(file_get_contents($path))->header('Content-Description', 'File Transfer')
->header('Content-Type', static::mime(pathinfo($path, PATHINFO_EXTENSION)))
->header('Content-Disposition', 'attachment; filename="'.$name.'"')
->header('Content-Transfer-Encoding', 'binary')
->header('Expires', 0)
->header('Cache-Control', 'must-revalidate, post-check=0, pre-check=0')
->header('Pragma', 'public')
->header('Content-Length', filesize($path));
}
/**
* Get a MIME type by extension.
*
* @param string $extension
* @param string $default
* @return string
*/
public static function mime($extension, $default = 'application/octet-stream')
{
return (array_key_exists($extension, static::$mimes)) ? static::$mimes[$extension] : $default;
}
}

156
system/error.php Normal file
View File

@@ -0,0 +1,156 @@
<?php namespace System;
class Error {
/**
* Error levels.
*
* @var array
*/
public static $levels = array(
0 => 'Error',
E_ERROR => 'Error',
E_WARNING => 'Warning',
E_PARSE => 'Parsing Error',
E_NOTICE => 'Notice',
E_CORE_ERROR => 'Core Error',
E_CORE_WARNING => 'Core Warning',
E_COMPILE_ERROR => 'Compile Error',
E_COMPILE_WARNING => 'Compile Warning',
E_USER_ERROR => 'User Error',
E_USER_WARNING => 'User Warning',
E_USER_NOTICE => 'User Notice',
E_STRICT => 'Runtime Notice'
);
/**
* Handle an exception.
*
* @param Exception $e
* @return void
*/
public static function handle($e)
{
// -----------------------------------------------------
// Clean the output buffer.
// -----------------------------------------------------
if (ob_get_level() > 0)
{
ob_clean();
}
// -----------------------------------------------------
// Get the error severity.
// -----------------------------------------------------
$severity = (array_key_exists($e->getCode(), static::$levels)) ? static::$levels[$e->getCode()] : $e->getCode();
// -----------------------------------------------------
// Get the error file. Views require special handling
// since view errors occur within eval'd code.
// -----------------------------------------------------
if (strpos($e->getFile(), 'view.php') !== false and strpos($e->getFile(), "eval()'d code") !== false)
{
$file = APP_PATH.'views/'.View::$last.EXT;
}
else
{
$file = $e->getFile();
}
// -----------------------------------------------------
// Trim the period off of the error message.
// -----------------------------------------------------
$message = rtrim($e->getMessage(), '.');
// -----------------------------------------------------
// Log the error.
// -----------------------------------------------------
if (Config::get('error.log'))
{
Log::error($message.' in '.$e->getFile().' on line '.$e->getLine());
}
if (Config::get('error.detail'))
{
// -----------------------------------------------------
// Build the error view.
// -----------------------------------------------------
$view = View::make('error/exception')
->bind('severity', $severity)
->bind('message', $message)
->bind('file', $file)
->bind('line', $e->getLine())
->bind('trace', $e->getTraceAsString())
->bind('contexts', static::context($file, $e->getLine()));
// -----------------------------------------------------
// Send the detailed error response.
// -----------------------------------------------------
Response::make($view, 500)->send();
}
else
{
// -----------------------------------------------------
// Send the generic error response.
// -----------------------------------------------------
Response::make(View::make('error/500'), 500)->send();
}
exit(1);
}
/**
* Get the file context of an exception.
*
* @param string $path
* @param int $line
* @param int $padding
* @return array
*/
private static function context($path, $line, $padding = 5)
{
// -----------------------------------------------------
// Verify that the file exists.
// -----------------------------------------------------
if (file_exists($path))
{
// -----------------------------------------------------
// Get the contents of the file.
// -----------------------------------------------------
$file = file($path, FILE_IGNORE_NEW_LINES);
// -----------------------------------------------------
// Unshift the array.
// -----------------------------------------------------
array_unshift($file, '');
// -----------------------------------------------------
// Calculate the starting position.
// -----------------------------------------------------
$start = $line - $padding;
if ($start < 0)
{
$start = 0;
}
// -----------------------------------------------------
// Calculate the context length.
// -----------------------------------------------------
$length = ($line - $start) + $padding + 1;
if (($start + $length) > count($file) - 1)
{
$length = null;
}
// -----------------------------------------------------
// Return the context.
// -----------------------------------------------------
return array_slice($file, $start, $length, true);
}
return array();
}
}

51
system/filter.php Normal file
View File

@@ -0,0 +1,51 @@
<?php namespace System;
class Filter {
/**
* The loaded route filters.
*
* @var array
*/
public static $filters;
/**
* Call a set of route filters.
*
* @param string $filter
* @param array $parameters
* @return mixed
*/
public static function call($filters, $parameters = array())
{
// --------------------------------------------------------------
// Load the route filters.
// --------------------------------------------------------------
if (is_null(static::$filters))
{
static::$filters = require APP_PATH.'filters'.EXT;
}
foreach (explode(', ', $filters) as $filter)
{
// --------------------------------------------------------------
// Verify that the filter is defined.
// --------------------------------------------------------------
if ( ! isset(static::$filters[$filter]))
{
throw new \Exception("Route filter [$filter] is not defined.");
}
$response = call_user_func_array(static::$filters[$filter], $parameters);
// --------------------------------------------------------------
// If the filter returned a response, return it.
// --------------------------------------------------------------
if ( ! is_null($response))
{
return $response;
}
}
}
}

327
system/form.php Normal file
View File

@@ -0,0 +1,327 @@
<?php namespace System;
class Form {
/**
* Open a HTML form.
*
* @param string $action
* @param string $method
* @param array $attributes
* @return string
*/
public static function open($action = null, $method = 'POST', $attributes = array())
{
// -------------------------------------------------------
// If no action was given, use the current URI.
// -------------------------------------------------------
if (is_null($action))
{
$action = Request::uri();
}
// -------------------------------------------------------
// Prepare the action URL.
// -------------------------------------------------------
$action = URL::to($action);
// -------------------------------------------------------
// Set the action attribute.
// -------------------------------------------------------
$attributes['action'] = $action;
// -------------------------------------------------------
// Set the method attribute.
// -------------------------------------------------------
$attributes['method'] = ($method == 'GET' or $method == 'POST') ? $method : 'POST';
// -------------------------------------------------------
// Set the default character set.
// -------------------------------------------------------
if ( ! array_key_exists('accept-charset', $attributes))
{
$attributes['accept-charset'] = 'UTF-8';
}
// -------------------------------------------------------
// Build the form tag.
// -------------------------------------------------------
$html = '<form'.HTML::attributes($attributes).'>';
// -------------------------------------------------------
// If the method is PUT or DELETE, we'll need to spoof it
// using a hidden input field.
//
// For more information, see the Input library.
// -------------------------------------------------------
if ($method == 'PUT' or $method == 'DELETE')
{
$html .= PHP_EOL.static::hidden('request_method', $method);
}
return $html.PHP_EOL;
}
/**
* Generate a hidden field containing the current CSRF token.
*
* @return string
*/
public static function token()
{
return static::hidden('csrf_token', static::raw_token());
}
/**
* Retrieve the current CSRF token.
*
* @return string
*/
public static function raw_token()
{
// -------------------------------------------------------
// Verify that sessions are enabled.
// -------------------------------------------------------
if (Config::get('session.driver') == '')
{
throw new \Exception('Sessions must be enabled to retrieve a CSRF token.');
}
return Session::get('csrf_token');
}
/**
* Create a HTML text input element.
*
* @param string $name
* @param string $value
* @param array $attributes
* @return string
*/
public static function text($name, $value = null, $attributes = array())
{
return static::input('text', $name, $value, $attributes);
}
/**
* Create a HTML password input element.
*
* @param string $name
* @param array $attributes
* @return string
*/
public static function password($name, $attributes = array())
{
return static::input('password', $name, null, $attributes);
}
/**
* Create a HTML hidden input element.
*
* @param string $name
* @param array $attributes
* @return string
*/
public static function hidden($name, $value = null, $attributes = array())
{
return static::input('hidden', $name, $value, $attributes);
}
/**
* Create a HTML file input element.
*
* @param string $name
* @param array $attributes
* @return string
*/
public static function file($name, $attributes = array())
{
return static::input('file', $name, null, $attributes);
}
/**
* Create a HTML submit input element.
*
* @param string $name
* @param array $attributes
* @return string
*/
public static function submit($value, $attributes = array())
{
return static::input('submit', null, $value, $attributes);
}
/**
* Create a HTML button element.
*
* @param string $name
* @param string $value
* @param array $attributes
* @return string
*/
public static function button($value, $attributes = array())
{
return '<button'.HTML::attributes($attributes).'>'.$value.'</button>'.PHP_EOL;
}
/**
* Create a HTML checkbox input element.
*
* @param string $name
* @param string $value
* @param bool $checked
* @param array $attributes
* @return string
*/
public static function checkbox($name, $value = null, $checked = false, $attributes = array())
{
return static::checkable('checkbox', $name, $value, $checked, $attributes);
}
/**
* Create a HTML radio button input element.
*
* @param string $name
* @param string $value
* @param bool $checked
* @param array $attributes
* @return string
*/
public static function radio($name, $value = null, $checked = false, $attributes = array())
{
return static::checkable('radio', $name, $value, $checked, $attributes);
}
/**
* Create a checkable input element.
*
* @param string $type
* @param string $name
* @param string $value
* @param bool $checked
* @param array $attributes
* @return string
*/
private static function checkable($type, $name, $value, $checked, $attributes)
{
// -------------------------------------------------------
// Set the checked attribute.
// -------------------------------------------------------
if ($checked === true)
{
$attributes['checked'] = 'checked';
}
return static::input($type, $name, $value, $attributes);
}
/**
* Create a HTML textarea element.
*
* @param string $name
* @param string $value
* @param array $attributes
* @return string
*/
public static function textarea($name, $value = '', $attributes = array())
{
// -------------------------------------------------------
// Add the name to the attributes.
// -------------------------------------------------------
$attributes['name'] = $name;
// -------------------------------------------------------
// Set the default number of rows.
// -------------------------------------------------------
if ( ! isset($attributes['rows']))
{
$attributes['rows'] = 10;
}
// -------------------------------------------------------
// Set the default number of columns.
// -------------------------------------------------------
if ( ! isset($attributes['cols']))
{
$attributes['cols'] = 50;
}
return '<textarea'.HTML::attributes($attributes).'>'.Str::entities($value).'</textarea>'.PHP_EOL;
}
/**
* Create a HTML select element.
*
* @param string $name
* @param array $options
* @param string $selected
* @param array $attributes
* @return string
*/
public static function select($name, $options = array(), $selected = null, $attributes = array())
{
// -------------------------------------------------------
// Set the name attribute.
// -------------------------------------------------------
$attributes['name'] = $name;
// -------------------------------------------------------
// Initialize the options array.
// -------------------------------------------------------
$html_options = array();
// -------------------------------------------------------
// Build the options in HTML.
// -------------------------------------------------------
foreach ($options as $value => $display)
{
$option_attributes = array();
// -------------------------------------------------------
// Set the value attribute.
// -------------------------------------------------------
$option_attributes['value'] = $value;
// -------------------------------------------------------
// Set the selected attribute.
// -------------------------------------------------------
$option_attributes['selected'] = ($value == $selected) ? 'selected' : null;
// -------------------------------------------------------
// Add the option HTML to the array of options.
// -------------------------------------------------------
$html_options[] = '<option'.HTML::attributes($option_attributes).'>'.$display.'</option>';
}
return '<select'.HTML::attributes($attributes).'>'.implode('', $html_options).'</select>'.PHP_EOL;
}
/**
* Create a HTML input element.
*
* @param string $name
* @param mixed $value
* @param array $attributes
* @return string
*/
private static function input($type, $name, $value = null, $attributes = array())
{
// -------------------------------------------------------
// Set the type attribute.
// -------------------------------------------------------
$attributes['type'] = $type;
// -------------------------------------------------------
// Set the name attribute.
// -------------------------------------------------------
$attributes['name'] = $name;
// -------------------------------------------------------
// Set the value attribute.
// -------------------------------------------------------
$attributes['value'] = $value;
return '<input'.HTML::attributes($attributes).' />'.PHP_EOL;
}
}

52
system/hash.php Normal file
View File

@@ -0,0 +1,52 @@
<?php namespace System;
class Hash {
/**
* The salty, hashed value.
*
* @var string
*/
public $value;
/**
* The salt used during hashing.
*
* @var string
*/
public $salt;
/**
* Create a new hash instance.
*
* @param string $value
* @param string $salt
* @return void
*/
public function __construct($value, $salt = null)
{
// --------------------------------------------------------------
// Get a random salt to hash the value with.
// --------------------------------------------------------------
$this->salt = (is_null($salt)) ? Str::random(16) : $salt;
// --------------------------------------------------------------
// Perform a salted, SHA-1 hash on the value.
// --------------------------------------------------------------
$this->value = sha1($value.$this->salt);
}
/**
* Factory for creating hash instances.
*
* @access public
* @param string $value
* @param string $salt
* @return Hash
*/
public static function make($value, $salt = null)
{
return new self($value, $salt);
}
}

275
system/html.php Normal file
View File

@@ -0,0 +1,275 @@
<?php namespace System;
class HTML {
/**
* Generate a JavaScript reference.
*
* @param string $url
* @return string
*/
public static function script($url)
{
return '<script type="text/javascript" src="'.trim(URL::to($url), '.js').'.js"></script>'.PHP_EOL;
}
/**
* Generate a CSS reference.
*
* @param string $url
* @return string
*/
public static function style($url, $media = 'all')
{
return '<link href="'.trim(URL::to($url), '.css').'.css" rel="stylesheet" type="text/css" media="'.$media.'" />'.PHP_EOL;
}
/**
* Generate a HTML link.
*
* @param string $url
* @param string $title
* @param array $attributes
* @param bool $https
* @return string
*/
public static function link($url, $title, $attributes = array(), $https = false)
{
return '<a href="'.URL::to($url, $https).'"'.static::attributes($attributes).'>'.Str::entities($title).'</a>';
}
/**
* Generate a HTTPS HTML link.
*
* @param string $url
* @param string $title
* @param array $attributes
* @return string
*/
public static function secure_link($url, $title, $attributes)
{
return static::link($url, $title, $attributes, true);
}
/**
* Generate an HTML mailto link.
*
* @param string $email
* @param string $title
* @param array $attributes
* @return string
*/
public static function mailto($email, $title = null, $attributes = array())
{
// -------------------------------------------------------
// Obfuscate the e-mail address.
// -------------------------------------------------------
$email = static::email($email);
// -------------------------------------------------------
// If no title is specified, just use the e-mail address.
// -------------------------------------------------------
if (is_null($title))
{
$title = $email;
}
return '<a href="&#109;&#097;&#105;&#108;&#116;&#111;&#058;'.$email.'"'.static::attributes($attributes).'>'.$title.'</a>';
}
/**
* Obfuscate an e-mail address to prevent spam-bots from sniffing it.
*
* @param string $email
* @return string
*/
public static function email($email)
{
return str_replace('@', '&#64;', static::obfuscate($email));
}
/**
* Generate an HTML image.
*
* @param string $url
* @param string $alt
* @param array $attributes
* @return string
*/
public static function image($url, $alt = '', $attributes = array())
{
// -------------------------------------------------------
// Add the "alt" tag to the attributes.
// -------------------------------------------------------
$attributes['alt'] = Str::entities($alt);
return '<img src="'.URL::to($url).'"'.static::attributes($attributes).' />';
}
/**
* Generate HTML breaks.
*
* @param int $count
* @return string
*/
public static function breaks($count = 1)
{
return str_repeat('<br />', $count);
}
/**
* Generate non-breaking spaces.
*
* @param int $count
* @return string
*/
public static function spaces($count = 1)
{
return str_repeat('&nbsp;', $count);
}
/**
* Generate an ordered list.
*
* @param array $list
* @param array $attributes
* @return string
*/
public static function ol($list, $attributes = array())
{
return static::list_elements('ol', $list, $attributes);
}
/**
* Generate an un-ordered list.
*
* @param array $list
* @param array $attributes
* @return string
*/
public static function ul($list, $attributes = array())
{
return static::list_elements('ul', $list, $attributes);
}
/**
* Generate an ordered or un-ordered list.
*
* @param string $type
* @param array $list
* @param array $attributes
* @return string
*/
private static function list_elements($type, $list, $attributes)
{
// -------------------------------------------------------
// Verify the list is an array.
// -------------------------------------------------------
if ( ! is_array($list))
{
return '';
}
// -------------------------------------------------------
// Initialize the output value.
// -------------------------------------------------------
$html = '';
// -------------------------------------------------------
// Add the list items.
// -------------------------------------------------------
foreach ($list as $key => $value)
{
$html .= '<li>'.Str::entities($value).'</li>';
}
// -------------------------------------------------------
// Build the list opening tag.
// -------------------------------------------------------
$start = '<'.$type.static::attributes($attributes).'>';
return $start.$html.'</'.$type.'>';
}
/**
* Build a list of HTML attributes.
*
* @param array $attributes
* @return string
*/
public static function attributes($attributes)
{
$html = array();
foreach ($attributes as $key => $value)
{
// -------------------------------------------------------
// If the value is null, skip it.
// -------------------------------------------------------
if (is_null($value))
{
continue;
}
// -------------------------------------------------------
// Add the HTML attribute to the array of attributes.
// -------------------------------------------------------
$html[] = $key.'="'.Str::entities($value).'"';
}
// -------------------------------------------------------
// Concatenate all of the attributes together.
// -------------------------------------------------------
if (count($html) > 0)
{
return ' '.implode(' ', $html);
}
else
{
return '';
}
}
/**
* Obfuscate a string to prevent spam-bots from sniffing it.
*
* @param string $value
* @return string
*/
public static function obfuscate($value)
{
$safe = '';
// -------------------------------------------------------
// Spin through the string letter by letter.
// -------------------------------------------------------
foreach (str_split($value) as $letter)
{
switch (rand(1, 3))
{
// -------------------------------------------------------
// Convert the letter to its entity representation.
// -------------------------------------------------------
case 1:
$safe .= '&#'.ord($letter).';';
break;
// -------------------------------------------------------
// Convert the letter to a Hex character code.
// -------------------------------------------------------
case 2:
$safe .= '&#x'.dechex(ord($letter)).';';
break;
// -------------------------------------------------------
// No encoding.
// -------------------------------------------------------
case 3:
$safe .= $letter;
}
}
return $safe;
}
}

230
system/inflector.php Normal file
View File

@@ -0,0 +1,230 @@
<?php namespace System;
class Inflector {
/**
* The words that have been converted to singular.
*
* @var array
*/
private static $singular_cache = array();
/**
* The words that have been converted to plural.
*
* @var array
*/
private static $plural_cache = array();
/**
* Plural word forms.
*
* @var array
*/
private static $plural = array(
'/(quiz)$/i' => "$1zes",
'/^(ox)$/i' => "$1en",
'/([m|l])ouse$/i' => "$1ice",
'/(matr|vert|ind)ix|ex$/i' => "$1ices",
'/(x|ch|ss|sh)$/i' => "$1es",
'/([^aeiouy]|qu)y$/i' => "$1ies",
'/(hive)$/i' => "$1s",
'/(?:([^f])fe|([lr])f)$/i' => "$1$2ves",
'/(shea|lea|loa|thie)f$/i' => "$1ves",
'/sis$/i' => "ses",
'/([ti])um$/i' => "$1a",
'/(tomat|potat|ech|her|vet)o$/i' => "$1oes",
'/(bu)s$/i' => "$1ses",
'/(alias)$/i' => "$1es",
'/(octop)us$/i' => "$1i",
'/(ax|test)is$/i' => "$1es",
'/(us)$/i' => "$1es",
'/s$/i' => "s",
'/$/' => "s"
);
/**
* Singular word forms.
*
* @var array
*/
private static $singular = array(
'/(quiz)zes$/i' => "$1",
'/(matr)ices$/i' => "$1ix",
'/(vert|ind)ices$/i' => "$1ex",
'/^(ox)en$/i' => "$1",
'/(alias)es$/i' => "$1",
'/(octop|vir)i$/i' => "$1us",
'/(cris|ax|test)es$/i' => "$1is",
'/(shoe)s$/i' => "$1",
'/(o)es$/i' => "$1",
'/(bus)es$/i' => "$1",
'/([m|l])ice$/i' => "$1ouse",
'/(x|ch|ss|sh)es$/i' => "$1",
'/(m)ovies$/i' => "$1ovie",
'/(s)eries$/i' => "$1eries",
'/([^aeiouy]|qu)ies$/i' => "$1y",
'/([lr])ves$/i' => "$1f",
'/(tive)s$/i' => "$1",
'/(hive)s$/i' => "$1",
'/(li|wi|kni)ves$/i' => "$1fe",
'/(shea|loa|lea|thie)ves$/i' => "$1f",
'/(^analy)ses$/i' => "$1sis",
'/((a)naly|(b)a|(d)iagno|(p)arenthe|(p)rogno|(s)ynop|(t)he)ses$/i' => "$1$2sis",
'/([ti])a$/i' => "$1um",
'/(n)ews$/i' => "$1ews",
'/(h|bl)ouses$/i' => "$1ouse",
'/(corpse)s$/i' => "$1",
'/(us)es$/i' => "$1",
'/(us|ss)$/i' => "$1",
'/s$/i' => "",
);
/**
* Irregular word forms.
*
* @var array
*/
private static $irregular = array(
'move' => 'moves',
'foot' => 'feet',
'goose' => 'geese',
'sex' => 'sexes',
'child' => 'children',
'man' => 'men',
'tooth' => 'teeth',
'person' => 'people',
);
/**
* Uncountable word forms.
*
* @var array
*/
private static $uncountable = array(
'sheep',
'fish',
'deer',
'series',
'species',
'money',
'rice',
'information',
'equipment',
);
/**
* Convert a word to its plural form.
*
* @param string $value
* @return string
*/
public static function plural($value)
{
// -----------------------------------------------------
// Have we already converted this word?
// -----------------------------------------------------
if (array_key_exists($value, static::$plural_cache))
{
return static::$plural_cache[$value];
}
// -----------------------------------------------------
// Are the singular and plural forms the same?
// -----------------------------------------------------
if (in_array(Str::lower($value), static::$uncountable))
{
return static::$plural_cache[$value] = $value;
}
// -----------------------------------------------------
// Is the plural form irregular?
// -----------------------------------------------------
foreach (static::$irregular as $pattern => $irregular)
{
$pattern = '/'.$pattern.'$/i';
if (preg_match($pattern, $value))
{
return static::$plural_cache[$value] = preg_replace($pattern, $irregular, $value);
}
}
// -----------------------------------------------------
// Check the plural forms for matches.
// -----------------------------------------------------
foreach (static::$plural as $pattern => $plural)
{
if (preg_match($pattern, $value))
{
return static::$plural_cache[$value] = preg_replace($pattern, $plural, $value);
}
}
return static::$plural_cache[$value] = $value;
}
/**
* Convert a word to its singular form.
*
* @param string $value
* @return string
*/
public static function singular($value)
{
// -----------------------------------------------------
// Have we already converted this word?
// -----------------------------------------------------
if (array_key_exists($value, static::$singular_cache))
{
return static::$singular_cache[$value];
}
// -----------------------------------------------------
// Are the singular and plural forms the same?
// -----------------------------------------------------
if (in_array(Str::lower($value), static::$uncountable))
{
return static::$singular_cache[$value] = $value;
}
// -----------------------------------------------------
// Is the plural form irregular?
// -----------------------------------------------------
foreach (static::$irregular as $irregular => $pattern)
{
$pattern = '/'.$pattern.'$/i';
if (preg_match($pattern, $value))
{
return static::$singular_cache[$value] = preg_replace($pattern, $irregular, $value);
}
}
// -----------------------------------------------------
// Check the singular forms for matches.
// -----------------------------------------------------
foreach (static::$singular as $pattern => $singular)
{
if (preg_match($pattern, $value))
{
return static::$singular_cache[$value] = preg_replace($pattern, $singular, $value);
}
}
return static::$singular_cache[$value] = $value;
}
/**
* Get the plural form of a word if the count is greater than zero.
*
* @param string $value
* @param int $count
* @return string
*/
public static function plural_if($value, $count)
{
return ($count > 1) ? static::plural($value) : $value;
}
}

135
system/input.php Normal file
View File

@@ -0,0 +1,135 @@
<?php namespace System;
class Input {
/**
* The input data for the request.
*
* @var array
*/
public static $input;
/**
* Determine if the input data contains an item.
*
* @param string $key
* @return bool
*/
public static function has($key)
{
return ( ! is_null(static::get($key)));
}
/**
* Determine if the old input data contains an item.
*
* @param string $key
* @return bool
*/
public static function has_old($key)
{
return ( ! is_null(static::old($key)));
}
/**
* Get an item from the input data.
*
* @param string $key
* @param mixed $default
* @return string
*/
public static function get($key = null, $default = null)
{
// -------------------------------------------------
// Hydrate the input data for the request.
// -------------------------------------------------
static::hydrate();
return static::from_array(static::$input, $key, $default);
}
/**
* Get input data from the previous request.
*
* @param string $key
* @param mixed $default
* @return string
*/
public static function old($key = null, $default = null)
{
// -------------------------------------------------
// Verify that sessions are enabled.
// -------------------------------------------------
if (Config::get('session.driver') == '')
{
throw new \Exception("Sessions must be enabled to retrieve old input data.");
}
return static::from_array(Session::get('laravel_old_input', array()), $key, $default);
}
/**
* Get an item from an array.
*
* @param array $array
* @param string $key
* @param mixed $default
* @return string
*/
private static function from_array($array, $key, $default)
{
// -------------------------------------------------
// If no key is given, return the entire array.
// -------------------------------------------------
if (is_null($key))
{
return $array;
}
return (array_key_exists($key, $array)) ? $array[$key] : $default;
}
/**
* Hydrate the input data for the request.
*
* @return void
*/
public static function hydrate()
{
if (is_null(static::$input))
{
switch (Request::method())
{
case 'GET':
static::$input =& $_GET;
break;
case 'POST':
static::$input =& $_POST;
break;
case 'PUT':
case 'DELETE':
// ----------------------------------------------------------------------
// Typically, browsers do not support PUT and DELETE methods on HTML
// forms. So, we simulate them using a hidden POST variable.
//
// If the request method is being "spoofed", we'll move the POST array
// into the PUT / DELETE array.
// ----------------------------------------------------------------------
if (isset($_POST['request_method']) and ($_POST['request_method'] == 'PUT' or $_POST['request_method'] == 'DELETE'))
{
static::$input =& $_POST;
}
// ----------------------------------------------------------------------
// If the request is a true PUT request, read the php://input file.
// ----------------------------------------------------------------------
else
{
parse_str(file_get_contents('php://input'), static::$input);
}
}
}
}
}

178
system/lang.php Normal file
View File

@@ -0,0 +1,178 @@
<?php namespace System;
class Lang {
/**
* All of the loaded language files.
*
* @var array
*/
private static $loaded = array();
/**
* All of the loaded language lines.
*
* @var array
*/
private static $lines = array();
/**
* The key of the line that is being requested.
*
* @var string
*/
private $key;
/**
* The place-holder replacements.
*
* @var array
*/
private $replacements = array();
/**
* Create a new Lang instance.
*
* @param string $line
* @return void
*/
public function __construct($key)
{
$this->key = $key;
}
/**
* Create a Lang instance for a language line.
*
* @param string $key
* @return Lang
*/
public static function line($key)
{
return new static($key);
}
/**
* Get the language line for a given language.
*
* @param string $language
* @return string
*/
public function get($language = null)
{
// --------------------------------------------------------------
// If no language was specified, use the default language.
// --------------------------------------------------------------
if (is_null($language))
{
$language = Config::get('application.language');
}
// --------------------------------------------------------------
// Extract the file and item from the key.
// --------------------------------------------------------------
list($file, $line) = $this->parse($this->key);
// --------------------------------------------------------------
// Load the language file.
// --------------------------------------------------------------
$this->load($file, $language);
// --------------------------------------------------------------
// Get the language line.
// --------------------------------------------------------------
if (array_key_exists($line, static::$lines[$language.$file]))
{
$line = static::$lines[$language.$file][$line];
}
else
{
throw new \Exception("Language line [$line] does not exist for language [$language]");
}
// --------------------------------------------------------------
// Make all place-holder replacements.
// --------------------------------------------------------------
foreach ($this->replacements as $key => $value)
{
$line = str_replace(':'.$key, $value, $line);
}
return $line;
}
/**
* Parse a language key.
*
* @param string $key
* @return array
*/
private function parse($key)
{
// ---------------------------------------------
// Get the key segments.
// ---------------------------------------------
$segments = explode('.', $key);
// ---------------------------------------------
// Validate the key format.
// ---------------------------------------------
if (count($segments) < 2)
{
throw new \Exception("Invalid language key [$key].");
}
// ---------------------------------------------
// Return the file and item name.
// ---------------------------------------------
return array($segments[0], implode('.', array_slice($segments, 1)));
}
/**
* Load a language file.
*
* @param string $file
* @param string $language
* @return void
*/
private function load($file, $language)
{
// --------------------------------------------------------------
// Do not load the file if it has already been loaded.
// --------------------------------------------------------------
if (in_array($language.$file, static::$loaded))
{
return;
}
// --------------------------------------------------------------
// Does the language file exist?
// --------------------------------------------------------------
if (file_exists($path = APP_PATH.'lang/'.$language.'/'.$file.EXT))
{
static::$lines[$language.$file] = require $path;
}
else
{
throw new \Exception("Language file [$file] does not exist for language [$language].");
}
// --------------------------------------------------------------
// Add the file to the array of loaded files.
// --------------------------------------------------------------
static::$loaded[] = $language.$file;
}
/**
* Set the place-holder replacements.
*
* @param array $replacements
* @return Lang
*/
public function replace($replacements)
{
$this->replacements = $replacements;
return $this;
}
}

50
system/loader.php Normal file
View File

@@ -0,0 +1,50 @@
<?php
/**
* This function is registered on the auto-loader stack by the front controller.
*/
return function($class) {
// ----------------------------------------------------------
// Replace namespace slashes with directory slashes.
// ----------------------------------------------------------
$file = System\Str::lower(str_replace('\\', '/', $class));
// ----------------------------------------------------------
// Should the class be aliased?
// ----------------------------------------------------------
if (array_key_exists($class, $aliases = System\Config::get('application.aliases')))
{
return class_alias($aliases[$class], $class);
}
// ----------------------------------------------------------
// Check for the class in the system directory.
// ----------------------------------------------------------
if (file_exists($path = BASE_PATH.$file.EXT))
{
require $path;
}
// ----------------------------------------------------------
// Check for the class in the models directory.
// ----------------------------------------------------------
elseif (file_exists($path = APP_PATH.'models/'.$file.EXT))
{
require $path;
}
// ----------------------------------------------------------
// Check for the class in the packages directory.
// ----------------------------------------------------------
elseif (file_exists($path = APP_PATH.'packages/'.$file.EXT))
{
require $path;
}
// ----------------------------------------------------------
// Check for the class in the application directory.
// ----------------------------------------------------------
elseif (file_exists($path = APP_PATH.$file.EXT))
{
require $path;
}
};

102
system/log.php Normal file
View File

@@ -0,0 +1,102 @@
<?php namespace System;
class Log {
/**
* Write an info message to the log.
*
* @param string $message
* @return void
*/
public static function info($message)
{
static::write('Info', $message);
}
/**
* Write a debug message to the log.
*
* @param string $message
* @return void
*/
public static function debug($message)
{
static::write('Debug', $message);
}
/**
* Write an error message to the logs.
*
* @param string $message
* @return void
*/
public static function error($message)
{
static::write('Error', $message);
}
/**
* Write a message to the logs.
*
* @param string $type
* @param string $message
* @return void
*/
public static function write($type, $message)
{
// -----------------------------------------------------
// Determine the yearly directory.
// -----------------------------------------------------
$directory = APP_PATH.'logs/'.date('Y');
if ( ! is_dir($directory))
{
static::make_directory($directory);
}
// -----------------------------------------------------
// Determine the monthly directory.
// -----------------------------------------------------
$directory .= '/'.date('m');
if ( ! is_dir($directory))
{
static::make_directory($directory);
}
// -----------------------------------------------------
// Determine the daily file.
// -----------------------------------------------------
$file = $directory.'/'.date('d').EXT;
// -----------------------------------------------------
// Write the message to the log.
// -----------------------------------------------------
file_put_contents($file, date('Y-m-d H:i:s').' '.$type.' - '.$message.PHP_EOL, LOCK_EX | FILE_APPEND);
// -----------------------------------------------------
// Set the log file permissions.
// -----------------------------------------------------
chmod($file, 0666);
}
/**
* Create a log directory.
*
* @param string $directory
* @return void
*/
private static function make_directory($directory)
{
// -----------------------------------------------------
// Create the directory.
// -----------------------------------------------------
mkdir($directory, 02777);
// -----------------------------------------------------
// Set the directory permissions.
// -----------------------------------------------------
chmod($directory, 02777);
}
}

56
system/memcached.php Normal file
View File

@@ -0,0 +1,56 @@
<?php namespace System;
class Memcached {
/**
* The Memcache instance.
*
* @var Memcache
*/
private static $instance = null;
/**
* Get the singleton Memcache instance.
*
* @return Memcache
*/
public static function instance()
{
if (is_null(static::$instance))
{
// -----------------------------------------------------
// Verify that the Memcache extension is installed.
// -----------------------------------------------------
if ( ! class_exists('Memcache'))
{
throw new \Exception('Attempting to use Memcached, but the Memcached PHP extension is not installed on this server.');
}
// -----------------------------------------------------
// Instantiate the Memcache class.
// -----------------------------------------------------
$memcache = new \Memcache;
// -----------------------------------------------------
// Configure the Memcache servers.
// -----------------------------------------------------
foreach (Config::get('cache.servers') as $server)
{
$memcache->addServer($server['host'], $server['port'], true, $server['weight']);
}
// -----------------------------------------------------
// Verify Memcache was configured successfully.
// -----------------------------------------------------
if ($memcache->getVersion() === false)
{
throw new \Exception('Memcached is configured. However, no connections could be made. Please verify your memcached configuration.');
}
static::$instance = $memcache;
}
return static::$instance;
}
}

66
system/redirect.php Normal file
View File

@@ -0,0 +1,66 @@
<?php namespace System;
class Redirect {
/**
* Create a redirect response.
*
* @param string $url
* @param string $method
* @param int $status
* @param bool $https
* @return Response
*/
public static function to($url, $method = 'location', $status = 302, $https = false)
{
// -------------------------------------------------
// Prepare the URL.
// -------------------------------------------------
$url = URL::to($url, $https);
// -------------------------------------------------
// Return the redirect response.
// -------------------------------------------------
return ($method == 'refresh')
? Response::make('', $status)->header('Refresh', '0;url='.$url)
: Response::make('', $status)->header('Location', $url);
}
/**
* Create a redirect response to a HTTPS URL.
*
* @param string $url
* @param string $method
* @param int $status
* @return Response
*/
public static function to_secure($url, $method = 'location', $status = 302)
{
return static::to($url, $method, $status, true);
}
/**
* Magic Method to handle redirecting to routes.
*/
public static function __callStatic($method, $parameters)
{
// ----------------------------------------------------
// Dynamically redirect to a secure route URL.
// ----------------------------------------------------
if (strpos($method, 'to_secure_') === 0)
{
return static::to(URL::to_route(substr($method, 10), $parameters, true));
}
// ----------------------------------------------------
// Dynamically redirect a route URL.
// ----------------------------------------------------
if (strpos($method, 'to_') === 0)
{
return static::to(URL::to_route(substr($method, 3), $parameters));
}
throw new \Exception("Method [$method] is not defined on the Redirect class.");
}
}

136
system/request.php Normal file
View File

@@ -0,0 +1,136 @@
<?php namespace System;
class Request {
/**
* The request URI.
*
* @var string
*/
public static $uri;
/**
* Get the request URI.
*
* @return string
*/
public static function uri()
{
// --------------------------------------------------------------
// Have we already determined the URI?
// --------------------------------------------------------------
if ( ! is_null(static::$uri))
{
return static::$uri;
}
// --------------------------------------------------------------
// Use the PATH_INFO variable if it is available.
// --------------------------------------------------------------
if (isset($_SERVER['PATH_INFO']))
{
return static::$uri = static::tidy($_SERVER['PATH_INFO']);
}
// --------------------------------------------------------------
// If the server REQUEST_URI variable is not available, bail out.
// --------------------------------------------------------------
if ( ! isset($_SERVER['REQUEST_URI']))
{
throw new \Exception('Unable to determine the request URI.');
}
// --------------------------------------------------------------
// Get the PHP_URL_PATH of the request URI.
// --------------------------------------------------------------
$uri = parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH);
// --------------------------------------------------------------
// Slice the application URL off of the URI.
// --------------------------------------------------------------
if (strpos($uri, $base_url = parse_url(Config::get('application.url'), PHP_URL_PATH)) === 0)
{
$uri = substr($uri, strlen($base_url));
}
return static::$uri = static::tidy($uri);
}
/**
* Tidy up a URI for use by Laravel. For empty URIs, a forward
* slash will be returned.
*
* @param string $uri
* @return string
*/
private static function tidy($uri)
{
return ($uri != '/') ? Str::lower(trim($uri, '/')) : '/';
}
/**
* Get the request method.
*
* @return string
*/
public static function method()
{
// --------------------------------------------------------------
// The method can be spoofed using a POST variable. This allows
// HTML forms to simulate PUT and DELETE methods.
// --------------------------------------------------------------
return (isset($_POST['request_method'])) ? $_POST['request_method'] : $_SERVER['REQUEST_METHOD'];
}
/**
* Get the requestor's IP address.
*
* @return string
*/
public static function ip()
{
if (isset($_SERVER['HTTP_X_FORWARDED_FOR']))
{
return $_SERVER['HTTP_X_FORWARDED_FOR'];
}
elseif (isset($_SERVER['HTTP_CLIENT_IP']))
{
return $_SERVER['HTTP_CLIENT_IP'];
}
elseif (isset($_SERVER['REMOTE_ADDR']))
{
return $_SERVER['REMOTE_ADDR'];
}
}
/**
* Determine if the request is using HTTPS.
*
* @return bool
*/
public static function is_secure()
{
return (static::protocol() == 'https');
}
/**
* Get the HTTP protocol for the request.
*
* @return string
*/
public static function protocol()
{
return (isset($_SERVER['HTTPS']) and $_SERVER['HTTPS'] !== 'off') ? 'https' : 'http';
}
/**
* Determine if the request is an AJAX request.
*
* @return bool
*/
public static function is_ajax()
{
return (isset($_SERVER['HTTP_X_REQUESTED_WITH']) and Str::lower($_SERVER['HTTP_X_REQUESTED_WITH']) === 'xmlhttprequest');
}
}

252
system/response.php Normal file
View File

@@ -0,0 +1,252 @@
<?php namespace System;
class Response {
/**
* The content of the response.
*
* @var mixed
*/
public $content;
/**
* The HTTP status code.
*
* @var int
*/
public $status;
/**
* The response headers.
*
* @var array
*/
private $headers = array();
/**
* HTTP status codes.
*
* @var array
*/
private $statuses = array(
100 => 'Continue',
101 => 'Switching Protocols',
200 => 'OK',
201 => 'Created',
202 => 'Accepted',
203 => 'Non-Authoritative Information',
204 => 'No Content',
205 => 'Reset Content',
206 => 'Partial Content',
207 => 'Multi-Status',
300 => 'Multiple Choices',
301 => 'Moved Permanently',
302 => 'Found',
303 => 'See Other',
304 => 'Not Modified',
305 => 'Use Proxy',
307 => 'Temporary Redirect',
400 => 'Bad Request',
401 => 'Unauthorized',
402 => 'Payment Required',
403 => 'Forbidden',
404 => 'Not Found',
405 => 'Method Not Allowed',
406 => 'Not Acceptable',
407 => 'Proxy Authentication Required',
408 => 'Request Timeout',
409 => 'Conflict',
410 => 'Gone',
411 => 'Length Required',
412 => 'Precondition Failed',
413 => 'Request Entity Too Large',
414 => 'Request-URI Too Long',
415 => 'Unsupported Media Type',
416 => 'Requested Range Not Satisfiable',
417 => 'Expectation Failed',
422 => 'Unprocessable Entity',
423 => 'Locked',
424 => 'Failed Dependency',
500 => 'Internal Server Error',
501 => 'Not Implemented',
502 => 'Bad Gateway',
503 => 'Service Unavailable',
504 => 'Gateway Timeout',
505 => 'HTTP Version Not Supported',
507 => 'Insufficient Storage',
509 => 'Bandwidth Limit Exceeded'
);
/**
* Create a new response instance.
*
* @param mixed $content
* @param int $status
*/
public function __construct($content, $status = 200)
{
$this->content = $content;
$this->status = $status;
}
/**
* Factory for creating new response instances.
*
* @param string $content
* @param int $status
* @return Response
*/
public static function make($content, $status = 200)
{
return new static($content, $status);
}
/**
* Factory for creating new view response instances.
*
* @param string $view
* @param int $status
* @return Response
*/
public static function view($view, $status = 200)
{
return static::make(View::make($view), $status);
}
/**
* Send the response to the browser.
*
* @return void
*/
public function send()
{
// -------------------------------------------------
// Set the content type if it has not been set.
// -------------------------------------------------
if ( ! array_key_exists('Content-Type', $this->headers))
{
$this->header('Content-Type', 'text/html; charset=utf-8');
}
// -------------------------------------------------
// Send the headers to the browser.
// -------------------------------------------------
if ( ! headers_sent())
{
// -------------------------------------------------
// Send the HTTP protocol and status code.
// -------------------------------------------------
$protocol = (isset($_SERVER['SERVER_PROTOCOL'])) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.1';
header($protocol.' '.$this->status.' '.$this->statuses[$this->status]);
// -------------------------------------------------
// Send the rest of the headers.
// -------------------------------------------------
foreach ($this->headers as $name => $value)
{
header($name.': '.$value, true);
}
}
// -------------------------------------------------
// Send the content of the response to the browser.
// -------------------------------------------------
echo (string) $this->content;
}
/**
* Add a header to the response.
*
* @param string $name
* @param string $value
* @return Response
*/
public function header($name, $value)
{
$this->headers[$name] = $value;
return $this;
}
/**
* Add an item to the session flash data.
*
* @param string $key
* @param mixed $value
* @return Response
*/
public function with($key, $value)
{
if (Config::get('session.driver') != '')
{
Session::flash($key, $value);
}
return $this;
}
/**
* Determine if the response is a redirect.
*
* @return bool
*/
public function is_redirect()
{
return $this->status == 301 or $this->status == 302;
}
/**
* Magic Method for getting response View data.
*/
public function __get($key)
{
// ------------------------------------------------------
// Attempt to get the data from the View.
// ------------------------------------------------------
if ($this->content instanceof View)
{
return $this->content->$key;
}
}
/**
* Magic Method for setting response View data.
*/
public function __set($key, $value)
{
// ------------------------------------------------------
// Attempt to set the data on the View.
// ------------------------------------------------------
if ($this->content instanceof View)
{
$this->content->bind($key, $value);
}
}
/**
* Magic Method for handling dynamic method calls.
*/
public function __call($method, $parameters)
{
// ------------------------------------------------------
// Attempt to the pass the method to the View instance.
// ------------------------------------------------------
if ($this->content instanceof View and method_exists($this->content, $method))
{
call_user_func_array(array($this->content, $method), $parameters);
return $this;
}
throw new \Exception("Method [$method] does not exist on the Response class.");
}
/**
* Get the content of the response.
*/
public function __toString()
{
return (string) $this->content;
}
}

85
system/route.php Normal file
View File

@@ -0,0 +1,85 @@
<?php namespace System;
class Route {
/**
* The route callback or array.
*
* @var mixed
*/
public $route;
/**
* The parameters that will passed to the route function.
*
* @var array
*/
public $parameters;
/**
* Create a new Route instance.
*
* @param mixed $route
* @param array $parameters
* @return void
*/
public function __construct($route, $parameters = array())
{
$this->route = $route;
$this->parameters = $parameters;
}
/**
* Execute the route function.
*
* @param mixed $route
* @param array $parameters
* @return mixed
*/
public function call()
{
$response = null;
// --------------------------------------------------------------
// If the route just has a callback, call it.
// --------------------------------------------------------------
if (is_callable($this->route))
{
$response = call_user_func_array($this->route, $this->parameters);
}
// --------------------------------------------------------------
// The route value is an array. We'll need to evaluate it.
// --------------------------------------------------------------
elseif (is_array($this->route))
{
// --------------------------------------------------------------
// Call the "before" route filters.
// --------------------------------------------------------------
$response = isset($this->route['before']) ? Filter::call($this->route['before']) : null;
// --------------------------------------------------------------
// Call the route callback.
// --------------------------------------------------------------
if (is_null($response) and isset($this->route['do']))
{
$response = call_user_func_array($this->route['do'], $this->parameters);
}
}
// --------------------------------------------------------------
// Make sure the response is a Response instance.
// --------------------------------------------------------------
$response = ( ! $response instanceof Response) ? new Response($response) : $response;
// --------------------------------------------------------------
// Call the "after" route filters.
// --------------------------------------------------------------
if (is_array($this->route) and isset($this->route['after']))
{
Filter::call($this->route['after'], array($response));
}
return $response;
}
}

148
system/router.php Normal file
View File

@@ -0,0 +1,148 @@
<?php namespace System;
class Router {
/**
* All of the loaded routes.
*
* @var array
*/
public static $routes;
/**
* The named routes that have been found so far.
*
* @var array
*/
public static $names = array();
/**
* Search a set of routes for the route matching a method and URI.
*
* @param string $method
* @param string $uri
* @return Route
*/
public static function route($method, $uri)
{
// --------------------------------------------------------------
// Add a forward slash to the URI if necessary.
// --------------------------------------------------------------
$uri = ($uri != '/') ? '/'.$uri : $uri;
// --------------------------------------------------------------
// Load all of the application routes.
// --------------------------------------------------------------
static::$routes = require APP_PATH.'routes'.EXT;
// --------------------------------------------------------------
// Is there an exact match for the request?
// --------------------------------------------------------------
if (isset(static::$routes[$method.' '.$uri]))
{
return new Route(static::$routes[$method.' '.$uri]);
}
// --------------------------------------------------------------
// No exact match... check each route individually.
// --------------------------------------------------------------
foreach (static::$routes as $keys => $callback)
{
// --------------------------------------------------------------
// Only check routes that have multiple URIs or wildcards.
// All other routes would have been caught by a literal match.
// --------------------------------------------------------------
if (strpos($keys, '(') !== false or strpos($keys, ',') !== false )
{
// --------------------------------------------------------------
// Multiple routes can be assigned to a callback using commas.
// --------------------------------------------------------------
foreach (explode(', ', $keys) as $route)
{
// --------------------------------------------------------------
// Change wildcards into regular expressions.
// --------------------------------------------------------------
$route = str_replace(':num', '[0-9]+', str_replace(':any', '.+', $route));
// --------------------------------------------------------------
// Test the route for a match.
// --------------------------------------------------------------
if (preg_match('#^'.$route.'$#', $method.' '.$uri))
{
return new Route($callback, static::parameters(explode('/', $uri), explode('/', $route)));
}
}
}
}
}
/**
* Find a route by name.
*
* @param string $name
* @return array
*/
public static function find($name)
{
// ----------------------------------------------------
// Have we already looked up this named route?
// ----------------------------------------------------
if (array_key_exists($name, static::$names))
{
return static::$names[$name];
}
// ----------------------------------------------------
// Instantiate the recursive array iterator.
// ----------------------------------------------------
$arrayIterator = new \RecursiveArrayIterator(static::$routes);
// ----------------------------------------------------
// Instantiate the recursive iterator iterator.
// ----------------------------------------------------
$recursiveIterator = new \RecursiveIteratorIterator($arrayIterator);
// ----------------------------------------------------
// Iterate through the routes searching for a route
// name that matches the given name.
// ----------------------------------------------------
foreach ($recursiveIterator as $iterator)
{
$route = $recursiveIterator->getSubIterator();
if ($route['name'] == $name)
{
return static::$names[$name] = array($arrayIterator->key() => iterator_to_array($route));
}
}
}
/**
* Get the parameters that should be passed to the route callback.
*
* @param array $uri_segments
* @param array $route_segments
* @return array
*/
private static function parameters($uri_segments, $route_segments)
{
$parameters = array();
// --------------------------------------------------------------
// Spin through the route segments looking for parameters.
// --------------------------------------------------------------
for ($i = 0; $i < count($route_segments); $i++)
{
// --------------------------------------------------------------
// Any segment wrapped in parentheses is a parameter.
// --------------------------------------------------------------
if (strpos($route_segments[$i], '(') === 0)
{
$parameters[] = $uri_segments[$i];
}
}
return $parameters;
}
}

281
system/session.php Normal file
View File

@@ -0,0 +1,281 @@
<?php namespace System;
class Session {
/**
* The active session driver.
*
* @var Session\Driver
*/
private static $driver;
/**
* The session.
*
* @var array
*/
private static $session = array();
/**
* Get the session driver instance.
*
* @return Session\Driver
*/
public static function driver()
{
if (is_null(static::$driver))
{
static::$driver = Session\Factory::make(Config::get('session.driver'));
}
return static::$driver;
}
/**
* Load the session for the user.
*
* @return void
*/
public static function load()
{
// -----------------------------------------------------
// If a valid ID is present, load the session.
// -----------------------------------------------------
if ( ! is_null($id = Cookie::get('laravel_session')))
{
static::$session = static::driver()->load($id);
}
// -----------------------------------------------------
// If the session is invalid, start a new one.
// -----------------------------------------------------
if (is_null($id) or is_null(static::$session) or (time() - static::$session['last_activity']) > (Config::get('session.lifetime') * 60))
{
static::$session['id'] = Str::random(40);
static::$session['data'] = array();
}
// -----------------------------------------------------
// Generate a CSRF token if one does not exist.
// -----------------------------------------------------
if ( ! static::has('csrf_token'))
{
static::put('csrf_token', Str::random(16));
}
// -----------------------------------------------------
// Set the last activity timestamp for the user.
// -----------------------------------------------------
static::$session['last_activity'] = time();
}
/**
* Determine if the session contains an item.
*
* @param string $key
* @return bool
*/
public static function has($key)
{
return array_key_exists($key, static::$session['data']) or
array_key_exists(':old:'.$key, static::$session['data']) or
array_key_exists(':new:'.$key, static::$session['data']);
}
/**
* Get an item from the session.
*
* @param string $key
* @return mixed
*/
public static function get($key, $default = null)
{
if (static::has($key))
{
if (array_key_exists($key, static::$session['data']))
{
return static::$session['data'][$key];
}
// -----------------------------------------------------
// Check the flash data for the item.
// -----------------------------------------------------
elseif (array_key_exists(':old:'.$key, static::$session['data']))
{
return static::$session['data'][':old:'.$key];
}
elseif (array_key_exists(':new:'.$key, static::$session['data']))
{
return static::$session['data'][':new:'.$key];
}
}
return $default;
}
/**
* Get an item from the session and delete it.
*
* @param string $key
* @return mixed
*/
public static function once($key, $default = null)
{
// -----------------------------------------------------
// Get the item from the session.
// -----------------------------------------------------
$value = static::get($key, $default);
// -----------------------------------------------------
// Delete the item from the session.
// -----------------------------------------------------
static::forget($key);
return $value;
}
/**
* 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 a flash item to the session.
*
* @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.
*
* @param string $key
* @return void
*/
public static function forget($key)
{
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()
{
// -----------------------------------------------------
// Delete the old session from storage.
// -----------------------------------------------------
static::driver()->delete(static::$session['id']);
// -----------------------------------------------------
// Create a new session ID.
// -----------------------------------------------------
static::$session['id'] = Str::random(40);
}
/**
* Close the session.
*
* @return void
*/
public static function close()
{
// -----------------------------------------------------
// Flash the old input into the session.
// -----------------------------------------------------
static::flash('laravel_old_input', Input::get());
// -----------------------------------------------------
// Age the session flash data.
// -----------------------------------------------------
static::age_flash();
// -----------------------------------------------------
// Save the session to storage.
// -----------------------------------------------------
static::driver()->save(static::$session);
if ( ! headers_sent())
{
// -----------------------------------------------------
// Calculate the cookie lifetime.
// -----------------------------------------------------
$lifetime = (Config::get('session.expire_on_close')) ? 0 : Config::get('session.lifetime');
// -----------------------------------------------------
// Write the session cookie.
// -----------------------------------------------------
Cookie::put('laravel_session', static::$session['id'], $lifetime, Config::get('session.path'), Config::get('session.domain'), Config::get('session.https'));
}
// -----------------------------------------------------
// Perform session garbage collection (2% chance).
// -----------------------------------------------------
if (mt_rand(1, 100) <= 2)
{
static::driver()->sweep(time() - (Config::get('session.lifetime') * 60));
}
}
/**
* Age the session flash data.
*
* @return void
*/
private static function age_flash()
{
// -----------------------------------------------------
// Expire all of the old flash data.
// -----------------------------------------------------
foreach (static::$session['data'] as $key => $value)
{
if (strpos($key, ':old:') === 0)
{
static::forget($key);
}
}
// -----------------------------------------------------
// Age all of the new flash data.
// -----------------------------------------------------
foreach (static::$session['data'] as $key => $value)
{
if (strpos($key, ':new:') === 0)
{
// -----------------------------------------------------
// Create an :old: flash item.
// -----------------------------------------------------
static::put(':old:'.substr($key, 5), $value);
// -----------------------------------------------------
// Forget the :new: flash item.
// -----------------------------------------------------
static::forget($key);
}
}
}
}

37
system/session/driver.php Normal file
View File

@@ -0,0 +1,37 @@
<?php namespace System\Session;
interface Driver {
/**
* Load a session by ID.
*
* @param string $id
* @return array
*/
public function load($id);
/**
* Save a session.
*
* @param array $session
* @return void
*/
public function save($session);
/**
* Delete a session by ID.
*
* @param string $id
* @return void
*/
public function delete($id);
/**
* Delete all expired sessions.
*
* @param int $expiration
* @return void
*/
public function sweep($expiration);
}

View File

@@ -0,0 +1,78 @@
<?php namespace System\Session\Driver;
class DB implements \System\Session\Driver {
/**
* Load a session by ID.
*
* @param string $id
* @return array
*/
public function load($id)
{
// -----------------------------------------------------
// Find the session in the database.
// -----------------------------------------------------
$session = $this->query()->find($id);
// -----------------------------------------------------
// If the session was found, return it.
// -----------------------------------------------------
if ( ! is_null($session))
{
return array('id' => $session->id, 'last_activity' => $session->last_activity, 'data' => unserialize($session->data));
}
}
/**
* Save a session.
*
* @param array $session
* @return void
*/
public function save($session)
{
// -----------------------------------------------------
// Delete the existing session row.
// -----------------------------------------------------
$this->delete($session['id']);
// -----------------------------------------------------
// Insert a new session row.
// -----------------------------------------------------
$this->query()->insert(array('id' => $session['id'], 'last_activity' => $session['last_activity'], 'data' => serialize($session['data'])));
}
/**
* Delete a session by ID.
*
* @param string $id
* @return void
*/
public function delete($id)
{
$this->query()->where('id', '=', $id)->delete();
}
/**
* Delete all expired sessions.
*
* @param int $expiration
* @return void
*/
public function sweep($expiration)
{
$this->query()->where('last_activity', '<', $expiration)->delete();
}
/**
* Get a session database query.
*
* @return Query
*/
private function query()
{
return \System\DB::table(\System\Config::get('session.table'));
}
}

View File

@@ -0,0 +1,64 @@
<?php namespace System\Session\Driver;
class File implements \System\Session\Driver {
/**
* Load a session by ID.
*
* @param string $id
* @return array
*/
public function load($id)
{
// -----------------------------------------------------
// Look for the session on the file system.
// -----------------------------------------------------
if (file_exists($path = APP_PATH.'sessions/'.$id))
{
return unserialize(file_get_contents($path));
}
}
/**
* Save a session.
*
* @param array $session
* @return void
*/
public function save($session)
{
file_put_contents(APP_PATH.'sessions/'.$session['id'], serialize($session), LOCK_EX);
}
/**
* Delete a session by ID.
*
* @param string $id
* @return void
*/
public function delete($id)
{
@unlink(APP_PATH.'sessions/'.$id);
}
/**
* Delete all expired sessions.
*
* @param int $expiration
* @return void
*/
public function sweep($expiration)
{
foreach (glob(APP_PATH.'sessions/*') as $file)
{
// -----------------------------------------------------
// If the session file has expired, delete it.
// -----------------------------------------------------
if (filetype($file) == 'file' and filemtime($file) < $expiration)
{
@unlink($file);
}
}
}
}

View File

@@ -0,0 +1,49 @@
<?php namespace System\Session\Driver;
class Memcached implements \System\Session\Driver {
/**
* Load a session by ID.
*
* @param string $id
* @return array
*/
public function load($id)
{
return \System\Cache::driver('memcached')->get($id);
}
/**
* Save a session.
*
* @param array $session
* @return void
*/
public function save($session)
{
\System\Cache::driver('memcached')->put($session['id'], $session, \System\Config::get('session.lifetime'));
}
/**
* Delete a session by ID.
*
* @param string $id
* @return void
*/
public function delete($id)
{
\System\Cache::driver('memcached')->forget($id);
}
/**
* Delete all expired sessions.
*
* @param int $expiration
* @return void
*/
public function sweep($expiration)
{
// Memcached sessions will expire automatically.
}
}

View File

@@ -0,0 +1,29 @@
<?php namespace System\Session;
class Factory {
/**
* Create a session driver instance.
*
* @param string $driver
* @return Driver
*/
public static function make($driver)
{
switch ($driver)
{
case 'file':
return new Driver\File;
case 'db':
return new Driver\DB;
case 'memcached':
return new Driver\Memcached;
default:
throw new \Exception("Session driver [$driver] is not supported.");
}
}
}

85
system/str.php Normal file
View File

@@ -0,0 +1,85 @@
<?php namespace System;
class Str {
/**
* The default encoding.
*
* @var string
*/
private static $encoding = 'UTF-8';
/**
* Convert HTML characters to entities.
*
* @param string $value
* @return string
*/
public static function entities($value)
{
return htmlentities($value, ENT_QUOTES, static::$encoding, false);
}
/**
* Convert a string to lowercase.
*
* @param string $value
* @return string
*/
public static function lower($value)
{
return function_exists('mb_strtolower') ? mb_strtolower($value, static::$encoding) : strtolower($value);
}
/**
* Convert a string to uppercase.
*
* @param string $value
* @return string
*/
public static function upper($value)
{
return function_exists('mb_strtoupper') ? mb_strtoupper($value, static::$encoding) : strtoupper($value);
}
/**
* Convert a string to title case (ucwords).
*
* @param string $value
* @return string
*/
public static function title($value)
{
return (function_exists('mb_convert_case')) ? mb_convert_case($value, MB_CASE_TITLE, static::$encoding) : ucwords(strtolower($value));
}
/**
* Generate a random alpha-numeric string.
*
* @param int $length
* @return string
*/
public static function random($length = 16)
{
// -----------------------------------------------------
// Split the character pool into an array.
// -----------------------------------------------------
$pool = str_split('0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ', 1);
// -----------------------------------------------------
// Initialize the return value.
// -----------------------------------------------------
$value = '';
// -----------------------------------------------------
// Build the random string.
// -----------------------------------------------------
for ($i = 0; $i < $length; $i++)
{
$value .= $pool[mt_rand(0, 61)];
}
return $value;
}
}

146
system/text.php Normal file
View File

@@ -0,0 +1,146 @@
<?php namespace System;
class Text {
/**
* Limit the words in a string. Word integrity will be preserved.
*
* @param string $value
* @param int $limit
* @param string $end
* @return string
*/
public static function words($value, $limit, $end = '&#8230;')
{
// -----------------------------------------------------
// If the value is an empty string, bail out.
// -----------------------------------------------------
if (trim($value) == '')
{
return $value;
}
// -----------------------------------------------------
// Limit the words in the string.
// -----------------------------------------------------
preg_match('/^\s*+(?:\S++\s*+){1,'.$limit.'}/', $value, $matches);
// -----------------------------------------------------
// If the string did not exceed the limit, we won't
// need an ending character.
// -----------------------------------------------------
if (strlen($value) == strlen($matches[0]))
{
$end = '';
}
// -----------------------------------------------------
// Add the ending character to the string.
// -----------------------------------------------------
return rtrim($matches[0]).$end;
}
/**
* Limit the number of characters in a string. Word integrity will be preserved.
*
* @param string $value
* @param int $limit
* @param string $end
* @return string
*/
public static function characters($value, $limit, $end = '&#8230;')
{
// -----------------------------------------------------
// If the value does not exceed the limit, bail out.
// -----------------------------------------------------
if (strlen($value) < $limit)
{
return $value;
}
// -----------------------------------------------------
// Replace new lines and whitespace in the string.
// -----------------------------------------------------
$value = preg_replace("/\s+/", ' ', str_replace(array("\r\n", "\r", "\n"), ' ', $value));
// -----------------------------------------------------
// If the value does not exceed the limit, bail out.
// -----------------------------------------------------
if (strlen($value) <= $limit)
{
return $value;
}
// -----------------------------------------------------
// Initialize the output string.
// -----------------------------------------------------
$out = '';
// -----------------------------------------------------
// The string exceeds the character limit. Add each word
// to the output individually until we reach the limit.
// -----------------------------------------------------
foreach (explode(' ', trim($value)) as $val)
{
// -----------------------------------------------------
// Add the word to the output.
// -----------------------------------------------------
$out .= $val.' ';
// -----------------------------------------------------
// Check the output length.
// -----------------------------------------------------
if (strlen($out) >= $limit)
{
// -----------------------------------------------------
// Trim the output.
// -----------------------------------------------------
$out = trim($out);
// -----------------------------------------------------
// Add the ending character to the string.
// -----------------------------------------------------
return (strlen($out) == strlen($value)) ? $out : $out.$end;
}
}
}
/**
* Censor a string.
*
* @param string $value
* @param array $censored
* @param string $replacement
* @return string
*/
public static function censor($value, $censored, $replacement = '####')
{
// -----------------------------------------------------
// Pad the value with spaces.
// -----------------------------------------------------
$value = ' '.$value.' ';
// -----------------------------------------------------
// Assume the word will be book-ended by the following.
// -----------------------------------------------------
$delim = '[-_\'\"`(){}<>\[\]|!?@#%&,.:;^~*+=\/ 0-9\n\r\t]';
// -----------------------------------------------------
// Replace the censored words.
// -----------------------------------------------------
foreach ($censored as $word)
{
if ($replacement != '')
{
$value = preg_replace("/({$delim})(".str_replace('\*', '\w*?', preg_quote($word, '/')).")({$delim})/i", "\\1{$replacement}\\3", $value);
}
else
{
$value = preg_replace("/({$delim})(".str_replace('\*', '\w*?', preg_quote($word, '/')).")({$delim})/ie", "'\\1'.str_repeat('#', strlen('\\2')).'\\3'", $value);
}
}
return trim($value);
}
}

132
system/url.php Normal file
View File

@@ -0,0 +1,132 @@
<?php namespace System;
class URL {
/**
* Generate an application URL.
*
* @param string $url
* @return string
*/
public static function to($url = '', $https = false)
{
// ----------------------------------------------------
// Return the URL unchanged if it is already formed.
// ----------------------------------------------------
if (strpos($url, '://') !== false)
{
return $url;
}
// ----------------------------------------------------
// Get the base URL of the application.
// ----------------------------------------------------
$base = Config::get('application.url');
// ----------------------------------------------------
// Does the URL need an HTTPS protocol?
// ----------------------------------------------------
if (strpos($base, 'http://') === 0 and $https)
{
$base = 'https://'.substr($base, 7);
}
return rtrim($base, '/').'/'.ltrim($url, '/');
}
/**
* Generate an application URL with HTTPS.
*
* @param string $url
* @return string
*/
public static function to_secure($url = '')
{
return static::to($url, true);
}
/**
* Generate a URL from a route name.
*
* @param string $name
* @param array $parameters
* @param bool $https
* @return string
*/
public static function to_route($name, $parameters = array(), $https = false)
{
// ----------------------------------------------------
// Does the named route exist?
// ----------------------------------------------------
if ( ! is_null($route = Router::find($name)))
{
$uris = explode(', ', key($route));
// ----------------------------------------------------
// Get the first URI assigned to the route.
// ----------------------------------------------------
$uri = substr($uris[0], strpos($uris[0], '/'));
// ----------------------------------------------------
// Replace any parameters in the URI.
// ----------------------------------------------------
foreach ($parameters as $parameter)
{
$uri = preg_replace('/\(\:any\)|\(\:num\)|\(.+\)/', $parameter, $uri, 1);
}
return static::to($uri, $https);
}
throw new \Exception("Error generating named route for route [$name]. Route is not defined.");
}
/**
* Generate a URL friendly "slug".
*
* @param string $title
* @param string $separator
* @return string
*/
public static function slug($title, $separator = '-')
{
// ----------------------------------------------------
// Remove all characters that are not the separator,
// letters, numbers, or whitespace.
// ----------------------------------------------------
$title = preg_replace('![^'.preg_quote($separator).'\pL\pN\s]+!u', '', Str::lower($title));
// ----------------------------------------------------
// Replace all separator characters and whitespace by
// a single separator
// ----------------------------------------------------
$title = preg_replace('!['.preg_quote($separator).'\s]+!u', $separator, $title);
return trim($title, $separator);
}
/**
* Magic Method for dynamically creating route URLs.
*/
public static function __callStatic($method, $parameters)
{
// ----------------------------------------------------
// Dynamically create a secure route URL.
// ----------------------------------------------------
if (strpos($method, 'to_secure_') === 0)
{
return static::to_route(substr($method, 10), $parameters, true);
}
// ----------------------------------------------------
// Dynamically create a route URL.
// ----------------------------------------------------
if (strpos($method, 'to_') === 0)
{
return static::to_route(substr($method, 3), $parameters);
}
throw new \Exception("Method [$method] is not defined on the URL class.");
}
}

191
system/view.php Normal file
View File

@@ -0,0 +1,191 @@
<?php namespace System;
class View {
/**
* The name of the view.
*
* @var string
*/
public $view;
/**
* The view data.
*
* @var array
*/
public $data = array();
/**
* The content of the view.
*
* @var string
*/
public $content = '';
/**
* The name of last rendered view.
*
* @var string
*/
public static $last;
/**
* Create a new view instance.
*
* @param string $view
* @param array $data
* @return void
*/
public function __construct($view, $data = array())
{
$this->view = $view;
$this->data = $data;
// -----------------------------------------------------
// Get the contents of the view from the file system.
// -----------------------------------------------------
$this->content = $this->load($view);
}
/**
* Create a new view instance.
*
* @param string $view
* @param array $data
* @return View
*/
public static function make($view, $data = array())
{
return new self($view, $data);
}
/**
* Load the content of a view.
*
* @param string $view
* @return string
*/
private function load($view)
{
// -----------------------------------------------------
// Is the view in the application directory?
// -----------------------------------------------------
if (file_exists($path = APP_PATH.'views/'.$view.EXT))
{
return file_get_contents($path);
}
// -----------------------------------------------------
// Is the view in the system directory?
// -----------------------------------------------------
elseif (file_exists($path = SYS_PATH.'views/'.$view.EXT))
{
return file_get_contents($path);
}
// -----------------------------------------------------
// Could not locate the view... bail out.
// -----------------------------------------------------
else
{
throw new \Exception("View [$view] doesn't exist.");
}
}
/**
* Add a key / value pair to the view data.
*
* @param string $key
* @param mixed $value
* @return View
*/
public function bind($key, $value)
{
$this->data[$key] = $value;
return $this;
}
/**
* Get the parsed content of the view.
*
* @return string
*/
public function get()
{
// -----------------------------------------------------
// Set the name of the last rendered view.
// -----------------------------------------------------
static::$last = $this->view;
// -----------------------------------------------------
// Get the content of all of the sub-views.
// -----------------------------------------------------
foreach ($this->data as &$data)
{
if ($data instanceof View or $data instanceof Response)
{
$data = (string) $data;
}
}
// -----------------------------------------------------
// Extract the view data into the local scope.
// -----------------------------------------------------
extract($this->data, EXTR_SKIP);
// -----------------------------------------------------
// Start an output buffer to catch the content.
// -----------------------------------------------------
ob_start();
// -----------------------------------------------------
// Echo the content of the view.
// -----------------------------------------------------
echo eval('?>'.$this->content);
// -----------------------------------------------------
// Get the contents of the output buffer.
// -----------------------------------------------------
return ob_get_clean();
}
/**
* Magic Method for getting items from the view data.
*/
public function __get($key)
{
return $this->data[$key];
}
/**
* Magic Method for setting items in the view data.
*/
public function __set($key, $value)
{
$this->bind($key, $value);
}
/**
* Magic Method for determining if an item is in the view data.
*/
public function __isset($key)
{
return array_key_exists($key, $this->data);
}
/**
* Magic Method for removing an item from the view data.
*/
public function __unset($key)
{
unset($this->data[$key]);
}
/**
* Get the parsed content of the View.
*/
public function __toString()
{
return $this->get();
}
}

View File

@@ -0,0 +1,78 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Laravel - Error</title>
<link href='http://fonts.googleapis.com/css?family=Ubuntu&amp;subset=latin' rel='stylesheet' type='text/css'>
<style type="text/css">
body {
background-color: #fff;
font-family: 'Ubuntu', sans-serif;
font-size: 18px;
color: #3f3f3f;
padding: 10px;
}
h1 {
font-family: 'Ubuntu', sans-serif;
font-size: 45px;
color: #6d6d6d;
margin: 0 0 10px 0;
}
h3 {
color: #6d6d6d;
margin: 0 0 10px 0;
}
pre {
font-size: 14px;
margin: 0 0 0 0;
padding: 0 0 0 0;
}
#wrapper {
width: 100%;
}
div.content {
padding: 10px 10px 10px 10px;
background-color: #eee;
border-radius: 10px;
margin-bottom: 10px;
}
</style>
</head>
<body>
<div id="wrapper">
<h1><?php echo $severity; ?></h1>
<div class="content">
<h3>Message:</h3>
<?php echo $message; ?> in <strong><?php echo basename($file); ?></strong> on line <strong><?php echo $line; ?></strong>.
</div>
<div class="content">
<h3>Stack Trace:</h3>
<pre><?php echo $trace; ?></pre>
</div>
<div class="content">
<h3>Context:</h3>
<?php if (count($contexts) > 0) { ?>
<?php foreach ($contexts as $num => $context) { ?>
<pre><?php echo htmlentities($num.' '.$context); ?></pre>
<?php } ?>
<?php } else { ?>
Context unavailable.
<?php } ?>
</div>
</div>
</body>
</html>