Merge pull request #44 from DanielSiepmann/feature/integration-into-project

Feature/integration into project
This commit is contained in:
Daniel Siepmann 2017-05-11 09:29:15 +02:00 committed by GitHub
commit 418251facf
10 changed files with 167 additions and 37 deletions

View file

@ -40,6 +40,7 @@ class ConfigurationContainer implements ConfigurationContainerInterface
* Inject settings via ConfigurationManager. * Inject settings via ConfigurationManager.
* *
* @param ConfigurationManagerInterface $configurationManager * @param ConfigurationManagerInterface $configurationManager
* @throws NoConfigurationException
*/ */
public function injectConfigurationManager(ConfigurationManagerInterface $configurationManager) public function injectConfigurationManager(ConfigurationManagerInterface $configurationManager)
{ {
@ -48,6 +49,9 @@ class ConfigurationContainer implements ConfigurationContainerInterface
'SearchCore', 'SearchCore',
'search' 'search'
); );
if ($this->settings === null) {
throw new NoConfigurationException('Could not fetch configuration.', 1484226842);
}
} }
/** /**

View file

@ -0,0 +1,25 @@
<?php
namespace Leonmrni\SearchCore\Configuration;
/*
* Copyright (C) 2016 Daniel Siepmann <coding@daniel-siepmann.de>
*
* 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.
*/
class NoConfigurationException extends \InvalidArgumentException
{
}

View file

@ -92,12 +92,16 @@ class Elasticsearch implements Singleton, ConnectionInterface
public function deleteDocument($documentType, $identifier) public function deleteDocument($documentType, $identifier)
{ {
try {
$this->withType( $this->withType(
$documentType, $documentType,
function ($type) use ($identifier) { function ($type) use ($identifier) {
$type->deleteById($identifier); $type->deleteById($identifier);
} }
); );
} catch (\Elastica\Exception\NotFoundException $exception) {
$this->logger->debug('Tried to delete document in index, which does not exist.', [$documentType, $identifier]);
}
} }
public function updateDocument($documentType, array $document) public function updateDocument($documentType, array $document)

View file

@ -0,0 +1,25 @@
<?php
namespace Leonmrni\SearchCore\Domain\Index;
/*
* Copyright (C) 2016 Daniel Siepmann <coding@daniel-siepmann.de>
*
* 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.
*/
class NoRecordFoundException extends IndexingException
{
}

View file

@ -82,7 +82,11 @@ class TcaIndexer implements IndexerInterface
public function indexDocument($identifier) public function indexDocument($identifier)
{ {
$this->logger->info('Start indexing single record.', [$identifier]); $this->logger->info('Start indexing single record.', [$identifier]);
try {
$this->connection->addDocument($this->tcaTableService->getTableName(), $this->getRecord($identifier)); $this->connection->addDocument($this->tcaTableService->getTableName(), $this->getRecord($identifier));
} catch (NoRecordFoundException $e) {
$this->logger->info('Could not index document.', [$e->getMessage()]);
}
$this->logger->info('Finish indexing'); $this->logger->info('Finish indexing');
} }
@ -116,8 +120,11 @@ class TcaIndexer implements IndexerInterface
'', '',
(int) $offset . ',' . (int) $limit (int) $offset . ',' . (int) $limit
); );
$this->tcaTableService->filterRecordsByRootLineBlacklist($records); if ($records === null) {
return null;
}
$this->tcaTableService->filterRecordsByRootLineBlacklist($records);
foreach ($records as &$record) { foreach ($records as &$record) {
$this->tcaTableService->prepareRecord($record); $this->tcaTableService->prepareRecord($record);
} }
@ -128,6 +135,7 @@ class TcaIndexer implements IndexerInterface
/** /**
* @param int $identifier * @param int $identifier
* @return array * @return array
* @throws NoRecordFoundException If record could not be found.
*/ */
protected function getRecord($identifier) protected function getRecord($identifier)
{ {
@ -137,6 +145,13 @@ class TcaIndexer implements IndexerInterface
$this->tcaTableService->getWhereClause() $this->tcaTableService->getWhereClause()
. ' AND ' . $this->tcaTableService->getTableName() . '.uid = ' . (int) $identifier . ' AND ' . $this->tcaTableService->getTableName() . '.uid = ' . (int) $identifier
); );
if ($record === false || $record === null) {
throw new NoRecordFoundException(
'Record could not be fetched from database: "' . $identifier . '". Perhaps record is not active.',
1484225364
);
}
$this->tcaTableService->prepareRecord($record); $this->tcaTableService->prepareRecord($record);
return $record; return $record;

View file

@ -151,9 +151,9 @@ class TcaTableService
. ' AND pages.no_search = 0' . ' AND pages.no_search = 0'
; ;
$userDefinedWhere = $this->configuration->getIfExists('indexer.tca.' . $this->tableName); $userDefinedWhere = $this->configuration->getIfExists('indexer.tca.' . $this->tableName . '.additionalWhereClause');
if (is_string($userDefinedWhere)) { if (is_string($userDefinedWhere)) {
$whereClause .= $userDefinedWhere; $whereClause .= ' AND ' . $userDefinedWhere;
} }
if ($this->isBlacklistedRootLineConfigured()) { if ($this->isBlacklistedRootLineConfigured()) {
@ -236,22 +236,28 @@ class TcaTableService
* Checks whether the given record was blacklisted by root line. * Checks whether the given record was blacklisted by root line.
* This can be configured by typoscript as whole root lines can be black listed. * This can be configured by typoscript as whole root lines can be black listed.
* *
* NOTE: Does not support pages yet. We have to add a switch once we
* support them to use uid instead.
*
* @param array &$record * @param array &$record
* @return bool * @return bool
*/ */
protected function isRecordBlacklistedByRootline(array &$record) protected function isRecordBlacklistedByRootline(array &$record)
{ {
// NOTE: Does not support pages yet. We have to add a switch once we // If no rootline exists, the record is on a unreachable page and therefore blacklisted.
// support them to use uid instead. $rootline = BackendUtility::BEgetRootLine($record['pid']);
if (! $this->isBlackListedRootLineConfigured()) { if (!isset($rootline[0])) {
return false; return true;
} }
foreach (BackendUtility::BEgetRootLine($record['uid']) as $pageInRootLine) { // Check configured black list if present.
if ($this->isBlackListedRootLineConfigured()) {
foreach ($rootline as $pageInRootLine) {
if (in_array($pageInRootLine['uid'], $this->getBlackListedRootLine())) { if (in_array($pageInRootLine['uid'], $this->getBlackListedRootLine())) {
return true; return true;
} }
} }
}
return false; return false;
} }

View file

@ -20,6 +20,8 @@ namespace Leonmrni\SearchCore\Hook;
* 02110-1301, USA. * 02110-1301, USA.
*/ */
use Leonmrni\SearchCore\Configuration\NoConfigurationException;
use Leonmrni\SearchCore\Domain\Service\DataHandler as OwnDataHandler;
use TYPO3\CMS\Backend\Utility\BackendUtility; use TYPO3\CMS\Backend\Utility\BackendUtility;
use TYPO3\CMS\Core\DataHandling\DataHandler as CoreDataHandler; use TYPO3\CMS\Core\DataHandling\DataHandler as CoreDataHandler;
use TYPO3\CMS\Core\Log\LogManager; use TYPO3\CMS\Core\Log\LogManager;
@ -27,7 +29,6 @@ use TYPO3\CMS\Core\Log\Logger;
use TYPO3\CMS\Core\SingletonInterface as Singleton; use TYPO3\CMS\Core\SingletonInterface as Singleton;
use TYPO3\CMS\Core\Utility\GeneralUtility; use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3\CMS\Extbase\Object\ObjectManager; use TYPO3\CMS\Extbase\Object\ObjectManager;
use Leonmrni\SearchCore\Domain\Service\DataHandler as OwnDataHandler;
/** /**
* Wrapper for TYPO3 Hooks to internal API. * Wrapper for TYPO3 Hooks to internal API.
@ -55,8 +56,13 @@ class DataHandler implements Singleton
{ {
$this->dataHandler = $dataHandler; $this->dataHandler = $dataHandler;
if ($this->dataHandler === null) { if ($this->dataHandler === null) {
try {
$this->dataHandler = GeneralUtility::makeInstance(ObjectManager::class) $this->dataHandler = GeneralUtility::makeInstance(ObjectManager::class)
->get(OwnDataHandler::class); ->get(OwnDataHandler::class);
} catch (NoConfigurationException $e) {
// We have no configuration. That's fine, hooks will not be
// executed due to check for existing DataHandler.
}
} }
$this->logger = $logger; $this->logger = $logger;
@ -76,8 +82,8 @@ class DataHandler implements Singleton
*/ */
public function processCmdmap_deleteAction($table, $uid) public function processCmdmap_deleteAction($table, $uid)
{ {
if (! $this->shouldProcessTable($table)) { if (! $this->shouldProcessHookForTable($table)) {
$this->logger->debug('Delete not processed, cause table is not allowed.', [$table]); $this->logger->debug('Delete not processed.', [$table, $uid]);
return false; return false;
} }
@ -98,8 +104,8 @@ class DataHandler implements Singleton
*/ */
public function processDatamap_afterDatabaseOperations($status, $table, $uid, array $fieldArray, CoreDataHandler $dataHandler) public function processDatamap_afterDatabaseOperations($status, $table, $uid, array $fieldArray, CoreDataHandler $dataHandler)
{ {
if (! $this->shouldProcessTable($table)) { if (! $this->shouldProcessHookForTable($table)) {
$this->logger->debug('Database update not processed, cause table is not allowed.', [$table]); $this->logger->debug('Database update not processed.', [$table, $uid]);
return false; return false;
} }
@ -124,6 +130,24 @@ class DataHandler implements Singleton
return false; return false;
} }
/**
* @param string $table
* @return bool
*/
protected function shouldProcessHookForTable($table)
{
if ($this->dataHandler === null) {
$this->logger->debug('Datahandler could not be setup.');
return false;
}
if (! $this->shouldProcessTable($table)) {
$this->logger->debug('Table is not allowed.', [$table]);
return false;
}
return true;
}
/** /**
* @param string $table * @param string $table
* @return bool * @return bool

29
Configuration/TypoScript/constants.txt Normal file → Executable file
View file

@ -0,0 +1,29 @@
plugin {
tx_searchcore {
settings {
connections {
elasticsearch {
host = localhost
port = 9200
}
}
indexer {
tca {
# Pages are not supported yet, see
# https://github.com/DanielSiepmann/search_core/issues/24 but
# should also be added, together with additionalWhereClause
# based on doktypes
allowedTables = tt_content
tt_content {
additionalWhereClause (
pages.doktype NOT IN (3, 199)
AND tt_content.CType NOT IN ('gridelements_pi1', 'list', 'div', 'menu', 'shortcut', 'search', 'login')
)
}
}
}
}
}
}

12
Configuration/TypoScript/setup.txt Normal file → Executable file
View file

@ -3,21 +3,17 @@ plugin {
settings { settings {
connections { connections {
elasticsearch { elasticsearch {
host = localhost host = {$plugin.tx_searchcore.settings.connections.elasticsearch.host}
port = 9200 port = {$plugin.tx_searchcore.settings.connections.elasticsearch.port}
} }
} }
indexer { indexer {
tca { tca {
# Pages are not supported yet, see allowedTables = {$plugin.tx_searchcore.settings.indexer.tca.allowedTables}
# https://github.com/DanielSiepmann/search_core/issues/24 but
# should also be added, together with additionalWhereClause
# based on doktypes
allowedTables = tt_content
tt_content { tt_content {
additionalWhereClause = tt_content.CType NOT IN ('gridelements_pi1', 'list', 'div', 'menu') additionalWhereClause = {$plugin.tx_searchcore.settings.indexer.tca.tt_content.additionalWhereClause}
} }
} }
} }

View file

@ -15,14 +15,16 @@ mode of TYPO3. Do so by placing the following line at the end::
We will use references inside the extension to make the above unnecessary in the future. We will use references inside the extension to make the above unnecessary in the future.
Currently no constants are available, but this will change in the near future to make configuration
easier.
The structure is following TYPO3 Extbase conventions. All settings are placed inside of:: The structure is following TYPO3 Extbase conventions. All settings are placed inside of::
plugin.tx_searchcore.settings plugin.tx_searchcore.settings
Here is the example default configuration that's provided through static setup: Here is the example default configuration that's provided through static include:
.. literalinclude:: ../../Configuration/TypoScript/constants.txt
:language: typoscript
:linenos:
:caption: Static TypoScript Constants
.. literalinclude:: ../../Configuration/TypoScript/setup.txt .. literalinclude:: ../../Configuration/TypoScript/setup.txt
:language: typoscript :language: typoscript
@ -145,7 +147,7 @@ The following settings are available. For each setting its documented which inde
The page attribute *No Search* is also taken into account to prevent indexing records from only one The page attribute *No Search* is also taken into account to prevent indexing records from only one
page without recursion. page without recursion.
Contains a comma separated list of table names. Spaces are trimmed. Contains a comma separated list of page uids. Spaces are trimmed.
Example:: Example::