From 0d469ac4ba056d69f17b3980a1154cea65e5993d Mon Sep 17 00:00:00 2001 From: nate Date: Sun, 23 Dec 2007 17:03:19 +0000 Subject: [PATCH] Fixing ability to specify select fields for join models, and adding tests git-svn-id: https://svn.cakephp.org/repo/branches/1.2.x.x@6230 3807eeeb-6ff5-0310-8944-8be069107fe0 --- cake/libs/model/datasources/dbo_source.php | 33 +++++++++++--- cake/libs/model/model.php | 3 ++ cake/tests/cases/libs/model/model.test.php | 50 +++++++++++++++++++++- cake/tests/fixtures/post_fixture.php | 6 +-- 4 files changed, 81 insertions(+), 11 deletions(-) diff --git a/cake/libs/model/datasources/dbo_source.php b/cake/libs/model/datasources/dbo_source.php index fd2cd4f79..a24574c2d 100644 --- a/cake/libs/model/datasources/dbo_source.php +++ b/cake/libs/model/datasources/dbo_source.php @@ -719,10 +719,9 @@ class DboSource extends DataSource { $query = str_replace(' WHERE 1 = 1', '', $query); } - $with = $model->hasAndBelongsToMany[$association]['with']; $foreignKey = $model->hasAndBelongsToMany[$association]['foreignKey']; - $habtmFields = $model->{$with}->schema(); - $habtmFields = array_keys($habtmFields); + $joinKeys = array($foreignKey, $model->hasAndBelongsToMany[$association]['associationForeignKey']); + list($with, $habtmFields) = $this->getJoinModel($model, $model->hasAndBelongsToMany[$association]['with'], $joinKeys); $habtmFieldsCount = count($habtmFields); $q = $this->insertQueryData($query, null, $association, $assocData, $model, $linkModel, $stack); @@ -1124,11 +1123,11 @@ class DboSource extends DataSource { $joinAlias = $joinTbl; if (isset($assocData['with']) && !empty($assocData['with'])) { - $joinFields = $model->{$assocData['with']}->schema(); - $joinFields = array_keys($joinFields); + $joinKeys = array($assocData['foreignKey'], $assocData['associationForeignKey']); + list($with, $joinFields) = $this->getJoinModel($model, $assocData['with'], $joinKeys); if (is_array($joinFields) && !empty($joinFields)) { - $joinFields = $this->fields($model->{$assocData['with']}, $model->{$assocData['with']}->alias, $joinFields); - $joinAssoc = $joinAlias = $model->{$assocData['with']}->alias; + $joinFields = $this->fields($model->{$with}, $model->{$with}->alias, $joinFields); + $joinAssoc = $joinAlias = $model->{$with}->alias; } else { $joinFields = array(); @@ -1158,6 +1157,24 @@ class DboSource extends DataSource { } return null; } +/** + * Gets the name and fields to be used by a join model. This allows specifying join fields in the association definition. + * + * @param object $model The model to be joined + * @param mixed $with The 'with' key of the model association + * @param array $keys Any join keys which must be merged with the keys queried + * @return array + */ + function getJoinModel($model, $assoc, $keys = array()) { + if (is_string($assoc)) { + return array($assoc, array_keys($model->{$assoc}->schema())); + } elseif (is_array($assoc)) { + $with = key($assoc); + return array($with, array_unique(array_merge($assoc[$with], $keys))); + } else { + trigger_error(sprintf(__('Invalid join model settings in %s', true), $model->alias), E_USER_WARNING); + } + } function buildJoinStatement($join) { $data = array_merge(array( @@ -1166,6 +1183,7 @@ class DboSource extends DataSource { 'table' => 'join_table', 'conditions' => array() ), $join); + //pr($data); if (!empty($data['alias'])) { $data['alias'] = $this->alias . $this->name($data['alias']); @@ -1173,6 +1191,7 @@ class DboSource extends DataSource { if (!empty($data['conditions'])) { $data['conditions'] = trim($this->conditions($data['conditions'], true, false)); } + //pr($data); return $this->renderJoinStatement($data); } diff --git a/cake/libs/model/model.php b/cake/libs/model/model.php index 10ed55fc1..abd2fbeae 100644 --- a/cake/libs/model/model.php +++ b/cake/libs/model/model.php @@ -715,6 +715,9 @@ class Model extends Overloadable { if (isset($this->{$type}[$assocKey]['with']) && !empty($this->{$type}[$assocKey]['with'])) { $joinClass = $this->{$type}[$assocKey]['with']; + if (is_array($joinClass)) { + $joinClass = key($joinClass); + } $plugin = null; if (strpos($joinClass, '.') !== false) { diff --git a/cake/tests/cases/libs/model/model.test.php b/cake/tests/cases/libs/model/model.test.php index 8d35b1fe4..2f2d0dfc5 100644 --- a/cake/tests/cases/libs/model/model.test.php +++ b/cake/tests/cases/libs/model/model.test.php @@ -371,8 +371,21 @@ class ModelC extends CakeTestModel { var $hasMany = array('ModelD'); } class ModelD extends CakeTestModel { + var $name = 'ModelD'; var $useTable = 'threads'; } +class Something extends CakeTestModel { + var $name = 'Something'; + var $hasAndBelongsToMany = array('SomethingElse' => array('with' => array('JoinThing' => array('doomed')))); +} +class SomethingElse extends CakeTestModel { + var $name = 'SomethingElse'; + var $hasAndBelongsToMany = array('Something' => array('with' => 'JoinThing')); +} +class JoinThing extends CakeTestModel { + var $name = 'JoinThing'; + var $belongsTo = array('Something', 'SomethingElse'); +} class Portfolio extends CakeTestModel { var $name = 'Portfolio'; var $hasAndBelongsToMany = array('Item'); @@ -443,7 +456,7 @@ class ModelTest extends CakeTestCase { 'core.project', 'core.thread', 'core.message', 'core.bid', 'core.portfolio', 'core.item', 'core.items_portfolio', 'core.syfile', 'core.image', 'core.device_type', 'core.device_type_category', 'core.feature_set', 'core.exterior_type_category', 'core.document', 'core.device', 'core.document_directory', - 'core.primary_model', 'core.secondary_model' + 'core.primary_model', 'core.secondary_model', 'core.something', 'core.something_else', 'core.join_thing' ); function start() { @@ -535,6 +548,41 @@ class ModelTest extends CakeTestCase { unset($this->Project); } + function testWithAssociation() { + $this->model =& new Something(); + $result = $this->model->SomethingElse->find('all'); + + $expected = array( + array('SomethingElse' => array('id' => '1', 'title' => 'First Post', 'body' => 'First Post Body', 'published' => 'Y', 'created' => '2007-03-18 10:39:23', 'updated' => '2007-03-18 10:41:31'), + 'Something' => array(array('id' => '3', 'title' => 'Third Post', 'body' => 'Third Post Body', 'published' => 'Y', 'created' => '2007-03-18 10:43:23', 'updated' => '2007-03-18 10:45:31', + 'JoinThing' => array('id' => '3', 'something_id' => '3', 'something_else_id' => '1', 'doomed' => '1', 'created' => '2007-03-18 10:43:23', 'updated' => '2007-03-18 10:45:31')))), + array('SomethingElse' => array('id' => '2', 'title' => 'Second Post', 'body' => 'Second Post Body', 'published' => 'Y', 'created' => '2007-03-18 10:41:23', 'updated' => '2007-03-18 10:43:31'), + 'Something' => array(array('id' => '1', 'title' => 'First Post', 'body' => 'First Post Body', 'published' => 'Y', 'created' => '2007-03-18 10:39:23', 'updated' => '2007-03-18 10:41:31', + 'JoinThing' => array('id' => '1', 'something_id' => '1', 'something_else_id' => '2', 'doomed' => '1', 'created' => '2007-03-18 10:39:23', 'updated' => '2007-03-18 10:41:31')))), + array('SomethingElse' => array('id' => '3', 'title' => 'Third Post', 'body' => 'Third Post Body', 'published' => 'Y', 'created' => '2007-03-18 10:43:23', 'updated' => '2007-03-18 10:45:31'), + 'Something' => array (array('id' => '2', 'title' => 'Second Post', 'body' => 'Second Post Body', 'published' => 'Y', 'created' => '2007-03-18 10:41:23', 'updated' => '2007-03-18 10:43:31', + 'JoinThing' => array('id' => '2', 'something_id' => '2', 'something_else_id' => '3', 'doomed' => '0', 'created' => '2007-03-18 10:41:23', 'updated' => '2007-03-18 10:43:31'))))); + + $this->assertEqual($result, $expected); + + $result = $this->model->find('all'); + $expected = array( + array('Something' => array('id' => '1', 'title' => 'First Post', 'body' => 'First Post Body', 'published' => 'Y', 'created' => '2007-03-18 10:39:23', 'updated' => '2007-03-18 10:41:31'), + 'SomethingElse' => array( + array('id' => '2', 'title' => 'Second Post', 'body' => 'Second Post Body', 'published' => 'Y', 'created' => '2007-03-18 10:41:23', 'updated' => '2007-03-18 10:43:31', + 'JoinThing' => array('doomed' => '1', 'something_id' => '1', 'something_else_id' => '2')))), + array('Something' => array('id' => '2', 'title' => 'Second Post', 'body' => 'Second Post Body', 'published' => 'Y', 'created' => '2007-03-18 10:41:23', 'updated' => '2007-03-18 10:43:31'), + 'SomethingElse' => array( + array('id' => '3', 'title' => 'Third Post', 'body' => 'Third Post Body', 'published' => 'Y', 'created' => '2007-03-18 10:43:23', 'updated' => '2007-03-18 10:45:31', + 'JoinThing' => array('doomed' => '0', 'something_id' => '2', 'something_else_id' => '3')))), + array('Something' => array('id' => '3', 'title' => 'Third Post', 'body' => 'Third Post Body', 'published' => 'Y', 'created' => '2007-03-18 10:43:23', 'updated' => '2007-03-18 10:45:31'), + 'SomethingElse' => array( + array('id' => '1', 'title' => 'First Post', 'body' => 'First Post Body', 'published' => 'Y', 'created' => '2007-03-18 10:39:23', 'updated' => '2007-03-18 10:41:31', + 'JoinThing' => array('doomed' => '1', 'something_id' => '3', 'something_else_id' => '1'))))); + + $this->assertEqual($result, $expected); + } + function testFindAllRecursiveSelfJoin() { $this->model =& new Home(); $this->model->recursive = 2; diff --git a/cake/tests/fixtures/post_fixture.php b/cake/tests/fixtures/post_fixture.php index e8d799522..f13da02b2 100644 --- a/cake/tests/fixtures/post_fixture.php +++ b/cake/tests/fixtures/post_fixture.php @@ -44,9 +44,9 @@ class PostFixture extends CakeTestFixture { 'updated' => 'datetime' ); var $records = array( - array ('id' => 1, 'author_id' => 1, 'title' => 'First Post', 'body' => 'First Post Body', 'published' => 'Y', 'created' => '2007-03-18 10:39:23', 'updated' => '2007-03-18 10:41:31'), - array ('id' => 2, 'author_id' => 3, 'title' => 'Second Post', 'body' => 'Second Post Body', 'published' => 'Y', 'created' => '2007-03-18 10:41:23', 'updated' => '2007-03-18 10:43:31'), - array ('id' => 3, 'author_id' => 1, 'title' => 'Third Post', 'body' => 'Third Post Body', 'published' => 'Y', 'created' => '2007-03-18 10:43:23', 'updated' => '2007-03-18 10:45:31') + array('id' => 1, 'author_id' => 1, 'title' => 'First Post', 'body' => 'First Post Body', 'published' => 'Y', 'created' => '2007-03-18 10:39:23', 'updated' => '2007-03-18 10:41:31'), + array('id' => 2, 'author_id' => 3, 'title' => 'Second Post', 'body' => 'Second Post Body', 'published' => 'Y', 'created' => '2007-03-18 10:41:23', 'updated' => '2007-03-18 10:43:31'), + array('id' => 3, 'author_id' => 1, 'title' => 'Third Post', 'body' => 'Third Post Body', 'published' => 'Y', 'created' => '2007-03-18 10:43:23', 'updated' => '2007-03-18 10:45:31') ); } ?> \ No newline at end of file