diff --git a/Classes/Connection/SearchRequestInterface.php b/Classes/Connection/SearchRequestInterface.php index ee779f7..7ec34ff 100644 --- a/Classes/Connection/SearchRequestInterface.php +++ b/Classes/Connection/SearchRequestInterface.php @@ -41,4 +41,11 @@ interface SearchRequestInterface * @return array */ public function getFilter(); + + /** + * Defines how many results should be fetched. + * + * @return int + */ + public function getSize(); } diff --git a/Classes/Domain/Model/SearchRequest.php b/Classes/Domain/Model/SearchRequest.php index 163f65a..7850b98 100644 --- a/Classes/Domain/Model/SearchRequest.php +++ b/Classes/Domain/Model/SearchRequest.php @@ -35,6 +35,11 @@ class SearchRequest implements SearchRequestInterface */ protected $query = ''; + /** + * @var int + */ + protected $size = 10; + /** * @var array */ @@ -112,4 +117,20 @@ class SearchRequest implements SearchRequestInterface { return $this->facets; } + + /** + * @return int + */ + public function getSize() + { + return $this->size; + } + + /** + * @param int $size + */ + public function setSize($size) + { + $this->size = (int) $size; + } } diff --git a/Classes/Domain/Search/QueryFactory.php b/Classes/Domain/Search/QueryFactory.php index 7809fb6..128e556 100644 --- a/Classes/Domain/Search/QueryFactory.php +++ b/Classes/Domain/Search/QueryFactory.php @@ -63,6 +63,7 @@ class QueryFactory */ protected function createElasticaQuery(SearchRequestInterface $searchRequest) { + $this->addSize($searchRequest); $this->addSearch($searchRequest); $this->addFilter($searchRequest); $this->addFacets($searchRequest); @@ -71,6 +72,17 @@ class QueryFactory return new \Elastica\Query($this->query); } + /** + * @param SearchRequestInterface $searchRequest + */ + protected function addSize(SearchRequestInterface $searchRequest) + { + $this->query = ArrayUtility::arrayMergeRecursiveOverrule($this->query, [ + 'from' => 0, + 'size' => $searchRequest->getSize(), + ]); + } + /** * @param SearchRequestInterface $searchRequest */ diff --git a/Classes/Domain/Search/SearchService.php b/Classes/Domain/Search/SearchService.php index 158d9d1..aaed496 100644 --- a/Classes/Domain/Search/SearchService.php +++ b/Classes/Domain/Search/SearchService.php @@ -69,11 +69,23 @@ class SearchService */ public function search(SearchRequestInterface $searchRequest) { + $this->addSize($searchRequest); $this->addConfiguredFacets($searchRequest); return $this->connection->search($searchRequest); } + /** + * Add configured size of search result items to request. + * + * @param SearchRequestInterface $searchRequest + */ + protected function addSize(SearchRequestInterface $searchRequest) + { + $size = $this->configuration->getIfExists('searching.size') ?: 10; + $searchRequest->setSize($size); + } + /** * Add facets from configuration to request. * diff --git a/Documentation/source/configuration.rst b/Documentation/source/configuration.rst index 3d8db75..4555cb1 100644 --- a/Documentation/source/configuration.rst +++ b/Documentation/source/configuration.rst @@ -189,6 +189,21 @@ options are available: Searching ^^^^^^^^^ +.. _size: + +``size`` +"""""""" + + Used by: Elasticsearch connection while building search query. + + Defined how many search results should be fetched to be available in search result. + + Example:: + + plugin.tx_searchcore.settings.searching.size = 50 + + Default if not configured is 10. + .. _facets: ``facets`` diff --git a/Tests/Unit/Domain/Search/QueryFactoryTest.php b/Tests/Unit/Domain/Search/QueryFactoryTest.php index 32c8fbd..56b0b03 100644 --- a/Tests/Unit/Domain/Search/QueryFactoryTest.php +++ b/Tests/Unit/Domain/Search/QueryFactoryTest.php @@ -145,4 +145,20 @@ class QueryFactoryTest extends AbstractUnitTestCase 'Facets were not added to query.' ); } + + /** + * @test + */ + public function sizeIsAddedToQuery() + { + $searchRequest = new SearchRequest('SearchWord'); + $searchRequest->setSize(45); + + $query = $this->subject->create($searchRequest); + $this->assertSame( + 45, + $query->toArray()['size'], + 'Size was not added to query.' + ); + } } diff --git a/Tests/Unit/Domain/Search/SearchServiceTest.php b/Tests/Unit/Domain/Search/SearchServiceTest.php new file mode 100644 index 0000000..6a90a3c --- /dev/null +++ b/Tests/Unit/Domain/Search/SearchServiceTest.php @@ -0,0 +1,95 @@ + + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +use Codappix\SearchCore\Configuration\ConfigurationContainerInterface; +use Codappix\SearchCore\Connection\ConnectionInterface; +use Codappix\SearchCore\Domain\Model\SearchRequest; +use Codappix\SearchCore\Domain\Search\SearchService; +use Codappix\SearchCore\Tests\Unit\AbstractUnitTestCase; +use TYPO3\CMS\Extbase\Object\ObjectManagerInterface; + +class SearchServiceTest extends AbstractUnitTestCase +{ + /** + * @var SearchService + */ + protected $subject; + + public function setUp() + { + parent::setUp(); + + $this->connection = $this->getMockBuilder(ConnectionInterface::class) + ->disableOriginalConstructor() + ->getMock(); + $this->configuration = $this->getMockBuilder(ConfigurationContainerInterface::class) + ->disableOriginalConstructor() + ->getMock(); + $this->objectManager = $this->getMockBuilder(ObjectManagerInterface::class) + ->disableOriginalConstructor() + ->getMock(); + + $this->subject = new SearchService( + $this->connection, + $this->configuration, + $this->objectManager + ); + } + + /** + * @test + */ + public function sizeIsAddedFromConfiguration() + { + $this->configuration->expects($this->exactly(2)) + ->method('getIfExists') + ->withConsecutive(['searching.size'], ['searching.facets']) + ->will($this->onConsecutiveCalls(45, null)); + $this->connection->expects($this->once()) + ->method('search') + ->with($this->callback(function ($searchRequest) { + return $searchRequest->getSize() === 45; + })); + + $searchRequest = new SearchRequest('SearchWord'); + $this->subject->search($searchRequest); + } + + /** + * @test + */ + public function defaultSizeIsAddedIfNothingIsConfigured() + { + $this->configuration->expects($this->exactly(2)) + ->method('getIfExists') + ->withConsecutive(['searching.size'], ['searching.facets']) + ->will($this->onConsecutiveCalls(null, null)); + $this->connection->expects($this->once()) + ->method('search') + ->with($this->callback(function ($searchRequest) { + return $searchRequest->getSize() === 10; + })); + + $searchRequest = new SearchRequest('SearchWord'); + $this->subject->search($searchRequest); + } +}