diff --git a/Classes/Controller/AbstractBaseController.php b/Classes/Controller/AbstractBaseController.php index 5f5827aa96..bc6e64332f 100644 --- a/Classes/Controller/AbstractBaseController.php +++ b/Classes/Controller/AbstractBaseController.php @@ -31,8 +31,6 @@ use TYPO3\CMS\Extbase\Configuration\ConfigurationManagerInterface; use TYPO3\CMS\Extbase\Mvc\Controller\ActionController; use TYPO3\CMS\Extbase\Mvc\Controller\ControllerContext; -use TYPO3\CMS\Extbase\SignalSlot\Exception\InvalidSlotException; -use TYPO3\CMS\Extbase\SignalSlot\Exception\InvalidSlotReturnException; use TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer; use TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController; @@ -265,20 +263,4 @@ protected function logSolrUnavailable() $logger->log(SolrLogManager::ERROR, 'Solr server is not available'); } } - - /** - * Emits signal for various actions - * - * @param string $className Name of the class containing the signal - * @param string $signalName Name of the signal slot - * @param array $signalArguments arguments for the signal slot - * - * @return array|mixed - * @throws InvalidSlotException - * @throws InvalidSlotReturnException - */ - protected function emitActionSignal(string $className, string $signalName, array $signalArguments) - { - return $this->signalSlotDispatcher->dispatch($className, $signalName, $signalArguments)[0]; - } } diff --git a/Classes/Controller/SearchController.php b/Classes/Controller/SearchController.php index 2257d07801..c7d4f0249f 100644 --- a/Classes/Controller/SearchController.php +++ b/Classes/Controller/SearchController.php @@ -16,6 +16,9 @@ namespace ApacheSolrForTypo3\Solr\Controller; use ApacheSolrForTypo3\Solr\Domain\Search\ResultSet\SearchResultSet; +use ApacheSolrForTypo3\Solr\Event\Search\AfterFrequentlySearchedEvent; +use ApacheSolrForTypo3\Solr\Event\Search\AfterSearchEvent; +use ApacheSolrForTypo3\Solr\Event\Search\FormEvent; use ApacheSolrForTypo3\Solr\Pagination\ResultsPagination; use ApacheSolrForTypo3\Solr\Pagination\ResultsPaginator; use ApacheSolrForTypo3\Solr\System\Solr\SolrUnavailableException; @@ -25,8 +28,6 @@ use TYPO3\CMS\Core\Utility\GeneralUtility; use TYPO3\CMS\Extbase\Http\ForwardResponse; use TYPO3\CMS\Extbase\Mvc\Exception\NoSuchArgumentException; -use TYPO3\CMS\Extbase\SignalSlot\Exception\InvalidSlotException; -use TYPO3\CMS\Extbase\SignalSlot\Exception\InvalidSlotReturnException; use TYPO3\CMS\Fluid\View\TemplateView; use TYPO3Fluid\Fluid\View\ViewInterface; @@ -96,8 +97,6 @@ protected function getCustomTemplateFromConfiguration(): string * @return ResponseInterface * @throws AspectNotFoundException * @throws NoSuchArgumentException - * @throws InvalidSlotException - * @throws InvalidSlotReturnException */ public function resultsAction(): ResponseInterface { @@ -125,17 +124,27 @@ public function resultsAction(): ResponseInterface $pagination = GeneralUtility::makeInstance(ResultsPagination::class, $paginator); $pagination->setMaxPageNumbers((int)$this->typoScriptConfiguration->getMaxPaginatorLinks(0)); + /* @var AfterSearchEvent $afterSearchEvent */ + $afterSearchEvent = $this->eventDispatcher->dispatch( + new AfterSearchEvent( + $searchResultSet, + $this->getAdditionalFilters(), + $this->typoScriptConfiguration->getSearchPluginNamespace(), + $arguments, + $pagination, + $currentPage + ) + ); + $values = [ - 'additionalFilters' => $this->getAdditionalFilters(), - 'resultSet' => $searchResultSet, - 'pluginNamespace' => $this->typoScriptConfiguration->getSearchPluginNamespace(), - 'arguments' => $arguments, - 'pagination' => $pagination, - 'currentPage' => $currentPage, + 'additionalFilters' => $afterSearchEvent->getAdditionalFilters(), + 'resultSet' => $afterSearchEvent->getResultSet(), + 'pluginNamespace' => $afterSearchEvent->getPluginNamespace(), + 'arguments' => $afterSearchEvent->getArguments(), + 'pagination' => $afterSearchEvent->getPagination(), + 'currentPage' => $afterSearchEvent->getCurrentPage(), ]; - $values = $this->emitActionSignal(__CLASS__, __FUNCTION__, [$values]); - $this->view->assignMultiple($values); } catch (SolrUnavailableException $e) { return $this->handleSolrUnavailable(); @@ -148,12 +157,19 @@ public function resultsAction(): ResponseInterface */ public function formAction(): ResponseInterface { + /* @var FormEvent $formEvent */ + $formEvent = $this->eventDispatcher->dispatch( + new FormEvent( + $this->searchService->getSearch(), + $this->getAdditionalFilters(), + $this->typoScriptConfiguration->getSearchPluginNamespace() + ) + ); $values = [ - 'search' => $this->searchService->getSearch(), - 'additionalFilters' => $this->getAdditionalFilters(), - 'pluginNamespace' => $this->typoScriptConfiguration->getSearchPluginNamespace(), + 'search' => $formEvent->getSearch(), + 'additionalFilters' => $formEvent->getAdditionalFilters(), + 'pluginNamespace' => $formEvent->getPluginNamespace(), ]; - $values = $this->emitActionSignal(__CLASS__, __FUNCTION__, [$values]); $this->view->assignMultiple($values); return $this->htmlResponse(); @@ -161,6 +177,8 @@ public function formAction(): ResponseInterface /** * Frequently Searched + * + * @return ResponseInterface */ public function frequentlySearchedAction(): ResponseInterface { @@ -174,12 +192,17 @@ public function frequentlySearchedAction(): ResponseInterface $this->controllerContext->setSearchResultSet($searchResultSet); + /* @var AfterFrequentlySearchedEvent $afterFrequentlySearchedEvent*/ + $afterFrequentlySearchedEvent = $this->eventDispatcher->dispatch( + new AfterFrequentlySearchedEvent( + $searchResultSet, + $this->getAdditionalFilters() + ) + ); $values = [ - 'additionalFilters' => $this->getAdditionalFilters(), - 'resultSet' => $searchResultSet, + 'additionalFilters' => $afterFrequentlySearchedEvent->getAdditionalFilters(), + 'resultSet' => $afterFrequentlySearchedEvent->getResultSet(), ]; - $values = $this->emitActionSignal(__CLASS__, __FUNCTION__, [$values]); - $this->view->assignMultiple($values); return $this->htmlResponse(); } @@ -203,6 +226,7 @@ public function detailAction(string $documentId = ''): ResponseInterface /** * Rendered when no search is available. + * * @return ResponseInterface */ public function solrNotAvailableAction(): ResponseInterface diff --git a/Classes/Domain/Index/IndexService.php b/Classes/Domain/Index/IndexService.php index 050528fff3..c3266863a0 100644 --- a/Classes/Domain/Index/IndexService.php +++ b/Classes/Domain/Index/IndexService.php @@ -17,19 +17,23 @@ use ApacheSolrForTypo3\Solr\ConnectionManager; use ApacheSolrForTypo3\Solr\Domain\Site\Site; +use ApacheSolrForTypo3\Solr\Event\Indexing\AfterIndexItemEvent; +use ApacheSolrForTypo3\Solr\Event\Indexing\AfterIndexItemsEvent; +use ApacheSolrForTypo3\Solr\Event\Indexing\BeforeIndexItemEvent; +use ApacheSolrForTypo3\Solr\Event\Indexing\BeforeIndexItemsEvent; use ApacheSolrForTypo3\Solr\IndexQueue\Indexer; use ApacheSolrForTypo3\Solr\IndexQueue\Item; use ApacheSolrForTypo3\Solr\IndexQueue\Queue; use ApacheSolrForTypo3\Solr\System\Configuration\TypoScriptConfiguration; use ApacheSolrForTypo3\Solr\System\Logging\SolrLogManager; use ApacheSolrForTypo3\Solr\Task\IndexQueueWorkerTask; +use Doctrine\DBAL\ConnectionException; +use Doctrine\DBAL\Driver\Exception; +use Psr\EventDispatcher\EventDispatcherInterface; use RuntimeException; use Solarium\Exception\HttpException; use Throwable; use TYPO3\CMS\Core\Utility\GeneralUtility; -use TYPO3\CMS\Extbase\SignalSlot\Dispatcher; -use TYPO3\CMS\Extbase\SignalSlot\Exception\InvalidSlotException; -use TYPO3\CMS\Extbase\SignalSlot\Exception\InvalidSlotReturnException; /** * Service to perform indexing operations @@ -54,9 +58,9 @@ class IndexService protected Queue $indexQueue; /** - * @var Dispatcher + * @var EventDispatcherInterface */ - protected $signalSlotDispatcher; + protected EventDispatcherInterface $eventDispatcher; /** * @var SolrLogManager @@ -67,18 +71,18 @@ class IndexService * IndexService constructor. * @param Site $site * @param Queue|null $queue - * @param Dispatcher|null $dispatcher + * @param EventDispatcherInterface|null $eventDispatcher * @param SolrLogManager|null $solrLogManager */ public function __construct( Site $site, Queue $queue = null, - Dispatcher $dispatcher = null, + EventDispatcherInterface $eventDispatcher = null, SolrLogManager $solrLogManager = null ) { $this->site = $site; $this->indexQueue = $queue ?? GeneralUtility::makeInstance(Queue::class); - $this->signalSlotDispatcher = $dispatcher ?? GeneralUtility::makeInstance(Dispatcher::class); + $this->eventDispatcher = $eventDispatcher ?? GeneralUtility::makeInstance(EventDispatcherInterface::class); $this->logger = $solrLogManager ?? GeneralUtility::makeInstance(SolrLogManager::class, /** @scrutinizer ignore-type */ __CLASS__); } @@ -91,7 +95,7 @@ public function setContextTask(IndexQueueWorkerTask $contextTask) } /** - * @return IndexQueueWorkerTask + * @return IndexQueueWorkerTask|null */ public function getContextTask(): ?IndexQueueWorkerTask { @@ -103,8 +107,10 @@ public function getContextTask(): ?IndexQueueWorkerTask * * @param int $limit * @return bool - * @throws InvalidSlotException - * @throws InvalidSlotReturnException + * @throws Throwable + * @throws ConnectionException + * @throws Exception + * @throws \Doctrine\DBAL\Exception */ public function indexItems(int $limit): bool { @@ -116,14 +122,19 @@ public function indexItems(int $limit): bool // get items to index $itemsToIndex = $this->indexQueue->getItemsToIndex($this->site, $limit); - $this->emitSignal('beforeIndexItems', [$itemsToIndex, $this->getContextTask(), $indexRunId]); + $beforeIndexItemsEvent = new BeforeIndexItemsEvent($itemsToIndex, $this->getContextTask(), $indexRunId); + $beforeIndexItemsEvent = $this->eventDispatcher->dispatch($beforeIndexItemsEvent); + $itemsToIndex = $beforeIndexItemsEvent->getItems(); foreach ($itemsToIndex as $itemToIndex) { try { // try indexing - $this->emitSignal('beforeIndexItem', [$itemToIndex, $this->getContextTask(), $indexRunId]); + $beforeIndexItemEvent = new BeforeIndexItemEvent($itemToIndex, $this->getContextTask(), $indexRunId); + $beforeIndexItemEvent = $this->eventDispatcher->dispatch($beforeIndexItemEvent); + $itemToIndex = $beforeIndexItemEvent->getItem(); $this->indexItem($itemToIndex, $configurationToUse); - $this->emitSignal('afterIndexItem', [$itemToIndex, $this->getContextTask(), $indexRunId]); + $afterIndexItemEvent = new AfterIndexItemEvent($itemToIndex, $this->getContextTask(), $indexRunId); + $this->eventDispatcher->dispatch($afterIndexItemEvent); } catch (Throwable $e) { $errors++; $this->indexQueue->markItemAsFailed($itemToIndex, $e->getCode() . ': ' . $e->__toString()); @@ -131,7 +142,8 @@ public function indexItems(int $limit): bool } } - $this->emitSignal('afterIndexItems', [$itemsToIndex, $this->getContextTask(), $indexRunId]); + $afterIndexItemsEvent = new AfterIndexItemsEvent($itemsToIndex, $this->getContextTask(), $indexRunId); + $this->eventDispatcher->dispatch($afterIndexItemsEvent); if ($enableCommitsSetting && count($itemsToIndex) > 0) { $solrServers = GeneralUtility::makeInstance(ConnectionManager::class)->getConnectionsBySite($this->site); @@ -165,20 +177,6 @@ protected function generateIndexingErrorLog(Item $itemToIndex, Throwable $e) ); } - /** - * Builds an emits a signal for the IndexService. - * - * @param string $name - * @param array $arguments - * @return mixed - * @throws InvalidSlotException - * @throws InvalidSlotReturnException - */ - protected function emitSignal(string $name, array $arguments = []) - { - return $this->signalSlotDispatcher->dispatch(__CLASS__, $name, $arguments); - } - /** * Indexes an item from the Index Queue. * diff --git a/Classes/Domain/Search/ResultSet/Facets/OptionBased/Options/OptionsFacetParser.php b/Classes/Domain/Search/ResultSet/Facets/OptionBased/Options/OptionsFacetParser.php index 5eaf293b7b..998329179d 100644 --- a/Classes/Domain/Search/ResultSet/Facets/OptionBased/Options/OptionsFacetParser.php +++ b/Classes/Domain/Search/ResultSet/Facets/OptionBased/Options/OptionsFacetParser.php @@ -20,11 +20,10 @@ use ApacheSolrForTypo3\Solr\Domain\Search\ResultSet\Facets\AbstractFacet; use ApacheSolrForTypo3\Solr\Domain\Search\ResultSet\Facets\AbstractFacetParser; use ApacheSolrForTypo3\Solr\Domain\Search\ResultSet\SearchResultSet; +use ApacheSolrForTypo3\Solr\Event\Parser\AfterFacetParsedEvent; use ApacheSolrForTypo3\Solr\System\Solr\ResponseAdapter; +use Psr\EventDispatcher\EventDispatcherInterface; use TYPO3\CMS\Core\Utility\GeneralUtility; -use TYPO3\CMS\Extbase\SignalSlot\Dispatcher; -use TYPO3\CMS\Extbase\SignalSlot\Exception\InvalidSlotException; -use TYPO3\CMS\Extbase\SignalSlot\Exception\InvalidSlotReturnException; /** * Class OptionsFacetParser @@ -32,16 +31,16 @@ class OptionsFacetParser extends AbstractFacetParser { /** - * @var Dispatcher|null + * @var EventDispatcherInterface|null */ - protected ?Dispatcher $dispatcher = null; + protected ?EventDispatcherInterface $eventDispatcher; /** - * @param Dispatcher $dispatcher + * @param EventDispatcherInterface $eventDispatcher */ - public function injectDispatcher(Dispatcher $dispatcher) + public function injectEventDispatcher(EventDispatcherInterface $eventDispatcher) { - $this->dispatcher = $dispatcher; + $this->eventDispatcher = $eventDispatcher; } /** @@ -49,8 +48,6 @@ public function injectDispatcher(Dispatcher $dispatcher) * @param string $facetName * @param array $facetConfiguration * @return OptionsFacet|null - * @throws InvalidSlotException - * @throws InvalidSlotReturnException */ public function parse(SearchResultSet $resultSet, string $facetName, array $facetConfiguration): ?AbstractFacet { @@ -110,8 +107,11 @@ public function parse(SearchResultSet $resultSet, string $facetName, array $face $this->applyManualSortOrder($facet, $facetConfiguration); $this->applyReverseOrder($facet, $facetConfiguration); - if (!is_null($this->dispatcher)) { - $this->dispatcher->dispatch(__CLASS__, 'optionsParsed', [&$facet, $facetConfiguration]); + if (isset($this->eventDispatcher)) { + /* @var AfterFacetParsedEvent $afterFacetParsedEvent */ + $afterFacetParsedEvent = $this->eventDispatcher + ->dispatch(new AfterFacetParsedEvent($facet, $facetConfiguration)); + $facet = $afterFacetParsedEvent->getFacet(); } return $facet; diff --git a/Classes/Event/Indexing/AfterIndexItemEvent.php b/Classes/Event/Indexing/AfterIndexItemEvent.php new file mode 100644 index 0000000000..903ad1b04b --- /dev/null +++ b/Classes/Event/Indexing/AfterIndexItemEvent.php @@ -0,0 +1,77 @@ + + */ +final class AfterIndexItemEvent +{ + /** + * @var Item + */ + private Item $item; + + /** + * @var IndexQueueWorkerTask|null + */ + private ?IndexQueueWorkerTask $task; + + private string $runId; + + /** + * @param Item $item + * @param IndexQueueWorkerTask|null $task + * @param string $runId + */ + public function __construct(Item $item, ?IndexQueueWorkerTask $task, string $runId) + { + $this->item = $item; + $this->task = $task; + $this->runId = $runId; + } + + /** + * @return Item + */ + public function getItem(): Item + { + return $this->item; + } + + /** + * @return IndexQueueWorkerTask|null + */ + public function getTask(): ?IndexQueueWorkerTask + { + return $this->task; + } + + /** + * @return string + */ + public function getRunId(): string + { + return $this->runId; + } +} diff --git a/Classes/Event/Indexing/AfterIndexItemsEvent.php b/Classes/Event/Indexing/AfterIndexItemsEvent.php new file mode 100644 index 0000000000..d522eccdf5 --- /dev/null +++ b/Classes/Event/Indexing/AfterIndexItemsEvent.php @@ -0,0 +1,85 @@ + + */ +final class AfterIndexItemsEvent +{ + /** + * @var array + */ + private array $items; + + /** + * @var IndexQueueWorkerTask|null + */ + private ?IndexQueueWorkerTask $task; + + private string $runId; + + /** + * @param array $items + * @param IndexQueueWorkerTask|null $task + * @param string $runId + */ + public function __construct(array $items, ?IndexQueueWorkerTask $task, string $runId) + { + $this->items = $items; + $this->task = $task; + $this->runId = $runId; + } + + /** + * @return array + */ + public function getItems(): array + { + return $this->items; + } + + /** + * @param array $items + */ + public function setItems(array $items): void + { + $this->items = $items; + } + + /** + * @return IndexQueueWorkerTask|null + */ + public function getTask(): ?IndexQueueWorkerTask + { + return $this->task; + } + + /** + * @return string + */ + public function getRunId(): string + { + return $this->runId; + } +} diff --git a/Classes/Event/Indexing/BeforeIndexItemEvent.php b/Classes/Event/Indexing/BeforeIndexItemEvent.php new file mode 100644 index 0000000000..3593d6d667 --- /dev/null +++ b/Classes/Event/Indexing/BeforeIndexItemEvent.php @@ -0,0 +1,85 @@ + + */ +final class BeforeIndexItemEvent +{ + /** + * @var Item + */ + private Item $item; + + /** + * @var IndexQueueWorkerTask|null + */ + private ?IndexQueueWorkerTask $task; + + private string $runId; + + /** + * @param Item $item + * @param IndexQueueWorkerTask|null $task + * @param string $runId + */ + public function __construct(Item $item, ?IndexQueueWorkerTask $task, string $runId) + { + $this->item = $item; + $this->task = $task; + $this->runId = $runId; + } + + /** + * @return Item + */ + public function getItem(): Item + { + return $this->item; + } + + /** + * @param Item $item + */ + public function setItem(Item $item): void + { + $this->item = $item; + } + + /** + * @return IndexQueueWorkerTask|null + */ + public function getTask(): ?IndexQueueWorkerTask + { + return $this->task; + } + + /** + * @return string + */ + public function getRunId(): string + { + return $this->runId; + } +} diff --git a/Classes/Event/Indexing/BeforeIndexItemsEvent.php b/Classes/Event/Indexing/BeforeIndexItemsEvent.php new file mode 100644 index 0000000000..018a8b26e9 --- /dev/null +++ b/Classes/Event/Indexing/BeforeIndexItemsEvent.php @@ -0,0 +1,85 @@ + + */ +final class BeforeIndexItemsEvent +{ + /** + * @var array + */ + private array $items; + + /** + * @var IndexQueueWorkerTask|null + */ + private ?IndexQueueWorkerTask $task; + + private string $runId; + + /** + * @param array $items + * @param IndexQueueWorkerTask|null $task + * @param string $runId + */ + public function __construct(array $items, ?IndexQueueWorkerTask $task, string $runId) + { + $this->items = $items; + $this->task = $task; + $this->runId = $runId; + } + + /** + * @return array + */ + public function getItems(): array + { + return $this->items; + } + + /** + * @param array $items + */ + public function setItems(array $items): void + { + $this->items = $items; + } + + /** + * @return IndexQueueWorkerTask|null + */ + public function getTask(): ?IndexQueueWorkerTask + { + return $this->task; + } + + /** + * @return string + */ + public function getRunId(): string + { + return $this->runId; + } +} diff --git a/Classes/Event/Parser/AfterFacetParsedEvent.php b/Classes/Event/Parser/AfterFacetParsedEvent.php new file mode 100644 index 0000000000..01476d91b4 --- /dev/null +++ b/Classes/Event/Parser/AfterFacetParsedEvent.php @@ -0,0 +1,78 @@ + + */ +final class AfterFacetParsedEvent +{ + /** + * The facet that was processed + * + * @var AbstractFacet + */ + private AbstractFacet $facet; + + /** + * The configuration of the facet + * + * @var array + */ + private array $facetConfiguration; + + /** + * @param AbstractFacet $facet + * @param array $facetConfiguration + */ + public function __construct(AbstractFacet $facet, array $facetConfiguration) + { + $this->facet = $facet; + $this->facetConfiguration = $facetConfiguration; + } + + /** + * Returns the class name of the facet + * + * @return string + */ + public function getFacetType(): string + { + return get_class($this->facet); + } + + /** + * @return AbstractFacet + */ + public function getFacet(): AbstractFacet + { + return $this->facet; + } + + /** + * @return array + */ + public function getFacetConfiguration(): array + { + return $this->facetConfiguration; + } +} diff --git a/Classes/Event/Search/AfterFrequentlySearchedEvent.php b/Classes/Event/Search/AfterFrequentlySearchedEvent.php new file mode 100644 index 0000000000..63068d4da5 --- /dev/null +++ b/Classes/Event/Search/AfterFrequentlySearchedEvent.php @@ -0,0 +1,58 @@ + + */ +final class AfterFrequentlySearchedEvent +{ + private SearchResultSet $resultSet; + private array $additionalFilters; + + /** + * @param SearchResultSet $resultSet + * @param array $additionalFilters + */ + public function __construct(SearchResultSet $resultSet, array $additionalFilters) + { + $this->resultSet = $resultSet; + $this->additionalFilters = $additionalFilters; + } + + /** + * @return SearchResultSet + */ + public function getResultSet(): SearchResultSet + { + return $this->resultSet; + } + + /** + * @return array + */ + public function getAdditionalFilters(): array + { + return $this->additionalFilters; + } +} diff --git a/Classes/Event/Search/AfterSearchEvent.php b/Classes/Event/Search/AfterSearchEvent.php new file mode 100644 index 0000000000..24d158eb42 --- /dev/null +++ b/Classes/Event/Search/AfterSearchEvent.php @@ -0,0 +1,108 @@ + + */ +final class AfterSearchEvent +{ + private SearchResultSet $resultSet; + private array $additionalFilters; + private string $pluginNamespace; + private array $arguments; + private ResultsPagination $pagination; + private int $currentPage; + + /** + * @param SearchResultSet $resultSet + * @param array $additionalFilters + * @param string $pluginNamespace + * @param array $arguments + * @param ResultsPagination $pagination + * @param int $currentPage + */ + public function __construct( + SearchResultSet $resultSet, + array $additionalFilters, + string $pluginNamespace, + array $arguments, + ResultsPagination $pagination, + int $currentPage + ) { + $this->resultSet = $resultSet; + $this->additionalFilters = $additionalFilters; + $this->pluginNamespace = $pluginNamespace; + $this->arguments = $arguments; + $this->pagination = $pagination; + $this->currentPage = $currentPage; + } + + /** + * @return SearchResultSet + */ + public function getResultSet(): SearchResultSet + { + return $this->resultSet; + } + + /** + * @return array + */ + public function getAdditionalFilters(): array + { + return $this->additionalFilters; + } + + /** + * @return string + */ + public function getPluginNamespace(): string + { + return $this->pluginNamespace; + } + + /** + * @return array + */ + public function getArguments(): array + { + return $this->arguments; + } + + /** + * @return ResultsPagination + */ + public function getPagination(): ResultsPagination + { + return $this->pagination; + } + + /** + * @return int + */ + public function getCurrentPage(): int + { + return $this->currentPage; + } +} diff --git a/Classes/Event/Search/FormEvent.php b/Classes/Event/Search/FormEvent.php new file mode 100644 index 0000000000..52098b4801 --- /dev/null +++ b/Classes/Event/Search/FormEvent.php @@ -0,0 +1,68 @@ + + */ +final class FormEvent +{ + private Search $search; + private array $additionalFilters; + private string $pluginNamespace; + + /** + * @param Search $search + * @param array $additionalFilters + * @param string $pluginNamespace + */ + public function __construct(Search $search, array $additionalFilters, string $pluginNamespace) + { + $this->search = $search; + $this->additionalFilters = $additionalFilters; + $this->pluginNamespace = $pluginNamespace; + } + + /** + * @return Search + */ + public function getSearch(): Search + { + return $this->search; + } + + /** + * @return array + */ + public function getAdditionalFilters(): array + { + return $this->additionalFilters; + } + + /** + * @return string + */ + public function getPluginNamespace(): string + { + return $this->pluginNamespace; + } +} diff --git a/Classes/Task/IndexQueueWorkerTask.php b/Classes/Task/IndexQueueWorkerTask.php index cf9be69269..76ae1f608a 100644 --- a/Classes/Task/IndexQueueWorkerTask.php +++ b/Classes/Task/IndexQueueWorkerTask.php @@ -24,8 +24,6 @@ use Doctrine\DBAL\Driver\Exception as DBALDriverException; use TYPO3\CMS\Core\Core\Environment; use TYPO3\CMS\Core\Utility\GeneralUtility; -use TYPO3\CMS\Extbase\SignalSlot\Exception\InvalidSlotException; -use TYPO3\CMS\Extbase\SignalSlot\Exception\InvalidSlotReturnException; use TYPO3\CMS\Scheduler\ProgressProviderInterface; /** @@ -52,8 +50,6 @@ class IndexQueueWorkerTask extends AbstractSolrTask implements ProgressProviderI * @return bool Returns TRUE on success, FALSE if no items were indexed or none were found. * * @throws DBALDriverException - * @throws InvalidSlotException - * @throws InvalidSlotReturnException * @throws WebRootAllReadyDefinedException * * @noinspection PhpMissingReturnTypeInspection See {@link \TYPO3\CMS\Scheduler\Task\AbstractTask::execute()} diff --git a/Documentation/Development/Index.rst b/Documentation/Development/Index.rst index f427c2b450..848b365347 100644 --- a/Documentation/Development/Index.rst +++ b/Documentation/Development/Index.rst @@ -18,5 +18,5 @@ There are many ways to extend and hook into EXT:solr to customize EXT:solr for y Environment CI CodeStructure - Signals + Events ViewHelpers diff --git a/Documentation/Development/Signals.rst b/Documentation/Development/Signals.rst deleted file mode 100644 index a229bc2d40..0000000000 --- a/Documentation/Development/Signals.rst +++ /dev/null @@ -1,48 +0,0 @@ -======== -Signals -======== -Signals are currently only used in the search controller. Every action emits a signal which can be used to change its variables assigned to the view. - - -Example -^^^^^^^ -As an example, the action ``resultsAction`` of the ``Classes/Controller/SearchController`` is used. - -.. code-block:: php - - $values = [ - 'hasSearched' => $this->searchService->getHasSearched(), - 'additionalFilters' => $this->searchService->getAdditionalFilters(), - 'resultSet' => $searchResultSet, - 'pluginNamespace' => $this->typoScriptConfiguration->getSearchPluginNamespace() - ]; - - $values = $this->emitActionSignal(__CLASS__, __FUNCTION__, [$values]); - -To fulfill that signal, you can create a slot in your custom extension. All what it needs is an entry in your ``ext_localconf.php`` file: - -.. code-block:: php - - /** @var \TYPO3\CMS\Extbase\SignalSlot\Dispatcher $signalSlotDispatcher */ - $signalSlotDispatcher = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(\TYPO3\CMS\Extbase\SignalSlot\Dispatcher::class); - $signalSlotDispatcher->connect( - \ApacheSolrForTypo3\Solr\Controller\SearchController::class, - 'resultsAction', - \YourVendor\yourextkey\Slot\SearchControllerSlot::class, // fully your choice - 'resultsActionSlot', // fully your choice - ); - -An example call look like this: - -.. code-block:: php - - /** - * @param array $values - */ - public function resultsActionSlot($values) { - $values['foo'] = 'bar' - - return [$values]; - } - -Notice: The values array needs to be returned as an single element of an array, because a slot method has to return the same number of arguments like it received. \ No newline at end of file diff --git a/Tests/Unit/Domain/Index/IndexServiceTest.php b/Tests/Unit/Domain/Index/IndexServiceTest.php index 448c55c3ea..d05cfcaa3e 100644 --- a/Tests/Unit/Domain/Index/IndexServiceTest.php +++ b/Tests/Unit/Domain/Index/IndexServiceTest.php @@ -26,7 +26,7 @@ use ApacheSolrForTypo3\Solr\Tests\Unit\UnitTest; use Exception; use PHPUnit\Framework\MockObject\MockObject; -use TYPO3\CMS\Extbase\SignalSlot\Dispatcher; +use TYPO3\CMS\Core\EventDispatcher\EventDispatcher; /** * @author Timo Hund @@ -44,9 +44,9 @@ class IndexServiceTest extends UnitTest protected $queueMock; /** - * @var Dispatcher + * @var EventDispatcher|MockObject */ - protected $dispatcherMock; + protected EventDispatcher|MockObject $eventDispatcherMock; /** * @var SolrLogManager @@ -57,7 +57,12 @@ protected function setUp(): void { $this->siteMock = $this->getDumbMock(Site::class); $this->queueMock = $this->getDumbMock(Queue::class); - $this->dispatcherMock = $this->getDumbMock(Dispatcher::class); + $this->eventDispatcherMock = $this->getMockBuilder(EventDispatcher::class) + ->disableOriginalConstructor() + ->onlyMethods(['dispatch']) + ->getMock(); + $this->eventDispatcherMock->method('dispatch') + ->willReturnArgument(0); $this->logManagerMock = $this->getDumbMock(SolrLogManager::class); parent::setUp(); } @@ -65,7 +70,7 @@ protected function setUp(): void /** * @test */ - public function signalsAreTriggered() + public function eventsAreTriggered() { $fakeConfiguration = $this->getDumbMock(TypoScriptConfiguration::class); $this->siteMock = $this->getMockBuilder(Site::class) @@ -76,7 +81,7 @@ public function signalsAreTriggered() // we create an IndexeService where indexItem is mocked to avoid real indexing in the unit test $indexService = $this->getMockBuilder(IndexService::class) - ->setConstructorArgs([$this->siteMock, $this->queueMock, $this->dispatcherMock, $this->logManagerMock]) + ->setConstructorArgs([$this->siteMock, $this->queueMock, $this->eventDispatcherMock, $this->logManagerMock]) ->onlyMethods(['indexItem']) ->getMock(); @@ -87,14 +92,14 @@ public function signalsAreTriggered() $this->fakeQueueItemContent($fakeItems); // we assert that 6 signals will be dispatched 1 at the beginning 1 before and after each items and 1 at the end. - $this->assertSignalsWillBeDispatched(6); + $this->assertEventsWillBeDispatched(6); $indexService->indexItems(2); } /** * @test */ - public function testConfigurationIsNotFetchedWhenProgressIsCaluclated() + public function testConfigurationIsNotFetchedWhenProgressIsCalculated() { $this->siteMock->expects(self::never())->method('getSolrConfiguration'); @@ -103,7 +108,7 @@ public function testConfigurationIsNotFetchedWhenProgressIsCaluclated() $this->queueMock->expects(self::once())->method('getStatisticsBySite')->willReturn($statisticMock); $indexService = $this->getMockBuilder(IndexService::class) - ->setConstructorArgs([$this->siteMock, $this->queueMock, $this->dispatcherMock, $this->logManagerMock]) + ->setConstructorArgs([$this->siteMock, $this->queueMock, $this->eventDispatcherMock, $this->logManagerMock]) ->onlyMethods(['indexItem']) ->getMock(); @@ -126,7 +131,7 @@ public function testServerHostIsRestoredInCaseOfAnException() /* @var IndexService|MockObject $indexService */ $indexService = $this->getMockBuilder(IndexService::class) - ->setConstructorArgs([$this->siteMock, $this->queueMock, $this->dispatcherMock, $this->logManagerMock]) + ->setConstructorArgs([$this->siteMock, $this->queueMock, $this->eventDispatcherMock, $this->logManagerMock]) ->onlyMethods(['getIndexerByItem', 'restoreOriginalHttpHost']) ->getMock(); @@ -165,7 +170,7 @@ public function testDomainIsUsedFromSiteObject() /* @var IndexService|MockObject $indexService */ $indexService = $this->getMockBuilder(IndexService::class) - ->setConstructorArgs([$this->siteMock, $this->queueMock, $this->dispatcherMock, $this->logManagerMock]) + ->setConstructorArgs([$this->siteMock, $this->queueMock, $this->eventDispatcherMock, $this->logManagerMock]) ->onlyMethods(['getIndexerByItem']) ->getMock(); @@ -200,8 +205,10 @@ protected function fakeQueueItemContent($fakeItems) /** * @param int $amount */ - protected function assertSignalsWillBeDispatched($amount = 0) + protected function assertEventsWillBeDispatched(int $amount = 0) { - $this->dispatcherMock->expects(self::exactly($amount))->method('dispatch'); + $this->eventDispatcherMock->expects(self::exactly($amount)) + ->method('dispatch') + ->willReturnArgument(0); } }