From 0feb93f7a076116572af65cbb16524d0b5744d62 Mon Sep 17 00:00:00 2001 From: Val Bancer Date: Mon, 5 Sep 2016 21:01:12 +0200 Subject: [PATCH 01/36] added Eclipse paths to gitignore --- .gitignore | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.gitignore b/.gitignore index 349903082..956dacdc7 100644 --- a/.gitignore +++ b/.gitignore @@ -14,6 +14,9 @@ ################################# /nbproject .idea +/.project +/.buildpath +/.settings/ # OS generated files # ###################### From 98cd278c0201f15adc20ebd7d6a0ae8507a34066 Mon Sep 17 00:00:00 2001 From: Val Bancer Date: Mon, 5 Sep 2016 21:28:07 +0200 Subject: [PATCH 02/36] improved performance of insertMulti() in Mysql --- lib/Cake/Model/Datasource/Database/Mysql.php | 53 ++++++++++++++++++ .../Model/Datasource/Database/MysqlTest.php | 56 +++++++++++++++++++ 2 files changed, 109 insertions(+) diff --git a/lib/Cake/Model/Datasource/Database/Mysql.php b/lib/Cake/Model/Datasource/Database/Mysql.php index 21f763dc4..df511767c 100644 --- a/lib/Cake/Model/Datasource/Database/Mysql.php +++ b/lib/Cake/Model/Datasource/Database/Mysql.php @@ -849,4 +849,57 @@ class Mysql extends DboSource { return strpos(strtolower($real), 'unsigned') !== false; } +/** + * Inserts multiple values into a table. Uses a single query in order to insert + * multiple rows. + * + * @param string $table The table being inserted into. + * @param array $fields The array of field/column names being inserted. + * @param array $values The array of values to insert. The values should + * be an array of rows. Each row should have values keyed by the column name. + * Each row must have the values in the same order as $fields. + * @return bool + */ + public function insertMulti($table, $fields, $values) { + $table = $this->fullTableName($table); + $holder = implode(',', array_fill(0, count($fields), '?')); + $fields = implode(', ', array_map(array(&$this, 'name'), $fields)); + $pdoMap = array( + 'integer' => PDO::PARAM_INT, + 'float' => PDO::PARAM_STR, + 'boolean' => PDO::PARAM_BOOL, + 'string' => PDO::PARAM_STR, + 'text' => PDO::PARAM_STR + ); + $columnMap = array(); + $rowHolder = "({$holder})"; + $sql = "INSERT INTO {$table} ({$fields}) VALUES "; + $countRows = count($values); + for ($i = 0; $i < $countRows; $i++) { + if ($i !== 0) { + $sql .= ','; + } + $sql .= " $rowHolder"; + } + $statement = $this->_connection->prepare($sql); + foreach ($values[key($values)] as $key => $val) { + $type = $this->introspectType($val); + $columnMap[$key] = $pdoMap[$type]; + } + $valuesList = array(); + $i = 1; + foreach ($values as $value) { + foreach ($value as $col => $val) { + $valuesList[] = $val; + $statement->bindValue($i, $val, $columnMap[$col]); + $i++; + } + } + $result = $statement->execute(); + $statement->closeCursor(); + if ($this->fullDebug) { + $this->logQuery($sql, $valuesList); + } + return $result; + } } diff --git a/lib/Cake/Test/Case/Model/Datasource/Database/MysqlTest.php b/lib/Cake/Test/Case/Model/Datasource/Database/MysqlTest.php index dcae76f65..ee9c0f57e 100644 --- a/lib/Cake/Test/Case/Model/Datasource/Database/MysqlTest.php +++ b/lib/Cake/Test/Case/Model/Datasource/Database/MysqlTest.php @@ -4174,4 +4174,60 @@ SQL; $this->assertTrue($this->Dbo->isConnected(), 'Should be connected.'); } +/** + * Test insertMulti with id position. + * + * @return void + */ + public function testInsertMultiId() { + $this->loadFixtures('Article'); + $Article = ClassRegistry::init('Article'); + $db = $Article->getDatasource(); + $datetime = date('Y-m-d H:i:s'); + $data = array( + array( + 'user_id' => 1, + 'title' => 'test', + 'body' => 'test', + 'published' => 'N', + 'created' => $datetime, + 'updated' => $datetime, + 'id' => 100, + ), + array( + 'user_id' => 1, + 'title' => 'test 101', + 'body' => 'test 101', + 'published' => 'N', + 'created' => $datetime, + 'updated' => $datetime, + 'id' => 101, + ) + ); + $result = $db->insertMulti('articles', array_keys($data[0]), $data); + $this->assertTrue($result, 'Data was saved'); + + $data = array( + array( + 'id' => 102, + 'user_id' => 1, + 'title' => 'test', + 'body' => 'test', + 'published' => 'N', + 'created' => $datetime, + 'updated' => $datetime, + ), + array( + 'id' => 103, + 'user_id' => 1, + 'title' => 'test 101', + 'body' => 'test 101', + 'published' => 'N', + 'created' => $datetime, + 'updated' => $datetime, + ) + ); + $result = $db->insertMulti('articles', array_keys($data[0]), $data); + $this->assertTrue($result, 'Data was saved'); + } } From 427d928d100c1f6a252285752170a7ed00b82201 Mon Sep 17 00:00:00 2001 From: Val Bancer Date: Mon, 5 Sep 2016 21:53:10 +0200 Subject: [PATCH 03/36] minor code style improvements --- lib/Cake/Model/Datasource/Database/Mysql.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/Cake/Model/Datasource/Database/Mysql.php b/lib/Cake/Model/Datasource/Database/Mysql.php index df511767c..bb6e1d18e 100644 --- a/lib/Cake/Model/Datasource/Database/Mysql.php +++ b/lib/Cake/Model/Datasource/Database/Mysql.php @@ -862,8 +862,8 @@ class Mysql extends DboSource { */ public function insertMulti($table, $fields, $values) { $table = $this->fullTableName($table); - $holder = implode(',', array_fill(0, count($fields), '?')); - $fields = implode(', ', array_map(array(&$this, 'name'), $fields)); + $holder = implode(', ', array_fill(0, count($fields), '?')); + $fields = implode(', ', array_map(array($this, 'name'), $fields)); $pdoMap = array( 'integer' => PDO::PARAM_INT, 'float' => PDO::PARAM_STR, From 5253f0b3bd06f3a1e3cc776e6dd90116a5a108e4 Mon Sep 17 00:00:00 2001 From: Val Bancer Date: Mon, 5 Sep 2016 23:14:43 +0200 Subject: [PATCH 04/36] fixes postLink form last action https://github.com/cakephp/cakephp/issues/9392 --- lib/Cake/View/Helper/FormHelper.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/Cake/View/Helper/FormHelper.php b/lib/Cake/View/Helper/FormHelper.php index 6896e2b76..2ce4edb9a 100644 --- a/lib/Cake/View/Helper/FormHelper.php +++ b/lib/Cake/View/Helper/FormHelper.php @@ -1888,7 +1888,7 @@ class FormHelper extends AppHelper { } $previousLastAction = $this->_lastAction; - $this->_lastAction($url); + $this->_lastAction($formUrl); $out = $this->Html->useTag('form', $formUrl, $formOptions); $out .= $this->Html->useTag('hidden', '_method', array( From d0041f155dcc70a76d0d6e36343a514e9540cbd3 Mon Sep 17 00:00:00 2001 From: mark_story Date: Fri, 9 Sep 2016 23:07:15 -0400 Subject: [PATCH 05/36] Update version number to 2.8.7 --- lib/Cake/VERSION.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/Cake/VERSION.txt b/lib/Cake/VERSION.txt index bbaea6fa9..dc460fe94 100644 --- a/lib/Cake/VERSION.txt +++ b/lib/Cake/VERSION.txt @@ -17,4 +17,4 @@ // @license http://www.opensource.org/licenses/mit-license.php MIT License // +--------------------------------------------------------------------------------------------+ // //////////////////////////////////////////////////////////////////////////////////////////////////// -2.8.6 +2.8.7 From 9d1fbb95b3685677dec101bf3e5a095b8a61d7a2 Mon Sep 17 00:00:00 2001 From: mark_story Date: Mon, 12 Sep 2016 22:15:22 -0400 Subject: [PATCH 06/36] Allow datasource access in constructors of mocked models. When mock objects are created from models that access their datasource in the constructor, an exception would be raised for the missing default datasource. By changing how configuration data is handled in the mock creation we can avoid this issue and not reopen #4867 Refs #8225 --- .../Test/Case/TestSuite/CakeTestCaseTest.php | 26 +++++++++++++++++++ lib/Cake/TestSuite/CakeTestCase.php | 6 ++--- 2 files changed, 29 insertions(+), 3 deletions(-) diff --git a/lib/Cake/Test/Case/TestSuite/CakeTestCaseTest.php b/lib/Cake/Test/Case/TestSuite/CakeTestCaseTest.php index da97150c3..d7b62e190 100644 --- a/lib/Cake/Test/Case/TestSuite/CakeTestCaseTest.php +++ b/lib/Cake/Test/Case/TestSuite/CakeTestCaseTest.php @@ -39,6 +39,22 @@ class SecondaryPost extends Model { } +/** + * ConstructorPost test stub. + */ +class ConstructorPost extends Model { + +/** + * @var string + */ + public $useTable = 'posts'; + + public function __construct($id = false, $table = null, $ds = null) { + parent::__construct($id, $table, $ds); + $this->getDataSource()->cacheMethods = false; + } +} + /** * CakeTestCaseTest * @@ -435,6 +451,16 @@ class CakeTestCaseTest extends CakeTestCase { ConnectionManager::drop('test_secondary'); } +/** + * Test getMockForModel when the model accesses the datasource in the constructor. + * + * @return void + */ + public function testGetMockForModelConstructorDatasource() { + $post = $this->getMockForModel('ConstructorPost', array('save'), array('ds' => 'test')); + $this->assertEquals('test', $post->useDbConfig); + } + /** * test getMockForModel() with plugin models * diff --git a/lib/Cake/TestSuite/CakeTestCase.php b/lib/Cake/TestSuite/CakeTestCase.php index c375717fe..ab04db6a7 100644 --- a/lib/Cake/TestSuite/CakeTestCase.php +++ b/lib/Cake/TestSuite/CakeTestCase.php @@ -718,13 +718,13 @@ abstract class CakeTestCase extends PHPUnit_Framework_TestCase { * @return Model */ public function getMockForModel($model, $methods = array(), $config = array()) { - $config += ClassRegistry::config('Model'); + $defaults = ClassRegistry::config('Model'); + unset($defaults['ds']); list($plugin, $name) = pluginSplit($model, true); App::uses($name, $plugin . 'Model'); - $config = array_merge((array)$config, array('name' => $name)); - unset($config['ds']); + $config = array_merge($defaults, (array)$config, array('name' => $name)); if (!class_exists($name)) { throw new MissingModelException(array($model)); From dc2fa498ef5ad3149f6db8ebafffbb9c2d887614 Mon Sep 17 00:00:00 2001 From: mark_story Date: Mon, 12 Sep 2016 23:19:08 -0400 Subject: [PATCH 07/36] PHPCS. --- lib/Cake/Test/Case/TestSuite/CakeTestCaseTest.php | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/Cake/Test/Case/TestSuite/CakeTestCaseTest.php b/lib/Cake/Test/Case/TestSuite/CakeTestCaseTest.php index d7b62e190..0ea4d6253 100644 --- a/lib/Cake/Test/Case/TestSuite/CakeTestCaseTest.php +++ b/lib/Cake/Test/Case/TestSuite/CakeTestCaseTest.php @@ -53,6 +53,7 @@ class ConstructorPost extends Model { parent::__construct($id, $table, $ds); $this->getDataSource()->cacheMethods = false; } + } /** From 35c6f2c7711509268e312bb2dca5ec09d1bc24cd Mon Sep 17 00:00:00 2001 From: Mark Story Date: Tue, 13 Sep 2016 11:00:32 -0400 Subject: [PATCH 08/36] Revert "CakeFixtureManager: Truncate tables only if not dropped." --- lib/Cake/TestSuite/Fixture/CakeFixtureManager.php | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/lib/Cake/TestSuite/Fixture/CakeFixtureManager.php b/lib/Cake/TestSuite/Fixture/CakeFixtureManager.php index 8d678047f..aa9a43cad 100644 --- a/lib/Cake/TestSuite/Fixture/CakeFixtureManager.php +++ b/lib/Cake/TestSuite/Fixture/CakeFixtureManager.php @@ -98,7 +98,7 @@ class CakeFixtureManager { /** * Parse the fixture path included in test cases, to get the fixture class name, and the * real fixture path including sub-directories - * + * * @param string $fixturePath the fixture path to parse * @return array containing fixture class name and optional additional path */ @@ -218,7 +218,7 @@ class CakeFixtureManager { if (empty($test->fixtures)) { return; } - $fixtures = array_unique($test->fixtures); + $fixtures = $test->fixtures; if (empty($fixtures) || !$test->autoFixtures) { return; } @@ -229,9 +229,7 @@ class CakeFixtureManager { $db = ConnectionManager::getDataSource($fixture->useDbConfig); $db->begin(); $this->_setupTable($fixture, $db, $test->dropTables); - if (!$test->dropTables) { - $fixture->truncate($db); - } + $fixture->truncate($db); $fixture->insert($db); $db->commit(); } @@ -276,9 +274,7 @@ class CakeFixtureManager { $db = ConnectionManager::getDataSource($fixture->useDbConfig); } $this->_setupTable($fixture, $db, $dropTables); - if (!$dropTables) { - $fixture->truncate($db); - } + $fixture->truncate($db); $fixture->insert($db); } else { throw new UnexpectedValueException(__d('cake_dev', 'Referenced fixture class %s not found', $name)); From 109cfbcf95bb9a3883fe179e446c609ecbbf2ac0 Mon Sep 17 00:00:00 2001 From: mark_story Date: Tue, 13 Sep 2016 21:46:28 -0400 Subject: [PATCH 09/36] Fix whitespace. --- lib/Cake/TestSuite/Fixture/CakeFixtureManager.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/Cake/TestSuite/Fixture/CakeFixtureManager.php b/lib/Cake/TestSuite/Fixture/CakeFixtureManager.php index aa9a43cad..a39b75c02 100644 --- a/lib/Cake/TestSuite/Fixture/CakeFixtureManager.php +++ b/lib/Cake/TestSuite/Fixture/CakeFixtureManager.php @@ -98,7 +98,7 @@ class CakeFixtureManager { /** * Parse the fixture path included in test cases, to get the fixture class name, and the * real fixture path including sub-directories - * + * * @param string $fixturePath the fixture path to parse * @return array containing fixture class name and optional additional path */ From 4f70bdb3b8ccab3d0194c6ff9d71cfe251ae8003 Mon Sep 17 00:00:00 2001 From: mark_story Date: Tue, 13 Sep 2016 22:21:01 -0400 Subject: [PATCH 10/36] The _lastAction property should not double include the base path. FormHelper should not run URLs through Router twice when determining the the form's lastAction attribute. However, because we're using the helper method (see #9414) we do need to HTML decode the URL before using it in form token generation. Refs #9455 --- lib/Cake/Test/Case/View/Helper/FormHelperTest.php | 11 +++++++++-- lib/Cake/View/Helper/FormHelper.php | 4 ++-- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/lib/Cake/Test/Case/View/Helper/FormHelperTest.php b/lib/Cake/Test/Case/View/Helper/FormHelperTest.php index 58a4545ab..e3f22c4ae 100644 --- a/lib/Cake/Test/Case/View/Helper/FormHelperTest.php +++ b/lib/Cake/Test/Case/View/Helper/FormHelperTest.php @@ -539,6 +539,7 @@ class FormHelperTest extends CakeTestCase { $this->Form->request['action'] = 'add'; $this->Form->request->webroot = ''; $this->Form->request->base = ''; + Router::setRequestInfo($this->Form->request); ClassRegistry::addObject('Contact', new Contact()); ClassRegistry::addObject('ContactNonStandardPk', new ContactNonStandardPk()); @@ -8191,12 +8192,14 @@ class FormHelperTest extends CakeTestCase { */ public function testPostLinkSecurityHashInline() { $hash = Security::hash( - '/posts/delete/1' . + '/basedir/posts/delete/1' . serialize(array()) . '' . Configure::read('Security.salt') ); $hash .= '%3A'; + $this->Form->request->base = '/basedir'; + $this->Form->request->webroot = '/basedir/'; $this->Form->request->params['_Token']['key'] = 'test'; $this->Form->create('Post', array('url' => array('action' => 'add'))); @@ -8206,7 +8209,11 @@ class FormHelperTest extends CakeTestCase { $this->assertEquals(array('Post.title'), $this->Form->fields); $this->assertContains($hash, $result, 'Should contain the correct hash.'); - $this->assertAttributeEquals('/posts/add', '_lastAction', $this->Form, 'lastAction was should be restored.'); + $this->assertAttributeEquals( + '/basedir/posts/add', + '_lastAction', + $this->Form, + 'lastAction was should be restored.'); } /** diff --git a/lib/Cake/View/Helper/FormHelper.php b/lib/Cake/View/Helper/FormHelper.php index 2ce4edb9a..e64045116 100644 --- a/lib/Cake/View/Helper/FormHelper.php +++ b/lib/Cake/View/Helper/FormHelper.php @@ -1888,7 +1888,7 @@ class FormHelper extends AppHelper { } $previousLastAction = $this->_lastAction; - $this->_lastAction($formUrl); + $this->_lastAction($url); $out = $this->Html->useTag('form', $formUrl, $formOptions); $out .= $this->Html->useTag('hidden', '_method', array( @@ -3105,7 +3105,7 @@ class FormHelper extends AppHelper { * @return void */ protected function _lastAction($url) { - $action = Router::url($url, true); + $action = html_entity_decode($this->url($url), ENT_QUOTES); $query = parse_url($action, PHP_URL_QUERY); $query = $query ? '?' . $query : ''; $this->_lastAction = parse_url($action, PHP_URL_PATH) . $query; From bcb2eaee311cf7499a05231fe645345fe847e73c Mon Sep 17 00:00:00 2001 From: mark_story Date: Wed, 14 Sep 2016 21:40:56 -0400 Subject: [PATCH 11/36] Update version number to 2.8.8 --- lib/Cake/VERSION.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/Cake/VERSION.txt b/lib/Cake/VERSION.txt index dc460fe94..e851cb8b6 100644 --- a/lib/Cake/VERSION.txt +++ b/lib/Cake/VERSION.txt @@ -17,4 +17,4 @@ // @license http://www.opensource.org/licenses/mit-license.php MIT License // +--------------------------------------------------------------------------------------------+ // //////////////////////////////////////////////////////////////////////////////////////////////////// -2.8.7 +2.8.8 From 1b101f73a62ab21193d525cf22866bd41f96c82b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc=20W=C3=BCrth?= Date: Fri, 16 Sep 2016 13:02:55 +0200 Subject: [PATCH 12/36] Minor DocBlock improvement --- lib/Cake/Model/Model.php | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/lib/Cake/Model/Model.php b/lib/Cake/Model/Model.php index 6148317af..e32cd7047 100644 --- a/lib/Cake/Model/Model.php +++ b/lib/Cake/Model/Model.php @@ -473,9 +473,14 @@ class Model extends Object implements CakeEventListener { /** * List of behaviors to load when the model object is initialized. Settings can be - * passed to behaviors by using the behavior name as index. Eg: + * passed to behaviors by using the behavior name as index. * - * public $actsAs = array('Translate', 'MyBehavior' => array('setting1' => 'value1')) + * For example: + * + * public $actsAs = array( + * 'Translate', + * 'MyBehavior' => array('setting1' => 'value1') + * ); * * @var array * @link http://book.cakephp.org/2.0/en/models/behaviors.html#using-behaviors From 835c709dfdd6f866bafb13e1b692ade2adcf8536 Mon Sep 17 00:00:00 2001 From: mark_story Date: Fri, 16 Sep 2016 19:17:08 -0400 Subject: [PATCH 13/36] Add code fencing on example. --- lib/Cake/Model/Model.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/Cake/Model/Model.php b/lib/Cake/Model/Model.php index e32cd7047..92fc48a7a 100644 --- a/lib/Cake/Model/Model.php +++ b/lib/Cake/Model/Model.php @@ -477,10 +477,12 @@ class Model extends Object implements CakeEventListener { * * For example: * + * ``` * public $actsAs = array( * 'Translate', * 'MyBehavior' => array('setting1' => 'value1') * ); + * ``` * * @var array * @link http://book.cakephp.org/2.0/en/models/behaviors.html#using-behaviors From 73dcbf2aa33b79512373baa63b39adf3fb838608 Mon Sep 17 00:00:00 2001 From: mark_story Date: Sun, 18 Sep 2016 22:18:18 -0400 Subject: [PATCH 14/36] Update version number to 2.8.9 --- lib/Cake/VERSION.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/Cake/VERSION.txt b/lib/Cake/VERSION.txt index e851cb8b6..7f256cf7e 100644 --- a/lib/Cake/VERSION.txt +++ b/lib/Cake/VERSION.txt @@ -17,4 +17,4 @@ // @license http://www.opensource.org/licenses/mit-license.php MIT License // +--------------------------------------------------------------------------------------------+ // //////////////////////////////////////////////////////////////////////////////////////////////////// -2.8.8 +2.8.9 From 68abc090ac7f0982e65d00cab5c5fc682d8e0cad Mon Sep 17 00:00:00 2001 From: mark_story Date: Sun, 18 Sep 2016 22:24:05 -0400 Subject: [PATCH 15/36] Rollback version file change. Build tools will fail otherwise. --- lib/Cake/VERSION.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/Cake/VERSION.txt b/lib/Cake/VERSION.txt index 30649bcdd..5f0d2e823 100644 --- a/lib/Cake/VERSION.txt +++ b/lib/Cake/VERSION.txt @@ -17,4 +17,4 @@ // @license http://www.opensource.org/licenses/mit-license.php MIT License // +--------------------------------------------------------------------------------------------+ // //////////////////////////////////////////////////////////////////////////////////////////////////// -2.9.0 +2.9.0-RC1 From 35d04ecb3dcb617ac6eddb109524a76fba3b6688 Mon Sep 17 00:00:00 2001 From: mark_story Date: Sun, 18 Sep 2016 22:24:27 -0400 Subject: [PATCH 16/36] Update version number to 2.9.0 --- lib/Cake/VERSION.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/Cake/VERSION.txt b/lib/Cake/VERSION.txt index 5f0d2e823..30649bcdd 100644 --- a/lib/Cake/VERSION.txt +++ b/lib/Cake/VERSION.txt @@ -17,4 +17,4 @@ // @license http://www.opensource.org/licenses/mit-license.php MIT License // +--------------------------------------------------------------------------------------------+ // //////////////////////////////////////////////////////////////////////////////////////////////////// -2.9.0-RC1 +2.9.0 From 4c9f1cc1543106f5821a1bccfda089eee9aa836f Mon Sep 17 00:00:00 2001 From: Mischa ter Smitten Date: Tue, 20 Sep 2016 15:07:36 +0200 Subject: [PATCH 17/36] _lastAction() should also work with named parameters in the url --- .../Test/Case/View/Helper/FormHelperTest.php | 38 +++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/lib/Cake/Test/Case/View/Helper/FormHelperTest.php b/lib/Cake/Test/Case/View/Helper/FormHelperTest.php index 030333933..1542d93a4 100644 --- a/lib/Cake/Test/Case/View/Helper/FormHelperTest.php +++ b/lib/Cake/Test/Case/View/Helper/FormHelperTest.php @@ -10648,4 +10648,42 @@ class FormHelperTest extends CakeTestCase { $this->assertEquals($expected, $result); } +/** + * Tests `_lastAction`. + * + * With named, numeric value + * + * @return void + */ + public function testLastActionWithNamedNumeric() { + $here = '/users/index/page:1'; + + $this->Form->request->here = $here; + $this->Form->create('User'); + + $expected = $here; + $actual = $this->Form->_lastAction; + + $this->assertEquals($expected, $actual); + } + +/** + * Tests `_lastAction`. + * + * With named, string value + * + * @return void + */ + public function testLastActionWithNamedString() { + $here = '/users/index/foo:bar'; + + $this->Form->request->here = $here; + $this->Form->create('User'); + + $expected = $here; + $actual = $this->Form->_lastAction; + + $this->assertEquals($expected, $actual); + } + } From 197c2f4e60da389547d4054ad99f7a0e908c3578 Mon Sep 17 00:00:00 2001 From: Mischa ter Smitten Date: Thu, 22 Sep 2016 21:30:18 +0200 Subject: [PATCH 18/36] Make use of assertAttributeEquals --- lib/Cake/Test/Case/View/Helper/FormHelperTest.php | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/lib/Cake/Test/Case/View/Helper/FormHelperTest.php b/lib/Cake/Test/Case/View/Helper/FormHelperTest.php index 1542d93a4..81dda0ea3 100644 --- a/lib/Cake/Test/Case/View/Helper/FormHelperTest.php +++ b/lib/Cake/Test/Case/View/Helper/FormHelperTest.php @@ -10661,10 +10661,7 @@ class FormHelperTest extends CakeTestCase { $this->Form->request->here = $here; $this->Form->create('User'); - $expected = $here; - $actual = $this->Form->_lastAction; - - $this->assertEquals($expected, $actual); + $this->assertAttributeEquals($here, '_lastAction', $this->Form, "_lastAction shouldn't be empty."); } /** @@ -10680,10 +10677,7 @@ class FormHelperTest extends CakeTestCase { $this->Form->request->here = $here; $this->Form->create('User'); - $expected = $here; - $actual = $this->Form->_lastAction; - - $this->assertEquals($expected, $actual); + $this->assertAttributeEquals($here, '_lastAction', $this->Form, "_lastAction shouldn't be empty."); } } From 1ccdc21d5b0835ab8d70816fdd0e6db33a8ef6e1 Mon Sep 17 00:00:00 2001 From: Mischa ter Smitten Date: Thu, 22 Sep 2016 21:33:43 +0200 Subject: [PATCH 19/36] Possible fix for _lastAction method --- lib/Cake/View/Helper/FormHelper.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/Cake/View/Helper/FormHelper.php b/lib/Cake/View/Helper/FormHelper.php index 68d6c9347..9133a4c3f 100644 --- a/lib/Cake/View/Helper/FormHelper.php +++ b/lib/Cake/View/Helper/FormHelper.php @@ -3107,7 +3107,7 @@ class FormHelper extends AppHelper { * @return void */ protected function _lastAction($url) { - $action = html_entity_decode($this->url($url), ENT_QUOTES); + $action = html_entity_decode($this->url($url, true), ENT_QUOTES); $query = parse_url($action, PHP_URL_QUERY); $query = $query ? '?' . $query : ''; $this->_lastAction = parse_url($action, PHP_URL_PATH) . $query; From 57bc0f9c457974378b708c79752a4ee1de26c389 Mon Sep 17 00:00:00 2001 From: mark_story Date: Fri, 23 Sep 2016 14:22:10 -0400 Subject: [PATCH 20/36] Ensure Object is autoloaded. When Object was renamed to CakeObject we broke behavior where plugins and app code were relying on Object being configured in the autoloader automatically. Refs cakephp/debug_kit#450 --- lib/Cake/bootstrap.php | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/Cake/bootstrap.php b/lib/Cake/bootstrap.php index 666c1b7ff..bdd8db4b8 100644 --- a/lib/Cake/bootstrap.php +++ b/lib/Cake/bootstrap.php @@ -146,6 +146,7 @@ App::uses('Configure', 'Core'); App::uses('CakePlugin', 'Core'); App::uses('Cache', 'Cache'); App::uses('CakeObject', 'Core'); +App::uses('Object', 'Core'); App::uses('Multibyte', 'I18n'); App::$bootstrapping = true; From e41ccdb701dab0c9fb9add319ffdfc1b7eaed1ef Mon Sep 17 00:00:00 2001 From: mark_story Date: Fri, 30 Sep 2016 22:25:25 -0400 Subject: [PATCH 21/36] Fix enum column length detection. Use simpler code to calculate the length of fields. Include more tests for DboSource as there weren't any before. Refs #9526 --- lib/Cake/Model/Datasource/DboSource.php | 57 ++++++++----------- .../Case/Model/Datasource/DboSourceTest.php | 31 ++++++++++ 2 files changed, 55 insertions(+), 33 deletions(-) diff --git a/lib/Cake/Model/Datasource/DboSource.php b/lib/Cake/Model/Datasource/DboSource.php index f37d6310e..68dd384a4 100644 --- a/lib/Cake/Model/Datasource/DboSource.php +++ b/lib/Cake/Model/Datasource/DboSource.php @@ -3097,54 +3097,45 @@ class DboSource extends DataSource { * @return mixed An integer or string representing the length of the column, or null for unknown length. */ public function length($real) { - if (!preg_match_all('/([\w\s]+)(?:\((\d+)(?:,(\d+))?\))?(\sunsigned)?(\szerofill)?/', $real, $result)) { - $col = str_replace(array(')', 'unsigned'), '', $real); - $limit = null; - - if (strpos($col, '(') !== false) { - list($col, $limit) = explode('(', $col); - } - if ($limit !== null) { - return (int)$limit; - } - return null; - } - + preg_match('/([\w\s]+)(?:\((.+?)\))?(\sunsigned)?/i', $real, $result); $types = array( 'int' => 1, 'tinyint' => 1, 'smallint' => 1, 'mediumint' => 1, 'integer' => 1, 'bigint' => 1 ); - list($real, $type, $length, $offset, $sign) = $result; - $typeArr = $type; - $type = $type[0]; - $length = $length[0]; - $offset = $offset[0]; + $type = $length = null; + if (isset($result[1])) { + $type = $result[1]; + } + if (isset($result[2])) { + $length = $result[2]; + } + $sign = isset($result[3]); $isFloat = in_array($type, array('dec', 'decimal', 'float', 'numeric', 'double')); - if ($isFloat && $offset) { - return $length . ',' . $offset; + if ($isFloat && strpos($length, ',') !== false) { + return $length; } - if (($real[0] == $type) && (count($real) === 1)) { + if ($length === null) { return null; } if (isset($types[$type])) { - $length += $types[$type]; - if (!empty($sign)) { - $length--; - } - } elseif (in_array($type, array('enum', 'set'))) { - $length = 0; - foreach ($typeArr as $key => $enumValue) { - if ($key === 0) { - continue; - } + return (int)$length; + } + if (in_array($type, array('enum', 'set'))) { + $values = array_map(function($value) { + return trim(trim($value), '\'"'); + }, explode(',', $length)); + + $maxLength = 0; + foreach ($values as $key => $enumValue) { $tmpLength = strlen($enumValue); - if ($tmpLength > $length) { - $length = $tmpLength; + if ($tmpLength > $maxLength) { + $maxLength = $tmpLength; } } + return $maxLength; } return (int)$length; } diff --git a/lib/Cake/Test/Case/Model/Datasource/DboSourceTest.php b/lib/Cake/Test/Case/Model/Datasource/DboSourceTest.php index 933cd9347..911faec5c 100644 --- a/lib/Cake/Test/Case/Model/Datasource/DboSourceTest.php +++ b/lib/Cake/Test/Case/Model/Datasource/DboSourceTest.php @@ -1826,4 +1826,35 @@ class DboSourceTest extends CakeTestCase { $this->db->flushQueryCache(); $this->assertAttributeCount(0, '_queryCache', $this->db); } + +/** + * Test length parsing. + * + * @return void + */ + public function testLength() { + $result = $this->db->length('varchar(255)'); + $this->assertEquals(255, $result); + + $result = $this->db->length('integer(11)'); + $this->assertEquals(11, $result); + + $result = $this->db->length('integer unsigned'); + $this->assertNull($result); + + $result = $this->db->length('integer(11) unsigned'); + $this->assertEquals(11, $result); + + $result = $this->db->length('integer(11) zerofill'); + $this->assertEquals(11, $result); + + $result = $this->db->length('decimal(20,3)'); + $this->assertEquals('20,3', $result); + + $result = $this->db->length('enum("one", "longer")'); + $this->assertEquals(6, $result); + + $result = $this->db->length("enum('One Value','ANOTHER ... VALUE ...')"); + $this->assertEquals(21, $result); + } } From 2d6e85ed1460be12388efb2e1b0f3e638371892e Mon Sep 17 00:00:00 2001 From: Andrej Griniuk Date: Mon, 3 Oct 2016 00:23:05 +0800 Subject: [PATCH 22/36] validate table name before generating schema file --- lib/Cake/Model/CakeSchema.php | 6 ++++++ lib/Cake/Test/Case/Model/CakeSchemaTest.php | 16 ++++++++++++++++ 2 files changed, 22 insertions(+) diff --git a/lib/Cake/Model/CakeSchema.php b/lib/Cake/Model/CakeSchema.php index 74c9e4ac4..529ceb5f8 100644 --- a/lib/Cake/Model/CakeSchema.php +++ b/lib/Cake/Model/CakeSchema.php @@ -405,8 +405,14 @@ class CakeSchema extends CakeObject { * @param string $table Table name you want returned. * @param array $fields Array of field information to generate the table with. * @return string Variable declaration for a schema class. + * @throws Exception */ public function generateTable($table, $fields) { + // Valid var name regex (http://www.php.net/manual/en/language.variables.basics.php) + if (!preg_match('/^[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*$/', $table)) { + throw new Exception("Invalid table name '{$table}'"); + } + $out = "\tpublic \${$table} = array(\n"; if (is_array($fields)) { $cols = array(); diff --git a/lib/Cake/Test/Case/Model/CakeSchemaTest.php b/lib/Cake/Test/Case/Model/CakeSchemaTest.php index eb2a64a82..aedb6ef3d 100644 --- a/lib/Cake/Test/Case/Model/CakeSchemaTest.php +++ b/lib/Cake/Test/Case/Model/CakeSchemaTest.php @@ -686,6 +686,22 @@ class CakeSchemaTest extends CakeTestCase { $this->assertRegExp('/\'type\' \=\> \'fulltext\'/', $result); } +/** + * test that tables with unsupported name are not getting through + * + * @return void + */ + public function testGenerateInvalidTable() { + $invalidTableName = 'invalid name !@#$%^&*()'; + $expectedException = "Invalid table name '{$invalidTableName}'"; + try{ + $this->Schema->generateTable($invalidTableName, array()); + $this->fail("Expected exception \"{$expectedException}\" not thrown"); + } catch (Exception $e) { + $this->assertEquals($expectedException, $e->getMessage()); + } + } + /** * testSchemaWrite method * From 3587ac99762977d8666d28e86ef8dfff3b1ea816 Mon Sep 17 00:00:00 2001 From: mark_story Date: Sun, 2 Oct 2016 19:06:10 -0400 Subject: [PATCH 23/36] Fix PHPCS error. --- lib/Cake/Model/Datasource/DboSource.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/Cake/Model/Datasource/DboSource.php b/lib/Cake/Model/Datasource/DboSource.php index 68dd384a4..a73eea8a7 100644 --- a/lib/Cake/Model/Datasource/DboSource.php +++ b/lib/Cake/Model/Datasource/DboSource.php @@ -3124,7 +3124,7 @@ class DboSource extends DataSource { return (int)$length; } if (in_array($type, array('enum', 'set'))) { - $values = array_map(function($value) { + $values = array_map(function ($value) { return trim(trim($value), '\'"'); }, explode(',', $length)); From 3a185f9713970b45f7bfd54ef8b66bb28cc5f48c Mon Sep 17 00:00:00 2001 From: mark_story Date: Sun, 2 Oct 2016 19:12:34 -0400 Subject: [PATCH 24/36] Remove incorrrect postgres implementation. It was wrong, and no longer really needs to exist as the parent method covers all the scenarios that were previously required other than the uuid one. --- lib/Cake/Model/Datasource/Database/Postgres.php | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/lib/Cake/Model/Datasource/Database/Postgres.php b/lib/Cake/Model/Datasource/Database/Postgres.php index dfe5272ec..152a9b405 100644 --- a/lib/Cake/Model/Datasource/Database/Postgres.php +++ b/lib/Cake/Model/Datasource/Database/Postgres.php @@ -727,19 +727,13 @@ class Postgres extends DboSource { * @return int An integer representing the length of the column */ public function length($real) { - $col = str_replace(array(')', 'unsigned'), '', $real); - $limit = null; - if (strpos($col, '(') !== false) { list($col, $limit) = explode('(', $col); } if ($col === 'uuid') { return 36; } - if ($limit) { - return (int)$limit; - } - return null; + return parent::length($real); } /** From 689d516a9956852e0e611a1228efc6fb8da5219a Mon Sep 17 00:00:00 2001 From: mark_story Date: Tue, 4 Oct 2016 21:38:26 -0400 Subject: [PATCH 25/36] Fix typo. --- lib/Cake/Model/Datasource/Database/Postgres.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/Cake/Model/Datasource/Database/Postgres.php b/lib/Cake/Model/Datasource/Database/Postgres.php index 152a9b405..7c0e58278 100644 --- a/lib/Cake/Model/Datasource/Database/Postgres.php +++ b/lib/Cake/Model/Datasource/Database/Postgres.php @@ -727,10 +727,10 @@ class Postgres extends DboSource { * @return int An integer representing the length of the column */ public function length($real) { - if (strpos($col, '(') !== false) { - list($col, $limit) = explode('(', $col); + if (strpos($real, '(') !== false) { + list($real, $limit) = explode('(', $real); } - if ($col === 'uuid') { + if ($real === 'uuid') { return 36; } return parent::length($real); From 9c3b17cbc71dbfd7f936c48ecfd3c7b1f00ea5d0 Mon Sep 17 00:00:00 2001 From: mark_story Date: Wed, 5 Oct 2016 22:28:51 -0400 Subject: [PATCH 26/36] Fix failing test in postgres. --- lib/Cake/Model/Datasource/Database/Postgres.php | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/lib/Cake/Model/Datasource/Database/Postgres.php b/lib/Cake/Model/Datasource/Database/Postgres.php index 7c0e58278..8673fbc5c 100644 --- a/lib/Cake/Model/Datasource/Database/Postgres.php +++ b/lib/Cake/Model/Datasource/Database/Postgres.php @@ -727,10 +727,11 @@ class Postgres extends DboSource { * @return int An integer representing the length of the column */ public function length($real) { + $col = $real; if (strpos($real, '(') !== false) { - list($real, $limit) = explode('(', $real); + list($col, $limit) = explode('(', $real); } - if ($real === 'uuid') { + if ($col === 'uuid') { return 36; } return parent::length($real); From bf908762db80c39eb22a73a2dbde42c018e1b676 Mon Sep 17 00:00:00 2001 From: Mark Sch Date: Fri, 7 Oct 2016 01:35:26 +0200 Subject: [PATCH 27/36] Remove dead code --- lib/Cake/Console/ShellDispatcher.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/Cake/Console/ShellDispatcher.php b/lib/Cake/Console/ShellDispatcher.php index d53851127..37aa30037 100644 --- a/lib/Cake/Console/ShellDispatcher.php +++ b/lib/Cake/Console/ShellDispatcher.php @@ -134,7 +134,7 @@ class ShellDispatcher { if (!defined('TMP') && !is_dir(APP . 'tmp')) { define('TMP', CAKE_CORE_INCLUDE_PATH . DS . 'Cake' . DS . 'Console' . DS . 'Templates' . DS . 'skel' . DS . 'tmp' . DS); } - $boot = file_exists(ROOT . DS . APP_DIR . DS . 'Config' . DS . 'bootstrap.php'); + require CORE_PATH . 'Cake' . DS . 'bootstrap.php'; if (!file_exists(APP . 'Config' . DS . 'core.php')) { From a35eec3f1baf0a82326d7250a5d7a0f086c14837 Mon Sep 17 00:00:00 2001 From: Mark Sch Date: Fri, 7 Oct 2016 12:25:24 +0200 Subject: [PATCH 28/36] Fix broken template --- app/View/Elements/Flash/default.ctp | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/app/View/Elements/Flash/default.ctp b/app/View/Elements/Flash/default.ctp index 4a86b69ac..96d4cbc37 100755 --- a/app/View/Elements/Flash/default.ctp +++ b/app/View/Elements/Flash/default.ctp @@ -1,15 +1 @@ -/** -* CakePHP(tm) : Rapid Development Framework (http://cakephp.org) -* Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org) -* -* Licensed under The MIT License -* For full copyright and license information, please see the LICENSE.txt -* Redistributions of files must retain the above copyright notice. -* -* @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org) -* @link http://cakephp.org CakePHP(tm) Project -* @package app.View.Emails.html -* @since CakePHP(tm) v 0.10.0.1076 -* @license http://www.opensource.org/licenses/mit-license.php MIT License -*/
From a932bce3de14b7157c9f2d1b1d8a7508612e7784 Mon Sep 17 00:00:00 2001 From: David Maicher Date: Sun, 9 Oct 2016 13:43:27 +0200 Subject: [PATCH 29/36] [Bugfix] use Model::$cacheQueries as default for ->query(...) --- lib/Cake/Model/Model.php | 6 ++ lib/Cake/Test/Case/Model/ModelReadTest.php | 90 +++++++++++++++++++++- 2 files changed, 93 insertions(+), 3 deletions(-) diff --git a/lib/Cake/Model/Model.php b/lib/Cake/Model/Model.php index 53368d4a1..309cf213a 100644 --- a/lib/Cake/Model/Model.php +++ b/lib/Cake/Model/Model.php @@ -3453,12 +3453,18 @@ class Model extends CakeObject implements CakeEventListener { * - 3rd param: If 2nd argument is provided, a boolean flag for enabling/disabled * query caching. * + * If the query cache param as 2nd or 3rd argument is not given then the model's default $cacheQueries value is used. + * * @param string $sql SQL statement * @return mixed Resultset array or boolean indicating success / failure depending on the query executed * @link http://book.cakephp.org/2.0/en/models/retrieving-your-data.html#model-query */ public function query($sql) { $params = func_get_args(); + // use $this->cacheQueries as default when argument not explicitly given already + if (count($params) === 1 || count($params) === 2 && !is_bool($params[1])) { + $params[] = $this->cacheQueries; + } $db = $this->getDataSource(); return call_user_func_array(array(&$db, 'query'), $params); } diff --git a/lib/Cake/Test/Case/Model/ModelReadTest.php b/lib/Cake/Test/Case/Model/ModelReadTest.php index dd8f92b58..2c63bebd2 100644 --- a/lib/Cake/Test/Case/Model/ModelReadTest.php +++ b/lib/Cake/Test/Case/Model/ModelReadTest.php @@ -403,7 +403,7 @@ class ModelReadTest extends BaseModelTest { $query .= '.id = ? AND ' . $this->db->fullTableName('articles') . '.published = ?'; $params = array(1, 'Y'); - $result = $Article->query($query, $params); + $result = $Article->query($query, $params, true); $expected = array( '0' => array( $this->db->fullTableName('articles', false, false) => array( @@ -438,7 +438,7 @@ class ModelReadTest extends BaseModelTest { $query .= ' WHERE ' . $this->db->fullTableName('articles') . '.title LIKE ?'; $params = array('%First%'); - $result = $Article->query($query, $params); + $result = $Article->query($query, $params, true); $this->assertTrue(is_array($result)); $this->assertTrue( isset($result[0][$this->db->fullTableName('articles', false, false)]['title']) || @@ -449,7 +449,7 @@ class ModelReadTest extends BaseModelTest { $query = 'SELECT title FROM '; $query .= $this->db->fullTableName('articles') . ' WHERE title = ? AND published = ?'; $params = array('First? Article', 'Y'); - $Article->query($query, $params); + $Article->query($query, $params, true); $result = $this->db->getQueryCache($query, $params); $this->assertFalse($result === false); @@ -8531,4 +8531,88 @@ class ModelReadTest extends BaseModelTest { ); $this->assertEquals($expected, $results, 'Model related with belongsTo afterFind callback fails'); } + + public static function extractUserNameFromQueryResult(array $result) { + return isset($result[0][0]) ? $result[0][0]['user'] : $result[0]['u']['user']; + } + + public function testQueryRespectsCacheQueriesAsSecondArgument() { + $model = new User(); + $model->save(array('user' => 'Chuck')); + $userTableName = $this->db->fullTableName('users'); + + $getUserNameFromDb = function ($cacheArgument) use ($model, $userTableName) { + $query = sprintf('SELECT u.user FROM %s u WHERE id=%d', $userTableName, $model->id); + $users = $model->query($query, $cacheArgument); + return ModelReadTest::extractUserNameFromQueryResult($users); + }; + + $model->cacheQueries = true; + $this->assertSame('Chuck', $getUserNameFromDb(true)); + $this->assertSame('Chuck', $getUserNameFromDb(false)); + + $model->updateAll(array('User.user' => "'Sylvester'"), array('User.id' => $model->id)); + + $model->cacheQueries = false; + $this->assertSame('Chuck', $getUserNameFromDb(true)); + $this->assertSame('Sylvester', $getUserNameFromDb(false)); + } + + public function testQueryRespectsCacheQueriesAsThirdArgument() { + $model = new User(); + $model->save(array('user' => 'Chuck')); + $userTableName = $this->db->fullTableName('users'); + + $getUserNameFromDb = function ($cacheArgument) use ($model, $userTableName) { + $query = sprintf('SELECT u.user FROM %s u WHERE id=?', $userTableName); + $users = $model->query($query, array($model->id), $cacheArgument); + return ModelReadTest::extractUserNameFromQueryResult($users); + }; + + $model->cacheQueries = true; + $this->assertSame('Chuck', $getUserNameFromDb(true)); + $this->assertSame('Chuck', $getUserNameFromDb(false)); + $model->updateAll(array('User.user' => "'Sylvester'"), array('User.id' => $model->id)); + $model->cacheQueries = false; + $this->assertSame('Chuck', $getUserNameFromDb(true)); + $this->assertSame('Sylvester', $getUserNameFromDb(false)); + } + + public function testQueryTakesModelCacheQueriesValueAsDefaultForOneArgument() { + $model = new User(); + $model->save(array('user' => 'Chuck')); + $userTableName = $this->db->fullTableName('users'); + + $getUserNameFromDb = function () use ($model, $userTableName) { + $query = sprintf('SELECT u.user FROM %s u WHERE id=%d', $userTableName, $model->id); + $users = $model->query($query); + return ModelReadTest::extractUserNameFromQueryResult($users); + }; + + $model->cacheQueries = true; + $this->assertSame('Chuck', $getUserNameFromDb()); + $model->updateAll(array('User.user' => "'Sylvester'"), array('User.id' => $model->id)); + $this->assertSame('Chuck', $getUserNameFromDb()); + $model->cacheQueries = false; + $this->assertSame('Sylvester', $getUserNameFromDb()); + } + + public function testQueryTakesModelCacheQueriesValueAsDefaultForTwoArguments() { + $model = new User(); + $model->save(array('user' => 'Chuck')); + $userTableName = $this->db->fullTableName('users'); + + $getUserNameFromDb = function () use ($model, $userTableName) { + $query = sprintf('SELECT u.user FROM %s u WHERE id=?', $userTableName); + $users = $model->query($query, array($model->id)); + return ModelReadTest::extractUserNameFromQueryResult($users); + }; + + $model->cacheQueries = true; + $this->assertSame('Chuck', $getUserNameFromDb()); + $model->updateAll(array('User.user' => "'Sylvester'"), array('User.id' => $model->id)); + $this->assertSame('Chuck', $getUserNameFromDb()); + $model->cacheQueries = false; + $this->assertSame('Sylvester', $getUserNameFromDb()); + } } From ecd270d04b19f98cf96322f97ad0df63a5eff023 Mon Sep 17 00:00:00 2001 From: mark_story Date: Sun, 9 Oct 2016 11:05:35 -0400 Subject: [PATCH 30/36] Tweak/Add doc blocks. --- lib/Cake/Model/Model.php | 3 +- lib/Cake/Test/Case/Model/ModelReadTest.php | 32 +++++++++++++++++++++- 2 files changed, 33 insertions(+), 2 deletions(-) diff --git a/lib/Cake/Model/Model.php b/lib/Cake/Model/Model.php index 309cf213a..dff60b57e 100644 --- a/lib/Cake/Model/Model.php +++ b/lib/Cake/Model/Model.php @@ -3453,7 +3453,8 @@ class Model extends CakeObject implements CakeEventListener { * - 3rd param: If 2nd argument is provided, a boolean flag for enabling/disabled * query caching. * - * If the query cache param as 2nd or 3rd argument is not given then the model's default $cacheQueries value is used. + * If the query cache param as 2nd or 3rd argument is not given then the model's + * default `$cacheQueries` value is used. * * @param string $sql SQL statement * @return mixed Resultset array or boolean indicating success / failure depending on the query executed diff --git a/lib/Cake/Test/Case/Model/ModelReadTest.php b/lib/Cake/Test/Case/Model/ModelReadTest.php index 2c63bebd2..7723a8cfc 100644 --- a/lib/Cake/Test/Case/Model/ModelReadTest.php +++ b/lib/Cake/Test/Case/Model/ModelReadTest.php @@ -8532,10 +8532,21 @@ class ModelReadTest extends BaseModelTest { $this->assertEquals($expected, $results, 'Model related with belongsTo afterFind callback fails'); } +/** + * Pull out the username from a result set. + * + * @param array $result The results. + * @return string The username. + */ public static function extractUserNameFromQueryResult(array $result) { return isset($result[0][0]) ? $result[0][0]['user'] : $result[0]['u']['user']; } +/** + * Test that query() doesn't override the 2nd argument with a default. + * + * @return void + */ public function testQueryRespectsCacheQueriesAsSecondArgument() { $model = new User(); $model->save(array('user' => 'Chuck')); @@ -8552,12 +8563,17 @@ class ModelReadTest extends BaseModelTest { $this->assertSame('Chuck', $getUserNameFromDb(false)); $model->updateAll(array('User.user' => "'Sylvester'"), array('User.id' => $model->id)); - $model->cacheQueries = false; $this->assertSame('Chuck', $getUserNameFromDb(true)); $this->assertSame('Sylvester', $getUserNameFromDb(false)); } +/** + * Test that query() doesn't override the cache param in the 3nd argument + * with a default. + * + * @return void + */ public function testQueryRespectsCacheQueriesAsThirdArgument() { $model = new User(); $model->save(array('user' => 'Chuck')); @@ -8572,12 +8588,18 @@ class ModelReadTest extends BaseModelTest { $model->cacheQueries = true; $this->assertSame('Chuck', $getUserNameFromDb(true)); $this->assertSame('Chuck', $getUserNameFromDb(false)); + $model->updateAll(array('User.user' => "'Sylvester'"), array('User.id' => $model->id)); $model->cacheQueries = false; $this->assertSame('Chuck', $getUserNameFromDb(true)); $this->assertSame('Sylvester', $getUserNameFromDb(false)); } +/** + * Test that query() uses the cacheQueries property when there is one argument. + * + * @return void + */ public function testQueryTakesModelCacheQueriesValueAsDefaultForOneArgument() { $model = new User(); $model->save(array('user' => 'Chuck')); @@ -8592,11 +8614,17 @@ class ModelReadTest extends BaseModelTest { $model->cacheQueries = true; $this->assertSame('Chuck', $getUserNameFromDb()); $model->updateAll(array('User.user' => "'Sylvester'"), array('User.id' => $model->id)); + $this->assertSame('Chuck', $getUserNameFromDb()); $model->cacheQueries = false; $this->assertSame('Sylvester', $getUserNameFromDb()); } +/** + * Test that query() uses the cacheQueries property when there are two arguments. + * + * @return void + */ public function testQueryTakesModelCacheQueriesValueAsDefaultForTwoArguments() { $model = new User(); $model->save(array('user' => 'Chuck')); @@ -8610,8 +8638,10 @@ class ModelReadTest extends BaseModelTest { $model->cacheQueries = true; $this->assertSame('Chuck', $getUserNameFromDb()); + $model->updateAll(array('User.user' => "'Sylvester'"), array('User.id' => $model->id)); $this->assertSame('Chuck', $getUserNameFromDb()); + $model->cacheQueries = false; $this->assertSame('Sylvester', $getUserNameFromDb()); } From 6cdf38c2ef5798692ed9fb22221527b9f4210d19 Mon Sep 17 00:00:00 2001 From: mark_story Date: Mon, 10 Oct 2016 21:36:32 -0400 Subject: [PATCH 31/36] Update version number to 2.9.1 --- lib/Cake/VERSION.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/Cake/VERSION.txt b/lib/Cake/VERSION.txt index 30649bcdd..301ac6ed0 100644 --- a/lib/Cake/VERSION.txt +++ b/lib/Cake/VERSION.txt @@ -17,4 +17,4 @@ // @license http://www.opensource.org/licenses/mit-license.php MIT License // +--------------------------------------------------------------------------------------------+ // //////////////////////////////////////////////////////////////////////////////////////////////////// -2.9.0 +2.9.1 From 8baf193995682ea282944697c93004d25a1696f1 Mon Sep 17 00:00:00 2001 From: mark_story Date: Tue, 11 Oct 2016 16:59:35 -0400 Subject: [PATCH 32/36] Fix warning in PHP 7.1 Refs #9592 --- lib/Cake/View/Helper/PaginatorHelper.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/Cake/View/Helper/PaginatorHelper.php b/lib/Cake/View/Helper/PaginatorHelper.php index 5744d83b1..917eb7f7f 100644 --- a/lib/Cake/View/Helper/PaginatorHelper.php +++ b/lib/Cake/View/Helper/PaginatorHelper.php @@ -946,7 +946,7 @@ class PaginatorHelper extends AppHelper { unset($options['tag'], $options['before'], $options['model'], $options['separator'], $options['ellipsis'], $options['class']); $out = ''; - $lower = $params['pageCount'] - $last + 1; + $lower = $params['pageCount'] - (int)$last + 1; if ((is_int($last) || ctype_digit($last)) && $params['page'] <= $lower) { if ($before === null) { From 1c37640678c7eab5a575f905a33c3f350d97057d Mon Sep 17 00:00:00 2001 From: TekkCraft Date: Wed, 12 Oct 2016 14:35:08 +0200 Subject: [PATCH 33/36] Add connectOptions to doc block --- lib/Cake/Routing/Router.php | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/Cake/Routing/Router.php b/lib/Cake/Routing/Router.php index 83de88feb..b464728c8 100644 --- a/lib/Cake/Routing/Router.php +++ b/lib/Cake/Routing/Router.php @@ -523,6 +523,7 @@ class Router { * - 'id' - The regular expression fragment to use when matching IDs. By default, matches * integer values and UUIDs. * - 'prefix' - URL prefix to use for the generated routes. Defaults to '/'. + * - 'connectOptions' – Custom options for connecting the routes. * * @param string|array $controller A controller name or array of controller names (i.e. "Posts" or "ListItems") * @param array $options Options to use when generating REST routes From 816801902eb30d5a44ca1580e17df7f27acb30d4 Mon Sep 17 00:00:00 2001 From: mark_story Date: Fri, 21 Oct 2016 10:54:39 -0400 Subject: [PATCH 34/36] Allow '' to be a valid key for Hash, and Session By removing a bunch of empty() guards we can make '' behave like all the other key names. This does change the existing behavior/tests around '' key, but I think that is ok given the need to manipulate ''. Refs #9632 --- lib/Cake/Model/Datasource/CakeSession.php | 10 ++++---- .../Case/Model/Datasource/CakeSessionTest.php | 23 +++++++++++++++---- lib/Cake/Test/Case/Utility/HashTest.php | 14 +++++++++++ lib/Cake/Utility/Hash.php | 2 +- 4 files changed, 39 insertions(+), 10 deletions(-) diff --git a/lib/Cake/Model/Datasource/CakeSession.php b/lib/Cake/Model/Datasource/CakeSession.php index 4a25f67c8..9b60fe761 100644 --- a/lib/Cake/Model/Datasource/CakeSession.php +++ b/lib/Cake/Model/Datasource/CakeSession.php @@ -230,9 +230,12 @@ class CakeSession { * @return bool True if variable is there */ public static function check($name) { - if (empty($name) || !static::_hasSession() || !static::start()) { + if (!static::_hasSession() || !static::start()) { return false; } + if (isset($_SESSION[$name])) { + return true; + } return Hash::get($_SESSION, $name) !== null; } @@ -380,9 +383,6 @@ class CakeSession { * session not started, or provided name not found in the session, false on failure. */ public static function read($name = null) { - if (empty($name) && $name !== null) { - return null; - } if (!static::_hasSession() || !static::start()) { return null; } @@ -418,7 +418,7 @@ class CakeSession { * @return bool True if the write was successful, false if the write failed */ public static function write($name, $value = null) { - if (empty($name) || !static::start()) { + if (!static::start()) { return false; } diff --git a/lib/Cake/Test/Case/Model/Datasource/CakeSessionTest.php b/lib/Cake/Test/Case/Model/Datasource/CakeSessionTest.php index d6cd59fa7..13371a946 100644 --- a/lib/Cake/Test/Case/Model/Datasource/CakeSessionTest.php +++ b/lib/Cake/Test/Case/Model/Datasource/CakeSessionTest.php @@ -307,9 +307,9 @@ class CakeSessionTest extends CakeTestCase { * @return void */ public function testWriteEmptyKey() { - $this->assertFalse(TestCakeSession::write('', 'graham')); - $this->assertFalse(TestCakeSession::write('', '')); - $this->assertFalse(TestCakeSession::write('')); + $this->assertTrue(TestCakeSession::write('', 'graham')); + $this->assertTrue(TestCakeSession::write('', '')); + $this->assertTrue(TestCakeSession::write('')); } /** @@ -403,6 +403,17 @@ class CakeSessionTest extends CakeTestCase { $this->assertFalse(TestCakeSession::check('Clearing')); } +/** + * test delete + * + * @return void + */ + public function testDeleteEmptyString() { + TestCakeSession::write('', 'empty string'); + $this->assertTrue(TestCakeSession::delete('')); + $this->assertFalse(TestCakeSession::check('')); + } + /** * testClear method * @@ -500,6 +511,10 @@ class CakeSessionTest extends CakeTestCase { * @return void */ public function testReadingSavedEmpty() { + TestCakeSession::write('', 'empty string'); + $this->assertTrue(TestCakeSession::check('')); + $this->assertEquals('empty string', TestCakeSession::read('')); + TestCakeSession::write('SessionTestCase', 0); $this->assertEquals(0, TestCakeSession::read('SessionTestCase')); @@ -511,7 +526,7 @@ class CakeSessionTest extends CakeTestCase { $this->assertFalse(TestCakeSession::read('SessionTestCase')); TestCakeSession::write('SessionTestCase', null); - $this->assertEquals(null, TestCakeSession::read('SessionTestCase')); + $this->assertNull(TestCakeSession::read('SessionTestCase')); } /** diff --git a/lib/Cake/Test/Case/Utility/HashTest.php b/lib/Cake/Test/Case/Utility/HashTest.php index a5a577e96..318a3538e 100644 --- a/lib/Cake/Test/Case/Utility/HashTest.php +++ b/lib/Cake/Test/Case/Utility/HashTest.php @@ -229,6 +229,20 @@ class HashTest extends CakeTestCase { $this->assertEquals($data[1]['Article'], $result); } +/** + * Test that get() can extract '' key data. + * + * @return void + */ + public function testGetEmptyKey() + { + $data = array( + '' => 'some value' + ); + $result = Hash::get($data, ''); + $this->assertSame($data[''], $result); + } + /** * Test get() with an invalid path * diff --git a/lib/Cake/Utility/Hash.php b/lib/Cake/Utility/Hash.php index 1c6e0bf27..2ca530ece 100644 --- a/lib/Cake/Utility/Hash.php +++ b/lib/Cake/Utility/Hash.php @@ -43,7 +43,7 @@ class Hash { * @link http://book.cakephp.org/2.0/en/core-utility-libraries/hash.html#Hash::get */ public static function get(array $data, $path, $default = null) { - if (empty($data) || $path === '' || $path === null) { + if (empty($data) || $path === null) { return $default; } if (is_string($path) || is_numeric($path)) { From c935bed8f6c3e5d4b9f2aefe539eb87f89510476 Mon Sep 17 00:00:00 2001 From: mark_story Date: Fri, 21 Oct 2016 18:35:05 -0400 Subject: [PATCH 35/36] Fix PHPCS --- lib/Cake/Test/Case/Utility/HashTest.php | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/lib/Cake/Test/Case/Utility/HashTest.php b/lib/Cake/Test/Case/Utility/HashTest.php index 318a3538e..53b1d40c8 100644 --- a/lib/Cake/Test/Case/Utility/HashTest.php +++ b/lib/Cake/Test/Case/Utility/HashTest.php @@ -234,8 +234,7 @@ class HashTest extends CakeTestCase { * * @return void */ - public function testGetEmptyKey() - { + public function testGetEmptyKey() { $data = array( '' => 'some value' ); From 6bae308778689d8b1be84e3774486caea123486c Mon Sep 17 00:00:00 2001 From: Alex Date: Sat, 22 Oct 2016 20:22:21 -0700 Subject: [PATCH 36/36] Update CakePHP version to 2.9 --- app/composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/composer.json b/app/composer.json index e05128e72..bf5c67cc8 100644 --- a/app/composer.json +++ b/app/composer.json @@ -23,7 +23,7 @@ }, "require-dev": { "phpunit/phpunit": "3.7.*", - "cakephp/cakephp": "~2.8" + "cakephp/cakephp": "~2.9" }, "suggest": { "cakephp/cakephp-codesniffer": "Easily check code formatting against the CakePHP coding standards."