/** * @param DataObject $entity * @param $association_name * @param QueryObject $query * @return bool|PersistentCollection * @throws Exception */ public function getOne2ManyAssociation(DataObject $entity, $association_name, QueryObject $query = null) { if (is_null($query)) { $query = new QueryObject(); } $child_class = $entity->has_many($association_name); if (!$child_class) { throw new Exception(sprintf("entity %s has not an one-to-many association called %s", get_class($entity), $association_name)); } if ($entity->getComponents($association_name) instanceof UnsavedRelationList) { $query = new QueryObject(); } $old = UnitOfWork::getInstance()->getCollection($entity, $child_class, $query, '1-to-many'); if ($old) { return $old; } $component = $entity->getComponents($association_name, (string) $query, $query->getOrder(true)); foreach ($query->getAlias(QueryAlias::INNER) as $specification) { $component = $component->innerJoin($specification->getTable(), $specification->getCondition()); } foreach ($query->getAlias(QueryAlias::LEFT) as $specification) { $component = $component->innerJoin($specification->getTable(), $specification->getCondition()); } return new PersistentCollection($entity, $component, $query, '1-to-many', $association_name); }
public function __construct(DataObject $controller, $name, $title = null, $className = null, $source = array(), $addTitle = null, $defaultsProperties = array(), $form = null) { $hasOne = false; if (!$title) { $this->title = self::name_to_label($name); } if (!$className) { if (substr($name, -2) == 'ID') { $name = substr($name, 0, -2); } if (!($hasOne = $className = $controller->has_one($name)) && !($className = $controller->belongs_to($name)) && (($settings = $controller->has_many($name)) || ($settings = $controller->many_many($name)))) { if (is_array($settings)) { $className = $settings[1]; } else { $className = $settings; } $this->fieldType = 'CheckboxSetField'; } if (!$className) { trigger_error('Couldn\'t determine class type from field name "' . $name . '". Please define the class name.'); } if ($hasOne) { $name .= 'ID'; } } else { if ($rels = $controller->has_many() + $controller->many_many()) { foreach ($rels as $rel => $class) { if ($class == $className || ClassInfo::is_subclass_of($class, $className)) { $this->fieldType = 'CheckboxSetField'; break; } } } } if (!class_exists($className)) { trigger_error($className . ' class doesn\'t exist'); } $this->setDefaults($defaultsProperties); $this->className = $className; $this->controller = $controller; parent::__construct($name, $title, $source, null, $form); }
/** * Save value to dataobject * * @see forms/CheckboxSetField::saveInto() */ public function saveInto(DataObject $record) { $fieldName = $this->name; // TODO - SiteTree admin seems to serialise value, whilst modeladmin doesn't // this explodes the serialised string, but there is probably a more elegant solution $valueArray = isset($this->value[0]) && strpos($this->value[0], ',') ? explode(',', $this->value[0]) : $this->value; if ($fieldName && ($record->has_many($fieldName) || $record->many_many($fieldName))) { // Set related records $record->{$fieldName}()->setByIDList($valueArray); } else { $record->{$fieldName} = implode(', ', $valueArray); } }
/** * Constructor * * @param DataObject $object The object that has_many somethings that we're calculating the aggregate for * @param string $relationship The name of the relationship * @param string $filter (optional) An SQL filter to apply to the relationship rows before calculating the * aggregate */ public function __construct($object, $relationship, $filter = '') { $this->object = $object; $this->relationship = $relationship; $this->has_many = $object->has_many($relationship); $this->many_many = $object->many_many($relationship); if (!$this->has_many && !$this->many_many) { user_error("Could not find relationship {$relationship} on object class {$object->class} in" . " Aggregate Relationship", E_USER_ERROR); } parent::__construct($this->has_many ? $this->has_many : $this->many_many[1], $filter); }
/** * Gets the foreign key from the child File class that relates to the $has_many or $many_many * on the parent record * * @param DataObject $record The record to search * @return string */ public function getForeignRelationName(DataObject $record) { if ($many_info = $record->many_many($this->name)) { // return parent field return $many_info[2]; } elseif ($file_class = $record->has_many($this->name)) { $class = $record->class; $relation_name = false; while($class != "DataObject") { if($relation_name = singleton($file_class)->getReverseAssociation($class)) { break; } $class = get_parent_class($class); } if(!$relation_name) { user_error("Could not find has_one or belongs many_many relation ship on $file_class", E_USER_ERROR); } return $relation_name .= "ID"; } return false; }
/** * Gets the form fields as defined through the metadata * on {@link $obj} and the custom parameters passed to FormScaffolder. * Depending on those parameters, the fields can be used in ajax-context, * contain {@link TabSet}s etc. * * @return FieldSet */ public function getFieldSet() { $fields = new FieldSet(); // tabbed or untabbed if($this->tabbed) { $fields->push(new TabSet("Root", $mainTab = new Tab("Main"))); $mainTab->setTitle(_t('SiteTree.TABMAIN', "Main")); } // add database fields foreach($this->obj->db() as $fieldName => $fieldType) { if($this->restrictFields && !in_array($fieldName, $this->restrictFields)) continue; // @todo Pass localized title if($this->fieldClasses && isset($this->fieldClasses[$fieldName])) { $fieldClass = $this->fieldClasses[$fieldName]; $fieldObject = new $fieldClass($fieldName); } else { $fieldObject = $this->obj->dbObject($fieldName)->scaffoldFormField(null, $this->getParamsArray()); } $fieldObject->setTitle($this->obj->fieldLabel($fieldName)); if($this->tabbed) { $fields->addFieldToTab("Root.Main", $fieldObject); } else { $fields->push($fieldObject); } } // add has_one relation fields if($this->obj->has_one()) { foreach($this->obj->has_one() as $relationship => $component) { if($this->restrictFields && !in_array($relationship, $this->restrictFields)) continue; $hasOneField = $this->obj->dbObject("{$relationship}ID")->scaffoldFormField(null, $this->getParamsArray()); $hasOneField->setTitle($this->obj->fieldLabel($relationship)); if($this->tabbed) { $fields->addFieldToTab("Root.Main", $hasOneField); } else { $fields->push($hasOneField); } } } // only add relational fields if an ID is present if($this->obj->ID) { // add has_many relation fields if($this->obj->has_many() && ($this->includeRelations === true || isset($this->includeRelations['has_many']))) { foreach($this->obj->has_many() as $relationship => $component) { if($this->tabbed) { $relationTab = $fields->findOrMakeTab( "Root.$relationship", $this->obj->fieldLabel($relationship) ); } $relationshipFields = singleton($component)->summaryFields(); $foreignKey = $this->obj->getComponentJoinField($relationship); $ctf = new ComplexTableField( $this, $relationship, $component, $relationshipFields, "getCMSFields", "$foreignKey = " . $this->obj->ID ); $ctf->setPermissions(TableListField::permissions_for_object($component)); if($this->tabbed) { $fields->addFieldToTab("Root.$relationship", $ctf); } else { $fields->push($ctf); } } } if($this->obj->many_many() && ($this->includeRelations === true || isset($this->includeRelations['many_many']))) { foreach($this->obj->many_many() as $relationship => $component) { if($this->tabbed) { $relationTab = $fields->findOrMakeTab( "Root.$relationship", $this->obj->fieldLabel($relationship) ); } $relationshipFields = singleton($component)->summaryFields(); $filterWhere = $this->obj->getManyManyFilter($relationship, $component); $filterJoin = $this->obj->getManyManyJoin($relationship, $component); $ctf = new ComplexTableField( $this, $relationship, $component, $relationshipFields, "getCMSFields", $filterWhere, '', $filterJoin ); $ctf->setPermissions(TableListField::permissions_for_object($component)); $ctf->popupClass = "ScaffoldingComplexTableField_Popup"; if($this->tabbed) { $fields->addFieldToTab("Root.$relationship", $ctf); } else { $fields->push($ctf); } } } } return $fields; }
/** * Save the current value of this CheckboxSetField into a DataObject. * If the field it is saving to is a has_many or many_many relationship, * it is saved by setByIDList(), otherwise it creates a comma separated * list for a standard DB text/varchar field. * * @param DataObject $record The record to save into */ function saveInto(DataObject $record) { $fieldname = $this->name; if ($fieldname && $record && ($record->has_many($fieldname) || $record->many_many($fieldname))) { $idList = array(); if ($this->value) { foreach ($this->value as $id => $bool) { if ($bool) { $idList[] = $id; } } } $record->{$fieldname}()->setByIDList($idList); } elseif ($fieldname && $record) { if ($this->value) { $this->value = str_replace(',', '{comma}', $this->value); $record->{$fieldname} = implode(",", $this->value); } else { $record->{$fieldname} = ''; } } }
/** * @param DataObject $obj * @param array $params * @param int|array $sort * @param int|array $limit * @param string $relationName * @return SQLQuery|boolean */ protected function getObjectRelationQuery($obj, $params, $sort, $limit, $relationName) { if ($obj->hasMethod("{$relationName}Query")) { // @todo HACK Switch to ComponentSet->getQuery() once we implement it (and lazy loading) $query = $obj->{"{$relationName}Query"}(null, $sort, null, $limit); $relationClass = $obj->{"{$relationName}Class"}(); } elseif ($relationClass = $obj->many_many($relationName)) { // many_many() returns different notation $relationClass = $relationClass[1]; $query = $obj->getManyManyComponentsQuery($relationName); } elseif ($relationClass = $obj->has_many($relationName)) { $query = $obj->getComponentsQuery($relationName); } elseif ($relationClass = $obj->has_one($relationName)) { $query = null; } else { return false; } // get all results return $this->getSearchQuery($relationClass, $params, $sort, $limit, $query); }
/** * Saves the Dataobjects contained in the field */ function saveInto(DataObject $record) { // CMS sometimes tries to set the value to one. if (is_array($this->value)) { $newFields = array(); // Sort into proper array $value = ArrayLib::invert($this->value); $dataObjects = $this->sortData($value, $record->ID); // New fields are nested in their own sub-array, and need to be sorted separately if (isset($dataObjects['new']) && $dataObjects['new']) { $newFields = $this->sortData($dataObjects['new'], $record->ID); } // Update existing fields // @todo Should this be in an else{} statement? $savedObjIds = $this->saveData($dataObjects, $this->editExisting); // Save newly added record if ($savedObjIds || $newFields) { $savedObjIds = $this->saveData($newFields, false); } // Optionally save the newly created records into a relationship // on $record. This assumes the name of this formfield instance // is set to a relationship name on $record. if ($this->relationAutoSetting) { $relationName = $this->Name(); if ($record->has_many($relationName) || $record->many_many($relationName)) { if ($savedObjIds) { foreach ($savedObjIds as $id => $status) { $record->{$relationName}()->add($id); } } } } // Update the internal source items cache $this->value = null; $items = $this->sourceItems(); FormResponse::update_dom_id($this->id(), $this->FieldHolder()); } }
/** * Update the permission set associated with $record DataObject * * @param DataObject $record */ function saveInto(DataObject $record) { $fieldname = $this->name; $managedClass = $this->managedClass; // remove all permissions and re-add them afterwards $permissions = $record->{$fieldname}(); foreach ($permissions as $permission) { $permission->delete(); } if ($fieldname && $record && ($record->has_many($fieldname) || $record->many_many($fieldname))) { $idList = array(); if ($this->value) { foreach ($this->value as $id => $bool) { if ($bool) { $perm = new $managedClass(); $perm->{$this->filterField} = $record->ID; $perm->Code = $id; $perm->write(); } } } } }
/** * Gets the class of the file being managed. Used in case the relation * is cast as a subclass of File. * * @param DataObject $record * @return string|bool */ public function getFileClass(DataObject $record) { if (!($file_class = $record->has_many($this->name))) { if (!($many_class = $record->many_many($this->name))) { return false; } // set child class. $file_class = $many_class[1]; } return $file_class; }
function saveInto(DataObject $record) { $fieldname = $this->name; $value = ArrayLib::invert($this->value); if ($fieldname && $record && ($record->has_many($fieldname) || $record->many_many($fieldname))) { $idList = array(); if ($value) { foreach ($value['Value'] as $id => $bool) { if ($bool) { $idList[] = $id; } } } $record->{$fieldname}()->setByIDList($idList); } elseif ($fieldname && $record) { if ($value) { if (is_array($value)) { foreach ($value as $k => $items) { if (is_array($items)) { foreach ($items as $key => $val) { if (!$val) { unset($value[$k][$key]); } else { if ($k == 'Value') { $value[$k][$key] = str_replace(", ", "{comma}", $val); } } } } } } foreach ($value as $k => $v) { if ($k == 'Value') { $record->{$fieldname} = implode(",", $v); } else { $record->{$k} = Convert::array2json($v); } } } else { $record->{$fieldname} = ''; } } }
/** * Gets the form fields as defined through the metadata * on {@link $obj} and the custom parameters passed to FormScaffolder. * Depending on those parameters, the fields can be used in ajax-context, * contain {@link TabSet}s etc. * * @return FieldList */ public function getFieldList() { $fields = new FieldList(); // tabbed or untabbed if ($this->tabbed) { $fields->push(new TabSet("Root", $mainTab = new Tab("Main"))); $mainTab->setTitle(_t('SiteTree.TABMAIN', "Main")); } // add database fields foreach ($this->obj->db() as $fieldName => $fieldType) { if ($this->restrictFields && !in_array($fieldName, $this->restrictFields)) { continue; } // @todo Pass localized title if ($this->fieldClasses && isset($this->fieldClasses[$fieldName])) { $fieldClass = $this->fieldClasses[$fieldName]; $fieldObject = new $fieldClass($fieldName); } else { $fieldObject = $this->obj->dbObject($fieldName)->scaffoldFormField(null, $this->getParamsArray()); } $fieldObject->setTitle($this->obj->fieldLabel($fieldName)); if ($this->tabbed) { $fields->addFieldToTab("Root.Main", $fieldObject); } else { $fields->push($fieldObject); } } // add has_one relation fields if ($this->obj->has_one()) { foreach ($this->obj->has_one() as $relationship => $component) { if ($this->restrictFields && !in_array($relationship, $this->restrictFields)) { continue; } $fieldName = $component === 'DataObject' ? $relationship : "{$relationship}ID"; if ($this->fieldClasses && isset($this->fieldClasses[$fieldName])) { $fieldClass = $this->fieldClasses[$fieldName]; $hasOneField = new $fieldClass($fieldName); } else { $hasOneField = $this->obj->dbObject($fieldName)->scaffoldFormField(null, $this->getParamsArray()); } if (empty($hasOneField)) { continue; } // Allow fields to opt out of scaffolding $hasOneField->setTitle($this->obj->fieldLabel($relationship)); if ($this->tabbed) { $fields->addFieldToTab("Root.Main", $hasOneField); } else { $fields->push($hasOneField); } } } // only add relational fields if an ID is present if ($this->obj->ID) { // add has_many relation fields if ($this->obj->has_many() && ($this->includeRelations === true || isset($this->includeRelations['has_many']))) { foreach ($this->obj->has_many() as $relationship => $component) { if ($this->tabbed) { $relationTab = $fields->findOrMakeTab("Root.{$relationship}", $this->obj->fieldLabel($relationship)); } $fieldClass = isset($this->fieldClasses[$relationship]) ? $this->fieldClasses[$relationship] : 'GridField'; $grid = Object::create($fieldClass, $relationship, $this->obj->fieldLabel($relationship), $this->obj->{$relationship}(), GridFieldConfig_RelationEditor::create()); if ($this->tabbed) { $fields->addFieldToTab("Root.{$relationship}", $grid); } else { $fields->push($grid); } } } if ($this->obj->many_many() && ($this->includeRelations === true || isset($this->includeRelations['many_many']))) { foreach ($this->obj->many_many() as $relationship => $component) { if ($this->tabbed) { $relationTab = $fields->findOrMakeTab("Root.{$relationship}", $this->obj->fieldLabel($relationship)); } $fieldClass = isset($this->fieldClasses[$relationship]) ? $this->fieldClasses[$relationship] : 'GridField'; $grid = Object::create($fieldClass, $relationship, $this->obj->fieldLabel($relationship), $this->obj->{$relationship}(), GridFieldConfig_RelationEditor::create()); if ($this->tabbed) { $fields->addFieldToTab("Root.{$relationship}", $grid); } else { $fields->push($grid); } } } } return $fields; }
/** * @desc */ function saveInto(DataObject $record) { $fieldname = $this->name; if ($fieldname && $record && ($record->has_many($fieldname) || $record->many_many($fieldname))) { $record->{$fieldname}()->setByIDList($this->value); } else { if ($fieldname && $record && $record->hasField($fieldname)) { if ($this->value) { $this->value = str_replace(",", "{comma}", $this->value); $record->{$fieldname} = implode(",", $this->value); } else { $record->{$fieldname} = ''; } } } }
/** * Update the permission set associated with $record DataObject * * @param DataObject $record */ function saveInto(DataObject $record) { $fieldname = $this->name; $managedClass = $this->managedClass; // Remove all "privileged" permissions if the currently logged-in user is not an admin if (!Permission::check('ADMIN')) { foreach ($this->value as $id => $bool) { if (in_array($id, Permission::$privileged_permissions)) { unset($this->value[$id]); } } } // remove all permissions and re-add them afterwards $permissions = $record->{$fieldname}(); foreach ($permissions as $permission) { $permission->delete(); } if ($fieldname && $record && ($record->has_many($fieldname) || $record->many_many($fieldname))) { $idList = array(); if ($this->value) { foreach ($this->value as $id => $bool) { if ($bool) { $perm = new $managedClass(); $perm->{$this->filterField} = $record->ID; $perm->Code = $id; $perm->write(); } } } } }