public function convert(DataObject $object) { if ($object->hasMethod('toFilteredMap')) { return Convert::raw2json($object->toFilteredMap()); } return Convert::raw2json($object->toMap()); }
protected function walkRelationshipChain(DataObject $from, ArrayList $list, array $parts, $lastPart, $lastItem) { $part = array_shift($parts); if (!$from->hasMethod($part)) { // error, no such part of relationship chain return false; } if (count($parts)) { foreach ($from->{$part}() as $item) { $this->walkRelationshipChain($item, $list, $parts, $part, $item); } } else { $images = $from->{$part}()->toNestedArray(); // mark the images with a source from relationship and ID /** @var Image $image */ foreach ($images as &$image) { if ($lastItem instanceof Variation) { $options = $lastItem->Options(); foreach ($options as $option) { $image['ProductID'] = $lastItem->Product()->ID; $image['VariationID'] = $lastItem->ID; $image['OptionID'] = $option->ID; $image['AttributeID'] = $option->AttributeID; } } } $list->merge(new ArrayList($images)); } return true; }
/** * @param DataObject $obj * @param array $config * @return array|bool */ public function convertDataObjectToArray(DataObject $obj, $config = array()) { $content = array(); $allowedFields = $obj instanceof FlexibleDataFormatterInterface ? $obj->getAllowedFields($config) : array_keys($obj->db()); foreach ($allowedFields as $fieldName) { if ($obj->hasMethod($fieldName)) { $fieldValue = $obj->{$fieldName}(); } else { $fieldValue = $obj->dbObject($fieldName); if (is_null($fieldValue)) { $fieldValue = $obj->{$fieldName}; } } if ($fieldValue instanceof Object) { switch (get_class($fieldValue)) { case 'Boolean': $content[$fieldName] = (bool) $fieldValue->getValue(); break; case 'PrimaryKey': $content[$fieldName] = $obj->{$fieldName}; break; case 'HTMLText': $content[$fieldName] = $fieldValue->forTemplate(); break; default: $content[$fieldName] = $fieldValue->getValue(); break; } } else { $content[$fieldName] = $fieldValue; } } if ($obj instanceof FlexibleDataFormatterInterface) { foreach ($obj->getAllowedHasOneRelations($config) as $relName) { if ($obj->{$relName . 'ID'}) { $content[$relName] = $this->convertDataObjectToArray($obj->{$relName}(), $config); } } foreach ($obj->getAllowedHasManyRelations($config) as $relName) { $items = $obj->{$relName}(); if ($items instanceof SS_List && count($items) > 0) { $content[$relName] = array(); foreach ($items as $item) { $content[$relName][] = $this->convertDataObjectToArray($item, $config); } } } foreach ($obj->getAllowedManyManyRelations($config) as $relName) { $items = $obj->{$relName}(); if ($items instanceof SS_List && count($items) > 0) { $content[$relName] = array(); foreach ($items as $item) { $content[$relName][] = $this->convertDataObjectToArray($item, $config); } } } } return $content; }
public function convert(DataObject $object) { if ($object->hasMethod('toFilteredMap')) { $data = $object->toFilteredMap(); } else { $data = $object->toMap(); } $converter = new ArrayToXml('item'); return $converter->convertArray($data); }
/** * @param GridField $gridField * @param DataObject $record * @param string $columnName * * @return string - the HTML for the column */ public function getColumnContent($gridField, $record, $columnName) { // No permission checks, handled through GridFieldDetailForm, // which can make the form readonly if no edit permissions are available. if ($record->hasMethod("CMSEditLink")) { $data = new ArrayData(array('Link' => Controller::join_links($record->CMSEditLink()))); return $data->renderWith('GridFieldEditButtonInSiteTree'); } else { return parent::getColumnContent($gridField, $record, $columnName); } }
/** * Recursivly search for a PlaceholderImage. * * @param DataObject $object * @return Image | null */ protected function getPlaceholderImageRecursive(DataObject $object) { if ($object->has_one('PlaceholderImage')) { $image = $object->getComponent('PlaceholderImage'); if ($image->exists()) { return $image; } } $parentObject = $object->hasMethod('Parent') ? $object->Parent() : null; return isset($parentObject) && $parentObject->exists() ? $this->getPlaceholderImageRecursive($parentObject) : null; }
public function trackInteraction($interactionType, DataObject $item = null, Member $user = null) { if ($user == null) { $user = Member::currentUserID(); } // Create a new user interaction object to track the page count. $link = '#'; if ($item->hasMethod('RelativeLink')) { $link = $item->RelativeLink(); } $interaction = UserInteraction::create(array('Title' => $item->Title, 'Type' => $interactionType, 'ItemClass' => get_class($item), 'ItemID' => $item->ID, 'URL' => $link, 'MemberID' => $user)); $interaction->write(); }
/** * Sets the value of the form field. * * @param mixed $value If numeric, get the file by ID, otherwise, introspect the $data object * @param DataObject $data The record associated with the parent form */ public function setValue($value = null, $data = null) { if (!is_numeric($value)) { if ($id = Controller::curr()->getRequest()->requestVar($this->Name() . "ID")) { $value = $id; } elseif (!$value && $data && $data instanceof DataObject && $data->hasMethod($this->name)) { $funcName = $this->name; if ($obj = $data->{$funcName}()) { if ($obj instanceof File || $obj instanceof S3File) { $value = $obj->ID; } } } } parent::setValue($value, $data); }
/** * Gets the workflow definition for a given dataobject, if there is one * * Will recursively query parent elements until it finds one, if available * * @param DataObject $dataObject */ public function getDefinitionFor(DataObject $dataObject) { if ($dataObject->hasExtension('WorkflowApplicable') || $dataObject->hasExtension('FileWorkflowApplicable')) { if ($dataObject->WorkflowDefinitionID) { return DataObject::get_by_id('WorkflowDefinition', $dataObject->WorkflowDefinitionID); } if ($dataObject->ParentID) { return $this->getDefinitionFor($dataObject->Parent()); } if ($dataObject->hasMethod('workflowParent')) { $obj = $dataObject->workflowParent(); if ($obj) { return $this->getDefinitionFor($obj); } } } return null; }
/** * * Dynamically augments any $cacheableClass object with * methods and properties of $model. * * Warning: Uses PHP magic methods __get() and __set(). * * @param DataObject $model * @param string $cacheableClass * @return ViewableData $cacheable */ public static function model2cacheable(DataObject $model, $cacheableClass = null) { if (!$cacheableClass) { $cacheableClass = "Cacheable" . $model->ClassName; } $cacheable = $cacheableClass::create(); $cacheable_fields = $cacheable->get_cacheable_fields(); foreach ($cacheable_fields as $field) { $cacheable->__set($field, $model->__get($field)); } $cacheable_functions = $cacheable->get_cacheable_functions(); foreach ($cacheable_functions as $function) { /* * Running tests inside a project with its own YML config for * cacheable_fields and cacheable_functions will fail if we don't check first */ if ($model->hasMethod($function)) { $cacheable->__set($function, $model->{$function}()); } } return $cacheable; }
/** * Save the results into the form * Calls function $record->onChange($items) before saving to the assummed * Component set. */ function saveInto(DataObject $record) { // Detect whether this field has actually been updated if ($this->value !== 'unchanged') { $fieldName = $this->name; $saveDest = $record->{$fieldName}(); if (!$saveDest) { user_error("TreeMultiselectField::saveInto() Field '{$fieldName}' not found on {$record->class}.{$record->ID}", E_USER_ERROR); } if ($this->value) { $items = split(" *, *", trim($this->value)); } // Allows you to modify the items on your object before save $funcName = "onChange{$fieldName}"; if ($record->hasMethod($funcName)) { $result = $record->{$funcName}($items); if (!$result) { return; } } $saveDest->setByIDList($items); } }
/** * Gets a writer for a DataObject * * If the field already has a value, a writer is created matching that * identifier. Otherwise, a new writer is created based on either * * - The $type passed in * - whether the $object class specifies a prefered storage type via * getEffectiveContentStore * - what the `defaultStore` is set to for the content service * * * @param DataObject $object * The object to get a writer for * @param String $field * The field being written to * @param String $type * Explicitly state what the content store type will be * @return ContentWriter */ public function getWriterFor(DataObject $object = null, $field = 'FilePointer', $type = null) { if ($object && $field && $object->hasField($field)) { $val = $object->{$field}; if (strlen($val)) { $reader = $this->getReader($val); if ($reader && $reader->isReadable()) { return $reader->getWriter(); } } } if (!$type) { // specifically expecting to be handling File objects, but allows other // objects to play too if ($object && $object->hasMethod('getEffectiveContentStore')) { $type = $object->getEffectiveContentStore(); } else { $type = $this->defaultStore; } } // looks like we're getting a writer with no underlying file (as yet) return $this->getWriter($type); }
/** * Determines the validator to use for the edit form * @example 'getCMSValidator' * * @param DataObject $file File context to generate validator from * @return Validator Validator object */ public function getFileEditValidator(DataObject $file) { // Empty validator if (empty($this->fileEditValidator)) { return null; } // Validator instance if ($this->fileEditValidator instanceof Validator) { return $this->fileEditValidator; } // Method to call on the given file if ($file->hasMethod($this->fileEditValidator)) { return $file->{$this->fileEditValidator}(); } user_error("Invalid value for UploadField::fileEditValidator", E_USER_ERROR); }
/** * Mark all children of the given node that match the marking filter. * * @param DataObject $node Parent node * @param mixed $context * @param string $childrenMethod The name of the instance method to call to get the object's list of children * @param string $numChildrenMethod The name of the instance method to call to count the object's children * @return DataList */ public function markChildren($node, $context = null, $childrenMethod = "AllChildrenIncludingDeleted", $numChildrenMethod = "numChildren") { if ($node->hasMethod($childrenMethod)) { $children = $node->{$childrenMethod}($context); } else { user_error(sprintf("Can't find the method '%s' on class '%s' for getting tree children", $childrenMethod, get_class($node)), E_USER_ERROR); } $node->markExpanded(); if ($children) { foreach ($children as $child) { $markingMatches = $this->markingFilterMatches($child); if ($markingMatches) { // Mark a child node as unexpanded if it has children and has not already been expanded if ($child->{$numChildrenMethod}() && !$child->isExpanded()) { $child->markUnexpanded(); } else { $child->markExpanded(); } $this->markedNodes[$child->ID] = $child; } } } return $children; }
/** * @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); }
/** * Track a change to a DataObject * @return DataChangeRecord **/ public function track(DataObject $changedObject, $type = 'Change') { $changes = $changedObject->getChangedFields(true, 2); if (count($changes)) { // remove any changes to ignored fields $ignored = $changedObject->hasMethod('getIgnoredFields') ? $changedObject->getIgnoredFields() : null; if ($ignored) { $changes = array_diff_key($changes, $ignored); foreach ($ignored as $ignore) { if (isset($changes[$ignore])) { unset($changes[$ignore]); } } } } foreach (self::config()->field_blacklist as $key) { if (isset($changes[$key])) { unset($changes[$key]); } } if (empty($changes) && $type == 'Change') { return; } if ($type === 'Delete' && Versioned::get_reading_mode() === 'Stage.Live') { $type = 'Delete from Live'; } $this->ChangeType = $type; $this->ClassType = $changedObject->ClassName; $this->ClassID = $changedObject->ID; // @TODO this will cause issue for objects without titles $this->ObjectTitle = $changedObject->Title; $this->Stage = Versioned::get_reading_mode(); $before = array(); $after = array(); if ($type != 'Change' && $type != 'New') { // If we are (un)publishing we want to store the entire object $before = $type === 'Unpublish' ? $changedObject->toMap() : null; $after = $type === 'Publish' ? $changedObject->toMap() : null; } else { // Else we're tracking the changes to the object foreach ($changes as $field => $change) { if ($field == 'SecurityID') { continue; } $before[$field] = $change['before']; $after[$field] = $change['after']; } } if ($this->Before && $this->Before !== 'null' && is_array($before)) { //merge the old array last to keep it's value as we want keep the earliest version of each field $this->Before = json_encode(array_replace(json_decode($this->Before, true), $before)); } else { $this->Before = json_encode($before); } if ($this->After && $this->After !== 'null' && is_array($after)) { //merge the new array last to keep it's value as we want the newest version of each field $this->After = json_encode(array_replace($after, json_decode($this->After, true))); } else { $this->After = json_encode($after); } if (self::config()->save_request_vars) { foreach (self::config()->request_vars_blacklist as $key) { unset($_GET[$key]); unset($_POST[$key]); } $this->GetVars = isset($_GET) ? json_encode($_GET) : null; $this->PostVars = isset($_POST) ? json_encode($_POST) : null; } $this->ChangedByID = Member::currentUserID(); if (Member::currentUserID() && Member::currentUser()) { $this->CurrentEmail = Member::currentUser()->Email; } if (isset($_SERVER['SERVER_NAME'])) { $protocol = 'http'; $protocol = isset($_SERVER["HTTPS"]) && $_SERVER["HTTPS"] == "on" ? 'https://' : 'http://'; $this->CurrentURL = $protocol . $_SERVER["SERVER_NAME"] . ":" . $_SERVER["SERVER_PORT"] . $_SERVER["REQUEST_URI"]; } else { if (Director::is_cli()) { $this->CurrentURL = 'CLI'; } else { $this->CurrentURL = 'Could not determine current URL'; } } $this->RemoteIP = isset($_SERVER['REMOTE_ADDR']) ? $_SERVER['REMOTE_ADDR'] : (Director::is_cli() ? 'CLI' : 'Unknown remote addr'); $this->Referer = isset($_SERVER['HTTP_REFERER']) ? $_SERVER['HTTP_REFERER'] : ''; $this->Agent = isset($_SERVER['HTTP_USER_AGENT']) ? $_SERVER['HTTP_USER_AGENT'] : ''; $this->write(); return $this; }
/** * Handles saving the page. Needs to keep an eye on fields * and options which have been removed / added * * @param DataObject Record to Save it In */ function saveInto(DataObject $record) { $name = $this->name; $fieldSet = $record->$name(); // @todo shouldn't we deal with customFormActions on that object? $record->EmailOnSubmit = isset($_REQUEST[$name]['EmailOnSubmit']) ? "1" : "0"; $record->SubmitButtonText = isset($_REQUEST[$name]['SubmitButtonText']) ? $_REQUEST[$name]['SubmitButtonText'] : ""; $record->ShowClearButton = isset($_REQUEST[$name]['ShowClearButton']) ? "1" : "0"; // store the field IDs and delete the missing fields // alternatively, we could delete all the fields and re add them $missingFields = array(); foreach($fieldSet as $existingField) { $missingFields[$existingField->ID] = $existingField; } if(isset($_REQUEST[$name]) && is_array($_REQUEST[$name])) { foreach($_REQUEST[$name] as $newEditableID => $newEditableData) { if(!is_numeric($newEditableID)) continue; // get it from the db $editable = DataObject::get_by_id('EditableFormField', $newEditableID); // if it exists in the db update it if($editable) { // remove it from the removed fields list if(isset($missingFields[$editable->ID]) && isset($newEditableData) && is_array($newEditableData)) { unset($missingFields[$editable->ID]); } // set form id if($editable->ParentID == 0) { $editable->ParentID = $record->ID; } // save data $editable->populateFromPostData($newEditableData); } } } // remove the fields not saved if($this->canEdit()) { foreach($missingFields as $removedField) { if(is_numeric($removedField->ID)) { // check we can edit this $removedField->delete(); } } } if($record->hasMethod('customFormSave')) { $record->customFormSave($_REQUEST[$name], $record); } if($record->hasMethod('processNewFormFields')) { $record->processNewFormFields(); } }
function testExtensionCanBeAppliedToDataObject() { $do = new DataObject(); $mo = new DataExtensionTest_MyObject(); $this->assertTrue($do->hasMethod('testMethodApplied')); $this->assertTrue($mo->hasMethod('testMethodApplied')); $this->assertEquals("hello world", $mo->testMethodApplied()); $this->assertEquals("hello world", $do->testMethodApplied()); }
/** * @param DataObject $target * @return array */ public function getContextFields(DataObject $target) { $result = array(); if (!$target) { return $result; } $fields = $target->inheritedDatabaseFields(); foreach ($fields as $field => $fieldDesc) { $result[$field] = $target->{$field}; } if ($target instanceof CMSPreviewable) { $result['CMSLink'] = $target->CMSEditLink(); } else { if ($target->hasMethod('WorkflowLink')) { $result['CMSLink'] = $target->WorkflowLink(); } } return $result; }
/** * @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) { // The relation method will return a DataList, that getSearchQuery subsequently manipulates if ($obj->hasMethod($relationName)) { $query = $obj->{$relationName}(); return $this->getSearchQuery($query->dataClass(), $params, $sort, $limit, $query); } }
/** * Returns a DataObject relation's data * formatted and ready to embed. * * @param DataObject $record The DataObject to get the data from * @param string $relationName The name of the relation * @return array|null Formatted DataObject or RelationList ready to embed or null if nothing to embed */ protected function getEmbedData(DataObject $record, $relationName) { if ($record->hasMethod($relationName)) { $relationData = $record->{$relationName}(); if ($relationData instanceof RelationList) { return $this->formatDataList($relationData); } else { return $this->formatDataObject($relationData); } } return null; }
/** * Pull out all the fields that should be indexed for a particular object * * This mapping is done to make it easier to * * @param DataObject $dataObject * @return array */ protected function objectToFields($dataObject) { $ret = array(); $fields = Config::inst()->get($dataObject->ClassName, 'db'); $fields['Created'] = 'SS_Datetime'; $fields['LastEdited'] = 'SS_Datetime'; $ret['ClassName'] = array('Type' => 'Varchar', 'Value' => $dataObject->class); $ret['SS_ID'] = array('Type' => 'Int', 'Value' => $dataObject->ID); foreach ($fields as $name => $type) { if (preg_match('/^(\\w+)\\(/', $type, $match)) { $type = $match[1]; } // Just index everything; the query can figure out what to exclude... ! $value = $dataObject->{$name}; if ($type == 'MultiValueField') { $value = $value->getValues(); } $ret[$name] = array('Type' => $type, 'Value' => $value); } $rels = Config::inst()->get($dataObject->ClassName, 'has_one'); if ($rels) { foreach (array_keys($rels) as $rel) { $ret["{$rel}ID"] = array('Type' => 'ForeignKey', 'Value' => $dataObject->{$rel . "ID"}); } } if ($dataObject->hasMethod('additionalSolrValues')) { $extras = $dataObject->extend('additionalSolrValues'); if ($extras && is_array($extras)) { foreach ($extras as $add) { foreach ($add as $k => $v) { $ret[$k] = array('Type' => $this->mapper->mapValueToType($k, $v), 'Value' => $v); } } } } return $ret; }
/** * Mark all children of the given node that match the marking filter. * @param DataObject $node Parent node. */ public function markChildren($node, $context = null, $childrenMethod = "AllChildrenIncludingDeleted", $numChildrenMethod = "numChildren") { if ($node->hasMethod($childrenMethod)) { $children = $node->{$childrenMethod}($context); } else { user_error(sprintf("Can't find the method '%s' on class '%s' for getting tree children", $childrenMethod, get_class($this->owner)), E_USER_ERROR); } $node->markExpanded(); if ($children) { foreach ($children as $child) { if (!$this->markingFilter || $this->markingFilterMatches($child)) { if ($child->{$numChildrenMethod}()) { $child->markUnexpanded(); } else { $child->markExpanded(); } $this->markedNodes[$child->ID] = $child; } } } }
/** * Loads the related record values into this field. UploadField can be uploaded * in one of three ways: * * - By passing in a list of file IDs in the $value parameter (an array with a single * key 'Files', with the value being the actual array of IDs). * - By passing in an explicit list of File objects in the $record parameter, and * leaving $value blank. * - By passing in a dataobject in the $record parameter, from which file objects * will be extracting using the field name as the relation field. * * Each of these methods will update both the items (list of File objects) and the * field value (list of file ID values). * * @param array $value Array of submitted form data, if submitting from a form * @param array|DataObject|SS_List $record Full source record, either as a DataObject, * SS_List of items, or an array of submitted form data * @return UploadField Self reference */ public function setValue($value, $record = null) { // If we're not passed a value directly, we can attempt to infer the field // value from the second parameter by inspecting its relations $items = new ArrayList(); // Determine format of presented data if (empty($value) && $record) { // If a record is given as a second parameter, but no submitted values, // then we should inspect this instead for the form values if ($record instanceof DataObject && $record->hasMethod($this->getName())) { // If given a dataobject use reflection to extract details $data = $record->{$this->getName()}(); if ($data instanceof DataObject) { // If has_one, add sole item to default list $items->push($data); } elseif ($data instanceof SS_List) { // For many_many and has_many relations we can use the relation list directly $items = $data; } } elseif ($record instanceof SS_List) { // If directly passing a list then save the items directly $items = $record; } } elseif (!empty($value['Files'])) { // If value is given as an array (such as a posted form), extract File IDs from this $class = $this->getRelationAutosetClass(); $items = DataObject::get($class)->byIDs($value['Files']); } // If javascript is disabled, direct file upload (non-html5 style) can // trigger a single or multiple file submission. Note that this may be // included in addition to re-submitted File IDs as above, so these // should be added to the list instead of operated on independently. if ($uploadedFiles = $this->extractUploadedFileData($value)) { foreach ($uploadedFiles as $tempFile) { $file = $this->saveTemporaryFile($tempFile, $error); if ($file) { $items->add($file); } else { throw new ValidationException($error); } } } // Filter items by what's allowed to be viewed $filteredItems = new ArrayList(); $fileIDs = array(); foreach ($items as $file) { if ($file->exists() && $file->canView()) { $filteredItems->push($file); $fileIDs[] = $file->ID; } } // Filter and cache updated item list $this->items = $filteredItems; // Same format as posted form values for this field. Also ensures that // $this->setValue($this->getValue()); is non-destructive $value = $fileIDs ? array('Files' => $fileIDs) : null; // Set value using parent return parent::setValue($value, $record); }
/** * @param DataObject $target * @return array */ public function getContextFields(DataObject $target) { $fields = $target->summaryFields(); $result = array(); foreach ($fields as $field => $fieldDesc) { $result[$field] = $target->{$field}; } if ($target instanceof SiteTree) { $result['CMSLink'] = singleton('CMSMain')->Link("show/{$target->ID}"); } else { if ($target->hasMethod('WorkflowLink')) { $result['CMSLink'] = $target->WorkflowLink(); } } return $result; }
/** * @param GridField $gridField * @param DataObject $record * @param string $columnName * * @return string - the HTML for the column */ public function getColumnContent($gridField, $record, $columnName) { $data = new ArrayData(array('Link' => $record->hasMethod('getExternalLink') ? $record->getExternalLink() : $record->ExternalLink, 'Text' => $record->hasMethod('getExternalLinkText') ? $record->getExternalLinkText() : 'External Link')); return $data->renderWith('GridFieldExternalLink'); }
function saveInto(DataObject $record) { $name = $this->name; $fieldSet = $record->{$name}(); $record->EmailTo = $_REQUEST[$name]['EmailTo']; $record->EmailOnSubmit = isset($_REQUEST[$name]['EmailOnSubmit']) ? "1" : "0"; $record->SubmitButtonText = $_REQUEST[$name]['SubmitButtonText']; // store the field IDs and delete the missing fields // alternatively, we could delete all the fields and re add them $missingFields = array(); foreach ($fieldSet as $existingField) { $missingFields[$existingField->ID] = $existingField; } // write the new fields to the database if ($_REQUEST[$name]) { foreach (array_keys($_REQUEST[$name]) as $newEditableID) { $newEditableData = $_REQUEST[$name][$newEditableID]; // `ParentID`=0 is for the new page $editable = DataObject::get_one('EditableFormField', "(`ParentID`='{$record->ID}' OR `ParentID`=0) AND `EditableFormField`.`ID`='{$newEditableID}'"); // check if we are updating an existing field if ($editable && isset($missingFields[$editable->ID])) { unset($missingFields[$editable->ID]); } // create a new object // this should now be obsolete if (!$editable && !empty($newEditableData['Type']) && class_exists($newEditableData['Type'])) { $editable = new $newEditableData['Type'](); $editable->ID = 0; $editable->ParentID = $record->ID; if (!is_subclass_of($editable, 'EditableFormField')) { $editable = null; } } if ($editable) { if ($editable->ParentID == 0) { $editable->ParentID = $record->ID; } $editable->populateFromPostData($newEditableData); //$editable->write(); } } } // remove the fields not saved foreach ($missingFields as $removedField) { if (is_numeric($removedField->ID)) { $removedField->delete(); } } if ($record->hasMethod('customFormSave')) { $record->customFormSave($_REQUEST[$name], $record); } //$record->writeWithoutVersion(); if ($record->hasMethod('processNewFormFields')) { $record->processNewFormFields(); } }
/** * Mark all children of the given node that match the marking filter. * @param DataObject $node Parent node. * @return DataList */ public function markChildren($node, $context = null, $childrenMethod = "AllChildrenIncludingDeleted", $numChildrenMethod = "numChildren") { if ($node->hasMethod($childrenMethod)) { $children = $node->{$childrenMethod}($context); } else { user_error(sprintf("Can't find the method '%s' on class '%s' for getting tree children", $childrenMethod, get_class($node)), E_USER_ERROR); } $node->markExpanded(); if ($children) { foreach ($children as $child) { $markingMatches = $this->markingFilterMatches($child); // Filtered results should always show opened, since actual matches // might be hidden by non-matching parent nodes. if ($this->markingFilter && $markingMatches) { $child->markOpened(); } if (!$this->markingFilter || $markingMatches) { if ($child->{$numChildrenMethod}()) { $child->markUnexpanded(); } else { $child->markExpanded(); } $this->markedNodes[$child->ID] = $child; } } } return $children; }
/** * Returns all fields on the object which should be shown * in the output. Can be customised through {@link self::setCustomFields()}. * * @todo Allow for custom getters on the processed object (currently filtered through inheritedDatabaseFields) * @todo Field level permission checks * * @param DataObject $obj * @return array */ protected function getFieldsForObj($obj) { $dbFields = array(); // if custom fields are specified, only select these if(is_array($this->customFields)) { foreach($this->customFields as $fieldName) { // @todo Possible security risk by making methods accessible - implement field-level security if($obj->hasField($fieldName) || $obj->hasMethod("get{$fieldName}")) $dbFields[$fieldName] = $fieldName; } } else { // by default, all database fields are selected $dbFields = $obj->inheritedDatabaseFields(); } if(is_array($this->customAddFields)) { foreach($this->customAddFields as $fieldName) { // @todo Possible security risk by making methods accessible - implement field-level security if($obj->hasField($fieldName) || $obj->hasMethod("get{$fieldName}")) $dbFields[$fieldName] = $fieldName; } } // add default required fields $dbFields = array_merge($dbFields, array('ID'=>'Int')); // @todo Requires PHP 5.1+ if(is_array($this->removeFields)) { $dbFields = array_diff_key($dbFields, array_combine($this->removeFields,$this->removeFields)); } return $dbFields; }
/** * @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) { // The relation method will return a DataList, that getSearchQuery subsequently manipulates if ($obj->hasMethod($relationName)) { if ($relationClass = $obj->has_one($relationName)) { $joinField = $relationName . 'ID'; $list = DataList::create($relationClass)->byIDs(array($obj->{$joinField})); } else { $list = $obj->{$relationName}(); } $apiAccess = singleton($list->dataClass())->stat('api_access'); if (!$apiAccess) { return false; } return $this->getSearchQuery($list->dataClass(), $params, $sort, $limit, $list); } }