Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

API Allow the modification of extraFields on a many_many relation #754

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
35 changes: 35 additions & 0 deletions model/ManyManyList.php
Expand Up @@ -95,6 +95,41 @@ function add($item, $extraFields = null) {
} }
} }


/**
* Modify an item in this many_many relationship
* Does so by updating an entry in the joinTable.
* @param $extraFields A map of additional columns to insert into the joinTable
*/
function modify($item, $extraFields = null) {
if(is_numeric($item)) $itemID = $item;
else if($item instanceof $this->dataClass) $itemID = $item->ID;
else throw new InvalidArgumentException("ManyManyList::modify() expecting a $this->dataClass object, or ID value", E_USER_ERROR);

// Validate foreignID
if(!$this->foreignID) {
throw new Exception("ManyManyList::modify() can't be called until a foreign ID is set", E_USER_WARNING);
}

// Check relation already exists
if(!$this->find($this->localKey, $itemID)){
throw new Exception("ManyManyList::modify() can't be called unless the relation is already set", E_USER_WARNING);
}

// Modify entry/entries
foreach((array)$this->foreignID as $foreignID) {
$manipulation = array();
$manipulation[$this->joinTable]['command'] = 'update';

if($extraFields) foreach($extraFields as $k => $v) {
$manipulation[$this->joinTable]['fields'][$k] = "'" . Convert::raw2sql($v) . "'";
}

$manipulation[$this->joinTable]['where'] = "\"$this->localKey\" = $itemID AND \"$this->foreignKey\" = $foreignID";

DB::manipulate($manipulation);
}
}

/** /**
* Remove the given item from this list. * Remove the given item from this list.
* Note that for a ManyManyList, the item is never actually deleted, only the join table is affected * Note that for a ManyManyList, the item is never actually deleted, only the join table is affected
Expand Down
12 changes: 12 additions & 0 deletions tests/model/DataObjectTest.php
Expand Up @@ -770,6 +770,18 @@ function testManyManyExtraFields() {
$this->assertEquals('Sam', $player->FirstName); $this->assertEquals('Sam', $player->FirstName);
$this->assertEquals("Prop", $player->Position); $this->assertEquals("Prop", $player->Position);


// Sam deserves instead to be on the wing
$newTeam->Players()->modify($newPlayer, array("Position" => "Winger"));

// Requery and uncache everything
$newTeam->flushCache();
$newTeam = DataObject::get_by_id('DataObjectTest_Team', $newTeamID);

// Check that the modified Position many_many_extraField is extracted.
$player = $newTeam->Players()->First();
$this->assertEquals('Sam', $player->FirstName);
$this->assertEquals("Winger", $player->Position);

// Check that ordering a many-many relation by an aggregate column doesn't fail // Check that ordering a many-many relation by an aggregate column doesn't fail
$player = $this->objFromFixture('DataObjectTest_Player', 'player2'); $player = $this->objFromFixture('DataObjectTest_Player', 'player2');
$player->Teams("", "count(DISTINCT \"DataObjectTest_Team_Players\".\"DataObjectTest_PlayerID\") DESC"); $player->Teams("", "count(DISTINCT \"DataObjectTest_Team_Players\".\"DataObjectTest_PlayerID\") DESC");
Expand Down