From 51bae9e4a6bdafcdee7d18d6e25cee37ad72f189 Mon Sep 17 00:00:00 2001 From: Ingo Schommer Date: Tue, 6 Mar 2012 16:34:51 +0100 Subject: [PATCH] ENHANCEMENT Allowing to save ManyManyList with multiple foreign keys (e.g. required to add to an overloaded Group->Members() relationship) --- model/DataQuery.php | 2 +- model/ManyManyList.php | 27 +++++++++++++-------------- model/RelationList.php | 10 ++++++++++ tests/model/DataObjectTest.yml | 3 ++- tests/model/ManyManyListTest.php | 16 +++++++++++++++- 5 files changed, 41 insertions(+), 17 deletions(-) diff --git a/model/DataQuery.php b/model/DataQuery.php index 25a44f4ab..a11dca4e0 100644 --- a/model/DataQuery.php +++ b/model/DataQuery.php @@ -62,7 +62,7 @@ class DataQuery { } } - if(!$matched) user_error("Couldn't find $fieldExpression in the query filter.", E_USER_WARNING); + if(!$matched) throw new InvalidArgumentException("Couldn't find $fieldExpression in the query filter."); return $this; } diff --git a/model/ManyManyList.php b/model/ManyManyList.php index 5ddb2b053..70fd32245 100644 --- a/model/ManyManyList.php +++ b/model/ManyManyList.php @@ -93,25 +93,24 @@ class ManyManyList extends RelationList { if(!$this->foreignID) { throw new Exception("ManyManyList::add() can't be called until a foreign ID is set", E_USER_WARNING); } - if(is_array($this->foreignID)) { - throw new Exception("ManyManyList::add() can't be called on a list linked to mulitple foreign IDs", E_USER_WARNING); - } - + // Delete old entries, to prevent duplication $this->removeById($itemID); - // Insert new entry - $manipulation = array(); - $manipulation[$this->joinTable]['command'] = 'insert'; + // Insert new entry/entries + foreach((array)$this->foreignID as $foreignID) { + $manipulation = array(); + $manipulation[$this->joinTable]['command'] = 'insert'; - if($extraFields) foreach($extraFields as $k => $v) { - $manipulation[$this->joinTable]['fields'][$k] = "'" . Convert::raw2sql($v) . "'"; + if($extraFields) foreach($extraFields as $k => $v) { + $manipulation[$this->joinTable]['fields'][$k] = "'" . Convert::raw2sql($v) . "'"; + } + + $manipulation[$this->joinTable]['fields'][$this->localKey] = $itemID; + $manipulation[$this->joinTable]['fields'][$this->foreignKey] = $foreignID; + + DB::manipulate($manipulation); } - - $manipulation[$this->joinTable]['fields'][$this->localKey] = $itemID; - $manipulation[$this->joinTable]['fields'][$this->foreignKey] = $this->foreignID; - - DB::manipulate($manipulation); } /** diff --git a/model/RelationList.php b/model/RelationList.php index 27f72f6d0..993769a79 100644 --- a/model/RelationList.php +++ b/model/RelationList.php @@ -14,11 +14,21 @@ abstract class RelationList extends DataList { * @param $id A single ID, or an array of IDs */ function setForeignID($id) { + // If already filtered on foreign ID, remove that first + if($this->foreignID !== null) { + $oldFilter = $this->foreignIDFilter(); + try { + $this->dataQuery->removeFilterOn($oldFilter); + } catch(InvalidArgumentException $e) {} + } + // Turn a 1-element array into a simple value if(is_array($id) && sizeof($id) == 1) $id = reset($id); $this->foreignID = $id; $this->dataQuery->where($this->foreignIDFilter()); + + return $this; } /** diff --git a/tests/model/DataObjectTest.yml b/tests/model/DataObjectTest.yml index df1f695e3..3e40f1cde 100644 --- a/tests/model/DataObjectTest.yml +++ b/tests/model/DataObjectTest.yml @@ -3,7 +3,8 @@ DataObjectTest_Team: Title: Team 1 team2: Title: Team 2 - + team3: + Title: Team 3 DataObjectTest_Player: captain1: FirstName: Captain diff --git a/tests/model/ManyManyListTest.php b/tests/model/ManyManyListTest.php index 158f095f7..b16f741a7 100644 --- a/tests/model/ManyManyListTest.php +++ b/tests/model/ManyManyListTest.php @@ -33,7 +33,7 @@ class ManyManyListTest extends SapphireTest { $compareTeams->byID($team1->ID); $this->assertEquals($player1->Teams()->column('ID'),$compareTeams->column('ID'),"Adding single record as DataObject to many_many"); } - + public function testRemovingSingleDataObjectByReference() { $player1 = $this->objFromFixture('DataObjectTest_Player', 'player1'); $team1 = $this->objFromFixture('DataObjectTest_Team', 'team1'); @@ -78,6 +78,20 @@ class ManyManyListTest extends SapphireTest { $player1->Teams()->setByIdList(array($team2->ID)); $this->assertEquals(array($team2->ID), $player1->Teams()->column()); } + + public function testAddingWithMultipleForeignKeys() { + $newPlayer = new DataObjectTest_Player(); + $newPlayer->write(); + $team1 = $this->objFromFixture('DataObjectTest_Team', 'team1'); + $team2 = $this->objFromFixture('DataObjectTest_Team', 'team2'); + + $playersTeam1Team2 = DataList::create('DataObjectTest_Team')->relation('Players')->setForeignID(array($team1->ID, $team2->ID)); + $playersTeam1Team2->add($newPlayer); + $this->assertEquals( + array($team1->ID, $team2->ID), + $newPlayer->Teams()->column('ID') + ); + } public function testSubtractOnAManyManyList() { $allList = ManyManyList::create('DataObjectTest_Player', 'DataObjectTest_Team_Players','DataObjectTest_PlayerID', 'DataObjectTest_TeamID');