From 2abf34d93e26894436bf1b198e74936d47e7a541 Mon Sep 17 00:00:00 2001 From: mark_story Date: Mon, 16 Aug 2010 22:11:25 -0400 Subject: [PATCH 001/166] Fixing issue where an app that was in a directory that had the same name as a controller would end up failing to find view cache files. Adding test for app name in controller name failure to create cache Fixes #1025 Conflicts: cake/libs/view/helpers/cache.php --- .../cases/libs/view/helpers/cache.test.php | 37 +++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/cake/tests/cases/libs/view/helpers/cache.test.php b/cake/tests/cases/libs/view/helpers/cache.test.php index 23e47f936..3a42ec0fa 100644 --- a/cake/tests/cases/libs/view/helpers/cache.test.php +++ b/cake/tests/cases/libs/view/helpers/cache.test.php @@ -451,6 +451,43 @@ class CacheHelperTest extends CakeTestCase { $this->assertTrue(file_exists($filename)); @unlink($filename); } + +/** + * test ControllerName contains AppName + * + * This test verifys view cache is created correctly when the app name is contained in part of the controller name. + * (webapp Name) base name is 'cache' controller is 'cacheTest' action is 'cache_name' + * apps url would look somehing like http://localhost/cache/cacheTest/cache_name + * + * @return void + **/ + function testCacheBaseNameControllerName() { + $this->Controller->cache_parsing(); + $this->Controller->cacheAction = array( + 'cache_name' => 21600 + ); + $this->Controller->params = array( + 'controller' => 'cacheTest', + 'action' => 'cache_name', + 'url' => array(), + 'pass' => array(), + 'named' => array() + ); + $this->Controller->here = '/cache/cacheTest/cache_name'; + $this->Controller->action = 'cache_name'; + $this->Controller->base = '/cache'; + + $View = new View($this->Controller); + $result = $View->render('index'); + + $this->assertNoPattern('/cake:nocache/', $result); + $this->assertNoPattern('/php echo/', $result); + + $filename = CACHE . 'views' . DS . 'cache_cachetest_cache_name.php'; + $this->assertTrue(file_exists($filename)); + @unlink($filename); + } + /** * testCacheEmptySections method * From fc9340213e2907fe22625dbe9e356ecb5745866d Mon Sep 17 00:00:00 2001 From: mark_story Date: Mon, 16 Aug 2010 22:25:55 -0400 Subject: [PATCH 002/166] Applying patch from 'thatcode', makes the 'us' rule case insensitive. Fixes #1020 --- cake/libs/inflector.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cake/libs/inflector.php b/cake/libs/inflector.php index 9cae3a1d2..65563639f 100644 --- a/cake/libs/inflector.php +++ b/cake/libs/inflector.php @@ -56,7 +56,7 @@ class Inflector { '/(c)hild$/i' => '\1hildren', '/(buffal|tomat)o$/i' => '\1\2oes', '/(alumn|bacill|cact|foc|fung|nucle|radi|stimul|syllab|termin|vir)us$/i' => '\1i', - '/us$/' => 'uses', + '/us$/i' => 'uses', '/(alias)$/i' => '\1es', '/(ax|cris|test)is$/i' => '\1es', '/s$/' => 's', From b22f2f746bc3b38fa46e6d1ca68116baacc119e6 Mon Sep 17 00:00:00 2001 From: zimakm Date: Wed, 18 Aug 2010 03:27:08 -0700 Subject: [PATCH 003/166] Configure fix problem 3-dimensional arrays to be handled as 4+ arrays. This saves a lot of execution time when configure holds many values. Fixes #1028 Signed-off-by: mark_story --- cake/libs/configure.php | 1 + 1 file changed, 1 insertion(+) diff --git a/cake/libs/configure.php b/cake/libs/configure.php index fc2f4eeda..79dff7bd0 100644 --- a/cake/libs/configure.php +++ b/cake/libs/configure.php @@ -96,6 +96,7 @@ class Configure extends Object { break; case 3: $_this->{$names[0]}[$names[1]][$names[2]] = $value; + break; case 4: $names = explode('.', $name, 2); if (!isset($_this->{$names[0]})) { From e23fe25787cfc53d6d8d5aa28d6c0af4873bf797 Mon Sep 17 00:00:00 2001 From: mark_story Date: Sat, 21 Aug 2010 00:17:40 -0400 Subject: [PATCH 004/166] Fixing code formatting. --- cake/libs/configure.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cake/libs/configure.php b/cake/libs/configure.php index 79dff7bd0..1428ba896 100644 --- a/cake/libs/configure.php +++ b/cake/libs/configure.php @@ -96,7 +96,7 @@ class Configure extends Object { break; case 3: $_this->{$names[0]}[$names[1]][$names[2]] = $value; - break; + break; case 4: $names = explode('.', $name, 2); if (!isset($_this->{$names[0]})) { From afc05c1e050869b20e85be87ac3d378c146b9a52 Mon Sep 17 00:00:00 2001 From: mark_story Date: Sat, 21 Aug 2010 00:19:30 -0400 Subject: [PATCH 005/166] Adding test cases for using localized floats with mysql. Also added a generic model test case. Refs #1029 --- .../model/datasources/dbo/dbo_mysql.test.php | 18 ++++++++++++++++++ .../cases/libs/model/model_write.test.php | 18 ++++++++++++++++++ 2 files changed, 36 insertions(+) diff --git a/cake/tests/cases/libs/model/datasources/dbo/dbo_mysql.test.php b/cake/tests/cases/libs/model/datasources/dbo/dbo_mysql.test.php index 5a1bb4619..59298f134 100644 --- a/cake/tests/cases/libs/model/datasources/dbo/dbo_mysql.test.php +++ b/cake/tests/cases/libs/model/datasources/dbo/dbo_mysql.test.php @@ -277,6 +277,24 @@ class DboMysqlTest extends CakeTestCase { $this->assertEqual($expected, $result); } +/** + * test that localized floats don't cause trouble. + * + * @return void + */ + function testLocalizedFloats() { + $restore = setlocale(LC_ALL, null); + setlocale(LC_ALL, 'de_DE'); + + $result = $this->db->value(3.141593, 'float'); + $this->assertEqual((string)$result, '3.141593'); + + $result = $this->db->value(3.141593); + $this->assertEqual((string)$result, '3.141593'); + + setlocale(LC_ALL, $restore); + } + /** * testTinyintCasting method * diff --git a/cake/tests/cases/libs/model/model_write.test.php b/cake/tests/cases/libs/model/model_write.test.php index 9c01485d5..7de1d0820 100644 --- a/cake/tests/cases/libs/model/model_write.test.php +++ b/cake/tests/cases/libs/model/model_write.test.php @@ -3880,4 +3880,22 @@ class ModelWriteTest extends BaseModelTest { $this->assertFalse($result); } +/** + * test writing floats in german locale. + * + * @return void + */ + function testWriteFloatAsGerman() { + $restore = setlocale(LC_ALL, null); + setlocale(LC_ALL, 'de_DE'); + + $model = new DataTest(); + $result = $model->save(array( + 'count' => 1, + 'float' => 3.14593 + )); + $this->assertTrue($result); + setlocale(LC_ALL, $restore); + } + } From eb96d8acfbe6c31230fb28f21110aaec5de57eaf Mon Sep 17 00:00:00 2001 From: mark_story Date: Sat, 21 Aug 2010 00:39:45 -0400 Subject: [PATCH 006/166] Adding tests to dbo_postgres for localized floats. Refs #1029 --- .../datasources/dbo/dbo_postgres.test.php | 20 ++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/cake/tests/cases/libs/model/datasources/dbo/dbo_postgres.test.php b/cake/tests/cases/libs/model/datasources/dbo/dbo_postgres.test.php index ad7b3166b..3fd70d1db 100644 --- a/cake/tests/cases/libs/model/datasources/dbo/dbo_postgres.test.php +++ b/cake/tests/cases/libs/model/datasources/dbo/dbo_postgres.test.php @@ -352,7 +352,7 @@ class DboPostgresTest extends CakeTestCase { * @return void */ function testValueQuoting() { - $this->assertIdentical($this->db2->value(1.2, 'float'), "'1.2'"); + $this->assertIdentical($this->db2->value(1.2, 'float'), "'1.200000'"); $this->assertEqual($this->db2->value('1,2', 'float'), "'1,2'"); $this->assertEqual($this->db2->value('0', 'integer'), "'0'"); @@ -378,6 +378,24 @@ class DboPostgresTest extends CakeTestCase { $this->assertEqual($this->db2->value(array()), "NULL"); } +/** + * test that localized floats don't cause trouble. + * + * @return void + */ + function testLocalizedFloats() { + $restore = setlocale(LC_ALL, null); + setlocale(LC_ALL, 'de_DE'); + + $result = $this->db->value(3.141593, 'float'); + $this->assertEqual((string)$result, "'3.141593'"); + + $result = $this->db->value(3.14); + $this->assertEqual((string)$result, "'3.140000'"); + + setlocale(LC_ALL, $restore); + } + /** * test that date and time columns do not generate errors with null and nullish values. * From 12d4b52f105e6c84824eb5c8e6ca6d4996760e4d Mon Sep 17 00:00:00 2001 From: mark_story Date: Sat, 21 Aug 2010 00:49:40 -0400 Subject: [PATCH 007/166] Fixing failing tests in DboMysql and DboPostgres related to localized floats. Refs #1029 --- cake/libs/model/datasources/dbo/dbo_mysql.php | 15 +++++++++------ cake/libs/model/datasources/dbo/dbo_postgres.php | 5 ++++- 2 files changed, 13 insertions(+), 7 deletions(-) diff --git a/cake/libs/model/datasources/dbo/dbo_mysql.php b/cake/libs/model/datasources/dbo/dbo_mysql.php index 7b0bfea9b..1ed2ae13a 100644 --- a/cake/libs/model/datasources/dbo/dbo_mysql.php +++ b/cake/libs/model/datasources/dbo/dbo_mysql.php @@ -658,16 +658,19 @@ class DboMysql extends DboMysqlBase { if ($data === '') { return 'NULL'; } - if ((is_int($data) || is_float($data) || $data === '0') || ( + if (is_float($data)) { + return sprintf('%F', $data); + } + if ((is_int($data) || $data === '0') || ( is_numeric($data) && strpos($data, ',') === false && - $data[0] != '0' && strpos($data, 'e') === false)) { - return $data; - } + $data[0] != '0' && strpos($data, 'e') === false) + ) { + return $data; + } default: - $data = "'" . mysql_real_escape_string($data, $this->connection) . "'"; + return "'" . mysql_real_escape_string($data, $this->connection) . "'"; break; } - return $data; } /** diff --git a/cake/libs/model/datasources/dbo/dbo_postgres.php b/cake/libs/model/datasources/dbo/dbo_postgres.php index 6c692d942..bd4e8562b 100644 --- a/cake/libs/model/datasources/dbo/dbo_postgres.php +++ b/cake/libs/model/datasources/dbo/dbo_postgres.php @@ -299,8 +299,11 @@ class DboPostgres extends DboSource { } switch($column) { - case 'inet': case 'float': + if (is_float($data)) { + $data = sprintf('%F', $data); + } + case 'inet': case 'integer': case 'date': case 'datetime': From 5446a062ee444c6973c76a4562eb3afe2f46d967 Mon Sep 17 00:00:00 2001 From: mark_story Date: Sat, 21 Aug 2010 22:48:59 -0400 Subject: [PATCH 008/166] Fixing issue where whitelist would not be used for validation. Test case added. Fixes #1037 --- cake/libs/model/model.php | 2 +- .../libs/model/model_validation.test.php | 25 ++++++++++++++++++- 2 files changed, 25 insertions(+), 2 deletions(-) diff --git a/cake/libs/model/model.php b/cake/libs/model/model.php index f99f75c7c..100d331b5 100644 --- a/cake/libs/model/model.php +++ b/cake/libs/model/model.php @@ -2511,7 +2511,7 @@ class Model extends Overloadable { $_validate = $this->validate; $whitelist = $this->whitelist; - if (array_key_exists('fieldList', $options)) { + if (!empty($options['fieldList'])) { $whitelist = $options['fieldList']; } diff --git a/cake/tests/cases/libs/model/model_validation.test.php b/cake/tests/cases/libs/model/model_validation.test.php index 6da40853d..bbf00996e 100644 --- a/cake/tests/cases/libs/model/model_validation.test.php +++ b/cake/tests/cases/libs/model/model_validation.test.php @@ -164,11 +164,34 @@ class ModelValidationTest extends BaseModelTest { $TestModel->invalidFields(); $expected = array('name' => 'This field cannot be left blank'); $this->assertEqual($TestModel->validationErrors, $expected); - $TestModel->validationErrors = array(); $this->assertEqual($TestModel->validate, $validate); } +/** + * Test that invalidFields() integrates well with save(). And that fieldList can be an empty type. + * + * @return void + */ + function testInvalidFieldsWhitelist() { + $TestModel =& new ValidationTest1(); + $TestModel->validate = $validate = array( + 'title' => array( + 'rule' => 'customValidator', + 'required' => true + ), + 'name' => array( + 'rule' => 'alphaNumeric', + 'required' => true + )); + + $TestModel->whitelist = array('name'); + $TestModel->save(array('name' => '#$$#')); + + $expected = array('name' => 'This field cannot be left blank'); + $this->assertEqual($TestModel->validationErrors, $expected); + } + /** * testValidates method * From 0ec0962932574fac51a7b76bbf0058f1053837e4 Mon Sep 17 00:00:00 2001 From: mark_story Date: Sun, 22 Aug 2010 00:15:13 -0400 Subject: [PATCH 009/166] Adding CakeRequest::method() to find the name of the HTTP method name used for the request. Test case added. --- cake/libs/cake_request.php | 9 +++++++++ cake/tests/cases/libs/cake_request.test.php | 12 ++++++++++++ 2 files changed, 21 insertions(+) diff --git a/cake/libs/cake_request.php b/cake/libs/cake_request.php index 6a84f16e7..1b15c2239 100644 --- a/cake/libs/cake_request.php +++ b/cake/libs/cake_request.php @@ -552,6 +552,15 @@ class CakeRequest implements ArrayAccess { return false; } +/** + * Get the HTTP method used for this request. + * + * @return string The name of the HTTP method used. + */ + public function method() { + return env('REQUEST_METHOD'); + } + /** * Find out which content types the client accepts or check if they accept a * particular type of content. diff --git a/cake/tests/cases/libs/cake_request.test.php b/cake/tests/cases/libs/cake_request.test.php index 3c51bc9b7..ff7107a56 100644 --- a/cake/tests/cases/libs/cake_request.test.php +++ b/cake/tests/cases/libs/cake_request.test.php @@ -500,6 +500,18 @@ class CakeRequestTestCase extends CakeTestCase { $this->assertFalse($request->is('delete')); } +/** + * test the method() method. + * + * @return void + */ + function testMethod() { + $_SERVER['REQUEST_METHOD'] = 'delete'; + $request = new CakeRequest('some/path'); + + $this->assertEquals('delete', $request->method()); + } + /** * test ajax, flash and friends * From ec22db597f70d914e0f815df2ca9b7a02abd973d Mon Sep 17 00:00:00 2001 From: mark_story Date: Sun, 22 Aug 2010 00:44:05 -0400 Subject: [PATCH 010/166] Adding methods to get host, domain and subdomains for a request. Tests added. --- cake/libs/cake_request.php | 32 +++++++++++++++ cake/tests/cases/libs/cake_request.test.php | 45 +++++++++++++++++++++ 2 files changed, 77 insertions(+) diff --git a/cake/libs/cake_request.php b/cake/libs/cake_request.php index 1b15c2239..d3828e15b 100644 --- a/cake/libs/cake_request.php +++ b/cake/libs/cake_request.php @@ -561,6 +561,38 @@ class CakeRequest implements ArrayAccess { return env('REQUEST_METHOD'); } +/** + * Get the host that the request was handled on. + * + * @return void + */ + public function host() { + return env('HTTP_HOST'); + } + +/** + * Get the domain name and include $tldLength segments of the tld. + * + * @param int $tldLength Number of segments your tld contains + * @return string Domain name without subdomains. + */ + function domain($tldLength = 1) { + $segments = explode('.', $this->host()); + $domain = array_slice($segments, -1 * ($tldLength + 1)); + return implode('.', $domain); + } + +/** + * Get the subdomains for a host. + * + * @param int $tldLength Number of segments your tld contains. + * @return array of subdomains. + */ + function subdomains($tldLength = 1) { + $segments = explode('.', $this->host()); + return array_slice($segments, 0, -1 * ($tldLength + 1)); + } + /** * Find out which content types the client accepts or check if they accept a * particular type of content. diff --git a/cake/tests/cases/libs/cake_request.test.php b/cake/tests/cases/libs/cake_request.test.php index ff7107a56..17089b4cb 100644 --- a/cake/tests/cases/libs/cake_request.test.php +++ b/cake/tests/cases/libs/cake_request.test.php @@ -512,6 +512,51 @@ class CakeRequestTestCase extends CakeTestCase { $this->assertEquals('delete', $request->method()); } +/** + * test host retrieval. + * + * @return void + */ + function testHost() { + $_SERVER['HTTP_HOST'] = 'localhost'; + $request = new CakeRequest('some/path'); + + $this->assertEquals('localhost', $request->host()); + } + +/** + * test domain retrieval. + * + * @return void + */ + function testDomain() { + $_SERVER['HTTP_HOST'] = 'something.example.com'; + $request = new CakeRequest('some/path'); + + $this->assertEquals('example.com', $request->domain()); + + $_SERVER['HTTP_HOST'] = 'something.example.co.uk'; + $this->assertEquals('example.co.uk', $request->domain(2)); + } + +/** + * test getting subdomains for a host. + * + * @return void + */ + function testSubdomain() { + $_SERVER['HTTP_HOST'] = 'something.example.com'; + $request = new CakeRequest('some/path'); + + $this->assertEquals(array('something'), $request->subdomains()); + + $_SERVER['HTTP_HOST'] = 'www.something.example.com'; + $this->assertEquals(array('www', 'something'), $request->subdomains()); + + $_SERVER['HTTP_HOST'] = 'www.something.example.co.uk'; + $this->assertEquals(array('www', 'something'), $request->subdomains(2)); + } + /** * test ajax, flash and friends * From efc1a2033f4ae4562fd4cccd6d2eb07e019031e5 Mon Sep 17 00:00:00 2001 From: mark_story Date: Sun, 22 Aug 2010 00:48:24 -0400 Subject: [PATCH 011/166] Adding spaces infront of comment blocks. --- cake/libs/cake_response.php | 50 ++++++++++++++++++------------------- 1 file changed, 25 insertions(+), 25 deletions(-) diff --git a/cake/libs/cake_response.php b/cake/libs/cake_response.php index 12b6a8cda..acd68158e 100644 --- a/cake/libs/cake_response.php +++ b/cake/libs/cake_response.php @@ -570,12 +570,12 @@ class CakeResponse { } /** -* Sets the response charset -* if $charset is null the current charset is returned -* -* @param string $charset -* @return string current charset -*/ + * Sets the response charset + * if $charset is null the current charset is returned + * + * @param string $charset + * @return string current charset + */ public function charset($charset = null) { if (is_null($charset)) { return $this->_charset; @@ -584,10 +584,10 @@ class CakeResponse { } /** -* Sets the correct headers to instruct the client to not cache te response -* -* @return void -*/ + * Sets the correct headers to instruct the client to not cache te response + * + * @return void + */ public function disableCache() { $this->header(array( 'Expires' => 'Mon, 26 Jul 1997 05:00:00 GMT', @@ -598,12 +598,12 @@ class CakeResponse { } /** -* Sets the correct headers to instruct the client to cache the response -* -* @param string $since a valid time since the response text has not been modified -* @param string $time a valid time for cache expiry -* @return void -*/ + * Sets the correct headers to instruct the client to cache the response + * + * @param string $since a valid time since the response text has not been modified + * @param string $time a valid time for cache expiry + * @return void + */ public function cache($since, $time = '+1 day') { if (!is_integer($time)) { $time = strtotime($time); @@ -617,10 +617,10 @@ class CakeResponse { } /** -* Sets the correct output buffering handler to send a compressed response -* -* @return boolean false if client does not accept compressed responses or no handler is available, true otherwise -*/ + * Sets the correct output buffering handler to send a compressed response + * + * @return boolean false if client does not accept compressed responses or no handler is available, true otherwise + */ public function compress() { $compressionEnabled = ini_get("zlib.output_compression") !== '1' && extension_loaded("zlib") && @@ -629,11 +629,11 @@ class CakeResponse { } /** -* Sets the correct headers to instruct the browser to dowload the response as a file -* -* @param string $filename the name of the file as the browser will download the response -* @return void -*/ + * Sets the correct headers to instruct the browser to dowload the response as a file + * + * @param string $filename the name of the file as the browser will download the response + * @return void + */ public function download($filename) { $this->header('Content-Disposition', 'attachment; filename="' . $filename . '"'); } From 44f1687f5be4c9e925448bd483a4caefcb061501 Mon Sep 17 00:00:00 2001 From: mark_story Date: Sun, 22 Aug 2010 00:54:55 -0400 Subject: [PATCH 012/166] Adding another test. --- cake/tests/cases/libs/cake_request.test.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/cake/tests/cases/libs/cake_request.test.php b/cake/tests/cases/libs/cake_request.test.php index 17089b4cb..e21450daf 100644 --- a/cake/tests/cases/libs/cake_request.test.php +++ b/cake/tests/cases/libs/cake_request.test.php @@ -555,6 +555,9 @@ class CakeRequestTestCase extends CakeTestCase { $_SERVER['HTTP_HOST'] = 'www.something.example.co.uk'; $this->assertEquals(array('www', 'something'), $request->subdomains(2)); + + $_SERVER['HTTP_HOST'] = 'example.co.uk'; + $this->assertEquals(array(), $request->subdomains(2)); } /** From 7221f9c3b94a88ac7f93d0871c7ee6c00ff72ad9 Mon Sep 17 00:00:00 2001 From: mark_story Date: Sun, 22 Aug 2010 12:31:55 -0400 Subject: [PATCH 013/166] Moving response construction into Controller, this will let controller classes more easily modify the response subclass they want to use. Test case updated. --- cake/libs/controller/controller.php | 32 +++++++++++++++++-- .../cases/libs/controller/controller.test.php | 23 ++++++++----- 2 files changed, 44 insertions(+), 11 deletions(-) diff --git a/cake/libs/controller/controller.php b/cake/libs/controller/controller.php index 08596f322..8ce403361 100644 --- a/cake/libs/controller/controller.php +++ b/cake/libs/controller/controller.php @@ -118,6 +118,21 @@ class Controller extends Object { */ public $request; +/** + * An instance of a CakeResponse object that contains information about the impending response + * + * @var CakeResponse + */ + public $response; + + +/** + * The classname to use for creating the response object. + * + * @var string + */ + protected $_responseClass = 'CakeResponse'; + /** * Holds pagination defaults for controller actions. The keys that can be included * in this array are: 'conditions', 'fields', 'order', 'limit', 'page', and 'recursive', @@ -322,9 +337,8 @@ class Controller extends Object { * * @param CakeRequest $request Request object for this controller can be null for testing. * But expect that features that use the params will not work. - * @param CakeResponse $response Response object for this controller */ - public function __construct($request = null, $response = null) { + public function __construct($request = null) { if ($this->name === null) { $r = null; if (!preg_match('/(.*)Controller/i', get_class($this), $r)) { @@ -349,7 +363,7 @@ class Controller extends Object { if ($request instanceof CakeRequest) { $this->_setRequest($request); } - $this->response = $response; + $this->getResponse(); parent::__construct(); } @@ -501,6 +515,18 @@ class Controller extends Object { return true; } +/** + * Gets the response object for this controller. Will construct the response if it has not already been built. + * + * @return CakeResponse + */ + public function getResponse() { + if (empty($this->response)) { + $this->response = new $this->_responseClass(array('charset' => Configure::read('App.encoding'))); + } + return $this->response; + } + /** * Perform the startup process for this controller. * Fire the Component and Controller callbacks in the correct order. diff --git a/cake/tests/cases/libs/controller/controller.test.php b/cake/tests/cases/libs/controller/controller.test.php index 64451a536..c9c99ed3c 100644 --- a/cake/tests/cases/libs/controller/controller.test.php +++ b/cake/tests/cases/libs/controller/controller.test.php @@ -856,7 +856,8 @@ class ControllerTest extends CakeTestCase { function testFlash() { $request = new CakeRequest('controller_posts/index'); - $Controller = new Controller($request, $this->getMock('CakeResponse', array('_sendHeader'))); + $Controller = new Controller($request); + $Controller->response = $this->getMock('CakeResponse', array('_sendHeader')); $Controller->flash('this should work', '/flash'); $result = $Controller->response->body(); @@ -880,7 +881,8 @@ class ControllerTest extends CakeTestCase { $this->assertEqual($result, $expected); App::build(array('views' => array(TEST_CAKE_CORE_INCLUDE_PATH . 'tests' . DS . 'test_app' . DS . 'views'. DS))); - $Controller = new Controller(null, $this->getMock('CakeResponse', array('_sendHeader'))); + $Controller = new Controller(null); + $Controller->response = $this->getMock('CakeResponse', array('_sendHeader')); $Controller->flash('this should work', '/flash', 1, 'ajax2'); $result = $Controller->response->body(); $this->assertPattern('/Ajax!/', $result); @@ -1030,11 +1032,12 @@ class ControllerTest extends CakeTestCase { * @return void */ function testRedirectByCode($code, $msg) { - $Controller = new Controller(null, $this->getMock('CakeResponse', array('header', 'statusCode'))); - + $Controller = new Controller(null); + $Controller->response = $this->getMock('CakeResponse', array('header', 'statusCode')); $Controller->Component = new Component(); $Controller->Component->init($Controller); + $Controller->response->expects($this->once())->method('statusCode') ->with($code); $Controller->response->expects($this->once())->method('header') @@ -1051,7 +1054,8 @@ class ControllerTest extends CakeTestCase { * @return void */ function testRedirectByMessage($code, $msg) { - $Controller = new Controller(null, $this->getMock('CakeResponse', array('header', 'statusCode'))); + $Controller = new Controller(null); + $Controller->response = $this->getMock('CakeResponse', array('header', 'statusCode')); $Controller->Component = new Component(); $Controller->Component->init($Controller); @@ -1072,7 +1076,8 @@ class ControllerTest extends CakeTestCase { * @return void */ function testRedirectTriggeringComponentsReturnNull() { - $Controller = new Controller(null, $this->getMock('CakeResponse', array('header', 'statusCode'))); + $Controller = new Controller(null); + $Controller->response = $this->getMock('CakeResponse', array('header', 'statusCode')); $Controller->Component = $this->getMock('Component'); $Controller->Component->expects($this->once())->method('beforeRedirect')->will($this->returnValue(null)); @@ -1092,7 +1097,8 @@ class ControllerTest extends CakeTestCase { * @return void */ function testRedirectBeforeRedirectModifyingParams() { - $Controller = new Controller(null, $this->getMock('CakeResponse', array('header', 'statusCode'))); + $Controller = new Controller(null); + $Controller->response = $this->getMock('CakeResponse', array('header', 'statusCode')); $Controller->Component = $this->getMock('Component'); $Controller->Component->expects($this->once())->method('beforeRedirect') @@ -1414,7 +1420,8 @@ class ControllerTest extends CakeTestCase { * @return void */ function testControllerHttpCodes() { - $Controller = new Controller(null, $this->getMock('CakeResponse', array('httpCodes'))); + $Controller = new Controller(null); + $Controller->response = $this->getMock('CakeResponse', array('httpCodes')); $Controller->response->expects($this->at(0))->method('httpCodes')->with(null); $Controller->response->expects($this->at(1))->method('httpCodes')->with(100); $Controller->httpCodes(); From 91c9c742745bdcbd372a74f0893a86c283719b52 Mon Sep 17 00:00:00 2001 From: mark_story Date: Sun, 22 Aug 2010 12:40:06 -0400 Subject: [PATCH 014/166] Removing response injection into controller from dispatcher. Modifying Dispatcher to use accessor method. --- cake/dispatcher.php | 21 ++++++++------------- 1 file changed, 8 insertions(+), 13 deletions(-) diff --git a/cake/dispatcher.php b/cake/dispatcher.php index 57529ee33..af389c331 100644 --- a/cake/dispatcher.php +++ b/cake/dispatcher.php @@ -78,10 +78,9 @@ class Dispatcher { public $request = null; /** - * The response object + * Response object used for asset/cached responses. * * @var CakeResponse - * @access public */ public $response = null; @@ -195,19 +194,20 @@ class Dispatcher { 'base' => $request->base ))); } - $output =& call_user_func_array(array(&$controller, $request->params['action']), $request->params['pass']); + $result =& call_user_func_array(array(&$controller, $request->params['action']), $request->params['pass']); + $response = $controller->getResponse(); if ($controller->autoRender) { $controller->render(); - } elseif ($this->response->body() === null) { - $this->response->body($output); + } elseif ($response->body() === null) { + $response->body($result); } $controller->shutdownProcess(); if (isset($request->params['return'])) { - return $this->response->body(); + return $response->body(); } - $this->response->send(); + $response->send(); } /** @@ -256,14 +256,9 @@ class Dispatcher { if (!$ctrlClass) { return $controller; } - if (!$this->response) { - $this->response = new CakeResponse(array( - 'charset' => Configure::read('App.encoding') - )); - } $ctrlClass .= 'Controller'; if (class_exists($ctrlClass)) { - $controller = new $ctrlClass($this->request, $this->response); + $controller = new $ctrlClass($this->request); } return $controller; } From b5b7595bc0441f2ec133ce79638cdd2f85c7fa7b Mon Sep 17 00:00:00 2001 From: mark_story Date: Sun, 22 Aug 2010 12:41:04 -0400 Subject: [PATCH 015/166] Fixing issue in scaffold where it accessed $output, which no longer exists. --- cake/libs/controller/scaffold.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cake/libs/controller/scaffold.php b/cake/libs/controller/scaffold.php index 8789db369..4563828aa 100644 --- a/cake/libs/controller/scaffold.php +++ b/cake/libs/controller/scaffold.php @@ -164,7 +164,7 @@ class Scaffold { */ protected function _output() { $this->controller->afterFilter(); - echo($this->controller->output); + $this->controller->getResponse()->send(); } /** From ece055eefe3fb374505f618a9d1c8d2c9b9a448d Mon Sep 17 00:00:00 2001 From: mark_story Date: Mon, 23 Aug 2010 21:39:23 -0400 Subject: [PATCH 016/166] Adding object type check to prevent fatal errors caused by view being used like a model object. Tests added. Fixes #1039 --- cake/libs/view/helper.php | 6 +++++- cake/tests/cases/libs/view/helper.test.php | 13 ++++++++++++- 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/cake/libs/view/helper.php b/cake/libs/view/helper.php index 570cd691c..ecd731b90 100644 --- a/cake/libs/view/helper.php +++ b/cake/libs/view/helper.php @@ -442,7 +442,11 @@ class Helper extends Overloadable { if (ClassRegistry::isKeySet($model)) { $ModelObj =& ClassRegistry::getObject($model); for ($i = 0; $i < $count; $i++) { - if ($ModelObj->hasField($parts[$i]) || array_key_exists($parts[$i], $ModelObj->validate)) { + if ( + is_a($ModelObj, 'Model') && + ($ModelObj->hasField($parts[$i]) || + array_key_exists($parts[$i], $ModelObj->validate)) + ) { $hasField = $i; if ($hasField === 0 || ($hasField === 1 && is_numeric($parts[0]))) { $sameScope = true; diff --git a/cake/tests/cases/libs/view/helper.test.php b/cake/tests/cases/libs/view/helper.test.php index 311e1b9b8..6f81c455e 100644 --- a/cake/tests/cases/libs/view/helper.test.php +++ b/cake/tests/cases/libs/view/helper.test.php @@ -219,7 +219,7 @@ class HelperTest extends CakeTestCase { * @access public * @return void */ - function testFormFieldNameParsing() { + function testSetEntity() { // PHP4 reference hack ClassRegistry::removeObject('view'); ClassRegistry::addObject('view', $this->View); @@ -350,6 +350,17 @@ class HelperTest extends CakeTestCase { $this->assertEqual($this->View->fieldSuffix, null); } +/** + * test that 'view' doesn't break things. + * + * @return void + */ + function testSetEntityWithView() { + $this->assertNull($this->Helper->setEntity('Allow.view.group_id')); + $this->assertNull($this->Helper->setEntity('Allow.view')); + $this->assertNull($this->Helper->setEntity('View.view')); + } + /** * test getting values from Helper * From c48c0d62950d28e0c0cb01cfb25bef3b21cc0529 Mon Sep 17 00:00:00 2001 From: mark_story Date: Mon, 23 Aug 2010 21:49:30 -0400 Subject: [PATCH 017/166] Fixing issue where ViewTask would make empty view files for actions that did not have templates. Test case added. Fixes #1040 --- cake/console/libs/tasks/view.php | 3 +++ cake/tests/cases/console/libs/tasks/view.test.php | 13 +++++++++++++ 2 files changed, 16 insertions(+) diff --git a/cake/console/libs/tasks/view.php b/cake/console/libs/tasks/view.php index 2ebffc733..7ccc74072 100644 --- a/cake/console/libs/tasks/view.php +++ b/cake/console/libs/tasks/view.php @@ -366,6 +366,9 @@ class ViewTask extends BakeTask { if ($content === true) { $content = $this->getContent($action); } + if (empty($content)) { + return false; + } $path = $this->getPath(); $filename = $path . $this->controllerPath . DS . Inflector::underscore($action) . '.ctp'; return $this->createFile($filename, $content); diff --git a/cake/tests/cases/console/libs/tasks/view.test.php b/cake/tests/cases/console/libs/tasks/view.test.php index 12f9d79d7..405b00a9a 100644 --- a/cake/tests/cases/console/libs/tasks/view.test.php +++ b/cake/tests/cases/console/libs/tasks/view.test.php @@ -374,6 +374,19 @@ class ViewTaskTest extends CakeTestCase { $this->Task->bake('index', true); } +/** + * test that baking a view with no template doesn't make a file. + * + * @return void + */ + function testBakeWithNoTemplate() { + $this->Task->controllerName = 'ViewTaskComments'; + $this->Task->controllerPath = 'view_task_comments'; + + $this->Task->expectNever('createFile'); + $this->Task->bake('delete', true); + } + /** * test bake() with a -plugin param * From 903b26063821dbdafd3c381cb121c78a42bc4a80 Mon Sep 17 00:00:00 2001 From: mark_story Date: Thu, 26 Aug 2010 20:29:03 -0400 Subject: [PATCH 018/166] Changing spaces to tabs. --- cake/tests/cases/libs/view/helpers/text.test.php | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/cake/tests/cases/libs/view/helpers/text.test.php b/cake/tests/cases/libs/view/helpers/text.test.php index 7a5470c01..316c61c7a 100644 --- a/cake/tests/cases/libs/view/helpers/text.test.php +++ b/cake/tests/cases/libs/view/helpers/text.test.php @@ -399,13 +399,13 @@ class TextHelperTest extends CakeTestCase { $result = $this->Text->toList(array('Dusty', 'Lucky', 'Ned'), 'y'); $this->assertEqual($result, 'Dusty, Lucky y Ned'); - $result = $this->Text->toList(array( 1 => 'Dusty', 2 => 'Lucky', 3 => 'Ned'), 'y'); - $this->assertEqual($result, 'Dusty, Lucky y Ned'); + $result = $this->Text->toList(array( 1 => 'Dusty', 2 => 'Lucky', 3 => 'Ned'), 'y'); + $this->assertEqual($result, 'Dusty, Lucky y Ned'); - $result = $this->Text->toList(array( 1 => 'Dusty', 2 => 'Lucky', 3 => 'Ned'), 'and', ' + '); - $this->assertEqual($result, 'Dusty + Lucky and Ned'); + $result = $this->Text->toList(array( 1 => 'Dusty', 2 => 'Lucky', 3 => 'Ned'), 'and', ' + '); + $this->assertEqual($result, 'Dusty + Lucky and Ned'); - $result = $this->Text->toList(array( 'name1' => 'Dusty', 'name2' => 'Lucky')); - $this->assertEqual($result, 'Dusty and Lucky'); + $result = $this->Text->toList(array( 'name1' => 'Dusty', 'name2' => 'Lucky')); + $this->assertEqual($result, 'Dusty and Lucky'); } } From 465c24f90313299a3bfa1b8ffb22f710ba021b5b Mon Sep 17 00:00:00 2001 From: mark_story Date: Thu, 26 Aug 2010 20:30:30 -0400 Subject: [PATCH 019/166] Adding a test case for TextHelper::toList(). Closes #1043 --- cake/tests/cases/libs/view/helpers/text.test.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/cake/tests/cases/libs/view/helpers/text.test.php b/cake/tests/cases/libs/view/helpers/text.test.php index 316c61c7a..f4c18d628 100644 --- a/cake/tests/cases/libs/view/helpers/text.test.php +++ b/cake/tests/cases/libs/view/helpers/text.test.php @@ -407,5 +407,8 @@ class TextHelperTest extends CakeTestCase { $result = $this->Text->toList(array( 'name1' => 'Dusty', 'name2' => 'Lucky')); $this->assertEqual($result, 'Dusty and Lucky'); + + $result = $this->Text->toList(array( 'test_0' => 'banana', 'test_1' => 'apple', 'test_2' => 'lemon')); + $this->assertEqual($result, 'banana, apple and lemon'); } } From 95168cee6e4a75f85ed414e7be48c93eb9d49929 Mon Sep 17 00:00:00 2001 From: dogmatic69 Date: Tue, 24 Aug 2010 12:14:46 +0100 Subject: [PATCH 020/166] casting the find as an array to avoid errors with array_values() fixes #1041 and 4 failing tests (3 previous) Signed-off-by: mark_story --- cake/libs/model/behaviors/tree.php | 2 +- cake/tests/cases/libs/model/behaviors/tree.test.php | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/cake/libs/model/behaviors/tree.php b/cake/libs/model/behaviors/tree.php index 10bd8544b..349506213 100644 --- a/cake/libs/model/behaviors/tree.php +++ b/cake/libs/model/behaviors/tree.php @@ -284,7 +284,7 @@ class TreeBehavior extends ModelBehavior { if (!$id) { $conditions = $scope; } else { - $result = array_values($Model->find('first', array( + $result = array_values((array)$Model->find('first', array( 'conditions' => array($scope, $Model->escapeField() => $id), 'fields' => array($left, $right), 'recursive' => $recursive diff --git a/cake/tests/cases/libs/model/behaviors/tree.test.php b/cake/tests/cases/libs/model/behaviors/tree.test.php index c0dc9ccc0..39475cd60 100644 --- a/cake/tests/cases/libs/model/behaviors/tree.test.php +++ b/cake/tests/cases/libs/model/behaviors/tree.test.php @@ -1089,6 +1089,8 @@ class NumberTreeTest extends CakeTestCase { array($modelClass => array( 'id' => 6, 'name' => '1.2.1', $parentField => 5, $leftField => 9, $rightField => 10)), array($modelClass => array('id' => 7, 'name' => '1.2.2', $parentField => 5, $leftField => 11, $rightField => 12))); $this->assertEqual($total, $expects); + + $this->assertEqual(array(), $this->Tree->children(10000)); } /** From 123873b4d817aacc9b7e7764fa04c73122ef486e Mon Sep 17 00:00:00 2001 From: mark_story Date: Thu, 26 Aug 2010 21:20:13 -0400 Subject: [PATCH 021/166] Updating DboSource test to account for formatting of floats done in mysql/postgresql. --- cake/tests/cases/libs/model/datasources/dbo_source.test.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cake/tests/cases/libs/model/datasources/dbo_source.test.php b/cake/tests/cases/libs/model/datasources/dbo_source.test.php index 6a71591bd..442d690ac 100644 --- a/cake/tests/cases/libs/model/datasources/dbo_source.test.php +++ b/cake/tests/cases/libs/model/datasources/dbo_source.test.php @@ -2548,11 +2548,11 @@ class DboSourceTest extends CakeTestCase { $this->assertEqual($result, $expected); $result = $this->testDb->conditions(array('score BETWEEN ? AND ?' => array(90.1, 95.7))); - $expected = " WHERE `score` BETWEEN 90.1 AND 95.7"; + $expected = " WHERE `score` BETWEEN 90.100000 AND 95.700000"; $this->assertEqual($result, $expected); $result = $this->testDb->conditions(array('Post.title' => 1.1)); - $expected = " WHERE `Post`.`title` = 1.1"; + $expected = " WHERE `Post`.`title` = 1.100000"; $this->assertEqual($result, $expected); $result = $this->testDb->conditions(array('Post.title' => 1.1), true, true, new Post()); From ea9e30890fa80558fc8afb005cc22231c0e1d1db Mon Sep 17 00:00:00 2001 From: mark_story Date: Thu, 26 Aug 2010 21:24:09 -0400 Subject: [PATCH 022/166] Adding a workaround to DboSource::showLog() to work around fix added in [da9c0da626901a1462e63af7e6840693bcb1f1d2]. Also adding explanation message when logs are not generated. --- cake/libs/model/datasources/dbo_source.php | 2 +- cake/libs/view/elements/sql_dump.ctp | 10 +++++++--- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/cake/libs/model/datasources/dbo_source.php b/cake/libs/model/datasources/dbo_source.php index 940a909df..abe268294 100755 --- a/cake/libs/model/datasources/dbo_source.php +++ b/cake/libs/model/datasources/dbo_source.php @@ -630,7 +630,7 @@ class DboSource extends DataSource { $controller = null; $View =& new View($controller, false); $View->set('logs', array($this->configKeyName => $log)); - echo $View->element('sql_dump'); + echo $View->element('sql_dump', array('_forced_from_dbo_' => true)); } else { foreach ($log['log'] as $k => $i) { print (($k + 1) . ". {$i['query']} {$i['error']}\n"); diff --git a/cake/libs/view/elements/sql_dump.ctp b/cake/libs/view/elements/sql_dump.ctp index c5cea554c..283946deb 100644 --- a/cake/libs/view/elements/sql_dump.ctp +++ b/cake/libs/view/elements/sql_dump.ctp @@ -20,7 +20,8 @@ if (!class_exists('ConnectionManager') || Configure::read('debug') < 2) { return false; } -if (!isset($logs)): +$noLogs = !isset($logs); +if ($noLogs): $sources = ConnectionManager::sourceList(); $logs = array(); @@ -31,8 +32,9 @@ if (!isset($logs)): endif; $logs[$source] = $db->getLog(); endforeach; +endif; - +if ($noLogs || isset($_forced_from_dbo_)): foreach ($logs as $source => $logInfo): $text = $logInfo['count'] > 1 ? 'queries' : 'query'; printf( @@ -52,6 +54,8 @@ if (!isset($logs)): ?> Encountered unexpected $logs cannot generate SQL log

'; endif; ?> From b02e21395834a59f7df5848a1f352f39da696c4c Mon Sep 17 00:00:00 2001 From: mark_story Date: Thu, 26 Aug 2010 22:21:39 -0400 Subject: [PATCH 023/166] Adding test case from '0x20h'. Fixing issue where atomic = false, validate = first and saveAll() saving many rows could return an incorrect value. Fixes #1050 --- cake/libs/model/model.php | 2 +- .../cases/libs/model/model_write.test.php | 59 +++++++++++++++++++ 2 files changed, 60 insertions(+), 1 deletion(-) diff --git a/cake/libs/model/model.php b/cake/libs/model/model.php index 100d331b5..32a19a717 100644 --- a/cake/libs/model/model.php +++ b/cake/libs/model/model.php @@ -1593,6 +1593,7 @@ class Model extends Overloadable { if (Set::numeric(array_keys($data))) { while ($validates) { + $return = array(); foreach ($data as $key => $record) { if (!$currentValidates = $this->__save($record, $options)) { $validationErrors[$key] = $this->validationErrors; @@ -1624,7 +1625,6 @@ class Model extends Overloadable { break; case ($options['validate'] === 'first'): $options['validate'] = true; - $return = array(); break; default: if ($options['atomic']) { diff --git a/cake/tests/cases/libs/model/model_write.test.php b/cake/tests/cases/libs/model/model_write.test.php index 7de1d0820..497bc56fa 100644 --- a/cake/tests/cases/libs/model/model_write.test.php +++ b/cake/tests/cases/libs/model/model_write.test.php @@ -3584,6 +3584,65 @@ class ModelWriteTest extends BaseModelTest { $this->assertEqual($result[0]['Comment'][0]['comment'], 'Only new comment'); } +/** + * test saveAll()'s return is correct when using atomic = false and validate = first. + * + * @return void + */ + function testSaveAllValidateFirstAtomicFalse() { + $Something =& new Something(); + $invalidData = array( + array( + 'title' => 'foo', + 'body' => 'bar', + 'published' => 'baz', + ), + array( + 'body' => 3, + 'published' =>'sd', + ), + ); + $Something->create(); + $Something->validate = array( + 'title' => array( + 'rule' => 'alphaNumeric', + 'required' => true, + ), + 'body' => array( + 'rule' => 'alphaNumeric', + 'required' => true, + 'allowEmpty' => true, + ), + ); + $result = $Something->saveAll($invalidData, array( + 'atomic' => false, + 'validate' => 'first', + )); + $expected = array(true, false); + $this->assertEqual($result, $expected); + + $Something =& new Something(); + $validData = array( + array( + 'title' => 'title value', + 'body' => 'body value', + 'published' => 'baz', + ), + array( + 'title' => 'valid', + 'body' => 'this body', + 'published' =>'sd', + ), + ); + $Something->create(); + $result = $Something->saveAll($validData, array( + 'atomic' => false, + 'validate' => 'first', + )); + $expected = array(true, true); + $this->assertEqual($result, $expected); + } + /** * testUpdateWithCalculation method * From 1980c924b9d587e6cab77fe69df7901f5c18c4b2 Mon Sep 17 00:00:00 2001 From: mark_story Date: Fri, 27 Aug 2010 22:48:02 -0400 Subject: [PATCH 024/166] Adding RuntimeException classes for Dispatcher. --- cake/dispatcher.php | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/cake/dispatcher.php b/cake/dispatcher.php index 21811a0f3..65686723f 100644 --- a/cake/dispatcher.php +++ b/cake/dispatcher.php @@ -657,3 +657,10 @@ class Dispatcher extends Object { header($header); } } + +/** + * Runtime Exceptions for dispatcher. + */ +class MissingControllerException extends RuntimeException {} +class MissingActionException extends RuntimeException {} +class PrivateActionException extends RuntimeException {} From a15c4f89b451682911574f8405b64fa98e8ba2e9 Mon Sep 17 00:00:00 2001 From: mark_story Date: Fri, 27 Aug 2010 22:59:48 -0400 Subject: [PATCH 025/166] Moving calls of cakeError() to using exceptions. --- cake/dispatcher.php | 33 +++++++++++++-------------------- 1 file changed, 13 insertions(+), 20 deletions(-) diff --git a/cake/dispatcher.php b/cake/dispatcher.php index 65686723f..ebfbf3bcd 100644 --- a/cake/dispatcher.php +++ b/cake/dispatcher.php @@ -116,12 +116,7 @@ class Dispatcher extends Object { if (!is_object($controller)) { Router::setRequestInfo(array($this->params, array('base' => $this->base, 'webroot' => $this->webroot))); - return $this->cakeError('missingController', array(array( - 'className' => Inflector::camelize($this->params['controller']) . 'Controller', - 'webroot' => $this->webroot, - 'url' => $url, - 'base' => $this->base - ))); + throw new MissingControllerException($this->params['controller'] . 'Controller'); } $privateAction = $this->params['action'][0] === '_'; $prefixes = Router::prefixes(); @@ -140,13 +135,12 @@ class Dispatcher extends Object { )); if ($privateAction) { - return $this->cakeError('privateAction', array(array( - 'className' => Inflector::camelize($this->params['controller'] . "Controller"), - 'action' => $this->params['action'], - 'webroot' => $this->webroot, - 'url' => $url, - 'base' => $this->base - ))); + $message = sprintf( + '%s::%s()', + Inflector::camelize($this->params['controller']) . "Controller", + $this->params['action'] + ); + throw new PrivateActionException($message); } $controller->base = $this->base; $controller->here = $this->here; @@ -191,13 +185,12 @@ class Dispatcher extends Object { App::import('Controller', 'Scaffold', false); return new Scaffold($controller, $params); } - return $this->cakeError('missingAction', array(array( - 'className' => Inflector::camelize($params['controller']."Controller"), - 'action' => $params['action'], - 'webroot' => $this->webroot, - 'url' => $this->here, - 'base' => $this->base - ))); + $message = sprintf( + '%s::%s', + Inflector::camelize($params['controller']) . "Controller", + $params['action'] + ); + throw new MissingActionException($message); } $output = call_user_func_array(array(&$controller, $params['action']), $params['pass']); From caf7668de50b65a569ff9475c32c666d308b9cda Mon Sep 17 00:00:00 2001 From: mark_story Date: Fri, 27 Aug 2010 23:04:09 -0400 Subject: [PATCH 026/166] Adding documentation for Dispatcher::dispatch throwing exceptions. --- cake/dispatcher.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/cake/dispatcher.php b/cake/dispatcher.php index ebfbf3bcd..952ba893e 100644 --- a/cake/dispatcher.php +++ b/cake/dispatcher.php @@ -92,6 +92,8 @@ class Dispatcher extends Object { * @param string $url URL information to work on * @param array $additionalParams Settings array ("bare", "return") which is melded with the GET and POST params * @return boolean Success + * @throws MissingControllerException, MissingActionException, PrivateActionException if any of those error states + * are encountered. */ public function dispatch($url = null, $additionalParams = array()) { if ($this->base === false) { From b301b0d86e87f190a3cf4638de2024b67fb4a6ed Mon Sep 17 00:00:00 2001 From: mark_story Date: Fri, 27 Aug 2010 23:04:35 -0400 Subject: [PATCH 027/166] Adding MissingModelException. --- cake/libs/controller/controller.php | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/cake/libs/controller/controller.php b/cake/libs/controller/controller.php index 7405bfb41..93bb4fb6f 100644 --- a/cake/libs/controller/controller.php +++ b/cake/libs/controller/controller.php @@ -572,6 +572,7 @@ class Controller extends Object { * @param string $modelClass Name of model class to load * @param mixed $id Initial ID the instanced model class should have * @return mixed true when single model found and instance created, error returned if model not found. + * @throws MissingModelException if the model class cannot be found. */ public function loadModel($modelClass = null, $id = null) { if ($modelClass === null) { @@ -593,9 +594,7 @@ class Controller extends Object { )); if (!$this->{$modelClass}) { - return $this->cakeError('missingModel', array(array( - 'className' => $modelClass, 'webroot' => '', 'base' => $this->base - ))); + throw new MissingModelException($modelClass); } if ($this->persistModel === true) { @@ -1252,3 +1251,5 @@ class Controller extends Object { return false; } } + +class MissingModelException extends RuntimeException {} From e600f86abd8480c14a2d80605ba151b7eec0d57b Mon Sep 17 00:00:00 2001 From: mark_story Date: Fri, 27 Aug 2010 23:40:22 -0400 Subject: [PATCH 028/166] Updating Dispatcher test to test for exceptions instead of cake error returns. Removing a test that is no longer valid. --- cake/dispatcher.php | 4 +- cake/tests/cases/dispatcher.test.php | 190 +++++++++++---------------- 2 files changed, 76 insertions(+), 118 deletions(-) diff --git a/cake/dispatcher.php b/cake/dispatcher.php index 952ba893e..dfb37a63d 100644 --- a/cake/dispatcher.php +++ b/cake/dispatcher.php @@ -118,7 +118,7 @@ class Dispatcher extends Object { if (!is_object($controller)) { Router::setRequestInfo(array($this->params, array('base' => $this->base, 'webroot' => $this->webroot))); - throw new MissingControllerException($this->params['controller'] . 'Controller'); + throw new MissingControllerException(Inflector::camelize($this->params['controller']) . 'Controller'); } $privateAction = $this->params['action'][0] === '_'; $prefixes = Router::prefixes(); @@ -188,7 +188,7 @@ class Dispatcher extends Object { return new Scaffold($controller, $params); } $message = sprintf( - '%s::%s', + '%s::%s()', Inflector::camelize($params['controller']) . "Controller", $params['action'] ); diff --git a/cake/tests/cases/dispatcher.test.php b/cake/tests/cases/dispatcher.test.php index 7ba91305c..28fcfc895 100644 --- a/cake/tests/cases/dispatcher.test.php +++ b/cake/tests/cases/dispatcher.test.php @@ -1206,17 +1206,15 @@ class DispatcherTest extends CakeTestCase { * @return void */ public function testMissingController() { - $Dispatcher = new TestDispatcher(); - Configure::write('App.baseUrl', '/index.php'); - $url = 'some_controller/home/param:value/param2:value2'; - $controller = $Dispatcher->dispatch($url, array('return' => 1)); - $expected = array('missingController', array(array( - 'className' => 'SomeControllerController', - 'webroot' => '/', - 'url' => 'some_controller/home/param:value/param2:value2', - 'base' => '/index.php' - ))); - $this->assertEqual($expected, $controller); + try { + $Dispatcher = new TestDispatcher(); + Configure::write('App.baseUrl', '/index.php'); + $url = 'some_controller/home/param:value/param2:value2'; + $controller = $Dispatcher->dispatch($url, array('return' => 1)); + $this->fail('No exception thrown'); + } catch (MissingControllerException $e) { + $this->assertEquals('SomeControllerController', $e->getMessage()); + } } /** @@ -1229,16 +1227,12 @@ class DispatcherTest extends CakeTestCase { Configure::write('App.baseUrl','/index.php'); $url = 'some_pages/_protected/param:value/param2:value2'; - $controller = $Dispatcher->dispatch($url, array('return' => 1)); - - $expected = array('privateAction', array(array( - 'className' => 'SomePagesController', - 'action' => '_protected', - 'webroot' => '/', - 'url' => 'some_pages/_protected/param:value/param2:value2', - 'base' => '/index.php' - ))); - $this->assertEqual($controller, $expected); + try { + $controller = $Dispatcher->dispatch($url, array('return' => 1)); + $this->fail('No exception thrown'); + } catch (PrivateActionException $e) { + $this->assertEquals('SomePagesController::_protected()', $e->getMessage()); + } } /** @@ -1251,31 +1245,30 @@ class DispatcherTest extends CakeTestCase { Configure::write('App.baseUrl', '/index.php'); $url = 'some_pages/home/param:value/param2:value2'; - $controller = $Dispatcher->dispatch($url, array('return'=> 1)); - - $expected = array('missingAction', array(array( - 'className' => 'SomePagesController', - 'action' => 'home', - 'webroot' => '/', - 'url' => '/index.php/some_pages/home/param:value/param2:value2', - 'base' => '/index.php' - ))); - $this->assertEqual($expected, $controller); - + try { + $controller = $Dispatcher->dispatch($url, array('return'=> 1)); + $this->fail('No exception thrown'); + } catch (MissingActionException $e) { + $this->assertEquals('SomePagesController::home()', $e->getMessage()); + } + } + +/** + * test that methods declared in Controller are treated as missing methods. + * + * @return void + */ + function testMissingActionFromBaseClassMethods() { $Dispatcher = new TestDispatcher(); Configure::write('App.baseUrl','/index.php'); $url = 'some_pages/redirect/param:value/param2:value2'; - $controller = $Dispatcher->dispatch($url, array('return'=> 1)); - - $expected = array('missingAction', array(array( - 'className' => 'SomePagesController', - 'action' => 'redirect', - 'webroot' => '/', - 'url' => '/index.php/some_pages/redirect/param:value/param2:value2', - 'base' => '/index.php' - ))); - $this->assertEqual($expected, $controller); + try { + $controller = $Dispatcher->dispatch($url, array('return'=> 1)); + $this->fail('No exception thrown'); + } catch (MissingActionException $e) { + $this->assertEquals('SomePagesController::redirect()', $e->getMessage()); + } } /** @@ -1655,32 +1648,25 @@ class DispatcherTest extends CakeTestCase { $Dispatcher->base = false; $url = 'my_plugin/not_here/param:value/param2:value2'; - $controller = $Dispatcher->dispatch($url, array('return'=> 1)); - - $expected = array('missingAction', array(array( - 'className' => 'MyPluginController', - 'action' => 'not_here', - 'webroot' => '/cake/repo/branches/1.2.x.x/', - 'url' => '/cake/repo/branches/1.2.x.x/my_plugin/not_here/param:value/param2:value2', - 'base' => '/cake/repo/branches/1.2.x.x' - ))); - $this->assertIdentical($expected, $controller); + + try { + $controller = $Dispatcher->dispatch($url, array('return'=> 1)); + $this->fail('No exception.'); + } catch (MissingActionException $e) { + $this->assertEquals('MyPluginController::not_here()', $e->getMessage()); + } Router::reload(); $Dispatcher = new TestDispatcher(); $Dispatcher->base = false; $url = 'my_plugin/param:value/param2:value2'; - $controller = $Dispatcher->dispatch($url, array('return'=> 1)); - - $expected = array('missingAction', array(array( - 'className' => 'MyPluginController', - 'action' => 'param:value', - 'webroot' => '/cake/repo/branches/1.2.x.x/', - 'url' => '/cake/repo/branches/1.2.x.x/my_plugin/param:value/param2:value2', - 'base' => '/cake/repo/branches/1.2.x.x' - ))); - $this->assertIdentical($expected, $controller); + try { + $controller = $Dispatcher->dispatch($url, array('return'=> 1)); + $this->fail('No exception.'); + } catch (MissingActionException $e) { + $this->assertEquals('MyPluginController::param:value()', $e->getMessage()); + } } /** @@ -1699,16 +1685,12 @@ class DispatcherTest extends CakeTestCase { $Dispatcher->base = false; $url = 'test_dispatch_pages/admin_index/param:value/param2:value2'; - $controller = $Dispatcher->dispatch($url, array('return' => 1)); - - $expected = array('privateAction', array(array( - 'className' => 'TestDispatchPagesController', - 'action' => 'admin_index', - 'webroot' => '/cake/repo/branches/1.2.x.x/', - 'url' => 'test_dispatch_pages/admin_index/param:value/param2:value2', - 'base' => '/cake/repo/branches/1.2.x.x' - ))); - $this->assertIdentical($expected, $controller); + try { + $controller = $Dispatcher->dispatch($url, array('return'=> 1)); + $this->fail('No exception.'); + } catch (PrivateActionException $e) { + $this->assertEquals('TestDispatchPagesController::admin_index()', $e->getMessage()); + } } /** @@ -1747,16 +1729,13 @@ class DispatcherTest extends CakeTestCase { $_SERVER['PHP_SELF'] = '/cake/repo/branches/1.2.x.x/index.php'; $Dispatcher = new TestDispatcher(); $url = 'some_posts/index/param:value/param2:value2'; - $controller = $Dispatcher->dispatch($url, array('return' => 1)); - - $expected = array('missingAction', array(array( - 'className' => 'SomePostsController', - 'action' => 'view', - 'webroot' => '/cake/repo/branches/1.2.x.x/', - 'url' => '/cake/repo/branches/1.2.x.x/some_posts/index/param:value/param2:value2', - 'base' => '/cake/repo/branches/1.2.x.x' - ))); - $this->assertEqual($expected, $controller); + + try { + $controller = $Dispatcher->dispatch($url, array('return'=> 1)); + $this->fail('No exception.'); + } catch (MissingActionException $e) { + $this->assertEquals('SomePostsController::view()', $e->getMessage()); + } $url = 'some_posts/something_else/param:value/param2:value2'; $controller = $Dispatcher->dispatch($url, array('return' => 1)); @@ -1789,15 +1768,19 @@ class DispatcherTest extends CakeTestCase { $debug = Configure::read('debug'); Configure::write('debug', 0); - ob_start(); - $Dispatcher->dispatch('theme/test_theme/../webroot/css/test_asset.css'); - $result = ob_get_clean(); - $this->assertEquals($result, ''); - - ob_start(); - $Dispatcher->dispatch('theme/test_theme/pdfs'); - $result = ob_get_clean(); - $this->assertEquals($result, ''); + try { + $Dispatcher->dispatch('theme/test_theme/../webroot/css/test_asset.css'); + $this->fail('No exception'); + } catch (MissingControllerException $e) { + $this->assertEquals('ThemeController', $e->getMessage()); + } + + try { + $Dispatcher->dispatch('theme/test_theme/pdfs'); + $this->fail('No exception'); + } catch (MissingControllerException $e) { + $this->assertEquals('ThemeController', $e->getMessage()); + } ob_start(); $Dispatcher->dispatch('theme/test_theme/flash/theme_test.swf'); @@ -2321,31 +2304,6 @@ class DispatcherTest extends CakeTestCase { $this->__loadEnvironment(array_merge(array('reload' => true), $backup)); } -/** - * Tests that the Dispatcher does not return an empty action - * - * @return void - */ - public function testTrailingSlash() { - $_POST = array(); - $_SERVER['PHP_SELF'] = '/cake/repo/branches/1.2.x.x/index.php'; - - Router::reload(); - $Dispatcher = new TestDispatcher(); - Router::connect('/myalias/:action/*', array('controller' => 'my_controller', 'action' => null)); - - $Dispatcher->base = false; - $url = 'myalias/'; //Fails - $controller = $Dispatcher->dispatch($url, array('return' => 1)); - $result = $Dispatcher->parseParams($url); - $this->assertEqual('index', $result['action']); - - $url = 'myalias'; //Passes - $controller = $Dispatcher->dispatch($url, array('return' => 1)); - $result = $Dispatcher->parseParams($url); - $this->assertEqual('index', $result['action']); - } - /** * backupEnvironment method * From c4cb629d807c65d116593d66c0fb88df13fb5be7 Mon Sep 17 00:00:00 2001 From: mark_story Date: Fri, 27 Aug 2010 23:54:00 -0400 Subject: [PATCH 029/166] Replacing cakeError with exceptions in Scaffold. --- cake/libs/controller/scaffold.php | 18 +++++------------- 1 file changed, 5 insertions(+), 13 deletions(-) diff --git a/cake/libs/controller/scaffold.php b/cake/libs/controller/scaffold.php index a54a6f82b..019089454 100644 --- a/cake/libs/controller/scaffold.php +++ b/cake/libs/controller/scaffold.php @@ -169,9 +169,7 @@ class Scaffold extends Object { $this->modelKey = $controller->modelKey; if (!is_object($this->controller->{$this->modelClass})) { - return $this->cakeError('missingModel', array(array( - 'className' => $this->modelClass, 'webroot' => '', 'base' => $controller->base - ))); + throw new MissingModelException($this->modelClass); } $this->ScaffoldModel =& $this->controller->{$this->modelClass}; @@ -485,17 +483,11 @@ class Scaffold extends Object { break; } } else { - return $this->cakeError('missingAction', array(array( - 'className' => $this->controller->name . "Controller", - 'base' => $this->controller->base, - 'action' => $this->action, - 'webroot' => $this->controller->webroot - ))); + $message = sprintf('%s::%s()', $this->controller->name . "Controller", $this->action); + throw new MissingActionException($message); } } else { - return $this->cakeError('missingDatabase', array(array( - 'webroot' => $this->controller->webroot - ))); + throw new MissingDatabaseException($this->ScaffoldModel->useDbConfig); } } @@ -605,6 +597,6 @@ class ScaffoldView extends ThemeView { return LIBS . 'view' . DS . 'errors' . DS . 'scaffold_error.ctp'; } - return $this->_missingView($paths[0] . $name . $this->ext, 'missingView'); + throw new MissingViewException($paths[0] . $name . $this->ext); } } From 0683dc43ff657dcf0f45793178ee71c2aa55a18c Mon Sep 17 00:00:00 2001 From: mark_story Date: Fri, 27 Aug 2010 23:54:22 -0400 Subject: [PATCH 030/166] Replacing cakeError calls with exceptions in ConnectionManager and Model. --- cake/libs/model/connection_manager.php | 6 +++++- cake/libs/model/model.php | 2 +- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/cake/libs/model/connection_manager.php b/cake/libs/model/connection_manager.php index 34a355108..3011cb740 100644 --- a/cake/libs/model/connection_manager.php +++ b/cake/libs/model/connection_manager.php @@ -222,7 +222,7 @@ class ConnectionManager { $this->_connectionsEnum[$name] = $this->__connectionData($config); } } else { - $this->cakeError('missingConnection', array(array('className' => 'ConnectionManager'))); + throw new MissingConnectionException('ConnectionManager'); } } @@ -274,3 +274,7 @@ class ConnectionManager { } } } + + +class MissingDatabaseException extends RuntimeException {} +class MissingConnectionException extends RuntimeException {} \ No newline at end of file diff --git a/cake/libs/model/model.php b/cake/libs/model/model.php index fcb0f122e..04639668b 100644 --- a/cake/libs/model/model.php +++ b/cake/libs/model/model.php @@ -2825,7 +2825,7 @@ class Model extends Object { } if (empty($db) || !is_object($db)) { - return $this->cakeError('missingConnection', array(array('className' => $this->alias))); + throw new MissingConnectionException($this->useDbConfig); } } From f0d938c1cb1f7faa2b3641ff568f5536d10c3eb0 Mon Sep 17 00:00:00 2001 From: mark_story Date: Fri, 27 Aug 2010 23:59:29 -0400 Subject: [PATCH 031/166] Fixing failing tests in scaffold. --- cake/tests/cases/libs/controller/scaffold.test.php | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/cake/tests/cases/libs/controller/scaffold.test.php b/cake/tests/cases/libs/controller/scaffold.test.php index 5134427f8..ad1526216 100644 --- a/cake/tests/cases/libs/controller/scaffold.test.php +++ b/cake/tests/cases/libs/controller/scaffold.test.php @@ -509,14 +509,14 @@ class ScaffoldViewTest extends CakeTestCase { new Scaffold($this->Controller, $params); $result = ob_get_clean(); - $this->assertPattern('/
assertPattern('/Edit Scaffold Mock<\/legend>/', $result); + $this->assertContains('assertContains('Edit Scaffold Mock', $result); - $this->assertPattern('/input type="hidden" name="data\[ScaffoldMock\]\[id\]" value="1" id="ScaffoldMockId"/', $result); - $this->assertPattern('/select name="data\[ScaffoldMock\]\[user_id\]" id="ScaffoldMockUserId"/', $result); - $this->assertPattern('/input name="data\[ScaffoldMock\]\[title\]" type="text" maxlength="255" value="First Article" id="ScaffoldMockTitle"/', $result); - $this->assertPattern('/input name="data\[ScaffoldMock\]\[published\]" type="text" maxlength="1" value="Y" id="ScaffoldMockPublished"/', $result); - $this->assertPattern('/textarea name="data\[ScaffoldMock\]\[body\]" cols="30" rows="6" id="ScaffoldMockBody"/', $result); + $this->assertContains('input type="hidden" name="data[ScaffoldMock][id]" value="1" id="ScaffoldMockId"', $result); + $this->assertContains('select name="data[ScaffoldMock][user_id]" id="ScaffoldMockUserId"', $result); + $this->assertContains('input name="data[ScaffoldMock][title]" maxlength="255" type="text" value="First Article" id="ScaffoldMockTitle"', $result); + $this->assertContains('input name="data[ScaffoldMock][published]" maxlength="1" type="text" value="Y" id="ScaffoldMockPublished"', $result); + $this->assertContains('textarea name="data[ScaffoldMock][body]" cols="30" rows="6" id="ScaffoldMockBody"', $result); $this->assertPattern('/
  • ]*>Delete<\/a>\s*<\/li>/', $result); } From dc67b9cacc91c116f0b978f526be1b22c0d25e6f Mon Sep 17 00:00:00 2001 From: mark_story Date: Sat, 28 Aug 2010 00:08:35 -0400 Subject: [PATCH 032/166] Moving all the exceptions into one file for the short term. --- cake/bootstrap.php | 1 + cake/console/libs/task_collection.php | 6 --- cake/dispatcher.php | 7 --- cake/libs/controller/component_collection.php | 8 +-- cake/libs/model/behavior_collection.php | 8 +-- cake/libs/model/connection_manager.php | 6 +-- cake/libs/model/model.php | 50 ------------------- cake/libs/view/view.php | 3 -- 8 files changed, 4 insertions(+), 85 deletions(-) diff --git a/cake/bootstrap.php b/cake/bootstrap.php index 8f9d640ec..7a05b8b01 100644 --- a/cake/bootstrap.php +++ b/cake/bootstrap.php @@ -27,6 +27,7 @@ error_reporting(E_ALL & ~E_DEPRECATED); require CORE_PATH . 'cake' . DS . 'basics.php'; $TIME_START = microtime(true); require CORE_PATH . 'cake' . DS . 'config' . DS . 'paths.php'; +require LIBS . 'exceptions.php'; require LIBS . 'object.php'; require LIBS . 'inflector.php'; require LIBS . 'configure.php'; diff --git a/cake/console/libs/task_collection.php b/cake/console/libs/task_collection.php index 5d196d7bb..d1ec21733 100644 --- a/cake/console/libs/task_collection.php +++ b/cake/console/libs/task_collection.php @@ -85,9 +85,3 @@ class TaskCollection extends ObjectCollection { } } -/** - * Exceptions used by the TaskCollection. - */ -class MissingTaskFileException extends RuntimeException { } - -class MissingTaskClassException extends RuntimeException { } \ No newline at end of file diff --git a/cake/dispatcher.php b/cake/dispatcher.php index dfb37a63d..f48643a70 100644 --- a/cake/dispatcher.php +++ b/cake/dispatcher.php @@ -652,10 +652,3 @@ class Dispatcher extends Object { header($header); } } - -/** - * Runtime Exceptions for dispatcher. - */ -class MissingControllerException extends RuntimeException {} -class MissingActionException extends RuntimeException {} -class PrivateActionException extends RuntimeException {} diff --git a/cake/libs/controller/component_collection.php b/cake/libs/controller/component_collection.php index 72aa13692..f0fc314e8 100644 --- a/cake/libs/controller/component_collection.php +++ b/cake/libs/controller/component_collection.php @@ -67,10 +67,4 @@ class ComponentCollection extends ObjectCollection { return $this->_loaded[$name]; } -} -/** - * Exceptions used by the ComponentCollection. - */ -class MissingComponentFileException extends RuntimeException { } - -class MissingComponentClassException extends RuntimeException { } \ No newline at end of file +} \ No newline at end of file diff --git a/cake/libs/model/behavior_collection.php b/cake/libs/model/behavior_collection.php index aaeeb6da7..8895a798a 100644 --- a/cake/libs/model/behavior_collection.php +++ b/cake/libs/model/behavior_collection.php @@ -273,10 +273,4 @@ class BehaviorCollection extends ObjectCollection { return $this->__methods; } -} - -/** - * Runtime Exceptions for behaviors - */ -class MissingBehaviorFileException extends RuntimeException { } -class MissingBehaviorClassException extends RuntimeException { } \ No newline at end of file +} \ No newline at end of file diff --git a/cake/libs/model/connection_manager.php b/cake/libs/model/connection_manager.php index 3011cb740..1937663ff 100644 --- a/cake/libs/model/connection_manager.php +++ b/cake/libs/model/connection_manager.php @@ -273,8 +273,4 @@ class ConnectionManager { session_write_close(); } } -} - - -class MissingDatabaseException extends RuntimeException {} -class MissingConnectionException extends RuntimeException {} \ No newline at end of file +} \ No newline at end of file diff --git a/cake/libs/model/model.php b/cake/libs/model/model.php index 04639668b..43fec9794 100644 --- a/cake/libs/model/model.php +++ b/cake/libs/model/model.php @@ -3064,53 +3064,3 @@ class Model extends Object { } } -/** -* Exception class to be thrown when a database table is not found in the datasource -* -*/ -class MissingTableException extends RuntimeException { -/** - * The name of the model wanting to load the database table - * - * @var string - */ - protected $model; -/** - * The name of the missing table - * - * @var string - */ - protected $table; - -/** - * Exception costructor - * - * @param string $model The name of the model wanting to load the database table - * @param string $table The name of the missing table - * @return void - */ - public function __construct($model, $table) { - $this->model = $model; - $this->$table = $table; - $message = sprintf(__('Database table %s for model %s was not found.'), $table, $model); - parent::__construct($message); - } - -/** - * Returns the name of the model wanting to load the database table - * - * @return string - */ - public function getModel() { - return $this->model; - } - -/** - * Returns the name of the missing table - * - * @return string - */ - public function getTable() { - return $this->table; - } -} diff --git a/cake/libs/view/view.php b/cake/libs/view/view.php index a8069d361..5fd575818 100644 --- a/cake/libs/view/view.php +++ b/cake/libs/view/view.php @@ -855,6 +855,3 @@ class View extends Object { return $this->__paths; } } - -class MissingViewException extends RuntimeException { } -class MissingLayoutException extends RuntimeException { } From c76f205bcbb54c1e9b1a44abf6844a86e8d8ce90 Mon Sep 17 00:00:00 2001 From: mark_story Date: Sat, 28 Aug 2010 00:18:46 -0400 Subject: [PATCH 033/166] Adding exceptions file. --- cake/libs/exceptions.php | 108 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 108 insertions(+) create mode 100644 cake/libs/exceptions.php diff --git a/cake/libs/exceptions.php b/cake/libs/exceptions.php new file mode 100644 index 000000000..1a3c62f90 --- /dev/null +++ b/cake/libs/exceptions.php @@ -0,0 +1,108 @@ +model = $model; + $this->$table = $table; + $message = sprintf(__('Database table %s for model %s was not found.'), $table, $model); + parent::__construct($message); + } + +/** + * Returns the name of the model wanting to load the database table + * + * @return string + */ + public function getModel() { + return $this->model; + } + +/** + * Returns the name of the missing table + * + * @return string + */ + public function getTable() { + return $this->table; + } +} \ No newline at end of file From e4545dbe5ec6a8a6ea9b320c85f67ab97b66b2de Mon Sep 17 00:00:00 2001 From: mark_story Date: Sat, 28 Aug 2010 00:19:09 -0400 Subject: [PATCH 034/166] Fixing failing tests in Dispatcher.test. --- cake/dispatcher.php | 6 +--- cake/libs/view/helper_collection.php | 2 +- cake/tests/cases/dispatcher.test.php | 47 +--------------------------- 3 files changed, 3 insertions(+), 52 deletions(-) diff --git a/cake/dispatcher.php b/cake/dispatcher.php index 1ca1f9f9b..e35534d8f 100644 --- a/cake/dispatcher.php +++ b/cake/dispatcher.php @@ -317,11 +317,7 @@ class Dispatcher { } $controller = null; $view = new View($controller); - $return = $view->renderCache($filename, microtime(true)); - if (!$return) { - ClassRegistry::removeObject('view'); - } - return $return; + return $view->renderCache($filename, microtime(true)); } } return false; diff --git a/cake/libs/view/helper_collection.php b/cake/libs/view/helper_collection.php index fd87c7d4e..74683db93 100644 --- a/cake/libs/view/helper_collection.php +++ b/cake/libs/view/helper_collection.php @@ -62,7 +62,7 @@ class HelperCollection extends ObjectCollection { } $this->_loaded[$name] = new $helperClass($this->_View, $settings); - $vars = array('base', 'webroot', 'here', 'params', 'action', 'data', 'theme', 'plugin'); + $vars = array('request', 'base', 'webroot', 'here', 'params', 'action', 'data', 'theme', 'plugin'); foreach ($vars as $var) { $this->_loaded[$name]->{$var} = $this->_View->{$var}; } diff --git a/cake/tests/cases/dispatcher.test.php b/cake/tests/cases/dispatcher.test.php index bbda338e3..5348e01a1 100644 --- a/cake/tests/cases/dispatcher.test.php +++ b/cake/tests/cases/dispatcher.test.php @@ -852,7 +852,6 @@ class DispatcherTest extends CakeTestCase { Router::reload(); Configure::write('App.baseUrl', '/index.php'); $Dispatcher = new TestDispatcher(); - Configure::write('App.baseUrl','/index.php'); $url = array('controller' => 'pages', 'action' => 'display'); $controller = $Dispatcher->dispatch($url, array( @@ -866,7 +865,7 @@ class DispatcherTest extends CakeTestCase { $expected = array('0' => 'home', 'param' => 'value', 'param2' => 'value2'); $this->assertIdentical($expected, $controller->passedArgs); - $this->assertEqual($Dispatcher->base . '/pages/display/home/param:value/param2:value2', $Dispatcher->here); + $this->assertEqual($Dispatcher->request->base . '/pages/display/home/param:value/param2:value2', $Dispatcher->request->here); } /** @@ -1583,50 +1582,6 @@ class DispatcherTest extends CakeTestCase { unlink($filename); } -/** - * test that cached() registers a view and un-registers it. Tests - * that helpers using don't fail - * - * @return void - */ - function testCachedRegisteringViewObject() { - Configure::write('Cache.disable', false); - Configure::write('Cache.check', true); - Configure::write('debug', 2); - - $_POST = array(); - $_SERVER['PHP_SELF'] = '/'; - - Router::reload(); - App::build(array( - 'views' => array(TEST_CAKE_CORE_INCLUDE_PATH . 'tests' . DS . 'test_app' . DS . 'views'. DS) - )); - - $dispatcher = new TestDispatcher(); - $dispatcher->response = $this->getMock('CakeResponse', array('_sendHeader')); - $dispatcher->base = false; - - $url = 'test_cached_pages/cache_form'; - ob_start(); - $dispatcher->dispatch($url); - $out = ob_get_clean(); - - ClassRegistry::flush(); - - ob_start(); - $dispatcher->cached($url); - $cached = ob_get_clean(); - - $result = str_replace(array("\t", "\r\n", "\n"), "", $out); - $cached = preg_replace('//', '', $cached); - $expected = str_replace(array("\t", "\r\n", "\n"), "", $cached); - - $this->assertEqual($result, $expected); - $filename = $this->__cachePath($dispatcher->here); - @unlink($filename); - ClassRegistry::flush(); - } - /** * testHttpMethodOverrides method * From dcb7a167b452f402afdf79e3716430070f62b59b Mon Sep 17 00:00:00 2001 From: mark_story Date: Sat, 28 Aug 2010 00:29:50 -0400 Subject: [PATCH 035/166] Fixing controller test cases. --- .../cases/libs/controller/controller.test.php | 20 +++++++++---------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/cake/tests/cases/libs/controller/controller.test.php b/cake/tests/cases/libs/controller/controller.test.php index a50669d3e..1f0d2a765 100644 --- a/cake/tests/cases/libs/controller/controller.test.php +++ b/cake/tests/cases/libs/controller/controller.test.php @@ -1035,8 +1035,7 @@ class ControllerTest extends CakeTestCase { $Controller = new Controller(null); $Controller->response = $this->getMock('CakeResponse', array('header', 'statusCode')); - $Controller->Component = new Component(); - $Controller->Component->init($Controller); + $Controller->Components = $this->getMock('ComponentCollection'); $Controller->response->expects($this->once())->method('statusCode') ->with($code); @@ -1077,7 +1076,7 @@ class ControllerTest extends CakeTestCase { function testRedirectTriggeringComponentsReturnNull() { $Controller = new Controller(null); $Controller->response = $this->getMock('CakeResponse', array('header', 'statusCode')); - $Controller->Component = $this->getMock('Component'); + $Controller->Components = $this->getMock('ComponentCollection'); $Controller->Components->expects($this->once())->method('trigger') ->will($this->returnValue(null)); @@ -1099,7 +1098,7 @@ class ControllerTest extends CakeTestCase { function testRedirectBeforeRedirectModifyingParams() { $Controller = new Controller(null); $Controller->response = $this->getMock('CakeResponse', array('header', 'statusCode')); - $Controller->Component = $this->getMock('Component'); + $Controller->Components = $this->getMock('ComponentCollection'); $Controller->Components->expects($this->once())->method('trigger') ->will($this->returnValue(array('http://book.cakephp.org'))); @@ -1136,11 +1135,11 @@ class ControllerTest extends CakeTestCase { $Controller->Components->expects($this->once())->method('trigger') ->will($this->returnValue($return)); - $Controller->expects($this->at(0))->method('header') - ->with('HTTP/1.1 302 Found'); + $Controller->response->expects($this->at(0))->method('header') + ->with('Location', 'http://example.com/test/2'); - $Controller->expects($this->at(1))->method('header') - ->with('Location: http://example.com/test/2'); + $Controller->response->expects($this->at(1))->method('statusCode') + ->with(302); $Controller->expects($this->never())->method('_stop'); $Controller->redirect('http://cakephp.org', 301); @@ -1438,16 +1437,15 @@ class ControllerTest extends CakeTestCase { $Controller->modelClass='ControllerPost'; $Controller->params['url'] = array('ext' => 'rss'); $Controller->constructClasses(); - $Controller->Component->initialize($Controller); + $Controller->Components->trigger('initialize', array(&$Controller)); $Controller->beforeFilter(); - $Controller->Component->startup($Controller); + $Controller->Components->trigger('startup', array(&$Controller)); $this->assertEqual($Controller->RequestHandler->prefers(), 'rss'); unset($Controller); } /** ->>>>>>> 2.0-request * testControllerHttpCodes method * * @access public From d8b2bcdf06cc33bacf1943c2479580d82a3fadfa Mon Sep 17 00:00:00 2001 From: mark_story Date: Sat, 28 Aug 2010 00:40:12 -0400 Subject: [PATCH 036/166] Making view + helpers groups pass. --- cake/libs/view/helper.php | 7 ++++--- cake/tests/cases/libs/view/helpers/cache.test.php | 7 +++---- cake/tests/cases/libs/view/view.test.php | 5 +++-- 3 files changed, 10 insertions(+), 9 deletions(-) diff --git a/cake/libs/view/helper.php b/cake/libs/view/helper.php index 7e9335a50..4ffd1c9c7 100644 --- a/cake/libs/view/helper.php +++ b/cake/libs/view/helper.php @@ -164,6 +164,7 @@ class Helper extends Object { public function __construct(View $View, $settings = array()) { $this->_View = $View; $this->params = $View->params; + $this->request = $View->request; if (!empty($this->helpers)) { $this->_helperMap = ObjectCollection::normalizeObjectArray($this->helpers); } @@ -722,13 +723,13 @@ class Helper extends Object { $data = $this->request->data; $entity = $this->_View->entity(); - if (!empty($this->data) && !empty($entity)) { - $result = Set::extract($this->data, join('.', $entity)); + if (!empty($data) && !empty($entity)) { + $result = Set::extract($data, join('.', $entity)); } $habtmKey = $this->field(); if (empty($result) && isset($data[$habtmKey][$habtmKey])) { - $result = $this->data[$habtmKey][$habtmKey]; + $result = $data[$habtmKey][$habtmKey]; } elseif (empty($result) && isset($data[$habtmKey]) && is_array($data[$habtmKey])) { if (ClassRegistry::isKeySet($habtmKey)) { $model =& ClassRegistry::getObject($habtmKey); diff --git a/cake/tests/cases/libs/view/helpers/cache.test.php b/cake/tests/cases/libs/view/helpers/cache.test.php index 62c51e5b6..5bd83fc41 100644 --- a/cake/tests/cases/libs/view/helpers/cache.test.php +++ b/cake/tests/cases/libs/view/helpers/cache.test.php @@ -373,7 +373,7 @@ class CacheHelperTest extends CakeTestCase { Router::reload(); $this->Controller->cache_parsing(); - $this->Controller->params = array( + $this->Controller->request->addParams(array( 'controller' => 'cache_test', 'action' => 'cache_parsing', 'url' => array(), @@ -382,12 +382,11 @@ class CacheHelperTest extends CakeTestCase { 'name' => 'mark', 'ice' => 'cream' ) - ); + )); $this->Controller->cacheAction = array( 'cache_parsing' => 21600 ); - $this->Controller->here = '/cache_test/cache_parsing/1/2/name:mark/ice:cream'; - $this->Controller->action = 'cache_parsing'; + $this->Controller->request->here = '/cache_test/cache_parsing/1/2/name:mark/ice:cream'; $View = new View($this->Controller); $result = $View->render('index'); diff --git a/cake/tests/cases/libs/view/view.test.php b/cake/tests/cases/libs/view/view.test.php index 58ae5b007..8faf32dee 100644 --- a/cake/tests/cases/libs/view/view.test.php +++ b/cake/tests/cases/libs/view/view.test.php @@ -228,7 +228,8 @@ class ViewTest extends CakeTestCase { function setUp() { Router::reload(); $this->Controller = new Controller(); - $this->PostsController = new ViewPostsController(); + $request = $this->getMock('CakeRequest'); + $this->PostsController = new ViewPostsController($request); $this->PostsController->viewPath = 'posts'; $this->PostsController->index(); $this->View = new View($this->PostsController); @@ -700,7 +701,7 @@ class ViewTest extends CakeTestCase { $_check = Configure::read('Cache.check'); Configure::write('Cache.check', true); - $Controller = new ViewPostsController(); + $Controller = new ViewPostsController($this->getMock('CakeRequest')); $Controller->cacheAction = '1 day'; $View = new View($Controller); $View->helpers = array('Cache', 'Html', 'Session'); From a2186c412a3c8b2056ae2206cd121f3d15c8e0f3 Mon Sep 17 00:00:00 2001 From: mark_story Date: Sat, 28 Aug 2010 00:59:07 -0400 Subject: [PATCH 037/166] Updating doc blocks for CakeRequest and CakeResponse. --- cake/libs/cake_request.php | 18 ++++++++++++++---- cake/libs/cake_response.php | 19 ++++++++++++------- 2 files changed, 26 insertions(+), 11 deletions(-) diff --git a/cake/libs/cake_request.php b/cake/libs/cake_request.php index d3828e15b..26c769a00 100644 --- a/cake/libs/cake_request.php +++ b/cake/libs/cake_request.php @@ -3,7 +3,7 @@ * A class that helps wrap Request information and particulars about a single request. * Provides methods commonly used to introspect on the request headers and request body. * - * Has both an Array and Object interface. You can access framework parameters using indexes + * Has both an Array and Object interface. You can access framework parameters using indexes: * * `$request['controller']` or `$request->controller`. * @@ -428,6 +428,8 @@ class CakeRequest implements ArrayAccess { /** * Magic get method allows access to parsed routing parameters directly on the object. * + * Allows access to `$this->params['controller']` via `$this->controller` + * * @param string $name The property being accessed. * @return mixed Either the value of the parameter or null. */ @@ -441,7 +443,7 @@ class CakeRequest implements ArrayAccess { /** * Check whether or not a Request is a certain type. Uses the built in detection rules * as well as additional rules defined with CakeRequest::addDetector(). Any detector can be called - * with `is($type)` or `is$Type()`. + * as `is($type)` or `is$Type()`. * * @param string $type The type of request you want to check. * @return boolean Whether or not the request is the type you are checking. @@ -513,7 +515,7 @@ class CakeRequest implements ArrayAccess { } /** - * Add parameters to the request's parsed parameter set. + * Add parameters to the request's parsed parameter set. This will overwrite any existing parameters * * @param array $params Array of parameters to merge in * @return The current object, you can chain this method. @@ -524,7 +526,7 @@ class CakeRequest implements ArrayAccess { } /** - * Add paths to the requests' paths vars + * Add paths to the requests' paths vars. This will overwrite any existing paths. * * @param array $paths Array of paths to merge in * @return the current object, you can chain this method. @@ -597,6 +599,14 @@ class CakeRequest implements ArrayAccess { * Find out which content types the client accepts or check if they accept a * particular type of content. * + * #### Get all types: + * + * `$request->accepts();` + * + * #### Check for a single type: + * + * `$request->accepts('json');` + * * @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. diff --git a/cake/libs/cake_response.php b/cake/libs/cake_response.php index acd68158e..b68aa65d3 100644 --- a/cake/libs/cake_response.php +++ b/cake/libs/cake_response.php @@ -1,7 +1,9 @@ _headers['Location']) && $this->_status === 200) { @@ -349,10 +352,11 @@ class CakeResponse { } /** -* Sends a header to the client +* Sends a header to the client. * * @param $name the header name * @param $value the header value +* @return void */ protected function _sendHeader($name, $value = null) { if (is_null($value)) { @@ -363,9 +367,10 @@ class CakeResponse { } /** -* Sends a content string to the client +* Sends a content string to the client. * * @param $content string to send as response body +* @return void */ protected function _sendContent($content) { echo $content; @@ -584,7 +589,7 @@ class CakeResponse { } /** - * Sets the correct headers to instruct the client to not cache te response + * Sets the correct headers to instruct the client to not cache the response * * @return void */ @@ -598,7 +603,7 @@ class CakeResponse { } /** - * Sets the correct headers to instruct the client to cache the response + * Sets the correct headers to instruct the client to cache the response. * * @param string $since a valid time since the response text has not been modified * @param string $time a valid time for cache expiry From 93b80042f8fc24fcc550a9db9600a5bc42d30a80 Mon Sep 17 00:00:00 2001 From: predominant Date: Sat, 28 Aug 2010 15:01:43 +1000 Subject: [PATCH 038/166] Fix failing scaffold tests. --- cake/tests/cases/libs/controller/scaffold.test.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cake/tests/cases/libs/controller/scaffold.test.php b/cake/tests/cases/libs/controller/scaffold.test.php index 100ed67b8..1d08a91de 100644 --- a/cake/tests/cases/libs/controller/scaffold.test.php +++ b/cake/tests/cases/libs/controller/scaffold.test.php @@ -789,7 +789,7 @@ class ScaffoldTest extends CakeTestCase { $this->Controller->theme = 'test_theme'; $this->Controller->view = 'Theme'; $this->Controller->constructClasses(); - $Scaffold =& new TestScaffoldMock($this->Controller, array()); + $Scaffold =& new TestScaffoldMock($this->Controller, new CakeRequest()); $this->assertEqual($this->Controller->view, 'Scaffold'); } From c1209a1a7a0b47e9d5a20dd61bec208afd4d642a Mon Sep 17 00:00:00 2001 From: predominant Date: Sat, 28 Aug 2010 15:15:23 +1000 Subject: [PATCH 039/166] Added RequestObject output in place of Controller:$output whicch no longer exists. --- cake/tests/cases/libs/controller/pages_controller.test.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cake/tests/cases/libs/controller/pages_controller.test.php b/cake/tests/cases/libs/controller/pages_controller.test.php index c913192d4..e61ba2018 100644 --- a/cake/tests/cases/libs/controller/pages_controller.test.php +++ b/cake/tests/cases/libs/controller/pages_controller.test.php @@ -60,12 +60,12 @@ class PagesControllerTest extends CakeTestCase { $Pages->viewPath = 'posts'; $Pages->display('index'); - $this->assertPattern('/posts index/', $Pages->output); + $this->assertPattern('/posts index/', $Pages->getResponse()->body()); $this->assertEqual($Pages->viewVars['page'], 'index'); $Pages->viewPath = 'themed'; $Pages->display('test_theme', 'posts', 'index'); - $this->assertPattern('/posts index themed view/', $Pages->output); + $this->assertPattern('/posts index themed view/', $Pages->getResponse()->body()); $this->assertEqual($Pages->viewVars['page'], 'test_theme'); $this->assertEqual($Pages->viewVars['subpage'], 'posts'); } From f7addabcf2ff4b882406cc2444378061bd39c31d Mon Sep 17 00:00:00 2001 From: predominant Date: Sat, 28 Aug 2010 15:27:12 +1000 Subject: [PATCH 040/166] Whitespace removal --- cake/libs/controller/components/request_handler.php | 1 - 1 file changed, 1 deletion(-) diff --git a/cake/libs/controller/components/request_handler.php b/cake/libs/controller/components/request_handler.php index 917f42ad8..6b69bde6a 100644 --- a/cake/libs/controller/components/request_handler.php +++ b/cake/libs/controller/components/request_handler.php @@ -480,7 +480,6 @@ class RequestHandlerComponent extends Component { return ($types[0] == $accepts[0]); } - $intersect = array_values(array_intersect($accepts, $types)); if (empty($intersect)) { return false; From 5de88c0f0252cb321ef9b8aa09fcdc931709db3a Mon Sep 17 00:00:00 2001 From: mark_story Date: Sat, 28 Aug 2010 01:37:39 -0400 Subject: [PATCH 041/166] Moving CakeErrorController to its own file. --- .../libs/controller/cake_error_controller.php | 34 +++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 cake/libs/controller/cake_error_controller.php diff --git a/cake/libs/controller/cake_error_controller.php b/cake/libs/controller/cake_error_controller.php new file mode 100644 index 000000000..8d98561bc --- /dev/null +++ b/cake/libs/controller/cake_error_controller.php @@ -0,0 +1,34 @@ +_set(Router::getPaths()); + $this->request = $this->params = Router::getRequest(); + $this->constructClasses(); + $this->Components->trigger('initialize', array(&$this)); + $this->_set(array('cacheAction' => false, 'viewPath' => 'errors')); + } +} \ No newline at end of file From 9b3e91089aefe78d2d9ecbbd5586ecc6ccdae18f Mon Sep 17 00:00:00 2001 From: mark_story Date: Sat, 28 Aug 2010 01:38:03 -0400 Subject: [PATCH 042/166] Adding omitted types of exceptions. --- cake/libs/exceptions.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/cake/libs/exceptions.php b/cake/libs/exceptions.php index 1a3c62f90..3e0f83b9b 100644 --- a/cake/libs/exceptions.php +++ b/cake/libs/exceptions.php @@ -19,6 +19,9 @@ * @license MIT License (http://www.opensource.org/licenses/mit-license.php) */ +class Error404Exception extends RuntimeException { } +class Error500Exception extends RuntimeException { } + /* * Exceptions used by Dispatcher */ From 04d3353ee4e0c1ca617fe185fa496eee9754843e Mon Sep 17 00:00:00 2001 From: predominant Date: Sat, 28 Aug 2010 15:38:48 +1000 Subject: [PATCH 043/166] Adding access specifiers to methods --- cake/libs/controller/components/request_handler.php | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/cake/libs/controller/components/request_handler.php b/cake/libs/controller/components/request_handler.php index 6b69bde6a..6418ab3d5 100644 --- a/cake/libs/controller/components/request_handler.php +++ b/cake/libs/controller/components/request_handler.php @@ -392,10 +392,9 @@ class RequestHandlerComponent extends Component { * types the client accepts. If a string is passed, returns true * if the client accepts it. If an array is passed, returns true * if the client accepts one or more elements in the array. - * @access public * @see RequestHandlerComponent::setContent() */ - function accepts($type = null) { + public function accepts($type = null) { $accepted = $this->request->accepts(); if ($type == null) { @@ -455,10 +454,9 @@ class RequestHandlerComponent extends Component { * 'html', 'xml', 'js', etc. * @return mixed If $type is null or not provided, the first content-type in the * list, based on preference, is returned. - * @access public * @see RequestHandlerComponent::setContent() */ - function prefers($type = null) { + public function prefers($type = null) { $accepts = $this->accepts(); if ($type == null) { @@ -493,11 +491,10 @@ class RequestHandlerComponent extends Component { * @param object $controller A reference to a controller object * @param string $type Type of response to send (e.g: 'ajax') * @return void - * @access public * @see RequestHandlerComponent::setContent() * @see RequestHandlerComponent::respondAs() */ - function renderAs(&$controller, $type) { + public function renderAs(&$controller, $type) { $options = array('charset' => 'UTF-8'); if (Configure::read('App.encoding') !== null) { @@ -547,10 +544,9 @@ class RequestHandlerComponent extends Component { * @return boolean Returns false if the friendly type name given in $type does * not exist in the type map, or if the Content-type header has * already been set by this method. - * @access public * @see RequestHandlerComponent::setContent() */ - function respondAs($type, $options = array()) { + public function respondAs($type, $options = array()) { $defaults = array('index' => null, 'charset' => null, 'attachment' => false); $options = $options + $defaults; @@ -628,5 +624,4 @@ class RequestHandlerComponent extends Component { } return null; } - } From 26f4ad4da181ec931195d21feaa5198f6ffa2aef Mon Sep 17 00:00:00 2001 From: mark_story Date: Sat, 28 Aug 2010 01:39:02 -0400 Subject: [PATCH 044/166] Modifying bootstrap so it sets a default exception handler. Making a ghetto implementation of exception handling. Adding a crude test case, adding incomplete markers to all other tests. --- cake/bootstrap.php | 2 + cake/libs/error.php | 86 +++++++++------------------- cake/tests/cases/libs/error.test.php | 35 ++++++++++- 3 files changed, 62 insertions(+), 61 deletions(-) diff --git a/cake/bootstrap.php b/cake/bootstrap.php index 7a05b8b01..05ac95ef3 100644 --- a/cake/bootstrap.php +++ b/cake/bootstrap.php @@ -34,4 +34,6 @@ require LIBS . 'configure.php'; require LIBS . 'set.php'; require LIBS . 'cache.php'; Configure::bootstrap(); +require LIBS . 'error.php'; +set_exception_handler(array('ErrorHandler', 'handleException')); require CAKE . 'dispatcher.php'; diff --git a/cake/libs/error.php b/cake/libs/error.php index 78060fd81..0f45b7a27 100644 --- a/cake/libs/error.php +++ b/cake/libs/error.php @@ -19,41 +19,6 @@ * @since CakePHP(tm) v 0.10.5.1732 * @license MIT License (http://www.opensource.org/licenses/mit-license.php) */ -App::import('Controller', 'App'); - -/** - * Error Handling Controller - * - * Controller used by ErrorHandler to render error views. - * - * @package cake - * @subpackage cake.cake.libs - */ -class CakeErrorController extends AppController { - public $name = 'CakeError'; - -/** - * Uses Property - * - * @var array - */ - public $uses = array(); - -/** - * __construct - * - * @access public - * @return void - */ - function __construct() { - parent::__construct(); - $this->_set(Router::getPaths()); - $this->request = $this->params = Router::getRequest(); - $this->constructClasses(); - $this->Component->initialize($this); - $this->_set(array('cacheAction' => false, 'viewPath' => 'errors')); - } -} /** * Error Handler. @@ -65,7 +30,7 @@ class CakeErrorController extends AppController { * @package cake * @subpackage cake.cake.libs */ -class ErrorHandler extends Object { +class ErrorHandler { /** * Controller instance. @@ -81,39 +46,35 @@ class ErrorHandler extends Object { * @param string $method Method producing the error * @param array $messages Error messages */ - function __construct($method, $messages) { - App::import('Core', 'Sanitize'); + function __construct(Exception $exception) { static $__previousError = null; + App::import('Core', 'Sanitize'); + App::import('Controller', 'CakeError'); - if ($__previousError != array($method, $messages)) { - $__previousError = array($method, $messages); + if ($__previousError != $exception) { + $__previousError = $exception; $this->controller = new CakeErrorController(); } else { $this->controller = new Controller(); $this->controller->viewPath = 'errors'; } - $options = array('escape' => false); - $messages = Sanitize::clean($messages, $options); - - if (!isset($messages[0])) { - $messages = array($messages); - } if (method_exists($this->controller, 'apperror')) { - return $this->controller->appError($method, $messages); + return $this->controller->appError($exception); } + $method = Inflector::variable(str_replace('Exception', '', get_class($exception))); - if (!in_array(strtolower($method), array_map('strtolower', get_class_methods($this)))) { + if (!in_array($method, get_class_methods($this))) { $method = 'error'; } if ($method !== 'error') { if (Configure::read('debug') == 0) { $parentClass = get_parent_class($this); - if (strtolower($parentClass) != 'errorhandler') { + if ($parentClass != 'ErrorHandler') { $method = 'error404'; } - $parentMethods = array_map('strtolower', get_class_methods($parentClass)); - if (in_array(strtolower($method), $parentMethods)) { + $parentMethods = get_class_methods($parentClass); + if (in_array($method, $parentMethods)) { $method = 'error404'; } if (isset($code) && $code == 500) { @@ -121,8 +82,19 @@ class ErrorHandler extends Object { } } } - $this->dispatchMethod($method, $messages); - $this->_stop(); + call_user_func_array(array($this, $method), array($exception)); + } + +/** + * Set as the default exception handler by the CakePHP bootstrap process. + * If you wish you use a custom default exception handler use set_exception_handler() + * in your app/config/bootstrap.php. + * + * @return void + * @see http://php.net/manual/en/function.set-exception-handler.php + */ + public static function handleException(Exception $exception) { + $error = new ErrorHandler($exception); } /** @@ -146,14 +118,12 @@ class ErrorHandler extends Object { * * @param array $params Parameters for controller */ - public function error404($params) { - extract($params, EXTR_OVERWRITE); - + public function error404($exception) { if (!isset($url)) { $url = $this->controller->here; } $url = Router::normalize($url); - $this->controller->header("HTTP/1.0 404 Not Found"); + $this->controller->response->statusCode(404); $this->controller->set(array( 'code' => '404', 'name' => __('Not Found'), @@ -437,6 +407,6 @@ class ErrorHandler extends Object { protected function _outputMessage($template) { $this->controller->render($template); $this->controller->afterFilter(); - echo $this->controller->output; + $this->controller->response->send(); } } diff --git a/cake/tests/cases/libs/error.test.php b/cake/tests/cases/libs/error.test.php index df0a962f0..532deced0 100644 --- a/cake/tests/cases/libs/error.test.php +++ b/cake/tests/cases/libs/error.test.php @@ -20,9 +20,6 @@ if (class_exists('TestErrorHandler')) { return; } -if (!defined('CAKEPHP_UNIT_TEST_EXECUTION')) { - define('CAKEPHP_UNIT_TEST_EXECUTION', 1); -} /** * BlueberryComponent class @@ -272,6 +269,19 @@ class ErrorHandlerTest extends CakeTestCase { Router::setRequestInfo($request); } +/** + * test handleException generating a page. + * + * @return void + */ + function testHandleException() { + $error = new Error404Exception('Kaboom!'); + ob_start(); + ErrorHandler::handleException($error); + $result = ob_get_clean(); + $this->assertPattern('/Not Found/', $result, 'message missing.'); + } + /** * test that methods declared in an ErrorHandler subclass are not converted * into error404 when debug == 0 @@ -279,6 +289,7 @@ class ErrorHandlerTest extends CakeTestCase { * @return void */ function testSubclassMethodsNotBeingConvertedToError() { + $this->markTestIncomplete('Not implemented now'); $back = Configure::read('debug'); Configure::write('debug', 2); ob_start(); @@ -310,6 +321,7 @@ class ErrorHandlerTest extends CakeTestCase { * @return void */ function testError() { + $this->markTestIncomplete('Not implemented now'); ob_start(); $TestErrorHandler = new TestErrorHandler('error404', array('message' => 'Page not found')); ob_clean(); @@ -331,6 +343,7 @@ class ErrorHandlerTest extends CakeTestCase { * @return void */ function testError404() { + $this->markTestIncomplete('Not implemented now'); App::build(array( 'views' => array(TEST_CAKE_CORE_INCLUDE_PATH . 'libs' . DS . 'view' . DS) ), true); @@ -363,6 +376,7 @@ class ErrorHandlerTest extends CakeTestCase { * @return void */ function testError500() { + $this->markTestIncomplete('Not implemented now'); ob_start(); $TestErrorHandler = new TestErrorHandler('error500', array( 'message' => 'An Internal Error Has Occurred' @@ -386,6 +400,7 @@ class ErrorHandlerTest extends CakeTestCase { * @return void */ function testMissingController() { + $this->markTestIncomplete('Not implemented now'); $this->skipIf(defined('APP_CONTROLLER_EXISTS'), '%s Need a non-existent AppController'); ob_start(); @@ -403,6 +418,7 @@ class ErrorHandlerTest extends CakeTestCase { * @return void */ function testMissingAction() { + $this->markTestIncomplete('Not implemented now'); ob_start(); $TestErrorHandler = new TestErrorHandler('missingAction', array('className' => 'PostsController', 'action' => 'index')); $result = ob_get_clean(); @@ -425,6 +441,7 @@ class ErrorHandlerTest extends CakeTestCase { * @return void */ function testPrivateAction() { + $this->markTestIncomplete('Not implemented now'); ob_start(); $TestErrorHandler = new TestErrorHandler('privateAction', array('className' => 'PostsController', 'action' => '_secretSauce')); $result = ob_get_clean(); @@ -439,6 +456,7 @@ class ErrorHandlerTest extends CakeTestCase { * @return void */ function testMissingTable() { + $this->markTestIncomplete('Not implemented now'); ob_start(); $TestErrorHandler = new TestErrorHandler('missingTable', array('className' => 'Article', 'table' => 'articles')); $result = ob_get_clean(); @@ -454,6 +472,7 @@ class ErrorHandlerTest extends CakeTestCase { * @return void */ function testMissingDatabase() { + $this->markTestIncomplete('Not implemented now'); ob_start(); $TestErrorHandler = new TestErrorHandler('missingDatabase', array()); $result = ob_get_clean(); @@ -469,6 +488,7 @@ class ErrorHandlerTest extends CakeTestCase { * @return void */ function testMissingView() { + $this->markTestIncomplete('Not implemented now'); ob_start(); $TestErrorHandler = new TestErrorHandler('missingView', array('className' => 'Pages', 'action' => 'display', 'file' => 'pages/about.ctp', 'base' => '')); $expected = ob_get_clean(); @@ -483,6 +503,7 @@ class ErrorHandlerTest extends CakeTestCase { * @return void */ function testMissingLayout() { + $this->markTestIncomplete('Not implemented now'); ob_start(); $TestErrorHandler = new TestErrorHandler('missingLayout', array( 'layout' => 'my_layout', 'file' => 'layouts/my_layout.ctp', 'base' => '')); $expected = ob_get_clean(); @@ -497,6 +518,7 @@ class ErrorHandlerTest extends CakeTestCase { * @return void */ function testMissingConnection() { + $this->markTestIncomplete('Not implemented now'); ob_start(); $TestErrorHandler = new TestErrorHandler('missingConnection', array('className' => 'Article')); $result = ob_get_clean(); @@ -511,6 +533,7 @@ class ErrorHandlerTest extends CakeTestCase { * @return void */ function testMissingHelperFile() { + $this->markTestIncomplete('Not implemented now'); ob_start(); $TestErrorHandler = new TestErrorHandler('missingHelperFile', array('helper' => 'MyCustom', 'file' => 'my_custom.php')); $result = ob_get_clean(); @@ -526,6 +549,7 @@ class ErrorHandlerTest extends CakeTestCase { * @return void */ function testMissingHelperClass() { + $this->markTestIncomplete('Not implemented now'); ob_start(); $TestErrorHandler = new TestErrorHandler('missingHelperClass', array('helper' => 'MyCustom', 'file' => 'my_custom.php')); $result = ob_get_clean(); @@ -541,6 +565,7 @@ class ErrorHandlerTest extends CakeTestCase { * @return void */ function testMissingBehaviorFile() { + $this->markTestIncomplete('Not implemented now'); ob_start(); $TestErrorHandler = new TestErrorHandler('missingBehaviorFile', array('behavior' => 'MyCustom', 'file' => 'my_custom.php')); $result = ob_get_clean(); @@ -556,6 +581,7 @@ class ErrorHandlerTest extends CakeTestCase { * @return void */ function testMissingBehaviorClass() { + $this->markTestIncomplete('Not implemented now'); ob_start(); $TestErrorHandler = new TestErrorHandler('missingBehaviorClass', array('behavior' => 'MyCustom', 'file' => 'my_custom.php')); $result = ob_get_clean(); @@ -570,6 +596,7 @@ class ErrorHandlerTest extends CakeTestCase { * @return void */ function testMissingComponentFile() { + $this->markTestIncomplete('Not implemented now'); ob_start(); $TestErrorHandler = new TestErrorHandler('missingComponentFile', array('className' => 'PostsController', 'component' => 'Sidebox', 'file' => 'sidebox.php')); $result = ob_get_clean(); @@ -585,6 +612,7 @@ class ErrorHandlerTest extends CakeTestCase { * @return void */ function testMissingComponentClass() { + $this->markTestIncomplete('Not implemented now'); ob_start(); $TestErrorHandler = new TestErrorHandler('missingComponentClass', array('className' => 'PostsController', 'component' => 'Sidebox', 'file' => 'sidebox.php')); $result = ob_get_clean(); @@ -600,6 +628,7 @@ class ErrorHandlerTest extends CakeTestCase { * @return void */ function testMissingModel() { + $this->markTestIncomplete('Not implemented now'); ob_start(); $TestErrorHandler = new TestErrorHandler('missingModel', array('className' => 'Article', 'file' => 'article.php')); $result = ob_get_clean(); From 5d942ee609607ebb1b8630cd10a1d2ef043e6ec4 Mon Sep 17 00:00:00 2001 From: mark_story Date: Sat, 28 Aug 2010 19:53:21 -0400 Subject: [PATCH 045/166] Extracting a few methods to make testing easier, and subclasses easier to create. --- cake/libs/error.php | 46 ++++++++++++++++++++++------ cake/tests/cases/libs/error.test.php | 5 +-- 2 files changed, 39 insertions(+), 12 deletions(-) diff --git a/cake/libs/error.php b/cake/libs/error.php index 0f45b7a27..983361450 100644 --- a/cake/libs/error.php +++ b/cake/libs/error.php @@ -47,17 +47,9 @@ class ErrorHandler { * @param array $messages Error messages */ function __construct(Exception $exception) { - static $__previousError = null; App::import('Core', 'Sanitize'); - App::import('Controller', 'CakeError'); - if ($__previousError != $exception) { - $__previousError = $exception; - $this->controller = new CakeErrorController(); - } else { - $this->controller = new Controller(); - $this->controller->viewPath = 'errors'; - } + $this->controller = $this->_getController($exception); if (method_exists($this->controller, 'apperror')) { return $this->controller->appError($exception); @@ -82,7 +74,31 @@ class ErrorHandler { } } } - call_user_func_array(array($this, $method), array($exception)); + $this->method = $method; + $this->error = $exception; + } + +/** + * Get the controller instance to handle the exception. + * Override this method in subclasses to customize the controller used. + * This method returns the built in `CakeErrorController` normally, or if an error is repeated + * a bare controller will be used. + * + * @param Exception $exception The exception to get a controller for. + * @return Controller + */ + protected function _getController($exception) { + static $__previousError = null; + App::import('Controller', 'CakeError'); + + if ($__previousError != $exception) { + $__previousError = $exception; + $controller = new CakeErrorController(); + } else { + $controller = new Controller(); + $controller->viewPath = 'errors'; + } + return $controller; } /** @@ -95,6 +111,16 @@ class ErrorHandler { */ public static function handleException(Exception $exception) { $error = new ErrorHandler($exception); + $error->render(); + } + +/** + * Renders the response for the exception. + * + * @return void + */ + public function render() { + call_user_func_array(array($this, $this->method), array($this->error)); } /** diff --git a/cake/tests/cases/libs/error.test.php b/cake/tests/cases/libs/error.test.php index 532deced0..4f259ef5e 100644 --- a/cake/tests/cases/libs/error.test.php +++ b/cake/tests/cases/libs/error.test.php @@ -321,10 +321,11 @@ class ErrorHandlerTest extends CakeTestCase { * @return void */ function testError() { - $this->markTestIncomplete('Not implemented now'); + $exception = new Error404Exception('Page not found'); ob_start(); - $TestErrorHandler = new TestErrorHandler('error404', array('message' => 'Page not found')); + $TestErrorHandler = new TestErrorHandler($exception); ob_clean(); + ob_start(); $TestErrorHandler->error(array( 'code' => 404, From a30721b46b21a76720ef729b6a57aae21b870bbb Mon Sep 17 00:00:00 2001 From: mark_story Date: Sat, 28 Aug 2010 22:49:52 -0400 Subject: [PATCH 046/166] Moving exception classes around and making all the core exceptions extend one class that overrides the code to 500. The code value will be used as the HTTP status code for the error page. --- cake/libs/exceptions.php | 48 ++++++++++++++++++++++++++-------------- 1 file changed, 32 insertions(+), 16 deletions(-) diff --git a/cake/libs/exceptions.php b/cake/libs/exceptions.php index 3e0f83b9b..b18c77fc3 100644 --- a/cake/libs/exceptions.php +++ b/cake/libs/exceptions.php @@ -18,52 +18,68 @@ * @since CakePHP(tm) v 2.0 * @license MIT License (http://www.opensource.org/licenses/mit-license.php) */ +/** + * CakeException is used a base class for CakePHP's internal exceptions. + * In general framework errors are interpreted as 500 code errors. + * + * @package cake.libs + */ +class CakeException extends RuntimeException { + public function __construct($message, $code = 500, Exception $previous = null) { + parent::__construct($message, $code, $previous); + } +} -class Error404Exception extends RuntimeException { } -class Error500Exception extends RuntimeException { } + +class Error404Exception extends RuntimeException { + public function __construct($message, $code = 404, Exception $previous = null) { + parent::__construct($message, $code, $previous); + } +} +class Error500Exception extends CakeException { } /* * Exceptions used by Dispatcher */ -class MissingControllerException extends RuntimeException { } -class MissingActionException extends RuntimeException { } -class PrivateActionException extends RuntimeException { } +class MissingControllerException extends Error404Exception { } +class MissingActionException extends Error404Exception { } +class PrivateActionException extends Error404Exception { } /** * Exceptions used by the ComponentCollection. */ -class MissingComponentFileException extends RuntimeException { } -class MissingComponentClassException extends RuntimeException { } +class MissingComponentFileException extends CakeException { } +class MissingComponentClassException extends CakeException { } /** * Runtime Exceptions for behaviors */ -class MissingBehaviorFileException extends RuntimeException { } -class MissingBehaviorClassException extends RuntimeException { } +class MissingBehaviorFileException extends CakeException { } +class MissingBehaviorClassException extends CakeException { } /** * Runtime Exceptions for Views */ -class MissingViewException extends RuntimeException { } -class MissingLayoutException extends RuntimeException { } +class MissingViewException extends CakeException { } +class MissingLayoutException extends CakeException { } /** * Runtime Exceptions for ConnectionManager */ -class MissingDatabaseException extends RuntimeException {} -class MissingConnectionException extends RuntimeException {} +class MissingDatabaseException extends CakeException {} +class MissingConnectionException extends CakeException {} /** * Exceptions used by the TaskCollection. */ -class MissingTaskFileException extends RuntimeException { } -class MissingTaskClassException extends RuntimeException { } +class MissingTaskFileException extends CakeException { } +class MissingTaskClassException extends CakeException { } /** * Exception class to be thrown when a database table is not found in the datasource * */ -class MissingTableException extends RuntimeException { +class MissingTableException extends CakeException { /** * The name of the model wanting to load the database table * From 8712a90c8bb533e51c1c19c286165ce6323f3069 Mon Sep 17 00:00:00 2001 From: mark_story Date: Sat, 28 Aug 2010 22:50:29 -0400 Subject: [PATCH 047/166] Adding some tests for construction. --- cake/libs/error.php | 2 +- cake/tests/cases/libs/error.test.php | 95 +++++++++++++++++----------- 2 files changed, 58 insertions(+), 39 deletions(-) diff --git a/cake/libs/error.php b/cake/libs/error.php index 983361450..dc6bf3395 100644 --- a/cake/libs/error.php +++ b/cake/libs/error.php @@ -65,7 +65,7 @@ class ErrorHandler { if ($parentClass != 'ErrorHandler') { $method = 'error404'; } - $parentMethods = get_class_methods($parentClass); + $parentMethods = (array)get_class_methods($parentClass); if (in_array($method, $parentMethods)) { $method = 'error404'; } diff --git a/cake/tests/cases/libs/error.test.php b/cake/tests/cases/libs/error.test.php index 4f259ef5e..b27ee40dd 100644 --- a/cake/tests/cases/libs/error.test.php +++ b/cake/tests/cases/libs/error.test.php @@ -209,16 +209,6 @@ class MyCustomErrorHandler extends ErrorHandler { function missingWidgetThing() { echo 'widget thing is missing'; } - -/** - * stop method - * - * @access public - * @return void - */ - function _stop() { - return; - } } /** @@ -267,8 +257,13 @@ class ErrorHandlerTest extends CakeTestCase { $request = new CakeRequest(null, false); $request->base = ''; Router::setRequestInfo($request); + $this->_debug = Configure::read('debug'); } + function teardown() { + Configure::write('debug', $this->_debug); + } + /** * test handleException generating a page. * @@ -314,6 +309,35 @@ class ErrorHandlerTest extends CakeTestCase { Configure::write('debug', $back); } +/** + * test things in the constructor. + * + * @return void + */ + function testConstruction() { + $exception = new Error404Exception('Page not found'); + $ErrorHandler = new ErrorHandler($exception); + + $this->assertType('CakeErrorController', $ErrorHandler->controller); + $this->assertEquals('error404', $ErrorHandler->method); + $this->assertEquals($exception, $ErrorHandler->error); + } + +/** + * test that method gets coerced when debug = 0 + * + * @return void + */ + function testErrorMethodCoercion() { + Configure::write('debug', 0); + $exception = new MissingActionException('Page not found'); + $ErrorHandler = new ErrorHandler($exception); + + $this->assertType('CakeErrorController', $ErrorHandler->controller); + $this->assertEquals('error404', $ErrorHandler->method); + $this->assertEquals($exception, $ErrorHandler->error); + } + /** * testError method * @@ -321,17 +345,12 @@ class ErrorHandlerTest extends CakeTestCase { * @return void */ function testError() { + $this->markTestIncomplete('Not done'); $exception = new Error404Exception('Page not found'); - ob_start(); - $TestErrorHandler = new TestErrorHandler($exception); - ob_clean(); + $ErrorHandler = new ErrorHandler($exception); ob_start(); - $TestErrorHandler->error(array( - 'code' => 404, - 'message' => 'Page not Found', - 'name' => "Couldn't find what you were looking for" - )); + $ErrorHandler->error($excpetion); $result = ob_get_clean(); $this->assertPattern("/

    Couldn't find what you were looking for<\/h2>/", $result); $this->assertPattern('/Page not Found/', $result); @@ -350,16 +369,16 @@ class ErrorHandlerTest extends CakeTestCase { ), true); ob_start(); - $TestErrorHandler = new TestErrorHandler('error404', array('message' => 'Page not found', 'url' => '/test_error')); + $ErrorHandler = new ErrorHandler('error404', array('message' => 'Page not found', 'url' => '/test_error')); $result = ob_get_clean(); $this->assertPattern('/

    Not Found<\/h2>/', $result); $this->assertPattern("/'\/test_error'<\/strong>/", $result); ob_start(); - $TestErrorHandler = new TestErrorHandler('error404', array('message' => 'Page not found')); + $ErrorHandler = new ErrorHandler('error404', array('message' => 'Page not found')); ob_get_clean(); ob_start(); - $TestErrorHandler->error404(array( + $ErrorHandler->error404(array( 'url' => 'pages/pink', 'message' => 'Page not found' )); @@ -379,14 +398,14 @@ class ErrorHandlerTest extends CakeTestCase { function testError500() { $this->markTestIncomplete('Not implemented now'); ob_start(); - $TestErrorHandler = new TestErrorHandler('error500', array( + $ErrorHandler = new ErrorHandler('error500', array( 'message' => 'An Internal Error Has Occurred' )); $result = ob_get_clean(); $this->assertPattern('/

    An Internal Error Has Occurred<\/h2>/', $result); ob_start(); - $TestErrorHandler = new TestErrorHandler('error500', array( + $ErrorHandler = new ErrorHandler('error500', array( 'message' => 'An Internal Error Has Occurred', 'code' => '500' )); @@ -405,7 +424,7 @@ class ErrorHandlerTest extends CakeTestCase { $this->skipIf(defined('APP_CONTROLLER_EXISTS'), '%s Need a non-existent AppController'); ob_start(); - $TestErrorHandler = new TestErrorHandler('missingController', array('className' => 'PostsController')); + $ErrorHandler = new ErrorHandler('missingController', array('className' => 'PostsController')); $result = ob_get_clean(); $this->assertPattern('/

    Missing Controller<\/h2>/', $result); $this->assertPattern('/PostsController<\/em>/', $result); @@ -421,7 +440,7 @@ class ErrorHandlerTest extends CakeTestCase { function testMissingAction() { $this->markTestIncomplete('Not implemented now'); ob_start(); - $TestErrorHandler = new TestErrorHandler('missingAction', array('className' => 'PostsController', 'action' => 'index')); + $ErrorHandler = new ErrorHandler('missingAction', array('className' => 'PostsController', 'action' => 'index')); $result = ob_get_clean(); $this->assertPattern('/

    Missing Method in PostsController<\/h2>/', $result); $this->assertPattern('/PostsController::<\/em>index\(\)<\/em>/', $result); @@ -444,7 +463,7 @@ class ErrorHandlerTest extends CakeTestCase { function testPrivateAction() { $this->markTestIncomplete('Not implemented now'); ob_start(); - $TestErrorHandler = new TestErrorHandler('privateAction', array('className' => 'PostsController', 'action' => '_secretSauce')); + $ErrorHandler = new ErrorHandler('privateAction', array('className' => 'PostsController', 'action' => '_secretSauce')); $result = ob_get_clean(); $this->assertPattern('/

    Private Method in PostsController<\/h2>/', $result); $this->assertPattern('/PostsController::<\/em>_secretSauce\(\)<\/em>/', $result); @@ -459,7 +478,7 @@ class ErrorHandlerTest extends CakeTestCase { function testMissingTable() { $this->markTestIncomplete('Not implemented now'); ob_start(); - $TestErrorHandler = new TestErrorHandler('missingTable', array('className' => 'Article', 'table' => 'articles')); + $ErrorHandler = new ErrorHandler('missingTable', array('className' => 'Article', 'table' => 'articles')); $result = ob_get_clean(); $this->assertPattern('/HTTP\/1\.0 500 Internal Server Error/', $result); $this->assertPattern('/

    Missing Database Table<\/h2>/', $result); @@ -475,7 +494,7 @@ class ErrorHandlerTest extends CakeTestCase { function testMissingDatabase() { $this->markTestIncomplete('Not implemented now'); ob_start(); - $TestErrorHandler = new TestErrorHandler('missingDatabase', array()); + $ErrorHandler = new ErrorHandler('missingDatabase', array()); $result = ob_get_clean(); $this->assertPattern('/HTTP\/1\.0 500 Internal Server Error/', $result); $this->assertPattern('/

    Missing Database Connection<\/h2>/', $result); @@ -491,7 +510,7 @@ class ErrorHandlerTest extends CakeTestCase { function testMissingView() { $this->markTestIncomplete('Not implemented now'); ob_start(); - $TestErrorHandler = new TestErrorHandler('missingView', array('className' => 'Pages', 'action' => 'display', 'file' => 'pages/about.ctp', 'base' => '')); + $ErrorHandler = new ErrorHandler('missingView', array('className' => 'Pages', 'action' => 'display', 'file' => 'pages/about.ctp', 'base' => '')); $expected = ob_get_clean(); $this->assertPattern("/PagesController::/", $expected); $this->assertPattern("/pages\/about.ctp/", $expected); @@ -506,7 +525,7 @@ class ErrorHandlerTest extends CakeTestCase { function testMissingLayout() { $this->markTestIncomplete('Not implemented now'); ob_start(); - $TestErrorHandler = new TestErrorHandler('missingLayout', array( 'layout' => 'my_layout', 'file' => 'layouts/my_layout.ctp', 'base' => '')); + $ErrorHandler = new ErrorHandler('missingLayout', array( 'layout' => 'my_layout', 'file' => 'layouts/my_layout.ctp', 'base' => '')); $expected = ob_get_clean(); $this->assertPattern("/Missing Layout/", $expected); $this->assertPattern("/layouts\/my_layout.ctp/", $expected); @@ -521,7 +540,7 @@ class ErrorHandlerTest extends CakeTestCase { function testMissingConnection() { $this->markTestIncomplete('Not implemented now'); ob_start(); - $TestErrorHandler = new TestErrorHandler('missingConnection', array('className' => 'Article')); + $ErrorHandler = new ErrorHandler('missingConnection', array('className' => 'Article')); $result = ob_get_clean(); $this->assertPattern('/

    Missing Database Connection<\/h2>/', $result); $this->assertPattern('/Article requires a database connection/', $result); @@ -536,7 +555,7 @@ class ErrorHandlerTest extends CakeTestCase { function testMissingHelperFile() { $this->markTestIncomplete('Not implemented now'); ob_start(); - $TestErrorHandler = new TestErrorHandler('missingHelperFile', array('helper' => 'MyCustom', 'file' => 'my_custom.php')); + $ErrorHandler = new ErrorHandler('missingHelperFile', array('helper' => 'MyCustom', 'file' => 'my_custom.php')); $result = ob_get_clean(); $this->assertPattern('/

    Missing Helper File<\/h2>/', $result); $this->assertPattern('/Create the class below in file:/', $result); @@ -552,7 +571,7 @@ class ErrorHandlerTest extends CakeTestCase { function testMissingHelperClass() { $this->markTestIncomplete('Not implemented now'); ob_start(); - $TestErrorHandler = new TestErrorHandler('missingHelperClass', array('helper' => 'MyCustom', 'file' => 'my_custom.php')); + $ErrorHandler = new ErrorHandler('missingHelperClass', array('helper' => 'MyCustom', 'file' => 'my_custom.php')); $result = ob_get_clean(); $this->assertPattern('/

    Missing Helper Class<\/h2>/', $result); $this->assertPattern('/The helper class MyCustomHelper<\/em> can not be found or does not exist./', $result); @@ -568,7 +587,7 @@ class ErrorHandlerTest extends CakeTestCase { function testMissingBehaviorFile() { $this->markTestIncomplete('Not implemented now'); ob_start(); - $TestErrorHandler = new TestErrorHandler('missingBehaviorFile', array('behavior' => 'MyCustom', 'file' => 'my_custom.php')); + $ErrorHandler = new ErrorHandler('missingBehaviorFile', array('behavior' => 'MyCustom', 'file' => 'my_custom.php')); $result = ob_get_clean(); $this->assertPattern('/

    Missing Behavior File<\/h2>/', $result); $this->assertPattern('/Create the class below in file:/', $result); @@ -584,7 +603,7 @@ class ErrorHandlerTest extends CakeTestCase { function testMissingBehaviorClass() { $this->markTestIncomplete('Not implemented now'); ob_start(); - $TestErrorHandler = new TestErrorHandler('missingBehaviorClass', array('behavior' => 'MyCustom', 'file' => 'my_custom.php')); + $ErrorHandler = new ErrorHandler('missingBehaviorClass', array('behavior' => 'MyCustom', 'file' => 'my_custom.php')); $result = ob_get_clean(); $this->assertPattern('/The behavior class MyCustomBehavior<\/em> can not be found or does not exist./', $result); $this->assertPattern('/(\/|\\\)my_custom.php/', $result); @@ -599,7 +618,7 @@ class ErrorHandlerTest extends CakeTestCase { function testMissingComponentFile() { $this->markTestIncomplete('Not implemented now'); ob_start(); - $TestErrorHandler = new TestErrorHandler('missingComponentFile', array('className' => 'PostsController', 'component' => 'Sidebox', 'file' => 'sidebox.php')); + $ErrorHandler = new ErrorHandler('missingComponentFile', array('className' => 'PostsController', 'component' => 'Sidebox', 'file' => 'sidebox.php')); $result = ob_get_clean(); $this->assertPattern('/

    Missing Component File<\/h2>/', $result); $this->assertPattern('/Create the class SideboxComponent<\/em> in file:/', $result); @@ -615,7 +634,7 @@ class ErrorHandlerTest extends CakeTestCase { function testMissingComponentClass() { $this->markTestIncomplete('Not implemented now'); ob_start(); - $TestErrorHandler = new TestErrorHandler('missingComponentClass', array('className' => 'PostsController', 'component' => 'Sidebox', 'file' => 'sidebox.php')); + $ErrorHandler = new ErrorHandler('missingComponentClass', array('className' => 'PostsController', 'component' => 'Sidebox', 'file' => 'sidebox.php')); $result = ob_get_clean(); $this->assertPattern('/

    Missing Component Class<\/h2>/', $result); $this->assertPattern('/Create the class SideboxComponent<\/em> in file:/', $result); @@ -631,7 +650,7 @@ class ErrorHandlerTest extends CakeTestCase { function testMissingModel() { $this->markTestIncomplete('Not implemented now'); ob_start(); - $TestErrorHandler = new TestErrorHandler('missingModel', array('className' => 'Article', 'file' => 'article.php')); + $ErrorHandler = new ErrorHandler('missingModel', array('className' => 'Article', 'file' => 'article.php')); $result = ob_get_clean(); $this->assertPattern('/

    Missing Model<\/h2>/', $result); $this->assertPattern('/Article<\/em> could not be found./', $result); From 756baeafdb757d90176a6cdc8e23897cf996c993 Mon Sep 17 00:00:00 2001 From: mark_story Date: Sat, 28 Aug 2010 23:32:14 -0400 Subject: [PATCH 048/166] Making CakeErrorController get the most recent request, this will help when using requestAction. Updating test cases for error404. Updating ErrorHandler --- .../libs/controller/cake_error_controller.php | 2 +- cake/libs/error.php | 27 +++------ cake/libs/view/errors/error404.ctp | 5 +- cake/tests/cases/libs/error.test.php | 59 ++++++++++++------- 4 files changed, 50 insertions(+), 43 deletions(-) diff --git a/cake/libs/controller/cake_error_controller.php b/cake/libs/controller/cake_error_controller.php index 8d98561bc..aafa76b6d 100644 --- a/cake/libs/controller/cake_error_controller.php +++ b/cake/libs/controller/cake_error_controller.php @@ -26,7 +26,7 @@ class CakeErrorController extends AppController { function __construct() { parent::__construct(); $this->_set(Router::getPaths()); - $this->request = $this->params = Router::getRequest(); + $this->request = $this->params = Router::getRequest(false); $this->constructClasses(); $this->Components->trigger('initialize', array(&$this)); $this->_set(array('cacheAction' => false, 'viewPath' => 'errors')); diff --git a/cake/libs/error.php b/cake/libs/error.php index dc6bf3395..60caa56be 100644 --- a/cake/libs/error.php +++ b/cake/libs/error.php @@ -98,7 +98,7 @@ class ErrorHandler { $controller = new Controller(); $controller->viewPath = 'errors'; } - return $controller; + return $controller; } /** @@ -128,15 +128,8 @@ class ErrorHandler { * * @param array $params Parameters for controller */ - public function error($params) { - extract($params, EXTR_OVERWRITE); - $this->controller->set(array( - 'code' => $code, - 'name' => $name, - 'message' => $message, - 'title' => $code . ' ' . $name - )); - $this->_outputMessage('error404'); + public function error(Exception $error) { + $this->error404($error); } /** @@ -144,17 +137,13 @@ class ErrorHandler { * * @param array $params Parameters for controller */ - public function error404($exception) { - if (!isset($url)) { - $url = $this->controller->here; - } - $url = Router::normalize($url); + public function error404($error) { + $url = Router::normalize($this->controller->request->here); $this->controller->response->statusCode(404); $this->controller->set(array( - 'code' => '404', - 'name' => __('Not Found'), - 'message' => h($url), - 'base' => $this->controller->request->base + 'code' => 404, + 'name' => $error->getMessage(), + 'url' => h($url), )); $this->_outputMessage('error404'); } diff --git a/cake/libs/view/errors/error404.ctp b/cake/libs/view/errors/error404.ctp index 0f6b761c8..6631b0532 100644 --- a/cake/libs/view/errors/error404.ctp +++ b/cake/libs/view/errors/error404.ctp @@ -20,5 +20,8 @@

    : - '{$message}'"); ?> + '{$url}'" + ); ?>

    \ No newline at end of file diff --git a/cake/tests/cases/libs/error.test.php b/cake/tests/cases/libs/error.test.php index b27ee40dd..4d069ded4 100644 --- a/cake/tests/cases/libs/error.test.php +++ b/cake/tests/cases/libs/error.test.php @@ -274,7 +274,7 @@ class ErrorHandlerTest extends CakeTestCase { ob_start(); ErrorHandler::handleException($error); $result = ob_get_clean(); - $this->assertPattern('/Not Found/', $result, 'message missing.'); + $this->assertPattern('/Kaboom!/', $result, 'message missing.'); } /** @@ -345,15 +345,13 @@ class ErrorHandlerTest extends CakeTestCase { * @return void */ function testError() { - $this->markTestIncomplete('Not done'); - $exception = new Error404Exception('Page not found'); + $exception = new Exception('Page not found'); $ErrorHandler = new ErrorHandler($exception); ob_start(); - $ErrorHandler->error($excpetion); + $ErrorHandler->error($exception); $result = ob_get_clean(); - $this->assertPattern("/

    Couldn't find what you were looking for<\/h2>/", $result); - $this->assertPattern('/Page not Found/', $result); + $this->assertPattern("/

    Page not found<\/h2>/", $result); } /** @@ -363,32 +361,49 @@ class ErrorHandlerTest extends CakeTestCase { * @return void */ function testError404() { - $this->markTestIncomplete('Not implemented now'); App::build(array( 'views' => array(TEST_CAKE_CORE_INCLUDE_PATH . 'libs' . DS . 'view' . DS) ), true); + Router::reload(); + + $request = new CakeRequest('posts/view/1000', false); + Router::setRequestInfo($request); + + $exception = new Error404Exception('Custom message'); + $ErrorHandler = new ErrorHandler($exception); ob_start(); - $ErrorHandler = new ErrorHandler('error404', array('message' => 'Page not found', 'url' => '/test_error')); + $ErrorHandler->render(); $result = ob_get_clean(); - $this->assertPattern('/

    Not Found<\/h2>/', $result); - $this->assertPattern("/'\/test_error'<\/strong>/", $result); - - ob_start(); - $ErrorHandler = new ErrorHandler('error404', array('message' => 'Page not found')); - ob_get_clean(); - ob_start(); - $ErrorHandler->error404(array( - 'url' => 'pages/pink', - 'message' => 'Page not found' - )); - $result = ob_get_clean(); - $this->assertNoPattern('##', $result); + $this->assertPattern('/

    Custom message<\/h2>/', $result); + $this->assertPattern("/'\/posts\/view\/1000'<\/strong>/", $result); + App::build(); } +/** + * test that error404 doesn't expose XSS + * + * @return void + */ + function testError404NoInjection() { + Router::reload(); + + $request = new CakeRequest('pages/pink', false); + Router::setRequestInfo($request); + + $exception = new Error404Exception('Custom message'); + $ErrorHandler = new ErrorHandler($exception); + + ob_start(); + $ErrorHandler->render(); + $result = ob_get_clean(); + + $this->assertNoPattern('##', $result); + } + /** * testError500 method * From 88c66c057dfad38fb9262d8dc83f18ca65157be2 Mon Sep 17 00:00:00 2001 From: mark_story Date: Sun, 29 Aug 2010 01:00:36 -0400 Subject: [PATCH 049/166] Renaming error.php to error_handler.php to better match its class name. --- cake/bootstrap.php | 2 +- cake/libs/{error.php => error_handler.php} | 53 ++++++++-------------- 2 files changed, 20 insertions(+), 35 deletions(-) rename cake/libs/{error.php => error_handler.php} (90%) diff --git a/cake/bootstrap.php b/cake/bootstrap.php index 05ac95ef3..5499ed029 100644 --- a/cake/bootstrap.php +++ b/cake/bootstrap.php @@ -34,6 +34,6 @@ require LIBS . 'configure.php'; require LIBS . 'set.php'; require LIBS . 'cache.php'; Configure::bootstrap(); -require LIBS . 'error.php'; +require LIBS . 'error_handler.php'; set_exception_handler(array('ErrorHandler', 'handleException')); require CAKE . 'dispatcher.php'; diff --git a/cake/libs/error.php b/cake/libs/error_handler.php similarity index 90% rename from cake/libs/error.php rename to cake/libs/error_handler.php index 60caa56be..512a27c28 100644 --- a/cake/libs/error.php +++ b/cake/libs/error_handler.php @@ -61,6 +61,7 @@ class ErrorHandler { } if ($method !== 'error') { if (Configure::read('debug') == 0) { + $code = $exception->getCode(); $parentClass = get_parent_class($this); if ($parentClass != 'ErrorHandler') { $method = 'error404'; @@ -69,7 +70,7 @@ class ErrorHandler { if (in_array($method, $parentMethods)) { $method = 'error404'; } - if (isset($code) && $code == 500) { + if ($code == 500) { $method = 'error500'; } } @@ -191,15 +192,12 @@ class ErrorHandler { * * @param array $params Parameters for controller */ - public function missingAction($params) { - extract($params, EXTR_OVERWRITE); - - $controllerName = str_replace('Controller', '', $className); + public function missingAction($error) { + $message = $error->getMessage(); + list($controllerName, $action) = explode('::', $message); $this->controller->set(array( - 'controller' => $className, - 'controllerName' => $controllerName, + 'controller' => $controllerName, 'action' => $action, - 'title' => __('Missing Method in Controller') )); $this->_outputMessage('missingAction'); } @@ -209,13 +207,12 @@ class ErrorHandler { * * @param array $params Parameters for controller */ - public function privateAction($params) { - extract($params, EXTR_OVERWRITE); - + public function privateAction($error) { + $message = $error->getMessage(); + list($controllerName, $action) = explode('::', $message); $this->controller->set(array( - 'controller' => $className, - 'action' => $action, - 'title' => __('Trying to access private method in class') + 'controller' => $controllerName, + 'action' => $action )); $this->_outputMessage('privateAction'); } @@ -225,15 +222,11 @@ class ErrorHandler { * * @param array $params Parameters for controller */ - public function missingTable($params) { - extract($params, EXTR_OVERWRITE); - + public function missingTable($error) { $this->controller->header("HTTP/1.0 500 Internal Server Error"); $this->controller->set(array( - 'code' => '500', - 'model' => $className, - 'table' => $table, - 'title' => __('Missing Database Table') + 'model' => $error->getModel(), + 'table' => $error->getTable(), )); $this->_outputMessage('missingTable'); } @@ -243,7 +236,7 @@ class ErrorHandler { * * @param array $params Parameters for controller */ - public function missingDatabase($params = array()) { + public function missingDatabase($exception) { $this->controller->header("HTTP/1.0 500 Internal Server Error"); $this->controller->set(array( 'code' => '500', @@ -257,14 +250,9 @@ class ErrorHandler { * * @param array $params Parameters for controller */ - public function missingView($params) { - extract($params, EXTR_OVERWRITE); - + public function missingView($error) { $this->controller->set(array( - 'controller' => $className, - 'action' => $action, - 'file' => $file, - 'title' => __('Missing View') + 'file' => $error->getMessage(), )); $this->_outputMessage('missingView'); } @@ -274,13 +262,10 @@ class ErrorHandler { * * @param array $params Parameters for controller */ - public function missingLayout($params) { - extract($params, EXTR_OVERWRITE); - + public function missingLayout($error) { $this->controller->layout = 'default'; $this->controller->set(array( - 'file' => $file, - 'title' => __('Missing Layout') + 'file' => $error->getMessage(), )); $this->_outputMessage('missingLayout'); } From 041aeecce4ef83382312453f46e34c3fa9f48264 Mon Sep 17 00:00:00 2001 From: mark_story Date: Sun, 29 Aug 2010 01:01:36 -0400 Subject: [PATCH 050/166] Renaming test case file to match class file. Updating tests and methods for missing_action, missing_view, private_action. --- cake/libs/exceptions.php | 2 +- cake/libs/view/errors/missing_action.ctp | 6 +- cake/libs/view/errors/missing_view.ctp | 2 +- cake/libs/view/errors/private_action.ctp | 2 +- ...{error.test.php => error_handler.test.php} | 135 +++++++++--------- 5 files changed, 71 insertions(+), 76 deletions(-) rename cake/tests/cases/libs/{error.test.php => error_handler.test.php} (89%) diff --git a/cake/libs/exceptions.php b/cake/libs/exceptions.php index b18c77fc3..51361d6c3 100644 --- a/cake/libs/exceptions.php +++ b/cake/libs/exceptions.php @@ -102,7 +102,7 @@ class MissingTableException extends CakeException { */ public function __construct($model, $table) { $this->model = $model; - $this->$table = $table; + $this->table = $table; $message = sprintf(__('Database table %s for model %s was not found.'), $table, $model); parent::__construct($message); } diff --git a/cake/libs/view/errors/missing_action.ctp b/cake/libs/view/errors/missing_action.ctp index 1a5872388..3bb14ceac 100644 --- a/cake/libs/view/errors/missing_action.ctp +++ b/cake/libs/view/errors/missing_action.ctp @@ -24,16 +24,14 @@

    : - ' . $controller . '::', '' . $action . '()', APP_DIR . DS . 'controllers' . DS . Inflector::underscore($controller) . '.php'); ?> + ' . $controller . '::', '' . $action . '', APP_DIR . DS . 'controllers' . DS . Inflector::underscore($controller) . '.php'); ?>

     <?php
     class  extends AppController {
     
    -	public $name = '';
    -
     
    -	function () {
    +	function  {
     
     	}
     
    diff --git a/cake/libs/view/errors/missing_view.ctp b/cake/libs/view/errors/missing_view.ctp
    index 121d97f9a..55aef34ce 100644
    --- a/cake/libs/view/errors/missing_view.ctp
    +++ b/cake/libs/view/errors/missing_view.ctp
    @@ -20,7 +20,7 @@
     

    : - ' . $controller . 'Controller::', '' . $action . '()'); ?> + ' . Inflector::camelize($this->request->controller) . 'Controller::', '' . $this->request->action . '()'); ?>

    : diff --git a/cake/libs/view/errors/private_action.ctp b/cake/libs/view/errors/private_action.ctp index ab9f13cdc..20236e31f 100644 --- a/cake/libs/view/errors/private_action.ctp +++ b/cake/libs/view/errors/private_action.ctp @@ -20,7 +20,7 @@

    : - ' . $controller . '::', '' . $action . '()'); ?> + ' . $controller . '::', '' . $action . ''); ?>

    : diff --git a/cake/tests/cases/libs/error.test.php b/cake/tests/cases/libs/error_handler.test.php similarity index 89% rename from cake/tests/cases/libs/error.test.php rename to cake/tests/cases/libs/error_handler.test.php index 4d069ded4..b4f3ede19 100644 --- a/cake/tests/cases/libs/error.test.php +++ b/cake/tests/cases/libs/error_handler.test.php @@ -17,56 +17,7 @@ * @since CakePHP(tm) v 1.2.0.5432 * @license http://www.opensource.org/licenses/opengroup.php The Open Group Test Suite License */ -if (class_exists('TestErrorHandler')) { - return; -} -/** - * BlueberryComponent class - * - * @package cake - * @subpackage cake.tests.cases.libs - */ -class BlueberryComponent extends Object { - -/** - * testName property - * - * @access public - * @return void - */ - public $testName = null; - -/** - * initialize method - * - * @access public - * @return void - */ - function initialize(&$controller) { - $this->testName = 'BlueberryComponent'; - } -} - -/** - * BlueberryDispatcher class - * - * @package cake - * @subpackage cake.tests.cases.libs - */ -class BlueberryDispatcher extends Dispatcher { - -/** - * cakeError method - * - * @access public - * @return void - */ - function cakeError($method, $messages = array()) { - $error = new TestErrorHandler($method, $messages); - return $error; - } -} /** * Short description for class. @@ -138,7 +89,34 @@ if (!class_exists('AppController')) { } elseif (!defined('APP_CONTROLLER_EXISTS')){ define('APP_CONTROLLER_EXISTS', true); } -App::import('Core', array('Error', 'Controller')); +App::import('Core', array('ErrorHandler', 'Controller', 'Component')); + +/** + * BlueberryComponent class + * + * @package cake + * @subpackage cake.tests.cases.libs + */ +class BlueberryComponent extends Component { + +/** + * testName property + * + * @access public + * @return void + */ + public $testName = null; + +/** + * initialize method + * + * @access public + * @return void + */ + function initialize(&$controller) { + $this->testName = 'BlueberryComponent'; + } +} /** * TestErrorController class @@ -453,20 +431,25 @@ class ErrorHandlerTest extends CakeTestCase { * @return void */ function testMissingAction() { - $this->markTestIncomplete('Not implemented now'); + $exception = new MissingActionException('PostsController::index()'); + $ErrorHandler = new ErrorHandler($exception); + ob_start(); - $ErrorHandler = new ErrorHandler('missingAction', array('className' => 'PostsController', 'action' => 'index')); + $ErrorHandler->render(); $result = ob_get_clean(); + $this->assertPattern('/

    Missing Method in PostsController<\/h2>/', $result); $this->assertPattern('/PostsController::<\/em>index\(\)<\/em>/', $result); + /* TODO: Integration test that needs to be moved ob_start(); - $dispatcher = new BlueberryDispatcher('/blueberry/inexistent'); + $dispatcher = new Dispatcher('/blueberry/inexistent'); $result = ob_get_clean(); $this->assertPattern('/

    Missing Method in BlueberryController<\/h2>/', $result); $this->assertPattern('/BlueberryController::<\/em>inexistent\(\)<\/em>/', $result); $this->assertNoPattern('/Location: (.*)\/users\/login/', $result); $this->assertNoPattern('/Stopped with status: 0/', $result); + */ } /** @@ -476,10 +459,13 @@ class ErrorHandlerTest extends CakeTestCase { * @return void */ function testPrivateAction() { - $this->markTestIncomplete('Not implemented now'); + $exception = new PrivateActionException('PostsController::_secretSauce()'); + $ErrorHandler = new ErrorHandler($exception); + ob_start(); - $ErrorHandler = new ErrorHandler('privateAction', array('className' => 'PostsController', 'action' => '_secretSauce')); + $ErrorHandler->render(); $result = ob_get_clean(); + $this->assertPattern('/

    Private Method in PostsController<\/h2>/', $result); $this->assertPattern('/PostsController::<\/em>_secretSauce\(\)<\/em>/', $result); } @@ -491,10 +477,13 @@ class ErrorHandlerTest extends CakeTestCase { * @return void */ function testMissingTable() { - $this->markTestIncomplete('Not implemented now'); + $exception = new MissingTableException('Article', 'articles'); + $ErrorHandler = new ErrorHandler($exception); + ob_start(); - $ErrorHandler = new ErrorHandler('missingTable', array('className' => 'Article', 'table' => 'articles')); + $ErrorHandler->render(); $result = ob_get_clean(); + $this->assertPattern('/HTTP\/1\.0 500 Internal Server Error/', $result); $this->assertPattern('/

    Missing Database Table<\/h2>/', $result); $this->assertPattern('/table articles<\/em> for model Article<\/em>/', $result); @@ -507,10 +496,13 @@ class ErrorHandlerTest extends CakeTestCase { * @return void */ function testMissingDatabase() { - $this->markTestIncomplete('Not implemented now'); + $exception = new MissingDatabaseException('default'); + $ErrorHandler = new ErrorHandler($exception); + ob_start(); - $ErrorHandler = new ErrorHandler('missingDatabase', array()); + $ErrorHandler->render(); $result = ob_get_clean(); + $this->assertPattern('/HTTP\/1\.0 500 Internal Server Error/', $result); $this->assertPattern('/

    Missing Database Connection<\/h2>/', $result); $this->assertPattern('/Confirm you have created the file/', $result); @@ -523,12 +515,14 @@ class ErrorHandlerTest extends CakeTestCase { * @return void */ function testMissingView() { - $this->markTestIncomplete('Not implemented now'); + $exception = new MissingViewException('/posts/about.ctp'); + $ErrorHandler = new ErrorHandler($exception); + ob_start(); - $ErrorHandler = new ErrorHandler('missingView', array('className' => 'Pages', 'action' => 'display', 'file' => 'pages/about.ctp', 'base' => '')); - $expected = ob_get_clean(); - $this->assertPattern("/PagesController::/", $expected); - $this->assertPattern("/pages\/about.ctp/", $expected); + $ErrorHandler->render(); + $result = ob_get_clean(); + + $this->assertPattern("/posts\/about.ctp/", $result); } /** @@ -538,12 +532,15 @@ class ErrorHandlerTest extends CakeTestCase { * @return void */ function testMissingLayout() { - $this->markTestIncomplete('Not implemented now'); + $exception = new MissingLayoutException('layouts/my_layout.ctp'); + $ErrorHandler = new ErrorHandler($exception); + ob_start(); - $ErrorHandler = new ErrorHandler('missingLayout', array( 'layout' => 'my_layout', 'file' => 'layouts/my_layout.ctp', 'base' => '')); - $expected = ob_get_clean(); - $this->assertPattern("/Missing Layout/", $expected); - $this->assertPattern("/layouts\/my_layout.ctp/", $expected); + $ErrorHandler->render(); + $result = ob_get_clean(); + + $this->assertPattern("/Missing Layout/", $result); + $this->assertPattern("/layouts\/my_layout.ctp/", $result); } /** From 7fb62e9b7e77b6b7a5d7832a900d6c5ef9cbfb0a Mon Sep 17 00:00:00 2001 From: mark_story Date: Sun, 29 Aug 2010 01:26:21 -0400 Subject: [PATCH 051/166] Updating more error messages to use exceptions. --- cake/libs/error_handler.php | 66 ++++++++----------- .../view/errors/missing_behavior_class.ctp | 4 +- .../view/errors/missing_behavior_file.ctp | 2 +- .../view/errors/missing_component_class.ctp | 6 +- .../view/errors/missing_component_file.ctp | 4 +- .../libs/view/errors/missing_helper_class.ctp | 4 +- cake/libs/view/errors/missing_helper_file.ctp | 2 +- cake/tests/cases/libs/error_handler.test.php | 49 ++++++++++---- 8 files changed, 72 insertions(+), 65 deletions(-) diff --git a/cake/libs/error_handler.php b/cake/libs/error_handler.php index 512a27c28..fa772e7e4 100644 --- a/cake/libs/error_handler.php +++ b/cake/libs/error_handler.php @@ -275,14 +275,11 @@ class ErrorHandler { * * @param array $params Parameters for controller */ - public function missingConnection($params) { - extract($params, EXTR_OVERWRITE); - + public function missingConnection($error) { $this->controller->header("HTTP/1.0 500 Internal Server Error"); $this->controller->set(array( 'code' => '500', - 'model' => $className, - 'title' => __('Missing Database Connection') + 'model' => $error->getMessage(), )); $this->_outputMessage('missingConnection'); } @@ -292,13 +289,11 @@ class ErrorHandler { * * @param array $params Parameters for controller */ - public function missingHelperFile($params) { - extract($params, EXTR_OVERWRITE); - + public function missingHelperFile($error) { + list($class, $ext) = explode('.', $error->getMessage()); $this->controller->set(array( - 'helperClass' => Inflector::camelize($helper) . "Helper", - 'file' => $file, - 'title' => __('Missing Helper File') + 'className' => Inflector::camelize($class), + 'file' => $error->getMessage() )); $this->_outputMessage('missingHelperFile'); } @@ -308,13 +303,12 @@ class ErrorHandler { * * @param array $params Parameters for controller */ - public function missingHelperClass($params) { - extract($params, EXTR_OVERWRITE); - + public function missingHelperClass($error) { + $class = $error->getMessage(); + $file = Inflector::underscore(str_replace('Helper', '', $error->getMessage())) . '.php'; $this->controller->set(array( - 'helperClass' => Inflector::camelize($helper) . "Helper", + 'className' => $class, 'file' => $file, - 'title' => __('Missing Helper Class') )); $this->_outputMessage('missingHelperClass'); } @@ -324,13 +318,11 @@ class ErrorHandler { * * @param array $params Parameters for controller */ - public function missingBehaviorFile($params) { - extract($params, EXTR_OVERWRITE); - + public function missingBehaviorFile($error) { + list($class, $ext) = explode('.', $error->getMessage()); $this->controller->set(array( - 'behaviorClass' => Inflector::camelize($behavior) . "Behavior", - 'file' => $file, - 'title' => __('Missing Behavior File') + 'className' => Inflector::camelize($class), + 'file' => $error->getMessage() )); $this->_outputMessage('missingBehaviorFile'); } @@ -340,13 +332,12 @@ class ErrorHandler { * * @param array $params Parameters for controller */ - public function missingBehaviorClass($params) { - extract($params, EXTR_OVERWRITE); - + public function missingBehaviorClass($error) { + $class = $error->getMessage(); + $file = Inflector::underscore(str_replace('Behavior', '', $error->getMessage())) . '.php'; $this->controller->set(array( - 'behaviorClass' => Inflector::camelize($behavior) . "Behavior", + 'className' => $class, 'file' => $file, - 'title' => __('Missing Behavior Class') )); $this->_outputMessage('missingBehaviorClass'); } @@ -356,14 +347,11 @@ class ErrorHandler { * * @param array $params Parameters for controller */ - public function missingComponentFile($params) { - extract($params, EXTR_OVERWRITE); - + public function missingComponentFile($error) { + list($class, $ext) = explode('.', $error->getMessage()); $this->controller->set(array( - 'controller' => $className, - 'component' => $component, - 'file' => $file, - 'title' => __('Missing Component File') + 'className' => Inflector::camelize($class), + 'file' => $error->getMessage() )); $this->_outputMessage('missingComponentFile'); } @@ -373,14 +361,12 @@ class ErrorHandler { * * @param array $params Parameters for controller */ - public function missingComponentClass($params) { - extract($params, EXTR_OVERWRITE); - + public function missingComponentClass($error) { + $class = $error->getMessage(); + $file = Inflector::underscore(str_replace('Component', '', $error->getMessage())) . '.php'; $this->controller->set(array( - 'controller' => $className, - 'component' => $component, + 'className' => $class, 'file' => $file, - 'title' => __('Missing Component Class') )); $this->_outputMessage('missingComponentClass'); } diff --git a/cake/libs/view/errors/missing_behavior_class.ctp b/cake/libs/view/errors/missing_behavior_class.ctp index e9bf56472..58f0aa2cb 100644 --- a/cake/libs/view/errors/missing_behavior_class.ctp +++ b/cake/libs/view/errors/missing_behavior_class.ctp @@ -20,7 +20,7 @@

    : - %s can not be found or does not exist.'), $behaviorClass); ?> + %s can not be found or does not exist.'), $className); ?>

    : @@ -28,7 +28,7 @@

     <?php
    -class  extends ModelBehavior {
    +class  extends ModelBehavior {
     
     }
     ?>
    diff --git a/cake/libs/view/errors/missing_behavior_file.ctp b/cake/libs/view/errors/missing_behavior_file.ctp
    index 654537404..23ae88e17 100644
    --- a/cake/libs/view/errors/missing_behavior_file.ctp
    +++ b/cake/libs/view/errors/missing_behavior_file.ctp
    @@ -28,7 +28,7 @@
     

     <?php
    -class  extends ModelBehavior {
    +class  extends ModelBehavior {
     
     }
     ?>
    diff --git a/cake/libs/view/errors/missing_component_class.ctp b/cake/libs/view/errors/missing_component_class.ctp
    index e63440c00..9a35e113c 100644
    --- a/cake/libs/view/errors/missing_component_class.ctp
    +++ b/cake/libs/view/errors/missing_component_class.ctp
    @@ -20,15 +20,15 @@
     

    : - ' . $component . 'Component', '' . $controller . 'Controller'); ?> + ' . $className . ''); ?>

    : - ' . $component . 'Component', APP_DIR . DS . 'controllers' . DS . 'components' . DS . $file); ?> + ' . $className . '', APP_DIR . DS . 'controllers' . DS . 'components' . DS . $file); ?>

     <?php
    -class Component extends Object {
    +class extends Component {
    } ?> diff --git a/cake/libs/view/errors/missing_component_file.ctp b/cake/libs/view/errors/missing_component_file.ctp index 44c607cd8..67f02cf08 100644 --- a/cake/libs/view/errors/missing_component_file.ctp +++ b/cake/libs/view/errors/missing_component_file.ctp @@ -24,11 +24,11 @@

    : - ' . $component . 'Component', APP_DIR . DS . 'controllers' . DS . 'components' . DS . $file); ?> + ' . $className . 'Component', APP_DIR . DS . 'controllers' . DS . 'components' . DS . $file); ?>

     <?php
    -class Component extends Object {
    +class Component extends Component {
    } ?> diff --git a/cake/libs/view/errors/missing_helper_class.ctp b/cake/libs/view/errors/missing_helper_class.ctp index 7c8a79079..a79bf9eec 100644 --- a/cake/libs/view/errors/missing_helper_class.ctp +++ b/cake/libs/view/errors/missing_helper_class.ctp @@ -20,7 +20,7 @@

    : - %s can not be found or does not exist.'), $helperClass); ?> + %s can not be found or does not exist.'), $className); ?>

    : @@ -28,7 +28,7 @@

     <?php
    -class  extends AppHelper {
    +class  extends AppHelper {
     
     }
     ?>
    diff --git a/cake/libs/view/errors/missing_helper_file.ctp b/cake/libs/view/errors/missing_helper_file.ctp
    index 1da5d577b..caa7ca119 100644
    --- a/cake/libs/view/errors/missing_helper_file.ctp
    +++ b/cake/libs/view/errors/missing_helper_file.ctp
    @@ -28,7 +28,7 @@
     

     <?php
    -class  extends AppHelper {
    +class  extends AppHelper {
     
     }
     ?>
    diff --git a/cake/tests/cases/libs/error_handler.test.php b/cake/tests/cases/libs/error_handler.test.php
    index b4f3ede19..e8681eb66 100644
    --- a/cake/tests/cases/libs/error_handler.test.php
    +++ b/cake/tests/cases/libs/error_handler.test.php
    @@ -550,10 +550,13 @@ class ErrorHandlerTest extends CakeTestCase {
      * @return void
      */
     	function testMissingConnection() {
    -		$this->markTestIncomplete('Not implemented now');
    +		$exception = new MissingConnectionException('Article');
    +		$ErrorHandler = new ErrorHandler($exception);
    +
     		ob_start();
    -		$ErrorHandler = new ErrorHandler('missingConnection', array('className' => 'Article'));
    +		$ErrorHandler->render();
     		$result = ob_get_clean();
    +
     		$this->assertPattern('/

    Missing Database Connection<\/h2>/', $result); $this->assertPattern('/Article requires a database connection/', $result); } @@ -565,10 +568,13 @@ class ErrorHandlerTest extends CakeTestCase { * @return void */ function testMissingHelperFile() { - $this->markTestIncomplete('Not implemented now'); + $exception = new MissingHelperFileException('my_custom.php'); + $ErrorHandler = new ErrorHandler($exception); + ob_start(); - $ErrorHandler = new ErrorHandler('missingHelperFile', array('helper' => 'MyCustom', 'file' => 'my_custom.php')); + $ErrorHandler->render(); $result = ob_get_clean(); + $this->assertPattern('/

    Missing Helper File<\/h2>/', $result); $this->assertPattern('/Create the class below in file:/', $result); $this->assertPattern('/(\/|\\\)my_custom.php/', $result); @@ -581,10 +587,13 @@ class ErrorHandlerTest extends CakeTestCase { * @return void */ function testMissingHelperClass() { - $this->markTestIncomplete('Not implemented now'); + $exception = new MissingHelperClassException('MyCustomHelper'); + $ErrorHandler = new ErrorHandler($exception); + ob_start(); - $ErrorHandler = new ErrorHandler('missingHelperClass', array('helper' => 'MyCustom', 'file' => 'my_custom.php')); + $ErrorHandler->render(); $result = ob_get_clean(); + $this->assertPattern('/

    Missing Helper Class<\/h2>/', $result); $this->assertPattern('/The helper class MyCustomHelper<\/em> can not be found or does not exist./', $result); $this->assertPattern('/(\/|\\\)my_custom.php/', $result); @@ -597,10 +606,13 @@ class ErrorHandlerTest extends CakeTestCase { * @return void */ function testMissingBehaviorFile() { - $this->markTestIncomplete('Not implemented now'); + $exception = new MissingBehaviorFileException('my_custom.php'); + $ErrorHandler = new ErrorHandler($exception); + ob_start(); - $ErrorHandler = new ErrorHandler('missingBehaviorFile', array('behavior' => 'MyCustom', 'file' => 'my_custom.php')); + $ErrorHandler->render(); $result = ob_get_clean(); + $this->assertPattern('/

    Missing Behavior File<\/h2>/', $result); $this->assertPattern('/Create the class below in file:/', $result); $this->assertPattern('/(\/|\\\)my_custom.php/', $result); @@ -613,10 +625,13 @@ class ErrorHandlerTest extends CakeTestCase { * @return void */ function testMissingBehaviorClass() { - $this->markTestIncomplete('Not implemented now'); + $exception = new MissingBehaviorClassException('MyCustomBehavior'); + $ErrorHandler = new ErrorHandler($exception); + ob_start(); - $ErrorHandler = new ErrorHandler('missingBehaviorClass', array('behavior' => 'MyCustom', 'file' => 'my_custom.php')); + $ErrorHandler->render(); $result = ob_get_clean(); + $this->assertPattern('/The behavior class MyCustomBehavior<\/em> can not be found or does not exist./', $result); $this->assertPattern('/(\/|\\\)my_custom.php/', $result); } @@ -628,10 +643,13 @@ class ErrorHandlerTest extends CakeTestCase { * @return void */ function testMissingComponentFile() { - $this->markTestIncomplete('Not implemented now'); + $exception = new MissingComponentFileException('sidebox.php'); + $ErrorHandler = new ErrorHandler($exception); + ob_start(); - $ErrorHandler = new ErrorHandler('missingComponentFile', array('className' => 'PostsController', 'component' => 'Sidebox', 'file' => 'sidebox.php')); + $ErrorHandler->render(); $result = ob_get_clean(); + $this->assertPattern('/

    Missing Component File<\/h2>/', $result); $this->assertPattern('/Create the class SideboxComponent<\/em> in file:/', $result); $this->assertPattern('/(\/|\\\)sidebox.php/', $result); @@ -644,10 +662,13 @@ class ErrorHandlerTest extends CakeTestCase { * @return void */ function testMissingComponentClass() { - $this->markTestIncomplete('Not implemented now'); + $exception = new MissingComponentClassException('SideboxComponent'); + $ErrorHandler = new ErrorHandler($exception); + ob_start(); - $ErrorHandler = new ErrorHandler('missingComponentClass', array('className' => 'PostsController', 'component' => 'Sidebox', 'file' => 'sidebox.php')); + $ErrorHandler->render(); $result = ob_get_clean(); + $this->assertPattern('/

    Missing Component Class<\/h2>/', $result); $this->assertPattern('/Create the class SideboxComponent<\/em> in file:/', $result); $this->assertPattern('/(\/|\\\)sidebox.php/', $result); From 465b15c64e38d1e04db32c8e62702618a9e0725d Mon Sep 17 00:00:00 2001 From: predominant Date: Sun, 29 Aug 2010 23:09:33 +1000 Subject: [PATCH 052/166] Removing reference assignments. --- cake/libs/session/database_session.php | 19 +++++-------------- 1 file changed, 5 insertions(+), 14 deletions(-) diff --git a/cake/libs/session/database_session.php b/cake/libs/session/database_session.php index 19c48dffe..31b136936 100644 --- a/cake/libs/session/database_session.php +++ b/cake/libs/session/database_session.php @@ -55,8 +55,7 @@ class DatabaseSession implements CakeSessionHandlerInterface { * @access private */ public static function read($id) { - $model =& ClassRegistry::getObject('Session'); - + $model = ClassRegistry::getObject('Session'); $row = $model->find('first', array( 'conditions' => array($model->primaryKey => $id) )); @@ -78,9 +77,7 @@ class DatabaseSession implements CakeSessionHandlerInterface { */ public static function write($id, $data) { $expires = time() + (Configure::read('Session.timeout') * 60); - $model =& ClassRegistry::getObject('Session'); - $return = $model->save(compact('id', 'data', 'expires')); - return $return; + return ClassRegistry::getObject('Session')->save(compact('id', 'data', 'expires')); } /** @@ -91,10 +88,7 @@ class DatabaseSession implements CakeSessionHandlerInterface { * @access private */ public static function destroy($id) { - $model =& ClassRegistry::getObject('Session'); - $return = $model->delete($id); - - return $return; + return ClassRegistry::getObject('Session')->delete($id); } /** @@ -105,13 +99,10 @@ class DatabaseSession implements CakeSessionHandlerInterface { * @access private */ public static function gc($expires = null) { - $model =& ClassRegistry::getObject('Session'); - if (!$expires) { $expires = time(); } - - $return = $model->deleteAll(array($model->alias . ".expires <" => $expires), false, false); - return $return; + $model = ClassRegistry::getObject('Session'); + return $model->deleteAll(array($model->alias . ".expires <" => $expires), false, false); } } From 99cde14432c730ef63a90ccffc5958f709c2fd11 Mon Sep 17 00:00:00 2001 From: mark_story Date: Sun, 29 Aug 2010 13:49:10 -0400 Subject: [PATCH 053/166] No more skipped tests for ErrorHandler. Removing missing_model as it was never called. --- cake/libs/error_handler.php | 43 ++----- cake/libs/view/errors/missing_model.ctp | 41 ------- cake/tests/cases/libs/error_handler.test.php | 115 +++++++++---------- 3 files changed, 68 insertions(+), 131 deletions(-) delete mode 100644 cake/libs/view/errors/missing_model.ctp diff --git a/cake/libs/error_handler.php b/cake/libs/error_handler.php index fa772e7e4..1d0502ee1 100644 --- a/cake/libs/error_handler.php +++ b/cake/libs/error_handler.php @@ -139,11 +139,15 @@ class ErrorHandler { * @param array $params Parameters for controller */ public function error404($error) { + $message = $error->getMessage(); + if (Configure::read('debug') == 0) { + $message = __('Not Found'); + } $url = Router::normalize($this->controller->request->here); $this->controller->response->statusCode(404); $this->controller->set(array( 'code' => 404, - 'name' => $error->getMessage(), + 'name' => $message, 'url' => h($url), )); $this->_outputMessage('error404'); @@ -155,18 +159,11 @@ class ErrorHandler { * @param array $params Parameters for controller */ public function error500($params) { - extract($params, EXTR_OVERWRITE); - - if (!isset($url)) { - $url = $this->controller->request->here; - } - $url = Router::normalize($url); - $this->controller->header("HTTP/1.0 500 Internal Server Error"); + $url = Router::normalize($this->controller->request->here); + $this->controller->response->statusCode(500); $this->controller->set(array( - 'code' => '500', 'name' => __('An Internal Error Has Occurred'), 'message' => h($url), - 'base' => $this->controller->request->base )); $this->_outputMessage('error500'); } @@ -175,14 +172,11 @@ class ErrorHandler { * * @param array $params Parameters for controller */ - public function missingController($params) { - extract($params, EXTR_OVERWRITE); - - $controllerName = str_replace('Controller', '', $className); + public function missingController($error) { + $controllerName = str_replace('Controller', '', $error->getMessage()); $this->controller->set(array( - 'controller' => $className, - 'controllerName' => $controllerName, - 'title' => __('Missing Controller') + 'controller' => $error->getMessage(), + 'controllerName' => $controllerName )); $this->_outputMessage('missingController'); } @@ -371,21 +365,6 @@ class ErrorHandler { $this->_outputMessage('missingComponentClass'); } -/** - * Renders the Missing Model class web page. - * - * @param unknown_type $params Parameters for controller - */ - public function missingModel($params) { - extract($params, EXTR_OVERWRITE); - - $this->controller->set(array( - 'model' => $className, - 'title' => __('Missing Model') - )); - $this->_outputMessage('missingModel'); - } - /** * Output message * diff --git a/cake/libs/view/errors/missing_model.ctp b/cake/libs/view/errors/missing_model.ctp deleted file mode 100644 index c3d7baa63..000000000 --- a/cake/libs/view/errors/missing_model.ctp +++ /dev/null @@ -1,41 +0,0 @@ - -

    -

    - : - %s could not be found.'), $model); ?> -

    -

    - : - ' . $model . '', APP_DIR . DS . 'models' . DS . Inflector::underscore($model) . '.php'); ?> -

    -
    -<?php
    -class  extends AppModel {
    -
    -	public $name = '';
    -
    -}
    -?>
    -
    -

    - : - -

    \ No newline at end of file diff --git a/cake/tests/cases/libs/error_handler.test.php b/cake/tests/cases/libs/error_handler.test.php index e8681eb66..e7ebf9af1 100644 --- a/cake/tests/cases/libs/error_handler.test.php +++ b/cake/tests/cases/libs/error_handler.test.php @@ -188,25 +188,13 @@ class MyCustomErrorHandler extends ErrorHandler { echo 'widget thing is missing'; } } - /** - * TestErrorHandler class + * Exception class for testing app error handlers and custom errors. * - * @package cake - * @subpackage cake.tests.cases.libs + * @package cake.test.cases.libs */ -class TestErrorHandler extends ErrorHandler { +class MissingWidgetThingException extends Error404Exception { } -/** - * stop method - * - * @access public - * @return void - */ - function _stop() { - return; - } -} /** * ErrorHandlerTest class @@ -257,34 +245,60 @@ class ErrorHandlerTest extends CakeTestCase { /** * test that methods declared in an ErrorHandler subclass are not converted - * into error404 when debug == 0 + * into error404 when debug > 0 * * @return void */ function testSubclassMethodsNotBeingConvertedToError() { - $this->markTestIncomplete('Not implemented now'); - $back = Configure::read('debug'); Configure::write('debug', 2); + + $exception = new MissingWidgetThingException('Widget not found'); + $ErrorHandler = new MyCustomErrorHandler($exception); + ob_start(); - $ErrorHandler = new MyCustomErrorHandler('missingWidgetThing', array('message' => 'doh!')); + $ErrorHandler->render(); $result = ob_get_clean(); + $this->assertEqual($result, 'widget thing is missing'); + } +/** + * test that subclass methods are not converted when debug = 0 + * + * @return void + */ + function testSubclassMethodsNotBeingConvertedDebug0() { Configure::write('debug', 0); - ob_start(); - $ErrorHandler = new MyCustomErrorHandler('missingWidgetThing', array('message' => 'doh!')); - $result = ob_get_clean(); - $this->assertEqual($result, 'widget thing is missing', 'Method declared in subclass converted to error404. %s'); + $exception = new MissingWidgetThingException('Widget not found'); + $ErrorHandler = new MyCustomErrorHandler($exception); + + $this->assertEqual('missingWidgetThing', $ErrorHandler->method); - Configure::write('debug', 0); ob_start(); - $ErrorHandler = new MyCustomErrorHandler('missingController', array( - 'className' => 'Missing', 'message' => 'Page not found' - )); + $ErrorHandler->render(); $result = ob_get_clean(); + + $this->assertEqual($result, 'widget thing is missing', 'Method declared in subclass converted to error404'); + } + +/** + * test that ErrorHandler subclasses properly convert framework errors. + * + * @return void + */ + function testSubclassConvertingFrameworkErrors() { + Configure::write('debug', 0); + + $exception = new MissingControllerException('PostsController'); + $ErrorHandler = new MyCustomErrorHandler($exception); + + $this->assertEqual('error404', $ErrorHandler->method); + + ob_start(); + $ErrorHandler->render(); + $result = ob_get_clean(); + $this->assertPattern('/Not Found/', $result, 'Method declared in error handler not converted to error404. %s'); - - Configure::write('debug', $back); } /** @@ -349,6 +363,8 @@ class ErrorHandlerTest extends CakeTestCase { $exception = new Error404Exception('Custom message'); $ErrorHandler = new ErrorHandler($exception); + $ErrorHandler->controller->response = $this->getMock('CakeResponse', array('statusCode')); + $ErrorHandler->controller->response->expects($this->once())->method('statusCode')->with(404); ob_start(); $ErrorHandler->render(); @@ -388,21 +404,16 @@ class ErrorHandlerTest extends CakeTestCase { * @access public * @return void */ - function testError500() { - $this->markTestIncomplete('Not implemented now'); - ob_start(); - $ErrorHandler = new ErrorHandler('error500', array( - 'message' => 'An Internal Error Has Occurred' - )); - $result = ob_get_clean(); - $this->assertPattern('/

    An Internal Error Has Occurred<\/h2>/', $result); + function testError500Message() { + $exception = new Error500Exception('An Internal Error Has Occurred'); + $ErrorHandler = new ErrorHandler($exception); + $ErrorHandler->controller->response = $this->getMock('CakeResponse', array('statusCode')); + $ErrorHandler->controller->response->expects($this->once())->method('statusCode')->with(500); ob_start(); - $ErrorHandler = new ErrorHandler('error500', array( - 'message' => 'An Internal Error Has Occurred', - 'code' => '500' - )); + $ErrorHandler->render(); $result = ob_get_clean(); + $this->assertPattern('/

    An Internal Error Has Occurred<\/h2>/', $result); } @@ -413,12 +424,15 @@ class ErrorHandlerTest extends CakeTestCase { * @return void */ function testMissingController() { - $this->markTestIncomplete('Not implemented now'); $this->skipIf(defined('APP_CONTROLLER_EXISTS'), '%s Need a non-existent AppController'); + $exception = new MissingControllerException('PostsController'); + $ErrorHandler = new ErrorHandler($exception); + ob_start(); - $ErrorHandler = new ErrorHandler('missingController', array('className' => 'PostsController')); + $ErrorHandler->render(); $result = ob_get_clean(); + $this->assertPattern('/

    Missing Controller<\/h2>/', $result); $this->assertPattern('/PostsController<\/em>/', $result); $this->assertPattern('/BlueberryComponent/', $result); @@ -674,19 +688,4 @@ class ErrorHandlerTest extends CakeTestCase { $this->assertPattern('/(\/|\\\)sidebox.php/', $result); } -/** - * testMissingModel method - * - * @access public - * @return void - */ - function testMissingModel() { - $this->markTestIncomplete('Not implemented now'); - ob_start(); - $ErrorHandler = new ErrorHandler('missingModel', array('className' => 'Article', 'file' => 'article.php')); - $result = ob_get_clean(); - $this->assertPattern('/

    Missing Model<\/h2>/', $result); - $this->assertPattern('/Article<\/em> could not be found./', $result); - $this->assertPattern('/(\/|\\\)article.php/', $result); - } } From 741f2972f9c6c1a22227483cc4e67ba185d8c825 Mon Sep 17 00:00:00 2001 From: mark_story Date: Sun, 29 Aug 2010 15:12:50 -0400 Subject: [PATCH 054/166] Removing non required attribute from missing controller error page. --- cake/libs/view/errors/missing_controller.ctp | 1 - 1 file changed, 1 deletion(-) diff --git a/cake/libs/view/errors/missing_controller.ctp b/cake/libs/view/errors/missing_controller.ctp index 0c7dd798b..855f0011d 100644 --- a/cake/libs/view/errors/missing_controller.ctp +++ b/cake/libs/view/errors/missing_controller.ctp @@ -30,7 +30,6 @@ <?php class extends AppController { - public $name = ''; } ?>

    From f1164c93d6b42c39b18aa3a308e7d8f597f14c28 Mon Sep 17 00:00:00 2001 From: mark_story Date: Sun, 29 Aug 2010 21:37:25 -0400 Subject: [PATCH 055/166] Updating the various CakeExceptions to take arrays in their constructors. This allows for the existing templates to continue working, as well as generalize the way in which errors are handled. This change also makes the messages coming out of exceptions more readable and removes string hackery. --- cake/dispatcher.php | 24 +- cake/libs/controller/component_collection.php | 10 +- cake/libs/controller/scaffold.php | 8 +- cake/libs/error_handler.php | 273 ++++-------------- cake/libs/exceptions.php | 160 +++++----- cake/libs/model/behavior_collection.php | 10 +- cake/libs/model/connection_manager.php | 2 +- cake/libs/model/model.php | 7 +- cake/libs/view/errors/missing_action.ctp | 2 +- .../view/errors/missing_behavior_class.ctp | 4 +- .../view/errors/missing_behavior_file.ctp | 2 +- .../view/errors/missing_component_class.ctp | 6 +- .../view/errors/missing_component_file.ctp | 4 +- cake/libs/view/errors/missing_connection.ctp | 2 +- ...ng_scaffolddb.ctp => missing_database.ctp} | 0 .../libs/view/errors/missing_helper_class.ctp | 4 +- cake/libs/view/errors/missing_helper_file.ctp | 2 +- cake/libs/view/errors/missing_table.ctp | 2 +- cake/libs/view/errors/private_action.ctp | 2 +- cake/libs/view/helper_collection.php | 18 +- cake/libs/view/view.php | 4 +- cake/tests/cases/libs/error_handler.test.php | 34 ++- 22 files changed, 233 insertions(+), 347 deletions(-) rename cake/libs/view/errors/{missing_scaffolddb.ctp => missing_database.ctp} (100%) diff --git a/cake/dispatcher.php b/cake/dispatcher.php index 54cf20dc7..cd5ae451a 100644 --- a/cake/dispatcher.php +++ b/cake/dispatcher.php @@ -134,7 +134,9 @@ class Dispatcher { if (!is_object($controller)) { Router::setRequestInfo($request); - throw new MissingControllerException(Inflector::camelize($request->params['controller']) . 'Controller'); + throw new MissingControllerException(array( + 'controller' => Inflector::camelize($request->params['controller']) . 'Controller' + )); } $privateAction = $request->params['action'][0] === '_'; $prefixes = Router::prefixes(); @@ -151,12 +153,10 @@ class Dispatcher { Router::setRequestInfo($request); if ($privateAction) { - $message = sprintf( - '%s::%s()', - Inflector::camelize($request->params['controller']) . "Controller", - $request->params['action'] - ); - throw new PrivateActionException($message); + throw new PrivateActionException(array( + 'controller' => Inflector::camelize($request->params['controller']) . "Controller", + 'action' => $request->params['action'] + )); } return $this->_invoke($controller, $request); @@ -184,12 +184,10 @@ class Dispatcher { App::import('Controller', 'Scaffold', false); return new Scaffold($controller, $request); } - $message = sprintf( - '%s::%s()', - Inflector::camelize($request->params['controller']) . "Controller", - $request->params['action'] - ); - throw new MissingActionException($message); + throw new MissingActionException(array( + 'controller' => Inflector::camelize($request->params['controller']) . "Controller", + 'action' => $request->params['action'] + )); } $result =& call_user_func_array(array(&$controller, $request->params['action']), $request->params['pass']); $response = $controller->getResponse(); diff --git a/cake/libs/controller/component_collection.php b/cake/libs/controller/component_collection.php index f0fc314e8..a4aea463b 100644 --- a/cake/libs/controller/component_collection.php +++ b/cake/libs/controller/component_collection.php @@ -54,10 +54,16 @@ class ComponentCollection extends ObjectCollection { $componentClass = $name . 'Component'; if (!class_exists($componentClass)) { if (!App::import('Component', $component)) { - throw new MissingComponentFileException(Inflector::underscore($component) . '.php'); + throw new MissingComponentFileException(array( + 'file' => Inflector::underscore($component) . '.php', + 'class' => $componentClass + )); } if (!class_exists($componentClass)) { - throw new MissingComponentFileException($component); + throw new MissingComponentFileException(array( + 'file' => Inflector::underscore($component) . '.php', + 'class' => $componentClass + )); } } $this->_loaded[$name] = new $componentClass($this, $settings); diff --git a/cake/libs/controller/scaffold.php b/cake/libs/controller/scaffold.php index 9d5779746..a5c3d7551 100644 --- a/cake/libs/controller/scaffold.php +++ b/cake/libs/controller/scaffold.php @@ -414,11 +414,13 @@ class Scaffold { break; } } else { - $message = sprintf('%s::%s()', $this->controller->name . "Controller", $request->action); - throw new MissingActionException($message); + throw new MissingActionException(array( + 'controller' => $this->controller->name, + 'action' => $request->action + )); } } else { - throw new MissingDatabaseException($this->ScaffoldModel->useDbConfig); + throw new MissingDatabaseException(array('connection' => $this->ScaffoldModel->useDbConfig)); } } diff --git a/cake/libs/error_handler.php b/cake/libs/error_handler.php index 1d0502ee1..7b3235a51 100644 --- a/cake/libs/error_handler.php +++ b/cake/libs/error_handler.php @@ -40,6 +40,27 @@ class ErrorHandler { */ public $controller = null; +/** + * template to render for CakeException + * + * @var string + */ + public $template = ''; + +/** + * The method corresponding to the Exception this object is for. + * + * @var string + */ + public $method = ''; + +/** + * The exception being handled. + * + * @var Exception + */ + public $error = null; + /** * Class constructor. * @@ -54,27 +75,27 @@ class ErrorHandler { if (method_exists($this->controller, 'apperror')) { return $this->controller->appError($exception); } - $method = Inflector::variable(str_replace('Exception', '', get_class($exception))); + $method = $template = Inflector::variable(str_replace('Exception', '', get_class($exception))); - if (!in_array($method, get_class_methods($this))) { - $method = 'error'; + if ($exception instanceof CakeException && !in_array($method, get_class_methods($this))) { + $method = '_cakeError'; } - if ($method !== 'error') { - if (Configure::read('debug') == 0) { - $code = $exception->getCode(); - $parentClass = get_parent_class($this); - if ($parentClass != 'ErrorHandler') { - $method = 'error404'; - } - $parentMethods = (array)get_class_methods($parentClass); - if (in_array($method, $parentMethods)) { - $method = 'error404'; - } - if ($code == 500) { - $method = 'error500'; - } + + if ($method !== 'error' && Configure::read('debug') == 0) { + $code = $exception->getCode(); + $parentClass = get_parent_class($this); + if ($parentClass != 'ErrorHandler') { + $method = 'error404'; + } + $parentMethods = (array)get_class_methods($parentClass); + if (in_array($method, $parentMethods)) { + $method = 'error404'; + } + if ($code == 500) { + $method = 'error500'; } } + $this->template = $template; $this->method = $method; $this->error = $exception; } @@ -133,6 +154,24 @@ class ErrorHandler { $this->error404($error); } +/** + * Generic handler for the internal framework errors CakePHP can generate. + * + * @param CakeExeption $error + * @return void + */ + protected function _cakeError(CakeException $error) { + $url = Router::normalize($this->controller->request->here); + $code = $error->getCode(); + $this->controller->response->statusCode($code); + $this->controller->set(array( + 'code' => $code, + 'url' => h($url), + )); + $this->controller->set($error->getAttributes()); + $this->_outputMessage($this->template); + } + /** * Convenience method to display a 404 page. * @@ -167,207 +206,11 @@ class ErrorHandler { )); $this->_outputMessage('error500'); } -/** - * Renders the Missing Controller web page. - * - * @param array $params Parameters for controller - */ - public function missingController($error) { - $controllerName = str_replace('Controller', '', $error->getMessage()); - $this->controller->set(array( - 'controller' => $error->getMessage(), - 'controllerName' => $controllerName - )); - $this->_outputMessage('missingController'); - } /** - * Renders the Missing Action web page. - * - * @param array $params Parameters for controller - */ - public function missingAction($error) { - $message = $error->getMessage(); - list($controllerName, $action) = explode('::', $message); - $this->controller->set(array( - 'controller' => $controllerName, - 'action' => $action, - )); - $this->_outputMessage('missingAction'); - } - -/** - * Renders the Private Action web page. - * - * @param array $params Parameters for controller - */ - public function privateAction($error) { - $message = $error->getMessage(); - list($controllerName, $action) = explode('::', $message); - $this->controller->set(array( - 'controller' => $controllerName, - 'action' => $action - )); - $this->_outputMessage('privateAction'); - } - -/** - * Renders the Missing Table web page. - * - * @param array $params Parameters for controller - */ - public function missingTable($error) { - $this->controller->header("HTTP/1.0 500 Internal Server Error"); - $this->controller->set(array( - 'model' => $error->getModel(), - 'table' => $error->getTable(), - )); - $this->_outputMessage('missingTable'); - } - -/** - * Renders the Missing Database web page. - * - * @param array $params Parameters for controller - */ - public function missingDatabase($exception) { - $this->controller->header("HTTP/1.0 500 Internal Server Error"); - $this->controller->set(array( - 'code' => '500', - 'title' => __('Scaffold Missing Database Connection') - )); - $this->_outputMessage('missingScaffolddb'); - } - -/** - * Renders the Missing View web page. - * - * @param array $params Parameters for controller - */ - public function missingView($error) { - $this->controller->set(array( - 'file' => $error->getMessage(), - )); - $this->_outputMessage('missingView'); - } - -/** - * Renders the Missing Layout web page. - * - * @param array $params Parameters for controller - */ - public function missingLayout($error) { - $this->controller->layout = 'default'; - $this->controller->set(array( - 'file' => $error->getMessage(), - )); - $this->_outputMessage('missingLayout'); - } - -/** - * Renders the Database Connection web page. - * - * @param array $params Parameters for controller - */ - public function missingConnection($error) { - $this->controller->header("HTTP/1.0 500 Internal Server Error"); - $this->controller->set(array( - 'code' => '500', - 'model' => $error->getMessage(), - )); - $this->_outputMessage('missingConnection'); - } - -/** - * Renders the Missing Helper file web page. - * - * @param array $params Parameters for controller - */ - public function missingHelperFile($error) { - list($class, $ext) = explode('.', $error->getMessage()); - $this->controller->set(array( - 'className' => Inflector::camelize($class), - 'file' => $error->getMessage() - )); - $this->_outputMessage('missingHelperFile'); - } - -/** - * Renders the Missing Helper class web page. - * - * @param array $params Parameters for controller - */ - public function missingHelperClass($error) { - $class = $error->getMessage(); - $file = Inflector::underscore(str_replace('Helper', '', $error->getMessage())) . '.php'; - $this->controller->set(array( - 'className' => $class, - 'file' => $file, - )); - $this->_outputMessage('missingHelperClass'); - } - -/** - * Renders the Missing Behavior file web page. - * - * @param array $params Parameters for controller - */ - public function missingBehaviorFile($error) { - list($class, $ext) = explode('.', $error->getMessage()); - $this->controller->set(array( - 'className' => Inflector::camelize($class), - 'file' => $error->getMessage() - )); - $this->_outputMessage('missingBehaviorFile'); - } - -/** - * Renders the Missing Behavior class web page. - * - * @param array $params Parameters for controller - */ - public function missingBehaviorClass($error) { - $class = $error->getMessage(); - $file = Inflector::underscore(str_replace('Behavior', '', $error->getMessage())) . '.php'; - $this->controller->set(array( - 'className' => $class, - 'file' => $file, - )); - $this->_outputMessage('missingBehaviorClass'); - } - -/** - * Renders the Missing Component file web page. - * - * @param array $params Parameters for controller - */ - public function missingComponentFile($error) { - list($class, $ext) = explode('.', $error->getMessage()); - $this->controller->set(array( - 'className' => Inflector::camelize($class), - 'file' => $error->getMessage() - )); - $this->_outputMessage('missingComponentFile'); - } - -/** - * Renders the Missing Component class web page. - * - * @param array $params Parameters for controller - */ - public function missingComponentClass($error) { - $class = $error->getMessage(); - $file = Inflector::underscore(str_replace('Component', '', $error->getMessage())) . '.php'; - $this->controller->set(array( - 'className' => $class, - 'file' => $file, - )); - $this->_outputMessage('missingComponentClass'); - } - -/** - * Output message + * Generate the response using the controller object. * + * @param string $template The template to render. */ protected function _outputMessage($template) { $this->controller->render($template); diff --git a/cake/libs/exceptions.php b/cake/libs/exceptions.php index 51361d6c3..fcf324f6f 100644 --- a/cake/libs/exceptions.php +++ b/cake/libs/exceptions.php @@ -18,38 +18,84 @@ * @since CakePHP(tm) v 2.0 * @license MIT License (http://www.opensource.org/licenses/mit-license.php) */ + + +class Error404Exception extends RuntimeException { + public function __construct($message, $code = 404) { + if (empty($message)) { + $message = __('Not Found'); + } + parent::__construct($message, $code); + } +} +class Error500Exception extends CakeException { + public function __construct($message, $code = 500) { + if (empty($message)) { + $message = __('Internal Server Error'); + } + parent::__construct($message, $code); + } +} + /** * CakeException is used a base class for CakePHP's internal exceptions. * In general framework errors are interpreted as 500 code errors. * * @package cake.libs */ -class CakeException extends RuntimeException { - public function __construct($message, $code = 500, Exception $previous = null) { - parent::__construct($message, $code, $previous); +class CakeException extends RuntimeException { + + protected $_attributes = array(); + + protected $_messageTemplate = ''; + + public function __construct($message, $code = 500) { + if (is_array($message)) { + $this->_attributes = $message; + $message = vsprintf(__($this->_messageTemplate), $message); + } + parent::__construct($message, $code); + } + + public function getAttributes() { + return $this->_attributes; } } - -class Error404Exception extends RuntimeException { - public function __construct($message, $code = 404, Exception $previous = null) { - parent::__construct($message, $code, $previous); - } -} -class Error500Exception extends CakeException { } - /* * Exceptions used by Dispatcher */ -class MissingControllerException extends Error404Exception { } -class MissingActionException extends Error404Exception { } -class PrivateActionException extends Error404Exception { } +class MissingControllerException extends CakeException { + protected $_messageTemplate = 'Controller class %s could not be found.'; + + public function __construct($message, $code = 404) { + parent::__construct($message, $code); + } +} +class MissingActionException extends CakeException { + protected $_messageTemplate = 'Action %s::%s() could not be found.'; + + public function __construct($message, $code = 404) { + parent::__construct($message, $code); + } +} +class PrivateActionException extends CakeException { + protected $_messageTemplate = 'Private Action %s::%s() is not directly accessible.'; + + public function __construct($message, $code = 404, Exception $previous = null) { + parent::__construct($message, $code, $previous); + } +} /** * Exceptions used by the ComponentCollection. */ -class MissingComponentFileException extends CakeException { } -class MissingComponentClassException extends CakeException { } +class MissingComponentFileException extends CakeException { + protected $_messageTemplate = 'Component File "%s" is missing.'; +} +class MissingComponentClassException extends CakeException { + protected $_messageTemplate = 'Component class "%s" is missing.'; +} /** * Runtime Exceptions for behaviors @@ -60,68 +106,48 @@ class MissingBehaviorClassException extends CakeException { } /** * Runtime Exceptions for Views */ -class MissingViewException extends CakeException { } -class MissingLayoutException extends CakeException { } +class MissingViewException extends CakeException { + protected $_messageTemplate = 'View file "%s" is missing.'; +} +class MissingLayoutException extends CakeException { + protected $_messageTemplate = 'Layout file "%s" is missing.'; +} + +/** + * Exceptions used by the HelperCollection. + */ +class MissingHelperFileException extends CakeException { + protected $_messageTemplate = 'Helper File "%s" is missing.'; +} +class MissingHelperClassException extends CakeException { + protected $_messageTemplate = 'Helper class "%s" is missing.'; +} + /** * Runtime Exceptions for ConnectionManager */ -class MissingDatabaseException extends CakeException {} -class MissingConnectionException extends CakeException {} +class MissingDatabaseException extends CakeException { + protected $_messageTemplate = 'Database connection "%s" could not be found.'; +} +class MissingConnectionException extends CakeException { + protected $_messageTemplate = 'Database connection "%s" is missing.'; +} /** * Exceptions used by the TaskCollection. */ -class MissingTaskFileException extends CakeException { } -class MissingTaskClassException extends CakeException { } +class MissingTaskFileException extends CakeException { + protected $_messageTemplate = 'Task file "%s" is missing.'; +} +class MissingTaskClassException extends CakeException { + protected $_messageTemplate = 'Task class "%s" is missing.'; +} /** * Exception class to be thrown when a database table is not found in the datasource * */ class MissingTableException extends CakeException { -/** - * The name of the model wanting to load the database table - * - * @var string - */ - protected $model; -/** - * The name of the missing table - * - * @var string - */ - protected $table; - -/** - * Exception costructor - * - * @param string $model The name of the model wanting to load the database table - * @param string $table The name of the missing table - * @return void - */ - public function __construct($model, $table) { - $this->model = $model; - $this->table = $table; - $message = sprintf(__('Database table %s for model %s was not found.'), $table, $model); - parent::__construct($message); - } - -/** - * Returns the name of the model wanting to load the database table - * - * @return string - */ - public function getModel() { - return $this->model; - } - -/** - * Returns the name of the missing table - * - * @return string - */ - public function getTable() { - return $this->table; - } -} \ No newline at end of file + protected $_messageTemplate = 'Database table %s for model %s was not found.'; +} diff --git a/cake/libs/model/behavior_collection.php b/cake/libs/model/behavior_collection.php index 8895a798a..71c6cbf75 100644 --- a/cake/libs/model/behavior_collection.php +++ b/cake/libs/model/behavior_collection.php @@ -94,10 +94,16 @@ class BehaviorCollection extends ObjectCollection { $class = $name . 'Behavior'; if (!App::import('Behavior', $behavior)) { - throw new MissingBehaviorFileException(Inflector::underscore($behavior) . '.php'); + throw new MissingBehaviorFileException(array( + 'file' => Inflector::underscore($behavior) . '.php', + 'class' => $class + )); } if (!class_exists($class)) { - throw new MissingBehaviorClassException(Inflector::underscore($class)); + throw new MissingBehaviorClassException(array( + 'file' => Inflector::underscore($behavior) . '.php', + 'class' => $class + )); } if (!isset($this->{$name})) { diff --git a/cake/libs/model/connection_manager.php b/cake/libs/model/connection_manager.php index 1937663ff..143a16f3a 100644 --- a/cake/libs/model/connection_manager.php +++ b/cake/libs/model/connection_manager.php @@ -222,7 +222,7 @@ class ConnectionManager { $this->_connectionsEnum[$name] = $this->__connectionData($config); } } else { - throw new MissingConnectionException('ConnectionManager'); + throw new MissingConnectionException(array('class' => 'ConnectionManager')); } } diff --git a/cake/libs/model/model.php b/cake/libs/model/model.php index 43fec9794..a1dc31420 100644 --- a/cake/libs/model/model.php +++ b/cake/libs/model/model.php @@ -799,7 +799,10 @@ class Model extends Object { if ($db->isInterfaceSupported('listSources')) { $sources = $db->listSources(); if (is_array($sources) && !in_array(strtolower($this->tablePrefix . $tableName), array_map('strtolower', $sources))) { - throw new MissingTableException($this->alias, $this->tablePrefix . $tableName); + throw new MissingTableException(array( + 'table' => $this->tablePrefix . $tableName, + 'class' => $this->alias + )); } $this->_schema = null; } @@ -2825,7 +2828,7 @@ class Model extends Object { } if (empty($db) || !is_object($db)) { - throw new MissingConnectionException($this->useDbConfig); + throw new MissingConnectionException(array('class' => $this->name)); } } diff --git a/cake/libs/view/errors/missing_action.ctp b/cake/libs/view/errors/missing_action.ctp index 3bb14ceac..fcaf5e5bf 100644 --- a/cake/libs/view/errors/missing_action.ctp +++ b/cake/libs/view/errors/missing_action.ctp @@ -24,7 +24,7 @@

    : - ' . $controller . '::', '' . $action . '', APP_DIR . DS . 'controllers' . DS . Inflector::underscore($controller) . '.php'); ?> + ' . $controller . '::', '' . $action . '()', APP_DIR . DS . 'controllers' . DS . Inflector::underscore($controller) . '.php'); ?>

     <?php
    diff --git a/cake/libs/view/errors/missing_behavior_class.ctp b/cake/libs/view/errors/missing_behavior_class.ctp
    index 58f0aa2cb..09dd42cbd 100644
    --- a/cake/libs/view/errors/missing_behavior_class.ctp
    +++ b/cake/libs/view/errors/missing_behavior_class.ctp
    @@ -20,7 +20,7 @@
     

    : - %s can not be found or does not exist.'), $className); ?> + %s can not be found or does not exist.'), $class); ?>

    : @@ -28,7 +28,7 @@

     <?php
    -class  extends ModelBehavior {
    +class  extends ModelBehavior {
     
     }
     ?>
    diff --git a/cake/libs/view/errors/missing_behavior_file.ctp b/cake/libs/view/errors/missing_behavior_file.ctp
    index 23ae88e17..aba397885 100644
    --- a/cake/libs/view/errors/missing_behavior_file.ctp
    +++ b/cake/libs/view/errors/missing_behavior_file.ctp
    @@ -28,7 +28,7 @@
     

     <?php
    -class  extends ModelBehavior {
    +class  extends ModelBehavior {
     
     }
     ?>
    diff --git a/cake/libs/view/errors/missing_component_class.ctp b/cake/libs/view/errors/missing_component_class.ctp
    index 9a35e113c..6829c781d 100644
    --- a/cake/libs/view/errors/missing_component_class.ctp
    +++ b/cake/libs/view/errors/missing_component_class.ctp
    @@ -20,15 +20,15 @@
     

    : - ' . $className . ''); ?> + ' . $class . ''); ?>

    : - ' . $className . '', APP_DIR . DS . 'controllers' . DS . 'components' . DS . $file); ?> + ' . $class . '', APP_DIR . DS . 'controllers' . DS . 'components' . DS . $file); ?>

     <?php
    -class  extends Component {
    +class extends Component {
    } ?> diff --git a/cake/libs/view/errors/missing_component_file.ctp b/cake/libs/view/errors/missing_component_file.ctp index 67f02cf08..ff57d432b 100644 --- a/cake/libs/view/errors/missing_component_file.ctp +++ b/cake/libs/view/errors/missing_component_file.ctp @@ -24,11 +24,11 @@

    : - ' . $className . 'Component', APP_DIR . DS . 'controllers' . DS . 'components' . DS . $file); ?> + ' . $class . '', APP_DIR . DS . 'controllers' . DS . 'components' . DS . $file); ?>

     <?php
    -class Component extends Component {
    +class extends Component {
    } ?> diff --git a/cake/libs/view/errors/missing_connection.ctp b/cake/libs/view/errors/missing_connection.ctp index 51d082d31..633997e7e 100644 --- a/cake/libs/view/errors/missing_connection.ctp +++ b/cake/libs/view/errors/missing_connection.ctp @@ -20,7 +20,7 @@

    : - +

    : diff --git a/cake/libs/view/errors/missing_scaffolddb.ctp b/cake/libs/view/errors/missing_database.ctp similarity index 100% rename from cake/libs/view/errors/missing_scaffolddb.ctp rename to cake/libs/view/errors/missing_database.ctp diff --git a/cake/libs/view/errors/missing_helper_class.ctp b/cake/libs/view/errors/missing_helper_class.ctp index a79bf9eec..9de192c14 100644 --- a/cake/libs/view/errors/missing_helper_class.ctp +++ b/cake/libs/view/errors/missing_helper_class.ctp @@ -20,7 +20,7 @@

    : - %s can not be found or does not exist.'), $className); ?> + %s can not be found or does not exist.'), $class); ?>

    : @@ -28,7 +28,7 @@

     <?php
    -class  extends AppHelper {
    +class  extends AppHelper {
     
     }
     ?>
    diff --git a/cake/libs/view/errors/missing_helper_file.ctp b/cake/libs/view/errors/missing_helper_file.ctp
    index caa7ca119..537ca3ad0 100644
    --- a/cake/libs/view/errors/missing_helper_file.ctp
    +++ b/cake/libs/view/errors/missing_helper_file.ctp
    @@ -28,7 +28,7 @@
     

     <?php
    -class  extends AppHelper {
    +class  extends AppHelper {
     
     }
     ?>
    diff --git a/cake/libs/view/errors/missing_table.ctp b/cake/libs/view/errors/missing_table.ctp
    index 3f0594e26..33d009293 100644
    --- a/cake/libs/view/errors/missing_table.ctp
    +++ b/cake/libs/view/errors/missing_table.ctp
    @@ -20,7 +20,7 @@
     

    : - ' . $table . '', '' . $model . ''); ?> + ' . $table . '', '' . $class . ''); ?>

    : diff --git a/cake/libs/view/errors/private_action.ctp b/cake/libs/view/errors/private_action.ctp index 20236e31f..ab9f13cdc 100644 --- a/cake/libs/view/errors/private_action.ctp +++ b/cake/libs/view/errors/private_action.ctp @@ -20,7 +20,7 @@

    : - ' . $controller . '::', '' . $action . ''); ?> + ' . $controller . '::', '' . $action . '()'); ?>

    : diff --git a/cake/libs/view/helper_collection.php b/cake/libs/view/helper_collection.php index 74683db93..faa63b14a 100644 --- a/cake/libs/view/helper_collection.php +++ b/cake/libs/view/helper_collection.php @@ -54,10 +54,16 @@ class HelperCollection extends ObjectCollection { $helperClass = $name . 'Helper'; if (!class_exists($helperClass)) { if (!App::import('Helper', $helper)) { - throw new MissingHelperFileException(Inflector::underscore($name) . '.php'); + throw new MissingHelperFileException(array( + 'class' => $helperClass, + 'file' => Inflector::underscore($name) . '.php' + )); } if (!class_exists($helperClass)) { - throw new MissingHelperClassException($helperClass); + throw new MissingHelperClassException(array( + 'class' => $helperClass, + 'file' => Inflector::underscore($name) . '.php' + )); } } $this->_loaded[$name] = new $helperClass($this->_View, $settings); @@ -73,10 +79,4 @@ class HelperCollection extends ObjectCollection { return $this->_loaded[$name]; } -} -/** - * Exceptions used by the HelperCollection. - */ -class MissingHelperFileException extends RuntimeException { } - -class MissingHelperClassException extends RuntimeException { } \ No newline at end of file +} \ No newline at end of file diff --git a/cake/libs/view/view.php b/cake/libs/view/view.php index 622f6f3e6..be32b3a20 100644 --- a/cake/libs/view/view.php +++ b/cake/libs/view/view.php @@ -791,7 +791,7 @@ class View extends Object { } } } - throw new MissingViewException($defaultPath . $name . $this->ext); + throw new MissingViewException(array('file' => $defaultPath . $name . $this->ext)); } /** @@ -824,7 +824,7 @@ class View extends Object { } } } - throw new MissingLayoutException($paths[0] . $file . $this->ext); + throw new MissingLayoutException(array('file' => $paths[0] . $file . $this->ext)); } /** diff --git a/cake/tests/cases/libs/error_handler.test.php b/cake/tests/cases/libs/error_handler.test.php index e7ebf9af1..9c5d8a22f 100644 --- a/cake/tests/cases/libs/error_handler.test.php +++ b/cake/tests/cases/libs/error_handler.test.php @@ -426,7 +426,7 @@ class ErrorHandlerTest extends CakeTestCase { function testMissingController() { $this->skipIf(defined('APP_CONTROLLER_EXISTS'), '%s Need a non-existent AppController'); - $exception = new MissingControllerException('PostsController'); + $exception = new MissingControllerException(array('controller' => 'PostsController')); $ErrorHandler = new ErrorHandler($exception); ob_start(); @@ -445,7 +445,7 @@ class ErrorHandlerTest extends CakeTestCase { * @return void */ function testMissingAction() { - $exception = new MissingActionException('PostsController::index()'); + $exception = new MissingActionException(array('controller' => 'PostsController', 'action' => 'index')); $ErrorHandler = new ErrorHandler($exception); ob_start(); @@ -473,7 +473,7 @@ class ErrorHandlerTest extends CakeTestCase { * @return void */ function testPrivateAction() { - $exception = new PrivateActionException('PostsController::_secretSauce()'); + $exception = new PrivateActionException(array('controller' => 'PostsController' , 'action' => '_secretSauce')); $ErrorHandler = new ErrorHandler($exception); ob_start(); @@ -491,14 +491,15 @@ class ErrorHandlerTest extends CakeTestCase { * @return void */ function testMissingTable() { - $exception = new MissingTableException('Article', 'articles'); + $exception = new MissingTableException(array('table' => 'articles', 'class' => 'Article')); $ErrorHandler = new ErrorHandler($exception); + $ErrorHandler->controller->response = $this->getMock('CakeResponse', array('statusCode')); + $ErrorHandler->controller->response->expects($this->once())->method('statusCode')->with(500); ob_start(); $ErrorHandler->render(); $result = ob_get_clean(); - $this->assertPattern('/HTTP\/1\.0 500 Internal Server Error/', $result); $this->assertPattern('/

    Missing Database Table<\/h2>/', $result); $this->assertPattern('/table articles<\/em> for model Article<\/em>/', $result); } @@ -510,14 +511,15 @@ class ErrorHandlerTest extends CakeTestCase { * @return void */ function testMissingDatabase() { - $exception = new MissingDatabaseException('default'); + $exception = new MissingDatabaseException(array('connection' => 'default')); $ErrorHandler = new ErrorHandler($exception); + $ErrorHandler->controller->response = $this->getMock('CakeResponse', array('statusCode')); + $ErrorHandler->controller->response->expects($this->once())->method('statusCode')->with(500); ob_start(); $ErrorHandler->render(); $result = ob_get_clean(); - $this->assertPattern('/HTTP\/1\.0 500 Internal Server Error/', $result); $this->assertPattern('/

    Missing Database Connection<\/h2>/', $result); $this->assertPattern('/Confirm you have created the file/', $result); } @@ -529,7 +531,7 @@ class ErrorHandlerTest extends CakeTestCase { * @return void */ function testMissingView() { - $exception = new MissingViewException('/posts/about.ctp'); + $exception = new MissingViewException(array('file' => '/posts/about.ctp')); $ErrorHandler = new ErrorHandler($exception); ob_start(); @@ -546,7 +548,7 @@ class ErrorHandlerTest extends CakeTestCase { * @return void */ function testMissingLayout() { - $exception = new MissingLayoutException('layouts/my_layout.ctp'); + $exception = new MissingLayoutException(array('file' => 'layouts/my_layout.ctp')); $ErrorHandler = new ErrorHandler($exception); ob_start(); @@ -564,7 +566,7 @@ class ErrorHandlerTest extends CakeTestCase { * @return void */ function testMissingConnection() { - $exception = new MissingConnectionException('Article'); + $exception = new MissingConnectionException(array('class' => 'Article')); $ErrorHandler = new ErrorHandler($exception); ob_start(); @@ -582,7 +584,7 @@ class ErrorHandlerTest extends CakeTestCase { * @return void */ function testMissingHelperFile() { - $exception = new MissingHelperFileException('my_custom.php'); + $exception = new MissingHelperFileException(array('file' => 'my_custom.php', 'class' => 'MyCustomHelper')); $ErrorHandler = new ErrorHandler($exception); ob_start(); @@ -601,7 +603,7 @@ class ErrorHandlerTest extends CakeTestCase { * @return void */ function testMissingHelperClass() { - $exception = new MissingHelperClassException('MyCustomHelper'); + $exception = new MissingHelperClassException(array('file' => 'my_custom.php', 'class' => 'MyCustomHelper')); $ErrorHandler = new ErrorHandler($exception); ob_start(); @@ -620,7 +622,7 @@ class ErrorHandlerTest extends CakeTestCase { * @return void */ function testMissingBehaviorFile() { - $exception = new MissingBehaviorFileException('my_custom.php'); + $exception = new MissingBehaviorFileException(array('file' => 'my_custom.php', 'class' => 'MyCustomBehavior')); $ErrorHandler = new ErrorHandler($exception); ob_start(); @@ -639,7 +641,7 @@ class ErrorHandlerTest extends CakeTestCase { * @return void */ function testMissingBehaviorClass() { - $exception = new MissingBehaviorClassException('MyCustomBehavior'); + $exception = new MissingBehaviorClassException(array('file' => 'my_custom.php', 'class' => 'MyCustomBehavior')); $ErrorHandler = new ErrorHandler($exception); ob_start(); @@ -657,7 +659,7 @@ class ErrorHandlerTest extends CakeTestCase { * @return void */ function testMissingComponentFile() { - $exception = new MissingComponentFileException('sidebox.php'); + $exception = new MissingComponentFileException(array('file' => 'sidebox.php', 'class' => 'SideboxComponent')); $ErrorHandler = new ErrorHandler($exception); ob_start(); @@ -676,7 +678,7 @@ class ErrorHandlerTest extends CakeTestCase { * @return void */ function testMissingComponentClass() { - $exception = new MissingComponentClassException('SideboxComponent'); + $exception = new MissingComponentClassException(array('file' => 'sidebox.php', 'class' => 'SideboxComponent')); $ErrorHandler = new ErrorHandler($exception); ob_start(); From efaa2e117746307c5be910a0b14f0434163e7ab9 Mon Sep 17 00:00:00 2001 From: mark_story Date: Sun, 29 Aug 2010 21:53:44 -0400 Subject: [PATCH 056/166] Refactoring test case to use a dataprovider for the uniform/copy paste test cases. --- cake/tests/cases/libs/error_handler.test.php | 367 +++++++------------ 1 file changed, 133 insertions(+), 234 deletions(-) diff --git a/cake/tests/cases/libs/error_handler.test.php b/cake/tests/cases/libs/error_handler.test.php index 9c5d8a22f..d36af6a9b 100644 --- a/cake/tests/cases/libs/error_handler.test.php +++ b/cake/tests/cases/libs/error_handler.test.php @@ -438,256 +438,155 @@ class ErrorHandlerTest extends CakeTestCase { $this->assertPattern('/BlueberryComponent/', $result); } + + /* TODO: Integration test that needs to be moved + ob_start(); + $dispatcher = new Dispatcher('/blueberry/inexistent'); + $result = ob_get_clean(); + $this->assertPattern('/

    Missing Method in BlueberryController<\/h2>/', $result); + $this->assertPattern('/BlueberryController::<\/em>inexistent\(\)<\/em>/', $result); + $this->assertNoPattern('/Location: (.*)\/users\/login/', $result); + $this->assertNoPattern('/Stopped with status: 0/', $result); + */ + /** - * testMissingAction method + * Returns an array of tests to run for the various CakeException classes. * - * @access public * @return void */ - function testMissingAction() { - $exception = new MissingActionException(array('controller' => 'PostsController', 'action' => 'index')); - $ErrorHandler = new ErrorHandler($exception); - - ob_start(); - $ErrorHandler->render(); - $result = ob_get_clean(); - - $this->assertPattern('/

    Missing Method in PostsController<\/h2>/', $result); - $this->assertPattern('/PostsController::<\/em>index\(\)<\/em>/', $result); - - /* TODO: Integration test that needs to be moved - ob_start(); - $dispatcher = new Dispatcher('/blueberry/inexistent'); - $result = ob_get_clean(); - $this->assertPattern('/

    Missing Method in BlueberryController<\/h2>/', $result); - $this->assertPattern('/BlueberryController::<\/em>inexistent\(\)<\/em>/', $result); - $this->assertNoPattern('/Location: (.*)\/users\/login/', $result); - $this->assertNoPattern('/Stopped with status: 0/', $result); - */ + public static function testProvider() { + return array( + array( + new MissingActionException(array('controller' => 'PostsController', 'action' => 'index')), + array( + '/

    Missing Method in PostsController<\/h2>/', + '/PostsController::<\/em>index\(\)<\/em>/' + ), + 404 + ), + array( + new PrivateActionException(array('controller' => 'PostsController' , 'action' => '_secretSauce')), + array( + '/

    Private Method in PostsController<\/h2>/', + '/PostsController::<\/em>_secretSauce\(\)<\/em>/' + ), + 404 + ), + array( + new MissingTableException(array('table' => 'articles', 'class' => 'Article')), + array( + '/

    Missing Database Table<\/h2>/', + '/table articles<\/em> for model Article<\/em>/' + ), + 500 + ), + array( + new MissingDatabaseException(array('connection' => 'default')), + array( + '/

    Missing Database Connection<\/h2>/', + '/Confirm you have created the file/' + ), + 500 + ), + array( + new MissingViewException(array('file' => '/posts/about.ctp')), + array( + "/posts\/about.ctp/" + ), + 500 + ), + array( + new MissingLayoutException(array('file' => 'layouts/my_layout.ctp')), + array( + "/Missing Layout/", + "/layouts\/my_layout.ctp/" + ), + 500 + ), + array( + new MissingConnectionException(array('class' => 'Article')), + array( + '/

    Missing Database Connection<\/h2>/', + '/Article requires a database connection/' + ), + 500 + ), + array( + new MissingHelperFileException(array('file' => 'my_custom.php', 'class' => 'MyCustomHelper')), + array( + '/

    Missing Helper File<\/h2>/', + '/Create the class below in file:/', + '/(\/|\\\)my_custom.php/' + ), + 500 + ), + array( + new MissingHelperClassException(array('file' => 'my_custom.php', 'class' => 'MyCustomHelper')), + array( + '/

    Missing Helper Class<\/h2>/', + '/The helper class MyCustomHelper<\/em> can not be found or does not exist./', + '/(\/|\\\)my_custom.php/', + ), + 500 + ), + array( + new MissingBehaviorFileException(array('file' => 'my_custom.php', 'class' => 'MyCustomBehavior')), + array( + '/

    Missing Behavior File<\/h2>/', + '/Create the class below in file:/', + '/(\/|\\\)my_custom.php/', + ), + 500 + ), + array( + new MissingBehaviorClassException(array('file' => 'my_custom.php', 'class' => 'MyCustomBehavior')), + array( + '/The behavior class MyCustomBehavior<\/em> can not be found or does not exist./', + '/(\/|\\\)my_custom.php/' + ), + 500 + ), + array( + new MissingComponentFileException(array('file' => 'sidebox.php', 'class' => 'SideboxComponent')), + array( + '/

    Missing Component File<\/h2>/', + '/Create the class SideboxComponent<\/em> in file:/', + '/(\/|\\\)sidebox.php/' + ), + 500 + ), + array( + new MissingComponentClassException(array('file' => 'sidebox.php', 'class' => 'SideboxComponent')), + array( + '/

    Missing Component Class<\/h2>/', + '/Create the class SideboxComponent<\/em> in file:/', + '/(\/|\\\)sidebox.php/' + ), + 500 + ) + + ); } /** - * testPrivateAction method + * Test the various CakeException sub classes * - * @access public + * @dataProvider testProvider * @return void */ - function testPrivateAction() { - $exception = new PrivateActionException(array('controller' => 'PostsController' , 'action' => '_secretSauce')); - $ErrorHandler = new ErrorHandler($exception); - - ob_start(); - $ErrorHandler->render(); - $result = ob_get_clean(); - - $this->assertPattern('/

    Private Method in PostsController<\/h2>/', $result); - $this->assertPattern('/PostsController::<\/em>_secretSauce\(\)<\/em>/', $result); - } - -/** - * testMissingTable method - * - * @access public - * @return void - */ - function testMissingTable() { - $exception = new MissingTableException(array('table' => 'articles', 'class' => 'Article')); + function testCakeExceptionHandling($exception, $patterns, $code) { $ErrorHandler = new ErrorHandler($exception); $ErrorHandler->controller->response = $this->getMock('CakeResponse', array('statusCode')); - $ErrorHandler->controller->response->expects($this->once())->method('statusCode')->with(500); + $ErrorHandler->controller->response->expects($this->once()) + ->method('statusCode') + ->with($code); ob_start(); $ErrorHandler->render(); $result = ob_get_clean(); - $this->assertPattern('/

    Missing Database Table<\/h2>/', $result); - $this->assertPattern('/table articles<\/em> for model Article<\/em>/', $result); + foreach ($patterns as $pattern) { + $this->assertPattern($pattern, $result); + } } - -/** - * testMissingDatabase method - * - * @access public - * @return void - */ - function testMissingDatabase() { - $exception = new MissingDatabaseException(array('connection' => 'default')); - $ErrorHandler = new ErrorHandler($exception); - $ErrorHandler->controller->response = $this->getMock('CakeResponse', array('statusCode')); - $ErrorHandler->controller->response->expects($this->once())->method('statusCode')->with(500); - - ob_start(); - $ErrorHandler->render(); - $result = ob_get_clean(); - - $this->assertPattern('/

    Missing Database Connection<\/h2>/', $result); - $this->assertPattern('/Confirm you have created the file/', $result); - } - -/** - * testMissingView method - * - * @access public - * @return void - */ - function testMissingView() { - $exception = new MissingViewException(array('file' => '/posts/about.ctp')); - $ErrorHandler = new ErrorHandler($exception); - - ob_start(); - $ErrorHandler->render(); - $result = ob_get_clean(); - - $this->assertPattern("/posts\/about.ctp/", $result); - } - -/** - * testMissingLayout method - * - * @access public - * @return void - */ - function testMissingLayout() { - $exception = new MissingLayoutException(array('file' => 'layouts/my_layout.ctp')); - $ErrorHandler = new ErrorHandler($exception); - - ob_start(); - $ErrorHandler->render(); - $result = ob_get_clean(); - - $this->assertPattern("/Missing Layout/", $result); - $this->assertPattern("/layouts\/my_layout.ctp/", $result); - } - -/** - * testMissingConnection method - * - * @access public - * @return void - */ - function testMissingConnection() { - $exception = new MissingConnectionException(array('class' => 'Article')); - $ErrorHandler = new ErrorHandler($exception); - - ob_start(); - $ErrorHandler->render(); - $result = ob_get_clean(); - - $this->assertPattern('/

    Missing Database Connection<\/h2>/', $result); - $this->assertPattern('/Article requires a database connection/', $result); - } - -/** - * testMissingHelperFile method - * - * @access public - * @return void - */ - function testMissingHelperFile() { - $exception = new MissingHelperFileException(array('file' => 'my_custom.php', 'class' => 'MyCustomHelper')); - $ErrorHandler = new ErrorHandler($exception); - - ob_start(); - $ErrorHandler->render(); - $result = ob_get_clean(); - - $this->assertPattern('/

    Missing Helper File<\/h2>/', $result); - $this->assertPattern('/Create the class below in file:/', $result); - $this->assertPattern('/(\/|\\\)my_custom.php/', $result); - } - -/** - * testMissingHelperClass method - * - * @access public - * @return void - */ - function testMissingHelperClass() { - $exception = new MissingHelperClassException(array('file' => 'my_custom.php', 'class' => 'MyCustomHelper')); - $ErrorHandler = new ErrorHandler($exception); - - ob_start(); - $ErrorHandler->render(); - $result = ob_get_clean(); - - $this->assertPattern('/

    Missing Helper Class<\/h2>/', $result); - $this->assertPattern('/The helper class MyCustomHelper<\/em> can not be found or does not exist./', $result); - $this->assertPattern('/(\/|\\\)my_custom.php/', $result); - } - -/** - * test missingBehaviorFile method - * - * @access public - * @return void - */ - function testMissingBehaviorFile() { - $exception = new MissingBehaviorFileException(array('file' => 'my_custom.php', 'class' => 'MyCustomBehavior')); - $ErrorHandler = new ErrorHandler($exception); - - ob_start(); - $ErrorHandler->render(); - $result = ob_get_clean(); - - $this->assertPattern('/

    Missing Behavior File<\/h2>/', $result); - $this->assertPattern('/Create the class below in file:/', $result); - $this->assertPattern('/(\/|\\\)my_custom.php/', $result); - } - -/** - * test MissingBehaviorClass method - * - * @access public - * @return void - */ - function testMissingBehaviorClass() { - $exception = new MissingBehaviorClassException(array('file' => 'my_custom.php', 'class' => 'MyCustomBehavior')); - $ErrorHandler = new ErrorHandler($exception); - - ob_start(); - $ErrorHandler->render(); - $result = ob_get_clean(); - - $this->assertPattern('/The behavior class MyCustomBehavior<\/em> can not be found or does not exist./', $result); - $this->assertPattern('/(\/|\\\)my_custom.php/', $result); - } - -/** - * testMissingComponentFile method - * - * @access public - * @return void - */ - function testMissingComponentFile() { - $exception = new MissingComponentFileException(array('file' => 'sidebox.php', 'class' => 'SideboxComponent')); - $ErrorHandler = new ErrorHandler($exception); - - ob_start(); - $ErrorHandler->render(); - $result = ob_get_clean(); - - $this->assertPattern('/

    Missing Component File<\/h2>/', $result); - $this->assertPattern('/Create the class SideboxComponent<\/em> in file:/', $result); - $this->assertPattern('/(\/|\\\)sidebox.php/', $result); - } - -/** - * testMissingComponentClass method - * - * @access public - * @return void - */ - function testMissingComponentClass() { - $exception = new MissingComponentClassException(array('file' => 'sidebox.php', 'class' => 'SideboxComponent')); - $ErrorHandler = new ErrorHandler($exception); - - ob_start(); - $ErrorHandler->render(); - $result = ob_get_clean(); - - $this->assertPattern('/

    Missing Component Class<\/h2>/', $result); - $this->assertPattern('/Create the class SideboxComponent<\/em> in file:/', $result); - $this->assertPattern('/(\/|\\\)sidebox.php/', $result); - } - } From 78ac5bd20fb8273d91882f9cd86a64a8dd89b6c9 Mon Sep 17 00:00:00 2001 From: mark_story Date: Sun, 29 Aug 2010 23:28:54 -0400 Subject: [PATCH 057/166] Removing sprintf() placeholders that don't work. --- cake/tests/cases/libs/cake_request.test.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cake/tests/cases/libs/cake_request.test.php b/cake/tests/cases/libs/cake_request.test.php index e21450daf..8bded114f 100644 --- a/cake/tests/cases/libs/cake_request.test.php +++ b/cake/tests/cases/libs/cake_request.test.php @@ -678,10 +678,10 @@ class CakeRequestTestCase extends CakeTestCase { $request->addDetector('compare', array('env' => 'TEST_VAR', 'value' => 'something')); $_SERVER['TEST_VAR'] = 'something'; - $this->assertTrue($request->is('compare'), 'Value match failed %s.'); + $this->assertTrue($request->is('compare'), 'Value match failed.'); $_SERVER['TEST_VAR'] = 'wrong'; - $this->assertFalse($request->is('compare'), 'Value mis-match failed %s.'); + $this->assertFalse($request->is('compare'), 'Value mis-match failed.'); $request->addDetector('banana', array('env' => 'TEST_VAR', 'pattern' => '/^ban.*$/')); $_SERVER['TEST_VAR'] = 'banana'; From 612c52bb8b98506fc80e8c31ba0153e21a126f1f Mon Sep 17 00:00:00 2001 From: mark_story Date: Sun, 29 Aug 2010 23:31:20 -0400 Subject: [PATCH 058/166] Adding a beforeRender() that automatically escapes all the content sent to errors handled by CakeErrorController. --- cake/libs/controller/cake_error_controller.php | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/cake/libs/controller/cake_error_controller.php b/cake/libs/controller/cake_error_controller.php index aafa76b6d..eb60e02b6 100644 --- a/cake/libs/controller/cake_error_controller.php +++ b/cake/libs/controller/cake_error_controller.php @@ -31,4 +31,15 @@ class CakeErrorController extends AppController { $this->Components->trigger('initialize', array(&$this)); $this->_set(array('cacheAction' => false, 'viewPath' => 'errors')); } + +/** + * Escapes the viewVars. + * + * @return void + */ + function beforeRender() { + foreach ($this->viewVars as $key => $value) { + $this->viewVars[$key] = h($value); + } + } } \ No newline at end of file From 534f6006f83f5593863784364909249d94f6dd2b Mon Sep 17 00:00:00 2001 From: mark_story Date: Sun, 29 Aug 2010 23:38:46 -0400 Subject: [PATCH 059/166] Adding omitted parent call. --- cake/libs/controller/cake_error_controller.php | 1 + 1 file changed, 1 insertion(+) diff --git a/cake/libs/controller/cake_error_controller.php b/cake/libs/controller/cake_error_controller.php index eb60e02b6..a5293d276 100644 --- a/cake/libs/controller/cake_error_controller.php +++ b/cake/libs/controller/cake_error_controller.php @@ -38,6 +38,7 @@ class CakeErrorController extends AppController { * @return void */ function beforeRender() { + parent::beforeRender(); foreach ($this->viewVars as $key => $value) { $this->viewVars[$key] = h($value); } From 1f30c06695911ea10543140abe4667155d573aae Mon Sep 17 00:00:00 2001 From: mark_story Date: Sun, 29 Aug 2010 23:39:28 -0400 Subject: [PATCH 060/166] Fixing method coercion in error404 so it only coerces CakeExceptions. Test Added. --- cake/libs/error_handler.php | 2 +- cake/tests/cases/libs/error_handler.test.php | 24 ++++++++++++++++++++ 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/cake/libs/error_handler.php b/cake/libs/error_handler.php index 7b3235a51..75b9efa10 100644 --- a/cake/libs/error_handler.php +++ b/cake/libs/error_handler.php @@ -179,7 +179,7 @@ class ErrorHandler { */ public function error404($error) { $message = $error->getMessage(); - if (Configure::read('debug') == 0) { + if (Configure::read('debug') == 0 && $error instanceof CakeException) { $message = __('Not Found'); } $url = Router::normalize($this->controller->request->here); diff --git a/cake/tests/cases/libs/error_handler.test.php b/cake/tests/cases/libs/error_handler.test.php index d36af6a9b..c38795999 100644 --- a/cake/tests/cases/libs/error_handler.test.php +++ b/cake/tests/cases/libs/error_handler.test.php @@ -376,6 +376,30 @@ class ErrorHandlerTest extends CakeTestCase { App::build(); } +/** + * test that error404 only modifies the messages on CakeExceptions. + * + * @return void + */ + function testError404OnlyChangingCakeException() { + Configure::write('debug', 0); + + $exception = new Error404Exception('Custom message'); + $ErrorHandler = new ErrorHandler($exception); + + ob_start(); + $ErrorHandler->render(); + $result = ob_get_clean(); + $this->assertContains('Custom message', $result); + + $exception = new MissingActionException(array('controller' => 'PostsController', 'action' => 'index')); + $ErrorHandler = new ErrorHandler($exception); + + ob_start(); + $ErrorHandler->render(); + $result = ob_get_clean(); + $this->assertContains('Not Found', $result); + } /** * test that error404 doesn't expose XSS * From a8d4015f47d31cff254bf6e9fce961cdd4c4598c Mon Sep 17 00:00:00 2001 From: mark_story Date: Mon, 30 Aug 2010 22:59:10 -0400 Subject: [PATCH 061/166] Updating bootstrap process in CLI to match the one in web. Updating all_libs to use new file. Updating error_handler test to run in cli. Updating Controller so it imports required classes. --- cake/console/cake.php | 1 + cake/libs/controller/controller.php | 1 + cake/tests/cases/libs/all_libs.test.php | 2 +- cake/tests/cases/libs/error_handler.test.php | 2 +- 4 files changed, 4 insertions(+), 2 deletions(-) diff --git a/cake/console/cake.php b/cake/console/cake.php index 4e4673cfc..0b94cb888 100644 --- a/cake/console/cake.php +++ b/cake/console/cake.php @@ -260,6 +260,7 @@ class ShellDispatcher { $includes = array( CORE_PATH . 'cake' . DS . 'config' . DS . 'paths.php', + CORE_PATH . 'cake' . DS . 'libs' . DS . 'exceptions.php', CORE_PATH . 'cake' . DS . 'libs' . DS . 'object.php', CORE_PATH . 'cake' . DS . 'libs' . DS . 'inflector.php', CORE_PATH . 'cake' . DS . 'libs' . DS . 'configure.php', diff --git a/cake/libs/controller/controller.php b/cake/libs/controller/controller.php index db1636ec0..97cfa8a4d 100644 --- a/cake/libs/controller/controller.php +++ b/cake/libs/controller/controller.php @@ -22,6 +22,7 @@ * Include files */ App::import('Controller', 'Component', false); +App::import('Core', 'CakeResponse', false); App::import('View', 'View', false); /** diff --git a/cake/tests/cases/libs/all_libs.test.php b/cake/tests/cases/libs/all_libs.test.php index 905c23c1e..32a196953 100644 --- a/cake/tests/cases/libs/all_libs.test.php +++ b/cake/tests/cases/libs/all_libs.test.php @@ -39,7 +39,7 @@ class AllLibsTest extends PHPUnit_Framework_TestSuite { $suite->addTestFile(CORE_TEST_CASES . DS . 'basics.test.php'); $suite->addTestFile(CORE_TEST_CASES . DS . 'libs' . DS . 'cake_session.test.php'); $suite->addTestFile(CORE_TEST_CASES . DS . 'libs' . DS . 'debugger.test.php'); - $suite->addTestFile(CORE_TEST_CASES . DS . 'libs' . DS . 'error.test.php'); + $suite->addTestFile(CORE_TEST_CASES . DS . 'libs' . DS . 'error_handler.test.php'); $suite->addTestFile(CORE_TEST_CASES . DS . 'libs' . DS . 'file.test.php'); $suite->addTestFile(CORE_TEST_CASES . DS . 'libs' . DS . 'folder.test.php'); $suite->addTestFile(CORE_TEST_CASES . DS . 'libs' . DS . 'log' . DS . 'file_log.test.php'); diff --git a/cake/tests/cases/libs/error_handler.test.php b/cake/tests/cases/libs/error_handler.test.php index c38795999..de2d82662 100644 --- a/cake/tests/cases/libs/error_handler.test.php +++ b/cake/tests/cases/libs/error_handler.test.php @@ -18,6 +18,7 @@ * @license http://www.opensource.org/licenses/opengroup.php The Open Group Test Suite License */ +App::import('Core', array('ErrorHandler', 'Controller', 'Component')); /** * Short description for class. @@ -89,7 +90,6 @@ if (!class_exists('AppController')) { } elseif (!defined('APP_CONTROLLER_EXISTS')){ define('APP_CONTROLLER_EXISTS', true); } -App::import('Core', array('ErrorHandler', 'Controller', 'Component')); /** * BlueberryComponent class From 08d6c19ab6aa65f68226d7dafd0a3ab27bd7ea26 Mon Sep 17 00:00:00 2001 From: mark_story Date: Tue, 31 Aug 2010 21:21:05 -0400 Subject: [PATCH 062/166] Adding test for themes in app/webroot dir. Closes #1061 --- .../cases/libs/view/helpers/html.test.php | 28 +++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/cake/tests/cases/libs/view/helpers/html.test.php b/cake/tests/cases/libs/view/helpers/html.test.php index 5b98a6d33..05bd540db 100644 --- a/cake/tests/cases/libs/view/helpers/html.test.php +++ b/cake/tests/cases/libs/view/helpers/html.test.php @@ -626,6 +626,34 @@ class HtmlHelperTest extends CakeTestCase { $this->assertNull($result); } +/** + * test a script file in the webroot/theme dir. + * + * @return void + */ + function testScriptInTheme() { + if ($this->skipIf(!is_writable(WWW_ROOT . 'theme'), 'Cannot write to webroot/theme')) { + return; + } + App::import('Core', 'File'); + + $testfile = WWW_ROOT . 'theme' . DS . 'test_theme' . DS . 'js' . DS . '__test_js.js'; + $file =& new File($testfile, true); + + App::build(array( + 'views' => array(TEST_CAKE_CORE_INCLUDE_PATH . 'tests' . DS . 'test_app' . DS . 'views'. DS) + )); + + $this->Html->webroot = '/'; + $this->Html->theme = 'test_theme'; + $result = $this->Html->script('__test_js.js'); + $expected = array( + 'script' => array('src' => '/theme/test_theme/js/__test_js.js', 'type' => 'text/javascript') + ); + $this->assertTags($result, $expected); + App::build(); + } + /** * test Script block generation * From 063fcf557d31b6e5af382b367f96257d5b89a973 Mon Sep 17 00:00:00 2001 From: Mark Story Date: Wed, 1 Sep 2010 20:29:55 -0400 Subject: [PATCH 063/166] Moving error handler inclusion to before Configure::bootstrap() so app error handlers can be created. Fixing issue where unknown exception types would not be handled spewing out errors. Unknown exception types are interpreted as 500 errors. --- cake/bootstrap.php | 3 ++- cake/libs/error_handler.php | 6 +++++- cake/tests/cases/libs/error_handler.test.php | 13 +++++++++++++ 3 files changed, 20 insertions(+), 2 deletions(-) diff --git a/cake/bootstrap.php b/cake/bootstrap.php index 5499ed029..d9149d8f7 100644 --- a/cake/bootstrap.php +++ b/cake/bootstrap.php @@ -33,7 +33,8 @@ require LIBS . 'inflector.php'; require LIBS . 'configure.php'; require LIBS . 'set.php'; require LIBS . 'cache.php'; -Configure::bootstrap(); require LIBS . 'error_handler.php'; set_exception_handler(array('ErrorHandler', 'handleException')); + +Configure::bootstrap(); require CAKE . 'dispatcher.php'; diff --git a/cake/libs/error_handler.php b/cake/libs/error_handler.php index 75b9efa10..a586c6812 100644 --- a/cake/libs/error_handler.php +++ b/cake/libs/error_handler.php @@ -62,7 +62,9 @@ class ErrorHandler { public $error = null; /** - * Class constructor. + * Creates the controller to perform rendering on the error response. + * If the error is a CakeException it will be converted to either a 404 or a 500 + * type error depending on the code used to construct the error. * * @param string $method Method producing the error * @param array $messages Error messages @@ -79,6 +81,8 @@ class ErrorHandler { if ($exception instanceof CakeException && !in_array($method, get_class_methods($this))) { $method = '_cakeError'; + } elseif (!method_exists($this, $method)) { + $method = 'error500'; } if ($method !== 'error' && Configure::read('debug') == 0) { diff --git a/cake/tests/cases/libs/error_handler.test.php b/cake/tests/cases/libs/error_handler.test.php index de2d82662..9030e6c21 100644 --- a/cake/tests/cases/libs/error_handler.test.php +++ b/cake/tests/cases/libs/error_handler.test.php @@ -330,6 +330,19 @@ class ErrorHandlerTest extends CakeTestCase { $this->assertEquals($exception, $ErrorHandler->error); } +/** + * test that unknown exception types are captured and converted to 500 + * + * @return void + */ + function testUnknownExceptionType() { + $exception = new MissingWidgetThingException('coding fail.'); + $ErrorHandler = new ErrorHandler($exception); + + $this->assertFalse(method_exists($ErrorHandler, 'missingWidgetThing'), 'no method should exist.'); + $this->assertEquals('error500', $ErrorHandler->method, 'incorrect method coercion.'); + } + /** * testError method * From 3e5e52d52e5775d8836342a4623b0dc1a6ca3fda Mon Sep 17 00:00:00 2001 From: Mark Story Date: Thu, 2 Sep 2010 00:29:04 -0400 Subject: [PATCH 064/166] Fixing doc block for Form::create(). Fixes #1058 --- cake/libs/view/helpers/form.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cake/libs/view/helpers/form.php b/cake/libs/view/helpers/form.php index 29dc58116..3a9c60815 100644 --- a/cake/libs/view/helpers/form.php +++ b/cake/libs/view/helpers/form.php @@ -172,7 +172,7 @@ class FormHelper extends AppHelper { * ### Options: * * - `type` Form method defaults to POST - * - `action` The Action the form submits to. Can be a string or array, + * - `action` The controller action the form submits to, (optional). * - `url` The url the form submits to. Can be a string or a url array, * - `default` Allows for the creation of Ajax forms. * - `onsubmit` Used in conjunction with 'default' to create ajax forms. From dbdd17f51ad26e27cae5c61e6938284f5f1a6267 Mon Sep 17 00:00:00 2001 From: Mark Story Date: Thu, 2 Sep 2010 11:16:10 -0400 Subject: [PATCH 065/166] Adding test cases from 'euromark' and updating how email addresses are parsed so they are slightly more conformant to RFC 5322. Fixes #1066 --- cake/libs/controller/components/email.php | 13 ++++----- .../libs/controller/components/email.test.php | 28 +++++++++++++++++++ 2 files changed, 33 insertions(+), 8 deletions(-) diff --git a/cake/libs/controller/components/email.php b/cake/libs/controller/components/email.php index aae446593..53d642b0f 100755 --- a/cake/libs/controller/components/email.php +++ b/cake/libs/controller/components/email.php @@ -743,19 +743,16 @@ class EmailComponent extends Object{ * @access private */ function _formatAddress($string, $smtp = false) { - if (strpos($string, '<') !== false) { - $value = explode('<', $string); - if ($smtp) { - $string = '<' . $value[1]; - } else { - $string = $this->_encode($value[0]) . ' <' . $value[1]; - } + $hasAlias = preg_match('/(.+)\s<(.+)>/', $string, $matches); + if ($hasAlias) { + return $this->_strip($matches[1] . ' <' . $matches[2] . '>'); } return $this->_strip($string); } /** - * Remove certain elements (such as bcc:, to:, %0a) from given value + * Remove certain elements (such as bcc:, to:, %0a) from given value. + * Helps prevent header injection / mainipulation on user content. * * @param string $value Value to strip * @param boolean $message Set to true to indicate main message content diff --git a/cake/tests/cases/libs/controller/components/email.test.php b/cake/tests/cases/libs/controller/components/email.test.php index 6d19c77f0..4684d88df 100755 --- a/cake/tests/cases/libs/controller/components/email.test.php +++ b/cake/tests/cases/libs/controller/components/email.test.php @@ -128,6 +128,15 @@ class EmailTestComponent extends EmailComponent { function strip($content, $message = false) { return parent::_strip($content, $message); } + +/** + * Wrapper for testing. + * + * @return void + */ + function formatAddress($string, $smtp = false) { + return parent::_formatAddress($string, $smtp); + } } /** @@ -1151,4 +1160,23 @@ HTMLBLOC; ); $this->assertEqual($expected, $result); } + +/** + * Test that _formatName doesn't jack up email addresses with alias parts. + * + * @return void + */ + function testFormatAddressAliases() { + $result = $this->Controller->EmailTest->formatAddress('email@example.com'); + $this->assertEqual($result, 'email@example.com'); + + $result = $this->Controller->EmailTest->formatAddress('alias '); + $this->assertEqual($result, 'alias '); + + $result = $this->Controller->EmailTest->formatAddress('email@example.com'); + $this->assertEqual($result, 'email@example.com'); + + $result = $this->Controller->EmailTest->formatAddress(''); + $this->assertEqual($result, ''); + } } From 2e8a60f93244c08db65de0cc3ef3b47aaaefa417 Mon Sep 17 00:00:00 2001 From: Mark Story Date: Thu, 2 Sep 2010 16:38:19 -0400 Subject: [PATCH 066/166] Removing some mentions of cakeError as its been removed. Also adding information about exceptions that can be raised. --- cake/libs/controller/controller.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/cake/libs/controller/controller.php b/cake/libs/controller/controller.php index 97cfa8a4d..88be76e90 100644 --- a/cake/libs/controller/controller.php +++ b/cake/libs/controller/controller.php @@ -491,9 +491,10 @@ class Controller extends Object { * see Controller::loadModel(); for more info. * Loads Components and prepares them for initialization. * - * @return mixed true if models found and instance created, or cakeError if models not found. + * @return mixed true if models found and instance created. * @see Controller::loadModel() * @link http://book.cakephp.org/view/977/Controller-Methods#constructClasses-986 + * @throws MissingModelException */ public function constructClasses() { $this->__mergeVars(); From 3940b059a370f854daa8d8fd93b310a6638be295 Mon Sep 17 00:00:00 2001 From: Mark Story Date: Thu, 2 Sep 2010 16:39:09 -0400 Subject: [PATCH 067/166] Adding a big docblock to explain how to setup application exception handling. --- cake/libs/error_handler.php | 28 +++++++++++++++++++++++++--- 1 file changed, 25 insertions(+), 3 deletions(-) diff --git a/cake/libs/error_handler.php b/cake/libs/error_handler.php index a586c6812..966d2108c 100644 --- a/cake/libs/error_handler.php +++ b/cake/libs/error_handler.php @@ -23,9 +23,31 @@ /** * Error Handler. * - * Captures and handles all cakeError() calls. - * Displays helpful framework errors when debug > 1. - * When debug < 1 cakeError() will render 404 or 500 errors. + * Captures and handles all unhandled exceptions. Displays helpful framework errors when debug > 1. + * When debug < 1 cakeError() will render 404 or 500 errors. If an uncaught exception is thrown + * and it is a type that ErrorHandler does not know about it will be treated as a 500 error. + * + * ### Implementing application specific exception handling + * + * You can implement application specific exception handling in one of a few ways: + * + * - Create a AppController::appError(); + * - Create an AppError class. + * + * #### Using AppController::appError(); + * + * This controller method is called instead of the default exception handling. It receives the + * thrown exception as its only argument. You should implement your error handling in that method. + * + * #### Using an AppError class + * + * This approach gives more flexibility and power in how you handle exceptions. You can create + * `app/libs/app_error.php` and create a class called `AppError`. The core ErrorHandler class + * will attempt to construct this class and let it handle the exception. This provides a more + * flexible way to handle exceptions in your application. + * + * Finally, in your `app/config/bootstrap.php` you can configure use `set_exception_handler()` + * to take total control over application exception handling. * * @package cake * @subpackage cake.cake.libs From ffa8b959e483cb2fdd0feb069f65de092d357c21 Mon Sep 17 00:00:00 2001 From: Mark Story Date: Thu, 2 Sep 2010 16:47:06 -0400 Subject: [PATCH 068/166] Changing classname and importing base class. --- cake/console/error.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/cake/console/error.php b/cake/console/error.php index 21860ef0d..1df183b12 100644 --- a/cake/console/error.php +++ b/cake/console/error.php @@ -18,13 +18,14 @@ * @license MIT License (http://www.opensource.org/licenses/mit-license.php) */ +App::import('Core', 'ErrorHandler'); /** * Error Handler for Cake console. * * @package cake * @subpackage cake.cake.console */ -class ErrorHandler extends Object { +class ConsoleErrorHandler extends ErrorHandler { /** * Standard output stream. From d6b43c0e2935acd67e0ba125a4c7c2982892d41c Mon Sep 17 00:00:00 2001 From: Mark Story Date: Thu, 2 Sep 2010 16:55:42 -0400 Subject: [PATCH 069/166] Removing TIME_START global, use $_SERVER['REQUEST_TIME'] instead. --- cake/bootstrap.php | 1 - 1 file changed, 1 deletion(-) diff --git a/cake/bootstrap.php b/cake/bootstrap.php index d9149d8f7..f6288ee01 100644 --- a/cake/bootstrap.php +++ b/cake/bootstrap.php @@ -25,7 +25,6 @@ if (!defined('E_DEPRECATED')) { error_reporting(E_ALL & ~E_DEPRECATED); require CORE_PATH . 'cake' . DS . 'basics.php'; -$TIME_START = microtime(true); require CORE_PATH . 'cake' . DS . 'config' . DS . 'paths.php'; require LIBS . 'exceptions.php'; require LIBS . 'object.php'; From 81e6ca22490a2b4b560f2e1a0b160b83d5fee20d Mon Sep 17 00:00:00 2001 From: Mark Story Date: Thu, 2 Sep 2010 17:00:52 -0400 Subject: [PATCH 070/166] Moving dispatcher include so that cake/bootstrap.php is only bootstrapping the framework. This should allow reusing the bootstrap file for console and web once console error handler is fixed. --- app/webroot/index.php | 1 + cake/bootstrap.php | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/app/webroot/index.php b/app/webroot/index.php index 396775b73..f6984a448 100644 --- a/app/webroot/index.php +++ b/app/webroot/index.php @@ -79,6 +79,7 @@ if (isset($_GET['url']) && $_GET['url'] === 'favicon.ico') { return; } else { + require CAKE . 'dispatcher.php'; $Dispatcher = new Dispatcher(); $Dispatcher->dispatch(); } diff --git a/cake/bootstrap.php b/cake/bootstrap.php index f6288ee01..33b29eeea 100644 --- a/cake/bootstrap.php +++ b/cake/bootstrap.php @@ -36,4 +36,4 @@ require LIBS . 'error_handler.php'; set_exception_handler(array('ErrorHandler', 'handleException')); Configure::bootstrap(); -require CAKE . 'dispatcher.php'; + From 034aaa7462ce0225620621b726ddf1c01d0e1d5a Mon Sep 17 00:00:00 2001 From: Mark Story Date: Thu, 2 Sep 2010 17:16:57 -0400 Subject: [PATCH 071/166] Creating optional boot variable that informs Configure if it should bootstrap the app. Changing how ShellDispatcher checks for app existence it sets the $boot var now and reuses the framework bootstrap file instead of a second custom one. --- cake/bootstrap.php | 2 +- cake/console/cake.php | 28 +++------------------------- 2 files changed, 4 insertions(+), 26 deletions(-) diff --git a/cake/bootstrap.php b/cake/bootstrap.php index 33b29eeea..413ef9931 100644 --- a/cake/bootstrap.php +++ b/cake/bootstrap.php @@ -35,5 +35,5 @@ require LIBS . 'cache.php'; require LIBS . 'error_handler.php'; set_exception_handler(array('ErrorHandler', 'handleException')); -Configure::bootstrap(); +Configure::bootstrap(isset($boot) ? $boot : true); diff --git a/cake/console/cake.php b/cake/console/cake.php index 0b94cb888..149247d04 100644 --- a/cake/console/cake.php +++ b/cake/console/cake.php @@ -20,9 +20,7 @@ * @since CakePHP(tm) v 1.2.0.5012 * @license MIT License (http://www.opensource.org/licenses/mit-license.php) */ -if (!defined('E_DEPRECATED')) { - define('E_DEPRECATED', 8192); -} + /** * Shell dispatcher * @@ -172,7 +170,6 @@ class ShellDispatcher { } } } - require_once(CORE_PATH . 'cake' . DS . 'basics.php'); } /** @@ -258,27 +255,8 @@ class ShellDispatcher { define('TMP', CORE_PATH . 'cake' . DS . 'console' . DS . 'templates' . DS . 'skel' . DS . 'tmp' . DS); } - $includes = array( - CORE_PATH . 'cake' . DS . 'config' . DS . 'paths.php', - CORE_PATH . 'cake' . DS . 'libs' . DS . 'exceptions.php', - CORE_PATH . 'cake' . DS . 'libs' . DS . 'object.php', - CORE_PATH . 'cake' . DS . 'libs' . DS . 'inflector.php', - CORE_PATH . 'cake' . DS . 'libs' . DS . 'configure.php', - CORE_PATH . 'cake' . DS . 'libs' . DS . 'file.php', - CORE_PATH . 'cake' . DS . 'libs' . DS . 'cache.php', - CORE_PATH . 'cake' . DS . 'libs' . DS . 'string.php', - CORE_PATH . 'cake' . DS . 'libs' . DS . 'class_registry.php', - CORE_PATH . 'cake' . DS . 'console' . DS . 'error.php' - ); - - foreach ($includes as $inc) { - if (!require($inc)) { - $this->stderr("Failed to load Cake core file {$inc}"); - return false; - } - } - - Configure::bootstrap(file_exists(CONFIGS . 'bootstrap.php')); + $boot = file_exists(ROOT . DS . APP_DIR . DS . 'config' . DS . 'bootstrap.php'); + require CORE_PATH . 'cake' . DS . 'bootstrap.php'; if (!file_exists(APP_PATH . 'config' . DS . 'core.php')) { include_once CORE_PATH . 'cake' . DS . 'console' . DS . 'templates' . DS . 'skel' . DS . 'config' . DS . 'core.php'; From 60e44660c3f4d0fdd8c75d0e2394d6eeb837369e Mon Sep 17 00:00:00 2001 From: Mark Story Date: Thu, 2 Sep 2010 17:49:00 -0400 Subject: [PATCH 072/166] Moving ErrorHandler to ConsoleErrorHandler so it doesn't have classname conflicts. Making the console use a subclass of ErrorHandler. --- cake/console/console_error_handler.php | 99 ++++++++++ cake/console/error.php | 249 ------------------------- 2 files changed, 99 insertions(+), 249 deletions(-) create mode 100644 cake/console/console_error_handler.php delete mode 100644 cake/console/error.php diff --git a/cake/console/console_error_handler.php b/cake/console/console_error_handler.php new file mode 100644 index 000000000..ed7f49710 --- /dev/null +++ b/cake/console/console_error_handler.php @@ -0,0 +1,99 @@ +stderr = fopen('php://stderr', 'w'); + parent::__construct($error); + } + +/** + * Handle a exception in the console environment. + * + * @return void + */ + public static function handleException($exception) { + $error = new ConsoleErrorHandler($exception); + $error->render(); + } + +/** + * Do nothing, no controllers are needed in the console. + * + * @return void + */ + protected function _getController($exception) { + return null; + } + +/** + * Overwrite how _cakeError behaves for console. There is no reason + * to prepare urls as they are not relevant for this. + * + * @param $error Exception Exception being handled. + * @return void + */ + protected function _cakeError($error) { + $this->_outputMessage(''); + } + +/** + * Outputs the exception to STDERR. + * + * @param string $template The name of the template to render. + * @return void + */ + public function _outputMessage($template) { + $this->stderr($this->error->getMessage()); + } + +/** + * Outputs to the stderr filehandle. + * + * @param string $string Error text to output. + */ + public function stderr($string) { + fwrite($this->stderr, "Error: ". $string . "\n"); + } +} diff --git a/cake/console/error.php b/cake/console/error.php deleted file mode 100644 index 1df183b12..000000000 --- a/cake/console/error.php +++ /dev/null @@ -1,249 +0,0 @@ -stdout = fopen('php://stdout', 'w'); - $this->stderr = fopen('php://stderr', 'w'); - call_user_func_array(array(&$this, $method), $messages); - } - -/** - * Displays an error page (e.g. 404 Not found). - * - * @param array $params Parameters (code, name, and message) - */ - public function error($params) { - extract($params, EXTR_OVERWRITE); - $this->stderr($code . $name . $message."\n"); - $this->_stop(); - } - -/** - * Convenience method to display a 404 page. - * - * @param array $params Parameters (url, message) - */ - public function error404($params) { - extract($params, EXTR_OVERWRITE); - $this->error(array( - 'code' => '404', - 'name' => 'Not found', - 'message' => sprintf(__('The requested address %s was not found on this server.'), $url, $message) - )); - $this->_stop(); - } - -/** - * Renders the Missing Controller web page. - * - * @param array $params Parameters (className) - */ - public function missingController($params) { - extract($params, EXTR_OVERWRITE); - $controllerName = str_replace('Controller', '', $className); - $this->stderr(sprintf(__("Missing Controller '%s'"), $controllerName)); - $this->_stop(); - } - -/** - * Renders the Missing Action web page. - * - * @param array $params Parameters (action, className) - */ - public function missingAction($params) { - extract($params, EXTR_OVERWRITE); - $this->stderr(sprintf(__("Missing Method '%s' in '%s'"), $action, $className)); - $this->_stop(); - } - -/** - * Renders the Private Action web page. - * - * @param array $params Parameters (action, className) - */ - public function privateAction($params) { - extract($params, EXTR_OVERWRITE); - $this->stderr(sprintf(__("Trying to access private method '%s' in '%s'"), $action, $className)); - $this->_stop(); - } - -/** - * Renders the Missing Table web page. - * - * @param array $params Parameters (table, className) - */ - public function missingTable($params) { - extract($params, EXTR_OVERWRITE); - $this->stderr(sprintf(__("Missing database table '%s' for model '%s'"), $table, $className)); - $this->_stop(); - } - -/** - * Renders the Missing Database web page. - * - * @param array $params Parameters - */ - public function missingDatabase($params = array()) { - $this->stderr(__('Missing Database')); - $this->_stop(); - } - -/** - * Renders the Missing View web page. - * - * @param array $params Parameters (file, action, className) - */ - public function missingView($params) { - extract($params, EXTR_OVERWRITE); - $this->stderr(sprintf(__("Missing View '%s' for '%s' in '%s'"), $file, $action, $className)); - $this->_stop(); - } - -/** - * Renders the Missing Layout web page. - * - * @param array $params Parameters (file) - */ - public function missingLayout($params) { - extract($params, EXTR_OVERWRITE); - $this->stderr(sprintf(__("Missing Layout '%s'"), $file)); - $this->_stop(); - } - -/** - * Renders the Database Connection web page. - * - * @param array $params Parameters - */ - public function missingConnection($params) { - extract($params, EXTR_OVERWRITE); - $this->stderr(__("Missing Database Connection. Try 'cake bake'")); - $this->_stop(); - } - -/** - * Renders the Missing Helper file web page. - * - * @param array $params Parameters (file, helper) - */ - public function missingHelperFile($params) { - extract($params, EXTR_OVERWRITE); - $this->stderr(sprintf(__("Missing Helper file '%s' for '%s'"), $file, Inflector::camelize($helper))); - $this->_stop(); - } - -/** - * Renders the Missing Helper class web page. - * - * @param array $params Parameters (file, helper) - */ - public function missingHelperClass($params) { - extract($params, EXTR_OVERWRITE); - $this->stderr(sprintf(__("Missing Helper class '%s' in '%s'"), Inflector::camelize($helper), $file)); - $this->_stop(); - } - -/** - * Renders the Missing Component file web page. - * - * @param array $params Parameters (file, component) - */ - public function missingComponentFile($params) { - extract($params, EXTR_OVERWRITE); - $this->stderr(sprintf(__("Missing Component file '%s' for '%s'"), $file, Inflector::camelize($component))); - $this->_stop(); - } - -/** - * Renders the Missing Component class web page. - * - * @param array $params Parameters (file, component) - */ - public function missingComponentClass($params) { - extract($params, EXTR_OVERWRITE); - $this->stderr(sprintf(__("Missing Component class '%s' in '%s'"), Inflector::camelize($component), $file)); - $this->_stop(); - } - -/** - * Renders the Missing Model class web page. - * - * @param array $params Parameters (className) - */ - public function missingModel($params) { - extract($params, EXTR_OVERWRITE); - $this->stderr(sprintf(__("Missing model '%s'"), $className)); - $this->_stop(); - } - -/** - * Outputs to the stdout filehandle. - * - * @param string $string String to output. - * @param boolean $newline If true, the outputs gets an added newline. - */ - public function stdout($string, $newline = true) { - if ($newline) { - fwrite($this->stdout, $string . "\n"); - } else { - fwrite($this->stdout, $string); - } - } - -/** - * Outputs to the stderr filehandle. - * - * @param string $string Error text to output. - */ - public function stderr($string) { - fwrite($this->stderr, "Error: ". $string . "\n"); - } -} From a44b35311d1817d8c99b2133029d5c399eaf129b Mon Sep 17 00:00:00 2001 From: Mark Story Date: Thu, 2 Sep 2010 17:49:43 -0400 Subject: [PATCH 073/166] Integrating the ConsoleErrorHandler into the console environment. --- cake/console/cake.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/cake/console/cake.php b/cake/console/cake.php index 149247d04..1ec1e9088 100644 --- a/cake/console/cake.php +++ b/cake/console/cake.php @@ -257,6 +257,8 @@ class ShellDispatcher { $boot = file_exists(ROOT . DS . APP_DIR . DS . 'config' . DS . 'bootstrap.php'); require CORE_PATH . 'cake' . DS . 'bootstrap.php'; + require CORE_PATH . 'cake' . DS . 'console' . DS . 'console_error_handler.php'; + set_exception_handler(array('ConsoleErrorHandler', 'handleException')); if (!file_exists(APP_PATH . 'config' . DS . 'core.php')) { include_once CORE_PATH . 'cake' . DS . 'console' . DS . 'templates' . DS . 'skel' . DS . 'config' . DS . 'core.php'; From a1e01e414b665e6b192bbb0e916ec3ebdb2fab62 Mon Sep 17 00:00:00 2001 From: Mark Story Date: Thu, 2 Sep 2010 18:02:58 -0400 Subject: [PATCH 074/166] Adding a tests for CakeExceptions and non CakeExceptions --- cake/console/console_error_handler.php | 23 +++++- .../console/console_error_handler.test.php | 73 +++++++++++++++++++ 2 files changed, 94 insertions(+), 2 deletions(-) create mode 100644 cake/tests/cases/console/console_error_handler.test.php diff --git a/cake/console/console_error_handler.php b/cake/console/console_error_handler.php index ed7f49710..0883b8b7f 100644 --- a/cake/console/console_error_handler.php +++ b/cake/console/console_error_handler.php @@ -75,16 +75,35 @@ class ConsoleErrorHandler extends ErrorHandler { * @return void */ protected function _cakeError($error) { - $this->_outputMessage(''); + $this->_outputMessage(); } +/** + * Override error404 method + * + * @param Exception $error Exception + * @return void + */ + public function error404($error) { + $this->_outputMessage(); + } + +/** + * Override error500 method + * + * @param Exception $error Exception + * @return void + */ + public function error500($error) { + $this->_outputMessage(); + } /** * Outputs the exception to STDERR. * * @param string $template The name of the template to render. * @return void */ - public function _outputMessage($template) { + public function _outputMessage($template = null) { $this->stderr($this->error->getMessage()); } diff --git a/cake/tests/cases/console/console_error_handler.test.php b/cake/tests/cases/console/console_error_handler.test.php new file mode 100644 index 000000000..42b1a88ce --- /dev/null +++ b/cake/tests/cases/console/console_error_handler.test.php @@ -0,0 +1,73 @@ +output[] = $line; + } +} + + +/** + * ConsoleErrorHandler Test case. + * + * @package cake.tests.cases.console + */ +class ConsoleErrorHandlerTest extends CakeTestCase { + +/** + * test that the console error handler can deal with CakeExceptions. + * + * @return void + */ + function testCakeErrors() { + $exception = new MissingActionException('Missing action'); + $error = new TestConsoleErrorHandler($exception); + $error->render(); + + $result = $error->output; + $this->assertEquals(1, count($result)); + $this->assertEquals('Missing action', $result[0]); + } + +/** + * test a non CakeException exception. + * + * @return void + */ + function testNonCakeExceptions() { + $exception = new InvalidArgumentException('Too many parameters.'); + $error = new TestConsoleErrorHandler($exception); + $error->render(); + + $result = $error->output; + $this->assertEquals(1, count($result)); + $this->assertEquals('Too many parameters.', $result[0]); + } +} \ No newline at end of file From 29ade860b117f55d3e72f183ea6b597dd79e03ff Mon Sep 17 00:00:00 2001 From: Mark Story Date: Thu, 2 Sep 2010 18:04:50 -0400 Subject: [PATCH 075/166] Adding cases for Error404 and Error500 exceptions. --- .../console/console_error_handler.test.php | 30 +++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/cake/tests/cases/console/console_error_handler.test.php b/cake/tests/cases/console/console_error_handler.test.php index 42b1a88ce..eba6d24f6 100644 --- a/cake/tests/cases/console/console_error_handler.test.php +++ b/cake/tests/cases/console/console_error_handler.test.php @@ -70,4 +70,34 @@ class ConsoleErrorHandlerTest extends CakeTestCase { $this->assertEquals(1, count($result)); $this->assertEquals('Too many parameters.', $result[0]); } + +/** + * test a Error404 exception. + * + * @return void + */ + function testError404Exception() { + $exception = new Error404Exception('dont use me in cli.'); + $error = new TestConsoleErrorHandler($exception); + $error->render(); + + $result = $error->output; + $this->assertEquals(1, count($result)); + $this->assertEquals('dont use me in cli.', $result[0]); + } + +/** + * test a Error500 exception. + * + * @return void + */ + function testError500Exception() { + $exception = new Error500Exception('dont use me in cli.'); + $error = new TestConsoleErrorHandler($exception); + $error->render(); + + $result = $error->output; + $this->assertEquals(1, count($result)); + $this->assertEquals('dont use me in cli.', $result[0]); + } } \ No newline at end of file From 2c7ef67e977528a17b6fe593bd0ab22a1d030ad2 Mon Sep 17 00:00:00 2001 From: Mark Story Date: Fri, 3 Sep 2010 10:22:58 -0400 Subject: [PATCH 076/166] Fixing stupid output buffering error. --- cake/tests/lib/reporter/cake_html_reporter.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/cake/tests/lib/reporter/cake_html_reporter.php b/cake/tests/lib/reporter/cake_html_reporter.php index fb4840fef..a61366060 100755 --- a/cake/tests/lib/reporter/cake_html_reporter.php +++ b/cake/tests/lib/reporter/cake_html_reporter.php @@ -216,7 +216,9 @@ class CakeHtmlReporter extends CakeBaseReporter { public function paintDocumentEnd() { $baseDir = $this->params['baseDir']; include CAKE_TESTS_LIB . 'templates/footer.php'; - ob_end_flush(); + if (ob_get_length()) { + ob_end_flush(); + } } /** From f2db19767d55eeed646a12d1cd0673caa96ce891 Mon Sep 17 00:00:00 2001 From: Mark Story Date: Fri, 3 Sep 2010 10:30:35 -0400 Subject: [PATCH 077/166] Adding in support for AppError. --- cake/libs/error_handler.php | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/cake/libs/error_handler.php b/cake/libs/error_handler.php index 966d2108c..5d147f476 100644 --- a/cake/libs/error_handler.php +++ b/cake/libs/error_handler.php @@ -4,7 +4,7 @@ * * Provides Error Capturing for Framework errors. * - * PHP versions 4 and 5 + * PHP 5 * * CakePHP(tm) : Rapid Development Framework (http://cakephp.org) * Copyright 2005-2010, Cake Software Foundation, Inc. (http://cakefoundation.org) @@ -99,6 +99,10 @@ class ErrorHandler { if (method_exists($this->controller, 'apperror')) { return $this->controller->appError($exception); } + if (file_exists(APP . 'app_error.php') && class_exists('AppError')) { + $AppError = new AppError($exception); + return $AppError->render(); + } $method = $template = Inflector::variable(str_replace('Exception', '', get_class($exception))); if ($exception instanceof CakeException && !in_array($method, get_class_methods($this))) { From 5c0fe1b16e1635d7a3bdf60b43c90aae20665060 Mon Sep 17 00:00:00 2001 From: Mark Story Date: Fri, 3 Sep 2010 12:33:59 -0400 Subject: [PATCH 078/166] Applying patch from 'majna'. Adding plugin to the list of template variables exposed in the controller task. Test added Fixes #1077 --- cake/console/libs/tasks/controller.php | 7 ++++--- cake/tests/cases/console/libs/tasks/controller.test.php | 2 ++ 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/cake/console/libs/tasks/controller.php b/cake/console/libs/tasks/controller.php index 36fd91600..b7f04bb18 100644 --- a/cake/console/libs/tasks/controller.php +++ b/cake/console/libs/tasks/controller.php @@ -275,8 +275,9 @@ class ControllerTask extends BakeTask { */ function bakeActions($controllerName, $admin = null, $wannaUseSession = true) { $currentModelName = $modelImport = $this->_modelName($controllerName); - if ($this->plugin) { - $modelImport = $this->plugin . '.' . $modelImport; + $plugin = $this->plugin; + if ($plugin) { + $modelImport = $plugin . '.' . $modelImport; } if (!App::import('Model', $modelImport)) { $this->err(__('You must have a model for this class to build basic methods. Please try again.', true)); @@ -290,7 +291,7 @@ class ControllerTask extends BakeTask { $singularHumanName = $this->_singularHumanName($controllerName); $pluralHumanName = $this->_pluralName($controllerName); - $this->Template->set(compact('admin', 'controllerPath', 'pluralName', 'singularName', 'singularHumanName', + $this->Template->set(compact('plugin', 'admin', 'controllerPath', 'pluralName', 'singularName', 'singularHumanName', 'pluralHumanName', 'modelObj', 'wannaUseSession', 'currentModelName')); $actions = $this->Template->generate('actions', 'controller_actions'); return $actions; diff --git a/cake/tests/cases/console/libs/tasks/controller.test.php b/cake/tests/cases/console/libs/tasks/controller.test.php index 0fbc888ff..618b0dfd3 100644 --- a/cake/tests/cases/console/libs/tasks/controller.test.php +++ b/cake/tests/cases/console/libs/tasks/controller.test.php @@ -299,6 +299,8 @@ class ControllerTaskTest extends CakeTestCase { $this->Task->expectAt(1, 'createFile', array( $path, new PatternExpectation('/ArticlesController extends ControllerTestAppController/'))); $this->Task->bake('Articles', '--actions--', array(), array(), array()); + + $this->assertEqual($this->Task->Template->templateVars['plugin'], 'ControllerTest'); } /** From 8c428ff8a89a33c4165026cd58e38b7e8b537c39 Mon Sep 17 00:00:00 2001 From: Mark Story Date: Fri, 3 Sep 2010 15:03:33 -0400 Subject: [PATCH 079/166] Moving where AppError is used, as infinite recursion is no fun. --- cake/libs/error_handler.php | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/cake/libs/error_handler.php b/cake/libs/error_handler.php index 5d147f476..3b59f55da 100644 --- a/cake/libs/error_handler.php +++ b/cake/libs/error_handler.php @@ -99,10 +99,6 @@ class ErrorHandler { if (method_exists($this->controller, 'apperror')) { return $this->controller->appError($exception); } - if (file_exists(APP . 'app_error.php') && class_exists('AppError')) { - $AppError = new AppError($exception); - return $AppError->render(); - } $method = $template = Inflector::variable(str_replace('Exception', '', get_class($exception))); if ($exception instanceof CakeException && !in_array($method, get_class_methods($this))) { @@ -155,13 +151,21 @@ class ErrorHandler { /** * Set as the default exception handler by the CakePHP bootstrap process. - * If you wish you use a custom default exception handler use set_exception_handler() - * in your app/config/bootstrap.php. + * + * This will either use an AppError class if your application has one, + * or use the default ErrorHandler. * * @return void * @see http://php.net/manual/en/function.set-exception-handler.php */ public static function handleException(Exception $exception) { + if (file_exists(APP . 'app_error.php') || class_exists('AppError')) { + if (!class_exists('AppError')) { + require(APP . 'app_error.php'); + } + $AppError = new AppError($exception); + return $AppError->render(); + } $error = new ErrorHandler($exception); $error->render(); } From af87e5d5bc45866a75ae416a472fc4900f07c642 Mon Sep 17 00:00:00 2001 From: Mark Story Date: Fri, 3 Sep 2010 15:35:11 -0400 Subject: [PATCH 080/166] Adding a skip when AppError is present, as its behaviour is unknown. --- cake/tests/cases/libs/error_handler.test.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/cake/tests/cases/libs/error_handler.test.php b/cake/tests/cases/libs/error_handler.test.php index 9030e6c21..61d77dda1 100644 --- a/cake/tests/cases/libs/error_handler.test.php +++ b/cake/tests/cases/libs/error_handler.test.php @@ -236,6 +236,9 @@ class ErrorHandlerTest extends CakeTestCase { * @return void */ function testHandleException() { + if ($this->skipIf(file_exists(APP . 'app_error.php'), 'App error exists cannot run.')) { + return; + } $error = new Error404Exception('Kaboom!'); ob_start(); ErrorHandler::handleException($error); From fa7549dc4cd8e99cfcc4f7ad4c0abb4b7fc7fe34 Mon Sep 17 00:00:00 2001 From: Mark Story Date: Sat, 4 Sep 2010 01:34:45 -0400 Subject: [PATCH 081/166] Fixing comments and removing cakeError(). Instead you should be throwing exceptions. --- cake/libs/error_handler.php | 4 ++-- cake/libs/object.php | 30 +----------------------------- 2 files changed, 3 insertions(+), 31 deletions(-) diff --git a/cake/libs/error_handler.php b/cake/libs/error_handler.php index 3b59f55da..8ae834d46 100644 --- a/cake/libs/error_handler.php +++ b/cake/libs/error_handler.php @@ -24,8 +24,8 @@ * Error Handler. * * Captures and handles all unhandled exceptions. Displays helpful framework errors when debug > 1. - * When debug < 1 cakeError() will render 404 or 500 errors. If an uncaught exception is thrown - * and it is a type that ErrorHandler does not know about it will be treated as a 500 error. + * When debug < 1 a CakeException will render 404 or 500 errors. If an uncaught exception is thrown + * and it is a type that ErrorHandler does not know about it will be treated as a 500 error. * * ### Implementing application specific exception handling * diff --git a/cake/libs/object.php b/cake/libs/object.php index b4da0bd68..987ba0154 100644 --- a/cake/libs/object.php +++ b/cake/libs/object.php @@ -22,7 +22,7 @@ */ /** - * Object class, allowing __construct and __destruct in PHP4. + * Object class provides a few generic methods used in several subclasses. * * Also includes methods for logging and the special method RequestAction, * to call other Controllers' Actions from anywhere. @@ -155,34 +155,6 @@ class Object { } } -/** - * Used to report user friendly errors. - * If there is a file app/error.php or app/app_error.php this file will be loaded - * error.php is the AppError class it should extend ErrorHandler class. - * - * @param string $method Method to be called in the error class (AppError or ErrorHandler classes) - * @param array $messages Message that is to be displayed by the error class - * @return error message - */ - public function cakeError($method, $messages = array()) { - if (!class_exists('ErrorHandler')) { - App::import('Core', 'Error'); - - if (file_exists(APP . 'error.php')) { - include_once (APP . 'error.php'); - } elseif (file_exists(APP . 'app_error.php')) { - include_once (APP . 'app_error.php'); - } - } - - if (class_exists('AppError')) { - $error = new AppError($method, $messages); - } else { - $error = new ErrorHandler($method, $messages); - } - return $error; - } - /** * Checks for a persistent class file, if found file is opened and true returned * If file is not found a file is created and false returned From 42d998ca3bae7ed4494fde1c50e9004ca446eb44 Mon Sep 17 00:00:00 2001 From: Mark Story Date: Sat, 4 Sep 2010 10:46:04 -0400 Subject: [PATCH 082/166] Fixing up the include for the console error handler, and adding a test for stderr handle. --- .../cases/console/console_error_handler.test.php | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/cake/tests/cases/console/console_error_handler.test.php b/cake/tests/cases/console/console_error_handler.test.php index eba6d24f6..6ad8c7659 100644 --- a/cake/tests/cases/console/console_error_handler.test.php +++ b/cake/tests/cases/console/console_error_handler.test.php @@ -17,7 +17,7 @@ * @since CakePHP(tm) v 2.0 * @license MIT License (http://www.opensource.org/licenses/mit-license.php) */ -App::import('Core', 'ConsoleErrorHandler'); +require CAKE . 'console' . DS . 'console_error_handler.php'; class TestConsoleErrorHandler extends ConsoleErrorHandler { public $output = array(); @@ -100,4 +100,16 @@ class ConsoleErrorHandlerTest extends CakeTestCase { $this->assertEquals(1, count($result)); $this->assertEquals('dont use me in cli.', $result[0]); } + +/** + * test that ConsoleErrorHandler has a stderr file handle. + * + * @return void + */ + function testStdErrFilehandle() { + $exception = new Error500Exception('dont use me in cli.'); + $error = new TestConsoleErrorHandler($exception); + + $this->assertTrue(is_resource($error->stderr), 'No handle.'); + } } \ No newline at end of file From 4980f42dc52833e26d1a7672726927ace1e320b1 Mon Sep 17 00:00:00 2001 From: Mark Story Date: Sat, 4 Sep 2010 15:35:01 -0400 Subject: [PATCH 083/166] Renaming file. --- cake/libs/view/errors/{error404.ctp => error400.ctp} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename cake/libs/view/errors/{error404.ctp => error400.ctp} (100%) diff --git a/cake/libs/view/errors/error404.ctp b/cake/libs/view/errors/error400.ctp similarity index 100% rename from cake/libs/view/errors/error404.ctp rename to cake/libs/view/errors/error400.ctp From dbd34c75c715d128423f09b287756c81c19fc718 Mon Sep 17 00:00:00 2001 From: Mark Story Date: Sat, 4 Sep 2010 15:36:57 -0400 Subject: [PATCH 084/166] Removing newlines and trailing space. --- cake/tests/cases/console/console_error_handler.test.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cake/tests/cases/console/console_error_handler.test.php b/cake/tests/cases/console/console_error_handler.test.php index 6ad8c7659..e17fec34e 100644 --- a/cake/tests/cases/console/console_error_handler.test.php +++ b/cake/tests/cases/console/console_error_handler.test.php @@ -109,7 +109,7 @@ class ConsoleErrorHandlerTest extends CakeTestCase { function testStdErrFilehandle() { $exception = new Error500Exception('dont use me in cli.'); $error = new TestConsoleErrorHandler($exception); - + $this->assertTrue(is_resource($error->stderr), 'No handle.'); } } \ No newline at end of file From 4d863618f560dd362c79e1c1b9652bdff8fae839 Mon Sep 17 00:00:00 2001 From: Mark Story Date: Sat, 4 Sep 2010 15:38:10 -0400 Subject: [PATCH 085/166] Refactoring exception handling so codes are much more flexible and easy to change. Made error404 and error500 more generic. Removed error() as it didn't really make that much sense. --- cake/libs/error_handler.php | 39 ++++++-------- cake/tests/cases/libs/error_handler.test.php | 56 +++++++++----------- 2 files changed, 43 insertions(+), 52 deletions(-) diff --git a/cake/libs/error_handler.php b/cake/libs/error_handler.php index 8ae834d46..611f08982 100644 --- a/cake/libs/error_handler.php +++ b/cake/libs/error_handler.php @@ -100,22 +100,27 @@ class ErrorHandler { return $this->controller->appError($exception); } $method = $template = Inflector::variable(str_replace('Exception', '', get_class($exception))); + $code = $exception->getCode(); - if ($exception instanceof CakeException && !in_array($method, get_class_methods($this))) { + $methodExists = method_exists($this, $method); + + if ($exception instanceof CakeException && !$methodExists) { $method = '_cakeError'; - } elseif (!method_exists($this, $method)) { + } elseif (!$methodExists) { $method = 'error500'; + if ($code >= 400) { + $method = 'error400'; + } } - if ($method !== 'error' && Configure::read('debug') == 0) { - $code = $exception->getCode(); + if (Configure::read('debug') == 0) { $parentClass = get_parent_class($this); if ($parentClass != 'ErrorHandler') { - $method = 'error404'; + $method = 'error400'; } $parentMethods = (array)get_class_methods($parentClass); if (in_array($method, $parentMethods)) { - $method = 'error404'; + $method = 'error400'; } if ($code == 500) { $method = 'error500'; @@ -179,15 +184,6 @@ class ErrorHandler { call_user_func_array(array($this, $this->method), array($this->error)); } -/** - * Displays an error page (e.g. 404 Not found). - * - * @param array $params Parameters for controller - */ - public function error(Exception $error) { - $this->error404($error); - } - /** * Generic handler for the internal framework errors CakePHP can generate. * @@ -207,23 +203,22 @@ class ErrorHandler { } /** - * Convenience method to display a 404 page. + * Convenience method to display a 400 series page. * * @param array $params Parameters for controller */ - public function error404($error) { + public function error400($error) { $message = $error->getMessage(); if (Configure::read('debug') == 0 && $error instanceof CakeException) { $message = __('Not Found'); } $url = Router::normalize($this->controller->request->here); - $this->controller->response->statusCode(404); + $this->controller->response->statusCode($error->getCode()); $this->controller->set(array( - 'code' => 404, 'name' => $message, 'url' => h($url), )); - $this->_outputMessage('error404'); + $this->_outputMessage('error400'); } /** @@ -231,9 +226,9 @@ class ErrorHandler { * * @param array $params Parameters for controller */ - public function error500($params) { + public function error500($error) { $url = Router::normalize($this->controller->request->here); - $this->controller->response->statusCode(500); + $this->controller->response->statusCode($error->getCode()); $this->controller->set(array( 'name' => __('An Internal Error Has Occurred'), 'message' => h($url), diff --git a/cake/tests/cases/libs/error_handler.test.php b/cake/tests/cases/libs/error_handler.test.php index 61d77dda1..170d246c1 100644 --- a/cake/tests/cases/libs/error_handler.test.php +++ b/cake/tests/cases/libs/error_handler.test.php @@ -248,7 +248,7 @@ class ErrorHandlerTest extends CakeTestCase { /** * test that methods declared in an ErrorHandler subclass are not converted - * into error404 when debug > 0 + * into error400 when debug > 0 * * @return void */ @@ -281,7 +281,7 @@ class ErrorHandlerTest extends CakeTestCase { $ErrorHandler->render(); $result = ob_get_clean(); - $this->assertEqual($result, 'widget thing is missing', 'Method declared in subclass converted to error404'); + $this->assertEqual($result, 'widget thing is missing', 'Method declared in subclass converted to error400'); } /** @@ -295,13 +295,13 @@ class ErrorHandlerTest extends CakeTestCase { $exception = new MissingControllerException('PostsController'); $ErrorHandler = new MyCustomErrorHandler($exception); - $this->assertEqual('error404', $ErrorHandler->method); + $this->assertEqual('error400', $ErrorHandler->method); ob_start(); $ErrorHandler->render(); $result = ob_get_clean(); - $this->assertPattern('/Not Found/', $result, 'Method declared in error handler not converted to error404. %s'); + $this->assertPattern('/Not Found/', $result, 'Method declared in error handler not converted to error400. %s'); } /** @@ -314,7 +314,7 @@ class ErrorHandlerTest extends CakeTestCase { $ErrorHandler = new ErrorHandler($exception); $this->assertType('CakeErrorController', $ErrorHandler->controller); - $this->assertEquals('error404', $ErrorHandler->method); + $this->assertEquals('error400', $ErrorHandler->method); $this->assertEquals($exception, $ErrorHandler->error); } @@ -329,46 +329,42 @@ class ErrorHandlerTest extends CakeTestCase { $ErrorHandler = new ErrorHandler($exception); $this->assertType('CakeErrorController', $ErrorHandler->controller); - $this->assertEquals('error404', $ErrorHandler->method); + $this->assertEquals('error400', $ErrorHandler->method); $this->assertEquals($exception, $ErrorHandler->error); } /** - * test that unknown exception types are captured and converted to 500 + * test that unknown exception types with valid status codes are treated correctly. * * @return void */ - function testUnknownExceptionType() { + function testUnknownExceptionTypeWithExceptionThatHasA400Code() { $exception = new MissingWidgetThingException('coding fail.'); $ErrorHandler = new ErrorHandler($exception); $this->assertFalse(method_exists($ErrorHandler, 'missingWidgetThing'), 'no method should exist.'); + $this->assertEquals('error400', $ErrorHandler->method, 'incorrect method coercion.'); + } + +/** + * test that unknown exception types with valid status codes are treated correctly. + * + * @return void + */ + function testUnknownExceptionTypeWithNoCodeIsA500() { + $exception = new OutOfBoundsException('foul ball.'); + $ErrorHandler = new ErrorHandler($exception); + $this->assertEquals('error500', $ErrorHandler->method, 'incorrect method coercion.'); } /** - * testError method + * testerror400 method * * @access public * @return void */ - function testError() { - $exception = new Exception('Page not found'); - $ErrorHandler = new ErrorHandler($exception); - - ob_start(); - $ErrorHandler->error($exception); - $result = ob_get_clean(); - $this->assertPattern("/

    Page not found<\/h2>/", $result); - } - -/** - * testError404 method - * - * @access public - * @return void - */ - function testError404() { + function testerror400() { App::build(array( 'views' => array(TEST_CAKE_CORE_INCLUDE_PATH . 'libs' . DS . 'view' . DS) ), true); @@ -393,11 +389,11 @@ class ErrorHandlerTest extends CakeTestCase { } /** - * test that error404 only modifies the messages on CakeExceptions. + * test that error400 only modifies the messages on CakeExceptions. * * @return void */ - function testError404OnlyChangingCakeException() { + function testerror400OnlyChangingCakeException() { Configure::write('debug', 0); $exception = new Error404Exception('Custom message'); @@ -417,11 +413,11 @@ class ErrorHandlerTest extends CakeTestCase { $this->assertContains('Not Found', $result); } /** - * test that error404 doesn't expose XSS + * test that error400 doesn't expose XSS * * @return void */ - function testError404NoInjection() { + function testerror400NoInjection() { Router::reload(); $request = new CakeRequest('pages/pink', false); From d198230e61b491587a4d29c69c915c9801cca5ae Mon Sep 17 00:00:00 2001 From: Mark Story Date: Sat, 4 Sep 2010 19:06:10 -0400 Subject: [PATCH 086/166] Fixing issue where errors that did not have a 500+ code would use the incorrect status code. --- cake/libs/error_handler.php | 7 ++++--- cake/tests/cases/libs/error_handler.test.php | 12 ++++++++++++ 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/cake/libs/error_handler.php b/cake/libs/error_handler.php index 611f08982..2b2277521 100644 --- a/cake/libs/error_handler.php +++ b/cake/libs/error_handler.php @@ -85,8 +85,8 @@ class ErrorHandler { /** * Creates the controller to perform rendering on the error response. - * If the error is a CakeException it will be converted to either a 404 or a 500 - * type error depending on the code used to construct the error. + * If the error is a CakeException it will be converted to either a 400 or a 500 + * code error depending on the code used to construct the error. * * @param string $method Method producing the error * @param array $messages Error messages @@ -228,7 +228,8 @@ class ErrorHandler { */ public function error500($error) { $url = Router::normalize($this->controller->request->here); - $this->controller->response->statusCode($error->getCode()); + $code = ($error->getCode() > 500) ? $error->getCode() : 500; + $this->controller->response->statusCode($code); $this->controller->set(array( 'name' => __('An Internal Error Has Occurred'), 'message' => h($url), diff --git a/cake/tests/cases/libs/error_handler.test.php b/cake/tests/cases/libs/error_handler.test.php index 170d246c1..7915c14bc 100644 --- a/cake/tests/cases/libs/error_handler.test.php +++ b/cake/tests/cases/libs/error_handler.test.php @@ -341,6 +341,12 @@ class ErrorHandlerTest extends CakeTestCase { function testUnknownExceptionTypeWithExceptionThatHasA400Code() { $exception = new MissingWidgetThingException('coding fail.'); $ErrorHandler = new ErrorHandler($exception); + $ErrorHandler->controller->response = $this->getMock('CakeResponse', array('statusCode')); + $ErrorHandler->controller->response->expects($this->once())->method('statusCode')->with(404); + + ob_start(); + $ErrorHandler->render(); + $results = ob_get_clean(); $this->assertFalse(method_exists($ErrorHandler, 'missingWidgetThing'), 'no method should exist.'); $this->assertEquals('error400', $ErrorHandler->method, 'incorrect method coercion.'); @@ -354,6 +360,12 @@ class ErrorHandlerTest extends CakeTestCase { function testUnknownExceptionTypeWithNoCodeIsA500() { $exception = new OutOfBoundsException('foul ball.'); $ErrorHandler = new ErrorHandler($exception); + $ErrorHandler->controller->response = $this->getMock('CakeResponse', array('statusCode')); + $ErrorHandler->controller->response->expects($this->once())->method('statusCode')->with(500); + + ob_start(); + $ErrorHandler->render(); + $results = ob_get_clean(); $this->assertEquals('error500', $ErrorHandler->method, 'incorrect method coercion.'); } From 954676c9f693148cf5056b704295f4986158b7e5 Mon Sep 17 00:00:00 2001 From: Mark Story Date: Sat, 4 Sep 2010 19:16:06 -0400 Subject: [PATCH 087/166] Adding doc blocks to the new exception classes. --- cake/libs/exceptions.php | 106 +++++++++++++++++++++++++++++++++++---- 1 file changed, 97 insertions(+), 9 deletions(-) diff --git a/cake/libs/exceptions.php b/cake/libs/exceptions.php index fcf324f6f..3f969c8a5 100644 --- a/cake/libs/exceptions.php +++ b/cake/libs/exceptions.php @@ -44,11 +44,31 @@ class Error500Exception extends CakeException { * @package cake.libs */ class CakeException extends RuntimeException { - +/** + * Array of attributes that are passed in from the constructor, and + * made available in the view when a development error is displayed. + * + * @var array + */ protected $_attributes = array(); +/** + * Template string that has attributes sprintf()'ed into it. + * + * @var string + */ protected $_messageTemplate = ''; +/** + * Constructor. + * + * Allows you to create exceptions that are treated as framework errors and disabled + * when debug = 0. + * + * @param mixed $message Either the string of the error message, or an array of attributes + * that are made available in the view, and sprintf()'d into CakeException::$_messageTemplate + * @param string $code The code of the error, is also the HTTP status code for the error. + */ public function __construct($message, $code = 500) { if (is_array($message)) { $this->_attributes = $message; @@ -56,14 +76,22 @@ class CakeException extends RuntimeException { } parent::__construct($message, $code); } - + +/** + * Get the passed in attributes + * + * @return array + */ public function getAttributes() { return $this->_attributes; } } -/* - * Exceptions used by Dispatcher +/** + * Missing Controller exception - used when a controller + * cannot be found. + * + * @package cake.libs */ class MissingControllerException extends CakeException { protected $_messageTemplate = 'Controller class %s could not be found.'; @@ -72,6 +100,13 @@ class MissingControllerException extends CakeException { parent::__construct($message, $code); } } + +/** + * Missing Action exception - used when a controller action + * cannot be found. + * + * @package cake.libs + */ class MissingActionException extends CakeException { protected $_messageTemplate = 'Action %s::%s() could not be found.'; @@ -79,6 +114,12 @@ class MissingActionException extends CakeException { parent::__construct($message, $code); } } +/** + * Private Action exception - used when a controller action + * is protected, or starts with a `_`. + * + * @package cake.libs + */ class PrivateActionException extends CakeException { protected $_messageTemplate = 'Private Action %s::%s() is not directly accessible.'; @@ -88,37 +129,69 @@ class PrivateActionException extends CakeException { } /** - * Exceptions used by the ComponentCollection. + * Used when a Component file cannot be found. + * + * @package cake.libs */ class MissingComponentFileException extends CakeException { protected $_messageTemplate = 'Component File "%s" is missing.'; } + +/** + * Used when a Component class cannot be found. + * + * @package cake.libs + */ class MissingComponentClassException extends CakeException { protected $_messageTemplate = 'Component class "%s" is missing.'; } /** - * Runtime Exceptions for behaviors + * Used when a Behavior file cannot be found. + * + * @package cake.libs */ class MissingBehaviorFileException extends CakeException { } + +/** + * Used when a Behavior class cannot be found. + * + * @package cake.libs + */ class MissingBehaviorClassException extends CakeException { } /** - * Runtime Exceptions for Views + * Used when a view file cannot be found. + * + * @package cake.libs */ class MissingViewException extends CakeException { protected $_messageTemplate = 'View file "%s" is missing.'; } + +/** + * Used when a layout file cannot be found. + * + * @package cake.libs + */ class MissingLayoutException extends CakeException { protected $_messageTemplate = 'Layout file "%s" is missing.'; } /** - * Exceptions used by the HelperCollection. + * Used when a helper file cannot be found. + * + * @package cake.libs */ class MissingHelperFileException extends CakeException { protected $_messageTemplate = 'Helper File "%s" is missing.'; } + +/** + * Used when a helper class cannot be found. + * + * @package cake.libs + */ class MissingHelperClassException extends CakeException { protected $_messageTemplate = 'Helper class "%s" is missing.'; } @@ -130,16 +203,30 @@ class MissingHelperClassException extends CakeException { class MissingDatabaseException extends CakeException { protected $_messageTemplate = 'Database connection "%s" could not be found.'; } + +/** + * Used when no connections can be found. + * + * @package cake.libs + */ class MissingConnectionException extends CakeException { protected $_messageTemplate = 'Database connection "%s" is missing.'; } /** - * Exceptions used by the TaskCollection. + * Used when a Task file cannot be found. + * + * @package cake.libs */ class MissingTaskFileException extends CakeException { protected $_messageTemplate = 'Task file "%s" is missing.'; } + +/** + * Used when a Task class cannot be found. + * + * @package cake.libs + */ class MissingTaskClassException extends CakeException { protected $_messageTemplate = 'Task class "%s" is missing.'; } @@ -147,6 +234,7 @@ class MissingTaskClassException extends CakeException { /** * Exception class to be thrown when a database table is not found in the datasource * + * @package cake.libs */ class MissingTableException extends CakeException { protected $_messageTemplate = 'Database table %s for model %s was not found.'; From cc17e1a85a8a27a39cab3fcda4e99f36fa00db57 Mon Sep 17 00:00:00 2001 From: Mark Story Date: Sat, 4 Sep 2010 19:18:14 -0400 Subject: [PATCH 088/166] Adding more doc blocks to error classes. --- cake/libs/exceptions.php | 26 ++++++++++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-) diff --git a/cake/libs/exceptions.php b/cake/libs/exceptions.php index 3f969c8a5..817dc2d20 100644 --- a/cake/libs/exceptions.php +++ b/cake/libs/exceptions.php @@ -19,8 +19,18 @@ * @license MIT License (http://www.opensource.org/licenses/mit-license.php) */ - +/** + * Represents an HTTP 404 error. + * + * @package cake.libs + */ class Error404Exception extends RuntimeException { +/** + * Constructor + * + * @param string $message If no message is given 'Not Found' will be the message + * @param string $code Status code, defaults to 404 + */ public function __construct($message, $code = 404) { if (empty($message)) { $message = __('Not Found'); @@ -28,7 +38,19 @@ class Error404Exception extends RuntimeException { parent::__construct($message, $code); } } -class Error500Exception extends CakeException { + +/** + * Represents an HTTP 500 error. + * + * @package cake.libs + */ +class Error500Exception extends CakeException { +/** + * Constructor + * + * @param string $message If no message is given 'Not Found' will be the message + * @param string $code Status code, defaults to 404 + */ public function __construct($message, $code = 500) { if (empty($message)) { $message = __('Internal Server Error'); From 82fffe6914429ad8b2cc8b1ee4cc34b657e574f5 Mon Sep 17 00:00:00 2001 From: Mark Story Date: Sun, 5 Sep 2010 01:28:13 -0400 Subject: [PATCH 089/166] Fixing issue where FormHelper::select() with multiple = checkbox and a custom name attribute would not work correctly. Fixes #1078 --- cake/libs/view/helpers/form.php | 7 +-- .../cases/libs/view/helpers/form.test.php | 52 +++++++++++++++++-- 2 files changed, 52 insertions(+), 7 deletions(-) diff --git a/cake/libs/view/helpers/form.php b/cake/libs/view/helpers/form.php index 3a9c60815..1e29d0461 100644 --- a/cake/libs/view/helpers/form.php +++ b/cake/libs/view/helpers/form.php @@ -1461,7 +1461,8 @@ class FormHelper extends AppHelper { $hiddenAttributes = array( 'value' => '', 'id' => $attributes['id'] . ($style ? '' : '_'), - 'secure' => false + 'secure' => false, + 'name' => $attributes['name'] ); $select[] = $this->hidden(null, $hiddenAttributes); } else { @@ -1495,7 +1496,7 @@ class FormHelper extends AppHelper { $selected, array(), $showParents, - array('escape' => $escapeOptions, 'style' => $style) + array('escape' => $escapeOptions, 'style' => $style, 'name' => $attributes['name']) )); $template = ($style == 'checkbox') ? 'checkboxmultipleend' : 'selectend'; @@ -2041,7 +2042,7 @@ class FormHelper extends AppHelper { $label['class'] = 'selected'; } - list($name) = array_values($this->_name()); + $name = $attributes['name']; if (empty($attributes['class'])) { $attributes['class'] = 'checkbox'; diff --git a/cake/tests/cases/libs/view/helpers/form.test.php b/cake/tests/cases/libs/view/helpers/form.test.php index 51b2b5803..10f1e4b4b 100644 --- a/cake/tests/cases/libs/view/helpers/form.test.php +++ b/cake/tests/cases/libs/view/helpers/form.test.php @@ -3448,7 +3448,10 @@ class FormHelperTest extends CakeTestCase { * @return void */ function testInputMultipleCheckboxes() { - $result = $this->Form->input('Model.multi_field', array('options' => array('first', 'second', 'third'), 'multiple' => 'checkbox')); + $result = $this->Form->input('Model.multi_field', array( + 'options' => array('first', 'second', 'third'), + 'multiple' => 'checkbox' + )); $expected = array( array('div' => array('class' => 'input select')), array('label' => array('for' => 'ModelMultiField')), @@ -3477,7 +3480,10 @@ class FormHelperTest extends CakeTestCase { ); $this->assertTags($result, $expected); - $result = $this->Form->input('Model.multi_field', array('options' => array('a' => 'first', 'b' => 'second', 'c' => 'third'), 'multiple' => 'checkbox')); + $result = $this->Form->input('Model.multi_field', array( + 'options' => array('a' => 'first', 'b' => 'second', 'c' => 'third'), + 'multiple' => 'checkbox' + )); $expected = array( array('div' => array('class' => 'input select')), array('label' => array('for' => 'ModelMultiField')), @@ -3506,7 +3512,12 @@ class FormHelperTest extends CakeTestCase { ); $this->assertTags($result, $expected); - $result = $this->Form->input('Model.multi_field', array('options' => array('1' => 'first'), 'multiple' => 'checkbox', 'label' => false, 'div' => false)); + $result = $this->Form->input('Model.multi_field', array( + 'options' => array('1' => 'first'), + 'multiple' => 'checkbox', + 'label' => false, + 'div' => false + )); $expected = array( 'input' => array('type' => 'hidden', 'name' => 'data[Model][multi_field]', 'value' => '', 'id' => 'ModelMultiField'), array('div' => array('class' => 'checkbox')), @@ -3518,7 +3529,12 @@ class FormHelperTest extends CakeTestCase { ); $this->assertTags($result, $expected); - $result = $this->Form->input('Model.multi_field', array('options' => array('2' => 'second'), 'multiple' => 'checkbox', 'label' => false, 'div' => false)); + $result = $this->Form->input('Model.multi_field', array( + 'options' => array('2' => 'second'), + 'multiple' => 'checkbox', + 'label' => false, + 'div' => false + )); $expected = array( 'input' => array('type' => 'hidden', 'name' => 'data[Model][multi_field]', 'value' => '', 'id' => 'ModelMultiField'), array('div' => array('class' => 'checkbox')), @@ -3531,6 +3547,34 @@ class FormHelperTest extends CakeTestCase { $this->assertTags($result, $expected); } +/** + * test that select() with multiple = checkbox works with overriding name attribute. + * + * @return void + */ + function testSelectCheckboxMultipleOverrideName() { + $result = $this->Form->input('category', array( + 'type' => 'select', + 'multiple' => 'checkbox', + 'name' => 'data[fish]', + 'options' => array('1', '2'), + 'div' => false, + 'label' => false, + )); + $expected = array( + 'input' => array('type' => 'hidden', 'name' => 'data[fish]', 'value' => '', 'id' => 'category'), + array('div' => array('class' => 'checkbox')), + array('input' => array('type' => 'checkbox', 'name' => 'data[fish][]', 'value' => '0', 'id' => 'Category0')), + array('label' => array('for' => 'Category0')), '1', '/label', + '/div', + array('div' => array('class' => 'checkbox')), + array('input' => array('type' => 'checkbox', 'name' => 'data[fish][]', 'value' => '1', 'id' => 'Category1')), + array('label' => array('for' => 'Category1')), '2', '/label', + '/div' + ); + $this->assertTags($result, $expected); + } + /** * testCheckbox method * From b7791dd94fbc5784e29839bf3a770d1f3616e140 Mon Sep 17 00:00:00 2001 From: Mark Story Date: Sun, 5 Sep 2010 02:04:08 -0400 Subject: [PATCH 090/166] Removing variable that wasn't provided by the exception. --- cake/libs/view/errors/error500.ctp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cake/libs/view/errors/error500.ctp b/cake/libs/view/errors/error500.ctp index fbd5a64bd..acc6a42c4 100644 --- a/cake/libs/view/errors/error500.ctp +++ b/cake/libs/view/errors/error500.ctp @@ -19,6 +19,6 @@ ?>

    - : - '{$message}'"); ?> + : +

    From e5b4dd94d71d92392fe209219c44407af578fe85 Mon Sep 17 00:00:00 2001 From: Mark Story Date: Sun, 5 Sep 2010 02:05:31 -0400 Subject: [PATCH 091/166] Renaming exceptions to not use Error400, Error500. Instead HTTP status words are used. Adding more common HTTP status errors. Updating tests for ErrorHandler. --- cake/libs/error_handler.php | 4 ++ cake/libs/exceptions.php | 68 ++++++++++++++++++-- cake/tests/cases/libs/error_handler.test.php | 16 ++--- 3 files changed, 76 insertions(+), 12 deletions(-) diff --git a/cake/libs/error_handler.php b/cake/libs/error_handler.php index 2b2277521..15fd4b101 100644 --- a/cake/libs/error_handler.php +++ b/cake/libs/error_handler.php @@ -106,6 +106,9 @@ class ErrorHandler { if ($exception instanceof CakeException && !$methodExists) { $method = '_cakeError'; + if ($template == 'internalError') { + $template = 'error500'; + } } elseif (!$methodExists) { $method = 'error500'; if ($code >= 400) { @@ -197,6 +200,7 @@ class ErrorHandler { $this->controller->set(array( 'code' => $code, 'url' => h($url), + 'name' => $error->getMessage() )); $this->controller->set($error->getAttributes()); $this->_outputMessage($this->template); diff --git a/cake/libs/exceptions.php b/cake/libs/exceptions.php index 817dc2d20..962c83195 100644 --- a/cake/libs/exceptions.php +++ b/cake/libs/exceptions.php @@ -19,12 +19,72 @@ * @license MIT License (http://www.opensource.org/licenses/mit-license.php) */ +/** + * Represents an HTTP 400 error. + * + * @package cake.libs + */ +class BadRequestException extends RuntimeException { +/** + * Constructor + * + * @param string $message If no message is given 'Bad Request' will be the message + * @param string $code Status code, defaults to 401 + */ + public function __construct($message, $code = 400) { + if (empty($message)) { + $message = 'Bad Request'; + } + parent::__construct($message, $code); + } +} + +/** + * Represents an HTTP 401 error. + * + * @package cake.libs + */ +class UnauthorizedException extends RuntimeException { +/** + * Constructor + * + * @param string $message If no message is given 'Unauthorized' will be the message + * @param string $code Status code, defaults to 401 + */ + public function __construct($message, $code = 401) { + if (empty($message)) { + $message = 'Unauthorized'; + } + parent::__construct($message, $code); + } +} + +/** + * Represents an HTTP 403 error. + * + * @package cake.libs + */ +class ForbiddenException extends RuntimeException { +/** + * Constructor + * + * @param string $message If no message is given 'Forbidden' will be the message + * @param string $code Status code, defaults to 401 + */ + public function __construct($message, $code = 403) { + if (empty($message)) { + $message = 'Forbidden'; + } + parent::__construct($message, $code); + } +} + /** * Represents an HTTP 404 error. * * @package cake.libs */ -class Error404Exception extends RuntimeException { +class NotFoundException extends RuntimeException { /** * Constructor * @@ -33,7 +93,7 @@ class Error404Exception extends RuntimeException { */ public function __construct($message, $code = 404) { if (empty($message)) { - $message = __('Not Found'); + $message = 'Not Found'; } parent::__construct($message, $code); } @@ -44,7 +104,7 @@ class Error404Exception extends RuntimeException { * * @package cake.libs */ -class Error500Exception extends CakeException { +class InternalErrorException extends CakeException { /** * Constructor * @@ -53,7 +113,7 @@ class Error500Exception extends CakeException { */ public function __construct($message, $code = 500) { if (empty($message)) { - $message = __('Internal Server Error'); + $message = 'Internal Server Error'; } parent::__construct($message, $code); } diff --git a/cake/tests/cases/libs/error_handler.test.php b/cake/tests/cases/libs/error_handler.test.php index 7915c14bc..a57de787d 100644 --- a/cake/tests/cases/libs/error_handler.test.php +++ b/cake/tests/cases/libs/error_handler.test.php @@ -193,7 +193,7 @@ class MyCustomErrorHandler extends ErrorHandler { * * @package cake.test.cases.libs */ -class MissingWidgetThingException extends Error404Exception { } +class MissingWidgetThingException extends NotFoundException { } /** @@ -239,7 +239,7 @@ class ErrorHandlerTest extends CakeTestCase { if ($this->skipIf(file_exists(APP . 'app_error.php'), 'App error exists cannot run.')) { return; } - $error = new Error404Exception('Kaboom!'); + $error = new NotFoundException('Kaboom!'); ob_start(); ErrorHandler::handleException($error); $result = ob_get_clean(); @@ -310,7 +310,7 @@ class ErrorHandlerTest extends CakeTestCase { * @return void */ function testConstruction() { - $exception = new Error404Exception('Page not found'); + $exception = new NotFoundException('Page not found'); $ErrorHandler = new ErrorHandler($exception); $this->assertType('CakeErrorController', $ErrorHandler->controller); @@ -385,7 +385,7 @@ class ErrorHandlerTest extends CakeTestCase { $request = new CakeRequest('posts/view/1000', false); Router::setRequestInfo($request); - $exception = new Error404Exception('Custom message'); + $exception = new NotFoundException('Custom message'); $ErrorHandler = new ErrorHandler($exception); $ErrorHandler->controller->response = $this->getMock('CakeResponse', array('statusCode')); $ErrorHandler->controller->response->expects($this->once())->method('statusCode')->with(404); @@ -408,7 +408,7 @@ class ErrorHandlerTest extends CakeTestCase { function testerror400OnlyChangingCakeException() { Configure::write('debug', 0); - $exception = new Error404Exception('Custom message'); + $exception = new NotFoundException('Custom message'); $ErrorHandler = new ErrorHandler($exception); ob_start(); @@ -429,13 +429,13 @@ class ErrorHandlerTest extends CakeTestCase { * * @return void */ - function testerror400NoInjection() { + function testError400NoInjection() { Router::reload(); $request = new CakeRequest('pages/pink', false); Router::setRequestInfo($request); - $exception = new Error404Exception('Custom message'); + $exception = new NotFoundException('Custom message'); $ErrorHandler = new ErrorHandler($exception); ob_start(); @@ -453,7 +453,7 @@ class ErrorHandlerTest extends CakeTestCase { * @return void */ function testError500Message() { - $exception = new Error500Exception('An Internal Error Has Occurred'); + $exception = new InternalErrorException('An Internal Error Has Occurred'); $ErrorHandler = new ErrorHandler($exception); $ErrorHandler->controller->response = $this->getMock('CakeResponse', array('statusCode')); $ErrorHandler->controller->response->expects($this->once())->method('statusCode')->with(500); From 9fee81cda0eedf4016672fd0d176055f04d463c0 Mon Sep 17 00:00:00 2001 From: Mark Story Date: Sun, 5 Sep 2010 11:10:48 -0400 Subject: [PATCH 092/166] Updating ConsoleErrorHandler to use new exception names and method renames. --- cake/console/console_error_handler.php | 2 +- cake/tests/cases/console/console_error_handler.test.php | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/cake/console/console_error_handler.php b/cake/console/console_error_handler.php index 0883b8b7f..942341bd8 100644 --- a/cake/console/console_error_handler.php +++ b/cake/console/console_error_handler.php @@ -84,7 +84,7 @@ class ConsoleErrorHandler extends ErrorHandler { * @param Exception $error Exception * @return void */ - public function error404($error) { + public function error400($error) { $this->_outputMessage(); } diff --git a/cake/tests/cases/console/console_error_handler.test.php b/cake/tests/cases/console/console_error_handler.test.php index e17fec34e..5254134d3 100644 --- a/cake/tests/cases/console/console_error_handler.test.php +++ b/cake/tests/cases/console/console_error_handler.test.php @@ -77,7 +77,7 @@ class ConsoleErrorHandlerTest extends CakeTestCase { * @return void */ function testError404Exception() { - $exception = new Error404Exception('dont use me in cli.'); + $exception = new NotFoundException('dont use me in cli.'); $error = new TestConsoleErrorHandler($exception); $error->render(); @@ -92,7 +92,7 @@ class ConsoleErrorHandlerTest extends CakeTestCase { * @return void */ function testError500Exception() { - $exception = new Error500Exception('dont use me in cli.'); + $exception = new InternalErrorException('dont use me in cli.'); $error = new TestConsoleErrorHandler($exception); $error->render(); @@ -107,7 +107,7 @@ class ConsoleErrorHandlerTest extends CakeTestCase { * @return void */ function testStdErrFilehandle() { - $exception = new Error500Exception('dont use me in cli.'); + $exception = new InternalErrorException('dont use me in cli.'); $error = new TestConsoleErrorHandler($exception); $this->assertTrue(is_resource($error->stderr), 'No handle.'); From 8bd0f18a53d26f9a701fea418851668b62c407d5 Mon Sep 17 00:00:00 2001 From: Mark Story Date: Sun, 5 Sep 2010 11:22:39 -0400 Subject: [PATCH 093/166] Adding a new line to the ConsoleErrorHandler Refactoring ConsoleErrorHandler test to use dynamic mocks. --- cake/console/console_error_handler.php | 1 + .../console/console_error_handler.test.php | 66 +++++++++---------- 2 files changed, 31 insertions(+), 36 deletions(-) diff --git a/cake/console/console_error_handler.php b/cake/console/console_error_handler.php index 942341bd8..58ce9527d 100644 --- a/cake/console/console_error_handler.php +++ b/cake/console/console_error_handler.php @@ -97,6 +97,7 @@ class ConsoleErrorHandler extends ErrorHandler { public function error500($error) { $this->_outputMessage(); } + /** * Outputs the exception to STDERR. * diff --git a/cake/tests/cases/console/console_error_handler.test.php b/cake/tests/cases/console/console_error_handler.test.php index 5254134d3..a35083bc6 100644 --- a/cake/tests/cases/console/console_error_handler.test.php +++ b/cake/tests/cases/console/console_error_handler.test.php @@ -19,21 +19,6 @@ */ require CAKE . 'console' . DS . 'console_error_handler.php'; -class TestConsoleErrorHandler extends ConsoleErrorHandler { - public $output = array(); - -/** - * Override stderr() so it doesn't do bad things. - * - * @param string $line - * @return void - */ - function stderr($line) { - $this->output[] = $line; - } -} - - /** * ConsoleErrorHandler Test case. * @@ -41,6 +26,15 @@ class TestConsoleErrorHandler extends ConsoleErrorHandler { */ class ConsoleErrorHandlerTest extends CakeTestCase { +/** + * Factory method for error handlers with stderr() mocked out. + * + * @return Mock object + */ + function getErrorHandler($exception) { + return $this->getMock('ConsoleErrorHandler', array('stderr'), array($exception)); + } + /** * test that the console error handler can deal with CakeExceptions. * @@ -48,12 +42,12 @@ class ConsoleErrorHandlerTest extends CakeTestCase { */ function testCakeErrors() { $exception = new MissingActionException('Missing action'); - $error = new TestConsoleErrorHandler($exception); - $error->render(); + $error = $this->getErrorHandler($exception); - $result = $error->output; - $this->assertEquals(1, count($result)); - $this->assertEquals('Missing action', $result[0]); + $error->expects($this->once())->method('stderr') + ->with('Missing action'); + + $error->render(); } /** @@ -63,12 +57,12 @@ class ConsoleErrorHandlerTest extends CakeTestCase { */ function testNonCakeExceptions() { $exception = new InvalidArgumentException('Too many parameters.'); - $error = new TestConsoleErrorHandler($exception); - $error->render(); + $error = $this->getErrorHandler($exception); - $result = $error->output; - $this->assertEquals(1, count($result)); - $this->assertEquals('Too many parameters.', $result[0]); + $error->expects($this->once())->method('stderr') + ->with('Too many parameters.'); + + $error->render(); } /** @@ -78,12 +72,12 @@ class ConsoleErrorHandlerTest extends CakeTestCase { */ function testError404Exception() { $exception = new NotFoundException('dont use me in cli.'); - $error = new TestConsoleErrorHandler($exception); - $error->render(); + $error = $this->getErrorHandler($exception); - $result = $error->output; - $this->assertEquals(1, count($result)); - $this->assertEquals('dont use me in cli.', $result[0]); + $error->expects($this->once())->method('stderr') + ->with('dont use me in cli.'); + + $error->render(); } /** @@ -93,12 +87,12 @@ class ConsoleErrorHandlerTest extends CakeTestCase { */ function testError500Exception() { $exception = new InternalErrorException('dont use me in cli.'); - $error = new TestConsoleErrorHandler($exception); - $error->render(); + $error = $this->getErrorHandler($exception); - $result = $error->output; - $this->assertEquals(1, count($result)); - $this->assertEquals('dont use me in cli.', $result[0]); + $error->expects($this->once())->method('stderr') + ->with('dont use me in cli.'); + + $error->render(); } /** @@ -108,7 +102,7 @@ class ConsoleErrorHandlerTest extends CakeTestCase { */ function testStdErrFilehandle() { $exception = new InternalErrorException('dont use me in cli.'); - $error = new TestConsoleErrorHandler($exception); + $error = new ConsoleErrorHandler($exception); $this->assertTrue(is_resource($error->stderr), 'No handle.'); } From 01eb0bf07d343545b3ea66870ccb393cffa4800d Mon Sep 17 00:00:00 2001 From: Mark Story Date: Sun, 5 Sep 2010 11:32:35 -0400 Subject: [PATCH 094/166] Making messages optional for HTTP exceptions. --- cake/libs/exceptions.php | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/cake/libs/exceptions.php b/cake/libs/exceptions.php index 962c83195..daa1e7f39 100644 --- a/cake/libs/exceptions.php +++ b/cake/libs/exceptions.php @@ -31,7 +31,7 @@ class BadRequestException extends RuntimeException { * @param string $message If no message is given 'Bad Request' will be the message * @param string $code Status code, defaults to 401 */ - public function __construct($message, $code = 400) { + public function __construct($message = null, $code = 400) { if (empty($message)) { $message = 'Bad Request'; } @@ -51,7 +51,7 @@ class UnauthorizedException extends RuntimeException { * @param string $message If no message is given 'Unauthorized' will be the message * @param string $code Status code, defaults to 401 */ - public function __construct($message, $code = 401) { + public function __construct($message = null, $code = 401) { if (empty($message)) { $message = 'Unauthorized'; } @@ -71,7 +71,7 @@ class ForbiddenException extends RuntimeException { * @param string $message If no message is given 'Forbidden' will be the message * @param string $code Status code, defaults to 401 */ - public function __construct($message, $code = 403) { + public function __construct($message = null, $code = 403) { if (empty($message)) { $message = 'Forbidden'; } @@ -91,7 +91,7 @@ class NotFoundException extends RuntimeException { * @param string $message If no message is given 'Not Found' will be the message * @param string $code Status code, defaults to 404 */ - public function __construct($message, $code = 404) { + public function __construct($message = null, $code = 404) { if (empty($message)) { $message = 'Not Found'; } @@ -111,7 +111,7 @@ class InternalErrorException extends CakeException { * @param string $message If no message is given 'Not Found' will be the message * @param string $code Status code, defaults to 404 */ - public function __construct($message, $code = 500) { + public function __construct($message = null, $code = 500) { if (empty($message)) { $message = 'Internal Server Error'; } From bfaaa6b8ba2422c7b9cec5c67a1ed81a8950388f Mon Sep 17 00:00:00 2001 From: ADmad Date: Sun, 5 Sep 2010 23:52:45 +0530 Subject: [PATCH 095/166] Fixing unnecessary extra calls to 'afterFind' callback of 'hasMany' associated models. Closes #995 --- cake/libs/model/datasources/dbo_source.php | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/cake/libs/model/datasources/dbo_source.php b/cake/libs/model/datasources/dbo_source.php index abe268294..ed5bbbf1d 100755 --- a/cake/libs/model/datasources/dbo_source.php +++ b/cake/libs/model/datasources/dbo_source.php @@ -54,7 +54,7 @@ class DboSource extends DataSource { /** * Caches result from query parsing operations. Cached results for both DboSource::name() and - * DboSource::conditions() will be stored here. Method caching uses `crc32()` which is + * DboSource::conditions() will be stored here. Method caching uses `crc32()` which is * fast but can collisions more easily than other hashing algorithms. If you have problems * with collisions, set DboSource::$cacheMethods to false. * @@ -519,7 +519,7 @@ class DboSource extends DataSource { * because the method uses a simple hashing algorithm it can infrequently have collisions. * Setting DboSource::$cacheMethods to false will disable the memory cache. * - * @param mixed $data Either a string with a column to quote. An array of columns to quote or an + * @param mixed $data Either a string with a column to quote. An array of columns to quote or an * object from DboSource::expression() or DboSource::identifier() * @return string SQL field * @access public @@ -845,6 +845,10 @@ class DboSource extends DataSource { $stack = array($assoc); $db->queryAssociation($model, $linkModel, $type, $assoc, $assocData, $array, true, $resultSet, $model->recursive - 1, $stack); unset($db); + + if ($type === 'hasMany') { + $filtered []= $assoc; + } } } } From 27ae7f1f44f6bf63f4f61a188ad4d1f7a683f7ee Mon Sep 17 00:00:00 2001 From: Mark Story Date: Mon, 6 Sep 2010 00:43:58 -0400 Subject: [PATCH 096/166] Making session storage classes not static, there was no real reason they were static before, and removing the static methods allows them to have constructors. This will allow moving database specific features from CakeSession to DatabaseSession. --- cake/libs/cake_session.php | 34 ++++++++-------- cake/libs/session/cache_session.php | 12 +++--- cake/libs/session/database_session.php | 12 +++--- .../cases/libs/session/cache_session.test.php | 30 +++++++++++--- .../libs/session/database_session.test.php | 40 ++++++++++++++----- 5 files changed, 82 insertions(+), 46 deletions(-) diff --git a/cake/libs/cake_session.php b/cake/libs/cake_session.php index b41237dae..4d5e71c8c 100644 --- a/cake/libs/cake_session.php +++ b/cake/libs/cake_session.php @@ -559,14 +559,14 @@ class CakeSession { call_user_func_array('session_set_save_handler', $sessionConfig['handler']); } if (!empty($sessionConfig['handler']['engine'])) { - $class = self::_getHandler($sessionConfig['handler']['engine']); + $handler = self::_getHandler($sessionConfig['handler']['engine']); session_set_save_handler( - array($class, 'open'), - array($class, 'close'), - array($class, 'read'), - array($class, 'write'), - array($class, 'destroy'), - array($class, 'gc') + array($handler, 'open'), + array($handler, 'close'), + array($handler, 'read'), + array($handler, 'write'), + array($handler, 'destroy'), + array($handler, 'gc') ); } Configure::write('Session', $sessionConfig); @@ -587,11 +587,11 @@ class CakeSession { if (!class_exists($class)) { throw new Exception(sprintf(__('Could not load %s to handle the session.'), $class)); } - $reflect = new ReflectionClass($class); - if (!$reflect->implementsInterface('CakeSessionHandlerInterface')) { - throw new Exception(__('Chosen SessionHandler does not implement CakeSessionHandlerInterface it cannot be used with an engine key.')); + $handler = new $class(); + if ($handler instanceof CakeSessionHandlerInterface) { + return $handler; } - return $class; + throw new Exception(__('Chosen SessionHandler does not implement CakeSessionHandlerInterface it cannot be used with an engine key.')); } /** @@ -768,14 +768,14 @@ interface CakeSessionHandlerInterface { * * @return boolean Success */ - public static function open(); + public function open(); /** * Method called on close of a session. * * @return boolean Success */ - public static function close(); + public function close(); /** * Method used to read from a session. @@ -783,7 +783,7 @@ interface CakeSessionHandlerInterface { * @param mixed $id The key of the value to read * @return mixed The value of the key or false if it does not exist */ - public static function read($id); + public function read($id); /** * Helper function called on write for sessions. @@ -792,7 +792,7 @@ interface CakeSessionHandlerInterface { * @param mixed $data The value of the data to be saved. * @return boolean True for successful write, false otherwise. */ - public static function write($id, $data); + public function write($id, $data); /** * Method called on the destruction of a session. @@ -800,7 +800,7 @@ interface CakeSessionHandlerInterface { * @param integer $id ID that uniquely identifies session in database * @return boolean True for successful delete, false otherwise. */ - public static function destroy($id); + public function destroy($id); /** * Run the Garbage collection on the session storage. This method should vacuum all @@ -809,7 +809,7 @@ interface CakeSessionHandlerInterface { * @param integer $expires Timestamp (defaults to current time) * @return boolean Success */ - public static function gc($expires = null); + public function gc($expires = null); } diff --git a/cake/libs/session/cache_session.php b/cake/libs/session/cache_session.php index e1b49ae16..5c8f2eae5 100644 --- a/cake/libs/session/cache_session.php +++ b/cake/libs/session/cache_session.php @@ -29,7 +29,7 @@ class CacheSession implements CakeSessionHandlerInterface { * @return boolean Success * @access private */ - public static function open() { + public function open() { return true; } @@ -39,7 +39,7 @@ class CacheSession implements CakeSessionHandlerInterface { * @return boolean Success * @access private */ - public static function close() { + public function close() { $probability = mt_rand(1, 150); if ($probability <= 3) { Cache::gc(); @@ -54,7 +54,7 @@ class CacheSession implements CakeSessionHandlerInterface { * @return mixed The value of the key or false if it does not exist * @access private */ - public static function read($id) { + public function read($id) { return Cache::read($id, Configure::read('Session.handler.config')); } @@ -66,7 +66,7 @@ class CacheSession implements CakeSessionHandlerInterface { * @return boolean True for successful write, false otherwise. * @access private */ - public static function write($id, $data) { + public function write($id, $data) { return Cache::write($id, $data, Configure::read('Session.handler.config')); } @@ -77,7 +77,7 @@ class CacheSession implements CakeSessionHandlerInterface { * @return boolean True for successful delete, false otherwise. * @access private */ - public static function destroy($id) { + public function destroy($id) { return Cache::delete($id, Configure::read('Session.handler.config')); } @@ -88,7 +88,7 @@ class CacheSession implements CakeSessionHandlerInterface { * @return boolean Success * @access private */ - public static function gc($expires = null) { + public function gc($expires = null) { return Cache::gc(); } } \ No newline at end of file diff --git a/cake/libs/session/database_session.php b/cake/libs/session/database_session.php index 19c48dffe..f2f7b710c 100644 --- a/cake/libs/session/database_session.php +++ b/cake/libs/session/database_session.php @@ -29,7 +29,7 @@ class DatabaseSession implements CakeSessionHandlerInterface { * @return boolean Success * @access private */ - public static function open() { + public function open() { return true; } @@ -39,7 +39,7 @@ class DatabaseSession implements CakeSessionHandlerInterface { * @return boolean Success * @access private */ - public static function close() { + public function close() { $probability = mt_rand(1, 150); if ($probability <= 3) { DatabaseSession::gc(); @@ -54,7 +54,7 @@ class DatabaseSession implements CakeSessionHandlerInterface { * @return mixed The value of the key or false if it does not exist * @access private */ - public static function read($id) { + public function read($id) { $model =& ClassRegistry::getObject('Session'); $row = $model->find('first', array( @@ -76,7 +76,7 @@ class DatabaseSession implements CakeSessionHandlerInterface { * @return boolean True for successful write, false otherwise. * @access private */ - public static function write($id, $data) { + public function write($id, $data) { $expires = time() + (Configure::read('Session.timeout') * 60); $model =& ClassRegistry::getObject('Session'); $return = $model->save(compact('id', 'data', 'expires')); @@ -90,7 +90,7 @@ class DatabaseSession implements CakeSessionHandlerInterface { * @return boolean True for successful delete, false otherwise. * @access private */ - public static function destroy($id) { + public function destroy($id) { $model =& ClassRegistry::getObject('Session'); $return = $model->delete($id); @@ -104,7 +104,7 @@ class DatabaseSession implements CakeSessionHandlerInterface { * @return boolean Success * @access private */ - public static function gc($expires = null) { + public function gc($expires = null) { $model =& ClassRegistry::getObject('Session'); if (!$expires) { diff --git a/cake/tests/cases/libs/session/cache_session.test.php b/cake/tests/cases/libs/session/cache_session.test.php index 64f2ae4d5..4b45eb7cc 100644 --- a/cake/tests/cases/libs/session/cache_session.test.php +++ b/cake/tests/cases/libs/session/cache_session.test.php @@ -52,13 +52,31 @@ class CacheSessionTest extends CakeTestCase { Configure::write('Session', self::$_sessionBackup); } +/** + * setup + * + * @return void + */ + function setup() { + $this->storage = new CacheSession(); + } + +/** + * teardown + * + * @return void + */ + function teardown() { + unset($this->storage); + } + /** * test open * * @return void */ function testOpen() { - $this->assertTrue(CacheSession::open()); + $this->assertTrue($this->storage->open()); } /** @@ -67,7 +85,7 @@ class CacheSessionTest extends CakeTestCase { * @return void */ function testWrite() { - CacheSession::write('abc', 'Some value'); + $this->storage->write('abc', 'Some value'); $this->assertEquals('Some value', Cache::read('abc', 'session_test'), 'Value was not written.'); $this->assertFalse(Cache::read('abc', 'default'), 'Cache should only write to the given config.'); } @@ -78,8 +96,8 @@ class CacheSessionTest extends CakeTestCase { * @return void */ function testRead() { - CacheSession::write('test_one', 'Some other value'); - $this->assertEquals('Some other value', CacheSession::read('test_one'), 'Incorrect value.'); + $this->storage->write('test_one', 'Some other value'); + $this->assertEquals('Some other value', $this->storage->read('test_one'), 'Incorrect value.'); } /** @@ -88,8 +106,8 @@ class CacheSessionTest extends CakeTestCase { * @return void */ function testDestroy() { - CacheSession::write('test_one', 'Some other value'); - $this->assertTrue(CacheSession::destroy('test_one'), 'Value was not deleted.'); + $this->storage->write('test_one', 'Some other value'); + $this->assertTrue($this->storage->destroy('test_one'), 'Value was not deleted.'); $this->assertFalse(Cache::read('test_one', 'session_test'), 'Value stuck around.'); } diff --git a/cake/tests/cases/libs/session/database_session.test.php b/cake/tests/cases/libs/session/database_session.test.php index d704887f7..e0cbe2494 100644 --- a/cake/tests/cases/libs/session/database_session.test.php +++ b/cake/tests/cases/libs/session/database_session.test.php @@ -68,13 +68,31 @@ class DatabaseSessionTest extends CakeTestCase { Configure::write('Session', self::$_sessionBackup); } +/** + * setup + * + * @return void + */ + function setup() { + $this->storage = new DatabaseSession(); + } + +/** + * teardown + * + * @return void + */ + function teardown() { + unset($this->storage); + } + /** * test opening the session * * @return void */ function testOpen() { - $this->assertTrue(DatabaseSession::open()); + $this->assertTrue($this->storage->open()); } /** @@ -83,7 +101,7 @@ class DatabaseSessionTest extends CakeTestCase { * @return void */ function testWrite() { - $result = DatabaseSession::write('foo', 'Some value'); + $result = $this->storage->write('foo', 'Some value'); $expected = array( 'Session' => array( 'id' => 'foo', @@ -100,13 +118,13 @@ class DatabaseSessionTest extends CakeTestCase { * @return void */ function testRead() { - DatabaseSession::write('foo', 'Some value'); + $this->storage->write('foo', 'Some value'); - $result = DatabaseSession::read('foo'); + $result = $this->storage->read('foo'); $expected = 'Some value'; $this->assertEquals($expected, $result); - $result = DatabaseSession::read('made up value'); + $result = $this->storage->read('made up value'); $this->assertFalse($result); } @@ -116,10 +134,10 @@ class DatabaseSessionTest extends CakeTestCase { * @return void */ function testDestroy() { - DatabaseSession::write('foo', 'Some value'); + $this->storage->write('foo', 'Some value'); - $this->assertTrue(DatabaseSession::destroy('foo'), 'Destroy failed'); - $this->assertFalse(DatabaseSession::read('foo'), 'Value still present.'); + $this->assertTrue($this->storage->destroy('foo'), 'Destroy failed'); + $this->assertFalse($this->storage->read('foo'), 'Value still present.'); } /** @@ -129,10 +147,10 @@ class DatabaseSessionTest extends CakeTestCase { */ function testGc() { Configure::write('Session.timeout', 0); - DatabaseSession::write('foo', 'Some value'); + $this->storage->write('foo', 'Some value'); sleep(1); - DatabaseSession::gc(); - $this->assertFalse(DatabaseSession::read('foo')); + $this->storage->gc(); + $this->assertFalse($this->storage->read('foo')); } } \ No newline at end of file From d62ae2900a58ebd9b3f8f8e860f4fd0ad26fb585 Mon Sep 17 00:00:00 2001 From: Mark Story Date: Mon, 6 Sep 2010 01:10:45 -0400 Subject: [PATCH 097/166] Fixing issue where ConnectionManager wasn't triggering session close, causing issues with database sessions. --- cake/libs/model/connection_manager.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cake/libs/model/connection_manager.php b/cake/libs/model/connection_manager.php index 1937663ff..db56cc189 100644 --- a/cake/libs/model/connection_manager.php +++ b/cake/libs/model/connection_manager.php @@ -269,7 +269,7 @@ class ConnectionManager { * */ function __destruct() { - if (Configure::read('Session.save') == 'database' && function_exists('session_write_close')) { + if (Configure::read('Session.defaults') == 'database' && function_exists('session_write_close')) { session_write_close(); } } From 474ace09c1c9bb9fbd3865b1facc545bdcf8bdc7 Mon Sep 17 00:00:00 2001 From: Mark Story Date: Mon, 6 Sep 2010 01:11:26 -0400 Subject: [PATCH 098/166] Adding CakeResponse to the list of included files for Controller. --- cake/libs/controller/controller.php | 1 + 1 file changed, 1 insertion(+) diff --git a/cake/libs/controller/controller.php b/cake/libs/controller/controller.php index db1636ec0..688b422a9 100644 --- a/cake/libs/controller/controller.php +++ b/cake/libs/controller/controller.php @@ -21,6 +21,7 @@ /** * Include files */ +App::import('Core', 'CakeResponse', false); App::import('Controller', 'Component', false); App::import('View', 'View', false); From c8ad4f11ebbe609882e4d280f50e41b3029a0218 Mon Sep 17 00:00:00 2001 From: Mark Story Date: Mon, 6 Sep 2010 01:11:54 -0400 Subject: [PATCH 099/166] Updating test session classes to not use static methods. --- .../test_app/libs/session/test_app_lib_session.php | 12 ++++++------ .../test_plugin/libs/session/test_plugin_session.php | 12 ++++++------ 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/cake/tests/test_app/libs/session/test_app_lib_session.php b/cake/tests/test_app/libs/session/test_app_lib_session.php index c3c522b70..a347404c0 100644 --- a/cake/tests/test_app/libs/session/test_app_lib_session.php +++ b/cake/tests/test_app/libs/session/test_app_lib_session.php @@ -5,27 +5,27 @@ */ class TestAppLibSession implements CakeSessionHandlerInterface { - public static function open() { + public function open() { return true; } - public static function close() { + public function close() { } - public static function read($id) { + public function read($id) { } - public static function write($id, $data) { + public function write($id, $data) { } - public static function destroy($id) { + public function destroy($id) { } - public static function gc($expires = null) { + public function gc($expires = null) { } } \ No newline at end of file diff --git a/cake/tests/test_app/plugins/test_plugin/libs/session/test_plugin_session.php b/cake/tests/test_app/plugins/test_plugin/libs/session/test_plugin_session.php index de5bf5a61..35a60d6e8 100644 --- a/cake/tests/test_app/plugins/test_plugin/libs/session/test_plugin_session.php +++ b/cake/tests/test_app/plugins/test_plugin/libs/session/test_plugin_session.php @@ -4,27 +4,27 @@ */ class TestPluginSession implements CakeSessionHandlerInterface { - public static function open() { + public function open() { return true; } - public static function close() { + public function close() { } - public static function read($id) { + public function read($id) { } - public static function write($id, $data) { + public function write($id, $data) { } - public static function destroy($id) { + public function destroy($id) { } - public static function gc($expires = null) { + public function gc($expires = null) { } } \ No newline at end of file From d54c901f5dce2000d4a85b00e59a71a6fc1047a9 Mon Sep 17 00:00:00 2001 From: Mark Story Date: Mon, 6 Sep 2010 01:12:23 -0400 Subject: [PATCH 100/166] Moving _setupDatabase() into the Database session class, as that's the only place its used. --- cake/libs/cake_session.php | 32 -------------------------- cake/libs/session/database_session.php | 30 ++++++++++++++++++++++++ 2 files changed, 30 insertions(+), 32 deletions(-) diff --git a/cake/libs/cake_session.php b/cake/libs/cake_session.php index 4d5e71c8c..abe0823ca 100644 --- a/cake/libs/cake_session.php +++ b/cake/libs/cake_session.php @@ -149,7 +149,6 @@ class CakeSession { self::$_userAgent = md5(env('HTTP_USER_AGENT') . Configure::read('Security.salt')); } - self::_setupDatabase(); if ($start === true) { self::_setPath($base); self::_setHost(env('HTTP_HOST')); @@ -192,37 +191,6 @@ class CakeSession { } } -/** - * Setup database configuration for Session, if enabled. - * - * @return void - */ - protected function _setupDatabase() { - if (Configure::read('Session.defaults') !== 'database') { - return; - } - $modelName = Configure::read('Session.handler.model'); - $database = Configure::read('Session.handler.database'); - $table = Configure::read('Session.handler.table'); - - if (empty($database)) { - $database = 'default'; - } - $settings = array( - 'class' => 'Session', - 'alias' => 'Session', - 'table' => 'cake_sessions', - 'ds' => $database - ); - if (!empty($modelName)) { - $settings['class'] = $modelName; - } - if (!empty($table)) { - $settings['table'] = $table; - } - ClassRegistry::init($settings); - } - /** * Starts the Session. * diff --git a/cake/libs/session/database_session.php b/cake/libs/session/database_session.php index f2f7b710c..5c9d18547 100644 --- a/cake/libs/session/database_session.php +++ b/cake/libs/session/database_session.php @@ -23,6 +23,36 @@ * @package cake.libs */ class DatabaseSession implements CakeSessionHandlerInterface { + +/** + * Constructor. Looks at Session configuration information and + * sets up the session model. + * + * @return void + */ + function __construct() { + $modelName = Configure::read('Session.handler.model'); + $database = Configure::read('Session.handler.database'); + $table = Configure::read('Session.handler.table'); + + if (empty($database)) { + $database = 'default'; + } + $settings = array( + 'class' => 'Session', + 'alias' => 'Session', + 'table' => 'cake_sessions', + 'ds' => $database + ); + if (!empty($modelName)) { + $settings['class'] = $modelName; + } + if (!empty($table)) { + $settings['table'] = $table; + } + ClassRegistry::init($settings); + } + /** * Method called on open of a database session. * From fd50c2ae2afeff5c13153adc9e931077bb543cc7 Mon Sep 17 00:00:00 2001 From: Mark Story Date: Mon, 6 Sep 2010 01:21:58 -0400 Subject: [PATCH 101/166] Adding some tests for the constructor. --- .../libs/session/database_session.test.php | 25 +++++++++++++++---- 1 file changed, 20 insertions(+), 5 deletions(-) diff --git a/cake/tests/cases/libs/session/database_session.test.php b/cake/tests/cases/libs/session/database_session.test.php index e0cbe2494..24d12b3b6 100644 --- a/cake/tests/cases/libs/session/database_session.test.php +++ b/cake/tests/cases/libs/session/database_session.test.php @@ -50,12 +50,11 @@ class DatabaseSessionTest extends CakeTestCase { */ public static function setupBeforeClass() { self::$_sessionBackup = Configure::read('Session'); - ClassRegistry::init(array( - 'class' => 'SessionTestModel', - 'alias' => 'Session', - 'ds' => 'test_suite' + Configure::write('Session.handler', array( + 'model' => 'SessionTestModel', + 'database' => 'test_suite', + 'table' => 'sessions' )); - Configure::write('Session.handler.model', 'SessionTestModel'); Configure::write('Session.timeout', 100); } @@ -84,6 +83,22 @@ class DatabaseSessionTest extends CakeTestCase { */ function teardown() { unset($this->storage); + ClassRegistry::flush(); + } + +/** + * test that constructor sets the right things up. + * + * @return void + */ + function testConstructionSettings() { + ClassRegistry::flush(); + $storage = new DatabaseSession(); + + $session = ClassRegistry::getObject('session'); + $this->assertType('SessionTestModel', $session); + $this->assertEquals('Session', $session->alias); + $this->assertEquals('test_suite', $session->useDbConfig); } /** From 2e46d2f5caa3cca78fe2d7f6646a7ff1606ef9ec Mon Sep 17 00:00:00 2001 From: Mark Story Date: Mon, 6 Sep 2010 01:38:31 -0400 Subject: [PATCH 102/166] Changing gif to png, so baked apps have the correct icon. Fixes #1081 --- cake/console/templates/skel/webroot/css/cake.generic.css | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cake/console/templates/skel/webroot/css/cake.generic.css b/cake/console/templates/skel/webroot/css/cake.generic.css index 4d0161f8c..7f978afc0 100644 --- a/cake/console/templates/skel/webroot/css/cake.generic.css +++ b/cake/console/templates/skel/webroot/css/cake.generic.css @@ -79,7 +79,7 @@ ul, li { } #header h1 { line-height:20px; - background: #003d4c url('../img/cake.icon.gif') no-repeat left; + background: #003d4c url('../img/cake.icon.png') no-repeat left; color: #fff; padding: 0px 30px; } From b491414a5101e06e579b2471ed215eb87c69a0be Mon Sep 17 00:00:00 2001 From: Mark Story Date: Mon, 6 Sep 2010 01:38:31 -0400 Subject: [PATCH 103/166] Changing gif to png, so baked apps have the correct icon. Fixes #1081 --- cake/console/templates/skel/webroot/css/cake.generic.css | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cake/console/templates/skel/webroot/css/cake.generic.css b/cake/console/templates/skel/webroot/css/cake.generic.css index 4d0161f8c..7f978afc0 100644 --- a/cake/console/templates/skel/webroot/css/cake.generic.css +++ b/cake/console/templates/skel/webroot/css/cake.generic.css @@ -79,7 +79,7 @@ ul, li { } #header h1 { line-height:20px; - background: #003d4c url('../img/cake.icon.gif') no-repeat left; + background: #003d4c url('../img/cake.icon.png') no-repeat left; color: #fff; padding: 0px 30px; } From 5789aaf24d5f6e527326878e62a099f1bf479b85 Mon Sep 17 00:00:00 2001 From: Mark Story Date: Mon, 6 Sep 2010 13:38:01 -0400 Subject: [PATCH 104/166] Applying patch from 'tkykmw'. Behavior mapped methods are no longer run through strtolower(). Mapped methods are now case sensitive. Fixes #318 --- cake/libs/model/behavior_collection.php | 4 ---- cake/tests/cases/libs/model/model_behavior.test.php | 4 ++++ 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/cake/libs/model/behavior_collection.php b/cake/libs/model/behavior_collection.php index 8895a798a..f5176d157 100644 --- a/cake/libs/model/behavior_collection.php +++ b/cake/libs/model/behavior_collection.php @@ -191,10 +191,6 @@ class BehaviorCollection extends ObjectCollection { */ public function dispatchMethod(&$model, $method, $params = array(), $strict = false) { $methods = array_keys($this->__methods); - foreach ($methods as $key => $value) { - $methods[$key] = strtolower($value); - } - $method = strtolower($method); $check = array_flip($methods); $found = isset($check[$method]); $call = null; diff --git a/cake/tests/cases/libs/model/model_behavior.test.php b/cake/tests/cases/libs/model/model_behavior.test.php index 06b69e38c..5d8c666ef 100644 --- a/cake/tests/cases/libs/model/model_behavior.test.php +++ b/cake/tests/cases/libs/model/model_behavior.test.php @@ -1024,6 +1024,10 @@ class BehaviorTest extends CakeTestCase { $result = $Apple->{'look for the remote'}('in the couch'); $expected = "Item.name = 'the remote' AND Location.name = 'the couch'"; $this->assertEqual($result, $expected); + + $result = $Apple->{'look for THE REMOTE'}('in the couch'); + $expected = "Item.name = 'THE REMOTE' AND Location.name = 'the couch'"; + $this->assertEqual($result, $expected, 'Mapped method was lowercased.'); } /** From 464d2217e63b83ae5d4b3bd2c4a28608f26d14db Mon Sep 17 00:00:00 2001 From: Mark Story Date: Mon, 6 Sep 2010 13:51:42 -0400 Subject: [PATCH 105/166] Renaming model_behavior test to behavior_collection test as that's the class that contains the tested methods. --- cake/libs/model/behavior_collection.php | 2 +- cake/tests/cases/libs/all_behaviors.test.php | 2 +- .../{model_behavior.test.php => behavior_collection.test.php} | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) rename cake/tests/cases/libs/model/{model_behavior.test.php => behavior_collection.test.php} (99%) diff --git a/cake/libs/model/behavior_collection.php b/cake/libs/model/behavior_collection.php index f5176d157..6b5de5072 100644 --- a/cake/libs/model/behavior_collection.php +++ b/cake/libs/model/behavior_collection.php @@ -65,7 +65,7 @@ class BehaviorCollection extends ObjectCollection { if (!empty($behaviors)) { foreach (Set::normalize($behaviors) as $behavior => $config) { - $this->attach($behavior, $config); + $this->load($behavior, $config); } } } diff --git a/cake/tests/cases/libs/all_behaviors.test.php b/cake/tests/cases/libs/all_behaviors.test.php index 1fd3a100d..625e4065a 100644 --- a/cake/tests/cases/libs/all_behaviors.test.php +++ b/cake/tests/cases/libs/all_behaviors.test.php @@ -36,7 +36,7 @@ class AllBehaviorsTest extends PHPUnit_Framework_TestSuite { $suite = new PHPUnit_Framework_TestSuite('Model Behavior and all behaviors'); $path = CORE_TEST_CASES . DS . 'libs' . DS . 'model' . DS . 'behaviors' . DS; - $suite->addTestFile(CORE_TEST_CASES . DS . 'libs' . DS . 'model' . DS . 'model_behavior.test.php'); + $suite->addTestFile(CORE_TEST_CASES . DS . 'libs' . DS . 'model' . DS . 'behavior_collection.test.php'); $suite->addTestFile($path . 'acl.test.php'); // $suite->addTestFile($path . 'containable.test.php'); diff --git a/cake/tests/cases/libs/model/model_behavior.test.php b/cake/tests/cases/libs/model/behavior_collection.test.php similarity index 99% rename from cake/tests/cases/libs/model/model_behavior.test.php rename to cake/tests/cases/libs/model/behavior_collection.test.php index 5d8c666ef..ebfa9fcbb 100644 --- a/cake/tests/cases/libs/model/model_behavior.test.php +++ b/cake/tests/cases/libs/model/behavior_collection.test.php @@ -411,12 +411,12 @@ class Test7Behavior extends ModelBehavior{ } /** - * BehaviorTest class + * BehaviorCollection class * * @package cake * @subpackage cake.tests.cases.libs.model */ -class BehaviorTest extends CakeTestCase { +class BehaviorCollectionTest extends CakeTestCase { /** * fixtures property From c60edfae6ddcdb1742415ce4287b2778a6f5df24 Mon Sep 17 00:00:00 2001 From: Mark Story Date: Mon, 6 Sep 2010 16:46:41 -0400 Subject: [PATCH 106/166] Fixing issue where errors containing code = 500, were not actually converted to error500 when debug = 0. Making missingConnection, and missingTable into error500 errors. --- cake/libs/error.php | 3 ++- cake/libs/model/connection_manager.php | 2 +- cake/libs/model/model.php | 5 +++-- cake/tests/cases/libs/error.test.php | 18 ++++++++++++++++++ 4 files changed, 24 insertions(+), 4 deletions(-) diff --git a/cake/libs/error.php b/cake/libs/error.php index 45c043bf4..e8d7a0d6a 100644 --- a/cake/libs/error.php +++ b/cake/libs/error.php @@ -106,6 +106,7 @@ class ErrorHandler extends Object { if (!in_array(strtolower($method), array_map('strtolower', get_class_methods($this)))) { $method = 'error'; } + if ($method !== 'error') { if (Configure::read('debug') == 0) { $parentClass = get_parent_class($this); @@ -116,7 +117,7 @@ class ErrorHandler extends Object { if (in_array(strtolower($method), $parentMethods)) { $method = 'error404'; } - if (isset($code) && $code == 500) { + if (isset($messages[0]['code']) && $messages[0]['code'] == 500) { $method = 'error500'; } } diff --git a/cake/libs/model/connection_manager.php b/cake/libs/model/connection_manager.php index 723ad0994..b9e599481 100644 --- a/cake/libs/model/connection_manager.php +++ b/cake/libs/model/connection_manager.php @@ -239,7 +239,7 @@ class ConnectionManager extends Object { $this->_connectionsEnum[$name] = $this->__connectionData($config); } } else { - $this->cakeError('missingConnection', array(array('className' => 'ConnectionManager'))); + $this->cakeError('missingConnection', array(array('code' => 500, 'className' => 'ConnectionManager'))); } } diff --git a/cake/libs/model/model.php b/cake/libs/model/model.php index 32a19a717..9a663204e 100644 --- a/cake/libs/model/model.php +++ b/cake/libs/model/model.php @@ -769,7 +769,8 @@ class Model extends Overloadable { if (is_array($sources) && !in_array(strtolower($this->tablePrefix . $tableName), array_map('strtolower', $sources))) { return $this->cakeError('missingTable', array(array( 'className' => $this->alias, - 'table' => $this->tablePrefix . $tableName + 'table' => $this->tablePrefix . $tableName, + 'code' => 500 ))); } $this->_schema = null; @@ -2826,7 +2827,7 @@ class Model extends Overloadable { } if (empty($db) || !is_object($db)) { - return $this->cakeError('missingConnection', array(array('className' => $this->alias))); + return $this->cakeError('missingConnection', array(array('code' => 500, 'className' => $this->alias))); } } diff --git a/cake/tests/cases/libs/error.test.php b/cake/tests/cases/libs/error.test.php index 4b181c3e5..ec90a57e2 100644 --- a/cake/tests/cases/libs/error.test.php +++ b/cake/tests/cases/libs/error.test.php @@ -609,4 +609,22 @@ class ErrorHandlerTest extends CakeTestCase { $this->assertPattern('/Article<\/em> could not be found./', $result); $this->assertPattern('/(\/|\\\)article.php/', $result); } + +/** + * testing that having a code => 500 in the cakeError call makes an + * internal server error. + * + * @return void + */ + function testThatCode500Works() { + Configure::write('debug', 0); + ob_start(); + $TestErrorHandler = new TestErrorHandler('missingTable', array( + 'className' => 'Article', + 'table' => 'articles', + 'code' => 500 + )); + $result = ob_get_clean(); + $this->assertPattern('/

    An Internal Error Has Occurred<\/h2>/', $result); + } } From 45dab881802eff7e85ebc63931cbf16b75b7f56a Mon Sep 17 00:00:00 2001 From: Mark Story Date: Mon, 6 Sep 2010 16:54:32 -0400 Subject: [PATCH 107/166] Adding a cast to fix a failing test from the merge. --- cake/tests/cases/libs/model/model_write.test.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cake/tests/cases/libs/model/model_write.test.php b/cake/tests/cases/libs/model/model_write.test.php index c4b0a6889..d05eba1cc 100644 --- a/cake/tests/cases/libs/model/model_write.test.php +++ b/cake/tests/cases/libs/model/model_write.test.php @@ -3877,7 +3877,7 @@ class ModelWriteTest extends BaseModelTest { 'count' => 1, 'float' => 3.14593 )); - $this->assertTrue($result); + $this->assertTrue((bool)$result); setlocale(LC_ALL, $restore); } From 09fd8ba46383ae01af5559a475c7977a1e51f5a0 Mon Sep 17 00:00:00 2001 From: Mark Story Date: Mon, 6 Sep 2010 17:54:48 -0400 Subject: [PATCH 108/166] Adding stack trace output to the framework errors. --- cake/libs/controller/cake_error_controller.php | 4 +++- cake/libs/error_handler.php | 3 ++- cake/libs/view/errors/missing_action.ctp | 3 ++- cake/libs/view/errors/missing_behavior_class.ctp | 4 +++- cake/libs/view/errors/missing_behavior_file.ctp | 2 ++ cake/libs/view/errors/missing_component_class.ctp | 4 +++- cake/libs/view/errors/missing_component_file.ctp | 4 +++- cake/libs/view/errors/missing_connection.ctp | 4 +++- cake/libs/view/errors/missing_controller.ctp | 4 +++- cake/libs/view/errors/missing_database.ctp | 4 +++- cake/libs/view/errors/missing_helper_class.ctp | 4 +++- cake/libs/view/errors/missing_helper_file.ctp | 2 ++ cake/libs/view/errors/missing_layout.ctp | 4 +++- cake/libs/view/errors/missing_table.ctp | 4 +++- cake/libs/view/errors/missing_view.ctp | 4 +++- cake/libs/view/errors/private_action.ctp | 4 +++- cake/libs/view/errors/scaffold_error.ctp | 4 +++- 17 files changed, 47 insertions(+), 15 deletions(-) diff --git a/cake/libs/controller/cake_error_controller.php b/cake/libs/controller/cake_error_controller.php index a5293d276..765e79f30 100644 --- a/cake/libs/controller/cake_error_controller.php +++ b/cake/libs/controller/cake_error_controller.php @@ -40,7 +40,9 @@ class CakeErrorController extends AppController { function beforeRender() { parent::beforeRender(); foreach ($this->viewVars as $key => $value) { - $this->viewVars[$key] = h($value); + if (!is_object($value)){ + $this->viewVars[$key] = h($value); + } } } } \ No newline at end of file diff --git a/cake/libs/error_handler.php b/cake/libs/error_handler.php index 15fd4b101..c1b7007df 100644 --- a/cake/libs/error_handler.php +++ b/cake/libs/error_handler.php @@ -200,7 +200,8 @@ class ErrorHandler { $this->controller->set(array( 'code' => $code, 'url' => h($url), - 'name' => $error->getMessage() + 'name' => $error->getMessage(), + 'error' => $error, )); $this->controller->set($error->getAttributes()); $this->_outputMessage($this->template); diff --git a/cake/libs/view/errors/missing_action.ctp b/cake/libs/view/errors/missing_action.ctp index fcaf5e5bf..85aae2dac 100644 --- a/cake/libs/view/errors/missing_action.ctp +++ b/cake/libs/view/errors/missing_action.ctp @@ -41,4 +41,5 @@ class extends AppController {

    : -

    \ No newline at end of file +

    +element('exception_stack_trace'); ?> \ No newline at end of file diff --git a/cake/libs/view/errors/missing_behavior_class.ctp b/cake/libs/view/errors/missing_behavior_class.ctp index 09dd42cbd..3bdc45a92 100644 --- a/cake/libs/view/errors/missing_behavior_class.ctp +++ b/cake/libs/view/errors/missing_behavior_class.ctp @@ -36,4 +36,6 @@ class extends ModelBehavior {

    : -

    \ No newline at end of file +

    + +element('exception_stack_trace'); ?> \ No newline at end of file diff --git a/cake/libs/view/errors/missing_behavior_file.ctp b/cake/libs/view/errors/missing_behavior_file.ctp index aba397885..a5a800bc6 100644 --- a/cake/libs/view/errors/missing_behavior_file.ctp +++ b/cake/libs/view/errors/missing_behavior_file.ctp @@ -37,3 +37,5 @@ class extends ModelBehavior { :

    + +element('exception_stack_trace'); ?> \ No newline at end of file diff --git a/cake/libs/view/errors/missing_component_class.ctp b/cake/libs/view/errors/missing_component_class.ctp index 6829c781d..85464acf6 100644 --- a/cake/libs/view/errors/missing_component_class.ctp +++ b/cake/libs/view/errors/missing_component_class.ctp @@ -36,4 +36,6 @@ class extends Component {

    : -

    \ No newline at end of file +

    + +element('exception_stack_trace'); ?> \ No newline at end of file diff --git a/cake/libs/view/errors/missing_component_file.ctp b/cake/libs/view/errors/missing_component_file.ctp index ff57d432b..ea9df3b9c 100644 --- a/cake/libs/view/errors/missing_component_file.ctp +++ b/cake/libs/view/errors/missing_component_file.ctp @@ -36,4 +36,6 @@ class extends Component {

    : -

    \ No newline at end of file +

    + +element('exception_stack_trace'); ?> \ No newline at end of file diff --git a/cake/libs/view/errors/missing_connection.ctp b/cake/libs/view/errors/missing_connection.ctp index 633997e7e..82c62bbb0 100644 --- a/cake/libs/view/errors/missing_connection.ctp +++ b/cake/libs/view/errors/missing_connection.ctp @@ -29,4 +29,6 @@

    : -

    \ No newline at end of file +

    + +element('exception_stack_trace'); ?> \ No newline at end of file diff --git a/cake/libs/view/errors/missing_controller.ctp b/cake/libs/view/errors/missing_controller.ctp index 855f0011d..afcef66fc 100644 --- a/cake/libs/view/errors/missing_controller.ctp +++ b/cake/libs/view/errors/missing_controller.ctp @@ -36,4 +36,6 @@ class extends AppController {

    : -

    \ No newline at end of file +

    + +element('exception_stack_trace'); ?> diff --git a/cake/libs/view/errors/missing_database.ctp b/cake/libs/view/errors/missing_database.ctp index 05b248b28..19750015d 100644 --- a/cake/libs/view/errors/missing_database.ctp +++ b/cake/libs/view/errors/missing_database.ctp @@ -29,4 +29,6 @@

    : -

    \ No newline at end of file +

    + +element('exception_stack_trace'); ?> \ No newline at end of file diff --git a/cake/libs/view/errors/missing_helper_class.ctp b/cake/libs/view/errors/missing_helper_class.ctp index 9de192c14..f98ae4262 100644 --- a/cake/libs/view/errors/missing_helper_class.ctp +++ b/cake/libs/view/errors/missing_helper_class.ctp @@ -36,4 +36,6 @@ class extends AppHelper {

    : -

    \ No newline at end of file +

    + +element('exception_stack_trace'); ?> \ No newline at end of file diff --git a/cake/libs/view/errors/missing_helper_file.ctp b/cake/libs/view/errors/missing_helper_file.ctp index 537ca3ad0..e7ca70cf7 100644 --- a/cake/libs/view/errors/missing_helper_file.ctp +++ b/cake/libs/view/errors/missing_helper_file.ctp @@ -37,3 +37,5 @@ class extends AppHelper { :

    + +element('exception_stack_trace'); ?> \ No newline at end of file diff --git a/cake/libs/view/errors/missing_layout.ctp b/cake/libs/view/errors/missing_layout.ctp index 02cfba190..128bbf3a5 100644 --- a/cake/libs/view/errors/missing_layout.ctp +++ b/cake/libs/view/errors/missing_layout.ctp @@ -29,4 +29,6 @@

    : -

    \ No newline at end of file +

    + +element('exception_stack_trace'); ?> \ No newline at end of file diff --git a/cake/libs/view/errors/missing_table.ctp b/cake/libs/view/errors/missing_table.ctp index 33d009293..03ba1d55c 100644 --- a/cake/libs/view/errors/missing_table.ctp +++ b/cake/libs/view/errors/missing_table.ctp @@ -25,4 +25,6 @@

    : -

    \ No newline at end of file +

    + +element('exception_stack_trace'); ?> \ No newline at end of file diff --git a/cake/libs/view/errors/missing_view.ctp b/cake/libs/view/errors/missing_view.ctp index 55aef34ce..4c1e88335 100644 --- a/cake/libs/view/errors/missing_view.ctp +++ b/cake/libs/view/errors/missing_view.ctp @@ -29,4 +29,6 @@

    : -

    \ No newline at end of file +

    + +element('exception_stack_trace'); ?> \ No newline at end of file diff --git a/cake/libs/view/errors/private_action.ctp b/cake/libs/view/errors/private_action.ctp index ab9f13cdc..d26d98995 100644 --- a/cake/libs/view/errors/private_action.ctp +++ b/cake/libs/view/errors/private_action.ctp @@ -25,4 +25,6 @@

    : -

    \ No newline at end of file +

    + +element('exception_stack_trace'); ?> \ No newline at end of file diff --git a/cake/libs/view/errors/scaffold_error.ctp b/cake/libs/view/errors/scaffold_error.ctp index 7c1800b42..e9efe610c 100644 --- a/cake/libs/view/errors/scaffold_error.ctp +++ b/cake/libs/view/errors/scaffold_error.ctp @@ -32,4 +32,6 @@ function _scaffoldError() {
    } ?> -

    \ No newline at end of file +
    + +element('exception_stack_trace'); ?> \ No newline at end of file From 0f2363438204afadcdd33b638127959d66424f3d Mon Sep 17 00:00:00 2001 From: Mark Story Date: Mon, 6 Sep 2010 18:09:11 -0400 Subject: [PATCH 109/166] Adding stack traces to error400 and error500 when debug > 0. Adding the stack trace element. --- cake/libs/error_handler.php | 2 ++ .../view/elements/exception_stack_trace.ctp | 24 +++++++++++++++++++ cake/libs/view/errors/error400.ctp | 7 +++++- cake/libs/view/errors/error500.ctp | 5 ++++ 4 files changed, 37 insertions(+), 1 deletion(-) create mode 100644 cake/libs/view/elements/exception_stack_trace.ctp diff --git a/cake/libs/error_handler.php b/cake/libs/error_handler.php index c1b7007df..53e1dfbaf 100644 --- a/cake/libs/error_handler.php +++ b/cake/libs/error_handler.php @@ -222,6 +222,7 @@ class ErrorHandler { $this->controller->set(array( 'name' => $message, 'url' => h($url), + 'error' => $error, )); $this->_outputMessage('error400'); } @@ -238,6 +239,7 @@ class ErrorHandler { $this->controller->set(array( 'name' => __('An Internal Error Has Occurred'), 'message' => h($url), + 'error' => $error, )); $this->_outputMessage('error500'); } diff --git a/cake/libs/view/elements/exception_stack_trace.ctp b/cake/libs/view/elements/exception_stack_trace.ctp new file mode 100644 index 000000000..9219e21ae --- /dev/null +++ b/cake/libs/view/elements/exception_stack_trace.ctp @@ -0,0 +1,24 @@ + +

    Stack Trace

    +
    +getTraceAsString(); ?>
    +
    \ No newline at end of file diff --git a/cake/libs/view/errors/error400.ctp b/cake/libs/view/errors/error400.ctp index 6631b0532..81a807b8b 100644 --- a/cake/libs/view/errors/error400.ctp +++ b/cake/libs/view/errors/error400.ctp @@ -24,4 +24,9 @@ __('The requested address %s was not found on this server.'), "'{$url}'" ); ?> -

    \ No newline at end of file +

    + 0 ): + echo $this->element('exception_stack_trace'); +endif; +?> \ No newline at end of file diff --git a/cake/libs/view/errors/error500.ctp b/cake/libs/view/errors/error500.ctp index acc6a42c4..d05f4107a 100644 --- a/cake/libs/view/errors/error500.ctp +++ b/cake/libs/view/errors/error500.ctp @@ -22,3 +22,8 @@ :

    + 0 ): + echo $this->element('exception_stack_trace'); +endif; +?> \ No newline at end of file From e15069769d387c9ec1edbb5db26a46254bb100ab Mon Sep 17 00:00:00 2001 From: Mark Story Date: Tue, 7 Sep 2010 00:09:06 -0400 Subject: [PATCH 110/166] Adding tests for #1079 and fixing some formatting. --- cake/libs/model/datasources/dbo_source.php | 2 +- .../model/datasources/dbo_source.test.php | 51 +++++++++++++++++++ 2 files changed, 52 insertions(+), 1 deletion(-) diff --git a/cake/libs/model/datasources/dbo_source.php b/cake/libs/model/datasources/dbo_source.php index ed5bbbf1d..6d718e3f1 100755 --- a/cake/libs/model/datasources/dbo_source.php +++ b/cake/libs/model/datasources/dbo_source.php @@ -1923,7 +1923,7 @@ class DboSource extends DataSource { foreach ($fields as $field) { $virtualField = $this->name($alias . $this->virtualFieldSeparator . $field); $expression = $this->__quoteFields($model->getVirtualField($field)); - $virtual[] = '(' .$expression . ") {$this->alias} {$virtualField}"; + $virtual[] = '(' . $expression . ") {$this->alias} {$virtualField}"; } return $virtual; } diff --git a/cake/tests/cases/libs/model/datasources/dbo_source.test.php b/cake/tests/cases/libs/model/datasources/dbo_source.test.php index 442d690ac..f7598ba11 100644 --- a/cake/tests/cases/libs/model/datasources/dbo_source.test.php +++ b/cake/tests/cases/libs/model/datasources/dbo_source.test.php @@ -4359,6 +4359,30 @@ class DboSourceTest extends CakeTestCase { $this->assertEqual($expected, $result); } +/** + * test that virtualFields with complex functions and aliases work. + * + * @return void + */ + function testConditionsWithComplexVirtualFields() { + $Article =& ClassRegistry::init('Article'); + $Article->virtualFields = array( + 'distance' => 'ACOS(SIN(20 * PI() / 180) + * SIN(Article.latitude * PI() / 180) + + COS(20 * PI() / 180) + * COS(Article.latitude * PI() / 180) + * COS((50 - Article.longitude) * PI() / 180) + ) * 180 / PI() * 60 * 1.1515 * 1.609344' + ); + + $conditions = array('distance >=' => 20); + $result = $this->db->conditions($conditions, true, true, $Article); + + $this->assertPattern('/\) >= 20/', $result); + $this->assertPattern('/[`\'"]Article[`\'"].[`\'"]latitude[`\'"]/', $result); + $this->assertPattern('/[`\'"]Article[`\'"].[`\'"]longitude[`\'"]/', $result); + } + /** * test order to generate query order clause for virtual fields * @@ -4432,6 +4456,33 @@ class DboSourceTest extends CakeTestCase { $this->assertEqual($expected, $result); } +/** + * test that virtualFields with complex functions and aliases work. + * + * @return void + */ + function testFieldsWithComplexVirtualFields() { + $Article =& new Article(); + $Article->virtualFields = array( + 'distance' => 'ACOS(SIN(20 * PI() / 180) + * SIN(Article.latitude * PI() / 180) + + COS(20 * PI() / 180) + * COS(Article.latitude * PI() / 180) + * COS((50 - Article.longitude) * PI() / 180) + ) * 180 / PI() * 60 * 1.1515 * 1.609344' + ); + + $fields = array('id', 'distance'); + $result = $this->db->fields($Article, null, $fields); + $qs = $this->db->startQuote; + $qe = $this->db->endQuote; + + $this->assertEqual($result[0], "{$qs}Article{$qe}.{$qs}id{$qe}"); + $this->assertPattern('/Article__distance/', $result[1]); + $this->assertPattern('/[`\'"]Article[`\'"].[`\'"]latitude[`\'"]/', $result[1]); + $this->assertPattern('/[`\'"]Article[`\'"].[`\'"]longitude[`\'"]/', $result[1]); + } + /** * test group to generate GROUP BY statements on virtual fields * From aad72871a09b8b1bf750cde84d42e6a4f4fd7d2e Mon Sep 17 00:00:00 2001 From: Mark Story Date: Tue, 7 Sep 2010 00:32:44 -0400 Subject: [PATCH 111/166] Adding more tests for virtualFields and complex expressions. Closes #1079 --- .../model/datasources/dbo_source.test.php | 44 ++++++++++++++----- cake/tests/fixtures/data_test_fixture.php | 9 +++- 2 files changed, 42 insertions(+), 11 deletions(-) diff --git a/cake/tests/cases/libs/model/datasources/dbo_source.test.php b/cake/tests/cases/libs/model/datasources/dbo_source.test.php index f7598ba11..eef348313 100644 --- a/cake/tests/cases/libs/model/datasources/dbo_source.test.php +++ b/cake/tests/cases/libs/model/datasources/dbo_source.test.php @@ -1279,7 +1279,7 @@ class DboSourceTest extends CakeTestCase { */ var $fixtures = array( 'core.apple', 'core.article', 'core.articles_tag', 'core.attachment', 'core.comment', - 'core.sample', 'core.tag', 'core.user', 'core.post', 'core.author' + 'core.sample', 'core.tag', 'core.user', 'core.post', 'core.author', 'core.data_test' ); /** @@ -4329,8 +4329,6 @@ class DboSourceTest extends CakeTestCase { * @return void */ function testVirtualFieldsInConditions() { - $this->loadFixtures('Article'); - $Article =& ClassRegistry::init('Article'); $Article->virtualFields = array( 'this_moment' => 'NOW()', @@ -4374,7 +4372,6 @@ class DboSourceTest extends CakeTestCase { * COS((50 - Article.longitude) * PI() / 180) ) * 180 / PI() * 60 * 1.1515 * 1.609344' ); - $conditions = array('distance >=' => 20); $result = $this->db->conditions($conditions, true, true, $Article); @@ -4389,8 +4386,6 @@ class DboSourceTest extends CakeTestCase { * @return void */ function testVirtualFieldsInOrder() { - $this->loadFixtures('Article'); - $Article =& ClassRegistry::init('Article'); $Article->virtualFields = array( 'this_moment' => 'NOW()', @@ -4413,8 +4408,6 @@ class DboSourceTest extends CakeTestCase { * @return void */ function testVirtualFieldsInCalculate() { - $this->loadFixtures('Article'); - $Article =& ClassRegistry::init('Article'); $Article->virtualFields = array( 'this_moment' => 'NOW()', @@ -4455,6 +4448,39 @@ class DboSourceTest extends CakeTestCase { )); $this->assertEqual($expected, $result); } +˝ +/** + * test reading complex virtualFields with subqueries. + * + * @return void + */ + function testVirtualFieldsComplexRead() { + $this->loadFixtures('DataTest', 'Article', 'Comment'); + + $Article =& ClassRegistry::init('Article'); + $commentTable = $this->db->fullTableName('comments'); + $Article =& ClassRegistry::init('Article'); + $Article->virtualFields = array( + 'comment_count' => 'SELECT COUNT(*) FROM ' . $commentTable . + ' AS Comment WHERE Article.id = Comment.article_id' + ); + $result = $Article->find('all'); + $this->assertTrue(count($result) > 0); + $this->assertTrue($result[0]['Article']['comment_count'] > 0); + + $DataTest =& ClassRegistry::init('DataTest'); + $DataTest->virtualFields = array( + 'complicated' => 'ACOS(SIN(20 * PI() / 180) + * SIN(DataTest.float * PI() / 180) + + COS(20 * PI() / 180) + * COS(DataTest.count * PI() / 180) + * COS((50 - DataTest.float) * PI() / 180) + ) * 180 / PI() * 60 * 1.1515 * 1.609344' + ); + $result = $DataTest->find('all'); + $this->assertTrue(count($result) > 0); + $this->assertTrue($result[0]['DataTest']['complicated'] > 0); + } /** * test that virtualFields with complex functions and aliases work. @@ -4489,8 +4515,6 @@ class DboSourceTest extends CakeTestCase { * @return void */ function testVirtualFieldsInGroup() { - $this->loadFixtures('Article'); - $Article =& ClassRegistry::init('Article'); $Article->virtualFields = array( 'this_year' => 'YEAR(Article.created)' diff --git a/cake/tests/fixtures/data_test_fixture.php b/cake/tests/fixtures/data_test_fixture.php index 54af3a200..adf635b9e 100644 --- a/cake/tests/fixtures/data_test_fixture.php +++ b/cake/tests/fixtures/data_test_fixture.php @@ -55,5 +55,12 @@ class DataTestFixture extends CakeTestFixture { * @var array * @access public */ - var $records = array(); + var $records = array( + array( + 'count' => 2, + 'float' => 2.4, + 'created' => '2010-09-06 12:28:00', + 'updated' => '2010-09-06 12:28:00' + ) + ); } From 2b3099fa7059a34273a85c77e90071fe1d946546 Mon Sep 17 00:00:00 2001 From: Mark Story Date: Tue, 7 Sep 2010 00:42:49 -0400 Subject: [PATCH 112/166] Removing duplicate method call. --- cake/libs/session/database_session.php | 2 -- 1 file changed, 2 deletions(-) diff --git a/cake/libs/session/database_session.php b/cake/libs/session/database_session.php index bba074c74..e10fe5a93 100644 --- a/cake/libs/session/database_session.php +++ b/cake/libs/session/database_session.php @@ -130,8 +130,6 @@ class DatabaseSession implements CakeSessionHandlerInterface { * @access private */ public function gc($expires = null) { - $model = ClassRegistry::getObject('Session'); - if (!$expires) { $expires = time(); } From 4ff52da57ebec3815be1765007148a00c8590f6b Mon Sep 17 00:00:00 2001 From: mark_story Date: Tue, 7 Sep 2010 23:39:31 -0400 Subject: [PATCH 113/166] Making import() ing a component ensure that the Component base class is loaded. --- cake/libs/configure.php | 1 + 1 file changed, 1 insertion(+) diff --git a/cake/libs/configure.php b/cake/libs/configure.php index ce7289029..1b9b6707e 100644 --- a/cake/libs/configure.php +++ b/cake/libs/configure.php @@ -1107,6 +1107,7 @@ class App { return array('class' => $type, 'suffix' => $type, 'path' => $path); break; case 'component': + App::import('Core', 'Component', false); if ($plugin) { $path = $pluginPath . DS . 'controllers' . DS . 'components' . DS; } From 6e5e32bef5762f7ebf7faa2e06a2cc4025365137 Mon Sep 17 00:00:00 2001 From: mark_story Date: Tue, 7 Sep 2010 23:40:07 -0400 Subject: [PATCH 114/166] Updating AclShell test to use AclComponent correctly. --- cake/console/libs/acl.php | 3 ++- cake/tests/cases/console/libs/acl.test.php | 5 +++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/cake/console/libs/acl.php b/cake/console/libs/acl.php index 6627d1850..fde573223 100644 --- a/cake/console/libs/acl.php +++ b/cake/console/libs/acl.php @@ -91,7 +91,8 @@ class AclShell extends Shell { require_once (CONFIGS.'database.php'); if (!in_array($this->command, array('initdb'))) { - $this->Acl =& new AclComponent(); + $collection = new ComponentCollection(); + $this->Acl =& new AclComponent($collection); $controller = null; $this->Acl->startup($controller); } diff --git a/cake/tests/cases/console/libs/acl.test.php b/cake/tests/cases/console/libs/acl.test.php index 628a168b3..559e5eb3a 100644 --- a/cake/tests/cases/console/libs/acl.test.php +++ b/cake/tests/cases/console/libs/acl.test.php @@ -63,7 +63,7 @@ class AclShellTest extends CakeTestCase { Configure::write('Acl.classname', 'DbAcl'); $this->Dispatcher = $this->getMock( - 'ShellDispather', + 'ShellDispatcher', array('getInput', 'stdout', 'stderr', '_stop', '_initEnvironment', 'dispatch') ); $this->Task = $this->getMock( @@ -71,7 +71,8 @@ class AclShellTest extends CakeTestCase { array('in', 'out', 'hr', 'createFile', 'error', 'err'), array(&$this->Dispatcher) ); - $this->Task->Acl = new AclComponent(); + $collection = new ComponentCollection(); + $this->Task->Acl = new AclComponent($collection); $this->Task->params['datasource'] = 'test_suite'; } From b02d961d827f91da337346d521f4e3db51c92f04 Mon Sep 17 00:00:00 2001 From: mark_story Date: Tue, 7 Sep 2010 23:40:31 -0400 Subject: [PATCH 115/166] Adding ConsoleErrorHandler to the shell group. --- cake/tests/cases/console/all_shells.test.php | 1 + 1 file changed, 1 insertion(+) diff --git a/cake/tests/cases/console/all_shells.test.php b/cake/tests/cases/console/all_shells.test.php index 42807f1d7..6c1f45190 100644 --- a/cake/tests/cases/console/all_shells.test.php +++ b/cake/tests/cases/console/all_shells.test.php @@ -39,6 +39,7 @@ class AllShellsTest extends PHPUnit_Framework_TestSuite { $path = CORE_TEST_CASES . DS . 'console' . DS . 'libs' . DS; $suite->addTestFile(CORE_TEST_CASES . DS . 'console' . DS . 'cake.test.php'); + $suite->addTestFile(CORE_TEST_CASES . DS . 'console' . DS . 'error_console_handler.test.php'); $tasks = array('acl', 'api', 'bake', 'schema', 'shell'); foreach ($tasks as $task) { $suite->addTestFile($path . $task . '.test.php'); From f94fcfb749ff18283fe531e4805567fb64508e7d Mon Sep 17 00:00:00 2001 From: mark_story Date: Tue, 7 Sep 2010 23:42:18 -0400 Subject: [PATCH 116/166] Updating Api shell test case to account for changes in controller api. --- cake/tests/cases/console/libs/api.test.php | 31 +++++++++++----------- 1 file changed, 16 insertions(+), 15 deletions(-) diff --git a/cake/tests/cases/console/libs/api.test.php b/cake/tests/cases/console/libs/api.test.php index aeea6c737..76f52b449 100644 --- a/cake/tests/cases/console/libs/api.test.php +++ b/cake/tests/cases/console/libs/api.test.php @@ -84,21 +84,22 @@ class ApiShellTest extends CakeTestCase { '4. constructClasses()', '5. disableCache()', '6. flash($message, $url, $pause = 1, $layout = \'flash\')', - '7. header($status)', - '8. httpCodes($code = NULL)', - '9. isAuthorized()', - '10. loadModel($modelClass = NULL, $id = NULL)', - '11. paginate($object = NULL, $scope = array (), $whitelist = array ())', - '12. postConditions($data = array (), $op = NULL, $bool = \'AND\', $exclusive = false)', - '13. redirect($url, $status = NULL, $exit = true)', - '14. referer($default = NULL, $local = false)', - '15. render($action = NULL, $layout = NULL, $file = NULL)', - '16. set($one, $two = NULL)', - '17. setAction($action)', - '18. shutdownProcess()', - '19. startupProcess()', - '20. validate()', - '21. validateErrors()' + '7. getResponse()', + '8. header($status)', + '9. httpCodes($code = NULL)', + '10. isAuthorized()', + '11. loadModel($modelClass = NULL, $id = NULL)', + '12. paginate($object = NULL, $scope = array (), $whitelist = array ())', + '13. postConditions($data = array (), $op = NULL, $bool = \'AND\', $exclusive = false)', + '14. redirect($url, $status = NULL, $exit = true)', + '15. referer($default = NULL, $local = false)', + '16. render($action = NULL, $layout = NULL, $file = NULL)', + '17. set($one, $two = NULL)', + '18. setAction($action)', + '19. shutdownProcess()', + '20. startupProcess()', + '21. validate()', + '22. validateErrors()' ); $this->Shell->expects($this->at(2))->method('out')->with($expected); From f677c4ab44e60763da9aa087f18aeb51b5123678 Mon Sep 17 00:00:00 2001 From: mark_story Date: Tue, 7 Sep 2010 23:51:39 -0400 Subject: [PATCH 117/166] Fixing bake task tests and adding ConsoleErrorHandler to the AllShells suite. --- cake/tests/cases/console/all_shells.test.php | 2 +- cake/tests/cases/console/libs/bake.test.php | 8 ++++---- cake/tests/cases/console/libs/tasks/fixture.test.php | 4 ++-- cake/tests/cases/console/libs/tasks/test.test.php | 2 +- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/cake/tests/cases/console/all_shells.test.php b/cake/tests/cases/console/all_shells.test.php index 6c1f45190..50f8763d9 100644 --- a/cake/tests/cases/console/all_shells.test.php +++ b/cake/tests/cases/console/all_shells.test.php @@ -39,7 +39,7 @@ class AllShellsTest extends PHPUnit_Framework_TestSuite { $path = CORE_TEST_CASES . DS . 'console' . DS . 'libs' . DS; $suite->addTestFile(CORE_TEST_CASES . DS . 'console' . DS . 'cake.test.php'); - $suite->addTestFile(CORE_TEST_CASES . DS . 'console' . DS . 'error_console_handler.test.php'); + $suite->addTestFile(CORE_TEST_CASES . DS . 'console' . DS . 'console_error_handler.test.php'); $tasks = array('acl', 'api', 'bake', 'schema', 'shell'); foreach ($tasks as $task) { $suite->addTestFile($path . $task . '.test.php'); diff --git a/cake/tests/cases/console/libs/bake.test.php b/cake/tests/cases/console/libs/bake.test.php index f11bf99be..370cabc90 100644 --- a/cake/tests/cases/console/libs/bake.test.php +++ b/cake/tests/cases/console/libs/bake.test.php @@ -91,10 +91,10 @@ class BakeShellTest extends CakeTestCase { if ($this->skipIf($userExists, 'User class exists, cannot test `bake all [param]`. %s')) { return; } - $this->Shell->Model = $this->getMock('ModelTask', array(), array(&$this->Dispatch)); - $this->Shell->Controller = $this->getMock('ControllerTask', array(), array(&$this->Dispatch)); - $this->Shell->View = $this->getMock('ModelTask', array(), array(&$this->Dispatch)); - $this->Shell->DbConfig = $this->getMock('DbConfigTask', array(), array(&$this->Dispatch)); + $this->Shell->Model = $this->getMock('ModelTask', array(), array(&$this->Dispatcher)); + $this->Shell->Controller = $this->getMock('ControllerTask', array(), array(&$this->Dispatcher)); + $this->Shell->View = $this->getMock('ModelTask', array(), array(&$this->Dispatcher)); + $this->Shell->DbConfig = $this->getMock('DbConfigTask', array(), array(&$this->Dispatcher)); $this->Shell->DbConfig->expects($this->once())->method('getConfig')->will($this->returnValue('test_suite')); diff --git a/cake/tests/cases/console/libs/tasks/fixture.test.php b/cake/tests/cases/console/libs/tasks/fixture.test.php index 975b492c6..f9485a789 100644 --- a/cake/tests/cases/console/libs/tasks/fixture.test.php +++ b/cake/tests/cases/console/libs/tasks/fixture.test.php @@ -87,8 +87,8 @@ class FixtureTaskTest extends CakeTestCase { * @return void */ public function testConstruct() { - $this->Dispatch->params['working'] = DS . 'my' . DS . 'path'; - $Task = new FixtureTask($this->Dispatch); + $this->Dispatcher->params['working'] = DS . 'my' . DS . 'path'; + $Task = new FixtureTask($this->Dispatcher); $expected = DS . 'my' . DS . 'path' . DS . 'tests' . DS . 'fixtures' . DS; $this->assertEqual($Task->path, $expected); diff --git a/cake/tests/cases/console/libs/tasks/test.test.php b/cake/tests/cases/console/libs/tasks/test.test.php index 7cd608020..f8753b905 100644 --- a/cake/tests/cases/console/libs/tasks/test.test.php +++ b/cake/tests/cases/console/libs/tasks/test.test.php @@ -368,7 +368,7 @@ class TestTaskTest extends CakeTestCase { ) )); $keys = ClassRegistry::keys(); - $this->assertTrue(in_array('random', $keys)); + $this->assertTrue(in_array('test_task_comment', $keys)); $object =& $this->Task->buildTestSubject('Model', 'TestTaskComment'); $keys = ClassRegistry::keys(); From 2d86c1248ffdb33d1e3daae81eef20b965dc4b21 Mon Sep 17 00:00:00 2001 From: mark_story Date: Tue, 7 Sep 2010 23:53:12 -0400 Subject: [PATCH 118/166] Adding view import to fix xml suite from not running. --- cake/tests/cases/libs/view/helpers/rss.test.php | 1 + 1 file changed, 1 insertion(+) diff --git a/cake/tests/cases/libs/view/helpers/rss.test.php b/cake/tests/cases/libs/view/helpers/rss.test.php index 7db36bbe3..3f7512d17 100644 --- a/cake/tests/cases/libs/view/helpers/rss.test.php +++ b/cake/tests/cases/libs/view/helpers/rss.test.php @@ -17,6 +17,7 @@ * @since CakePHP(tm) v 1.2.0.4206 * @license http://www.opensource.org/licenses/opengroup.php The Open Group Test Suite License */ +App::import('View', 'View'); App::import('Helper', array('Rss', 'Time')); /** From fa9eb94fb00e6268cecadea50972e573c537835a Mon Sep 17 00:00:00 2001 From: mark_story Date: Wed, 8 Sep 2010 00:10:36 -0400 Subject: [PATCH 119/166] Adding base class import for view classes. --- cake/libs/configure.php | 1 + 1 file changed, 1 insertion(+) diff --git a/cake/libs/configure.php b/cake/libs/configure.php index 1b9b6707e..16148f2a4 100644 --- a/cake/libs/configure.php +++ b/cake/libs/configure.php @@ -1120,6 +1120,7 @@ class App { return array('class' => null, 'suffix' => null, 'path' => $path); break; case 'view': + App::import('View', 'View', false); if ($plugin) { $path = $pluginPath . DS . 'views' . DS; } From 58d62cb369e5a7b488b5d24213c46e7a5f765c5a Mon Sep 17 00:00:00 2001 From: mark_story Date: Wed, 8 Sep 2010 00:11:11 -0400 Subject: [PATCH 120/166] Fixing issues with tests failing because exception messages changed. --- cake/tests/cases/dispatcher.test.php | 25 +++++++++++++++---------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/cake/tests/cases/dispatcher.test.php b/cake/tests/cases/dispatcher.test.php index 5348e01a1..f6717e6bb 100644 --- a/cake/tests/cases/dispatcher.test.php +++ b/cake/tests/cases/dispatcher.test.php @@ -720,7 +720,7 @@ class DispatcherTest extends CakeTestCase { $controller = $Dispatcher->dispatch($url, array('return' => 1)); $this->fail('No exception thrown'); } catch (MissingControllerException $e) { - $this->assertEquals('SomeControllerController', $e->getMessage()); + $this->assertEquals('Controller class SomeControllerController could not be found.', $e->getMessage()); } } @@ -738,7 +738,9 @@ class DispatcherTest extends CakeTestCase { $controller = $Dispatcher->dispatch($url, array('return' => 1)); $this->fail('No exception thrown'); } catch (PrivateActionException $e) { - $this->assertEquals('SomePagesController::_protected()', $e->getMessage()); + $this->assertEquals( + 'Private Action SomePagesController::_protected() is not directly accessible.', $e->getMessage() + ); } } @@ -756,7 +758,7 @@ class DispatcherTest extends CakeTestCase { $controller = $Dispatcher->dispatch($url, array('return'=> 1)); $this->fail('No exception thrown'); } catch (MissingActionException $e) { - $this->assertEquals('SomePagesController::home()', $e->getMessage()); + $this->assertEquals('Action SomePagesController::home() could not be found.', $e->getMessage()); } } @@ -774,7 +776,7 @@ class DispatcherTest extends CakeTestCase { $controller = $Dispatcher->dispatch($url, array('return'=> 1)); $this->fail('No exception thrown'); } catch (MissingActionException $e) { - $this->assertEquals('SomePagesController::redirect()', $e->getMessage()); + $this->assertEquals('Action SomePagesController::redirect() could not be found.', $e->getMessage()); } } @@ -1155,7 +1157,7 @@ class DispatcherTest extends CakeTestCase { $controller = $Dispatcher->dispatch($url, array('return'=> 1)); $this->fail('No exception.'); } catch (MissingActionException $e) { - $this->assertEquals('MyPluginController::not_here()', $e->getMessage()); + $this->assertEquals('Action MyPluginController::not_here() could not be found.', $e->getMessage()); } Router::reload(); @@ -1167,7 +1169,7 @@ class DispatcherTest extends CakeTestCase { $controller = $Dispatcher->dispatch($url, array('return'=> 1)); $this->fail('No exception.'); } catch (MissingActionException $e) { - $this->assertEquals('MyPluginController::param:value()', $e->getMessage()); + $this->assertEquals('Action MyPluginController::param:value() could not be found.', $e->getMessage()); } } @@ -1190,7 +1192,10 @@ class DispatcherTest extends CakeTestCase { $controller = $Dispatcher->dispatch($url, array('return'=> 1)); $this->fail('No exception.'); } catch (PrivateActionException $e) { - $this->assertEquals('TestDispatchPagesController::admin_index()', $e->getMessage()); + $this->assertEquals( + 'Private Action TestDispatchPagesController::admin_index() is not directly accessible.', + $e->getMessage() + ); } } @@ -1235,7 +1240,7 @@ class DispatcherTest extends CakeTestCase { $controller = $Dispatcher->dispatch($url, array('return'=> 1)); $this->fail('No exception.'); } catch (MissingActionException $e) { - $this->assertEquals('SomePostsController::view()', $e->getMessage()); + $this->assertEquals('Action SomePostsController::view() could not be found.', $e->getMessage()); } $url = 'some_posts/something_else/param:value/param2:value2'; @@ -1274,14 +1279,14 @@ class DispatcherTest extends CakeTestCase { $Dispatcher->dispatch('theme/test_theme/../webroot/css/test_asset.css'); $this->fail('No exception'); } catch (MissingControllerException $e) { - $this->assertEquals('ThemeController', $e->getMessage()); + $this->assertEquals('Controller class ThemeController could not be found.', $e->getMessage()); } try { $Dispatcher->dispatch('theme/test_theme/pdfs'); $this->fail('No exception'); } catch (MissingControllerException $e) { - $this->assertEquals('ThemeController', $e->getMessage()); + $this->assertEquals('Controller class ThemeController could not be found.', $e->getMessage()); } ob_start(); From 5d703c4f503a9f65dfb6ee5cb8d5f8fb57eea4d7 Mon Sep 17 00:00:00 2001 From: mark_story Date: Wed, 8 Sep 2010 00:11:37 -0400 Subject: [PATCH 121/166] Fixing + adding imports for Scaffold. --- cake/libs/controller/scaffold.php | 4 +--- cake/libs/view/theme.php | 1 + cake/tests/cases/libs/controller/scaffold.test.php | 5 +++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/cake/libs/controller/scaffold.php b/cake/libs/controller/scaffold.php index a5c3d7551..a281083db 100644 --- a/cake/libs/controller/scaffold.php +++ b/cake/libs/controller/scaffold.php @@ -462,9 +462,7 @@ class Scaffold { * @package cake * @subpackage cake.cake.libs.controller */ -if (!class_exists('ThemeView')) { - App::import('View', 'Theme'); -} +App::import('View', 'Theme'); /** * ScaffoldView provides specific view file loading features for scaffolded views. diff --git a/cake/libs/view/theme.php b/cake/libs/view/theme.php index 5706f9ba4..834fed182 100644 --- a/cake/libs/view/theme.php +++ b/cake/libs/view/theme.php @@ -17,6 +17,7 @@ * @since CakePHP(tm) v 0.10.0.1076 * @license MIT License (http://www.opensource.org/licenses/mit-license.php) */ +App::import('View', 'View'); /** * Theme view class diff --git a/cake/tests/cases/libs/controller/scaffold.test.php b/cake/tests/cases/libs/controller/scaffold.test.php index 100ed67b8..65de0bb1b 100644 --- a/cake/tests/cases/libs/controller/scaffold.test.php +++ b/cake/tests/cases/libs/controller/scaffold.test.php @@ -17,7 +17,8 @@ * @since CakePHP(tm) v 1.2.0.5436 * @license http://www.opensource.org/licenses/opengroup.php The Open Group Test Suite License */ -App::import('Core', 'Scaffold'); +App::import('Core', 'Scaffold', false); +App::import('Core', 'Controller', false); /** * ScaffoldMockController class @@ -789,7 +790,7 @@ class ScaffoldTest extends CakeTestCase { $this->Controller->theme = 'test_theme'; $this->Controller->view = 'Theme'; $this->Controller->constructClasses(); - $Scaffold =& new TestScaffoldMock($this->Controller, array()); + $Scaffold =& new TestScaffoldMock($this->Controller, $this->Controller->request); $this->assertEqual($this->Controller->view, 'Scaffold'); } From d5bde3fe7a5a66044d4778ccffed0254e2fc87d8 Mon Sep 17 00:00:00 2001 From: mark_story Date: Wed, 8 Sep 2010 22:05:53 -0400 Subject: [PATCH 122/166] Adding a call to session_destroy() to remove the session data. This fixes the issue where data would not be totally destroyed. Fixes #1089 --- cake/libs/cake_session.php | 3 +++ cake/tests/cases/libs/cake_session.test.php | 3 ++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/cake/libs/cake_session.php b/cake/libs/cake_session.php index a854db4d0..22ee0f50f 100644 --- a/cake/libs/cake_session.php +++ b/cake/libs/cake_session.php @@ -454,6 +454,9 @@ class CakeSession extends Object { * @access public */ function destroy() { + if ($this->started()) { + session_destroy(); + } $_SESSION = null; $this->__construct($this->path); $this->start(); diff --git a/cake/tests/cases/libs/cake_session.test.php b/cake/tests/cases/libs/cake_session.test.php index 2c4019d1e..1ef143f67 100644 --- a/cake/tests/cases/libs/cake_session.test.php +++ b/cake/tests/cases/libs/cake_session.test.php @@ -255,7 +255,8 @@ class CakeSessionTest extends CakeTestCase { $this->Session->destroy(); $this->assertFalse($this->Session->check('bulletProof')); $this->assertNotEqual($id, $this->Session->id()); - + $this->assertTrue($this->Session->started()); + $this->Session->cookieLifeTime = 'test'; $this->Session->destroy(); $this->assertNotEqual('test', $this->Session->cookieLifeTime); From b60f65f4207e5d0e7ca0b3ee7ec0365847d09a55 Mon Sep 17 00:00:00 2001 From: mark_story Date: Wed, 8 Sep 2010 22:29:47 -0400 Subject: [PATCH 123/166] Adding a tiny bit of documentation to App::import(). --- cake/libs/configure.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/cake/libs/configure.php b/cake/libs/configure.php index 1428ba896..7166546b8 100644 --- a/cake/libs/configure.php +++ b/cake/libs/configure.php @@ -845,7 +845,8 @@ class App extends Object { } /** - * Finds classes based on $name or specific file(s) to search. + * Finds classes based on $name or specific file(s) to search. Calling App::import() will + * not construct any classes contained in the files. It will only find and require() the file. * * @link http://book.cakephp.org/view/934/Using-App-import * @param mixed $type The type of Class if passed as a string, or all params can be passed as From 12338a0c16751889c2f885877602682350ae3b7c Mon Sep 17 00:00:00 2001 From: mark_story Date: Wed, 8 Sep 2010 22:48:21 -0400 Subject: [PATCH 124/166] Updating instance method calls in AclComponent. --- cake/libs/controller/components/acl.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cake/libs/controller/components/acl.php b/cake/libs/controller/components/acl.php index f5920753f..5fac438d2 100644 --- a/cake/libs/controller/components/acl.php +++ b/cake/libs/controller/components/acl.php @@ -163,7 +163,7 @@ class AclComponent extends Component { */ public function grant($aro, $aco, $action = "*") { trigger_error(__('AclComponent::grant() is deprecated, use allow() instead'), E_USER_WARNING); - return $this->_Instance->grant($aro, $aco, $action); + return $this->_Instance->allow($aro, $aco, $action); } /** @@ -176,7 +176,7 @@ class AclComponent extends Component { */ public function revoke($aro, $aco, $action = "*") { trigger_error(__('AclComponent::revoke() is deprecated, use deny() instead'), E_USER_WARNING); - return $this->_Instance->revoke($aro, $aco, $action); + return $this->_Instance->deny($aro, $aco, $action); } } From d5e906f086edd3e41af0c127a81a23dbf4b8f26d Mon Sep 17 00:00:00 2001 From: mark_story Date: Wed, 8 Sep 2010 22:49:00 -0400 Subject: [PATCH 125/166] Adding deprecation flags. --- cake/libs/controller/components/acl.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/cake/libs/controller/components/acl.php b/cake/libs/controller/components/acl.php index 5fac438d2..6f78cd274 100644 --- a/cake/libs/controller/components/acl.php +++ b/cake/libs/controller/components/acl.php @@ -160,6 +160,7 @@ class AclComponent extends Component { * @param string $aco ACO The controlled object identifier. * @param string $action Action (defaults to *) * @return boolean Success + * @deprecated */ public function grant($aro, $aco, $action = "*") { trigger_error(__('AclComponent::grant() is deprecated, use allow() instead'), E_USER_WARNING); @@ -173,6 +174,7 @@ class AclComponent extends Component { * @param string $aco ACO The controlled object identifier. * @param string $action Action (defaults to *) * @return boolean Success + * @deprecated */ public function revoke($aro, $aco, $action = "*") { trigger_error(__('AclComponent::revoke() is deprecated, use deny() instead'), E_USER_WARNING); From bdb3feb7fd48b16be6f74ad574f77012371e1710 Mon Sep 17 00:00:00 2001 From: mark_story Date: Wed, 8 Sep 2010 23:38:51 -0400 Subject: [PATCH 126/166] Adding stack trace to the console error handler. Updating tests. Changing require to require_once so the test case for ConsoleErrorHandler doesn't blow up in cli. --- cake/console/cake.php | 2 +- cake/console/console_error_handler.php | 2 +- .../tests/cases/console/console_error_handler.test.php | 10 +++++----- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/cake/console/cake.php b/cake/console/cake.php index 1ec1e9088..472987c46 100644 --- a/cake/console/cake.php +++ b/cake/console/cake.php @@ -257,7 +257,7 @@ class ShellDispatcher { $boot = file_exists(ROOT . DS . APP_DIR . DS . 'config' . DS . 'bootstrap.php'); require CORE_PATH . 'cake' . DS . 'bootstrap.php'; - require CORE_PATH . 'cake' . DS . 'console' . DS . 'console_error_handler.php'; + require_once CORE_PATH . 'cake' . DS . 'console' . DS . 'console_error_handler.php'; set_exception_handler(array('ConsoleErrorHandler', 'handleException')); if (!file_exists(APP_PATH . 'config' . DS . 'core.php')) { diff --git a/cake/console/console_error_handler.php b/cake/console/console_error_handler.php index 58ce9527d..91469b89e 100644 --- a/cake/console/console_error_handler.php +++ b/cake/console/console_error_handler.php @@ -105,7 +105,7 @@ class ConsoleErrorHandler extends ErrorHandler { * @return void */ public function _outputMessage($template = null) { - $this->stderr($this->error->getMessage()); + $this->stderr($this->error->getMessage() . "\n" . $this->error->getTraceAsString()); } /** diff --git a/cake/tests/cases/console/console_error_handler.test.php b/cake/tests/cases/console/console_error_handler.test.php index a35083bc6..d6e3b261e 100644 --- a/cake/tests/cases/console/console_error_handler.test.php +++ b/cake/tests/cases/console/console_error_handler.test.php @@ -17,7 +17,7 @@ * @since CakePHP(tm) v 2.0 * @license MIT License (http://www.opensource.org/licenses/mit-license.php) */ -require CAKE . 'console' . DS . 'console_error_handler.php'; +require_once CAKE . 'console' . DS . 'console_error_handler.php'; /** * ConsoleErrorHandler Test case. @@ -45,7 +45,7 @@ class ConsoleErrorHandlerTest extends CakeTestCase { $error = $this->getErrorHandler($exception); $error->expects($this->once())->method('stderr') - ->with('Missing action'); + ->with($this->stringContains('Missing action')); $error->render(); } @@ -60,7 +60,7 @@ class ConsoleErrorHandlerTest extends CakeTestCase { $error = $this->getErrorHandler($exception); $error->expects($this->once())->method('stderr') - ->with('Too many parameters.'); + ->with($this->stringContains('Too many parameters.')); $error->render(); } @@ -75,7 +75,7 @@ class ConsoleErrorHandlerTest extends CakeTestCase { $error = $this->getErrorHandler($exception); $error->expects($this->once())->method('stderr') - ->with('dont use me in cli.'); + ->with($this->stringContains('dont use me in cli.')); $error->render(); } @@ -90,7 +90,7 @@ class ConsoleErrorHandlerTest extends CakeTestCase { $error = $this->getErrorHandler($exception); $error->expects($this->once())->method('stderr') - ->with('dont use me in cli.'); + ->with($this->stringContains('dont use me in cli.')); $error->render(); } From 4a0e34a0d6e23f42bf7e590918a4e640cd909fe2 Mon Sep 17 00:00:00 2001 From: mark_story Date: Thu, 9 Sep 2010 21:31:34 -0400 Subject: [PATCH 127/166] Applying patch from 'jeremyharris' to make RequestHandler::renderAs() accept an array of options that can be used to send a file as a download. Fixes #950 --- .../controller/components/request_handler.php | 8 ++-- .../components/request_handler.test.php | 40 ++++++++++++++++++- 2 files changed, 43 insertions(+), 5 deletions(-) diff --git a/cake/libs/controller/components/request_handler.php b/cake/libs/controller/components/request_handler.php index 6418ab3d5..ebbf4c20a 100644 --- a/cake/libs/controller/components/request_handler.php +++ b/cake/libs/controller/components/request_handler.php @@ -490,16 +490,18 @@ class RequestHandlerComponent extends Component { * * @param object $controller A reference to a controller object * @param string $type Type of response to send (e.g: 'ajax') + * @param array $options Array of options to use * @return void * @see RequestHandlerComponent::setContent() * @see RequestHandlerComponent::respondAs() */ - public function renderAs(&$controller, $type) { - $options = array('charset' => 'UTF-8'); + public function renderAs(&$controller, $type, $options = array()) { + $defaults = array('charset' => 'UTF-8'); if (Configure::read('App.encoding') !== null) { - $options = array('charset' => Configure::read('App.encoding')); + $defaults['charset'] = Configure::read('App.encoding'); } + $options = array_merge($defaults, $options); if ($type == 'ajax') { $controller->layout = $this->ajaxLayout; 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 9b343d945..6e971b93e 100644 --- a/cake/tests/cases/libs/controller/components/request_handler.test.php +++ b/cake/tests/cases/libs/controller/components/request_handler.test.php @@ -319,6 +319,34 @@ class RequestHandlerComponentTest extends CakeTestCase { $this->assertEqual($this->Controller->viewPath, 'request_handler_test' . DS . 'js'); } +/** + * test that attachment headers work with renderAs + * + * @return void + */ + function testRenderAsWithAttachment() { + $this->RequestHandler->request = $this->getMock('CakeRequest'); + $this->RequestHandler->request->expects($this->any()) + ->method('accepts') + ->will($this->returnValue(array('application/xml'))); + + $this->RequestHandler->response = $this->getMock('CakeResponse', array('type', 'download', 'charset')); + $this->RequestHandler->response->expects($this->at(0)) + ->method('type') + ->with('application/xml'); + $this->RequestHandler->response->expects($this->at(1)) + ->method('charset') + ->with('UTF-8'); + $this->RequestHandler->response->expects($this->at(2)) + ->method('download') + ->with('myfile.xml'); + + $this->RequestHandler->renderAs($this->Controller, 'xml', array('attachment' => 'myfile.xml')); + + $expected = 'request_handler_test' . DS . 'xml'; + $this->assertEquals($expected, $this->Controller->viewPath); + } + /** * test that respondAs works as expected. * @@ -344,15 +372,23 @@ class RequestHandlerComponentTest extends CakeTestCase { * @return void */ function testRespondAsWithAttachment() { - $this->RequestHandler = $this->getMock('RequestHandlerComponent', array('_header'), array(&$this->Controller->Components)); + $this->RequestHandler = $this->getMock( + 'RequestHandlerComponent', + array('_header'), + array(&$this->Controller->Components) + ); $this->RequestHandler->response = $this->getMock('CakeResponse', array('type', 'download')); $this->RequestHandler->request = $this->getMock('CakeRequest'); + + $this->RequestHandler->request->expects($this->once()) + ->method('accepts') + ->will($this->returnValue(array('application/xml'))); + $this->RequestHandler->response->expects($this->once())->method('download') ->with('myfile.xml'); $this->RequestHandler->response->expects($this->once())->method('type') ->with('application/xml'); - $result = $this->RequestHandler->respondAs('xml', array('attachment' => 'myfile.xml')); $this->assertTrue($result); } From f8dbeb2b7054562aaa8c667b10f58a7d2f0d658e Mon Sep 17 00:00:00 2001 From: mark_story Date: Thu, 9 Sep 2010 22:02:36 -0400 Subject: [PATCH 128/166] Adding documentation for a new feature. --- .../controller/components/request_handler.php | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/cake/libs/controller/components/request_handler.php b/cake/libs/controller/components/request_handler.php index ebbf4c20a..75d28919b 100644 --- a/cake/libs/controller/components/request_handler.php +++ b/cake/libs/controller/components/request_handler.php @@ -487,6 +487,16 @@ class RequestHandlerComponent extends Component { /** * Sets the layout and template paths for the content type defined by $type. + * + * ### Usage: + * + * Render the response as an 'ajax' response. + * + * `$this->RequestHandler->renderAs($this, 'ajax');` + * + * Render the response as an xml file and force the result as a file download. + * + * `$this->RequestHandler->renderAs($this, 'xml', array('attachment' => 'myfile.xml');` * * @param object $controller A reference to a controller object * @param string $type Type of response to send (e.g: 'ajax') @@ -536,8 +546,8 @@ class RequestHandlerComponent extends Component { } /** - * Sets the response header based on type map index name. If DEBUG is greater than 2, the header - * is not set. + * Sets the response header based on type map index name. This wraps several methods + * available on CakeResponse. It also allows you to use Content-Type aliases. * * @param mixed $type Friendly type name, i.e. 'html' or 'xml', or a full content-type, * like 'application/x-shockwave'. @@ -601,6 +611,7 @@ class RequestHandlerComponent extends Component { * * @param mixed $cType Either a string content type to map, or an array of types. * @return mixed Aliases for the types provided. + * @deprecated Use $this->response->mapType() in your controller instead. */ public function mapType($cType) { return $this->response->mapType($cType); From fbd0741a834a85af14e39365849de708545181f3 Mon Sep 17 00:00:00 2001 From: mark_story Date: Thu, 9 Sep 2010 22:54:22 -0400 Subject: [PATCH 129/166] Making a test more resilient when additional fixtures are loaded. --- cake/tests/cases/console/libs/tasks/model.test.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cake/tests/cases/console/libs/tasks/model.test.php b/cake/tests/cases/console/libs/tasks/model.test.php index 52f086e4c..b81e3f3d8 100644 --- a/cake/tests/cases/console/libs/tasks/model.test.php +++ b/cake/tests/cases/console/libs/tasks/model.test.php @@ -179,7 +179,7 @@ class ModelTaskTest extends CakeTestCase { * @return void */ function testGetNameWithOutOfBoundsOption() { - $this->Task->expects($this->any())->method('in')->will($this->onConsecutiveCalls(10, 1)); + $this->Task->expects($this->any())->method('in')->will($this->onConsecutiveCalls(99, 1)); $this->Task->expects($this->once())->method('err'); $result = $this->Task->getName('test_suite'); From 8625d7b374d3eaa8d39ae0556f5202dcacee0134 Mon Sep 17 00:00:00 2001 From: mark_story Date: Thu, 9 Sep 2010 22:58:34 -0400 Subject: [PATCH 130/166] Making debugger test case pass. --- cake/tests/cases/libs/debugger.test.php | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/cake/tests/cases/libs/debugger.test.php b/cake/tests/cases/libs/debugger.test.php index 3cce32740..ca332bd8c 100644 --- a/cake/tests/cases/libs/debugger.test.php +++ b/cake/tests/cases/libs/debugger.test.php @@ -216,7 +216,9 @@ class DebuggerTest extends CakeTestCase { $Controller->helpers = array('Html', 'Form'); $View = new View($Controller); $result = Debugger::exportVar($View); - $expected = 'ViewView::$base = NULL + $expected = 'View + View::$Helpers = HelperCollection object + View::$base = NULL View::$here = NULL View::$plugin = NULL View::$name = "" @@ -237,7 +239,6 @@ class DebuggerTest extends CakeTestCase { View::$cacheAction = false View::$validationErrors = array View::$hasRendered = false - View::$loaded = array View::$modelScope = false View::$model = NULL View::$association = NULL @@ -246,7 +247,8 @@ class DebuggerTest extends CakeTestCase { View::$modelId = NULL View::$uuids = array View::$output = false - View::$webroot = NULL'; + View::$webroot = NULL + View::$request = NULL'; $result = str_replace(array("\t", "\r\n", "\n"), "", strtolower($result)); $expected = str_replace(array("\t", "\r\n", "\n"), "", strtolower($expected)); $this->assertEqual($result, $expected); From 9ac8d1af1b87d0b807c5d4135fdfdb7fb318d8b8 Mon Sep 17 00:00:00 2001 From: Scott Reeves Date: Fri, 10 Sep 2010 12:49:30 -0400 Subject: [PATCH 131/166] Cleaning up link to 1.3 docs, fixing link to blog tutorial. Fixes #1097 Signed-off-by: mark_story --- cake/libs/view/pages/home.ctp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cake/libs/view/pages/home.ctp b/cake/libs/view/pages/home.ctp index 82d3b8bf6..9b78edb8b 100644 --- a/cake/libs/view/pages/home.ctp +++ b/cake/libs/view/pages/home.ctp @@ -106,7 +106,7 @@ You can also add some CSS styles for your pages at: APP/webroot/css.');

    Html->link( - sprintf('%s%s', __('new', true), __('CakePHP 1.3 Docs', true)), + sprintf('%s %s', __('New', true), __('CakePHP 1.3 Docs', true)), 'http://book.cakephp.org/view/875/x1-3-Collection', array('target' => '_blank', 'escape' => false) ); @@ -116,7 +116,7 @@ You can also add some CSS styles for your pages at: APP/webroot/css.'); Html->link( __('The 15 min Blog Tutorial', true), - 'http://book.cakephp.org/view/219/the-cakephp-blog-tutorial', + 'http://book.cakephp.org/view/1528/Blog', array('target' => '_blank', 'escape' => false) ); ?> From 7c79583caab9a3175344b486823cd7efdf106f7f Mon Sep 17 00:00:00 2001 From: mark_story Date: Sat, 11 Sep 2010 15:44:52 -0400 Subject: [PATCH 132/166] Updating expiry time to be within tolerances of memcached. --- cake/tests/cases/libs/cache/memcache.test.php | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/cake/tests/cases/libs/cache/memcache.test.php b/cake/tests/cases/libs/cache/memcache.test.php index 30b84bb66..907281175 100644 --- a/cake/tests/cases/libs/cache/memcache.test.php +++ b/cake/tests/cases/libs/cache/memcache.test.php @@ -194,7 +194,7 @@ class MemcacheEngineTest extends CakeTestCase { $result = Cache::read('other_test'); $this->assertFalse($result); - Cache::config('memcache', array('duration' => '+31 day')); + Cache::config('memcache', array('duration' => '+30 day')); $data = 'this is a test of the emergency broadcasting system'; $result = Cache::write('long_expiry_test', $data); $this->assertTrue($result); @@ -204,9 +204,6 @@ class MemcacheEngineTest extends CakeTestCase { $expecting = $data; $this->assertEqual($result, $expecting); - $result = Cache::read('long_expiry_test'); - $this->assertTrue($result); - Cache::config('memcache', array('duration' => 3600)); } From 55ecfe029247b9d541c86dea1b603b0f1019adde Mon Sep 17 00:00:00 2001 From: mark_story Date: Sat, 11 Sep 2010 15:48:48 -0400 Subject: [PATCH 133/166] Fixing stupid typo. --- cake/tests/cases/libs/model/datasources/dbo_source.test.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cake/tests/cases/libs/model/datasources/dbo_source.test.php b/cake/tests/cases/libs/model/datasources/dbo_source.test.php index eef348313..9fafa1d12 100644 --- a/cake/tests/cases/libs/model/datasources/dbo_source.test.php +++ b/cake/tests/cases/libs/model/datasources/dbo_source.test.php @@ -4448,7 +4448,7 @@ class DboSourceTest extends CakeTestCase { )); $this->assertEqual($expected, $result); } -˝ + /** * test reading complex virtualFields with subqueries. * From 703344cbae2cd9a8469bcd6524febf576fed154d Mon Sep 17 00:00:00 2001 From: predominant Date: Sun, 12 Sep 2010 17:57:55 +1000 Subject: [PATCH 134/166] Updated version number to 1.3.4 --- cake/VERSION.txt | 3 ++- cake/config/config.php | 2 +- cake/libs/view/pages/home.ctp | 2 +- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/cake/VERSION.txt b/cake/VERSION.txt index 458264c68..5bf937a55 100644 --- a/cake/VERSION.txt +++ b/cake/VERSION.txt @@ -18,5 +18,6 @@ // @license MIT License (http://www.opensource.org/licenses/mit-license.php) // +--------------------------------------------------------------------------------------------+ // //////////////////////////////////////////////////////////////////////////////////////////////////// -1.3.3 +1.3.4 + diff --git a/cake/config/config.php b/cake/config/config.php index 52a713037..3232decac 100644 --- a/cake/config/config.php +++ b/cake/config/config.php @@ -17,4 +17,4 @@ * @since CakePHP(tm) v 1.1.11.4062 * @license MIT License (http://www.opensource.org/licenses/mit-license.php) */ -return $config['Cake.version'] = '1.3.3'; +return $config['Cake.version'] = '1.3.4'; diff --git a/cake/libs/view/pages/home.ctp b/cake/libs/view/pages/home.ctp index 9b78edb8b..d15bcdb95 100644 --- a/cake/libs/view/pages/home.ctp +++ b/cake/libs/view/pages/home.ctp @@ -21,7 +21,7 @@ if (Configure::read() == 0): endif; ?>

    - + 0): Debugger::checkSecurityKeys(); From e9d194822d99ef2031cfe59451f9f9b156015522 Mon Sep 17 00:00:00 2001 From: mark_story Date: Sun, 12 Sep 2010 11:48:09 -0400 Subject: [PATCH 135/166] Adding more tests for SMTP address formatting. Fixes #1100 --- cake/libs/controller/components/email.php | 11 ++++++++--- .../cases/libs/controller/components/email.test.php | 9 +++++++++ 2 files changed, 17 insertions(+), 3 deletions(-) diff --git a/cake/libs/controller/components/email.php b/cake/libs/controller/components/email.php index 53d642b0f..399600402 100755 --- a/cake/libs/controller/components/email.php +++ b/cake/libs/controller/components/email.php @@ -743,9 +743,14 @@ class EmailComponent extends Object{ * @access private */ function _formatAddress($string, $smtp = false) { - $hasAlias = preg_match('/(.+)\s<(.+)>/', $string, $matches); - if ($hasAlias) { - return $this->_strip($matches[1] . ' <' . $matches[2] . '>'); + $hasAlias = preg_match('/((.*)\s)?<(.+)>/', $string, $matches); + if ($smtp && $hasAlias) { + return $this->_strip(' <' . $matches[3] . '>'); + } elseif ($smtp) { + return $this->_strip(' <' . $string . '>'); + } + if ($hasAlias && !empty($matches[2])) { + return $this->_strip($matches[2] . ' <' . $matches[3] . '>'); } return $this->_strip($string); } diff --git a/cake/tests/cases/libs/controller/components/email.test.php b/cake/tests/cases/libs/controller/components/email.test.php index 4684d88df..666dfb381 100755 --- a/cake/tests/cases/libs/controller/components/email.test.php +++ b/cake/tests/cases/libs/controller/components/email.test.php @@ -1178,5 +1178,14 @@ HTMLBLOC; $result = $this->Controller->EmailTest->formatAddress(''); $this->assertEqual($result, ''); + + $result = $this->Controller->EmailTest->formatAddress('email@example.com', true); + $this->assertEqual($result, ' '); + + $result = $this->Controller->EmailTest->formatAddress('', true); + $this->assertEqual($result, ' '); + + $result = $this->Controller->EmailTest->formatAddress('alias name ', true); + $this->assertEqual($result, ' '); } } From 85ccd1f0963486551b77c71f5406524127fc444e Mon Sep 17 00:00:00 2001 From: mark_story Date: Sun, 12 Sep 2010 13:06:49 -0400 Subject: [PATCH 136/166] Fixing skipIf calls so email test runs in a reasonable time frame when there is no local smtp server. --- .../libs/controller/components/email.test.php | 21 ++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/cake/tests/cases/libs/controller/components/email.test.php b/cake/tests/cases/libs/controller/components/email.test.php index 666dfb381..1d43deb3b 100755 --- a/cake/tests/cases/libs/controller/components/email.test.php +++ b/cake/tests/cases/libs/controller/components/email.test.php @@ -260,6 +260,9 @@ class EmailComponentTest extends CakeTestCase { * @return void */ function testSmtpConfig() { + if ($this->skipIf(!@fsockopen('localhost', 25), '%s No SMTP server running on localhost')) { + return; + } $this->Controller->EmailTest->delivery = 'smtp'; $this->Controller->EmailTest->smtpOptions = array(); $this->Controller->EmailTest->send('anything'); @@ -284,6 +287,9 @@ class EmailComponentTest extends CakeTestCase { * @return void */ function testBadSmtpSend() { + if ($this->skipIf(!@fsockopen('localhost', 25), '%s No SMTP server running on localhost')) { + return; + } $this->Controller->EmailTest->smtpOptions['host'] = 'blah'; $this->Controller->EmailTest->delivery = 'smtp'; $this->assertFalse($this->Controller->EmailTest->send('Should not work')); @@ -296,7 +302,7 @@ class EmailComponentTest extends CakeTestCase { * @return void */ function testSmtpSend() { - if (!$this->skipIf(!@fsockopen('localhost', 25), '%s No SMTP server running on localhost')) { + if ($this->skipIf(!@fsockopen('localhost', 25), '%s No SMTP server running on localhost')) { return; } @@ -345,7 +351,7 @@ TEMPDOC; * @return void */ function testSmtpEhlo() { - if (!$this->skipIf(!@fsockopen('localhost', 25), '%s No SMTP server running on localhost')) { + if ($this->skipIf(!@fsockopen('localhost', 25), '%s No SMTP server running on localhost')) { return; } @@ -402,7 +408,7 @@ TEMPDOC; * @return void */ function testSmtpSendMultipleTo() { - if (!$this->skipIf(!@fsockopen('localhost', 25), '%s No SMTP server running on localhost')) { + if ($this->skipIf(!@fsockopen('localhost', 25), '%s No SMTP server running on localhost')) { return; } $this->Controller->EmailTest->reset(); @@ -451,7 +457,9 @@ TEMPDOC; * @return void */ function testAuthenticatedSmtpSend() { - $this->skipIf(!@fsockopen('localhost', 25), '%s No SMTP server running on localhost'); + if ($this->skipIf(!@fsockopen('localhost', 25), '%s No SMTP server running on localhost')) { + return; + } $this->Controller->EmailTest->to = 'postmaster@localhost'; $this->Controller->EmailTest->from = 'noreply@example.com'; @@ -642,7 +650,9 @@ TEXTBLOC; * @return void */ function testSmtpSendSocket() { - $this->skipIf(!@fsockopen('localhost', 25), '%s No SMTP server running on localhost'); + if ($this->skipIf(!@fsockopen('localhost', 25), '%s No SMTP server running on localhost')) { + return; + } $this->Controller->EmailTest->smtpOptions['timeout'] = 10; $socket =& new CakeSocket(array_merge(array('protocol'=>'smtp'), $this->Controller->EmailTest->smtpOptions)); @@ -1037,6 +1047,7 @@ HTMLBLOC; $this->Controller->EmailTest->additionalParams = 'X-additional-header'; $this->Controller->EmailTest->delivery = 'smtp'; $this->Controller->EmailTest->smtpOptions['host'] = 'blah'; + $this->Controller->EmailTest->smtpOptions['timeout'] = 0.5; $this->Controller->EmailTest->attachments = array('attachment1', 'attachment2'); $this->Controller->EmailTest->textMessage = 'This is the body of the message'; $this->Controller->EmailTest->htmlMessage = 'This is the body of the message'; From 6519de3a2e36ab086087d6506cd2e0d089babf10 Mon Sep 17 00:00:00 2001 From: mark_story Date: Sun, 12 Sep 2010 14:05:57 -0400 Subject: [PATCH 137/166] Adding CakeRequest::data() to make reading/writing data similar to CakeSession. Tests added. --- cake/libs/cake_request.php | 48 +++++++++++++--- cake/tests/cases/libs/cake_request.test.php | 62 +++++++++++++++++++++ 2 files changed, 103 insertions(+), 7 deletions(-) diff --git a/cake/libs/cake_request.php b/cake/libs/cake_request.php index 26c769a00..435d5007d 100644 --- a/cake/libs/cake_request.php +++ b/cake/libs/cake_request.php @@ -1,11 +1,6 @@ controller`. + * CakeRequest * * PHP 5 * @@ -24,6 +19,15 @@ */ App::import('Core', 'Set'); +/** + * A class that helps wrap Request information and particulars about a single request. + * Provides methods commonly used to introspect on the request headers and request body. + * + * Has both an Array and Object interface. You can access framework parameters using indexes: + * + * `$request['controller']` or `$request->controller`. + * + */ class CakeRequest implements ArrayAccess { /** * Array of parameters parsed from the url. @@ -105,7 +109,7 @@ class CakeRequest implements ArrayAccess { /** * Constructor * - * @param string $url Url string to use + * @param string $url Trimmed url string to use. Should not contain the application base path. * @param boolean $parseEnvironment Set to false to not auto parse the environment. ie. GET, POST and FILES. * @return void */ @@ -625,6 +629,36 @@ class CakeRequest implements ArrayAccess { return in_array($type, $acceptTypes); } +/** + * Provides a read/write accessor for `$this->data`. Allows you + * to use a syntax similar to `CakeSession` for reading post data. + * + * ## Reading values. + * + * `$request->data('Post.title');` + * + * When reading values you will get `null` for keys/values that do not exist. + * + * ## Writing values + * + * `$request->data('Post.title', 'New post!');` + * + * You can write to any value, even paths/keys that do not exist, and the arrays + * will be created for you. + * + * @param string $name Dot separated name of the value to read/write + * @param mixed $value Value to write to the data array. + * @return mixed Either the value being read, or this so you can chain consecutive writes. + */ + public function data($name) { + $args = func_get_args(); + if (count($args) == 2) { + $this->data = Set::insert($this->data, $name, $args[1]); + return $this; + } + return Set::classicExtract($this->data, $name); + } + /** * Array access read implementation * diff --git a/cake/tests/cases/libs/cake_request.test.php b/cake/tests/cases/libs/cake_request.test.php index 8bded114f..f5fbe8400 100644 --- a/cake/tests/cases/libs/cake_request.test.php +++ b/cake/tests/cases/libs/cake_request.test.php @@ -1,4 +1,25 @@ assertEqual($request->base, $expected); } +/** + * test the data() method reading + * + * @return void + */ + function testDataReading() { + $_POST['data'] = array( + 'Model' => array( + 'field' => 'value' + ) + ); + $request = new CakeRequest('posts/index'); + $result = $request->data('Model'); + $this->assertEquals($_POST['data']['Model'], $result); + + $result = $request->data('Model.imaginary'); + $this->assertNull($result); + } + +/** + * test writing with data() + * + * @return void + */ + function testDataWriting() { + $_POST['data'] = array( + 'Model' => array( + 'field' => 'value' + ) + ); + $request = new CakeRequest('posts/index'); + $result = $request->data('Model.new_value', 'new value'); + $this->assertSame($result, $request, 'Return was not $this'); + + $this->assertEquals($request->data['Model']['new_value'], 'new value'); + + $request->data('Post.title', 'New post')->data('Comment.1.author', 'Mark'); + $this->assertEquals($request->data['Post']['title'], 'New post'); + $this->assertEquals($request->data['Comment']['1']['author'], 'Mark'); + } + /** * backupEnvironment method * From 404e49b37d9b1aaf0c9e9551b0cfb5692d4be40a Mon Sep 17 00:00:00 2001 From: mark_story Date: Sun, 12 Sep 2010 14:08:17 -0400 Subject: [PATCH 138/166] Adding tests for writing falsey values. --- cake/tests/cases/libs/cake_request.test.php | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/cake/tests/cases/libs/cake_request.test.php b/cake/tests/cases/libs/cake_request.test.php index f5fbe8400..550240baa 100644 --- a/cake/tests/cases/libs/cake_request.test.php +++ b/cake/tests/cases/libs/cake_request.test.php @@ -1303,6 +1303,27 @@ class CakeRequestTestCase extends CakeTestCase { $this->assertEquals($request->data['Comment']['1']['author'], 'Mark'); } +/** + * test writing falsey values. + * + * @return void + */ + function testDataWritingFalsey() { + $request = new CakeRequest('posts/index'); + + $request->data('Post.null', null); + $this->assertNull($request->data['Post']['null']); + + $request->data('Post.false', false); + $this->assertFalse($request->data['Post']['false']); + + $request->data('Post.zero', 0); + $this->assertSame(0, $request->data['Post']['zero']); + + $request->data('Post.empty', ''); + $this->assertSame('', $request->data['Post']['empty']); + } + /** * backupEnvironment method * From 578674f0e1b245a46e4f4ea741129d9466cc5d74 Mon Sep 17 00:00:00 2001 From: mark_story Date: Sun, 12 Sep 2010 14:19:36 -0400 Subject: [PATCH 139/166] Reformatting some code in Set::classicExtract test case. --- cake/tests/cases/libs/set.test.php | 56 ++++++++++++++++++------------ 1 file changed, 34 insertions(+), 22 deletions(-) diff --git a/cake/tests/cases/libs/set.test.php b/cake/tests/cases/libs/set.test.php index 5bb6ddcad..fca969150 100644 --- a/cake/tests/cases/libs/set.test.php +++ b/cake/tests/cases/libs/set.test.php @@ -1341,16 +1341,27 @@ class SetTest extends CakeTestCase { $this->assertEquals($result, $expected); $a = array( - array('Article' => array('id' => 1, 'title' => 'Article 1', - 'Comment' => array( - array('id' => 10, 'title' => 'Comment 10'), - array('id' => 11, 'title' => 'Comment 11'), - array('id' => 12, 'title' => 'Comment 12')))), - array('Article' => array('id' => 2, 'title' => 'Article 2', - 'Comment' => array( - array('id' => 13, 'title' => 'Comment 13'), - array('id' => 14, 'title' => 'Comment 14')))), - array('Article' => array('id' => 3, 'title' => 'Article 3'))); + array( + 'Article' => array( + 'id' => 1, 'title' => 'Article 1', + 'Comment' => array( + array('id' => 10, 'title' => 'Comment 10'), + array('id' => 11, 'title' => 'Comment 11'), + array('id' => 12, 'title' => 'Comment 12') + ) + ) + ), + array( + 'Article' => array( + 'id' => 2, 'title' => 'Article 2', + 'Comment' => array( + array('id' => 13, 'title' => 'Comment 13'), + array('id' => 14, 'title' => 'Comment 14') + ) + ) + ), + array('Article' => array('id' => 3, 'title' => 'Article 3')) + ); $result = Set::extract($a, '{n}.Article.Comment.{n}.id'); $expected = array (array(10, 11, 12), array(13, 14), null); @@ -1370,9 +1381,9 @@ class SetTest extends CakeTestCase { $this->assertEquals($result, $expected); $a = array( - 'pages' => array('name' => 'page'), - 'fruites' => array('name' => 'fruit'), - 0 => array('name' => 'zero') + 'pages' => array('name' => 'page'), + 'fruites' => array('name' => 'fruit'), + 0 => array('name' => 'zero') ); $result = Set::extract($a, '{s}.name'); $expected = array('page','fruit'); @@ -1393,7 +1404,7 @@ class SetTest extends CakeTestCase { $expected = array(array('jippi'), array('jippi')); $this->assertEquals($result, $expected); - $result = Set::extract($a,'{\w+}.{\w+}.name'); + $result = Set::extract($a, '{\w+}.{\w+}.name'); $expected = array( array('pages' => 'page'), array('fruites' => 'fruit'), @@ -1402,23 +1413,23 @@ class SetTest extends CakeTestCase { ); $this->assertEquals($result, $expected); - $result = Set::extract($a,'{\d+}.{\w+}.name'); + $result = Set::extract($a, '{\d+}.{\w+}.name'); $expected = array(array('pages' => 'page'), array('fruites' => 'fruit')); $this->assertEquals($result, $expected); - $result = Set::extract($a,'{n}.{\w+}.name'); + $result = Set::extract($a, '{n}.{\w+}.name'); $expected = array(array('pages' => 'page'), array('fruites' => 'fruit')); $this->assertEquals($result, $expected); - $result = Set::extract($a,'{s}.{\d+}.name'); + $result = Set::extract($a, '{s}.{\d+}.name'); $expected = array(array('jippi'), array('jippi')); $this->assertEquals($result, $expected); - $result = Set::extract($a,'{s}'); + $result = Set::extract($a, '{s}'); $expected = array(array(array('name' => 'jippi')), array(array('name' => 'jippi'))); $this->assertEquals($result, $expected); - $result = Set::extract($a,'{[a-z]}'); + $result = Set::extract($a, '{[a-z]}'); $expected = array( 'test' => array(array('name' => 'jippi')), 'dot.test' => array(array('name' => 'jippi')) @@ -1433,14 +1444,15 @@ class SetTest extends CakeTestCase { $a->articles = array( array('Article' => array('id' => 1, 'title' => 'Article 1')), array('Article' => array('id' => 2, 'title' => 'Article 2')), - array('Article' => array('id' => 3, 'title' => 'Article 3'))); + array('Article' => array('id' => 3, 'title' => 'Article 3')) + ); $result = Set::extract($a, 'articles.{n}.Article.id'); - $expected = array( 1, 2, 3 ); + $expected = array(1, 2, 3); $this->assertEquals($result, $expected); $result = Set::extract($a, 'articles.{n}.Article.title'); - $expected = array( 'Article 1', 'Article 2', 'Article 3' ); + $expected = array('Article 1', 'Article 2', 'Article 3'); $this->assertEquals($result, $expected); } From 834c44b3030b86bbacc6357bb7af9c65ed1f3ee5 Mon Sep 17 00:00:00 2001 From: mark_story Date: Mon, 13 Sep 2010 23:06:15 -0400 Subject: [PATCH 140/166] Fixing return value tag. --- cake/libs/cake_request.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cake/libs/cake_request.php b/cake/libs/cake_request.php index 435d5007d..7ff06df2f 100644 --- a/cake/libs/cake_request.php +++ b/cake/libs/cake_request.php @@ -359,7 +359,7 @@ class CakeRequest implements ArrayAccess { * * @param boolean $safe Use safe = false when you think the user might manipulate their HTTP_CLIENT_IP * header. Setting $safe = false will will also look at HTTP_X_FORWARDED_FOR - * @return void + * @return string The client IP. */ public function clientIp($safe = true) { if (!$safe && env('HTTP_X_FORWARDED_FOR') != null) { From c7fb20d13ab62699139b9b549fbdf0c48f2c1bba Mon Sep 17 00:00:00 2001 From: mark_story Date: Mon, 13 Sep 2010 23:09:00 -0400 Subject: [PATCH 141/166] Reformatting doc block indentation. --- cake/libs/cake_response.php | 232 ++++++++++++++++++------------------ 1 file changed, 116 insertions(+), 116 deletions(-) diff --git a/cake/libs/cake_response.php b/cake/libs/cake_response.php index b68aa65d3..96c262754 100644 --- a/cake/libs/cake_response.php +++ b/cake/libs/cake_response.php @@ -23,10 +23,10 @@ class CakeResponse { /** -* Holds HTTP response statuses -* -* @var array -*/ + * Holds HTTP response statuses + * + * @var array + */ protected $_statusCodes = array( 100 => 'Continue', 101 => 'Switching Protocols', @@ -70,10 +70,10 @@ class CakeResponse { ); /** -* Holds known mime type mappings -* -* @var array -*/ + * Holds known mime type mappings + * + * @var array + */ protected $_mimeTypes = array( 'ai' => 'application/postscript', 'bcpio' => 'application/x-bcpio', @@ -263,58 +263,58 @@ class CakeResponse { ); /** -* Protocol header to send to the client -* -* @var string -*/ + * Protocol header to send to the client + * + * @var string + */ protected $_protocol = 'HTTP/1.1'; /** -* Status code to send to the client -* -* @var integer -*/ + * Status code to send to the client + * + * @var integer + */ protected $_status = 200; /** -* Content type to send. This can be an 'extension' that will be transformed using the $_mimetypes array -* or a complete mime-type -* -* @var integer -*/ + * Content type to send. This can be an 'extension' that will be transformed using the $_mimetypes array + * or a complete mime-type + * + * @var integer + */ protected $_contentType = 'text/html'; /** -* Buffer list of headers -* -* @var array -*/ + * Buffer list of headers + * + * @var array + */ protected $_headers = array(); /** -* Buffer string for response message -* -* @var string -*/ + * Buffer string for response message + * + * @var string + */ protected $_body = null; /** -* The charset the response body is encoded with -* -* @var string -*/ + * The charset the response body is encoded with + * + * @var string + */ protected $_charset = 'UTF-8'; /** -* Class constructor -* -* @param array $options list of parameters to setup the response. Possible values are: -* - body: the rensonse text that should be sent to the client -* - status: the HTTP status code to respond with -* - type: a complete mime-type string or an extension mapepd in this class -* - charset: the charset for the response body -* @return void -*/ + * Class constructor + * + * @param array $options list of parameters to setup the response. Possible values are: + * - body: the rensonse text that should be sent to the client + * - status: the HTTP status code to respond with + * - type: a complete mime-type string or an extension mapepd in this class + * - charset: the charset for the response body + * @return void + */ public function __construct(array $options = array()) { if (isset($options['body'])) { $this->body($options['body']); @@ -331,11 +331,11 @@ class CakeResponse { } /** -* Sends the complete response to the client including headers and message body. -* Will echo out the content in the response body. -* -* @return void -*/ + * Sends the complete response to the client including headers and message body. + * Will echo out the content in the response body. + * + * @return void + */ public function send() { if (isset($this->_headers['Location']) && $this->_status === 200) { $this->statusCode(302); @@ -352,12 +352,12 @@ class CakeResponse { } /** -* Sends a header to the client. -* -* @param $name the header name -* @param $value the header value -* @return void -*/ + * Sends a header to the client. + * + * @param $name the header name + * @param $value the header value + * @return void + */ protected function _sendHeader($name, $value = null) { if (is_null($value)) { header($name); @@ -367,42 +367,42 @@ class CakeResponse { } /** -* Sends a content string to the client. -* -* @param $content string to send as response body -* @return void -*/ + * Sends a content string to the client. + * + * @param $content string to send as response body + * @return void + */ protected function _sendContent($content) { echo $content; } /** -* Buffers a header string to be sent -* Returns the complete list of buffered headers -* -* ### Single header -* e.g `header('Location', 'http://example.com');` -* -* ### Multiple headers -* e.g `header(array('Location' => 'http://example.com', 'X-Extra' => 'My header'));` -* -* ### String header -* e.g `header('WWW-Authenticate: Negotiate');` -* -* ### Array of string headers -* e.g `header(array('WWW-Authenticate: Negotiate'), array('Content-type: application/pdf'));` -* -* Multiple calls for setting the same header name will have the same effect as setting the header once -* with the last value sent for it -* e.g `header('WWW-Authenticate: Negotiate'); header('WWW-Authenticate: Not-Negotiate');` -* will have the same effect as only doing `header('WWW-Authenticate: Not-Negotiate');` -* -* @param mixed $header. An array of header strings or a single header string -* - an assotiative array of "header name" => "header value" is also accepted -* - an array of string headers is also accepted -* @param mixed $value. The header value. -* @return array list of headers to be sent -*/ + * Buffers a header string to be sent + * Returns the complete list of buffered headers + * + * ### Single header + * e.g `header('Location', 'http://example.com');` + * + * ### Multiple headers + * e.g `header(array('Location' => 'http://example.com', 'X-Extra' => 'My header'));` + * + * ### String header + * e.g `header('WWW-Authenticate: Negotiate');` + * + * ### Array of string headers + * e.g `header(array('WWW-Authenticate: Negotiate'), array('Content-type: application/pdf'));` + * + * Multiple calls for setting the same header name will have the same effect as setting the header once + * with the last value sent for it + * e.g `header('WWW-Authenticate: Negotiate'); header('WWW-Authenticate: Not-Negotiate');` + * will have the same effect as only doing `header('WWW-Authenticate: Not-Negotiate');` + * + * @param mixed $header. An array of header strings or a single header string + * - an assotiative array of "header name" => "header value" is also accepted + * - an array of string headers is also accepted + * @param mixed $value. The header value. + * @return array list of headers to be sent + */ public function header($header = null, $value = null) { if (is_null($header)) { return $this->_headers; @@ -429,12 +429,12 @@ class CakeResponse { } /** -* Buffers the response message to be sent -* if $content is null the current buffer is returned -* -* @param string $content the string message to be sent -* @return string current message buffer if $content param is passed as null -*/ + * Buffers the response message to be sent + * if $content is null the current buffer is returned + * + * @param string $content the string message to be sent + * @return string current message buffer if $content param is passed as null + */ public function body($content = null) { if (is_null($content)) { return $this->_body; @@ -443,12 +443,12 @@ class CakeResponse { } /** -* Sets the HTTP status code to be sent -* if $code is null the current code is returned -* -* @param integer $code -* @return integer current status code -*/ + * Sets the HTTP status code to be sent + * if $code is null the current code is returned + * + * @param integer $code + * @return integer current status code + */ public function statusCode($code = null) { if (is_null($code)) { return $this->_status; @@ -494,26 +494,26 @@ class CakeResponse { } /** -* Sets the response content type. It can be either a file extension -* which will be mapped internally to a mime-type or a string representing a mime-type -* if $contentType is null the current content type is returned -* if $contentType is an associative array, it will be stored as a content type definition -* -* ### Setting the content type -* e.g `type('jpg');` -* -* ### Returning the current content type -* e.g `type();` -* -* ### Storing a content type definition -* e.g `type(array('keynote' => 'application/keynote'));` -* -* ### Replacing a content type definition -* e.g `type(array('jpg' => 'text/plain'));` -* -* @param string $contentType -* @return mixed current content type or false if supplied an invalid content type -*/ + * Sets the response content type. It can be either a file extension + * which will be mapped internally to a mime-type or a string representing a mime-type + * if $contentType is null the current content type is returned + * if $contentType is an associative array, it will be stored as a content type definition + * + * ### Setting the content type + * e.g `type('jpg');` + * + * ### Returning the current content type + * e.g `type();` + * + * ### Storing a content type definition + * e.g `type(array('keynote' => 'application/keynote'));` + * + * ### Replacing a content type definition + * e.g `type(array('jpg' => 'text/plain'));` + * + * @param string $contentType + * @return mixed current content type or false if supplied an invalid content type + */ public function type($contentType = null) { if (is_null($contentType)) { return $this->_contentType; From 84565151dedbde6787784824b520cb52e6343905 Mon Sep 17 00:00:00 2001 From: mark_story Date: Fri, 10 Sep 2010 23:15:32 -0400 Subject: [PATCH 142/166] Removing all the deprecated properties from Controller. Adding a __get() method to provide the properties that were moved to CakeRequest. Tests added. --- cake/libs/controller/controller.php | 85 ++++++------------- .../cases/libs/controller/controller.test.php | 36 ++++++++ 2 files changed, 61 insertions(+), 60 deletions(-) diff --git a/cake/libs/controller/controller.php b/cake/libs/controller/controller.php index e866c6655..abc5a0b2c 100644 --- a/cake/libs/controller/controller.php +++ b/cake/libs/controller/controller.php @@ -47,29 +47,6 @@ class Controller extends Object { */ public $name = null; -/** - * Stores the current URL, relative to the webroot of the application. - * - * @var string - * @deprecated Will be removed in future versions. Use $this->request->here instead - */ - public $here = null; - -/** - * The webroot of the application. - * - * @var string - * @deprecated Will be removed in future versions. Use $this->request->webroot instead - */ - public $webroot = null; - -/** - * The name of the currently requested controller action. - * - * @var string - */ - public $action = null; - /** * An array containing the class names of models this controller uses. * @@ -94,27 +71,10 @@ class Controller extends Object { */ public $helpers = array('Session', 'Html', 'Form'); -/** - * Parameters received in the current request: GET and POST data, information - * about the request, etc. - * - * @var array - * @link http://book.cakephp.org/view/963/The-Parameters-Attribute-params - * @deprecated Will be removed in future versions. Use $this->request instead - */ - public $params = array(); - -/** - * Data POSTed to the controller using the HtmlHelper. Data here is accessible - * using the `$this->data['ModelName']['fieldName']` pattern. - * - * @var array - * @deprecated Will be removed in future versions. Use $this->request->data instead - */ - public $data = array(); - /** * An instance of a CakeRequest object that contains information about the current request. + * This object contains all the information about a request and several methods for reading + * additional information about the request. * * @var CakeRequest */ @@ -127,7 +87,6 @@ class Controller extends Object { */ public $response; - /** * The classname to use for creating the response object. * @@ -183,14 +142,6 @@ class Controller extends Object { */ public $modelNames = array(); -/** - * Base URL path. - * - * @var string - * @deprecated Will be removed in future versions. Use $this->request->base instead - */ - public $base = null; - /** * The name of the layout file to render the view inside of. The name specified * is the filename of the layout in /app/views/layouts without the .ctp @@ -376,6 +327,27 @@ class Controller extends Object { parent::__construct(); } +/** + * Provides backwards compatbility access to the request object properties. + * Also provides the params alias. + * + * @return void + */ + public function __get($name) { + switch ($name) { + case 'base': + case 'here': + case 'webroot': + case 'data': + return $this->request->{$name}; + case 'action': + return $this->request->params['action']; + case 'params': + return $this->request; + } + return null; + } + /** * Sets the request objects and configures a number of controller properties * based on the contents of the request. @@ -384,20 +356,13 @@ class Controller extends Object { * @return void */ protected function _setRequest(CakeRequest $request) { - $this->base = $request->base; - $this->here = $request->here; - $this->webroot = $request->webroot; + $this->request = $request; $this->plugin = isset($request->params['plugin']) ? $request->params['plugin'] : null; - $this->params = $this->request = $request; - $this->action =& $request->params['action']; + if (isset($request->params['pass']) && isset($request->params['named'])) { $this->passedArgs = array_merge($request->params['pass'], $request->params['named']); } - $this->data = null; - if (!empty($request->params['data'])) { - $this->data =& $request->params['data']; - } if (array_key_exists('return', $request->params) && $request->params['return'] == 1) { $this->autoRender = false; } diff --git a/cake/tests/cases/libs/controller/controller.test.php b/cake/tests/cases/libs/controller/controller.test.php index 1f0d2a765..a72707678 100644 --- a/cake/tests/cases/libs/controller/controller.test.php +++ b/cake/tests/cases/libs/controller/controller.test.php @@ -1499,4 +1499,40 @@ class ControllerTest extends CakeTestCase { $Controller->shutdownProcess(); } + +/** + * test that BC works for attributes on the request object. + * + * @return void + */ + function testPropertyBackwardsCompatibility() { + $request = new CakeRequest('posts/index', null); + $request->addParams(array('controller' => 'posts', 'action' => 'index')); + $request->data = array('Post' => array('id' => 1)); + $request->here = '/posts/index'; + $request->webroot = '/'; + + $Controller = new TestController($request); + $this->assertEquals($request->data, $Controller->data); + $this->assertEquals($request->webroot, $Controller->webroot); + $this->assertEquals($request->here, $Controller->here); + $this->assertEquals($request->action, $Controller->action); + + $this->assertEquals($request, $Controller->params); + $this->assertEquals($request->params['controller'], $Controller->params['controller']); + } + +/** + * test that the BC wrapper doesn't interfere with models and components. + * + * @return void + */ + function testPropertyCompatibilityAndModelsComponents() { + $request = new CakeRequest('controller_posts/index'); + + $Controller = new TestController($request); + $Controller->constructClasses(); + $this->assertType('SecurityComponent', $Controller->Security); + $this->assertType('ControllerComment', $Controller->ControllerComment); + } } From a521291afd0c60dde6ea51d25ce09f7952359093 Mon Sep 17 00:00:00 2001 From: mark_story Date: Fri, 10 Sep 2010 23:37:15 -0400 Subject: [PATCH 143/166] Adding a __set() method to make some tests pass. Updating internal usage to not use deprecated attributes. Updating test cases to not use deprecated attributes. --- cake/libs/controller/controller.php | 28 ++++++++++++++++--- .../cases/libs/controller/controller.test.php | 14 ++++++---- 2 files changed, 33 insertions(+), 9 deletions(-) diff --git a/cake/libs/controller/controller.php b/cake/libs/controller/controller.php index abc5a0b2c..57fcfeeac 100644 --- a/cake/libs/controller/controller.php +++ b/cake/libs/controller/controller.php @@ -348,6 +348,26 @@ class Controller extends Object { return null; } +/** + * Provides backwards compatiblity access for setting values to the request object. + * + * @return void + */ + public function __set($name, $value) { + switch ($name) { + case 'base': + case 'here': + case 'webroot': + case 'data': + return $this->request->{$name} = $value; + case 'action': + return $this->request->params['action'] = $value; + case 'params': + return $this->request->params = $value; + } + return $this->{$name} = $value; + } + /** * Sets the request objects and configures a number of controller properties * based on the contents of the request. @@ -716,7 +736,7 @@ class Controller extends Object { * @return mixed Returns the return value of the called action */ public function setAction($action) { - $this->action = $action; + $this->request->action = $action; $args = func_get_args(); unset($args[0]); return call_user_func_array(array(&$this, $action), $args); @@ -798,7 +818,7 @@ class Controller extends Object { App::import('View', $this->view); } - $this->params['models'] = $this->modelNames; + $this->request->params['models'] = $this->modelNames; $View = new $viewClass($this); @@ -899,8 +919,8 @@ class Controller extends Object { */ public function postConditions($data = array(), $op = null, $bool = 'AND', $exclusive = false) { if (!is_array($data) || empty($data)) { - if (!empty($this->data)) { - $data = $this->data; + if (!empty($this->request->data)) { + $data = $this->request->data; } else { return null; } diff --git a/cake/tests/cases/libs/controller/controller.test.php b/cake/tests/cases/libs/controller/controller.test.php index a72707678..5ad875016 100644 --- a/cake/tests/cases/libs/controller/controller.test.php +++ b/cake/tests/cases/libs/controller/controller.test.php @@ -345,8 +345,10 @@ class TestController extends AppController { * @return void */ function index($testId, $test2Id) { - $this->data['testId'] = $testId; - $this->data['test2Id'] = $test2Id; + $this->data = array( + 'testId' => $testId, + 'test2Id' => $test2Id + ); } } @@ -880,8 +882,10 @@ class ControllerTest extends CakeTestCase { $expected = str_replace(array("\t", "\r\n", "\n"), "", $expected); $this->assertEqual($result, $expected); - App::build(array('views' => array(TEST_CAKE_CORE_INCLUDE_PATH . 'tests' . DS . 'test_app' . DS . 'views'. DS))); - $Controller = new Controller(null); + App::build(array( + 'views' => array(TEST_CAKE_CORE_INCLUDE_PATH . 'tests' . DS . 'test_app' . DS . 'views'. DS) + )); + $Controller = new Controller($request); $Controller->response = $this->getMock('CakeResponse', array('_sendHeader')); $Controller->flash('this should work', '/flash', 1, 'ajax2'); $result = $Controller->response->body(); @@ -979,7 +983,7 @@ class ControllerTest extends CakeTestCase { $core[0] ) ), true); - $Controller =& new Controller(null, $this->getMock('CakeResponse')); + $Controller =& new Controller($this->getMock('CakeRequest')); $Controller->uses = array(); $Controller->components = array('Test'); $Controller->constructClasses(); From 634cea24ebfe3e59d060e38cf1dc2d2fe34d95e1 Mon Sep 17 00:00:00 2001 From: mark_story Date: Fri, 10 Sep 2010 23:38:15 -0400 Subject: [PATCH 144/166] Adding 'action' into View::__get() to make an integration test pass. --- cake/libs/view/view.php | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/cake/libs/view/view.php b/cake/libs/view/view.php index be32b3a20..741d6d461 100644 --- a/cake/libs/view/view.php +++ b/cake/libs/view/view.php @@ -276,7 +276,7 @@ class View extends Object { * @access protected */ private $__passedVars = array( - 'viewVars', 'action', 'autoLayout', 'autoRender', 'ext', 'base', 'webroot', + 'viewVars', 'autoLayout', 'autoRender', 'ext', 'base', 'webroot', 'helpers', 'here', 'layout', 'name', 'layoutPath', 'viewPath', 'params', 'request', 'data', 'plugin', 'passedArgs', 'cacheAction' ); @@ -653,6 +653,10 @@ class View extends Object { if (isset($this->Helpers->{$name})) { return $this->Helpers->{$name}; } + switch ($name) { + case 'action': + return $this->request->params['action']; + } return null; } From e4b2fb173bc665fda2b46dc3808c74f62ebf14d6 Mon Sep 17 00:00:00 2001 From: mark_story Date: Fri, 10 Sep 2010 23:55:42 -0400 Subject: [PATCH 145/166] Removing the deprecated properties. Removing property copying to helpers. Making the view test cases pass again. --- cake/libs/controller/controller.php | 2 +- cake/libs/view/helper_collection.php | 2 +- cake/libs/view/view.php | 71 +++++++++--------------- cake/tests/cases/libs/view/view.test.php | 7 +-- 4 files changed, 30 insertions(+), 52 deletions(-) diff --git a/cake/libs/controller/controller.php b/cake/libs/controller/controller.php index 57fcfeeac..0b2e55c35 100644 --- a/cake/libs/controller/controller.php +++ b/cake/libs/controller/controller.php @@ -341,7 +341,7 @@ class Controller extends Object { case 'data': return $this->request->{$name}; case 'action': - return $this->request->params['action']; + return isset($this->request->params['action']) ? $this->request->params['action'] : ''; case 'params': return $this->request; } diff --git a/cake/libs/view/helper_collection.php b/cake/libs/view/helper_collection.php index faa63b14a..27f9d00bb 100644 --- a/cake/libs/view/helper_collection.php +++ b/cake/libs/view/helper_collection.php @@ -68,7 +68,7 @@ class HelperCollection extends ObjectCollection { } $this->_loaded[$name] = new $helperClass($this->_View, $settings); - $vars = array('request', 'base', 'webroot', 'here', 'params', 'action', 'data', 'theme', 'plugin'); + $vars = array('request', 'theme', 'plugin'); foreach ($vars as $var) { $this->_loaded[$name]->{$var} = $this->_View->{$var}; } diff --git a/cake/libs/view/view.php b/cake/libs/view/view.php index 741d6d461..0876238aa 100644 --- a/cake/libs/view/view.php +++ b/cake/libs/view/view.php @@ -42,21 +42,6 @@ class View extends Object { */ public $Helpers; -/** - * Path parts for creating links in views. - * - * @var string Base URL - * @access public - */ - public $base = null; - -/** - * Stores the current URL (for links etc.) - * - * @var string Current URL - */ - public $here = null; - /** * Name of the plugin. * @@ -73,21 +58,6 @@ class View extends Object { */ public $name = null; -/** - * Action to be performed. - * - * @var string Name of action - * @access public - */ - public $action = null; - -/** - * Array of parameter data - * - * @var array Parameter data - */ - public $params = array(); - /** * Current passed params * @@ -95,13 +65,6 @@ class View extends Object { */ public $passedArgs = array(); -/** - * Array of data - * - * @var array Parameter data - */ - public $data = array(); - /** * An array of names of built-in helpers to include. * @@ -269,6 +232,15 @@ class View extends Object { */ public $output = false; +/** + * An instance of a CakeRequest object that contains information about the current request. + * This object contains all the information about a request and several methods for reading + * additional information about the request. + * + * @var CakeRequest + */ + public $request; + /** * List of variables to collect from the associated controller * @@ -276,9 +248,8 @@ class View extends Object { * @access protected */ private $__passedVars = array( - 'viewVars', 'autoLayout', 'autoRender', 'ext', 'base', 'webroot', - 'helpers', 'here', 'layout', 'name', 'layoutPath', 'viewPath', - 'params', 'request', 'data', 'plugin', 'passedArgs', 'cacheAction' + 'viewVars', 'autoLayout', 'autoRender', 'ext', 'helpers', 'layout', 'name', + 'layoutPath', 'viewPath', 'request', 'plugin', 'passedArgs', 'cacheAction' ); /** @@ -645,17 +616,25 @@ class View extends Object { } /** - * Magic accessor for helpers. + * Magic accessor for helpers. Provides access to attributes that were deprecated. * - * @return void + * @param string $name Name of the attribute to get. + * @return mixed */ public function __get($name) { if (isset($this->Helpers->{$name})) { return $this->Helpers->{$name}; } switch ($name) { + case 'base': + case 'here': + case 'webroot': + case 'data': + return $this->request->{$name}; case 'action': - return $this->request->params['action']; + return isset($this->request->params['action']) ? $this->request->params['action'] : ''; + case 'params': + return $this->request; } return null; } @@ -712,10 +691,10 @@ class View extends Object { if ($caching) { if (isset($this->Helpers->Cache)) { $cache =& $this->Helpers->Cache; - $cache->base = $this->base; - $cache->here = $this->here; + $cache->base = $this->request->base; + $cache->here = $this->request->here; $cache->helpers = $this->helpers; - $cache->action = $this->action; + $cache->action = $this->request->action; $cache->controllerName = $this->name; $cache->layout = $this->layout; $cache->cacheAction = $this->cacheAction; diff --git a/cake/tests/cases/libs/view/view.test.php b/cake/tests/cases/libs/view/view.test.php index 8faf32dee..2466f5228 100644 --- a/cake/tests/cases/libs/view/view.test.php +++ b/cake/tests/cases/libs/view/view.test.php @@ -19,10 +19,8 @@ */ App::import('Core', array('View', 'Controller')); App::import('Helper', 'Cache'); +App::import('Core', array('ErrorHandler')); -if (!class_exists('ErrorHandler')) { - App::import('Core', array('Error')); -} /** * ViewPostsController class @@ -227,8 +225,9 @@ class ViewTest extends CakeTestCase { */ function setUp() { Router::reload(); - $this->Controller = new Controller(); + $request = $this->getMock('CakeRequest'); + $this->Controller = new Controller($request); $this->PostsController = new ViewPostsController($request); $this->PostsController->viewPath = 'posts'; $this->PostsController->index(); From 003d02d8d9e86660766f4bc33d6402cb7f215d20 Mon Sep 17 00:00:00 2001 From: mark_story Date: Sat, 11 Sep 2010 18:56:35 -0400 Subject: [PATCH 146/166] Making view test pass by moving property assignment on mock. --- cake/tests/cases/libs/view/view.test.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cake/tests/cases/libs/view/view.test.php b/cake/tests/cases/libs/view/view.test.php index 2466f5228..9972d1dcd 100644 --- a/cake/tests/cases/libs/view/view.test.php +++ b/cake/tests/cases/libs/view/view.test.php @@ -680,7 +680,7 @@ class ViewTest extends CakeTestCase { $this->PostsController->helpers = array('Session', 'Cache', 'Html'); $this->PostsController->constructClasses(); $this->PostsController->cacheAction = array('index' => 3600); - $this->PostsController->params['action'] = 'index'; + $this->PostsController->request->params['action'] = 'index'; Configure::write('Cache.check', true); $View = new TestView($this->PostsController); From 2906927a16627124f068c748aa91d62d1c89148d Mon Sep 17 00:00:00 2001 From: mark_story Date: Sun, 12 Sep 2010 00:24:37 -0400 Subject: [PATCH 147/166] Adding BC wrappers for helpers. Updating paginator test case to use non deprecated properties. --- cake/libs/view/helper.php | 79 +++++++------------ .../libs/view/helpers/paginator.test.php | 4 +- 2 files changed, 32 insertions(+), 51 deletions(-) diff --git a/cake/libs/view/helper.php b/cake/libs/view/helper.php index 94f880a12..dbc6f4dfe 100644 --- a/cake/libs/view/helper.php +++ b/cake/libs/view/helper.php @@ -47,22 +47,6 @@ class Helper extends Object { */ protected $_helperMap = array(); -/** - * Base URL - * - * @deprecated use $request->base instead - * @var string - */ - public $base = null; - -/** - * Webroot path - * - * @deprecated use $request->webroot instead - * @var string - */ - public $webroot = null; - /** * The current theme name if any. * @@ -70,22 +54,6 @@ class Helper extends Object { */ public $theme = null; -/** - * URL to current action. - * - * @deprecated use $request->here instead - * @var string - */ - public $here = null; - -/** - * Parameter array. - * - * @deprecated use $request instead - * @var array - */ - public $params = array(); - /** * Request object * @@ -93,14 +61,6 @@ class Helper extends Object { */ public $request = null; -/** - * Current action. - * - * @deprecated use $request->action instead - * @var string - */ - public $action = null; - /** * Plugin path * @@ -108,14 +68,6 @@ class Helper extends Object { */ public $plugin = null; -/** - * POST data for models - * - * @deprecated use $request->data instead - * @var array - */ - public $data = null; - /** * Contains model validation errors of form post-backs * @@ -181,7 +133,7 @@ class Helper extends Object { } /** - * Lazy loads helpers + * Lazy loads helpers. Provides access to deprecated request properties as well. * * @param string $name Name of the property being accessed. * @return mixed Helper or property found at $name @@ -195,6 +147,35 @@ class Helper extends Object { if (isset($this->{$name})) { return $this->{$name}; } + switch ($name) { + case 'base': + case 'here': + case 'webroot': + case 'data': + return $this->request->{$name}; + case 'action': + return isset($this->request->params['action']) ? $this->request->params['action'] : ''; + case 'params': + return $this->request; + } + } + +/** + * Provides backwards compatiblity access for setting values to the request object. + * + * @return void + */ + public function __set($name, $value) { + switch ($name) { + case 'base': + case 'here': + case 'webroot': + case 'data': + return $this->request->{$name} = $value; + case 'action': + return $this->request->params['action'] = $value; + } + return $this->{$name} = $value; } /** diff --git a/cake/tests/cases/libs/view/helpers/paginator.test.php b/cake/tests/cases/libs/view/helpers/paginator.test.php index b92cd533f..52f651196 100644 --- a/cake/tests/cases/libs/view/helpers/paginator.test.php +++ b/cake/tests/cases/libs/view/helpers/paginator.test.php @@ -212,8 +212,8 @@ class PaginatorHelperTest extends CakeTestCase { $result = $this->Paginator->sort('Title', 'title', array('direction' => 'desc')); $this->assertPattern('/\/accounts\/index\/param\/page:1\/sort:title\/direction:desc" class="asc">Title<\/a>$/', $result); - $this->Paginator->params['paging']['Article']['options']['order'] = array('Article.title' => 'asc'); - $this->Paginator->params['paging']['Article']['options']['sort'] = null; + $this->Paginator->request->params['paging']['Article']['options']['order'] = array('Article.title' => 'asc'); + $this->Paginator->request->params['paging']['Article']['options']['sort'] = null; $result = $this->Paginator->sort('Title', 'title', array('direction' => 'desc', 'class' => 'foo')); $this->assertPattern('/\/accounts\/index\/param\/page:1\/sort:title\/direction:desc" class="foo asc">Title<\/a>$/', $result); } From 97dd7c76448184edf71ecda5a91c8904dd1c8046 Mon Sep 17 00:00:00 2001 From: mark_story Date: Tue, 14 Sep 2010 21:57:40 -0400 Subject: [PATCH 148/166] Adding support to ObjectCollection and its subclasses to trigger callbacks on all objects instead of just the enabled ones. Fixes issues where inner components would not get access to the controller as the initialize callback wasn't fired. This fixes some backwards compatibility issues. Tests updated. --- cake/libs/controller/controller.php | 2 +- cake/libs/object_collection.php | 8 ++++++- .../controller/component_collection.test.php | 21 +++++++++++++++++++ .../cases/libs/controller/controller.test.php | 2 +- 4 files changed, 30 insertions(+), 3 deletions(-) diff --git a/cake/libs/controller/controller.php b/cake/libs/controller/controller.php index 0b2e55c35..07e0b8f59 100644 --- a/cake/libs/controller/controller.php +++ b/cake/libs/controller/controller.php @@ -533,7 +533,7 @@ class Controller extends Object { * @return void */ public function startupProcess() { - $this->Components->trigger('initialize', array(&$this)); + $this->Components->trigger('initialize', array(&$this), array('triggerDisabled' => true)); $this->beforeFilter(); $this->Components->trigger('startup', array(&$this)); } diff --git a/cake/libs/object_collection.php b/cake/libs/object_collection.php index 01f1efeda..cca7ec58f 100644 --- a/cake/libs/object_collection.php +++ b/cake/libs/object_collection.php @@ -57,6 +57,8 @@ abstract class ObjectCollection { * - `break` Set to true to enabled breaking. Defaults to `false`. * - `collectReturn` Set to true to collect the return of each object into an array. * This array of return values will be returned from the trigger() call. Defaults to `false`. + * - `triggerDisabled` Will trigger the callback on all objects in the collection even the non-enabled + * objects. Defaults to false. * * @param string $callback Method to fire on all the objects. Its assumed all the objects implement * the method you are calling. @@ -69,10 +71,14 @@ abstract class ObjectCollection { return true; } $options = array_merge( - array('break' => false, 'breakOn' => false, 'collectReturn' => false), + array('break' => false, 'breakOn' => false, 'collectReturn' => false, 'triggerDisabled' => false), $options ); $collected = array(); + $list = $this->_enabled; + if ($options['triggerDisabled'] === true) { + $list = array_keys($this->_loaded); + } foreach ($this->_enabled as $name) { $result = call_user_func_array(array(&$this->_loaded[$name], $callback), $params); if ($options['collectReturn'] === true) { diff --git a/cake/tests/cases/libs/controller/component_collection.test.php b/cake/tests/cases/libs/controller/component_collection.test.php index a44e33e63..ccaacbc99 100644 --- a/cake/tests/cases/libs/controller/component_collection.test.php +++ b/cake/tests/cases/libs/controller/component_collection.test.php @@ -149,6 +149,27 @@ class ComponentCollectionTest extends CakeTestCase { $this->assertTrue($this->Components->trigger('startup', array(&$controller))); } +/** + * test that the initalize callback is triggered on all components even those that are disabled. + * + * @return void + */ + function testTriggerOnDisabledObjects() { + $controller = 'Not a controller'; + + $this->_makeMockClasses(); + $this->Components->load('TriggerMockCookie', array(), false); + $this->Components->load('TriggerMockSecurity'); + + $this->Components->TriggerMockCookie->expects($this->once())->method('initalize') + ->with($controller); + $this->Components->TriggerMockSecurity->expects($this->once())->method('initalize') + ->with($controller); + + $result = $this->Components->trigger('initialize', array(&$controller), array('triggerDisabled' => true)); + $this->assertTrue($result); + } + /** * test trigger and disabled helpers. * diff --git a/cake/tests/cases/libs/controller/controller.test.php b/cake/tests/cases/libs/controller/controller.test.php index 5ad875016..20eb72642 100644 --- a/cake/tests/cases/libs/controller/controller.test.php +++ b/cake/tests/cases/libs/controller/controller.test.php @@ -1478,7 +1478,7 @@ class ControllerTest extends CakeTestCase { $Controller->expects($this->once())->method('beforeFilter'); $Controller->Components->expects($this->at(0))->method('trigger') - ->with('initialize', array(&$Controller)); + ->with('initialize', array(&$Controller), array('triggerDisabled' => true)); $Controller->Components->expects($this->at(1))->method('trigger') ->with('startup', array(&$Controller)); From 0baaf6801b9633ac62a0b8f5171ac02f8bcd4af3 Mon Sep 17 00:00:00 2001 From: mark_story Date: Tue, 14 Sep 2010 22:12:14 -0400 Subject: [PATCH 149/166] Removing call to RequestHandler as its just a pass through to the request object which is available in that scope. Updating the test cases to not use deprecated and non-existent things. --- cake/libs/controller/components/auth.php | 2 +- .../libs/controller/components/auth.test.php | 42 +++++++++++++------ 2 files changed, 30 insertions(+), 14 deletions(-) diff --git a/cake/libs/controller/components/auth.php b/cake/libs/controller/components/auth.php index 0cebd05ef..2dd5674a5 100644 --- a/cake/libs/controller/components/auth.php +++ b/cake/libs/controller/components/auth.php @@ -377,7 +377,7 @@ class AuthComponent extends Component { return false; } else { if (!$this->user()) { - if (!$this->RequestHandler->isAjax()) { + if (!$request->is('ajax')) { $this->Session->setFlash($this->authError, $this->flashElement, array(), 'auth'); if (!empty($request->query) && count($request->query) >= 2) { $query = $request->query; diff --git a/cake/tests/cases/libs/controller/components/auth.test.php b/cake/tests/cases/libs/controller/components/auth.test.php index 4ab4aece7..275c1e884 100644 --- a/cake/tests/cases/libs/controller/components/auth.test.php +++ b/cake/tests/cases/libs/controller/components/auth.test.php @@ -17,6 +17,7 @@ * @since CakePHP(tm) v 1.2.0.5347 * @license http://www.opensource.org/licenses/opengroup.php The Open Group Test Suite License */ +App::import('Core', 'Controller'); App::import('Component', array('Auth', 'Acl')); App::import('Model', 'DbAcl'); App::import('Core', 'Xml'); @@ -493,8 +494,10 @@ class AuthTest extends CakeTestCase { $request = new CakeRequest(null, false); $this->Controller = new AuthTestController($request); - $this->Controller->Component->init($this->Controller); - $this->Controller->Component->initialize($this->Controller); + $this->Controller->Components->init($this->Controller); + $this->Controller->Components->trigger( + 'initialize', array(&$this->Controller), array('triggerDisabled' => true) + ); $this->Controller->beforeFilter(); ClassRegistry::addObject('view', new View($this->Controller)); @@ -641,7 +644,6 @@ class AuthTest extends CakeTestCase { * @return void */ function testLoginActionNotSettingAuthRedirect() { - $_referer = $_SERVER['HTTP_REFERER']; $_SERVER['HTTP_REFERER'] = '/pages/display/about'; $this->Controller->data = array(); @@ -1065,7 +1067,9 @@ class AuthTest extends CakeTestCase { ); $this->Controller->Session->delete('Auth'); $url = '/posts/index/29'; - $this->Controller->request = Dispatcher::parseParams(new CakeRequest($url)); + $this->Controller->request = new CakeRequest($url); + $this->Controller->request->addParams(Router::parse($url)); + $this->Controller->Auth->initialize($this->Controller); $this->Controller->Auth->loginAction = array('controller' => 'AuthTest', 'action' => 'login'); $this->Controller->Auth->userModel = 'AuthUser'; @@ -1081,7 +1085,9 @@ class AuthTest extends CakeTestCase { ); $this->Controller->Session->delete('Auth'); $url = '/posts/index/29'; - $this->Controller->request = Dispatcher::parseParams(new CakeRequest($url)); + $this->Controller->request = new CakeRequest($url); + $this->Controller->request->addParams(Router::parse($url)); + $this->Controller->Auth->initialize($this->Controller); $this->Controller->Auth->loginAction = array('controller' => 'AuthTest', 'action' => 'login'); $this->Controller->Auth->userModel = 'AuthUser'; @@ -1094,6 +1100,7 @@ class AuthTest extends CakeTestCase { $_SERVER['HTTP_REFERER'] = 'http://webmail.example.com/view/message'; $this->Controller->Session->delete('Auth'); $url = '/posts/edit/1'; + $this->Controller->request = new CakeRequest($url); $this->Controller->request->addParams(Router::parse($url)); $this->Controller->request->query = array('url' => Router::normalize($url)); $this->Controller->Auth->initialize($this->Controller); @@ -1107,6 +1114,7 @@ class AuthTest extends CakeTestCase { $_SERVER['HTTP_REFERER'] = 'http://webmail.example.com/view/message'; $this->Controller->Session->delete('Auth'); $url = '/AuthTest/login'; + $this->Controller->request = new CakeRequest($url); $this->Controller->request->addParams(Router::parse($url)); $this->Controller->request->query['url'] = Router::normalize($url); $this->Controller->Auth->initialize($this->Controller); @@ -1192,8 +1200,12 @@ class AuthTest extends CakeTestCase { $this->Controller->Session->delete($this->Controller->Auth->sessionKey); - $this->Controller->data['AuthUser']['username'] = 'nate'; - $this->Controller->data['AuthUser']['password'] = 'cake1'; + $this->Controller->request->data = array( + 'AuthUser' => array( + 'username' => 'nate', + 'password' => 'cake1' + ) + ); $this->Controller->request->query['url'] = 'auth_test/login'; $this->Controller->Auth->initialize($this->Controller); @@ -1204,22 +1216,26 @@ class AuthTest extends CakeTestCase { $this->Controller->Session->delete($this->Controller->Auth->sessionKey); - $this->Controller->data['AuthUser']['username'] = '> n'; - $this->Controller->data['AuthUser']['password'] = 'cake'; + $this->Controller->request->data = array( + 'AuthUser' => array( + 'username' => '> n', + 'password' => 'cake' + ) + ); $this->Controller->Auth->initialize($this->Controller); $this->Controller->Auth->startup($this->Controller); $this->assertTrue(is_null($this->Controller->Auth->user())); - unset($this->Controller->data['AuthUser']['password']); - $this->Controller->data['AuthUser']['username'] = "1'1"; + unset($this->Controller->request->data['AuthUser']['password']); + $this->Controller->request->data['AuthUser']['username'] = "1'1"; $this->Controller->Auth->initialize($this->Controller); $this->Controller->Auth->startup($this->Controller); $this->assertTrue(is_null($this->Controller->Auth->user())); - unset($this->Controller->data['AuthUser']['username']); - $this->Controller->data['AuthUser']['password'] = "1'1"; + unset($this->Controller->request->data['AuthUser']['username']); + $this->Controller->request->data['AuthUser']['password'] = "1'1"; $this->Controller->Auth->initialize($this->Controller); $this->Controller->Auth->startup($this->Controller); From 8e97a5ee2d616753eaf920c9ae3b14c0eba77153 Mon Sep 17 00:00:00 2001 From: mark_story Date: Tue, 14 Sep 2010 22:20:30 -0400 Subject: [PATCH 150/166] Fixing failing tests caused by missing index in Security component testcase. --- cake/tests/cases/libs/controller/components/security.test.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/cake/tests/cases/libs/controller/components/security.test.php b/cake/tests/cases/libs/controller/components/security.test.php index 7cef73fc1..fd6767950 100644 --- a/cake/tests/cases/libs/controller/components/security.test.php +++ b/cake/tests/cases/libs/controller/components/security.test.php @@ -144,7 +144,9 @@ class SecurityComponentTest extends CakeTestCase { * @return void */ function startTest() { - $this->Controller = new SecurityTestController(new CakeRequest(null, false)); + $request = new CakeRequest('posts/index', false); + $request->addParams(array('controller' => 'posts', 'action' => 'index')); + $this->Controller = new SecurityTestController($request); $this->Controller->Components->init($this->Controller); $this->Controller->Security = $this->Controller->TestSecurity; $this->Controller->Security->blackHoleCallback = 'fail'; From 5d697b9d6ef8320d9e440670ba0abaca90fdd0d5 Mon Sep 17 00:00:00 2001 From: mark_story Date: Tue, 14 Sep 2010 22:39:05 -0400 Subject: [PATCH 151/166] Fixing tests where objects were not added to the mockObjects lists, making their expects() not count. --- cake/tests/cases/libs/view/helper_collection.test.php | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/cake/tests/cases/libs/view/helper_collection.test.php b/cake/tests/cases/libs/view/helper_collection.test.php index c08237e0c..e0b586e2a 100644 --- a/cake/tests/cases/libs/view/helper_collection.test.php +++ b/cake/tests/cases/libs/view/helper_collection.test.php @@ -129,10 +129,12 @@ class HelperCollectionTest extends CakeTestCase { $this->Helpers->load('TriggerMockHtml'); $this->Helpers->load('TriggerMockForm'); - $this->Helpers->TriggerMockForm->expects($this->once())->method('beforeRender') + $this->Helpers->TriggerMockHtml->expects($this->once())->method('beforeRender') ->with('one', 'two'); $this->Helpers->TriggerMockForm->expects($this->once())->method('beforeRender') ->with('one', 'two'); + + $this->mockObjects[] = $this->Helpers->TriggerMockForm; $this->assertTrue($this->Helpers->trigger('beforeRender', array('one', 'two'))); } @@ -155,6 +157,9 @@ class HelperCollectionTest extends CakeTestCase { ->with('one', 'two'); $this->Helpers->TriggerMockForm->expects($this->never())->method('beforeRender'); + $this->mockObjects[] = $this->Helpers->TriggerMockForm; + $this->mockObjects[] = $this->Helpers->TriggerMockHtml; + $this->Helpers->disable('TriggerMockForm'); $this->assertTrue($this->Helpers->trigger('beforeRender', array('one', 'two'))); From 7a14d3a8f206a11166e987add51833e7ec709ee9 Mon Sep 17 00:00:00 2001 From: mark_story Date: Tue, 14 Sep 2010 22:40:46 -0400 Subject: [PATCH 152/166] Fixing issue where mockObject expectations were not counted hiding fails. Fixing all objects not actually being iterated. --- cake/libs/object_collection.php | 2 +- .../controller/component_collection.test.php | 27 ++++++++++++++----- 2 files changed, 22 insertions(+), 7 deletions(-) diff --git a/cake/libs/object_collection.php b/cake/libs/object_collection.php index cca7ec58f..26947641b 100644 --- a/cake/libs/object_collection.php +++ b/cake/libs/object_collection.php @@ -79,7 +79,7 @@ abstract class ObjectCollection { if ($options['triggerDisabled'] === true) { $list = array_keys($this->_loaded); } - foreach ($this->_enabled as $name) { + foreach ($list as $name) { $result = call_user_func_array(array(&$this->_loaded[$name], $callback), $params); if ($options['collectReturn'] === true) { $collected[] = $result; diff --git a/cake/tests/cases/libs/controller/component_collection.test.php b/cake/tests/cases/libs/controller/component_collection.test.php index ccaacbc99..6d4eabb22 100644 --- a/cake/tests/cases/libs/controller/component_collection.test.php +++ b/cake/tests/cases/libs/controller/component_collection.test.php @@ -18,6 +18,7 @@ * @license MIT License (http://www.opensource.org/licenses/mit-license.php) */ +App::import('Component', array('Cookie', 'Security')); App::import('Core', 'ComponentCollection'); class ComponentCollectionTest extends CakeTestCase { @@ -145,6 +146,9 @@ class ComponentCollectionTest extends CakeTestCase { ->with(null); $this->Components->TriggerMockSecurity->expects($this->once())->method('startup') ->with(null); + + $this->mockObjects[] = $this->Components->TriggerMockCookie; + $this->mockObjects[] = $this->Components->TriggerMockSecurity; $this->assertTrue($this->Components->trigger('startup', array(&$controller))); } @@ -154,17 +158,20 @@ class ComponentCollectionTest extends CakeTestCase { * * @return void */ - function testTriggerOnDisabledObjects() { + function testTriggerWithTriggerDisabledObjects() { $controller = 'Not a controller'; $this->_makeMockClasses(); $this->Components->load('TriggerMockCookie', array(), false); $this->Components->load('TriggerMockSecurity'); - $this->Components->TriggerMockCookie->expects($this->once())->method('initalize') + $this->Components->TriggerMockCookie->expects($this->once())->method('initialize') ->with($controller); - $this->Components->TriggerMockSecurity->expects($this->once())->method('initalize') + $this->Components->TriggerMockSecurity->expects($this->once())->method('initialize') ->with($controller); + + $this->mockObjects[] = $this->Components->TriggerMockCookie; + $this->mockObjects[] = $this->Components->TriggerMockSecurity; $result = $this->Components->trigger('initialize', array(&$controller), array('triggerDisabled' => true)); $this->assertTrue($result); @@ -182,9 +189,11 @@ class ComponentCollectionTest extends CakeTestCase { $this->Components->load('TriggerMockSecurity'); $this->Components->TriggerMockCookie->expects($this->once())->method('startup') - ->with(null); - $this->Components->TriggerMockSecurity->expects($this->never())->method('startup') - ->with(null); + ->with($controller); + $this->Components->TriggerMockSecurity->expects($this->never())->method('startup'); + + $this->mockObjects[] = $this->Components->TriggerMockCookie; + $this->mockObjects[] = $this->Components->TriggerMockSecurity; $this->Components->disable('TriggerMockSecurity'); @@ -206,6 +215,9 @@ class ComponentCollectionTest extends CakeTestCase { ->will($this->returnValue(array('one', 'two'))); $this->Components->TriggerMockSecurity->expects($this->once())->method('startup') ->will($this->returnValue(array('three', 'four'))); + + $this->mockObjects[] = $this->Components->TriggerMockCookie; + $this->mockObjects[] = $this->Components->TriggerMockSecurity; $result = $this->Components->trigger('startup', array(&$controller), array('collectReturn' => true)); $expected = array( @@ -229,6 +241,9 @@ class ComponentCollectionTest extends CakeTestCase { $this->Components->TriggerMockCookie->expects($this->once())->method('startup') ->will($this->returnValue(false)); $this->Components->TriggerMockSecurity->expects($this->never())->method('startup'); + + $this->mockObjects[] = $this->Components->TriggerMockCookie; + $this->mockObjects[] = $this->Components->TriggerMockSecurity; $result = $this->Components->trigger( 'startup', From 0ef76eb69ada803a03c5f1b0d0a1d5570b80874c Mon Sep 17 00:00:00 2001 From: mark_story Date: Tue, 14 Sep 2010 22:52:51 -0400 Subject: [PATCH 153/166] Adding a reference of the controller to the component collection, so components can easily access the controller in their constructor. --- cake/libs/controller/component_collection.php | 17 +++++++++++++++++ .../controller/component_collection.test.php | 14 ++++++++++++++ 2 files changed, 31 insertions(+) diff --git a/cake/libs/controller/component_collection.php b/cake/libs/controller/component_collection.php index a4aea463b..2f8e6b286 100644 --- a/cake/libs/controller/component_collection.php +++ b/cake/libs/controller/component_collection.php @@ -20,6 +20,13 @@ App::import('Core', 'ObjectCollection'); class ComponentCollection extends ObjectCollection { +/** + * The controller that this collection was initialized with. + * + * @var Controller + */ + protected $_Controller = null; + /** * Initializes all the Components for a controller. * Attaches a reference of each component to the Controller. @@ -31,12 +38,22 @@ class ComponentCollection extends ObjectCollection { if (empty($Controller->components)) { return; } + $this->_Controller = $Controller; $components = ComponentCollection::normalizeObjectArray($Controller->components); foreach ($components as $name => $properties) { $Controller->{$name} = $this->load($properties['class'], $properties['settings']); } } +/** + * Get the controller associated with the collection. + * + * @return Controller. + */ + public function getController() { + return $this->_Controller; + } + /** * Loads/constructs a component. Will return the instance in the registry if it already exists. * diff --git a/cake/tests/cases/libs/controller/component_collection.test.php b/cake/tests/cases/libs/controller/component_collection.test.php index 6d4eabb22..cb0e83b83 100644 --- a/cake/tests/cases/libs/controller/component_collection.test.php +++ b/cake/tests/cases/libs/controller/component_collection.test.php @@ -274,4 +274,18 @@ class ComponentCollectionTest extends CakeTestCase { ); $this->assertEquals($expected, $result); } + +/** + * test getting the controller out of the collection + * + * @return void + */ + function testGetController() { + $controller = $this->getMock('Controller'); + $controller->components = array('Security'); + $this->Components->init($controller); + $result = $this->Components->getController(); + + $this->assertSame($controller, $result); + } } \ No newline at end of file From 30589e2cdf6cf64b10d67717bb38aa5579a3335f Mon Sep 17 00:00:00 2001 From: mark_story Date: Tue, 14 Sep 2010 22:56:33 -0400 Subject: [PATCH 154/166] Removing dead method. --- cake/libs/controller/components/security.php | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/cake/libs/controller/components/security.php b/cake/libs/controller/components/security.php index 63b6676c2..90c3ccdc8 100644 --- a/cake/libs/controller/components/security.php +++ b/cake/libs/controller/components/security.php @@ -176,17 +176,6 @@ class SecurityComponent extends Component { */ public $request; -/** - * Initialize the SecurityComponent - * - * @param object $controller Controller instance for the request - * @param array $settings Settings to set to the component - * @return void - */ - public function initialize(&$controller, $settings = array()) { - $this->_set($settings); - } - /** * Component startup. All security checking happens here. * From 273a189e98bdbc13a7d6af0f109752cb65d2239c Mon Sep 17 00:00:00 2001 From: mark_story Date: Tue, 14 Sep 2010 23:01:39 -0400 Subject: [PATCH 155/166] Adding some documentation about component callbacks. --- cake/libs/controller/component.php | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/cake/libs/controller/component.php b/cake/libs/controller/component.php index 7a6e684f1..c426fd8b7 100644 --- a/cake/libs/controller/component.php +++ b/cake/libs/controller/component.php @@ -23,6 +23,18 @@ App::import('Controller', 'ComponentCollection', false); * controller logic that can be composed into a controller. Components also * provide request life-cycle callbacks for injecting logic at specific points. * + * ## Life cycle callbacks + * + * Components can provide several callbacks that are fired at various stages of the request + * cycle. The available callbacks are: + * + * - `initialize()` - Fired before the controller's beforeFilter method. + * - `startup()` - Fired after the controller's beforeFilter method. + * - `beforeRender()` - Fired before the view + layout are rendered. + * - `shutdown()` - Fired after the action is complete and the view has been rendered + * but before Controller::afterFilter(). + * - `beforeRedirect()` - Fired before a redirect() is done. + * * @package cake * @subpackage cake.cake.libs.controller * @link http://book.cakephp.org/view/993/Components From f34cfd1f1ec026481997539590394121bb9c0e1d Mon Sep 17 00:00:00 2001 From: mark_story Date: Tue, 14 Sep 2010 23:02:38 -0400 Subject: [PATCH 156/166] Updating EmailComponent to use new methods on the ComponentCollection to ensure it always has a controller reference. Removing triggerDisabled key as its no longer needed or wanted. --- cake/libs/controller/components/email.php | 12 +++++++++++- cake/libs/controller/controller.php | 2 +- cake/tests/cases/libs/controller/controller.test.php | 2 +- 3 files changed, 13 insertions(+), 3 deletions(-) diff --git a/cake/libs/controller/components/email.php b/cake/libs/controller/components/email.php index b22806895..d0aab867b 100755 --- a/cake/libs/controller/components/email.php +++ b/cake/libs/controller/components/email.php @@ -298,13 +298,23 @@ class EmailComponent extends Component { */ protected $_smtpConnection = null; +/** + * Constructor + * + * @param ComponentCollection $collection A ComponentCollection this component can use to lazy load its components + * @param array $settings Array of configuration settings. + */ + public function __construct(ComponentCollection $collection, $settings = array()) { + $this->Controller = $collection->getController(); + parent::__construct($collection, $settings); + } + /** * Initialize component * * @param object $controller Instantiating controller */ public function initialize(&$controller) { - $this->Controller = $controller; if (Configure::read('App.encoding') !== null) { $this->charset = Configure::read('App.encoding'); } diff --git a/cake/libs/controller/controller.php b/cake/libs/controller/controller.php index 07e0b8f59..0b2e55c35 100644 --- a/cake/libs/controller/controller.php +++ b/cake/libs/controller/controller.php @@ -533,7 +533,7 @@ class Controller extends Object { * @return void */ public function startupProcess() { - $this->Components->trigger('initialize', array(&$this), array('triggerDisabled' => true)); + $this->Components->trigger('initialize', array(&$this)); $this->beforeFilter(); $this->Components->trigger('startup', array(&$this)); } diff --git a/cake/tests/cases/libs/controller/controller.test.php b/cake/tests/cases/libs/controller/controller.test.php index 20eb72642..5ad875016 100644 --- a/cake/tests/cases/libs/controller/controller.test.php +++ b/cake/tests/cases/libs/controller/controller.test.php @@ -1478,7 +1478,7 @@ class ControllerTest extends CakeTestCase { $Controller->expects($this->once())->method('beforeFilter'); $Controller->Components->expects($this->at(0))->method('trigger') - ->with('initialize', array(&$Controller), array('triggerDisabled' => true)); + ->with('initialize', array(&$Controller)); $Controller->Components->expects($this->at(1))->method('trigger') ->with('startup', array(&$Controller)); From c255539980c0f5be4bff3f70f5e939dbd167536c Mon Sep 17 00:00:00 2001 From: mark_story Date: Tue, 14 Sep 2010 23:13:00 -0400 Subject: [PATCH 157/166] Removing assignment of reference to theme view. Removing cruft in ThemeView test. --- cake/libs/view/theme.php | 2 +- cake/tests/cases/libs/view/theme.test.php | 44 +++-------------------- 2 files changed, 6 insertions(+), 40 deletions(-) diff --git a/cake/libs/view/theme.php b/cake/libs/view/theme.php index 834fed182..ebeb1d815 100644 --- a/cake/libs/view/theme.php +++ b/cake/libs/view/theme.php @@ -40,7 +40,7 @@ class ThemeView extends View { */ function __construct(&$controller) { parent::__construct($controller); - $this->theme =& $controller->theme; + $this->theme = $controller->theme; } /** diff --git a/cake/tests/cases/libs/view/theme.test.php b/cake/tests/cases/libs/view/theme.test.php index 297976b7d..e071586b5 100644 --- a/cake/tests/cases/libs/view/theme.test.php +++ b/cake/tests/cases/libs/view/theme.test.php @@ -21,12 +21,6 @@ App::import('View', 'View'); App::import('View', 'Theme'); App::import('Core', 'Controller'); -if (!class_exists('ErrorHandler')) { - App::import('Core', array('Error')); -} -if (!defined('CAKEPHP_UNIT_TEST_EXECUTION')) { - define('CAKEPHP_UNIT_TEST_EXECUTION', 1); -} /** * ThemePostsController class @@ -43,6 +37,8 @@ class ThemePostsController extends Controller { * @access public */ public $name = 'ThemePosts'; + + public $theme = null; /** * index method @@ -58,25 +54,6 @@ class ThemePostsController extends Controller { } } -/** - * ThemeViewTestErrorHandler class - * - * @package cake - * @subpackage cake.tests.cases.libs.view - */ -class ThemeViewTestErrorHandler extends ErrorHandler { - -/** - * stop method - * - * @access public - * @return void - */ - function _stop() { - return; - } -} - /** * TestThemeView class * @@ -119,18 +96,6 @@ class TestThemeView extends ThemeView { return $this->_getLayoutFileName($name); } -/** - * cakeError method - * - * @param mixed $method - * @param mixed $messages - * @access public - * @return void - */ - function cakeError($method, $messages) { - $error = new ThemeViewTestErrorHandler($method, $messages); - return $error; - } } /** @@ -149,8 +114,9 @@ class ThemeViewTest extends CakeTestCase { */ function setUp() { Router::reload(); - $this->Controller = new Controller(); - $this->PostsController = new ThemePostsController(); + $request = new CakeRequest('posts/index'); + $this->Controller = new Controller($request); + $this->PostsController = new ThemePostsController($request); $this->PostsController->viewPath = 'posts'; $this->PostsController->index(); $this->ThemeView = new ThemeView($this->PostsController); From 1707c92aa1c530e8750bf6325c012444cebc780e Mon Sep 17 00:00:00 2001 From: mark_story Date: Tue, 14 Sep 2010 23:15:10 -0400 Subject: [PATCH 158/166] Removing duplicated code. --- cake/libs/controller/controller.php | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/cake/libs/controller/controller.php b/cake/libs/controller/controller.php index 0b2e55c35..a9b11759d 100644 --- a/cake/libs/controller/controller.php +++ b/cake/libs/controller/controller.php @@ -497,10 +497,7 @@ class Controller extends Object { $this->loadModel($this->modelClass, $id); } elseif ($this->uses) { $uses = is_array($this->uses) ? $this->uses : array($this->uses); - $modelClassName = $uses[0]; - if (strpos($uses[0], '.') !== false) { - list($plugin, $modelClassName) = explode('.', $uses[0]); - } + list($plugin, $modelClassName) = pluginSplit($uses[0]); $this->modelClass = $modelClassName; foreach ($uses as $modelClass) { $this->loadModel($modelClass); From dc65f2306b899e5cd1c42b562328cb54af8507ca Mon Sep 17 00:00:00 2001 From: mark_story Date: Sat, 18 Sep 2010 00:45:29 -0400 Subject: [PATCH 159/166] Making Cache methods always need a config name. This allows the removal of hidden and often confusing state that gets remembered by Cache each time config() is called. Removing the hidden state makes Cache more predictable. --- cake/libs/cache.php | 112 ++++++++------------------- cake/tests/cases/libs/cache.test.php | 38 ++++----- 2 files changed, 51 insertions(+), 99 deletions(-) diff --git a/cake/libs/cache.php b/cake/libs/cache.php index da5cba99c..ce1465384 100644 --- a/cake/libs/cache.php +++ b/cake/libs/cache.php @@ -36,13 +36,6 @@ class Cache { */ protected static $_config = array(); -/** - * Holds name of the current configuration name being used. - * - * @var array - */ - protected static $_name = 'default'; - /** * Whether to reset the settings with the next call to Cache::set(); * @@ -60,8 +53,7 @@ class Cache { /** * Set the cache configuration to use. config() can * both create new configurations, return the settings for already configured - * configurations. It also sets the 'default' configuration to use for subsequent - * operations. + * configurations. * * To create a new configuration: * @@ -82,10 +74,6 @@ class Cache { $settings = $name; } - if ($name === null || !is_string($name)) { - $name = self::$_name; - } - $current = array(); if (isset(self::$_config[$name])) { $current = self::$_config[$name]; @@ -100,12 +88,11 @@ class Cache { } $engine = self::$_config[$name]['engine']; - self::$_name = $name; if (!isset(self::$_engines[$name])) { self::_buildEngine($name); $settings = self::$_config[$name] = self::settings($name); - } elseif ($settings = self::set(self::$_config[$name])) { + } elseif ($settings = self::set(self::$_config[$name], null, $name)) { self::$_config[$name] = $settings; } return compact('engine', 'settings'); @@ -190,13 +177,13 @@ class Cache { * * @param mixed $settings Optional string for simple name-value pair or array * @param string $value Optional for a simple name-value pair + * @param string $config The configuration name you are changing. Defaults to 'default' * @return array Array of settings. */ - public static function set($settings = array(), $value = null) { - if (!isset(self::$_config[self::$_name]) || !isset(self::$_engines[self::$_name])) { + public static function set($settings = array(), $value = null, $config = 'default') { + if (!isset(self::$_config[$config]) || !isset(self::$_engines[$config])) { return false; } - $name = self::$_name; if (!empty($settings)) { self::$_reset = true; } @@ -204,19 +191,19 @@ class Cache { if (self::$_reset === true) { if (empty($settings)) { self::$_reset = false; - $settings = self::$_config[$name]; + $settings = self::$_config[$config]; } else { if (is_string($settings) && $value !== null) { $settings = array($settings => $value); } - $settings = array_merge(self::$_config[$name], $settings); + $settings = array_merge(self::$_config[$config], $settings); if (isset($settings['duration']) && !is_numeric($settings['duration'])) { $settings['duration'] = strtotime($settings['duration']) - time(); } } - self::$_engines[$name]->settings = $settings; + self::$_engines[$config]->settings = $settings; } - return self::settings($name); + return self::settings($config); } /** @@ -224,10 +211,11 @@ class Cache { * * Permanently remove all expired and deleted data * + * @param string $config The config name you wish to have garbage collected. Defaults to 'default' * @return void */ - public static function gc() { - self::$_engines[self::$_name]->gc(); + public static function gc($config = 'default') { + self::$_engines[$config]->gc(); } /** @@ -247,13 +235,10 @@ class Cache { * * @param string $key Identifier for the data * @param mixed $value Data to be cached - anything except a resource - * @param string $config Optional string configuration name to write to. + * @param string $config Optional string configuration name to write to. Defaults to 'default' * @return boolean True if the data was successfully cached, false on failure */ - public static function write($key, $value, $config = null) { - if (!$config) { - $config = self::$_name; - } + public static function write($key, $value, $config = 'default') { $settings = self::settings($config); if (empty($settings)) { @@ -269,7 +254,7 @@ class Cache { } $success = self::$_engines[$config]->write($settings['prefix'] . $key, $value, $settings['duration']); - self::set(); + self::set(array(), null, $config); if ($success === false && $value !== '') { trigger_error( sprintf(__("%s cache was unable to write '%s' to cache", true), $config, $key), @@ -295,13 +280,10 @@ class Cache { * `Cache::read('my_data', 'long_term');` * * @param string $key Identifier for the data - * @param string $config optional name of the configuration to use. + * @param string $config optional name of the configuration to use. Defaults to 'default' * @return mixed The cached data, or false if the data doesn't exist, has expired, or if there was an error fetching it */ - public static function read($key, $config = null) { - if (!$config) { - $config = self::$_name; - } + public static function read($key, $config = 'default') { $settings = self::settings($config); if (empty($settings)) { @@ -316,9 +298,7 @@ class Cache { } $success = self::$_engines[$config]->read($settings['prefix'] . $key); - if ($config !== null && $config !== self::$_name) { - self::set(); - } + self::set(array(), null, $config); return $success; } @@ -327,15 +307,11 @@ class Cache { * * @param string $key Identifier for the data * @param integer $offset How much to add - * @param string $config Optional string configuration name. If not specified the current - * default config will be used. + * @param string $config Optional string configuration name. Defaults to 'default' * @return mixed new value, or false if the data doesn't exist, is not integer, * or if there was an error fetching it. */ - public static function increment($key, $offset = 1, $config = null) { - if (!$config) { - $config = self::$_name; - } + public static function increment($key, $offset = 1, $config = 'default') { $settings = self::settings($config); if (empty($settings)) { @@ -350,7 +326,7 @@ class Cache { return false; } $success = self::$_engines[$config]->increment($settings['prefix'] . $key, $offset); - self::set(); + self::set(array(), null, $config); return $success; } /** @@ -358,15 +334,11 @@ class Cache { * * @param string $key Identifier for the data * @param integer $offset How much to substract - * @param string $config Optional string configuration name, if not specified the current - * default config will be used. + * @param string $config Optional string configuration name. Defaults to 'default' * @return mixed new value, or false if the data doesn't exist, is not integer, * or if there was an error fetching it */ - public static function decrement($key, $offset = 1, $config = null) { - if (!$config) { - $config = self::$_name; - } + public static function decrement($key, $offset = 1, $config = 'default') { $settings = self::settings($config); if (empty($settings)) { @@ -381,13 +353,11 @@ class Cache { return false; } $success = self::$_engines[$config]->decrement($settings['prefix'] . $key, $offset); - self::set(); + self::set(array(), null, $config); return $success; } /** - * Delete a key from the cache. Will automatically use the currently - * active cache configuration. To set the currently active configuration use - * Cache::config() + * Delete a key from the cache. * * ### Usage: * @@ -400,13 +370,10 @@ class Cache { * `Cache::delete('my_data', 'long_term');` * * @param string $key Identifier for the data - * @param string $config name of the configuration to use + * @param string $config name of the configuration to use. Defaults to 'default' * @return boolean True if the value was succesfully deleted, false if it didn't exist or couldn't be removed */ - public static function delete($key, $config = null) { - if (!$config) { - $config = self::$_name; - } + public static function delete($key, $config = 'default') { $settings = self::settings($config); if (empty($settings)) { @@ -421,7 +388,7 @@ class Cache { } $success = self::$_engines[$config]->delete($settings['prefix'] . $key); - self::set(); + self::set(array(), null, $config); return $success; } @@ -429,13 +396,10 @@ class Cache { * Delete all keys from the cache. * * @param boolean $check if true will check expiration, otherwise delete all - * @param string $config name of the configuration to use + * @param string $config name of the configuration to use. Defaults to 'default' * @return boolean True if the cache was succesfully cleared, false otherwise */ - public static function clear($check = false, $config = null) { - if (!$config) { - $config = self::$_name; - } + public static function clear($check = false, $config = 'default') { $settings = self::settings($config); if (empty($settings)) { @@ -446,7 +410,7 @@ class Cache { return false; } $success = self::$_engines[$config]->clear($check); - self::set(); + self::set(array(), null, $config); return $success; } @@ -457,20 +421,15 @@ class Cache { * @param string $config Name of the configuration setting * @return bool Whether or not the config name has been initialized. */ - public static function isInitialized($name = null) { + public static function isInitialized($name) { if (Configure::read('Cache.disable')) { return false; } - if (!$name && isset(self::$_config[self::$_name])) { - $name = self::$_name; - } return isset(self::$_engines[$name]); } /** - * Return the settings for current cache engine. If no name is supplied the settings - * for the 'active default' configuration will be returned. To set the 'active default' - * configuration use `Cache::config()` + * Return the settings for the named cache engine. * * @param string $engine Name of the configuration to get settings for. * @return array list of settings for this engine @@ -478,10 +437,7 @@ class Cache { * @access public * @static */ - public static function settings($name = null) { - if (!$name && isset(self::$_config[self::$_name])) { - $name = self::$_name; - } + public static function settings($name = 'default') { if (!empty(self::$_engines[$name])) { return self::$_engines[$name]->settings(); } diff --git a/cake/tests/cases/libs/cache.test.php b/cake/tests/cases/libs/cache.test.php index 964e3a2fc..6b97a9cfd 100644 --- a/cake/tests/cases/libs/cache.test.php +++ b/cake/tests/cases/libs/cache.test.php @@ -172,12 +172,10 @@ class CacheTest extends CakeTestCase { function testConfigSettingDefaultConfigKey() { Cache::config('test_name', array('engine' => 'File', 'prefix' => 'test_name_')); - Cache::config('test_name'); - Cache::write('value_one', 'I am cached'); - $result = Cache::read('value_one'); + Cache::write('value_one', 'I am cached', 'test_name'); + $result = Cache::read('value_one', 'test_name'); $this->assertEqual($result, 'I am cached'); - Cache::config('default'); $result = Cache::read('value_one'); $this->assertEqual($result, null); @@ -185,13 +183,11 @@ class CacheTest extends CakeTestCase { $result = Cache::read('value_one'); $this->assertEqual($result, 'I am in default config!'); - Cache::config('test_name'); - $result = Cache::read('value_one'); + $result = Cache::read('value_one', 'test_name'); $this->assertEqual($result, 'I am cached'); - Cache::delete('value_one'); - Cache::config('default'); - Cache::delete('value_one'); + Cache::delete('value_one', 'test_name'); + Cache::delete('value_one', 'default'); } /** @@ -345,34 +341,34 @@ class CacheTest extends CakeTestCase { Configure::write('Cache.disable', false); Cache::config('test_cache_disable_1', array('engine'=> 'File', 'path' => TMP . 'tests')); - $this->assertTrue(Cache::write('key_1', 'hello')); - $this->assertIdentical(Cache::read('key_1'), 'hello'); + $this->assertTrue(Cache::write('key_1', 'hello', 'test_cache_disable_1')); + $this->assertIdentical(Cache::read('key_1', 'test_cache_disable_1'), 'hello'); Configure::write('Cache.disable', true); - $this->assertFalse(Cache::write('key_2', 'hello')); - $this->assertFalse(Cache::read('key_2')); + $this->assertFalse(Cache::write('key_2', 'hello', 'test_cache_disable_1')); + $this->assertFalse(Cache::read('key_2', 'test_cache_disable_1')); Configure::write('Cache.disable', false); - $this->assertTrue(Cache::write('key_3', 'hello')); - $this->assertIdentical(Cache::read('key_3'), 'hello'); + $this->assertTrue(Cache::write('key_3', 'hello', 'test_cache_disable_1')); + $this->assertIdentical(Cache::read('key_3', 'test_cache_disable_1'), 'hello'); Configure::write('Cache.disable', true); Cache::config('test_cache_disable_2', array('engine'=> 'File', 'path' => TMP . 'tests')); - $this->assertFalse(Cache::write('key_4', 'hello')); - $this->assertFalse(Cache::read('key_4')); + $this->assertFalse(Cache::write('key_4', 'hello', 'test_cache_disable_2')); + $this->assertFalse(Cache::read('key_4', 'test_cache_disable_2')); Configure::write('Cache.disable', false); - $this->assertTrue(Cache::write('key_5', 'hello')); - $this->assertIdentical(Cache::read('key_5'), 'hello'); + $this->assertTrue(Cache::write('key_5', 'hello', 'test_cache_disable_2')); + $this->assertIdentical(Cache::read('key_5', 'test_cache_disable_2'), 'hello'); Configure::write('Cache.disable', true); - $this->assertFalse(Cache::write('key_6', 'hello')); - $this->assertFalse(Cache::read('key_6')); + $this->assertFalse(Cache::write('key_6', 'hello', 'test_cache_disable_2')); + $this->assertFalse(Cache::read('key_6', 'test_cache_disable_2')); } /** From 9ccbe5e26992e3ddb64737b3bf6a7426eea01525 Mon Sep 17 00:00:00 2001 From: mark_story Date: Sat, 18 Sep 2010 00:46:26 -0400 Subject: [PATCH 160/166] Removing unnecessary call to config(). --- cake/libs/configure.php | 1 - 1 file changed, 1 deletion(-) diff --git a/cake/libs/configure.php b/cake/libs/configure.php index f807dc0cc..07b50d99d 100644 --- a/cake/libs/configure.php +++ b/cake/libs/configure.php @@ -378,7 +378,6 @@ class Configure { 'serialize' => true, 'duration' => $duration ))); } - Cache::config('default'); } App::init(); App::build(); From 1eb746bf7e10ea01ccaef30db79dd6390b9f97b1 Mon Sep 17 00:00:00 2001 From: mark_story Date: Sat, 18 Sep 2010 11:10:35 -0400 Subject: [PATCH 161/166] Fixing fatal error caused by missing argument. --- cake/tests/test_app/views/posts/test_nocache_tags.ctp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cake/tests/test_app/views/posts/test_nocache_tags.ctp b/cake/tests/test_app/views/posts/test_nocache_tags.ctp index 61e7e19f5..78ab5a817 100644 --- a/cake/tests/test_app/views/posts/test_nocache_tags.ctp +++ b/cake/tests/test_app/views/posts/test_nocache_tags.ctp @@ -35,7 +35,7 @@ ' . $settings['engine']; From b432e6097141340ee07943dcc713770969bde020 Mon Sep 17 00:00:00 2001 From: mark_story Date: Sat, 18 Sep 2010 11:11:28 -0400 Subject: [PATCH 162/166] Making Cache::set() work with 2 or 3 parameters. Test cases added. --- cake/libs/cache.php | 17 ++++++++++++++--- cake/tests/cases/libs/cache.test.php | 13 +++++++++++++ 2 files changed, 27 insertions(+), 3 deletions(-) diff --git a/cake/libs/cache.php b/cake/libs/cache.php index ce1465384..3dd134264 100644 --- a/cake/libs/cache.php +++ b/cake/libs/cache.php @@ -175,12 +175,23 @@ class Cache { * Temporarily change settings to current config options. if no params are passed, resets settings if needed * Cache::write() will reset the configuration changes made * + * Can be called with 2 or 3 parameters. To set multiple values at once. + * + * `Cache::set(array('duration' => '+30 minutes'), 'my_config');` + * + * Or to set one value. + * + * `Cache::set('duration', '+30 minutes', 'my_config');` + * * @param mixed $settings Optional string for simple name-value pair or array * @param string $value Optional for a simple name-value pair * @param string $config The configuration name you are changing. Defaults to 'default' * @return array Array of settings. */ public static function set($settings = array(), $value = null, $config = 'default') { + if (is_array($settings) && $value !== null) { + $config = $value; + } if (!isset(self::$_config[$config]) || !isset(self::$_engines[$config])) { return false; } @@ -417,11 +428,11 @@ class Cache { /** * Check if Cache has initialized a working config for the given name. * - * @param string $engine Name of the engine + * @param string $engine Name of the engine, Defaults to default * @param string $config Name of the configuration setting * @return bool Whether or not the config name has been initialized. */ - public static function isInitialized($name) { + public static function isInitialized($name = 'default') { if (Configure::read('Cache.disable')) { return false; } @@ -431,7 +442,7 @@ class Cache { /** * Return the settings for the named cache engine. * - * @param string $engine Name of the configuration to get settings for. + * @param string $engine Name of the configuration to get settings for. Defaults to 'default' * @return array list of settings for this engine * @see Cache::config() * @access public diff --git a/cake/tests/cases/libs/cache.test.php b/cake/tests/cases/libs/cache.test.php index 6b97a9cfd..8c4d83b65 100644 --- a/cake/tests/cases/libs/cache.test.php +++ b/cake/tests/cases/libs/cache.test.php @@ -399,4 +399,17 @@ class CacheTest extends CakeTestCase { Cache::set($_cacheSet); } +/** + * test set() parameter handling for user cache configs. + * + * @return void + */ + function testSetOnAlternateConfigs() { + Cache::config('file_config', array('engine' => 'File', 'prefix' => 'test_file_')); + Cache::set(array('duration' => '+1 year'), 'file_config'); + $settings = Cache::settings('file_config'); + + $this->assertEquals('test_file_', $settings['prefix']); + $this->assertEquals(31536000, $settings['duration']); + } } From 5e725e62ca89f10813662fc1f01395c3a052bb9b Mon Sep 17 00:00:00 2001 From: mark_story Date: Sat, 18 Sep 2010 11:11:51 -0400 Subject: [PATCH 163/166] Making MemcacheEngine match the interface. --- cake/libs/cache/memcache.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cake/libs/cache/memcache.php b/cake/libs/cache/memcache.php index 077f5cba0..1c94d3893 100644 --- a/cake/libs/cache/memcache.php +++ b/cake/libs/cache/memcache.php @@ -107,7 +107,7 @@ class MemcacheEngine extends CacheEngine { * @return boolean True if the data was succesfully cached, false on failure * @see http://php.net/manual/en/memcache.set.php */ - public function write($key, &$value, $duration) { + public function write($key, $value, $duration) { return $this->__Memcache->set($key, $value, $this->settings['compress'], $duration); } From b6d845adc4583d64f7569a855f0ee85bd95c3e03 Mon Sep 17 00:00:00 2001 From: mark_story Date: Sat, 18 Sep 2010 12:32:43 -0400 Subject: [PATCH 164/166] Updating calls of Cache::set() inside Cache. Updating the documentation for set() so it better explains how the temporary settings work. Updating APC and Memcache engine tests to reflect the lack of state being stored inside Cache. --- cake/libs/cache.php | 25 ++++---- cake/tests/cases/libs/cache/apc.test.php | 50 ++++++++-------- cake/tests/cases/libs/cache/memcache.test.php | 58 +++++++++---------- 3 files changed, 68 insertions(+), 65 deletions(-) diff --git a/cake/libs/cache.php b/cake/libs/cache.php index 3dd134264..b674bd390 100644 --- a/cake/libs/cache.php +++ b/cake/libs/cache.php @@ -172,8 +172,10 @@ class Cache { } /** - * Temporarily change settings to current config options. if no params are passed, resets settings if needed - * Cache::write() will reset the configuration changes made + * Temporarily change the settings on a cache config. The settings will persist for the next write + * operation (write, decrement, increment, clear). Any reads that are done before the write, will + * use the modified settings. If `$settings` is empty, the settings will be reset to the + * original configuration. * * Can be called with 2 or 3 parameters. To set multiple values at once. * @@ -183,6 +185,10 @@ class Cache { * * `Cache::set('duration', '+30 minutes', 'my_config');` * + * To reset a config back to the originally configured values. + * + * `Cache::set(null, 'my_config');` + * * @param mixed $settings Optional string for simple name-value pair or array * @param string $value Optional for a simple name-value pair * @param string $config The configuration name you are changing. Defaults to 'default' @@ -265,7 +271,7 @@ class Cache { } $success = self::$_engines[$config]->write($settings['prefix'] . $key, $value, $settings['duration']); - self::set(array(), null, $config); + self::set(null, $config); if ($success === false && $value !== '') { trigger_error( sprintf(__("%s cache was unable to write '%s' to cache", true), $config, $key), @@ -307,10 +313,7 @@ class Cache { if (!$key) { return false; } - $success = self::$_engines[$config]->read($settings['prefix'] . $key); - - self::set(array(), null, $config); - return $success; + return self::$_engines[$config]->read($settings['prefix'] . $key); } /** @@ -337,7 +340,7 @@ class Cache { return false; } $success = self::$_engines[$config]->increment($settings['prefix'] . $key, $offset); - self::set(array(), null, $config); + self::set(null, $config); return $success; } /** @@ -364,7 +367,7 @@ class Cache { return false; } $success = self::$_engines[$config]->decrement($settings['prefix'] . $key, $offset); - self::set(array(), null, $config); + self::set(null, $config); return $success; } /** @@ -399,7 +402,7 @@ class Cache { } $success = self::$_engines[$config]->delete($settings['prefix'] . $key); - self::set(array(), null, $config); + self::set(null, $config); return $success; } @@ -421,7 +424,7 @@ class Cache { return false; } $success = self::$_engines[$config]->clear($check); - self::set(array(), null, $config); + self::set(null, $config); return $success; } diff --git a/cake/tests/cases/libs/cache/apc.test.php b/cake/tests/cases/libs/cache/apc.test.php index 883f9b852..9d2e81f08 100644 --- a/cake/tests/cases/libs/cache/apc.test.php +++ b/cake/tests/cases/libs/cache/apc.test.php @@ -74,21 +74,21 @@ class ApcEngineTest extends CakeTestCase { * @return void */ function testReadAndWriteCache() { - Cache::set(array('duration' => 1)); + Cache::set(array('duration' => 1), 'apc'); - $result = Cache::read('test'); + $result = Cache::read('test', 'apc'); $expecting = ''; $this->assertEqual($result, $expecting); $data = 'this is a test of the emergency broadcasting system'; - $result = Cache::write('test', $data); + $result = Cache::write('test', $data, 'apc'); $this->assertTrue($result); - $result = Cache::read('test'); + $result = Cache::read('test', 'apc'); $expecting = $data; $this->assertEqual($result, $expecting); - Cache::delete('test'); + Cache::delete('test', 'apc'); } /** @@ -98,31 +98,31 @@ class ApcEngineTest extends CakeTestCase { * @return void */ function testExpiry() { - Cache::set(array('duration' => 1)); + Cache::set(array('duration' => 1), 'apc'); - $result = Cache::read('test'); + $result = Cache::read('test', 'apc'); $this->assertFalse($result); $data = 'this is a test of the emergency broadcasting system'; - $result = Cache::write('other_test', $data); + $result = Cache::write('other_test', $data, 'apc'); $this->assertTrue($result); sleep(2); - $result = Cache::read('other_test'); + $result = Cache::read('other_test', 'apc'); $this->assertFalse($result); - Cache::set(array('duration' => 1)); + Cache::set(array('duration' => 1), 'apc'); $data = 'this is a test of the emergency broadcasting system'; - $result = Cache::write('other_test', $data); + $result = Cache::write('other_test', $data, 'apc'); $this->assertTrue($result); sleep(2); - $result = Cache::read('other_test'); + $result = Cache::read('other_test', 'apc'); $this->assertFalse($result); sleep(2); - $result = Cache::read('other_test'); + $result = Cache::read('other_test', 'apc'); $this->assertFalse($result); } @@ -134,10 +134,10 @@ class ApcEngineTest extends CakeTestCase { */ function testDeleteCache() { $data = 'this is a test of the emergency broadcasting system'; - $result = Cache::write('delete_test', $data); + $result = Cache::write('delete_test', $data, 'apc'); $this->assertTrue($result); - $result = Cache::delete('delete_test'); + $result = Cache::delete('delete_test', 'apc'); $this->assertTrue($result); } @@ -151,19 +151,19 @@ class ApcEngineTest extends CakeTestCase { if ($this->skipIf(!function_exists('apc_dec'), 'No apc_dec() function, cannot test decrement() %s')) { return; } - $result = Cache::write('test_decrement', 5); + $result = Cache::write('test_decrement', 5, 'apc'); $this->assertTrue($result); - $result = Cache::decrement('test_decrement'); + $result = Cache::decrement('test_decrement', 1, 'apc'); $this->assertEqual(4, $result); - $result = Cache::read('test_decrement'); + $result = Cache::read('test_decrement', 'apc'); $this->assertEqual(4, $result); - $result = Cache::decrement('test_decrement', 2); + $result = Cache::decrement('test_decrement', 2, 'apc'); $this->assertEqual(2, $result); - $result = Cache::read('test_decrement'); + $result = Cache::read('test_decrement', 'apc'); $this->assertEqual(2, $result); } @@ -178,19 +178,19 @@ class ApcEngineTest extends CakeTestCase { if ($this->skipIf(!function_exists('apc_inc'), 'No apc_inc() function, cannot test increment() %s')) { return; } - $result = Cache::write('test_increment', 5); + $result = Cache::write('test_increment', 5, 'apc'); $this->assertTrue($result); - $result = Cache::increment('test_increment'); + $result = Cache::increment('test_increment', 1, 'apc'); $this->assertEqual(6, $result); - $result = Cache::read('test_increment'); + $result = Cache::read('test_increment', 'apc'); $this->assertEqual(6, $result); - $result = Cache::increment('test_increment', 2); + $result = Cache::increment('test_increment', 2, 'apc'); $this->assertEqual(8, $result); - $result = Cache::read('test_increment'); + $result = Cache::read('test_increment', 'apc'); $this->assertEqual(8, $result); } } diff --git a/cake/tests/cases/libs/cache/memcache.test.php b/cake/tests/cases/libs/cache/memcache.test.php index 907281175..61b8e9ad8 100644 --- a/cake/tests/cases/libs/cache/memcache.test.php +++ b/cake/tests/cases/libs/cache/memcache.test.php @@ -78,7 +78,7 @@ class MemcacheEngineTest extends CakeTestCase { * @return void */ function testSettings() { - $settings = Cache::settings(); + $settings = Cache::settings('memcache'); unset($settings['serialize'], $settings['path']); $expecting = array( 'prefix' => 'cake_', @@ -141,21 +141,21 @@ class MemcacheEngineTest extends CakeTestCase { * @return void */ function testReadAndWriteCache() { - Cache::set(array('duration' => 1)); + Cache::set(array('duration' => 1), null, 'memcache'); - $result = Cache::read('test'); + $result = Cache::read('test', 'memcache'); $expecting = ''; $this->assertEqual($result, $expecting); $data = 'this is a test of the emergency broadcasting system'; - $result = Cache::write('test', $data); + $result = Cache::write('test', $data, 'memcache'); $this->assertTrue($result); - $result = Cache::read('test'); + $result = Cache::read('test', 'memcache'); $expecting = $data; $this->assertEqual($result, $expecting); - Cache::delete('test'); + Cache::delete('test', 'memcache'); } /** @@ -165,42 +165,42 @@ class MemcacheEngineTest extends CakeTestCase { * @return void */ function testExpiry() { - Cache::set(array('duration' => 1)); + Cache::set(array('duration' => 1), 'memcache'); - $result = Cache::read('test'); + $result = Cache::read('test', 'memcache'); $this->assertFalse($result); $data = 'this is a test of the emergency broadcasting system'; - $result = Cache::write('other_test', $data); + $result = Cache::write('other_test', $data, 'memcache'); $this->assertTrue($result); sleep(2); - $result = Cache::read('other_test'); + $result = Cache::read('other_test', 'memcache'); $this->assertFalse($result); - Cache::set(array('duration' => "+1 second")); + Cache::set(array('duration' => "+1 second"), 'memcache'); $data = 'this is a test of the emergency broadcasting system'; - $result = Cache::write('other_test', $data); + $result = Cache::write('other_test', $data, 'memcache'); $this->assertTrue($result); sleep(2); - $result = Cache::read('other_test'); + $result = Cache::read('other_test', 'memcache'); $this->assertFalse($result); Cache::config('memcache', array('duration' => '+1 second')); sleep(2); - $result = Cache::read('other_test'); + $result = Cache::read('other_test', 'memcache'); $this->assertFalse($result); - Cache::config('memcache', array('duration' => '+30 day')); + Cache::config('memcache', array('duration' => '+30 days')); $data = 'this is a test of the emergency broadcasting system'; - $result = Cache::write('long_expiry_test', $data); + $result = Cache::write('long_expiry_test', $data, 'memcache'); $this->assertTrue($result); sleep(2); - $result = Cache::read('long_expiry_test'); + $result = Cache::read('long_expiry_test', 'memcache'); $expecting = $data; $this->assertEqual($result, $expecting); @@ -215,10 +215,10 @@ class MemcacheEngineTest extends CakeTestCase { */ function testDeleteCache() { $data = 'this is a test of the emergency broadcasting system'; - $result = Cache::write('delete_test', $data); + $result = Cache::write('delete_test', $data, 'memcache'); $this->assertTrue($result); - $result = Cache::delete('delete_test'); + $result = Cache::delete('delete_test', 'memcache'); $this->assertTrue($result); } @@ -229,19 +229,19 @@ class MemcacheEngineTest extends CakeTestCase { * @return void */ function testDecrement() { - $result = Cache::write('test_decrement', 5); + $result = Cache::write('test_decrement', 5, 'memcache'); $this->assertTrue($result); - $result = Cache::decrement('test_decrement'); + $result = Cache::decrement('test_decrement', 1, 'memcache'); $this->assertEqual(4, $result); - $result = Cache::read('test_decrement'); + $result = Cache::read('test_decrement', 'memcache'); $this->assertEqual(4, $result); - $result = Cache::decrement('test_decrement', 2); + $result = Cache::decrement('test_decrement', 2, 'memcache'); $this->assertEqual(2, $result); - $result = Cache::read('test_decrement'); + $result = Cache::read('test_decrement', 'memcache'); $this->assertEqual(2, $result); } @@ -252,19 +252,19 @@ class MemcacheEngineTest extends CakeTestCase { * @return void */ function testIncrement() { - $result = Cache::write('test_increment', 5); + $result = Cache::write('test_increment', 5, 'memcache'); $this->assertTrue($result); - $result = Cache::increment('test_increment'); + $result = Cache::increment('test_increment', 1, 'memcache'); $this->assertEqual(6, $result); - $result = Cache::read('test_increment'); + $result = Cache::read('test_increment', 'memcache'); $this->assertEqual(6, $result); - $result = Cache::increment('test_increment', 2); + $result = Cache::increment('test_increment', 2, 'memcache'); $this->assertEqual(8, $result); - $result = Cache::read('test_increment'); + $result = Cache::read('test_increment', 'memcache'); $this->assertEqual(8, $result); } From 7518d0e804e758b927cfdad273a35a3649e92e29 Mon Sep 17 00:00:00 2001 From: mark_story Date: Sat, 18 Sep 2010 12:52:08 -0400 Subject: [PATCH 165/166] Removing dead code in Cache. Adding tests for ApcEngine::clear(). --- cake/libs/cache.php | 6 ------ cake/libs/cache/apc.php | 2 +- cake/tests/cases/libs/cache/apc.test.php | 13 +++++++++++++ 3 files changed, 14 insertions(+), 7 deletions(-) diff --git a/cake/libs/cache.php b/cake/libs/cache.php index b674bd390..7f47a7edb 100644 --- a/cake/libs/cache.php +++ b/cake/libs/cache.php @@ -414,12 +414,6 @@ class Cache { * @return boolean True if the cache was succesfully cleared, false otherwise */ public static function clear($check = false, $config = 'default') { - $settings = self::settings($config); - - if (empty($settings)) { - return null; - } - if (!self::isInitialized($config)) { return false; } diff --git a/cake/libs/cache/apc.php b/cake/libs/cache/apc.php index eac2fce8a..653e87c4f 100644 --- a/cake/libs/cache/apc.php +++ b/cake/libs/cache/apc.php @@ -106,7 +106,7 @@ class ApcEngine extends CacheEngine { } /** - * Delete all keys from the cache + * Delete all keys from the cache. This will clear every cache config using APC. * * @return boolean True if the cache was succesfully cleared, false otherwise */ diff --git a/cake/tests/cases/libs/cache/apc.test.php b/cake/tests/cases/libs/cache/apc.test.php index 9d2e81f08..dfd86e47f 100644 --- a/cake/tests/cases/libs/cache/apc.test.php +++ b/cake/tests/cases/libs/cache/apc.test.php @@ -193,4 +193,17 @@ class ApcEngineTest extends CakeTestCase { $result = Cache::read('test_increment', 'apc'); $this->assertEqual(8, $result); } + +/** + * test the clearing of cache keys + * + * @return void + */ + function testClear() { + Cache::write('some_value', 'value', 'apc'); + + $result = Cache::clear(false, 'apc'); + $this->assertTrue($result); + $this->assertFalse(Cache::read('some_value', 'apc')); + } } From 443e5233132e9f2ec31646e2bd9ba65e3f883f8a Mon Sep 17 00:00:00 2001 From: mark_story Date: Sat, 18 Sep 2010 13:15:37 -0400 Subject: [PATCH 166/166] Adding tests for clearing the cache with memcache. --- cake/tests/cases/libs/cache/memcache.test.php | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/cake/tests/cases/libs/cache/memcache.test.php b/cake/tests/cases/libs/cache/memcache.test.php index 61b8e9ad8..819c15476 100644 --- a/cake/tests/cases/libs/cache/memcache.test.php +++ b/cake/tests/cases/libs/cache/memcache.test.php @@ -303,4 +303,16 @@ class MemcacheEngineTest extends CakeTestCase { Cache::delete('short_duration_test', 'short_memcache'); } +/** + * test clearing memcache. + * + * @return void + */ + function testClear() { + Cache::write('some_value', 'value', 'memcache'); + + $result = Cache::clear(false, 'memcache'); + $this->assertTrue($result); + $this->assertFalse(Cache::read('some_value', 'memcache')); + } }