From ce79a57f95ce518326a3e178a39b01a59462b307 Mon Sep 17 00:00:00 2001 From: Thomas Date: Mon, 2 Dec 2024 12:36:33 +0100 Subject: [PATCH] fix readonly actions / fix somes types --- src/ActionsGridFieldItemRequest.php | 64 ++++++++++++++++++++++++++--- src/CustomButton.php | 8 ++-- src/DefaultLink.php | 4 ++ src/GridFieldSaveAllButton.php | 23 +++++++++-- src/ProgressiveAction.php | 3 ++ 5 files changed, 91 insertions(+), 11 deletions(-) diff --git a/src/ActionsGridFieldItemRequest.php b/src/ActionsGridFieldItemRequest.php index b7c7f72..2004497 100644 --- a/src/ActionsGridFieldItemRequest.php +++ b/src/ActionsGridFieldItemRequest.php @@ -3,6 +3,7 @@ namespace LeKoala\CmsActions; use Exception; +use PhpOffice\PhpSpreadsheet\Calculation\MathTrig\Exp; use ReflectionMethod; use SilverStripe\Forms\Tab; use SilverStripe\Forms\Form; @@ -152,6 +153,7 @@ public function recordCmsUtils() $reflectionMethod = new ReflectionMethod($owner, 'getRecord'); $record = count($reflectionMethod->getParameters()) > 0 ? $owner->getRecord(0) : $owner->getRecord(); if ($record && $record->hasMethod('getCMSUtils')) { + //@phpstan-ignore-next-line $utils = $record->getCMSUtils(); $this->extend('onCMSUtils', $utils, $record); $record->extend('onCMSUtils', $utils); @@ -160,9 +162,38 @@ public function recordCmsUtils() return false; } + /** + * @param Form $form + * @return void + */ + public function updateItemEditForm($form) + { + $record = $this->owner->getRecord(); + if (!$record) { + return; + } + + // We get the actions as defined on our record + /** @var FieldList $CMSActions */ + $CMSActions = $record->getCMSActions(); + + $FormActions = $form->Actions(); + + // Push our actions that are otherwise ignored by SilverStripe + foreach ($CMSActions as $CMSAction) { + $action = $FormActions->fieldByName($CMSAction->getName()); + + if ($action) { + // If it has been made readonly, revert + if ($CMSAction->isReadonly() != $action->isReadonly()) { + $FormActions->replaceField($action->getName(), $action->setReadonly($CMSAction->isReadonly())); + } + } + } + } + /** * Called by GridField_ItemRequest - * GridField_ItemRequest defines its own set of actions so we need to add ours * We add our custom save&close, save&next and other tweaks * Actions can be made readonly after this extension point * @param FieldList $actions @@ -546,7 +577,7 @@ protected function getBtnClassForRecord(DataObject $record) /** * @param string $action * @param array|FieldList $definedActions - * @return mixed|CompositeField|null + * @return FormField|null */ protected static function findAction($action, $definedActions) { @@ -632,6 +663,14 @@ protected function forwardActionToRecord($action, $data = [], $form = null) $availableActions )); } + + if ($clickedAction->isReadonly() || $clickedAction->isDisabled()) { + return $this->owner->httpError(403, sprintf( + 'Action %s is disabled', + $clickedAction->getName(), + )); + } + $message = null; $error = false; @@ -639,6 +678,11 @@ protected function forwardActionToRecord($action, $data = [], $form = null) // It can be deleted by the action, and it will return to the list $isNewRecord = $record->ID === 0; + $actionTitle = $clickedAction->getName(); + if (method_exists($clickedAction, 'getTitle')) { + $actionTitle = $clickedAction->getTitle(); + } + try { $result = $record->$action($data, $form, $controller); @@ -653,7 +697,10 @@ protected function forwardActionToRecord($action, $data = [], $form = null) $message = _t( 'ActionsGridFieldItemRequest.FAILED', 'Action {action} failed on {name}', - ['action' => $clickedAction->getTitle(), 'name' => $record->i18n_singular_name()] + [ + 'action' => $actionTitle, + 'name' => $record->i18n_singular_name(), + ] ); } elseif (is_string($result)) { // Result is a message @@ -670,7 +717,10 @@ protected function forwardActionToRecord($action, $data = [], $form = null) $message = _t( 'ActionsGridFieldItemRequest.DONE', 'Action {action} was done on {name}', - ['action' => $clickedAction->getTitle(), 'name' => $record->i18n_singular_name()] + [ + 'action' => $actionTitle, + 'name' => $record->i18n_singular_name(), + ] ); } $status = 'good'; @@ -822,7 +872,7 @@ public function doSaveAndClose($data, $form) * @param string $dir prev|next * @param array $data The form data * @param Form|null $form - * @return void + * @return HTTPResponse */ protected function doSaveAndAdjacent(string $dir, array $data, ?Form $form) { @@ -837,6 +887,10 @@ protected function doSaveAndAdjacent(string $dir, array $data, ?Form $form) throw new Exception("Could not get class"); } + if (!in_array($dir, ['prev', 'next'])) { + throw new Exception("Invalid dir $dir"); + } + $method = match ($dir) { 'prev' => 'getCustomPreviousRecordID', 'next' => 'getCustomNextRecordID', diff --git a/src/CustomButton.php b/src/CustomButton.php index d79bf61..9bc31d8 100644 --- a/src/CustomButton.php +++ b/src/CustomButton.php @@ -15,7 +15,8 @@ trait CustomButton * @var array */ private static $default_classes = [ - 'btn', 'btn-info' + 'btn', + 'btn-info' ]; /** @@ -56,7 +57,7 @@ public function getTitle() /** * Set the value of title * - * @param string $is + * @param string $title * @return $this */ public function setTitle($title) @@ -206,6 +207,7 @@ public function renderLastIcon() /** * Get the value of confirmation + * @return bool|string */ public function getConfirmation() { @@ -215,7 +217,7 @@ public function getConfirmation() /** * Set the value of confirmation * - * @param string|bool A confirm message or true for a generic message + * @param string|bool $confirmation A confirm message or true for a generic message * @return $this */ public function setConfirmation($confirmation) diff --git a/src/DefaultLink.php b/src/DefaultLink.php index 6066eea..de66717 100644 --- a/src/DefaultLink.php +++ b/src/DefaultLink.php @@ -93,6 +93,7 @@ public function getControllerLink($action, array $params = null) /** * Get the value of link + * @return string */ public function getLink() { @@ -102,6 +103,7 @@ public function getLink() /** * Set the value of link * + * @param string $link * @return $this */ public function setLink($link) @@ -113,6 +115,7 @@ public function setLink($link) /** * Get the value of newWindow + * @return bool */ public function getNewWindow() { @@ -122,6 +125,7 @@ public function getNewWindow() /** * Set the value of newWindow * + * @param bool $newWindow * @return $this */ public function setNewWindow($newWindow) diff --git a/src/GridFieldSaveAllButton.php b/src/GridFieldSaveAllButton.php index 9b6a6ae..df32b80 100644 --- a/src/GridFieldSaveAllButton.php +++ b/src/GridFieldSaveAllButton.php @@ -5,7 +5,10 @@ use SilverStripe\Control\Controller; use SilverStripe\Control\Director; use SilverStripe\Forms\GridField\GridField; +use SilverStripe\ORM\DataList; use SilverStripe\ORM\DataObject; +use Exception; +use SilverStripe\Control\HTTPResponse; /** * When using inline editing on a ModelAdmin, there is no save button @@ -25,12 +28,23 @@ class GridFieldSaveAllButton extends GridFieldTableButton protected $allowEmptyResponse = true; protected bool $shouldReload = false; + /** + * @param string $targetFragment + * @param mixed $buttonLabel + */ public function __construct($targetFragment = 'buttons-before-left', $buttonLabel = null) { parent::__construct($targetFragment, $buttonLabel); $this->buttonLabel = $buttonLabel ?? _t('GridFieldSaveAllButton.SaveAll', 'Save all'); } + /** + * @param GridField $gridField + * @param Controller $controller + * @param array $arguments + * @param array $data + * @return ?HTTPResponse + */ public function handle(GridField $gridField, Controller $controller, $arguments = [], $data = []) { $fieldName = $gridField->getName(); @@ -40,9 +54,12 @@ public function handle(GridField $gridField, Controller $controller, $arguments // Without this, handleSave does not work $gridField->setSubmittedValue($data[$fieldName]); + if (!($list instanceof DataList)) { + throw new Exception("Requires a DataList"); + } + $updatedData = $data[$fieldName]['GridFieldEditableColumns'] ?? []; foreach ($updatedData as $id => $values) { - /** @var DataObject $record */ $record = $list->byID($id); if (!$record) { continue; @@ -61,17 +78,17 @@ public function handle(GridField $gridField, Controller $controller, $arguments } $newData = $data[$fieldName]['GridFieldAddNewInlineButton'] ?? []; foreach ($newData as $idx => $values) { + $record = new $model; if ($this->useHandleSave) { /** @var \Symbiote\GridFieldExtensions\GridFieldAddNewInlineButton $component */ $component = $gridField->getConfig()->getComponentByType(\Symbiote\GridFieldExtensions\GridFieldAddNewInlineButton::class); $component->handleSave($gridField, $record); } else { - $record = new $model; foreach ($values as $k => $v) { $record->$k = $v; } - $record->write(); } + $record->write(); } $response = $controller->getResponse(); diff --git a/src/ProgressiveAction.php b/src/ProgressiveAction.php index 55ef36c..036eda5 100644 --- a/src/ProgressiveAction.php +++ b/src/ProgressiveAction.php @@ -4,6 +4,9 @@ trait ProgressiveAction { + /** + * @var bool + */ protected $progressive = false; /**