diff --git a/Classes/Domain/Index/TcaIndexer.php b/Classes/Domain/Index/TcaIndexer.php index 229f9e8..0d92abc 100644 --- a/Classes/Domain/Index/TcaIndexer.php +++ b/Classes/Domain/Index/TcaIndexer.php @@ -116,6 +116,7 @@ class TcaIndexer implements IndexerInterface '', (int) $offset . ',' . (int) $limit ); + $this->tcaTableService->filterRecordsByRootLineBlacklist($records); foreach ($records as &$record) { $this->tcaTableService->prepareRecord($record); diff --git a/Classes/Domain/Index/TcaIndexer/TcaTableService.php b/Classes/Domain/Index/TcaIndexer/TcaTableService.php index cc808dc..9540c55 100644 --- a/Classes/Domain/Index/TcaIndexer/TcaTableService.php +++ b/Classes/Domain/Index/TcaIndexer/TcaTableService.php @@ -23,6 +23,7 @@ namespace Leonmrni\SearchCore\Domain\Index\TcaIndexer; use Leonmrni\SearchCore\Configuration\ConfigurationContainerInterface; use Leonmrni\SearchCore\Domain\Index\IndexingException; use TYPO3\CMS\Backend\Utility\BackendUtility; +use TYPO3\CMS\Core\Utility\GeneralUtility; /** * Encapsulate logik related to TCA configuration. @@ -104,6 +105,22 @@ class TcaTableService return $this->tableName . ' LEFT JOIN pages on ' . $this->tableName . '.pid = pages.uid'; } + /** + * Filter the given records by root line blacklist settings. + * + * @param array &$records + * @return void + */ + public function filterRecordsByRootLineBlacklist(array &$records) + { + $records = array_filter( + $records, + function ($record) { + return ! $this->isRecordBlacklistedByRootline($record); + } + ); + } + /** * Adjust record accordingly to configuration. * @param array &$record @@ -125,7 +142,7 @@ class TcaTableService */ public function getWhereClause() { - $whereClause = '1=1 ' + $whereClause = '1=1' . BackendUtility::BEenableFields($this->tableName) . BackendUtility::deleteClause($this->tableName) @@ -139,6 +156,15 @@ class TcaTableService $whereClause .= $userDefinedWhere; } + if ($this->isBlacklistedRootLineConfigured()) { + $whereClause .= ' AND pages.uid NOT IN (' + . implode(',', $this->getBlacklistedRootLine()) + . ')' + . ' AND pages.pid NOT IN (' + . implode(',', $this->getBlacklistedRootLine()) + . ')'; + } + $this->logger->debug('Generated where clause.', [$this->tableName, $whereClause]); return $whereClause; } @@ -206,4 +232,47 @@ class TcaTableService return $this->tca['columns'][$columnName]['config']; } + /** + * Checks whether the given record was blacklisted by root line. + * This can be configured by typoscript as whole root lines can be black listed. + * + * @param array &$record + * @return bool + */ + protected function isRecordBlacklistedByRootline(array &$record) + { + // NOTE: Does not support pages yet. We have to add a switch once we + // support them to use uid instead. + if (! $this->isBlackListedRootLineConfigured()) { + return false; + } + + foreach (BackendUtility::BEgetRootLine($record['uid']) as $pageInRootLine) { + if (in_array($pageInRootLine['uid'], $this->getBlackListedRootLine())) { + return true; + } + } + + return false; + } + + /** + * Checks whether any page uids are black listed. + * + * @return bool + */ + protected function isBlackListedRootLineConfigured() + { + return (bool) $this->configuration->getIfExists('index', 'rootLineBlacklist'); + } + + /** + * Get the list of black listed root line page uids. + * + * @return array + */ + protected function getBlackListedRootLine() + { + return GeneralUtility::intExplode(',', $this->configuration->getIfExists('index', 'rootLineBlacklist')); + } } diff --git a/Tests/Functional/Fixtures/Indexing/TcaIndexer/RespectRootLineBlacklist.ts b/Tests/Functional/Fixtures/Indexing/TcaIndexer/RespectRootLineBlacklist.ts new file mode 100644 index 0000000..4c134e6 --- /dev/null +++ b/Tests/Functional/Fixtures/Indexing/TcaIndexer/RespectRootLineBlacklist.ts @@ -0,0 +1,11 @@ +plugin { + tx_searchcore { + settings { + index { + rootLineBlacklist = 3 + } + } + } +} + +module.tx_searchcore < plugin.tx_searchcore diff --git a/Tests/Functional/Fixtures/Indexing/TcaIndexer/RespectRootLineBlacklist.xml b/Tests/Functional/Fixtures/Indexing/TcaIndexer/RespectRootLineBlacklist.xml new file mode 100644 index 0000000..0e9cbda --- /dev/null +++ b/Tests/Functional/Fixtures/Indexing/TcaIndexer/RespectRootLineBlacklist.xml @@ -0,0 +1,100 @@ + + + + 2 + 1 + Content here will be indexed + + + + 3 + 2 + Content here will not be indexed + + + + 4 + 3 + Content here will not be indexed either + + + + 1 + 1 + 1480686370 + 1480686370 + 0 + 72 + textmedia +
indexed content element
+ this is the content of textmedia content element that should get indexed + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 +
+ + + 2 + 2 + 1480686371 + 1480686370 + 0 + 72 + textmedia +
indexed content element
+ this is the content of textmedia content element that should get indexed + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 +
+ + + 3 + 3 + 1480686371 + 1480686370 + 0 + 72 + textmedia +
This content should not be indexed due to root line contraints
+ + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 +
+ + + 4 + 4 + 1480686371 + 1480686370 + 0 + 72 + textmedia +
This content should not be indexed due to root line contraints
+ + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 +
+
diff --git a/Tests/Functional/Indexing/TcaIndexerTest.php b/Tests/Functional/Indexing/TcaIndexerTest.php new file mode 100644 index 0000000..1610cc0 --- /dev/null +++ b/Tests/Functional/Indexing/TcaIndexerTest.php @@ -0,0 +1,86 @@ + + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +use Leonmrni\SearchCore\Configuration\ConfigurationContainerInterface; +use Leonmrni\SearchCore\Connection\Elasticsearch; +use Leonmrni\SearchCore\Domain\Index\TcaIndexer; +use Leonmrni\SearchCore\Domain\Index\TcaIndexer\RelationResolver; +use Leonmrni\SearchCore\Domain\Index\TcaIndexer\TcaTableService; +use Leonmrni\SearchCore\Tests\Functional\AbstractFunctionalTestCase; +use TYPO3\CMS\Extbase\Object\ObjectManager; + +class TcaIndexerTest extends AbstractFunctionalTestCase +{ + protected $loadDefaultTs = false; + + /** + * @test + */ + public function respectRootLineBlacklist() + { + $this->importDataSet('Tests/Functional/Fixtures/Indexing/TcaIndexer/RespectRootLineBlacklist.xml'); + $this->setUpFrontendRootPage( + 1, + array_merge( + $this->getDefaultPageTs(), + ['EXT:search_core/Tests/Functional/Fixtures/Indexing/TcaIndexer/RespectRootLineBlacklist.ts'] + ) + ); + + $objectManager = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(ObjectManager::class); + $tableName = 'tt_content'; + $tableService = $objectManager->get( + TcaTableService::class, + $tableName, + $objectManager->get(RelationResolver::class), + $objectManager->get(ConfigurationContainerInterface::class) + ); + $connection = $this->getAccessibleMock( + Elasticsearch::class, + [ + 'addDocuments', + ], + [], + '', + false + ); + + $connection->expects($this->once()) + ->method('addDocuments') + ->with( + $this->stringContains('tt_content'), + $this->callback(function ($documents) { + foreach ($documents as $document) { + // Page uids 1 and 2 are allowed while 3 and 4 are not allowed. + // Therefore only documents with page uid 1 and 2 should exist. + if (! isset($document['pid']) || ! in_array($document['pid'], [1, 2])) { + return false; + } + } + + return true; + }) + ); + + $objectManager->get(TcaIndexer::class, $tableService, $connection)->indexAllDocuments(); + } +}