From a4c382b23a518d01d1866d2d3584d602487c952d Mon Sep 17 00:00:00 2001 From: schrolli Date: Sun, 2 Sep 2012 06:02:30 +0300 Subject: [PATCH 01/32] Update lib/Cake/Configure/IniReader.php Copied standard path from PhpReader --- lib/Cake/Configure/IniReader.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lib/Cake/Configure/IniReader.php b/lib/Cake/Configure/IniReader.php index 900d65489..1e5180ff5 100644 --- a/lib/Cake/Configure/IniReader.php +++ b/lib/Cake/Configure/IniReader.php @@ -77,6 +77,9 @@ class IniReader implements ConfigReaderInterface { * all sections in the ini file. */ public function __construct($path, $section = null) { + if (!$path) { + $path = APP . 'Config' . DS; + } $this->_path = $path; $this->_section = $section; } From 83c05c24b325808ddaaa1dd1d8e46354139d1b1c Mon Sep 17 00:00:00 2001 From: schrolli Date: Sun, 2 Sep 2012 14:23:26 +0300 Subject: [PATCH 02/32] Update lib/Cake/Configure/IniReader.php Updated docblock and set NULL as the default value of $path --- lib/Cake/Configure/IniReader.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/Cake/Configure/IniReader.php b/lib/Cake/Configure/IniReader.php index 1e5180ff5..49b81b80f 100644 --- a/lib/Cake/Configure/IniReader.php +++ b/lib/Cake/Configure/IniReader.php @@ -72,11 +72,11 @@ class IniReader implements ConfigReaderInterface { * Build and construct a new ini file parser. The parser can be used to read * ini files that are on the filesystem. * - * @param string $path Path to load ini config files from. + * @param string $path Path to load ini config files from. Defaults to APP . 'Config' . DS * @param string $section Only get one section, leave null to parse and fetch * all sections in the ini file. */ - public function __construct($path, $section = null) { + public function __construct($path = null, $section = null) { if (!$path) { $path = APP . 'Config' . DS; } From bc40ac7d3f5c3f5448225bff3f368db7902e9107 Mon Sep 17 00:00:00 2001 From: Kyle Robinson Young Date: Wed, 5 Sep 2012 15:22:30 -0700 Subject: [PATCH 03/32] Remove unused variables and code --- lib/Cake/Controller/Component/Acl/PhpAcl.php | 2 -- lib/Cake/Controller/Controller.php | 1 - lib/Cake/Core/Configure.php | 1 - lib/Cake/Model/Behavior/TranslateBehavior.php | 1 - lib/Cake/Model/CakeSchema.php | 4 ++-- lib/Cake/Model/Datasource/CakeSession.php | 1 - lib/Cake/Model/Datasource/Database/Postgres.php | 2 +- lib/Cake/Model/Datasource/Database/Sqlite.php | 2 +- lib/Cake/Model/Datasource/DboSource.php | 12 ++++++------ lib/Cake/Model/Model.php | 6 +++--- lib/Cake/Network/CakeRequest.php | 2 +- lib/Cake/Utility/ClassRegistry.php | 2 +- lib/Cake/Utility/Debugger.php | 1 - lib/Cake/Utility/Folder.php | 2 +- lib/Cake/Utility/Hash.php | 1 - lib/Cake/View/Helper/FormHelper.php | 3 +-- lib/Cake/View/Helper/MootoolsEngineHelper.php | 1 - lib/Cake/View/Helper/PrototypeEngineHelper.php | 1 - lib/Cake/View/Helper/RssHelper.php | 2 +- lib/Cake/View/Helper/TimeHelper.php | 1 - lib/Cake/View/MediaView.php | 2 -- lib/Cake/View/View.php | 7 +------ 22 files changed, 19 insertions(+), 38 deletions(-) diff --git a/lib/Cake/Controller/Component/Acl/PhpAcl.php b/lib/Cake/Controller/Component/Acl/PhpAcl.php index 28b3b941f..d63217857 100644 --- a/lib/Cake/Controller/Component/Acl/PhpAcl.php +++ b/lib/Cake/Controller/Component/Acl/PhpAcl.php @@ -318,10 +318,8 @@ class PhpAco { * @return void */ public function build(array $allow, array $deny = array()) { - $stack = array(); $this->_tree = array(); $tree = array(); - $root = &$tree; foreach ($allow as $dotPath => $aros) { if (is_string($aros)) { diff --git a/lib/Cake/Controller/Controller.php b/lib/Cake/Controller/Controller.php index fa8b7dae9..978dade84 100644 --- a/lib/Cake/Controller/Controller.php +++ b/lib/Cake/Controller/Controller.php @@ -557,7 +557,6 @@ class Controller extends Object implements CakeEventListener { if ($mergeParent || !empty($pluginController)) { $appVars = get_class_vars($this->_mergeParent); - $uses = $appVars['uses']; $merge = array('components', 'helpers'); $this->_mergeVars($merge, $this->_mergeParent, true); } diff --git a/lib/Cake/Core/Configure.php b/lib/Cake/Core/Configure.php index 09615825c..9896aa8de 100644 --- a/lib/Cake/Core/Configure.php +++ b/lib/Cake/Core/Configure.php @@ -185,7 +185,6 @@ class Configure { */ public static function delete($var = null) { $keys = explode('.', $var); - $last = array_pop($keys); self::$_values = Hash::remove(self::$_values, $var); } diff --git a/lib/Cake/Model/Behavior/TranslateBehavior.php b/lib/Cake/Model/Behavior/TranslateBehavior.php index f90615992..8adbd35c8 100644 --- a/lib/Cake/Model/Behavior/TranslateBehavior.php +++ b/lib/Cake/Model/Behavior/TranslateBehavior.php @@ -603,7 +603,6 @@ class TranslateBehavior extends ModelBehavior { if (is_string($fields)) { $fields = array($fields); } - $RuntimeModel = $this->translateModel($Model); $associations = array(); foreach ($fields as $key => $value) { diff --git a/lib/Cake/Model/CakeSchema.php b/lib/Cake/Model/CakeSchema.php index 60c3b7643..2fda5f75e 100644 --- a/lib/Cake/Model/CakeSchema.php +++ b/lib/Cake/Model/CakeSchema.php @@ -271,7 +271,7 @@ class CakeSchema extends Object { unset($currentTables[$key]); } if (!empty($Object->hasAndBelongsToMany)) { - foreach ($Object->hasAndBelongsToMany as $Assoc => $assocData) { + foreach ($Object->hasAndBelongsToMany as $assocData) { if (isset($assocData['with'])) { $class = $assocData['with']; } @@ -597,7 +597,7 @@ class CakeSchema extends Object { $db = $Obj->getDataSource(); $fields = $Obj->schema(true); - $columns = $props = array(); + $columns = array(); foreach ($fields as $name => $value) { if ($Obj->primaryKey == $name) { $value['key'] = 'primary'; diff --git a/lib/Cake/Model/Datasource/CakeSession.php b/lib/Cake/Model/Datasource/CakeSession.php index 6baab1d5b..af457cdba 100644 --- a/lib/Cake/Model/Datasource/CakeSession.php +++ b/lib/Cake/Model/Datasource/CakeSession.php @@ -449,7 +449,6 @@ class CakeSession { */ protected static function _configureSession() { $sessionConfig = Configure::read('Session'); - $iniSet = function_exists('ini_set'); if (isset($sessionConfig['defaults'])) { $defaults = self::_defaultConfig($sessionConfig['defaults']); diff --git a/lib/Cake/Model/Datasource/Database/Postgres.php b/lib/Cake/Model/Datasource/Database/Postgres.php index cd7cffcac..2c7b8472e 100644 --- a/lib/Cake/Model/Datasource/Database/Postgres.php +++ b/lib/Cake/Model/Datasource/Database/Postgres.php @@ -438,7 +438,7 @@ class Postgres extends DboSource { ) AND c.oid = i.indrelid AND i.indexrelid = c2.oid ORDER BY i.indisprimary DESC, i.indisunique DESC, c2.relname", false); - foreach ($indexes as $i => $info) { + foreach ($indexes as $info) { $key = array_pop($info); if ($key['indisprimary']) { $key['relname'] = 'PRIMARY'; diff --git a/lib/Cake/Model/Datasource/Database/Sqlite.php b/lib/Cake/Model/Datasource/Database/Sqlite.php index e85504ed5..e267f5a65 100644 --- a/lib/Cake/Model/Datasource/Database/Sqlite.php +++ b/lib/Cake/Model/Datasource/Database/Sqlite.php @@ -474,7 +474,7 @@ class Sqlite extends DboSource { if (is_bool($indexes)) { return array(); } - foreach ($indexes as $i => $info) { + foreach ($indexes as $info) { $key = array_pop($info); $keyInfo = $this->query('PRAGMA index_info("' . $key['name'] . '")'); foreach ($keyInfo as $keyCol) { diff --git a/lib/Cake/Model/Datasource/DboSource.php b/lib/Cake/Model/Datasource/DboSource.php index e05763b0e..c8efb56fc 100644 --- a/lib/Cake/Model/Datasource/DboSource.php +++ b/lib/Cake/Model/Datasource/DboSource.php @@ -1294,9 +1294,9 @@ class DboSource extends DataSource { } } if ($type === 'hasAndBelongsToMany') { - $uniqueIds = $merge = array(); + $merge = array(); - foreach ($fetch as $j => $data) { + foreach ($fetch as $data) { if (isset($data[$with]) && $data[$with][$foreignKey] === $row[$modelAlias][$modelPK]) { if ($habtmFieldsCount <= 2) { unset($data[$with]); @@ -1445,7 +1445,7 @@ class DboSource extends DataSource { $data[$association] = array(); } } else { - foreach ($merge as $i => $row) { + foreach ($merge as $row) { $insert = array(); if (count($row) === 1) { $insert = $row[$association]; @@ -2413,7 +2413,7 @@ class DboSource extends DataSource { } $clauses = '/^WHERE\\x20|^GROUP\\x20BY\\x20|^HAVING\\x20|^ORDER\\x20BY\\x20/i'; - if (preg_match($clauses, $conditions, $match)) { + if (preg_match($clauses, $conditions)) { $clause = ''; } $conditions = $this->_quoteFields($conditions); @@ -2908,7 +2908,7 @@ class DboSource extends DataSource { $columnMap[$key] = $pdoMap[$type]; } - foreach ($values as $row => $value) { + foreach ($values as $value) { $i = 1; foreach ($value as $col => $val) { $statement->bindValue($i, $val, $columnMap[$col]); @@ -3205,7 +3205,7 @@ class DboSource extends DataSource { $isAllFloat = $isAllInt = true; $containsFloat = $containsInt = $containsString = false; - foreach ($value as $key => $valElement) { + foreach ($value as $valElement) { $valElement = trim($valElement); if (!is_float($valElement) && !preg_match('/^[\d]+\.[\d]+$/', $valElement)) { $isAllFloat = false; diff --git a/lib/Cake/Model/Model.php b/lib/Cake/Model/Model.php index 515f2e5b3..1e6dc56a5 100644 --- a/lib/Cake/Model/Model.php +++ b/lib/Cake/Model/Model.php @@ -2363,7 +2363,7 @@ class Model extends Object implements CakeEventListener { $updateCounterCache = false; if (!empty($this->belongsTo)) { - foreach ($this->belongsTo as $parent => $assoc) { + foreach ($this->belongsTo as $assoc) { if (!empty($assoc['counterCache'])) { $updateCounterCache = true; break; @@ -2449,7 +2449,7 @@ class Model extends Object implements CakeEventListener { * @return void */ protected function _deleteLinks($id) { - foreach ($this->hasAndBelongsToMany as $assoc => $data) { + foreach ($this->hasAndBelongsToMany as $data) { list($plugin, $joinModel) = pluginSplit($data['with']); $records = $this->{$joinModel}->find('all', array( 'conditions' => array($this->{$joinModel}->escapeField($data['foreignKey']) => $id), @@ -3042,7 +3042,7 @@ class Model extends Object implements CakeEventListener { public function isForeignKey($field) { $foreignKeys = array(); if (!empty($this->belongsTo)) { - foreach ($this->belongsTo as $assoc => $data) { + foreach ($this->belongsTo as $data) { $foreignKeys[] = $data['foreignKey']; } } diff --git a/lib/Cake/Network/CakeRequest.php b/lib/Cake/Network/CakeRequest.php index 1ac08cf8f..238793912 100644 --- a/lib/Cake/Network/CakeRequest.php +++ b/lib/Cake/Network/CakeRequest.php @@ -675,7 +675,7 @@ class CakeRequest implements ArrayAccess { public function accepts($type = null) { $raw = $this->parseAccept(); $accept = array(); - foreach ($raw as $value => $types) { + foreach ($raw as $types) { $accept = array_merge($accept, $types); } if ($type === null) { diff --git a/lib/Cake/Utility/ClassRegistry.php b/lib/Cake/Utility/ClassRegistry.php index da7b125a7..6dd757f30 100644 --- a/lib/Cake/Utility/ClassRegistry.php +++ b/lib/Cake/Utility/ClassRegistry.php @@ -175,7 +175,7 @@ class ClassRegistry { } if (!isset($instance)) { - trigger_error(__d('cake_dev', '(ClassRegistry::init() could not create instance of %1$s class %2$s ', $class, $type), E_USER_WARNING); + trigger_error(__d('cake_dev', '(ClassRegistry::init() could not create instance of %s', $class), E_USER_WARNING); return $false; } } diff --git a/lib/Cake/Utility/Debugger.php b/lib/Cake/Utility/Debugger.php index 3a58cb326..0a0d746b4 100644 --- a/lib/Cake/Utility/Debugger.php +++ b/lib/Cake/Utility/Debugger.php @@ -213,7 +213,6 @@ class Debugger { if (empty($line)) { $line = '??'; } - $path = self::trimPath($file); $info = compact('code', 'description', 'file', 'line'); if (!in_array($info, $self->errors)) { diff --git a/lib/Cake/Utility/Folder.php b/lib/Cake/Utility/Folder.php index 08895bf2e..bda485869 100644 --- a/lib/Cake/Utility/Folder.php +++ b/lib/Cake/Utility/Folder.php @@ -367,7 +367,7 @@ class Folder { $paths = $this->tree($path); foreach ($paths as $type) { - foreach ($type as $key => $fullpath) { + foreach ($type as $fullpath) { $check = explode(DS, $fullpath); $count = count($check); diff --git a/lib/Cake/Utility/Hash.php b/lib/Cake/Utility/Hash.php index 9514cccb9..fc133ff5f 100644 --- a/lib/Cake/Utility/Hash.php +++ b/lib/Cake/Utility/Hash.php @@ -432,7 +432,6 @@ class Hash { } $stack = array(); - $i = 1; while (!empty($needle)) { $key = key($needle); $val = $needle[$key]; diff --git a/lib/Cake/View/Helper/FormHelper.php b/lib/Cake/View/Helper/FormHelper.php index d24bb997e..3cf95a59e 100644 --- a/lib/Cake/View/Helper/FormHelper.php +++ b/lib/Cake/View/Helper/FormHelper.php @@ -194,7 +194,7 @@ class FormHelper extends AppHelper { if ($key === 'fields') { if (!isset($this->fieldset[$model]['fields'])) { - $fields = $this->fieldset[$model]['fields'] = $object->schema(); + $this->fieldset[$model]['fields'] = $object->schema(); foreach ($object->hasAndBelongsToMany as $alias => $assocData) { $this->fieldset[$object->alias]['fields'][$alias] = array('type' => 'multiple'); } @@ -320,7 +320,6 @@ class FormHelper extends AppHelper { $key = null; if ($model !== false) { - $object = $this->_getModel($model); $key = $this->_introspectModel($model, 'key'); $this->setEntity($model, true); } diff --git a/lib/Cake/View/Helper/MootoolsEngineHelper.php b/lib/Cake/View/Helper/MootoolsEngineHelper.php index 3919754fe..cc0340b6e 100644 --- a/lib/Cake/View/Helper/MootoolsEngineHelper.php +++ b/lib/Cake/View/Helper/MootoolsEngineHelper.php @@ -254,7 +254,6 @@ class MootoolsEngineHelper extends JsBaseEngineHelper { $options['url'] = $url; $options = $this->_prepareCallbacks('request', $options); if (!empty($options['dataExpression'])) { - $callbacks[] = 'data'; unset($options['dataExpression']); } elseif (!empty($data)) { $data = $this->object($data); diff --git a/lib/Cake/View/Helper/PrototypeEngineHelper.php b/lib/Cake/View/Helper/PrototypeEngineHelper.php index c1feb6d41..6c483aa13 100644 --- a/lib/Cake/View/Helper/PrototypeEngineHelper.php +++ b/lib/Cake/View/Helper/PrototypeEngineHelper.php @@ -237,7 +237,6 @@ class PrototypeEngineHelper extends JsBaseEngineHelper { $url = '"' . $this->url($url) . '"'; $options = $this->_mapOptions('request', $options); $type = '.Request'; - $data = null; if (isset($options['type']) && strtolower($options['type']) == 'json') { unset($options['type']); } diff --git a/lib/Cake/View/Helper/RssHelper.php b/lib/Cake/View/Helper/RssHelper.php index 26160f055..6e9db7cb3 100644 --- a/lib/Cake/View/Helper/RssHelper.php +++ b/lib/Cake/View/Helper/RssHelper.php @@ -341,7 +341,7 @@ class RssHelper extends AppHelper { $nodes->item(0)->setAttribute($key, $value); } } - foreach ($children as $k => $child) { + foreach ($children as $child) { $child = $elem->createElement($name, $child); $nodes->item(0)->appendChild($child); } diff --git a/lib/Cake/View/Helper/TimeHelper.php b/lib/Cake/View/Helper/TimeHelper.php index 284917971..630952817 100644 --- a/lib/Cake/View/Helper/TimeHelper.php +++ b/lib/Cake/View/Helper/TimeHelper.php @@ -358,7 +358,6 @@ class TimeHelper extends AppHelper { */ public function timeAgoInWords($dateTime, $options = array()) { $element = null; - $stringDate = ''; if (is_array($options) && !empty($options['element'])) { $element = array( diff --git a/lib/Cake/View/MediaView.php b/lib/Cake/View/MediaView.php index 49a3140a8..9dec162f0 100644 --- a/lib/Cake/View/MediaView.php +++ b/lib/Cake/View/MediaView.php @@ -101,8 +101,6 @@ class MediaView extends View { if ($this->_isActive()) { $extension = strtolower($extension); - $chunkSize = 8192; - $buffer = ''; $fileSize = @filesize($path); $handle = fopen($path, 'rb'); diff --git a/lib/Cake/View/View.php b/lib/Cake/View/View.php index b65a8fa52..9fa93d01c 100644 --- a/lib/Cake/View/View.php +++ b/lib/Cake/View/View.php @@ -289,11 +289,6 @@ class View extends Object { */ protected $_eventManager = null; -/** - * The view file to be rendered, only used inside _execute() - */ - private $__viewFileName = null; - /** * Whether the event manager was already configured for this object * @@ -856,7 +851,7 @@ class View extends Object { */ public function loadHelpers() { $helpers = HelperCollection::normalizeObjectArray($this->helpers); - foreach ($helpers as $name => $properties) { + foreach ($helpers as $properties) { list($plugin, $class) = pluginSplit($properties['class']); $this->{$class} = $this->Helpers->load($properties['class'], $properties['settings']); } From 0b0d83f261d3d1dd9068841a2e6161a2b10e3633 Mon Sep 17 00:00:00 2001 From: Ceeram Date: Fri, 7 Sep 2012 00:04:03 +0200 Subject: [PATCH 04/32] remove cookie reading in startup --- lib/Cake/Controller/Component/CookieComponent.php | 3 --- 1 file changed, 3 deletions(-) diff --git a/lib/Cake/Controller/Component/CookieComponent.php b/lib/Cake/Controller/Component/CookieComponent.php index 9f0879f92..f314c42fa 100644 --- a/lib/Cake/Controller/Component/CookieComponent.php +++ b/lib/Cake/Controller/Component/CookieComponent.php @@ -191,9 +191,6 @@ class CookieComponent extends Component { $this->_expire($this->time); $this->_values[$this->name] = array(); - if (isset($_COOKIE[$this->name])) { - $this->_values[$this->name] = $this->_decrypt($_COOKIE[$this->name]); - } } /** From 9ac5cbed3669a0af6faa6e8130ce2994213e8177 Mon Sep 17 00:00:00 2001 From: Jose Lorenzo Rodriguez Date: Sun, 9 Sep 2012 15:32:50 +0200 Subject: [PATCH 05/32] Added MailTransport test class refs #2824 --- lib/Cake/Network/Email/MailTransport.php | 29 +++++-- .../Case/Network/Email/MailTransportTest.php | 84 +++++++++++++++++++ 2 files changed, 107 insertions(+), 6 deletions(-) create mode 100644 lib/Cake/Test/Case/Network/Email/MailTransportTest.php diff --git a/lib/Cake/Network/Email/MailTransport.php b/lib/Cake/Network/Email/MailTransport.php index ae63b7612..2b849772a 100644 --- a/lib/Cake/Network/Email/MailTransport.php +++ b/lib/Cake/Network/Email/MailTransport.php @@ -41,14 +41,31 @@ class MailTransport extends AbstractTransport { unset($headers['To']); $headers = $this->_headersToString($headers, $eol); $message = implode($eol, $email->message()); - if (ini_get('safe_mode') || !isset($this->_config['additionalParameters'])) { - if (!@mail($to, $email->subject(), $message, $headers)) { - throw new SocketException(__d('cake_dev', 'Could not send email.')); - } - } elseif (!@mail($to, $email->subject(), $message, $headers, $this->_config['additionalParameters'])) { - throw new SocketException(__d('cake_dev', 'Could not send email.')); + + $params = null; + if (!ini_get('safe_mode')) { + $params = isset($this->_config['additionalParameters']) ? $this->_config['additionalParameters'] : null; } + + $this->_mail($to, $email->subject(), $message, $headers, $params); return array('headers' => $headers, 'message' => $message); } +/** + * Wraps internal function mail() and throws exception instead of errors if anything goes wrong + * + * @param string $to email's recipient + * @param string $subject email's subject + * @param string $message email's body + * @param string $headers email's custom headers + * @param string $params additional params for sending email + * @throws SocketException if mail could not be sent + * @return void + */ + protected function _mail($to, $subject, $message, $headers, $params = null) { + if (!@mail($to, $subject, $message, $headers, $params)) { + throw new SocketException(__d('cake_dev', 'Could not send email.')); + } + } + } diff --git a/lib/Cake/Test/Case/Network/Email/MailTransportTest.php b/lib/Cake/Test/Case/Network/Email/MailTransportTest.php new file mode 100644 index 000000000..2d1741b44 --- /dev/null +++ b/lib/Cake/Test/Case/Network/Email/MailTransportTest.php @@ -0,0 +1,84 @@ + + * Copyright 2005-2012, Cake Software Foundation, Inc. (http://cakefoundation.org) + * + * Licensed under The MIT License + * Redistributions of files must retain the above copyright notice + * + * @copyright Copyright 2005-2012, Cake Software Foundation, Inc. (http://cakefoundation.org) + * @link http://book.cakephp.org/2.0/en/development/testing.html CakePHP(tm) Tests + * @package Cake.Test.Case.Network.Email + * @since CakePHP(tm) v 2.0.0 + * @license MIT License (http://www.opensource.org/licenses/mit-license.php) + */ +App::uses('CakeEmail', 'Network/Email'); +App::uses('AbstractTransport', 'Network/Email'); +App::uses('MailTransport', 'Network/Email'); + + +/** + * Test case + * + */ +class MailTransportTest extends CakeTestCase { + +/** + * Setup + * + * @return void + */ + public function setUp() { + $this->MailTransport = $this->getMock('MailTransport', array('_mail')); + $this->MailTransport->config(array('additionalParameters' => '-f')); + } + +/** + * testSend method + * + * @return void + */ + public function testSendData() { + $email = $this->getMock('CakeEmail', array('message'), array()); + $email->from('noreply@cakephp.org', 'CakePHP Test'); + $email->returnPath('pleasereply@cakephp.org', 'CakePHP Return'); + $email->to('cake@cakephp.org', 'CakePHP'); + $email->cc(array('mark@cakephp.org' => 'Mark Story', 'juan@cakephp.org' => 'Juan Basso')); + $email->bcc('phpnut@cakephp.org'); + $email->messageID('<4d9946cf-0a44-4907-88fe-1d0ccbdd56cb@localhost>'); + $email->subject('Foø Bår Béz Foø Bår Béz Foø Bår Béz Foø Bår Béz'); + $date = date(DATE_RFC2822); + $email->setHeaders(array('X-Mailer' => 'CakePHP Email', 'Date' => $date)); + $email->expects($this->any())->method('message')->will($this->returnValue(array('First Line', 'Second Line', '.Third Line', ''))); + + $data = "From: CakePHP Test " . PHP_EOL; + $data .= "Return-Path: CakePHP Return " . PHP_EOL; + $data .= "Cc: Mark Story , Juan Basso " . PHP_EOL; + $data .= "Bcc: phpnut@cakephp.org" . PHP_EOL; + $data .= "X-Mailer: CakePHP Email" . PHP_EOL; + $data .= "Date: " . $date . PHP_EOL; + $data .= "Message-ID: <4d9946cf-0a44-4907-88fe-1d0ccbdd56cb@localhost>" . PHP_EOL; + $data .= "MIME-Version: 1.0" . PHP_EOL; + $data .= "Content-Type: text/plain; charset=UTF-8" . PHP_EOL; + $data .= "Content-Transfer-Encoding: 8bit"; + + $subject = '=?UTF-8?B?Rm/DuCBCw6VyIELDqXogRm/DuCBCw6VyIELDqXogRm/DuCBCw6VyIELDqXog?='; + $subject .= "\r\n" . ' =?UTF-8?B?Rm/DuCBCw6VyIELDqXo=?='; + $this->MailTransport->expects($this->once())->method('_mail') + ->with( + 'CakePHP ', + $subject, + implode(PHP_EOL, array('First Line', 'Second Line', '.Third Line', '')), + $data, + '-f' + ); + + $this->MailTransport->send($email); + } + +} + From a934f700f1cf4b11580c98f360bbca3236bb62ac Mon Sep 17 00:00:00 2001 From: mark_story Date: Sun, 9 Sep 2012 20:56:40 -0400 Subject: [PATCH 06/32] Fix parsing '0' as a url. Fixes #3198 --- lib/Cake/Routing/Router.php | 2 +- lib/Cake/Test/Case/Routing/RouterTest.php | 24 +++++++++++++++++++++++ 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/lib/Cake/Routing/Router.php b/lib/Cake/Routing/Router.php index cb28f6e9c..2c56c5290 100644 --- a/lib/Cake/Routing/Router.php +++ b/lib/Cake/Routing/Router.php @@ -518,7 +518,7 @@ class Router { $ext = null; $out = array(); - if ($url && strpos($url, '/') !== 0) { + if (strlen($url) && strpos($url, '/') !== 0) { $url = '/' . $url; } if (strpos($url, '?') !== false) { diff --git a/lib/Cake/Test/Case/Routing/RouterTest.php b/lib/Cake/Test/Case/Routing/RouterTest.php index 44bf6aacd..b4c956de0 100644 --- a/lib/Cake/Test/Case/Routing/RouterTest.php +++ b/lib/Cake/Test/Case/Routing/RouterTest.php @@ -451,6 +451,30 @@ class RouterTest extends CakeTestCase { $this->assertEquals($expected, $result); } +/** + * Test that catch all routes work with a variety of falsey inputs. + * + * @return void + */ + public function testUrlCatchAllRoute() { + Router::connect('/*', array('controller' => 'categories', 'action' => 'index')); + $result = Router::url(array('controller' => 'categories', 'action' => 'index', '0')); + $this->assertEquals('/0', $result); + + $expected = array( + 'plugin' => null, + 'controller' => 'categories', + 'action' => 'index', + 'pass' => array('0'), + 'named' => array() + ); + $result = Router::parse('/0'); + $this->assertEquals($expected, $result); + + $result = Router::parse('0'); + $this->assertEquals($expected, $result); + } + /** * Tests using arrays in named parameters * From e8c1140fc8f5f54d16302151386bc12e2bbb0c83 Mon Sep 17 00:00:00 2001 From: mark_story Date: Sun, 9 Sep 2012 21:08:21 -0400 Subject: [PATCH 07/32] Fix notice error. --- lib/Cake/Test/Case/Utility/DebuggerTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/Cake/Test/Case/Utility/DebuggerTest.php b/lib/Cake/Test/Case/Utility/DebuggerTest.php index e5817f87d..8040073c3 100644 --- a/lib/Cake/Test/Case/Utility/DebuggerTest.php +++ b/lib/Cake/Test/Case/Utility/DebuggerTest.php @@ -268,7 +268,7 @@ class DebuggerTest extends CakeTestCase { * Test method for testing addFormat with callbacks. */ public function customFormat($error, $strings) { - return $error['error'] . ': I eated an error ' . $error['path']; + return $error['error'] . ': I eated an error ' . $error['file']; } /** From d26040e3aa2173dfc3562ceb522287eb1083a5db Mon Sep 17 00:00:00 2001 From: mark_story Date: Sun, 9 Sep 2012 21:25:53 -0400 Subject: [PATCH 08/32] Fix failing tests in PHPUnit 3.7.0-RC2 --- .../Test/Case/Event/CakeEventManagerTest.php | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/lib/Cake/Test/Case/Event/CakeEventManagerTest.php b/lib/Cake/Test/Case/Event/CakeEventManagerTest.php index 04a358ab4..4211e8e86 100644 --- a/lib/Cake/Test/Case/Event/CakeEventManagerTest.php +++ b/lib/Cake/Test/Case/Event/CakeEventManagerTest.php @@ -241,11 +241,13 @@ class CakeEventManagerTest extends CakeTestCase { $manager->attach(array($anotherListener, 'listenerFunction'), 'fake.event'); $event = new CakeEvent('fake.event'); - $firstStep = clone $event; - $listener->expects($this->at(0))->method('listenerFunction') - ->with($firstStep) + $listener->expects($this->at(0)) + ->method('listenerFunction') + ->with($event) ->will($this->returnValue('something special')); - $anotherListener->expects($this->at(0))->method('listenerFunction')->with($event); + $anotherListener->expects($this->at(0)) + ->method('listenerFunction') + ->with($event); $manager->dispatch($event); $this->assertEquals('something special', $event->result); } @@ -263,11 +265,11 @@ class CakeEventManagerTest extends CakeTestCase { $manager->attach(array($anotherListener, 'listenerFunction'), 'fake.event'); $event = new CakeEvent('fake.event'); - $originalEvent = clone $event; $listener->expects($this->at(0))->method('listenerFunction') - ->with($originalEvent) + ->with($event) ->will($this->returnValue(false)); - $anotherListener->expects($this->never())->method('listenerFunction'); + $anotherListener->expects($this->never()) + ->method('listenerFunction'); $manager->dispatch($event); $this->assertTrue($event->isStopped()); } From 4f637ed4c4dc1b4c1f280bc0c3f16d2530e88de4 Mon Sep 17 00:00:00 2001 From: mark_story Date: Sun, 9 Sep 2012 21:36:33 -0400 Subject: [PATCH 09/32] Revert "Fix failing tests in PHPUnit 3.7.0-RC2" This reverts commit d26040e3aa2173dfc3562ceb522287eb1083a5db. This change causes tests to fail in PHPUnit 3.6, this will have to wait until 3.7.0 stable. --- .../Test/Case/Event/CakeEventManagerTest.php | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/lib/Cake/Test/Case/Event/CakeEventManagerTest.php b/lib/Cake/Test/Case/Event/CakeEventManagerTest.php index 4211e8e86..04a358ab4 100644 --- a/lib/Cake/Test/Case/Event/CakeEventManagerTest.php +++ b/lib/Cake/Test/Case/Event/CakeEventManagerTest.php @@ -241,13 +241,11 @@ class CakeEventManagerTest extends CakeTestCase { $manager->attach(array($anotherListener, 'listenerFunction'), 'fake.event'); $event = new CakeEvent('fake.event'); - $listener->expects($this->at(0)) - ->method('listenerFunction') - ->with($event) + $firstStep = clone $event; + $listener->expects($this->at(0))->method('listenerFunction') + ->with($firstStep) ->will($this->returnValue('something special')); - $anotherListener->expects($this->at(0)) - ->method('listenerFunction') - ->with($event); + $anotherListener->expects($this->at(0))->method('listenerFunction')->with($event); $manager->dispatch($event); $this->assertEquals('something special', $event->result); } @@ -265,11 +263,11 @@ class CakeEventManagerTest extends CakeTestCase { $manager->attach(array($anotherListener, 'listenerFunction'), 'fake.event'); $event = new CakeEvent('fake.event'); + $originalEvent = clone $event; $listener->expects($this->at(0))->method('listenerFunction') - ->with($event) + ->with($originalEvent) ->will($this->returnValue(false)); - $anotherListener->expects($this->never()) - ->method('listenerFunction'); + $anotherListener->expects($this->never())->method('listenerFunction'); $manager->dispatch($event); $this->assertTrue($event->isStopped()); } From ce1b387de298c10db8a37e95dca53ad88448955b Mon Sep 17 00:00:00 2001 From: Ceeram Date: Mon, 10 Sep 2012 09:17:29 +0200 Subject: [PATCH 10/32] fix incorrect docblock --- lib/Cake/Test/Case/Network/Email/MailTransportTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/Cake/Test/Case/Network/Email/MailTransportTest.php b/lib/Cake/Test/Case/Network/Email/MailTransportTest.php index 2d1741b44..9e102c1be 100644 --- a/lib/Cake/Test/Case/Network/Email/MailTransportTest.php +++ b/lib/Cake/Test/Case/Network/Email/MailTransportTest.php @@ -1,6 +1,6 @@ Date: Tue, 11 Sep 2012 21:47:25 -0400 Subject: [PATCH 11/32] Forward model option to PaginatorHelper::link(). Fixes #3193 --- lib/Cake/View/Helper/PaginatorHelper.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/Cake/View/Helper/PaginatorHelper.php b/lib/Cake/View/Helper/PaginatorHelper.php index 05a9935b1..252aea8a4 100644 --- a/lib/Cake/View/Helper/PaginatorHelper.php +++ b/lib/Cake/View/Helper/PaginatorHelper.php @@ -471,7 +471,7 @@ class PaginatorHelper extends AppHelper { $url = array_merge(array('page' => $paging['page'] + ($which == 'Prev' ? $step * -1 : $step)), $url); if ($this->{$check}($model)) { - return $this->Html->tag($tag, $this->link($title, $url, array_merge($options, compact('escape'))), compact('class')); + return $this->Html->tag($tag, $this->link($title, $url, array_merge($options, compact('escape', 'model'))), compact('class')); } else { unset($options['rel']); return $this->Html->tag($tag, $title, array_merge($options, compact('escape', 'class'))); From 99a9cc96693a62a8f64510fd7d312f760a40540b Mon Sep 17 00:00:00 2001 From: mark_story Date: Tue, 11 Sep 2012 21:59:46 -0400 Subject: [PATCH 12/32] Fix required field detection. Fix required field detection to match documentation and behavior when validating. Having `allowEmpty` in the first validation rule, makes the field not 'required' as the field is allowed to be empty. Fixes #3194 --- lib/Cake/Test/Case/View/Helper/FormHelperTest.php | 3 +-- lib/Cake/View/Helper/FormHelper.php | 9 ++++++--- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/lib/Cake/Test/Case/View/Helper/FormHelperTest.php b/lib/Cake/Test/Case/View/Helper/FormHelperTest.php index 0b964cc20..0a4a5e78a 100644 --- a/lib/Cake/Test/Case/View/Helper/FormHelperTest.php +++ b/lib/Cake/Test/Case/View/Helper/FormHelperTest.php @@ -107,8 +107,7 @@ class Contact extends CakeTestModel { 'imrequiredonupdate' => array('notEmpty' => array('rule' => 'alphaNumeric', 'on' => 'update')), 'imrequiredoncreate' => array('required' => array('rule' => 'alphaNumeric', 'on' => 'create')), 'imrequiredonboth' => array( - 'required' => array('rule' => 'alphaNumeric', 'allowEmpty' => true), - 'check' => array('rule' => 'alphaNumeric') + 'required' => array('rule' => 'alphaNumeric'), ), 'string_required' => 'notEmpty', 'imalsorequired' => array('rule' => 'alphaNumeric', 'allowEmpty' => false), diff --git a/lib/Cake/View/Helper/FormHelper.php b/lib/Cake/View/Helper/FormHelper.php index 3cf95a59e..d70e4d286 100644 --- a/lib/Cake/View/Helper/FormHelper.php +++ b/lib/Cake/View/Helper/FormHelper.php @@ -244,13 +244,16 @@ class FormHelper extends AppHelper { * @return boolean true if field is required to be filled, false otherwise */ protected function _isRequiredField($validationRules) { + if (empty($validationRules) || count($validationRules) === 0) { + return false; + } foreach ($validationRules as $rule) { $rule->isUpdate($this->requestType === 'put'); - if (!$rule->isEmptyAllowed()) { - return true; + if ($rule->isEmptyAllowed()) { + return false; } } - return false; + return true; } /** From fb9360767ea25281bc0d9761b80e068131a96beb Mon Sep 17 00:00:00 2001 From: mark_story Date: Wed, 12 Sep 2012 22:31:07 -0400 Subject: [PATCH 13/32] Make connection exceptions more helpful. Fixes #3204 --- lib/Cake/Model/Datasource/Database/Mysql.php | 5 ++++- lib/Cake/Model/Datasource/Database/Postgres.php | 5 ++++- lib/Cake/Model/Datasource/Database/Sqlite.php | 5 ++++- lib/Cake/Model/Datasource/Database/Sqlserver.php | 5 ++++- lib/Cake/Model/Datasource/DboSource.php | 1 + lib/Cake/Test/Case/Error/ExceptionRendererTest.php | 6 +++--- lib/Cake/View/Errors/missing_connection.ctp | 8 +++++++- 7 files changed, 27 insertions(+), 8 deletions(-) diff --git a/lib/Cake/Model/Datasource/Database/Mysql.php b/lib/Cake/Model/Datasource/Database/Mysql.php index c26de45e7..f96dfa420 100644 --- a/lib/Cake/Model/Datasource/Database/Mysql.php +++ b/lib/Cake/Model/Datasource/Database/Mysql.php @@ -149,7 +149,10 @@ class Mysql extends DboSource { ); $this->connected = true; } catch (PDOException $e) { - throw new MissingConnectionException(array('class' => $e->getMessage())); + throw new MissingConnectionException(array( + 'class' => get_class($this), + 'message' => $e->getMessage() + )); } $this->_useAlias = (bool)version_compare($this->getVersion(), "4.1", ">="); diff --git a/lib/Cake/Model/Datasource/Database/Postgres.php b/lib/Cake/Model/Datasource/Database/Postgres.php index 2c7b8472e..cca94a664 100644 --- a/lib/Cake/Model/Datasource/Database/Postgres.php +++ b/lib/Cake/Model/Datasource/Database/Postgres.php @@ -121,7 +121,10 @@ class Postgres extends DboSource { $this->_execute('SET search_path TO ' . $config['schema']); } } catch (PDOException $e) { - throw new MissingConnectionException(array('class' => $e->getMessage())); + throw new MissingConnectionException(array( + 'class' => get_class($this), + 'message' => $e->getMessage() + )); } return $this->connected; diff --git a/lib/Cake/Model/Datasource/Database/Sqlite.php b/lib/Cake/Model/Datasource/Database/Sqlite.php index e267f5a65..d30cc67df 100644 --- a/lib/Cake/Model/Datasource/Database/Sqlite.php +++ b/lib/Cake/Model/Datasource/Database/Sqlite.php @@ -113,7 +113,10 @@ class Sqlite extends DboSource { $this->_connection = new PDO('sqlite:' . $config['database'], null, null, $flags); $this->connected = true; } catch(PDOException $e) { - throw new MissingConnectionException(array('class' => $e->getMessage())); + throw new MissingConnectionException(array( + 'class' => get_class($this), + 'message' => $e->getMessage() + )); } return $this->connected; } diff --git a/lib/Cake/Model/Datasource/Database/Sqlserver.php b/lib/Cake/Model/Datasource/Database/Sqlserver.php index eaf93f433..46d565400 100644 --- a/lib/Cake/Model/Datasource/Database/Sqlserver.php +++ b/lib/Cake/Model/Datasource/Database/Sqlserver.php @@ -129,7 +129,10 @@ class Sqlserver extends DboSource { ); $this->connected = true; } catch (PDOException $e) { - throw new MissingConnectionException(array('class' => $e->getMessage())); + throw new MissingConnectionException(array( + 'class' => get_class($this), + 'message' => $e->getMessage() + )); } return $this->connected; diff --git a/lib/Cake/Model/Datasource/DboSource.php b/lib/Cake/Model/Datasource/DboSource.php index c8efb56fc..bae55cff9 100644 --- a/lib/Cake/Model/Datasource/DboSource.php +++ b/lib/Cake/Model/Datasource/DboSource.php @@ -253,6 +253,7 @@ class DboSource extends DataSource { if (!$this->enabled()) { throw new MissingConnectionException(array( 'class' => get_class($this), + 'message' => __d('cake_dev', 'Selected driver is not enabled'), 'enabled' => false )); } diff --git a/lib/Cake/Test/Case/Error/ExceptionRendererTest.php b/lib/Cake/Test/Case/Error/ExceptionRendererTest.php index 956acecc2..46745e89e 100644 --- a/lib/Cake/Test/Case/Error/ExceptionRendererTest.php +++ b/lib/Cake/Test/Case/Error/ExceptionRendererTest.php @@ -552,10 +552,10 @@ class ExceptionRendererTest extends CakeTestCase { 500 ), array( - new MissingConnectionException(array('class' => 'Article')), + new MissingConnectionException(array('class' => 'Mysql')), array( '/

Missing Database Connection<\/h2>/', - '/Article requires a database connection/' + '/A Database connection using "Mysql" was missing or unable to connect./', ), 500 ), @@ -563,7 +563,7 @@ class ExceptionRendererTest extends CakeTestCase { new MissingConnectionException(array('class' => 'Mysql', 'enabled' => false)), array( '/

Missing Database Connection<\/h2>/', - '/Mysql requires a database connection/', + '/A Database connection using "Mysql" was missing or unable to connect./', '/Mysql driver is NOT enabled/' ), 500 diff --git a/lib/Cake/View/Errors/missing_connection.ctp b/lib/Cake/View/Errors/missing_connection.ctp index b29fb9fc3..27d00a8ba 100644 --- a/lib/Cake/View/Errors/missing_connection.ctp +++ b/lib/Cake/View/Errors/missing_connection.ctp @@ -19,7 +19,13 @@

: - + +
+

From cf4a9f420f6f88e9761e59aa38bcd403f6c4f21e Mon Sep 17 00:00:00 2001 From: mark_story Date: Wed, 12 Sep 2012 22:56:46 -0400 Subject: [PATCH 14/32] Tidy doc block. --- lib/Cake/View/Helper/FormHelper.php | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/lib/Cake/View/Helper/FormHelper.php b/lib/Cake/View/Helper/FormHelper.php index d70e4d286..0c3cef835 100644 --- a/lib/Cake/View/Helper/FormHelper.php +++ b/lib/Cake/View/Helper/FormHelper.php @@ -168,14 +168,14 @@ class FormHelper extends AppHelper { * * The $key parameter accepts the following list of values: * - * - key: Returns the name of the primary key for the model - * - fields: Returns the model schema - * - validates: returns the list of fields that are required - * - errors: returns the list of validation errors + * - key: Returns the name of the primary key for the model + * - fields: Returns the model schema + * - validates: returns the list of fields that are required + * - errors: returns the list of validation errors * * If the $field parameter is passed if will return the information for that sole field. * - * `$this->_introspectModel('Post', 'fields', 'title');` will return the schema information for title column + * `$this->_introspectModel('Post', 'fields', 'title');` will return the schema information for title column * * @param string $model name of the model to extract information from * @param string $key name of the special information key to obtain (key, fields, validates, errors) From 82a8400deff6fe56f3ea2b3bc8c59556419d1075 Mon Sep 17 00:00:00 2001 From: mark_story Date: Thu, 13 Sep 2012 22:11:46 -0400 Subject: [PATCH 15/32] Fix null not stopping model callbacks. Add a compatibility shim into CakeEventManager to fix `null` not breaking model callbacks. This was a regression created when model callbacks were re-factored to use the event manager. This code should be removed in 3.x as its inconsistent with events used everywhere else in the framework. Fixes #3123 --- lib/Cake/Event/CakeEventManager.php | 4 +++ lib/Cake/Model/Model.php | 2 +- lib/Cake/Test/Case/Model/ModelWriteTest.php | 39 +++++++++++++++++++++ 3 files changed, 44 insertions(+), 1 deletion(-) diff --git a/lib/Cake/Event/CakeEventManager.php b/lib/Cake/Event/CakeEventManager.php index 252364d4c..1fecacd45 100644 --- a/lib/Cake/Event/CakeEventManager.php +++ b/lib/Cake/Event/CakeEventManager.php @@ -248,6 +248,10 @@ class CakeEventManager { if ($result === false) { $event->stopPropagation(); } + // TODO remove this in 3.0 as its a compatibility shim for model callbacks. + if (isset($event->break, $event->breakOn) && in_array($result, (array)$event->breakOn)) { + $event->stopPropagation(); + } if ($result !== null) { $event->result = $result; } diff --git a/lib/Cake/Model/Model.php b/lib/Cake/Model/Model.php index 1e6dc56a5..f799948e7 100644 --- a/lib/Cake/Model/Model.php +++ b/lib/Cake/Model/Model.php @@ -1667,7 +1667,7 @@ class Model extends Object implements CakeEventListener { $event = new CakeEvent('Model.beforeSave', $this, array($options)); list($event->break, $event->breakOn) = array(true, array(false, null)); $this->getEventManager()->dispatch($event); - if (!$event->result) { + if ($event->isStopped()) { $this->whitelist = $_whitelist; return false; } diff --git a/lib/Cake/Test/Case/Model/ModelWriteTest.php b/lib/Cake/Test/Case/Model/ModelWriteTest.php index 31327e7de..576afdf39 100644 --- a/lib/Cake/Test/Case/Model/ModelWriteTest.php +++ b/lib/Cake/Test/Case/Model/ModelWriteTest.php @@ -539,6 +539,25 @@ class ModelWriteTest extends BaseModelTest { $this->assertFalse($result); } +/** + * test that beforeValidate returning false can abort saves. + * + * @return void + */ + public function testBeforeValidateNullSaveAbortion() { + $this->loadFixtures('Post'); + $Model = new CallbackPostTestModel(); + $Model->beforeValidateReturn = null; + + $data = array( + 'title' => 'new article', + 'body' => 'this is some text.' + ); + $Model->create(); + $result = $Model->save($data); + $this->assertFalse($result); + } + /** * test that beforeSave returning false can abort saves. * @@ -558,6 +577,26 @@ class ModelWriteTest extends BaseModelTest { $this->assertFalse($result); } +/** + * Test that beforeSave returnning null can abort saves. + * + * @return void + */ + public function testBeforeSaveNullAbort() { + $this->loadFixtures('Post'); + $Model = new CallbackPostTestModel(); + $Model->beforeSaveReturn = null; + + $data = array( + 'title' => 'new article', + 'body' => 'this is some text.' + ); + $Model->create(); + $result = $Model->save($data); + $this->assertFalse($result); + + } + /** * testSaveField method * From 7d2cbec79d8f966085c55ca30fa984158cb40153 Mon Sep 17 00:00:00 2001 From: mark_story Date: Thu, 13 Sep 2012 22:49:17 -0400 Subject: [PATCH 16/32] Revert "Fix null not stopping model callbacks." This reverts commit 82a8400deff6fe56f3ea2b3bc8c59556419d1075. The previous change broke a number of tests as existing tests expect that a return value of null will not stop events. --- lib/Cake/Event/CakeEventManager.php | 4 --- lib/Cake/Model/Model.php | 2 +- lib/Cake/Test/Case/Model/ModelWriteTest.php | 39 --------------------- 3 files changed, 1 insertion(+), 44 deletions(-) diff --git a/lib/Cake/Event/CakeEventManager.php b/lib/Cake/Event/CakeEventManager.php index 1fecacd45..252364d4c 100644 --- a/lib/Cake/Event/CakeEventManager.php +++ b/lib/Cake/Event/CakeEventManager.php @@ -248,10 +248,6 @@ class CakeEventManager { if ($result === false) { $event->stopPropagation(); } - // TODO remove this in 3.0 as its a compatibility shim for model callbacks. - if (isset($event->break, $event->breakOn) && in_array($result, (array)$event->breakOn)) { - $event->stopPropagation(); - } if ($result !== null) { $event->result = $result; } diff --git a/lib/Cake/Model/Model.php b/lib/Cake/Model/Model.php index f799948e7..1e6dc56a5 100644 --- a/lib/Cake/Model/Model.php +++ b/lib/Cake/Model/Model.php @@ -1667,7 +1667,7 @@ class Model extends Object implements CakeEventListener { $event = new CakeEvent('Model.beforeSave', $this, array($options)); list($event->break, $event->breakOn) = array(true, array(false, null)); $this->getEventManager()->dispatch($event); - if ($event->isStopped()) { + if (!$event->result) { $this->whitelist = $_whitelist; return false; } diff --git a/lib/Cake/Test/Case/Model/ModelWriteTest.php b/lib/Cake/Test/Case/Model/ModelWriteTest.php index 576afdf39..31327e7de 100644 --- a/lib/Cake/Test/Case/Model/ModelWriteTest.php +++ b/lib/Cake/Test/Case/Model/ModelWriteTest.php @@ -539,25 +539,6 @@ class ModelWriteTest extends BaseModelTest { $this->assertFalse($result); } -/** - * test that beforeValidate returning false can abort saves. - * - * @return void - */ - public function testBeforeValidateNullSaveAbortion() { - $this->loadFixtures('Post'); - $Model = new CallbackPostTestModel(); - $Model->beforeValidateReturn = null; - - $data = array( - 'title' => 'new article', - 'body' => 'this is some text.' - ); - $Model->create(); - $result = $Model->save($data); - $this->assertFalse($result); - } - /** * test that beforeSave returning false can abort saves. * @@ -577,26 +558,6 @@ class ModelWriteTest extends BaseModelTest { $this->assertFalse($result); } -/** - * Test that beforeSave returnning null can abort saves. - * - * @return void - */ - public function testBeforeSaveNullAbort() { - $this->loadFixtures('Post'); - $Model = new CallbackPostTestModel(); - $Model->beforeSaveReturn = null; - - $data = array( - 'title' => 'new article', - 'body' => 'this is some text.' - ); - $Model->create(); - $result = $Model->save($data); - $this->assertFalse($result); - - } - /** * testSaveField method * From d33f676ddd72b798fba3aff6fdf58ba1a7bdf445 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Renan=20Gonc=CC=A7alves?= Date: Fri, 14 Sep 2012 14:17:07 +0200 Subject: [PATCH 17/32] Handling a fatal error on console should call Shell::_stop(1). Just like we do on web, any exception or fatal error will result into a InternalErrorException/FatalErrorException. --- lib/Cake/Console/ConsoleErrorHandler.php | 4 ++++ .../Case/Console/ConsoleErrorHandlerTest.php | 17 +++++++++++++++++ 2 files changed, 21 insertions(+) diff --git a/lib/Cake/Console/ConsoleErrorHandler.php b/lib/Cake/Console/ConsoleErrorHandler.php index 043c62125..e7409e891 100644 --- a/lib/Cake/Console/ConsoleErrorHandler.php +++ b/lib/Cake/Console/ConsoleErrorHandler.php @@ -84,6 +84,10 @@ class ConsoleErrorHandler { if (Configure::read('debug') == 0) { CakeLog::write($log, $message); } + + if ($log === LOG_ERR) { + $this->_stop(1); + } } /** diff --git a/lib/Cake/Test/Case/Console/ConsoleErrorHandlerTest.php b/lib/Cake/Test/Case/Console/ConsoleErrorHandlerTest.php index ef24dcbcf..32cddd4b0 100644 --- a/lib/Cake/Test/Case/Console/ConsoleErrorHandlerTest.php +++ b/lib/Cake/Test/Case/Console/ConsoleErrorHandlerTest.php @@ -60,6 +60,23 @@ class ConsoleErrorHandlerTest extends CakeTestCase { $this->Error->handleError(E_NOTICE, 'This is a notice error', '/some/file', 275); } +/** + * test that the console error handler can deal with fatal errors. + * + * @return void + */ + public function testHandleFatalError() { + $content = "Fatal Error Error: This is a fatal error in [/some/file, line 275]\n"; + ConsoleErrorHandler::$stderr->expects($this->once())->method('write') + ->with($content); + + $this->Error->expects($this->once()) + ->method('_stop') + ->with(1); + + $this->Error->handleError(E_USER_ERROR, 'This is a fatal error', '/some/file', 275); + } + /** * test that the console error handler can deal with CakeExceptions. * From 0282194c205816309dacbbd8fe562ebc10eaf143 Mon Sep 17 00:00:00 2001 From: mark_story Date: Fri, 14 Sep 2012 09:39:45 -0400 Subject: [PATCH 18/32] Make permission denied redirects host relative. This helps fix infinite redirect loops when HTTP_X_FORWARDED_HOST is set, and fixes redirects back to external domains on authentication errors. Fixes #3207 --- lib/Cake/Controller/Component/AuthComponent.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/Cake/Controller/Component/AuthComponent.php b/lib/Cake/Controller/Component/AuthComponent.php index c0869571f..3ce93c999 100644 --- a/lib/Cake/Controller/Component/AuthComponent.php +++ b/lib/Cake/Controller/Component/AuthComponent.php @@ -332,7 +332,7 @@ class AuthComponent extends Component { if (!empty($this->loginRedirect)) { $default = $this->loginRedirect; } - $controller->redirect($controller->referer($default), null, true); + $controller->redirect($controller->referer($default, true), null, true); return false; } From d6e2b6f83e0080a52ee3472c5f99c5be22386493 Mon Sep 17 00:00:00 2001 From: mark_story Date: Fri, 14 Sep 2012 22:06:41 -0400 Subject: [PATCH 19/32] Re-format long lines. --- lib/Cake/Model/Behavior/TranslateBehavior.php | 37 +++++++++++++++---- 1 file changed, 30 insertions(+), 7 deletions(-) diff --git a/lib/Cake/Model/Behavior/TranslateBehavior.php b/lib/Cake/Model/Behavior/TranslateBehavior.php index 8adbd35c8..37eb5c426 100644 --- a/lib/Cake/Model/Behavior/TranslateBehavior.php +++ b/lib/Cake/Model/Behavior/TranslateBehavior.php @@ -139,7 +139,10 @@ class TranslateBehavior extends ModelBehavior { return $query; } - $fields = array_merge($this->settings[$Model->alias], $this->runtime[$Model->alias]['fields']); + $fields = array_merge( + $this->settings[$Model->alias], + $this->runtime[$Model->alias]['fields'] + ); $addFields = array(); if (empty($query['fields'])) { $addFields = $fields; @@ -147,7 +150,11 @@ class TranslateBehavior extends ModelBehavior { foreach ($fields as $key => $value) { $field = (is_numeric($key)) ? $value : $key; - if (in_array($Model->escapeField('*'), $query['fields']) || in_array($Model->alias . '.' . $field, $query['fields']) || in_array($field, $query['fields'])) { + if ( + in_array($Model->escapeField('*'), $query['fields']) || + in_array($Model->alias . '.' . $field, $query['fields']) || + in_array($field, $query['fields']) + ) { $addFields[] = $field; } } @@ -395,7 +402,10 @@ class TranslateBehavior extends ModelBehavior { $conditions = array('model' => $Model->alias, 'foreign_key' => $Model->id); $RuntimeModel = $this->translateModel($Model); - $fields = array_merge($this->settings[$Model->alias], $this->runtime[$Model->alias]['fields']); + $fields = array_merge( + $this->settings[$Model->alias], + $this->runtime[$Model->alias]['fields'] + ); if ($created) { // set each field value to an empty string foreach ($fields as $key => $field) { @@ -421,13 +431,20 @@ class TranslateBehavior extends ModelBehavior { $value = array($locale => $value); } } - $translations = $RuntimeModel->find('list', array('conditions' => $conditions, 'fields' => array($RuntimeModel->alias . '.locale', $RuntimeModel->alias . '.id'))); + $translations = $RuntimeModel->find('list', array( + 'conditions' => $conditions, + 'fields' => array($RuntimeModel->alias . '.locale', $RuntimeModel->alias . '.id') + )); foreach ($value as $_locale => $_value) { $RuntimeModel->create(); $conditions['locale'] = $_locale; $conditions['content'] = $_value; if (array_key_exists($_locale, $translations)) { - $RuntimeModel->save(array($RuntimeModel->alias => array_merge($conditions, array('id' => $translations[$_locale])))); + $RuntimeModel->save(array( + $RuntimeModel->alias => array_merge( + $conditions, array('id' => $translations[$_locale]) + ) + )); } else { $RuntimeModel->save(array($RuntimeModel->alias => $conditions)); } @@ -443,7 +460,10 @@ class TranslateBehavior extends ModelBehavior { */ public function afterDelete(Model $Model) { $RuntimeModel = $this->translateModel($Model); - $conditions = array('model' => $Model->alias, 'foreign_key' => $Model->id); + $conditions = array( + 'model' => $Model->alias, + 'foreign_key' => $Model->id + ); $RuntimeModel->deleteAll($conditions); } @@ -511,7 +531,10 @@ class TranslateBehavior extends ModelBehavior { } $associations = array(); $RuntimeModel = $this->translateModel($Model); - $default = array('className' => $RuntimeModel->alias, 'foreignKey' => 'foreign_key'); + $default = array( + 'className' => $RuntimeModel->alias, + 'foreignKey' => 'foreign_key' + ); foreach ($fields as $key => $value) { if (is_numeric($key)) { From 990d5f89f0933945994782e785094d12ae90c568 Mon Sep 17 00:00:00 2001 From: Dave Date: Tue, 18 Sep 2012 10:51:24 -0300 Subject: [PATCH 20/32] Update lib/Cake/View/Helper/FormHelper.php --- lib/Cake/View/Helper/FormHelper.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/Cake/View/Helper/FormHelper.php b/lib/Cake/View/Helper/FormHelper.php index 0c3cef835..ee01b60fa 100644 --- a/lib/Cake/View/Helper/FormHelper.php +++ b/lib/Cake/View/Helper/FormHelper.php @@ -260,7 +260,7 @@ class FormHelper extends AppHelper { * Returns false if given form field described by the current entity has no errors. * Otherwise it returns the validation message * - * @return mixed Either false when there or no errors, or an array of error + * @return mixed Either false when there are no errors, or an array of error * strings. An error string could be ''. * @link http://book.cakephp.org/2.0/en/core-libraries/helpers/form.html#FormHelper::tagIsInvalid */ From 46035cfd737c8cbbe1b06ab0c6d33c8b615648a9 Mon Sep 17 00:00:00 2001 From: Dave Date: Tue, 18 Sep 2012 10:56:36 -0300 Subject: [PATCH 21/32] Update lib/Cake/View/Helper/FormHelper.php --- lib/Cake/View/Helper/FormHelper.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/Cake/View/Helper/FormHelper.php b/lib/Cake/View/Helper/FormHelper.php index ee01b60fa..92ee6c372 100644 --- a/lib/Cake/View/Helper/FormHelper.php +++ b/lib/Cake/View/Helper/FormHelper.php @@ -719,7 +719,7 @@ class FormHelper extends AppHelper { /** * Returns a formatted LABEL element for HTML FORMs. Will automatically generate - * a for attribute if one is not provided. + * a `for` attribute if one is not provided. * * ### Options * From 5d830d7adb449becfd4aae45a7e623d576e141ea Mon Sep 17 00:00:00 2001 From: mark_story Date: Tue, 18 Sep 2012 14:41:51 -0400 Subject: [PATCH 22/32] Fix multiple selects always failing post validation. Fixes #3218 --- .../Test/Case/View/Helper/FormHelperTest.php | 17 +++++++++++++++++ lib/Cake/View/Helper/FormHelper.php | 4 +++- 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/lib/Cake/Test/Case/View/Helper/FormHelperTest.php b/lib/Cake/Test/Case/View/Helper/FormHelperTest.php index 0a4a5e78a..de5747b3f 100644 --- a/lib/Cake/Test/Case/View/Helper/FormHelperTest.php +++ b/lib/Cake/Test/Case/View/Helper/FormHelperTest.php @@ -4255,6 +4255,23 @@ class FormHelperTest extends CakeTestCase { $this->assertRegExp('/"' . $key . '"/', $result); } +/** + * Multiple select elements should always be secured as they always participate + * in the POST data. + * + * @return void + */ + public function testSelectMultipleSecureWithNoOptions() { + $this->Form->request['_Token'] = array('key' => 'testkey'); + $this->assertEquals(array(), $this->Form->fields); + + $result = $this->Form->select( + 'Model.select', + array(), + array('multiple' => true) + ); + $this->assertEquals(array('Model.select'), $this->Form->fields); + } /** * When a select box has no options it should not be added to the fields list * as it always fail post validation. diff --git a/lib/Cake/View/Helper/FormHelper.php b/lib/Cake/View/Helper/FormHelper.php index 92ee6c372..ab24d38c3 100644 --- a/lib/Cake/View/Helper/FormHelper.php +++ b/lib/Cake/View/Helper/FormHelper.php @@ -1850,10 +1850,12 @@ class FormHelper extends AppHelper { if (!empty($tag) || isset($template)) { $hasOptions = (count($options) > 0 || $showEmpty); + // Secure the field if there are options, or its a multi select. + // Single selects with no options don't submit, but multiselects do. if ( (!isset($secure) || $secure == true) && empty($attributes['disabled']) && - $hasOptions + (!empty($attributes['multiple']) || $hasOptions) ) { $this->_secure(true); } From da6d49e5549ecb48d43728cac7777d3a174f7ef8 Mon Sep 17 00:00:00 2001 From: mark_story Date: Tue, 18 Sep 2012 14:50:03 -0400 Subject: [PATCH 23/32] Fix code conventions. --- lib/Cake/Test/Case/Network/Email/MailTransportTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/Cake/Test/Case/Network/Email/MailTransportTest.php b/lib/Cake/Test/Case/Network/Email/MailTransportTest.php index 9e102c1be..43f0cc5e6 100644 --- a/lib/Cake/Test/Case/Network/Email/MailTransportTest.php +++ b/lib/Cake/Test/Case/Network/Email/MailTransportTest.php @@ -60,7 +60,7 @@ class MailTransportTest extends CakeTestCase { $data .= "Cc: Mark Story , Juan Basso " . PHP_EOL; $data .= "Bcc: phpnut@cakephp.org" . PHP_EOL; $data .= "X-Mailer: CakePHP Email" . PHP_EOL; - $data .= "Date: " . $date . PHP_EOL; + $data .= "Date: " . $date . PHP_EOL; $data .= "Message-ID: <4d9946cf-0a44-4907-88fe-1d0ccbdd56cb@localhost>" . PHP_EOL; $data .= "MIME-Version: 1.0" . PHP_EOL; $data .= "Content-Type: text/plain; charset=UTF-8" . PHP_EOL; From 0f0b5e7668e9cf8160efea26b9f0e84b35fa3262 Mon Sep 17 00:00:00 2001 From: mark_story Date: Wed, 19 Sep 2012 10:14:29 -0400 Subject: [PATCH 24/32] Fix incorrect radio selection with falsey values. Use strval() to work around 0 == '' type issues. Cleanup some tests. Fixes #3221 --- .../Test/Case/View/Helper/FormHelperTest.php | 133 ++++++++---------- lib/Cake/View/Helper/FormHelper.php | 2 +- 2 files changed, 57 insertions(+), 78 deletions(-) diff --git a/lib/Cake/Test/Case/View/Helper/FormHelperTest.php b/lib/Cake/Test/Case/View/Helper/FormHelperTest.php index de5747b3f..5e822c7a0 100644 --- a/lib/Cake/Test/Case/View/Helper/FormHelperTest.php +++ b/lib/Cake/Test/Case/View/Helper/FormHelperTest.php @@ -3183,80 +3183,6 @@ class FormHelperTest extends CakeTestCase { ); $this->assertTags($result, $expected); - $result = $this->Form->radio('Model.field', array('1' => 'Yes', '0' => 'No'), array('value' => '1')); - $expected = array( - 'fieldset' => array(), - 'legend' => array(), - 'Field', - '/legend', - array('input' => array('type' => 'radio', 'name' => 'data[Model][field]', 'value' => '1', 'id' => 'ModelField1', 'checked' => 'checked')), - array('label' => array('for' => 'ModelField1')), - 'Yes', - '/label', - array('input' => array('type' => 'radio', 'name' => 'data[Model][field]', 'value' => '0', 'id' => 'ModelField0')), - array('label' => array('for' => 'ModelField0')), - 'No', - '/label', - '/fieldset' - ); - $this->assertTags($result, $expected); - - $result = $this->Form->radio('Model.field', array('1' => 'Yes', '0' => 'No'), array('value' => '0')); - $expected = array( - 'fieldset' => array(), - 'legend' => array(), - 'Field', - '/legend', - array('input' => array('type' => 'radio', 'name' => 'data[Model][field]', 'value' => '1', 'id' => 'ModelField1')), - array('label' => array('for' => 'ModelField1')), - 'Yes', - '/label', - array('input' => array('type' => 'radio', 'name' => 'data[Model][field]', 'value' => '0', 'id' => 'ModelField0', 'checked' => 'checked')), - array('label' => array('for' => 'ModelField0')), - 'No', - '/label', - '/fieldset' - ); - $this->assertTags($result, $expected); - - $result = $this->Form->radio('Model.field', array('1' => 'Yes', '0' => 'No'), array('value' => null)); - $expected = array( - 'fieldset' => array(), - 'legend' => array(), - 'Field', - '/legend', - 'input' => array('type' => 'hidden', 'name' => 'data[Model][field]', 'value' => '', 'id' => 'ModelField_'), - array('input' => array('type' => 'radio', 'name' => 'data[Model][field]', 'value' => '1', 'id' => 'ModelField1')), - array('label' => array('for' => 'ModelField1')), - 'Yes', - '/label', - array('input' => array('type' => 'radio', 'name' => 'data[Model][field]', 'value' => '0', 'id' => 'ModelField0')), - array('label' => array('for' => 'ModelField0')), - 'No', - '/label', - '/fieldset' - ); - $this->assertTags($result, $expected); - - $result = $this->Form->radio('Model.field', array('1' => 'Yes', '0' => 'No')); - $expected = array( - 'fieldset' => array(), - 'legend' => array(), - 'Field', - '/legend', - 'input' => array('type' => 'hidden', 'name' => 'data[Model][field]', 'value' => '', 'id' => 'ModelField_'), - array('input' => array('type' => 'radio', 'name' => 'data[Model][field]', 'value' => '1', 'id' => 'ModelField1')), - array('label' => array('for' => 'ModelField1')), - 'Yes', - '/label', - array('input' => array('type' => 'radio', 'name' => 'data[Model][field]', 'value' => '0', 'id' => 'ModelField0')), - array('label' => array('for' => 'ModelField0')), - 'No', - '/label', - '/fieldset' - ); - $this->assertTags($result, $expected); - $result = $this->Form->input('Newsletter.subscribe', array('legend' => 'Legend title', 'type' => 'radio', 'options' => array('0' => 'Unsubscribe', '1' => 'Subscribe'))); $expected = array( 'div' => array('class' => 'input radio'), @@ -3445,6 +3371,59 @@ class FormHelperTest extends CakeTestCase { $this->assertTags($result, $expected); } +/** + * Test that radios with a 0 value are selected under the correct conditions. + * + * @return void + */ + public function testRadioOptionWithZeroValue() { + $expected = array( + 'fieldset' => array(), + 'legend' => array(), + 'Field', + '/legend', + array('input' => array('type' => 'radio', 'name' => 'data[Model][field]', 'value' => '1', 'id' => 'ModelField1')), + array('label' => array('for' => 'ModelField1')), + 'Yes', + '/label', + array('input' => array('type' => 'radio', 'name' => 'data[Model][field]', 'value' => '0', 'id' => 'ModelField0', 'checked' => 'checked')), + array('label' => array('for' => 'ModelField0')), + 'No', + '/label', + '/fieldset' + ); + $result = $this->Form->radio('Model.field', array('1' => 'Yes', '0' => 'No'), array('value' => '0')); + $this->assertTags($result, $expected); + + $result = $this->Form->radio('Model.field', array('1' => 'Yes', '0' => 'No'), array('value' => 0)); + $this->assertTags($result, $expected); + + $expected = array( + 'fieldset' => array(), + 'legend' => array(), + 'Field', + '/legend', + 'input' => array('type' => 'hidden', 'name' => 'data[Model][field]', 'value' => '', 'id' => 'ModelField_'), + array('input' => array('type' => 'radio', 'name' => 'data[Model][field]', 'value' => '1', 'id' => 'ModelField1')), + array('label' => array('for' => 'ModelField1')), + 'Yes', + '/label', + array('input' => array('type' => 'radio', 'name' => 'data[Model][field]', 'value' => '0', 'id' => 'ModelField0')), + array('label' => array('for' => 'ModelField0')), + 'No', + '/label', + '/fieldset' + ); + $result = $this->Form->radio('Model.field', array('1' => 'Yes', '0' => 'No'), array('value' => null)); + $this->assertTags($result, $expected); + + $result = $this->Form->radio('Model.field', array('1' => 'Yes', '0' => 'No'), array('value' => '')); + $this->assertTags($result, $expected); + + $result = $this->Form->radio('Model.field', array('1' => 'Yes', '0' => 'No')); + $this->assertTags($result, $expected); + } + /** * test disabled radio options * @@ -3454,7 +3433,7 @@ class FormHelperTest extends CakeTestCase { $result = $this->Form->radio( 'Model.field', array('option A', 'option B'), - array('disabled' => array('option A'), 'value' => 'option A') + array('disabled' => array('option A'), 'value' => '0') ); $expected = array( 'fieldset' => array(), @@ -3476,7 +3455,7 @@ class FormHelperTest extends CakeTestCase { $result = $this->Form->radio( 'Model.field', array('option A', 'option B'), - array('disabled' => true, 'value' => 'option A') + array('disabled' => true, 'value' => '0') ); $expected = array( 'fieldset' => array(), @@ -3498,7 +3477,7 @@ class FormHelperTest extends CakeTestCase { $result = $this->Form->radio( 'Model.field', array('option A', 'option B'), - array('disabled' => 'disabled', 'value' => 'option A') + array('disabled' => 'disabled', 'value' => '0') ); $expected = array( 'fieldset' => array(), diff --git a/lib/Cake/View/Helper/FormHelper.php b/lib/Cake/View/Helper/FormHelper.php index ab24d38c3..ad6bf80a0 100644 --- a/lib/Cake/View/Helper/FormHelper.php +++ b/lib/Cake/View/Helper/FormHelper.php @@ -1377,7 +1377,7 @@ class FormHelper extends AppHelper { foreach ($options as $optValue => $optTitle) { $optionsHere = array('value' => $optValue); - if (isset($value) && $optValue == $value) { + if (isset($value) && strval($optValue) === strval($value)) { $optionsHere['checked'] = 'checked'; } if ($disabled && (!is_array($disabled) || in_array($optValue, $disabled))) { From d12f50a2b660d1cf1f763e0ab3001f16c21eef9a Mon Sep 17 00:00:00 2001 From: ADmad Date: Thu, 20 Sep 2012 02:40:54 +0530 Subject: [PATCH 25/32] Removing unneeded App::uses() calls --- lib/Cake/Model/Validator/CakeValidationRule.php | 5 ++--- lib/Cake/Model/Validator/CakeValidationSet.php | 2 +- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/lib/Cake/Model/Validator/CakeValidationRule.php b/lib/Cake/Model/Validator/CakeValidationRule.php index a59a01c7b..6380376bf 100644 --- a/lib/Cake/Model/Validator/CakeValidationRule.php +++ b/lib/Cake/Model/Validator/CakeValidationRule.php @@ -18,8 +18,7 @@ * @since CakePHP(tm) v 2.2.0 * @license MIT License (http://www.opensource.org/licenses/mit-license.php) */ -App::uses('ModelValidator', 'Model'); -App::uses('CakeValidationSet', 'Model/Validator'); + App::uses('Validation', 'Utility'); /** @@ -246,7 +245,7 @@ class CakeValidationRule { * If called with no parameters it will return whether this rule * is configured for update operations or not. * - * @return boolean + * @return boolean **/ public function isUpdate($exists = null) { if ($exists === null) { diff --git a/lib/Cake/Model/Validator/CakeValidationSet.php b/lib/Cake/Model/Validator/CakeValidationSet.php index 1cd32c617..3451f8103 100644 --- a/lib/Cake/Model/Validator/CakeValidationSet.php +++ b/lib/Cake/Model/Validator/CakeValidationSet.php @@ -18,7 +18,7 @@ * @since CakePHP(tm) v 2.2.0 * @license MIT License (http://www.opensource.org/licenses/mit-license.php) */ -App::uses('ModelValidator', 'Model'); + App::uses('CakeValidationRule', 'Model/Validator'); /** From 3dd82e6d88abb88f931103b9732504b761702ea4 Mon Sep 17 00:00:00 2001 From: mark_story Date: Wed, 19 Sep 2012 20:55:39 -0400 Subject: [PATCH 26/32] Fix Database/ from always being appended to the driver name. Fixes #3223 --- lib/Cake/Console/Command/Task/DbConfigTask.php | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/lib/Cake/Console/Command/Task/DbConfigTask.php b/lib/Cake/Console/Command/Task/DbConfigTask.php index b9778a558..596ad817d 100644 --- a/lib/Cake/Console/Command/Task/DbConfigTask.php +++ b/lib/Cake/Console/Command/Task/DbConfigTask.php @@ -315,8 +315,11 @@ class DbConfigTask extends AppShell { $config = array_merge($this->_defaultConfig, $config); extract($config); + if (strpos($datasource, 'Database/') === false) { + $datasource = "Database/{$datasource}"; + } $out .= "\tpublic \${$name} = array(\n"; - $out .= "\t\t'datasource' => 'Database/{$datasource}',\n"; + $out .= "\t\t'datasource' => '{$datasource}',\n"; $out .= "\t\t'persistent' => {$persistent},\n"; $out .= "\t\t'host' => '{$host}',\n"; From 36c99a358f19381f874185c8613c3748fae30dd9 Mon Sep 17 00:00:00 2001 From: Ber Clausen Date: Thu, 20 Sep 2012 00:21:26 -0300 Subject: [PATCH 27/32] Add MySQL FULLTEXT support. Minor optimizations and testing added. --- lib/Cake/Model/Datasource/Database/Mysql.php | 35 ++++++--------- lib/Cake/Model/Datasource/DboSource.php | 4 +- lib/Cake/Test/Case/Model/CakeSchemaTest.php | 17 +++++++ .../Model/Datasource/Database/MysqlTest.php | 45 +++++++++++++------ 4 files changed, 64 insertions(+), 37 deletions(-) diff --git a/lib/Cake/Model/Datasource/Database/Mysql.php b/lib/Cake/Model/Datasource/Database/Mysql.php index 9506a8a94..3036f3368 100644 --- a/lib/Cake/Model/Datasource/Database/Mysql.php +++ b/lib/Cake/Model/Datasource/Database/Mysql.php @@ -422,17 +422,21 @@ class Mysql extends DboSource { $table = $this->fullTableName($model); $old = version_compare($this->getVersion(), '4.1', '<='); if ($table) { - $indices = $this->_execute('SHOW INDEX FROM ' . $table); + $indexes = $this->_execute('SHOW INDEX FROM ' . $table); // @codingStandardsIgnoreStart // MySQL columns don't match the cakephp conventions. - while ($idx = $indices->fetch(PDO::FETCH_OBJ)) { + while ($idx = $indexes->fetch(PDO::FETCH_OBJ)) { if ($old) { $idx = (object)current((array)$idx); } if (!isset($index[$idx->Key_name]['column'])) { $col = array(); $index[$idx->Key_name]['column'] = $idx->Column_name; - $index[$idx->Key_name]['unique'] = intval($idx->Non_unique == 0); + if ($idx->Index_type === 'FULLTEXT') { + $index[$idx->Key_name]['type'] = strtolower($idx->Index_type); + } else { + $index[$idx->Key_name]['unique'] = intval($idx->Non_unique == 0); + } } else { if (!empty($index[$idx->Key_name]['column']) && !is_array($index[$idx->Key_name]['column'])) { $col[] = $index[$idx->Key_name]['column']; @@ -442,7 +446,7 @@ class Mysql extends DboSource { } } // @codingStandardsIgnoreEnd - $indices->closeCursor(); + $indexes->closeCursor(); } return $index; } @@ -553,31 +557,18 @@ class Mysql extends DboSource { if (isset($indexes['drop'])) { foreach ($indexes['drop'] as $name => $value) { $out = 'DROP '; - if ($name == 'PRIMARY') { + if ($name === 'PRIMARY') { $out .= 'PRIMARY KEY'; } else { - $out .= 'KEY ' . $name; + $out .= 'KEY ' . $this->startQuote . $name . $this->endQuote; } $alter[] = $out; } } if (isset($indexes['add'])) { - foreach ($indexes['add'] as $name => $value) { - $out = 'ADD '; - if ($name == 'PRIMARY') { - $out .= 'PRIMARY '; - $name = null; - } else { - if (!empty($value['unique'])) { - $out .= 'UNIQUE '; - } - } - if (is_array($value['column'])) { - $out .= 'KEY ' . $name . ' (' . implode(', ', array_map(array(&$this, 'name'), $value['column'])) . ')'; - } else { - $out .= 'KEY ' . $name . ' (' . $this->name($value['column']) . ')'; - } - $alter[] = $out; + $add = $this->buildIndex($indexes['add']); + foreach ($add as $index) { + $alter[] = 'ADD ' . $index; } } return $alter; diff --git a/lib/Cake/Model/Datasource/DboSource.php b/lib/Cake/Model/Datasource/DboSource.php index 64536c610..7cdf22e73 100644 --- a/lib/Cake/Model/Datasource/DboSource.php +++ b/lib/Cake/Model/Datasource/DboSource.php @@ -3114,7 +3114,7 @@ class DboSource extends DataSource { } /** - * Format indexes for create table + * Format indexes for create table. * * @param array $indexes * @param string $table @@ -3130,6 +3130,8 @@ class DboSource extends DataSource { } else { if (!empty($value['unique'])) { $out .= 'UNIQUE '; + } elseif (!empty($value['type']) && strtoupper($value['type']) === 'FULLTEXT') { + $out .= 'FULLTEXT '; } $name = $this->startQuote . $name . $this->endQuote; } diff --git a/lib/Cake/Test/Case/Model/CakeSchemaTest.php b/lib/Cake/Test/Case/Model/CakeSchemaTest.php index 47effcc14..e403d3a57 100644 --- a/lib/Cake/Test/Case/Model/CakeSchemaTest.php +++ b/lib/Cake/Test/Case/Model/CakeSchemaTest.php @@ -762,6 +762,23 @@ class CakeSchemaTest extends CakeTestCase { ); $result = $this->Schema->generateTable('posts', $posts); $this->assertRegExp('/public \$posts/', $result); + + $posts = array( + 'id' => array('type' => 'integer', 'null' => false, 'default' => 0, 'key' => 'primary'), + 'author_id' => array('type' => 'integer', 'null' => false), + 'title' => array('type' => 'string', 'null' => false), + 'body' => array('type' => 'text', 'null' => true, 'default' => null), + 'published' => array('type' => 'string', 'null' => true, 'default' => 'N', 'length' => 1), + 'created' => array('type' => 'datetime', 'null' => true, 'default' => null), + 'updated' => array('type' => 'datetime', 'null' => true, 'default' => null), + 'indexes' => array( + 'PRIMARY' => array('column' => 'id', 'unique' => true), + 'MyFtIndex' => array('column' => array('title', 'body'), 'type' => 'fulltext') + ) + ); + $result = $this->Schema->generateTable('fields', $posts); + $this->assertRegExp('/public \$fields/', $result); + $this->assertPattern('/\'type\' \=\> \'fulltext\'/', $result); } /** diff --git a/lib/Cake/Test/Case/Model/Datasource/Database/MysqlTest.php b/lib/Cake/Test/Case/Model/Datasource/Database/MysqlTest.php index c6645a3c5..c3a0bc986 100644 --- a/lib/Cake/Test/Case/Model/Datasource/Database/MysqlTest.php +++ b/lib/Cake/Test/Case/Model/Datasource/Database/MysqlTest.php @@ -313,6 +313,16 @@ class MysqlTest extends CakeTestCase { $result = $this->Dbo->index('with_multiple_compound_keys', false); $this->Dbo->rawQuery('DROP TABLE ' . $name); $this->assertEquals($expected, $result); + + $name = $this->Dbo->fullTableName('with_fulltext'); + $this->Dbo->rawQuery('CREATE TABLE ' . $name . ' (id int(11) AUTO_INCREMENT, name varchar(255), description text, primary key(id), FULLTEXT KEY `MyFtIndex` ( `name`, `description` )) ENGINE=MyISAM;'); + $expected = array( + 'PRIMARY' => array('column' => 'id', 'unique' => 1), + 'MyFtIndex' => array('column' => array('name', 'description'), 'type' => 'fulltext') + ); + $result = $this->Dbo->index('with_fulltext', false); + $this->Dbo->rawQuery('DROP TABLE ' . $name); + $this->assertEquals($expected, $result); } /** @@ -548,9 +558,9 @@ class MysqlTest extends CakeTestCase { $result = $this->Dbo->alterSchema($schemaB->compare($schemaA)); $this->assertContains("ALTER TABLE $table", $result); - $this->assertContains('ADD KEY name_idx (`name`),', $result); - $this->assertContains('ADD KEY group_idx (`group1`),', $result); - $this->assertContains('ADD KEY compound_idx (`group1`, `group2`),', $result); + $this->assertContains('ADD KEY `name_idx` (`name`),', $result); + $this->assertContains('ADD KEY `group_idx` (`group1`),', $result); + $this->assertContains('ADD KEY `compound_idx` (`group1`, `group2`),', $result); $this->assertContains('ADD PRIMARY KEY (`id`);', $result); //Test that the string is syntactically correct @@ -576,13 +586,13 @@ class MysqlTest extends CakeTestCase { $result = $this->Dbo->alterSchema($schemaC->compare($schemaB)); $this->assertContains("ALTER TABLE $table", $result); $this->assertContains('DROP PRIMARY KEY,', $result); - $this->assertContains('DROP KEY name_idx,', $result); - $this->assertContains('DROP KEY group_idx,', $result); - $this->assertContains('DROP KEY compound_idx,', $result); - $this->assertContains('ADD KEY id_name_idx (`id`, `name`),', $result); - $this->assertContains('ADD UNIQUE KEY name_idx (`name`),', $result); - $this->assertContains('ADD KEY group_idx (`group2`),', $result); - $this->assertContains('ADD KEY compound_idx (`group2`, `group1`);', $result); + $this->assertContains('DROP KEY `name_idx`,', $result); + $this->assertContains('DROP KEY `group_idx`,', $result); + $this->assertContains('DROP KEY `compound_idx`,', $result); + $this->assertContains('ADD KEY `id_name_idx` (`id`, `name`),', $result); + $this->assertContains('ADD UNIQUE KEY `name_idx` (`name`),', $result); + $this->assertContains('ADD KEY `group_idx` (`group2`),', $result); + $this->assertContains('ADD KEY `compound_idx` (`group2`, `group1`);', $result); $query = $this->Dbo->getConnection()->prepare($result); $this->assertEquals($query->queryString, $result); @@ -594,10 +604,10 @@ class MysqlTest extends CakeTestCase { $result = $this->Dbo->alterSchema($schemaA->compare($schemaC)); $this->assertContains("ALTER TABLE $table", $result); - $this->assertContains('DROP KEY name_idx,', $result); - $this->assertContains('DROP KEY group_idx,', $result); - $this->assertContains('DROP KEY compound_idx,', $result); - $this->assertContains('DROP KEY id_name_idx;', $result); + $this->assertContains('DROP KEY `name_idx`,', $result); + $this->assertContains('DROP KEY `group_idx`,', $result); + $this->assertContains('DROP KEY `compound_idx`,', $result); + $this->assertContains('DROP KEY `id_name_idx`;', $result); $query = $this->Dbo->getConnection()->prepare($result); $this->assertEquals($query->queryString, $result); @@ -2837,6 +2847,13 @@ class MysqlTest extends CakeTestCase { $result = $this->Dbo->buildIndex($data); $expected = array('UNIQUE KEY `MyIndex` (`id`, `name`)'); $this->assertEquals($expected, $result); + + $data = array( + 'MyFtIndex' => array('column' => array('name', 'description'), 'type' => 'fulltext') + ); + $result = $this->Dbo->buildIndex($data); + $expected = array('FULLTEXT KEY `MyFtIndex` (`name`, `description`)'); + $this->assertEquals($expected, $result); } /** From a9750264e452a3491ec94c210f403bc44a337847 Mon Sep 17 00:00:00 2001 From: mark_story Date: Thu, 20 Sep 2012 20:39:02 -0400 Subject: [PATCH 28/32] Revert "Add MySQL FULLTEXT support." This reverts commit 36c99a358f19381f874185c8613c3748fae30dd9. --- lib/Cake/Model/Datasource/Database/Mysql.php | 35 +++++++++------ lib/Cake/Model/Datasource/DboSource.php | 4 +- lib/Cake/Test/Case/Model/CakeSchemaTest.php | 17 ------- .../Model/Datasource/Database/MysqlTest.php | 45 ++++++------------- 4 files changed, 37 insertions(+), 64 deletions(-) diff --git a/lib/Cake/Model/Datasource/Database/Mysql.php b/lib/Cake/Model/Datasource/Database/Mysql.php index fe7139649..f96dfa420 100644 --- a/lib/Cake/Model/Datasource/Database/Mysql.php +++ b/lib/Cake/Model/Datasource/Database/Mysql.php @@ -425,21 +425,17 @@ class Mysql extends DboSource { $table = $this->fullTableName($model); $old = version_compare($this->getVersion(), '4.1', '<='); if ($table) { - $indexes = $this->_execute('SHOW INDEX FROM ' . $table); + $indices = $this->_execute('SHOW INDEX FROM ' . $table); // @codingStandardsIgnoreStart // MySQL columns don't match the cakephp conventions. - while ($idx = $indexes->fetch(PDO::FETCH_OBJ)) { + while ($idx = $indices->fetch(PDO::FETCH_OBJ)) { if ($old) { $idx = (object)current((array)$idx); } if (!isset($index[$idx->Key_name]['column'])) { $col = array(); $index[$idx->Key_name]['column'] = $idx->Column_name; - if ($idx->Index_type === 'FULLTEXT') { - $index[$idx->Key_name]['type'] = strtolower($idx->Index_type); - } else { - $index[$idx->Key_name]['unique'] = intval($idx->Non_unique == 0); - } + $index[$idx->Key_name]['unique'] = intval($idx->Non_unique == 0); } else { if (!empty($index[$idx->Key_name]['column']) && !is_array($index[$idx->Key_name]['column'])) { $col[] = $index[$idx->Key_name]['column']; @@ -449,7 +445,7 @@ class Mysql extends DboSource { } } // @codingStandardsIgnoreEnd - $indexes->closeCursor(); + $indices->closeCursor(); } return $index; } @@ -559,18 +555,31 @@ class Mysql extends DboSource { if (isset($indexes['drop'])) { foreach ($indexes['drop'] as $name => $value) { $out = 'DROP '; - if ($name === 'PRIMARY') { + if ($name == 'PRIMARY') { $out .= 'PRIMARY KEY'; } else { - $out .= 'KEY ' . $this->startQuote . $name . $this->endQuote; + $out .= 'KEY ' . $name; } $alter[] = $out; } } if (isset($indexes['add'])) { - $add = $this->buildIndex($indexes['add']); - foreach ($add as $index) { - $alter[] = 'ADD ' . $index; + foreach ($indexes['add'] as $name => $value) { + $out = 'ADD '; + if ($name == 'PRIMARY') { + $out .= 'PRIMARY '; + $name = null; + } else { + if (!empty($value['unique'])) { + $out .= 'UNIQUE '; + } + } + if (is_array($value['column'])) { + $out .= 'KEY ' . $name . ' (' . implode(', ', array_map(array(&$this, 'name'), $value['column'])) . ')'; + } else { + $out .= 'KEY ' . $name . ' (' . $this->name($value['column']) . ')'; + } + $alter[] = $out; } } return $alter; diff --git a/lib/Cake/Model/Datasource/DboSource.php b/lib/Cake/Model/Datasource/DboSource.php index 5c1aa97e1..bae55cff9 100644 --- a/lib/Cake/Model/Datasource/DboSource.php +++ b/lib/Cake/Model/Datasource/DboSource.php @@ -3113,7 +3113,7 @@ class DboSource extends DataSource { } /** - * Format indexes for create table. + * Format indexes for create table * * @param array $indexes * @param string $table @@ -3129,8 +3129,6 @@ class DboSource extends DataSource { } else { if (!empty($value['unique'])) { $out .= 'UNIQUE '; - } elseif (!empty($value['type']) && strtoupper($value['type']) === 'FULLTEXT') { - $out .= 'FULLTEXT '; } $name = $this->startQuote . $name . $this->endQuote; } diff --git a/lib/Cake/Test/Case/Model/CakeSchemaTest.php b/lib/Cake/Test/Case/Model/CakeSchemaTest.php index e403d3a57..47effcc14 100644 --- a/lib/Cake/Test/Case/Model/CakeSchemaTest.php +++ b/lib/Cake/Test/Case/Model/CakeSchemaTest.php @@ -762,23 +762,6 @@ class CakeSchemaTest extends CakeTestCase { ); $result = $this->Schema->generateTable('posts', $posts); $this->assertRegExp('/public \$posts/', $result); - - $posts = array( - 'id' => array('type' => 'integer', 'null' => false, 'default' => 0, 'key' => 'primary'), - 'author_id' => array('type' => 'integer', 'null' => false), - 'title' => array('type' => 'string', 'null' => false), - 'body' => array('type' => 'text', 'null' => true, 'default' => null), - 'published' => array('type' => 'string', 'null' => true, 'default' => 'N', 'length' => 1), - 'created' => array('type' => 'datetime', 'null' => true, 'default' => null), - 'updated' => array('type' => 'datetime', 'null' => true, 'default' => null), - 'indexes' => array( - 'PRIMARY' => array('column' => 'id', 'unique' => true), - 'MyFtIndex' => array('column' => array('title', 'body'), 'type' => 'fulltext') - ) - ); - $result = $this->Schema->generateTable('fields', $posts); - $this->assertRegExp('/public \$fields/', $result); - $this->assertPattern('/\'type\' \=\> \'fulltext\'/', $result); } /** diff --git a/lib/Cake/Test/Case/Model/Datasource/Database/MysqlTest.php b/lib/Cake/Test/Case/Model/Datasource/Database/MysqlTest.php index 340ea1e12..f14bf6116 100644 --- a/lib/Cake/Test/Case/Model/Datasource/Database/MysqlTest.php +++ b/lib/Cake/Test/Case/Model/Datasource/Database/MysqlTest.php @@ -313,16 +313,6 @@ class MysqlTest extends CakeTestCase { $result = $this->Dbo->index('with_multiple_compound_keys', false); $this->Dbo->rawQuery('DROP TABLE ' . $name); $this->assertEquals($expected, $result); - - $name = $this->Dbo->fullTableName('with_fulltext'); - $this->Dbo->rawQuery('CREATE TABLE ' . $name . ' (id int(11) AUTO_INCREMENT, name varchar(255), description text, primary key(id), FULLTEXT KEY `MyFtIndex` ( `name`, `description` )) ENGINE=MyISAM;'); - $expected = array( - 'PRIMARY' => array('column' => 'id', 'unique' => 1), - 'MyFtIndex' => array('column' => array('name', 'description'), 'type' => 'fulltext') - ); - $result = $this->Dbo->index('with_fulltext', false); - $this->Dbo->rawQuery('DROP TABLE ' . $name); - $this->assertEquals($expected, $result); } /** @@ -558,9 +548,9 @@ class MysqlTest extends CakeTestCase { $result = $this->Dbo->alterSchema($schemaB->compare($schemaA)); $this->assertContains("ALTER TABLE $table", $result); - $this->assertContains('ADD KEY `name_idx` (`name`),', $result); - $this->assertContains('ADD KEY `group_idx` (`group1`),', $result); - $this->assertContains('ADD KEY `compound_idx` (`group1`, `group2`),', $result); + $this->assertContains('ADD KEY name_idx (`name`),', $result); + $this->assertContains('ADD KEY group_idx (`group1`),', $result); + $this->assertContains('ADD KEY compound_idx (`group1`, `group2`),', $result); $this->assertContains('ADD PRIMARY KEY (`id`);', $result); //Test that the string is syntactically correct @@ -586,13 +576,13 @@ class MysqlTest extends CakeTestCase { $result = $this->Dbo->alterSchema($schemaC->compare($schemaB)); $this->assertContains("ALTER TABLE $table", $result); $this->assertContains('DROP PRIMARY KEY,', $result); - $this->assertContains('DROP KEY `name_idx`,', $result); - $this->assertContains('DROP KEY `group_idx`,', $result); - $this->assertContains('DROP KEY `compound_idx`,', $result); - $this->assertContains('ADD KEY `id_name_idx` (`id`, `name`),', $result); - $this->assertContains('ADD UNIQUE KEY `name_idx` (`name`),', $result); - $this->assertContains('ADD KEY `group_idx` (`group2`),', $result); - $this->assertContains('ADD KEY `compound_idx` (`group2`, `group1`);', $result); + $this->assertContains('DROP KEY name_idx,', $result); + $this->assertContains('DROP KEY group_idx,', $result); + $this->assertContains('DROP KEY compound_idx,', $result); + $this->assertContains('ADD KEY id_name_idx (`id`, `name`),', $result); + $this->assertContains('ADD UNIQUE KEY name_idx (`name`),', $result); + $this->assertContains('ADD KEY group_idx (`group2`),', $result); + $this->assertContains('ADD KEY compound_idx (`group2`, `group1`);', $result); $query = $this->Dbo->getConnection()->prepare($result); $this->assertEquals($query->queryString, $result); @@ -604,10 +594,10 @@ class MysqlTest extends CakeTestCase { $result = $this->Dbo->alterSchema($schemaA->compare($schemaC)); $this->assertContains("ALTER TABLE $table", $result); - $this->assertContains('DROP KEY `name_idx`,', $result); - $this->assertContains('DROP KEY `group_idx`,', $result); - $this->assertContains('DROP KEY `compound_idx`,', $result); - $this->assertContains('DROP KEY `id_name_idx`;', $result); + $this->assertContains('DROP KEY name_idx,', $result); + $this->assertContains('DROP KEY group_idx,', $result); + $this->assertContains('DROP KEY compound_idx,', $result); + $this->assertContains('DROP KEY id_name_idx;', $result); $query = $this->Dbo->getConnection()->prepare($result); $this->assertEquals($query->queryString, $result); @@ -2866,13 +2856,6 @@ class MysqlTest extends CakeTestCase { $result = $this->Dbo->buildIndex($data); $expected = array('UNIQUE KEY `MyIndex` (`id`, `name`)'); $this->assertEquals($expected, $result); - - $data = array( - 'MyFtIndex' => array('column' => array('name', 'description'), 'type' => 'fulltext') - ); - $result = $this->Dbo->buildIndex($data); - $expected = array('FULLTEXT KEY `MyFtIndex` (`name`, `description`)'); - $this->assertEquals($expected, $result); } /** From d3ba9703a5602caaca4dd039f8065727e8579788 Mon Sep 17 00:00:00 2001 From: mark_story Date: Thu, 20 Sep 2012 21:07:14 -0400 Subject: [PATCH 29/32] Try to make some time related test failures go away. --- .../Case/Controller/Component/CookieComponentTest.php | 4 +++- lib/Cake/Test/Case/Utility/FileTest.php | 10 +++++----- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/lib/Cake/Test/Case/Controller/Component/CookieComponentTest.php b/lib/Cake/Test/Case/Controller/Component/CookieComponentTest.php index 6ed65a673..380c29099 100644 --- a/lib/Cake/Test/Case/Controller/Component/CookieComponentTest.php +++ b/lib/Cake/Test/Case/Controller/Component/CookieComponentTest.php @@ -271,12 +271,14 @@ class CookieComponentTest extends CakeTestCase { $expected = array( 'name' => $this->Cookie->name . '[Testing]', 'value' => '[1,2,3]', - 'expire' => time() + 10, 'path' => '/', 'domain' => '', 'secure' => false, 'httpOnly' => false); $result = $this->Controller->response->cookie($this->Cookie->name . '[Testing]'); + + $this->assertWithinMargin($result['expire'], time() + 10, 1); + unset($result['expire']); $this->assertEquals($expected, $result); } diff --git a/lib/Cake/Test/Case/Utility/FileTest.php b/lib/Cake/Test/Case/Utility/FileTest.php index 93c7227be..01799519d 100644 --- a/lib/Cake/Test/Case/Utility/FileTest.php +++ b/lib/Cake/Test/Case/Utility/FileTest.php @@ -362,11 +362,10 @@ class FileTest extends CakeTestCase { * @return void */ public function testLastAccess() { - $ts = time(); $someFile = new File(TMP . 'some_file.txt', false); $this->assertFalse($someFile->lastAccess()); $this->assertTrue($someFile->open()); - $this->assertTrue($someFile->lastAccess() >= $ts); + $this->assertWithinMargin($someFile->lastAccess(), time(), 2); $someFile->close(); $someFile->delete(); } @@ -377,13 +376,14 @@ class FileTest extends CakeTestCase { * @return void */ public function testLastChange() { - $ts = time(); $someFile = new File(TMP . 'some_file.txt', false); $this->assertFalse($someFile->lastChange()); $this->assertTrue($someFile->open('r+')); - $this->assertTrue($someFile->lastChange() >= $ts); + $this->assertWithinMargin($someFile->lastChange(), time(), 2); + $someFile->write('something'); - $this->assertTrue($someFile->lastChange() >= $ts); + $this->assertWithinMargin($someFile->lastChange(), time(), 2); + $someFile->close(); $someFile->delete(); } From fe5b49e6eba930867adade4ac88125d8bf319d3f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Renan=20Gonc=CC=A7alves?= Date: Mon, 24 Sep 2012 13:41:56 +0200 Subject: [PATCH 30/32] Fixing variable name used to set error handlers. --- lib/Cake/Console/ShellDispatcher.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/Cake/Console/ShellDispatcher.php b/lib/Cake/Console/ShellDispatcher.php index 40c27cc15..6eb0e1624 100644 --- a/lib/Cake/Console/ShellDispatcher.php +++ b/lib/Cake/Console/ShellDispatcher.php @@ -160,11 +160,11 @@ class ShellDispatcher { $errorHandler = new ConsoleErrorHandler(); if (empty($error['consoleHandler'])) { $error['consoleHandler'] = array($errorHandler, 'handleError'); - Configure::write('error', $error); + Configure::write('Error', $error); } if (empty($exception['consoleHandler'])) { $exception['consoleHandler'] = array($errorHandler, 'handleException'); - Configure::write('exception', $exception); + Configure::write('Exception', $exception); } set_exception_handler($exception['consoleHandler']); set_error_handler($error['consoleHandler'], Configure::read('Error.level')); From b0822d2246b6bad7dfb0c52b996dd8d5ea3ee036 Mon Sep 17 00:00:00 2001 From: Jose Lorenzo Rodriguez Date: Tue, 25 Sep 2012 15:23:19 +0200 Subject: [PATCH 31/32] Introducing failing test case to prove issue in CakeTime --- lib/Cake/Test/Case/Utility/CakeTimeTest.php | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/lib/Cake/Test/Case/Utility/CakeTimeTest.php b/lib/Cake/Test/Case/Utility/CakeTimeTest.php index 13bf89ddc..04b1b3cde 100644 --- a/lib/Cake/Test/Case/Utility/CakeTimeTest.php +++ b/lib/Cake/Test/Case/Utility/CakeTimeTest.php @@ -1049,4 +1049,19 @@ class CakeTimeTest extends CakeTestCase { } } +/** + * Tests that using CakeTime::format() with the correct sytax actually converts + * from one timezone to the other correctly + * + * @return void + **/ + public function testCorrectTimezoneConversion() { + date_default_timezone_set('UTC'); + $date = '2012-01-01 10:00:00'; + $converted = CakeTime::format($date, '%Y-%m-%d %H:%M:%S', '', 'Europe/Copenhagen'); + $expected = new DateTime($date); + $expected->setTimezone(new DateTimeZone('Europe/Copenhagen')); + $this->assertEquals($expected->format('Y-m-d H:i:s'), $converted); + } + } From 6818d69fc344c8c44b72c1701380a43fba1ba155 Mon Sep 17 00:00:00 2001 From: Jose Lorenzo Rodriguez Date: Tue, 25 Sep 2012 15:23:46 +0200 Subject: [PATCH 32/32] Fixed issue in CakeTime that it would apply userOffset twice when using the format() function --- lib/Cake/Utility/CakeTime.php | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/lib/Cake/Utility/CakeTime.php b/lib/Cake/Utility/CakeTime.php index f5e343fc6..35c7241d0 100644 --- a/lib/Cake/Utility/CakeTime.php +++ b/lib/Cake/Utility/CakeTime.php @@ -941,15 +941,11 @@ class CakeTime { * @see CakeTime::i18nFormat() */ public static function format($date, $format = null, $default = false, $timezone = null) { - //Backwards compatible params order + //Backwards compatible params re-order test $time = self::fromString($format, $timezone); - $_time = is_numeric($time) ? false : self::fromString($date, $timezone); - if (is_numeric($_time) && $time === false) { - return self::i18nFormat($_time, $format, $default, $timezone); - } - if ($time === false && $default !== false) { - return $default; + if ($time === false) { + return self::i18nFormat($date, $format, $default, $timezone); } return date($date, $time); }