From d526fdadc1de0f612dfc291f7d391f02a6d3a056 Mon Sep 17 00:00:00 2001 From: Joseph Woodruff Date: Wed, 2 Apr 2014 13:58:29 -0600 Subject: [PATCH 1/4] Base model class no longer changes an already defined schemaName value --- lib/Cake/Model/Model.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/Cake/Model/Model.php b/lib/Cake/Model/Model.php index 209b3e7c9..7e230d7d1 100644 --- a/lib/Cake/Model/Model.php +++ b/lib/Cake/Model/Model.php @@ -3485,7 +3485,7 @@ class Model extends Object implements CakeEventListener { $this->tablePrefix = $db->config['prefix']; } - $this->schemaName = $db->getSchemaName(); + $this->schemaName = (empty($this->schemaName) ? $db->getSchemaName() : $this->schemaName); } /** From 85363715010cc572f9bff31b920846a37b5769e5 Mon Sep 17 00:00:00 2001 From: Joseph Woodruff Date: Wed, 2 Apr 2014 13:59:04 -0600 Subject: [PATCH 2/4] Sqlserver Datasource how properly appends the schemaName prefix in the describe() method --- lib/Cake/Model/Datasource/Database/Sqlserver.php | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/lib/Cake/Model/Datasource/Database/Sqlserver.php b/lib/Cake/Model/Datasource/Database/Sqlserver.php index b6b0c4bf2..db7d34212 100644 --- a/lib/Cake/Model/Datasource/Database/Sqlserver.php +++ b/lib/Cake/Model/Datasource/Database/Sqlserver.php @@ -195,26 +195,30 @@ class Sqlserver extends DboSource { * @throws CakeException */ public function describe($model) { - $table = $this->fullTableName($model, false); - $cache = parent::describe($table); + $table = $this->fullTableName($model, false, false); + $fulltable = $this->fullTableName($model, false, true); + + $cache = parent::describe($fulltable); if ($cache) { return $cache; } + $fields = array(); - $table = $this->fullTableName($model, false, false); $schema = $model->schemaName; + $cols = $this->_execute( "SELECT COLUMN_NAME as Field, DATA_TYPE as Type, - COL_LENGTH('" . $table . "', COLUMN_NAME) as Length, + COL_LENGTH('" . ($schema ? $fulltable : $table) . "', COLUMN_NAME) as Length, IS_NULLABLE As [Null], COLUMN_DEFAULT as [Default], - COLUMNPROPERTY(OBJECT_ID('" . $table . "'), COLUMN_NAME, 'IsIdentity') as [Key], + COLUMNPROPERTY(OBJECT_ID('" . ($schema ? $fulltable : $table) . "'), COLUMN_NAME, 'IsIdentity') as [Key], NUMERIC_SCALE as Size FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = '" . $table . "'" . ($schema ? " AND TABLE_SCHEMA = '" . $schema . "'" : '') ); + if (!$cols) { throw new CakeException(__d('cake_dev', 'Could not describe table for %s', $table)); } From db450a96e95c35b9328e33bd992c1dcf5837ffb0 Mon Sep 17 00:00:00 2001 From: Guillaume Lafarge Date: Thu, 10 Apr 2014 20:19:32 +0200 Subject: [PATCH 3/4] Fix Hash type casting When using comparison with a boolean, as the filter is a string, we have to convert the data boolean to "boolean string" to avoid type-casting troubles. ## Example ```php $users = [ [ 'id' => 2, 'username' => 'johndoe', 'active' => true ], [ 'id' => 5, 'username' => 'kevin', 'active' => true ], [ 'id' => 9, 'username' => 'samantha', 'active' => false ], ]; $unactiveUsers = Hash::extract($users, '{n}[active=false]'); print_r($unactiveUsers); ``` This example returns the two unwanted active users because `"false"` is `true` but not `false` :) I think this pull request will fix this issue by converting true/false boolean to string (to match with our filter). --- lib/Cake/Utility/Hash.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/Cake/Utility/Hash.php b/lib/Cake/Utility/Hash.php index 7c9b685f0..b35cad715 100644 --- a/lib/Cake/Utility/Hash.php +++ b/lib/Cake/Utility/Hash.php @@ -192,7 +192,7 @@ class Hash { return false; } - $prop = isset($data[$attr]) ? $data[$attr] : null; + $prop = isset($data[$attr]) ? ( is_bool($data[$attr]) ? (($data[$attr]) ? 'true' : 'false') : $data[$attr] ) : null; // Pattern matches and other operators. if ($op === '=' && $val && $val[0] === '/') { From c6173a0054ca61c2b05c1cd3d1ed6d651ce03618 Mon Sep 17 00:00:00 2001 From: mark_story Date: Thu, 10 Apr 2014 20:37:08 -0400 Subject: [PATCH 4/4] Add tests for #3288 and remove nested ternaries. Nested ternaries are complicated to maintain and hard to read. Break down the nested ternary into two conditionals. --- lib/Cake/Test/Case/Utility/HashTest.php | 33 +++++++++++++++++++++++++ lib/Cake/Utility/Hash.php | 8 +++++- 2 files changed, 40 insertions(+), 1 deletion(-) diff --git a/lib/Cake/Test/Case/Utility/HashTest.php b/lib/Cake/Test/Case/Utility/HashTest.php index 037c6a2a7..65c1a0e39 100644 --- a/lib/Cake/Test/Case/Utility/HashTest.php +++ b/lib/Cake/Test/Case/Utility/HashTest.php @@ -831,6 +831,39 @@ class HashTest extends CakeTestCase { $this->assertEquals(5, $result[3]['id']); } +/** + * Test extracting based on attributes with boolean values. + * + * @return void + */ + public function testExtractAttributeBoolean() { + $users = array( + array( + 'id' => 2, + 'username' => 'johndoe', + 'active' => true + ), + array( + 'id' => 5, + 'username' => 'kevin', + 'active' => true + ), + array( + 'id' => 9, + 'username' => 'samantha', + 'active' => false + ), + ); + $result = Hash::extract($users, '{n}[active=false]'); + $this->assertCount(1, $result); + $this->assertEquals($users[2], $result[0]); + + $result = Hash::extract($users, '{n}[active=true]'); + $this->assertCount(2, $result); + $this->assertEquals($users[0], $result[0]); + $this->assertEquals($users[1], $result[1]); + } + /** * Test that attribute matchers don't cause errors on scalar data. * diff --git a/lib/Cake/Utility/Hash.php b/lib/Cake/Utility/Hash.php index b35cad715..fa22fe8d1 100644 --- a/lib/Cake/Utility/Hash.php +++ b/lib/Cake/Utility/Hash.php @@ -192,7 +192,13 @@ class Hash { return false; } - $prop = isset($data[$attr]) ? ( is_bool($data[$attr]) ? (($data[$attr]) ? 'true' : 'false') : $data[$attr] ) : null; + $prop = null; + if (isset($data[$attr])) { + $prop = $data[$attr]; + } + if ($prop === true || $prop === false) { + $prop = $prop ? 'true' : 'false'; + } // Pattern matches and other operators. if ($op === '=' && $val && $val[0] === '/') {