mirror of
https://github.com/Codappix/search_core.git
synced 2024-11-22 14:16:11 +01:00
Merge remote-tracking branch 'origin/develop' into feature/cms-8-support
This commit is contained in:
commit
3d90bad58d
78 changed files with 2066 additions and 319 deletions
21
.travis.yml
21
.travis.yml
|
@ -1,7 +1,15 @@
|
||||||
|
sudo: true
|
||||||
|
|
||||||
|
addons:
|
||||||
|
apt:
|
||||||
|
packages:
|
||||||
|
- oracle-java8-set-default
|
||||||
|
before_install:
|
||||||
|
- curl -O https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-5.2.0.deb && sudo dpkg -i --force-confnew elasticsearch-5.2.0.deb && sudo service elasticsearch start
|
||||||
|
|
||||||
language: php
|
language: php
|
||||||
|
|
||||||
php:
|
php:
|
||||||
- 5.6
|
|
||||||
- 7.0
|
- 7.0
|
||||||
- 7.1
|
- 7.1
|
||||||
|
|
||||||
|
@ -16,18 +24,12 @@ env:
|
||||||
- typo3DatabaseUsername="travis"
|
- typo3DatabaseUsername="travis"
|
||||||
- typo3DatabasePassword=""
|
- typo3DatabasePassword=""
|
||||||
matrix:
|
matrix:
|
||||||
- TYPO3_VERSION="~7.6"
|
|
||||||
- TYPO3_VERSION="~8"
|
- TYPO3_VERSION="~8"
|
||||||
- TYPO3_VERSION="dev-master"
|
- TYPO3_VERSION="dev-master"
|
||||||
|
|
||||||
matrix:
|
matrix:
|
||||||
fast_finish: true
|
fast_finish: true
|
||||||
exclude:
|
exclude:
|
||||||
# TYPO3 no longer supports 5.6
|
|
||||||
- env: TYPO3_VERSION="~8"
|
|
||||||
php: 5.6
|
|
||||||
- env: TYPO3_VERSION="dev-master"
|
|
||||||
php: 5.6
|
|
||||||
allow_failures:
|
allow_failures:
|
||||||
- env: TYPO3_VERSION="~8"
|
- env: TYPO3_VERSION="~8"
|
||||||
php: 7.0
|
php: 7.0
|
||||||
|
@ -40,11 +42,12 @@ matrix:
|
||||||
|
|
||||||
services:
|
services:
|
||||||
- mysql
|
- mysql
|
||||||
- elasticsearch
|
|
||||||
|
|
||||||
install: make install
|
install: make install
|
||||||
|
|
||||||
script: make functionalTests
|
script:
|
||||||
|
- make unitTests
|
||||||
|
- make functionalTests
|
||||||
|
|
||||||
after_script:
|
after_script:
|
||||||
- make uploadCodeCoverage
|
- make uploadCodeCoverage
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<?php
|
<?php
|
||||||
namespace Leonmrni\SearchCore\Command;
|
namespace Codappix\SearchCore\Command;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (C) 2016 Daniel Siepmann <coding@daniel-siepmann.de>
|
* Copyright (C) 2016 Daniel Siepmann <coding@daniel-siepmann.de>
|
||||||
|
@ -20,7 +20,8 @@ namespace Leonmrni\SearchCore\Command;
|
||||||
* 02110-1301, USA.
|
* 02110-1301, USA.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
use Leonmrni\SearchCore\Domain\Index\IndexerFactory;
|
use Codappix\SearchCore\Domain\Index\IndexerFactory;
|
||||||
|
use Codappix\SearchCore\Domain\Index\NoMatchingIndexerException;
|
||||||
use TYPO3\CMS\Core\Utility\GeneralUtility;
|
use TYPO3\CMS\Core\Utility\GeneralUtility;
|
||||||
use TYPO3\CMS\Extbase\Mvc\Controller\CommandController;
|
use TYPO3\CMS\Extbase\Mvc\Controller\CommandController;
|
||||||
|
|
||||||
|
@ -34,12 +35,6 @@ class IndexCommandController extends CommandController
|
||||||
*/
|
*/
|
||||||
protected $indexerFactory;
|
protected $indexerFactory;
|
||||||
|
|
||||||
/**
|
|
||||||
* @var \Leonmrni\SearchCore\Configuration\ConfigurationContainerInterface
|
|
||||||
* @inject
|
|
||||||
*/
|
|
||||||
protected $configuration;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param IndexerFactory $factory
|
* @param IndexerFactory $factory
|
||||||
*/
|
*/
|
||||||
|
@ -49,19 +44,18 @@ class IndexCommandController extends CommandController
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Will index the given table or everything.
|
* Will index the given identifier.
|
||||||
*
|
*
|
||||||
* @param string $table
|
* @param string $identifier
|
||||||
*/
|
*/
|
||||||
public function indexCommand($table)
|
public function indexCommand($identifier)
|
||||||
{
|
{
|
||||||
// TODO: Allow to index multiple tables at once?
|
|
||||||
// TODO: Also allow to index everything?
|
// TODO: Also allow to index everything?
|
||||||
if (! in_array($table, GeneralUtility::trimExplode(',', $this->configuration->get('indexer.tca.allowedTables')))) {
|
try {
|
||||||
$this->outputLine('Table is not allowed for indexing.');
|
$this->indexerFactory->getIndexer($identifier)->indexAllDocuments();
|
||||||
$this->quit(1);
|
$this->outputLine($identifier . ' was indexed.');
|
||||||
|
} catch (NoMatchingIndexerException $e) {
|
||||||
|
$this->outputLine('No indexer found for: ' . $identifier);
|
||||||
}
|
}
|
||||||
$this->indexerFactory->getIndexer($table)->indexAllDocuments();
|
|
||||||
$this->outputLine('Table was indexed.');
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<?php
|
<?php
|
||||||
namespace Leonmrni\SearchCore\Configuration;
|
namespace Codappix\SearchCore\Configuration;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (C) 2016 Daniel Siepmann <coding@daniel-siepmann.de>
|
* Copyright (C) 2016 Daniel Siepmann <coding@daniel-siepmann.de>
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<?php
|
<?php
|
||||||
namespace Leonmrni\SearchCore\Configuration;
|
namespace Codappix\SearchCore\Configuration;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (C) 2016 Daniel Siepmann <coding@daniel-siepmann.de>
|
* Copyright (C) 2016 Daniel Siepmann <coding@daniel-siepmann.de>
|
||||||
|
@ -34,6 +34,8 @@ interface ConfigurationContainerInterface extends Singleton
|
||||||
*
|
*
|
||||||
* @param string $path In dot notation. E.g. indexer.tca.allowedTables
|
* @param string $path In dot notation. E.g. indexer.tca.allowedTables
|
||||||
* @return mixed
|
* @return mixed
|
||||||
|
*
|
||||||
|
* @throws InvalidArgumentException
|
||||||
*/
|
*/
|
||||||
public function get($path);
|
public function get($path);
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<?php
|
<?php
|
||||||
namespace Leonmrni\SearchCore\Configuration;
|
namespace Codappix\SearchCore\Configuration;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (C) 2016 Daniel Siepmann <coding@daniel-siepmann.de>
|
* Copyright (C) 2016 Daniel Siepmann <coding@daniel-siepmann.de>
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<?php
|
<?php
|
||||||
namespace Leonmrni\SearchCore\Configuration;
|
namespace Codappix\SearchCore\Configuration;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (C) 2016 Daniel Siepmann <coding@daniel-siepmann.de>
|
* Copyright (C) 2016 Daniel Siepmann <coding@daniel-siepmann.de>
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<?php
|
<?php
|
||||||
namespace Leonmrni\SearchCore\Connection;
|
namespace Codappix\SearchCore\Connection;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (C) 2016 Daniel Siepmann <coding@daniel-siepmann.de>
|
* Copyright (C) 2016 Daniel Siepmann <coding@daniel-siepmann.de>
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<?php
|
<?php
|
||||||
namespace Leonmrni\SearchCore\Connection;
|
namespace Codappix\SearchCore\Connection;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (C) 2016 Daniel Siepmann <coding@daniel-siepmann.de>
|
* Copyright (C) 2016 Daniel Siepmann <coding@daniel-siepmann.de>
|
||||||
|
@ -20,7 +20,10 @@ namespace Leonmrni\SearchCore\Connection;
|
||||||
* 02110-1301, USA.
|
* 02110-1301, USA.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
use Codappix\SearchCore\Connection\Elasticsearch\SearchResult;
|
||||||
|
use Codappix\SearchCore\Domain\Search\QueryFactory;
|
||||||
use TYPO3\CMS\Core\SingletonInterface as Singleton;
|
use TYPO3\CMS\Core\SingletonInterface as Singleton;
|
||||||
|
use TYPO3\CMS\Extbase\Object\ObjectManagerInterface;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Outer wrapper to elasticsearch.
|
* Outer wrapper to elasticsearch.
|
||||||
|
@ -42,16 +45,31 @@ class Elasticsearch implements Singleton, ConnectionInterface
|
||||||
*/
|
*/
|
||||||
protected $typeFactory;
|
protected $typeFactory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var Elasticsearch\MappingFactory
|
||||||
|
*/
|
||||||
|
protected $mappingFactory;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var Elasticsearch\DocumentFactory
|
* @var Elasticsearch\DocumentFactory
|
||||||
*/
|
*/
|
||||||
protected $documentFactory;
|
protected $documentFactory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var QueryFactory
|
||||||
|
*/
|
||||||
|
protected $queryFactory;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var \TYPO3\CMS\Core\Log\Logger
|
* @var \TYPO3\CMS\Core\Log\Logger
|
||||||
*/
|
*/
|
||||||
protected $logger;
|
protected $logger;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var ObjectManagerInterface
|
||||||
|
*/
|
||||||
|
protected $objectManager;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Inject log manager to get concrete logger from it.
|
* Inject log manager to get concrete logger from it.
|
||||||
*
|
*
|
||||||
|
@ -62,22 +80,36 @@ class Elasticsearch implements Singleton, ConnectionInterface
|
||||||
$this->logger = $logManager->getLogger(__CLASS__);
|
$this->logger = $logManager->getLogger(__CLASS__);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param ObjectManagerInterface $objectManager
|
||||||
|
*/
|
||||||
|
public function injectObjectManager(ObjectManagerInterface $objectManager)
|
||||||
|
{
|
||||||
|
$this->objectManager = $objectManager;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param Elasticsearch\Connection $connection
|
* @param Elasticsearch\Connection $connection
|
||||||
* @param Elasticsearch\IndexFactory $indexFactory
|
* @param Elasticsearch\IndexFactory $indexFactory
|
||||||
* @param Elasticsearch\TypeFactory $typeFactory
|
* @param Elasticsearch\TypeFactory $typeFactory
|
||||||
|
* @param Elasticsearch\MappingFactory $mappingFactory
|
||||||
* @param Elasticsearch\DocumentFactory $documentFactory
|
* @param Elasticsearch\DocumentFactory $documentFactory
|
||||||
|
* @param QueryFactory $queryFactory
|
||||||
*/
|
*/
|
||||||
public function __construct(
|
public function __construct(
|
||||||
Elasticsearch\Connection $connection,
|
Elasticsearch\Connection $connection,
|
||||||
Elasticsearch\IndexFactory $indexFactory,
|
Elasticsearch\IndexFactory $indexFactory,
|
||||||
Elasticsearch\TypeFactory $typeFactory,
|
Elasticsearch\TypeFactory $typeFactory,
|
||||||
Elasticsearch\DocumentFactory $documentFactory
|
Elasticsearch\MappingFactory $mappingFactory,
|
||||||
|
Elasticsearch\DocumentFactory $documentFactory,
|
||||||
|
QueryFactory $queryFactory
|
||||||
) {
|
) {
|
||||||
$this->connection = $connection;
|
$this->connection = $connection;
|
||||||
$this->indexFactory = $indexFactory;
|
$this->indexFactory = $indexFactory;
|
||||||
$this->typeFactory = $typeFactory;
|
$this->typeFactory = $typeFactory;
|
||||||
|
$this->mappingFactory = $mappingFactory;
|
||||||
$this->documentFactory = $documentFactory;
|
$this->documentFactory = $documentFactory;
|
||||||
|
$this->queryFactory = $queryFactory;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function addDocument($documentType, array $document)
|
public function addDocument($documentType, array $document)
|
||||||
|
@ -133,6 +165,13 @@ class Elasticsearch implements Singleton, ConnectionInterface
|
||||||
protected function withType($documentType, callable $callback)
|
protected function withType($documentType, callable $callback)
|
||||||
{
|
{
|
||||||
$type = $this->getType($documentType);
|
$type = $this->getType($documentType);
|
||||||
|
// TODO: Check whether it's to heavy to send it so often e.g. for every single document.
|
||||||
|
// Perhaps add command controller to submit mapping?!
|
||||||
|
// Also it's not possible to change mapping without deleting index first.
|
||||||
|
// Mattes told about a solution.
|
||||||
|
// So command looks like the best way so far, except we manage mattes solution.
|
||||||
|
// Still then this should be done once. So perhaps singleton which tracks state and does only once?
|
||||||
|
$this->mappingFactory->getMapping($type)->send();
|
||||||
$callback($type);
|
$callback($type);
|
||||||
$type->getIndex()->refresh();
|
$type->getIndex()->refresh();
|
||||||
}
|
}
|
||||||
|
@ -140,7 +179,7 @@ class Elasticsearch implements Singleton, ConnectionInterface
|
||||||
/**
|
/**
|
||||||
* @param SearchRequestInterface $searchRequest
|
* @param SearchRequestInterface $searchRequest
|
||||||
*
|
*
|
||||||
* @return \Elastica\ResultSet
|
* @return SearchResultInterface
|
||||||
*/
|
*/
|
||||||
public function search(SearchRequestInterface $searchRequest)
|
public function search(SearchRequestInterface $searchRequest)
|
||||||
{
|
{
|
||||||
|
@ -148,10 +187,9 @@ class Elasticsearch implements Singleton, ConnectionInterface
|
||||||
|
|
||||||
$search = new \Elastica\Search($this->connection->getClient());
|
$search = new \Elastica\Search($this->connection->getClient());
|
||||||
$search->addIndex('typo3content');
|
$search->addIndex('typo3content');
|
||||||
|
$search->setQuery($this->queryFactory->create($searchRequest));
|
||||||
|
|
||||||
// TODO: Return wrapped result to implement our interface.
|
return $this->objectManager->get(SearchResult::class, $search->search());
|
||||||
// Also update php doc to reflect the change.
|
|
||||||
return $search->search('"' . $searchRequest->getSearchTerm() . '"');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<?php
|
<?php
|
||||||
namespace Leonmrni\SearchCore\Connection\Elasticsearch;
|
namespace Codappix\SearchCore\Connection\Elasticsearch;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (C) 2016 Daniel Siepmann <coding@daniel-siepmann.de>
|
* Copyright (C) 2016 Daniel Siepmann <coding@daniel-siepmann.de>
|
||||||
|
@ -20,7 +20,7 @@ namespace Leonmrni\SearchCore\Connection\Elasticsearch;
|
||||||
* 02110-1301, USA.
|
* 02110-1301, USA.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
use Leonmrni\SearchCore\Configuration\ConfigurationContainerInterface;
|
use Codappix\SearchCore\Configuration\ConfigurationContainerInterface;
|
||||||
use TYPO3\CMS\Core\SingletonInterface as Singleton;
|
use TYPO3\CMS\Core\SingletonInterface as Singleton;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<?php
|
<?php
|
||||||
namespace Leonmrni\SearchCore\Connection\Elasticsearch;
|
namespace Codappix\SearchCore\Connection\Elasticsearch;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (C) 2016 Daniel Siepmann <coding@daniel-siepmann.de>
|
* Copyright (C) 2016 Daniel Siepmann <coding@daniel-siepmann.de>
|
||||||
|
|
93
Classes/Connection/Elasticsearch/Facet.php
Normal file
93
Classes/Connection/Elasticsearch/Facet.php
Normal file
|
@ -0,0 +1,93 @@
|
||||||
|
<?php
|
||||||
|
namespace Codappix\SearchCore\Connection\Elasticsearch;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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\FacetInterface;
|
||||||
|
|
||||||
|
class Facet implements FacetInterface
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
protected $name = '';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
protected $field = '';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
protected $buckets = [];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var array<FacetOption>
|
||||||
|
*/
|
||||||
|
protected $options = [];
|
||||||
|
|
||||||
|
public function __construct($name, array $aggregation, ConfigurationContainerInterface $configuration)
|
||||||
|
{
|
||||||
|
$this->name = $name;
|
||||||
|
$this->buckets = $aggregation['buckets'];
|
||||||
|
$this->field = $configuration->getIfExists('searching.facets.' . $this->name . '.field') ?: '';
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getName()
|
||||||
|
{
|
||||||
|
return $this->name;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getField()
|
||||||
|
{
|
||||||
|
return $this->field;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns all possible options for this facet.
|
||||||
|
*
|
||||||
|
* @return array<FacetOptionInterface>
|
||||||
|
*/
|
||||||
|
public function getOptions()
|
||||||
|
{
|
||||||
|
$this->initOptions();
|
||||||
|
|
||||||
|
return $this->options;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function initOptions()
|
||||||
|
{
|
||||||
|
if ($this->options !== []) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($this->buckets as $bucket) {
|
||||||
|
$this->options[] = new FacetOption($bucket);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
61
Classes/Connection/Elasticsearch/FacetOption.php
Normal file
61
Classes/Connection/Elasticsearch/FacetOption.php
Normal file
|
@ -0,0 +1,61 @@
|
||||||
|
<?php
|
||||||
|
namespace Codappix\SearchCore\Connection\Elasticsearch;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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\Connection\FacetOptionInterface;
|
||||||
|
|
||||||
|
class FacetOption implements FacetOptionInterface
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
protected $name = '';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var int
|
||||||
|
*/
|
||||||
|
protected $count = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param array $bucket
|
||||||
|
*/
|
||||||
|
public function __construct(array $bucket)
|
||||||
|
{
|
||||||
|
$this->name = $bucket['key'];
|
||||||
|
$this->count = $bucket['doc_count'];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getName()
|
||||||
|
{
|
||||||
|
return $this->name;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return int
|
||||||
|
*/
|
||||||
|
public function getCount()
|
||||||
|
{
|
||||||
|
return $this->count;
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,5 +1,5 @@
|
||||||
<?php
|
<?php
|
||||||
namespace Leonmrni\SearchCore\Connection\Elasticsearch;
|
namespace Codappix\SearchCore\Connection\Elasticsearch;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (C) 2016 Daniel Siepmann <coding@daniel-siepmann.de>
|
* Copyright (C) 2016 Daniel Siepmann <coding@daniel-siepmann.de>
|
||||||
|
|
73
Classes/Connection/Elasticsearch/MappingFactory.php
Normal file
73
Classes/Connection/Elasticsearch/MappingFactory.php
Normal file
|
@ -0,0 +1,73 @@
|
||||||
|
<?php
|
||||||
|
namespace Codappix\SearchCore\Connection\Elasticsearch;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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\Configuration\InvalidArgumentException;
|
||||||
|
use TYPO3\CMS\Core\SingletonInterface as Singleton;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Factory to get mappings.
|
||||||
|
*/
|
||||||
|
class MappingFactory implements Singleton
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var ConfigurationContainerInterface
|
||||||
|
*/
|
||||||
|
protected $configuration;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param ConfigurationContainerInterface $configuration
|
||||||
|
*/
|
||||||
|
public function __construct(ConfigurationContainerInterface $configuration)
|
||||||
|
{
|
||||||
|
$this->configuration = $configuration;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get an mapping based on type.
|
||||||
|
*
|
||||||
|
* @param \Elastica\Type $type
|
||||||
|
*
|
||||||
|
* @return \Elastica\Mapping
|
||||||
|
*/
|
||||||
|
public function getMapping(\Elastica\Type $type)
|
||||||
|
{
|
||||||
|
$mapping = new \Elastica\Type\Mapping();
|
||||||
|
$mapping->setType($type);
|
||||||
|
$mapping->setProperties($this->getConfiguration($type->getName()));
|
||||||
|
|
||||||
|
return $mapping;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $identifier
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
protected function getConfiguration($identifier)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
return $this->configuration->get('indexing.' . $identifier . '.mapping');
|
||||||
|
} catch (InvalidArgumentException $e) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
56
Classes/Connection/Elasticsearch/ResultItem.php
Normal file
56
Classes/Connection/Elasticsearch/ResultItem.php
Normal file
|
@ -0,0 +1,56 @@
|
||||||
|
<?php
|
||||||
|
namespace Codappix\SearchCore\Connection\Elasticsearch;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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\Connection\ResultItemInterface;
|
||||||
|
|
||||||
|
class ResultItem implements ResultItemInterface
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
protected $data = [];
|
||||||
|
|
||||||
|
public function __construct(\Elastica\Result $result)
|
||||||
|
{
|
||||||
|
$this->data = $result->getData();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function offsetExists($offset)
|
||||||
|
{
|
||||||
|
return isset($this->data[$offset]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function offsetGet($offset)
|
||||||
|
{
|
||||||
|
return $this->data[$offset];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function offsetSet($offset, $value)
|
||||||
|
{
|
||||||
|
throw new \BadMethodCallException('It\'s not possible to change the search result.', 1499179077);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function offsetUnset($offset)
|
||||||
|
{
|
||||||
|
throw new \BadMethodCallException('It\'s not possible to change the search result.', 1499179077);
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,5 +1,5 @@
|
||||||
<?php
|
<?php
|
||||||
namespace Leonmrni\SearchCore\Connection\Elasticsearch;
|
namespace Codappix\SearchCore\Connection\Elasticsearch;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (C) 2016 Daniel Siepmann <coding@daniel-siepmann.de>
|
* Copyright (C) 2016 Daniel Siepmann <coding@daniel-siepmann.de>
|
||||||
|
@ -20,12 +20,127 @@ namespace Leonmrni\SearchCore\Connection\Elasticsearch;
|
||||||
* 02110-1301, USA.
|
* 02110-1301, USA.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
use Leonmrni\SearchCore\Connection\SearchResultInterface;
|
use Codappix\SearchCore\Connection\FacetInterface;
|
||||||
|
use Codappix\SearchCore\Connection\ResultItemInterface;
|
||||||
|
use Codappix\SearchCore\Connection\SearchResultInterface;
|
||||||
|
use TYPO3\CMS\Extbase\Object\ObjectManagerInterface;
|
||||||
|
|
||||||
/**
|
class SearchResult implements SearchResultInterface
|
||||||
*
|
|
||||||
*/
|
|
||||||
class SearchResult extends \Elastica\SearchResult implements SearchResultInterface
|
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* @var \Elastica\ResultSet
|
||||||
|
*/
|
||||||
|
protected $result;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var array<FacetInterface>
|
||||||
|
*/
|
||||||
|
protected $facets = [];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var array<ResultItemInterface>
|
||||||
|
*/
|
||||||
|
protected $results = [];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var ObjectManagerInterface
|
||||||
|
*/
|
||||||
|
protected $objectManager;
|
||||||
|
|
||||||
|
public function __construct(\Elastica\ResultSet $result, ObjectManagerInterface $objectManager)
|
||||||
|
{
|
||||||
|
$this->result = $result;
|
||||||
|
$this->objectManager = $objectManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return array<ResultItemInterface>
|
||||||
|
*/
|
||||||
|
public function getResults()
|
||||||
|
{
|
||||||
|
$this->initResults();
|
||||||
|
|
||||||
|
return $this->results;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return all facets, if any.
|
||||||
|
*
|
||||||
|
* @return array<FacetIterface>
|
||||||
|
*/
|
||||||
|
public function getFacets()
|
||||||
|
{
|
||||||
|
$this->initFacets();
|
||||||
|
|
||||||
|
return $this->facets;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the total sum of matching results.
|
||||||
|
*
|
||||||
|
* @return int
|
||||||
|
*/
|
||||||
|
public function getTotalCount()
|
||||||
|
{
|
||||||
|
return $this->result->getTotalHits();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Countable - Interface
|
||||||
|
/**
|
||||||
|
* Returns the total sum of results contained in this result.
|
||||||
|
*
|
||||||
|
* @return int
|
||||||
|
*/
|
||||||
|
public function count()
|
||||||
|
{
|
||||||
|
return $this->result->count();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Iterator - Interface
|
||||||
|
public function current()
|
||||||
|
{
|
||||||
|
return $this->result->current();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function next()
|
||||||
|
{
|
||||||
|
return $this->result->next();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function key()
|
||||||
|
{
|
||||||
|
return $this->result->key();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function valid()
|
||||||
|
{
|
||||||
|
return $this->result->valid();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function rewind()
|
||||||
|
{
|
||||||
|
$this->result->rewind();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function initResults()
|
||||||
|
{
|
||||||
|
if ($this->results !== []) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($this->result->getResults() as $result) {
|
||||||
|
$this->results[] = new ResultItem($result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function initFacets()
|
||||||
|
{
|
||||||
|
if ($this->facets !== [] || !$this->result->hasAggregations()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($this->result->getAggregations() as $aggregationName => $aggregation) {
|
||||||
|
$this->facets[] = $this->objectManager->get(Facet::class, $aggregationName, $aggregation);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<?php
|
<?php
|
||||||
namespace Leonmrni\SearchCore\Connection\Elasticsearch;
|
namespace Codappix\SearchCore\Connection\Elasticsearch;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (C) 2016 Daniel Siepmann <coding@daniel-siepmann.de>
|
* Copyright (C) 2016 Daniel Siepmann <coding@daniel-siepmann.de>
|
||||||
|
|
39
Classes/Connection/FacetInterface.php
Normal file
39
Classes/Connection/FacetInterface.php
Normal file
|
@ -0,0 +1,39 @@
|
||||||
|
<?php
|
||||||
|
namespace Codappix\SearchCore\Connection;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A single facet, e.g. keyword based.
|
||||||
|
*/
|
||||||
|
interface FacetInterface
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getName();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns all possible options for this facet.
|
||||||
|
*
|
||||||
|
* @return array<FacetOptionInterface>
|
||||||
|
*/
|
||||||
|
public function getOptions();
|
||||||
|
}
|
42
Classes/Connection/FacetOptionInterface.php
Normal file
42
Classes/Connection/FacetOptionInterface.php
Normal file
|
@ -0,0 +1,42 @@
|
||||||
|
<?php
|
||||||
|
namespace Codappix\SearchCore\Connection;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A single possible option of a facet.
|
||||||
|
*/
|
||||||
|
interface FacetOptionInterface
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Returns the name of this option. Equivalent
|
||||||
|
* to value used for filtering.
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getName();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the number of found results for this option.
|
||||||
|
*
|
||||||
|
* @return int
|
||||||
|
*/
|
||||||
|
public function getCount();
|
||||||
|
}
|
42
Classes/Connection/FacetRequestInterface.php
Normal file
42
Classes/Connection/FacetRequestInterface.php
Normal file
|
@ -0,0 +1,42 @@
|
||||||
|
<?php
|
||||||
|
namespace Codappix\SearchCore\Connection;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used to request facets / aggregates from connection.
|
||||||
|
*/
|
||||||
|
interface FacetRequestInterface
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* The identifier of the facet, used as key in arrays and to get the facet
|
||||||
|
* from search request, etc.
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getIdentifier();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The field to use for facet building.
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getField();
|
||||||
|
}
|
29
Classes/Connection/ResultItemInterface.php
Normal file
29
Classes/Connection/ResultItemInterface.php
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
<?php
|
||||||
|
namespace Codappix\SearchCore\Connection;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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 ArrayAccess to enable retrieval of information in fluid.
|
||||||
|
*/
|
||||||
|
interface ResultItemInterface extends \ArrayAccess
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
|
@ -1,5 +1,5 @@
|
||||||
<?php
|
<?php
|
||||||
namespace Leonmrni\SearchCore\Connection;
|
namespace Codappix\SearchCore\Connection;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (C) 2016 Daniel Siepmann <coding@daniel-siepmann.de>
|
* Copyright (C) 2016 Daniel Siepmann <coding@daniel-siepmann.de>
|
||||||
|
@ -31,4 +31,14 @@ interface SearchRequestInterface
|
||||||
* @return string
|
* @return string
|
||||||
*/
|
*/
|
||||||
public function getSearchTerm();
|
public function getSearchTerm();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function hasFilter();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function getFilter();
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<?php
|
<?php
|
||||||
namespace Leonmrni\SearchCore\Connection;
|
namespace Codappix\SearchCore\Connection;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (C) 2016 Daniel Siepmann <coding@daniel-siepmann.de>
|
* Copyright (C) 2016 Daniel Siepmann <coding@daniel-siepmann.de>
|
||||||
|
@ -21,9 +21,35 @@ namespace Leonmrni\SearchCore\Connection;
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
* A search result.
|
||||||
*/
|
*/
|
||||||
interface SearchResultInterface extends \Iterator, \Countable, \ArrayAccess
|
interface SearchResultInterface extends \Iterator, \Countable
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* @return array<ResultItemInterface>
|
||||||
|
*/
|
||||||
|
public function getResults();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return all facets, if any.
|
||||||
|
*
|
||||||
|
* @return array<FacetIterface>
|
||||||
|
*/
|
||||||
|
public function getFacets();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the total sum of matching results.
|
||||||
|
*
|
||||||
|
* @return int
|
||||||
|
*/
|
||||||
|
public function getTotalCount();
|
||||||
|
|
||||||
|
// Countable - Interface
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the total sum of results contained in this result.
|
||||||
|
*
|
||||||
|
* @return int
|
||||||
|
*/
|
||||||
|
public function count();
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<?php
|
<?php
|
||||||
namespace Leonmrni\SearchCore\Controller;
|
namespace Codappix\SearchCore\Controller;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (C) 2016 Daniel Siepmann <coding@daniel-siepmann.de>
|
* Copyright (C) 2016 Daniel Siepmann <coding@daniel-siepmann.de>
|
||||||
|
@ -20,8 +20,8 @@ namespace Leonmrni\SearchCore\Controller;
|
||||||
* 02110-1301, USA.
|
* 02110-1301, USA.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
use Leonmrni\SearchCore\Domain\Model\SearchRequest;
|
use Codappix\SearchCore\Domain\Model\SearchRequest;
|
||||||
use Leonmrni\SearchCore\Domain\Search\SearchService;
|
use Codappix\SearchCore\Domain\Search\SearchService;
|
||||||
use TYPO3\CMS\Extbase\Mvc\Controller\ActionController;
|
use TYPO3\CMS\Extbase\Mvc\Controller\ActionController;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
113
Classes/Domain/Index/AbstractIndexer.php
Normal file
113
Classes/Domain/Index/AbstractIndexer.php
Normal file
|
@ -0,0 +1,113 @@
|
||||||
|
<?php
|
||||||
|
namespace Codappix\SearchCore\Domain\Index;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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\Connection\ConnectionInterface;
|
||||||
|
|
||||||
|
abstract class AbstractIndexer implements IndexerInterface
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var ConnectionInterface
|
||||||
|
*/
|
||||||
|
protected $connection;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var \TYPO3\CMS\Core\Log\Logger
|
||||||
|
*/
|
||||||
|
protected $logger;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Inject log manager to get concrete logger from it.
|
||||||
|
*
|
||||||
|
* @param \TYPO3\CMS\Core\Log\LogManager $logManager
|
||||||
|
*/
|
||||||
|
public function injectLogger(\TYPO3\CMS\Core\Log\LogManager $logManager)
|
||||||
|
{
|
||||||
|
$this->logger = $logManager->getLogger(__CLASS__);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param ConnectionInterface $connection
|
||||||
|
*/
|
||||||
|
public function __construct(ConnectionInterface $connection)
|
||||||
|
{
|
||||||
|
$this->connection = $connection;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function indexAllDocuments()
|
||||||
|
{
|
||||||
|
$this->logger->info('Start indexing');
|
||||||
|
foreach ($this->getRecordGenerator() as $records) {
|
||||||
|
$this->logger->debug('Index records.', [$records]);
|
||||||
|
if ($records === null) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->connection->addDocuments($this->getDocumentName(), $records);
|
||||||
|
}
|
||||||
|
$this->logger->info('Finish indexing');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function indexDocument($identifier)
|
||||||
|
{
|
||||||
|
$this->logger->info('Start indexing single record.', [$identifier]);
|
||||||
|
try {
|
||||||
|
$this->connection->addDocument($this->getDocumentName(), $this->getRecord($identifier));
|
||||||
|
} catch (NoRecordFoundException $e) {
|
||||||
|
$this->logger->info('Could not index document.', [$e->getMessage()]);
|
||||||
|
}
|
||||||
|
$this->logger->info('Finish indexing');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return \Generator
|
||||||
|
*/
|
||||||
|
protected function getRecordGenerator()
|
||||||
|
{
|
||||||
|
$offset = 0;
|
||||||
|
// TODO: Make configurable.
|
||||||
|
$limit = 50;
|
||||||
|
|
||||||
|
while (($records = $this->getRecords($offset, $limit)) !== []) {
|
||||||
|
yield $records;
|
||||||
|
$offset += $limit;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param int $offset
|
||||||
|
* @param int $limit
|
||||||
|
* @return array|null
|
||||||
|
*/
|
||||||
|
abstract protected function getRecords($offset, $limit);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param int $identifier
|
||||||
|
* @return array
|
||||||
|
* @throws NoRecordFoundException If record could not be found.
|
||||||
|
*/
|
||||||
|
abstract protected function getRecord($identifier);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
abstract protected function getDocumentName();
|
||||||
|
}
|
|
@ -1,5 +1,5 @@
|
||||||
<?php
|
<?php
|
||||||
namespace Leonmrni\SearchCore\Domain\Index;
|
namespace Codappix\SearchCore\Domain\Index;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (C) 2016 Daniel Siepmann <coding@daniel-siepmann.de>
|
* Copyright (C) 2016 Daniel Siepmann <coding@daniel-siepmann.de>
|
||||||
|
@ -20,6 +20,11 @@ namespace Leonmrni\SearchCore\Domain\Index;
|
||||||
* 02110-1301, USA.
|
* 02110-1301, USA.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
use Codappix\SearchCore\Configuration\ConfigurationContainerInterface;
|
||||||
|
use Codappix\SearchCore\Configuration\InvalidArgumentException;
|
||||||
|
use Codappix\SearchCore\Domain\Index\IndexerInterface;
|
||||||
|
use Codappix\SearchCore\Domain\Index\TcaIndexer;
|
||||||
|
use Codappix\SearchCore\Domain\Index\TcaIndexer\TcaTableService;
|
||||||
use TYPO3\CMS\Core\SingletonInterface as Singleton;
|
use TYPO3\CMS\Core\SingletonInterface as Singleton;
|
||||||
use TYPO3\CMS\Extbase\Object\ObjectManagerInterface;
|
use TYPO3\CMS\Extbase\Object\ObjectManagerInterface;
|
||||||
|
|
||||||
|
@ -34,27 +39,61 @@ class IndexerFactory implements Singleton
|
||||||
protected $objectManager;
|
protected $objectManager;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param ObjectManagerInterface $objectManager
|
* @var ConfigurationContainerInterface
|
||||||
*/
|
*/
|
||||||
public function __construct(ObjectManagerInterface $objectManager)
|
protected $configuration;
|
||||||
{
|
|
||||||
|
/**
|
||||||
|
* @param ObjectManagerInterface $objectManager
|
||||||
|
* @param ConfigurationContainerInterface $configuration
|
||||||
|
*/
|
||||||
|
public function __construct(
|
||||||
|
ObjectManagerInterface $objectManager,
|
||||||
|
ConfigurationContainerInterface $configuration
|
||||||
|
) {
|
||||||
$this->objectManager = $objectManager;
|
$this->objectManager = $objectManager;
|
||||||
|
$this->configuration = $configuration;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param string $tableName
|
* @param string $identifier
|
||||||
*
|
*
|
||||||
* @return IndexerInterface
|
* @return IndexerInterface
|
||||||
|
* @throws NoMatchingIndexer
|
||||||
*/
|
*/
|
||||||
public function getIndexer($tableName)
|
public function getIndexer($identifier)
|
||||||
{
|
{
|
||||||
// This is the place to use configuration to return different indexer.
|
try {
|
||||||
|
return $this->buildIndexer($this->configuration->get('indexing.' . $identifier . '.indexer'), $identifier);
|
||||||
|
} catch (NoMatchingIndexerException $e) {
|
||||||
|
// Nothing to do, we throw exception below
|
||||||
|
} catch (InvalidArgumentException $e) {
|
||||||
|
// Nothing to do, we throw exception below
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new NoMatchingIndexerException('Could not find an indexer for ' . $identifier, 1497341442);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $indexerClass
|
||||||
|
* @param string $identifier
|
||||||
|
*
|
||||||
|
* @return IndexerInterface
|
||||||
|
* @throws NoMatchingIndexer
|
||||||
|
*/
|
||||||
|
protected function buildIndexer($indexerClass, $identifier)
|
||||||
|
{
|
||||||
|
if ($indexerClass === TcaIndexer::class) {
|
||||||
return $this->objectManager->get(
|
return $this->objectManager->get(
|
||||||
TcaIndexer::Class,
|
TcaIndexer::class,
|
||||||
$this->objectManager->get(
|
$this->objectManager->get(TcaTableService::class, $identifier)
|
||||||
TcaIndexer\TcaTableService::class,
|
|
||||||
$tableName
|
|
||||||
)
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (class_exists($indexerClass) && in_array(IndexerInterface::class, class_implements($indexerClass))) {
|
||||||
|
return $this->objectManager->get($indexerClass);
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new NoMatchingIndexerException('Could not find indexer: ' . $indexerClass, 1497341442);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<?php
|
<?php
|
||||||
namespace Leonmrni\SearchCore\Domain\Index;
|
namespace Codappix\SearchCore\Domain\Index;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (C) 2016 Daniel Siepmann <coding@daniel-siepmann.de>
|
* Copyright (C) 2016 Daniel Siepmann <coding@daniel-siepmann.de>
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<?php
|
<?php
|
||||||
namespace Leonmrni\SearchCore\Domain\Index;
|
namespace Codappix\SearchCore\Domain\Index;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (C) 2016 Daniel Siepmann <coding@daniel-siepmann.de>
|
* Copyright (C) 2016 Daniel Siepmann <coding@daniel-siepmann.de>
|
||||||
|
|
25
Classes/Domain/Index/NoMatchingIndexerException.php
Normal file
25
Classes/Domain/Index/NoMatchingIndexerException.php
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
<?php
|
||||||
|
namespace Codappix\SearchCore\Domain\Index;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
class NoMatchingIndexerException extends IndexingException
|
||||||
|
{
|
||||||
|
}
|
|
@ -1,5 +1,5 @@
|
||||||
<?php
|
<?php
|
||||||
namespace Leonmrni\SearchCore\Domain\Index;
|
namespace Codappix\SearchCore\Domain\Index;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (C) 2016 Daniel Siepmann <coding@daniel-siepmann.de>
|
* Copyright (C) 2016 Daniel Siepmann <coding@daniel-siepmann.de>
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<?php
|
<?php
|
||||||
namespace Leonmrni\SearchCore\Domain\Index;
|
namespace Codappix\SearchCore\Domain\Index;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (C) 2016 Daniel Siepmann <coding@daniel-siepmann.de>
|
* Copyright (C) 2016 Daniel Siepmann <coding@daniel-siepmann.de>
|
||||||
|
@ -20,39 +20,18 @@ namespace Leonmrni\SearchCore\Domain\Index;
|
||||||
* 02110-1301, USA.
|
* 02110-1301, USA.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
use TYPO3\CMS\Extbase\Object\ObjectManagerInterface;
|
use Codappix\SearchCore\Connection\ConnectionInterface;
|
||||||
use Leonmrni\SearchCore\Connection\ConnectionInterface;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Will index the given table using configuration from TCA.
|
* Will index the given table using configuration from TCA.
|
||||||
*/
|
*/
|
||||||
class TcaIndexer implements IndexerInterface
|
class TcaIndexer extends AbstractIndexer
|
||||||
{
|
{
|
||||||
/**
|
|
||||||
* @var ConnectionInterface
|
|
||||||
*/
|
|
||||||
protected $connection;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var TcaIndexer\TcaTableService
|
* @var TcaIndexer\TcaTableService
|
||||||
*/
|
*/
|
||||||
protected $tcaTableService;
|
protected $tcaTableService;
|
||||||
|
|
||||||
/**
|
|
||||||
* @var \TYPO3\CMS\Core\Log\Logger
|
|
||||||
*/
|
|
||||||
protected $logger;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Inject log manager to get concrete logger from it.
|
|
||||||
*
|
|
||||||
* @param \TYPO3\CMS\Core\Log\LogManager $logManager
|
|
||||||
*/
|
|
||||||
public function injectLogger(\TYPO3\CMS\Core\Log\LogManager $logManager)
|
|
||||||
{
|
|
||||||
$this->logger = $logManager->getLogger(__CLASS__);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param TcaIndexer\TcaTableService $tcaTableService
|
* @param TcaIndexer\TcaTableService $tcaTableService
|
||||||
* @param ConnectionInterface $connection
|
* @param ConnectionInterface $connection
|
||||||
|
@ -65,46 +44,6 @@ class TcaIndexer implements IndexerInterface
|
||||||
$this->connection = $connection;
|
$this->connection = $connection;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function indexAllDocuments()
|
|
||||||
{
|
|
||||||
$this->logger->info('Start indexing');
|
|
||||||
foreach ($this->getRecordGenerator() as $records) {
|
|
||||||
$this->logger->debug('Index records.', [$records]);
|
|
||||||
if ($records === null) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->connection->addDocuments($this->tcaTableService->getTableName(), $records);
|
|
||||||
}
|
|
||||||
$this->logger->info('Finish indexing');
|
|
||||||
}
|
|
||||||
|
|
||||||
public function indexDocument($identifier)
|
|
||||||
{
|
|
||||||
$this->logger->info('Start indexing single record.', [$identifier]);
|
|
||||||
try {
|
|
||||||
$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');
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return \Generator
|
|
||||||
*/
|
|
||||||
protected function getRecordGenerator()
|
|
||||||
{
|
|
||||||
$offset = 0;
|
|
||||||
// TODO: Make configurable.
|
|
||||||
$limit = 50;
|
|
||||||
|
|
||||||
while (($records = $this->getRecords($offset, $limit)) !== []) {
|
|
||||||
yield $records;
|
|
||||||
$offset += $limit;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param int $offset
|
* @param int $offset
|
||||||
* @param int $limit
|
* @param int $limit
|
||||||
|
@ -157,6 +96,14 @@ class TcaIndexer implements IndexerInterface
|
||||||
return $record;
|
return $record;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
protected function getDocumentName()
|
||||||
|
{
|
||||||
|
return $this->tcaTableService->getTableName();
|
||||||
|
}
|
||||||
|
|
||||||
protected function getDatabaseConnection()
|
protected function getDatabaseConnection()
|
||||||
{
|
{
|
||||||
return GeneralUtility::makeInstance(ConnectionPool::class)
|
return GeneralUtility::makeInstance(ConnectionPool::class)
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<?php
|
<?php
|
||||||
namespace Leonmrni\SearchCore\Domain\Index\TcaIndexer;
|
namespace Codappix\SearchCore\Domain\Index\TcaIndexer;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (C) 2016 Daniel Siepmann <coding@daniel-siepmann.de>
|
* Copyright (C) 2016 Daniel Siepmann <coding@daniel-siepmann.de>
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<?php
|
<?php
|
||||||
namespace Leonmrni\SearchCore\Domain\Index\TcaIndexer;
|
namespace Codappix\SearchCore\Domain\Index\TcaIndexer;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (C) 2016 Daniel Siepmann <coding@daniel-siepmann.de>
|
* Copyright (C) 2016 Daniel Siepmann <coding@daniel-siepmann.de>
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<?php
|
<?php
|
||||||
namespace Leonmrni\SearchCore\Domain\Index\TcaIndexer;
|
namespace Codappix\SearchCore\Domain\Index\TcaIndexer;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (C) 2016 Daniel Siepmann <coding@daniel-siepmann.de>
|
* Copyright (C) 2016 Daniel Siepmann <coding@daniel-siepmann.de>
|
||||||
|
@ -20,8 +20,8 @@ namespace Leonmrni\SearchCore\Domain\Index\TcaIndexer;
|
||||||
* 02110-1301, USA.
|
* 02110-1301, USA.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
use Leonmrni\SearchCore\Configuration\ConfigurationContainerInterface;
|
use Codappix\SearchCore\Configuration\ConfigurationContainerInterface;
|
||||||
use Leonmrni\SearchCore\Domain\Index\IndexingException;
|
use Codappix\SearchCore\Domain\Index\IndexingException;
|
||||||
use TYPO3\CMS\Backend\Utility\BackendUtility;
|
use TYPO3\CMS\Backend\Utility\BackendUtility;
|
||||||
use TYPO3\CMS\Core\Utility\GeneralUtility;
|
use TYPO3\CMS\Core\Utility\GeneralUtility;
|
||||||
|
|
||||||
|
@ -151,7 +151,7 @@ class TcaTableService
|
||||||
. ' AND pages.no_search = 0'
|
. ' AND pages.no_search = 0'
|
||||||
;
|
;
|
||||||
|
|
||||||
$userDefinedWhere = $this->configuration->getIfExists('indexer.tca.' . $this->tableName . '.additionalWhereClause');
|
$userDefinedWhere = $this->configuration->getIfExists('indexing.' . $this->getTableName() . '.additionalWhereClause');
|
||||||
if (is_string($userDefinedWhere)) {
|
if (is_string($userDefinedWhere)) {
|
||||||
$whereClause .= ' AND ' . $userDefinedWhere;
|
$whereClause .= ' AND ' . $userDefinedWhere;
|
||||||
}
|
}
|
||||||
|
@ -269,7 +269,7 @@ class TcaTableService
|
||||||
*/
|
*/
|
||||||
protected function isBlackListedRootLineConfigured()
|
protected function isBlackListedRootLineConfigured()
|
||||||
{
|
{
|
||||||
return (bool) $this->configuration->getIfExists('indexer.tca.rootLineBlacklist');
|
return (bool) $this->configuration->getIfExists('indexing.' . $this->getTableName() . '.rootLineBlacklist');
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -279,6 +279,6 @@ class TcaTableService
|
||||||
*/
|
*/
|
||||||
protected function getBlackListedRootLine()
|
protected function getBlackListedRootLine()
|
||||||
{
|
{
|
||||||
return GeneralUtility::intExplode(',', $this->configuration->getIfExists('indexer.tca.rootLineBlacklist'));
|
return GeneralUtility::intExplode(',', $this->configuration->getIfExists('indexing.' . $this->getTableName() . '.rootLineBlacklist'));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
66
Classes/Domain/Model/FacetRequest.php
Normal file
66
Classes/Domain/Model/FacetRequest.php
Normal file
|
@ -0,0 +1,66 @@
|
||||||
|
<?php
|
||||||
|
namespace Codappix\SearchCore\Domain\Model;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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\Connection\FacetRequestInterface;
|
||||||
|
|
||||||
|
class FacetRequest implements FacetRequestInterface
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
protected $identifier = '';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
protected $field = '';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TODO: Add validation / exception?
|
||||||
|
* As the facets come from configuration this might be a good idea to help
|
||||||
|
* integrators find issues.
|
||||||
|
*
|
||||||
|
* @param string $identifier
|
||||||
|
* @param string $field
|
||||||
|
*/
|
||||||
|
public function __construct($identifier, $field)
|
||||||
|
{
|
||||||
|
$this->identifier = $identifier;
|
||||||
|
$this->field = $field;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getIdentifier()
|
||||||
|
{
|
||||||
|
return $this->identifier;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getField()
|
||||||
|
{
|
||||||
|
return $this->field;
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,5 +1,5 @@
|
||||||
<?php
|
<?php
|
||||||
namespace Leonmrni\SearchCore\Domain\Model;
|
namespace Codappix\SearchCore\Domain\Model;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (C) 2016 Daniel Siepmann <coding@daniel-siepmann.de>
|
* Copyright (C) 2016 Daniel Siepmann <coding@daniel-siepmann.de>
|
||||||
|
@ -20,7 +20,8 @@ namespace Leonmrni\SearchCore\Domain\Model;
|
||||||
* 02110-1301, USA.
|
* 02110-1301, USA.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
use Leonmrni\SearchCore\Connection\SearchRequestInterface;
|
use Codappix\SearchCore\Connection\FacetRequestInterface;
|
||||||
|
use Codappix\SearchCore\Connection\SearchRequestInterface;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents a search request used to process an actual search.
|
* Represents a search request used to process an actual search.
|
||||||
|
@ -32,14 +33,24 @@ class SearchRequest implements SearchRequestInterface
|
||||||
*
|
*
|
||||||
* @var string
|
* @var string
|
||||||
*/
|
*/
|
||||||
protected $query;
|
protected $query = '';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
protected $filter = [];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
protected $facets = [];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param string $query
|
* @param string $query
|
||||||
*/
|
*/
|
||||||
public function __construct($query)
|
public function __construct($query)
|
||||||
{
|
{
|
||||||
$this->query = $query;
|
$this->query = (string) $query;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -57,4 +68,48 @@ class SearchRequest implements SearchRequestInterface
|
||||||
{
|
{
|
||||||
return $this->query;
|
return $this->query;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param array $filter
|
||||||
|
*/
|
||||||
|
public function setFilter(array $filter)
|
||||||
|
{
|
||||||
|
$this->filter = array_filter(array_map('strval', $filter));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function hasFilter()
|
||||||
|
{
|
||||||
|
return count($this->filter) > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function getFilter()
|
||||||
|
{
|
||||||
|
return $this->filter;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a facet to gather in this search request.
|
||||||
|
*
|
||||||
|
* @param FacetRequestInterface $facet
|
||||||
|
*/
|
||||||
|
public function addFacet(FacetRequestInterface $facet)
|
||||||
|
{
|
||||||
|
$this->facets[$facet->getIdentifier()] = $facet;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns all configured facets to fetch in this search request.
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function getFacets()
|
||||||
|
{
|
||||||
|
return $this->facets;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
138
Classes/Domain/Search/QueryFactory.php
Normal file
138
Classes/Domain/Search/QueryFactory.php
Normal file
|
@ -0,0 +1,138 @@
|
||||||
|
<?php
|
||||||
|
namespace Codappix\SearchCore\Domain\Search;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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\Connection\ConnectionInterface;
|
||||||
|
use Codappix\SearchCore\Connection\Elasticsearch\Query;
|
||||||
|
use Codappix\SearchCore\Connection\SearchRequestInterface;
|
||||||
|
use TYPO3\CMS\Extbase\Utility\ArrayUtility;
|
||||||
|
|
||||||
|
class QueryFactory
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var \TYPO3\CMS\Core\Log\Logger
|
||||||
|
*/
|
||||||
|
protected $logger;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
protected $query = [];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param \TYPO3\CMS\Core\Log\LogManager $logManager
|
||||||
|
*/
|
||||||
|
public function __construct(\TYPO3\CMS\Core\Log\LogManager $logManager)
|
||||||
|
{
|
||||||
|
$this->logger = $logManager->getLogger(__CLASS__);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param SearchRequestInterface $searchRequest
|
||||||
|
*
|
||||||
|
* @return \Elastica\Query
|
||||||
|
*/
|
||||||
|
public function create(SearchRequestInterface $searchRequest)
|
||||||
|
{
|
||||||
|
return $this->createElasticaQuery($searchRequest);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param SearchRequestInterface $searchRequest
|
||||||
|
*
|
||||||
|
* TODO: This is not in scope Elasticsearch, therefore should not return elastica.
|
||||||
|
* @return \Elastica\Query
|
||||||
|
*/
|
||||||
|
protected function createElasticaQuery(SearchRequestInterface $searchRequest)
|
||||||
|
{
|
||||||
|
$this->addSearch($searchRequest);
|
||||||
|
$this->addFilter($searchRequest);
|
||||||
|
$this->addFacets($searchRequest);
|
||||||
|
|
||||||
|
$this->logger->debug('Generated elasticsearch query.', [$this->query]);
|
||||||
|
return new \Elastica\Query($this->query);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param SearchRequestInterface $searchRequest
|
||||||
|
*/
|
||||||
|
protected function addSearch(SearchRequestInterface $searchRequest)
|
||||||
|
{
|
||||||
|
$this->query = ArrayUtility::arrayMergeRecursiveOverrule($this->query, [
|
||||||
|
'query' => [
|
||||||
|
'bool' => [
|
||||||
|
'must' => [
|
||||||
|
[
|
||||||
|
'match' => [
|
||||||
|
'_all' => $searchRequest->getSearchTerm()
|
||||||
|
],
|
||||||
|
],
|
||||||
|
],
|
||||||
|
],
|
||||||
|
],
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param SearchRequestInterface $searchRequest
|
||||||
|
*/
|
||||||
|
protected function addFilter(SearchRequestInterface $searchRequest)
|
||||||
|
{
|
||||||
|
if (! $searchRequest->hasFilter()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$terms = [];
|
||||||
|
foreach ($searchRequest->getFilter() as $name => $value) {
|
||||||
|
$terms[] = [
|
||||||
|
'term' => [
|
||||||
|
$name => $value,
|
||||||
|
],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->query = ArrayUtility::arrayMergeRecursiveOverrule($this->query, [
|
||||||
|
'query' => [
|
||||||
|
'bool' => [
|
||||||
|
'filter' => $terms,
|
||||||
|
],
|
||||||
|
],
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param SearchRequestInterface $searchRequest
|
||||||
|
*/
|
||||||
|
protected function addFacets(SearchRequestInterface $searchRequest)
|
||||||
|
{
|
||||||
|
foreach ($searchRequest->getFacets() as $facet) {
|
||||||
|
$this->query = ArrayUtility::arrayMergeRecursiveOverrule($this->query, [
|
||||||
|
'aggs' => [
|
||||||
|
$facet->getIdentifier() => [
|
||||||
|
'terms' => [
|
||||||
|
'field' => $facet->getField(),
|
||||||
|
],
|
||||||
|
],
|
||||||
|
],
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,5 +1,5 @@
|
||||||
<?php
|
<?php
|
||||||
namespace Leonmrni\SearchCore\Domain\Search;
|
namespace Codappix\SearchCore\Domain\Search;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (C) 2016 Daniel Siepmann <coding@daniel-siepmann.de>
|
* Copyright (C) 2016 Daniel Siepmann <coding@daniel-siepmann.de>
|
||||||
|
@ -20,10 +20,13 @@ namespace Leonmrni\SearchCore\Domain\Search;
|
||||||
* 02110-1301, USA.
|
* 02110-1301, USA.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
use Leonmrni\SearchCore\Connection\ConnectionInterface;
|
use Codappix\SearchCore\Configuration\ConfigurationContainerInterface;
|
||||||
use Leonmrni\SearchCore\Connection\SearchRequestInterface;
|
use Codappix\SearchCore\Configuration\InvalidArgumentException;
|
||||||
use Leonmrni\SearchCore\Connection\SearchResultInterface;
|
use Codappix\SearchCore\Connection\ConnectionInterface;
|
||||||
use Leonmrni\SearchCore\Domain\Model\SearchRequest;
|
use Codappix\SearchCore\Connection\SearchRequestInterface;
|
||||||
|
use Codappix\SearchCore\Connection\SearchResultInterface;
|
||||||
|
use Codappix\SearchCore\Domain\Model\FacetRequest;
|
||||||
|
use TYPO3\CMS\Extbase\Object\ObjectManagerInterface;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Service to process a search request.
|
* Service to process a search request.
|
||||||
|
@ -36,11 +39,28 @@ class SearchService
|
||||||
protected $connection;
|
protected $connection;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param ConnectionInterface $connection
|
* @var ConfigurationContainerInterface
|
||||||
*/
|
*/
|
||||||
public function __construct(ConnectionInterface $connection)
|
protected $configuration;
|
||||||
{
|
|
||||||
|
/**
|
||||||
|
* @var ObjectManagerInterface
|
||||||
|
*/
|
||||||
|
protected $objectManager;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param ConnectionInterface $connection
|
||||||
|
* @param ConfigurationContainerInterface $configuration
|
||||||
|
* @param ObjectManagerInterface $objectManager
|
||||||
|
*/
|
||||||
|
public function __construct(
|
||||||
|
ConnectionInterface $connection,
|
||||||
|
ConfigurationContainerInterface $configuration,
|
||||||
|
ObjectManagerInterface $objectManager
|
||||||
|
) {
|
||||||
$this->connection = $connection;
|
$this->connection = $connection;
|
||||||
|
$this->configuration = $configuration;
|
||||||
|
$this->objectManager = $objectManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -49,6 +69,34 @@ class SearchService
|
||||||
*/
|
*/
|
||||||
public function search(SearchRequestInterface $searchRequest)
|
public function search(SearchRequestInterface $searchRequest)
|
||||||
{
|
{
|
||||||
|
$this->addConfiguredFacets($searchRequest);
|
||||||
|
|
||||||
return $this->connection->search($searchRequest);
|
return $this->connection->search($searchRequest);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add facets from configuration to request.
|
||||||
|
*
|
||||||
|
* @param SearchRequestInterface $searchRequest
|
||||||
|
*/
|
||||||
|
protected function addConfiguredFacets(SearchRequestInterface $searchRequest)
|
||||||
|
{
|
||||||
|
$facetsConfig = $this->configuration->getIfExists('searching.facets');
|
||||||
|
if ($facetsConfig === null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($facetsConfig as $identifier => $facetConfig) {
|
||||||
|
if (!isset($facetConfig['field']) || trim($facetConfig['field']) === '') {
|
||||||
|
// TODO: Finish throw
|
||||||
|
throw new \Exception('message', 1499171142);
|
||||||
|
}
|
||||||
|
|
||||||
|
$searchRequest->addFacet($this->objectManager->get(
|
||||||
|
FacetRequest::class,
|
||||||
|
$identifier,
|
||||||
|
$facetConfig['field']
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<?php
|
<?php
|
||||||
namespace Leonmrni\SearchCore\Domain\Service;
|
namespace Codappix\SearchCore\Domain\Service;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (C) 2016 Daniel Siepmann <coding@daniel-siepmann.de>
|
* Copyright (C) 2016 Daniel Siepmann <coding@daniel-siepmann.de>
|
||||||
|
@ -20,7 +20,10 @@ namespace Leonmrni\SearchCore\Domain\Service;
|
||||||
* 02110-1301, USA.
|
* 02110-1301, USA.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
use Leonmrni\SearchCore\Configuration\ConfigurationContainerInterface;
|
use Codappix\SearchCore\Configuration\ConfigurationContainerInterface;
|
||||||
|
use Codappix\SearchCore\Domain\Index\IndexerFactory;
|
||||||
|
use Codappix\SearchCore\Domain\Index\NoMatchingIndexerException;
|
||||||
|
use Codappix\SearchCore\Domain\Index\TcaIndexer;
|
||||||
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;
|
||||||
|
|
||||||
|
@ -40,14 +43,13 @@ class DataHandler implements Singleton
|
||||||
/**
|
/**
|
||||||
* TODO: Only inject on first use?!
|
* TODO: Only inject on first use?!
|
||||||
*
|
*
|
||||||
* @var \Leonmrni\SearchCore\Connection\ConnectionInterface
|
* @var \Codappix\SearchCore\Connection\ConnectionInterface
|
||||||
* @inject
|
* @inject
|
||||||
*/
|
*/
|
||||||
protected $connection;
|
protected $connection;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var \Leonmrni\SearchCore\Domain\Index\IndexerFactory
|
* @var IndexerFactory
|
||||||
* @inject
|
|
||||||
*/
|
*/
|
||||||
protected $indexerFactory;
|
protected $indexerFactory;
|
||||||
|
|
||||||
|
@ -73,20 +75,12 @@ class DataHandler implements Singleton
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param ConfigurationContainerInterface $configuration
|
* @param ConfigurationContainerInterface $configuration
|
||||||
|
* @param IndexerFactory $indexerFactory
|
||||||
*/
|
*/
|
||||||
public function __construct(ConfigurationContainerInterface $configuration)
|
public function __construct(ConfigurationContainerInterface $configuration, IndexerFactory $indexerFactory)
|
||||||
{
|
{
|
||||||
$this->configuration = $configuration;
|
$this->configuration = $configuration;
|
||||||
}
|
$this->indexerFactory = $indexerFactory;
|
||||||
|
|
||||||
/**
|
|
||||||
* Get all tables that are allowed for indexing.
|
|
||||||
*
|
|
||||||
* @return array<String>
|
|
||||||
*/
|
|
||||||
public function getAllowedTablesForIndexing()
|
|
||||||
{
|
|
||||||
return GeneralUtility::trimExplode(',', $this->configuration->get('indexer.tca.allowedTables'));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -96,7 +90,7 @@ class DataHandler implements Singleton
|
||||||
public function add($table, array $record)
|
public function add($table, array $record)
|
||||||
{
|
{
|
||||||
$this->logger->debug('Record received for add.', [$table, $record]);
|
$this->logger->debug('Record received for add.', [$table, $record]);
|
||||||
$this->indexerFactory->getIndexer($table)->indexDocument($record['uid']);
|
$this->getIndexer($table)->indexDocument($record['uid']);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -105,7 +99,7 @@ class DataHandler implements Singleton
|
||||||
public function update($table, array $record)
|
public function update($table, array $record)
|
||||||
{
|
{
|
||||||
$this->logger->debug('Record received for update.', [$table, $record]);
|
$this->logger->debug('Record received for update.', [$table, $record]);
|
||||||
$this->indexerFactory->getIndexer($table)->indexDocument($record['uid']);
|
$this->getIndexer($table)->indexDocument($record['uid']);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -117,4 +111,31 @@ class DataHandler implements Singleton
|
||||||
$this->logger->debug('Record received for delete.', [$table, $identifier]);
|
$this->logger->debug('Record received for delete.', [$table, $identifier]);
|
||||||
$this->connection->deleteDocument($table, $identifier);
|
$this->connection->deleteDocument($table, $identifier);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $table
|
||||||
|
* @return IndexerInterface
|
||||||
|
*
|
||||||
|
* @throws NoMatchingIndexerException
|
||||||
|
*/
|
||||||
|
protected function getIndexer($table)
|
||||||
|
{
|
||||||
|
return $this->indexerFactory->getIndexer($table);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $table
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function canHandle($table)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
$this->getIndexer($table);
|
||||||
|
return true;
|
||||||
|
} catch (NoMatchingIndexerException $e) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<?php
|
<?php
|
||||||
namespace Leonmrni\SearchCore\Hook;
|
namespace Codappix\SearchCore\Hook;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (C) 2016 Daniel Siepmann <coding@daniel-siepmann.de>
|
* Copyright (C) 2016 Daniel Siepmann <coding@daniel-siepmann.de>
|
||||||
|
@ -20,8 +20,9 @@ namespace Leonmrni\SearchCore\Hook;
|
||||||
* 02110-1301, USA.
|
* 02110-1301, USA.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
use Leonmrni\SearchCore\Configuration\NoConfigurationException;
|
use Codappix\SearchCore\Configuration\NoConfigurationException;
|
||||||
use Leonmrni\SearchCore\Domain\Service\DataHandler as OwnDataHandler;
|
use Codappix\SearchCore\Domain\Index\NoMatchingIndexerException;
|
||||||
|
use Codappix\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;
|
||||||
|
@ -140,7 +141,7 @@ class DataHandler implements Singleton
|
||||||
$this->logger->debug('Datahandler could not be setup.');
|
$this->logger->debug('Datahandler could not be setup.');
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (! $this->shouldProcessTable($table)) {
|
if (! $this->dataHandler->canHandle($table)) {
|
||||||
$this->logger->debug('Table is not allowed.', [$table]);
|
$this->logger->debug('Table is not allowed.', [$table]);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -148,15 +149,6 @@ class DataHandler implements Singleton
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @param string $table
|
|
||||||
* @return bool
|
|
||||||
*/
|
|
||||||
protected function shouldProcessTable($table)
|
|
||||||
{
|
|
||||||
return in_array($table, $this->dataHandler->getAllowedTablesForIndexing());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Wrapper to allow unit testing.
|
* Wrapper to allow unit testing.
|
||||||
*
|
*
|
||||||
|
|
6
Configuration/TypoScript/constants.txt
Executable file → Normal file
6
Configuration/TypoScript/constants.txt
Executable file → Normal file
|
@ -8,14 +8,11 @@ plugin {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
indexer {
|
indexing {
|
||||||
tca {
|
|
||||||
# Pages are not supported yet, see
|
# Pages are not supported yet, see
|
||||||
# https://github.com/DanielSiepmann/search_core/issues/24 but
|
# https://github.com/DanielSiepmann/search_core/issues/24 but
|
||||||
# should also be added, together with additionalWhereClause
|
# should also be added, together with additionalWhereClause
|
||||||
# based on doktypes
|
# based on doktypes
|
||||||
allowedTables = tt_content
|
|
||||||
|
|
||||||
tt_content {
|
tt_content {
|
||||||
additionalWhereClause (
|
additionalWhereClause (
|
||||||
pages.doktype NOT IN (3, 199)
|
pages.doktype NOT IN (3, 199)
|
||||||
|
@ -25,5 +22,4 @@ plugin {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
9
Configuration/TypoScript/setup.txt
Executable file → Normal file
9
Configuration/TypoScript/setup.txt
Executable file → Normal file
|
@ -8,13 +8,10 @@ plugin {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
indexer {
|
indexing {
|
||||||
tca {
|
|
||||||
allowedTables = {$plugin.tx_searchcore.settings.indexer.tca.allowedTables}
|
|
||||||
|
|
||||||
tt_content {
|
tt_content {
|
||||||
additionalWhereClause = {$plugin.tx_searchcore.settings.indexer.tca.tt_content.additionalWhereClause}
|
indexer = Codappix\SearchCore\Domain\Index\TcaIndexer
|
||||||
}
|
additionalWhereClause = {$plugin.tx_searchcore.settings.indexing.tt_content.additionalWhereClause}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,7 +24,7 @@ Currently only :ref:`Elasticsearch` is provided.
|
||||||
Indexing
|
Indexing
|
||||||
--------
|
--------
|
||||||
|
|
||||||
The indexing is done by one of the available indexer. It should be possible to define the indexer to
|
The indexing is done by one of the available indexer. For each identifier it's possible to define
|
||||||
use for certein document types. Also it should be possible to write custom indexer to use.
|
the indexer to use. Also it's possible to write custom indexer to use.
|
||||||
|
|
||||||
Currently only the :ref:`TcaIndexer` is provided.
|
Currently only the :ref:`TcaIndexer` is provided.
|
||||||
|
|
|
@ -120,7 +120,7 @@ html_theme = 'alabaster'
|
||||||
# documentation.
|
# documentation.
|
||||||
html_theme_options = {
|
html_theme_options = {
|
||||||
'description': 'TYPO3 Extension to integrate search services.',
|
'description': 'TYPO3 Extension to integrate search services.',
|
||||||
'github_user': 'DanielSiepmann',
|
'github_user': 'Codappix',
|
||||||
'github_repo': 'search_core',
|
'github_repo': 'search_core',
|
||||||
'github_button': True,
|
'github_button': True,
|
||||||
'github_banner': True,
|
'github_banner': True,
|
||||||
|
@ -306,7 +306,7 @@ intersphinx_mapping = {
|
||||||
't3tcaref': ('https://docs.typo3.org/typo3cms/TCAReference/', None),
|
't3tcaref': ('https://docs.typo3.org/typo3cms/TCAReference/', None),
|
||||||
}
|
}
|
||||||
extlinks = {
|
extlinks = {
|
||||||
'project': ('https://github.com/DanielSiepmann/search_core/projects/%s', 'Github project: '),
|
'project': ('https://github.com/Codappix/search_core/projects/%s', 'Github project: '),
|
||||||
'pr': ('https://github.com/DanielSiepmann/search_core/pull/%s', 'Github pull request: '),
|
'pr': ('https://github.com/Codappix/search_core/pull/%s', 'Github pull request: '),
|
||||||
'issue': ('https://github.com/DanielSiepmann/search_core/issues/%s', 'Github issue: '),
|
'issue': ('https://github.com/Codappix/search_core/issues/%s', 'Github issue: '),
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,7 +38,7 @@ Options
|
||||||
|
|
||||||
The following section contains the different options, e.g. for :ref:`connections` and
|
The following section contains the different options, e.g. for :ref:`connections` and
|
||||||
:ref:`indexer`: ``plugin.tx_searchcore.settings.connection`` or
|
:ref:`indexer`: ``plugin.tx_searchcore.settings.connection`` or
|
||||||
``plugin.tx_searchcore.settings.index``.
|
``plugin.tx_searchcore.settings.indexing``.
|
||||||
|
|
||||||
.. _configuration_options_connection:
|
.. _configuration_options_connection:
|
||||||
|
|
||||||
|
@ -96,8 +96,8 @@ The following settings are available. For each setting its documented which conn
|
||||||
|
|
||||||
.. _configuration_options_index:
|
.. _configuration_options_index:
|
||||||
|
|
||||||
index
|
Indexing
|
||||||
^^^^^
|
^^^^^^^^
|
||||||
|
|
||||||
Holds settings regarding the indexing, e.g. of TYPO3 records, to search services.
|
Holds settings regarding the indexing, e.g. of TYPO3 records, to search services.
|
||||||
|
|
||||||
|
@ -106,8 +106,9 @@ Configured as::
|
||||||
plugin {
|
plugin {
|
||||||
tx_searchcore {
|
tx_searchcore {
|
||||||
settings {
|
settings {
|
||||||
indexer {
|
indexing {
|
||||||
indexerName {
|
identifier {
|
||||||
|
indexer = FullyQualifiedClassname
|
||||||
// the settings
|
// the settings
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -115,26 +116,10 @@ Configured as::
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Where ``indexerName`` is one of the available :ref:`indexer`.
|
Where ``identifier`` is up to you, but should match table names to make :ref:`TcaIndexer` work.
|
||||||
|
|
||||||
The following settings are available. For each setting its documented which indexer consumes it.
|
The following settings are available. For each setting its documented which indexer consumes it.
|
||||||
|
|
||||||
.. _allowedTables:
|
|
||||||
|
|
||||||
``allowedTables``
|
|
||||||
"""""""""""""""""
|
|
||||||
|
|
||||||
Used by: :ref:`TcaIndexer`.
|
|
||||||
|
|
||||||
Defines which TYPO3 tables are allowed to be indexed. Only white listed tables will be processed
|
|
||||||
through Command Line Interface and Hooks.
|
|
||||||
|
|
||||||
Contains a comma separated list of table names. Spaces are trimmed.
|
|
||||||
|
|
||||||
Example::
|
|
||||||
|
|
||||||
plugin.tx_searchcore.settings.indexer.tca.allowedTables = tt_content, fe_users
|
|
||||||
|
|
||||||
.. _rootLineBlacklist:
|
.. _rootLineBlacklist:
|
||||||
|
|
||||||
``rootLineBlacklist``
|
``rootLineBlacklist``
|
||||||
|
@ -151,7 +136,7 @@ The following settings are available. For each setting its documented which inde
|
||||||
|
|
||||||
Example::
|
Example::
|
||||||
|
|
||||||
plugin.tx_searchcore.settings.index.tca.rootLineBlacklist = 3, 10, 100
|
plugin.tx_searchcore.settings.indexing.<identifier>.rootLineBlacklist = 3, 10, 100
|
||||||
|
|
||||||
Also it's possible to define some behaviour for the different document types. In context of TYPO3
|
Also it's possible to define some behaviour for the different document types. In context of TYPO3
|
||||||
tables are used as document types 1:1. It's possible to configure different tables. The following
|
tables are used as document types 1:1. It's possible to configure different tables. The following
|
||||||
|
@ -170,9 +155,57 @@ options are available:
|
||||||
|
|
||||||
Example::
|
Example::
|
||||||
|
|
||||||
plugin.tx_searchcore.settings.index.tca.tt_content.additionalWhereClause = tt_content.CType NOT IN ('gridelements_pi1', 'list', 'div', 'menu')
|
plugin.tx_searchcore.settings.indexing.<identifier>.additionalWhereClause = tt_content.CType NOT IN ('gridelements_pi1', 'list', 'div', 'menu')
|
||||||
|
|
||||||
.. attention::
|
.. attention::
|
||||||
|
|
||||||
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.
|
||||||
|
|
||||||
|
.. _mapping:
|
||||||
|
|
||||||
|
``mapping``
|
||||||
|
"""""""""""
|
||||||
|
|
||||||
|
Used by: Elasticsearch connection while indexing.
|
||||||
|
|
||||||
|
Define mapping for Elasticsearch, have a look at the official docs: https://www.elastic.co/guide/en/elasticsearch/reference/5.2/mapping.html
|
||||||
|
You are able to define the mapping for each property / columns.
|
||||||
|
|
||||||
|
Example::
|
||||||
|
|
||||||
|
plugin.tx_searchcore.settings.indexing.tt_content.mapping {
|
||||||
|
CType {
|
||||||
|
type = keyword
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
The above example will define the ``CType`` field of ``tt_content`` as ``type: keyword``. This
|
||||||
|
makes building a facet possible.
|
||||||
|
|
||||||
|
|
||||||
|
.. _configuration_options_search:
|
||||||
|
|
||||||
|
Searching
|
||||||
|
^^^^^^^^^
|
||||||
|
|
||||||
|
.. _facets:
|
||||||
|
|
||||||
|
``facets``
|
||||||
|
"""""""""""
|
||||||
|
|
||||||
|
Used by: Elasticsearch connection while building search query.
|
||||||
|
|
||||||
|
Define aggregations for Elasticsearch, have a look at the official docs: https://www.elastic.co/guide/en/elasticsearch/reference/5.2/search-aggregations-bucket-terms-aggregation.html
|
||||||
|
Currently only the term facet is provided.
|
||||||
|
|
||||||
|
Example::
|
||||||
|
|
||||||
|
plugin.tx_searchcore.settings.searching.facets {
|
||||||
|
contentTypes {
|
||||||
|
field = CType
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
The above example will provide a facet with options for all found ``CType`` results together
|
||||||
|
with a count.
|
||||||
|
|
|
@ -22,5 +22,9 @@ The connection is configurable through the following options:
|
||||||
|
|
||||||
* :ref:`port`
|
* :ref:`port`
|
||||||
|
|
||||||
|
* :ref:`mapping`
|
||||||
|
|
||||||
|
* :ref:`facets`
|
||||||
|
|
||||||
.. _elastic Elasticsearch: https://www.elastic.co/products/elasticsearch
|
.. _elastic Elasticsearch: https://www.elastic.co/products/elasticsearch
|
||||||
.. _elastica: http://elastica.io/
|
.. _elastica: http://elastica.io/
|
||||||
|
|
|
@ -32,9 +32,10 @@ Then setup your system::
|
||||||
|
|
||||||
git clone git@github.com:DanielSiepmann/search_core.git \
|
git clone git@github.com:DanielSiepmann/search_core.git \
|
||||||
&& cd search_core \
|
&& cd search_core \
|
||||||
&& export typo3DatabaseName="searchcoretest62" \
|
&& export typo3DatabaseName="searchcoretest76" \
|
||||||
&& export TYPO3_VERSION="~6.2" \
|
&& export TYPO3_VERSION="~7.6" \
|
||||||
&& make install \
|
&& make install \
|
||||||
|
&& make unitTests \
|
||||||
&& make functionalTests
|
&& make functionalTests
|
||||||
|
|
||||||
If all tests are okay, start your work.
|
If all tests are okay, start your work.
|
||||||
|
@ -42,8 +43,8 @@ If all tests are okay, start your work.
|
||||||
If you are working with multiple TYPO3 versions make sure to export `typo3DatabaseName` and
|
If you are working with multiple TYPO3 versions make sure to export `typo3DatabaseName` and
|
||||||
`TYPO3_VERSION` in your environment like::
|
`TYPO3_VERSION` in your environment like::
|
||||||
|
|
||||||
export typo3DatabaseName="searchcoretest76"
|
export typo3DatabaseName="searchcoretest62"
|
||||||
export TYPO3_VERSION="~7.6"
|
export TYPO3_VERSION="~6.2"
|
||||||
|
|
||||||
Also run the install command for each version before running any tests. Only this will make sure you
|
Also run the install command for each version before running any tests. Only this will make sure you
|
||||||
are testing against the actual TYPO3 Version and database scheme.
|
are testing against the actual TYPO3 Version and database scheme.
|
||||||
|
|
38
Documentation/source/features.rst
Normal file
38
Documentation/source/features.rst
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
.. _features:
|
||||||
|
|
||||||
|
Features
|
||||||
|
========
|
||||||
|
|
||||||
|
The following features are currently provided:
|
||||||
|
|
||||||
|
.. _features_indexing:
|
||||||
|
|
||||||
|
Indexing
|
||||||
|
--------
|
||||||
|
|
||||||
|
Indexing data to Elasticsearch is provided. The extension delivers an indexer for TCA with zero
|
||||||
|
configuration needs. Still it's possible to configure the indexer.
|
||||||
|
|
||||||
|
Also custom classes can be used as indexers.
|
||||||
|
|
||||||
|
.. _features_search:
|
||||||
|
|
||||||
|
Searching
|
||||||
|
---------
|
||||||
|
|
||||||
|
Currently all fields are searched for a single search input.
|
||||||
|
|
||||||
|
Also multiple filter are supported. Filtering results by fields for string contents.
|
||||||
|
|
||||||
|
Even facets / aggregates are now possible. Therefore a mapping has to be defined in TypoScript for
|
||||||
|
indexing, and the facets itself while searching.
|
||||||
|
|
||||||
|
.. _features_planned:
|
||||||
|
|
||||||
|
Planned
|
||||||
|
---------
|
||||||
|
|
||||||
|
The following features are currently planned and will be integrated:
|
||||||
|
|
||||||
|
#. Pagination
|
||||||
|
Add a pagination to search results, to allow users to walk through all results.
|
|
@ -7,6 +7,7 @@ Table of Contents
|
||||||
:maxdepth: 1
|
:maxdepth: 1
|
||||||
:glob:
|
:glob:
|
||||||
|
|
||||||
|
features
|
||||||
installation
|
installation
|
||||||
configuration
|
configuration
|
||||||
usage
|
usage
|
||||||
|
|
|
@ -6,7 +6,7 @@ Installation
|
||||||
|
|
||||||
The extension can be installed through composer::
|
The extension can be installed through composer::
|
||||||
|
|
||||||
composer require "leonmrni/search_core dev-feature/integrate-elasticsearch"
|
composer require "leonmrni/search_core dev-master as 1.0.x-dev"
|
||||||
|
|
||||||
or by `downloading`_ and placing it inside the :file:`typo3conf/ext`-Folder of your installation.
|
or by `downloading`_ and placing it inside the :file:`typo3conf/ext`-Folder of your installation.
|
||||||
In that case you need to install all dependencies yourself. Dependencies are:
|
In that case you need to install all dependencies yourself. Dependencies are:
|
||||||
|
@ -16,8 +16,7 @@ In that case you need to install all dependencies yourself. Dependencies are:
|
||||||
:lines: 19-21
|
:lines: 19-21
|
||||||
:dedent: 8
|
:dedent: 8
|
||||||
|
|
||||||
|
|
||||||
Afterwards you need to enable the extension through the extension manager and include the static
|
Afterwards you need to enable the extension through the extension manager and include the static
|
||||||
typoscript setup.
|
TypoScript setup.
|
||||||
|
|
||||||
.. _downloading: https://github.com/DanielSiepmann/search_core/archive/feature/integrate-elasticsearch.zip
|
.. _downloading: https://github.com/DanielSiepmann/search_core/archive/master.zip
|
||||||
|
|
|
@ -18,14 +18,14 @@ reindexing.
|
||||||
Current state
|
Current state
|
||||||
-------------
|
-------------
|
||||||
|
|
||||||
This is still a very early alpha version. More information can be taken from Github at
|
This is still a very early beta version. More information can be taken from Github at
|
||||||
`current issues`_ and `current projects`_.
|
`current issues`_ and `current projects`_.
|
||||||
|
|
||||||
We are also focusing on Code Quality and Testing through `travis ci`_, `scrutinizer`_ and `codacy`_.
|
We are also focusing on Code Quality and Testing through `travis ci`_, `scrutinizer`_ and `codacy`_.
|
||||||
|
|
||||||
.. _current issues: https://github.com/DanielSiepmann/search_core/issues
|
.. _current issues: https://github.com/Codappix/search_core/issues
|
||||||
.. _current projects: https://github.com/DanielSiepmann/search_core/projects
|
.. _current projects: https://github.com/Codappix/search_core/projects
|
||||||
.. _travis ci: https://travis-ci.org/DanielSiepmann/search_core
|
.. _travis ci: https://travis-ci.org/Codappix/search_core
|
||||||
.. _scrutinizer: https://scrutinizer-ci.com/g/DanielSiepmann/search_core/inspections
|
.. _scrutinizer: https://scrutinizer-ci.com/g/Codappix/search_core/inspections
|
||||||
.. _codacy: https://www.codacy.com/app/daniel-siepmann/search_core/dashboard
|
.. _codacy: https://www.codacy.com/app/Codappix/search_core/dashboard
|
||||||
|
|
||||||
|
|
|
@ -11,12 +11,12 @@ Manual indexing
|
||||||
|
|
||||||
You can trigger indexing from CLI::
|
You can trigger indexing from CLI::
|
||||||
|
|
||||||
./typo3/cli_dispatch.phpsh extbase index:index --table 'tt_content'
|
./typo3/cli_dispatch.phpsh extbase index:index --identifier 'tt_content'
|
||||||
|
|
||||||
This will index the table ``tt_content`` using the :ref:`TcaIndexer`.
|
This will index the table ``tt_content`` using the :ref:`TcaIndexer`.
|
||||||
|
|
||||||
Only one table per call is available, to index multiple tables just make multiple calls.
|
Only one index per call is available, to run multiple indexers, just make multiple calls.
|
||||||
The tables have to be white listed through :ref:`allowedTables` option.
|
The indexers have to be defined in TypoScript via :ref:`configuration_options_index`.
|
||||||
|
|
||||||
.. _usage_auto_indexing:
|
.. _usage_auto_indexing:
|
||||||
|
|
||||||
|
@ -24,7 +24,7 @@ Auto indexing
|
||||||
-------------
|
-------------
|
||||||
|
|
||||||
Indexing is done through hooks every time an record is changed.
|
Indexing is done through hooks every time an record is changed.
|
||||||
The tables have to be white listed through :ref:`allowedTables` option.
|
The tables have to be configured via :ref:`configuration_options_index`.
|
||||||
|
|
||||||
.. note::
|
.. note::
|
||||||
|
|
||||||
|
@ -37,3 +37,48 @@ Searching / Frontend Plugin
|
||||||
|
|
||||||
To provide a search interface you can insert the frontend Plugin as normal content element of type
|
To provide a search interface you can insert the frontend Plugin as normal content element of type
|
||||||
plugin. The plugin is named *Search Core*.
|
plugin. The plugin is named *Search Core*.
|
||||||
|
|
||||||
|
Please provide your own template, the extension will not deliver a useful template for now.
|
||||||
|
|
||||||
|
The extbase mapping is used, this way you can create a form:
|
||||||
|
|
||||||
|
.. code-block:: html
|
||||||
|
|
||||||
|
<f:form name="searchRequest" object="{searchRequest}">
|
||||||
|
<f:form.textfield property="query" />
|
||||||
|
<f:form.submit value="search" />
|
||||||
|
</f:form>
|
||||||
|
|
||||||
|
.. _usage_searching_filter:
|
||||||
|
|
||||||
|
Filter
|
||||||
|
""""""
|
||||||
|
|
||||||
|
Thanks to extbase mapping, filter are added to the form:
|
||||||
|
|
||||||
|
.. code-block:: html
|
||||||
|
|
||||||
|
<!-- Case sensitive for fields of type keyword. -->
|
||||||
|
<f:form.textfield property="filter.exampleName" value="the value to match" />
|
||||||
|
|
||||||
|
.. _usage_searching_facets:
|
||||||
|
|
||||||
|
Facets
|
||||||
|
""""""
|
||||||
|
|
||||||
|
To add a facet as criteria for searching, use :ref:`usage_searching_filter`.
|
||||||
|
|
||||||
|
To display facet results use:
|
||||||
|
|
||||||
|
.. code-block:: html
|
||||||
|
|
||||||
|
<f:for each="{searchResult.facets}" as="facet">
|
||||||
|
<f:for each="{facet.options}" as="option">
|
||||||
|
<label for="{option.name}-desktop">
|
||||||
|
<f:form.checkbox value="{option.name}" property="filter.{facet.field}" />
|
||||||
|
{f:translate(id: 'search.filter.channel.{option.name}', default: option.name, extensionName: 'SitePackage')}
|
||||||
|
({option.count})
|
||||||
|
</label>
|
||||||
|
</f:for>
|
||||||
|
</f:for>
|
||||||
|
|
||||||
|
|
5
Makefile
5
Makefile
|
@ -25,6 +25,11 @@ functionalTests:
|
||||||
--stop-on-error \
|
--stop-on-error \
|
||||||
-c Tests/Functional/FunctionalTests.xml
|
-c Tests/Functional/FunctionalTests.xml
|
||||||
|
|
||||||
|
unitTests:
|
||||||
|
TYPO3_PATH_WEB=$(TYPO3_WEB_DIR) \
|
||||||
|
.Build/bin/phpunit --colors --debug -v \
|
||||||
|
-c Tests/Unit/UnitTests.xml
|
||||||
|
|
||||||
uploadCodeCoverage: uploadCodeCoverageToScrutinizer uploadCodeCoverageToCodacy
|
uploadCodeCoverage: uploadCodeCoverageToScrutinizer uploadCodeCoverageToCodacy
|
||||||
|
|
||||||
uploadCodeCoverageToScrutinizer:
|
uploadCodeCoverageToScrutinizer:
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<?php
|
<?php
|
||||||
namespace Leonmrni\SearchCore\Tests\Functional;
|
namespace Codappix\SearchCore\Tests\Functional;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (C) 2016 Daniel Siepmann <coding@daniel-siepmann.de>
|
* Copyright (C) 2016 Daniel Siepmann <coding@daniel-siepmann.de>
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<?php
|
<?php
|
||||||
namespace Leonmrni\SearchCore\Tests\Functional\Connection\Elasticsearch;
|
namespace Codappix\SearchCore\Tests\Functional\Connection\Elasticsearch;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (C) 2016 Daniel Siepmann <coding@daniel-siepmann.de>
|
* Copyright (C) 2016 Daniel Siepmann <coding@daniel-siepmann.de>
|
||||||
|
@ -20,7 +20,7 @@ namespace Leonmrni\SearchCore\Tests\Functional\Connection\Elasticsearch;
|
||||||
* 02110-1301, USA.
|
* 02110-1301, USA.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
use Leonmrni\SearchCore\Tests\Functional\AbstractFunctionalTestCase as BaseFunctionalTestCase;
|
use Codappix\SearchCore\Tests\Functional\AbstractFunctionalTestCase as BaseFunctionalTestCase;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* All functional tests should extend this base class.
|
* All functional tests should extend this base class.
|
||||||
|
@ -43,11 +43,19 @@ abstract class AbstractFunctionalTestCase extends BaseFunctionalTestCase
|
||||||
'host' => getenv('ES_HOST') ?: \Elastica\Connection::DEFAULT_HOST,
|
'host' => getenv('ES_HOST') ?: \Elastica\Connection::DEFAULT_HOST,
|
||||||
'port' => getenv('ES_PORT') ?: \Elastica\Connection::DEFAULT_PORT,
|
'port' => getenv('ES_PORT') ?: \Elastica\Connection::DEFAULT_PORT,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
// Start with clean system for test.
|
||||||
|
$this->cleanUp();
|
||||||
}
|
}
|
||||||
|
|
||||||
public function tearDown()
|
public function tearDown()
|
||||||
{
|
{
|
||||||
// Delete everything so next test starts clean.
|
// Make system clean again.
|
||||||
|
$this->cleanUp();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function cleanUp()
|
||||||
|
{
|
||||||
$this->client->getIndex('_all')->delete();
|
$this->client->getIndex('_all')->delete();
|
||||||
$this->client->getIndex('_all')->clearCache();
|
$this->client->getIndex('_all')->clearCache();
|
||||||
}
|
}
|
||||||
|
|
94
Tests/Functional/Connection/Elasticsearch/FilterTest.php
Normal file
94
Tests/Functional/Connection/Elasticsearch/FilterTest.php
Normal file
|
@ -0,0 +1,94 @@
|
||||||
|
<?php
|
||||||
|
namespace Codappix\SearchCore\Tests\Functional\Connection\Elasticsearch;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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\Domain\Index\IndexerFactory;
|
||||||
|
use Codappix\SearchCore\Domain\Model\SearchRequest;
|
||||||
|
use Codappix\SearchCore\Domain\Search\SearchService;
|
||||||
|
use TYPO3\CMS\Extbase\Object\ObjectManager;
|
||||||
|
|
||||||
|
class FilterTest extends AbstractFunctionalTestCase
|
||||||
|
{
|
||||||
|
protected function getDataSets()
|
||||||
|
{
|
||||||
|
return array_merge(
|
||||||
|
parent::getDataSets(),
|
||||||
|
['Tests/Functional/Fixtures/Searching/Filter.xml']
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @test
|
||||||
|
*/
|
||||||
|
public function itsPossibleToFilterResultsByASingleField()
|
||||||
|
{
|
||||||
|
\TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(ObjectManager::class)
|
||||||
|
->get(IndexerFactory::class)
|
||||||
|
->getIndexer('tt_content')
|
||||||
|
->indexAllDocuments()
|
||||||
|
;
|
||||||
|
|
||||||
|
$searchService = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(ObjectManager::class)
|
||||||
|
->get(SearchService::class);
|
||||||
|
$searchRequest = new SearchRequest('Search Word');
|
||||||
|
|
||||||
|
$result = $searchService->search($searchRequest);
|
||||||
|
$this->assertSame(2, count($result), 'Did not receive both indexed elements without filter.');
|
||||||
|
|
||||||
|
$searchRequest->setFilter(['CType' => 'HTML']);
|
||||||
|
$result = $searchService->search($searchRequest);
|
||||||
|
$this->assertSame('5', $result->getResults()[0]['uid'], 'Did not get the expected result entry.');
|
||||||
|
$this->assertSame(1, count($result), 'Did not receive the single filtered element.');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @test
|
||||||
|
*/
|
||||||
|
public function itsPossibleToFetchFacetsForField()
|
||||||
|
{
|
||||||
|
\TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(ObjectManager::class)
|
||||||
|
->get(IndexerFactory::class)
|
||||||
|
->getIndexer('tt_content')
|
||||||
|
->indexAllDocuments()
|
||||||
|
;
|
||||||
|
|
||||||
|
$searchService = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(ObjectManager::class)
|
||||||
|
->get(SearchService::class);
|
||||||
|
|
||||||
|
$searchRequest = new SearchRequest('Search Word');
|
||||||
|
$result = $searchService->search($searchRequest);
|
||||||
|
|
||||||
|
$this->assertSame(1, count($result->getFacets()), 'Did not receive the single defined facet.');
|
||||||
|
|
||||||
|
$facet = $result->getFacets()[0];
|
||||||
|
$this->assertSame('contentTypes', $facet->getName(), 'Name of facet was not as expected.');
|
||||||
|
$this->assertSame('CType', $facet->getField(), 'Field of facet was not expected.');
|
||||||
|
|
||||||
|
$options = $facet->getOptions();
|
||||||
|
$this->assertSame(2, count($options), 'Did not receive the expected number of possible options for facet.');
|
||||||
|
$option = $options[0];
|
||||||
|
$this->assertSame('HTML', $option->getName(), 'Option did not have expected Name.');
|
||||||
|
$this->assertSame(1, $option->getCount(), 'Option did not have expected count.');
|
||||||
|
$option = $options[1];
|
||||||
|
$this->assertSame('Header', $option->getName(), 'Option did not have expected Name.');
|
||||||
|
$this->assertSame(1, $option->getCount(), 'Option did not have expected count.');
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,5 +1,5 @@
|
||||||
<?php
|
<?php
|
||||||
namespace Leonmrni\SearchCore\Tests\Functional\Connection\Elasticsearch;
|
namespace Codappix\SearchCore\Tests\Functional\Connection\Elasticsearch;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (C) 2016 Daniel Siepmann <coding@daniel-siepmann.de>
|
* Copyright (C) 2016 Daniel Siepmann <coding@daniel-siepmann.de>
|
||||||
|
@ -20,7 +20,7 @@ namespace Leonmrni\SearchCore\Tests\Functional\Connection\Elasticsearch;
|
||||||
* 02110-1301, USA.
|
* 02110-1301, USA.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
use Leonmrni\SearchCore\Domain\Index\IndexerFactory;
|
use Codappix\SearchCore\Domain\Index\IndexerFactory;
|
||||||
use TYPO3\CMS\Extbase\Object\ObjectManager;
|
use TYPO3\CMS\Extbase\Object\ObjectManager;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -61,7 +61,7 @@ class IndexTcaTableTest extends AbstractFunctionalTestCase
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @test
|
* @test
|
||||||
* @expectedException \Leonmrni\SearchCore\Domain\Index\IndexingException
|
* @expectedException \Codappix\SearchCore\Domain\Index\IndexingException
|
||||||
*/
|
*/
|
||||||
public function indexingNonConfiguredTableWillThrowException()
|
public function indexingNonConfiguredTableWillThrowException()
|
||||||
{
|
{
|
||||||
|
|
|
@ -8,9 +8,23 @@ plugin {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
indexer {
|
indexing {
|
||||||
tca {
|
tt_content {
|
||||||
allowedTables = tt_content
|
indexer = Codappix\SearchCore\Domain\Index\TcaIndexer
|
||||||
|
|
||||||
|
mapping {
|
||||||
|
CType {
|
||||||
|
type = keyword
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
searching {
|
||||||
|
facets {
|
||||||
|
contentTypes {
|
||||||
|
field = CType
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
plugin {
|
plugin {
|
||||||
tx_searchcore {
|
tx_searchcore {
|
||||||
settings {
|
settings {
|
||||||
indexer {
|
indexing {
|
||||||
tca {
|
tt_content {
|
||||||
rootLineBlacklist = 3
|
rootLineBlacklist = 3
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,15 +1,13 @@
|
||||||
plugin {
|
plugin {
|
||||||
tx_searchcore {
|
tx_searchcore {
|
||||||
settings {
|
settings {
|
||||||
indexer {
|
indexing {
|
||||||
tca {
|
|
||||||
tt_content {
|
tt_content {
|
||||||
additionalWhereClause = tt_content.CType NOT IN ('div')
|
additionalWhereClause = tt_content.CType NOT IN ('div')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
module.tx_searchcore < plugin.tx_searchcore
|
module.tx_searchcore < plugin.tx_searchcore
|
||||||
|
|
42
Tests/Functional/Fixtures/Searching/Filter.xml
Normal file
42
Tests/Functional/Fixtures/Searching/Filter.xml
Normal file
|
@ -0,0 +1,42 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<dataset>
|
||||||
|
<tt_content>
|
||||||
|
<uid>5</uid>
|
||||||
|
<pid>1</pid>
|
||||||
|
<tstamp>1480686370</tstamp>
|
||||||
|
<crdate>1480686370</crdate>
|
||||||
|
<hidden>0</hidden>
|
||||||
|
<sorting>72</sorting>
|
||||||
|
<CType>html</CType>
|
||||||
|
<header>indexed content element with html ctype</header>
|
||||||
|
<bodytext>Search Word</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>6</uid>
|
||||||
|
<pid>1</pid>
|
||||||
|
<tstamp>1480686370</tstamp>
|
||||||
|
<crdate>1480686370</crdate>
|
||||||
|
<hidden>0</hidden>
|
||||||
|
<sorting>72</sorting>
|
||||||
|
<CType>header</CType>
|
||||||
|
<header>indexed content element with header ctype</header>
|
||||||
|
<bodytext>Search Word</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>
|
|
@ -1,5 +1,5 @@
|
||||||
<?php
|
<?php
|
||||||
namespace Leonmrni\SearchCore\Tests\Functional\Hooks\DataHandler;
|
namespace Codappix\SearchCore\Tests\Functional\Hooks\DataHandler;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (C) 2016 Daniel Siepmann <coding@daniel-siepmann.de>
|
* Copyright (C) 2016 Daniel Siepmann <coding@daniel-siepmann.de>
|
||||||
|
@ -20,10 +20,11 @@ namespace Leonmrni\SearchCore\Tests\Functional\Hooks\DataHandler;
|
||||||
* 02110-1301, USA.
|
* 02110-1301, USA.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
use Leonmrni\SearchCore\Configuration\ConfigurationContainerInterface;
|
use Codappix\SearchCore\Configuration\ConfigurationContainerInterface;
|
||||||
use Leonmrni\SearchCore\Domain\Service\DataHandler as DataHandlerService;
|
use Codappix\SearchCore\Domain\Index\IndexerFactory;
|
||||||
use Leonmrni\SearchCore\Hook\DataHandler as DataHandlerHook;
|
use Codappix\SearchCore\Domain\Service\DataHandler as DataHandlerService;
|
||||||
use Leonmrni\SearchCore\Tests\Functional\AbstractFunctionalTestCase;
|
use Codappix\SearchCore\Hook\DataHandler as DataHandlerHook;
|
||||||
|
use Codappix\SearchCore\Tests\Functional\AbstractFunctionalTestCase;
|
||||||
use TYPO3\CMS\Core\DataHandling\DataHandler as Typo3DataHandler;
|
use TYPO3\CMS\Core\DataHandling\DataHandler as Typo3DataHandler;
|
||||||
use TYPO3\CMS\Core\Utility\GeneralUtility;
|
use TYPO3\CMS\Core\Utility\GeneralUtility;
|
||||||
use TYPO3\CMS\Extbase\Object\ObjectManager;
|
use TYPO3\CMS\Extbase\Object\ObjectManager;
|
||||||
|
@ -42,7 +43,10 @@ abstract class AbstractDataHandlerTest extends AbstractFunctionalTestCase
|
||||||
$objectManager = GeneralUtility::makeInstance(ObjectManager::class);
|
$objectManager = GeneralUtility::makeInstance(ObjectManager::class);
|
||||||
|
|
||||||
$this->subject = $this->getMockBuilder(DataHandlerService::class)
|
$this->subject = $this->getMockBuilder(DataHandlerService::class)
|
||||||
->setConstructorArgs([$objectManager->get(ConfigurationContainerInterface::class)])
|
->setConstructorArgs([
|
||||||
|
$objectManager->get(ConfigurationContainerInterface::class),
|
||||||
|
$objectManager->get(IndexerFactory::class)
|
||||||
|
])
|
||||||
->setMethods(['add', 'update', 'delete'])
|
->setMethods(['add', 'update', 'delete'])
|
||||||
->getMock();
|
->getMock();
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<?php
|
<?php
|
||||||
namespace Leonmrni\SearchCore\Tests\Functional\Hooks\DataHandler;
|
namespace Codappix\SearchCore\Tests\Functional\Hooks\DataHandler;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (C) 2016 Daniel Siepmann <coding@daniel-siepmann.de>
|
* Copyright (C) 2016 Daniel Siepmann <coding@daniel-siepmann.de>
|
||||||
|
@ -20,9 +20,9 @@ namespace Leonmrni\SearchCore\Tests\Functional\Hooks\DataHandler;
|
||||||
* 02110-1301, USA.
|
* 02110-1301, USA.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
use Leonmrni\SearchCore\Configuration\ConfigurationContainerInterface;
|
use Codappix\SearchCore\Configuration\ConfigurationContainerInterface;
|
||||||
use Leonmrni\SearchCore\Domain\Service\DataHandler as DataHandlerService;
|
use Codappix\SearchCore\Domain\Service\DataHandler as DataHandlerService;
|
||||||
use Leonmrni\SearchCore\Hook\DataHandler as DataHandlerHook;
|
use Codappix\SearchCore\Hook\DataHandler as DataHandlerHook;
|
||||||
use TYPO3\CMS\Core\DataHandling\DataHandler as Typo3DataHandler;
|
use TYPO3\CMS\Core\DataHandling\DataHandler as Typo3DataHandler;
|
||||||
use TYPO3\CMS\Core\Utility\GeneralUtility;
|
use TYPO3\CMS\Core\Utility\GeneralUtility;
|
||||||
use TYPO3\CMS\Extbase\Object\ObjectManager;
|
use TYPO3\CMS\Extbase\Object\ObjectManager;
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<?php
|
<?php
|
||||||
namespace Leonmrni\SearchCore\Tests\Functional\Hooks\DataHandler;
|
namespace Codappix\SearchCore\Tests\Functional\Hooks\DataHandler;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (C) 2016 Daniel Siepmann <coding@daniel-siepmann.de>
|
* Copyright (C) 2016 Daniel Siepmann <coding@daniel-siepmann.de>
|
||||||
|
@ -20,9 +20,9 @@ namespace Leonmrni\SearchCore\Tests\Functional\Hooks\DataHandler;
|
||||||
* 02110-1301, USA.
|
* 02110-1301, USA.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
use Leonmrni\SearchCore\Configuration\ConfigurationContainerInterface;
|
use Codappix\SearchCore\Configuration\ConfigurationContainerInterface;
|
||||||
use Leonmrni\SearchCore\Domain\Service\DataHandler as DataHandlerService;
|
use Codappix\SearchCore\Domain\Service\DataHandler as DataHandlerService;
|
||||||
use Leonmrni\SearchCore\Hook\DataHandler as DataHandlerHook;
|
use Codappix\SearchCore\Hook\DataHandler as DataHandlerHook;
|
||||||
use TYPO3\CMS\Core\DataHandling\DataHandler as Typo3DataHandler;
|
use TYPO3\CMS\Core\DataHandling\DataHandler as Typo3DataHandler;
|
||||||
use TYPO3\CMS\Core\Utility\GeneralUtility;
|
use TYPO3\CMS\Core\Utility\GeneralUtility;
|
||||||
use TYPO3\CMS\Extbase\Object\ObjectManager;
|
use TYPO3\CMS\Extbase\Object\ObjectManager;
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<?php
|
<?php
|
||||||
namespace Leonmrni\SearchCore\Tests\Functional\Hooks\DataHandler;
|
namespace Codappix\SearchCore\Tests\Functional\Hooks\DataHandler;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (C) 2016 Daniel Siepmann <coding@daniel-siepmann.de>
|
* Copyright (C) 2016 Daniel Siepmann <coding@daniel-siepmann.de>
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<?php
|
<?php
|
||||||
namespace Leonmrni\SearchCore\Tests\Functional\Hooks\DataHandler;
|
namespace Codappix\SearchCore\Tests\Functional\Hooks\DataHandler;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (C) 2016 Daniel Siepmann <coding@daniel-siepmann.de>
|
* Copyright (C) 2016 Daniel Siepmann <coding@daniel-siepmann.de>
|
||||||
|
@ -20,9 +20,9 @@ namespace Leonmrni\SearchCore\Tests\Functional\Hooks\DataHandler;
|
||||||
* 02110-1301, USA.
|
* 02110-1301, USA.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
use Leonmrni\SearchCore\Configuration\ConfigurationContainerInterface;
|
use Codappix\SearchCore\Configuration\ConfigurationContainerInterface;
|
||||||
use Leonmrni\SearchCore\Domain\Service\DataHandler as DataHandlerService;
|
use Codappix\SearchCore\Domain\Service\DataHandler as DataHandlerService;
|
||||||
use Leonmrni\SearchCore\Hook\DataHandler as DataHandlerHook;
|
use Codappix\SearchCore\Hook\DataHandler as DataHandlerHook;
|
||||||
use TYPO3\CMS\Core\DataHandling\DataHandler as Typo3DataHandler;
|
use TYPO3\CMS\Core\DataHandling\DataHandler as Typo3DataHandler;
|
||||||
use TYPO3\CMS\Core\Utility\GeneralUtility;
|
use TYPO3\CMS\Core\Utility\GeneralUtility;
|
||||||
use TYPO3\CMS\Extbase\Object\ObjectManager;
|
use TYPO3\CMS\Extbase\Object\ObjectManager;
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<?php
|
<?php
|
||||||
namespace Leonmrni\SearchCore\Tests\Functional\Hooks\DataHandler;
|
namespace Codappix\SearchCore\Tests\Functional\Hooks\DataHandler;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (C) 2016 Daniel Siepmann <coding@daniel-siepmann.de>
|
* Copyright (C) 2016 Daniel Siepmann <coding@daniel-siepmann.de>
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<?php
|
<?php
|
||||||
namespace Leonmrni\SearchCore\Tests\Indexing\TcaIndexer;
|
namespace Codappix\SearchCore\Tests\Indexing\TcaIndexer;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (C) 2016 Daniel Siepmann <coding@daniel-siepmann.de>
|
* Copyright (C) 2016 Daniel Siepmann <coding@daniel-siepmann.de>
|
||||||
|
@ -20,8 +20,8 @@ namespace Leonmrni\SearchCore\Tests\Indexing\TcaIndexer;
|
||||||
* 02110-1301, USA.
|
* 02110-1301, USA.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
use Leonmrni\SearchCore\Domain\Index\TcaIndexer\TcaTableService;
|
use Codappix\SearchCore\Domain\Index\TcaIndexer\TcaTableService;
|
||||||
use Leonmrni\SearchCore\Tests\Functional\AbstractFunctionalTestCase;
|
use Codappix\SearchCore\Tests\Functional\AbstractFunctionalTestCase;
|
||||||
use TYPO3\CMS\Backend\Utility\BackendUtility;
|
use TYPO3\CMS\Backend\Utility\BackendUtility;
|
||||||
use TYPO3\CMS\Core\Utility\GeneralUtility;
|
use TYPO3\CMS\Core\Utility\GeneralUtility;
|
||||||
use TYPO3\CMS\Extbase\Object\ObjectManager;
|
use TYPO3\CMS\Extbase\Object\ObjectManager;
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<?php
|
<?php
|
||||||
namespace Leonmrni\SearchCore\Tests\Indexing;
|
namespace Codappix\SearchCore\Tests\Indexing;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (C) 2016 Daniel Siepmann <coding@daniel-siepmann.de>
|
* Copyright (C) 2016 Daniel Siepmann <coding@daniel-siepmann.de>
|
||||||
|
@ -20,12 +20,12 @@ namespace Leonmrni\SearchCore\Tests\Indexing;
|
||||||
* 02110-1301, USA.
|
* 02110-1301, USA.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
use Leonmrni\SearchCore\Configuration\ConfigurationContainerInterface;
|
use Codappix\SearchCore\Configuration\ConfigurationContainerInterface;
|
||||||
use Leonmrni\SearchCore\Connection\Elasticsearch;
|
use Codappix\SearchCore\Connection\Elasticsearch;
|
||||||
use Leonmrni\SearchCore\Domain\Index\TcaIndexer;
|
use Codappix\SearchCore\Domain\Index\TcaIndexer;
|
||||||
use Leonmrni\SearchCore\Domain\Index\TcaIndexer\RelationResolver;
|
use Codappix\SearchCore\Domain\Index\TcaIndexer\RelationResolver;
|
||||||
use Leonmrni\SearchCore\Domain\Index\TcaIndexer\TcaTableService;
|
use Codappix\SearchCore\Domain\Index\TcaIndexer\TcaTableService;
|
||||||
use Leonmrni\SearchCore\Tests\Functional\AbstractFunctionalTestCase;
|
use Codappix\SearchCore\Tests\Functional\AbstractFunctionalTestCase;
|
||||||
use TYPO3\CMS\Extbase\Object\ObjectManager;
|
use TYPO3\CMS\Extbase\Object\ObjectManager;
|
||||||
|
|
||||||
class TcaIndexerTest extends AbstractFunctionalTestCase
|
class TcaIndexerTest extends AbstractFunctionalTestCase
|
||||||
|
|
46
Tests/Unit/AbstractUnitTestCase.php
Normal file
46
Tests/Unit/AbstractUnitTestCase.php
Normal file
|
@ -0,0 +1,46 @@
|
||||||
|
<?php
|
||||||
|
namespace Codappix\SearchCore\Tests\Unit;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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 TYPO3\CMS\Core\Tests\UnitTestCase as CoreTestCase;
|
||||||
|
|
||||||
|
abstract class AbstractUnitTestCase extends CoreTestCase
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @return \TYPO3\CMS\Core\Log\LogManager
|
||||||
|
*/
|
||||||
|
protected function getMockedLogger()
|
||||||
|
{
|
||||||
|
$logger = $this->getMockBuilder(\TYPO3\CMS\Core\Log\LogManager::class)
|
||||||
|
->disableOriginalConstructor()
|
||||||
|
->setMethods(['getLogger'])
|
||||||
|
->getMock();
|
||||||
|
$logger->expects($this->once())
|
||||||
|
->method('getLogger')
|
||||||
|
->will($this->returnValue(
|
||||||
|
$this->getMockBuilder(\TYPO3\CMS\Core\Log\Logger::class)
|
||||||
|
->disableOriginalConstructor()
|
||||||
|
->getMock()
|
||||||
|
));
|
||||||
|
|
||||||
|
return $logger;
|
||||||
|
}
|
||||||
|
}
|
94
Tests/Unit/Command/IndexCommandControllerTest.php
Normal file
94
Tests/Unit/Command/IndexCommandControllerTest.php
Normal file
|
@ -0,0 +1,94 @@
|
||||||
|
<?php
|
||||||
|
namespace Codappix\SearchCore\Tests\Unit\Command;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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\Command\IndexCommandController;
|
||||||
|
use Codappix\SearchCore\Domain\Index\IndexerFactory;
|
||||||
|
use Codappix\SearchCore\Domain\Index\NoMatchingIndexerException;
|
||||||
|
use Codappix\SearchCore\Domain\Index\TcaIndexer;
|
||||||
|
use Codappix\SearchCore\Tests\Unit\AbstractUnitTestCase;
|
||||||
|
use TYPO3\CMS\Extbase\Mvc\Controller\CommandController;
|
||||||
|
use TYPO3\CMS\Extbase\Mvc\Exception\StopActionException;
|
||||||
|
|
||||||
|
class IndexCommandControllerTest extends AbstractUnitTestCase
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var IndexCommandController
|
||||||
|
*/
|
||||||
|
protected $subject;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var IndexerFactory
|
||||||
|
*/
|
||||||
|
protected $indexerFactory;
|
||||||
|
|
||||||
|
public function setUp()
|
||||||
|
{
|
||||||
|
parent::setUp();
|
||||||
|
|
||||||
|
$this->indexerFactory = $this->getMockBuilder(IndexerFactory::class)
|
||||||
|
->disableOriginalConstructor()
|
||||||
|
->getMock();
|
||||||
|
|
||||||
|
$this->subject = $this->getMockBuilder(IndexCommandController::class)
|
||||||
|
->disableOriginalConstructor()
|
||||||
|
->setMethods(['quit', 'outputLine'])
|
||||||
|
->getMock();
|
||||||
|
$this->subject->injectIndexerFactory($this->indexerFactory);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @test
|
||||||
|
*/
|
||||||
|
public function indexerStopsForNonAllowedTable()
|
||||||
|
{
|
||||||
|
$this->subject->expects($this->once())
|
||||||
|
->method('outputLine')
|
||||||
|
->with('No indexer found for: nonAllowedTable');
|
||||||
|
$this->indexerFactory->expects($this->once())
|
||||||
|
->method('getIndexer')
|
||||||
|
->with('nonAllowedTable')
|
||||||
|
->will($this->throwException(new NoMatchingIndexerException));
|
||||||
|
|
||||||
|
$this->subject->indexCommand('nonAllowedTable');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @test
|
||||||
|
*/
|
||||||
|
public function indexerExecutesForAllowedTable()
|
||||||
|
{
|
||||||
|
$indexerMock = $this->getMockBuilder(TcaIndexer::class)
|
||||||
|
->disableOriginalConstructor()
|
||||||
|
->getMock();
|
||||||
|
$this->subject->expects($this->never())
|
||||||
|
->method('quit');
|
||||||
|
$this->subject->expects($this->once())
|
||||||
|
->method('outputLine')
|
||||||
|
->with('allowedTable was indexed.');
|
||||||
|
$this->indexerFactory->expects($this->once())
|
||||||
|
->method('getIndexer')
|
||||||
|
->with('allowedTable')
|
||||||
|
->will($this->returnValue($indexerMock));
|
||||||
|
|
||||||
|
$this->subject->indexCommand('allowedTable');
|
||||||
|
}
|
||||||
|
}
|
85
Tests/Unit/Domain/Index/TcaIndexer/TcaTableServiceTest.php
Normal file
85
Tests/Unit/Domain/Index/TcaIndexer/TcaTableServiceTest.php
Normal file
|
@ -0,0 +1,85 @@
|
||||||
|
<?php
|
||||||
|
namespace Codappix\SearchCore\Tests\Unit\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\Domain\Index\TcaIndexer\TcaTableService;
|
||||||
|
use Codappix\SearchCore\Tests\Unit\AbstractUnitTestCase;
|
||||||
|
|
||||||
|
class TcaTableServiceTest extends AbstractUnitTestCase
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var TcaTableService
|
||||||
|
*/
|
||||||
|
protected $subject;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var ConfigurationContainerInterface
|
||||||
|
*/
|
||||||
|
protected $configuration;
|
||||||
|
|
||||||
|
public function setUp()
|
||||||
|
{
|
||||||
|
parent::setUp();
|
||||||
|
|
||||||
|
$this->configuration = $this->getMockBuilder(ConfigurationContainerInterface::class)->getMock();
|
||||||
|
|
||||||
|
$this->subject = $this->getMockBuilder(TcaTableService::class)
|
||||||
|
->disableOriginalConstructor()
|
||||||
|
->setMethodsExcept(['getWhereClause', 'injectLogger', 'getTableName'])
|
||||||
|
->getMock();
|
||||||
|
$this->inject($this->subject, 'configuration', $this->configuration);
|
||||||
|
$this->inject($this->subject, 'logger', $this->getMockedLogger());
|
||||||
|
$this->inject($this->subject, 'tableName', 'table');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @test
|
||||||
|
*/
|
||||||
|
public function doUsePlainQueryIfNoAdditionalWhereClauseIsDefined()
|
||||||
|
{
|
||||||
|
$this->configuration->expects($this->exactly(2))
|
||||||
|
->method('getIfExists')
|
||||||
|
->withConsecutive(['indexing.table.additionalWhereClause'], ['indexing.table.rootLineBlacklist'])
|
||||||
|
->will($this->onConsecutiveCalls(null, false));
|
||||||
|
|
||||||
|
$this->assertSame(
|
||||||
|
'1=1 AND pages.no_search = 0',
|
||||||
|
$this->subject->getWhereClause()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @test
|
||||||
|
*/
|
||||||
|
public function configuredAdditionalWhereClauseIsAdded()
|
||||||
|
{
|
||||||
|
$this->configuration->expects($this->exactly(2))
|
||||||
|
->method('getIfExists')
|
||||||
|
->withConsecutive(['indexing.table.additionalWhereClause'], ['indexing.table.rootLineBlacklist'])
|
||||||
|
->will($this->onConsecutiveCalls('table.field = "someValue"', false));
|
||||||
|
|
||||||
|
$this->assertSame(
|
||||||
|
'1=1 AND pages.no_search = 0 AND table.field = "someValue"',
|
||||||
|
$this->subject->getWhereClause()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
148
Tests/Unit/Domain/Search/QueryFactoryTest.php
Normal file
148
Tests/Unit/Domain/Search/QueryFactoryTest.php
Normal file
|
@ -0,0 +1,148 @@
|
||||||
|
<?php
|
||||||
|
namespace Codappix\SearchCore\Tests\Unit\Domain\Search;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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\Domain\Model\FacetRequest;
|
||||||
|
use Codappix\SearchCore\Domain\Model\SearchRequest;
|
||||||
|
use Codappix\SearchCore\Domain\Search\QueryFactory;
|
||||||
|
use Codappix\SearchCore\Tests\Unit\AbstractUnitTestCase;
|
||||||
|
|
||||||
|
class QueryFactoryTest extends AbstractUnitTestCase
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var QueryFactory
|
||||||
|
*/
|
||||||
|
protected $subject;
|
||||||
|
|
||||||
|
public function setUp()
|
||||||
|
{
|
||||||
|
parent::setUp();
|
||||||
|
|
||||||
|
$this->subject = new QueryFactory($this->getMockedLogger());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @test
|
||||||
|
*/
|
||||||
|
public function creatonOfQueryWorksInGeneral()
|
||||||
|
{
|
||||||
|
$searchRequest = new SearchRequest('SearchWord');
|
||||||
|
|
||||||
|
$query = $this->subject->create($searchRequest);
|
||||||
|
$this->assertInstanceOf(
|
||||||
|
\Elastica\Query::class,
|
||||||
|
$query,
|
||||||
|
'Factory did not create the expected instance.'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @test
|
||||||
|
*/
|
||||||
|
public function filterIsAddedToQuery()
|
||||||
|
{
|
||||||
|
$searchRequest = new SearchRequest('SearchWord');
|
||||||
|
$searchRequest->setFilter(['field' => 'content']);
|
||||||
|
|
||||||
|
$query = $this->subject->create($searchRequest);
|
||||||
|
$this->assertSame(
|
||||||
|
[
|
||||||
|
['term' => ['field' => 'content']]
|
||||||
|
],
|
||||||
|
$query->toArray()['query']['bool']['filter'],
|
||||||
|
'Filter was not added to query.'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @test
|
||||||
|
*/
|
||||||
|
public function emptyFilterIsNotAddedToQuery()
|
||||||
|
{
|
||||||
|
$searchRequest = new SearchRequest('SearchWord');
|
||||||
|
$searchRequest->setFilter([
|
||||||
|
'field' => '',
|
||||||
|
'field1' => 0,
|
||||||
|
'field2' => false,
|
||||||
|
]);
|
||||||
|
|
||||||
|
$this->assertFalse(
|
||||||
|
$searchRequest->hasFilter(),
|
||||||
|
'Search request contains filter even if it should not.'
|
||||||
|
);
|
||||||
|
|
||||||
|
$query = $this->subject->create($searchRequest);
|
||||||
|
$this->assertSame(
|
||||||
|
null,
|
||||||
|
$query->toArray()['query']['bool']['filter'],
|
||||||
|
'Filter was added to query, even if no filter exists.'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @test
|
||||||
|
*/
|
||||||
|
public function userInputIsAlwaysString()
|
||||||
|
{
|
||||||
|
$searchRequest = new SearchRequest(10);
|
||||||
|
$searchRequest->setFilter(['field' => 20]);
|
||||||
|
|
||||||
|
$query = $this->subject->create($searchRequest);
|
||||||
|
$this->assertSame(
|
||||||
|
'10',
|
||||||
|
$query->toArray()['query']['bool']['must'][0]['match']['_all'],
|
||||||
|
'Search word was not escaped as expected.'
|
||||||
|
);
|
||||||
|
$this->assertSame(
|
||||||
|
'20',
|
||||||
|
$query->toArray()['query']['bool']['filter'][0]['term']['field'],
|
||||||
|
'Search word was not escaped as expected.'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @test
|
||||||
|
*/
|
||||||
|
public function facetsAreAddedToQuery()
|
||||||
|
{
|
||||||
|
$searchRequest = new SearchRequest('SearchWord');
|
||||||
|
$searchRequest->addFacet(new FacetRequest('Identifier', 'FieldName'));
|
||||||
|
$searchRequest->addFacet(new FacetRequest('Identifier 2', 'FieldName 2'));
|
||||||
|
|
||||||
|
$query = $this->subject->create($searchRequest);
|
||||||
|
$this->assertSame(
|
||||||
|
[
|
||||||
|
'Identifier' => [
|
||||||
|
'terms' => [
|
||||||
|
'field' => 'FieldName',
|
||||||
|
],
|
||||||
|
],
|
||||||
|
'Identifier 2' => [
|
||||||
|
'terms' => [
|
||||||
|
'field' => 'FieldName 2',
|
||||||
|
],
|
||||||
|
],
|
||||||
|
],
|
||||||
|
$query->toArray()['aggs'],
|
||||||
|
'Facets were not added to query.'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
28
Tests/Unit/UnitTests.xml
Normal file
28
Tests/Unit/UnitTests.xml
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
<phpunit
|
||||||
|
backupGlobals="false"
|
||||||
|
backupStaticAttributes="false"
|
||||||
|
bootstrap="../../.Build/vendor/typo3/cms/typo3/sysext/core/Build/UnitTestsBootstrap.php"
|
||||||
|
|
||||||
|
colors="true"
|
||||||
|
convertErrorsToExceptions="false"
|
||||||
|
convertWarningsToExceptions="false"
|
||||||
|
forceCoversAnnotation="false"
|
||||||
|
processIsolation="false"
|
||||||
|
stopOnError="false"
|
||||||
|
stopOnFailure="false"
|
||||||
|
stopOnIncomplete="false"
|
||||||
|
stopOnSkipped="false"
|
||||||
|
verbose="false">
|
||||||
|
|
||||||
|
<testsuites>
|
||||||
|
<testsuite name="unit-tests">
|
||||||
|
<directory>.</directory>
|
||||||
|
</testsuite>
|
||||||
|
</testsuites>
|
||||||
|
|
||||||
|
<filter>
|
||||||
|
<whitelist>
|
||||||
|
<directory suffix=".php">../../Classes</directory>
|
||||||
|
</whitelist>
|
||||||
|
</filter>
|
||||||
|
</phpunit>
|
|
@ -1,17 +1,17 @@
|
||||||
{
|
{
|
||||||
"name": "leonmrni/search_core",
|
"name": "codappix/search_core",
|
||||||
"type": "typo3-cms-extension",
|
"type": "typo3-cms-extension",
|
||||||
"description": "Leonmrni Search Core.",
|
"description": "Codappix Search Core.",
|
||||||
"homepage": "http://www.leonmrni.com",
|
"homepage": "https://github.com/Codappix/search_core",
|
||||||
"license": ["GPL-2.0+"],
|
"license": ["GPL-2.0+"],
|
||||||
"autoload": {
|
"autoload": {
|
||||||
"psr-4": {
|
"psr-4": {
|
||||||
"Leonmrni\\SearchCore\\": "Classes"
|
"Codappix\\SearchCore\\": "Classes"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"autoload-dev": {
|
"autoload-dev": {
|
||||||
"psr-4": {
|
"psr-4": {
|
||||||
"Leonmrni\\SearchCore\\Tests\\": "Tests/",
|
"Codappix\\SearchCore\\Tests\\": "Tests/",
|
||||||
"TYPO3\\CMS\\Core\\Tests\\": ".Build/vendor/typo3/cms/typo3/sysext/core/Tests/"
|
"TYPO3\\CMS\\Core\\Tests\\": ".Build/vendor/typo3/cms/typo3/sysext/core/Tests/"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
|
@ -4,6 +4,7 @@ $EM_CONF[$_EXTKEY] = [
|
||||||
'title' => 'Search Core',
|
'title' => 'Search Core',
|
||||||
'description' => 'Search core for implementing various search types.',
|
'description' => 'Search core for implementing various search types.',
|
||||||
'category' => 'be',
|
'category' => 'be',
|
||||||
|
'clearCacheOnLoad' => 1,
|
||||||
'constraints' => [
|
'constraints' => [
|
||||||
'depends' => [
|
'depends' => [
|
||||||
'typo3' => '7.6.0-7.6.99',
|
'typo3' => '7.6.0-7.6.99',
|
||||||
|
@ -13,12 +14,11 @@ $EM_CONF[$_EXTKEY] = [
|
||||||
],
|
],
|
||||||
'autoload' => [
|
'autoload' => [
|
||||||
'psr-4' => [
|
'psr-4' => [
|
||||||
'Leonmrni\\SearchCore\\' => 'Classes',
|
'Codappix\\SearchCore\\' => 'Classes',
|
||||||
],
|
],
|
||||||
],
|
],
|
||||||
'state' => 'alpha',
|
'state' => 'beta',
|
||||||
'clearCacheOnLoad' => 1,
|
'version' => '1.0.0',
|
||||||
'author' => 'Daniel Siepmann',
|
'author' => 'Daniel Siepmann',
|
||||||
'author_email' => 'coding@daniel-siepmann.de',
|
'author_email' => 'coding@daniel-siepmann.de',
|
||||||
'version' => '1.0.0',
|
|
||||||
];
|
];
|
||||||
|
|
|
@ -11,15 +11,15 @@ call_user_func(
|
||||||
'SC_OPTIONS' => [
|
'SC_OPTIONS' => [
|
||||||
'extbase' => [
|
'extbase' => [
|
||||||
'commandControllers' => [
|
'commandControllers' => [
|
||||||
Leonmrni\SearchCore\Command\IndexCommandController::class,
|
Codappix\SearchCore\Command\IndexCommandController::class,
|
||||||
],
|
],
|
||||||
],
|
],
|
||||||
't3lib/class.t3lib_tcemain.php' => [
|
't3lib/class.t3lib_tcemain.php' => [
|
||||||
'processCmdmapClass' => [
|
'processCmdmapClass' => [
|
||||||
$extensionKey => '&' . \Leonmrni\SearchCore\Hook\DataHandler::class,
|
$extensionKey => '&' . \Codappix\SearchCore\Hook\DataHandler::class,
|
||||||
],
|
],
|
||||||
'processDatamapClass' => [
|
'processDatamapClass' => [
|
||||||
$extensionKey => '&' . \Leonmrni\SearchCore\Hook\DataHandler::class,
|
$extensionKey => '&' . \Codappix\SearchCore\Hook\DataHandler::class,
|
||||||
],
|
],
|
||||||
],
|
],
|
||||||
],
|
],
|
||||||
|
@ -27,7 +27,7 @@ call_user_func(
|
||||||
);
|
);
|
||||||
|
|
||||||
TYPO3\CMS\Extbase\Utility\ExtensionUtility::configurePlugin(
|
TYPO3\CMS\Extbase\Utility\ExtensionUtility::configurePlugin(
|
||||||
'Leonmrni.' . $extensionKey,
|
'Codappix.' . $extensionKey,
|
||||||
'search',
|
'search',
|
||||||
[
|
[
|
||||||
'Search' => 'search'
|
'Search' => 'search'
|
||||||
|
@ -39,8 +39,8 @@ call_user_func(
|
||||||
|
|
||||||
\TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance('TYPO3\CMS\Extbase\Object\Container\Container')
|
\TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance('TYPO3\CMS\Extbase\Object\Container\Container')
|
||||||
->registerImplementation(
|
->registerImplementation(
|
||||||
'Leonmrni\SearchCore\Connection\ConnectionInterface',
|
'Codappix\SearchCore\Connection\ConnectionInterface',
|
||||||
'Leonmrni\SearchCore\Connection\Elasticsearch'
|
'Codappix\SearchCore\Connection\Elasticsearch'
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
$_EXTKEY
|
$_EXTKEY
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
);
|
);
|
||||||
|
|
||||||
TYPO3\CMS\Extbase\Utility\ExtensionUtility::registerPlugin(
|
TYPO3\CMS\Extbase\Utility\ExtensionUtility::registerPlugin(
|
||||||
'Leonmrni.' . $_EXTKEY,
|
'Codappix.' . $_EXTKEY,
|
||||||
'search',
|
'search',
|
||||||
'Search Core'
|
'Search Core'
|
||||||
);
|
);
|
||||||
|
|
Loading…
Reference in a new issue