Permalink
Browse files

Merge pull request #922 from simonwelsh/rellist-presave

NEW: Allows setting of has_many and many_many relations before writing
  • Loading branch information...
chillu committed Dec 4, 2012
2 parents 65002f6 + bbc4443 commit a108f67476877124cca1a282ba408a06e9a181a1
@@ -569,13 +569,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
View
@@ -12,7 +12,7 @@ class ArrayList extends ViewableData implements SS_List, SS_Filterable, SS_Sorta
*
* @var array
*/
- protected $items;
+ protected $items = array();
/**
*
View
@@ -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 @@ public function write($showDebug = false, $forceInsert = false, $forceWrite = fa
}
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 @@ public function getComponents($componentName, $filter = "", $sort = "", $join =
. " 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 @@ public function getRemoteJoinField($component, $type = 'has_many') {
*/
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));
Oops, something went wrong.

0 comments on commit a108f67

Please sign in to comment.