Merge remote-tracking branch 'origin/develop' into feature/cms-8-support

This commit is contained in:
Daniel Siepmann 2017-08-04 13:01:33 +02:00
commit 96cfa46056
Signed by: Daniel Siepmann
GPG key ID: 33D6629915560EF4
18 changed files with 418 additions and 57 deletions

View file

@ -20,7 +20,10 @@ namespace Codappix\SearchCore\Domain\Index;
* 02110-1301, USA. * 02110-1301, USA.
*/ */
use Codappix\SearchCore\Configuration\ConfigurationContainerInterface;
use Codappix\SearchCore\Configuration\InvalidArgumentException;
use Codappix\SearchCore\Connection\ConnectionInterface; use Codappix\SearchCore\Connection\ConnectionInterface;
use \TYPO3\CMS\Core\Utility\GeneralUtility;
abstract class AbstractIndexer implements IndexerInterface abstract class AbstractIndexer implements IndexerInterface
{ {
@ -29,6 +32,16 @@ abstract class AbstractIndexer implements IndexerInterface
*/ */
protected $connection; protected $connection;
/**
* @var ConfigurationContainerInterface
*/
protected $configuration;
/**
* @var string
*/
protected $identifier = '';
/** /**
* @var \TYPO3\CMS\Core\Log\Logger * @var \TYPO3\CMS\Core\Log\Logger
*/ */
@ -44,23 +57,34 @@ abstract class AbstractIndexer implements IndexerInterface
$this->logger = $logManager->getLogger(__CLASS__); $this->logger = $logManager->getLogger(__CLASS__);
} }
public function setIdentifier($identifier)
{
$this->identifier = $identifier;
}
/** /**
* @param ConnectionInterface $connection * @param ConnectionInterface $connection
* @param ConfigurationContainerInterface $configuration
*/ */
public function __construct(ConnectionInterface $connection) public function __construct(ConnectionInterface $connection, ConfigurationContainerInterface $configuration)
{ {
$this->connection = $connection; $this->connection = $connection;
$this->configuration = $configuration;
} }
public function indexAllDocuments() public function indexAllDocuments()
{ {
$this->logger->info('Start indexing'); $this->logger->info('Start indexing');
foreach ($this->getRecordGenerator() as $records) { foreach ($this->getRecordGenerator() as $records) {
$this->logger->debug('Index records.', [$records]);
if ($records === null) { if ($records === null) {
break; break;
} }
foreach ($records as &$record) {
$this->prepareRecord($record);
}
$this->logger->debug('Index records.', [$records]);
$this->connection->addDocuments($this->getDocumentName(), $records); $this->connection->addDocuments($this->getDocumentName(), $records);
} }
$this->logger->info('Finish indexing'); $this->logger->info('Finish indexing');
@ -70,7 +94,10 @@ abstract class AbstractIndexer implements IndexerInterface
{ {
$this->logger->info('Start indexing single record.', [$identifier]); $this->logger->info('Start indexing single record.', [$identifier]);
try { try {
$this->connection->addDocument($this->getDocumentName(), $this->getRecord($identifier)); $record = $this->getRecord($identifier);
$this->prepareRecord($record);
$this->connection->addDocument($this->getDocumentName(), $record);
} catch (NoRecordFoundException $e) { } catch (NoRecordFoundException $e) {
$this->logger->info('Could not index document.', [$e->getMessage()]); $this->logger->info('Could not index document.', [$e->getMessage()]);
} }
@ -91,6 +118,32 @@ abstract class AbstractIndexer implements IndexerInterface
} }
} }
/**
* @param array &$record
*/
protected function prepareRecord(array &$record)
{
$record['search_abstract'] = '';
try {
$fieldsToUse = GeneralUtility::trimExplode(
',',
$this->configuration->get('indexing.' . $this->identifier . '.abstractFields')
);
if (!$fieldsToUse) {
return;
}
foreach ($fieldsToUse as $fieldToUse) {
if (isset($record[$fieldToUse]) && trim($record[$fieldToUse])) {
$record['search_abstract'] = trim($record[$fieldToUse]);
break;
}
}
} catch (InvalidArgumentException $e) {
return;
}
}
/** /**
* Returns the limit to use to fetch records. * Returns the limit to use to fetch records.
* *

View file

@ -83,17 +83,30 @@ class IndexerFactory implements Singleton
*/ */
protected function buildIndexer($indexerClass, $identifier) protected function buildIndexer($indexerClass, $identifier)
{ {
if ($indexerClass === TcaIndexer::class) { $indexer = null;
return $this->objectManager->get( if (is_subclass_of($indexerClass, TcaIndexer\PagesIndexer::class)
TcaIndexer::class, || $indexerClass === TcaIndexer\PagesIndexer::class
) {
$indexer = $this->objectManager->get(
$indexerClass,
$this->objectManager->get(TcaTableService::class, $identifier),
$this->objectManager->get(TcaTableService::class, 'tt_content')
);
} elseif (is_subclass_of($indexerClass, TcaIndexer::class) || $indexerClass === TcaIndexer::class) {
$indexer = $this->objectManager->get(
$indexerClass,
$this->objectManager->get(TcaTableService::class, $identifier) $this->objectManager->get(TcaTableService::class, $identifier)
); );
} elseif (class_exists($indexerClass) && in_array(IndexerInterface::class, class_implements($indexerClass))) {
$indexer = $this->objectManager->get($indexerClass);
} }
if (class_exists($indexerClass) && in_array(IndexerInterface::class, class_implements($indexerClass))) { if ($indexer === null) {
return $this->objectManager->get($indexerClass); throw new NoMatchingIndexerException('Could not find indexer: ' . $indexerClass, 1497341442);
} }
throw new NoMatchingIndexerException('Could not find indexer: ' . $indexerClass, 1497341442); $indexer->setIdentifier($identifier);
return $indexer;
} }
} }

View file

@ -40,4 +40,13 @@ interface IndexerInterface
* @return void * @return void
*/ */
public function indexDocument($identifier); public function indexDocument($identifier);
/**
* Recieves the identifier of the indexer itself.
*
* @param string $identifier
*
* @return void
*/
public function setIdentifier($identifier);
} }

View file

@ -20,6 +20,7 @@ namespace Codappix\SearchCore\Domain\Index;
* 02110-1301, USA. * 02110-1301, USA.
*/ */
use Codappix\SearchCore\Configuration\ConfigurationContainerInterface;
use Codappix\SearchCore\Connection\ConnectionInterface; use Codappix\SearchCore\Connection\ConnectionInterface;
use TYPO3\CMS\Core\Database\ConnectionPool; use TYPO3\CMS\Core\Database\ConnectionPool;
use TYPO3\CMS\Core\Database\Query\QueryBuilder; use TYPO3\CMS\Core\Database\Query\QueryBuilder;
@ -38,13 +39,16 @@ class TcaIndexer extends AbstractIndexer
/** /**
* @param TcaIndexer\TcaTableService $tcaTableService * @param TcaIndexer\TcaTableService $tcaTableService
* @param ConnectionInterface $connection * @param ConnectionInterface $connection
* @param ConfigurationContainerInterface $configuration
*/ */
public function __construct( public function __construct(
TcaIndexer\TcaTableService $tcaTableService, TcaIndexer\TcaTableService $tcaTableService,
ConnectionInterface $connection ConnectionInterface $connection,
ConfigurationContainerInterface $configuration
) { ) {
$this->tcaTableService = $tcaTableService; $this->tcaTableService = $tcaTableService;
$this->connection = $connection; $this->connection = $connection;
$this->configuration = $configuration;
} }
/** /**
@ -100,16 +104,19 @@ class TcaIndexer extends AbstractIndexer
return $this->tcaTableService->getTableName(); return $this->tcaTableService->getTableName();
} }
protected function getQuery() : QueryBuilder protected function getQuery($tcaTableService = null) : QueryBuilder
{ {
$queryBuilder = $this->getDatabaseConnection()->getQueryBuilderForTable($this->tcaTableService->getTableName()); if ($tcaTableService === null) {
$where = $this->tcaTableService->getWhereClause(); $tcaTableService = $this->tcaTableService;
$query = $queryBuilder->select(... $this->tcaTableService->getFields()) }
->from($this->tcaTableService->getTableClause()) $queryBuilder = $this->getDatabaseConnection()->getQueryBuilderForTable($tcaTableService->getTableName());
$where = $tcaTableService->getWhereClause();
$query = $queryBuilder->select(... $tcaTableService->getFields())
->from($tcaTableService->getTableClause())
->where($where->getStatement()) ->where($where->getStatement())
->setParameters($where->getParameters()); ->setParameters($where->getParameters());
foreach ($this->tcaTableService->getJoins() as $join) { foreach ($tcaTableService->getJoins() as $join) {
$query->from($join->getTable()); $query->from($join->getTable());
$query->andWhere($join->getCondition()); $query->andWhere($join->getCondition());
} }

View file

@ -0,0 +1,96 @@
<?php
namespace Codappix\SearchCore\Domain\Index\TcaIndexer;
/*
* Copyright (C) 2017 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.
*/
use Codappix\SearchCore\Configuration\ConfigurationContainerInterface;
use Codappix\SearchCore\Connection\ConnectionInterface;
use Codappix\SearchCore\Domain\Index\TcaIndexer;
/**
* Specific indexer for Pages, will basically add content of page.
*/
class PagesIndexer extends TcaIndexer
{
/**
* @var TcaTableService
*/
protected $contentTableService;
/**
* @param TcaTableService $tcaTableService
* @param TcaTableService $tcaTableService
* @param ConnectionInterface $connection
* @param ConfigurationContainerInterface $configuration
*/
public function __construct(
TcaTableService $tcaTableService,
TcaTableService $contentTableService,
ConnectionInterface $connection,
ConfigurationContainerInterface $configuration
) {
$this->tcaTableService = $tcaTableService;
$this->contentTableService = $contentTableService;
$this->connection = $connection;
$this->configuration = $configuration;
}
/**
* @param array &$record
*/
protected function prepareRecord(array &$record)
{
$possibleTitleFields = ['nav_title', 'tx_tqseo_pagetitle_rel', 'title'];
foreach ($possibleTitleFields as $searchTitleField) {
if (isset($record[$searchTitleField]) && trim($record[$searchTitleField])) {
$record['search_title'] = trim($record[$searchTitleField]);
break;
}
}
$record['content'] = $this->fetchContentForPage($record['uid']);
parent::prepareRecord($record);
}
/**
* @param int $uid
* @return string
*/
protected function fetchContentForPage($uid)
{
$contentElements = $this->getQuery($this->contentTableService)->execute()->fetchAll();
if ($contentElements === null) {
$this->logger->debug('No content for page ' . $uid);
return '';
}
$this->logger->debug('Fetched content for page ' . $uid);
$content = [];
foreach ($contentElements as $contentElement) {
$content[] = $contentElement['bodytext'];
}
// Remove Tags.
// Interpret escaped new lines and special chars.
// Trim, e.g. trailing or leading new lines.
return trim(stripcslashes(strip_tags(implode(' ', $content))));
}
}

View file

@ -143,6 +143,7 @@ class TcaTableService
{ {
$parameters = []; $parameters = [];
$whereClause = $this->getSystemWhereClause(); $whereClause = $this->getSystemWhereClause();
$userDefinedWhere = $this->configuration->getIfExists('indexing.' . $this->getTableName() . '.additionalWhereClause'); $userDefinedWhere = $this->configuration->getIfExists('indexing.' . $this->getTableName() . '.additionalWhereClause');
if (is_string($userDefinedWhere)) { if (is_string($userDefinedWhere)) {
$whereClause .= ' AND ' . $userDefinedWhere; $whereClause .= ' AND ' . $userDefinedWhere;
@ -176,11 +177,14 @@ class TcaTableService
$this->logger->debug('Generated fields.', [$this->tableName, $fields]); $this->logger->debug('Generated fields.', [$this->tableName, $fields]);
return $fields; return $fields;
return implode(', ', $fields);
} }
public function getJoins() : array public function getJoins() : array
{ {
if ($this->tableName === 'pages') {
return [];
}
return [ return [
new Join('pages', 'pages.uid = ' . $this->tableName . '.pid'), new Join('pages', 'pages.uid = ' . $this->tableName . '.pid'),
]; ];
@ -192,14 +196,19 @@ class TcaTableService
*/ */
public function getSystemWhereClause() : string public function getSystemWhereClause() : string
{ {
return '1=1' $whereClause = '1=1'
. BackendUtility::BEenableFields($this->tableName) . BackendUtility::BEenableFields($this->tableName)
. BackendUtility::deleteClause($this->tableName) . BackendUtility::deleteClause($this->tableName)
. BackendUtility::BEenableFields('pages')
. BackendUtility::deleteClause('pages')
. ' AND pages.no_search = 0' . ' AND pages.no_search = 0'
; ;
if ($this->tableName !== 'pages') {
$whereClause .= BackendUtility::BEenableFields('pages')
. BackendUtility::deleteClause('pages')
;
}
return $whereClause;
} }
/** /**

View file

@ -9,12 +9,12 @@ plugin {
} }
indexing { indexing {
# 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
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') additionalWhereClause = tt_content.CType NOT IN ('gridelements_pi1', 'list', 'div', 'menu', 'shortcut', 'search', 'login')
pages {
additionalWhereClause = pages.doktype NOT IN (3, 199, 6, 254, 255)
abstractFields = abstract, description, bodytext
} }
} }
} }

View file

@ -9,9 +9,19 @@ plugin {
} }
indexing { indexing {
# Not for direct indexing therefore no indexer.
# Used to configure tt_content fetching while indexing pages
tt_content { tt_content {
indexer = Codappix\SearchCore\Domain\Index\TcaIndexer additionalWhereClause (
additionalWhereClause = {$plugin.tx_searchcore.settings.indexing.tt_content.additionalWhereClause} tt_content.CType NOT IN ('gridelements_pi1', 'list', 'div', 'menu', 'shortcut', 'search', 'login')
AND tt_content.bodytext != ''
)
}
pages {
indexer = Codappix\SearchCore\Domain\Index\TcaIndexer\PagesIndexer
additionalWhereClause = {$plugin.tx_searchcore.settings.indexing.pages.additionalWhereClause}
abstractFields = {$plugin.tx_searchcore.settings.indexing.pages.abstractFields}
} }
} }
} }

View file

@ -125,7 +125,7 @@ The following settings are available. For each setting its documented which inde
``rootLineBlacklist`` ``rootLineBlacklist``
""""""""""""""""""""" """""""""""""""""""""
Used by: :ref:`TcaIndexer`. Used by: :ref:`TcaIndexer`, :ref:`PagesIndexer`.
Defines a blacklist of page uids. Records below any of these pages, or subpages, are not Defines a blacklist of page uids. Records below any of these pages, or subpages, are not
indexed. This allows you to define areas that should not be indexed. indexed. This allows you to define areas that should not be indexed.
@ -147,7 +147,7 @@ options are available:
``additionalWhereClause`` ``additionalWhereClause``
""""""""""""""""""""""""" """""""""""""""""""""""""
Used by: :ref:`TcaIndexer`. Used by: :ref:`TcaIndexer`, :ref:`PagesIndexer`.
Add additional SQL to where clauses to determine indexable records from the table. This way you Add additional SQL to where clauses to determine indexable records from the table. This way you
can exclude specific records like ``tt_content`` records with specific ``CType`` values or can exclude specific records like ``tt_content`` records with specific ``CType`` values or
@ -162,6 +162,26 @@ options are available:
Make sure to prefix all fields with the corresponding table name. The selection from Make sure to prefix all fields with the corresponding table name. The selection from
database will contain joins and can lead to SQL errors if a field exists in multiple tables. database will contain joins and can lead to SQL errors if a field exists in multiple tables.
.. _abstractFields:
``abstractFields``
"""""""""""""""""""""""""
Used by: :ref:`PagesIndexer`.
Define which field should be used to provide the auto generated field "search_abstract".
The fields have to exist in the record to be indexed. Therefore fields like ``content`` are also
possible.
Example::
# As last fallback we use the content of the page
plugin.tx_searchcore.settings.indexing.<identifier>.abstractFields := addToList(content)
Default::
abstract, description, bodytext
.. _mapping: .. _mapping:
``mapping`` ``mapping``

View file

@ -27,7 +27,29 @@ The indexer is configurable through the following options:
* :ref:`additionalWhereClause` * :ref:`additionalWhereClause`
.. _PagesIndexer:
PagesIndexer
------------
Provides zero configuration TYPO3 integration by using the :ref:`t3tcaref:start`. You just can
start indexing TYPO3.
The indexer will use the TCA to fetch all necessary information like relations. Currently the
implementation is very basic. In future it will also provide mapping for :ref:`Elasticsearch` and
further stuff. Also all static content from each page will be concatenated into a single field to
improve search.
The indexer is configurable through the following options:
* :ref:`allowedTables`
* :ref:`rootLineBlacklist`
* :ref:`additionalWhereClause`
* :ref:`abstractFields`
.. note:: .. note::
Not all relations are resolved yet, see :issue:`17` and :pr:`20`. Not all relations are resolved yet, see :issue:`17` and :pr:`20`.
Also the `pages`-Table is not available yet, see :issue:`24`.

View file

@ -50,10 +50,10 @@ class IndexTcaTableTest extends AbstractFunctionalTestCase
$response = $this->client->request('typo3content/_search?q=*:*'); $response = $this->client->request('typo3content/_search?q=*:*');
$this->assertTrue($response->isOK(), 'Elastica did not answer with ok code.'); $this->assertTrue($response->isOK(), 'Elastica did not answer with ok code.');
$this->assertSame($response->getData()['hits']['total'], 1, 'Not exactly 1 document was indexed.'); $this->assertSame($response->getData()['hits']['total'], 2, 'Not exactly 2 documents were indexed.');
$this->assertArraySubset( $this->assertArraySubset(
['_source' => ['header' => 'indexed content element']], ['_source' => ['header' => 'indexed content element']],
$response->getData()['hits']['hits'][0], $response->getData()['hits']['hits'][1],
false, false,
'Record was not indexed.' 'Record was not indexed.'
); );
@ -113,7 +113,7 @@ class IndexTcaTableTest extends AbstractFunctionalTestCase
$response = $this->client->request('typo3content/_search?q=*:*'); $response = $this->client->request('typo3content/_search?q=*:*');
$this->assertTrue($response->isOK(), 'Elastica did not answer with ok code.'); $this->assertTrue($response->isOK(), 'Elastica did not answer with ok code.');
$this->assertSame($response->getData()['hits']['total'], 1, 'Not exactly 1 document was indexed.'); $this->assertSame($response->getData()['hits']['total'], 2, 'Not exactly 2 documents were indexed.');
} }
/** /**
@ -136,16 +136,18 @@ class IndexTcaTableTest extends AbstractFunctionalTestCase
$response = $this->client->request('typo3content/_search?q=*:*'); $response = $this->client->request('typo3content/_search?q=*:*');
$this->assertTrue($response->isOK(), 'Elastica did not answer with ok code.'); $this->assertTrue($response->isOK(), 'Elastica did not answer with ok code.');
$this->assertSame($response->getData()['hits']['total'], 2, 'Not exactly 2 documents were indexed.'); $this->assertSame($response->getData()['hits']['total'], 3, 'Not exactly 3 documents were indexed.');
$response = $this->client->request('typo3content/_search?q=uid:11');
$this->assertArraySubset( $this->assertArraySubset(
['_source' => ['header' => 'Also indexable record']], ['_source' => ['header' => 'Also indexable record']],
$response->getData()['hits']['hits'][0], $response->getData()['hits']['hits'][0],
false, false,
'Record was not indexed.' 'Record was not indexed.'
); );
$response = $this->client->request('typo3content/_search?q=uid:6');
$this->assertArraySubset( $this->assertArraySubset(
['_source' => ['header' => 'indexed content element']], ['_source' => ['header' => 'indexed content element']],
$response->getData()['hits']['hits'][1], $response->getData()['hits']['hits'][0],
false, false,
'Record was not indexed.' 'Record was not indexed.'
); );
@ -166,12 +168,12 @@ class IndexTcaTableTest extends AbstractFunctionalTestCase
$response = $this->client->request('typo3content/_search?q=*:*'); $response = $this->client->request('typo3content/_search?q=*:*');
$this->assertTrue($response->isOK(), 'Elastica did not answer with ok code.'); $this->assertTrue($response->isOK(), 'Elastica did not answer with ok code.');
$this->assertSame($response->getData()['hits']['total'], 3, 'Not exactly 3 documents were indexed.'); $this->assertSame($response->getData()['hits']['total'], 4, 'Not exactly 4 documents were indexed.');
$response = $this->client->request('typo3content/_search?q=uid:9'); $response = $this->client->request('typo3content/_search?q=uid:11');
$this->assertArraySubset( $this->assertArraySubset(
['_source' => [ ['_source' => [
'uid' => '9', 'uid' => '11',
'CType' => 'Header', // Testing items 'CType' => 'Header', // Testing items
'categories' => ['Category 2', 'Category 1'], // Testing mm 'categories' => ['Category 2', 'Category 1'], // Testing mm
]], ]],
@ -180,10 +182,10 @@ class IndexTcaTableTest extends AbstractFunctionalTestCase
'Record was not indexed with resolved category relations to multiple values.' 'Record was not indexed with resolved category relations to multiple values.'
); );
$response = $this->client->request('typo3content/_search?q=uid:10'); $response = $this->client->request('typo3content/_search?q=uid:12');
$this->assertArraySubset( $this->assertArraySubset(
['_source' => [ ['_source' => [
'uid' => '10', 'uid' => '12',
'CType' => 'Header', 'CType' => 'Header',
'categories' => ['Category 2'], 'categories' => ['Category 2'],
]], ]],

View file

@ -12,6 +12,22 @@ plugin {
tt_content { tt_content {
indexer = Codappix\SearchCore\Domain\Index\TcaIndexer indexer = Codappix\SearchCore\Domain\Index\TcaIndexer
additionalWhereClause (
tt_content.CType NOT IN ('gridelements_pi1', 'list', 'div', 'menu', 'shortcut', 'search', 'login')
AND tt_content.bodytext != ''
)
mapping {
CType {
type = keyword
}
}
}
pages {
indexer = Codappix\SearchCore\Domain\Index\TcaIndexer\PagesIndexer
abstractFields = abstract, description, bodytext
mapping { mapping {
CType { CType {
type = keyword type = keyword

View file

@ -4,5 +4,6 @@
<uid>1</uid> <uid>1</uid>
<pid>0</pid> <pid>0</pid>
<title>Root page containing necessary TypoScript</title> <title>Root page containing necessary TypoScript</title>
<description>Used as abstract as no abstract is defined.</description>
</pages> </pages>
</dataset> </dataset>

View file

@ -60,4 +60,43 @@
<filelink_sorting>0</filelink_sorting> <filelink_sorting>0</filelink_sorting>
</tt_content> </tt_content>
<tt_content>
<uid>9</uid>
<pid>1</pid>
<tstamp>1480686370</tstamp>
<crdate>1480686370</crdate>
<hidden>0</hidden>
<sorting>72</sorting>
<CType>div</CType>
<header>not indexed due to ctype</header>
<bodytext>this is the content of div content element that should not get indexed</bodytext>
<media>0</media>
<layout>0</layout>
<deleted>0</deleted>
<cols>0</cols>
<starttime>0</starttime>
<endtime>0</endtime>
<colPos>0</colPos>
<filelink_sorting>0</filelink_sorting>
</tt_content>
<tt_content>
<uid>10</uid>
<pid>1</pid>
<tstamp>1480686370</tstamp>
<crdate>1480686370</crdate>
<hidden>0</hidden>
<sorting>72</sorting>
<CType>html</CType>
<header>Indexed without html tags</header>
<bodytext><![CDATA[<p>Some text in paragraph</p>]]></bodytext>
<media>0</media>
<layout>0</layout>
<deleted>0</deleted>
<cols>0</cols>
<starttime>0</starttime>
<endtime>0</endtime>
<colPos>0</colPos>
<filelink_sorting>0</filelink_sorting>
</tt_content>
</dataset> </dataset>

View file

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<dataset> <dataset>
<tt_content> <tt_content>
<uid>9</uid> <uid>11</uid>
<pid>1</pid> <pid>1</pid>
<tstamp>1480686370</tstamp> <tstamp>1480686370</tstamp>
<crdate>1480686370</crdate> <crdate>1480686370</crdate>
@ -22,7 +22,7 @@
</tt_content> </tt_content>
<tt_content> <tt_content>
<uid>10</uid> <uid>12</uid>
<pid>1</pid> <pid>1</pid>
<tstamp>1480686370</tstamp> <tstamp>1480686370</tstamp>
<crdate>1480686370</crdate> <crdate>1480686370</crdate>
@ -92,7 +92,7 @@
<sys_category_record_mm> <sys_category_record_mm>
<uid_local>1</uid_local> <uid_local>1</uid_local>
<uid_foreign>9</uid_foreign> <uid_foreign>11</uid_foreign>
<tablenames>tt_content</tablenames> <tablenames>tt_content</tablenames>
<fieldname>categories</fieldname> <fieldname>categories</fieldname>
<sorting>2</sorting> <sorting>2</sorting>
@ -100,7 +100,7 @@
</sys_category_record_mm> </sys_category_record_mm>
<sys_category_record_mm> <sys_category_record_mm>
<uid_local>2</uid_local> <uid_local>2</uid_local>
<uid_foreign>9</uid_foreign> <uid_foreign>11</uid_foreign>
<tablenames>tt_content</tablenames> <tablenames>tt_content</tablenames>
<fieldname>categories</fieldname> <fieldname>categories</fieldname>
<sorting>1</sorting> <sorting>1</sorting>
@ -108,7 +108,7 @@
</sys_category_record_mm> </sys_category_record_mm>
<sys_category_record_mm> <sys_category_record_mm>
<uid_local>3</uid_local> <uid_local>3</uid_local>
<uid_foreign>9</uid_foreign> <uid_foreign>11</uid_foreign>
<tablenames>tt_content</tablenames> <tablenames>tt_content</tablenames>
<fieldname>categories</fieldname> <fieldname>categories</fieldname>
<sorting>3</sorting> <sorting>3</sorting>
@ -117,7 +117,7 @@
<sys_category_record_mm> <sys_category_record_mm>
<uid_local>2</uid_local> <uid_local>2</uid_local>
<uid_foreign>10</uid_foreign> <uid_foreign>12</uid_foreign>
<tablenames>tt_content</tablenames> <tablenames>tt_content</tablenames>
<fieldname>categories</fieldname> <fieldname>categories</fieldname>
<sorting>1</sorting> <sorting>1</sorting>

View file

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<dataset> <dataset>
<tt_content> <tt_content>
<uid>9</uid> <uid>11</uid>
<pid>1</pid> <pid>1</pid>
<tstamp>1480686370</tstamp> <tstamp>1480686370</tstamp>
<crdate>1480686370</crdate> <crdate>1480686370</crdate>
@ -21,7 +21,7 @@
</tt_content> </tt_content>
<tt_content> <tt_content>
<uid>10</uid> <uid>12</uid>
<pid>1</pid> <pid>1</pid>
<tstamp>1480686370</tstamp> <tstamp>1480686370</tstamp>
<crdate>1480686370</crdate> <crdate>1480686370</crdate>

View file

@ -0,0 +1,64 @@
<?php
namespace Codappix\SearchCore\Tests\Indexing;
/*
* 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.
*/
use Codappix\SearchCore\Configuration\ConfigurationContainerInterface;
use Codappix\SearchCore\Connection\Elasticsearch;
use Codappix\SearchCore\Domain\Index\IndexerFactory;
use Codappix\SearchCore\Tests\Functional\AbstractFunctionalTestCase;
use TYPO3\CMS\Extbase\Object\ObjectManager;
class PagesIndexerTest extends AbstractFunctionalTestCase
{
/**
* @test
*/
public function pagesContainAllAdditionalInformation()
{
$this->importDataSet('Tests/Functional/Fixtures/Indexing/IndexTcaTable.xml');
$objectManager = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(ObjectManager::class);
$tableName = 'pages';
$connection = $this->getMockBuilder(Elasticsearch::class)
->setMethods(['addDocuments'])
->disableOriginalConstructor()
->getMock();
$connection->expects($this->once())
->method('addDocuments')
->with(
$this->stringContains($tableName),
$this->callback(function ($documents) {
return count($documents) === 1
&& isset($documents[0]['content']) && $documents[0]['content'] ===
'this is the content of header content element that should get indexed Some text in paragraph'
&& isset($documents[0]['search_abstract']) && $documents[0]['search_abstract'] ===
'Used as abstract as no abstract is defined.'
;
})
);
$indexer = $objectManager->get(IndexerFactory::class)->getIndexer($tableName);
$this->inject($indexer, 'connection', $connection);
$indexer->indexAllDocuments();
}
}

View file

@ -30,6 +30,14 @@ use TYPO3\CMS\Extbase\Object\ObjectManager;
class TcaIndexerTest extends AbstractFunctionalTestCase class TcaIndexerTest extends AbstractFunctionalTestCase
{ {
protected function getTypoScriptFilesForFrontendRootPage()
{
return array_merge(
parent::getTypoScriptFilesForFrontendRootPage(),
['EXT:search_core/Tests/Functional/Fixtures/Indexing/TcaIndexer/RespectRootLineBlacklist.ts']
);
}
/** /**
* @test * @test
*/ */
@ -69,12 +77,4 @@ class TcaIndexerTest extends AbstractFunctionalTestCase
$objectManager->get(TcaIndexer::class, $tableService, $connection)->indexAllDocuments(); $objectManager->get(TcaIndexer::class, $tableService, $connection)->indexAllDocuments();
} }
protected function getTypoScriptFilesForFrontendRootPage()
{
return array_merge(
parent::getTypoScriptFilesForFrontendRootPage(),
['EXT:search_core/Tests/Functional/Fixtures/Indexing/TcaIndexer/RespectRootLineBlacklist.ts']
);
}
} }