diff --git a/Classes/Controller/Backend/Search/AbstractModuleController.php b/Classes/Controller/Backend/Search/AbstractModuleController.php index 0444b40321..ed288d9e43 100644 --- a/Classes/Controller/Backend/Search/AbstractModuleController.php +++ b/Classes/Controller/Backend/Search/AbstractModuleController.php @@ -20,6 +20,7 @@ use ApacheSolrForTypo3\Solr\Domain\Site\Site; use ApacheSolrForTypo3\Solr\Domain\Site\SiteRepository; use ApacheSolrForTypo3\Solr\IndexQueue\Queue; +use ApacheSolrForTypo3\Solr\IndexQueue\QueueInterface; use ApacheSolrForTypo3\Solr\System\Mvc\Backend\Service\ModuleDataStorageService; use ApacheSolrForTypo3\Solr\System\Solr\SolrConnection as SolrCoreConnection; use Doctrine\DBAL\Exception as DBALException; @@ -65,7 +66,7 @@ public function __construct( protected readonly SiteRepository $siteRepository, protected readonly SiteFinder $siteFinder, protected readonly ConnectionManager $solrConnectionManager, - protected Queue $indexQueue, + protected QueueInterface $indexQueue, protected ?int $selectedPageUID = null, ) { $this->selectedPageUID = $selectedPageUID ?? 0; diff --git a/Classes/Controller/Backend/Search/IndexQueueModuleController.php b/Classes/Controller/Backend/Search/IndexQueueModuleController.php index 5c7e813de1..3646d285ba 100644 --- a/Classes/Controller/Backend/Search/IndexQueueModuleController.php +++ b/Classes/Controller/Backend/Search/IndexQueueModuleController.php @@ -17,8 +17,11 @@ use ApacheSolrForTypo3\Solr\Backend\IndexingConfigurationSelectorField; use ApacheSolrForTypo3\Solr\Domain\Index\IndexService; +use ApacheSolrForTypo3\Solr\Domain\Index\Queue\QueueInitializationService; use ApacheSolrForTypo3\Solr\Domain\Site\Exception\UnexpectedTYPO3SiteInitializationException; use ApacheSolrForTypo3\Solr\IndexQueue\Queue; +use ApacheSolrForTypo3\Solr\IndexQueue\QueueInterface; +use ApacheSolrForTypo3\Solr\IndexQueue\QueueInitializationServiceAwareInterface; use Doctrine\DBAL\ConnectionException; use Doctrine\DBAL\Exception as DBALException; use Psr\Http\Message\ResponseInterface; @@ -36,7 +39,7 @@ */ class IndexQueueModuleController extends AbstractModuleController { - public function setIndexQueue(Queue $indexQueue): void + public function setIndexQueue(QueueInterface $indexQueue): void { $this->indexQueue = $indexQueue; } @@ -107,7 +110,13 @@ public function initializeIndexQueueAction(): ResponseInterface if ((!empty($indexingConfigurationsToInitialize)) && (is_array($indexingConfigurationsToInitialize))) { // initialize selected indexing configuration try { - $initializedIndexingConfigurations = $this->indexQueue->getInitializationService()->initializeBySiteAndIndexConfigurations($this->selectedSite, $indexingConfigurationsToInitialize); + if ($this->indexQueue instanceof QueueInitializationServiceAwareInterface) { + $initializationService = $this->indexQueue->getQueueInitializationService(); + } else { + $initializationService = GeneralUtility::makeInstance(QueueInitializationService::class); + } + + $initializedIndexingConfigurations = $initializationService->initializeBySiteAndIndexConfigurations($this->selectedSite, $indexingConfigurationsToInitialize); } catch (Throwable $e) { $this->addFlashMessage( sprintf( diff --git a/Classes/Domain/Index/IndexService.php b/Classes/Domain/Index/IndexService.php index 6144084eaa..1e0aae5cd2 100644 --- a/Classes/Domain/Index/IndexService.php +++ b/Classes/Domain/Index/IndexService.php @@ -24,6 +24,7 @@ use ApacheSolrForTypo3\Solr\IndexQueue\Indexer; use ApacheSolrForTypo3\Solr\IndexQueue\Item; use ApacheSolrForTypo3\Solr\IndexQueue\Queue; +use ApacheSolrForTypo3\Solr\IndexQueue\QueueInterface; use ApacheSolrForTypo3\Solr\System\Configuration\TypoScriptConfiguration; use ApacheSolrForTypo3\Solr\System\Logging\SolrLogManager; use ApacheSolrForTypo3\Solr\Task\IndexQueueWorkerTask; @@ -45,7 +46,7 @@ class IndexService protected ?IndexQueueWorkerTask $contextTask = null; - protected Queue $indexQueue; + protected QueueInterface $indexQueue; protected EventDispatcherInterface $eventDispatcher; @@ -53,7 +54,7 @@ class IndexService public function __construct( Site $site, - Queue $queue = null, + QueueInterface $queue = null, EventDispatcherInterface $eventDispatcher = null, SolrLogManager $solrLogManager = null, ) { diff --git a/Classes/Domain/Index/Queue/GarbageRemover/AbstractStrategy.php b/Classes/Domain/Index/Queue/GarbageRemover/AbstractStrategy.php index d27984bed8..11cff9f6c3 100644 --- a/Classes/Domain/Index/Queue/GarbageRemover/AbstractStrategy.php +++ b/Classes/Domain/Index/Queue/GarbageRemover/AbstractStrategy.php @@ -19,6 +19,7 @@ use ApacheSolrForTypo3\Solr\Domain\Site\Exception\UnexpectedTYPO3SiteInitializationException; use ApacheSolrForTypo3\Solr\GarbageCollectorPostProcessor; use ApacheSolrForTypo3\Solr\IndexQueue\Queue; +use ApacheSolrForTypo3\Solr\IndexQueue\QueueInterface; use ApacheSolrForTypo3\Solr\System\Logging\SolrLogManager; use Doctrine\DBAL\Exception as DBALException; use InvalidArgumentException; @@ -31,12 +32,12 @@ */ abstract class AbstractStrategy { - protected Queue $queue; + protected QueueInterface $queue; protected ConnectionManager $connectionManager; public function __construct( - Queue $queue = null, + QueueInterface $queue = null, ConnectionManager $connectionManager = null, ) { $this->queue = $queue ?? GeneralUtility::makeInstance(Queue::class); diff --git a/Classes/Domain/Index/Queue/QueueInitializationService.php b/Classes/Domain/Index/Queue/QueueInitializationService.php index 33b1524713..7c2124265c 100644 --- a/Classes/Domain/Index/Queue/QueueInitializationService.php +++ b/Classes/Domain/Index/Queue/QueueInitializationService.php @@ -20,7 +20,7 @@ use ApacheSolrForTypo3\Solr\Domain\Site\Site; use ApacheSolrForTypo3\Solr\Event\IndexQueue\AfterIndexQueueHasBeenInitializedEvent; use ApacheSolrForTypo3\Solr\IndexQueue\Initializer\AbstractInitializer; -use ApacheSolrForTypo3\Solr\IndexQueue\Queue; +use ApacheSolrForTypo3\Solr\IndexQueue\QueueInterface; use Doctrine\DBAL\ConnectionException; use Doctrine\DBAL\Exception as DBALException; use Psr\EventDispatcher\EventDispatcherInterface; @@ -35,14 +35,18 @@ */ class QueueInitializationService { - protected Queue $queue; + protected bool $clearQueueOnInitialization = true; protected EventDispatcherInterface $eventDispatcher; - public function __construct(Queue $queue, EventDispatcherInterface $eventDispatcher = null) + public function __construct(EventDispatcherInterface $eventDispatcher = null) { - $this->queue = $queue; $this->eventDispatcher = $eventDispatcher ?? GeneralUtility::makeInstance(EventDispatcherInterface::class); } + + public function setClearQueueOnInitialization(bool $clearQueueOnInitialization): void + { + $this->clearQueueOnInitialization = $clearQueueOnInitialization; + } /** * Truncate and rebuild the tx_solr_indexqueue_item table. This is the most @@ -113,10 +117,21 @@ public function initializeBySiteAndIndexConfigurations(Site $site, array $indexi */ protected function applyInitialization(Site $site, string $indexingConfigurationName): bool { + $solrConfiguration = $site->getSolrConfiguration(); + + /** @var QueueInterface $queue */ + $queue = GeneralUtility::makeInstance( + $solrConfiguration->getIndexQueueClassByConfigurationName($indexingConfigurationName) + ); + if ($queue instanceof QueueInitializationServiceAwareInterface) { + $queue->setQueueInitializationService($this); + } + // clear queue - $this->queue->deleteItemsBySite($site, $indexingConfigurationName); + if ($this->clearQueueOnInitialization) { + $queue->deleteItemsBySite($site, $indexingConfigurationName); + } - $solrConfiguration = $site->getSolrConfiguration(); $type = $solrConfiguration->getIndexQueueTypeOrFallbackToConfigurationName($indexingConfigurationName); $initializerClass = $solrConfiguration->getIndexQueueInitializerClassByConfigurationName($indexingConfigurationName); $indexConfiguration = $solrConfiguration->getIndexQueueConfigurationByName($indexingConfigurationName); diff --git a/Classes/Domain/Index/Queue/QueueItemRepository.php b/Classes/Domain/Index/Queue/QueueItemRepository.php index ad8aab2d01..8338fd95ce 100644 --- a/Classes/Domain/Index/Queue/QueueItemRepository.php +++ b/Classes/Domain/Index/Queue/QueueItemRepository.php @@ -20,6 +20,7 @@ use ApacheSolrForTypo3\Solr\Domain\Site\Site; use ApacheSolrForTypo3\Solr\Event\IndexQueue\AfterRecordsForIndexQueueItemsHaveBeenRetrievedEvent; use ApacheSolrForTypo3\Solr\IndexQueue\Item; +use ApacheSolrForTypo3\Solr\IndexQueue\ItemInterface; use ApacheSolrForTypo3\Solr\System\Logging\SolrLogManager; use ApacheSolrForTypo3\Solr\System\Records\AbstractRepository; use ApacheSolrForTypo3\Solr\System\Util\SiteUtility; @@ -118,7 +119,7 @@ public function flushErrorsBySite(Site $site): int /** * Flushes the error for a single item. */ - public function flushErrorByItem(Item $item): int + public function flushErrorByItem(ItemInterface $item): int { $queryBuilder = $this->getQueryBuilder(); return $this->getPreparedFlushErrorQuery($queryBuilder) @@ -751,7 +752,7 @@ protected function getQueueItemObjectsByRecords(array $indexQueueItemRecords, ar * Marks an item as failed and causes the indexer to skip the item in the * next run. */ - public function markItemAsFailed(Item|int|null $item, string $errorMessage = ''): int + public function markItemAsFailed(ItemInterface|int|null $item, string $errorMessage = ''): int { $itemUid = ($item instanceof Item) ? $item->getIndexQueueUid() : (int)$item; $errorMessage = empty($errorMessage) ? '1' : $errorMessage; @@ -767,7 +768,7 @@ public function markItemAsFailed(Item|int|null $item, string $errorMessage = '') /** * Sets the timestamp of when an item last has been indexed. */ - public function updateIndexTimeByItem(Item $item): int + public function updateIndexTimeByItem(ItemInterface $item): int { $queryBuilder = $this->getQueryBuilder(); return $queryBuilder @@ -780,7 +781,7 @@ public function updateIndexTimeByItem(Item $item): int /** * Sets the change timestamp of an item. */ - public function updateChangedTimeByItem(Item $item, int $changedTime = 0): int + public function updateChangedTimeByItem(ItemInterface $item, int $changedTime = 0): int { $queryBuilder = $this->getQueryBuilder(); return $queryBuilder diff --git a/Classes/Event/IndexQueue/AfterIndexQueueItemHasBeenMarkedForReindexingEvent.php b/Classes/Event/IndexQueue/AfterIndexQueueItemHasBeenMarkedForReindexingEvent.php index 9faf124b5c..a33e425a2c 100644 --- a/Classes/Event/IndexQueue/AfterIndexQueueItemHasBeenMarkedForReindexingEvent.php +++ b/Classes/Event/IndexQueue/AfterIndexQueueItemHasBeenMarkedForReindexingEvent.php @@ -27,9 +27,10 @@ final class AfterIndexQueueItemHasBeenMarkedForReindexingEvent { public function __construct( private readonly string $itemType, - private readonly int $itemUid, + private readonly int|string $itemUid, private readonly int $forcedChangeTime, - private int $updateCount + private int $updateCount, + private ?array $validLanguageUids ) { } @@ -38,7 +39,7 @@ public function getItemType(): string return $this->itemType; } - public function getItemUid(): int + public function getItemUid(): int|string { return $this->itemUid; } @@ -57,4 +58,9 @@ public function setUpdateCount(int $updateCount): void { $this->updateCount = $updateCount; } + + public function getValidLanguageUids(): ?array + { + return $this->validLanguageUids; + } } diff --git a/Classes/IndexQueue/Item.php b/Classes/IndexQueue/Item.php index 4446579dfa..518e8bf859 100644 --- a/Classes/IndexQueue/Item.php +++ b/Classes/IndexQueue/Item.php @@ -34,14 +34,8 @@ * * @author Ingo Renner */ -class Item +class Item implements ItemInterface, MountPointAwareItemInterface { - public const STATE_BLOCKED = -1; - - public const STATE_PENDING = 0; - - public const STATE_INDEXED = 1; - /** * The item's uid in the index queue (tx_solr_indexqueue_item.uid) */ @@ -94,6 +88,13 @@ class Item */ protected ?int $recordUid = null; + /** + * The indexing priority + * + * @var int + */ + protected int $indexingPriority = 0; + /** * The record itself */ @@ -136,6 +137,7 @@ public function __construct( $this->indexingConfigurationName = $itemMetaData['indexing_configuration'] ?? ''; $this->hasIndexingProperties = (bool)($itemMetaData['has_indexing_properties'] ?? false); + $this->indexingPriority = (int)($itemMetaData['indexing_priority'] ?? 0); if (!empty($fullRecord)) { $this->record = $fullRecord; @@ -217,7 +219,7 @@ public function getType(): ?string return $this->type; } - public function setType($type): void + public function setType(string $type): void { $this->type = $type; } @@ -266,7 +268,7 @@ public function getRecordUid(): int { $this->getRecord(); - return $this->record['uid']; + return (int)$this->record['uid']; } /** @@ -439,4 +441,12 @@ public function getIndexingPropertyNames(): array $this->loadIndexingProperties(); return array_keys($this->indexingProperties); } + + /** + * Returns the index priority. + */ + public function getIndexPriority(): int + { + return $this->indexingPriority; + } } diff --git a/Classes/IndexQueue/ItemInterface.php b/Classes/IndexQueue/ItemInterface.php new file mode 100644 index 0000000000..5c6675c645 --- /dev/null +++ b/Classes/IndexQueue/ItemInterface.php @@ -0,0 +1,115 @@ + */ -class Queue +class Queue implements QueueInterface, QueueInitializationServiceAwareInterface { protected RootPageResolver $rootPageResolver; @@ -60,20 +60,18 @@ class Queue protected EventDispatcherInterface $eventDispatcher; public function __construct( - RootPageResolver $rootPageResolver = null, - ConfigurationAwareRecordService $recordService = null, - QueueItemRepository $queueItemRepository = null, - QueueStatisticsRepository $queueStatisticsRepository = null, - QueueInitializationService $queueInitializationService = null, - FrontendEnvironment $frontendEnvironment = null, - EventDispatcherInterface $eventDispatcher = null, + ?RootPageResolver $rootPageResolver = null, + ?ConfigurationAwareRecordService $recordService = null, + ?QueueItemRepository $queueItemRepository = null, + ?QueueStatisticsRepository $queueStatisticsRepository = null, + ?FrontendEnvironment $frontendEnvironment = null, + ?EventDispatcherInterface $eventDispatcher = null, ) { $this->logger = GeneralUtility::makeInstance(SolrLogManager::class, __CLASS__); $this->rootPageResolver = $rootPageResolver ?? GeneralUtility::makeInstance(RootPageResolver::class); $this->recordService = $recordService ?? GeneralUtility::makeInstance(ConfigurationAwareRecordService::class); $this->queueItemRepository = $queueItemRepository ?? GeneralUtility::makeInstance(QueueItemRepository::class); $this->queueStatisticsRepository = $queueStatisticsRepository ?? GeneralUtility::makeInstance(QueueStatisticsRepository::class); - $this->queueInitializationService = $queueInitializationService ?? GeneralUtility::makeInstance(QueueInitializationService::class, $this); $this->frontendEnvironment = $frontendEnvironment ?? GeneralUtility::makeInstance(FrontendEnvironment::class); $this->eventDispatcher = $eventDispatcher ?? GeneralUtility::makeInstance(EventDispatcherInterface::class); } @@ -113,14 +111,43 @@ public function getLastIndexedItemId(int $rootPageId): int return $lastIndexedItemId; } + public function setQueueInitializationService(QueueInitializationService $queueInitializationService): void + { + $this->queueInitializationService = $queueInitializationService; + } + /** * Returns the QueueInitializationService */ - public function getInitializationService(): QueueInitializationService + public function getQueueInitializationService(): QueueInitializationService { + if (!isset($this->queueInitializationService)) { + trigger_error( + 'queueInitializationService is no longer initalized automatically, till EXT:solr supports DI' + . ' the QueueInitializationService has to be set manually, fallback will be removed in v13.', + E_USER_DEPRECATED + ); + $this->queueInitializationService = GeneralUtility::makeInstance(QueueInitializationService::class); + } + return $this->queueInitializationService; } + /** + * @deprecated Queue->getInitializationService is deprecated and will be removed in v12. + * Use Queue->getQueueInitializationService instead or create a fresh instance. + */ + public function getInitializationService(): QueueInitializationService + { + trigger_error( + 'Queue->getInitializationService is deprecated and will be removed in v13.' + . ' Use Queue->getQueueInitializationService instead or create a fresh instance.', + E_USER_DEPRECATED + ); + + return $this->getQueueInitializationService(); + } + /** * Marks an item as needing (re)indexing. * @@ -134,11 +161,12 @@ public function getInitializationService(): QueueInitializationService */ public function updateItem( string $itemType, - int $itemUid, + int|string $itemUid, int $forcedChangeTime = 0, + ?array $validLanguageUids = null ): int { $updateCount = $this->updateOrAddItemForAllRelatedRootPages($itemType, $itemUid, $forcedChangeTime); - $event = new AfterIndexQueueItemHasBeenMarkedForReindexingEvent($itemType, $itemUid, $forcedChangeTime, $updateCount); + $event = new AfterIndexQueueItemHasBeenMarkedForReindexingEvent($itemType, $itemUid, $forcedChangeTime, $updateCount, $validLanguageUids); $event = $this->eventDispatcher->dispatch($event); return $event->getUpdateCount(); } @@ -156,7 +184,7 @@ protected function updateOrAddItemForAllRelatedRootPages( ): int { $updateCount = 0; try { - $rootPageIds = $this->rootPageResolver->getResponsibleRootPageIds($itemType, $itemUid); + $rootPageIds = $this->rootPageResolver->getResponsibleRootPageIds($itemType, (int)$itemUid); } catch (RootPageRecordNotFoundException $e) { $this->deleteItem($itemType, $itemUid); return 0; @@ -184,8 +212,8 @@ protected function updateOrAddItemForAllRelatedRootPages( $itemInQueueForRootPage = $this->containsItemWithRootPageId($itemType, $itemUid, $rootPageId, $indexingConfiguration); if ($itemInQueueForRootPage) { // update changed time if that item is in the queue already - $changedTime = ($forcedChangeTime > 0) ? $forcedChangeTime : $this->getItemChangedTime($itemType, $itemUid); - $updatedRows = $this->queueItemRepository->updateExistingItemByItemTypeAndItemUidAndRootPageId($itemType, $itemUid, $rootPageId, $changedTime, $indexingConfiguration, $indexingPriority); + $changedTime = ($forcedChangeTime > 0) ? $forcedChangeTime : $this->getItemChangedTime($itemType, (int)$itemUid); + $updatedRows = $this->queueItemRepository->updateExistingItemByItemTypeAndItemUidAndRootPageId($itemType, (int)$itemUid, $rootPageId, $changedTime, $indexingConfiguration, $indexingPriority); } else { // add the item since it's not in the queue yet $updatedRows = $this->addNewItem($itemType, $itemUid, $indexingConfiguration, $rootPageId, $indexingPriority); @@ -226,7 +254,7 @@ public function resetErrorsBySite(Site $site): int /** * Resets the error in the index queue for a specific item */ - public function resetErrorByItem(Item $item): int + public function resetErrorByItem(ItemInterface $item): int { return $this->queueItemRepository->flushErrorByItem($item); } @@ -249,15 +277,15 @@ private function addNewItem( $additionalRecordFields = ', doktype, uid'; } - $record = $this->getRecordCached($itemType, $itemUid, $additionalRecordFields); + $record = $this->getRecordCached($itemType, (int)$itemUid, $additionalRecordFields); if (empty($record) || ($itemType === 'pages' && !$this->frontendEnvironment->isAllowedPageType($record, $indexingConfiguration))) { return 0; } - $changedTime = $this->getItemChangedTime($itemType, $itemUid); + $changedTime = $this->getItemChangedTime($itemType, (int)$itemUid); - return $this->queueItemRepository->add($itemType, $itemUid, $rootPageId, $changedTime, $indexingConfiguration, $indexingPriority); + return $this->queueItemRepository->add($itemType, (int)$itemUid, $rootPageId, $changedTime, $indexingConfiguration, $indexingPriority); } /** @@ -269,7 +297,7 @@ protected function getRecordCached( string $additionalRecordFields, ): ?array { $cache = GeneralUtility::makeInstance(TwoLevelCache::class, 'runtime'); - $cacheId = md5('Queue' . ':' . 'getRecordCached' . ':' . $itemType . ':' . $itemUid . ':' . 'pid' . $additionalRecordFields); + $cacheId = md5('Queue' . ':' . 'getRecordCached' . ':' . $itemType . ':' . (string)$itemUid . ':' . 'pid' . $additionalRecordFields); $record = $cache->get($cacheId); if (empty($record)) { @@ -324,7 +352,7 @@ protected function getItemChangedTime( $pageChangedTime = $this->getPageItemChangedTime($record); } - $localizationsChangedTime = $this->queueItemRepository->getLocalizableItemChangedTime($itemType, (int)$itemUid); + $localizationsChangedTime = $this->queueItemRepository->getLocalizableItemChangedTime($itemType, $itemUid); // if start time exists and start time is higher than last changed timestamp // then set changed to the future start time to make the item @@ -358,7 +386,7 @@ protected function getPageItemChangedTime(array $page): int */ public function containsItem( string $itemType, - int $itemUid, + int|string $itemUid, ): bool { return $this->queueItemRepository->containsItem($itemType, (int)$itemUid); } @@ -370,7 +398,7 @@ public function containsItem( */ public function containsItemWithRootPageId( string $itemType, - int $itemUid, + int|string $itemUid, int $rootPageId, string $indexingConfiguration ): bool { @@ -385,7 +413,7 @@ public function containsItemWithRootPageId( */ public function containsIndexedItem( string $itemType, - int $itemUid, + int|string $itemUid, ): bool { return $this->queueItemRepository->containsIndexedItem($itemType, (int)$itemUid); } @@ -397,7 +425,7 @@ public function containsIndexedItem( */ public function deleteItem( string $itemType, - int $itemUid, + int|string $itemUid, ): void { $this->queueItemRepository->deleteItem($itemType, (int)$itemUid); } @@ -438,7 +466,7 @@ public function deleteAllItems(): int * * @throws DBALException */ - public function getItem(int $itemId): ?Item + public function getItem(int|string $itemId): ?Item { return $this->queueItemRepository->findItemByUid($itemId); } @@ -452,7 +480,7 @@ public function getItem(int $itemId): ?Item */ public function getItems( string $itemType, - int $itemUid, + int|string $itemUid, ): array { return $this->queueItemRepository->findItemsByItemTypeAndItemUid($itemType, (int)$itemUid); } @@ -509,24 +537,24 @@ public function getItemsToIndex(Site $site, int $limit = 50): array * Marks an item as failed and causes the indexer to skip the item in the * next run. */ - public function markItemAsFailed(Item|int|null $item, string $errorMessage = ''): void + public function markItemAsFailed(ItemInterface|int|null $item, string $errorMessage = ''): int { - $this->queueItemRepository->markItemAsFailed($item, $errorMessage); + return $this->queueItemRepository->markItemAsFailed($item, $errorMessage); } /** * Sets the timestamp of when an item last has been indexed. */ - public function updateIndexTimeByItem(Item $item): void + public function updateIndexTimeByItem(ItemInterface $item): int { - $this->queueItemRepository->updateIndexTimeByItem($item); + return $this->queueItemRepository->updateIndexTimeByItem($item); } /** * Sets the change timestamp of an item. */ - public function setForcedChangeTimeByItem(Item $item, int $forcedChangeTime = 0): void + public function setForcedChangeTimeByItem(ItemInterface $item, int $forcedChangeTime = 0): int { - $this->queueItemRepository->updateChangedTimeByItem($item, $forcedChangeTime); + return $this->queueItemRepository->updateChangedTimeByItem($item, $forcedChangeTime); } } diff --git a/Classes/IndexQueue/QueueInitializationServiceAwareInterface.php b/Classes/IndexQueue/QueueInitializationServiceAwareInterface.php new file mode 100644 index 0000000000..9b850e82c0 --- /dev/null +++ b/Classes/IndexQueue/QueueInitializationServiceAwareInterface.php @@ -0,0 +1,36 @@ +getValueByPathOrDefaultValue($path, $defaultIfEmpty); } + /** + * This method is used to retrieve the className of a queue initializer for a certain indexing configuration + * + * plugin.tx_solr.index.queue..indexQueue + * + * @param string $configurationName + * @return string + */ + public function getIndexQueueClassByConfigurationName(string $configurationName): string + { + $path = 'plugin.tx_solr.index.queue.' . $configurationName . '.indexQueue'; + return (string)$this->getValueByPathOrDefaultValue($path, Queue::class); + } + /** * Returns the _LOCAL_LANG configuration from the TypoScript. * diff --git a/Classes/Task/ReIndexTask.php b/Classes/Task/ReIndexTask.php index c460b387f2..3265a355ae 100644 --- a/Classes/Task/ReIndexTask.php +++ b/Classes/Task/ReIndexTask.php @@ -18,7 +18,7 @@ namespace ApacheSolrForTypo3\Solr\Task; use ApacheSolrForTypo3\Solr\ConnectionManager; -use ApacheSolrForTypo3\Solr\IndexQueue\Queue; +use ApacheSolrForTypo3\Solr\Domain\Index\Queue\QueueInitializationService; use Doctrine\DBAL\ConnectionException as DBALConnectionException; use Doctrine\DBAL\Exception as DBALException; use TYPO3\CMS\Core\Utility\GeneralUtility; @@ -53,9 +53,9 @@ public function execute() $cleanUpResult = $this->cleanUpIndex(); // initialize for re-indexing - /** @var Queue $indexQueue */ - $indexQueue = GeneralUtility::makeInstance(Queue::class); - $indexQueueInitializationResults = $indexQueue->getInitializationService() + /* @var QueueInitializationService $indexQueueInitializationService */ + $indexQueueInitializationService = GeneralUtility::makeInstance(QueueInitializationService::class); + $indexQueueInitializationResults = $indexQueueInitializationService ->initializeBySiteAndIndexConfigurations($this->getSite(), $this->indexingConfigurationsToReIndex); return $cleanUpResult && !in_array(false, $indexQueueInitializationResults); diff --git a/Documentation/Configuration/Reference/TxSolrIndex.rst b/Documentation/Configuration/Reference/TxSolrIndex.rst index 746624f034..3b0bd3039d 100644 --- a/Documentation/Configuration/Reference/TxSolrIndex.rst +++ b/Documentation/Configuration/Reference/TxSolrIndex.rst @@ -224,6 +224,16 @@ Defines the type to index, which is usally the database table. Sometimes you may +queue.[indexConfig].indexQueue +------------------------------ + +:Type: String +:TS Path: plugin.tx_solr.index.queue.[indexConfig].indexQueue +:Since: 11.6 +:Default: + +Class name of custom index queue implementation, falls back to the default index queue (ApacheSolrForTypo3\Solr\IndexQueue\Queue). + queue.[indexConfig].initialization ---------------------------------- diff --git a/Tests/Integration/IndexQueue/QueueTest.php b/Tests/Integration/IndexQueue/QueueTest.php index 91788de63d..3f92597471 100644 --- a/Tests/Integration/IndexQueue/QueueTest.php +++ b/Tests/Integration/IndexQueue/QueueTest.php @@ -15,6 +15,7 @@ namespace ApacheSolrForTypo3\Solr\Tests\Integration\IndexQueue; +use ApacheSolrForTypo3\Solr\Domain\Index\Queue\QueueInitializationService; use ApacheSolrForTypo3\Solr\Domain\Site\Site; use ApacheSolrForTypo3\Solr\Domain\Site\SiteRepository; use ApacheSolrForTypo3\Solr\IndexQueue\Queue; @@ -43,6 +44,7 @@ protected function setUp(): void parent::setUp(); $this->writeDefaultSolrTestSiteConfiguration(); $this->indexQueue = GeneralUtility::makeInstance(Queue::class); + $this->indexQueue->setQueueInitializationService(GeneralUtility::makeInstance(QueueInitializationService::class)); $this->siteRepository = GeneralUtility::makeInstance(SiteRepository::class); } @@ -75,7 +77,7 @@ public function preFilledQueueContainsRootPageAfterInitialize() // after initialize the prefilled queue item should be lost and the root page should be added again $site = $this->siteRepository->getFirstAvailableSite(); - $this->indexQueue->getInitializationService()->initializeBySiteAndIndexConfiguration($site, 'pages'); + $this->indexQueue->getQueueInitializationService()->initializeBySiteAndIndexConfiguration($site, 'pages'); $this->assertItemsInQueue(1); self::assertTrue($this->indexQueue->containsItem('pages', 1)); @@ -152,10 +154,10 @@ public function mountPagesAreOnlyAddedOnceAfterInitialize() $this->assertEmptyQueue(); $site = $this->siteRepository->getFirstAvailableSite(); - $this->indexQueue->getInitializationService()->initializeBySiteAndIndexConfiguration($site, 'pages'); + $this->indexQueue->getQueueInitializationService()->initializeBySiteAndIndexConfiguration($site, 'pages'); $this->assertItemsInQueue(4); - $this->indexQueue->getInitializationService()->initializeBySiteAndIndexConfiguration($site, 'pages'); + $this->indexQueue->getQueueInitializationService()->initializeBySiteAndIndexConfiguration($site, 'pages'); $this->assertItemsInQueue(4); } @@ -188,7 +190,7 @@ public function canAddCustomPageTypeToTheQueue() }' ); $site = $this->siteRepository->getFirstAvailableSite(); - $this->indexQueue->getInitializationService()->initializeBySiteAndIndexConfiguration($site, 'custom_page_type'); + $this->indexQueue->getQueueInitializationService()->initializeBySiteAndIndexConfiguration($site, 'custom_page_type'); $this->assertItemsInQueue(1); @@ -244,7 +246,7 @@ public function canInitializeMultipleSites() if (is_array($availableSites)) { foreach ($availableSites as $site) { if ($site instanceof Site) { - $this->indexQueue->getInitializationService()->initializeBySiteAndIndexConfiguration($site); + $this->indexQueue->getQueueInitializationService()->initializeBySiteAndIndexConfiguration($site); } } } diff --git a/Tests/Unit/Controller/Backend/Search/IndexQueueModuleControllerTest.php b/Tests/Unit/Controller/Backend/Search/IndexQueueModuleControllerTest.php index c1a368a329..40123fb6b2 100644 --- a/Tests/Unit/Controller/Backend/Search/IndexQueueModuleControllerTest.php +++ b/Tests/Unit/Controller/Backend/Search/IndexQueueModuleControllerTest.php @@ -16,7 +16,6 @@ namespace ApacheSolrForTypo3\Solr\Tests\Unit\Controller\Backend\Search; use ApacheSolrForTypo3\Solr\Controller\Backend\Search\IndexQueueModuleController; -use ApacheSolrForTypo3\Solr\Domain\Index\Queue\QueueInitializationService; use ApacheSolrForTypo3\Solr\Domain\Index\Queue\QueueItemRepository; use ApacheSolrForTypo3\Solr\Domain\Index\Queue\RecordMonitor\Helper\ConfigurationAwareRecordService; use ApacheSolrForTypo3\Solr\Domain\Index\Queue\RecordMonitor\Helper\RootPageResolver; @@ -57,7 +56,6 @@ protected function setUp(): void $this->createMock(ConfigurationAwareRecordService::class), $this->createMock(QueueItemRepository::class), $this->createMock(QueueStatisticsRepository::class), - $this->createMock(QueueInitializationService::class), $this->createMock(FrontendEnvironment::class), $this->eventDispatcher, ]) diff --git a/Tests/Unit/Domain/Index/Queue/QueueInitializerServiceTest.php b/Tests/Unit/Domain/Index/Queue/QueueInitializerServiceTest.php index 9f8248f536..62392ca2bb 100644 --- a/Tests/Unit/Domain/Index/Queue/QueueInitializerServiceTest.php +++ b/Tests/Unit/Domain/Index/Queue/QueueInitializerServiceTest.php @@ -38,6 +38,7 @@ use ApacheSolrForTypo3\Solr\System\Configuration\TypoScriptConfiguration; use ApacheSolrForTypo3\Solr\Tests\Unit\SetUpUnitTestCase; use TYPO3\CMS\Core\EventDispatcher\NoopEventDispatcher; +use TYPO3\CMS\Core\Utility\GeneralUtility; /** * @author Timo Hund @@ -50,7 +51,9 @@ class QueueInitializerServiceTest extends SetUpUnitTestCase public function allIndexConfigurationsAreUsedWhenWildcardIsPassed(): void { $queueMock = $this->createMock(Queue::class); - $service = $this->getMockBuilder(QueueInitializationService::class)->onlyMethods(['executeInitializer'])->setConstructorArgs([$queueMock, new NoopEventDispatcher()])->getMock(); + GeneralUtility::addInstance(Queue::class, $queueMock); + GeneralUtility::addInstance(Queue::class, $queueMock); + $service = $this->getMockBuilder(QueueInitializationService::class)->onlyMethods(['executeInitializer'])->setConstructorArgs([new NoopEventDispatcher()])->getMock(); $fakeTs = [ 'plugin.' => [ diff --git a/Tests/Unit/System/Configuration/TypoScriptConfigurationTest.php b/Tests/Unit/System/Configuration/TypoScriptConfigurationTest.php index 75c470951b..c0df7c41c3 100644 --- a/Tests/Unit/System/Configuration/TypoScriptConfigurationTest.php +++ b/Tests/Unit/System/Configuration/TypoScriptConfigurationTest.php @@ -15,6 +15,8 @@ namespace ApacheSolrForTypo3\Solr\Tests\Unit\System\Configuration; +use ApacheSolrForTypo3\Solr\IndexQueue\Initializer\Record; +use ApacheSolrForTypo3\Solr\IndexQueue\Queue; use ApacheSolrForTypo3\Solr\System\Configuration\TypoScriptConfiguration; use ApacheSolrForTypo3\Solr\Tests\Unit\SetUpUnitTestCase; @@ -316,7 +318,6 @@ public function canGetIndexQueueConfigurationNamesByTableName() 'custom_one.' => [ 'type' => 'tx_model_bar', ], - 'custom_two' => 1, 'custom_two.' => [ 'type' => 'tx_model_news', @@ -329,6 +330,54 @@ public function canGetIndexQueueConfigurationNamesByTableName() self::assertEquals(['tx_model_news', 'custom_two'], $configuration->getIndexQueueConfigurationNamesByTableName('tx_model_news')); } + /** + * @test + */ + public function canGetIndexQueueInitializerClassByConfigurationName() + { + $fakeConfigurationArray['plugin.']['tx_solr.'] = [ + 'index.' => [ + 'queue.' => [ + 'tx_model_news' => 1, + 'tx_model_news.' => [ + ], + 'custom_one' => 1, + 'custom_one.' => [ + 'initialization' => 'CustomInitializer', + ], + ], + ], + ]; + + $configuration = new TypoScriptConfiguration($fakeConfigurationArray); + self::assertEquals(Record::class, $configuration->getIndexQueueInitializerClassByConfigurationName('tx_model_news')); + self::assertEquals('CustomInitializer', $configuration->getIndexQueueInitializerClassByConfigurationName('custom_one')); + } + + /** + * @test + */ + public function canGetIndexQueueClassByConfigurationName() + { + $fakeConfigurationArray['plugin.']['tx_solr.'] = [ + 'index.' => [ + 'queue.' => [ + 'tx_model_news' => 1, + 'tx_model_news.' => [ + ], + 'custom_one' => 1, + 'custom_one.' => [ + 'indexQueue' => 'CustomQueue', + ], + ], + ], + ]; + + $configuration = new TypoScriptConfiguration($fakeConfigurationArray); + self::assertEquals(Queue::class, $configuration->getIndexQueueClassByConfigurationName('tx_model_news')); + self::assertEquals('CustomQueue', $configuration->getIndexQueueClassByConfigurationName('custom_one')); + } + /** * @test */