From 21f46bbd256fe498bac798b8d56ad4b035e0395f Mon Sep 17 00:00:00 2001 From: Benni Mack Date: Thu, 1 Jun 2023 17:33:38 +0200 Subject: [PATCH] [!!!][FEATURE] Add new PSR-14 instead of SubstitutePageIndexer $GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['solr']['Indexer']['indexPageSubstitutePageDocument'] is removed in favor of a new PSR-14 event: "ApacheSolrForTypo3\Solr\Event\Indexing\AfterPageDocumentIsCreatedForIndexingEvent" For this reason, the SubstitutePageIndexer Interface is removed. At the same time, the "Typo3PageIndexer" class is now merged into FrontendHelper/PageIndexer to avoid cross-cutting conerns between classes and to show the dependencies to TSFE properly. --- .../Search/ApacheSolrDocument/Builder.php | 20 +- ...rPageDocumentIsCreatedForIndexingEvent.php | 85 ++++ .../AdditionalFieldsForPageIndexing.php} | 27 +- .../PageFieldMappingIndexer.php | 42 +- .../IndexQueue/FrontendHelper/PageIndexer.php | 299 +++++++++---- Classes/SubstitutePageIndexer.php | 37 -- Classes/Typo3PageIndexer.php | 423 ------------------ Configuration/Services.yaml | 17 +- Documentation/Development/Indexing.rst | 34 +- Documentation/Releases/solr-release-12-0.rst | 22 + .../Controller/SearchControllerTest.php | 13 - .../Controller/SuggestControllerTest.php | 13 - .../FrontendHelper/PageIndexerTest.php | 5 - Tests/Integration/SearchTest.php | 32 +- Tests/Integration/TSFETestBootstrapper.php | 1 + ext_localconf.php | 2 - 16 files changed, 416 insertions(+), 656 deletions(-) create mode 100644 Classes/Event/Indexing/AfterPageDocumentIsCreatedForIndexingEvent.php rename Classes/{AdditionalFieldsIndexer.php => EventListener/PageIndexer/AdditionalFieldsForPageIndexing.php} (73%) delete mode 100644 Classes/SubstitutePageIndexer.php delete mode 100644 Classes/Typo3PageIndexer.php diff --git a/Classes/Domain/Search/ApacheSolrDocument/Builder.php b/Classes/Domain/Search/ApacheSolrDocument/Builder.php index 2d73d0bd17..faa08b216a 100644 --- a/Classes/Domain/Search/ApacheSolrDocument/Builder.php +++ b/Classes/Domain/Search/ApacheSolrDocument/Builder.php @@ -25,7 +25,6 @@ use ApacheSolrForTypo3\Solr\Typo3PageContentExtractor; use ApacheSolrForTypo3\Solr\Util; use Doctrine\DBAL\Exception as DBALException; -use TYPO3\CMS\Core\Context\Exception\AspectNotFoundException; use TYPO3\CMS\Core\Utility\GeneralUtility; use TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController; @@ -45,9 +44,6 @@ public function __construct( /** * This method can be used to build a Document from a TYPO3 page. - * - * @throws AspectNotFoundException - * @throws DBALException */ public function fromPage( TypoScriptFrontendController $page, @@ -55,11 +51,12 @@ public function fromPage( Rootline $pageAccessRootline, string $mountPointParameter = '', ): Document { - /** @var Document $document */ - $document = GeneralUtility::makeInstance(Document::class); - $site = $this->getSiteByPageId($page->id); + $pageId = $page->id; $pageRecord = $page->page; + $document = GeneralUtility::makeInstance(Document::class); + $site = $this->getSiteByPageId($pageId); + $accessGroups = $this->getDocumentIdGroups($pageAccessRootline); $documentId = $this->getPageDocumentId($page, $accessGroups, $mountPointParameter); @@ -70,18 +67,18 @@ public function fromPage( $document->setField('type', 'pages'); // system fields - $document->setField('uid', $page->id); + $document->setField('uid', $pageId); $document->setField('pid', $pageRecord['pid']); // variantId - $variantId = $this->variantIdBuilder->buildFromTypeAndUid('pages', $page->id); + $variantId = $this->variantIdBuilder->buildFromTypeAndUid('pages', $pageId); $document->setField('variantId', $variantId); $document->setField('typeNum', (int)$page->getPageArguments()->getPageType()); $document->setField('created', $pageRecord['crdate']); $document->setField('changed', $pageRecord['SYS_LASTCHANGED']); - $rootline = $this->getRootLineFieldValue($page->id, $mountPointParameter); + $rootline = $this->getRootLineFieldValue($pageId, $mountPointParameter); $document->setField('rootline', $rootline); // access @@ -157,12 +154,11 @@ public function fromRecord(array $itemRecord, string $type, int $rootPageUid, st } /** - * @throws AspectNotFoundException * @throws DBALException */ protected function getPageDocumentId(TypoScriptFrontendController $frontendController, string $accessGroups, string $mountPointParameter): string { - return Util::getPageDocumentId($frontendController->id, (int)$frontendController->getPageArguments()->getPageType(), Util::getLanguageUid(), $accessGroups, $mountPointParameter); + return Util::getPageDocumentId($frontendController->id, (int)$frontendController->getPageArguments()->getPageType(), $frontendController->getLanguage()->getLanguageId(), $accessGroups, $mountPointParameter); } /** diff --git a/Classes/Event/Indexing/AfterPageDocumentIsCreatedForIndexingEvent.php b/Classes/Event/Indexing/AfterPageDocumentIsCreatedForIndexingEvent.php new file mode 100644 index 0000000000..2a8922ad2a --- /dev/null +++ b/Classes/Event/Indexing/AfterPageDocumentIsCreatedForIndexingEvent.php @@ -0,0 +1,85 @@ +document; + } + + public function overrideDocument(Document $document): void + { + $this->document = $document; + } + + public function getIndexQueueItem(): Item + { + return $this->indexQueueItem; + } + + public function getIndexingConfigurationName(): string + { + return $this->indexQueueItem->getIndexingConfigurationName(); + } + + public function getSite(): Site + { + return $this->site; + } + + public function getSiteLanguage(): SiteLanguage + { + return $this->siteLanguage; + } + + public function getRecord(): array + { + return $this->record; + } + + public function getConfiguration(): TypoScriptConfiguration + { + return $this->configuration; + } +} diff --git a/Classes/AdditionalFieldsIndexer.php b/Classes/EventListener/PageIndexer/AdditionalFieldsForPageIndexing.php similarity index 73% rename from Classes/AdditionalFieldsIndexer.php rename to Classes/EventListener/PageIndexer/AdditionalFieldsForPageIndexing.php index 0e1c9e341d..77221d555a 100644 --- a/Classes/AdditionalFieldsIndexer.php +++ b/Classes/EventListener/PageIndexer/AdditionalFieldsForPageIndexing.php @@ -15,11 +15,10 @@ * The TYPO3 project - inspiring people to share! */ -namespace ApacheSolrForTypo3\Solr; +namespace ApacheSolrForTypo3\Solr\EventListener\PageIndexer; -use ApacheSolrForTypo3\Solr\System\Configuration\TypoScriptConfiguration; +use ApacheSolrForTypo3\Solr\Event\Indexing\AfterPageDocumentIsCreatedForIndexingEvent; use ApacheSolrForTypo3\Solr\System\ContentObject\ContentObjectService; -use ApacheSolrForTypo3\Solr\System\Solr\Document\Document; use TYPO3\CMS\Core\Utility\GeneralUtility; /** @@ -32,31 +31,28 @@ * * @author Ingo Renner */ -class AdditionalFieldsIndexer implements SubstitutePageIndexer +class AdditionalFieldsForPageIndexing { - protected TypoScriptConfiguration $configuration; - protected array $additionalIndexingFields = []; protected array $additionalFieldNames = []; protected ContentObjectService $contentObjectService; - public function __construct( - TypoScriptConfiguration $configuration = null, - ContentObjectService $contentObjectService = null - ) { - $this->configuration = $configuration ?? Util::getSolrConfiguration(); - $this->additionalIndexingFields = $this->configuration->getIndexAdditionalFieldsConfiguration(); - $this->additionalFieldNames = $this->configuration->getIndexMappedAdditionalFieldNames(); + public function __construct(ContentObjectService $contentObjectService = null) + { $this->contentObjectService = $contentObjectService ?? GeneralUtility::makeInstance(ContentObjectService::class); } /** * Returns a substituted document for the currently being indexed page. */ - public function getPageDocument(Document $originalPageDocument): Document + public function __invoke(AfterPageDocumentIsCreatedForIndexingEvent $event): void { + $this->additionalIndexingFields = $event->getConfiguration()->getIndexAdditionalFieldsConfiguration(); + $this->additionalFieldNames = $event->getConfiguration()->getIndexMappedAdditionalFieldNames(); + + $originalPageDocument = $event->getDocument(); $substitutePageDocument = clone $originalPageDocument; $additionalFields = $this->getAdditionalFields(); @@ -66,8 +62,7 @@ public function getPageDocument(Document $originalPageDocument): Document $substitutePageDocument->setField($fieldName, $fieldValue); } } - - return $substitutePageDocument; + $event->overrideDocument($substitutePageDocument); } /** diff --git a/Classes/IndexQueue/FrontendHelper/PageFieldMappingIndexer.php b/Classes/IndexQueue/FrontendHelper/PageFieldMappingIndexer.php index 3ccb014369..f34366e70b 100644 --- a/Classes/IndexQueue/FrontendHelper/PageFieldMappingIndexer.php +++ b/Classes/IndexQueue/FrontendHelper/PageFieldMappingIndexer.php @@ -18,12 +18,11 @@ namespace ApacheSolrForTypo3\Solr\IndexQueue\FrontendHelper; // TODO use/extend ApacheSolrForTypo3\Solr\IndexQueue\AbstractIndexer +use ApacheSolrForTypo3\Solr\Event\Indexing\AfterPageDocumentIsCreatedForIndexingEvent; use ApacheSolrForTypo3\Solr\IndexQueue\AbstractIndexer; use ApacheSolrForTypo3\Solr\IndexQueue\InvalidFieldNameException; -use ApacheSolrForTypo3\Solr\SubstitutePageIndexer; use ApacheSolrForTypo3\Solr\System\Configuration\TypoScriptConfiguration; use ApacheSolrForTypo3\Solr\System\Solr\Document\Document; -use ApacheSolrForTypo3\Solr\Util; use TYPO3\CMS\Core\Utility\GeneralUtility; use TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer; @@ -33,37 +32,24 @@ * * @author Ingo Renner */ -class PageFieldMappingIndexer implements SubstitutePageIndexer +class PageFieldMappingIndexer { protected TypoScriptConfiguration $configuration; - protected string $pageIndexingConfigurationName = 'pages'; - public function __construct(TypoScriptConfiguration $configuration = null) - { - $this->configuration = $configuration == null ? Util::getSolrConfiguration() : $configuration; - } - - public function setPageIndexingConfigurationName(string $pageIndexingConfigurationName): void - { - $this->pageIndexingConfigurationName = $pageIndexingConfigurationName; - } - /** - * Returns a substitute document for the currently being indexed page. + * Builds a substitute document for the currently being indexed page. * * Uses the original document and adds fields as defined in * plugin.tx_solr.index.queue.pages.fields. - * - * @param Document $originalPageDocument The original page document. - * - * @return Document A Apache Solr Document object that replace the default page document */ - public function getPageDocument(Document $originalPageDocument): Document + public function __invoke(AfterPageDocumentIsCreatedForIndexingEvent $event): void { - $substitutePageDocument = clone $originalPageDocument; + $substitutePageDocument = clone $event->getDocument(); + $this->configuration = $event->getConfiguration(); + $this->pageIndexingConfigurationName = $event->getIndexingConfigurationName(); - $mappedFields = $this->getMappedFields($originalPageDocument); + $mappedFields = $this->getMappedFields($event->getDocument(), $event->getRecord()); foreach ($mappedFields as $fieldName => $fieldValue) { if (isset($substitutePageDocument->{$fieldName})) { // reset = overwrite, especially important to not make fields @@ -77,19 +63,18 @@ public function getPageDocument(Document $originalPageDocument): Document } } - return $substitutePageDocument; + $event->overrideDocument($substitutePageDocument); } /** * Gets the mapped fields as an array mapping field names to values. * * @param Document $pageDocument The original page document. - * * @return array An array mapping field names to their values. * * @throws InvalidFieldNameException */ - protected function getMappedFields(Document $pageDocument): array + protected function getMappedFields(Document $pageDocument, array $pageRecord): array { $fields = []; @@ -102,7 +87,7 @@ protected function getMappedFields(Document $pageDocument): array 1435441863 ); } - $fields[$mappedFieldName] = $this->resolveFieldValue($mappedFieldName, $pageDocument); + $fields[$mappedFieldName] = $this->resolveFieldValue($mappedFieldName, $pageDocument, $pageRecord); } return $fields; @@ -115,13 +100,10 @@ protected function getMappedFields(Document $pageDocument): array * Otherwise, the plain page record field value is used. * * @param string $solrFieldName The Solr field name to resolve the value from the item's record - * * @return string|array The resolved value to be indexed */ - protected function resolveFieldValue(string $solrFieldName, Document $pageDocument): array|string + protected function resolveFieldValue(string $solrFieldName, Document $pageDocument, array $pageRecord): array|string { - $pageRecord = $GLOBALS['TSFE']->page; - $pageIndexingConfiguration = $this->configuration->getIndexQueueFieldsConfigurationByConfigurationName($this->pageIndexingConfigurationName); if (isset($pageIndexingConfiguration[$solrFieldName . '.'])) { diff --git a/Classes/IndexQueue/FrontendHelper/PageIndexer.php b/Classes/IndexQueue/FrontendHelper/PageIndexer.php index 8475dc516d..27158ed7ae 100644 --- a/Classes/IndexQueue/FrontendHelper/PageIndexer.php +++ b/Classes/IndexQueue/FrontendHelper/PageIndexer.php @@ -17,27 +17,39 @@ use ApacheSolrForTypo3\Solr\Access\Rootline; use ApacheSolrForTypo3\Solr\ConnectionManager; +use ApacheSolrForTypo3\Solr\Domain\Search\ApacheSolrDocument\Builder; +use ApacheSolrForTypo3\Solr\Event\Indexing\AfterPageDocumentIsCreatedForIndexingEvent; +use ApacheSolrForTypo3\Solr\Event\Indexing\BeforeDocumentsAreIndexedEvent; +use ApacheSolrForTypo3\Solr\Event\Indexing\BeforePageDocumentIsProcessedForIndexingEvent; +use ApacheSolrForTypo3\Solr\Exception; +use ApacheSolrForTypo3\Solr\FieldProcessor\Service; use ApacheSolrForTypo3\Solr\IndexQueue\Item; use ApacheSolrForTypo3\Solr\IndexQueue\Queue; use ApacheSolrForTypo3\Solr\NoSolrConnectionFoundException; +use ApacheSolrForTypo3\Solr\System\Configuration\TypoScriptConfiguration; use ApacheSolrForTypo3\Solr\System\Logging\DebugWriter; use ApacheSolrForTypo3\Solr\System\Logging\SolrLogManager; +use ApacheSolrForTypo3\Solr\System\Solr\Document\Document; use ApacheSolrForTypo3\Solr\System\Solr\SolrConnection; -use ApacheSolrForTypo3\Solr\Typo3PageIndexer; use ApacheSolrForTypo3\Solr\Util; use Doctrine\DBAL\Exception as DBALException; +use Psr\EventDispatcher\EventDispatcherInterface; use Throwable; use TYPO3\CMS\Core\Context\Exception\AspectNotFoundException; +use TYPO3\CMS\Core\Site\Entity\Site; +use TYPO3\CMS\Core\Site\Entity\SiteLanguage; use TYPO3\CMS\Core\Utility\ExtensionManagementUtility; use TYPO3\CMS\Core\Utility\GeneralUtility; -use TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer; +use TYPO3\CMS\Core\Utility\MathUtility; use TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController; use TYPO3\CMS\Frontend\Event\AfterCacheableContentIsGeneratedEvent; use UnexpectedValueException; /** - * Index Queue Page Indexer frontend helper to ask the frontend page indexer to - * index the page. + * Index Queue Page Indexer frontend helper to validate if a page + * should be used by the Index Queue. + * + * Once the FrontendHelper construct is separated, this will be a standalone Indexer. * * @author Ingo Renner */ @@ -49,14 +61,21 @@ class PageIndexer extends AbstractFrontendHelper protected string $action = 'indexPage'; /** - * the page currently being indexed. + * Response data */ - protected TypoScriptFrontendController $page; + protected array $responseData = []; /** - * Response data + * Solr server connection. */ - protected array $responseData = []; + protected ?SolrConnection $solrConnection = null; + + /** + * Documents that have been sent to Solr + */ + protected array $documentsSentToSolr = []; + + protected ?TypoScriptConfiguration $configuration = null; /** * Activates a frontend helper by registering for hooks and other @@ -67,10 +86,6 @@ class PageIndexer extends AbstractFrontendHelper public function activate(): void { $this->isActivated = true; - - // indexes fields defined in plugin.tx_solr.index.queue.pages.fields - $GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['solr']['Indexer']['indexPageSubstitutePageDocument'][PageFieldMappingIndexer::class] = PageFieldMappingIndexer::class; - $this->registerAuthorizationService(); } @@ -94,7 +109,7 @@ protected function getAccessRootline(): Rootline { $stringAccessRootline = ''; - if ($this->request->getParameter('accessRootline')) { + if ($this->request?->getParameter('accessRootline')) { $stringAccessRootline = $this->request->getParameter('accessRootline'); } @@ -158,35 +173,23 @@ protected function getHighestAuthenticationServicePriority(): int /** * Generates the current page's URL as string. - * Uses the provided GET parameters, page id and language id. + * Uses the provided parameters from TSFE, page id and language id. */ - protected function generatePageUrl(): string + protected function generatePageUrl(TypoScriptFrontendController $controller): string { - if ($this->request->getParameter('overridePageUrl')) { + if ($this->request?->getParameter('overridePageUrl')) { return $this->request->getParameter('overridePageUrl'); } - /** @var ContentObjectRenderer $contentObject */ - $contentObject = GeneralUtility::makeInstance(ContentObjectRenderer::class); - - $typolinkConfiguration = [ - 'parameter' => $this->page->id, - 'linkAccessRestrictedPages' => '1', - ]; - - $language = GeneralUtility::_GET('L'); - if (!empty($language)) { - $typolinkConfiguration['additionalParams'] = '&L=' . $language; + $parameter = $controller->page['uid']; + $type = $controller->getPageArguments()->getPageType(); + if ($type && MathUtility::canBeInterpretedAsInteger($type)) { + $parameter .= ',' . $type; } - - $url = $contentObject->typoLink_URL($typolinkConfiguration); - - // clean up - if ($url == '') { - $url = '/'; - } - - return $url; + return $controller->cObj->createUrl([ + 'parameter' => $parameter, + 'linkAccessRestrictedPages' => '1', + ]); } /** @@ -197,14 +200,11 @@ public function __invoke(AfterCacheableContentIsGeneratedEvent $event): void if (!$this->isActivated) { return; } + $this->setupConfiguration(); + $tsfe = $event->getController(); - $this->logger = new SolrLogManager(__CLASS__, GeneralUtility::makeInstance(DebugWriter::class)); - - $this->page = $event->getController(); - $configuration = Util::getSolrConfiguration(); - - $logPageIndexed = $configuration->getLoggingIndexingPageIndexed(); - if (!($this->page->config['config']['index_enable'] ?? false)) { + $logPageIndexed = $this->configuration->getLoggingIndexingPageIndexed(); + if (!($tsfe->config['config']['index_enable'] ?? false)) { if ($logPageIndexed) { $this->logger->log( SolrLogManager::ERROR, @@ -216,38 +216,16 @@ public function __invoke(AfterCacheableContentIsGeneratedEvent $event): void try { $indexQueueItem = $this->getIndexQueueItem(); - if (is_null($indexQueueItem)) { + if ($indexQueueItem === null) { throw new UnexpectedValueException('Can not get index queue item', 1482162337); } - - $solrConnection = $this->getSolrConnection($indexQueueItem); - - /** @var Typo3PageIndexer $indexer */ - $indexer = GeneralUtility::makeInstance(Typo3PageIndexer::class, $this->page); - $indexer->setSolrConnection($solrConnection); - $indexer->setPageAccessRootline($this->getAccessRootline()); - $indexer->setPageUrl($this->generatePageUrl()); - $indexer->setMountPointParameter($GLOBALS['TSFE']->MP); - $indexer->setIndexQueueItem($indexQueueItem); - - $this->responseData['pageIndexed'] = (int)$indexer->indexPage(); - $this->responseData['originalPageDocument'] = (array)$indexer->getPageSolrDocument(); - $this->responseData['solrConnection'] = [ - 'rootPage' => $indexQueueItem->getRootPageUid(), - 'sys_language_uid' => Util::getLanguageUid(), - 'solr' => (string)$solrConnection->getNode('write'), - ]; - - $documentsSentToSolr = $indexer->getDocumentsSentToSolr(); - foreach ($documentsSentToSolr as $document) { - $this->responseData['documentsSentToSolr'][] = (array)$document; - } + $this->index($indexQueueItem, $tsfe); } catch (Throwable $e) { $this->responseData['pageIndexed'] = false; - if ($configuration->getLoggingExceptions()) { + if ($this->configuration->getLoggingExceptions()) { $this->logger->log( SolrLogManager::ERROR, - 'Exception while trying to index page ' . $this->page->id, + 'Exception while trying to index page ' . $tsfe->id, [ $e->__toString(), ] @@ -267,23 +245,66 @@ public function __invoke(AfterCacheableContentIsGeneratedEvent $event): void } } + /** + * @internal currently only public for tests + */ + public function index(Item $indexQueueItem, TypoScriptFrontendController $tsfe): void + { + $this->solrConnection = $this->getSolrConnection($indexQueueItem, $tsfe->getLanguage(), $this->configuration->getLoggingExceptions()); + + $document = $this->getPageDocument($tsfe, $this->generatePageUrl($tsfe), $this->getAccessRootline(), $tsfe->MP); + $document = $this->substitutePageDocument($document, $tsfe->getSite(), $tsfe->getLanguage(), $tsfe->page, $indexQueueItem); + + $this->responseData['pageIndexed'] = (int)$this->indexPage($document, $indexQueueItem, $tsfe->getSite(), $tsfe->getLanguage()); + $this->responseData['originalPageDocument'] = (array)$document; + $this->responseData['solrConnection'] = [ + 'rootPage' => $indexQueueItem->getRootPageUid(), + 'sys_language_uid' => $tsfe->getLanguage()->getLanguageId(), + 'solr' => (string)$this->solrConnection->getNode('write'), + ]; + + foreach ($this->documentsSentToSolr as $document) { + $this->responseData['documentsSentToSolr'][] = (array)$document; + } + } + /** * Gets the solr connection to use for indexing the page based on the * Index Queue item's properties. * - * @throws AspectNotFoundException * @throws NoSolrConnectionFoundException * @throws DBALException */ - protected function getSolrConnection(Item $indexQueueItem): SolrConnection + protected function getSolrConnection(Item $indexQueueItem, SiteLanguage $siteLanguage, bool $logExceptions): SolrConnection { - /** @var ConnectionManager $connectionManager */ $connectionManager = GeneralUtility::makeInstance(ConnectionManager::class); + try { + $solrConnection = $connectionManager->getConnectionByRootPageId($indexQueueItem->getRootPageUid(), $siteLanguage->getLanguageId()); + if (!$solrConnection->getWriteService()->ping()) { + throw new Exception( + 'Could not connect to Solr server.', + 1323946472 + ); + } + return $solrConnection; + } catch (Throwable $e) { + $this->logger->log( + SolrLogManager::ERROR, + $e->getMessage() . ' Error code: ' . $e->getCode() + ); - return $connectionManager->getConnectionByRootPageId( - $indexQueueItem->getRootPageUid(), - Util::getLanguageUid() - ); + // TODO extract to a class "ExceptionLogger" + if ($logExceptions) { + $this->logger->log( + SolrLogManager::ERROR, + 'Exception while trying to index a page', + [ + $e->__toString(), + ] + ); + } + throw $e; + } } /** @@ -293,8 +314,132 @@ protected function getSolrConnection(Item $indexQueueItem): SolrConnection */ protected function getIndexQueueItem(): ?Item { - /** @var Queue $indexQueue */ $indexQueue = GeneralUtility::makeInstance(Queue::class); return $indexQueue->getItem($this->request->getParameter('item')); } + + /** + * Allows third party extensions to replace or modify the page document + * created by this indexer. + * + * @param Document $pageDocument The page document created by this indexer. + * @return Document An Apache Solr document representing the currently indexed page + */ + protected function substitutePageDocument(Document $pageDocument, Site $site, SiteLanguage $siteLanguage, array $pageRecord, Item $indexQueueItem): Document + { + $event = new AfterPageDocumentIsCreatedForIndexingEvent($pageDocument, $indexQueueItem, $site, $siteLanguage, $pageRecord, $this->configuration); + $event = $this->getEventDispatcher()->dispatch($event); + return $event->getDocument(); + } + + /** + * Builds the Solr document for the current page. + * + * @return Document A document representing the page + * + * @throws AspectNotFoundException + * @throws DBALException + */ + protected function getPageDocument(TypoScriptFrontendController $tsfe, string $url, Rootline $pageAccessRootline, string $mountPointParameter): Document + { + $documentBuilder = GeneralUtility::makeInstance(Builder::class); + return $documentBuilder->fromPage($tsfe, $url, $pageAccessRootline, $mountPointParameter); + } + + /** + * Indexes a page. + * + * @return bool TRUE after successfully indexing the page, FALSE on error + * + * @throws AspectNotFoundException + * @throws DBALException + * @throws Exception + */ + public function indexPage(Document $pageDocument, Item $indexQueueItem, Site $site, SiteLanguage $siteLanguage): bool + { + $event = new BeforePageDocumentIsProcessedForIndexingEvent($pageDocument, $site, $siteLanguage, $indexQueueItem); + $event = $this->getEventDispatcher()->dispatch($event); + $documents = $event->getDocuments(); + + $this->processDocuments($documents); + + $event = new BeforeDocumentsAreIndexedEvent($pageDocument, $site, $siteLanguage, $indexQueueItem, $documents); + $event = $this->getEventDispatcher()->dispatch($event); + $documents = $event->getDocuments(); + + $pageIndexed = $this->addDocumentsToSolrIndex($documents); + $this->documentsSentToSolr = $documents; + + return $pageIndexed; + } + + /** + * Sends the given documents to the field processing service which takes + * care of manipulating fields as defined in the field's configuration. + * + * @param Document[] $documents An array of documents to manipulate + * @throws DBALException + * @throws Exception + */ + protected function processDocuments(array $documents): void + { + $processingInstructions = $this->configuration?->getIndexFieldProcessingInstructionsConfiguration(); + if (is_array($processingInstructions) && !empty($processingInstructions)) { + $service = GeneralUtility::makeInstance(Service::class); + $service->processDocuments($documents, $processingInstructions); + } + } + + /** + * Adds the collected documents to the Solr index. + * + * @param Document[] $documents An array of Document objects. + * @return bool TRUE if documents were added successfully, FALSE otherwise + */ + protected function addDocumentsToSolrIndex(array $documents): bool + { + $documentsAdded = false; + + if ($documents === []) { + return false; + } + + try { + $this->logger->log(SolrLogManager::INFO, 'Adding ' . count($documents) . ' documents.', $documents); + + // chunk adds by 20 + $documentChunks = array_chunk($documents, 20); + foreach ($documentChunks as $documentChunk) { + $response = $this->solrConnection->getWriteService()->addDocuments($documentChunk); + if ($response->getHttpStatus() != 200) { + throw new \RuntimeException('Solr Request failed.', 1331834983); + } + } + + $documentsAdded = true; + } catch (Throwable $e) { + $this->logger->log(SolrLogManager::ERROR, $e->getMessage() . ' Error code: ' . $e->getCode()); + + if ($this->configuration->getLoggingExceptions()) { + $this->logger->log(SolrLogManager::ERROR, 'Exception while adding documents', [$e->__toString()]); + } + } + + return $documentsAdded; + } + + /** + * @internal only used for tests + */ + public function setupConfiguration(): void + { + // currently needed for tests, will be separated. + $this->logger = new SolrLogManager(__CLASS__, GeneralUtility::makeInstance(DebugWriter::class)); + $this->configuration = Util::getSolrConfiguration(); + } + + protected function getEventDispatcher(): EventDispatcherInterface + { + return GeneralUtility::makeInstance(EventDispatcherInterface::class); + } } diff --git a/Classes/SubstitutePageIndexer.php b/Classes/SubstitutePageIndexer.php deleted file mode 100644 index f8cb4c8a82..0000000000 --- a/Classes/SubstitutePageIndexer.php +++ /dev/null @@ -1,37 +0,0 @@ - - */ -interface SubstitutePageIndexer -{ - /** - * returns a substitute document for the currently being indexed page - * - * @param Document $originalPageDocument The original page document. - * @return Document returns an \ApacheSolrForTypo3\Solr\System\Solr\Document\Document object that replace the default page document - */ - public function getPageDocument(Document $originalPageDocument): Document; -} diff --git a/Classes/Typo3PageIndexer.php b/Classes/Typo3PageIndexer.php deleted file mode 100644 index 1e2e0c557e..0000000000 --- a/Classes/Typo3PageIndexer.php +++ /dev/null @@ -1,423 +0,0 @@ - - * @author Daniel Poetzinger - * @author Timo Schmidt - */ -class Typo3PageIndexer -{ - /** - * ID of the current page's Solr document. - */ - protected static string $pageSolrDocumentId = ''; - - /** - * The Solr document generated for the current page. - */ - protected static Document $pageSolrDocument; - - /** - * The mount point parameter used in the Frontend controller. - */ - protected string $mountPointParameter = ''; - - /** - * Solr server connection. - */ - protected ?SolrConnection $solrConnection = null; - - /** - * Frontend page object (TSFE). - */ - protected TypoScriptFrontendController $page; - - /** - * URL to be indexed as the page's URL - */ - protected string $pageUrl = ''; - - /** - * The page's access rootline - */ - protected Rootline $pageAccessRootline; - - /** - * Documents that have been sent to Solr - */ - protected array $documentsSentToSolr = []; - - protected TypoScriptConfiguration $configuration; - - protected Item $indexQueueItem; - - protected SolrLogManager $logger; - - /** - * Constructor - * - * @param TypoScriptFrontendController $page The page to index - */ - public function __construct(TypoScriptFrontendController $page) - { - $this->logger = new SolrLogManager(__CLASS__, GeneralUtility::makeInstance(DebugWriter::class)); - - $this->page = $page; - $this->pageUrl = GeneralUtility::getIndpEnv('TYPO3_REQUEST_URL'); - $this->configuration = Util::getSolrConfiguration(); - - try { - $this->initializeSolrConnection(); - } catch (Throwable $e) { - $this->logger->log( - SolrLogManager::ERROR, - $e->getMessage() . ' Error code: ' . $e->getCode() - ); - - // TODO extract to a class "ExceptionLogger" - if ($this->configuration->getLoggingExceptions()) { - $this->logger->log( - SolrLogManager::ERROR, - 'Exception while trying to index a page', - [ - $e->__toString(), - ] - ); - } - } - - $this->pageAccessRootline = GeneralUtility::makeInstance(Rootline::class, ''); - } - - public function setIndexQueueItem(Item $indexQueueItem): void - { - $this->indexQueueItem = $indexQueueItem; - } - - /** - * Initializes the Solr server connection. - * - * @throws AspectNotFoundException - * @throws DBALException - * @throws Exception - * @throws NoSolrConnectionFoundException - */ - protected function initializeSolrConnection(): void - { - $solr = GeneralUtility::makeInstance(ConnectionManager::class)->getConnectionByPageId($this->page->id, Util::getLanguageUid()); - - // do not continue if no server is available - if (!$solr->getWriteService()->ping()) { - throw new Exception( - 'No Solr instance available while trying to index a page.', - 1234790825 - ); - } - - $this->solrConnection = $solr; - } - - /** - * Gets the current page's Solr document ID. - * - * @return string The page's Solr document ID or empty string in case no document was generated yet. - */ - public static function getPageSolrDocumentId(): string - { - return self::$pageSolrDocumentId; - } - - /** - * Gets the Solr document generated for the current page. - * - * @return Document|null The page's Solr document or NULL if it has not been generated yet. - */ - public static function getPageSolrDocument(): ?Document - { - return self::$pageSolrDocument; - } - - /** - * Allows to provide a Solr server connection other than the one - * initialized by the constructor. - * - * @param SolrConnection $solrConnection Solr connection - * @throws Exception if the Solr server cannot be reached - */ - public function setSolrConnection(SolrConnection $solrConnection): void - { - if (!$solrConnection->getWriteService()->ping()) { - throw new Exception( - 'Could not connect to Solr server.', - 1323946472 - ); - } - - $this->solrConnection = $solrConnection; - } - - /** - * Indexes a page. - * - * @return bool TRUE after successfully indexing the page, FALSE on error - * - * @throws AspectNotFoundException - * @throws DBALException - * @throws Exception - */ - public function indexPage(): bool - { - if (is_null($this->solrConnection)) { - // intended early return as it doesn't make sense to continue - // and waste processing time if the solr server isn't available - // anyways - // FIXME use an exception - return false; - } - - $pageDocument = $this->getPageDocument(); - $pageDocument = $this->substitutePageDocument($pageDocument); - - self::$pageSolrDocument = $pageDocument; - $event = new BeforePageDocumentIsProcessedForIndexingEvent($pageDocument, $this->page->getSite(), $this->page->getLanguage(), $this->indexQueueItem); - $event = $this->getEventDispatcher()->dispatch($event); - $documents = $event->getDocuments(); - - $this->processDocuments($documents); - - $event = new BeforeDocumentsAreIndexedEvent($pageDocument, $this->page->getSite(), $this->page->getLanguage(), $this->indexQueueItem, $documents); - $event = $this->getEventDispatcher()->dispatch($event); - $documents = $event->getDocuments(); - - $pageIndexed = $this->addDocumentsToSolrIndex($documents); - $this->documentsSentToSolr = $documents; - - return $pageIndexed; - } - - /** - * Builds the Solr document for the current page. - * - * @return Document A document representing the page - * - * @throws AspectNotFoundException - * @throws DBALException - */ - protected function getPageDocument(): Document - { - $documentBuilder = GeneralUtility::makeInstance(Builder::class); - $document = $documentBuilder->fromPage($this->page, $this->pageUrl, $this->pageAccessRootline, $this->mountPointParameter); - - self::$pageSolrDocumentId = $document['id']; - - return $document; - } - - /** - * Gets the mount point parameter that is used in the Frontend controller. - */ - public function getMountPointParameter(): string - { - return $this->mountPointParameter; - } - - // Misc - - /** - * Sets the mount point parameter that is used in the Frontend controller. - */ - public function setMountPointParameter(string $mountPointParameter): void - { - $this->mountPointParameter = $mountPointParameter; - } - - /** - * Allows third party extensions to replace or modify the page document - * created by this indexer. - * - * @param Document $pageDocument The page document created by this indexer. - * @return Document An Apache Solr document representing the currently indexed page - */ - protected function substitutePageDocument(Document $pageDocument): Document - { - if (!is_array($GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['solr']['Indexer']['indexPageSubstitutePageDocument'] ?? null)) { - return $pageDocument; - } - - $indexConfigurationName = $this->getIndexConfigurationNameForCurrentPage(); - foreach ($GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['solr']['Indexer']['indexPageSubstitutePageDocument'] as $classReference) { - $substituteIndexer = GeneralUtility::makeInstance($classReference); - - if (!$substituteIndexer instanceof SubstitutePageIndexer) { - $message = get_class($substituteIndexer) . ' must implement interface ' . SubstitutePageIndexer::class; - throw new UnexpectedValueException($message, 1310491001); - } - - if ($substituteIndexer instanceof PageFieldMappingIndexer) { - $substituteIndexer->setPageIndexingConfigurationName($indexConfigurationName); - } - - $pageDocument = $substituteIndexer->getPageDocument($pageDocument); - } - - return $pageDocument; - } - - /** - * Retrieves the indexConfigurationName from the related queueItem, or falls back to pages when no queue item set. - */ - protected function getIndexConfigurationNameForCurrentPage(): string - { - return isset($this->indexQueueItem) ? $this->indexQueueItem->getIndexingConfigurationName() : 'pages'; - } - - /** - * Sends the given documents to the field processing service which takes - * care of manipulating fields as defined in the field's configuration. - * - * @param Document[] $documents An array of documents to manipulate - * @throws DBALException - * @throws Exception - */ - protected function processDocuments(array $documents): void - { - $processingInstructions = $this->configuration->getIndexFieldProcessingInstructionsConfiguration(); - if (count($processingInstructions) > 0) { - $service = GeneralUtility::makeInstance(Service::class); - $service->processDocuments($documents, $processingInstructions); - } - } - - /** - * Adds the collected documents to the Solr index. - * - * @param Document[] $documents An array of Document objects. - * @return bool TRUE if documents were added successfully, FALSE otherwise - */ - protected function addDocumentsToSolrIndex(array $documents): bool - { - $documentsAdded = false; - - if (!count($documents)) { - return false; - } - - try { - $this->logger->log(SolrLogManager::INFO, 'Adding ' . count($documents) . ' documents.', $documents); - - // chunk adds by 20 - $documentChunks = array_chunk($documents, 20); - foreach ($documentChunks as $documentChunk) { - $response = $this->solrConnection->getWriteService()->addDocuments($documentChunk); - if ($response->getHttpStatus() != 200) { - throw new RuntimeException('Solr Request failed.', 1331834983); - } - } - - $documentsAdded = true; - } catch (Throwable $e) { - $this->logger->log(SolrLogManager::ERROR, $e->getMessage() . ' Error code: ' . $e->getCode()); - - if ($this->configuration->getLoggingExceptions()) { - $this->logger->log(SolrLogManager::ERROR, 'Exception while adding documents', [$e->__toString()]); - } - } - - return $documentsAdded; - } - - /** - * Gets the current page's URL. - * - * @return string URL of the current page. - */ - public function getPageUrl(): string - { - return $this->pageUrl; - } - - /** - * Sets the URL to use for the page document. - * - * @param string $url The page's URL. - */ - public function setPageUrl(string $url): void - { - $this->pageUrl = $url; - } - - /** - * Gets the page's access rootline. - * - * @return Rootline The page's access rootline - */ - public function getPageAccessRootline(): Rootline - { - return $this->pageAccessRootline; - } - - /** - * Sets the page's access rootline. - * - * @param Rootline $accessRootline The page's access rootline - */ - public function setPageAccessRootline(Rootline $accessRootline): void - { - $this->pageAccessRootline = $accessRootline; - } - - /** - * Gets the documents that have been sent to Solr - * - * @return Document[] An array of Document objects - */ - public function getDocumentsSentToSolr(): array - { - return $this->documentsSentToSolr; - } - - protected function getEventDispatcher(): EventDispatcherInterface - { - return GeneralUtility::makeInstance(EventDispatcherInterface::class); - } -} diff --git a/Configuration/Services.yaml b/Configuration/Services.yaml index b02292632b..69458115d2 100644 --- a/Configuration/Services.yaml +++ b/Configuration/Services.yaml @@ -195,15 +195,28 @@ services: ### Indexing ApacheSolrForTypo3\Solr\EventListener\PageIndexer\FrontendGroupsModifier: + autowire: true tags: - name: event.listener identifier: 'solr.index.PageIndexer.FrontendUserAuthenticator' - event: TYPO3\CMS\Frontend\Authentication\ModifyResolvedFrontendGroupsEvent + ApacheSolrForTypo3\Solr\IndexQueue\FrontendHelper\PageIndexer: + autowire: true tags: - name: event.listener identifier: 'solr.index.FrontendHelper.PageIndexer.indexPageContentAfterCacheableContentIsGenerated' - event: TYPO3\CMS\Frontend\Event\AfterCacheableContentIsGeneratedEvent + + ApacheSolrForTypo3\Solr\EventListener\PageIndexer\AdditionalFieldsForPageIndexing: + autowire: true + tags: + - name: event.listener + identifier: 'solr.index.AdditionalFieldsForPageIndexing' + + ApacheSolrForTypo3\Solr\IndexQueue\FrontendHelper\PageFieldMappingIndexer: + autowire: true + tags: + - name: event.listener + identifier: 'solr.index.PageFieldMappingIndexer' ### EXT:solr content objects ApacheSolrForTypo3\Solr\ContentObject\Classification: diff --git a/Documentation/Development/Indexing.rst b/Documentation/Development/Indexing.rst index 05016731d8..66bc304b27 100644 --- a/Documentation/Development/Indexing.rst +++ b/Documentation/Development/Indexing.rst @@ -4,12 +4,12 @@ Indexing ======== -In this section i describe the possibilities to extend page indexing in EXT:solr with custom code via TYPO3 Hooks or PSR-14 events. +This section describes the possibilities to extend page indexing in EXT:solr with custom code via PSR-14 events. Page Indexing ============= -There are several points to extend the Typo3PageIndexer class and register own classes that are used during the indexing. +There are several points to extend the Page Indexer class and register own classes that are used during the indexing. BeforePageDocumentIsProcessedForIndexingEvent --------------------------------------------- @@ -43,14 +43,34 @@ The corresponding event listener class: For other records than pages, the PSR-14 Event :php:class:`ApacheSolrForTypo3\Solr\Event\Indexing\BeforeDocumentIsProcessedForIndexingEvent` can be used. -indexPageSubstitutePageDocument -------------------------------- +AfterPageDocumentIsCreatedForIndexingEvent +------------------------------------------ -Registered classes can be used to replace/substitute a Solr document of a page. +Registered event listeners can be used to replace/substitute a Solr document of a page. +Registration of an event listener in your extension's :file:`Services.yaml`: + +.. code-block:: yaml + + MyVendor\MyPackage\EventListeners\MyEventListener: + tags: + - name: event.listener + identifier: 'my-package/modify-page' + +The corresponding event listener class: + +.. code-block:: php + + use ApacheSolrForTypo3\Solr\Event\Indexing\AfterPageDocumentIsCreatedForIndexingEvent; + + class MyEventListener { + + public function __invoke(AfterPageDocumentIsCreatedForIndexingEvent $event): void + { + $event->setDocument($myCustomDocument); + } + } -Registration with: $GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['solr']['Indexer']['indexPageSubstitutePageDocument'] -Required Interface: SubstitutePageIndexer BeforeDocumentsAreIndexedEvent diff --git a/Documentation/Releases/solr-release-12-0.rst b/Documentation/Releases/solr-release-12-0.rst index 3f4b704103..f7001be5a8 100644 --- a/Documentation/Releases/solr-release-12-0.rst +++ b/Documentation/Releases/solr-release-12-0.rst @@ -18,6 +18,28 @@ Support of TYPO3 12 LTS With EXT:solr 12.0 we provide the support of TYPO3 12 LTS. +Hooks replaced by PSR-14 events +------------------------------- + +The previously available hooks and their respective interfaces have been removed from EXT:solr. + +The hook :php:`$GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['solr']['Indexer']['indexPageAddDocuments']` and its +interface :php:`ApacheSolrForTypo3\Solr\AdditionalPageIndexer` are now superseded +by the PSR-14 event :php:`ApacheSolrForTypo3\Solr\Event\Indexing\BeforePageDocumentIsProcessedForIndexingEvent`. + +The hook :php:`$GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['solr']['IndexQueueIndexer']['preAddModifyDocuments']` and its +interface :php:`ApacheSolrForTypo3\Solr\PageIndexerDocumentsModifier` are now superseded +by the PSR-14 event :php:`ApacheSolrForTypo3\Solr\Event\Indexing\BeforeDocumentIsProcessedForIndexingEvent`. + +The hook :php:`$GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['solr']['IndexQueueIndexer']['indexItemAddDocuments']` and its +interface :php:`ApacheSolrForTypo3\Solr\AdditionalIndexQueueItemIndexer` are now superseded +by the PSR-14 event :php:`ApacheSolrForTypo3\Solr\Event\Indexing\BeforeDocumentsAreIndexedEvent`. + +The hook :php:`$GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['solr']['Indexer']['indexPageSubstitutePageDocument']` and its +interface :php:`ApacheSolrForTypo3\Solr\SubstitutePageIndexer` are now superseded +by the PSR-14 event :php:`ApacheSolrForTypo3\Solr\Event\Indexing\AfterPageDocumentIsCreatedForIndexingEvent`. + + Contributors ============ diff --git a/Tests/Integration/Controller/SearchControllerTest.php b/Tests/Integration/Controller/SearchControllerTest.php index 8561124cf1..faefd81d2b 100644 --- a/Tests/Integration/Controller/SearchControllerTest.php +++ b/Tests/Integration/Controller/SearchControllerTest.php @@ -18,7 +18,6 @@ namespace ApacheSolrForTypo3\Solr\Tests\Integration\Controller; use ApacheSolrForTypo3\Solr\Controller\SearchController; -use ApacheSolrForTypo3\Solr\IndexQueue\FrontendHelper\PageFieldMappingIndexer; use ApacheSolrForTypo3\Solr\Tests\Integration\IntegrationTest; use DOMDocument; use TYPO3\CMS\Core\Http\Response; @@ -45,18 +44,6 @@ class SearchControllerTest extends IntegrationTest */ protected $searchResponse; - protected array $configurationToUseInTestInstance = [ - 'EXTCONF' => [ - 'solr' => [ - 'Indexer' => [ - 'indexPageSubstitutePageDocument' => [ - PageFieldMappingIndexer::class => PageFieldMappingIndexer::class, - ], - ], - ], - ], - ]; - protected function setUp(): void { parent::setUp(); diff --git a/Tests/Integration/Controller/SuggestControllerTest.php b/Tests/Integration/Controller/SuggestControllerTest.php index 06700d54c6..1acd45ddad 100644 --- a/Tests/Integration/Controller/SuggestControllerTest.php +++ b/Tests/Integration/Controller/SuggestControllerTest.php @@ -16,7 +16,6 @@ namespace ApacheSolrForTypo3\Solr\Tests\Integration\Controller; use ApacheSolrForTypo3\Solr\Controller\SuggestController; -use ApacheSolrForTypo3\Solr\IndexQueue\FrontendHelper\PageFieldMappingIndexer; use ApacheSolrForTypo3\Solr\Tests\Integration\IntegrationTest; use TYPO3\CMS\Core\Http\Response; use TYPO3\TestingFramework\Core\Functional\Framework\Frontend\InternalRequest; @@ -29,18 +28,6 @@ */ class SuggestControllerTest extends IntegrationTest { - protected array $configurationToUseInTestInstance = [ - 'EXTCONF' => [ - 'solr' => [ - 'Indexer' => [ - 'indexPageSubstitutePageDocument' => [ - PageFieldMappingIndexer::class => PageFieldMappingIndexer::class, - ], - ], - ], - ], - ]; - protected function setUp(): void { parent::setUp(); diff --git a/Tests/Integration/IndexQueue/FrontendHelper/PageIndexerTest.php b/Tests/Integration/IndexQueue/FrontendHelper/PageIndexerTest.php index 59c670d180..737a0a3261 100644 --- a/Tests/Integration/IndexQueue/FrontendHelper/PageIndexerTest.php +++ b/Tests/Integration/IndexQueue/FrontendHelper/PageIndexerTest.php @@ -17,7 +17,6 @@ namespace ApacheSolrForTypo3\Solr\Tests\Integration\IndexQueue\FrontendHelper; -use ApacheSolrForTypo3\Solr\AdditionalFieldsIndexer; use ApacheSolrForTypo3\Solr\IndexQueue\Item; use ApacheSolrForTypo3\Solr\Tests\Integration\IntegrationTest; use Psr\Http\Message\ResponseInterface; @@ -158,10 +157,6 @@ public function canIndexPageToCategoryRelation() */ public function canIndexPageIntoSolrWithAdditionalFields() { - //@todo additional fields indexer requires the hook to be activated which is normally done in ext_localconf.php - // this needs to be unified with the PageFieldMappingIndexer registration. - $GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['solr']['Indexer']['indexPageSubstitutePageDocument']['ApacheSolrForTypo3\Solr\AdditionalFieldsIndexer'] = AdditionalFieldsIndexer::class; - $this->importCSVDataSet(__DIR__ . '/Fixtures/can_index_with_additional_fields_into_solr.csv'); $this->indexQueuedPage(); diff --git a/Tests/Integration/SearchTest.php b/Tests/Integration/SearchTest.php index 077b4dc5bf..1c38be070a 100644 --- a/Tests/Integration/SearchTest.php +++ b/Tests/Integration/SearchTest.php @@ -22,11 +22,11 @@ use ApacheSolrForTypo3\Solr\Domain\Search\Query\ParameterBuilder\TrigramPhraseFields; use ApacheSolrForTypo3\Solr\Domain\Search\Query\Query; use ApacheSolrForTypo3\Solr\Domain\Search\Query\QueryBuilder; +use ApacheSolrForTypo3\Solr\IndexQueue\FrontendHelper\PageIndexer; use ApacheSolrForTypo3\Solr\IndexQueue\Item; use ApacheSolrForTypo3\Solr\Search; use ApacheSolrForTypo3\Solr\System\Configuration\ConfigurationManager; use ApacheSolrForTypo3\Solr\System\Configuration\TypoScriptConfiguration; -use ApacheSolrForTypo3\Solr\Typo3PageIndexer; use TYPO3\CMS\Core\Utility\GeneralUtility; use TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController; @@ -64,15 +64,12 @@ public function canSearchForADocument(): void { $this->importCSVDataSet(__DIR__ . '/Fixtures/Search/can_search.csv'); - $fakeTSFE = $this->getConfiguredTSFE(); - - $pageIndexer = GeneralUtility::makeInstance(Typo3PageIndexer::class, $fakeTSFE); - $indexQueueItemMock = $this->createMock(Item::class); - $indexQueueItemMock->expects(self::any()) - ->method('getIndexingConfigurationName') - ->willReturn('pages'); - $pageIndexer->setIndexQueueItem($indexQueueItemMock); - $pageIndexer->indexPage(); + $tsfe = $this->getConfiguredTSFE(); + $pageIndexer = GeneralUtility::makeInstance(PageIndexer::class); + $indexQueueItem = new Item(['root' => 1, 'indexing_configuration' => 'pages', 'item_type' => 'pages']); + $indexQueueItem->setRecord(['uid' => 1]); + $pageIndexer->setupConfiguration(); + $pageIndexer->index($indexQueueItem, $tsfe); $this->waitToBeVisibleInSolr(); @@ -425,15 +422,12 @@ public function explicitPhraseSearchPrecisionCanBeAdjustedByQuerySlop(): void protected function fillIndexForPhraseSearchTests(): void { for ($i = 1; $i <= 15; $i++) { - $fakeTSFE = $this->getConfiguredTSFE($i); - - $pageIndexer = GeneralUtility::makeInstance(Typo3PageIndexer::class, $fakeTSFE); - $indexQueueItemMock = $this->createMock(Item::class); - $indexQueueItemMock->expects(self::any()) - ->method('getIndexingConfigurationName') - ->willReturn('pages'); - $pageIndexer->setIndexQueueItem($indexQueueItemMock); - $pageIndexer->indexPage(); + $tsfe = $this->getConfiguredTSFE($i); + $pageIndexer = GeneralUtility::makeInstance(PageIndexer::class); + $indexQueueItem = new Item(['root' => 1, 'indexing_configuration' => 'pages', 'item_type' => 'pages']); + $indexQueueItem->setRecord(['uid' => $i]); + $pageIndexer->setupConfiguration(); + $pageIndexer->index($indexQueueItem, $tsfe); } $this->waitToBeVisibleInSolr(); } diff --git a/Tests/Integration/TSFETestBootstrapper.php b/Tests/Integration/TSFETestBootstrapper.php index 5646a90109..99e71e9e3a 100644 --- a/Tests/Integration/TSFETestBootstrapper.php +++ b/Tests/Integration/TSFETestBootstrapper.php @@ -37,6 +37,7 @@ public function bootstrap(int $pageId): TypoScriptFrontendController $TSFE->determineId($request); $GLOBALS['TYPO3_REQUEST'] = $TSFE->getFromCache($request); $TSFE->releaseLocks(); + $TSFE->newCObj($GLOBALS['TYPO3_REQUEST']); return $TSFE; } } diff --git a/ext_localconf.php b/ext_localconf.php index 30292da154..b54427c4e8 100644 --- a/ext_localconf.php +++ b/ext_localconf.php @@ -21,8 +21,6 @@ // ----- # ----- # ----- # ----- # ----- # ----- # ----- # ----- # ----- # // registering Index Queue page indexer helpers - $GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['solr']['Indexer']['indexPageSubstitutePageDocument'][\ApacheSolrForTypo3\Solr\AdditionalFieldsIndexer::class] = \ApacheSolrForTypo3\Solr\AdditionalFieldsIndexer::class; - \ApacheSolrForTypo3\Solr\IndexQueue\FrontendHelper\Manager::registerFrontendHelper( 'findUserGroups', \ApacheSolrForTypo3\Solr\IndexQueue\FrontendHelper\UserGroupDetector::class