From 68c4b665500a02f33f8fd9359544fc19c22fb007 Mon Sep 17 00:00:00 2001 From: ADmad Date: Mon, 15 Aug 2011 18:26:08 +0530 Subject: [PATCH 01/18] Fixed bug in Validation::date(). Closes #1908 --- cake/libs/validation.php | 4 ++-- cake/tests/cases/libs/validation.test.php | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/cake/libs/validation.php b/cake/libs/validation.php index 2a4f871d8..b8abb5c94 100644 --- a/cake/libs/validation.php +++ b/cake/libs/validation.php @@ -400,7 +400,7 @@ class Validation extends Object { $regex['mdy'] = '%^(?:(?:(?:0?[13578]|1[02])(\\/|-|\\.|\\x20)31)\\1|(?:(?:0?[13-9]|1[0-2])(\\/|-|\\.|\\x20)(?:29|30)\\2))(?:(?:1[6-9]|[2-9]\\d)?\\d{2})$|^(?:0?2(\\/|-|\\.|\\x20)29\\3(?:(?:(?:1[6-9]|[2-9]\\d)?(?:0[48]|[2468][048]|[13579][26])|(?:(?:16|[2468][048]|[3579][26])00))))$|^(?:(?:0?[1-9])|(?:1[0-2]))(\\/|-|\\.|\\x20)(?:0?[1-9]|1\\d|2[0-8])\\4(?:(?:1[6-9]|[2-9]\\d)?\\d{2})$%'; $regex['ymd'] = '%^(?:(?:(?:(?:(?:1[6-9]|[2-9]\\d)?(?:0[48]|[2468][048]|[13579][26])|(?:(?:16|[2468][048]|[3579][26])00)))(\\/|-|\\.|\\x20)(?:0?2\\1(?:29)))|(?:(?:(?:1[6-9]|[2-9]\\d)?\\d{2})(\\/|-|\\.|\\x20)(?:(?:(?:0?[13578]|1[02])\\2(?:31))|(?:(?:0?[1,3-9]|1[0-2])\\2(29|30))|(?:(?:0?[1-9])|(?:1[0-2]))\\2(?:0?[1-9]|1\\d|2[0-8]))))$%'; $regex['dMy'] = '/^((31(?!\\ (Feb(ruary)?|Apr(il)?|June?|(Sep(?=\\b|t)t?|Nov)(ember)?)))|((30|29)(?!\\ Feb(ruary)?))|(29(?=\\ Feb(ruary)?\\ (((1[6-9]|[2-9]\\d)(0[48]|[2468][048]|[13579][26])|((16|[2468][048]|[3579][26])00)))))|(0?[1-9])|1\\d|2[0-8])\\ (Jan(uary)?|Feb(ruary)?|Ma(r(ch)?|y)|Apr(il)?|Ju((ly?)|(ne?))|Aug(ust)?|Oct(ober)?|(Sep(?=\\b|t)t?|Nov|Dec)(ember)?)\\ ((1[6-9]|[2-9]\\d)\\d{2})$/'; - $regex['Mdy'] = '/^(?:(((Jan(uary)?|Ma(r(ch)?|y)|Jul(y)?|Aug(ust)?|Oct(ober)?|Dec(ember)?)\\ 31)|((Jan(uary)?|Ma(r(ch)?|y)|Apr(il)?|Ju((ly?)|(ne?))|Aug(ust)?|Oct(ober)?|(Sept|Nov|Dec)(ember)?)\\ (0?[1-9]|([12]\\d)|30))|(Feb(ruary)?\\ (0?[1-9]|1\\d|2[0-8]|(29(?=,?\\ ((1[6-9]|[2-9]\\d)(0[48]|[2468][048]|[13579][26])|((16|[2468][048]|[3579][26])00)))))))\\,?\\ ((1[6-9]|[2-9]\\d)\\d{2}))$/'; + $regex['Mdy'] = '/^(?:(((Jan(uary)?|Ma(r(ch)?|y)|Jul(y)?|Aug(ust)?|Oct(ober)?|Dec(ember)?)\\ 31)|((Jan(uary)?|Ma(r(ch)?|y)|Apr(il)?|Ju((ly?)|(ne?))|Aug(ust)?|Oct(ober)?|(Sep)(tember)?|(Nov|Dec)(ember)?)\\ (0?[1-9]|([12]\\d)|30))|(Feb(ruary)?\\ (0?[1-9]|1\\d|2[0-8]|(29(?=,?\\ ((1[6-9]|[2-9]\\d)(0[48]|[2468][048]|[13579][26])|((16|[2468][048]|[3579][26])00)))))))\\,?\\ ((1[6-9]|[2-9]\\d)\\d{2}))$/'; $regex['My'] = '%^(Jan(uary)?|Feb(ruary)?|Ma(r(ch)?|y)|Apr(il)?|Ju((ly?)|(ne?))|Aug(ust)?|Oct(ober)?|(Sep(?=\\b|t)t?|Nov|Dec)(ember)?)[ /]((1[6-9]|[2-9]\\d)\\d{2})$%'; $regex['my'] = '%^(((0[123456789]|10|11|12)([- /.])(([1][9][0-9][0-9])|([2][0-9][0-9][0-9]))))$%'; @@ -840,7 +840,7 @@ class Validation extends Object { /** * Checks that a value is a valid uuid - http://tools.ietf.org/html/rfc4122 - * + * * @param string $check Value to check * @return boolean Success * @access public diff --git a/cake/tests/cases/libs/validation.test.php b/cake/tests/cases/libs/validation.test.php index bd3e4e445..0afaf2113 100644 --- a/cake/tests/cases/libs/validation.test.php +++ b/cake/tests/cases/libs/validation.test.php @@ -1447,6 +1447,7 @@ class ValidationTest extends CakeTestCase { $this->assertTrue(Validation::date('Dec 27 2006', array('Mdy'))); $this->assertFalse(Validation::date('27 Dec 2006', array('Mdy'))); $this->assertFalse(Validation::date('2006 December 27', array('Mdy'))); + $this->assertTrue(Validation::date('Sep 12, 2011', array('Mdy'))); } /** From 18acc65fe1fd22b42b999559234abead4c1bd691 Mon Sep 17 00:00:00 2001 From: Mark Story Date: Fri, 19 Aug 2011 12:35:59 -0400 Subject: [PATCH 02/18] Adding Cache disabling to bake tasks and parent bakeshell. Fixes #1889 --- cake/console/libs/bake.php | 2 ++ cake/console/libs/tasks/bake.php | 11 +++++++++++ 2 files changed, 13 insertions(+) diff --git a/cake/console/libs/bake.php b/cake/console/libs/bake.php index 47005bfb9..e326bc54a 100644 --- a/cake/console/libs/bake.php +++ b/cake/console/libs/bake.php @@ -69,6 +69,8 @@ class BakeShell extends Shell { * @access public */ function main() { + Configure::write('Cache.disable', 1); + if (!is_dir($this->DbConfig->path)) { if ($this->Project->execute()) { $this->DbConfig->path = $this->params['working'] . DS . 'config' . DS; diff --git a/cake/console/libs/tasks/bake.php b/cake/console/libs/tasks/bake.php index 424e84cf0..c47deb4fb 100644 --- a/cake/console/libs/tasks/bake.php +++ b/cake/console/libs/tasks/bake.php @@ -42,6 +42,17 @@ class BakeTask extends Shell { */ var $interactive = false; +/** + * Disable caching for baking. + * This forces the most current database schema to be used. + * + * @return void + */ + function startup() { + Configure::write('Cache.disable', 1); + parent::startup(); + } + /** * Gets the path for output. Checks the plugin property * and returns the correct path. From 8dcb7fd9cbbcdb3a4e41afc6aa58f3f41d2ffafa Mon Sep 17 00:00:00 2001 From: Mark Story Date: Fri, 19 Aug 2011 21:08:03 -0400 Subject: [PATCH 03/18] Fixing failing tests. --- cake/tests/cases/console/libs/tasks/fixture.test.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/cake/tests/cases/console/libs/tasks/fixture.test.php b/cake/tests/cases/console/libs/tasks/fixture.test.php index b35b2e945..2364f68d1 100644 --- a/cake/tests/cases/console/libs/tasks/fixture.test.php +++ b/cake/tests/cases/console/libs/tasks/fixture.test.php @@ -141,9 +141,9 @@ class FixtureTaskTest extends CakeTestCase { * @return void */ function testImportOptionsAlternateConnection() { - $this->Task->connection = 'test'; + $this->Task->connection = 'test_suite'; $result = $this->Task->bake('Article', false, array('schema' => 'Article')); - $this->assertPattern("/'connection' => 'test'/", $result); + $this->assertPattern("/'connection' => 'test_suite'/", $result); } /** @@ -351,7 +351,7 @@ class FixtureTaskTest extends CakeTestCase { $this->Task->expectAt(0, 'createFile', array($filename, new PatternExpectation('/Article/'))); $result = $this->Task->generateFixtureFile('Article', array()); - $this->Task->expectAt(1, 'createFile', array($filename, new PatternExpectation('/\<\?php(.*)\?\>/ms'))); + $this->Task->expectAt(1, 'createFile', array($filename, new PatternExpectation('/\<\?php(.*)$/ms'))); $result = $this->Task->generateFixtureFile('Article', array()); } From f9ff4e1e68cd84fad6008210ae4648734fb32320 Mon Sep 17 00:00:00 2001 From: Matt Alexander Date: Sat, 28 May 2011 14:48:31 -0600 Subject: [PATCH 04/18] Add Tibetan locales --- cake/libs/l10n.php | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/cake/libs/l10n.php b/cake/libs/l10n.php index d6d0c6b93..ef3ed133c 100644 --- a/cake/libs/l10n.php +++ b/cake/libs/l10n.php @@ -103,6 +103,7 @@ class L10n extends Object { /* Arabic */ 'ara' => 'ar', /* Armenian - Armenia */ 'hye' => 'hy', /* Basque */ 'baq' => 'eu', + /* Tibetan */ 'bod' => 'bo', /* Bosnian */ 'bos' => 'bs', /* Bulgarian */ 'bul' => 'bg', /* Byelorussian */ 'bel' => 'be', @@ -205,6 +206,9 @@ class L10n extends Object { 'ar-ye' => array('language' => 'Arabic (Yemen)', 'locale' => 'ar_ye', 'localeFallback' => 'ara', 'charset' => 'utf-8', 'direction' => 'rtl'), 'be' => array('language' => 'Byelorussian', 'locale' => 'bel', 'localeFallback' => 'bel', 'charset' => 'utf-8', 'direction' => 'ltr'), 'bg' => array('language' => 'Bulgarian', 'locale' => 'bul', 'localeFallback' => 'bul', 'charset' => 'utf-8', 'direction' => 'ltr'), + 'bo' => array('language' => 'Tibetan', 'locale' => 'bod', 'localeFallback' => 'bod', 'charset' => 'utf-8', 'direction' => 'ltr'), + 'bo-cn' => array('language' => 'Tibetan (China)', 'locale' => 'bo_cn', 'localeFallback' => 'bod', 'charset' => 'utf-8', 'direction' => 'ltr'), + 'bo-in' => array('language' => 'Tibetan (India)', 'locale' => 'bo_in', 'localeFallback' => 'bod', 'charset' => 'utf-8', 'direction' => 'ltr'), 'bs' => array('language' => 'Bosnian', 'locale' => 'bos', 'localeFallback' => 'bos', 'charset' => 'utf-8', 'direction' => 'ltr'), 'ca' => array('language' => 'Catalan', 'locale' => 'cat', 'localeFallback' => 'cat', 'charset' => 'utf-8', 'direction' => 'ltr'), 'cs' => array('language' => 'Czech', 'locale' => 'cze', 'localeFallback' => 'cze', 'charset' => 'utf-8', 'direction' => 'ltr'), From 9daa969783e26d2d478d20c193a70384a303454e Mon Sep 17 00:00:00 2001 From: Mark Story Date: Sat, 20 Aug 2011 20:08:45 -0400 Subject: [PATCH 05/18] Switching FixtureTask to use var_export() instead of custom escaping code. Fixes issues with quotes in text. Fixes #1922 --- cake/console/libs/tasks/fixture.php | 22 ++++++++----------- .../cases/console/libs/tasks/fixture.test.php | 22 +++++++++++++++++++ 2 files changed, 31 insertions(+), 13 deletions(-) diff --git a/cake/console/libs/tasks/fixture.php b/cake/console/libs/tasks/fixture.php index 7c4508cbf..d4285f4b3 100644 --- a/cake/console/libs/tasks/fixture.php +++ b/cake/console/libs/tasks/fixture.php @@ -296,35 +296,30 @@ class FixtureTask extends BakeTask { $insert = substr($insert, 0, (int)$fieldInfo['length'] - 2); } } - $insert = "'$insert'"; break; case 'timestamp': - $ts = time(); - $insert = "'$ts'"; + $insert = time(); break; case 'datetime': - $ts = date('Y-m-d H:i:s'); - $insert = "'$ts'"; + $insert = date('Y-m-d H:i:s'); break; case 'date': - $ts = date('Y-m-d'); - $insert = "'$ts'"; + $insert = date('Y-m-d'); break; case 'time': - $ts = date('H:i:s'); - $insert = "'$ts'"; + $insert = date('H:i:s'); break; case 'boolean': $insert = 1; break; case 'text': - $insert = "'Lorem ipsum dolor sit amet, aliquet feugiat."; + $insert = "Lorem ipsum dolor sit amet, aliquet feugiat."; $insert .= " Convallis morbi fringilla gravida,"; $insert .= " phasellus feugiat dapibus velit nunc, pulvinar eget sollicitudin"; $insert .= " venenatis cum nullam, vivamus ut a sed, mollitia lectus. Nulla"; $insert .= " vestibulum massa neque ut et, id hendrerit sit,"; $insert .= " feugiat in taciti enim proin nibh, tempor dignissim, rhoncus"; - $insert .= " duis vestibulum nunc mattis convallis.'"; + $insert .= " duis vestibulum nunc mattis convallis."; break; } $record[$field] = $insert; @@ -346,7 +341,8 @@ class FixtureTask extends BakeTask { foreach ($records as $record) { $values = array(); foreach ($record as $field => $value) { - $values[] = "\t\t\t'$field' => $value"; + $val = var_export($value, true); + $values[] = "\t\t\t'$field' => $val"; } $out .= "\t\tarray(\n"; $out .= implode(",\n", $values); @@ -387,7 +383,7 @@ class FixtureTask extends BakeTask { foreach ($records as $record) { $row = array(); foreach ($record[$modelObject->alias] as $field => $value) { - $row[$field] = $db->value($value, $schema[$field]['type']); + $row[$field] = $value; } $out[] = $row; } diff --git a/cake/tests/cases/console/libs/tasks/fixture.test.php b/cake/tests/cases/console/libs/tasks/fixture.test.php index 2364f68d1..553d97b73 100644 --- a/cake/tests/cases/console/libs/tasks/fixture.test.php +++ b/cake/tests/cases/console/libs/tasks/fixture.test.php @@ -167,6 +167,28 @@ class FixtureTaskTest extends CakeTestCase { $this->assertPattern('/Third Article/', $result, 'Missing import data %s'); } +/** + * Ensure that fixture data doesn't get overly escaped. + * + * @return void + */ + function testImportRecordsNoEscaping() { + $Article = ClassRegistry::init('Article'); + $Article->updateAll(array('body' => "'Body \"value\"'")); + + $this->Task->interactive = true; + $this->Task->setReturnValueAt(0, 'in', 'WHERE 1=1 LIMIT 10'); + $this->Task->connection = 'test_suite'; + $this->Task->path = '/my/path/'; + $result = $this->Task->bake('Article', false, array( + 'fromTable' => true, + 'schema' => 'Article', + 'records' => false + )); + + $this->assertPattern("/'body' => 'Body \"value\"'/", $result, 'Data has escaping %s'); + } + /** * test that execute passes runs bake depending with named model. * From ec79a09d27c340960cef3d6e5363b031d9da8874 Mon Sep 17 00:00:00 2001 From: mark_story Date: Thu, 25 Aug 2011 22:12:33 -0400 Subject: [PATCH 06/18] Removing PHP5.2.6 only mode value, and replacing it with PHP4 & 5 compatible mode. --- cake/libs/cache/file.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cake/libs/cache/file.php b/cake/libs/cache/file.php index c7d07d912..087ba0aa1 100644 --- a/cake/libs/cache/file.php +++ b/cake/libs/cache/file.php @@ -139,7 +139,7 @@ class FileEngine extends CacheEngine { $expires = time() + $duration; $contents = $expires . $lineBreak . $data . $lineBreak; - if (!$handle = fopen($this->_File->path, 'c')) { + if (!$handle = fopen($this->_File->path, 'a')) { return false; } From 72ef310867c208a80a414114eba56befe3511055 Mon Sep 17 00:00:00 2001 From: mark_story Date: Thu, 25 Aug 2011 22:31:25 -0400 Subject: [PATCH 07/18] Fixing Accept header parsing so content types with leading/trailing spaces are treated as spaceless. Fixes #1684 --- cake/libs/controller/components/request_handler.php | 1 + .../libs/controller/components/request_handler.test.php | 5 ++++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/cake/libs/controller/components/request_handler.php b/cake/libs/controller/components/request_handler.php index af708d394..a5682932d 100644 --- a/cake/libs/controller/components/request_handler.php +++ b/cake/libs/controller/components/request_handler.php @@ -176,6 +176,7 @@ class RequestHandlerComponent extends Object { */ function __construct() { $this->__acceptTypes = explode(',', env('HTTP_ACCEPT')); + $this->__acceptTypes = array_map('trim', $this->__acceptTypes); foreach ($this->__acceptTypes as $i => $type) { if (strpos($type, ';')) { diff --git a/cake/tests/cases/libs/controller/components/request_handler.test.php b/cake/tests/cases/libs/controller/components/request_handler.test.php index ce8d7a228..a8632c8d8 100644 --- a/cake/tests/cases/libs/controller/components/request_handler.test.php +++ b/cake/tests/cases/libs/controller/components/request_handler.test.php @@ -469,7 +469,10 @@ class RequestHandlerComponentTest extends CakeTestCase { $this->_init(); $this->assertTrue($this->RequestHandler->isWap()); - $_SERVER['HTTP_ACCEPT'] = 'application/rss+xml,text/xml,application/xml,application/xhtml+xml,text/html,text/plain,image/png,*/*'; + $_SERVER['HTTP_ACCEPT'] = 'application/rss+xml , text/xml, application/xml,application/xhtml+xml'; + $this->_init(); + $this->assertFalse($this->RequestHandler->isAtom()); + $this->assertTrue($this->RequestHandler->isRSS()); } /** From aee650defb22b769aff1bfe5d2e90e59d28f1c3f Mon Sep 17 00:00:00 2001 From: mark_story Date: Thu, 25 Aug 2011 22:33:21 -0400 Subject: [PATCH 08/18] Adding a test and fixing issues where q value had whitespace as well. Refs #1684 --- cake/libs/controller/components/request_handler.php | 2 +- .../cases/libs/controller/components/request_handler.test.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/cake/libs/controller/components/request_handler.php b/cake/libs/controller/components/request_handler.php index a5682932d..32cf6391d 100644 --- a/cake/libs/controller/components/request_handler.php +++ b/cake/libs/controller/components/request_handler.php @@ -181,7 +181,7 @@ class RequestHandlerComponent extends Object { foreach ($this->__acceptTypes as $i => $type) { if (strpos($type, ';')) { $type = explode(';', $type); - $this->__acceptTypes[$i] = $type[0]; + $this->__acceptTypes[$i] = trim($type[0]); } } parent::__construct(); diff --git a/cake/tests/cases/libs/controller/components/request_handler.test.php b/cake/tests/cases/libs/controller/components/request_handler.test.php index a8632c8d8..4b01f7b11 100644 --- a/cake/tests/cases/libs/controller/components/request_handler.test.php +++ b/cake/tests/cases/libs/controller/components/request_handler.test.php @@ -469,7 +469,7 @@ class RequestHandlerComponentTest extends CakeTestCase { $this->_init(); $this->assertTrue($this->RequestHandler->isWap()); - $_SERVER['HTTP_ACCEPT'] = 'application/rss+xml , text/xml, application/xml,application/xhtml+xml'; + $_SERVER['HTTP_ACCEPT'] = 'application/rss+xml ;q=0.9 , text/xml, application/xml,application/xhtml+xml'; $this->_init(); $this->assertFalse($this->RequestHandler->isAtom()); $this->assertTrue($this->RequestHandler->isRSS()); From fdc006a2e3a0686f4050b5bed7cbaf096e77e1f3 Mon Sep 17 00:00:00 2001 From: mark_story Date: Sat, 27 Aug 2011 10:14:24 -0400 Subject: [PATCH 09/18] Fixing how error handlers are registered when debug levels are toggled mid request. Previously Debugger would stay as the active error handler even after changing debug to 0. Now, either CakeLog or Debugger will be assigned as the error handler depending on the debug level. Fixes #1941 --- cake/libs/configure.php | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/cake/libs/configure.php b/cake/libs/configure.php index 0f310cc51..82df61f04 100644 --- a/cake/libs/configure.php +++ b/cake/libs/configure.php @@ -118,6 +118,7 @@ class Configure extends Object { if (function_exists('ini_set')) { ini_set('display_errors', 1); } + $callback = array('Debugger', 'getInstance'); } elseif (function_exists('ini_set')) { ini_set('display_errors', 0); } @@ -132,6 +133,12 @@ class Configure extends Object { if (!class_exists('CakeLog')) { require LIBS . 'cake_log.php'; } + if (empty($callback)) { + $callback = array('CakeLog', 'getInstance'); + } + } + if (!empty($callback) && class_exists('Debugger')) { + Debugger::invoke(call_user_func($callback)); } error_reporting($reporting); } From 7656feb0bb264d5f082fb7c57cedefd903ccaaeb Mon Sep 17 00:00:00 2001 From: mark_story Date: Fri, 26 Aug 2011 22:10:29 -0400 Subject: [PATCH 10/18] Converting internals of Folder::read() to use DirectoryIterator. --- lib/Cake/Utility/Folder.php | 26 +++++++++++++++----------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/lib/Cake/Utility/Folder.php b/lib/Cake/Utility/Folder.php index 44af50df2..1d8c8db13 100644 --- a/lib/Cake/Utility/Folder.php +++ b/lib/Cake/Utility/Folder.php @@ -145,29 +145,33 @@ class Folder { } $skipHidden = isset($exceptions['.']) || $exceptions === true; - if (false === ($dir = @opendir($this->path))) { + try { + $iterator = new DirectoryIterator($this->path); + } catch (UnexpectedValueException $e) { return array($dirs, $files); } - while (false !== ($item = readdir($dir))) { - if ($item === '.' || $item === '..' || ($skipHidden && $item[0] === '.') || isset($exceptions[$item])) { + foreach ($iterator as $item) { + if ($item->isDot()) { continue; } - - $path = Folder::addPathElement($this->path, $item); - if (is_dir($path)) { - $dirs[] = $fullPath ? $path : $item; + $name = $item->getFileName(); + if ($skipHidden && $name[0] === '.' || isset($exceptions[$name])) { + continue; + } + if ($fullPath) { + $name = $item->getPathName(); + } + if ($item->isDir()) { + $dirs[] = $name; } else { - $files[] = $fullPath ? $path : $item; + $files[] = $name; } } - if ($sort || $this->sort) { sort($dirs); sort($files); } - - closedir($dir); return array($dirs, $files); } From 682dc5e24b5e4f9ff9b9a526eaf84535372353e5 Mon Sep 17 00:00:00 2001 From: mark_story Date: Fri, 26 Aug 2011 22:38:34 -0400 Subject: [PATCH 11/18] Make Folder::tree use SPL Iterators. --- lib/Cake/Utility/Folder.php | 37 +++++++++++++++++++++++++------------ 1 file changed, 25 insertions(+), 12 deletions(-) diff --git a/lib/Cake/Utility/Folder.php b/lib/Cake/Utility/Folder.php index 1d8c8db13..9614a66da 100644 --- a/lib/Cake/Utility/Folder.php +++ b/lib/Cake/Utility/Folder.php @@ -393,28 +393,41 @@ class Folder { } return array(); } - $this->_files = array(); - $this->_directories = array($this->realpath($path)); - $directories = array(); + $files = array(); + $directories = array($path); + $skipHidden = false; if ($exceptions === false) { - $exceptions = true; + $skipHidden = true; } - while (!empty($this->_directories)) { - $dir = array_pop($this->_directories); - $this->_tree($dir, $exceptions); - $directories[] = $dir; + if (is_array($exceptions)) { + $exceptions = array_flip($exceptions); } + try { + $directory = new RecursiveDirectoryIterator($path); + $iterator = new RecursiveIteratorIterator($directory, RecursiveIteratorIterator::SELF_FIRST); + } catch (UnexpectedValueException $e) { + return array(); + } + foreach ($iterator as $item) { + $name = $item->getFileName(); + if ($skipHidden && $name[0] === '.' || isset($exceptions[$name])) { + continue; + } + if ($item->isFile()) { + $files[] = $item->getPathName(); + } else if ($item->isDir()) { + $directories[] = $item->getPathName(); + } + } if ($type === null) { - return array($directories, $this->_files); + return array($directories, $files); } if ($type === 'dir') { return $directories; } - $this->cd($original); - - return $this->_files; + return $files; } /** From 02a6883b22d198960fad8fd7584b3a38c579f6a1 Mon Sep 17 00:00:00 2001 From: mark_story Date: Sat, 27 Aug 2011 10:34:08 -0400 Subject: [PATCH 12/18] Using Folder class in CakeTestSuite, this fixes issues where hidden directories from VCS would be added as test cases. Fixes #1933 --- lib/Cake/Test/Case/AllComponentsTest.php | 3 +-- lib/Cake/TestSuite/CakeTestSuite.php | 18 +++++++----------- lib/Cake/Utility/Folder.php | 14 ++++++-------- 3 files changed, 14 insertions(+), 21 deletions(-) diff --git a/lib/Cake/Test/Case/AllComponentsTest.php b/lib/Cake/Test/Case/AllComponentsTest.php index f93628417..3b6f5ce03 100644 --- a/lib/Cake/Test/Case/AllComponentsTest.php +++ b/lib/Cake/Test/Case/AllComponentsTest.php @@ -36,8 +36,7 @@ class AllComponentsTest extends PHPUnit_Framework_TestSuite { $suite->addTestFile(CORE_TEST_CASES . DS . 'Controller' . DS . 'ComponentTest.php'); $suite->addTestFile(CORE_TEST_CASES . DS . 'Controller' . DS . 'ComponentCollectionTest.php'); - $suite->addTestDirectory(CORE_TEST_CASES . DS . 'Controller' . DS . 'Component'); - $suite->addTestDirectory(CORE_TEST_CASES . DS . 'Controller' . DS . 'Component' . DS . 'Auth'); + $suite->addTestDirectoryRecursive(CORE_TEST_CASES . DS . 'Controller' . DS . 'Component'); return $suite; } } diff --git a/lib/Cake/TestSuite/CakeTestSuite.php b/lib/Cake/TestSuite/CakeTestSuite.php index 1b121b65c..ea8656155 100644 --- a/lib/Cake/TestSuite/CakeTestSuite.php +++ b/lib/Cake/TestSuite/CakeTestSuite.php @@ -18,6 +18,8 @@ */ PHP_CodeCoverage_Filter::getInstance()->addFileToBlacklist(__FILE__, 'DEFAULT'); +App::uses('Folder', 'Utility'); + class CakeTestSuite extends PHPUnit_Framework_TestSuite { /** @@ -27,13 +29,10 @@ class CakeTestSuite extends PHPUnit_Framework_TestSuite { * @return void */ public function addTestDirectory($directory = '.') { - $files = new DirectoryIterator($directory); + $folder = new Folder($directory); + list($dirs, $files) = $folder->read(true, false, true); foreach ($files as $file) { - if (!$file->isFile()) { - continue; - } - $file = $file->getRealPath(); $this->addTestFile($file); } } @@ -45,15 +44,12 @@ class CakeTestSuite extends PHPUnit_Framework_TestSuite { * @return void */ public function addTestDirectoryRecursive($directory = '.') { - $files = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($directory)); + $folder = new Folder($directory); + $files = $folder->tree(null, false, 'files'); foreach ($files as $file) { - if (!$file->isFile()) { - continue; - } - $file = $file->getRealPath(); $this->addTestFile($file); } } -} \ No newline at end of file +} diff --git a/lib/Cake/Utility/Folder.php b/lib/Cake/Utility/Folder.php index 9614a66da..671ff1e2b 100644 --- a/lib/Cake/Utility/Folder.php +++ b/lib/Cake/Utility/Folder.php @@ -384,14 +384,9 @@ class Folder { * @param string $type either file or dir. null returns both files and directories * @return mixed array of nested directories and files in each directory */ - public function tree($path, $exceptions = true, $type = null) { - $original = $this->path; - $path = rtrim($path, DS); - if (!$this->cd($path)) { - if ($type === null) { - return array(array(), array()); - } - return array(); + public function tree($path = null, $exceptions = true, $type = null) { + if ($path == null) { + $path = $this->path; } $files = array(); $directories = array($path); @@ -408,6 +403,9 @@ class Folder { $directory = new RecursiveDirectoryIterator($path); $iterator = new RecursiveIteratorIterator($directory, RecursiveIteratorIterator::SELF_FIRST); } catch (UnexpectedValueException $e) { + if ($type === null) { + return array(array(), array()); + } return array(); } foreach ($iterator as $item) { From 5df12a287e47122aff5fe1ae282c9e1b043354d8 Mon Sep 17 00:00:00 2001 From: mark_story Date: Sat, 27 Aug 2011 10:36:11 -0400 Subject: [PATCH 13/18] Fixing failing tests caused by moving params[ext]. --- .../Controller/Component/RequestHandlerComponentTest.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/Cake/Test/Case/Controller/Component/RequestHandlerComponentTest.php b/lib/Cake/Test/Case/Controller/Component/RequestHandlerComponentTest.php index efe979545..2d2817e0b 100644 --- a/lib/Cake/Test/Case/Controller/Component/RequestHandlerComponentTest.php +++ b/lib/Cake/Test/Case/Controller/Component/RequestHandlerComponentTest.php @@ -157,7 +157,7 @@ class RequestHandlerComponentTest extends CakeTestCase { */ public function testInitializeCallback() { $this->assertNull($this->RequestHandler->ext); - $this->Controller->request->params['url']['ext'] = 'rss'; + $this->Controller->request->params['ext'] = 'rss'; $this->RequestHandler->initialize($this->Controller); $this->assertEqual($this->RequestHandler->ext, 'rss'); } @@ -222,7 +222,7 @@ class RequestHandlerComponentTest extends CakeTestCase { */ public function testAutoResponseType() { $this->Controller->ext = '.thtml'; - $this->Controller->request->params['url']['ext'] = 'rss'; + $this->Controller->request->params['ext'] = 'rss'; $this->RequestHandler->initialize($this->Controller); $this->RequestHandler->startup($this->Controller); $this->assertEqual($this->Controller->ext, '.ctp'); @@ -240,7 +240,7 @@ class RequestHandlerComponentTest extends CakeTestCase { $this->assertEquals($this->Controller->layout, $this->RequestHandler->ajaxLayout); $this->_init(); - $this->Controller->request->params['url']['ext'] = 'js'; + $this->Controller->request->params['ext'] = 'js'; $this->RequestHandler->initialize($this->Controller); $this->RequestHandler->startup($this->Controller); $this->assertNotEqual($this->Controller->layout, 'ajax'); From 1a872e6544d382f691365b91e1740c7be9f3129e Mon Sep 17 00:00:00 2001 From: mark_story Date: Sat, 27 Aug 2011 11:39:22 -0400 Subject: [PATCH 14/18] Fixing CakeRequest::accepts() where ;q values on Accept header were not respected. Fixes #1940 --- lib/Cake/Network/CakeRequest.php | 28 +++++++++++++------ .../Test/Case/Network/CakeRequestTest.php | 15 +++++++++- 2 files changed, 34 insertions(+), 9 deletions(-) diff --git a/lib/Cake/Network/CakeRequest.php b/lib/Cake/Network/CakeRequest.php index afad26b57..213d84bef 100644 --- a/lib/Cake/Network/CakeRequest.php +++ b/lib/Cake/Network/CakeRequest.php @@ -605,23 +605,35 @@ class CakeRequest implements ArrayAccess { * * `$this->request->accepts('json');` * + * This method will order the returned content types by the preference values indicated + * by the client. + * * @param string $type The content type to check for. Leave null to get all types a client accepts. * @return mixed Either an array of all the types the client accepts or a boolean if they accept the * provided type. */ public function accepts($type = null) { - $acceptTypes = explode(',', $this->header('accept')); - $acceptTypes = array_map('trim', $acceptTypes); - foreach ($acceptTypes as $i => $accepted) { - if (strpos($accepted, ';') !== false) { - list($accepted) = explode(';', $accepted); - $acceptTypes[$i] = $accepted; + $accept = array(); + $header = explode(',', $this->header('accept')); + foreach (array_filter(array_reverse($header)) as $value) { + $prefPos = strpos($value, ';'); + if ($prefPos !== false) { + $prefValue = (float) substr($value, strpos($value, '=') + 1); + $value = trim(substr($value, 0, $prefPos)); + } else { + $prefValue = 1.0; + $value = trim($value); + } + if ($prefValue) { + $accept[$value] = $prefValue; } } + arsort($accept); + $accept = array_keys($accept); if ($type === null) { - return $acceptTypes; + return $accept; } - return in_array($type, $acceptTypes); + return in_array($type, $accept); } /** diff --git a/lib/Cake/Test/Case/Network/CakeRequestTest.php b/lib/Cake/Test/Case/Network/CakeRequestTest.php index 16211dee0..f89ef7625 100644 --- a/lib/Cake/Test/Case/Network/CakeRequestTest.php +++ b/lib/Cake/Test/Case/Network/CakeRequestTest.php @@ -785,7 +785,7 @@ class CakeRequestTestCase extends CakeTestCase { $result = $request->accepts(); $expected = array( - 'text/xml', 'application/xml', 'application/xhtml+xml', 'text/html', 'text/plain', 'image/png' + 'text/xml', 'application/xhtml+xml', 'text/html', 'image/png', 'text/plain', 'application/xml' ); $this->assertEquals($expected, $result, 'Content types differ.'); @@ -813,6 +813,19 @@ class CakeRequestTestCase extends CakeTestCase { $this->assertTrue($request->accepts('text/html')); } +/** + * Content types from accepts() should respect the client's q preference values. + * + * @return void + */ + public function testAcceptWithQvalueSorting() { + $_SERVER['HTTP_ACCEPT'] = 'text/html;q=0.8,application/json;q=0.7,application/xml;q=1.0'; + $request = new CakeRequest('/', false); + $result = $request->accepts(); + $expected = array('application/xml', 'text/html', 'application/json'); + $this->assertEquals($expected, $result); + } + /** * testBaseUrlAndWebrootWithModRewrite method * From 4a7bd031e5b637fe0049ae9b569c284849f67c2f Mon Sep 17 00:00:00 2001 From: mark_story Date: Sat, 27 Aug 2011 11:52:29 -0400 Subject: [PATCH 15/18] Adding a file_exists() check before unlinking cache files. This prevents issues where two concurrent requests could be clearing the same cache files. Fixes #1936 --- lib/Cake/Cache/Engine/FileEngine.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/Cake/Cache/Engine/FileEngine.php b/lib/Cake/Cache/Engine/FileEngine.php index c8eafbd0b..f81889dcb 100644 --- a/lib/Cake/Cache/Engine/FileEngine.php +++ b/lib/Cake/Cache/Engine/FileEngine.php @@ -240,7 +240,9 @@ class FileEngine extends CacheEngine { } $path = $this->_File->getRealPath(); $this->_File = null; - unlink($path); + if (file_exists($path)) { + unlink($path); + } } $dir->close(); return true; From 27ab9093b5be7ca16192982d4f6640130d963421 Mon Sep 17 00:00:00 2001 From: mark_story Date: Sun, 28 Aug 2011 14:18:09 -0400 Subject: [PATCH 16/18] Removing getTests() and fixing failing test in accidentaly skipped tests. --- cake/tests/cases/libs/controller/scaffold.test.php | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/cake/tests/cases/libs/controller/scaffold.test.php b/cake/tests/cases/libs/controller/scaffold.test.php index a7de6c1df..b3766c306 100644 --- a/cake/tests/cases/libs/controller/scaffold.test.php +++ b/cake/tests/cases/libs/controller/scaffold.test.php @@ -509,7 +509,7 @@ class ScaffoldViewTest extends CakeTestCase { new Scaffold($this->Controller, $params); $result = ob_get_clean(); - $this->assertPattern('/
assertPattern('/assertPattern('/Edit Scaffold Mock<\/legend>/', $result); $this->assertPattern('/input type="hidden" name="data\[ScaffoldMock\]\[id\]" value="1" id="ScaffoldMockId"/', $result); @@ -770,9 +770,6 @@ class ScaffoldTest extends CakeTestCase { $this->assertEqual($result['pluralVar'], 'scaffoldMock'); $this->assertEqual($result['scaffoldFields'], array('id', 'user_id', 'title', 'body', 'published', 'created', 'updated')); } - function getTests() { - return array('start', 'startCase', 'testScaffoldChangingViewProperty', 'endCase', 'end'); - } /** * test that Scaffold overrides the view property even if its set to 'Theme' From 9ff922cbc7274cf5d4dddf73dbccb8e954cc31f9 Mon Sep 17 00:00:00 2001 From: mark_story Date: Sun, 28 Aug 2011 15:36:19 -0400 Subject: [PATCH 17/18] App::objects() should skip directories and files starting with `.`. These generally contain version control or OS metadata, and not code CakePHP can use. Fixes #1933 --- lib/Cake/Core/App.php | 10 +++++++--- lib/Cake/Test/Case/Core/AppTest.php | 15 +++++++++++++++ 2 files changed, 22 insertions(+), 3 deletions(-) diff --git a/lib/Cake/Core/App.php b/lib/Cake/Core/App.php index 1e92aa76c..d36ff7966 100644 --- a/lib/Cake/Core/App.php +++ b/lib/Cake/Core/App.php @@ -427,6 +427,9 @@ class App { * * `App::objects('MyPlugin.Model');` returns `array('MyPluginPost', 'MyPluginComment');` * + * When scanning directories, files and directories beginning with `.` will be excluded as these + * are commonly used by version control systems. + * * @param string $type Type of object, i.e. 'Model', 'Controller', 'View/Helper', 'file', 'class' or 'plugin' * @param mixed $path Optional Scan only the path given. If null, paths for the chosen type will be used. * @param boolean $cache Set to false to rescan objects of the chosen type. Defaults to true. @@ -476,12 +479,13 @@ class App { if ($dir != APP && is_dir($dir)) { $files = new RegexIterator(new DirectoryIterator($dir), $extension); foreach ($files as $file) { - if (!$file->isDot()) { + $fileName = basename($file); + if (!$file->isDot() && $fileName[0] !== '.') { $isDir = $file->isDir() ; if ($isDir && $includeDirectories) { - $objects[] = basename($file); + $objects[] = $fileName; } elseif (!$includeDirectories && !$isDir) { - $objects[] = substr(basename($file), 0, -4); + $objects[] = substr($fileName, 0, -4); } } } diff --git a/lib/Cake/Test/Case/Core/AppTest.php b/lib/Cake/Test/Case/Core/AppTest.php index 9f51fd1a1..945a76062 100644 --- a/lib/Cake/Test/Case/Core/AppTest.php +++ b/lib/Cake/Test/Case/Core/AppTest.php @@ -305,6 +305,21 @@ class AppTest extends CakeTestCase { App::build(); } +/** + * Make sure that .svn and friends are excluded from App::objects('plugin') + */ + public function testListObjectsIgnoreDotDirectories() { + $path = CAKE . 'Test' . DS . 'test_app' . DS . 'Plugin' . DS; + App::build(array( + 'plugins' => array($path) + ), true); + mkdir($path . '.svn'); + $result = App::objects('plugin', null, false); + rmdir($path . '.svn'); + + $this->assertNotContains('.svn', $result); + } + /** * Tests listing objects within a plugin * From 5b43d6b9a7534f7bc3280fdb3ee9b1c6f826ea2a Mon Sep 17 00:00:00 2001 From: mark_story Date: Sun, 28 Aug 2011 21:45:16 -0400 Subject: [PATCH 18/18] Adding cafe to the list of irregular plurals. Seems that its french origins befuddle normal english pluralization rules. Fixes #1930 --- cake/libs/inflector.php | 1 + cake/tests/cases/libs/inflector.test.php | 4 ++++ 2 files changed, 5 insertions(+) diff --git a/cake/libs/inflector.php b/cake/libs/inflector.php index 37d4ab330..7f3e02f38 100644 --- a/cake/libs/inflector.php +++ b/cake/libs/inflector.php @@ -70,6 +70,7 @@ class Inflector { 'atlas' => 'atlases', 'beef' => 'beefs', 'brother' => 'brothers', + 'cafe' => 'cafes', 'child' => 'children', 'corpus' => 'corpuses', 'cow' => 'cows', diff --git a/cake/tests/cases/libs/inflector.test.php b/cake/tests/cases/libs/inflector.test.php index 39e61cf99..6f0562b3c 100644 --- a/cake/tests/cases/libs/inflector.test.php +++ b/cake/tests/cases/libs/inflector.test.php @@ -116,6 +116,8 @@ class InflectorTest extends CakeTestCase { $this->assertEqual(Inflector::singularize('bases'), 'basis'); $this->assertEqual(Inflector::singularize('analyses'), 'analysis'); $this->assertEqual(Inflector::singularize('curves'), 'curve'); + $this->assertEqual(Inflector::singularize('cafes'), 'cafe'); + $this->assertEqual(Inflector::singularize('roofs'), 'roof'); $this->assertEqual(Inflector::singularize(''), ''); } @@ -164,6 +166,8 @@ class InflectorTest extends CakeTestCase { $this->assertEqual(Inflector::pluralize('tax'), 'taxes'); $this->assertEqual(Inflector::pluralize('wave'), 'waves'); $this->assertEqual(Inflector::pluralize('bureau'), 'bureaus'); + $this->assertEqual(Inflector::pluralize('cafe'), 'cafes'); + $this->assertEqual(Inflector::pluralize('roof'), 'roofs'); $this->assertEqual(Inflector::pluralize(''), ''); }