/** * Returns a data class that is a DataObject type that this GridField should look like. * * @return string * * @throws LogicException */ public function getModelClass() { if ($this->modelClassName) { return $this->modelClassName; } if ($this->list && $this->list->hasMethod('dataClass')) { $class = $this->list->dataClass(); if ($class) { return $class; } } throw new LogicException('GridField doesn\'t have a modelClassName, so it doesn\'t know the columns of this grid.'); }
/** * If an object ID is set, add the object to the list * * @param GridField $gridField * @param SS_List $dataList * @return SS_List */ public function getManipulatedData(GridField $gridField, SS_List $dataList) { $objectID = $gridField->State->GridFieldAddRelation(null); if (empty($objectID)) { return $dataList; } $object = DataObject::get_by_id($gridField->getModelClass(), $objectID); if ($object) { $dataList->add($object); } $gridField->State->GridFieldAddRelation = null; return $dataList; }
/** * 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 $this Self reference * @throws ValidationException */ 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 parent::setValue($value, $record); return $this; }
/** * @param array $properties * @return string */ public function Field($properties = array()) { $uninheritedCodes = array(); $inheritedCodes = array(); $records = $this->records ? $this->records : new ArrayList(); // Get existing values from the form record (assuming the formfield name is a join field on the record) if (is_object($this->form)) { $record = $this->form->getRecord(); if ($record && ($record instanceof Group || $record instanceof PermissionRole) && !$records->find('ID', $record->ID)) { $records->push($record); } } // Get all 'inherited' codes not directly assigned to the group (which is stored in $values) foreach ($records as $record) { // Get all uninherited permissions $relationMethod = $this->name; foreach ($record->{$relationMethod}() as $permission) { if (!isset($uninheritedCodes[$permission->Code])) { $uninheritedCodes[$permission->Code] = array(); } $uninheritedCodes[$permission->Code][] = _t('PermissionCheckboxSetField.AssignedTo', 'assigned to "{title}"', array('title' => $record->dbObject('Title')->forTemplate())); } // Special case for Group records (not PermissionRole): // Determine inherited assignments if ($record instanceof Group) { // Get all permissions from roles if ($record->Roles()->count()) { foreach ($record->Roles() as $role) { /** @var PermissionRole $role */ foreach ($role->Codes() as $code) { if (!isset($inheritedCodes[$code->Code])) { $inheritedCodes[$code->Code] = array(); } $inheritedCodes[$code->Code][] = _t('PermissionCheckboxSetField.FromRole', 'inherited from role "{title}"', 'A permission inherited from a certain permission role', array('title' => $role->dbObject('Title')->forTemplate())); } } } // Get from parent groups $parentGroups = $record->getAncestors(); if ($parentGroups) { foreach ($parentGroups as $parent) { if (!$parent->Roles()->Count()) { continue; } foreach ($parent->Roles() as $role) { if ($role->Codes()) { foreach ($role->Codes() as $code) { if (!isset($inheritedCodes[$code->Code])) { $inheritedCodes[$code->Code] = array(); } $inheritedCodes[$code->Code][] = _t('PermissionCheckboxSetField.FromRoleOnGroup', 'inherited from role "%s" on group "%s"', 'A permission inherited from a role on a certain group', array('roletitle' => $role->dbObject('Title')->forTemplate(), 'grouptitle' => $parent->dbObject('Title')->forTemplate())); } } } if ($parent->Permissions()->Count()) { foreach ($parent->Permissions() as $permission) { if (!isset($inheritedCodes[$permission->Code])) { $inheritedCodes[$permission->Code] = array(); } $inheritedCodes[$permission->Code][] = _t('PermissionCheckboxSetField.FromGroup', 'inherited from group "{title}"', 'A permission inherited from a certain group', array('title' => $parent->dbObject('Title')->forTemplate())); } } } } } } $odd = 0; $options = ''; $globalHidden = (array) Config::inst()->get('SilverStripe\\Security\\Permission', 'hidden_permissions'); if ($this->source) { $privilegedPermissions = Permission::config()->privileged_permissions; // loop through all available categorized permissions and see if they're assigned for the given groups foreach ($this->source as $categoryName => $permissions) { $options .= "<li><h5>{$categoryName}</h5></li>"; foreach ($permissions as $code => $permission) { if (in_array($code, $this->hiddenPermissions)) { continue; } if (in_array($code, $globalHidden)) { continue; } $value = $permission['name']; $odd = ($odd + 1) % 2; $extraClass = $odd ? 'odd' : 'even'; $extraClass .= ' val' . str_replace(' ', '', $code); $itemID = $this->ID() . '_' . preg_replace('/[^a-zA-Z0-9]+/', '', $code); $disabled = $inheritMessage = ''; $checked = isset($uninheritedCodes[$code]) || isset($inheritedCodes[$code]) ? ' checked="checked"' : ''; $title = $permission['help'] ? 'title="' . htmlentities($permission['help'], ENT_COMPAT, 'UTF-8') . '" ' : ''; if (isset($inheritedCodes[$code])) { // disable inherited codes, as any saving logic would be too complicate to express in this // interface $disabled = ' disabled="true"'; $inheritMessage = ' (' . join(', ', $inheritedCodes[$code]) . ')'; } elseif ($this->records && $this->records->Count() > 1 && isset($uninheritedCodes[$code])) { // If code assignments are collected from more than one "source group", // show its origin automatically $inheritMessage = ' (' . join(', ', $uninheritedCodes[$code]) . ')'; } // Disallow modification of "privileged" permissions unless currently logged-in user is an admin if (!Permission::check('ADMIN') && in_array($code, $privilegedPermissions)) { $disabled = ' disabled="true"'; } // If the field is readonly, always mark as "disabled" if ($this->readonly) { $disabled = ' disabled="true"'; } $inheritMessage = '<small>' . $inheritMessage . '</small>'; $icon = $checked ? 'accept' : 'decline'; // If the field is readonly, add a span that will replace the disabled checkbox input if ($this->readonly) { $options .= "<li class=\"{$extraClass}\">" . "<input id=\"{$itemID}\"{$disabled} name=\"{$this->name}[{$code}]\" type=\"checkbox\"" . " value=\"{$code}\"{$checked} class=\"checkbox\" />" . "<label {$title}for=\"{$itemID}\">" . "<span class=\"ui-button-icon-primary ui-icon btn-icon-{$icon}\"></span>" . "{$value}{$inheritMessage}</label>" . "</li>\n"; } else { $options .= "<li class=\"{$extraClass}\">" . "<input id=\"{$itemID}\"{$disabled} name=\"{$this->name}[{$code}]\" type=\"checkbox\"" . " value=\"{$code}\"{$checked} class=\"checkbox\" />" . "<label {$title}for=\"{$itemID}\">{$value}{$inheritMessage}</label>" . "</li>\n"; } } } } if ($this->readonly) { return "<ul id=\"{$this->ID()}\" class=\"optionset checkboxsetfield{$this->extraClass()}\">\n" . "<li class=\"help\">" . _t('Permissions.UserPermissionsIntro', 'Assigning groups to this user will adjust the permissions they have.' . ' See the groups section for details of permissions on individual groups.') . "</li>" . $options . "</ul>\n"; } else { return "<ul id=\"{$this->ID()}\" class=\"optionset checkboxsetfield{$this->extraClass()}\">\n" . $options . "</ul>\n"; } }
public function debug() { return $this->list->debug(); }
/** * Get the list of extra data from the $record as saved into it by * {@see Form::saveInto()} * * Handles detection of falsey values explicitly saved into the * DataObject by formfields * * @param DataObject $record * @param SS_List $list * @return array List of data to write to the relation */ protected function getExtraSavedData($record, $list) { // Skip extra data if not ManyManyList if (!$list instanceof ManyManyList) { return null; } $data = array(); foreach ($list->getExtraFields() as $field => $dbSpec) { $savedField = "ManyMany[{$field}]"; if ($record->hasField($savedField)) { $data[$field] = $record->getField($savedField); } } return $data; }