first commit of 2.0
This commit is contained in:
81
laravel/arr.php
Normal file
81
laravel/arr.php
Normal file
@@ -0,0 +1,81 @@
|
||||
<?php namespace Laravel;
|
||||
|
||||
class Arr {
|
||||
|
||||
/**
|
||||
* Get an item from an array.
|
||||
*
|
||||
* If the specified key is null, the entire array will be returned. The array may
|
||||
* also be accessed using JavaScript "dot" style notation. Retrieving items nested
|
||||
* in multiple arrays is also supported.
|
||||
*
|
||||
* <code>
|
||||
* // Returns "taylor"
|
||||
* Arr::get(array('name' => array('is' => 'Taylor')), 'name.is');
|
||||
* </code>
|
||||
*
|
||||
* @param array $array
|
||||
* @param string $key
|
||||
* @param mixed $default
|
||||
* @return mixed
|
||||
*/
|
||||
public static function get($array, $key, $default = null)
|
||||
{
|
||||
if (is_null($key)) return $array;
|
||||
|
||||
foreach (explode('.', $key) as $segment)
|
||||
{
|
||||
if ( ! is_array($array) or ! array_key_exists($segment, $array))
|
||||
{
|
||||
return is_callable($default) ? call_user_func($default) : $default;
|
||||
}
|
||||
|
||||
$array = $array[$segment];
|
||||
}
|
||||
|
||||
return $array;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set an array item to a given value.
|
||||
*
|
||||
* This method is primarly helpful for setting the value in an array with
|
||||
* a variable depth, such as configuration arrays.
|
||||
*
|
||||
* If the specified item doesn't exist, it will be created. If the item's
|
||||
* parents do no exist, they will also be created as arrays.
|
||||
*
|
||||
* Like the Arr::get method, JavaScript "dot" syntax is supported.
|
||||
*
|
||||
* <code>
|
||||
* // Set "name.is" to "taylor"
|
||||
* Arr::set(array('name' => array('is' => 'something')), 'name.is', 'taylor');
|
||||
* </code>
|
||||
*
|
||||
* @param array $array
|
||||
* @param string $key
|
||||
* @param mixed $value
|
||||
* @return void
|
||||
*/
|
||||
public static function set(&$array, $key, $value)
|
||||
{
|
||||
if (is_null($key)) return $array = $value;
|
||||
|
||||
$keys = explode('.', $key);
|
||||
|
||||
while (count($keys) > 1)
|
||||
{
|
||||
$key = array_shift($keys);
|
||||
|
||||
if ( ! isset($array[$key]) or ! is_array($array[$key]))
|
||||
{
|
||||
$array[$key] = array();
|
||||
}
|
||||
|
||||
$array =& $array[$key];
|
||||
}
|
||||
|
||||
$array[array_shift($keys)] = $value;
|
||||
}
|
||||
|
||||
}
|
||||
360
laravel/asset.php
Normal file
360
laravel/asset.php
Normal file
@@ -0,0 +1,360 @@
|
||||
<?php namespace Laravel;
|
||||
|
||||
use Laravel\File;
|
||||
use Laravel\HTML;
|
||||
|
||||
class Asset {
|
||||
|
||||
/**
|
||||
* All of the instantiated asset containers.
|
||||
*
|
||||
* Asset containers are created through the container method, and are singletons.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $containers = array();
|
||||
|
||||
/**
|
||||
* Get an asset container instance.
|
||||
*
|
||||
* If no container name is specified, the default container will be returned.
|
||||
* Containers provide a convenient method of grouping assets while maintaining
|
||||
* expressive code and a clean API.
|
||||
*
|
||||
* <code>
|
||||
* // Get the default asset container
|
||||
* $container = Asset::container();
|
||||
*
|
||||
* // Get the "footer" asset container
|
||||
* $container = Asset::container('footer');
|
||||
* </code>
|
||||
*
|
||||
* @param string $container
|
||||
* @return Asset_Container
|
||||
*/
|
||||
public static function container($container = 'default')
|
||||
{
|
||||
if ( ! isset(static::$containers[$container]))
|
||||
{
|
||||
static::$containers[$container] = new Asset_Container($container);
|
||||
}
|
||||
|
||||
return static::$containers[$container];
|
||||
}
|
||||
|
||||
/**
|
||||
* Magic Method for calling methods on the default Asset container.
|
||||
*
|
||||
* This provides a convenient API, allowing the develop to skip the "container"
|
||||
* method when using the default container.
|
||||
*
|
||||
* <code>
|
||||
* // Add an asset to the default container
|
||||
* Asset::add('jquery', 'js/jquery.js');
|
||||
*
|
||||
* // Equivalent statement using the container method
|
||||
* Asset::container()->add('jquery', 'js/jquery.js');
|
||||
* </code>
|
||||
*/
|
||||
public static function __callStatic($method, $parameters)
|
||||
{
|
||||
return call_user_func_array(array(static::container(), $method), $parameters);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class Asset_Container {
|
||||
|
||||
/**
|
||||
* The asset container name.
|
||||
*
|
||||
* This name may be used to access the container instance via the Asset::container method.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $name;
|
||||
|
||||
/**
|
||||
* All of the registered assets.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public $assets = array();
|
||||
|
||||
/**
|
||||
* Create a new asset container instance.
|
||||
*
|
||||
* @param string $name
|
||||
* @return void
|
||||
*/
|
||||
public function __construct($name)
|
||||
{
|
||||
$this->name = $name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add an asset to the container.
|
||||
*
|
||||
* The extension of the asset source will be used to determine the type of
|
||||
* asset being registered (CSS or JavaScript). If you are using a non-standard
|
||||
* extension, you may use the style or script methods to register assets.
|
||||
*
|
||||
* You may also specify asset dependencies. This will instruct the class to
|
||||
* only link to the registered asset after its dependencies have been linked.
|
||||
* For example, you may wish to make jQuery UI dependent on jQuery.
|
||||
*
|
||||
* <code>
|
||||
* // Add an asset to the container
|
||||
* Asset::container()->add('jquery', 'js/jquery.js');
|
||||
*
|
||||
* // Add an asset that is dependent on another asset
|
||||
* Asset::container()->add('jquery-ui', 'js/jquery-ui.js', array('jquery'));
|
||||
* </code>
|
||||
*
|
||||
* @param string $name
|
||||
* @param string $source
|
||||
* @param array $dependencies
|
||||
* @param array $attributes
|
||||
* @return void
|
||||
*/
|
||||
public function add($name, $source, $dependencies = array(), $attributes = array())
|
||||
{
|
||||
$type = (File::extension($source) == 'css') ? 'style' : 'script';
|
||||
|
||||
return call_user_func(array($this, $type), $name, $source, $dependencies, $attributes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add CSS to the registered assets.
|
||||
*
|
||||
* @param string $name
|
||||
* @param string $source
|
||||
* @param array $dependencies
|
||||
* @param array $attributes
|
||||
* @return void
|
||||
*/
|
||||
public function style($name, $source, $dependencies = array(), $attributes = array())
|
||||
{
|
||||
if ( ! array_key_exists('media', $attributes))
|
||||
{
|
||||
$attributes['media'] = 'all';
|
||||
}
|
||||
|
||||
$this->register('style', $name, $source, $dependencies, $attributes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add JavaScript to the registered assets.
|
||||
*
|
||||
* @param string $name
|
||||
* @param string $source
|
||||
* @param array $dependencies
|
||||
* @param array $attributes
|
||||
* @return void
|
||||
*/
|
||||
public function script($name, $source, $dependencies = array(), $attributes = array())
|
||||
{
|
||||
$this->register('script', $name, $source, $dependencies, $attributes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add an asset to the array of registered assets.
|
||||
*
|
||||
* Assets are organized in the array by type (CSS or JavaScript).
|
||||
*
|
||||
* @param string $type
|
||||
* @param string $name
|
||||
* @param string $source
|
||||
* @param array $dependencies
|
||||
* @param array $attributes
|
||||
* @return void
|
||||
*/
|
||||
private function register($type, $name, $source, $dependencies, $attributes)
|
||||
{
|
||||
$dependencies = (array) $dependencies;
|
||||
|
||||
$this->assets[$type][$name] = compact('source', 'dependencies', 'attributes');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the links to all of the registered CSS assets.
|
||||
*
|
||||
* <code>
|
||||
* echo Asset::container()->styles();
|
||||
* </code>
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function styles()
|
||||
{
|
||||
return $this->get_group('style');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the links to all of the registered JavaScript assets.
|
||||
*
|
||||
* <code>
|
||||
* echo Asset::container()->scripts();
|
||||
* </code>
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function scripts()
|
||||
{
|
||||
return $this->get_group('script');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all of the registered assets for a given type / group.
|
||||
*
|
||||
* @param string $group
|
||||
* @return string
|
||||
*/
|
||||
private function get_group($group)
|
||||
{
|
||||
if ( ! isset($this->assets[$group]) or count($this->assets[$group]) == 0) return '';
|
||||
|
||||
$assets = '';
|
||||
|
||||
foreach ($this->arrange($this->assets[$group]) as $name => $data)
|
||||
{
|
||||
$assets .= $this->get_asset($group, $name);
|
||||
}
|
||||
|
||||
return $assets;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the link to a single registered CSS asset.
|
||||
*
|
||||
* <code>
|
||||
* echo Asset::container()->get_style('common');
|
||||
* </code>
|
||||
*
|
||||
* @param string $name
|
||||
* @return string
|
||||
*/
|
||||
public function get_style($name)
|
||||
{
|
||||
return $this->get_asset('style', $name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the link to a single registered JavaScript asset.
|
||||
*
|
||||
* <code>
|
||||
* echo Asset::container()->get_script('jquery');
|
||||
* </code>
|
||||
*
|
||||
* @param string $name
|
||||
* @return string
|
||||
*/
|
||||
public function get_script($name)
|
||||
{
|
||||
return $this->get_asset('script', $name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the HTML link to a registered asset.
|
||||
*
|
||||
* @param string $group
|
||||
* @param string $name
|
||||
* @return string
|
||||
*/
|
||||
private function get_asset($group, $name)
|
||||
{
|
||||
if ( ! isset($this->assets[$group][$name])) return '';
|
||||
|
||||
$asset = $this->assets[$group][$name];
|
||||
|
||||
return HTML::$group($asset['source'], $asset['attributes']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sort and retrieve assets based on their dependencies
|
||||
*
|
||||
* @param array $assets
|
||||
* @return array
|
||||
*/
|
||||
private function arrange($assets)
|
||||
{
|
||||
list($original, $sorted) = array($assets, array());
|
||||
|
||||
while (count($assets) > 0)
|
||||
{
|
||||
foreach ($assets as $asset => $value)
|
||||
{
|
||||
$this->evaluate_asset($asset, $value, $original, $sorted, $assets);
|
||||
}
|
||||
}
|
||||
|
||||
return $sorted;
|
||||
}
|
||||
|
||||
/**
|
||||
* Evaluate an asset and its dependencies.
|
||||
*
|
||||
* @param string $asset
|
||||
* @param string $value
|
||||
* @param array $original
|
||||
* @param array $sorted
|
||||
* @param array $assets
|
||||
* @return void
|
||||
*/
|
||||
private function evaluate_asset($asset, $value, $original, &$sorted, &$assets)
|
||||
{
|
||||
// If the asset has no more dependencies, we can add it to the sorted list
|
||||
// and remove it from the array of assets. Otherwise, we will not verify
|
||||
// the asset's dependencies and determine if they have already been sorted.
|
||||
if (count($assets[$asset]['dependencies']) == 0)
|
||||
{
|
||||
$sorted[$asset] = $value;
|
||||
unset($assets[$asset]);
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach ($assets[$asset]['dependencies'] as $key => $dependency)
|
||||
{
|
||||
if ( ! $this->dependency_is_valid($asset, $dependency, $original, $assets))
|
||||
{
|
||||
unset($assets[$asset]['dependencies'][$key]);
|
||||
continue;
|
||||
}
|
||||
|
||||
// If the dependency has not yet been added to the sorted list, we can not
|
||||
// remove it from this asset's array of dependencies. We'll try again on
|
||||
// the next trip through the loop.
|
||||
if ( ! isset($sorted[$dependency])) continue;
|
||||
|
||||
unset($assets[$asset]['dependencies'][$key]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Verify that an asset's dependency is valid.
|
||||
*
|
||||
* A dependency is considered valid if it exists, is not a circular reference, and is
|
||||
* not a reference to the owning asset itself.
|
||||
*
|
||||
* @param string $asset
|
||||
* @param string $dependency
|
||||
* @param array $original
|
||||
* @param array $assets
|
||||
* @return bool
|
||||
*/
|
||||
private function dependency_is_valid($asset, $dependency, $original, $assets)
|
||||
{
|
||||
if ( ! isset($original[$dependency])) return false;
|
||||
|
||||
if ($dependency === $asset)
|
||||
{
|
||||
throw new \Exception("Asset [$asset] is dependent on itself.");
|
||||
}
|
||||
elseif (isset($assets[$dependency]) and in_array($asset, $assets[$dependency]['dependencies']))
|
||||
{
|
||||
throw new \Exception("Assets [$asset] and [$dependency] have a circular dependency.");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
132
laravel/auth.php
Normal file
132
laravel/auth.php
Normal file
@@ -0,0 +1,132 @@
|
||||
<?php namespace Laravel;
|
||||
|
||||
if (Config::get('session.driver') == '')
|
||||
{
|
||||
throw new \Exception("You must specify a session driver before using the Auth class.");
|
||||
}
|
||||
|
||||
class Auth {
|
||||
|
||||
/**
|
||||
* The current user of the application.
|
||||
*
|
||||
* If no user is logged in, this will be NULL. Otherwise, it will contain the result
|
||||
* of the "by_id" closure in the authentication configuration file.
|
||||
*
|
||||
* Typically, the user should be accessed via the "user" method.
|
||||
*
|
||||
* @var object
|
||||
*/
|
||||
public static $user;
|
||||
|
||||
/**
|
||||
* The key used to store the user ID in the session.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected static $key = 'laravel_user_id';
|
||||
|
||||
/**
|
||||
* Determine if the current user of the application is authenticated.
|
||||
*
|
||||
* @see login()
|
||||
* @return bool
|
||||
*/
|
||||
public static function check()
|
||||
{
|
||||
return ! is_null(static::user());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the current user of the application.
|
||||
*
|
||||
* To retrieve the user, the user ID stored in the session will be passed to
|
||||
* the "by_id" closure in the authentication configuration file. The result
|
||||
* of the closure will be cached and returned.
|
||||
*
|
||||
* <code>
|
||||
* $email = Auth::user()->email;
|
||||
* </code>
|
||||
*
|
||||
* @return object
|
||||
*/
|
||||
public static function user()
|
||||
{
|
||||
if (is_null(static::$user) and Session::has(static::$key))
|
||||
{
|
||||
static::$user = call_user_func(Config::get('auth.by_id'), Session::get(static::$key));
|
||||
}
|
||||
|
||||
return static::$user;
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempt to log a user into your application.
|
||||
*
|
||||
* If the user credentials are valid. The user's ID will be stored in the session and the
|
||||
* user will be considered "logged in" on subsequent requests to the application.
|
||||
*
|
||||
* The password passed to the method should be plain text, as it will be hashed
|
||||
* by the Hash class when authenticating.
|
||||
*
|
||||
* <code>
|
||||
* if (Auth::login('email@example.com', 'password'))
|
||||
* {
|
||||
* // The credentials are valid and the user is now logged in.
|
||||
* }
|
||||
* </code>
|
||||
*
|
||||
* @param string $username
|
||||
* @param string $password
|
||||
* @return bool
|
||||
*/
|
||||
public static function login($username, $password)
|
||||
{
|
||||
if ( ! is_null($user = call_user_func(Config::get('auth.by_username'), $username)))
|
||||
{
|
||||
if (Hash::check($password, $user->password))
|
||||
{
|
||||
static::remember($user);
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Log a user into your application.
|
||||
*
|
||||
* The user's ID will be stored in the session and the user will be considered
|
||||
* "logged in" on subsequent requests to your application. This method is called
|
||||
* by the login method after determining a user's credentials are valid.
|
||||
*
|
||||
* Note: The user given to this method should be an object having an "id" property.
|
||||
*
|
||||
* @param object $user
|
||||
* @return void
|
||||
*/
|
||||
public static function remember($user)
|
||||
{
|
||||
static::$user = $user;
|
||||
|
||||
Session::put(static::$key, $user->id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Log the user out of your application.
|
||||
*
|
||||
* The user ID will be removed from the session and the user will no longer
|
||||
* be considered logged in on subsequent requests to your application.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public static function logout()
|
||||
{
|
||||
static::$user = null;
|
||||
|
||||
Session::forget(static::$key);
|
||||
}
|
||||
|
||||
}
|
||||
52
laravel/benchmark.php
Normal file
52
laravel/benchmark.php
Normal file
@@ -0,0 +1,52 @@
|
||||
<?php namespace Laravel;
|
||||
|
||||
class Benchmark {
|
||||
|
||||
/**
|
||||
* All of the benchmark starting times.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $marks = array();
|
||||
|
||||
/**
|
||||
* Start a benchmark.
|
||||
*
|
||||
* After starting a benchmark, the elapsed time in milliseconds can be
|
||||
* retrieved using the "check" method.
|
||||
*
|
||||
* @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);
|
||||
}
|
||||
|
||||
}
|
||||
70
laravel/cache.php
Normal file
70
laravel/cache.php
Normal file
@@ -0,0 +1,70 @@
|
||||
<?php namespace Laravel;
|
||||
|
||||
class Cache {
|
||||
|
||||
/**
|
||||
* All of the active cache drivers.
|
||||
*
|
||||
* @var Cache\Driver
|
||||
*/
|
||||
public static $drivers = array();
|
||||
|
||||
/**
|
||||
* Get a cache driver instance.
|
||||
*
|
||||
* If no driver name is specified, the default cache driver will be returned
|
||||
* as defined in the cache configuration file.
|
||||
*
|
||||
* <code>
|
||||
* // Get the default cache driver
|
||||
* $driver = Cache::driver();
|
||||
*
|
||||
* // Get the APC cache driver
|
||||
* $apc = Cache::driver('apc');
|
||||
* </code>
|
||||
*
|
||||
* @param string $driver
|
||||
* @return Cache\Driver
|
||||
*/
|
||||
public static function driver($driver = null)
|
||||
{
|
||||
if (is_null($driver)) $driver = Config::get('cache.driver');
|
||||
|
||||
if ( ! array_key_exists($driver, static::$drivers))
|
||||
{
|
||||
switch ($driver)
|
||||
{
|
||||
case 'file':
|
||||
return static::$drivers[$driver] = new Cache\File;
|
||||
|
||||
case 'memcached':
|
||||
return static::$drivers[$driver] = new Cache\Memcached;
|
||||
|
||||
case 'apc':
|
||||
return static::$drivers[$driver] = new Cache\APC;
|
||||
|
||||
default:
|
||||
throw new \Exception("Cache driver [$driver] is not supported.");
|
||||
}
|
||||
}
|
||||
|
||||
return static::$drivers[$driver];
|
||||
}
|
||||
|
||||
/**
|
||||
* Pass all other methods to the default driver.
|
||||
*
|
||||
* Passing method calls to the driver instance provides a convenient API for the developer
|
||||
* when always using the default cache driver.
|
||||
*
|
||||
* <code>
|
||||
* // Get an item from the default cache driver
|
||||
* $name = Cache::get('name');
|
||||
* </code>
|
||||
*/
|
||||
public static function __callStatic($method, $parameters)
|
||||
{
|
||||
return call_user_func_array(array(static::driver(), $method), $parameters);
|
||||
}
|
||||
|
||||
}
|
||||
29
laravel/cache/apc.php
vendored
Normal file
29
laravel/cache/apc.php
vendored
Normal file
@@ -0,0 +1,29 @@
|
||||
<?php namespace Laravel\Cache;
|
||||
|
||||
use Laravel\Config;
|
||||
|
||||
class APC extends Driver {
|
||||
|
||||
public function has($key)
|
||||
{
|
||||
return ( ! is_null($this->get($key)));
|
||||
}
|
||||
|
||||
public function get($key, $default = null)
|
||||
{
|
||||
$item = ( ! is_null($cache = apc_fetch(Config::get('cache.key').$key))) ? $cache : null;
|
||||
|
||||
return $this->prepare($item, $default);
|
||||
}
|
||||
|
||||
public function put($key, $value, $minutes)
|
||||
{
|
||||
apc_store(Config::get('cache.key').$key, $value, $minutes * 60);
|
||||
}
|
||||
|
||||
public function forget($key)
|
||||
{
|
||||
apc_delete(Config::get('cache.key').$key);
|
||||
}
|
||||
|
||||
}
|
||||
93
laravel/cache/driver.php
vendored
Normal file
93
laravel/cache/driver.php
vendored
Normal file
@@ -0,0 +1,93 @@
|
||||
<?php namespace Laravel\Cache;
|
||||
|
||||
abstract class Driver {
|
||||
|
||||
/**
|
||||
* Determine if an item exists in the cache.
|
||||
*
|
||||
* @param string $key
|
||||
* @return bool
|
||||
*/
|
||||
abstract public function has($key);
|
||||
|
||||
/**
|
||||
* Get an item from the cache.
|
||||
*
|
||||
* A default value may also be specified, and will be returned in the requested
|
||||
* item does not exist in the cache.
|
||||
*
|
||||
* <code>
|
||||
* // Get the "name" item from the cache
|
||||
* $name = Cache::driver()->get('name');
|
||||
*
|
||||
* // Get the "name" item from the cache or return "Fred"
|
||||
* $name = Cache::driver()->get('name', 'Fred');
|
||||
* </code>
|
||||
*
|
||||
* @param string $key
|
||||
* @param mixed $default
|
||||
* @param string $driver
|
||||
* @return mixed
|
||||
*/
|
||||
abstract public function get($key, $default = null);
|
||||
|
||||
/**
|
||||
* Prepare the cache item for returning to the requestor.
|
||||
*
|
||||
* If the item is NULL, the default will be returned.
|
||||
*
|
||||
* @param mixed $item
|
||||
* @param mixed $default
|
||||
* @return mixed
|
||||
*/
|
||||
protected function prepare($item, $default)
|
||||
{
|
||||
if ( ! is_null($item)) return $item;
|
||||
|
||||
return (is_callable($default)) ? call_user_func($default) : $default;
|
||||
}
|
||||
|
||||
/**
|
||||
* Write an item to the cache.
|
||||
*
|
||||
* @param string $key
|
||||
* @param mixed $value
|
||||
* @param int $minutes
|
||||
* @return void
|
||||
*/
|
||||
abstract public function put($key, $value, $minutes);
|
||||
|
||||
/**
|
||||
* Get an item from the cache. If the item doesn't exist in the cache, store
|
||||
* the default value in the cache and return it.
|
||||
*
|
||||
* <code>
|
||||
* // Get the "name" item from the cache or store "Fred" for 30 minutes
|
||||
* $name = Cache::driver()->remember('name', 'Fred', 30);
|
||||
* </code>
|
||||
*
|
||||
* @param string $key
|
||||
* @param mixed $default
|
||||
* @param int $minutes
|
||||
* @return mixed
|
||||
*/
|
||||
public function remember($key, $value, $minutes)
|
||||
{
|
||||
if ( ! is_null($item = $this->get($key, null, $driver))) return $item;
|
||||
|
||||
$default = is_callable($default) ? call_user_func($default) : $default;
|
||||
|
||||
$this->put($key, $default, $minutes);
|
||||
|
||||
return $default;
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete an item from the cache.
|
||||
*
|
||||
* @param string $key
|
||||
* @return void
|
||||
*/
|
||||
abstract public function forget($key);
|
||||
|
||||
}
|
||||
41
laravel/cache/file.php
vendored
Normal file
41
laravel/cache/file.php
vendored
Normal file
@@ -0,0 +1,41 @@
|
||||
<?php namespace Laravel\Cache;
|
||||
|
||||
class File extends Driver {
|
||||
|
||||
public function has($key)
|
||||
{
|
||||
return ( ! is_null($this->get($key)));
|
||||
}
|
||||
|
||||
public function get($key, $default = null)
|
||||
{
|
||||
if ( ! file_exists(CACHE_PATH.$key))
|
||||
{
|
||||
return $this->prepare(null, $default);
|
||||
}
|
||||
|
||||
$cache = file_get_contents(CACHE_PATH.$key);
|
||||
|
||||
// The cache expiration date is stored as a UNIX timestamp at the beginning
|
||||
// of the cache file. We'll extract it out and check it here.
|
||||
if (time() >= substr($cache, 0, 10))
|
||||
{
|
||||
$this->forget($key);
|
||||
|
||||
return $this->prepare(null, $default);
|
||||
}
|
||||
|
||||
return $this->prepare(unserialize(substr($cache, 10)), $default);
|
||||
}
|
||||
|
||||
public function put($key, $value, $minutes)
|
||||
{
|
||||
file_put_contents(CACHE_PATH.$key, (time() + ($minutes * 60)).serialize($value), LOCK_EX);
|
||||
}
|
||||
|
||||
public function forget($key)
|
||||
{
|
||||
@unlink(CACHE_PATH.$key);
|
||||
}
|
||||
|
||||
}
|
||||
30
laravel/cache/memcached.php
vendored
Normal file
30
laravel/cache/memcached.php
vendored
Normal file
@@ -0,0 +1,30 @@
|
||||
<?php namespace Laravel\Cache;
|
||||
|
||||
use Laravel\Config;
|
||||
use Laravel\Memcached as Mem;
|
||||
|
||||
class Memcached extends Driver {
|
||||
|
||||
public function has($key)
|
||||
{
|
||||
return ( ! is_null($this->get($key)));
|
||||
}
|
||||
|
||||
public function get($key, $default = null)
|
||||
{
|
||||
$item = (($cache = Mem::instance()->get(Config::get('cache.key').$key)) !== false) ? $cache : null;
|
||||
|
||||
return $this->prepare($item, $default);
|
||||
}
|
||||
|
||||
public function put($key, $value, $minutes)
|
||||
{
|
||||
Mem::instance()->set(Config::get('cache.key').$key, $value, 0, $minutes * 60);
|
||||
}
|
||||
|
||||
public function forget($key)
|
||||
{
|
||||
Mem::instance()->delete(Config::get('cache.key').$key);
|
||||
}
|
||||
|
||||
}
|
||||
170
laravel/config.php
Normal file
170
laravel/config.php
Normal file
@@ -0,0 +1,170 @@
|
||||
<?php namespace Laravel;
|
||||
|
||||
class Config {
|
||||
|
||||
/**
|
||||
* All of the loaded configuration items.
|
||||
*
|
||||
* The configuration arrays are keyed by module and file names.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $items = array();
|
||||
|
||||
/**
|
||||
* Determine if a configuration item or file exists.
|
||||
*
|
||||
* <code>
|
||||
* // Determine if the "session" configuration file exists
|
||||
* Config::has('session');
|
||||
*
|
||||
* // Determine if the application timezone option exists
|
||||
* Config::has('application.timezone');
|
||||
* </code>
|
||||
*
|
||||
* @param string $key
|
||||
* @return bool
|
||||
*/
|
||||
public static function has($key)
|
||||
{
|
||||
return ! is_null(static::get($key));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a configuration item.
|
||||
*
|
||||
* Configuration items are retrieved using "dot" notation. So, asking for the
|
||||
* "application.timezone" configuration item would return the "timezone" option
|
||||
* from the "application" configuration file.
|
||||
*
|
||||
* If the name of a configuration file is passed without specifying an item, the
|
||||
* entire configuration array will be returned.
|
||||
*
|
||||
* <code>
|
||||
* // Get the timezone option from the application configuration file
|
||||
* $timezone = Config::get('application.timezone');
|
||||
*
|
||||
* // Get the SQLite database connection configuration
|
||||
* $sqlite = Config::get('db.connections.sqlite');
|
||||
* </code>
|
||||
*
|
||||
* @param string $key
|
||||
* @param string $default
|
||||
* @return array
|
||||
*/
|
||||
public static function get($key, $default = null)
|
||||
{
|
||||
list($module, $file, $key) = static::parse($key);
|
||||
|
||||
if ( ! static::load($module, $file))
|
||||
{
|
||||
return is_callable($default) ? call_user_func($default) : $default;
|
||||
}
|
||||
|
||||
if (is_null($key)) return static::$items[$module][$file];
|
||||
|
||||
return Arr::get(static::$items[$module][$file], $key, $default);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a configuration item.
|
||||
*
|
||||
* Like the get method, "dot" notation is used to set items, and setting items
|
||||
* at any depth in the configuration array is supported.
|
||||
*
|
||||
* If a specific configuration item is not specified, the entire configuration
|
||||
* array will be replaced with the given value.
|
||||
*
|
||||
* <code>
|
||||
* // Set the timezone option in the application configuration file
|
||||
* Config::set('application.timezone', 'America/Chicago');
|
||||
*
|
||||
* // Set the session configuration array
|
||||
* Config::set('session', array());
|
||||
* </code>
|
||||
*
|
||||
* @param string $key
|
||||
* @param mixed $value
|
||||
* @return void
|
||||
*/
|
||||
public static function set($key, $value)
|
||||
{
|
||||
list($module, $file, $key) = static::parse($key);
|
||||
|
||||
if ( ! static::load($module, $file))
|
||||
{
|
||||
throw new \Exception("Error setting configuration option. Configuration file [$file] is not defined.");
|
||||
}
|
||||
|
||||
Arr::set(static::$items[$module][$file], $key, $value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse a configuration key and return its module, file, and key segments.
|
||||
*
|
||||
* Modular configuration keys follow a {module}::{file}.{key} convention.
|
||||
*
|
||||
* @param string $key
|
||||
* @return array
|
||||
*/
|
||||
private static function parse($key)
|
||||
{
|
||||
list($module, $key) = Module::parse($key);
|
||||
|
||||
$segments = explode('.', $key);
|
||||
|
||||
return array($module, $segments[0], (count($segments) > 1) ? implode('.', array_slice($segments, 1)) : null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Load all of the configuration items from a module configuration file.
|
||||
*
|
||||
* If the configuration file has already been loaded, it will not be loaded again.
|
||||
*
|
||||
* @param string $file
|
||||
* @param string $module
|
||||
* @return bool
|
||||
*/
|
||||
private static function load($module, $file)
|
||||
{
|
||||
if (isset(static::$items[$module]) and array_key_exists($file, static::$items[$module])) return true;
|
||||
|
||||
$config = array();
|
||||
|
||||
foreach (static::paths($module, $file) as $directory)
|
||||
{
|
||||
$config = (file_exists($path = $directory.$file.EXT)) ? array_merge($config, require $path) : $config;
|
||||
}
|
||||
|
||||
if (count($config) > 0) static::$items[$module][$file] = $config;
|
||||
|
||||
return isset(static::$items[$module][$file]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the path hierarchy for a given configuration file and module.
|
||||
*
|
||||
* The paths returned by this method paths will be searched by the load method when merging
|
||||
* configuration files, meaning the configuration files will cascade in this order.
|
||||
*
|
||||
* By default, the base configuration directory will be searched first, followed by the configuration
|
||||
* directory for the active module. Next, any environment specific configuration directories
|
||||
* will be searched.
|
||||
*
|
||||
* @param string $module
|
||||
* @param string $file
|
||||
* @return array
|
||||
*/
|
||||
private static function paths($module, $file)
|
||||
{
|
||||
$paths = array(CONFIG_PATH, Module::path($module).'config/');
|
||||
|
||||
if (isset($_SERVER['LARAVEL_ENV']))
|
||||
{
|
||||
$paths[] = Module::path($module).'/config/'.$_SERVER['LARAVEL_ENV'].'/';
|
||||
}
|
||||
|
||||
return $paths;
|
||||
}
|
||||
|
||||
}
|
||||
75
laravel/cookie.php
Normal file
75
laravel/cookie.php
Normal file
@@ -0,0 +1,75 @@
|
||||
<?php namespace Laravel;
|
||||
|
||||
class Cookie {
|
||||
|
||||
/**
|
||||
* Determine if a cookie exists.
|
||||
*
|
||||
* @param string $name
|
||||
* @return bool
|
||||
*/
|
||||
public static function has($name)
|
||||
{
|
||||
return ! is_null(static::get($name));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the value of a cookie.
|
||||
*
|
||||
* @param string $name
|
||||
* @param mixed $default
|
||||
* @return string
|
||||
*/
|
||||
public static function get($name, $default = null)
|
||||
{
|
||||
return Arr::get($_COOKIE, $name, $default);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a "permanent" cookie. The cookie will last 5 years.
|
||||
*
|
||||
* @param string $name
|
||||
* @param string $value
|
||||
* @param string $path
|
||||
* @param string $domain
|
||||
* @param bool $secure
|
||||
* @param bool $http_only
|
||||
* @return bool
|
||||
*/
|
||||
public static function forever($name, $value, $path = '/', $domain = null, $secure = false, $http_only = false)
|
||||
{
|
||||
return static::put($name, $value, 2628000, $path, $domain, $secure, $http_only);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the value of a cookie. If a negative number of minutes is
|
||||
* specified, the cookie will be deleted.
|
||||
*
|
||||
* @param string $name
|
||||
* @param string $value
|
||||
* @param int $minutes
|
||||
* @param string $path
|
||||
* @param string $domain
|
||||
* @param bool $secure
|
||||
* @param bool $http_only
|
||||
* @return bool
|
||||
*/
|
||||
public static function put($name, $value, $minutes = 0, $path = '/', $domain = null, $secure = false, $http_only = false)
|
||||
{
|
||||
if ($minutes < 0) unset($_COOKIE[$name]);
|
||||
|
||||
return setcookie($name, $value, ($minutes != 0) ? time() + ($minutes * 60) : 0, $path, $domain, $secure, $http_only);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete a cookie.
|
||||
*
|
||||
* @param string $name
|
||||
* @return bool
|
||||
*/
|
||||
public static function forget($name)
|
||||
{
|
||||
return static::put($name, null, -60);
|
||||
}
|
||||
|
||||
}
|
||||
118
laravel/crypter.php
Normal file
118
laravel/crypter.php
Normal file
@@ -0,0 +1,118 @@
|
||||
<?php namespace Laravel;
|
||||
|
||||
class Crypter {
|
||||
|
||||
/**
|
||||
* The encryption cipher.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $cipher;
|
||||
|
||||
/**
|
||||
* The encryption mode.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $mode;
|
||||
|
||||
/**
|
||||
* Create a new Crypter instance.
|
||||
*
|
||||
* @param string $cipher
|
||||
* @param string $mode
|
||||
* @return void
|
||||
*/
|
||||
public function __construct($cipher = 'rijndael-256', $mode = 'cbc')
|
||||
{
|
||||
$this->cipher = $cipher;
|
||||
$this->mode = $mode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new Crypter instance.
|
||||
*
|
||||
* @param string $cipher
|
||||
* @param string $mode
|
||||
* @return Crypt
|
||||
*/
|
||||
public static function make($cipher = 'rijndael-256', $mode = 'cbc')
|
||||
{
|
||||
return new static($cipher, $mode);
|
||||
}
|
||||
|
||||
/**
|
||||
* Encrypt a value using the MCrypt library.
|
||||
*
|
||||
* @param string $value
|
||||
* @return string
|
||||
*/
|
||||
public function encrypt($value)
|
||||
{
|
||||
$iv = mcrypt_create_iv($this->iv_size(), $this->randomizer());
|
||||
|
||||
return base64_encode($iv.mcrypt_encrypt($this->cipher, $this->key(), $value, $this->mode, $iv));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the random number source available to the OS.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
protected function randomizer()
|
||||
{
|
||||
if (defined('MCRYPT_DEV_URANDOM'))
|
||||
{
|
||||
return MCRYPT_DEV_URANDOM;
|
||||
}
|
||||
elseif (defined('MCRYPT_DEV_RANDOM'))
|
||||
{
|
||||
return MCRYPT_DEV_RANDOM;
|
||||
}
|
||||
|
||||
return MCRYPT_RAND;
|
||||
}
|
||||
|
||||
/**
|
||||
* Decrypt a value using the MCrypt library.
|
||||
*
|
||||
* @param string $value
|
||||
* @return string
|
||||
*/
|
||||
public function decrypt($value)
|
||||
{
|
||||
if ( ! is_string($value = base64_decode($value, true)))
|
||||
{
|
||||
throw new \Exception('Decryption error. Input value is not valid base64 data.');
|
||||
}
|
||||
|
||||
list($iv, $value) = array(substr($value, 0, $this->iv_size()), substr($value, $this->iv_size()));
|
||||
|
||||
return rtrim(mcrypt_decrypt($this->cipher, $this->key(), $value, $this->mode, $iv), "\0");
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the application key from the application configuration file.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private function key()
|
||||
{
|
||||
if ( ! is_null($key = Config::get('application.key')) and $key !== '') return $key;
|
||||
|
||||
throw new \Exception("The encryption class can not be used without an encryption key.");
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the input vector size for the cipher and mode.
|
||||
*
|
||||
* Different ciphers and modes use varying lengths of input vectors.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
private function iv_size()
|
||||
{
|
||||
return mcrypt_get_iv_size($this->cipher, $this->mode);
|
||||
}
|
||||
|
||||
}
|
||||
58
laravel/db.php
Normal file
58
laravel/db.php
Normal file
@@ -0,0 +1,58 @@
|
||||
<?php namespace Laravel;
|
||||
|
||||
class DB {
|
||||
|
||||
/**
|
||||
* The established database connections.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $connections = array();
|
||||
|
||||
/**
|
||||
* Get a database connection. If no database name is specified, the default
|
||||
* connection will be returned as defined in the db configuration file.
|
||||
*
|
||||
* Note: Database connections are managed as singletons.
|
||||
*
|
||||
* @param string $connection
|
||||
* @return DB\Connection
|
||||
*/
|
||||
public static function connection($connection = null)
|
||||
{
|
||||
if (is_null($connection)) $connection = Config::get('db.default');
|
||||
|
||||
if ( ! array_key_exists($connection, static::$connections))
|
||||
{
|
||||
if (is_null($config = Config::get('db.connections.'.$connection)))
|
||||
{
|
||||
throw new \Exception("Database connection [$connection] is not defined.");
|
||||
}
|
||||
|
||||
static::$connections[$connection] = new DB\Connection($connection, (object) $config, new DB\Connector);
|
||||
}
|
||||
|
||||
return static::$connections[$connection];
|
||||
}
|
||||
|
||||
/**
|
||||
* Begin a fluent query against a table.
|
||||
*
|
||||
* @param string $table
|
||||
* @param string $connection
|
||||
* @return DB\Query
|
||||
*/
|
||||
public static function table($table, $connection = null)
|
||||
{
|
||||
return static::connection($connection)->table($table);
|
||||
}
|
||||
|
||||
/**
|
||||
* Magic Method for calling methods on the default database connection.
|
||||
*/
|
||||
public static function __callStatic($method, $parameters)
|
||||
{
|
||||
return call_user_func_array(array(static::connection(), $method), $parameters);
|
||||
}
|
||||
|
||||
}
|
||||
137
laravel/db/connection.php
Normal file
137
laravel/db/connection.php
Normal file
@@ -0,0 +1,137 @@
|
||||
<?php namespace Laravel\DB;
|
||||
|
||||
class Connection {
|
||||
|
||||
/**
|
||||
* The connection name.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $name;
|
||||
|
||||
/**
|
||||
* The connection configuration.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public $config;
|
||||
|
||||
/**
|
||||
* The PDO connection.
|
||||
*
|
||||
* @var PDO
|
||||
*/
|
||||
public $pdo;
|
||||
|
||||
/**
|
||||
* All of the queries that have been executed on the connection.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public $queries = array();
|
||||
|
||||
/**
|
||||
* Create a new Connection instance.
|
||||
*
|
||||
* @param string $name
|
||||
* @param object $config
|
||||
* @param Connector $connector
|
||||
* @return void
|
||||
*/
|
||||
public function __construct($name, $config, $connector)
|
||||
{
|
||||
$this->name = $name;
|
||||
$this->config = $config;
|
||||
$this->pdo = $connector->connect($this->config);
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute a SQL query against the connection and return the first result.
|
||||
*
|
||||
* @param string $sql
|
||||
* @param array $bindings
|
||||
* @return object
|
||||
*/
|
||||
public function first($sql, $bindings = array())
|
||||
{
|
||||
return (count($results = $this->query($sql, $bindings)) > 0) ? $results[0] : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute a SQL query against the connection.
|
||||
*
|
||||
* The method returns the following based on query type:
|
||||
*
|
||||
* SELECT -> Array of stdClasses
|
||||
* UPDATE -> Number of rows affected.
|
||||
* DELETE -> Number of Rows affected.
|
||||
* ELSE -> Boolean true / false depending on success.
|
||||
*
|
||||
* @param string $sql
|
||||
* @param array $bindings
|
||||
* @return array
|
||||
*/
|
||||
public function query($sql, $bindings = array())
|
||||
{
|
||||
$this->queries[] = $sql;
|
||||
|
||||
$query = $this->pdo->prepare($sql);
|
||||
|
||||
$result = $query->execute($bindings);
|
||||
|
||||
if (strpos(strtoupper($sql), 'SELECT') === 0)
|
||||
{
|
||||
return $query->fetchAll(\PDO::FETCH_CLASS, 'stdClass');
|
||||
}
|
||||
elseif (strpos(strtoupper($sql), 'UPDATE') === 0 or strpos(strtoupper($sql), 'DELETE') === 0)
|
||||
{
|
||||
return $query->rowCount();
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Begin a fluent query against a table.
|
||||
*
|
||||
* @param string $table
|
||||
* @return Query
|
||||
*/
|
||||
public function table($table)
|
||||
{
|
||||
return new Query($table, $this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the keyword identifier wrapper for the connection.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function wrapper()
|
||||
{
|
||||
if (array_key_exists('wrap', $this->config) and $this->config['wrap'] === false) return '';
|
||||
|
||||
return ($this->driver() == 'mysql') ? '`' : '"';
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the driver name for the database connection.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function driver()
|
||||
{
|
||||
return $this->pdo->getAttribute(\PDO::ATTR_DRIVER_NAME);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the table prefix for the database connection.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function prefix()
|
||||
{
|
||||
return (array_key_exists('prefix', $this->config)) ? $this->config['prefix'] : '';
|
||||
}
|
||||
|
||||
}
|
||||
108
laravel/db/connector.php
Normal file
108
laravel/db/connector.php
Normal file
@@ -0,0 +1,108 @@
|
||||
<?php namespace Laravel\DB;
|
||||
|
||||
use Laravel\Config;
|
||||
|
||||
class Connector {
|
||||
|
||||
/**
|
||||
* The PDO connection options.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public $options = array(
|
||||
\PDO::ATTR_CASE => \PDO::CASE_LOWER,
|
||||
\PDO::ATTR_ERRMODE => \PDO::ERRMODE_EXCEPTION,
|
||||
\PDO::ATTR_ORACLE_NULLS => \PDO::NULL_NATURAL,
|
||||
\PDO::ATTR_STRINGIFY_FETCHES => false,
|
||||
\PDO::ATTR_EMULATE_PREPARES => false,
|
||||
);
|
||||
|
||||
/**
|
||||
* Establish a PDO database connection.
|
||||
*
|
||||
* @param object $connection
|
||||
* @return PDO
|
||||
*/
|
||||
public function connect($config)
|
||||
{
|
||||
switch ($config->driver)
|
||||
{
|
||||
case 'sqlite':
|
||||
return $this->connect_to_sqlite($config);
|
||||
|
||||
case 'mysql':
|
||||
case 'pgsql':
|
||||
return $this->connect_to_server($config);
|
||||
|
||||
default:
|
||||
return $this->connect_to_generic($config);
|
||||
}
|
||||
|
||||
throw new \Exception('Database driver '.$config->driver.' is not supported.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Establish a PDO connection to a SQLite database.
|
||||
*
|
||||
* SQLite database paths can be specified either relative to the application/db
|
||||
* directory, or as an absolute path to any location on the file system. In-memory
|
||||
* databases are also supported.
|
||||
*
|
||||
* @param object $config
|
||||
* @return PDO
|
||||
*/
|
||||
private function connect_to_sqlite($config)
|
||||
{
|
||||
if ($config->database == ':memory:')
|
||||
{
|
||||
return new \PDO('sqlite::memory:', null, null, $this->options);
|
||||
}
|
||||
elseif (file_exists($path = DATABASE_PATH.$config->database.'.sqlite'))
|
||||
{
|
||||
return new \PDO('sqlite:'.$path, null, null, $this->options);
|
||||
}
|
||||
elseif (file_exists($config->database))
|
||||
{
|
||||
return new \PDO('sqlite:'.$config->database, null, null, $this->options);
|
||||
}
|
||||
|
||||
throw new \Exception("SQLite database [".$config->database."] could not be found.");
|
||||
}
|
||||
|
||||
/**
|
||||
* Connect to a MySQL or PostgreSQL database server.
|
||||
*
|
||||
* @param object $config
|
||||
* @return PDO
|
||||
*/
|
||||
private function connect_to_server($config)
|
||||
{
|
||||
$dsn = $config->driver.':host='.$config->host.';dbname='.$config->database;
|
||||
|
||||
if (isset($config->port))
|
||||
{
|
||||
$dsn .= ';port='.$config->port;
|
||||
}
|
||||
|
||||
$connection = new \PDO($dsn, $config->username, $config->password, $this->options);
|
||||
|
||||
if (isset($config->charset))
|
||||
{
|
||||
$connection->prepare("SET NAMES '".$config->charset."'")->execute();
|
||||
}
|
||||
|
||||
return $connection;
|
||||
}
|
||||
|
||||
/**
|
||||
* Connect to a generic data source.
|
||||
*
|
||||
* @param object $config
|
||||
* @return PDO
|
||||
*/
|
||||
private function connect_to_generic($config)
|
||||
{
|
||||
return new \PDO($config->driver.':'.$config->dsn, $config->username, $config->password, $this->options);
|
||||
}
|
||||
|
||||
}
|
||||
203
laravel/db/eloquent/hydrator.php
Normal file
203
laravel/db/eloquent/hydrator.php
Normal file
@@ -0,0 +1,203 @@
|
||||
<?php namespace System\DB\Eloquent;
|
||||
|
||||
class Hydrator {
|
||||
|
||||
/**
|
||||
* Load the array of hydrated models and their eager relationships.
|
||||
*
|
||||
* @param Model $eloquent
|
||||
* @return array
|
||||
*/
|
||||
public static function hydrate($eloquent)
|
||||
{
|
||||
$results = static::base(get_class($eloquent), $eloquent->query->get());
|
||||
|
||||
if (count($results) > 0)
|
||||
{
|
||||
foreach ($eloquent->includes as $include)
|
||||
{
|
||||
if ( ! method_exists($eloquent, $include))
|
||||
{
|
||||
throw new \Exception("Attempting to eager load [$include], but the relationship is not defined.");
|
||||
}
|
||||
|
||||
static::eagerly($eloquent, $results, $include);
|
||||
}
|
||||
}
|
||||
|
||||
return $results;
|
||||
}
|
||||
|
||||
/**
|
||||
* Hydrate the base models for a query.
|
||||
*
|
||||
* The resulting model array is keyed by the primary keys of the models.
|
||||
* This allows the models to easily be matched to their children.
|
||||
*
|
||||
* @param string $class
|
||||
* @param array $results
|
||||
* @return array
|
||||
*/
|
||||
private static function base($class, $results)
|
||||
{
|
||||
$models = array();
|
||||
|
||||
foreach ($results as $result)
|
||||
{
|
||||
$model = new $class;
|
||||
|
||||
$model->attributes = (array) $result;
|
||||
|
||||
$model->exists = true;
|
||||
|
||||
$models[$model->id] = $model;
|
||||
}
|
||||
|
||||
return $models;
|
||||
}
|
||||
|
||||
/**
|
||||
* Eagerly load a relationship.
|
||||
*
|
||||
* @param object $eloquent
|
||||
* @param array $parents
|
||||
* @param string $include
|
||||
* @return void
|
||||
*/
|
||||
private static function eagerly($eloquent, &$parents, $include)
|
||||
{
|
||||
// We temporarily spoof the belongs_to key to allow the query to be fetched without
|
||||
// any problems, since the belongs_to method actually gets the attribute.
|
||||
$eloquent->attributes[$spoof = $include.'_id'] = 0;
|
||||
|
||||
$relationship = $eloquent->$include();
|
||||
|
||||
unset($eloquent->attributes[$spoof]);
|
||||
|
||||
// Reset the WHERE clause and bindings on the query. We'll add our own WHERE clause soon.
|
||||
// This will allow us to load a range of related models instead of only one.
|
||||
$relationship->query->reset_where();
|
||||
|
||||
// Initialize the relationship attribute on the parents. As expected, "many" relationships
|
||||
// are initialized to an array and "one" relationships are initialized to null.
|
||||
foreach ($parents as &$parent)
|
||||
{
|
||||
$parent->ignore[$include] = (in_array($eloquent->relating, array('has_many', 'has_and_belongs_to_many'))) ? array() : null;
|
||||
}
|
||||
|
||||
if (in_array($relating = $eloquent->relating, array('has_one', 'has_many', 'belongs_to')))
|
||||
{
|
||||
return static::$relating($relationship, $parents, $eloquent->relating_key, $include);
|
||||
}
|
||||
else
|
||||
{
|
||||
static::has_and_belongs_to_many($relationship, $parents, $eloquent->relating_key, $eloquent->relating_table, $include);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Eagerly load a 1:1 relationship.
|
||||
*
|
||||
* @param object $relationship
|
||||
* @param array $parents
|
||||
* @param string $relating_key
|
||||
* @param string $relating
|
||||
* @param string $include
|
||||
* @return void
|
||||
*/
|
||||
private static function has_one($relationship, &$parents, $relating_key, $include)
|
||||
{
|
||||
foreach ($relationship->where_in($relating_key, array_keys($parents))->get() as $key => $child)
|
||||
{
|
||||
$parents[$child->$relating_key]->ignore[$include] = $child;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Eagerly load a 1:* relationship.
|
||||
*
|
||||
* @param object $relationship
|
||||
* @param array $parents
|
||||
* @param string $relating_key
|
||||
* @param string $relating
|
||||
* @param string $include
|
||||
* @return void
|
||||
*/
|
||||
private static function has_many($relationship, &$parents, $relating_key, $include)
|
||||
{
|
||||
foreach ($relationship->where_in($relating_key, array_keys($parents))->get() as $key => $child)
|
||||
{
|
||||
$parents[$child->$relating_key]->ignore[$include][$child->id] = $child;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Eagerly load a 1:1 belonging relationship.
|
||||
*
|
||||
* @param object $relationship
|
||||
* @param array $parents
|
||||
* @param string $relating_key
|
||||
* @param string $include
|
||||
* @return void
|
||||
*/
|
||||
private static function belongs_to($relationship, &$parents, $relating_key, $include)
|
||||
{
|
||||
$keys = array();
|
||||
|
||||
foreach ($parents as &$parent)
|
||||
{
|
||||
$keys[] = $parent->$relating_key;
|
||||
}
|
||||
|
||||
$children = $relationship->where_in('id', array_unique($keys))->get();
|
||||
|
||||
foreach ($parents as &$parent)
|
||||
{
|
||||
if (array_key_exists($parent->$relating_key, $children))
|
||||
{
|
||||
$parent->ignore[$include] = $children[$parent->$relating_key];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Eagerly load a many-to-many relationship.
|
||||
*
|
||||
* @param object $relationship
|
||||
* @param array $parents
|
||||
* @param string $relating_key
|
||||
* @param string $relating_table
|
||||
* @param string $include
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
private static function has_and_belongs_to_many($relationship, &$parents, $relating_key, $relating_table, $include)
|
||||
{
|
||||
// The model "has and belongs to many" method sets the SELECT clause; however, we need
|
||||
// to clear it here since we will be adding the foreign key to the select.
|
||||
$relationship->query->select = null;
|
||||
|
||||
$relationship->query->where_in($relating_table.'.'.$relating_key, array_keys($parents));
|
||||
|
||||
// The foreign key is added to the select to allow us to easily match the models back to their parents.
|
||||
// Otherwise, there would be no apparent connection between the models to allow us to match them.
|
||||
$children = $relationship->query->get(array(Model::table(get_class($relationship)).'.*', $relating_table.'.'.$relating_key));
|
||||
|
||||
$class = get_class($relationship);
|
||||
|
||||
foreach ($children as $child)
|
||||
{
|
||||
$related = new $class;
|
||||
|
||||
$related->attributes = (array) $child;
|
||||
|
||||
$related->exists = true;
|
||||
|
||||
// Remove the foreign key since it was only added to the query to help match the models.
|
||||
unset($related->attributes[$relating_key]);
|
||||
|
||||
$parents[$child->$relating_key]->ignore[$include][$child->id] = $related;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
520
laravel/db/eloquent/model.php
Normal file
520
laravel/db/eloquent/model.php
Normal file
@@ -0,0 +1,520 @@
|
||||
<?php namespace System\DB\Eloquent;
|
||||
|
||||
use System\DB;
|
||||
use System\Str;
|
||||
use System\Config;
|
||||
use System\Inflector;
|
||||
use System\Paginator;
|
||||
|
||||
abstract class Model {
|
||||
|
||||
/**
|
||||
* The connection that should be used for the model.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public static $connection;
|
||||
|
||||
/**
|
||||
* The model query instance.
|
||||
*
|
||||
* @var Query
|
||||
*/
|
||||
public $query;
|
||||
|
||||
/**
|
||||
* Indicates if the model exists in the database.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
public $exists = false;
|
||||
|
||||
/**
|
||||
* The model's attributes.
|
||||
*
|
||||
* Typically, a model has an attribute for each column on the table.
|
||||
*
|
||||
* @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.
|
||||
*
|
||||
* This is used during many-to-many eager loading.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $relating_table;
|
||||
|
||||
/**
|
||||
* Create a new Eloquent model instance.
|
||||
*
|
||||
* @param array $attributes
|
||||
* @return void
|
||||
*/
|
||||
public function __construct($attributes = array())
|
||||
{
|
||||
$this->fill($attributes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the attributes of the model using an array.
|
||||
*
|
||||
* @param array $attributes
|
||||
* @return Model
|
||||
*/
|
||||
public function fill($attributes)
|
||||
{
|
||||
foreach ($attributes as $key => $value)
|
||||
{
|
||||
$this->$key = $value;
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the eagerly loaded models on the queryable model.
|
||||
*
|
||||
* @return Model
|
||||
*/
|
||||
private function _with()
|
||||
{
|
||||
$this->includes = func_get_args();
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Factory for creating queryable Eloquent model instances.
|
||||
*
|
||||
* @param string $class
|
||||
* @return object
|
||||
*/
|
||||
public static function query($class)
|
||||
{
|
||||
$model = new $class;
|
||||
|
||||
// Since this method is only used for instantiating models for querying
|
||||
// purposes, we will go ahead and set the Query instance on the model.
|
||||
$model->query = DB::connection(static::$connection)->table(static::table($class));
|
||||
|
||||
return $model;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the table name for a model.
|
||||
*
|
||||
* @param string $class
|
||||
* @return string
|
||||
*/
|
||||
public static function table($class)
|
||||
{
|
||||
if (property_exists($class, 'table')) return $class::$table;
|
||||
|
||||
return strtolower(Inflector::plural(static::model_name($class)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get an Eloquent model name without any namespaces.
|
||||
*
|
||||
* @param string|Model $model
|
||||
* @return string
|
||||
*/
|
||||
public static function model_name($model)
|
||||
{
|
||||
$class = (is_object($model)) ? get_class($model) : $model;
|
||||
|
||||
$segments = array_reverse(explode('\\', $class));
|
||||
|
||||
return $segments[0];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all of the models from the database.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public static function all()
|
||||
{
|
||||
return Hydrator::hydrate(static::query(get_called_class()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a model by the primary key.
|
||||
*
|
||||
* @param int $id
|
||||
* @return mixed
|
||||
*/
|
||||
public static function find($id)
|
||||
{
|
||||
return static::query(get_called_class())->where('id', '=', $id)->first();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get an array of models from the database.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
private function _get($columns = array('*'))
|
||||
{
|
||||
$this->query->select($columns);
|
||||
|
||||
return Hydrator::hydrate($this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the first model result
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
private function _first($columns = array('*'))
|
||||
{
|
||||
return (count($results = $this->take(1)->_get($columns)) > 0) ? reset($results) : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get paginated model results.
|
||||
*
|
||||
* @param int $per_page
|
||||
* @return Paginator
|
||||
*/
|
||||
private function _paginate($per_page = null, $columns = array('*'))
|
||||
{
|
||||
$total = $this->query->count();
|
||||
|
||||
if (is_null($per_page))
|
||||
{
|
||||
$per_page = (property_exists(get_class($this), 'per_page')) ? static::$per_page : 20;
|
||||
}
|
||||
|
||||
return Paginator::make($this->select($columns)->for_page(Paginator::page($total, $per_page), $per_page)->get(), $total, $per_page);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the query for a 1:1 relationship.
|
||||
*
|
||||
* @param string $model
|
||||
* @param string $foreign_key
|
||||
* @return mixed
|
||||
*/
|
||||
public function has_one($model, $foreign_key = null)
|
||||
{
|
||||
$this->relating = __FUNCTION__;
|
||||
|
||||
return $this->has_one_or_many($model, $foreign_key);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the query for a 1:* relationship.
|
||||
*
|
||||
* @param string $model
|
||||
* @param string $foreign_key
|
||||
* @return mixed
|
||||
*/
|
||||
public function has_many($model, $foreign_key = null)
|
||||
{
|
||||
$this->relating = __FUNCTION__;
|
||||
|
||||
return $this->has_one_or_many($model, $foreign_key);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the query for a 1:1 or 1:* relationship.
|
||||
*
|
||||
* The default foreign key for has one and has many relationships is the name
|
||||
* of the model with an appended _id. For example, the foreign key for a
|
||||
* User model would be user_id. Photo would be photo_id, etc.
|
||||
*
|
||||
* @param string $model
|
||||
* @param string $foreign_key
|
||||
* @return mixed
|
||||
*/
|
||||
private function has_one_or_many($model, $foreign_key)
|
||||
{
|
||||
$this->relating_key = (is_null($foreign_key)) ? strtolower(static::model_name($this)).'_id' : $foreign_key;
|
||||
|
||||
return static::query($model)->where($this->relating_key, '=', $this->id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the query for a 1:1 belonging relationship.
|
||||
*
|
||||
* The default foreign key for belonging relationships is the name of the
|
||||
* relationship method name with _id. So, if a model has a "manager" method
|
||||
* returning a belongs_to relationship, the key would be manager_id.
|
||||
*
|
||||
* @param string $model
|
||||
* @param string $foreign_key
|
||||
* @return mixed
|
||||
*/
|
||||
public function belongs_to($model, $foreign_key = null)
|
||||
{
|
||||
$this->relating = __FUNCTION__;
|
||||
|
||||
if ( ! is_null($foreign_key))
|
||||
{
|
||||
$this->relating_key = $foreign_key;
|
||||
}
|
||||
else
|
||||
{
|
||||
list(, $caller) = debug_backtrace(false);
|
||||
|
||||
$this->relating_key = $caller['function'].'_id';
|
||||
}
|
||||
|
||||
return static::query($model)->where('id', '=', $this->attributes[$this->relating_key]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the query for a *:* relationship.
|
||||
*
|
||||
* The default foreign key for many-to-many relations is the name of the model
|
||||
* with an appended _id. This is the same convention as has_one and has_many.
|
||||
*
|
||||
* @param string $model
|
||||
* @param string $table
|
||||
* @param string $foreign_key
|
||||
* @param string $associated_key
|
||||
* @return mixed
|
||||
*/
|
||||
public function has_and_belongs_to_many($model, $table = null, $foreign_key = null, $associated_key = null)
|
||||
{
|
||||
$this->relating = __FUNCTION__;
|
||||
|
||||
$this->relating_table = (is_null($table)) ? $this->intermediate_table($model) : $table;
|
||||
|
||||
// Allowing the overriding of the foreign and associated keys provides the flexibility for
|
||||
// self-referential many-to-many relationships, such as a "buddy list".
|
||||
$this->relating_key = (is_null($foreign_key)) ? strtolower(static::model_name($this)).'_id' : $foreign_key;
|
||||
|
||||
// The associated key is the foreign key name of the related model. So, if the related model
|
||||
// is "Role", the associated key on the intermediate table would be "role_id".
|
||||
$associated_key = (is_null($associated_key)) ? strtolower(static::model_name($model)).'_id' : $associated_key;
|
||||
|
||||
return static::query($model)
|
||||
->select(array(static::table($model).'.*'))
|
||||
->join($this->relating_table, static::table($model).'.id', '=', $this->relating_table.'.'.$associated_key)
|
||||
->where($this->relating_table.'.'.$this->relating_key, '=', $this->id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine the intermediate table name for a given model.
|
||||
*
|
||||
* By default, the intermediate table name is the plural names of the models
|
||||
* arranged alphabetically and concatenated with an underscore.
|
||||
*
|
||||
* @param string $model
|
||||
* @return string
|
||||
*/
|
||||
private function intermediate_table($model)
|
||||
{
|
||||
$models = array(Inflector::plural(static::model_name($model)), Inflector::plural(static::model_name($this)));
|
||||
|
||||
sort($models);
|
||||
|
||||
return strtolower($models[0].'_'.$models[1]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Save the model to the database.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function save()
|
||||
{
|
||||
// If the model does not have any dirty attributes, there is no reason
|
||||
// to save it to the database.
|
||||
if ($this->exists and count($this->dirty) == 0) return true;
|
||||
|
||||
$model = get_class($this);
|
||||
|
||||
// Since the model was instantiated using "new", a query instance has not been set.
|
||||
// Only models being used for querying have their query instances set by default.
|
||||
$this->query = DB::connection(static::$connection)->table(static::table($model));
|
||||
|
||||
if (property_exists($model, 'timestamps') and $model::$timestamps)
|
||||
{
|
||||
$this->timestamp();
|
||||
}
|
||||
|
||||
// If the model already exists in the database, we will just update it.
|
||||
// Otherwise, we will insert the model and set the ID attribute.
|
||||
if ($this->exists)
|
||||
{
|
||||
$success = ($this->query->where_id($this->attributes['id'])->update($this->dirty) === 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
$success = is_numeric($this->attributes['id'] = $this->query->insert_get_id($this->attributes));
|
||||
}
|
||||
|
||||
($this->exists = true) and $this->dirty = array();
|
||||
|
||||
return $success;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the creation and update timestamps on the model.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
private function timestamp()
|
||||
{
|
||||
$this->updated_at = date('Y-m-d H:i:s');
|
||||
|
||||
if ( ! $this->exists) $this->created_at = $this->updated_at;
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete a model from the database.
|
||||
*
|
||||
* @param int $id
|
||||
* @return int
|
||||
*/
|
||||
public function delete($id = null)
|
||||
{
|
||||
// If the delete method is being called on an existing model, we only want to delete
|
||||
// that model. If it is being called from an Eloquent query model, it is probably
|
||||
// the developer's intention to delete more than one model, so we will pass the
|
||||
// delete statement to the query instance.
|
||||
if ( ! $this->exists) return $this->query->delete();
|
||||
|
||||
return DB::connection(static::$connection)->table(static::table(get_class($this)))->delete($this->id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Magic method for retrieving model attributes.
|
||||
*/
|
||||
public function __get($key)
|
||||
{
|
||||
if (array_key_exists($key, $this->attributes))
|
||||
{
|
||||
return $this->attributes[$key];
|
||||
}
|
||||
// Is the requested item a model relationship that has already been loaded?
|
||||
// All of the loaded relationships are stored in the "ignore" array.
|
||||
elseif (array_key_exists($key, $this->ignore))
|
||||
{
|
||||
return $this->ignore[$key];
|
||||
}
|
||||
// Is the requested item a model relationship? If it is, we will dynamically
|
||||
// load it and return the results of the relationship query.
|
||||
elseif (method_exists($this, $key))
|
||||
{
|
||||
$query = $this->$key();
|
||||
|
||||
return $this->ignore[$key] = (in_array($this->relating, array('has_one', 'belongs_to'))) ? $query->first() : $query->get();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Magic Method for setting model attributes.
|
||||
*/
|
||||
public function __set($key, $value)
|
||||
{
|
||||
// If the key is a relationship, add it to the ignored attributes.
|
||||
// Ignored attributes are not stored in the database.
|
||||
if (method_exists($this, $key))
|
||||
{
|
||||
$this->ignore[$key] = $value;
|
||||
}
|
||||
else
|
||||
{
|
||||
$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], $this->ignore[$key], $this->dirty[$key]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Magic Method for handling dynamic method calls.
|
||||
*/
|
||||
public function __call($method, $parameters)
|
||||
{
|
||||
// To allow the "with", "get", "first", and "paginate" methods to be called both
|
||||
// staticly and on an instance, we need to have private, underscored versions
|
||||
// of the methods and handle them dynamically.
|
||||
if (in_array($method, array('with', 'get', 'first', 'paginate')))
|
||||
{
|
||||
return call_user_func_array(array($this, '_'.$method), $parameters);
|
||||
}
|
||||
|
||||
// All of the aggregate and persistance functions can be passed directly to the query
|
||||
// instance. For these functions, we can simply return the response of the query.
|
||||
if (in_array($method, array('insert', 'update', 'count', 'sum', 'min', 'max', 'avg')))
|
||||
{
|
||||
return call_user_func_array(array($this->query, $method), $parameters);
|
||||
}
|
||||
|
||||
// Pass the method to the query instance. This allows the chaining of methods
|
||||
// from the query builder, providing the same convenient query API as the
|
||||
// query builder itself.
|
||||
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)
|
||||
{
|
||||
// Just pass the method to a model instance and let the __call method take care of it.
|
||||
return call_user_func_array(array(static::query(get_called_class()), $method), $parameters);
|
||||
}
|
||||
|
||||
}
|
||||
709
laravel/db/query.php
Normal file
709
laravel/db/query.php
Normal file
@@ -0,0 +1,709 @@
|
||||
<?php namespace Laravel\DB;
|
||||
|
||||
use Laravel\Str;
|
||||
use Laravel\Config;
|
||||
use Laravel\Paginator;
|
||||
|
||||
class Query {
|
||||
|
||||
/**
|
||||
* The database connection.
|
||||
*
|
||||
* @var Connection
|
||||
*/
|
||||
public $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 Connection $connection
|
||||
* @return void
|
||||
*/
|
||||
public function __construct($table, $connection)
|
||||
{
|
||||
$this->table = $table;
|
||||
$this->connection = $connection;
|
||||
$this->from = 'FROM '.$this->wrap($table);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new query instance.
|
||||
*
|
||||
* @param string $table
|
||||
* @param Connection $connection
|
||||
* @return Query
|
||||
*/
|
||||
public static function table($table, $connection)
|
||||
{
|
||||
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.
|
||||
*
|
||||
* @param array $columns
|
||||
* @return Query
|
||||
*/
|
||||
public function select($columns = array('*'))
|
||||
{
|
||||
$this->select = ($this->distinct) ? 'SELECT DISTINCT ' : 'SELECT ';
|
||||
|
||||
$this->select .= implode(', ', array_map(array($this, 'wrap'), $columns));
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the FROM clause.
|
||||
*
|
||||
* @param string $from
|
||||
* @return Query
|
||||
*/
|
||||
public function from($from)
|
||||
{
|
||||
$this->from = $from;
|
||||
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');
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset the where clause to its initial state. All bindings will be cleared.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function reset_where()
|
||||
{
|
||||
$this->where = 'WHERE 1 = 1';
|
||||
$this->bindings = array();
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 condition for the primary key to the query.
|
||||
* This is simply a short-cut method for convenience.
|
||||
*
|
||||
* @param mixed $value
|
||||
* @return Query
|
||||
*/
|
||||
public function where_id($value)
|
||||
{
|
||||
return $this->where('id', '=', $value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add an or where condition for the primary key to the query.
|
||||
* This is simply a short-cut method for convenience.
|
||||
*
|
||||
* @param mixed $value
|
||||
* @return Query
|
||||
*/
|
||||
public function or_where_id($value)
|
||||
{
|
||||
return $this->or_where('id', '=', $value);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 dynamic where conditions to the query.
|
||||
*
|
||||
* Dynamic queries are caught by the __call magic method and are parsed here.
|
||||
* They provide a convenient, expressive API for building simple conditions.
|
||||
*
|
||||
* @param string $method
|
||||
* @param array $parameters
|
||||
* @return Query
|
||||
*/
|
||||
private function dynamic_where($method, $parameters)
|
||||
{
|
||||
// Strip the "where_" off of the method.
|
||||
$finder = substr($method, 6);
|
||||
|
||||
// Split the column names from the connectors.
|
||||
$segments = preg_split('/(_and_|_or_)/i', $finder, -1, PREG_SPLIT_DELIM_CAPTURE);
|
||||
|
||||
// The connector variable will determine which connector will be used for the condition.
|
||||
// We'll change it as we come across new connectors in the dynamic method string.
|
||||
//
|
||||
// The index variable helps us get the correct parameter value for the where condition.
|
||||
// We increment it each time we add a condition.
|
||||
$connector = 'AND';
|
||||
|
||||
$index = 0;
|
||||
|
||||
foreach ($segments as $segment)
|
||||
{
|
||||
if ($segment != '_and_' and $segment != '_or_')
|
||||
{
|
||||
$this->where($segment, '=', $parameters[$index], $connector);
|
||||
|
||||
$index++;
|
||||
}
|
||||
else
|
||||
{
|
||||
$connector = trim(strtoupper($segment), '_');
|
||||
}
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add an ordering to the query.
|
||||
*
|
||||
* @param string $column
|
||||
* @param string $direction
|
||||
* @return Query
|
||||
*/
|
||||
public function order_by($column, $direction = 'asc')
|
||||
{
|
||||
$this->orderings[] = $this->wrap($column).' '.strtoupper($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;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the limit and offset values for a given page.
|
||||
*
|
||||
* @param int $page
|
||||
* @param int $per_page
|
||||
* @return Query
|
||||
*/
|
||||
public function for_page($page, $per_page)
|
||||
{
|
||||
return $this->skip(($page - 1) * $per_page)->take($per_page);
|
||||
}
|
||||
|
||||
/**
|
||||
* Find a record by the primary key.
|
||||
*
|
||||
* @param int $id
|
||||
* @param array $columns
|
||||
* @return object
|
||||
*/
|
||||
public function find($id, $columns = array('*'))
|
||||
{
|
||||
return $this->where('id', '=', $id)->first($columns);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get an aggregate value.
|
||||
*
|
||||
* @param string $aggregate
|
||||
* @param string $column
|
||||
* @return mixed
|
||||
*/
|
||||
private function aggregate($aggregator, $column)
|
||||
{
|
||||
$this->select = 'SELECT '.$aggregator.'('.$this->wrap($column).') AS '.$this->wrap('aggregate');
|
||||
|
||||
return $this->first()->aggregate;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get paginated query results.
|
||||
*
|
||||
* @param int $per_page
|
||||
* @param array $columns
|
||||
* @return Paginator
|
||||
*/
|
||||
public function paginate($per_page, $columns = array('*'))
|
||||
{
|
||||
$total = $this->count();
|
||||
|
||||
return Paginator::make($this->for_page(Paginator::page($total, $per_page), $per_page)->get($columns), $total, $per_page);
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the query as a SELECT statement and return the first result.
|
||||
*
|
||||
* @param array $columns
|
||||
* @return object
|
||||
*/
|
||||
public function first($columns = array('*'))
|
||||
{
|
||||
return (count($results = $this->take(1)->get($columns)) > 0) ? $results[0] : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the query as a SELECT statement.
|
||||
*
|
||||
* @param array $columns
|
||||
* @return array
|
||||
*/
|
||||
public function get($columns = array('*'))
|
||||
{
|
||||
if (is_null($this->select))
|
||||
{
|
||||
$this->select($columns);
|
||||
}
|
||||
|
||||
$results = $this->connection->query($this->compile_select(), $this->bindings);
|
||||
|
||||
// Reset the SELECT clause so more queries can be performed using the same instance.
|
||||
// This is helpful for getting aggregates and then getting actual results.
|
||||
$this->select = null;
|
||||
|
||||
return $results;
|
||||
}
|
||||
|
||||
/**
|
||||
* Compile the query into a SQL SELECT statement.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private function compile_select()
|
||||
{
|
||||
$sql = $this->select.' '.$this->from.' '.$this->where;
|
||||
|
||||
if (count($this->orderings) > 0)
|
||||
{
|
||||
$sql .= ' ORDER BY '.implode(', ', $this->orderings);
|
||||
}
|
||||
|
||||
if ( ! is_null($this->limit))
|
||||
{
|
||||
$sql .= ' LIMIT '.$this->limit;
|
||||
}
|
||||
|
||||
if ( ! is_null($this->offset))
|
||||
{
|
||||
$sql .= ' OFFSET '.$this->offset;
|
||||
}
|
||||
|
||||
return $sql;
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute an INSERT statement.
|
||||
*
|
||||
* @param array $values
|
||||
* @return bool
|
||||
*/
|
||||
public function insert($values)
|
||||
{
|
||||
return $this->connection->query($this->compile_insert($values), array_values($values));
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute an INSERT statement and get the insert ID.
|
||||
*
|
||||
* @param array $values
|
||||
* @return int
|
||||
*/
|
||||
public function insert_get_id($values)
|
||||
{
|
||||
$sql = $this->compile_insert($values);
|
||||
|
||||
if ($this->connection->driver() == 'pgsql')
|
||||
{
|
||||
$query = $this->connection->pdo->prepare($sql.' RETURNING '.$this->wrap('id'));
|
||||
|
||||
$query->execute(array_values($values));
|
||||
|
||||
return $query->fetch(\PDO::FETCH_CLASS, 'stdClass')->id;
|
||||
}
|
||||
|
||||
$this->connection->query($sql, array_values($values));
|
||||
|
||||
return $this->connection->pdo->lastInsertId();
|
||||
}
|
||||
|
||||
/**
|
||||
* Compile the query into a SQL INSERT statement.
|
||||
*
|
||||
* @param array $values
|
||||
* @return string
|
||||
*/
|
||||
private function compile_insert($values)
|
||||
{
|
||||
$sql = 'INSERT INTO '.$this->wrap($this->table);
|
||||
|
||||
$columns = array_map(array($this, 'wrap'), array_keys($values));
|
||||
|
||||
return $sql .= ' ('.implode(', ', $columns).') VALUES ('.$this->parameterize($values).')';
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the query as an UPDATE statement.
|
||||
*
|
||||
* @param array $values
|
||||
* @return bool
|
||||
*/
|
||||
public function update($values)
|
||||
{
|
||||
$sql = 'UPDATE '.$this->wrap($this->table).' SET ';
|
||||
|
||||
foreach (array_keys($values) as $column)
|
||||
{
|
||||
$sets[] = $this->wrap($column).' = ?';
|
||||
}
|
||||
|
||||
return $this->connection->query($sql.implode(', ', $sets).' '.$this->where, array_merge(array_values($values), $this->bindings));
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the query as a DELETE statement.
|
||||
*
|
||||
* @param int $id
|
||||
* @return bool
|
||||
*/
|
||||
public function delete($id = null)
|
||||
{
|
||||
if ( ! is_null($id)) $this->where('id', '=', $id);
|
||||
|
||||
return $this->connection->query('DELETE FROM '.$this->wrap($this->table).' '.$this->where, $this->bindings);
|
||||
}
|
||||
|
||||
/**
|
||||
* Wrap a value in keyword identifiers.
|
||||
*
|
||||
* @param string $value
|
||||
* @return string
|
||||
*/
|
||||
private function wrap($value)
|
||||
{
|
||||
if (strpos(strtolower($value), ' as ') !== false)
|
||||
{
|
||||
return $this->wrap_alias($value);
|
||||
}
|
||||
|
||||
$wrap = $this->connection->wrapper();
|
||||
|
||||
foreach (explode('.', $value) as $segment)
|
||||
{
|
||||
$wrapped[] = ($segment != '*') ? $wrap.$segment.$wrap : $segment;
|
||||
}
|
||||
|
||||
return implode('.', $wrapped);
|
||||
}
|
||||
|
||||
/**
|
||||
* Wrap an alias in keyword identifiers.
|
||||
*
|
||||
* @param string $value
|
||||
* @return string
|
||||
*/
|
||||
private function wrap_alias($value)
|
||||
{
|
||||
$segments = explode(' ', $value);
|
||||
|
||||
return $this->wrap($segments[0]).' AS '.$this->wrap($segments[2]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create query parameters from an array of values.
|
||||
*
|
||||
* @param array $values
|
||||
* @return string
|
||||
*/
|
||||
private function parameterize($values)
|
||||
{
|
||||
return implode(', ', array_fill(0, count($values), '?'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Magic Method for handling dynamic functions.
|
||||
*/
|
||||
public function __call($method, $parameters)
|
||||
{
|
||||
if (strpos($method, 'where_') === 0)
|
||||
{
|
||||
return $this->dynamic_where($method, $parameters, $this);
|
||||
}
|
||||
|
||||
if (in_array($method, array('count', 'min', 'max', 'avg', 'sum')))
|
||||
{
|
||||
return ($method == 'count') ? $this->aggregate(strtoupper($method), '*') : $this->aggregate(strtoupper($method), $parameters[0]);
|
||||
}
|
||||
|
||||
throw new \Exception("Method [$method] is not defined on the Query class.");
|
||||
}
|
||||
|
||||
}
|
||||
94
laravel/exception/examiner.php
Normal file
94
laravel/exception/examiner.php
Normal file
@@ -0,0 +1,94 @@
|
||||
<?php namespace Laravel\Exception;
|
||||
|
||||
use Laravel\File;
|
||||
|
||||
class Examiner {
|
||||
|
||||
/**
|
||||
* The exception being examined.
|
||||
*
|
||||
* @var Exception
|
||||
*/
|
||||
public $exception;
|
||||
|
||||
/**
|
||||
* Human-readable error levels and descriptions.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
private $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'
|
||||
);
|
||||
|
||||
/**
|
||||
* Create a new exception examiner instance.
|
||||
*
|
||||
* @param Exception $e
|
||||
* @return void
|
||||
*/
|
||||
public function __construct($e)
|
||||
{
|
||||
$this->exception = $e;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a human-readable version of the exception error code.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function severity()
|
||||
{
|
||||
if (array_key_exists($this->exception->getCode(), $this->levels))
|
||||
{
|
||||
return $this->levels[$this->exception->getCode()];
|
||||
}
|
||||
|
||||
return $this->exception->getCode();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the exception error message formatted for use by Laravel.
|
||||
*
|
||||
* The exception file paths will be shortened, and the file name and line number
|
||||
* will be added to the exception message.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function message()
|
||||
{
|
||||
$file = str_replace(array(ACTIVE_MODULE_PATH, SYS_PATH), array('MODULE_PATH/', 'SYS_PATH/'), $this->exception->getFile());
|
||||
|
||||
return rtrim($this->exception->getMessage(), '.').' in '.$file.' on line '.$this->exception->getLine().'.';
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the code surrounding the line where the exception occurred.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function context()
|
||||
{
|
||||
return File::snapshot($this->exception->getFile(), $this->exception->getLine());
|
||||
}
|
||||
|
||||
/**
|
||||
* Magic Method to pass function calls to the exception.
|
||||
*/
|
||||
public function __call($method, $parameters)
|
||||
{
|
||||
return call_user_func_array(array($this->exception, $method), $parameters);
|
||||
}
|
||||
|
||||
}
|
||||
107
laravel/exception/handler.php
Normal file
107
laravel/exception/handler.php
Normal file
@@ -0,0 +1,107 @@
|
||||
<?php namespace Laravel\Exception;
|
||||
|
||||
use Laravel\View;
|
||||
use Laravel\Config;
|
||||
use Laravel\Response;
|
||||
|
||||
class Handler {
|
||||
|
||||
/**
|
||||
* The exception examiner for the exception being handled.
|
||||
*
|
||||
* @var Examiner
|
||||
*/
|
||||
public $exception;
|
||||
|
||||
/**
|
||||
* Create a new exception handler instance.
|
||||
*
|
||||
* @param Exception $e
|
||||
* @return void
|
||||
*/
|
||||
public function __construct($e)
|
||||
{
|
||||
$this->exception = new Examiner($e);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new exception handler instance.
|
||||
*
|
||||
* @param Exception $e
|
||||
* @return Handler
|
||||
*/
|
||||
public static function make($e)
|
||||
{
|
||||
return new static($e);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle the exception and display the error report.
|
||||
*
|
||||
* The exception will be logged if error logging is enabled.
|
||||
*
|
||||
* The output buffer will be cleaned so nothing is sent to the browser except the
|
||||
* error message. This prevents any views that have already been rendered from
|
||||
* being shown in an incomplete or erroneous state.
|
||||
*
|
||||
* After the exception is displayed, the request will be halted.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function handle()
|
||||
{
|
||||
if (ob_get_level() > 0) ob_clean();
|
||||
|
||||
if (Config::get('error.log')) $this->log();
|
||||
|
||||
$this->get_response(Config::get('error.detail'))->send();
|
||||
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Log the exception using the logger closure specified in the error configuration.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
private function log()
|
||||
{
|
||||
$parameters = array(
|
||||
$this->exception->severity(),
|
||||
$this->exception->message(),
|
||||
$this->exception->getTraceAsString(),
|
||||
);
|
||||
|
||||
call_user_func_array(Config::get('error.logger'), $parameters);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the error report response for the exception.
|
||||
*
|
||||
* @param bool $detailed
|
||||
* @return Resposne
|
||||
*/
|
||||
private function get_response($detailed)
|
||||
{
|
||||
return ($detailed) ? $this->detailed_response() : Response::error('500');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the detailed error report for the exception.
|
||||
*
|
||||
* @return Response
|
||||
*/
|
||||
private function detailed_response()
|
||||
{
|
||||
$data = array(
|
||||
'severity' => $this->exception->severity(),
|
||||
'message' => $this->exception->message(),
|
||||
'line' => $this->exception->getLine(),
|
||||
'trace' => $this->exception->getTraceAsString(),
|
||||
'contexts' => $this->exception->context(),
|
||||
);
|
||||
|
||||
return Response::make(View::make('error.exception', $data), 500);
|
||||
}
|
||||
|
||||
}
|
||||
153
laravel/file.php
Normal file
153
laravel/file.php
Normal file
@@ -0,0 +1,153 @@
|
||||
<?php namespace Laravel;
|
||||
|
||||
class File {
|
||||
|
||||
/**
|
||||
* Get the contents of a file.
|
||||
*
|
||||
* @param string $path
|
||||
* @return string
|
||||
*/
|
||||
public static function get($path)
|
||||
{
|
||||
return file_get_contents($path);
|
||||
}
|
||||
|
||||
/**
|
||||
* Write to a file.
|
||||
*
|
||||
* @param string $path
|
||||
* @param string $data
|
||||
* @return int
|
||||
*/
|
||||
public static function put($path, $data)
|
||||
{
|
||||
return file_put_contents($path, $data, LOCK_EX);
|
||||
}
|
||||
|
||||
/**
|
||||
* Append to a file.
|
||||
*
|
||||
* @param string $path
|
||||
* @param string $data
|
||||
* @return int
|
||||
*/
|
||||
public static function append($path, $data)
|
||||
{
|
||||
return file_put_contents($path, $data, LOCK_EX | FILE_APPEND);
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract the extension from a file path.
|
||||
*
|
||||
* @param string $path
|
||||
* @return string
|
||||
*/
|
||||
public static function extension($path)
|
||||
{
|
||||
return pathinfo($path, PATHINFO_EXTENSION);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the lines surrounding a given line in a file.
|
||||
*
|
||||
* @param string $path
|
||||
* @param int $line
|
||||
* @param int $padding
|
||||
* @return array
|
||||
*/
|
||||
public static function snapshot($path, $line, $padding = 5)
|
||||
{
|
||||
if ( ! file_exists($path)) return array();
|
||||
|
||||
$file = file($path, FILE_IGNORE_NEW_LINES);
|
||||
|
||||
array_unshift($file, '');
|
||||
|
||||
if (($start = $line - $padding) < 0) $start = 0;
|
||||
|
||||
if (($length = ($line - $start) + $padding + 1) < 0) $length = 0;
|
||||
|
||||
return array_slice($file, $start, $length, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a file MIME type by extension.
|
||||
*
|
||||
* @param string $extension
|
||||
* @param string $default
|
||||
* @return string
|
||||
*/
|
||||
public static function mime($extension, $default = 'application/octet-stream')
|
||||
{
|
||||
$mimes = Config::get('mimes');
|
||||
|
||||
if (array_key_exists($extension, $mimes))
|
||||
{
|
||||
return (is_array($mimes[$extension])) ? $mimes[$extension][0] : $mimes[$extension];
|
||||
}
|
||||
|
||||
return $default;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if a file is a given type.
|
||||
*
|
||||
* The Fileinfo PHP extension will be used to determine the MIME type
|
||||
* of the file. Any extension in the mimes configuration array may
|
||||
* be passed as a type.
|
||||
*/
|
||||
public static function is($extension, $path)
|
||||
{
|
||||
$mimes = Config::get('mimes');
|
||||
|
||||
if ( ! array_key_exists($extension, $mimes))
|
||||
{
|
||||
throw new \Exception("File extension [$extension] is unknown. Cannot determine file type.");
|
||||
}
|
||||
|
||||
$mime = finfo_file(finfo_open(FILEINFO_MIME_TYPE), $path);
|
||||
|
||||
return (is_array($mimes[$extension])) ? in_array($mime, $mimes[$extension]) : $mime === $mimes[$extension];
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a response that will force a file to be downloaded.
|
||||
*
|
||||
* @param string $path
|
||||
* @param string $name
|
||||
* @return Response
|
||||
*/
|
||||
public static function download($path, $name = null)
|
||||
{
|
||||
if (is_null($name))
|
||||
{
|
||||
$name = basename($path);
|
||||
}
|
||||
|
||||
$response = Response::make(static::get($path));
|
||||
|
||||
$response->header('Content-Description', 'File Transfer');
|
||||
$response->header('Content-Type', static::mime(static::extension($path)));
|
||||
$response->header('Content-Disposition', 'attachment; filename="'.$name.'"');
|
||||
$response->header('Content-Transfer-Encoding', 'binary');
|
||||
$response->header('Expires', 0);
|
||||
$response->header('Cache-Control', 'must-revalidate, post-check=0, pre-check=0');
|
||||
$response->header('Pragma', 'public');
|
||||
$response->header('Content-Length', filesize($path));
|
||||
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* Move an uploaded file to storage.
|
||||
*
|
||||
* @param string $key
|
||||
* @param string $path
|
||||
* @return bool
|
||||
*/
|
||||
public static function upload($key, $path)
|
||||
{
|
||||
return array_key_exists($key, $_FILES) ? move_uploaded_file($_FILES[$key]['tmp_name'], $path) : false;
|
||||
}
|
||||
}
|
||||
423
laravel/form.php
Normal file
423
laravel/form.php
Normal file
@@ -0,0 +1,423 @@
|
||||
<?php namespace Laravel;
|
||||
|
||||
class Form {
|
||||
|
||||
/**
|
||||
* Stores labels names.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
private static $labels = array();
|
||||
|
||||
/**
|
||||
* Open a HTML form.
|
||||
*
|
||||
* @param string $action
|
||||
* @param string $method
|
||||
* @param array $attributes
|
||||
* @param bool $https
|
||||
* @return string
|
||||
*/
|
||||
public static function open($action = null, $method = 'POST', $attributes = array(), $https = false)
|
||||
{
|
||||
$attributes['action'] = HTML::entities(URL::to(((is_null($action)) ? Request::uri() : $action), $https));
|
||||
|
||||
// PUT and DELETE methods are spoofed using a hidden field containing the request method.
|
||||
// Since, HTML does not support PUT and DELETE on forms, we will use POST.
|
||||
$attributes['method'] = ($method == 'PUT' or $method == 'DELETE') ? 'POST' : $method;
|
||||
|
||||
if ( ! array_key_exists('accept-charset', $attributes))
|
||||
{
|
||||
$attributes['accept-charset'] = Config::get('application.encoding');
|
||||
}
|
||||
|
||||
$html = '<form'.HTML::attributes($attributes).'>';
|
||||
|
||||
if ($method == 'PUT' or $method == 'DELETE')
|
||||
{
|
||||
$html .= PHP_EOL.static::input('hidden', 'REQUEST_METHOD', $method);
|
||||
}
|
||||
|
||||
return $html.PHP_EOL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Open a HTML form with a HTTPS action.
|
||||
*
|
||||
* @param string $action
|
||||
* @param string $method
|
||||
* @param array $attributes
|
||||
* @return string
|
||||
*/
|
||||
public static function open_secure($action = null, $method = 'POST', $attributes = array())
|
||||
{
|
||||
return static::open($action, $method, $attributes, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Open a HTML form that accepts file uploads.
|
||||
*
|
||||
* @param string $action
|
||||
* @param string $method
|
||||
* @param array $attributes
|
||||
* @param bool $https
|
||||
* @return string
|
||||
*/
|
||||
public static function open_for_files($action = null, $method = 'POST', $attributes = array(), $https = false)
|
||||
{
|
||||
$attributes['enctype'] = 'multipart/form-data';
|
||||
|
||||
return static::open($action, $method, $attributes, $https);
|
||||
}
|
||||
|
||||
/**
|
||||
* Open a HTML form that accepts file uploads with a HTTPS action.
|
||||
*
|
||||
* @param string $action
|
||||
* @param string $method
|
||||
* @param array $attributes
|
||||
* @return string
|
||||
*/
|
||||
public static function open_secure_for_files($action = null, $method = 'POST', $attributes = array())
|
||||
{
|
||||
return static::open_for_files($action, $method, $attributes, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Close a HTML form.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function close()
|
||||
{
|
||||
return '</form>';
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate a hidden field containing the current CSRF token.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function token()
|
||||
{
|
||||
return static::input('hidden', 'csrf_token', static::raw_token());
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the current CSRF token.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function raw_token()
|
||||
{
|
||||
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 label element.
|
||||
*
|
||||
* @param string $name
|
||||
* @param string $value
|
||||
* @param array $attributes
|
||||
* @return string
|
||||
*/
|
||||
public static function label($name, $value, $attributes = array())
|
||||
{
|
||||
static::$labels[] = $name;
|
||||
|
||||
return '<label for="'.$name.'"'.HTML::attributes($attributes).'>'.HTML::entities($value).'</label>'.PHP_EOL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a HTML input element.
|
||||
*
|
||||
* @param string $name
|
||||
* @param mixed $value
|
||||
* @param array $attributes
|
||||
* @return string
|
||||
*/
|
||||
public static function input($type, $name, $value = null, $attributes = array())
|
||||
{
|
||||
$id = static::id($name, $attributes);
|
||||
|
||||
return '<input'.HTML::attributes(array_merge($attributes, compact('type', 'name', 'value', 'id'))).'>'.PHP_EOL;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 string $value
|
||||
* @param array $attributes
|
||||
* @return string
|
||||
*/
|
||||
public static function hidden($name, $value = null, $attributes = array())
|
||||
{
|
||||
return static::input('hidden', $name, $value, $attributes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a HTML search input element.
|
||||
*
|
||||
* @param string $name
|
||||
* @param string $value
|
||||
* @param array $attributes
|
||||
* @return string
|
||||
*/
|
||||
public static function search($name, $value = null, $attributes = array())
|
||||
{
|
||||
return static::input('search', $name, $value, $attributes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a HTML email input element.
|
||||
*
|
||||
* @param string $name
|
||||
* @param string $value
|
||||
* @param array $attributes
|
||||
* @return string
|
||||
*/
|
||||
public static function email($name, $value = null, $attributes = array())
|
||||
{
|
||||
return static::input('email', $name, $value, $attributes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a HTML telephone input element.
|
||||
*
|
||||
* @param string $name
|
||||
* @param string $value
|
||||
* @param array $attributes
|
||||
* @return string
|
||||
*/
|
||||
public static function telephone($name, $value = null, $attributes = array())
|
||||
{
|
||||
return static::input('tel', $name, $value, $attributes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a HTML URL input element.
|
||||
*
|
||||
* @param string $name
|
||||
* @param string $value
|
||||
* @param array $attributes
|
||||
* @return string
|
||||
*/
|
||||
public static function url($name, $value = null, $attributes = array())
|
||||
{
|
||||
return static::input('url', $name, $value, $attributes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a HTML number input element.
|
||||
*
|
||||
* @param string $name
|
||||
* @param string $value
|
||||
* @param array $attributes
|
||||
* @return string
|
||||
*/
|
||||
public static function number($name, $value = null, $attributes = array())
|
||||
{
|
||||
return static::input('number', $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 textarea element.
|
||||
*
|
||||
* @param string $name
|
||||
* @param string $value
|
||||
* @param array $attributes
|
||||
* @return string
|
||||
*/
|
||||
public static function textarea($name, $value = '', $attributes = array())
|
||||
{
|
||||
$attributes = array_merge($attributes, array('id' => static::id($name, $attributes), 'name' => $name));
|
||||
|
||||
if ( ! isset($attributes['rows'])) $attributes['rows'] = 10;
|
||||
|
||||
if ( ! isset($attributes['cols'])) $attributes['cols'] = 50;
|
||||
|
||||
return '<textarea'.HTML::attributes($attributes).'>'.HTML::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())
|
||||
{
|
||||
$attributes = array_merge($attributes, array('id' => static::id($name, $attributes), 'name' => $name));
|
||||
|
||||
$html = array();
|
||||
|
||||
foreach ($options as $value => $display)
|
||||
{
|
||||
$option_attributes = array('value' => HTML::entities($value), 'selected' => ($value == $selected) ? 'selected' : null);
|
||||
|
||||
$html[] = '<option'.HTML::attributes($option_attributes).'>'.HTML::entities($display).'</option>';
|
||||
}
|
||||
|
||||
return '<select'.HTML::attributes($attributes).'>'.implode('', $html).'</select>'.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)
|
||||
{
|
||||
$attributes = array_merge($attributes, array('id' => static::id($name, $attributes), 'checked' => ($checked) ? 'checked' : null));
|
||||
|
||||
return static::input($type, $name, $value, $attributes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a HTML submit input element.
|
||||
*
|
||||
* @param string $value
|
||||
* @param array $attributes
|
||||
* @return string
|
||||
*/
|
||||
public static function submit($value, $attributes = array())
|
||||
{
|
||||
return static::input('submit', null, $value, $attributes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a HTML reset input element.
|
||||
*
|
||||
* @param string $value
|
||||
* @param array $attributes
|
||||
* @return string
|
||||
*/
|
||||
public static function reset($value, $attributes = array())
|
||||
{
|
||||
return static::input('reset', null, $value, $attributes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a HTML image input element.
|
||||
*
|
||||
* @param string $url
|
||||
* @param array $attributes
|
||||
* @return string
|
||||
*/
|
||||
public static function image($url, $name = null, $attributes = array())
|
||||
{
|
||||
$attributes['src'] = URL::to_asset($url);
|
||||
|
||||
return static::input('image', $name, null, $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).'>'.HTML::entities($value).'</button>'.PHP_EOL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine the ID attribute for a form element.
|
||||
*
|
||||
* An explicitly specified ID in the attributes takes first precedence, then
|
||||
* the label names will be checked for a label matching the element name.
|
||||
*
|
||||
* @param string $name
|
||||
* @param array $attributes
|
||||
* @return mixed
|
||||
*/
|
||||
private static function id($name, $attributes)
|
||||
{
|
||||
if (array_key_exists('id', $attributes)) return $attributes['id'];
|
||||
|
||||
if (in_array($name, static::$labels)) return $name;
|
||||
}
|
||||
|
||||
}
|
||||
45
laravel/hash.php
Normal file
45
laravel/hash.php
Normal file
@@ -0,0 +1,45 @@
|
||||
<?php namespace Laravel;
|
||||
|
||||
class Hash {
|
||||
|
||||
/**
|
||||
* Hash a string using PHPass.
|
||||
*
|
||||
* PHPass provides reliable bcrypt hashing, and is used by many popular PHP
|
||||
* applications such as Wordpress and Joomla.
|
||||
*
|
||||
* @access public
|
||||
* @param string $value
|
||||
* @return string
|
||||
*/
|
||||
public static function make($value, $rounds = 10)
|
||||
{
|
||||
return static::hasher($rounds)->HashPassword($value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if an unhashed value matches a given hash.
|
||||
*
|
||||
* @param string $value
|
||||
* @param string $hash
|
||||
* @return bool
|
||||
*/
|
||||
public static function check($value, $hash)
|
||||
{
|
||||
return static::hasher()->CheckPassword($value, $hash);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new PHPass instance.
|
||||
*
|
||||
* @param int $rounds
|
||||
* @return PasswordHash
|
||||
*/
|
||||
private static function hasher($rounds = 10)
|
||||
{
|
||||
require_once SYS_PATH.'vendor/phpass'.EXT;
|
||||
|
||||
return new \PasswordHash($rounds, false);
|
||||
}
|
||||
|
||||
}
|
||||
305
laravel/html.php
Normal file
305
laravel/html.php
Normal file
@@ -0,0 +1,305 @@
|
||||
<?php namespace Laravel;
|
||||
|
||||
class HTML {
|
||||
|
||||
/**
|
||||
* Convert HTML characters to entities.
|
||||
*
|
||||
* @param string $value
|
||||
* @return string
|
||||
*/
|
||||
public static function entities($value)
|
||||
{
|
||||
return htmlentities($value, ENT_QUOTES, Config::get('application.encoding'), false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate a JavaScript reference.
|
||||
*
|
||||
* @param string $url
|
||||
* @param array $attributes
|
||||
* @return string
|
||||
*/
|
||||
public static function script($url, $attributes = array())
|
||||
{
|
||||
return '<script type="text/javascript" src="'.static::entities(URL::to_asset($url)).'"'.static::attributes($attributes).'></script>'.PHP_EOL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate a CSS reference.
|
||||
*
|
||||
* @param string $url
|
||||
* @param array $attributes
|
||||
* @return string
|
||||
*/
|
||||
public static function style($url, $attributes = array())
|
||||
{
|
||||
if ( ! array_key_exists('media', $attributes)) $attributes['media'] = 'all';
|
||||
|
||||
$attributes = $attributes + array('rel' => 'stylesheet', 'type' => 'text/css');
|
||||
|
||||
return '<link href="'.static::entities(URL::to_asset($url)).'"'.static::attributes($attributes).'>'.PHP_EOL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate a HTML span.
|
||||
*
|
||||
* @param string $value
|
||||
* @param array $attributes
|
||||
* @return string
|
||||
*/
|
||||
public static function span($value, $attributes = array())
|
||||
{
|
||||
return '<span'.static::attributes($attributes).'>'.static::entities($value).'</span>';
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate a HTML link.
|
||||
*
|
||||
* @param string $url
|
||||
* @param string $title
|
||||
* @param array $attributes
|
||||
* @param bool $https
|
||||
* @param bool $asset
|
||||
* @return string
|
||||
*/
|
||||
public static function link($url, $title, $attributes = array(), $https = false, $asset = false)
|
||||
{
|
||||
return '<a href="'.static::entities(URL::to($url, $https, $asset)).'"'.static::attributes($attributes).'>'.static::entities($title).'</a>';
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate a HTTPS HTML link.
|
||||
*
|
||||
* @param string $url
|
||||
* @param string $title
|
||||
* @param array $attributes
|
||||
* @return string
|
||||
*/
|
||||
public static function link_to_secure($url, $title, $attributes = array())
|
||||
{
|
||||
return static::link($url, $title, $attributes, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate an HTML link to an asset.
|
||||
*
|
||||
* @param string $url
|
||||
* @param string $title
|
||||
* @param array $attributes
|
||||
* @return string
|
||||
*/
|
||||
public static function link_to_asset($url, $title, $attributes = array(), $https = false)
|
||||
{
|
||||
return static::link($url, $title, $attributes, $https, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate an HTTPS HTML link to an asset.
|
||||
*
|
||||
* @param string $url
|
||||
* @param string $title
|
||||
* @param array $attributes
|
||||
* @return string
|
||||
*/
|
||||
public static function link_to_secure_asset($url, $title, $attributes = array())
|
||||
{
|
||||
return static::link_to_asset($url, $title, $attributes, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate an HTML link to a route.
|
||||
*
|
||||
* @param string $name
|
||||
* @param string $title
|
||||
* @param array $parameters
|
||||
* @param array $attributes
|
||||
* @return string
|
||||
*/
|
||||
public static function link_to_route($name, $title, $parameters = array(), $attributes = array(), $https = false)
|
||||
{
|
||||
return static::link(URL::to_route($name, $parameters, $https), $title, $attributes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate an HTTPS HTML link to a route.
|
||||
*
|
||||
* @param string $name
|
||||
* @param string $title
|
||||
* @param array $parameters
|
||||
* @param array $attributes
|
||||
* @return string
|
||||
*/
|
||||
public static function link_to_secure_route($name, $title, $parameters = array(), $attributes = array())
|
||||
{
|
||||
return static::link_to_route($name, $title, $parameters, $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())
|
||||
{
|
||||
$email = static::email($email);
|
||||
|
||||
if (is_null($title)) $title = $email;
|
||||
|
||||
return '<a href="mailto:'.$email.'"'.static::attributes($attributes).'>'.static::entities($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('@', '@', 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())
|
||||
{
|
||||
$attributes['alt'] = static::entities($alt);
|
||||
|
||||
return '<img src="'.static::entities(URL::to_asset($url)).'"'.static::attributes($attributes).'>';
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 = array())
|
||||
{
|
||||
$html = '';
|
||||
|
||||
foreach ($list as $key => $value)
|
||||
{
|
||||
$html .= (is_array($value)) ? static::list_elements($type, $value) : '<li>'.static::entities($value).'</li>';
|
||||
}
|
||||
|
||||
return '<'.$type.static::attributes($attributes).'>'.$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)
|
||||
{
|
||||
// Assume numeric-keyed attributes to have the same key and value.
|
||||
// Example: required="required", autofocus="autofocus", etc.
|
||||
if (is_numeric($key)) $key = $value;
|
||||
|
||||
if ( ! is_null($value))
|
||||
{
|
||||
$html[] = $key.'="'.static::entities($value).'"';
|
||||
}
|
||||
}
|
||||
|
||||
return (count($html) > 0) ? ' '.implode(' ', $html) : '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Obfuscate a string to prevent spam-bots from sniffing it.
|
||||
*
|
||||
* @param string $value
|
||||
* @return string
|
||||
*/
|
||||
public static function obfuscate($value)
|
||||
{
|
||||
$safe = '';
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
/**
|
||||
* Magic Method for handling dynamic static methods.
|
||||
*/
|
||||
public static function __callStatic($method, $parameters)
|
||||
{
|
||||
if (strpos($method, 'link_to_secure_') === 0)
|
||||
{
|
||||
array_unshift($parameters, substr($method, 15));
|
||||
|
||||
return forward_static_call_array('HTML::link_to_secure_route', $parameters);
|
||||
}
|
||||
|
||||
if (strpos($method, 'link_to_') === 0)
|
||||
{
|
||||
array_unshift($parameters, substr($method, 8));
|
||||
|
||||
return forward_static_call_array('HTML::link_to_route', $parameters);
|
||||
}
|
||||
|
||||
throw new \Exception("Static method [$method] is not defined on the HTML class.");
|
||||
}
|
||||
|
||||
}
|
||||
206
laravel/inflector.php
Normal file
206
laravel/inflector.php
Normal file
@@ -0,0 +1,206 @@
|
||||
<?php namespace Laravel;
|
||||
|
||||
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)
|
||||
{
|
||||
if (array_key_exists($value, static::$plural_cache))
|
||||
{
|
||||
return static::$plural_cache[$value];
|
||||
}
|
||||
|
||||
if (in_array(strtolower($value), static::$uncountable))
|
||||
{
|
||||
return static::$plural_cache[$value] = $value;
|
||||
}
|
||||
|
||||
foreach (static::$irregular as $pattern => $irregular)
|
||||
{
|
||||
$pattern = '/'.$pattern.'$/i';
|
||||
|
||||
if (preg_match($pattern, $value))
|
||||
{
|
||||
return static::$plural_cache[$value] = preg_replace($pattern, $irregular, $value);
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
if (array_key_exists($value, static::$singular_cache))
|
||||
{
|
||||
return static::$singular_cache[$value];
|
||||
}
|
||||
|
||||
if (in_array(strtolower($value), static::$uncountable))
|
||||
{
|
||||
return static::$singular_cache[$value] = $value;
|
||||
}
|
||||
|
||||
foreach (static::$irregular as $irregular => $pattern)
|
||||
{
|
||||
$pattern = '/'.$pattern.'$/i';
|
||||
|
||||
if (preg_match($pattern, $value))
|
||||
{
|
||||
return static::$singular_cache[$value] = preg_replace($pattern, $irregular, $value);
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
}
|
||||
119
laravel/input.php
Normal file
119
laravel/input.php
Normal file
@@ -0,0 +1,119 @@
|
||||
<?php namespace Laravel;
|
||||
|
||||
class Input {
|
||||
|
||||
/**
|
||||
* The input data for the request.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $input;
|
||||
|
||||
/**
|
||||
* Get all of the input data for the request.
|
||||
*
|
||||
* This method returns a merged array containing Input::get and Input::file.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public static function all()
|
||||
{
|
||||
return array_merge(static::get(), static::file());
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the input data contains an item.
|
||||
*
|
||||
* @param string $key
|
||||
* @return bool
|
||||
*/
|
||||
public static function has($key)
|
||||
{
|
||||
return ( ! is_null(static::get($key)) and trim((string) static::get($key)) !== '');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get an item from the input data.
|
||||
*
|
||||
* @param string $key
|
||||
* @param mixed $default
|
||||
* @return string
|
||||
*/
|
||||
public static function get($key = null, $default = null)
|
||||
{
|
||||
if (is_null(static::$input)) static::hydrate();
|
||||
|
||||
return Arr::get(static::$input, $key, $default);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the old input data contains an item.
|
||||
*
|
||||
* @param string $key
|
||||
* @return bool
|
||||
*/
|
||||
public static function had($key)
|
||||
{
|
||||
return ( ! is_null(static::old($key)) and trim((string) static::old($key)) !== '');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get input data from the previous request.
|
||||
*
|
||||
* @param string $key
|
||||
* @param mixed $default
|
||||
* @return string
|
||||
*/
|
||||
public static function old($key = null, $default = null)
|
||||
{
|
||||
if (Config::get('session.driver') == '')
|
||||
{
|
||||
throw new \Exception("Sessions must be enabled to retrieve old input data.");
|
||||
}
|
||||
|
||||
return Arr::get(Session::get('laravel_old_input', array()), $key, $default);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get an item from the uploaded file data.
|
||||
*
|
||||
* @param string $key
|
||||
* @param mixed $default
|
||||
* @return array
|
||||
*/
|
||||
public static function file($key = null, $default = null)
|
||||
{
|
||||
return Arr::get($_FILES, $key, $default);
|
||||
}
|
||||
|
||||
/**
|
||||
* Hydrate the input data for the request.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public static function hydrate()
|
||||
{
|
||||
switch (Request::method())
|
||||
{
|
||||
case 'GET':
|
||||
static::$input =& $_GET;
|
||||
break;
|
||||
|
||||
case 'POST':
|
||||
static::$input =& $_POST;
|
||||
break;
|
||||
|
||||
case 'PUT':
|
||||
case 'DELETE':
|
||||
if (Request::spoofed())
|
||||
{
|
||||
static::$input =& $_POST;
|
||||
}
|
||||
else
|
||||
{
|
||||
parse_str(file_get_contents('php://input'), static::$input);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
132
laravel/lang.php
Normal file
132
laravel/lang.php
Normal file
@@ -0,0 +1,132 @@
|
||||
<?php namespace Laravel;
|
||||
|
||||
class Lang {
|
||||
|
||||
/**
|
||||
* All of the loaded language lines.
|
||||
*
|
||||
* The array is keyed by [$language.$file].
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $lines = array();
|
||||
|
||||
/**
|
||||
* The key of the line that is being requested.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $key;
|
||||
|
||||
/**
|
||||
* The place-holder replacements.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public $replacements = array();
|
||||
|
||||
/**
|
||||
* Create a new Lang instance.
|
||||
*
|
||||
* Language lines are retrieved using "dot" notation. So, asking for the
|
||||
* "messages.required" language line would return the "required" line
|
||||
* from the "messages" language file.
|
||||
*
|
||||
* @param string $key
|
||||
* @param array $replacements
|
||||
* @return void
|
||||
*/
|
||||
public function __construct($key, $replacements = array())
|
||||
{
|
||||
$this->key = $key;
|
||||
$this->replacements = $replacements;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a Lang instance for a language line.
|
||||
*
|
||||
* @param string $key
|
||||
* @param array $replacements
|
||||
* @return Lang
|
||||
*/
|
||||
public static function line($key, $replacements = array())
|
||||
{
|
||||
return new static($key, $replacements);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the language line.
|
||||
*
|
||||
* @param string $language
|
||||
* @param mixed $default
|
||||
* @return string
|
||||
*/
|
||||
public function get($language = null, $default = null)
|
||||
{
|
||||
if (is_null($language)) $language = Config::get('application.language');
|
||||
|
||||
list($module, $file, $line) = $this->parse($this->key, $language);
|
||||
|
||||
$this->load($module, $file, $language);
|
||||
|
||||
if ( ! isset(static::$lines[$module][$language.$file][$line]))
|
||||
{
|
||||
return is_callable($default) ? call_user_func($default) : $default;
|
||||
}
|
||||
|
||||
$line = static::$lines[$module][$language.$file][$line];
|
||||
|
||||
foreach ($this->replacements as $key => $value)
|
||||
{
|
||||
$line = str_replace(':'.$key, $value, $line);
|
||||
}
|
||||
|
||||
return $line;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse a language key.
|
||||
*
|
||||
* @param string $key
|
||||
* @param string $language
|
||||
* @return array
|
||||
*/
|
||||
private function parse($key, $language)
|
||||
{
|
||||
list($module, $key) = Module::parse($key);
|
||||
|
||||
if (count($segments = explode('.', $key)) > 1)
|
||||
{
|
||||
return array($module, $segments[0], implode('.', array_slice($segments, 1)));
|
||||
}
|
||||
|
||||
throw new \Exception("Invalid language line [$key]. A specific line must be specified.");
|
||||
}
|
||||
|
||||
/**
|
||||
* Load a language file.
|
||||
*
|
||||
* @param string $module
|
||||
* @param string $file
|
||||
* @param string $language
|
||||
* @return void
|
||||
*/
|
||||
private function load($module, $file, $language)
|
||||
{
|
||||
if (isset(static::$lines[$module][$language.$file])) return;
|
||||
|
||||
if (file_exists($path = Module::path($module).'lang/'.$language.'/'.$file.EXT))
|
||||
{
|
||||
static::$lines[$module][$language.$file] = require $path;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the string content of the language line.
|
||||
*/
|
||||
public function __toString()
|
||||
{
|
||||
return $this->get();
|
||||
}
|
||||
|
||||
}
|
||||
198
laravel/laravel.php
Normal file
198
laravel/laravel.php
Normal file
@@ -0,0 +1,198 @@
|
||||
<?php namespace Laravel;
|
||||
|
||||
// --------------------------------------------------------------
|
||||
// Define the PHP file extension.
|
||||
// --------------------------------------------------------------
|
||||
define('EXT', '.php');
|
||||
|
||||
// --------------------------------------------------------------
|
||||
// Define the core framework paths.
|
||||
// --------------------------------------------------------------
|
||||
define('BASE_PATH', realpath(str_replace('laravel', '', $system)).'/');
|
||||
define('CONFIG_PATH', realpath($config).'/');
|
||||
define('MODULE_PATH', realpath($modules).'/');
|
||||
define('PACKAGE_PATH', realpath($packages).'/');
|
||||
define('PUBLIC_PATH', realpath($public).'/');
|
||||
define('STORAGE_PATH', realpath($storage).'/');
|
||||
define('SYS_PATH', realpath($system).'/');
|
||||
|
||||
unset($system, $config, $modules, $packages, $public, $storage);
|
||||
|
||||
// --------------------------------------------------------------
|
||||
// Define various other framework paths.
|
||||
// --------------------------------------------------------------
|
||||
define('CACHE_PATH', STORAGE_PATH.'cache/');
|
||||
define('DATABASE_PATH', STORAGE_PATH.'db/');
|
||||
define('SCRIPT_PATH', PUBLIC_PATH.'js/');
|
||||
define('SESSION_PATH', STORAGE_PATH.'sessions/');
|
||||
define('STYLE_PATH', PUBLIC_PATH.'css/');
|
||||
|
||||
// --------------------------------------------------------------
|
||||
// Define the default module.
|
||||
// --------------------------------------------------------------
|
||||
define('DEFAULT_MODULE', 'application');
|
||||
|
||||
// --------------------------------------------------------------
|
||||
// Load the classes used by the auto-loader.
|
||||
// --------------------------------------------------------------
|
||||
require SYS_PATH.'loader'.EXT;
|
||||
require SYS_PATH.'config'.EXT;
|
||||
require SYS_PATH.'module'.EXT;
|
||||
require SYS_PATH.'arr'.EXT;
|
||||
|
||||
// --------------------------------------------------------------
|
||||
// Register the active modules.
|
||||
// --------------------------------------------------------------
|
||||
Module::$modules = $active;
|
||||
|
||||
unset($active);
|
||||
|
||||
// --------------------------------------------------------------
|
||||
// Register the auto-loader.
|
||||
// --------------------------------------------------------------
|
||||
Loader::bootstrap(array(
|
||||
Module::path(DEFAULT_MODULE).'libraries/',
|
||||
Module::path(DEFAULT_MODULE).'models/',
|
||||
));
|
||||
|
||||
spl_autoload_register(array('Laravel\\Loader', 'load'));
|
||||
|
||||
// --------------------------------------------------------------
|
||||
// Set the error reporting and display levels.
|
||||
// --------------------------------------------------------------
|
||||
error_reporting(E_ALL | E_STRICT);
|
||||
|
||||
ini_set('display_errors', 'Off');
|
||||
|
||||
// --------------------------------------------------------------
|
||||
// Register the error / exception handlers.
|
||||
// --------------------------------------------------------------
|
||||
$error_dependencies = function()
|
||||
{
|
||||
require_once SYS_PATH.'exception/handler'.EXT;
|
||||
require_once SYS_PATH.'exception/examiner'.EXT;
|
||||
require_once SYS_PATH.'file'.EXT;
|
||||
};
|
||||
|
||||
set_exception_handler(function($e) use ($error_dependencies)
|
||||
{
|
||||
call_user_func($error_dependencies);
|
||||
|
||||
Exception\Handler::make($e)->handle();
|
||||
});
|
||||
|
||||
set_error_handler(function($number, $error, $file, $line) use ($error_dependencies)
|
||||
{
|
||||
call_user_func($error_dependencies);
|
||||
|
||||
Exception\Handler::make(new \ErrorException($error, $number, 0, $file, $line))->handle();
|
||||
});
|
||||
|
||||
register_shutdown_function(function() use ($error_dependencies)
|
||||
{
|
||||
if ( ! is_null($error = error_get_last()))
|
||||
{
|
||||
call_user_func($error_dependencies);
|
||||
|
||||
extract($error);
|
||||
|
||||
Exception\Handler::make(new \ErrorException($message, $type, 0, $file, $line))->handle();
|
||||
}
|
||||
});
|
||||
|
||||
// --------------------------------------------------------------
|
||||
// Set the default timezone.
|
||||
// --------------------------------------------------------------
|
||||
date_default_timezone_set(Config::get('application.timezone'));
|
||||
|
||||
// --------------------------------------------------------------
|
||||
// Load the session.
|
||||
// --------------------------------------------------------------
|
||||
if (Config::get('session.driver') != '') Session::load(Cookie::get('laravel_session'));
|
||||
|
||||
// --------------------------------------------------------------
|
||||
// Load all of the core routing classes.
|
||||
// --------------------------------------------------------------
|
||||
require SYS_PATH.'request'.EXT;
|
||||
require SYS_PATH.'response'.EXT;
|
||||
require SYS_PATH.'routing/route'.EXT;
|
||||
require SYS_PATH.'routing/router'.EXT;
|
||||
require SYS_PATH.'routing/loader'.EXT;
|
||||
require SYS_PATH.'routing/filter'.EXT;
|
||||
|
||||
// --------------------------------------------------------------
|
||||
// Load the packages that are in the auto-loaded packages array.
|
||||
// --------------------------------------------------------------
|
||||
if (count(Config::get('application.packages')) > 0)
|
||||
{
|
||||
require SYS_PATH.'package'.EXT;
|
||||
|
||||
Package::load(Config::get('application.packages'));
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------
|
||||
// Determine the module that should handle the request.
|
||||
// --------------------------------------------------------------
|
||||
$segments = explode('/', Request::uri());
|
||||
|
||||
define('ACTIVE_MODULE', (array_key_exists($segments[0], Module::$modules)) ? $segments[0] : DEFAULT_MODULE);
|
||||
|
||||
// --------------------------------------------------------------
|
||||
// Determine the path to the root of the active module.
|
||||
// --------------------------------------------------------------
|
||||
define('ACTIVE_MODULE_PATH', Module::path(ACTIVE_MODULE));
|
||||
|
||||
// --------------------------------------------------------------
|
||||
// Register the filters for the active module.
|
||||
// --------------------------------------------------------------
|
||||
if (file_exists(ACTIVE_MODULE_PATH.'filters'.EXT))
|
||||
{
|
||||
Routing\Filter::register(require ACTIVE_MODULE_PATH.'filters'.EXT);
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------
|
||||
// Call the "before" filter for the application and module.
|
||||
// --------------------------------------------------------------
|
||||
foreach (array('before', ACTIVE_MODULE.'::before') as $filter)
|
||||
{
|
||||
$response = Routing\Filter::call($filter, array(Request::method(), Request::uri()), true);
|
||||
|
||||
if ( ! is_null($response)) break;
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------
|
||||
// Route the request and get the response from the route.
|
||||
// --------------------------------------------------------------
|
||||
if (is_null($response))
|
||||
{
|
||||
$loader = new Routing\Loader(ACTIVE_MODULE_PATH);
|
||||
|
||||
$route = Routing\Router::make(Request::method(), Request::uri(), $loader)->route();
|
||||
|
||||
$response = (is_null($route)) ? Response::error('404') : $route->call();
|
||||
}
|
||||
|
||||
$response = Response::prepare($response);
|
||||
|
||||
// --------------------------------------------------------------
|
||||
// Call the "after" filter for the application and module.
|
||||
// --------------------------------------------------------------
|
||||
foreach (array(ACTIVE_MODULE.'::after', 'after') as $filter)
|
||||
{
|
||||
Routing\Filter::call($filter, array($response, Request::method(), Request::uri()));
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------
|
||||
// Stringify the response.
|
||||
// --------------------------------------------------------------
|
||||
$response->content = (string) $response->content;
|
||||
|
||||
// --------------------------------------------------------------
|
||||
// Close the session.
|
||||
// --------------------------------------------------------------
|
||||
if (Config::get('session.driver') != '') Session::close();
|
||||
|
||||
// --------------------------------------------------------------
|
||||
// Send the response to the browser.
|
||||
// --------------------------------------------------------------
|
||||
$response->send();
|
||||
120
laravel/loader.php
Normal file
120
laravel/loader.php
Normal file
@@ -0,0 +1,120 @@
|
||||
<?php namespace Laravel;
|
||||
|
||||
class Loader {
|
||||
|
||||
/**
|
||||
* The paths to be searched by the loader.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $paths = array(BASE_PATH);
|
||||
|
||||
/**
|
||||
* All of the class aliases.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $aliases = array();
|
||||
|
||||
/**
|
||||
* All of the active modules.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $modules = array();
|
||||
|
||||
/**
|
||||
* Bootstrap the auto-loader.
|
||||
*
|
||||
* @param array $paths
|
||||
* @return void
|
||||
*/
|
||||
public static function bootstrap($paths = array())
|
||||
{
|
||||
static::$aliases = Config::get('aliases');
|
||||
|
||||
foreach ($paths as $path) { static::register($path); }
|
||||
}
|
||||
|
||||
/**
|
||||
* Load a class file for a given class name.
|
||||
*
|
||||
* This function is registered on the SPL auto-loader stack by the front controller during each request.
|
||||
* All Laravel class names follow a namespace to directory convention.
|
||||
*
|
||||
* @param string $class
|
||||
* @return void
|
||||
*/
|
||||
public static function load($class)
|
||||
{
|
||||
$file = strtolower(str_replace('\\', '/', $class));
|
||||
|
||||
if (array_key_exists($class, static::$aliases)) return class_alias(static::$aliases[$class], $class);
|
||||
|
||||
(static::load_from_registered($file)) or static::load_from_module($file);
|
||||
}
|
||||
|
||||
/**
|
||||
* Load a class that is stored in the registered directories.
|
||||
*
|
||||
* @param string $file
|
||||
* @return bool
|
||||
*/
|
||||
private static function load_from_registered($file)
|
||||
{
|
||||
foreach (static::$paths as $directory)
|
||||
{
|
||||
if (file_exists($path = $directory.$file.EXT))
|
||||
{
|
||||
require $path;
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Load a class that is stored in a module.
|
||||
*
|
||||
* @param string $file
|
||||
* @return void
|
||||
*/
|
||||
private static function load_from_module($file)
|
||||
{
|
||||
// Since all module models and libraries must be namespaced to the
|
||||
// module name, we'll extract the module name from the file.
|
||||
$module = substr($file, 0, strpos($file, '/'));
|
||||
|
||||
if (in_array($module, Module::$modules))
|
||||
{
|
||||
$module = MODULE_PATH.$module.'/';
|
||||
|
||||
// Slice the module name off of the filename. Even though module libraries
|
||||
// and models are namespaced under the module, there will obviously not be
|
||||
// a folder matching that namespace in the libraries or models directories
|
||||
// of the module. Slicing it off will allow us to make a clean search for
|
||||
// the relevant class file.
|
||||
$file = substr($file, strpos($file, '/') + 1);
|
||||
|
||||
foreach (array($module.'models', $module.'libraries') as $directory)
|
||||
{
|
||||
if (file_exists($path = $directory.'/'.$file.EXT)) return require $path;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a path with the auto-loader. After registering the path, it will be
|
||||
* checked similarly to the models and libraries directories.
|
||||
*
|
||||
* @param string $path
|
||||
* @return void
|
||||
*/
|
||||
public static function register($path)
|
||||
{
|
||||
static::$paths[] = rtrim($path, '/').'/';
|
||||
}
|
||||
|
||||
}
|
||||
55
laravel/memcached.php
Normal file
55
laravel/memcached.php
Normal file
@@ -0,0 +1,55 @@
|
||||
<?php namespace Laravel;
|
||||
|
||||
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))
|
||||
{
|
||||
static::$instance = static::connect(Config::get('cache.servers'));
|
||||
}
|
||||
|
||||
return static::$instance;
|
||||
}
|
||||
|
||||
/**
|
||||
* Connect to the configured Memcached servers.
|
||||
*
|
||||
* @param array $servers
|
||||
* @return Memcache
|
||||
*/
|
||||
private static function connect($servers)
|
||||
{
|
||||
if ( ! class_exists('Memcache'))
|
||||
{
|
||||
throw new \Exception('Attempting to use Memcached, but the Memcached PHP extension is not installed on this server.');
|
||||
}
|
||||
|
||||
$memcache = new \Memcache;
|
||||
|
||||
foreach ($servers as $server)
|
||||
{
|
||||
$memcache->addServer($server['host'], $server['port'], true, $server['weight']);
|
||||
}
|
||||
|
||||
if ($memcache->getVersion() === false)
|
||||
{
|
||||
throw new \Exception('Memcached is configured. However, no connections could be made. Please verify your memcached configuration.');
|
||||
}
|
||||
|
||||
return $memcache;
|
||||
}
|
||||
|
||||
}
|
||||
113
laravel/messages.php
Normal file
113
laravel/messages.php
Normal file
@@ -0,0 +1,113 @@
|
||||
<?php namespace Laravel;
|
||||
|
||||
class Messages {
|
||||
|
||||
/**
|
||||
* All of the messages.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public $messages;
|
||||
|
||||
/**
|
||||
* Create a new Messages instance.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct($messages = array())
|
||||
{
|
||||
$this->messages = $messages;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a message to the collector.
|
||||
*
|
||||
* Duplicate messages will not be added.
|
||||
*
|
||||
* @param string $key
|
||||
* @param string $message
|
||||
* @return void
|
||||
*/
|
||||
public function add($key, $message)
|
||||
{
|
||||
if ( ! isset($this->messages[$key]) or array_search($message, $this->messages[$key]) === false)
|
||||
{
|
||||
$this->messages[$key][] = $message;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if messages exist for a given key.
|
||||
*
|
||||
* @param string $key
|
||||
* @return bool
|
||||
*/
|
||||
public function has($key)
|
||||
{
|
||||
return $this->first($key) !== '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the first message for a given key.
|
||||
*
|
||||
* @param string $key
|
||||
* @param string $format
|
||||
* @return string
|
||||
*/
|
||||
public function first($key, $format = ':message')
|
||||
{
|
||||
return (count($messages = $this->get($key, $format)) > 0) ? $messages[0] : '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all of the messages for a key.
|
||||
*
|
||||
* If no key is specified, all of the messages will be returned.
|
||||
*
|
||||
* @param string $key
|
||||
* @param string $format
|
||||
* @return array
|
||||
*/
|
||||
public function get($key = null, $format = ':message')
|
||||
{
|
||||
if (is_null($key)) return $this->all($format);
|
||||
|
||||
return (array_key_exists($key, $this->messages)) ? $this->format($this->messages[$key], $format) : array();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all of the messages.
|
||||
*
|
||||
* @param string $format
|
||||
* @return array
|
||||
*/
|
||||
public function all($format = ':message')
|
||||
{
|
||||
$all = array();
|
||||
|
||||
foreach ($this->messages as $messages)
|
||||
{
|
||||
$all = array_merge($all, $this->format($messages, $format));
|
||||
}
|
||||
|
||||
return $all;
|
||||
}
|
||||
|
||||
/**
|
||||
* Format an array of messages.
|
||||
*
|
||||
* @param array $messages
|
||||
* @param string $format
|
||||
* @return array
|
||||
*/
|
||||
private function format($messages, $format)
|
||||
{
|
||||
foreach ($messages as $key => &$message)
|
||||
{
|
||||
$message = str_replace(':message', $message, $format);
|
||||
}
|
||||
|
||||
return $messages;
|
||||
}
|
||||
|
||||
}
|
||||
67
laravel/module.php
Normal file
67
laravel/module.php
Normal file
@@ -0,0 +1,67 @@
|
||||
<?php namespace Laravel;
|
||||
|
||||
class Module {
|
||||
|
||||
/**
|
||||
* The active modules for the installation.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $modules = array();
|
||||
|
||||
/**
|
||||
* All of the loaded module paths.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
private static $paths = array();
|
||||
|
||||
/**
|
||||
* Parse a modularized identifier and get the module and key.
|
||||
*
|
||||
* Modular identifiers follow a {module}::{key} convention.
|
||||
*
|
||||
* @param string $key
|
||||
* @return array
|
||||
*/
|
||||
public static function parse($key)
|
||||
{
|
||||
$module = (strpos($key, '::') !== false) ? substr($key, 0, strpos($key, ':')) : DEFAULT_MODULE;
|
||||
|
||||
if ($module !== DEFAULT_MODULE) $key = substr($key, strpos($key, ':') + 2);
|
||||
|
||||
return array($module, $key);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the path for a given module.
|
||||
*
|
||||
* @param string $module
|
||||
* @return string
|
||||
*/
|
||||
public static function path($module)
|
||||
{
|
||||
if (array_key_exists($module, static::$paths)) return static::$paths[$module];
|
||||
|
||||
if (array_key_exists($module, static::$modules))
|
||||
{
|
||||
$path = (strpos(static::$modules[$module], BASE_PATH) === 0) ? static::$modules[$module].'/' : MODULE_PATH.static::$modules[$module].'/';
|
||||
}
|
||||
|
||||
return static::$paths[$module] = $path;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the an array of paths to all of the modules.
|
||||
*
|
||||
* The module paths will be determined by the modules that are specified in the application
|
||||
* modules configuration item. A trailing slash will be added to the paths.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public static function paths()
|
||||
{
|
||||
return array_map(function($module) { return Laravel\Module::path($module); }, static::$modules);
|
||||
}
|
||||
|
||||
}
|
||||
42
laravel/package.php
Normal file
42
laravel/package.php
Normal file
@@ -0,0 +1,42 @@
|
||||
<?php namespace Laravel;
|
||||
|
||||
class Package {
|
||||
|
||||
/**
|
||||
* All of the loaded packages.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $loaded = array();
|
||||
|
||||
/**
|
||||
* Load a package or set of packages.
|
||||
*
|
||||
* @param string|array $packages
|
||||
* @return void
|
||||
*/
|
||||
public static function load($packages)
|
||||
{
|
||||
foreach ((array) $packages as $package)
|
||||
{
|
||||
if ( ! static::loaded($package) and file_exists($bootstrap = PACKAGE_PATH.$package.'/bootstrap'.EXT))
|
||||
{
|
||||
require $bootstrap;
|
||||
}
|
||||
|
||||
static::$loaded[] = $package;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if a given package has been loaded.
|
||||
*
|
||||
* @param string $package
|
||||
* @return bool
|
||||
*/
|
||||
public static function loaded($package)
|
||||
{
|
||||
return array_key_exists($package, static::$loaded);
|
||||
}
|
||||
|
||||
}
|
||||
265
laravel/paginator.php
Normal file
265
laravel/paginator.php
Normal file
@@ -0,0 +1,265 @@
|
||||
<?php namespace Laravel;
|
||||
|
||||
class Paginator {
|
||||
|
||||
/**
|
||||
* The results for the current page.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public $results;
|
||||
|
||||
/**
|
||||
* The total number of results.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
public $total;
|
||||
|
||||
/**
|
||||
* The current page.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
public $page;
|
||||
|
||||
/**
|
||||
* The number of items per page.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
public $per_page;
|
||||
|
||||
/**
|
||||
* The last page available for the result set.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
public $last_page;
|
||||
|
||||
/**
|
||||
* The language that should be used when generating page links.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $language;
|
||||
|
||||
/**
|
||||
* The values that should be appended to the end of the link query strings.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public $append = array();
|
||||
|
||||
/**
|
||||
* Create a new Paginator instance.
|
||||
*
|
||||
* @param array $results
|
||||
* @param int $page
|
||||
* @param int $total
|
||||
* @param int $per_page
|
||||
* @param int $last_page
|
||||
* @return void
|
||||
*/
|
||||
public function __construct($results, $page, $total, $per_page, $last_page)
|
||||
{
|
||||
$this->last_page = $last_page;
|
||||
$this->per_page = $per_page;
|
||||
$this->results = $results;
|
||||
$this->total = $total;
|
||||
$this->page = $page;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new Paginator instance.
|
||||
*
|
||||
* @param array $results
|
||||
* @param int $total
|
||||
* @param int $per_page
|
||||
* @return Paginator
|
||||
*/
|
||||
public static function make($results, $total, $per_page)
|
||||
{
|
||||
return new static($results, static::page($total, $per_page), $total, $per_page, ceil($total / $per_page));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the current page from the request query string.
|
||||
*
|
||||
* The page will be validated and adjusted if it is less than one or greater than the last page.
|
||||
* For example, if the current page is not an integer or less than one, one will be returned.
|
||||
* If the current page is greater than the last page, the last page will be returned.
|
||||
*
|
||||
* @param int $total
|
||||
* @param int $per_page
|
||||
* @return int
|
||||
*/
|
||||
public static function page($total, $per_page)
|
||||
{
|
||||
$page = Input::get('page', 1);
|
||||
|
||||
if (is_numeric($page) and $page > $last_page = ceil($total / $per_page))
|
||||
{
|
||||
return ($last_page > 0) ? $last_page : 1;
|
||||
}
|
||||
|
||||
return ($page < 1 or filter_var($page, FILTER_VALIDATE_INT) === false) ? 1 : $page;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create the HTML pagination links.
|
||||
*
|
||||
* @param int $adjacent
|
||||
* @return string
|
||||
*/
|
||||
public function links($adjacent = 3)
|
||||
{
|
||||
if ($this->last_page <= 1) return '';
|
||||
|
||||
// The hard-coded "7" is to account for all of the constant elements in a sliding range.
|
||||
// Namely: The the current page, the two ellipses, the two beginning pages, and the two ending pages.
|
||||
$numbers = ($this->last_page < 7 + ($adjacent * 2)) ? $this->range(1, $this->last_page) : $this->slider($adjacent);
|
||||
|
||||
return '<div class="pagination">'.$this->previous().$numbers.$this->next().'</div>';
|
||||
}
|
||||
|
||||
/**
|
||||
* Build sliding list of HTML numeric page links.
|
||||
*
|
||||
* @param int $adjacent
|
||||
* @return string
|
||||
*/
|
||||
private function slider($adjacent)
|
||||
{
|
||||
if ($this->page <= $adjacent * 2)
|
||||
{
|
||||
return $this->range(1, 2 + ($adjacent * 2)).$this->ending();
|
||||
}
|
||||
elseif ($this->page >= $this->last_page - ($adjacent * 2))
|
||||
{
|
||||
return $this->beginning().$this->range($this->last_page - 2 - ($adjacent * 2), $this->last_page);
|
||||
}
|
||||
|
||||
return $this->beginning().$this->range($this->page - $adjacent, $this->page + $adjacent).$this->ending();
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate the "previous" HTML link.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function previous()
|
||||
{
|
||||
$text = Lang::line('pagination.previous')->get($this->language);
|
||||
|
||||
if ($this->page > 1)
|
||||
{
|
||||
return $this->link($this->page - 1, $text, 'prev_page').' ';
|
||||
}
|
||||
|
||||
return HTML::span($text, array('class' => 'disabled prev_page')).' ';
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate the "next" HTML link.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function next()
|
||||
{
|
||||
$text = Lang::line('pagination.next')->get($this->language);
|
||||
|
||||
if ($this->page < $this->last_page)
|
||||
{
|
||||
return $this->link($this->page + 1, $text, 'next_page');
|
||||
}
|
||||
|
||||
return HTML::span($text, array('class' => 'disabled next_page'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Build the first two page links for a sliding page range.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private function beginning()
|
||||
{
|
||||
return $this->range(1, 2).'<span class="dots">...</span>';
|
||||
}
|
||||
|
||||
/**
|
||||
* Build the last two page links for a sliding page range.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private function ending()
|
||||
{
|
||||
return '<span class="dots">...</span>'.$this->range($this->last_page - 1, $this->last_page);
|
||||
}
|
||||
|
||||
/**
|
||||
* Build a range of page links.
|
||||
*
|
||||
* For the current page, an HTML span element will be generated instead of a link.
|
||||
*
|
||||
* @param int $start
|
||||
* @param int $end
|
||||
* @return string
|
||||
*/
|
||||
private function range($start, $end)
|
||||
{
|
||||
$pages = '';
|
||||
|
||||
for ($i = $start; $i <= $end; $i++)
|
||||
{
|
||||
$pages .= ($this->page == $i) ? HTML::span($i, array('class' => 'current')).' ' : $this->link($i, $i, null).' ';
|
||||
}
|
||||
|
||||
return $pages;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a HTML page link.
|
||||
*
|
||||
* @param int $page
|
||||
* @param string $text
|
||||
* @param string $attributes
|
||||
* @return string
|
||||
*/
|
||||
private function link($page, $text, $class)
|
||||
{
|
||||
$append = '';
|
||||
|
||||
foreach ($this->append as $key => $value)
|
||||
{
|
||||
$append .= '&'.$key.'='.$value;
|
||||
}
|
||||
|
||||
return HTML::link(Request::uri().'?page='.$page.$append, $text, compact('class'), Request::is_secure());
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the language that should be used when generating page links.
|
||||
*
|
||||
* @param string $language
|
||||
* @return Paginator
|
||||
*/
|
||||
public function lang($language)
|
||||
{
|
||||
$this->language = $language;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the items that should be appended to the link query strings.
|
||||
*
|
||||
* @param array $values
|
||||
* @return Paginator
|
||||
*/
|
||||
public function append($values)
|
||||
{
|
||||
$this->append = $values;
|
||||
return $this;
|
||||
}
|
||||
|
||||
}
|
||||
93
laravel/redirect.php
Normal file
93
laravel/redirect.php
Normal file
@@ -0,0 +1,93 @@
|
||||
<?php namespace Laravel;
|
||||
|
||||
class Redirect {
|
||||
|
||||
/**
|
||||
* The redirect response.
|
||||
*
|
||||
* @var Response
|
||||
*/
|
||||
public $response;
|
||||
|
||||
/**
|
||||
* Create a new redirect instance.
|
||||
*
|
||||
* @param Response $response
|
||||
* @return void
|
||||
*/
|
||||
public function __construct($response)
|
||||
{
|
||||
$this->response = $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a redirect response.
|
||||
*
|
||||
* @param string $url
|
||||
* @param int $status
|
||||
* @param string $method
|
||||
* @param bool $https
|
||||
* @return Redirect
|
||||
*/
|
||||
public static function to($url, $status = 302, $method = 'location', $https = false)
|
||||
{
|
||||
$url = URL::to($url, $https);
|
||||
|
||||
return ($method == 'refresh')
|
||||
? new static(Response::make('', $status)->header('Refresh', '0;url='.$url))
|
||||
: new static(Response::make('', $status)->header('Location', $url));
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a redirect response to a HTTPS URL.
|
||||
*
|
||||
* @param string $url
|
||||
* @param int $status
|
||||
* @param string $method
|
||||
* @return Response
|
||||
*/
|
||||
public static function to_secure($url, $status = 302, $method = 'location')
|
||||
{
|
||||
return static::to($url, $status, $method, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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') == '')
|
||||
{
|
||||
throw new \Exception("Attempting to flash data to the session, but no session driver has been specified.");
|
||||
}
|
||||
|
||||
Session::flash($key, $value);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Magic Method to handle redirecting to routes.
|
||||
*/
|
||||
public static function __callStatic($method, $parameters)
|
||||
{
|
||||
$parameters = (isset($parameters[0])) ? $parameters[0] : array();
|
||||
|
||||
if (strpos($method, 'to_secure_') === 0)
|
||||
{
|
||||
return static::to(URL::to_route(substr($method, 10), $parameters, true));
|
||||
}
|
||||
|
||||
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.");
|
||||
}
|
||||
|
||||
}
|
||||
169
laravel/request.php
Normal file
169
laravel/request.php
Normal file
@@ -0,0 +1,169 @@
|
||||
<?php namespace Laravel;
|
||||
|
||||
class Request {
|
||||
|
||||
/**
|
||||
* The route handling the current request.
|
||||
*
|
||||
* @var Route
|
||||
*/
|
||||
public static $route;
|
||||
|
||||
/**
|
||||
* The request URI.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public static $uri;
|
||||
|
||||
/**
|
||||
* Get the request URI.
|
||||
*
|
||||
* If the request is to the root of application, a single forward slash will be returned.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function uri()
|
||||
{
|
||||
if ( ! is_null(static::$uri)) return static::$uri;
|
||||
|
||||
$uri = static::raw_uri();
|
||||
|
||||
if (strpos($uri, $base = parse_url(Config::get('application.url'), PHP_URL_PATH)) === 0)
|
||||
{
|
||||
$uri = substr($uri, strlen($base));
|
||||
}
|
||||
|
||||
if (strpos($uri, $index = '/index.php') === 0)
|
||||
{
|
||||
$uri = substr($uri, strlen($index));
|
||||
}
|
||||
|
||||
return static::$uri = (($uri = trim($uri, '/')) == '') ? '/' : $uri;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the raw request URI from the $_SERVER array.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private static function raw_uri()
|
||||
{
|
||||
if (isset($_SERVER['PATH_INFO']))
|
||||
{
|
||||
$uri = $_SERVER['PATH_INFO'];
|
||||
}
|
||||
elseif (isset($_SERVER['REQUEST_URI']))
|
||||
{
|
||||
$uri = parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new \Exception('Unable to determine the request URI.');
|
||||
}
|
||||
|
||||
if ($uri === false)
|
||||
{
|
||||
throw new \Exception("Malformed request URI. Request terminated.");
|
||||
}
|
||||
|
||||
return $uri;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the request method.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function method()
|
||||
{
|
||||
return (static::spoofed()) ? $_POST['REQUEST_METHOD'] : $_SERVER['REQUEST_METHOD'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the request method is being spoofed by a hidden Form element.
|
||||
*
|
||||
* Hidden form elements are used to spoof PUT and DELETE requests since
|
||||
* they are not supported by HTML forms.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public static function spoofed()
|
||||
{
|
||||
return is_array($_POST) and array_key_exists('REQUEST_METHOD', $_POST);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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'];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 using HTTPS.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public static function is_secure()
|
||||
{
|
||||
return (static::protocol() == 'https');
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the request is an AJAX request.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public static function is_ajax()
|
||||
{
|
||||
return (isset($_SERVER['HTTP_X_REQUESTED_WITH']) and strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) === 'xmlhttprequest');
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the route handling the request is a given name.
|
||||
*
|
||||
* @param string $name
|
||||
* @return bool
|
||||
*/
|
||||
public static function route_is($name)
|
||||
{
|
||||
return (is_array(static::$route->callback) and isset(static::$route->callback['name']) and static::$route->callback['name'] === $name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Magic Method to handle dynamic static methods.
|
||||
*/
|
||||
public static function __callStatic($method, $parameters)
|
||||
{
|
||||
if (strpos($method, 'route_is_') === 0)
|
||||
{
|
||||
return static::route_is(substr($method, 9));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
194
laravel/response.php
Normal file
194
laravel/response.php
Normal file
@@ -0,0 +1,194 @@
|
||||
<?php namespace Laravel;
|
||||
|
||||
class Response {
|
||||
|
||||
/**
|
||||
* The content of the response.
|
||||
*
|
||||
* @var mixed
|
||||
*/
|
||||
public $content;
|
||||
|
||||
/**
|
||||
* The HTTP status code of the response.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
public $status;
|
||||
|
||||
/**
|
||||
* The response headers.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public $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 error response instances.
|
||||
*
|
||||
* @param int $code
|
||||
* @param array $data
|
||||
* @return Response
|
||||
*/
|
||||
public static function error($code, $data = array())
|
||||
{
|
||||
return static::make(View::make('error/'.$code, $data), $code);
|
||||
}
|
||||
|
||||
/**
|
||||
* Take a value returned by a route and prepare a Response instance.
|
||||
*
|
||||
* @param mixed $response
|
||||
* @return Response
|
||||
*/
|
||||
public static function prepare($response)
|
||||
{
|
||||
if ($response instanceof Redirect) $response = $response->response;
|
||||
|
||||
return ( ! $response instanceof Response) ? new static($response) : $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* Send the response to the browser.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function send()
|
||||
{
|
||||
if ( ! array_key_exists('Content-Type', $this->headers))
|
||||
{
|
||||
$this->header('Content-Type', 'text/html; charset=utf-8');
|
||||
}
|
||||
|
||||
if ( ! headers_sent()) $this->send_headers();
|
||||
|
||||
echo (string) $this->content;
|
||||
}
|
||||
|
||||
/**
|
||||
* Send the response headers to the browser.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function send_headers()
|
||||
{
|
||||
$protocol = (isset($_SERVER['SERVER_PROTOCOL'])) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.1';
|
||||
|
||||
header($protocol.' '.$this->status.' '.$this->statuses[$this->status]);
|
||||
|
||||
foreach ($this->headers as $name => $value)
|
||||
{
|
||||
header($name.': '.$value, true);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the response is a redirect.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function is_redirect()
|
||||
{
|
||||
return $this->status == 301 or $this->status == 302;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the parsed content of the Response.
|
||||
*/
|
||||
public function __toString()
|
||||
{
|
||||
return (string) $this->content;
|
||||
}
|
||||
|
||||
}
|
||||
56
laravel/routing/filter.php
Normal file
56
laravel/routing/filter.php
Normal file
@@ -0,0 +1,56 @@
|
||||
<?php namespace Laravel\Routing;
|
||||
|
||||
class Filter {
|
||||
|
||||
/**
|
||||
* The loaded route filters.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
private static $filters = array();
|
||||
|
||||
/**
|
||||
* Register a set of route filters.
|
||||
*
|
||||
* @param array $filters
|
||||
* @return void
|
||||
*/
|
||||
public static function register($filters)
|
||||
{
|
||||
static::$filters = array_merge(static::$filters, $filters);
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear all of the registered route filters.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public static function clear()
|
||||
{
|
||||
static::$filters = array();
|
||||
}
|
||||
|
||||
/**
|
||||
* Call a set of route filters.
|
||||
*
|
||||
* @param string $filter
|
||||
* @param array $parameters
|
||||
* @param bool $override
|
||||
* @return mixed
|
||||
*/
|
||||
public static function call($filters, $parameters = array(), $override = false)
|
||||
{
|
||||
foreach (explode(', ', $filters) as $filter)
|
||||
{
|
||||
if ( ! isset(static::$filters[$filter])) continue;
|
||||
|
||||
$response = call_user_func_array(static::$filters[$filter], $parameters);
|
||||
|
||||
// "Before" filters may override the request cycle. For example, an authentication
|
||||
// filter may redirect a user to a login view if they are not logged in. Because of
|
||||
// this, we will return the first filter response if overriding is enabled.
|
||||
if ( ! is_null($response) and $override) return $response;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
40
laravel/routing/finder.php
Normal file
40
laravel/routing/finder.php
Normal file
@@ -0,0 +1,40 @@
|
||||
<?php namespace Laravel\Routing;
|
||||
|
||||
class Finder {
|
||||
|
||||
/**
|
||||
* The named routes that have been found so far.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $names = array();
|
||||
|
||||
/**
|
||||
* Find a named route in a given array of routes.
|
||||
*
|
||||
* @param string $name
|
||||
* @param array $routes
|
||||
* @return array
|
||||
*/
|
||||
public static function find($name, $routes)
|
||||
{
|
||||
if (array_key_exists($name, static::$names)) return static::$names[$name];
|
||||
|
||||
$arrayIterator = new \RecursiveArrayIterator($routes);
|
||||
|
||||
$recursiveIterator = new \RecursiveIteratorIterator($arrayIterator);
|
||||
|
||||
// Since routes can be nested deep within sub-directories, we need to recursively
|
||||
// iterate through each directory and gather all of the routes.
|
||||
foreach ($recursiveIterator as $iterator)
|
||||
{
|
||||
$route = $recursiveIterator->getSubIterator();
|
||||
|
||||
if (isset($route['name']) and $route['name'] == $name)
|
||||
{
|
||||
return static::$names[$name] = array($arrayIterator->key() => iterator_to_array($route));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
126
laravel/routing/loader.php
Normal file
126
laravel/routing/loader.php
Normal file
@@ -0,0 +1,126 @@
|
||||
<?php namespace Laravel\Routing;
|
||||
|
||||
use Laravel\Config;
|
||||
|
||||
class Loader {
|
||||
|
||||
/**
|
||||
* All of the routes for the application.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
private static $routes;
|
||||
|
||||
/**
|
||||
* The path where the routes are located.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $path;
|
||||
|
||||
/**
|
||||
* Create a new route loader instance.
|
||||
*
|
||||
* @param string $path
|
||||
* @return void
|
||||
*/
|
||||
public function __construct($path)
|
||||
{
|
||||
$this->path = $path;
|
||||
}
|
||||
|
||||
/**
|
||||
* Load the appropriate routes for the request URI.
|
||||
*
|
||||
* @param string
|
||||
* @return array
|
||||
*/
|
||||
public function load($uri)
|
||||
{
|
||||
$base = (file_exists($path = $this->path.'routes'.EXT)) ? require $path : array();
|
||||
|
||||
return array_merge($this->load_nested_routes(explode('/', $uri)), $base);
|
||||
}
|
||||
|
||||
/**
|
||||
* Load the appropriate routes from the routes directory.
|
||||
*
|
||||
* @param array $segments
|
||||
* @return array
|
||||
*/
|
||||
private function load_nested_routes($segments)
|
||||
{
|
||||
// If the request URI only more than one segment, and the last segment contains a dot, we will
|
||||
// assume the request is for a specific format (users.json or users.xml) and strip off
|
||||
// everything after the dot so we can load the appropriate file.
|
||||
if (count($segments) > 0 and strpos(end($segments), '.') !== false)
|
||||
{
|
||||
$segment = array_pop($segments);
|
||||
|
||||
array_push($segments, substr($segment, 0, strpos($segment, '.')));
|
||||
}
|
||||
|
||||
// Since it is no part of the route directory structure, shift the module name off of the
|
||||
// beginning of the array so we can locate the appropriate route file.
|
||||
if (count($segments) > 0 and ACTIVE_MODULE !== DEFAULT_MODULE)
|
||||
{
|
||||
array_shift($segments);
|
||||
}
|
||||
|
||||
// Work backwards through the URI segments until we find the deepest possible
|
||||
// matching route directory. Once we find it, we will return those routes.
|
||||
foreach (array_reverse($segments, true) as $key => $value)
|
||||
{
|
||||
if (file_exists($path = $this->path.'routes/'.implode('/', array_slice($segments, 0, $key + 1)).EXT))
|
||||
{
|
||||
return require $path;
|
||||
}
|
||||
}
|
||||
|
||||
return array();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all of the routes for the application.
|
||||
*
|
||||
* To improve performance, this operation will only be performed once. The routes
|
||||
* will be cached and returned on every subsequent call.
|
||||
*
|
||||
* @param bool $reload
|
||||
* @return array
|
||||
*/
|
||||
public static function all($reload = false)
|
||||
{
|
||||
if ( ! is_null(static::$routes) and ! $reload) return static::$routes;
|
||||
|
||||
$routes = array();
|
||||
|
||||
foreach (Module::paths() as $path)
|
||||
{
|
||||
if (file_exists($path.'routes'.EXT))
|
||||
{
|
||||
$routes = array_merge($routes, require $path.'routes'.EXT);
|
||||
}
|
||||
|
||||
if (is_dir($path.'routes'))
|
||||
{
|
||||
// Since route files can be nested deep within the route directory, we need to
|
||||
// recursively spin through the directory to find every file.
|
||||
$directoryIterator = new \RecursiveDirectoryIterator($path.'routes');
|
||||
|
||||
$recursiveIterator = new \RecursiveIteratorIterator($directoryIterator, \RecursiveIteratorIterator::SELF_FIRST);
|
||||
|
||||
foreach ($recursiveIterator as $file)
|
||||
{
|
||||
if (filetype($file) === 'file' and strpos($file, EXT) !== false)
|
||||
{
|
||||
$routes = array_merge($routes, require $file);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return static::$routes = $routes;
|
||||
}
|
||||
|
||||
}
|
||||
105
laravel/routing/route.php
Normal file
105
laravel/routing/route.php
Normal file
@@ -0,0 +1,105 @@
|
||||
<?php namespace Laravel\Routing;
|
||||
|
||||
use Laravel\Package;
|
||||
use Laravel\Response;
|
||||
|
||||
class Route {
|
||||
|
||||
/**
|
||||
* The route key, including request method and URI.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $key;
|
||||
|
||||
/**
|
||||
* The route callback or array.
|
||||
*
|
||||
* @var mixed
|
||||
*/
|
||||
public $callback;
|
||||
|
||||
/**
|
||||
* The parameters that will passed to the route function.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public $parameters;
|
||||
|
||||
/**
|
||||
* Create a new Route instance.
|
||||
*
|
||||
* @param string $key
|
||||
* @param mixed $callback
|
||||
* @param array $parameters
|
||||
* @return void
|
||||
*/
|
||||
public function __construct($key, $callback, $parameters = array())
|
||||
{
|
||||
$this->key = $key;
|
||||
$this->callback = $callback;
|
||||
$this->parameters = $parameters;
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the route function.
|
||||
*
|
||||
* @param mixed $route
|
||||
* @param array $parameters
|
||||
* @return Response
|
||||
*/
|
||||
public function call()
|
||||
{
|
||||
$response = null;
|
||||
|
||||
// The callback may be in array form, meaning it has attached filters or is named and we
|
||||
// will need to evaluate it further to determine what to do. If the callback is just a
|
||||
// closure, we can execute it now and return the result.
|
||||
if (is_callable($this->callback))
|
||||
{
|
||||
$response = call_user_func_array($this->callback, $this->parameters);
|
||||
}
|
||||
elseif (is_array($this->callback))
|
||||
{
|
||||
if (isset($this->callback['needs']))
|
||||
{
|
||||
Package::load(explode(', ', $this->callback['needs']));
|
||||
}
|
||||
|
||||
$response = isset($this->callback['before']) ? Filter::call($this->callback['before'], array(), true) : null;
|
||||
|
||||
if (is_null($response) and ! is_null($handler = $this->find_route_function()))
|
||||
{
|
||||
$response = call_user_func_array($handler, $this->parameters);
|
||||
}
|
||||
}
|
||||
|
||||
$response = Response::prepare($response);
|
||||
|
||||
if (is_array($this->callback) and isset($this->callback['after']))
|
||||
{
|
||||
Filter::call($this->callback['after'], array($response));
|
||||
}
|
||||
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract the route function from the route.
|
||||
*
|
||||
* If a "do" index is specified on the callback, that is the handler.
|
||||
* Otherwise, we will return the first callable array value.
|
||||
*
|
||||
* @return Closure
|
||||
*/
|
||||
private function find_route_function()
|
||||
{
|
||||
if (isset($this->callback['do'])) return $this->callback['do'];
|
||||
|
||||
foreach ($this->callback as $value)
|
||||
{
|
||||
if (is_callable($value)) return $value;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
116
laravel/routing/router.php
Normal file
116
laravel/routing/router.php
Normal file
@@ -0,0 +1,116 @@
|
||||
<?php namespace Laravel\Routing;
|
||||
|
||||
use Laravel\Request;
|
||||
|
||||
class Router {
|
||||
|
||||
/**
|
||||
* The request method and URI.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $request;
|
||||
|
||||
/**
|
||||
* All of the loaded routes.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public $routes;
|
||||
|
||||
/**
|
||||
* Create a new router for a request method and URI.
|
||||
*
|
||||
* @param string $method
|
||||
* @param string $uri
|
||||
* @param Loader $loader
|
||||
* @return void
|
||||
*/
|
||||
public function __construct($method, $uri, $loader)
|
||||
{
|
||||
// Put the request method and URI in route form. Routes begin with
|
||||
// the request method and a forward slash.
|
||||
$this->request = $method.' /'.trim($uri, '/');
|
||||
|
||||
$this->routes = $loader->load($uri);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new router for a request method and URI.
|
||||
*
|
||||
* @param string $method
|
||||
* @param string $uri
|
||||
* @param Loader $loader
|
||||
* @return Router
|
||||
*/
|
||||
public static function make($method, $uri, $loader)
|
||||
{
|
||||
return new static($method, $uri, $loader);
|
||||
}
|
||||
|
||||
/**
|
||||
* Search a set of routes for the route matching a method and URI.
|
||||
*
|
||||
* @return Route
|
||||
*/
|
||||
public function route()
|
||||
{
|
||||
// Check for a literal route match first. If we find one, there is
|
||||
// no need to spin through all of the routes.
|
||||
if (isset($this->routes[$this->request]))
|
||||
{
|
||||
return Request::$route = new Route($this->request, $this->routes[$this->request]);
|
||||
}
|
||||
|
||||
foreach ($this->routes as $keys => $callback)
|
||||
{
|
||||
// Only check routes that have multiple URIs or wildcards.
|
||||
// Other routes would have been caught by the check for literal matches.
|
||||
if (strpos($keys, '(') !== false or strpos($keys, ',') !== false )
|
||||
{
|
||||
foreach (explode(', ', $keys) as $key)
|
||||
{
|
||||
if (preg_match('#^'.$this->translate_wildcards($key).'$#', $this->request))
|
||||
{
|
||||
return Request::$route = new Route($keys, $callback, $this->parameters($this->request, $key));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Translate route URI wildcards into actual regular expressions.
|
||||
*
|
||||
* @param string $key
|
||||
* @return string
|
||||
*/
|
||||
private function translate_wildcards($key)
|
||||
{
|
||||
$replacements = 0;
|
||||
|
||||
// For optional parameters, first translate the wildcards to their
|
||||
// regex equivalent, sans the ")?" ending. We will add the endings
|
||||
// back on after we know how many replacements we made.
|
||||
$key = str_replace(array('/(:num?)', '/(:any?)'), array('(?:/([0-9]+)', '(?:/([a-zA-Z0-9\.\-_]+)'), $key, $replacements);
|
||||
|
||||
$key .= ($replacements > 0) ? str_repeat(')?', $replacements) : '';
|
||||
|
||||
return str_replace(array(':num', ':any'), array('[0-9]+', '[a-zA-Z0-9\.\-_]+'), $key);
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract the parameters from a URI based on a route URI.
|
||||
*
|
||||
* Any route segment wrapped in parentheses is considered a parameter.
|
||||
*
|
||||
* @param string $uri
|
||||
* @param string $route
|
||||
* @return array
|
||||
*/
|
||||
private function parameters($uri, $route)
|
||||
{
|
||||
return array_values(array_intersect_key(explode('/', $uri), preg_grep('/\(.+\)/', explode('/', $route))));
|
||||
}
|
||||
|
||||
}
|
||||
238
laravel/session.php
Normal file
238
laravel/session.php
Normal file
@@ -0,0 +1,238 @@
|
||||
<?php namespace Laravel;
|
||||
|
||||
class Session {
|
||||
|
||||
/**
|
||||
* The active session driver.
|
||||
*
|
||||
* @var Session\Driver
|
||||
*/
|
||||
public static $driver;
|
||||
|
||||
/**
|
||||
* The session payload, which contains the session ID, data and last activity timestamp.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $session = array();
|
||||
|
||||
/**
|
||||
* Get the session driver.
|
||||
*
|
||||
* @return Session\Driver
|
||||
*/
|
||||
public static function driver()
|
||||
{
|
||||
if (is_null(static::$driver))
|
||||
{
|
||||
switch (Config::get('session.driver'))
|
||||
{
|
||||
case 'cookie':
|
||||
return static::$driver = new Session\Cookie;
|
||||
|
||||
case 'file':
|
||||
return static::$driver = new Session\File;
|
||||
|
||||
case 'db':
|
||||
return static::$driver = new Session\DB;
|
||||
|
||||
case 'memcached':
|
||||
return static::$driver = new Session\Memcached;
|
||||
|
||||
case 'apc':
|
||||
return static::$driver = new Session\APC;
|
||||
|
||||
default:
|
||||
throw new \Exception("Session driver [$driver] is not supported.");
|
||||
}
|
||||
}
|
||||
|
||||
return static::$driver;
|
||||
}
|
||||
|
||||
/**
|
||||
* Load a user session by ID.
|
||||
*
|
||||
* @param string $id
|
||||
* @return void
|
||||
*/
|
||||
public static function load($id)
|
||||
{
|
||||
static::$session = ( ! is_null($id)) ? static::driver()->load($id) : null;
|
||||
|
||||
if (static::invalid(static::$session))
|
||||
{
|
||||
static::$session = array('id' => Str::random(40), 'data' => array());
|
||||
}
|
||||
|
||||
if ( ! static::has('csrf_token'))
|
||||
{
|
||||
static::put('csrf_token', Str::random(16));
|
||||
}
|
||||
|
||||
static::$session['last_activity'] = time();
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if a session is valid.
|
||||
*
|
||||
* A session is considered valid if it exists and has not expired.
|
||||
*
|
||||
* @param array $session
|
||||
* @return bool
|
||||
*/
|
||||
private static function invalid($session)
|
||||
{
|
||||
return is_null($session) or (time() - $session['last_activity']) > (Config::get('session.lifetime') * 60);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the session or flash data contains an item.
|
||||
*
|
||||
* @param string $key
|
||||
* @return bool
|
||||
*/
|
||||
public static function has($key)
|
||||
{
|
||||
return ( ! is_null(static::get($key)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get an item from the session or flash data.
|
||||
*
|
||||
* @param string $key
|
||||
* @return mixed
|
||||
*/
|
||||
public static function get($key, $default = null)
|
||||
{
|
||||
foreach (array($key, ':old:'.$key, ':new:'.$key) as $possibility)
|
||||
{
|
||||
if (array_key_exists($possibility, static::$session['data'])) return static::$session['data'][$possibility];
|
||||
}
|
||||
|
||||
return is_callable($default) ? call_user_func($default) : $default;
|
||||
}
|
||||
|
||||
/**
|
||||
* Write an item to the session.
|
||||
*
|
||||
* @param string $key
|
||||
* @param mixed $value
|
||||
* @return void
|
||||
*/
|
||||
public static function put($key, $value)
|
||||
{
|
||||
static::$session['data'][$key] = $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Write an item to the session flash data.
|
||||
*
|
||||
* @param string $key
|
||||
* @param mixed $value
|
||||
* @return void
|
||||
*/
|
||||
public static function flash($key, $value)
|
||||
{
|
||||
static::put(':new:'.$key, $value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove an item from the session.
|
||||
*
|
||||
* @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()
|
||||
{
|
||||
static::driver()->delete(static::$session['id']);
|
||||
|
||||
static::$session['id'] = Str::random(40);
|
||||
}
|
||||
|
||||
/**
|
||||
* Close the session.
|
||||
*
|
||||
* The session will be stored in persistant storage and the session cookie will be
|
||||
* session cookie will be sent to the browser. The old input data will also be
|
||||
* stored in the session flash data.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public static function close()
|
||||
{
|
||||
static::flash('laravel_old_input', Input::get());
|
||||
|
||||
static::age_flash();
|
||||
|
||||
static::driver()->save(static::$session);
|
||||
|
||||
static::write_cookie();
|
||||
|
||||
if (mt_rand(1, 100) <= 2 and static::driver() instanceof Session\Sweeper)
|
||||
{
|
||||
static::driver()->sweep(time() - (Config::get('session.lifetime') * 60));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Age the session flash data.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
private static function age_flash()
|
||||
{
|
||||
foreach (static::$session['data'] as $key => $value)
|
||||
{
|
||||
if (strpos($key, ':old:') === 0) static::forget($key);
|
||||
}
|
||||
|
||||
foreach (static::$session['data'] as $key => $value)
|
||||
{
|
||||
if (strpos($key, ':new:') === 0)
|
||||
{
|
||||
static::put(':old:'.substr($key, 5), $value);
|
||||
|
||||
static::forget($key);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Write the session cookie.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
private static function write_cookie()
|
||||
{
|
||||
if ( ! headers_sent())
|
||||
{
|
||||
extract(Config::get('session'));
|
||||
|
||||
$minutes = ($expire_on_close) ? 0 : $lifetime;
|
||||
|
||||
Cookie::put('laravel_session', static::$session['id'], $minutes, $path, $domain, $https, $http_only);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
41
laravel/session/apc.php
Normal file
41
laravel/session/apc.php
Normal file
@@ -0,0 +1,41 @@
|
||||
<?php namespace Laravel\Session;
|
||||
|
||||
use Laravel\Cache;
|
||||
use Laravel\Config;
|
||||
|
||||
class APC implements Driver {
|
||||
|
||||
/**
|
||||
* Load a session by ID.
|
||||
*
|
||||
* @param string $id
|
||||
* @return array
|
||||
*/
|
||||
public function load($id)
|
||||
{
|
||||
return Cache::driver('apc')->get($id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Save a session.
|
||||
*
|
||||
* @param array $session
|
||||
* @return void
|
||||
*/
|
||||
public function save($session)
|
||||
{
|
||||
Cache::driver('apc')->put($session['id'], $session, Config::get('session.lifetime'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete a session by ID.
|
||||
*
|
||||
* @param string $id
|
||||
* @return void
|
||||
*/
|
||||
public function delete($id)
|
||||
{
|
||||
Cache::driver('apc')->forget($id);
|
||||
}
|
||||
|
||||
}
|
||||
73
laravel/session/cookie.php
Normal file
73
laravel/session/cookie.php
Normal file
@@ -0,0 +1,73 @@
|
||||
<?php namespace Laravel\Session;
|
||||
|
||||
use Laravel\Config;
|
||||
use Laravel\Crypter;
|
||||
|
||||
class Cookie implements Driver {
|
||||
|
||||
/**
|
||||
* The Crypter instance.
|
||||
*
|
||||
* @var Crypter
|
||||
*/
|
||||
private $crypter;
|
||||
|
||||
/**
|
||||
* Create a new Cookie session driver instance.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
$this->crypter = new Crypter;
|
||||
|
||||
if (Config::get('application.key') == '')
|
||||
{
|
||||
throw new \Exception("You must set an application key before using the Cookie session driver.");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Load a session by ID.
|
||||
*
|
||||
* @param string $id
|
||||
* @return array
|
||||
*/
|
||||
public function load($id)
|
||||
{
|
||||
if (\System\Cookie::has('session_payload'))
|
||||
{
|
||||
return unserialize($this->crypter->decrypt(\System\Cookie::get('session_payload')));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Save a session.
|
||||
*
|
||||
* @param array $session
|
||||
* @return void
|
||||
*/
|
||||
public function save($session)
|
||||
{
|
||||
if ( ! headers_sent())
|
||||
{
|
||||
extract(Config::get('session'));
|
||||
|
||||
$payload = $this->crypter->encrypt(serialize($session));
|
||||
|
||||
\System\Cookie::put('session_payload', $payload, $lifetime, $path, $domain, $https, $http_only);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete a session by ID.
|
||||
*
|
||||
* @param string $id
|
||||
* @return void
|
||||
*/
|
||||
public function delete($id)
|
||||
{
|
||||
\System\Cookie::forget('session_payload');
|
||||
}
|
||||
|
||||
}
|
||||
76
laravel/session/db.php
Normal file
76
laravel/session/db.php
Normal file
@@ -0,0 +1,76 @@
|
||||
<?php namespace Laravel\Session;
|
||||
|
||||
use Laravel\Config;
|
||||
|
||||
class DB implements Driver, Sweeper {
|
||||
|
||||
/**
|
||||
* Load a session by ID.
|
||||
*
|
||||
* @param string $id
|
||||
* @return array
|
||||
*/
|
||||
public function load($id)
|
||||
{
|
||||
$session = $this->table()->find($id);
|
||||
|
||||
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)
|
||||
{
|
||||
$this->delete($session['id']);
|
||||
|
||||
$this->table()->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->table()->delete($id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete all expired sessions.
|
||||
*
|
||||
* @param int $expiration
|
||||
* @return void
|
||||
*/
|
||||
public function sweep($expiration)
|
||||
{
|
||||
$this->table()->where('last_activity', '<', $expiration)->delete();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a session database query.
|
||||
*
|
||||
* @return Query
|
||||
*/
|
||||
private function table()
|
||||
{
|
||||
return \System\DB::connection()->table(Config::get('session.table'));
|
||||
}
|
||||
|
||||
}
|
||||
29
laravel/session/driver.php
Normal file
29
laravel/session/driver.php
Normal file
@@ -0,0 +1,29 @@
|
||||
<?php namespace Laravel\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);
|
||||
|
||||
}
|
||||
52
laravel/session/file.php
Normal file
52
laravel/session/file.php
Normal file
@@ -0,0 +1,52 @@
|
||||
<?php namespace Laravel\Session;
|
||||
|
||||
class File implements Driver, Sweeper {
|
||||
|
||||
/**
|
||||
* Load a session by ID.
|
||||
*
|
||||
* @param string $id
|
||||
* @return array
|
||||
*/
|
||||
public function load($id)
|
||||
{
|
||||
if (file_exists($path = SESSION_PATH.$id)) return unserialize(file_get_contents($path));
|
||||
}
|
||||
|
||||
/**
|
||||
* Save a session.
|
||||
*
|
||||
* @param array $session
|
||||
* @return void
|
||||
*/
|
||||
public function save($session)
|
||||
{
|
||||
file_put_contents(SESSION_PATH.$session['id'], serialize($session), LOCK_EX);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete a session by ID.
|
||||
*
|
||||
* @param string $id
|
||||
* @return void
|
||||
*/
|
||||
public function delete($id)
|
||||
{
|
||||
@unlink(SESSION_PATH.$id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete all expired sessions.
|
||||
*
|
||||
* @param int $expiration
|
||||
* @return void
|
||||
*/
|
||||
public function sweep($expiration)
|
||||
{
|
||||
foreach (glob(SESSION_PATH.'*') as $file)
|
||||
{
|
||||
if (filetype($file) == 'file' and filemtime($file) < $expiration) @unlink($file);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
41
laravel/session/memcached.php
Normal file
41
laravel/session/memcached.php
Normal file
@@ -0,0 +1,41 @@
|
||||
<?php namespace Laravel\Session;
|
||||
|
||||
use Laravel\Cache;
|
||||
use Laravel\Config;
|
||||
|
||||
class Memcached implements Driver {
|
||||
|
||||
/**
|
||||
* Load a session by ID.
|
||||
*
|
||||
* @param string $id
|
||||
* @return array
|
||||
*/
|
||||
public function load($id)
|
||||
{
|
||||
return Cache::driver('memcached')->get($id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Save a session.
|
||||
*
|
||||
* @param array $session
|
||||
* @return void
|
||||
*/
|
||||
public function save($session)
|
||||
{
|
||||
Cache::driver('memcached')->put($session['id'], $session, Config::get('session.lifetime'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete a session by ID.
|
||||
*
|
||||
* @param string $id
|
||||
* @return void
|
||||
*/
|
||||
public function delete($id)
|
||||
{
|
||||
Cache::driver('memcached')->forget($id);
|
||||
}
|
||||
|
||||
}
|
||||
13
laravel/session/sweeper.php
Normal file
13
laravel/session/sweeper.php
Normal file
@@ -0,0 +1,13 @@
|
||||
<?php namespace Laravel\Session;
|
||||
|
||||
interface Sweeper {
|
||||
|
||||
/**
|
||||
* Delete all expired sessions.
|
||||
*
|
||||
* @param int $expiration
|
||||
* @return void
|
||||
*/
|
||||
public function sweep($expiration);
|
||||
|
||||
}
|
||||
116
laravel/str.php
Normal file
116
laravel/str.php
Normal file
@@ -0,0 +1,116 @@
|
||||
<?php namespace Laravel;
|
||||
|
||||
class Str {
|
||||
|
||||
/**
|
||||
* Convert HTML characters to entities.
|
||||
*
|
||||
* @param string $value
|
||||
* @return string
|
||||
*/
|
||||
public static function entities($value)
|
||||
{
|
||||
return htmlentities($value, ENT_QUOTES, Config::get('application.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, Config::get('application.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, Config::get('application.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, Config::get('application.encoding')) : ucwords(strtolower($value));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the length of a string.
|
||||
*
|
||||
* @param string $value
|
||||
* @return int
|
||||
*/
|
||||
public static function length($value)
|
||||
{
|
||||
return function_exists('mb_strlen') ? mb_strlen($value, Config::get('application.encoding')) : strlen($value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a string to 7-bit ASCII.
|
||||
*
|
||||
* @param string $value
|
||||
* @return string
|
||||
*/
|
||||
public static function ascii($value)
|
||||
{
|
||||
$foreign = Config::get('ascii');
|
||||
|
||||
$value = preg_replace(array_keys($foreign), array_values($foreign), $value);
|
||||
|
||||
return preg_replace('/[^\x09\x0A\x0D\x20-\x7E]/', '', $value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate a random alpha or alpha-numeric string.
|
||||
*
|
||||
* Supported types: 'alpha_num' and 'alpha'.
|
||||
*
|
||||
* @param int $length
|
||||
* @param string $type
|
||||
* @return string
|
||||
*/
|
||||
public static function random($length = 16, $type = 'alpha_num')
|
||||
{
|
||||
$value = '';
|
||||
|
||||
$pool_length = strlen($pool = static::pool($type)) - 1;
|
||||
|
||||
for ($i = 0; $i < $length; $i++)
|
||||
{
|
||||
$value .= $pool[mt_rand(0, $pool_length)];
|
||||
}
|
||||
|
||||
return $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a chracter pool.
|
||||
*
|
||||
* @param string $type
|
||||
* @return string
|
||||
*/
|
||||
private static function pool($type = 'alpha_num')
|
||||
{
|
||||
switch ($type)
|
||||
{
|
||||
case 'alpha_num':
|
||||
return '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
|
||||
|
||||
default:
|
||||
return 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
142
laravel/url.php
Normal file
142
laravel/url.php
Normal file
@@ -0,0 +1,142 @@
|
||||
<?php namespace Laravel;
|
||||
|
||||
class URL {
|
||||
|
||||
/**
|
||||
* Generate an application URL.
|
||||
*
|
||||
* If the given URL is already well-formed, it will be returned unchanged.
|
||||
*
|
||||
* @param string $url
|
||||
* @param bool $https
|
||||
* @param bool $asset
|
||||
* @return string
|
||||
*/
|
||||
public static function to($url = '', $https = false, $asset = false)
|
||||
{
|
||||
if (filter_var($url, FILTER_VALIDATE_URL) !== false) return $url;
|
||||
|
||||
$base = Config::get('application.url').'/'.Config::get('application.index');
|
||||
|
||||
if ($asset and Config::get('application.index') !== '')
|
||||
{
|
||||
$base = str_replace('/'.Config::get('application.index'), '', $base);
|
||||
}
|
||||
|
||||
if ($https and strpos($base, 'http://') === 0)
|
||||
{
|
||||
$base = 'https://'.substr($base, 7);
|
||||
}
|
||||
|
||||
return rtrim($base, '/').'/'.trim($url, '/');
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate an application URL with HTTPS.
|
||||
*
|
||||
* @param string $url
|
||||
* @return string
|
||||
*/
|
||||
public static function to_secure($url = '')
|
||||
{
|
||||
return static::to($url, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate an application URL to an asset. The index file
|
||||
* will not be added to the URL.
|
||||
*
|
||||
* @param string $url
|
||||
* @return string
|
||||
*/
|
||||
public static function to_asset($url)
|
||||
{
|
||||
return static::to($url, Request::is_secure(), true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate a URL from a route name.
|
||||
*
|
||||
* For routes that have wildcard parameters, an array may be passed as the
|
||||
* second parameter to the method. The values of this array will be used
|
||||
* to fill the wildcard segments of the route URI.
|
||||
*
|
||||
* @param string $name
|
||||
* @param array $parameters
|
||||
* @param bool $https
|
||||
* @return string
|
||||
*/
|
||||
public static function to_route($name, $parameters = array(), $https = false)
|
||||
{
|
||||
if ( ! is_null($route = Routing\Finder::find($name, Routing\Loader::all())))
|
||||
{
|
||||
$uris = explode(', ', key($route));
|
||||
|
||||
$uri = substr($uris[0], strpos($uris[0], '/'));
|
||||
|
||||
foreach ($parameters as $parameter)
|
||||
{
|
||||
$uri = preg_replace('/\(.+?\)/', $parameter, $uri, 1);
|
||||
}
|
||||
|
||||
$uri = str_replace(array('/(:any?)', '/(:num?)'), '', $uri);
|
||||
|
||||
return static::to($uri, $https);
|
||||
}
|
||||
|
||||
throw new \Exception("Error generating named route for route [$name]. Route is not defined.");
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate a HTTPS URL from a route name.
|
||||
*
|
||||
* @param string $name
|
||||
* @param array $parameters
|
||||
* @return string
|
||||
*/
|
||||
public static function to_secure_route($name, $parameters = array())
|
||||
{
|
||||
return static::to_route($name, $parameters, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate a URL friendly "slug".
|
||||
*
|
||||
* @param string $title
|
||||
* @param string $separator
|
||||
* @return string
|
||||
*/
|
||||
public static function slug($title, $separator = '-')
|
||||
{
|
||||
$title = Str::ascii($title);
|
||||
|
||||
// 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)
|
||||
{
|
||||
$parameters = (isset($parameters[0])) ? $parameters[0] : array();
|
||||
|
||||
if (strpos($method, 'to_secure_') === 0)
|
||||
{
|
||||
return static::to_route(substr($method, 10), $parameters, true);
|
||||
}
|
||||
|
||||
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.");
|
||||
}
|
||||
|
||||
}
|
||||
517
laravel/validator.php
Normal file
517
laravel/validator.php
Normal file
@@ -0,0 +1,517 @@
|
||||
<?php namespace Laravel;
|
||||
|
||||
class Validator {
|
||||
|
||||
/**
|
||||
* The array being validated.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public $attributes;
|
||||
|
||||
/**
|
||||
* The validation rules.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public $rules;
|
||||
|
||||
/**
|
||||
* The validation messages.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public $messages;
|
||||
|
||||
/**
|
||||
* The post-validation error messages.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public $errors;
|
||||
|
||||
/**
|
||||
* The language that should be used when retrieving error messages.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $language;
|
||||
|
||||
/**
|
||||
* The size related validation rules.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $size_rules = array('size', 'between', 'min', 'max');
|
||||
|
||||
/**
|
||||
* The numeric related validation rules.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $numeric_rules = array('numeric', 'integer');
|
||||
|
||||
/**
|
||||
* Create a new validator instance.
|
||||
*
|
||||
* @param array $attributes
|
||||
* @param array $rules
|
||||
* @param array $messages
|
||||
* @return void
|
||||
*/
|
||||
public function __construct($attributes, $rules, $messages = array())
|
||||
{
|
||||
foreach ($rules as $key => &$rule)
|
||||
{
|
||||
$rule = (is_string($rule)) ? explode('|', $rule) : $rule;
|
||||
}
|
||||
|
||||
$this->attributes = $attributes;
|
||||
$this->messages = $messages;
|
||||
$this->rules = $rules;
|
||||
}
|
||||
|
||||
/**
|
||||
* Factory for creating new validator instances.
|
||||
*
|
||||
* @param array $attributes
|
||||
* @param array $rules
|
||||
* @param array $messages
|
||||
* @return Validator
|
||||
*/
|
||||
public static function make($attributes, $rules, $messages = array())
|
||||
{
|
||||
return new static($attributes, $rules, $messages);
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate the target array using the specified validation rules.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function invalid()
|
||||
{
|
||||
return ! $this->valid();
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate the target array using the specified validation rules.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function valid()
|
||||
{
|
||||
$this->errors = new Messages;
|
||||
|
||||
foreach ($this->rules as $attribute => $rules)
|
||||
{
|
||||
foreach ($rules as $rule)
|
||||
{
|
||||
$this->check($attribute, $rule);
|
||||
}
|
||||
}
|
||||
|
||||
return count($this->errors->messages) == 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Evaluate an attribute against a validation rule.
|
||||
*
|
||||
* @param string $attribute
|
||||
* @param string $rule
|
||||
* @return void
|
||||
*/
|
||||
protected function check($attribute, $rule)
|
||||
{
|
||||
list($rule, $parameters) = $this->parse($rule);
|
||||
|
||||
if ( ! method_exists($this, $validator = 'validate_'.$rule))
|
||||
{
|
||||
throw new \Exception("Validation rule [$rule] doesn't exist.");
|
||||
}
|
||||
|
||||
// No validation will be run for attributes that do not exist unless the rule being validated
|
||||
// is "required" or "accepted". No other rules have implicit "required" checks.
|
||||
if ( ! static::validate_required($attribute) and ! in_array($rule, array('required', 'accepted'))) return;
|
||||
|
||||
if ( ! $this->$validator($attribute, $parameters))
|
||||
{
|
||||
$this->errors->add($attribute, $this->format_message($this->get_message($attribute, $rule), $attribute, $rule, $parameters));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate that a required attribute exists in the attributes array.
|
||||
*
|
||||
* @param string $attribute
|
||||
* @return bool
|
||||
*/
|
||||
protected function validate_required($attribute)
|
||||
{
|
||||
if ( ! array_key_exists($attribute, $this->attributes)) return false;
|
||||
|
||||
if (is_string($this->attributes[$attribute]) and trim($this->attributes[$attribute]) === '') return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate that an attribute has a matching confirmation attribute.
|
||||
*
|
||||
* @param string $attribute
|
||||
* @return bool
|
||||
*/
|
||||
protected function validate_confirmed($attribute)
|
||||
{
|
||||
return array_key_exists($attribute.'_confirmation', $this->attributes) and $this->attributes[$attribute] == $this->attributes[$attribute.'_confirmation'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate that an attribute was "accepted".
|
||||
*
|
||||
* This validation rule implies the attribute is "required".
|
||||
*
|
||||
* @param string $attribute
|
||||
* @return bool
|
||||
*/
|
||||
protected function validate_accepted($attribute)
|
||||
{
|
||||
return static::validate_required($attribute) and ($this->attributes[$attribute] == 'yes' or $this->attributes[$attribute] == '1');
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate that an attribute is numeric.
|
||||
*
|
||||
* @param string $attribute
|
||||
* @return bool
|
||||
*/
|
||||
protected function validate_numeric($attribute)
|
||||
{
|
||||
return is_numeric($this->attributes[$attribute]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate that an attribute is an integer.
|
||||
*
|
||||
* @param string $attribute
|
||||
* @return bool
|
||||
*/
|
||||
protected function validate_integer($attribute)
|
||||
{
|
||||
return filter_var($this->attributes[$attribute], FILTER_VALIDATE_INT) !== false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate the size of an attribute.
|
||||
*
|
||||
* @param string $attribute
|
||||
* @param array $parameters
|
||||
* @return bool
|
||||
*/
|
||||
protected function validate_size($attribute, $parameters)
|
||||
{
|
||||
return $this->get_size($attribute) == $parameters[0];
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate the size of an attribute is between a set of values.
|
||||
*
|
||||
* @param string $attribute
|
||||
* @param array $parameters
|
||||
* @return bool
|
||||
*/
|
||||
protected function validate_between($attribute, $parameters)
|
||||
{
|
||||
return $this->get_size($attribute) >= $parameters[0] and $this->get_size($attribute) <= $parameters[1];
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate the size of an attribute is greater than a minimum value.
|
||||
*
|
||||
* @param string $attribute
|
||||
* @param array $parameters
|
||||
* @return bool
|
||||
*/
|
||||
protected function validate_min($attribute, $parameters)
|
||||
{
|
||||
return $this->get_size($attribute) >= $parameters[0];
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate the size of an attribute is less than a maximum value.
|
||||
*
|
||||
* @param string $attribute
|
||||
* @param array $parameters
|
||||
* @return bool
|
||||
*/
|
||||
protected function validate_max($attribute, $parameters)
|
||||
{
|
||||
return $this->get_size($attribute) <= $parameters[0];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the size of an attribute.
|
||||
*
|
||||
* @param string $attribute
|
||||
* @return mixed
|
||||
*/
|
||||
protected function get_size($attribute)
|
||||
{
|
||||
if (is_numeric($this->attributes[$attribute]) and $this->has_rule($attribute, $this->numeric_rules))
|
||||
{
|
||||
return $this->attributes[$attribute];
|
||||
}
|
||||
|
||||
return (array_key_exists($attribute, $_FILES)) ? $this->attributes[$attribute]['size'] / 1024 : Str::length(trim($this->attributes[$attribute]));
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate an attribute is contained within a list of values.
|
||||
*
|
||||
* @param string $attribute
|
||||
* @param array $parameters
|
||||
* @return bool
|
||||
*/
|
||||
protected function validate_in($attribute, $parameters)
|
||||
{
|
||||
return in_array($this->attributes[$attribute], $parameters);
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate an attribute is not contained within a list of values.
|
||||
*
|
||||
* @param string $attribute
|
||||
* @param array $parameters
|
||||
* @return bool
|
||||
*/
|
||||
protected function validate_not_in($attribute, $parameters)
|
||||
{
|
||||
return ! in_array($this->attributes[$attribute], $parameters);
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate the uniqueness of an attribute value on a given database table.
|
||||
*
|
||||
* If a database column is not specified, the attribute name will be used.
|
||||
*
|
||||
* @param string $attribute
|
||||
* @param array $parameters
|
||||
* @return bool
|
||||
*/
|
||||
protected function validate_unique($attribute, $parameters)
|
||||
{
|
||||
if ( ! isset($parameters[1])) $parameters[1] = $attribute;
|
||||
|
||||
return DB::connection()->table($parameters[0])->where($parameters[1], '=', $this->attributes[$attribute])->count() == 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate than an attribute is a valid e-mail address.
|
||||
*
|
||||
* @param string $attribute
|
||||
* @return bool
|
||||
*/
|
||||
protected function validate_email($attribute)
|
||||
{
|
||||
return filter_var($this->attributes[$attribute], FILTER_VALIDATE_EMAIL) !== false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate than an attribute is a valid URL.
|
||||
*
|
||||
* @param string $attribute
|
||||
* @return bool
|
||||
*/
|
||||
protected function validate_url($attribute)
|
||||
{
|
||||
return filter_var($this->attributes[$attribute], FILTER_VALIDATE_URL) !== false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate that an attribute is an active URL.
|
||||
*
|
||||
* @param string $attribute
|
||||
* @return bool
|
||||
*/
|
||||
protected function validate_active_url($attribute)
|
||||
{
|
||||
$url = str_replace(array('http://', 'https://', 'ftp://'), '', Str::lower($this->attributes[$attribute]));
|
||||
|
||||
return checkdnsrr($url);
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate the MIME type of a file is an image MIME type.
|
||||
*
|
||||
* @param string $attribute
|
||||
* @return bool
|
||||
*/
|
||||
protected function validate_image($attribute)
|
||||
{
|
||||
return static::validate_mimes($attribute, array('jpg', 'png', 'gif', 'bmp'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate than an attribute contains only alphabetic characters.
|
||||
*
|
||||
* @param string $attribute
|
||||
* @return bool
|
||||
*/
|
||||
protected function validate_alpha($attribute)
|
||||
{
|
||||
return preg_match('/^([a-z])+$/i', $this->attributes[$attribute]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate than an attribute contains only alpha-numeric characters.
|
||||
*
|
||||
* @param string $attribute
|
||||
* @return bool
|
||||
*/
|
||||
protected function validate_alpha_num($attribute)
|
||||
{
|
||||
return preg_match('/^([a-z0-9])+$/i', $this->attributes[$attribute]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate than an attribute contains only alpha-numeric characters, dashes, and underscores.
|
||||
*
|
||||
* @param string $attribute
|
||||
* @return bool
|
||||
*/
|
||||
protected function validate_alpha_dash($attribute)
|
||||
{
|
||||
return preg_match('/^([-a-z0-9_-])+$/i', $this->attributes[$attribute]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate the MIME type of a file upload attribute is in a set of MIME types.
|
||||
*
|
||||
* @param string $attribute
|
||||
* @param array $parameters
|
||||
* @return bool
|
||||
*/
|
||||
protected function validate_mimes($attribute, $parameters)
|
||||
{
|
||||
foreach ($parameters as $extension)
|
||||
{
|
||||
if (File::is($extension, $this->attributes[$attribute]['tmp_name'])) return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the proper error message for an attribute and rule.
|
||||
*
|
||||
* Developer specified attribute specific rules take first priority.
|
||||
* Developer specified error rules take second priority.
|
||||
*
|
||||
* If the message has not been specified by the developer, the default will be used
|
||||
* from the validation language file.
|
||||
*
|
||||
* @param string $attribute
|
||||
* @param string $rule
|
||||
* @return string
|
||||
*/
|
||||
protected function get_message($attribute, $rule)
|
||||
{
|
||||
if (array_key_exists($attribute.'_'.$rule, $this->messages))
|
||||
{
|
||||
return $this->messages[$attribute.'_'.$rule];
|
||||
}
|
||||
elseif (array_key_exists($rule, $this->messages))
|
||||
{
|
||||
return $this->messages[$rule];
|
||||
}
|
||||
else
|
||||
{
|
||||
$message = Lang::line('validation.'.$rule)->get($this->language);
|
||||
|
||||
// For "size" rules that are validating strings or files, we need to adjust
|
||||
// the default error message for the appropriate type.
|
||||
if (in_array($rule, $this->size_rules) and ! $this->has_rule($attribute, $this->numeric_rules))
|
||||
{
|
||||
return (array_key_exists($attribute, $_FILES))
|
||||
? rtrim($message, '.').' '.Lang::line('validation.kilobytes')->get($this->language).'.'
|
||||
: rtrim($message, '.').' '.Lang::line('validation.characters')->get($this->language).'.';
|
||||
}
|
||||
|
||||
return $message;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Replace all error message place-holders with actual values.
|
||||
*
|
||||
* @param string $message
|
||||
* @param string $attribute
|
||||
* @param string $rule
|
||||
* @param array $parameters
|
||||
* @return string
|
||||
*/
|
||||
protected function format_message($message, $attribute, $rule, $parameters)
|
||||
{
|
||||
$display = Lang::line('attributes.'.$attribute)->get($this->language, str_replace('_', ' ', $attribute));
|
||||
|
||||
$message = str_replace(':attribute', $display, $message);
|
||||
|
||||
if (in_array($rule, $this->size_rules))
|
||||
{
|
||||
$max = ($rule == 'between') ? $parameters[1] : $parameters[0];
|
||||
|
||||
$message = str_replace(array(':size', ':min', ':max'), array($parameters[0], $parameters[0], $max), $message);
|
||||
}
|
||||
elseif (in_array($rule, array('in', 'not_in', 'mimes')))
|
||||
{
|
||||
$message = str_replace(':values', implode(', ', $parameters), $message);
|
||||
}
|
||||
|
||||
return $message;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if an attribute has a rule assigned to it.
|
||||
*
|
||||
* @param string $attribute
|
||||
* @param array $rules
|
||||
* @return bool
|
||||
*/
|
||||
protected function has_rule($attribute, $rules)
|
||||
{
|
||||
foreach ($this->rules[$attribute] as $rule)
|
||||
{
|
||||
list($rule, $parameters) = $this->parse($rule);
|
||||
|
||||
if (in_array($rule, $rules)) return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract the rule name and parameters from a rule.
|
||||
*
|
||||
* @param string $rule
|
||||
* @return array
|
||||
*/
|
||||
protected function parse($rule)
|
||||
{
|
||||
$parameters = (($colon = strpos($rule, ':')) !== false) ? explode(',', substr($rule, $colon + 1)) : array();
|
||||
|
||||
return array(is_numeric($colon) ? substr($rule, 0, $colon) : $rule, $parameters);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the language that should be used when retrieving error messages.
|
||||
*
|
||||
* @param string $language
|
||||
* @return Validator
|
||||
*/
|
||||
public function lang($language)
|
||||
{
|
||||
$this->language = $language;
|
||||
return $this;
|
||||
}
|
||||
|
||||
}
|
||||
253
laravel/vendor/phpass.php
vendored
Normal file
253
laravel/vendor/phpass.php
vendored
Normal file
@@ -0,0 +1,253 @@
|
||||
<?php
|
||||
#
|
||||
# Portable PHP password hashing framework.
|
||||
#
|
||||
# Version 0.3 / genuine.
|
||||
#
|
||||
# Written by Solar Designer <solar at openwall.com> in 2004-2006 and placed in
|
||||
# the public domain. Revised in subsequent years, still public domain.
|
||||
#
|
||||
# There's absolutely no warranty.
|
||||
#
|
||||
# The homepage URL for this framework is:
|
||||
#
|
||||
# http://www.openwall.com/phpass/
|
||||
#
|
||||
# Please be sure to update the Version line if you edit this file in any way.
|
||||
# It is suggested that you leave the main version number intact, but indicate
|
||||
# your project name (after the slash) and add your own revision information.
|
||||
#
|
||||
# Please do not change the "private" password hashing method implemented in
|
||||
# here, thereby making your hashes incompatible. However, if you must, please
|
||||
# change the hash type identifier (the "$P$") to something different.
|
||||
#
|
||||
# Obviously, since this code is in the public domain, the above are not
|
||||
# requirements (there can be none), but merely suggestions.
|
||||
#
|
||||
class PasswordHash {
|
||||
var $itoa64;
|
||||
var $iteration_count_log2;
|
||||
var $portable_hashes;
|
||||
var $random_state;
|
||||
|
||||
function PasswordHash($iteration_count_log2, $portable_hashes)
|
||||
{
|
||||
$this->itoa64 = './0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz';
|
||||
|
||||
if ($iteration_count_log2 < 4 || $iteration_count_log2 > 31)
|
||||
$iteration_count_log2 = 8;
|
||||
$this->iteration_count_log2 = $iteration_count_log2;
|
||||
|
||||
$this->portable_hashes = $portable_hashes;
|
||||
|
||||
$this->random_state = microtime();
|
||||
if (function_exists('getmypid'))
|
||||
$this->random_state .= getmypid();
|
||||
}
|
||||
|
||||
function get_random_bytes($count)
|
||||
{
|
||||
$output = '';
|
||||
if (is_readable('/dev/urandom') &&
|
||||
($fh = @fopen('/dev/urandom', 'rb'))) {
|
||||
$output = fread($fh, $count);
|
||||
fclose($fh);
|
||||
}
|
||||
|
||||
if (strlen($output) < $count) {
|
||||
$output = '';
|
||||
for ($i = 0; $i < $count; $i += 16) {
|
||||
$this->random_state =
|
||||
md5(microtime() . $this->random_state);
|
||||
$output .=
|
||||
pack('H*', md5($this->random_state));
|
||||
}
|
||||
$output = substr($output, 0, $count);
|
||||
}
|
||||
|
||||
return $output;
|
||||
}
|
||||
|
||||
function encode64($input, $count)
|
||||
{
|
||||
$output = '';
|
||||
$i = 0;
|
||||
do {
|
||||
$value = ord($input[$i++]);
|
||||
$output .= $this->itoa64[$value & 0x3f];
|
||||
if ($i < $count)
|
||||
$value |= ord($input[$i]) << 8;
|
||||
$output .= $this->itoa64[($value >> 6) & 0x3f];
|
||||
if ($i++ >= $count)
|
||||
break;
|
||||
if ($i < $count)
|
||||
$value |= ord($input[$i]) << 16;
|
||||
$output .= $this->itoa64[($value >> 12) & 0x3f];
|
||||
if ($i++ >= $count)
|
||||
break;
|
||||
$output .= $this->itoa64[($value >> 18) & 0x3f];
|
||||
} while ($i < $count);
|
||||
|
||||
return $output;
|
||||
}
|
||||
|
||||
function gensalt_private($input)
|
||||
{
|
||||
$output = '$P$';
|
||||
$output .= $this->itoa64[min($this->iteration_count_log2 +
|
||||
((PHP_VERSION >= '5') ? 5 : 3), 30)];
|
||||
$output .= $this->encode64($input, 6);
|
||||
|
||||
return $output;
|
||||
}
|
||||
|
||||
function crypt_private($password, $setting)
|
||||
{
|
||||
$output = '*0';
|
||||
if (substr($setting, 0, 2) == $output)
|
||||
$output = '*1';
|
||||
|
||||
$id = substr($setting, 0, 3);
|
||||
# We use "$P$", phpBB3 uses "$H$" for the same thing
|
||||
if ($id != '$P$' && $id != '$H$')
|
||||
return $output;
|
||||
|
||||
$count_log2 = strpos($this->itoa64, $setting[3]);
|
||||
if ($count_log2 < 7 || $count_log2 > 30)
|
||||
return $output;
|
||||
|
||||
$count = 1 << $count_log2;
|
||||
|
||||
$salt = substr($setting, 4, 8);
|
||||
if (strlen($salt) != 8)
|
||||
return $output;
|
||||
|
||||
# We're kind of forced to use MD5 here since it's the only
|
||||
# cryptographic primitive available in all versions of PHP
|
||||
# currently in use. To implement our own low-level crypto
|
||||
# in PHP would result in much worse performance and
|
||||
# consequently in lower iteration counts and hashes that are
|
||||
# quicker to crack (by non-PHP code).
|
||||
if (PHP_VERSION >= '5') {
|
||||
$hash = md5($salt . $password, TRUE);
|
||||
do {
|
||||
$hash = md5($hash . $password, TRUE);
|
||||
} while (--$count);
|
||||
} else {
|
||||
$hash = pack('H*', md5($salt . $password));
|
||||
do {
|
||||
$hash = pack('H*', md5($hash . $password));
|
||||
} while (--$count);
|
||||
}
|
||||
|
||||
$output = substr($setting, 0, 12);
|
||||
$output .= $this->encode64($hash, 16);
|
||||
|
||||
return $output;
|
||||
}
|
||||
|
||||
function gensalt_extended($input)
|
||||
{
|
||||
$count_log2 = min($this->iteration_count_log2 + 8, 24);
|
||||
# This should be odd to not reveal weak DES keys, and the
|
||||
# maximum valid value is (2**24 - 1) which is odd anyway.
|
||||
$count = (1 << $count_log2) - 1;
|
||||
|
||||
$output = '_';
|
||||
$output .= $this->itoa64[$count & 0x3f];
|
||||
$output .= $this->itoa64[($count >> 6) & 0x3f];
|
||||
$output .= $this->itoa64[($count >> 12) & 0x3f];
|
||||
$output .= $this->itoa64[($count >> 18) & 0x3f];
|
||||
|
||||
$output .= $this->encode64($input, 3);
|
||||
|
||||
return $output;
|
||||
}
|
||||
|
||||
function gensalt_blowfish($input)
|
||||
{
|
||||
# This one needs to use a different order of characters and a
|
||||
# different encoding scheme from the one in encode64() above.
|
||||
# We care because the last character in our encoded string will
|
||||
# only represent 2 bits. While two known implementations of
|
||||
# bcrypt will happily accept and correct a salt string which
|
||||
# has the 4 unused bits set to non-zero, we do not want to take
|
||||
# chances and we also do not want to waste an additional byte
|
||||
# of entropy.
|
||||
$itoa64 = './ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
|
||||
|
||||
$output = '$2a$';
|
||||
$output .= chr(ord('0') + $this->iteration_count_log2 / 10);
|
||||
$output .= chr(ord('0') + $this->iteration_count_log2 % 10);
|
||||
$output .= '$';
|
||||
|
||||
$i = 0;
|
||||
do {
|
||||
$c1 = ord($input[$i++]);
|
||||
$output .= $itoa64[$c1 >> 2];
|
||||
$c1 = ($c1 & 0x03) << 4;
|
||||
if ($i >= 16) {
|
||||
$output .= $itoa64[$c1];
|
||||
break;
|
||||
}
|
||||
|
||||
$c2 = ord($input[$i++]);
|
||||
$c1 |= $c2 >> 4;
|
||||
$output .= $itoa64[$c1];
|
||||
$c1 = ($c2 & 0x0f) << 2;
|
||||
|
||||
$c2 = ord($input[$i++]);
|
||||
$c1 |= $c2 >> 6;
|
||||
$output .= $itoa64[$c1];
|
||||
$output .= $itoa64[$c2 & 0x3f];
|
||||
} while (1);
|
||||
|
||||
return $output;
|
||||
}
|
||||
|
||||
function HashPassword($password)
|
||||
{
|
||||
$random = '';
|
||||
|
||||
if (CRYPT_BLOWFISH == 1 && !$this->portable_hashes) {
|
||||
$random = $this->get_random_bytes(16);
|
||||
$hash =
|
||||
crypt($password, $this->gensalt_blowfish($random));
|
||||
if (strlen($hash) == 60)
|
||||
return $hash;
|
||||
}
|
||||
|
||||
if (CRYPT_EXT_DES == 1 && !$this->portable_hashes) {
|
||||
if (strlen($random) < 3)
|
||||
$random = $this->get_random_bytes(3);
|
||||
$hash =
|
||||
crypt($password, $this->gensalt_extended($random));
|
||||
if (strlen($hash) == 20)
|
||||
return $hash;
|
||||
}
|
||||
|
||||
if (strlen($random) < 6)
|
||||
$random = $this->get_random_bytes(6);
|
||||
$hash =
|
||||
$this->crypt_private($password,
|
||||
$this->gensalt_private($random));
|
||||
if (strlen($hash) == 34)
|
||||
return $hash;
|
||||
|
||||
# Returning '*' on error is safe here, but would _not_ be safe
|
||||
# in a crypt(3)-like function used _both_ for generating new
|
||||
# hashes and for validating passwords against existing hashes.
|
||||
return '*';
|
||||
}
|
||||
|
||||
function CheckPassword($password, $stored_hash)
|
||||
{
|
||||
$hash = $this->crypt_private($password, $stored_hash);
|
||||
if ($hash[0] == '*')
|
||||
$hash = crypt($password, $stored_hash);
|
||||
|
||||
return $hash == $stored_hash;
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
245
laravel/view.php
Normal file
245
laravel/view.php
Normal file
@@ -0,0 +1,245 @@
|
||||
<?php namespace Laravel;
|
||||
|
||||
class View {
|
||||
|
||||
/**
|
||||
* The name of the view.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $view;
|
||||
|
||||
/**
|
||||
* The view data.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public $data = array();
|
||||
|
||||
/**
|
||||
* The module that contains the view.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $module;
|
||||
|
||||
/**
|
||||
* The path to the view.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $path;
|
||||
|
||||
/**
|
||||
* The defined view composers.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $composers;
|
||||
|
||||
/**
|
||||
* Create a new view instance.
|
||||
*
|
||||
* @param string $view
|
||||
* @param array $data
|
||||
* @return void
|
||||
*/
|
||||
public function __construct($view, $data = array())
|
||||
{
|
||||
$this->data = $data;
|
||||
|
||||
list($this->module, $this->path, $this->view) = static::parse($view);
|
||||
|
||||
$this->compose();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new view instance.
|
||||
*
|
||||
* @param string $view
|
||||
* @param array $data
|
||||
* @return View
|
||||
*/
|
||||
public static function make($view, $data = array())
|
||||
{
|
||||
return new static($view, $data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new view instance from a view name.
|
||||
*
|
||||
* The view names for the active module will be searched first, followed by the view names
|
||||
* for the default module. Finally, the names for all modules will be searched.
|
||||
*
|
||||
* @param string $name
|
||||
* @param array $data
|
||||
* @return View
|
||||
*/
|
||||
protected static function of($name, $data = array())
|
||||
{
|
||||
foreach (array_unique(array_merge(array(ACTIVE_MODULE, DEFAULT_MODULE), Module::$modules)) as $module)
|
||||
{
|
||||
static::load_composers($module);
|
||||
|
||||
foreach (static::$composers[$module] as $key => $value)
|
||||
{
|
||||
if ($name === $value or (isset($value['name']) and $name === $value['name']))
|
||||
{
|
||||
return new static($key, $data);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
throw new \Exception("Named view [$name] is not defined.");
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse a view identifier and get the module, path, and view name.
|
||||
*
|
||||
* @param string $view
|
||||
* @return array
|
||||
*/
|
||||
protected static function parse($view)
|
||||
{
|
||||
list($module, $view) = Module::parse($view);
|
||||
|
||||
return array($module, Module::path($module).'views/', $view);
|
||||
}
|
||||
|
||||
/**
|
||||
* Call the composer for the view instance.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function compose()
|
||||
{
|
||||
static::load_composers($this->module);
|
||||
|
||||
if (isset(static::$composers[$this->module][$this->view]))
|
||||
{
|
||||
foreach ((array) static::$composers[$this->module][$this->view] as $key => $value)
|
||||
{
|
||||
if (is_callable($value)) return call_user_func($value, $this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Load the view composers for a given module.
|
||||
*
|
||||
* @param string $module
|
||||
* @return void
|
||||
*/
|
||||
protected static function load_composers($module)
|
||||
{
|
||||
if (isset(static::$composers[$module])) return;
|
||||
|
||||
$composers = Module::path($module).'composers'.EXT;
|
||||
|
||||
static::$composers[$module] = (file_exists($composers)) ? require $composers : array();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the parsed content of the view.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function get()
|
||||
{
|
||||
$view = str_replace('.', '/', $this->view);
|
||||
|
||||
if ( ! file_exists($this->path.$view.EXT))
|
||||
{
|
||||
Exception\Handler::make(new Exception("View [$view] does not exist."))->handle();
|
||||
}
|
||||
|
||||
foreach ($this->data as &$data)
|
||||
{
|
||||
if ($data instanceof View or $data instanceof Response) $data = (string) $data;
|
||||
}
|
||||
|
||||
ob_start() and extract($this->data, EXTR_SKIP);
|
||||
|
||||
try { include $this->path.$view.EXT; } catch (\Exception $e) { Exception\Handler::make($e)->handle(); }
|
||||
|
||||
return ob_get_clean();
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a view instance to the view data.
|
||||
*
|
||||
* @param string $key
|
||||
* @param string $view
|
||||
* @param array $data
|
||||
* @return View
|
||||
*/
|
||||
public function partial($key, $view, $data = array())
|
||||
{
|
||||
return $this->bind($key, new static($view, $data));
|
||||
}
|
||||
|
||||
/**
|
||||
* 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;
|
||||
}
|
||||
|
||||
/**
|
||||
* Magic Method for handling the dynamic creation of named views.
|
||||
*/
|
||||
public static function __callStatic($method, $parameters)
|
||||
{
|
||||
if (strpos($method, 'of_') === 0)
|
||||
{
|
||||
return static::of(substr($method, 3), Arr::get($parameters, 0, array()));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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();
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user