mirror of
https://github.com/silverstripe/silverstripe-framework
synced 2024-10-22 14:05:37 +02:00
NEW: Allows setting of has_many and many_many relations before writing
Adds a new wrapper list, UnsavedRelationList, that maintains the relations until writing, where it is converted into the correct RelationList.
This commit is contained in:
parent
fbfff8df28
commit
bbc4443af7
@ -553,13 +553,25 @@ See `[api:DataObject::$has_many]` for more info on the described relations.
|
||||
|
||||
// can be accessed by $myTeam->ActivePlayers()
|
||||
public function ActivePlayers() {
|
||||
return $this->Players("Status='Active'");
|
||||
return $this->Players()->filter('Status', 'Active');
|
||||
}
|
||||
}
|
||||
|
||||
Note: Adding new records to a filtered `RelationList` like in the example above doesn't automatically set the
|
||||
filtered criteria on the added record.
|
||||
|
||||
### Relations on Unsaved Objects
|
||||
|
||||
You can also set *has_many* and *many_many* relations before the `DataObject` is saved. This behaviour uses the
|
||||
`[api:UnsavedRelationList]` and converts it into the correct `RelationList` when saving the `DataObject` for the
|
||||
first time.
|
||||
|
||||
This unsaved lists will also recursively save any unsaved objects that they contain.
|
||||
|
||||
As these lists are not backed by the database, most of the filtering methods on `DataList` cannot be used on a
|
||||
list of this type. As such, an `UnsavedRelationList` should only be used for setting a relation before saving an
|
||||
object, not for displaying the objects contained in the relation.
|
||||
|
||||
## Validation and Constraints
|
||||
|
||||
Traditionally, validation in SilverStripe has been mostly handled on the controller
|
||||
|
@ -12,7 +12,7 @@ class ArrayList extends ViewableData implements SS_List, SS_Filterable, SS_Sorta
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $items;
|
||||
protected $items = array();
|
||||
|
||||
/**
|
||||
*
|
||||
|
@ -157,6 +157,11 @@ class DataObject extends ViewableData implements DataObjectInterface, i18nEntity
|
||||
*/
|
||||
protected $components;
|
||||
|
||||
/**
|
||||
* Non-static cache of has_many and many_many relations that can't be written until this object is saved.
|
||||
*/
|
||||
protected $unsavedRelations;
|
||||
|
||||
/**
|
||||
* Returns when validation on DataObjects is enabled.
|
||||
* @return bool
|
||||
@ -1188,6 +1193,15 @@ class DataObject extends ViewableData implements DataObjectInterface, i18nEntity
|
||||
}
|
||||
|
||||
DB::manipulate($manipulation);
|
||||
|
||||
// If there's any relations that couldn't be saved before, save them now (we have an ID here)
|
||||
if($this->unsavedRelations) {
|
||||
foreach($this->unsavedRelations as $name => $list) {
|
||||
$list->changeToList($this->$name());
|
||||
}
|
||||
$this->unsavedRelations = array();
|
||||
}
|
||||
|
||||
$this->onAfterWrite();
|
||||
|
||||
$this->changed = null;
|
||||
@ -1365,6 +1379,15 @@ class DataObject extends ViewableData implements DataObjectInterface, i18nEntity
|
||||
. " on class '$this->class'", E_USER_ERROR);
|
||||
}
|
||||
|
||||
// If we haven't been written yet, we can't save these relations, so use a list that handles this case
|
||||
if(!$this->ID) {
|
||||
if(!isset($this->unsavedRelations[$componentName])) {
|
||||
$this->unsavedRelations[$componentName] =
|
||||
new UnsavedRelationList($this->class, $componentName, $componentClass);
|
||||
}
|
||||
return $this->unsavedRelations[$componentName];
|
||||
}
|
||||
|
||||
$joinField = $this->getRemoteJoinField($componentName, 'has_many');
|
||||
|
||||
$result = new HasManyList($componentClass, $joinField);
|
||||
@ -1473,6 +1496,15 @@ class DataObject extends ViewableData implements DataObjectInterface, i18nEntity
|
||||
*/
|
||||
public function getManyManyComponents($componentName, $filter = "", $sort = "", $join = "", $limit = "") {
|
||||
list($parentClass, $componentClass, $parentField, $componentField, $table) = $this->many_many($componentName);
|
||||
|
||||
// If we haven't been written yet, we can't save these relations, so use a list that handles this case
|
||||
if(!$this->ID) {
|
||||
if(!isset($this->unsavedRelations[$componentName])) {
|
||||
$this->unsavedRelations[$componentName] =
|
||||
new UnsavedRelationList($parentClass, $componentName, $componentClass);
|
||||
}
|
||||
return $this->unsavedRelations[$componentName];
|
||||
}
|
||||
|
||||
$result = Injector::inst()->create('ManyManyList', $componentClass, $table, $componentField, $parentField,
|
||||
$this->many_many_extraFields($componentName));
|
||||
|
432
model/UnsavedRelationList.php
Normal file
432
model/UnsavedRelationList.php
Normal file
@ -0,0 +1,432 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* An ArrayList that represents an unsaved relation.
|
||||
*
|
||||
* has_many and many_many relations cannot be saved until after the DataObject they're
|
||||
* on has been written. This List pretends to be a RelationList and stores the related
|
||||
* objects in memory.
|
||||
*
|
||||
* It can store both saved objects (as IDs) or unsaved objects (as instances of
|
||||
* $dataClass). Unsaved objects are then written when the list is saved into an instance
|
||||
* of RelationList.
|
||||
*
|
||||
* Most methods that alter the list of objects throw LogicExceptions.
|
||||
*/
|
||||
class UnsavedRelationList extends ArrayList {
|
||||
/**
|
||||
* The DataObject class name that this relation is on
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $baseClass;
|
||||
|
||||
/**
|
||||
* The name of the relation
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $relationName;
|
||||
|
||||
/**
|
||||
* The DataObject class name that this relation is querying
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $dataClass;
|
||||
|
||||
/**
|
||||
* The extra fields associated with the relation
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $extraFields = array();
|
||||
|
||||
/**
|
||||
* Create a new UnsavedRelationList
|
||||
*
|
||||
* @param string $dataClass The DataObject class used in the relation
|
||||
*/
|
||||
public function __construct($baseClass, $relationName, $dataClass) {
|
||||
$this->baseClass = $baseClass;
|
||||
$this->relationName = $relationName;
|
||||
$this->dataClass = $dataClass;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add an item to this relationship
|
||||
*
|
||||
* @param $extraFields A map of additional columns to insert into the joinTable in the case of a many_many relation
|
||||
*/
|
||||
public function add($item, $extraFields = null) {
|
||||
$this->push($item, $extraFields);
|
||||
}
|
||||
|
||||
/**
|
||||
* Save all the items in this list into the RelationList
|
||||
*
|
||||
* @param RelationList $list
|
||||
*/
|
||||
public function changeToList(RelationList $list) {
|
||||
foreach($this->items as $key => $item) {
|
||||
if(is_object($item)) {
|
||||
$item->write();
|
||||
}
|
||||
$list->add($item, $this->extraFields[$key]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Pushes an item onto the end of this list.
|
||||
*
|
||||
* @param array|object $item
|
||||
*/
|
||||
public function push($item, $extraFields = null) {
|
||||
if((is_object($item) && !$item instanceof $this->dataClass)
|
||||
|| (!is_object($item) && !is_numeric($item))) {
|
||||
throw new InvalidArgumentException(
|
||||
"UnsavedRelationList::add() expecting a $this->dataClass object, or ID value",
|
||||
E_USER_ERROR);
|
||||
}
|
||||
if(is_object($item) && $item->ID) {
|
||||
$item = $item->ID;
|
||||
}
|
||||
$this->extraFields[] = $extraFields;
|
||||
parent::push($item);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the dataClass name for this relation, ie the DataObject ClassName
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function dataClass() {
|
||||
return $this->dataClass;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an Iterator for this relation.
|
||||
*
|
||||
* @return ArrayIterator
|
||||
*/
|
||||
public function getIterator() {
|
||||
return new ArrayIterator($this->toArray());
|
||||
}
|
||||
|
||||
/**
|
||||
* Return an array of the actual items that this relation contains at this stage.
|
||||
* This is when the query is actually executed.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function toArray() {
|
||||
$items = array();
|
||||
foreach($this->items as $key => $item) {
|
||||
if(is_numeric($item)) {
|
||||
$item = DataObject::get_by_id($this->dataClass, $item);
|
||||
}
|
||||
if(!empty($this->extraFields[$key])) {
|
||||
$item->update($this->extraFields[$key]);
|
||||
}
|
||||
$items[] = $item;
|
||||
}
|
||||
return $items;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a number of items to the relation.
|
||||
*
|
||||
* @param array $items Items to add, as either DataObjects or IDs.
|
||||
* @return DataList
|
||||
*/
|
||||
public function addMany($items) {
|
||||
foreach($items as $item) {
|
||||
$this->add($item);
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the given column can be used to filter the records.
|
||||
*/
|
||||
public function canFilterBy($by) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns true if the given column can be used to sort the records.
|
||||
*/
|
||||
public function canSortBy($by) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove all items from this relation.
|
||||
*/
|
||||
public function removeAll() {
|
||||
$this->items = array();
|
||||
$this->extraFields = array();
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the items from this list with the given IDs
|
||||
*
|
||||
* @param array $idList
|
||||
*/
|
||||
public function removeMany($items) {
|
||||
$this->items = array_diff($this->items, $items);
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes items from this list which are equal.
|
||||
*
|
||||
* @param string $field unused
|
||||
*/
|
||||
public function removeDuplicates($field = 'ID') {
|
||||
$this->items = array_unique($this->items);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the Relation to be the given ID list.
|
||||
* Records will be added and deleted as appropriate.
|
||||
*
|
||||
* @param array $idList List of IDs.
|
||||
*/
|
||||
public function setByIDList($idList) {
|
||||
$this->removeAll();
|
||||
$this->addMany($idList);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the first item in the list
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function first() {
|
||||
$item = reset($this->items);
|
||||
if(is_numeric($item)) {
|
||||
$item = DataObject::get_by_id($this->dataClass, $item);
|
||||
}
|
||||
if(!empty($this->extraFields[key($this->items)])) {
|
||||
$item->update($this->extraFields[key($this->items)]);
|
||||
}
|
||||
return $item;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the last item in the list
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function last() {
|
||||
$item = end($this->items);
|
||||
if(!empty($this->extraFields[key($this->items)])) {
|
||||
$item->update($this->extraFields[key($this->items)]);
|
||||
}
|
||||
return $item;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an array of a single field value for all items in the list.
|
||||
*
|
||||
* @param string $colName
|
||||
* @return array
|
||||
*/
|
||||
public function column($colName = 'ID') {
|
||||
$list = new ArrayList($this->toArray());
|
||||
return $list->column('ID');
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the ID of the record that this RelationList is linking.
|
||||
*
|
||||
* Adds the
|
||||
*
|
||||
* @param $id A single ID, or an array of IDs
|
||||
*/
|
||||
public function setForeignID($id) {
|
||||
$class = singleton($this->baseClass);
|
||||
$class->ID = 1;
|
||||
return $class->{$this->relationName}()->setForeignID($id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a copy of this list with the relationship linked to the given foreign ID.
|
||||
* @param $id An ID or an array of IDs.
|
||||
*/
|
||||
public function forForeignID($id) {
|
||||
return $this->setForeignID($id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the DBField object that represents the given field on the related class.
|
||||
*
|
||||
* @param string $fieldName Name of the field
|
||||
* @return DBField The field as a DBField object
|
||||
*/
|
||||
public function dbObject($fieldName) {
|
||||
return singleton($this->dataClass)->dbObject($fieldName);
|
||||
}
|
||||
|
||||
/**#@+
|
||||
* Prevents calling DataList methods that rely on the objects being saved
|
||||
*/
|
||||
public function addFilter() {
|
||||
throw new LogicException(__FUNCTION__ . " can't be called on an UnsavedRelationList.");
|
||||
}
|
||||
|
||||
public function alterDataQuery() {
|
||||
throw new LogicException(__FUNCTION__ . " can't be called on an UnsavedRelationList.");
|
||||
}
|
||||
|
||||
public function avg() {
|
||||
throw new LogicException(__FUNCTION__ . " can't be called on an UnsavedRelationList.");
|
||||
}
|
||||
|
||||
public function byIDs() {
|
||||
throw new LogicException(__FUNCTION__ . " can't be called on an UnsavedRelationList.");
|
||||
}
|
||||
|
||||
public function byID($id) {
|
||||
throw new LogicException(__FUNCTION__ . " can't be called on an UnsavedRelationList.");
|
||||
}
|
||||
|
||||
public function dataQuery() {
|
||||
throw new LogicException(__FUNCTION__ . " can't be called on an UnsavedRelationList.");
|
||||
}
|
||||
|
||||
public function exclude() {
|
||||
throw new LogicException(__FUNCTION__ . " can't be called on an UnsavedRelationList.");
|
||||
}
|
||||
|
||||
public function filter() {
|
||||
throw new LogicException(__FUNCTION__ . " can't be called on an UnsavedRelationList.");
|
||||
}
|
||||
|
||||
public function getIDList() {
|
||||
throw new LogicException(__FUNCTION__ . " can't be called on an UnsavedRelationList.");
|
||||
}
|
||||
|
||||
public function getRange($offset, $length) {
|
||||
throw new LogicException(__FUNCTION__ . " can't be called on an UnsavedRelationList.");
|
||||
}
|
||||
|
||||
public function getRelationName() {
|
||||
throw new LogicException(__FUNCTION__ . " can't be called on an UnsavedRelationList.");
|
||||
}
|
||||
|
||||
public function innerJoin() {
|
||||
throw new LogicException(__FUNCTION__ . " can't be called on an UnsavedRelationList.");
|
||||
}
|
||||
|
||||
public function insertFirst() {
|
||||
throw new LogicException(__FUNCTION__ . " can't be called on an UnsavedRelationList.");
|
||||
}
|
||||
|
||||
public function join() {
|
||||
throw new LogicException(__FUNCTION__ . " can't be called on an UnsavedRelationList.");
|
||||
}
|
||||
|
||||
public function leftJoin() {
|
||||
throw new LogicException(__FUNCTION__ . " can't be called on an UnsavedRelationList.");
|
||||
}
|
||||
|
||||
public function limit($length, $offset = 0) {
|
||||
throw new LogicException(__FUNCTION__ . " can't be called on an UnsavedRelationList.");
|
||||
}
|
||||
|
||||
public function map($keyField = 'ID', $titleField = 'Title') {
|
||||
throw new LogicException(__FUNCTION__ . " can't be called on an UnsavedRelationList.");
|
||||
}
|
||||
|
||||
public function max() {
|
||||
throw new LogicException(__FUNCTION__ . " can't be called on an UnsavedRelationList.");
|
||||
}
|
||||
|
||||
public function merge($with) {
|
||||
throw new LogicException(__FUNCTION__ . " can't be called on an UnsavedRelationList.");
|
||||
}
|
||||
|
||||
public function min() {
|
||||
throw new LogicException(__FUNCTION__ . " can't be called on an UnsavedRelationList.");
|
||||
}
|
||||
|
||||
public function newObject() {
|
||||
throw new LogicException(__FUNCTION__ . " can't be called on an UnsavedRelationList.");
|
||||
}
|
||||
|
||||
public function offsetExists($offset) {
|
||||
throw new LogicException(__FUNCTION__ . " can't be called on an UnsavedRelationList.");
|
||||
}
|
||||
|
||||
public function offsetGet($offset) {
|
||||
throw new LogicException(__FUNCTION__ . " can't be called on an UnsavedRelationList.");
|
||||
}
|
||||
|
||||
public function offsetSet($offset, $value) {
|
||||
throw new LogicException(__FUNCTION__ . " can't be called on an UnsavedRelationList.");
|
||||
}
|
||||
|
||||
public function offsetUnset($offset) {
|
||||
throw new LogicException(__FUNCTION__ . " can't be called on an UnsavedRelationList.");
|
||||
}
|
||||
|
||||
public function pop() {
|
||||
throw new LogicException(__FUNCTION__ . " can't be called on an UnsavedRelationList.");
|
||||
}
|
||||
|
||||
public function relation() {
|
||||
throw new LogicException(__FUNCTION__ . " can't be called on an UnsavedRelationList.");
|
||||
}
|
||||
|
||||
public function removeByFilter() {
|
||||
throw new LogicException(__FUNCTION__ . " can't be called on an UnsavedRelationList.");
|
||||
}
|
||||
|
||||
public function removeByID() {
|
||||
throw new LogicException(__FUNCTION__ . " can't be called on an UnsavedRelationList.");
|
||||
}
|
||||
|
||||
public function reverse() {
|
||||
throw new LogicException(__FUNCTION__ . " can't be called on an UnsavedRelationList.");
|
||||
}
|
||||
|
||||
public function setDataModel() {
|
||||
throw new LogicException(__FUNCTION__ . " can't be called on an UnsavedRelationList.");
|
||||
}
|
||||
|
||||
public function setDataQuery() {
|
||||
throw new LogicException(__FUNCTION__ . " can't be called on an UnsavedRelationList.");
|
||||
}
|
||||
|
||||
public function setQueriedColumns() {
|
||||
throw new LogicException(__FUNCTION__ . " can't be called on an UnsavedRelationList.");
|
||||
}
|
||||
|
||||
public function shift() {
|
||||
throw new LogicException(__FUNCTION__ . " can't be called on an UnsavedRelationList.");
|
||||
}
|
||||
|
||||
public function sql() {
|
||||
throw new LogicException(__FUNCTION__ . " can't be called on an UnsavedRelationList.");
|
||||
}
|
||||
|
||||
public function subtract() {
|
||||
throw new LogicException(__FUNCTION__ . " can't be called on an UnsavedRelationList.");
|
||||
}
|
||||
|
||||
public function sum() {
|
||||
throw new LogicException(__FUNCTION__ . " can't be called on an UnsavedRelationList.");
|
||||
}
|
||||
|
||||
public function unshift($item) {
|
||||
throw new LogicException(__FUNCTION__ . " can't be called on an UnsavedRelationList.");
|
||||
}
|
||||
|
||||
public function where() {
|
||||
throw new LogicException(__FUNCTION__ . " can't be called on an UnsavedRelationList.");
|
||||
}
|
||||
/**#@-*/
|
||||
}
|
184
tests/model/UnsavedRelationListTest.php
Normal file
184
tests/model/UnsavedRelationListTest.php
Normal file
@ -0,0 +1,184 @@
|
||||
<?php
|
||||
|
||||
class UnsavedRelationListTest extends SapphireTest {
|
||||
public static $fixture_file = 'UnsavedRelationListTest.yml';
|
||||
|
||||
protected $extraDataObjects = array('UnsavedRelationListTest_DataObject');
|
||||
|
||||
public function testReturnedList() {
|
||||
$object = new UnsavedRelationListTest_DataObject;
|
||||
$children = $object->Children();
|
||||
$siblings = $object->Siblings();
|
||||
$this->assertEquals($children, $object->Children(),
|
||||
'Returned UnsavedRelationList should be the same.');
|
||||
$this->assertEquals($siblings, $object->Siblings(),
|
||||
'Returned UnsavedRelationList should be the same.');
|
||||
|
||||
$object->write();
|
||||
$this->assertInstanceOf('RelationList', $object->Children());
|
||||
$this->assertNotEquals($children, $object->Children(),
|
||||
'Return should be a RelationList after first write');
|
||||
$this->assertInstanceOf('RelationList', $object->Siblings());
|
||||
$this->assertNotEquals($siblings, $object->Siblings(),
|
||||
'Return should be a RelationList after first write');
|
||||
}
|
||||
|
||||
public function testHasManyExisting() {
|
||||
$object = new UnsavedRelationListTest_DataObject;
|
||||
|
||||
$children = $object->Children();
|
||||
$children->add($this->objFromFixture('UnsavedRelationListTest_DataObject', 'ObjectA'));
|
||||
$children->add($this->objFromFixture('UnsavedRelationListTest_DataObject', 'ObjectB'));
|
||||
$children->add($this->objFromFixture('UnsavedRelationListTest_DataObject', 'ObjectC'));
|
||||
|
||||
$children = $object->Children();
|
||||
|
||||
$this->assertDOSEquals(array(
|
||||
array('Name' => 'A'),
|
||||
array('Name' => 'B'),
|
||||
array('Name' => 'C')
|
||||
), $children);
|
||||
|
||||
$object->write();
|
||||
|
||||
$this->assertNotEquals($children, $object->Children());
|
||||
|
||||
$this->assertDOSEquals(array(
|
||||
array('Name' => 'A'),
|
||||
array('Name' => 'B'),
|
||||
array('Name' => 'C')
|
||||
), $object->Children());
|
||||
}
|
||||
|
||||
public function testManyManyExisting() {
|
||||
$object = new UnsavedRelationListTest_DataObject;
|
||||
|
||||
$Siblings = $object->Siblings();
|
||||
$Siblings->add($this->objFromFixture('UnsavedRelationListTest_DataObject', 'ObjectA'));
|
||||
$Siblings->add($this->objFromFixture('UnsavedRelationListTest_DataObject', 'ObjectB'));
|
||||
$Siblings->add($this->objFromFixture('UnsavedRelationListTest_DataObject', 'ObjectC'));
|
||||
|
||||
$siblings = $object->Siblings();
|
||||
|
||||
$this->assertDOSEquals(array(
|
||||
array('Name' => 'A'),
|
||||
array('Name' => 'B'),
|
||||
array('Name' => 'C')
|
||||
), $siblings);
|
||||
|
||||
$object->write();
|
||||
|
||||
$this->assertNotEquals($siblings, $object->Siblings());
|
||||
|
||||
$this->assertDOSEquals(array(
|
||||
array('Name' => 'A'),
|
||||
array('Name' => 'B'),
|
||||
array('Name' => 'C')
|
||||
), $object->Siblings());
|
||||
}
|
||||
|
||||
public function testHasManyNew() {
|
||||
$object = new UnsavedRelationListTest_DataObject;
|
||||
|
||||
$children = $object->Children();
|
||||
$children->add(new UnsavedRelationListTest_DataObject(array('Name' => 'A')));
|
||||
$children->add(new UnsavedRelationListTest_DataObject(array('Name' => 'B')));
|
||||
$children->add(new UnsavedRelationListTest_DataObject(array('Name' => 'C')));
|
||||
|
||||
$children = $object->Children();
|
||||
|
||||
$this->assertDOSEquals(array(
|
||||
array('Name' => 'A'),
|
||||
array('Name' => 'B'),
|
||||
array('Name' => 'C')
|
||||
), $children);
|
||||
|
||||
$object->write();
|
||||
|
||||
$this->assertNotEquals($children, $object->Children());
|
||||
|
||||
$this->assertDOSEquals(array(
|
||||
array('Name' => 'A'),
|
||||
array('Name' => 'B'),
|
||||
array('Name' => 'C')
|
||||
), $object->Children());
|
||||
}
|
||||
|
||||
public function testManyManyNew() {
|
||||
$object = new UnsavedRelationListTest_DataObject;
|
||||
|
||||
$Siblings = $object->Siblings();
|
||||
$Siblings->add(new UnsavedRelationListTest_DataObject(array('Name' => 'A')));
|
||||
$Siblings->add(new UnsavedRelationListTest_DataObject(array('Name' => 'B')));
|
||||
$Siblings->add(new UnsavedRelationListTest_DataObject(array('Name' => 'C')));
|
||||
|
||||
$siblings = $object->Siblings();
|
||||
|
||||
$this->assertDOSEquals(array(
|
||||
array('Name' => 'A'),
|
||||
array('Name' => 'B'),
|
||||
array('Name' => 'C')
|
||||
), $siblings);
|
||||
|
||||
$object->write();
|
||||
|
||||
$this->assertNotEquals($siblings, $object->Siblings());
|
||||
|
||||
$this->assertDOSEquals(array(
|
||||
array('Name' => 'A'),
|
||||
array('Name' => 'B'),
|
||||
array('Name' => 'C')
|
||||
), $object->Siblings());
|
||||
}
|
||||
|
||||
public function testManyManyExtraFields() {
|
||||
$object = new UnsavedRelationListTest_DataObject;
|
||||
|
||||
$Siblings = $object->Siblings();
|
||||
$Siblings->add(new UnsavedRelationListTest_DataObject(array('Name' => 'A')), array('Number' => 1));
|
||||
$Siblings->add(new UnsavedRelationListTest_DataObject(array('Name' => 'B')), array('Number' => 2));
|
||||
$Siblings->add(new UnsavedRelationListTest_DataObject(array('Name' => 'C')), array('Number' => 3));
|
||||
|
||||
$siblings = $object->Siblings();
|
||||
|
||||
$this->assertDOSEquals(array(
|
||||
array('Name' => 'A', 'Number' => 1),
|
||||
array('Name' => 'B', 'Number' => 2),
|
||||
array('Name' => 'C', 'Number' => 3)
|
||||
), $siblings);
|
||||
|
||||
$object->write();
|
||||
|
||||
$this->assertNotEquals($siblings, $object->Siblings());
|
||||
|
||||
$this->assertDOSEquals(array(
|
||||
array('Name' => 'A', 'Number' => 1),
|
||||
array('Name' => 'B', 'Number' => 2),
|
||||
array('Name' => 'C', 'Number' => 3)
|
||||
), $object->Siblings());
|
||||
}
|
||||
}
|
||||
|
||||
class UnsavedRelationListTest_DataObject extends DataObject implements TestOnly {
|
||||
public static $db = array(
|
||||
'Name' => 'Varchar',
|
||||
);
|
||||
|
||||
public static $has_one = array(
|
||||
'Parent' => 'UnsavedRelationListTest_DataObject',
|
||||
);
|
||||
|
||||
public static $has_many = array(
|
||||
'Children' => 'UnsavedRelationListTest_DataObject',
|
||||
);
|
||||
|
||||
public static $many_many = array(
|
||||
'Siblings' => 'UnsavedRelationListTest_DataObject',
|
||||
);
|
||||
|
||||
public static $many_many_extraFields = array(
|
||||
'Siblings' => array(
|
||||
'Number' => 'Int',
|
||||
),
|
||||
);
|
||||
}
|
7
tests/model/UnsavedRelationListTest.yml
Normal file
7
tests/model/UnsavedRelationListTest.yml
Normal file
@ -0,0 +1,7 @@
|
||||
UnsavedRelationListTest_DataObject:
|
||||
ObjectA:
|
||||
Name: A
|
||||
ObjectB:
|
||||
Name: B
|
||||
ObjectC:
|
||||
Name: C
|
Loading…
Reference in New Issue
Block a user