diff --git a/Classes/EventListener/PageIndexer/FrontendGroupsModifier.php b/Classes/EventListener/PageIndexer/FrontendGroupsModifier.php index 91c2d01484..cbaa06daba 100644 --- a/Classes/EventListener/PageIndexer/FrontendGroupsModifier.php +++ b/Classes/EventListener/PageIndexer/FrontendGroupsModifier.php @@ -20,10 +20,7 @@ use ApacheSolrForTypo3\Solr\Access\Rootline; use ApacheSolrForTypo3\Solr\IndexQueue\FrontendHelper\AuthorizationService; use ApacheSolrForTypo3\Solr\IndexQueue\PageIndexerRequest; -use ApacheSolrForTypo3\Solr\IndexQueue\PageIndexerRequestHandler; use ApacheSolrForTypo3\Solr\System\Logging\SolrLogManager; -use Psr\Http\Message\RequestInterface; -use Psr\Http\Message\ServerRequestInterface; use TYPO3\CMS\Core\Http\JsonResponse; use TYPO3\CMS\Core\Http\PropagateResponseException; use TYPO3\CMS\Core\Utility\GeneralUtility; @@ -42,23 +39,19 @@ class FrontendGroupsModifier */ public function __invoke(ModifyResolvedFrontendGroupsEvent $event): void { - if (!$event->getRequest()->hasHeader(PageIndexerRequest::SOLR_INDEX_HEADER)) { + $pageIndexerRequest = $event->getRequest()->getAttribute('solr.pageIndexingInstructions'); + if (!$pageIndexerRequest instanceof PageIndexerRequest) { return; } - - $jsonEncodedParameters = $event->getRequest()->getHeader(PageIndexerRequest::SOLR_INDEX_HEADER)[0]; - /** @var PageIndexerRequestHandler $pageIndexerRequestHandler */ - $pageIndexerRequestHandler = GeneralUtility::makeInstance(PageIndexerRequestHandler::class, $jsonEncodedParameters); - - if (!$pageIndexerRequestHandler->getRequest()->isAuthenticated()) { + if (!$pageIndexerRequest->isAuthenticated()) { /** @var SolrLogManager $logger */ $logger = GeneralUtility::makeInstance(SolrLogManager::class, self::class); $logger->log( SolrLogManager::ERROR, 'Invalid Index Queue Frontend Request detected!', [ - 'page indexer request' => (array)$pageIndexerRequestHandler->getRequest(), - 'index queue header' => $jsonEncodedParameters, + 'page indexer request' => (array)$pageIndexerRequest, + 'index queue header' => $event->getRequest()->getHeader(PageIndexerRequest::SOLR_INDEX_HEADER)[0], ] ); throw new PropagateResponseException( @@ -75,7 +68,7 @@ public function __invoke(ModifyResolvedFrontendGroupsEvent $event): void ); } - $groups = $this->resolveFrontendUserGroups($event->getRequest()); + $groups = $this->resolveFrontendUserGroups($pageIndexerRequest); $groupData = []; foreach ($groups as $groupUid) { if (in_array($groupUid, [-2, -1])) { @@ -94,9 +87,9 @@ public function __invoke(ModifyResolvedFrontendGroupsEvent $event): void /** * Resolves a logged in fe_groups to retrieve access restricted content. */ - protected function resolveFrontendUserGroups(ServerRequestInterface $request): array + protected function resolveFrontendUserGroups(PageIndexerRequest $pageIndexerRequest): array { - $accessRootline = $this->getAccessRootline($request); + $accessRootline = $this->getAccessRootline($pageIndexerRequest); $stringAccessRootline = (string)$accessRootline; if (empty($stringAccessRootline)) { return []; @@ -107,16 +100,11 @@ protected function resolveFrontendUserGroups(ServerRequestInterface $request): a /** * Gets the access rootline as defined by the request. */ - protected function getAccessRootline(RequestInterface $request): Rootline + protected function getAccessRootline(PageIndexerRequest $pageIndexerRequest): Rootline { $stringAccessRootline = ''; - - $jsonEncodedParameters = $request->getHeader(PageIndexerRequest::SOLR_INDEX_HEADER)[0]; - /** @var PageIndexerRequestHandler $pageIndexerRequestHandler */ - $pageIndexerRequestHandler = GeneralUtility::makeInstance(PageIndexerRequestHandler::class, $jsonEncodedParameters); - - if ($pageIndexerRequestHandler->getRequest()->getParameter('accessRootline')) { - $stringAccessRootline = $pageIndexerRequestHandler->getRequest()->getParameter('accessRootline'); + if ($pageIndexerRequest->getParameter('accessRootline')) { + $stringAccessRootline = $pageIndexerRequest->getParameter('accessRootline'); } return GeneralUtility::makeInstance(Rootline::class, $stringAccessRootline); } diff --git a/Classes/IndexQueue/FrontendHelper/AbstractFrontendHelper.php b/Classes/IndexQueue/FrontendHelper/AbstractFrontendHelper.php deleted file mode 100644 index d4645d6f21..0000000000 --- a/Classes/IndexQueue/FrontendHelper/AbstractFrontendHelper.php +++ /dev/null @@ -1,90 +0,0 @@ - - */ -abstract class AbstractFrontendHelper implements FrontendHelper, SingletonInterface -{ - /** - * Index Queue page indexer request. - */ - protected ?PageIndexerRequest $request = null; - - /** - * Index Queue page indexer response. - */ - protected ?PageIndexerResponse $response = null; - - /** - * Singleton instance variable for indication of indexing request. - */ - protected bool $isActivated = false; - - /** - * The action a frontend helper executes. - */ - protected string $action; - - protected ?SolrLogManager $logger = null; - - /** - * Starts the execution of a frontend helper. - * - * @param PageIndexerRequest $request Page indexer request - * @param PageIndexerResponse $response Page indexer response - */ - public function processRequest( - PageIndexerRequest $request, - PageIndexerResponse $response - ): void { - $this->request = $request; - $this->response = $response; - $this->logger = GeneralUtility::makeInstance(SolrLogManager::class, __CLASS__); - - if ($request->getParameter('loggingEnabled')) { - $this->logger->log( - SolrLogManager::INFO, - 'Page indexer request received', - [ - 'request' => (array)$request, - ] - ); - } - } - - /** - * Deactivates a frontend helper by unregistering from hooks and releasing - * resources. - */ - public function deactivate(): void - { - $this->isActivated = false; - $this->response->addActionResult($this->action, $this->getData()); - } -} diff --git a/Classes/IndexQueue/FrontendHelper/AuthorizationService.php b/Classes/IndexQueue/FrontendHelper/AuthorizationService.php index 2beab5e9e9..3d46b816bb 100644 --- a/Classes/IndexQueue/FrontendHelper/AuthorizationService.php +++ b/Classes/IndexQueue/FrontendHelper/AuthorizationService.php @@ -17,10 +17,7 @@ namespace ApacheSolrForTypo3\Solr\IndexQueue\FrontendHelper; -use ApacheSolrForTypo3\Solr\Access\Rootline; -use ApacheSolrForTypo3\Solr\IndexQueue\PageIndexerRequestHandler; use TYPO3\CMS\Core\Authentication\AbstractAuthenticationService; -use TYPO3\CMS\Core\Utility\GeneralUtility; /** * Authentication service to authorize the Index Queue page indexer to access @@ -40,10 +37,13 @@ class AuthorizationService extends AbstractAuthenticationService /** * Gets a fake frontend user record to allow access to protected pages. * - * @return array An array representing a frontend user. + * @return ?array An array representing a frontend user if a authenticated solr request is available. */ - public function getUser(): array + public function getUser(): ?array { + if (!$this->authInfo['request']->getAttribute('solr.pageIndexingInstructions')) { + return null; + } return [ 'uid' => 0, 'username' => self::SOLR_INDEXER_USERNAME, @@ -62,10 +62,13 @@ public function getUser(): array * * @param array $user Array of user data * @return int Returns 200 to grant access for the page indexer. - *@see \TYPO3\CMS\Core\Authentication\AbstractUserAuthentication::checkAuthentication() + * @see \TYPO3\CMS\Core\Authentication\AbstractUserAuthentication::checkAuthentication() */ public function authUser(array $user): int { + if (!$this->authInfo['request']->getAttribute('solr.pageIndexingInstructions')) { + return 100; + } // shouldn't happen, but in case we get a regular user we just // pass it on to another (regular) auth service $authenticationLevel = 100; @@ -76,41 +79,4 @@ public function authUser(array $user): int return $authenticationLevel; } - - /** - * Creates user group records so that the page indexer is granted access to - * protected pages. - * - * @param array $user Data of user. - * @param array $knownGroups Group data array of already known groups. This is handy if you want select other related groups. Keys in this array are unique IDs of those groups. - * @return array Groups array, keys = uid which must be unique - */ - public function getGroups( - array $user, - /** @noinspection PhpUnusedParameterInspection */ - array $knownGroups = [] - ): array { - $groupData = []; - - /** @var PageIndexerRequestHandler $requestHandler */ - $requestHandler = GeneralUtility::makeInstance(PageIndexerRequestHandler::class); - $accessRootline = $requestHandler->getRequest()->getParameter('accessRootline'); - - if ($user['username'] == self::SOLR_INDEXER_USERNAME && !empty($accessRootline)) { - $accessRootline = GeneralUtility::makeInstance(Rootline::class, $accessRootline); - $groups = $accessRootline->getGroups(); - - foreach ($groups as $groupId) { - // faking a user group record - $groupData[] = [ - 'uid' => $groupId, - 'pid' => 0, - 'title' => '__SolrIndexerGroup__', - 'TSconfig' => '', - ]; - } - } - - return $groupData; - } } diff --git a/Classes/IndexQueue/FrontendHelper/Dispatcher.php b/Classes/IndexQueue/FrontendHelper/Dispatcher.php deleted file mode 100644 index b9f3832556..0000000000 --- a/Classes/IndexQueue/FrontendHelper/Dispatcher.php +++ /dev/null @@ -1,73 +0,0 @@ - - */ -class Dispatcher -{ - /** - * Frontend helper manager. - */ - protected Manager $frontendHelperManager; - - public function __construct(Manager $frontendHelperManager = null) - { - $this->frontendHelperManager = $frontendHelperManager ?? GeneralUtility::makeInstance(Manager::class); - } - - /** - * Takes the request's actions and hands them of to the according frontend - * helpers. - * - * @param PageIndexerRequest $request The request to dispatch - * @param PageIndexerResponse $response The request's response - */ - public function dispatch( - PageIndexerRequest $request, - PageIndexerResponse $response - ): void { - $actions = $request->getActions(); - - foreach ($actions as $action) { - $frontendHelper = $this->frontendHelperManager->resolveAction($action); - $frontendHelper->activate(); - $frontendHelper->processRequest($request, $response); - } - } - - /** - * Sends a shutdown signal to all activated frontend helpers. - */ - public function shutdown(): void - { - $frontendHelpers = $this->frontendHelperManager->getActivatedFrontendHelpers(); - - foreach ($frontendHelpers as $frontendHelper) { - /** @var FrontendHelper $frontendHelper */ - $frontendHelper->deactivate(); - } - } -} diff --git a/Classes/IndexQueue/FrontendHelper/FrontendHelper.php b/Classes/IndexQueue/FrontendHelper/FrontendHelper.php index 382dc9b1a4..6ca754c321 100644 --- a/Classes/IndexQueue/FrontendHelper/FrontendHelper.php +++ b/Classes/IndexQueue/FrontendHelper/FrontendHelper.php @@ -17,7 +17,6 @@ namespace ApacheSolrForTypo3\Solr\IndexQueue\FrontendHelper; -use ApacheSolrForTypo3\Solr\IndexQueue\PageIndexerRequest; use ApacheSolrForTypo3\Solr\IndexQueue\PageIndexerResponse; /** @@ -37,23 +36,5 @@ public function activate(): void; * Deactivates a frontend helper by unregistering from hooks and releasing * resources. */ - public function deactivate(): void; - - /** - * Starts the execution of a frontend helper. - * - * @param PageIndexerRequest $request Page indexer request - * @param PageIndexerResponse $response Page indexer response - */ - public function processRequest( - PageIndexerRequest $request, - PageIndexerResponse $response - ): void; - - /** - * Returns the collected data. - * - * @return array Collected data. - */ - public function getData(): array; + public function deactivate(PageIndexerResponse $response): void; } diff --git a/Classes/IndexQueue/FrontendHelper/Manager.php b/Classes/IndexQueue/FrontendHelper/Manager.php index 6b12535380..9a97cef07f 100644 --- a/Classes/IndexQueue/FrontendHelper/Manager.php +++ b/Classes/IndexQueue/FrontendHelper/Manager.php @@ -74,7 +74,7 @@ public function resolveAction(string $action): ?FrontendHelper /** * Gets an array with references to activated frontend helpers. * - * @return array Array of references to activated frontend helpers. + * @return FrontendHelper[] Array of references to activated frontend helpers. */ public function getActivatedFrontendHelpers(): array { diff --git a/Classes/IndexQueue/FrontendHelper/PageIndexer.php b/Classes/IndexQueue/FrontendHelper/PageIndexer.php index edb41cf156..b7033df406 100644 --- a/Classes/IndexQueue/FrontendHelper/PageIndexer.php +++ b/Classes/IndexQueue/FrontendHelper/PageIndexer.php @@ -24,20 +24,20 @@ use ApacheSolrForTypo3\Solr\Exception; use ApacheSolrForTypo3\Solr\FieldProcessor\Service; use ApacheSolrForTypo3\Solr\IndexQueue\Item; +use ApacheSolrForTypo3\Solr\IndexQueue\PageIndexerRequest; +use ApacheSolrForTypo3\Solr\IndexQueue\PageIndexerResponse; 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\Util; -use Doctrine\DBAL\Exception as DBALException; use Psr\EventDispatcher\EventDispatcherInterface; use Throwable; +use TYPO3\CMS\Core\SingletonInterface; 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\Core\Utility\MathUtility; use TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController; @@ -52,13 +52,18 @@ * * @author Ingo Renner */ -class PageIndexer extends AbstractFrontendHelper +class PageIndexer implements FrontendHelper, SingletonInterface { /** * This frontend helper's executed action. */ protected string $action = 'indexPage'; + /** + * Index Queue page indexer request. + */ + protected ?PageIndexerRequest $request = null; + /** * Response data */ @@ -76,6 +81,8 @@ class PageIndexer extends AbstractFrontendHelper protected ?TypoScriptConfiguration $configuration = null; + protected ?SolrLogManager $logger = null; + /** * Activates a frontend helper by registering for hooks and other * resources required by the frontend helper to work. @@ -84,19 +91,7 @@ class PageIndexer extends AbstractFrontendHelper */ public function activate(): void { - $this->isActivated = true; - $this->registerAuthorizationService(); - } - - /** - * Returns the status of whether a page was indexed. - * - * @return array Page indexed status. - * @noinspection PhpUnused - */ - public function getData(): array - { - return $this->responseData; + $this->logger = GeneralUtility::makeInstance(SolrLogManager::class, __CLASS__); } /** @@ -115,57 +110,6 @@ protected function getAccessRootline(): Rootline return GeneralUtility::makeInstance(Rootline::class, $stringAccessRootline); } - /** - * Registers an authentication service to authorize / grant the indexer to - * access protected pages. - */ - protected function registerAuthorizationService(): void - { - $overrulingPriority = $this->getHighestAuthenticationServicePriority() + 1; - - ExtensionManagementUtility::addService( - 'solr', // extension key - 'auth', // service type - AuthorizationService::class, - // service key - [// service meta data - 'title' => 'Solr Indexer Authorization', - 'description' => 'Authorizes the Solr Index Queue indexer to access protected pages.', - - 'subtype' => 'getUserFE,authUserFE,getGroupsFE', - - 'available' => true, - 'priority' => $overrulingPriority, - 'quality' => 100, - - 'os' => '', - 'exec' => '', - 'className' => AuthorizationService::class, - ] - ); - } - - /** - * Determines the highest priority of all registered authentication - * services. - * - * @return int Highest priority of all registered authentication service - */ - protected function getHighestAuthenticationServicePriority(): int - { - $highestPriority = 0; - - if (is_array($GLOBALS['T3_SERVICES']['auth'] ?? null)) { - foreach ($GLOBALS['T3_SERVICES']['auth'] as $service) { - if ($service['priority'] > $highestPriority) { - $highestPriority = $service['priority']; - } - } - } - - return $highestPriority; - } - // // Indexing // @@ -196,7 +140,8 @@ protected function generatePageUrl(TypoScriptFrontendController $controller): st */ public function __invoke(AfterCacheableContentIsGeneratedEvent $event): void { - if (!$this->isActivated) { + $this->request = $event->getRequest()->getAttribute('solr.pageIndexingInstructions'); + if (!$this->request) { return; } $this->setupConfiguration(); @@ -270,9 +215,6 @@ public function index(Item $indexQueueItem, TypoScriptFrontendController $tsfe): /** * Gets the solr connection to use for indexing the page based on the * Index Queue item's properties. - * - * @throws NoSolrConnectionFoundException - * @throws DBALException */ protected function getSolrConnection(Item $indexQueueItem, SiteLanguage $siteLanguage, bool $logExceptions): SolrConnection { @@ -308,8 +250,6 @@ protected function getSolrConnection(Item $indexQueueItem, SiteLanguage $siteLan /** * This method retrieves the item from the index queue, that is indexed in this request. - * - * @throws DBALException */ protected function getIndexQueueItem(): ?Item { @@ -346,9 +286,6 @@ protected function getPageDocument(TypoScriptFrontendController $tsfe, string $u * Indexes a page. * * @return bool TRUE after successfully indexing the page, FALSE on error - * - * @throws DBALException - * @throws Exception */ public function indexPage(Document $pageDocument, Item $indexQueueItem, Site $site, SiteLanguage $siteLanguage): bool { @@ -373,8 +310,6 @@ public function indexPage(Document $pageDocument, Item $indexQueueItem, Site $si * 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 { @@ -437,4 +372,12 @@ protected function getEventDispatcher(): EventDispatcherInterface { return GeneralUtility::makeInstance(EventDispatcherInterface::class); } + + /** + * Adds the status of whether a page was indexed to the pageIndexer Response. + */ + public function deactivate(PageIndexerResponse $response): void + { + $response->addActionResult($this->action, $this->responseData); + } } diff --git a/Classes/IndexQueue/FrontendHelper/UserGroupDetector.php b/Classes/IndexQueue/FrontendHelper/UserGroupDetector.php index 100a94d184..e9d9e82ec0 100644 --- a/Classes/IndexQueue/FrontendHelper/UserGroupDetector.php +++ b/Classes/IndexQueue/FrontendHelper/UserGroupDetector.php @@ -17,10 +17,13 @@ namespace ApacheSolrForTypo3\Solr\IndexQueue\FrontendHelper; +use ApacheSolrForTypo3\Solr\IndexQueue\PageIndexerRequest; +use ApacheSolrForTypo3\Solr\IndexQueue\PageIndexerResponse; use ApacheSolrForTypo3\Solr\System\Logging\SolrLogManager; use TYPO3\CMS\Core\Domain\Repository\PageRepository; use TYPO3\CMS\Core\Domain\Repository\PageRepositoryGetPageHookInterface; use TYPO3\CMS\Core\Domain\Repository\PageRepositoryGetPageOverlayHookInterface; +use TYPO3\CMS\Core\SingletonInterface; use TYPO3\CMS\Core\Utility\GeneralUtility; use TYPO3\CMS\Frontend\ContentObject\ContentObjectPostInitHookInterface; use TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer; @@ -31,11 +34,18 @@ * * @author Ingo Renner */ -class UserGroupDetector extends AbstractFrontendHelper implements +class UserGroupDetector implements + FrontendHelper, + SingletonInterface, ContentObjectPostInitHookInterface, PageRepositoryGetPageHookInterface, PageRepositoryGetPageOverlayHookInterface { + /** + * Index Queue page indexer request. + */ + protected ?PageIndexerRequest $request = null; + /** * This frontend helper's executed action. */ @@ -51,6 +61,7 @@ class UserGroupDetector extends AbstractFrontendHelper implements */ protected array $frontendGroups = []; + protected ?SolrLogManager $logger = null; // activation /** @@ -59,8 +70,6 @@ class UserGroupDetector extends AbstractFrontendHelper implements */ public function activate(): void { - $this->isActivated = true; - $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['tslib/class.tslib_fe.php']['configArrayPostProc'][__CLASS__] = UserGroupDetector::class . '->deactivateTcaFrontendGroupEnableFields'; $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['tslib/class.tslib_fe.php']['hook_checkEnableFields'][__CLASS__] = UserGroupDetector::class . '->checkEnableFields'; @@ -68,6 +77,7 @@ public function activate(): void $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_page.php']['getPageOverlay'][__CLASS__] = UserGroupDetector::class; $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['tslib/class.tslib_content.php']['postInit'][__CLASS__] = UserGroupDetector::class; + $this->logger = GeneralUtility::makeInstance(SolrLogManager::class, __CLASS__); } /** @@ -159,6 +169,7 @@ public function getPageOverlay_preProcess( */ public function postProcessContentObjectInitialization(ContentObjectRenderer &$parentObject) { + $this->request = $parentObject->getRequest()->getAttribute('solr.pageIndexingInstructions'); if (!empty($parentObject->currentRecord)) { [$table] = explode(':', $parentObject->currentRecord); @@ -225,10 +236,10 @@ protected function getFrontendGroups(): array } /** - * Returns the user groups found. + * Adds the user groups found to the PageIndexerResponse */ - public function getData(): array + public function deactivate(PageIndexerResponse $response): void { - return $this->getFrontendGroups(); + $response->addActionResult($this->action, $this->getFrontendGroups()); } } diff --git a/Classes/IndexQueue/PageIndexerRequestHandler.php b/Classes/IndexQueue/PageIndexerRequestHandler.php index a354df1840..c94dd7d61e 100644 --- a/Classes/IndexQueue/PageIndexerRequestHandler.php +++ b/Classes/IndexQueue/PageIndexerRequestHandler.php @@ -17,78 +17,76 @@ namespace ApacheSolrForTypo3\Solr\IndexQueue; -use ApacheSolrForTypo3\Solr\IndexQueue\FrontendHelper\Dispatcher; -use TYPO3\CMS\Core\SingletonInterface; +use ApacheSolrForTypo3\Solr\IndexQueue\FrontendHelper\FrontendHelper; +use ApacheSolrForTypo3\Solr\IndexQueue\FrontendHelper\Manager; +use ApacheSolrForTypo3\Solr\System\Logging\SolrLogManager; use TYPO3\CMS\Core\Utility\GeneralUtility; /** * Checks for Index Queue page indexer requests and handles the actions * requested by them. * + * This is added in the PSR-7 Frontend Request as "solr.pageIndexingInstructions" attribute + * * @author Ingo Renner */ -class PageIndexerRequestHandler implements SingletonInterface +class PageIndexerRequestHandler { /** * Index Queue page indexer request. */ protected PageIndexerRequest $request; - /** - * Index Queue page indexer response. - */ - protected PageIndexerResponse $response; + protected Manager $frontendHelperManager; /** - * Index Queue page indexer frontend helper dispatcher. + * @var FrontendHelper[] */ - protected Dispatcher $dispatcher; + protected array $frontendHelpers = []; - /** - * Constructor. - * - * Initializes request, response, and dispatcher. - */ - public function __construct(string $jsonEncodedParameters = null) + public function __construct(Manager $manager) { - $this->dispatcher = GeneralUtility::makeInstance(Dispatcher::class); - $this->request = GeneralUtility::makeInstance(PageIndexerRequest::class, $jsonEncodedParameters); - $this->response = GeneralUtility::makeInstance(PageIndexerResponse::class); - $this->response->setRequestId($this->request->getRequestId()); + $this->frontendHelperManager = $manager; } /** * Authenticates the request, runs the frontend helpers defined by the - * request, and registers its own shutdown() method for execution at - * hook_eofe in tslib/class.tslib_fe.php. + * request, and registers its own shutdown() method for execution at a later stage + * when the response is available. */ - public function run(): void + public function initialize(PageIndexerRequest $request): void { - $this->dispatcher->dispatch($this->request, $this->response); - } + $actions = $request->getActions(); - /** - * Completes the Index Queue page indexer request and returns the response - * with the collected results. - */ - public function shutdown(): void - { - $this->dispatcher->shutdown(); - } + foreach ($actions as $action) { + $frontendHelper = $this->frontendHelperManager->resolveAction($action); + $frontendHelper->activate(); + $this->frontendHelpers[] = $frontendHelper; - /** - * Gets the Index Queue page indexer request. - */ - public function getRequest(): PageIndexerRequest - { - return $this->request; + if ($request->getParameter('loggingEnabled')) { + $logger = GeneralUtility::makeInstance(SolrLogManager::class, get_class($frontendHelper)); + $logger->log( + SolrLogManager::INFO, + 'Page indexer request received', + [ + 'request' => (array)$request, + ] + ); + } + } } /** - * Gets the Index Queue page indexer response. + * Completes the Index Queue page indexer request and returns the response + * with the collected results. */ - public function getResponse(): PageIndexerResponse + public function shutdown(PageIndexerRequest $request): PageIndexerResponse { - return $this->response; + $indexerResponse = GeneralUtility::makeInstance(PageIndexerResponse::class); + $indexerResponse->setRequestId($request->getRequestId()); + foreach ($this->frontendHelpers as $frontendHelper) { + $frontendHelper->deactivate($indexerResponse); + } + return $indexerResponse; } } diff --git a/Classes/Middleware/PageIndexerFinisher.php b/Classes/Middleware/PageIndexerFinisher.php deleted file mode 100644 index 1a3acadaf4..0000000000 --- a/Classes/Middleware/PageIndexerFinisher.php +++ /dev/null @@ -1,55 +0,0 @@ -handle($request); - if ($request->hasHeader(PageIndexerRequest::SOLR_INDEX_HEADER)) { - /** @var PageIndexerRequestHandler $pageIndexerRequestHandler */ - $pageIndexerRequestHandler = GeneralUtility::makeInstance(PageIndexerRequestHandler::class); - $pageIndexerRequestHandler->shutdown(); - $pageIndexResponse = $pageIndexerRequestHandler->getResponse(); - $response = new Response(); - - $body = new Stream('php://temp', 'rw'); - $content = $pageIndexResponse->getContent(); - $body->write($content); - $response = $response - ->withBody($body) - ->withHeader('Content-Length', (string)strlen($content)) - ->withHeader('Content-Type', 'application/json'); - } - return $response; - } -} diff --git a/Classes/Middleware/PageIndexerInitialization.php b/Classes/Middleware/PageIndexerInitialization.php index 59d1adccd4..4b1fdb8408 100644 --- a/Classes/Middleware/PageIndexerInitialization.php +++ b/Classes/Middleware/PageIndexerInitialization.php @@ -25,6 +25,8 @@ use Psr\Http\Server\MiddlewareInterface; use Psr\Http\Server\RequestHandlerInterface; use TYPO3\CMS\Core\Http\JsonResponse; +use TYPO3\CMS\Core\Http\Response; +use TYPO3\CMS\Core\Http\Stream; use TYPO3\CMS\Core\Utility\GeneralUtility; /** @@ -34,14 +36,13 @@ class PageIndexerInitialization implements MiddlewareInterface { public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface { + $pageIndexerRequestHandler = null; + $pageIndexerRequest = null; if ($request->hasHeader(PageIndexerRequest::SOLR_INDEX_HEADER)) { // disable TSFE cache for TYPO3 v10 $request = $request->withAttribute('noCache', true); $jsonEncodedParameters = $request->getHeader(PageIndexerRequest::SOLR_INDEX_HEADER)[0]; - /** @var PageIndexerRequestHandler $pageIndexerRequestHandler */ - $pageIndexerRequestHandler = GeneralUtility::makeInstance(PageIndexerRequestHandler::class, $jsonEncodedParameters); - - $pageIndexerRequest = $pageIndexerRequestHandler->getRequest(); + $pageIndexerRequest = GeneralUtility::makeInstance(PageIndexerRequest::class, $jsonEncodedParameters); if (!$pageIndexerRequest->isAuthenticated()) { /** @var SolrLogManager $logger */ $logger = GeneralUtility::makeInstance(SolrLogManager::class, self::class); @@ -55,9 +56,23 @@ public function process(ServerRequestInterface $request, RequestHandlerInterface ); return new JsonResponse(['error' => ['code' => 403, 'message' => 'Invalid Index Queue Request.']], 403); } - $pageIndexerRequestHandler->run(); + $request = $request->withAttribute('solr.pageIndexingInstructions', $pageIndexerRequest); + $pageIndexerRequestHandler = GeneralUtility::makeInstance(PageIndexerRequestHandler::class); + $pageIndexerRequestHandler->initialize($pageIndexerRequest); } - return $handler->handle($request); + $response = $handler->handle($request); + if ($pageIndexerRequestHandler instanceof PageIndexerRequestHandler && $pageIndexerRequest instanceof PageIndexerRequest) { + $pageIndexResponse = $pageIndexerRequestHandler->shutdown($pageIndexerRequest); + + $body = new Stream('php://temp', 'rw'); + $content = $pageIndexResponse->getContent(); + $body->write($content); + return (new Response()) + ->withBody($body) + ->withHeader('Content-Length', (string)strlen($content)) + ->withHeader('Content-Type', 'application/json'); + } + return $response; } } diff --git a/Configuration/RequestMiddlewares.php b/Configuration/RequestMiddlewares.php index 795171cf85..f40b9be8a5 100644 --- a/Configuration/RequestMiddlewares.php +++ b/Configuration/RequestMiddlewares.php @@ -8,10 +8,6 @@ 'before' => ['typo3/cms-frontend/tsfe'], 'after' => ['typo3/cms-core/normalized-params-attribute'], ], - 'apache-solr-for-typo3/page-indexer-finisher' => [ - 'target' => \ApacheSolrForTypo3\Solr\Middleware\PageIndexerFinisher::class, - 'after' => ['typo3/cms-frontend/content-length-headers'], - ], 'apache-solr-for-typo3/solr-route-enhancer' => [ 'target' => \ApacheSolrForTypo3\Solr\Middleware\SolrRoutingMiddleware::class, 'before' => [ diff --git a/Configuration/Services.yaml b/Configuration/Services.yaml index 69458115d2..bc74b35dde 100644 --- a/Configuration/Services.yaml +++ b/Configuration/Services.yaml @@ -85,6 +85,10 @@ services: public: true autowire: true + ApacheSolrForTypo3\Solr\IndexQueue\PageIndexerRequestHandler: + public: true + autowire: true + ApacheSolrForTypo3\Solr\EventListener\EnhancedRouting\CachedUrlModifier: tags: - name: event.listener diff --git a/Documentation/Releases/solr-release-12-0.rst b/Documentation/Releases/solr-release-12-0.rst index f32c1506c2..ee11551abf 100644 --- a/Documentation/Releases/solr-release-12-0.rst +++ b/Documentation/Releases/solr-release-12-0.rst @@ -18,7 +18,7 @@ Support of TYPO3 12 LTS With EXT:solr 12.0 we provide the support of TYPO3 12 LTS. -Hooks replaced by PSR-14 events +Hooks replaced by PSR-14 Events ------------------------------- The previously available hooks and their respective interfaces have been removed from EXT:solr. @@ -57,6 +57,19 @@ is now superseded by the PSR-14 event :php:`ApacheSolrForTypo3\Solr\Event\Indexi The hook :php:`$GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['solr']['postProcessIndexQueueUpdateItem']` is now superseded by the PSR-14 event :php:`ApacheSolrForTypo3\Solr\Event\Indexing\AfterIndexQueueItemHasBeenMarkedForReindexingEvent` + +Frontend Helper Changes +----------------------- + +The FrontendHelper logic revolving around PageIndexer has been reduced to +a minimum by only having two methods available: + +* :php:`ApacheSolrForTypo3\Solr\IndexQueue\FrontendHelper\FrontendHelper::activate()` - used to register hooks and PSR-14 event listeners +* :php:`ApacheSolrForTypo3\Solr\IndexQueue\FrontendHelper\FrontendHelper::deactivate(PageIndexerResponse $response)` - used to populate data into the PageIndexerResponse object + +The actual PageIndexerRequest object is now available as a property of TYPO3's +Request object as attribute named "solr.pageIndexingInstructions". + Contributors ============ diff --git a/Tests/Integration/Controller/SearchControllerTest.php b/Tests/Integration/Controller/SearchControllerTest.php index faefd81d2b..de978e1aed 100644 --- a/Tests/Integration/Controller/SearchControllerTest.php +++ b/Tests/Integration/Controller/SearchControllerTest.php @@ -21,7 +21,6 @@ use ApacheSolrForTypo3\Solr\Tests\Integration\IntegrationTest; use DOMDocument; use TYPO3\CMS\Core\Http\Response; -use TYPO3\TestingFramework\Core\Exception as TestingFrameworkCoreException; use TYPO3\TestingFramework\Core\Functional\Framework\Frontend\InternalRequest; use TYPO3\TestingFramework\Core\Functional\Framework\Frontend\InternalRequestContext; use TYPO3Fluid\Fluid\View\Exception\InvalidTemplateResourceException; @@ -60,9 +59,6 @@ protected function tearDown(): void parent::tearDown(); } - /** - * @throws TestingFrameworkCoreException - */ protected function bootstrapSearchResultsPluginOnPage(): void { $this->importCSVDataSet(__DIR__ . '/Fixtures/default_search_results_plugin.csv'); @@ -88,7 +84,7 @@ protected function bootstrapSearchResultsPluginOnPage(): void * @test * @group frontend */ - public function canShowSearchFormViaPlugin() + public function canShowSearchFormViaPlugin(): void { $response = $this->executeFrontendSubRequest($this->getPreparedRequest(2022)); $content = (string)$response->getBody(); diff --git a/Tests/Integration/IndexQueue/RecordMonitorTest.php b/Tests/Integration/IndexQueue/RecordMonitorTest.php index 4642c15109..eaf664d155 100644 --- a/Tests/Integration/IndexQueue/RecordMonitorTest.php +++ b/Tests/Integration/IndexQueue/RecordMonitorTest.php @@ -35,7 +35,6 @@ use TYPO3\CMS\Core\Localization\LanguageServiceFactory; use TYPO3\CMS\Core\Utility\GeneralUtility; use TYPO3\CMS\Scheduler\Scheduler; -use TYPO3\TestingFramework\Core\Exception as TestingFrameworkCoreException; /** * Testcase for the record monitor @@ -1838,7 +1837,6 @@ protected function prepareUpdateRecordMonitoringTablesTests(int $monitoringType, * This testcase checks if we can create a new testpage on the root level without any errors. * * @test - * @throws TestingFrameworkCoreException */ public function canCreateSiteOneRootLevel(): void { diff --git a/Tests/Integration/IntegrationTest.php b/Tests/Integration/IntegrationTest.php index b4bf5c1251..59506eb180 100644 --- a/Tests/Integration/IntegrationTest.php +++ b/Tests/Integration/IntegrationTest.php @@ -30,7 +30,6 @@ use TYPO3\CMS\Core\Site\SiteFinder; use TYPO3\CMS\Core\Tests\Functional\SiteHandling\SiteBasedTestTrait; use TYPO3\CMS\Core\Utility\GeneralUtility; -use TYPO3\TestingFramework\Core\Exception as TestingFrameworkCoreException; use TYPO3\TestingFramework\Core\Functional\Framework\Frontend\InternalRequest; use TYPO3\TestingFramework\Core\Functional\Framework\Frontend\InternalRequestContext; use TYPO3\TestingFramework\Core\Functional\FunctionalTestCase; @@ -149,8 +148,6 @@ protected function assertSolrContainsDocumentCount(int $documentCount): void * To add or override TypoScript setting please use following typo3/testing-framework methods: * * {@link addTypoScriptToTemplateRecord()} * * {@link setUpFrontendRootPage()} - * - * @throws TestingFrameworkCoreException */ protected function writeDefaultSolrTestSiteConfiguration(): void { diff --git a/ext_localconf.php b/ext_localconf.php index b54427c4e8..6d45ad5761 100644 --- a/ext_localconf.php +++ b/ext_localconf.php @@ -1,7 +1,9 @@ 'Solr Indexer Authorization', + 'description' => 'Authorizes the Solr Index Queue indexer to access protected pages.', + 'subtype' => 'getUserFE,authUserFE', + 'available' => true, + 'priority' => 100, + 'quality' => 100, + + 'os' => '', + 'exec' => '', + 'className' => AuthorizationService::class, + ] + ); })(); $isComposerMode = defined('TYPO3_COMPOSER_MODE') && TYPO3_COMPOSER_MODE;