From 2e0acbf505fa4053aaf5d333a46dd08d9548b6da Mon Sep 17 00:00:00 2001 From: mark_story Date: Sun, 22 Nov 2009 17:56:46 -0500 Subject: [PATCH] Making habtm join conditions used by __saveMulti when finding link records to remove. It should be noted that having conditions on non-joinTable tables, and not having a model on the joinTable can cause SQL issues. Fixes #304 --- cake/libs/model/model.php | 18 ++++--- .../cases/libs/model/model_write.test.php | 50 ++++++++++++++++++- 2 files changed, 59 insertions(+), 9 deletions(-) diff --git a/cake/libs/model/model.php b/cake/libs/model/model.php index e688f1ea9..d559af5a3 100644 --- a/cake/libs/model/model.php +++ b/cake/libs/model/model.php @@ -1302,14 +1302,6 @@ class Model extends Overloadable { if (isset($this->hasAndBelongsToMany[$assoc])) { list($join) = $this->joinModel($this->hasAndBelongsToMany[$assoc]['with']); - $conditions = array($join . '.' . $this->hasAndBelongsToMany[$assoc]['foreignKey'] => $id); - - $links = $this->{$join}->find('all', array( - 'conditions' => $conditions, - 'recursive' => -1, - 'fields' => $this->hasAndBelongsToMany[$assoc]['associationForeignKey'] - )); - $isUUID = !empty($this->{$join}->primaryKey) && ( $this->{$join}->_schema[$this->{$join}->primaryKey]['length'] == 36 && ( $this->{$join}->_schema[$this->{$join}->primaryKey]['type'] === 'string' || @@ -1351,6 +1343,16 @@ class Model extends Overloadable { } if ($this->hasAndBelongsToMany[$assoc]['unique']) { + $conditions = array_merge( + array($join . '.' . $this->hasAndBelongsToMany[$assoc]['foreignKey'] => $id), + (array)$this->hasAndBelongsToMany[$assoc]['conditions'] + ); + $links = $this->{$join}->find('all', array( + 'conditions' => $conditions, + 'recursive' => empty($this->hasAndBelongsToMany[$assoc]['conditions']) ? -1 : 0, + 'fields' => $this->hasAndBelongsToMany[$assoc]['associationForeignKey'] + )); + $associationForeignKey = "{$join}." . $this->hasAndBelongsToMany[$assoc]['associationForeignKey']; $oldLinks = Set::extract($links, "{n}.{$associationForeignKey}"); if (!empty($oldLinks)) { diff --git a/cake/tests/cases/libs/model/model_write.test.php b/cake/tests/cases/libs/model/model_write.test.php index 4d969cca9..2931b4be2 100644 --- a/cake/tests/cases/libs/model/model_write.test.php +++ b/cake/tests/cases/libs/model/model_write.test.php @@ -609,7 +609,7 @@ class ModelWriteTest extends BaseModelTest { function testBeforeValidateSaveAbortion() { $Model =& new CallbackPostTestModel(); $Model->beforeValidateReturn = false; - + $data = array( 'title' => 'new article', 'body' => 'this is some text.' @@ -1992,6 +1992,54 @@ class ModelWriteTest extends BaseModelTest { )); $this->assertEqual($result, $expected); } +/** + * test that saving habtm records respects conditions set in the the 'conditions' key + * for the association. + * + * @return void + */ + function testHabtmSaveWithConditionsInAssociation() { + $this->loadFixtures('JoinThing', 'Something', 'SomethingElse'); + $Something =& new Something(); + $Something->unbindModel(array('hasAndBelongsToMany' => array('SomethingElse')), false); + + $Something->bindModel(array( + 'hasAndBelongsToMany' => array( + 'DoomedSomethingElse' => array( + 'className' => 'SomethingElse', + 'joinTable' => 'join_things', + 'conditions' => 'JoinThing.doomed = 1', + 'unique' => true + ), + 'NotDoomedSomethingElse' => array( + 'className' => 'SomethingElse', + 'joinTable' => 'join_things', + 'conditions' => array('JoinThing.doomed' => 0), + 'unique' => true + ) + ) + ), false); + $result = $Something->read(null, 1); + $this->assertTrue(empty($result['NotDoomedSomethingElse'])); + $this->assertEqual(count($result['DoomedSomethingElse']), 1); + + $data = array( + 'Something' => array('id' => 1), + 'NotDoomedSomethingElse' => array( + 'NotDoomedSomethingElse' => array( + array('something_else_id' => 2, 'doomed' => 0), + array('something_else_id' => 3, 'doomed' => 0) + ) + ) + ); + $Something->create($data); + $result = $Something->save(); + $this->assertTrue($result); + + $result = $Something->read(null, 1); + $this->assertEqual(count($result['NotDoomedSomethingElse']), 2); + $this->assertEqual(count($result['DoomedSomethingElse']), 1); + } /** * testHabtmSaveKeyResolution method *