Commit aa27df8b authored by Colin Viebrock's avatar Colin Viebrock

Merge remote-tracking branch 'laravel/develop' into develop

Conflicts:
	laravel/form.php
parents 8f103cde 2fe7cfd9
...@@ -113,7 +113,11 @@ return array( ...@@ -113,7 +113,11 @@ return array(
'redis' => array( 'redis' => array(
'default' => array('host' => '127.0.0.1', 'port' => 6379), 'default' => array(
'host' => '127.0.0.1',
'port' => 6379,
'database' => 0
),
), ),
......
...@@ -36,6 +36,7 @@ return array( ...@@ -36,6 +36,7 @@ return array(
"in" => "The selected :attribute is invalid.", "in" => "The selected :attribute is invalid.",
"integer" => "The :attribute must be an integer.", "integer" => "The :attribute must be an integer.",
"ip" => "The :attribute must be a valid IP address.", "ip" => "The :attribute must be a valid IP address.",
"match" => "The :attribute format is invalid.",
"max" => array( "max" => array(
"numeric" => "The :attribute must be less than :max.", "numeric" => "The :attribute must be less than :max.",
"file" => "The :attribute must be less than :max kilobytes.", "file" => "The :attribute must be less than :max kilobytes.",
......
...@@ -21,3 +21,7 @@ Changes for 3.1: ...@@ -21,3 +21,7 @@ Changes for 3.1:
- Added Cache::forever method. - Added Cache::forever method.
- Controller layouts now resolved in Laravel\Controller __construct. - Controller layouts now resolved in Laravel\Controller __construct.
- Rewrote Eloquent and included in core. - Rewrote Eloquent and included in core.
- Added "match" validation rule.
- Fixed table prefix bug.
- Added Form::macro method.
- Added Route::forward method.
\ No newline at end of file
...@@ -154,9 +154,9 @@ class Migrator extends Task { ...@@ -154,9 +154,9 @@ class Migrator extends Task {
// the bundle name and string migration name as an unique ID // the bundle name and string migration name as an unique ID
// for the migrations, allowing us to easily identify which // for the migrations, allowing us to easily identify which
// migrations have been run for each bundle. // migrations have been run for each bundle.
$table->string('bundle'); $table->string('bundle', 50);
$table->string('name'); $table->string('name', 200);
// When running a migration command, we will store a batch // When running a migration command, we will store a batch
// ID with each of the rows on the table. This will allow // ID with each of the rows on the table. This will allow
......
...@@ -89,21 +89,34 @@ abstract class Grammar { ...@@ -89,21 +89,34 @@ abstract class Grammar {
// Since columns may be prefixed with their corresponding table // Since columns may be prefixed with their corresponding table
// name so as to not make them ambiguous, we will need to wrap // name so as to not make them ambiguous, we will need to wrap
// the table and the column in keyword identifiers. // the table and the column in keyword identifiers.
foreach (explode('.', $value) as $segment) $segments = explode('.', $value);
foreach ($segments as $key => $value)
{ {
if ($segment == '*') if ($key == 0 and count($segments) > 1)
{ {
$wrapped[] = $segment; $wrapped[] = $this->wrap_table($value);
} }
else else
{ {
$wrapped[] = sprintf($this->wrapper, $segment); $wrapped[] = $this->wrap_value($value);
} }
} }
return implode('.', $wrapped); return implode('.', $wrapped);
} }
/**
* Wrap a single string value in keyword identifiers.
*
* @param string $value
* @return string
*/
protected function wrap_value($value)
{
return ($value !== '*') ? sprintf($this->wrapper, $value) : $value;
}
/** /**
* Create query parameters from an array of values. * Create query parameters from an array of values.
* *
......
...@@ -182,7 +182,7 @@ class Query { ...@@ -182,7 +182,7 @@ class Query {
* @param string $column2 * @param string $column2
* @return Query * @return Query
*/ */
public function left_join($table, $column1, $operator, $column2) public function left_join($table, $column1, $operator = null, $column2 = null)
{ {
return $this->join($table, $column1, $operator, $column2, 'LEFT'); return $this->join($table, $column1, $operator, $column2, 'LEFT');
} }
......
...@@ -32,7 +32,22 @@ abstract class Grammar extends \Laravel\Database\Grammar { ...@@ -32,7 +32,22 @@ abstract class Grammar extends \Laravel\Database\Grammar {
$sql = "ALTER TABLE $table ADD CONSTRAINT $name "; $sql = "ALTER TABLE $table ADD CONSTRAINT $name ";
return $sql .= "FOREIGN KEY ($foreign) REFERENCES $on ($referenced)"; $sql .= "FOREIGN KEY ($foreign) REFERENCES $on ($referenced)";
// Finally we will check for any "on delete" or "on update" options for
// the foreign key. These control the behavior of the constraint when
// an update or delete statement is run against the record.
if ( ! is_null($command->on_delete))
{
$sql .= " ON DELETE {$command->on_delete}";
}
if ( ! is_null($command->on_update))
{
$sql .= " ON UPDATE {$command->on_update}";
}
return $sql;
} }
/** /**
......
...@@ -68,6 +68,30 @@ class File { ...@@ -68,6 +68,30 @@ class File {
if (static::exists($path)) @unlink($path); if (static::exists($path)) @unlink($path);
} }
/**
* Move a file to a new location.
*
* @param string $path
* @param string $target
* @return void
*/
public static function move($path, $target)
{
return rename($path, $target);
}
/**
* Copy a file to a new location.
*
* @param string $path
* @param string $target
* @return void
*/
public static function copy($path, $target)
{
return copy($path, $target);
}
/** /**
* Extract the file extension from a file path. * Extract the file extension from a file path.
* *
...@@ -173,6 +197,18 @@ class File { ...@@ -173,6 +197,18 @@ class File {
return false; return false;
} }
/**
* Create a new directory.
*
* @param string $path
* @param int $chmod
* @return void
*/
public static function mkdir($path, $chmod = 0777)
{
return ( ! is_dir($path)) ? mkdir($path, $chmod, true) : true;
}
/** /**
* Move a directory from one location to another. * Move a directory from one location to another.
* *
...@@ -183,7 +219,7 @@ class File { ...@@ -183,7 +219,7 @@ class File {
*/ */
public static function mvdir($source, $destination, $options = fIterator::SKIP_DOTS) public static function mvdir($source, $destination, $options = fIterator::SKIP_DOTS)
{ {
static::cpdir($source, $destination, true, $options); return static::cpdir($source, $destination, true, $options);
} }
/** /**
...@@ -197,7 +233,7 @@ class File { ...@@ -197,7 +233,7 @@ class File {
*/ */
public static function cpdir($source, $destination, $delete = false, $options = fIterator::SKIP_DOTS) public static function cpdir($source, $destination, $delete = false, $options = fIterator::SKIP_DOTS)
{ {
if ( ! is_dir($source)) return; if ( ! is_dir($source)) return false;
// First we need to create the destination directory if it doesn't // First we need to create the destination directory if it doesn't
// already exists. This directory hosts all of the assets we copy // already exists. This directory hosts all of the assets we copy
...@@ -221,7 +257,7 @@ class File { ...@@ -221,7 +257,7 @@ class File {
{ {
$path = $item->getRealPath(); $path = $item->getRealPath();
static::cpdir($path, $location, $delete, $options); if (! static::cpdir($path, $location, $delete, $options)) return false;
if ($delete) @rmdir($item->getRealPath()); if ($delete) @rmdir($item->getRealPath());
} }
...@@ -231,22 +267,25 @@ class File { ...@@ -231,22 +267,25 @@ class File {
// files with the same name. // files with the same name.
else else
{ {
copy($item->getRealPath(), $location); if(! copy($item->getRealPath(), $location)) return false;
if ($delete) @unlink($item->getRealPath()); if ($delete) @unlink($item->getRealPath());
} }
} }
if ($delete) rmdir($source); if ($delete) rmdir($source);
return true;
} }
/** /**
* Recursively delete a directory. * Recursively delete a directory.
* *
* @param string $directory * @param string $directory
* @param bool $preserve
* @return void * @return void
*/ */
public static function rmdir($directory) public static function rmdir($directory, $preserve = false)
{ {
if ( ! is_dir($directory)) return; if ( ! is_dir($directory)) return;
...@@ -267,7 +306,18 @@ class File { ...@@ -267,7 +306,18 @@ class File {
} }
} }
@rmdir($directory); if ( ! $preserve) @rmdir($directory);
}
/**
* Empty the specified directory of all files and folders.
*
* @param string $directory
* @return void
*/
public static function cleandir($directory)
{
return static::rmdir($directory, true);
} }
/** /**
......
...@@ -7,7 +7,26 @@ class Form { ...@@ -7,7 +7,26 @@ class Form {
* *
* @var array * @var array
*/ */
protected static $labels = array(); public static $labels = array();
/**
* The registered custom macros.
*
* @var array
*/
public static $macros = array();
/**
* Registers a custom macro.
*
* @param string $name
* @param Closure $input
* @return void
*/
public static function macro($name, $macro)
{
static::$macros[$name] = $macro;
}
/** /**
* Open a HTML form. * Open a HTML form.
...@@ -52,8 +71,7 @@ class Form { ...@@ -52,8 +71,7 @@ class Form {
// Since PUT and DELETE methods are not actually supported by HTML forms, // Since PUT and DELETE methods are not actually supported by HTML forms,
// we'll create a hidden input element that contains the request method // we'll create a hidden input element that contains the request method
// and set the actual request method to POST. Laravel will look for the // and set the actual request method variable to POST.
// hidden element to determine the request method.
if ($method == 'PUT' or $method == 'DELETE') if ($method == 'PUT' or $method == 'DELETE')
{ {
$append = static::hidden(Request::spoofer, $method); $append = static::hidden(Request::spoofer, $method);
...@@ -541,8 +559,7 @@ class Form { ...@@ -541,8 +559,7 @@ class Form {
{ {
// If an ID has been explicitly specified in the attributes, we will // If an ID has been explicitly specified in the attributes, we will
// use that ID. Otherwise, we will look for an ID in the array of // use that ID. Otherwise, we will look for an ID in the array of
// label names as this makes it convenient to give input elements // label names so labels and their elements have the same ID.
// the same ID as their corresponding labels.
if (array_key_exists('id', $attributes)) if (array_key_exists('id', $attributes))
{ {
return $attributes['id']; return $attributes['id'];
...@@ -554,4 +571,21 @@ class Form { ...@@ -554,4 +571,21 @@ class Form {
} }
} }
/**
* Dynamically handle calls to custom macros.
*
* @param string $method
* @param array $parameters
* @return mixed
*/
public static function __callStatic($method, $parameters)
{
if (isset(static::$macros[$method]))
{
return call_user_func_array(static::$macros[$method], $parameters);
}
throw new \Exception("Method [$method] does not exist.");
}
} }
...@@ -16,6 +16,13 @@ class Redis { ...@@ -16,6 +16,13 @@ class Redis {
*/ */
protected $port; protected $port;
/**
* The databse number the connection selects on load.
*
* @var int
*/
protected $database;
/** /**
* The connection to the Redis database. * The connection to the Redis database.
* *
...@@ -35,12 +42,14 @@ class Redis { ...@@ -35,12 +42,14 @@ class Redis {
* *
* @param string $host * @param string $host
* @param string $port * @param string $port
* @param int $database
* @return void * @return void
*/ */
public function __construct($host, $port) public function __construct($host, $port, $database = 0)
{ {
$this->host = $host; $this->host = $host;
$this->port = $port; $this->port = $port;
$this->database = $database;
} }
/** /**
...@@ -68,7 +77,9 @@ class Redis { ...@@ -68,7 +77,9 @@ class Redis {
throw new \Exception("Redis database [$name] is not defined."); throw new \Exception("Redis database [$name] is not defined.");
} }
static::$databases[$name] = new static($config['host'], $config['port']); extract($config);
static::$databases[$name] = new static($host, $port, $database);
} }
return static::$databases[$name]; return static::$databases[$name];
...@@ -95,6 +106,17 @@ class Redis { ...@@ -95,6 +106,17 @@ class Redis {
$response = trim(fgets($this->connection, 512)); $response = trim(fgets($this->connection, 512));
return $this->parse($response);
}
/**
* Parse and return the response from the Redis database.
*
* @param string $response
* @return mixed
*/
protected function parse($response)
{
switch (substr($response, 0, 1)) switch (substr($response, 0, 1))
{ {
case '-': case '-':
...@@ -131,6 +153,8 @@ class Redis { ...@@ -131,6 +153,8 @@ class Redis {
throw new \Exception("Error making Redis connection: {$error} - {$message}"); throw new \Exception("Error making Redis connection: {$error} - {$message}");
} }
$this->select($this->database);
return $this->connection; return $this->connection;
} }
...@@ -191,6 +215,8 @@ class Redis { ...@@ -191,6 +215,8 @@ class Redis {
list($read, $response, $size) = array(0, '', substr($head, 1)); list($read, $response, $size) = array(0, '', substr($head, 1));
if ($size > 0)
{
do do
{ {
// Calculate and read the appropriate bytes off of the Redis response. // Calculate and read the appropriate bytes off of the Redis response.
...@@ -203,6 +229,7 @@ class Redis { ...@@ -203,6 +229,7 @@ class Redis {
$read += $block; $read += $block;
} while ($read < $size); } while ($read < $size);
}
// The response ends with a trailing CRLF. So, we need to read that off // The response ends with a trailing CRLF. So, we need to read that off
// of the end of the file stream to get it out of the way of the next // of the end of the file stream to get it out of the way of the next
...@@ -225,11 +252,11 @@ class Redis { ...@@ -225,11 +252,11 @@ class Redis {
$response = array(); $response = array();
// Iterate through each bulk response in the multi-bulk and parse it out // Iterate through each bulk response in the multi-bulk and parse it out
// using the "bulk" method since a multi-bulk response is just a list of // using the "parse" method since a multi-bulk response is just a list
// plain old bulk responses. // of plain old Redis database responses.
for ($i = 0; $i < $count; $i++) for ($i = 0; $i < $count; $i++)
{ {
$response[] = $this->bulk(trim(fgets($this->connection, 512))); $response[] = $this->parse(trim(fgets($this->connection, 512)));
} }
return $response; return $response;
......
...@@ -381,4 +381,16 @@ class Route { ...@@ -381,4 +381,16 @@ class Route {
Filter::register($name, $callback); Filter::register($name, $callback);
} }
/**
* Calls the specified route and returns its response.
*
* @param string $method
* @param string $uri
* @return Response
*/
public static function forward($method, $uri)
{
return Router::route(strtoupper($method), $uri)->call();
}
} }
\ No newline at end of file
...@@ -611,6 +611,18 @@ class Validator { ...@@ -611,6 +611,18 @@ class Validator {
return preg_match('/^([-a-z0-9_-])+$/i', $value); return preg_match('/^([-a-z0-9_-])+$/i', $value);
} }
/**
* Validate that an attribute passes a regular expression check.
*
* @param string $attribute
* @param mixed $value
* @return bool
*/
protected function validate_match($attribute, $value, $parameters)
{
return preg_match($parameters[0], $value);
}
/** /**
* Validate the MIME type of a file upload attribute is in a set of MIME types. * Validate the MIME type of a file upload attribute is in a set of MIME types.
* *
......
...@@ -41,7 +41,7 @@ Laravel is a clean and classy framework for PHP web development. Freeing you fro ...@@ -41,7 +41,7 @@ Laravel is a clean and classy framework for PHP web development. Freeing you fro
Contributions are encouraged and welcome; however, please review the Developer Certificate of Origin in the "license.txt" file included in the repository. All commits must be signed off using the "-s" switch. Contributions are encouraged and welcome; however, please review the Developer Certificate of Origin in the "license.txt" file included in the repository. All commits must be signed off using the "-s" switch.
git commit -s -m "thie commit will be signed off automatically!" git commit -s -m "this commit will be signed off automatically!"
### License ### License
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment