diff --git a/README.md b/README.md index cfa9968c..089cca33 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ [![Read the Docs](https://img.shields.io/readthedocs/pip.svg?style=flat-square)](https://netgen-ezplatform-search-extra.readthedocs.io/en/latest/index.html) [![Downloads](https://img.shields.io/packagist/dt/netgen/ezplatform-search-extra.svg?style=flat-square)](https://packagist.org/packages/netgen/ezplatform-search-extra) [![Latest stable](https://img.shields.io/github/release/netgen/ezplatform-search-extra.svg?style=flat-square)](https://packagist.org/packages/netgen/ezplatform-search-extra) -[![eZ](https://img.shields.io/badge/eZ%20Platform-%E2%89%A5%203.1-orange.svg?style=flat-square)](https://ezplatform.com/) +[![eZ](https://img.shields.io/badge/eZ%20Platform-%E2%89%A5%203.2-orange.svg?style=flat-square)](https://ezplatform.com/) [![License](https://img.shields.io/github/license/netgen/ezplatform-search-extra.svg?style=flat-square)](https://packagist.org/packages/netgen/ezplatform-search-extra) ### Note: release compatible with eZ Platform v2 is `1.14`. diff --git a/composer.json b/composer.json index 8acffcc4..a82ab511 100644 --- a/composer.json +++ b/composer.json @@ -10,7 +10,7 @@ } ], "require": { - "ezsystems/ezplatform-kernel": "^1.1", + "ezsystems/ezplatform-kernel": "^1.2", "ext-json": "*", "ext-dom": "*" }, diff --git a/lib/Container/Compiler/SearchResultExtractorPass.php b/lib/Container/Compiler/SearchResultExtractorPass.php index be962990..89be5a12 100644 --- a/lib/Container/Compiler/SearchResultExtractorPass.php +++ b/lib/Container/Compiler/SearchResultExtractorPass.php @@ -1,9 +1,10 @@ getParameter( 'netgen_ez_platform_search_extra.use_loading_search_result_extractor' @@ -30,8 +31,8 @@ public function process(ContainerBuilder $container) return; } - $serviceId = 'netgen.search.solr.result_extractor.native_override'; - $decoratedServiceId = 'ezpublish.search.solr.result_extractor.native'; + $serviceId = 'netgen.search.solr.result_extractor.content.native_override'; + $decoratedServiceId = 'ezpublish.search.solr.result_extractor.content.native'; $container ->register($serviceId, NativeResultExtractor::class) @@ -39,6 +40,20 @@ public function process(ContainerBuilder $container) ->setArguments([ new Reference($serviceId . '.inner'), new Reference('ezpublish.search.solr.query.content.facet_builder_visitor.aggregate'), + new Reference('ezpublish.search.solr.query.content.aggregation_result_extractor.dispatcher'), + new Reference('ezpublish.search.solr.gateway.endpoint_registry'), + ]); + + $serviceId = 'netgen.search.solr.result_extractor.location.native_override'; + $decoratedServiceId = 'ezpublish.search.solr.result_extractor.location.native'; + + $container + ->register($serviceId, NativeResultExtractor::class) + ->setDecoratedService($decoratedServiceId) + ->setArguments([ + new Reference($serviceId . '.inner'), + new Reference('ezpublish.search.solr.query.location.facet_builder_visitor.aggregate'), + new Reference('ezpublish.search.solr.query.location.aggregation_result_extractor.dispatcher'), new Reference('ezpublish.search.solr.gateway.endpoint_registry'), ]); } diff --git a/lib/Core/Pagination/Pagerfanta/BaseAdapter.php b/lib/Core/Pagination/Pagerfanta/BaseAdapter.php index 5e324479..ea1f103e 100644 --- a/lib/Core/Pagination/Pagerfanta/BaseAdapter.php +++ b/lib/Core/Pagination/Pagerfanta/BaseAdapter.php @@ -1,8 +1,11 @@ query = $query; } - public function getNbResults() + public function getNbResults(): int { $this->initializeExtraInfo(); return $this->nbResults; } - public function getFacets() + public function getFacets(): array { $this->initializeExtraInfo(); return $this->facets; } - public function getMaxScore() + public function getAggregations(): AggregationResultCollection + { + $this->initializeExtraInfo(); + + return $this->aggregations; + } + + public function getMaxScore(): float { $this->initializeExtraInfo(); return $this->maxScore; } - public function getSuggestion() + public function getSuggestion(): Suggestion { $this->initializeExtraInfo(); return $this->suggestion; } - public function getTime() + public function getTime(): ?int { return $this->time; } @@ -115,9 +127,9 @@ public function getSlice($offset, $length) * * @return \eZ\Publish\API\Repository\Values\Content\Search\SearchResult */ - abstract protected function executeQuery(Query $query); + abstract protected function executeQuery(Query $query): SearchResult; - private function initializeExtraInfo() + private function initializeExtraInfo(): void { if ($this->isExtraInfoInitialized) { return; @@ -130,9 +142,10 @@ private function initializeExtraInfo() $this->setExtraInfo($searchResult); } - private function setExtraInfo(SearchResult $searchResult) + private function setExtraInfo(SearchResult $searchResult): void { $this->facets = $searchResult->facets; + $this->aggregations = $searchResult->aggregations; $this->maxScore = $searchResult->maxScore; $this->nbResults = $searchResult->totalCount; $this->suggestion = new Suggestion([]); diff --git a/lib/Core/Pagination/Pagerfanta/SearchAdapter.php b/lib/Core/Pagination/Pagerfanta/SearchAdapter.php index f10b6bdb..f06210f3 100644 --- a/lib/Core/Pagination/Pagerfanta/SearchAdapter.php +++ b/lib/Core/Pagination/Pagerfanta/SearchAdapter.php @@ -1,16 +1,16 @@ searchService->findLocations($query); diff --git a/lib/Core/Pagination/Pagerfanta/SearchHandlerAdapter.php b/lib/Core/Pagination/Pagerfanta/SearchHandlerAdapter.php index d179bf8a..572d3dde 100644 --- a/lib/Core/Pagination/Pagerfanta/SearchHandlerAdapter.php +++ b/lib/Core/Pagination/Pagerfanta/SearchHandlerAdapter.php @@ -1,16 +1,16 @@ searchHandler->findLocations($query); diff --git a/lib/Core/Pagination/Pagerfanta/Slice.php b/lib/Core/Pagination/Pagerfanta/Slice.php index 1c9a3bcd..cece58c8 100644 --- a/lib/Core/Pagination/Pagerfanta/Slice.php +++ b/lib/Core/Pagination/Pagerfanta/Slice.php @@ -1,5 +1,7 @@ searchHits); } @@ -52,12 +54,12 @@ public function offsetGet($offset) return $this->searchHits[$offset]->valueObject; } - public function offsetSet($offset, $value) + public function offsetSet($offset, $value): void { throw new RuntimeException('Method ' . __METHOD__ . ' is not supported'); } - public function offsetUnset($offset) + public function offsetUnset($offset): void { throw new RuntimeException('Method ' . __METHOD__ . ' is not supported'); } diff --git a/lib/Core/Pagination/SearchResultExtras.php b/lib/Core/Pagination/SearchResultExtras.php index 5093882c..534e12b1 100644 --- a/lib/Core/Pagination/SearchResultExtras.php +++ b/lib/Core/Pagination/SearchResultExtras.php @@ -1,7 +1,11 @@ criterionVisitor = $criterionVisitor; $this->sortClauseVisitor = $sortClauseVisitor; $this->facetBuilderVisitor = $facetBuilderVisitor; + $this->aggregationVisitor = $aggregationVisitor; } - public function convert(Query $query) + public function convert(Query $query, array $languageSettings = []): array { $params = [ 'q' => '{!lucene}' . $this->criterionVisitor->visit($query->query), @@ -77,6 +59,24 @@ public function convert(Query $query) $params = array_merge($oldFacetParams, $params); } + if (!empty($query->aggregations)) { + $aggregations = []; + + foreach ($query->aggregations as $aggregation) { + if ($this->aggregationVisitor->canVisit($aggregation, $languageSettings)) { + $aggregations[$aggregation->getName()] = $this->aggregationVisitor->visit( + $this->aggregationVisitor, + $aggregation, + $languageSettings + ); + } + } + + if (!empty($aggregations)) { + $params['json.facet'] = json_encode($aggregations); + } + } + if ($query->query instanceof FulltextSpellcheck) { $spellcheckQuery = $query->query->getSpellcheckQuery(); @@ -98,7 +98,7 @@ public function convert(Query $query) * * @return string */ - private function getSortParams(array $sortClauses) + private function getSortParams(array $sortClauses): string { return implode( ', ', @@ -114,7 +114,7 @@ private function getSortParams(array $sortClauses) * * @return array */ - private function getFacetParams(array $facetBuilders) + private function getFacetParams(array $facetBuilders): array { $facetParams = []; $facetBuilders = $this->filterNewFacetBuilders($facetBuilders); @@ -136,11 +136,11 @@ private function getFacetParams(array $facetBuilders) * * @return \eZ\Publish\API\Repository\Values\Content\Query\FacetBuilder[] */ - private function filterNewFacetBuilders(array $facetBuilders) + private function filterNewFacetBuilders(array $facetBuilders): array { return array_filter( $facetBuilders, - function ($facetBuilder) { + static function ($facetBuilder) { return $facetBuilder instanceof RawFacetBuilder; } ); @@ -156,7 +156,7 @@ function ($facetBuilder) { * * @return array */ - private function getOldFacetParams(array $facetBuilders) + private function getOldFacetParams(array $facetBuilders): array { $facetParamsGrouped = array_map( function ($facetBuilder) { @@ -173,17 +173,17 @@ function ($facetBuilder) { * * @return \eZ\Publish\API\Repository\Values\Content\Query\FacetBuilder[] */ - private function filterOldFacetBuilders(array $facetBuilders) + private function filterOldFacetBuilders(array $facetBuilders): array { return array_filter( $facetBuilders, - function ($facetBuilder) { + static function ($facetBuilder) { return !($facetBuilder instanceof RawFacetBuilder); } ); } - private function formatOldFacetParams(array $facetParamsGrouped) + private function formatOldFacetParams(array $facetParamsGrouped): array { $params = []; diff --git a/lib/Core/Search/Solr/ResultExtractor.php b/lib/Core/Search/Solr/ResultExtractor.php index 9ff759ef..2b303e49 100644 --- a/lib/Core/Search/Solr/ResultExtractor.php +++ b/lib/Core/Search/Solr/ResultExtractor.php @@ -1,9 +1,13 @@ extractSearchResult($data, $facetBuilders); + public function extract( + $data, + array $facetBuilders = [], + array $aggregations = [], + array $languageFilter = [] + ): SearchResult { + $searchResult = $this->extractSearchResult( + $data, + $facetBuilders, + $aggregations, + $languageFilter + ); if (!isset($data->facets) || $data->facets->count === 0) { return $searchResult; } foreach ($this->filterNewFacetBuilders($facetBuilders) as $facetBuilder) { - $identifier = \spl_object_hash($facetBuilder); + $identifier = spl_object_hash($facetBuilder); $searchResult->facets[] = $this->facetBuilderVisitor->mapField( $identifier, @@ -38,21 +51,28 @@ public function extract($data, array $facetBuilders = []) * * @param mixed $data * @param \eZ\Publish\API\Repository\Values\Content\Query\FacetBuilder[] $facetBuilders + * @param \eZ\Publish\API\Repository\Values\Content\Query\Aggregation[] $aggregations + * @param array $languageFilter * * @return \eZ\Publish\API\Repository\Values\Content\Search\SearchResult */ - abstract protected function extractSearchResult($data, array $facetBuilders = []); + abstract protected function extractSearchResult( + $data, + array $facetBuilders = [], + array $aggregations = [], + array $languageFilter = [] + ): SearchResult; /** * @param \eZ\Publish\API\Repository\Values\Content\Query\FacetBuilder[] $facetBuilders * * @return \eZ\Publish\API\Repository\Values\Content\Query\FacetBuilder[] */ - private function filterNewFacetBuilders(array $facetBuilders) + private function filterNewFacetBuilders(array $facetBuilders): array { return array_filter( $facetBuilders, - function ($facetBuilder) { + static function ($facetBuilder) { return $facetBuilder instanceof RawFacetBuilder; } ); diff --git a/lib/Core/Search/Solr/ResultExtractor/LoadingResultExtractor.php b/lib/Core/Search/Solr/ResultExtractor/LoadingResultExtractor.php index 878bcf20..7176bc50 100644 --- a/lib/Core/Search/Solr/ResultExtractor/LoadingResultExtractor.php +++ b/lib/Core/Search/Solr/ResultExtractor/LoadingResultExtractor.php @@ -1,8 +1,11 @@ contentHandler = $contentHandler; $this->locationHandler = $locationHandler; $this->nativeResultExtractor = $nativeResultExtractor; - parent::__construct($facetBuilderVisitor, $endpointRegistry); + parent::__construct($facetBuilderVisitor, $aggregationResultExtractor, $endpointRegistry); } - protected function extractSearchResult($data, array $facetBuilders = []) - { - $searchResult = $this->nativeResultExtractor->extract($data, $facetBuilders); + protected function extractSearchResult( + $data, + array $facetBuilders = [], + array $aggregations = [], + array $languageFilter = [] + ): APISearchResult { + $searchResult = $this->nativeResultExtractor->extract( + $data, + $facetBuilders, + $aggregations, + $languageFilter + ); $searchResult = new SearchResult(get_object_vars($searchResult)); $this->replaceExtractedValuesByLoadedValues($searchResult); @@ -69,7 +72,7 @@ protected function extractSearchResult($data, array $facetBuilders = []) * * @return \eZ\Publish\API\Repository\Values\Content\Search\SearchResult */ - private function replaceExtractedValuesByLoadedValues(SearchResult $searchResult) + private function replaceExtractedValuesByLoadedValues(SearchResult $searchResult): APISearchResult { $valueObjectMapById = $this->loadValueObjectMapById($searchResult); @@ -92,7 +95,7 @@ private function replaceExtractedValuesByLoadedValues(SearchResult $searchResult * * @return array|\eZ\Publish\SPI\Persistence\Content\ContentInfo[] */ - private function loadValueObjectMapById(SearchResult $searchResult) + private function loadValueObjectMapById(SearchResult $searchResult): array { if (!isset($searchResult->searchHits[0])) { return []; @@ -107,7 +110,7 @@ private function loadValueObjectMapById(SearchResult $searchResult) return $this->loadLocationMapByIdList($idList); } - private function extractIdList(SearchResult $searchResult) + private function extractIdList(SearchResult $searchResult): array { $idList = []; @@ -131,7 +134,7 @@ private function getValueObjectId($valueObject) throw new RuntimeException("Couldn't handle given value object."); } - private function loadContentInfoMapByIdList(array $contentIdList) + private function loadContentInfoMapByIdList(array $contentIdList): array { if (method_exists($this->contentHandler, 'loadContentInfoList')) { return $this->contentHandler->loadContentInfoList($contentIdList); @@ -155,7 +158,7 @@ private function loadContentInfoMapByIdList(array $contentIdList) * * @return array|\eZ\Publish\SPI\Persistence\Content\ContentInfo[] */ - private function loadLocationMapByIdList(array $locationIdList) + private function loadLocationMapByIdList(array $locationIdList): array { if (method_exists($this->locationHandler, 'loadList')) { return $this->locationHandler->loadList($locationIdList); @@ -179,7 +182,7 @@ private function loadLocationMapByIdList(array $locationIdList) * * @return bool */ - private function isSpellCheckAvailable($data) + private function isSpellCheckAvailable($data): bool { return property_exists($data, 'spellcheck') && property_exists($data->spellcheck, 'suggestions'); } @@ -191,7 +194,7 @@ private function isSpellCheckAvailable($data) * * @return \Netgen\EzPlatformSearchExtra\API\Values\Content\Search\Suggestion */ - private function getSpellCheckSuggestion($data) + private function getSpellCheckSuggestion($data): Suggestion { $receivedSuggestions = (array) $data->spellcheck->suggestions; $wordSuggestions = []; diff --git a/lib/Core/Search/Solr/ResultExtractor/NativeResultExtractor.php b/lib/Core/Search/Solr/ResultExtractor/NativeResultExtractor.php index 6de01f83..ee8688af 100644 --- a/lib/Core/Search/Solr/ResultExtractor/NativeResultExtractor.php +++ b/lib/Core/Search/Solr/ResultExtractor/NativeResultExtractor.php @@ -1,10 +1,15 @@ nativeResultExtractor = $nativeResultExtractor; - parent::__construct($facetBuilderVisitor, $endpointRegistry); + parent::__construct($facetBuilderVisitor, $aggregationResultExtractor, $endpointRegistry); } - protected function extractSearchResult($data, array $facetBuilders = []) - { - return $this->nativeResultExtractor->extract($data, $facetBuilders); + protected function extractSearchResult( + $data, + array $facetBuilders = [], + array $aggregations = [], + array $languageFilter = [] + ): SearchResult { + return $this->nativeResultExtractor->extract( + $data, + $facetBuilders, + $aggregations, + $languageFilter + ); } - public function extractHit($hit) + public function extractHit($hit): ValueObject { return $this->nativeResultExtractor->extractHit($hit); } diff --git a/lib/Resources/config/search/solr.yml b/lib/Resources/config/search/solr.yml index 000fdd1c..7bc3e5e6 100644 --- a/lib/Resources/config/search/solr.yml +++ b/lib/Resources/config/search/solr.yml @@ -17,14 +17,26 @@ services: - '@netgen.search.solr.subdocument_mapper.content.aggregate' - '@netgen.search.solr.subdocument_mapper.content_translation.aggregate' - netgen.search.solr.result_extractor: + netgen.search.solr.result_extractor.content: class: Netgen\EzPlatformSearchExtra\Core\Search\Solr\ResultExtractor\LoadingResultExtractor - decorates: ezpublish.search.solr.result_extractor.native + decorates: ezpublish.search.solr.result_extractor.content.native arguments: - '@ezpublish.spi.persistence.content_handler' - '@ezpublish.spi.persistence.location_handler' - - '@netgen.search.solr.result_extractor.inner' + - '@netgen.search.solr.result_extractor.content.inner' - '@ezpublish.search.solr.query.content.facet_builder_visitor.aggregate' + - "@ezpublish.search.solr.query.content.aggregation_result_extractor.dispatcher" + - '@ezpublish.search.solr.gateway.endpoint_registry' + + netgen.search.solr.result_extractor.location: + class: Netgen\EzPlatformSearchExtra\Core\Search\Solr\ResultExtractor\LoadingResultExtractor + decorates: ezpublish.search.solr.result_extractor.location.native + arguments: + - '@ezpublish.spi.persistence.content_handler' + - '@ezpublish.spi.persistence.location_handler' + - '@netgen.search.solr.result_extractor.location.inner' + - '@ezpublish.search.solr.query.location.facet_builder_visitor.aggregate' + - "@ezpublish.search.solr.query.location.aggregation_result_extractor.dispatcher" - '@ezpublish.search.solr.gateway.endpoint_registry' netgen.search.solr.query.content.query_converter: @@ -34,6 +46,7 @@ services: - '@ezpublish.search.solr.query.content.criterion_visitor.aggregate' - '@ezpublish.search.solr.query.content.sort_clause_visitor.aggregate' - '@ezpublish.search.solr.query.content.facet_builder_visitor.aggregate' + - "@ezpublish.search.solr.query.content.aggregation_visitor.dispatcher" netgen.search.solr.query.location.query_converter: class: Netgen\EzPlatformSearchExtra\Core\Search\Solr\Query\Common\QueryConverter @@ -42,3 +55,4 @@ services: - '@ezpublish.search.solr.query.location.criterion_visitor.aggregate' - '@ezpublish.search.solr.query.location.sort_clause_visitor.aggregate' - '@ezpublish.search.solr.query.location.facet_builder_visitor.aggregate' + - "@ezpublish.search.solr.query.location.aggregation_visitor.dispatcher" diff --git a/tests/lib/Integration/API/FulltextSpellcheckCriterionTest.php b/tests/lib/Integration/API/FulltextSpellcheckCriterionTest.php index 3c565db7..1259ba63 100644 --- a/tests/lib/Integration/API/FulltextSpellcheckCriterionTest.php +++ b/tests/lib/Integration/API/FulltextSpellcheckCriterionTest.php @@ -2,6 +2,7 @@ namespace Netgen\EzPlatformSearchExtra\Tests\Integration\API; +use eZ\Publish\API\Repository\SearchService; use eZ\Publish\API\Repository\Tests\BaseTest; use eZ\Publish\API\Repository\Values\Content\LocationQuery; use eZ\Publish\API\Repository\Values\Content\Query; @@ -11,7 +12,7 @@ class FulltextSpellcheckCriterionTest extends BaseTest { - public function providerForTestFind() + public function providerForTestFind(): array { return [ [ @@ -105,7 +106,7 @@ public function providerForTestFind() * @throws \eZ\Publish\API\Repository\Exceptions\NotFoundException * @throws \eZ\Publish\API\Repository\Exceptions\UnauthorizedException */ - public function testPrepareTestFixtures() + public function testPrepareTestFixtures(): void { $repository = $this->getRepository(); $contentService = $repository->getContentService(); @@ -147,7 +148,7 @@ public function testPrepareTestFixtures() $this->refreshSearch($repository); - $this->assertTrue(true); + self::assertTrue(true); } /** @@ -158,7 +159,7 @@ public function testPrepareTestFixtures() * * @throws \eZ\Publish\API\Repository\Exceptions\InvalidArgumentException */ - public function testFindContent(Query $query, array $expectedWordSuggestions) + public function testFindContent(Query $query, array $expectedWordSuggestions): void { $searchService = $this->getSearchService(false); @@ -178,7 +179,7 @@ public function testFindContent(Query $query, array $expectedWordSuggestions) * * @throws \eZ\Publish\API\Repository\Exceptions\InvalidArgumentException */ - public function testFindLocations(LocationQuery $query, array $expectedWordSuggestions) + public function testFindLocations(LocationQuery $query, array $expectedWordSuggestions): void { $searchService = $this->getSearchService(false); @@ -190,7 +191,7 @@ public function testFindLocations(LocationQuery $query, array $expectedWordSugge $this->assertEquals($expectedWordSuggestions, $searchResult->suggestion->getSuggestions()); } - protected function getSearchService($initialInitializeFromScratch = true) + protected function getSearchService($initialInitializeFromScratch = true): SearchService { return $this->getRepository($initialInitializeFromScratch)->getSearchService(); } diff --git a/tests/lib/Unit/Core/Pagination/Pagerfanta/SearchAdapterTest.php b/tests/lib/Unit/Core/Pagination/Pagerfanta/SearchAdapterTest.php index f74e5ca6..7c521a82 100644 --- a/tests/lib/Unit/Core/Pagination/Pagerfanta/SearchAdapterTest.php +++ b/tests/lib/Unit/Core/Pagination/Pagerfanta/SearchAdapterTest.php @@ -1,10 +1,13 @@ searchService = $this->getMockBuilder(SearchService::class)->getMock(); } - public function testGetNbResults() + public function testGetNbResults(): void { $nbResults = 123; $query = new Query(['limit' => 10]); @@ -37,18 +40,18 @@ public function testGetNbResults() $searchResult = new SearchResult(['totalCount' => $nbResults]); $this->searchService - ->expects($this->once()) + ->expects(self::once()) ->method('findContent') - ->with($this->equalTo($countQuery)) + ->with(self::equalTo($countQuery)) ->willReturn($searchResult); $adapter = $this->getAdapter($query); - $this->assertSame($nbResults, $adapter->getNbResults()); - $this->assertSame($nbResults, $adapter->getNbResults()); + self::assertSame($nbResults, $adapter->getNbResults()); + self::assertSame($nbResults, $adapter->getNbResults()); } - public function testGetFacets() + public function testGetFacets(): void { $facets = ['facet', 'facet']; $query = new Query(['limit' => 10]); @@ -57,56 +60,76 @@ public function testGetFacets() $searchResult = new SearchResult(['facets' => $facets]); $this->searchService - ->expects($this->once()) + ->expects(self::once()) + ->method('findContent') + ->with(self::equalTo($countQuery)) + ->willReturn($searchResult); + + $adapter = $this->getAdapter($query); + + self::assertSame($facets, $adapter->getFacets()); + self::assertSame($facets, $adapter->getFacets()); + } + + public function testGetAggregations(): void + { + $aggregations = new AggregationResultCollection(); + $query = new Query(['limit' => 10]); + $countQuery = clone $query; + $countQuery->limit = 0; + $searchResult = new SearchResult(['aggregations' => $aggregations]); + + $this->searchService + ->expects(self::once()) ->method('findContent') - ->with($this->equalTo($countQuery)) + ->with(self::equalTo($countQuery)) ->willReturn($searchResult); $adapter = $this->getAdapter($query); - $this->assertSame($facets, $adapter->getFacets()); - $this->assertSame($facets, $adapter->getFacets()); + self::assertSame($aggregations, $adapter->getAggregations()); + self::assertSame($aggregations, $adapter->getAggregations()); } - public function testMaxScore() + public function testMaxScore(): void { - $maxScore = 100; + $maxScore = 100.0; $query = new Query(['limit' => 10]); $countQuery = clone $query; $countQuery->limit = 0; $searchResult = new SearchResult(['maxScore' => $maxScore]); $this->searchService - ->expects($this->once()) + ->expects(self::once()) ->method('findContent') - ->with($this->equalTo($countQuery)) + ->with(self::equalTo($countQuery)) ->willReturn($searchResult); $adapter = $this->getAdapter($query); - $this->assertSame($maxScore, $adapter->getMaxScore()); - $this->assertSame($maxScore, $adapter->getMaxScore()); + self::assertSame($maxScore, $adapter->getMaxScore()); + self::assertSame($maxScore, $adapter->getMaxScore()); } - public function testTimeIsNotSet() + public function testTimeIsNotSet(): void { $this->searchService - ->expects($this->never()) + ->expects(self::never()) ->method('findContent'); $adapter = $this->getAdapter(new Query()); - $this->assertNull($adapter->getTime()); - $this->assertNull($adapter->getTime()); + self::assertNull($adapter->getTime()); + self::assertNull($adapter->getTime()); } - public function testGetSlice() + public function testGetSlice(): void { $offset = 20; $limit = 25; $nbResults = 123; $facets = ['facet', 'facet']; - $maxScore = 100; + $maxScore = 100.0; $time = 256; $query = new Query(['offset' => 5, 'limit' => 10]); $searchQuery = clone $query; @@ -124,37 +147,37 @@ public function testGetSlice() ]); $this->searchService - ->expects($this->once()) + ->expects(self::once()) ->method('findContent') - ->with($this->equalTo($searchQuery)) + ->with(self::equalTo($searchQuery)) ->willReturn($searchResult); $adapter = $this->getAdapter($query); $slice = $adapter->getSlice($offset, $limit); - $this->assertInstanceOf(Slice::class, $slice); - $this->assertSame($hits, $slice->getSearchHits()); - $this->assertSame($nbResults, $adapter->getNbResults()); - $this->assertSame($facets, $adapter->getFacets()); - $this->assertSame($maxScore, $adapter->getMaxScore()); - $this->assertSame($time, $adapter->getTime()); + self::assertInstanceOf(Slice::class, $slice); + self::assertSame($hits, $slice->getSearchHits()); + self::assertSame($nbResults, $adapter->getNbResults()); + self::assertSame($facets, $adapter->getFacets()); + self::assertSame($maxScore, $adapter->getMaxScore()); + self::assertSame($time, $adapter->getTime()); } - public function testLocationQuery() + public function testLocationQuery(): void { $query = new LocationQuery(['performCount' => false]); $this->searchService - ->expects($this->once()) + ->expects(self::once()) ->method('findLocations') - ->with($this->equalTo($query)) + ->with(self::equalTo($query)) ->willReturn(new SearchResult()); $adapter = $this->getAdapter($query); $adapter->getSlice(0, 25); } - protected function getAdapter(Query $query) + protected function getAdapter(Query $query): SearchAdapter { return new SearchAdapter($query, $this->searchService); } diff --git a/tests/lib/Unit/Core/Pagination/Pagerfanta/SearchHandlerAdapterTest.php b/tests/lib/Unit/Core/Pagination/Pagerfanta/SearchHandlerAdapterTest.php index 423a99a1..8e095fa4 100644 --- a/tests/lib/Unit/Core/Pagination/Pagerfanta/SearchHandlerAdapterTest.php +++ b/tests/lib/Unit/Core/Pagination/Pagerfanta/SearchHandlerAdapterTest.php @@ -4,6 +4,7 @@ use eZ\Publish\API\Repository\Values\Content\LocationQuery; use eZ\Publish\API\Repository\Values\Content\Query; +use eZ\Publish\API\Repository\Values\Content\Search\AggregationResultCollection; use eZ\Publish\API\Repository\Values\Content\Search\SearchHit; use eZ\Publish\API\Repository\Values\Content\Search\SearchResult; use eZ\Publish\SPI\Search\Handler; @@ -17,7 +18,7 @@ class SearchHandlerAdapterTest extends TestCase { /** - * @var \eZ\Publish\SPI\Search\Handler|\PHPUnit_Framework_MockObject_MockObject + * @var \eZ\Publish\SPI\Search\Handler|\PHPUnit\Framework\MockObject\MockObject */ protected $searchHandler; @@ -28,7 +29,7 @@ protected function setUp(): void $this->searchHandler = $this->getMockBuilder(Handler::class)->getMock(); } - public function testGetNbResults() + public function testGetNbResults(): void { $nbResults = 123; $query = new Query(['limit' => 10]); @@ -37,18 +38,18 @@ public function testGetNbResults() $searchResult = new SearchResult(['totalCount' => $nbResults]); $this->searchHandler - ->expects($this->once()) + ->expects(self::once()) ->method('findContent') - ->with($this->equalTo($countQuery)) + ->with(self::equalTo($countQuery)) ->willReturn($searchResult); $adapter = $this->getAdapter($query); - $this->assertSame($nbResults, $adapter->getNbResults()); - $this->assertSame($nbResults, $adapter->getNbResults()); + self::assertSame($nbResults, $adapter->getNbResults()); + self::assertSame($nbResults, $adapter->getNbResults()); } - public function testGetFacets() + public function testGetFacets(): void { $facets = ['facet', 'facet']; $query = new Query(['limit' => 10]); @@ -57,56 +58,76 @@ public function testGetFacets() $searchResult = new SearchResult(['facets' => $facets]); $this->searchHandler - ->expects($this->once()) + ->expects(self::once()) ->method('findContent') - ->with($this->equalTo($countQuery)) + ->with(self::equalTo($countQuery)) ->willReturn($searchResult); $adapter = $this->getAdapter($query); - $this->assertSame($facets, $adapter->getFacets()); - $this->assertSame($facets, $adapter->getFacets()); + self::assertSame($facets, $adapter->getFacets()); + self::assertSame($facets, $adapter->getFacets()); } - public function testMaxScore() + public function testGetAggregations(): void { - $maxScore = 100; + $aggregations = new AggregationResultCollection(); + $query = new Query(['limit' => 10]); + $countQuery = clone $query; + $countQuery->limit = 0; + $searchResult = new SearchResult(['aggregations' => $aggregations]); + + $this->searchHandler + ->expects(self::once()) + ->method('findContent') + ->with(self::equalTo($countQuery)) + ->willReturn($searchResult); + + $adapter = $this->getAdapter($query); + + self::assertSame($aggregations, $adapter->getAggregations()); + self::assertSame($aggregations, $adapter->getAggregations()); + } + + public function testMaxScore(): void + { + $maxScore = 100.0; $query = new Query(['limit' => 10]); $countQuery = clone $query; $countQuery->limit = 0; $searchResult = new SearchResult(['maxScore' => $maxScore]); $this->searchHandler - ->expects($this->once()) + ->expects(self::once()) ->method('findContent') - ->with($this->equalTo($countQuery)) + ->with(self::equalTo($countQuery)) ->willReturn($searchResult); $adapter = $this->getAdapter($query); - $this->assertSame($maxScore, $adapter->getMaxScore()); - $this->assertSame($maxScore, $adapter->getMaxScore()); + self::assertSame($maxScore, $adapter->getMaxScore()); + self::assertSame($maxScore, $adapter->getMaxScore()); } - public function testTimeIsNotSet() + public function testTimeIsNotSet(): void { $this->searchHandler - ->expects($this->never()) + ->expects(self::never()) ->method('findContent'); $adapter = $this->getAdapter(new Query()); - $this->assertNull($adapter->getTime()); - $this->assertNull($adapter->getTime()); + self::assertNull($adapter->getTime()); + self::assertNull($adapter->getTime()); } - public function testGetSlice() + public function testGetSlice(): void { $offset = 20; $limit = 25; $nbResults = 123; $facets = ['facet', 'facet']; - $maxScore = 100; + $maxScore = 100.0; $time = 256; $query = new Query(['offset' => 5, 'limit' => 10]); $searchQuery = clone $query; @@ -124,37 +145,37 @@ public function testGetSlice() ]); $this->searchHandler - ->expects($this->once()) + ->expects(self::once()) ->method('findContent') - ->with($this->equalTo($searchQuery)) + ->with(self::equalTo($searchQuery)) ->willReturn($searchResult); $adapter = $this->getAdapter($query); $slice = $adapter->getSlice($offset, $limit); - $this->assertInstanceOf(Slice::class, $slice); - $this->assertSame($hits, $slice->getSearchHits()); - $this->assertSame($nbResults, $adapter->getNbResults()); - $this->assertSame($facets, $adapter->getFacets()); - $this->assertSame($maxScore, $adapter->getMaxScore()); - $this->assertSame($time, $adapter->getTime()); + self::assertInstanceOf(Slice::class, $slice); + self::assertSame($hits, $slice->getSearchHits()); + self::assertSame($nbResults, $adapter->getNbResults()); + self::assertSame($facets, $adapter->getFacets()); + self::assertSame($maxScore, $adapter->getMaxScore()); + self::assertSame($time, $adapter->getTime()); } - public function testLocationQuery() + public function testLocationQuery(): void { $query = new LocationQuery(['performCount' => false]); $this->searchHandler - ->expects($this->once()) + ->expects(self::once()) ->method('findLocations') - ->with($this->equalTo($query)) + ->with(self::equalTo($query)) ->willReturn(new SearchResult()); $adapter = $this->getAdapter($query); $adapter->getSlice(0, 25); } - protected function getAdapter(Query $query) + protected function getAdapter(Query $query): SearchHandlerAdapter { return new SearchHandlerAdapter($query, $this->searchHandler); } diff --git a/tests/lib/Unit/Core/Pagination/Pagerfanta/SliceTest.php b/tests/lib/Unit/Core/Pagination/Pagerfanta/SliceTest.php index 47e22cee..2809c0b2 100644 --- a/tests/lib/Unit/Core/Pagination/Pagerfanta/SliceTest.php +++ b/tests/lib/Unit/Core/Pagination/Pagerfanta/SliceTest.php @@ -1,5 +1,7 @@ getSlice(); - $this->assertCount(2, $slice); + self::assertCount(2, $slice); foreach ($slice as $searchHit) { - $this->assertIsString($searchHit); + self::assertIsString($searchHit); } } - public function testIteratorArrayAccess() + public function testIteratorArrayAccess(): void { $slice = $this->getSlice(); $iterator = $slice->getIterator(); - $this->assertEquals('one', $iterator[0]); - $this->assertEquals('two', $iterator[1]); + self::assertEquals('one', $iterator[0]); + self::assertEquals('two', $iterator[1]); } - public function testArrayAccessGet() + public function testArrayAccessGet(): void { $slice = $this->getSlice(); - $this->assertEquals('one', $slice[0]); - $this->assertEquals('two', $slice[1]); + self::assertEquals('one', $slice[0]); + self::assertEquals('two', $slice[1]); } - public function testArrayAccessExists() + public function testArrayAccessExists(): void { $slice = $this->getSlice(); - $this->assertTrue(isset($slice[0])); - $this->assertTrue(isset($slice[1])); - $this->assertFalse(isset($slice[2])); + self::assertTrue(isset($slice[0])); + self::assertTrue(isset($slice[1])); + self::assertFalse(isset($slice[2])); } - public function testArrayAccessSet() + public function testArrayAccessSet(): void { $this->expectException(RuntimeException::class); @@ -58,7 +60,7 @@ public function testArrayAccessSet() $slice[0] = 1; } - public function testArrayAccessUnset() + public function testArrayAccessUnset(): void { $this->expectException(RuntimeException::class); @@ -67,17 +69,17 @@ public function testArrayAccessUnset() unset($slice[0]); } - public function testGetSearchHits() + public function testGetSearchHits(): void { $slice = $this->getSlice(); - $this->assertEquals( + self::assertEquals( $this->getSearchHits(), $slice->getSearchHits() ); } - protected function getSearchHits() + protected function getSearchHits(): array { return [ new SearchHit(['valueObject' => 'one']), @@ -85,7 +87,7 @@ protected function getSearchHits() ]; } - protected function getSlice() + protected function getSlice(): Slice { return new Slice($this->getSearchHits()); }