Merge branch 'master' into 2.5

Conflicts:
	CONTRIBUTING.md
	lib/Cake/Model/Model.php
	lib/Cake/VERSION.txt
This commit is contained in:
ADmad 2013-10-30 02:34:09 +05:30
commit d9ca148499
73 changed files with 688 additions and 539 deletions

View file

@ -63,11 +63,11 @@ Check the [cakephp-codesniffer](https://github.com/cakephp/cakephp-codesniffer)
repository to setup the CakePHP standard. The README contains installation info repository to setup the CakePHP standard. The README contains installation info
for the sniff and phpcs. for the sniff and phpcs.
# Additional Resources # Additional Resources
* [CakePHP coding standards](http://book.cakephp.org/2.0/en/contributing/cakephp-coding-conventions.html) * [CakePHP coding standards](http://book.cakephp.org/2.0/en/contributing/cakephp-coding-conventions.html)
* [Existing issues](https://github.com/cakephp/cakephp/issues) * [Existing issues](https://github.com/cakephp/cakephp/issues)
* [Development Roadmaps](https://github.com/cakephp/cakephp/wiki#roadmaps)
* [General GitHub documentation](https://help.github.com/) * [General GitHub documentation](https://help.github.com/)
* [GitHub pull request documentation](https://help.github.com/send-pull-requests/) * [GitHub pull request documentation](https://help.github.com/send-pull-requests/)
* #cakephp IRC channel on freenode.org * #cakephp IRC channel on freenode.org

View file

@ -36,6 +36,8 @@ Get Support!
[GitHub Issues](https://github.com/cakephp/cakephp/issues) - Got issues? Please tell us! [GitHub Issues](https://github.com/cakephp/cakephp/issues) - Got issues? Please tell us!
[Roadmaps](https://github.com/cakephp/cakephp/wiki#roadmaps) - Want to contribute? Get involved!
[![Bake Status](https://secure.travis-ci.org/cakephp/cakephp.png?branch=master)](http://travis-ci.org/cakephp/cakephp) [![Bake Status](https://secure.travis-ci.org/cakephp/cakephp.png?branch=master)](http://travis-ci.org/cakephp/cakephp)
![Cake Power](https://raw.github.com/cakephp/cakephp/master/lib/Cake/Console/Templates/skel/webroot/img/cake.power.gif) ![Cake Power](https://raw.github.com/cakephp/cakephp/master/lib/Cake/Console/Templates/skel/webroot/img/cake.power.gif)

View file

@ -1,9 +1,5 @@
<?php <?php
/** /**
* This is core configuration file.
*
* Use it to configure core behaviour of CakePHP.
*
* PHP 5 * PHP 5
* *
* CakePHP(tm) : Rapid Development Framework (http://cakephp.org) * CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
@ -18,8 +14,11 @@
* @package app.Config * @package app.Config
* @since CakePHP(tm) v 0.2.9 * @since CakePHP(tm) v 0.2.9
* @license http://www.opensource.org/licenses/mit-license.php MIT License * @license http://www.opensource.org/licenses/mit-license.php MIT License
* */
/**
* Database configuration class. * Database configuration class.
*
* You can specify multiple configurations for production, development and testing. * You can specify multiple configurations for production, development and testing.
* *
* datasource => The name of a supported datasource; valid options are as follows: * datasource => The name of a supported datasource; valid options are as follows:
@ -43,7 +42,8 @@
* on a per-table basis with the Model::$tablePrefix property. * on a per-table basis with the Model::$tablePrefix property.
* *
* schema => * schema =>
* For Postgres/Sqlserver specifies which schema you would like to use the tables in. Postgres defaults to 'public'. For Sqlserver, it defaults to empty and use * For Postgres/Sqlserver specifies which schema you would like to use the tables in.
* Postgres defaults to 'public'. For Sqlserver, it defaults to empty and use
* the connected user's default schema (typically 'dbo'). * the connected user's default schema (typically 'dbo').
* *
* encoding => * encoding =>

View file

@ -1,9 +1,5 @@
<?php <?php
/** /**
* This is email configuration file.
*
* Use it to configure email transports of CakePHP.
*
* PHP 5 * PHP 5
* *
* CakePHP(tm) : Rapid Development Framework (http://cakephp.org) * CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
@ -18,6 +14,12 @@
* @package app.Config * @package app.Config
* @since CakePHP(tm) v 2.0.0 * @since CakePHP(tm) v 2.0.0
* @license http://www.opensource.org/licenses/mit-license.php MIT License * @license http://www.opensource.org/licenses/mit-license.php MIT License
*/
/**
* This is email configuration file.
*
* Use it to configure email transports of CakePHP.
* *
* Email configuration class. * Email configuration class.
* You can specify multiple configurations for production, development and testing. * You can specify multiple configurations for production, development and testing.

View file

@ -18,6 +18,7 @@
* @since CakePHP(tm) v 2.0 * @since CakePHP(tm) v 2.0
* @license http://www.opensource.org/licenses/mit-license.php MIT License * @license http://www.opensource.org/licenses/mit-license.php MIT License
*/ */
$ds = DIRECTORY_SEPARATOR; $ds = DIRECTORY_SEPARATOR;
$dispatcher = 'Cake' . $ds . 'Console' . $ds . 'ShellDispatcher.php'; $dispatcher = 'Cake' . $ds . 'Console' . $ds . 'ShellDispatcher.php';
@ -29,7 +30,7 @@ if (function_exists('ini_set')) {
ini_set('include_path', $root . $ds . 'lib' . PATH_SEPARATOR . ini_get('include_path')); ini_set('include_path', $root . $ds . 'lib' . PATH_SEPARATOR . ini_get('include_path'));
} }
if (!include ($dispatcher)) { if (!include $dispatcher) {
trigger_error('Could not locate CakePHP core files.', E_USER_ERROR); trigger_error('Could not locate CakePHP core files.', E_USER_ERROR);
} }
unset($paths, $path, $dispatcher, $root, $ds); unset($paths, $path, $dispatcher, $root, $ds);

View file

@ -144,7 +144,7 @@ if (isset($filePresent)):
echo '<span class="notice">'; echo '<span class="notice">';
echo __d('cake_dev', 'DebugKit is not installed. It will help you inspect and debug different aspects of your application.'); echo __d('cake_dev', 'DebugKit is not installed. It will help you inspect and debug different aspects of your application.');
echo '<br/>'; echo '<br/>';
echo __d('cake_dev', 'You can install it from %s', $this->Html->link('github', 'https://github.com/cakephp/debug_kit')); echo __d('cake_dev', 'You can install it from %s', $this->Html->link('GitHub', 'https://github.com/cakephp/debug_kit'));
echo '</span>'; echo '</span>';
endif; endif;
?> ?>
@ -194,7 +194,7 @@ You can also add some CSS styles for your pages at: %s.',
</ul> </ul>
</p> </p>
<h3><?php echo __d('cake_dev', 'More about Cake'); ?></h3> <h3><?php echo __d('cake_dev', 'More about CakePHP'); ?></h3>
<p> <p>
<?php echo __d('cake_dev', 'CakePHP is a rapid development framework for PHP which uses commonly known design patterns like Active Record, Association Data Mapping, Front Controller and MVC.'); ?> <?php echo __d('cake_dev', 'CakePHP is a rapid development framework for PHP which uses commonly known design patterns like Active Record, Association Data Mapping, Front Controller and MVC.'); ?>
</p> </p>
@ -203,24 +203,32 @@ You can also add some CSS styles for your pages at: %s.',
</p> </p>
<ul> <ul>
<li><a href="http://cakefoundation.org/"><?php echo __d('cake_dev', 'Cake Software Foundation'); ?> </a> <li><a href="http://cakephp.org">CakePHP</a>
<ul><li><?php echo __d('cake_dev', 'Promoting development related to CakePHP'); ?></li></ul></li>
<li><a href="http://www.cakephp.org">CakePHP</a>
<ul><li><?php echo __d('cake_dev', 'The Rapid Development Framework'); ?></li></ul></li> <ul><li><?php echo __d('cake_dev', 'The Rapid Development Framework'); ?></li></ul></li>
<li><a href="http://book.cakephp.org"><?php echo __d('cake_dev', 'CakePHP Documentation'); ?> </a> <li><a href="http://book.cakephp.org"><?php echo __d('cake_dev', 'CakePHP Documentation'); ?> </a>
<ul><li><?php echo __d('cake_dev', 'Your Rapid Development Cookbook'); ?></li></ul></li> <ul><li><?php echo __d('cake_dev', 'Your Rapid Development Cookbook'); ?></li></ul></li>
<li><a href="http://api.cakephp.org"><?php echo __d('cake_dev', 'CakePHP API'); ?> </a> <li><a href="http://api.cakephp.org"><?php echo __d('cake_dev', 'CakePHP API'); ?> </a>
<ul><li><?php echo __d('cake_dev', 'Quick Reference'); ?></li></ul></li> <ul><li><?php echo __d('cake_dev', 'Quick API Reference'); ?></li></ul></li>
<li><a href="http://bakery.cakephp.org"><?php echo __d('cake_dev', 'The Bakery'); ?> </a> <li><a href="http://bakery.cakephp.org"><?php echo __d('cake_dev', 'The Bakery'); ?> </a>
<ul><li><?php echo __d('cake_dev', 'Everything CakePHP'); ?></li></ul></li> <ul><li><?php echo __d('cake_dev', 'Everything CakePHP'); ?></li></ul></li>
<li><a href="http://plugins.cakephp.org"><?php echo __d('cake_dev', 'CakePHP plugins repo'); ?> </a> <li><a href="http://plugins.cakephp.org"><?php echo __d('cake_dev', 'CakePHP Plugins'); ?> </a>
<ul><li><?php echo __d('cake_dev', 'A comprehensive list of all CakePHP plugins created by the community'); ?></li></ul></li> <ul><li><?php echo __d('cake_dev', 'A comprehensive list of all CakePHP plugins created by the community'); ?></li></ul></li>
<li><a href="http://community.cakephp.org"><?php echo __d('cake_dev', 'CakePHP Community Center'); ?> </a>
<ul><li><?php echo __d('cake_dev', 'Everything related to the CakePHP community in one place'); ?></li></ul></li>
<li><a href="https://groups.google.com/group/cake-php"><?php echo __d('cake_dev', 'CakePHP Google Group'); ?> </a> <li><a href="https://groups.google.com/group/cake-php"><?php echo __d('cake_dev', 'CakePHP Google Group'); ?> </a>
<ul><li><?php echo __d('cake_dev', 'Community mailing list'); ?></li></ul></li> <ul><li><?php echo __d('cake_dev', 'Community mailing list'); ?></li></ul></li>
<li><a href="irc://irc.freenode.net/cakephp">irc.freenode.net #cakephp</a> <li><a href="irc://irc.freenode.net/cakephp">irc.freenode.net #cakephp</a>
<ul><li><?php echo __d('cake_dev', 'Live chat about CakePHP'); ?></li></ul></li> <ul><li><?php echo __d('cake_dev', 'Live chat about CakePHP'); ?></li></ul></li>
<li><a href="https://github.com/cakephp/"><?php echo __d('cake_dev', 'CakePHP Code'); ?> </a> <li><a href="https://github.com/cakephp/"><?php echo __d('cake_dev', 'CakePHP Code'); ?> </a>
<ul><li><?php echo __d('cake_dev', 'For the Development of CakePHP Git repository, Downloads'); ?></li></ul></li> <ul><li><?php echo __d('cake_dev', 'Find the CakePHP code on GitHub and contribute to the framework'); ?></li></ul></li>
<li><a href="https://cakephp.lighthouseapp.com/"><?php echo __d('cake_dev', 'CakePHP Lighthouse'); ?> </a> <li><a href="https://github.com/cakephp/cakephp/issues"><?php echo __d('cake_dev', 'CakePHP Issues'); ?> </a>
<ul><li><?php echo __d('cake_dev', 'CakePHP Tickets, Wiki pages, Roadmap'); ?></li></ul></li> <ul><li><?php echo __d('cake_dev', 'CakePHP Issues'); ?></li></ul></li>
<li><a href="https://github.com/cakephp/cakephp/wiki#roadmaps"><?php echo __d('cake_dev', 'CakePHP Roadmaps'); ?> </a>
<ul><li><?php echo __d('cake_dev', 'CakePHP Roadmaps'); ?></li></ul></li>
<li><a href="http://training.cakephp.org"><?php echo __d('cake_dev', 'Training'); ?> </a>
<ul><li><?php echo __d('cake_dev', 'Join a live session and get skilled with the framework'); ?></li></ul></li>
<li><a href="http://cakefest.org"><?php echo __d('cake_dev', 'CakeFest'); ?> </a>
<ul><li><?php echo __d('cake_dev', 'Don\'t miss our annual CakePHP conference'); ?></li></ul></li>
<li><a href="http://cakefoundation.org"><?php echo __d('cake_dev', 'Cake Software Foundation'); ?> </a>
<ul><li><?php echo __d('cake_dev', 'Promoting development related to CakePHP'); ?></li></ul></li>
</ul> </ul>

View file

@ -78,7 +78,7 @@ if (!defined('WWW_ROOT')) {
} }
// for built-in server // for built-in server
if (php_sapi_name() == 'cli-server') { if (php_sapi_name() === 'cli-server') {
if ($_SERVER['REQUEST_URI'] !== '/' && file_exists(WWW_ROOT . $_SERVER['PHP_SELF'])) { if ($_SERVER['REQUEST_URI'] !== '/' && file_exists(WWW_ROOT . $_SERVER['PHP_SELF'])) {
return false; return false;
} }
@ -89,11 +89,11 @@ if (!defined('CAKE_CORE_INCLUDE_PATH')) {
if (function_exists('ini_set')) { if (function_exists('ini_set')) {
ini_set('include_path', ROOT . DS . 'lib' . PATH_SEPARATOR . ini_get('include_path')); ini_set('include_path', ROOT . DS . 'lib' . PATH_SEPARATOR . ini_get('include_path'));
} }
if (!include ('Cake' . DS . 'bootstrap.php')) { if (!include 'Cake' . DS . 'bootstrap.php') {
$failed = true; $failed = true;
} }
} else { } else {
if (!include (CAKE_CORE_INCLUDE_PATH . DS . 'Cake' . DS . 'bootstrap.php')) { if (!include CAKE_CORE_INCLUDE_PATH . DS . 'Cake' . DS . 'bootstrap.php') {
$failed = true; $failed = true;
} }
} }

View file

@ -79,11 +79,11 @@ if (!defined('CAKE_CORE_INCLUDE_PATH')) {
if (function_exists('ini_set')) { if (function_exists('ini_set')) {
ini_set('include_path', ROOT . DS . 'lib' . PATH_SEPARATOR . ini_get('include_path')); ini_set('include_path', ROOT . DS . 'lib' . PATH_SEPARATOR . ini_get('include_path'));
} }
if (!include ('Cake' . DS . 'bootstrap.php')) { if (!include 'Cake' . DS . 'bootstrap.php') {
$failed = true; $failed = true;
} }
} else { } else {
if (!include (CAKE_CORE_INCLUDE_PATH . DS . 'Cake' . DS . 'bootstrap.php')) { if (!include CAKE_CORE_INCLUDE_PATH . DS . 'Cake' . DS . 'bootstrap.php') {
$failed = true; $failed = true;
} }
} }

View file

@ -145,9 +145,9 @@
<dirroles key="Cake/Console/Templates/default">php</dirroles> <dirroles key="Cake/Console/Templates/default">php</dirroles>
<dirroles key="Cake/View">php</dirroles> <dirroles key="Cake/View">php</dirroles>
<release> <release>
<install as="cake" name="bin/cake" />
<install as="cake.php" name="bin/cake.php" />
<install as="cake.bat" name="bin/cake.bat" /> <install as="cake.bat" name="bin/cake.bat" />
<install as="cake.php" name="bin/cake.php" />
<install as="cake" name="bin/cake" />
</release> </release>
<exceptions key="Cake/VERSION.txt">php</exceptions> <exceptions key="Cake/VERSION.txt">php</exceptions>
<exceptions key="Cake/LICENSE.txt">php</exceptions> <exceptions key="Cake/LICENSE.txt">php</exceptions>

View file

@ -533,7 +533,7 @@ class Cache {
* @throws CacheException * @throws CacheException
*/ */
public static function groupConfigs($group = null) { public static function groupConfigs($group = null) {
if ($group == null) { if ($group === null) {
return self::$_groups; return self::$_groups;
} }
if (isset(self::$_groups[$group])) { if (isset(self::$_groups[$group])) {

View file

@ -44,7 +44,7 @@ class FileEngine extends CacheEngine {
* *
* - path = absolute path to cache directory, default => CACHE * - path = absolute path to cache directory, default => CACHE
* - prefix = string prefix for filename, default => cake_ * - prefix = string prefix for filename, default => cake_
* - lock = enable file locking on write, default => false * - lock = enable file locking on write, default => true
* - serialize = serialize the data, default => true * - serialize = serialize the data, default => true
* *
* @var array * @var array

View file

@ -91,7 +91,7 @@ class AclShell extends AppShell {
$this->args = null; $this->args = null;
return $this->DbConfig->execute(); return $this->DbConfig->execute();
} }
require_once (APP . 'Config' . DS . 'database.php'); require_once APP . 'Config' . DS . 'database.php';
if (!in_array($this->command, array('initdb'))) { if (!in_array($this->command, array('initdb'))) {
$collection = new ComponentCollection(); $collection = new ComponentCollection();

View file

@ -67,12 +67,12 @@ class SchemaShell extends AppShell {
$name = $this->params['name'] = $splitName; $name = $this->params['name'] = $splitName;
} }
if ($name && empty($this->params['file'])) { $defaultFile = 'schema.php';
$this->params['file'] = Inflector::underscore($name);
}
if (empty($this->params['file'])) { if (empty($this->params['file'])) {
$this->params['file'] = 'schema.php'; $this->params['file'] = $defaultFile;
}
if ($name && $this->params['file'] === $defaultFile) {
$this->params['file'] = Inflector::underscore($name);
} }
if (strpos($this->params['file'], '.php') === false) { if (strpos($this->params['file'], '.php') === false) {
$this->params['file'] .= '.php'; $this->params['file'] .= '.php';

View file

@ -438,6 +438,8 @@ class ModelTask extends BakeTask {
$guess = $methods['notEmpty']; $guess = $methods['notEmpty'];
} elseif ($metaData['type'] === 'integer') { } elseif ($metaData['type'] === 'integer') {
$guess = $methods['numeric']; $guess = $methods['numeric'];
} elseif ($metaData['type'] === 'float') {
$guess = $methods['numeric'];
} elseif ($metaData['type'] === 'boolean') { } elseif ($metaData['type'] === 'boolean') {
$guess = $methods['boolean']; $guess = $methods['boolean'];
} elseif ($metaData['type'] === 'date') { } elseif ($metaData['type'] === 'date') {

View file

@ -295,7 +295,7 @@ class TestTask extends BakeTask {
* *
* @param string $type The Type of object you are generating tests for eg. controller * @param string $type The Type of object you are generating tests for eg. controller
* @param string $class the Classname of the class the test is being generated for. * @param string $class the Classname of the class the test is being generated for.
* @return string Real classname * @return string Real class name
*/ */
public function getRealClassName($type, $class) { public function getRealClassName($type, $class) {
if (strtolower($type) === 'model' || empty($this->classTypes[$type])) { if (strtolower($type) === 'model' || empty($this->classTypes[$type])) {
@ -430,7 +430,7 @@ class TestTask extends BakeTask {
} }
/** /**
* Add classname to the fixture list. * Add class name to the fixture list.
* Sets the app. or plugin.plugin_name. prefix. * Sets the app. or plugin.plugin_name. prefix.
* *
* @param string $name Name of the Model class that a fixture might be required for. * @param string $name Name of the Model class that a fixture might be required for.
@ -476,7 +476,7 @@ class TestTask extends BakeTask {
} }
/** /**
* Generate a constructor code snippet for the type and classname * Generate a constructor code snippet for the type and class name
* *
* @param string $type The Type of object you are generating tests for eg. controller * @param string $type The Type of object you are generating tests for eg. controller
* @param string $fullClassName The Classname of the class the test is being generated for. * @param string $fullClassName The Classname of the class the test is being generated for.
@ -504,7 +504,7 @@ class TestTask extends BakeTask {
} }
/** /**
* Generate the uses() calls for a type & classname * Generate the uses() calls for a type & class name
* *
* @param string $type The Type of object you are generating tests for eg. controller * @param string $type The Type of object you are generating tests for eg. controller
* @param string $realType The package name for the class. * @param string $realType The package name for the class.

View file

@ -45,7 +45,7 @@ Cache::config('default', array('engine' => 'File'));
*/ */
/** /**
* Custom Inflector rules, can be set to correctly pluralize or singularize table, model, controller names or whatever other * Custom Inflector rules can be set to correctly pluralize or singularize table, model, controller names or whatever other
* string is passed to the inflection functions * string is passed to the inflection functions
* *
* Inflector::rules('singular', array('rules' => array(), 'irregular' => array(), 'uninflected' => array())); * Inflector::rules('singular', array('rules' => array(), 'irregular' => array(), 'uninflected' => array()));
@ -55,7 +55,7 @@ Cache::config('default', array('engine' => 'File'));
/** /**
* Plugins need to be loaded manually, you can either load them one by one or all of them in a single call * Plugins need to be loaded manually, you can either load them one by one or all of them in a single call
* Uncomment one of the lines below, as you need. make sure you read the documentation on CakePlugin to use more * Uncomment one of the lines below, as you need. Make sure you read the documentation on CakePlugin to use more
* advanced ways of loading plugins * advanced ways of loading plugins
* *
* CakePlugin::loadAll(); // Loads all plugins at once * CakePlugin::loadAll(); // Loads all plugins at once
@ -64,7 +64,7 @@ Cache::config('default', array('engine' => 'File'));
*/ */
/** /**
* You can attach event listeners to the request lifecycle as Dispatcher Filter . By Default CakePHP bundles two filters: * You can attach event listeners to the request lifecycle as Dispatcher Filter . By default CakePHP bundles two filters:
* *
* - AssetDispatcher filter will serve your asset files (css, images, js, etc) from your themes and plugins * - AssetDispatcher filter will serve your asset files (css, images, js, etc) from your themes and plugins
* - CacheDispatcher filter will read the Cache.check configure variable and try to serve cached content generated from controllers * - CacheDispatcher filter will read the Cache.check configure variable and try to serve cached content generated from controllers

View file

@ -1,9 +1,5 @@
<?php <?php
/** /**
* This is core configuration file.
*
* Use it to configure core behaviour of Cake.
*
* PHP 5 * PHP 5
* *
* @link http://cakephp.org CakePHP(tm) Project * @link http://cakephp.org CakePHP(tm) Project
@ -45,6 +41,12 @@
* *
* unix_socket => * unix_socket =>
* For MySQL to connect via socket specify the `unix_socket` parameter instead of `host` and `port` * For MySQL to connect via socket specify the `unix_socket` parameter instead of `host` and `port`
* settings =>
* Array of key/value pairs, on connection it executes SET statements for each pair
* For MySQL : http://dev.mysql.com/doc/refman/5.6/en/set-statement.html
* For Postgres : http://www.postgresql.org/docs/9.2/static/sql-set.html
* For Sql Server : http://msdn.microsoft.com/en-us/library/ms190356.aspx
*/ */
class DATABASE_CONFIG { class DATABASE_CONFIG {

View file

@ -29,7 +29,7 @@ if (function_exists('ini_set')) {
ini_set('include_path', $root . PATH_SEPARATOR . __CAKE_PATH__ . PATH_SEPARATOR . ini_get('include_path')); ini_set('include_path', $root . PATH_SEPARATOR . __CAKE_PATH__ . PATH_SEPARATOR . ini_get('include_path'));
} }
if (!include ($dispatcher)) { if (!include $dispatcher) {
trigger_error('Could not locate CakePHP core files.', E_USER_ERROR); trigger_error('Could not locate CakePHP core files.', E_USER_ERROR);
} }
unset($paths, $path, $dispatcher, $root, $ds); unset($paths, $path, $dispatcher, $root, $ds);

View file

@ -14,9 +14,9 @@
<?php echo $this->Html->charset(); ?> <?php echo $this->Html->charset(); ?>
<title><?php echo $page_title; ?></title> <title><?php echo $page_title; ?></title>
<?php if (Configure::read('debug') == 0) { ?> <?php if (Configure::read('debug') == 0): ?>
<meta http-equiv="Refresh" content="<?php echo $pause; ?>;url=<?php echo $url; ?>"/> <meta http-equiv="Refresh" content="<?php echo $pause; ?>;url=<?php echo $url; ?>"/>
<?php } ?> <?php endif ?>
<style><!-- <style><!--
P { text-align:center; font:bold 1.1em sans-serif } P { text-align:center; font:bold 1.1em sans-serif }
A { color:#444; text-decoration:none } A { color:#444; text-decoration:none }

View file

@ -1,14 +1,13 @@
<?php <?php
if (!isset($channel)) { if (!isset($channel)):
$channel = array(); $channel = array();
} endif;
if (!isset($channel['title'])) { if (!isset($channel['title'])):
$channel['title'] = $title_for_layout; $channel['title'] = $title_for_layout;
} endif;
echo $this->Rss->document( echo $this->Rss->document(
$this->Rss->channel( $this->Rss->channel(
array(), $channel, $this->fetch('content') array(), $channel, $this->fetch('content')
) )
); );
?>

View file

@ -144,7 +144,7 @@ if (isset($filePresent)):
echo '<span class="notice">'; echo '<span class="notice">';
echo __d('cake_dev', 'DebugKit is not installed. It will help you inspect and debug different aspects of your application.'); echo __d('cake_dev', 'DebugKit is not installed. It will help you inspect and debug different aspects of your application.');
echo '<br/>'; echo '<br/>';
echo __d('cake_dev', 'You can install it from %s', $this->Html->link('github', 'https://github.com/cakephp/debug_kit')); echo __d('cake_dev', 'You can install it from %s', $this->Html->link('GitHub', 'https://github.com/cakephp/debug_kit'));
echo '</span>'; echo '</span>';
endif; endif;
?> ?>
@ -194,7 +194,7 @@ You can also add some CSS styles for your pages at: %s.',
</ul> </ul>
</p> </p>
<h3><?php echo __d('cake_dev', 'More about Cake'); ?></h3> <h3><?php echo __d('cake_dev', 'More about CakePHP'); ?></h3>
<p> <p>
<?php echo __d('cake_dev', 'CakePHP is a rapid development framework for PHP which uses commonly known design patterns like Active Record, Association Data Mapping, Front Controller and MVC.'); ?> <?php echo __d('cake_dev', 'CakePHP is a rapid development framework for PHP which uses commonly known design patterns like Active Record, Association Data Mapping, Front Controller and MVC.'); ?>
</p> </p>
@ -203,24 +203,32 @@ You can also add some CSS styles for your pages at: %s.',
</p> </p>
<ul> <ul>
<li><a href="http://cakefoundation.org/"><?php echo __d('cake_dev', 'Cake Software Foundation'); ?> </a> <li><a href="http://cakephp.org">CakePHP</a>
<ul><li><?php echo __d('cake_dev', 'Promoting development related to CakePHP'); ?></li></ul></li>
<li><a href="http://www.cakephp.org">CakePHP</a>
<ul><li><?php echo __d('cake_dev', 'The Rapid Development Framework'); ?></li></ul></li> <ul><li><?php echo __d('cake_dev', 'The Rapid Development Framework'); ?></li></ul></li>
<li><a href="http://book.cakephp.org"><?php echo __d('cake_dev', 'CakePHP Documentation'); ?> </a> <li><a href="http://book.cakephp.org"><?php echo __d('cake_dev', 'CakePHP Documentation'); ?> </a>
<ul><li><?php echo __d('cake_dev', 'Your Rapid Development Cookbook'); ?></li></ul></li> <ul><li><?php echo __d('cake_dev', 'Your Rapid Development Cookbook'); ?></li></ul></li>
<li><a href="http://api.cakephp.org"><?php echo __d('cake_dev', 'CakePHP API'); ?> </a> <li><a href="http://api.cakephp.org"><?php echo __d('cake_dev', 'CakePHP API'); ?> </a>
<ul><li><?php echo __d('cake_dev', 'Quick Reference'); ?></li></ul></li> <ul><li><?php echo __d('cake_dev', 'Quick API Reference'); ?></li></ul></li>
<li><a href="http://bakery.cakephp.org"><?php echo __d('cake_dev', 'The Bakery'); ?> </a> <li><a href="http://bakery.cakephp.org"><?php echo __d('cake_dev', 'The Bakery'); ?> </a>
<ul><li><?php echo __d('cake_dev', 'Everything CakePHP'); ?></li></ul></li> <ul><li><?php echo __d('cake_dev', 'Everything CakePHP'); ?></li></ul></li>
<li><a href="http://plugins.cakephp.org"><?php echo __d('cake_dev', 'CakePHP plugins repo'); ?> </a> <li><a href="http://plugins.cakephp.org"><?php echo __d('cake_dev', 'CakePHP Plugins'); ?> </a>
<ul><li><?php echo __d('cake_dev', 'A comprehensive list of all CakePHP plugins created by the community'); ?></li></ul></li> <ul><li><?php echo __d('cake_dev', 'A comprehensive list of all CakePHP plugins created by the community'); ?></li></ul></li>
<li><a href="http://community.cakephp.org"><?php echo __d('cake_dev', 'CakePHP Community Center'); ?> </a>
<ul><li><?php echo __d('cake_dev', 'Everything related to the CakePHP community in one place'); ?></li></ul></li>
<li><a href="https://groups.google.com/group/cake-php"><?php echo __d('cake_dev', 'CakePHP Google Group'); ?> </a> <li><a href="https://groups.google.com/group/cake-php"><?php echo __d('cake_dev', 'CakePHP Google Group'); ?> </a>
<ul><li><?php echo __d('cake_dev', 'Community mailing list'); ?></li></ul></li> <ul><li><?php echo __d('cake_dev', 'Community mailing list'); ?></li></ul></li>
<li><a href="irc://irc.freenode.net/cakephp">irc.freenode.net #cakephp</a> <li><a href="irc://irc.freenode.net/cakephp">irc.freenode.net #cakephp</a>
<ul><li><?php echo __d('cake_dev', 'Live chat about CakePHP'); ?></li></ul></li> <ul><li><?php echo __d('cake_dev', 'Live chat about CakePHP'); ?></li></ul></li>
<li><a href="https://github.com/cakephp/"><?php echo __d('cake_dev', 'CakePHP Code'); ?> </a> <li><a href="https://github.com/cakephp/"><?php echo __d('cake_dev', 'CakePHP Code'); ?> </a>
<ul><li><?php echo __d('cake_dev', 'For the Development of CakePHP Git repository, Downloads'); ?></li></ul></li> <ul><li><?php echo __d('cake_dev', 'Find the CakePHP code on GitHub and contribute to the framework'); ?></li></ul></li>
<li><a href="https://cakephp.lighthouseapp.com/"><?php echo __d('cake_dev', 'CakePHP Lighthouse'); ?> </a> <li><a href="https://github.com/cakephp/cakephp/issues"><?php echo __d('cake_dev', 'CakePHP Issues'); ?> </a>
<ul><li><?php echo __d('cake_dev', 'CakePHP Tickets, Wiki pages, Roadmap'); ?></li></ul></li> <ul><li><?php echo __d('cake_dev', 'CakePHP Issues'); ?></li></ul></li>
<li><a href="https://github.com/cakephp/cakephp/wiki#roadmaps"><?php echo __d('cake_dev', 'CakePHP Roadmaps'); ?> </a>
<ul><li><?php echo __d('cake_dev', 'CakePHP Roadmaps'); ?></li></ul></li>
<li><a href="http://training.cakephp.org"><?php echo __d('cake_dev', 'Training'); ?> </a>
<ul><li><?php echo __d('cake_dev', 'Join a live session and get skilled with the framework'); ?></li></ul></li>
<li><a href="http://cakefest.org"><?php echo __d('cake_dev', 'CakeFest'); ?> </a>
<ul><li><?php echo __d('cake_dev', 'Don\'t miss our annual CakePHP conference'); ?></li></ul></li>
<li><a href="http://cakefoundation.org"><?php echo __d('cake_dev', 'Cake Software Foundation'); ?> </a>
<ul><li><?php echo __d('cake_dev', 'Promoting development related to CakePHP'); ?></li></ul></li>
</ul> </ul>

View file

@ -80,11 +80,11 @@ if (!defined('CAKE_CORE_INCLUDE_PATH')) {
if (function_exists('ini_set')) { if (function_exists('ini_set')) {
ini_set('include_path', ROOT . DS . 'lib' . PATH_SEPARATOR . ini_get('include_path')); ini_set('include_path', ROOT . DS . 'lib' . PATH_SEPARATOR . ini_get('include_path'));
} }
if (!include ('Cake' . DS . 'bootstrap.php')) { if (!include 'Cake' . DS . 'bootstrap.php') {
$failed = true; $failed = true;
} }
} else { } else {
if (!include (CAKE_CORE_INCLUDE_PATH . DS . 'Cake' . DS . 'bootstrap.php')) { if (!include CAKE_CORE_INCLUDE_PATH . DS . 'Cake' . DS . 'bootstrap.php') {
$failed = true; $failed = true;
} }
} }

View file

@ -70,11 +70,11 @@ if (!defined('CAKE_CORE_INCLUDE_PATH')) {
if (function_exists('ini_set')) { if (function_exists('ini_set')) {
ini_set('include_path', ROOT . DS . 'lib' . PATH_SEPARATOR . ini_get('include_path')); ini_set('include_path', ROOT . DS . 'lib' . PATH_SEPARATOR . ini_get('include_path'));
} }
if (!include ('Cake' . DS . 'bootstrap.php')) { if (!include 'Cake' . DS . 'bootstrap.php') {
$failed = true; $failed = true;
} }
} else { } else {
if (!include (CAKE_CORE_INCLUDE_PATH . DS . 'Cake' . DS . 'bootstrap.php')) { if (!include CAKE_CORE_INCLUDE_PATH . DS . 'Cake' . DS . 'bootstrap.php') {
$failed = true; $failed = true;
} }
} }

View file

@ -174,7 +174,7 @@ class AuthComponent extends Component {
protected static $_user = array(); protected static $_user = array();
/** /**
* An URL (defined as a string or array) to the controller action that handles * A URL (defined as a string or array) to the controller action that handles
* logins. Defaults to `/users/login`. * logins. Defaults to `/users/login`.
* *
* @var mixed * @var mixed
@ -220,7 +220,7 @@ class AuthComponent extends Component {
* Controls handling of unauthorized access. * Controls handling of unauthorized access.
* - For default value `true` unauthorized user is redirected to the referrer URL * - For default value `true` unauthorized user is redirected to the referrer URL
* or AuthComponent::$loginRedirect or '/'. * or AuthComponent::$loginRedirect or '/'.
* - If set to a string or array the value is used as an URL to redirect to. * - If set to a string or array the value is used as a URL to redirect to.
* - If set to false a ForbiddenException exception is thrown instead of redirecting. * - If set to false a ForbiddenException exception is thrown instead of redirecting.
* *
* @var mixed * @var mixed
@ -699,7 +699,7 @@ class AuthComponent extends Component {
/** /**
* Get the URL a user should be redirected to upon login. * Get the URL a user should be redirected to upon login.
* *
* Pass an URL in to set the destination a user should be redirected to upon * Pass a URL in to set the destination a user should be redirected to upon
* logging in. * logging in.
* *
* If no parameter is passed, gets the authentication redirect URL. The URL * If no parameter is passed, gets the authentication redirect URL. The URL

View file

@ -232,17 +232,27 @@ class CookieComponent extends Component {
} }
foreach ($key as $name => $value) { foreach ($key as $name => $value) {
if (strpos($name, '.') === false) { $names = array($name);
$this->_values[$this->name][$name] = $value; if (strpos($name, '.') !== false) {
$this->_write("[$name]", $value);
} else {
$names = explode('.', $name, 2); $names = explode('.', $name, 2);
if (!isset($this->_values[$this->name][$names[0]])) {
$this->_values[$this->name][$names[0]] = array();
} }
$this->_values[$this->name][$names[0]] = Hash::insert($this->_values[$this->name][$names[0]], $names[1], $value); $firstName = $names[0];
$this->_write('[' . implode('][', $names) . ']', $value); $isMultiValue = (is_array($value) || count($names) > 1);
if (!isset($this->_values[$this->name][$firstName]) && $isMultiValue) {
$this->_values[$this->name][$firstName] = array();
} }
if (count($names) > 1) {
$this->_values[$this->name][$firstName] = Hash::insert(
$this->_values[$this->name][$firstName],
$names[1],
$value
);
} else {
$this->_values[$this->name][$firstName] = $value;
}
$this->_write('[' . $firstName . ']', $this->_values[$this->name][$firstName]);
} }
$this->_encrypted = true; $this->_encrypted = true;
} }
@ -299,11 +309,17 @@ class CookieComponent extends Component {
* Delete a cookie value * Delete a cookie value
* *
* Optional [Name.], required key * Optional [Name.], required key
* $this->Cookie->read('Name.key); * $this->Cookie->delete('Name.key);
* *
* You must use this method before any output is sent to the browser. * You must use this method before any output is sent to the browser.
* Failure to do so will result in header already sent errors. * Failure to do so will result in header already sent errors.
* *
* This method will delete both the top level and 2nd level cookies set.
* For example assuming that $name = App, deleting `User` will delete
* both `App[User]` and any other cookie values like `App[User][email]`
* This is done to clean up cookie storage from before 2.4.3, where cookies
* were stored inconsistently.
*
* @param string $key Key of the value to be deleted * @param string $key Key of the value to be deleted
* @return void * @return void
* @link http://book.cakephp.org/2.0/en/core-libraries/components/cookie.html#CookieComponent::delete * @link http://book.cakephp.org/2.0/en/core-libraries/components/cookie.html#CookieComponent::delete

View file

@ -86,7 +86,7 @@ class Controller extends Object implements CakeEventListener {
/** /**
* An array containing the names of helpers this controller uses. The array elements should * An array containing the names of helpers this controller uses. The array elements should
* not contain the "Helper" part of the classname. * not contain the "Helper" part of the class name.
* *
* Example: `public $helpers = array('Html', 'Js', 'Time', 'Ajax');` * Example: `public $helpers = array('Html', 'Js', 'Time', 'Ajax');`
* *
@ -114,7 +114,7 @@ class Controller extends Object implements CakeEventListener {
public $response; public $response;
/** /**
* The classname to use for creating the response object. * The class name to use for creating the response object.
* *
* @var string * @var string
*/ */
@ -182,7 +182,7 @@ class Controller extends Object implements CakeEventListener {
/** /**
* Array containing the names of components this controller uses. Component names * Array containing the names of components this controller uses. Component names
* should not contain the "Component" portion of the classname. * should not contain the "Component" portion of the class name.
* *
* Example: `public $components = array('Session', 'RequestHandler', 'Acl');` * Example: `public $components = array('Session', 'RequestHandler', 'Acl');`
* *

View file

@ -192,7 +192,7 @@ class CakeLog {
throw new CakeLogException(__d('cake_dev', 'Invalid key name')); throw new CakeLogException(__d('cake_dev', 'Invalid key name'));
} }
if (empty($config['engine'])) { if (empty($config['engine'])) {
throw new CakeLogException(__d('cake_dev', 'Missing logger classname')); throw new CakeLogException(__d('cake_dev', 'Missing logger class name'));
} }
if (empty(self::$_Collection)) { if (empty(self::$_Collection)) {
self::_init(); self::_init();

View file

@ -551,7 +551,7 @@ class CakeSchema extends Object {
continue; continue;
} }
$correspondingValue = $array2[$key]; $correspondingValue = $array2[$key];
if (is_null($value) !== is_null($correspondingValue)) { if (($value === null) !== ($correspondingValue === null)) {
$difference[$key] = $value; $difference[$key] = $value;
continue; continue;
} }

View file

@ -605,7 +605,7 @@ class Sqlserver extends DboSource {
* @param Model $model * @param Model $model
* @param array $queryData * @param array $queryData
* @param integer $recursive * @param integer $recursive
* @return array Array of resultset rows, or false if no rows matched * @return array|false Array of resultset rows, or false if no rows matched
*/ */
public function read(Model $model, $queryData = array(), $recursive = null) { public function read(Model $model, $queryData = array(), $recursive = null) {
$results = parent::read($model, $queryData, $recursive); $results = parent::read($model, $queryData, $recursive);

View file

@ -663,7 +663,8 @@ class DboSource extends DataSource {
if ($cache && ($cached = $this->getQueryCache($sql, $params)) !== false) { if ($cache && ($cached = $this->getQueryCache($sql, $params)) !== false) {
return $cached; return $cached;
} }
if ($result = $this->execute($sql, array(), $params)) { $result = $this->execute($sql, array(), $params);
if ($result) {
$out = array(); $out = array();
if ($this->hasResult()) { if ($this->hasResult()) {
@ -1072,7 +1073,7 @@ class DboSource extends DataSource {
} }
} }
$query = trim($this->generateAssociationQuery($model, null, null, null, null, $queryData, false, $null)); $query = $this->generateAssociationQuery($model, null, null, null, null, $queryData, false, $null);
$resultSet = $this->fetchAll($query, $model->cacheQueries); $resultSet = $this->fetchAll($query, $model->cacheQueries);
@ -1404,7 +1405,7 @@ class DboSource extends DataSource {
if (isset($merge[$association])) { if (isset($merge[$association])) {
$data[$association] = $merge[$association][0]; $data[$association] = $merge[$association][0];
} else { } else {
if (count($merge[0][$association]) > 1) { if (!empty($merge[0][$association])) {
foreach ($merge[0] as $assoc => $data2) { foreach ($merge[0] as $assoc => $data2) {
if ($assoc !== $association) { if ($assoc !== $association) {
$merge[0][$association][$assoc] = $data2; $merge[0][$association][$assoc] = $data2;
@ -1755,19 +1756,19 @@ class DboSource extends DataSource {
switch (strtolower($type)) { switch (strtolower($type)) {
case 'select': case 'select':
return "SELECT {$fields} FROM {$table} {$alias} {$joins} {$conditions} {$group} {$order} {$limit}"; return trim("SELECT {$fields} FROM {$table} {$alias} {$joins} {$conditions} {$group} {$order} {$limit}");
case 'create': case 'create':
return "INSERT INTO {$table} ({$fields}) VALUES ({$values})"; return "INSERT INTO {$table} ({$fields}) VALUES ({$values})";
case 'update': case 'update':
if (!empty($alias)) { if (!empty($alias)) {
$aliases = "{$this->alias}{$alias} {$joins} "; $aliases = "{$this->alias}{$alias} {$joins} ";
} }
return "UPDATE {$table} {$aliases}SET {$fields} {$conditions}"; return trim("UPDATE {$table} {$aliases}SET {$fields} {$conditions}");
case 'delete': case 'delete':
if (!empty($alias)) { if (!empty($alias)) {
$aliases = "{$this->alias}{$alias} {$joins} "; $aliases = "{$this->alias}{$alias} {$joins} ";
} }
return "DELETE {$alias} FROM {$table} {$aliases}{$conditions}"; return trim("DELETE {$alias} FROM {$table} {$aliases}{$conditions}");
case 'schema': case 'schema':
foreach (array('columns', 'indexes', 'tableParameters') as $var) { foreach (array('columns', 'indexes', 'tableParameters') as $var) {
if (is_array(${$var})) { if (is_array(${$var})) {

View file

@ -294,7 +294,7 @@ class Model extends Object implements CakeEventListener {
* *
* ### Possible keys in association * ### Possible keys in association
* *
* - `className`: the classname of the model being associated to the current model. * - `className`: the class name of the model being associated to the current model.
* If you're defining a 'Profile belongsTo User' relationship, the className key should equal 'User.' * If you're defining a 'Profile belongsTo User' relationship, the className key should equal 'User.'
* - `foreignKey`: the name of the foreign key found in the current model. This is * - `foreignKey`: the name of the foreign key found in the current model. This is
* especially handy if you need to define multiple belongsTo relationships. The default * especially handy if you need to define multiple belongsTo relationships. The default
@ -341,7 +341,7 @@ class Model extends Object implements CakeEventListener {
* *
* ### Possible keys in association * ### Possible keys in association
* *
* - `className`: the classname of the model being associated to the current model. * - `className`: the class name of the model being associated to the current model.
* If you're defining a 'User hasOne Profile' relationship, the className key should equal 'Profile.' * If you're defining a 'User hasOne Profile' relationship, the className key should equal 'Profile.'
* - `foreignKey`: the name of the foreign key found in the other model. This is * - `foreignKey`: the name of the foreign key found in the other model. This is
* especially handy if you need to define multiple hasOne relationships. * especially handy if you need to define multiple hasOne relationships.
@ -384,7 +384,7 @@ class Model extends Object implements CakeEventListener {
* *
* ### Possible keys in association * ### Possible keys in association
* *
* - `className`: the classname of the model being associated to the current model. * - `className`: the class name of the model being associated to the current model.
* If you're defining a 'User hasMany Comment' relationship, the className key should equal 'Comment.' * If you're defining a 'User hasMany Comment' relationship, the className key should equal 'Comment.'
* - `foreignKey`: the name of the foreign key found in the other model. This is * - `foreignKey`: the name of the foreign key found in the other model. This is
* especially handy if you need to define multiple hasMany relationships. The default * especially handy if you need to define multiple hasMany relationships. The default
@ -435,7 +435,7 @@ class Model extends Object implements CakeEventListener {
* *
* ### Possible keys in association * ### Possible keys in association
* *
* - `className`: the classname of the model being associated to the current model. * - `className`: the class name of the model being associated to the current model.
* If you're defining a 'Recipe HABTM Tag' relationship, the className key should equal 'Tag.' * If you're defining a 'Recipe HABTM Tag' relationship, the className key should equal 'Tag.'
* - `joinTable`: The name of the join table used in this association (if the * - `joinTable`: The name of the join table used in this association (if the
* current table doesn't adhere to the naming convention for HABTM join tables). * current table doesn't adhere to the naming convention for HABTM join tables).
@ -665,7 +665,8 @@ class Model extends Object implements CakeEventListener {
* Would create a model attached to the posts table on connection2. Dynamic model creation is useful * Would create a model attached to the posts table on connection2. Dynamic model creation is useful
* when you want a model object that contains no associations or attached behaviors. * when you want a model object that contains no associations or attached behaviors.
* *
* @param integer|string|array $id Set this ID for this model on startup, can also be an array of options, see above. * @param boolean|integer|string|array $id Set this ID for this model on startup,
* can also be an array of options, see above.
* @param string $table Name of database table to use. * @param string $table Name of database table to use.
* @param string $ds DataSource connection name. * @param string $ds DataSource connection name.
*/ */
@ -904,7 +905,7 @@ class Model extends Object implements CakeEventListener {
* Example: Add a new hasOne binding to the Profile model not * Example: Add a new hasOne binding to the Profile model not
* defined in the model source code: * defined in the model source code:
* *
* `$this->User->bindModel( array('hasOne' => array('Profile')) );` * `$this->User->bindModel(array('hasOne' => array('Profile')));`
* *
* Bindings that are not made permanent will be reset by the next Model::find() call on this * Bindings that are not made permanent will be reset by the next Model::find() call on this
* model. * model.
@ -989,30 +990,32 @@ class Model extends Object implements CakeEventListener {
*/ */
protected function _createLinks() { protected function _createLinks() {
foreach ($this->_associations as $type) { foreach ($this->_associations as $type) {
if (!is_array($this->{$type})) { $association =& $this->{$type};
$this->{$type} = explode(',', $this->{$type});
foreach ($this->{$type} as $i => $className) { if (!is_array($association)) {
$association = explode(',', $association);
foreach ($association as $i => $className) {
$className = trim($className); $className = trim($className);
unset ($this->{$type}[$i]); unset ($association[$i]);
$this->{$type}[$className] = array(); $association[$className] = array();
} }
} }
if (!empty($this->{$type})) { if (!empty($association)) {
foreach ($this->{$type} as $assoc => $value) { foreach ($association as $assoc => $value) {
$plugin = null; $plugin = null;
if (is_numeric($assoc)) { if (is_numeric($assoc)) {
unset($this->{$type}[$assoc]); unset($association[$assoc]);
$assoc = $value; $assoc = $value;
$value = array(); $value = array();
if (strpos($assoc, '.') !== false) { if (strpos($assoc, '.') !== false) {
list($plugin, $assoc) = pluginSplit($assoc, true); list($plugin, $assoc) = pluginSplit($assoc, true);
$this->{$type}[$assoc] = array('className' => $plugin . $assoc); $association[$assoc] = array('className' => $plugin . $assoc);
} else { } else {
$this->{$type}[$assoc] = $value; $association[$assoc] = $value;
} }
} }
@ -1068,9 +1071,10 @@ class Model extends Object implements CakeEventListener {
protected function _generateAssociation($type, $assocKey) { protected function _generateAssociation($type, $assocKey) {
$class = $assocKey; $class = $assocKey;
$dynamicWith = false; $dynamicWith = false;
$assoc =& $this->{$type}[$assocKey];
foreach ($this->_associationKeys[$type] as $key) { foreach ($this->_associationKeys[$type] as $key) {
if (!isset($this->{$type}[$assocKey][$key]) || $this->{$type}[$assocKey][$key] === null) { if (!isset($assoc[$key]) || $assoc[$key] === null) {
$data = ''; $data = '';
switch ($key) { switch ($key) {
@ -1087,7 +1091,7 @@ class Model extends Object implements CakeEventListener {
break; break;
case 'with': case 'with':
$data = Inflector::camelize(Inflector::singularize($this->{$type}[$assocKey]['joinTable'])); $data = Inflector::camelize(Inflector::singularize($assoc['joinTable']));
$dynamicWith = true; $dynamicWith = true;
break; break;
@ -1106,11 +1110,11 @@ class Model extends Object implements CakeEventListener {
break; break;
} }
$this->{$type}[$assocKey][$key] = $data; $assoc[$key] = $data;
} }
if ($dynamicWith) { if ($dynamicWith) {
$this->{$type}[$assocKey]['dynamicWith'] = true; $assoc['dynamicWith'] = true;
} }
} }
} }
@ -1182,17 +1186,16 @@ class Model extends Object implements CakeEventListener {
} }
foreach ($data as $modelName => $fieldSet) { foreach ($data as $modelName => $fieldSet) {
if (is_array($fieldSet)) { if (!is_array($fieldSet)) {
foreach ($fieldSet as $fieldName => $fieldValue) { continue;
if (isset($this->validationErrors[$fieldName])) {
unset($this->validationErrors[$fieldName]);
} }
if ($modelName === $this->alias) { foreach ($fieldSet as $fieldName => $fieldValue) {
if ($fieldName === $this->primaryKey) { unset($this->validationErrors[$fieldName]);
if ($modelName === $this->alias && $fieldName === $this->primaryKey) {
$this->id = $fieldValue; $this->id = $fieldValue;
} }
}
if (is_array($fieldValue) || is_object($fieldValue)) { if (is_array($fieldValue) || is_object($fieldValue)) {
$fieldValue = $this->deconstruct($fieldName, $fieldValue); $fieldValue = $this->deconstruct($fieldName, $fieldValue);
@ -1201,7 +1204,6 @@ class Model extends Object implements CakeEventListener {
$this->data[$modelName][$fieldName] = $fieldValue; $this->data[$modelName][$fieldName] = $fieldValue;
} }
} }
}
return $data; return $data;
} }
@ -1554,7 +1556,7 @@ class Model extends Object implements CakeEventListener {
/** /**
* This function is a convenient wrapper class to create(false) and, as the name suggests, clears the id, data, and validation errors. * This function is a convenient wrapper class to create(false) and, as the name suggests, clears the id, data, and validation errors.
* *
* @return always boolean TRUE upon success * @return boolean Always true upon success
* @see Model::create() * @see Model::create()
*/ */
public function clear() { public function clear() {
@ -1746,12 +1748,15 @@ class Model extends Object implements CakeEventListener {
$now = time(); $now = time();
foreach ($dateFields as $updateCol) { foreach ($dateFields as $updateCol) {
if ($this->hasField($updateCol) && !in_array($updateCol, $fields)) { if (in_array($updateCol, $fields) || !$this->hasField($updateCol)) {
continue;
}
$default = array('formatter' => 'date'); $default = array('formatter' => 'date');
$colType = array_merge($default, $db->columns[$this->getColumnType($updateCol)]); $colType = array_merge($default, $db->columns[$this->getColumnType($updateCol)]);
if (!array_key_exists('format', $colType)) {
$time = $now; $time = $now;
} else { if (array_key_exists('format', $colType)) {
$time = call_user_func($colType['formatter'], $colType['format']); $time = call_user_func($colType['formatter'], $colType['format']);
} }
@ -1760,7 +1765,6 @@ class Model extends Object implements CakeEventListener {
} }
$this->set($updateCol, $time); $this->set($updateCol, $time);
} }
}
if ($options['callbacks'] === true || $options['callbacks'] === 'before') { if ($options['callbacks'] === true || $options['callbacks'] === 'before') {
$event = new CakeEvent('Model.beforeSave', $this, array($options)); $event = new CakeEvent('Model.beforeSave', $this, array($options));
@ -1785,8 +1789,7 @@ class Model extends Object implements CakeEventListener {
$v = $v[$n]; $v = $v[$n];
} }
$joined[$n] = $v; $joined[$n] = $v;
} else { } elseif ($n === $this->alias) {
if ($n === $this->alias) {
foreach (array('created', 'updated', 'modified') as $field) { foreach (array('created', 'updated', 'modified') as $field) {
if (array_key_exists($field, $v) && empty($v[$field])) { if (array_key_exists($field, $v) && empty($v[$field])) {
unset($v[$field]); unset($v[$field]);
@ -1800,7 +1803,6 @@ class Model extends Object implements CakeEventListener {
} }
} }
} }
}
$count = count($fields); $count = count($fields);
@ -1892,35 +1894,42 @@ class Model extends Object implements CakeEventListener {
*/ */
protected function _saveMulti($joined, $id, $db) { protected function _saveMulti($joined, $id, $db) {
foreach ($joined as $assoc => $data) { foreach ($joined as $assoc => $data) {
if (isset($this->hasAndBelongsToMany[$assoc])) { if (!isset($this->hasAndBelongsToMany[$assoc])) {
list($join) = $this->joinModel($this->hasAndBelongsToMany[$assoc]['with']); continue;
}
if ($with = $this->hasAndBelongsToMany[$assoc]['with']) { $habtm = $this->hasAndBelongsToMany[$assoc];
$withModel = is_array($with) ? key($with) : $with;
list($join) = $this->joinModel($habtm['with']);
$Model = $this->{$join};
if (!empty($habtm['with'])) {
$withModel = is_array($habtm['with']) ? key($habtm['with']) : $habtm['with'];
list(, $withModel) = pluginSplit($withModel); list(, $withModel) = pluginSplit($withModel);
$dbMulti = $this->{$withModel}->getDataSource(); $dbMulti = $this->{$withModel}->getDataSource();
} else { } else {
$dbMulti = $db; $dbMulti = $db;
} }
$isUUID = !empty($this->{$join}->primaryKey) && $this->{$join}->_isUUIDField($this->{$join}->primaryKey); $isUUID = !empty($Model->primaryKey) && $Model->_isUUIDField($Model->primaryKey);
$newData = $newValues = $newJoins = array(); $newData = $newValues = $newJoins = array();
$primaryAdded = false; $primaryAdded = false;
$fields = array( $fields = array(
$dbMulti->name($this->hasAndBelongsToMany[$assoc]['foreignKey']), $dbMulti->name($habtm['foreignKey']),
$dbMulti->name($this->hasAndBelongsToMany[$assoc]['associationForeignKey']) $dbMulti->name($habtm['associationForeignKey'])
); );
$idField = $db->name($this->{$join}->primaryKey); $idField = $db->name($Model->primaryKey);
if ($isUUID && !in_array($idField, $fields)) { if ($isUUID && !in_array($idField, $fields)) {
$fields[] = $idField; $fields[] = $idField;
$primaryAdded = true; $primaryAdded = true;
} }
foreach ((array)$data as $row) { foreach ((array)$data as $row) {
if ((is_string($row) && (strlen($row) === 36 || strlen($row) === 16)) || is_numeric($row)) { if ((is_string($row) && (strlen($row) == 36 || strlen($row) == 16)) || is_numeric($row)) {
$newJoins[] = $row; $newJoins[] = $row;
$values = array($id, $row); $values = array($id, $row);
@ -1930,35 +1939,35 @@ class Model extends Object implements CakeEventListener {
$newValues[$row] = $values; $newValues[$row] = $values;
unset($values); unset($values);
} elseif (isset($row[$this->hasAndBelongsToMany[$assoc]['associationForeignKey']])) { } elseif (isset($row[$habtm['associationForeignKey']])) {
if (!empty($row[$this->{$join}->primaryKey])) { if (!empty($row[$Model->primaryKey])) {
$newJoins[] = $row[$this->hasAndBelongsToMany[$assoc]['associationForeignKey']]; $newJoins[] = $row[$habtm['associationForeignKey']];
} }
$newData[] = $row; $newData[] = $row;
} elseif (isset($row[$join]) && isset($row[$join][$this->hasAndBelongsToMany[$assoc]['associationForeignKey']])) { } elseif (isset($row[$join]) && isset($row[$join][$habtm['associationForeignKey']])) {
if (!empty($row[$join][$this->{$join}->primaryKey])) { if (!empty($row[$join][$Model->primaryKey])) {
$newJoins[] = $row[$join][$this->hasAndBelongsToMany[$assoc]['associationForeignKey']]; $newJoins[] = $row[$join][$habtm['associationForeignKey']];
} }
$newData[] = $row[$join]; $newData[] = $row[$join];
} }
} }
$keepExisting = $this->hasAndBelongsToMany[$assoc]['unique'] === 'keepExisting'; $keepExisting = $habtm['unique'] === 'keepExisting';
if ($this->hasAndBelongsToMany[$assoc]['unique']) { if ($habtm['unique']) {
$conditions = array( $conditions = array(
$join . '.' . $this->hasAndBelongsToMany[$assoc]['foreignKey'] => $id $join . '.' . $habtm['foreignKey'] => $id
); );
if (!empty($this->hasAndBelongsToMany[$assoc]['conditions'])) { if (!empty($habtm['conditions'])) {
$conditions = array_merge($conditions, (array)$this->hasAndBelongsToMany[$assoc]['conditions']); $conditions = array_merge($conditions, (array)$habtm['conditions']);
} }
$associationForeignKey = $this->{$join}->alias . '.' . $this->hasAndBelongsToMany[$assoc]['associationForeignKey']; $associationForeignKey = $Model->alias . '.' . $habtm['associationForeignKey'];
$links = $this->{$join}->find('all', array( $links = $Model->find('all', array(
'conditions' => $conditions, 'conditions' => $conditions,
'recursive' => empty($this->hasAndBelongsToMany[$assoc]['conditions']) ? -1 : 0, 'recursive' => empty($habtm['conditions']) ? -1 : 0,
'fields' => $associationForeignKey, 'fields' => $associationForeignKey,
)); ));
@ -1970,28 +1979,28 @@ class Model extends Object implements CakeEventListener {
$conditions[$associationForeignKey] = $oldLinks; $conditions[$associationForeignKey] = $oldLinks;
} }
$dbMulti->delete($this->{$join}, $conditions); $dbMulti->delete($Model, $conditions);
} }
} }
if (!empty($newData)) { if (!empty($newData)) {
foreach ($newData as $data) { foreach ($newData as $data) {
$data[$this->hasAndBelongsToMany[$assoc]['foreignKey']] = $id; $data[$habtm['foreignKey']] = $id;
if (empty($data[$this->{$join}->primaryKey])) { if (empty($data[$Model->primaryKey])) {
$this->{$join}->create(); $Model->create();
} }
$this->{$join}->save($data); $Model->save($data);
} }
} }
if (!empty($newValues)) { if (!empty($newValues)) {
if ($keepExisting && !empty($links)) { if ($keepExisting && !empty($links)) {
foreach ($links as $link) { foreach ($links as $link) {
$oldJoin = $link[$join][$this->hasAndBelongsToMany[$assoc]['associationForeignKey']]; $oldJoin = $link[$join][$habtm['associationForeignKey']];
if (!in_array($oldJoin, $newJoins)) { if (!in_array($oldJoin, $newJoins)) {
$conditions[$associationForeignKey] = $oldJoin; $conditions[$associationForeignKey] = $oldJoin;
$db->delete($this->{$join}, $conditions); $db->delete($Model, $conditions);
} else { } else {
unset($newValues[$oldJoin]); unset($newValues[$oldJoin]);
} }
@ -2001,8 +2010,7 @@ class Model extends Object implements CakeEventListener {
} }
if (!empty($newValues)) { if (!empty($newValues)) {
$dbMulti->insertMulti($this->{$join}, $fields, $newValues); $dbMulti->insertMulti($Model, $fields, $newValues);
}
} }
} }
} }
@ -2021,7 +2029,12 @@ class Model extends Object implements CakeEventListener {
$keys['old'] = isset($keys['old']) ? $keys['old'] : array(); $keys['old'] = isset($keys['old']) ? $keys['old'] : array();
foreach ($this->belongsTo as $parent => $assoc) { foreach ($this->belongsTo as $parent => $assoc) {
if (!empty($assoc['counterCache'])) { if (empty($assoc['counterCache'])) {
continue;
}
$Model = $this->{$parent};
if (!is_array($assoc['counterCache'])) { if (!is_array($assoc['counterCache'])) {
if (isset($assoc['counterScope'])) { if (isset($assoc['counterScope'])) {
$assoc['counterCache'] = array($assoc['counterCache'] => $assoc['counterScope']); $assoc['counterCache'] = array($assoc['counterCache'] => $assoc['counterScope']);
@ -2038,7 +2051,7 @@ class Model extends Object implements CakeEventListener {
$field = Inflector::underscore($this->alias) . '_count'; $field = Inflector::underscore($this->alias) . '_count';
} }
if (!$this->{$parent}->hasField($field)) { if (!$Model->hasField($field)) {
continue; continue;
} }
@ -2054,17 +2067,15 @@ class Model extends Object implements CakeEventListener {
$recursive = (empty($conditions) ? -1 : 0); $recursive = (empty($conditions) ? -1 : 0);
if (isset($keys['old'][$foreignKey])) { if (isset($keys['old'][$foreignKey]) && $keys['old'][$foreignKey] != $keys[$foreignKey]) {
if ($keys['old'][$foreignKey] != $keys[$foreignKey]) {
$conditions[$fkQuoted] = $keys['old'][$foreignKey]; $conditions[$fkQuoted] = $keys['old'][$foreignKey];
$count = intval($this->find('count', compact('conditions', 'recursive'))); $count = intval($this->find('count', compact('conditions', 'recursive')));
$this->{$parent}->updateAll( $Model->updateAll(
array($field => $count), array($field => $count),
array($this->{$parent}->escapeField() => $keys['old'][$foreignKey]) array($Model->escapeField() => $keys['old'][$foreignKey])
); );
} }
}
$conditions[$fkQuoted] = $keys[$foreignKey]; $conditions[$fkQuoted] = $keys[$foreignKey];
@ -2074,14 +2085,13 @@ class Model extends Object implements CakeEventListener {
$count = intval($this->find('count', compact('conditions', 'recursive'))); $count = intval($this->find('count', compact('conditions', 'recursive')));
$this->{$parent}->updateAll( $Model->updateAll(
array($field => $count), array($field => $count),
array($this->{$parent}->escapeField() => $keys[$foreignKey]) array($Model->escapeField() => $keys[$foreignKey])
); );
} }
} }
} }
}
/** /**
* Helper method for `Model::updateCounterCache()`. Checks the fields to be updated for * Helper method for `Model::updateCounterCache()`. Checks the fields to be updated for
@ -2343,15 +2353,20 @@ class Model extends Object implements CakeEventListener {
$return = array(); $return = array();
$validates = true; $validates = true;
foreach ($data as $association => $values) { foreach ($data as $association => $values) {
$notEmpty = !empty($values[$association]) || (!isset($values[$association]) && !empty($values)); $isEmpty = empty($values) || (isset($values[$association]) && empty($values[$association]));
if (isset($associations[$association]) && $associations[$association] === 'belongsTo' && $notEmpty) { if ($isEmpty || !isset($associations[$association]) || $associations[$association] !== 'belongsTo') {
$validates = $this->{$association}->create(null) !== null; continue;
}
$Model = $this->{$association};
$validates = $Model->create(null) !== null;
$saved = false; $saved = false;
if ($validates) { if ($validates) {
if ($options['deep']) { if ($options['deep']) {
$saved = $this->{$association}->saveAssociated($values, array_merge($options, array('atomic' => false))); $saved = $Model->saveAssociated($values, array_merge($options, array('atomic' => false)));
} else { } else {
$saved = $this->{$association}->save($values, array_merge($options, array('atomic' => false))); $saved = $Model->save($values, array_merge($options, array('atomic' => false)));
} }
$validates = ($saved === true || (is_array($saved) && !in_array(false, $saved, true))); $validates = ($saved === true || (is_array($saved) && !in_array(false, $saved, true)));
} }
@ -2359,18 +2374,17 @@ class Model extends Object implements CakeEventListener {
if ($validates) { if ($validates) {
$key = $this->belongsTo[$association]['foreignKey']; $key = $this->belongsTo[$association]['foreignKey'];
if (isset($data[$this->alias])) { if (isset($data[$this->alias])) {
$data[$this->alias][$key] = $this->{$association}->id; $data[$this->alias][$key] = $Model->id;
} else { } else {
$data = array_merge(array($key => $this->{$association}->id), $data, array($key => $this->{$association}->id)); $data = array_merge(array($key => $Model->id), $data, array($key => $Model->id));
} }
$options = $this->_addToWhiteList($key, $options); $options = $this->_addToWhiteList($key, $options);
} else { } else {
$validationErrors[$association] = $this->{$association}->validationErrors; $validationErrors[$association] = $Model->validationErrors;
} }
$return[$association] = $validates; $return[$association] = $validates;
} }
}
if ($validates && !($this->create(null) !== null && $this->save($data, $options))) { if ($validates && !($this->create(null) !== null && $this->save($data, $options))) {
$validationErrors[$this->alias] = $this->validationErrors; $validationErrors[$this->alias] = $this->validationErrors;
@ -2383,8 +2397,13 @@ class Model extends Object implements CakeEventListener {
break; break;
} }
$notEmpty = !empty($values[$association]) || (!isset($values[$association]) && !empty($values)); $isEmpty = empty($values) || (isset($values[$association]) && empty($values[$association]));
if (isset($associations[$association]) && $notEmpty) { if ($isEmpty || !isset($associations[$association])) {
continue;
}
$Model = $this->{$association};
$type = $associations[$association]; $type = $associations[$association];
$key = $this->{$type}[$association]['foreignKey']; $key = $this->{$type}[$association]['foreignKey'];
switch ($type) { switch ($type) {
@ -2395,21 +2414,21 @@ class Model extends Object implements CakeEventListener {
$values = array_merge(array($key => $this->id), $values, array($key => $this->id)); $values = array_merge(array($key => $this->id), $values, array($key => $this->id));
} }
$validates = $this->{$association}->create(null) !== null; $validates = $Model->create(null) !== null;
$saved = false; $saved = false;
if ($validates) { if ($validates) {
$options = $this->{$association}->_addToWhiteList($key, $options); $options = $Model->_addToWhiteList($key, $options);
if ($options['deep']) { if ($options['deep']) {
$saved = $this->{$association}->saveAssociated($values, array_merge($options, array('atomic' => false))); $saved = $Model->saveAssociated($values, array_merge($options, array('atomic' => false)));
} else { } else {
$saved = $this->{$association}->save($values, $options); $saved = $Model->save($values, $options);
} }
} }
$validates = ($validates && ($saved === true || (is_array($saved) && !in_array(false, $saved, true)))); $validates = ($validates && ($saved === true || (is_array($saved) && !in_array(false, $saved, true))));
if (!$validates) { if (!$validates) {
$validationErrors[$association] = $this->{$association}->validationErrors; $validationErrors[$association] = $Model->validationErrors;
} }
$return[$association] = $validates; $return[$association] = $validates;
@ -2423,10 +2442,10 @@ class Model extends Object implements CakeEventListener {
} }
} }
$options = $this->{$association}->_addToWhiteList($key, $options); $options = $Model->_addToWhiteList($key, $options);
$_return = $this->{$association}->saveMany($values, array_merge($options, array('atomic' => false))); $_return = $Model->saveMany($values, array_merge($options, array('atomic' => false)));
if (in_array(false, $_return, true)) { if (in_array(false, $_return, true)) {
$validationErrors[$association] = $this->{$association}->validationErrors; $validationErrors[$association] = $Model->validationErrors;
$validates = false; $validates = false;
} }
@ -2434,7 +2453,6 @@ class Model extends Object implements CakeEventListener {
break; break;
} }
} }
}
$this->validationErrors = $validationErrors; $this->validationErrors = $validationErrors;
if (isset($validationErrors[$this->alias])) { if (isset($validationErrors[$this->alias])) {
@ -2477,10 +2495,7 @@ class Model extends Object implements CakeEventListener {
return $options; return $options;
} }
if (!empty($options['fieldList']) && if (!empty($options['fieldList']) && is_array($options['fieldList']) && Hash::dimensions($options['fieldList']) < 2) {
is_array($options['fieldList']) &&
Hash::dimensions($options['fieldList']) < 2
) {
$options['fieldList'][] = $key; $options['fieldList'][] = $key;
} }
@ -2606,29 +2621,29 @@ class Model extends Object implements CakeEventListener {
continue; continue;
} }
$model = $this->{$assoc}; $Model = $this->{$assoc};
if ($data['foreignKey'] === false && $data['conditions'] && in_array($this->name, $model->getAssociated('belongsTo'))) { if ($data['foreignKey'] === false && $data['conditions'] && in_array($this->name, $Model->getAssociated('belongsTo'))) {
$model->recursive = 0; $Model->recursive = 0;
$conditions = array($this->escapeField(null, $this->name) => $id); $conditions = array($this->escapeField(null, $this->name) => $id);
} else { } else {
$model->recursive = -1; $Model->recursive = -1;
$conditions = array($model->escapeField($data['foreignKey']) => $id); $conditions = array($Model->escapeField($data['foreignKey']) => $id);
if ($data['conditions']) { if ($data['conditions']) {
$conditions = array_merge((array)$data['conditions'], $conditions); $conditions = array_merge((array)$data['conditions'], $conditions);
} }
} }
if (isset($data['exclusive']) && $data['exclusive']) { if (isset($data['exclusive']) && $data['exclusive']) {
$model->deleteAll($conditions); $Model->deleteAll($conditions);
} else { } else {
$records = $model->find('all', array( $records = $Model->find('all', array(
'conditions' => $conditions, 'fields' => $model->primaryKey 'conditions' => $conditions, 'fields' => $Model->primaryKey
)); ));
if (!empty($records)) { if (!empty($records)) {
foreach ($records as $record) { foreach ($records as $record) {
$model->delete($record[$model->alias][$model->primaryKey]); $Model->delete($record[$Model->alias][$Model->primaryKey]);
} }
} }
} }
@ -2648,16 +2663,17 @@ class Model extends Object implements CakeEventListener {
protected function _deleteLinks($id) { protected function _deleteLinks($id) {
foreach ($this->hasAndBelongsToMany as $data) { foreach ($this->hasAndBelongsToMany as $data) {
list(, $joinModel) = pluginSplit($data['with']); list(, $joinModel) = pluginSplit($data['with']);
$records = $this->{$joinModel}->find('all', array( $Model = $this->{$joinModel};
'conditions' => array($this->{$joinModel}->escapeField($data['foreignKey']) => $id), $records = $Model->find('all', array(
'fields' => $this->{$joinModel}->primaryKey, 'conditions' => array($Model->escapeField($data['foreignKey']) => $id),
'fields' => $Model->primaryKey,
'recursive' => -1, 'recursive' => -1,
'callbacks' => false 'callbacks' => false
)); ));
if (!empty($records)) { if (!empty($records)) {
foreach ($records as $record) { foreach ($records as $record) {
$this->{$joinModel}->delete($record[$this->{$joinModel}->alias][$this->{$joinModel}->primaryKey]); $Model->delete($record[$Model->alias][$Model->primaryKey]);
} }
} }
} }
@ -2779,7 +2795,7 @@ class Model extends Object implements CakeEventListener {
* *
* Used to perform find operations, where the first argument is type of find operation to perform * Used to perform find operations, where the first argument is type of find operation to perform
* (all / first / count / neighbors / list / threaded), * (all / first / count / neighbors / list / threaded),
* second parameter options for finding ( indexed array, including: 'conditions', 'limit', * second parameter options for finding (indexed array, including: 'conditions', 'limit',
* 'recursive', 'page', 'fields', 'offset', 'order', 'callbacks') * 'recursive', 'page', 'fields', 'offset', 'order', 'callbacks')
* *
* Eg: * Eg:
@ -3304,7 +3320,7 @@ class Model extends Object implements CakeEventListener {
* *
* Additionally it populates the validationErrors property of the model with the same array. * Additionally it populates the validationErrors property of the model with the same array.
* *
* @param string $options An optional array of custom options to be made available in the beforeValidate callback * @param array|string $options An optional array of custom options to be made available in the beforeValidate callback
* @return array Array of invalid fields and their error messages * @return array Array of invalid fields and their error messages
* @see Model::validates() * @see Model::validates()
*/ */
@ -3671,25 +3687,29 @@ class Model extends Object implements CakeEventListener {
* *
* @param string $type If null this deletes cached views if Cache.check is true * @param string $type If null this deletes cached views if Cache.check is true
* Will be used to allow deleting query cache also * Will be used to allow deleting query cache also
* @return boolean true on delete * @return mixed True on delete, null otherwise
*/ */
protected function _clearCache($type = null) { protected function _clearCache($type = null) {
if ($type !== null || Configure::read('Cache.check') !== true) { if ($type !== null || Configure::read('Cache.check') !== true) {
return; return;
} }
$assoc[] = strtolower(Inflector::pluralize($this->alias)); $pluralized = Inflector::pluralize($this->alias);
$assoc[] = Inflector::underscore(Inflector::pluralize($this->alias)); $assoc = array(
strtolower($pluralized),
Inflector::underscore($pluralized)
);
foreach ($this->_associations as $association) { foreach ($this->_associations as $association) {
foreach ($this->$association as $className) { foreach ($this->{$association} as $className) {
$pluralized = strtolower(Inflector::pluralize($className['className'])); $pluralizedAssociation = Inflector::pluralize($className['className']);
if (!in_array($pluralized, $assoc)) { if (!in_array(strtolower($pluralizedAssociation), $assoc)) {
$assoc[] = $pluralized; $assoc = array_merge($assoc, array(
$assoc[] = Inflector::underscore(Inflector::pluralize($className['className'])); strtolower($pluralizedAssociation),
Inflector::underscore($pluralizedAssociation)
));
} }
} }
} }
$assoc = array_unique($assoc); clearCache(array_unique($assoc));
clearCache($assoc);
return true; return true;
} }

View file

@ -141,7 +141,7 @@ class ModelValidator implements ArrayAccess, IteratorAggregate, Countable {
if (!empty($options['deep']) && isset($data[$model->alias])) { if (!empty($options['deep']) && isset($data[$model->alias])) {
$recordData = $data[$model->alias]; $recordData = $data[$model->alias];
unset($data[$model->alias]); unset($data[$model->alias]);
$data = array_merge($data, $recordData); $data += $recordData;
} }
$associations = $model->getAssociated(); $associations = $model->getAssociated();

View file

@ -300,6 +300,7 @@ class CakeResponse {
'webapp' => 'application/x-web-app-manifest+json', 'webapp' => 'application/x-web-app-manifest+json',
'vcf' => 'text/x-vcard', 'vcf' => 'text/x-vcard',
'vtt' => 'text/vtt', 'vtt' => 'text/vtt',
'mkv' => 'video/x-matroska',
); );
/** /**
@ -1281,7 +1282,7 @@ class CakeResponse {
$agent = env('HTTP_USER_AGENT'); $agent = env('HTTP_USER_AGENT');
if (preg_match('%Opera(/| )([0-9].[0-9]{1,2})%', $agent)) { if (preg_match('%Opera(/| )([0-9].[0-9]{1,2})%', $agent)) {
$contentType = 'application/octetstream'; $contentType = 'application/octet-stream';
} elseif (preg_match('/MSIE ([0-9].[0-9]{1,2})/', $agent)) { } elseif (preg_match('/MSIE ([0-9].[0-9]{1,2})/', $agent)) {
$contentType = 'application/force-download'; $contentType = 'application/force-download';
} }
@ -1296,6 +1297,7 @@ class CakeResponse {
} }
$this->download($name); $this->download($name);
$this->header('Accept-Ranges', 'bytes'); $this->header('Accept-Ranges', 'bytes');
$this->header('Content-Transfer-Encoding', 'binary');
$httpRange = env('HTTP_RANGE'); $httpRange = env('HTTP_RANGE');
if (isset($httpRange)) { if (isset($httpRange)) {
@ -1373,6 +1375,7 @@ class CakeResponse {
$bufferSize = 8192; $bufferSize = 8192;
set_time_limit(0); set_time_limit(0);
session_write_close();
while (!feof($file->handle)) { while (!feof($file->handle)) {
if (!$this->_isActive()) { if (!$this->_isActive()) {
$file->close(); $file->close();

View file

@ -326,7 +326,7 @@ class CakeEmail {
protected $_emailPattern = null; protected $_emailPattern = null;
/** /**
* The classname used for email configuration. * The class name used for email configuration.
* *
* @var string * @var string
*/ */

View file

@ -42,9 +42,10 @@ class MailTransport extends AbstractTransport {
unset($headers['To']); unset($headers['To']);
$headers = $this->_headersToString($headers, $eol); $headers = $this->_headersToString($headers, $eol);
$message = implode($eol, $email->message()); $message = implode($eol, $email->message());
$subject = str_replace(array("\r", "\n"), '', $email->subject());
$params = isset($this->_config['additionalParameters']) ? $this->_config['additionalParameters'] : null; $params = isset($this->_config['additionalParameters']) ? $this->_config['additionalParameters'] : null;
$this->_mail($to, $email->subject(), $message, $headers, $params); $this->_mail($to, $subject, $message, $headers, $params);
return array('headers' => $headers, 'message' => $message); return array('headers' => $headers, 'message' => $message);
} }

View file

@ -78,7 +78,7 @@ class HttpSocket extends CakeSocket {
public $response = null; public $response = null;
/** /**
* Response classname * Response class name
* *
* @var string * @var string
*/ */
@ -134,7 +134,7 @@ class HttpSocket extends CakeSocket {
/** /**
* Build an HTTP Socket using the specified configuration. * Build an HTTP Socket using the specified configuration.
* *
* You can use an URL string to set the URL and use default configurations for * You can use a URL string to set the URL and use default configurations for
* all other options: * all other options:
* *
* `$http = new HttpSocket('http://cakephp.org/');` * `$http = new HttpSocket('http://cakephp.org/');`
@ -464,7 +464,7 @@ class HttpSocket extends CakeSocket {
/** /**
* Issues a POST request to the specified URI, query, and request. * Issues a POST request to the specified URI, query, and request.
* *
* `post()` can be used to post simple data arrays to an URL: * `post()` can be used to post simple data arrays to a URL:
* *
* {{{ * {{{
* $response = $http->post('http://example.com', array( * $response = $http->post('http://example.com', array(
@ -545,7 +545,7 @@ class HttpSocket extends CakeSocket {
* *
* Would return `/search?q=socket`. * Would return `/search?q=socket`.
* *
* @param string|array Either a string or array of URL options to create an URL with. * @param string|array Either a string or array of URL options to create a URL with.
* @param string $uriTemplate A template string to use for URL formatting. * @param string $uriTemplate A template string to use for URL formatting.
* @return mixed Either false on failure or a string containing the composed URL. * @return mixed Either false on failure or a string containing the composed URL.
*/ */

View file

@ -192,9 +192,7 @@ class Dispatcher implements CakeEventListener {
if ($render && $controller->autoRender) { if ($render && $controller->autoRender) {
$response = $controller->render(); $response = $controller->render();
} elseif (!($result instanceof CakeResponse) && } elseif (!($result instanceof CakeResponse) && $response->body() === null) {
$response->body() === null
) {
$response->body($result); $response->body($result);
} }
$controller->shutdownProcess(); $controller->shutdownProcess();
@ -240,7 +238,7 @@ class Dispatcher implements CakeEventListener {
} }
/** /**
* Load controller and return controller classname * Load controller and return controller class name
* *
* @param CakeRequest $request * @param CakeRequest $request
* @return string|boolean Name of controller class name * @return string|boolean Name of controller class name

View file

@ -369,9 +369,9 @@ class CakeRoute {
} }
/** /**
* Apply persistent parameters to an URL array. Persistent parameters are a special * Apply persistent parameters to a URL array. Persistent parameters are a special
* key used during route creation to force route parameters to persist when omitted from * key used during route creation to force route parameters to persist when omitted from
* an URL array. * a URL array.
* *
* @param array $url The array to apply persistent parameters to. * @param array $url The array to apply persistent parameters to.
* @param array $params An array of persistent values to replace persistent ones. * @param array $params An array of persistent values to replace persistent ones.
@ -390,7 +390,7 @@ class CakeRoute {
} }
/** /**
* Check if an URL array matches this route instance. * Check if a URL array matches this route instance.
* *
* If the URL matches the route parameters and settings, then * If the URL matches the route parameters and settings, then
* return a generated string URL. If the URL doesn't match the route parameters, false will be returned. * return a generated string URL. If the URL doesn't match the route parameters, false will be returned.
@ -485,7 +485,7 @@ class CakeRoute {
} }
/** /**
* Converts a matching route array into an URL string. * Converts a matching route array into a URL string.
* *
* Composes the string URL using the template * Composes the string URL using the template
* used to create the route. * used to create the route.

View file

@ -41,7 +41,7 @@ class RedirectRoute extends CakeRoute {
public $redirect; public $redirect;
/** /**
* Flag for disabling exit() when this route parses an URL. * Flag for disabling exit() when this route parses a URL.
* *
* @var boolean * @var boolean
*/ */

View file

@ -80,7 +80,7 @@ class Router {
protected static $_parseExtensions = false; protected static $_parseExtensions = false;
/** /**
* List of valid extensions to parse from an URL. If null, any extension is allowed. * List of valid extensions to parse from a URL. If null, any extension is allowed.
* *
* @var array * @var array
*/ */
@ -278,7 +278,7 @@ class Router {
* - `pass` is used to define which of the routed parameters should be shifted into the pass array. Adding a * - `pass` is used to define which of the routed parameters should be shifted into the pass array. Adding a
* parameter to pass will remove it from the regular route array. Ex. `'pass' => array('slug')` * parameter to pass will remove it from the regular route array. Ex. `'pass' => array('slug')`
* - `persist` is used to define which route parameters should be automatically included when generating * - `persist` is used to define which route parameters should be automatically included when generating
* new URLs. You can override persistent parameters by redefining them in an URL or remove them by * new URLs. You can override persistent parameters by redefining them in a URL or remove them by
* setting the parameter to `false`. Ex. `'persist' => array('lang')` * setting the parameter to `false`. Ex. `'persist' => array('lang')`
* - `routeClass` is used to extend and change how individual routes parse requests and handle reverse routing, * - `routeClass` is used to extend and change how individual routes parse requests and handle reverse routing,
* via a custom routing class. Ex. `'routeClass' => 'SlugRoute'` * via a custom routing class. Ex. `'routeClass' => 'SlugRoute'`
@ -359,7 +359,7 @@ class Router {
* `Router::redirect('/home/*', array('controller' => 'posts', 'action' => 'view'), array('persist' => true));` * `Router::redirect('/home/*', array('controller' => 'posts', 'action' => 'view'), array('persist' => true));`
* *
* Redirects /home/* to /posts/view and passes the parameters to /posts/view. Using an array as the * Redirects /home/* to /posts/view and passes the parameters to /posts/view. Using an array as the
* redirect destination allows you to use other routes to define where an URL string should be redirected to. * redirect destination allows you to use other routes to define where a URL string should be redirected to.
* *
* `Router::redirect('/posts/*', 'http://google.com', array('status' => 302));` * `Router::redirect('/posts/*', 'http://google.com', array('status' => 302));`
* *
@ -595,7 +595,7 @@ class Router {
} }
/** /**
* Parses a file extension out of an URL, if Router::parseExtensions() is enabled. * Parses a file extension out of a URL, if Router::parseExtensions() is enabled.
* *
* @param string $url * @param string $url
* @return array Returns an array containing the altered URL and the parsed extension. * @return array Returns an array containing the altered URL and the parsed extension.
@ -764,7 +764,7 @@ class Router {
/** /**
* Finds URL for specified action. * Finds URL for specified action.
* *
* Returns an URL pointing to a combination of controller and action. Param * Returns a URL pointing to a combination of controller and action. Param
* $url can be: * $url can be:
* *
* - Empty - the method will find address to actual controller/action. * - Empty - the method will find address to actual controller/action.
@ -944,7 +944,7 @@ class Router {
* A special fallback method that handles URL arrays that cannot match * A special fallback method that handles URL arrays that cannot match
* any defined routes. * any defined routes.
* *
* @param array $url An URL that didn't match any routes * @param array $url A URL that didn't match any routes
* @return string A generated URL for the array * @return string A generated URL for the array
* @see Router::url() * @see Router::url()
*/ */
@ -1091,7 +1091,7 @@ class Router {
} }
/** /**
* Normalizes an URL for purposes of comparison. * Normalizes a URL for purposes of comparison.
* *
* Will strip the base path off and replace any double /'s. * Will strip the base path off and replace any double /'s.
* It will not unify the casing and underscoring of the input value. * It will not unify the casing and underscoring of the input value.

View file

@ -637,7 +637,7 @@ class SchemaShellTest extends CakeTestCase {
/** /**
* test that passing name and file creates the passed filename with the * test that passing name and file creates the passed filename with the
* passed classname * passed class name
* *
* @return void * @return void
*/ */

View file

@ -149,7 +149,7 @@ class ExtractTaskTest extends CakeTestCase {
$this->assertRegExp($pattern, $result); $this->assertRegExp($pattern, $result);
$pattern = '/\#: (\\\\|\/)extract\.ctp:14\n'; $pattern = '/\#: (\\\\|\/)extract\.ctp:14\n';
$pattern .= '\#: (\\\\|\/)home\.ctp:83\n'; $pattern .= '\#: (\\\\|\/)home\.ctp:68\n';
$pattern .= 'msgid "Editing this Page"\nmsgstr ""/'; $pattern .= 'msgid "Editing this Page"\nmsgstr ""/';
$this->assertRegExp($pattern, $result); $this->assertRegExp($pattern, $result);

View file

@ -324,7 +324,7 @@ class TestTaskTest extends CakeTestCase {
} }
/** /**
* test that getClassName returns the user choice as a classname. * test that getClassName returns the user choice as a class name.
* *
* @return void * @return void
*/ */
@ -359,7 +359,7 @@ class TestTaskTest extends CakeTestCase {
} }
/** /**
* test that resolving classnames works * test that resolving class names works
* *
* @return void * @return void
*/ */
@ -394,7 +394,7 @@ class TestTaskTest extends CakeTestCase {
/** /**
* test baking files. The conditionally run tests are known to fail in PHP4 * test baking files. The conditionally run tests are known to fail in PHP4
* as PHP4 classnames are all lower case, breaking the plugin path inflection. * as PHP4 class names are all lower case, breaking the plugin path inflection.
* *
* @return void * @return void
*/ */

View file

@ -327,6 +327,44 @@ class CookieComponentTest extends CakeTestCase {
$this->assertEquals($expected, $result); $this->assertEquals($expected, $result);
} }
/**
* Test that writing mixed arrays results in the correct data.
*
* @return void
*/
public function testWriteMixedArray() {
$this->Cookie->encrypt = false;
$this->Cookie->write('User', array('name' => 'mark'), false);
$this->Cookie->write('User.email', 'mark@example.com', false);
$expected = array(
'name' => $this->Cookie->name . '[User]',
'value' => '{"name":"mark","email":"mark@example.com"}',
'path' => '/',
'domain' => '',
'secure' => false,
'httpOnly' => false
);
$result = $this->Controller->response->cookie($this->Cookie->name . '[User]');
unset($result['expire']);
$this->assertEquals($expected, $result);
$this->Cookie->write('User.email', 'mark@example.com', false);
$this->Cookie->write('User', array('name' => 'mark'), false);
$expected = array(
'name' => $this->Cookie->name . '[User]',
'value' => '{"name":"mark"}',
'path' => '/',
'domain' => '',
'secure' => false,
'httpOnly' => false
);
$result = $this->Controller->response->cookie($this->Cookie->name . '[User]');
unset($result['expire']);
$this->assertEquals($expected, $result);
}
/** /**
* testReadingCookieValue * testReadingCookieValue
* *

View file

@ -682,6 +682,65 @@ class ContainableBehaviorTest extends CakeTestCase {
); );
$this->assertEquals($expected, $result); $this->assertEquals($expected, $result);
$this->Article->contain(array('User' => array('id', 'ArticleFeatured')));
$result = $this->Article->find('all', array('recursive' => 2));
$expected = array(
array(
'Article' => array(
'id' => 1, 'user_id' => 1, 'title' => 'First Article', 'body' => 'First Article Body',
'published' => 'Y', 'created' => '2007-03-18 10:39:23', 'updated' => '2007-03-18 10:41:31'
),
'User' => array(
'id' => 1,
'ArticleFeatured' => array(
array(
'id' => 1, 'user_id' => 1, 'title' => 'First Article', 'body' => 'First Article Body',
'published' => 'Y', 'created' => '2007-03-18 10:39:23', 'updated' => '2007-03-18 10:41:31'
),
array(
'id' => 3, 'user_id' => 1, 'title' => 'Third Article', 'body' => 'Third Article Body',
'published' => 'Y', 'created' => '2007-03-18 10:43:23', 'updated' => '2007-03-18 10:45:31'
)
)
)
),
array(
'Article' => array(
'id' => 2, 'user_id' => 3, 'title' => 'Second Article', 'body' => 'Second Article Body',
'published' => 'Y', 'created' => '2007-03-18 10:41:23', 'updated' => '2007-03-18 10:43:31'
),
'User' => array(
'id' => 3,
'ArticleFeatured' => array(
array(
'id' => 2, 'user_id' => 3, 'title' => 'Second Article', 'body' => 'Second Article Body',
'published' => 'Y', 'created' => '2007-03-18 10:41:23', 'updated' => '2007-03-18 10:43:31'
)
)
)
),
array(
'Article' => array(
'id' => 3, 'user_id' => 1, 'title' => 'Third Article', 'body' => 'Third Article Body',
'published' => 'Y', 'created' => '2007-03-18 10:43:23', 'updated' => '2007-03-18 10:45:31'
),
'User' => array(
'id' => 1,
'ArticleFeatured' => array(
array(
'id' => 1, 'user_id' => 1, 'title' => 'First Article', 'body' => 'First Article Body',
'published' => 'Y', 'created' => '2007-03-18 10:39:23', 'updated' => '2007-03-18 10:41:31'
),
array(
'id' => 3, 'user_id' => 1, 'title' => 'Third Article', 'body' => 'Third Article Body',
'published' => 'Y', 'created' => '2007-03-18 10:43:23', 'updated' => '2007-03-18 10:45:31'
)
)
)
)
);
$this->assertEquals($expected, $result);
$this->Article->contain(array('User' => array('ArticleFeatured', 'Comment'))); $this->Article->contain(array('User' => array('ArticleFeatured', 'Comment')));
$result = $this->Article->find('all', array('recursive' => 2)); $result = $this->Article->find('all', array('recursive' => 2));
$expected = array( $expected = array(

View file

@ -1206,7 +1206,7 @@ class MysqlTest extends CakeTestCase {
$this->assertRegExp('/^SELECT\s+`TestModel4`\.`id`, `TestModel4`\.`name`, `TestModel4`\.`created`, `TestModel4`\.`updated`, `TestModel4Parent`\.`id`, `TestModel4Parent`\.`name`, `TestModel4Parent`\.`created`, `TestModel4Parent`\.`updated`\s+/', $result); $this->assertRegExp('/^SELECT\s+`TestModel4`\.`id`, `TestModel4`\.`name`, `TestModel4`\.`created`, `TestModel4`\.`updated`, `TestModel4Parent`\.`id`, `TestModel4Parent`\.`name`, `TestModel4Parent`\.`created`, `TestModel4Parent`\.`updated`\s+/', $result);
$this->assertRegExp('/FROM\s+\S+`test_model4` AS `TestModel4`\s+LEFT JOIN\s+\S+`test_model4` AS `TestModel4Parent`/', $result); $this->assertRegExp('/FROM\s+\S+`test_model4` AS `TestModel4`\s+LEFT JOIN\s+\S+`test_model4` AS `TestModel4Parent`/', $result);
$this->assertRegExp('/\s+ON\s+\(`TestModel4`.`parent_id` = `TestModel4Parent`.`id`\)\s+WHERE/', $result); $this->assertRegExp('/\s+ON\s+\(`TestModel4`.`parent_id` = `TestModel4Parent`.`id`\)\s+WHERE/', $result);
$this->assertRegExp('/\s+WHERE\s+1 = 1\s+$/', $result); $this->assertRegExp('/\s+WHERE\s+1 = 1$/', $result);
$params['assocData']['type'] = 'INNER'; $params['assocData']['type'] = 'INNER';
$this->Model->belongsTo['TestModel4Parent']['type'] = 'INNER'; $this->Model->belongsTo['TestModel4Parent']['type'] = 'INNER';

View file

@ -1143,7 +1143,7 @@ class DboSourceTest extends CakeTestCase {
), ),
$this->Model $this->Model
); );
$expected = 'SELECT DISTINCT(AssetsTag.asset_id) FROM assets_tags AS AssetsTag WHERE Tag.name = foo bar GROUP BY AssetsTag.asset_id '; $expected = 'SELECT DISTINCT(AssetsTag.asset_id) FROM assets_tags AS AssetsTag WHERE Tag.name = foo bar GROUP BY AssetsTag.asset_id';
$this->assertEquals($expected, $subQuery); $this->assertEquals($expected, $subQuery);
} }

View file

@ -1132,6 +1132,10 @@ class CakeResponseTest extends CakeTestCase {
->with('Accept-Ranges', 'bytes'); ->with('Accept-Ranges', 'bytes');
$response->expects($this->at(3)) $response->expects($this->at(3))
->method('header')
->with('Content-Transfer-Encoding', 'binary');
$response->expects($this->at(4))
->method('header') ->method('header')
->with('Content-Length', 35); ->with('Content-Length', 35);
@ -1181,7 +1185,7 @@ class CakeResponseTest extends CakeTestCase {
$response->expects($this->at(1)) $response->expects($this->at(1))
->method('type') ->method('type')
->with('application/octetstream') ->with('application/octet-stream')
->will($this->returnValue(false)); ->will($this->returnValue(false));
$response->expects($this->once()) $response->expects($this->once())
@ -1193,6 +1197,10 @@ class CakeResponseTest extends CakeTestCase {
->with('Accept-Ranges', 'bytes'); ->with('Accept-Ranges', 'bytes');
$response->expects($this->at(4)) $response->expects($this->at(4))
->method('header')
->with('Content-Transfer-Encoding', 'binary');
$response->expects($this->at(5))
->method('header') ->method('header')
->with('Content-Length', 35); ->with('Content-Length', 35);
@ -1253,6 +1261,10 @@ class CakeResponseTest extends CakeTestCase {
->with('Accept-Ranges', 'bytes'); ->with('Accept-Ranges', 'bytes');
$response->expects($this->at(4)) $response->expects($this->at(4))
->method('header')
->with('Content-Transfer-Encoding', 'binary');
$response->expects($this->at(5))
->method('header') ->method('header')
->with('Content-Length', 35); ->with('Content-Length', 35);
@ -1455,6 +1467,10 @@ class CakeResponseTest extends CakeTestCase {
->with('Accept-Ranges', 'bytes'); ->with('Accept-Ranges', 'bytes');
$response->expects($this->at(3)) $response->expects($this->at(3))
->method('header')
->with('Content-Transfer-Encoding', 'binary');
$response->expects($this->at(4))
->method('header') ->method('header')
->with(array( ->with(array(
'Content-Length' => $length, 'Content-Length' => $length,
@ -1506,6 +1522,10 @@ class CakeResponseTest extends CakeTestCase {
->with('Accept-Ranges', 'bytes'); ->with('Accept-Ranges', 'bytes');
$response->expects($this->at(3)) $response->expects($this->at(3))
->method('header')
->with('Content-Transfer-Encoding', 'binary');
$response->expects($this->at(4))
->method('header') ->method('header')
->with(array( ->with(array(
'Content-Length' => 18, 'Content-Length' => 18,
@ -1557,6 +1577,10 @@ class CakeResponseTest extends CakeTestCase {
->with('Accept-Ranges', 'bytes'); ->with('Accept-Ranges', 'bytes');
$response->expects($this->at(3)) $response->expects($this->at(3))
->method('header')
->with('Content-Transfer-Encoding', 'binary');
$response->expects($this->at(4))
->method('header') ->method('header')
->with(array( ->with(array(
'Content-Range' => 'bytes 0-37/38', 'Content-Range' => 'bytes 0-37/38',

View file

@ -27,7 +27,7 @@ App::uses('CakeEmail', 'Network/Email');
class TestCakeEmail extends CakeEmail { class TestCakeEmail extends CakeEmail {
/** /**
* Config classname. * Config class name.
* *
* Use a the testing config class in this file. * Use a the testing config class in this file.
* *

View file

@ -69,7 +69,7 @@ class MailTransportTest extends CakeTestCase {
$data .= "Content-Transfer-Encoding: 8bit"; $data .= "Content-Transfer-Encoding: 8bit";
$subject = '=?UTF-8?B?Rm/DuCBCw6VyIELDqXogRm/DuCBCw6VyIELDqXogRm/DuCBCw6VyIELDqXog?='; $subject = '=?UTF-8?B?Rm/DuCBCw6VyIELDqXogRm/DuCBCw6VyIELDqXogRm/DuCBCw6VyIELDqXog?=';
$subject .= "\r\n" . ' =?UTF-8?B?Rm/DuCBCw6VyIELDqXo=?='; $subject .= ' =?UTF-8?B?Rm/DuCBCw6VyIELDqXo=?=';
$this->MailTransport->expects($this->once())->method('_mail') $this->MailTransport->expects($this->once())->method('_mail')
->with( ->with(
'CakePHP <cake@cakephp.org>', 'CakePHP <cake@cakephp.org>',

View file

@ -396,7 +396,7 @@ class FileTest extends CakeTestCase {
public function testWrite() { public function testWrite() {
if (!$tmpFile = $this->_getTmpFile()) { if (!$tmpFile = $this->_getTmpFile()) {
return false; return false;
}; }
if (file_exists($tmpFile)) { if (file_exists($tmpFile)) {
unlink($tmpFile); unlink($tmpFile);
} }
@ -426,7 +426,7 @@ class FileTest extends CakeTestCase {
public function testAppend() { public function testAppend() {
if (!$tmpFile = $this->_getTmpFile()) { if (!$tmpFile = $this->_getTmpFile()) {
return false; return false;
}; }
if (file_exists($tmpFile)) { if (file_exists($tmpFile)) {
unlink($tmpFile); unlink($tmpFile);
} }

View file

@ -120,6 +120,9 @@ class InflectorTest extends CakeTestCase {
$this->assertEquals(Inflector::singularize('objectives'), 'objective'); $this->assertEquals(Inflector::singularize('objectives'), 'objective');
$this->assertEquals(Inflector::singularize('archives'), 'archive'); $this->assertEquals(Inflector::singularize('archives'), 'archive');
$this->assertEquals(Inflector::singularize('briefs'), 'brief'); $this->assertEquals(Inflector::singularize('briefs'), 'brief');
$this->assertEquals(Inflector::singularize('quotas'), 'quota');
$this->assertEquals(Inflector::singularize('curves'), 'curve');
$this->assertEquals(Inflector::singularize('body_curves'), 'body_curve');
$this->assertEquals(Inflector::singularize(''), ''); $this->assertEquals(Inflector::singularize(''), '');
} }
@ -181,6 +184,9 @@ class InflectorTest extends CakeTestCase {
$this->assertEquals(Inflector::pluralize('foot'), 'feet'); $this->assertEquals(Inflector::pluralize('foot'), 'feet');
$this->assertEquals(Inflector::pluralize('objective'), 'objectives'); $this->assertEquals(Inflector::pluralize('objective'), 'objectives');
$this->assertEquals(Inflector::pluralize('brief'), 'briefs'); $this->assertEquals(Inflector::pluralize('brief'), 'briefs');
$this->assertEquals(Inflector::pluralize('quota'), 'quotas');
$this->assertEquals(Inflector::pluralize('curve'), 'curves');
$this->assertEquals(Inflector::pluralize('body_curve'), 'body_curves');
$this->assertEquals(Inflector::pluralize(''), ''); $this->assertEquals(Inflector::pluralize(''), '');
} }

View file

@ -219,6 +219,17 @@ class JqueryEngineHelperTest extends CakeTestCase {
)); ));
$expected = '$.ajax({beforeSend:function (XMLHttpRequest) {doBefore}, data:$("#someId").serialize(), success:function (data, textStatus) {doFoo}, type:"post", url:"\\/people\\/edit\\/1"});'; $expected = '$.ajax({beforeSend:function (XMLHttpRequest) {doBefore}, data:$("#someId").serialize(), success:function (data, textStatus) {doFoo}, type:"post", url:"\\/people\\/edit\\/1"});';
$this->assertEquals($expected, $result); $this->assertEquals($expected, $result);
$result = $this->Jquery->request('/people/edit/1', array(
'success' => 'doFoo',
'xhr' => 'return jQuery.ajaxSettings.xhr();',
'async' => true,
'method' => 'post',
'dataExpression' => true,
'data' => '$("#someId").serialize()',
));
$expected = '$.ajax({async:true, data:$("#someId").serialize(), success:function (data, textStatus) {doFoo}, type:"post", url:"\/people\/edit\/1", xhr:function () {return jQuery.ajaxSettings.xhr();}});';
$this->assertEquals($expected, $result);
} }
/** /**

View file

@ -1515,6 +1515,20 @@ class ViewTest extends CakeTestCase {
$this->assertEquals('In second', $this->View->fetch('second')); $this->assertEquals('In second', $this->View->fetch('second'));
} }
/**
* Test that starting the same block twice throws an exception
*
* @expectedException CakeException
* @return void
*/
public function testStartBlocksTwice() {
$this->View->start('first');
echo 'In first ';
$this->View->start('second');
echo 'In second';
$this->View->start('first');
}
/** /**
* Test that an exception gets thrown when you leave a block open at the end * Test that an exception gets thrown when you leave a block open at the end
* of a view. * of a view.

View file

@ -1,8 +1,3 @@
<?php
App::uses('Debugger', 'Utility');
?>
<h2><?php echo __d('cake_dev', 'Release Notes for CakePHP %s.', Configure::version()); ?></h2>
<a href="http://cakephp.org/changelogs/1.3.6"><?php echo __d('cake_dev', 'Read the changelog'); ?> </a>
<p> <p>
<?php <?php
if (is_writable(TMP)): if (is_writable(TMP)):
@ -70,78 +65,8 @@ if (isset($filePresent)):
?> ?>
</p> </p>
<?php endif; ?> <?php endif; ?>
<?php
App::uses('Validation', 'Utility');
if (!Validation::alphaNumeric('cakephp')) {
echo '<p><span class="notice">';
__('PCRE has not been compiled with Unicode support.');
echo '<br/>';
__('Recompile PCRE with Unicode support by adding <code>--enable-unicode-properties</code> when configuring');
echo '</span></p>';
}
?>
<h3><?php echo __d('cake_dev', 'Editing this Page'); ?></h3> <h3><?php echo __d('cake_dev', 'Editing this Page'); ?></h3>
<p>
<?php <?php
echo __d('cake_dev', 'To change the content of this page, create: APP/views/pages/home.ctp.<br /> echo __d('cake_dev', 'To change the content of this page, create: APP/views/pages/home.ctp.<br />
To change its layout, create: APP/views/layouts/default.ctp.<br /> To change its layout, create: APP/views/layouts/default.ctp.<br />
You can also add some CSS styles for your pages at: APP/webroot/css.'); You can also add some CSS styles for your pages at: APP/webroot/css.');
?>
</p>
<h3><?php echo __d('cake_dev', 'Getting Started'); ?></h3>
<p>
<?php
echo $this->Html->link(
sprintf('<strong>%s</strong> %s', __d('cake_dev', 'New'), __d('cake_dev', 'CakePHP 1.3 Docs')),
'http://book.cakephp.org/view/875/x1-3-Collection',
array('target' => '_blank', 'escape' => false)
);
?>
</p>
<p>
<?php
echo $this->Html->link(
__d('cake_dev', 'The 15 min Blog Tutorial'),
'http://book.cakephp.org/view/1528/Blog',
array('target' => '_blank', 'escape' => false)
);
?>
</p>
<h3><?php echo __d('cake_dev', 'More about Cake'); ?></h3>
<p>
<?php echo __d('cake_dev', 'CakePHP is a rapid development framework for PHP which uses commonly known design patterns like Active Record, Association Data Mapping, Front Controller and MVC.'); ?>
</p>
<p>
<?php echo __d('cake_dev', 'Our primary goal is to provide a structured framework that enables PHP users at all levels to rapidly develop robust web applications, without any loss to flexibility.'); ?>
</p>
<ul>
<li><a href="http://cakefoundation.org/"><?php echo __d('cake_dev', 'Cake Software Foundation'); ?> </a>
<ul><li><?php echo __d('cake_dev', 'Promoting development related to CakePHP'); ?></li></ul></li>
<li><a href="http://www.cakephp.org"><?php echo __d('cake_dev', 'CakePHP'); ?> </a>
<ul><li><?php echo __d('cake_dev', 'The Rapid Development Framework'); ?></li></ul></li>
<li><a href="http://book.cakephp.org"><?php echo __d('cake_dev', 'CakePHP Documentation'); ?> </a>
<ul><li><?php echo __d('cake_dev', 'Your Rapid Development Cookbook'); ?></li></ul></li>
<li><a href="http://api.cakephp.org"><?php echo __d('cake_dev', 'CakePHP API'); ?> </a>
<ul><li><?php echo __d('cake_dev', 'Quick Reference'); ?></li></ul></li>
<li><a href="http://bakery.cakephp.org"><?php echo __d('cake_dev', 'The Bakery'); ?> </a>
<ul><li><?php echo __d('cake_dev', 'Everything CakePHP'); ?></li></ul></li>
<li><a href="http://live.cakephp.org"><?php echo __d('cake_dev', 'The Show'); ?> </a>
<ul><li><?php echo __d('cake_dev', 'The Show is a live and archived internet radio broadcast CakePHP-related topics and answer questions live via IRC, Skype, and telephone.'); ?></li></ul></li>
<li><a href="http://groups.google.com/group/cake-php"><?php echo __d('cake_dev', 'CakePHP Google Group'); ?> </a>
<ul><li><?php echo __d('cake_dev', 'Community mailing list'); ?></li></ul></li>
<li><a href="irc://irc.freenode.net/cakephp">irc.freenode.net #cakephp</a>
<ul><li><?php echo __d('cake_dev', 'Live chat about CakePHP'); ?></li></ul></li>
<li><a href="https://github.com/cakephp/"><?php echo __d('cake_dev', 'CakePHP Code'); ?> </a>
<ul><li><?php echo __d('cake_dev', 'For the Development of CakePHP Git repository, Downloads'); ?></li></ul></li>
<li><a href="https://cakephp.lighthouseapp.com/"><?php echo __d('cake_dev', 'CakePHP Lighthouse'); ?> </a>
<ul><li><?php echo __d('cake_dev', 'CakePHP Tickets, Wiki pages, Roadmap'); ?></li></ul></li>
<li><a href="http://www.cakeforge.org"><?php echo __d('cake_dev', 'CakeForge'); ?> </a>
<ul><li><?php echo __d('cake_dev', 'Open Development for CakePHP'); ?></li></ul></li>
<li><a href="http://astore.amazon.com/cakesoftwaref-20/"><?php echo __d('cake_dev', 'Book Store'); ?> </a>
<ul><li><?php echo __d('cake_dev', 'Recommended Software Books'); ?></li></ul></li>
<li><a href="http://www.cafepress.com/cakefoundation"><?php echo __d('cake_dev', 'CakePHP gear'); ?> </a>
<ul><li><?php echo __d('cake_dev', 'Get your own CakePHP gear - Doughnate to Cake'); ?></li></ul></li>
</ul>

View file

@ -91,7 +91,7 @@ if (!empty($filePresent)):
<a href="http://www-128.ibm.com/developerworks/edu/os-dw-os-php-cake1.html"><?php echo __d('cake', 'Cook up Web sites fast with CakePHP'); ?></a><br /> <a href="http://www-128.ibm.com/developerworks/edu/os-dw-os-php-cake1.html"><?php echo __d('cake', 'Cook up Web sites fast with CakePHP'); ?></a><br />
<a href="http://www-128.ibm.com/developerworks/edu/os-dw-os-php-wiki1.html"><?php echo __d('cake', 'Create an interactive production wiki using PHP'); ?></a> <a href="http://www-128.ibm.com/developerworks/edu/os-dw-os-php-wiki1.html"><?php echo __d('cake', 'Create an interactive production wiki using PHP'); ?></a>
</p> </p>
<h2><?php echo __d('cake', 'More about Cake'); ?></h2> <h2><?php echo __d('cake', 'More about CakePHP'); ?></h2>
<p> <p>
<?php echo __d('cake', 'CakePHP is a rapid development framework for PHP which uses commonly known design patterns like Active Record, Association Data Mapping, Front Controller and MVC.'); ?> <?php echo __d('cake', 'CakePHP is a rapid development framework for PHP which uses commonly known design patterns like Active Record, Association Data Mapping, Front Controller and MVC.'); ?>
</p> </p>

View file

@ -55,7 +55,7 @@ class CakeTestSuiteCommand extends PHPUnit_TextUI_Command {
} }
/** /**
* Ugly hack to get around PHPUnit having a hard coded classname for the Runner. :( * Ugly hack to get around PHPUnit having a hard coded class name for the Runner. :(
* *
* @param array $argv * @param array $argv
* @param boolean $exit * @param boolean $exit

View file

@ -125,7 +125,7 @@ HTML;
} }
/** /**
* Guess the classname the test was for based on the test case filename. * Guess the class name the test was for based on the test case filename.
* *
* @param ReflectionClass $testReflection. * @param ReflectionClass $testReflection.
* @return string Possible test subject name. * @return string Possible test subject name.

View file

@ -805,7 +805,7 @@ class Debugger {
} }
/** /**
* Get the type of the given variable. Will return the classname * Get the type of the given variable. Will return the class name
* for objects. * for objects.
* *
* @param mixed $var The variable to get the type of * @param mixed $var The variable to get the type of

View file

@ -593,7 +593,7 @@ class Hash {
} }
/** /**
* Expand/unflattens an string to an array * Expands a flat array to a nested array.
* *
* For example, unflattens an array that was collapsed with `Hash::flatten()` * For example, unflattens an array that was collapsed with `Hash::flatten()`
* into a multi-dimensional array. So, `array('0.Foo.Bar' => 'Far')` becomes * into a multi-dimensional array. So, `array('0.Foo.Bar' => 'Far')` becomes

View file

@ -129,8 +129,8 @@ class Inflector {
'/(tive)s$/i' => '\1', '/(tive)s$/i' => '\1',
'/(hive)s$/i' => '\1', '/(hive)s$/i' => '\1',
'/(drive)s$/i' => '\1', '/(drive)s$/i' => '\1',
'/([lre])ves$/i' => '\1f', '/([le])ves$/i' => '\1f',
'/([^fo])ves$/i' => '\1fe', '/([^rfo])ves$/i' => '\1fe',
'/(^analy)ses$/i' => '\1sis', '/(^analy)ses$/i' => '\1sis',
'/(analy|diagno|^ba|(p)arenthe|(p)rogno|(s)ynop|(t)he)ses$/i' => '\1\2sis', '/(analy|diagno|^ba|(p)arenthe|(p)rogno|(s)ynop|(t)he)ses$/i' => '\1\2sis',
'/([ti])a$/i' => '\1um', '/([ti])a$/i' => '\1um',
@ -148,7 +148,6 @@ class Inflector {
'irregular' => array( 'irregular' => array(
'foes' => 'foe', 'foes' => 'foe',
'waves' => 'wave', 'waves' => 'wave',
'curves' => 'curve'
) )
); );

View file

@ -81,7 +81,7 @@ class Xml {
* is disabled by default for security reasons. * is disabled by default for security reasons.
* - If using array as input, you can pass `options` from Xml::fromArray. * - If using array as input, you can pass `options` from Xml::fromArray.
* *
* @param string|array $input XML string, a path to a file, an URL or an array * @param string|array $input XML string, a path to a file, a URL or an array
* @param array $options The options to use * @param array $options The options to use
* @return SimpleXMLElement|DOMDocument SimpleXMLElement or DOMDocument * @return SimpleXMLElement|DOMDocument SimpleXMLElement or DOMDocument
* @throws XmlException * @throws XmlException

View file

@ -196,6 +196,7 @@ class Helper extends Object {
* *
* @param string $name Name of the property being accessed. * @param string $name Name of the property being accessed.
* @return mixed Helper or property found at $name * @return mixed Helper or property found at $name
* @deprecated Accessing request properties through this method is deprecated and will be removed in 3.0.
*/ */
public function __get($name) { public function __get($name) {
if (isset($this->_helperMap[$name]) && !isset($this->{$name})) { if (isset($this->_helperMap[$name]) && !isset($this->{$name})) {
@ -224,6 +225,7 @@ class Helper extends Object {
* @param string $name Name of the property being accessed. * @param string $name Name of the property being accessed.
* @param mixed $value * @param mixed $value
* @return void * @return void
* @deprecated This method will be removed in 3.0
*/ */
public function __set($name, $value) { public function __set($name, $value) {
switch ($name) { switch ($name) {
@ -243,7 +245,7 @@ class Helper extends Object {
/** /**
* Finds URL for specified action. * Finds URL for specified action.
* *
* Returns an URL pointing at the provided parameters. * Returns a URL pointing at the provided parameters.
* *
* @param string|array $url Either a relative string url like `/products/view/23` or * @param string|array $url Either a relative string url like `/products/view/23` or
* an array of URL parameters. Using an array for URLs will allow you to leverage * an array of URL parameters. Using an array for URLs will allow you to leverage
@ -339,7 +341,7 @@ class Helper extends Object {
} }
/** /**
* Encodes an URL for use in HTML attributes. * Encodes a URL for use in HTML attributes.
* *
* @param string $url The URL to encode. * @param string $url The URL to encode.
* @return string The URL encoded for both URL & HTML contexts. * @return string The URL encoded for both URL & HTML contexts.
@ -404,6 +406,7 @@ class Helper extends Object {
* *
* @param string|array $output Either an array of strings to clean or a single string to clean. * @param string|array $output Either an array of strings to clean or a single string to clean.
* @return string|array cleaned content for output * @return string|array cleaned content for output
* @deprecated This method will be removed in 3.0
*/ */
public function clean($output) { public function clean($output) {
$this->_reset(); $this->_reset();
@ -777,7 +780,7 @@ class Helper extends Object {
* Adds the given class to the element options * Adds the given class to the element options
* *
* @param array $options Array options/attributes to add a class to * @param array $options Array options/attributes to add a class to
* @param string $class The classname being added. * @param string $class The class name being added.
* @param string $key the key to use for class. * @param string $key the key to use for class.
* @return array Array of options with $key set. * @return array Array of options with $key set.
*/ */

View file

@ -297,7 +297,7 @@ class FormHelper extends AppHelper {
* *
* - `type` Form method defaults to POST * - `type` Form method defaults to POST
* - `action` The controller action the form submits to, (optional). * - `action` The controller action the form submits to, (optional).
* - `url` The URL the form submits to. Can be a string or an URL array. If you use 'url' * - `url` The URL the form submits to. Can be a string or a URL array. If you use 'url'
* you should leave 'action' undefined. * you should leave 'action' undefined.
* - `default` Allows for the creation of Ajax forms. Set this to false to prevent the default event handler. * - `default` Allows for the creation of Ajax forms. Set this to false to prevent the default event handler.
* Will create an onsubmit attribute if it doesn't not exist. If it does, default action suppression * Will create an onsubmit attribute if it doesn't not exist. If it does, default action suppression
@ -650,7 +650,7 @@ class FormHelper extends AppHelper {
* - `escape` boolean - Whether or not to html escape the contents of the error. * - `escape` boolean - Whether or not to html escape the contents of the error.
* - `wrap` mixed - Whether or not the error message should be wrapped in a div. If a * - `wrap` mixed - Whether or not the error message should be wrapped in a div. If a
* string, will be used as the HTML tag to use. * string, will be used as the HTML tag to use.
* - `class` string - The classname for the error message * - `class` string - The class name for the error message
* *
* @param string $field A field name, like "Modelname.fieldname" * @param string $field A field name, like "Modelname.fieldname"
* @param string|array $text Error message as string or array of messages. * @param string|array $text Error message as string or array of messages.
@ -836,7 +836,7 @@ class FormHelper extends AppHelper {
* @param array $blacklist A simple array of fields to not create inputs for. * @param array $blacklist A simple array of fields to not create inputs for.
* @param array $options Options array. Valid keys are: * @param array $options Options array. Valid keys are:
* - `fieldset` Set to false to disable the fieldset. If a string is supplied it will be used as * - `fieldset` Set to false to disable the fieldset. If a string is supplied it will be used as
* the classname for the fieldset element. * the class name for the fieldset element.
* - `legend` Set to false to disable the legend for the generated input set. Or supply a string * - `legend` Set to false to disable the legend for the generated input set. Or supply a string
* to customize the legend text. * to customize the legend text.
* @return string Completed form inputs. * @return string Completed form inputs.
@ -1917,7 +1917,7 @@ class FormHelper extends AppHelper {
* that string is displayed as the empty element. * that string is displayed as the empty element.
* - `escape` - If true contents of options will be HTML entity encoded. Defaults to true. * - `escape` - If true contents of options will be HTML entity encoded. Defaults to true.
* - `value` The selected value of the input. * - `value` The selected value of the input.
* - `class` - When using multiple = checkbox the classname to apply to the divs. Defaults to 'checkbox'. * - `class` - When using multiple = checkbox the class name to apply to the divs. Defaults to 'checkbox'.
* - `disabled` - Control the disabled attribute. When creating a select box, set to true to disable the * - `disabled` - Control the disabled attribute. When creating a select box, set to true to disable the
* select box. When creating checkboxes, `true` will disable all checkboxes. You can also set disabled * select box. When creating checkboxes, `true` will disable all checkboxes. You can also set disabled
* to a list of values you want to disable when creating checkboxes. * to a list of values you want to disable when creating checkboxes.

View file

@ -271,7 +271,7 @@ class JqueryEngineHelper extends JsBaseEngineHelper {
$options['success'] = $success; $options['success'] = $success;
unset($options['update']); unset($options['update']);
} }
$callbacks = array('success', 'error', 'beforeSend', 'complete'); $callbacks = array('success', 'error', 'beforeSend', 'complete', 'xhr');
if (!empty($options['dataExpression'])) { if (!empty($options['dataExpression'])) {
$callbacks[] = 'data'; $callbacks[] = 'data';
unset($options['dataExpression']); unset($options['dataExpression']);

View file

@ -67,7 +67,7 @@ abstract class JsBaseEngineHelper extends AppHelper {
} }
/** /**
* Redirects to an URL. Creates a window.location modification snippet * Redirects to a URL. Creates a window.location modification snippet
* that can be used to trigger 'redirects' from JavaScript. * that can be used to trigger 'redirects' from JavaScript.
* *
* @param string|array $url URL * @param string|array $url URL

View file

@ -68,6 +68,7 @@ class NumberHelper extends AppHelper {
/** /**
* Call methods from CakeNumber utility class * Call methods from CakeNumber utility class
* @return mixed Whatever is returned by called method, or false on failure
*/ */
public function __call($method, $params) { public function __call($method, $params) {
return call_user_func_array(array($this->_engine, $method), $params); return call_user_func_array(array($this->_engine, $method), $params);

View file

@ -83,6 +83,7 @@ class TextHelper extends AppHelper {
/** /**
* Call methods from String utility class * Call methods from String utility class
* @return mixed Whatever is returned by called method, or false on failure
*/ */
public function __call($method, $params) { public function __call($method, $params) {
return call_user_func_array(array($this->_engine, $method), $params); return call_user_func_array(array($this->_engine, $method), $params);

View file

@ -117,6 +117,7 @@ class TimeHelper extends AppHelper {
/** /**
* Call methods from CakeTime utility class * Call methods from CakeTime utility class
* @return mixed Whatever is returned by called method, or false on failure
*/ */
public function __call($method, $params) { public function __call($method, $params) {
return call_user_func_array(array($this->_engine, $method), $params); return call_user_func_array(array($this->_engine, $method), $params);
@ -350,7 +351,7 @@ class TimeHelper extends AppHelper {
* - `element` - The element to wrap the formatted time in. * - `element` - The element to wrap the formatted time in.
* Has a few additional options: * Has a few additional options:
* - `tag` - The tag to use, defaults to 'span'. * - `tag` - The tag to use, defaults to 'span'.
* - `class` - The classname to use, defaults to `time-ago-in-words`. * - `class` - The class name to use, defaults to `time-ago-in-words`.
* - `title` - Defaults to the $dateTime input. * - `title` - Defaults to the $dateTime input.
* *
* @param integer|string|DateTime $dateTime UNIX timestamp, strtotime() valid string or DateTime object * @param integer|string|DateTime $dateTime UNIX timestamp, strtotime() valid string or DateTime object

View file

@ -539,7 +539,7 @@ class View extends Object {
public function renderCache($filename, $timeStart) { public function renderCache($filename, $timeStart) {
$response = $this->response; $response = $this->response;
ob_start(); ob_start();
include ($filename); include $filename;
$type = $response->mapType($response->type()); $type = $response->mapType($response->type());
if (Configure::read('debug') > 0 && $type === 'html') { if (Configure::read('debug') > 0 && $type === 'html') {

View file

@ -72,9 +72,13 @@ class ViewBlock {
* using View::get(); * using View::get();
* *
* @param string $name The name of the block to capture for. * @param string $name The name of the block to capture for.
* @throws CakeException When starting a block twice
* @return void * @return void
*/ */
public function start($name) { public function start($name) {
if (in_array($name, $this->_active)) {
throw new CakeException(__("A view block with the name '%s' is already/still open.", $name));
}
$this->_active[] = $name; $this->_active[] = $name;
ob_start(); ob_start();
} }

View file

@ -125,22 +125,22 @@ TEXT;
if (!function_exists('sortByKey')) { if (!function_exists('sortByKey')) {
/** /**
* Sorts given $array by key $sortby. * Sorts given $array by key $sortBy.
* *
* @param array $array Array to sort * @param array $array Array to sort
* @param string $sortby Sort by this key * @param string $sortBy Sort by this key
* @param string $order Sort order asc/desc (ascending or descending). * @param string $order Sort order asc/desc (ascending or descending).
* @param integer $type Type of sorting to perform * @param integer $type Type of sorting to perform
* @return mixed Sorted array * @return mixed Sorted array
* @link http://book.cakephp.org/2.0/en/core-libraries/global-constants-and-functions.html#sortByKey * @link http://book.cakephp.org/2.0/en/core-libraries/global-constants-and-functions.html#sortByKey
*/ */
function sortByKey(&$array, $sortby, $order = 'asc', $type = SORT_NUMERIC) { function sortByKey(&$array, $sortBy, $order = 'asc', $type = SORT_NUMERIC) {
if (!is_array($array)) { if (!is_array($array)) {
return null; return null;
} }
foreach ($array as $key => $val) { foreach ($array as $key => $val) {
$sa[$key] = $val[$sortby]; $sa[$key] = $val[$sortBy];
} }
if ($order === 'asc') { if ($order === 'asc') {
@ -205,7 +205,7 @@ if (!function_exists('h')) {
if (!function_exists('pluginSplit')) { if (!function_exists('pluginSplit')) {
/** /**
* Splits a dot syntax plugin name into its plugin and classname. * Splits a dot syntax plugin name into its plugin and class name.
* If $name does not have a dot, then index 0 will be null. * If $name does not have a dot, then index 0 will be null.
* *
* Commonly used like `list($plugin, $name) = pluginSplit($name);` * Commonly used like `list($plugin, $name) = pluginSplit($name);`
@ -213,7 +213,7 @@ if (!function_exists('pluginSplit')) {
* @param string $name The name you want to plugin split. * @param string $name The name you want to plugin split.
* @param boolean $dotAppend Set to true if you want the plugin to have a '.' appended to it. * @param boolean $dotAppend Set to true if you want the plugin to have a '.' appended to it.
* @param string $plugin Optional default plugin to use if no plugin is found. Defaults to null. * @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 * @return array Array with 2 indexes. 0 => plugin name, 1 => class name
* @link http://book.cakephp.org/2.0/en/core-libraries/global-constants-and-functions.html#pluginSplit * @link http://book.cakephp.org/2.0/en/core-libraries/global-constants-and-functions.html#pluginSplit
*/ */
function pluginSplit($name, $dotAppend = false, $plugin = null) { function pluginSplit($name, $dotAppend = false, $plugin = null) {