TASK: Integrate working code

Copied code from customer installation with working implementation.
This commit is contained in:
Daniel Siepmann 2017-07-06 12:03:52 +02:00
parent 432335c80d
commit 975381cc4a
Signed by: Daniel Siepmann
GPG key ID: 33D6629915560EF4
18 changed files with 832 additions and 33 deletions

View file

@ -34,6 +34,8 @@ interface ConfigurationContainerInterface extends Singleton
*
* @param string $path In dot notation. E.g. indexer.tca.allowedTables
* @return mixed
*
* @throws InvalidArgumentException
*/
public function get($path);

View file

@ -20,8 +20,10 @@ namespace Leonmrni\SearchCore\Connection;
* 02110-1301, USA.
*/
use TYPO3\CMS\Core\SingletonInterface as Singleton;
use Leonmrni\SearchCore\Connection\Elasticsearch\SearchResult;
use Leonmrni\SearchCore\Domain\Search\QueryFactory;
use TYPO3\CMS\Core\SingletonInterface as Singleton;
use TYPO3\CMS\Extbase\Object\ObjectManagerInterface;
/**
* Outer wrapper to elasticsearch.
@ -43,6 +45,11 @@ class Elasticsearch implements Singleton, ConnectionInterface
*/
protected $typeFactory;
/**
* @var Elasticsearch\MappingFactory
*/
protected $mappingFactory;
/**
* @var Elasticsearch\DocumentFactory
*/
@ -58,6 +65,11 @@ class Elasticsearch implements Singleton, ConnectionInterface
*/
protected $logger;
/**
* @var ObjectManagerInterface
*/
protected $objectManager;
/**
* Inject log manager to get concrete logger from it.
*
@ -68,10 +80,19 @@ class Elasticsearch implements Singleton, ConnectionInterface
$this->logger = $logManager->getLogger(__CLASS__);
}
/**
* @param ObjectManagerInterface $objectManager
*/
public function injectObjectManager(ObjectManagerInterface $objectManager)
{
$this->objectManager = $objectManager;
}
/**
* @param Elasticsearch\Connection $connection
* @param Elasticsearch\IndexFactory $indexFactory
* @param Elasticsearch\TypeFactory $typeFactory
* @param Elasticsearch\MappingFactory $mappingFactory
* @param Elasticsearch\DocumentFactory $documentFactory
* @param QueryFactory $queryFactory
*/
@ -79,12 +100,14 @@ class Elasticsearch implements Singleton, ConnectionInterface
Elasticsearch\Connection $connection,
Elasticsearch\IndexFactory $indexFactory,
Elasticsearch\TypeFactory $typeFactory,
Elasticsearch\MappingFactory $mappingFactory,
Elasticsearch\DocumentFactory $documentFactory,
QueryFactory $queryFactory
) {
$this->connection = $connection;
$this->indexFactory = $indexFactory;
$this->typeFactory = $typeFactory;
$this->mappingFactory = $mappingFactory;
$this->documentFactory = $documentFactory;
$this->queryFactory = $queryFactory;
}
@ -142,6 +165,13 @@ class Elasticsearch implements Singleton, ConnectionInterface
protected function withType($documentType, callable $callback)
{
$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);
$type->getIndex()->refresh();
}
@ -149,7 +179,7 @@ class Elasticsearch implements Singleton, ConnectionInterface
/**
* @param SearchRequestInterface $searchRequest
*
* @return \Elastica\ResultSet
* @return SearchResultInterface
*/
public function search(SearchRequestInterface $searchRequest)
{
@ -157,11 +187,9 @@ class Elasticsearch implements Singleton, ConnectionInterface
$search = new \Elastica\Search($this->connection->getClient());
$search->addIndex('typo3content');
$search->setQuery($this->queryFactory->create($this, $searchRequest));
$search->setQuery($this->queryFactory->create($searchRequest));
// TODO: Return wrapped result to implement our interface.
// Also update php doc to reflect the change.
return $search->search();
return $this->objectManager->get(SearchResult::class, $search->search());
}
/**

View file

@ -0,0 +1,93 @@
<?php
namespace Leonmrni\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 Leonmrni\SearchCore\Configuration\ConfigurationContainerInterface;
use Leonmrni\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);
}
}
}

View file

@ -0,0 +1,61 @@
<?php
namespace Leonmrni\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 Leonmrni\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;
}
}

View file

@ -0,0 +1,73 @@
<?php
namespace Leonmrni\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 Leonmrni\SearchCore\Configuration\ConfigurationContainerInterface;
use Leonmrni\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 [];
}
}
}

View file

@ -0,0 +1,56 @@
<?php
namespace Leonmrni\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 Leonmrni\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()
{
throw new \BadMethodCallException('It\'s not possible to change the search result.', 1499179077);
}
public function offsetUnset()
{
throw new \BadMethodCallException('It\'s not possible to change the search result.', 1499179077);
}
}

View file

@ -20,12 +20,127 @@ namespace Leonmrni\SearchCore\Connection\Elasticsearch;
* 02110-1301, USA.
*/
use Leonmrni\SearchCore\Connection\FacetInterface;
use Leonmrni\SearchCore\Connection\ResultItemInterface;
use Leonmrni\SearchCore\Connection\SearchResultInterface;
use TYPO3\CMS\Extbase\Object\ObjectManagerInterface;
class SearchResult implements SearchResultInterface
{
/**
* @var \Elastica\ResultSet
*/
protected $result;
/**
*
* @var array<FacetInterface>
*/
class SearchResult extends \Elastica\SearchResult implements SearchResultInterface
{
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);
}
}
}

View file

@ -0,0 +1,39 @@
<?php
namespace Leonmrni\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();
}

View file

@ -0,0 +1,42 @@
<?php
namespace Leonmrni\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();
}

View file

@ -0,0 +1,42 @@
<?php
namespace Leonmrni\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();
}

View file

@ -0,0 +1,29 @@
<?php
namespace Leonmrni\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
{
}

View file

@ -21,9 +21,19 @@ 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();
}

View file

@ -45,6 +45,7 @@ class IndexerFactory implements Singleton
/**
* @param ObjectManagerInterface $objectManager
* @param ConfigurationContainerInterface $configuration
*/
public function __construct(
ObjectManagerInterface $objectManager,

View file

@ -20,7 +20,6 @@ namespace Leonmrni\SearchCore\Domain\Index;
* 02110-1301, USA.
*/
use TYPO3\CMS\Extbase\Object\ObjectManagerInterface;
use Leonmrni\SearchCore\Connection\ConnectionInterface;
/**

View file

@ -0,0 +1,62 @@
<?php
namespace Leonmrni\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 Leonmrni\SearchCore\Connection\FacetRequestInterface;
class FacetRequest implements FacetRequestInterface
{
/**
* @var string
*/
protected $identifier = '';
/**
* @var string
*/
protected $field = '';
/**
* @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;
}
}

View file

@ -20,6 +20,7 @@ namespace Leonmrni\SearchCore\Domain\Model;
* 02110-1301, USA.
*/
use Leonmrni\SearchCore\Connection\FacetRequestInterface;
use Leonmrni\SearchCore\Connection\SearchRequestInterface;
/**
@ -39,6 +40,11 @@ class SearchRequest implements SearchRequestInterface
*/
protected $filter = [];
/**
* @var array
*/
protected $facets = [];
/**
* @param string $query
*/
@ -68,7 +74,7 @@ class SearchRequest implements SearchRequestInterface
*/
public function setFilter(array $filter)
{
$this->filter = array_map('strval', $filter);
$this->filter = array_filter(array_map('strval', $filter));
}
/**
@ -86,4 +92,24 @@ class SearchRequest implements SearchRequestInterface
{
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;
}
}

View file

@ -23,29 +23,62 @@ namespace Leonmrni\SearchCore\Domain\Search;
use Leonmrni\SearchCore\Connection\ConnectionInterface;
use Leonmrni\SearchCore\Connection\Elasticsearch\Query;
use Leonmrni\SearchCore\Connection\SearchRequestInterface;
use TYPO3\CMS\Extbase\Utility\ArrayUtility;
class QueryFactory
{
/**
* @param ConnectionInterface $connection
* @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(
ConnectionInterface $connection,
SearchRequestInterface $searchRequest
) {
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)
{
$query = [
$this->addSearch($searchRequest);
$this->addFilter($searchRequest);
$this->addFacets($searchRequest);
// TODO: Add logging here.
$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' => [
[
@ -55,12 +88,52 @@ class QueryFactory
],
],
],
],
]);
}
/**
* @param SearchRequestInterface $searchRequest
*/
protected function addFilter(SearchRequestInterface $searchRequest)
{
if (! $searchRequest->hasFilter()) {
return;
}
$terms = [];
foreach ($searchRequest->getFilter() as $name => $value) {
$terms[] = [
'term' => [
$name => $value,
],
];
if ($searchRequest->hasFilter()) {
$query['bool']['filter'] = ['term' => $searchRequest->getFilter()];
}
return new \Elastica\Query(['query' => $query]);
$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(),
],
],
],
]);
}
}
}

View file

@ -20,10 +20,13 @@ namespace Leonmrni\SearchCore\Domain\Search;
* 02110-1301, USA.
*/
use Leonmrni\SearchCore\Configuration\ConfigurationContainerInterface;
use Leonmrni\SearchCore\Configuration\InvalidArgumentException;
use Leonmrni\SearchCore\Connection\ConnectionInterface;
use Leonmrni\SearchCore\Connection\SearchRequestInterface;
use Leonmrni\SearchCore\Connection\SearchResultInterface;
use Leonmrni\SearchCore\Domain\Model\SearchRequest;
use Leonmrni\SearchCore\Domain\Model\FacetRequest;
use TYPO3\CMS\Extbase\Object\ObjectManagerInterface;
/**
* Service to process a search request.
@ -36,11 +39,28 @@ class SearchService
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->configuration = $configuration;
$this->objectManager = $objectManager;
}
/**
@ -49,6 +69,34 @@ class SearchService
*/
public function search(SearchRequestInterface $searchRequest)
{
$this->addConfiguredFacets($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']
));
}
}
}