Browse Source

Merge branch '2.0' of github.com:cakephp/cakephp into 2.0

Jose Lorenzo Rodriguez 15 years ago
parent
commit
492f1ce12e

+ 2 - 1
lib/Cake/Console/Command/Task/ControllerTask.php

@@ -18,6 +18,7 @@
  */
 
 App::uses('BakeTask', 'Console/Command/Task');
+App::uses('AppModel', 'Model');
 
 /**
  * Task class for creating and updating controller files.
@@ -499,4 +500,4 @@ class ControllerTask extends BakeTask {
 		$this->out();
 		$this->_stop();
 	}
-}
+}

+ 3 - 3
lib/Cake/Console/Command/Task/DbConfigTask.php

@@ -38,7 +38,7 @@ class DbConfigTask extends Shell {
  */
 	protected $_defaultConfig = array(
 		'name' => 'default',
-		'driver'=> 'mysql',
+		'datasource'=> 'Database/Mysql',
 		'persistent'=> 'false',
 		'host'=> 'localhost',
 		'login'=> 'root',
@@ -104,7 +104,7 @@ class DbConfigTask extends Shell {
 				}
 			}
 
-			$driver = $this->in(__d('cake_console', 'Driver:'), array('mssql', 'mysql', 'oracle', 'postgres', 'sqlite'), 'mysql');
+			$driver = $this->in(__d('cake_console', 'Driver:'), array('Mssql', 'Mysql', 'Oracle', 'Postgres', 'Sqlite'), 'Mysql');
 
 			$persistent = $this->in(__d('cake_console', 'Persistent Connection?'), array('y', 'n'), 'n');
 			if (strtolower($persistent) == 'n') {
@@ -313,7 +313,7 @@ class DbConfigTask extends Shell {
 			extract($config);
 
 			$out .= "\tpublic \${$name} = array(\n";
-			$out .= "\t\t'driver' => '{$driver}',\n";
+			$out .= "\t\t'datasource' => 'Database/{$driver}',\n";
 			$out .= "\t\t'persistent' => {$persistent},\n";
 			$out .= "\t\t'host' => '{$host}',\n";
 

+ 1 - 1
lib/Cake/Console/Shell.php

@@ -220,7 +220,7 @@ class Shell extends Object {
 		if ($this->uses === null || $this->uses === false) {
 			return;
 		}
-		App::import('Core', 'ClassRegistry');
+		App::uses('ClassRegistry', 'Utility');
 
 		if ($this->uses !== true && !empty($this->uses)) {
 			$uses = is_array($this->uses) ? $this->uses : array($this->uses);

+ 60 - 36
lib/Cake/Controller/Component/RequestHandlerComponent.php

@@ -34,7 +34,6 @@ class RequestHandlerComponent extends Component {
  * The layout that will be switched to for Ajax requests
  *
  * @var string
- * @access public
  * @see RequestHandler::setAjax()
  */
 	public $ajaxLayout = 'ajax';
@@ -43,7 +42,6 @@ class RequestHandlerComponent extends Component {
  * Determines whether or not callbacks will be fired on this component
  *
  * @var boolean
- * @access public
  */
 	public $enabled = true;
 
@@ -51,7 +49,6 @@ class RequestHandlerComponent extends Component {
  * Holds the reference to Controller::$request
  *
  * @var CakeRequest
- * @access public
  */
 	public $request;
 
@@ -59,35 +56,33 @@ class RequestHandlerComponent extends Component {
  * Holds the reference to Controller::$response
  *
  * @var CakeResponse
- * @access public
  */
 	public $response;
 
 /**
- * The template to use when rendering the given content type.
+ * Contains the file extension parsed out by the Router
  *
  * @var string
- * @access private
+ * @see Router::parseExtensions()
  */
-	private $__renderType = null;
+	public $ext = null;
 
 /**
- * Contains the file extension parsed out by the Router
+ * The template to use when rendering the given content type.
  *
  * @var string
- * @access public
- * @see Router::parseExtensions()
  */
-	public $ext = null;
+	private $__renderType = null;
 
 /**
- * Flag set when MIME types have been initialized
+ * A mapping between extensions and deserializers for request bodies of that type.
+ * By default only JSON and XML are mapped, use RequestHandlerComponent::addInputType()
  *
- * @var boolean
- * @access private
- * @see RequestHandler::__initializeTypes()
+ * @var array
  */
-	private $__typesInitialized = false;
+	private $__inputTypeMap = array(
+		'json' => array('json_decode', true)
+	);
 
 /**
  * Constructor. Parses the accepted content types accepted by the client using HTTP_ACCEPT
@@ -96,14 +91,7 @@ class RequestHandlerComponent extends Component {
  * @param array $settings Array of settings.
  */
 	function __construct(ComponentCollection $collection, $settings = array()) {
-		$this->__acceptTypes = explode(',', env('HTTP_ACCEPT'));
-
-		foreach ($this->__acceptTypes as $i => $type) {
-			if (strpos($type, ';')) {
-				$type = explode(';', $type);
-				$this->__acceptTypes[$i] = $type[0];
-			}
-		}
+		$this->addInputType('xml', array(array($this, '_convertXml')));
 		parent::__construct($collection, $settings);
 	}
 
@@ -124,7 +112,7 @@ class RequestHandlerComponent extends Component {
 		if (isset($this->request->params['url']['ext'])) {
 			$this->ext = $this->request->params['url']['ext'];
 		}
-		if (empty($this->ext)) {
+		if (empty($this->ext) || $this->ext == 'html') {
 			$accepts = $this->request->accepts();
 			$extensions = Router::extensions();
 			if (count($accepts) == 1) {
@@ -172,20 +160,35 @@ class RequestHandlerComponent extends Component {
 			$this->respondAs('html', array('charset' => Configure::read('App.encoding')));
 		}
 
-		if ($this->requestedWith('xml')) {
-			try {
-				$xml = Xml::build(trim(file_get_contents('php://input')));
-
-				if (isset($xml->data)) {
-					$controller->data = Xml::toArray($xml->data);
-				} else {
-					$controller->data = Xml::toArray($xml);
-				}
-			} catch (Exception $e) {}
+		foreach ($this->__inputTypeMap as $type => $handler) {
+			if ($this->requestedWith($type)) {
+				$input = call_user_func_array(array($controller->request, 'input'), $handler);
+				$controller->request->data = $input;
+			}
 		}
 	}
 
 /**
+ * Helper method to parse xml input data, due to lack of anonymous functions
+ * this lives here.
+ *
+ * @param string $xml 
+ * @return array Xml array data
+ * @access protected
+ */
+	public function _convertXml($xml) {
+		try {
+			$xml = Xml::build($xml);
+			if (isset($xml->data)) {
+				return Xml::toArray($xml->data);
+			}
+			return Xml::toArray($xml);
+		 } catch (XmlException $e) {
+			return array();
+		 }
+	}
+
+/**
  * Handles (fakes) redirects for Ajax requests using requestAction()
  *
  * @param object $controller A reference to the controller
@@ -216,6 +219,7 @@ class RequestHandlerComponent extends Component {
  * Returns true if the current HTTP request is Ajax, false otherwise
  *
  * @return boolean True if call is Ajax
+ * @deprecated use `$this->request->is('ajax')` instead.
  */
 	public function isAjax() {
 		return $this->request->is('ajax');
@@ -225,6 +229,7 @@ class RequestHandlerComponent extends Component {
  * Returns true if the current HTTP request is coming from a Flash-based client
  *
  * @return boolean True if call is from Flash
+ * @deprecated use `$this->request->is('flash')` instead.
  */
 	public function isFlash() {
 		return $this->request->is('flash');
@@ -234,6 +239,7 @@ class RequestHandlerComponent extends Component {
  * Returns true if the current request is over HTTPS, false otherwise.
  *
  * @return bool True if call is over HTTPS
+ * @deprecated use `$this->request->is('ssl')` instead.
  */
 	public function isSSL() {
 		return $this->request->is('ssl');
@@ -348,6 +354,7 @@ class RequestHandlerComponent extends Component {
  * @param mixed $type The Content-type or array of Content-types assigned to the name,
  *    i.e. "text/html", or "application/xml"
  * @return void
+ * @deprecated use `$this->response->type()` instead.
  */
 	public function setContent($name, $type = null) {
 		$this->response->type(array($name => $type));
@@ -367,7 +374,7 @@ class RequestHandlerComponent extends Component {
  * Gets remote client IP
  *
  * @return string Client IP address
- * @deprecated use $this->request->clientIp() from your controller instead.
+ * @deprecated use $this->request->clientIp() from your,  controller instead.
  */
 	public function getClientIP($safe = true) {
 		return $this->request->clientIp($safe);
@@ -641,4 +648,21 @@ class RequestHandlerComponent extends Component {
 		}
 		return null;
 	}
+
+/**
+ * Add a new mapped input type.  Mapped input types are automatically 
+ * converted by RequestHandlerComponent during the startup() callback.
+ *
+ * @param string $type The type alias being converted, ie. json
+ * @param array $handler The handler array for the type.  The first index should
+ *    be the handling callback, all other arguments should be additional parameters
+ *    for the handler.
+ * @return void
+ */
+	public function addInputType($type, $handler) {
+		if (!is_array($handler) || !isset($handler[0]) || !is_callable($handler[0])) {
+			throw new CakeException(__d('cake_dev', 'You must give a handler callback.'));
+		}
+		$this->__inputTypeMap[$type] = $handler;
+	}
 }

+ 37 - 12
lib/Cake/Core/App.php

@@ -63,6 +63,27 @@
 class App {
 
 /**
+ * Append paths
+ *
+ * @constant APPEND
+ */
+	const APPEND = 'append';
+
+/**
+ * Prepend paths
+ *
+ * @constant PREPEND
+ */
+	const PREPEND = 'prepend';
+
+/**
+ * Reset paths instead of merging
+ *
+ * @constant RESET
+ */
+	const RESET = true;
+
+/**
  * List of object types and their properties
  *
  * @var array
@@ -222,15 +243,15 @@ class App {
  *
  * `App::build(array(Model' => array('/a/full/path/to/models/'))); will setup a new search path for the Model package`
  *
- * `App::build(array('Model' => array('/path/to/models/')), true); will setup the path as the only valid path for searching models`
+ * `App::build(array('Model' => array('/path/to/models/')), App::RESET); will setup the path as the only valid path for searching models`
  *
- * `App::build(array('View/Helper' => array('/path/to/models/', '/another/path/))); will setup multiple search paths for helpers`
+ * `App::build(array('View/Helper' => array('/path/to/helpers/', '/another/path/))); will setup multiple search paths for helpers`
  *
  * @param array $paths associative array with package names as keys and a list of directories for new search paths
- * @param boolean $reset true will set paths, false merges paths [default] false
+ * @param mixed $mode App::RESET will set paths, App::APPEND with append paths, App::PREPEND will prepend paths, [default] App::PREPEND
  * @return void
  */
-	public static function build($paths = array(), $reset = false) {
+	public static function build($paths = array(), $mode = App::PREPEND) {
 		if (empty(self::$__packageFormat)) {
 			self::$__packageFormat = array(
 				'Model' => array(
@@ -296,7 +317,7 @@ class App {
 			);
 		}
 
-		if ($reset == true) {
+		if ($mode === App::RESET) {
 			foreach ($paths as $type => $new) {
 				if (!empty(self::$legacy[$type])) {
 					$type = self::$legacy[$type];
@@ -329,7 +350,11 @@ class App {
 			}
 
 			if (!empty($paths[$type])) {
-				$path = array_merge((array)$paths[$type], self::$__packages[$type]);
+				if ($mode === App::PREPEND) {
+					$path = array_merge((array)$paths[$type], self::$__packages[$type]);
+				} else {
+					$path = array_merge(self::$__packages[$type], (array)$paths[$type]);
+				}
 			} else {
 				$path = self::$__packages[$type];
 			}
@@ -614,10 +639,10 @@ class App {
 			return true;
 		}
 
-		$originalType = $type = strtolower($type);
-		$specialPackage = in_array($type, array('file', 'vendor'));
-		if (!$specialPackage && isset(self::$legacy[$type . 's'])) {
-			$type = self::$legacy[$type . 's'];
+		$originalType = strtolower($type);
+		$specialPackage = in_array($originalType, array('file', 'vendor'));
+		if (!$specialPackage && isset(self::$legacy[$originalType . 's'])) {
+			$type = self::$legacy[$originalType . 's'];
 		}
 		list($plugin, $name) = pluginSplit($name);
 		if (!empty($plugin)) {
@@ -628,11 +653,11 @@ class App {
 			return self::_loadClass($name, $plugin, $type, $originalType, $parent);
 		}
 
-		if ($type == 'file' && !empty($file)) {
+		if ($originalType == 'file' && !empty($file)) {
 			return self::_loadFile($name, $plugin, $search, $file, $return);
 		}
 
-		if ($type == 'vendor') {
+		if ($originalType == 'vendor') {
 			return self::_loadVendor($name, $plugin, $file, $ext);
 		}
 

+ 75 - 11
lib/Cake/Network/CakeRequest.php

@@ -106,6 +106,15 @@ class CakeRequest implements ArrayAccess {
 			'webOS', 'Windows CE', 'Xiino'
 		))
 	);
+
+/**
+ * Copy of php://input.  Since this stream can only be read once in most SAPI's
+ * keep a copy of it so users don't need to know about that detail.
+ *
+ * @var string
+ */
+	private $__input = '';
+
 /**
  * Constructor 
  *
@@ -133,28 +142,30 @@ class CakeRequest implements ArrayAccess {
 
 /**
  * process the post data and set what is there into the object.
+ * processed data is available at $this->data
  *
  * @return void
  */
 	protected function _processPost() {
-		$this->params['form'] = $_POST;
+		$this->data = $_POST;
 		if (ini_get('magic_quotes_gpc') === '1') {
-			$this->params['form'] = stripslashes_deep($this->params['form']);
+			$this->data = stripslashes_deep($this->data);
 		}
 		if (env('HTTP_X_HTTP_METHOD_OVERRIDE')) {
-			$this->params['form']['_method'] = env('HTTP_X_HTTP_METHOD_OVERRIDE');
+			$this->data['_method'] = env('HTTP_X_HTTP_METHOD_OVERRIDE');
 		}
-		if (isset($this->params['form']['_method'])) {
+		if (isset($this->data['_method'])) {
 			if (!empty($_SERVER)) {
-				$_SERVER['REQUEST_METHOD'] = $this->params['form']['_method'];
+				$_SERVER['REQUEST_METHOD'] = $this->data['_method'];
 			} else {
-				$_ENV['REQUEST_METHOD'] = $this->params['form']['_method'];
+				$_ENV['REQUEST_METHOD'] = $this->data['_method'];
 			}
-			unset($this->params['form']['_method']);
+			unset($this->data['_method']);
 		}
-		if (isset($this->params['form']['data'])) {
-			$this->data = $this->params['form']['data'];
-			unset($this->params['form']['data']);
+		if (isset($this->data['data'])) {
+			$data = $this->data['data'];
+			unset($this->data['data']);
+			$this->data = Set::merge($this->data, $data);
 		}
 	}
 
@@ -533,6 +544,14 @@ class CakeRequest implements ArrayAccess {
 
 /**
  * Get the HTTP method used for this request.
+ * There are a few ways to specify a method.  
+ *
+ * - If your client supports it you can use native HTTP methods.
+ * - You can set the HTTP-X-Method-Override header. 
+ * - You can submit an input with the name `_method`
+ *
+ * Any of these 3 approaches can be used to set the HTTP method used
+ * by CakePHP internally, and will effect the result of this method.
  *
  * @return string The name of the HTTP method used.
  */
@@ -663,6 +682,51 @@ class CakeRequest implements ArrayAccess {
 	}
 
 /**
+ * Read data from `php://stdin`. Useful when interacting with XML or JSON
+ * request body content.
+ * 
+ * Getting input with a decoding function:
+ *
+ * `$this->request->input('json_decode');`
+ *
+ * Getting input using a decoding function, and additional params:
+ *
+ * `$this->request->input('Xml::build', array('return' => 'DOMDocument'));`
+ *
+ * Any additional parameters are applied to the callback in the order they are given.
+ *
+ * @param string $callback A decoding callback that will convert the string data to another
+ *     representation. Leave empty to access the raw input data. You can also
+ *     supply additional parameters for the decoding callback using var args, see above.
+ * @return The decoded/processed request data.
+ */
+	public function input($callback = null) {
+		$input = $this->_readStdin();
+		$args = func_get_args();
+		if (!empty($args)) {
+			$callback = array_shift($args);
+			array_unshift($args, $input);
+			return call_user_func_array($callback, $args);
+		}
+		return $input;
+	}
+
+/**
+ * Read data from php://stdin, mocked in tests.
+ *
+ * @return string contents of stdin
+ */
+	protected function _readStdin() {
+		if (empty($this->__input)) {
+			$fh = fopen('php://input', 'r');
+			$content = stream_get_contents($fh);
+			fclose($fh);
+			$this->__input = $content;
+		}
+		return $this->__input;
+	}
+
+/**
  * Array access read implementation
  *
  * @param string $name Name of the key being accessed.
@@ -711,4 +775,4 @@ class CakeRequest implements ArrayAccess {
 	public function offsetUnset($name) {
 		unset($this->params[$name]);
 	}
-}
+}

+ 15 - 15
lib/Cake/Network/Email/CakeEmail.php

@@ -277,7 +277,7 @@ class CakeEmail {
  * @param mixed $email
  * @param string $name
  * @return mixed
- * @thrown SocketException
+ * @throws SocketException
  */
 	public function from($email = null, $name = null) {
 		if ($email === null) {
@@ -292,7 +292,7 @@ class CakeEmail {
  * @param mixed $email
  * @param string $name
  * @return mixed
- * @thrown SocketException
+ * @throws SocketException
  */
 	public function sender($email = null, $name = null) {
 		if ($email === null) {
@@ -307,7 +307,7 @@ class CakeEmail {
  * @param mixed $email
  * @param string $name
  * @return mixed
- * @thrown SocketException
+ * @throws SocketException
  */
 	public function replyTo($email = null, $name = null) {
 		if ($email === null) {
@@ -322,7 +322,7 @@ class CakeEmail {
  * @param mixed $email
  * @param string $name
  * @return mixed
- * @thrown SocketException
+ * @throws SocketException
  */
 	public function readReceipt($email = null, $name = null) {
 		if ($email === null) {
@@ -337,7 +337,7 @@ class CakeEmail {
  * @param mixed $email
  * @param string $name
  * @return mixed
- * @thrown SocketException
+ * @throws SocketException
  */
 	public function returnPath($email = null, $name = null) {
 		if ($email === null) {
@@ -428,7 +428,7 @@ class CakeEmail {
  * @param mixed $email
  * @param mixed $name
  * @return object $this
- * @thrown SocketException
+ * @throws SocketException
  */
 	protected function _setEmail($varName, $email, $name) {
 		if (!is_array($email)) {
@@ -463,7 +463,7 @@ class CakeEmail {
  * @param string $name
  * @param string $throwMessage
  * @return object $this
- * @thrown SocketExpceiton
+ * @throws SocketExpceiton
  */
 	protected function _setEmailSingle($varName, $email, $name, $throwMessage) {
 		$current = $this->{$varName};
@@ -527,7 +527,7 @@ class CakeEmail {
  *
  * @param array Associative array containing headers to be set.
  * @return object $this
- * @thrown SocketException
+ * @throws SocketException
  */
 	public function setHeaders($headers) {
 		if (!is_array($headers)) {
@@ -542,7 +542,7 @@ class CakeEmail {
  *
  * @param array $headers
  * @return mixed $this
- * @thrown SocketException
+ * @throws SocketException
  */
 	public function addHeaders($headers) {
 		if (!is_array($headers)) {
@@ -720,7 +720,7 @@ class CakeEmail {
  *
  * @param string $format
  * @return mixed
- * @thrown SocketException
+ * @throws SocketException
  */
 	public function emailFormat($format = null) {
 		if ($format === null) {
@@ -752,7 +752,7 @@ class CakeEmail {
  * Return the transport class
  *
  * @return object
- * @thrown SocketException
+ * @throws SocketException
  */
 	public function transportClass() {
 		if ($this->_transportClass) {
@@ -775,7 +775,7 @@ class CakeEmail {
  *
  * @param mixed $message True to generate a new Message-ID, False to ignore (not send in email), String to set as Message-ID
  * @return mixed
- * @thrown SocketException
+ * @throws SocketException
  */
 	public function messageId($message = null) {
 		if ($message === null) {
@@ -797,7 +797,7 @@ class CakeEmail {
  *
  * @param mixed $attachments String with the filename or array with filenames
  * @return mixed
- * @thrown SocketException
+ * @throws SocketException
  */
 	public function attachments($attachments = null) {
 		if ($attachments === null) {
@@ -832,7 +832,7 @@ class CakeEmail {
  *
  * @param mixed $attachments String with the filename or array with filenames
  * @return object $this
- * @thrown SocketException
+ * @throws SocketException
  */
 	public function addAttachments($attachments) {
 		$current = $this->_attachments;
@@ -885,7 +885,7 @@ class CakeEmail {
  * Send an email using the specified content, template and layout
  *
  * @return boolean Success
- * @thrown SocketException
+ * @throws SocketException
  */
 	public function send($content = null) {
 		if (is_string($this->_config)) {

+ 8 - 8
lib/Cake/Network/Email/SmtpTransport.php

@@ -44,7 +44,7 @@ class SmtpTransport extends AbstractTransport {
  *
  * @params object $email CakeEmail
  * @return boolean
- * @thrown SocketException
+ * @throws SocketException
  */
 	public function send(CakeEmail $email) {
 		$this->_cakeEmail = $email;
@@ -80,7 +80,7 @@ class SmtpTransport extends AbstractTransport {
  * Connect to SMTP Server
  *
  * @return void
- * @thrown SocketException
+ * @throws SocketException
  */
 	protected function _connect() {
 		$this->_generateSocket();
@@ -112,7 +112,7 @@ class SmtpTransport extends AbstractTransport {
  * Send authentication
  *
  * @return void
- * @thrown SocketException
+ * @throws SocketException
  */
 	protected function _auth() {
 		if (isset($this->_config['username']) && isset($this->_config['password'])) {
@@ -134,7 +134,7 @@ class SmtpTransport extends AbstractTransport {
  * Send emails
  *
  * @return void
- * @thrown SocketException
+ * @throws SocketException
  */
 	protected function _sendRcpt() {
 		$from = $this->_cakeEmail->from();
@@ -153,7 +153,7 @@ class SmtpTransport extends AbstractTransport {
  * Send Data
  *
  * @return void
- * @thrown SocketException
+ * @throws SocketException
  */
 	protected function _sendData() {
 		$this->_smtpSend('DATA', '354');
@@ -168,7 +168,7 @@ class SmtpTransport extends AbstractTransport {
  * Disconnect
  *
  * @return void
- * @thrown SocketException
+ * @throws SocketException
  */
 	protected function _disconnect() {
 		$this->_smtpSend('QUIT', false);
@@ -179,7 +179,7 @@ class SmtpTransport extends AbstractTransport {
  * Helper method to generate socket
  *
  * @return void
- * @thrown SocketException
+ * @throws SocketException
  */
 	protected function _generateSocket() {
 		$this->_socket = new CakeSocket($this->_config);
@@ -191,7 +191,7 @@ class SmtpTransport extends AbstractTransport {
  * @param string $data data to be sent to SMTP server
  * @param mixed $checkCode code to check for in server response, false to skip
  * @return void
- * @thrown SocketException
+ * @throws SocketException
  */
 	function _smtpSend($data, $checkCode = '250') {
 		if (!is_null($data)) {

+ 366 - 343
lib/Cake/basics.php

@@ -1,4 +1,5 @@
 <?php
+
 /**
  * Basic Cake functionality.
  *
@@ -40,25 +41,25 @@
  * @return boolean Success
  * @link http://book.cakephp.org/view/1125/config
  */
-	function config() {
-		$args = func_get_args();
-		foreach ($args as $arg) {
-			if ($arg === 'database' && file_exists(CONFIGS . 'database.php')) {
-				include_once(CONFIGS . $arg . '.php');
-			} elseif (file_exists(CONFIGS . $arg . '.php')) {
-				include_once(CONFIGS . $arg . '.php');
-
-				if (count($args) == 1) {
-					return true;
-				}
-			} else {
-				if (count($args) == 1) {
-					return false;
-				}
+function config() {
+	$args = func_get_args();
+	foreach ($args as $arg) {
+		if ($arg === 'database' && file_exists(CONFIGS . 'database.php')) {
+			include_once(CONFIGS . $arg . '.php');
+		} elseif (file_exists(CONFIGS . $arg . '.php')) {
+			include_once(CONFIGS . $arg . '.php');
+
+			if (count($args) == 1) {
+				return true;
+			}
+		} else {
+			if (count($args) == 1) {
+				return false;
 			}
 		}
-		return true;
 	}
+	return true;
+}
 
 /**
  * Prints out debug information about given variable.
@@ -71,16 +72,16 @@
  * @link http://book.cakephp.org/view/1190/Basic-Debugging
  * @link http://book.cakephp.org/view/1128/debug
  */
-	function debug($var = false, $showHtml = null, $showFrom = true) {
-		if (Configure::read('debug') > 0) {
-			$file = '';
-			$line = '';
-			if ($showFrom) {
-				$calledFrom = debug_backtrace();
-				$file = substr(str_replace(ROOT, '', $calledFrom[0]['file']), 1);
-				$line = $calledFrom[0]['line'];
-			}
-			$html = <<<HTML
+function debug($var = false, $showHtml = null, $showFrom = true) {
+	if (Configure::read('debug') > 0) {
+		$file = '';
+		$line = '';
+		if ($showFrom) {
+			$calledFrom = debug_backtrace();
+			$file = substr(str_replace(ROOT, '', $calledFrom[0]['file']), 1);
+			$line = $calledFrom[0]['line'];
+		}
+		$html = <<<HTML
 <strong>%s</strong> (line <strong>%s</strong>)
 <pre class="cake-debug">
 %s
@@ -94,32 +95,32 @@ HTML;
 ###########################
 
 TEXT;
-			$template = $html;
-			if (php_sapi_name() == 'cli') {
-				$template = $text;
-			}
-			if ($showHtml === null && $template !== $text) {
-				$showHtml = true;
-			}
-			$var = print_r($var, true);
-			if ($showHtml) {
-				$var = str_replace(array('<', '>'), array('&lt;', '&gt;'), $var);
-			}
-			printf($template, $file, $line, $var);
+		$template = $html;
+		if (php_sapi_name() == 'cli') {
+			$template = $text;
 		}
+		if ($showHtml === null && $template !== $text) {
+			$showHtml = true;
+		}
+		$var = print_r($var, true);
+		if ($showHtml) {
+			$var = str_replace(array('<', '>'), array('&lt;', '&gt;'), $var);
+		}
+		printf($template, $file, $line, $var);
 	}
+}
 
 if (!function_exists('sortByKey')) {
 
-/**
- * Sorts given $array by key $sortby.
- *
- * @param array $array Array to sort
- * @param string $sortby Sort by this key
- * @param string $order  Sort order asc/desc (ascending or descending).
- * @param integer $type Type of sorting to perform
- * @return mixed Sorted array
- */
+	/**
+	 * Sorts given $array by key $sortby.
+	 *
+	 * @param array $array Array to sort
+	 * @param string $sortby Sort by this key
+	 * @param string $order  Sort order asc/desc (ascending or descending).
+	 * @param integer $type Type of sorting to perform
+	 * @return mixed Sorted array
+	 */
 	function sortByKey(&$array, $sortby, $order = 'asc', $type = SORT_NUMERIC) {
 		if (!is_array($array)) {
 			return null;
@@ -151,27 +152,27 @@ if (!function_exists('sortByKey')) {
  * @return string Wrapped text
  * @link http://book.cakephp.org/view/1132/h
  */
-	function h($text, $double = true, $charset = null) {
-		if (is_array($text)) {
-			$texts = array();
-			foreach ($text as $k => $t) {
-				$texts[$k] = h($t, $double, $charset);
-			}
-			return $texts;
+function h($text, $double = true, $charset = null) {
+	if (is_array($text)) {
+		$texts = array();
+		foreach ($text as $k => $t) {
+			$texts[$k] = h($t, $double, $charset);
 		}
+		return $texts;
+	}
 
-		static $defaultCharset = false;
-		if ($defaultCharset === false) {
-			$defaultCharset = Configure::read('App.encoding');
-			if ($defaultCharset === null) {
-				$defaultCharset = 'UTF-8';
-			}
-		}
-		if (is_string($double)) {
-			$charset = $double;
+	static $defaultCharset = false;
+	if ($defaultCharset === false) {
+		$defaultCharset = Configure::read('App.encoding');
+		if ($defaultCharset === null) {
+			$defaultCharset = 'UTF-8';
 		}
-		return htmlspecialchars($text, ENT_QUOTES, ($charset) ? $charset : $defaultCharset, $double);
 	}
+	if (is_string($double)) {
+		$charset = $double;
+	}
+	return htmlspecialchars($text, ENT_QUOTES, ($charset) ? $charset : $defaultCharset, $double);
+}
 
 /**
  * Splits a dot syntax plugin name into its plugin and classname.
@@ -184,16 +185,16 @@ if (!function_exists('sortByKey')) {
  * @param string $plugin Optional default plugin to use if no plugin is found. Defaults to null.
  * @return array Array with 2 indexes.  0 => plugin name, 1 => classname
  */
-	function pluginSplit($name, $dotAppend = false, $plugin = null) {
-		if (strpos($name, '.') !== false) {
-			$parts = explode('.', $name, 2);
-			if ($dotAppend) {
-				$parts[0] .= '.';
-			}
-			return $parts;
+function pluginSplit($name, $dotAppend = false, $plugin = null) {
+	if (strpos($name, '.') !== false) {
+		$parts = explode('.', $name, 2);
+		if ($dotAppend) {
+			$parts[0] .= '.';
 		}
-		return array($plugin, $name);
+		return $parts;
 	}
+	return array($plugin, $name);
+}
 
 /**
  * Print_r convenience function, which prints out <PRE> tags around
@@ -203,13 +204,13 @@ if (!function_exists('sortByKey')) {
  * @param array $var Variable to print out
  * @link http://book.cakephp.org/view/1136/pr
  */
-	function pr($var) {
-		if (Configure::read('debug') > 0) {
-			echo '<pre>';
-			print_r($var);
-			echo '</pre>';
-		}
+function pr($var) {
+	if (Configure::read('debug') > 0) {
+		echo '<pre>';
+		print_r($var);
+		echo '</pre>';
 	}
+}
 
 /**
  * Merge a group of arrays
@@ -221,17 +222,17 @@ if (!function_exists('sortByKey')) {
  * @return array All array parameters merged into one
  * @link http://book.cakephp.org/view/1124/am
  */
-	function am() {
-		$r = array();
-		$args = func_get_args();
-		foreach ($args as $a) {
-			if (!is_array($a)) {
-				$a = array($a);
-			}
-			$r = array_merge($r, $a);
-		}
-		return $r;
+function am() {
+	$r = array();
+	$args = func_get_args();
+	foreach ($args as $a) {
+		if (!is_array($a)) {
+			$a = array($a);
+		}
+		$r = array_merge($r, $a);
 	}
+	return $r;
+}
 
 /**
  * Gets an environment variable from available sources, and provides emulation
@@ -243,82 +244,104 @@ if (!function_exists('sortByKey')) {
  * @return string Environment variable setting.
  * @link http://book.cakephp.org/view/1130/env
  */
-	function env($key) {
-		if ($key === 'HTTPS') {
-			if (isset($_SERVER['HTTPS'])) {
-				return (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off');
-			}
-			return (strpos(env('SCRIPT_URI'), 'https://') === 0);
+function env($key) {
+	if ($key === 'HTTPS') {
+		if (isset($_SERVER['HTTPS'])) {
+			return (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off');
 		}
+		return (strpos(env('SCRIPT_URI'), 'https://') === 0);
+	}
 
-		if ($key === 'SCRIPT_NAME') {
-			if (env('CGI_MODE') && isset($_ENV['SCRIPT_URL'])) {
-				$key = 'SCRIPT_URL';
-			}
+	if ($key === 'SCRIPT_NAME') {
+		if (env('CGI_MODE') && isset($_ENV['SCRIPT_URL'])) {
+			$key = 'SCRIPT_URL';
 		}
+	}
 
-		$val = null;
-		if (isset($_SERVER[$key])) {
-			$val = $_SERVER[$key];
-		} elseif (isset($_ENV[$key])) {
-			$val = $_ENV[$key];
-		} elseif (getenv($key) !== false) {
-			$val = getenv($key);
-		}
+	$val = null;
+	if (isset($_SERVER[$key])) {
+		$val = $_SERVER[$key];
+	} elseif (isset($_ENV[$key])) {
+		$val = $_ENV[$key];
+	} elseif (getenv($key) !== false) {
+		$val = getenv($key);
+	}
 
-		if ($key === 'REMOTE_ADDR' && $val === env('SERVER_ADDR')) {
-			$addr = env('HTTP_PC_REMOTE_ADDR');
-			if ($addr !== null) {
-				$val = $addr;
-			}
+	if ($key === 'REMOTE_ADDR' && $val === env('SERVER_ADDR')) {
+		$addr = env('HTTP_PC_REMOTE_ADDR');
+		if ($addr !== null) {
+			$val = $addr;
 		}
+	}
 
-		if ($val !== null) {
-			return $val;
-		}
+	if ($val !== null) {
+		return $val;
+	}
 
-		switch ($key) {
-			case 'SCRIPT_FILENAME':
-				if (defined('SERVER_IIS') && SERVER_IIS === true) {
-					return str_replace('\\\\', '\\', env('PATH_TRANSLATED'));
-				}
-				break;
-			case 'DOCUMENT_ROOT':
-				$name = env('SCRIPT_NAME');
-				$filename = env('SCRIPT_FILENAME');
-				$offset = 0;
-				if (!strpos($name, '.php')) {
-					$offset = 4;
-				}
-				return substr($filename, 0, strlen($filename) - (strlen($name) + $offset));
-				break;
-			case 'PHP_SELF':
-				return str_replace(env('DOCUMENT_ROOT'), '', env('SCRIPT_FILENAME'));
-				break;
-			case 'CGI_MODE':
-				return (PHP_SAPI === 'cgi');
-				break;
-			case 'HTTP_BASE':
-				$host = env('HTTP_HOST');
-				$parts = explode('.', $host);
-				$count = count($parts);
-
-				if ($count === 1) {
-					return '.' . $host;
-				} elseif ($count === 2) {
+	switch ($key) {
+		case 'SCRIPT_FILENAME':
+			if (defined('SERVER_IIS') && SERVER_IIS === true) {
+				return str_replace('\\\\', '\\', env('PATH_TRANSLATED'));
+			}
+			break;
+		case 'DOCUMENT_ROOT':
+			$name = env('SCRIPT_NAME');
+			$filename = env('SCRIPT_FILENAME');
+			$offset = 0;
+			if (!strpos($name, '.php')) {
+				$offset = 4;
+			}
+			return substr($filename, 0, strlen($filename) - (strlen($name) + $offset));
+			break;
+		case 'PHP_SELF':
+			return str_replace(env('DOCUMENT_ROOT'), '', env('SCRIPT_FILENAME'));
+			break;
+		case 'CGI_MODE':
+			return (PHP_SAPI === 'cgi');
+			break;
+		case 'HTTP_BASE':
+			$host = env('HTTP_HOST');
+			$parts = explode('.', $host);
+			$count = count($parts);
+
+			if ($count === 1) {
+				return '.' . $host;
+			} elseif ($count === 2) {
+				return '.' . $host;
+			} elseif ($count === 3) {
+				$gTLD = array(
+					'aero',
+					'asia',
+					'biz',
+					'cat',
+					'com',
+					'coop',
+					'edu',
+					'gov',
+					'info',
+					'int',
+					'jobs',
+					'mil',
+					'mobi',
+					'museum',
+					'name',
+					'net',
+					'org',
+					'pro',
+					'tel',
+					'travel',
+					'xxx'
+				);
+				if (in_array($parts[1], $gTLD)) {
 					return '.' . $host;
-				} elseif ($count === 3) {
-					$gTLD = array('aero', 'asia', 'biz', 'cat', 'com', 'coop', 'edu', 'gov', 'info', 'int', 'jobs', 'mil', 'mobi', 'museum', 'name', 'net', 'org', 'pro', 'tel', 'travel', 'xxx');
-					if (in_array($parts[1], $gTLD)) {
-						return '.' . $host;
-					}
 				}
-				array_shift($parts);
-				return '.' . implode('.', $parts);
-				break;
-		}
-		return null;
+			}
+			array_shift($parts);
+			return '.' . implode('.', $parts);
+			break;
 	}
+	return null;
+}
 
 /**
  * Reads/writes temporary data to cache files or session.
@@ -330,47 +353,47 @@ if (!function_exists('sortByKey')) {
  * @return mixed  The contents of the temporary file.
  * @deprecated Please use Cache::write() instead
  */
-	function cache($path, $data = null, $expires = '+1 day', $target = 'cache') {
-		if (Configure::read('Cache.disable')) {
-			return null;
-		}
-		$now = time();
+function cache($path, $data = null, $expires = '+1 day', $target = 'cache') {
+	if (Configure::read('Cache.disable')) {
+		return null;
+	}
+	$now = time();
 
-		if (!is_numeric($expires)) {
-			$expires = strtotime($expires, $now);
-		}
+	if (!is_numeric($expires)) {
+		$expires = strtotime($expires, $now);
+	}
 
-		switch (strtolower($target)) {
-			case 'cache':
-				$filename = CACHE . $path;
-			break;
-			case 'public':
-				$filename = WWW_ROOT . $path;
-			break;
-			case 'tmp':
-				$filename = TMP . $path;
-			break;
-		}
-		$timediff = $expires - $now;
-		$filetime = false;
+	switch (strtolower($target)) {
+		case 'cache':
+			$filename = CACHE . $path;
+		break;
+		case 'public':
+			$filename = WWW_ROOT . $path;
+		break;
+		case 'tmp':
+			$filename = TMP . $path;
+		break;
+	}
+	$timediff = $expires - $now;
+	$filetime = false;
 
-		if (file_exists($filename)) {
-			$filetime = @filemtime($filename);
-		}
+	if (file_exists($filename)) {
+		$filetime = @filemtime($filename);
+	}
 
-		if ($data === null) {
-			if (file_exists($filename) && $filetime !== false) {
-				if ($filetime + $timediff < $now) {
-					@unlink($filename);
-				} else {
-					$data = @file_get_contents($filename);
-				}
+	if ($data === null) {
+		if (file_exists($filename) && $filetime !== false) {
+			if ($filetime + $timediff < $now) {
+				@unlink($filename);
+			} else {
+				$data = @file_get_contents($filename);
 			}
-		} elseif (is_writable(dirname($filename))) {
-			@file_put_contents($filename, $data);
 		}
-		return $data;
+	} elseif (is_writable(dirname($filename))) {
+		@file_put_contents($filename, $data);
 	}
+	return $data;
+}
 
 /**
  * Used to delete files in the cache directories, or clear contents of cache directories
@@ -382,57 +405,57 @@ if (!function_exists('sortByKey')) {
  * @param string $ext The file extension you are deleting
  * @return true if files found and deleted false otherwise
  */
-	function clearCache($params = null, $type = 'views', $ext = '.php') {
-		if (is_string($params) || $params === null) {
-			$params = preg_replace('/\/\//', '/', $params);
-			$cache = CACHE . $type . DS . $params;
+function clearCache($params = null, $type = 'views', $ext = '.php') {
+	if (is_string($params) || $params === null) {
+		$params = preg_replace('/\/\//', '/', $params);
+		$cache = CACHE . $type . DS . $params;
 
-			if (is_file($cache . $ext)) {
-				@unlink($cache . $ext);
-				return true;
-			} elseif (is_dir($cache)) {
-				$files = glob($cache . '*');
+		if (is_file($cache . $ext)) {
+			@unlink($cache . $ext);
+			return true;
+		} elseif (is_dir($cache)) {
+			$files = glob($cache . '*');
 
-				if ($files === false) {
-					return false;
-				}
+			if ($files === false) {
+				return false;
+			}
 
-				foreach ($files as $file) {
-					if (is_file($file) && strrpos($file, DS . 'empty') !== strlen($file) - 6) {
-						@unlink($file);
-					}
-				}
-				return true;
-			} else {
-				$cache = array(
-					CACHE . $type . DS . '*' . $params . $ext,
-					CACHE . $type . DS . '*' . $params . '_*' . $ext
-				);
-				$files = array();
-				while ($search = array_shift($cache)) {
-					$results = glob($search);
-					if ($results !== false) {
-						$files = array_merge($files, $results);
-					}
+			foreach ($files as $file) {
+				if (is_file($file) && strrpos($file, DS . 'empty') !== strlen($file) - 6) {
+					@unlink($file);
 				}
-				if (empty($files)) {
-					return false;
-				}
-				foreach ($files as $file) {
-					if (is_file($file) && strrpos($file, DS . 'empty') !== strlen($file) - 6) {
-						@unlink($file);
-					}
+			}
+			return true;
+		} else {
+			$cache = array(
+				CACHE . $type . DS . '*' . $params . $ext,
+				CACHE . $type . DS . '*' . $params . '_*' . $ext
+			);
+			$files = array();
+			while ($search = array_shift($cache)) {
+				$results = glob($search);
+				if ($results !== false) {
+					$files = array_merge($files, $results);
 				}
-				return true;
 			}
-		} elseif (is_array($params)) {
-			foreach ($params as $file) {
-				clearCache($file, $type, $ext);
+			if (empty($files)) {
+				return false;
+			}
+			foreach ($files as $file) {
+				if (is_file($file) && strrpos($file, DS . 'empty') !== strlen($file) - 6) {
+					@unlink($file);
+				}
 			}
 			return true;
 		}
-		return false;
+	} elseif (is_array($params)) {
+		foreach ($params as $file) {
+			clearCache($file, $type, $ext);
+		}
+		return true;
 	}
+	return false;
+}
 
 /**
  * Recursively strips slashes from all values in an array
@@ -441,16 +464,16 @@ if (!function_exists('sortByKey')) {
  * @return mixed What is returned from calling stripslashes
  * @link http://book.cakephp.org/view/1138/stripslashes_deep
  */
-	function stripslashes_deep($values) {
-		if (is_array($values)) {
-			foreach ($values as $key => $value) {
-				$values[$key] = stripslashes_deep($value);
-			}
-		} else {
-			$values = stripslashes($values);
+function stripslashes_deep($values) {
+	if (is_array($values)) {
+		foreach ($values as $key => $value) {
+			$values[$key] = stripslashes_deep($value);
 		}
-		return $values;
+	} else {
+		$values = stripslashes($values);
 	}
+	return $values;
+}
 
 /**
  * Returns a translated string if one is found; Otherwise, the submitted message.
@@ -460,20 +483,20 @@ if (!function_exists('sortByKey')) {
  * @return mixed translated string
  * @link http://book.cakephp.org/view/1121/__
  */
-	function __($singular, $args = null) {
-		if (!$singular) {
-			return;
-		}
+function __($singular, $args = null) {
+	if (!$singular) {
+		return;
+	}
 
-		App::uses('I18n', 'I18n');
-		$translated = I18n::translate($singular);
-		if ($args === null) {
-			return $translated;
-		} elseif (!is_array($args)) {
-			$args = array_slice(func_get_args(), 1);
-		}
-		return vsprintf($translated, $args);
+	App::uses('I18n', 'I18n');
+	$translated = I18n::translate($singular);
+	if ($args === null) {
+		return $translated;
+	} elseif (!is_array($args)) {
+		$args = array_slice(func_get_args(), 1);
 	}
+	return vsprintf($translated, $args);
+}
 
 /**
  * Returns correct plural form of message identified by $singular and $plural for count $count.
@@ -485,20 +508,20 @@ if (!function_exists('sortByKey')) {
  * @param mixed $args Array with arguments or multiple arguments in function
  * @return mixed plural form of translated string
  */
-	function __n($singular, $plural, $count, $args = null) {
-		if (!$singular) {
-			return;
-		}
+function __n($singular, $plural, $count, $args = null) {
+	if (!$singular) {
+		return;
+	}
 
-		App::uses('I18n', 'I18n');
-		$translated = I18n::translate($singular, $plural, null, 6, $count);
-		if ($args === null) {
-			return $translated;
-		} elseif (!is_array($args)) {
-			$args = array_slice(func_get_args(), 3);
-		}
-		return vsprintf($translated, $args);
+	App::uses('I18n', 'I18n');
+	$translated = I18n::translate($singular, $plural, null, 6, $count);
+	if ($args === null) {
+		return $translated;
+	} elseif (!is_array($args)) {
+		$args = array_slice(func_get_args(), 3);
 	}
+	return vsprintf($translated, $args);
+}
 
 /**
  * Allows you to override the current domain for a single message lookup.
@@ -508,19 +531,19 @@ if (!function_exists('sortByKey')) {
  * @param mixed $args Array with arguments or multiple arguments in function
  * @return translated string
  */
-	function __d($domain, $msg, $args = null) {
-		if (!$msg) {
-			return;
-		}
-		App::uses('I18n', 'I18n');
-		$translated = I18n::translate($msg, null, $domain);
-		if ($args === null) {
-			return $translated;
-		} elseif (!is_array($args)) {
-			$args = array_slice(func_get_args(), 2);
-		}
-		return vsprintf($translated, $args);
+function __d($domain, $msg, $args = null) {
+	if (!$msg) {
+		return;
+	}
+	App::uses('I18n', 'I18n');
+	$translated = I18n::translate($msg, null, $domain);
+	if ($args === null) {
+		return $translated;
+	} elseif (!is_array($args)) {
+		$args = array_slice(func_get_args(), 2);
 	}
+	return vsprintf($translated, $args);
+}
 
 /**
  * Allows you to override the current domain for a single plural message lookup.
@@ -534,19 +557,19 @@ if (!function_exists('sortByKey')) {
  * @param mixed $args Array with arguments or multiple arguments in function
  * @return plural form of translated string
  */
-	function __dn($domain, $singular, $plural, $count, $args = null) {
-		if (!$singular) {
-			return;
-		}
-		App::uses('I18n', 'I18n');
-		$translated = I18n::translate($singular, $plural, $domain, 6, $count);
-		if ($args === null) {
-			return $translated;
-		} elseif (!is_array($args)) {
-			$args = array_slice(func_get_args(), 4);
-		}
-		return vsprintf($translated, $args);
+function __dn($domain, $singular, $plural, $count, $args = null) {
+	if (!$singular) {
+		return;
+	}
+	App::uses('I18n', 'I18n');
+	$translated = I18n::translate($singular, $plural, $domain, 6, $count);
+	if ($args === null) {
+		return $translated;
+	} elseif (!is_array($args)) {
+		$args = array_slice(func_get_args(), 4);
 	}
+	return vsprintf($translated, $args);
+}
 
 /**
  * Allows you to override the current domain for a single message lookup.
@@ -571,19 +594,19 @@ if (!function_exists('sortByKey')) {
  * @param mixed $args Array with arguments or multiple arguments in function
  * @return translated string
  */
-	function __dc($domain, $msg, $category, $args = null) {
-		if (!$msg) {
-			return;
-		}
-		App::uses('I18n', 'I18n');
-		$translated = I18n::translate($msg, null, $domain, $category);
-		if ($args === null) {
-			return $translated;
-		} elseif (!is_array($args)) {
-			$args = array_slice(func_get_args(), 3);
-		}
-		return vsprintf($translated, $args);
+function __dc($domain, $msg, $category, $args = null) {
+	if (!$msg) {
+		return;
+	}
+	App::uses('I18n', 'I18n');
+	$translated = I18n::translate($msg, null, $domain, $category);
+	if ($args === null) {
+		return $translated;
+	} elseif (!is_array($args)) {
+		$args = array_slice(func_get_args(), 3);
 	}
+	return vsprintf($translated, $args);
+}
 
 /**
  * Allows you to override the current domain for a single plural message lookup.
@@ -612,19 +635,19 @@ if (!function_exists('sortByKey')) {
  * @param mixed $args Array with arguments or multiple arguments in function
  * @return plural form of translated string
  */
-	function __dcn($domain, $singular, $plural, $count, $category, $args = null) {
-		if (!$singular) {
-			return;
-		}
-		App::uses('I18n', 'I18n');
-		$translated = I18n::translate($singular, $plural, $domain, $category, $count);
-		if ($args === null) {
-			return $translated;
-		} elseif (!is_array($args)) {
-			$args = array_slice(func_get_args(), 5);
-		}
-		return vsprintf($translated, $args);
+function __dcn($domain, $singular, $plural, $count, $category, $args = null) {
+	if (!$singular) {
+		return;
+	}
+	App::uses('I18n', 'I18n');
+	$translated = I18n::translate($singular, $plural, $domain, $category, $count);
+	if ($args === null) {
+		return $translated;
+	} elseif (!is_array($args)) {
+		$args = array_slice(func_get_args(), 5);
 	}
+	return vsprintf($translated, $args);
+}
 
 /**
  * The category argument allows a specific category of the locale settings to be used for fetching a message.
@@ -645,31 +668,31 @@ if (!function_exists('sortByKey')) {
  * @param mixed $args Array with arguments or multiple arguments in function
  * @return translated string
  */
-	function __c($msg, $category, $args = null) {
-		if (!$msg) {
-			return;
-		}
-		App::uses('I18n', 'I18n');
-		$translated = I18n::translate($msg, null, null, $category);
-		if ($args === null) {
-			return $translated;
-		} elseif (!is_array($args)) {
-			$args = array_slice(func_get_args(), 2);
-		}
-		return vsprintf($translated, $args);
+function __c($msg, $category, $args = null) {
+	if (!$msg) {
+		return;
+	}
+	App::uses('I18n', 'I18n');
+	$translated = I18n::translate($msg, null, null, $category);
+	if ($args === null) {
+		return $translated;
+	} elseif (!is_array($args)) {
+		$args = array_slice(func_get_args(), 2);
 	}
+	return vsprintf($translated, $args);
+}
 
 /**
  * Shortcut to Log::write.
  *
  * @param string $message Message to write to log
  */
-	function LogError($message) {
-		App::uses('CakeLog', 'Log');
-		$bad = array("\n", "\r", "\t");
-		$good = ' ';
-		CakeLog::write('error', str_replace($bad, $good, $message));
-	}
+function LogError($message) {
+	App::uses('CakeLog', 'Log');
+	$bad = array("\n", "\r", "\t");
+	$good = ' ';
+	CakeLog::write('error', str_replace($bad, $good, $message));
+}
 
 /**
  * Searches include path for files.
@@ -678,19 +701,19 @@ if (!function_exists('sortByKey')) {
  * @return Full path to file if exists, otherwise false
  * @link http://book.cakephp.org/view/1131/fileExistsInPath
  */
-	function fileExistsInPath($file) {
-		$paths = explode(PATH_SEPARATOR, ini_get('include_path'));
-		foreach ($paths as $path) {
-			$fullPath = $path . DS . $file;
-
-			if (file_exists($fullPath)) {
-				return $fullPath;
-			} elseif (file_exists($file)) {
-				return $file;
-			}
+function fileExistsInPath($file) {
+	$paths = explode(PATH_SEPARATOR, ini_get('include_path'));
+	foreach ($paths as $path) {
+		$fullPath = $path . DS . $file;
+
+		if (file_exists($fullPath)) {
+			return $fullPath;
+		} elseif (file_exists($file)) {
+			return $file;
 		}
-		return false;
 	}
+	return false;
+}
 
 /**
  * Convert forward slashes to underscores and removes first and last underscores in a string
@@ -699,9 +722,9 @@ if (!function_exists('sortByKey')) {
  * @return string with underscore remove from start and end of string
  * @link http://book.cakephp.org/view/1126/convertSlash
  */
-	function convertSlash($string) {
-		$string = trim($string, '/');
-		$string = preg_replace('/\/\//', '/', $string);
-		$string = str_replace('/', '_', $string);
-		return $string;
-	}
+function convertSlash($string) {
+	$string = trim($string, '/');
+	$string = preg_replace('/\/\//', '/', $string);
+	$string = str_replace('/', '_', $string);
+	return $string;
+}

+ 32 - 0
lib/Cake/tests/Case/Controller/Component/RequestHandlerComponentTest.php

@@ -292,6 +292,7 @@ class RequestHandlerComponentTest extends CakeTestCase {
 	function testStartupCallback() {
 		$_SERVER['REQUEST_METHOD'] = 'PUT';
 		$_SERVER['CONTENT_TYPE'] = 'application/xml';
+		$this->Controller->request = $this->getMock('CakeRequest', array('_readStdin'));
 		$this->RequestHandler->startup($this->Controller);
 		$this->assertTrue(is_array($this->Controller->data));
 		$this->assertFalse(is_object($this->Controller->data));
@@ -305,12 +306,36 @@ class RequestHandlerComponentTest extends CakeTestCase {
 	function testStartupCallbackCharset() {
 		$_SERVER['REQUEST_METHOD'] = 'PUT';
 		$_SERVER['CONTENT_TYPE'] = 'application/xml; charset=UTF-8';
+		$this->Controller->request = $this->getMock('CakeRequest', array('_readStdin'));
 		$this->RequestHandler->startup($this->Controller);
 		$this->assertTrue(is_array($this->Controller->data));
 		$this->assertFalse(is_object($this->Controller->data));
 	}
 
 /**
+ * Test mapping a new type and having startup process it.
+ *
+ * @return void
+ */
+	function testStartupCustomTypeProcess() {
+		if (!function_exists('str_getcsv')) {
+			$this->markTestSkipped('Need "str_getcsv" for this test.');
+		}
+		$_SERVER['REQUEST_METHOD'] = 'POST';
+		$_SERVER['CONTENT_TYPE'] = 'text/csv';
+		$this->Controller->request = $this->getMock('CakeRequest', array('_readStdin'));
+		$this->Controller->request->expects($this->once())
+			->method('_readStdin')
+			->will($this->returnValue('"A","csv","string"'));
+		$this->RequestHandler->addInputType('csv', array('str_getcsv'));
+		$this->RequestHandler->startup($this->Controller);
+		$expected = array(
+			'A', 'csv', 'string'
+		);
+		$this->assertEquals($expected, $this->Controller->request->data);
+	}
+
+/**
  * testNonAjaxRedirect method
  *
  * @access public
@@ -774,4 +799,11 @@ class RequestHandlerComponentTest extends CakeTestCase {
 		$result = ob_get_clean();
 	}
 
+/**
+ * @expectedException CakeException
+ * @return void
+ */
+	function testAddInputTypeException() {
+		$this->RequestHandler->addInputType('csv', array('I am not callable'));
+	}
 }

+ 47 - 7
lib/Cake/tests/Case/Core/AppTest.php

@@ -22,9 +22,17 @@ class AppImportTest extends CakeTestCase {
 		$this->assertEqual($expected, $old);
 
 		App::build(array('Model' => array('/path/to/models/')));
-
 		$new = App::path('Model');
+		$expected = array(
+			'/path/to/models/',
+			APP . 'Model' . DS,
+			APP . 'models' . DS
+		);
+		$this->assertEqual($expected, $new);
 
+		App::build();
+		App::build(array('Model' => array('/path/to/models/')), App::PREPEND);
+		$new = App::path('Model');
 		$expected = array(
 			'/path/to/models/',
 			APP . 'Model' . DS,
@@ -32,6 +40,36 @@ class AppImportTest extends CakeTestCase {
 		);
 		$this->assertEqual($expected, $new);
 
+		App::build();
+		App::build(array('Model' => array('/path/to/models/')), App::APPEND);
+		$new = App::path('Model');
+		$expected = array(
+			APP . 'Model' . DS,
+			APP . 'models' . DS,
+			'/path/to/models/'
+		);
+		$this->assertEqual($expected, $new);
+
+		App::build();
+		App::build(array(
+			'Model' => array('/path/to/models/'),
+			'Controller' => array('/path/to/controllers/'),
+		), App::APPEND);
+		$new = App::path('Model');
+		$expected = array(
+			APP . 'Model' . DS,
+			APP . 'models' . DS,
+			'/path/to/models/'
+		);
+		$this->assertEqual($expected, $new);
+		$new = App::path('Controller');
+		$expected = array(
+			APP . 'Controller' . DS,
+			APP . 'controllers' . DS,
+			'/path/to/controllers/'
+		);
+		$this->assertEqual($expected, $new);
+
 		App::build(); //reset defaults
 		$defaults = App::path('Model');
 		$this->assertEqual($old, $defaults);
@@ -152,7 +190,7 @@ class AppImportTest extends CakeTestCase {
 		);
 		$this->assertEqual($expected, $old);
 
-		App::build(array('Model' => array('/path/to/models/')), true);
+		App::build(array('Model' => array('/path/to/models/')), App::RESET);
 
 		$new = App::path('Model');
 
@@ -210,7 +248,7 @@ class AppImportTest extends CakeTestCase {
 			'View' => App::core('View'),
 			'Model' => App::core('Model'),
 			'View/Helper' => App::core('View/Helper'),
-		), true);
+		), App::RESET);
 		$result = App::objects('behavior', null, false);
 		$this->assertTrue(in_array('TreeBehavior', $result));
 		$result = App::objects('Model/Behavior', null, false);
@@ -285,9 +323,11 @@ class AppImportTest extends CakeTestCase {
 		$this->assertTrue(in_array('TestPluginPersisterOne', $result));
 
 		$result = App::objects('TestPlugin.helper');
+		sort($result);
 		$expected = array('OtherHelperHelper', 'PluggedHelper', 'TestPluginApp');
 		$this->assertEquals($result, $expected);
 		$result = App::objects('TestPlugin.View/Helper');
+		sort($result);
 		$expected = array('OtherHelperHelper', 'PluggedHelper', 'TestPluginApp');
 		$this->assertEquals($result, $expected);
 
@@ -462,7 +502,7 @@ class AppImportTest extends CakeTestCase {
 		$result = App::import('Helper', 'TestPlugin.OtherHelper');
 		$this->assertTrue($result);
 		$this->assertTrue(class_exists('OtherHelperHelper'));
-		
+
 		$result = App::import('Helper', 'TestPlugin.TestPluginApp');
 		$this->assertTrue($result);
 		$this->assertTrue(class_exists('TestPluginAppHelper'));
@@ -470,7 +510,7 @@ class AppImportTest extends CakeTestCase {
 		$result = App::import('Datasource', 'TestPlugin.TestSource');
 		$this->assertTrue($result);
 		$this->assertTrue(class_exists('TestSource'));
-		
+
 		App::build();
 	}
 
@@ -621,7 +661,7 @@ class AppImportTest extends CakeTestCase {
 		App::build(array(
 			'plugins' => array(LIBS . 'tests' . DS . 'test_app' . DS . 'plugins' . DS),
 			'vendors' => array(LIBS . 'tests' . DS . 'test_app' . DS . 'vendors'. DS),
-		), true);
+		), App::RESET);
 
 		ob_start();
 		$result = App::import('Vendor', 'css/TestAsset', array('ext' => 'css'));
@@ -677,7 +717,7 @@ class AppImportTest extends CakeTestCase {
 		App::build(array(
 			'libs' => array(LIBS . 'tests' . DS . 'test_app' . DS . 'libs' . DS),
 			'plugins' => array(LIBS . 'tests' . DS . 'test_app' . DS . 'plugins' . DS)
-		), true);
+		), App::RESET);
 
 		$this->assertFalse(class_exists('CustomLibClass', false));
 		App::uses('CustomLibClass', 'TestPlugin.Custom/Package');

+ 56 - 2
lib/Cake/tests/Case/Network/CakeRequestTest.php

@@ -18,6 +18,7 @@
  */
 
 App::uses('Dispatcher', 'Routing');
+App::uses('Xml', 'Utility');
 App::uses('CakeRequest', 'Network');
 
 class CakeRequestTestCase extends CakeTestCase {
@@ -160,7 +161,7 @@ class CakeRequestTestCase extends CakeTestCase {
 
 		$_POST = array('one' => 1, 'two' => 'three');
 		$request = new CakeRequest('some/path');
-		$this->assertEqual($request->params['form'], $_POST);
+		$this->assertEquals($_POST, $request->data);
 	}
 
 /**
@@ -1435,6 +1436,59 @@ class CakeRequestTestCase extends CakeTestCase {
 	}
 
 /**
+ * Test the input() method.
+ *
+ * @return void
+ */
+	function testInput() {
+		$request = $this->getMock('CakeRequest', array('_readStdin'));
+		$request->expects($this->once())->method('_readStdin')
+			->will($this->returnValue('I came from stdin'));
+		
+		$result = $request->input();
+		$this->assertEquals('I came from stdin', $result);
+	}
+
+/**
+ * Test input() decoding.
+ *
+ * @return void
+ */
+	function testInputDecode() {
+		$request = $this->getMock('CakeRequest', array('_readStdin'));
+		$request->expects($this->once())->method('_readStdin')
+			->will($this->returnValue('{"name":"value"}'));
+
+		$result = $request->input('json_decode');
+		$this->assertEquals(array('name' => 'value'), (array)$result);
+	}
+
+/** 
+ * Test input() decoding with additional arguments.
+ *
+ * @return void
+ */
+	function testInputDecodeExtraParams() {
+		$xml = <<<XML
+<?xml version="1.0" encoding="utf-8"?>
+<post>
+	<title id="title">Test</title>
+</post>
+XML;
+
+		$request = $this->getMock('CakeRequest', array('_readStdin'));
+		$request->expects($this->once())->method('_readStdin')
+			->will($this->returnValue($xml));
+
+		$result = $request->input('Xml::build', array('return' => 'domdocument'));
+		$this->assertInstanceOf('DOMDocument', $result);
+		$this->assertEquals(
+			'Test', 
+			$result->getElementsByTagName('title')->item(0)->childNodes->item(0)->wholeText
+		);
+	}
+
+/**
  * loadEnvironment method
  *
  * @param mixed $env
@@ -1465,4 +1519,4 @@ class CakeRequestTestCase extends CakeTestCase {
 		}
 	}
 
-}
+}

+ 15 - 9
lib/Cake/tests/Case/Routing/DispatcherTest.php

@@ -585,8 +585,7 @@ class DispatcherTest extends CakeTestCase {
 		$Dispatcher = new Dispatcher();
 
 		$test = $Dispatcher->parseParams(new CakeRequest("/"));
-		$this->assertFalse(empty($test['form']), "Parsed URL not returning post data");
-		$this->assertEquals($test['form']['testdata'], "My Posted Content");
+		$this->assertEquals($test['data']['testdata'], "My Posted Content");
 	}
 
 /**
@@ -868,7 +867,7 @@ class DispatcherTest extends CakeTestCase {
 		$expected = array(
 			'pass' => array('home'),
 			'named' => array('param'=> 'value', 'param2'=> 'value2'), 'plugin'=> 'my_plugin',
-			'controller'=> 'some_pages', 'action'=> 'display', 'form'=> array(),
+			'controller'=> 'some_pages', 'action'=> 'display'
 		);
 		foreach ($expected as $key => $value) {
 			$this->assertEqual($result[$key], $value, 'Value mismatch ' . $key . ' %');
@@ -1000,7 +999,6 @@ class DispatcherTest extends CakeTestCase {
 			'action' => 'admin_index',
 			'prefix' => 'admin',
 			'admin' =>  true,
-			'form' => array(), 
 			'return' => 1
 		);
 		foreach ($expected as $key => $value) {
@@ -1524,7 +1522,7 @@ class DispatcherTest extends CakeTestCase {
 		$dispatcher = new Dispatcher();
 
 		$result = $dispatcher->parseParams(new CakeRequest('/posts'));
-		$expected = array('pass' => array(), 'named' => array(), 'plugin' => null, 'controller' => 'posts', 'action' => 'add', '[method]' => 'POST', 'form' => array());
+		$expected = array('pass' => array(), 'named' => array(), 'plugin' => null, 'controller' => 'posts', 'action' => 'add', '[method]' => 'POST');
 		foreach ($expected as $key => $value) {
 			$this->assertEqual($result[$key], $value, 'Value mismatch for ' . $key . ' %s');
 		}
@@ -1533,7 +1531,15 @@ class DispatcherTest extends CakeTestCase {
 		$_SERVER['HTTP_X_HTTP_METHOD_OVERRIDE'] = 'PUT';
 
 		$result = $dispatcher->parseParams(new CakeRequest('/posts/5'));
-		$expected = array('pass' => array('5'), 'named' => array(), 'id' => '5', 'plugin' => null, 'controller' => 'posts', 'action' => 'edit', '[method]' => 'PUT', 'form' => array());
+		$expected = array(
+			'pass' => array('5'),
+			'named' => array(),
+			'id' => '5',
+			'plugin' => null,
+			'controller' => 'posts',
+			'action' => 'edit',
+			'[method]' => 'PUT'
+		);
 		foreach ($expected as $key => $value) {
 			$this->assertEqual($result[$key], $value, 'Value mismatch for ' . $key . ' %s');
 		}
@@ -1542,7 +1548,7 @@ class DispatcherTest extends CakeTestCase {
 		$_SERVER['REQUEST_METHOD'] = 'GET';
 
 		$result = $dispatcher->parseParams(new CakeRequest('/posts/5'));
-		$expected = array('pass' => array('5'), 'named' => array(), 'id' => '5', 'plugin' => null, 'controller' => 'posts', 'action' => 'view', '[method]' => 'GET', 'form' => array());
+		$expected = array('pass' => array('5'), 'named' => array(), 'id' => '5', 'plugin' => null, 'controller' => 'posts', 'action' => 'view', '[method]' => 'GET');
 		foreach ($expected as $key => $value) {
 			$this->assertEqual($result[$key], $value, 'Value mismatch for ' . $key . ' %s');
 		}
@@ -1550,7 +1556,7 @@ class DispatcherTest extends CakeTestCase {
 		$_POST['_method'] = 'PUT';
 
 		$result = $dispatcher->parseParams(new CakeRequest('/posts/5'));
-		$expected = array('pass' => array('5'), 'named' => array(), 'id' => '5', 'plugin' => null, 'controller' => 'posts', 'action' => 'edit', '[method]' => 'PUT', 'form' => array());
+		$expected = array('pass' => array('5'), 'named' => array(), 'id' => '5', 'plugin' => null, 'controller' => 'posts', 'action' => 'edit', '[method]' => 'PUT');
 		foreach ($expected as $key => $value) {
 			$this->assertEqual($result[$key], $value, 'Value mismatch for ' . $key . ' %s');
 		}
@@ -1563,7 +1569,7 @@ class DispatcherTest extends CakeTestCase {
 		$result = $dispatcher->parseParams(new CakeRequest('/posts'));
 		$expected = array(
 			'pass' => array(), 'named' => array(), 'plugin' => null, 'controller' => 'posts', 'action' => 'add',
-			'[method]' => 'POST', 'form' => array('extra' => 'data'), 'data' => array('Post' => array('title' => 'New Post')),
+			'[method]' => 'POST', 'data' => array('extra' => 'data', 'Post' => array('title' => 'New Post')),
 		);
 		foreach ($expected as $key => $value) {
 			$this->assertEqual($result[$key], $value, 'Value mismatch for ' . $key . ' %s');

+ 2 - 2
lib/Cake/tests/Case/Routing/RouterTest.php

@@ -2164,7 +2164,7 @@ class RouterTest extends CakeTestCase {
 
 		$expected = array(
 			'plugin' => null, 'controller' => false, 'action' => false,
-			'param1' => '1', 'param2' => '2', 'form' => array()
+			'param1' => '1', 'param2' => '2'
 		);
 		$this->assertEqual(Router::getParams(), $expected);
 		$this->assertEqual(Router::getParam('controller'), false);
@@ -2175,7 +2175,7 @@ class RouterTest extends CakeTestCase {
 
 		$params = array('controller' => 'pages', 'action' => 'display');
 		Router::setRequestInfo(array($params, $paths));
-		$expected = array('plugin' => null, 'controller' => 'pages', 'action' => 'display', 'form' => array());
+		$expected = array('plugin' => null, 'controller' => 'pages', 'action' => 'display');
 		$this->assertEqual(Router::getParams(), $expected);
 		$this->assertEqual(Router::getParams(true), $expected);
 	}