diff --git a/Classes/Configuration/ConfigurationContainer.php b/Classes/Configuration/ConfigurationContainer.php
new file mode 100644
index 0000000..f5a50b8
--- /dev/null
+++ b/Classes/Configuration/ConfigurationContainer.php
@@ -0,0 +1,83 @@
+
+ *
+ * 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 TYPO3\CMS\Extbase\Configuration\ConfigurationManagerInterface;
+
+/**
+ * Container of all configurations for extension.
+ * Always inject this to have a single place for configuration and parsing only once.
+ */
+class ConfigurationContainer implements ConfigurationContainerInterface
+{
+ /**
+ * Plaint TypoScript array from extbase for extension / plugin.
+ *
+ * @var array
+ */
+ protected $settings;
+
+ /**
+ * Inject news settings via ConfigurationManager.
+ *
+ * @param ConfigurationManagerInterface $configurationManager
+ */
+ public function injectConfigurationManager(ConfigurationManagerInterface $configurationManager)
+ {
+ $this->settings = $configurationManager->getConfiguration(
+ ConfigurationManagerInterface::CONFIGURATION_TYPE_SETTINGS,
+ 'SearchCore',
+ 'search'
+ );
+ }
+
+ /**
+ * @param string $section
+ * @param string $key
+ * @return mixed
+ * @throws InvalidArgumentException
+ */
+ public function get($section, $key)
+ {
+ if (!isset($this->settings[$section]) || !isset($this->settings[$section][$key])) {
+ throw new InvalidArgumentException(
+ 'The given configuration option does not exit.',
+ InvalidArgumentException::OPTION_DOES_NOT_EXIST
+ );
+ }
+
+ return $this->settings[$section][$key];
+ }
+
+ /**
+ * @param string $section
+ * @param string $key
+ * @return mixed|null
+ */
+ public function getIfExists($section, $key)
+ {
+ try {
+ return $this->get($section, $key);
+ } catch (InvalidArgumentException $e) {
+ return null;
+ }
+ }
+}
diff --git a/Classes/Configuration/ConfigurationContainerInterface.php b/Classes/Configuration/ConfigurationContainerInterface.php
new file mode 100644
index 0000000..2b988c5
--- /dev/null
+++ b/Classes/Configuration/ConfigurationContainerInterface.php
@@ -0,0 +1,49 @@
+
+ *
+ * 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 TYPO3\CMS\Core\SingletonInterface as Singleton;
+
+/**
+ * Container of all configurations for extension.
+ * Always inject this to have a single place for configuration and parsing only once.
+ */
+interface ConfigurationContainerInterface extends Singleton
+{
+ /**
+ * Returns the option defined by section and key.
+ * May throw an exception if it's not set.
+ *
+ * @param string $section
+ * @param string $key
+ * @return mixed
+ */
+ public function get($section, $key);
+
+ /**
+ * Same as get but will not throw an exception but return null.
+ *
+ * @param string $section
+ * @param string $key
+ * @return mixed|null
+ */
+ public function getIfExists($section, $key);
+}
diff --git a/Classes/Configuration/InvalidArgumentException.php b/Classes/Configuration/InvalidArgumentException.php
new file mode 100644
index 0000000..078485a
--- /dev/null
+++ b/Classes/Configuration/InvalidArgumentException.php
@@ -0,0 +1,29 @@
+
+ *
+ * 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 InvalidArgumentException extends \InvalidArgumentException
+{
+ const OPTION_DOES_NOT_EXIST = 1481623127;
+}
diff --git a/Classes/Connection/Elasticsearch/Connection.php b/Classes/Connection/Elasticsearch/Connection.php
index 81f31d2..e473241 100644
--- a/Classes/Connection/Elasticsearch/Connection.php
+++ b/Classes/Connection/Elasticsearch/Connection.php
@@ -20,8 +20,8 @@ namespace Leonmrni\SearchCore\Connection\Elasticsearch;
* 02110-1301, USA.
*/
+use Leonmrni\SearchCore\Configuration\ConfigurationContainerInterface;
use TYPO3\CMS\Core\SingletonInterface as Singleton;
-use TYPO3\CMS\Extbase\Configuration\ConfigurationManagerInterface;
/**
* The current connection to elasticsearch.
@@ -36,45 +36,24 @@ class Connection implements Singleton
protected $elasticaClient;
/**
- * @var array
+ * @var ConfigurationContainerInterface
*/
- protected $settings;
+ protected $configuration;
/**
* @param \Elastica\Client $elasticaClient
*/
- public function __construct(\Elastica\Client $elasticaClient = null)
- {
+ public function __construct(
+ ConfigurationContainerInterface $configuration,
+ \Elastica\Client $elasticaClient = null
+ ) {
+ $this->configuration = $configuration;
+
$this->elasticaClient = $elasticaClient;
- }
-
- /**
- * Inject news settings via ConfigurationManager.
- *
- * TODO: Refactor to configuration object to have a singleton holding the
- * settings with validation and propper getter?
- *
- * @param \TYPO3\CMS\Extbase\Configuration\ConfigurationManagerInterface $configurationManager
- */
- public function injectConfigurationManager(ConfigurationManagerInterface $configurationManager)
- {
- $this->settings = $configurationManager->getConfiguration(
- ConfigurationManagerInterface::CONFIGURATION_TYPE_SETTINGS,
- 'SearchCore',
- 'search'
- );
- }
-
- /**
- * Used to configure elasticaClient if no one was injected. Will use
- * injected settings for configuration.
- */
- public function initializeObject()
- {
if ($this->elasticaClient === null) {
$this->elasticaClient = new \Elastica\Client([
- 'host' => $this->settings['host'],
- 'port' => $this->settings['port'],
+ 'host' => $this->configuration->get('connection', 'host'),
+ 'port' => $this->configuration->get('connection', 'port'),
// TODO: Make configurable
// 'log' => 'file',
]);
diff --git a/Classes/Domain/Index/TcaIndexer/TcaTableService.php b/Classes/Domain/Index/TcaIndexer/TcaTableService.php
index 5fa8e80..b717169 100644
--- a/Classes/Domain/Index/TcaIndexer/TcaTableService.php
+++ b/Classes/Domain/Index/TcaIndexer/TcaTableService.php
@@ -20,8 +20,9 @@ namespace Leonmrni\SearchCore\Domain\Index\TcaIndexer;
* 02110-1301, USA.
*/
-use TYPO3\CMS\Backend\Utility\BackendUtility;
+use Leonmrni\SearchCore\Configuration\ConfigurationContainerInterface;
use Leonmrni\SearchCore\Domain\Index\IndexingException;
+use TYPO3\CMS\Backend\Utility\BackendUtility;
/**
* Encapsulate logik related to tca configuration.
@@ -40,6 +41,11 @@ class TcaTableService
*/
protected $tableName;
+ /**
+ * @var ConfigurationContaineInterfacer
+ */
+ protected $configuration;
+
/**
* @var \TYPO3\CMS\Core\Log\Logger
*/
@@ -55,7 +61,11 @@ class TcaTableService
$this->logger = $logManager->getLogger(__CLASS__);
}
- public function __construct($tableName)
+ /**
+ * @param string $tableName
+ * @param ConfigurationContainer $configuration
+ */
+ public function __construct($tableName, ConfigurationContainerInterface $configuration)
{
if (!isset($GLOBALS['TCA'][$tableName])) {
throw new IndexingException(
@@ -66,6 +76,7 @@ class TcaTableService
$this->tableName = $tableName;
$this->tca = &$GLOBALS['TCA'][$this->tableName];
+ $this->configuration = $configuration;
}
/**
@@ -114,6 +125,11 @@ class TcaTableService
. ' AND pages.no_search = 0'
;
+ $userDefinedWhere = $this->configuration->getIfExists('index', $this->tableName);
+ if (is_string($userDefinedWhere)) {
+ $whereClause .= $userDefinedWhere;
+ }
+
$this->logger->debug('Generated where clause.', [$this->tableName, $whereClause]);
return $whereClause;
}
diff --git a/Configuration/TypoScript/setup.txt b/Configuration/TypoScript/setup.txt
index 22c4ed8..7eeead8 100644
--- a/Configuration/TypoScript/setup.txt
+++ b/Configuration/TypoScript/setup.txt
@@ -5,6 +5,12 @@ plugin {
host = localhost
port = 9200
}
+
+ index {
+ tt_content {
+ additionalWhereClause = tt_content.CType NOT IN ('gridelements_pi1', 'list', 'div', 'menu')
+ }
+ }
}
}
}
diff --git a/Tests/Functional/Fixtures/Indexing/IndexTcaTable.xml b/Tests/Functional/Fixtures/Indexing/IndexTcaTable.xml
index 14ef723..f25a402 100644
--- a/Tests/Functional/Fixtures/Indexing/IndexTcaTable.xml
+++ b/Tests/Functional/Fixtures/Indexing/IndexTcaTable.xml
@@ -8,7 +8,7 @@
0
72
textmedia
-
+
this is the content of textmedia content element that should get indexed
0
0
diff --git a/Tests/Functional/Fixtures/Indexing/UserWhereClause.ts b/Tests/Functional/Fixtures/Indexing/UserWhereClause.ts
new file mode 100644
index 0000000..641eaf5
--- /dev/null
+++ b/Tests/Functional/Fixtures/Indexing/UserWhereClause.ts
@@ -0,0 +1,13 @@
+plugin {
+ tx_searchcore {
+ settings {
+ index {
+ tt_content {
+ additionalWhereClause = tt_content.CType NOT IN ('div')
+ }
+ }
+ }
+ }
+}
+
+module.tx_searchcore < plugin.tx_searchcore
diff --git a/Tests/Functional/Fixtures/Indexing/UserWhereClause.xml b/Tests/Functional/Fixtures/Indexing/UserWhereClause.xml
new file mode 100644
index 0000000..5d50d1c
--- /dev/null
+++ b/Tests/Functional/Fixtures/Indexing/UserWhereClause.xml
@@ -0,0 +1,42 @@
+
+
+
+ 9
+ 1
+ 1480686370
+ 1480686370
+ 0
+ 72
+ textmedia
+
+
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+
+
+
+ 10
+ 1
+ 1480686370
+ 1480686370
+ 1
+ 72
+ div
+ Not indexed by user where ctype condition
+
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+
+
diff --git a/Tests/Functional/Indexing/IndexTcaTableTest.php b/Tests/Functional/Indexing/IndexTcaTableTest.php
index cbd195c..88ba1e4 100644
--- a/Tests/Functional/Indexing/IndexTcaTableTest.php
+++ b/Tests/Functional/Indexing/IndexTcaTableTest.php
@@ -39,7 +39,7 @@ class IndexTcaTableTest extends AbstractFunctionalTestCase
/**
* @test
*/
- public function indexBasicTtContentWithoutBasicConfiguration()
+ public function indexBasicTtContent()
{
\TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(ObjectManager::class)
->get(IndexerFactory::class)
@@ -51,6 +51,12 @@ class IndexTcaTableTest extends AbstractFunctionalTestCase
$this->assertTrue($response->isOK());
$this->assertSame($response->getData()['hits']['total'], 1, 'Not exactly 1 document was indexed.');
+ $this->assertArraySubset(
+ ['_source' => ['header' => 'indexed content element']],
+ $response->getData()['hits']['hits'][0],
+ false,
+ 'Record was not indexed.'
+ );
}
/**
@@ -85,4 +91,36 @@ class IndexTcaTableTest extends AbstractFunctionalTestCase
$this->assertTrue($response->isOK());
$this->assertSame($response->getData()['hits']['total'], 1, 'Not exactly 1 document was indexed.');
}
+
+ /**
+ * @test
+ */
+ public function indexingRespectsUserWhereClause()
+ {
+ $this->setUpFrontendRootPage(1, ['EXT:search_core/Tests/Functional/Fixtures/Indexing/UserWhereClause.ts']);
+ $this->importDataSet('Tests/Functional/Fixtures/Indexing/UserWhereClause.xml');
+
+ \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(ObjectManager::class)
+ ->get(IndexerFactory::class)
+ ->getIndexer('tt_content')
+ ->index()
+ ;
+
+ $response = $this->client->request('typo3content/_search?q=*:*');
+
+ $this->assertTrue($response->isOK());
+ $this->assertSame($response->getData()['hits']['total'], 2, 'Not exactly 2 document was indexed.');
+ $this->assertArraySubset(
+ ['_source' => ['header' => 'Also indexable record']],
+ $response->getData()['hits']['hits'][0],
+ false,
+ 'Record was not indexed.'
+ );
+ $this->assertArraySubset(
+ ['_source' => ['header' => 'indexed content element']],
+ $response->getData()['hits']['hits'][1],
+ false,
+ 'Record was not indexed.'
+ );
+ }
}