Skip to content

Commit

Permalink
NEW Make most GridField components work with arbitrary data
Browse files Browse the repository at this point in the history
  • Loading branch information
GuySartorelli committed Nov 14, 2023
1 parent 4843fba commit 0149f7b
Show file tree
Hide file tree
Showing 7 changed files with 55 additions and 35 deletions.
5 changes: 3 additions & 2 deletions src/Forms/GridField/GridFieldAddNewButton.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
namespace SilverStripe\Forms\GridField;

use SilverStripe\Control\Controller;
use SilverStripe\Core\ClassInfo;
use SilverStripe\ORM\DataObject;
use SilverStripe\ORM\RelationList;
use SilverStripe\View\ArrayData;
Expand Down Expand Up @@ -45,13 +46,13 @@ public function getHTMLFragments($gridField)
}
}

if (!$singleton->canCreate(null, $context)) {
if (!$singleton->hasMethod('canCreate') || !$singleton->canCreate(null, $context)) {
return [];
}

if (!$this->buttonName) {
// provide a default button name, can be changed by calling {@link setButtonName()} on this component
$objectName = $singleton->i18n_singular_name();
$objectName = $singleton->hasMethod('i18n_singular_name') ? $singleton->i18n_singular_name() : ClassInfo::shortName($singleton);
$this->buttonName = _t('SilverStripe\\Forms\\GridField\\GridField.Add', 'Add {name}', ['name' => $objectName]);
}

Expand Down
8 changes: 4 additions & 4 deletions src/Forms/GridField/GridFieldDeleteAction.php
Original file line number Diff line number Diff line change
Expand Up @@ -187,15 +187,15 @@ public function handleAction(GridField $gridField, $actionName, $arguments, $dat
}

if ($actionName == 'deleterecord') {
if (!$item->canDelete()) {
if (!$item->hasMethod('canDelete') || !$item->canDelete()) {
throw new ValidationException(
_t(__CLASS__ . '.DeletePermissionsFailure', "No delete permissions")
);
}

$item->delete();
} else {
if (!$item->canEdit()) {
if (!$item->hasMethod('canEdit') || !$item->canEdit()) {
throw new ValidationException(
_t(__CLASS__ . '.EditPermissionsFailure', "No permission to unlink record")
);
Expand All @@ -216,7 +216,7 @@ public function handleAction(GridField $gridField, $actionName, $arguments, $dat
private function getRemoveAction($gridField, $record, $columnName)
{
if ($this->getRemoveRelation()) {
if (!$record->canEdit()) {
if (!$record->hasMethod('canEdit') || !$record->canEdit()) {
return null;
}
$title = _t(__CLASS__ . '.UnlinkRelation', "Unlink");
Expand All @@ -233,7 +233,7 @@ private function getRemoveAction($gridField, $record, $columnName)
->setDescription($title)
->setAttribute('aria-label', $title);
} else {
if (!$record->canDelete()) {
if (!$record->hasMethod('canDelete') || !$record->canDelete()) {
return null;
}
$title = _t(__CLASS__ . '.Delete', "Delete");
Expand Down
11 changes: 9 additions & 2 deletions src/Forms/GridField/GridFieldDetailForm.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,12 @@
use SilverStripe\Core\Extensible;
use SilverStripe\Core\Injector\Injector;
use SilverStripe\Forms\FieldList;
use SilverStripe\Forms\FieldsValidator;
use SilverStripe\Forms\Validator;
use SilverStripe\ORM\DataList;
use SilverStripe\ORM\DataObject;
use SilverStripe\ORM\Filterable;
use SilverStripe\View\ViewableData;

/**
* Provides view and edit forms at GridField-specific URLs.
Expand Down Expand Up @@ -143,7 +145,12 @@ public function handleItem($gridField, $request)

// if no validator has been set on the GridField then use the Validators from the record.
if (!$this->getValidator()) {
$this->setValidator($record->getCMSCompositeValidator());
if ($record->hasMethod('getCMSCompositeValidator')) {
$validator = $record->getCMSCompositeValidator();
} else {
$validator = FieldsValidator::create();
}
$this->setValidator($validator);
}

return $handler->handleRequest($request);
Expand All @@ -154,7 +161,7 @@ public function handleItem($gridField, $request)
* @param HTTPRequest $request
* @return DataObject|null
*/
protected function getRecordFromRequest(GridField $gridField, HTTPRequest $request): ?DataObject
protected function getRecordFromRequest(GridField $gridField, HTTPRequest $request): ?ViewableData
{
/** @var DataObject $record */
if (is_numeric($request->param('ID'))) {
Expand Down
50 changes: 31 additions & 19 deletions src/Forms/GridField/GridFieldDetailForm_ItemRequest.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
use SilverStripe\Control\HTTPRequest;
use SilverStripe\Control\HTTPResponse;
use SilverStripe\Control\RequestHandler;
use SilverStripe\Core\ClassInfo;
use SilverStripe\Forms\CompositeField;
use SilverStripe\Forms\FieldList;
use SilverStripe\Forms\Form;
Expand All @@ -27,6 +28,7 @@
use SilverStripe\View\ArrayData;
use SilverStripe\View\HTML;
use SilverStripe\View\SSViewer;
use SilverStripe\View\ViewableData;

class GridFieldDetailForm_ItemRequest extends RequestHandler
{
Expand Down Expand Up @@ -63,7 +65,7 @@ class GridFieldDetailForm_ItemRequest extends RequestHandler
protected $component;

/**
* @var DataObject
* @var ViewableData
*/
protected $record;

Expand Down Expand Up @@ -95,7 +97,7 @@ class GridFieldDetailForm_ItemRequest extends RequestHandler
*
* @param GridField $gridField
* @param GridFieldDetailForm $component
* @param DataObject $record
* @param ViewableData $record
* @param RequestHandler $requestHandler
* @param string $popupFormName
*/
Expand Down Expand Up @@ -124,11 +126,12 @@ public function Link($action = null)
*/
public function view($request)
{
if (!$this->record->canView()) {
// Assume we can view the record if there's no canView method
if ($this->record->hasMethod('canView') && !$this->record->canView()) {
$this->httpError(403, _t(
__CLASS__ . '.ViewPermissionsFailure',
'It seems you don\'t have the necessary permissions to view "{ObjectTitle}"',
['ObjectTitle' => $this->record->singular_name()]
['ObjectTitle' => $this->getModelName()]
));
}

Expand Down Expand Up @@ -206,12 +209,13 @@ public function ItemEditForm()
}
}

if (!$this->record->canView()) {
// Assume we can view the record if there's no canView method
if ($this->record->hasMethod('canView') && !$this->record->canView()) {
$controller = $this->getToplevelController();
return $controller->httpError(403, _t(
__CLASS__ . '.ViewPermissionsFailure',
'It seems you don\'t have the necessary permissions to view "{ObjectTitle}"',
['ObjectTitle' => $this->record->singular_name()]
['ObjectTitle' => $this->getModelName()]
));
}

Expand Down Expand Up @@ -240,15 +244,15 @@ public function ItemEditForm()

$form->loadDataFrom($this->record, $this->record->ID == 0 ? Form::MERGE_IGNORE_FALSEISH : Form::MERGE_DEFAULT);

if ($this->record->ID && !$this->record->canEdit()) {
if ($this->record->ID && (!$this->record->hasMethod('canEdit') || !$this->record->canEdit())) {
// Restrict editing of existing records
$form->makeReadonly();
// Hack to re-enable delete button if user can delete
if ($this->record->canDelete()) {
if ($this->record->hasMethod('canDelete') && $this->record->canDelete()) {
$form->Actions()->fieldByName('action_doDelete')->setReadonly(false);
}
} elseif (!$this->record->ID
&& !$this->record->canCreate(null, $this->getCreateContext())
&& (!$this->record->hasMethod('canCreate') || !$this->record->canCreate(null, $this->getCreateContext()))
) {
// Restrict creation of new records
$form->makeReadonly();
Expand Down Expand Up @@ -358,7 +362,7 @@ protected function getRightGroupField()

$rightGroup->push($previousAndNextGroup);

if ($component && $component->getShowAdd() && $this->record->canCreate()) {
if ($component && $component->getShowAdd() && $this->record->hasMethod('canCreate') && $this->record->canCreate()) {
$rightGroup->push(
LiteralField::create(
'new-record',
Expand Down Expand Up @@ -391,7 +395,7 @@ protected function getFormActions()
$actions->push($majorActions);

if ($this->record->ID !== 0) { // existing record
if ($this->record->canEdit()) {
if ($this->record->hasMethod('canEdit') && $this->record->canEdit()) {
$noChangesClasses = 'btn-outline-primary font-icon-tick';
$majorActions->push(FormAction::create('doSave', _t('SilverStripe\\Forms\\GridField\\GridFieldDetailForm.Save', 'Save'))
->addExtraClass($noChangesClasses)
Expand All @@ -401,7 +405,7 @@ protected function getFormActions()
->setAttribute('data-text-alternate', _t('SilverStripe\\CMS\\Controllers\\CMSMain.SAVEDRAFT', 'Save')));
}

if ($this->record->canDelete()) {
if ($this->record->hasMethod('canDelete') && $this->record->canDelete()) {
$actions->insertAfter('MajorActions', FormAction::create('doDelete', _t('SilverStripe\\Forms\\GridField\\GridFieldDetailForm.Delete', 'Delete'))
->setUseButtonTag(true)
->addExtraClass('btn-outline-danger btn-hide-outline font-icon-trash-bin action--delete'));
Expand Down Expand Up @@ -509,11 +513,11 @@ public function doSave($data, $form)
$isNewRecord = $this->record->ID == 0;

// Check permission
if (!$this->record->canEdit()) {
if (!$this->record->hasMethod('canEdit') || !$this->record->canEdit()) {
$this->httpError(403, _t(
__CLASS__ . '.EditPermissionsFailure',
'It seems you don\'t have the necessary permissions to edit "{ObjectTitle}"',
['ObjectTitle' => $this->record->singular_name()]
['ObjectTitle' => $this->getModelName()]
));
return null;
}
Expand All @@ -528,7 +532,7 @@ public function doSave($data, $form)
'SilverStripe\\Forms\\GridField\\GridFieldDetailForm.Saved',
'Saved {name} {link}',
[
'name' => $this->record->i18n_singular_name(),
'name' => $this->getModelName(),
'link' => $link
]
);
Expand Down Expand Up @@ -765,7 +769,7 @@ protected function saveFormIntoRecord($data, $form)
public function doDelete($data, $form)
{
$title = $this->record->Title;
if (!$this->record->canDelete()) {
if (!$this->record->hasMethod('canDelete') || !$this->record->canDelete()) {
throw new ValidationException(
_t('SilverStripe\\Forms\\GridField\\GridFieldDetailForm.DeletePermissionsFailure', "No delete permissions")
);
Expand All @@ -776,7 +780,7 @@ public function doDelete($data, $form)
'SilverStripe\\Forms\\GridField\\GridFieldDetailForm.Deleted',
'Deleted {type} {name}',
[
'type' => $this->record->i18n_singular_name(),
'type' => $this->getModelName(),
'name' => htmlspecialchars($title ?? '', ENT_QUOTES)
]
);
Expand Down Expand Up @@ -846,7 +850,7 @@ public function getGridField()
}

/**
* @return DataObject
* @return ViewableData
*/
public function getRecord()
{
Expand Down Expand Up @@ -882,7 +886,7 @@ public function Breadcrumbs($unlinked = false)
]));
} else {
$items->push(ArrayData::create([
'Title' => _t('SilverStripe\\Forms\\GridField\\GridField.NewRecord', 'New {type}', ['type' => $this->record->i18n_singular_name()]),
'Title' => _t('SilverStripe\\Forms\\GridField\\GridField.NewRecord', 'New {type}', ['type' => $this->getModelName()]),
'Link' => false
]));
}
Expand All @@ -896,4 +900,12 @@ public function Breadcrumbs($unlinked = false)
$this->extend('updateBreadcrumbs', $items);
return $items;
}

private function getModelName(): string
{
if ($this->record->hasMethod('i18n_singular_name')) {
return $this->record->i18n_singular_name();
}
return ClassInfo::shortName($this->record);
}
}
6 changes: 3 additions & 3 deletions src/Forms/GridField/GridFieldExportButton.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@
use SilverStripe\Control\HTTPResponse;
use SilverStripe\Core\Config\Config;
use SilverStripe\ORM\DataList;
use SilverStripe\ORM\DataObject;
use SilverStripe\ORM\ArrayList;
use SilverStripe\View\ViewableData;

/**
* Adds an "Export list" button to the bottom of a {@link GridField}.
Expand Down Expand Up @@ -155,7 +155,7 @@ protected function getExportColumnsForGridField(GridField $gridField)
return $dataCols->getDisplayFields($gridField);
}

return DataObject::singleton($gridField->getModelClass())->summaryFields();
return singleton($gridField->getModelClass())->summaryFields();
}

/**
Expand Down Expand Up @@ -225,7 +225,7 @@ public function generateExportFileData($gridField)
// Remove limit as the list may be paginated, we want the full list for the export
$items = $items->limit(null);

/** @var DataObject $item */
/** @var ViewableData $item */
foreach ($items as $item) {
if (!$item->hasMethod('canView') || $item->canView()) {
$columnData = [];
Expand Down
8 changes: 4 additions & 4 deletions src/Forms/GridField/GridFieldPrintButton.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,12 @@
use SilverStripe\Core\Convert;
use SilverStripe\Core\Extensible;
use SilverStripe\ORM\ArrayList;
use SilverStripe\ORM\DataObject;
use SilverStripe\ORM\FieldType\DBDatetime;
use SilverStripe\ORM\FieldType\DBHTMLText;
use SilverStripe\Security\Security;
use SilverStripe\View\ArrayData;
use SilverStripe\View\Requirements;
use SilverStripe\View\ViewableData;

/**
* Adds an "Print" button to the bottom or top of a GridField.
Expand Down Expand Up @@ -161,7 +161,7 @@ protected function getPrintColumnsForGridField(GridField $gridField)
return $dataCols->getDisplayFields($gridField);
}

return DataObject::singleton($gridField->getModelClass())->summaryFields();
return singleton($gridField->getModelClass())->summaryFields();
}

/**
Expand Down Expand Up @@ -226,9 +226,9 @@ public function generatePrintData(GridField $gridField)
/** @var GridFieldDataColumns $gridFieldColumnsComponent */
$gridFieldColumnsComponent = $gridField->getConfig()->getComponentByType(GridFieldDataColumns::class);

/** @var DataObject $item */
/** @var ViewableData $item */
foreach ($items->limit(null) as $item) {
if (!$item->hasMethod('canView') || $item->canView()) {
if ($item->hasMethod('canView') && $item->canView()) {
$itemRow = new ArrayList();

foreach ($printColumns as $field => $label) {
Expand Down
2 changes: 1 addition & 1 deletion src/Forms/GridField/GridFieldViewButton.php
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ public function getColumnsHandled($field)

public function getColumnContent($field, $record, $col)
{
if (!$record->canView()) {
if ($record->hasMethod('canView') && !$record->canView()) {
return null;
}
$data = new ArrayData([
Expand Down

0 comments on commit 0149f7b

Please sign in to comment.