From e5ebb63e7d07e812a1b8a1ddf50109af7790a3ec Mon Sep 17 00:00:00 2001 From: Daniel Gohlke Date: Tue, 22 Oct 2024 17:11:43 +0200 Subject: [PATCH 1/3] [FEATURE] Add events to add buttons to backend module Relates: #588 --- .../Backend/Order/OrderController.php | 112 +++---------- .../Components/ModifyButtonBarEvent.php | 57 +++++++ .../Template/Components/ModifyButtonBar.php | 150 ++++++++++++++++++ Configuration/Services.yaml | 6 + 4 files changed, 235 insertions(+), 90 deletions(-) create mode 100644 Classes/Event/Template/Components/ModifyButtonBarEvent.php create mode 100644 Classes/EventListener/Template/Components/ModifyButtonBar.php diff --git a/Classes/Controller/Backend/Order/OrderController.php b/Classes/Controller/Backend/Order/OrderController.php index 358f7657..9bb2badf 100644 --- a/Classes/Controller/Backend/Order/OrderController.php +++ b/Classes/Controller/Backend/Order/OrderController.php @@ -16,6 +16,7 @@ use Extcode\Cart\Domain\Model\Order\Item; use Extcode\Cart\Domain\Repository\Order\ItemRepository; use Extcode\Cart\Event\Order\NumberGeneratorEvent; +use Extcode\Cart\Event\Template\Components\ModifyButtonBarEvent; use Psr\Http\Message\ResponseInterface; use TYPO3\CMS\Backend\Template\Components\ButtonBar; use TYPO3\CMS\Backend\Template\ModuleTemplate; @@ -61,7 +62,7 @@ public function listAction(int $currentPage = 1): ResponseInterface { $this->moduleTemplate = $this->moduleTemplateFactory->create($this->request); - $this->setDocHeader($this->getListButtons()); + $this->setDocHeader($this->getListActionButtons()); $this->addBackendAssets(); $this->moduleTemplate->assign('settings', $this->settings); @@ -119,8 +120,7 @@ public function exportAction(): ResponseInterface public function showAction(Item $orderItem): ResponseInterface { $this->moduleTemplate = $this->moduleTemplateFactory->create($this->request); - $buttons = $this->getOrderButtons($orderItem); - $this->setDocHeader($buttons); + $this->setDocHeader($this->getShowActionButtons($orderItem)); $this->addBackendAssets(); @@ -257,99 +257,31 @@ protected function getLanguageService(): LanguageService return $GLOBALS['LANG']; } - private function getOrderButtons(Item $orderItem): array + private function getShowActionButtons(Item $orderItem): array { - $buttons = [ - [ - 'link' => $this->uriBuilder->reset()->setRequest($this->request) - ->uriFor( - 'list' - ), - 'title' => 'tx_cart.controller.order.action.close', - 'icon' => 'actions-close', - 'group' => 1, - 'showLabel' => true, - ], - ]; - - $buttons = array_merge($buttons, $this->getDocumentButtons($orderItem, 'order', 2)); - $buttons = array_merge($buttons, $this->getDocumentButtons($orderItem, 'invoice', 3)); - $buttons = array_merge($buttons, $this->getDocumentButtons($orderItem, 'delivery', 4)); - - return $buttons; - } - - private function getDocumentButtons(Item $orderItem, string $type, int $groupId): array - { - $buttons = []; - - $numberGetter = 'get' . ucfirst($type) . 'Number'; - $documentGetter = 'get' . ucfirst($type) . 'Pdfs'; - - $numberExists = $orderItem->$numberGetter(); - $documentExists = $orderItem->$documentGetter()->current(); - - if (!$numberExists) { - $buttons[] = [ - 'link' => $this->uriBuilder->reset()->setRequest($this->request) - ->uriFor( - 'generateNumber', - ['orderItem' => $orderItem, 'numberType' => $type] - ), - 'title' => 'tx_cart.controller.order.action.generate' . ucfirst($type) . 'Number', - 'icon' => 'actions-duplicates', - 'group' => $groupId, - 'showLabel' => true, - ]; - } - - if ($numberExists && ExtensionManagementUtility::isLoaded('cart_pdf')) { - $buttons[] = [ - 'link' => $this->uriBuilder->reset()->setRequest($this->request) - ->uriFor( - 'create', - ['orderItem' => $orderItem, 'pdfType' => $type], - 'Backend\Order\Document' - ), - 'title' => 'tx_cart.controller.order.action.generate' . ucfirst($type) . 'Document', - 'icon' => 'actions-file-pdf', - 'group' => $groupId, - 'showLabel' => true, - ]; - } + $showButtonEvent = new ModifyButtonBarEvent( + $this->request, + $this->settings, + $this->searchArguments, + $orderItem + ); - if ($documentExists) { - $buttons[] = [ - 'link' => $this->uriBuilder->reset()->setRequest($this->request) - ->uriFor( - 'download', - ['orderItem' => $orderItem, 'pdfType' => $type], - 'Backend\Order\Document' - ), - 'title' => 'tx_cart.controller.order.action.download' . ucfirst($type) . 'Document', - 'icon' => 'actions-file-t3d-download', - 'group' => $groupId, - 'showLabel' => true, - ]; - } + $this->eventDispatcher->dispatch($showButtonEvent); - return $buttons; + return $showButtonEvent->getButtons(); } - private function getListButtons(): array + private function getListActionButtons(): array { - return [ - [ - 'link' => $this->uriBuilder->reset()->setRequest($this->request) - ->setArguments(['searchArguments' => $this->searchArguments]) - ->setFormat('csv') - ->uriFor('export'), - 'title' => 'tx_cart.controller.order.action.export.csv', - 'icon' => 'actions-file-csv-download', - 'group' => 1, - 'showLabel' => true, - ], - ]; + $listButtonEvent = new ModifyButtonBarEvent( + $this->request, + $this->settings, + $this->searchArguments + ); + + $this->eventDispatcher->dispatch($listButtonEvent); + + return $listButtonEvent->getButtons(); } private function addBackendAssets(): void diff --git a/Classes/Event/Template/Components/ModifyButtonBarEvent.php b/Classes/Event/Template/Components/ModifyButtonBarEvent.php new file mode 100644 index 00000000..f024b383 --- /dev/null +++ b/Classes/Event/Template/Components/ModifyButtonBarEvent.php @@ -0,0 +1,57 @@ +request; + } + + public function getSettings(): array + { + return $this->settings; + } + + public function getSearchArguments(): array + { + return $this->searchArguments; + } + + public function getOrderItem(): ?Item + { + return $this->orderItem; + } + + public function getButtons(): array + { + return $this->buttons; + } + + public function setButtons(array $buttons): void + { + $this->buttons = $buttons; + } +} diff --git a/Classes/EventListener/Template/Components/ModifyButtonBar.php b/Classes/EventListener/Template/Components/ModifyButtonBar.php new file mode 100644 index 00000000..ed6b3dad --- /dev/null +++ b/Classes/EventListener/Template/Components/ModifyButtonBar.php @@ -0,0 +1,150 @@ +getRequest(); + + if ($request->getControllerName() !== 'Backend\Order\Order') { + return; + } + + if ($request->getControllerActionName() === 'list') { + $this->modifyListActionButtons($event); + return; + } + + if ($request->getControllerActionName() === 'show') { + $this->modifyShowActionButtons($event); + return; + } + } + + private function modifyListActionButtons(ModifyButtonBarEvent $event) + { + $event->setButtons( + array_merge( + $event->getButtons(), + [ 'action-export-csv' => [ + 'link' => $this->uriBuilder->reset()->setRequest($event->getRequest()) + ->setArguments(['searchArguments' => $event->getSearchArguments()]) + ->setFormat('csv') + ->uriFor('export'), + 'title' => 'tx_cart.controller.order.action.export.csv', + 'icon' => 'actions-file-csv-download', + 'group' => 1, + 'showLabel' => true, + ], + ] + ) + ); + } + + private function modifyShowActionButtons(ModifyButtonBarEvent $event) + { + $event->setButtons( + array_merge( + $event->getButtons(), + [ 'action-close' => [ + 'link' => $this->uriBuilder->reset()->setRequest($event->getRequest()) + ->uriFor( + 'list' + ), + 'title' => 'tx_cart.controller.order.action.close', + 'icon' => 'actions-close', + 'group' => 1, + 'showLabel' => true, + ], + ] + ) + ); + + $event->setButtons( + array_merge( + $event->getButtons(), + $this->getDocumentButtons($event, 'order', 2) + ) + ); + $event->setButtons( + array_merge( + $event->getButtons(), + $this->getDocumentButtons($event, 'invoice', 3) + ) + ); + $event->setButtons( + array_merge( + $event->getButtons(), + $this->getDocumentButtons($event, 'delivery', 4) + ) + ); + } + + private function getDocumentButtons(ModifyButtonBarEvent $event, string $type, int $groupId): array + { + $buttons = []; + + $numberGetter = 'get' . ucfirst($type) . 'Number'; + $documentGetter = 'get' . ucfirst($type) . 'Pdfs'; + + $numberExists = $event->getOrderItem()->$numberGetter(); + $documentExists = $event->getOrderItem()->$documentGetter()->current(); + + if (!$numberExists) { + $buttons['action-generate-' . $type . '-number'] = [ + 'link' => $this->uriBuilder->reset()->setRequest($event->getRequest()) + ->uriFor( + 'generateNumber', + ['orderItem' => $event->getOrderItem(), 'numberType' => $type] + ), + 'title' => 'tx_cart.controller.order.action.generate' . ucfirst($type) . 'Number', + 'icon' => 'actions-duplicates', + 'group' => $groupId, + 'showLabel' => true, + ]; + } + + // ToDo: this could be moved to an EventListener to extcode/cart-pdf + if ($numberExists && ExtensionManagementUtility::isLoaded('cart_pdf')) { + $buttons['action-create-' . $type . '-pdf'] = [ + 'link' => $this->uriBuilder->reset()->setRequest($event->getRequest()) + ->uriFor( + 'create', + ['orderItem' => $event->getOrderItem(), 'pdfType' => $type], + 'Backend\Order\Document' + ), + 'title' => 'tx_cart.controller.order.action.generate' . ucfirst($type) . 'Document', + 'icon' => 'actions-file-pdf', + 'group' => $groupId, + 'showLabel' => true, + ]; + } + + if ($documentExists) { + $buttons['action-download-' . $type . '-pdf'] = [ + 'link' => $this->uriBuilder->reset()->setRequest($event->getRequest()) + ->uriFor( + 'download', + ['orderItem' => $event->getOrderItem(), 'pdfType' => $type], + 'Backend\Order\Document' + ), + 'title' => 'tx_cart.controller.order.action.download' . ucfirst($type) . 'Document', + 'icon' => 'actions-file-t3d-download', + 'group' => $groupId, + 'showLabel' => true, + ]; + } + + return $buttons; + } +} diff --git a/Configuration/Services.yaml b/Configuration/Services.yaml index 62f23f5b..6f9a6ec2 100644 --- a/Configuration/Services.yaml +++ b/Configuration/Services.yaml @@ -8,6 +8,12 @@ services: resource: '../Classes/*' exclude: '../Classes/Widgets/*' + Extcode\Cart\EventListener\Template\Components\ModifyButtonBar: + tags: + - name: event.listener + identifier: 'cart--cart--template--components--modify-button-bar' + event: Extcode\Cart\Event\Template\Components\ModifyButtonBarEvent + Extcode\Cart\EventListener\Cart\UpdateCountry: tags: - name: event.listener From bb7005a16df7219f6a3d8fd27b3b794e76c81454 Mon Sep 17 00:00:00 2001 From: Daniel Gohlke Date: Wed, 23 Oct 2024 08:54:58 +0200 Subject: [PATCH 2/3] [TASK] Reduce get*ButtonButtons to one method Related: #588 --- .../Backend/Order/OrderController.php | 80 ++++++++----------- 1 file changed, 33 insertions(+), 47 deletions(-) diff --git a/Classes/Controller/Backend/Order/OrderController.php b/Classes/Controller/Backend/Order/OrderController.php index 9bb2badf..7d82f3e4 100644 --- a/Classes/Controller/Backend/Order/OrderController.php +++ b/Classes/Controller/Backend/Order/OrderController.php @@ -62,7 +62,7 @@ public function listAction(int $currentPage = 1): ResponseInterface { $this->moduleTemplate = $this->moduleTemplateFactory->create($this->request); - $this->setDocHeader($this->getListActionButtons()); + $this->setDocHeader($this->dispatchModifyButtonBarEvent()); $this->addBackendAssets(); $this->moduleTemplate->assign('settings', $this->settings); @@ -95,32 +95,11 @@ public function listAction(int $currentPage = 1): ResponseInterface return $this->moduleTemplate->renderResponse('List'); } - public function exportAction(): ResponseInterface - { - $format = $this->request->getFormat(); - $orderItems = $this->itemRepository->findAll($this->searchArguments); - - $this->view->assign('searchArguments', $this->searchArguments); - $this->view->assign('orderItems', $orderItems); - - $pdfRendererInstalled = ExtensionManagementUtility::isLoaded('cart_pdf'); - $this->view->assign('pdfRendererInstalled', $pdfRendererInstalled); - - $title = 'Order-Export-' . date('Y-m-d_H-i'); - $filename = $title . '.' . $format; - - return $this->responseFactory->createResponse() - ->withAddedHeader('Content-Type', 'text/' . $format) - ->withAddedHeader('Content-Description', 'File transfer') - ->withAddedHeader('Content-Disposition', 'attachment; filename="' . $filename . '"') - ->withBody($this->streamFactory->createStream($this->view->render())); - } - #[IgnoreValidation(['value' => 'orderItem'])] public function showAction(Item $orderItem): ResponseInterface { $this->moduleTemplate = $this->moduleTemplateFactory->create($this->request); - $this->setDocHeader($this->getShowActionButtons($orderItem)); + $this->setDocHeader($this->dispatchModifyButtonBarEvent($orderItem)); $this->addBackendAssets(); @@ -153,22 +132,25 @@ public function showAction(Item $orderItem): ResponseInterface return $this->moduleTemplate->renderResponse('Show'); } - private function setDocHeader(array $buttons): void + public function exportAction(): ResponseInterface { - $buttonBar = $this->moduleTemplate->getDocHeaderComponent()->getButtonBar(); + $format = $this->request->getFormat(); + $orderItems = $this->itemRepository->findAll($this->searchArguments); - foreach ($buttons as $button) { - $title = $this->getLanguageService()->sL(self::LANG_FILE . $button['title']); - $icon = $this->iconFactory->getIcon($button['icon'], Icon::SIZE_SMALL); + $this->view->assign('searchArguments', $this->searchArguments); + $this->view->assign('orderItems', $orderItems); - $viewButton = $buttonBar->makeLinkButton() - ->setHref($button['link']) - ->setTitle($title) - ->setShowLabelText($button['showLabel']) - ->setIcon($icon); - $buttonBar->addButton($viewButton, ButtonBar::BUTTON_POSITION_LEFT, $button['group']); - } + $pdfRendererInstalled = ExtensionManagementUtility::isLoaded('cart_pdf'); + $this->view->assign('pdfRendererInstalled', $pdfRendererInstalled); + $title = 'Order-Export-' . date('Y-m-d_H-i'); + $filename = $title . '.' . $format; + + return $this->responseFactory->createResponse() + ->withAddedHeader('Content-Type', 'text/' . $format) + ->withAddedHeader('Content-Description', 'File transfer') + ->withAddedHeader('Content-Disposition', 'attachment; filename="' . $filename . '"') + ->withBody($this->streamFactory->createStream($this->view->render())); } public function generateNumberAction(Item $orderItem, string $numberType): ResponseInterface @@ -257,31 +239,35 @@ protected function getLanguageService(): LanguageService return $GLOBALS['LANG']; } - private function getShowActionButtons(Item $orderItem): array + private function dispatchModifyButtonBarEvent(?Item $orderItem = null): array { - $showButtonEvent = new ModifyButtonBarEvent( + $modifyButtonBarEvent = new ModifyButtonBarEvent( $this->request, $this->settings, $this->searchArguments, $orderItem ); - $this->eventDispatcher->dispatch($showButtonEvent); + $this->eventDispatcher->dispatch($modifyButtonBarEvent); - return $showButtonEvent->getButtons(); + return $modifyButtonBarEvent->getButtons(); } - private function getListActionButtons(): array + private function setDocHeader(array $buttons): void { - $listButtonEvent = new ModifyButtonBarEvent( - $this->request, - $this->settings, - $this->searchArguments - ); + $buttonBar = $this->moduleTemplate->getDocHeaderComponent()->getButtonBar(); - $this->eventDispatcher->dispatch($listButtonEvent); + foreach ($buttons as $button) { + $title = $this->getLanguageService()->sL(self::LANG_FILE . $button['title']); + $icon = $this->iconFactory->getIcon($button['icon'], Icon::SIZE_SMALL); - return $listButtonEvent->getButtons(); + $viewButton = $buttonBar->makeLinkButton() + ->setHref($button['link']) + ->setTitle($title) + ->setShowLabelText($button['showLabel']) + ->setIcon($icon); + $buttonBar->addButton($viewButton, ButtonBar::BUTTON_POSITION_LEFT, $button['group']); + } } private function addBackendAssets(): void From ee551687bf99ebc42de9b91db9502a7c3991c536 Mon Sep 17 00:00:00 2001 From: Daniel Gohlke Date: Wed, 23 Oct 2024 12:52:23 +0200 Subject: [PATCH 3/3] [TASK] Add documentation for the new event Relates: #588 --- ...AddEventToModifyButtonsInBackendModule.rst | 34 +++++++++++++++++++ Documentation/Changelog/9.1/Index.rst | 20 +++++++++++ Documentation/Changelog/Index.rst | 3 +- Documentation/Developer/Events/Index.rst | 8 +++++ 4 files changed, 64 insertions(+), 1 deletion(-) create mode 100644 Documentation/Changelog/9.1/Feature-588-AddEventToModifyButtonsInBackendModule.rst create mode 100644 Documentation/Changelog/9.1/Index.rst diff --git a/Documentation/Changelog/9.1/Feature-588-AddEventToModifyButtonsInBackendModule.rst b/Documentation/Changelog/9.1/Feature-588-AddEventToModifyButtonsInBackendModule.rst new file mode 100644 index 00000000..49e99bfc --- /dev/null +++ b/Documentation/Changelog/9.1/Feature-588-AddEventToModifyButtonsInBackendModule.rst @@ -0,0 +1,34 @@ +.. include:: ../../Includes.rst.txt + +============================================================= +Feature: #588 - Add event to modify buttons in backend module +============================================================= + +See `Issue 588 `__ + +Description +=========== + +Adding your own buttons to the backend module is not so easy in controllers. In +order to extend or replace the CSV export with an XML export, you need a way to +insert your own buttons if you do not want to develop your own backend module. + +The OrderController for the administration in the backend has been extended by +the `\Extcode\Cart\Event\Template\Components\ModifyButtonBarEvent`. The buttons +in the OrderController have been moved to the +`\Extcode\Cart\EventListener\Template\Components\ModifyButtonBar` EventListener, + which uses this event to decide which buttons should be displayed in which + action based on the request. + +Custom buttons can use the methods `getRequest()`, `getSettings()`, +`getSearchArguments()` and in the case of the `showAction` also `getOrderItem()` +to retrieve all the necessary information to insert custom buttons for custom +tasks. + +Impact +====== + +No impact is expected as only private methods have changed. + + +.. index:: Backend diff --git a/Documentation/Changelog/9.1/Index.rst b/Documentation/Changelog/9.1/Index.rst new file mode 100644 index 00000000..cc6116b1 --- /dev/null +++ b/Documentation/Changelog/9.1/Index.rst @@ -0,0 +1,20 @@ +.. include:: ../../Includes.rst.txt + +9.1 Changes +=========== + +**Table of contents** + +.. contents:: + :local: + :depth: 1 + +Features +-------- + +.. toctree:: + :maxdepth: 1 + :titlesonly: + :glob: + + Feature-* diff --git a/Documentation/Changelog/Index.rst b/Documentation/Changelog/Index.rst index 3db9d020..256f5ffe 100644 --- a/Documentation/Changelog/Index.rst +++ b/Documentation/Changelog/Index.rst @@ -1,5 +1,5 @@ .. include:: ../Includes.rst.txt - + .. _changelog: ========= @@ -10,6 +10,7 @@ ChangeLog :maxdepth: 5 :titlesonly: + 9.1/Index 9.0/Index 8.5/Index 8.4/Index diff --git a/Documentation/Developer/Events/Index.rst b/Documentation/Developer/Events/Index.rst index fb635336..9852ddc2 100644 --- a/Documentation/Developer/Events/Index.rst +++ b/Documentation/Developer/Events/Index.rst @@ -10,6 +10,14 @@ integrate custom requirements in the ordering process. You can register your own EventListener for the following events: +.. confval:: \Extcode\Cart\Event\Template\Components\ModifyButtonBarEvent + + This event is triggered in the `listAction` and `showAction` of the backend + module `OrderController`. + + The event allows to add own buttons or change existing buttons in the + DocHeader of the module template. + .. confval:: \Extcode\Cart\Event\Cart\BeforeShowCartEvent Triggered before the cart is shown.