From a0e2ba7a872c95a1e3d812c8b5de9a50b3db97ff Mon Sep 17 00:00:00 2001 From: Benni Mack Date: Fri, 2 Jun 2023 11:31:46 +0200 Subject: [PATCH] [!!!][FEATURE] Migrate IndexQueue hooks to PSR-14 events More hooks have been removed: The hook :php:`$GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['solr']['postProcessIndexQueueInitialization']` and its interface :php:`ApacheSolrForTypo3\Solr\IndexQueue\InitializationPostProcessor` are now superseded by the PSR-14 event :php:`ApacheSolrForTypo3\Solr\Event\IndexQueue\AfterIndexQueueHasBeenInitializedEvent` The hook :php:`$GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['solr']['postProcessFetchRecordsForIndexQueueItem']` is now superseded by the PSR-14 event :php:`ApacheSolrForTypo3\Solr\Event\IndexQueue\AfterRecordsForIndexQueueItemsHaveBeenRetrievedEvent` Tests have been added and documentation has been adapted. Fixes: #3666 --- .../Queue/QueueInitializationService.php | 31 +++----- .../Index/Queue/QueueItemRepository.php | 23 ++---- ...AfterIndexQueueHasBeenInitializedEvent.php | 75 +++++++++++++++++++ ...rIndexQueueItemsHaveBeenRetrievedEvent.php | 53 +++++++++++++ .../InitializationPostProcessor.php | 39 ---------- Documentation/Releases/solr-release-12-0.rst | 10 +++ .../Index/Queue/QueueItemRepositoryTest.php | 29 +++++++ .../Queue/QueueInitializerServiceTest.php | 22 +++++- Tests/Unit/IndexQueue/ItemTest.php | 15 ++-- 9 files changed, 213 insertions(+), 84 deletions(-) create mode 100644 Classes/Event/IndexQueue/AfterIndexQueueHasBeenInitializedEvent.php create mode 100644 Classes/Event/IndexQueue/AfterRecordsForIndexQueueItemsHaveBeenRetrievedEvent.php delete mode 100644 Classes/IndexQueue/InitializationPostProcessor.php diff --git a/Classes/Domain/Index/Queue/QueueInitializationService.php b/Classes/Domain/Index/Queue/QueueInitializationService.php index 5a0ab675bd..33b1524713 100644 --- a/Classes/Domain/Index/Queue/QueueInitializationService.php +++ b/Classes/Domain/Index/Queue/QueueInitializationService.php @@ -18,13 +18,13 @@ namespace ApacheSolrForTypo3\Solr\Domain\Index\Queue; use ApacheSolrForTypo3\Solr\Domain\Site\Site; -use ApacheSolrForTypo3\Solr\IndexQueue\InitializationPostProcessor; +use ApacheSolrForTypo3\Solr\Event\IndexQueue\AfterIndexQueueHasBeenInitializedEvent; use ApacheSolrForTypo3\Solr\IndexQueue\Initializer\AbstractInitializer; use ApacheSolrForTypo3\Solr\IndexQueue\Queue; use Doctrine\DBAL\ConnectionException; use Doctrine\DBAL\Exception as DBALException; +use Psr\EventDispatcher\EventDispatcherInterface; use TYPO3\CMS\Core\Utility\GeneralUtility; -use UnexpectedValueException; /** * The queue initialization service is responsible to run the initialization of the index queue for a combination of sites @@ -36,10 +36,12 @@ class QueueInitializationService { protected Queue $queue; + protected EventDispatcherInterface $eventDispatcher; - public function __construct(Queue $queue) + public function __construct(Queue $queue, EventDispatcherInterface $eventDispatcher = null) { $this->queue = $queue; + $this->eventDispatcher = $eventDispatcher ?? GeneralUtility::makeInstance(EventDispatcherInterface::class); } /** @@ -85,6 +87,8 @@ public function initializeBySitesAndConfigurations(array $sites, array $indexing * Initializes a set of index configurations for a given site. * If one of the indexing configuration names is a * (wildcard) all configurations are used, * + * @param array $indexingConfigurationNames + * @return array * @throws ConnectionException * @throws DBALException */ @@ -97,20 +101,6 @@ public function initializeBySiteAndIndexConfigurations(Site $site, array $indexi foreach ($indexingConfigurationNames as $indexingConfigurationName) { $initializationStatus[$indexingConfigurationName] = $this->applyInitialization($site, (string)$indexingConfigurationName); } - - if (!isset($GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['solr']['postProcessIndexQueueInitialization'])) { - return $initializationStatus; - } - - foreach ($GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['solr']['postProcessIndexQueueInitialization'] as $classReference) { - $indexQueueInitializationPostProcessor = GeneralUtility::makeInstance($classReference); - if ($indexQueueInitializationPostProcessor instanceof InitializationPostProcessor) { - $indexQueueInitializationPostProcessor->postProcessIndexQueueInitialization($site, $indexingConfigurationNames, $initializationStatus); - } else { - throw new UnexpectedValueException(get_class($indexQueueInitializationPostProcessor) . ' must implement interface ' . InitializationPostProcessor::class, 1345815561); - } - } - return $initializationStatus; } @@ -136,8 +126,6 @@ protected function applyInitialization(Site $site, string $indexingConfiguration /** * Executes desired initializer - * - * @throws DBALException */ protected function executeInitializer( Site $site, @@ -153,6 +141,9 @@ protected function executeInitializer( $initializer->setIndexingConfigurationName($indexingConfigurationName); $initializer->setIndexingConfiguration($indexConfiguration); - return $initializer->initialize(); + $isInitialized = $initializer->initialize(); + $event = new AfterIndexQueueHasBeenInitializedEvent($initializer, $site, $indexingConfigurationName, $type, $indexConfiguration, $isInitialized); + $event = $this->eventDispatcher->dispatch($event); + return $event->isInitialized(); } } diff --git a/Classes/Domain/Index/Queue/QueueItemRepository.php b/Classes/Domain/Index/Queue/QueueItemRepository.php index a9bad5f8a4..652055825b 100644 --- a/Classes/Domain/Index/Queue/QueueItemRepository.php +++ b/Classes/Domain/Index/Queue/QueueItemRepository.php @@ -18,12 +18,14 @@ namespace ApacheSolrForTypo3\Solr\Domain\Index\Queue; use ApacheSolrForTypo3\Solr\Domain\Site\Site; +use ApacheSolrForTypo3\Solr\Event\IndexQueue\AfterRecordsForIndexQueueItemsHaveBeenRetrievedEvent; use ApacheSolrForTypo3\Solr\IndexQueue\Item; use ApacheSolrForTypo3\Solr\System\Logging\SolrLogManager; use ApacheSolrForTypo3\Solr\System\Records\AbstractRepository; use ApacheSolrForTypo3\Solr\System\Util\SiteUtility; use Doctrine\DBAL\Exception as DBALException; use PDO; +use Psr\EventDispatcher\EventDispatcherInterface; use TYPO3\CMS\Core\Database\ConnectionPool; use TYPO3\CMS\Core\Database\Query\Expression\CompositeExpression; use TYPO3\CMS\Core\Database\Query\QueryBuilder; @@ -38,13 +40,15 @@ class QueueItemRepository extends AbstractRepository protected string $table = 'tx_solr_indexqueue_item'; protected SolrLogManager $logger; + protected EventDispatcherInterface $eventDispatcher; - public function __construct(SolrLogManager $logManager = null) + public function __construct(SolrLogManager $logManager = null, EventDispatcherInterface $eventDispatcher = null) { $this->logger = $logManager ?? GeneralUtility::makeInstance( SolrLogManager::class, __CLASS__ ); + $this->eventDispatcher = $eventDispatcher ?? GeneralUtility::makeInstance(EventDispatcherInterface::class); } /** @@ -699,26 +703,13 @@ protected function getAllQueueItemRecordsByUidsGroupedByTable(array $indexQueueI } $tableRecords[$table] = $records; - $this->hookPostProcessFetchRecordsForIndexQueueItem($table, $uids, $tableRecords); + $event = $this->eventDispatcher->dispatch(new AfterRecordsForIndexQueueItemsHaveBeenRetrievedEvent($table, $uids, $records)); + $tableRecords[$table] = $event->getRecords(); } return $tableRecords; } - /** - * Calls defined in postProcessFetchRecordsForIndexQueueItem hook method. - */ - protected function hookPostProcessFetchRecordsForIndexQueueItem(string $table, array $uids, array &$tableRecords): void - { - if (!is_array($GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['solr']['postProcessFetchRecordsForIndexQueueItem'] ?? null)) { - return; - } - $params = ['table' => $table, 'uids' => $uids, 'tableRecords' => &$tableRecords]; - foreach ($GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['solr']['postProcessFetchRecordsForIndexQueueItem'] as $reference) { - GeneralUtility::callUserFunction($reference, $params, $this); - } - } - /** * Instantiates a list of Item objects from database records. * diff --git a/Classes/Event/IndexQueue/AfterIndexQueueHasBeenInitializedEvent.php b/Classes/Event/IndexQueue/AfterIndexQueueHasBeenInitializedEvent.php new file mode 100644 index 0000000000..80fbe45648 --- /dev/null +++ b/Classes/Event/IndexQueue/AfterIndexQueueHasBeenInitializedEvent.php @@ -0,0 +1,75 @@ +initializer; + } + + public function getSite(): Site + { + return $this->site; + } + + public function getIndexingConfigurationName(): string + { + return $this->indexingConfigurationName; + } + + public function getType(): string + { + return $this->type; + } + + public function getIndexingConfiguration(): array + { + return $this->indexingConfiguration; + } + + public function isInitialized(): bool + { + return $this->isInitialized; + } + + public function setIsInitialized(bool $isInitialized): void + { + $this->isInitialized = $isInitialized; + } +} diff --git a/Classes/Event/IndexQueue/AfterRecordsForIndexQueueItemsHaveBeenRetrievedEvent.php b/Classes/Event/IndexQueue/AfterRecordsForIndexQueueItemsHaveBeenRetrievedEvent.php new file mode 100644 index 0000000000..71fa47555a --- /dev/null +++ b/Classes/Event/IndexQueue/AfterRecordsForIndexQueueItemsHaveBeenRetrievedEvent.php @@ -0,0 +1,53 @@ +table; + } + + public function getRecordUids(): array + { + return $this->uids; + } + + public function getRecords(): array + { + return $this->records; + } + + public function setRecords(array $records): void + { + $this->records = $records; + } +} diff --git a/Classes/IndexQueue/InitializationPostProcessor.php b/Classes/IndexQueue/InitializationPostProcessor.php deleted file mode 100644 index bd079d2b6f..0000000000 --- a/Classes/IndexQueue/InitializationPostProcessor.php +++ /dev/null @@ -1,39 +0,0 @@ - - */ -interface InitializationPostProcessor -{ - /** - * Post process Index Queue initialization - * - * @param Site $site The site to initialize - * @param array $indexingConfigurations Initialized indexing configurations - * @param array $initializationStatus Results of Index Queue initializations - */ - public function postProcessIndexQueueInitialization( - Site $site, - array $indexingConfigurations, - array $initializationStatus - ); -} diff --git a/Documentation/Releases/solr-release-12-0.rst b/Documentation/Releases/solr-release-12-0.rst index f7001be5a8..182bd84c6a 100644 --- a/Documentation/Releases/solr-release-12-0.rst +++ b/Documentation/Releases/solr-release-12-0.rst @@ -39,6 +39,16 @@ The hook :php:`$GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['solr']['Indexer']['indexP interface :php:`ApacheSolrForTypo3\Solr\SubstitutePageIndexer` are now superseded by the PSR-14 event :php:`ApacheSolrForTypo3\Solr\Event\Indexing\AfterPageDocumentIsCreatedForIndexingEvent`. +The hook :php:`$GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['solr']['postProcessIndexQueueInitialization']` and its +interface :php:`ApacheSolrForTypo3\Solr\IndexQueue\InitializationPostProcessor` are now superseded +by the PSR-14 event :php:`ApacheSolrForTypo3\Solr\Event\IndexQueue\AfterIndexQueueHasBeenInitializedEvent` + +The hook :php:`$GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['solr']['postProcessFetchRecordsForIndexQueueItem']` is now superseded +by the PSR-14 event :php:`ApacheSolrForTypo3\Solr\Event\IndexQueue\AfterRecordsForIndexQueueItemsHaveBeenRetrievedEvent` + +The hook :php:`$GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['solr']['IndexQueuePageIndexer']['dataUrlModifier']` +and the according interface :php:`ApacheSolrForTypo3\Solr\IndexQueue\PageIndexerDataUrlModifier` +is now superseded by the PSR-14 event :php:`ApacheSolrForTypo3\Solr\Event\Indexing\AfterFrontendPageUriForIndexingHasBeenGeneratedEvent` Contributors ============ diff --git a/Tests/Integration/Domain/Index/Queue/QueueItemRepositoryTest.php b/Tests/Integration/Domain/Index/Queue/QueueItemRepositoryTest.php index 8dddb8d9c1..bbb15ca036 100644 --- a/Tests/Integration/Domain/Index/Queue/QueueItemRepositoryTest.php +++ b/Tests/Integration/Domain/Index/Queue/QueueItemRepositoryTest.php @@ -1,5 +1,7 @@ getType(), 'First item has unexpected type'); } + /** + * @test + */ + public function canFindItemsAndModifyViaEventListener(): void + { + $this->importCSVDataSet(__DIR__ . '/Fixtures/pages_and_news_queueitems.csv'); + $eventDispatcher = new MockEventDispatcher(); + $queueItemRepository = GeneralUtility::makeInstance(QueueItemRepository::class, null, $eventDispatcher); + $items = $queueItemRepository->findItems([], ['pages']); + + /** @var Item $firstItem */ + $firstItem = $items[0]; + self::assertSame(2, count($items)); + self::assertSame('pages', $firstItem->getType(), 'First item has unexpected type'); + + $eventDispatcher->addListener(function (AfterRecordsForIndexQueueItemsHaveBeenRetrievedEvent $event): void { + if ($event->getTable() === 'pages') { + $event->setRecords([]); + } + }); + + $items = $queueItemRepository->findItems([], ['pages']); + self::assertCount(0, $items); + } + /** * @test */ diff --git a/Tests/Unit/Domain/Index/Queue/QueueInitializerServiceTest.php b/Tests/Unit/Domain/Index/Queue/QueueInitializerServiceTest.php index b71cb2351b..9f8248f536 100644 --- a/Tests/Unit/Domain/Index/Queue/QueueInitializerServiceTest.php +++ b/Tests/Unit/Domain/Index/Queue/QueueInitializerServiceTest.php @@ -1,5 +1,22 @@ @@ -29,10 +47,10 @@ class QueueInitializerServiceTest extends SetUpUnitTestCase /** * @test */ - public function allIndexConfigurationsAreUsedWhenWildcardIsPassed() + public function allIndexConfigurationsAreUsedWhenWildcardIsPassed(): void { $queueMock = $this->createMock(Queue::class); - $service = $this->getMockBuilder(QueueInitializationService::class)->onlyMethods(['executeInitializer'])->setConstructorArgs([$queueMock])->getMock(); + $service = $this->getMockBuilder(QueueInitializationService::class)->onlyMethods(['executeInitializer'])->setConstructorArgs([$queueMock, new NoopEventDispatcher()])->getMock(); $fakeTs = [ 'plugin.' => [ diff --git a/Tests/Unit/IndexQueue/ItemTest.php b/Tests/Unit/IndexQueue/ItemTest.php index e93fc5d269..d64b9800a5 100644 --- a/Tests/Unit/IndexQueue/ItemTest.php +++ b/Tests/Unit/IndexQueue/ItemTest.php @@ -15,6 +15,7 @@ namespace ApacheSolrForTypo3\Solr\Tests\Unit\IndexQueue; +use ApacheSolrForTypo3\Solr\Domain\Index\Queue\QueueItemRepository; use ApacheSolrForTypo3\Solr\IndexQueue\Item; use ApacheSolrForTypo3\Solr\Tests\Unit\SetUpUnitTestCase; @@ -30,7 +31,7 @@ public function canGetErrors() { $metaData = ['errors' => 'error during index']; $record = []; - $item = new Item($metaData, $record); + $item = new Item($metaData, $record, null, $this->createMock(QueueItemRepository::class)); $errors = $item->getErrors(); self::assertSame('error during index', $errors, 'Can not get errors from queue item'); @@ -43,7 +44,7 @@ public function canGetType() { $metaData = ['item_type' => 'pages']; $record = []; - $item = new Item($metaData, $record); + $item = new Item($metaData, $record, null, $this->createMock(QueueItemRepository::class)); $type = $item->getType(); self::assertSame('pages', $type, 'Can not get type from queue item'); @@ -67,7 +68,7 @@ public function getStateDataProvider(): array */ public function canGetState($metaData, $expectedState) { - $item = new Item($metaData, []); + $item = new Item($metaData, [], null, $this->createMock(QueueItemRepository::class)); self::assertSame($expectedState, $item->getState(), 'Can not get state from item as expected'); } @@ -76,10 +77,10 @@ public function canGetState($metaData, $expectedState) */ public function testHasErrors() { - $item = new Item([], []); + $item = new Item([], [], null, $this->createMock(QueueItemRepository::class)); self::assertFalse($item->getHasErrors(), 'Expected that item without any data has no errors'); - $item = new Item(['errors' => 'something is broken'], []); + $item = new Item(['errors' => 'something is broken'], [], null, $this->createMock(QueueItemRepository::class)); self::assertTrue($item->getHasErrors(), 'Item with errors was not indicated to have errors'); } @@ -88,10 +89,10 @@ public function testHasErrors() */ public function testHasIndexingProperties() { - $item = new Item([], []); + $item = new Item([], [], null, $this->createMock(QueueItemRepository::class)); self::assertFalse($item->hasIndexingProperties(), 'Expected that empty item should not have any indexing properties'); - $item = new Item(['has_indexing_properties' => true], []); + $item = new Item(['has_indexing_properties' => true], [], null, $this->createMock(QueueItemRepository::class)); self::assertTrue($item->hasIndexingProperties(), 'Item with proper meta data should have indexing properties'); } }