Source of file EditableBlockRow.php
Size: 16,148 Bytes - Last Modified: 2021-12-23T10:04:34+00:00
/var/www/docs.ssmods.com/process/src/code/forms/EditableBlockRow.php
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531 | <?php //namespace Milkyway\SS\GridFieldUtils; /** * Milkyway Multimedia * EditableRow.php * * @package milkyway-multimedia/ss-gridfield-utils * @author Mellisa Hankins <mell@milkywaymultimedia.com.au> */ use RequestHandler as RequestHandler; use GridField_HTMLProvider as GridField_HTMLProvider; use GridField_SaveHandler as GridField_SaveHandler; use GridField_URLHandler as GridField_URLHandler; use GridField_ColumnProvider as GridField_ColumnProvider; use Validator as Validator; use FieldList as FieldList; use Session as Session; class EditableBlockRow extends RequestHandler implements GridField_HTMLProvider, GridField_SaveHandler, GridField_URLHandler, GridField_ColumnProvider { public $column = '_OpenRowForEditing'; public $urlSegment = 'editableRow'; public $setWorkingParentOnRecordTo = 'Parent'; public $disableToggleStateSave = false; public $cacheToggleStateSave = false; public $openNewTogglesOnCreate = true; protected $permissionCallback; protected $itemEditFormCallback; protected $fields; protected $template; protected $validator; private $workingGrid; private static $allowed_actions = [ 'loadItem', 'handleForm', ]; /** * @param FieldList|callable|array $fields the fields to display in inline form */ public function __construct($fields = null) { $this->fields = $fields; parent::__construct(); } /** * Gets the fields for this class * * @return FieldList|callable|array */ public function getFields() { return $this->fields; } /** * Sets the fields that will be displayed in this component * * @param FieldList|callable|array $fields * @return static $this */ public function setFields($fields) { $this->fields = $fields; return $this; } /** * Gets the validator * * @return Validator|callable|array */ public function getValidator() { return $this->validator; } /** * Sets the validator that will be displayed in this component * * @param \Validator|Callable|array $validator * @return static $this */ public function setValidator($validator) { $this->validator = $validator; return $this; } /** * Get the permission callback for this column * * @return callable */ public function getPermissionCallback() { return $this->permissionCallback; } /** * Sets the permission callback for this column * * @param callable $permissionCallback * @return static $this */ public function setPermissionCallback($permissionCallback) { $this->permissionCallback = $permissionCallback; return $this; } /** * Get the callback for changes on the edit form after constructing it * * @return callable */ public function getItemEditFormCallback() { return $this->itemEditFormCallback; } /** * Make changes on the edit form after constructing it. * * @param callable $itemEditFormCallback * @return static $this */ public function setItemEditFormCallback($itemEditFormCallback) { $this->itemEditFormCallback = $itemEditFormCallback; return $this; } public function getURLHandlers($gridField) { return [ $this->urlSegment . '/load/$ID' => 'loadItem', $this->urlSegment . '/form/$ID' => 'handleForm', ]; } /** * Modify the list of columns displayed in the table. * * @see {@link GridFieldDataColumns->getDisplayFields()} * @see {@link GridFieldDataColumns}. * * @param \GridField $gridField * @param array - List reference of all column names. */ public function augmentColumns($gridField, &$columns) { if (!in_array($this->column, $columns)) { array_unshift($columns, $this->column); } } /** * Names of all columns which are affected by this component. * * @param \GridField $gridField * * @return array */ public function getColumnsHandled($gridField) { return [$this->column]; } /** * HTML for the column, content of the <td> element. * * @param \GridField $gridField * @param \DataObject $record - Record displayed in this row * @param string $columnName * * @return string - HTML for the column. Return NULL to skip. */ public function getColumnContent($gridField, $record, $columnName) { if (!$this->checkPermission($gridField, $record, $columnName)) { return ''; } $classes = 'ss-gridfield-editable-row--icon'; if ($record) { $classes .= ' ss-gridfield-editable-row--toggle'; } $openToggleId = 'EditableRowToggles.' . $gridField->ID() . '.' . get_class($record) . '_' . $record->ID; if ($this->openNewTogglesOnCreate && Session::get($openToggleId)) { $classes .= ' ss-gridfield-editable-row--toggle_start'; } Session::clear($openToggleId); return sprintf('<i class="%s"></i>', $classes); } /** * Attributes for the element containing the content returned by {@link getColumnContent()}. * * @param \GridField $gridField * @param \DataObject $record displayed in this row * @param string $columnName * * @return array */ public function getColumnAttributes($gridField, $record, $columnName) { $this->workingGrid = $gridField; if (!$this->checkPermission($gridField, $record, $columnName)) { return []; } return [ 'data-link' => $this->Link('load', $record->ID), 'class' => 'ss-gridfield-editable-row--icon-holder', ]; } /** * Additional metadata about the column which can be used by other components, * e.g. to set a title for a search column header. * * @param \GridField $gridField * @param string $columnName * * @return array - Map of arbitrary metadata identifiers to their values. */ public function getColumnMetadata($gridField, $columnName) { if ($columnName == $this->column) { return [ 'title' => '', ]; } } public function getHTMLFragments($grid) { //singleton('require')->css(SS_MWM_DIR . '/thirdparty/font-awesome/font-awesome.min.css'); $grid->addExtraClass('ss-gridfield-editable-rows'); //Utilities::include_requirements(); if ($this->disableToggleStateSave) { $grid->addExtraClass('ss-gridfield-editable-rows_disableToggleState'); } if ($this->cacheToggleStateSave) { $grid->addExtraClass('ss-gridfield-editable-rows_allowCachedToggles'); } $this->workingGrid = $grid; } public function handleSave(\GridField $grid, \DataObjectInterface $record) { $list = $grid->getList(); $value = $grid->Value(); $className = $this->getComponentName(); if (!isset($value[$className]) || !is_array($value[$className])) { return; } foreach ($value[$className] as $id => $fields) { if (!is_numeric($id) || !is_array($fields)) { continue; } $item = $list->byID($id); if (!$item || !$item->canEdit()) { continue; } $form = $this->getForm($grid, $item, false); $form->loadDataFrom($fields); $form->saveInto($item); $extra = method_exists($list, 'getExtraFields') ? array_intersect_key($form->Data, (array)$list->getExtraFields()) : []; // FIX: nonsaving boolean/checkboxfields (unchecked will not be posted) foreach ($form->Fields()->saveableFields() as $formfield) { // if boolean field is included in form and unset in values, unset on object if($formfield instanceof CheckboxField && !array_key_exists($formfield->name,$fields)){ $item->{$formfield->name} = 0; } } $item->write(); $list->add($item, $extra); } } public function getForm($grid, $record, $removeEditableColumnFields = true) { $this->workingGrid = $grid; $form = \Form::create($this, $grid->ID() . '-EditableRow-' . $record->ID, //\FieldList::create(), $this->getFieldList($record, $grid, $removeEditableColumnFields), \FieldList::create(), $this->getValidatorForForm($record, $grid) ) ->loadDataFrom($record) ->setFormAction($this->Link('form',$record->ID)) ->disableSecurityToken() ; if ($form->Fields()->hasTabSet() && ($root = $form->Fields()->findOrMakeTab('Root')) && $root->Template == 'CMSTabSet') { $root->setTemplate(''); $form->removeExtraClass('cms-tabset'); } $callback = $this->getItemEditFormCallback(); if ($callback) { call_user_func($callback, $form, $this, $grid, $record, $removeEditableColumnFields); } return $form; } protected function getFieldList($record, $grid = null, $removeEditableColumnFields = true) { $fields = null; if ($this->fields) { if ($this->fields instanceof \FieldList) { $fields = $this->fields; } elseif (is_callable($this->fields)) { $fields = call_user_func_array($this->fields, [$record, $grid, $this]); } else { $fields = \FieldList::create($this->fields); } } if (!$fields && $record->hasMethod('getEditableRowFields')) { $fields = $record->getEditableRowFields($grid); } if (!$fields && $grid) { if ($editable = $grid->getConfig()->getComponentByType('GridFieldDetailForm')) { if ($editable->getFields()) { $fields = $editable->getFields(); } else { $fields = \Object::create($editable->getItemRequestClass(), $grid, $editable, $record, $grid->getForm()->getController(), $editable->getName())->ItemEditForm()->Fields(); } } } if ($removeEditableColumnFields && $grid && $editable = $grid->getConfig()->getComponentByType('GridFieldEditableColumns')) { $editableColumns = $editable->getFields($grid, $record); foreach ($editableColumns as $column) { $fields->removeByName($column->Name); } } //print_r($fields->saveableFields()); return $fields; } protected function getValidatorForForm($record, $grid = null) { if ($this->validator) { if ($this->validator instanceof \Validator) { return $this->validator; } elseif (is_callable($this->validator)) { return call_user_func_array($this->validator, [$record, $grid, $this]); } else { return \Validator::create($this->validator); } } if ($grid) { if ($editable = $grid->getConfig()->getComponentByType('GridFieldDetailForm')) { return $editable->getValidator(); } } if ($record->hasMethod('getEditableRowValidator')) { return $record->getEditableRowValidator($grid); } return $record->hasMethod('getCMSValidator') ? $record->getCMSValidator() : null; } public function handleForm($grid, $request) { $id = $request->param('ID'); $record = $this->getRecordFromRequest($grid, $request); $form = $this->getForm($grid, $record); $class = $this->getComponentName(); foreach ($form->Fields()->dataFields() as $field) { $field->setName(sprintf( '%s[%s][%s][%s]', $grid->getName(), $class, $id, $field->getName() )); } $form->setController($grid->getForm()->getController()); // if(!$request->isGET() && $request->remaining() && ($newGrid = $form->handleRequest($request, \DataModel::inst())) && ($newGrid instanceof $grid) && ($row = $newGrid->getConfig()->getComponentByType(__CLASS__))) { // $form = $row->handleForm($newGrid, $request); // } return $form; } public function loadItem($grid, $request) { $record = $this->getRecordFromRequest($grid, $request); $form = $this->getForm($grid, $record); //$form = new \Form($this, 'something', $record->getCMSFields(), FieldList::create()); $this->renameFieldsInCompositeField($form->Fields(), $grid, $record); $canEdit = $record->canEdit(); $canView = $record->canView(); if (!$canEdit && !$canView) { throw new \LogicException('You do not have permission to view this record'); } if (!$canEdit) { $form->makeReadonly(); } $countUntilThisColumn = 0; foreach ($grid->getColumns() as $column) { $countUntilThisColumn++; if ($column == $this->column) { break; } } if ($countUntilThisColumn == count($grid->getColumns())) { $countUntilThisColumn = 0; } return $record->customise([ 'Form' => $form, 'ColumnCount' => count($grid->getColumns()), 'PrevColumnsCount' => $countUntilThisColumn, 'OtherColumnsCount' => count($grid->getColumns()) - $countUntilThisColumn, ])->renderWith(array_merge((array)$this->template, ['GridField_EditableBlockRow'])); } protected function getRecordFromRequest($grid, $request) { $id = $request->param('ID'); $list = $grid->getList(); if (!ctype_digit($id)) { throw new \SS_HTTPResponse_Exception(null, 400); } if (!$record = $list->byID($id)) { throw new \SS_HTTPResponse_Exception(null, 404); } if ($this->setWorkingParentOnRecordTo) { if ($grid->List && ($grid->List instanceof \ManyManyList) && $grid->Form && $grid->Form->Record) { $record->{$this->setWorkingParentOnRecordTo} = $grid->Form->Record; } } return $record; } public function Link($action = null, $id = null) { return $this->workingGrid ? \Controller::join_links($this->workingGrid->Link($this->urlSegment), $action, $id) : null; } protected function renameFieldsInCompositeField($fields, $grid, $record) { $class = $this->getComponentName(); foreach ($fields as $field) { $field->setName(sprintf( '%s[%s][%s][%s]', $grid->getName(), $class, $record->ID, $field->getName() )); if ($field->isComposite()) { $this->renameFieldsInCompositeField($field->FieldList(), $grid, $record); } } } private $canView = []; protected function checkPermission($gridField, $record, $columnName) { if (isset($this->canView[$record->ID])) { return $this->canView[$record->ID]; } $this->canView[$record->ID] = ($this->permissionCallback && call_user_func($this->permissionCallback, $gridField, $record, $columnName)) || (!$this->permissionCallback && ($record->canView() || $record->canEdit())); return $this->canView[$record->ID]; } protected function getComponentName() { return str_replace(['\\', '-'], '_', __CLASS__ . '_' . $this->urlSegment); } } |