mirror of
https://github.com/silverstripe/silverstripe-framework
synced 2024-10-22 14:05:37 +02:00
Merge pull request #10406 from creative-commoners/pulls/4/manymany-extra-fields
NEW Set many_many_extraFields data via the ORM
This commit is contained in:
commit
d79564751f
@ -433,6 +433,58 @@ class ManyManyList extends RelationList
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the extra field data for a single row of the relationship join
|
||||||
|
* table, given the known child ID.
|
||||||
|
*
|
||||||
|
* @param int $itemID The ID of the child for the relationship
|
||||||
|
* @param array $data The data to set, with field names as keys and values as values
|
||||||
|
* @throws InvalidArgumentException if the $data array is invalid
|
||||||
|
*/
|
||||||
|
public function setExtraData(int $itemID, array $data): void
|
||||||
|
{
|
||||||
|
// Don't bother doing anything if we aren't given any data
|
||||||
|
if (empty($data)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Prepare db manipulation
|
||||||
|
$foreignID = $this->getForeignID();
|
||||||
|
$manipulation = [
|
||||||
|
$this->joinTable => [
|
||||||
|
'command' => 'update',
|
||||||
|
'fields' => [],
|
||||||
|
'where' => [
|
||||||
|
"\"{$this->joinTable}\".\"{$this->foreignKey}\"" => $foreignID,
|
||||||
|
"\"{$this->joinTable}\".\"{$this->localKey}\"" => $itemID
|
||||||
|
],
|
||||||
|
],
|
||||||
|
];
|
||||||
|
|
||||||
|
/** @var DBField[] $fieldObjects */
|
||||||
|
$fieldObjects = [];
|
||||||
|
// Write extra field to manipluation in the same way
|
||||||
|
// that DataObject::prepareManipulationTable writes fields
|
||||||
|
foreach ($data as $fieldName => $value) {
|
||||||
|
if (!array_key_exists($fieldName, $this->extraFields)) {
|
||||||
|
throw new InvalidArgumentException("Field '$fieldName' is not defined in many_many_extraFields for this relationship");
|
||||||
|
}
|
||||||
|
$fieldObject = Injector::inst()->create($this->extraFields[$fieldName], $fieldName);
|
||||||
|
// Make sure the field assignment is not an array unless the field allows non-scalar values
|
||||||
|
if (is_array($value) && $fieldObject->scalarValueOnly()) {
|
||||||
|
throw new InvalidArgumentException(
|
||||||
|
'ManyManyList::setExtraData: parameterised field assignments are disallowed'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
// Set the value into the manipulation
|
||||||
|
$fieldObject->setValue($value);
|
||||||
|
$fieldObject->writeToManipulation($manipulation[$this->joinTable]);
|
||||||
|
$fieldObjects[$fieldName] = $fieldObject;
|
||||||
|
}
|
||||||
|
|
||||||
|
DB::manipulate($manipulation);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Find the extra field data for a single row of the relationship join
|
* Find the extra field data for a single row of the relationship join
|
||||||
* table, given the known child ID.
|
* table, given the known child ID.
|
||||||
|
@ -11,7 +11,6 @@ use SilverStripe\ORM\Tests\DataObjectTest\Player;
|
|||||||
use SilverStripe\ORM\Tests\DataObjectTest\Team;
|
use SilverStripe\ORM\Tests\DataObjectTest\Team;
|
||||||
use SilverStripe\ORM\Tests\ManyManyListTest\ExtraFieldsObject;
|
use SilverStripe\ORM\Tests\ManyManyListTest\ExtraFieldsObject;
|
||||||
use SilverStripe\ORM\Tests\ManyManyListTest\Product;
|
use SilverStripe\ORM\Tests\ManyManyListTest\Product;
|
||||||
use InvalidArgumentException;
|
|
||||||
|
|
||||||
class ManyManyListTest extends SapphireTest
|
class ManyManyListTest extends SapphireTest
|
||||||
{
|
{
|
||||||
@ -73,7 +72,7 @@ class ManyManyListTest extends SapphireTest
|
|||||||
|
|
||||||
// the actual test is that this does not generate an error in the sql.
|
// the actual test is that this does not generate an error in the sql.
|
||||||
$obj->Products()->add($product, [
|
$obj->Products()->add($product, [
|
||||||
'Reference' => 'Foo'
|
'Reference' => 'Foo',
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$result = $obj->Products()->First();
|
$result = $obj->Products()->First();
|
||||||
@ -81,6 +80,36 @@ class ManyManyListTest extends SapphireTest
|
|||||||
$this->assertEquals('Test Product', $result->Title);
|
$this->assertEquals('Test Product', $result->Title);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function testSetExtraData()
|
||||||
|
{
|
||||||
|
$obj = new ManyManyListTest\ExtraFieldsObject();
|
||||||
|
$obj->write();
|
||||||
|
|
||||||
|
$obj2 = new ManyManyListTest\ExtraFieldsObject();
|
||||||
|
$obj2->write();
|
||||||
|
|
||||||
|
$money = new DBMoney();
|
||||||
|
$money->setAmount(100);
|
||||||
|
$money->setCurrency('USD');
|
||||||
|
|
||||||
|
// Set some data on add
|
||||||
|
$obj->Clients()->add($obj2, [
|
||||||
|
'Worth' => $money,
|
||||||
|
'Reference' => 'Foo',
|
||||||
|
]);
|
||||||
|
// Change the data afterward
|
||||||
|
$money->setAmount(50);
|
||||||
|
$obj->Clients()->setExtraData($obj2->ID, [
|
||||||
|
'Worth' => $money,
|
||||||
|
'Reference' => 'Bar',
|
||||||
|
]);
|
||||||
|
|
||||||
|
$result = $obj->Clients()->First();
|
||||||
|
$this->assertEquals('Bar', $result->Reference, 'Basic scalar fields should exist');
|
||||||
|
$this->assertInstanceOf(DBMoney::class, $result->Worth, 'Composite fields should exist on the record');
|
||||||
|
$this->assertEquals(50, $result->Worth->getAmount());
|
||||||
|
}
|
||||||
|
|
||||||
public function testCreateList()
|
public function testCreateList()
|
||||||
{
|
{
|
||||||
$list = ManyManyList::create(
|
$list = ManyManyList::create(
|
||||||
|
Loading…
Reference in New Issue
Block a user