diff --git a/.editorconfig b/.editorconfig index d1bdb6df20..c4163d0163 100644 --- a/.editorconfig +++ b/.editorconfig @@ -1,9 +1,10 @@ # EditorConfig is awesome: http://EditorConfig.org -# TYPO3 Standard: https://github.com/TYPO3/TYPO3.CMS/blob/master/.editorconfig +# TYPO3 Standard: https://github.com/TYPO3/coding-standards # top-most EditorConfig file root = true +# Unix-style newlines with a newline ending every file [*] charset = utf-8 end_of_line = lf @@ -12,19 +13,37 @@ indent_size = 4 insert_final_newline = true trim_trailing_whitespace = true +# TS/JS-Files +[*.{ts,js}] +indent_size = 2 + # JSON-Files [*.json] -indent_size = 2 +indent_style = tab # ReST-Files [*.rst] -indent_size = 3 +indent_size = 4 max_line_length = 80 # YAML-Files [*.{yaml,yml}] indent_size = 2 +# NEON-Files +[*.neon] +indent_size = 2 +indent_style = tab + +# package.json +[package.json] +indent_size = 2 + +# composer.json (Reason: git history in composer.json) +[composer.json] +indent_size = 2 +indent_style = space + # TypoScript [*.{typoscript,tsconfig}] indent_size = 2 @@ -33,6 +52,15 @@ indent_size = 2 [*.{xlf,xml}] indent_style = tab +# SQL-Files +[*.sql] +indent_style = tab +indent_size = 2 + +# .htaccess +[{_.htaccess,.htaccess}] +indent_style = tab + # Bash scripts [*.sh] indent_style = space diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index c21bd52501..2627602edb 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -130,7 +130,7 @@ jobs: name: Mount RAMFS run: | sudo mkdir -p ${{ env.CI_BUILD_DIRECTORY }} - sudo mount -t tmpfs -o size=2048m none ${{ env.CI_BUILD_DIRECTORY }} + sudo mount -t tmpfs -o size=2560m none ${{ env.CI_BUILD_DIRECTORY }} sudo mkdir -p ${{ env.CI_BUILD_DIRECTORY }}/data-{solr,mysql} \ && sudo chown $USER ${{ env.CI_BUILD_DIRECTORY }}/data-mysql \ && sudo chown 8983:8983 ${{ env.CI_BUILD_DIRECTORY }}/data-solr @@ -206,8 +206,8 @@ jobs: - name: Upload code coverage to Scrutinizer run: | - ocular code-coverage:upload --format=php-clover coverage.unit.clover - ocular code-coverage:upload --format=php-clover coverage.integration.clover + .Build/bin/ocular code-coverage:upload --format=php-clover coverage.unit.clover + .Build/bin/ocular code-coverage:upload --format=php-clover coverage.integration.clover - name: Clean up run: | diff --git a/.gitignore b/.gitignore index 81bf9a54b8..c90d70df64 100644 --- a/.gitignore +++ b/.gitignore @@ -1,18 +1,18 @@ +.Build .buildpath +.DS_Store +.idea/ +.php_cs.cache .project/ .settings/ -.idea/ atlassian-ide-plugin.xml -.DS_Store +composer.lock +Documentation/_make index.php typo3 -typo3_src typo3conf typo3temp +typo3_src uploads +var vendor -/composer.lock -.Build -Documentation/_make - -.php_cs.cache diff --git a/.php-cs-fixer.php b/.php-cs-fixer.php new file mode 100644 index 0000000000..4ea4def24a --- /dev/null +++ b/.php-cs-fixer.php @@ -0,0 +1,11 @@ +getFinder() + ->exclude([ + '.Build' + ]) + ->in(__DIR__); +return $config; diff --git a/Build/Helpers/GET_LACAL_BACKAGE_VERSION_CONSTRAINT.sh b/Build/Helpers/GET_LACAL_PACKAGE_VERSION_CONSTRAINT.sh similarity index 100% rename from Build/Helpers/GET_LACAL_BACKAGE_VERSION_CONSTRAINT.sh rename to Build/Helpers/GET_LACAL_PACKAGE_VERSION_CONSTRAINT.sh diff --git a/Build/Test/bootstrap.sh b/Build/Test/bootstrap.sh index 55cf88a838..f05b02ed5b 100755 --- a/Build/Test/bootstrap.sh +++ b/Build/Test/bootstrap.sh @@ -80,16 +80,7 @@ then exit 1 fi -# Install build tools -echo "Install build tools: " -if ! composer global require \ - friendsofphp/php-cs-fixer:"$PHP_CS_FIXER_VERSION" \ - sclable/xml-lint \ - scrutinizer/ocular -then - echo "The build tools(friendsofphp/php-cs-fixer, sclable/xml-lint, scrutinizer/ocular) could not be installed. Please fix this issue." - exit 1 -fi +COMPOSER_NO_INTERACTION=1 # Setup TYPO3 environment variables export TYPO3_PATH_PACKAGES="${EXTENSION_ROOTPATH}.Build/vendor/" @@ -123,14 +114,3 @@ then fi mkdir -p $TYPO3_PATH_WEB/uploads $TYPO3_PATH_WEB/typo3temp - -if [[ $* != *--skip-solr-install* ]]; then - # Setup Solr Using our install script - echo "Setup Solr Using our install script: " - chmod 500 ${EXTENSION_ROOTPATH}Resources/Private/Install/install-solr.sh - if ! ${EXTENSION_ROOTPATH}Resources/Private/Install/install-solr.sh -d "$HOME/solr" -t - then - echo "Apache Solr server could not be installed or started. Please fix this issue." - exit 1 - fi -fi diff --git a/Build/Test/cibuild.sh b/Build/Test/cibuild.sh index 3c0974f27e..f8840ffa32 100755 --- a/Build/Test/cibuild.sh +++ b/Build/Test/cibuild.sh @@ -30,19 +30,26 @@ else echo "No syntax errors! Great job!" fi -# use from vendor dir -if ! php-cs-fixer --version > /dev/null 2>&1 +echo "Check compliance against TYPO3 Coding Standards" +if ! .Build/bin/php-cs-fixer --version > /dev/null 2>&1 then - echo "PHP CS Fixer not found, skipping PHP linting." + echo "TYPO3 https://github.com/TYPO3/coding-standards is not set properly." + echo "Please fix that asap to avoid unwanted changes in the future." + exit 1 else - echo "Check PSR-2 compliance" - if ! php-cs-fixer fix --diff --verbose --dry-run --rules='{"function_declaration": {"closure_function_spacing": "none"}}' Classes + echo "TYPO3 Coding Standards compliance: See https://github.com/TYPO3/coding-standards" + if ! composer t3:standards:fix -- --diff --verbose --dry-run && rm .php-cs-fixer.cache then - echo "Some files are not PSR-2 compliant" - echo "Please fix the files listed above" + echo "Some files are not compliant to TYPO3 Coding Standards" + echo "Please fix the files listed above." + echo "Tip for auto fix: " + echo " composer install && composer exec php-cs-fixer fix" exit 1 + else + echo "The code is TYPO3 Coding Standards compliant! Great job!" fi fi +echo -e "\n\n" echo "Run XML Lint" if ! xmllint --version > /dev/null 2>&1; then @@ -50,7 +57,7 @@ if ! xmllint --version > /dev/null 2>&1; then else echo -e "\n\n" echo "Check syntax of XML files" - if ! xmllint Resources/Private/Language/ -p '*.xlf' + if ! composer lint:xlf then echo "Some XML files are not valid" echo "Please fix the files listed above" diff --git a/Classes/Access/Rootline.php b/Classes/Access/Rootline.php index bed7759ba2..7d68c7c8a8 100644 --- a/Classes/Access/Rootline.php +++ b/Classes/Access/Rootline.php @@ -15,6 +15,7 @@ namespace ApacheSolrForTypo3\Solr\Access; +use RuntimeException; use TYPO3\CMS\Core\Domain\Repository\PageRepository; use TYPO3\CMS\Core\Utility\GeneralUtility; use TYPO3\CMS\Core\Utility\RootlineUtility; @@ -57,7 +58,6 @@ */ class Rootline { - /** * Delimiter for page and content access right elements in the rootline. * @@ -70,15 +70,15 @@ class Rootline * * @var array */ - protected $rootlineElements = []; + protected array $rootlineElements = []; /** * Constructor, turns a string representation of an access rootline into an * object representation. * - * @param string $accessRootline Access Rootline String representation. + * @param string|null $accessRootline Access Rootline String representation. */ - public function __construct($accessRootline = null) + public function __construct(string $accessRootline = null) { if (!is_null($accessRootline)) { $rawRootlineElements = explode(self::ELEMENT_DELIMITER, $accessRootline); @@ -121,22 +121,22 @@ public function push(RootlineElement $rootlineElement) } /** - * Gets the Access Rootline for a specific page Id. + * Gets the Access Rootline for a specific page id. * - * @param int $pageId The page Id to generate the Access Rootline for. + * @param int $pageId The page id to generate the Access Rootline for. * @param string $mountPointParameter The mount point parameter for generating the rootline. - * @return \ApacheSolrForTypo3\Solr\Access\Rootline Access Rootline for the given page Id. + * @return Rootline Access Rootline for the given page id. */ public static function getAccessRootlineByPageId( - $pageId, - $mountPointParameter = '' - ) { + int $pageId, + string $mountPointParameter = '' + ): Rootline { /* @var Rootline $accessRootline */ $accessRootline = GeneralUtility::makeInstance(Rootline::class); $rootlineUtility = GeneralUtility::makeInstance(RootlineUtility::class, $pageId, $mountPointParameter); try { $rootline = $rootlineUtility->get(); - } catch (\RuntimeException $e) { + } catch (RuntimeException $e) { $rootline = []; } $rootline = array_reverse($rootline); @@ -148,12 +148,13 @@ public static function getAccessRootlineByPageId( ) { $accessRootline->push(GeneralUtility::makeInstance( RootlineElement::class, - /** @scrutinizer ignore-type */ $pageRecord['uid'] . RootlineElement::PAGE_ID_GROUP_DELIMITER . $pageRecord['fe_group'] + /** @scrutinizer ignore-type */ + $pageRecord['uid'] . RootlineElement::PAGE_ID_GROUP_DELIMITER . $pageRecord['fe_group'] )); } } - /** @var $pageSelector PageRepository */ + /** @var $pageSelector PageRepository */ $pageSelector = GeneralUtility::makeInstance(PageRepository::class); // current page @@ -161,7 +162,8 @@ public static function getAccessRootlineByPageId( if ($currentPageRecord['fe_group']) { $accessRootline->push(GeneralUtility::makeInstance( RootlineElement::class, - /** @scrutinizer ignore-type */ $currentPageRecord['uid'] . RootlineElement::PAGE_ID_GROUP_DELIMITER . $currentPageRecord['fe_group'] + /** @scrutinizer ignore-type */ + $currentPageRecord['uid'] . RootlineElement::PAGE_ID_GROUP_DELIMITER . $currentPageRecord['fe_group'] )); } @@ -185,11 +187,11 @@ public function __toString() } /** - * Gets a the groups in the Access Rootline. + * Gets the groups in the Access Rootline. * * @return array An array of sorted, unique user group IDs required to access a page. */ - public function getGroups() + public function getGroups(): array { $groups = []; @@ -198,19 +200,17 @@ public function getGroups() $groups = array_merge($groups, $rootlineElementGroups); } - $groups = $this->cleanGroupArray($groups); - - return $groups; + return $this->cleanGroupArray($groups); } /** - * Cleans an array of frontend user group IDs. Removes duplicates and sorts + * Cleans an array of frontend user group IDs. Removes the duplicates and sorts * the array. * * @param array $groups An array of frontend user group IDs * @return array An array of cleaned frontend user group IDs, unique, sorted. */ - public static function cleanGroupArray(array $groups) + public static function cleanGroupArray(array $groups): array { $groups = array_unique($groups); // removes duplicates sort($groups, SORT_NUMERIC); // sort diff --git a/Classes/Access/RootlineElement.php b/Classes/Access/RootlineElement.php index 8b7aec8605..cad65e7a67 100644 --- a/Classes/Access/RootlineElement.php +++ b/Classes/Access/RootlineElement.php @@ -66,9 +66,9 @@ class RootlineElement /** * Page Id for the element. NULL for the content type. * - * @var int + * @var int|null */ - protected $pageId = null; + protected ?int $pageId = null; /** * Set of access groups assigned to the element. @@ -116,7 +116,7 @@ public function __construct($element) ); } - $this->pageId = intval($elementAccess[0]); + $this->pageId = (int)($elementAccess[0]); $elementGroups = $elementAccess[1]; } diff --git a/Classes/AdditionalFieldsIndexer.php b/Classes/AdditionalFieldsIndexer.php index 7f99c436a4..d8ced978b8 100644 --- a/Classes/AdditionalFieldsIndexer.php +++ b/Classes/AdditionalFieldsIndexer.php @@ -1,5 +1,7 @@ configuration = $configuration === null ? Util::getSolrConfiguration() : $configuration; + public function __construct( + TypoScriptConfiguration $configuration = null, + ContentObjectService $contentObjectService = null + ) { + $this->configuration = $configuration ?? Util::getSolrConfiguration(); $this->additionalIndexingFields = $this->configuration->getIndexAdditionalFieldsConfiguration(); $this->additionalFieldNames = $this->configuration->getIndexMappedAdditionalFieldNames(); - $this->contentObjectService = $contentObjectService === null ? GeneralUtility::makeInstance(ContentObjectService::class) : $contentObjectService; + $this->contentObjectService = $contentObjectService ?? GeneralUtility::makeInstance(ContentObjectService::class); } /** @@ -71,16 +74,16 @@ public function __construct(TypoScriptConfiguration $configuration = null, Conte * Uses the original document and adds fields as defined in * plugin.tx_solr.index.additionalFields. * - * @param Document $pageDocument The original page document. + * @param Document $originalPageDocument The original page document. * @return Document A Apache Solr Document object that replace the default page document */ - public function getPageDocument(Document $pageDocument) + public function getPageDocument(Document $originalPageDocument): Document { - $substitutePageDocument = clone $pageDocument; + $substitutePageDocument = clone $originalPageDocument; $additionalFields = $this->getAdditionalFields(); foreach ($additionalFields as $fieldName => $fieldValue) { - if (!isset($pageDocument->{$fieldName})) { + if (!isset($originalPageDocument->{$fieldName})) { // making sure we only _add_ new fields $substitutePageDocument->setField($fieldName, $fieldValue); } @@ -94,7 +97,7 @@ public function getPageDocument(Document $pageDocument) * * @return array An array mapping additional field names to their values. */ - protected function getAdditionalFields() + protected function getAdditionalFields(): array { $additionalFields = []; @@ -111,7 +114,7 @@ protected function getAdditionalFields() * @param string $fieldName The name of the field to get. * @return string The field's value. */ - protected function getFieldValue($fieldName) + protected function getFieldValue(string $fieldName): string { return $this->contentObjectService->renderSingleContentObjectByArrayAndKey($this->additionalIndexingFields, $fieldName); } diff --git a/Classes/AdditionalPageIndexer.php b/Classes/AdditionalPageIndexer.php index 967b511c92..6f71cdec4a 100644 --- a/Classes/AdditionalPageIndexer.php +++ b/Classes/AdditionalPageIndexer.php @@ -25,7 +25,6 @@ */ interface AdditionalPageIndexer { - /** * Provides additional documents that should be indexed together with a page. * @@ -33,5 +32,5 @@ interface AdditionalPageIndexer * @param array $allDocuments An array containing all the documents collected until here, including the page document * @return array An array of additional \ApacheSolrForTypo3\Solr\System\Solr\Document\Document objects */ - public function getAdditionalPageDocuments(Document $pageDocument, array $allDocuments); + public function getAdditionalPageDocuments(Document $pageDocument, array $allDocuments): array; } diff --git a/Classes/Api.php b/Classes/Api.php index 6649ef8713..9ec3dcdb9b 100644 --- a/Classes/Api.php +++ b/Classes/Api.php @@ -31,7 +31,7 @@ class Api */ public static function isValidApiKey($apiKey) { - return ($apiKey === self::getApiKey()); + return $apiKey === self::getApiKey(); } /** diff --git a/Classes/Backend/CoreSelectorField.php b/Classes/Backend/CoreSelectorField.php index 81b82a9c62..dd2151d449 100644 --- a/Classes/Backend/CoreSelectorField.php +++ b/Classes/Backend/CoreSelectorField.php @@ -172,13 +172,16 @@ protected function renderSelectCheckbox(array $items, array $selectedValues): st 'itemFormElName' => $this->formElementName, 'itemFormElValue' => $selectedValues, 'fieldConf' => ['config' => ['items' => $items]], - 'fieldTSConfig' => ['noMatchingValue_label' => ''] + 'fieldTSConfig' => ['noMatchingValue_label' => ''], ]; $nodeFactory = GeneralUtility::makeInstance(NodeFactory::class); $options = [ - 'renderType' => 'selectCheckBox', 'table' => 'tx_solr_classes_backend_coreselector', - 'fieldName' => 'additionalFields', 'databaseRow' => [], 'parameterArray' => $parameterArray + 'renderType' => 'selectCheckBox', + 'table' => 'tx_solr_classes_backend_coreselector', + 'fieldName' => 'additionalFields', + 'databaseRow' => [], + 'parameterArray' => $parameterArray, ]; $selectCheckboxResult = $nodeFactory->create($options)->render(); diff --git a/Classes/Backend/IndexingConfigurationSelectorField.php b/Classes/Backend/IndexingConfigurationSelectorField.php index 068d2cd901..2d50956e98 100644 --- a/Classes/Backend/IndexingConfigurationSelectorField.php +++ b/Classes/Backend/IndexingConfigurationSelectorField.php @@ -184,7 +184,7 @@ protected function renderSelectCheckbox(array $items, ?array $selectedValues = [ 'itemFormElName' => $this->formElementName, 'itemFormElValue' => $selectedValues, 'fieldConf' => ['config' => ['items' => $items]], - 'fieldTSConfig' => ['noMatchingValue_label' => ''] + 'fieldTSConfig' => ['noMatchingValue_label' => ''], ]; $nodeFactory = GeneralUtility::makeInstance(NodeFactory::class); @@ -192,8 +192,10 @@ protected function renderSelectCheckbox(array $items, ?array $selectedValues = [ 'type' => 'select', 'renderType' => 'selectCheckBox', 'table' => 'tx_solr_classes_backend_indexingconfigurationselector', 'tableName' => 'tx_solr_classes_backend_indexingconfigurationselector', - 'fieldName' => 'additionalFields', 'databaseRow' => ['uid' => 0], 'parameterArray' => $parameterArray, - 'processedTca' => ['columns' => ['additionalFields' => ['config' => ['type' => 'select']]]] + 'fieldName' => 'additionalFields', + 'databaseRow' => ['uid' => 0], + 'parameterArray' => $parameterArray, + 'processedTca' => ['columns' => ['additionalFields' => ['config' => ['type' => 'select']]]], ]; $options['parameterArray']['fieldConf']['config']['items'] = $items; $options['parameterArray']['fieldTSConfig']['noMatchingValue_label'] = ''; diff --git a/Classes/Backend/SiteSelectorField.php b/Classes/Backend/SiteSelectorField.php index 8b4865f680..d965d64278 100644 --- a/Classes/Backend/SiteSelectorField.php +++ b/Classes/Backend/SiteSelectorField.php @@ -15,8 +15,8 @@ namespace ApacheSolrForTypo3\Solr\Backend; -use ApacheSolrForTypo3\Solr\Domain\Site\SiteRepository; use ApacheSolrForTypo3\Solr\Domain\Site\Site; +use ApacheSolrForTypo3\Solr\Domain\Site\SiteRepository; use Doctrine\DBAL\Driver\Exception as DBALDriverException; use Throwable; use TYPO3\CMS\Core\Utility\GeneralUtility; diff --git a/Classes/ConnectionManager.php b/Classes/ConnectionManager.php index 9ee8e5b45e..0575f045d8 100644 --- a/Classes/ConnectionManager.php +++ b/Classes/ConnectionManager.php @@ -1,5 +1,7 @@ systemLanguageRepository = $systemLanguageRepository ?? GeneralUtility::makeInstance(SystemLanguageRepository::class); - $this->siteRepository = $siteRepository ?? GeneralUtility::makeInstance(SiteRepository::class); + $this->siteRepository = $siteRepository ?? GeneralUtility::makeInstance(SiteRepository::class); $this->pagesRepositoryAtExtSolr = $pagesRepositoryAtExtSolr ?? GeneralUtility::makeInstance(PagesRepositoryAtExtSolr::class); } @@ -80,7 +81,7 @@ public function __construct( */ public function getSolrConnectionForNodes(array $readNodeConfiguration, array $writeNodeConfiguration) { - $connectionHash = md5(json_encode($readNodeConfiguration) . json_encode($writeNodeConfiguration)); + $connectionHash = md5(json_encode($readNodeConfiguration) . json_encode($writeNodeConfiguration)); if (!isset(self::$connections[$connectionHash])) { $readNode = Node::fromArray($readNodeConfiguration); $writeNode = Node::fromArray($writeNodeConfiguration); @@ -111,6 +112,7 @@ public function getConnectionFromConfiguration(array $config) * @param ?int $language The language ID to get the connection for as the path may differ. Optional, defaults to 0. * @param ?string $mount Comma list of MountPoint parameters * @return SolrConnection A solr connection. + * @throws DBALDriverException * @throws NoSolrConnectionFoundException */ public function getConnectionByPageId(int $pageId, int $language = 0, string $mount = ''): SolrConnection @@ -131,6 +133,7 @@ public function getConnectionByPageId(int $pageId, int $language = 0, string $mo * @param int $pageId A root page ID. * @param ?int $language The language ID to get the connection for as the path may differ. Optional, defaults to 0. * @return SolrConnection A solr connection. + * @throws DBALDriverException * @throws NoSolrConnectionFoundException */ public function getConnectionByRootPageId(int $pageId, ?int $language = 0): SolrConnection @@ -188,7 +191,7 @@ public function getConnectionsBySite(Site $site): array * @return string Connection label * @todo Remove, since not used, or take used. */ - protected function buildConnectionLabel(array $connection) + protected function buildConnectionLabel(array $connection): string { return $connection['rootPageTitle'] . ' (pid: ' . $connection['rootPageUid'] @@ -197,7 +200,7 @@ protected function buildConnectionLabel(array $connection) . $connection['read']['host'] . ':' . $connection['read']['port'] . $connection['read']['path'] - .' - Write node: ' + . ' - Write node: ' . $connection['write']['host'] . ':' . $connection['write']['port'] . $connection['write']['path']; @@ -241,13 +244,12 @@ protected function throwExceptionOnInvalidSite(?Site $site, string $message) protected function buildNoConnectionException(string $message): NoSolrConnectionFoundException { /* @var NoSolrConnectionFoundException $noSolrConnectionException */ - $noSolrConnectionException = GeneralUtility::makeInstance( + return GeneralUtility::makeInstance( NoSolrConnectionFoundException::class, /** @scrutinizer ignore-type */ $message, /** @scrutinizer ignore-type */ 1575396474 ); - return $noSolrConnectionException; } } diff --git a/Classes/ContentObject/Classification.php b/Classes/ContentObject/Classification.php index cc640394b2..853ba186f5 100644 --- a/Classes/ContentObject/Classification.php +++ b/Classes/ContentObject/Classification.php @@ -47,10 +47,10 @@ class Classification extends AbstractContentObject * Returns mapped classes when the field matches on of the configured patterns ... * * @inheritDoc + * @noinspection PhpMissingReturnTypeInspection, because foreign source inheritance See {@link AbstractContentObject::render()} */ public function render($conf = []) { - if (!is_array($conf['classes.'])) { throw new InvalidArgumentException('No class configuration configured for SOLR_CLASSIFICATION object. Given configuration: ' . serialize($conf)); } @@ -80,15 +80,15 @@ public function render($conf = []) * @param array $configuredMappedClasses * @return ClassificationItem[] */ - protected function buildClassificationsFromConfiguration($configuredMappedClasses) : array + protected function buildClassificationsFromConfiguration(array $configuredMappedClasses): array { $classifications = []; foreach ($configuredMappedClasses as $class) { - if ( (empty($class['patterns']) && empty($class['matchPatterns'])) || empty($class['class'])) { + if ((empty($class['patterns']) && empty($class['matchPatterns'])) || empty($class['class'])) { throw new InvalidArgumentException('A class configuration in SOLR_CLASSIFCATION needs to have a pattern and a class configured. Given configuration: ' . serialize($class)); } - // @todo deprecate patterns configuration + // @todo deprecate patterns configuration $patterns = empty($class['patterns']) ? [] : GeneralUtility::trimExplode(',', $class['patterns']); $matchPatterns = empty($class['matchPatterns']) ? [] : GeneralUtility::trimExplode(',', $class['matchPatterns']); $matchPatterns = $matchPatterns + $patterns; @@ -97,9 +97,12 @@ protected function buildClassificationsFromConfiguration($configuredMappedClasse $className = $class['class']; $classifications[] = GeneralUtility::makeInstance( ClassificationItem::class, - /** @scrutinizer ignore-type */ $matchPatterns, - /** @scrutinizer ignore-type */ $unMatchPatters, - /** @scrutinizer ignore-type */ $className + /** @scrutinizer ignore-type */ + $matchPatterns, + /** @scrutinizer ignore-type */ + $unMatchPatters, + /** @scrutinizer ignore-type */ + $className ); } diff --git a/Classes/ContentObject/Content.php b/Classes/ContentObject/Content.php index 3c56f205d3..a06a8125e1 100644 --- a/Classes/ContentObject/Content.php +++ b/Classes/ContentObject/Content.php @@ -36,12 +36,14 @@ class Content extends AbstractContentObject * Cleans content coming from a database field, removing HTML tags ... * * @inheritDoc + * @noinspection PhpMissingReturnTypeInspection, because foreign source inheritance See {@link AbstractContentObject::render()} */ public function render($conf = []) { $contentExtractor = GeneralUtility::makeInstance( HtmlContentExtractor::class, - /** @scrutinizer ignore-type */ $this->getRawContent($this->cObj, $conf) + /** @scrutinizer ignore-type */ + $this->getRawContent($this->cObj, $conf) ); return $contentExtractor->getIndexableContent(); @@ -54,7 +56,7 @@ public function render($conf = []) * @param array $configuration content object configuration * @return string The raw content */ - protected function getRawContent($contentObject, $configuration) + protected function getRawContent(ContentObjectRenderer $contentObject, array $configuration): string { $content = ''; if (isset($configuration['value'])) { @@ -63,7 +65,7 @@ protected function getRawContent($contentObject, $configuration) } if (!empty($configuration)) { - $content = $contentObject->stdWrap($content, $configuration); + $content = $contentObject->stdWrap($content, $configuration) ?? ''; } return $content; diff --git a/Classes/ContentObject/Multivalue.php b/Classes/ContentObject/Multivalue.php index adfaac4b25..6d78a07e4d 100644 --- a/Classes/ContentObject/Multivalue.php +++ b/Classes/ContentObject/Multivalue.php @@ -46,6 +46,7 @@ class Multivalue extends AbstractContentObject * serialized form as content objects are expected to return strings. * * @inheritDoc + * @noinspection PhpMissingReturnTypeInspection, because foreign source inheritance See {@link AbstractContentObject::render()} */ public function render($conf = []) { diff --git a/Classes/ContentObject/Relation.php b/Classes/ContentObject/Relation.php index bb09b40ef6..9d8017df9a 100644 --- a/Classes/ContentObject/Relation.php +++ b/Classes/ContentObject/Relation.php @@ -17,8 +17,8 @@ use ApacheSolrForTypo3\Solr\System\Language\FrontendOverlayService; use ApacheSolrForTypo3\Solr\System\TCA\TCAService; -use Doctrine\DBAL\Exception as DBALException; use Doctrine\DBAL\Driver\Statement; +use Doctrine\DBAL\Exception as DBALException; use ReflectionClass; use TYPO3\CMS\Core\Context\Exception\AspectNotFoundException; use TYPO3\CMS\Core\Database\ConnectionPool; @@ -98,7 +98,11 @@ public function __construct( * * @inheritDoc * + * @param array $conf + * @return string * @throws AspectNotFoundException + * @throws DBALException + * @noinspection PhpMissingReturnTypeInspection, because foreign source inheritance See {@link AbstractContentObject::render()} */ public function render($conf = []) { @@ -130,11 +134,12 @@ public function render($conf = []) * @return array Array of related items, values already resolved from related records * * @throws AspectNotFoundException + * @throws DBALException */ protected function getRelatedItems(ContentObjectRenderer $parentContentObject): array { list($table, $uid) = explode(':', $parentContentObject->currentRecord); - $uid = (int) $uid; + $uid = (int)$uid; $field = $this->configuration['localField']; if (!$this->tcaService->/** @scrutinizer ignore-call */ getHasConfigurationForField($table, $field)) { @@ -203,12 +208,11 @@ protected function getRelatedItemsFromMMTable(string $localTableName, int $local $contentObject->start($record, $foreignTableName); return $this->getRelatedItems($contentObject); - } else { - if ($this->getLanguageUid() > 0) { - $record = $this->frontendOverlayService->getOverlay($foreignTableName, $record); - } - $relatedItems[] = $record[$foreignTableLabelField]; } + if ($this->getLanguageUid() > 0) { + $record = $this->frontendOverlayService->getOverlay($foreignTableName, $record); + } + $relatedItems[] = $record[$foreignTableLabelField]; } return $relatedItems; @@ -253,9 +257,9 @@ protected function resolveForeignTableLabelField(array $foreignTableTca): ?strin * @throws DBALException */ protected function getRelatedItemsFromForeignTable( - string $localTableName, - int $localRecordUid, - array $localFieldTca, + string $localTableName, + int $localRecordUid, + array $localFieldTca, ContentObjectRenderer $parentContentObject ): array { $relatedItems = []; @@ -310,10 +314,10 @@ protected function getRelatedItemsFromForeignTable( */ protected function resolveRelatedValue( array $relatedRecord, - $foreignTableTca, - $foreignTableLabelField, + array $foreignTableTca, + string $foreignTableLabelField, ContentObjectRenderer $parentContentObject, - $foreignTableName = '' + string $foreignTableName = '' ): string { if ($this->getLanguageUid() > 0 && !empty($foreignTableName)) { $relatedRecord = $this->frontendOverlayService->getOverlay($foreignTableName, $relatedRecord); @@ -367,7 +371,7 @@ protected function resolveRelatedValue( * @param int ...$uids The uids to fetch from table. * @return array * - * @throws DBALException + * @throws \Doctrine\DBAL\DBALException */ protected function getRelatedRecords(string $foreignTable, int ...$uids): array { diff --git a/Classes/Controller/AbstractBaseController.php b/Classes/Controller/AbstractBaseController.php index 1329091e73..eafe3b8dc5 100644 --- a/Classes/Controller/AbstractBaseController.php +++ b/Classes/Controller/AbstractBaseController.php @@ -18,13 +18,13 @@ use ApacheSolrForTypo3\Solr\ConnectionManager; use ApacheSolrForTypo3\Solr\Domain\Search\ResultSet\SearchResultSetService; use ApacheSolrForTypo3\Solr\Domain\Search\SearchRequestBuilder; +use ApacheSolrForTypo3\Solr\Mvc\Controller\SolrControllerContext; use ApacheSolrForTypo3\Solr\NoSolrConnectionFoundException; use ApacheSolrForTypo3\Solr\Search; +use ApacheSolrForTypo3\Solr\System\Configuration\ConfigurationManager as SolrConfigurationManager; use ApacheSolrForTypo3\Solr\System\Configuration\TypoScriptConfiguration; -use ApacheSolrForTypo3\Solr\Mvc\Controller\SolrControllerContext; use ApacheSolrForTypo3\Solr\System\Logging\SolrLogManager; use ApacheSolrForTypo3\Solr\System\Service\ConfigurationService; -use ApacheSolrForTypo3\Solr\System\Configuration\ConfigurationManager as SolrConfigurationManager; use ApacheSolrForTypo3\Solr\Util; use TYPO3\CMS\Core\Context\Exception\AspectNotFoundException; use TYPO3\CMS\Core\TypoScript\TypoScriptService; @@ -92,7 +92,6 @@ abstract class AbstractBaseController extends ActionController /** * @param ConfigurationManagerInterface $configurationManager - * @return void */ public function injectConfigurationManager(ConfigurationManagerInterface $configurationManager) { @@ -205,8 +204,6 @@ protected function initializeAction() /** * Inject settings of plugin.tx_solr - * - * @return void */ protected function initializeSettings() { @@ -258,8 +255,6 @@ protected function getSearchRequestBuilder(): SearchRequestBuilder /** * Called when the solr server is unavailable. - * - * @return void */ protected function logSolrUnavailable() { diff --git a/Classes/Controller/Backend/PageModuleSummary.php b/Classes/Controller/Backend/PageModuleSummary.php index 63f51f93fa..573979d219 100644 --- a/Classes/Controller/Backend/PageModuleSummary.php +++ b/Classes/Controller/Backend/PageModuleSummary.php @@ -16,12 +16,12 @@ namespace ApacheSolrForTypo3\Solr\Controller\Backend; use TYPO3\CMS\Backend\Utility\BackendUtility; +use TYPO3\CMS\Backend\View\PageLayoutView; +use TYPO3\CMS\Core\Localization\LanguageService; use TYPO3\CMS\Core\Service\FlexFormService; use TYPO3\CMS\Core\Utility\GeneralUtility; use TYPO3\CMS\Extbase\Reflection\ObjectAccess; use TYPO3\CMS\Fluid\View\StandaloneView; -use TYPO3\CMS\Core\Localization\LanguageService; -use TYPO3\CMS\Backend\View\PageLayoutView; /** * Summary to display flexform settings in the page layout backend module. diff --git a/Classes/Controller/Backend/Search/AbstractModuleController.php b/Classes/Controller/Backend/Search/AbstractModuleController.php index f8fbf47059..d9811a9334 100644 --- a/Classes/Controller/Backend/Search/AbstractModuleController.php +++ b/Classes/Controller/Backend/Search/AbstractModuleController.php @@ -16,11 +16,11 @@ namespace ApacheSolrForTypo3\Solr\Controller\Backend\Search; use ApacheSolrForTypo3\Solr\ConnectionManager; -use ApacheSolrForTypo3\Solr\Domain\Site\SiteRepository; use ApacheSolrForTypo3\Solr\Domain\Site\Site; +use ApacheSolrForTypo3\Solr\Domain\Site\SiteRepository; use ApacheSolrForTypo3\Solr\IndexQueue\Queue; -use ApacheSolrForTypo3\Solr\System\Solr\SolrConnection as SolrCoreConnection; use ApacheSolrForTypo3\Solr\System\Mvc\Backend\Service\ModuleDataStorageService; +use ApacheSolrForTypo3\Solr\System\Solr\SolrConnection as SolrCoreConnection; use Doctrine\DBAL\Driver\Exception as DBALDriverException; use InvalidArgumentException; use Psr\Http\Message\ResponseInterface; @@ -137,7 +137,6 @@ public function __construct( * Purpose: Is already set in {@link processRequest} but wanted in PhpUnit * * @param UriBuilder $uriBuilder - * @return void */ public function injectUriBuilder(UriBuilder $uriBuilder) { @@ -209,7 +208,6 @@ protected function autoSelectFirstSiteAndRootPageWhenOnlyOneSiteIsAvailable(): b * Set up the doc header properly here * * @param ViewInterface $view - * @return void * @throws DBALDriverException * @throws Throwable */ @@ -283,7 +281,7 @@ protected function generateCoreSelectorMenu(Site $site, string $uriToRedirectTo 'switchCore', [ 'corePath' => $coreAdmin->getCorePath(), - 'uriToRedirectTo' => $uriToRedirectTo + 'uriToRedirectTo' => $uriToRedirectTo, ] ); $menuItem->setHref($uri); @@ -306,7 +304,6 @@ protected function generateCoreSelectorMenu(Site $site, string $uriToRedirectTo */ public function clearIndexQueueAction(): ResponseInterface { - $this->indexQueue->deleteItemsBySite($this->selectedSite); $this->addFlashMessage( LocalizationUtility::translate( @@ -349,7 +346,6 @@ public function switchCoreAction(string $corePath, string $uriToRedirectTo): Res */ protected function getModuleTemplateResponse(): ResponseInterface { - $this->moduleTemplate->setContent($this->view->render()); return $this->htmlResponse($this->moduleTemplate->renderContent()); } @@ -357,7 +353,6 @@ protected function getModuleTemplateResponse(): ResponseInterface /** * Initializes the solr core connection considerately to the components state. * Uses and persists default core connection if persisted core in Site does not exist. - * */ private function initializeSelectedSolrCoreConnection() { diff --git a/Classes/Controller/Backend/Search/CoreOptimizationModuleController.php b/Classes/Controller/Backend/Search/CoreOptimizationModuleController.php index 22c068b231..d30a36b4e8 100644 --- a/Classes/Controller/Backend/Search/CoreOptimizationModuleController.php +++ b/Classes/Controller/Backend/Search/CoreOptimizationModuleController.php @@ -35,7 +35,6 @@ class CoreOptimizationModuleController extends AbstractModuleController * Set up the doc header properly here * * @param ViewInterface $view - * @return void * @throws DBALDriverException * @throws InvalidViewObjectNameException * @throws Throwable @@ -74,7 +73,7 @@ public function indexAction(): ResponseInterface $this->view->assignMultiple([ 'synonyms' => $synonyms, 'stopWords' => implode(PHP_EOL, $stopWords), - 'stopWordsCount' => count($stopWords) + 'stopWordsCount' => count($stopWords), ]); return $this->getModuleTemplateResponse(); diff --git a/Classes/Controller/Backend/Search/InfoModuleController.php b/Classes/Controller/Backend/Search/InfoModuleController.php index 981c6f5ac1..3049c236bf 100644 --- a/Classes/Controller/Backend/Search/InfoModuleController.php +++ b/Classes/Controller/Backend/Search/InfoModuleController.php @@ -16,8 +16,8 @@ namespace ApacheSolrForTypo3\Solr\Controller\Backend\Search; use ApacheSolrForTypo3\Solr\Api; -use ApacheSolrForTypo3\Solr\Domain\Search\Statistics\StatisticsRepository; use ApacheSolrForTypo3\Solr\Domain\Search\ApacheSolrDocument\Repository as ApacheSolrDocumentRepository; +use ApacheSolrForTypo3\Solr\Domain\Search\Statistics\StatisticsRepository; use ApacheSolrForTypo3\Solr\System\Solr\ResponseAdapter; use ApacheSolrForTypo3\Solr\System\Validator\Path; use Psr\Http\Message\ResponseInterface; @@ -81,8 +81,6 @@ public function documentsDetailsAction(string $type, int $uid, int $pageId, int /** * Checks whether the configured Solr server can be reached and provides a * flash message according to the result of the check. - * - * @return void */ protected function collectConnectionInfos(): void { @@ -119,14 +117,12 @@ protected function collectConnectionInfos(): void 'apiKey' => Api::getApiKey(), 'connectedHosts' => $connectedHosts, 'missingHosts' => $missingHosts, - 'invalidPaths' => $invalidPaths + 'invalidPaths' => $invalidPaths, ]); } /** * Index action, shows an overview of the state of the Solr index - * - * @return void */ protected function collectStatistics(): void { @@ -165,8 +161,6 @@ protected function collectStatistics(): void /** * Gets Luke metadata for the currently selected core and provides a list * of that data. - * - * @return void */ protected function collectIndexFieldsInfo(): void { @@ -177,7 +171,7 @@ protected function collectIndexFieldsInfo(): void $coreAdmin = $solrCoreConnection->getAdminService(); $indexFieldsInfo = [ - 'corePath' => $coreAdmin->getCorePath() + 'corePath' => $coreAdmin->getCorePath(), ]; if ($coreAdmin->ping()) { $lukeData = $coreAdmin->getLukeMetaData(); @@ -218,8 +212,6 @@ protected function collectIndexFieldsInfo(): void /** * Retrieves the information for the index inspector. - * - * @return void */ protected function collectIndexInspectorInfo(): void { @@ -240,7 +232,7 @@ protected function collectIndexInspectorInfo(): void $this->view->assignMultiple([ 'pageId' => $this->selectedPageUID, - 'indexInspectorDocumentsByLanguageAndType' => $documentsByCoreAndType + 'indexInspectorDocumentsByLanguageAndType' => $documentsByCoreAndType, ]); } @@ -262,7 +254,7 @@ protected function getFields(ResponseAdapter $lukeData, string $limitNote): arra 'name' => $name, 'type' => $field->type, 'docs' => $field->docs ?? 0, - 'terms' => $field->distinct ?? $limitNote + 'terms' => $field->distinct ?? $limitNote, ]; } ksort($rows); @@ -284,7 +276,7 @@ protected function getCoreMetrics(ResponseAdapter $lukeData, array $fields): arr 'numberOfDocuments' => $lukeData->index->numDocs ?? 0, 'numberOfDeletedDocuments' => $lukeData->index->deletedDocs ?? 0, 'numberOfTerms' => $lukeData->index->numTerms ?? 0, - 'numberOfFields' => count($fields) + 'numberOfFields' => count($fields), ]; } } diff --git a/Classes/Controller/SearchController.php b/Classes/Controller/SearchController.php index f5e04cea43..5d547f3986 100644 --- a/Classes/Controller/SearchController.php +++ b/Classes/Controller/SearchController.php @@ -22,8 +22,8 @@ use ApacheSolrForTypo3\Solr\Util; use Psr\Http\Message\ResponseInterface; use TYPO3\CMS\Core\Context\Exception\AspectNotFoundException; -use TYPO3\CMS\Extbase\Http\ForwardResponse; 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; @@ -52,9 +52,6 @@ protected function initializeAction() $this->mapGlobalQueryStringWhenEnabled(); } - /** - * @return void - */ protected function mapGlobalQueryStringWhenEnabled() { $query = GeneralUtility::_GET('q'); @@ -148,7 +145,7 @@ public function formAction(): ResponseInterface $values = [ 'search' => $this->searchService->getSearch(), 'additionalFilters' => $this->getAdditionalFilters(), - 'pluginNamespace' => $this->typoScriptConfiguration->getSearchPluginNamespace() + 'pluginNamespace' => $this->typoScriptConfiguration->getSearchPluginNamespace(), ]; $values = $this->emitActionSignal(__CLASS__, __FUNCTION__, [$values]); @@ -173,7 +170,7 @@ public function frequentlySearchedAction(): ResponseInterface $values = [ 'additionalFilters' => $this->getAdditionalFilters(), - 'resultSet' => $searchResultSet + 'resultSet' => $searchResultSet, ]; $values = $this->emitActionSignal(__CLASS__, __FUNCTION__, [$values]); diff --git a/Classes/Controller/SuggestController.php b/Classes/Controller/SuggestController.php index 847cac4469..bfeb440bb0 100644 --- a/Classes/Controller/SuggestController.php +++ b/Classes/Controller/SuggestController.php @@ -15,11 +15,11 @@ namespace ApacheSolrForTypo3\Solr\Controller; -use Psr\Http\Message\ResponseInterface; - use ApacheSolrForTypo3\Solr\Domain\Search\Suggest\SuggestService; + use ApacheSolrForTypo3\Solr\System\Solr\SolrUnavailableException; use ApacheSolrForTypo3\Solr\Util; +use Psr\Http\Message\ResponseInterface; use TYPO3\CMS\Core\Context\Exception\AspectNotFoundException; use TYPO3\CMS\Core\Utility\GeneralUtility; diff --git a/Classes/Domain/Index/Classification/Classification.php b/Classes/Domain/Index/Classification/Classification.php index 7f4bc13fab..b793798539 100644 --- a/Classes/Domain/Index/Classification/Classification.php +++ b/Classes/Domain/Index/Classification/Classification.php @@ -1,6 +1,6 @@ matchPatterns = $matchPatterns; $this->unMatchPatterns = $unMatchPatterns; $this->mappedClass = $mappedClass; diff --git a/Classes/Domain/Index/Classification/ClassificationService.php b/Classes/Domain/Index/Classification/ClassificationService.php index 6b88241903..c3110a624d 100644 --- a/Classes/Domain/Index/Classification/ClassificationService.php +++ b/Classes/Domain/Index/Classification/ClassificationService.php @@ -1,6 +1,6 @@ applyMatchPatterns($stringToMatch, $classification, $matchingClassification); @@ -44,9 +47,11 @@ public function getMatchingClassNames(string $stringToMatch, $classifications) : * @param $matchingClassification * @return array */ - protected function applyMatchPatterns(string $stringToMatch, $classification, $matchingClassification): array - { - /** @var $classification Classification */ + protected function applyMatchPatterns( + string $stringToMatch, + Classification $classification, + $matchingClassification + ): array { foreach ($classification->getMatchPatterns() as $matchPattern) { if (preg_match_all('~' . $matchPattern . '~ims', $stringToMatch) > 0) { $matchingClassification[] = $classification->getMappedClass(); @@ -61,11 +66,13 @@ protected function applyMatchPatterns(string $stringToMatch, $classification, $m * @param string $stringToMatch * @param Classification $classification * @param $matchingClassification - * @param $messages * @return array */ - protected function applyUnMatchPatterns(string $stringToMatch, $classification, $matchingClassification): array - { + protected function applyUnMatchPatterns( + string $stringToMatch, + Classification $classification, + $matchingClassification + ): array { foreach ($classification->getUnMatchPatterns() as $unMatchPattern) { if (preg_match_all('~' . $unMatchPattern . '~ims', $stringToMatch) > 0) { // if we found one match, we do not need to check the other patterns diff --git a/Classes/Domain/Index/IndexService.php b/Classes/Domain/Index/IndexService.php index a440310b2a..050528fff3 100644 --- a/Classes/Domain/Index/IndexService.php +++ b/Classes/Domain/Index/IndexService.php @@ -16,16 +16,20 @@ namespace ApacheSolrForTypo3\Solr\Domain\Index; use ApacheSolrForTypo3\Solr\ConnectionManager; +use ApacheSolrForTypo3\Solr\Domain\Site\Site; use ApacheSolrForTypo3\Solr\IndexQueue\Indexer; use ApacheSolrForTypo3\Solr\IndexQueue\Item; use ApacheSolrForTypo3\Solr\IndexQueue\Queue; -use ApacheSolrForTypo3\Solr\Domain\Site\Site; use ApacheSolrForTypo3\Solr\System\Configuration\TypoScriptConfiguration; use ApacheSolrForTypo3\Solr\System\Logging\SolrLogManager; use ApacheSolrForTypo3\Solr\Task\IndexQueueWorkerTask; +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 @@ -34,25 +38,20 @@ */ class IndexService { - /** - * @var TypoScriptConfiguration - */ - protected $configuration; - /** * @var Site */ - protected $site; + protected Site $site; /** - * @var IndexQueueWorkerTask + * @var IndexQueueWorkerTask|null */ - protected $contextTask; + protected ?IndexQueueWorkerTask $contextTask = null; /** * @var Queue */ - protected $indexQueue; + protected Queue $indexQueue; /** * @var Dispatcher @@ -60,9 +59,9 @@ class IndexService protected $signalSlotDispatcher; /** - * @var \ApacheSolrForTypo3\Solr\System\Logging\SolrLogManager + * @var SolrLogManager */ - protected $logger = null; + protected SolrLogManager $logger; /** * IndexService constructor. @@ -71,8 +70,12 @@ class IndexService * @param Dispatcher|null $dispatcher * @param SolrLogManager|null $solrLogManager */ - public function __construct(Site $site, Queue $queue = null, Dispatcher $dispatcher = null, SolrLogManager $solrLogManager = null) - { + public function __construct( + Site $site, + Queue $queue = null, + Dispatcher $dispatcher = null, + SolrLogManager $solrLogManager = null + ) { $this->site = $site; $this->indexQueue = $queue ?? GeneralUtility::makeInstance(Queue::class); $this->signalSlotDispatcher = $dispatcher ?? GeneralUtility::makeInstance(Dispatcher::class); @@ -80,17 +83,17 @@ public function __construct(Site $site, Queue $queue = null, Dispatcher $dispatc } /** - * @param \ApacheSolrForTypo3\Solr\Task\IndexQueueWorkerTask $contextTask + * @param IndexQueueWorkerTask $contextTask */ - public function setContextTask($contextTask) + public function setContextTask(IndexQueueWorkerTask $contextTask) { $this->contextTask = $contextTask; } /** - * @return \ApacheSolrForTypo3\Solr\Task\IndexQueueWorkerTask + * @return IndexQueueWorkerTask */ - public function getContextTask() + public function getContextTask(): ?IndexQueueWorkerTask { return $this->contextTask; } @@ -100,8 +103,10 @@ public function getContextTask() * * @param int $limit * @return bool + * @throws InvalidSlotException + * @throws InvalidSlotReturnException */ - public function indexItems($limit) + public function indexItems(int $limit): bool { $errors = 0; $indexRunId = uniqid(); @@ -119,7 +124,7 @@ public function indexItems($limit) $this->emitSignal('beforeIndexItem', [$itemToIndex, $this->getContextTask(), $indexRunId]); $this->indexItem($itemToIndex, $configurationToUse); $this->emitSignal('afterIndexItem', [$itemToIndex, $this->getContextTask(), $indexRunId]); - } catch (\Throwable $e) { + } catch (Throwable $e) { $errors++; $this->indexQueue->markItemAsFailed($itemToIndex, $e->getCode() . ': ' . $e->__toString()); $this->generateIndexingErrorLog($itemToIndex, $e); @@ -132,23 +137,23 @@ public function indexItems($limit) $solrServers = GeneralUtility::makeInstance(ConnectionManager::class)->getConnectionsBySite($this->site); foreach ($solrServers as $solrServer) { try { - $solrServer->getWriteService()->commit(false, false, false); + $solrServer->getWriteService()->commit(false, false); } catch (HttpException $e) { $errors++; } } } - return ($errors === 0); + return $errors === 0; } /** - * Generates a message in the error log when an error occured. + * Generates a message in the error log when an error occurred. * * @param Item $itemToIndex - * @param \Throwable $e + * @param Throwable $e */ - protected function generateIndexingErrorLog(Item $itemToIndex, \Throwable $e) + protected function generateIndexingErrorLog(Item $itemToIndex, Throwable $e) { $message = 'Failed indexing Index Queue item ' . $itemToIndex->getIndexQueueUid(); $data = ['code' => $e->getCode(), 'message' => $e->getMessage(), 'trace' => $e->getTraceAsString(), 'item' => (array)$itemToIndex]; @@ -161,13 +166,15 @@ protected function generateIndexingErrorLog(Item $itemToIndex, \Throwable $e) } /** - * Builds an emits a singal for the IndexService. + * Builds an emits a signal for the IndexService. * * @param string $name * @param array $arguments * @return mixed + * @throws InvalidSlotException + * @throws InvalidSlotReturnException */ - protected function emitSignal($name, $arguments) + protected function emitSignal(string $name, array $arguments = []) { return $this->signalSlotDispatcher->dispatch(__CLASS__, $name, $arguments); } @@ -178,12 +185,13 @@ protected function emitSignal($name, $arguments) * @param Item $item An index queue item to index * @param TypoScriptConfiguration $configuration * @return bool TRUE if the item was successfully indexed, FALSE otherwise + * @throws Throwable */ - protected function indexItem(Item $item, TypoScriptConfiguration $configuration) + protected function indexItem(Item $item, TypoScriptConfiguration $configuration): bool { $indexer = $this->getIndexerByItem($item->getIndexingConfigurationName(), $configuration); // Remember original http host value - $originalHttpHost = isset($_SERVER['HTTP_HOST']) ? $_SERVER['HTTP_HOST'] : null; + $originalHttpHost = $_SERVER['HTTP_HOST'] ?? null; $itemChangedDate = $item->getChanged(); $itemChangedDateAfterIndex = 0; @@ -201,7 +209,7 @@ protected function indexItem(Item $item, TypoScriptConfiguration $configuration) if ($itemChangedDateAfterIndex > $itemChangedDate && $itemChangedDateAfterIndex > time()) { $this->indexQueue->setForcedChangeTimeByItem($item, $itemChangedDateAfterIndex); } - } catch (\Throwable $e) { + } catch (Throwable $e) { $this->restoreOriginalHttpHost($originalHttpHost); throw $e; } @@ -214,7 +222,7 @@ protected function indexItem(Item $item, TypoScriptConfiguration $configuration) /** * A factory method to get an indexer depending on an item's configuration. * - * By default all items are indexed using the default indexer + * By default, all items are indexed using the default indexer * (ApacheSolrForTypo3\Solr\IndexQueue\Indexer) coming with EXT:solr. Pages by default are * configured to be indexed through a dedicated indexer * (ApacheSolrForTypo3\Solr\IndexQueue\PageIndexer). In all other cases a dedicated indexer @@ -224,14 +232,16 @@ protected function indexItem(Item $item, TypoScriptConfiguration $configuration) * @param TypoScriptConfiguration $configuration * @return Indexer */ - protected function getIndexerByItem($indexingConfigurationName, TypoScriptConfiguration $configuration) - { + protected function getIndexerByItem( + string $indexingConfigurationName, + TypoScriptConfiguration $configuration + ): Indexer { $indexerClass = $configuration->getIndexQueueIndexerByConfigurationName($indexingConfigurationName); $indexerConfiguration = $configuration->getIndexQueueIndexerConfigurationByConfigurationName($indexingConfigurationName); $indexer = GeneralUtility::makeInstance($indexerClass, /** @scrutinizer ignore-type */ $indexerConfiguration); if (!($indexer instanceof Indexer)) { - throw new \RuntimeException( + throw new RuntimeException( 'The indexer class "' . $indexerClass . '" for indexing configuration "' . $indexingConfigurationName . '" is not a valid indexer. Must be a subclass of ApacheSolrForTypo3\Solr\IndexQueue\Indexer.', 1260463206 ); @@ -245,7 +255,7 @@ protected function getIndexerByItem($indexingConfigurationName, TypoScriptConfig * * @return float Indexing progress as a two decimal precision float. f.e. 44.87 */ - public function getProgress() + public function getProgress(): float { return $this->indexQueue->getStatisticsBySite($this->site)->getSuccessPercentage(); } @@ -255,7 +265,7 @@ public function getProgress() * * @return int */ - public function getFailCount() + public function getFailCount(): int { return $this->indexQueue->getStatisticsBySite($this->site)->getFailedCount(); } @@ -276,14 +286,14 @@ public function getFailCount() protected function initializeHttpServerEnvironment(Item $item) { static $hosts = []; - $rootpageId = $item->getRootPageUid(); - $hostFound = !empty($hosts[$rootpageId]); + $rootPageId = $item->getRootPageUid(); + $hostFound = !empty($hosts[$rootPageId]); if (!$hostFound) { - $hosts[$rootpageId] = $item->getSite()->getDomain(); + $hosts[$rootPageId] = $item->getSite()->getDomain(); } - $_SERVER['HTTP_HOST'] = $hosts[$rootpageId]; + $_SERVER['HTTP_HOST'] = $hosts[$rootPageId]; // needed since TYPO3 7.5 GeneralUtility::flushInternalRuntimeCaches(); @@ -292,7 +302,7 @@ protected function initializeHttpServerEnvironment(Item $item) /** * @param string|null $originalHttpHost */ - protected function restoreOriginalHttpHost($originalHttpHost) + protected function restoreOriginalHttpHost(?string $originalHttpHost) { if (!is_null($originalHttpHost)) { $_SERVER['HTTP_HOST'] = $originalHttpHost; diff --git a/Classes/Domain/Index/PageIndexer/Helper/UriBuilder/AbstractUriStrategy.php b/Classes/Domain/Index/PageIndexer/Helper/UriBuilder/AbstractUriStrategy.php index 869155571d..fe57f3074f 100644 --- a/Classes/Domain/Index/PageIndexer/Helper/UriBuilder/AbstractUriStrategy.php +++ b/Classes/Domain/Index/PageIndexer/Helper/UriBuilder/AbstractUriStrategy.php @@ -1,6 +1,6 @@ logger = $logger ?? GeneralUtility::makeInstance(SolrLogManager::class, /** @scrutinizer ignore-type */ __CLASS__); } @@ -64,7 +66,7 @@ protected function applyTypoScriptOverridesOnIndexingUrl(UrlHelper $urlHelper, a $urlHelper->setPort($overrideConfiguration['port']); } - // setting a path if TYPO3 is installed in a sub directory + // setting a path if TYPO3 is installed in a subdirectory if (!empty($overrideConfiguration['path'])) { $urlHelper->setPath($overrideConfiguration['path']); } @@ -79,8 +81,12 @@ protected function applyTypoScriptOverridesOnIndexingUrl(UrlHelper $urlHelper, a * @param array $options * @return string */ - public function getPageIndexingUriFromPageItemAndLanguageId(Item $item, int $language = 0, string $mountPointParameter = '', $options = []): string - { + public function getPageIndexingUriFromPageItemAndLanguageId( + Item $item, + int $language = 0, + string $mountPointParameter = '', + array $options = [] + ): string { $pageIndexUri = $this->buildPageIndexingUriFromPageItemAndLanguageId($item, $language, $mountPointParameter); $urlHelper = GeneralUtility::makeInstance(UrlHelper::class, $pageIndexUri); $overrideConfiguration = $options['frontendDataHelper.'] ?? []; @@ -98,17 +104,16 @@ public function getPageIndexingUriFromPageItemAndLanguageId(Item $item, int $lan 'host' => $urlHelper->getHost(), 'path' => $urlHelper->getPath(), 'page ID' => $item->getRecordUid(), - 'indexer options' => $options + 'indexer options' => $options, ] ); - throw new \RuntimeException( + throw new RuntimeException( 'Could not create a valid URL to get frontend data while trying to index a page. Created URL: ' . $dataUrl, 1311080805 ); } - return $this->applyDataUrlModifier($item, $language, $dataUrl, $urlHelper); } @@ -118,7 +123,11 @@ public function getPageIndexingUriFromPageItemAndLanguageId(Item $item, int $lan * @param string $mountPointParameter * @return mixed */ - abstract protected function buildPageIndexingUriFromPageItemAndLanguageId(Item $item, int $language = 0, string $mountPointParameter = ''); + abstract protected function buildPageIndexingUriFromPageItemAndLanguageId( + Item $item, + int $language = 0, + string $mountPointParameter = '' + ); /** * @param Item $item @@ -127,21 +136,26 @@ abstract protected function buildPageIndexingUriFromPageItemAndLanguageId(Item $ * @param UrlHelper $urlHelper * @return string */ - protected function applyDataUrlModifier(Item $item, int $language, $dataUrl, UrlHelper $urlHelper):string - { + protected function applyDataUrlModifier( + Item $item, + int $language, + string $dataUrl, + UrlHelper $urlHelper + ): string { if (empty($GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['solr']['IndexQueuePageIndexer']['dataUrlModifier'])) { return $dataUrl; } $dataUrlModifier = GeneralUtility::makeInstance($GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['solr']['IndexQueuePageIndexer']['dataUrlModifier']); if (!$dataUrlModifier instanceof PageIndexerDataUrlModifier) { - throw new \RuntimeException($GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['solr']['IndexQueuePageIndexer']['dataUrlModifier'] . ' is not an implementation of ApacheSolrForTypo3\Solr\IndexQueue\PageIndexerDataUrlModifier', 1290523345); + throw new RuntimeException($GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['solr']['IndexQueuePageIndexer']['dataUrlModifier'] . ' is not an implementation of ApacheSolrForTypo3\Solr\IndexQueue\PageIndexerDataUrlModifier', 1290523345); } - return $dataUrlModifier->modifyDataUrl($dataUrl, + return $dataUrlModifier->modifyDataUrl( + $dataUrl, [ 'item' => $item, 'scheme' => $urlHelper->getScheme(), 'host' => $urlHelper->getHost(), - 'path' => $urlHelper->getPath(), 'pageId' => $item->getRecordUid(), 'language' => $language + 'path' => $urlHelper->getPath(), 'pageId' => $item->getRecordUid(), 'language' => $language, ] ); } diff --git a/Classes/Domain/Index/PageIndexer/Helper/UriBuilder/TYPO3SiteStrategy.php b/Classes/Domain/Index/PageIndexer/Helper/UriBuilder/TYPO3SiteStrategy.php index d8ddc9096d..733c146657 100644 --- a/Classes/Domain/Index/PageIndexer/Helper/UriBuilder/TYPO3SiteStrategy.php +++ b/Classes/Domain/Index/PageIndexer/Helper/UriBuilder/TYPO3SiteStrategy.php @@ -1,6 +1,6 @@ siteFinder = $siteFinder ?? GeneralUtility::makeInstance(SiteFinder::class); } @@ -53,22 +54,23 @@ public function __construct(SolrLogManager $logger = null, SiteFinder $siteFinde * @param string $mountPointParameter * @return string * @throws SiteNotFoundException - * @throws InvalidRouteArgumentsException */ - protected function buildPageIndexingUriFromPageItemAndLanguageId(Item $item, int $language = 0, string $mountPointParameter = '') - { + protected function buildPageIndexingUriFromPageItemAndLanguageId( + Item $item, + int $language = 0, + string $mountPointParameter = '' + ): string { $site = $this->siteFinder->getSiteByPageId((int)$item->getRecordUid()); $parameters = []; if ($language > 0) { $parameters['_language'] = $language; - }; + } if ($mountPointParameter !== '') { $parameters['MP'] = $mountPointParameter; } - $pageIndexUri = (string)$site->getRouter()->generateUri($item->getRecord(), $parameters); - return $pageIndexUri; + return (string)$site->getRouter()->generateUri($item->getRecord(), $parameters); } } diff --git a/Classes/Domain/Index/PageIndexer/Helper/UriStrategyFactory.php b/Classes/Domain/Index/PageIndexer/Helper/UriStrategyFactory.php index a52228180d..5093566456 100644 --- a/Classes/Domain/Index/PageIndexer/Helper/UriStrategyFactory.php +++ b/Classes/Domain/Index/PageIndexer/Helper/UriStrategyFactory.php @@ -1,6 +1,6 @@ queue = $queue ?? GeneralUtility::makeInstance(Queue::class); $this->connectionManager = $connectionManager ?? GeneralUtility::makeInstance(ConnectionManager::class); } /** - * Call's the removal of the strategy and afterwards the garbagecollector post processing hook. + * Call's the removal of the strategy and afterwards the garbage-collector post-processing hook. * * @param string $table * @param int $uid - * @return mixed */ - public function removeGarbageOf($table, $uid) + public function removeGarbageOf(string $table, int $uid) { $this->removeGarbageOfByStrategy($table, $uid); $this->callPostProcessGarbageCollectorHook($table, $uid); } /** - * A implementation of the GarbageCollection strategy is responsible to remove the garbage from + * An implementation of the GarbageCollection strategy is responsible to remove the garbage from * the indexqueue and from the solr server. * * @param string $table * @param int $uid */ - abstract protected function removeGarbageOfByStrategy($table, $uid); + abstract protected function removeGarbageOfByStrategy(string $table, int $uid); /** * Deletes a document from solr and from the index queue. * * @param string $table - * @param integer $uid + * @param int $uid */ - protected function deleteInSolrAndRemoveFromIndexQueue($table, $uid) + protected function deleteInSolrAndRemoveFromIndexQueue(string $table, int $uid) { $this->deleteIndexDocuments($table, $uid); $this->queue->deleteItem($table, $uid); @@ -87,9 +87,9 @@ protected function deleteInSolrAndRemoveFromIndexQueue($table, $uid) * Deletes a document from solr and updates the item in the index queue (e.g. on page content updates). * * @param string $table - * @param integer $uid + * @param int $uid */ - protected function deleteInSolrAndUpdateIndexQueue($table, $uid) + protected function deleteInSolrAndUpdateIndexQueue(string $table, int $uid) { $this->deleteIndexDocuments($table, $uid); $this->queue->updateItem($table, $uid); @@ -101,7 +101,7 @@ protected function deleteInSolrAndUpdateIndexQueue($table, $uid) * @param string $table The record's table name. * @param int $uid The record's uid. */ - protected function deleteIndexDocuments($table, $uid, $language = 0) + protected function deleteIndexDocuments(string $table, int $uid, int $language = 0) { // record can be indexed for multiple sites $indexQueueItems = $this->queue->getItems($table, $uid); @@ -125,12 +125,19 @@ protected function deleteIndexDocuments($table, $uid, $language = 0) * @param int $uid * @param SolrConnection[] $solrConnections * @param string $siteHash - * @param boolean $enableCommitsSetting + * @param bool $enableCommitsSetting */ - protected function deleteRecordInAllSolrConnections($table, $uid, $solrConnections, $siteHash, $enableCommitsSetting) - { + protected function deleteRecordInAllSolrConnections( + string $table, + int $uid, + array $solrConnections, + string $siteHash, + bool $enableCommitsSetting + ) { foreach ($solrConnections as $solr) { - $solr->getWriteService()->deleteByQuery('type:' . $table . ' AND uid:' . (int)$uid . ' AND siteHash:' . $siteHash); + $solr->getWriteService()->deleteByQuery( + 'type:' . $table . ' AND uid:' . $uid . ' AND siteHash:' . $siteHash + ); if ($enableCommitsSetting) { $solr->getWriteService()->commit(false, false); } @@ -138,12 +145,12 @@ protected function deleteRecordInAllSolrConnections($table, $uid, $solrConnectio } /** - * Calls the registered post processing hooks after the garbageCollection. + * Calls the registered post-processing hooks after the garbageCollection. * * @param string $table * @param int $uid */ - protected function callPostProcessGarbageCollectorHook($table, $uid) + protected function callPostProcessGarbageCollectorHook(string $table, int $uid) { if (!is_array($GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['solr']['postProcessGarbageCollector'] ?? null)) { return; diff --git a/Classes/Domain/Index/Queue/GarbageRemover/PageStrategy.php b/Classes/Domain/Index/Queue/GarbageRemover/PageStrategy.php index 37670c0872..07f4fab110 100644 --- a/Classes/Domain/Index/Queue/GarbageRemover/PageStrategy.php +++ b/Classes/Domain/Index/Queue/GarbageRemover/PageStrategy.php @@ -17,17 +17,16 @@ use TYPO3\CMS\Backend\Utility\BackendUtility; - /** * Class PageStrategy */ -class PageStrategy extends AbstractStrategy { - +class PageStrategy extends AbstractStrategy +{ /** * @param string $table * @param int $uid */ - protected function removeGarbageOfByStrategy($table, $uid) + protected function removeGarbageOfByStrategy(string $table, int $uid) { if ($table === 'tt_content') { $this->collectPageGarbageByContentChange($uid); @@ -40,12 +39,12 @@ protected function removeGarbageOfByStrategy($table, $uid) } /** - * Determines the relevant page id for an content element update. Deletes the page from solr and requeues the + * Determines the relevant page id for a content element update. Deletes the page from solr and requeues the * page for a reindex. * * @param int $ttContentUid */ - protected function collectPageGarbageByContentChange($ttContentUid) + protected function collectPageGarbageByContentChange(int $ttContentUid) { $contentElement = BackendUtility::getRecord('tt_content', $ttContentUid, 'uid, pid', '', false); $this->deleteInSolrAndUpdateIndexQueue('pages', $contentElement['pid']); @@ -56,10 +55,10 @@ protected function collectPageGarbageByContentChange($ttContentUid) * * @param int $uid */ - protected function collectPageGarbageByPageChange($uid) + protected function collectPageGarbageByPageChange(int $uid) { $pageOverlay = BackendUtility::getRecord('pages', $uid, 'l10n_parent, sys_language_uid', '', false); - if (!empty($pageOverlay['l10n_parent']) && intval($pageOverlay['l10n_parent']) !== 0) { + if (!empty($pageOverlay['l10n_parent']) && (int)($pageOverlay['l10n_parent']) !== 0) { $this->deleteIndexDocuments('pages', (int)$pageOverlay['l10n_parent'], (int)$pageOverlay['sys_language_uid']); } else { $this->deleteInSolrAndRemoveFromIndexQueue('pages', $uid); diff --git a/Classes/Domain/Index/Queue/GarbageRemover/RecordStrategy.php b/Classes/Domain/Index/Queue/GarbageRemover/RecordStrategy.php index 10bb2c1f1c..570e994ba8 100644 --- a/Classes/Domain/Index/Queue/GarbageRemover/RecordStrategy.php +++ b/Classes/Domain/Index/Queue/GarbageRemover/RecordStrategy.php @@ -20,15 +20,15 @@ /** * Class RecordStrategy */ -class RecordStrategy extends AbstractStrategy { - +class RecordStrategy extends AbstractStrategy +{ /** * Removes the garbage of a record. * * @param string $table * @param int $uid */ - protected function removeGarbageOfByStrategy($table, $uid) + protected function removeGarbageOfByStrategy(string $table, int $uid) { $languageField = $GLOBALS['TCA'][$table]['ctrl']['languageField'] ?? false; $transOrigPointerField = $GLOBALS['TCA'][$table]['ctrl']['transOrigPointerField'] ?? false; diff --git a/Classes/Domain/Index/Queue/GarbageRemover/StrategyFactory.php b/Classes/Domain/Index/Queue/GarbageRemover/StrategyFactory.php index b9ff14a0e4..6dc425f8b0 100644 --- a/Classes/Domain/Index/Queue/GarbageRemover/StrategyFactory.php +++ b/Classes/Domain/Index/Queue/GarbageRemover/StrategyFactory.php @@ -1,5 +1,7 @@ * @author Ingo Renner */ -class QueueInitializationService { +class QueueInitializationService +{ /** * @var Queue */ - protected $queue; + protected Queue $queue; /** * QueueInitializationService constructor. @@ -54,8 +59,11 @@ public function __construct(Queue $queue) * @param string $indexingConfigurationName Name of a specific indexing configuration, when * is passed any is used * @return array An array of booleans, each representing whether the * initialization for an indexing configuration was successful + * @throws ConnectionException + * @throws DBALException + * @throws Throwable */ - public function initializeBySiteAndIndexConfiguration(Site $site, $indexingConfigurationName = '*'): array + public function initializeBySiteAndIndexConfiguration(Site $site, string $indexingConfigurationName = '*'): array { return $this->initializeBySiteAndIndexConfigurations($site, [$indexingConfigurationName]); } @@ -66,11 +74,14 @@ public function initializeBySiteAndIndexConfiguration(Site $site, $indexingConfi * @param array $sites The array of sites to initialize * @param array $indexingConfigurationNames the array of index configurations to initialize. * @return array + * @throws ConnectionException + * @throws DBALException + * @throws Throwable */ public function initializeBySitesAndConfigurations(array $sites, array $indexingConfigurationNames = ['*']): array { $initializationStatesBySiteId = []; - foreach($sites as $site) { + foreach ($sites as $site) { /** @var Site $site */ $initializationResult = $this->initializeBySiteAndIndexConfigurations($site, $indexingConfigurationNames); $initializationStatesBySiteId[$site->getRootPageId()] = $initializationResult; @@ -85,6 +96,9 @@ public function initializeBySitesAndConfigurations(array $sites, array $indexing * @param Site $site * @param array $indexingConfigurationNames if one of the names is a * (wildcard) all configurations are used, * @return array + * @throws ConnectionException + * @throws Throwable + * @throws DBALException */ public function initializeBySiteAndIndexConfigurations(Site $site, array $indexingConfigurationNames): array { @@ -105,7 +119,7 @@ public function initializeBySiteAndIndexConfigurations(Site $site, array $indexi if ($indexQueueInitializationPostProcessor instanceof InitializationPostProcessor) { $indexQueueInitializationPostProcessor->postProcessIndexQueueInitialization($site, $indexingConfigurationNames, $initializationStatus); } else { - throw new \UnexpectedValueException(get_class($indexQueueInitializationPostProcessor) . ' must implement interface ' . InitializationPostProcessor::class, 1345815561); + throw new UnexpectedValueException(get_class($indexQueueInitializationPostProcessor) . ' must implement interface ' . InitializationPostProcessor::class, 1345815561); } } @@ -119,8 +133,11 @@ public function initializeBySiteAndIndexConfigurations(Site $site, array $indexi * @param string $indexingConfigurationName name of a specific * indexing configuration * @return bool TRUE if the initialization was successful, FALSE otherwise + * @throws ConnectionException + * @throws DBALException + * @throws Throwable */ - protected function applyInitialization(Site $site, $indexingConfigurationName): bool + protected function applyInitialization(Site $site, string $indexingConfigurationName): bool { // clear queue $this->queue->deleteItemsBySite($site, $indexingConfigurationName); @@ -141,8 +158,13 @@ protected function applyInitialization(Site $site, $indexingConfigurationName): * @param array $indexConfiguration * @return bool */ - protected function executeInitializer(Site $site, $indexingConfigurationName, $initializerClass, $tableToIndex, $indexConfiguration): bool - { + protected function executeInitializer( + Site $site, + string $indexingConfigurationName, + string $initializerClass, + string $tableToIndex, + array $indexConfiguration + ): bool { $initializer = GeneralUtility::makeInstance($initializerClass); /* @var AbstractInitializer $initializer */ $initializer->setSite($site); @@ -152,5 +174,4 @@ protected function executeInitializer(Site $site, $indexingConfigurationName, $i return $initializer->initialize(); } - } diff --git a/Classes/Domain/Index/Queue/QueueItemRepository.php b/Classes/Domain/Index/Queue/QueueItemRepository.php index 1ce7ed4364..721788526f 100644 --- a/Classes/Domain/Index/Queue/QueueItemRepository.php +++ b/Classes/Domain/Index/Queue/QueueItemRepository.php @@ -17,13 +17,13 @@ namespace ApacheSolrForTypo3\Solr\Domain\Index\Queue; -use ApacheSolrForTypo3\Solr\IndexQueue\Item; use ApacheSolrForTypo3\Solr\Domain\Site\Site; +use ApacheSolrForTypo3\Solr\IndexQueue\Item; use ApacheSolrForTypo3\Solr\System\Logging\SolrLogManager; use ApacheSolrForTypo3\Solr\System\Records\AbstractRepository; use Doctrine\DBAL\ConnectionException; -use Doctrine\DBAL\Exception as DBALException; use Doctrine\DBAL\Driver\Exception as DBALDriverException; +use Doctrine\DBAL\Exception as DBALException; use PDO; use Throwable; use TYPO3\CMS\Core\Database\ConnectionPool; @@ -34,19 +34,18 @@ /** * Class QueueItemRepository * Handles all CRUD operations to tx_solr_indexqueue_item table - * */ class QueueItemRepository extends AbstractRepository { /** * @var string */ - protected $table = 'tx_solr_indexqueue_item'; + protected string $table = 'tx_solr_indexqueue_item'; /** * @var SolrLogManager */ - protected $logger; + protected SolrLogManager $logger; /** * QueueItemRepository constructor. @@ -69,8 +68,7 @@ public function __construct(SolrLogManager $logManager = null) * @return array * * @throws DBALDriverException - * - * @throws \Doctrine\DBAL\DBALException + * @throws DBALException|\Doctrine\DBAL\DBALException */ public function findLastIndexedRow(int $rootPageId): array { @@ -99,7 +97,7 @@ public function findLastIndexedRow(int $rootPageId): array * @return array Error items for the current site's Index Queue * * @throws DBALDriverException - * @throws \Doctrine\DBAL\DBALException + * @throws DBALException|\Doctrine\DBAL\DBALException */ public function findErrorsBySite(Site $site): array { @@ -121,7 +119,7 @@ public function findErrorsBySite(Site $site): array * * @return int affected rows * - * @throws \Doctrine\DBAL\DBALException + * @throws DBALException|\Doctrine\DBAL\DBALException */ public function flushAllErrors(): int { @@ -136,7 +134,7 @@ public function flushAllErrors(): int * @param Site $site * @return int * - * @throws \Doctrine\DBAL\DBALException + * @throws DBALException|\Doctrine\DBAL\DBALException */ public function flushErrorsBySite(Site $site): int { @@ -155,7 +153,7 @@ public function flushErrorsBySite(Site $site): int * @param Item $item * @return int affected rows * - * @throws \Doctrine\DBAL\DBALException + * @throws DBALException|\Doctrine\DBAL\DBALException */ public function flushErrorByItem(Item $item): int { @@ -196,7 +194,7 @@ private function getPreparedFlushErrorQuery(QueryBuilder $queryBuilder): QueryBu * @param string $indexingConfiguration The name of the related indexConfiguration * @return int affected rows * - * @throws \Doctrine\DBAL\DBALException + * @throws DBALException|\Doctrine\DBAL\DBALException */ public function updateExistingItemByItemTypeAndItemUidAndRootPageId( string $itemType, @@ -237,7 +235,7 @@ public function updateExistingItemByItemTypeAndItemUidAndRootPageId( * @param string $indexingConfiguration The item's indexing configuration to use. Optional, overwrites existing / determined configuration. * @return int the number of inserted rows, which is typically 1 * - * @throws \Doctrine\DBAL\DBALException + * @throws DBALException|\Doctrine\DBAL\DBALException */ public function add( string $itemType, @@ -255,7 +253,7 @@ public function add( 'item_uid' => $itemUid, 'changed' => $changedTime, 'errors' => '', - 'indexing_configuration' => $indexingConfiguration + 'indexing_configuration' => $indexingConfiguration, ]) ->execute(); } @@ -271,7 +269,7 @@ public function add( * @return int * * @throws DBALDriverException - * @throws \Doctrine\DBAL\DBALException + * @throws DBALException|\Doctrine\DBAL\DBALException */ public function countItems( array $sites = [], @@ -309,7 +307,7 @@ public function countItems( * @return int|null Timestamp of the most recent content element change or null if nothing is found. * * @throws DBALDriverException - * @throws \Doctrine\DBAL\DBALException + * @throws DBALException|\Doctrine\DBAL\DBALException */ public function getPageItemChangedTimeByPageUid(int $pageUid): ?int { @@ -338,7 +336,7 @@ public function getPageItemChangedTimeByPageUid(int $pageUid): ?int * @return int Timestamp of the most recent content element change * * @throws DBALDriverException - * @throws \Doctrine\DBAL\DBALException + * @throws DBALException|\Doctrine\DBAL\DBALException */ public function getLocalizableItemChangedTime(string $itemType, int $itemUid): int { @@ -391,8 +389,8 @@ protected function getQueryBuilderForContainsMethods(string $itemType, int $item * @param int $itemUid The item's uid * @return bool TRUE if the item is found in the queue, FALSE otherwise * - * @throws \Doctrine\DBAL\DBALException * @throws DBALDriverException + * @throws DBALException|\Doctrine\DBAL\DBALException */ public function containsItem(string $itemType, int $itemUid): bool { @@ -406,11 +404,11 @@ public function containsItem(string $itemType, int $itemUid): bool * * @param string $itemType The item's type, usually a table name. * @param int $itemUid The item's uid - * @param integer $rootPageId + * @param int $rootPageId * @return bool TRUE if the item is found in the queue, FALSE otherwise * - * @throws \Doctrine\DBAL\DBALException * @throws DBALDriverException + * @throws DBALException|\Doctrine\DBAL\DBALException */ public function containsItemWithRootPageId(string $itemType, int $itemUid, int $rootPageId): bool { @@ -429,8 +427,8 @@ public function containsItemWithRootPageId(string $itemType, int $itemUid, int $ * @param int $itemUid The item's uid * @return bool TRUE if the item is found in the queue and marked as indexed, FALSE otherwise * - * @throws \Doctrine\DBAL\DBALException * @throws DBALDriverException + * @throws DBALException|\Doctrine\DBAL\DBALException */ public function containsIndexedItem(string $itemType, int $itemUid): bool { @@ -449,7 +447,7 @@ public function containsIndexedItem(string $itemType, int $itemUid): bool * * @throws ConnectionException * @throws Throwable - * @throws \Doctrine\DBAL\DBALException + * @throws DBALException */ public function deleteItem(string $itemType, int $itemUid = null) { @@ -464,7 +462,7 @@ public function deleteItem(string $itemType, int $itemUid = null) * * @throws ConnectionException * @throws Throwable - * @throws \Doctrine\DBAL\DBALException + * @throws DBALException */ public function deleteItemsByType(string $itemType) { @@ -480,7 +478,7 @@ public function deleteItemsByType(string $itemType) * * @throws ConnectionException * @throws Throwable - * @throws \Doctrine\DBAL\DBALException + * @throws DBALException */ public function deleteItemsBySite(Site $site, string $indexingConfigurationName = '') { @@ -498,7 +496,7 @@ public function deleteItemsBySite(Site $site, string $indexingConfigurationName * @param array $uids * * @throws ConnectionException - * @throws \Doctrine\DBAL\DBALException + * @throws DBALException * @throws Throwable */ public function deleteItems( @@ -509,10 +507,10 @@ public function deleteItems( array $uids = [] ): void { $rootPageIds = Site::getRootPageIdsFromSites($sites); - $indexQueueConfigurationList = implode(",", $indexQueueConfigurationNames); - $itemTypeList = implode(",", $itemTypes); - $itemUids = array_map("intval", $itemUids); - $uids = array_map("intval", $uids); + $indexQueueConfigurationList = implode(',', $indexQueueConfigurationNames); + $itemTypeList = implode(',', $itemTypes); + $itemUids = array_map('intval', $itemUids); + $uids = array_map('intval', $uids); $queryBuilderForDeletingItems = $this->getQueryBuilder(); $queryBuilderForDeletingItems->delete($this->table); @@ -607,7 +605,7 @@ private function addItemWhereClauses( * @return QueryBuilder * * @throws DBALDriverException - * @throws \Doctrine\DBAL\DBALException + * @throws DBALException|\Doctrine\DBAL\DBALException */ private function buildQueryForPropertyDeletion( QueryBuilder $queryBuilderForDeletingItems, @@ -675,7 +673,7 @@ public function deleteAllItems(): int * @return Item|null The request Index Queue item or NULL if no item with $itemId was found * * @throws DBALDriverException - * @throws \Doctrine\DBAL\DBALException + * @throws DBALException|\Doctrine\DBAL\DBALException */ public function findItemByUid(int $uid): ?Item { @@ -704,7 +702,7 @@ public function findItemByUid(int $uid): ?Item * @throws ConnectionException * @throws DBALDriverException * @throws Throwable - * @throws \Doctrine\DBAL\DBALException + * @throws DBALException */ public function findItemsByItemTypeAndItemUid(string $itemType, int $itemUid): array { @@ -727,7 +725,7 @@ public function findItemsByItemTypeAndItemUid(string $itemType, int $itemUid): a * @throws ConnectionException * @throws DBALDriverException * @throws Throwable - * @throws \Doctrine\DBAL\DBALException + * @throws DBALException */ protected function getItemsByCompositeExpression( CompositeExpression $expression = null, @@ -756,7 +754,7 @@ protected function getItemsByCompositeExpression( * @throws ConnectionException * @throws DBALDriverException * @throws Throwable - * @throws \Doctrine\DBAL\DBALException + * @throws DBALException */ public function findAll(): array { @@ -779,7 +777,7 @@ public function findAll(): array * @throws ConnectionException * @throws DBALDriverException * @throws Throwable - * @throws \Doctrine\DBAL\DBALException + * @throws DBALException */ public function findItemsToIndex(Site $site, int $limit = 50): array { @@ -823,7 +821,7 @@ public function findItemsToIndex(Site $site, int $limit = 50): array * @throws ConnectionException * @throws DBALDriverException * @throws Throwable - * @throws \Doctrine\DBAL\DBALException + * @throws DBALException */ public function findItems( array $sites = [], @@ -831,14 +829,14 @@ public function findItems( array $itemTypes = [], array $itemUids = [], array $uids = [], - int $start = 0, - int $limit = 50 + int $start = 0, + int $limit = 50 ): array { $rootPageIds = Site::getRootPageIdsFromSites($sites); - $indexQueueConfigurationList = implode(",", $indexQueueConfigurationNames); - $itemTypeList = implode(",", $itemTypes); - $itemUids = array_map("intval", $itemUids); - $uids = array_map("intval", $uids); + $indexQueueConfigurationList = implode(',', $indexQueueConfigurationNames); + $itemTypeList = implode(',', $itemTypes); + $itemUids = array_map('intval', $itemUids); + $uids = array_map('intval', $uids); $itemQueryBuilder = $this->getQueryBuilder()->select('*')->from($this->table); $itemQueryBuilder = $this->addItemWhereClauses($itemQueryBuilder, $rootPageIds, $indexQueueConfigurationList, $itemTypeList, $itemUids, $uids); $itemRecords = $itemQueryBuilder->setFirstResult($start) @@ -858,7 +856,7 @@ public function findItems( * @throws ConnectionException * @throws DBALDriverException * @throws Throwable - * @throws \Doctrine\DBAL\DBALException + * @throws DBALException */ protected function getIndexQueueItemObjectsFromRecords(array $indexQueueItemRecords): array { @@ -873,7 +871,7 @@ protected function getIndexQueueItemObjectsFromRecords(array $indexQueueItemReco * @return array * * @throws DBALDriverException - * @throws \Doctrine\DBAL\DBALException + * @throws DBALException|\Doctrine\DBAL\DBALException */ protected function getAllQueueItemRecordsByUidsGroupedByTable(array $indexQueueItemRecords): array { @@ -913,8 +911,6 @@ protected function getAllQueueItemRecordsByUidsGroupedByTable(array $indexQueueI * @param string $table * @param array $uids * @param array $tableRecords - * - * @return void */ protected function hookPostProcessFetchRecordsForIndexQueueItem(string $table, array $uids, array &$tableRecords) { @@ -936,7 +932,7 @@ protected function hookPostProcessFetchRecordsForIndexQueueItem(string $table, a * * @throws ConnectionException * @throws Throwable - * @throws \Doctrine\DBAL\DBALException + * @throws DBALException */ protected function getQueueItemObjectsByRecords(array $indexQueueItemRecords, array $tableRecords): array { @@ -955,7 +951,7 @@ protected function getQueueItemObjectsByRecords(array $indexQueueItemRecords, ar SolrLogManager::ERROR, 'Record missing for Index Queue item. Item removed.', [ - $indexQueueItemRecord + $indexQueueItemRecord, ] ); $this->deleteItem( @@ -976,7 +972,7 @@ protected function getQueueItemObjectsByRecords(array $indexQueueItemRecords, ar * @param string $errorMessage Error message * @return int affected rows * - * @throws \Doctrine\DBAL\DBALException + * @throws DBALException|\Doctrine\DBAL\DBALException */ public function markItemAsFailed($item, string $errorMessage = ''): int { @@ -997,7 +993,7 @@ public function markItemAsFailed($item, string $errorMessage = ''): int * @param Item $item * @return int affected rows * - * @throws \Doctrine\DBAL\DBALException + * @throws DBALException|\Doctrine\DBAL\DBALException */ public function updateIndexTimeByItem(Item $item): int { @@ -1016,9 +1012,9 @@ public function updateIndexTimeByItem(Item $item): int * @param int $changedTime * @return int affected rows * - * @throws \Doctrine\DBAL\DBALException + * @throws DBALException|\Doctrine\DBAL\DBALException */ - public function updateChangedTimeByItem(Item $item, int $changedTime): int + public function updateChangedTimeByItem(Item $item, int $changedTime = 0): int { $queryBuilder = $this->getQueryBuilder(); return (int)$queryBuilder @@ -1053,7 +1049,7 @@ public function initializeByNativeSQLStatement(string $sqlStatement): int * @return array pageIds from mountPoints that already have a queue entry * * @throws DBALDriverException - * @throws \Doctrine\DBAL\DBALException + * @throws DBALException|\Doctrine\DBAL\DBALException */ public function findPageIdsOfExistingMountPagesByMountIdentifier(string $identifier): array { @@ -1088,7 +1084,7 @@ public function findPageIdsOfExistingMountPagesByMountIdentifier(string $identif * @return array * * @throws DBALDriverException - * @throws \Doctrine\DBAL\DBALException + * @throws DBALException|\Doctrine\DBAL\DBALException */ public function findAllIndexQueueItemsByRootPidAndMountIdentifierAndMountedPids( int $rootPid, @@ -1117,7 +1113,7 @@ public function findAllIndexQueueItemsByRootPidAndMountIdentifierAndMountedPids( * @param bool $hasIndexingPropertiesFlag * @return int number of affected rows, 1 on success * - * @throws \Doctrine\DBAL\DBALException + * @throws DBALException|\Doctrine\DBAL\DBALException */ public function updateHasIndexingPropertiesFlagByItemUid(int $itemUid, bool $hasIndexingPropertiesFlag): int { diff --git a/Classes/Domain/Index/Queue/RecordMonitor/Helper/ConfigurationAwareRecordService.php b/Classes/Domain/Index/Queue/RecordMonitor/Helper/ConfigurationAwareRecordService.php index 8a45bab309..395b36667a 100644 --- a/Classes/Domain/Index/Queue/RecordMonitor/Helper/ConfigurationAwareRecordService.php +++ b/Classes/Domain/Index/Queue/RecordMonitor/Helper/ConfigurationAwareRecordService.php @@ -32,12 +32,15 @@ class ConfigurationAwareRecordService * Retrieves the name of the Index Queue Configuration for a record. * * @param string $recordTable Table to read from - * @param int $recordUid Id of the record + * @param int $recordUid id of the record * @param TypoScriptConfiguration $solrConfiguration * @return string|null Name of indexing configuration */ - public function getIndexingConfigurationName($recordTable, $recordUid, TypoScriptConfiguration $solrConfiguration) - { + public function getIndexingConfigurationName( + string $recordTable, + int $recordUid, + TypoScriptConfiguration $solrConfiguration + ): ?string { $name = null; $indexingConfigurations = $solrConfiguration->getEnabledIndexQueueConfigurationNames(); foreach ($indexingConfigurations as $indexingConfigurationName) { @@ -46,8 +49,12 @@ public function getIndexingConfigurationName($recordTable, $recordUid, TypoScrip continue; } - $record = $this->getRecordIfIndexConfigurationIsValid($recordTable, $recordUid, - $indexingConfigurationName, $solrConfiguration); + $record = $this->getRecordIfIndexConfigurationIsValid( + $recordTable, + $recordUid, + $indexingConfigurationName, + $solrConfiguration + ); if (!empty($record)) { $name = $indexingConfigurationName; // FIXME currently returns after the first configuration match @@ -63,17 +70,24 @@ public function getIndexingConfigurationName($recordTable, $recordUid, TypoScrip * Indexing Queue configurations. * * @param string $recordTable Table to read from - * @param int $recordUid Id of the record + * @param int $recordUid id of the record * @param TypoScriptConfiguration $solrConfiguration * @return array Record if found, otherwise empty array */ - public function getRecord($recordTable, $recordUid, TypoScriptConfiguration $solrConfiguration) - { + public function getRecord( + string $recordTable, + int $recordUid, + TypoScriptConfiguration $solrConfiguration + ): array { $record = []; $indexingConfigurations = $solrConfiguration->getEnabledIndexQueueConfigurationNames(); foreach ($indexingConfigurations as $indexingConfigurationName) { - $record = $this->getRecordIfIndexConfigurationIsValid($recordTable, $recordUid, - $indexingConfigurationName, $solrConfiguration); + $record = $this->getRecordIfIndexConfigurationIsValid( + $recordTable, + $recordUid, + $indexingConfigurationName, + $solrConfiguration + ); if (!empty($record)) { // if we found a record which matches the conditions, we can continue break; @@ -84,25 +98,27 @@ public function getRecord($recordTable, $recordUid, TypoScriptConfiguration $sol /** * This method return the record array if the table is valid for this indexingConfiguration. - * Otherwise an empty array will be returned. + * Otherwise, an empty array will be returned. * * @param string $recordTable - * @param integer $recordUid + * @param int $recordUid * @param string $indexingConfigurationName * @param TypoScriptConfiguration $solrConfiguration * @return array */ - protected function getRecordIfIndexConfigurationIsValid($recordTable, $recordUid, $indexingConfigurationName, TypoScriptConfiguration $solrConfiguration) - { + protected function getRecordIfIndexConfigurationIsValid( + string $recordTable, + int $recordUid, + string $indexingConfigurationName, + TypoScriptConfiguration $solrConfiguration + ): array { if (!$this->isValidTableForIndexConfigurationName($recordTable, $indexingConfigurationName, $solrConfiguration)) { return []; } $recordWhereClause = $solrConfiguration->getIndexQueueAdditionalWhereClauseByConfigurationName($indexingConfigurationName); - $row = $this->getRecordForIndexConfigurationIsValid($recordTable, $recordUid, $recordWhereClause); - - return $row; + return $this->getRecordForIndexConfigurationIsValid($recordTable, $recordUid, $recordWhereClause); } /** @@ -110,13 +126,16 @@ protected function getRecordIfIndexConfigurationIsValid($recordTable, $recordUid * or from cache * * @param string $recordTable - * @param integer $recordUid + * @param int $recordUid * @param string $recordWhereClause * * @return array */ - protected function getRecordForIndexConfigurationIsValid($recordTable, $recordUid, $recordWhereClause) - { + protected function getRecordForIndexConfigurationIsValid( + string $recordTable, + int $recordUid, + string $recordWhereClause = '' + ): array { $cache = GeneralUtility::makeInstance(TwoLevelCache::class, /** @scrutinizer ignore-type */ 'runtime'); $cacheId = md5('ConfigurationAwareRecordService' . ':' . 'getRecordIfIndexConfigurationIsValid' . ':' . $recordTable . ':' . $recordUid . ':' . $recordWhereClause); @@ -128,7 +147,7 @@ protected function getRecordForIndexConfigurationIsValid($recordTable, $recordUi $row = (array)BackendUtility::getRecord($recordTable, $recordUid, '*', $recordWhereClause); $cache->set($cacheId, $row); - return $row; + return $row ?? []; } /** @@ -137,10 +156,13 @@ protected function getRecordForIndexConfigurationIsValid($recordTable, $recordUi * @param string $recordTable * @param string $indexingConfigurationName * @param TypoScriptConfiguration $solrConfiguration - * @return boolean + * @return bool */ - protected function isValidTableForIndexConfigurationName($recordTable, $indexingConfigurationName, TypoScriptConfiguration $solrConfiguration) - { + protected function isValidTableForIndexConfigurationName( + string $recordTable, + string $indexingConfigurationName, + TypoScriptConfiguration $solrConfiguration + ): bool { $tableToIndex = $solrConfiguration->getIndexQueueTableNameOrFallbackToConfigurationName($indexingConfigurationName); $isMatchingTable = ($tableToIndex === $recordTable); @@ -151,26 +173,4 @@ protected function isValidTableForIndexConfigurationName($recordTable, $indexing return false; } - - /** - * This method retrieves the parent pages record when the parent record is accessible - * through the recordWhereClause - * - * @param int $recordUid - * @param string $parentWhereClause - * @return array - */ - protected function getPageOverlayRecordIfParentIsAccessible($recordUid, $parentWhereClause) - { - $overlayRecord = (array)BackendUtility::getRecord('pages', $recordUid, '*'); - $overlayParentId = $overlayRecord['l10n_parent']; - - $pageRecord = (array)BackendUtility::getRecord('pages', $overlayParentId, '*', $parentWhereClause); - - if (empty($pageRecord)) { - return []; - } - - return $overlayRecord; - } } diff --git a/Classes/Domain/Index/Queue/RecordMonitor/Helper/MountPagesUpdater.php b/Classes/Domain/Index/Queue/RecordMonitor/Helper/MountPagesUpdater.php index bd69b905a2..ba59b8b29b 100644 --- a/Classes/Domain/Index/Queue/RecordMonitor/Helper/MountPagesUpdater.php +++ b/Classes/Domain/Index/Queue/RecordMonitor/Helper/MountPagesUpdater.php @@ -30,7 +30,6 @@ */ class MountPagesUpdater { - /** * @var PagesRepository */ @@ -41,17 +40,18 @@ class MountPagesUpdater * * @param PagesRepository|null $pagesRepository */ - public function __construct(PagesRepository $pagesRepository = null) { + public function __construct(PagesRepository $pagesRepository = null) + { $this->pagesRepository = $pagesRepository ?? GeneralUtility::makeInstance(PagesRepository::class); } /** * Handles updates of the Index Queue in case a newly created or changed - * page is part of a tree that is mounted into a another site. + * page is part of a tree that is mounted into another site. * * @param int $pageId Page Id (uid). */ - public function update($pageId) + public function update(int $pageId) { // get the root line of the page, every parent page could be a Mount Page source $rootlineUtility = GeneralUtility::makeInstance(RootlineUtility::class, $pageId); @@ -68,7 +68,7 @@ public function update($pageId) return; } - /** @var $rootLine Rootline */ + /* @var Rootline $rootLine */ $rootLine = GeneralUtility::makeInstance(Rootline::class, /** @scrutinizer ignore-type */ $rootLineArray); $rootLineParentPageIds = array_map('intval', $rootLine->getParentPageIds()); $destinationMountProperties = $this->pagesRepository->findMountPointPropertiesByPageIdOrByRootLineParentPageIds($currentPageUid, $rootLineParentPageIds); @@ -88,12 +88,12 @@ public function update($pageId) * @param int $mountedPageId ID (uid) of the mounted page. * @param array $mountProperties Array of mount point properties mountPageSource, mountPageDestination, and mountPageOverlayed */ - protected function addPageToMountingSiteIndexQueue($mountedPageId, array $mountProperties) + protected function addPageToMountingSiteIndexQueue(int $mountedPageId, array $mountProperties) { $siteRepository = GeneralUtility::makeInstance(SiteRepository::class); $mountingSite = $siteRepository->getSiteByPageId($mountProperties['mountPageDestination']); - /** @var $pageInitializer Page */ + /* @var Page $pageInitializer */ $pageInitializer = GeneralUtility::makeInstance(Page::class); $pageInitializer->setSite($mountingSite); $pageInitializer->setIndexingConfigurationName('pages'); diff --git a/Classes/Domain/Index/Queue/RecordMonitor/Helper/RootPageResolver.php b/Classes/Domain/Index/Queue/RecordMonitor/Helper/RootPageResolver.php index 325a1e5bd1..7e683fd41e 100644 --- a/Classes/Domain/Index/Queue/RecordMonitor/Helper/RootPageResolver.php +++ b/Classes/Domain/Index/Queue/RecordMonitor/Helper/RootPageResolver.php @@ -1,5 +1,7 @@ recordService = $recordService ?? GeneralUtility::makeInstance(ConfigurationAwareRecordService::class); $this->runtimeCache = $twoLevelCache ?? GeneralUtility::makeInstance(TwoLevelCache::class, /** @scrutinizer ignore-type */ 'runtime'); $this->extensionConfiguration = GeneralUtility::makeInstance(ExtensionConfiguration::class); @@ -71,8 +78,10 @@ public function __construct(ConfigurationAwareRecordService $recordService = nul * @param string $table * @param int $uid * @return array + * @throws DBALDriverException + * @throws Throwable */ - public function getResponsibleRootPageIds($table, $uid) + public function getResponsibleRootPageIds(string $table, int $uid): array { $cacheId = 'RootPageResolver' . '_' . 'getResponsibleRootPageIds' . '_' . $table . '_' . $uid; $methodResult = $this->runtimeCache->get($cacheId); @@ -92,7 +101,7 @@ public function getResponsibleRootPageIds($table, $uid) * @param int $pageId Page ID * @return bool TRUE if the page is marked as root page, FALSE otherwise */ - public function getIsRootPageId($pageId) + public function getIsRootPageId(int $pageId): bool { // Page 0 can never be a root page if ($pageId === 0) { @@ -113,7 +122,7 @@ public function getIsRootPageId($pageId) $page = $this->getPageRecordByPageId($pageId); if (empty($page)) { // @todo: 1636120156 See \ApacheSolrForTypo3\Solr\Tests\Integration\IndexQueue\FrontendHelper\PageIndexerTest::phpProcessDoesNotDieIfPageIsNotAvailable() - throw new \InvalidArgumentException( + throw new InvalidArgumentException( 'The page for the given page ID \'' . $pageId . '\' could not be found in the database and can therefore not be used as site root page.', 1487171426 @@ -127,13 +136,13 @@ public function getIsRootPageId($pageId) } /** - * @param $pageId + * @param int $pageId * @param string $fieldList * @return array */ - protected function getPageRecordByPageId($pageId, $fieldList = 'is_siteroot') + protected function getPageRecordByPageId(int $pageId, string $fieldList = 'is_siteroot'): array { - return (array)BackendUtility::getRecord('pages', $pageId, $fieldList); + return BackendUtility::getRecord('pages', $pageId, $fieldList) ?? []; } /** @@ -144,11 +153,14 @@ protected function getPageRecordByPageId($pageId, $fieldList = 'is_siteroot') * @param string $mountPointIdentifier * @return int The page's tree branch's root page ID */ - public function getRootPageId($pageId = 0, $forceFallback = false, $mountPointIdentifier = '') - { + public function getRootPageId( + int $pageId = 0, + bool $forceFallback = false, + string $mountPointIdentifier = '' + ): int { /** @var Rootline $rootLine */ $rootLine = GeneralUtility::makeInstance(Rootline::class); - $rootPageId = intval($pageId) ?: intval($GLOBALS['TSFE']->id); + $rootPageId = $pageId ?: (int)($GLOBALS['TSFE']->id); // frontend if (!empty($GLOBALS['TSFE']->rootLine)) { @@ -160,7 +172,7 @@ public function getRootPageId($pageId = 0, $forceFallback = false, $mountPointId $rootlineUtility = GeneralUtility::makeInstance(RootlineUtility::class, $pageId, $mountPointIdentifier); try { $rootLineArray = $rootlineUtility->get(); - } catch (\RuntimeException $e) { + } catch (RuntimeException $e) { $rootLineArray = []; } $rootLine->setRootLineArray($rootLineArray); @@ -171,16 +183,17 @@ public function getRootPageId($pageId = 0, $forceFallback = false, $mountPointId return $rootPageFromRootLine === 0 ? $rootPageId : $rootPageFromRootLine; } - /** * This method determines the responsible site roots for a record by getting the rootPage of the record and checking * if the pid is references in another site with additionalPageIds and returning those rootPageIds as well. * * @param string $table - * @param integer $uid + * @param int $uid * @return array + * @throws DBALDriverException + * @throws Throwable */ - protected function buildResponsibleRootPageIds($table, $uid) + protected function buildResponsibleRootPageIds(string $table, int $uid): array { $rootPages = []; $rootPageId = $this->getRootPageIdByTableAndUid($table, $uid); @@ -207,29 +220,26 @@ protected function buildResponsibleRootPageIds($table, $uid) * @param int $uid * @return int */ - protected function getRootPageIdByTableAndUid($table, $uid) + protected function getRootPageIdByTableAndUid(string $table, int $uid): int { if ($table === 'pages') { - $rootPageId = $this->getRootPageId($uid); - return $rootPageId; - } else { - $recordPageId = $this->getRecordPageId($table, $uid); - $rootPageId = $this->getRootPageId($recordPageId, true); - return $rootPageId; + return $this->getRootPageId($uid); } + $recordPageId = $this->getRecordPageId($table, $uid); + return $this->getRootPageId($recordPageId, true); } /** - * Returns the pageId of the record or 0 when no valid record was given. + * Returns the pageId of the record or 0 when no valid record was found. * * @param string $table - * @param integer $uid - * @return mixed + * @param int $uid + * @return int */ - protected function getRecordPageId($table, $uid) + protected function getRecordPageId(string $table, int $uid): int { $record = BackendUtility::getRecord($table, $uid, 'pid'); - return !empty($record['pid']) ? (int)$record['pid'] : 0; + return (int)$record['pid'] ?? 0; } /** @@ -241,8 +251,10 @@ protected function getRecordPageId($table, $uid) * @param int $uid * @param int $recordPageId * @return array + * @throws DBALDriverException + * @throws Throwable */ - public function getAlternativeSiteRootPagesIds($table, $uid, $recordPageId) + public function getAlternativeSiteRootPagesIds(string $table, int $uid, int $recordPageId): array { $siteRootsByObservedPageIds = $this->getSiteRootsByObservedPageIds($table, $uid); if (!isset($siteRootsByObservedPageIds[$recordPageId])) { @@ -253,13 +265,15 @@ public function getAlternativeSiteRootPagesIds($table, $uid, $recordPageId) } /** - * Retrieves an optimized array structure we the monitored pageId as key and the relevant site rootIds as value. + * Retrieves an optimized array structure with the monitored pageId as key and the relevant site rootIds as value. * * @param string $table - * @param integer $uid + * @param int $uid * @return array + * @throws DBALDriverException + * @throws Throwable */ - protected function getSiteRootsByObservedPageIds($table, $uid) + protected function getSiteRootsByObservedPageIds(string $table, int $uid): array { $cacheId = 'RootPageResolver' . '_' . 'getSiteRootsByObservedPageIds' . '_' . $table . '_' . $uid; $methodResult = $this->runtimeCache->get($cacheId); @@ -274,14 +288,16 @@ protected function getSiteRootsByObservedPageIds($table, $uid) } /** - * This methods build an array with observer page id as key and rootPageIds as values to determine which root pages + * This method builds an array with observer page id as key and rootPageIds as values to determine which root pages * are responsible for this record by referencing the pageId in additionalPageIds configuration. * * @param string $table - * @param integer $uid + * @param int $uid * @return array + * @throws DBALDriverException + * @throws Throwable */ - protected function buildSiteRootsByObservedPageIds($table, $uid) + protected function buildSiteRootsByObservedPageIds(string $table, int $uid): array { $siteRootByObservedPageIds = []; $siteRepository = GeneralUtility::makeInstance(SiteRepository::class); diff --git a/Classes/Domain/Index/Queue/Statistic/QueueStatistic.php b/Classes/Domain/Index/Queue/Statistic/QueueStatistic.php index bdf4f05e00..6c10a15b40 100644 --- a/Classes/Domain/Index/Queue/Statistic/QueueStatistic.php +++ b/Classes/Domain/Index/Queue/Statistic/QueueStatistic.php @@ -15,28 +15,30 @@ namespace ApacheSolrForTypo3\Solr\Domain\Index\Queue\Statistic; +/** + * Class QueueStatistic is responsible for index queue metrics calculations. + */ class QueueStatistic { - /** * @var int */ - protected $failedCount = 0; + protected int $failedCount = 0; /** * @var int */ - protected $pendingCount = 0; + protected int $pendingCount = 0; /** * @var int */ - protected $successCount = 0; + protected int $successCount = 0; /** * @param int $failedCount */ - public function setFailedCount($failedCount) + public function setFailedCount(int $failedCount) { $this->failedCount = $failedCount; } @@ -44,15 +46,15 @@ public function setFailedCount($failedCount) /** * @return int */ - public function getFailedCount() + public function getFailedCount(): int { return $this->failedCount; } /** - * @return float|int + * @return float */ - public function getFailedPercentage() + public function getFailedPercentage(): float { return $this->getPercentage($this->getFailedCount()); } @@ -60,7 +62,7 @@ public function getFailedPercentage() /** * @param int $pendingCount */ - public function setPendingCount($pendingCount) + public function setPendingCount(int $pendingCount) { $this->pendingCount = $pendingCount; } @@ -68,15 +70,15 @@ public function setPendingCount($pendingCount) /** * @return int */ - public function getPendingCount() + public function getPendingCount(): int { return $this->pendingCount; } /** - * @return float|int + * @return float */ - public function getPendingPercentage() + public function getPendingPercentage(): float { return $this->getPercentage($this->getPendingCount()); } @@ -84,7 +86,7 @@ public function getPendingPercentage() /** * @param int $successCount */ - public function setSuccessCount($successCount) + public function setSuccessCount(int $successCount) { $this->successCount = $successCount; } @@ -92,15 +94,15 @@ public function setSuccessCount($successCount) /** * @return int */ - public function getSuccessCount() + public function getSuccessCount(): int { return $this->successCount; } /** - * @return float|int + * @return float */ - public function getSuccessPercentage() + public function getSuccessPercentage(): float { return $this->getPercentage($this->getSuccessCount()); } @@ -108,21 +110,21 @@ public function getSuccessPercentage() /** * @return int */ - public function getTotalCount() + public function getTotalCount(): int { return $this->pendingCount + $this->failedCount + $this->successCount; } /** - * @param integer $count + * @param int $count * @return float */ - protected function getPercentage($count) + protected function getPercentage(int $count): float { $total = $this->getTotalCount(); if ($total === 0) { return 0.0; } - return (float)round((100 / $total) * $count, 2); + return round((100 / $total) * $count, 2); } } diff --git a/Classes/Domain/Index/Queue/Statistic/QueueStatisticsRepository.php b/Classes/Domain/Index/Queue/Statistic/QueueStatisticsRepository.php index 15198233ab..1e1f41a11b 100644 --- a/Classes/Domain/Index/Queue/Statistic/QueueStatisticsRepository.php +++ b/Classes/Domain/Index/Queue/Statistic/QueueStatisticsRepository.php @@ -18,8 +18,8 @@ namespace ApacheSolrForTypo3\Solr\Domain\Index\Queue\Statistic; use ApacheSolrForTypo3\Solr\System\Records\AbstractRepository; -use Doctrine\DBAL\Exception as DBALException; use Doctrine\DBAL\Driver\Exception as DBALDriverException; +use Doctrine\DBAL\Exception as DBALException; use PDO; use TYPO3\CMS\Core\Utility\GeneralUtility; use TYPO3\CMS\Extbase\Persistence\Generic\Exception\UnsupportedMethodException; @@ -32,7 +32,7 @@ class QueueStatisticsRepository extends AbstractRepository /** * @var string */ - protected $table = 'tx_solr_indexqueue_item'; + protected string $table = 'tx_solr_indexqueue_item'; /** * Extracts the number of pending, indexed and erroneous items from the @@ -55,11 +55,11 @@ public function findOneByRootPidAndOptionalIndexingConfigurationName( ->add('select', vsprintf('(%s < %s) AS %s', [ $queryBuilder->quoteIdentifier('indexed'), $queryBuilder->quoteIdentifier('changed'), - $queryBuilder->quoteIdentifier('pending') + $queryBuilder->quoteIdentifier('pending'), ]), true) ->add('select', vsprintf('(%s) AS %s', [ $queryBuilder->expr()->notLike('errors', $queryBuilder->createNamedParameter('')), - $queryBuilder->quoteIdentifier('failed') + $queryBuilder->quoteIdentifier('failed'), ]), true) ->add('select', $queryBuilder->expr()->count('*', 'count'), true) ->from($this->table) diff --git a/Classes/Domain/Index/Queue/UpdateHandler/AbstractUpdateHandler.php b/Classes/Domain/Index/Queue/UpdateHandler/AbstractUpdateHandler.php index cf8a8c8ce5..ee178e9beb 100644 --- a/Classes/Domain/Index/Queue/UpdateHandler/AbstractUpdateHandler.php +++ b/Classes/Domain/Index/Queue/UpdateHandler/AbstractUpdateHandler.php @@ -1,6 +1,6 @@ configurationAwareRecordService = $recordService; - $this->frontendEnvironment = $frontendEnvironment; - $this->tcaService = $tcaService; - $this->indexQueue = $indexQueue; + ) { + $this->configurationAwareRecordService = $recordService; + $this->frontendEnvironment = $frontendEnvironment; + $this->tcaService = $tcaService; + $this->indexQueue = $indexQueue; } /** @@ -153,14 +156,14 @@ protected function getAllRelevantFieldsForCurrentState(): array $allCurrentStateFieldnames = array_merge( $allCurrentStateFieldnames, array_keys($triggerConfiguration['currentState']) - ); + ); } return array_unique($allCurrentStateFieldnames); } /** - * When the extend to subpages flag was set, we determine the affected subpages and return them. + * When the extend-to-subpages flag was set, we determine the affected subpages and return them. * * @param int $pageId * @return array @@ -201,13 +204,13 @@ protected function isRecursivePageUpdateRequired(int $pageId, array $updatedFiel 'pages', $pageId, $solrConfiguration - ); + ); if ($indexQueueConfigurationName === null) { return false; } $updateFields = $solrConfiguration->getIndexQueueConfigurationRecursiveUpdateFields( $indexQueueConfigurationName - ); + ); // Check if no additional fields have been defined and then skip recursive update if (empty($updateFields)) { diff --git a/Classes/Domain/Index/Queue/UpdateHandler/DataUpdateHandler.php b/Classes/Domain/Index/Queue/UpdateHandler/DataUpdateHandler.php index 2a76e55475..343f44b111 100644 --- a/Classes/Domain/Index/Queue/UpdateHandler/DataUpdateHandler.php +++ b/Classes/Domain/Index/Queue/UpdateHandler/DataUpdateHandler.php @@ -1,6 +1,6 @@ requeue subpages 'HiddenAndExtendToSubpageWereDisabled' => [ 'changeSet' => [ 'hidden' => '0', - 'extendToSubpages' => '0' - ] + 'extendToSubpages' => '0', + ], ], // the current page has the field "extendToSubpages" enabled and the field "hidden" was set to 0 => requeue subpages 'extendToSubpageEnabledAndHiddenFlagWasRemoved' => [ 'currentState' => ['extendToSubpages' => '1'], - 'changeSet' => ['hidden' => '0'] + 'changeSet' => ['hidden' => '0'], ], // the current page has the field "hidden" enabled and the field "extendToSubpages" was set to 0 => requeue subpages 'hiddenIsEnabledAndExtendToSubPagesWasRemoved' => [ 'currentState' => ['hidden' => '1'], - 'changeSet' => ['extendToSubpages' => '0'] + 'changeSet' => ['extendToSubpages' => '0'], ], // the field "no_search_sub_entries" of current page was set to 0 'no_search_sub_entriesFlagWasAdded' => [ - 'changeSet' => ['no_search_sub_entries' => '0'] + 'changeSet' => ['no_search_sub_entries' => '0'], ], ]; /** * @var MountPagesUpdater */ - protected $mountPageUpdater; + protected MountPagesUpdater $mountPageUpdater; /** * @var RootPageResolver */ - protected $rootPageResolver = null; + protected RootPageResolver $rootPageResolver; /** - * @var PagesRepository + * @var PagesRepository|null */ - protected $pagesRepository; + protected ?PagesRepository $pagesRepository; /** * @var SolrLogManager */ - protected $logger = null; + protected SolrLogManager $logger; /** * @var DataHandler */ - protected $dataHandler; + protected DataHandler $dataHandler; /** * @param ConfigurationAwareRecordService $recordService @@ -123,11 +127,11 @@ class DataUpdateHandler extends AbstractUpdateHandler * @param MountPagesUpdater $mountPageUpdater * @param RootPageResolver $rootPageResolver * @param PagesRepository $pagesRepository - * @param SolrLogManager $solrLogManager * @param DataHandler $dataHandler + * @param SolrLogManager|null $solrLogManager */ public function __construct( - ConfigurationAwareRecordService $recordService , + ConfigurationAwareRecordService $recordService, FrontendEnvironment $frontendEnvironment, TCAService $tcaService, Queue $indexQueue, @@ -145,7 +149,8 @@ public function __construct( $this->dataHandler = $dataHandler; $this->logger = $solrLogManager ?? GeneralUtility::makeInstance( SolrLogManager::class, - /** @scrutinizer ignore-type */ __CLASS__ + /** @scrutinizer ignore-type */ + __CLASS__ ); } @@ -154,6 +159,8 @@ public function __construct( * * @param int $uid * @param array $updatedFields + * @throws DBALDriverException + * @throws Throwable */ public function handleContentElementUpdate(int $uid, array $updatedFields = []): void { @@ -169,6 +176,10 @@ public function handleContentElementUpdate(int $uid, array $updatedFields = []): * Handles the deletion of a content element * * @param int $uid + * @throws AspectNotFoundException + * @throws DBALDriverException + * @throws DBALException|\Doctrine\DBAL\DBALException + * @throws Throwable */ public function handleContentElementDeletion(int $uid): void { @@ -180,7 +191,7 @@ public function handleContentElementDeletion(int $uid): void return; } - $this->indexQueue->updateItem('pages', $pid, Util::getExectionTime()); + $this->indexQueue->updateItem('pages', $pid, Util::getExceptionTime()); } /** @@ -188,18 +199,20 @@ public function handleContentElementDeletion(int $uid): void * * @param int $uid * @param array $updatedFields + * @throws DBALDriverException + * @throws Throwable */ public function handlePageUpdate(int $uid, array $updatedFields = []): void { try { - if (isset($updatedFields['l10n_parent']) && intval($updatedFields['l10n_parent']) > 0) { + if (isset($updatedFields['l10n_parent']) && (int)($updatedFields['l10n_parent']) > 0) { $pid = $updatedFields['l10n_parent']; } elseif ($this->rootPageResolver->getIsRootPageId($uid)) { $pid = $uid; } else { $pid = $updatedFields['pid'] ?? $this->getValidatedPid('pages', $uid); } - } catch (\Throwable $e) { + } catch (Throwable $e) { $pid = null; } @@ -216,6 +229,8 @@ public function handlePageUpdate(int $uid, array $updatedFields = []): void * * @param int $uid * @param string $table + * @throws DBALDriverException + * @throws Throwable */ public function handleRecordUpdate(int $uid, string $table): void { @@ -228,11 +243,14 @@ public function handleRecordUpdate(int $uid, string $table): void * * @param int $uid * @param string $table + * @throws DBALDriverException + * @throws DBALException|\Doctrine\DBAL\DBALException + * @throws Throwable */ public function handleVersionSwap(int $uid, string $table): void { $isPageRelatedRecord = ($table === 'tt_content' || $table === 'pages'); - if($isPageRelatedRecord) { + if ($isPageRelatedRecord) { $uid = ($table === 'tt_content' ? $this->getValidatedPid($table, $uid) : $uid); if ($uid === null) { return; @@ -251,6 +269,9 @@ public function handleVersionSwap(int $uid, string $table): void * Handle page move * * @param int $uid + * @throws DBALDriverException + * @throws DBALException|\Doctrine\DBAL\DBALException + * @throws Throwable */ public function handleMovedPage(int $uid): void { @@ -262,6 +283,9 @@ public function handleMovedPage(int $uid): void * * @param int $uid * @param string $table + * @throws DBALDriverException + * @throws DBALException|\Doctrine\DBAL\DBALException + * @throws Throwable */ public function handleMovedRecord(int $uid, string $table): void { @@ -278,6 +302,9 @@ public function handleMovedRecord(int $uid, string $table): void * from the queue. * * @param int $uid + * @throws DBALDriverException + * @throws DBALException|\Doctrine\DBAL\DBALException + * @throws Throwable */ protected function applyPageChangesToQueue(int $uid): void { @@ -297,6 +324,9 @@ protected function applyPageChangesToQueue(int $uid): void * @param string $table * @param int $uid * @param int $pid + * @throws DBALDriverException + * @throws DBALException|\Doctrine\DBAL\DBALException + * @throws Throwable */ protected function applyRecordChangesToQueue(string $table, int $uid, int $pid): void { @@ -320,7 +350,7 @@ protected function applyRecordChangesToQueue(string $table, int $uid, int $pid): * Removes record from the index queue and from the solr index * * @param string $recordTable Name of table where the record lives - * @param int $recordUid Id of record + * @param int $recordUid id of record */ protected function removeFromIndexAndQueue(string $recordTable, int $recordUid): void { @@ -331,7 +361,9 @@ protected function removeFromIndexAndQueue(string $recordTable, int $recordUid): * Removes record from the index queue and from the solr index when the item is in the queue. * * @param string $recordTable Name of table where the record lives - * @param int $recordUid Id of record + * @param int $recordUid id of record + * @throws DBALDriverException + * @throws DBALException|\Doctrine\DBAL\DBALException */ protected function removeFromIndexAndQueueWhenItemInQueue(string $recordTable, int $recordUid): void { @@ -343,8 +375,9 @@ protected function removeFromIndexAndQueueWhenItemInQueue(string $recordTable, i } /** - * @param $pageId + * @param int $pageId * @return TypoScriptConfiguration + * @throws DBALDriverException */ protected function getSolrConfigurationFromPageId(int $pageId): TypoScriptConfiguration { @@ -357,12 +390,14 @@ protected function getSolrConfigurationFromPageId(int $pageId): TypoScriptConfig * @param string $recordTable The table the record belongs to * @param int $recordUid * @return int[] + * @throws DBALDriverException + * @throws Throwable */ protected function getRecordRootPageIds(string $recordTable, int $recordUid): array { try { $rootPageIds = $this->rootPageResolver->getResponsibleRootPageIds($recordTable, $recordUid); - } catch (\InvalidArgumentException $e) { + } catch (InvalidArgumentException $e) { $rootPageIds = []; } @@ -378,10 +413,12 @@ protected function getRecordRootPageIds(string $recordTable, int $recordUid): ar * @param int $uid * @param int $pid * @param array $updatedFields + * @throws DBALDriverException + * @throws Throwable */ protected function processPageRecord(int $uid, int $pid, array $updatedFields = []): void { - $configurationPageId = $this->getConfigurationPageId('pages', (int)$pid, $uid); + $configurationPageId = $this->getConfigurationPageId('pages', $pid, $uid); if ($configurationPageId === 0) { $this->mountPageUpdater->update($uid); return; @@ -406,6 +443,9 @@ protected function processPageRecord(int $uid, int $pid, array $updatedFields = * @param string $recordTable * @param int $recordUid * @param array $rootPageIds + * @throws DBALDriverException + * @throws DBALException|\Doctrine\DBAL\DBALException + * @throws Throwable */ protected function processRecord(string $recordTable, int $recordUid, array $rootPageIds): void { @@ -467,11 +507,13 @@ protected function processRecord(string $recordTable, int $recordUid, array $roo * @param int $recordPageId * @param int $recordUid * @return int + * @throws DBALDriverException + * @throws Throwable */ protected function getConfigurationPageId(string $recordTable, int $recordPageId, int $recordUid): int { $rootPageId = $this->rootPageResolver->getRootPageId($recordPageId); - $rootPageRecord = $this->getPagesRepository()->getPage((int)$rootPageId); + $rootPageRecord = $this->getPagesRepository()->getPage($rootPageId); if (isset($rootPageRecord['sys_language_uid']) && (int)$rootPageRecord['sys_language_uid'] > 0 && isset($rootPageRecord['l10n_parent']) @@ -508,6 +550,9 @@ protected function getIsTranslationParentRecordEnabled(string $recordTable, int * Applies the updateItem instruction on a collection of pageIds. * * @param array $treePageIds + * @throws DBALDriverException + * @throws DBALException|\Doctrine\DBAL\DBALException + * @throws Throwable */ protected function updatePageIdItems(array $treePageIds): void { @@ -521,10 +566,13 @@ protected function updatePageIdItems(array $treePageIds): void * page currently being updated. * * @param int $pageId UID of the page currently being updated + * @throws DBALDriverException + * @throws DBALException|\Doctrine\DBAL\DBALException + * @throws Throwable */ protected function updateCanonicalPages(int $pageId): void { - $canonicalPages = $this->pagesRepository->findPageUidsWithContentsFromPid((int)$pageId); + $canonicalPages = $this->pagesRepository->findPageUidsWithContentsFromPid($pageId); foreach ($canonicalPages as $page) { $this->indexQueue->updateItem('pages', $page['uid']); } @@ -546,7 +594,7 @@ protected function getValidatedPid(string $table, int $uid): ?int return null; } - return (int)$pid; + return $pid; } /** diff --git a/Classes/Domain/Index/Queue/UpdateHandler/EventListener/AbstractBaseEventListener.php b/Classes/Domain/Index/Queue/UpdateHandler/EventListener/AbstractBaseEventListener.php index 3f7033cf21..a0abef917c 100644 --- a/Classes/Domain/Index/Queue/UpdateHandler/EventListener/AbstractBaseEventListener.php +++ b/Classes/Domain/Index/Queue/UpdateHandler/EventListener/AbstractBaseEventListener.php @@ -1,6 +1,6 @@ getMonitoringType() === static::MONITORING_TYPE); + return $this->getMonitoringType() === static::MONITORING_TYPE; } } diff --git a/Classes/Domain/Index/Queue/UpdateHandler/EventListener/DelayedProcessingEventListener.php b/Classes/Domain/Index/Queue/UpdateHandler/EventListener/DelayedProcessingEventListener.php index 3f3a9a3149..fa6da25f70 100644 --- a/Classes/Domain/Index/Queue/UpdateHandler/EventListener/DelayedProcessingEventListener.php +++ b/Classes/Domain/Index/Queue/UpdateHandler/EventListener/DelayedProcessingEventListener.php @@ -1,6 +1,6 @@ table === 'pages'); + return $this->table === 'pages'; } /** @@ -184,7 +184,7 @@ public function isPageUpdate(): bool */ public function isContentElementUpdate(): bool { - return ($this->table === 'tt_content'); + return $this->table === 'tt_content'; } /** diff --git a/Classes/Domain/Index/Queue/UpdateHandler/Events/ContentElementDeletedEvent.php b/Classes/Domain/Index/Queue/UpdateHandler/Events/ContentElementDeletedEvent.php index 1d9ddbf09d..82999a672d 100644 --- a/Classes/Domain/Index/Queue/UpdateHandler/Events/ContentElementDeletedEvent.php +++ b/Classes/Domain/Index/Queue/UpdateHandler/Events/ContentElementDeletedEvent.php @@ -1,6 +1,6 @@ ['hidden' => '0', 'extendToSubpages' => '0|1'], 'changeSet' => ['hidden' => '1', (optional)'extendToSubpages' => '1'] 'extendToSubpageEnabledAndHiddenFlagWasAdded' => [ 'currentState' => ['extendToSubpages' => '1'], - 'changeSet' => ['hidden' => '1'] + 'changeSet' => ['hidden' => '1'], ], // the current page has the field "hidden" enabled and the field "extendToSubpages" was set to 1 // covers following scenarios: // 'currentState' => ['hidden' => '0|1', 'extendToSubpages' => '0'], 'changeSet' => [(optional)'hidden' => '1', 'extendToSubpages' => '1'] 'hiddenIsEnabledAndExtendToSubPagesWasAdded' => [ 'currentState' => ['hidden' => '1'], - 'changeSet' => ['extendToSubpages' => '1'] + 'changeSet' => ['extendToSubpages' => '1'], ], // the field "no_search_sub_entries" of current page was set to 1 'no_search_sub_entriesFlagWasAdded' => [ - 'changeSet' => ['no_search_sub_entries' => '1'] + 'changeSet' => ['no_search_sub_entries' => '1'], ], ]; @@ -67,10 +70,9 @@ class GarbageHandler extends AbstractUpdateHandler * * @param string $table The record's table name. * @param int $uid The record's uid. - * @throws \UnexpectedValueException if a hook object does not implement interface - * \ApacheSolrForTypo3\Solr\GarbageCollectorPostProcessor + * @throws UnexpectedValueException if a hook object does not implement interface {@linkt \ApacheSolrForTypo3\Solr\GarbageCollectorPostProcessor::} */ - public function collectGarbage($table, $uid): void + public function collectGarbage(string $table, int $uid): void { $garbageRemoverStrategy = StrategyFactory::getByTable($table); $garbageRemoverStrategy->removeGarbageOf($table, $uid); @@ -95,12 +97,13 @@ public function handlePageMovement(int $uid): void } /** - * Performs a record garbage check + * Performs record garbage check * * @param int $uid * @param string $table * @param array $updatedFields * @param bool $frontendGroupsRemoved + * @throws DBALDriverException */ public function performRecordGarbageCheck( int $uid, @@ -132,6 +135,7 @@ public function performRecordGarbageCheck( * @param string $table * @param int $uid * @param array $updatedFields + * @throws DBALDriverException */ protected function deleteSubEntriesWhenRecursiveTriggerIsRecognized( string $table, @@ -192,9 +196,8 @@ protected function isPageExcludedFromSearch(array $record): bool return (bool)$record['no_search']; } - /** - * Check if a record is getting invisible due to changes in start or endtime. In addition it is checked that the related + * Check if a record is getting invisible due to changes in start or endtime. In addition, it is checked that the related * queue item was marked as indexed. * * @param string $table @@ -203,11 +206,11 @@ protected function isPageExcludedFromSearch(array $record): bool */ protected function isInvisibleByStartOrEndtime(string $table, array $record): bool { - return ( + return ($this->tcaService->isStartTimeInFuture($table, $record) || $this->tcaService->isEndTimeInPast($table, $record)) && $this->isRelatedQueueRecordMarkedAsIndexed($table, $record) - ); + ; } /** @@ -248,10 +251,10 @@ public function getRecordWithFieldRelevantForGarbageCollection(string $table, in $row = $queryBuilder ->select(...GeneralUtility::trimExplode(',', $garbageCollectionRelevantFields, true)) ->from($table) - ->where($queryBuilder->expr()->eq('uid', $queryBuilder->createNamedParameter($uid, \PDO::PARAM_INT))) + ->where($queryBuilder->expr()->eq('uid', $queryBuilder->createNamedParameter($uid, PDO::PARAM_INT))) ->executeQuery() ->fetchAssociative(); - } catch (\Throwable $e) { + } catch (Throwable $e) { $row = false; } diff --git a/Classes/Domain/Search/ApacheSolrDocument/Builder.php b/Classes/Domain/Search/ApacheSolrDocument/Builder.php index d353c523c7..abdcf9e896 100644 --- a/Classes/Domain/Search/ApacheSolrDocument/Builder.php +++ b/Classes/Domain/Search/ApacheSolrDocument/Builder.php @@ -1,5 +1,7 @@ getSiteByPageId($page->id); + $site = $this->getSiteByPageId((int)$page->id); $pageRecord = $page->page; $accessGroups = $this->getDocumentIdGroups($pageAccessRootline); @@ -74,18 +84,18 @@ public function fromPage(TypoScriptFrontendController $page, $url, Rootline $pag $document->setField('type', 'pages'); // system fields - $document->setField('uid', $page->id); + $document->setField('uid', (int)$page->id); $document->setField('pid', $pageRecord['pid']); // variantId - $variantId = $this->variantIdBuilder->buildFromTypeAndUid('pages', $page->id); + $variantId = $this->variantIdBuilder->buildFromTypeAndUid('pages', (int)$page->id); $document->setField('variantId', $variantId); $document->setField('typeNum', $page->type); $document->setField('created', $pageRecord['crdate']); $document->setField('changed', $pageRecord['SYS_LASTCHANGED']); - $rootline = $this->getRootLineFieldValue($page->id, $mountPointParameter); + $rootline = $this->getRootLineFieldValue((int)$page->id, $mountPointParameter); $document->setField('rootline', $rootline); // access @@ -110,7 +120,6 @@ public function fromPage(TypoScriptFrontendController $page, $url, Rootline $pag return $document; } - /** * Creates a Solr document with the basic / core fields set already. * @@ -119,6 +128,7 @@ public function fromPage(TypoScriptFrontendController $page, $url, Rootline $pag * @param int $rootPageUid * @param string $accessRootLine * @return Document + * @throws DBALDriverException */ public function fromRecord(array $itemRecord, string $type, int $rootPageUid, string $accessRootLine): Document { @@ -166,10 +176,12 @@ public function fromRecord(array $itemRecord, string $type, int $rootPageUid, st } /** - * @param TypoScriptFrontendController $page + * @param TypoScriptFrontendController $frontendController * @param string $accessGroups * @param string $mountPointParameter * @return string + * @throws AspectNotFoundException + * @throws DBALDriverException */ protected function getPageDocumentId(TypoScriptFrontendController $frontendController, string $accessGroups, string $mountPointParameter): string { @@ -181,6 +193,7 @@ protected function getPageDocumentId(TypoScriptFrontendController $frontendContr * @param int $rootPageId * @param int $recordUid * @return string + * @throws DBALDriverException */ protected function getDocumentId(string $type, int $rootPageId, int $recordUid): string { @@ -188,10 +201,11 @@ protected function getDocumentId(string $type, int $rootPageId, int $recordUid): } /** - * @param integer $pageId + * @param int $pageId * @return Site + * @throws DBALDriverException */ - protected function getSiteByPageId($pageId) + protected function getSiteByPageId(int $pageId): Site { $siteRepository = GeneralUtility::makeInstance(SiteRepository::class); return $siteRepository->getSiteByPageId($pageId); @@ -201,7 +215,7 @@ protected function getSiteByPageId($pageId) * @param string $pageContent * @return Typo3PageContentExtractor */ - protected function getExtractorForPageContent($pageContent) + protected function getExtractorForPageContent(string $pageContent): Typo3PageContentExtractor { return GeneralUtility::makeInstance(Typo3PageContentExtractor::class, /** @scrutinizer ignore-type */ $pageContent); } @@ -213,7 +227,7 @@ protected function getExtractorForPageContent($pageContent) * @param string $mountPointParameter * @return string */ - protected function getRootLineFieldValue($pageId, $mountPointParameter) + protected function getRootLineFieldValue(int $pageId, string $mountPointParameter = '') { $rootline = $pageId; if ($mountPointParameter !== '') { @@ -229,7 +243,7 @@ protected function getRootLineFieldValue($pageId, $mountPointParameter) * @param Rootline $pageAccessRootline * @return string A comma separated list of frontend user groups. */ - protected function getDocumentIdGroups(Rootline $pageAccessRootline) + protected function getDocumentIdGroups(Rootline $pageAccessRootline): string { $groups = $pageAccessRootline->getGroups(); $groups = Rootline::cleanGroupArray($groups); @@ -238,9 +252,7 @@ protected function getDocumentIdGroups(Rootline $pageAccessRootline) $groups[] = 0; } - $groups = implode(',', $groups); - - return $groups; + return implode(',', $groups); } /** @@ -263,9 +275,9 @@ protected function addAccessField(Document $document, Rootline $pageAccessRootli * @param Document $document * @param array $pageRecord */ - protected function addEndtimeField(Document $document, $pageRecord) + protected function addEndtimeField(Document $document, array $pageRecord) { - if ($pageRecord['endtime']) { + if (isset($pageRecord['endtime']) && $pageRecord['endtime'] > 0) { $document->setField('endtime', $pageRecord['endtime']); } } @@ -276,7 +288,7 @@ protected function addEndtimeField(Document $document, $pageRecord) * @param Document $document * @param array $pageRecord */ - protected function addKeywordsField(Document $document, $pageRecord) + protected function addKeywordsField(Document $document, array $pageRecord) { if (!isset($pageRecord['keywords'])) { return; @@ -294,7 +306,7 @@ protected function addKeywordsField(Document $document, $pageRecord) * @param Document $document * @param array $tagContent */ - protected function addTagContentFields(Document $document, $tagContent = []) + protected function addTagContentFields(Document $document, array $tagContent = []) { foreach ($tagContent as $fieldName => $fieldValue) { $document->setField($fieldName, $fieldValue); diff --git a/Classes/Domain/Search/ApacheSolrDocument/Repository.php b/Classes/Domain/Search/ApacheSolrDocument/Repository.php index 0d168eb122..7fef6ae34f 100644 --- a/Classes/Domain/Search/ApacheSolrDocument/Repository.php +++ b/Classes/Domain/Search/ApacheSolrDocument/Repository.php @@ -25,11 +25,14 @@ use ApacheSolrForTypo3\Solr\System\Solr\SolrCommunicationException; use ApacheSolrForTypo3\Solr\System\Solr\SolrConnection; use ApacheSolrForTypo3\Solr\Util; +use Exception; use TYPO3\CMS\Core\SingletonInterface; use TYPO3\CMS\Core\Utility\GeneralUtility; /** * Class Repository + * + * Purpose: TYPO3 BE INFO module :: Index Documents tab */ class Repository implements SingletonInterface { @@ -37,32 +40,35 @@ class Repository implements SingletonInterface /** * Search * - * @var \ApacheSolrForTypo3\Solr\Search + * @var Search|null */ - protected $search; + protected ?Search $search = null; /** * @var DocumentEscapeService */ - protected $documentEscapeService = null; + protected DocumentEscapeService $documentEscapeService; /** - * @var TypoScriptConfiguration|null + * @var TypoScriptConfiguration */ - protected $typoScriptConfiguration = null; + protected TypoScriptConfiguration $typoScriptConfiguration; /** * @var QueryBuilder */ - protected $queryBuilder; + protected QueryBuilder $queryBuilder; /** * Repository constructor. * @param DocumentEscapeService|null $documentEscapeService * @param QueryBuilder|null $queryBuilder */ - public function __construct(DocumentEscapeService $documentEscapeService = null, TypoScriptConfiguration $typoScriptConfiguration = null, QueryBuilder $queryBuilder = null) - { + public function __construct( + DocumentEscapeService $documentEscapeService = null, + TypoScriptConfiguration $typoScriptConfiguration = null, + QueryBuilder $queryBuilder = null + ) { $this->typoScriptConfiguration = $typoScriptConfiguration ?? Util::getSolrConfiguration(); $this->documentEscapeService = $documentEscapeService ?? GeneralUtility::makeInstance(DocumentEscapeService::class, /** @scrutinizer ignore-type */ $typoScriptConfiguration); $this->queryBuilder = $queryBuilder ?? GeneralUtility::makeInstance(QueryBuilder::class, /** @scrutinizer ignore-type */ $this->typoScriptConfiguration); @@ -71,8 +77,10 @@ public function __construct(DocumentEscapeService $documentEscapeService = null, /** * Returns firs found \ApacheSolrForTypo3\Solr\System\Solr\Document\Document for current page by given language id. * + * @param $pageId * @param $languageId * @return Document|false + * @throws Exception */ public function findOneByPageIdAndByLanguageId($pageId, $languageId) { @@ -87,16 +95,15 @@ public function findOneByPageIdAndByLanguageId($pageId, $languageId) * @param int $pageId * @param int $languageId * @return Document[] + * @throws Exception */ - public function findByPageIdAndByLanguageId($pageId, $languageId) + public function findByPageIdAndByLanguageId(int $pageId, int $languageId): array { try { $this->initializeSearch($pageId, $languageId); $pageQuery = $this->queryBuilder->buildPageQuery($pageId); $response = $this->search->search($pageQuery, 0, 10000); - } catch (NoSolrConnectionFoundException $exception) { - return []; - } catch (SolrCommunicationException $exception) { + } catch (NoSolrConnectionFoundException|SolrCommunicationException $exception) { return []; } $data = $response->getParsedData(); @@ -110,16 +117,19 @@ public function findByPageIdAndByLanguageId($pageId, $languageId) * @param int $pageId * @param int $languageId * @return Document[]|array + * @throws Exception */ - public function findByTypeAndPidAndUidAndLanguageId($type, $uid, $pageId, $languageId): array - { + public function findByTypeAndPidAndUidAndLanguageId( + string $type, + int $uid, + int $pageId, + int $languageId + ): array { try { $this->initializeSearch($pageId, $languageId); $recordQuery = $this->queryBuilder->buildRecordQuery($type, $uid, $pageId); $response = $this->search->search($recordQuery, 0, 10000); - } catch (NoSolrConnectionFoundException $exception) { - return []; - } catch (SolrCommunicationException $exception) { + } catch (NoSolrConnectionFoundException|SolrCommunicationException $exception) { return []; } $data = $response->getParsedData(); @@ -130,17 +140,13 @@ public function findByTypeAndPidAndUidAndLanguageId($type, $uid, $pageId, $langu /** * Initializes Search for given language * + * @param int $pageId * @param int $languageId + * @throws NoSolrConnectionFoundException */ - protected function initializeSearch($pageId, $languageId = 0) + protected function initializeSearch(int $pageId, int $languageId = 0) { - if (!is_int($pageId)) { - throw new \InvalidArgumentException('Invalid page ID = ' . $pageId, 1487332926); - } - if (!is_int($languageId)) { // @todo: Check if lang id is defined and present? - throw new \InvalidArgumentException('Invalid language ID = ' . $languageId, 1487335178); - } - /* @var $connectionManager ConnectionManager */ + /* @var ConnectionManager $connectionManager */ $connectionManager = GeneralUtility::makeInstance(ConnectionManager::class); $solrConnection = $connectionManager->getConnectionByPageId($pageId, $languageId); @@ -153,7 +159,7 @@ protected function initializeSearch($pageId, $languageId = 0) * @param SolrConnection $solrConnection * @return Search */ - protected function getSearch($solrConnection) + protected function getSearch(SolrConnection $solrConnection): Search { return GeneralUtility::makeInstance(Search::class, /** @scrutinizer ignore-type */ $solrConnection); } diff --git a/Classes/Domain/Search/FrequentSearches/FrequentSearchesService.php b/Classes/Domain/Search/FrequentSearches/FrequentSearchesService.php index 5c774faec0..5aebf16eb5 100644 --- a/Classes/Domain/Search/FrequentSearches/FrequentSearchesService.php +++ b/Classes/Domain/Search/FrequentSearches/FrequentSearchesService.php @@ -1,6 +1,6 @@ configuration->getSearchFrequentSearchesConfiguration(); @@ -99,7 +100,7 @@ public function getFrequentSearchTerms() : array $lifetime = null; if (isset($frequentSearchConfiguration['cacheLifetime'])) { - $lifetime = intval($frequentSearchConfiguration['cacheLifetime']); + $lifetime = (int)($frequentSearchConfiguration['cacheLifetime']); } if ($this->hasValidCache()) { @@ -115,8 +116,9 @@ public function getFrequentSearchTerms() : array * * @param array $frequentSearchConfiguration * @return array Array of frequent search terms, keys are the terms, values are hits + * @throws AspectNotFoundException */ - protected function getFrequentSearchTermsFromStatistics(array $frequentSearchConfiguration) : array + protected function getFrequentSearchTermsFromStatistics(array $frequentSearchConfiguration = []): array { $terms = []; @@ -138,10 +140,6 @@ protected function getFrequentSearchTermsFromStatistics(array $frequentSearchCon $frequentSearchTerms = $this->statisticsRepository ->getFrequentSearchTermsFromStatisticsByFrequentSearchConfiguration($frequentSearchConfiguration); - if (!is_array($frequentSearchTerms)) { - return $terms; - } - foreach ($frequentSearchTerms as $term) { $cleanedTerm = html_entity_decode($term['search_term'], ENT_QUOTES, 'UTF-8'); $terms[$cleanedTerm] = $term['hits']; @@ -153,8 +151,9 @@ protected function getFrequentSearchTermsFromStatistics(array $frequentSearchCon /** * @param array $frequentSearchConfiguration * @return string + * @throws AspectNotFoundException */ - protected function getCacheIdentifier(array $frequentSearchConfiguration) : string + protected function getCacheIdentifier(array $frequentSearchConfiguration): string { // Use configuration as cache identifier $identifier = 'frequentSearchesTags'; @@ -177,6 +176,6 @@ protected function getCacheIdentifier(array $frequentSearchConfiguration) : stri */ protected function hasValidCache(): bool { - return ($this->cache instanceof FrontendInterface); + return $this->cache instanceof FrontendInterface; } } diff --git a/Classes/Domain/Search/Highlight/SiteHighlighterUrlModifier.php b/Classes/Domain/Search/Highlight/SiteHighlighterUrlModifier.php index 2a0f057697..eece27d514 100644 --- a/Classes/Domain/Search/Highlight/SiteHighlighterUrlModifier.php +++ b/Classes/Domain/Search/Highlight/SiteHighlighterUrlModifier.php @@ -11,10 +11,15 @@ * LICENSE.txt file that was distributed with this source code. * * The TYPO3 project - inspiring people to share! + */ +namespace ApacheSolrForTypo3\Solr\Domain\Search\Highlight; + +use ApacheSolrForTypo3\Solr\System\Url\UrlHelper; +use TYPO3\CMS\Core\Utility\GeneralUtility; /** - * Provides highlighting of the search words on the document's actual page by + * Class SiteHighlighterUrlModifier provides highlighting of the search words on the document's actual page by * adding parameters to a document's URL property. * * Initial code from ApacheSolrForTypo3\Solr\ResultDocumentModifier\SiteHighlighter @@ -22,40 +27,36 @@ * @author Stefan Sprenger * @author Timo Hund */ - -namespace ApacheSolrForTypo3\Solr\Domain\Search\Highlight; - -use ApacheSolrForTypo3\Solr\System\Url\UrlHelper; -use TYPO3\CMS\Core\Utility\GeneralUtility; - -/** - * Class SiteHighlighterUrlModifier - */ -class SiteHighlighterUrlModifier { - +class SiteHighlighterUrlModifier +{ /** * @param string $url * @param string $searchWords - * @param boolean $addNoCache - * @param boolean $keepCHash + * @param bool $addNoCache + * @param bool $keepCHash * @return string */ - public function modify($url, $searchWords, $addNoCache = true, $keepCHash = false) { + public function modify( + string $url, + string $searchWords, + bool $addNoCache = true, + bool $keepCHash = false + ): string { $searchWords = str_replace('"', '', $searchWords); $searchWords = GeneralUtility::trimExplode(' ', $searchWords, true); - /** @var UrlHelper $urlHelper */ - $urlHelper = GeneralUtility::makeInstance(UrlHelper::class, /** @scrutinizer ignore-type */ $url); - $urlHelper->addQueryParameter('sword_list', $searchWords); + /** @var UrlHelper $urlHelper */ + $urlHelper = GeneralUtility::makeInstance(UrlHelper::class, /** @scrutinizer ignore-type */ $url) + ->withQueryParameter('sword_list', $searchWords); if ($addNoCache) { - $urlHelper->addQueryParameter('no_cache', '1'); + $urlHelper = $urlHelper->withQueryParameter('no_cache', '1'); } if (!$keepCHash) { - $urlHelper->removeQueryParameter('cHash'); + $urlHelper = $urlHelper->withoutQueryParameter('cHash'); } - return $urlHelper->getUrl(); + return $urlHelper->__toString(); } } diff --git a/Classes/Domain/Search/LastSearches/LastSearchesRepository.php b/Classes/Domain/Search/LastSearches/LastSearchesRepository.php index 106c99e57d..d6c07e8d33 100644 --- a/Classes/Domain/Search/LastSearches/LastSearchesRepository.php +++ b/Classes/Domain/Search/LastSearches/LastSearchesRepository.php @@ -16,21 +16,27 @@ namespace ApacheSolrForTypo3\Solr\Domain\Search\LastSearches; use ApacheSolrForTypo3\Solr\System\Records\AbstractRepository; +use Doctrine\DBAL\Driver\Exception as DBALDriverException; +use Doctrine\DBAL\Exception as DBALException; +use InvalidArgumentException; +use function json_encode; class LastSearchesRepository extends AbstractRepository { /** * @var string */ - protected $table = 'tx_solr_last_searches'; + protected string $table = 'tx_solr_last_searches'; /** * Finds the last searched keywords from the database * * @param int $limit * @return array An array containing the last searches of the current user + * @throws DBALDriverException + * @throws DBALException|\Doctrine\DBAL\DBALException */ - public function findAllKeywords($limit = 10) : array + public function findAllKeywords(int $limit = 10): array { $lastSearchesResultSet = $this->getLastSearchesResultSet($limit); if (empty($lastSearchesResultSet)) { @@ -48,22 +54,26 @@ public function findAllKeywords($limit = 10) : array /** * Returns all last searches * - * @param $limit + * @param int $limit * @return array + * @throws DBALException|\Doctrine\DBAL\DBALException + * @throws DBALDriverException */ - protected function getLastSearchesResultSet($limit) : array + protected function getLastSearchesResultSet(int $limit): array { $queryBuilder = $this->getQueryBuilder(); return $queryBuilder ->select('keywords') ->addSelectLiteral( - $queryBuilder->expr()->max('tstamp','maxtstamp') + $queryBuilder->expr()->max('tstamp', 'maxtstamp') ) ->from($this->table) // There is no support for DISTINCT, a ->groupBy() has to be used instead. ->groupBy('keywords') ->orderBy('maxtstamp', 'DESC') - ->setMaxResults($limit)->execute()->fetchAll(); + ->setMaxResults($limit) + ->execute() + ->fetchAllAssociative(); } /** @@ -71,7 +81,8 @@ protected function getLastSearchesResultSet($limit) : array * * @param string $lastSearchesKeywords * @param int $lastSearchesLimit - * @return void + * @throws DBALDriverException + * @throws DBALException|\Doctrine\DBAL\DBALException */ public function add(string $lastSearchesKeywords, int $lastSearchesLimit) { @@ -80,7 +91,7 @@ public function add(string $lastSearchesKeywords, int $lastSearchesLimit) if ($nextSequenceId < $rowsCount) { $this->update([ 'sequence_id' => $nextSequenceId, - 'keywords' => $lastSearchesKeywords + 'keywords' => $lastSearchesKeywords, ]); return; } @@ -91,7 +102,7 @@ public function add(string $lastSearchesKeywords, int $lastSearchesLimit) ->values([ 'sequence_id' => $nextSequenceId, 'keywords' => $lastSearchesKeywords, - 'tstamp' => time() + 'tstamp' => time(), ]) ->execute(); } @@ -101,8 +112,10 @@ public function add(string $lastSearchesKeywords, int $lastSearchesLimit) * * @param int $lastSearchesLimit * @return int + * @throws DBALDriverException + * @throws DBALException|\Doctrine\DBAL\DBALException */ - protected function resolveNextSequenceIdForGivenLimit(int $lastSearchesLimit) : int + protected function resolveNextSequenceIdForGivenLimit(int $lastSearchesLimit): int { $nextSequenceId = 0; @@ -111,7 +124,8 @@ protected function resolveNextSequenceIdForGivenLimit(int $lastSearchesLimit) : ->from($this->table) ->orderBy('tstamp', 'DESC') ->setMaxResults(1) - ->execute()->fetch(); + ->execute() + ->fetchAssociative(); if (!empty($result)) { $nextSequenceId = ($result['sequence_id'] + 1) % $lastSearchesLimit; @@ -124,8 +138,8 @@ protected function resolveNextSequenceIdForGivenLimit(int $lastSearchesLimit) : * Updates last searches row by using sequence_id from given $lastSearchesRow array * * @param array $lastSearchesRow - * @return void - * @throws \InvalidArgumentException + * @throws InvalidArgumentException + * @throws DBALException|\Doctrine\DBAL\DBALException */ protected function update(array $lastSearchesRow) { @@ -141,7 +155,7 @@ protected function update(array $lastSearchesRow) ->execute(); if ($affectedRows < 1) { - throw new \InvalidArgumentException(vsprintf('By trying to update last searches row with values "%s" nothing was updated, make sure the given "sequence_id" exists in database.', [\json_encode($lastSearchesRow)]), 1502717923); + throw new InvalidArgumentException(vsprintf('By trying to update last searches row with values "%s" nothing was updated, make sure the given "sequence_id" exists in database.', [json_encode($lastSearchesRow)]), 1502717923); } } } diff --git a/Classes/Domain/Search/LastSearches/LastSearchesService.php b/Classes/Domain/Search/LastSearches/LastSearchesService.php index 2dabb1ab63..00265e8af8 100644 --- a/Classes/Domain/Search/LastSearches/LastSearchesService.php +++ b/Classes/Domain/Search/LastSearches/LastSearchesService.php @@ -17,6 +17,8 @@ use ApacheSolrForTypo3\Solr\System\Configuration\TypoScriptConfiguration; use ApacheSolrForTypo3\Solr\System\Session\FrontendUserSession; +use Doctrine\DBAL\Driver\Exception as DBALDriverException; +use Doctrine\DBAL\Exception as DBALException; use TYPO3\CMS\Core\Utility\GeneralUtility; use UnexpectedValueException; @@ -28,29 +30,31 @@ */ class LastSearchesService { - /** * @var TypoScriptConfiguration */ - protected $configuration; + protected TypoScriptConfiguration $configuration; /** * @var FrontendUserSession */ - protected $session; + protected FrontendUserSession $session; /** * @var LastSearchesRepository */ - protected $lastSearchesRepository; + protected LastSearchesRepository $lastSearchesRepository; /** * @param TypoScriptConfiguration $typoscriptConfiguration * @param FrontendUserSession|null $session * @param LastSearchesRepository|null $lastSearchesRepository */ - public function __construct(TypoScriptConfiguration $typoscriptConfiguration, FrontendUserSession $session = null, LastSearchesRepository $lastSearchesRepository = null) - { + public function __construct( + TypoScriptConfiguration $typoscriptConfiguration, + FrontendUserSession $session = null, + LastSearchesRepository $lastSearchesRepository = null + ) { $this->configuration = $typoscriptConfiguration; $this->session = $session ?? GeneralUtility::makeInstance(FrontendUserSession::class); $this->lastSearchesRepository = $lastSearchesRepository ?? GeneralUtility::makeInstance(LastSearchesRepository::class); @@ -60,8 +64,10 @@ public function __construct(TypoScriptConfiguration $typoscriptConfiguration, Fr * Retrieves the last searches from the session or database depending on the configuration. * * @return array + * @throws DBALDriverException + * @throws DBALException|\Doctrine\DBAL\DBALException */ - public function getLastSearches() + public function getLastSearches(): array { $lastSearchesKeywords = []; $mode = $this->configuration->getSearchLastSearchesMode(); @@ -83,9 +89,10 @@ public function getLastSearches() * Saves the keywords to the last searches in the database or session depending on the configuration. * * @param string $keywords - * @throws UnexpectedValueException + * @throws DBALDriverException + * @throws DBALException|\Doctrine\DBAL\DBALException */ - public function addToLastSearches($keywords) + public function addToLastSearches(string $keywords) { $mode = $this->configuration->getSearchLastSearchesMode(); switch ($mode) { @@ -93,7 +100,7 @@ public function addToLastSearches($keywords) $this->storeKeywordsToSession($keywords); break; case 'global': - $this->lastSearchesRepository->add($keywords, (int)$this->configuration->getSearchLastSearchesLimit()); + $this->lastSearchesRepository->add($keywords, $this->configuration->getSearchLastSearchesLimit()); break; default: throw new UnexpectedValueException( @@ -109,21 +116,18 @@ public function addToLastSearches($keywords) * @param int $limit * @return array An array containing the last searches of the current user */ - protected function getLastSearchesFromSession($limit) + protected function getLastSearchesFromSession(int $limit): array { $lastSearches = $this->session->getLastSearches(); - $lastSearches = array_slice(array_reverse(array_unique($lastSearches)), 0, $limit); - - return $lastSearches; + return array_slice(array_reverse(array_unique($lastSearches)), 0, $limit); } /** * Stores the keywords from the current query to the user's session. * * @param string $keywords The current query's keywords - * @return void */ - protected function storeKeywordsToSession($keywords) + protected function storeKeywordsToSession(string $keywords) { $currentLastSearches = $this->session->getLastSearches(); $lastSearches = $currentLastSearches; diff --git a/Classes/Domain/Search/LastSearches/LastSearchesWriterProcessor.php b/Classes/Domain/Search/LastSearches/LastSearchesWriterProcessor.php index d799ee1e4b..8bb96d856d 100644 --- a/Classes/Domain/Search/LastSearches/LastSearchesWriterProcessor.php +++ b/Classes/Domain/Search/LastSearches/LastSearchesWriterProcessor.php @@ -15,9 +15,10 @@ namespace ApacheSolrForTypo3\Solr\Domain\Search\LastSearches; -use ApacheSolrForTypo3\Solr\Domain\Search\LastSearches\LastSearchesService; use ApacheSolrForTypo3\Solr\Domain\Search\ResultSet\SearchResultSet; use ApacheSolrForTypo3\Solr\Domain\Search\ResultSet\SearchResultSetProcessor; +use Doctrine\DBAL\Driver\Exception as DBALDriverException; +use Doctrine\DBAL\Exception as DBALException; use TYPO3\CMS\Core\Utility\GeneralUtility; /** @@ -30,10 +31,13 @@ class LastSearchesWriterProcessor implements SearchResultSetProcessor /** * @param SearchResultSet $resultSet + * + * @throws DBALDriverException + * @throws DBALException|\Doctrine\DBAL\DBALException * @return SearchResultSet */ - public function process(SearchResultSet $resultSet) { - + public function process(SearchResultSet $resultSet): SearchResultSet + { if ($resultSet->getAllResultCount() === 0) { // when the search does not produce a result we do not store the last searches return $resultSet; @@ -57,8 +61,12 @@ public function process(SearchResultSet $resultSet) { * @param SearchResultSet $resultSet * @return LastSearchesService */ - protected function getLastSearchesService(SearchResultSet $resultSet) { - return GeneralUtility::makeInstance(LastSearchesService::class, - /** @scrutinizer ignore-type */ $resultSet->getUsedSearchRequest()->getContextTypoScriptConfiguration()); + protected function getLastSearchesService(SearchResultSet $resultSet): LastSearchesService + { + return GeneralUtility::makeInstance( + LastSearchesService::class, + /** @scrutinizer ignore-type */ + $resultSet->getUsedSearchRequest()->getContextTypoScriptConfiguration() + ); } } diff --git a/Classes/Domain/Search/Query/AbstractQueryBuilder.php b/Classes/Domain/Search/Query/AbstractQueryBuilder.php index 5e89898d08..15d3c31460 100644 --- a/Classes/Domain/Search/Query/AbstractQueryBuilder.php +++ b/Classes/Domain/Search/Query/AbstractQueryBuilder.php @@ -1,5 +1,7 @@ queryToBuild = $query; return $this; } /** - * @return Query + * @return SolariumQuery|Query */ - public function getQuery(): Query + public function getQuery(): SolariumQuery { return $this->queryToBuild; } @@ -65,7 +67,7 @@ public function getQuery(): Query * @param bool $omitHeader * @return $this */ - public function useOmitHeader($omitHeader = true) + public function useOmitHeader(bool $omitHeader = true): AbstractQueryBuilder { $this->queryToBuild->setOmitHeader($omitHeader); @@ -78,10 +80,10 @@ public function useOmitHeader($omitHeader = true) * @param array $filterArray * @return $this */ - public function useFilterArray(array $filterArray) + public function useFilterArray(array $filterArray): AbstractQueryBuilder { foreach ($filterArray as $key => $additionalFilter) { - $this->useFilter($additionalFilter, $key); + $this->useFilter($additionalFilter, (string)$key); } return $this; @@ -93,7 +95,7 @@ public function useFilterArray(array $filterArray) * @param string $queryString * @return $this */ - public function useQueryString($queryString) + public function useQueryString(string $queryString): AbstractQueryBuilder { $this->queryToBuild->setQuery($queryString); return $this; @@ -105,7 +107,7 @@ public function useQueryString($queryString) * @param string $queryType * @return $this */ - public function useQueryType(string $queryType) + public function useQueryType(string $queryType): AbstractQueryBuilder { $this->queryToBuild->addParam('qt', $queryType); return $this; @@ -116,7 +118,7 @@ public function useQueryType(string $queryType) * * @return $this */ - public function removeQueryType() + public function removeQueryType(): AbstractQueryBuilder { $this->queryToBuild->addParam('qt', null); return $this; @@ -127,7 +129,7 @@ public function removeQueryType() * * @return $this */ - public function removeAllSortings() + public function removeAllSortings(): AbstractQueryBuilder { $this->queryToBuild->clearSorts(); return $this; @@ -139,7 +141,7 @@ public function removeAllSortings() * @param Sorting $sorting * @return $this */ - public function useSorting(Sorting $sorting) + public function useSorting(Sorting $sorting): AbstractQueryBuilder { if (strpos($sorting->getFieldName(), 'relevance') !== false) { $this->removeAllSortings(); @@ -156,9 +158,9 @@ public function useSorting(Sorting $sorting) * @param Sortings $sortings * @return $this */ - public function useSortings(Sortings $sortings) + public function useSortings(Sortings $sortings): AbstractQueryBuilder { - foreach($sortings->getSortings() as $sorting) { + foreach ($sortings->getSortings() as $sorting) { $this->useSorting($sorting); } @@ -169,7 +171,7 @@ public function useSortings(Sortings $sortings) * @param int $resultsPerPage * @return $this */ - public function useResultsPerPage($resultsPerPage) + public function useResultsPerPage(int $resultsPerPage): AbstractQueryBuilder { $this->queryToBuild->setRows($resultsPerPage); return $this; @@ -179,7 +181,7 @@ public function useResultsPerPage($resultsPerPage) * @param int $page * @return $this */ - public function usePage($page) + public function usePage(int $page): AbstractQueryBuilder { $this->queryToBuild->setStart($page); return $this; @@ -189,9 +191,9 @@ public function usePage($page) * @param Operator $operator * @return $this */ - public function useOperator(Operator $operator) + public function useOperator(Operator $operator): AbstractQueryBuilder { - $this->queryToBuild->setQueryDefaultOperator( $operator->getOperator()); + $this->queryToBuild->setQueryDefaultOperator($operator->getOperator()); return $this; } @@ -200,7 +202,7 @@ public function useOperator(Operator $operator) * * @return $this */ - public function removeOperator() + public function removeOperator(): AbstractQueryBuilder { $this->queryToBuild->setQueryDefaultOperator(''); return $this; @@ -210,7 +212,7 @@ public function removeOperator() * @param Slops $slops * @return $this */ - public function useSlops(Slops $slops) + public function useSlops(Slops $slops): AbstractQueryBuilder { return $slops->build($this); } @@ -221,11 +223,11 @@ public function useSlops(Slops $slops) * @param string|array $boostQueries * @return $this */ - public function useBoostQueries($boostQueries) + public function useBoostQueries($boostQueries): AbstractQueryBuilder { $boostQueryArray = []; - if(is_array($boostQueries)) { - foreach($boostQueries as $boostQuery) { + if (is_array($boostQueries)) { + foreach ($boostQueries as $boostQuery) { $boostQueryArray[] = ['key' => md5($boostQuery), 'query' => $boostQuery]; } } else { @@ -241,7 +243,7 @@ public function useBoostQueries($boostQueries) * * @return $this */ - public function removeAllBoostQueries() + public function removeAllBoostQueries(): AbstractQueryBuilder { $this->queryToBuild->getEDisMax()->clearBoostQueries(); return $this; @@ -253,7 +255,7 @@ public function removeAllBoostQueries() * @param string $boostFunction * @return $this */ - public function useBoostFunction(string $boostFunction) + public function useBoostFunction(string $boostFunction): AbstractQueryBuilder { $this->queryToBuild->getEDisMax()->setBoostFunctions($boostFunction); return $this; @@ -264,20 +266,19 @@ public function useBoostFunction(string $boostFunction) * * @return $this */ - public function removeAllBoostFunctions() + public function removeAllBoostFunctions(): AbstractQueryBuilder { $this->queryToBuild->getEDisMax()->setBoostFunctions(''); return $this; } - /** * Uses the passed minimumMatch(mm) for the query. * * @param string $minimumMatch * @return $this */ - public function useMinimumMatch(string $minimumMatch) + public function useMinimumMatch(string $minimumMatch): AbstractQueryBuilder { $this->queryToBuild->getEDisMax()->setMinimumMatch($minimumMatch); return $this; @@ -288,20 +289,19 @@ public function useMinimumMatch(string $minimumMatch) * * @return $this */ - public function removeMinimumMatch() + public function removeMinimumMatch(): AbstractQueryBuilder { $this->queryToBuild->getEDisMax()->setMinimumMatch(''); return $this; } - /** * Applies the tie parameter to the query. * - * @param mixed $tie + * @param float $tie * @return $this */ - public function useTieParameter($tie) + public function useTieParameter(float $tie): AbstractQueryBuilder { $this->queryToBuild->getEDisMax()->setTie($tie); return $this; @@ -313,7 +313,7 @@ public function useTieParameter($tie) * @param QueryFields $queryFields * @return $this */ - public function useQueryFields(QueryFields $queryFields) + public function useQueryFields(QueryFields $queryFields): AbstractQueryBuilder { return $queryFields->build($this); } @@ -324,7 +324,7 @@ public function useQueryFields(QueryFields $queryFields) * @param ReturnFields $returnFields * @return $this */ - public function useReturnFields(ReturnFields $returnFields) + public function useReturnFields(ReturnFields $returnFields): AbstractQueryBuilder { return $returnFields->build($this); } @@ -336,12 +336,12 @@ public function useReturnFields(ReturnFields $returnFields) * @param string $filterName * @return $this */ - public function useFilter($filterString, $filterName = '') + public function useFilter(string $filterString, string $filterName = ''): AbstractQueryBuilder { $filterName = $filterName === '' ? $filterString : $filterName; - $nameWasPassedAndFilterIsAllreadySet = $filterName !== '' && $this->queryToBuild->getFilterQuery($filterName) !== null; - if($nameWasPassedAndFilterIsAllreadySet) { + $nameWasPassedAndFilterIsAlreadySet = $filterName !== '' && $this->queryToBuild->getFilterQuery($filterName) !== null; + if ($nameWasPassedAndFilterIsAlreadySet) { return $this; } $this->queryToBuild->addFilterQuery(['key' => $filterName, 'query' => $filterString]); @@ -354,12 +354,12 @@ public function useFilter($filterString, $filterName = '') * @param string $fieldName * @return $this */ - public function removeFilterByFieldName($fieldName) + public function removeFilterByFieldName(string $fieldName): AbstractQueryBuilder { return $this->removeFilterByFunction( - function($key, $query) use ($fieldName) { + function ($key, $query) use ($fieldName) { $queryString = $query->getQuery(); - $storedFieldName = substr($queryString,0, strpos($queryString, ":")); + $storedFieldName = substr($queryString, 0, strpos($queryString, ':')); return $storedFieldName == $fieldName; } ); @@ -371,10 +371,10 @@ function($key, $query) use ($fieldName) { * @param string $name * @return $this */ - public function removeFilterByName($name) + public function removeFilterByName(string $name): AbstractQueryBuilder { return $this->removeFilterByFunction( - function($key, $query) use ($name) { + function ($key, $query) use ($name) { $key = $query->getKey(); return $key == $name; } @@ -387,10 +387,10 @@ function($key, $query) use ($name) { * @param string $value * @return $this */ - public function removeFilterByValue($value) + public function removeFilterByValue(string $value): AbstractQueryBuilder { return $this->removeFilterByFunction( - function($key, $query) use ($value) { + function ($key, $query) use ($value) { $query = $query->getQuery(); return $query == $value; } @@ -398,15 +398,15 @@ function($key, $query) use ($value) { } /** - * @param \Closure $filterFunction + * @param Closure $filterFunction * @return $this */ - public function removeFilterByFunction($filterFunction) + public function removeFilterByFunction(Closure $filterFunction): AbstractQueryBuilder { $queries = $this->queryToBuild->getFilterQueries(); - foreach($queries as $key => $query) { + foreach ($queries as $key => $query) { $canBeRemoved = $filterFunction($key, $query); - if($canBeRemoved) { + if ($canBeRemoved) { unset($queries[$key]); } } @@ -416,22 +416,22 @@ public function removeFilterByFunction($filterFunction) } /** - * Passes the alternative query to the Query + * Passes the alternative query to the SolariumQuery * @param string $query * @return $this */ - public function useAlternativeQuery(string $query) + public function useAlternativeQuery(string $query): AbstractQueryBuilder { $this->queryToBuild->getEDisMax()->setQueryAlternative($query); return $this; } /** - * Remove the alternative query from the Query. + * Remove the alternative query from the SolariumQuery. * * @return $this */ - public function removeAlternativeQuery() + public function removeAlternativeQuery(): AbstractQueryBuilder { $this->queryToBuild->getEDisMax()->setQueryAlternative(null); return $this; @@ -443,7 +443,7 @@ public function removeAlternativeQuery() * @param Faceting $faceting * @return $this */ - public function useFaceting(Faceting $faceting) + public function useFaceting(Faceting $faceting): AbstractQueryBuilder { return $faceting->build($this); } @@ -452,7 +452,7 @@ public function useFaceting(Faceting $faceting) * @param FieldCollapsing $fieldCollapsing * @return $this */ - public function useFieldCollapsing(FieldCollapsing $fieldCollapsing) + public function useFieldCollapsing(FieldCollapsing $fieldCollapsing): AbstractQueryBuilder { return $fieldCollapsing->build($this); } @@ -463,7 +463,7 @@ public function useFieldCollapsing(FieldCollapsing $fieldCollapsing) * @param Grouping $grouping * @return $this */ - public function useGrouping(Grouping $grouping) + public function useGrouping(Grouping $grouping): AbstractQueryBuilder { return $grouping->build($this); } @@ -472,16 +472,16 @@ public function useGrouping(Grouping $grouping) * @param Highlighting $highlighting * @return $this */ - public function useHighlighting(Highlighting $highlighting) + public function useHighlighting(Highlighting $highlighting): AbstractQueryBuilder { return $highlighting->build($this); } /** - * @param boolean $debugMode + * @param bool $debugMode * @return $this */ - public function useDebug($debugMode) + public function useDebug(bool $debugMode): AbstractQueryBuilder { if (!$debugMode) { $this->queryToBuild->addParam('debugQuery', null); @@ -499,7 +499,7 @@ public function useDebug($debugMode) * @param Elevation $elevation * @return QueryBuilder */ - public function useElevation(Elevation $elevation) + public function useElevation(Elevation $elevation): AbstractQueryBuilder { return $elevation->build($this); } @@ -508,7 +508,7 @@ public function useElevation(Elevation $elevation) * @param Spellchecking $spellchecking * @return $this */ - public function useSpellchecking(Spellchecking $spellchecking) + public function useSpellchecking(Spellchecking $spellchecking): AbstractQueryBuilder { return $spellchecking->build($this); } @@ -519,7 +519,7 @@ public function useSpellchecking(Spellchecking $spellchecking) * @param PhraseFields $phraseFields * @return $this */ - public function usePhraseFields(PhraseFields $phraseFields) + public function usePhraseFields(PhraseFields $phraseFields): AbstractQueryBuilder { return $phraseFields->build($this); } @@ -530,7 +530,7 @@ public function usePhraseFields(PhraseFields $phraseFields) * @param BigramPhraseFields $bigramPhraseFields * @return $this */ - public function useBigramPhraseFields(BigramPhraseFields $bigramPhraseFields) + public function useBigramPhraseFields(BigramPhraseFields $bigramPhraseFields): AbstractQueryBuilder { return $bigramPhraseFields->build($this); } @@ -541,7 +541,7 @@ public function useBigramPhraseFields(BigramPhraseFields $bigramPhraseFields) * @param TrigramPhraseFields $trigramPhraseFields * @return $this */ - public function useTrigramPhraseFields(TrigramPhraseFields $trigramPhraseFields) + public function useTrigramPhraseFields(TrigramPhraseFields $trigramPhraseFields): AbstractQueryBuilder { return $trigramPhraseFields->build($this); } diff --git a/Classes/Domain/Search/Query/ExtractingQuery.php b/Classes/Domain/Search/Query/ExtractingQuery.php index 592c75b24b..33755aa953 100644 --- a/Classes/Domain/Search/Query/ExtractingQuery.php +++ b/Classes/Domain/Search/Query/ExtractingQuery.php @@ -19,7 +19,6 @@ /** * Specialized query for content extraction using Solr Cell - * */ class ExtractingQuery extends SolariumExtractQuery { @@ -34,5 +33,4 @@ public function __construct($file) $this->setFile($file); $this->addParam('extractFormat', 'text'); } - } diff --git a/Classes/Domain/Search/Query/Helper/EscapeService.php b/Classes/Domain/Search/Query/Helper/EscapeService.php index 75d9339594..8403323281 100644 --- a/Classes/Domain/Search/Query/Helper/EscapeService.php +++ b/Classes/Domain/Search/Query/Helper/EscapeService.php @@ -1,5 +1,7 @@ */ -class EscapeService { - +class EscapeService +{ /** * Quote and escape search strings * - * @param string|int|double $string String to escape - * @return string|int|double The escaped/quoted string + * @param string|int|float $string String to escape + * @return string|int|float The escaped/quoted string */ public static function escape($string) { @@ -56,24 +58,23 @@ public static function escape($string) /** * Applies trim and htmlspecialchars on the querystring to use it as output. * - * @param mixed $string + * @param string $string * @return string */ - public static function clean($string): string + public static function clean(string $string): string { $string = trim($string); - $string = htmlspecialchars($string); - return $string; + return htmlspecialchars($string); } /** * This method is used to escape the content in the query string surrounded by quotes - * different then when it is not in a quoted context. + * different, then when it is not in a quoted context. * * @param string $string * @return string */ - protected static function tokenizeByQuotesAndEscapeDependingOnContext($string) + protected static function tokenizeByQuotesAndEscapeDependingOnContext(string $string): string { $result = ''; $quotesCount = substr_count($string, '"'); @@ -110,7 +111,7 @@ protected static function tokenizeByQuotesAndEscapeDependingOnContext($string) * @param string $value Unescaped - "dirty" - string * @return string Escaped - "clean" - string */ - protected static function escapePhrase($value) + protected static function escapePhrase(string $value): string { $pattern = '/("|\\\)/'; $replace = '\\\$1'; @@ -124,7 +125,7 @@ protected static function escapePhrase($value) * @param string $value Unescaped - "dirty" - string * @return string Escaped - "clean" - string */ - protected static function escapeSpecialCharacters($value) + protected static function escapeSpecialCharacters(string $value): string { // list taken from http://lucene.apache.org/core/4_4_0/queryparser/org/apache/lucene/queryparser/classic/package-summary.html#package_description // which mentions: + - && || ! ( ) { } [ ] ^ " ~ * ? : \ / diff --git a/Classes/Domain/Search/Query/ParameterBuilder/AbstractDeactivatable.php b/Classes/Domain/Search/Query/ParameterBuilder/AbstractDeactivatable.php index 908286d401..e06631449f 100644 --- a/Classes/Domain/Search/Query/ParameterBuilder/AbstractDeactivatable.php +++ b/Classes/Domain/Search/Query/ParameterBuilder/AbstractDeactivatable.php @@ -15,23 +15,25 @@ namespace ApacheSolrForTypo3\Solr\Domain\Search\Query\ParameterBuilder; -abstract class AbstractDeactivatable { - +abstract class AbstractDeactivatable +{ /** * @var bool */ - protected $isEnabled = false; + protected bool $isEnabled = false; + /** - * @return boolean + * @return bool */ - public function getIsEnabled() + public function getIsEnabled(): bool { return $this->isEnabled; } + /** - * @param boolean $isEnabled + * @param bool $isEnabled */ - public function setIsEnabled($isEnabled) + public function setIsEnabled(bool $isEnabled) { $this->isEnabled = $isEnabled; } diff --git a/Classes/Domain/Search/Query/ParameterBuilder/AbstractFieldList.php b/Classes/Domain/Search/Query/ParameterBuilder/AbstractFieldList.php index fb2c491373..4f32720f58 100644 --- a/Classes/Domain/Search/Query/ParameterBuilder/AbstractFieldList.php +++ b/Classes/Domain/Search/Query/ParameterBuilder/AbstractFieldList.php @@ -1,5 +1,7 @@ fieldList[$fieldName] = (float)$boost; + $this->fieldList[$fieldName] = $boost; return $this; } @@ -87,7 +83,7 @@ public function add(string $fieldName, float $boost = 1.0): AbstractFieldList * @param string $delimiter * @return string */ - public function toString(string $delimiter = ' ') + public function toString(string $delimiter = ' '): string { $fieldListString = ''; diff --git a/Classes/Domain/Search/Query/ParameterBuilder/BigramPhraseFields.php b/Classes/Domain/Search/Query/ParameterBuilder/BigramPhraseFields.php index c31853ebb4..375572e282 100644 --- a/Classes/Domain/Search/Query/ParameterBuilder/BigramPhraseFields.php +++ b/Classes/Domain/Search/Query/ParameterBuilder/BigramPhraseFields.php @@ -1,5 +1,7 @@ getBigramPhraseSearchIsEnabled(); if (!$isEnabled) { return new BigramPhraseFields(false); } - return self::fromString((string)$solrConfiguration->getSearchQueryBigramPhraseFields()); + return self::fromString($solrConfiguration->getSearchQueryBigramPhraseFields()); } /** @@ -63,7 +58,7 @@ public static function fromTypoScriptConfiguration(TypoScriptConfiguration $solr * @param string $delimiter * @return BigramPhraseFields */ - protected static function initializeFromString(string $fieldListString, string $delimiter = ',') : BigramPhraseFields + protected static function initializeFromString(string $fieldListString, string $delimiter = ','): BigramPhraseFields { $fieldList = self::buildFieldList($fieldListString, $delimiter); return new BigramPhraseFields(true, $fieldList); diff --git a/Classes/Domain/Search/Query/ParameterBuilder/Elevation.php b/Classes/Domain/Search/Query/ParameterBuilder/Elevation.php index cbe45e736b..0ad0c889a7 100644 --- a/Classes/Domain/Search/Query/ParameterBuilder/Elevation.php +++ b/Classes/Domain/Search/Query/ParameterBuilder/Elevation.php @@ -1,5 +1,7 @@ isEnabled = $isEnabled; $this->isForced = $isForced; $this->markElevatedResults = $markElevatedResults; } /** - * @return boolean + * @return bool */ public function getIsForced(): bool { @@ -56,7 +61,7 @@ public function getIsForced(): bool } /** - * @param boolean $isForced + * @param bool $isForced */ public function setIsForced(bool $isForced) { @@ -64,7 +69,7 @@ public function setIsForced(bool $isForced) } /** - * @return boolean + * @return bool */ public function getMarkElevatedResults(): bool { @@ -72,7 +77,7 @@ public function getMarkElevatedResults(): bool } /** - * @param boolean $markElevatedResults + * @param bool $markElevatedResults */ public function setMarkElevatedResults(bool $markElevatedResults) { @@ -83,7 +88,7 @@ public function setMarkElevatedResults(bool $markElevatedResults) * @param TypoScriptConfiguration $solrConfiguration * @return Elevation */ - public static function fromTypoScriptConfiguration(TypoScriptConfiguration $solrConfiguration) + public static function fromTypoScriptConfiguration(TypoScriptConfiguration $solrConfiguration): Elevation { $isEnabled = $solrConfiguration->getSearchElevation(); if (!$isEnabled) { @@ -98,7 +103,7 @@ public static function fromTypoScriptConfiguration(TypoScriptConfiguration $solr /** * @return Elevation */ - public static function getEmpty() + public static function getEmpty(): Elevation { return new Elevation(false); } diff --git a/Classes/Domain/Search/Query/ParameterBuilder/Faceting.php b/Classes/Domain/Search/Query/ParameterBuilder/Faceting.php index 92efd9bb9c..55c91bd9b6 100644 --- a/Classes/Domain/Search/Query/ParameterBuilder/Faceting.php +++ b/Classes/Domain/Search/Query/ParameterBuilder/Faceting.php @@ -26,9 +26,8 @@ * The Faceting ParameterProvider is responsible to build the solr query parameters * that are needed for the highlighting. */ -class Faceting extends AbstractDeactivatable implements ParameterBuilder +class Faceting extends AbstractDeactivatable implements ParameterBuilderInterface { - /** * @var string */ @@ -169,9 +168,10 @@ public function setAdditionalParameters(array $additionalParameters) } /** - * @param array $value + * @param string $key + * @param mixed $value */ - public function addAdditionalParameter($key, $value) + public function addAdditionalParameter(string $key, $value) { $this->additionalParameters[$key] = $value; } @@ -261,7 +261,7 @@ public function build(AbstractQueryBuilder $parentBuilder): AbstractQueryBuilder $query->addParam('facet.sort', null); $params = $query->getParams(); - foreach($params as $key => $value) { + foreach ($params as $key => $value) { if (strpos($key, 'f.') !== false) { $query->addParam($key, null); } @@ -272,7 +272,7 @@ public function build(AbstractQueryBuilder $parentBuilder): AbstractQueryBuilder //@todo check of $this->queryToBuilder->getFacetSet() can be used $facetingParameters = $this->getFacetParameters(); - foreach($facetingParameters as $key => $value) { + foreach ($facetingParameters as $key => $value) { $query->addParam($key, $value); } diff --git a/Classes/Domain/Search/Query/ParameterBuilder/FieldCollapsing.php b/Classes/Domain/Search/Query/ParameterBuilder/FieldCollapsing.php index 3b4cd00cd7..137ca33f55 100644 --- a/Classes/Domain/Search/Query/ParameterBuilder/FieldCollapsing.php +++ b/Classes/Domain/Search/Query/ParameterBuilder/FieldCollapsing.php @@ -22,22 +22,22 @@ * The FieldCollapsing ParameterProvider is responsible to build the solr query parameters * that are needed for the field collapsing. */ -class FieldCollapsing extends AbstractDeactivatable implements ParameterBuilder +class FieldCollapsing extends AbstractDeactivatable implements ParameterBuilderInterface { /** * @var string */ - protected $collapseFieldName = 'variantId'; + protected string $collapseFieldName = 'variantId'; /** * @var bool */ - protected $expand = false; + protected bool $expand = false; /** * @var int */ - protected $expandRowCount = 10; + protected int $expandRowCount = 10; /** * FieldCollapsing constructor. @@ -46,8 +46,12 @@ class FieldCollapsing extends AbstractDeactivatable implements ParameterBuilder * @param bool $expand * @param int $expandRowCount */ - public function __construct($isEnabled, $collapseFieldName = 'variantId', $expand = false, $expandRowCount = 10) - { + public function __construct( + bool $isEnabled, + string $collapseFieldName = 'variantId', + bool $expand = false, + int $expandRowCount = 10 + ) { $this->isEnabled = $isEnabled; $this->collapseFieldName = $collapseFieldName; $this->expand = $expand; @@ -71,7 +75,7 @@ public function setCollapseFieldName(string $collapseFieldName) } /** - * @return boolean + * @return bool */ public function getIsExpand(): bool { @@ -79,7 +83,7 @@ public function getIsExpand(): bool } /** - * @param boolean $expand + * @param bool $expand */ public function setExpand(bool $expand) { @@ -106,7 +110,7 @@ public function setExpandRowCount(int $expandRowCount) * @param TypoScriptConfiguration $solrConfiguration * @return FieldCollapsing */ - public static function fromTypoScriptConfiguration(TypoScriptConfiguration $solrConfiguration) + public static function fromTypoScriptConfiguration(TypoScriptConfiguration $solrConfiguration): FieldCollapsing { $isEnabled = $solrConfiguration->getSearchVariants(); if (!$isEnabled) { @@ -114,7 +118,7 @@ public static function fromTypoScriptConfiguration(TypoScriptConfiguration $solr } $collapseField = $solrConfiguration->getSearchVariantsField(); - $expand = (bool)$solrConfiguration->getSearchVariantsExpand(); + $expand = $solrConfiguration->getSearchVariantsExpand(); $expandRows = $solrConfiguration->getSearchVariantsLimit(); return new FieldCollapsing(true, $collapseField, $expand, $expandRows); @@ -123,7 +127,7 @@ public static function fromTypoScriptConfiguration(TypoScriptConfiguration $solr /** * @return FieldCollapsing */ - public static function getEmpty() + public static function getEmpty(): FieldCollapsing { return new FieldCollapsing(false); } @@ -135,12 +139,12 @@ public static function getEmpty() public function build(AbstractQueryBuilder $parentBuilder): AbstractQueryBuilder { $query = $parentBuilder->getQuery(); - if(!$this->getIsEnabled()) { + if (!$this->getIsEnabled()) { return $parentBuilder; } - $parentBuilder->useFilter('{!collapse field=' . $this->getCollapseFieldName(). '}', 'fieldCollapsing'); - if($this->getIsExpand()) { + $parentBuilder->useFilter('{!collapse field=' . $this->getCollapseFieldName() . '}', 'fieldCollapsing'); + if ($this->getIsExpand()) { $query->addParam('expand', 'true'); $query->addParam('expand.rows', $this->getExpandRowCount()); } diff --git a/Classes/Domain/Search/Query/ParameterBuilder/Filters.php b/Classes/Domain/Search/Query/ParameterBuilder/Filters.php index a088f9cd5b..542d123f11 100644 --- a/Classes/Domain/Search/Query/ParameterBuilder/Filters.php +++ b/Classes/Domain/Search/Query/ParameterBuilder/Filters.php @@ -16,7 +16,7 @@ namespace ApacheSolrForTypo3\Solr\Domain\Search\Query\ParameterBuilder; use ApacheSolrForTypo3\Solr\System\Configuration\TypoScriptConfiguration; -use TYPO3\CMS\Core\Utility\GeneralUtility; +use function str_starts_with; /** * The Filters ParameterProvider is responsible to build the solr query parameters @@ -24,19 +24,17 @@ */ class Filters { - /** * @var array */ - protected $filters = []; + protected array $filters = []; /** * Removes a filter on a field * * @param string $filterFieldName The field name the filter should be removed for - * @return void */ - public function removeByFieldName($filterFieldName) + public function removeByFieldName(string $filterFieldName) { $this->removeByPrefix($filterFieldName . ':'); } @@ -44,10 +42,10 @@ public function removeByFieldName($filterFieldName) /** * @param string $filterFieldName */ - public function removeByPrefix($filterFieldName) + public function removeByPrefix(string $filterFieldName) { foreach ($this->filters as $key => $filterString) { - if (\str_starts_with($filterString, $filterFieldName)) { + if (str_starts_with($filterString, $filterFieldName)) { unset($this->filters[$key]); } } @@ -58,17 +56,16 @@ public function removeByPrefix($filterFieldName) * * @param string $name name of the filter */ - public function removeByName($name) + public function removeByName(string $name) { unset($this->filters[$name]); } - /** * @param string $filterString * @param string $name */ - public function add($filterString, $name = '') + public function add(string $filterString, string $name = '') { if ($name !== '') { $this->filters[$name] = $filterString; @@ -78,14 +75,14 @@ public function add($filterString, $name = '') } /** - * Add's multiple filters to the filter collection. + * Adds multiple filters to the filter collection. * * @param array $filterArray * @return Filters */ - public function addMultiple($filterArray) + public function addMultiple(array $filterArray): Filters { - foreach($filterArray as $key => $value) { + foreach ($filterArray as $key => $value) { if (!$this->hasWithName($key)) { $this->add($value, $key); } @@ -98,7 +95,7 @@ public function addMultiple($filterArray) * @param string $name * @return bool */ - public function hasWithName($name) + public function hasWithName(string $name): bool { return array_key_exists($name, $this->filters); } @@ -110,7 +107,7 @@ public function hasWithName($name) * * @param string $filterString The filter to remove, in the form of field:value */ - public function removeByValue($filterString) + public function removeByValue(string $filterString) { $key = array_search($filterString, $this->filters); if ($key === false) { @@ -125,7 +122,7 @@ public function removeByValue($filterString) * * @return array Array of filters */ - public function getValues() + public function getValues(): array { return $this->filters; } @@ -133,8 +130,9 @@ public function getValues() /** * @param TypoScriptConfiguration $solrConfiguration * @return Filters + * @todo: Check why $solrConfiguration isn't used. */ - public static function fromTypoScriptConfiguration(TypoScriptConfiguration $solrConfiguration) + public static function fromTypoScriptConfiguration(TypoScriptConfiguration $solrConfiguration): Filters { return new Filters(); } @@ -142,7 +140,7 @@ public static function fromTypoScriptConfiguration(TypoScriptConfiguration $solr /** * @return Filters */ - public static function getEmpty() + public static function getEmpty(): Filters { return new Filters(); } diff --git a/Classes/Domain/Search/Query/ParameterBuilder/Grouping.php b/Classes/Domain/Search/Query/ParameterBuilder/Grouping.php index 64cf989a84..b3e2668f68 100644 --- a/Classes/Domain/Search/Query/ParameterBuilder/Grouping.php +++ b/Classes/Domain/Search/Query/ParameterBuilder/Grouping.php @@ -22,33 +22,32 @@ * The Grouping ParameterProvider is responsible to build the solr query parameters * that are needed for the grouping. */ -class Grouping extends AbstractDeactivatable implements ParameterBuilder +class Grouping extends AbstractDeactivatable implements ParameterBuilderInterface { - /** * @var array */ - protected $fields = []; + protected array $fields = []; /** * @var array */ - protected $sortings = []; + protected array $sortings = []; /** * @var array */ - protected $queries = []; + protected array $queries = []; /** * @var int */ - protected $numberOfGroups = 5; + protected int $numberOfGroups = 5; /** * @var int */ - protected $resultsPerGroup = 1; + protected int $resultsPerGroup = 1; /** * Grouping constructor. @@ -60,8 +59,14 @@ class Grouping extends AbstractDeactivatable implements ParameterBuilder * @param int $numberOfGroups * @param int $resultsPerGroup */ - public function __construct($isEnabled, array $fields = [], array $sortings = [], array $queries = [], $numberOfGroups = 5, $resultsPerGroup = 1) - { + public function __construct( + bool $isEnabled, + array $fields = [], + array $sortings = [], + array $queries = [], + int $numberOfGroups = 5, + int $resultsPerGroup = 1 + ) { $this->isEnabled = $isEnabled; $this->fields = $fields; $this->sortings = $sortings; @@ -73,7 +78,7 @@ public function __construct($isEnabled, array $fields = [], array $sortings = [] /** * @return array */ - public function getFields() + public function getFields(): array { return $this->fields; } @@ -97,7 +102,7 @@ public function addField(string $field) /** * @return array */ - public function getSortings() + public function getSortings(): array { return $this->sortings; } @@ -105,7 +110,7 @@ public function getSortings() /** * @param string $sorting */ - public function addSorting($sorting) + public function addSorting(string $sorting) { $this->sortings[] = $sorting; } @@ -129,7 +134,7 @@ public function getQueries(): array /** * @param string $query */ - public function addQuery($query) + public function addQuery(string $query) { $this->queries[] = $query; } @@ -145,7 +150,7 @@ public function setQueries(array $queries) /** * @return int */ - public function getNumberOfGroups() + public function getNumberOfGroups(): int { return $this->numberOfGroups; } @@ -153,7 +158,7 @@ public function getNumberOfGroups() /** * @param int $numberOfGroups */ - public function setNumberOfGroups($numberOfGroups) + public function setNumberOfGroups(int $numberOfGroups) { $this->numberOfGroups = $numberOfGroups; } @@ -161,7 +166,7 @@ public function setNumberOfGroups($numberOfGroups) /** * @return int */ - public function getResultsPerGroup() + public function getResultsPerGroup(): int { return $this->resultsPerGroup; } @@ -169,9 +174,9 @@ public function getResultsPerGroup() /** * @param int $resultsPerGroup */ - public function setResultsPerGroup($resultsPerGroup) + public function setResultsPerGroup(int $resultsPerGroup) { - $resultsPerGroup = max(intval($resultsPerGroup), 0); + $resultsPerGroup = max($resultsPerGroup, 0); $this->resultsPerGroup = $resultsPerGroup; } @@ -179,10 +184,9 @@ public function setResultsPerGroup($resultsPerGroup) * @param TypoScriptConfiguration $solrConfiguration * @return Grouping */ - public static function fromTypoScriptConfiguration(TypoScriptConfiguration $solrConfiguration) + public static function fromTypoScriptConfiguration(TypoScriptConfiguration $solrConfiguration): Grouping { - $isEnabled = $solrConfiguration->getSearchGrouping(); - if (!$isEnabled) { + if (!$solrConfiguration->getIsSearchGroupingEnabled()) { return new Grouping(false); } @@ -195,7 +199,7 @@ public static function fromTypoScriptConfiguration(TypoScriptConfiguration $solr $numberOfGroups = $solrConfiguration->getSearchGroupingNumberOfGroups(); $sortBy = $solrConfiguration->getSearchGroupingSortBy(); - foreach ($configuredGroups as $groupName => $groupConfiguration) { + foreach ($configuredGroups as $groupConfiguration) { if (isset($groupConfiguration['field'])) { $fields[] = $groupConfiguration['field']; } elseif (isset($groupConfiguration['query'])) { @@ -207,13 +211,13 @@ public static function fromTypoScriptConfiguration(TypoScriptConfiguration $solr $sortings[] = $sortBy; } - return new Grouping($isEnabled, $fields, $sortings, $queries, $numberOfGroups, $resultsPerGroup); + return new Grouping(true, $fields, $sortings, $queries, $numberOfGroups, $resultsPerGroup); } /** * @return Grouping */ - public static function getEmpty() + public static function getEmpty(): Grouping { return new Grouping(false); } @@ -225,7 +229,7 @@ public static function getEmpty() public function build(AbstractQueryBuilder $parentBuilder): AbstractQueryBuilder { $query = $parentBuilder->getQuery(); - if(!$this->getIsEnabled()) { + if (!$this->getIsEnabled()) { $query->removeComponent($query->getGrouping()); return $parentBuilder; } diff --git a/Classes/Domain/Search/Query/ParameterBuilder/Highlighting.php b/Classes/Domain/Search/Query/ParameterBuilder/Highlighting.php index 9b7337cab1..41fce440bf 100644 --- a/Classes/Domain/Search/Query/ParameterBuilder/Highlighting.php +++ b/Classes/Domain/Search/Query/ParameterBuilder/Highlighting.php @@ -1,5 +1,7 @@ isEnabled = $isEnabled; $this->fragmentSize = $fragmentSize; $this->highlightingFieldList = $highlightingFieldList; @@ -131,19 +137,18 @@ public function setPostfix(string $postfix) /** * @return bool */ - public function getUseFastVectorHighlighter() + public function getUseFastVectorHighlighter(): bool { - return ($this->fragmentSize >= 18); + return $this->fragmentSize >= 18; } - /** * @param TypoScriptConfiguration $solrConfiguration * @return Highlighting */ - public static function fromTypoScriptConfiguration(TypoScriptConfiguration $solrConfiguration) + public static function fromTypoScriptConfiguration(TypoScriptConfiguration $solrConfiguration): Highlighting { - $isEnabled = $solrConfiguration->getSearchResultsHighlighting(); + $isEnabled = $solrConfiguration->getIsSearchResultsHighlightingEnabled(); if (!$isEnabled) { return new Highlighting(false); } @@ -151,22 +156,20 @@ public static function fromTypoScriptConfiguration(TypoScriptConfiguration $solr $fragmentSize = $solrConfiguration->getSearchResultsHighlightingFragmentSize(); $highlightingFields = $solrConfiguration->getSearchResultsHighlightingFields(); $wrap = explode('|', $solrConfiguration->getSearchResultsHighlightingWrap()); - $prefix = isset($wrap[0]) ? $wrap[0] : ''; - $postfix = isset($wrap[1]) ? $wrap[1] : ''; + $prefix = $wrap[0] ?? ''; + $postfix = $wrap[1] ?? ''; - - return new Highlighting($isEnabled, $fragmentSize, $highlightingFields, $prefix, $postfix); + return new Highlighting(true, $fragmentSize, $highlightingFields, $prefix, $postfix); } /** * @return Highlighting */ - public static function getEmpty() + public static function getEmpty(): Highlighting { return new Highlighting(false); } - /** * @param AbstractQueryBuilder $parentBuilder * @return AbstractQueryBuilder @@ -174,13 +177,13 @@ public static function getEmpty() public function build(AbstractQueryBuilder $parentBuilder): AbstractQueryBuilder { $query = $parentBuilder->getQuery(); - if(!$this->getIsEnabled()) { + if (!$this->getIsEnabled()) { $query->removeComponent($query->getHighlighting()); return $parentBuilder; } $query->getHighlighting()->setFragSize($this->getFragmentSize()); - $query->getHighlighting()->setFields(GeneralUtility::trimExplode(",", $this->getHighlightingFieldList())); + $query->getHighlighting()->setFields(GeneralUtility::trimExplode(',', $this->getHighlightingFieldList())); if ($this->getUseFastVectorHighlighter()) { $query->getHighlighting()->setUseFastVectorHighlighter(true); diff --git a/Classes/Domain/Search/Query/ParameterBuilder/Operator.php b/Classes/Domain/Search/Query/ParameterBuilder/Operator.php index 5d8fbd74d4..e05f84d1a7 100644 --- a/Classes/Domain/Search/Query/ParameterBuilder/Operator.php +++ b/Classes/Domain/Search/Query/ParameterBuilder/Operator.php @@ -15,6 +15,8 @@ namespace ApacheSolrForTypo3\Solr\Domain\Search\Query\ParameterBuilder; +use InvalidArgumentException; + /** * The Operator ParameterProvider is responsible to build the solr query parameters * that are needed for the operator q.op. @@ -27,7 +29,7 @@ class Operator extends AbstractDeactivatable /** * @var string */ - protected $operator = 'AND'; + protected string $operator = 'AND'; /** * Faceting constructor. @@ -35,8 +37,10 @@ class Operator extends AbstractDeactivatable * @param bool $isEnabled * @param string $operator */ - public function __construct($isEnabled, $operator = Operator::OPERATOR_AND) - { + public function __construct( + bool $isEnabled, + string $operator = Operator::OPERATOR_AND + ) { $this->isEnabled = $isEnabled; $this->setOperator($operator); } @@ -44,10 +48,10 @@ public function __construct($isEnabled, $operator = Operator::OPERATOR_AND) /** * @param string $operator */ - public function setOperator($operator) + public function setOperator(string $operator) { if (!in_array($operator, [self::OPERATOR_AND, self::OPERATOR_OR])) { - throw new \InvalidArgumentException("Invalid operator"); + throw new InvalidArgumentException('Invalid operator'); } $this->operator = $operator; @@ -89,7 +93,7 @@ public static function getOr(): Operator * @param string $operator * @return Operator */ - public static function fromString($operator) + public static function fromString(string $operator): Operator { return new Operator(true, $operator); } diff --git a/Classes/Domain/Search/Query/ParameterBuilder/ParameterBuilder.php b/Classes/Domain/Search/Query/ParameterBuilder/ParameterBuilderInterface.php similarity index 96% rename from Classes/Domain/Search/Query/ParameterBuilder/ParameterBuilder.php rename to Classes/Domain/Search/Query/ParameterBuilder/ParameterBuilderInterface.php index fc183aaa7f..ff5c91864f 100644 --- a/Classes/Domain/Search/Query/ParameterBuilder/ParameterBuilder.php +++ b/Classes/Domain/Search/Query/ParameterBuilder/ParameterBuilderInterface.php @@ -23,9 +23,8 @@ * * Interface ParameterProvider */ -interface ParameterBuilder { - - +interface ParameterBuilderInterface +{ /** * @param AbstractQueryBuilder $parentBuilder * @return AbstractQueryBuilder diff --git a/Classes/Domain/Search/Query/ParameterBuilder/PhraseFields.php b/Classes/Domain/Search/Query/ParameterBuilder/PhraseFields.php index 57d2b9e245..621eb9ff2f 100644 --- a/Classes/Domain/Search/Query/ParameterBuilder/PhraseFields.php +++ b/Classes/Domain/Search/Query/ParameterBuilder/PhraseFields.php @@ -21,15 +21,8 @@ /** * The PhraseFields class */ -class PhraseFields extends AbstractFieldList implements ParameterBuilder +class PhraseFields extends AbstractFieldList implements ParameterBuilderInterface { - /** - * Parameter key which should be used for Apache Solr URL query - * - * @var string - */ - protected $parameterKey = 'pf'; - /** * Parses the string representation of the fieldList (e.g. content^100, title^10) to the object representation. * @@ -37,7 +30,7 @@ class PhraseFields extends AbstractFieldList implements ParameterBuilder * @param string $delimiter * @return PhraseFields */ - public static function fromString(string $fieldListString, string $delimiter = ',') : PhraseFields + public static function fromString(string $fieldListString, string $delimiter = ','): PhraseFields { return self::initializeFromString($fieldListString, $delimiter); } @@ -46,14 +39,14 @@ public static function fromString(string $fieldListString, string $delimiter = ' * @param TypoScriptConfiguration $solrConfiguration * @return PhraseFields */ - public static function fromTypoScriptConfiguration(TypoScriptConfiguration $solrConfiguration) + public static function fromTypoScriptConfiguration(TypoScriptConfiguration $solrConfiguration): PhraseFields { $isEnabled = $solrConfiguration->getPhraseSearchIsEnabled(); if (!$isEnabled) { return new PhraseFields(false); } - return self::fromString((string)$solrConfiguration->getSearchQueryPhraseFields()); + return self::fromString($solrConfiguration->getSearchQueryPhraseFields()); } /** @@ -63,7 +56,7 @@ public static function fromTypoScriptConfiguration(TypoScriptConfiguration $solr * @param string $delimiter * @return PhraseFields */ - protected static function initializeFromString(string $fieldListString, string $delimiter = ',') : PhraseFields + protected static function initializeFromString(string $fieldListString, string $delimiter = ','): PhraseFields { $fieldList = self::buildFieldList($fieldListString, $delimiter); return new PhraseFields(true, $fieldList); diff --git a/Classes/Domain/Search/Query/ParameterBuilder/QueryFields.php b/Classes/Domain/Search/Query/ParameterBuilder/QueryFields.php index 1b8d589b2b..c66a23f245 100644 --- a/Classes/Domain/Search/Query/ParameterBuilder/QueryFields.php +++ b/Classes/Domain/Search/Query/ParameterBuilder/QueryFields.php @@ -21,13 +21,12 @@ /** * The QueryFields class holds all information for the query which fields should be used to query (Solr qf parameter). */ -class QueryFields implements ParameterBuilder +class QueryFields implements ParameterBuilderInterface { - /** * @var array */ - protected $queryFields = []; + protected array $queryFields = []; /** * QueryFields constructor. @@ -43,9 +42,9 @@ public function __construct(array $queryFields = []) * @param string $fieldName * @param float $boost */ - public function set($fieldName, $boost = 1.0) + public function set(string $fieldName, float $boost = 1.0) { - $this->queryFields[$fieldName] = (float)$boost; + $this->queryFields[$fieldName] = $boost; } /** @@ -54,7 +53,8 @@ public function set($fieldName, $boost = 1.0) * @param string $delimiter * @return string */ - public function toString($delimiter = ' ') { + public function toString(string $delimiter = ' '): string + { $queryFieldString = ''; foreach ($this->queryFields as $fieldName => $fieldBoost) { @@ -77,7 +77,8 @@ public function toString($delimiter = ' ') { * @param string $delimiter * @return QueryFields */ - public static function fromString($queryFieldsString, $delimiter = ',') { + public static function fromString(string $queryFieldsString, string $delimiter = ','): QueryFields + { $fields = GeneralUtility::trimExplode($delimiter, $queryFieldsString, true); $queryFields = []; @@ -86,7 +87,7 @@ public static function fromString($queryFieldsString, $delimiter = ',') { $boost = 1.0; if (isset($fieldNameAndBoost[1])) { - $boost = floatval($fieldNameAndBoost[1]); + $boost = (float)($fieldNameAndBoost[1]); } $fieldName = $fieldNameAndBoost[0]; diff --git a/Classes/Domain/Search/Query/ParameterBuilder/ReturnFields.php b/Classes/Domain/Search/Query/ParameterBuilder/ReturnFields.php index a73368d386..26fb717921 100644 --- a/Classes/Domain/Search/Query/ParameterBuilder/ReturnFields.php +++ b/Classes/Domain/Search/Query/ParameterBuilder/ReturnFields.php @@ -22,13 +22,12 @@ * The ReturnFields class is responsible to hold a list of field names that should be returned from * solr. */ -class ReturnFields implements ParameterBuilder +class ReturnFields implements ParameterBuilderInterface { - /** * @var array */ - protected $fieldList = []; + protected array $fieldList = []; /** * FieldList constructor. @@ -46,7 +45,7 @@ public function __construct(array $fieldList = []) * * @param string $fieldName Name of a field to return in the result documents */ - public function add($fieldName) + public function add(string $fieldName) { if (strpos($fieldName, '[') === false && strpos($fieldName, ']') === false && in_array('*', $this->fieldList)) { $this->fieldList = array_diff($this->fieldList, ['*']); @@ -60,7 +59,7 @@ public function add($fieldName) * * @param string $fieldName Field to remove from the list of fields to return */ - public function remove($fieldName) + public function remove(string $fieldName) { $key = array_search($fieldName, $this->fieldList); @@ -73,7 +72,7 @@ public function remove($fieldName) * @param string $delimiter * @return string */ - public function toString($delimiter = ',') + public function toString(string $delimiter = ','): string { return implode($delimiter, $this->fieldList); } @@ -83,7 +82,7 @@ public function toString($delimiter = ',') * @param string $delimiter * @return ReturnFields */ - public static function fromString($fieldList, $delimiter = ',') + public static function fromString(string $fieldList, string $delimiter = ','): ReturnFields { $fieldListArray = GeneralUtility::trimExplode($delimiter, $fieldList); return static::fromArray($fieldListArray); @@ -93,7 +92,7 @@ public static function fromString($fieldList, $delimiter = ',') * @param array $fieldListArray * @return ReturnFields */ - public static function fromArray(array $fieldListArray) + public static function fromArray(array $fieldListArray): ReturnFields { return new ReturnFields($fieldListArray); } @@ -101,7 +100,7 @@ public static function fromArray(array $fieldListArray) /** * @return array */ - public function getValues() + public function getValues(): array { return array_unique(array_values($this->fieldList)); } diff --git a/Classes/Domain/Search/Query/ParameterBuilder/Slops.php b/Classes/Domain/Search/Query/ParameterBuilder/Slops.php index 9099096c2c..17fe0e4b5b 100644 --- a/Classes/Domain/Search/Query/ParameterBuilder/Slops.php +++ b/Classes/Domain/Search/Query/ParameterBuilder/Slops.php @@ -1,5 +1,7 @@ querySlop = $querySlop; $this->phraseSlop = $phraseSlop; $this->bigramPhraseSlop = $bigramPhraseSlop; @@ -64,7 +70,7 @@ public function __construct($querySlop = self::NO_SLOP, $phraseSlop = self::NO_S } /** - * @return boolean + * @return bool */ public function getHasQuerySlop() { @@ -88,14 +94,13 @@ public function setQuerySlop(int $querySlop) } /** - * @return boolean + * @return bool */ public function getHasPhraseSlop() { return $this->phraseSlop !== null; } - /** * @return int|null */ @@ -113,7 +118,7 @@ public function setPhraseSlop(int $phraseSlop) } /** - * @return boolean + * @return bool */ public function getHasBigramPhraseSlop() { @@ -137,7 +142,7 @@ public function setBigramPhraseSlop(int $bigramPhraseSlop) } /** - * @return boolean + * @return bool */ public function getHasTrigramPhraseSlop() { diff --git a/Classes/Domain/Search/Query/ParameterBuilder/Sortings.php b/Classes/Domain/Search/Query/ParameterBuilder/Sortings.php index 133a421535..953b8a3feb 100644 --- a/Classes/Domain/Search/Query/ParameterBuilder/Sortings.php +++ b/Classes/Domain/Search/Query/ParameterBuilder/Sortings.php @@ -26,15 +26,17 @@ class Sortings extends AbstractDeactivatable /** * @var array */ - protected $sortings = []; + protected array $sortings = []; /** * Sortings constructor. * @param bool $isEnabled * @param array $sortings */ - public function __construct($isEnabled = false, $sortings = []) - { + public function __construct( + bool $isEnabled = false, + array $sortings = [] + ) { $this->isEnabled = $isEnabled; $this->setSortings($sortings); } @@ -42,7 +44,7 @@ public function __construct($isEnabled = false, $sortings = []) /** * @return Sortings */ - public static function getEmpty() + public static function getEmpty(): Sortings { return new Sortings(false); } @@ -76,11 +78,11 @@ public function addSorting(Sorting $sorting) * @param string $sortingsString * @return Sortings */ - public static function fromString($sortingsString) + public static function fromString(string $sortingsString): Sortings { - $sortFields = GeneralUtility::trimExplode(',',$sortingsString); + $sortFields = GeneralUtility::trimExplode(',', $sortingsString); $sortings = []; - foreach($sortFields as $sortField) { + foreach ($sortFields as $sortField) { $sorting = Sorting::fromString($sortField); $sortings[] = $sorting; } diff --git a/Classes/Domain/Search/Query/ParameterBuilder/Spellchecking.php b/Classes/Domain/Search/Query/ParameterBuilder/Spellchecking.php index dc5c308710..6f8cae698e 100644 --- a/Classes/Domain/Search/Query/ParameterBuilder/Spellchecking.php +++ b/Classes/Domain/Search/Query/ParameterBuilder/Spellchecking.php @@ -22,13 +22,13 @@ * The Spellchecking ParameterProvider is responsible to build the solr query parameters * that are needed for the spellchecking. */ -class Spellchecking extends AbstractDeactivatable implements ParameterBuilder +class Spellchecking extends AbstractDeactivatable implements ParameterBuilderInterface { /** * @var int */ - protected $maxCollationTries = 0; + protected int $maxCollationTries = 0; /** * Spellchecking constructor. @@ -36,8 +36,10 @@ class Spellchecking extends AbstractDeactivatable implements ParameterBuilder * @param bool $isEnabled * @param int $maxCollationTries */ - public function __construct($isEnabled = false, int $maxCollationTries = 0) - { + public function __construct( + bool $isEnabled = false, + int $maxCollationTries = 0 + ) { $this->isEnabled = $isEnabled; $this->maxCollationTries = $maxCollationTries; } @@ -54,7 +56,7 @@ public function getMaxCollationTries(): int * @param TypoScriptConfiguration $solrConfiguration * @return Spellchecking */ - public static function fromTypoScriptConfiguration(TypoScriptConfiguration $solrConfiguration) + public static function fromTypoScriptConfiguration(TypoScriptConfiguration $solrConfiguration): Spellchecking { $isEnabled = $solrConfiguration->getSearchSpellchecking(); if (!$isEnabled) { @@ -63,13 +65,13 @@ public static function fromTypoScriptConfiguration(TypoScriptConfiguration $solr $maxCollationTries = $solrConfiguration->getSearchSpellcheckingNumberOfSuggestionsToTry(); - return new Spellchecking($isEnabled, $maxCollationTries); + return new Spellchecking(true, $maxCollationTries); } /** * @return Spellchecking */ - public static function getEmpty() + public static function getEmpty(): Spellchecking { return new Spellchecking(false); } diff --git a/Classes/Domain/Search/Query/ParameterBuilder/TrigramPhraseFields.php b/Classes/Domain/Search/Query/ParameterBuilder/TrigramPhraseFields.php index 0d1e81e51d..34eaf71e4a 100644 --- a/Classes/Domain/Search/Query/ParameterBuilder/TrigramPhraseFields.php +++ b/Classes/Domain/Search/Query/ParameterBuilder/TrigramPhraseFields.php @@ -21,15 +21,8 @@ /** * The TrigramPhraseFields class */ -class TrigramPhraseFields extends AbstractFieldList implements ParameterBuilder +class TrigramPhraseFields extends AbstractFieldList implements ParameterBuilderInterface { - /** - * Parameter key which should be used for Apache Solr URL query - * - * @var string - */ - protected $parameterKey = 'pf3'; - /** * Parses the string representation of the fieldList (e.g. content^100, title^10) to the object representation. * @@ -37,7 +30,7 @@ class TrigramPhraseFields extends AbstractFieldList implements ParameterBuilder * @param string $delimiter * @return TrigramPhraseFields */ - public static function fromString(string $fieldListString, string $delimiter = ',') : TrigramPhraseFields + public static function fromString(string $fieldListString, string $delimiter = ','): TrigramPhraseFields { return self::initializeFromString($fieldListString, $delimiter); } @@ -46,14 +39,14 @@ public static function fromString(string $fieldListString, string $delimiter = ' * @param TypoScriptConfiguration $solrConfiguration * @return TrigramPhraseFields */ - public static function fromTypoScriptConfiguration(TypoScriptConfiguration $solrConfiguration) + public static function fromTypoScriptConfiguration(TypoScriptConfiguration $solrConfiguration): TrigramPhraseFields { $isEnabled = $solrConfiguration->getTrigramPhraseSearchIsEnabled(); if (!$isEnabled) { return new TrigramPhraseFields(false); } - return self::fromString((string)$solrConfiguration->getSearchQueryTrigramPhraseFields()); + return self::fromString($solrConfiguration->getSearchQueryTrigramPhraseFields()); } /** @@ -63,7 +56,7 @@ public static function fromTypoScriptConfiguration(TypoScriptConfiguration $solr * @param string $delimiter * @return TrigramPhraseFields */ - protected static function initializeFromString(string $fieldListString, string $delimiter = ',') : TrigramPhraseFields + protected static function initializeFromString(string $fieldListString, string $delimiter = ','): TrigramPhraseFields { $fieldList = self::buildFieldList($fieldListString, $delimiter); return new TrigramPhraseFields(true, $fieldList); diff --git a/Classes/Domain/Search/Query/Query.php b/Classes/Domain/Search/Query/Query.php index 683c82eff4..abfa31b79e 100644 --- a/Classes/Domain/Search/Query/Query.php +++ b/Classes/Domain/Search/Query/Query.php @@ -17,17 +17,8 @@ use Solarium\QueryType\Select\Query\Query as SolariumQuery; -class Query extends SolariumQuery { - - /** - * Returns the query parameters that should be used. - * - * @return array - */ - public function getQueryParameters() { - return $this->getParams(); - } - +class Query extends SolariumQuery +{ /** * @return string */ diff --git a/Classes/Domain/Search/Query/QueryBuilder.php b/Classes/Domain/Search/Query/QueryBuilder.php index 6d561a0e2a..467694b0f6 100644 --- a/Classes/Domain/Search/Query/QueryBuilder.php +++ b/Classes/Domain/Search/Query/QueryBuilder.php @@ -1,5 +1,7 @@ queryToBuild = $this->getSearchQueryInstance((string)$queryString); + $this->queryToBuild = $this->getSearchQueryInstance($queryString); return $this; } @@ -100,7 +103,7 @@ public function newSearchQuery($queryString): QueryBuilder * @param string $queryString * @return QueryBuilder */ - public function newSuggestQuery($queryString): QueryBuilder + public function newSuggestQuery(string $queryString): QueryBuilder { $this->queryToBuild = $this->getSuggestQueryInstance($queryString); return $this; @@ -113,15 +116,17 @@ public function newSuggestQuery($queryString): QueryBuilder * @param string|null $rawQuery * @param int $resultsPerPage * @param array $additionalFiltersFromRequest - * @return SearchQuery + * @return SolariumSelectQuery */ - public function buildSearchQuery($rawQuery, $resultsPerPage = 10, array $additionalFiltersFromRequest = []) : SearchQuery - { + public function buildSearchQuery( + string $rawQuery = '', + int $resultsPerPage = 10, + array $additionalFiltersFromRequest = [] + ): SolariumSelectQuery { if ($this->typoScriptConfiguration->getLoggingQuerySearchWords()) { $this->logger->log(SolrLogManager::INFO, 'Received search query', [$rawQuery]); } - /* @var $query SearchQuery */ return $this->newSearchQuery($rawQuery) ->useResultsPerPage($resultsPerPage) ->useReturnFieldsFromTypoScript() @@ -145,11 +150,13 @@ public function buildSearchQuery($rawQuery, $resultsPerPage = 10, array $additio * * @param string $queryString * @param array $additionalFilters - * @param integer $requestedPageId + * @param int $requestedPageId * @param string $groupList * @return SuggestQuery + * @throws DBALDriverException + * @throws Throwable */ - public function buildSuggestQuery(string $queryString, array $additionalFilters, int $requestedPageId, string $groupList) : SuggestQuery + public function buildSuggestQuery(string $queryString, array $additionalFilters, int $requestedPageId, string $groupList): SuggestQuery { $this->newSuggestQuery($queryString) ->useFiltersFromTypoScript() @@ -157,7 +164,6 @@ public function buildSuggestQuery(string $queryString, array $additionalFilters, ->useUserAccessGroups(explode(',', $groupList)) ->useOmitHeader(); - if (!empty($additionalFilters)) { $this->useFilterArray($additionalFilters); } @@ -169,9 +175,11 @@ public function buildSuggestQuery(string $queryString, array $additionalFilters, * Returns Query for Search which finds document for given page. * Note: The Connection is per language as recommended in ext-solr docs. * - * @return Query + * @param int $pageId + * @return SolariumSelectQuery + * @throws DBALDriverException */ - public function buildPageQuery($pageId) + public function buildPageQuery(int $pageId): SolariumSelectQuery { $siteRepository = GeneralUtility::makeInstance(SiteRepository::class); $site = $siteRepository->getSiteByPageId($pageId); @@ -189,9 +197,13 @@ public function buildPageQuery($pageId) /** * Returns a query for single record * - * @return Query + * @param string $type + * @param int $uid + * @param int $pageId + * @return SolariumSelectQuery|Query + * @throws DBALDriverException */ - public function buildRecordQuery($type, $uid, $pageId): Query + public function buildRecordQuery(string $type, int $uid, int $pageId): SolariumSelectQuery { $siteRepository = GeneralUtility::makeInstance(SiteRepository::class); $site = $siteRepository->getSiteByPageId($pageId); @@ -275,7 +287,7 @@ public function useTieParameterFromTypoScript(): QueryBuilder return $this; } - return $this->useTieParameter($searchConfiguration['query.']['tieParameter']); + return $this->useTieParameter((float)$searchConfiguration['query.']['tieParameter']); } /** @@ -295,17 +307,17 @@ public function useQueryFieldsFromTypoScript(): QueryBuilder */ public function useReturnFieldsFromTypoScript(): QueryBuilder { - $returnFieldsArray = (array)$this->typoScriptConfiguration->getSearchQueryReturnFieldsAsArray(['*', 'score']); + $returnFieldsArray = $this->typoScriptConfiguration->getSearchQueryReturnFieldsAsArray(['*', 'score']); return $this->useReturnFields(ReturnFields::fromArray($returnFieldsArray)); } - - /** * Can be used to apply the allowed sites from plugin.tx_solr.search.query.allowedSites to the query. * * @param int $requestedPageId * @return QueryBuilder + * @throws DBALDriverException + * @throws Throwable */ public function useSiteHashFromTypoScript(int $requestedPageId): QueryBuilder { @@ -320,7 +332,7 @@ public function useSiteHashFromTypoScript(int $requestedPageId): QueryBuilder * @param string $allowedSites * @return QueryBuilder */ - public function useSiteHashFromAllowedSites($allowedSites): QueryBuilder + public function useSiteHashFromAllowedSites(string $allowedSites): QueryBuilder { $isAnySiteAllowed = trim($allowedSites) === '*'; if ($isAnySiteAllowed) { @@ -421,6 +433,7 @@ public function useHighlightingFromTypoScript(): QueryBuilder * Applies the configured filters (page section and other from typoscript). * * @return QueryBuilder + * @todo: Method is widely used but {@link Filters::fromTypoScriptConfiguration()} does not take TypoScript into account */ public function useFiltersFromTypoScript(): QueryBuilder { @@ -431,7 +444,7 @@ public function useFiltersFromTypoScript(): QueryBuilder $searchQueryFilters = $this->typoScriptConfiguration->getSearchQueryFilterConfiguration(); - if (!is_array($searchQueryFilters) || count($searchQueryFilters) <= 0) { + if (count($searchQueryFilters) <= 0) { return $this; } @@ -523,15 +536,15 @@ public function useTrigramPhraseFieldsFromTypoScript(): QueryBuilder * * @return array */ - public function getAdditionalFilters() : array + public function getAdditionalFilters(): array { - // when we've build the additionalFilter once, we could return them + // when we've built the additionalFilter once, we could return them if (count($this->additionalFilters) > 0) { return $this->additionalFilters; } $searchQueryFilters = $this->typoScriptConfiguration->getSearchQueryFilterConfiguration(); - if (!is_array($searchQueryFilters) || count($searchQueryFilters) <= 0) { + if (count($searchQueryFilters) <= 0) { return []; } @@ -575,10 +588,8 @@ protected function getSearchQueryInstance(string $rawQuery): SearchQuery * @param string $rawQuery * @return SuggestQuery */ - protected function getSuggestQueryInstance($rawQuery): SuggestQuery + protected function getSuggestQueryInstance(string $rawQuery): SuggestQuery { - $query = GeneralUtility::makeInstance(SuggestQuery::class, /** @scrutinizer ignore-type */ $rawQuery, /** @scrutinizer ignore-type */ $this->typoScriptConfiguration); - - return $query; + return GeneralUtility::makeInstance(SuggestQuery::class, /** @scrutinizer ignore-type */ $rawQuery, /** @scrutinizer ignore-type */ $this->typoScriptConfiguration); } } diff --git a/Classes/Domain/Search/Query/SearchQuery.php b/Classes/Domain/Search/Query/SearchQuery.php index 6ebb7b74b7..ad658b9fe2 100644 --- a/Classes/Domain/Search/Query/SearchQuery.php +++ b/Classes/Domain/Search/Query/SearchQuery.php @@ -1,5 +1,7 @@ setQuery($keywords); @@ -66,7 +66,7 @@ public function __construct($keywords, $solrConfiguration = null) } $this->getEDisMax()->setQueryAlternative('*:*'); - $this->setFields(ReturnFields::fromString(($this->configuration['suggestField'] ?? null))->getValues()); + $this->setFields(ReturnFields::fromString(($this->configuration['suggestField'] ?? ''))->getValues()); $this->addParam('facet', 'on'); $this->addParam('facet.prefix', $this->prefix); $this->addParam('facet.field', ($this->configuration['suggestField'] ?? null)); diff --git a/Classes/Domain/Search/ResultSet/Facets/AbstractFacet.php b/Classes/Domain/Search/ResultSet/Facets/AbstractFacet.php index 5dbc7dda73..5cdadf7b87 100644 --- a/Classes/Domain/Search/ResultSet/Facets/AbstractFacet.php +++ b/Classes/Domain/Search/ResultSet/Facets/AbstractFacet.php @@ -19,7 +19,7 @@ use TYPO3\CMS\Extbase\Object\ObjectManagerInterface; /** - * Value object that represent a options facet. + * Value object that represent the options facet. * * @author Frans Saris * @author Timo Hund @@ -32,54 +32,54 @@ abstract class AbstractFacet * String * @var string */ - protected static $type = self::TYPE_ABSTRACT; + protected static string $type = self::TYPE_ABSTRACT; /** * The resultSet where this facet belongs to. * * @var SearchResultSet */ - protected $resultSet = null; + protected SearchResultSet $resultSet; /** * @var string */ - protected $name; + protected string $name; /** * @var string */ - protected $field; + protected string $field; /** * @var string */ - protected $label; + protected string $label; /** * @var array */ - protected $configuration; + protected array $configuration; /** - * @var boolean + * @var bool */ - protected $isAvailable = false; + protected bool $isAvailable = false; /** * @var bool */ - protected $isUsed = false; + protected bool $isUsed = false; /** * @var bool */ - protected $allRequirementsMet = true; + protected bool $allRequirementsMet = true; /** - * @var \TYPO3\CMS\Extbase\Object\ObjectManagerInterface + * @var ObjectManagerInterface */ - protected $objectManager; + protected ObjectManagerInterface $objectManager; /** * AbstractFacet constructor. @@ -90,8 +90,13 @@ abstract class AbstractFacet * @param string $label * @param array $configuration Facet configuration passed from typoscript */ - public function __construct(SearchResultSet $resultSet, $name, $field, $label = '', array $configuration = []) - { + public function __construct( + SearchResultSet $resultSet, + string $name, + string $field, + string $label = '', + array $configuration = [] + ) { $this->resultSet = $resultSet; $this->name = $name; $this->field = $field; @@ -102,7 +107,7 @@ public function __construct(SearchResultSet $resultSet, $name, $field, $label = /** * Injects the object manager * - * @param \TYPO3\CMS\Extbase\Object\ObjectManagerInterface $objectManager + * @param ObjectManagerInterface $objectManager */ public function injectObjectManager(ObjectManagerInterface $objectManager) { @@ -114,7 +119,7 @@ public function injectObjectManager(ObjectManagerInterface $objectManager) * * @return string */ - public function getName() + public function getName(): string { return $this->name; } @@ -124,7 +129,7 @@ public function getName() * * @return string */ - public function getField() + public function getField(): string { return $this->field; } @@ -132,7 +137,7 @@ public function getField() /** * @param string $label */ - public function setLabel($label) + public function setLabel(string $label) { $this->label = $label; } @@ -140,39 +145,39 @@ public function setLabel($label) /** * @return string */ - public function getLabel() + public function getLabel(): string { return $this->label; } /** - * @param boolean $isAvailable + * @param bool $isAvailable */ - public function setIsAvailable($isAvailable) + public function setIsAvailable(bool $isAvailable) { $this->isAvailable = $isAvailable; } /** - * @return boolean + * @return bool */ - public function getIsAvailable() + public function getIsAvailable(): bool { return $this->isAvailable; } /** - * @param boolean $isUsed + * @param bool $isUsed */ - public function setIsUsed($isUsed) + public function setIsUsed(bool $isUsed) { $this->isUsed = $isUsed; } /** - * @return boolean + * @return bool */ - public function getIsUsed() + public function getIsUsed(): bool { return $this->isUsed; } @@ -180,23 +185,23 @@ public function getIsUsed() /** * @return string */ - public function getType() + public function getType(): string { return static::$type; } /** - * @return boolean + * @return bool */ - public function getAllRequirementsMet() + public function getAllRequirementsMet(): bool { return $this->allRequirementsMet; } /** - * @param boolean $allRequirementsMet + * @param bool $allRequirementsMet */ - public function setAllRequirementsMet($allRequirementsMet) + public function setAllRequirementsMet(bool $allRequirementsMet) { $this->allRequirementsMet = $allRequirementsMet; } @@ -204,7 +209,7 @@ public function setAllRequirementsMet($allRequirementsMet) /** * @return SearchResultSet */ - public function getResultSet() + public function getResultSet(): SearchResultSet { return $this->resultSet; } @@ -212,9 +217,9 @@ public function getResultSet() /** * Get configuration * - * @return mixed + * @return array */ - public function getConfiguration() + public function getConfiguration(): array { return $this->configuration; } @@ -224,7 +229,7 @@ public function getConfiguration() * * @return string */ - public function getPartialName() + public function getPartialName(): string { return 'Default'; } @@ -232,31 +237,30 @@ public function getPartialName() /** * @return string */ - public function getGroupName() + public function getGroupName(): string { - return isset($this->configuration['groupName']) ? $this->configuration['groupName'] : 'main'; + return $this->configuration['groupName'] ?? 'main'; } /** - * Indicates if this facet should ne included in the available facets. When nothing is configured, + * Indicates if this facet should be included in the available facets. When nothing is configured, * the method return TRUE. * - * @return boolean + * @return bool */ - public function getIncludeInAvailableFacets() + public function getIncludeInAvailableFacets(): bool { return ((int)$this->getFacetSettingOrDefaultValue('includeInAvailableFacets', 1)) === 1; } /** - * Indicates if this facets should be included in the used facets. When nothing is configured, + * Indicates if these facets should be included in the used facets. When nothing is configured, * the methods returns true. * - * @return boolean + * @return bool */ - public function getIncludeInUsedFacets() + public function getIncludeInUsedFacets(): bool { - return ((int)$this->getFacetSettingOrDefaultValue('includeInUsedFacets', 1)) === 1; } @@ -265,7 +269,7 @@ public function getIncludeInUsedFacets() * * @return array */ - public function getRequirements() + public function getRequirements(): array { return $this->getFacetSettingOrDefaultValue('requirements.', []); } @@ -275,19 +279,19 @@ public function getRequirements() * * @return AbstractFacetItemCollection */ - abstract public function getAllFacetItems(); + abstract public function getAllFacetItems(): AbstractFacetItemCollection; /** * @param string $key * @param mixed $defaultValue * @return mixed */ - protected function getFacetSettingOrDefaultValue($key, $defaultValue) + protected function getFacetSettingOrDefaultValue(string $key, $defaultValue) { if (!isset($this->configuration[$key])) { return $defaultValue; } - return ($this->configuration[$key]); + return $this->configuration[$key]; } } diff --git a/Classes/Domain/Search/ResultSet/Facets/AbstractFacetItem.php b/Classes/Domain/Search/ResultSet/Facets/AbstractFacetItem.php index 7e25f903dc..0390115b36 100644 --- a/Classes/Domain/Search/ResultSet/Facets/AbstractFacetItem.php +++ b/Classes/Domain/Search/ResultSet/Facets/AbstractFacetItem.php @@ -1,5 +1,7 @@ facet = $facet; $this->label = $label; $this->documentCount = $documentCount; @@ -69,15 +74,15 @@ public function __construct(AbstractFacet $facet, $label = '', $documentCount = /** * @return int */ - public function getDocumentCount() + public function getDocumentCount(): int { return $this->documentCount; } /** - * @return \ApacheSolrForTypo3\Solr\Domain\Search\ResultSet\Facets\AbstractFacet + * @return AbstractFacet */ - public function getFacet() + public function getFacet(): AbstractFacet { return $this->facet; } @@ -85,15 +90,15 @@ public function getFacet() /** * @return string */ - public function getLabel() + public function getLabel(): string { return $this->label; } /** - * @return boolean + * @return bool */ - public function getSelected() + public function getSelected(): bool { return $this->selected; } @@ -101,7 +106,7 @@ public function getSelected() /** * @return array */ - public function getMetrics() + public function getMetrics(): array { return $this->metrics; } @@ -109,10 +114,10 @@ public function getMetrics() /** * @return string */ - abstract public function getUriValue(); + abstract public function getUriValue(): string; /** * @return string */ - abstract function getCollectionKey(); + abstract public function getCollectionKey(): string; } diff --git a/Classes/Domain/Search/ResultSet/Facets/AbstractFacetItemCollection.php b/Classes/Domain/Search/ResultSet/Facets/AbstractFacetItemCollection.php index 5dde9a1763..8138c700d6 100644 --- a/Classes/Domain/Search/ResultSet/Facets/AbstractFacetItemCollection.php +++ b/Classes/Domain/Search/ResultSet/Facets/AbstractFacetItemCollection.php @@ -1,5 +1,7 @@ getFilteredCopy(function(AbstractFacetItem $item) { + return $this->getFilteredCopy(function (AbstractFacetItem $item) { return $item->getSelected(); }); } @@ -73,7 +74,7 @@ public function getSelected() * @param array $manualSorting * @return AbstractFacetItemCollection */ - public function getManualSortedCopy(array $manualSorting) + public function getManualSortedCopy(array $manualSorting): AbstractFacetItemCollection { $result = clone $this; $copiedItems = $result->data; @@ -94,7 +95,7 @@ public function getManualSortedCopy(array $manualSorting) /** * @return AbstractFacetItemCollection */ - public function getReversedOrderCopy() + public function getReversedOrderCopy(): AbstractFacetItemCollection { $result = clone $this; $result->data = array_reverse($result->data, true); diff --git a/Classes/Domain/Search/ResultSet/Facets/AbstractFacetPackage.php b/Classes/Domain/Search/ResultSet/Facets/AbstractFacetPackage.php index 65442a28a7..fdd6a6b176 100644 --- a/Classes/Domain/Search/ResultSet/Facets/AbstractFacetPackage.php +++ b/Classes/Domain/Search/ResultSet/Facets/AbstractFacetPackage.php @@ -1,5 +1,7 @@ objectManager->get($this->getParserClassName()); if (!$parser instanceof FacetParserInterface) { @@ -55,19 +58,20 @@ public function getParser() /** * @return string */ - public function getUrlDecoderClassName() { - return (string)DefaultUrlDecoder::class; + public function getUrlDecoderClassName(): string + { + return DefaultUrlDecoder::class; } /** * @throws InvalidUrlDecoderException * @return FacetUrlDecoderInterface */ - public function getUrlDecoder() + public function getUrlDecoder(): FacetUrlDecoderInterface { $urlDecoder = $this->objectManager->get($this->getUrlDecoderClassName()); if (!$urlDecoder instanceof FacetUrlDecoderInterface) { - throw new InvalidUrlDecoderException('Invalid urldecoder for package ' . __CLASS__); + throw new InvalidUrlDecoderException('Invalid url-decoder for package ' . __CLASS__); } return $urlDecoder; } @@ -75,19 +79,20 @@ public function getUrlDecoder() /** * @return string */ - public function getQueryBuilderClassName() { - return (string)DefaultFacetQueryBuilder::class; + public function getQueryBuilderClassName(): string + { + return DefaultFacetQueryBuilder::class; } /** * @throws InvalidQueryBuilderException * @return FacetQueryBuilderInterface */ - public function getQueryBuilder() + public function getQueryBuilder(): FacetQueryBuilderInterface { $urlDecoder = $this->objectManager->get($this->getQueryBuilderClassName()); - if(!$urlDecoder instanceof FacetQueryBuilderInterface) { - throw new InvalidQueryBuilderException('Invalid querybuilder for package ' . __CLASS__); + if (!$urlDecoder instanceof FacetQueryBuilderInterface) { + throw new InvalidQueryBuilderException('Invalid query-builder for package ' . __CLASS__); } return $urlDecoder; } diff --git a/Classes/Domain/Search/ResultSet/Facets/AbstractFacetParser.php b/Classes/Domain/Search/ResultSet/Facets/AbstractFacetParser.php index 2b82adf88c..4c7d36a5ff 100644 --- a/Classes/Domain/Search/ResultSet/Facets/AbstractFacetParser.php +++ b/Classes/Domain/Search/ResultSet/Facets/AbstractFacetParser.php @@ -1,5 +1,7 @@ getUsedSearchRequest()->getActiveFacetValuesByName($facetName); - $activeFacetValues = is_array($activeFacetValues) ? $activeFacetValues : []; - - return $activeFacetValues; + return is_array($activeFacetValues) ? $activeFacetValues : []; } - /** * @param array $facetValuesFromSolrResponse * @param array $facetValuesFromSearchRequest - * @return mixed + * @return array */ - protected function getMergedFacetValueFromSearchRequestAndSolrResponse($facetValuesFromSolrResponse, $facetValuesFromSearchRequest) - { + protected function getMergedFacetValueFromSearchRequestAndSolrResponse( + array $facetValuesFromSolrResponse, + array $facetValuesFromSearchRequest + ): array { $facetValueItemsToCreate = $facetValuesFromSolrResponse; foreach ($facetValuesFromSearchRequest as $valueFromRequest) { @@ -141,8 +145,10 @@ protected function getMergedFacetValueFromSearchRequestAndSolrResponse($facetVal * @param array $facetConfiguration * @return AbstractOptionsFacet */ - protected function applyManualSortOrder(AbstractOptionsFacet $facet, array $facetConfiguration) - { + protected function applyManualSortOrder( + AbstractOptionsFacet $facet, + array $facetConfiguration + ): AbstractOptionsFacet { if (!isset($facetConfiguration['manualSortOrder'])) { return $facet; } @@ -161,7 +167,7 @@ protected function applyManualSortOrder(AbstractOptionsFacet $facet, array $face * @param array $facetConfiguration * @return AbstractOptionsFacet */ - protected function applyReverseOrder(AbstractOptionsFacet $facet, array $facetConfiguration) + protected function applyReverseOrder(AbstractOptionsFacet $facet, array $facetConfiguration): AbstractOptionsFacet { if (empty($facetConfiguration['reverseOrder'])) { return $facet; @@ -176,9 +182,9 @@ protected function applyReverseOrder(AbstractOptionsFacet $facet, array $facetCo /** * @param mixed $value * @param array $facetConfiguration - * @return boolean + * @return bool */ - protected function getIsExcludedFacetValue($value, array $facetConfiguration) + protected function getIsExcludedFacetValue($value, array $facetConfiguration): bool { if (!isset($facetConfiguration['excludeValues'])) { return false; diff --git a/Classes/Domain/Search/ResultSet/Facets/DefaultFacetQueryBuilder.php b/Classes/Domain/Search/ResultSet/Facets/DefaultFacetQueryBuilder.php index 26bd20687a..882f66a1ed 100644 --- a/Classes/Domain/Search/ResultSet/Facets/DefaultFacetQueryBuilder.php +++ b/Classes/Domain/Search/ResultSet/Facets/DefaultFacetQueryBuilder.php @@ -1,5 +1,7 @@ getSearchFacetingFacetByName($facetName); @@ -46,7 +48,7 @@ public function build($facetName, TypoScriptConfiguration $configuration) * @param TypoScriptConfiguration $configuration * @return string */ - protected function buildExcludeTags(array $facetConfiguration, TypoScriptConfiguration $configuration) + protected function buildExcludeTags(array $facetConfiguration, TypoScriptConfiguration $configuration): string { // simple for now, may add overrides f..facet.* later if ($configuration->getSearchFacetingKeepAllFacetsOnSelection()) { @@ -56,7 +58,8 @@ protected function buildExcludeTags(array $facetConfiguration, TypoScriptConfigu } return '{!ex=' . implode(',', $facets) . '}'; - } elseif (($facetConfiguration['keepAllOptionsOnSelection'] ?? null) == 1) { + } + if (($facetConfiguration['keepAllOptionsOnSelection'] ?? null) == 1) { return '{!ex=' . $facetConfiguration['field'] . '}'; } diff --git a/Classes/Domain/Search/ResultSet/Facets/DefaultUrlDecoder.php b/Classes/Domain/Search/ResultSet/Facets/DefaultUrlDecoder.php index 3c217dcfc5..08c038bf5a 100644 --- a/Classes/Domain/Search/ResultSet/Facets/DefaultUrlDecoder.php +++ b/Classes/Domain/Search/ResultSet/Facets/DefaultUrlDecoder.php @@ -1,5 +1,7 @@ getFilteredCopy( - function(AbstractFacet $facet) { + function (AbstractFacet $facet) { return $facet->getIsUsed() && $facet->getIncludeInUsedFacets(); } ); } /** - * @return FacetCollection + * @return FacetCollection|AbstractCollection */ - public function getAvailable() + public function getAvailable(): AbstractCollection { return $this->getFilteredCopy( - function(AbstractFacet $facet) { + function (AbstractFacet $facet) { return $facet->getIsAvailable() && $facet->getIncludeInAvailableFacets() && $facet->getAllRequirementsMet(); } ); @@ -46,10 +60,10 @@ function(AbstractFacet $facet) { * @param string $requiredGroup * @return AbstractCollection */ - public function getByGroupName($requiredGroup = 'all') + public function getByGroupName(string $requiredGroup = 'all'): AbstractCollection { return $this->getFilteredCopy( - function(AbstractFacet $facet) use ($requiredGroup) { + function (AbstractFacet $facet) use ($requiredGroup) { return $facet->getGroupName() == $requiredGroup; } ); @@ -59,9 +73,10 @@ function(AbstractFacet $facet) use ($requiredGroup) { * @param string $requiredName * @return AbstractCollection */ - public function getByName($requiredName) { + public function getByName(string $requiredName): AbstractCollection + { return $this->getFilteredCopy( - function(AbstractFacet $facet) use ($requiredName) { + function (AbstractFacet $facet) use ($requiredName) { return $facet->getName() == $requiredName; } ); @@ -71,7 +86,7 @@ function(AbstractFacet $facet) use ($requiredName) { * @param int $position * @return AbstractFacet */ - public function getByPosition(int $position) + public function getByPosition(int $position): ?object { return parent::getByPosition($position); } diff --git a/Classes/Domain/Search/ResultSet/Facets/FacetParserInterface.php b/Classes/Domain/Search/ResultSet/Facets/FacetParserInterface.php index 3c6af41797..896a8e9094 100644 --- a/Classes/Domain/Search/ResultSet/Facets/FacetParserInterface.php +++ b/Classes/Domain/Search/ResultSet/Facets/FacetParserInterface.php @@ -31,5 +31,5 @@ interface FacetParserInterface * @param array $facetConfiguration * @return AbstractFacet|null */ - public function parse(SearchResultSet $resultSet, $facetName, array $facetConfiguration); + public function parse(SearchResultSet $resultSet, string $facetName, array $facetConfiguration): ?AbstractFacet; } diff --git a/Classes/Domain/Search/ResultSet/Facets/FacetQueryBuilderInterface.php b/Classes/Domain/Search/ResultSet/Facets/FacetQueryBuilderInterface.php index 2226531494..e4f5364c47 100644 --- a/Classes/Domain/Search/ResultSet/Facets/FacetQueryBuilderInterface.php +++ b/Classes/Domain/Search/ResultSet/Facets/FacetQueryBuilderInterface.php @@ -1,5 +1,7 @@ OptionsPackage::class, 'hierarchy' => HierarchyPackage::class, 'queryGroup' => QueryGroupPackage::class, @@ -48,14 +51,14 @@ class FacetRegistry extends AbstractClassRegistry * * @var string */ - protected $defaultClass = OptionsPackage::class; + protected string $defaultClass = OptionsPackage::class; /** * Get defaultParser * * @return string */ - public function getDefaultPackage() + public function getDefaultPackage(): string { return $this->defaultClass; } @@ -65,7 +68,7 @@ public function getDefaultPackage() * * @param string $defaultPackageClassName */ - public function setDefaultPackage($defaultPackageClassName) + public function setDefaultPackage(string $defaultPackageClassName) { $this->defaultClass = $defaultPackageClassName; } @@ -75,7 +78,7 @@ public function setDefaultPackage($defaultPackageClassName) * * @return array */ - public function getPackages() + public function getPackages(): array { return $this->classMap; } @@ -83,11 +86,11 @@ public function getPackages() /** * @param string $className * @param string $type - * @throws \InvalidArgumentException + * @throws InvalidArgumentException */ - public function registerPackage($className, $type) + public function registerPackage(string $className, string $type): void { - return $this->register($className, $type, AbstractFacetPackage::class); + $this->register($className, $type, AbstractFacetPackage::class); } /** @@ -97,7 +100,7 @@ public function registerPackage($className, $type) * @return AbstractFacetPackage * @throws InvalidFacetPackageException */ - public function getPackage($type) + public function getPackage(string $type): AbstractFacetPackage { $instance = $this->getInstance($type); if (!$instance instanceof AbstractFacetPackage) { diff --git a/Classes/Domain/Search/ResultSet/Facets/FacetUrlDecoderInterface.php b/Classes/Domain/Search/ResultSet/Facets/FacetUrlDecoderInterface.php index f37aea81ed..8cf4682605 100644 --- a/Classes/Domain/Search/ResultSet/Facets/FacetUrlDecoderInterface.php +++ b/Classes/Domain/Search/ResultSet/Facets/FacetUrlDecoderInterface.php @@ -1,5 +1,7 @@ value = $value; parent::__construct($facet, $label, $documentCount, $selected, $metrics); } @@ -48,7 +56,7 @@ public function __construct(AbstractFacet $facet, $label = '', $value = '', $doc /** * @return string */ - public function getValue() + public function getValue(): string { return $this->value; } @@ -56,7 +64,7 @@ public function getValue() /** * @return string */ - public function getUriValue() + public function getUriValue(): string { return $this->getValue(); } @@ -64,7 +72,7 @@ public function getUriValue() /** * @return string */ - public function getCollectionKey() + public function getCollectionKey(): string { return $this->getValue(); } diff --git a/Classes/Domain/Search/ResultSet/Facets/OptionBased/AbstractOptionsFacet.php b/Classes/Domain/Search/ResultSet/Facets/OptionBased/AbstractOptionsFacet.php index dcf102907b..42c14e389d 100644 --- a/Classes/Domain/Search/ResultSet/Facets/OptionBased/AbstractOptionsFacet.php +++ b/Classes/Domain/Search/ResultSet/Facets/OptionBased/AbstractOptionsFacet.php @@ -1,5 +1,7 @@ options = new OptionCollection(); } @@ -50,7 +57,7 @@ public function __construct(SearchResultSet $resultSet, $name, $field, $label = /** * @return OptionCollection */ - public function getOptions() + public function getOptions(): OptionCollection { return $this->options; } @@ -58,7 +65,7 @@ public function getOptions() /** * @param OptionCollection $options */ - public function setOptions($options) + public function setOptions(OptionCollection $options) { $this->options = $options; } @@ -76,7 +83,7 @@ public function addOption(AbstractOptionFacetItem $option) * * @return OptionCollection */ - public function getAllFacetItems() + public function getAllFacetItems(): AbstractFacetItemCollection { return $this->options; } @@ -86,7 +93,7 @@ public function getAllFacetItems() * * @return string */ - public function getPartialName() + public function getPartialName(): string { return !empty($this->configuration['partialName']) ? $this->configuration['partialName'] : 'Options'; } diff --git a/Classes/Domain/Search/ResultSet/Facets/OptionBased/Hierarchy/HierarchyFacet.php b/Classes/Domain/Search/ResultSet/Facets/OptionBased/Hierarchy/HierarchyFacet.php index 73ad514236..f558179ab7 100644 --- a/Classes/Domain/Search/ResultSet/Facets/OptionBased/Hierarchy/HierarchyFacet.php +++ b/Classes/Domain/Search/ResultSet/Facets/OptionBased/Hierarchy/HierarchyFacet.php @@ -18,9 +18,10 @@ use ApacheSolrForTypo3\Solr\Domain\Search\ResultSet\Facets\AbstractFacet; use ApacheSolrForTypo3\Solr\Domain\Search\ResultSet\Facets\AbstractFacetItemCollection; use ApacheSolrForTypo3\Solr\Domain\Search\ResultSet\SearchResultSet; +use TYPO3\CMS\Core\Utility\GeneralUtility; /** - * Value object that represent a options facet. + * Value object that represent the options facet. * * @author Frans Saris * @author Timo Hund @@ -33,22 +34,22 @@ class HierarchyFacet extends AbstractFacet * String * @var string */ - protected static $type = self::TYPE_HIERARCHY; + protected static string $type = self::TYPE_HIERARCHY; /** * @var NodeCollection */ - protected $childNodes; + protected NodeCollection $childNodes; /** * @var NodeCollection */ - protected $allNodes; + protected NodeCollection $allNodes; /** * @var array */ - protected $nodesByKey = []; + protected array $nodesByKey = []; /** * OptionsFacet constructor @@ -59,8 +60,13 @@ class HierarchyFacet extends AbstractFacet * @param string $label * @param array $configuration Facet configuration passed from typoscript */ - public function __construct(SearchResultSet $resultSet, $name, $field, $label = '', array $configuration = []) - { + public function __construct( + SearchResultSet $resultSet, + string $name, + string $field, + string $label = '', + array $configuration = [] + ) { parent::__construct($resultSet, $name, $field, $label, $configuration); $this->childNodes = new NodeCollection(); $this->allNodes = new NodeCollection(); @@ -77,7 +83,7 @@ public function addChildNode(Node $node) /** * @return NodeCollection */ - public function getChildNodes() + public function getChildNodes(): NodeCollection { return $this->childNodes; } @@ -85,19 +91,34 @@ public function getChildNodes() /** * Creates a new node on the right position with the right parent node. * - * @param string $parentKey + * @param string|null $parentKey * @param string $key * @param string $label * @param string $value - * @param integer $count - * @param boolean $selected + * @param int $count + * @param bool $selected */ - public function createNode($parentKey, $key, $label, $value, $count, $selected) - { - /** @var $parentNode Node|null */ - $parentNode = isset($this->nodesByKey[$parentKey]) ? $this->nodesByKey[$parentKey] : null; - /** @var Node $node */ - $node = $this->objectManager->get(Node::class, $this, $parentNode, $key, $label, $value, $count, $selected); + public function createNode( + ?string $parentKey, + string $key, + string $label, + string $value, + int $count, + bool $selected + ) { + /* @var $parentNode Node|null */ + $parentNode = $this->nodesByKey[$parentKey] ?? null; + /* @var Node $node */ + $node = GeneralUtility::makeInstance( + Node::class, + $this, + $parentNode, + $key, + $label, + $value, + $count, + $selected + ); $this->nodesByKey[$key] = $node; if ($parentNode === null) { @@ -114,7 +135,7 @@ public function createNode($parentKey, $key, $label, $value, $count, $selected) * * @return string */ - public function getPartialName() + public function getPartialName(): string { return !empty($this->configuration['partialName']) ? $this->configuration['partialName'] : 'Hierarchy'; } @@ -124,7 +145,7 @@ public function getPartialName() * * @return AbstractFacetItemCollection */ - public function getAllFacetItems() + public function getAllFacetItems(): AbstractFacetItemCollection { return $this->allNodes; } diff --git a/Classes/Domain/Search/ResultSet/Facets/OptionBased/Hierarchy/HierarchyFacetParser.php b/Classes/Domain/Search/ResultSet/Facets/OptionBased/Hierarchy/HierarchyFacetParser.php index c5aa79caff..ddaefa4220 100644 --- a/Classes/Domain/Search/ResultSet/Facets/OptionBased/Hierarchy/HierarchyFacetParser.php +++ b/Classes/Domain/Search/ResultSet/Facets/OptionBased/Hierarchy/HierarchyFacetParser.php @@ -1,5 +1,7 @@ getResponse(); $fieldName = $facetConfiguration['field']; @@ -85,12 +88,12 @@ public function parse(SearchResultSet $resultSet, $facetName, array $facetConfig * because lower nesting levels must be instantiated first, to serve as parents for higher nested levels. * See implementation of HierarchyFacet::createNode(). * - * @param array $flatOptionsListForFacet - * @return void sorted list of facet options + * @param array $flatOptionsListForHierarchyFacet + * @return array */ - protected function sortFacetOptionsInNaturalOrder(array $flatOptionsListForHierarchyFacet) + protected function sortFacetOptionsInNaturalOrder(array $flatOptionsListForHierarchyFacet): array { - uksort($flatOptionsListForHierarchyFacet, "strnatcmp"); + uksort($flatOptionsListForHierarchyFacet, 'strnatcmp'); return $flatOptionsListForHierarchyFacet; } @@ -108,7 +111,7 @@ protected function sortFacetOptionsInNaturalOrder(array $flatOptionsListForHiera * @param array $facetConfiguration * @return bool */ - protected function facetOptionsMustBeResorted(array $facetConfiguration) + protected function facetOptionsMustBeResorted(array $facetConfiguration): bool { if (isset($facetConfiguration['sortBy']) && $facetConfiguration['sortBy'] === 'index') { return true; @@ -124,12 +127,12 @@ protected function facetOptionsMustBeResorted(array $facetConfiguration) * @param string $path * @return array */ - protected function getPathAsArray($path) + protected function getPathAsArray(string $path): array { $path = str_replace('\/', '@@@', $path); - $path = rtrim($path, "/"); + $path = rtrim($path, '/'); $segments = explode('/', $path); - return array_map(function($item) { + return array_map(function ($item) { return str_replace('@@@', '/', $item); }, $segments); } @@ -140,7 +143,7 @@ protected function getPathAsArray($path) * @param string $facetName * @return array */ - protected function getActiveFacetValuesFromRequest(SearchResultSet $resultSet, $facetName) + protected function getActiveFacetValuesFromRequest(SearchResultSet $resultSet, string $facetName): array { $activeFacetValues = []; $values = $resultSet->getUsedSearchRequest()->getActiveFacetValuesByName($facetName); diff --git a/Classes/Domain/Search/ResultSet/Facets/OptionBased/Hierarchy/HierarchyPackage.php b/Classes/Domain/Search/ResultSet/Facets/OptionBased/Hierarchy/HierarchyPackage.php index a96668b9dc..89bb9eb9d2 100644 --- a/Classes/Domain/Search/ResultSet/Facets/OptionBased/Hierarchy/HierarchyPackage.php +++ b/Classes/Domain/Search/ResultSet/Facets/OptionBased/Hierarchy/HierarchyPackage.php @@ -1,5 +1,7 @@ getLabelPrefixes($length); return array_map('mb_strtolower', $prefixes); @@ -45,12 +46,12 @@ public function getLowercaseLabelPrefixes($length = 1) /** * @param string $filteredPrefix - * @return AbstractFacetItemCollection + * @return AbstractFacetItemCollection|OptionCollection */ - public function getByLowercaseLabelPrefix($filteredPrefix) + public function getByLowercaseLabelPrefix(string $filteredPrefix): OptionCollection { - return $this->getFilteredCopy(function(Option $option) use ($filteredPrefix) - { + /** @noinspection PhpIncompatibleReturnTypeInspection */ + return $this->getFilteredCopy(function (Option $option) use ($filteredPrefix) { $filteredPrefixLength = mb_strlen($filteredPrefix); $currentPrefix = mb_substr(mb_strtolower($option->getLabel()), 0, $filteredPrefixLength); @@ -62,7 +63,7 @@ public function getByLowercaseLabelPrefix($filteredPrefix) * @param int $length * @return array */ - protected function getLabelPrefixes($length = 1) : array + protected function getLabelPrefixes(int $length = 1): array { $prefixes = []; foreach ($this->data as $option) { diff --git a/Classes/Domain/Search/ResultSet/Facets/OptionBased/Options/Option.php b/Classes/Domain/Search/ResultSet/Facets/OptionBased/Options/Option.php index 96c8302647..22364b3aa0 100644 --- a/Classes/Domain/Search/ResultSet/Facets/OptionBased/Options/Option.php +++ b/Classes/Domain/Search/ResultSet/Facets/OptionBased/Options/Option.php @@ -1,5 +1,7 @@ getResponse(); $fieldName = $facetConfiguration['field']; @@ -63,7 +70,7 @@ public function parse(SearchResultSet $resultSet, $facetName, array $facetConfig } /** @var $facet OptionsFacet */ - $facet = $this->objectManager->get( + $facet = GeneralUtility::makeInstance( OptionsFacet::class, $resultSet, $facetName, @@ -84,7 +91,17 @@ public function parse(SearchResultSet $resultSet, $facetName, array $facetConfig $isOptionsActive = in_array($optionsValue, $optionsFromRequest); $label = $this->getLabelFromRenderingInstructions($optionsValue, $count, $facetName, $facetConfiguration); - $facet->addOption($this->objectManager->get(Option::class, $facet, $label, $optionsValue, $count, $isOptionsActive, ($metricsFromSolrResponse[$optionsValue] ?? null))); + $facet->addOption( + GeneralUtility::makeInstance( + Option::class, + $facet, + $label, + $optionsValue, + $count, + $isOptionsActive, + ($metricsFromSolrResponse[$optionsValue] ?? []) + ) + ); } // after all options have been created we apply a manualSortOrder if configured @@ -93,7 +110,7 @@ public function parse(SearchResultSet $resultSet, $facetName, array $facetConfig $this->applyManualSortOrder($facet, $facetConfiguration); $this->applyReverseOrder($facet, $facetConfiguration); - if(!is_null($this->dispatcher)) { + if (!is_null($this->dispatcher)) { $this->dispatcher->dispatch(__CLASS__, 'optionsParsed', [&$facet, $facetConfiguration]); } @@ -105,7 +122,7 @@ public function parse(SearchResultSet $resultSet, $facetName, array $facetConfig * @param ResponseAdapter $response * @return array */ - protected function getOptionsFromSolrResponse($facetName, ResponseAdapter $response) + protected function getOptionsFromSolrResponse(string $facetName, ResponseAdapter $response): array { $optionsFromSolrResponse = []; if (!isset($response->facets->{$facetName})) { @@ -126,7 +143,7 @@ protected function getOptionsFromSolrResponse($facetName, ResponseAdapter $respo * @param ResponseAdapter $response * @return array */ - protected function getMetricsFromSolrResponse($facetName, ResponseAdapter $response) + protected function getMetricsFromSolrResponse(string $facetName, ResponseAdapter $response): array { $metricsFromSolrResponse = []; diff --git a/Classes/Domain/Search/ResultSet/Facets/OptionBased/Options/OptionsFacetQueryBuilder.php b/Classes/Domain/Search/ResultSet/Facets/OptionBased/Options/OptionsFacetQueryBuilder.php index 7050f809d3..ed9d0c43cd 100644 --- a/Classes/Domain/Search/ResultSet/Facets/OptionBased/Options/OptionsFacetQueryBuilder.php +++ b/Classes/Domain/Search/ResultSet/Facets/OptionBased/Options/OptionsFacetQueryBuilder.php @@ -1,5 +1,7 @@ getSearchFacetingFacetByName($facetName); @@ -73,7 +75,7 @@ public function build($facetName, TypoScriptConfiguration $configuration) * @param TypoScriptConfiguration $configuration * @return string */ - protected function buildExcludeTagsForJson(array $facetConfiguration, TypoScriptConfiguration $configuration) + protected function buildExcludeTagsForJson(array $facetConfiguration, TypoScriptConfiguration $configuration): string { $excludeFields = []; @@ -115,7 +117,7 @@ protected function buildLimitForJson(array $facetConfiguration, TypoScriptConfig * @param TypoScriptConfiguration $configuration * @return int */ - protected function buildMincountForJson(array $facetConfiguration, TypoScriptConfiguration $configuration) + protected function buildMincountForJson(array $facetConfiguration, TypoScriptConfiguration $configuration): int { return $facetConfiguration['minimumCount'] ?? ($configuration->getSearchFacetingMinimumCount() ?? 1); } @@ -124,12 +126,13 @@ protected function buildMincountForJson(array $facetConfiguration, TypoScriptCon * @param array $facetConfiguration * @return string */ - protected function buildSortingForJson(array $facetConfiguration) { + protected function buildSortingForJson(array $facetConfiguration): string + { if (isset($facetConfiguration['sortBy'])) { $sortingExpression = new SortingExpression(); $sorting = $facetConfiguration['sortBy']; - $direction = $facetConfiguration['sortDirection'] ?? null; - return $sortingExpression->getForJsonFacet($sorting, $direction); + $direction = $facetConfiguration['sortDirection'] ?? ''; + return $sortingExpression->getForJsonFacet((string)$sorting, $direction); } return ''; } diff --git a/Classes/Domain/Search/ResultSet/Facets/OptionBased/Options/OptionsPackage.php b/Classes/Domain/Search/ResultSet/Facets/OptionBased/Options/OptionsPackage.php index efaf655ad0..0794409b21 100644 --- a/Classes/Domain/Search/ResultSet/Facets/OptionBased/Options/OptionsPackage.php +++ b/Classes/Domain/Search/ResultSet/Facets/OptionBased/Options/OptionsPackage.php @@ -1,5 +1,7 @@ getResponse(); $fieldName = $facetConfiguration['field']; @@ -85,7 +86,6 @@ public function parse(SearchResultSet $resultSet, $facetName, array $facetConfig } } - // after all options have been created we apply a manualSortOrder if configured // the sortBy (lex,..) is done by the solr server and triggered by the query, therefore it does not // need to be handled in the frontend. diff --git a/Classes/Domain/Search/ResultSet/Facets/OptionBased/QueryGroup/QueryGroupFacetQueryBuilder.php b/Classes/Domain/Search/ResultSet/Facets/OptionBased/QueryGroup/QueryGroupFacetQueryBuilder.php index 0721767394..029b2e1a64 100644 --- a/Classes/Domain/Search/ResultSet/Facets/OptionBased/QueryGroup/QueryGroupFacetQueryBuilder.php +++ b/Classes/Domain/Search/ResultSet/Facets/OptionBased/QueryGroup/QueryGroupFacetQueryBuilder.php @@ -1,5 +1,7 @@ getSearchFacetingFacetByName($facetName); diff --git a/Classes/Domain/Search/ResultSet/Facets/OptionBased/QueryGroup/QueryGroupPackage.php b/Classes/Domain/Search/ResultSet/Facets/OptionBased/QueryGroup/QueryGroupPackage.php index 0cf9314ca2..e98ba62a16 100644 --- a/Classes/Domain/Search/ResultSet/Facets/OptionBased/QueryGroup/QueryGroupPackage.php +++ b/Classes/Domain/Search/ResultSet/Facets/OptionBased/QueryGroup/QueryGroupPackage.php @@ -1,5 +1,7 @@ getRangeString(); } @@ -46,7 +48,7 @@ public function getUriValue() /** * @return string */ - public function getCollectionKey() + public function getCollectionKey(): string { return $this->getRangeString(); } @@ -54,7 +56,7 @@ public function getCollectionKey() /** * @return array */ - public function getRangeCounts() + public function getRangeCounts(): array { return $this->rangeCounts; } @@ -62,7 +64,7 @@ public function getRangeCounts() /** * @return string */ - public function getGap() + public function getGap(): string { return $this->gap; } @@ -70,5 +72,5 @@ public function getGap() /** * @return string */ - abstract protected function getRangeString(); + abstract protected function getRangeString(): string; } diff --git a/Classes/Domain/Search/ResultSet/Facets/RangeBased/AbstractRangeFacetParser.php b/Classes/Domain/Search/ResultSet/Facets/RangeBased/AbstractRangeFacetParser.php index 751dda3087..05b1714c41 100644 --- a/Classes/Domain/Search/ResultSet/Facets/RangeBased/AbstractRangeFacetParser.php +++ b/Classes/Domain/Search/ResultSet/Facets/RangeBased/AbstractRangeFacetParser.php @@ -1,5 +1,7 @@ getPlainLabelOrApplyCObject($facetConfiguration); $activeValue = $this->getActiveFacetValuesFromRequest($resultSet, $facetName); @@ -48,8 +58,8 @@ protected function getParsedFacet(SearchResultSet $resultSet, $facetName, array $valuesFromResponse = isset($response->facet_counts->facet_ranges->{$fieldName}) ? get_object_vars($response->facet_counts->facet_ranges->{$fieldName}) : []; - /** @var NumericRangeFacet|DateRangeFacet $facet */ - $facet = $this->objectManager->get( + /* @var NumericRangeFacet|DateRangeFacet $facet */ + $facet = GeneralUtility::makeInstance( $facetClass, $resultSet, $facetName, @@ -61,7 +71,7 @@ protected function getParsedFacet(SearchResultSet $resultSet, $facetName, array $facet->setIsAvailable(count($valuesFromResponse) > 0); $facet->setIsUsed(count($activeValue) > 0); - if (is_array($valuesFromResponse)) { + if (!empty($valuesFromResponse)) { $rangeCounts = []; $allCount = 0; @@ -69,7 +79,7 @@ protected function getParsedFacet(SearchResultSet $resultSet, $facetName, array foreach ($countsFromResponse as $rangeCountValue => $count) { $rangeCountValue = $this->parseResponseValue($rangeCountValue); - $rangeCount = $this->objectManager->get($facetRangeCountClass, $rangeCountValue, $count); + $rangeCount = GeneralUtility::makeInstance($facetRangeCountClass, $rangeCountValue, $count); $rangeCounts[] = $rangeCount; $allCount += $count; } @@ -88,10 +98,23 @@ protected function getParsedFacet(SearchResultSet $resultSet, $facetName, array $from = $this->parseRequestValue($rawFrom); $to = $this->parseRequestValue($rawTo); - $type = isset($facetConfiguration['type']) ? $facetConfiguration['type'] : 'numericRange'; - $gap = isset($facetConfiguration[$type . '.']['gap']) ? $facetConfiguration[$type . '.']['gap'] : 1; - - $range = $this->objectManager->get($facetItemClass, $facet, $from, $to, $fromInResponse, $toInResponse, $gap, $allCount, $rangeCounts, true); + $type = $facetConfiguration['type'] ?? 'numericRange'; + $gap = $facetConfiguration[$type . '.']['gap'] ?? 1; + + /* @var AbstractRangeFacetItem|NumericRangeFacet|DateRangeFacet $range */ + $range = GeneralUtility::makeInstance( + $facetItemClass, + $facet, + $from, + $to, + $fromInResponse, + $toInResponse, + $gap, + $allCount, + $rangeCounts, + true + ); + /* @noinspection PhpParamsInspection */ $facet->setRange($range); } @@ -99,14 +122,14 @@ protected function getParsedFacet(SearchResultSet $resultSet, $facetName, array } /** - * @param string $requestValue - * @return mixed + * @param float|int|string|null $rawRequestValue + * @return mixed|float|int|DateTime|null */ - abstract protected function parseRequestValue($requestValue); + abstract protected function parseRequestValue($rawRequestValue); /** - * @param string $responseValue - * @return mixed + * @param float|int|string|null $rawResponseValue + * @return mixed|float|int|DateTime|null */ - abstract protected function parseResponseValue($responseValue); + abstract protected function parseResponseValue($rawResponseValue); } diff --git a/Classes/Domain/Search/ResultSet/Facets/RangeBased/DateRange/DateRange.php b/Classes/Domain/Search/ResultSet/Facets/RangeBased/DateRange/DateRange.php index f9c58d97e2..2ac3e00d35 100644 --- a/Classes/Domain/Search/ResultSet/Facets/RangeBased/DateRange/DateRange.php +++ b/Classes/Domain/Search/ResultSet/Facets/RangeBased/DateRange/DateRange.php @@ -1,5 +1,7 @@ * @author Timo Hund @@ -27,24 +29,24 @@ class DateRange extends AbstractRangeFacetItem { /** - * @var DateTime + * @var DateTime|null */ - protected $startRequested; + protected ?DateTime $startRequested = null; /** - * @var DateTime + * @var DateTime|null */ - protected $endRequested; + protected ?DateTime $endRequested = null; /** - * @var DateTime + * @var DateTime|null */ - protected $startInResponse; + protected ?DateTime $startInResponse = null; /** - * @var DateTime + * @var DateTime|null */ - protected $endInResponse; + protected ?DateTime $endInResponse = null; /** * @param DateRangeFacet $facet @@ -52,13 +54,22 @@ class DateRange extends AbstractRangeFacetItem * @param DateTime|null $endRequested * @param DateTime|null $startInResponse * @param DateTime|null $endInResponse - * @param string $gap + * @param string|null $gap * @param int $documentCount * @param array $rangeCounts * @param bool $selected */ - public function __construct(DateRangeFacet $facet, DateTime $startRequested = null, DateTime $endRequested = null, DateTime $startInResponse = null, DateTime $endInResponse = null, $gap = '', $documentCount = 0, array $rangeCounts = null, $selected = false) - { + public function __construct( + DateRangeFacet $facet, + DateTime $startRequested = null, + DateTime $endRequested = null, + DateTime $startInResponse = null, + DateTime $endInResponse = null, + string $gap = '', + int $documentCount = 0, + array $rangeCounts = [], + bool $selected = false + ) { $this->startInResponse = $startInResponse; $this->endInResponse = $endInResponse; $this->startRequested = $startRequested; @@ -71,14 +82,13 @@ public function __construct(DateRangeFacet $facet, DateTime $startRequested = nu $label = $this->getRangeString(); } - parent::__construct($facet, $label, $documentCount, $selected); } /** * @return string */ - protected function getRangeString() + protected function getRangeString(): string { $from = null === $this->startRequested ? '' : $this->startRequested->format('Ymd') . '0000'; $till = null === $this->endRequested ? '' : $this->endRequested->format('Ymd') . '0000'; @@ -88,9 +98,9 @@ protected function getRangeString() /** * Retrieves the end date that was requested by the user for this facet. * - * @return \DateTime + * @return DateTime|null */ - public function getEndRequested() + public function getEndRequested(): ?DateTime { return $this->endRequested; } @@ -98,9 +108,9 @@ public function getEndRequested() /** * Retrieves the start date that was requested by the used for the facet. * - * @return \DateTime + * @return DateTime|null */ - public function getStartRequested() + public function getStartRequested(): ?DateTime { return $this->startRequested; } @@ -108,9 +118,9 @@ public function getStartRequested() /** * Retrieves the end date that was received from solr for this facet. * - * @return \DateTime + * @return DateTime|null */ - public function getEndInResponse() + public function getEndInResponse(): ?DateTime { return $this->endInResponse; } @@ -118,9 +128,9 @@ public function getEndInResponse() /** * Retrieves the start date that was received from solr for this facet. * - * @return \DateTime + * @return DateTime|null */ - public function getStartInResponse() + public function getStartInResponse(): ?DateTime { return $this->startInResponse; } diff --git a/Classes/Domain/Search/ResultSet/Facets/RangeBased/DateRange/DateRangeCollection.php b/Classes/Domain/Search/ResultSet/Facets/RangeBased/DateRange/DateRangeCollection.php index 01b41c302d..a972151d58 100644 --- a/Classes/Domain/Search/ResultSet/Facets/RangeBased/DateRange/DateRangeCollection.php +++ b/Classes/Domain/Search/ResultSet/Facets/RangeBased/DateRange/DateRangeCollection.php @@ -1,5 +1,7 @@ * @author Timo Hund */ class DateRangeCount { - /** * @var DateTime */ - protected $date; + protected DateTime $date; /** * @var int */ - protected $documentCount = 0; + protected int $documentCount = 0; /** - * @param $date - * @param $documentCount + * @param DateTime $date + * @param int $documentCount */ - public function __construct($date, $documentCount) + public function __construct(DateTime $date, int $documentCount = 0) { $this->date = $date; $this->documentCount = $documentCount; } /** - * @return \DateTime + * @return DateTime */ - public function getDate() + public function getDate(): DateTime { return $this->date; } @@ -57,7 +58,7 @@ public function getDate() /** * @return int */ - public function getDocumentCount() + public function getDocumentCount(): int { return $this->documentCount; } diff --git a/Classes/Domain/Search/ResultSet/Facets/RangeBased/DateRange/DateRangeFacet.php b/Classes/Domain/Search/ResultSet/Facets/RangeBased/DateRange/DateRangeFacet.php index 5c8027511e..945bfa0d71 100644 --- a/Classes/Domain/Search/ResultSet/Facets/RangeBased/DateRange/DateRangeFacet.php +++ b/Classes/Domain/Search/ResultSet/Facets/RangeBased/DateRange/DateRangeFacet.php @@ -1,5 +1,7 @@ range; } - /** * Get facet partial name used for rendering the facet * * @return string */ - public function getPartialName() + public function getPartialName(): string { return !empty($this->configuration['partialName']) ? $this->configuration['partialName'] : 'RangeDate.html'; } @@ -87,7 +93,7 @@ public function getPartialName() * * @return AbstractFacetItemCollection */ - public function getAllFacetItems() + public function getAllFacetItems(): AbstractFacetItemCollection { return new DateRangeCollection([$this->range]); } diff --git a/Classes/Domain/Search/ResultSet/Facets/RangeBased/DateRange/DateRangeFacetParser.php b/Classes/Domain/Search/ResultSet/Facets/RangeBased/DateRange/DateRangeFacetParser.php index a24ef07721..89b1ebb50c 100644 --- a/Classes/Domain/Search/ResultSet/Facets/RangeBased/DateRange/DateRangeFacetParser.php +++ b/Classes/Domain/Search/ResultSet/Facets/RangeBased/DateRange/DateRangeFacetParser.php @@ -1,5 +1,7 @@ getParsedFacet( $resultSet, @@ -62,26 +66,27 @@ public function parse(SearchResultSet $resultSet, $facetName, array $facetConfig } /** - * @param string $rawDate + * @param float|int|string|null $rawRequestValue * @return DateTime|null + * @throws Exception */ - protected function parseRequestValue($rawDate) + protected function parseRequestValue($rawRequestValue): ?DateTime { - $rawDate = \DateTime::createFromFormat('Ymd', substr($rawDate, 0, 8)); - if ($rawDate === false) { + $rawRequestValue = PhpDateTime::createFromFormat('Ymd', substr((string)$rawRequestValue, 0, 8)); + if ($rawRequestValue === false) { return null; } - $date = new DateTime($rawDate->format(DateTime::ISO8601)); - return $date; + return new DateTime($rawRequestValue->format(DateTime::ISO8601)); } /** - * @param string $isoDateString + * @param float|int|string|null $rawResponseValue * @return DateTime + * @throws Exception */ - protected function parseResponseValue($isoDateString) + protected function parseResponseValue($rawResponseValue): DateTime { - $rawDate = \DateTime::createFromFormat(\DateTime::ISO8601, $isoDateString); + $rawDate = PhpDateTime::createFromFormat(PhpDateTime::ISO8601, $rawResponseValue); return new DateTime($rawDate->format(DateTime::ISO8601)); } } diff --git a/Classes/Domain/Search/ResultSet/Facets/RangeBased/DateRange/DateRangeFacetQueryBuilder.php b/Classes/Domain/Search/ResultSet/Facets/RangeBased/DateRange/DateRangeFacetQueryBuilder.php index f6ba28634a..9e2c704b84 100644 --- a/Classes/Domain/Search/ResultSet/Facets/RangeBased/DateRange/DateRangeFacetQueryBuilder.php +++ b/Classes/Domain/Search/ResultSet/Facets/RangeBased/DateRange/DateRangeFacetQueryBuilder.php @@ -1,5 +1,7 @@ getSearchFacetingFacetByName($facetName); diff --git a/Classes/Domain/Search/ResultSet/Facets/RangeBased/DateRange/DateRangePackage.php b/Classes/Domain/Search/ResultSet/Facets/RangeBased/DateRange/DateRangePackage.php index 53a08539bc..8b80d47374 100644 --- a/Classes/Domain/Search/ResultSet/Facets/RangeBased/DateRange/DateRangePackage.php +++ b/Classes/Domain/Search/ResultSet/Facets/RangeBased/DateRange/DateRangePackage.php @@ -1,5 +1,7 @@ timestampToIso(strtotime($dateRangeStart)); } $toPart = '*'; - if($dateRangeEnd !== ''){ + if ($dateRangeEnd !== '') { $dateRangeEnd .= '59'; // adding 59 seconds $toPart = $formatService->timestampToIso(strtotime($dateRangeEnd)); } - $dateRangeFilter = '[' . $fromPart . ' TO ' . $toPart . ']'; - return $dateRangeFilter; + return '[' . $fromPart . ' TO ' . $toPart . ']'; } } diff --git a/Classes/Domain/Search/ResultSet/Facets/RangeBased/NumericRange/NumericRange.php b/Classes/Domain/Search/ResultSet/Facets/RangeBased/NumericRange/NumericRange.php index d0fe2e2488..3277b5037b 100644 --- a/Classes/Domain/Search/ResultSet/Facets/RangeBased/NumericRange/NumericRange.php +++ b/Classes/Domain/Search/ResultSet/Facets/RangeBased/NumericRange/NumericRange.php @@ -1,5 +1,7 @@ * @author Timo Hund @@ -26,24 +28,24 @@ class NumericRange extends AbstractRangeFacetItem { /** - * @var float + * @var float|null */ - protected $startRequested; + protected ?float $startRequested = null; /** - * @var float + * @var float|null */ - protected $endRequested; + protected ?float $endRequested = null; /** - * @var float + * @var float|null */ - protected $startInResponse; + protected ?float $startInResponse = null; /** - * @var float + * @var float|null */ - protected $endInResponse; + protected ?float $endInResponse = null; /** * @param NumericRangeFacet $facet @@ -53,11 +55,20 @@ class NumericRange extends AbstractRangeFacetItem * @param float|null $endInResponse * @param string $gap * @param int $documentCount - * @param array $rangeCounts + * @param array|null $rangeCounts * @param bool $selected */ - public function __construct(NumericRangeFacet $facet, $startRequested = null, $endRequested = null, $startInResponse = null, $endInResponse = null, $gap = '', $documentCount = 0, array $rangeCounts = null, $selected = false) - { + public function __construct( + NumericRangeFacet $facet, + ?float $startRequested = null, + ?float $endRequested = null, + ?float $startInResponse = null, + ?float $endInResponse = null, + string $gap = '', + int $documentCount = 0, + ?array $rangeCounts = [], + bool $selected = false + ) { $this->startInResponse = $startInResponse; $this->endInResponse = $endInResponse; $this->startRequested = $startRequested; @@ -70,14 +81,13 @@ public function __construct(NumericRangeFacet $facet, $startRequested = null, $e $label = $this->getRangeString(); } - parent::__construct($facet, $label, $documentCount, $selected); } /** * @return string */ - protected function getRangeString() + protected function getRangeString(): string { return $this->startRequested . '-' . $this->endRequested; } @@ -85,9 +95,9 @@ protected function getRangeString() /** * Retrieves the end date that was requested by the user for this facet. * - * @return float + * @return float|null */ - public function getEndRequested() + public function getEndRequested(): ?float { return $this->endRequested; } @@ -95,9 +105,9 @@ public function getEndRequested() /** * Retrieves the start date that was requested by the used for the facet. * - * @return float + * @return float|null */ - public function getStartRequested() + public function getStartRequested(): ?float { return $this->startRequested; } @@ -105,9 +115,9 @@ public function getStartRequested() /** * Retrieves the end date that was received from solr for this facet. * - * @return float + * @return float|null */ - public function getEndInResponse() + public function getEndInResponse(): ?float { return $this->endInResponse; } @@ -115,9 +125,9 @@ public function getEndInResponse() /** * Retrieves the start date that was received from solr for this facet. * - * @return float + * @return float|null */ - public function getStartInResponse() + public function getStartInResponse(): ?float { return $this->startInResponse; } diff --git a/Classes/Domain/Search/ResultSet/Facets/RangeBased/NumericRange/NumericRangeCollection.php b/Classes/Domain/Search/ResultSet/Facets/RangeBased/NumericRange/NumericRangeCollection.php index c2a74fd32d..0753a1a7ac 100644 --- a/Classes/Domain/Search/ResultSet/Facets/RangeBased/NumericRange/NumericRangeCollection.php +++ b/Classes/Domain/Search/ResultSet/Facets/RangeBased/NumericRange/NumericRangeCollection.php @@ -1,5 +1,7 @@ numericRange; } - /** * Get facet partial name used for rendering the facet * * @return string */ - public function getPartialName() + public function getPartialName(): string { return !empty($this->configuration['partialName']) ? $this->configuration['partialName'] : 'RangeNumeric.html'; } @@ -87,7 +93,7 @@ public function getPartialName() * * @return AbstractFacetItemCollection */ - public function getAllFacetItems() + public function getAllFacetItems(): AbstractFacetItemCollection { return new NumericRangeCollection([$this->numericRange]); } diff --git a/Classes/Domain/Search/ResultSet/Facets/RangeBased/NumericRange/NumericRangeFacetParser.php b/Classes/Domain/Search/ResultSet/Facets/RangeBased/NumericRange/NumericRangeFacetParser.php index 042281385a..edde55612a 100644 --- a/Classes/Domain/Search/ResultSet/Facets/RangeBased/NumericRange/NumericRangeFacetParser.php +++ b/Classes/Domain/Search/ResultSet/Facets/RangeBased/NumericRange/NumericRangeFacetParser.php @@ -1,5 +1,7 @@ getParsedFacet( $resultSet, @@ -59,21 +61,22 @@ public function parse(SearchResultSet $resultSet, $facetName, array $facetConfig $this->facetRangeCountClass ); } + /** - * @param mixed $rawValue - * @return mixed (numeric value) + * @param float|int|string|null $rawRequestValue + * @return float (numeric value) */ - protected function parseRequestValue($rawValue) + protected function parseRequestValue($rawRequestValue): float { - return is_numeric($rawValue) ? $rawValue : 0; + return is_numeric($rawRequestValue) ? (float)$rawRequestValue : 0.0; } /** - * @param $rawValue - * @return mixed (numeric value) + * @param float|int|string|null $rawResponseValue + * @return float (numeric value) */ - protected function parseResponseValue($rawValue) + protected function parseResponseValue($rawResponseValue): float { - return is_numeric($rawValue) ? $rawValue : 0; + return is_numeric($rawResponseValue) ? (float)$rawResponseValue : 0.0; } } diff --git a/Classes/Domain/Search/ResultSet/Facets/RangeBased/NumericRange/NumericRangeFacetQueryBuilder.php b/Classes/Domain/Search/ResultSet/Facets/RangeBased/NumericRange/NumericRangeFacetQueryBuilder.php index 70e3b9ffb9..7acbfacb34 100644 --- a/Classes/Domain/Search/ResultSet/Facets/RangeBased/NumericRange/NumericRangeFacetQueryBuilder.php +++ b/Classes/Domain/Search/ResultSet/Facets/RangeBased/NumericRange/NumericRangeFacetQueryBuilder.php @@ -1,5 +1,7 @@ getSearchFacetingFacetByName($facetName); $tag = ''; - if ($facetConfiguration['keepAllOptionsOnSelection'] == 1) { + if (true === (bool)($facetConfiguration['keepAllOptionsOnSelection'] ?? null)) { $tag = '{!ex=' . $facetConfiguration['field'] . '}'; } $facetParameters['facet.range'][] = $tag . $facetConfiguration['field']; diff --git a/Classes/Domain/Search/ResultSet/Facets/RangeBased/NumericRange/NumericRangePackage.php b/Classes/Domain/Search/ResultSet/Facets/RangeBased/NumericRange/NumericRangePackage.php index cff6399609..bd0a24df5d 100644 --- a/Classes/Domain/Search/ResultSet/Facets/RangeBased/NumericRange/NumericRangePackage.php +++ b/Classes/Domain/Search/ResultSet/Facets/RangeBased/NumericRange/NumericRangePackage.php @@ -1,5 +1,7 @@ getSelectedItemValues($facet, $requirement['facet']); $csvActiveFacetItemValues = implode(', ', $selectedItemValues); $requirementValues = GeneralUtility::trimExplode(',', $requirement['values']); @@ -110,9 +111,9 @@ protected function getSelectedItemValues(AbstractFacet $facet, $facetNameToCheck /** * Negates the result when configured. * - * @param boolean $value + * @param bool $value * @param array $configuration - * @return boolean + * @return bool */ protected function getNegationWhenConfigured($value, $configuration) { diff --git a/Classes/Domain/Search/ResultSet/Facets/SortingExpression.php b/Classes/Domain/Search/ResultSet/Facets/SortingExpression.php index 7bbbd63ab8..91a18666cf 100644 --- a/Classes/Domain/Search/ResultSet/Facets/SortingExpression.php +++ b/Classes/Domain/Search/ResultSet/Facets/SortingExpression.php @@ -1,5 +1,7 @@ getForFacet($sorting); diff --git a/Classes/Domain/Search/ResultSet/Facets/UrlFacetContainer.php b/Classes/Domain/Search/ResultSet/Facets/UrlFacetContainer.php index fbea555cac..ffee00b369 100644 --- a/Classes/Domain/Search/ResultSet/Facets/UrlFacetContainer.php +++ b/Classes/Domain/Search/ResultSet/Facets/UrlFacetContainer.php @@ -164,11 +164,11 @@ public function getActiveFacetNames(): array $facetNames = []; if ($this->parameterStyle === self::PARAMETER_STYLE_INDEX) { - array_map(function($activeFacet) use (&$facetNames) { + array_map(function ($activeFacet) use (&$facetNames) { $facetNames[] = substr($activeFacet, 0, strpos($activeFacet, ':')); }, $activeFacets); } else { - array_map(function($activeFacet) use (&$facetNames) { + array_map(function ($activeFacet) use (&$facetNames) { $facetNames[] = substr($activeFacet, 0, strpos($activeFacet, ':')); }, array_keys($activeFacets)); } @@ -188,7 +188,7 @@ public function getActiveFacetValuesByName(string $facetName): array if ($this->parameterStyle === self::PARAMETER_STYLE_ASSOC) { $activeFacets = array_keys($activeFacets); } - array_map(function($activeFacet) use (&$values, $facetName) { + array_map(function ($activeFacet) use (&$values, $facetName) { $parts = explode(':', $activeFacet, 2); if ($parts[0] === $facetName) { $values[] = $parts[1]; @@ -324,7 +324,7 @@ public function removeAllFacetValuesByName(string $facetName): UrlFacetContainer $filterOptions = ARRAY_FILTER_USE_KEY; } - $facetValues = array_filter($facetValues, function($facetNameValue) use ($facetName) { + $facetValues = array_filter($facetValues, function ($facetNameValue) use ($facetName) { $parts = explode(':', $facetNameValue, 2); return $parts[0] !== $facetName; }, $filterOptions); @@ -362,9 +362,8 @@ public function hasFacetValue(string $facetName, $facetValue): bool if ($this->parameterStyle === self::PARAMETER_STYLE_INDEX) { return in_array($facetNameAndValueToCheck, $this->getActiveFacets()); - } else { - return isset($facetValues[$facetNameAndValueToCheck]) && (int)$facetValues[$facetNameAndValueToCheck] === 1; } + return isset($facetValues[$facetNameAndValueToCheck]) && (int)$facetValues[$facetNameAndValueToCheck] === 1; } /** diff --git a/Classes/Domain/Search/ResultSet/Grouping/Group.php b/Classes/Domain/Search/ResultSet/Grouping/Group.php index f6e5549573..bff7f3ac02 100644 --- a/Classes/Domain/Search/ResultSet/Grouping/Group.php +++ b/Classes/Domain/Search/ResultSet/Grouping/Group.php @@ -1,5 +1,7 @@ data as $group) { - /** @var $group Group */ + /* @var Group $group */ if ($group->getGroupName() === $name) { return $group; } } - return null; } /** * @param string $name - * @return boolean + * @return bool */ - public function getHasWithName($name): bool + public function getHasWithName(string $name): bool { foreach ($this->data as $group) { - /** @var $group Group */ + /* @var Group $group */ if ($group->getGroupName() === $name) { return true; } @@ -61,10 +60,9 @@ public function getGroupNames(): array { $names = []; foreach ($this->data as $group) { - /** @var $group Group */ + /* @var Group $group */ $names[] = $group->getGroupName(); } - return $names; } diff --git a/Classes/Domain/Search/ResultSet/Grouping/GroupItemCollection.php b/Classes/Domain/Search/ResultSet/Grouping/GroupItemCollection.php index d7e29a2937..1906278bc8 100644 --- a/Classes/Domain/Search/ResultSet/Grouping/GroupItemCollection.php +++ b/Classes/Domain/Search/ResultSet/Grouping/GroupItemCollection.php @@ -1,5 +1,7 @@ searchResultBuilder = $resultBuilder ?? GeneralUtility::makeInstance(SearchResultBuilder::class); $this->documentEscapeService = $documentEscapeService ?? GeneralUtility::makeInstance(DocumentEscapeService::class); } @@ -52,11 +55,11 @@ public function __construct(SearchResultBuilder $resultBuilder = null, DocumentE * @param bool $useRawDocuments * @return SearchResultSet */ - abstract public function parse(SearchResultSet $resultSet, bool $useRawDocuments = true); + abstract public function parse(SearchResultSet $resultSet, bool $useRawDocuments = true): SearchResultSet; /** * @param SearchResultSet $resultSet - * @return mixed + * @return bool */ - abstract public function canParse(SearchResultSet $resultSet); + abstract public function canParse(SearchResultSet $resultSet): bool; } diff --git a/Classes/Domain/Search/ResultSet/Result/Parser/DefaultResultParser.php b/Classes/Domain/Search/ResultSet/Result/Parser/DefaultResultParser.php index 65c3b99b3c..64e29b3723 100644 --- a/Classes/Domain/Search/ResultSet/Result/Parser/DefaultResultParser.php +++ b/Classes/Domain/Search/ResultSet/Result/Parser/DefaultResultParser.php @@ -1,5 +1,7 @@ getResponse()->getParsedData(); @@ -64,12 +67,11 @@ public function parse(SearchResultSet $resultSet, bool $useRawDocuments = true) * @param SearchResultSet $resultSet * @return bool */ - public function canParse(SearchResultSet $resultSet) + public function canParse(SearchResultSet $resultSet): bool { - // This parsers should not be used when grouping is enabled + // These parsers should not be used when grouping is enabled $configuration = $resultSet->getUsedSearchRequest()->getContextTypoScriptConfiguration(); - if ($configuration instanceof TypoScriptConfiguration && $configuration->getSearchGrouping()) - { + if ($configuration instanceof TypoScriptConfiguration && $configuration->getIsSearchGroupingEnabled()) { return false; } diff --git a/Classes/Domain/Search/ResultSet/Result/Parser/DocumentEscapeService.php b/Classes/Domain/Search/ResultSet/Result/Parser/DocumentEscapeService.php index 682bf872c7..4df995849b 100644 --- a/Classes/Domain/Search/ResultSet/Result/Parser/DocumentEscapeService.php +++ b/Classes/Domain/Search/ResultSet/Result/Parser/DocumentEscapeService.php @@ -1,5 +1,7 @@ typoScriptConfiguration = $typoScriptConfiguration ?? Util::getSolrConfiguration(); } @@ -70,17 +74,17 @@ public function applyHtmlSpecialCharsOnAllFields(array $documents): array /** * Applies htmlspecialchars on all items of an array of a single value. * - * @param $fieldValue + * @param mixed $fieldValue * @return array|string */ protected function applyHtmlSpecialCharsOnSingleFieldValue($fieldValue) { if (is_array($fieldValue)) { foreach ($fieldValue as $key => $fieldValueItem) { - $fieldValue[$key] = htmlspecialchars($fieldValueItem, ENT_COMPAT, 'UTF-8', false); + $fieldValue[$key] = htmlspecialchars((string)$fieldValueItem, ENT_COMPAT, 'UTF-8', false); } } else { - $fieldValue = htmlspecialchars($fieldValue, ENT_COMPAT, 'UTF-8', false); + $fieldValue = htmlspecialchars((string)$fieldValue, ENT_COMPAT, 'UTF-8', false); } return $fieldValue; diff --git a/Classes/Domain/Search/ResultSet/Result/Parser/ResultParserRegistry.php b/Classes/Domain/Search/ResultSet/Result/Parser/ResultParserRegistry.php index e3f1064a19..3109abf8c5 100644 --- a/Classes/Domain/Search/ResultSet/Result/Parser/ResultParserRegistry.php +++ b/Classes/Domain/Search/ResultSet/Result/Parser/ResultParserRegistry.php @@ -1,5 +1,7 @@ DefaultResultParser::class, ]; /** - * @var AbstractResultParser[] + * @var AbstractResultParser[]|null */ - protected $parserInstances; + protected ?array $parserInstances = null; /** * Get registered parser classNames * * @return array */ - public function getParsers() + public function getParsers(): array { return $this->parsers; } @@ -56,34 +59,34 @@ public function getParsers() * * @param string $className classname of the parser that should be used * @param int $priority higher priority means more important - * @throws \InvalidArgumentException + * @throws InvalidArgumentException */ - public function registerParser($className, $priority) + public function registerParser(string $className, int $priority): void { // check if the class is available for TYPO3 before registering the driver if (!class_exists($className)) { - throw new \InvalidArgumentException('Class ' . $className . ' does not exist.', 1468863997); + throw new InvalidArgumentException('Class ' . $className . ' does not exist.', 1468863997); } if (!is_subclass_of($className, AbstractResultParser::class)) { - throw new \InvalidArgumentException('Parser ' . $className . ' needs to implement the AbstractResultParser.', 1468863998); + throw new InvalidArgumentException('Parser ' . $className . ' needs to implement the AbstractResultParser.', 1468863998); } - if (array_key_exists((int)$priority, $this->parsers)) { - throw new \InvalidArgumentException('There is already a parser registerd with priority ' . (int)$priority . '.', 1468863999); + if (array_key_exists($priority, $this->parsers)) { + throw new InvalidArgumentException('There is already a parser registered with priority ' . $priority . '.', 1468863999); } - $this->parsers[(int)$priority] = $className; + $this->parsers[$priority] = $className; } /** - * Method to check if a certain parser is allready registered + * Method to check if a certain parser is already registered * * @param string $className * @param int $priority - * @return boolean + * @return bool */ - public function hasParser($className, $priority) + public function hasParser(string $className, int $priority): bool { if (empty($this->parsers[$priority])) { return false; @@ -95,7 +98,7 @@ public function hasParser($className, $priority) /** * @return AbstractResultParser[] */ - public function getParserInstances() + public function getParserInstances(): ?array { if ($this->parserInstances === null) { ksort($this->parsers); @@ -111,9 +114,9 @@ public function getParserInstances() * @param SearchResultSet $resultSet * @return AbstractResultParser|null */ - public function getParser(SearchResultSet $resultSet) + public function getParser(SearchResultSet $resultSet): ?AbstractResultParser { - /** @var AbstractResultParser $parser */ + /* @var AbstractResultParser $parser */ foreach ($this->getParserInstances() as $parser) { if ($parser->canParse($resultSet)) { return $parser; @@ -125,9 +128,11 @@ public function getParser(SearchResultSet $resultSet) /** * Create an instance of a certain parser class * + * @param string $className * @return AbstractResultParser + * @noinspection PhpIncompatibleReturnTypeInspection */ - protected function createParserInstance($className) + protected function createParserInstance(string $className): AbstractResultParser { return GeneralUtility::makeInstance($className); } diff --git a/Classes/Domain/Search/ResultSet/Result/SearchResult.php b/Classes/Domain/Search/ResultSet/Result/SearchResult.php index 9371da1cda..f5e84ef6c6 100644 --- a/Classes/Domain/Search/ResultSet/Result/SearchResult.php +++ b/Classes/Domain/Search/ResultSet/Result/SearchResult.php @@ -1,5 +1,7 @@ groupItem !== null; } @@ -129,7 +130,7 @@ public function setVariantsNumFound(int $numFound) /** * @return SearchResult[] */ - public function getVariants() + public function getVariants(): array { return $this->variants; } @@ -145,7 +146,7 @@ public function addVariant(SearchResult $expandedResult) /** * @return bool */ - public function getIsVariant() + public function getIsVariant(): bool { return $this->isVariant; } @@ -153,15 +154,15 @@ public function getIsVariant() /** * @param bool $isVariant */ - public function setIsVariant($isVariant) + public function setIsVariant(bool $isVariant) { $this->isVariant = $isVariant; } /** - * @return SearchResult + * @return SearchResult|null */ - public function getVariantParent() + public function getVariantParent(): ?SearchResult { return $this->variantParent; } @@ -177,15 +178,15 @@ public function setVariantParent(SearchResult $variantParent) /** * @return string */ - public function getContent() + public function getContent(): string { return $this->fields['content'] ?? ''; } /** - * @return boolean + * @return bool */ - public function getIsElevated() + public function getIsElevated(): bool { return $this->fields['isElevated'] ?? false; } @@ -193,31 +194,32 @@ public function getIsElevated() /** * @return string */ - public function getType() + public function getType(): string { return $this->fields['type'] ?? ''; } /** - * @return integer + * @return string + * Note: The id field on Apache Solr document is a string. */ - public function getId() + public function getId(): string { - return $this->fields['id'] ?? 0; + return $this->fields['id'] ?? ''; } /** * @return float */ - public function getScore() + public function getScore(): float { - return $this->fields['score'] ?? 0; + return $this->fields['score'] ?? 0.0; } /** * @return string */ - public function getUrl() + public function getUrl(): string { return $this->fields['url'] ?? ''; } @@ -225,7 +227,7 @@ public function getUrl() /** * @return string */ - public function getTitle() + public function getTitle(): string { return $this->fields['title'] ?? ''; } diff --git a/Classes/Domain/Search/ResultSet/Result/SearchResultBuilder.php b/Classes/Domain/Search/ResultSet/Result/SearchResultBuilder.php index 8ebcfbf362..e722370cc7 100644 --- a/Classes/Domain/Search/ResultSet/Result/SearchResultBuilder.php +++ b/Classes/Domain/Search/ResultSet/Result/SearchResultBuilder.php @@ -1,5 +1,7 @@ getResultClassName(); $result = GeneralUtility::makeInstance($searchResultClassName, /** @scrutinizer ignore-type */ $originalDocument->getFields() ?? []); if (!$result instanceof SearchResult) { - throw new \InvalidArgumentException('Could not create result object with class: ' . (string)$searchResultClassName, 1470037679); + throw new InvalidArgumentException('Could not create result object with class: ' . $searchResultClassName, 1470037679); } return $result; @@ -48,9 +50,8 @@ public function fromApacheSolrDocument(Document $originalDocument) /** * @return string */ - protected function getResultClassName() + protected function getResultClassName(): string { - return isset($GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['solr']['searchResultClassName ']) ? - $GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['solr']['searchResultClassName '] : SearchResult::class; + return $GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['solr']['searchResultClassName '] ?? SearchResult::class; } } diff --git a/Classes/Domain/Search/ResultSet/Result/SearchResultCollection.php b/Classes/Domain/Search/ResultSet/Result/SearchResultCollection.php index f4b14c40db..e7202a1f1d 100644 --- a/Classes/Domain/Search/ResultSet/Result/SearchResultCollection.php +++ b/Classes/Domain/Search/ResultSet/Result/SearchResultCollection.php @@ -1,5 +1,7 @@ objectManager === null) { $this->objectManager = GeneralUtility::makeInstance(ObjectManager::class); @@ -52,17 +55,18 @@ public function getObjectManager() /** * @param ObjectManagerInterface $objectManager + * Purpose: PhpUnit + * @todo: Replace with proper DI */ - public function setObjectManager($objectManager) + public function setObjectManager(ObjectManagerInterface $objectManager) { $this->objectManager = $objectManager; } - /** * @return FacetRegistry */ - protected function getFacetRegistry() + protected function getFacetRegistry(): FacetRegistry { // @extensionScannerIgnoreLine return $this->getObjectManager()->get(FacetRegistry::class); @@ -74,27 +78,22 @@ protected function getFacetRegistry() * * @param SearchResultSet $resultSet * @return SearchResultSet + * @throws InvalidFacetPackageException */ - public function process(SearchResultSet $resultSet) + public function process(SearchResultSet $resultSet): SearchResultSet { - if (!$resultSet instanceof SearchResultSet) { - return $resultSet; - } - $resultSet = $this->parseSpellCheckingResponseIntoObjects($resultSet); $resultSet = $this->parseSortingIntoObjects($resultSet); // here we can reconstitute other domain objects from the solr response - $resultSet = $this->parseFacetsIntoObjects($resultSet); - - return $resultSet; + return $this->parseFacetsIntoObjects($resultSet); } /** * @param SearchResultSet $resultSet * @return SearchResultSet */ - protected function parseSortingIntoObjects(SearchResultSet $resultSet) + protected function parseSortingIntoObjects(SearchResultSet $resultSet): SearchResultSet { $configuration = $resultSet->getUsedSearchRequest()->getContextTypoScriptConfiguration(); $hasSorting = $resultSet->getUsedSearchRequest()->getHasSorting(); @@ -138,7 +137,17 @@ protected function parseSortingIntoObjects(SearchResultSet $resultSet) $selected = true; } - $sorting = $this->getObjectManager()->get(Sorting::class, $resultSet, $sortingName, $field, $direction, $label, $selected, $isResetOption); + /** @noinspection PhpParamsInspection */ + $sorting = $this->getObjectManager()->get( + Sorting::class, + $resultSet, + $sortingName, + $field, + $direction, + $label, + $selected, + $isResetOption + ); $resultSet->addSorting($sorting); } @@ -149,7 +158,7 @@ protected function parseSortingIntoObjects(SearchResultSet $resultSet) * @param SearchResultSet $resultSet * @return SearchResultSet */ - private function parseSpellCheckingResponseIntoObjects(SearchResultSet $resultSet) + private function parseSpellCheckingResponseIntoObjects(SearchResultSet $resultSet): SearchResultSet { //read the response $response = $resultSet->getResponse(); @@ -166,7 +175,7 @@ private function parseSpellCheckingResponseIntoObjects(SearchResultSet $resultSe } if ($misspelledTerm === '') { - throw new \UnexpectedValueException('No missspelled term before suggestion'); + throw new UnexpectedValueException('No misspelled term before suggestion'); } if (!is_object($suggestionData) && !is_array($suggestionData->suggestion)) { @@ -178,28 +187,29 @@ private function parseSpellCheckingResponseIntoObjects(SearchResultSet $resultSe //add it to the resultSet $resultSet->addSpellCheckingSuggestion($suggestion); } - } return $resultSet; } /** - * @param \stdClass $suggestionData + * @param stdClass $suggestionData * @param string $suggestedTerm * @param string $misspelledTerm * @return Suggestion */ - private function createSuggestionFromResponseFragment($suggestionData, $suggestedTerm, $misspelledTerm) - { - $numFound = isset($suggestionData->numFound) ? $suggestionData->numFound : 0; - $startOffset = isset($suggestionData->startOffset) ? $suggestionData->startOffset : 0; - $endOffset = isset($suggestionData->endOffset) ? $suggestionData->endOffset : 0; + private function createSuggestionFromResponseFragment( + stdClass $suggestionData, + string $suggestedTerm, + string $misspelledTerm + ): Suggestion { + $numFound = $suggestionData->numFound ?? 0; + $startOffset = $suggestionData->startOffset ?? 0; + $endOffset = $suggestionData->endOffset ?? 0; // by now we avoid to use GeneralUtility::makeInstance, since we only create a value object - // and the usage might be a overhead. - $suggestion = new Suggestion($suggestedTerm, $misspelledTerm, $numFound, $startOffset, $endOffset); - return $suggestion; + // and the usage might be an overhead. + return new Suggestion($suggestedTerm, $misspelledTerm, $numFound, $startOffset, $endOffset); } /** @@ -207,8 +217,9 @@ private function createSuggestionFromResponseFragment($suggestionData, $suggeste * * @param SearchResultSet $resultSet * @return SearchResultSet + * @throws InvalidFacetPackageException */ - private function parseFacetsIntoObjects(SearchResultSet $resultSet) + private function parseFacetsIntoObjects(SearchResultSet $resultSet): SearchResultSet { // Make sure we can access the facet configuration if (!$resultSet->getUsedSearchRequest() || !$resultSet->getUsedSearchRequest()->getContextTypoScriptConfiguration()) { @@ -221,7 +232,6 @@ private function parseFacetsIntoObjects(SearchResultSet $resultSet) return $resultSet; } - /** @var FacetRegistry $facetRegistry */ $facetRegistry = $this->getFacetRegistry(); $facetsConfiguration = $resultSet->getUsedSearchRequest()->getContextTypoScriptConfiguration()->getSearchFacetingFacets(); @@ -261,7 +271,7 @@ protected function applyRequirements(SearchResultSet $resultSet) /** * @return RequirementsService */ - protected function getRequirementsService() + protected function getRequirementsService(): RequirementsService { // @extensionScannerIgnoreLine return $this->getObjectManager()->get(RequirementsService::class); diff --git a/Classes/Domain/Search/ResultSet/SearchResultSet.php b/Classes/Domain/Search/ResultSet/SearchResultSet.php index 657ecfe730..05b0915311 100644 --- a/Classes/Domain/Search/ResultSet/SearchResultSet.php +++ b/Classes/Domain/Search/ResultSet/SearchResultSet.php @@ -1,5 +1,7 @@ */ class SearchResultSet { - /** - * @var Query + * @var Query|null */ - protected $usedQuery = null; + protected ?Query $usedQuery = null; /** - * @var SearchRequest + * @var SearchRequest|null */ - protected $usedSearchRequest = null; + protected ?SearchRequest $usedSearchRequest = null; /** - * @var Search + * @var Search|null */ - protected $usedSearch; + protected ?Search $usedSearch = null; /** * @var ResponseAdapter */ - protected $response = null; + protected ResponseAdapter $response; /** * @var int */ - protected $usedPage = 0; + protected int $usedPage = 0; /** * @var int */ - protected $usedResultsPerPage = 0; + protected int $usedResultsPerPage = 0; /** * @var array */ - protected $usedAdditionalFilters = []; + protected array $usedAdditionalFilters = []; /** * @var SearchResultCollection */ - protected $searchResults = null; + protected SearchResultCollection $searchResults; /** * @var int */ - protected $allResultCount = 0; + protected int $allResultCount = 0; /** * @var float */ - protected $maximumScore = 0.0; + protected float $maximumScore = 0.0; /** * @var Suggestion[] */ - protected $spellCheckingSuggestions = []; + protected array $spellCheckingSuggestions = []; /** * @var FacetCollection */ - protected $facets = null; + protected FacetCollection $facets; /** * @var SortingCollection */ - protected $sortings = null; + protected SortingCollection $sortings; /** * @var bool */ - protected $isAutoCorrected = false; + protected bool $isAutoCorrected = false; /** * @var string */ - protected $initialQueryString = ''; + protected string $initialQueryString = ''; /** * @var string */ - protected $correctedQueryString = ''; + protected string $correctedQueryString = ''; /** * @var bool */ - protected $hasSearched = false; + protected bool $hasSearched = false; /** - * @return \ApacheSolrForTypo3\Solr\Domain\Search\ResultSet\SearchResultSet + * Constructor for SearchResultSet */ public function __construct() { @@ -134,7 +135,7 @@ public function __construct() /** * @param int $allResultCount */ - public function setAllResultCount($allResultCount) + public function setAllResultCount(int $allResultCount) { $this->allResultCount = $allResultCount; } @@ -142,7 +143,7 @@ public function setAllResultCount($allResultCount) /** * @return int */ - public function getAllResultCount() + public function getAllResultCount(): int { return $this->allResultCount; } @@ -158,23 +159,23 @@ public function addSpellCheckingSuggestion(Suggestion $suggestion) /** * @return bool */ - public function getHasSpellCheckingSuggestions() + public function getHasSpellCheckingSuggestions(): bool { return count($this->spellCheckingSuggestions) > 0; } /** - * @param \ApacheSolrForTypo3\Solr\Domain\Search\ResultSet\Spellchecking\Suggestion[] $spellCheckingSuggestions + * @param Suggestion[] $spellCheckingSuggestions */ - public function setSpellCheckingSuggestions($spellCheckingSuggestions) + public function setSpellCheckingSuggestions(array $spellCheckingSuggestions) { $this->spellCheckingSuggestions = $spellCheckingSuggestions; } /** - * @return \ApacheSolrForTypo3\Solr\Domain\Search\ResultSet\Spellchecking\Suggestion[] + * @return Suggestion[] */ - public function getSpellCheckingSuggestions() + public function getSpellCheckingSuggestions(): array { return $this->spellCheckingSuggestions; } @@ -182,7 +183,7 @@ public function getSpellCheckingSuggestions() /** * @return FacetCollection */ - public function getFacets() + public function getFacets(): FacetCollection { return $this->facets; } @@ -198,7 +199,7 @@ public function addFacet(AbstractFacet $facet) /** * @return float */ - public function getMaximumScore() + public function getMaximumScore(): float { return $this->maximumScore; } @@ -206,7 +207,7 @@ public function getMaximumScore() /** * @param float $maximumScore */ - public function setMaximumScore($maximumScore) + public function setMaximumScore(float $maximumScore) { $this->maximumScore = $maximumScore; } @@ -222,7 +223,7 @@ public function addSorting(Sorting $sorting) /** * @return SortingCollection */ - public function getSortings() + public function getSortings(): SortingCollection { return $this->sortings; } @@ -230,7 +231,7 @@ public function getSortings() /** * @param ResponseAdapter $response */ - public function setResponse($response) + public function setResponse(ResponseAdapter $response) { $this->response = $response; } @@ -238,7 +239,7 @@ public function setResponse($response) /** * @return ResponseAdapter */ - public function getResponse() + public function getResponse(): ResponseAdapter { return $this->response; } @@ -246,7 +247,7 @@ public function getResponse() /** * @param array $usedAdditionalFilters */ - public function setUsedAdditionalFilters($usedAdditionalFilters) + public function setUsedAdditionalFilters(array $usedAdditionalFilters) { $this->usedAdditionalFilters = $usedAdditionalFilters; } @@ -254,7 +255,7 @@ public function setUsedAdditionalFilters($usedAdditionalFilters) /** * @return array */ - public function getUsedAdditionalFilters() + public function getUsedAdditionalFilters(): array { return $this->usedAdditionalFilters; } @@ -262,7 +263,7 @@ public function getUsedAdditionalFilters() /** * @param Query $usedQuery */ - public function setUsedQuery($usedQuery) + public function setUsedQuery(Query $usedQuery) { $this->usedQuery = $usedQuery; } @@ -272,7 +273,7 @@ public function setUsedQuery($usedQuery) * * @return Query */ - public function getUsedQuery() + public function getUsedQuery(): ?Query { return $this->usedQuery; } @@ -280,7 +281,7 @@ public function getUsedQuery() /** * @param int $page */ - public function setUsedPage($page) + public function setUsedPage(int $page) { $this->usedPage = $page; } @@ -290,15 +291,15 @@ public function setUsedPage($page) * * @return int */ - public function getUsedPage() + public function getUsedPage(): int { return $this->usedPage; } /** - * @param \ApacheSolrForTypo3\Solr\Domain\Search\SearchRequest $usedSearchRequest + * @param SearchRequest $usedSearchRequest */ - public function setUsedSearchRequest($usedSearchRequest) + public function setUsedSearchRequest(SearchRequest $usedSearchRequest) { $this->usedSearchRequest = $usedSearchRequest; } @@ -306,25 +307,25 @@ public function setUsedSearchRequest($usedSearchRequest) /** * Retrieves the SearchRequest that has been used to build this SearchResultSet. * - * @return \ApacheSolrForTypo3\Solr\Domain\Search\SearchRequest + * @return SearchRequest */ - public function getUsedSearchRequest() + public function getUsedSearchRequest(): ?SearchRequest { return $this->usedSearchRequest; } /** - * @param \ApacheSolrForTypo3\Solr\Search $usedSearch + * @param Search $usedSearch */ - public function setUsedSearch($usedSearch) + public function setUsedSearch(Search $usedSearch) { $this->usedSearch = $usedSearch; } /** - * @return \ApacheSolrForTypo3\Solr\Search + * @return Search */ - public function getUsedSearch() + public function getUsedSearch(): ?Search { return $this->usedSearch; } @@ -332,7 +333,7 @@ public function getUsedSearch() /** * @param int $usedResultsPerPage */ - public function setUsedResultsPerPage($usedResultsPerPage) + public function setUsedResultsPerPage(int $usedResultsPerPage) { $this->usedResultsPerPage = $usedResultsPerPage; } @@ -340,7 +341,7 @@ public function setUsedResultsPerPage($usedResultsPerPage) /** * @return int */ - public function getUsedResultsPerPage() + public function getUsedResultsPerPage(): int { return $this->usedResultsPerPage; } @@ -348,7 +349,7 @@ public function getUsedResultsPerPage() /** * @return SearchResultCollection */ - public function getSearchResults() + public function getSearchResults(): SearchResultCollection { return $this->searchResults; } @@ -356,7 +357,7 @@ public function getSearchResults() /** * @param SearchResultCollection $searchResults */ - public function setSearchResults($searchResults) + public function setSearchResults(SearchResultCollection $searchResults) { $this->searchResults = $searchResults; } @@ -370,17 +371,17 @@ public function addSearchResult(SearchResult $searchResult) } /** - * @return boolean + * @return bool */ - public function getIsAutoCorrected() + public function getIsAutoCorrected(): bool { return $this->isAutoCorrected; } /** - * @param boolean $wasAutoCorrected + * @param bool $wasAutoCorrected */ - public function setIsAutoCorrected($wasAutoCorrected) + public function setIsAutoCorrected(bool $wasAutoCorrected) { $this->isAutoCorrected = $wasAutoCorrected; } @@ -388,7 +389,7 @@ public function setIsAutoCorrected($wasAutoCorrected) /** * @return string */ - public function getInitialQueryString() + public function getInitialQueryString(): string { return $this->initialQueryString; } @@ -396,7 +397,7 @@ public function getInitialQueryString() /** * @param string $initialQueryString */ - public function setInitialQueryString($initialQueryString) + public function setInitialQueryString(string $initialQueryString) { $this->initialQueryString = $initialQueryString; } @@ -404,7 +405,7 @@ public function setInitialQueryString($initialQueryString) /** * @return string */ - public function getCorrectedQueryString() + public function getCorrectedQueryString(): string { return $this->correctedQueryString; } @@ -412,13 +413,13 @@ public function getCorrectedQueryString() /** * @param string $correctedQueryString */ - public function setCorrectedQueryString($correctedQueryString) + public function setCorrectedQueryString(string $correctedQueryString) { $this->correctedQueryString = $correctedQueryString; } /** - * @return boolean + * @return bool */ public function getHasSearched(): bool { @@ -426,7 +427,7 @@ public function getHasSearched(): bool } /** - * @param boolean $hasSearched + * @param bool $hasSearched */ public function setHasSearched(bool $hasSearched) { diff --git a/Classes/Domain/Search/ResultSet/SearchResultSetProcessor.php b/Classes/Domain/Search/ResultSet/SearchResultSetProcessor.php index 78da3f1177..01bd472248 100644 --- a/Classes/Domain/Search/ResultSet/SearchResultSetProcessor.php +++ b/Classes/Domain/Search/ResultSet/SearchResultSetProcessor.php @@ -30,5 +30,5 @@ interface SearchResultSetProcessor * @param SearchResultSet $resultSet * @return mixed */ - public function process(SearchResultSet $resultSet); + public function process(SearchResultSet $resultSet): SearchResultSet; } diff --git a/Classes/Domain/Search/ResultSet/SearchResultSetService.php b/Classes/Domain/Search/ResultSet/SearchResultSetService.php index 80a5d9d0a6..785eb32784 100644 --- a/Classes/Domain/Search/ResultSet/SearchResultSetService.php +++ b/Classes/Domain/Search/ResultSet/SearchResultSetService.php @@ -1,5 +1,7 @@ search = $search; $this->typoScriptConfiguration = $configuration; $this->logger = $solrLogManager ?? GeneralUtility::makeInstance(SolrLogManager::class, /** @scrutinizer ignore-type */ __CLASS__); @@ -123,8 +130,9 @@ public function injectObjectManager(ObjectManagerInterface $objectManager) /** * @param bool $useCache * @return bool + * @throws Exception */ - public function getIsSolrAvailable($useCache = true) + public function getIsSolrAvailable(bool $useCache = true): bool { $this->isSolrAvailable = $this->search->ping($useCache); return $this->isSolrAvailable; @@ -135,7 +143,7 @@ public function getIsSolrAvailable($useCache = true) * * @return Search */ - public function getSearch() + public function getSearch(): Search { return $this->search; } @@ -167,10 +175,9 @@ protected function initializeRegisteredSearchComponents(Query $query, SearchRequ /** * @return string */ - protected function getResultSetClassName() + protected function getResultSetClassName(): string { - return isset($GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['solr']['searchResultSetClassName ']) ? - $GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['solr']['searchResultSetClassName '] : SearchResultSet::class; + return $GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['solr']['searchResultSetClassName '] ?? SearchResultSet::class; } /** @@ -178,8 +185,10 @@ protected function getResultSetClassName() * * @param SearchRequest $searchRequest * @return SearchResultSet + * @throws Facets\InvalidFacetPackageException + * @throws Exception */ - public function search(SearchRequest $searchRequest) + public function search(SearchRequest $searchRequest): SearchResultSet { $resultSet = $this->getInitializedSearchResultSet($searchRequest); $this->lastResultSet = $resultSet; @@ -190,7 +199,11 @@ public function search(SearchRequest $searchRequest) return $resultSet; } - $query = $this->queryBuilder->buildSearchQuery($searchRequest->getRawUserQuery(), (int)$searchRequest->getResultsPerPage(), $searchRequest->getAdditionalFilters()); + $query = $this->queryBuilder->buildSearchQuery( + $searchRequest->getRawUserQuery(), + $searchRequest->getResultsPerPage(), + $searchRequest->getAdditionalFilters() + ); $this->initializeRegisteredSearchComponents($query, $searchRequest); $resultSet->setUsedQuery($query); @@ -198,7 +211,7 @@ public function search(SearchRequest $searchRequest) $query = $this->modifyQuery($query, $searchRequest, $this->search); $response = $this->doASearch($query, $searchRequest); - if ((int)$searchRequest->getResultsPerPage() === 0) { + if ($searchRequest->getResultsPerPage() === 0) { // when resultPerPage was forced to 0 we also set the numFound to 0 to hide results, e.g. // when results for the initial search should not be shown. // @extensionScannerIgnoreLine @@ -215,8 +228,10 @@ public function search(SearchRequest $searchRequest) /** @var $variantsProcessor VariantsProcessor */ $variantsProcessor = GeneralUtility::makeInstance( VariantsProcessor::class, - /** @scrutinizer ignore-type */ $this->typoScriptConfiguration, - /** @scrutinizer ignore-type */ $this->searchResultBuilder + /** @scrutinizer ignore-type */ + $this->typoScriptConfiguration, + /** @scrutinizer ignore-type */ + $this->searchResultBuilder ); $variantsProcessor->process($resultSet); @@ -234,7 +249,7 @@ public function search(SearchRequest $searchRequest) * * @param SearchResultSet $resultSet */ - protected function getParsedSearchResults($resultSet) + protected function getParsedSearchResults(SearchResultSet $resultSet) { /** @var ResultParserRegistry $parserRegistry */ $parserRegistry = GeneralUtility::makeInstance(ResultParserRegistry::class, /** @scrutinizer ignore-type */ $this->typoScriptConfiguration); @@ -249,7 +264,7 @@ protected function getParsedSearchResults($resultSet) * @param SearchRequest $searchRequest * @return bool */ - protected function shouldReturnEmptyResultSetWithoutExecutedSearch(SearchRequest $searchRequest) + protected function shouldReturnEmptyResultSetWithoutExecutedSearch(SearchRequest $searchRequest): bool { if ($searchRequest->getRawUserQueryIsNull() && !$this->getInitialSearchIsConfigured()) { // when no rawQuery was passed or no initialSearch is configured, we pass an empty result set @@ -270,7 +285,7 @@ protected function shouldReturnEmptyResultSetWithoutExecutedSearch(SearchRequest * @param SearchRequest $searchRequest * @return SearchResultSet */ - protected function getInitializedSearchResultSet(SearchRequest $searchRequest):SearchResultSet + protected function getInitializedSearchResultSet(SearchRequest $searchRequest): SearchResultSet { /** @var $resultSet SearchResultSet */ $resultSetClass = $this->getResultSetClassName(); @@ -278,7 +293,7 @@ protected function getInitializedSearchResultSet(SearchRequest $searchRequest):S $resultSet->setUsedSearchRequest($searchRequest); $resultSet->setUsedPage((int)$searchRequest->getPage()); - $resultSet->setUsedResultsPerPage((int)$searchRequest->getResultsPerPage()); + $resultSet->setUsedResultsPerPage($searchRequest->getResultsPerPage()); $resultSet->setUsedSearch($this->search); return $resultSet; } @@ -289,15 +304,16 @@ protected function getInitializedSearchResultSet(SearchRequest $searchRequest):S * @param Query $query * @param SearchRequest $searchRequest * @return ResponseAdapter + * @throws Exception */ - protected function doASearch($query, $searchRequest): ResponseAdapter + protected function doASearch(Query $query, SearchRequest $searchRequest): ResponseAdapter { - // the offset mulitplier is page - 1 but not less then zero + // the offset multiplier is page - 1 but not less than zero $offsetMultiplier = max(0, $searchRequest->getPage() - 1); - $offSet = $offsetMultiplier * (int)$searchRequest->getResultsPerPage(); + $offSet = $offsetMultiplier * $searchRequest->getResultsPerPage(); - $response = $this->search->search($query, $offSet, null); - if($response === null) { + $response = $this->search->search($query, $offSet); + if ($response === null) { throw new SolrIncompleteResponseException('The response retrieved from solr was incomplete', 1505989678); } @@ -307,15 +323,16 @@ protected function doASearch($query, $searchRequest): ResponseAdapter /** * @param SearchResultSet $searchResultSet * @return SearchResultSet + * @throws Facets\InvalidFacetPackageException */ - protected function getAutoCorrection(SearchResultSet $searchResultSet) + protected function getAutoCorrection(SearchResultSet $searchResultSet): SearchResultSet { // no secondary search configured if (!$this->typoScriptConfiguration->getSearchSpellcheckingSearchUsingSpellCheckerSuggestion()) { return $searchResultSet; } - // more then zero results + // if more as zero results if ($searchResultSet->getAllResultCount() > 0) { return $searchResultSet; } @@ -325,21 +342,21 @@ protected function getAutoCorrection(SearchResultSet $searchResultSet) return $searchResultSet; } - $searchResultSet = $this->peformAutoCorrection($searchResultSet); - - return $searchResultSet; + return $this->performAutoCorrection($searchResultSet); } /** * @param SearchResultSet $searchResultSet * @return SearchResultSet + * + * @throws Facets\InvalidFacetPackageException */ - protected function peformAutoCorrection(SearchResultSet $searchResultSet) + protected function performAutoCorrection(SearchResultSet $searchResultSet): SearchResultSet { $searchRequest = $searchResultSet->getUsedSearchRequest(); $suggestions = $searchResultSet->getSpellCheckingSuggestions(); - $maximumRuns = $this->typoScriptConfiguration->getSearchSpellcheckingNumberOfSuggestionsToTry(1); + $maximumRuns = $this->typoScriptConfiguration->getSearchSpellcheckingNumberOfSuggestionsToTry(); $runs = 0; foreach ($suggestions as $suggestion) { @@ -370,10 +387,10 @@ protected function peformAutoCorrection(SearchResultSet $searchResultSet) * @param Query $query The current query before it's being handed over to Solr. * @param SearchRequest $searchRequest The searchRequest, relevant in the current context * @param Search $search The search, relevant in the current context - * @throws \UnexpectedValueException + * @throws UnexpectedValueException * @return Query The modified query that is actually going to be given to Solr. */ - protected function modifyQuery(Query $query, SearchRequest $searchRequest, Search $search) + protected function modifyQuery(Query $query, SearchRequest $searchRequest, Search $search): Query { // hook to modify the search query if (is_array($GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['solr']['modifySearchQuery'] ?? null)) { @@ -391,7 +408,7 @@ protected function modifyQuery(Query $query, SearchRequest $searchRequest, Searc $query = $queryModifier->modifyQuery($query); } else { - throw new \UnexpectedValueException( + throw new UnexpectedValueException( get_class($queryModifier) . ' must implement interface ' . Modifier::class, 1310387414 ); @@ -407,18 +424,19 @@ protected function modifyQuery(Query $query, SearchRequest $searchRequest, Searc * * @param string $documentId * @return SearchResult + * @throws Exception */ - public function getDocumentById($documentId) + public function getDocumentById(string $documentId): SearchResult { /* @var $query SearchQuery */ $query = $this->queryBuilder->newSearchQuery($documentId)->useQueryFields(QueryFields::fromString('id'))->getQuery(); $response = $this->search->search($query, 0, 1); $parsedData = $response->getParsedData(); // @extensionScannerIgnoreLine - $resultDocument = isset($parsedData->response->docs[0]) ? $parsedData->response->docs[0] : null; + $resultDocument = $parsedData->response->docs[0] ?? null; if (!$resultDocument instanceof Document) { - throw new \UnexpectedValueException("Response did not contain a valid Document object"); + throw new UnexpectedValueException('Response did not contain a valid Document object'); } return $this->searchResultBuilder->fromApacheSolrDocument($resultDocument); @@ -431,7 +449,7 @@ public function getDocumentById($documentId) * @param SearchResultSet $resultSet * @return SearchResultSet */ - private function handleSearchHook($eventName, SearchResultSet $resultSet) + private function handleSearchHook(string $eventName, SearchResultSet $resultSet): SearchResultSet { if (!is_array($GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['solr'][$eventName] ?? null)) { return $resultSet; @@ -450,7 +468,7 @@ private function handleSearchHook($eventName, SearchResultSet $resultSet) /** * @return SearchResultSet */ - public function getLastResultSet() + public function getLastResultSet(): ?SearchResultSet { return $this->lastResultSet; } @@ -461,7 +479,7 @@ public function getLastResultSet() * * @return bool */ - public function getLastSearchWasExecutedWithEmptyQueryString() + public function getLastSearchWasExecutedWithEmptyQueryString(): bool { $wasEmptyQueryString = false; if ($this->lastResultSet != null) { @@ -474,7 +492,7 @@ public function getLastSearchWasExecutedWithEmptyQueryString() /** * @return bool */ - protected function getInitialSearchIsConfigured() + protected function getInitialSearchIsConfigured(): bool { return $this->typoScriptConfiguration->getSearchInitializeWithEmptyQuery() || $this->typoScriptConfiguration->getSearchShowResultsOfInitialEmptyQuery() || $this->typoScriptConfiguration->getSearchInitializeWithQuery() || $this->typoScriptConfiguration->getSearchShowResultsOfInitialQuery(); } diff --git a/Classes/Domain/Search/ResultSet/Sorting/Sorting.php b/Classes/Domain/Search/ResultSet/Sorting/Sorting.php index 9949f10e16..27e750f0d8 100644 --- a/Classes/Domain/Search/ResultSet/Sorting/Sorting.php +++ b/Classes/Domain/Search/ResultSet/Sorting/Sorting.php @@ -1,8 +1,24 @@ name = $name; $this->direction = $direction; @@ -74,7 +97,7 @@ public function __construct(SearchResultSet $resultSet, $name, $field, $directio /** * @return string */ - public function getDirection() + public function getDirection(): string { return $this->direction; } @@ -82,7 +105,7 @@ public function getDirection() /** * @return bool */ - public function getIsAscDirection() + public function getIsAscDirection(): bool { return $this->direction === self::DIRECTION_ASC; } @@ -90,7 +113,7 @@ public function getIsAscDirection() /** * @return bool */ - public function getIsDescDirection() + public function getIsDescDirection(): bool { return $this->direction === self::DIRECTION_DESC; } @@ -100,7 +123,7 @@ public function getIsDescDirection() * * @return string */ - public function getOppositeDirection() + public function getOppositeDirection(): string { return self::getOppositeDirectionFromDirection($this->direction); } @@ -108,7 +131,7 @@ public function getOppositeDirection() /** * @return string */ - public function getField() + public function getField(): string { return $this->field; } @@ -116,7 +139,7 @@ public function getField() /** * @return string */ - public function getLabel() + public function getLabel(): string { return $this->label; } @@ -124,15 +147,15 @@ public function getLabel() /** * @return string */ - public function getName() + public function getName(): string { return $this->name; } /** - * @return boolean + * @return bool */ - public function getSelected() + public function getSelected(): bool { return $this->selected; } @@ -141,7 +164,7 @@ public function getSelected() * @param string $direction * @return bool */ - public static function getIsValidDirection($direction) + public static function getIsValidDirection(string $direction): bool { return in_array($direction, self::$validDirections); } @@ -150,19 +173,18 @@ public static function getIsValidDirection($direction) * @param string $direction * @return string */ - public static function getOppositeDirectionFromDirection($direction) + public static function getOppositeDirectionFromDirection(string $direction): string { if ($direction === self::DIRECTION_ASC) { return self::DIRECTION_DESC; - } else { - return self::DIRECTION_ASC; } + return self::DIRECTION_ASC; } /** - * @return boolean + * @return bool */ - public function getIsResetOption() + public function getIsResetOption(): bool { return $this->isResetOption; } diff --git a/Classes/Domain/Search/ResultSet/Sorting/SortingHelper.php b/Classes/Domain/Search/ResultSet/Sorting/SortingHelper.php index 8fdfe2e89a..0b69d45118 100644 --- a/Classes/Domain/Search/ResultSet/Sorting/SortingHelper.php +++ b/Classes/Domain/Search/ResultSet/Sorting/SortingHelper.php @@ -1,5 +1,7 @@ configuration)); foreach ($sortParameters as $sortParameter) { list($sortOption, $sortDirection) = explode(' ', $sortParameter); if (!in_array($sortOption, $configuredSortingName)) { - throw new \InvalidArgumentException('No sorting configuration found for option name ' . $sortOption, 1316187644); + throw new InvalidArgumentException('No sorting configuration found for option name ' . $sortOption, 1316187644); } $sortField = $this->configuration[$sortOption . '.']['field']; diff --git a/Classes/Domain/Search/ResultSet/Spellchecking/Suggestion.php b/Classes/Domain/Search/ResultSet/Spellchecking/Suggestion.php index b52d718610..e217969f44 100644 --- a/Classes/Domain/Search/ResultSet/Spellchecking/Suggestion.php +++ b/Classes/Domain/Search/ResultSet/Spellchecking/Suggestion.php @@ -1,5 +1,7 @@ suggestion = $suggestion; $this->missSpelled = $missSpelled; $this->numFound = $numFound; @@ -68,7 +74,7 @@ public function __construct($suggestion = '', $missSpelled = '', $numFound = 1, /** * @return int */ - public function getEndOffset() + public function getEndOffset(): int { return $this->endOffset; } @@ -76,7 +82,7 @@ public function getEndOffset() /** * @return int */ - public function getNumFound() + public function getNumFound(): int { return $this->numFound; } @@ -84,7 +90,7 @@ public function getNumFound() /** * @return int */ - public function getStartOffset() + public function getStartOffset(): int { return $this->startOffset; } @@ -92,7 +98,7 @@ public function getStartOffset() /** * @return string */ - public function getSuggestion() + public function getSuggestion(): string { return $this->suggestion; } @@ -100,7 +106,7 @@ public function getSuggestion() /** * @return string */ - public function getMissSpelled() + public function getMissSpelled(): string { return $this->missSpelled; } diff --git a/Classes/Domain/Search/SearchRequest.php b/Classes/Domain/Search/SearchRequest.php index be3921a280..19ba5a84d4 100644 --- a/Classes/Domain/Search/SearchRequest.php +++ b/Classes/Domain/Search/SearchRequest.php @@ -1,6 +1,6 @@ stateChanged = true; $this->persistedArguments = $argumentsArray; $this->contextPageUid = $pageUid; @@ -138,7 +148,7 @@ public function __construct(array $argumentsArray = [], int $pageUid = 0, int $s /** * @return string */ - public function getId() + public function getId(): string { return $this->id; } @@ -149,7 +159,7 @@ public function getId() * @param array $argumentsToMerge * @return SearchRequest */ - public function mergeArguments(array $argumentsToMerge) + public function mergeArguments(array $argumentsToMerge): SearchRequest { ArrayUtility::mergeRecursiveWithOverrule( $this->persistedArguments, @@ -175,7 +185,7 @@ protected function prefixWithNamespace(string $path): string /** * @return array */ - public function getActiveFacetNames() + public function getActiveFacetNames(): array { return $this->activeFacetContainer->getActiveFacetNames(); } @@ -185,7 +195,7 @@ public function getActiveFacetNames() * @param string $facetName * @return array */ - public function getActiveFacetValuesByName(string $facetName) + public function getActiveFacetValuesByName(string $facetName): array { return $this->activeFacetContainer->getActiveFacetValuesByName($facetName); } @@ -193,13 +203,14 @@ public function getActiveFacetValuesByName(string $facetName) /** * @return array */ - public function getActiveFacets() + public function getActiveFacets(): array { return $this->activeFacetContainer->getActiveFacets(); } /** * Enable sorting of URL parameters + * @noinspection PhpUnused */ public function sortActiveFacets(): void { @@ -227,7 +238,7 @@ public function getActiveFacetsUrlParameterStyle(): string * * @return int */ - public function getActiveFacetCount() + public function getActiveFacetCount(): int { return $this->activeFacetContainer->count(); } @@ -236,8 +247,9 @@ public function getActiveFacetCount() * @param array $activeFacets * * @return SearchRequest + * @noinspection PhpUnused */ - protected function setActiveFacets($activeFacets = []) + protected function setActiveFacets(array $activeFacets = []): SearchRequest { $this->activeFacetContainer->setActiveFacets($activeFacets); @@ -252,7 +264,7 @@ protected function setActiveFacets($activeFacets = []) * * @return SearchRequest */ - public function addFacetValue(string $facetName, $facetValue) + public function addFacetValue(string $facetName, $facetValue): SearchRequest { $this->activeFacetContainer->addFacetValue($facetName, $facetValue); @@ -272,7 +284,7 @@ public function addFacetValue(string $facetName, $facetValue) * * @return SearchRequest */ - public function removeFacetValue(string $facetName, $facetValue) + public function removeFacetValue(string $facetName, $facetValue): SearchRequest { $this->activeFacetContainer->removeFacetValue($facetName, $facetValue); if ($this->activeFacetContainer->hasChanged()) { @@ -290,7 +302,7 @@ public function removeFacetValue(string $facetName, $facetValue) * * @return SearchRequest */ - public function removeAllFacetValuesByName(string $facetName) + public function removeAllFacetValuesByName(string $facetName): SearchRequest { $this->activeFacetContainer->removeAllFacetValuesByName($facetName); if ($this->activeFacetContainer->hasChanged()) { @@ -305,7 +317,7 @@ public function removeAllFacetValuesByName(string $facetName) * * @return SearchRequest */ - public function removeAllFacets() + public function removeAllFacets(): SearchRequest { $this->activeFacetContainer->removeAllFacets(); if ($this->activeFacetContainer->hasChanged()) { @@ -330,7 +342,7 @@ public function getHasFacetValue(string $facetName, $facetValue): bool /** * @return bool */ - public function getHasSorting() + public function getHasSorting(): bool { $path = $this->prefixWithNamespace('sort'); return $this->argumentsAccessor->has($path); @@ -353,7 +365,7 @@ public function getSorting(): string * @param int $index * @return string */ - protected function getSortingPart($index) + protected function getSortingPart(int $index): ?string { $sorting = $this->getSorting(); if ($sorting === '') { @@ -369,7 +381,7 @@ protected function getSortingPart($index) * * @return string */ - public function getSortingName() + public function getSortingName(): ?string { return $this->getSortingPart(0); } @@ -387,7 +399,7 @@ public function getSortingDirection(): string /** * @return SearchRequest */ - public function removeSorting() + public function removeSorting(): SearchRequest { $path = $this->prefixWithNamespace('sort'); $this->argumentsAccessor->reset($path); @@ -401,7 +413,7 @@ public function removeSorting() * * @return SearchRequest */ - public function setSorting($sortingName, $direction = 'asc') + public function setSorting(string $sortingName, string $direction = 'asc'): SearchRequest { $value = $sortingName . ' ' . $direction; $path = $this->prefixWithNamespace('sort'); @@ -416,7 +428,7 @@ public function setSorting($sortingName, $direction = 'asc') * @param int $page * @return SearchRequest */ - public function setPage($page) + public function setPage(int $page): SearchRequest { $this->stateChanged = true; $path = $this->prefixWithNamespace('page'); @@ -433,7 +445,7 @@ public function setPage($page) * * @return int|null */ - public function getPage() + public function getPage(): ?int { $path = $this->prefixWithNamespace('page'); return $this->argumentsAccessor->get($path); @@ -484,14 +496,14 @@ public function getGroupItemPage(string $groupName, string $groupItemValue): int } /** - * Removes all non alphanumeric values from the groupItem value to have a valid array key. + * Removes all non-alphanumeric values from the groupItem value to have a valid array key. * * @param string $groupItemValue * @return string */ - protected function getEscapedGroupItemValue(string $groupItemValue) + protected function getEscapedGroupItemValue(string $groupItemValue): string { - return preg_replace("/[^A-Za-z0-9]/", '', $groupItemValue); + return preg_replace('/[^A-Za-z0-9]/', '', $groupItemValue); } /** @@ -499,13 +511,15 @@ protected function getEscapedGroupItemValue(string $groupItemValue) * * @return int */ - public function getHighestGroupPage() + public function getHighestGroupPage(): int { $max = 1; $path = $this->prefixWithNamespace('groupPage'); $groupPages = $this->argumentsAccessor->get($path, []); foreach ($groupPages as $groups) { - if (!is_array($groups)) continue; + if (!is_array($groups)) { + continue; + } foreach ($groups as $groupItemPage) { if ($groupItemPage > $max) { $max = $groupItemPage; @@ -522,7 +536,7 @@ public function getHighestGroupPage() * @param string $rawQueryString * @return SearchRequest */ - public function setRawQueryString($rawQueryString) + public function setRawQueryString(string $rawQueryString = ''): SearchRequest { $this->stateChanged = true; $path = $this->prefixWithNamespace('q'); @@ -533,13 +547,13 @@ public function setRawQueryString($rawQueryString) /** * Returns the passed rawQueryString. * - * @return string|null + * @return string */ - public function getRawUserQuery() + public function getRawUserQuery(): string { $path = $this->prefixWithNamespace('q'); - $query = $this->argumentsAccessor->get($path, null); - return is_null($query) ? $query : (string)$query; + $query = $this->argumentsAccessor->get($path); + return (string)($query ?? ''); } /** @@ -549,10 +563,10 @@ public function getRawUserQuery() * When no query string is set (null) the method returns false. * @return bool */ - public function getRawUserQueryIsEmptyString() + public function getRawUserQueryIsEmptyString(): bool { $path = $this->prefixWithNamespace('q'); - $query = $this->argumentsAccessor->get($path, null); + $query = $this->argumentsAccessor->get($path); if ($query === null) { return false; @@ -571,10 +585,10 @@ public function getRawUserQueryIsEmptyString() * * @return bool */ - public function getRawUserQueryIsNull() + public function getRawUserQueryIsNull(): bool { $path = $this->prefixWithNamespace('q'); - $query = $this->argumentsAccessor->get($path, null); + $query = $this->argumentsAccessor->get($path); return $query === null; } @@ -584,7 +598,7 @@ public function getRawUserQueryIsNull() * @param int $resultsPerPage * @return SearchRequest */ - public function setResultsPerPage($resultsPerPage) + public function setResultsPerPage(int $resultsPerPage): SearchRequest { $path = $this->prefixWithNamespace('resultsPerPage'); $this->argumentsAccessor->set($path, $resultsPerPage); @@ -596,28 +610,28 @@ public function setResultsPerPage($resultsPerPage) /** * @return bool */ - public function getStateChanged() + public function getStateChanged(): bool { return $this->stateChanged; } /** * Returns the passed resultsPerPage value - * @return int|null + * @return int */ - public function getResultsPerPage() + public function getResultsPerPage(): int { $path = $this->prefixWithNamespace('resultsPerPage'); - return $this->argumentsAccessor->get($path); + return (int)$this->argumentsAccessor->get($path); } /** - * Allows to set additional filters that are used on time and not transported during the request. + * Allows setting additional filters that are used on time and not transported during the request. * * @param array $additionalFilters * @return SearchRequest */ - public function setAdditionalFilters($additionalFilters) + public function setAdditionalFilters(array $additionalFilters): SearchRequest { $path = $this->prefixWithNamespace('additionalFilters'); $this->argumentsAccessor->set($path, $additionalFilters); @@ -627,11 +641,11 @@ public function setAdditionalFilters($additionalFilters) } /** - * Retrieves the addtional filters that have been set + * Retrieves the additional filters that have been set * * @return array */ - public function getAdditionalFilters() + public function getAdditionalFilters(): array { $path = $this->prefixWithNamespace('additionalFilters'); return $this->argumentsAccessor->get($path, []); @@ -640,7 +654,7 @@ public function getAdditionalFilters() /** * @return int */ - public function getContextSystemLanguageUid() + public function getContextSystemLanguageUid(): int { return $this->contextSystemLanguageUid; } @@ -648,7 +662,7 @@ public function getContextSystemLanguageUid() /** * @return int */ - public function getContextPageUid() + public function getContextPageUid(): int { return $this->contextPageUid; } @@ -726,6 +740,7 @@ public function getCopyForSubRequest(bool $onlyPersistentArguments = true): Sear /** * @return string + * @noinspection PhpUnused */ public function getArgumentNamespace(): string { diff --git a/Classes/Domain/Search/SearchRequestBuilder.php b/Classes/Domain/Search/SearchRequestBuilder.php index 1245d7b3e6..8320c3b0b2 100644 --- a/Classes/Domain/Search/SearchRequestBuilder.php +++ b/Classes/Domain/Search/SearchRequestBuilder.php @@ -1,5 +1,7 @@ adjustPageArgumentToPositiveInteger($controllerArguments); - /** @var $searchRequest SearchRequest */ + /* @var SearchRequest $searchRequest */ $argumentsNamespace = $this->typoScriptConfiguration->getSearchPluginNamespace(); $searchRequest = $this->getRequest([$argumentsNamespace => $controllerArguments], $pageId, $languageId); - $searchRequest = $this->applyPassedResultsPerPage($searchRequest); - - return $searchRequest; + return $this->applyPassedResultsPerPage($searchRequest); } /** @@ -109,7 +108,7 @@ protected function applyPassedResultsPerPage(SearchRequest $searchRequest): Sear * @param SearchRequest $searchRequest * @return bool */ - protected function shouldHideResultsFromInitialSearch(SearchRequest $searchRequest) + protected function shouldHideResultsFromInitialSearch(SearchRequest $searchRequest): bool { return ($this->typoScriptConfiguration->getSearchInitializeWithEmptyQuery() || $this->typoScriptConfiguration->getSearchInitializeWithQuery()) && @@ -123,11 +122,10 @@ protected function shouldHideResultsFromInitialSearch(SearchRequest $searchReque * @param int $languageId * @return SearchRequest */ - public function buildForFrequentSearches($pageId, $languageId) + public function buildForFrequentSearches(int $pageId, int $languageId): SearchRequest { - /** @var $searchRequest SearchRequest */ - $searchRequest = $this->getRequest([], $pageId, $languageId); - return $searchRequest; + /* @var SearchRequest $searchRequest */ + return $this->getRequest([], $pageId, $languageId); } /** @@ -137,13 +135,24 @@ public function buildForFrequentSearches($pageId, $languageId) * @param int $languageId * @return SearchRequest */ - public function buildForSuggest(array $controllerArguments, $rawUserQuery, $pageId, $languageId) - { + public function buildForSuggest( + array $controllerArguments, + string $rawUserQuery, + int $pageId, + int $languageId + ): SearchRequest { $controllerArguments['page'] = 0; $controllerArguments['q'] = $rawUserQuery; $argumentsNamespace = $this->typoScriptConfiguration->getSearchPluginNamespace(); - return $this->getRequest(['q' => $rawUserQuery, $argumentsNamespace => $controllerArguments], $pageId, $languageId); + return $this->getRequest( + [ + 'q' => $rawUserQuery, + $argumentsNamespace => $controllerArguments, + ], + $pageId, + $languageId + ); } /** @@ -158,24 +167,27 @@ protected function getRequest(array $requestArguments = [], int $pageId = 0, int { return GeneralUtility::makeInstance( SearchRequest::class, - /** @scrutinizer ignore-type */ $requestArguments, - /** @scrutinizer ignore-type */ $pageId, - /** @scrutinizer ignore-type */ $languageId, - /** @scrutinizer ignore-type */ $this->typoScriptConfiguration + /** @scrutinizer ignore-type */ + $requestArguments, + /** @scrutinizer ignore-type */ + $pageId, + /** @scrutinizer ignore-type */ + $languageId, + /** @scrutinizer ignore-type */ + $this->typoScriptConfiguration ); } /** - * This methods sets the page argument to an expected positive integer value in the arguments array. + * This method sets the page argument to an expected positive integer value in the arguments array. * * @param array $arguments * @return array */ protected function adjustPageArgumentToPositiveInteger(array $arguments): array { - $page = isset($arguments['page']) ? intval($arguments['page']) : 0; + $page = isset($arguments['page']) ? (int)($arguments['page']) : 0; $arguments['page'] = max($page, 0); - return $arguments; } } diff --git a/Classes/Domain/Search/Statistics/StatisticsRepository.php b/Classes/Domain/Search/Statistics/StatisticsRepository.php index f3ce99f34b..c3bf0ec822 100644 --- a/Classes/Domain/Search/Statistics/StatisticsRepository.php +++ b/Classes/Domain/Search/Statistics/StatisticsRepository.php @@ -1,6 +1,6 @@ getPreparedQueryBuilderForSearchStatisticsAndTopKeywords($rootPageId, $timeStart, $limit) - ->execute()->fetchAll(); + ->execute()->fetchAllAssociative(); } /** @@ -58,12 +60,14 @@ public function getSearchStatistics(int $rootPageId, int $days = 30, $limit = 10 * @param int $timeStart * @param int $limit * @return QueryBuilder + * @throws DBALDriverException + * @throws DBALException|\Doctrine\DBAL\DBALException */ - protected function getPreparedQueryBuilderForSearchStatisticsAndTopKeywords(int $rootPageId, int $timeStart, int $limit) : QueryBuilder + protected function getPreparedQueryBuilderForSearchStatisticsAndTopKeywords(int $rootPageId, int $timeStart, int $limit): QueryBuilder { $countRows = $this->countByRootPageId($rootPageId); $queryBuilder = $this->getQueryBuilder(); - $statisticsQueryBuilder = $queryBuilder + return $queryBuilder ->select('keywords') ->add('select', $queryBuilder->expr()->count('keywords', 'count'), true) ->add('select', $queryBuilder->expr()->avg('num_found', 'hits'), true) @@ -78,8 +82,6 @@ protected function getPreparedQueryBuilderForSearchStatisticsAndTopKeywords(int ->addOrderBy('hits', 'DESC') ->addOrderBy('keywords', 'ASC') ->setMaxResults($limit); - - return $statisticsQueryBuilder; } /** @@ -89,10 +91,12 @@ protected function getPreparedQueryBuilderForSearchStatisticsAndTopKeywords(int * @param int $days number of days of history to query * @param int $limit * @return array + * @throws DBALDriverException + * @throws DBALException|\Doctrine\DBAL\DBALException */ - public function getTopKeyWordsWithHits(int $rootPageId, int $days = 30, int $limit = 10) : array + public function getTopKeyWordsWithHits(int $rootPageId, int $days = 30, int $limit = 10): array { - return $this->getTopKeyWordsWithOrWithoutHits($rootPageId, $days, $limit, false); + return $this->getTopKeyWordsWithOrWithoutHits($rootPageId, $days, $limit); } /** @@ -102,8 +106,10 @@ public function getTopKeyWordsWithHits(int $rootPageId, int $days = 30, int $lim * @param int $days number of days of history to query * @param int $limit * @return array + * @throws DBALDriverException + * @throws DBALException|\Doctrine\DBAL\DBALException */ - public function getTopKeyWordsWithoutHits(int $rootPageId, int $days = 30, int $limit = 10) : array + public function getTopKeyWordsWithoutHits(int $rootPageId, int $days = 30, int $limit = 10): array { return $this->getTopKeyWordsWithOrWithoutHits($rootPageId, $days, $limit, true); } @@ -116,8 +122,10 @@ public function getTopKeyWordsWithoutHits(int $rootPageId, int $days = 30, int $ * @param int $limit * @param bool $withoutHits * @return array + * @throws DBALException|\Doctrine\DBAL\DBALException + * @throws DBALDriverException */ - protected function getTopKeyWordsWithOrWithoutHits(int $rootPageId, int $days = 30, int $limit = 10, bool $withoutHits = false) : array + protected function getTopKeyWordsWithOrWithoutHits(int $rootPageId, int $days = 30, int $limit = 10, bool $withoutHits = false): array { $now = time(); $timeStart = $now - 86400 * $days; // 86400 seconds/day @@ -130,7 +138,7 @@ protected function getTopKeyWordsWithOrWithoutHits(int $rootPageId, int $days = $queryBuilder->andWhere($queryBuilder->expr()->gt('num_found', 0)); } - return $queryBuilder->execute()->fetchAll(); + return $queryBuilder->execute()->fetchAllAssociative(); } /** @@ -140,14 +148,16 @@ protected function getTopKeyWordsWithOrWithoutHits(int $rootPageId, int $days = * @param int $days number of days of history to query * @param int $bucketSeconds Seconds per bucket * @return array [labels, data] + * @throws DBALException|\Doctrine\DBAL\DBALException + * @throws DBALDriverException */ - public function getQueriesOverTime(int $rootPageId, int $days = 30, int $bucketSeconds = 3600) : array + public function getQueriesOverTime(int $rootPageId, int $days = 30, int $bucketSeconds = 3600): array { $now = time(); - $timeStart = $now - 86400 * intval($days); // 86400 seconds/day + $timeStart = $now - 86400 * $days; // 86400 seconds/day $queryBuilder = $this->getQueryBuilder(); - $result = $queryBuilder + return $queryBuilder ->addSelectLiteral( 'FLOOR(tstamp/' . $bucketSeconds . ') AS bucket', '(tstamp - (tstamp % 86400)) AS timestamp', @@ -160,21 +170,22 @@ public function getQueriesOverTime(int $rootPageId, int $days = 30, int $bucketS ) ->groupBy('bucket', 'timestamp') ->orderBy('bucket', 'ASC') - ->execute()->fetchAll(); - - return $result; + ->execute() + ->fetchAllAssociative(); } /** - * Regurns a result set by given plugin.tx_solr.search.frequentSearches.select configuration. + * Returns a result set by given plugin.tx_solr.search.frequentSearches.select configuration. * * @param array $frequentSearchConfiguration * @return array Array of frequent search terms, keys are the terms, values are hits + * @throws DBALException|\Doctrine\DBAL\DBALException + * @throws DBALDriverException */ - public function getFrequentSearchTermsFromStatisticsByFrequentSearchConfiguration(array $frequentSearchConfiguration) : array + public function getFrequentSearchTermsFromStatisticsByFrequentSearchConfiguration(array $frequentSearchConfiguration): array { $queryBuilder = $this->getQueryBuilder(); - $resultSet = $queryBuilder + return $queryBuilder ->addSelectLiteral( $frequentSearchConfiguration['select.']['SELECT'] ) @@ -183,16 +194,15 @@ public function getFrequentSearchTermsFromStatisticsByFrequentSearchConfiguratio ->add('groupBy', $frequentSearchConfiguration['select.']['GROUP_BY'], true) ->add('orderBy', $frequentSearchConfiguration['select.']['ORDER_BY']) ->setMaxResults((int)$frequentSearchConfiguration['limit']) - ->execute()->fetchAll(); - - return $resultSet; + ->execute() + ->fetchAllAssociative(); } /** * Persists statistics record * * @param array $statisticsRecord - * @return void + * @throws DBALException|\Doctrine\DBAL\DBALException */ public function saveStatisticsRecord(array $statisticsRecord) { @@ -205,6 +215,8 @@ public function saveStatisticsRecord(array $statisticsRecord) * * @param int $rootPageId * @return int + * @throws DBALDriverException + * @throws DBALException|\Doctrine\DBAL\DBALException */ public function countByRootPageId(int $rootPageId): int { @@ -213,6 +225,7 @@ public function countByRootPageId(int $rootPageId): int ->count('*') ->from($this->table) ->andWhere($queryBuilder->expr()->eq('root_pid', $rootPageId)) - ->execute()->fetchColumn(0); + ->execute() + ->fetchOne(); } } diff --git a/Classes/Domain/Search/Statistics/StatisticsWriterProcessor.php b/Classes/Domain/Search/Statistics/StatisticsWriterProcessor.php index e3278b85ca..7fa44232b9 100644 --- a/Classes/Domain/Search/Statistics/StatisticsWriterProcessor.php +++ b/Classes/Domain/Search/Statistics/StatisticsWriterProcessor.php @@ -18,10 +18,13 @@ use ApacheSolrForTypo3\Solr\Domain\Search\Query\Query; use ApacheSolrForTypo3\Solr\Domain\Search\ResultSet\SearchResultSet; use ApacheSolrForTypo3\Solr\Domain\Search\ResultSet\SearchResultSetProcessor; -use ApacheSolrForTypo3\Solr\HtmlContentExtractor; use ApacheSolrForTypo3\Solr\Domain\Site\SiteRepository; +use ApacheSolrForTypo3\Solr\HtmlContentExtractor; use ApacheSolrForTypo3\Solr\Util; +use function inet_pton; +use function pack; use TYPO3\CMS\Core\Context\Context; +use TYPO3\CMS\Core\Context\Exception\AspectNotFoundException; use TYPO3\CMS\Core\Utility\GeneralUtility; use TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController; @@ -45,11 +48,13 @@ class StatisticsWriterProcessor implements SearchResultSetProcessor protected $siteRepository; /** - * @param StatisticsRepository $statisticsRepository - * @param SiteRepository $siteRepository + * @param StatisticsRepository|null $statisticsRepository + * @param SiteRepository|null $siteRepository */ - public function __construct(StatisticsRepository $statisticsRepository = null, SiteRepository $siteRepository = null) - { + public function __construct( + StatisticsRepository $statisticsRepository = null, + SiteRepository $siteRepository = null + ) { $this->statisticsRepository = $statisticsRepository ?? GeneralUtility::makeInstance(StatisticsRepository::class); $this->siteRepository = $siteRepository ?? GeneralUtility::makeInstance(SiteRepository::class); } @@ -57,8 +62,10 @@ public function __construct(StatisticsRepository $statisticsRepository = null, S /** * @param SearchResultSet $resultSet * @return SearchResultSet + * @throws AspectNotFoundException */ - public function process(SearchResultSet $resultSet) { + public function process(SearchResultSet $resultSet): SearchResultSet + { $searchRequest = $resultSet->getUsedSearchRequest(); $response = $resultSet->getResponse(); $configuration = $searchRequest->getContextTypoScriptConfiguration(); @@ -72,7 +79,7 @@ public function process(SearchResultSet $resultSet) { $filters = $searchRequest->getActiveFacets(); $sorting = $this->sanitizeString($searchRequest->getSorting()); $page = (int)$searchRequest->getPage(); - $ipMaskLength = (int)$configuration->getStatisticsAnonymizeIP(); + $ipMaskLength = $configuration->getStatisticsAnonymizeIP(); $TSFE = $this->getTSFE(); $root_pid = $this->siteRepository->getSiteByPageId($TSFE->id)->getRootPageId(); @@ -82,7 +89,7 @@ public function process(SearchResultSet $resultSet) { 'tstamp' => $this->getTime(), 'language' => Util::getLanguageUid(), // @extensionScannerIgnoreLine - 'num_found' => (int)$resultSet->getAllResultCount(), + 'num_found' => $resultSet->getAllResultCount(), 'suggestions_shown' => is_object($response->spellcheck->suggestions ?? null) ? (int)get_object_vars($response->spellcheck->suggestions) : 0, // @extensionScannerIgnoreLine 'time_total' => $response->debug->timing->time ?? 0, @@ -92,12 +99,12 @@ public function process(SearchResultSet $resultSet) { 'time_processing' => $response->debug->timing->process->time ?? 0, 'feuser_id' => isset($TSFE->fe_user->user) ? (int)$TSFE->fe_user->user['uid'] ?? 0 : 0, 'cookie' => $TSFE->fe_user->id ?? '', - 'ip' => $this->applyIpMask((string)$this->getUserIp(), $ipMaskLength), - 'page' => (int)$page, + 'ip' => $this->applyIpMask($this->getUserIp(), $ipMaskLength), + 'page' => $page, 'keywords' => $keywords, 'filters' => serialize($filters), 'sorting' => $sorting, - 'parameters' => isset($response->responseHeader->params) ? serialize($response->responseHeader->params) : '' + 'parameters' => isset($response->responseHeader->params) ? serialize($response->responseHeader->params) : '', ]; $this->statisticsRepository->saveStatisticsRecord($statisticData); @@ -107,11 +114,13 @@ public function process(SearchResultSet $resultSet) { /** * @param Query $query - * @param boolean $lowerCaseQuery + * @param bool $lowerCaseQuery * @return string */ - protected function getProcessedKeywords(Query $query, $lowerCaseQuery = false) - { + protected function getProcessedKeywords( + Query $query, + bool $lowerCaseQuery = false + ): string { $keywords = $query->getQuery(); $keywords = $this->sanitizeString($keywords); if ($lowerCaseQuery) { @@ -127,11 +136,11 @@ protected function getProcessedKeywords(Query $query, $lowerCaseQuery = false) * @param $string String to sanitize * @return string Sanitized string */ - protected function sanitizeString($string): string + protected function sanitizeString(string $string): string { // clean content $string = HtmlContentExtractor::cleanContent($string); - $string = htmlspecialchars(strip_tags($string), ENT_QUOTES, 'UTF-8'); // after entity decoding we might have tags again + $string = htmlspecialchars(strip_tags($string), ENT_QUOTES); // after entity decoding we might have tags again return trim($string); } @@ -163,7 +172,7 @@ protected function applyIpMask(string $ip, int $maskLength): string * @param int $maskLength * @return string */ - protected function applyIpV4Mask($ip, $maskLength) + protected function applyIpV4Mask(string $ip, int $maskLength): string { $i = strlen($ip); if ($maskLength > $i) { @@ -173,7 +182,7 @@ protected function applyIpV4Mask($ip, $maskLength) while ($maskLength-- > 0) { $ip[--$i] = chr(0); } - return (string)$ip; + return $ip; } /** @@ -183,7 +192,7 @@ protected function applyIpV4Mask($ip, $maskLength) * @param int $maskLength * @return string */ - protected function applyIpV6Mask($ip, $maskLength):string + protected function applyIpV6Mask(string $ip, int $maskLength): string { $masks = ['ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff', 'ffff:ffff:ffff:ffff::', 'ffff:ffff:ffff:0000::', 'ffff:ff00:0000:0000::']; $packedAddress = inet_pton($masks[$maskLength]); @@ -194,7 +203,7 @@ protected function applyIpV6Mask($ip, $maskLength):string /** * @return TypoScriptFrontendController */ - protected function getTSFE() + protected function getTSFE(): ?TypoScriptFrontendController { return $GLOBALS['TSFE']; } @@ -202,13 +211,14 @@ protected function getTSFE() /** * @return string */ - protected function getUserIp() + protected function getUserIp(): string { return GeneralUtility::getIndpEnv('REMOTE_ADDR'); } /** * @return mixed + * @throws AspectNotFoundException */ protected function getTime() { diff --git a/Classes/Domain/Search/Suggest/SuggestService.php b/Classes/Domain/Search/Suggest/SuggestService.php index 87bd8d75fe..130a633289 100644 --- a/Classes/Domain/Search/Suggest/SuggestService.php +++ b/Classes/Domain/Search/Suggest/SuggestService.php @@ -1,5 +1,7 @@ * @author Timo Hund */ -class SuggestService { - +class SuggestService +{ /** * @var TypoScriptFrontendController */ - protected $tsfe; + protected TypoScriptFrontendController $tsfe; /** * @var SearchResultSetService */ - protected $searchService; + protected SearchResultSetService $searchService; /** * @var TypoScriptConfiguration */ - protected $typoScriptConfiguration; + protected TypoScriptConfiguration $typoScriptConfiguration; /** * @var QueryBuilder */ - protected $queryBuilder; + protected QueryBuilder $queryBuilder; /** * SuggestService constructor. * @param TypoScriptFrontendController $tsfe * @param SearchResultSetService $searchResultSetService + * @param TypoScriptConfiguration $typoScriptConfiguration * @param QueryBuilder|null $queryBuilder */ - public function __construct(TypoScriptFrontendController $tsfe, SearchResultSetService $searchResultSetService, TypoScriptConfiguration $typoScriptConfiguration, QueryBuilder $queryBuilder = null) - { + public function __construct( + TypoScriptFrontendController $tsfe, + SearchResultSetService $searchResultSetService, + TypoScriptConfiguration $typoScriptConfiguration, + QueryBuilder $queryBuilder = null + ) { $this->tsfe = $tsfe; $this->searchService = $searchResultSetService; $this->typoScriptConfiguration = $typoScriptConfiguration; - $this->queryBuilder = $queryBuilder ?? GeneralUtility::makeInstance(QueryBuilder::class, /** @scrutinizer ignore-type */ $typoScriptConfiguration); + $this->queryBuilder = $queryBuilder ?? GeneralUtility::makeInstance( + QueryBuilder::class, + /** @scrutinizer ignore-type */ + $typoScriptConfiguration + ); } /** @@ -80,8 +93,11 @@ public function __construct(TypoScriptFrontendController $tsfe, SearchResultSetS * @param SearchRequest $searchRequest * @param array $additionalFilters * @return array + * @throws AspectNotFoundException + * @throws InvalidFacetPackageException + * @throws NoSolrConnectionFoundException */ - public function getSuggestions(SearchRequest $searchRequest, array $additionalFilters = []) : array + public function getSuggestions(SearchRequest $searchRequest, array $additionalFilters = []): array { $requestId = (int)$this->tsfe->getRequestedId(); $groupList = Util::getFrontendUserGroupsList(); @@ -111,8 +127,9 @@ public function getSuggestions(SearchRequest $searchRequest, array $additionalFi * @param array $suggestions * @param array $additionalFilters * @return array + * @throws InvalidFacetPackageException */ - protected function addTopResultsToSuggestions(SearchRequest $searchRequest, $suggestions, array $additionalFilters) : array + protected function addTopResultsToSuggestions(SearchRequest $searchRequest, array $suggestions, array $additionalFilters): array { $maxDocuments = $this->typoScriptConfiguration->getSuggestNumberOfTopResults(); @@ -130,7 +147,7 @@ protected function addTopResultsToSuggestions(SearchRequest $searchRequest, $sug } $suggestionKeys = array_keys($suggestions); - $bestSuggestion = reset($suggestionKeys); + $bestSuggestion = (string)reset($suggestionKeys); $bestSuggestionRequest = $searchRequest->getCopyForSubRequest(); $bestSuggestionRequest->setRawQueryString($bestSuggestion); $bestSuggestionRequest->setResultsPerPage($maxDocuments); @@ -153,6 +170,7 @@ protected function addTopResultsToSuggestions(SearchRequest $searchRequest, $sug * @return array * @throws NoSolrConnectionFoundException * @throws AspectNotFoundException + * @throws Exception */ protected function getSolrSuggestions(SuggestQuery $suggestQuery): array { @@ -179,11 +197,14 @@ protected function getSolrSuggestions(SuggestQuery $suggestQuery): array * * @param SuggestQuery $suggestQuery * @param array $solrSuggestions - * @param integer $maxSuggestions + * @param int $maxSuggestions * @return array */ - protected function getSuggestionArray(SuggestQuery $suggestQuery, $solrSuggestions, $maxSuggestions) : array - { + protected function getSuggestionArray( + SuggestQuery $suggestQuery, + array $solrSuggestions, + int $maxSuggestions + ): array { $queryString = $suggestQuery->getQuery(); $suggestionCount = 0; $suggestions = []; @@ -204,10 +225,10 @@ protected function getSuggestionArray(SuggestQuery $suggestQuery, $solrSuggestio * * @param array $documents * @param SearchResultCollection $documentsToAdd - * @param integer $maxDocuments + * @param int $maxDocuments * @return array */ - protected function addDocumentsWhenLimitNotReached(array $documents, SearchResultCollection $documentsToAdd, int $maxDocuments) : array + protected function addDocumentsWhenLimitNotReached(array $documents, SearchResultCollection $documentsToAdd, int $maxDocuments): array { $additionalTopResultsFields = $this->typoScriptConfiguration->getSuggestAdditionalTopResultsFields(); /** @var SearchResult $document */ @@ -228,7 +249,7 @@ protected function addDocumentsWhenLimitNotReached(array $documents, SearchResul * @param array $additionalTopResultsFields * @return array */ - protected function getDocumentAsArray(SearchResult $document, $additionalTopResultsFields = []) : array + protected function getDocumentAsArray(SearchResult $document, array $additionalTopResultsFields = []): array { $fields = [ 'link' => $document->getUrl(), @@ -248,26 +269,34 @@ protected function getDocumentAsArray(SearchResult $document, $additionalTopResu * Runs a search and returns the results. * * @param SearchRequest $searchRequest - * @return \ApacheSolrForTypo3\Solr\Domain\Search\ResultSet\SearchResultSet + * @return SearchResultSet + * @throws InvalidFacetPackageException */ - protected function doASearch($searchRequest) : SearchResultSet + protected function doASearch(SearchRequest $searchRequest): SearchResultSet { return $this->searchService->search($searchRequest); } /** - * Creates an result array with the required fields. + * Creates a result array with the required fields. * * @param SearchRequest $searchRequest * @param array $suggestions * @param array $documents - * @param boolean $didASecondSearch + * @param bool $didASecondSearch * @return array */ - protected function getResultArray(SearchRequest $searchRequest, $suggestions, $documents, $didASecondSearch) : array - { - return ['suggestions' => $suggestions, 'suggestion' => $searchRequest->getRawUserQuery(), 'documents' => $documents, 'didSecondSearch' => $didASecondSearch]; + protected function getResultArray( + SearchRequest $searchRequest, + array $suggestions, + array $documents, + bool $didASecondSearch + ): array { + return [ + 'suggestions' => $suggestions, + 'suggestion' => $searchRequest->getRawUserQuery(), + 'documents' => $documents, + 'didSecondSearch' => $didASecondSearch, + ]; } - - } diff --git a/Classes/Domain/Search/Uri/SearchUriBuilder.php b/Classes/Domain/Search/Uri/SearchUriBuilder.php index 8d5d010c10..85236482c8 100644 --- a/Classes/Domain/Search/Uri/SearchUriBuilder.php +++ b/Classes/Domain/Search/Uri/SearchUriBuilder.php @@ -1,5 +1,7 @@ @@ -42,41 +44,40 @@ */ class SearchUriBuilder { - /** - * @var UriBuilder + * @var UriBuilder|null */ - protected $uriBuilder; + protected ?UriBuilder $uriBuilder = null; /** * @var array */ - protected static $preCompiledLinks = []; + protected static array $preCompiledLinks = []; /** - * @var integer + * @var int */ - protected static $hitCount; + protected static int $hitCount = 0; /** - * @var integer + * @var int */ - protected static $missCount; + protected static int $missCount = 0; /** * @var array */ - protected static $additionalArgumentsCache = []; + protected static array $additionalArgumentsCache = []; /** * @var EventDispatcherInterface */ - protected $eventDispatcher; + protected EventDispatcherInterface $eventDispatcher; /** * @var RoutingService */ - protected $routingService; + protected RoutingService $routingService; /** * @param UriBuilder $uriBuilder @@ -104,18 +105,17 @@ public function injectEventDispatcher(EventDispatcherInterface $eventDispatcher) /** * @param SearchRequest $previousSearchRequest - * @param $facetName - * @param $facetValue + * @param string $facetName + * @param mixed $facetValue * @return string */ - public function getAddFacetValueUri(SearchRequest $previousSearchRequest, $facetName, $facetValue): string + public function getAddFacetValueUri(SearchRequest $previousSearchRequest, string $facetName, $facetValue): string { $persistentAndFacetArguments = $previousSearchRequest ->getCopyForSubRequest()->removeAllGroupItemPages()->addFacetValue($facetName, $facetValue) ->getAsArray(); $additionalArguments = $this->getAdditionalArgumentsFromRequestConfiguration($previousSearchRequest); - $additionalArguments = is_array($additionalArguments) ? $additionalArguments : []; $arguments = $persistentAndFacetArguments + $additionalArguments; @@ -256,9 +256,12 @@ public function getNewSearchUri(SearchRequest $previousSearchRequest, $queryStri $request = GeneralUtility::makeInstance( SearchRequest::class, [], - /** @scrutinizer ignore-type */ $contextPageUid, - /** @scrutinizer ignore-type */ $contextSystemLanguage, - /** @scrutinizer ignore-type */ $contextConfiguration + /** @scrutinizer ignore-type */ + $contextPageUid, + /** @scrutinizer ignore-type */ + $contextSystemLanguage, + /** @scrutinizer ignore-type */ + $contextConfiguration ); $arguments = $request->setRawQueryString($queryString)->getAsArray(); @@ -372,11 +375,11 @@ protected function buildLinkWithInMemoryCache(?int $pageUid, array $arguments): self::$preCompiledLinks[$hash] = (string)$urlHelper; } - $keys = array_map(function($value) { - return urlencode($value); + $keys = array_map(function ($value) { + return urlencode((string)$value); }, array_keys($values)); - $values = array_map(function($value) { - return urlencode($value); + $values = array_map(function ($value) { + return urlencode((string)$value); }, $values); $routingConfigurations = $this->routingService @@ -408,7 +411,7 @@ protected function buildLinkWithInMemoryCache(?int $pageUid, array $arguments): $values = $variableEvent->getVariableValues(); // Take care that everything is urlencoded! - $keys = array_map(function($value) { + $keys = array_map(function ($value) { // @TODO: With only PHP 8 support, replace this with str_contains() if (strpos($value, '###') === false) { return $value; @@ -429,8 +432,6 @@ protected function buildLinkWithInMemoryCache(?int $pageUid, array $arguments): /** * Flushes the internal in memory cache. - * - * @return void */ public function flushInMemoryCache() { @@ -468,12 +469,12 @@ public function flushInMemoryCache() * @param array $values * @param array $branch */ - protected function getSubstitution(array &$structure, array &$values, array $branch = []): void + protected function getSubstitution(array &$structure, array &$values, array $branch = []): void { /* * Adds information about the filter facet to the placeholder. * - * This feature allows to handle even placeholder in RouteEnhancer + * This feature allows the handle even placeholder in RouteEnhancer */ $filter = false; if (count($branch) > 0 && $branch[count($branch) - 1] === 'filter') { @@ -484,8 +485,11 @@ protected function getSubstitution(array &$structure, array &$values, array $br if (is_array($value)) { $this->getSubstitution($value, $values, $branch); } else { - if ($filter) { - [$facetType, $facetValue] = explode(':', $value); + // @todo: Refactor to multi-dimensional array. + // https://solr-ddev-site.ddev.site/content-examples/form-elements/search?tx_solr[filter][type:tx_news_domain_model_news]=1&tx_solr[q]=* + // https://solr-ddev-site.ddev.site/content-examples/form-elements/search?tx_solr[filter][0]=type:pages&tx_solr[q]=* + if ($filter && $value !== 1) { + [$facetType] = explode(':', $value); $branch[] = $facetType; } $path = '###' . implode(':', $branch) . '###'; diff --git a/Classes/Domain/Site/Exception/InvalidSiteConfigurationCombinationException.php b/Classes/Domain/Site/Exception/InvalidSiteConfigurationCombinationException.php index afe2a94304..3b43b5217e 100644 --- a/Classes/Domain/Site/Exception/InvalidSiteConfigurationCombinationException.php +++ b/Classes/Domain/Site/Exception/InvalidSiteConfigurationCombinationException.php @@ -1,5 +1,7 @@ getRootPageId() . '] and language [' . $language . '].', - /** @scrutinizer ignore-type */ 1552491117 + /** @scrutinizer ignore-type */ + 'Could not find a Solr connection for root page [' . $this->getRootPageId() . '] and language [' . $language . '].', + /** @scrutinizer ignore-type */ + 1552491117 ); $noSolrConnectionException->setRootPageId($this->getRootPageId()); $noSolrConnectionException->setLanguageId($language); @@ -178,11 +181,10 @@ public function getFreeContentModeLanguages(): array } if (!$this->typo3SiteObject instanceof Typo3Site) { - return false; + return []; } - foreach ($this->availableLanguageIds as $languageId) - { + foreach ($this->availableLanguageIds as $languageId) { if ($languageId > 0 && $this->typo3SiteObject->getLanguageById($languageId)->getFallbackType() === 'free') { $this->freeContentModeLanguages[$languageId] = $languageId; } @@ -227,7 +229,7 @@ public function getAvailableLanguageIds(): array } /** - * Gets the site's label. The label is build from the the site title and root + * Gets the site's label. The label is build from the site title and root * page ID (uid). * * @return string The site's label. @@ -276,8 +278,7 @@ public function getDefaultLanguageId(): int public function getPages( ?int $pageId = null, ?string $indexQueueConfigurationName = null - ): array - { + ): array { $pageId = $pageId ?? (int)$this->rootPage['uid']; $initialPagesAdditionalWhereClause = ''; @@ -328,7 +329,7 @@ public function getRootPage(): array */ public function getTitle(): string { - return $this->rootPage['title']; + return $this->rootPage['title'] ?? ''; } /** @@ -357,11 +358,15 @@ public function getAllSolrConnectionConfigurations(): array foreach ($this->getAvailableLanguageIds() as $languageId) { try { $configs[$languageId] = $this->getSolrConnectionConfiguration($languageId); - } catch (NoSolrConnectionFoundException $e) {} + } catch (NoSolrConnectionFoundException $e) { + } } return $configs; } + /** + * @return bool + */ public function isEnabled(): bool { return !empty($this->getAllSolrConnectionConfigurations()); diff --git a/Classes/Domain/Site/SiteHashService.php b/Classes/Domain/Site/SiteHashService.php index e555cf3061..0da68d33bf 100644 --- a/Classes/Domain/Site/SiteHashService.php +++ b/Classes/Domain/Site/SiteHashService.php @@ -1,5 +1,7 @@ getDomainListOfAllSites(); - } elseif ($allowedSitesConfiguration === '*') { + } + if ($allowedSitesConfiguration === '*') { return '*'; - } else { - // we thread empty allowed site configurations as __solr_current_site since this is the default behaviour - $allowedSitesConfiguration = empty($allowedSitesConfiguration) ? '__solr_current_site' : $allowedSitesConfiguration; - return $this->getDomainByPageIdAndReplaceMarkers($pageId, $allowedSitesConfiguration); } + // we thread empty allowed site configurations as __solr_current_site since this is the default behaviour + $allowedSitesConfiguration = empty($allowedSitesConfiguration) ? '__solr_current_site' : $allowedSitesConfiguration; + return $this->getDomainByPageIdAndReplaceMarkers($pageId, $allowedSitesConfiguration); } /** @@ -58,7 +65,7 @@ public function getAllowedSitesForPageIdAndAllowedSitesConfiguration($pageId, $a * @param string $domain Domain to calculate the site hash for. * @return string site hash for $domain */ - public function getSiteHashForDomain($domain) + public function getSiteHashForDomain(string $domain): string { static $siteHashes = []; if (isset($siteHashes[$domain])) { @@ -69,13 +76,14 @@ public function getSiteHashForDomain($domain) return $siteHashes[$domain]; } - /** * Returns a comma separated list of all domains from all sites. * * @return string + * @throws DBALDriverException + * @throws Throwable */ - protected function getDomainListOfAllSites() + protected function getDomainListOfAllSites(): string { $sites = $this->getAvailableSites(); $domains = []; @@ -83,19 +91,18 @@ protected function getDomainListOfAllSites() $domains[] = $site->getDomain(); } - $allowedSites = implode(',', $domains); - return $allowedSites; + return implode(',', $domains); } /** * Retrieves the domain of the site that belongs to the passed pageId and replaces their markers __solr_current_site * and __current_site. * - * @param integer $pageId + * @param int $pageId * @param string $allowedSitesConfiguration * @return string */ - protected function getDomainByPageIdAndReplaceMarkers($pageId, $allowedSitesConfiguration) + protected function getDomainByPageIdAndReplaceMarkers(int $pageId, string $allowedSitesConfiguration): string { $domainOfPage = $this->getSiteByPageId($pageId)->getDomain(); $allowedSites = str_replace(['__solr_current_site', '__current_site'], $domainOfPage, $allowedSitesConfiguration); @@ -104,17 +111,19 @@ protected function getDomainByPageIdAndReplaceMarkers($pageId, $allowedSitesConf /** * @return Site[] + * @throws DBALDriverException + * @throws Throwable */ - protected function getAvailableSites() + protected function getAvailableSites(): array { return $this->getSiteRepository()->getAvailableSites(); } /** - * @param $pageId + * @param int $pageId * @return SiteInterface */ - protected function getSiteByPageId($pageId) + protected function getSiteByPageId(int $pageId): SiteInterface { return $this->getSiteRepository()->getSiteByPageId($pageId); } @@ -124,7 +133,7 @@ protected function getSiteByPageId($pageId) * * @return SiteRepository */ - protected function getSiteRepository() + protected function getSiteRepository(): SiteRepository { return GeneralUtility::makeInstance(SiteRepository::class); } diff --git a/Classes/Domain/Site/SiteInterface.php b/Classes/Domain/Site/SiteInterface.php index fea1a505d5..9582b048ea 100644 --- a/Classes/Domain/Site/SiteInterface.php +++ b/Classes/Domain/Site/SiteInterface.php @@ -1,5 +1,7 @@ rootPageResolver = $rootPageResolver ?? GeneralUtility::makeInstance(RootPageResolver::class); $this->runtimeCache = $twoLevelCache ?? GeneralUtility::makeInstance(TwoLevelCache::class, /** @scrutinizer ignore-type */'runtime'); $this->registry = $registry ?? GeneralUtility::makeInstance(Registry::class); @@ -106,6 +106,7 @@ public function __construct( * @param int $pageId The page ID to get a Site object for. * @param string $mountPointIdentifier * @return SiteInterface Site for the given page ID. + * @throws DBALDriverException */ public function getSiteByPageId(int $pageId, string $mountPointIdentifier = '') { @@ -114,10 +115,11 @@ public function getSiteByPageId(int $pageId, string $mountPointIdentifier = '') } /** - * Gets the Site for a specific root page Id. + * Gets the Site for a specific root page-id. * * @param int $rootPageId Root page Id to get a Site object for. - * @return SiteInterface Site for the given page Id. + * @return SiteInterface Site for the given page-id. + * @throws DBALDriverException */ public function getSiteByRootPageId(int $rootPageId) { @@ -138,10 +140,11 @@ public function getSiteByRootPageId(int $rootPageId) * Returns the first available Site. * * @param bool $stopOnInvalidSite - * @throws Exception - * @return Site + * @return Site|null + * @throws DBALDriverException + * @throws Throwable */ - public function getFirstAvailableSite($stopOnInvalidSite = false) + public function getFirstAvailableSite(bool $stopOnInvalidSite = false): ?Site { $sites = $this->getAvailableSites($stopOnInvalidSite); return array_shift($sites); @@ -155,7 +158,7 @@ public function getFirstAvailableSite($stopOnInvalidSite = false) * @throws DBALDriverException * @throws Throwable */ - public function getAvailableSites($stopOnInvalidSite = false) + public function getAvailableSites(bool $stopOnInvalidSite = false): array { $cacheId = 'SiteRepository' . '_' . 'getAvailableSites'; @@ -167,7 +170,7 @@ public function getAvailableSites($stopOnInvalidSite = false) $sites = $this->getAvailableTYPO3ManagedSites($stopOnInvalidSite); $this->runtimeCache->set($cacheId, $sites); - return $sites; + return $sites ?? []; } /** @@ -191,7 +194,6 @@ protected function getAvailableTYPO3ManagedSites(bool $stopOnInvalidSite): array if ($typo3ManagedSolrSite->isEnabled()) { $typo3ManagedSolrSites[$rootPageId] = $typo3ManagedSolrSite; } - } catch (Throwable $e) { if ($stopOnInvalidSite) { throw $e; @@ -213,7 +215,7 @@ protected function buildSite(int $rootPageId) $rootPageRecord = BackendUtility::getRecord('pages', $rootPageId); if (empty($rootPageRecord)) { throw new InvalidArgumentException( - "The rootPageRecord for the given rootPageRecord ID '{$rootPageId}' could not be found in the database and can therefore not be used as site root rootPageRecord.", + "The rootPageRecord for the given rootPageRecord ID '$rootPageId' could not be found in the database and can therefore not be used as site root rootPageRecord.", 1487326416 ); } @@ -243,7 +245,7 @@ protected function validateRootPageRecord(int $rootPageId, array $rootPageRecord { if (!Site::isRootPage($rootPageRecord)) { throw new InvalidArgumentException( - "The rootPageRecord for the given rootPageRecord ID '{$rootPageId}' is not marked as root rootPageRecord and can therefore not be used as site root rootPageRecord.", + "The rootPageRecord for the given rootPageRecord ID '$rootPageId' is not marked as root rootPageRecord and can therefore not be used as site root rootPageRecord.", 1309272922 ); } @@ -270,7 +272,7 @@ protected function buildTypo3ManagedSite(array $rootPageRecord): ?Site $siteHash = $this->getSiteHashForDomain($domain); $defaultLanguage = $typo3Site->getDefaultLanguage()->getLanguageId(); $pageRepository = GeneralUtility::makeInstance(PagesRepository::class); - $availableLanguageIds = array_map(function($language) { + $availableLanguageIds = array_map(function ($language) { return $language->getLanguageId(); }, $typo3Site->getLanguages()); @@ -303,7 +305,7 @@ protected function buildTypo3ManagedSite(array $rootPageRecord): ?Site SiteUtility::getConnectionProperty($typo3Site, 'path', $languageUid, 'read', '/solr/') . SiteUtility::getConnectionProperty($typo3Site, 'core', $languageUid, 'read', 'core_en') . '/' , 'username' => SiteUtility::getConnectionProperty($typo3Site, 'username', $languageUid, 'read', ''), - 'password' => SiteUtility::getConnectionProperty($typo3Site, 'password', $languageUid, 'read', '') + 'password' => SiteUtility::getConnectionProperty($typo3Site, 'password', $languageUid, 'read', ''), ], 'write' => [ 'scheme' => SiteUtility::getConnectionProperty($typo3Site, 'scheme', $languageUid, 'write', 'http'), @@ -314,10 +316,10 @@ protected function buildTypo3ManagedSite(array $rootPageRecord): ?Site SiteUtility::getConnectionProperty($typo3Site, 'path', $languageUid, 'write', '/solr/') . SiteUtility::getConnectionProperty($typo3Site, 'core', $languageUid, 'write', 'core_en') . '/' , 'username' => SiteUtility::getConnectionProperty($typo3Site, 'username', $languageUid, 'write', ''), - 'password' => SiteUtility::getConnectionProperty($typo3Site, 'password', $languageUid, 'write', '') + 'password' => SiteUtility::getConnectionProperty($typo3Site, 'password', $languageUid, 'write', ''), ], - 'language' => $languageUid + 'language' => $languageUid, ]; } } @@ -360,8 +362,8 @@ protected function getTypo3Site(int $pageUid): ?CoreSite { try { return $this->siteFinder->getSiteByPageId($pageUid); - } catch (Throwable $e) {} + } catch (Throwable $e) { + } return null; } - } diff --git a/Classes/Domain/Variants/IdBuilder.php b/Classes/Domain/Variants/IdBuilder.php index f70749f1fb..09819273db 100644 --- a/Classes/Domain/Variants/IdBuilder.php +++ b/Classes/Domain/Variants/IdBuilder.php @@ -1,5 +1,7 @@ getSystemHash(); $variantId = $systemHash . '/' . $type . '/' . $uid; - $variantId = $this->applyHook($variantId, $systemHash, $type, $uid); - return $variantId; + return $this->applyHook($variantId, $systemHash, $type, $uid); } /** @@ -52,11 +53,15 @@ public function buildFromTypeAndUid($type, $uid) * @param string $variantId * @param string $systemHash * @param string $type - * @param integer $uid + * @param int $uid * @return string */ - protected function applyHook($variantId, $systemHash, $type, $uid) - { + protected function applyHook( + string $variantId, + string $systemHash, + string $type, + int $uid + ): string { if (!is_array($GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['solr']['modifyVariantId'] ?? null)) { return $variantId; } @@ -76,10 +81,10 @@ protected function applyHook($variantId, $systemHash, $type, $uid) * * @return string */ - protected function getSystemHash() + protected function getSystemHash(): string { if (!isset($GLOBALS['TYPO3_CONF_VARS']['SYS']['sitename'])) { - throw new \InvalidArgumentException("No sitename set in TYPO3_CONF_VARS|SYS|sitename"); + throw new InvalidArgumentException('No sitename set in TYPO3_CONF_VARS|SYS|sitename'); } $siteName = $GLOBALS['TYPO3_CONF_VARS']['SYS']['sitename']; diff --git a/Classes/Domain/Variants/IdModifier.php b/Classes/Domain/Variants/IdModifier.php index e696847722..773e04aa60 100644 --- a/Classes/Domain/Variants/IdModifier.php +++ b/Classes/Domain/Variants/IdModifier.php @@ -1,5 +1,7 @@ getResponse(); // @extensionScannerIgnoreLine @@ -98,8 +100,11 @@ public function process(SearchResultSet $resultSet) * @param string $variantAccessKey * @param SearchResult $resultDocument */ - protected function buildVariantDocumentAndAssignToParentResult(ResponseAdapter $response, $variantAccessKey, SearchResult $resultDocument) - { + protected function buildVariantDocumentAndAssignToParentResult( + ResponseAdapter $response, + string $variantAccessKey, + SearchResult $resultDocument + ) { foreach ($response->{'expanded'}->{$variantAccessKey}->{'docs'} as $variantDocumentArray) { $fields = get_object_vars($variantDocumentArray); $variantDocument = new SearchResult($fields); @@ -111,5 +116,4 @@ protected function buildVariantDocumentAndAssignToParentResult(ResponseAdapter $ $resultDocument->addVariant($variantSearchResult); } } - } diff --git a/Classes/Eid/SiteHash.php b/Classes/Eid/SiteHash.php index cf3d87a487..654688c781 100644 --- a/Classes/Eid/SiteHash.php +++ b/Classes/Eid/SiteHash.php @@ -23,9 +23,8 @@ */ use ApacheSolrForTypo3\Solr\Domain\Site\SiteHashService; -use ApacheSolrForTypo3\Solr\Util; -use TYPO3\CMS\Core\Utility\HttpUtility; use TYPO3\CMS\Core\Utility\GeneralUtility; +use TYPO3\CMS\Core\Utility\HttpUtility; $domain = GeneralUtility::_GP('domain'); $returnData = ''; diff --git a/Classes/Event/Routing/BeforeProcessCachedVariablesEvent.php b/Classes/Event/Routing/BeforeProcessCachedVariablesEvent.php index 28249aff1e..2d31f0ecc3 100644 --- a/Classes/Event/Routing/BeforeProcessCachedVariablesEvent.php +++ b/Classes/Event/Routing/BeforeProcessCachedVariablesEvent.php @@ -1,4 +1,5 @@ uri = $uri; } diff --git a/Classes/Event/Routing/PostProcessUriEvent.php b/Classes/Event/Routing/PostProcessUriEvent.php index 23e728df36..37793f26ae 100644 --- a/Classes/Event/Routing/PostProcessUriEvent.php +++ b/Classes/Event/Routing/PostProcessUriEvent.php @@ -1,4 +1,5 @@ uri = $uri; } diff --git a/Classes/EventListener/EnhancedRouting/CachedPathVariableModifier.php b/Classes/EventListener/EnhancedRouting/CachedPathVariableModifier.php index 48963863cc..cb8ef5c981 100644 --- a/Classes/EventListener/EnhancedRouting/CachedPathVariableModifier.php +++ b/Classes/EventListener/EnhancedRouting/CachedPathVariableModifier.php @@ -1,4 +1,5 @@ getSolrRootlineForCategoryId($value)); + $results = array_merge( + $results, + $this->getSolrRootlineForCategoryId($value) + ); } return $results; @@ -84,13 +92,13 @@ public function process(array $values) * * @param int $categoryId Category ID to get a rootline as Solr hierarchy for * @return array Rootline as Solr hierarchy array + * @throws DBALDriverException + * @throws DBALException */ - protected function getSolrRootlineForCategoryId($categoryId) + protected function getSolrRootlineForCategoryId(int $categoryId): array { $categoryIdRootline = $this->buildCategoryIdRootline($categoryId); - $solrRootline = $this->buildSolrHierarchyFromIdRootline($categoryIdRootline); - - return $solrRootline; + return $this->buildSolrHierarchyFromIdRootline($categoryIdRootline); } /** @@ -98,11 +106,13 @@ protected function getSolrRootlineForCategoryId($categoryId) * * @param int $uid The category ID to build the rootline for * @return array Category ID rootline as array + * @throws DBALDriverException + * @throws DBALException */ - protected function buildCategoryIdRootline($uid) + protected function buildCategoryIdRootline(int $uid): array { $rootlineIds = []; - $parentCategory = intval($uid); + $parentCategory = $uid; while ($parentCategory !== 0) { $rootlineIds[] = $parentCategory; @@ -110,7 +120,7 @@ protected function buildCategoryIdRootline($uid) if ($childCategory === null) { $parentCategory = 0; } else { - $parentCategory = intval($childCategory['parent']); + $parentCategory = (int)($childCategory['parent']); } } krsort($rootlineIds); diff --git a/Classes/FieldProcessor/FieldProcessor.php b/Classes/FieldProcessor/FieldProcessor.php index e06f685b47..b333fa86b2 100644 --- a/Classes/FieldProcessor/FieldProcessor.php +++ b/Classes/FieldProcessor/FieldProcessor.php @@ -22,12 +22,11 @@ */ interface FieldProcessor { - /** * process method * * @param array $values Array of values, an array because of multivalued fields * @return array Modified array of values */ - public function process(array $values); + public function process(array $values): array; } diff --git a/Classes/FieldProcessor/PageUidToHierarchy.php b/Classes/FieldProcessor/PageUidToHierarchy.php index e2c9b0941f..08483803f5 100644 --- a/Classes/FieldProcessor/PageUidToHierarchy.php +++ b/Classes/FieldProcessor/PageUidToHierarchy.php @@ -1,5 +1,7 @@ getSolrRootlineForPageId( - /** @scrutinizer ignore-type */ - ...GeneralUtility::trimExplode( - ',', - $value, - true, - 2 - ) + (int)$rootPageUidAndMountPoint[0], + $rootPageUidAndMountPoint[1] ?? '' ); } @@ -80,12 +78,10 @@ public function process(array $values) * @param string $mountPoint The mount point parameter that will be used for building the rootline. * @return array Rootline as Solr hierarchy array */ - protected function getSolrRootlineForPageId($pageId, $mountPoint = '') + protected function getSolrRootlineForPageId(int $pageId, string $mountPoint = ''): array { $pageIdRootline = $this->buildPageIdRootline($pageId, $mountPoint); - $solrRootline = $this->buildSolrHierarchyFromIdRootline($pageIdRootline); - - return $solrRootline; + return $this->buildSolrHierarchyFromIdRootline($pageIdRootline); } /** @@ -95,14 +91,14 @@ protected function getSolrRootlineForPageId($pageId, $mountPoint = '') * @param string $mountPoint The mount point parameter that will be passed to getRootline(). * @return array Page Id rootline as array */ - protected function buildPageIdRootline($pageId, $mountPoint = '') + protected function buildPageIdRootline(int $pageId, string $mountPoint = ''): array { $rootlinePageIds = []; $rootlineUtility = GeneralUtility::makeInstance(RootlineUtility::class, $pageId, $mountPoint); try { $rootline = $rootlineUtility->get(); - } catch (\RuntimeException $e) { + } catch (RuntimeException $e) { $rootline = []; } diff --git a/Classes/FieldProcessor/PathToHierarchy.php b/Classes/FieldProcessor/PathToHierarchy.php index dd1be8fe94..d75828ed25 100644 --- a/Classes/FieldProcessor/PathToHierarchy.php +++ b/Classes/FieldProcessor/PathToHierarchy.php @@ -1,5 +1,7 @@ @@ -32,14 +31,16 @@ */ class Service { - /** * Modifies a list of documents * * @param Document[] $documents * @param array $processingConfiguration + * @throws DBALDriverException + * @throws DBALException */ - public function processDocuments(array $documents, array $processingConfiguration) { + public function processDocuments(array $documents, array $processingConfiguration) + { foreach ($documents as $document) { $this->processDocument($document, $processingConfiguration); } @@ -50,8 +51,11 @@ public function processDocuments(array $documents, array $processingConfiguratio * * @param Document $document * @param array $processingConfiguration + * @throws DBALDriverException + * @throws DBALException */ - public function processDocument(Document $document, array $processingConfiguration) { + public function processDocument(Document $document, array $processingConfiguration) + { foreach ($processingConfiguration as $fieldName => $instruction) { $fieldValue = $document[$fieldName] ?? false; $isSingleValueField = false; diff --git a/Classes/FieldProcessor/TimestampToIsoDate.php b/Classes/FieldProcessor/TimestampToIsoDate.php index b64488beea..8e6cf8e756 100644 --- a/Classes/FieldProcessor/TimestampToIsoDate.php +++ b/Classes/FieldProcessor/TimestampToIsoDate.php @@ -1,5 +1,7 @@ timestampToIso($timestamp); + $results[] = $formatService->timestampToIso((int)$timestamp); } return $results; diff --git a/Classes/FieldProcessor/TimestampToUtcIsoDate.php b/Classes/FieldProcessor/TimestampToUtcIsoDate.php index 2fba392910..0ab72ab602 100644 --- a/Classes/FieldProcessor/TimestampToUtcIsoDate.php +++ b/Classes/FieldProcessor/TimestampToUtcIsoDate.php @@ -1,5 +1,7 @@ siteFinder->getSiteByPageId($pageId); // $siteLanguage and $languageAspect takes the language id into account. // See: $site->getLanguageById($language); @@ -241,11 +262,10 @@ public function getTsfeByPageIdIgnoringLanguage(int $pageId): ?TypoScriptFronten { try { $typo3Site = $this->siteFinder->getSiteByPageId($pageId); - } catch (Throwable $e) - { + } catch (Throwable $e) { return null; } - $availableLanguageIds = array_map(function($siteLanguage) { + $availableLanguageIds = array_map(function ($siteLanguage) { return $siteLanguage->getLanguageId(); }, $typo3Site->getLanguages()); @@ -291,7 +311,7 @@ public function getServerRequestForTsfeByPageIdAndLanguageId(int $pageId, int $l protected function assureIsInitialized(int $pageId, int $language, ?int $rootPageId = null): void { $cacheIdentifier = $this->getCacheIdentifier($pageId, $language, $rootPageId); - if(!array_key_exists($cacheIdentifier, $this->tsfeCache)) { + if (!array_key_exists($cacheIdentifier, $this->tsfeCache)) { $this->initializeTsfe($pageId, $language, $rootPageId); return; } @@ -349,7 +369,8 @@ protected function getPidToUseForTsfeInitialization(int $pidToUse, ?int $rootPag "The closest page with active template to page \"$askedPid\" could not be resolved and alternative rootPageId is not provided.", 1637339439 ); - } else if (isset($rootPageId)) { + } + if (isset($rootPageId)) { return $rootPageId; } return $this->getPidToUseForTsfeInitialization($pidToUse, $rootPageId); diff --git a/Classes/FrontendEnvironment/TypoScript.php b/Classes/FrontendEnvironment/TypoScript.php index 7c8d4afecf..cc020b8a71 100644 --- a/Classes/FrontendEnvironment/TypoScript.php +++ b/Classes/FrontendEnvironment/TypoScript.php @@ -1,5 +1,7 @@ configurationObjectCache[$cacheId])) { return $this->configurationObjectCache[$cacheId]; @@ -72,7 +76,6 @@ public function getConfigurationFromPageId(int $pageId, string $path, int $langu $cache = GeneralUtility::makeInstance(TwoLevelCache::class, /** @scrutinizer ignore-type */ 'tx_solr_configuration'); $configurationArray = $cache->get($cacheId); - if (!empty($configurationArray)) { // we have a cache hit and can return it. return $this->configurationObjectCache[$cacheId] = $this->buildTypoScriptConfigurationFromArray($configurationArray, $pageId, $language, $path); @@ -111,7 +114,6 @@ protected function buildConfigurationArray(int $pageId, string $path, int $langu return $getConfigurationFromInitializedTSFEAndWriteToCache[0] ?? []; } - /** * @param array $theSetup * @param string $theKey @@ -146,5 +148,4 @@ protected function buildTypoScriptConfigurationFromArray(array $configurationToU $configurationManager = GeneralUtility::makeInstance(ConfigurationManager::class); return $configurationManager->getTypoScriptConfiguration($configurationToUse, $pageId, $languageId, $typoScriptPath); } - } diff --git a/Classes/GarbageCollector.php b/Classes/GarbageCollector.php index 868d851e6b..856806a9fd 100644 --- a/Classes/GarbageCollector.php +++ b/Classes/GarbageCollector.php @@ -1,5 +1,7 @@ getGarbageHandler()->collectGarbage((string)$table, (int)$uid); + $this->getGarbageHandler()->collectGarbage($table, $uid); } /** @@ -103,8 +108,11 @@ public function collectGarbage($table, $uid): void * @param int $uid The record's uid * @param string $value Not used * @param DataHandler $tceMain TYPO3 Core Engine parent object, not used + * @noinspection PhpMissingParamTypeInspection + * @noinspection PhpUnusedParameterInspection */ - public function processCmdmap_postProcess($command, $table, $uid, $value, DataHandler $tceMain) { + public function processCmdmap_postProcess($command, $table, $uid, $value, DataHandler $tceMain) + { // workspaces: collect garbage only for LIVE workspace if ($command === 'move' && $table === 'pages' && ($GLOBALS['BE_USER']->workspace ?? null) == 0) { $this->eventDispatcher->dispatch( @@ -122,6 +130,8 @@ public function processCmdmap_postProcess($command, $table, $uid, $value, DataHa * @param string $table The table the record belongs to * @param mixed $uid The record's uid, [integer] or [string] (like 'NEW...') * @param DataHandler $tceMain TYPO3 Core Engine parent object, not used + * @noinspection PhpMissingParamTypeInspection + * @noinspection PhpUnusedParameterInspection */ public function processDatamap_preProcessFieldArray($incomingFields, $table, $uid, DataHandler $tceMain): void { @@ -164,6 +174,8 @@ public function processDatamap_preProcessFieldArray($incomingFields, $table, $ui * @param mixed $uid The record's uid, [integer] or [string] (like 'NEW...') * @param array $fields The record's data, not used * @param DataHandler $tceMain TYPO3 Core Engine parent object, not used + * @noinspection PhpMissingParamTypeInspection + * @noinspection PhpUnusedParameterInspection */ public function processDatamap_afterDatabaseOperations($status, $table, $uid, array $fields, DataHandler $tceMain): void { @@ -195,7 +207,7 @@ public function processDatamap_afterDatabaseOperations($status, $table, $uid, ar } /** - * Checks whether the a frontend group field exists for the record and if so + * Checks whether the frontend group field exists for the record and if so * whether groups have been removed from accessing the record thus making * the record invisible to at least some people. * diff --git a/Classes/GarbageCollectorPostProcessor.php b/Classes/GarbageCollectorPostProcessor.php index cb3bc0f35d..2801bf9650 100644 --- a/Classes/GarbageCollectorPostProcessor.php +++ b/Classes/GarbageCollectorPostProcessor.php @@ -1,5 +1,7 @@ collectGarbage() + * @see \ApacheSolrForTypo3\Solr\GarbageCollector::collectGarbage() */ - public function postProcessGarbageCollector($table, $uid); + public function postProcessGarbageCollector(string $table, int $uid); } diff --git a/Classes/HtmlContentExtractor.php b/Classes/HtmlContentExtractor.php index 47203b8a71..c6c63dd0cf 100644 --- a/Classes/HtmlContentExtractor.php +++ b/Classes/HtmlContentExtractor.php @@ -24,7 +24,6 @@ */ class HtmlContentExtractor { - /** * Unicode ranges which should get stripped before sending a document to solr. * This is necessary if a document (PDF, etc.) contains unicode characters which @@ -38,7 +37,7 @@ class HtmlContentExtractor * @see http://en.wikipedia.org/wiki/Unicode_block * @var array */ - protected static $stripUnicodeRanges = [ + protected static array $stripUnicodeRanges = [ ['FFFD', 'FFFD'], // Replacement Character (�) @see http://en.wikipedia.org/wiki/Specials_%28Unicode_block%29 ['E000', 'F8FF'], @@ -48,18 +47,20 @@ class HtmlContentExtractor ['100000', '10FFFF'], // Supplementary Private Use Area (Plane 16) ]; + /** * The raw HTML markup content to extract clean content from. * * @var string */ - protected $content; + protected string $content = ''; + /** * Mapping of HTML tags to Solr document fields. * * @var array */ - protected $tagToFieldMapping = [ + protected array $tagToFieldMapping = [ 'h1' => 'tagsH1', 'h2' => 'tagsH2H3', 'h3' => 'tagsH2H3', @@ -75,27 +76,27 @@ class HtmlContentExtractor ]; /** - * @var TypoScriptConfiguration + * @var TypoScriptConfiguration|null */ - private $configuration; + protected ?TypoScriptConfiguration $configuration = null; /** * Constructor. * * @param string $content Content HTML markup */ - public function __construct($content) + public function __construct(string $content) { // @extensionScannerIgnoreLine $this->content = $content; } /** - * @return TypoScriptConfiguration|array + * @return TypoScriptConfiguration */ - protected function getConfiguration() + protected function getConfiguration(): TypoScriptConfiguration { - if ($this->configuration == null) { + if ($this->configuration === null) { $this->configuration = Util::getSolrConfiguration(); } @@ -118,13 +119,11 @@ public function setConfiguration(TypoScriptConfiguration $configuration) * * @return string Indexable, cleaned content ready for indexing. */ - public function getIndexableContent() + public function getIndexableContent(): string { // @extensionScannerIgnoreLine $content = self::cleanContent($this->content); - $content = trim($content); - - return $content; + return trim($content); } /** @@ -138,10 +137,10 @@ public static function cleanContent(string $content): string { $content = self::stripControlCharacters($content); // remove Javascript - $content = preg_replace('@]*>.*?<\/script>@msi', '', $content); + $content = preg_replace('@]*>.*?@msi', '', $content); // remove internal CSS styles - $content = preg_replace('@]*>.*?<\/style>@msi', '', $content); + $content = preg_replace('@]*>.*?@msi', '', $content); // prevents concatenated words when stripping tags afterwards $content = str_replace(['<', '>'], [' <', '> '], $content); @@ -162,7 +161,7 @@ public static function cleanContent(string $content): string * @return string the sanitized content * @see http://w3.org/International/questions/qa-forms-utf-8.html */ - public static function stripControlCharacters($content) + public static function stripControlCharacters(string $content): string { // Printable utf-8 does not include any of these chars below x7F return preg_replace('@[\x00-\x08\x0B\x0C\x0E-\x1F]@', ' ', $content); @@ -174,12 +173,11 @@ public static function stripControlCharacters($content) * @param string $content Content to sanitize * @return string Sanitized content */ - public static function stripUnicodeRanges($content) + public static function stripUnicodeRanges(string $content): string { foreach (self::$stripUnicodeRanges as $range) { $content = self::stripUnicodeRange($content, $range[0], $range[1]); } - return $content; } @@ -190,11 +188,15 @@ public static function stripUnicodeRanges($content) * @param string $start Unicode range start character as uppercase hexadecimal string * @param string $end Unicode range end character as uppercase hexadecimal string * @return string Sanitized content + * @noinspection Annotator */ - public static function stripUnicodeRange($content, $start, $end) + public static function stripUnicodeRange(string $content, string $start, string $end): string { - return preg_replace('/[\x{' . $start . '}-\x{' . $end . '}]/u', '', - $content); + return preg_replace( + '/[\x{' . $start . '}-\x{' . $end . '}]/u', + '', + $content + ); } /** @@ -202,7 +204,7 @@ public static function stripUnicodeRange($content, $start, $end) * * @return string Content marked for indexing. */ - public function getContentMarkedForIndexing() + public function getContentMarkedForIndexing(): string { // @extensionScannerIgnoreLine return $this->content; @@ -213,7 +215,7 @@ public function getContentMarkedForIndexing() * * @return array A mapping of Solr document field names to content found in defined tags. */ - public function getTagContent() + public function getTagContent(): array { $result = []; $matches = []; @@ -226,8 +228,10 @@ public function getTagContent() ); preg_match_all( - '@<(' . implode('|', - array_keys($this->tagToFieldMapping)) . ')[^>]*>(.*)@Ui', + '@<(' . implode( + '|', + array_keys($this->tagToFieldMapping) + ) . ')[^>]*>(.*)@Ui', $content, $matches ); diff --git a/Classes/IndexQueue/AbstractIndexer.php b/Classes/IndexQueue/AbstractIndexer.php index 587e11b2b5..23bb6afa45 100644 --- a/Classes/IndexQueue/AbstractIndexer.php +++ b/Classes/IndexQueue/AbstractIndexer.php @@ -1,5 +1,7 @@ isSerializedValue($indexingConfiguration, - $solrFieldName) + if ($this->isSerializedValue( + $indexingConfiguration, + $solrFieldName + ) ) { $fieldValue = unserialize($fieldValue); } } elseif ( substr($indexingConfiguration[$solrFieldName], 0, 1) === '<' ) { - $referencedTsPath = trim(substr($indexingConfiguration[$solrFieldName], - 1)); + $referencedTsPath = trim(substr( + $indexingConfiguration[$solrFieldName], + 1 + )); $typoScriptParser = GeneralUtility::makeInstance(TypoScriptParser::class); // $name and $conf is loaded with the referenced values. list($name, $conf) = $typoScriptParser->getVal($referencedTsPath, $GLOBALS['TSFE']->tmpl->setup); @@ -170,13 +174,15 @@ protected function resolveFieldValue( $backupWorkingDirectory = getcwd(); chdir(Environment::getPublicPath() . '/'); - $tsfe->start($data, $this->type); - $fieldValue = $tsfe->cObjGetSingle($name, $conf); + $tsfe->cObj->start($data, $this->type); + $fieldValue = $tsfe->cObj->cObjGetSingle($name, $conf); chdir($backupWorkingDirectory); - if ($this->isSerializedValue($indexingConfiguration, - $solrFieldName) + if ($this->isSerializedValue( + $indexingConfiguration, + $solrFieldName + ) ) { $fieldValue = unserialize($fieldValue); } @@ -187,12 +193,17 @@ protected function resolveFieldValue( // detect and correct type for dynamic fields // find last underscore, substr from there, cut off last character (S/M) - $fieldType = substr($solrFieldName, strrpos($solrFieldName, '_') + 1, - -1); + $fieldType = substr( + $solrFieldName, + strrpos($solrFieldName, '_') + 1, + -1 + ); if (is_array($fieldValue)) { foreach ($fieldValue as $key => $value) { - $fieldValue[$key] = $this->ensureFieldValueType($value, - $fieldType); + $fieldValue[$key] = $this->ensureFieldValueType( + $value, + $fieldType + ); } } else { $fieldValue = $this->ensureFieldValueType($fieldValue, $fieldType); @@ -282,17 +293,17 @@ protected static function isSerializedResultFromRegisteredHook(array $indexingCo * @param string $fieldType The dynamic field's type * @return mixed Returns the value in the correct format for the field type */ - protected function ensureFieldValueType($value, $fieldType) + protected function ensureFieldValueType($value, string $fieldType) { switch ($fieldType) { case 'int': case 'tInt': - $value = intval($value); + $value = (int)$value; break; case 'float': case 'tFloat': - $value = floatval($value); + $value = (float)$value; break; // long and double do not exist in PHP diff --git a/Classes/IndexQueue/FrontendHelper/AbstractFrontendHelper.php b/Classes/IndexQueue/FrontendHelper/AbstractFrontendHelper.php index 92d6786fc4..1bd3d7604c 100644 --- a/Classes/IndexQueue/FrontendHelper/AbstractFrontendHelper.php +++ b/Classes/IndexQueue/FrontendHelper/AbstractFrontendHelper.php @@ -1,5 +1,7 @@ no_cache = true; } diff --git a/Classes/IndexQueue/FrontendHelper/AuthorizationService.php b/Classes/IndexQueue/FrontendHelper/AuthorizationService.php index 2ccf35a0e7..b1be05fdec 100644 --- a/Classes/IndexQueue/FrontendHelper/AuthorizationService.php +++ b/Classes/IndexQueue/FrontendHelper/AuthorizationService.php @@ -1,5 +1,7 @@ 0, 'username' => self::SOLR_INDEXER_USERNAME, - 'authenticated' => true + 'authenticated' => true, ]; } @@ -61,11 +62,11 @@ public function getUser() * conduct other services that might be registered for "their opinion" * whether a user is authenticated. * - * @see \TYPO3\CMS\Core\Authentication\AbstractUserAuthentication::checkAuthentication() * @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() */ - public function authUser($user) + public function authUser(array $user): int { // shouldn't happen, but in case we get a regular user we just // pass it on to another (regular) auth service @@ -84,16 +85,16 @@ public function authUser($user) * * @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 mixed Groups array, keys = uid which must be unique + * @return array Groups array, keys = uid which must be unique */ public function getGroups( - $user, + array $user, /** @noinspection PhpUnusedParameterInspection */ - $knownGroups - ) { + array $knownGroups = [] + ): array { $groupData = []; - /** @var $requestHandler PageIndexerRequestHandler */ + /** @var $requestHandler PageIndexerRequestHandler */ $requestHandler = GeneralUtility::makeInstance(PageIndexerRequestHandler::class); $accessRootline = $requestHandler->getRequest()->getParameter('accessRootline'); @@ -107,7 +108,7 @@ public function getGroups( 'uid' => $groupId, 'pid' => 0, 'title' => '__SolrIndexerGroup__', - 'TSconfig' => '' + 'TSconfig' => '', ]; } } diff --git a/Classes/IndexQueue/FrontendHelper/Dispatcher.php b/Classes/IndexQueue/FrontendHelper/Dispatcher.php index c2c3441f26..39db8e3281 100644 --- a/Classes/IndexQueue/FrontendHelper/Dispatcher.php +++ b/Classes/IndexQueue/FrontendHelper/Dispatcher.php @@ -1,5 +1,7 @@ pageIndexingConfigurationName = $pageIndexingConfigurationName; } @@ -65,19 +67,18 @@ public function setPageIndexingConfigurationName($pageIndexingConfigurationName) * Uses the original document and adds fields as defined in * plugin.tx_solr.index.queue.pages.fields. * - * @param Document $pageDocument The original page document. + * @param Document $originalPageDocument The original page document. * @return Document A Apache Solr Document object that replace the default page document */ - public function getPageDocument(Document $pageDocument) + public function getPageDocument(Document $originalPageDocument): Document { - $substitutePageDocument = clone $pageDocument; - + $substitutePageDocument = clone $originalPageDocument; - $mappedFields = $this->getMappedFields($pageDocument); + $mappedFields = $this->getMappedFields($originalPageDocument); foreach ($mappedFields as $fieldName => $fieldValue) { if (isset($substitutePageDocument->{$fieldName})) { // reset = overwrite, especially important to not make fields - // multi valued where they may not accept multiple values + // multivalued where they may not accept multiple values unset($substitutePageDocument->{$fieldName}); } @@ -97,7 +98,7 @@ public function getPageDocument(Document $pageDocument) * @param Document $pageDocument The original page document. * @return array An array mapping field names to their values. */ - protected function getMappedFields(Document $pageDocument) + protected function getMappedFields(Document $pageDocument): array { $fields = []; @@ -120,12 +121,12 @@ protected function getMappedFields(Document $pageDocument) * Resolves a field mapping to its value depending on its configuration. * * Allows to put the page record through cObj processing if wanted / needed. - * Otherwise the plain page record field value is used. + * 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 The resolved string value to be indexed + * @return string|array The resolved string value to be indexed */ - protected function resolveFieldValue($solrFieldName, Document $pageDocument) + protected function resolveFieldValue(string $solrFieldName, Document $pageDocument) { $pageRecord = $GLOBALS['TSFE']->page; diff --git a/Classes/IndexQueue/FrontendHelper/PageIndexer.php b/Classes/IndexQueue/FrontendHelper/PageIndexer.php index af57b95bb6..e6e26d38fa 100644 --- a/Classes/IndexQueue/FrontendHelper/PageIndexer.php +++ b/Classes/IndexQueue/FrontendHelper/PageIndexer.php @@ -24,9 +24,10 @@ use ApacheSolrForTypo3\Solr\System\Solr\SolrConnection; use ApacheSolrForTypo3\Solr\Typo3PageIndexer; use ApacheSolrForTypo3\Solr\Util; +use Doctrine\DBAL\Driver\Exception as DBALDriverException; +use Doctrine\DBAL\Exception as DBALException; use Throwable; use TYPO3\CMS\Core\Context\Exception\AspectNotFoundException; -use TYPO3\CMS\Core\Log\Logger; use TYPO3\CMS\Core\SingletonInterface; use TYPO3\CMS\Core\Utility\ExtensionManagementUtility; use TYPO3\CMS\Core\Utility\GeneralUtility; @@ -48,26 +49,21 @@ class PageIndexer extends AbstractFrontendHelper implements SingletonInterface * * @var string */ - protected $action = 'indexPage'; + protected string $action = 'indexPage'; /** * the page currently being indexed. * * @var TypoScriptFrontendController */ - protected $page; + protected TypoScriptFrontendController $page; /** * Response data * * @var array */ - protected $responseData = []; - - /** - * @var Logger - */ - protected $logger = null; + protected array $responseData = []; /** * Activates a frontend helper by registering for hooks and other @@ -93,19 +89,18 @@ public function activate() * @return array Page indexed status. * @noinspection PhpUnused */ - public function getData() + public function getData(): array { return $this->responseData; } - # - # Indexer authorisation for access restricted pages / content - # + // + // Indexer authorisation for access restricted pages / content + // /** * Fakes a logged in user to retrieve access restricted content. * - * @return void * @noinspection PhpUnused */ public function authorizeFrontendUser() @@ -129,7 +124,7 @@ public function authorizeFrontendUser() $this->responseData['authorization'] = [ 'username' => $GLOBALS['TSFE']->fe_user->user['username'], - 'usergroups' => $GLOBALS['TSFE']->fe_user->user['usergroup'] + 'usergroups' => $GLOBALS['TSFE']->fe_user->user['usergroup'], ]; } @@ -138,7 +133,7 @@ public function authorizeFrontendUser() * * @return Rootline The access rootline to use for indexing. */ - protected function getAccessRootline() + protected function getAccessRootline(): Rootline { $stringAccessRootline = ''; @@ -146,15 +141,12 @@ protected function getAccessRootline() $stringAccessRootline = $this->request->getParameter('accessRootline'); } - /** @noinspection PhpIncompatibleReturnTypeInspection */ return GeneralUtility::makeInstance(Rootline::class, /** @scrutinizer ignore-type */ $stringAccessRootline); } /** * Registers an authentication service to authorize / grant the indexer to * access protected pages. - * - * @return void */ protected function registerAuthorizationService() { @@ -190,7 +182,7 @@ protected function registerAuthorizationService() * * @return int Highest priority of all registered authentication service */ - protected function getHighestAuthenticationServicePriority() + protected function getHighestAuthenticationServicePriority(): int { $highestPriority = 0; @@ -205,9 +197,9 @@ protected function getHighestAuthenticationServicePriority() return $highestPriority; } - # - # Indexing - # + // + // Indexing + // /** * Generates the current page's URL. @@ -216,18 +208,18 @@ protected function getHighestAuthenticationServicePriority() * * @return string URL of the current page. */ - protected function generatePageUrl() + protected function generatePageUrl(): string { if ($this->request->getParameter('overridePageUrl')) { return $this->request->getParameter('overridePageUrl'); } - /** @var $contentObject ContentObjectRenderer */ + /** @var $contentObject ContentObjectRenderer */ $contentObject = GeneralUtility::makeInstance(ContentObjectRenderer::class); $typolinkConfiguration = [ - 'parameter' => intval($this->page->id), - 'linkAccessRestrictedPages' => '1' + 'parameter' => (int)($this->page->id), + 'linkAccessRestrictedPages' => '1', ]; $language = GeneralUtility::_GET('L'); @@ -252,6 +244,7 @@ protected function generatePageUrl() * @param array $params unused * @param TypoScriptFrontendController $page TypoScript frontend * @noinspection PhpUnused + * @noinspection PhpUnusedParameterInspection */ public function hook_indexContent(array $params, TypoScriptFrontendController $page) { @@ -292,7 +285,7 @@ public function hook_indexContent(array $params, TypoScriptFrontendController $p $this->responseData['solrConnection'] = [ 'rootPage' => $indexQueueItem->getRootPageUid(), 'sys_language_uid' => Util::getLanguageUid(), - 'solr' => (string)$solrConnection->getNode('write') + 'solr' => (string)$solrConnection->getNode('write'), ]; $documentsSentToSolr = $indexer->getDocumentsSentToSolr(); @@ -305,7 +298,7 @@ public function hook_indexContent(array $params, TypoScriptFrontendController $p SolrLogManager::ERROR, 'Exception while trying to index page ' . $page->id, [ - $e->__toString() + $e->__toString(), ] ); } @@ -329,10 +322,11 @@ public function hook_indexContent(array $params, TypoScriptFrontendController $p * * @param Item $indexQueueItem * @return SolrConnection Solr server connection - * @throws NoSolrConnectionFoundException * @throws AspectNotFoundException + * @throws NoSolrConnectionFoundException + * @throws DBALDriverException */ - protected function getSolrConnection(Item $indexQueueItem) + protected function getSolrConnection(Item $indexQueueItem): SolrConnection { /** @var $connectionManager ConnectionManager */ $connectionManager = GeneralUtility::makeInstance(ConnectionManager::class); @@ -346,9 +340,11 @@ protected function getSolrConnection(Item $indexQueueItem) /** * This method retrieves the item from the index queue, that is indexed in this request. * - * @return Item + * @return Item|null + * @throws DBALDriverException + * @throws DBALException|\Doctrine\DBAL\DBALException */ - protected function getIndexQueueItem() + protected function getIndexQueueItem(): ?Item { /** @var $indexQueue Queue */ $indexQueue = GeneralUtility::makeInstance(Queue::class); diff --git a/Classes/IndexQueue/FrontendHelper/UserGroupDetector.php b/Classes/IndexQueue/FrontendHelper/UserGroupDetector.php index 79b51b033a..1d5971b717 100644 --- a/Classes/IndexQueue/FrontendHelper/UserGroupDetector.php +++ b/Classes/IndexQueue/FrontendHelper/UserGroupDetector.php @@ -1,5 +1,7 @@ originalTca = $GLOBALS['TCA']; @@ -143,27 +139,29 @@ public function getPage_preProcess( * Modifies page records so that when checking for access through fe groups * no groups or extendToSubpages flag is found and thus access is granted. * - * @param array $pageRecord Page record - * @param int $languageUid Overlay language ID - * @param PageRepository $parentObject Parent \TYPO3\CMS\Core\Domain\Repository\PageRepository object + * @param array $pageInput Page record + * @param int $lUid Overlay language ID + * @param PageRepository $parent Parent \TYPO3\CMS\Core\Domain\Repository\PageRepository object */ public function getPageOverlay_preProcess( - &$pageRecord, - &$languageUid, - PageRepository $parentObject + &$pageInput, + &$lUid, + PageRepository $parent ) { - if (is_array($pageRecord)) { - $pageRecord['fe_group'] = ''; - $pageRecord['extendToSubpages'] = '0'; + if (!is_array($pageInput)) { + return; } + $pageInput['fe_group'] = ''; + $pageInput['extendToSubpages'] = '0'; } // execution /** - * Hook for post processing the initialization of ContentObjectRenderer + * Hook for post-processing the initialization of ContentObjectRenderer * * @param ContentObjectRenderer $parentObject parent content object + * @noinspection PhpParameterByRefIsNotUsedAsReferenceInspection */ public function postProcessContentObjectInitialization(ContentObjectRenderer &$parentObject) { @@ -177,12 +175,12 @@ public function postProcessContentObjectInitialization(ContentObjectRenderer &$p } /** - * Tracks user groups access restriction applied to records. + * Tracks user groups access restriction applied to the records. * * @param array $record A record as an array of fieldname => fieldvalue mappings * @param string $table Table name the record belongs to */ - protected function findFrontendGroups($record, $table) + protected function findFrontendGroups(array $record, string $table) { if ($this->originalTca[$table]['ctrl']['enablecolumns']['fe_group']) { $frontendGroups = $record[$this->originalTca[$table]['ctrl']['enablecolumns']['fe_group']]; @@ -214,11 +212,14 @@ protected function findFrontendGroups($record, $table) * * @return array Array of user group IDs */ - protected function getFrontendGroups() + protected function getFrontendGroups(): array { $frontendGroupsList = implode(',', $this->frontendGroups); - $frontendGroups = GeneralUtility::trimExplode(',', $frontendGroupsList, - true); + $frontendGroups = GeneralUtility::trimExplode( + ',', + $frontendGroupsList, + true + ); // clean up: filter double groups $frontendGroups = array_unique($frontendGroups); @@ -231,9 +232,7 @@ protected function getFrontendGroups() // Index user groups first sort($frontendGroups, SORT_NUMERIC); - $frontendGroups = array_reverse($frontendGroups); - - return $frontendGroups; + return array_reverse($frontendGroups); } /** @@ -241,7 +240,7 @@ protected function getFrontendGroups() * * @return array Array of user groups. */ - public function getData() + public function getData(): array { return $this->getFrontendGroups(); } diff --git a/Classes/IndexQueue/Indexer.php b/Classes/IndexQueue/Indexer.php index 9842d3764c..e2bb38335b 100644 --- a/Classes/IndexQueue/Indexer.php +++ b/Classes/IndexQueue/Indexer.php @@ -1,5 +1,7 @@ options = $options; $this->pagesRepository = $pagesRepository ?? GeneralUtility::makeInstance(PagesRepository::class); $this->documentBuilder = $documentBuilder ?? GeneralUtility::makeInstance(Builder::class); @@ -129,8 +132,13 @@ public function __construct( * * @param Item $item An index queue item * @return bool returns true when indexed, false when not + * @throws DBALDriverException + * @throws DBALException + * @throws FrontendEnvironmentException + * @throws NoSolrConnectionFoundException + * @throws SiteNotFoundException */ - public function index(Item $item) + public function index(Item $item): bool { $indexed = true; @@ -163,8 +171,9 @@ public function index(Item $item) * @param Item $item An index queue item to index. * @param int $language The language to use. * @return bool TRUE if item was indexed successfully, FALSE on failure - * @throws InternalServerErrorException - * @throws ServiceUnavailableException + * @throws DBALDriverException + * @throws DBALException + * @throws FrontendEnvironmentException * @throws SiteNotFoundException */ protected function indexItem(Item $item, int $language = 0): bool @@ -172,7 +181,6 @@ protected function indexItem(Item $item, int $language = 0): bool $itemIndexed = false; $documents = []; - $itemDocument = $this->itemToDocument($item, $language); if (is_null($itemDocument)) { /* @@ -195,7 +203,7 @@ protected function indexItem(Item $item, int $language = 0): bool $itemIndexed = true; } } catch (HttpException $e) { - $response = new ResponseAdapter($e->getBody(), $httpStatus = 500, $e->getStatusMessage()); + $response = new ResponseAdapter($e->getBody(), 500, $e->getStatusMessage()); } $this->log($item, $documents, $response); @@ -212,9 +220,9 @@ protected function indexItem(Item $item, int $language = 0): bool * * @param Item $item The item to be indexed * @param int $language Language Id (sys_language.uid) - * @return array|NULL The full record with fields of data to be used for indexing or NULL to prevent an item from being indexed - * @throws InternalServerErrorException - * @throws ServiceUnavailableException + * @return array|null The full record with fields of data to be used for indexing or NULL to prevent an item from being indexed + * @throws DBALDriverException + * @throws FrontendEnvironmentException * @throws SiteNotFoundException */ protected function getFullItemRecord(Item $item, int $language = 0): ?array @@ -235,7 +243,7 @@ protected function getFullItemRecord(Item $item, int $language = 0): ?array * @param int $language * @return array|mixed|null * @throws DBALDriverException - * @throws FrontendEnvironment\Exception\Exception + * @throws FrontendEnvironmentException * @throws SiteNotFoundException */ protected function getItemRecordOverlayed(Item $item, int $language): ?array @@ -243,7 +251,7 @@ protected function getItemRecordOverlayed(Item $item, int $language): ?array $itemRecord = $item->getRecord(); $languageField = $GLOBALS['TCA'][$item->getType()]['ctrl']['languageField'] ?? null; // skip "free content mode"-record for other languages, if item is a "free content mode"-record - if ($this->isAFreeContentModeItemRecord($item, $language) + if ($this->isAFreeContentModeItemRecord($item) && isset($languageField) && (int)($itemRecord[$languageField] ?? null) !== $language ) { @@ -266,21 +274,16 @@ protected function getItemRecordOverlayed(Item $item, int $language): ?array /** * @param Item $item - * @param int $language * * @return bool */ - protected function isAFreeContentModeItemRecord(Item $item, int $language): bool + protected function isAFreeContentModeItemRecord(Item $item): bool { $languageField = $GLOBALS['TCA'][$item->getType()]['ctrl']['languageField'] ?? null; $itemRecord = $item->getRecord(); - if (isset($languageField) + return isset($languageField) && (int)($itemRecord[$languageField] ?? null) > 0 - && $this->isLanguageInAFreeContentMode($item, (int)($itemRecord[$languageField] ?? null)) - ) { - return true; - } - return false; + && $this->isLanguageInAFreeContentMode($item, (int)($itemRecord[$languageField] ?? null)); } /** @@ -288,8 +291,8 @@ protected function isAFreeContentModeItemRecord(Item $item, int $language): bool * * @param Item $item An index queue item * @param int $language Language ID - * @throws RuntimeException * @return array Configuration array from TypoScript + * @throws DBALDriverException */ protected function getItemTypeConfiguration(Item $item, int $language = 0): array { @@ -310,7 +313,7 @@ protected function getItemTypeConfiguration(Item $item, int $language = 0): arra * The method retrieves the field configuration of the items record page id (pid). * * @param Item $item - * @param integer $language + * @param int $language * @param string $indexConfigurationName * @return array */ @@ -320,7 +323,7 @@ protected function getFieldConfigurationFromItemRecordPage(Item $item, int $lang $pageId = $this->getPageIdOfItem($item); $solrConfiguration = $this->frontendEnvironment->getSolrConfigurationFromPageId($pageId, $language, $item->getRootPageUid()); return $solrConfiguration->getIndexQueueFieldsConfigurationByConfigurationName($indexConfigurationName, []); - } catch (\Throwable $e) { + } catch (Throwable $e) { return []; } } @@ -341,9 +344,10 @@ protected function getPageIdOfItem(Item $item): int * The method returns the field configuration of the items root page id (uid of the related root page). * * @param Item $item - * @param integer $language + * @param int $language * @param string $indexConfigurationName * @return array + * @throws DBALDriverException */ protected function getFieldConfigurationFromItemRootPage(Item $item, int $language, string $indexConfigurationName): array { @@ -353,7 +357,7 @@ protected function getFieldConfigurationFromItemRootPage(Item $item, int $langua } /** - * In case of additionalStoragePid config recordPageId can be outside of siteroot. + * In case of additionalStoragePid config recordPageId can be outside siteroot. * In that case we should not read TS config of foreign siteroot. * * @param Item $item @@ -366,7 +370,7 @@ protected function isRootPageIdPartOfRootLine(Item $item): bool $rootlineUtility = GeneralUtility::makeInstance(RootlineUtility::class, $buildRootlineWithPid); $rootline = $rootlineUtility->get(); - $pageInRootline = array_filter($rootline, function($page) use ($rootPageId) { + $pageInRootline = array_filter($rootline, function ($page) use ($rootPageId) { return (int)$page['uid'] === $rootPageId; }); return !empty($pageInRootline); @@ -381,10 +385,9 @@ protected function isRootPageIdPartOfRootLine(Item $item): bool * * @return Document|null The Solr document converted from the record * - * @throws InternalServerErrorException - * @throws ServiceUnavailableException + * @throws DBALDriverException + * @throws FrontendEnvironmentException * @throws SiteNotFoundException - * @throws Exception */ protected function itemToDocument(Item $item, int $language = 0): ?Document { @@ -421,7 +424,7 @@ protected function getBaseDocument(Item $item, array $itemRecord): Document * Generates an Access Rootline for an item. * * @param Item $item Index Queue item to index. - * @return string The Access Rootline for the item + * @return mixed|string The Access Rootline for the item */ protected function getAccessRootline(Item $item) { @@ -448,12 +451,14 @@ protected function getAccessRootline(Item $item) * * @param Item $item An index queue item * @param array $documents An array of \ApacheSolrForTypo3\Solr\System\Solr\Document\Document objects to manipulate. - * @return Document[] array Array of manipulated Document objects. + * @return Document[] An array of manipulated Document objects. + * @throws DBALDriverException + * @throws DBALException */ - protected function processDocuments(Item $item, array $documents) + protected function processDocuments(Item $item, array $documents): array { - // needs to respect the TS settings for the page the item is on, conditions may apply - $solrConfiguration = $this->frontendEnvironment->getSolrConfigurationFromPageId($item->getRootPageUid()); +// // needs to respect the TS settings for the page the item is on, conditions may apply +// $solrConfiguration = $this->frontendEnvironment->getSolrConfigurationFromPageId($item->getRootPageUid()); $siteRepository = GeneralUtility::makeInstance(SiteRepository::class); $solrConfiguration = $siteRepository->getSiteByPageId($item->getRootPageUid())->getSolrConfiguration(); @@ -477,25 +482,27 @@ protected function processDocuments(Item $item, array $documents) * @param Document $itemDocument The document representing the item for the given language. * @return Document[] array An array of additional Document objects to index. */ - protected function getAdditionalDocuments(Item $item, int $language, Document $itemDocument) + protected function getAdditionalDocuments(Item $item, int $language, Document $itemDocument): array { $documents = []; if (is_array($GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['solr']['IndexQueueIndexer']['indexItemAddDocuments'] ?? null)) { foreach ($GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['solr']['IndexQueueIndexer']['indexItemAddDocuments'] as $classReference) { if (!class_exists($classReference)) { - throw new \InvalidArgumentException('Class does not exits' . $classReference, 1490363487); + throw new InvalidArgumentException('Class does not exits' . $classReference, 1490363487); } $additionalIndexer = GeneralUtility::makeInstance($classReference); if ($additionalIndexer instanceof AdditionalIndexQueueItemIndexer) { $additionalDocuments = $additionalIndexer->getAdditionalItemDocuments($item, $language, $itemDocument); if (is_array($additionalDocuments)) { - $documents = array_merge($documents, - $additionalDocuments); + $documents = array_merge( + $documents, + $additionalDocuments + ); } } else { - throw new \UnexpectedValueException( + throw new UnexpectedValueException( get_class($additionalIndexer) . ' must implement interface ' . AdditionalIndexQueueItemIndexer::class, 1326284551 ); @@ -514,7 +521,7 @@ protected function getAdditionalDocuments(Item $item, int $language, Document $i * @param array $documents An array of documents to be indexed * @return array An array of modified documents */ - protected function preAddModifyDocuments(Item $item, int $language, array $documents) + protected function preAddModifyDocuments(Item $item, int $language, array $documents): array { if (is_array($GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['solr']['IndexQueueIndexer']['preAddModifyDocuments'] ?? null)) { foreach ($GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['solr']['IndexQueueIndexer']['preAddModifyDocuments'] as $classReference) { @@ -547,6 +554,7 @@ protected function preAddModifyDocuments(Item $item, int $language, array $docum * * @param Item $item An index queue item * @return array An array of ApacheSolrForTypo3\Solr\System\Solr\SolrConnection connections, the array's keys are the sys_language_uid of the language of the connection + * @throws DBALDriverException * @throws NoSolrConnectionFoundException */ protected function getSolrConnectionsByItem(Item $item): array @@ -569,7 +577,7 @@ protected function getSolrConnectionsByItem(Item $item): array } $defaultLanguageUid = $this->getDefaultLanguageUid($item, $site->getRootPage(), $siteLanguages); - $translationOverlays = $this->getTranslationOverlaysWithConfiguredSite((int)$pageId, $site, (array)$siteLanguages); + $translationOverlays = $this->getTranslationOverlaysWithConfiguredSite((int)$pageId, $site, $siteLanguages); $defaultConnection = $this->connectionManager->getConnectionByPageId($rootPageId, $defaultLanguageUid, $item->getMountPointIdentifier() ?? ''); $translationConnections = $this->getConnectionsForIndexableLanguages($translationOverlays); @@ -607,13 +615,13 @@ protected function getTranslationOverlaysWithConfiguredSite(int $pageId, Site $s // add Language Fallback foreach ($siteLanguages as $languageId) { if ($languageId !== 0 && !in_array((int)$languageId, $translatedLanguages, true)) { - $fallbackLanguageIds = $this->getFallbackOrder($site, (int)$languageId, (int)$pageId); + $fallbackLanguageIds = $this->getFallbackOrder($site, (int)$languageId); foreach ($fallbackLanguageIds as $fallbackLanguageId) { if ($fallbackLanguageId === 0 || in_array((int)$fallbackLanguageId, $translatedLanguages, true)) { $translationOverlay = [ 'pid' => $pageId, 'sys_language_uid' => $languageId, - 'l10n_parent' => $pageId + 'l10n_parent' => $pageId, ]; $translationOverlays[] = $translationOverlay; continue 2; @@ -628,10 +636,9 @@ protected function getTranslationOverlaysWithConfiguredSite(int $pageId, Site $s /** * @param Site $site * @param int $languageId - * @param int $pageId * @return array */ - protected function getFallbackOrder(Site $site, int $languageId, int $pageId): array + protected function getFallbackOrder(Site $site, int $languageId): array { $fallbackChain = []; $siteFinder = GeneralUtility::makeInstance(SiteFinder::class); @@ -640,7 +647,6 @@ protected function getFallbackOrder(Site $site, int $languageId, int $pageId): $languageAspect = LanguageAspectFactory::createFromSiteLanguage($site->getLanguageById($languageId)); $fallbackChain = $languageAspect->getFallbackChain(); } catch (SiteNotFoundException $e) { - } return $fallbackChain; } @@ -653,7 +659,7 @@ protected function getFallbackOrder(Site $site, int $languageId, int $pageId): * @return int * @throws RuntimeException */ - protected function getDefaultLanguageUid(Item $item, array $rootPage, array $siteLanguages) + protected function getDefaultLanguageUid(Item $item, array $rootPage, array $siteLanguages): int { $defaultLanguageUid = 0; if (($rootPage['l18n_cfg'] & 1) == 1 && count($siteLanguages) == 1 && $siteLanguages[min(array_keys($siteLanguages))] > 0) { @@ -675,8 +681,9 @@ protected function getDefaultLanguageUid(Item $item, array $rootPage, array $sit * * @param array $translationOverlays An array of translation overlays to check for configured connections. * @return array An array of ApacheSolrForTypo3\Solr\System\Solr\SolrConnection connections. + * @throws DBALDriverException */ - protected function getConnectionsForIndexableLanguages(array $translationOverlays) + protected function getConnectionsForIndexableLanguages(array $translationOverlays): array { $connections = []; @@ -705,7 +712,7 @@ protected function getConnectionsForIndexableLanguages(array $translationOverlay * Enables logging dependent on the configuration of the item's site * * @param Item $item An item being indexed - * @return void + * @throws DBALDriverException */ protected function setLogging(Item $item) { diff --git a/Classes/IndexQueue/Initializer/AbstractInitializer.php b/Classes/IndexQueue/Initializer/AbstractInitializer.php index 0182ed69ef..61aa4f0de6 100644 --- a/Classes/IndexQueue/Initializer/AbstractInitializer.php +++ b/Classes/IndexQueue/Initializer/AbstractInitializer.php @@ -1,5 +1,7 @@ logger = GeneralUtility::makeInstance(SolrLogManager::class, /** @scrutinizer ignore-type */ __CLASS__); $flashMessageService = GeneralUtility::makeInstance(FlashMessageService::class); $this->flashMessageQueue = $flashMessageService->getMessageQueueByIdentifier('solr.queue.initializer'); @@ -112,7 +118,7 @@ public function setSite(Site $site) * * @param string $type Type to initialize. */ - public function setType($type) + public function setType(string $type) { $this->type = $type; } @@ -132,9 +138,9 @@ public function setIndexingConfiguration(array $indexingConfiguration) * * @param string $indexingConfigurationName Indexing configuration name */ - public function setIndexingConfigurationName($indexingConfigurationName) + public function setIndexingConfigurationName(string $indexingConfigurationName) { - $this->indexingConfigurationName = (string)$indexingConfigurationName; + $this->indexingConfigurationName = $indexingConfigurationName; } /** @@ -142,8 +148,9 @@ public function setIndexingConfigurationName($indexingConfigurationName) * configuration. * * @return bool TRUE if initialization was successful, FALSE on error. + * @throws DBALDriverException */ - public function initialize() + public function initialize(): bool { /** @var ConnectionPool $connectionPool */ $connectionPool = GeneralUtility::makeInstance(ConnectionPool::class); @@ -164,7 +171,7 @@ public function initialize() } else { // If tables are using distinct connections, start by fetching items matching criteria $logData = ['query' => $fetchItemsQuery]; - $items = $connectionPool->getConnectionForTable($this->type)->fetchAll($fetchItemsQuery); + $items = $connectionPool->getConnectionForTable($this->type)->fetchAllAssociative($fetchItemsQuery); $logData['rows'] = count($items); if (count($items)) { @@ -184,23 +191,20 @@ public function initialize() /** * Builds the SELECT part of the Index Queue initialization query. - * */ - protected function buildSelectStatement() + protected function buildSelectStatement(): string { $changedField = $GLOBALS['TCA'][$this->type]['ctrl']['tstamp']; if (!empty($GLOBALS['TCA'][$this->type]['ctrl']['enablecolumns']['starttime'])) { $changedField = 'GREATEST(' . $GLOBALS['TCA'][$this->type]['ctrl']['enablecolumns']['starttime'] . ',' . $GLOBALS['TCA'][$this->type]['ctrl']['tstamp'] . ')'; } - $select = 'SELECT ' + return 'SELECT ' . '\'' . $this->site->getRootPageId() . '\' as root, ' . '\'' . $this->type . '\' AS item_type, ' . 'uid AS item_uid, ' . '\'' . $this->indexingConfigurationName . '\' as indexing_configuration, ' . $this->getIndexingPriority() . ' AS indexing_priority, ' . $changedField . ' AS changed'; - - return $select; } // initialization query building @@ -210,7 +214,7 @@ protected function buildSelectStatement() * * @return int Indexing priority */ - protected function getIndexingPriority() + protected function getIndexingPriority(): int { $priority = 0; @@ -225,9 +229,9 @@ protected function getIndexingPriority() * Builds a part of the WHERE clause of the Index Queue initialization * query. This part selects the limits items to be selected from the pages * in a site only, plus additional pages that may have been configured. - * + * @throws DBALDriverException */ - protected function buildPagesClause() + protected function buildPagesClause(): string { $pages = $this->getPages(); $pageIdField = ($this->type === 'pages') ? 'uid' : 'pid'; @@ -240,6 +244,7 @@ protected function buildPagesClause() * configured. * * @return array A (sorted) array of page IDs in a site + * @throws DBALDriverException */ protected function getPages(): array { @@ -263,7 +268,7 @@ protected function getPages(): array * * @return string Conditions to only add indexable items to the Index Queue */ - protected function buildTcaWhereClause() + protected function buildTcaWhereClause(): string { $tcaWhereClause = ''; $conditions = []; @@ -287,7 +292,7 @@ protected function buildTcaWhereClause() // default language $GLOBALS['TCA'][$this->type]['ctrl']['languageField'] . ' = 0', // all languages - $GLOBALS['TCA'][$this->type]['ctrl']['languageField'] . ' = -1' + $GLOBALS['TCA'][$this->type]['ctrl']['languageField'] . ' = -1', ]; // all "free"-Mode languages for "non-pages"-records only if ($this->type !== 'pages' && $this->site->hasFreeContentModeLanguages()) { @@ -301,8 +306,10 @@ protected function buildTcaWhereClause() if (isset($GLOBALS['TCA'][$this->type]['ctrl']['transOrigPointerField'])) { $conditions['languageField'][] = $GLOBALS['TCA'][$this->type]['ctrl']['transOrigPointerField'] . ' = 0'; // translations without original language source } - $conditions['languageField'] = '(' . implode(' OR ', - $conditions['languageField']) . ')'; + $conditions['languageField'] = '(' . implode( + ' OR ', + $conditions['languageField'] + ) . ')'; } if (!empty($GLOBALS['TCA'][$this->type]['ctrl']['versioningWS'])) { @@ -324,7 +331,7 @@ protected function buildTcaWhereClause() * * @return string Conditions to add items to the Index Queue based on TypoScript configuration */ - protected function buildUserWhereClause() + protected function buildUserWhereClause(): string { $condition = ''; diff --git a/Classes/IndexQueue/Initializer/IndexQueueInitializer.php b/Classes/IndexQueue/Initializer/IndexQueueInitializer.php index 1901aa961a..e81248819a 100644 --- a/Classes/IndexQueue/Initializer/IndexQueueInitializer.php +++ b/Classes/IndexQueue/Initializer/IndexQueueInitializer.php @@ -37,14 +37,14 @@ public function setSite(Site $site); * * @param string $type Type to initialize. */ - public function setType($type); + public function setType(string $type); /** * Sets the name of the indexing configuration to initialize. * * @param string $indexingConfigurationName Indexing configuration name */ - public function setIndexingConfigurationName($indexingConfigurationName); + public function setIndexingConfigurationName(string $indexingConfigurationName); /** * Sets the configuration for how to index a type of items. @@ -59,5 +59,5 @@ public function setIndexingConfiguration(array $indexingConfiguration); * * @return bool TRUE if initialization was successful, FALSE on error. */ - public function initialize(); + public function initialize(): bool; } diff --git a/Classes/IndexQueue/Initializer/Page.php b/Classes/IndexQueue/Initializer/Page.php index 212fa0e991..0ab836a67b 100644 --- a/Classes/IndexQueue/Initializer/Page.php +++ b/Classes/IndexQueue/Initializer/Page.php @@ -15,15 +15,14 @@ namespace ApacheSolrForTypo3\Solr\IndexQueue\Initializer; -use ApacheSolrForTypo3\Solr\Domain\Index\Queue\QueueItemRepository; -use ApacheSolrForTypo3\Solr\Domain\Site\SiteInterface; -use ApacheSolrForTypo3\Solr\Domain\Site\SiteRepository; use ApacheSolrForTypo3\Solr\IndexQueue\Item; use ApacheSolrForTypo3\Solr\IndexQueue\Queue; use ApacheSolrForTypo3\Solr\System\Logging\SolrLogManager; -use ApacheSolrForTypo3\Solr\System\Records\Pages\PagesRepository; use Doctrine\DBAL\ConnectionException; +use Doctrine\DBAL\Driver\Exception as DBALDriverException; use Doctrine\DBAL\Exception as DBALException; +use PDO; +use Throwable; use TYPO3\CMS\Backend\Utility\BackendUtility; use TYPO3\CMS\Core\Database\Connection; use TYPO3\CMS\Core\Database\ConnectionPool; @@ -42,14 +41,14 @@ class Page extends AbstractInitializer * The type of items this initializer is handling. * @var string */ - protected $type = 'pages'; + protected string $type = 'pages'; /** * Overrides the general setType() implementation, forcing type to "pages". * * @param string $type Type to initialize (ignored). */ - public function setType($type) + public function setType(string $type) { $this->type = 'pages'; } @@ -59,13 +58,17 @@ public function setType($type) * and mounted pages - no nested mount page structures though. * * @return bool TRUE if initialization was successful, FALSE on error. + * @throws ConnectionException + * @throws DBALDriverException + * @throws DBALException|\Doctrine\DBAL\DBALException + * @throws Throwable */ - public function initialize() + public function initialize(): bool { $pagesInitialized = parent::initialize(); $mountPagesInitialized = $this->initializeMountPointPages(); - return ($pagesInitialized && $mountPagesInitialized); + return $pagesInitialized && $mountPagesInitialized; } /** @@ -73,6 +76,8 @@ public function initialize() * * @param array $mountProperties Array of mount point properties mountPageSource, mountPageDestination, and mountPageOverlayed * @param int $mountedPageId The ID of the mounted page + * @throws DBALDriverException + * @throws DBALException|\Doctrine\DBAL\DBALException */ public function initializeMountedPage(array $mountProperties, int $mountedPageId) { @@ -90,6 +95,9 @@ public function initializeMountedPage(array $mountProperties, int $mountedPageId * * @return bool TRUE if initialization of the Mount Pages was successful, FALSE otherwise * @throws ConnectionException + * @throws DBALDriverException + * @throws DBALException|\Doctrine\DBAL\DBALException + * @throws Throwable */ protected function initializeMountPointPages(): bool { @@ -118,7 +126,7 @@ protected function initializeMountPointPages(): bool // handling mount_pid_ol behavior if (!$mountPoint['mountPageOverlayed']) { - // Add page like a regular page, as only the sub tree is mounted. + // Add page like a regular page, as only the sub-tree is mounted. // The page itself has its own content, which is handled like standard page. $indexQueue = GeneralUtility::makeInstance(Queue::class); $indexQueue->updateItem($this->type, $mountPoint['uid']); @@ -137,14 +145,14 @@ protected function initializeMountPointPages(): bool $databaseConnection->commit(); $mountPointsInitialized = true; - } catch (\Throwable $e) { + } catch (Throwable $e) { $databaseConnection->rollBack(); $this->logger->log( SolrLogManager::ERROR, 'Index Queue initialization failed for mount pages', [ - $e->__toString() + $e->__toString(), ] ); break; @@ -199,13 +207,13 @@ protected function validateMountPoint(array $mountPoint): bool /** * Checks whether the mounted page (mount page source) exists. That is, - * whether it accessible in the frontend. So the record must exist + * whether it is accessible in the frontend. So the record must exist * (deleted = 0) and must not be hidden (hidden = 0). * * @param int $mountedPageId Mounted page ID * @return bool TRUE if the page is accessible in the frontend, FALSE otherwise. */ - protected function mountedPageExists($mountedPageId): bool + protected function mountedPageExists(int $mountedPageId): bool { $mountedPageExists = false; @@ -223,6 +231,8 @@ protected function mountedPageExists($mountedPageId): bool * * @param array $mountedPages An array of mounted page IDs * @param array $mountProperties Array with mount point properties (mountPageSource, mountPageDestination, mountPageOverlayed) + * @throws DBALDriverException + * @throws DBALException|\Doctrine\DBAL\DBALException */ protected function addMountedPagesToIndexQueue(array $mountedPages, array $mountProperties) { @@ -240,7 +250,7 @@ protected function addMountedPagesToIndexQueue(array $mountedPages, array $mount $mountIdentifier = $this->getMountPointIdentifier($mountProperties); $initializationQuery = 'INSERT INTO tx_solr_indexqueue_item (root, item_type, item_uid, indexing_configuration, indexing_priority, changed, has_indexing_properties, pages_mountidentifier, errors) ' - . $this->buildSelectStatement() . ', 1, ' . $connection->quote($mountIdentifier, \PDO::PARAM_STR) . ',""' + . $this->buildSelectStatement() . ', 1, ' . $connection->quote($mountIdentifier, PDO::PARAM_STR) . ',""' . 'FROM pages ' . 'WHERE ' . 'uid IN(' . implode(',', $mountedPagesThatNeedToBeAdded) . ') ' @@ -265,6 +275,8 @@ protected function addMountedPagesToIndexQueue(array $mountedPages, array $mount * * @param array $mountPage An array with information about the root/destination Mount Page * @param array $mountedPages An array of mounted page IDs + * @throws DBALDriverException + * @throws DBALException|\Doctrine\DBAL\DBALException */ protected function addIndexQueueItemIndexingProperties(array $mountPage, array $mountedPages) { @@ -288,7 +300,7 @@ protected function addIndexQueueItemIndexingProperties(array $mountPage, array $ * @param array $mountProperties Array with mount point properties (mountPageSource, mountPageDestination, mountPageOverlayed) * @return string String consisting of mountPageSource-mountPageDestination-mountPageOverlayed */ - protected function getMountPointIdentifier(array $mountProperties) + protected function getMountPointIdentifier(array $mountProperties): string { return $mountProperties['mountPageSource'] . '-' . $mountProperties['mountPageDestination'] @@ -302,6 +314,7 @@ protected function getMountPointIdentifier(array $mountProperties) * * @param array $mountPage * @return array An array of page IDs in the mounted page tree + * @throws DBALDriverException */ protected function resolveMountPageTree(array $mountPage): array { @@ -311,7 +324,7 @@ protected function resolveMountPageTree(array $mountPage): array // Do not include $mountPageSourceId in tree, if the mount point is not set to overlay. if (!empty($mountPageTree) && !$mountPage['mountPageOverlayed']) { - $mountPageTree = array_diff($mountPageTree , [$mountPageSourceId]); + $mountPageTree = array_diff($mountPageTree, [$mountPageSourceId]); } return $mountPageTree; diff --git a/Classes/IndexQueue/Item.php b/Classes/IndexQueue/Item.php index 2450176b95..76420642f9 100644 --- a/Classes/IndexQueue/Item.php +++ b/Classes/IndexQueue/Item.php @@ -1,5 +1,7 @@ indexQueueUid = $itemMetaData['uid'] ?? null; $this->rootPageUid = $itemMetaData['root'] ?? null; $this->type = $itemMetaData['item_type'] ?? null; $this->recordUid = $itemMetaData['item_uid'] ?? null; - $this->mountPointIdentifier = (string) empty($itemMetaData['pages_mountidentifier']) ? '' : $itemMetaData['pages_mountidentifier']; + $this->mountPointIdentifier = (string)empty($itemMetaData['pages_mountidentifier']) ? '' : $itemMetaData['pages_mountidentifier']; $this->changed = $itemMetaData['changed'] ?? null; $this->indexed = $itemMetaData['indexed'] ?? null; - $this->errors = (string) empty($itemMetaData['errors']) ? '' : $itemMetaData['errors']; + $this->errors = (string)empty($itemMetaData['errors']) ? '' : $itemMetaData['errors']; $this->indexingConfigurationName = $itemMetaData['indexing_configuration'] ?? ''; $this->hasIndexingProperties = (boolean)($itemMetaData['has_indexing_properties'] ?? false); @@ -172,9 +181,9 @@ public function __construct(array $itemMetaData, array $fullRecord = [], IndexQu /** * Getter for Index Queue UID * - * @return integer + * @return int */ - public function getIndexQueueUid() + public function getIndexQueueUid(): ?int { return $this->indexQueueUid; } @@ -182,9 +191,9 @@ public function getIndexQueueUid() /** * Gets the item's root page ID (uid) * - * @return int root page ID + * @return int|null root page ID */ - public function getRootPageUid() + public function getRootPageUid(): ?int { return $this->rootPageUid; } @@ -194,31 +203,31 @@ public function getRootPageUid() * * @return string */ - public function getMountPointIdentifier() + public function getMountPointIdentifier(): ?string { return $this->mountPointIdentifier; } /** - * @param integer $uid + * @param int $uid */ - public function setRootPageUid($uid) + public function setRootPageUid(int $uid) { - $this->rootPageUid = intval($uid); + $this->rootPageUid = $uid; } /** * @return string */ - public function getErrors() + public function getErrors(): string { return $this->errors; } /** - * @return boolean + * @return bool */ - public function getHasErrors() + public function getHasErrors(): bool { return trim($this->errors) !== ''; } @@ -226,7 +235,7 @@ public function getHasErrors() /** * @return int */ - public function getState() + public function getState(): int { if ($this->getHasErrors()) { return self::STATE_BLOCKED; @@ -242,9 +251,10 @@ public function getState() /** * Gets the site the item belongs to. * - * @return Site Site instance the item belongs to. + * @return Site|null Site instance the item belongs to. + * @throws DBALDriverException */ - public function getSite() + public function getSite(): ?Site { $siteRepository = GeneralUtility::makeInstance(SiteRepository::class); return $siteRepository->getSiteByRootPageId($this->rootPageUid); @@ -281,7 +291,7 @@ public function getIndexingConfigurationName() /** * @param string $indexingConfigurationName */ - public function setIndexingConfigurationName($indexingConfigurationName) + public function setIndexingConfigurationName(string $indexingConfigurationName) { $this->indexingConfigurationName = $indexingConfigurationName; } @@ -311,9 +321,9 @@ public function getIndexed() * * @param int $changed */ - public function setChanged($changed) + public function setChanged(int $changed) { - $this->changed = intval($changed); + $this->changed = $changed; } /** @@ -335,7 +345,7 @@ public function getRecordUid() * * @return array The item's DB record. */ - public function getRecord() + public function getRecord(): array { if (empty($this->record)) { $this->record = (array)BackendUtility::getRecord( @@ -365,7 +375,7 @@ public function setRecord(array $record) * * @return int */ - public function getRecordPageId() + public function getRecordPageId(): int { $this->getRecord(); @@ -374,11 +384,11 @@ public function getRecordPageId() /** * Stores the indexing properties. - * + * @throws DBALException|\Doctrine\DBAL\DBALException */ public function storeIndexingProperties() { - $this->indexQueueIndexingPropertyRepository->removeByRootPidAndIndexQueueUid(intval($this->rootPageUid), intval($this->indexQueueUid)); + $this->indexQueueIndexingPropertyRepository->removeByRootPidAndIndexQueueUid((int)($this->rootPageUid), (int)($this->indexQueueUid)); if ($this->hasIndexingProperties()) { $this->writeIndexingProperties(); @@ -390,7 +400,7 @@ public function storeIndexingProperties() /** * @return bool */ - public function hasIndexingProperties() + public function hasIndexingProperties(): bool { return $this->hasIndexingProperties; } @@ -406,7 +416,7 @@ protected function writeIndexingProperties() 'root' => $this->rootPageUid, 'item_id' => $this->indexQueueUid, 'property_key' => $propertyKey, - 'property_value' => $propertyValue + 'property_value' => $propertyValue, ]; } if (empty($properties)) { @@ -418,8 +428,10 @@ protected function writeIndexingProperties() /** * @param string $key * @return bool + * @throws DBALDriverException + * @throws DBALException */ - public function hasIndexingProperty($key) + public function hasIndexingProperty(string $key): bool { $this->loadIndexingProperties(); @@ -428,6 +440,9 @@ public function hasIndexingProperty($key) /** * Loads the indexing properties for the item - if not already loaded. + * + * @throws DBALDriverException + * @throws DBALException */ public function loadIndexingProperties() { @@ -435,7 +450,7 @@ public function loadIndexingProperties() return; } - $indexingProperties = $this->indexQueueIndexingPropertyRepository->findAllByIndexQueueUid(intval($this->indexQueueUid)); + $indexingProperties = $this->indexQueueIndexingPropertyRepository->findAllByIndexQueueUid((int)($this->indexQueueUid)); $this->indexingPropertiesLoaded = true; if (empty($indexingProperties)) { return; @@ -451,17 +466,18 @@ public function loadIndexingProperties() * * @param string $key Indexing property name * @param string|int|float $value Indexing property value - * @throws \InvalidArgumentException when $value is not string, integer or float + * + * @throws InvalidArgumentException when $value is not string, integer or float + * @throws DBALDriverException + * @throws DBALException */ - public function setIndexingProperty($key, $value) + public function setIndexingProperty(string $key, $value) { // make sure to not interfere with existing indexing properties $this->loadIndexingProperties(); - $key = (string)$key; // Scalar typehints now! - if (!is_string($value) && !is_int($value) && !is_float($value)) { - throw new \InvalidArgumentException( + throw new InvalidArgumentException( 'Cannot set indexing property "' . $key . '", its value must be string, integer or float, ' . 'type given was "' . gettype($value) . '"', @@ -477,15 +493,18 @@ public function setIndexingProperty($key, $value) * Gets a specific indexing property by its name/key. * * @param string $key Indexing property name/key. - * @throws \InvalidArgumentException when the given $key does not exist. * @return string + * + * @throws InvalidArgumentException when the given $key does not exist. + * @throws DBALDriverException + * @throws DBALException */ - public function getIndexingProperty($key) + public function getIndexingProperty(string $key): string { $this->loadIndexingProperties(); if (!array_key_exists($key, $this->indexingProperties)) { - throw new \InvalidArgumentException( + throw new InvalidArgumentException( 'No indexing property "' . $key . '".', 1323174143 ); @@ -498,8 +517,10 @@ public function getIndexingProperty($key) * Gets all indexing properties set for this item. * * @return array Array of indexing properties. + * @throws DBALDriverException + * @throws DBALException */ - public function getIndexingProperties() + public function getIndexingProperties(): array { $this->loadIndexingProperties(); @@ -510,8 +531,10 @@ public function getIndexingProperties() * Gets the names/keys of the item's indexing properties. * * @return array Array of indexing property names/keys + * @throws DBALDriverException + * @throws DBALException */ - public function getIndexingPropertyKeys() + public function getIndexingPropertyKeys(): array { $this->loadIndexingProperties(); diff --git a/Classes/IndexQueue/PageIndexer.php b/Classes/IndexQueue/PageIndexer.php index 5f5312383e..bf7f230171 100644 --- a/Classes/IndexQueue/PageIndexer.php +++ b/Classes/IndexQueue/PageIndexer.php @@ -1,5 +1,7 @@ */ @@ -40,8 +46,11 @@ class PageIndexer extends Indexer * * @param Item $item An index queue item * @return bool Whether indexing was successful + * @throws DBALDriverException + * @throws DBALException + * @throws NoSolrConnectionFoundException */ - public function index(Item $item) + public function index(Item $item): bool { $this->setLogging($item); @@ -61,7 +70,7 @@ public function index(Item $item) } foreach ($contentAccessGroups as $userGroup) { - $this->indexPage($item, $systemLanguageUid, $userGroup); + $this->indexPage($item, $systemLanguageUid, (int)$userGroup); } } @@ -74,7 +83,7 @@ public function index(Item $item) * @param Item $item The page we want to index encapsulated in an index queue item * @return bool True if we can index this page, FALSE otherwise */ - protected function isPageIndexable(Item $item) + protected function isPageIndexable(Item $item): bool { // TODO do we still need this? @@ -100,6 +109,8 @@ protected function isPageIndexable(Item $item) * * @param Item $item An index queue item * @return array An array of ApacheSolrForTypo3\Solr\System\Solr\SolrConnection connections, the array's keys are the sys_language_uid of the language of the connection + * @throws DBALDriverException + * @throws NoSolrConnectionFoundException */ protected function getSolrConnectionsByItem(Item $item): array { @@ -140,8 +151,10 @@ protected function getSolrConnectionsByItem(Item $item): array * @param Item $item Index queue item representing the current page to get the user groups from * @param int $language The sys_language_uid language ID * @return array Array of user group IDs + * @throws DBALDriverException + * @throws DBALException */ - protected function getAccessGroupsFromContent(Item $item, $language = 0) + protected function getAccessGroupsFromContent(Item $item, int $language = 0): array { static $accessGroupsCache; @@ -169,7 +182,7 @@ protected function getAccessGroupsFromContent(Item $item, $language = 0) 'index request url' => $indexRequestUrl, 'request' => (array)$request, 'response' => (array)$response, - 'groups' => $groups + 'groups' => $groups, ] ); } @@ -186,7 +199,7 @@ protected function getAccessGroupsFromContent(Item $item, $language = 0) * * @return PageIndexerRequest Base page indexer request */ - protected function buildBasePageIndexerRequest() + protected function buildBasePageIndexerRequest(): PageIndexerRequest { $request = $this->getPageIndexerRequest(); $request->setParameter('loggingEnabled', $this->loggingEnabled); @@ -214,7 +227,7 @@ protected function buildBasePageIndexerRequest() /** * @return PageIndexerRequest */ - protected function getPageIndexerRequest() + protected function getPageIndexerRequest(): PageIndexerRequest { return GeneralUtility::makeInstance(PageIndexerRequest::class); } @@ -222,29 +235,30 @@ protected function getPageIndexerRequest() /** * Determines a page ID's URL. * - * Tries to find a domain record to use to build an URL for a given page ID + * Tries to find a domain record to use to build a URL for a given page ID * and then actually build and return the page URL. * * @param Item $item Item to index * @param int $language The language id * @return string URL to send the index request to - * @throws RuntimeException + * @throws DBALDriverException + * @throws DBALException + * @throws Exception */ - protected function getDataUrl(Item $item, $language = 0) + protected function getDataUrl(Item $item, int $language = 0): string { $pageId = $item->getRecordUid(); $strategy = $this->getUriStrategy($pageId); $mountPointParameter = $this->getMountPageDataUrlParameter($item); - $dataUrl = $strategy->getPageIndexingUriFromPageItemAndLanguageId($item, $language, $mountPointParameter, $this->options); - - return $dataUrl; + return $strategy->getPageIndexingUriFromPageItemAndLanguageId($item, $language, $mountPointParameter, $this->options); } /** * @param int $pageId * @return AbstractUriStrategy + * @throws Exception */ - protected function getUriStrategy($pageId) + protected function getUriStrategy(int $pageId): AbstractUriStrategy { return GeneralUtility::makeInstance(UriStrategyFactory::class)->getForPageId($pageId); } @@ -254,9 +268,11 @@ protected function getUriStrategy($pageId) * is identified as being a mounted page, the &MP parameter is generated. * * @param Item $item Item to get an &MP URL parameter for - * @return string &MP URL parameter if $item is a mounted page + * @return string 'MP' URL parameter if $item is a mounted page + * @throws DBALDriverException + * @throws DBALException */ - protected function getMountPageDataUrlParameter(Item $item) + protected function getMountPageDataUrlParameter(Item $item): string { if (!$item->hasIndexingProperty('isMountedPage')) { return ''; @@ -265,9 +281,9 @@ protected function getMountPageDataUrlParameter(Item $item) return $item->getIndexingProperty('mountPageSource') . '-' . $item->getIndexingProperty('mountPageDestination'); } - # - # Frontend User Groups Access - # + // + // Frontend User Groups Access + // /** * Creates a single Solr Document for a page in a specific language and for @@ -277,7 +293,8 @@ protected function getMountPageDataUrlParameter(Item $item) * @param ?int $language The language to use. * @param ?int $userGroup The frontend user group to use. * @return PageIndexerResponse Page indexer response - * @throws RuntimeException if indexing an item failed + * @throws DBALDriverException + * @throws DBALException */ protected function indexPage(Item $item, ?int $language = 0, ?int $userGroup = 0): PageIndexerResponse { @@ -309,7 +326,7 @@ protected function indexPage(Item $item, ?int $language = 0, ?int $userGroup = 0 'index request url' => $indexRequestUrl, 'request' => (array)$request, 'request headers' => $request->getHeaders(), - 'response' => (array)$response + 'response' => (array)$response, ] ); } @@ -344,10 +361,12 @@ protected function indexPage(Item $item, ?int $language = 0, ?int $userGroup = 0 * * @param Item $item Index queue item representing the current page * @param int $language The sys_language_uid language ID - * @param int $contentAccessGroup The user group to use for the content access rootline element. Optional, will be determined automatically if not set. - * @return string An Access Rootline. + * @param int|null $contentAccessGroup The user group to use for the content access rootline element. Optional, will be determined automatically if not set. + * @return mixed|Rootline An Access Rootline. + * @throws DBALDriverException + * @throws DBALException */ - protected function getAccessRootline(Item $item, $language = 0, $contentAccessGroup = null) + protected function getAccessRootline(Item $item, int $language = 0, int $contentAccessGroup = null) { static $accessRootlineCache; @@ -382,12 +401,11 @@ protected function getAccessRootline(Item $item, $language = 0, $contentAccessGr * Returns the access rootLine for a certain pageId. * * @param int $pageId - * @param string $mountPointparameter + * @param string $mountPointParameter * @return Rootline */ - protected function getAccessRootlineByPageId($pageId, $mountPointParameter) + protected function getAccessRootlineByPageId(int $pageId, string $mountPointParameter): Rootline { return Rootline::getAccessRootlineByPageId($pageId, $mountPointParameter); } - } diff --git a/Classes/IndexQueue/PageIndexerRequest.php b/Classes/IndexQueue/PageIndexerRequest.php index c80741515b..84319960c4 100644 --- a/Classes/IndexQueue/PageIndexerRequest.php +++ b/Classes/IndexQueue/PageIndexerRequest.php @@ -1,5 +1,7 @@ requestId = uniqid(); $this->timeout = (float)ini_get('default_socket_timeout'); @@ -141,7 +148,7 @@ public function __construct($jsonEncodedParameters = null, SolrLogManager $solrL * * @param string $action Action name. */ - public function addAction($action) + public function addAction(string $action) { $this->actions[] = $action; } @@ -154,15 +161,16 @@ public function addAction($action) * * @param string $url The URL to request. * @return PageIndexerResponse Response + * @throws Exception */ - public function send($url) + public function send(string $url): PageIndexerResponse { /** @var $response PageIndexerResponse */ $response = GeneralUtility::makeInstance(PageIndexerResponse::class); $decodedResponse = $this->getUrlAndDecodeResponse($url, $response); if ($decodedResponse['requestId'] != $this->requestId) { - throw new \RuntimeException( + throw new RuntimeException( 'Request ID mismatch. Request ID was ' . $this->requestId . ', received ' . $decodedResponse['requestId'] . '. Are requests cached?', 1351260655 ); @@ -187,16 +195,17 @@ public function send($url) * * @param string $url * @param PageIndexerResponse $response - * @return mixed + * @return array|bool + * @throws Exception */ - protected function getUrlAndDecodeResponse($url, PageIndexerResponse $response) + protected function getUrlAndDecodeResponse(string $url, PageIndexerResponse $response) { $headers = $this->getHeaders(); $rawResponse = $this->getUrl($url, $headers, $this->timeout); // convert JSON response to response object properties $decodedResponse = $response->getResultsFromJson($rawResponse->getBody()->getContents()); - if ($rawResponse === false || $decodedResponse === false) { + if ($decodedResponse === false) { $this->logger->log( SolrLogManager::ERROR, 'Failed to execute Page Indexer Request. Request ID: ' . $this->requestId, @@ -205,21 +214,21 @@ protected function getUrlAndDecodeResponse($url, PageIndexerResponse $response) 'request url' => $url, 'request headers' => $headers, 'response headers' => $rawResponse->getHeaders(), - 'raw response body' => $rawResponse->getBody()->getContents() + 'raw response body' => $rawResponse->getBody()->getContents(), ] ); - throw new \RuntimeException('Failed to execute Page Indexer Request. See log for details. Request ID: ' . $this->requestId, 1319116885); + throw new RuntimeException('Failed to execute Page Indexer Request. See log for details. Request ID: ' . $this->requestId, 1319116885); } return $decodedResponse; } /** - * Generates the headers to be send with the request. + * Generates the headers to be sent with the request. * * @return string[] Array of HTTP headers. */ - public function getHeaders() + public function getHeaders(): array { $headers = $this->header; $headers[] = 'User-Agent: ' . $this->getUserAgent(); @@ -235,7 +244,7 @@ public function getHeaders() $itemId . '|' . $pageId . '|' . $GLOBALS['TYPO3_CONF_VARS']['SYS']['encryptionKey'] - ) + ), ]; $indexerRequestData = array_merge($indexerRequestData, $this->parameters); @@ -247,17 +256,17 @@ public function getHeaders() /** * @return string */ - protected function getUserAgent() + protected function getUserAgent(): string { return $GLOBALS['TYPO3_CONF_VARS']['HTTP']['headers']['User-Agent'] ?? 'TYPO3'; } /** - * Adds an HTTP header to be send with the request. + * Adds an HTTP header to be sent with the request. * * @param string $header HTTP header */ - public function addHeader($header) + public function addHeader(string $header) { $this->header[] = $header; } @@ -268,12 +277,12 @@ public function addHeader($header) * * @return bool TRUE if it's a legitimate request, FALSE otherwise. */ - public function isAuthenticated() + public function isAuthenticated(): bool { $authenticated = false; - if (is_null($this->parameters)) { - return $authenticated; + if (empty($this->parameters)) { + return false; } $calculatedHash = md5( @@ -294,7 +303,7 @@ public function isAuthenticated() * * @return array List of actions */ - public function getActions() + public function getActions(): array { return $this->actions; } @@ -304,7 +313,7 @@ public function getActions() * * @return array Request parameters. */ - public function getParameters() + public function getParameters(): array { return $this->parameters; } @@ -312,9 +321,9 @@ public function getParameters() /** * Gets the request's unique ID. * - * @return string Unique request ID. + * @return string|null Unique request ID. */ - public function getRequestId() + public function getRequestId(): ?string { return $this->requestId; } @@ -323,20 +332,20 @@ public function getRequestId() * Gets a specific parameter's value. * * @param string $parameterName The parameter to retrieve. - * @return mixed NULL if a parameter was not set or it's value otherwise. + * @return mixed|null NULL if a parameter was not set, or it's value otherwise. */ - public function getParameter($parameterName) + public function getParameter(string $parameterName) { - return isset($this->parameters[$parameterName]) ? $this->parameters[$parameterName] : null; + return $this->parameters[$parameterName] ?? null; } /** * Sets a request's parameter and its value. * * @param string $parameter Parameter name - * @param string $value Parameter value. + * @param mixed $value Parameter value. */ - public function setParameter($parameter, $value) + public function setParameter(string $parameter, $value) { if (is_bool($value)) { $value = $value ? '1' : '0'; @@ -351,7 +360,7 @@ public function setParameter($parameter, $value) * @param string $username username. * @param string $password password. */ - public function setAuthorizationCredentials($username, $password) + public function setAuthorizationCredentials(string $username, string $password) { $this->username = $username; $this->password = $password; @@ -372,7 +381,7 @@ public function setIndexQueueItem(Item $item) * * @return float */ - public function getTimeout() + public function getTimeout(): float { return $this->timeout; } @@ -382,9 +391,9 @@ public function getTimeout() * * @param float $timeout Timeout seconds */ - public function setTimeout($timeout) + public function setTimeout(float $timeout) { - $this->timeout = (float)$timeout; + $this->timeout = $timeout; } /** @@ -394,30 +403,27 @@ public function setTimeout($timeout) * @param string[] $headers * @param float $timeout * @return ResponseInterface - * @throws \Exception + * @throws Exception */ - protected function getUrl($url, $headers, $timeout): ResponseInterface + protected function getUrl(string $url, array $headers, float $timeout): ResponseInterface { try { $options = $this->buildGuzzleOptions($headers, $timeout); $response = $this->requestFactory->request($url, 'GET', $options); - } catch (ClientException $e) { - $response = $e->getResponse(); - } catch (ServerException $e) { + } catch (ClientException|ServerException $e) { $response = $e->getResponse(); } - return $response; } /** - * Build the options array for the guzzle client. + * Build the options array for the guzzle-client. * * @param array $headers * @param float $timeout * @return array */ - protected function buildGuzzleOptions($headers, $timeout) + protected function buildGuzzleOptions(array $headers, float $timeout): array { $finalHeaders = []; diff --git a/Classes/IndexQueue/PageIndexerRequestHandler.php b/Classes/IndexQueue/PageIndexerRequestHandler.php index 24766ac19a..cfd2154940 100644 --- a/Classes/IndexQueue/PageIndexerRequestHandler.php +++ b/Classes/IndexQueue/PageIndexerRequestHandler.php @@ -1,5 +1,7 @@ response->setRequestId($this->request->getRequestId()); } - /** * 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. - * - * @return void */ public function run() { @@ -79,8 +77,6 @@ public function run() /** * Completes the Index Queue page indexer request and returns the response * with the collected results. - * - * @return void */ public function shutdown() { @@ -92,7 +88,7 @@ public function shutdown() * * @return PageIndexerRequest */ - public function getRequest() + public function getRequest(): PageIndexerRequest { return $this->request; } @@ -102,7 +98,7 @@ public function getRequest() * * @return PageIndexerResponse */ - public function getResponse() + public function getResponse(): PageIndexerResponse { return $this->response; } diff --git a/Classes/IndexQueue/PageIndexerResponse.php b/Classes/IndexQueue/PageIndexerResponse.php index bb8d4507f0..f7df17ca59 100644 --- a/Classes/IndexQueue/PageIndexerResponse.php +++ b/Classes/IndexQueue/PageIndexerResponse.php @@ -1,5 +1,7 @@ result pairs. * * @var array */ - protected $results = []; + protected array $results = []; /** * Turns a JSON encoded result string back into its PHP representation. @@ -43,7 +46,7 @@ class PageIndexerResponse * @param string $jsonEncodedResponse JSON encoded result string * @return array|bool An array of action => result pairs or FALSE if the response could not be decoded */ - public static function getResultsFromJson($jsonEncodedResponse) + public static function getResultsFromJson(string $jsonEncodedResponse) { $responseData = json_decode($jsonEncodedResponse, true); @@ -63,35 +66,25 @@ public static function getResultsFromJson($jsonEncodedResponse) * * @param string $action The action name. * @param mixed $result The action's result. - * @throws \RuntimeException if $action is null + * @throws RuntimeException if $action is null */ - public function addActionResult($action, $result) + public function addActionResult(string $action, $result) { - if (is_null($action)) { - throw new \RuntimeException( - 'Attempt to provide a result without providing an action', - 1294080509 - ); - } - $this->results[$action] = $result; } /** * Gets the complete set of results or a specific action's results. * - * @param string $action Optional action name. - * @return array + * @param string|null $action Optional action name. + * @return mixed */ - public function getActionResult($action = null) + public function getActionResult(?string $action = null) { - $result = $this->results; - - if (!empty($action)) { - $result = $this->results[$action]; + if (empty($action)) { + return $this->results; } - - return $result; + return $this->results[$action]; } /** @@ -100,7 +93,7 @@ public function getActionResult($action = null) * * @return string The response content */ - public function getContent() + public function getContent(): string { return $this->toJson(); } @@ -110,7 +103,7 @@ public function getContent() * * @return string JSON representation of the results. */ - protected function toJson() + protected function toJson(): string { $serializedActionResults = []; @@ -120,7 +113,7 @@ protected function toJson() $responseData = [ 'requestId' => $this->requestId, - 'actionResults' => $serializedActionResults + 'actionResults' => $serializedActionResults, ]; return json_encode($responseData); @@ -131,7 +124,7 @@ protected function toJson() * * @return string Request Id. */ - public function getRequestId() + public function getRequestId(): string { return $this->requestId; } @@ -140,9 +133,8 @@ public function getRequestId() * Sets the Id of the request this response belongs to. * * @param string $requestId Request Id. - * @return void */ - public function setRequestId($requestId) + public function setRequestId(string $requestId) { $this->requestId = $requestId; } diff --git a/Classes/IndexQueue/Queue.php b/Classes/IndexQueue/Queue.php index 849e7bdb4b..13aa68d3e8 100644 --- a/Classes/IndexQueue/Queue.php +++ b/Classes/IndexQueue/Queue.php @@ -1,5 +1,7 @@ */ @@ -40,37 +46,37 @@ class Queue /** * @var RootPageResolver */ - protected $rootPageResolver; + protected RootPageResolver $rootPageResolver; /** * @var ConfigurationAwareRecordService */ - protected $recordService; + protected ConfigurationAwareRecordService $recordService; /** - * @var \ApacheSolrForTypo3\Solr\System\Logging\SolrLogManager + * @var SolrLogManager */ - protected $logger = null; + protected SolrLogManager $logger; /** * @var QueueItemRepository */ - protected $queueItemRepository; + protected QueueItemRepository $queueItemRepository; /** * @var QueueStatisticsRepository */ - protected $queueStatisticsRepository; + protected QueueStatisticsRepository $queueStatisticsRepository; /** * @var QueueInitializationService */ - protected $queueInitializationService; + protected QueueInitializationService $queueInitializationService; /** * @var FrontendEnvironment */ - protected $frontendEnvironment = null; + protected FrontendEnvironment $frontendEnvironment; /** * Queue constructor. @@ -106,8 +112,10 @@ public function __construct( * @param int $rootPageId The root page uid for which to get * the last indexed item id * @return int Timestamp of last index run. + * @throws DBALDriverException + * @throws DBALException|\Doctrine\DBAL\DBALException */ - public function getLastIndexTime($rootPageId) + public function getLastIndexTime(int $rootPageId): int { $lastIndexTime = 0; @@ -126,8 +134,10 @@ public function getLastIndexTime($rootPageId) * @param int $rootPageId The root page uid for which to get * the last indexed item id * @return int The last indexed item's ID. + * @throws DBALDriverException + * @throws DBALException|\Doctrine\DBAL\DBALException */ - public function getLastIndexedItemId($rootPageId) + public function getLastIndexedItemId(int $rootPageId): int { $lastIndexedItemId = 0; @@ -142,7 +152,7 @@ public function getLastIndexedItemId($rootPageId) /** * @return QueueInitializationService */ - public function getInitializationService() + public function getInitializationService(): QueueInitializationService { return $this->queueInitializationService; } @@ -156,27 +166,31 @@ public function getInitializationService() * The method creates or updates the index queue items for all related rootPageIds. * * @param string $itemType The item's type, usually a table name. - * @param string $itemUid The item's uid, usually an integer uid, could be a different value for non-database-record types. + * @param int|string $itemUid The item's uid, usually an integer uid, could be a different value for non-database-record types. * @param int $forcedChangeTime The change time for the item if set, otherwise value from getItemChangedTime() is used. * @return int Number of updated/created items + * @throws DBALDriverException + * @throws DBALException|\Doctrine\DBAL\DBALException + * @throws Throwable */ - public function updateItem($itemType, $itemUid, $forcedChangeTime = 0) + public function updateItem(string $itemType, $itemUid, int $forcedChangeTime = 0): int { $updateCount = $this->updateOrAddItemForAllRelatedRootPages($itemType, $itemUid, $forcedChangeTime); - $updateCount = $this->postProcessIndexQueueUpdateItem($itemType, $itemUid, $updateCount, $forcedChangeTime); - - return $updateCount; + return $this->postProcessIndexQueueUpdateItem($itemType, $itemUid, $updateCount, $forcedChangeTime); } /** - * Updates or add's the item for all relevant root pages. + * Updates or adds the item for all relevant root pages. * * @param string $itemType The item's type, usually a table name. - * @param string $itemUid The item's uid, usually an integer uid, could be a different value for non-database-record types. + * @param int|string $itemUid The item's uid, usually an integer uid, could be a different value for non-database-record types. * @param int $forcedChangeTime The change time for the item if set, otherwise value from getItemChangedTime() is used. * @return int + * @throws DBALDriverException + * @throws DBALException|\Doctrine\DBAL\DBALException + * @throws Throwable */ - protected function updateOrAddItemForAllRelatedRootPages($itemType, $itemUid, $forcedChangeTime): int + protected function updateOrAddItemForAllRelatedRootPages(string $itemType, $itemUid, int $forcedChangeTime): int { $updateCount = 0; $rootPageIds = $this->rootPageResolver->getResponsibleRootPageIds($itemType, $itemUid); @@ -210,16 +224,20 @@ protected function updateOrAddItemForAllRelatedRootPages($itemType, $itemUid, $f } /** - * Executes the updateItem post processing hook. + * Executes the updateItem post-processing hook. * * @param string $itemType - * @param int $itemUid + * @param int|string $itemUid The item's uid, usually an integer uid, could be a different value for non-database-record types. * @param int $updateCount * @param int $forcedChangeTime * @return int */ - protected function postProcessIndexQueueUpdateItem($itemType, $itemUid, $updateCount, $forcedChangeTime = 0) - { + protected function postProcessIndexQueueUpdateItem( + string $itemType, + $itemUid, + int $updateCount, + int $forcedChangeTime = 0 + ): int { if (!is_array($GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['solr']['postProcessIndexQueueUpdateItem'] ?? null)) { return $updateCount; } @@ -236,7 +254,7 @@ protected function postProcessIndexQueueUpdateItem($itemType, $itemUid, $updateC * @param string $classReference * @return object */ - protected function getHookImplementation($classReference) + protected function getHookImplementation(string $classReference): object { return GeneralUtility::makeInstance($classReference); } @@ -246,8 +264,10 @@ protected function getHookImplementation($classReference) * * @param Site $site * @return array Error items for the current site's Index Queue + * @throws DBALDriverException + * @throws DBALException|\Doctrine\DBAL\DBALException */ - public function getErrorsBySite(Site $site) + public function getErrorsBySite(Site $site): array { return $this->queueItemRepository->findErrorsBySite($site); } @@ -256,6 +276,7 @@ public function getErrorsBySite(Site $site) * Resets all the errors for all index queue items. * * @return mixed + * @throws DBALException|\Doctrine\DBAL\DBALException */ public function resetAllErrors() { @@ -267,6 +288,7 @@ public function resetAllErrors() * * @param Site $site * @return mixed + * @throws DBALException|\Doctrine\DBAL\DBALException */ public function resetErrorsBySite(Site $site) { @@ -278,6 +300,7 @@ public function resetErrorsBySite(Site $site) * * @param Item $item * @return mixed + * @throws DBALException|\Doctrine\DBAL\DBALException */ public function resetErrorByItem(Item $item) { @@ -290,15 +313,21 @@ public function resetErrorByItem(Item $item) * Not meant for public use. * * @param string $itemType The item's type, usually a table name. - * @param string $itemUid The item's uid, usually an integer uid, could be a + * @param int|string $itemUid The item's uid, usually an integer uid, could be a * different value for non-database-record types. * @param string $indexingConfiguration The item's indexing configuration to use. * Optional, overwrites existing / determined configuration. - * @param $rootPageId + * @param int $rootPageId * @return int - */ - private function addNewItem($itemType, $itemUid, $indexingConfiguration, $rootPageId) - { + * @throws DBALDriverException + * @throws DBALException|\Doctrine\DBAL\DBALException + */ + private function addNewItem( + string $itemType, + $itemUid, + string $indexingConfiguration, + int $rootPageId + ): int { $additionalRecordFields = ''; if ($itemType === 'pages') { $additionalRecordFields = ', doktype, uid'; @@ -319,13 +348,13 @@ private function addNewItem($itemType, $itemUid, $indexingConfiguration, $rootPa * Get record to be added in addNewItem * * @param string $itemType The item's type, usually a table name. - * @param string $itemUid The item's uid, usually an integer uid, could be a + * @param int|string $itemUid The item's uid, usually an integer uid, could be a * different value for non-database-record types. * @param string $additionalRecordFields for sql-query * - * @return array|NULL + * @return array|null */ - protected function getRecordCached($itemType, $itemUid, $additionalRecordFields) + protected function getRecordCached(string $itemType, $itemUid, string $additionalRecordFields): ?array { $cache = GeneralUtility::makeInstance(TwoLevelCache::class, /** @scrutinizer ignore-type */ 'runtime'); $cacheId = md5('Queue' . ':' . 'getRecordCached' . ':' . $itemType . ':' . $itemUid . ':' . 'pid' . $additionalRecordFields); @@ -349,11 +378,13 @@ protected function getRecordCached($itemType, $itemUid, $additionalRecordFields) * of an item. * * @param string $itemType The item's table name. - * @param string $itemUid The item's uid, usually an integer uid, could be a + * @param int|string $itemUid The item's uid, usually an integer uid, could be a * different value for non-database-record types. * @return int Timestamp of the item's changed time or future start time + * @throws DBALDriverException + * @throws DBALException|\Doctrine\DBAL\DBALException */ - protected function getItemChangedTime($itemType, $itemUid) + protected function getItemChangedTime(string $itemType, $itemUid): int { $itemTypeHasStartTimeColumn = false; $changedTimeColumns = $GLOBALS['TCA'][$itemType]['ctrl']['tstamp']; @@ -389,14 +420,12 @@ protected function getItemChangedTime($itemType, $itemUid) // if start time exists and start time is higher than last changed timestamp // then set changed to the future start time to make the item // indexed at a later time - $changedTime = max( + return (int)max( $itemChangedTime, $pageChangedTime, $localizationsChangedTime, $startTime ); - - return $changedTime; } /** @@ -404,25 +433,29 @@ protected function getItemChangedTime($itemType, $itemUid) * * @param array $page Partial page record * @return int Timestamp of the most recent content element change + * @throws DBALDriverException + * @throws DBALException|\Doctrine\DBAL\DBALException */ - protected function getPageItemChangedTime(array $page) + protected function getPageItemChangedTime(array $page): int { if (!empty($page['content_from_pid'])) { // canonical page, get the original page's last changed time return $this->queueItemRepository->getPageItemChangedTimeByPageUid((int)$page['content_from_pid']); } - return $this->queueItemRepository->getPageItemChangedTimeByPageUid((int)$page['uid']); + return $this->queueItemRepository->getPageItemChangedTimeByPageUid((int)$page['uid']) ?? 0; } /** * Checks whether the Index Queue contains a specific item. * * @param string $itemType The item's type, usually a table name. - * @param string $itemUid The item's uid, usually an integer uid, could be a + * @param int|string $itemUid The item's uid, usually an integer uid, could be a * different value for non-database-record types. * @return bool TRUE if the item is found in the queue, FALSE otherwise + * @throws DBALDriverException + * @throws DBALException|\Doctrine\DBAL\DBALException */ - public function containsItem($itemType, $itemUid) + public function containsItem(string $itemType, $itemUid): bool { return $this->queueItemRepository->containsItem($itemType, (int)$itemUid); } @@ -431,14 +464,16 @@ public function containsItem($itemType, $itemUid) * Checks whether the Index Queue contains a specific item. * * @param string $itemType The item's type, usually a table name. - * @param string $itemUid The item's uid, usually an integer uid, could be a + * @param int|string $itemUid The item's uid, usually an integer uid, could be a * different value for non-database-record types. - * @param integer $rootPageId + * @param int $rootPageId * @return bool TRUE if the item is found in the queue, FALSE otherwise + * @throws DBALDriverException + * @throws DBALException|\Doctrine\DBAL\DBALException */ - public function containsItemWithRootPageId($itemType, $itemUid, $rootPageId) + public function containsItemWithRootPageId(string $itemType, $itemUid, int $rootPageId): bool { - return $this->queueItemRepository->containsItemWithRootPageId($itemType, (int)$itemUid, (int)$rootPageId); + return $this->queueItemRepository->containsItemWithRootPageId($itemType, (int)$itemUid, $rootPageId); } /** @@ -446,12 +481,14 @@ public function containsItemWithRootPageId($itemType, $itemUid, $rootPageId) * marked as indexed. * * @param string $itemType The item's type, usually a table name. - * @param string $itemUid The item's uid, usually an integer uid, could be a + * @param int|string $itemUid The item's uid, usually an integer uid, could be a * different value for non-database-record types. * @return bool TRUE if the item is found in the queue and marked as * indexed, FALSE otherwise + * @throws DBALDriverException + * @throws DBALException|\Doctrine\DBAL\DBALException */ - public function containsIndexedItem($itemType, $itemUid) + public function containsIndexedItem(string $itemType, $itemUid): bool { return $this->queueItemRepository->containsIndexedItem($itemType, (int)$itemUid); } @@ -460,9 +497,12 @@ public function containsIndexedItem($itemType, $itemUid) * Removes an item from the Index Queue. * * @param string $itemType The type of the item to remove, usually a table name. - * @param int $itemUid The uid of the item to remove + * @param int|string $itemUid The uid of the item to remove + * @throws ConnectionException + * @throws DBALException + * @throws Throwable */ - public function deleteItem($itemType, $itemUid) + public function deleteItem(string $itemType, $itemUid) { $this->queueItemRepository->deleteItem($itemType, (int)$itemUid); } @@ -471,8 +511,11 @@ public function deleteItem($itemType, $itemUid) * Removes all items of a certain type from the Index Queue. * * @param string $itemType The type of items to remove, usually a table name. + * @throws ConnectionException + * @throws DBALException + * @throws Throwable */ - public function deleteItemsByType($itemType) + public function deleteItemsByType(string $itemType) { $this->queueItemRepository->deleteItemsByType($itemType); } @@ -484,15 +527,17 @@ public function deleteItemsByType($itemType) * @param Site $site The site to remove items for. * @param string $indexingConfigurationName Name of a specific indexing * configuration + * @throws ConnectionException + * @throws \Doctrine\DBAL\DBALException + * @throws Throwable */ - public function deleteItemsBySite(Site $site, $indexingConfigurationName = '') + public function deleteItemsBySite(Site $site, string $indexingConfigurationName = '') { $this->queueItemRepository->deleteItemsBySite($site, $indexingConfigurationName); } /** * Removes all items from the Index Queue. - * */ public function deleteAllItems() { @@ -504,6 +549,8 @@ public function deleteAllItems() * * @param int $itemId Index Queue item uid * @return Item|null The request Index Queue item or NULL if no item with $itemId was found + * @throws DBALDriverException + * @throws DBALException|\Doctrine\DBAL\DBALException */ public function getItem(int $itemId): ?Item { @@ -514,10 +561,14 @@ public function getItem(int $itemId): ?Item * Gets Index Queue items by type and uid. * * @param string $itemType item type, usually the table name - * @param int $itemUid item uid + * @param int|string $itemUid item uid * @return Item[] An array of items matching $itemType and $itemUid + * @throws ConnectionException + * @throws DBALDriverException + * @throws DBALException + * @throws Throwable */ - public function getItems($itemType, $itemUid) + public function getItems(string $itemType, $itemUid): array { return $this->queueItemRepository->findItemsByItemTypeAndItemUid($itemType, (int)$itemUid); } @@ -526,8 +577,12 @@ public function getItems($itemType, $itemUid) * Returns all items in the queue. * * @return Item[] An array of items + * @throws ConnectionException + * @throws DBALDriverException + * @throws DBALException + * @throws Throwable */ - public function getAllItems() + public function getAllItems(): array { return $this->queueItemRepository->findAll(); } @@ -536,8 +591,10 @@ public function getAllItems() * Returns the number of items for all queues. * * @return int + * @throws DBALDriverException + * @throws DBALException */ - public function getAllItemsCount() + public function getAllItemsCount(): int { return $this->queueItemRepository->count(); } @@ -550,10 +607,16 @@ public function getAllItemsCount() * @param string $indexingConfigurationName * * @return QueueStatistic + * @throws DBALDriverException + * @throws DBALException */ - public function getStatisticsBySite(Site $site, $indexingConfigurationName = '') + public function getStatisticsBySite(Site $site, string $indexingConfigurationName = ''): QueueStatistic { - return $this->queueStatisticsRepository->findOneByRootPidAndOptionalIndexingConfigurationName($site->getRootPageId(), $indexingConfigurationName); + return $this->queueStatisticsRepository + ->findOneByRootPidAndOptionalIndexingConfigurationName( + $site->getRootPageId(), + $indexingConfigurationName + ); } /** @@ -562,8 +625,12 @@ public function getStatisticsBySite(Site $site, $indexingConfigurationName = '') * @param Site $site TYPO3 site * @param int $limit Number of items to get from the queue * @return Item[] Items to index to the given solr server + * @throws ConnectionException + * @throws DBALDriverException + * @throws DBALException + * @throws Throwable */ - public function getItemsToIndex(Site $site, $limit = 50) + public function getItemsToIndex(Site $site, int $limit = 50): array { return $this->queueItemRepository->findItemsToIndex($site, $limit); } @@ -574,8 +641,9 @@ public function getItemsToIndex(Site $site, $limit = 50) * * @param int|Item $item Either the item's Index Queue uid or the complete item * @param string $errorMessage Error message + * @throws DBALException|\Doctrine\DBAL\DBALException */ - public function markItemAsFailed($item, $errorMessage = '') + public function markItemAsFailed($item, string $errorMessage = '') { $this->queueItemRepository->markItemAsFailed($item, $errorMessage); } @@ -584,6 +652,7 @@ public function markItemAsFailed($item, $errorMessage = '') * Sets the timestamp of when an item last has been indexed. * * @param Item $item + * @throws DBALException|\Doctrine\DBAL\DBALException */ public function updateIndexTimeByItem(Item $item) { @@ -595,8 +664,9 @@ public function updateIndexTimeByItem(Item $item) * * @param Item $item * @param int $forcedChangeTime The change time for the item + * @throws DBALException|\Doctrine\DBAL\DBALException */ - public function setForcedChangeTimeByItem(Item $item, $forcedChangeTime) + public function setForcedChangeTimeByItem(Item $item, int $forcedChangeTime = 0) { $this->queueItemRepository->updateChangedTimeByItem($item, $forcedChangeTime); } diff --git a/Classes/IndexQueue/RecordMonitor.php b/Classes/IndexQueue/RecordMonitor.php index 05a2cdf2fa..3eb3999cdc 100644 --- a/Classes/IndexQueue/RecordMonitor.php +++ b/Classes/IndexQueue/RecordMonitor.php @@ -1,5 +1,7 @@ @@ -37,7 +39,7 @@ class RecordMonitor /** * @var EventDispatcherInterface */ - protected $eventDispatcher; + protected EventDispatcherInterface $eventDispatcher; /** * RecordMonitor constructor. @@ -63,7 +65,7 @@ public function processCmdmap_preProcess( ): void { if ($command === 'delete' && $table === 'tt_content' && ($GLOBALS['BE_USER']->workspace ?? null) == 0) { $this->eventDispatcher->dispatch( - new ContentElementDeletedEvent((int)$uid) + new ContentElementDeletedEvent($uid) ); } } @@ -77,11 +79,12 @@ public function processCmdmap_preProcess( * @param int $uid The record's uid * @param mixed $value */ - public function processCmdmap_postProcess($command, $table, $uid, $value): void - { - $uid = (int)$uid; - $table = (string)$table; - + public function processCmdmap_postProcess( + $command, + $table, + $uid, + $value + ): void { if (Util::isDraftRecord($table, $uid)) { // skip workspaces: index only LIVE workspace return; @@ -110,15 +113,18 @@ public function processCmdmap_postProcess($command, $table, $uid, $value): void * * @param string $status Status of the current operation, 'new' or 'update' * @param string $table The table the record belongs to - * @param mixed $uid The record's uid, [integer] or [string] (like 'NEW...') + * @param int|string $uid The record's uid, [integer] or [string] (like 'NEW...') * @param array $fields The record's data * @param DataHandler $tceMain TYPO3 Core Engine parent object - * @return void */ - public function processDatamap_afterDatabaseOperations($status, $table, $uid, array $fields, DataHandler $tceMain): void - { + public function processDatamap_afterDatabaseOperations( + string $status, + string $table, + $uid, + array $fields, + DataHandler $tceMain + ): void { $recordUid = $uid; - $table = (string)$table; if ($this->skipMonitoringOfTable($table)) { return; } diff --git a/Classes/Middleware/FrontendUserAuthenticator.php b/Classes/Middleware/FrontendUserAuthenticator.php index 143ab582e7..199c787c12 100644 --- a/Classes/Middleware/FrontendUserAuthenticator.php +++ b/Classes/Middleware/FrontendUserAuthenticator.php @@ -1,4 +1,5 @@ (array)$pageIndexerRequestHandler->getRequest(), - 'index queue header' => $jsonEncodedParameters + 'index queue header' => $jsonEncodedParameters, ] ); return new JsonResponse(['error' => ['code' => 403, 'message' => 'Invalid Index Queue Request.']], 403); - } $request = $this->tryToAuthenticateFrontendUser($pageIndexerRequestHandler, $request); @@ -100,6 +101,7 @@ public function process(ServerRequestInterface $request, RequestHandlerInterface * @param ServerRequestInterface $request * @return ServerRequestInterface * @noinspection PhpUnused + * @throws MfaRequiredException */ protected function tryToAuthenticateFrontendUser(PageIndexerRequestHandler $handler, ServerRequestInterface $request): ServerRequestInterface { @@ -115,7 +117,6 @@ protected function tryToAuthenticateFrontendUser(PageIndexerRequestHandler $hand /* @var FrontendUserAuthentication $feUser */ $feUser = GeneralUtility::makeInstance(FrontendUserAuthentication::class); $feUser->user[$feUser->username_column] = AuthorizationService::SOLR_INDEXER_USERNAME; - /* @noinspection PhpParamsInspection */ $this->context->setAspect('frontend.user', GeneralUtility::makeInstance(UserAspect::class, $feUser, $groups)); $request = $request->withAttribute('frontend.user', $feUser); $feUser->start($request); @@ -137,8 +138,6 @@ protected function getAccessRootline(PageIndexerRequestHandler $handler): Rootli $stringAccessRootline = $handler->getRequest()->getParameter('accessRootline'); } - /* @noinspection PhpIncompatibleReturnTypeInspection */ return GeneralUtility::makeInstance(Rootline::class, /** @scrutinizer ignore-type */ $stringAccessRootline); } - } diff --git a/Classes/Middleware/PageIndexerFinisher.php b/Classes/Middleware/PageIndexerFinisher.php index 9f54b0d022..febad28aac 100644 --- a/Classes/Middleware/PageIndexerFinisher.php +++ b/Classes/Middleware/PageIndexerFinisher.php @@ -1,5 +1,7 @@ write($content); $response = $response ->withBody($body) - ->withHeader('Content-Length', (string)strlen($content)) - ->withHeader('Content-Type', 'application/json'); + ->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 7a371c2fcb..43fffab5df 100644 --- a/Classes/Middleware/PageIndexerInitialization.php +++ b/Classes/Middleware/PageIndexerInitialization.php @@ -1,5 +1,7 @@ (array)$pageIndexerRequest, - 'index queue header' => $jsonEncodedParameters + 'index queue header' => $jsonEncodedParameters, ] ); return new JsonResponse(['error' => ['code' => 403, 'message' => 'Invalid Index Queue Request.']], 403); diff --git a/Classes/Middleware/SolrRoutingMiddleware.php b/Classes/Middleware/SolrRoutingMiddleware.php index 26f9c4bd23..3d12675d70 100644 --- a/Classes/Middleware/SolrRoutingMiddleware.php +++ b/Classes/Middleware/SolrRoutingMiddleware.php @@ -1,5 +1,7 @@ extractParametersFromUriPath( $request->getUri(), $enhancerConfiguration['routePath'], - (string)$page['slug'] + $page['slug'] ?? '' ); /* @@ -164,7 +166,7 @@ public function process(ServerRequestInterface $request, RequestHandlerInterface $uri = $request->getUri()->withPath( $this->getRoutingService()->cleanupHeadingSlash( $this->language->getBase()->getPath() . - (string)$page['slug'] + $page['slug'] ?? '' ) ); $request = $request->withUri($uri); @@ -225,7 +227,7 @@ protected function getEnhancerConfiguration(Site $site, int $pageUid): ?array protected function extractParametersFromUriPath(UriInterface $uri, string $path, string $pageSlug): array { // URI get path returns the path with given language parameter - // The parameter pageSlug itself does not contains the language parameter. + // The parameter pageSlug itself does not contain the language parameter. $uriPath = $this->getRoutingService()->stripLanguagePrefixFromPath( $this->language, $uri->getPath() @@ -234,11 +236,11 @@ protected function extractParametersFromUriPath(UriInterface $uri, string $path, if ($uriPath === $pageSlug) { return [ $pageSlug, - [] + [], ]; } - // Remove slug from URI path in order the ensure only the arguments left + // Remove slug from URI path in order to ensure only the arguments left if (mb_substr($uriPath, 0, mb_strlen($pageSlug) + 1) === $pageSlug . '/') { $length = mb_strlen($pageSlug) + 1; $uriPath = mb_substr($uriPath, $length, mb_strlen($uriPath) - $length); @@ -255,7 +257,7 @@ protected function extractParametersFromUriPath(UriInterface $uri, string $path, $arguments = []; $process = true; /* - * Extract the slug elements, until the the amount of route elements reached + * Extract the slug elements, until the amount of route elements reached */ do { if (count($uriElements) > count($routeElements)) { @@ -288,7 +290,7 @@ protected function extractParametersFromUriPath(UriInterface $uri, string $path, return [ implode('/', $slugElements), - $arguments + $arguments, ]; } @@ -322,7 +324,7 @@ protected function retrievePageInformation(UriInterface $uri, Site $site): array [ $path, $this->language->getTwoLetterIsoCode(), - $uri->getPath() + $uri->getPath(), ] ) ); @@ -335,7 +337,7 @@ protected function retrievePageInformation(UriInterface $uri, Site $site): array 'Could not resolve page by path "%1$s" and language "%2$s".', [ $uri->getPath(), - $this->language->getTwoLetterIsoCode() + $this->language->getTwoLetterIsoCode(), ] ) ); @@ -348,7 +350,7 @@ protected function retrievePageInformation(UriInterface $uri, Site $site): array 'Path "%1$s" -> slug "%2$s"', [ $path, - $item['slug'] + $item['slug'], ] ) ); @@ -370,7 +372,7 @@ protected function retrievePageInformation(UriInterface $uri, Site $site): array } } } - } while($scan); + } while ($scan); return $page; } diff --git a/Classes/Migrations/Migration.php b/Classes/Migrations/Migration.php index fc06f68a45..240e0c3c96 100644 --- a/Classes/Migrations/Migration.php +++ b/Classes/Migrations/Migration.php @@ -1,5 +1,7 @@ getTasksWithAssignedSite(); $legacySchedulerTaskCount = $taskRows->rowCount(); @@ -41,13 +48,14 @@ public function isNeeded() /** * Main update function called by the extension manager. * - * @return string + * @return array + * @throws DBALException|\Doctrine\DBAL\DBALException */ - public function process() + public function process(): array { $taskRows = $this->getTasksWithAssignedSite(); $legacySchedulerTasks = $taskRows->fetchAll(); - $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable("tx_scheduler_task"); + $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('tx_scheduler_task'); $status = FlashMessage::OK; $title = 'Remove site from scheduler task'; @@ -65,32 +73,31 @@ public function process() ->execute(); $migratedTaskCount += $updatedRows; - } catch (\Throwable $e) { + } catch (Throwable $e) { $failedTaskCount++; $status = FlashMessage::ERROR; } } - $message = 'Migrated ' . (int)$migratedTaskCount . ' scheduler tasks! Update of ' . (int)$failedTaskCount . ' failed!'; + $message = 'Migrated ' . (int)$migratedTaskCount . ' scheduler tasks! Update of ' . $failedTaskCount . ' failed!'; return [$status, $title, $message]; } /** - * @return \Doctrine\DBAL\Driver\Statement|int + * @return DBALDriverStatement|int + * @throws DBALException|\Doctrine\DBAL\DBALException */ protected function getTasksWithAssignedSite() { - $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable("tx_scheduler_task"); - $taskRows = $queryBuilder + $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('tx_scheduler_task'); + return $queryBuilder ->select('uid', 'serialized_task_object') - ->from("tx_scheduler_task") + ->from('tx_scheduler_task') ->where( $queryBuilder->expr()->andX( $queryBuilder->expr()->like('serialized_task_object', "'%ApacheSolrForTypo3%'"), $queryBuilder->expr()->like('serialized_task_object', "'%site\";O:28:\"%'") ) )->execute(); - - return $taskRows; } } diff --git a/Classes/Mvc/Controller/SolrControllerContext.php b/Classes/Mvc/Controller/SolrControllerContext.php index 4920b9b308..6c6ea6fb73 100644 --- a/Classes/Mvc/Controller/SolrControllerContext.php +++ b/Classes/Mvc/Controller/SolrControllerContext.php @@ -1,5 +1,7 @@ typoScriptConfiguration; } @@ -63,9 +64,9 @@ public function setSearchResultSet(SearchResultSet $searchResultSet) } /** - * @return SearchResultSet + * @return SearchResultSet|null */ - public function getSearchResultSet() + public function getSearchResultSet(): ?SearchResultSet { return $this->searchResultSet; } diff --git a/Classes/NoSolrConnectionFoundException.php b/Classes/NoSolrConnectionFoundException.php index 212cb54397..cc71030a0d 100644 --- a/Classes/NoSolrConnectionFoundException.php +++ b/Classes/NoSolrConnectionFoundException.php @@ -1,5 +1,7 @@ pageId; } public function setPageId($pageId) { - $this->pageId = intval($pageId); + $this->pageId = (int)$pageId; } - public function getLanguageId() + public function getLanguageId(): ?int { return $this->languageId; } - public function setLanguageId($languageId) + public function setLanguageId(int $languageId) { - $this->languageId = intval($languageId); + $this->languageId = $languageId; } - public function getRootPageId() + public function getRootPageId(): ?int { return $this->rootPageId; } - public function setRootPageId($rootPageId) + public function setRootPageId(int $rootPageId) { - $this->rootPageId = intval($rootPageId); + $this->rootPageId = $rootPageId; } } diff --git a/Classes/PageDocumentPostProcessor.php b/Classes/PageDocumentPostProcessor.php index 5871c9250d..1d69d25cb0 100644 --- a/Classes/PageDocumentPostProcessor.php +++ b/Classes/PageDocumentPostProcessor.php @@ -1,5 +1,7 @@ resultSet->getAllResultCount(); } - } diff --git a/Classes/PingFailedException.php b/Classes/PingFailedException.php index 7497d2c194..8576b798ea 100644 --- a/Classes/PingFailedException.php +++ b/Classes/PingFailedException.php @@ -1,5 +1,7 @@ */ -class PingFailedException extends \Exception {} +class PingFailedException extends Exception +{ +} diff --git a/Classes/Query/Modifier/Elevation.php b/Classes/Query/Modifier/Elevation.php index 35ea4e7425..2679afae4e 100644 --- a/Classes/Query/Modifier/Elevation.php +++ b/Classes/Query/Modifier/Elevation.php @@ -1,5 +1,7 @@ queryBuilder->startFrom($query)->useElevationFromTypoScript()->getQuery(); - return $query; + return $this->queryBuilder + ->startFrom($query) + ->useElevationFromTypoScript() + ->getQuery(); } } diff --git a/Classes/Query/Modifier/Faceting.php b/Classes/Query/Modifier/Faceting.php index b44c7198ea..b2ba2e132c 100644 --- a/Classes/Query/Modifier/Faceting.php +++ b/Classes/Query/Modifier/Faceting.php @@ -1,6 +1,6 @@ getSearchFacetingFacets(); $facetParameters = $this->buildFacetingParameters($allFacets, $typoScriptConfiguration); foreach ($facetParameters as $facetParameter => $value) { - if(strtolower($facetParameter) === 'facet.field') { + if (strtolower($facetParameter) === 'facet.field') { $faceting->setFields($value); } else { $faceting->addAdditionalParameter($facetParameter, $value); @@ -93,9 +93,6 @@ public function modifyQuery(Query $query): Query } $searchArguments = $this->searchRequest->getArguments(); - if (!is_array($searchArguments)) { - return $query; - } $keepAllFacetsOnSelection = $typoScriptConfiguration->getSearchFacetingKeepAllFacetsOnSelection(); $facetFilters = $this->addFacetQueryFilters($searchArguments, $keepAllFacetsOnSelection, $allFacets); diff --git a/Classes/Query/Modifier/Modifier.php b/Classes/Query/Modifier/Modifier.php index 058d39c414..97b451c936 100644 --- a/Classes/Query/Modifier/Modifier.php +++ b/Classes/Query/Modifier/Modifier.php @@ -1,5 +1,7 @@ queryBuilder->startFrom($query)->useDebug(true)->getQuery(); } diff --git a/Classes/Report/AbstractSolrStatus.php b/Classes/Report/AbstractSolrStatus.php index 245f9d049f..60cd654974 100644 --- a/Classes/Report/AbstractSolrStatus.php +++ b/Classes/Report/AbstractSolrStatus.php @@ -1,5 +1,7 @@ isPluginInstalled($adminService)) { return null; @@ -92,20 +99,24 @@ protected function checkPluginInstallationStatus(SolrAdminService $adminService) $report = $this->getRenderedReport('AccessFilterPluginInstalledStatusNotInstalled.html', $variables); return GeneralUtility::makeInstance( Status::class, - /** @scrutinizer ignore-type */ 'Access Filter Plugin', - /** @scrutinizer ignore-type */ 'Not Installed', - /** @scrutinizer ignore-type */ $report, - /** @scrutinizer ignore-type */ Status::WARNING + /** @scrutinizer ignore-type */ + 'Access Filter Plugin', + /** @scrutinizer ignore-type */ + 'Not Installed', + /** @scrutinizer ignore-type */ + $report, + /** @scrutinizer ignore-type */ + Status::WARNING ); } /** - * Checks whether the Solr plugin version is up to date. + * Checks whether the Solr plugin version is up-to-date. * * @param SolrAdminService $adminService - * @return null|\TYPO3\CMS\Reports\Status + * @return Status|null */ - protected function checkPluginVersion(SolrAdminService $adminService) + protected function checkPluginVersion(SolrAdminService $adminService): ?Status { if (!($this->isPluginInstalled($adminService) && $this->isPluginOutdated($adminService))) { return null; @@ -117,10 +128,14 @@ protected function checkPluginVersion(SolrAdminService $adminService) return GeneralUtility::makeInstance( Status::class, - /** @scrutinizer ignore-type */ 'Access Filter Plugin', - /** @scrutinizer ignore-type */ 'Outdated', - /** @scrutinizer ignore-type */ $report, - /** @scrutinizer ignore-type */ Status::WARNING + /** @scrutinizer ignore-type */ + 'Access Filter Plugin', + /** @scrutinizer ignore-type */ + 'Outdated', + /** @scrutinizer ignore-type */ + $report, + /** @scrutinizer ignore-type */ + Status::WARNING ); } @@ -131,7 +146,7 @@ protected function checkPluginVersion(SolrAdminService $adminService) * @param SolrAdminService $adminService * @return bool True if the plugin is installed, FALSE otherwise. */ - protected function isPluginInstalled(SolrAdminService $adminService) + protected function isPluginInstalled(SolrAdminService $adminService): bool { $accessFilterQueryParserPluginInstalled = false; @@ -149,12 +164,10 @@ protected function isPluginInstalled(SolrAdminService $adminService) * @param SolrAdminService $adminService * @return bool True if the plugin is outdated, FALSE if it meets the current version recommendation. */ - protected function isPluginOutdated(SolrAdminService $adminService) + protected function isPluginOutdated(SolrAdminService $adminService): bool { $pluginVersion = $this->getInstalledPluginVersion($adminService); - $pluginVersionOutdated = version_compare($pluginVersion, self::RECOMMENDED_PLUGIN_VERSION, '<'); - - return $pluginVersionOutdated; + return version_compare($pluginVersion, self::RECOMMENDED_PLUGIN_VERSION, '<'); } /** @@ -163,7 +176,7 @@ protected function isPluginOutdated(SolrAdminService $adminService) * @param SolrAdminService $adminService * @return string The installed plugin's version number. */ - public function getInstalledPluginVersion(SolrAdminService $adminService) + public function getInstalledPluginVersion(SolrAdminService $adminService): string { $pluginsInformation = $adminService->getPluginsInformation(); @@ -173,8 +186,6 @@ public function getInstalledPluginVersion(SolrAdminService $adminService) $rawVersion = $matches['version'][0] ?? ''; $explodedRawVersion = explode('-', $rawVersion); - $version = $explodedRawVersion[0]; - - return $version; + return $explodedRawVersion[0] ?? ''; } } diff --git a/Classes/Report/AllowUrlFOpenStatus.php b/Classes/Report/AllowUrlFOpenStatus.php index 299936d3e2..675361c0cd 100644 --- a/Classes/Report/AllowUrlFOpenStatus.php +++ b/Classes/Report/AllowUrlFOpenStatus.php @@ -1,5 +1,7 @@ php.net.'; - $reports[] = GeneralUtility::makeInstance(Status::class, + $reports[] = GeneralUtility::makeInstance( + Status::class, 'PHP filter_var() bug', 'Affected PHP version detected.', $message, diff --git a/Classes/Report/SchemaStatus.php b/Classes/Report/SchemaStatus.php index 21d7376caa..27e2c6a60a 100644 --- a/Classes/Report/SchemaStatus.php +++ b/Classes/Report/SchemaStatus.php @@ -1,5 +1,7 @@ */ class SchemaStatus extends AbstractSolrStatus { - /** * The schema name property is constructed as follows: * @@ -47,11 +50,15 @@ class SchemaStatus extends AbstractSolrStatus * Solr server. Only adds an entry if a schema other than the * recommended one was found. * + * @throws DBALDriverException + * @throws Throwable + * + * @noinspection PhpMissingReturnTypeInspection see {@link \TYPO3\CMS\Reports\StatusProviderInterface::getStatus()} */ public function getStatus() { $reports = []; - /** @var $connectionManager ConnectionManager */ + /** @var $connectionManager ConnectionManager */ $connectionManager = GeneralUtility::makeInstance(ConnectionManager::class); $solrConnections = $connectionManager->getAllConnections(); @@ -60,13 +67,17 @@ public function getStatus() /** @var $solrConnection SolrConnection */ if (!$adminService->ping()) { $url = $adminService->__toString(); - $pingFailedMsg = 'Could not ping solr server, can not check version ' . (string)$url; + $pingFailedMsg = 'Could not ping solr server, can not check version ' . $url; $status = GeneralUtility::makeInstance( Status::class, - /** @scrutinizer ignore-type */ 'Apache Solr Version', - /** @scrutinizer ignore-type */ 'Not accessible', - /** @scrutinizer ignore-type */ $pingFailedMsg, - /** @scrutinizer ignore-type */ Status::ERROR + /** @scrutinizer ignore-type */ + 'Apache Solr Version', + /** @scrutinizer ignore-type */ + 'Not accessible', + /** @scrutinizer ignore-type */ + $pingFailedMsg, + /** @scrutinizer ignore-type */ + Status::ERROR ); $reports[] = $status; continue; @@ -78,10 +89,14 @@ public function getStatus() $report = $this->getRenderedReport('SchemaStatus.html', $variables); $status = GeneralUtility::makeInstance( Status::class, - /** @scrutinizer ignore-type */ 'Schema Version', - /** @scrutinizer ignore-type */ 'Unsupported Schema', - /** @scrutinizer ignore-type */ $report, - /** @scrutinizer ignore-type */ Status::WARNING + /** @scrutinizer ignore-type */ + 'Schema Version', + /** @scrutinizer ignore-type */ + 'Unsupported Schema', + /** @scrutinizer ignore-type */ + $report, + /** @scrutinizer ignore-type */ + Status::WARNING ); $reports[] = $status; } diff --git a/Classes/Report/SiteHandlingStatus.php b/Classes/Report/SiteHandlingStatus.php index b2585457b6..961d660489 100644 --- a/Classes/Report/SiteHandlingStatus.php +++ b/Classes/Report/SiteHandlingStatus.php @@ -1,5 +1,7 @@ http[s] * * Entry Point[base] authority expects -> [user-info@]host[:port] */ @@ -36,6 +39,9 @@ class SiteHandlingStatus extends AbstractSolrStatus { const TITLE_SITE_HANDLING_CONFIGURATION = 'Site handling configuration'; + /** + * @var string + */ const CSS_STATUS_NOTICE = 'notice', CSS_STATUS_INFO = 'info', @@ -48,27 +54,32 @@ class SiteHandlingStatus extends AbstractSolrStatus * * @var SiteRepository */ - protected $siteRepository = null; + protected $siteRepository; /** * @var ExtensionConfiguration */ - protected $extensionConfiguration = null; + protected $extensionConfiguration; /** * SolrStatus constructor. - * @param ExtensionConfiguration $extensionConfiguration + * @param ExtensionConfiguration|null $extensionConfiguration * @param SiteRepository|null $siteRepository */ - public function __construct(ExtensionConfiguration $extensionConfiguration = null, SiteRepository $siteRepository = null) - { + public function __construct( + ExtensionConfiguration $extensionConfiguration = null, + SiteRepository $siteRepository = null + ) { $this->extensionConfiguration = $extensionConfiguration ?? GeneralUtility::makeInstance(ExtensionConfiguration::class); $this->siteRepository = $siteRepository ?? GeneralUtility::makeInstance(SiteRepository::class); } /** * @return array - * @throws Exception + * + * @throws DBALDriverException + * @throws Throwable + * @noinspection PhpMissingReturnTypeInspection see {@link \TYPO3\CMS\Reports\StatusProviderInterface::getStatus()} */ public function getStatus() { @@ -79,10 +90,14 @@ public function getStatus() if (!($site instanceof Site)) { $reports[] = GeneralUtility::makeInstance( Status::class, - /** @scrutinizer ignore-type */ self::TITLE_SITE_HANDLING_CONFIGURATION, - /** @scrutinizer ignore-type */ 'Something went wrong', - /** @scrutinizer ignore-type */ vsprintf('The configured Site "%s" is not TYPO3 managed site. Please refer to TYPO3 site management docs and configure the site properly.', [$site->getLabel()]), - /** @scrutinizer ignore-type */ Status::ERROR + /** @scrutinizer ignore-type */ + self::TITLE_SITE_HANDLING_CONFIGURATION, + /** @scrutinizer ignore-type */ + 'Something went wrong', + /** @scrutinizer ignore-type */ + vsprintf('The configured Site "%s" is not TYPO3 managed site. Please refer to TYPO3 site management docs and configure the site properly.', [$site->getLabel()]), + /** @scrutinizer ignore-type */ + Status::ERROR ); continue; } @@ -101,7 +116,7 @@ public function getStatus() protected function generateValidationReportForSingleSite(Typo3Site $ypo3Site): Status { $variables = [ - 'identifier' => $ypo3Site->getIdentifier() + 'identifier' => $ypo3Site->getIdentifier(), ]; $globalPassedStateForThisSite = true; @@ -111,9 +126,9 @@ protected function generateValidationReportForSingleSite(Typo3Site $ypo3Site): S 'label' => 'Language: ' . $siteLanguage->getTitle(), 'message' => 'No checks: The language is disabled in site configuration.', 'CSSClassesFor' => [ - 'tr' => self::CSS_STATUS_NOTICE + 'tr' => self::CSS_STATUS_NOTICE, ], - 'passed' => true + 'passed' => true, ]; continue; } @@ -123,18 +138,21 @@ protected function generateValidationReportForSingleSite(Typo3Site $ypo3Site): S $renderedReport = $this->getRenderedReport('SiteHandlingStatus.html', $variables); /* @var Status $status */ - $status = GeneralUtility::makeInstance( + return GeneralUtility::makeInstance( Status::class, - /** @scrutinizer ignore-type */ sprintf('Site Identifier: "%s"', $ypo3Site->getIdentifier()), - /** @scrutinizer ignore-type */ '', - /** @scrutinizer ignore-type */ $renderedReport, - /** @scrutinizer ignore-type */ $globalPassedStateForThisSite == true ? Status::OK : Status::ERROR + /** @scrutinizer ignore-type */ + sprintf('Site Identifier: "%s"', $ypo3Site->getIdentifier()), + /** @scrutinizer ignore-type */ + '', + /** @scrutinizer ignore-type */ + $renderedReport, + /** @scrutinizer ignore-type */ + $globalPassedStateForThisSite == true ? Status::OK : Status::ERROR ); - return $status; } /** - * Generates the validation result array for using them in standalone view as an table row. + * Generates the validation result array for using them in standalone view as a table row. * * @param SiteLanguage $siteLanguage * @return array @@ -145,16 +163,25 @@ protected function generateValidationResultsForSingleSiteLanguage(SiteLanguage $ 'label' => 'Language: ' . $siteLanguage->getTitle(), 'passed' => true, 'CSSClassesFor' => [ - 'tr' => self::CSS_STATUS_OK - ] + 'tr' => self::CSS_STATUS_OK, + ], ]; if (!GeneralUtility::isValidUrl((string)$siteLanguage->getBase())) { - $validationResult['message'] = sprintf('Entry Point[base]="%s" is not valid URL. Following parts of defined URL are empty or invalid: "%s"', (string)$siteLanguage->getBase(), $this->fetchInvalidPartsOfUri($siteLanguage->getBase())); + $validationResult['message'] = + sprintf( + 'Entry Point[base]="%s" is not valid URL.' + . ' Following parts of defined URL are empty or invalid: "%s"', + $siteLanguage->getBase()->__toString(), + $this->fetchInvalidPartsOfUri($siteLanguage->getBase()) + ); $validationResult['passed'] = false; $validationResult['CSSClassesFor']['tr'] = self::CSS_STATUS_ERROR; } else { - $validationResult['message'] = sprintf('Entry Point[base]="%s" is valid URL.', (string)$siteLanguage->getBase()); + $validationResult['message'] = sprintf( + 'Entry Point[base]="%s" is valid URL.', + $siteLanguage->getBase()->__toString() + ); } return $validationResult; diff --git a/Classes/Report/SolrConfigStatus.php b/Classes/Report/SolrConfigStatus.php index a90c40306e..d808863b38 100644 --- a/Classes/Report/SolrConfigStatus.php +++ b/Classes/Report/SolrConfigStatus.php @@ -1,5 +1,7 @@ getRenderedReport('SolrConfigStatus.html', $variables); $status = GeneralUtility::makeInstance( Status::class, - /** @scrutinizer ignore-type */ 'Solrconfig Version', - /** @scrutinizer ignore-type */ 'Unsupported solrconfig.xml', - /** @scrutinizer ignore-type */ $report, - /** @scrutinizer ignore-type */ Status::WARNING + /** @scrutinizer ignore-type */ + 'Solrconfig Version', + /** @scrutinizer ignore-type */ + 'Unsupported solrconfig.xml', + /** @scrutinizer ignore-type */ + $report, + /** @scrutinizer ignore-type */ + Status::WARNING ); $reports[] = $status; diff --git a/Classes/Report/SolrConfigurationStatus.php b/Classes/Report/SolrConfigurationStatus.php index 155fb063a1..fdcf242d85 100644 --- a/Classes/Report/SolrConfigurationStatus.php +++ b/Classes/Report/SolrConfigurationStatus.php @@ -1,5 +1,7 @@ @@ -41,19 +43,17 @@ class SolrConfigurationStatus extends AbstractSolrStatus /** * @var FrontendEnvironment */ - protected $frontendEnvironment = null; + protected $frontendEnvironment; /** * SolrConfigurationStatus constructor. * @param ExtensionConfiguration|null $extensionConfiguration * @param FrontendEnvironment|null $frontendEnvironment - */ public function __construct( ExtensionConfiguration $extensionConfiguration = null, FrontendEnvironment $frontendEnvironment = null - ) - { + ) { $this->extensionConfiguration = $extensionConfiguration ?? GeneralUtility::makeInstance(ExtensionConfiguration::class); $this->frontendEnvironment = $frontendEnvironment ?? GeneralUtility::makeInstance(FrontendEnvironment::class); } @@ -62,7 +62,10 @@ public function __construct( * Compiles a collection of configuration status checks. * * @return array - * @noinspection PhpMissingReturnTypeInspection + * + * @throws DBALDriverException + * + * @noinspection PhpMissingReturnTypeInspection see {@link \TYPO3\CMS\Reports\StatusProviderInterface::getStatus()} */ public function getStatus() { @@ -88,7 +91,7 @@ public function getStatus() * Checks whether the "Use as Root Page" page property has been set for any * site. * - * @return null|Status An error status is returned if no root pages were found. + * @return Status|null An error status is returned if no root pages were found. */ protected function getRootPageFlagStatus(): ?Status { @@ -100,10 +103,14 @@ protected function getRootPageFlagStatus(): ?Status $report = $this->getRenderedReport('RootPageFlagStatus.html'); return GeneralUtility::makeInstance( Status::class, - /** @scrutinizer ignore-type */ 'Sites', - /** @scrutinizer ignore-type */ 'No sites found', - /** @scrutinizer ignore-type */ $report, - /** @scrutinizer ignore-type */ Status::ERROR + /** @scrutinizer ignore-type */ + 'Sites', + /** @scrutinizer ignore-type */ + 'No sites found', + /** @scrutinizer ignore-type */ + $report, + /** @scrutinizer ignore-type */ + Status::ERROR ); } @@ -111,7 +118,8 @@ protected function getRootPageFlagStatus(): ?Status * Checks whether config.index_enable is set to 1, otherwise indexing will * not work. * - * @return null|Status An error status is returned for each site root page config.index_enable = 0. + * @return Status|null An error status is returned for each site root page config.index_enable = 0. + * @throws DBALDriverException */ protected function getConfigIndexEnableStatus(): ?Status { @@ -123,10 +131,14 @@ protected function getConfigIndexEnableStatus(): ?Status $report = $this->getRenderedReport('SolrConfigurationStatusIndexing.html', ['pages' => $rootPagesWithIndexingOff]); return GeneralUtility::makeInstance( Status::class, - /** @scrutinizer ignore-type */ 'Page Indexing', - /** @scrutinizer ignore-type */ 'Indexing is disabled', - /** @scrutinizer ignore-type */ $report, - /** @scrutinizer ignore-type */ Status::WARNING + /** @scrutinizer ignore-type */ + 'Page Indexing', + /** @scrutinizer ignore-type */ + 'Indexing is disabled', + /** @scrutinizer ignore-type */ + $report, + /** @scrutinizer ignore-type */ + Status::WARNING ); } @@ -134,6 +146,7 @@ protected function getConfigIndexEnableStatus(): ?Status * Returns an array of rootPages where the indexing is off and EXT:solr is enabled. * * @return array + * @throws DBALDriverException */ protected function getRootPagesWithIndexingOff(): array { @@ -183,6 +196,7 @@ protected function getRootPages(): array * * @param int $pageUid * @return bool + * @throws DBALDriverException */ protected function getIsSolrEnabled(int $pageUid): bool { @@ -194,6 +208,7 @@ protected function getIsSolrEnabled(int $pageUid): bool * * @param int $pageUid * @return bool + * @throws DBALDriverException */ protected function getIsIndexingEnabled(int $pageUid): bool { diff --git a/Classes/Report/SolrStatus.php b/Classes/Report/SolrStatus.php index 74e4a16f61..9c1f46fa6c 100644 --- a/Classes/Report/SolrStatus.php +++ b/Classes/Report/SolrStatus.php @@ -1,5 +1,7 @@ */ class SolrStatus extends AbstractSolrStatus { - /** * Site Repository * * @var SiteRepository */ - protected $siteRepository = null; + protected $siteRepository; /** * Connection Manager * * @var ConnectionManager */ - protected $connectionManager = null; + protected $connectionManager; /** * Holds the response status * * @var int */ - protected $responseStatus = Status::OK; + protected int $responseStatus = Status::OK; /** * Holds the response message build by the checks * * @var string */ - protected $responseMessage = ''; - + protected string $responseMessage = ''; /** * SolrStatus constructor. @@ -76,6 +76,10 @@ public function __construct(SiteRepository $siteRepository = null, ConnectionMan /** * Compiles a collection of status checks against each configured Solr server. * + * @throws DBALDriverException + * @throws Throwable + * + * @noinspection PhpMissingReturnTypeInspection see {@link \TYPO3\CMS\Reports\StatusProviderInterface::getStatus()} */ public function getStatus() { @@ -95,7 +99,7 @@ public function getStatus() * @param array $solrConnection Solr connection parameters * @return Status Status of the Solr connection */ - protected function getConnectionStatus(array $solrConnection) + protected function getConnectionStatus(array $solrConnection): Status { $header = 'Your site has contacted the Apache Solr server.'; $this->responseStatus = Status::OK; @@ -122,16 +126,20 @@ protected function getConnectionStatus(array $solrConnection) 'pingTime' => $pingTime, 'configName' => $configName, 'schemaName' => $schemaName, - 'accessFilter' => $accessFilter + 'accessFilter' => $accessFilter, ]; $report = $this->getRenderedReport('SolrStatus.html', $variables); return GeneralUtility::makeInstance( Status::class, - /** @scrutinizer ignore-type */ 'Apache Solr', - /** @scrutinizer ignore-type */ '', - /** @scrutinizer ignore-type */ $report, - /** @scrutinizer ignore-type */ $this->responseStatus + /** @scrutinizer ignore-type */ + 'Apache Solr', + /** @scrutinizer ignore-type */ + '', + /** @scrutinizer ignore-type */ + $report, + /** @scrutinizer ignore-type */ + $this->responseStatus ); } @@ -141,11 +149,11 @@ protected function getConnectionStatus(array $solrConnection) * @param SolrAdminService $solr * @return string solr version */ - protected function checkSolrVersion(SolrAdminService $solr) + protected function checkSolrVersion(SolrAdminService $solr): string { try { $solrVersion = $this->formatSolrVersion($solr->getSolrServerVersion()); - } catch (\Throwable $e) { + } catch (Throwable $e) { $this->responseStatus = Status::ERROR; $solrVersion = 'Error getting solr version: ' . $e->getMessage(); } @@ -159,13 +167,13 @@ protected function checkSolrVersion(SolrAdminService $solr) * @param SolrAdminService $solrAdminService * @return string */ - protected function checkAccessFilter(SolrAdminService $solrAdminService) + protected function checkAccessFilter(SolrAdminService $solrAdminService): string { try { $accessFilterPluginStatus = GeneralUtility::makeInstance(AccessFilterPluginInstalledStatus::class); $accessFilterPluginVersion = $accessFilterPluginStatus->getInstalledPluginVersion($solrAdminService); $accessFilterMessage = $accessFilterPluginVersion; - } catch (\Throwable $e) { + } catch (Throwable $e) { $this->responseStatus = Status::ERROR; $accessFilterMessage = 'Error getting access filter: ' . $e->getMessage(); } @@ -178,7 +186,7 @@ protected function checkAccessFilter(SolrAdminService $solrAdminService) * @param SolrAdminService $solrAdminService * @return string */ - protected function checkPingTime(SolrAdminService $solrAdminService) + protected function checkPingTime(SolrAdminService $solrAdminService): string { try { $pingQueryTime = $solrAdminService->getPingRoundTripRuntime(); @@ -196,11 +204,11 @@ protected function checkPingTime(SolrAdminService $solrAdminService) * @param SolrAdminService $solrAdminService * @return string */ - protected function checkSolrConfigName(SolrAdminService $solrAdminService) + protected function checkSolrConfigName(SolrAdminService $solrAdminService): string { try { $solrConfigMessage = $solrAdminService->getSolrconfigName(); - } catch (\Throwable $e) { + } catch (Throwable $e) { $this->responseStatus = Status::ERROR; $solrConfigMessage = 'Error determining solr config: ' . $e->getMessage(); } @@ -214,11 +222,11 @@ protected function checkSolrConfigName(SolrAdminService $solrAdminService) * @param SolrAdminService $solrAdminService * @return string */ - protected function checkSolrSchemaName(SolrAdminService $solrAdminService) + protected function checkSolrSchemaName(SolrAdminService $solrAdminService): string { try { $solrSchemaMessage = $solrAdminService->getSchema()->getName(); - } catch (\Throwable $e) { + } catch (Throwable $e) { $this->responseStatus = Status::ERROR; $solrSchemaMessage = 'Error determining schema name: ' . $e->getMessage(); } @@ -227,15 +235,15 @@ protected function checkSolrSchemaName(SolrAdminService $solrAdminService) } /** - * Formats the Apache Solr server version number. By default this is going + * Formats the Apache Solr server version number. By default, this is going * to be the simple major.minor.patch-level version. Custom Builds provide - * more information though, in case of custom builds, their complete + * more information though, in case of custom-builds, their complete * version will be added, too. * - * @param string $solrVersion Unformatted Apache Solr version number as provided by Solr. - * @return string formatted short version number, in case of custom builds followed by the complete version number + * @param string $solrVersion Unformatted Apache Solr version number a provided by Solr. + * @return string formatted short version number, in case of custom-builds followed by the complete version number */ - protected function formatSolrVersion($solrVersion) + protected function formatSolrVersion(string $solrVersion): string { $explodedSolrVersion = explode('.', $solrVersion); diff --git a/Classes/Report/SolrVersionStatus.php b/Classes/Report/SolrVersionStatus.php index 19f5d2398a..b1cdbc0710 100644 --- a/Classes/Report/SolrVersionStatus.php +++ b/Classes/Report/SolrVersionStatus.php @@ -1,5 +1,7 @@ ping()) { $url = $coreAdmin->__toString(); - $pingFailedMsg = 'Could not ping solr server, can not check version ' . (string)$url; + $pingFailedMsg = 'Could not ping solr server, can not check version ' . $url; $status = GeneralUtility::makeInstance( Status::class, - /** @scrutinizer ignore-type */ 'Apache Solr Version', - /** @scrutinizer ignore-type */ 'Not accessible', - /** @scrutinizer ignore-type */ $pingFailedMsg, - /** @scrutinizer ignore-type */ Status::ERROR + /** @scrutinizer ignore-type */ + 'Apache Solr Version', + /** @scrutinizer ignore-type */ + 'Not accessible', + /** @scrutinizer ignore-type */ + $pingFailedMsg, + /** @scrutinizer ignore-type */ + Status::ERROR ); $reports[] = $status; continue; @@ -75,10 +86,14 @@ public function getStatus() $report = $this->getRenderedReport('SolrVersionStatus.html', $variables); $status = GeneralUtility::makeInstance( Status::class, - /** @scrutinizer ignore-type */ 'Apache Solr Version', - /** @scrutinizer ignore-type */ 'Outdated, Unsupported', - /** @scrutinizer ignore-type */ $report, - /** @scrutinizer ignore-type */ Status::ERROR + /** @scrutinizer ignore-type */ + 'Apache Solr Version', + /** @scrutinizer ignore-type */ + 'Outdated, Unsupported', + /** @scrutinizer ignore-type */ + $report, + /** @scrutinizer ignore-type */ + Status::ERROR ); $reports[] = $status; @@ -91,30 +106,28 @@ public function getStatus() * Gets the clean Solr version in case of a custom build which may have * additional information in the version string. * - * @param string $solrVersion Unformatted Apache Solr version number as provided by Solr. - * @return string Clean Solr version number: mayor.minor.patchlevel + * @param string $solrVersion Unformatted Apache Solr version number a provided by Solr. + * @return string Clean Solr version number: mayor.minor.patch-level */ - protected function getCleanSolrVersion($solrVersion) + protected function getCleanSolrVersion(string $solrVersion): string { $explodedSolrVersion = explode('.', $solrVersion); - $shortSolrVersion = $explodedSolrVersion[0] + return $explodedSolrVersion[0] . '.' . $explodedSolrVersion[1] . '.' . $explodedSolrVersion[2]; - - return $shortSolrVersion; } /** - * Formats the Apache Solr server version number. By default this is going + * Formats the Apache Solr server version number. By default, this is going * to be the simple major.minor.patch-level version. Custom Builds provide - * more information though, in case of custom builds, their complete + * more information though, in case of custom-builds, their complete * version will be added, too. * - * @param string $solrVersion Unformatted Apache Solr version number as provided by Solr. - * @return string formatted short version number, in case of custom builds followed by the complete version number + * @param string $solrVersion Unformatted Apache Solr version number a provided by Solr. + * @return string formatted short version number, in case of custom-builds followed by the complete version number */ - protected function formatSolrVersion($solrVersion) + protected function formatSolrVersion(string $solrVersion): string { $shortSolrVersion = $this->getCleanSolrVersion($solrVersion); $formattedSolrVersion = $shortSolrVersion; diff --git a/Classes/Response/Processor/ResponseProcessor.php b/Classes/Response/Processor/ResponseProcessor.php index bd3cf266cb..951d0624ee 100644 --- a/Classes/Response/Processor/ResponseProcessor.php +++ b/Classes/Response/Processor/ResponseProcessor.php @@ -1,5 +1,7 @@ */ interface ResponseProcessor { - /** * Processes a query and its response after searching for that query. * * @param Query $query The query that has been searched for. * @param ResponseAdapter $response The response for the last query. - * @return void */ public function processResponse( Query $query, diff --git a/Classes/Routing/Enhancer/SolrFacetMaskAndCombineEnhancer.php b/Classes/Routing/Enhancer/SolrFacetMaskAndCombineEnhancer.php index e9ae6e4b4c..d5111f3480 100644 --- a/Classes/Routing/Enhancer/SolrFacetMaskAndCombineEnhancer.php +++ b/Classes/Routing/Enhancer/SolrFacetMaskAndCombineEnhancer.php @@ -28,7 +28,7 @@ class SolrFacetMaskAndCombineEnhancer extends AbstractEnhancer implements Routin /** * @var array */ - protected $configuration; + protected array $configuration; /** * @var string @@ -60,10 +60,14 @@ public function enhanceForMatching(RouteCollection $collection): void * * @param Route $defaultPageRoute * @param array $configuration + * + * @todo: Refactor to get cHash expected functionality. + * * @return Route */ protected function getVariant(Route $defaultPageRoute, array $configuration): Route { + /** @noinspection DuplicatedCode copied from \TYPO3\CMS\Core\Routing\Enhancer\PluginEnhancer::getVariant() */ $arguments = $configuration['_arguments'] ?? []; unset($configuration['_arguments']); @@ -87,7 +91,7 @@ protected function getVariant(Route $defaultPageRoute, array $configuration): Ro public function enhanceForGeneration(RouteCollection $collection, array $parameters): void { // No parameter for this namespace given, so this route does not fit the requirements - if (!is_array($parameters[$this->namespace])) { + if (!is_array($parameters[$this->namespace] ?? null)) { return; } /** @var Route $defaultPageRoute */ @@ -177,7 +181,7 @@ protected function combineArrayParameters(array $parameters = []): array $parameterValueNew = $facetValue; } } - if (is_array($parametersCombined[$parameterNameNew])) { + if (is_array($parametersCombined[$parameterNameNew] ?? null)) { $parametersCombined[$parameterNameNew][] = $parameterValueNew; } else { $parametersCombined[$parameterNameNew] = $parameterValueNew; @@ -197,8 +201,8 @@ protected function combineArrayParameters(array $parameters = []): array /** * We need to convert our internal names by hand into hashes. * - * This needs to be done, because we not exactly configure a path inside of the site configuration. - * What we are configure is a placeholder contains information, what we should process + * This needs to be done, because we not exactly configure a path inside the site configuration. + * What we are configuring is a placeholder contains information, what we should process * * @param Route $route * @param array $parameters @@ -213,11 +217,9 @@ protected function replaceVariableWithHash(Route $route, array $parameters = []) $routeArguments = $route->getArguments(); $pathTokens = $route->compile()->getTokens(); - $keepVariables = []; - $pathTokensCount = count($pathTokens); for ($i = 0; $i < $pathTokensCount; $i++) { - // wee only looking for variables + // we're only looking for variables if ($pathTokens[$i][0] !== 'variable') { continue; } @@ -243,7 +245,6 @@ protected function replaceVariableWithHash(Route $route, array $parameters = []) } $parameters[$pathTokens[$i][3]] = $parameters[$parameterName]; - $keepVariables[] = $pathTokens[$i][3]; unset($parameters[$parameterName]); } @@ -270,10 +271,10 @@ protected function inflateUnprocessedVariables(Route $variant, array $deflatedPa foreach ($deflatedParameters as $argumentKey => $argumentPath) { if (in_array($argumentKey, $variablesToHandle)) { - $mixedVariables[$argumentKey] = $deflatedParameters[$argumentKey]; + $mixedVariables[$argumentKey] = $argumentPath; } else { $elements = explode('__', $argumentKey); - $elements[] = $deflatedParameters[$argumentKey]; + $elements[] = $argumentPath; $data = $this->inflateQueryParams($elements); $mixedVariables = array_merge_recursive($mixedVariables, $data); diff --git a/Classes/Routing/Enhancer/SolrRouteEnhancerInterface.php b/Classes/Routing/Enhancer/SolrRouteEnhancerInterface.php index f92116014a..0179b333a9 100644 --- a/Classes/Routing/Enhancer/SolrRouteEnhancerInterface.php +++ b/Classes/Routing/Enhancer/SolrRouteEnhancerInterface.php @@ -22,5 +22,4 @@ */ interface SolrRouteEnhancerInterface { - } diff --git a/Classes/Routing/RoutingService.php b/Classes/Routing/RoutingService.php index ff445fb410..dc3e000882 100644 --- a/Classes/Routing/RoutingService.php +++ b/Classes/Routing/RoutingService.php @@ -1,4 +1,5 @@ containsFacetAndValueSeparator((string)$queryValues[$i])) { + if ($this->containsFacetAndValueSeparator($queryValues[$i])) { [$facetName, $facetValue] = explode( - $this->detectFacetAndValueSeparator((string)$queryValues[$i]), - (string)$queryValues[$i], + $this->detectFacetAndValueSeparator($queryValues[$i]), + $queryValues[$i], 2 ); if ($this->isPathArgument((string)$facetName)) { $queryValues[$i] = $facetValue; } - } $queryValues[$i] = $this->urlFacetPathService->applyCharacterMap($queryValues[$i]); } @@ -314,7 +321,7 @@ public function shouldMaskQueryParameter(): bool } /** - * Masks Solr filter inside of the query parameters + * Masks Solr filter inside the query parameters * * @param array $queryParams * @return array @@ -351,7 +358,7 @@ public function maskQueryParameters(array $queryParams): array $newQueryParams = $queryParams; $newFilterArray = []; - foreach ($newQueryParams[$this->getPluginNamespace()]['filter'] as $queryParamName => $queryParamValue) { + foreach ($newQueryParams[$this->getPluginNamespace()]['filter'] as $queryParamValue) { $defaultSeparator = $this->detectFacetAndValueSeparator((string)$queryParamValue); [$facetName, $facetValue] = explode($defaultSeparator, $queryParamValue, 2); $keep = false; @@ -445,7 +452,7 @@ public function shouldConcatQueryParameters(): bool return true; } - return isset($this->settings['query']['concat']) && (bool)$this->settings['query']['concat']; + return isset($this->settings['query']['concat']) && true === (bool)$this->settings['query']['concat']; } /** @@ -466,7 +473,7 @@ public function getQueryParameterMap(): array $self = $this; return array_filter( $this->settings['query']['map'], - function($value) use ($self) { + function ($value) use ($self) { return !$self->isCoreParameter($value); } ); @@ -662,10 +669,10 @@ public function cleanUpQueryParameters(array $queryParams): array /** * Builds a string out of multiple facet values * - * A facet value could contain the multi value separator. This value have to masked in order to + * A facet value could contain the multi value separator. This value has to be masked in order to * avoid problems during separation of the values later. * - * This mask have to apply before contact the values + * This mask has to be applied before contact the values * * @param array $facets * @return string @@ -791,7 +798,7 @@ public function getDefaultMultiValueSeparator(): string } /** - * Find a enhancer configuration by a given page id + * Find an enhancer configuration by a given page id * * @param int $pageUid * @return array @@ -803,6 +810,7 @@ public function fetchEnhancerByPageUid(int $pageUid): array return []; } + /** @noinspection PhpParamsInspection */ return $this->fetchEnhancerInSiteConfigurationByPageUid( $site, $pageUid @@ -823,7 +831,7 @@ public function fetchEnhancerInSiteConfigurationByPageUid(Site $site, int $pageU return []; } $result = []; - foreach ($configuration['routeEnhancers'] as $routing => $settings) { + foreach ($configuration['routeEnhancers'] as $settings) { // Not the page we are looking for if (isset($settings['limitToPages']) && is_array($settings['limitToPages']) && @@ -852,7 +860,8 @@ public function cleanupHeadingSlash(string $slug): string { if (mb_substr($slug, 0, 1) !== '/') { return '/' . $slug; - } else if (mb_substr($slug, 0, 2) === '//') { + } + if (mb_substr($slug, 0, 2) === '//') { return mb_substr($slug, 1, mb_strlen($slug) - 1); } @@ -898,9 +907,8 @@ public function removeHeadingSlash(string $slug): string public function findSiteByUid(int $pageUid): SiteInterface { try { - $site = $this->getSiteFinder() + return $this->getSiteFinder() ->getSiteByPageId($pageUid); - return $site; } catch (SiteNotFoundException $exception) { return new NullSite(); } @@ -931,13 +939,11 @@ public function convertStringIntoUri(string $base): ?UriInterface { try { /* @var Uri $uri */ - $uri = GeneralUtility::makeInstance( + return GeneralUtility::makeInstance( Uri::class, $base ); - - return $uri; - } catch (\InvalidArgumentException $argumentException) { + } catch (InvalidArgumentException $argumentException) { return null; } } @@ -1018,7 +1024,7 @@ public function isMappingArgument(string $facetName): bool } /** - * Check if given facet type is an path argument + * Check if given facet type is a path argument * * @param string $facetName * @return bool @@ -1034,11 +1040,11 @@ public function isPathArgument(string $facetName): bool */ public function reviewVariable(string $variable): string { - if (!$this->containsFacetAndValueSeparator((string)$variable)) { + if (!$this->containsFacetAndValueSeparator($variable)) { return $variable; } - $separator = $this->detectFacetAndValueSeparator((string)$variable); + $separator = $this->detectFacetAndValueSeparator($variable); [$type, $value] = explode($separator, $variable, 2); return $this->isMappingArgument($type) ? $value : $variable; @@ -1107,7 +1113,7 @@ protected function processUriPathArgument( if (strpos($queryKey, '-') !== false) { [$tmpQueryKey, $filterName] = explode('-', $tmpQueryKey, 2); } - if (!isset($queryParams[$tmpQueryKey]) || $queryParams[$tmpQueryKey] === null) { + if (!isset($queryParams[$tmpQueryKey])) { $queryParams[$tmpQueryKey] = []; } diff --git a/Classes/Routing/UrlFacetService.php b/Classes/Routing/UrlFacetService.php index e68b92d360..8a60443b8f 100644 --- a/Classes/Routing/UrlFacetService.php +++ b/Classes/Routing/UrlFacetService.php @@ -1,4 +1,5 @@ solr = $connectionManager->getConnectionByPageId(($GLOBALS['TSFE']->id ?? null), Util::getLanguageUid()); + $this->solr = $connectionManager->getConnectionByPageId(($GLOBALS['TSFE']->id ?? 0), Util::getLanguageUid()); } $this->configuration = Util::getSolrConfiguration(); @@ -90,7 +98,7 @@ public function __construct(SolrConnection $solrConnection = null) * * @return SolrConnection Solr connection */ - public function getSolrConnection() + public function getSolrConnection(): ?SolrConnection { return $this->solr; } @@ -118,11 +126,10 @@ public function setSolrConnection(SolrConnection $solrConnection) * * @param Query $query The query with keywords, filters, and so on. * @param int $offset Result offset for pagination. - * @param int $limit Maximum number of results to return. If set to NULL, this value is taken from the query object. + * @param int|null $limit Maximum number of results to return. If set to NULL, this value is taken from the query object. * @return ResponseAdapter Solr response - * @throws \Exception */ - public function search(Query $query, $offset = 0, $limit = 10) + public function search(Query $query, int $offset = 0, ?int $limit = null): ?ResponseAdapter { $this->query = $query; @@ -134,16 +141,17 @@ public function search(Query $query, $offset = 0, $limit = 10) try { $response = $this->solr->getReadService()->search($query); if ($this->configuration->getLoggingQueryQueryString()) { - $this->logger->log(SolrLogManager::INFO, + $this->logger->log( + SolrLogManager::INFO, 'Querying Solr, getting result', [ 'query string' => $query->getQuery(), 'query parameters' => $query->getRequestBuilder()->build($query)->getParams(), - 'response' => json_decode($response->getRawResponse(), true) + 'response' => json_decode($response->getRawResponse(), true), ] ); } - } catch (SolrCommunicationException $e) { + } catch (SolrCommunicationException $e) { if ($this->configuration->getLoggingExceptions()) { $this->logger->log( SolrLogManager::ERROR, @@ -152,7 +160,7 @@ public function search(Query $query, $offset = 0, $limit = 10) 'exception' => $e->__toString(), 'query' => (array)$query, 'offset' => $offset, - 'limit' => $query->getRows() + 'limit' => $query->getRows(), ] ); } @@ -170,25 +178,24 @@ public function search(Query $query, $offset = 0, $limit = 10) * * @param bool $useCache Set to true if the cache should be used. * @return bool Returns TRUE on successful ping. - * @throws \Exception Throws an exception in case ping was not successful. */ - public function ping($useCache = true) + public function ping(bool $useCache = true): bool { $solrAvailable = false; try { if (!$this->solr->getReadService()->ping($useCache)) { - throw new \Exception('Solr Server not responding.', 1237475791); + throw new Exception('Solr Server not responding.', 1237475791); } $solrAvailable = true; - } catch (\Throwable $e) { + } catch (Throwable $e) { if ($this->configuration->getLoggingExceptions()) { $this->logger->log( SolrLogManager::ERROR, 'Exception while trying to ping the solr server', [ - $e->__toString() + $e->__toString(), ] ); } @@ -200,9 +207,9 @@ public function ping($useCache = true) /** * Gets the query object. * - * @return Query + * @return Query|null */ - public function getQuery() + public function getQuery(): ?Query { return $this->query; } @@ -210,24 +217,30 @@ public function getQuery() /** * Gets the Solr response * - * @return ResponseAdapter + * @return ResponseAdapter|null */ - public function getResponse() + public function getResponse(): ?ResponseAdapter { return $this->response; } - public function getRawResponse() + /** + * @return string|null + */ + public function getRawResponse(): ?string { return $this->response->getRawResponse(); } - public function getResponseHeader() + /** + * @return stdClass|null + */ + public function getResponseHeader(): ?stdClass { return $this->getResponse()->responseHeader; } - public function getResponseBody() + public function getResponseBody(): ?stdClass { // @extensionScannerIgnoreLine return $this->getResponse()->response; @@ -238,7 +251,7 @@ public function getResponseBody() * * @return int Query time in milliseconds */ - public function getQueryTime() + public function getQueryTime(): int { return $this->getResponseHeader()->QTime; } @@ -248,7 +261,7 @@ public function getQueryTime() * * @return int Number of results per page */ - public function getResultsPerPage() + public function getResultsPerPage(): int { return $this->getResponseHeader()->params->rows; } @@ -258,21 +271,21 @@ public function getResultsPerPage() * * @return int Result offset */ - public function getResultOffset() + public function getResultOffset(): int { // @extensionScannerIgnoreLine return $this->response->response->start; } - public function getDebugResponse() + public function getDebugResponse(): ?stdClass { // @extensionScannerIgnoreLine return $this->response->debug; } - public function getHighlightedContent() + public function getHighlightedContent(): ?stdClass { - $highlightedContent = false; + $highlightedContent = new stdClass(); if ($this->response->highlighting) { $highlightedContent = $this->response->highlighting; diff --git a/Classes/Search/AccessComponent.php b/Classes/Search/AccessComponent.php index 2873689c93..35fee6d8fa 100644 --- a/Classes/Search/AccessComponent.php +++ b/Classes/Search/AccessComponent.php @@ -1,5 +1,7 @@ seachRequest = $searchRequest; + $this->searchRequest = $searchRequest; } /** * Initializes the search component. * * Sets the debug query parameter - * */ public function initializeSearchComponent() { - if ($this->seachRequest->getContextTypoScriptConfiguration()->getEnabledDebugMode()) { + if ($this->searchRequest->getContextTypoScriptConfiguration()->getEnabledDebugMode()) { $this->queryBuilder->startFrom($this->query)->useDebug(true); } } diff --git a/Classes/Search/ElevationComponent.php b/Classes/Search/ElevationComponent.php index c41801feec..a2d54e3c07 100644 --- a/Classes/Search/ElevationComponent.php +++ b/Classes/Search/ElevationComponent.php @@ -1,5 +1,7 @@ query = $this->queryBuilder->startFrom($this->query) - ->useMinimumMatchFromTypoScript() - ->useBoostFunctionFromTypoScript() - ->useSlopsFromTypoScript() - ->useBoostQueriesFromTypoScript() - ->useTieParameterFromTypoScript() - ->getQuery(); + $this->query = $this->queryBuilder + ->startFrom($this->query) + ->useMinimumMatchFromTypoScript() + ->useBoostFunctionFromTypoScript() + ->useSlopsFromTypoScript() + ->useBoostQueriesFromTypoScript() + ->useTieParameterFromTypoScript() + ->getQuery(); } /** diff --git a/Classes/Search/SearchComponent.php b/Classes/Search/SearchComponent.php index 8467627097..64ad69de51 100644 --- a/Classes/Search/SearchComponent.php +++ b/Classes/Search/SearchComponent.php @@ -1,5 +1,7 @@ searchConfiguration['sorting']) && ((int)$this->searchConfiguration['sorting']) === 1; - if(!$isSortingEnabled) { + if (!$isSortingEnabled) { return; } @@ -86,7 +87,7 @@ public function initializeSearchComponent() return; } - // a passed sorting has allways priority an overwrites the configured initial sorting + // a passed sorting has always priority an overwrites the configured initial sorting $this->query->clearSorts(); /** @var $sortHelper SortingHelper */ $sortHelper = GeneralUtility::makeInstance(SortingHelper::class, $this->searchConfiguration['sorting.']['options.']); @@ -101,7 +102,7 @@ public function initializeSearchComponent() * @param array $arguments * @return bool */ - protected function hasValidSorting(array $arguments) + protected function hasValidSorting(array $arguments): bool { return !empty($arguments['sort']) && preg_match('/^([a-z0-9_]+ (asc|desc)[, ]*)*([a-z0-9_]+ (asc|desc))+$/i', $arguments['sort']); } diff --git a/Classes/Search/SpellcheckingComponent.php b/Classes/Search/SpellcheckingComponent.php index aaa81a03ed..d8dcac75a4 100644 --- a/Classes/Search/SpellcheckingComponent.php +++ b/Classes/Search/SpellcheckingComponent.php @@ -1,5 +1,7 @@ seachRequest = $searchRequest; + $this->searchRequest = $searchRequest; } /** * Initializes the search component. - * */ public function initializeSearchComponent() { - $solrConfiguration = $this->seachRequest->getContextTypoScriptConfiguration(); + $solrConfiguration = $this->searchRequest->getContextTypoScriptConfiguration(); if ($solrConfiguration->getStatistics()) { if (empty($GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['solr']['afterSearch']['statistics'])) { @@ -61,5 +61,4 @@ public function initializeSearchComponent() } } } - } diff --git a/Classes/SubstitutePageIndexer.php b/Classes/SubstitutePageIndexer.php index dd45c7807c..f8cb4c8a82 100644 --- a/Classes/SubstitutePageIndexer.php +++ b/Classes/SubstitutePageIndexer.php @@ -1,5 +1,7 @@ getConfigurationOrDefaultValue( - 'pluginNamespaces' - ); + 'pluginNamespaces' + ); return array_unique(GeneralUtility::trimExplode(',', $pluginNamespacesList)); } @@ -122,15 +124,25 @@ public function getAvailablePluginNamespaces(): array public function getCacheHashExcludedParameters(): array { $pluginNamespaces = array_map( - function($pluginNamespace) { + function ($pluginNamespace) { return '^' . $pluginNamespace . '['; }, $this->getAvailablePluginNamespaces() ); + $enhancersRouteParts = array_map( + function ($pluginNamespace) { + // __ \TYPO3\CMS\Core\Routing\Enhancer\VariableProcessor::LEVEL_DELIMITER + return '^' . $pluginNamespace . '__'; + }, + $this->getAvailablePluginNamespaces() + ); + + $exclusions = array_merge($pluginNamespaces, $enhancersRouteParts); + if (false === $this->getIncludeGlobalQParameterInCacheHash()) { - $pluginNamespaces[] = 'q'; + $exclusions[] = 'q'; } - return array_combine($pluginNamespaces, $pluginNamespaces); + return array_combine($exclusions, $exclusions); } /** diff --git a/Classes/System/Configuration/TypoScriptConfiguration.php b/Classes/System/Configuration/TypoScriptConfiguration.php index 77718e5db9..a8060b21ef 100644 --- a/Classes/System/Configuration/TypoScriptConfiguration.php +++ b/Classes/System/Configuration/TypoScriptConfiguration.php @@ -252,8 +252,8 @@ public function mergeSolrConfiguration(array $configurationToMerge, bool $addKey /** * Returns true when ext_solr is enabled * - * @param boolean $defaultIfEmpty - * @return boolean + * @param bool $defaultIfEmpty + * @return bool */ public function getEnabled(bool $defaultIfEmpty = false): bool { @@ -549,7 +549,6 @@ public function getIndexQueueConfigurationRecursiveUpdateFields(string $configur return array_combine($recursiveUpdateFields, $recursiveUpdateFields); } - /** * Retrieves and initialPagesAdditionalWhereClause where clause when configured or an empty string. * @@ -1299,8 +1298,6 @@ public function setSearchQueryFilterConfiguration(array $configuration) /** * Removes the pageSections filter setting. - * - * @return void */ public function removeSearchQueryFilterForPageSections() { @@ -1466,7 +1463,6 @@ public function getSearchResultsSiteHighlighting(bool $defaultIfEmpty = true): b return $this->getBool($isSiteHighlightingEnabled); } - /** * Can be used to check if the highlighting is enabled * @@ -1475,7 +1471,7 @@ public function getSearchResultsSiteHighlighting(bool $defaultIfEmpty = true): b * @param bool $defaultIfEmpty * @return bool */ - public function getSearchResultsHighlighting(bool $defaultIfEmpty = false): bool + public function getIsSearchResultsHighlightingEnabled(bool $defaultIfEmpty = false): bool { $isHighlightingEnabled = $this->getValueByPathOrDefaultValue('plugin.tx_solr.search.results.resultsHighlighting', $defaultIfEmpty); return $this->getBool($isHighlightingEnabled); @@ -1579,7 +1575,7 @@ public function getSearchResultsPerPageSwitchOptionsAsArray(array $defaultIfEmpt * @param int $defaultIfEmpty * @return int */ - public function getMaxPaginatorLinks($defaultIfEmpty = 0) + public function getMaxPaginatorLinks(int $defaultIfEmpty = 0): int { return (int)$this->getValueByPathOrDefaultValue('plugin.tx_solr.search.results.maxPaginatorLinks', $defaultIfEmpty); } @@ -2141,7 +2137,7 @@ public function getSearchAdditionalPersistentArgumentNames(array $defaultIfEmpty * @param bool $defaultIfEmpty * @return bool */ - public function getSearchGrouping(bool $defaultIfEmpty = false): bool + public function getIsSearchGroupingEnabled(bool $defaultIfEmpty = false): bool { $groupingEnabled = $this->getValueByPathOrDefaultValue('plugin.tx_solr.search.grouping', $defaultIfEmpty); return $this->getBool($groupingEnabled); @@ -2194,7 +2190,7 @@ public function getSearchGroupingHighestGroupResultsLimit(?int $defaultIfEmpty = return $highestLimit; } - foreach ($groupingConfiguration['groups.'] as $groupName => $groupConfiguration) { + foreach ($groupingConfiguration['groups.'] as $groupConfiguration) { if (!empty($groupConfiguration['numberOfResultsPerGroup']) && $groupConfiguration['numberOfResultsPerGroup'] > $highestLimit) { $highestLimit = $groupConfiguration['numberOfResultsPerGroup']; } @@ -2221,13 +2217,13 @@ public function getSearchGroupingResultLimit(string $groupName, ?int $defaultIfE $specificResultsPerGroup = $this->getValueByPathOrDefaultValue($specificPath, null); if ($specificResultsPerGroup !== null) { - return (int) $specificResultsPerGroup; + return (int)$specificResultsPerGroup; } $commonPath = 'plugin.tx_solr.search.grouping.numberOfResultsPerGroup'; $commonValue = $this->getValueByPathOrDefaultValue($commonPath, null); if ($commonValue !== null) { - return (int) $commonValue; + return (int)$commonValue; } return $defaultIfEmpty; diff --git a/Classes/System/ContentObject/ContentObjectService.php b/Classes/System/ContentObject/ContentObjectService.php index 995cff662a..66ba41f314 100644 --- a/Classes/System/ContentObject/ContentObjectService.php +++ b/Classes/System/ContentObject/ContentObjectService.php @@ -1,5 +1,7 @@ contentObjectRenderer->cObjGetSingle($name, $conf); } @@ -60,10 +61,10 @@ public function renderSingleContentObject($name = '', $conf = []) * @param string $key * @return string */ - public function renderSingleContentObjectByArrayAndKey($array = [], $key = '') + public function renderSingleContentObjectByArrayAndKey(array $array = [], string $key = '') { - $name = isset($array[$key]) ? $array[$key] : []; - $conf = isset($array[$key . '.']) ? $array[$key . '.'] : ''; + $name = $array[$key] ?? []; + $conf = $array[$key . '.'] ?? ''; if (!is_array($conf)) { return $name; diff --git a/Classes/System/Data/AbstractCollection.php b/Classes/System/Data/AbstractCollection.php index 964d103b35..6bf92d138c 100644 --- a/Classes/System/Data/AbstractCollection.php +++ b/Classes/System/Data/AbstractCollection.php @@ -1,5 +1,7 @@ data = []; } /** - * This method can be used to pass a closure to created a filtered copy. - * The closure get an collection item passed and needs to return true when the item should + * This method can be used to pass a closure to create a filtered copy. + * The closure get a collection item passed and needs to return true when the item should * be kept or false when it can be skipped. * - * @param callable $filter + * @param Closure $filter * @return AbstractCollection */ - public function getFilteredCopy(\Closure $filter) + public function getFilteredCopy(Closure $filter): AbstractCollection { $copy = clone $this; $filteredData = []; @@ -79,16 +86,16 @@ public function getIterator(): Traversable /** * @return array */ - public function getArrayCopy() + public function getArrayCopy(): array { return $this->data; } /** * @param int $position - * @return ?Object + * @return ?object */ - public function getByPosition(int $position) + public function getByPosition(int $position): ?object { $keys = array_keys($this->data); return $this->data[$keys[$position] ?? null] ?? null; @@ -117,10 +124,7 @@ public function getCount(): int } /** - * Whether a offset exists - * - * @param mixed $offset - * @return bool true on success or false on failure + * @inheritDoc */ public function offsetExists($offset): bool { @@ -132,15 +136,15 @@ public function offsetExists($offset): bool * * @param mixed $offset * @return mixed + * @noinspection PhpLanguageLevelInspection */ #[ReturnTypeWillChange] public function offsetGet($offset) { if ($this->offsetExists($offset)) { return $this->data[$offset]; - } else { - return null; } + return null; } /** @@ -148,7 +152,6 @@ public function offsetGet($offset) * * @param mixed $offset * @param mixed $value - * @return void */ public function offsetSet($offset, $value): void { @@ -163,7 +166,6 @@ public function offsetSet($offset, $value): void * Offset to unset * * @param mixed $offset - * @return void */ public function offsetUnset($offset): void { diff --git a/Classes/System/Data/DateTime.php b/Classes/System/Data/DateTime.php index cf7d03f6f2..2d00b06716 100644 --- a/Classes/System/Data/DateTime.php +++ b/Classes/System/Data/DateTime.php @@ -1,5 +1,7 @@ format(\DateTime::ISO8601); + return $this->format(PhpDateTime::ISO8601); } } diff --git a/Classes/System/Environment/CliEnvironment.php b/Classes/System/Environment/CliEnvironment.php index ae5b6a5895..dac0a4c906 100644 --- a/Classes/System/Environment/CliEnvironment.php +++ b/Classes/System/Environment/CliEnvironment.php @@ -1,5 +1,7 @@ backupServerVariables = $_SERVER; @@ -52,11 +50,15 @@ public function backup() * @param string $scriptFileName * @param string $phpSelf * @param string $scriptName - * @throws WebRootAllReadyDefinedException * @return bool + *@throws WebRootAllReadyDefinedException */ - public function initialize($webRoot, $scriptFileName = '', $phpSelf = '/index.php', $scriptName = '/index.php') - { + public function initialize( + string $webRoot, + string $scriptFileName = '', + string $phpSelf = '/index.php', + string $scriptName = '/index.php' + ): bool { // if the environment has be initialized once, we do not need to initialize it twice. if ($this->isInitialized) { return false; @@ -82,15 +84,12 @@ public function initialize($webRoot, $scriptFileName = '', $phpSelf = '/index.ph /** * @return bool */ - public function getIsInitialized() + public function getIsInitialized(): bool { return $this->isInitialized; } - /** - * @return void - */ - public function restore() + public function restore(): void { $_SERVER = $this->backupServerVariables; } diff --git a/Classes/System/Language/FrontendOverlayService.php b/Classes/System/Language/FrontendOverlayService.php index 99c2aee2ad..510f150753 100644 --- a/Classes/System/Language/FrontendOverlayService.php +++ b/Classes/System/Language/FrontendOverlayService.php @@ -1,5 +1,7 @@ tsfe->getContext()->getPropertyFromAspect('language', 'id'); // when no language is set at all we do not need to overlay if ($contextsLanguageId === null) { @@ -117,7 +126,8 @@ protected function getLocalRecordUidFromOverlay(string $localTableName, array $o // when there is a _PAGES_OVERLAY_UID | _LOCALIZED_UID in the overlay, we return it if ($localTableName === 'pages' && isset($overlayRecord['_PAGES_OVERLAY_UID'])) { return (int)$overlayRecord['_PAGES_OVERLAY_UID']; - } elseif (isset($overlayRecord['_LOCALIZED_UID'])) { + } + if (isset($overlayRecord['_LOCALIZED_UID'])) { return (int)$overlayRecord['_LOCALIZED_UID']; } @@ -125,15 +135,22 @@ protected function getLocalRecordUidFromOverlay(string $localTableName, array $o } /** - * @param $localTableName - * @param $localRecordUid + * @param string $localTableName + * @param int $localRecordUid * @return mixed + * @throws DBALDriverException + * @throws DBALException|\Doctrine\DBAL\DBALException */ - protected function getRecord($localTableName, $localRecordUid) + protected function getRecord(string $localTableName, int $localRecordUid) { /* @var QueryBuilder $queryBuilder */ $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable($localTableName); - return $queryBuilder->select('*')->from($localTableName)->where($queryBuilder->expr()->eq('uid', $localRecordUid))->execute()->fetch(); + return $queryBuilder + ->select('*') + ->from($localTableName) + ->where($queryBuilder->expr()->eq('uid', $localRecordUid)) + ->execute() + ->fetchAssociative(); } } diff --git a/Classes/System/Logging/SolrLogManager.php b/Classes/System/Logging/SolrLogManager.php index 149d235c50..e85900b5da 100644 --- a/Classes/System/Logging/SolrLogManager.php +++ b/Classes/System/Logging/SolrLogManager.php @@ -15,7 +15,7 @@ namespace ApacheSolrForTypo3\Solr\System\Logging; -use ApacheSolrForTypo3\Solr\Util; +use TYPO3\CMS\Core\Log\Logger; use TYPO3\CMS\Core\Log\LogLevel; use TYPO3\CMS\Core\Log\LogManager; use TYPO3\CMS\Core\Utility\GeneralUtility; @@ -33,36 +33,36 @@ class SolrLogManager const NOTICE = LogLevel::NOTICE; /** - * @var \TYPO3\CMS\Core\Log\Logger + * @var Logger|null */ - protected $logger = null; + protected ?Logger $logger = null; /** * @var DebugWriter */ - protected $debugWriter = null; + protected $debugWriter; /** * @var string */ - protected $className = ''; + protected string $className = ''; /** * SolrLogManager constructor. * * @param string $className - * @param DebugWriter $debugWriter + * @param DebugWriter|null $debugWriter */ - public function __construct($className, DebugWriter $debugWriter = null) + public function __construct(string $className, DebugWriter $debugWriter = null) { $this->className = $className; $this->debugWriter = $debugWriter ?? GeneralUtility::makeInstance(DebugWriter::class); } /** - * @return \TYPO3\CMS\Core\Log\Logger + * @return Logger */ - protected function getLogger() + protected function getLogger(): Logger { if ($this->logger === null) { $this->logger = GeneralUtility::makeInstance(LogManager::class)->getLogger($this->className); @@ -77,10 +77,8 @@ protected function getLogger() * @param int|string $level Log level. Value according to \TYPO3\CMS\Core\Log\LogLevel. Alternatively accepts a string. * @param string $message Log message. * @param array $data Additional data to log - * - * @return mixed */ - public function log($level, $message, array $data = []) + public function log($level, string $message, array $data = []) { $this->getLogger()->log($level, $message, $data); $this->debugWriter->write($level, $message, $data); diff --git a/Classes/System/Mvc/Backend/Component/Exception/InvalidViewObjectNameException.php b/Classes/System/Mvc/Backend/Component/Exception/InvalidViewObjectNameException.php index b18c0b5941..1ecafde5f0 100644 --- a/Classes/System/Mvc/Backend/Component/Exception/InvalidViewObjectNameException.php +++ b/Classes/System/Mvc/Backend/Component/Exception/InvalidViewObjectNameException.php @@ -1,5 +1,7 @@ site; } @@ -46,7 +48,6 @@ public function getSite() * Sets the site to work with. * * @param Site $site - * @return void */ public function setSite(Site $site) { @@ -58,7 +59,7 @@ public function setSite(Site $site) * * @return string Selected core name */ - public function getCore() + public function getCore(): string { return $this->core; } @@ -68,7 +69,7 @@ public function getCore() * * @param string $core Selected core name */ - public function setCore($core) + public function setCore(string $core) { $this->core = $core; } diff --git a/Classes/System/Mvc/Backend/Service/ModuleDataStorageService.php b/Classes/System/Mvc/Backend/Service/ModuleDataStorageService.php index fb62c5c378..f80c93ff7c 100644 --- a/Classes/System/Mvc/Backend/Service/ModuleDataStorageService.php +++ b/Classes/System/Mvc/Backend/Service/ModuleDataStorageService.php @@ -1,5 +1,7 @@ getModuleData(self::KEY); $this->unsetModuleDataIfCanNotBeSerialized($moduleData); - if (empty($moduleData) || !$moduleData) { + if (empty($moduleData)) { $moduleData = GeneralUtility::makeInstance(ModuleData::class); } else { $moduleData = unserialize($moduleData); @@ -54,7 +54,6 @@ public function loadModuleData() * Persists serialized module data to user settings * * @param ModuleData $moduleData - * @return void */ public function persistModuleData(ModuleData $moduleData) { diff --git a/Classes/System/Object/AbstractClassRegistry.php b/Classes/System/Object/AbstractClassRegistry.php index 0d0f45c1cb..da6e1a8778 100644 --- a/Classes/System/Object/AbstractClassRegistry.php +++ b/Classes/System/Object/AbstractClassRegistry.php @@ -1,5 +1,7 @@ className * @var array */ - protected $classMap = []; + protected array $classMap = []; /** * Name for the default implementation * * @var string */ - protected $defaultClass = \stdClass::class; + protected string $defaultClass = stdClass::class; /** - * @var ObjectManagerInterface + * @var ObjectManagerInterface|null */ - protected $objectManager; + protected ?ObjectManagerInterface $objectManager = null; /** * @param ObjectManagerInterface $objectManager @@ -55,12 +59,12 @@ public function injectObjectManager(ObjectManagerInterface $objectManager) } /** - * Retrieves an instance for an registered type. + * Retrieves an instance for a registered type. * * @param string $type * @return object */ - public function getInstance($type) + public function getInstance(string $type): object { $className = $this->resolveClassName($type); return $this->createInstance($className); @@ -70,12 +74,11 @@ public function getInstance($type) * @param string $type * @return string */ - protected function resolveClassName($type) + protected function resolveClassName(string $type): string { $className = $this->defaultClass; if (isset($this->classMap[$type])) { - $className = $this->classMap[$type]; - return $className; + return $this->classMap[$type]; } return $className; } @@ -86,7 +89,7 @@ protected function resolveClassName($type) * @param string $className * @return object */ - protected function createInstance($className) + protected function createInstance(string $className): object { return $this->objectManager->get($className); } @@ -98,14 +101,15 @@ protected function createInstance($className) * @param string $type * @param string $requiredBaseClass */ - protected function register($className, $type, $requiredBaseClass) { + protected function register(string $className, string $type, string $requiredBaseClass): void + { // check if the class is available for TYPO3 before registering the driver if (!class_exists($className)) { - throw new \InvalidArgumentException('Class ' . $className . ' does not exist.', 1462883324); + throw new InvalidArgumentException('Class ' . $className . ' does not exist.', 1462883324); } if (!is_subclass_of($className, $requiredBaseClass)) { - throw new \InvalidArgumentException('Parser ' . $className . ' needs to extend the ' . $requiredBaseClass . '.', 1462883325); + throw new InvalidArgumentException('Parser ' . $className . ' needs to extend the ' . $requiredBaseClass . '.', 1462883325); } $this->classMap[$type] = $className; diff --git a/Classes/System/Page/Rootline.php b/Classes/System/Page/Rootline.php index 609f77ce3d..1a4fc7f448 100644 --- a/Classes/System/Page/Rootline.php +++ b/Classes/System/Page/Rootline.php @@ -1,5 +1,7 @@ rootline. + * The constructor requires a rootline array as arguments (as you get it from + * PageRepository::getRootline or TSFE->rootline.) * * @author Timo Hund */ @@ -29,7 +31,7 @@ class Rootline /** * @var array */ - protected $rootLineArray = []; + protected array $rootLineArray = []; /** * Rootline constructor. @@ -43,7 +45,7 @@ public function __construct(array $rootLineArray = []) /** * @return array */ - public function getRootLineArray() + public function getRootLineArray(): array { return $this->rootLineArray; } @@ -51,17 +53,17 @@ public function getRootLineArray() /** * @param array $rootLineArray */ - public function setRootLineArray($rootLineArray) + public function setRootLineArray(array $rootLineArray) { $this->rootLineArray = $rootLineArray; } /** - * Returns true if the rooline contains a root page. + * Returns true if the rootline contains a root page. * - * @return boolean + * @return bool */ - public function getHasRootPage() + public function getHasRootPage(): bool { return $this->getRootPageId() !== 0; } @@ -70,9 +72,9 @@ public function getHasRootPage() * Returns the rootPageId as integer if a rootpage is given, * if non is given 0 will be returned * - * @return integer + * @return int */ - public function getRootPageId() + public function getRootPageId(): int { $rootPageId = 0; @@ -95,7 +97,7 @@ public function getRootPageId() * * @return array */ - public function getParentPageIds() + public function getParentPageIds(): array { $rootLineParentPageIds = []; if (empty($this->rootLineArray)) { diff --git a/Classes/System/Records/AbstractRepository.php b/Classes/System/Records/AbstractRepository.php index 8a40ce274b..5d0440c306 100644 --- a/Classes/System/Records/AbstractRepository.php +++ b/Classes/System/Records/AbstractRepository.php @@ -1,5 +1,7 @@ |false + * @throws DBALDriverException + * @throws DBALException|\Doctrine\DBAL\DBALException */ - protected function getOneRowByUid($fields, $uid) + protected function getOneRowByUid(string $fields, int $uid) { $queryBuilder = $this->getQueryBuilder(); return $queryBuilder ->select($fields) ->from($this->table) - ->where($queryBuilder->expr()->eq('uid', intval($uid))) - ->execute()->fetch(); + ->where($queryBuilder->expr()->eq('uid', $uid)) + ->execute() + ->fetchAssociative(); } /** @@ -54,24 +63,26 @@ protected function getOneRowByUid($fields, $uid) * * @return QueryBuilder */ - protected function getQueryBuilder() + protected function getQueryBuilder(): QueryBuilder { - /** @var QueryBuilder $queryBuilder */ - $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable($this->table); - return $queryBuilder; + /* @var QueryBuilder $queryBuilder */ + return GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable($this->table); } /** * Returns current count of last searches * * @return int + * @throws DBALDriverException + * @throws DBALException|\Doctrine\DBAL\DBALException */ - public function count() : int + public function count(): int { return (int)$this->getQueryBuilder() ->count('*') ->from($this->table) - ->execute()->fetchColumn(); + ->execute() + ->fetchOne(); } /** @@ -79,20 +90,23 @@ public function count() : int * * Note: Rollback will not work in case of different connections. * - * @param string[] ...$tableNames + * @param string ...$tableNames * @return Connection */ - public function getConnectionForAllInTransactionInvolvedTables(string ...$tableNames) : Connection + public function getConnectionForAllInTransactionInvolvedTables(string ...$tableNames): Connection { if (empty($tableNames) || count($tableNames) < 2) { - throw new \InvalidArgumentException(__METHOD__ . ' requires at least 2 table names.', 1504801512); + throw new InvalidArgumentException(__METHOD__ . ' requires at least 2 table names.', 1504801512); } if (!$this->isConnectionForAllTablesTheSame(...$tableNames)) { - throw new \RuntimeException( - vsprintf('The tables "%s" using different database connections. Transaction needs same database connection ' . - 'for all tables, please reconfigure the database settings for involved tables properly.', [implode('", "', $tableNames)] - ), 1504866142 + throw new RuntimeException( + vsprintf( + 'The tables "%s" using different database connections. Transaction needs same database connection ' . + 'for all tables, please reconfigure the database settings for involved tables properly.', + [implode('", "', $tableNames)] + ), + 1504866142 ); } return GeneralUtility::makeInstance(ConnectionPool::class)->getConnectionForTable(array_shift($tableNames)); @@ -101,10 +115,10 @@ public function getConnectionForAllInTransactionInvolvedTables(string ...$tableN /** * Checks whether all table involved in transaction using same connection. * - * @param string[] ...$tableNames + * @param string ...$tableNames * @return bool */ - protected function isConnectionForAllTablesTheSame(string ...$tableNames) : bool + protected function isConnectionForAllTablesTheSame(string ...$tableNames): bool { /** @var ConnectionPool $connectionPool */ $connectionPool = GeneralUtility::makeInstance(ConnectionPool::class); diff --git a/Classes/System/Records/Pages/PagesRepository.php b/Classes/System/Records/Pages/PagesRepository.php index 12de0864f4..d520fb7b21 100644 --- a/Classes/System/Records/Pages/PagesRepository.php +++ b/Classes/System/Records/Pages/PagesRepository.php @@ -1,5 +1,7 @@ getQueryBuilder(); @@ -71,10 +77,11 @@ public function findAllRootPages() $queryBuilder->expr()->eq('is_siteroot', 1) ); - $this->addDefaultLanguageUidConstraint($queryBuilder); - return $queryBuilder->execute()->fetchAll(); + return $queryBuilder + ->execute() + ->fetchAllAssociative(); } /** @@ -83,22 +90,25 @@ public function findAllRootPages() * @param int $mountedPageUid * @param array $rootLineParentPageIds * @return array + * @throws DBALException|\Doctrine\DBAL\DBALException + * @throws DBALDriverException */ - public function findMountPointPropertiesByPageIdOrByRootLineParentPageIds(int $mountedPageUid, array $rootLineParentPageIds = []) : array + public function findMountPointPropertiesByPageIdOrByRootLineParentPageIds(int $mountedPageUid, array $rootLineParentPageIds = []): array { if (array_filter($rootLineParentPageIds, 'is_int') !== $rootLineParentPageIds) { - throw new \InvalidArgumentException('Given $rootLineParentPageIds array is not valid. Allowed only the arrays with the root line page UIDs as integers.', 1502459711); + throw new InvalidArgumentException('Given $rootLineParentPageIds array is not valid. Allowed only the arrays with the root line page UIDs as integers.', 1502459711); } $queryBuilder = $this->getQueryBuilder(); $queryBuilder->select('uid', 'uid AS mountPageDestination', 'mount_pid AS mountPageSource', 'mount_pid_ol AS mountPageOverlayed')->from($this->table); $queryBuilder = $this->addWhereClauseForMountpointDestinationProperties($queryBuilder, $mountedPageUid, $rootLineParentPageIds); - $result = $queryBuilder->execute()->fetchAll(); - return $result; + return $queryBuilder + ->execute() + ->fetchAllAssociative(); } /** - * This methods builds the where clause for the mountpoint destinations. It retrieves all records where the mount_pid = $mountedPageUid or the mount_pid is + * This method builds the where clause for the mountpoint destinations. It retrieves all records where the mount_pid = $mountedPageUid or the mount_pid is * in the rootLineParentPageIds. * * @param QueryBuilder $queryBuilder @@ -106,8 +116,11 @@ public function findMountPointPropertiesByPageIdOrByRootLineParentPageIds(int $m * @param array $rootLineParentPageIds * @return QueryBuilder */ - protected function addWhereClauseForMountpointDestinationProperties(QueryBuilder $queryBuilder, $mountedPageUid, array $rootLineParentPageIds) : QueryBuilder - { + protected function addWhereClauseForMountpointDestinationProperties( + QueryBuilder $queryBuilder, + int $mountedPageUid, + array $rootLineParentPageIds + ): QueryBuilder { if (empty($rootLineParentPageIds)) { $queryBuilder->andWhere( $queryBuilder->expr()->eq('doktype', 7), @@ -139,18 +152,17 @@ protected function addWhereClauseForMountpointDestinationProperties(QueryBuilder * Attentions: * * Includes all page types except deleted pages! * - * @param int $rootPageId Page ID from where to start collection sub pages + * @param int $rootPageId Page ID from where to start collection sub-pages * @param string $initialPagesAdditionalWhereClause * @return array Array of pages (IDs) in this site * @throws DBALDriverException + * @throws DBALException|\Doctrine\DBAL\DBALException */ public function findAllSubPageIdsByRootPage( int $rootPageId, string $initialPagesAdditionalWhereClause = '' - ) : array - { - - $cacheIdentifier = sha1('getPages' . (string)$rootPageId . $initialPagesAdditionalWhereClause); + ): array { + $cacheIdentifier = sha1('getPages' . $rootPageId . $initialPagesAdditionalWhereClause); if ($this->transientVariableCache->get($cacheIdentifier) !== false) { return $this->transientVariableCache->get($cacheIdentifier); } @@ -167,19 +179,19 @@ public function findAllSubPageIdsByRootPage( } /** - * This method retrieves the pages ids from the current tree level an calls getPages recursive, + * This method retrieves the pages ids from the current tree level a calls getPages recursive, * when the maxDepth has not been reached. * * @param array $pageIds * @param string $initialPagesAdditionalWhereClause * @return array * @throws DBALDriverException + * @throws DBALException|\Doctrine\DBAL\DBALException */ protected function filterPageIdsByInitialPagesAdditionalWhereClause( array $pageIds, string $initialPagesAdditionalWhereClause ): array { - $queryBuilder = $this->getQueryBuilder(); $queryBuilder->getRestrictions()->removeAll()->add(GeneralUtility::makeInstance(DeletedRestriction::class)); @@ -205,6 +217,7 @@ protected function filterPageIdsByInitialPagesAdditionalWhereClause( * * @return array * @throws DBALDriverException + * @throws DBALException|\Doctrine\DBAL\DBALException * @deprecated since v11 and will be removed in v12. Use {@link findAllPagesWithinNoSearchSubEntriesMarkedPages()} instead. */ public function findAllPagesWithinNoSearchSubEntriesMarkedPagesByRootPage(int $rootPageId): array @@ -268,14 +281,15 @@ public function findAllPagesWithinNoSearchSubEntriesMarkedPages(): array return $pageIds; } - /** * Finds translation overlays by given page Id. * * @param int $pageId * @return array + * @throws DBALException|\Doctrine\DBAL\DBALException + * @throws DBALDriverException */ - public function findTranslationOverlaysByPageId(int $pageId) : array + public function findTranslationOverlaysByPageId(int $pageId): array { $queryBuilder = $this->getQueryBuilder(); $queryBuilder->getRestrictions()->removeAll(); @@ -284,11 +298,12 @@ public function findTranslationOverlaysByPageId(int $pageId) : array return $queryBuilder ->select('pid', 'l10n_parent', 'sys_language_uid') ->from('pages') - ->add('where', + ->add( + 'where', $queryBuilder->expr()->eq('l10n_parent', $queryBuilder->createNamedParameter($pageId, PDO::PARAM_INT)) . BackendUtility::BEenableFields('pages') - )->execute()->fetchAll(); - + )->execute() + ->fetchAllAssociative(); } /** @@ -296,8 +311,10 @@ public function findTranslationOverlaysByPageId(int $pageId) : array * * @param int $pageId UID of the page currently being updated * @return array with page Uids from pages, which are showing contents from given Page Id + * @throws DBALException|\Doctrine\DBAL\DBALException + * @throws DBALDriverException */ - public function findPageUidsWithContentsFromPid(int $pageId) : array + public function findPageUidsWithContentsFromPid(int $pageId): array { $queryBuilder = $this->getQueryBuilder(); $queryBuilder->getRestrictions()->removeAll(); @@ -306,13 +323,16 @@ public function findPageUidsWithContentsFromPid(int $pageId) : array $queryBuilder ->select('uid') ->from($this->table) - ->add('where', + ->add( + 'where', $queryBuilder->expr()->eq('content_from_pid', $queryBuilder->createNamedParameter($pageId, PDO::PARAM_INT)) ); $this->addDefaultLanguageUidConstraint($queryBuilder); - return $queryBuilder->execute()->fetchAll(); + return $queryBuilder + ->execute() + ->fetchAllAssociative(); } /** @@ -320,8 +340,10 @@ public function findPageUidsWithContentsFromPid(int $pageId) : array * * @param string $whereClause * @return array + * @throws DBALException|\Doctrine\DBAL\DBALException + * @throws DBALDriverException */ - public function findAllMountPagesByWhereClause(string $whereClause) : array + public function findAllMountPagesByWhereClause(string $whereClause): array { $queryBuilder = $this->getQueryBuilder(); $queryBuilder->getRestrictions()->removeAll(); @@ -330,13 +352,16 @@ public function findAllMountPagesByWhereClause(string $whereClause) : array 'uid', 'mount_pid AS mountPageSource', 'uid AS mountPageDestination', - 'mount_pid_ol AS mountPageOverlayed') + 'mount_pid_ol AS mountPageOverlayed' + ) ->from($this->table) ->add('where', $whereClause); $this->addDefaultLanguageUidConstraint($queryBuilder); - return $queryBuilder->execute()->fetchAll(); + return $queryBuilder + ->execute() + ->fetchAllAssociative(); } /** @@ -363,7 +388,7 @@ public function getPage(int $uid, string $fields = '*', string $additionalWhereC * Note: Currently just a wrapper for BEenableFields, but as this should only be used internally * we should switch to the DefaultRestrictionHandler * - * @param string $table The table from which to return enableFields WHERE clause. Table name must have a 'ctrl' section in $GLOBALS['TCA']. + * @return string */ public function getBackendEnableFields(): string { @@ -392,6 +417,7 @@ protected function addDefaultLanguageUidConstraint($queryBuilder) * @param string $permClause * @return string comma separated list of descendant pages * @throws DBALDriverException + * @throws DBALException|\Doctrine\DBAL\DBALException * @noinspection Duplicates */ protected function getTreeList(int $id, int $depth = 999, int $begin = 0, string $permClause = ''): string @@ -410,7 +436,7 @@ protected function getTreeList(int $id, int $depth = 999, int $begin = 0, string $queryBuilder->select('uid') ->from('pages') ->where( - $queryBuilder->expr()->eq('pid', $queryBuilder->createNamedParameter($id, \PDO::PARAM_INT)), + $queryBuilder->expr()->eq('pid', $queryBuilder->createNamedParameter($id, PDO::PARAM_INT)), $queryBuilder->expr()->eq('sys_language_uid', 0) ) ->orderBy('uid'); @@ -431,6 +457,6 @@ protected function getTreeList(int $id, int $depth = 999, int $begin = 0, string } } } - return $theList; + return (string)$theList; } } diff --git a/Classes/System/Records/Queue/EventQueueItemRepository.php b/Classes/System/Records/Queue/EventQueueItemRepository.php index fde28aa5fb..ac95940c51 100644 --- a/Classes/System/Records/Queue/EventQueueItemRepository.php +++ b/Classes/System/Records/Queue/EventQueueItemRepository.php @@ -1,5 +1,7 @@ insert($this->table) ->values([ - 'tstamp' => Util::getExectionTime(), - 'event' => $serializedEvent + 'tstamp' => Util::getExceptionTime(), + 'event' => $serializedEvent, ]) ->execute(); @@ -53,9 +60,11 @@ public function addEventToQueue(DataUpdateEventInterface $event): void /** * Returns event queue items * - * @param int $limit + * @param int|null $limit * @param bool $excludeErroneousItems * @return array + * @throws DBALDriverException + * @throws DBALException|\Doctrine\DBAL\DBALException */ public function getEventQueueItems(int $limit = null, bool $excludeErroneousItems = true): array { @@ -72,7 +81,9 @@ public function getEventQueueItems(int $limit = null, bool $excludeErroneousItem $queryBuilder->andWhere($queryBuilder->expr()->eq('error', 0)); } - return $queryBuilder->execute()->fetchAll(); + return $queryBuilder + ->execute() + ->fetchAllAssociative(); } /** @@ -80,6 +91,7 @@ public function getEventQueueItems(int $limit = null, bool $excludeErroneousItem * * @param int $uid * @param array $data + * @throws DBALException|\Doctrine\DBAL\DBALException */ public function updateEventQueueItem(int $uid, array $data): void { @@ -94,7 +106,7 @@ public function updateEventQueueItem(int $uid, array $data): void $queryBuilder->expr()->eq('uid', $uid) ); - foreach($data as $column => $value) { + foreach ($data as $column => $value) { $queryBuilder->set($column, $value); } @@ -105,6 +117,7 @@ public function updateEventQueueItem(int $uid, array $data): void * Deletes event queue items * * @param int[] $uids + * @throws DBALException|\Doctrine\DBAL\DBALException */ public function deleteEventQueueItems(array $uids): void { @@ -126,8 +139,10 @@ public function deleteEventQueueItems(array $uids): void * * @param bool $excludeErroneousItems * @return int + * @throws DBALException|\Doctrine\DBAL\DBALException + * @throws DBALDriverException */ - public function count($excludeErroneousItems = true): int + public function count(bool $excludeErroneousItems = true): int { $queryBuilder = $this->getQueryBuilder(); $queryBuilder @@ -138,6 +153,8 @@ public function count($excludeErroneousItems = true): int $queryBuilder->andWhere($queryBuilder->expr()->eq('error', 0)); } - return (int)$queryBuilder->execute()->fetchColumn(); + return (int)$queryBuilder + ->execute() + ->fetchOne(); } } diff --git a/Classes/System/Records/SystemCategory/SystemCategoryRepository.php b/Classes/System/Records/SystemCategory/SystemCategoryRepository.php index 8e8b0aa0e7..d4edc4384b 100644 --- a/Classes/System/Records/SystemCategory/SystemCategoryRepository.php +++ b/Classes/System/Records/SystemCategory/SystemCategoryRepository.php @@ -1,5 +1,7 @@ |false + * + * @throws DBALDriverException + * @throws DBALException|\Doctrine\DBAL\DBALException */ - public function findOneByUid($uid = 0, $limitFields = '*') + public function findOneByUid(int $uid = 0, string $limitFields = '*') { return $this->getOneRowByUid($limitFields, $uid); } diff --git a/Classes/System/Records/SystemLanguage/SystemLanguageRepository.php b/Classes/System/Records/SystemLanguage/SystemLanguageRepository.php index bba57d0e45..cf96c4e08d 100644 --- a/Classes/System/Records/SystemLanguage/SystemLanguageRepository.php +++ b/Classes/System/Records/SystemLanguage/SystemLanguageRepository.php @@ -1,5 +1,7 @@ getQueryBuilder(); $result = $queryBuilder->select('title') ->from($this->table) ->where($queryBuilder->expr()->eq('uid', $languageId)) - ->execute()->fetch(); + ->execute() + ->fetchAssociative(); if ($result == false && $languageId == 0) { return 'default'; } - return isset($result['title']) ? $result['title'] : ''; + return $result['title'] ?? ''; } /** * Finds the system's configured languages. * * @return array An array of language UIDs + * @throws DBALException|\Doctrine\DBAL\DBALException + * @throws DBALDriverException */ - public function findSystemLanguages() + public function findSystemLanguages(): array { $languages = [0]; @@ -67,7 +73,8 @@ public function findSystemLanguages() $queryBuilder->getRestrictions()->add(GeneralUtility::makeInstance(HiddenRestriction::class)); $languageRecords = $queryBuilder->select('uid') ->from($this->table) - ->execute()->fetchAll(); + ->execute() + ->fetchAllAssociative(); if ($languageRecords == false) { return $languages; diff --git a/Classes/System/Records/SystemTemplate/SystemTemplateRepository.php b/Classes/System/Records/SystemTemplate/SystemTemplateRepository.php index e51bfd3192..1ffcc31bca 100644 --- a/Classes/System/Records/SystemTemplate/SystemTemplateRepository.php +++ b/Classes/System/Records/SystemTemplate/SystemTemplateRepository.php @@ -1,5 +1,7 @@ flexFormService = $flexFormService; } /** - * @param \TYPO3\CMS\Core\TypoScript\TypoScriptService $typoScriptService + * @param TypoScriptService $typoScriptService */ - public function setTypoScriptService($typoScriptService) + public function setTypoScriptService(TypoScriptService $typoScriptService) { $this->typoScriptService = $typoScriptService; } @@ -65,10 +67,8 @@ public function setTypoScriptService($typoScriptService) * * @param string $flexFormData The raw data from database. * @param TypoScriptConfiguration $solrTypoScriptConfiguration - * - * @return void */ - public function overrideConfigurationWithFlexFormSettings($flexFormData, TypoScriptConfiguration $solrTypoScriptConfiguration) + public function overrideConfigurationWithFlexFormSettings(string $flexFormData, TypoScriptConfiguration $solrTypoScriptConfiguration) { if (empty($flexFormData)) { return; @@ -90,7 +90,7 @@ public function overrideConfigurationWithFlexFormSettings($flexFormData, TypoScr * * @return array */ - protected function overrideFilter(array $flexFormConfiguration) + protected function overrideFilter(array $flexFormConfiguration): array { $filter = $this->getFilterFromFlexForm($flexFormConfiguration); unset($flexFormConfiguration['search']['query']['filter']); @@ -117,7 +117,7 @@ protected function overrideFilter(array $flexFormConfiguration) * * @return array */ - protected function getFilterFromFlexForm(array $flexFormConfiguration) + protected function getFilterFromFlexForm(array $flexFormConfiguration): array { $filterConfiguration = []; $filters = ObjectAccess::getPropertyPath($flexFormConfiguration, 'search.query.filter'); diff --git a/Classes/System/Session/FrontendUserSession.php b/Classes/System/Session/FrontendUserSession.php index 5681859255..002952216b 100644 --- a/Classes/System/Session/FrontendUserSession.php +++ b/Classes/System/Session/FrontendUserSession.php @@ -1,6 +1,6 @@ feUser->setKey('ses', 'tx_solr_resultsPerPage', intval($requestedPerPage)); + $this->feUser->setKey('ses', 'tx_solr_resultsPerPage', $requestedPerPage); } /** * @return int */ - public function getPerPage() : int + public function getPerPage(): int { return (int)$this->feUser->getKey('ses', 'tx_solr_resultsPerPage'); } /** - * @return boolean + * @return bool */ - public function getHasPerPage() + public function getHasPerPage(): bool { return $this->feUser->getKey('ses', 'tx_solr_resultsPerPage') !== null; } @@ -68,7 +68,7 @@ public function getHasPerPage() /** * @return array */ - public function getLastSearches() : array + public function getLastSearches(): array { $result = $this->feUser->getKey('ses', 'tx_solr_lastSearches'); return is_array($result) ? $result : []; @@ -77,8 +77,8 @@ public function getLastSearches() : array /** * @param array $lastSearches */ - public function setLastSearches(array $lastSearches) + public function setLastSearches(array $lastSearches): void { - return $this->feUser->setKey('ses', 'tx_solr_lastSearches', $lastSearches); + $this->feUser->setKey('ses', 'tx_solr_lastSearches', $lastSearches); } } diff --git a/Classes/System/Solr/Document/Document.php b/Classes/System/Solr/Document/Document.php index bca22c652b..f5d0f57307 100644 --- a/Classes/System/Solr/Document/Document.php +++ b/Classes/System/Solr/Document/Document.php @@ -1,5 +1,7 @@ fields[$field] ?? null; - } else { - throw new RuntimeException('Call to undefined method. Supports magic getters only.', 1311006605); } + throw new RuntimeException('Call to undefined method. Supports magic getters only.', 1311006605); } /** * @return array */ - public function getFieldNames() + public function getFieldNames(): array { return array_keys($this->fields); } diff --git a/Classes/System/Solr/Node.php b/Classes/System/Solr/Node.php index a90b1daa4f..6f33883a08 100644 --- a/Classes/System/Solr/Node.php +++ b/Classes/System/Solr/Node.php @@ -1,5 +1,7 @@ * @copyright Copyright (c) 2009-2020 Timo Hund * - * @deprecated Class will removed with Ext:solr 12.x. Use class \Solarium\Core\Client\Endpoint instead. + * @deprecated Class will be removed with Ext:solr 12.x. Use class \Solarium\Core\Client\Endpoint instead. */ class Node extends Endpoint { @@ -100,7 +102,7 @@ public static function fromArray(array $configuration): Node protected static function checkIfRequiredKeyIsSet(array $configuration, string $name) { if (empty($configuration[$name])) { - throw new UnexpectedValueException('Required solr connection property ' . $name. ' is missing.'); + throw new UnexpectedValueException('Required solr connection property ' . $name . ' is missing.'); } } @@ -127,8 +129,8 @@ public function getPassword(): string */ public function getCoreBasePath(): string { - $pathWithoutLeadingAndTrailingSlashes = trim(trim($this->getPath()), "/"); - $pathWithoutLastSegment = substr($pathWithoutLeadingAndTrailingSlashes, 0, strrpos($pathWithoutLeadingAndTrailingSlashes, "/")); + $pathWithoutLeadingAndTrailingSlashes = trim(trim($this->getPath()), '/'); + $pathWithoutLastSegment = substr($pathWithoutLeadingAndTrailingSlashes, 0, strrpos($pathWithoutLeadingAndTrailingSlashes, '/')); return ($pathWithoutLastSegment === '') ? '/' : '/' . $pathWithoutLastSegment . '/'; } @@ -136,7 +138,7 @@ public function getCoreBasePath(): string * Returns the core name from the configured path. * * @return string - * @deprecated Will be remove with Ext:solr 12.x. Use method getCore() instead. + * @deprecated Will be removed with Ext:solr 12.x. Use method getCore() instead. */ public function getCoreName(): string { @@ -153,7 +155,7 @@ public function getSolariumClientOptions(): array 'port' => $this->getPort(), 'scheme' => $this->getScheme(), 'path' => $this->getPath(), - 'core' => $this->getCore() + 'core' => $this->getCore(), ]; } diff --git a/Classes/System/Solr/ParsingUtil.php b/Classes/System/Solr/ParsingUtil.php index d74df1b7ca..aacf9ef0db 100644 --- a/Classes/System/Solr/ParsingUtil.php +++ b/Classes/System/Solr/ParsingUtil.php @@ -1,6 +1,24 @@ $value) { + foreach ($options as $key => $value) { $isKeyNode = (($key % 2) == 0); if ($isKeyNode) { $valueFromKeyNode = $value; } else { - if($valueFromKeyNode == -1) { - throw new \UnexpectedValueException('No optionValue before count value'); + if ($valueFromKeyNode == -1) { + throw new UnexpectedValueException('No optionValue before count value'); } //we have a countNode $keyValueMap[$valueFromKeyNode] = $value; diff --git a/Classes/System/Solr/ResponseAdapter.php b/Classes/System/Solr/ResponseAdapter.php index c5d75d8d0d..5f0d7ca56d 100644 --- a/Classes/System/Solr/ResponseAdapter.php +++ b/Classes/System/Solr/ResponseAdapter.php @@ -1,5 +1,7 @@ data->response) && is_array($this->data->response->docs ?? null)) { - $documents = array(); + $documents = []; // @extensionScannerIgnoreLine foreach ($this->data->response->docs as $originalDocument) { @@ -117,7 +120,7 @@ public function __get(string $key) * Magic function for isset function on parsed data * * @param string $key - * @return boolean + * @return bool */ public function __isset(string $key) { diff --git a/Classes/System/Solr/Service/AbstractSolrService.php b/Classes/System/Solr/Service/AbstractSolrService.php index b94719507f..be233db4c6 100644 --- a/Classes/System/Solr/Service/AbstractSolrService.php +++ b/Classes/System/Solr/Service/AbstractSolrService.php @@ -22,36 +22,37 @@ use ApacheSolrForTypo3\Solr\System\Logging\SolrLogManager; use ApacheSolrForTypo3\Solr\System\Solr\ResponseAdapter; use ApacheSolrForTypo3\Solr\Util; +use Closure; use Solarium\Client; use Solarium\Core\Client\Endpoint; use Solarium\Core\Client\Request; use Solarium\Core\Query\QueryInterface; use Solarium\Exception\HttpException; +use Throwable; use TYPO3\CMS\Core\Http\Uri; use TYPO3\CMS\Core\Utility\GeneralUtility; abstract class AbstractSolrService { - /** * @var array */ - protected static $pingCache = []; + protected static array $pingCache = []; /** * @var TypoScriptConfiguration */ - protected $configuration; + protected TypoScriptConfiguration $configuration; /** - * @var \ApacheSolrForTypo3\Solr\System\Logging\SolrLogManager + * @var SolrLogManager */ - protected $logger = null; + protected SolrLogManager $logger; /** * @var Client */ - protected $client = null; + protected Client $client; /** * SolrReadService constructor. @@ -68,10 +69,10 @@ public function __construct(Client $client, $typoScriptConfiguration = null, $lo * * @return string */ - public function getCorePath() + public function getCorePath(): string { $endpoint = $this->getPrimaryEndpoint(); - return is_null($endpoint) ? '' : $endpoint->getPath() .'/'. $endpoint->getCore(); + return $endpoint->getPath() . '/' . $endpoint->getCore(); } /** @@ -91,9 +92,9 @@ public function getClient(): ?Client * @param array $params * @return string */ - protected function _constructUrl($servlet, $params = []) + protected function _constructUrl(string $servlet, array $params = []): string { - $queryString = count($params) ? '?' . http_build_query($params, '', '&') : ''; + $queryString = count($params) ? '?' . http_build_query($params) : ''; return $this->__toString() . $servlet . $queryString; } @@ -107,24 +108,19 @@ protected function _constructUrl($servlet, $params = []) public function __toString() { $endpoint = $this->getPrimaryEndpoint(); - if (!$endpoint instanceof Endpoint) { - return ''; - } - try { return $endpoint->getCoreBaseUri(); - } catch (\Exception $exception) { + } catch (Throwable $exception) { } - return $endpoint->getScheme(). '://' . $endpoint->getHost() . ':' . $endpoint->getPort() . $endpoint->getPath() . '/' . $endpoint->getCore() . '/'; + return $endpoint->getScheme() . '://' . $endpoint->getHost() . ':' . $endpoint->getPort() . $endpoint->getPath() . '/' . $endpoint->getCore() . '/'; } /** * @return Endpoint|null */ - public function getPrimaryEndpoint() + public function getPrimaryEndpoint(): Endpoint { - $clientEndpoints = $this->client->getEndpoints(); - return is_array($clientEndpoints) ? reset($clientEndpoints) : null; + return $this->client->getEndpoint(); } /** @@ -133,18 +129,18 @@ public function getPrimaryEndpoint() * @param string $url * @return ResponseAdapter */ - protected function _sendRawGet($url) + protected function _sendRawGet(string $url): ResponseAdapter { - return $this->_sendRawRequest($url, Request::METHOD_GET); + return $this->_sendRawRequest($url); } /** - * Central method for making a HTTP DELETE operation against the Solr server + * Central method for making an HTTP DELETE operation against the Solr server * * @param string $url * @return ResponseAdapter */ - protected function _sendRawDelete($url) + protected function _sendRawDelete(string $url): ResponseAdapter { return $this->_sendRawRequest($url, Request::METHOD_DELETE); } @@ -157,9 +153,12 @@ protected function _sendRawDelete($url) * @param string $contentType * @return ResponseAdapter */ - protected function _sendRawPost($url, $rawPost, $contentType = 'text/xml; charset=UTF-8') - { - $initializeRequest = function(Request $request) use ($rawPost, $contentType) { + protected function _sendRawPost( + string $url, + string $rawPost, + string $contentType = 'text/xml; charset=UTF-8' + ): ResponseAdapter { + $initializeRequest = function (Request $request) use ($rawPost, $contentType) { $request->setRawData($rawPost); $request->addHeader('Content-Type: ' . $contentType); return $request; @@ -169,26 +168,26 @@ protected function _sendRawPost($url, $rawPost, $contentType = 'text/xml; charse } /** - * Method that performs an http request with the solarium client. + * Method that performs an HTTP request with the solarium client. * * @param string $url * @param string $method * @param string $body - * @param ?\Closure $initializeRequest + * @param ?Closure $initializeRequest * @return ResponseAdapter */ protected function _sendRawRequest( string $url, - $method = Request::METHOD_GET, - $body = '', - \Closure $initializeRequest = null - ) { + string $method = Request::METHOD_GET, + string $body = '', + Closure $initializeRequest = null + ): ResponseAdapter { $logSeverity = SolrLogManager::INFO; $exception = null; $url = $this->reviseUrl($url); try { $request = $this->buildSolariumRequestFromUrl($url, $method); - if($initializeRequest !== null) { + if ($initializeRequest !== null) { $request = $initializeRequest($request); } $response = $this->executeRequest($request); @@ -198,7 +197,7 @@ protected function _sendRawRequest( } if ($this->configuration->getLoggingQueryRawPost() || $response->getHttpStatus() != 200) { - $message = 'Querying Solr using '.$method; + $message = 'Querying Solr using ' . $method; $this->writeLog($logSeverity, $message, $url, $response, $exception, $body); } @@ -217,7 +216,7 @@ protected function reviseUrl(string $url): string /* @var Uri $uri */ $uri = GeneralUtility::makeInstance(Uri::class, $url); - if ((string)$uri->getPath() === '') { + if ($uri->getPath() === '') { return $url; } @@ -242,15 +241,21 @@ protected function reviseUrl(string $url): string /** * Build the log data and writes the message to the log * - * @param integer $logSeverity + * @param string $logSeverity * @param string $message * @param string $url - * @param ResponseAdapter $solrResponse - * @param ?\Exception $exception + * @param ResponseAdapter|null $solrResponse + * @param ?Throwable $exception * @param string $contentSend */ - protected function writeLog($logSeverity, $message, $url, $solrResponse, $exception = null, $contentSend = '') - { + protected function writeLog( + string $logSeverity, + string $message, + string $url, + ?ResponseAdapter $solrResponse, + Throwable $exception = null, + string $contentSend = '' + ) { $logData = $this->buildLogDataFromResponse($solrResponse, $exception, $url, $contentSend); $this->logger->log($logSeverity, $message, $logData); } @@ -259,13 +264,17 @@ protected function writeLog($logSeverity, $message, $url, $solrResponse, $except * Parses the solr information to build data for the logger. * * @param ResponseAdapter $solrResponse - * @param ?\Exception $e + * @param ?Throwable $e * @param string $url * @param string $contentSend * @return array */ - protected function buildLogDataFromResponse(ResponseAdapter $solrResponse, \Exception $e = null, $url = '', $contentSend = '') - { + protected function buildLogDataFromResponse( + ResponseAdapter $solrResponse, + Throwable $e = null, + string $url = '', + string $contentSend = '' + ): array { $logData = ['query url' => $url, 'response' => (array)$solrResponse]; if ($contentSend !== '') { @@ -275,13 +284,15 @@ protected function buildLogDataFromResponse(ResponseAdapter $solrResponse, \Exce if (!empty($e)) { $logData['exception'] = $e->__toString(); return $logData; - } else { - // trigger data parsing - // @extensionScannerIgnoreLine - $solrResponse->response; - $logData['response data'] = print_r($solrResponse, true); - return $logData; } + // trigger data parsing + /** + * @noinspection PhpExpressionResultUnusedInspection + * @extensionScannerIgnoreLine + */ + $solrResponse->response; + $logData['response data'] = print_r($solrResponse, true); + return $logData; } /** @@ -293,10 +304,10 @@ protected function buildLogDataFromResponse(ResponseAdapter $solrResponse, \Exce * * Also does not report the time, see https://forge.typo3.org/issues/64551 * - * @param boolean $useCache indicates if the ping result should be cached in the instance or not + * @param bool $useCache indicates if the ping result should be cached in the instance or not * @return bool TRUE if Solr can be reached, FALSE if not */ - public function ping($useCache = true) + public function ping(bool $useCache = true): bool { try { $httpResponse = $this->performPingRequest($useCache); @@ -304,34 +315,34 @@ public function ping($useCache = true) return false; } - return ($httpResponse->getHttpStatus() === 200); + return $httpResponse->getHttpStatus() === 200; } /** * Call the /admin/ping servlet, can be used to get the runtime of a ping request. * - * @param boolean $useCache indicates if the ping result should be cached in the instance or not - * @return double runtime in milliseconds - * @throws \ApacheSolrForTypo3\Solr\PingFailedException + * @param bool $useCache indicates if the ping result should be cached in the instance or not + * @return float runtime in milliseconds + * @throws PingFailedException */ - public function getPingRoundTripRuntime($useCache = true) + public function getPingRoundTripRuntime(bool $useCache = true): float { try { $start = $this->getMilliseconds(); $httpResponse = $this->performPingRequest($useCache); $end = $this->getMilliseconds(); } catch (HttpException $e) { - $message = 'Solr ping failed with unexpected response code: ' . $e->getCode(); - /** @var $exception \ApacheSolrForTypo3\Solr\PingFailedException */ - $exception = GeneralUtility::makeInstance(PingFailedException::class, /** @scrutinizer ignore-type */ $message); - throw $exception; + throw new PingFailedException( + 'Solr ping failed with unexpected response code: ' . $e->getCode(), + 1645716101 + ); } if ($httpResponse->getHttpStatus() !== 200) { - $message = 'Solr ping failed with unexpected response code: ' . $httpResponse->getHttpStatus(); - /** @var $exception \ApacheSolrForTypo3\Solr\PingFailedException */ - $exception = GeneralUtility::makeInstance(PingFailedException::class, /** @scrutinizer ignore-type */ $message); - throw $exception; + throw new PingFailedException( + 'Solr ping failed with unexpected response code: ' . $httpResponse->getHttpStatus(), + 1645716102 + ); } return $end - $start; @@ -340,10 +351,10 @@ public function getPingRoundTripRuntime($useCache = true) /** * Performs a ping request and returns the result. * - * @param boolean $useCache indicates if the ping result should be cached in the instance or not + * @param bool $useCache indicates if the ping result should be cached in the instance or not * @return ResponseAdapter */ - protected function performPingRequest($useCache = true) + protected function performPingRequest(bool $useCache = true): ResponseAdapter { $cacheKey = (string)($this); if ($useCache && isset(static::$pingCache[$cacheKey])) { @@ -363,9 +374,9 @@ protected function performPingRequest($useCache = true) /** * Returns the current time in milliseconds. * - * @return double + * @return float */ - protected function getMilliseconds() + protected function getMilliseconds(): float { return round(microtime(true) * 1000); } @@ -381,10 +392,10 @@ protected function createAndExecuteRequest(QueryInterface $query): ResponseAdapt } /** - * @param $request + * @param Request $request * @return ResponseAdapter */ - protected function executeRequest($request): ResponseAdapter + protected function executeRequest(Request $request): ResponseAdapter { $result = $this->client->executeRequest($request); return new ResponseAdapter($result->getBody(), $result->getStatusCode(), $result->getStatusMessage()); @@ -400,8 +411,10 @@ protected function executeRequest($request): ResponseAdapter * @param string $httpMethod * @return Request */ - protected function buildSolariumRequestFromUrl(string $url, string $httpMethod = Request::METHOD_GET): Request - { + protected function buildSolariumRequestFromUrl( + string $url, + string $httpMethod = Request::METHOD_GET + ): Request { $params = []; parse_str(parse_url($url, PHP_URL_QUERY) ?? '', $params); $request = new Request(); diff --git a/Classes/System/Solr/Service/SolrAdminService.php b/Classes/System/Solr/Service/SolrAdminService.php index 68fa37bb5e..1354e77258 100644 --- a/Classes/System/Solr/Service/SolrAdminService.php +++ b/Classes/System/Solr/Service/SolrAdminService.php @@ -1,5 +1,7 @@ synonymParser = $synonymParser ?? GeneralUtility::makeInstance(SynonymParser::class); $this->stopWordParser = $stopWordParser ?? GeneralUtility::makeInstance(StopWordParser::class); @@ -116,7 +124,7 @@ public function __construct( * * @return ResponseAdapter */ - public function system() + public function system(): ResponseAdapter { return $this->_sendRawGet($this->_constructUrl(self::SYSTEM_SERVLET, ['wt' => 'json'])); } @@ -124,15 +132,18 @@ public function system() /** * Gets information about the plugins installed in Solr * - * @return array A nested array of plugin data. + * @return ResponseAdapter|null A nested array of plugin data. */ - public function getPluginsInformation() + public function getPluginsInformation(): ?ResponseAdapter { - if (count($this->pluginsData) == 0) { + if (count($this->pluginsData ?? []) === 0) { $url = $this->_constructUrl(self::PLUGINS_SERVLET, ['wt' => 'json']); $pluginsInformation = $this->_sendRawGet($url); - // access a random property to trigger response parsing + /** + * access a random property to trigger response parsing + * @noinspection PhpExpressionResultUnusedInspection + */ $pluginsInformation->responseHeader; $this->pluginsData = $pluginsInformation; } @@ -144,24 +155,25 @@ public function getPluginsInformation() * get field meta data for the index * * @param int $numberOfTerms Number of top terms to fetch for each field - * @return \stdClass + * @return stdClass */ - public function getFieldsMetaData($numberOfTerms = 0) + public function getFieldsMetaData(int $numberOfTerms = 0): stdClass { return $this->getLukeMetaData($numberOfTerms)->fields; } /** - * Retrieves meta data about the index from the luke request handler + * Retrieves metadata about the index from the luke request handler * * @param int $numberOfTerms Number of top terms to fetch for each field * @return ResponseAdapter Index meta data */ - public function getLukeMetaData($numberOfTerms = 0) + public function getLukeMetaData(int $numberOfTerms = 0): ResponseAdapter { if (!isset($this->lukeData[$numberOfTerms])) { $lukeUrl = $this->_constructUrl( - self::LUKE_SERVLET, ['numTerms' => $numberOfTerms, 'wt' => 'json', 'fl' => '*'] + self::LUKE_SERVLET, + ['numTerms' => $numberOfTerms, 'wt' => 'json', 'fl' => '*'] ); $this->lukeData[$numberOfTerms] = $this->_sendRawGet($lukeUrl); @@ -175,12 +187,15 @@ public function getLukeMetaData($numberOfTerms = 0) * * @return ResponseAdapter */ - public function getSystemInformation() + public function getSystemInformation(): ResponseAdapter { if (empty($this->systemData)) { $systemInformation = $this->system(); - // access a random property to trigger response parsing + /** + * access a random property to trigger response parsing + * @noinspection PhpExpressionResultUnusedInspection + */ $systemInformation->responseHeader; $this->systemData = $systemInformation; } @@ -194,7 +209,7 @@ public function getSystemInformation() * * @return string Name of the active solrconfig.xml */ - public function getSolrconfigName() + public function getSolrconfigName(): ?string { if (is_null($this->solrconfigName)) { $solrconfigXmlUrl = $this->_constructUrl(self::FILE_SERVLET, ['file' => 'solrconfig.xml']); @@ -227,18 +242,18 @@ public function getSolrServerVersion(): string * * @return ResponseAdapter */ - public function reloadCore() + public function reloadCore(): ResponseAdapter { return $this->reloadCoreByName($this->getPrimaryEndpoint()->getCore()); } /** - * Reloads a core of the connection by a given corename. + * Reloads a core of the connection by a given core-name. * * @param string $coreName * @return ResponseAdapter */ - public function reloadCoreByName($coreName) + public function reloadCoreByName(string $coreName): ResponseAdapter { $coreAdminReloadUrl = $this->_constructUrl(self::CORES_SERVLET) . '?action=reload&core=' . $coreName; return $this->_sendRawGet($coreAdminReloadUrl); @@ -249,7 +264,7 @@ public function reloadCoreByName($coreName) * * @return Schema */ - public function getSchema() + public function getSchema(): Schema { if ($this->schema !== null) { return $this->schema; @@ -266,7 +281,7 @@ public function getSchema() * @param string $baseWord If given a base word, retrieves the synonyms for that word only * @return array */ - public function getSynonyms($baseWord = '') + public function getSynonyms(string $baseWord = ''): array { $this->initializeSynonymsUrl(); $synonymsUrl = $this->_synonymsUrl; @@ -338,7 +353,7 @@ public function addStopWords($stopWords): ResponseAdapter * @return ResponseAdapter * @throws InvalidArgumentException If $stopWords is empty */ - public function deleteStopWord($stopWord) + public function deleteStopWord(string $stopWord): ResponseAdapter { $this->initializeStopWordsUrl(); if (empty($stopWord)) { @@ -348,9 +363,6 @@ public function deleteStopWord($stopWord) return $this->_sendRawDelete($this->_stopWordsUrl . '/' . rawurlencode(rawurlencode($stopWord))); } - /** - * @return void - */ protected function initializeSynonymsUrl() { if (trim($this->_synonymsUrl ?? '') !== '') { @@ -359,9 +371,6 @@ protected function initializeSynonymsUrl() $this->_synonymsUrl = $this->_constructUrl(self::SYNONYMS_SERVLET) . $this->getSchema()->getManagedResourceId(); } - /** - * @return void - */ protected function initializeStopWordsUrl() { if (trim($this->_stopWordsUrl ?? '') !== '') { diff --git a/Classes/System/Solr/Service/SolrReadService.php b/Classes/System/Solr/Service/SolrReadService.php index 7536fa62fd..78148aa039 100644 --- a/Classes/System/Solr/Service/SolrReadService.php +++ b/Classes/System/Solr/Service/SolrReadService.php @@ -1,5 +1,7 @@ client->createRequest($query); @@ -63,7 +65,7 @@ public function search($query) * * @return bool TRUE if a search has been executed, FALSE otherwise */ - public function hasSearched() + public function hasSearched(): bool { return $this->hasSearched; } @@ -71,9 +73,9 @@ public function hasSearched() /** * Gets the most recent response (if any) * - * @return ResponseAdapter Most recent response, or NULL if a search has not been executed yet. + * @return ResponseAdapter|null Most recent response, or NULL if a search has not been executed yet. */ - public function getResponse() + public function getResponse(): ?ResponseAdapter { return $this->responseCache; } @@ -83,28 +85,27 @@ public function getResponse() * * @param HttpException $exception * @throws SolrCommunicationException - * @return HttpException */ protected function handleErrorResponses(HttpException $exception) { $status = $exception->getCode(); $message = $exception->getStatusMessage(); - $solrRespone = new ResponseAdapter($exception->getBody()); + $solrResponse = new ResponseAdapter($exception->getBody()); if ($status === 0 || $status === 502) { $e = new SolrUnavailableException('Solr Server not available: ' . $message, 1505989391); - $e->setSolrResponse($solrRespone); + $e->setSolrResponse($solrResponse); throw $e; } if ($status === 500) { $e = new SolrInternalServerErrorException('Internal Server error during search: ' . $message, 1505989897); - $e->setSolrResponse($solrRespone); + $e->setSolrResponse($solrResponse); throw $e; } $e = new SolrCommunicationException('Invalid query. Solr returned an error: ' . $status . ' ' . $message, 1293109870); - $e->setSolrResponse($solrRespone); + $e->setSolrResponse($solrResponse); throw $e; } diff --git a/Classes/System/Solr/Service/SolrWriteService.php b/Classes/System/Solr/Service/SolrWriteService.php index 10633cdf82..295430d1a1 100644 --- a/Classes/System/Solr/Service/SolrWriteService.php +++ b/Classes/System/Solr/Service/SolrWriteService.php @@ -1,5 +1,7 @@ createAndExecuteRequest($query); - return [$response->file, (array)$response->file_metadata]; + return [$response->file, $response->file_metadata]; } catch (Throwable $e) { $param = $query->getRequestBuilder()->build($query)->getParams(); $this->logger->log( @@ -51,7 +53,7 @@ public function extractByQuery(Query $query) 'parameters' => $param, 'file' => $query->getFile(), 'query url' => self::EXTRACT_SERVLET, - 'exception' => $e->getMessage() + 'exception' => $e->getMessage(), ] ); } @@ -66,7 +68,7 @@ public function extractByQuery(Query $query) * @param string $type The type of documents to delete, usually a table name. * @param bool $commit Will commit immediately after deleting the documents if set, defaults to TRUE */ - public function deleteByType($type, $commit = true) + public function deleteByType(string $type, bool $commit = true) { $this->deleteByQuery('type:' . trim($type)); @@ -76,12 +78,13 @@ public function deleteByType($type, $commit = true) } /** - * Create a delete document based on a query and submit it + * Create the delete-query, which is document based on a query and submit it * * @param string $rawQuery Expected to be utf-8 encoded * @return ResponseAdapter */ - public function deleteByQuery($rawQuery) { + public function deleteByQuery(string $rawQuery): ResponseAdapter + { $query = $this->client->createUpdate(); $query->addDeleteQuery($rawQuery); return $this->createAndExecuteRequest($query); @@ -93,7 +96,7 @@ public function deleteByQuery($rawQuery) { * @param array $documents Should be an array of \ApacheSolrForTypo3\Solr\System\Solr\Document\Document instances * @return ResponseAdapter */ - public function addDocuments($documents) + public function addDocuments(array $documents): ResponseAdapter { $update = $this->client->createUpdate(); $update->addDocuments($documents); @@ -103,11 +106,11 @@ public function addDocuments($documents) /** * Send a commit command. Will be synchronous unless both wait parameters are set to false. * - * @param boolean $expungeDeletes Defaults to false, merge segments with deletes away - * @param boolean $waitSearcher Defaults to true, block until a new searcher is opened and registered as the main query searcher, making the changes visible + * @param bool $expungeDeletes Defaults to false, merge segments with deletes away + * @param bool $waitSearcher Defaults to true, block until a new searcher is opened and registered as the main query searcher, making the changes visible * @return ResponseAdapter */ - public function commit($expungeDeletes = false, $waitSearcher = true) + public function commit(bool $expungeDeletes = false, bool $waitSearcher = true): ResponseAdapter { $update = $this->client->createUpdate(); $update->addCommit(false, $waitSearcher, $expungeDeletes); @@ -119,7 +122,7 @@ public function commit($expungeDeletes = false, $waitSearcher = true) * * @return Result */ - public function optimizeIndex() + public function optimizeIndex(): Result { $update = $this->client->createUpdate(); $update->addOptimize(true, false, 5); diff --git a/Classes/System/Solr/SolrCommunicationException.php b/Classes/System/Solr/SolrCommunicationException.php index 4439d7d52b..d2c35f80c8 100644 --- a/Classes/System/Solr/SolrCommunicationException.php +++ b/Classes/System/Solr/SolrCommunicationException.php @@ -1,5 +1,7 @@ solrResponse; } diff --git a/Classes/System/Solr/SolrConnection.php b/Classes/System/Solr/SolrConnection.php index d6542200b4..7966808f51 100644 --- a/Classes/System/Solr/SolrConnection.php +++ b/Classes/System/Solr/SolrConnection.php @@ -1,5 +1,7 @@ getClient($endpointKey); $this->initializeClient($client, $endpointKey); - return GeneralUtility::makeInstance(SolrAdminService::class, $client, $this->configuration, $this->logger, $this->synonymParser, $this->stopWordParser, $this->schemaParser); + return GeneralUtility::makeInstance( + SolrAdminService::class, + $client, + $this->configuration, + $this->logger, + $this->synonymParser, + $this->stopWordParser, + $this->schemaParser + ); } /** @@ -203,7 +212,6 @@ public function getReadService(): SolrReadService /** * @return SolrReadService - * @noinspection PhpIncompatibleReturnTypeInspection */ protected function buildReadService(): SolrReadService { @@ -227,7 +235,6 @@ public function getWriteService(): SolrWriteService /** * @return SolrWriteService - * @noinspection PhpIncompatibleReturnTypeInspection */ protected function buildWriteService(): SolrWriteService { diff --git a/Classes/System/Solr/SolrIncompleteResponseException.php b/Classes/System/Solr/SolrIncompleteResponseException.php index 3184712eee..cb11f28d53 100644 --- a/Classes/System/Solr/SolrIncompleteResponseException.php +++ b/Classes/System/Solr/SolrIncompleteResponseException.php @@ -1,5 +1,7 @@ tca = (array)($TCA ?? $GLOBALS['TCA']); } @@ -67,7 +69,7 @@ protected function getTime(): int * @param array $record The record to check * @return bool TRUE if the record is enabled, FALSE otherwise */ - public function isEnabledRecord($table, $record) + public function isEnabledRecord(string $table, array $record): bool { if ( (empty($record)) @@ -85,15 +87,16 @@ public function isEnabledRecord($table, $record) } /** - * Checks whether a end time field exists for the record's table and if so - * determines if a time is set and whether that time is in the past, + * Checks whether an end time field exists for the record's table and if so + * determines a time is set and whether that time is in the past, * making the record invisible on the website. * * @param string $table The table name. * @param array $record An array with record fields that may affect visibility. * @return bool True if the record's end time is in the past, FALSE otherwise. + * @throws AspectNotFoundException */ - public function isEndTimeInPast($table, $record) + public function isEndTimeInPast(string $table, array $record): bool { $endTimeInPast = false; @@ -114,33 +117,35 @@ public function isEndTimeInPast($table, $record) * * Example: * - * $GLOBALS['TCA']['my_table']]['ctrl']['enablecolumns']['fe_group'] = 'mygroupfield' + * $GLOBALS['TCA']['my_table']['ctrl']['enablecolumns']['fe_group'] = 'mygroupfield' * * ->isEnableColumn('my_table', 'fe_group') will return true, because 'mygroupfield' is * configured as column. * * @params string $table + * @param string $table * @param string $columnName * @return bool */ - public function isEnableColumn($table, $columnName) + public function isEnableColumn(string $table, string $columnName): bool { - return ( + return isset($GLOBALS['TCA'][$table]['ctrl']['enablecolumns']) && array_key_exists($columnName, $GLOBALS['TCA'][$table]['ctrl']['enablecolumns']) - ); + ; } /** * Checks whether a start time field exists for the record's table and if so - * determines if a time is set and whether that time is in the future, + * determines a time is set and whether that time is in the future, * making the record invisible on the website. * * @param string $table The table name. * @param array $record An array with record fields that may affect visibility. * @return bool True if the record's start time is in the future, FALSE otherwise. + * @throws AspectNotFoundException */ - public function isStartTimeInFuture($table, $record) + public function isStartTimeInFuture(string $table, array $record): bool { $startTimeInFuture = false; @@ -152,7 +157,6 @@ public function isStartTimeInFuture($table, $record) return $startTimeInFuture; } - /** * Checks whether a hidden field exists for the current table and if so * determines whether it is set on the current record. @@ -161,7 +165,7 @@ public function isStartTimeInFuture($table, $record) * @param array $record An array with record fields that may affect visibility. * @return bool True if the record is hidden, FALSE otherwise. */ - public function isHidden($table, $record) + public function isHidden(string $table, array $record): bool { $hidden = false; @@ -180,7 +184,7 @@ public function isHidden($table, $record) * @param array $record the record array. * @return array The cleaned record */ - public function normalizeFrontendGroupField($table, $record) + public function normalizeFrontendGroupField(string $table, array $record): array { if (isset($this->tca[$table]['ctrl']['enablecolumns']['fe_group'])) { $frontendGroupsField = $this->tca[$table]['ctrl']['enablecolumns']['fe_group']; @@ -196,9 +200,9 @@ public function normalizeFrontendGroupField($table, $record) /** * @param string $table * @param array $record - * @return mixed + * @return int|null */ - public function getTranslationOriginalUid(string $table, array $record) + public function getTranslationOriginalUid(string $table, array $record): ?int { if (!isset($this->tca[$table]['ctrl']['transOrigPointerField'])) { return null; @@ -210,12 +214,12 @@ public function getTranslationOriginalUid(string $table, array $record) * Retrieves the uid that as marked as original if the record is a translation if not it returns the * originalUid. * - * @param $table + * @param string $table * @param array $record - * @param $originalUid - * @return integer + * @param int $originalUid + * @return int */ - public function getTranslationOriginalUidIfTranslated($table, array $record, $originalUid) + public function getTranslationOriginalUidIfTranslated(string $table, array $record, int $originalUid): ?int { if (!$this->isLocalizedRecord($table, $record)) { return $originalUid; @@ -231,7 +235,7 @@ public function getTranslationOriginalUidIfTranslated($table, array $record, $or * @param array $record The record to check * @return bool TRUE if the record is a language overlay, FALSE otherwise */ - public function isLocalizedRecord($tableName, array $record) + public function isLocalizedRecord(string $tableName, array $record): bool { $translationUid = $this->getTranslationOriginalUid($tableName, $record); if (is_null($translationUid)) { @@ -253,13 +257,13 @@ public function isLocalizedRecord($tableName, array $record) * @param string $table Table name to retrieve visibility affecting fields for * @return string Comma separated list of field names that affect the visibility of a record on the website */ - public function getVisibilityAffectingFieldsByTable($table) + public function getVisibilityAffectingFieldsByTable(string $table): string { if (isset($this->visibilityAffectingFields[$table])) { return $this->visibilityAffectingFields[$table]; } - // we always want to get the uid and pid although they do not affect visibility + // we always want to get the uid and pid, although they do not affect visibility $fields = ['uid', 'pid']; if (isset($this->tca[$table]['ctrl']['enablecolumns'])) { $fields = array_merge($fields, $this->tca[$table]['ctrl']['enablecolumns']); @@ -286,19 +290,19 @@ public function getVisibilityAffectingFieldsByTable($table) * @param string $fieldName * @return bool */ - public function getHasConfigurationForField(string $tableName, string $fieldName) : bool + public function getHasConfigurationForField(string $tableName, string $fieldName): bool { return isset($this->tca[$tableName]['columns'][$fieldName]); } /** - * Returns the tca configuration for a certains field + * Returns the tca configuration for a certain field * * @param string $tableName * @param string $fieldName * @return array */ - public function getConfigurationForField(string $tableName, string $fieldName) : array + public function getConfigurationForField(string $tableName, string $fieldName): array { return $this->tca[$tableName]['columns'][$fieldName] ?? []; } @@ -307,7 +311,7 @@ public function getConfigurationForField(string $tableName, string $fieldName) : * @param string $tableName * @return array */ - public function getTableConfiguration(string $tableName) : array + public function getTableConfiguration(string $tableName): array { return $this->tca[$tableName] ?? []; } diff --git a/Classes/System/Url/UrlHelper.php b/Classes/System/Url/UrlHelper.php index 884956edb4..1c090ea397 100644 --- a/Classes/System/Url/UrlHelper.php +++ b/Classes/System/Url/UrlHelper.php @@ -15,8 +15,8 @@ namespace ApacheSolrForTypo3\Solr\System\Url; +use InvalidArgumentException; use TYPO3\CMS\Core\Http\Uri; -use TYPO3\CMS\Core\Utility\MathUtility; /** * Class UrlHelper @@ -31,30 +31,22 @@ class UrlHelper extends Uri * @deprecated Will be removed with v12. Use withHost instead. * @see Uri::withHost() */ - public function setHost(string $host) + public function setHost(string $host): UrlHelper { $this->host = $host; return $this; } /** - * @param string $port + * @param int $port * @return UrlHelper * @deprecated Will be removed with v12. Use withPort instead. * @see Uri::withPort() */ - public function setPort(string $port) + public function setPort(int $port): UrlHelper { - if ($port !== '') { - if (MathUtility::canBeInterpretedAsInteger($port) === false) { - $argumentType = is_object($port) ? get_class($port) : gettype($port); - throw new \InvalidArgumentException('Invalid port "' . $argumentType . '" specified, must be an integer.', 1436717324); - } - - $port = (int)$port; - if ($port < 1 || $port > 65535) { - throw new \InvalidArgumentException('Invalid port "' . $port . '" specified, must be a valid TCP/UDP port.', 1436717326); - } + if ($port < 1 || $port > 65535) { + throw new InvalidArgumentException('Invalid port "' . $port . '" specified, must be a valid TCP/UDP port.', 1436717326); } $this->port = $port; @@ -67,7 +59,7 @@ public function setPort(string $port) * @deprecated Will be removed with v12. Use Uri::withScheme instead. * @see Uri::withScheme() */ - public function setScheme(string $scheme) + public function setScheme(string $scheme): UrlHelper { $this->scheme = $this->sanitizeScheme($scheme); return $this; @@ -79,18 +71,14 @@ public function setScheme(string $scheme) * @deprecated Will be removed with v12. Use withPath instead. * @see Uri::withPath() */ - public function setPath($path) + public function setPath(string $path): UrlHelper { - if (!is_string($path)) { - throw new \InvalidArgumentException('Invalid path provided. Must be of type string.', 1436717328); - } - if (strpos($path, '?') !== false) { - throw new \InvalidArgumentException('Invalid path provided. Must not contain a query string.', 1436717330); + throw new InvalidArgumentException('Invalid path provided. Must not contain a query string.', 1436717330); } if (strpos($path, '#') !== false) { - throw new \InvalidArgumentException('Invalid path provided; must not contain a URI fragment', 1436717332); + throw new InvalidArgumentException('Invalid path provided; must not contain a URI fragment', 1436717332); } $this->path = $this->sanitizePath($path); return $this; @@ -120,9 +108,9 @@ public function withoutQueryParameter(string $parameterName): UrlHelper /** * @param string $parameterName - * @throws \InvalidArgumentException + * @throws InvalidArgumentException * @return UrlHelper - * @deprecated Will be removed with v12. Use {@link withoutQueryParameter} instead. + * @deprecated Will be removed with v12. Use {@link withoutQueryParameter()} instead. */ public function removeQueryParameter(string $parameterName): UrlHelper { @@ -163,9 +151,9 @@ public function withQueryParameter(string $parameterName, $value): UrlHelper /** * @param string $parameterName * @param mixed $value - * @throws \InvalidArgumentException + * @throws InvalidArgumentException * @return UrlHelper - * @deprecated Will be removed with v12. Use withQueryParameter instead. + * @deprecated Will be removed with v12. Use {@link withQueryParameter()} instead. */ public function addQueryParameter(string $parameterName, $value): UrlHelper { @@ -185,7 +173,7 @@ public function addQueryParameter(string $parameterName, $value): UrlHelper /** * @return string - * @deprecated Will be removed with v12. Use __toString() instead. + * @deprecated Will be removed with v12. Use {@link __toString()} instead. */ public function getUrl(): string { diff --git a/Classes/System/UserFunctions/FlexFormUserFunctions.php b/Classes/System/UserFunctions/FlexFormUserFunctions.php index 97ff842c44..55c4c3cfe7 100644 --- a/Classes/System/UserFunctions/FlexFormUserFunctions.php +++ b/Classes/System/UserFunctions/FlexFormUserFunctions.php @@ -1,5 +1,7 @@ getConfiguredFacetsForPage($pageRecord['pid'] ?? null); if (!is_array($pageRecord)) { @@ -66,18 +72,20 @@ public function getFacetFieldsFromSchema(array &$parentInformation) * * @param array $configuredFacets * @param array $pageRecord - * @return mixed + * @return array + * @throws DBALDriverException + * @throws NoSolrConnectionFoundException */ - protected function getParsedSolrFieldsFromSchema($configuredFacets, $pageRecord) + protected function getParsedSolrFieldsFromSchema(array $configuredFacets, array $pageRecord): array { $newItems = []; - array_map(function($fieldName) use (&$newItems, $configuredFacets) { + array_map(function ($fieldName) use (&$newItems, $configuredFacets) { $value = $fieldName; $label = $fieldName; - $facetNameFilter = function($facet) use ($fieldName) { - return ($facet['field'] === $fieldName); + $facetNameFilter = function ($facet) use ($fieldName) { + return $facet['field'] === $fieldName; }; $configuredFacets = array_filter($configuredFacets, $facetNameFilter); if (!empty($configuredFacets)) { @@ -102,11 +110,16 @@ protected function getParsedSolrFieldsFromSchema($configuredFacets, $pageRecord) /** * Retrieves the configured facets for a page. * - * @param integer $pid + * @param int|null $pid * @return array + * @throws DBALDriverException + * @todo: Fix type hinting properly */ - protected function getConfiguredFacetsForPage($pid) + protected function getConfiguredFacetsForPage(?int $pid = null): ?array { + if (null === $pid) { + return null; + } $typoScriptConfiguration = $this->getConfigurationFromPageId($pid); return $typoScriptConfiguration->getSearchFacetingFacets(); } @@ -115,9 +128,9 @@ protected function getConfiguredFacetsForPage($pid) * Retrieves the translation with the LocalizationUtility. * * @param string $label - * @return null|string + * @return string|null */ - protected function getTranslation($label) + protected function getTranslation(string $label): ?string { return LocalizationUtility::translate($label); } @@ -127,31 +140,36 @@ protected function getTranslation($label) * * @param array $pageRecord * - * @return \ApacheSolrForTypo3\Solr\System\Solr\SolrConnection + * @return SolrConnection + * @throws DBALDriverException + * @throws NoSolrConnectionFoundException */ - protected function getConnection(array $pageRecord) + protected function getConnection(array $pageRecord): SolrConnection { return GeneralUtility::makeInstance(ConnectionManager::class)->getConnectionByPageId($pageRecord['pid'], $pageRecord['sys_language_uid']); } /** - * Retrieves all fieldnames that occure in the solr schema for one page. + * Retrieves all fieldnames that occurs in the solr schema for one page. * * @param array $pageRecord * @return array + * @throws DBALDriverException + * @throws NoSolrConnectionFoundException */ - protected function getFieldNamesFromSolrMetaDataForPage(array $pageRecord) + protected function getFieldNamesFromSolrMetaDataForPage(array $pageRecord): array { return array_keys((array)$this->getConnection($pageRecord)->getAdminService()->getFieldsMetaData()); } /** * @param array $parentInformation + * @throws DBALDriverException */ public function getAvailableTemplates(array &$parentInformation) { $pageRecord = $parentInformation['flexParentDatabaseRow']; - if (!is_array($pageRecord) || !isset ($pageRecord['pid'])) { + if (!is_array($pageRecord) || !isset($pageRecord['pid'])) { $parentInformation['items'] = []; return; } @@ -181,32 +199,37 @@ public function getAvailablePluginNamespaces(array &$parentInformation) /** * @param array $parentInformation - * @return string + * @return string|string[] */ - protected function getTypoScriptTemplateKeyFromFieldName(array &$parentInformation) + protected function getTypoScriptTemplateKeyFromFieldName(array $parentInformation) { $field = $parentInformation['field']; return str_replace('view.templateFiles.', '', $field); } /** - * @param $pid - * @return \ApacheSolrForTypo3\Solr\System\Configuration\TypoScriptConfiguration|array + * @param int|null $pid + * @return TypoScriptConfiguration|null + * @throws DBALDriverException + * @todo: Fix type hinting properly */ - protected function getConfigurationFromPageId($pid) + protected function getConfigurationFromPageId(?int $pid = null): ?TypoScriptConfiguration { - $typoScriptConfiguration = $this->frontendEnvironment->getSolrConfigurationFromPageId($pid); - return $typoScriptConfiguration; + if (null === $pid) { + return null; + } + return $this->frontendEnvironment->getSolrConfigurationFromPageId($pid); } /** * Retrieves the configured templates from TypoScript. * - * @param integer $pageId + * @param int $pageId * @param string $templateKey * @return array + * @throws DBALDriverException */ - protected function getAvailableTemplateFromTypoScriptConfiguration($pageId, $templateKey) + protected function getAvailableTemplateFromTypoScriptConfiguration(int $pageId, string $templateKey): array { $configuration = $this->getConfigurationFromPageId($pageId); return $configuration->getAvailableTemplatesByFileKey($templateKey); @@ -218,13 +241,13 @@ protected function getAvailableTemplateFromTypoScriptConfiguration($pageId, $tem * @param array $availableTemplates * @return array */ - protected function buildSelectItemsFromAvailableTemplate($availableTemplates) + protected function buildSelectItemsFromAvailableTemplate(array $availableTemplates): array { $newItems = []; $newItems['Use Default'] = ['Use Default', null]; foreach ($availableTemplates as $availableTemplate) { - $label = isset($availableTemplate['label']) ? $availableTemplate['label'] : ''; - $value = isset($availableTemplate['file']) ? $availableTemplate['file'] : ''; + $label = $availableTemplate['label'] ?? ''; + $value = $availableTemplate['file'] ?? ''; $newItems[$label] = [$label, $value]; } diff --git a/Classes/System/Util/ArrayAccessor.php b/Classes/System/Util/ArrayAccessor.php index b9570f0c65..c5a280a730 100644 --- a/Classes/System/Util/ArrayAccessor.php +++ b/Classes/System/Util/ArrayAccessor.php @@ -1,5 +1,7 @@ get('foo.bar'); * * echo $value; * * the example above will output "bla" - * */ class ArrayAccessor { /** - * @var array + * @var array|null */ - protected $data; + protected ?array $data; /** * @var string */ - protected $pathSeparator = ':'; + protected string $pathSeparator = ':'; /** * @var bool */ - protected $includePathSeparatorInKeys = false; + protected bool $includePathSeparatorInKeys = false; /** * @param array $data * @param string $pathSeparator * @param bool $includePathSeparatorInKeys */ - public function __construct(array $data = [], $pathSeparator = ':', $includePathSeparatorInKeys = false) - { + public function __construct( + array $data = [], + string $pathSeparator = ':', + bool $includePathSeparatorInKeys = false + ) { $this->data = $data; $this->pathSeparator = $pathSeparator; $this->includePathSeparatorInKeys = $includePathSeparatorInKeys; @@ -75,17 +79,17 @@ public function setData($data) /** * @return array */ - public function getData() + public function getData(): array { return $this->data; } /** - * @param $path + * @param string $path * @param mixed $defaultIfEmpty * @return mixed */ - public function get($path, $defaultIfEmpty = null) + public function get(string $path, $defaultIfEmpty = null) { $pathArray = $this->getPathAsArray($path); $pathSegmentCount = count($pathArray); @@ -106,10 +110,10 @@ public function get($path, $defaultIfEmpty = null) } /** - * @param $pathArray - * @return array|null + * @param array $pathArray + * @return mixed */ - protected function getDeepElementWithLoop($pathArray) + protected function getDeepElementWithLoop(array $pathArray) { $currentElement = $this->data; foreach ($pathArray as $key => $pathSegment) { @@ -131,10 +135,10 @@ protected function getDeepElementWithLoop($pathArray) } /** - * @param $path + * @param string $path * @return bool */ - public function has($path): bool + public function has(string $path): bool { return $this->get($path) !== null; } @@ -216,6 +220,7 @@ protected function resetDeepElementWithLoop(array $pathArray) unset($pathArray[$key]); // if segments are left the item does not exist if (count($pathArray) === 0) { + /** @noinspection PhpUndefinedVariableInspection */ unset($currentElement[$pathSegment]); // when the element is empty after unsetting the path segment, we can remove it completely if (empty($currentElement)) { diff --git a/Classes/System/Util/SiteUtility.php b/Classes/System/Util/SiteUtility.php index 68417903d8..b2a9326440 100644 --- a/Classes/System/Util/SiteUtility.php +++ b/Classes/System/Util/SiteUtility.php @@ -25,28 +25,26 @@ */ class SiteUtility { - - /** @var array */ - public static $languages = []; + /** + * @var array + */ + public static array $languages = []; /** * Determines if the site where the page belongs to is managed with the TYPO3 site management. * * @param int $pageId - * @return boolean + * @return bool */ public static function getIsSiteManagedSite(int $pageId): bool { - $siteFinder = GeneralUtility::makeInstance(SiteFinder::class); try { /* @var SiteFinder $siteFinder */ - $site = $siteFinder->getSiteByPageId($pageId); + return $siteFinder->getSiteByPageId($pageId) instanceof Site; } catch (SiteNotFoundException $e) { - return false; } - - return $site instanceof Site; + return false; } /** @@ -57,9 +55,9 @@ public static function getIsSiteManagedSite(int $pageId): bool * The configuration is done in the globals configuration of a site, and be extended in the language specific configuration * of a site. * - * Typically everything except the core name is configured on the global level and the core name differs for each language. + * Typically, everything except the core name is configured on the global level and the core name differs for each language. * - * In addition every property can be defined for the ```read``` and ```write``` scope. + * In addition, every property can be defined for the ```read``` and ```write``` scope. * * The convention for property keys is "solr_{propertyName}_{scope}". With the configuration "solr_host_read" you define the host * for the solr read connection. @@ -68,11 +66,16 @@ public static function getIsSiteManagedSite(int $pageId): bool * @param string $property * @param int $languageId * @param string $scope - * @param string $defaultValue - * @return string + * @param mixed $defaultValue + * @return mixed */ - public static function getConnectionProperty(Site $typo3Site, string $property, int $languageId, string $scope, string $defaultValue = null): string - { + public static function getConnectionProperty( + Site $typo3Site, + string $property, + int $languageId, + string $scope, + $defaultValue = null + ): string { $value = self::getConnectionPropertyOrFallback($typo3Site, $property, $languageId, $scope); if ($value === null) { return $defaultValue; @@ -88,10 +91,14 @@ public static function getConnectionProperty(Site $typo3Site, string $property, * @param string $property * @param int $languageId * @param string $scope - * @return mixed + * @return string|bool|null */ - protected static function getConnectionPropertyOrFallback(Site $typo3Site, string $property, int $languageId, string $scope) - { + protected static function getConnectionPropertyOrFallback( + Site $typo3Site, + string $property, + int $languageId, + string $scope + ) { if ($scope === 'write' && !self::writeConnectionIsEnabled($typo3Site, $languageId)) { $scope = 'read'; } @@ -174,7 +181,8 @@ protected static function evaluateConfigurationData($value) { if ($value === 'true') { return true; - } elseif ($value === 'false') { + } + if ($value === 'false') { return false; } diff --git a/Classes/Task/AbstractSolrTask.php b/Classes/Task/AbstractSolrTask.php index 22ef7fd2ef..1ae2502276 100644 --- a/Classes/Task/AbstractSolrTask.php +++ b/Classes/Task/AbstractSolrTask.php @@ -1,5 +1,7 @@ rootPageId = $rootPageId; } /** - * @return Site + * @return Site|null + * @throws DBALDriverException */ - public function getSite() + public function getSite(): ?Site { if (!is_null($this->site)) { return $this->site; } try { - /** @var $siteRepository SiteRepository */ + /* @var SiteRepository $siteRepository */ $siteRepository = GeneralUtility::makeInstance(SiteRepository::class); - $this->site = $siteRepository->getSiteByRootPageId($this->rootPageId); - } catch (\InvalidArgumentException $e) { + $this->site = $siteRepository->getSiteByRootPageId((int)$this->rootPageId); + } catch (InvalidArgumentException $e) { $logger = GeneralUtility::makeInstance(SolrLogManager::class, /** @scrutinizer ignore-type */ __CLASS__); $logger->log(SolrLogManager::ERROR, 'Scheduler task tried to get invalid site'); } diff --git a/Classes/Task/EventQueueWorkerTask.php b/Classes/Task/EventQueueWorkerTask.php index a2919e6b85..b5e3fed656 100644 --- a/Classes/Task/EventQueueWorkerTask.php +++ b/Classes/Task/EventQueueWorkerTask.php @@ -1,5 +1,7 @@ processEvents(); - return true; + $this->processEvents(); + return true; } /** * Process queued data update events + * + * @throws DBALDriverException + * @throws DBALException|\Doctrine\DBAL\DBALException */ protected function processEvents(): void { @@ -65,7 +78,7 @@ protected function processEvents(): void try { $event = unserialize($queueItem['event']); if (!$event instanceof DataUpdateEventInterface) { - throw new \InvalidArgumentException( + throw new InvalidArgumentException( 'Unsupported event found: ' . (is_object($event) ? get_class($event) : (string)$event), 1639747163 @@ -80,7 +93,7 @@ protected function processEvents(): void $dispatcher->dispatch( new DelayedProcessingFinishedEvent($event) ); - } catch (\Throwable $e) { + } catch (Throwable $e) { $this->getSolrLogManager()->log( SolrLogManager::ERROR, 'Couldn\'t process queued event', @@ -88,14 +101,14 @@ protected function processEvents(): void 'eventQueueItemUid' => $queueItem['uid'], 'error' => $e->getMessage(), 'errorCode' => $e->getCode(), - 'errorFile' => $e->getFile() . ':' . $e->getLine() + 'errorFile' => $e->getFile() . ':' . $e->getLine(), ] ); $itemRepository->updateEventQueueItem( $queueItem['uid'], [ 'error' => 1, - 'error_message' => $e->getMessage() . '[' . $e->getCode() . ']' + 'error_message' => $e->getMessage() . '[' . $e->getCode() . ']', ] ); } @@ -110,6 +123,8 @@ protected function processEvents(): void * the scheduler's task overview list. * * @return string Information to display + * @throws DBALDriverException + * @throws DBALException|\Doctrine\DBAL\DBALException */ public function getAdditionalInformation(): string { @@ -140,7 +155,7 @@ public function setLimit(int $limit): void /** * Returns the limit * - * @param int $limit + * @return int */ public function getLimit(): int { diff --git a/Classes/Task/EventQueueWorkerTaskAdditionalFieldProvider.php b/Classes/Task/EventQueueWorkerTaskAdditionalFieldProvider.php index fe5969472e..1376bc8ee0 100644 --- a/Classes/Task/EventQueueWorkerTaskAdditionalFieldProvider.php +++ b/Classes/Task/EventQueueWorkerTaskAdditionalFieldProvider.php @@ -1,5 +1,7 @@ '', 'label' => 'LLL:EXT:solr/Resources/Private/Language/locallang_be.xlf:task.eventQueueWorkerTask.limit', 'cshKey' => '', - 'cshLabel' => '' + 'cshLabel' => '', ]; return $additionalFields; diff --git a/Classes/Task/IndexQueueWorkerTask.php b/Classes/Task/IndexQueueWorkerTask.php index cbeae1eb4a..4e855f4d59 100644 --- a/Classes/Task/IndexQueueWorkerTask.php +++ b/Classes/Task/IndexQueueWorkerTask.php @@ -1,5 +1,7 @@ restore(); } - $executionSucceeded = true; - - return $executionSucceeded; + return true; } /** @@ -79,7 +90,7 @@ public function execute() * * @return string */ - public function getWebRoot() + public function getWebRoot(): string { if ($this->forcedWebRoot !== '') { return $this->replaceWebRootMarkers($this->forcedWebRoot); @@ -92,7 +103,7 @@ public function getWebRoot() * @param string $webRoot * @return string */ - protected function replaceWebRootMarkers($webRoot) + protected function replaceWebRootMarkers(string $webRoot): string { if (strpos($webRoot, '###PATH_typo3###') !== false) { $webRoot = str_replace('###PATH_typo3###', Environment::getPublicPath() . '/typo3/', $webRoot); @@ -110,6 +121,9 @@ protected function replaceWebRootMarkers($webRoot) * the scheduler's task overview list. * * @return string Information to display + * @throws DBALDriverException + * + * @noinspection PhpMissingReturnTypeInspection {@link \TYPO3\CMS\Scheduler\Task\AbstractTask::getAdditionalInformation()} */ public function getAdditionalInformation() { @@ -121,7 +135,6 @@ public function getAdditionalInformation() $message = 'Site: ' . $site->getLabel(); - /** @var $indexService \ApacheSolrForTypo3\Solr\Domain\Index\IndexService */ $indexService = $this->getInitializedIndexService($site); $failedItemsCount = $indexService->getFailCount(); @@ -138,6 +151,8 @@ public function getAdditionalInformation() * Gets the indexing progress. * * @return float Indexing progress as a two decimal precision float. f.e. 44.87 + * @throws DBALDriverException + * @noinspection PhpMissingReturnTypeInspection {@link \TYPO3\CMS\Scheduler\ProgressProviderInterface::getProgress()} */ public function getProgress() { @@ -146,16 +161,14 @@ public function getProgress() return 0.0; } - /** @var $indexService \ApacheSolrForTypo3\Solr\Domain\Index\IndexService */ $indexService = $this->getInitializedIndexService($site); - return $indexService->getProgress(); } /** - * @return mixed + * @return int|null */ - public function getDocumentsToIndexLimit() + public function getDocumentsToIndexLimit(): ?int { return $this->documentsToIndexLimit; } @@ -163,7 +176,7 @@ public function getDocumentsToIndexLimit() /** * @param int $limit */ - public function setDocumentsToIndexLimit($limit) + public function setDocumentsToIndexLimit(int $limit) { $this->documentsToIndexLimit = $limit; } @@ -171,7 +184,7 @@ public function setDocumentsToIndexLimit($limit) /** * @param string $forcedWebRoot */ - public function setForcedWebRoot($forcedWebRoot) + public function setForcedWebRoot(string $forcedWebRoot) { $this->forcedWebRoot = $forcedWebRoot; } @@ -179,19 +192,19 @@ public function setForcedWebRoot($forcedWebRoot) /** * @return string */ - public function getForcedWebRoot() + public function getForcedWebRoot(): string { return $this->forcedWebRoot; } /** - * Returns the initialize IndexService instance. + * Returns the initialized IndexService instance. * * @param Site $site * @return IndexService * @internal param $Site */ - protected function getInitializedIndexService(Site $site) + protected function getInitializedIndexService(Site $site): IndexService { $indexService = GeneralUtility::makeInstance(IndexService::class, /** @scrutinizer ignore-type */ $site); $indexService->setContextTask($this); diff --git a/Classes/Task/IndexQueueWorkerTaskAdditionalFieldProvider.php b/Classes/Task/IndexQueueWorkerTaskAdditionalFieldProvider.php index 7d6d271911..2b86f600dd 100644 --- a/Classes/Task/IndexQueueWorkerTaskAdditionalFieldProvider.php +++ b/Classes/Task/IndexQueueWorkerTaskAdditionalFieldProvider.php @@ -1,5 +1,7 @@ equals(Action::EDIT)) { - $taskInfo['site'] = $this->siteRepository->getSiteByRootPageId($task->getRootPageId()); + $taskInfo['site'] = $this->siteRepository->getSiteByRootPageId((int)$task->getRootPageId()); $taskInfo['documentsToIndexLimit'] = $task->getDocumentsToIndexLimit(); $taskInfo['forcedWebRoot'] = $task->getForcedWebRoot(); } $additionalFields['site'] = [ - 'code' => $siteSelectorField->getAvailableSitesSelector('tx_scheduler[site]', - $taskInfo['site']), + 'code' => $siteSelectorField->getAvailableSitesSelector( + 'tx_scheduler[site]', + $taskInfo['site'] + ), 'label' => 'LLL:EXT:solr/Resources/Private/Language/locallang.xlf:field_site', 'cshKey' => '', - 'cshLabel' => '' + 'cshLabel' => '', ]; $additionalFields['documentsToIndexLimit'] = [ - 'code' => '', + 'code' => '', 'label' => 'LLL:EXT:solr/Resources/Private/Language/locallang.xlf:indexqueueworker_field_documentsToIndexLimit', 'cshKey' => '', - 'cshLabel' => '' + 'cshLabel' => '', ]; $additionalFields['forcedWebRoot'] = [ 'code' => '', 'label' => 'LLL:EXT:solr/Resources/Private/Language/locallang.xlf:indexqueueworker_field_forcedWebRoot', 'cshKey' => '', - 'cshLabel' => '' + 'cshLabel' => '', ]; return $additionalFields; @@ -114,13 +120,13 @@ public function getAdditionalFields( * @param array $submittedData reference to the array containing the data submitted by the user * @param SchedulerModuleController $schedulerModule reference to the calling object (Scheduler's BE module) * @return bool True if validation was ok (or selected class is not relevant), FALSE otherwise - * @throws Exception + * @throws DBALDriverException + * @throws Throwable */ public function validateAdditionalFields( array &$submittedData, SchedulerModuleController $schedulerModule - ): bool - { + ): bool { $result = false; // validate site @@ -130,7 +136,7 @@ public function validateAdditionalFields( } // escape limit - $submittedData['documentsToIndexLimit'] = intval($submittedData['documentsToIndexLimit']); + $submittedData['documentsToIndexLimit'] = (int)($submittedData['documentsToIndexLimit']); return $result; } @@ -140,7 +146,7 @@ public function validateAdditionalFields( * class matches. * * @param array $submittedData array containing the data submitted by the user - * @param AbstractTask $task reference to the current task object + * @param AbstractTask|AbstractSolrTask|IndexQueueWorkerTask $task reference to the current task object */ public function saveAdditionalFields( array $submittedData, @@ -150,7 +156,7 @@ public function saveAdditionalFields( return; } - $task->setRootPageId($submittedData['site']); + $task->setRootPageId((int)$submittedData['site']); $task->setDocumentsToIndexLimit($submittedData['documentsToIndexLimit']); $task->setForcedWebRoot($submittedData['forcedWebRoot']); } @@ -159,7 +165,7 @@ public function saveAdditionalFields( * Check that a task is an instance of IndexQueueWorkerTask * * @param ?AbstractTask $task - * @return boolean + * @return bool * @throws LogicException */ protected function isTaskInstanceofIndexQueueWorkerTask(?AbstractTask $task): bool @@ -167,7 +173,8 @@ protected function isTaskInstanceofIndexQueueWorkerTask(?AbstractTask $task): bo if ((!is_null($task)) && !($task instanceof IndexQueueWorkerTask)) { throw new LogicException( '$task must be an instance of IndexQueueWorkerTask, ' - .'other instances are not supported.', 1487499814 + . 'other instances are not supported.', + 1487499814 ); } return true; diff --git a/Classes/Task/OptimizeIndexTask.php b/Classes/Task/OptimizeIndexTask.php index fa057ca8c1..df9ab78660 100644 --- a/Classes/Task/OptimizeIndexTask.php +++ b/Classes/Task/OptimizeIndexTask.php @@ -1,5 +1,7 @@ */ @@ -44,47 +47,47 @@ class OptimizeIndexTaskAdditionalFieldProvider extends AbstractAdditionalFieldPr * * @var string */ - protected $languageFile = 'LLL:EXT:solr/Resources/Private/Language/locallang.xlf'; + protected string $languageFile = 'LLL:EXT:solr/Resources/Private/Language/locallang.xlf'; /** * Task information * * @var array */ - protected $taskInformation; + protected array $taskInformation = []; /** * Scheduler task * * @var AbstractTask|null */ - protected $task = null; + protected ?AbstractTask $task = null; /** * Scheduler Module * - * @var SchedulerModuleController + * @var SchedulerModuleController|null */ - protected $schedulerModule; + protected ?SchedulerModuleController $schedulerModule = null; /** * Selected site * - * @var Site + * @var Site|null */ - protected $site = null; + protected ?Site $site = null; /** * SiteRepository * - * @var SiteRepository + * @var SiteRepository|null */ - protected $siteRepository; + protected ?SiteRepository $siteRepository = null; /** - * @var PageRenderer + * @var PageRenderer|null */ - protected $pageRenderer = null; + protected ?PageRenderer $pageRenderer = null; /** * ReIndexTaskAdditionalFieldProvider constructor. @@ -100,13 +103,13 @@ public function __construct() * @param SchedulerModuleController $schedulerModule * @param AbstractTask|null $task * @param array $taskInfo + * @throws DBALDriverException */ protected function initialize( SchedulerModuleController $schedulerModule, AbstractTask $task = null, array $taskInfo = [] - ) - { + ) { /** @var $task ReIndexTask */ $this->task = $task; $this->schedulerModule = $schedulerModule; @@ -130,7 +133,9 @@ protected function initialize( * The array is multidimensional, keyed to the task class name and each field's id * For each field it provides an associative sub-array with the following: * @throws BackendFormException + * @throws DBALDriverException * @throws NoSolrConnectionFoundException + * @throws Throwable * @noinspection PhpParameterByRefIsNotUsedAsReferenceInspection * @noinspection PhpMissingReturnTypeInspection */ @@ -138,8 +143,7 @@ public function getAdditionalFields( array &$taskInfo, $task, SchedulerModuleController $schedulerModule - ) - { + ) { $additionalFields = []; if (!$this->isTaskInstanceofOptimizeIndexTask($task)) { @@ -153,14 +157,14 @@ public function getAdditionalFields( 'code' => $siteSelectorField->getAvailableSitesSelector('tx_scheduler[site]', $this->site), 'label' => $this->languageFile . ':field_site', 'cshKey' => '', - 'cshLabel' => '' + 'cshLabel' => '', ]; $additionalFields['cores'] = [ 'code' => $this->getCoreSelectorMarkup(), 'label' => $this->languageFile . ':field_cores', 'cshKey' => '', - 'cshLabel' => '' + 'cshLabel' => '', ]; return $additionalFields; @@ -195,15 +199,15 @@ protected function getCoreSelectorMarkup(): string * @param array $submittedData reference to the array containing the data submitted by the user * @param SchedulerModuleController $schedulerModule reference to the calling object (Scheduler's BE module) * @return bool True if validation was ok (or selected class is not relevant), FALSE otherwise - * @throws Exception + * @throws DBALDriverException + * @throws Throwable * @noinspection PhpParameterByRefIsNotUsedAsReferenceInspection * @noinspection PhpMissingReturnTypeInspection */ public function validateAdditionalFields( array &$submittedData, SchedulerModuleController $schedulerModule - ) - { + ) { $result = true; // validate site $sites = $this->siteRepository->getAvailableSites(); @@ -234,8 +238,7 @@ public function validateAdditionalFields( public function saveAdditionalFields( array $submittedData, AbstractTask $task - ) - { + ) { /** @var $task OptimizeIndexTask */ if (!$this->isTaskInstanceofOptimizeIndexTask($task)) { return; @@ -267,14 +270,15 @@ protected function getPageRenderer(): ?PageRenderer * Check that a task is an instance of ReIndexTask * * @param ?AbstractTask $task - * @return boolean + * @return bool */ protected function isTaskInstanceofOptimizeIndexTask(?AbstractTask $task): bool { if ((!is_null($task)) && (!($task instanceof OptimizeIndexTask))) { throw new LogicException( '$task must be an instance of OptimizeIndexTask, ' - .'other instances are not supported.', 1624620844 + . 'other instances are not supported.', + 1624620844 ); } return true; diff --git a/Classes/Task/ReIndexTask.php b/Classes/Task/ReIndexTask.php index b455b3bb51..822dc9cc37 100644 --- a/Classes/Task/ReIndexTask.php +++ b/Classes/Task/ReIndexTask.php @@ -1,5 +1,7 @@ cleanUpIndex(); // initialize for re-indexing - /** @var Queue $indexQueue */ + /* @var Queue $indexQueue */ $indexQueue = GeneralUtility::makeInstance(Queue::class); $indexQueueInitializationResults = $indexQueue->getInitializationService() ->initializeBySiteAndIndexConfigurations($this->getSite(), $this->indexingConfigurationsToReIndex); - return ($cleanUpResult && !in_array(false, $indexQueueInitializationResults)); + return $cleanUpResult && !in_array(false, $indexQueueInitializationResults); } /** * Removes documents of the selected types from the index. * * @return bool TRUE if clean up was successful, FALSE on error + * @throws DBALDriverException */ - protected function cleanUpIndex() + protected function cleanUpIndex(): bool { $cleanUpResult = true; $solrConfiguration = $this->getSite()->getSolrConfiguration(); @@ -78,11 +91,11 @@ protected function cleanUpIndex() $solrServer->getWriteService()->deleteByQuery($deleteQuery); if (!$enableCommitsSetting) { - # Do not commit + // Do not commit continue; } - $response = $solrServer->getWriteService()->commit(false, false, false); + $response = $solrServer->getWriteService()->commit(false, false); if ($response->getHttpStatus() != 200) { $cleanUpResult = false; break; @@ -97,7 +110,7 @@ protected function cleanUpIndex() * * @return array */ - public function getIndexingConfigurationsToReIndex() + public function getIndexingConfigurationsToReIndex(): array { return $this->indexingConfigurationsToReIndex; } @@ -119,6 +132,9 @@ public function setIndexingConfigurationsToReIndex(array $indexingConfigurations * This method should be implemented in most task classes * * @return string Information to display + * + * @throws DBALDriverException + * @noinspection PhpMissingReturnTypeInspection See {@link \TYPO3\CMS\Scheduler\Task\AbstractTask::getAdditionalInformation()} */ public function getAdditionalInformation() { @@ -129,8 +145,10 @@ public function getAdditionalInformation() $information = 'Site: ' . $this->getSite()->getLabel(); if (!empty($this->indexingConfigurationsToReIndex)) { - $information .= ', Indexing Configurations: ' . implode(', ', - $this->indexingConfigurationsToReIndex); + $information .= ', Indexing Configurations: ' . implode( + ', ', + $this->indexingConfigurationsToReIndex + ); } return $information; diff --git a/Classes/Task/ReIndexTaskAdditionalFieldProvider.php b/Classes/Task/ReIndexTaskAdditionalFieldProvider.php index 7b3f70e72c..621da5b5d6 100644 --- a/Classes/Task/ReIndexTaskAdditionalFieldProvider.php +++ b/Classes/Task/ReIndexTaskAdditionalFieldProvider.php @@ -1,5 +1,7 @@ */ @@ -39,40 +44,40 @@ class ReIndexTaskAdditionalFieldProvider extends AbstractAdditionalFieldProvider * * @var array */ - protected $taskInformation; + protected array $taskInformation = []; /** * Scheduler task * - * @var AbstractTask|ReIndexTask|NULL + * @var AbstractTask|ReIndexTask|null */ - protected $task = null; + protected ?AbstractTask $task; /** * Scheduler Module * - * @var SchedulerModuleController + * @var SchedulerModuleController|null */ - protected $schedulerModule; + protected ?SchedulerModuleController $schedulerModule = null; /** * Selected site * - * @var Site + * @var Site|null */ - protected $site = null; + protected ?Site $site = null; /** * SiteRepository * * @var SiteRepository */ - protected $siteRepository; + protected SiteRepository $siteRepository; /** - * @var PageRenderer + * @var PageRenderer|null */ - protected $pageRenderer = null; + protected ?PageRenderer $pageRenderer = null; /** * ReIndexTaskAdditionalFieldProvider constructor. @@ -84,15 +89,15 @@ public function __construct() /** * @param array $taskInfo - * @param AbstractTask|NULL $task + * @param AbstractTask|null $task * @param SchedulerModuleController $schedulerModule + * @throws DBALDriverException */ protected function initialize( array $taskInfo, ?AbstractTask $task, SchedulerModuleController $schedulerModule - ) - { + ) { /** @var $task ReIndexTask */ $this->taskInformation = $taskInfo; $this->task = $task; @@ -115,6 +120,10 @@ protected function initialize( * @return array Array containing all the information pertaining to the additional fields * The array is multidimensional, keyed to the task class name and each field's id * For each field it provides an associative sub-array with the following: + * @throws DBALDriverException + * @throws Throwable + * @noinspection PhpParameterByRefIsNotUsedAsReferenceInspection + * @noinspection PhpMissingReturnTypeInspection */ public function getAdditionalFields( array &$taskInfo, @@ -131,23 +140,29 @@ public function getAdditionalFields( $siteSelectorField = GeneralUtility::makeInstance(SiteSelectorField::class); $additionalFields['site'] = [ - 'code' => $siteSelectorField->getAvailableSitesSelector('tx_scheduler[site]', - $this->site), + 'code' => $siteSelectorField->getAvailableSitesSelector( + 'tx_scheduler[site]', + $this->site + ), 'label' => 'LLL:EXT:solr/Resources/Private/Language/locallang.xlf:field_site', 'cshKey' => '', - 'cshLabel' => '' + 'cshLabel' => '', ]; $additionalFields['indexingConfigurations'] = [ 'code' => $this->getIndexingConfigurationSelector(), 'label' => 'Index Queue configurations to re-index', 'cshKey' => '', - 'cshLabel' => '' + 'cshLabel' => '', ]; return $additionalFields; } - protected function getIndexingConfigurationSelector() + + /** + * @throws BackendFormException + */ + protected function getIndexingConfigurationSelector(): string { $selectorMarkup = 'Please select a site first.'; $this->getPageRenderer()->addCssFile('../typo3conf/ext/solr/Resources/Css/Backend/indexingconfigurationselectorfield.css'); @@ -161,9 +176,7 @@ protected function getIndexingConfigurationSelector() $selectorField->setFormElementName('tx_scheduler[indexingConfigurations]'); $selectorField->setSelectedValues($this->task->getIndexingConfigurationsToReIndex()); - $selectorMarkup = $selectorField->render(); - - return $selectorMarkup; + return $selectorField->render(); } /** @@ -173,6 +186,10 @@ protected function getIndexingConfigurationSelector() * @param array $submittedData reference to the array containing the data submitted by the user * @param SchedulerModuleController $schedulerModule reference to the calling object (Scheduler's BE module) * @return bool True if validation was ok (or selected class is not relevant), FALSE otherwise + * @throws DBALDriverException + * @throws Throwable + * @noinspection PhpParameterByRefIsNotUsedAsReferenceInspection + * @noinspection PhpMissingReturnTypeInspection */ public function validateAdditionalFields( array &$submittedData, @@ -217,7 +234,7 @@ public function saveAdditionalFields( /** * @return PageRenderer */ - protected function getPageRenderer() + protected function getPageRenderer(): PageRenderer { if (!isset($this->pageRenderer)) { $this->pageRenderer = GeneralUtility::makeInstance(PageRenderer::class); @@ -229,14 +246,15 @@ protected function getPageRenderer() * Check that a task is an instance of ReIndexTask * * @param ?AbstractTask $task - * @return boolean + * @return bool */ - protected function isTaskInstanceofReIndexTask(?AbstractTask $task) + protected function isTaskInstanceofReIndexTask(?AbstractTask $task): bool { if ((!is_null($task)) && (!($task instanceof ReIndexTask))) { throw new LogicException( '$task must be an instance of ReIndexTask, ' - . 'other instances are not supported.', 1487500366 + . 'other instances are not supported.', + 1487500366 ); } return true; diff --git a/Classes/Typo3PageContentExtractor.php b/Classes/Typo3PageContentExtractor.php index 144758182d..2a9d1dcbf4 100644 --- a/Classes/Typo3PageContentExtractor.php +++ b/Classes/Typo3PageContentExtractor.php @@ -17,6 +17,8 @@ use ApacheSolrForTypo3\Solr\System\Logging\SolrLogManager; use DOMDocument; +use DOMXPath; +use function libxml_use_internal_errors; use TYPO3\CMS\Core\Utility\GeneralUtility; /** @@ -28,18 +30,17 @@ class Typo3PageContentExtractor extends HtmlContentExtractor { /** - * @var \ApacheSolrForTypo3\Solr\System\Logging\SolrLogManager + * @var SolrLogManager|null */ - protected $logger = null; + protected ?SolrLogManager $logger; /** * Shortcut method to retrieve the raw content marked for indexing. * * @return string Content marked for indexing. */ - public function getContentMarkedForIndexing() + public function getContentMarkedForIndexing(): string { - // @extensionScannerIgnoreLine return $this->extractContentMarkedForIndexing($this->content); } @@ -50,10 +51,13 @@ public function getContentMarkedForIndexing() * @param string $html HTML markup with TYPO3SEARCH markers for content that should be indexed * @return string HTML markup found between TYPO3SEARCH markers */ - protected function extractContentMarkedForIndexing($html) + protected function extractContentMarkedForIndexing(string $html): string { - preg_match_all('/.*?/mis', - $html, $indexableContents); + preg_match_all( + '/.*?/mis', + $html, + $indexableContents + ); $indexableContent = implode('', $indexableContents[0]); $indexableContent = $this->excludeContentByClass($indexableContent); @@ -72,7 +76,7 @@ protected function extractContentMarkedForIndexing($html) * @param string $indexableContent HTML markup * @return string HTML */ - public function excludeContentByClass($indexableContent) + public function excludeContentByClass(string $indexableContent): string { if (empty(trim($indexableContent))) { return $indexableContent; @@ -91,7 +95,7 @@ public function excludeContentByClass($indexableContent) $doc = new DOMDocument('1.0', 'UTF-8'); libxml_use_internal_errors(true); $doc->loadHTML('' . PHP_EOL . $indexableContent); - $xpath = new \DOMXPath($doc); + $xpath = new DOMXPath($doc); foreach ($excludeClasses as $excludePart) { $elements = $xpath->query("//*[contains(@class,'" . $excludePart . "')]"); if (count($elements) == 0) { @@ -105,9 +109,7 @@ public function excludeContentByClass($indexableContent) $html = $doc->saveHTML($doc->documentElement->parentNode); // remove XML-Preamble, newlines and doctype $html = preg_replace('/(<\?xml[^>]+\?>|\r?\n|)/imS', '', $html); - $html = str_replace(['', '', '', ''], ['', '', '', ''], $html); - - return $html; + return str_replace(['', '', '', ''], ['', '', '', ''], $html); } /** @@ -118,7 +120,7 @@ public function excludeContentByClass($indexableContent) * * @return string Indexable, cleaned content ready for indexing. */ - public function getIndexableContent() + public function getIndexableContent(): string { // @extensionScannerIgnoreLine $content = $this->extractContentMarkedForIndexing($this->content); @@ -126,9 +128,8 @@ public function getIndexableContent() // clean content $content = self::cleanContent($content); $content = trim($content); - $content = preg_replace('!\s+!u', ' ', $content); // reduce multiple spaces to one space - - return $content; + // reduce multiple spaces to one space and return + return preg_replace('!\s+!u', ' ', $content); } /** @@ -137,7 +138,7 @@ public function getIndexableContent() * * @return string the page's title */ - public function getPageTitle() + public function getPageTitle(): string { $page = $GLOBALS['TSFE']; @@ -149,7 +150,7 @@ public function getPageTitle() $pageTitle = $page->page['title']; } - return $pageTitle; + return $pageTitle ?? ''; } /** @@ -157,11 +158,8 @@ public function getPageTitle() * * @return string the page's body */ - public function getPageBody() + public function getPageBody(): string { - // @extensionScannerIgnoreLine - $pageContent = $this->content; - - return stristr($pageContent, 'content, 'initializeSolrConnection(); - } catch (\Throwable $e) { + } catch (Throwable $e) { $this->logger->log( SolrLogManager::ERROR, $e->getMessage() . ' Error code: ' . $e->getCode() @@ -135,7 +150,7 @@ public function __construct(TypoScriptFrontendController $page) SolrLogManager::ERROR, 'Exception while trying to index a page', [ - $e->__toString() + $e->__toString(), ] ); } @@ -147,7 +162,7 @@ public function __construct(TypoScriptFrontendController $page) /** * @param Item $indexQueueItem */ - public function setIndexQueueItem($indexQueueItem) + public function setIndexQueueItem(Item $indexQueueItem) { $this->indexQueueItem = $indexQueueItem; } @@ -155,7 +170,10 @@ public function setIndexQueueItem($indexQueueItem) /** * Initializes the Solr server connection. * - * @throws Exception when no Solr connection can be established. + * @throws AspectNotFoundException + * @throws DBALDriverException + * @throws NoSolrConnectionFoundException + * @throws Exception */ protected function initializeSolrConnection() { @@ -175,9 +193,9 @@ protected function initializeSolrConnection() /** * Gets the current page's Solr document ID. * - * @return string|NULL The page's Solr document ID or NULL in case no document was generated yet. + * @return string The page's Solr document ID or empty string in case no document was generated yet. */ - public static function getPageSolrDocumentId() + public static function getPageSolrDocumentId(): string { return self::$pageSolrDocumentId; } @@ -185,9 +203,9 @@ public static function getPageSolrDocumentId() /** * 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. + * @return Document|null The page's Solr document or NULL if it has not been generated yet. */ - public static function getPageSolrDocument() + public static function getPageSolrDocument(): ?Document { return self::$pageSolrDocument; } @@ -215,11 +233,12 @@ public function setSolrConnection(SolrConnection $solrConnection) * Indexes a page. * * @return bool TRUE after successfully indexing the page, FALSE on error - * @throws \UnexpectedValueException if a page document post processor fails to implement interface ApacheSolrForTypo3\Solr\PageDocumentPostProcessor + * @throws AspectNotFoundException + * @throws DBALDriverException + * @throws DBALException */ - public function indexPage() + public function indexPage(): bool { - $pageIndexed = false; $documents = []; // this will become useful as soon as when starting to index individual records instead of whole pages if (is_null($this->solrConnection)) { @@ -227,7 +246,7 @@ public function indexPage() // and waste processing time if the solr server isn't available // anyways // FIXME use an exception - return $pageIndexed; + return false; } $pageDocument = $this->getPageDocument(); @@ -251,7 +270,7 @@ public function indexPage() * * @param Document $pageDocument */ - protected function applyIndexPagePostProcessors($pageDocument) + protected function applyIndexPagePostProcessors(Document $pageDocument) { if (!is_array($GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['solr']['Indexer']['indexPagePostProcessPageDocument'] ?? null)) { return; @@ -260,7 +279,7 @@ protected function applyIndexPagePostProcessors($pageDocument) foreach ($GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['solr']['Indexer']['indexPagePostProcessPageDocument'] as $classReference) { $postProcessor = GeneralUtility::makeInstance($classReference); if (!$postProcessor instanceof PageDocumentPostProcessor) { - throw new \UnexpectedValueException(get_class($pageDocument) . ' must implement interface ' . PageDocumentPostProcessor::class, 1397739154); + throw new UnexpectedValueException(get_class($pageDocument) . ' must implement interface ' . PageDocumentPostProcessor::class, 1397739154); } $postProcessor->postProcessPageDocument($pageDocument, $this->page); @@ -271,18 +290,18 @@ protected function applyIndexPagePostProcessors($pageDocument) * Builds the Solr document for the current page. * * @return Document A document representing the page + * @throws AspectNotFoundException */ - protected function getPageDocument() + protected function getPageDocument(): Document { $documentBuilder = GeneralUtility::makeInstance(Builder::class); - $document = $documentBuilder->fromPage($this->page, $this->pageUrl, $this->pageAccessRootline, (string)$this->mountPointParameter); + $document = $documentBuilder->fromPage($this->page, $this->pageUrl, $this->pageAccessRootline, $this->mountPointParameter); self::$pageSolrDocumentId = $document['id']; return $document; } - // Logging // TODO replace by a central logger @@ -291,7 +310,7 @@ protected function getPageDocument() * * @return string */ - public function getMountPointParameter() + public function getMountPointParameter(): string { return $this->mountPointParameter; } @@ -303,9 +322,9 @@ public function getMountPointParameter() * * @param string $mountPointParameter */ - public function setMountPointParameter($mountPointParameter) + public function setMountPointParameter(string $mountPointParameter) { - $this->mountPointParameter = (string)$mountPointParameter; + $this->mountPointParameter = $mountPointParameter; } /** @@ -315,7 +334,7 @@ public function setMountPointParameter($mountPointParameter) * @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) + protected function substitutePageDocument(Document $pageDocument): Document { if (!is_array($GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['solr']['Indexer']['indexPageSubstitutePageDocument'] ?? null)) { return $pageDocument; @@ -327,7 +346,7 @@ protected function substitutePageDocument(Document $pageDocument) if (!$substituteIndexer instanceof SubstitutePageIndexer) { $message = get_class($substituteIndexer) . ' must implement interface ' . SubstitutePageIndexer::class; - throw new \UnexpectedValueException($message, 1310491001); + throw new UnexpectedValueException($message, 1310491001); } if ($substituteIndexer instanceof PageFieldMappingIndexer) { @@ -335,10 +354,6 @@ protected function substitutePageDocument(Document $pageDocument) } $substituteDocument = $substituteIndexer->getPageDocument($pageDocument); - if (!$substituteDocument instanceof Document) { - $message = 'The document returned by ' . get_class($substituteIndexer) . ' is not a valid Document object.'; - throw new \UnexpectedValueException($message, 1310490952); - } $pageDocument = $substituteDocument; } @@ -350,7 +365,7 @@ protected function substitutePageDocument(Document $pageDocument) * * @return string */ - protected function getIndexConfigurationNameForCurrentPage() + protected function getIndexConfigurationNameForCurrentPage(): string { return isset($this->indexQueueItem) ? $this->indexQueueItem->getIndexingConfigurationName() : 'pages'; } @@ -363,7 +378,7 @@ protected function getIndexConfigurationNameForCurrentPage() * @param Document[] $existingDocuments An array of documents already created for this page. * @return array An array of additional Document objects to index */ - protected function getAdditionalDocuments(Document $pageDocument, array $existingDocuments) + protected function getAdditionalDocuments(Document $pageDocument, array $existingDocuments): array { $documents = $existingDocuments; @@ -376,11 +391,11 @@ protected function getAdditionalDocuments(Document $pageDocument, array $existin if (!$additionalIndexer instanceof AdditionalPageIndexer) { $message = get_class($additionalIndexer) . ' must implement interface ' . AdditionalPageIndexer::class; - throw new \UnexpectedValueException($message, 1310491024); + throw new UnexpectedValueException($message, 1310491024); } $additionalDocuments = $additionalIndexer->getAdditionalPageDocuments($pageDocument, $documents); - if (is_array($additionalDocuments)) { + if (!empty($additionalDocuments)) { $documents = array_merge($documents, $additionalDocuments); } } @@ -393,6 +408,8 @@ protected function getAdditionalDocuments(Document $pageDocument, array $existin * care of manipulating fields as defined in the field's configuration. * * @param array $documents An array of documents to manipulate + * @throws DBALDriverException + * @throws DBALException */ protected function processDocuments(array $documents) { @@ -409,12 +426,12 @@ protected function processDocuments(array $documents) * @param array $documents An array of Document objects. * @return bool TRUE if documents were added successfully, FALSE otherwise */ - protected function addDocumentsToSolrIndex(array $documents) + protected function addDocumentsToSolrIndex(array $documents): bool { $documentsAdded = false; if (!count($documents)) { - return $documentsAdded; + return false; } try { @@ -425,12 +442,12 @@ protected function addDocumentsToSolrIndex(array $documents) foreach ($documentChunks as $documentChunk) { $response = $this->solrConnection->getWriteService()->addDocuments($documentChunk); if ($response->getHttpStatus() != 200) { - throw new \RuntimeException('Solr Request failed.', 1331834983); + throw new RuntimeException('Solr Request failed.', 1331834983); } } $documentsAdded = true; - } catch (\Throwable $e) { + } catch (Throwable $e) { $this->logger->log(SolrLogManager::ERROR, $e->getMessage() . ' Error code: ' . $e->getCode()); if ($this->configuration->getLoggingExceptions()) { @@ -446,7 +463,7 @@ protected function addDocumentsToSolrIndex(array $documents) * * @return string URL of the current page. */ - public function getPageUrl() + public function getPageUrl(): string { return $this->pageUrl; } @@ -456,7 +473,7 @@ public function getPageUrl() * * @param string $url The page's URL. */ - public function setPageUrl($url) + public function setPageUrl(string $url) { $this->pageUrl = $url; } @@ -466,7 +483,7 @@ public function setPageUrl($url) * * @return Rootline The page's access rootline */ - public function getPageAccessRootline() + public function getPageAccessRootline(): Rootline { return $this->pageAccessRootline; } @@ -486,7 +503,7 @@ public function setPageAccessRootline(Rootline $accessRootline) * * @return array An array of Document objects */ - public function getDocumentsSentToSolr() + public function getDocumentsSentToSolr(): array { return $this->documentsSentToSolr; } diff --git a/Classes/Util.php b/Classes/Util.php index dac49ba752..0c9ddacfc1 100644 --- a/Classes/Util.php +++ b/Classes/Util.php @@ -1,5 +1,7 @@ getSiteByPageId($rootPageId); $siteHash = $site->getSiteHash(); @@ -85,7 +96,7 @@ public static function getDocumentId($table, $rootPageId, $uid, $additionalIdPar * * @return TypoScriptConfiguration */ - public static function getSolrConfiguration() + public static function getSolrConfiguration(): TypoScriptConfiguration { $configurationManager = GeneralUtility::makeInstance(ConfigurationManager::class); return $configurationManager->getTypoScriptConfiguration(); @@ -98,7 +109,7 @@ public static function getSolrConfiguration() * @param int $uid The record's uid * @return bool TRUE if the record is in a draft workspace, FALSE if it's a LIVE record */ - public static function isDraftRecord($table, $uid) + public static function isDraftRecord(string $table, int $uid): bool { $isWorkspaceRecord = false; @@ -132,7 +143,7 @@ public static function isDraftRecord($table, $uid) * @param array $needles * @return bool */ - public static function containsOneOfTheStrings($haystack, array $needles) + public static function containsOneOfTheStrings(string $haystack, array $needles): bool { foreach ($needles as $needle) { $position = strpos($haystack, $needle); @@ -158,6 +169,7 @@ public static function getLanguageUid(): int /** * @return string + * @throws AspectNotFoundException */ public static function getFrontendUserGroupsList(): string { @@ -166,6 +178,7 @@ public static function getFrontendUserGroupsList(): string /** * @return array + * @throws AspectNotFoundException */ public static function getFrontendUserGroups(): array { @@ -176,8 +189,9 @@ public static function getFrontendUserGroups(): array /** * Returns the current execution time (formerly known as EXEC_TIME) * @return int + * @throws AspectNotFoundException */ - public static function getExectionTime(): int + public static function getExceptionTime(): int { $context = GeneralUtility::makeInstance(Context::class); return (int)$context->getPropertyFromAspect('date', 'timestamp'); diff --git a/Classes/Utility/ManagedResourcesUtility.php b/Classes/Utility/ManagedResourcesUtility.php index c3bafdfe5b..f83abf03df 100644 --- a/Classes/Utility/ManagedResourcesUtility.php +++ b/Classes/Utility/ManagedResourcesUtility.php @@ -1,5 +1,7 @@ ', $line, true); diff --git a/Classes/Utility/RoutingUtility.php b/Classes/Utility/RoutingUtility.php index 6215bd9e0a..69ce347b0a 100644 --- a/Classes/Utility/RoutingUtility.php +++ b/Classes/Utility/RoutingUtility.php @@ -1,5 +1,7 @@ */ diff --git a/Classes/ViewHelpers/AbstractSolrFrontendTagBasedViewHelper.php b/Classes/ViewHelpers/AbstractSolrFrontendTagBasedViewHelper.php index 18a6b9351a..0d84f74192 100644 --- a/Classes/ViewHelpers/AbstractSolrFrontendTagBasedViewHelper.php +++ b/Classes/ViewHelpers/AbstractSolrFrontendTagBasedViewHelper.php @@ -1,5 +1,7 @@ getControllerContext()->getTypoScriptConfiguration(); } /** - * @return SearchResultSet + * @return SearchResultSet|null */ - protected function getSearchResultSet() + protected function getSearchResultSet(): ?SearchResultSet { return $this->getControllerContext()->getSearchResultSet(); } /** - * @return SolrControllerContext - * @throws \InvalidArgumentException + * @return ControllerContext|SolrControllerContext + * @throws InvalidArgumentException */ - protected function getControllerContext() + protected function getControllerContext(): ControllerContext { $controllerContext = null; if (method_exists($this->renderingContext, 'getControllerContext')) { @@ -61,7 +64,7 @@ protected function getControllerContext() } if (!$controllerContext instanceof SolrControllerContext) { - throw new \InvalidArgumentException('No valid SolrControllerContext found', 1512998673); + throw new InvalidArgumentException('No valid SolrControllerContext found', 1512998673); } return $controllerContext; diff --git a/Classes/ViewHelpers/AbstractSolrFrontendViewHelper.php b/Classes/ViewHelpers/AbstractSolrFrontendViewHelper.php index 9903406c61..87ada376ee 100644 --- a/Classes/ViewHelpers/AbstractSolrFrontendViewHelper.php +++ b/Classes/ViewHelpers/AbstractSolrFrontendViewHelper.php @@ -1,5 +1,7 @@ getControllerContext()->getTypoScriptConfiguration(); } /** - * @return SearchResultSet + * @return SearchResultSet|null */ - protected function getSearchResultSet() + protected function getSearchResultSet(): ?SearchResultSet { return $this->getControllerContext()->getSearchResultSet(); } /** * @return SolrControllerContext - * @throws \InvalidArgumentException + * @throws InvalidArgumentException */ - protected function getControllerContext() + protected function getControllerContext(): SolrControllerContext { $controllerContext = null; if (method_exists($this->renderingContext, 'getControllerContext')) { @@ -63,7 +64,7 @@ protected function getControllerContext() } if (!$controllerContext instanceof SolrControllerContext) { - throw new \InvalidArgumentException('No valid SolrControllerContext found', 1512998673); + throw new InvalidArgumentException('No valid SolrControllerContext found', 1512998673); } return $controllerContext; @@ -71,11 +72,10 @@ protected function getControllerContext() /** * @param RenderingContextInterface $renderingContext - * @return SearchResultSet + * @return SearchResultSet|null */ - protected static function getUsedSearchResultSetFromRenderingContext(RenderingContextInterface $renderingContext) + protected static function getUsedSearchResultSetFromRenderingContext(RenderingContextInterface $renderingContext): ?SearchResultSet { - $resultSet = $renderingContext->getVariableProvider()->get('resultSet'); - return $resultSet; + return $renderingContext->getVariableProvider()->get('resultSet'); } } diff --git a/Classes/ViewHelpers/AbstractSolrTagBasedViewHelper.php b/Classes/ViewHelpers/AbstractSolrTagBasedViewHelper.php index 6570256ec1..0ea3aff2ca 100644 --- a/Classes/ViewHelpers/AbstractSolrTagBasedViewHelper.php +++ b/Classes/ViewHelpers/AbstractSolrTagBasedViewHelper.php @@ -1,5 +1,7 @@ registerArgument('title', 'string', 'Title', true); @@ -46,15 +46,19 @@ public function initializeArguments() * Render a help button wit the given title and content * * @param array $arguments - * @param \Closure $renderChildrenClosure + * @param Closure $renderChildrenClosure * @param RenderingContextInterface $renderingContext * @return string + * @noinspection PhpMissingReturnTypeInspection */ - public static function renderStatic(array $arguments, \Closure $renderChildrenClosure, RenderingContextInterface $renderingContext) - { + public static function renderStatic( + array $arguments, + Closure $renderChildrenClosure, + RenderingContextInterface $renderingContext + ) { return BackendUtility::wrapInHelp('', '', '', [ 'title' => $arguments['title'], - 'description' => $arguments['description'] + 'description' => $arguments['description'], ]); } } diff --git a/Classes/ViewHelpers/Backend/Security/IfHasAccessToModuleViewHelper.php b/Classes/ViewHelpers/Backend/Security/IfHasAccessToModuleViewHelper.php index 0a1be3ebf8..3ec80a9d01 100644 --- a/Classes/ViewHelpers/Backend/Security/IfHasAccessToModuleViewHelper.php +++ b/Classes/ViewHelpers/Backend/Security/IfHasAccessToModuleViewHelper.php @@ -1,5 +1,7 @@ modAccess( self::getModuleConfiguration(self::getModuleSignatureFromArguments($arguments)) ); - } catch (\RuntimeException $exception) { + } catch (RuntimeException $exception) { return false; } return $hasAccessToModule; @@ -87,9 +92,9 @@ protected static function getModuleConfiguration(string $moduleSignature) * Resolves * * @param array $arguments - * @return mixed|string + * @return string */ - protected static function getModuleSignatureFromArguments(array $arguments) + protected static function getModuleSignatureFromArguments(array $arguments): string { $moduleSignature = $arguments['signature']; @@ -103,7 +108,7 @@ protected static function getModuleSignatureFromArguments(array $arguments) $possibleErrorCode = 1496311010; } if (!isset($GLOBALS['TBE_MODULES']['_configuration'][$moduleSignature])) { - throw new \RuntimeException(vsprintf('Module with signature "%s" is not configured or couldn\'t be resolved. ' . $possibleErrorMessageAppendix, [$moduleSignature]), $possibleErrorCode); + throw new RuntimeException(vsprintf('Module with signature "%s" is not configured or couldn\'t be resolved. ' . $possibleErrorMessageAppendix, [$moduleSignature]), $possibleErrorCode); } return $moduleSignature; } @@ -118,10 +123,11 @@ public function validateArguments() parent::validateArguments(); if (empty($this->arguments['signature']) - && (empty($this->arguments['extension']) || empty($this->arguments['main']) || empty($this->arguments['sub']) + && ( + empty($this->arguments['extension']) || empty($this->arguments['main']) || empty($this->arguments['sub']) ) ) { - throw new \InvalidArgumentException('ifHasAccessToModule view helper requires either "signature" or all three other arguments: "extension", "main" and "sub". Please set arguments properly.', 1496314352); + throw new InvalidArgumentException('ifHasAccessToModule view helper requires either "signature" or all three other arguments: "extension", "main" and "sub". Please set arguments properly.', 1496314352); } } } diff --git a/Classes/ViewHelpers/Debug/DocumentScoreAnalyzerViewHelper.php b/Classes/ViewHelpers/Debug/DocumentScoreAnalyzerViewHelper.php index 7d057c80aa..3c0cd9c9fc 100644 --- a/Classes/ViewHelpers/Debug/DocumentScoreAnalyzerViewHelper.php +++ b/Classes/ViewHelpers/Debug/DocumentScoreAnalyzerViewHelper.php @@ -1,5 +1,7 @@ getUsedSearch()->getDebugResponse()->explain->{$document->getId()} ?? ''; } - /** @var $scoreService ScoreCalculationService */ $scoreService = self::getScoreService(); $queryFields = $resultSet->getUsedSearchRequest()->getContextTypoScriptConfiguration()->getSearchQueryQueryFields(); $content = $scoreService->getRenderedScores($debugData, $queryFields); @@ -92,7 +97,7 @@ public static function renderStatic(array $arguments, \Closure $renderChildrenCl /** * @return ScoreCalculationService */ - protected static function getScoreService() + protected static function getScoreService(): ScoreCalculationService { if (isset(self::$scoreService)) { return self::$scoreService; diff --git a/Classes/ViewHelpers/Document/HighlightResultViewHelper.php b/Classes/ViewHelpers/Document/HighlightResultViewHelper.php index 3f53dfd6d5..eabcaf4588 100644 --- a/Classes/ViewHelpers/Document/HighlightResultViewHelper.php +++ b/Classes/ViewHelpers/Document/HighlightResultViewHelper.php @@ -1,5 +1,7 @@ getUsedSearch()->getHighlightedContent(); if (!empty($highlightedContent->{$document->getId()}->{$fieldName}[0])) { - $content = implode(' ' . $fragmentSeparator . ' ', $highlightedContent->{$document->getId()}->{$fieldName}); - return $content; + return implode(' ' . $fragmentSeparator . ' ', $highlightedContent->{$document->getId()}->{$fieldName}); } return $content; } @@ -88,14 +94,14 @@ protected static function getHighlightedContent(SearchResultSet $resultSet, $doc * @param $content * @return string */ - protected static function escapeEverythingExceptAllowedTags(SearchResultSet $resultSet, $content) + protected static function escapeEverythingExceptAllowedTags(SearchResultSet $resultSet, $content): string { $wrap = $resultSet->getUsedSearchRequest()->getContextTypoScriptConfiguration()->getSearchResultsHighlightingWrap(); if ($wrap === '') { return htmlspecialchars($content); } - $wrapParts = GeneralUtility::trimExplode("|", $wrap); + $wrapParts = GeneralUtility::trimExplode('|', $wrap); if (count($wrapParts) !== 2) { return htmlspecialchars($content); } @@ -104,8 +110,6 @@ protected static function escapeEverythingExceptAllowedTags(SearchResultSet $res $substitutedContent = str_replace($wrapParts[1], '___highlight_end___', $substitutedContent); $output = htmlspecialchars($substitutedContent); $output = str_replace('___highlight_begin___', $wrapParts[0], $output); - $output = str_replace('___highlight_end___', $wrapParts[1], $output); - - return $output; + return str_replace('___highlight_end___', $wrapParts[1], $output); } } diff --git a/Classes/ViewHelpers/Document/RelevanceViewHelper.php b/Classes/ViewHelpers/Document/RelevanceViewHelper.php index a8ae9b6886..84050420f4 100644 --- a/Classes/ViewHelpers/Document/RelevanceViewHelper.php +++ b/Classes/ViewHelpers/Document/RelevanceViewHelper.php @@ -1,5 +1,7 @@ getMaximumScore(); @@ -64,10 +70,8 @@ public static function renderStatic(array $arguments, \Closure $renderChildrenCl } $documentScore = $document->getScore(); - $score = floatval($documentScore); + $score = $documentScore; $multiplier = 100 / $maximumScore; - $scorePercentage = round($score * $multiplier); - $content = $scorePercentage; - return $content; + return (string)round($score * $multiplier); } } diff --git a/Classes/ViewHelpers/Facet/Options/Group/Prefix/LabelPrefixesViewHelper.php b/Classes/ViewHelpers/Facet/Options/Group/Prefix/LabelPrefixesViewHelper.php index 7ab9a74397..1eea33abba 100644 --- a/Classes/ViewHelpers/Facet/Options/Group/Prefix/LabelPrefixesViewHelper.php +++ b/Classes/ViewHelpers/Facet/Options/Group/Prefix/LabelPrefixesViewHelper.php @@ -1,5 +1,7 @@ registerArgument('options', OptionCollection::class, 'The options where prefixed should be available', true); $this->registerArgument('length', 'int', 'The length of the prefixed that should be retrieved', false, 1); $this->registerArgument('sortBy', 'string', 'The sorting mode (count,alpha)', false, 'count'); - } /** * @param array $arguments - * @param \Closure $renderChildrenClosure + * @param Closure $renderChildrenClosure * @param RenderingContextInterface $renderingContext * @return string + * @noinspection PhpMissingReturnTypeInspection */ - public static function renderStatic(array $arguments, \Closure $renderChildrenClosure, RenderingContextInterface $renderingContext) - { + public static function renderStatic( + array $arguments, + Closure $renderChildrenClosure, + RenderingContextInterface $renderingContext + ) { /** @var $options OptionCollection */ $options = $arguments['options']; - $length = isset($arguments['length']) ? $arguments['length'] : 1; - $sortBy = isset($arguments['sortBy']) ? $arguments['sortBy'] : 'count'; + $length = $arguments['length'] ?? 1; + $sortBy = $arguments['sortBy'] ?? 'count'; $prefixes = $options->getLowercaseLabelPrefixes($length); $prefixes = static::applySortBy($prefixes, $sortBy); @@ -77,17 +83,13 @@ public static function renderStatic(array $arguments, \Closure $renderChildrenCl * @param string $sortBy * @return array */ - protected static function applySortBy(array $prefixes, $sortBy): array + protected static function applySortBy(array $prefixes, string $sortBy = ''): array { - if($sortBy === 'count' || $sortBy === '') - { - return $prefixes; - } - - if($sortBy === 'alpha') - { + if ($sortBy === 'alpha') { sort($prefixes); return $prefixes; } + // count is default + return $prefixes; } } diff --git a/Classes/ViewHelpers/FrequentlySearchedViewHelper.php b/Classes/ViewHelpers/FrequentlySearchedViewHelper.php index ac79963d2f..e8890e1c0a 100644 --- a/Classes/ViewHelpers/FrequentlySearchedViewHelper.php +++ b/Classes/ViewHelpers/FrequentlySearchedViewHelper.php @@ -1,5 +1,7 @@ $hits) { $size = round($minimumSize + (($hits - $minimumHits) * $step)); $frequentSearches[] = [ - 'q' => htmlspecialchars_decode($term), + 'q' => htmlspecialchars_decode((string)$term), 'hits' => $hits, 'style' => 'font-size: ' . $size . 'px', 'class' => 'tx-solr-frequent-term-' . $size, - 'size' => $size + 'size' => $size, ]; } } diff --git a/Classes/ViewHelpers/PageBrowserRangeViewHelper.php b/Classes/ViewHelpers/PageBrowserRangeViewHelper.php index f97ae81ec2..33c70270a9 100644 --- a/Classes/ViewHelpers/PageBrowserRangeViewHelper.php +++ b/Classes/ViewHelpers/PageBrowserRangeViewHelper.php @@ -1,5 +1,7 @@ registerArgument('addSuggestUrl', 'boolean', 'Indicates if suggestUrl should be rendered or not', false, true); $this->registerArgument('suggestHeader', 'string', 'The header for the top results', false, 'Top Results'); $this->registerArgument('suggestPageType', 'integer', 'The page type that should be used for the suggest', false, 7384); - } /** * Render search form tag * * @return string + * @throws AspectNotFoundException + * @noinspection PhpMissingReturnTypeInspection */ public function render() { @@ -147,7 +148,7 @@ public function render() * * @return array */ - protected function getExistingSearchParameters() + protected function getExistingSearchParameters(): array { $searchParameters = []; if ($this->getTypoScriptConfiguration()->getSearchKeepExistingParametersForNewSearches()) { @@ -159,14 +160,16 @@ protected function getExistingSearchParameters() } /** - * Translate the multi-dimensional array of existing arguments into a flat array of name-value pairs for the input tags + * Translate the multidimensional array of existing arguments into a flat array of name-value pairs for the input tags * - * @param $arguments + * @param array $arguments * @param string $nameAttributePrefix * @return array */ - protected function translateSearchParametersToInputTagAttributes($arguments, $nameAttributePrefix = '') - { + protected function translateSearchParametersToInputTagAttributes( + array $arguments, + string $nameAttributePrefix = '' + ): array { $attributes = []; foreach ($arguments as $key => $value) { $name = $nameAttributePrefix . '[' . $key . ']'; @@ -187,17 +190,18 @@ protected function translateSearchParametersToInputTagAttributes($arguments, $na * When no speaking urls are active (e.g. with TYPO3 8 and no realurl) this information is passed as query parameter * and would get lost when it is only part of the query arguments in the action parameter of the form. * - * @return boolean + * @param $pageId + * @return bool */ - protected function getIsSiteManagedSite($pageId) + protected function getIsSiteManagedSite($pageId): bool { return SiteUtility::getIsSiteManagedSite($pageId); } /** - * @return \TYPO3Fluid\Fluid\Core\Variables\VariableProviderInterface + * @return VariableProviderInterface|null */ - protected function getTemplateVariableContainer() + protected function getTemplateVariableContainer(): ?VariableProviderInterface { return $this->templateVariableContainer; } @@ -215,15 +219,20 @@ protected function getQueryString(): string } /** - * @param NULL|array $additionalFilters + * @param array|null $additionalFilters * @param int $pageUid * @return string */ - protected function getSuggestUrl($additionalFilters, $pageUid) + protected function getSuggestUrl(?array $additionalFilters, int $pageUid): string { $uriBuilder = $this->getControllerContext()->getUriBuilder(); $pluginNamespace = $this->getTypoScriptConfiguration()->getSearchPluginNamespace(); - $suggestUrl = $uriBuilder->reset()->setTargetPageUid($pageUid)->setTargetPageType($this->arguments['suggestPageType'])->setArguments([$pluginNamespace => ['additionalFilters' => $additionalFilters]])->build(); + $suggestUrl = $uriBuilder + ->reset() + ->setTargetPageUid($pageUid) + ->setTargetPageType($this->arguments['suggestPageType']) + ->setArguments([$pluginNamespace => ['additionalFilters' => $additionalFilters]]) + ->build(); /* @var UrlHelper $urlService */ $urlService = GeneralUtility::makeInstance(UrlHelper::class, $suggestUrl); @@ -237,7 +246,7 @@ protected function getSuggestUrl($additionalFilters, $pageUid) protected function buildUriFromPageUidAndArguments($pageUid): string { $uriBuilder = $this->getControllerContext()->getUriBuilder(); - $uri = $uriBuilder + return $uriBuilder ->reset() ->setTargetPageUid($pageUid) ->setTargetPageType($this->arguments['pageType'] ?? 0) @@ -249,6 +258,5 @@ protected function buildUriFromPageUidAndArguments($pageUid): string ->setAddQueryStringMethod($this->arguments['addQueryStringMethod'] ?? '') ->setSection($this->arguments['section'] ?? '') ->build(); - return $uri; } } diff --git a/Classes/ViewHelpers/TranslateViewHelper.php b/Classes/ViewHelpers/TranslateViewHelper.php index cf9ac3c162..3867b7f767 100644 --- a/Classes/ViewHelpers/TranslateViewHelper.php +++ b/Classes/ViewHelpers/TranslateViewHelper.php @@ -1,5 +1,7 @@ getControllerContext()->getRequest()->getControllerExtensionName(), %2$s[\'arguments\'], %2$s[\'languageKey\'], %2$s[\'alternativeLanguageKeys\']) ?? %2$s[\'default\'] ?? %3$s()', static::class, diff --git a/Classes/ViewHelpers/Uri/AbstractUriViewHelper.php b/Classes/ViewHelpers/Uri/AbstractUriViewHelper.php index 1e17a494dc..c26b36c135 100644 --- a/Classes/ViewHelpers/Uri/AbstractUriViewHelper.php +++ b/Classes/ViewHelpers/Uri/AbstractUriViewHelper.php @@ -1,5 +1,7 @@ getUsedSearchRequest(); diff --git a/Classes/ViewHelpers/Uri/Paginate/GroupItemPageViewHelper.php b/Classes/ViewHelpers/Uri/Paginate/GroupItemPageViewHelper.php index f1ae2511b8..dcb85b9a91 100644 --- a/Classes/ViewHelpers/Uri/Paginate/GroupItemPageViewHelper.php +++ b/Classes/ViewHelpers/Uri/Paginate/GroupItemPageViewHelper.php @@ -1,5 +1,7 @@ registerArgument('page', 'int', 'The page', false, 0); $this->registerArgument('groupItem', GroupItem::class, 'The group item', true); - } /** * @param array $arguments - * @param \Closure $renderChildrenClosure + * @param Closure $renderChildrenClosure * @param RenderingContextInterface $renderingContext * @return string + * @throws ExtbaseObjectException + * + * @noinspection PhpMissingReturnTypeInspection */ - public static function renderStatic(array $arguments, \Closure $renderChildrenClosure, RenderingContextInterface $renderingContext) + public static function renderStatic(array $arguments, Closure $renderChildrenClosure, RenderingContextInterface $renderingContext) { $page = $arguments['page']; $groupItem = $arguments['groupItem']; $previousRequest = static::getUsedSearchRequestFromRenderingContext($renderingContext); - $uri = self::getSearchUriBuilder($renderingContext)->getResultGroupItemPageUri($previousRequest, $groupItem, (int)$page); - return $uri; + return self::getSearchUriBuilder($renderingContext)->getResultGroupItemPageUri($previousRequest, $groupItem, (int)$page); } } diff --git a/Classes/ViewHelpers/Uri/Paginate/ResultPageViewHelper.php b/Classes/ViewHelpers/Uri/Paginate/ResultPageViewHelper.php index 47533af76c..15180e506f 100644 --- a/Classes/ViewHelpers/Uri/Paginate/ResultPageViewHelper.php +++ b/Classes/ViewHelpers/Uri/Paginate/ResultPageViewHelper.php @@ -1,5 +1,7 @@ registerArgument('page', 'int', 'The page', false, 0); - } /** * @param array $arguments - * @param \Closure $renderChildrenClosure + * @param Closure $renderChildrenClosure * @param RenderingContextInterface $renderingContext * @return string + * @throws ExtbaseObjectException + * + * @noinspection PhpMissingReturnTypeInspection */ - public static function renderStatic(array $arguments, \Closure $renderChildrenClosure, RenderingContextInterface $renderingContext) + public static function renderStatic(array $arguments, Closure $renderChildrenClosure, RenderingContextInterface $renderingContext) { $page = $arguments['page']; $previousRequest = static::getUsedSearchRequestFromRenderingContext($renderingContext); - $uri = self::getSearchUriBuilder($renderingContext)->getResultPageUri($previousRequest, $page); - return $uri; + return self::getSearchUriBuilder($renderingContext)->getResultPageUri($previousRequest, $page); } } diff --git a/Classes/ViewHelpers/Uri/Result/AddSearchWordListViewHelper.php b/Classes/ViewHelpers/Uri/Result/AddSearchWordListViewHelper.php index b7ec56090f..5e06e087e8 100644 --- a/Classes/ViewHelpers/Uri/Result/AddSearchWordListViewHelper.php +++ b/Classes/ViewHelpers/Uri/Result/AddSearchWordListViewHelper.php @@ -1,5 +1,7 @@ getUsedSearchRequest()->getContextTypoScriptConfiguration()->getSearchResultsSiteHighlighting()) { return $url; diff --git a/Classes/ViewHelpers/Widget/Controller/AbstractPaginateWidgetController.php b/Classes/ViewHelpers/Widget/Controller/AbstractPaginateWidgetController.php deleted file mode 100644 index da15e1fcb6..0000000000 --- a/Classes/ViewHelpers/Widget/Controller/AbstractPaginateWidgetController.php +++ /dev/null @@ -1,137 +0,0 @@ - - * @author Timo Hund - */ -abstract class AbstractPaginateWidgetController extends AbstractWidgetController -{ - - /** - * @var array - */ - protected $configuration = [ - 'insertAbove' => true, - 'insertBelow' => true, - 'maximumNumberOfLinks' => 10, - 'addQueryStringMethod' => '', - 'templatePath' => '' - ]; - - /** - * @var int - */ - protected $currentPage = 1; - - /** - * @var int - */ - protected $displayRangeStart; - - /** - * @var int - */ - protected $displayRangeEnd; - - /** - * @var int - */ - protected $maximumNumberOfLinks = 99; - - /** - * @var int - */ - protected $numberOfPages = 1; - - /** - * @var string - */ - protected $templatePath = ''; - - /** - * @return void - */ - public function initializeAction() { - $configuration = is_array($this->widgetConfiguration['configuration']) ? $this->widgetConfiguration['configuration'] : []; - ArrayUtility::mergeRecursiveWithOverrule($this->configuration, $configuration, false); - $this->maximumNumberOfLinks = (int)$this->configuration['maximumNumberOfLinks']; - if (!empty($this->configuration['templatePath'])) { - $this->templatePath = \TYPO3\CMS\Core\Utility\GeneralUtility::getFileAbsFileName($this->configuration['templatePath']); - } - } - - /** - * If a certain number of links should be displayed, adjust before and after - * amounts accordingly. - * - * @return void - */ - protected function calculateDisplayRange() - { - $maximumNumberOfLinks = $this->maximumNumberOfLinks; - if ($maximumNumberOfLinks > $this->numberOfPages) { - $maximumNumberOfLinks = $this->numberOfPages; - } - $delta = floor($maximumNumberOfLinks / 2); - $this->displayRangeStart = $this->currentPage - $delta; - $this->displayRangeEnd = $this->currentPage + $delta - ($maximumNumberOfLinks % 2 === 0 ? 1 : 0); - if ($this->displayRangeStart < 1) { - $this->displayRangeEnd -= $this->displayRangeStart - 1; - } - if ($this->displayRangeEnd > $this->numberOfPages) { - $this->displayRangeStart -= $this->displayRangeEnd - $this->numberOfPages; - } - $this->displayRangeStart = (int)max($this->displayRangeStart, 1); - $this->displayRangeEnd = (int)min($this->displayRangeEnd, $this->numberOfPages); - } - - /** - * Returns an array with the keys "pages", "current", "numberOfPages", "nextPage" & "previousPage" - * - * @return array - */ - protected function buildPagination() - { - $this->calculateDisplayRange(); - $pages = []; - for ($i = $this->displayRangeStart; $i <= $this->displayRangeEnd; $i++) { - $pages[] = ['number' => $i, 'isCurrent' => $i === $this->currentPage]; - } - $pagination = ['pages' => $pages, 'current' => $this->currentPage, 'numberOfPages' => $this->numberOfPages, 'displayRangeStart' => $this->displayRangeStart, 'displayRangeEnd' => $this->displayRangeEnd, 'hasLessPages' => $this->displayRangeStart > 2, 'hasMorePages' => $this->displayRangeEnd + 1 < $this->numberOfPages]; - if ($this->currentPage < $this->numberOfPages) { - $pagination['nextPage'] = $this->currentPage + 1; - } - if ($this->currentPage > 1) { - $pagination['previousPage'] = $this->currentPage - 1; - } - - // calculate starting count for
    (items per page multiplied by (number of pages -1) and adding +1) - $pagination['resultCountStart'] = (($this->getItemsPerPage() * ($this->currentPage - 1)) + 1); - return $pagination; - } - - /** - * @return int - */ - abstract protected function getItemsPerPage(); -} diff --git a/Classes/ViewHelpers/Widget/Controller/GroupItemPaginateController.php b/Classes/ViewHelpers/Widget/Controller/GroupItemPaginateController.php deleted file mode 100644 index 666d999c7e..0000000000 --- a/Classes/ViewHelpers/Widget/Controller/GroupItemPaginateController.php +++ /dev/null @@ -1,96 +0,0 @@ - - * @author Timo Hund - */ -class GroupItemPaginateController extends AbstractPaginateWidgetController -{ - - /** - * @var SearchResultSet - */ - protected $resultSet; - - /** - * @var GroupItem - */ - protected $groupItem; - - /** - * @return void - */ - public function initializeAction() - { - parent::initializeAction(); - - $this->resultSet = $this->widgetConfiguration['resultSet']; - $this->groupItem = $this->widgetConfiguration['groupItem']; - $this->configuration['itemsPerPage'] = $this->getItemsPerPage(); - - $this->numberOfPages = (int)ceil($this->groupItem->getAllResultCount() / $this->configuration['itemsPerPage']); - } - - /** - * Determines the number of results per page. When nothing is configured 10 will be returned. - * - * @return int - */ - protected function getItemsPerPage() - { - $perPage = (int)$this->groupItem->getGroup()->getResultsPerPage(); - return $perPage > 0 ? $perPage : 10; - } - - /** - * @param \ApacheSolrForTypo3\Solr\Mvc\Controller\SolrControllerContext $controllerContext - * @return \ApacheSolrForTypo3\Solr\Mvc\Controller\SolrControllerContext - */ - protected function setActiveSearchResultSet($controllerContext) { - $controllerContext->setSearchResultSet($this->resultSet); - return $controllerContext; - } - - /** - * @return void - */ - public function indexAction() - { - // set current page - $groupName = $this->groupItem->getGroup()->getGroupName(); - $groupItemValue = $this->groupItem->getGroupValue(); - $this->currentPage = $this->resultSet->getUsedSearchRequest()->getGroupItemPage($groupName, $groupItemValue); - if ($this->currentPage < 1) { - $this->currentPage = 1; - } - $this->view->assign('contentArguments', [$this->widgetConfiguration['as'] => $this->groupItem->getSearchResults(), 'pagination' => $this->buildPagination()]); - $this->view->assign('configuration', $this->configuration); - $this->view->assign('resultSet', $this->resultSet); - $this->view->assign('groupItem', $this->groupItem); - - if (!empty($this->templatePath)) { - $this->view->setTemplatePathAndFilename($this->templatePath); - } - } -} diff --git a/Classes/ViewHelpers/Widget/GroupItemPaginateViewHelper.php b/Classes/ViewHelpers/Widget/GroupItemPaginateViewHelper.php deleted file mode 100644 index a9aa43f907..0000000000 --- a/Classes/ViewHelpers/Widget/GroupItemPaginateViewHelper.php +++ /dev/null @@ -1,62 +0,0 @@ -controller = $groupItemPaginateController; - } - - /** - * Initializes the arguments - */ - public function initializeArguments() - { - parent::initializeArguments(); - $this->registerArgument('resultSet', SearchResultSet::class, 'resultSet', true); - $this->registerArgument('groupItem', GroupItem::class, 'groupItem', true); - $this->registerArgument('as', 'string', 'as', false, 'documents'); - $this->registerArgument('configuration', 'array', 'configuration', false, ['insertAbove' => true, 'insertBelow' => true, 'maximumNumberOfLinks' => 10, 'templatePath' => '']); - } - - /** - * @return \TYPO3\CMS\Extbase\Mvc\ResponseInterface - * @throws \TYPO3\CMS\Fluid\Core\Widget\Exception\MissingControllerException - */ - public function render() - { - return $this->initiateSubRequest(); - } -} diff --git a/Classes/Widget/AbstractWidgetController.php b/Classes/Widget/AbstractWidgetController.php deleted file mode 100644 index 205524cc17..0000000000 --- a/Classes/Widget/AbstractWidgetController.php +++ /dev/null @@ -1,116 +0,0 @@ - - * @author Timo Hund - */ -class AbstractWidgetController extends CoreAbstractWidgetController -{ - - /** - * @var array - */ - protected $supportedRequestTypes = [WidgetRequest::class]; - - /** - * @var ConfigurationManager - */ - private $solrConfigurationManager; - - /** - * @var \ApacheSolrForTypo3\Solr\Mvc\Controller\SolrControllerContext - */ - protected $controllerContext; - - /** - * @param \ApacheSolrForTypo3\Solr\System\Configuration\ConfigurationManager - */ - public function injectSolrConfigurationManager(ConfigurationManager $configurationManager) - { - $this->solrConfigurationManager = $configurationManager; - } - - /** - * Initialize the controller context - * - * @return \ApacheSolrForTypo3\Solr\Mvc\Controller\SolrControllerContext ControllerContext to be passed to the view - * @api - */ - protected function buildControllerContext() - { - /** @var $controllerContext \ApacheSolrForTypo3\Solr\Mvc\Controller\SolrControllerContext */ - $controllerContext = $this->objectManager->get(SolrControllerContext::class); - $controllerContext->setRequest($this->request); - $controllerContext->setResponse($this->response); - if ($this->arguments !== null) { - $controllerContext->setArguments($this->arguments); - } - $controllerContext->setUriBuilder($this->uriBuilder); - $typoScriptConfiguration = $this->solrConfigurationManager->getTypoScriptConfiguration(); - $controllerContext->setTypoScriptConfiguration($typoScriptConfiguration); - - $this->setActiveSearchResultSet($controllerContext); - - return $controllerContext; - } - - /** - * @param \ApacheSolrForTypo3\Solr\Mvc\Controller\SolrControllerContext $controllerContext - * @return \ApacheSolrForTypo3\Solr\Mvc\Controller\SolrControllerContext - */ - protected function setActiveSearchResultSet($controllerContext) - { - $resultSetService = $this->initializeSearch($controllerContext->getTypoScriptConfiguration()); - $lastResult = $resultSetService->getLastResultSet(); - if (!is_null($lastResult)) { - $controllerContext->setSearchResultSet($lastResult); - } - - return $controllerContext; - } - - /** - * @param TypoScriptConfiguration $typoScriptConfiguration - * @return SearchResultSetService - */ - protected function initializeSearch(TypoScriptConfiguration $typoScriptConfiguration) - { - /** @var \ApacheSolrForTypo3\Solr\ConnectionManager $solrConnection */ - $solrConnection = GeneralUtility::makeInstance(ConnectionManager::class)->getConnectionByPageId($GLOBALS['TSFE']->id, Util::getLanguageUid(), $GLOBALS['TSFE']->MP); - $search = GeneralUtility::makeInstance(Search::class, /** @scrutinizer ignore-type */ $solrConnection); - - return GeneralUtility::makeInstance( - SearchResultSetService::class, - /** @scrutinizer ignore-type */ $typoScriptConfiguration, - /** @scrutinizer ignore-type */ $search - ); - } -} diff --git a/Classes/Widget/AbstractWidgetViewHelper.php b/Classes/Widget/AbstractWidgetViewHelper.php deleted file mode 100644 index d6ce38426e..0000000000 --- a/Classes/Widget/AbstractWidgetViewHelper.php +++ /dev/null @@ -1,248 +0,0 @@ - - * @author Timo Hund - */ -abstract class AbstractWidgetViewHelper extends AbstractCoreWidgetViewHelper implements ViewHelperInterface -{ - - /** - * The Controller associated to this widget. - * This needs to be filled by the individual subclass by di - * annotation. - * - * @var AbstractWidgetController - * @api - */ - protected $controller; - - /** - * If set to TRUE, it is an AJAX widget. - * - * @var boolean - * @api - */ - protected $ajaxWidget = false; - - /** - * @var AjaxWidgetContextHolder - */ - private $ajaxWidgetContextHolder; - - /** - * @var ObjectManagerInterface - */ - protected $objectManager; - - /** - * @var ExtensionService - */ - protected $extensionService; - - /** - * @var \TYPO3\CMS\Fluid\Core\Widget\WidgetContext - */ - private $widgetContext; - - /** - * @param ExtensionService $extensionService - */ - public function injectExtensionService(ExtensionService $extensionService) - { - $this->extensionService = $extensionService; - } - - /** - * @param AjaxWidgetContextHolder $ajaxWidgetContextHolder - * @return void - */ - public function injectAjaxWidgetContextHolder(AjaxWidgetContextHolder $ajaxWidgetContextHolder) - { - $this->ajaxWidgetContextHolder = $ajaxWidgetContextHolder; - } - - /** - * @param ObjectManagerInterface $objectManager - * @return void - */ - public function injectObjectManager(ObjectManagerInterface $objectManager) - { - $this->objectManager = $objectManager; - $this->widgetContext = $this->objectManager->get(WidgetContext::class); - } - - /** - * Initialize the arguments of the ViewHelper, and call the render() method of the ViewHelper. - * - * @return string the rendered ViewHelper. - */ - public function initializeArgumentsAndRender() - { - $this->validateArguments(); - $this->initialize(); - $this->initializeWidgetContext(); - return $this->callRenderMethod(); - } - - /** - * @return SolrControllerContext - * @throws \InvalidArgumentException - */ - protected function getControllerContext() - { - $controllerContext = null; - if (method_exists($this->renderingContext, 'getControllerContext')) { - $controllerContext = $this->renderingContext->getControllerContext(); - } - - if (!$controllerContext instanceof SolrControllerContext) { - throw new \InvalidArgumentException('No valid SolrControllerContext found', 1512998673); - } - - return $controllerContext; - } - - /** - * Initialize the Widget Context, before the Render method is called. - * - * @return void - */ - private function initializeWidgetContext() - { - $this->widgetContext->setWidgetConfiguration($this->getWidgetConfiguration()); - $this->initializeWidgetIdentifier(); - $this->widgetContext->setControllerObjectName(get_class($this->controller)); - - $extensionName = $this->getControllerContext()->getRequest()->getControllerExtensionName(); - $pluginName = $this->getControllerContext()->getRequest()->getPluginName(); - $this->widgetContext->setParentExtensionName($extensionName); - $this->widgetContext->setParentPluginName($pluginName); - $pluginNamespace = $this->extensionService->getPluginNamespace($extensionName, $pluginName); - $this->widgetContext->setParentPluginNamespace($pluginNamespace); - $this->widgetContext->setWidgetViewHelperClassName(get_class($this)); - - if ($this->ajaxWidget === true) { - $this->ajaxWidgetContextHolder->store($this->widgetContext); - } - } - - /** - * Stores the syntax tree child nodes in the Widget Context, so they can be - * rendered with lateron. - * - * @param array $childNodes The SyntaxTree Child nodes of this ViewHelper. - * @return void - */ - public function setChildNodes(array $childNodes) - { - $rootNode = $this->objectManager->get(RootNode::class); - foreach ($childNodes as $childNode) { - $rootNode->addChildNode($childNode); - } - $this->widgetContext->setViewHelperChildNodes($rootNode, $this->renderingContext); - } - - /** - * Generate the configuration for this widget. Override to adjust. - * - * @return array - * @api - */ - protected function getWidgetConfiguration() - { - return $this->arguments; - } - - /** - * Initiate a sub request to $this->controller. Make sure to fill $this->controller - * via Dependency Injection. - * - * @return \TYPO3\CMS\Extbase\Mvc\ResponseInterface the response of this request. - * @throws MissingControllerException - */ - protected function initiateSubRequest() - { - if (!$this->controller instanceof AbstractWidgetController) { - if (isset($this->controller)) { - throw new MissingControllerException('initiateSubRequest() can not be called if there is no valid controller extending TYPO3\\CMS\\Fluid\\Core\\Widget\\AbstractWidgetController. Got "' . get_class($this->controller) . '" in class "' . get_class($this) . '".', 1289422564); - } - throw new MissingControllerException('initiateSubRequest() can not be called if there is no controller inside $this->controller. Make sure to add a corresponding injectController method to your WidgetViewHelper class "' . get_class($this) . '".', 1284401632); - } - /** @var $subRequest \ApacheSolrForTypo3\Solr\Widget\WidgetRequest */ - $subRequest = $this->objectManager->get(SolrFluidWidgetRequest::class); - $subRequest->setWidgetContext($this->widgetContext); - - $this->passArgumentsToSubRequest($subRequest); - $subResponse = $this->objectManager->get(Response::class); - $this->controller->processRequest($subRequest, $subResponse); - return $subResponse; - } - - /** - * Pass the arguments of the widget to the subrequest. - * - * @param CoreWidgetRequest $subRequest - * @return void - */ - private function passArgumentsToSubRequest(CoreWidgetRequest $subRequest) - { - $arguments = $this->getControllerContext()->getRequest()->getArguments(); - - if (isset($arguments)) { - if (isset($arguments['action'])) { - $subRequest->setControllerActionName($arguments['action']); - unset($arguments['action']); - } - $subRequest->setArguments($arguments); - } - } - - /** - * The widget identifier is unique on the current page, and is used - * in the URI as a namespace for the widget's arguments. - * - * @return string the widget identifier for this widget - * @return void - * @todo clean up, and make it somehow more routing compatible. - */ - private function initializeWidgetIdentifier() - { - $this->widgetContext->setWidgetIdentifier(''); - } -} diff --git a/Classes/Widget/WidgetRequest.php b/Classes/Widget/WidgetRequest.php deleted file mode 100644 index 277f515df1..0000000000 --- a/Classes/Widget/WidgetRequest.php +++ /dev/null @@ -1,39 +0,0 @@ - - * @author Timo Hund - */ -class WidgetRequest extends CoreWidgetRequest -{ - - /** - * Returns the unique URI namespace for this widget in the format pluginNamespace[widgetIdentifier] - * - * @return string - */ - public function getArgumentPrefix() - { - // we skip the [@widget] part - return $this->widgetContext->getParentPluginNamespace(); - } -} diff --git a/Configuration/RequestMiddlewares.php b/Configuration/RequestMiddlewares.php index e99193e5dc..8fb4283aa0 100644 --- a/Configuration/RequestMiddlewares.php +++ b/Configuration/RequestMiddlewares.php @@ -5,22 +5,22 @@ 'frontend' => [ 'apache-solr-for-typo3/page-indexer-fe-user-authenticator' => [ 'target' => \ApacheSolrForTypo3\Solr\Middleware\FrontendUserAuthenticator::class, - 'before' => ['apache-solr-for-typo3/page-indexer-initialization'] + 'before' => ['apache-solr-for-typo3/page-indexer-initialization'], ], 'apache-solr-for-typo3/page-indexer-initialization' => [ 'target' => \ApacheSolrForTypo3\Solr\Middleware\PageIndexerInitialization::class, 'before' => ['typo3/cms-frontend/tsfe'], - 'after' => ['typo3/cms-core/normalized-params-attribute'] + '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'] + 'after' => ['typo3/cms-frontend/content-length-headers'], ], 'apache-solr-for-typo3/solr-route-enhancer' => [ 'target' => \ApacheSolrForTypo3\Solr\Middleware\SolrRoutingMiddleware::class, 'before' => [ 'typo3/cms-frontend/site', - ] - ] - ] + ], + ], + ], ]; diff --git a/Configuration/SiteConfiguration/Overrides/sites.php b/Configuration/SiteConfiguration/Overrides/sites.php index 71ca7b002c..a61b77bc5d 100644 --- a/Configuration/SiteConfiguration/Overrides/sites.php +++ b/Configuration/SiteConfiguration/Overrides/sites.php @@ -3,7 +3,6 @@ /** * Global Solr Connection Settings */ - $GLOBALS['SiteConfiguration']['site']['columns']['solr_enabled_read'] = [ 'label' => 'Enable Solr for this site', 'onChange' => 'reload', @@ -14,9 +13,9 @@ 'items' => [ [ 0 => '', - 1 => '' - ] - ] + 1 => '', + ], + ], ], ]; @@ -28,12 +27,12 @@ 'valuePicker' => [ 'items' => [ [ 'http', 'http'], - [ 'https', 'https'] - ] + [ 'https', 'https'], + ], ], 'placeholder' => 'http', ], - 'displayCond' => 'FIELD:solr_enabled_read:=:1' + 'displayCond' => 'FIELD:solr_enabled_read:=:1', ]; $GLOBALS['SiteConfiguration']['site']['columns']['solr_host_read'] = [ @@ -42,21 +41,20 @@ 'type' => 'input', 'default' => 'localhost', 'placeholder' => 'localhost', - 'size' => 10 + 'size' => 10, ], - 'displayCond' => 'FIELD:solr_enabled_read:=:1' + 'displayCond' => 'FIELD:solr_enabled_read:=:1', ]; - $GLOBALS['SiteConfiguration']['site']['columns']['solr_port_read'] = [ 'label' => 'Port', 'config' => [ 'type' => 'input', 'eval' => 'required', 'size' => 5, - 'default' => 8983 + 'default' => 8983, ], - 'displayCond' => 'FIELD:solr_enabled_read:=:1' + 'displayCond' => 'FIELD:solr_enabled_read:=:1', ]; $GLOBALS['SiteConfiguration']['site']['columns']['solr_path_read'] = [ @@ -65,9 +63,9 @@ 'config' => [ 'type' => 'input', 'eval' => 'trim', - 'default' => '/' + 'default' => '/', ], - 'displayCond' => 'FIELD:solr_enabled_read:=:1' + 'displayCond' => 'FIELD:solr_enabled_read:=:1', ]; $GLOBALS['SiteConfiguration']['site']['columns']['solr_use_write_connection'] = [ @@ -80,11 +78,11 @@ 'items' => [ [ 0 => '', - 1 => '' - ] - ] + 1 => '', + ], + ], ], - 'displayCond' => 'FIELD:solr_enabled_read:=:1' + 'displayCond' => 'FIELD:solr_enabled_read:=:1', ]; // write TCA @@ -103,13 +101,11 @@ $GLOBALS['SiteConfiguration']['site']['columns']['solr_path_write']['config']['eval'] = ''; $GLOBALS['SiteConfiguration']['site']['columns']['solr_path_write']['displayCond'] = 'FIELD:solr_use_write_connection:=:1'; - $GLOBALS['SiteConfiguration']['site']['palettes']['solr_read']['showitem'] = 'solr_scheme_read, solr_host_read, solr_port_read, solr_path_read'; $GLOBALS['SiteConfiguration']['site']['palettes']['solr_write']['showitem'] = 'solr_scheme_write, solr_host_write, solr_port_write, solr_path_write'; $GLOBALS['SiteConfiguration']['site']['types']['0']['showitem'] .= ',--div--;Solr,solr_enabled_read,--palette--;;solr_read, solr_use_write_connection,--palette--;;solr_write'; - /** * Language specific core configuration */ @@ -161,7 +157,7 @@ ], ], 'placeholder' => 'core_*', - ] + ], ]; $GLOBALS['SiteConfiguration']['site_language']['types']['1']['showitem'] = str_replace( diff --git a/Configuration/TCA/Overrides/pages.php b/Configuration/TCA/Overrides/pages.php index e45da829b9..e995fbeedb 100644 --- a/Configuration/TCA/Overrides/pages.php +++ b/Configuration/TCA/Overrides/pages.php @@ -1,4 +1,5 @@ '', 1 => '', - 'invertStateDisplay' => true - ] + 'invertStateDisplay' => true, + ], ], 'behaviour' => [ - 'allowLanguageSynchronization' => true - ] - ] + 'allowLanguageSynchronization' => true, + ], + ], ], ] ); diff --git a/Configuration/TCA/Overrides/sys_template.php b/Configuration/TCA/Overrides/sys_template.php index d59f3a6646..cce6afa6e4 100644 --- a/Configuration/TCA/Overrides/sys_template.php +++ b/Configuration/TCA/Overrides/sys_template.php @@ -1,75 +1,123 @@ withPageId($pageId); } - - /** - * @return Response - */ - protected function getPreparedResponse() - { - return $this->objectManager->get(Response::class); - } } diff --git a/Tests/Integration/Controller/Fixtures/can_render_error_message_when_solr_unavailable.xml b/Tests/Integration/Controller/Fixtures/can_render_error_message_when_solr_unavailable.xml deleted file mode 100644 index 664ffe9450..0000000000 --- a/Tests/Integration/Controller/Fixtures/can_render_error_message_when_solr_unavailable.xml +++ /dev/null @@ -1,308 +0,0 @@ - - - - - 1 - 1 - 1 - 3 - - - - # very simple rendering - page.10 = CONTENT - page.10 { - table = tt_content - select.orderBy = sorting - select.where = colPos=0 - renderObj = COA - renderObj { - 10 = TEXT - 10.field = bodytext - } - } - - page.10.wrap = | - - plugin.tx_solr { - view { - - # important! else linkbuilding will fail - pluginNamespace = tx_solr - } - enabled = 1 - - enableDebugMode = 0 - - general { - dateFormat.date = d.m.Y H:i - baseWrap { - value =
    |
    - } - } - - - index { - additionalFields { - - } - - // assigns processing instructions to Solr fields during indexing, Solr field = processing instruction - fieldProcessingInstructions { - changed = timestampToIsoDate - created = timestampToIsoDate - endtime = timestampToUtcIsoDate - rootline = pageUidToHierarchy - pageHierarchy_stringM = pathToHierarchy - } - - queue { - - // mapping tableName.fields.SolrFieldName => TableFieldName (+ cObj processing) - - pages = 1 - pages { - initialization = ApacheSolrForTypo3\Solr\IndexQueue\Initializer\Page - - // allowed page types (doktype) when indexing records from table "pages" - allowedPageTypes = 1,7,4 - - indexingPriority = 0 - - indexer = ApacheSolrForTypo3\Solr\IndexQueue\PageIndexer - indexer { - // add options for the indexer here - } - - // Only index standard pages and mount points that are not overlayed. - additionalWhereClause = (doktype = 1 OR doktype=4 OR (doktype=7 AND mount_pid_ol=0)) AND no_search = 0 - - //exclude some html parts inside TYPO3SEARCH markers by classname (comma list) - excludeContentByClass = typo3-search-exclude - - fields { - sortSubTitle_stringS = subtitle - } - } - - } - } - - search { - // fields that are allowed to contain html and should be skipped during escaping after retrieval from Solr - // by default all fields expect url get escaped, you might need to add other url fields here as well because of & - // characters in the url. - trustedFields = url - - targetPage = {$plugin.tx_solr.search.targetPage} - - initializeWithEmptyQuery = 0 - showResultsOfInitialEmptyQuery = 0 - - initializeWithQuery = - showResultsOfInitialQuery = 0 - - keepExistingParametersForNewSearches = 1 - - query { - allowEmptyQuery = 1 - - allowedSites = __solr_current_site - - // qf parameter http://wiki.apache.org/solr/DisMaxQParserPlugin#qf_.28Query_Fields.29 - queryFields = content^40.0, title^5.0, keywords^2.0, tagsH1^5.0, tagsH2H3^3.0, tagsH4H5H6^2.0, tagsInline^1.0, description^4.0, abstract^1.0, subtitle^1.0, navtitle^1.0, author^1.0 - - // fl parameter http://wiki.apache.org/solr/CommonQueryParameters#fl - returnFields = *, score - - // see http://wiki.apache.org/solr/DisMaxRequestHandler#mm_.28Minimum_.27Should.27_Match.29 - minimumMatch = - - // see http://wiki.apache.org/solr/DisMaxRequestHandler#bf_.28Boost_Functions.29 - boostFunction = - - // see http://wiki.apache.org/solr/DisMaxQParserPlugin#bq_.28Boost_Query.29 - boostQuery = - - filter { - - } - - sortBy = - } - - results { - resultsHighlighting = 1 - resultsHighlighting { - // can be used to increase the highlighting performance requires the field is termVectors=on, - // termPositions=on and termOffsets=on which is set for content. NOTE: fragmentSize needs to be larger - // then 18 - useFastVectorHighlighter = 0 - highlightFields = content - fragmentSize = 20 - fragmentSeparator = [...] - - wrap = | - } - siteHighlighting = 0 - - resultsPerPage = 5 - resultsPerPageSwitchOptions = 5, 10, 25, 50 - - pagebrowser { - enabled = 1 - - pagesBefore = 3 - pagesAfter = 3 - - enableMorePages = 1 - enableLessPages = 1 - } - - showDocumentScoreAnalysis = 1 - } - - spellchecking = 1 - spellchecking { - wrap = |
    ###LLL:didYouMean### |
    | - searchUsingSpellCheckerSuggestion = 0 - numberOfSuggestionsToTry = 0 - } - - lastSearches = 1 - lastSearches { - limit = 10 - // tracking mode "user" or "global" - mode = user - } - - frequentSearches = 1 - frequentSearches { - useLowercaseKeywords = 0 - - minSize = 15 - maxSize = 40 - limit = 20 - - select { - SELECT = keywords as search_term, count(*) as hits - FROM = tx_solr_statistics - ADD_WHERE = AND num_found != 0 - GROUP_BY = keywords - ORDER_BY = hits DESC, search_term ASC - checkRootPageId = 1 - checkLanguage = 1 - } - - // cache lifetime in seconds (default is 86400s = 24h) - cacheLifetime = 86400 - } - - faceting = 1 - faceting { - minimumCount = 1 - sortBy = count - limit = 10 - showEmptyFacets = 0 - keepAllFacetsOnSelection = 0 - - facetLinkUrlParameters = &foo=bar - - facets { - type { - label = Content Type - field = type - } - } - - showAllLink.wrap =
  1. |
  2. - } - - elevation = 1 - elevation { - markElevatedResults = 1 - forceElevation = 1 - } - - } - - suggest = 1 - suggest { - numberOfSuggestions = 10 - suggestField = spell - forceHttps = 0 - } - - statistics = 1 - statistics { - anonymizeIP = 0 - } - - viewHelpers { - crop { - maxLength = 300 - cropIndicator = ... - } - - sortIndicator { - up { - altText = sort ascending - file = EXT:solr/Resources/Public/Images/IndicatorUp.png - } - down { - altText = sort descending - file = EXT:solr/Resources/Public/Images/IndicatorDown.png - } - } - } - - logging { - exceptions = 1 - - indexing { - indexQueueInitialization = 0 - missingTypo3SearchMarkers = 1 - pageIndexed = 0 - - queue { - pages = 0 - } - } - - query { - filters = 0 - searchWords = 0 - queryString = 0 - rawPost = 0 - rawGet = 0 - rawDelete = 0 - } - } - } - ]]> -
    - 100 - 0 -
    - - 1 - 1 - 1 - Products - -
    \ No newline at end of file diff --git a/Tests/Integration/Controller/SearchControllerTest.php b/Tests/Integration/Controller/SearchControllerTest.php index c40de4baa9..9e64212f0a 100644 --- a/Tests/Integration/Controller/SearchControllerTest.php +++ b/Tests/Integration/Controller/SearchControllerTest.php @@ -1,5 +1,7 @@ collectGarbage() + * @see \ApacheSolrForTypo3\Solr\GarbageCollector::collectGarbage() */ - public function postProcessGarbageCollector($table, $uid) + public function postProcessGarbageCollector(string $table, int $uid) { $this->hookWasCalled = true; } diff --git a/Tests/Unit/Domain/Index/IndexServiceTest.php b/Tests/Unit/Domain/Index/IndexServiceTest.php index fe52a05060..448c55c3ea 100644 --- a/Tests/Unit/Domain/Index/IndexServiceTest.php +++ b/Tests/Unit/Domain/Index/IndexServiceTest.php @@ -25,6 +25,7 @@ use ApacheSolrForTypo3\Solr\System\Logging\SolrLogManager; use ApacheSolrForTypo3\Solr\Tests\Unit\UnitTest; use Exception; +use PHPUnit\Framework\MockObject\MockObject; use TYPO3\CMS\Extbase\SignalSlot\Dispatcher; /** @@ -33,7 +34,7 @@ class IndexServiceTest extends UnitTest { /** - * @var Site + * @var Site|MockObject */ protected $siteMock; @@ -67,6 +68,10 @@ protected function setUp(): void public function signalsAreTriggered() { $fakeConfiguration = $this->getDumbMock(TypoScriptConfiguration::class); + $this->siteMock = $this->getMockBuilder(Site::class) + ->disableOriginalConstructor() + ->onlyMethods(['getSolrConfiguration']) + ->getMock(); $this->siteMock->expects(self::once())->method('getSolrConfiguration')->willReturn($fakeConfiguration); // we create an IndexeService where indexItem is mocked to avoid real indexing in the unit test @@ -112,10 +117,14 @@ public function testConfigurationIsNotFetchedWhenProgressIsCaluclated() public function testServerHostIsRestoredInCaseOfAnException() { $fakeConfiguration = $this->getDumbMock(TypoScriptConfiguration::class); - $this->siteMock->expects(self::once())->method('getSolrConfiguration')->willReturn($fakeConfiguration); - $this->siteMock->expects(self::once())->method('getDomain')->willReturn('www.indextest.local'); + $this->siteMock = $this->getMockBuilder(Site::class) + ->disableOriginalConstructor() + ->onlyMethods(['getSolrConfiguration', 'getDomain']) + ->getMock(); + $this->siteMock->expects(self::any())->method('getSolrConfiguration')->willReturn($fakeConfiguration); + $this->siteMock->expects(self::any())->method('getDomain')->willReturn('www.indextest.local'); - /** @var $indexService IndexService */ + /* @var IndexService|MockObject $indexService */ $indexService = $this->getMockBuilder(IndexService::class) ->setConstructorArgs([$this->siteMock, $this->queueMock, $this->dispatcherMock, $this->logManagerMock]) ->onlyMethods(['getIndexerByItem', 'restoreOriginalHttpHost']) @@ -123,16 +132,21 @@ public function testServerHostIsRestoredInCaseOfAnException() $indexService->expects(self::exactly(2))->method('restoreOriginalHttpHost'); - $indexerMock = $this->getDumbMock(Indexer::class); + $indexerMock = $this->getMockBuilder(Indexer::class) + ->disableOriginalConstructor() + ->onlyMethods(['index']) + ->getMock(); $indexerMock->expects(self::exactly(2))->method('index')->willReturnCallback(function () { - throw new Exception('unknowen error occured'); + throw new Exception('unknown error occurred'); }); $indexService->expects(self::exactly(2))->method('getIndexerByItem')->willReturn($indexerMock); // we fake an index queue with two items $item1 = $this->getDumbMock(Item::class); $item1->expects(self::any())->method('getSite')->willReturn($this->siteMock); + $item1->expects(self::any())->method('getIndexingConfigurationName')->willReturn('fake_table'); $item2 = $this->getDumbMock(Item::class); + $item2->expects(self::any())->method('getIndexingConfigurationName')->willReturn('fake_table'); $fakeItems = [$item1, $item2]; $this->fakeQueueItemContent($fakeItems); @@ -149,7 +163,7 @@ public function testDomainIsUsedFromSiteObject() $this->siteMock->expects(self::once())->method('getSolrConfiguration')->willReturn($fakeConfiguration); $this->siteMock->expects(self::any())->method('getDomain')->willReturn('www.indextest.local'); - /** @var $indexService IndexService */ + /* @var IndexService|MockObject $indexService */ $indexService = $this->getMockBuilder(IndexService::class) ->setConstructorArgs([$this->siteMock, $this->queueMock, $this->dispatcherMock, $this->logManagerMock]) ->onlyMethods(['getIndexerByItem']) @@ -162,7 +176,9 @@ public function testDomainIsUsedFromSiteObject() // we fake an index queue with two items $item1 = $this->getDumbMock(Item::class); $item1->expects(self::any())->method('getSite')->willReturn($this->siteMock); + $item1->expects(self::any())->method('getIndexingConfigurationName')->willReturn('fake_table'); $item2 = $this->getDumbMock(Item::class); + $item2->expects(self::any())->method('getIndexingConfigurationName')->willReturn('fake_table'); $fakeItems = [$item1, $item2]; $this->fakeQueueItemContent($fakeItems); @@ -175,7 +191,10 @@ public function testDomainIsUsedFromSiteObject() */ protected function fakeQueueItemContent($fakeItems) { - $this->queueMock->expects(self::once())->method('getItemsToIndex')->willReturn($fakeItems); + $this->queueMock + ->expects(self::once()) + ->method('getItemsToIndex') + ->willReturn($fakeItems); } /** diff --git a/Tests/Unit/Domain/Index/Queue/RecordMonitor/Helper/RootPageResolverTest.php b/Tests/Unit/Domain/Index/Queue/RecordMonitor/Helper/RootPageResolverTest.php index 25aaba12fc..ae50fdba63 100644 --- a/Tests/Unit/Domain/Index/Queue/RecordMonitor/Helper/RootPageResolverTest.php +++ b/Tests/Unit/Domain/Index/Queue/RecordMonitor/Helper/RootPageResolverTest.php @@ -19,6 +19,7 @@ use ApacheSolrForTypo3\Solr\Domain\Index\Queue\RecordMonitor\Helper\RootPageResolver; use ApacheSolrForTypo3\Solr\System\Cache\TwoLevelCache; use ApacheSolrForTypo3\Solr\Tests\Unit\UnitTest; +use InvalidArgumentException; use PHPUnit\Framework\MockObject\MockObject; /** @@ -125,8 +126,8 @@ public function getIsRootPageIdWithUnknownPageId() $this->rootPageResolver = $this->getMockBuilder(RootPageResolver::class) ->setConstructorArgs([$this->recordServiceMock, $this->cacheMock]) ->onlyMethods(['getPageRecordByPageId'])->getMock(); - $this->rootPageResolver->expects(self::once())->method('getPageRecordByPageId')->willReturn(null); - $this->expectException(\InvalidArgumentException::class); + $this->rootPageResolver->expects(self::once())->method('getPageRecordByPageId')->willReturn([]); + $this->expectException(InvalidArgumentException::class); $this->rootPageResolver->getIsRootPageId(42); } diff --git a/Tests/Unit/Domain/Index/Queue/UpdateHandler/DataUpdateHandlerTest.php b/Tests/Unit/Domain/Index/Queue/UpdateHandler/DataUpdateHandlerTest.php index e024ec36d9..6a6402362c 100644 --- a/Tests/Unit/Domain/Index/Queue/UpdateHandler/DataUpdateHandlerTest.php +++ b/Tests/Unit/Domain/Index/Queue/UpdateHandler/DataUpdateHandlerTest.php @@ -266,7 +266,7 @@ public function handleContentElementDeletionTriggersPageUpdate(): void self::DUMMY_PAGE_ID, 1641472388 ) - ->willReturn(true); + ->willReturn(1); $this->dataUpdateHandler->handleContentElementDeletion(123); } diff --git a/Tests/Unit/Domain/Search/ApacheSolrDocument/RepositoryTest.php b/Tests/Unit/Domain/Search/ApacheSolrDocument/RepositoryTest.php index 57d3070df6..4e0fc08aa4 100644 --- a/Tests/Unit/Domain/Search/ApacheSolrDocument/RepositoryTest.php +++ b/Tests/Unit/Domain/Search/ApacheSolrDocument/RepositoryTest.php @@ -26,7 +26,7 @@ use ApacheSolrForTypo3\Solr\System\Solr\ResponseAdapter; use ApacheSolrForTypo3\Solr\System\Solr\SolrConnection; use ApacheSolrForTypo3\Solr\Tests\Unit\UnitTest; -use InvalidArgumentException; +use TypeError; use TYPO3\CMS\Core\Utility\GeneralUtility; /** @@ -71,8 +71,7 @@ public function findOneByPageIdAndByLanguageIdReturnsFirstFoundDocument() */ public function findByPageIdAndByLanguageIdThrowsInvalidArgumentExceptionIfPageIdIsNotSet() { - $this->expectException(InvalidArgumentException::class); - $this->expectExceptionCode(1487332926); + $this->expectException(TypeError::class); /* @var $apacheSolrDocumentRepository Repository */ $apacheSolrDocumentRepository = GeneralUtility::makeInstance(Repository::class); $apacheSolrDocumentRepository->findByPageIdAndByLanguageId(null, 3); @@ -83,8 +82,7 @@ public function findByPageIdAndByLanguageIdThrowsInvalidArgumentExceptionIfPageI */ public function findByPageIdAndByLanguageIdThrowsInvalidArgumentExceptionIfLanguageIdIsNotInteger() { - $this->expectException(InvalidArgumentException::class); - $this->expectExceptionCode(1487335178); + $this->expectException(TypeError::class); /* @var $apacheSolrDocumentRepository Repository */ $apacheSolrDocumentRepository = GeneralUtility::makeInstance(Repository::class); $apacheSolrDocumentRepository->findByPageIdAndByLanguageId(1, 'Abc'); diff --git a/Tests/Unit/Domain/Search/Highlight/SiteHighlighterUrlModifierTest.php b/Tests/Unit/Domain/Search/Highlight/SiteHighlighterUrlModifierTest.php index 56d9f23017..b653d128d6 100644 --- a/Tests/Unit/Domain/Search/Highlight/SiteHighlighterUrlModifierTest.php +++ b/Tests/Unit/Domain/Search/Highlight/SiteHighlighterUrlModifierTest.php @@ -23,7 +23,7 @@ */ class SiteHighlighterUrlModifierTest extends UnitTest { - public function canModifyDataProvider() + public function canModifyDataProvider(): array { return [ 'nothingChangedWhenNoSearchWordPresent' => [ diff --git a/Tests/Unit/Domain/Search/Query/QueryBuilderTest.php b/Tests/Unit/Domain/Search/Query/QueryBuilderTest.php index e5369f7323..6793f6a30e 100644 --- a/Tests/Unit/Domain/Search/Query/QueryBuilderTest.php +++ b/Tests/Unit/Domain/Search/Query/QueryBuilderTest.php @@ -1,5 +1,7 @@ getInitializedTestSearchQuery(); - $queryParameters = $query->getQueryParameters(); + $queryParameters = $query->getParams(); foreach ($queryParameters as $queryParameter => $value) { self::assertTrue( !str_starts_with($queryParameter, 'group'), @@ -748,7 +750,7 @@ public function canAddFacetField() $fakeConfiguration = new TypoScriptConfiguration([]); $query = $this->getInitializedTestSearchQuery('test', $fakeConfiguration); - $queryParameters = $query->getQueryParameters(); + $queryParameters = $query->getParams(); self::assertArrayNotHasKey('facet.field', $queryParameters, 'facet.field query parameter was expected to be null after init.'); $faceting = Faceting::fromTypoScriptConfiguration($fakeConfiguration); @@ -1073,7 +1075,7 @@ public function canSetOperator() { $query = $this->getInitializedTestSearchQuery('test'); - $queryParameters = $query->getQueryParameters(); + $queryParameters = $query->getParams(); self::assertArrayNotHasKey('q.op', $queryParameters, 'The queryParameter q.op should be null because no operator was passed'); $this->builder->startFrom($query)->useOperator(Operator::getOr()); @@ -1118,7 +1120,7 @@ public function canSetOmitHeaders() { // check initial value $query = $this->getInitializedTestSearchQuery('test'); - $queryParameters = $query->getQueryParameters(); + $queryParameters = $query->getParams(); self::assertArrayNotHasKey('omitHeader', $queryParameters, 'The queryParameter omitHeader should be null because it was not'); $this->builder->startFrom($query)->useOmitHeader(); diff --git a/Tests/Unit/Domain/Search/ResultSet/Facets/RangeBased/DateRange/DateRangeTest.php b/Tests/Unit/Domain/Search/ResultSet/Facets/RangeBased/DateRange/DateRangeTest.php index d609d5a893..3b7911e28c 100644 --- a/Tests/Unit/Domain/Search/ResultSet/Facets/RangeBased/DateRange/DateRangeTest.php +++ b/Tests/Unit/Domain/Search/ResultSet/Facets/RangeBased/DateRange/DateRangeTest.php @@ -1,5 +1,7 @@ getDumbMock(DateRangeFacet::class), @@ -48,18 +52,19 @@ public function canHandleHalfOpenDateRanges() null, null, null, - null, - null, + '', + 0, [], - null + false ); try { $dateRangeCollectionKeyOpenStart = $dateRangeOpenStart->getCollectionKey(); $dateRangeCollectionKeyOpenEnd = $dateRangeOpenEnd->getCollectionKey(); - } catch (\Error $error) { + } catch (Error $error) { self::fail( - 'Can\'t handle half open date ranges. Please see: https://github.com/TYPO3-Solr/ext-solr/issues/2942 and error: ' . PHP_EOL . + 'Can\'t handle half open date ranges.' . PHP_EOL . + ' Please see: https://github.com/TYPO3-Solr/ext-solr/issues/2942 and error: ' . PHP_EOL . $error->getMessage() . ' in ' . $error->getFile() . ':' . $error->getLine() ); } diff --git a/Tests/Unit/Domain/Search/ResultSet/Facets/RangeBased/NumericRange/NumericRangeFacetParserTest.php b/Tests/Unit/Domain/Search/ResultSet/Facets/RangeBased/NumericRange/NumericRangeFacetParserTest.php index d354d1e727..7a54ba8407 100644 --- a/Tests/Unit/Domain/Search/ResultSet/Facets/RangeBased/NumericRange/NumericRangeFacetParserTest.php +++ b/Tests/Unit/Domain/Search/ResultSet/Facets/RangeBased/NumericRange/NumericRangeFacetParserTest.php @@ -1,5 +1,7 @@ [ @@ -57,18 +60,20 @@ protected function getPageIdFacetConfiguration($start = -100, $end = 100, $gap = * @param array $facetConfiguration * @param array $filters * @param string $facetName - * @return NumericRangeFacet + * @return AbstractFacet|NumericRangeFacet|null */ - protected function getNumericRangeFacet($facetConfiguration, $filters, $facetName) - { + protected function getNumericRangeFacet( + array $facetConfiguration, + array $filters, + string $facetName + ): ?AbstractFacet { $searchResultSet = $this->initializeSearchResultSetFromFakeResponse( 'fake_solr_response_with_numericRange_facet.json', $facetConfiguration, - $filters, - $facetName + $filters ); - /** @var $parser NumericRangeFacetParser */ + /* @var NumericRangeFacetParser $parser */ $parser = $this->getInitializedParser(NumericRangeFacetParser::class); return $parser->parse($searchResultSet, $facetName, $facetConfiguration[$facetName . '.']); } @@ -82,18 +87,26 @@ public function facetIsCreated() $facet = $this->getNumericRangeFacet($facetConfiguration, ['myPids:10-98'], 'myPids'); self::assertInstanceOf(NumericRangeFacet::class, $facet); - self::assertSame($facet->getConfiguration(), $facetConfiguration['myPids.'], 'Configuration was not passed to new facets'); + self::assertSame( + $facet->getConfiguration(), + $facetConfiguration['myPids.'], + 'Configuration was not passed to new facets' + ); self::assertTrue($facet->getIsUsed()); self::assertEquals('10-98', $facet->getRange()->getLabel()); self::assertEquals(25, $facet->getRange()->getDocumentCount()); - self::assertCount(4, $facet->getRange()->getRangeCounts(), 'We expected that there are four count items attached'); + self::assertCount( + 4, + $facet->getRange()->getRangeCounts(), + 'We expected that there are four count items attached' + ); - self::assertSame($facet->getRange()->getEndInResponse(), 100); - self::assertSame($facet->getRange()->getStartInResponse(), -100); - self::assertSame($facet->getRange()->getGap(), 2); - self::assertSame((int)$facet->getRange()->getStartRequested(), 10); - self::assertSame((int)$facet->getRange()->getEndRequested(), 98); + self::assertSame($facet->getRange()->getEndInResponse(), 100.0); + self::assertSame($facet->getRange()->getStartInResponse(), -100.0); + self::assertSame($facet->getRange()->getGap(), '2'); + self::assertSame($facet->getRange()->getStartRequested(), 10.0); + self::assertSame($facet->getRange()->getEndRequested(), 98.0); } /** @@ -104,10 +117,14 @@ public function facetIsCreated() * @param int $endRequested * @test */ - public function canParseActiveFacetValues($startRequested, $endRequested) + public function canParseActiveFacetValues(int $startRequested, int $endRequested): void { $facetConfiguration = $this->getPageIdFacetConfiguration(); - $facet = $this->getNumericRangeFacet($facetConfiguration, ['myPids:' . $startRequested . '-' . $endRequested], 'myPids'); + $facet = $this->getNumericRangeFacet( + $facetConfiguration, + ['myPids:' . $startRequested . '-' . $endRequested], + 'myPids' + ); self::assertSame((int)$facet->getRange()->getStartRequested(), $startRequested); self::assertSame((int)$facet->getRange()->getEndRequested(), $endRequested); @@ -118,7 +135,7 @@ public function canParseActiveFacetValues($startRequested, $endRequested) * * @return array */ - public function canParseActiveFacetValuesProvider() + public function canParseActiveFacetValuesProvider(): array { return [ [ diff --git a/Tests/Unit/Domain/Search/ResultSet/Facets/SortingExpressionTest.php b/Tests/Unit/Domain/Search/ResultSet/Facets/SortingExpressionTest.php index 4ebfdecec5..347e0724be 100644 --- a/Tests/Unit/Domain/Search/ResultSet/Facets/SortingExpressionTest.php +++ b/Tests/Unit/Domain/Search/ResultSet/Facets/SortingExpressionTest.php @@ -1,5 +1,7 @@ ['sorting' => 'alpha', 'direction' => '', 'isJson' => false, 'expectedResult' => 'index'], @@ -68,24 +70,24 @@ public function canBuildSortExpressionDataProvider() 'byCountJsonSortAsc' => ['sorting' => 'count', 'direction' => 'asc', 'isJson' => true, 'expectedResult' => 'count asc'], 'byCountJsonSortDesc' => ['sorting' => 'count', 'direction' => 'desc', 'isJson' => true, 'expectedResult' => 'count desc'], - 'byMetricJsonSortAsc' => ['sorting' => 'metrics_neweset', 'direction' => 'asc', 'isJson' => true, 'expectedResult' => 'metrics_neweset asc'], - 'byMetricJsonSortDesc' => ['sorting' => 'metrics_neweset', 'direction' => 'desc', 'isJson' => true, 'expectedResult' => 'metrics_neweset desc'], + 'byMetricJsonSortAsc' => ['sorting' => 'metrics_newest', 'direction' => 'asc', 'isJson' => true, 'expectedResult' => 'metrics_newest asc'], + 'byMetricJsonSortDesc' => ['sorting' => 'metrics_newest', 'direction' => 'desc', 'isJson' => true, 'expectedResult' => 'metrics_newest desc'], ]; } /** - * @param string $sorting + * @param string|int|bool $sorting * @param string $direction * @param bool $isJson * @param string $expectedResult * @dataProvider canBuildSortExpressionDataProvider * @test */ - public function canBuildSortExpression($sorting, $direction, $isJson, $expectedResult) + public function canBuildSortExpression($sorting, string $direction, bool $isJson, string $expectedResult) { $expression = new SortingExpression(); if ($isJson) { - $result = $expression->getForJsonFacet($sorting, $direction); + $result = $expression->getForJsonFacet((string)$sorting, $direction); } else { $result = $expression->getForFacet($sorting); } diff --git a/Tests/Unit/Domain/Search/ResultSet/Facets/TestPackage/TestFacet.php b/Tests/Unit/Domain/Search/ResultSet/Facets/TestPackage/TestFacet.php index 1a80b723ba..966786bd0f 100644 --- a/Tests/Unit/Domain/Search/ResultSet/Facets/TestPackage/TestFacet.php +++ b/Tests/Unit/Domain/Search/ResultSet/Facets/TestPackage/TestFacet.php @@ -7,13 +7,12 @@ class TestFacet extends AbstractFacet { - /** * The implementation of this method should return a "flatten" collection of all items. * * @return AbstractFacetItemCollection */ - public function getAllFacetItems() + public function getAllFacetItems(): AbstractFacetItemCollection { // TODO: Implement getAllFacetItems() method. } diff --git a/Tests/Unit/Domain/Search/ResultSet/Facets/TestPackage/TestPackage.php b/Tests/Unit/Domain/Search/ResultSet/Facets/TestPackage/TestPackage.php index f1e4fe598a..1db612abc9 100644 --- a/Tests/Unit/Domain/Search/ResultSet/Facets/TestPackage/TestPackage.php +++ b/Tests/Unit/Domain/Search/ResultSet/Facets/TestPackage/TestPackage.php @@ -1,16 +1,30 @@ getDumbMock(SearchResultSet::class); $fakeResultSet->expects(self::any())->method('getUsedSearchRequest')->willReturn($requestMock); - $this->configurationMock->expects(self::once())->method('getSearchGrouping')->willReturn(true); + $this->configurationMock->expects(self::once())->method('getIsSearchGroupingEnabled')->willReturn(true); self::assertFalse($this->parser->canParse($fakeResultSet)); } @@ -115,7 +115,7 @@ public function canParseReturnsTrueWhenGroupingIsDisabled() $fakeResultSet = $this->getDumbMock(SearchResultSet::class); $fakeResultSet->expects(self::any())->method('getUsedSearchRequest')->willReturn($requestMock); - $this->configurationMock->expects(self::once())->method('getSearchGrouping')->willReturn(false); + $this->configurationMock->expects(self::once())->method('getIsSearchGroupingEnabled')->willReturn(false); self::assertTrue($this->parser->canParse($fakeResultSet)); } } diff --git a/Tests/Unit/Domain/Search/ResultSet/Result/Parser/TestResultParser.php b/Tests/Unit/Domain/Search/ResultSet/Result/Parser/TestResultParser.php index f54e7ffcef..1bc268d913 100644 --- a/Tests/Unit/Domain/Search/ResultSet/Result/Parser/TestResultParser.php +++ b/Tests/Unit/Domain/Search/ResultSet/Result/Parser/TestResultParser.php @@ -1,5 +1,7 @@ 4711, + 'id' => '4711', 'title' => 'The title', 'score' => 0.55, 'content' => 'foobar', @@ -50,7 +52,11 @@ protected function setUp(): void */ public function canGetId() { - self::assertSame(4711, $this->searchResult->getId(), 'Could not get id from searchResult'); + self::assertSame( + '4711', + $this->searchResult->getId(), + 'Could not get id from searchResult' + ); } /** @@ -58,7 +64,11 @@ public function canGetId() */ public function canGetScore() { - self::assertSame(0.55, $this->searchResult->getScore(), 'Could not get score from searchResult'); + self::assertSame( + 0.55, + $this->searchResult->getScore(), + 'Could not get score from searchResult' + ); } /** @@ -66,7 +76,11 @@ public function canGetScore() */ public function canGetContent() { - self::assertSame('foobar', $this->searchResult->getContent(), 'Could not get content from searchResult'); + self::assertSame( + 'foobar', + $this->searchResult->getContent(), + 'Could not get content from searchResult' + ); } /** @@ -74,7 +88,11 @@ public function canGetContent() */ public function canGetType() { - self::assertSame('pages', $this->searchResult->getType(), 'Could not get type from searchResult'); + self::assertSame( + 'pages', + $this->searchResult->getType(), + 'Could not get type from searchResult' + ); } /** @@ -82,7 +100,11 @@ public function canGetType() */ public function canGetTitle() { - self::assertSame('The title', $this->searchResult->getTitle(), 'Could not get title from searchResult'); + self::assertSame( + 'The title', + $this->searchResult->getTitle(), + 'Could not get title from searchResult' + ); } /** @@ -90,7 +112,11 @@ public function canGetTitle() */ public function canGetUrl() { - self::assertSame('://mytestdomain.com/test', $this->searchResult->getUrl(), 'Could not get url from searchResult'); + self::assertSame( + '://mytestdomain.com/test', + $this->searchResult->getUrl(), + 'Could not get url from searchResult' + ); } /** @@ -98,7 +124,10 @@ public function canGetUrl() */ public function canGetIsElevated() { - self::assertTrue($this->searchResult->getIsElevated(), 'Could not get isElevated from searchResult'); + self::assertTrue( + $this->searchResult->getIsElevated(), + 'Could not get isElevated from searchResult' + ); } /** @@ -106,6 +135,10 @@ public function canGetIsElevated() */ public function getOnUnexistingFieldReturnsNull() { - self::assertNull($this->searchResult->getUnexistingField(), 'Calling getter for unexisting field does not return null'); + /** @noinspection PhpUndefinedMethodInspection */ + self::assertNull( + $this->searchResult->getUnexistingField(), + 'Calling getter for unexisting field does not return null' + ); } } diff --git a/Tests/Unit/Domain/Search/ResultSet/SearchResultSetServiceTest.php b/Tests/Unit/Domain/Search/ResultSet/SearchResultSetServiceTest.php index dc71d78a8f..e61ff43761 100644 --- a/Tests/Unit/Domain/Search/ResultSet/SearchResultSetServiceTest.php +++ b/Tests/Unit/Domain/Search/ResultSet/SearchResultSetServiceTest.php @@ -85,7 +85,7 @@ protected function setUp(): void public function searchIsNotTriggeredWhenEmptySearchDisabledAndEmptyQueryWasPassed() { $searchRequest = new SearchRequest(); - $searchRequest->setRawQueryString(null); + $searchRequest->setRawQueryString(''); $this->assertAllInitialSearchesAreDisabled(); $this->objectManagerMock->expects(self::once())->method('get')->with(SearchResultSet::class)->willReturn(new SearchResultSet()); $resultSet = $this->searchResultSetService->search($searchRequest); diff --git a/Tests/Unit/Domain/Search/ResultSet/SearchResultSetTest.php b/Tests/Unit/Domain/Search/ResultSet/SearchResultSetTest.php index 962524e152..63e26749c2 100644 --- a/Tests/Unit/Domain/Search/ResultSet/SearchResultSetTest.php +++ b/Tests/Unit/Domain/Search/ResultSet/SearchResultSetTest.php @@ -1,5 +1,7 @@ getSearchResults() as $result) { $result->type = strtoupper($result->type); diff --git a/Tests/Unit/Domain/Search/Suggest/SuggestServiceTest.php b/Tests/Unit/Domain/Search/Suggest/SuggestServiceTest.php index 88b0b9dfe5..a3f667b0af 100644 --- a/Tests/Unit/Domain/Search/Suggest/SuggestServiceTest.php +++ b/Tests/Unit/Domain/Search/Suggest/SuggestServiceTest.php @@ -1,5 +1,7 @@ getDumbMock(SolrConnection::class)) extends Search implements SingletonInterface { public static $suggestServiceTest; - public function search(Query $query, $offset = 0, $limit = 10) + public function search(Query $query, $offset = 0, $limit = 10): ?ResponseAdapter { return self::$suggestServiceTest->getMockBuilder(ResponseAdapter::class) ->onlyMethods([])->disableOriginalConstructor()->getMock(); @@ -201,8 +203,8 @@ public function canGetSuggestionsWithTopResults() $fakeRequest->expects(self::any())->method('getCopyForSubRequest')->willReturn($fakeRequest); $this->suggestService->expects(self::once())->method('getSolrSuggestions')->willReturn([ - 'type', - 'typo', + 'type' => 25, + 'typo' => 5, ]); $fakeTopResults = $this->getDumbMock(SearchResultSet::class); diff --git a/Tests/Unit/Domain/Variants/CustomIdModifier.php b/Tests/Unit/Domain/Variants/CustomIdModifier.php index 33b2f36974..adda3d8f54 100644 --- a/Tests/Unit/Domain/Variants/CustomIdModifier.php +++ b/Tests/Unit/Domain/Variants/CustomIdModifier.php @@ -1,5 +1,7 @@ [['item_type' => 'pages', 'indexed' => 3, 'changed' => '4'], Item::STATE_PENDING], - 'indexed item' => [['item_type' => 'pages', 'indexed' => 5, 'changed' => '4'], Item::STATE_INDEXED], - 'blocked item' => [['item_type' => 'pages', 'indexed' => 5, 'changed' => '4', 'errors' => 'Something bad happened'], Item::STATE_BLOCKED], + 'pending item' => [['item_type' => 'pages', 'indexed' => 3, 'changed' => 4], Item::STATE_PENDING], + 'indexed item' => [['item_type' => 'pages', 'indexed' => 5, 'changed' => 4], Item::STATE_INDEXED], + 'blocked item' => [['item_type' => 'pages', 'indexed' => 5, 'changed' => 4, 'errors' => 'Something bad happened'], Item::STATE_BLOCKED], ]; } diff --git a/Tests/Unit/IndexQueue/PageIndexerResponseTest.php b/Tests/Unit/IndexQueue/PageIndexerResponseTest.php index 0c2a44d115..c830843715 100644 --- a/Tests/Unit/IndexQueue/PageIndexerResponseTest.php +++ b/Tests/Unit/IndexQueue/PageIndexerResponseTest.php @@ -1,5 +1,7 @@ getDumbMock(Query::class); - $queryBuilderMock = $this->getDumbMock(QueryBuilder::class); + $queryBuilderMock = $this->getMockBuilder(QueryBuilder::class) + ->disableProxyingToOriginalMethods() + ->getMock(); $queryBuilderMock->expects(self::once())->method('startFrom')->willReturn($queryBuilderMock); $queryBuilderMock->expects(self::once())->method('useElevationFromTypoScript')->willReturn($queryBuilderMock); + $queryBuilderMock->expects(self::once())->method('getQuery')->willReturn($query); $modifier = new Elevation($queryBuilderMock); $modifier->modifyQuery($query); diff --git a/Tests/Unit/Query/Modifier/FacetingTest.php b/Tests/Unit/Query/Modifier/FacetingTest.php index 051c6c005a..526bb4a565 100644 --- a/Tests/Unit/Query/Modifier/FacetingTest.php +++ b/Tests/Unit/Query/Modifier/FacetingTest.php @@ -1,5 +1,7 @@ getMockBuilder(ObjectManager::class)->disableOriginalConstructor()->onlyMethods(['get'])->getMock(); - $fakeObjectManager->expects(self::any())->method('get')->willReturnCallback(function ($className) { - return new $className(); - }); + private function getQueryParametersFromExecutedFacetingModifier( + TypoScriptConfiguration $fakeConfiguration, + SearchRequest $fakeSearchRequest + ): array { + $fakeObjectManager = $this->getMockBuilder(ObjectManager::class) + ->disableOriginalConstructor() + ->onlyMethods(['get']) + ->getMock(); + $fakeObjectManager->expects(self::any()) + ->method('get') + ->willReturnCallback(function ($className) { + return new $className(); + }); $facetRegistry = new FacetRegistry(); // @extensionScannerIgnoreLine $facetRegistry->injectObjectManager($fakeObjectManager); + /* @var SolrLogManager|MockObject $solrLogManagerMock */ $solrLogManagerMock = $this->getDumbMock(SolrLogManager::class); - /** @var $query \ApacheSolrForTypo3\Solr\Domain\Search\Query\Query */ + /* @var Query $query */ $queryBuilder = new QueryBuilder($fakeConfiguration, $solrLogManagerMock); $query = $queryBuilder->buildSearchQuery('test'); - /** @var $facetModifier \ApacheSolrForTypo3\Solr\Query\Modifier\Faceting */ + /* @var Faceting $facetModifier */ $facetModifier = GeneralUtility::makeInstance(Faceting::class, $facetRegistry); $facetModifier->setSearchRequest($fakeSearchRequest); - $facetModifier->modifyQuery($query); + /** @noinspection PhpUnhandledExceptionInspection */ + $query = $facetModifier->modifyQuery($query); $requestBuilder = new RequestBuilder(); @@ -78,6 +98,10 @@ private function getQueryParametersFromExecutedFacetingModifier($fakeConfigurati * } * * @test + * + * @throws InvalidFacetPackageException + * @throws InvalidQueryBuilderException + * @throws InvalidUrlDecoderException */ public function testCanAddASimpleFacet() { @@ -90,6 +114,7 @@ public function testCanAddASimpleFacet() ]; $fakeConfiguration = new TypoScriptConfiguration($fakeConfigurationArray); + /* @var SearchRequest|MockObject $fakeRequest */ $fakeRequest = $this->getDumbMock(SearchRequest::class); $fakeRequest->expects(self::any())->method('getContextTypoScriptConfiguration')->willReturn($fakeConfiguration); $fakeRequest->expects(self::once())->method('getArguments')->willReturn([]); @@ -112,6 +137,10 @@ public function testCanAddASimpleFacet() * } * * @test + * + * @throws InvalidFacetPackageException + * @throws InvalidQueryBuilderException + * @throws InvalidUrlDecoderException */ public function testCanAddSortByIndexArgument() { @@ -124,6 +153,8 @@ public function testCanAddSortByIndexArgument() ], ]; $fakeConfiguration = new TypoScriptConfiguration($fakeConfigurationArray); + + /* @var SearchRequest|MockObject $fakeRequest */ $fakeRequest = $this->getDumbMock(SearchRequest::class); $fakeRequest->expects(self::any())->method('getContextTypoScriptConfiguration')->willReturn($fakeConfiguration); $fakeRequest->expects(self::once())->method('getArguments')->willReturn([]); @@ -144,6 +175,10 @@ public function testCanAddSortByIndexArgument() * } * * @test + * + * @throws InvalidFacetPackageException + * @throws InvalidQueryBuilderException + * @throws InvalidUrlDecoderException */ public function testCanAddSortByCountArgument() { @@ -156,6 +191,8 @@ public function testCanAddSortByCountArgument() ], ]; $fakeConfiguration = new TypoScriptConfiguration($fakeConfigurationArray); + + /* @var SearchRequest|MockObject $fakeRequest */ $fakeRequest = $this->getDumbMock(SearchRequest::class); $fakeRequest->expects(self::any())->method('getContextTypoScriptConfiguration')->willReturn($fakeConfiguration); $fakeRequest->expects(self::once())->method('getArguments')->willReturn([]); @@ -183,6 +220,10 @@ public function testCanAddSortByCountArgument() * } * * @test + * + * @throws InvalidFacetPackageException + * @throws InvalidQueryBuilderException + * @throws InvalidUrlDecoderException */ public function testCanHandleKeepAllFacetsOnSelectionOnAllFacetWhenGloballyConfigured() { @@ -199,6 +240,7 @@ public function testCanHandleKeepAllFacetsOnSelectionOnAllFacetWhenGloballyConfi ]; $fakeConfiguration = new TypoScriptConfiguration($fakeConfigurationArray); + /* @var SearchRequest|MockObject $fakeRequest */ $fakeRequest = $this->getDumbMock(SearchRequest::class); $fakeRequest->expects(self::once())->method('getArguments')->willReturn([]); $fakeRequest->expects(self::any())->method('getContextTypoScriptConfiguration')->willReturn($fakeConfiguration); @@ -206,7 +248,7 @@ public function testCanHandleKeepAllFacetsOnSelectionOnAllFacetWhenGloballyConfi $queryParameter = $this->getQueryParametersFromExecutedFacetingModifier($fakeConfiguration, $fakeRequest); self::assertStringContainsString('true', $queryParameter['facet'], 'Query string did not contain expected snipped'); - $jsonData = \json_decode($queryParameter['json.facet']); + $jsonData = json_decode($queryParameter['json.facet']); self::assertEquals('type,color', $jsonData->type->domain->excludeTags, 'Query string did not contain expected snipped'); self::assertEquals('type,color', $jsonData->color->domain->excludeTags, 'Query string did not contain expected snipped'); } @@ -226,6 +268,10 @@ public function testCanHandleKeepAllFacetsOnSelectionOnAllFacetWhenGloballyConfi * } * * @test + * + * @throws InvalidFacetPackageException + * @throws InvalidQueryBuilderException + * @throws InvalidUrlDecoderException */ public function testExcludeTagsAreEmptyWhenKeepAllFacetsOnSelectionIsNotSet() { @@ -241,6 +287,7 @@ public function testExcludeTagsAreEmptyWhenKeepAllFacetsOnSelectionIsNotSet() ]; $fakeConfiguration = new TypoScriptConfiguration($fakeConfigurationArray); + /* @var SearchRequest|MockObject $fakeRequest */ $fakeRequest = $this->getDumbMock(SearchRequest::class); $fakeRequest->expects(self::once())->method('getArguments')->willReturn([]); $fakeRequest->expects(self::any())->method('getContextTypoScriptConfiguration')->willReturn($fakeConfiguration); @@ -248,7 +295,7 @@ public function testExcludeTagsAreEmptyWhenKeepAllFacetsOnSelectionIsNotSet() $queryParameter = $this->getQueryParametersFromExecutedFacetingModifier($fakeConfiguration, $fakeRequest); self::assertStringContainsString('true', $queryParameter['facet'], 'Query string did not contain expected snipped'); - $jsonData = \json_decode($queryParameter['json.facet']); + $jsonData = json_decode($queryParameter['json.facet']); self::assertEmpty(($jsonData->type->domain->excludeTags ?? ''), 'Query string did not contain expected snipped'); self::assertEmpty(($jsonData->color->domain->excludeTags ?? ''), 'Query string did not contain expected snipped'); } @@ -270,6 +317,10 @@ public function testExcludeTagsAreEmptyWhenKeepAllFacetsOnSelectionIsNotSet() * } * * @test + * + * @throws InvalidFacetPackageException + * @throws InvalidQueryBuilderException + * @throws InvalidUrlDecoderException */ public function testCanHandleKeepAllOptionsOnSelectionForASingleFacet() { @@ -286,12 +337,13 @@ public function testCanHandleKeepAllOptionsOnSelectionForASingleFacet() ]; $fakeConfiguration = new TypoScriptConfiguration($fakeConfigurationArray); + /* @var SearchRequest|MockObject $fakeRequest */ $fakeRequest = $this->getDumbMock(SearchRequest::class); $fakeRequest->expects(self::once())->method('getArguments')->willReturn([]); $fakeRequest->expects(self::any())->method('getContextTypoScriptConfiguration')->willReturn($fakeConfiguration); $queryParameter = $this->getQueryParametersFromExecutedFacetingModifier($fakeConfiguration, $fakeRequest); - $jsonData = \json_decode($queryParameter['json.facet']); + $jsonData = json_decode($queryParameter['json.facet']); self::assertStringContainsString('true', $queryParameter['facet'], 'Query string did not contain expected snipped'); self::assertEquals('type', $jsonData->type->domain->excludeTags, 'Query string did not contain expected snipped'); self::assertEquals('color', $jsonData->color->field, 'Query string did not contain expected snipped'); @@ -299,6 +351,10 @@ public function testCanHandleKeepAllOptionsOnSelectionForASingleFacet() /** * @test + * + * @throws InvalidFacetPackageException + * @throws InvalidQueryBuilderException + * @throws InvalidUrlDecoderException */ public function testCanHandleCombinationOfKeepAllFacetsOnSelectionAndKeepAllOptionsOnSelection() { @@ -318,6 +374,7 @@ public function testCanHandleCombinationOfKeepAllFacetsOnSelectionAndKeepAllOpti $fakeArguments = ['filter' => [urlencode('color:red'), urlencode('type:product')]]; + /* @var SearchRequest|MockObject $fakeRequest */ $fakeRequest = $this->getDumbMock(SearchRequest::class); $fakeRequest->expects(self::once())->method('getArguments')->willReturn($fakeArguments); $fakeRequest->expects(self::any())->method('getContextTypoScriptConfiguration')->willReturn($fakeConfiguration); @@ -325,7 +382,7 @@ public function testCanHandleCombinationOfKeepAllFacetsOnSelectionAndKeepAllOpti $queryParameter = $this->getQueryParametersFromExecutedFacetingModifier($fakeConfiguration, $fakeRequest); self::assertStringContainsString('true', $queryParameter['facet'], 'Query string did not contain expected snipped'); - $jsonData = \json_decode($queryParameter['json.facet']); + $jsonData = json_decode($queryParameter['json.facet']); self::assertEquals('type,color', $jsonData->type->domain->excludeTags, 'Query string did not contain expected snipped'); self::assertEquals('type', $jsonData->type->field, 'Did not build json field properly'); @@ -336,6 +393,10 @@ public function testCanHandleCombinationOfKeepAllFacetsOnSelectionAndKeepAllOpti /** * @test + * + * @throws InvalidFacetPackageException + * @throws InvalidQueryBuilderException + * @throws InvalidUrlDecoderException */ public function testCanHandleCombinationOfKeepAllFacetsOnSelectionAndKeepAllOptionsOnSelectionAndCountAllFacetsForSelection() { @@ -357,6 +418,7 @@ public function testCanHandleCombinationOfKeepAllFacetsOnSelectionAndKeepAllOpti $fakeArguments = ['filter' => [urlencode('color:red'), urlencode('type:product')]]; + /* @var SearchRequest|MockObject $fakeRequest */ $fakeRequest = $this->getDumbMock(SearchRequest::class); $fakeRequest->expects(self::once())->method('getArguments')->willReturn($fakeArguments); $fakeRequest->expects(self::any())->method('getContextTypoScriptConfiguration')->willReturn($fakeConfiguration); @@ -364,7 +426,7 @@ public function testCanHandleCombinationOfKeepAllFacetsOnSelectionAndKeepAllOpti $queryParameter = $this->getQueryParametersFromExecutedFacetingModifier($fakeConfiguration, $fakeRequest); self::assertStringContainsString('true', $queryParameter['facet'], 'Query string did not contain expected snipped'); - $jsonData = \json_decode($queryParameter['json.facet']); + $jsonData = json_decode($queryParameter['json.facet']); self::assertEquals('type', $jsonData->type->domain->excludeTags, 'Query string did not contain expected snipped'); self::assertEquals('type', $jsonData->type->field, 'Did not build json field properly'); @@ -375,6 +437,10 @@ public function testCanHandleCombinationOfKeepAllFacetsOnSelectionAndKeepAllOpti /** * @test + * + * @throws InvalidFacetPackageException + * @throws InvalidQueryBuilderException + * @throws InvalidUrlDecoderException */ public function testCanAddQueryFilters() { @@ -392,6 +458,8 @@ public function testCanAddQueryFilters() $fakeConfiguration = new TypoScriptConfiguration($fakeConfigurationArray); $fakeArguments = ['filter' => [urlencode('color:red'), urlencode('type:product')]]; + + /* @var SearchRequest|MockObject $fakeRequest */ $fakeRequest = $this->getDumbMock(SearchRequest::class); $fakeRequest->expects(self::once())->method('getArguments')->willReturn($fakeArguments); $fakeRequest->expects(self::any())->method('getContextTypoScriptConfiguration')->willReturn($fakeConfiguration); @@ -406,6 +474,10 @@ public function testCanAddQueryFilters() /** * @test + * + * @throws InvalidFacetPackageException + * @throws InvalidQueryBuilderException + * @throws InvalidUrlDecoderException */ public function testCanAddQueryFiltersWithKeepAllOptionsOnSelectionFacet() { @@ -423,6 +495,8 @@ public function testCanAddQueryFiltersWithKeepAllOptionsOnSelectionFacet() $fakeConfiguration = new TypoScriptConfiguration($fakeConfigurationArray); $fakeArguments = ['filter' => [urlencode('color:red'), urlencode('type:product')]]; + + /* @var SearchRequest|MockObject $fakeRequest */ $fakeRequest = $this->getDumbMock(SearchRequest::class); $fakeRequest->expects(self::once())->method('getArguments')->willReturn($fakeArguments); $fakeRequest->expects(self::any())->method('getContextTypoScriptConfiguration')->willReturn($fakeConfiguration); @@ -437,6 +511,10 @@ public function testCanAddQueryFiltersWithKeepAllOptionsOnSelectionFacet() /** * @test + * + * @throws InvalidFacetPackageException + * @throws InvalidQueryBuilderException + * @throws InvalidUrlDecoderException */ public function testCanAddQueryFiltersWithGlobalKeepAllOptionsOnSelection() { @@ -455,6 +533,7 @@ public function testCanAddQueryFiltersWithGlobalKeepAllOptionsOnSelection() $fakeArguments = ['filter' => [urlencode('color:red'), urlencode('type:product')]]; + /* @var SearchRequest|MockObject $fakeRequest */ $fakeRequest = $this->getDumbMock(SearchRequest::class); $fakeRequest->expects(self::once())->method('getArguments')->willReturn($fakeArguments); $fakeRequest->expects(self::any())->method('getContextTypoScriptConfiguration')->willReturn($fakeConfiguration); @@ -469,6 +548,10 @@ public function testCanAddQueryFiltersWithGlobalKeepAllOptionsOnSelection() /** * @test + * + * @throws InvalidFacetPackageException + * @throws InvalidQueryBuilderException + * @throws InvalidUrlDecoderException */ public function testCanAddExcludeTagWithAdditionalExcludeTagConfiguration() { @@ -488,6 +571,7 @@ public function testCanAddExcludeTagWithAdditionalExcludeTagConfiguration() $fakeArguments = ['filter' => [urlencode('type:product')]]; + /* @var SearchRequest|MockObject $fakeRequest */ $fakeRequest = $this->getDumbMock(SearchRequest::class); $fakeRequest->expects(self::once())->method('getArguments')->willReturn($fakeArguments); $fakeRequest->expects(self::any())->method('getContextTypoScriptConfiguration')->willReturn($fakeConfiguration); @@ -495,13 +579,17 @@ public function testCanAddExcludeTagWithAdditionalExcludeTagConfiguration() $queryParameter = $this->getQueryParametersFromExecutedFacetingModifier($fakeConfiguration, $fakeRequest); self::assertStringContainsString('true', $queryParameter['facet'], 'Query string did not contain expected snipped'); - $jsonData = \json_decode($queryParameter['json.facet']); + $jsonData = json_decode($queryParameter['json.facet']); self::assertEquals('type,color', $jsonData->type->domain->excludeTags, 'Query string did not contain expected snipped'); self::assertEquals('{!tag=type}(type:"product")', $queryParameter['fq'], 'Did not build filter query from color'); } /** * @test + * + * @throws InvalidFacetPackageException + * @throws InvalidQueryBuilderException + * @throws InvalidUrlDecoderException */ public function testCanAddQueryFiltersContainingPlusSign() { @@ -529,7 +617,7 @@ public function testCanAddQueryFiltersContainingPlusSign() ]; $fakeConfiguration = new TypoScriptConfiguration($fakeConfigurationArray); - /* @var SearchRequest $fakeRequest */ + /* @var SearchRequest|MockObject $fakeRequest */ $fakeRequest = $this->getDumbMock(SearchRequest::class); $fakeRequest->expects(self::once())->method('getArguments')->willReturn($fakeArguments); $fakeRequest->expects(self::any())->method('getContextTypoScriptConfiguration')->willReturn($fakeConfiguration); @@ -557,6 +645,8 @@ public function callGetFiltersByFacetName(array $resultParameters, array $allFac $typoScriptConfigurationMock->expects(self::once()) ->method('getSearchFacetingUrlParameterStyle') ->willReturn(UrlFacetContainer::PARAMETER_STYLE_ASSOC); + + /* @var SearchRequest|MockObject $searchRequestMock */ $searchRequestMock = $this->getDumbMock(SearchRequest::class); $searchRequestMock->expects(self::once()) ->method('getContextTypoScriptConfiguration') diff --git a/Tests/Unit/SearchTest.php b/Tests/Unit/SearchTest.php index 7829cb41e4..932308f172 100644 --- a/Tests/Unit/SearchTest.php +++ b/Tests/Unit/SearchTest.php @@ -1,5 +1,7 @@ solrReadServiceMock = $this->getDumbMock(SolrReadService::class); +// $this->solrReadServiceMock = $this->getDumbMock(SolrReadService::class); + $this->solrReadServiceMock = $this->getMockBuilder(SolrReadService::class) + ->disableOriginalConstructor() + ->onlyMethods(['search']) + ->getMock(); + $this->solrConnectionMock = $this->getDumbMock(SolrConnection::class); $this->solrConnectionMock->expects(self::any())->method('getReadService')->willReturn($this->solrReadServiceMock); $this->search = new Search($this->solrConnectionMock); @@ -57,6 +65,7 @@ public function canPassLimit() $this->solrReadServiceMock->expects(self::once())->method('search')->willReturnCallback( function ($query) use ($limit) { $this->assertSame($limit, $query->getRows(), 'Unexpected limit was passed'); + return $this->getDumbMock(ResponseAdapter::class); } ); @@ -75,6 +84,7 @@ public function canKeepLimitWhenNullWasPassedAsLimit() $this->solrReadServiceMock->expects(self::once())->method('search')->willReturnCallback( function ($query) use ($limit) { $this->assertSame($limit, $query->getRows(), 'Unexpected limit was passed'); + return $this->getDumbMock(ResponseAdapter::class); } ); diff --git a/Tests/Unit/System/Configuration/TypoScriptConfigurationTest.php b/Tests/Unit/System/Configuration/TypoScriptConfigurationTest.php index 9124f7d603..0d93fd5d6b 100644 --- a/Tests/Unit/System/Configuration/TypoScriptConfigurationTest.php +++ b/Tests/Unit/System/Configuration/TypoScriptConfigurationTest.php @@ -809,7 +809,7 @@ public function canGetSearchGroupingWhenDisabled() $configuration = new TypoScriptConfiguration($fakeConfigurationArray); - self::assertFalse($configuration->getSearchGrouping(), 'Expected grouping to be disabled'); + self::assertFalse($configuration->getIsSearchGroupingEnabled(), 'Expected grouping to be disabled'); } /** diff --git a/Tests/Unit/System/ContentObject/ContentObjectServiceTest.php b/Tests/Unit/System/ContentObject/ContentObjectServiceTest.php index 59e0f4afeb..dfb4dd2939 100644 --- a/Tests/Unit/System/ContentObject/ContentObjectServiceTest.php +++ b/Tests/Unit/System/ContentObject/ContentObjectServiceTest.php @@ -1,5 +1,7 @@ contentObjectRendererMock = $this->getDumbMock(ContentObjectRenderer::class); + $this->contentObjectRendererMock = $this->getMockBuilder(ContentObjectRenderer::class) + ->onlyMethods(['cObjGetSingle']) + ->getMock(); $this->contentObjectService = new ContentObjectService($this->contentObjectRendererMock); parent::setUp(); } @@ -54,7 +59,11 @@ public function canRenderSingleContentObjectByArrayAndKey() 'field.' => ['value' => 'test'], ]; - $this->contentObjectRendererMock->expects(self::once())->method('cObjGetSingle')->with('TEXT', ['value' => 'test']); + $this->contentObjectRendererMock + ->expects(self::once()) + ->method('cObjGetSingle') + ->with('TEXT', ['value' => 'test']) + ->willReturn('test'); $this->contentObjectService->renderSingleContentObjectByArrayAndKey($fakeStdWrapConfiguration, 'field'); } diff --git a/Tests/Unit/System/Session/FrontendUserSessionTest.php b/Tests/Unit/System/Session/FrontendUserSessionTest.php index 94e57fed86..4131c4fb30 100644 --- a/Tests/Unit/System/Session/FrontendUserSessionTest.php +++ b/Tests/Unit/System/Session/FrontendUserSessionTest.php @@ -35,7 +35,7 @@ class FrontendSessionTest extends UnitTest /** * @var FrontendUserSession */ - protected $session; + protected FrontendUserSession $session; protected function setUp(): void { diff --git a/Tests/Unit/System/Solr/Service/SolrAdminServiceTest.php b/Tests/Unit/System/Solr/Service/SolrAdminServiceTest.php index 834dff9ad8..1923a5f9e8 100644 --- a/Tests/Unit/System/Solr/Service/SolrAdminServiceTest.php +++ b/Tests/Unit/System/Solr/Service/SolrAdminServiceTest.php @@ -55,7 +55,7 @@ protected function setUp(): void $this->endpointMock->expects(self::any())->method('getCoreBaseUri')->willReturn('http://localhost:8983/solr/core_en/'); $this->clientMock = $this->getDumbMock(Client::class); - $this->clientMock->expects(self::any())->method('getEndpoints')->willReturn([$this->endpointMock]); + $this->clientMock->expects(self::any())->method('getEndpoint')->willReturn($this->endpointMock); $this->adminService = $this->getMockBuilder(SolrAdminService::class)->setConstructorArgs([$this->clientMock])->onlyMethods(['_sendRawGet'])->getMock(); parent::setUp(); } @@ -64,7 +64,7 @@ protected function setUp(): void */ public function getLukeMetaDataIsSendingRequestToExpectedUrl() { - $fakedLukeResponse = []; + $fakedLukeResponse = $this->getDumbMock(ResponseAdapter::class); $this->assertGetRequestIsTriggered('http://localhost:8983/solr/core_en/admin/luke?numTerms=50&wt=json&fl=%2A', $fakedLukeResponse); $result = $this->adminService->getLukeMetaData(50); @@ -125,7 +125,7 @@ public function canGetSolrConfigNameFromFakedXmlResponse() * @param string $url * @param mixed $fakeResponse */ - protected function assertGetRequestIsTriggered($url, $fakeResponse) + protected function assertGetRequestIsTriggered(string $url, $fakeResponse) { $this->adminService->expects(self::once())->method('_sendRawGet')->with($url)->willReturn($fakeResponse); } diff --git a/Tests/Unit/System/Solr/Service/SolrReadServiceTest.php b/Tests/Unit/System/Solr/Service/SolrReadServiceTest.php index f4aeb9df98..e236cb2a53 100644 --- a/Tests/Unit/System/Solr/Service/SolrReadServiceTest.php +++ b/Tests/Unit/System/Solr/Service/SolrReadServiceTest.php @@ -55,7 +55,7 @@ class SolrReadServiceTest extends UnitTest /** * @var SolrReadService */ - protected $service; + protected SolrReadService $service; protected function setUp(): void { diff --git a/Tests/Unit/ViewHelpers/Document/HighlightingResultViewHelperTest.php b/Tests/Unit/ViewHelpers/Document/HighlightingResultViewHelperTest.php index 42076da27f..0a1efa87c5 100644 --- a/Tests/Unit/ViewHelpers/Document/HighlightingResultViewHelperTest.php +++ b/Tests/Unit/ViewHelpers/Document/HighlightingResultViewHelperTest.php @@ -1,5 +1,7 @@ getDumbMock(RenderingContextInterface::class); $configurationMock = $this->getDumbMock(TypoScriptConfiguration::class); @@ -75,8 +79,8 @@ public function canRenderCreateHighlightSnipped(array $input, $expectedOutput, $ $configurationMock ); - $fakeHighlightedContent = new \stdClass(); - $fakeHighlightedContent->foo = new \stdClass(); + $fakeHighlightedContent = new stdClass(); + $fakeHighlightedContent->foo = new stdClass(); $fakeHighlightedContent->foo->content = $input; $searchMock = $this->getDumbMock(Search::class); diff --git a/Tests/Unit/ViewHelpers/SearchFormViewHelperTest.php b/Tests/Unit/ViewHelpers/SearchFormViewHelperTest.php index 4cb3c053f7..98bb963222 100644 --- a/Tests/Unit/ViewHelpers/SearchFormViewHelperTest.php +++ b/Tests/Unit/ViewHelpers/SearchFormViewHelperTest.php @@ -49,7 +49,14 @@ protected function setUp(): void $controllerContextMock = $this->getDumbMock(ControllerContext::class); $controllerContextMock->expects(self::once())->method('getUriBuilder')->willReturn($this->uriBuilderMock); - $this->viewHelper = $this->getMockBuilder(SearchFormViewHelper::class)->onlyMethods(['getControllerContext', 'getTypoScriptConfiguration', 'getTemplateVariableContainer', 'getSearchResultSet', 'renderChildren', 'getIsSiteManagedSite'])->getMock(); + $this->viewHelper = $this->getMockBuilder(SearchFormViewHelper::class)->onlyMethods([ + 'getControllerContext', + 'getTypoScriptConfiguration', + 'getTemplateVariableContainer', + 'getSearchResultSet', + 'renderChildren', + 'getIsSiteManagedSite', + ])->getMock(); $this->viewHelper->expects(self::any())->method('getControllerContext')->willReturn($controllerContextMock); $this->viewHelper->expects(self::any())->method('getTypoScriptConfiguration')->willReturn($this->typoScriptConfigurationMock); $this->viewHelper->expects(self::any())->method('getTemplateVariableContainer')->willReturn($this->getDumbMock(VariableProviderInterface::class)); diff --git a/class.ext_update.php b/class.ext_update.php index 1af5e72f42..eff62637b1 100644 --- a/class.ext_update.php +++ b/class.ext_update.php @@ -13,10 +13,10 @@ * The TYPO3 project - inspiring people to share! */ +use ApacheSolrForTypo3\Solr\Migrations\RemoveSiteFromScheduler; use TYPO3\CMS\Core\Messaging\FlashMessage; use TYPO3\CMS\Core\Messaging\FlashMessageRendererResolver; use TYPO3\CMS\Core\Utility\GeneralUtility; -use ApacheSolrForTypo3\Solr\Migrations\RemoveSiteFromScheduler; /** * Update class for the extension manager. @@ -42,7 +42,8 @@ class ext_update /** * Constructor initializing all migrations */ - public function __construct() { + public function __construct() + { $this->migrators[] = new RemoveSiteFromScheduler(); } @@ -52,13 +53,14 @@ public function __construct() { * * @return bool */ - public function access() { + public function access() + { foreach ($this->migrators as $migration) { if ($migration->isNeeded()) { - return TRUE; + return true; } } - return FALSE; + return false; } /** @@ -66,7 +68,8 @@ public function access() { * * @return string */ - public function main() { + public function main() + { foreach ($this->migrators as $migration) { if ($migration->isNeeded()) { try { @@ -84,14 +87,15 @@ public function main() { * * @return string */ - protected function generateOutput() { + protected function generateOutput() + { $flashMessages = []; foreach ($this->messages as $messageItem) { /** @var \TYPO3\CMS\Core\Messaging\FlashMessage $flashMessage */ $flashMessages[] = GeneralUtility::makeInstance(FlashMessage::class, $messageItem[2], $messageItem[1], $messageItem[0]); } - /** @var $resolver FlashMessageRendererResolver */ + /** @var $resolver FlashMessageRendererResolver */ $resolver = GeneralUtility::makeInstance(FlashMessageRendererResolver::class); $renderer = $resolver->resolve(); return $renderer->render($flashMessages); diff --git a/composer.json b/composer.json index 48249bac81..e64248f4e5 100644 --- a/composer.json +++ b/composer.json @@ -23,6 +23,7 @@ "php": "^7.4.0 || ^8.0", "ext-dom": "*", "ext-json": "*", + "ext-libxml": "*", "ext-simplexml": "*", "solarium/solarium": "6.2.3", "typo3/cms-backend": "*", @@ -35,10 +36,13 @@ "typo3/cms-tstemplate": "*" }, "require-dev": { + "typo3/coding-standards": ">=0.5.0", "phpunit/phpunit": "^9.5", "phpspec/prophecy-phpunit":"*", "typo3/testing-framework": "^6.12", - "typo3/cms-fluid-styled-content": "*" + "typo3/cms-fluid-styled-content": "*", + "scrutinizer/ocular": "*", + "sclable/xml-lint": "*" }, "replace": { "apache-solr-for-typo3/solrfluid": "*", @@ -56,6 +60,8 @@ "TYPO3\\CMS\\Core\\Tests\\": ".Build/Web/typo3/sysext/core/Tests/" } }, + "minimum-stability": "dev", + "prefer-stable": true, "config": { "allow-plugins": true, "vendor-dir": ".Build/vendor", @@ -67,10 +73,32 @@ "[ -L .Build/Web/typo3conf/ext/solr ] || ln -snvf ../../../../. .Build/Web/typo3conf/ext/solr" ], "extension-create-libs": [ - "@composer req -d Resources/Private/Php/ComposerLibraries solarium/solarium:$(Build/Helpers/GET_LACAL_BACKAGE_VERSION_CONSTRAINT.sh solarium/solarium)" + "@composer req -d Resources/Private/Php/ComposerLibraries solarium/solarium:$(Build/Helpers/GET_LACAL_PACKAGE_VERSION_CONSTRAINT.sh solarium/solarium)" ], "extension-build": [ "@extension-create-libs" + ], + "tests:restore-git": "echo \"Retore composer.json to initial state:\" && git checkout composer.json", + "tests:env": [ + "if [ -z ${TYPO3_VERSION+x} ]; then >&2 echo \"Can not proceed, because env var TYPO3_VERSION is not set\"; exit 1; else echo \"Setup test environment for TYPO3 ${TYPO3_VERSION}\"; fi", + "if [ \"${TYPO3_VERSION#*dev}\" != \"dev\" ]; then $COMPOSER_BINARY config minimum-stability dev; fi" + ], + "tests:setup": [ + "@tests:env", + "@composer req --prefer-source --update-with-all-dependencies typo3/cms-core:${TYPO3_VERSION}", + "@tests:restore-git" + ], + "tests:unit": [ + "phpunit --colors --config=Build/Test/UnitTests.xml --bootstrap=Build/Test/UnitTestsBootstrap.php" + ], + "tests:integration": [ + "phpunit --colors --config=Build/Test/IntegrationTests.xml --bootstrap=.Build/Web/typo3conf/ext/solr/Build/Test/IntegrationTestsBootstrap.php" + ], + "t3:standards:fix": [ + "php-cs-fixer fix" + ], + "lint:xlf": [ + "xmllint Resources/Private/Language/ -p '*.xlf'" ] }, "extra": { diff --git a/ext_emconf.php b/ext_emconf.php index 79f5a29ae5..bfd733ee2d 100644 --- a/ext_emconf.php +++ b/ext_emconf.php @@ -1,4 +1,5 @@ 'Apache Solr for TYPO3 - Enterprise Search', 'description' => 'Apache Solr for TYPO3 is the enterprise search server you were looking for with special features such as Faceted Search or Synonym Support and incredibly fast response times of results within milliseconds.', @@ -11,7 +12,7 @@ 'constraints' => [ 'depends' => [ 'scheduler' => '', - 'typo3' => '11.5.4-11.5.99' + 'typo3' => '11.5.4-11.5.99', ], 'conflicts' => [], 'suggests' => [ @@ -20,10 +21,10 @@ ], 'autoload' => [ 'classmap' => [ - 'Resources/Private/Php/' + 'Resources/Private/Php/', ], 'psr-4' => [ - 'ApacheSolrForTypo3\\Solr\\' => 'Classes/' - ] - ] + 'ApacheSolrForTypo3\\Solr\\' => 'Classes/', + ], + ], ]; diff --git a/ext_localconf.php b/ext_localconf.php index 71acc0f45a..f19e0c7090 100644 --- a/ext_localconf.php +++ b/ext_localconf.php @@ -1,7 +1,8 @@ getSummary'; - # ----- # ----- # ----- # ----- # ----- # ----- # ----- # ----- # ----- # + // ----- # ----- # ----- # ----- # ----- # ----- # ----- # ----- # ----- # // register search components @@ -91,7 +91,7 @@ \ApacheSolrForTypo3\Solr\Search\ElevationComponent::class ); - # ----- # ----- # ----- # ----- # ----- # ----- # ----- # ----- # ----- # + // ----- # ----- # ----- # ----- # ----- # ----- # ----- # ----- # ----- # // adding scheduler tasks @@ -99,44 +99,44 @@ 'extension' => 'solr', 'title' => 'LLL:EXT:solr/Resources/Private/Language/locallang.xlf:optimizeindex_title', 'description' => 'LLL:EXT:solr/Resources/Private/Language/locallang.xlf:optimizeindex_description', - 'additionalFields' => \ApacheSolrForTypo3\Solr\Task\OptimizeIndexTaskAdditionalFieldProvider::class + 'additionalFields' => \ApacheSolrForTypo3\Solr\Task\OptimizeIndexTaskAdditionalFieldProvider::class, ]; $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['scheduler']['tasks'][\ApacheSolrForTypo3\Solr\Task\ReIndexTask::class] = [ 'extension' => 'solr', 'title' => 'LLL:EXT:solr/Resources/Private/Language/locallang.xlf:reindex_title', 'description' => 'LLL:EXT:solr/Resources/Private/Language/locallang.xlf:reindex_description', - 'additionalFields' => \ApacheSolrForTypo3\Solr\Task\ReIndexTaskAdditionalFieldProvider::class + 'additionalFields' => \ApacheSolrForTypo3\Solr\Task\ReIndexTaskAdditionalFieldProvider::class, ]; $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['scheduler']['tasks'][\ApacheSolrForTypo3\Solr\Task\IndexQueueWorkerTask::class] = [ 'extension' => 'solr', 'title' => 'LLL:EXT:solr/Resources/Private/Language/locallang.xlf:indexqueueworker_title', 'description' => 'LLL:EXT:solr/Resources/Private/Language/locallang.xlf:indexqueueworker_description', - 'additionalFields' => \ApacheSolrForTypo3\Solr\Task\IndexQueueWorkerTaskAdditionalFieldProvider::class + 'additionalFields' => \ApacheSolrForTypo3\Solr\Task\IndexQueueWorkerTaskAdditionalFieldProvider::class, ]; $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['scheduler']['tasks'][\ApacheSolrForTypo3\Solr\Task\EventQueueWorkerTask::class] = [ 'extension' => 'solr', 'title' => 'LLL:EXT:solr/Resources/Private/Language/locallang_be.xlf:task.eventQueueWorkerTask.title', 'description' => 'LLL:EXT:solr/Resources/Private/Language/locallang_be.xlf:task.eventQueueWorkerTask.description', - 'additionalFields' => \ApacheSolrForTypo3\Solr\Task\EventQueueWorkerTaskAdditionalFieldProvider::class + 'additionalFields' => \ApacheSolrForTypo3\Solr\Task\EventQueueWorkerTaskAdditionalFieldProvider::class, ]; if (!isset($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['scheduler']['tasks'][\TYPO3\CMS\Scheduler\Task\TableGarbageCollectionTask::class]['options']['tables']['tx_solr_statistics'])) { $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['scheduler']['tasks'][\TYPO3\CMS\Scheduler\Task\TableGarbageCollectionTask::class]['options']['tables']['tx_solr_statistics'] = [ 'dateField' => 'tstamp', - 'expirePeriod' => 180 + 'expirePeriod' => 180, ]; } - # ----- # ----- # ----- # ----- # ----- # ----- # ----- # ----- # ----- # + // ----- # ----- # ----- # ----- # ----- # ----- # ----- # ----- # ----- # // registering the eID scripts // TODO move to suggest form modifier $GLOBALS['TYPO3_CONF_VARS']['FE']['eID_include']['tx_solr_api'] = 'EXT:solr/Classes/Eid/Api.php'; - # ----- # ----- # ----- # ----- # ----- # ----- # ----- # ----- # ----- # + // ----- # ----- # ----- # ----- # ----- # ----- # ----- # ----- # ----- # // add custom Solr content objects @@ -152,8 +152,7 @@ $GLOBALS['TYPO3_CONF_VARS']['FE']['ContentObjects'][\ApacheSolrForTypo3\Solr\ContentObject\Classification::CONTENT_OBJECT_NAME] = \ApacheSolrForTypo3\Solr\ContentObject\Classification::class; - - # ----- # ----- # ----- # ----- # ----- # ----- # ----- # ----- # ----- # + // ----- # ----- # ----- # ----- # ----- # ----- # ----- # ----- # ----- # // Register cache for frequent searches @@ -178,7 +177,7 @@ $GLOBALS['TYPO3_CONF_VARS']['SYS']['caching']['cacheConfigurations']['tx_solr_configuration']['groups'] = ['all']; } - # ----- # ----- # ----- # ----- # ----- # ----- # ----- # ----- # ----- # + // ----- # ----- # ----- # ----- # ----- # ----- # ----- # ----- # ----- # /* @var \ApacheSolrForTypo3\Solr\System\Configuration\ExtensionConfiguration $extensionConfiguration */ $extensionConfiguration = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance( \ApacheSolrForTypo3\Solr\System\Configuration\ExtensionConfiguration::class @@ -190,13 +189,13 @@ [ 'FE' => [ 'cacheHash' => [ - 'excludedParameters' => $extensionConfiguration->getCacheHashExcludedParameters() - ] - ] + 'excludedParameters' => $extensionConfiguration->getCacheHashExcludedParameters(), + ], + ], ] ); - # ----- # ----- # ----- # ----- # ----- # ----- # ----- # ----- # ----- # + // ----- # ----- # ----- # ----- # ----- # ----- # ----- # ----- # ----- # if (!isset($GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['solr']['searchResultClassName '])) { $GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['solr']['searchResultClassName '] = \ApacheSolrForTypo3\Solr\Domain\Search\ResultSet\Result\SearchResult::class; @@ -218,22 +217,22 @@ $GLOBALS['TYPO3_CONF_VARS']['LOG']['ApacheSolrForTypo3']['Solr']['writerConfiguration'] = [ $logLevel => [ \TYPO3\CMS\Core\Log\Writer\FileWriter::class => [ - 'logFileInfix' => 'solr' - ] + 'logFileInfix' => 'solr', + ], ], ]; } - # ----- # ----- # ----- # ----- # ----- # ----- # ----- # ----- # ----- # + // ----- # ----- # ----- # ----- # ----- # ----- # ----- # ----- # ----- # \TYPO3\CMS\Extbase\Utility\ExtensionUtility::configurePlugin( 'Solr', 'pi_results', [ - \ApacheSolrForTypo3\Solr\Controller\SearchController::class => 'results,form,detail' + \ApacheSolrForTypo3\Solr\Controller\SearchController::class => 'results,form,detail', ], [ - \ApacheSolrForTypo3\Solr\Controller\SearchController::class => 'results' + \ApacheSolrForTypo3\Solr\Controller\SearchController::class => 'results', ] ); @@ -241,7 +240,7 @@ 'Solr', 'pi_search', [ - \ApacheSolrForTypo3\Solr\Controller\SearchController::class => 'form' + \ApacheSolrForTypo3\Solr\Controller\SearchController::class => 'form', ] ); @@ -249,10 +248,10 @@ 'Solr', 'pi_frequentlySearched', [ - \ApacheSolrForTypo3\Solr\Controller\SearchController::class => 'frequentlySearched' + \ApacheSolrForTypo3\Solr\Controller\SearchController::class => 'frequentlySearched', ], [ - \ApacheSolrForTypo3\Solr\Controller\SearchController::class => 'frequentlySearched' + \ApacheSolrForTypo3\Solr\Controller\SearchController::class => 'frequentlySearched', ] ); @@ -260,10 +259,10 @@ 'Solr', 'pi_suggest', [ - \ApacheSolrForTypo3\Solr\Controller\SuggestController::class => 'suggest' + \ApacheSolrForTypo3\Solr\Controller\SuggestController::class => 'suggest', ], [ - \ApacheSolrForTypo3\Solr\Controller\SuggestController::class => 'suggest' + \ApacheSolrForTypo3\Solr\Controller\SuggestController::class => 'suggest', ] ); diff --git a/ext_tables.php b/ext_tables.php index c04d68e8e8..74efed8d1a 100644 --- a/ext_tables.php +++ b/ext_tables.php @@ -15,21 +15,39 @@ $extIconPath = 'EXT:solr/Resources/Public/Images/Icons/'; /* @var \TYPO3\CMS\Core\Imaging\IconRegistry $iconRegistry */ $iconRegistry = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(\TYPO3\CMS\Core\Imaging\IconRegistry::class); - $iconRegistry->registerIcon($modulePrefix . '-main', $svgProvider, - ['source' => $extIconPath . 'ModuleSolrMain.svg']); - $iconRegistry->registerIcon($modulePrefix . '-solr-core-optimization', $svgProvider, - ['source' => $extIconPath . 'ModuleCoreOptimization.svg']); - $iconRegistry->registerIcon($modulePrefix . '-index-administration', $svgProvider, - ['source' => $extIconPath . 'ModuleIndexAdministration.svg']); + $iconRegistry->registerIcon( + $modulePrefix . '-main', + $svgProvider, + ['source' => $extIconPath . 'ModuleSolrMain.svg'] + ); + $iconRegistry->registerIcon( + $modulePrefix . '-solr-core-optimization', + $svgProvider, + ['source' => $extIconPath . 'ModuleCoreOptimization.svg'] + ); + $iconRegistry->registerIcon( + $modulePrefix . '-index-administration', + $svgProvider, + ['source' => $extIconPath . 'ModuleIndexAdministration.svg'] + ); // all connections - $iconRegistry->registerIcon($modulePrefix . '-initsolrconnections', $svgProvider, - ['source' => $extIconPath . 'InitSolrConnections.svg']); + $iconRegistry->registerIcon( + $modulePrefix . '-initsolrconnections', + $svgProvider, + ['source' => $extIconPath . 'InitSolrConnections.svg'] + ); // single connection - context menu - $iconRegistry->registerIcon($modulePrefix . '-initsolrconnection', $svgProvider, - ['source' => $extIconPath . 'InitSolrConnection.svg']); + $iconRegistry->registerIcon( + $modulePrefix . '-initsolrconnection', + $svgProvider, + ['source' => $extIconPath . 'InitSolrConnection.svg'] + ); // register plugin icon - $iconRegistry->registerIcon('extensions-solr-plugin-contentelement', $svgProvider, - ['source' => $extIconPath . 'ContentElement.svg']); + $iconRegistry->registerIcon( + 'extensions-solr-plugin-contentelement', + $svgProvider, + ['source' => $extIconPath . 'ContentElement.svg'] + ); // Add Main module "APACHE SOLR". // Acces to a main module is implicit, as soon as a user has access to at least one of its submodules. To make it possible, main module must be registered in that way and without any Actions! @@ -41,7 +59,7 @@ [ 'name' => 'searchbackend', 'labels' => 'LLL:EXT:solr/Resources/Private/Language/locallang_mod.xlf', - 'iconIdentifier' => 'extensions-solr-module-main' + 'iconIdentifier' => 'extensions-solr-module-main', ] ); @@ -59,7 +77,7 @@ 'access' => 'user,group', 'icon' => 'EXT:solr/Resources/Public/Images/Icons/ModuleInfo.svg', 'labels' => 'LLL:EXT:solr/Resources/Private/Language/locallang_mod_info.xlf', - 'navigationComponentId' => $treeComponentId + 'navigationComponentId' => $treeComponentId, ] ); @@ -69,13 +87,13 @@ 'CoreOptimization', '', [ - \ApacheSolrForTypo3\Solr\Controller\Backend\Search\CoreOptimizationModuleController::class => 'index, addSynonyms, importSynonymList, deleteAllSynonyms, exportSynonyms, deleteSynonyms, saveStopWords, importStopWordList, exportStopWords, switchSite, switchCore' + \ApacheSolrForTypo3\Solr\Controller\Backend\Search\CoreOptimizationModuleController::class => 'index, addSynonyms, importSynonymList, deleteAllSynonyms, exportSynonyms, deleteSynonyms, saveStopWords, importStopWordList, exportStopWords, switchSite, switchCore', ], [ 'access' => 'user,group', 'icon' => 'EXT:solr/Resources/Public/Images/Icons/ModuleCoreOptimization.svg', 'labels' => 'LLL:EXT:solr/Resources/Private/Language/locallang_mod_coreoptimize.xlf', - 'navigationComponentId' => $treeComponentId + 'navigationComponentId' => $treeComponentId, ] ); @@ -86,13 +104,13 @@ '', [ \ApacheSolrForTypo3\Solr\Controller\Backend\Search\IndexQueueModuleController::class => - 'index, initializeIndexQueue, clearIndexQueue, requeueDocument, resetLogErrors, showError, doIndexingRun, switchSite' + 'index, initializeIndexQueue, clearIndexQueue, requeueDocument, resetLogErrors, showError, doIndexingRun, switchSite', ], [ 'access' => 'user,group', 'icon' => 'EXT:solr/Resources/Public/Images/Icons/ModuleIndexQueue.svg', 'labels' => 'LLL:EXT:solr/Resources/Private/Language/locallang_mod_indexqueue.xlf', - 'navigationComponentId' => $treeComponentId + 'navigationComponentId' => $treeComponentId, ] ); @@ -103,18 +121,18 @@ '', [ \ApacheSolrForTypo3\Solr\Controller\Backend\Search\IndexAdministrationModuleController::class => - 'index, emptyIndex, clearIndexQueue, reloadIndexConfiguration, switchSite' + 'index, emptyIndex, clearIndexQueue, reloadIndexConfiguration, switchSite', ], [ 'access' => 'user,group', 'icon' => 'EXT:solr/Resources/Public/Images/Icons/ModuleIndexAdministration.svg', 'labels' => 'LLL:EXT:solr/Resources/Private/Language/locallang_mod_indexadmin.xlf', - 'navigationComponentId' => $treeComponentId + 'navigationComponentId' => $treeComponentId, ] ); - // registering reports - $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['reports']['tx_reports']['status']['providers']['solr'] = [ + // registering reports + $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['reports']['tx_reports']['status']['providers']['solr'] = [ \ApacheSolrForTypo3\Solr\Report\SiteHandlingStatus::class, \ApacheSolrForTypo3\Solr\Report\SchemaStatus::class, \ApacheSolrForTypo3\Solr\Report\SolrConfigStatus::class, @@ -123,15 +141,15 @@ \ApacheSolrForTypo3\Solr\Report\SolrVersionStatus::class, \ApacheSolrForTypo3\Solr\Report\AccessFilterPluginInstalledStatus::class, \ApacheSolrForTypo3\Solr\Report\AllowUrlFOpenStatus::class, - \ApacheSolrForTypo3\Solr\Report\FilterVarStatus::class + \ApacheSolrForTypo3\Solr\Report\FilterVarStatus::class, ]; - // Register Context Sensitive Help (CSH) translation labels - \TYPO3\CMS\Core\Utility\ExtensionManagementUtility::addLLrefForTCAdescr( - 'pages', - 'EXT:solr/Resources/Private/Language/locallang_csh_pages.xlf' - ); -} + // Register Context Sensitive Help (CSH) translation labels + \TYPO3\CMS\Core\Utility\ExtensionManagementUtility::addLLrefForTCAdescr( + 'pages', + 'EXT:solr/Resources/Private/Language/locallang_csh_pages.xlf' + ); + } if ((TYPO3_MODE === 'BE') || (TYPO3_MODE === 'FE' && isset($_POST['TSFE_EDIT']))) { // the order of registering the garbage collector and the record monitor is important! @@ -147,8 +165,7 @@ } })(); - -# ----- # ----- # ----- # ----- # ----- # ----- # ----- # ----- # ----- # +// ----- # ----- # ----- # ----- # ----- # ----- # ----- # ----- # ----- # $isComposerMode = defined('TYPO3_COMPOSER_MODE') && TYPO3_COMPOSER_MODE; if (!$isComposerMode) {