From 588090da21226736f2cd91e2e001e4ed3dccfd45 Mon Sep 17 00:00:00 2001 From: 0x20h Date: Tue, 17 Jan 2012 08:58:22 +0100 Subject: [PATCH 01/24] moved docblock on default cache configuration to bootstrap.php, left a note in core.php --- app/Config/bootstrap.php | 60 ++++++++++++++++++++++++++++++++++++- app/Config/core.php | 65 +++------------------------------------- 2 files changed, 63 insertions(+), 62 deletions(-) diff --git a/app/Config/bootstrap.php b/app/Config/bootstrap.php index fce18ccba..86b711894 100644 --- a/app/Config/bootstrap.php +++ b/app/Config/bootstrap.php @@ -23,7 +23,65 @@ * @license MIT License (http://www.opensource.org/licenses/mit-license.php) */ -// Setup a 'default' cache configuration for use in the application. +/** + * Cache Engine Configuration + * Default settings provided below + * + * File storage engine. + * + * Cache::config('default', array( + * 'engine' => 'File', //[required] + * 'duration'=> 3600, //[optional] + * 'probability'=> 100, //[optional] + * 'path' => CACHE, //[optional] use system tmp directory - remember to use absolute path + * 'prefix' => 'cake_', //[optional] prefix every cache file with this string + * 'lock' => false, //[optional] use file locking + * 'serialize' => true, [optional] + * )); + * + * APC (http://pecl.php.net/package/APC) + * + * Cache::config('default', array( + * 'engine' => 'Apc', //[required] + * 'duration'=> 3600, //[optional] + * 'probability'=> 100, //[optional] + * 'prefix' => Inflector::slug(APP_DIR) . '_', //[optional] prefix every cache file with this string + * )); + * + * Xcache (http://xcache.lighttpd.net/) + * + * Cache::config('default', array( + * 'engine' => 'Xcache', //[required] + * 'duration'=> 3600, //[optional] + * 'probability'=> 100, //[optional] + * 'prefix' => Inflector::slug(APP_DIR) . '_', //[optional] prefix every cache file with this string + * 'user' => 'user', //user from xcache.admin.user settings + * 'password' => 'password', //plaintext password (xcache.admin.pass) + * )); + * + * Memcache (http://memcached.org/) + * + * Cache::config('default', array( + * 'engine' => 'Memcache', //[required] + * 'duration'=> 3600, //[optional] + * 'probability'=> 100, //[optional] + * 'prefix' => Inflector::slug(APP_DIR) . '_', //[optional] prefix every cache file with this string + * 'servers' => array( + * '127.0.0.1:11211' // localhost, default port 11211 + * ), //[optional] + * 'persistent' => true, // [optional] set this to false for non-persistent connections + * 'compress' => false, // [optional] compress data in Memcache (slower, but uses less memory) + * )); + * + * Wincache (http://php.net/wincache) + * + * Cache::config('default', array( + * 'engine' => 'Wincache', //[required] + * 'duration'=> 3600, //[optional] + * 'probability'=> 100, //[optional] + * 'prefix' => Inflector::slug(APP_DIR) . '_', //[optional] prefix every cache file with this string + * )); + */ Cache::config('default', array('engine' => 'File')); /** diff --git a/app/Config/core.php b/app/Config/core.php index aa95b8130..e4ffe3cff 100644 --- a/app/Config/core.php +++ b/app/Config/core.php @@ -231,67 +231,6 @@ */ //date_default_timezone_set('UTC'); -/** - * - * Cache Engine Configuration - * Default settings provided below - * - * File storage engine. - * - * Cache::config('default', array( - * 'engine' => 'File', //[required] - * 'duration'=> 3600, //[optional] - * 'probability'=> 100, //[optional] - * 'path' => CACHE, //[optional] use system tmp directory - remember to use absolute path - * 'prefix' => 'cake_', //[optional] prefix every cache file with this string - * 'lock' => false, //[optional] use file locking - * 'serialize' => true, [optional] - * )); - * - * APC (http://pecl.php.net/package/APC) - * - * Cache::config('default', array( - * 'engine' => 'Apc', //[required] - * 'duration'=> 3600, //[optional] - * 'probability'=> 100, //[optional] - * 'prefix' => Inflector::slug(APP_DIR) . '_', //[optional] prefix every cache file with this string - * )); - * - * Xcache (http://xcache.lighttpd.net/) - * - * Cache::config('default', array( - * 'engine' => 'Xcache', //[required] - * 'duration'=> 3600, //[optional] - * 'probability'=> 100, //[optional] - * 'prefix' => Inflector::slug(APP_DIR) . '_', //[optional] prefix every cache file with this string - * 'user' => 'user', //user from xcache.admin.user settings - * 'password' => 'password', //plaintext password (xcache.admin.pass) - * )); - * - * Memcache (http://memcached.org/) - * - * Cache::config('default', array( - * 'engine' => 'Memcache', //[required] - * 'duration'=> 3600, //[optional] - * 'probability'=> 100, //[optional] - * 'prefix' => Inflector::slug(APP_DIR) . '_', //[optional] prefix every cache file with this string - * 'servers' => array( - * '127.0.0.1:11211' // localhost, default port 11211 - * ), //[optional] - * 'persistent' => true, // [optional] set this to false for non-persistent connections - * 'compress' => false, // [optional] compress data in Memcache (slower, but uses less memory) - * )); - * - * Wincache (http://php.net/wincache) - * - * Cache::config('default', array( - * 'engine' => 'Wincache', //[required] - * 'duration'=> 3600, //[optional] - * 'probability'=> 100, //[optional] - * 'prefix' => Inflector::slug(APP_DIR) . '_', //[optional] prefix every cache file with this string - * )); - */ - /** * Pick the caching engine to use. If APC is enabled use it. * If running via cli - apc is disabled by default. ensure it's available and enabled in this case @@ -331,3 +270,7 @@ Cache::config('_cake_model_', array( 'serialize' => ($engine === 'File'), 'duration' => $duration )); + +/** + * Note: 'default' and other application caches should be configured in app/Config/bootstrap.php + */ From 54869fc965cd47668ce6a8a177a5f1c94289d456 Mon Sep 17 00:00:00 2001 From: 0x20h Date: Tue, 17 Jan 2012 19:39:46 +0100 Subject: [PATCH 02/24] moved note about 'default' cache configuration to the APC config docblock --- app/Config/core.php | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/app/Config/core.php b/app/Config/core.php index e4ffe3cff..d128bbd50 100644 --- a/app/Config/core.php +++ b/app/Config/core.php @@ -235,6 +235,7 @@ * Pick the caching engine to use. If APC is enabled use it. * If running via cli - apc is disabled by default. ensure it's available and enabled in this case * + * Note: 'default' and other application caches should be configured in app/Config/bootstrap.php */ $engine = 'File'; if (extension_loaded('apc') && function_exists('apc_dec') && (php_sapi_name() !== 'cli' || ini_get('apc.enable_cli'))) { @@ -270,7 +271,3 @@ Cache::config('_cake_model_', array( 'serialize' => ($engine === 'File'), 'duration' => $duration )); - -/** - * Note: 'default' and other application caches should be configured in app/Config/bootstrap.php - */ From bc8feefc89d54b23a005f8a3f29f7b6c5d987390 Mon Sep 17 00:00:00 2001 From: 0x20h Date: Wed, 1 Feb 2012 20:12:34 +0100 Subject: [PATCH 03/24] added 'mask' option hint to file cache docblock --- app/Config/bootstrap.php | 1 + 1 file changed, 1 insertion(+) diff --git a/app/Config/bootstrap.php b/app/Config/bootstrap.php index 86b711894..cdaf4f5bf 100644 --- a/app/Config/bootstrap.php +++ b/app/Config/bootstrap.php @@ -37,6 +37,7 @@ * 'prefix' => 'cake_', //[optional] prefix every cache file with this string * 'lock' => false, //[optional] use file locking * 'serialize' => true, [optional] + * 'mask' => 0666, // [optional] permission mask to use when creating cache files * )); * * APC (http://pecl.php.net/package/APC) From 162b77310c82b3a76bdb38d1a9db045681dc35a1 Mon Sep 17 00:00:00 2001 From: 0x20h Date: Wed, 1 Feb 2012 20:14:56 +0100 Subject: [PATCH 04/24] fixed typo --- app/Config/bootstrap.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/Config/bootstrap.php b/app/Config/bootstrap.php index cdaf4f5bf..3b772c691 100644 --- a/app/Config/bootstrap.php +++ b/app/Config/bootstrap.php @@ -36,7 +36,7 @@ * 'path' => CACHE, //[optional] use system tmp directory - remember to use absolute path * 'prefix' => 'cake_', //[optional] prefix every cache file with this string * 'lock' => false, //[optional] use file locking - * 'serialize' => true, [optional] + * 'serialize' => true, // [optional] * 'mask' => 0666, // [optional] permission mask to use when creating cache files * )); * From 94e5ec0545f051c64b0638e9c20fb3332e0c979e Mon Sep 17 00:00:00 2001 From: Thomas Ploch Date: Sat, 4 Feb 2012 19:27:09 +0100 Subject: [PATCH 05/24] Added handling of E_USER_DEPRECATED to ErrorHandler and Debugger. --- lib/Cake/Error/ErrorHandler.php | 1 + lib/Cake/Utility/Debugger.php | 6 +++++- lib/Cake/bootstrap.php | 4 ++++ 3 files changed, 10 insertions(+), 1 deletion(-) diff --git a/lib/Cake/Error/ErrorHandler.php b/lib/Cake/Error/ErrorHandler.php index 2c2a2ee09..5899a71b4 100644 --- a/lib/Cake/Error/ErrorHandler.php +++ b/lib/Cake/Error/ErrorHandler.php @@ -217,6 +217,7 @@ class ErrorHandler { $log = LOG_NOTICE; break; case E_DEPRECATED: + case E_USER_DEPRECATED: $error = 'Deprecated'; $log = LOG_NOTICE; break; diff --git a/lib/Cake/Utility/Debugger.php b/lib/Cake/Utility/Debugger.php index fd7739492..624c60f61 100644 --- a/lib/Cake/Utility/Debugger.php +++ b/lib/Cake/Utility/Debugger.php @@ -241,6 +241,11 @@ class Debugger { $error = 'Notice'; $level = LOG_NOTICE; break; + case E_DEPRECATED: + case E_USER_DEPRECATED: + $error = 'Deprecated'; + $level = LOG_NOTICE; + break; default: return; break; @@ -716,5 +721,4 @@ class Debugger { trigger_error(__d('cake_dev', 'Please change the value of \'Security.cipherSeed\' in app/Config/core.php to a numeric (digits only) seed value specific to your application'), E_USER_NOTICE); } } - } diff --git a/lib/Cake/bootstrap.php b/lib/Cake/bootstrap.php index 17f647784..f34b4001e 100644 --- a/lib/Cake/bootstrap.php +++ b/lib/Cake/bootstrap.php @@ -23,6 +23,10 @@ define('TIME_START', microtime(true)); if (!defined('E_DEPRECATED')) { define('E_DEPRECATED', 8192); } + +if (!defined('E_USER_DEPRECATED')) { + define('E_USER_DEPRECATED', E_USER_NOTICE); +} error_reporting(E_ALL & ~E_DEPRECATED); if (!defined('CAKE_CORE_INCLUDE_PATH')) { From f3b990bf0f65d25b53e1f9942f751796d0c875e7 Mon Sep 17 00:00:00 2001 From: mark_story Date: Sun, 5 Feb 2012 12:00:30 -0500 Subject: [PATCH 06/24] Correct path display for plugins. Fixes #2548 --- lib/Cake/Console/Command/Task/ControllerTask.php | 2 +- lib/Cake/Console/Command/Task/FixtureTask.php | 2 +- lib/Cake/Console/Command/Task/ModelTask.php | 2 +- lib/Cake/Console/Command/Task/TestTask.php | 2 +- lib/Cake/Console/Command/Task/ViewTask.php | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/lib/Cake/Console/Command/Task/ControllerTask.php b/lib/Cake/Console/Command/Task/ControllerTask.php index 621b95cc8..c1178dcec 100644 --- a/lib/Cake/Console/Command/Task/ControllerTask.php +++ b/lib/Cake/Console/Command/Task/ControllerTask.php @@ -126,7 +126,7 @@ class ControllerTask extends BakeTask { protected function _interactive() { $this->interactive = true; $this->hr(); - $this->out(__d('cake_console', "Bake Controller\nPath: %s", $this->path)); + $this->out(__d('cake_console', "Bake Controller\nPath: %s", $this->getPath())); $this->hr(); if (empty($this->connection)) { diff --git a/lib/Cake/Console/Command/Task/FixtureTask.php b/lib/Cake/Console/Command/Task/FixtureTask.php index 36c51e3d7..bf58cd4a7 100644 --- a/lib/Cake/Console/Command/Task/FixtureTask.php +++ b/lib/Cake/Console/Command/Task/FixtureTask.php @@ -137,7 +137,7 @@ class FixtureTask extends BakeTask { protected function _interactive() { $this->DbConfig->interactive = $this->Model->interactive = $this->interactive = true; $this->hr(); - $this->out(__d('cake_console', "Bake Fixture\nPath: %s", $this->path)); + $this->out(__d('cake_console', "Bake Fixture\nPath: %s", $this->getPath())); $this->hr(); if (!isset($this->connection)) { diff --git a/lib/Cake/Console/Command/Task/ModelTask.php b/lib/Cake/Console/Command/Task/ModelTask.php index 3fb6c2e6a..28bfefd5e 100644 --- a/lib/Cake/Console/Command/Task/ModelTask.php +++ b/lib/Cake/Console/Command/Task/ModelTask.php @@ -190,7 +190,7 @@ class ModelTask extends BakeTask { */ protected function _interactive() { $this->hr(); - $this->out(__d('cake_console', "Bake Model\nPath: %s", $this->path)); + $this->out(__d('cake_console', "Bake Model\nPath: %s", $this->getPath())); $this->hr(); $this->interactive = true; diff --git a/lib/Cake/Console/Command/Task/TestTask.php b/lib/Cake/Console/Command/Task/TestTask.php index 503ddd77f..66646f597 100644 --- a/lib/Cake/Console/Command/Task/TestTask.php +++ b/lib/Cake/Console/Command/Task/TestTask.php @@ -94,7 +94,7 @@ class TestTask extends BakeTask { $this->interactive = true; $this->hr(); $this->out(__d('cake_console', 'Bake Tests')); - $this->out(__d('cake_console', 'Path: %s', $this->path)); + $this->out(__d('cake_console', 'Path: %s', $this->getPath())); $this->hr(); if ($type) { diff --git a/lib/Cake/Console/Command/Task/ViewTask.php b/lib/Cake/Console/Command/Task/ViewTask.php index b125d0791..4fe53b7ec 100644 --- a/lib/Cake/Console/Command/Task/ViewTask.php +++ b/lib/Cake/Console/Command/Task/ViewTask.php @@ -195,7 +195,7 @@ class ViewTask extends BakeTask { */ protected function _interactive() { $this->hr(); - $this->out(sprintf("Bake View\nPath: %s", $this->path)); + $this->out(sprintf("Bake View\nPath: %s", $this->getPath())); $this->hr(); $this->DbConfig->interactive = $this->Controller->interactive = $this->interactive = true; From 4bb404085113b92221da84c37dac3cd7d6f7ec69 Mon Sep 17 00:00:00 2001 From: mark_story Date: Sun, 5 Feb 2012 12:54:20 -0500 Subject: [PATCH 07/24] Check method existence before calling. Datasource does not implemente calculate() or expression(). Only call them if they exist. Fixes #2535 --- lib/Cake/Model/Model.php | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/lib/Cake/Model/Model.php b/lib/Cake/Model/Model.php index 2d7486e4f..5b617d9b0 100644 --- a/lib/Cake/Model/Model.php +++ b/lib/Cake/Model/Model.php @@ -2589,6 +2589,10 @@ class Model extends Object { protected function _findCount($state, $query, $results = array()) { if ($state === 'before') { $db = $this->getDataSource(); + $query['order'] = false; + if (!method_exists($db, 'calculate') || !method_exists($db, 'expression')) { + return $query; + } if (empty($query['fields'])) { $query['fields'] = $db->calculate($this, 'count'); } elseif (is_string($query['fields']) && !preg_match('/count/i', $query['fields'])) { @@ -2596,7 +2600,6 @@ class Model extends Object { $db->expression($query['fields']), 'count' )); } - $query['order'] = false; return $query; } elseif ($state === 'after') { foreach (array(0, $this->alias) as $key) { From f799d1c056ec818f43de6e7685e5245b4362131f Mon Sep 17 00:00:00 2001 From: mark_story Date: Sun, 5 Feb 2012 13:07:01 -0500 Subject: [PATCH 08/24] Add absolute path to cake/vendors. When the app + cake are on different paths, `VENDORS` is incorrect, and the built-in repo/vendors directory is not reachable by the default paths. Fixes #2545 --- lib/Cake/Core/App.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/Cake/Core/App.php b/lib/Cake/Core/App.php index 707b345dc..9d0e9d968 100644 --- a/lib/Cake/Core/App.php +++ b/lib/Cake/Core/App.php @@ -861,7 +861,9 @@ class App { '%s' . 'locale' . DS ), 'Vendor' => array( - '%s' . 'Vendor' . DS, VENDORS + '%s' . 'Vendor' . DS, + dirname(dirname(CAKE)) . DS . 'vendors' . DS, + VENDORS ), 'Plugin' => array( APP . 'Plugin' . DS, From 5886b25345481960c0a2f741b7ca38a803ab109c Mon Sep 17 00:00:00 2001 From: Jose Lorenzo Rodriguez Date: Sun, 5 Feb 2012 19:33:52 -0430 Subject: [PATCH 09/24] Releasing 2.0.6 --- lib/Cake/Config/config.php | 2 +- lib/Cake/VERSION.txt | 3 +-- lib/Cake/View/Pages/home.ctp | 2 +- 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/lib/Cake/Config/config.php b/lib/Cake/Config/config.php index 9bbbb5cde..7e0e9dd1f 100644 --- a/lib/Cake/Config/config.php +++ b/lib/Cake/Config/config.php @@ -16,5 +16,5 @@ * @since CakePHP(tm) v 1.1.11.4062 * @license MIT License (http://www.opensource.org/licenses/mit-license.php) */ -$config['Cake.version'] = '2.0.5'; +$config['Cake.version'] = '2.0.6'; return $config; diff --git a/lib/Cake/VERSION.txt b/lib/Cake/VERSION.txt index a555d42c1..af0a7c892 100644 --- a/lib/Cake/VERSION.txt +++ b/lib/Cake/VERSION.txt @@ -17,5 +17,4 @@ // @license MIT License (http://www.opensource.org/licenses/mit-license.php) // +--------------------------------------------------------------------------------------------+ // //////////////////////////////////////////////////////////////////////////////////////////////////// -2.0.5 - +2.0.6 diff --git a/lib/Cake/View/Pages/home.ctp b/lib/Cake/View/Pages/home.ctp index 2fac59aad..59e8013ba 100644 --- a/lib/Cake/View/Pages/home.ctp +++ b/lib/Cake/View/Pages/home.ctp @@ -24,7 +24,7 @@ App::uses('Debugger', 'Utility');

For updates and important announcements, visit http://cakefest.org

- + 0): Debugger::checkSecurityKeys(); From 610213dd6c75ec010a42e5b696995863dc10fd50 Mon Sep 17 00:00:00 2001 From: ADmad Date: Tue, 7 Feb 2012 01:12:14 +0530 Subject: [PATCH 10/24] Added test for deleting dependent hasMany associated records. Refs #2553 --- lib/Cake/Test/Case/Model/ModelDeleteTest.php | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/lib/Cake/Test/Case/Model/ModelDeleteTest.php b/lib/Cake/Test/Case/Model/ModelDeleteTest.php index 9ce2e0717..e3a64e0b1 100644 --- a/lib/Cake/Test/Case/Model/ModelDeleteTest.php +++ b/lib/Cake/Test/Case/Model/ModelDeleteTest.php @@ -555,7 +555,9 @@ class ModelDeleteTest extends BaseModelTest { * @return void */ public function testDeleteDependent() { - $this->loadFixtures('Bidding', 'BiddingMessage'); + $this->loadFixtures('Bidding', 'BiddingMessage', 'Article', + 'ArticlesTag', 'Comment', 'User', 'Attachment' + ); $Bidding = new Bidding(); $result = $Bidding->find('all'); $expected = array( @@ -626,6 +628,20 @@ class ModelDeleteTest extends BaseModelTest { ), ); $this->assertEquals($expected, $result); + + $Article = new Article(); + $result = $Article->Comment->find('count', array( + 'conditions' => array('Comment.article_id' => 1) + )); + $this->assertEquals(4, $result); + + $result = $Article->delete(1, true); + $this->assertIdentical(true, true); + + $result = $Article->Comment->find('count', array( + 'conditions' => array('Comment.article_id' => 1) + )); + $this->assertEquals(0, $result); } /** From 10350a9fdcd7f25c9d20e772781737f4ab5913c3 Mon Sep 17 00:00:00 2001 From: 0x20h Date: Mon, 6 Feb 2012 21:02:52 +0100 Subject: [PATCH 11/24] added a further note where to look for available cache implementations and their respective settings --- app/Config/core.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/app/Config/core.php b/app/Config/core.php index d128bbd50..2493bcb6d 100644 --- a/app/Config/core.php +++ b/app/Config/core.php @@ -235,7 +235,9 @@ * Pick the caching engine to use. If APC is enabled use it. * If running via cli - apc is disabled by default. ensure it's available and enabled in this case * - * Note: 'default' and other application caches should be configured in app/Config/bootstrap.php + * Note: 'default' and other application caches should be configured in app/Config/bootstrap.php. + * Please check the comments in boostrap.php for more info on the cache engines available + * and their setttings. */ $engine = 'File'; if (extension_loaded('apc') && function_exists('apc_dec') && (php_sapi_name() !== 'cli' || ini_get('apc.enable_cli'))) { From fa5f17524428a9532d5b3168ab9d898bf0e0e61d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vin=C3=ADcius=20Krolow?= Date: Sun, 5 Feb 2012 21:38:08 -0200 Subject: [PATCH 12/24] Improve the extract to know when there is the same string inside one plural Fixes #2538 --- lib/Cake/Console/Command/Task/ExtractTask.php | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/lib/Cake/Console/Command/Task/ExtractTask.php b/lib/Cake/Console/Command/Task/ExtractTask.php index ed28c196b..3cd562073 100644 --- a/lib/Cake/Console/Command/Task/ExtractTask.php +++ b/lib/Cake/Console/Command/Task/ExtractTask.php @@ -76,6 +76,13 @@ class ExtractTask extends AppShell { */ protected $_strings = array(); +/** + * Extracted sigular strings + * + * @var array + */ + protected $_singulars = array(); + /** * Destination path * @@ -325,6 +332,12 @@ class ExtractTask extends AppShell { if ($mapCount == count($strings)) { extract(array_combine($map, $strings)); $domain = isset($domain) ? $domain : 'default'; + if (isset($plural)) { + if (!isset($_this->_singulars[$domain])) { + $this->_singulars[$domain] = array(); + } + array_push($this->_singulars[$domain], $singular); + } $string = isset($plural) ? $singular . "\0" . $plural : $singular; $this->_strings[$domain][$string][$this->_file][] = $line; } else { @@ -428,7 +441,10 @@ class ExtractTask extends AppShell { $header = '#: ' . str_replace($this->_paths, '', $occurrences) . "\n"; if (strpos($string, "\0") === false) { - $sentence = "msgid \"{$string}\"\n"; + if (isset($this->_singulars[$domain]) && in_array($string, $this->_singulars[$domain])) { + continue; + } + $sentence = "msgid \"{$string}\"\n"; $sentence .= "msgstr \"\"\n\n"; } else { list($singular, $plural) = explode("\0", $string); From 4949a87b7ee4aa66f9a89cdc17bdd87edd86e826 Mon Sep 17 00:00:00 2001 From: mark_story Date: Mon, 6 Feb 2012 21:25:11 -0500 Subject: [PATCH 13/24] Fix issues with duplicate msgid values. Msgid values could be duplicated if the same string was used for singular and pluralized translations. Re-index how the data is stored so duplicate singular detection per domain is easier. Fixes #2538 --- lib/Cake/Console/Command/Task/ExtractTask.php | 43 +++++++++++-------- .../Console/Command/Task/ExtractTaskTest.php | 17 +++++++- lib/Cake/Test/test_app/View/Pages/extract.ctp | 1 + 3 files changed, 41 insertions(+), 20 deletions(-) diff --git a/lib/Cake/Console/Command/Task/ExtractTask.php b/lib/Cake/Console/Command/Task/ExtractTask.php index 3cd562073..fad45e89a 100644 --- a/lib/Cake/Console/Command/Task/ExtractTask.php +++ b/lib/Cake/Console/Command/Task/ExtractTask.php @@ -70,18 +70,18 @@ class ExtractTask extends AppShell { protected $_tokens = array(); /** - * Extracted strings + * Extracted strings indexed by domain. * * @var array */ protected $_strings = array(); /** - * Extracted sigular strings + * Singular strings and their line numbers. * * @var array */ - protected $_singulars = array(); + protected $_lines = array(); /** * Destination path @@ -332,14 +332,10 @@ class ExtractTask extends AppShell { if ($mapCount == count($strings)) { extract(array_combine($map, $strings)); $domain = isset($domain) ? $domain : 'default'; - if (isset($plural)) { - if (!isset($_this->_singulars[$domain])) { - $this->_singulars[$domain] = array(); - } - array_push($this->_singulars[$domain], $singular); - } + $string = isset($plural) ? $singular . "\0" . $plural : $singular; - $this->_strings[$domain][$string][$this->_file][] = $line; + $this->_strings[$domain][] = $string; + $this->_lines[$domain][$singular][$this->_file][] = $line; } else { $this->_markerError($this->_file, $line, $functionName, $count); } @@ -419,7 +415,8 @@ class ExtractTask extends AppShell { $message = $rule; } if ($message) { - $this->_strings[$domain][$message][$file][] = 'validation for field ' . $field; + $this->_strings[$domain][] = $message; + $this->_lines[$domain][$message][$file][] = 'validation for field ' . $field; } } } @@ -432,7 +429,16 @@ class ExtractTask extends AppShell { */ protected function _buildFiles() { foreach ($this->_strings as $domain => $strings) { - foreach ($strings as $string => $files) { + $added = array(); + rsort($strings); + + foreach ($strings as $i => $string) { + $plural = false; + $singular = $string; + if (strpos($string, "\0") !== false) { + list($singular, $plural) = explode("\0", $string); + } + $files = $this->_lines[$domain][$singular]; $occurrences = array(); foreach ($files as $file => $lines) { $occurrences[] = $file . ':' . implode(';', $lines); @@ -440,20 +446,21 @@ class ExtractTask extends AppShell { $occurrences = implode("\n#: ", $occurrences); $header = '#: ' . str_replace($this->_paths, '', $occurrences) . "\n"; - if (strpos($string, "\0") === false) { - if (isset($this->_singulars[$domain]) && in_array($string, $this->_singulars[$domain])) { - continue; - } - $sentence = "msgid \"{$string}\"\n"; + if ($plural === false && !empty($added[$singular])) { + continue; + } + + if ($plural === false) { + $sentence = "msgid \"{$string}\"\n"; $sentence .= "msgstr \"\"\n\n"; } else { - list($singular, $plural) = explode("\0", $string); $sentence = "msgid \"{$singular}\"\n"; $sentence .= "msgid_plural \"{$plural}\"\n"; $sentence .= "msgstr[0] \"\"\n"; $sentence .= "msgstr[1] \"\"\n\n"; } + $added[$singular] = true; $this->_store($domain, $header, $sentence); if ($domain != 'default' && $this->_merge) { $this->_store('default', $header, $sentence); diff --git a/lib/Cake/Test/Case/Console/Command/Task/ExtractTaskTest.php b/lib/Cake/Test/Case/Console/Command/Task/ExtractTaskTest.php index 15e0254ee..d358c7540 100644 --- a/lib/Cake/Test/Case/Console/Command/Task/ExtractTaskTest.php +++ b/lib/Cake/Test/Case/Console/Command/Task/ExtractTaskTest.php @@ -93,27 +93,37 @@ class ExtractTaskTest extends CakeTestCase { // home.ctp $pattern = '/msgid "Your tmp directory is writable."\nmsgstr ""\n/'; $this->assertRegExp($pattern, $result); + $pattern = '/msgid "Your tmp directory is NOT writable."\nmsgstr ""\n/'; $this->assertRegExp($pattern, $result); + $pattern = '/msgid "The %s is being used for caching. To change the config edit '; $pattern .= 'APP\/config\/core.php "\nmsgstr ""\n/'; $this->assertRegExp($pattern, $result); + $pattern = '/msgid "Your cache is NOT working. Please check '; $pattern .= 'the settings in APP\/config\/core.php"\nmsgstr ""\n/'; $this->assertRegExp($pattern, $result); + $pattern = '/msgid "Your database configuration file is present."\nmsgstr ""\n/'; $this->assertRegExp($pattern, $result); + $pattern = '/msgid "Your database configuration file is NOT present."\nmsgstr ""\n/'; $this->assertRegExp($pattern, $result); + $pattern = '/msgid "Rename config\/database.php.default to '; $pattern .= 'config\/database.php"\nmsgstr ""\n/'; $this->assertRegExp($pattern, $result); + $pattern = '/msgid "Cake is able to connect to the database."\nmsgstr ""\n/'; $this->assertRegExp($pattern, $result); + $pattern = '/msgid "Cake is NOT able to connect to the database."\nmsgstr ""\n/'; $this->assertRegExp($pattern, $result); + $pattern = '/msgid "Editing this Page"\nmsgstr ""\n/'; $this->assertRegExp($pattern, $result); + $pattern = '/msgid "To change the content of this page, create: APP\/views\/pages\/home\.ctp/'; $this->assertRegExp($pattern, $result); @@ -121,10 +131,13 @@ class ExtractTaskTest extends CakeTestCase { $this->assertRegExp($pattern, $result); // extract.ctp - $pattern = '/\#: (\\\\|\/)extract\.ctp:6\n'; + $pattern = '/\#: (\\\\|\/)extract\.ctp:15;6\n'; $pattern .= 'msgid "You have %d new message."\nmsgid_plural "You have %d new messages."/'; $this->assertRegExp($pattern, $result); + $pattern = '/msgid "You have %d new message."\nmsgstr ""/'; + $this->assertNotRegExp($pattern, $result, 'No duplicate msgid'); + $pattern = '/\#: (\\\\|\/)extract\.ctp:7\n'; $pattern .= 'msgid "You deleted %d message."\nmsgid_plural "You deleted %d messages."/'; $this->assertRegExp($pattern, $result); @@ -134,7 +147,7 @@ class ExtractTaskTest extends CakeTestCase { $pattern .= 'msgid "Editing this Page"\nmsgstr ""/'; $this->assertRegExp($pattern, $result); - $pattern = '/\#: (\\\\|\/)extract\.ctp:17\nmsgid "'; + $pattern = '/\#: (\\\\|\/)extract\.ctp:18\nmsgid "'; $pattern .= 'Hot features!'; $pattern .= '\\\n - No Configuration: Set-up the database and let the magic begin'; $pattern .= '\\\n - Extremely Simple: Just look at the name...It\'s Cake'; diff --git a/lib/Cake/Test/test_app/View/Pages/extract.ctp b/lib/Cake/Test/test_app/View/Pages/extract.ctp index 5e6abf54e..cba9b012f 100644 --- a/lib/Cake/Test/test_app/View/Pages/extract.ctp +++ b/lib/Cake/Test/test_app/View/Pages/extract.ctp @@ -12,6 +12,7 @@ echo __dn('domain', 'You deleted %d message (domain).', 'You deleted %d messages // Duplicated Message echo __('Editing this Page'); +echo __('You have %d new message.'); // Multiline __('Hot features!' From bf700c826a582b1f4311bdf009b977e0292806db Mon Sep 17 00:00:00 2001 From: ADmad Date: Wed, 8 Feb 2012 01:08:04 +0530 Subject: [PATCH 14/24] Made specifying 'extension' optional. Fixed bug where downloaded file did not have extension when 'name' was specified. Fixes #2554 --- lib/Cake/Test/Case/View/MediaViewTest.php | 28 +++++++++++++++++++++-- lib/Cake/View/MediaView.php | 14 +++++++++--- 2 files changed, 37 insertions(+), 5 deletions(-) diff --git a/lib/Cake/Test/Case/View/MediaViewTest.php b/lib/Cake/Test/Case/View/MediaViewTest.php index d1377ee20..38d68a239 100644 --- a/lib/Cake/Test/Case/View/MediaViewTest.php +++ b/lib/Cake/Test/Case/View/MediaViewTest.php @@ -244,6 +244,7 @@ class MediaViewTest extends CakeTestCase { 'path' => CAKE . 'Test' . DS . 'test_app' . DS . 'Config' . DS, 'id' => 'no_section.ini', 'extension' => 'ini', + 'name' => 'config' ); $this->MediaView->expects($this->exactly(2)) ->method('_isActive') @@ -270,7 +271,7 @@ class MediaViewTest extends CakeTestCase { $this->MediaView->response->expects($this->once()) ->method('download') - ->with('no_section.ini'); + ->with('config.ini'); $this->MediaView->response->expects($this->at(4)) ->method('header') @@ -357,7 +358,7 @@ class MediaViewTest extends CakeTestCase { * * @return void */ - function testRenderUpperExtesnion() { + public function testRenderUpperExtension() { $this->MediaView->viewVars = array( 'path' => CAKE . 'Test' . DS . 'test_app' . DS . 'Vendor' . DS .'img' . DS, 'id' => 'test_2.JPG', @@ -376,4 +377,27 @@ class MediaViewTest extends CakeTestCase { $this->MediaView->render(); } +/** + * Test downloading files with extension not explicitly set. + * + * @return void + */ + public function testRenderExtensionNotSet() { + $this->MediaView->viewVars = array( + 'path' => CAKE . 'Test' . DS . 'test_app' . DS . 'Vendor' . DS .'img' . DS, + 'id' => 'test_2.JPG', + ); + + $this->MediaView->response->expects($this->any()) + ->method('type') + ->with('jpg') + ->will($this->returnArgument(0)); + + $this->MediaView->expects($this->at(0)) + ->method('_isActive') + ->will($this->returnValue(true)); + + $this->MediaView->render(); + } + } diff --git a/lib/Cake/View/MediaView.php b/lib/Cake/View/MediaView.php index 96fdf543b..99d301968 100644 --- a/lib/Cake/View/MediaView.php +++ b/lib/Cake/View/MediaView.php @@ -31,9 +31,11 @@ App::uses('CakeRequest', 'Network'); * - `id` The filename on the server's filesystem, including extension. * - `name` The filename that will be sent to the user, specified without the extension. * - `download` Set to true to set a `Content-Disposition` header. This is ideal for file downloads. - * - `extension` The extension of the file being served. This is used to set the mimetype + * - `extension` The extension of the file being served. This is used to set the mimetype. + * If not provided its extracted from filename provided as `id`. * - `path` The absolute path, including the trailing / on the server's filesystem to `id`. * - `mimeType` The mime type of the file if CakeResponse doesn't know about it. + * Must be an associative array with extension as key and mime type as value eg. array('ini' => 'text/plain') * * ### Usage * @@ -113,7 +115,11 @@ class MediaView extends View { $this->response->type($mimeType); } - if (isset($extension) && $this->_isActive()) { + if (!isset($extension)) { + $extension = pathinfo($id, PATHINFO_EXTENSION); + } + + if ($this->_isActive()) { $extension = strtolower($extension); $chunkSize = 8192; $buffer = ''; @@ -128,7 +134,7 @@ class MediaView extends View { } else { $modified = time(); } - if ($this->response->type($extension) === false) { + if (!$extension || $this->response->type($extension) === false) { $download = true; } @@ -157,6 +163,8 @@ class MediaView extends View { } if (is_null($name)) { $name = $id; + } elseif ($extension) { + $name .= '.' . $extension; } $this->response->download($name); $this->response->header(array('Accept-Ranges' => 'bytes')); From 0cfec525b226436361ad9d0ca2802ba7af30ae14 Mon Sep 17 00:00:00 2001 From: mark_story Date: Thu, 9 Feb 2012 22:27:30 -0500 Subject: [PATCH 15/24] Allow SqlServer to execute procs correctly. Both SELECT and EXECUTE statements should go through the parent method as they could fetch results. Fixes #2558 --- .../Model/Datasource/Database/Sqlserver.php | 2 +- .../Datasource/Database/SqlserverTest.php | 27 +++++++++++++++++++ 2 files changed, 28 insertions(+), 1 deletion(-) diff --git a/lib/Cake/Model/Datasource/Database/Sqlserver.php b/lib/Cake/Model/Datasource/Database/Sqlserver.php index 1db5bed09..5db56f8b2 100644 --- a/lib/Cake/Model/Datasource/Database/Sqlserver.php +++ b/lib/Cake/Model/Datasource/Database/Sqlserver.php @@ -745,7 +745,7 @@ class Sqlserver extends DboSource { */ protected function _execute($sql, $params = array(), $prepareOptions = array()) { $this->_lastAffected = false; - if (strncasecmp($sql, 'SELECT', 6) == 0) { + if (strncasecmp($sql, 'SELECT', 6) == 0 || preg_match('/^EXEC(?:UCUTE)?\s/m', $sql) > 0) { $prepareOptions += array(PDO::ATTR_CURSOR => PDO::CURSOR_SCROLL); return parent::_execute($sql, $params, $prepareOptions); } diff --git a/lib/Cake/Test/Case/Model/Datasource/Database/SqlserverTest.php b/lib/Cake/Test/Case/Model/Datasource/Database/SqlserverTest.php index 95394bf62..c01678c68 100644 --- a/lib/Cake/Test/Case/Model/Datasource/Database/SqlserverTest.php +++ b/lib/Cake/Test/Case/Model/Datasource/Database/SqlserverTest.php @@ -633,4 +633,31 @@ class SqlserverTest extends CakeTestCase { $this->assertEquals('nate', $results[1]['User']['user']); } +/** + * Test that the return of stored procedures is honoured + * + * @return void + */ + public function testStoredProcedureReturn() { + $sql = <<Dbo->execute($sql); + + $sql = <<Dbo->execute($sql); + $this->Dbo->execute('DROP PROC cake_test_procedure'); + + $result = $query->fetch(); + $this->assertEquals(2, $result['value']); + } + } From 9c1fa28d601dd5391f213cfbe0284c08059166b1 Mon Sep 17 00:00:00 2001 From: mark_story Date: Fri, 10 Feb 2012 12:43:07 -0500 Subject: [PATCH 16/24] Its EXECUTE not EXECUCUTE Also make the search insensitive as casing bugs are no fun. --- lib/Cake/Model/Datasource/Database/Sqlserver.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/Cake/Model/Datasource/Database/Sqlserver.php b/lib/Cake/Model/Datasource/Database/Sqlserver.php index 5db56f8b2..c43cf3870 100644 --- a/lib/Cake/Model/Datasource/Database/Sqlserver.php +++ b/lib/Cake/Model/Datasource/Database/Sqlserver.php @@ -745,7 +745,7 @@ class Sqlserver extends DboSource { */ protected function _execute($sql, $params = array(), $prepareOptions = array()) { $this->_lastAffected = false; - if (strncasecmp($sql, 'SELECT', 6) == 0 || preg_match('/^EXEC(?:UCUTE)?\s/m', $sql) > 0) { + if (strncasecmp($sql, 'SELECT', 6) == 0 || preg_match('/^EXEC(?:UTE)?\s/mi', $sql) > 0) { $prepareOptions += array(PDO::ATTR_CURSOR => PDO::CURSOR_SCROLL); return parent::_execute($sql, $params, $prepareOptions); } From 83e8d436f815550f457fdcdbf03da8a5c9dfd68e Mon Sep 17 00:00:00 2001 From: ADmad Date: Sat, 11 Feb 2012 06:09:58 +0530 Subject: [PATCH 17/24] Fixing docbloc and adding tests for FormHelper::tagIsInvalid(). Refs #2562 --- .../Test/Case/View/Helper/FormHelperTest.php | 25 +++++++++++++++++++ lib/Cake/View/Helper/FormHelper.php | 14 +++++------ 2 files changed, 32 insertions(+), 7 deletions(-) diff --git a/lib/Cake/Test/Case/View/Helper/FormHelperTest.php b/lib/Cake/Test/Case/View/Helper/FormHelperTest.php index 41cf2c1e9..f1002c661 100644 --- a/lib/Cake/Test/Case/View/Helper/FormHelperTest.php +++ b/lib/Cake/Test/Case/View/Helper/FormHelperTest.php @@ -1434,6 +1434,31 @@ class FormHelperTest extends CakeTestCase { $this->assertEquals(array(), $this->Form->fields); } +/** + * testTagIsInvalid method + * + * @return void + */ + public function testTagIsInvalid() { + $Contact = ClassRegistry::getObject('Contact'); + $Contact->validationErrors[0]['email'] = array('Please provide an email'); + + $this->Form->setEntity('Contact.0.email'); + $result = $this->Form->tagIsInvalid(); + $expected = array('Please provide an email'); + $this->assertEquals($expected, $result); + + $this->Form->setEntity('Contact.1.email'); + $result = $this->Form->tagIsInvalid(); + $expected = false; + $this->assertIdentical($expected, $result); + + $this->Form->setEntity('Contact.0.name'); + $result = $this->Form->tagIsInvalid(); + $expected = false; + $this->assertIdentical($expected, $result); + } + /** * testPasswordValidation method * diff --git a/lib/Cake/View/Helper/FormHelper.php b/lib/Cake/View/Helper/FormHelper.php index 80dca5840..ea354d3d1 100644 --- a/lib/Cake/View/Helper/FormHelper.php +++ b/lib/Cake/View/Helper/FormHelper.php @@ -272,8 +272,8 @@ 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 the error - * string. The error string could be ''. + * @return mixed Either false when there or 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 */ public function tagIsInvalid() { @@ -289,8 +289,8 @@ class FormHelper extends AppHelper { if (empty($errors)) { return false; } - $error = Set::classicExtract($errors, join('.', $entity)); - return $error === null ? false : $error; + $errors = Set::classicExtract($errors, join('.', $entity)); + return $errors === null ? false : $errors; } /** @@ -739,7 +739,7 @@ class FormHelper extends AppHelper { * * ### Options * - * - `for` - Set the for attribute, if its not defined the for attribute + * - `for` - Set the for attribute, if its not defined the for attribute * will be generated from the $fieldName parameter using * FormHelper::domId(). * @@ -776,8 +776,8 @@ class FormHelper extends AppHelper { * }}} * * @param string $fieldName This should be "Modelname.fieldname" - * @param string $text Text that will appear in the label field. If - * $text is left undefined the text will be inflected from the + * @param string $text Text that will appear in the label field. If + * $text is left undefined the text will be inflected from the * fieldName. * @param mixed $options An array of HTML attributes, or a string, to be used as a class name. * @return string The formatted LABEL element From 730ac10ae4d54b7dfb1af211ee804df7d2910eba Mon Sep 17 00:00:00 2001 From: Kyle Robinson Young Date: Fri, 10 Feb 2012 22:17:58 -0800 Subject: [PATCH 18/24] Add missing options to NumberHelper docblocks --- lib/Cake/View/Helper/NumberHelper.php | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/lib/Cake/View/Helper/NumberHelper.php b/lib/Cake/View/Helper/NumberHelper.php index 8457133f6..3019a6a92 100644 --- a/lib/Cake/View/Helper/NumberHelper.php +++ b/lib/Cake/View/Helper/NumberHelper.php @@ -59,7 +59,7 @@ class NumberHelper extends AppHelper { */ protected $_currencyDefaults = array( 'wholeSymbol' => '', 'wholePosition' => 'before', 'fractionSymbol' => '', 'fractionPosition' => 'after', - 'zero' => '0', 'places' => 2, 'thousands' => ',', 'decimals' => '.','negative' => '()', 'escape' => true, + 'zero' => '0', 'places' => 2, 'thousands' => ',', 'decimals' => '.', 'negative' => '()', 'escape' => true, ); /** @@ -165,7 +165,11 @@ class NumberHelper extends AppHelper { * - `thousands` - Thousands separator ie. ',' * - `decimals` - Decimal separator symbol ie. '.' * - `negative` - Symbol for negative numbers. If equal to '()', the number will be wrapped with ( and ) - * - `escape` - Should the output be htmlentity escaped? Defaults to true + * - `escape` - Should the output be htmlentity escaped? Defaults to true. + * - `wholeSymbol` String to use for whole numbers ie. ' dollars'. + * - `wholePosition` Either 'before' or 'after' to place the whole symbol. + * - `fractionSymbol` String to use for fraction numbers ie. ' cents'. + * - `fractionPosition` Either 'before' or 'after' to place the fraction symbol. * * @param float $number * @param string $currency Shortcut to default options. Valid values are 'USD', 'EUR', 'GBP', otherwise @@ -238,8 +242,10 @@ class NumberHelper extends AppHelper { * * {{{ * array( - * 'before' => '$', 'after' => 'c', 'zero' => 0, 'places' => 2, 'thousands' => ',', - * 'decimals' => '.', 'negative' => '()', 'escape' => true + * 'wholeSymbol' => '', 'wholePosition' => 'before', + * 'fractionSymbol' => '', 'fractionPosition' => 'after', + * 'zero' => '0', 'places' => 2, 'thousands' => ',', + * 'decimals' => '.', 'negative' => '()', 'escape' => true, * ) * }}} * From e1dba6798fcce3d9cedc6440f1485af966d1b004 Mon Sep 17 00:00:00 2001 From: ADmad Date: Sat, 11 Feb 2012 13:53:46 +0530 Subject: [PATCH 19/24] Added missing echos --- lib/Cake/View/Pages/home.ctp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/Cake/View/Pages/home.ctp b/lib/Cake/View/Pages/home.ctp index 59e8013ba..2b337ec9b 100644 --- a/lib/Cake/View/Pages/home.ctp +++ b/lib/Cake/View/Pages/home.ctp @@ -119,9 +119,9 @@ if (isset($filePresent)): App::uses('Validation', 'Utility'); if (!Validation::alphaNumeric('cakephp')) { echo '

'; - __d('cake_dev', 'PCRE has not been compiled with Unicode support.'); - echo '
'; - __d('cake_dev', 'Recompile PCRE with Unicode support by adding --enable-unicode-properties when configuring'); + echo __d('cake_dev', 'PCRE has not been compiled with Unicode support.'); + echo '
'; + echo __d('cake_dev', 'Recompile PCRE with Unicode support by adding --enable-unicode-properties when configuring'); echo '

'; } ?> From 0207a61e9ba357219740cdf716a75f17419572bf Mon Sep 17 00:00:00 2001 From: mark_story Date: Sat, 11 Feb 2012 10:15:53 -0500 Subject: [PATCH 20/24] Move alias wrapping into _formatAddress() Fixes #2502 --- lib/Cake/Network/Email/CakeEmail.php | 6 +++--- lib/Cake/Test/Case/Network/Email/CakeEmailTest.php | 2 ++ 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/lib/Cake/Network/Email/CakeEmail.php b/lib/Cake/Network/Email/CakeEmail.php index 69c3982c2..c9aaf72ce 100644 --- a/lib/Cake/Network/Email/CakeEmail.php +++ b/lib/Cake/Network/Email/CakeEmail.php @@ -686,6 +686,9 @@ class CakeEmail { if ($email === $alias) { $return[] = $email; } else { + if (strpos($alias, ',') !== false) { + $alias = '"' . $alias . '"'; + } $return[] = sprintf('%s <%s>', $this->_encode($alias), $email); } } @@ -1109,9 +1112,6 @@ class CakeEmail { $restore = mb_internal_encoding(); mb_internal_encoding($this->_appCharset); } - if (strpos($text, ',') !== false) { - $text = '"' . $text . '"'; - } $return = mb_encode_mimeheader($text, $this->headerCharset, 'B'); if ($internalEncoding) { mb_internal_encoding($restore); diff --git a/lib/Cake/Test/Case/Network/Email/CakeEmailTest.php b/lib/Cake/Test/Case/Network/Email/CakeEmailTest.php index a962bab1c..3c8c0d0fb 100644 --- a/lib/Cake/Test/Case/Network/Email/CakeEmailTest.php +++ b/lib/Cake/Test/Case/Network/Email/CakeEmailTest.php @@ -395,6 +395,8 @@ class CakeEmailTest extends CakeTestCase { $this->CakeEmail->subject('You have a new message.'); $this->assertSame($this->CakeEmail->subject(), 'You have a new message.'); + $this->CakeEmail->subject('You have a new message, I think.'); + $this->assertSame($this->CakeEmail->subject(), 'You have a new message, I think.'); $this->CakeEmail->subject(1); $this->assertSame($this->CakeEmail->subject(), '1'); From 6f914174a63c2af27547d5123409d36865784abe Mon Sep 17 00:00:00 2001 From: mark_story Date: Sat, 11 Feb 2012 10:29:18 -0500 Subject: [PATCH 21/24] Fix issues with double / & leading/trailing / Authorize classes should remove // and leading trailing / Without this incorrect paths that fail to match nodes can be generated. This also allows settings[actionPath] to be permissive in what it accepts. Fixes #2563 --- .../Component/Auth/BaseAuthorize.php | 4 ++- .../Component/Auth/ActionsAuthorizeTest.php | 25 +++++++++++++++---- 2 files changed, 23 insertions(+), 6 deletions(-) diff --git a/lib/Cake/Controller/Component/Auth/BaseAuthorize.php b/lib/Cake/Controller/Component/Auth/BaseAuthorize.php index f4c33fe3d..00763ab84 100644 --- a/lib/Cake/Controller/Component/Auth/BaseAuthorize.php +++ b/lib/Cake/Controller/Component/Auth/BaseAuthorize.php @@ -108,11 +108,13 @@ abstract class BaseAuthorize { */ public function action($request, $path = '/:plugin/:controller/:action') { $plugin = empty($request['plugin']) ? null : Inflector::camelize($request['plugin']) . '/'; - return str_replace( + $path = str_replace( array(':controller', ':action', ':plugin/'), array(Inflector::camelize($request['controller']), $request['action'], $plugin), $this->settings['actionPath'] . $path ); + $path = str_replace('//', '/', $path); + return trim($path, '/'); } /** diff --git a/lib/Cake/Test/Case/Controller/Component/Auth/ActionsAuthorizeTest.php b/lib/Cake/Test/Case/Controller/Component/Auth/ActionsAuthorizeTest.php index 5861bfe03..dc3afda78 100644 --- a/lib/Cake/Test/Case/Controller/Component/Auth/ActionsAuthorizeTest.php +++ b/lib/Cake/Test/Case/Controller/Component/Auth/ActionsAuthorizeTest.php @@ -75,7 +75,7 @@ class ActionsAuthorizeTest extends CakeTestCase { $this->Acl->expects($this->once()) ->method('check') - ->with($user, '/controllers/Posts/index') + ->with($user, 'controllers/Posts/index') ->will($this->returnValue(false)); $this->assertFalse($this->auth->authorize($user['User'], $request)); @@ -104,7 +104,7 @@ class ActionsAuthorizeTest extends CakeTestCase { $this->Acl->expects($this->once()) ->method('check') - ->with($user, '/controllers/Posts/index') + ->with($user, 'controllers/Posts/index') ->will($this->returnValue(true)); $this->assertTrue($this->auth->authorize($user['User'], $request)); @@ -134,7 +134,7 @@ class ActionsAuthorizeTest extends CakeTestCase { $expected = array('TestPlugin.TestPluginAuthUser' => array('id' => 1, 'user' => 'mariano')); $this->Acl->expects($this->once()) ->method('check') - ->with($expected, '/controllers/Posts/index') + ->with($expected, 'controllers/Posts/index') ->will($this->returnValue(true)); $this->assertTrue($this->auth->authorize($user, $request)); @@ -154,8 +154,23 @@ class ActionsAuthorizeTest extends CakeTestCase { )); $result = $this->auth->action($request); + $this->assertEquals('controllers/Posts/index', $result); + } - $this->assertEquals('/controllers/Posts/index', $result); +/** + * Make sure that action() doesn't create double slashes anywhere. + * + * @return void + */ + public function testActionNoDoubleSlash() { + $this->auth->settings['actionPath'] = '/controllers/'; + $request = array( + 'plugin' => null, + 'controller' => 'posts', + 'action' => 'index' + ); + $result = $this->auth->action($request); + $this->assertEquals('controllers/Posts/index', $result); } /** @@ -172,6 +187,6 @@ class ActionsAuthorizeTest extends CakeTestCase { )); $result = $this->auth->action($request); - $this->assertEquals('/controllers/DebugKit/Posts/index', $result); + $this->assertEquals('controllers/DebugKit/Posts/index', $result); } } From 7e17da0ae8a81cfde96bef4e7d4be553c487e821 Mon Sep 17 00:00:00 2001 From: mark_story Date: Sat, 11 Feb 2012 11:32:44 -0500 Subject: [PATCH 22/24] Fix notice error when reading empty values. When reading empty values a notice error would be triggered. Slicing the first char off and comparing that solves this. Fixes #2537 --- .../Controller/Component/CookieComponent.php | 3 ++- .../Controller/Component/CookieComponentTest.php | 16 ++++++++++++++++ 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/lib/Cake/Controller/Component/CookieComponent.php b/lib/Cake/Controller/Component/CookieComponent.php index cea188349..3abb24ddc 100644 --- a/lib/Cake/Controller/Component/CookieComponent.php +++ b/lib/Cake/Controller/Component/CookieComponent.php @@ -483,7 +483,8 @@ class CookieComponent extends Component { * @return array Map of key and values */ protected function _explode($string) { - if ($string[0] === '{' || $string[0] === '[') { + $first = substr($string, 0, 1); + if ($first !== false && $first === '{' || $first === '[') { $ret = json_decode($string, true); return ($ret != null) ? $ret : $string; } diff --git a/lib/Cake/Test/Case/Controller/Component/CookieComponentTest.php b/lib/Cake/Test/Case/Controller/Component/CookieComponentTest.php index 56fe5b645..701973dab 100644 --- a/lib/Cake/Test/Case/Controller/Component/CookieComponentTest.php +++ b/lib/Cake/Test/Case/Controller/Component/CookieComponentTest.php @@ -471,6 +471,21 @@ class CookieComponentTest extends CakeTestCase { $this->assertEquals($expected, $result); } +/** + * Test reading empty values. + */ + public function testReadEmpty() { + $_COOKIE['CakeTestCookie'] = array( + 'JSON' => '{"name":"value"}', + 'Empty' => '', + 'String' => '{"somewhat:"broken"}' + ); + $this->assertEqual(array('name' => 'value'), $this->Cookie->read('JSON')); + $this->assertEqual('value', $this->Cookie->read('JSON.name')); + $this->assertEqual('', $this->Cookie->read('Empty')); + $this->assertEqual('{"somewhat:"broken"}', $this->Cookie->read('String')); + } + /** * test that no error is issued for non array data. * @@ -483,6 +498,7 @@ class CookieComponentTest extends CakeTestCase { $this->assertNull($this->Cookie->read('value')); } + /** * test that deleting a top level keys kills the child elements too. * From 4c01ba7224ab9609a644d8b331b8346e4d5fc4c9 Mon Sep 17 00:00:00 2001 From: mark_story Date: Sat, 11 Feb 2012 11:39:24 -0500 Subject: [PATCH 23/24] Add ics mime type. Fixes #2565 --- lib/Cake/Network/CakeResponse.php | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/Cake/Network/CakeResponse.php b/lib/Cake/Network/CakeResponse.php index 6a20545cc..52bc0c874 100644 --- a/lib/Cake/Network/CakeResponse.php +++ b/lib/Cake/Network/CakeResponse.php @@ -208,6 +208,7 @@ class CakeResponse { 'hh' => 'text/plain', 'html' => array('text/html', '*/*'), 'htm' => array('text/html', '*/*'), + 'ics' => 'text/calendar', 'm' => 'text/plain', 'rtf' => 'text/rtf', 'rtx' => 'text/richtext', From ab09229d405939234c3439ec8151aee145325183 Mon Sep 17 00:00:00 2001 From: mark_story Date: Sat, 11 Feb 2012 11:45:06 -0500 Subject: [PATCH 24/24] Update API docs View switching only happens for known mime types. Refs #2565 --- lib/Cake/Controller/Component/RequestHandlerComponent.php | 5 ++++- lib/Cake/Routing/Router.php | 6 ++++-- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/lib/Cake/Controller/Component/RequestHandlerComponent.php b/lib/Cake/Controller/Component/RequestHandlerComponent.php index 2279653b8..b0f2152f4 100644 --- a/lib/Cake/Controller/Component/RequestHandlerComponent.php +++ b/lib/Cake/Controller/Component/RequestHandlerComponent.php @@ -159,7 +159,10 @@ class RequestHandlerComponent extends Component { * switched based on the parsed extension or Accept-Type header. For example, if `controller/action.xml` * is requested, the view path becomes `app/View/Controller/xml/action.ctp`. Also if * `controller/action` is requested with `Accept-Type: application/xml` in the headers - * the view path will become `app/View/Controller/xml/action.ctp`. + * the view path will become `app/View/Controller/xml/action.ctp`. Layout and template + * types will only switch to mime-types recognized by CakeResponse. If you need to declare + * additional mime-types, you can do so using CakeResponse::type() in your controllers beforeFilter() + * method. * - If a helper with the same name as the extension exists, it is added to the controller. * - If the extension is of a type that RequestHandler understands, it will set that * Content-type in the response header. diff --git a/lib/Cake/Routing/Router.php b/lib/Cake/Routing/Router.php index d722cf7da..d8643f1a8 100644 --- a/lib/Cake/Routing/Router.php +++ b/lib/Cake/Routing/Router.php @@ -1030,15 +1030,17 @@ class Router { * Instructs the router to parse out file extensions from the URL. For example, * http://example.com/posts.rss would yield an file extension of "rss". * The file extension itself is made available in the controller as - * $this->params['url']['ext'], and is used by the RequestHandler component to + * `$this->params['ext']`, and is used by the RequestHandler component to * automatically switch to alternate layouts and templates, and load helpers - * corresponding to the given content, i.e. RssHelper. + * corresponding to the given content, i.e. RssHelper. Switching layouts and helpers + * requires that the chosen extension has a defined mime type in `CakeResponse` * * A list of valid extension can be passed to this method, i.e. Router::parseExtensions('rss', 'xml'); * If no parameters are given, anything after the first . (dot) after the last / in the URL will be * parsed, excluding querystring parameters (i.e. ?q=...). * * @return void + * @see RequestHandler::startup() */ public static function parseExtensions() { self::$_parseExtensions = true;