From 407a4e7fd24e90f2dc37bb358ad4eb4829d83210 Mon Sep 17 00:00:00 2001 From: Susanne Moog <look@susi.dev> Date: Tue, 27 Dec 2022 09:39:58 +0100 Subject: [PATCH] [FEATURE] Add event after record published in workspaces A new PSR-14 event has been added to allow extension developers to react on record publishing in workspaces. The event does not allow any modifications, but provides context related information, such as the table name, the current workspace and the record uid. Resolves: #99430 Releases: main Change-Id: I56a75c86b26d7af169c2531f93d0c0a2f4f1ee02 Reviewed-on: https://review.typo3.org/c/Packages/TYPO3.CMS/+/77210 Tested-by: Christian Kuhn <lolli@schwarzbu.ch> Reviewed-by: Christian Kuhn <lolli@schwarzbu.ch> Reviewed-by: Oliver Bartsch <bo@cedev.de> Tested-by: Oliver Bartsch <bo@cedev.de> Tested-by: core-ci <typo3@b13.com> --- ...EventAfterRecordPublishingInWorkspaces.rst | 58 +++++++++++++++++++ .../Event/AfterRecordPublishedEvent.php | 46 +++++++++++++++ .../Classes/Hook/DataHandlerHook.php | 8 +++ .../workspaces/Configuration/Services.yaml | 3 + .../Functional/Hook/DataHandlerHookTest.php | 38 ++++++++++++ .../Event/AfterRecordPublishedEventTest.php | 40 +++++++++++++ 6 files changed, 193 insertions(+) create mode 100644 typo3/sysext/core/Documentation/Changelog/12.2/Feature-99430-AddEventAfterRecordPublishingInWorkspaces.rst create mode 100644 typo3/sysext/workspaces/Classes/Event/AfterRecordPublishedEvent.php create mode 100644 typo3/sysext/workspaces/Tests/Unit/Event/AfterRecordPublishedEventTest.php diff --git a/typo3/sysext/core/Documentation/Changelog/12.2/Feature-99430-AddEventAfterRecordPublishingInWorkspaces.rst b/typo3/sysext/core/Documentation/Changelog/12.2/Feature-99430-AddEventAfterRecordPublishingInWorkspaces.rst new file mode 100644 index 000000000000..8c4e058e52d1 --- /dev/null +++ b/typo3/sysext/core/Documentation/Changelog/12.2/Feature-99430-AddEventAfterRecordPublishingInWorkspaces.rst @@ -0,0 +1,58 @@ +.. include:: /Includes.rst.txt + +.. _feature-99430-1672129914: + +================================================================= +Feature: #99430 - Add event after record publishing in workspaces +================================================================= + +See :issue:`99430` + +Description +=========== + +A new PSR-14 event :php:`\TYPO3\CMS\Workspaces\Event\AfterRecordPublishedEvent` +has been added to allow extension developers to react on record publishing +in workspaces. + +The new event is fired after a record has been published in a workspace and +provides the following information: + +- :php:`getTable()`: The records' table name +- :php:`getRecordId()`: The records' uid +- :php:`getWorkspaceId()`: The workspace the record has been published in + +Example +======= + +Registration of the :php:`AfterRecordPublishedEvent` in your extensions' +:file:`Services.yaml`: + +.. code-block:: yaml + + MyVendor\MyPackage\Workspaces\MyEventListener: + tags: + - name: event.listener + identifier: 'my-package/after-record-published' + +The corresponding event listener class: + +.. code-block:: php + + use TYPO3\CMS\Workspaces\Event\AfterRecordPublishedEvent; + + class MyEventListener { + + public function __invoke(AfterRecordPublishedEvent $event): void + { + // Do your magic here + } + } + +Impact +====== + +With the new PSR-14 :php:`AfterRecordPublishedEvent` it is possible to +execute custom functionality after a record has been published in a workspace. + +.. index:: PHP-API, ext:workspaces diff --git a/typo3/sysext/workspaces/Classes/Event/AfterRecordPublishedEvent.php b/typo3/sysext/workspaces/Classes/Event/AfterRecordPublishedEvent.php new file mode 100644 index 000000000000..684b3a78ab54 --- /dev/null +++ b/typo3/sysext/workspaces/Classes/Event/AfterRecordPublishedEvent.php @@ -0,0 +1,46 @@ +<?php + +declare(strict_types=1); + +/* + * This file is part of the TYPO3 CMS project. + * + * It is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License, either version 2 + * of the License, or any later version. + * + * For the full copyright and license information, please read the + * LICENSE.txt file that was distributed with this source code. + * + * The TYPO3 project - inspiring people to share! + */ + +namespace TYPO3\CMS\Workspaces\Event; + +/** + * Event that is fired after a record has been published ina workspace. + */ +final class AfterRecordPublishedEvent +{ + public function __construct( + private readonly string $table, + private readonly int $recordId, + private readonly int $workspaceId, + ) { + } + + public function getTable(): string + { + return $this->table; + } + + public function getRecordId(): int + { + return $this->recordId; + } + + public function getWorkspaceId(): int + { + return $this->workspaceId; + } +} diff --git a/typo3/sysext/workspaces/Classes/Hook/DataHandlerHook.php b/typo3/sysext/workspaces/Classes/Hook/DataHandlerHook.php index e9050c14cf7e..9841f5b06a38 100644 --- a/typo3/sysext/workspaces/Classes/Hook/DataHandlerHook.php +++ b/typo3/sysext/workspaces/Classes/Hook/DataHandlerHook.php @@ -16,6 +16,7 @@ namespace TYPO3\CMS\Workspaces\Hook; use Doctrine\DBAL\Exception as DBALException; +use Psr\EventDispatcher\EventDispatcherInterface; use TYPO3\CMS\Backend\Utility\BackendUtility; use TYPO3\CMS\Core\Authentication\BackendUserAuthentication; use TYPO3\CMS\Core\Cache\CacheManager; @@ -34,6 +35,7 @@ use TYPO3\CMS\Core\Utility\ArrayUtility; use TYPO3\CMS\Core\Utility\GeneralUtility; use TYPO3\CMS\Core\Versioning\VersionState; use TYPO3\CMS\Workspaces\DataHandler\CommandMap; +use TYPO3\CMS\Workspaces\Event\AfterRecordPublishedEvent; use TYPO3\CMS\Workspaces\Notification\StageChangeNotification; use TYPO3\CMS\Workspaces\Service\StagesService; use TYPO3\CMS\Workspaces\Service\WorkspaceService; @@ -45,6 +47,10 @@ use TYPO3\CMS\Workspaces\Service\WorkspaceService; */ class DataHandlerHook { + public function __construct(private readonly EventDispatcherInterface $eventDispatcher) + { + } + /** * For accumulating information about workspace stages raised * on elements so a single mail is sent as notification. @@ -709,6 +715,7 @@ class DataHandlerHook $dataHandler->deleteEl($table, $id, true); $dataHandler->BE_USER->workspace = $currentUserWorkspace; } + $this->eventDispatcher->dispatch(new AfterRecordPublishedEvent($table, $id, $workspaceId)); $dataHandler->log($table, $id, DatabaseAction::PUBLISH, 0, SystemLogErrorClassification::MESSAGE, 'Publishing successful for table "{table}" uid {liveId}=>{versionId}', -1, ['table' => $table, 'versionId' => $swapWith, 'liveId' => $id], $dataHandler->eventPid($table, $id, $swapVersion['pid'])); // Set log entry for live record: @@ -945,6 +952,7 @@ class DataHandlerHook if ($dataHandler->enableLogging) { $dataHandler->log($table, $id, DatabaseAction::PUBLISH, 0, SystemLogErrorClassification::MESSAGE, 'Publishing successful for table "{table}" uid {uid} (new record)', -1, ['table' => $table, 'uid' => $id], $dataHandler->eventPid($table, $id, $newRecordInWorkspace['pid'])); } + $this->eventDispatcher->dispatch(new AfterRecordPublishedEvent($table, $id, $workspaceId)); // Set log entry for record $propArr = $dataHandler->getRecordPropertiesFromRow($table, $newRecordInWorkspace); diff --git a/typo3/sysext/workspaces/Configuration/Services.yaml b/typo3/sysext/workspaces/Configuration/Services.yaml index adeaa923f670..1b704351ee7a 100644 --- a/typo3/sysext/workspaces/Configuration/Services.yaml +++ b/typo3/sysext/workspaces/Configuration/Services.yaml @@ -40,6 +40,9 @@ services: TYPO3\CMS\Workspaces\Controller\Remote\ActionHandler: public: true + TYPO3\CMS\Workspaces\Hook\DataHandlerHook: + public: true + TYPO3\CMS\Workspaces\Hook\BackendUtilityHook: tags: - name: event.listener diff --git a/typo3/sysext/workspaces/Tests/Functional/Hook/DataHandlerHookTest.php b/typo3/sysext/workspaces/Tests/Functional/Hook/DataHandlerHookTest.php index 280185610718..a9b29f2ca4dc 100644 --- a/typo3/sysext/workspaces/Tests/Functional/Hook/DataHandlerHookTest.php +++ b/typo3/sysext/workspaces/Tests/Functional/Hook/DataHandlerHookTest.php @@ -17,11 +17,14 @@ declare(strict_types=1); namespace TYPO3\CMS\Workspaces\Tests\Functional\Hook; +use Symfony\Component\DependencyInjection\Container; use TYPO3\CMS\Core\Authentication\BackendUserAuthentication; use TYPO3\CMS\Core\Context\Context; use TYPO3\CMS\Core\Context\WorkspaceAspect; use TYPO3\CMS\Core\Core\Bootstrap; +use TYPO3\CMS\Core\EventDispatcher\ListenerProvider; use TYPO3\CMS\Core\Utility\GeneralUtility; +use TYPO3\CMS\Workspaces\Event\AfterRecordPublishedEvent; use TYPO3\TestingFramework\Core\Functional\Framework\DataHandling\ActionService; use TYPO3\TestingFramework\Core\Functional\FunctionalTestCase; @@ -84,4 +87,39 @@ class DataHandlerHookTest extends FunctionalTestCase $this->assertCSVDataSet(__DIR__ . '/DataSet/deletingSysWorkspaceDeletesWorkspaceRecordsResult.csv'); } + + /** + * @test + */ + public function flushByTagEventIsTriggered(): void + { + $afterRecordPublishedEvent = null; + + /** @var Container $container */ + $container = $this->getContainer(); + $container->set( + 'after-record-published-event', + static function (AfterRecordPublishedEvent $event) use (&$afterRecordPublishedEvent) { + $afterRecordPublishedEvent = $event; + } + ); + + $eventListener = $container->get(ListenerProvider::class); + $eventListener->addListener(AfterRecordPublishedEvent::class, 'after-record-published-event'); + + $this->importCSVDataSet(__DIR__ . '/DataSet/deletingSysWorkspaceDeletesWorkspaceRecords.csv'); + + $workspaceId = 1; + $tableName = 'tt_content'; + $recordId = 301; + + $this->setWorkspaceId($workspaceId); + $this->actionService->modifyRecord($tableName, $recordId, ['header' => '[Translate to Dansk:] Regular Element #1 Changed']); + $this->actionService->publishRecord($tableName, $recordId); + + self::assertInstanceOf(AfterRecordPublishedEvent::class, $afterRecordPublishedEvent); + self::assertEquals($tableName, $afterRecordPublishedEvent->getTable()); + self::assertEquals($recordId, $afterRecordPublishedEvent->getRecordId()); + self::assertEquals($workspaceId, $afterRecordPublishedEvent->getWorkspaceId()); + } } diff --git a/typo3/sysext/workspaces/Tests/Unit/Event/AfterRecordPublishedEventTest.php b/typo3/sysext/workspaces/Tests/Unit/Event/AfterRecordPublishedEventTest.php new file mode 100644 index 000000000000..b46cfbd29920 --- /dev/null +++ b/typo3/sysext/workspaces/Tests/Unit/Event/AfterRecordPublishedEventTest.php @@ -0,0 +1,40 @@ +<?php + +declare(strict_types=1); + +/* + * This file is part of the TYPO3 CMS project. + * + * It is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License, either version 2 + * of the License, or any later version. + * + * For the full copyright and license information, please read the + * LICENSE.txt file that was distributed with this source code. + * + * The TYPO3 project - inspiring people to share! + */ + +namespace TYPO3\CMS\Workspaces\Tests\Unit\Event; + +use TYPO3\CMS\Workspaces\Event\AfterRecordPublishedEvent; +use TYPO3\TestingFramework\Core\Unit\UnitTestCase; + +class AfterRecordPublishedEventTest extends UnitTestCase +{ + /** + * @test + */ + public function gettersReturnInitializedObjects(): void + { + $table = 'some_table'; + $recordId = 2004; + $workspaceId = 13; + + $event = new AfterRecordPublishedEvent($table, $recordId, $workspaceId); + + self::assertEquals($table, $event->getTable()); + self::assertEquals($recordId, $event->getRecordId()); + self::assertEquals($workspaceId, $event->getWorkspaceId()); + } +} -- GitLab