various refactorings.

This commit is contained in:
Taylor Otwell 2011-11-02 21:27:43 -05:00
parent 128984facb
commit 9caf239f6b
29 changed files with 275 additions and 150 deletions

View File

@ -13,8 +13,8 @@
|
| 'home.index' => array('name' => 'home')
|
| Now, you can create an instance of that view using the expressive View::of
| dynamic method. Take a look at this example:
| Now, you can create an instance of that view using the very expressive
| View::of dynamic method. Take a look at this example:
|
| return View::of_home();
|

View File

@ -7,12 +7,12 @@
| Error Detail
|--------------------------------------------------------------------------
|
| Detailed error messages contain information about the file in which
| an error occurs, a stack trace, and a snapshot of the source code
| in which the error occured.
| Detailed error messages contain information about the file in which an
| error occurs, as well as a PHP stack trace containing the call stack.
|
| If your application is in production, consider turning off error details
| for enhanced security and user experience.
| for enhanced security and user experience. The error stack trace could
| contain sensitive information that should not be publicly visible.
|
*/
@ -23,9 +23,9 @@
| Error Logging
|--------------------------------------------------------------------------
|
| Error Logging will use the "logger" function defined below to log error
| messages, which gives you complete freedom to determine how error
| messages are logged. Enjoy the flexibility.
| When error logging is enabled, the "logger" Closure defined below will
| be called for every error in your application. You are free to log the
| errors however you want. Enjoy the flexibility.
|
*/
@ -37,23 +37,28 @@
|--------------------------------------------------------------------------
|
| Because of the various ways of managing error logging, you get complete
| flexibility in Laravel to manage error logging as you see fit.
| flexibility in Laravel to manage all error logging as you see fit.
|
| This function will be called when an error occurs in your application.
| You are free to handle the exception any way your heart desires.
|
| The error "severity" passed to the method is a human-readable severity
| level such as "Parsing Error" or "Fatal Error".
| You are free to handle the exception any way you want. The severity
| will be a human-readable severity level such as "Parsing Error".
|
*/
'handler' => function($exception, $severity, $message, $config)
{
if ($config['detail'])
{
$data = compact('exception', 'severity', 'message');
$data['detailed'] = $config['detail'];
$response = Response::view('error.exception', $data)->status(500);
}
else
{
$response = Response::error('500');
}
Response::error('500', $data)->send();
$response->send();
},
/*
@ -62,19 +67,21 @@
|--------------------------------------------------------------------------
|
| Because of the various ways of managing error logging, you get complete
| flexibility to manage error logging as you see fit.
| flexibility to manage error logging as you see fit. This function will
| be called anytime an error occurs within your application and error
| logging is enabled.
|
| This function will be called when an error occurs in your application
| and error loggins is enabled. You can log the error however you like.
|
| A simple logging system has been setup for you. By default, all errors
| will be logged to the storage/log.txt file.
| You may log the error message however you like; however, a simple logging
| solution has been setup for you which will log all error messages to a
| single text file within the application storage directory.
|
*/
'logger' => function($exception, $severity, $message, $config)
{
File::append(STORAGE_PATH.'log.txt', date('Y-m-d H:i:s').' '.$severity.' - '.$message.PHP_EOL);
$message = date('Y-m-d H:i:s').' '.$severity.' - '.$message.PHP_EOL;
File::append(STORAGE_PATH.'log.txt', $message);
}
);

View File

@ -50,19 +50,19 @@
'after' => function($response)
{
if (Config::get('session.driver') !== '') Input::flash();
Input::flash();
},
'auth' => function()
{
if ( ! Auth::check()) return Redirect::to_login();
if (Auth::guest()) return Redirect::to_login();
},
'csrf' => function()
{
if (Input::get('csrf_token') !== Form::raw_token()) return Response::error('500');
if (Request::forged()) return Response::error('500');
},
);

View File

@ -10,9 +10,9 @@
| Here is the public API of your application. To add functionality to your
| application, you just add to the array of routes located in this file.
|
| Simply tell Laravel the HTTP verbs and URIs it should respond to. It is a
| breeze to create beautiful applications using the simplicity and elegance
| of Laravel's RESTful routing.
| Simply tell Laravel the HTTP verbs and URIs it should respond to. It's a
| piece of cake to create beautiful applications using the elegant RESTful
| routing available in Laravel.
|
| Let's respond to a simple GET request to http://example.com/hello:
|

View File

@ -78,8 +78,8 @@
spl_autoload_register(array('Laravel\\Autoloader', 'load'));
/**
* Define a few convenient functions to make our lives as
* developers a little more easy and enjoyable.
* Define a few global convenience functions to make our lives
* as Laravel PHP developers a little more easy and enjoyable.
*/
function e($value)
{

View File

@ -39,16 +39,9 @@
E_STRICT => 'Runtime Notice',
);
if (array_key_exists($e->getCode(), $levels))
{
$level = $levels[$e->getCode()];
}
else
{
$level = $e->getCode();
}
$code = $e->getCode();
return $level;
return (array_key_exists($code, $levels)) ? $levels[$code] : $code;
};
/**

View File

@ -39,7 +39,10 @@ public function has($key)
*/
protected function retrieve($key)
{
if ( ! is_null($cache = apc_fetch($this->key.$key))) return $cache;
if ( ! is_null($cache = apc_fetch($this->key.$key)))
{
return $cache;
}
}
/**

View File

@ -47,7 +47,10 @@ public function has($key)
*/
protected function retrieve($key)
{
if (($cache = $this->memcache->get($this->key.$key)) !== false) return $cache;
if (($cache = $this->memcache->get($this->key.$key)) !== false)
{
return $cache;
}
}
/**

View File

@ -32,12 +32,12 @@ public static function driver($driver = null)
if ( ! array_key_exists($driver, static::$drivers))
{
if ( ! IoC::container()->registered('laravel.cache.'.$driver))
if ( ! IoC::container()->registered("laravel.cache.{$driver}"))
{
throw new \Exception("Cache driver [$driver] is not supported.");
}
return static::$drivers[$driver] = IoC::container()->core('cache.'.$driver);
return static::$drivers[$driver] = IoC::container()->core("cache.{$driver}");
}
return static::$drivers[$driver];

View File

@ -2,6 +2,12 @@
return array(
'laravel.view.composers' => array('singleton' => true, 'resolver' => function()
{
return require APP_PATH.'composers'.EXT;
}),
'laravel.routing.router' => array('singleton' => true, 'resolver' => function($c)
{
return new Routing\Router($c->core('routing.loader'), CONTROLLER_PATH);

View File

@ -2,20 +2,6 @@
class Connection {
/**
* The connection configuration array.
*
* @var array
*/
protected $config;
/**
* The query grammar instance for the connection.
*
* @var Grammars\Grammar
*/
protected $grammar;
/**
* The raw PDO connection instance.
*
@ -30,6 +16,20 @@ class Connection {
*/
public $queries = array();
/**
* The connection configuration array.
*
* @var array
*/
protected $config;
/**
* The query grammar instance for the connection.
*
* @var Grammars\Grammar
*/
protected $grammar;
/**
* Create a new database connection instance.
*
@ -112,7 +112,10 @@ public function only($sql, $bindings = array())
*/
public function first($sql, $bindings = array())
{
if (count($results = $this->query($sql, $bindings)) > 0) return $results[0];
if (count($results = $this->query($sql, $bindings)) > 0)
{
return $results[0];
}
}
/**
@ -144,7 +147,7 @@ public function query($sql, $bindings = array())
if ($value instanceof Expression) unset($bindings[$key]);
}
$sql = $this->transform(trim($sql), $bindings);
$sql = $this->transform($sql, $bindings);
$this->queries[] = compact('sql', 'bindings');
@ -164,8 +167,8 @@ public function query($sql, $bindings = array())
*/
protected function transform($sql, $bindings)
{
if (strpos($sql, '(...)') === false) return $sql;
if (strpos($sql, '(...)') !== false)
{
for ($i = 0; $i < count($bindings); $i++)
{
// If the binding is an array, we can assume it is being used to fill
@ -179,8 +182,9 @@ protected function transform($sql, $bindings)
$sql = preg_replace('~\(\.\.\.\)~', "({$parameters})", $sql, 1);
}
}
}
return $sql;
return trim($sql);
}
/**
@ -204,9 +208,11 @@ protected function execute(PDOStatement $statement, $bindings)
{
return $statement->rowCount();
}
else
{
return $result;
}
}
/**
* Get the driver name for the database connection.

View File

@ -30,6 +30,10 @@ public function connect($config)
{
$options = $this->options($config);
// SQLite provides supported for "in-memory" databases, which exist only for the
// lifetime of the request. Any given in-memory database may only have one PDO
// connection open to it at a time. Generally, these databases are use for
// testing and development purposes, not in production scenarios.
if ($config['database'] == ':memory:')
{
return new PDO('sqlite::memory:', null, null, $options);

View File

@ -84,7 +84,9 @@ protected function selects(Query $query)
*/
protected function aggregate(Query $query)
{
return 'SELECT '.$query->aggregate['aggregator'].'('.$this->wrap($query->aggregate['column']).')';
$column = $this->wrap($query->aggregate['column']);
return 'SELECT '.$query->aggregate['aggregator'].'('.$column.')';
}
/**
@ -332,7 +334,7 @@ public function delete(Query $query)
* @param array $columns
* @return string
*/
public function columnize($columns)
final public function columnize($columns)
{
return implode(', ', array_map(array($this, 'wrap'), $columns));
}
@ -349,16 +351,29 @@ public function columnize($columns)
*/
public function wrap($value)
{
if (strpos(strtolower($value), ' as ') !== false) return $this->alias($value);
// If the value being wrapped contains a column alias, we need to wrap
// it a little differently since each segment must be wrapped and not
// the entire string.
if (strpos(strtolower($value), ' as ') !== false)
{
return $this->alias($value);
}
// Expressions should be injected into the query as raw strings, so we
// do not want to wrap them in any way. We will just return the string
// value from the expression.
// value from the expression to be included in the query.
if ($value instanceof Expression) return $value->get();
foreach (explode('.', $value) as $segment)
{
$wrapped[] = ($segment !== '*') ? $this->wrapper.$segment.$this->wrapper : $segment;
if ($segment === '*')
{
$wrapped[] = $segment;
}
else
{
$wrapped[] = $this->wrapper.$segment.$this->wrapper;
}
}
return implode('.', $wrapped);

View File

@ -55,6 +55,11 @@ public static function connection($connection = null)
*/
protected static function connect($config)
{
// We allow the developer to place a "connector" option in the database
// configuration, which should have a Closure value. If the connector
// is present, we will use the Closure to retrieve the PDO connection
// to the database. This allows the flexiblity to connect to database
// systems that are not officially supported by the the framework.
if (isset($config['connector']))
{
return call_user_func($config['connector'], $config);

View File

@ -144,22 +144,7 @@ public static function close()
*/
public static function token()
{
return static::input('hidden', 'csrf_token', static::raw_token());
}
/**
* Get the CSRF token for the current session.
*
* @return string
*/
public static function raw_token()
{
if (Config::get('session.driver') == '')
{
throw new \Exception("A session driver must be specified before using CSRF tokens.");
}
return Session::get('csrf_token');
return static::input('hidden', 'csrf_token', Session::token());
}
/**

View File

@ -69,9 +69,12 @@ public static function get($key = null, $default = null)
* @return void
*/
public static function flash()
{
if (Config::$items['session']['driver'] !== '')
{
Session::flash(Input::old_input, static::get());
}
}
/**
* Determine if the old input data contains an item.

View File

@ -74,7 +74,7 @@
/**
* The spoofed request method is removed from the input so it is
* not unexpectedly included in Input::all() or Input::get().s
* not unexpectedly included in Input::all() or Input::get().
*/
unset($input[Request::spoofer]);

View File

@ -145,6 +145,18 @@ public static function secure()
return isset($_SERVER['HTTPS']) and strtolower($_SERVER['HTTPS']) !== 'off';
}
/**
* Determine if the request has been forged.
*
* The session CSRF token will be compared to the CSRF token in the request input.
*
* @return bool
*/
public static function forged()
{
return Input::get('csrf_token') !== Session::token();
}
/**
* Determine if the current request is an AJAX request.
*

View File

@ -258,7 +258,9 @@ public function headers()
{
if ( ! isset($this->headers['Content-Type']))
{
$this->header('Content-Type', 'text/html; charset='.Config::$items['application']['encoding']);
$encoding = Config::$items['application']['encoding'];
$this->header('Content-Type', "text/html; charset={$encoding}");
}
header(Request::protocol().' '.$this->status.' '.$this->statuses[$this->status]);

View File

@ -29,7 +29,19 @@ class Auth {
const remember_key = 'laravel_remember';
/**
* Determine if the current user of the application is authenticated.
* Determine if the user of the application is not logged in.
*
* This method is the inverse of the "check" method.
*
* @return bool
*/
public static function guest()
{
return ! static::check();
}
/**
* Determine if the user of the application is logged in.
*
* @return bool
*/

View File

@ -43,17 +43,19 @@ public static function check($value, $hash)
/**
* Get a salt for use during Bcrypt hashing.
*
* Bcrypt expects salts to be 22 alpha-numeric characters including
* dots and forward slashes. OpenSSL will be used if available and
* the Str::random method will be used if it isn't.
*
* @return string
*/
protected static function salt()
{
// Bcrypt expects the salt to be 22 base64 encoded characters, including dots
// and slashes. We will get rid of the plus signs included in the base64 data
// and replace them with dots. OpenSSL will be used if available, since it is
// more random, otherwise we will fallback on Str::random.
if (function_exists('openssl_random_pseudo_bytes'))
{
return substr(strtr(base64_encode(openssl_random_pseudo_bytes(16)), '+', '.'), 0 , 22);
$bytes = openssl_random_pseudo_bytes(16);
return substr(strtr(base64_encode($bytes), '+', '.'), 0 , 22);
}
return substr(str_replace('+', '.', base64_encode(Str::random(40))), 0, 22);

View File

@ -182,6 +182,16 @@ public static function regenerate()
static::$exists = false;
}
/**
* Get the CSRF token that is stored in the session data.
*
* @return string
*/
public static function token()
{
return static::get('csrf_token');
}
/**
* Store the session payload in storage.
*
@ -196,9 +206,6 @@ public static function save(Driver $driver)
$config = Config::$items['session'];
// To keep the session persistence code clean, session drivers are
// responsible for the storage of the session array to the various
// available persistent storage mechanisms.
$driver->save(static::$session, $config, static::$exists);
static::cookie();

View File

@ -24,13 +24,6 @@ public function __construct($messages = array())
/**
* Add a message to the collector.
*
* Duplicate messages will not be added.
*
* <code>
* // Add a message to the collector for the "email" attribute
* $messages->add('email', 'The e-mail address is invalid.');
* </code>
*
* @param string $key
* @param string $message
* @return void

View File

@ -2,8 +2,8 @@
use Closure;
use Laravel\Arr;
use Laravel\IoC;
use Laravel\Str;
use Laravel\File;
use Laravel\Lang;
use Laravel\Input;
use Laravel\Database\Manager as DB;
@ -200,7 +200,9 @@ protected function validatable($rule, $attribute, $value)
*/
protected function error($attribute, $rule, $parameters)
{
$message = $this->replace($this->message($attribute, $rule), $attribute, $rule, $parameters);
$message = $this->message($attribute, $rule);
$message = $this->replace($message, $attribute, $rule, $parameters);
$this->errors->add($attribute, $message);
}
@ -226,9 +228,11 @@ protected function validate_required($attribute, $value)
*/
protected function validate_confirmed($attribute, $value)
{
$confirmation = $this->attributes[$attribute.'_confirmation'];
$confirmed = $attribute.'_confirmation';
return array_key_exists($attribute.'_confirmation', $this->attributes) and $value == $confirmation;
$confirmation = $this->attributes[$confirmed];
return array_key_exists($confirmed, $this->attributes) and $value == $confirmation;
}
/**
@ -493,7 +497,10 @@ protected function validate_mimes($attribute, $parameters)
{
foreach ($parameters as $extension)
{
if (File::is($extension, $this->attributes[$attribute]['tmp_name'])) return true;
if (File::is($extension, $this->attributes[$attribute]['tmp_name']))
{
return true;
}
}
return false;
@ -527,7 +534,7 @@ protected function message($attribute, $rule)
// If the rule being validated is a "size" rule and the attribute is not
// a number, we will need to gather the specific size message for the
// type of attribute being validated, either a file or a string.
elseif (in_array($rule, $this->size_rules) and ! $this->has_rule($attribute, $this->numeric_rules))
elseif (isset($this->size_rules[$rule]) and ! $this->has_rule($attribute, $this->numeric_rules))
{
$line = (array_key_exists($attribute, Input::file())) ? "file" : "string";
@ -560,7 +567,7 @@ protected function replace($message, $attribute, $rule, $parameters)
{
// Even though every size rule will not have a place-holder for min,
// max, and size, we will go ahead and make replacements for all of
// them just for convenience. Except for "between" every replacement
// them just for convenience. Except for "between", every replacement
// should be the first parameter.
$max = ($rule == 'between') ? $parameters[1] : $parameters[0];

View File

@ -1,4 +1,7 @@
<?php namespace Laravel; use Closure;
<?php namespace Laravel;
use Closure;
use Laravel\Validation\Messages;
class View {
@ -42,6 +45,20 @@ public function __construct($view, $data = array())
$this->view = $view;
$this->data = $data;
$this->path = $this->path($view);
// If a session driver has been specified, we will bind an instance of
// the validation error message container to every view. If an errors
// instance exists in the session, we will use that instance.
//
// This makes the implementation of the Post/Redirect/Get pattern very
// convenient since each view can assume it has a message container.
if (Config::$items['session']['driver'] !== '')
{
$this->data['errors'] = Session::get('errors', function()
{
return new Messages;
});
}
}
/**
@ -117,7 +134,10 @@ public static function make($view, $data = array())
*/
public static function of($name, $data = array())
{
if ( ! is_null($view = static::name($name))) return static::make($view, $data);
if ( ! is_null($view = static::name($name)))
{
return static::make($view, $data);
}
throw new \Exception("Named view [$name] is not defined.");
}
@ -134,11 +154,11 @@ public static function of($name, $data = array())
*/
protected static function name($name)
{
if (is_null(static::$composers)) static::$composers = require APP_PATH.'composers'.EXT;
static::composers();
foreach (static::$composers as $key => $value)
{
if ($name === $value or (is_array($value) and $name === Arr::get($value, 'name')))
if ($name === $value or $name === Arr::get((array) $value, 'name'))
{
return $key;
}
@ -153,7 +173,7 @@ protected static function name($name)
*/
protected static function compose(View $view)
{
if (is_null(static::$composers)) static::$composers = require APP_PATH.'composers'.EXT;
static::composers();
if (isset(static::$composers[$view->view]))
{
@ -164,6 +184,18 @@ protected static function compose(View $view)
}
}
/**
* Load the view composers for the application.
*
* For better testing flexiblity, we load the composers from the IoC container.
*
* @return void
*/
protected static function composers()
{
static::$composers = IoC::container()->core('view.composers');
}
/**
* Get the evaluated string content of the view.
*

View File

@ -22,8 +22,9 @@
<h3>What does this mean?</h3>
<p>
We couldn't find the page you requested on our servers. We're really sorry about that.
It's our fault, not yours. We'll work hard to get this page back online as soon as possible.
We couldn't find the page you requested on our servers. We're really sorry
about that. It's our fault, not yours. We'll work hard to get this page
back online as soon as possible.
</p>
<p>

View File

@ -30,24 +30,6 @@
<p>
Perhaps you would like to go to our <?php echo HTML::link('/', 'home page'); ?>?
</p>
<?php if (isset($detailed) and $detailed): ?>
<h3>Error Message:</h3>
<pre style="word-wrap: break-word;"><?php echo $message; ?></pre>
<h3>Stack Trace:</h3>
<?php
$search = array(APP_PATH, SYS_PATH);
$replace = array('APP_PATH/', 'SYS_PATH/');
$trace = str_replace($search, $replace, $exception->getTraceAsString());
?>
<pre style="word-wrap: break-word;"><?php echo $trace; ?></pre>
<?php endif; ?>
</div>
</body>
</html>

View File

@ -0,0 +1,41 @@
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title><?php echo $severity; ?></title>
<style>
<?php echo file_get_contents(PUBLIC_PATH.'css/laravel.css'); ?>
</style>
<style>
pre {
word-wrap: break-word;
}
</style>
</head>
<body>
<div id="main">
<img src="http://laravel.com/img/splash/error.png" class="marker">
<h1><?php echo $severity; ?></h1>
<h3>Error Message:</h3>
<pre><?php echo $message; ?></pre>
<h3>Stack Trace:</h3>
<?php
$search = array(APP_PATH, SYS_PATH);
$replace = array('APP_PATH/', 'SYS_PATH/');
$trace = str_replace($search, $replace, $exception->getTraceAsString());
?>
<pre style="word-wrap: break-word;"><?php echo $trace; ?></pre>
</div>
</body>
</html>

View File

@ -8,6 +8,8 @@
* @link http://laravel.com
*/
define('LARAVEL_START', microtime(true));
// --------------------------------------------------------------
// The path to the application directory.
// --------------------------------------------------------------
@ -27,3 +29,5 @@
// Launch Laravel.
// --------------------------------------------------------------
require $laravel.'/laravel.php';
echo (microtime(true) - LARAVEL_START) * 1000;