From 8eade1adb3a600e6811e3d2b4141a2478632c94a Mon Sep 17 00:00:00 2001 From: nate Date: Wed, 17 Dec 2008 04:13:45 +0000 Subject: [PATCH] Fixing code formatting to wrap at 100 characters, adding fix for ticket #5596, counterCache now decrements properly when foreign key value changes. git-svn-id: https://svn.cakephp.org/repo/branches/1.2.x.x@7927 3807eeeb-6ff5-0310-8944-8be069107fe0 --- cake/libs/configure.php | 47 +++-- cake/libs/model/connection_manager.php | 3 +- cake/libs/model/model.php | 104 +++++++--- cake/libs/set.php | 4 +- cake/tests/cases/libs/model/model.test.php | 103 ++++++++-- cake/tests/cases/libs/model/models.php | 36 +++- cake/tests/cases/libs/set.test.php | 179 +++++++++++++++--- .../fixtures/counter_cache_post_fixture.php | 50 +++++ .../fixtures/counter_cache_user_fixture.php | 49 +++++ 9 files changed, 483 insertions(+), 92 deletions(-) create mode 100644 cake/tests/fixtures/counter_cache_post_fixture.php create mode 100644 cake/tests/fixtures/counter_cache_user_fixture.php diff --git a/cake/libs/configure.php b/cake/libs/configure.php index c8ae0e31c..f600b1772 100644 --- a/cake/libs/configure.php +++ b/cake/libs/configure.php @@ -249,8 +249,14 @@ class Configure extends Object { * Usage * Configure::write('One.key1', 'value of the Configure::One[key1]'); * Configure::write(array('One.key1' => 'value of the Configure::One[key1]')); - * Configure::write('One', array('key1'=>'value of the Configure::One[key1]', 'key2'=>'value of the Configure::One[key2]'); - * Configure::write(array('One.key1' => 'value of the Configure::One[key1]', 'One.key2' => 'value of the Configure::One[key2]')); + * Configure::write('One', array( + * 'key1' => 'value of the Configure::One[key1]', + * 'key2' => 'value of the Configure::One[key2]' + * ); + * Configure::write(array( + * 'One.key1' => 'value of the Configure::One[key1]', + * 'One.key2' => 'value of the Configure::One[key2]' + * )); * * @link http://book.cakephp.org/view/412/write * @param array $config Name of var to write @@ -379,7 +385,8 @@ class Configure extends Object { * Usage Configure::load('configure_file'); * * @link http://book.cakephp.org/view/415/load - * @param string $fileName name of file to load, extension must be .php and only the name should be used, not the extenstion + * @param string $fileName name of file to load, extension must be .php and only the name + * should be used, not the extenstion * @return mixed false if file not found, void if load successful * @access public */ @@ -407,7 +414,8 @@ class Configure extends Object { } if (!isset($config)) { - trigger_error(sprintf(__("Configure::load() - no variable \$config found in %s.php", true), $fileName), E_USER_WARNING); + $error = __("Configure::load() - no variable \$config found in %s.php", true); + trigger_error(sprintf($error, $fileName), E_USER_WARNING); return false; } return Configure::write($config); @@ -433,7 +441,9 @@ class Configure extends Object { /** * Used to write a config file to disk. * - * Configure::store('Model', 'class.paths', array('Users' => array('path' => 'users', 'plugin' => true))); + * Configure::store('Model', 'class.paths', array('Users' => array( + * 'path' => 'users', 'plugin' => true + * ))); * * @param string $type Type of config file to write, ex: Models, Controllers, Helpers, Components * @param string $name file name. @@ -470,7 +480,8 @@ class Configure extends Object { * Returns a key/value list of all paths where core libs are found. * Passing $type only returns the values for a given value of $key. * - * @param string $type valid values are: 'model', 'behavior', 'controller', 'component', 'view', 'helper', 'libs', and 'cake' + * @param string $type valid values are: 'model', 'behavior', 'controller', 'component', + * 'view', 'helper', 'datasource', 'libs', and 'cake' * @return array numeric keyed array of core lib paths * @access public */ @@ -589,7 +600,8 @@ class Configure extends Object { 'plugin' => array(APP . 'plugins' . DS), 'vendor' => array(APP . 'vendors' . DS, VENDORS), 'locale' => array(APP . 'locale' . DS), - 'shell' => array() + 'shell' => array(), + 'datasource' => array(MODELS . 'datasources') ); foreach ($basePaths as $type => $default) { @@ -609,7 +621,9 @@ class Configure extends Object { $_this->{$pathsVar} = $default; if (isset($paths[$pathsVar]) && !empty($paths[$pathsVar])) { - $path = array_flip(array_flip((array_merge($_this->{$pathsVar}, (array)$paths[$pathsVar], $merge)))); + $path = array_flip(array_flip((array_merge( + $_this->{$pathsVar}, (array)$paths[$pathsVar], $merge + )))); $_this->{$pathsVar} = array_values($path); } else { $path = array_flip(array_flip((array_merge($_this->{$pathsVar}, $merge)))); @@ -676,7 +690,10 @@ class Configure extends Object { } Cache::config('default'); } - Configure::buildPaths(compact('modelPaths', 'viewPaths', 'controllerPaths', 'helperPaths', 'componentPaths', 'behaviorPaths', 'pluginPaths', 'vendorPaths', 'localePaths', 'shellPaths')); + Configure::buildPaths(compact( + 'modelPaths', 'viewPaths', 'controllerPaths', 'helperPaths', 'componentPaths', + 'behaviorPaths', 'pluginPaths', 'vendorPaths', 'localePaths', 'shellPaths' + )); } } /** @@ -745,13 +762,17 @@ class App extends Object { * Finds classes based on $name or specific file(s) to search. * * @link http://book.cakephp.org/view/529/Using-App-import - * @param mixed $type The type of Class if passed as a string, or all params can be passed as an single array to $type, + * @param mixed $type The type of Class if passed as a string, or all params can be passed as + * an single array to $type, * @param string $name Name of the Class or a unique name for the file - * @param mixed $parent boolean true if Class Parent should be searched, accepts key => value array('parent' => $parent ,'file' => $file, 'search' => $search, 'ext' => '$ext'); - * $ext allows setting the extension of the file name based on Inflector::underscore($name) . ".$ext"; + * @param mixed $parent boolean true if Class Parent should be searched, accepts key => value + * array('parent' => $parent ,'file' => $file, 'search' => $search, 'ext' => '$ext'); + * $ext allows setting the extension of the file name + * based on Inflector::underscore($name) . ".$ext"; * @param array $search paths to search for files, array('path 1', 'path 2', 'path 3'); * @param string $file full name of the file to search for including extension - * @param boolean $return, return the loaded file, the file must have a return statement in it to work: return $variable; + * @param boolean $return, return the loaded file, the file must have a return + * statement in it to work: return $variable; * @return boolean true if Class is already in memory or if file is found and loaded, false if not * @access public */ diff --git a/cake/libs/model/connection_manager.php b/cake/libs/model/connection_manager.php index 8654b785c..524d2bd36 100644 --- a/cake/libs/model/connection_manager.php +++ b/cake/libs/model/connection_manager.php @@ -174,7 +174,8 @@ class ConnectionManager extends Object { } elseif (fileExistsInPath(LIBS . 'model' . DS . 'datasources' . DS . $conn['filename'] . '.php')) { require (LIBS . 'model' . DS . 'datasources' . DS . $conn['filename'] . '.php'); } else { - trigger_error(sprintf(__('Unable to load DataSource file %s.php', true), $conn['filename']), E_USER_ERROR); + $error = __('Unable to load DataSource file %s.php', true); + trigger_error(sprintf($error, $conn['filename']), E_USER_ERROR); return null; } } diff --git a/cake/libs/model/model.php b/cake/libs/model/model.php index 8e9496c46..f3f9eb721 100644 --- a/cake/libs/model/model.php +++ b/cake/libs/model/model.php @@ -1141,8 +1141,9 @@ class Model extends Overloadable { foreach ($dateFields as $updateCol) { if ($this->hasField($updateCol) && !in_array($updateCol, $fields)) { - $colType = array_merge(array('formatter' => 'date'), $db->columns[$this->getColumnType($updateCol)]); - if (!array_key_exists('formatter', $colType) || !array_key_exists('format', $colType)) { + $default = array('formatter' => 'date'); + $colType = array_merge($default, $db->columns[$this->getColumnType($updateCol)]); + if (!array_key_exists('format', $colType)) { $time = strtotime('now'); } else { $time = $colType['formatter']($colType['format']); @@ -1155,7 +1156,10 @@ class Model extends Overloadable { } if ($options['callbacks'] === true || $options['callbacks'] === 'before') { - if (!$this->Behaviors->trigger($this, 'beforeSave', array($options), array('break' => true, 'breakOn' => false)) || !$this->beforeSave($options)) { + $result = $this->Behaviors->trigger($this, 'beforeSave', array($options), array( + 'break' => true, 'breakOn' => false + )); + if (!$result || !$this->beforeSave($options)) { $this->whitelist = $_whitelist; return false; } @@ -1197,15 +1201,18 @@ class Model extends Overloadable { $created = false; if ($count > 0) { + $cache = $this->_prepareUpdateFields(array_combine($fields, $values)); + if (!empty($this->id)) { - if (!$db->update($this, $fields, $values)) { - $success = false; - } + $success = (bool)$db->update($this, $fields, $values); } else { foreach ($this->_schema as $field => $properties) { if ($this->primaryKey === $field) { - $isUUID = ($this->_schema[$field]['type'] === 'string' && $this->_schema[$field]['length'] === 36) - || ($this->_schema[$field]['type'] === 'binary' && $this->_schema[$field]['length'] === 16); + $fInfo = $this->_schema[$field]; + $isUUID = ( + ($fInfo['type'] === 'string' && $fInfo['length'] === 36) || + ($fInfo['type'] === 'binary' && $fInfo['length'] === 16) + ); if (empty($this->data[$this->alias][$this->primaryKey]) && $isUUID) { list($fields[], $values[]) = array($this->primaryKey, String::uuid()); } @@ -1219,10 +1226,10 @@ class Model extends Overloadable { $created = true; } } - } - if (!empty($this->belongsTo)) { - $this->updateCounterCache(array(), $created); + if ($success && !empty($this->belongsTo)) { + $this->updateCounterCache($cache, $created); + } } if (!empty($joined) && $success === true) { @@ -1334,32 +1341,80 @@ class Model extends Overloadable { * @access public */ function updateCounterCache($keys = array(), $created = false) { - if (empty($keys)) { - $keys = $this->data[$this->alias]; - } + $keys = empty($keys) ? $this->data[$this->alias] : $keys; + $keys['old'] = isset($keys['old']) ? $keys['old'] : array(); + foreach ($this->belongsTo as $parent => $assoc) { + $foreignKey = $assoc['foreignKey']; + $fkQuoted = $this->escapeField($assoc['foreignKey']); + if (!empty($assoc['counterCache'])) { if ($assoc['counterCache'] === true) { $assoc['counterCache'] = Inflector::underscore($this->alias) . '_count'; } - if (!isset($keys[$assoc['foreignKey']]) || empty($keys[$assoc['foreignKey']])) { - $keys[$assoc['foreignKey']] = $this->field($assoc['foreignKey']); + if (!$this->{$parent}->hasField($assoc['counterCache'])) { + continue; } - if ($this->{$parent}->hasField($assoc['counterCache'])) { - $conditions = array($this->escapeField($assoc['foreignKey']) => $keys[$assoc['foreignKey']]); - $recursive = -1; - if (isset($assoc['counterScope'])) { - $conditions = array_merge($conditions, (array)$assoc['counterScope']); - $recursive = 1; + + if (!array_key_exists($foreignKey, $keys)) { + $keys[$foreignKey] = $this->field($foreignKey); + } + $recursive = (isset($assoc['counterScope']) ? 1 : -1); + $conditions = ($recursive == 1) ? (array)$assoc['counterScope'] : array(); + + if (isset($keys['old'][$foreignKey])) { + if ($keys['old'][$foreignKey] == $keys[$foreignKey]) { + continue; } + $conditions[$fkQuoted] = $keys['old'][$foreignKey]; + $count = intval($this->find('count', compact('conditions', 'recursive'))); + $this->{$parent}->updateAll( - array($assoc['counterCache'] => intval($this->find('count', compact('conditions', 'recursive')))), - array($this->{$parent}->escapeField() => $keys[$assoc['foreignKey']]) + array($assoc['counterCache'] => $count), + array($this->{$parent}->escapeField() => $keys['old'][$foreignKey]) ); } + $conditions[$fkQuoted] = $keys[$foreignKey]; + + if ($recursive == 1) { + $conditions = array_merge($conditions, (array)$assoc['counterScope']); + } + $count = intval($this->find('count', compact('conditions', 'recursive'))); + + $this->{$parent}->updateAll( + array($assoc['counterCache'] => $count), + array($this->{$parent}->escapeField() => $keys[$foreignKey]) + ); } } } +/** + * Helper method for Model::updateCounterCache(). Checks the fields to be updated for + * + * @param array $data The fields of the record that will be updated + * @return array Returns updated foreign key values, along with an 'old' key containing the old + * values, or empty if no foreign keys are updated. + * @access protected + */ + function _prepareUpdateFields($data) { + $foreignKeys = array(); + foreach ($this->belongsTo as $assoc => $info) { + if ($info['counterCache']) { + $foreignKeys[$assoc] = $info['foreignKey']; + } + } + $included = array_intersect($foreignKeys, array_keys($data)); + + if (empty($included) || empty($this->id)) { + return array(); + } + $old = $this->find('first', array( + 'conditions' => array('id' => $this->id), + 'fields' => array_values($included), + 'recursive' => -1 + )); + return array_merge($data, array('old' => $old[$this->alias])); + } /** * Saves multiple individual records for a single model; Also works with a single record, as well as * all its associated records. @@ -2419,6 +2474,7 @@ class Model extends Overloadable { * * @return string The name of the display field for this Model (i.e. 'name', 'title'). * @access public + * @deprecated */ function getDisplayField() { return $this->displayField; diff --git a/cake/libs/set.php b/cake/libs/set.php index 360aed74d..e2ebf8d7c 100644 --- a/cake/libs/set.php +++ b/cake/libs/set.php @@ -406,7 +406,7 @@ class Set extends Object { if (count($context['trace']) == 1) { $context['trace'][] = $context['key']; } - $parent = join('/', $context['trace']).'/.'; + $parent = join('/', $context['trace']) . '/.'; $context['item'] = Set::extract($parent, $data); $context['key'] = array_pop($context['trace']); if (isset($context['trace'][1]) && $context['trace'][1] > 0) { @@ -455,7 +455,7 @@ class Set extends Object { $filtered = array(); $length = count($matches); foreach ($matches as $i => $match) { - if (Set::matches(array($condition), $match['item'], $i+1, $length)) { + if (Set::matches(array($condition), $match['item'], $i + 1, $length)) { $filtered[] = $match; } } diff --git a/cake/tests/cases/libs/model/model.test.php b/cake/tests/cases/libs/model/model.test.php index 0f69534c2..b588e86a5 100644 --- a/cake/tests/cases/libs/model/model.test.php +++ b/cake/tests/cases/libs/model/model.test.php @@ -65,7 +65,8 @@ class ModelTest extends CakeTestCase { 'core.dependency', 'core.story', 'core.stories_tag', 'core.cd', 'core.book', 'core.basket', 'core.overall_favorite', 'core.account', 'core.content', 'core.content_account', 'core.film_file', 'core.test_plugin_article', 'core.test_plugin_comment', 'core.uuiditem', - 'core.uuidportfolio', 'core.uuiditems_uuidportfolio', 'core.uuiditems_uuidportfolio_numericid' + 'core.counter_cache_user', 'core.counter_cache_post', 'core.uuidportfolio', + 'core.uuiditems_uuidportfolio', 'core.uuiditems_uuidportfolio_numericid' ); /** * start method @@ -190,7 +191,8 @@ class ModelTest extends CakeTestCase { $this->assertTrue(isset($TestModel->Behaviors->Tree)); $TestModel =& ClassRegistry::init('MergeVarPluginComment'); - $this->assertEqual($TestModel->actsAs, array('Containable', 'Containable' => array('some_settings'))); + $expected = array('Containable', 'Containable' => array('some_settings')); + $this->assertEqual($TestModel->actsAs, $expected); $this->assertTrue(isset($TestModel->Behaviors->Containable)); } /** @@ -1073,13 +1075,15 @@ class ModelTest extends CakeTestCase { $TestModel->id = 7; $result = $TestModel->read(); $expected = array( - 'CategoryThread' => array('id' => 7, 'parent_id' => 6, 'name' => 'Category 2.1', 'created' => '2007-03-18 15:30:23', 'updated' => '2007-03-18 15:32:31'), - 'ParentCategory' => array('id' => 6, 'parent_id' => 5, 'name' => 'Category 2', 'created' => '2007-03-18 15:30:23', 'updated' => '2007-03-18 15:32:31', - 'ParentCategory' => array('id' => 5, 'parent_id' => 4, 'name' => 'Category 1.1.1.1', 'created' => '2007-03-18 15:30:23', 'updated' => '2007-03-18 15:32:31', - 'ParentCategory' => array('id' => 4, 'parent_id' => 3, 'name' => 'Category 1.1.2', 'created' => '2007-03-18 15:30:23', 'updated' => '2007-03-18 15:32:31', - 'ParentCategory' => array('id' => 3, 'parent_id' => 2, 'name' => 'Category 1.1.1', 'created' => '2007-03-18 15:30:23', 'updated' => '2007-03-18 15:32:31', - 'ParentCategory' => array('id' => 2, 'parent_id' => 1, 'name' => 'Category 1.1', 'created' => '2007-03-18 15:30:23', 'updated' => '2007-03-18 15:32:31', - 'ParentCategory' => array('id' => 1, 'parent_id' => 0, 'name' => 'Category 1', 'created' => '2007-03-18 15:30:23', 'updated' => '2007-03-18 15:32:31'))))))); + 'CategoryThread' => array('id' => 7, 'parent_id' => 6, 'name' => 'Category 2.1', 'created' => '2007-03-18 15:30:23', 'updated' => '2007-03-18 15:32:31'), + 'ParentCategory' => array('id' => 6, 'parent_id' => 5, 'name' => 'Category 2', 'created' => '2007-03-18 15:30:23', 'updated' => '2007-03-18 15:32:31', + 'ParentCategory' => array('id' => 5, 'parent_id' => 4, 'name' => 'Category 1.1.1.1', 'created' => '2007-03-18 15:30:23', 'updated' => '2007-03-18 15:32:31', + 'ParentCategory' => array('id' => 4, 'parent_id' => 3, 'name' => 'Category 1.1.2', 'created' => '2007-03-18 15:30:23', 'updated' => '2007-03-18 15:32:31', + 'ParentCategory' => array('id' => 3, 'parent_id' => 2, 'name' => 'Category 1.1.1', 'created' => '2007-03-18 15:30:23', 'updated' => '2007-03-18 15:32:31', + 'ParentCategory' => array('id' => 2, 'parent_id' => 1, 'name' => 'Category 1.1', 'created' => '2007-03-18 15:30:23', 'updated' => '2007-03-18 15:32:31', + 'ParentCategory' => array('id' => 1, 'parent_id' => 0, 'name' => 'Category 1', 'created' => '2007-03-18 15:30:23', 'updated' => '2007-03-18 15:32:31'))))) + ) + ); $this->db->fullDebug = $fullDebug; $this->assertEqual($result, $expected); } @@ -1099,13 +1103,15 @@ class ModelTest extends CakeTestCase { $result = $TestModel->find(array('CategoryThread.id' => 7)); $expected = array( - 'CategoryThread' => array('id' => 7, 'parent_id' => 6, 'name' => 'Category 2.1', 'created' => '2007-03-18 15:30:23', 'updated' => '2007-03-18 15:32:31'), - 'ParentCategory' => array('id' => 6, 'parent_id' => 5, 'name' => 'Category 2', 'created' => '2007-03-18 15:30:23', 'updated' => '2007-03-18 15:32:31', - 'ParentCategory' => array('id' => 5, 'parent_id' => 4, 'name' => 'Category 1.1.1.1', 'created' => '2007-03-18 15:30:23', 'updated' => '2007-03-18 15:32:31', - 'ParentCategory' => array('id' => 4, 'parent_id' => 3, 'name' => 'Category 1.1.2', 'created' => '2007-03-18 15:30:23', 'updated' => '2007-03-18 15:32:31', - 'ParentCategory' => array('id' => 3, 'parent_id' => 2, 'name' => 'Category 1.1.1', 'created' => '2007-03-18 15:30:23', 'updated' => '2007-03-18 15:32:31', - 'ParentCategory' => array('id' => 2, 'parent_id' => 1, 'name' => 'Category 1.1', 'created' => '2007-03-18 15:30:23', 'updated' => '2007-03-18 15:32:31', - 'ParentCategory' => array('id' => 1, 'parent_id' => 0, 'name' => 'Category 1', 'created' => '2007-03-18 15:30:23', 'updated' => '2007-03-18 15:32:31'))))))); + 'CategoryThread' => array('id' => 7, 'parent_id' => 6, 'name' => 'Category 2.1', 'created' => '2007-03-18 15:30:23', 'updated' => '2007-03-18 15:32:31'), + 'ParentCategory' => array('id' => 6, 'parent_id' => 5, 'name' => 'Category 2', 'created' => '2007-03-18 15:30:23', 'updated' => '2007-03-18 15:32:31', + 'ParentCategory' => array('id' => 5, 'parent_id' => 4, 'name' => 'Category 1.1.1.1', 'created' => '2007-03-18 15:30:23', 'updated' => '2007-03-18 15:32:31', + 'ParentCategory' => array('id' => 4, 'parent_id' => 3, 'name' => 'Category 1.1.2', 'created' => '2007-03-18 15:30:23', 'updated' => '2007-03-18 15:32:31', + 'ParentCategory' => array('id' => 3, 'parent_id' => 2, 'name' => 'Category 1.1.1', 'created' => '2007-03-18 15:30:23', 'updated' => '2007-03-18 15:32:31', + 'ParentCategory' => array('id' => 2, 'parent_id' => 1, 'name' => 'Category 1.1', 'created' => '2007-03-18 15:30:23', 'updated' => '2007-03-18 15:32:31', + 'ParentCategory' => array('id' => 1, 'parent_id' => 0, 'name' => 'Category 1', 'created' => '2007-03-18 15:30:23', 'updated' => '2007-03-18 15:32:31'))))) + ) + ); $this->db->fullDebug = $fullDebug; $this->assertEqual($result, $expected); } @@ -3681,7 +3687,70 @@ class ModelTest extends CakeTestCase { $this->assertIdentical($result['Syfile']['item_count'], '2'); $result = $TestModel->findById(2); - $this->assertIdentical($result['Syfile']['item_count'], null); + $this->assertIdentical($result['Syfile']['item_count'], '0'); + } +/** + * Tests that counter caches are updated when records are added + * + * @access public + * @return void + */ + function testCounterCacheIncrease() { + $this->loadFixtures('CounterCacheUser', 'CounterCachePost'); + $User = new CounterCacheUser(); + $Post = new CounterCachePost(); + $data = array('Post' => array('title' => 'New Post', 'user_id' => 66)); + + $Post->save($data); + $user = $User->find('first', array( + 'conditions' => array('id' => 66),'recursive' => -1 + )); + + $result = $user[$User->alias]['post_count']; + $expected = 3; + $this->assertEqual($result, $expected); + + } +/** + * Tests that counter caches are updated when records are deleted + * + * @access public + * @return void + */ + function testCounterCacheDecrease() { + $this->loadFixtures('CounterCacheUser', 'CounterCachePost'); + $User = new CounterCacheUser(); + $Post = new CounterCachePost(); + + $Post->del(2); + $user = $User->find('first', array( + 'conditions' => array('id' => 66),'recursive' => -1 + )); + + $result = $user[$User->alias]['post_count']; + $expected = 1; + $this->assertEqual($result, $expected); + } +/** + * Tests that counter caches are updated when foreign keys of counted records change + * + * @access public + * @return void + */ + function testCounterCacheUpdated() { + $this->loadFixtures('CounterCacheUser', 'CounterCachePost'); + $User = new CounterCacheUser(); + $Post = new CounterCachePost(); + + $data = $Post->find('first', array( + 'conditions' => array('id' => 1),'recursive' => -1 + )); + $data[$Post->alias]['user_id'] = 301; + $Post->save($data); + + $users = $User->find('all',array('order' => 'User.id')); + $this->assertEqual($users[0]['User']['post_count'], 1); + $this->assertEqual($users[1]['User']['post_count'], 2); } /** * test Counter Cache With Self Joining table diff --git a/cake/tests/cases/libs/model/models.php b/cake/tests/cases/libs/model/models.php index b89da27f2..b9e5063b4 100644 --- a/cake/tests/cases/libs/model/models.php +++ b/cake/tests/cases/libs/model/models.php @@ -2840,6 +2840,29 @@ class TranslatedArticle extends CakeTestModel { var $belongsTo = array('User'); } +class CounterCacheUser extends CakeTestModel { + var $name = 'CounterCacheUser'; + var $alias = 'User'; + var $fixture = 'counter_cache_user'; + + var $hasMany = array('Post' => array( + 'className' => 'CounterCachePost', + 'foreignKey' => 'user_id' + )); +} + +class CounterCachePost extends CakeTestModel { + var $name = 'CounterCachePost'; + var $alias = 'Post'; + var $fixture = 'counter_cache_user'; + + var $belongsTo = array('User' => array( + 'className' => 'CounterCacheUser', + 'foreignKey' => 'user_id', + 'counterCache' => true + )); +} + class ArticleB extends CakeTestModel { var $name = 'ArticleB'; var $useTable = 'articles'; @@ -2848,8 +2871,9 @@ class ArticleB extends CakeTestModel { 'className' => 'TagB', 'joinTable' => 'articles_tags', 'foreignKey' => 'article_id', - 'associationForeignKey' => 'tag_id') - ); + 'associationForeignKey' => 'tag_id' + ) + ); } class TagB extends CakeTestModel { @@ -2860,7 +2884,9 @@ class TagB extends CakeTestModel { 'className' => 'ArticleB', 'joinTable' => 'articles_tags', 'foreignKey' => 'tag_id', - 'associationForeignKey' => 'article_id') - ); + 'associationForeignKey' => 'article_id' + ) + ); } -?> \ No newline at end of file + +?> diff --git a/cake/tests/cases/libs/set.test.php b/cake/tests/cases/libs/set.test.php index a4b702442..218b4b84b 100644 --- a/cake/tests/cases/libs/set.test.php +++ b/cake/tests/cases/libs/set.test.php @@ -395,28 +395,13 @@ class SetTest extends CakeTestCase { ); $b = array('Deep' => $a[0]['Deep']); $c = array( - array( - 'a' => array( - 'I' => array( - 'a' => 1 - ) - ) - ), + array('a' => array('I' => array('a' => 1))), array( 'a' => array( 2 ) ), - array( - 'a' => array( - 'II' => array( - 'a' => 3, - 'III' => array( - 'a' => array('foo' => 4) - ) - ) - ) - ), + array('a' => array('II' => array('a' => 3, 'III' => array('a' => array('foo' => 4))))), ); $nonSequential = array( @@ -447,9 +432,25 @@ class SetTest extends CakeTestCase { $this->assertEqual(Set::extract('/User/id', $a), $expected); $this->assertEqual(Set::extract('/User/id', $nonSequential), $expected); - $this->assertEqual(Set::extract('/User/id', $nonZero), $expected, 'Failed non zero array key extract'); + $result = Set::extract('/User/id', $nonZero); + $this->assertEqual($result, $expected, 'Failed non zero array key extract'); + Configure::write('foo', null); + + // $expected = array( + // array('id' => 1), array('id' => 2), array('id' => 3), array('id' => 4), array('id' => 5) + // ); + + $expected = array(1, 2, 3, 4, 5); + $this->assertEqual(Set::extract('/User/id', $a), $expected); + $this->assertEqual(Set::extract('/User/id', $nonSequential), $expected); + + $result = Set::extract('/User/id', $nonZero); + $this->assertEqual($result, $expected, 'Failed non zero array key extract'); + + $expected = array( + array('id' => 1), array('id' => 2), array('id' => 3), array('id' => 4), array('id' => 5) + ); - $expected = array(array('id' => 1), array('id' => 2), array('id' => 3), array('id' => 4), array('id' => 5)); $r = Set::extract('/User/id', $a, array('flatten' => false)); $this->assertEqual($r, $expected); @@ -701,6 +702,103 @@ class SetTest extends CakeTestCase { $this->assertEqual($r[1]['Comment']['User']['name'], 'dan'); $this->assertEqual(count($r), 2); + $r = Set::extract('/Comment/User[name=/bob|tod/]/..', $habtm); + $this->assertEqual($r[0]['Comment']['User']['name'], 'bob'); + + $this->assertEqual($r[1]['Comment']['User']['name'], 'tod'); + $this->assertEqual(count($r), 2); + + $tree = array( + array( + 'Category' => array('name' => 'Category 1'), + 'children' => array(array('Category' => array('name' => 'Category 1.1'))) + ), + array( + 'Category' => array('name' => 'Category 2'), + 'children' => array( + array('Category' => array('name' => 'Category 2.1')), + array('Category' => array('name' => 'Category 2.2')) + ) + ), + array( + 'Category' => array('name' => 'Category 3'), + 'children' => array(array('Category' => array('name' => 'Category 3.1'))) + ) + ); + + $expected = array(array('Category' => $tree[1]['Category'])); + $r = Set::extract('/Category[name=Category 2]', $tree); + $this->assertEqual($r, $expected); + + $expected = array( + array('Category' => $tree[1]['Category'], 'children' => $tree[1]['children']) + ); + $r = Set::extract('/Category[name=Category 2]/..', $tree); + $this->assertEqual($r, $expected); + + $expected = array( + array('children' => $tree[1]['children'][0]), + array('children' => $tree[1]['children'][1]) + ); + $r = Set::extract('/Category[name=Category 2]/../children', $tree); + $this->assertEqual($r, $expected); + + $habtm = array( + array( + 'Post' => array( + 'id' => 1, + 'title' => 'great post', + ), + 'Comment' => array( + array( + 'id' => 1, + 'text' => 'foo', + 'User' => array( + 'id' => 1, + 'name' => 'bob' + ), + ), + array( + 'id' => 2, + 'text' => 'bar', + 'User' => array( + 'id' => 2, + 'name' => 'tod' + ), + ), + ), + ), + array( + 'Post' => array( + 'id' => 2, + 'title' => 'fun post', + ), + 'Comment' => array( + array( + 'id' => 3, + 'text' => '123', + 'User' => array( + 'id' => 3, + 'name' => 'dan' + ), + ), + array( + 'id' => 4, + 'text' => '987', + 'User' => array( + 'id' => 4, + 'name' => 'jim' + ), + ), + ), + ), + ); + + $r = Set::extract('/Comment/User[name=/bob|dan/]/..', $habtm); + $this->assertEqual($r[0]['Comment']['User']['name'], 'bob'); + $this->assertEqual($r[1]['Comment']['User']['name'], 'dan'); + $this->assertEqual(count($r), 2); + $r = Set::extract('/Comment/User[name=/bob|tod/]/..', $habtm); $this->assertEqual($r[0]['Comment']['User']['name'], 'bob'); // Currently failing, needs fix @@ -773,7 +871,8 @@ class SetTest extends CakeTestCase { $a = 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')) + ); $this->assertTrue(Set::matches(array('id=2'), $a[1]['Article'])); $this->assertFalse(Set::matches(array('id>2'), $a[1]['Article'])); @@ -805,7 +904,8 @@ class SetTest extends CakeTestCase { $a = 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, '{n}.Article.id'); $expected = array( 1, 2, 3 ); @@ -824,12 +924,19 @@ class SetTest extends CakeTestCase { $this->assertIdentical($result, $expected); $a = array( - array('Article' => array('id' => 1, 'title' => 'Article 1', - 'User' => array('id' => 1, 'username' => 'mariano.iglesias'))), - array('Article' => array('id' => 2, 'title' => 'Article 2', - 'User' => array('id' => 1, 'username' => 'mariano.iglesias'))), - array('Article' => array('id' => 3, 'title' => 'Article 3', - 'User' => array('id' => 2, 'username' => 'phpnut')))); + array( + 'Article' => array('id' => 1, 'title' => 'Article 1', + 'User' => array('id' => 1, 'username' => 'mariano.iglesias')) + ), + array( + 'Article' => array('id' => 2, 'title' => 'Article 2', + 'User' => array('id' => 1, 'username' => 'mariano.iglesias')) + ), + array( + 'Article' => array('id' => 3, 'title' => 'Article 3', + 'User' => array('id' => 2, 'username' => 'phpnut')) + ) + ); $result = Set::extract($a, '{n}.Article.User.username'); $expected = array( 'mariano.iglesias', 'mariano.iglesias', 'phpnut' ); @@ -852,7 +959,11 @@ class SetTest extends CakeTestCase { $this->assertIdentical($result, $expected); $result = Set::extract($a, '{n}.Article.Comment.{n}.title'); - $expected = array (array('Comment 10', 'Comment 11', 'Comment 12'), array('Comment 13', 'Comment 14'), null); + $expected = array( + array('Comment 10', 'Comment 11', 'Comment 12'), + array('Comment 13', 'Comment 14'), + null + ); $this->assertIdentical($result, $expected); $a = array(array('1day' => '20 sales'), array('1day' => '2 sales')); @@ -885,7 +996,12 @@ class SetTest extends CakeTestCase { $this->assertIdentical($result, $expected); $result = Set::extract($a,'{\w+}.{\w+}.name'); - $expected = array(array('pages' => 'page'), array('fruites' => 'fruit'), 'test' => array('jippi'), 'dot.test' => array('jippi')); + $expected = array( + array('pages' => 'page'), + array('fruites' => 'fruit'), + 'test' => array('jippi'), + 'dot.test' => array('jippi') + ); $this->assertIdentical($result, $expected); $result = Set::extract($a,'{\d+}.{\w+}.name'); @@ -905,7 +1021,10 @@ class SetTest extends CakeTestCase { $this->assertIdentical($result, $expected); $result = Set::extract($a,'{[a-z]}'); - $expected = array('test' => array(array('name' => 'jippi')), 'dot.test' => array(array('name' => 'jippi'))); + $expected = array( + 'test' => array(array('name' => 'jippi')), + 'dot.test' => array(array('name' => 'jippi')) + ); $this->assertIdentical($result, $expected); $result = Set::extract($a, '{dot\.test}.{n}'); diff --git a/cake/tests/fixtures/counter_cache_post_fixture.php b/cake/tests/fixtures/counter_cache_post_fixture.php new file mode 100644 index 000000000..fdbb5a39c --- /dev/null +++ b/cake/tests/fixtures/counter_cache_post_fixture.php @@ -0,0 +1,50 @@ + + * Copyright 2005-2008, Cake Software Foundation, Inc. (http://www.cakefoundation.org) + * + * Licensed under The Open Group Test Suite License + * Redistributions of files must retain the above copyright notice. + * + * @filesource + * @copyright Copyright 2005-2008, Cake Software Foundation, Inc. (http://www.cakefoundation.org) + * @link https://trac.cakephp.org/wiki/Developement/TestSuite CakePHP(tm) Tests + * @package cake.tests + * @subpackage cake.tests.fixtures + * @since CakePHP(tm) v 1.2.0.4667 + * @version $Revision: 7848 $ + * @modifiedby $LastChangedBy: renan.saddam $ + * @lastmodified $Date: 2008-11-07 21:58:37 -0500 (Fri, 07 Nov 2008) $ + * @license http://www.opensource.org/licenses/opengroup.php The Open Group Test Suite License + */ +/** + * Short description for class. + * + * @package cake.tests + * @subpackage cake.tests.fixtures + */ +class CounterCachePostFixture extends CakeTestFixture { + + var $name = 'CounterCachePost'; + + var $fields = array( + 'id' => array('type' => 'integer', 'key' => 'primary'), + 'title' => array('type' => 'string', 'length' => 255, 'null' => false), + 'user_id' => array('type' => 'integer', 'null' => true), + ); + + var $records = array( + array('id' => 1, 'title' => 'Rock and Roll', 'user_id' => 66), + array('id' => 2, 'title' => 'Music', 'user_id' => 66), + array('id' => 3, 'title' => 'Food', 'user_id' => 301), + ); +} + +?> \ No newline at end of file diff --git a/cake/tests/fixtures/counter_cache_user_fixture.php b/cake/tests/fixtures/counter_cache_user_fixture.php new file mode 100644 index 000000000..3ee6ec954 --- /dev/null +++ b/cake/tests/fixtures/counter_cache_user_fixture.php @@ -0,0 +1,49 @@ + + * Copyright 2005-2008, Cake Software Foundation, Inc. (http://www.cakefoundation.org) + * + * Licensed under The Open Group Test Suite License + * Redistributions of files must retain the above copyright notice. + * + * @filesource + * @copyright Copyright 2005-2008, Cake Software Foundation, Inc. (http://www.cakefoundation.org) + * @link https://trac.cakephp.org/wiki/Developement/TestSuite CakePHP(tm) Tests + * @package cake.tests + * @subpackage cake.tests.fixtures + * @since CakePHP(tm) v 1.2.0.4667 + * @version $Revision: 7848 $ + * @modifiedby $LastChangedBy: renan.saddam $ + * @lastmodified $Date: 2008-11-07 21:58:37 -0500 (Fri, 07 Nov 2008) $ + * @license http://www.opensource.org/licenses/opengroup.php The Open Group Test Suite License + */ +/** + * Short description for class. + * + * @package cake.tests + * @subpackage cake.tests.fixtures + */ +class CounterCacheUserFixture extends CakeTestFixture { + + var $name = 'CounterCacheUser'; + + var $fields = array( + 'id' => array('type' => 'integer', 'key' => 'primary'), + 'name' => array('type' => 'string', 'length' => 255, 'null' => false), + 'post_count' => array('type' => 'integer', 'null' => true) + ); + + var $records = array( + array('id' => 66, 'name' => 'Alexander','post_count' => 2), + array('id' => 301, 'name' => 'Steven','post_count' => 1), + ); +} + +?> \ No newline at end of file