mirror of
https://github.com/silverstripe/silverstripe-framework
synced 2024-10-22 14:05:37 +02:00
BUG Renable the ability to do dynamic assignment with DBField
This commit is contained in:
parent
ab5f09a9f3
commit
4ec1a682cf
@ -1362,8 +1362,11 @@ class DataObject extends ViewableData implements DataObjectInterface, i18nEntity
|
||||
if (!isset($tableManipulation['fields'])) {
|
||||
continue;
|
||||
}
|
||||
foreach ($tableManipulation['fields'] as $fieldValue) {
|
||||
foreach ($tableManipulation['fields'] as $fieldName => $fieldValue) {
|
||||
if (is_array($fieldValue)) {
|
||||
$dbObject = $this->dbObject($fieldName);
|
||||
// If the field allows non-scalar values we'll let it do dynamic assignments
|
||||
if ($dbObject && $dbObject->scalarValueOnly()) {
|
||||
user_error(
|
||||
'DataObject::writeManipulation: parameterised field assignments are disallowed',
|
||||
E_USER_ERROR
|
||||
@ -1371,6 +1374,7 @@ class DataObject extends ViewableData implements DataObjectInterface, i18nEntity
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Perform the manipulation
|
||||
DB::manipulate($manipulation);
|
||||
|
@ -254,8 +254,10 @@ class ManyManyList extends RelationList {
|
||||
);
|
||||
}
|
||||
|
||||
/** @var DBField[] $fieldObjects */
|
||||
$fieldObjects = array();
|
||||
if($extraFields && $this->extraFields) {
|
||||
// Write extra field to manipluation in the same way
|
||||
// Write extra field to manipulation in the same way
|
||||
// that DataObject::prepareManipulationTable writes fields
|
||||
foreach($this->extraFields as $fieldName => $fieldSpec) {
|
||||
// Skip fields without an assignment
|
||||
@ -263,6 +265,7 @@ class ManyManyList extends RelationList {
|
||||
$fieldObject = Object::create_from_string($fieldSpec, $fieldName);
|
||||
$fieldObject->setValue($extraFields[$fieldName]);
|
||||
$fieldObject->writeToManipulation($manipulation[$this->joinTable]);
|
||||
$fieldObjects[$fieldName] = $fieldObject;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -275,14 +278,17 @@ class ManyManyList extends RelationList {
|
||||
if (!isset($tableManipulation['fields'])) {
|
||||
continue;
|
||||
}
|
||||
foreach ($tableManipulation['fields'] as $fieldValue) {
|
||||
foreach ($tableManipulation['fields'] as $fieldName => $fieldValue) {
|
||||
if (is_array($fieldValue)) {
|
||||
// If the field allows non-scalar values we'll let it do dynamic assignments
|
||||
if (isset($fieldObjects[$fieldName]) && $fieldObjects[$fieldName]->scalarValueOnly()) {
|
||||
user_error(
|
||||
'ManyManyList::add: parameterised field assignments are disallowed',
|
||||
E_USER_ERROR
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
DB::manipulate($manipulation);
|
||||
|
@ -32,6 +32,7 @@ class DataObjectTest extends SapphireTest {
|
||||
'DataObjectTest_Sortable',
|
||||
'ManyManyListTest_Product',
|
||||
'ManyManyListTest_Category',
|
||||
'MockDynamicAssignmentDataObject'
|
||||
);
|
||||
|
||||
/**
|
||||
@ -1773,6 +1774,36 @@ class DataObjectTest extends SapphireTest {
|
||||
$this->assertNotEmpty($do->CompositeMoneyField);
|
||||
}
|
||||
|
||||
|
||||
public function testWriteManipulationWithNonScalarValuesAllowed()
|
||||
{
|
||||
$do = MockDynamicAssignmentDataObject::create();
|
||||
$do->write();
|
||||
$do->StaticScalarOnlyField = true;
|
||||
$do->DynamicScalarOnlyField = false;
|
||||
$do->DynamicField = true;
|
||||
$do->write();
|
||||
$this->assertEquals(1, $do->StaticScalarOnlyField);
|
||||
$this->assertEquals(0, $do->DynamicScalarOnlyField);
|
||||
$this->assertEquals(1, $do->DynamicField);
|
||||
}
|
||||
|
||||
public function testWriteManipulationWithNonScalarValuesDisallowed()
|
||||
{
|
||||
|
||||
$do = MockDynamicAssignmentDataObject::create();
|
||||
$do->write();
|
||||
$do->StaticScalarOnlyField = false;
|
||||
$do->DynamicScalarOnlyField = true;
|
||||
$do->DynamicField = false;
|
||||
|
||||
try {
|
||||
$do->write();
|
||||
$this->fail("Expected exception \"parameterised field assignments are disallowed\"");
|
||||
} catch (Exception $ex) {
|
||||
$this->assertContains('parameterised field assignments are disallowed', $ex->getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class DataObjectTest_Sortable extends DataObject implements TestOnly {
|
||||
|
@ -21,6 +21,7 @@ class ManyManyListTest extends SapphireTest {
|
||||
'ManyManyListTest_ExtraFields',
|
||||
'ManyManyListTest_Product',
|
||||
'ManyManyListTest_Category',
|
||||
'MockDynamicAssignmentDataObject',
|
||||
);
|
||||
|
||||
|
||||
@ -306,7 +307,41 @@ class ManyManyListTest extends SapphireTest {
|
||||
$this->assertEquals(1, $productsRelatedToProductB->count());
|
||||
}
|
||||
|
||||
public function testWriteManipulationWithNonScalarValuesAllowed()
|
||||
{
|
||||
$left = MockDynamicAssignmentDataObject::create();
|
||||
$left->write();
|
||||
$right = MockDynamicAssignmentDataObject::create();
|
||||
$right->write();
|
||||
$left->MockManyMany()->add($right, array(
|
||||
'ManyManyStaticScalarOnlyField' => true,
|
||||
'ManyManyDynamicScalarOnlyField' => false,
|
||||
'ManyManyDynamicField' => true
|
||||
));
|
||||
$pivot = $left->MockManyMany()->first();
|
||||
$this->assertEquals(1, $pivot->ManyManyStaticScalarOnlyField);
|
||||
$this->assertEquals(0, $pivot->ManyManyDynamicScalarOnlyField);
|
||||
$this->assertEquals(1, $pivot->ManyManyDynamicField);
|
||||
}
|
||||
|
||||
public function testWriteManipulationWithNonScalarValuesDisallowed()
|
||||
{
|
||||
$left = MockDynamicAssignmentDataObject::create();
|
||||
$left->write();
|
||||
$right = MockDynamicAssignmentDataObject::create();
|
||||
$right->write();
|
||||
|
||||
try {
|
||||
$left->MockManyMany()->add($right, array(
|
||||
'ManyManyStaticScalarOnlyField' => true,
|
||||
'ManyManyDynamicScalarOnlyField' => false,
|
||||
'ManyManyDynamicField' => true
|
||||
));
|
||||
$this->fail("Expected exception \"parameterised field assignments are disallowed\"");
|
||||
} catch (Exception $ex) {
|
||||
$this->assertContains('parameterised field assignments are disallowed', $ex->getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
49
tests/model/Mock/MockDynamicAssignmentDBField.php
Normal file
49
tests/model/Mock/MockDynamicAssignmentDBField.php
Normal file
@ -0,0 +1,49 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This is a fake DB field specifically design to test dynamic value assignment. You can set `scalarValueOnly` in
|
||||
* the constructor. You can control whetever the field will try to do a dynamic assignment by specifing
|
||||
* `$dynamicAssignment` in nthe consturctor.
|
||||
*
|
||||
* If the field is set to false, it will try to do a plain assignment. This is so you can save the initial value no
|
||||
* matter what. If the field is set to true, it will try to do a dynamic assignment.
|
||||
*/
|
||||
class MockDynamicAssignmentDBField extends Boolean
|
||||
{
|
||||
|
||||
private $scalarOnly;
|
||||
private $dynamicAssignment;
|
||||
|
||||
/**
|
||||
* @param $name
|
||||
* @param boolean $scalarOnly Whether our fake field should be scalar only.
|
||||
* @param boolean $dynamicAssignment Whether our fake field will try to do a dynamic assignment.
|
||||
*/
|
||||
public function __construct($name = '', $scalarOnly = false, $dynamicAssignment = false)
|
||||
{
|
||||
$this->scalarOnly = $scalarOnly;
|
||||
$this->dynamicAssignment = $dynamicAssignment;
|
||||
parent::__construct($name);
|
||||
}
|
||||
|
||||
/**
|
||||
* If the field value and dynamicAssignment are true, we'll try to do a dynamic assignment
|
||||
* @param $value
|
||||
* @return array|int|mixed
|
||||
*/
|
||||
public function prepValueForDB($value)
|
||||
{
|
||||
if ($value) {
|
||||
return $this->dynamicAssignment
|
||||
? array('GREATEST(?, ?)' => array(0, 1))
|
||||
: 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
public function scalarValueOnly()
|
||||
{
|
||||
return $this->scalarOnly;
|
||||
}
|
||||
}
|
44
tests/model/Mock/MockDynamicAssignmentDataObject.php
Normal file
44
tests/model/Mock/MockDynamicAssignmentDataObject.php
Normal file
@ -0,0 +1,44 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This is a fake DB field specifically design to test dynamic value assignment
|
||||
* @property boolean $StaticScalarOnlyField
|
||||
* @property boolean $DynamicScalarOnlyField
|
||||
* @property boolean $DynamicField
|
||||
* @method ManyManyList MockManyMany
|
||||
*/
|
||||
class MockDynamicAssignmentDataObject extends DataObject implements TestOnly
|
||||
{
|
||||
|
||||
private static $db = array(
|
||||
// This field only emits scalar value and will save
|
||||
'StaticScalarOnlyField' => 'MockDynamicAssignmentDBField(1,0)',
|
||||
|
||||
// This field tries to emit dynamic assignment but will fail because of scalar only
|
||||
'DynamicScalarOnlyField' => 'MockDynamicAssignmentDBField(1,1)',
|
||||
|
||||
// This field does dynamic assignment and will pass
|
||||
'DynamicField' => 'MockDynamicAssignmentDBField(0,1)',
|
||||
);
|
||||
|
||||
private static $many_many = array(
|
||||
"MockManyMany" => 'MockDynamicAssignmentDataObject'
|
||||
);
|
||||
|
||||
private static $belongs_many_many = array(
|
||||
"MockBelongsManyMany" => 'MockDynamicAssignmentDataObject'
|
||||
);
|
||||
|
||||
private static $many_many_extraFields = array(
|
||||
'MockManyMany' => array(
|
||||
// This field only emits scalar value and will save
|
||||
'ManyManyStaticScalarOnlyField' => 'MockDynamicAssignmentDBField(1,0)',
|
||||
|
||||
// This field tries to emit dynamic assignment but will fail because of scalar only
|
||||
'ManyManyDynamicScalarOnlyField' => 'MockDynamicAssignmentDBField(1,1)',
|
||||
|
||||
// This field does dynamic assignment and will pass
|
||||
'ManyManyDynamicField' => 'MockDynamicAssignmentDBField(0,1)',
|
||||
)
|
||||
);
|
||||
}
|
Loading…
Reference in New Issue
Block a user