mirror of
https://github.com/Codappix/search_core.git
synced 2024-11-26 06:16:11 +01:00
Merge pull request #44 from DanielSiepmann/feature/integration-into-project
Feature/integration into project
This commit is contained in:
commit
418251facf
10 changed files with 167 additions and 37 deletions
|
@ -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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
25
Classes/Configuration/NoConfigurationException.php
Normal file
25
Classes/Configuration/NoConfigurationException.php
Normal 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
|
||||||
|
{
|
||||||
|
}
|
|
@ -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)
|
||||||
|
|
25
Classes/Domain/Index/NoRecordFoundException.php
Normal file
25
Classes/Domain/Index/NoRecordFoundException.php
Normal 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
|
||||||
|
{
|
||||||
|
}
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
29
Configuration/TypoScript/constants.txt
Normal file → Executable 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
12
Configuration/TypoScript/setup.txt
Normal file → Executable 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}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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::
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue