Browse Source

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

Conflicts:
	laravel/form.php
Colin Viebrock 12 years ago
parent
commit
aa27df8bcb

+ 5 - 1
application/config/database.php

@@ -113,7 +113,11 @@ return array(
 
 	'redis' => array(
 
-		'default' => array('host' => '127.0.0.1', 'port' => 6379),
+		'default' => array(
+			'host'     => '127.0.0.1',
+			'port'     => 6379,
+			'database' => 0
+		),
 
 	),
 

+ 1 - 0
application/language/en/validation.php

@@ -36,6 +36,7 @@ return array(
 	"in"             => "The selected :attribute is invalid.",
 	"integer"        => "The :attribute must be an integer.",
 	"ip"             => "The :attribute must be a valid IP address.",
+	"match"          => "The :attribute format is invalid.",
 	"max"            => array(
 		"numeric" => "The :attribute must be less than :max.",
 		"file"    => "The :attribute must be less than :max kilobytes.",

+ 5 - 1
changes.txt

@@ -20,4 +20,8 @@ Changes for 3.1:
 	- Added controller::detect method.
 	- Added Cache::forever method.
 	- 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.

+ 2 - 2
laravel/cli/tasks/migrate/migrator.php

@@ -154,9 +154,9 @@ class Migrator extends Task {
 			// the bundle name and string migration name as an unique ID
 			// for the migrations, allowing us to easily identify which
 			// 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
 			// ID with each of the rows on the table. This will allow

+ 17 - 4
laravel/database/grammar.php

@@ -89,21 +89,34 @@ abstract class Grammar {
 		// Since columns may be prefixed with their corresponding table
 		// name so as to not make them ambiguous, we will need to wrap
 		// 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
 			{
-				$wrapped[] = sprintf($this->wrapper, $segment);
+				$wrapped[] = $this->wrap_value($value);
 			}
 		}
 
 		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.
 	 *

+ 1 - 1
laravel/database/query.php

@@ -182,7 +182,7 @@ class Query {
 	 * @param  string  $column2
 	 * @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');
 	}

+ 16 - 1
laravel/database/schema/grammars/grammar.php

@@ -32,7 +32,22 @@ abstract class Grammar extends \Laravel\Database\Grammar {
 
 		$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;
 	}
 
 	/**

+ 56 - 6
laravel/file.php

@@ -68,6 +68,30 @@ class File {
 		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.
 	 * 
@@ -173,6 +197,18 @@ class File {
 		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.
 	 *
@@ -183,7 +219,7 @@ class File {
 	 */
 	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 {
 	 */
 	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
 		// already exists. This directory hosts all of the assets we copy
@@ -221,7 +257,7 @@ class File {
 			{
 				$path = $item->getRealPath();
 
-				static::cpdir($path, $location, $delete, $options);
+				if (! static::cpdir($path, $location, $delete, $options)) return false;
 
 				if ($delete) @rmdir($item->getRealPath());
 			}
@@ -231,22 +267,25 @@ class File {
 			// files with the same name.
 			else
 			{
-				copy($item->getRealPath(), $location);
+				if(! copy($item->getRealPath(), $location)) return false;
 
 				if ($delete) @unlink($item->getRealPath());
 			}
 		}
 
 		if ($delete) rmdir($source);
+		
+		return true;
 	}
 
 	/**
 	 * Recursively delete a directory.
 	 *
 	 * @param  string  $directory
+	 * @param  bool    $preserve
 	 * @return void
 	 */
-	public static function rmdir($directory)
+	public static function rmdir($directory, $preserve = false)
 	{
 		if ( ! is_dir($directory)) return;
 
@@ -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);
 	}
 
 	/**

+ 39 - 5
laravel/form.php

@@ -7,7 +7,26 @@ class Form {
 	 *
 	 * @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.
@@ -52,8 +71,7 @@ class Form {
 
 		// Since PUT and DELETE methods are not actually supported by HTML forms,
 		// 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
-		// hidden element to determine the request method.
+		// and set the actual request method variable to POST.
 		if ($method == 'PUT' or $method == 'DELETE')
 		{
 			$append = static::hidden(Request::spoofer, $method);
@@ -541,8 +559,7 @@ class Form {
 	{
 		// 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
-		// label names as this makes it convenient to give input elements
-		// the same ID as their corresponding labels.
+		// label names so labels and their elements have the same ID.
 		if (array_key_exists('id', $attributes))
 		{
 			return $attributes['id'];
@@ -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.");
+	}
+
 }

+ 40 - 13
laravel/redis.php

@@ -16,6 +16,13 @@ class Redis {
 	 */
 	protected $port;
 
+	/**
+	 * The databse number the connection selects on load.
+	 *
+	 * @var int
+	 */
+	protected $database;
+
 	/**
 	 * The connection to the Redis database.
 	 *
@@ -35,12 +42,14 @@ class Redis {
 	 *
 	 * @param  string  $host
 	 * @param  string  $port
+	 * @param  int     $database
 	 * @return void
 	 */
-	public function __construct($host, $port)
+	public function __construct($host, $port, $database = 0)
 	{
 		$this->host = $host;
 		$this->port = $port;
+		$this->database = $database;
 	}
 
 	/**
@@ -68,7 +77,9 @@ class Redis {
 				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];
@@ -95,6 +106,17 @@ class Redis {
 
 		$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))
 		{
 			case '-':
@@ -131,6 +153,8 @@ class Redis {
 			throw new \Exception("Error making Redis connection: {$error} - {$message}");
 		}
 
+		$this->select($this->database);
+
 		return $this->connection;
 	}
 
@@ -191,18 +215,21 @@ class Redis {
 
 		list($read, $response, $size) = array(0, '', substr($head, 1));
 
-		do
+		if ($size > 0)
 		{
-			// Calculate and read the appropriate bytes off of the Redis response.
-			// We'll read off the response in 1024 byte chunks until the entire
-			// response has been read from the database.
-			$block = (($remaining = $size - $read) < 1024) ? $remaining : 1024;
+			do
+			{
+				// Calculate and read the appropriate bytes off of the Redis response.
+				// We'll read off the response in 1024 byte chunks until the entire
+				// response has been read from the database.
+				$block = (($remaining = $size - $read) < 1024) ? $remaining : 1024;
 
-			$response .= fread($this->connection, $block);
+				$response .= fread($this->connection, $block);
 
-			$read += $block;
+				$read += $block;
 
-		} while ($read < $size);
+			} while ($read < $size);
+		}
 
 		// 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
@@ -225,11 +252,11 @@ class Redis {
 		$response = array();
 
 		// 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
-		// plain old bulk responses.
+		// using the "parse" method since a multi-bulk response is just a list
+		// of plain old Redis database responses.
 		for ($i = 0; $i < $count; $i++)
 		{
-			$response[] = $this->bulk(trim(fgets($this->connection, 512)));
+			$response[] = $this->parse(trim(fgets($this->connection, 512)));
 		}
 
 		return $response;

+ 12 - 0
laravel/routing/route.php

@@ -381,4 +381,16 @@ class Route {
 		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();
+	}
+
 }

+ 12 - 0
laravel/validator.php

@@ -611,6 +611,18 @@ class Validator {
 		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.
 	 *

+ 1 - 1
readme.md

@@ -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.
 
-	git commit -s -m "thie commit will be signed off automatically!"
+	git commit -s -m "this commit will be signed off automatically!"
 
 ### License