From a0ddbbf6d2278adb1220fa2a741878e82955701b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafael=20K=C3=A4hm?= Date: Thu, 28 Nov 2024 17:49:44 +0100 Subject: [PATCH 1/7] [FIX] deprecations in Dockerfile Fixes deprecation notices in Dockerfile: - MaintainerDeprecated: Maintainer instruction is deprecated in favor of using label (line 2) - LegacyKeyValueFormat: "ENV key=value" should be used instead of legacy "ENV key value" format (line 3) Ports: #4110 --- Docker/SolrServer/Dockerfile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Docker/SolrServer/Dockerfile b/Docker/SolrServer/Dockerfile index b965636a3..afa4b8d95 100644 --- a/Docker/SolrServer/Dockerfile +++ b/Docker/SolrServer/Dockerfile @@ -1,6 +1,6 @@ FROM solr:9.7.0 -MAINTAINER dkd Internet Service GmbH -ENV TERM linux +LABEL org.opencontainers.image.authors="dkd Internet Service GmbH info@dkd.de" +ENV TERM=linux ARG SOLR_UNIX_UID="8983" ARG SOLR_UNIX_GID="8983" From 3ca93291860fb761294d9639fe0292bedcfa85a2 Mon Sep 17 00:00:00 2001 From: Markus Friedrich Date: Mon, 15 Jul 2024 15:01:46 +0200 Subject: [PATCH 2/7] [BUGFIX] Ensure index document is deleted If an index document has no representation in the index queue, EXT:solr fails to remove the item on deletions or updates of the corresponding record in TYPO3. By adjusting the checks in the record monitor, garbage remover and update handler this issue is resolved. The ConfigurationAwareRecordService is no longer using BackendUtility::getRecord() as this would return hidden records. Resolves: #4107 --- .../Queue/GarbageRemover/AbstractStrategy.php | 27 ++++- .../ConfigurationAwareRecordService.php | 31 ++++- .../Queue/UpdateHandler/DataUpdateHandler.php | 20 ++-- .../Queue/UpdateHandler/GarbageHandler.php | 3 +- Tests/Integration/GarbageCollectorTest.php | 107 ++++++++++++++++++ .../UpdateHandler/DataUpdateHandlerTest.php | 56 ++------- 6 files changed, 183 insertions(+), 61 deletions(-) diff --git a/Classes/Domain/Index/Queue/GarbageRemover/AbstractStrategy.php b/Classes/Domain/Index/Queue/GarbageRemover/AbstractStrategy.php index 610daeac2..45ea17af5 100644 --- a/Classes/Domain/Index/Queue/GarbageRemover/AbstractStrategy.php +++ b/Classes/Domain/Index/Queue/GarbageRemover/AbstractStrategy.php @@ -17,6 +17,7 @@ use ApacheSolrForTypo3\Solr\ConnectionManager; use ApacheSolrForTypo3\Solr\Domain\Site\Exception\UnexpectedTYPO3SiteInitializationException; +use ApacheSolrForTypo3\Solr\Domain\Site\SiteRepository; use ApacheSolrForTypo3\Solr\Exception\InvalidArgumentException; use ApacheSolrForTypo3\Solr\GarbageCollectorPostProcessor; use ApacheSolrForTypo3\Solr\IndexQueue\Queue; @@ -33,15 +34,17 @@ abstract class AbstractStrategy { protected QueueInterface $queue; - protected ConnectionManager $connectionManager; + protected SiteRepository $siteRepository; public function __construct( QueueInterface $queue = null, ConnectionManager $connectionManager = null, + SiteRepository $siteRepository = null, ) { $this->queue = $queue ?? GeneralUtility::makeInstance(Queue::class); $this->connectionManager = $connectionManager ?? GeneralUtility::makeInstance(ConnectionManager::class); + $this->siteRepository = $siteRepository ?? GeneralUtility::makeInstance(SiteRepository::class); } /** @@ -90,8 +93,13 @@ protected function deleteInSolrAndUpdateIndexQueue(string $table, int $uid): voi */ protected function deleteIndexDocuments(string $table, int $uid, int $language = 0): void { - // record can be indexed for multiple sites $indexQueueItems = $this->queue->getItems($table, $uid); + if ($indexQueueItems === []) { + $this->deleteRecordInAllSites($table, $uid); + return; + } + + // record can be indexed for multiple sites foreach ($indexQueueItems as $indexQueueItem) { try { $site = $indexQueueItem->getSite(); @@ -115,6 +123,21 @@ protected function deleteIndexDocuments(string $table, int $uid, int $language = } } + protected function deleteRecordInAllSites(string $table, int $uid): void + { + $sites = $this->siteRepository->getAvailableSites(); + foreach ($sites as $site) { + $solrConnections = $this->connectionManager->getConnectionsBySite($site); + $this->deleteRecordInAllSolrConnections( + $table, + $uid, + $solrConnections, + $site->getSiteHash(), + $site->getSolrConfiguration()->getEnableCommits() + ); + } + } + /** * Deletes the record in all solr connections from that site. */ diff --git a/Classes/Domain/Index/Queue/RecordMonitor/Helper/ConfigurationAwareRecordService.php b/Classes/Domain/Index/Queue/RecordMonitor/Helper/ConfigurationAwareRecordService.php index 71406779b..f0edd7f0b 100644 --- a/Classes/Domain/Index/Queue/RecordMonitor/Helper/ConfigurationAwareRecordService.php +++ b/Classes/Domain/Index/Queue/RecordMonitor/Helper/ConfigurationAwareRecordService.php @@ -17,7 +17,10 @@ use ApacheSolrForTypo3\Solr\System\Cache\TwoLevelCache; use ApacheSolrForTypo3\Solr\System\Configuration\TypoScriptConfiguration; -use TYPO3\CMS\Backend\Utility\BackendUtility; +use TYPO3\CMS\Core\Database\Connection; +use TYPO3\CMS\Core\Database\ConnectionPool; +use TYPO3\CMS\Core\Database\Query\QueryBuilder; +use TYPO3\CMS\Core\Database\Query\QueryHelper; use TYPO3\CMS\Core\Utility\GeneralUtility; /** @@ -130,9 +133,26 @@ protected function getRecordForIndexConfigurationIsValid( return $row; } - $row = BackendUtility::getRecord($recordTable, $recordUid, '*', $recordWhereClause) ?? []; - $cache->set($cacheId, $row); + $queryBuilder = $this->getQueryBuilderForTable($recordTable); + $queryBuilder + ->select('*') + ->from($recordTable) + ->where( + $queryBuilder->expr()->eq( + 'uid', + $queryBuilder->createNamedParameter($recordUid, Connection::PARAM_INT) + ) + ); + + if ($recordWhereClause !== '') { + $queryBuilder->andWhere(QueryHelper::stripLogicalOperatorPrefix($recordWhereClause)); + } + $row = $queryBuilder->executeQuery()->fetchAssociative(); + if ($row === false) { + $row = []; + } + $cache->set($cacheId, $row); return $row; } @@ -154,4 +174,9 @@ protected function isValidTableForIndexConfigurationName( return false; } + + protected static function getQueryBuilderForTable(string $table): QueryBuilder + { + return GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable($table); + } } diff --git a/Classes/Domain/Index/Queue/UpdateHandler/DataUpdateHandler.php b/Classes/Domain/Index/Queue/UpdateHandler/DataUpdateHandler.php index 3299d077b..2d3941f7f 100644 --- a/Classes/Domain/Index/Queue/UpdateHandler/DataUpdateHandler.php +++ b/Classes/Domain/Index/Queue/UpdateHandler/DataUpdateHandler.php @@ -184,7 +184,7 @@ public function handlePageUpdate(int $uid, array $updatedFields = []): void } if ($pid === null) { - $this->removeFromIndexAndQueueWhenItemInQueue('pages', $uid); + $this->removeFromIndexAndQueue('pages', $uid); return; } @@ -284,7 +284,7 @@ protected function applyPageChangesToQueue(int $uid): void $this->mountPageUpdater->update($uid); $this->indexQueue->updateItem('pages', $uid); } else { - $this->removeFromIndexAndQueueWhenItemInQueue('pages', $uid); + $this->removeFromIndexAndQueue('pages', $uid); } } @@ -307,7 +307,7 @@ protected function applyRecordChangesToQueue(string $table, int $uid, int $pid): $this->indexQueue->updateItem($table, $uid); } else { // TODO should be moved to garbage collector - $this->removeFromIndexAndQueueWhenItemInQueue($table, $uid); + $this->removeFromIndexAndQueue($table, $uid); } } } @@ -324,9 +324,17 @@ 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. * * @throws DBALException + * @deprecated DataUpdateHandler->removeFromIndexAndQueueWhenItemInQueue is deprecated and will be removed in v13. + Use DataUpdateHandler->removeFromIndexAndQueue instead. */ protected function removeFromIndexAndQueueWhenItemInQueue(string $recordTable, int $recordUid): void { + trigger_error( + 'DataUpdateHandler->removeFromIndexAndQueueWhenItemInQueue is deprecated and will be removed in v13.' + . ' Use DataUpdateHandler->removeFromIndexAndQueue instead.', + E_USER_DEPRECATED + ); + if (!$this->indexQueue->containsItem($recordTable, $recordUid)) { return; } @@ -406,7 +414,7 @@ protected function processPageRecord(int $uid, int $pid, array $updatedFields = protected function processRecord(string $recordTable, int $recordUid, array $rootPageIds): void { if (empty($rootPageIds)) { - $this->removeFromIndexAndQueueWhenItemInQueue($recordTable, $recordUid); + $this->removeFromIndexAndQueue($recordTable, $recordUid); return; } @@ -424,9 +432,7 @@ protected function processRecord(string $recordTable, int $recordUid, array $roo $record = $this->configurationAwareRecordService->getRecord($recordTable, $recordUid, $solrConfiguration); if (empty($record)) { - // TODO move this part to the garbage collector - // check if the item should be removed from the index because it no longer matches the conditions - $this->removeFromIndexAndQueueWhenItemInQueue($recordTable, $recordUid); + // skip processing, queue and index entry will be removed by garbage collection triggered via RecordGarbageCheckEvent continue; } // Clear existing index queue items to prevent mount point duplicates. diff --git a/Classes/Domain/Index/Queue/UpdateHandler/GarbageHandler.php b/Classes/Domain/Index/Queue/UpdateHandler/GarbageHandler.php index 42e4cbd5a..b8f608ee9 100644 --- a/Classes/Domain/Index/Queue/UpdateHandler/GarbageHandler.php +++ b/Classes/Domain/Index/Queue/UpdateHandler/GarbageHandler.php @@ -119,8 +119,9 @@ public function performRecordGarbageCheck( ): void { $record = $this->getRecordWithFieldRelevantForGarbageCollection($table, $uid); - // If no record could be found skip further processing + // If no record could be found, remove remains from index and queue if (empty($record)) { + $this->collectGarbage($table, $uid); return; } diff --git a/Tests/Integration/GarbageCollectorTest.php b/Tests/Integration/GarbageCollectorTest.php index 51ed8b7fe..f9ee9c55a 100644 --- a/Tests/Integration/GarbageCollectorTest.php +++ b/Tests/Integration/GarbageCollectorTest.php @@ -20,9 +20,12 @@ use ApacheSolrForTypo3\Solr\IndexQueue\Indexer; use ApacheSolrForTypo3\Solr\IndexQueue\Queue; use ApacheSolrForTypo3\Solr\IndexQueue\RecordMonitor; +use ApacheSolrForTypo3\Solr\System\Cache\TwoLevelCache; use ApacheSolrForTypo3\Solr\System\Records\Queue\EventQueueItemRepository; use ApacheSolrForTypo3\Solr\Task\EventQueueWorkerTask; +use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\Attributes\Test; +use Traversable; use TYPO3\CMS\Core\Authentication\BackendUserAuthentication; use TYPO3\CMS\Core\Configuration\ExtensionConfiguration; use TYPO3\CMS\Core\Database\Connection; @@ -360,6 +363,110 @@ public function canCollectGarbageIfPageTreeIsMovedButStaysOnSamePage(): void $this->assertSolrContainsDocumentCount(3); } + #[Test] + public function canCollectGarbageEvenIfNotInIndexQueue(): void + { + $this->prepareCanCollectGarbageEvenIfNotInIndexQueue(); + $this->assertIndexQueueContainsItemAmount(0); + $this->assertSolrIsEmpty(); + } + + #[Test] + public function canCollectGarbageEvenIfNotInIndexQueueInDelayedProcessingMode(): void + { + $this->extensionConfiguration->set('solr', ['monitoringType' => 1]); + $this->prepareCanCollectGarbageEvenIfNotInIndexQueue(); + $this->assertEventQueueContainsItemAmount(2); + $this->processEventQueue(); + $this->assertIndexQueueContainsItemAmount(0); + $this->assertSolrIsEmpty(); + } + + protected function prepareCanCollectGarbageEvenIfNotInIndexQueue(): void + { + $this->importCSVDataSet(__DIR__ . '/Fixtures/subpage.csv'); + + $this->cleanUpSolrServerAndAssertEmpty(); + $this->assertEmptyIndexQueue(); + $this->addToQueueAndIndexRecord('pages', 2); + $this->assertIndexQueueContainsItemAmount(1); + $this->waitToBeVisibleInSolr(); + $this->assertSolrContainsDocumentCount(1); + + // flush cache after preparing the environment to be sure no wrong version is cached + $cache = new TwoLevelCache('runtime'); + $cache->flush(); + + // clear index queue, as we want to test if garbage collection works if record has no representation in queue + $connection = $this->getConnectionPool()->getConnectionForTable('tx_solr_indexqueue_item'); + $connection->truncate('tx_solr_indexqueue_item'); + + $this->dataHandler->start( + ['pages' => [2 => ['hidden' => 1]]], + [], + $this->backendUser + ); + $this->dataHandler->process_datamap(); + } + + #[Test] + #[DataProvider('canCollectGarbageOfDeletedRecordEvenIfNotInIndexQueueDataProvider')] + public function canCollectGarbageOfDeletedRecordEvenIfNotInIndexQueue(bool $forceHardDelete): void + { + $this->prepareCanCollectGarbageOfDeletedRecordEvenIfNotInIndexQueue($forceHardDelete); + $this->assertIndexQueueContainsItemAmount(0); + $this->assertSolrIsEmpty(); + } + + #[Test] + #[DataProvider('canCollectGarbageOfDeletedRecordEvenIfNotInIndexQueueDataProvider')] + public function canCollectGarbageOfDeletedRecordEvenIfNotInIndexQueueInDelayedProcessingMode(bool $forceHardDelete): void + { + $this->extensionConfiguration->set('solr', ['monitoringType' => 1]); + $this->prepareCanCollectGarbageOfDeletedRecordEvenIfNotInIndexQueue($forceHardDelete); + $this->assertEventQueueContainsItemAmount(1); + $this->processEventQueue(); + $this->assertIndexQueueContainsItemAmount(0); + $this->assertSolrIsEmpty(); + } + + protected function prepareCanCollectGarbageOfDeletedRecordEvenIfNotInIndexQueue(bool $forceHardDelete): void + { + $this->importCSVDataSet(__DIR__ . '/Fixtures/subpage.csv'); + + $this->cleanUpSolrServerAndAssertEmpty(); + $this->assertEmptyIndexQueue(); + $this->addToQueueAndIndexRecord('pages', 2); + $this->assertIndexQueueContainsItemAmount(1); + $this->waitToBeVisibleInSolr(); + $this->assertSolrContainsDocumentCount(1); + + // flush cache after preparing the environment to be sure no wrong version is cached + $cache = new TwoLevelCache('runtime'); + $cache->flush(); + + // clear index queue, as we want to test if garbage collection works if record has no representation in queue + $connection = $this->getConnectionPool()->getConnectionForTable('tx_solr_indexqueue_item'); + $connection->truncate('tx_solr_indexqueue_item'); + + if ($forceHardDelete) { + unset($GLOBALS['TCA']['pages']['ctrl']['delete']); + } + + $this->dataHandler->start( + [], + ['pages' => [2 => ['delete' => 1 ]]], + $this->backendUser + ); + $this->dataHandler->process_cmdmap(); + } + + public static function canCollectGarbageOfDeletedRecordEvenIfNotInIndexQueueDataProvider(): Traversable + { + yield 'Test soft delete' => [ false ]; + yield 'Test hard delete' => [ true ]; + } + #[Test] public function canRemoveDeletedContentElement(): void { diff --git a/Tests/Unit/Domain/Index/Queue/UpdateHandler/DataUpdateHandlerTest.php b/Tests/Unit/Domain/Index/Queue/UpdateHandler/DataUpdateHandlerTest.php index 481dd88d4..2033bd79c 100644 --- a/Tests/Unit/Domain/Index/Queue/UpdateHandler/DataUpdateHandlerTest.php +++ b/Tests/Unit/Domain/Index/Queue/UpdateHandler/DataUpdateHandlerTest.php @@ -200,29 +200,14 @@ public function handleContentElementUpdateTriggersInvalidPageProcessing(): void ]; $this->initSiteForDummyConfiguration($dummyPageRecord['uid']); - $garbageHandlerMock = $this->createMock(GarbageHandler::class); - $garbageHandlerMock - ->expects(self::once()) - ->method('collectGarbage') - ->with( - 'pages', - $dummyPageRecord['uid'] - ); - GeneralUtility::addInstance(GarbageHandler::class, $garbageHandlerMock); - $this->mountPagesUpdaterMock ->expects(self::once()) ->method('update') ->with($dummyPageRecord['uid']); $this->indexQueueMock - ->expects(self::once()) - ->method('containsItem') - ->with( - 'pages', - $dummyPageRecord['uid'] - ) - ->willReturn(true); + ->expects(self::never()) + ->method('containsItem'); $this->typoScriptConfigurationMock ->expects(self::once()) @@ -538,16 +523,6 @@ public function handleRecordUpdateTriggersInvalidRecordProcessing(): void 'pid' => self::DUMMY_PAGE_ID, ]; - $garbageHandlerMock = $this->createMock(GarbageHandler::class); - $garbageHandlerMock - ->expects(self::once()) - ->method('collectGarbage') - ->with( - 'tx_foo_bar', - $dummyRecord['uid'] - ); - GeneralUtility::addInstance(GarbageHandler::class, $garbageHandlerMock); - $this->typoScriptConfigurationMock ->expects(self::once()) ->method('getIndexQueueIsMonitoredTable') @@ -565,13 +540,8 @@ public function handleRecordUpdateTriggersInvalidRecordProcessing(): void ->willReturn([]); $this->indexQueueMock - ->expects(self::once()) - ->method('containsItem') - ->with( - 'tx_foo_bar', - $dummyRecord['uid'] - ) - ->willReturn(true); + ->expects(self::never()) + ->method('containsItem'); $this->dataUpdateHandler->handleRecordUpdate($dummyRecord['uid'], 'tx_foo_bar'); } @@ -737,13 +707,8 @@ public function handleVersionSwapAppliesInvalidPageChangesToQueue(): void ->willReturn([]); $this->indexQueueMock - ->expects(self::once()) - ->method('containsItem') - ->with( - 'pages', - $dummyPageRecord['uid'] - ) - ->willReturn(true); + ->expects(self::never()) + ->method('containsItem'); $garbageHandlerMock = $this->createMock(GarbageHandler::class); $garbageHandlerMock @@ -836,13 +801,8 @@ public function handleVersionSwapAppliesInvalidRecordChangesToQueue(): void ->willReturn([]); $this->indexQueueMock - ->expects(self::once()) - ->method('containsItem') - ->with( - 'tx_foo_bar', - $dummyRecord['uid'] - ) - ->willReturn(true); + ->expects(self::never()) + ->method('containsItem'); $garbageHandlerMock = $this->createMock(GarbageHandler::class); $garbageHandlerMock From 75799a253cbdb6e285c2f534d1bc441edde92497 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafael=20K=C3=A4hm?= Date: Thu, 28 Nov 2024 18:07:34 +0100 Subject: [PATCH 3/7] [DOCs] for release 12.0.4 Picked from: https://github.com/TYPO3-Solr/ext-solr/commit/ea50dc24060b0eb4135a56f9752df3579ecf8d7a Ports: #4115 --- Documentation/Releases/solr-release-12-0.rst | 63 +++++++++++++++++++- 1 file changed, 60 insertions(+), 3 deletions(-) diff --git a/Documentation/Releases/solr-release-12-0.rst b/Documentation/Releases/solr-release-12-0.rst index 3880e3b41..5e2cec62e 100644 --- a/Documentation/Releases/solr-release-12-0.rst +++ b/Documentation/Releases/solr-release-12-0.rst @@ -7,6 +7,41 @@ Releases 12.0 .. include:: HintAboutOutdatedChangelog.rst.txt +Release 12.0.4 +============== + +This is a maintenance release for TYPO3 12.4 LTS, containing: + +- [TASK] Use request object to retrieve query params instead of _GET by @sfroemkenjw in `#4045 `_ - Dmitry Dulepov - Elias Häußler - Eric Chavaillaz @@ -550,6 +586,8 @@ awesome community. Here are the contributors to this release. - Florian Rival - Georg Ringer - Harald Witt +- `Hendrik vom Lehn `_ +- `@hnadler `_ - Henrik Elsner - Ingo Fabbri - Jennifer Geiß @@ -558,14 +596,14 @@ awesome community. Here are the contributors to this release. - Lukas Niestroj - Marc Hirdes - Mario Lubenka -- Markus Friedrich +- `Markus Friedrich `_ - Matthias Vogel - `@n3amil / Cypelt `_ - Oliver Bartsch - Patrick Schriner - Philipp Kitzberger - Pierrick Caillon -- Rafael Kähm +- `Rafael Kähm `_ - René Maas - Roman Schilter - Sascha Nowak @@ -578,6 +616,7 @@ awesome community. Here are the contributors to this release. - Stämpfli Kommunikation - Sven Erens - Sven Teuber +- Thomas Löffler - Till Hörner - Tim Dreier - Tobias Hövelborn @@ -589,6 +628,7 @@ Also a big thank you to our partners who have already concluded one of our new d as Apache Solr EB for TYPO3 12 LTS (Feature): - .hausformat +- +Pluswerk AG - 711media websolutions GmbH - ACO Ahlmann SE & Co. KG - AVM Computersysteme Vertriebs GmbH @@ -597,6 +637,7 @@ as Apache Solr EB for TYPO3 12 LTS (Feature): - Autorité des Marchés Financiers (Québec) - b13 GmbH - Beech IT +- Bytebetrieb GmbH & Co. KG - CARL von CHIARI GmbH - clickstorm GmbH Apache Solr EB für TYPO3 12 LTS (Feature) - Connecta AG @@ -605,23 +646,32 @@ as Apache Solr EB for TYPO3 12 LTS (Feature): - CS2 AG - cyperfection GmbH - digit.ly +- DGB Rechtsschutz GmbH - DMK E-BUSINESS GmbH - DP-Medsystems AG - DSCHOY GmbH - Deutsches Literaturarchiv Marbach - EB-12LTS-FEATURE - F7 Media GmbH +- Fachagentur Nachwachsende Rohstoffe fnr.de +- Forte Digital Germany GmbH - FTI Touristik GmbH - gedacht +- Getdesigned GmbH - GPM Deutsche Gesellschaft für Projektmanagement e. V. +- Groupe Toumoro inc - HEAD acoustics GmbH +- helhum.io +- Hochschule Koblenz - Standort Remagen - in2code GmbH - Internezzo +- IW Medien GmbH - jweiland.net +- Kassenärztliche Vereinigung Rheinland-Pfalz - keeen GmbH - KONVERTO AG -- Kassenärztliche Vereinigung Rheinland-Pfalz - Kreis Euskirchen +- Kwintessens B.V. - L.N. Schaffrath DigitalMedien GmbH - LOUIS INTERNET GmbH - Leuchtfeuer Digital Marketing GmbH @@ -635,12 +685,19 @@ as Apache Solr EB for TYPO3 12 LTS (Feature): - plan2net GmbH - ProPotsdam GmbH - Québec.ca gouv.qc.ca Apache Solr EB für TYPO3 12 LTS (Feature) +- Rechnungshof Österreich - Red Dot GmbH & Co. KG +- rocket-media GmbH & Co KG +- Sandstein Neue Medien GmbH - Schoene neue kinder GmbH +- SIWA Online GmbH - Snowflake Productions GmbH Apache Solr EB für TYPO3 12 LTS (Feature) - Stadtverwaltung Villingen-Schwenningen - Stämpfli AG +- Statistik Österreich - studio ahoi - Weitenauer Schwardt GbR +- Südwestfalen IT +- Systime/Gyldendal A/S - THE BRETTINGHAMS GmbH - Typoheads GmbH - UEBERBIT GmbH From dc677e56c919b182f01459de15a6a8da51f31b0b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafael=20K=C3=A4hm?= Date: Thu, 28 Nov 2024 18:14:26 +0100 Subject: [PATCH 4/7] [DOCs] Update EXT:solr 12.0.x line in version matrix Cherry-Picked from: https://github.com/TYPO3-Solr/ext-solr/commit/27ab5cd7fe04d757572f1d715ea539d6a372b66c Ports: #4147 --- Documentation/Appendix/VersionMatrix.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/Appendix/VersionMatrix.rst b/Documentation/Appendix/VersionMatrix.rst index a75456625..9657b62c9 100644 --- a/Documentation/Appendix/VersionMatrix.rst +++ b/Documentation/Appendix/VersionMatrix.rst @@ -15,7 +15,7 @@ List of EXT:solr versions and the matching versions of Apache Solr and TYPO3 tha TYPO3 EXT:solr EXT:tika EXT:solrfal EXT:solrconsole EXT:solrdebugtools EXT:solrfluidgrouping EXT:solrmlt Apache Solr Configset ========= ========== ========== =========== =============== ================== ================================ =============== =============== ================= 13.4 13.0 (ᾱ) 13.0 (Ø) 13.0 (ᾱ) 13.0 (Ø) 13.0 (Ø) N/A (integrated in EXT:solr) 13.0 (Ø) 9.7.0¹ ext_solr_13_0_0 -12.4 12.0 12.0 12.0 12.0 12.0 N/A (integrated in EXT:solr) 12.0 (Ø) 9.6.1¹ ext_solr_12_0_0 +12.4 12.0 12.0 12.0 12.0 12.0 N/A (integrated in EXT:solr) 12.0 (Ø) 9.7.0¹ ext_solr_12_0_0 ========= ========== ========== =========== =============== ================== ================================ =============== =============== ================= | Ø - not yet available From 99ca981eedabb60b4ac9dd7432c7c0e73813b027 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafael=20K=C3=A4hm?= Date: Thu, 28 Nov 2024 18:30:25 +0100 Subject: [PATCH 5/7] [FIX] phpstan: Method UrlHelper::withQueryParameter() has parameter $value with no type specified Relates: #3995 --- Classes/System/Url/UrlHelper.php | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/Classes/System/Url/UrlHelper.php b/Classes/System/Url/UrlHelper.php index 0ef3e918e..4acb4034c 100644 --- a/Classes/System/Url/UrlHelper.php +++ b/Classes/System/Url/UrlHelper.php @@ -44,8 +44,10 @@ public function withoutQueryParameter(string $parameterName): UrlHelper /** * Add a given parameter with value to the query and create a new instance. */ - public function withQueryParameter(string $parameterName, $value): UrlHelper - { + public function withQueryParameter( + string $parameterName, + mixed $value, + ): UrlHelper { parse_str($this->query, $parameters); $parameters[$parameterName] = $value; $query = http_build_query($parameters); From f96bf3a77b1a7064e1f4883b7effedd4f498f3c4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafael=20K=C3=A4hm?= Date: Mon, 9 Sep 2024 17:14:45 +0200 Subject: [PATCH 6/7] [TASK] Remove Scrutinizer integrations on release-12.0.x Due of troubles within CI builds, the scrutinizer must be removed. Cherry-Picked from: https://github.com/TYPO3-Solr/ext-solr/commit/ac09602b4f75dac9216460cb8ed6d7775d2fdbce Ports: #4143 --- .gitattributes | 1 - .github/workflows/ci.yml | 5 ----- .scrutinizer.yml | 29 ----------------------------- Build/Test/bootstrap.sh | 2 +- Build/Test/cibuild.sh | 4 ++-- composer.json | 3 +-- 6 files changed, 4 insertions(+), 40 deletions(-) delete mode 100644 .scrutinizer.yml diff --git a/.gitattributes b/.gitattributes index 15a5c51ad..50ce0b6f2 100644 --- a/.gitattributes +++ b/.gitattributes @@ -4,7 +4,6 @@ /.github export-ignore /.gitignore export-ignore /.php-cs-fixer.php export-ignore -/.scrutinizer.yml export-ignore /.styleci.yml export-ignore /Build/ export-ignore /CONTRIBUTING.md export-ignore diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 83bd58c53..c6a450678 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -164,11 +164,6 @@ jobs: echo "Current Size of EXT:Solr build Artefacts after run: " \ && sudo du -sh "${{ env.CI_BUILD_DIRECTORY }}" \ && sudo du -sh ${{ env.CI_BUILD_DIRECTORY }}/* - - - 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 - name: Clean up run: | diff --git a/.scrutinizer.yml b/.scrutinizer.yml deleted file mode 100644 index 17a118110..000000000 --- a/.scrutinizer.yml +++ /dev/null @@ -1,29 +0,0 @@ -filter: - excluded_paths: - - 'Documentation/*' - - 'Tests/*' - - 'Resources/Public/JavaScript/*' - - 'Resources/Private/Solr/*' - paths: - - 'Classes/*' - -tools: - php_cpd: - enabled: false - - # we do this on GitHub-Actions via typo3/coding-standards - php_code_sniffer: - enabled: false - # we do this on GitHub-Actions via typo3/coding-standards - php_cs_fixer: - enabled: false - - php_mess_detector: - enabled: false - - php_pdepend: - enabled: false - - external_code_coverage: - runs: 2 - timeout: 2400 diff --git a/Build/Test/bootstrap.sh b/Build/Test/bootstrap.sh index 426fde352..685bfdaa8 100755 --- a/Build/Test/bootstrap.sh +++ b/Build/Test/bootstrap.sh @@ -74,7 +74,7 @@ fi echo "Install third party tools globally:" export PATH=$PATH:$(composer config --global home)/vendor/bin -if ! composer global require sclable/xml-lint scrutinizer/ocular --ignore-platform-reqs +if ! composer global require sclable/xml-lint --ignore-platform-reqs then "The test environment could not be installed by composer as expected. Please fix this issue." exit 1 diff --git a/Build/Test/cibuild.sh b/Build/Test/cibuild.sh index d6aae6891..537d2b0c0 100755 --- a/Build/Test/cibuild.sh +++ b/Build/Test/cibuild.sh @@ -55,7 +55,7 @@ fi echo -e "\n\n" echo "Run unit tests" -if ! composer tests:unit -- --coverage-clover=coverage.unit.clover +if ! composer tests:unit then echo "Error during running the unit tests please check and fix them" EXIT_CODE=5 @@ -95,7 +95,7 @@ fi echo -e "\n\n" echo "Run integration tests" -if ! composer tests:integration -- --coverage-clover=coverage.integration.clover +if ! composer tests:integration then echo "Error during running the integration tests please check and fix them" EXIT_CODE=6 diff --git a/composer.json b/composer.json index 8a6632e60..5135618e2 100644 --- a/composer.json +++ b/composer.json @@ -158,8 +158,7 @@ "ext-solrfal": { }, "stack-for-ci": { - "sclable/xml-lint": "*", - "scrutinizer/ocular": "*" + "sclable/xml-lint": "*" } } } From cdfaf6d31473efdda2ad3127eddbab027f81d84d Mon Sep 17 00:00:00 2001 From: thomashohn Date: Fri, 26 Jul 2024 10:33:43 +0200 Subject: [PATCH 7/7] [FIX] Re-added template variables for SearchFormViewHelper This PR re-introduces the template variables in the SearchFormViewHelper Cherry-Picked from: https://github.com/TYPO3-Solr/ext-solr/commit/8f60143e568e9bb05b030542762719a3d4586480 Fixes: #4117 Ports: #4118 --- Classes/ViewHelpers/SearchFormViewHelper.php | 22 +++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/Classes/ViewHelpers/SearchFormViewHelper.php b/Classes/ViewHelpers/SearchFormViewHelper.php index ffe5df850..002917791 100644 --- a/Classes/ViewHelpers/SearchFormViewHelper.php +++ b/Classes/ViewHelpers/SearchFormViewHelper.php @@ -79,7 +79,7 @@ public function initializeArguments(): void } /** - * Render search form tag + * Renders search form-tag * * @throws AspectNotFoundException * @noinspection PhpMissingReturnTypeInspection @@ -110,12 +110,32 @@ public function render() // @extensionScannerIgnoreLine $this->getTemplateVariableContainer()->add('q', $this->getQueryString()); // @extensionScannerIgnoreLine + $this->getTemplateVariableContainer()->add('pageUid', $pageUid); + // @extensionScannerIgnoreLine + $this->getTemplateVariableContainer()->add( + 'languageUid', + ( + $this->renderingContext + ->getAttribute(ServerRequestInterface::class) + ->getAttribute('language') + ?->getLanguageId() ?? 0 + ) + ); + // @extensionScannerIgnoreLine $this->getTemplateVariableContainer()->add('existingParameters', $this->getExistingSearchParameters()); // @extensionScannerIgnoreLine + // Added addPageAndLanguageId for compatibility + $this->getTemplateVariableContainer()->add('addPageAndLanguageId', false); $formContent = $this->renderChildren(); // @extensionScannerIgnoreLine + $this->getTemplateVariableContainer()->remove('addPageAndLanguageId'); + // @extensionScannerIgnoreLine $this->getTemplateVariableContainer()->remove('q'); // @extensionScannerIgnoreLine + $this->getTemplateVariableContainer()->remove('pageUid'); + // @extensionScannerIgnoreLine + $this->getTemplateVariableContainer()->remove('languageUid'); + // @extensionScannerIgnoreLine $this->getTemplateVariableContainer()->remove('existingParameters'); $this->tag->setContent($formContent);