From ea41701624d46edb8fc36f21bf3b09d5368c6973 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20B=C3=BCrk?= <stefan@buerk.tech> Date: Thu, 10 Nov 2022 13:11:07 +0100 Subject: [PATCH] [FEATURE] Add two PSR-14 events around auto create redirects With #91776 auto-created redirects have been stored with a pid of the page, which the slug has been changed. This was streamlined and changed to use the site rootPageId instead with #99044, which reverted the original use-case. This change implements two new PSR-14 events around each auto-create-redirect: * `ModifyAutoCreateRedirectRecordBeforePersistingEvent`: can be used to modify the redirect record before it is persisted * `AfterAutoCreateRedirectHasBeenPersistedEvent`: can be used to chain further task after the redirect has been persisted to the database. It's kind of a plain notification event. Resolves: #99834 Related: #99802 Related: #99044 Related: #91776 Releases: main Change-Id: I974020b148a3b5eb109624648016a79ed557af3e Reviewed-on: https://review.typo3.org/c/Packages/TYPO3.CMS/+/76539 Tested-by: core-ci <typo3@b13.com> Reviewed-by: Georg Ringer <georg.ringer@gmail.com> Reviewed-by: Sybille Peters <sypets@gmx.de> Tested-by: Georg Ringer <georg.ringer@gmail.com> Tested-by: Benni Mack <benni@typo3.org> Reviewed-by: Benni Mack <benni@typo3.org> --- ...utoCreateRedirectHasBeenPersistedEvent.rst | 74 ++++++++++ ...ateRedirectRecordBeforePersistingEvent.rst | 85 ++++++++++++ ...utoCreateRedirectHasBeenPersistedEvent.php | 54 ++++++++ ...ateRedirectRecordBeforePersistingEvent.php | 59 ++++++++ .../redirects/Classes/Service/SlugService.php | 21 ++- ...utoCreateRedirectHasBeenPersistedEvent.csv | 4 + ...ateRedirectRecordBeforePersistingEvent.csv | 4 + .../Functional/Service/SlugServiceTest.php | 126 +++++++++++++++++- ...reateRedirectHasBeenPersistedEventTest.php | 61 +++++++++ ...edirectRecordBeforePersistingEventTest.php | 97 ++++++++++++++ 10 files changed, 576 insertions(+), 9 deletions(-) create mode 100644 typo3/sysext/core/Documentation/Changelog/12.3/Feature-99834-NewPSR-14AfterAutoCreateRedirectHasBeenPersistedEvent.rst create mode 100644 typo3/sysext/core/Documentation/Changelog/12.3/Feature-99834-NewPSR-14ModifyAutoCreateRedirectRecordBeforePersistingEvent.rst create mode 100644 typo3/sysext/redirects/Classes/Event/AfterAutoCreateRedirectHasBeenPersistedEvent.php create mode 100644 typo3/sysext/redirects/Classes/Event/ModifyAutoCreateRedirectRecordBeforePersistingEvent.php create mode 100644 typo3/sysext/redirects/Tests/Functional/Service/Fixtures/SlugServiceTest_AfterAutoCreateRedirectHasBeenPersistedEvent.csv create mode 100644 typo3/sysext/redirects/Tests/Functional/Service/Fixtures/SlugServiceTest_ModifyAutoCreateRedirectRecordBeforePersistingEvent.csv create mode 100644 typo3/sysext/redirects/Tests/Unit/Event/AfterAutoCreateRedirectHasBeenPersistedEventTest.php create mode 100644 typo3/sysext/redirects/Tests/Unit/Event/ModifyAutoCreateRedirectRecordBeforePersistingEventTest.php diff --git a/typo3/sysext/core/Documentation/Changelog/12.3/Feature-99834-NewPSR-14AfterAutoCreateRedirectHasBeenPersistedEvent.rst b/typo3/sysext/core/Documentation/Changelog/12.3/Feature-99834-NewPSR-14AfterAutoCreateRedirectHasBeenPersistedEvent.rst new file mode 100644 index 000000000000..092e43ff6f34 --- /dev/null +++ b/typo3/sysext/core/Documentation/Changelog/12.3/Feature-99834-NewPSR-14AfterAutoCreateRedirectHasBeenPersistedEvent.rst @@ -0,0 +1,74 @@ +.. include:: /Includes.rst.txt + +.. _feature-99834-1675612921: + +========================================================================= +Feature: #99834 - New PSR-14 AfterAutoCreateRedirectHasBeenPersistedEvent +========================================================================= + +See :issue:`99834` + +Description +=========== + +A new PSR-14 event :php:`\TYPO3\CMS\Redirects\Event\AfterAutoCreateRedirectHasBeenPersistedEvent` +is introduced, allowing extension authors to react on persisted auto-created redirects. This +can be used to call external API or do other tasks based on the real persisted redirects. + +.. note:: + + To handle later updates or react on manual created redirects in the backend + module, available hooks of :php:`\TYPO3\CMS\Core\DataHandling\DataHandler` + can be used. + +Example: +-------- + +Registration of the event listener: + +.. code-block:: yaml + :caption: EXT:my_extension/Configuration/Services.yaml + + MyVendor\MyExtension\Backend\MyEventListener: + tags: + - name: event.listener + identifier: 'my-extension/after-auto-create-redirect-has-been-persisted' + +The corresponding event listener class: + +.. code-block:: php + :caption: EXT:my_extension/Classes/Backend/MyEventListener.php + + namespace MyVendor\MyExtension\Backend; + + use TYPO3\CMS\Redirects\Event\AfterAutoCreateRedirectHasBeenPersistedEvent; + use TYPO3\CMS\Redirects\RedirectUpdate\PlainSlugReplacementRedirectSource; + + class MyEventListener { + + public function __invoke( + AfterAutoCreateRedirectHasBeenPersistedEvent $event + ): void { + $redirectUid = $event->getRedirectRecord()['uid'] ?? null; + if ($redirectUid === null + && !($event->getSource() instanceof PlainSlugReplacementRedirectSource) + ) { + return; + } + + // Implement code what should be done with this information. E.g. + // write to another table, call a rest api or similar. Find your + // use-case. + } + } + + +Impact +====== + +With the new :php:`AfterAutoCreateRedirectHasBeenPersistedEvent`, it's now possible +to react on persisted auto-created redirects. Manually created redirects can be handled +by using one of the available :php:`\TYPO3\CMS\Core\DataHandling\DataHandler` hooks, +not suitable for auto-created redirects. + +.. index:: PHP-API, ext:redirects diff --git a/typo3/sysext/core/Documentation/Changelog/12.3/Feature-99834-NewPSR-14ModifyAutoCreateRedirectRecordBeforePersistingEvent.rst b/typo3/sysext/core/Documentation/Changelog/12.3/Feature-99834-NewPSR-14ModifyAutoCreateRedirectRecordBeforePersistingEvent.rst new file mode 100644 index 000000000000..dff7b008477c --- /dev/null +++ b/typo3/sysext/core/Documentation/Changelog/12.3/Feature-99834-NewPSR-14ModifyAutoCreateRedirectRecordBeforePersistingEvent.rst @@ -0,0 +1,85 @@ +.. include:: /Includes.rst.txt + +.. _feature-99834-1675612872: + +================================================================================ +Feature: #99834 - New PSR-14 ModifyAutoCreateRedirectRecordBeforePersistingEvent +================================================================================ + +See :issue:`99834` + +Description +=========== + +A new PSR-14 :php:`\TYPO3\CMS\Redirects\Event\ModifyAutoCreateRedirectRecordBeforePersistingEvent` +is introduced, allowing extension authors to modify the redirect record before it is persisted to +the database. This can be used to change values based on circumstances like e.g. +different sub tree settings, not covered by core site configuration. Another use-case +could be to write data to additional :sql:`sys_redirect` columns added by a custom +extension for later use. + +.. note:: + + To handle later updates or react on manually created redirects in the backend + module, available hooks of :php:`\TYPO3\CMS\Core\DataHandling\DataHandler` + can be used. + +Example: +-------- + +.. code-block:: yaml + :caption: my_extension/Configuration/Services.yaml + + MyVendor\MyExtension\Backend\MyEventListener: + tags: + - name: event.listener + identifier: 'my-extension/after-auto-create-redirect-has-been-persisted' + +The corresponding event listener class: + +.. code-block:: php + :caption: my_extension/Classes/Backend/MyEventListener.php + + namespace MyVendor\MyExtension\Backend; + + use TYPO3\CMS\Redirects\Event\ModifyAutoCreateRedirectRecordBeforePersistingEvent; + use TYPO3\CMS\Redirects\RedirectUpdate\PlainSlugReplacementRedirectSource; + + final class MyEventListener { + + public function __invoke( + ModifyAutoCreateRedirectRecordBeforePersistingEvent $event + ): void { + + // only work on plain slug replacement redirect sources. + if (!($event->getSource() instanceof PlainSlugReplacementRedirectSource)) { + return; + } + + // Get prepared redirect record and change some values + $record = $event->getRedirectRecord(); + + // override the status code, eventually to another value than + // configured in the site configuration + $record['status_code'] = 307; + + // Set value to a field extended by a custom extension, to persist + // additional data to the redirect record. + $record['custom_field_added_by_a_extension'] + = 'page_' . $event->getSlugRedirectChangeItem()->getPageUid(); + + // Update changed record in event to ensure changed values are saved. + $event->setRedirectRecord($record); + } + } + + +Impact +====== + +With the new :php:`ModifyAutoCreateRedirectRecordBeforePersistingEvent`, it's now +possible to modify the auto-create redirect record before it is persisted to the database. +Manually created redirects or updated redirects can be handled by using the well known +:php:`\TYPO3\CMS\Core\DataHandling\DataHandler` and the available hooks. + +.. index:: PHP-API, ext:redirects diff --git a/typo3/sysext/redirects/Classes/Event/AfterAutoCreateRedirectHasBeenPersistedEvent.php b/typo3/sysext/redirects/Classes/Event/AfterAutoCreateRedirectHasBeenPersistedEvent.php new file mode 100644 index 000000000000..b51cb2980a10 --- /dev/null +++ b/typo3/sysext/redirects/Classes/Event/AfterAutoCreateRedirectHasBeenPersistedEvent.php @@ -0,0 +1,54 @@ +<?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\Redirects\Event; + +use TYPO3\CMS\Redirects\RedirectUpdate\RedirectSourceInterface; +use TYPO3\CMS\Redirects\RedirectUpdate\SlugRedirectChangeItem; + +/** + * This event is fired in the \TYPO3\CMS\Redirects\Service\SlugService after + * a redirect record has been automatically created and persisted after page + * slug change. It's mainly a pure notification event. + * + * It can be used to update redirects external in a load-balancer directly for + * example, or doing some kind of synchronization. + */ +final class AfterAutoCreateRedirectHasBeenPersistedEvent +{ + public function __construct( + private readonly SlugRedirectChangeItem $slugRedirectChangeItem, + private readonly RedirectSourceInterface $source, + private readonly array $redirectRecord, + ) { + } + + public function getSlugRedirectChangeItem(): SlugRedirectChangeItem + { + return $this->slugRedirectChangeItem; + } + + public function getSource(): RedirectSourceInterface + { + return $this->source; + } + + public function getRedirectRecord(): array + { + return $this->redirectRecord; + } +} diff --git a/typo3/sysext/redirects/Classes/Event/ModifyAutoCreateRedirectRecordBeforePersistingEvent.php b/typo3/sysext/redirects/Classes/Event/ModifyAutoCreateRedirectRecordBeforePersistingEvent.php new file mode 100644 index 000000000000..b5789da9fd88 --- /dev/null +++ b/typo3/sysext/redirects/Classes/Event/ModifyAutoCreateRedirectRecordBeforePersistingEvent.php @@ -0,0 +1,59 @@ +<?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\Redirects\Event; + +use TYPO3\CMS\Redirects\RedirectUpdate\RedirectSourceInterface; +use TYPO3\CMS\Redirects\RedirectUpdate\SlugRedirectChangeItem; + +/** + * This event is fired in the \TYPO3\CMS\Redirects\Service\SlugService before + * a redirect record is persisted for changed page slug. + * + * It can be used to modify the redirect record before persisting it. This + * gives extension developers the ability to apply defaults or add custom + * values to the record. + */ +final class ModifyAutoCreateRedirectRecordBeforePersistingEvent +{ + public function __construct( + private readonly SlugRedirectChangeItem $slugRedirectChangeItem, + private readonly RedirectSourceInterface $source, + private array $redirectRecord, + ) { + } + + public function getSlugRedirectChangeItem(): SlugRedirectChangeItem + { + return $this->slugRedirectChangeItem; + } + + public function getSource(): RedirectSourceInterface + { + return $this->source; + } + + public function getRedirectRecord(): array + { + return $this->redirectRecord; + } + + public function setRedirectRecord(array $redirectRecord): void + { + $this->redirectRecord = $redirectRecord; + } +} diff --git a/typo3/sysext/redirects/Classes/Service/SlugService.php b/typo3/sysext/redirects/Classes/Service/SlugService.php index 4bc5a4796ee2..fcb41e4b968f 100644 --- a/typo3/sysext/redirects/Classes/Service/SlugService.php +++ b/typo3/sysext/redirects/Classes/Service/SlugService.php @@ -17,6 +17,7 @@ declare(strict_types=1); namespace TYPO3\CMS\Redirects\Service; +use Psr\EventDispatcher\EventDispatcherInterface; use Psr\Log\LoggerAwareInterface; use Psr\Log\LoggerAwareTrait; use TYPO3\CMS\Backend\Utility\BackendUtility; @@ -40,6 +41,8 @@ use TYPO3\CMS\Core\Site\Entity\SiteInterface; use TYPO3\CMS\Core\Site\SiteFinder; use TYPO3\CMS\Core\Utility\GeneralUtility; use TYPO3\CMS\Core\Utility\HttpUtility; +use TYPO3\CMS\Redirects\Event\AfterAutoCreateRedirectHasBeenPersistedEvent; +use TYPO3\CMS\Redirects\Event\ModifyAutoCreateRedirectRecordBeforePersistingEvent; use TYPO3\CMS\Redirects\Hooks\DataHandlerSlugUpdateHook; use TYPO3\CMS\Redirects\RedirectUpdate\SlugRedirectChangeItem; use TYPO3\CMS\Redirects\RedirectUpdate\SlugRedirectChangeItemFactory; @@ -98,6 +101,7 @@ class SlugService implements LoggerAwareInterface protected readonly LinkService $linkService, protected readonly RedirectCacheService $redirectCacheService, protected readonly SlugRedirectChangeItemFactory $slugRedirectChangeItemFactory, + protected readonly EventDispatcherInterface $eventDispatcher, ) { } @@ -187,7 +191,14 @@ class SlugService implements LoggerAwareInterface 'disable_hitcount' => 0, 'creation_type' => 0, ]; - // @todo Add a pre-create event here, which can be used to change the record before it is persisted. + + $record = $this->eventDispatcher->dispatch( + new ModifyAutoCreateRedirectRecordBeforePersistingEvent( + slugRedirectChangeItem: $changeItem, + source: $source, + redirectRecord: $record, + ) + )->getRedirectRecord(); // @todo Use dataHandler to create records $connection = GeneralUtility::makeInstance(ConnectionPool::class) ->getConnectionForTable('sys_redirect'); @@ -195,7 +206,13 @@ class SlugService implements LoggerAwareInterface $id = (int)$connection->lastInsertId('sys_redirect'); $record['uid'] = $id; $this->getRecordHistoryStore()->addRecord('sys_redirect', $id, $record, $this->correlationIdRedirectCreation); - // @todo Add a post-create event here, thus extensions can trigger stuff based on the created redirect. + $this->eventDispatcher->dispatch( + new AfterAutoCreateRedirectHasBeenPersistedEvent( + slugRedirectChangeItem: $changeItem, + source: $source, + redirectRecord: $record, + ) + ); if (!in_array($source->getHost(), $sourceHosts)) { $sourceHosts[] = $source->getHost(); } diff --git a/typo3/sysext/redirects/Tests/Functional/Service/Fixtures/SlugServiceTest_AfterAutoCreateRedirectHasBeenPersistedEvent.csv b/typo3/sysext/redirects/Tests/Functional/Service/Fixtures/SlugServiceTest_AfterAutoCreateRedirectHasBeenPersistedEvent.csv new file mode 100644 index 000000000000..61243b3cd9a8 --- /dev/null +++ b/typo3/sysext/redirects/Tests/Functional/Service/Fixtures/SlugServiceTest_AfterAutoCreateRedirectHasBeenPersistedEvent.csv @@ -0,0 +1,4 @@ +"pages",,,,,,, +,"uid","pid","title","slug","l10n_parent","l10n_source","sys_language_uid" +,1,0,"Root 1","/",0,0,0 +,2,1,"Dummy 1-2","/dummy-1-2",0,0,0 diff --git a/typo3/sysext/redirects/Tests/Functional/Service/Fixtures/SlugServiceTest_ModifyAutoCreateRedirectRecordBeforePersistingEvent.csv b/typo3/sysext/redirects/Tests/Functional/Service/Fixtures/SlugServiceTest_ModifyAutoCreateRedirectRecordBeforePersistingEvent.csv new file mode 100644 index 000000000000..61243b3cd9a8 --- /dev/null +++ b/typo3/sysext/redirects/Tests/Functional/Service/Fixtures/SlugServiceTest_ModifyAutoCreateRedirectRecordBeforePersistingEvent.csv @@ -0,0 +1,4 @@ +"pages",,,,,,, +,"uid","pid","title","slug","l10n_parent","l10n_source","sys_language_uid" +,1,0,"Root 1","/",0,0,0 +,2,1,"Dummy 1-2","/dummy-1-2",0,0,0 diff --git a/typo3/sysext/redirects/Tests/Functional/Service/SlugServiceTest.php b/typo3/sysext/redirects/Tests/Functional/Service/SlugServiceTest.php index 909d42e73edf..057a290cb422 100644 --- a/typo3/sysext/redirects/Tests/Functional/Service/SlugServiceTest.php +++ b/typo3/sysext/redirects/Tests/Functional/Service/SlugServiceTest.php @@ -17,17 +17,23 @@ declare(strict_types=1); namespace TYPO3\CMS\Redirects\Tests\Functional\Service; +use Psr\EventDispatcher\EventDispatcherInterface; use Psr\Log\NullLogger; +use Symfony\Component\DependencyInjection\Container; use TYPO3\CMS\Core\Configuration\SiteConfiguration; use TYPO3\CMS\Core\Context\Context; use TYPO3\CMS\Core\Core\Bootstrap; use TYPO3\CMS\Core\DataHandling\Model\CorrelationId; use TYPO3\CMS\Core\Domain\Repository\PageRepository; +use TYPO3\CMS\Core\EventDispatcher\ListenerProvider; use TYPO3\CMS\Core\LinkHandling\LinkService; use TYPO3\CMS\Core\Routing\SiteMatcher; use TYPO3\CMS\Core\Site\SiteFinder; use TYPO3\CMS\Core\Utility\GeneralUtility; use TYPO3\CMS\Core\Utility\StringUtility; +use TYPO3\CMS\Redirects\Event\AfterAutoCreateRedirectHasBeenPersistedEvent; +use TYPO3\CMS\Redirects\Event\ModifyAutoCreateRedirectRecordBeforePersistingEvent; +use TYPO3\CMS\Redirects\RedirectUpdate\SlugRedirectChangeItem; use TYPO3\CMS\Redirects\RedirectUpdate\SlugRedirectChangeItemFactory; use TYPO3\CMS\Redirects\Service\RedirectCacheService; use TYPO3\CMS\Redirects\Service\SlugService; @@ -403,6 +409,103 @@ class SlugServiceTest extends FunctionalTestCase $this->assertSlugsAndRedirectsExists($slugs, $redirects); } + /** + * @test + */ + public function modifyAutoCreateRedirectRecordBeforePersistingIsTriggered(): void + { + $newPageSlug = '/test-new'; + $eventOverrideSource = '/overridden-new'; + $this->buildBaseSiteWithLanguages(); + $this->importCSVDataSet(__DIR__ . '/Fixtures/SlugServiceTest_ModifyAutoCreateRedirectRecordBeforePersistingEvent.csv'); + + /** @var Container $container */ + $container = $this->getContainer(); + $container->set( + 'modify-auto-create-redirect-record-before-persisting', + static function (ModifyAutoCreateRedirectRecordBeforePersistingEvent $event) use ( + &$modifyAutoCreateRedirectRecordBeforePersisting, + $eventOverrideSource + ) { + $modifyAutoCreateRedirectRecordBeforePersisting = $event; + $event->setRedirectRecord( + array_replace( + $event->getRedirectRecord(), + [ + 'source_path' => $eventOverrideSource, + ], + ) + ); + } + ); + $listenerProvider = $container->get(ListenerProvider::class); + $listenerProvider->addListener(ModifyAutoCreateRedirectRecordBeforePersistingEvent::class, 'modify-auto-create-redirect-record-before-persisting'); + $this->createSubject(); + + /** @var SlugRedirectChangeItem $changeItem */ + $changeItem = $this->get(SlugRedirectChangeItemFactory::class)->create(2); + $changeItem = $changeItem->withChanged(array_merge($changeItem->getOriginal(), ['slug' => $newPageSlug])); + $this->subject->rebuildSlugsForSlugChange(2, $changeItem, $this->correlationId); + $this->setPageSlug(2, $newPageSlug); + + self::assertInstanceOf(ModifyAutoCreateRedirectRecordBeforePersistingEvent::class, $modifyAutoCreateRedirectRecordBeforePersisting); + self::assertSame($eventOverrideSource, $modifyAutoCreateRedirectRecordBeforePersisting->getRedirectRecord()['source_path']); + + $this->assertSlugsAndRedirectsExists( + slugs: [ + '/', + $newPageSlug, + ], + redirects: [ + ['source_host' => '*', 'source_path' => $eventOverrideSource, 'target' => 't3://page?uid=2&_language=0'], + ], + ); + } + + /** + * @test + */ + public function afterAutoCreteRedirectHasBeenPersistedIsTriggered(): void + { + $newPageSlug = '/test-new'; + $this->buildBaseSiteWithLanguages(); + $this->importCSVDataSet(__DIR__ . '/Fixtures/SlugServiceTest_AfterAutoCreateRedirectHasBeenPersistedEvent.csv'); + + /** @var Container $container */ + $container = $this->getContainer(); + $container->set( + 'after-auto-create-redirect-has-been-persisted', + static function (AfterAutoCreateRedirectHasBeenPersistedEvent $event) use ( + &$afterAutoCreateRedirectHasBeenPersisted + ) { + $afterAutoCreateRedirectHasBeenPersisted = $event; + } + ); + $listenerProvider = $container->get(ListenerProvider::class); + $listenerProvider->addListener(AfterAutoCreateRedirectHasBeenPersistedEvent::class, 'after-auto-create-redirect-has-been-persisted'); + $this->createSubject(); + + /** @var SlugRedirectChangeItem $changeItem */ + $changeItem = $this->get(SlugRedirectChangeItemFactory::class)->create(2); + $changeItem = $changeItem->withChanged(array_merge($changeItem->getOriginal(), ['slug' => $newPageSlug])); + $this->subject->rebuildSlugsForSlugChange(2, $changeItem, $this->correlationId); + $this->setPageSlug(2, $newPageSlug); + + self::assertInstanceOf(AfterAutoCreateRedirectHasBeenPersistedEvent::class, $afterAutoCreateRedirectHasBeenPersisted); + self::assertSame(1, $afterAutoCreateRedirectHasBeenPersisted->getRedirectRecord()['uid'] ?? null); + + $this->assertSlugsAndRedirectsExists( + slugs: [ + '/', + $newPageSlug, + ], + redirects: [ + ['uid' => 1, 'source_host' => '*', 'source_path' => '/en/dummy-1-2', 'target' => 't3://page?uid=2&_language=0'], + ], + withRedirectUid: true, + ); + } + protected function buildBaseSite(): void { $configuration = [ @@ -457,17 +560,18 @@ class SlugServiceTest extends FunctionalTestCase { GeneralUtility::makeInstance(SiteMatcher::class)->refresh(); $this->subject = new SlugService( - GeneralUtility::makeInstance(Context::class), - GeneralUtility::makeInstance(SiteFinder::class), - GeneralUtility::makeInstance(PageRepository::class), - GeneralUtility::makeInstance(LinkService::class), - GeneralUtility::makeInstance(RedirectCacheService::class), - $this->get(SlugRedirectChangeItemFactory::class), + context: GeneralUtility::makeInstance(Context::class), + siteFinder: GeneralUtility::makeInstance(SiteFinder::class), + pageRepository: GeneralUtility::makeInstance(PageRepository::class), + linkService: GeneralUtility::makeInstance(LinkService::class), + redirectCacheService: GeneralUtility::makeInstance(RedirectCacheService::class), + slugRedirectChangeItemFactory: $this->get(SlugRedirectChangeItemFactory::class), + eventDispatcher: $this->get(EventDispatcherInterface::class), ); $this->subject->setLogger(new NullLogger()); } - protected function assertSlugsAndRedirectsExists(array $slugs, array $redirects): void + protected function assertSlugsAndRedirectsExists(array $slugs, array $redirects, bool $withRedirectUid = false): void { $pageRecords = $this->getAllRecords('pages'); self::assertCount(count($slugs), $pageRecords); @@ -483,6 +587,14 @@ class SlugServiceTest extends FunctionalTestCase 'source_path' => $record['source_path'], 'target' => $record['target'], ]; + if ($withRedirectUid) { + $combination = [ + 'uid' => $record['uid'], + 'source_host' => $record['source_host'], + 'source_path' => $record['source_path'], + 'target' => $record['target'], + ]; + } self::assertContains($combination, $redirects, 'wrong redirect found'); } } diff --git a/typo3/sysext/redirects/Tests/Unit/Event/AfterAutoCreateRedirectHasBeenPersistedEventTest.php b/typo3/sysext/redirects/Tests/Unit/Event/AfterAutoCreateRedirectHasBeenPersistedEventTest.php new file mode 100644 index 000000000000..0f28a913b99b --- /dev/null +++ b/typo3/sysext/redirects/Tests/Unit/Event/AfterAutoCreateRedirectHasBeenPersistedEventTest.php @@ -0,0 +1,61 @@ +<?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\Redirects\Tests\Unit\Event; + +use TYPO3\CMS\Core\Site\Entity\Site; +use TYPO3\CMS\Core\Site\Entity\SiteLanguage; +use TYPO3\CMS\Redirects\Event\AfterAutoCreateRedirectHasBeenPersistedEvent; +use TYPO3\CMS\Redirects\RedirectUpdate\PlainSlugReplacementRedirectSource; +use TYPO3\CMS\Redirects\RedirectUpdate\RedirectSourceCollection; +use TYPO3\CMS\Redirects\RedirectUpdate\SlugRedirectChangeItem; +use TYPO3\TestingFramework\Core\Unit\UnitTestCase; + +class AfterAutoCreateRedirectHasBeenPersistedEventTest extends UnitTestCase +{ + /** + * @test + */ + public function afterAutoCreateRedirectHasBeenPersistedGettersReturnsCreationValues(): void + { + $source = new PlainSlugReplacementRedirectSource( + host: '*', + path: '/some-path', + targetLinkParameters: [] + ); + $changeItem = new SlugRedirectChangeItem( + defaultLanguagePageId: 1, + pageId: 1, + site: $this->createMock(Site::class), + siteLanguage: $this->createMock(SiteLanguage::class), + original: ['original'], + sourcesCollection: new RedirectSourceCollection($source), + changed: ['changed'], + ); + $redirectRecord = ['redirect-record']; + + $event = new AfterAutoCreateRedirectHasBeenPersistedEvent( + slugRedirectChangeItem: $changeItem, + source: $source, + redirectRecord: $redirectRecord, + ); + + self::assertSame($source, $event->getSource()); + self::assertSame($changeItem, $event->getSlugRedirectChangeItem()); + self::assertSame($redirectRecord, $event->getRedirectRecord()); + } +} diff --git a/typo3/sysext/redirects/Tests/Unit/Event/ModifyAutoCreateRedirectRecordBeforePersistingEventTest.php b/typo3/sysext/redirects/Tests/Unit/Event/ModifyAutoCreateRedirectRecordBeforePersistingEventTest.php new file mode 100644 index 000000000000..154408c6a3c0 --- /dev/null +++ b/typo3/sysext/redirects/Tests/Unit/Event/ModifyAutoCreateRedirectRecordBeforePersistingEventTest.php @@ -0,0 +1,97 @@ +<?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\Redirects\Tests\Unit\Event; + +use TYPO3\CMS\Core\Site\Entity\Site; +use TYPO3\CMS\Core\Site\Entity\SiteLanguage; +use TYPO3\CMS\Redirects\Event\ModifyAutoCreateRedirectRecordBeforePersistingEvent; +use TYPO3\CMS\Redirects\RedirectUpdate\PlainSlugReplacementRedirectSource; +use TYPO3\CMS\Redirects\RedirectUpdate\RedirectSourceCollection; +use TYPO3\CMS\Redirects\RedirectUpdate\SlugRedirectChangeItem; +use TYPO3\TestingFramework\Core\Unit\UnitTestCase; + +class ModifyAutoCreateRedirectRecordBeforePersistingEventTest extends UnitTestCase +{ + public function modifyAutoCreateRedirectRecordBeforePersistingGettersReturnInstantiatingValues(): void + { + $source = new PlainSlugReplacementRedirectSource( + host: '*', + path: '/some-path', + targetLinkParameters: [] + ); + $changeItem = new SlugRedirectChangeItem( + defaultLanguagePageId: 1, + pageId: 1, + site: $this->createMock(Site::class), + siteLanguage: $this->createMock(SiteLanguage::class), + original: ['original'], + sourcesCollection: new RedirectSourceCollection($source), + changed: ['changed'], + ); + $redirectRecord = ['redirect-record']; + + $event = new ModifyAutoCreateRedirectRecordBeforePersistingEvent( + slugRedirectChangeItem: $changeItem, + source: $source, + redirectRecord: $redirectRecord, + ); + + self::assertSame($source, $event->getSource()); + self::assertSame($changeItem, $event->getSlugRedirectChangeItem()); + self::assertSame($redirectRecord, $event->getRedirectRecord()); + } + + /** + * @test + */ + public function modifyAutoCreateRedirectRecordBeforePersistingRedirectRecordCanBeSet(): void + { + $source = new PlainSlugReplacementRedirectSource( + host: '*', + path: '/some-path', + targetLinkParameters: [] + ); + $changeItem = new SlugRedirectChangeItem( + defaultLanguagePageId: 1, + pageId: 1, + site: $this->createMock(Site::class), + siteLanguage: $this->createMock(SiteLanguage::class), + original: ['original'], + sourcesCollection: new RedirectSourceCollection($source), + changed: ['changed'], + ); + $redirectRecord = ['redirect-record']; + + $event = new ModifyAutoCreateRedirectRecordBeforePersistingEvent( + slugRedirectChangeItem: $changeItem, + source: $source, + redirectRecord: $redirectRecord, + ); + + self::assertSame($source, $event->getSource()); + self::assertSame($changeItem, $event->getSlugRedirectChangeItem()); + self::assertSame($redirectRecord, $event->getRedirectRecord()); + + $changedRedirectRecord = ['changed-record']; + $event->setRedirectRecord($changedRedirectRecord); + + self::assertSame($source, $event->getSource()); + self::assertSame($changeItem, $event->getSlugRedirectChangeItem()); + self::assertSame($changedRedirectRecord, $event->getRedirectRecord()); + } +} -- GitLab