Skip to content

Commit e3de453

Browse files
author
Bertrand Dunogier
authored
Support for getting the results for a location (#38)
1 parent 2ebe523 commit e3de453

9 files changed

+300
-87
lines changed

spec/API/QueryFieldServiceSpec.php

+54-16
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
class QueryFieldServiceSpec extends ObjectBehavior
2424
{
2525
const CONTENT_TYPE_ID = 1;
26+
const CONTENT_TYPE_ID_WITHOUT_PAGINATION = 2;
2627
const LOCATION_ID = 1;
2728
const QUERY_TYPE_IDENTIFIER = 'query_type_identifier';
2829
const FIELD_DEFINITION_IDENTIFIER = 'test';
@@ -46,24 +47,16 @@ function let(
4647
'param2' => 'value2',
4748
];
4849

49-
$contentType = new Values\ContentType\ContentType([
50-
'fieldDefinitions' => new Values\ContentType\FieldDefinitionCollection([
51-
new Values\ContentType\FieldDefinition([
52-
'identifier' => self::FIELD_DEFINITION_IDENTIFIER,
53-
'fieldTypeIdentifier' => 'ezcontentquery',
54-
'fieldSettings' => [
55-
'ReturnedType' => 'folder',
56-
'QueryType' => self::QUERY_TYPE_IDENTIFIER,
57-
'Parameters' => $parameters,
58-
],
59-
]),
60-
]),
61-
]);
6250
$location = new Values\Content\Location([
6351
'id' => self::LOCATION_ID,
6452
]);
6553

66-
$contentTypeService->loadContentType(self::CONTENT_TYPE_ID)->willReturn($contentType);
54+
$contentTypeWithPagination = $this->getContentType($parameters);
55+
$contentTypeService->loadContentType(self::CONTENT_TYPE_ID)->willReturn($contentTypeWithPagination);
56+
57+
$contentTypeWithoutPagination = $this->getContentType($parameters, false, 10);
58+
$contentTypeService->loadContentType(self::CONTENT_TYPE_ID_WITHOUT_PAGINATION)->willReturn($contentTypeWithoutPagination);
59+
6760
$locationService->loadLocation(self::LOCATION_ID)->willReturn($location);
6861
$queryTypeRegistry->getQueryType(self::QUERY_TYPE_IDENTIFIER)->willReturn($queryType);
6962
$queryType->getQuery(Argument::any())->willReturn(new ApiQuery());
@@ -113,18 +106,63 @@ function it_returns_zero_if_offset_is_bigger_than_count(QueryType $queryType, Se
113106
$this->countContentItems($this->getContent(), self::FIELD_DEFINITION_IDENTIFIER)->shouldBe(0);
114107
}
115108

109+
function it_returns_0_as_pagination_configuration_if_pagination_is_disabled()
110+
{
111+
$this->getPaginationConfiguration(
112+
$this->getContent(self::CONTENT_TYPE_ID_WITHOUT_PAGINATION),
113+
self::FIELD_DEFINITION_IDENTIFIER
114+
)->shouldBe(0);
115+
}
116+
117+
function it_returns_the_items_per_page_number_as_pagination_configuration_if_pagination_is_enabled()
118+
{
119+
$this->getPaginationConfiguration(
120+
$this->getContent(),
121+
self::FIELD_DEFINITION_IDENTIFIER
122+
)->shouldBe(10);
123+
}
124+
116125
/**
117126
* @return \eZ\Publish\Core\Repository\Values\Content\Content
118127
*/
119-
private function getContent(): Values\Content\Content
128+
private function getContent(int $contentTypeId = self::CONTENT_TYPE_ID): Values\Content\Content
120129
{
121130
return new Values\Content\Content([
122131
'versionInfo' => new Values\Content\VersionInfo([
123132
'contentInfo' => new ContentInfo([
124-
'contentTypeId' => self::CONTENT_TYPE_ID,
133+
'contentTypeId' => $contentTypeId,
125134
'mainLocationId' => self::LOCATION_ID,
135+
'mainLocation' => new Values\Content\Location([
136+
'id' => self::LOCATION_ID,
137+
]),
138+
]),
139+
]),
140+
]);
141+
}
142+
143+
/**
144+
* @param array $parameters
145+
*
146+
* @return \eZ\Publish\API\Repository\Values\ContentType\ContentType
147+
*/
148+
private function getContentType(array $parameters, bool $enablePagination = true, $itemsPerPage = 10): \eZ\Publish\API\Repository\Values\ContentType\ContentType
149+
{
150+
$contentType = new Values\ContentType\ContentType([
151+
'fieldDefinitions' => new Values\ContentType\FieldDefinitionCollection([
152+
new Values\ContentType\FieldDefinition([
153+
'identifier' => self::FIELD_DEFINITION_IDENTIFIER,
154+
'fieldTypeIdentifier' => 'ezcontentquery',
155+
'fieldSettings' => [
156+
'ReturnedType' => 'folder',
157+
'QueryType' => self::QUERY_TYPE_IDENTIFIER,
158+
'EnablePagination' => $enablePagination,
159+
'ItemsPerPage' => $itemsPerPage,
160+
'Parameters' => $parameters,
161+
],
126162
]),
127163
]),
128164
]);
165+
166+
return $contentType;
129167
}
130168
}

src/API/QueryFieldLocationService.php

+34
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
<?php
2+
3+
/**
4+
* @copyright Copyright (C) eZ Systems AS. All rights reserved.
5+
* @license For full copyright and license information view LICENSE file distributed with this source code.
6+
*/
7+
namespace EzSystems\EzPlatformQueryFieldType\API;
8+
9+
use eZ\Publish\API\Repository\Values\Content\Location;
10+
11+
/**
12+
* Executes queries for a query field for a given a location.
13+
*/
14+
interface QueryFieldLocationService
15+
{
16+
/**
17+
* Returns the query results for the given location.
18+
*
19+
* @return iterable An iterable that yields Content items.
20+
*/
21+
public function loadContentItemsForLocation(Location $location, string $fieldDefinitionIdentifier): iterable;
22+
23+
/**
24+
* Returns a slice of the query results for the given location.
25+
*
26+
* @return iterable An iterable that yields Content items.
27+
*/
28+
public function loadContentItemsSliceForLocation(Location $location, string $fieldDefinitionIdentifier, int $offset, int $limit): iterable;
29+
30+
/**
31+
* Counts the results for the given location.
32+
*/
33+
public function countContentItemsForLocation(Location $location, string $fieldDefinitionIdentifier): int;
34+
}

src/API/QueryFieldService.php

+53-51
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
use eZ\Publish\API\Repository\LocationService;
1111
use eZ\Publish\API\Repository\SearchService;
1212
use eZ\Publish\API\Repository\Values\Content\Content;
13+
use eZ\Publish\API\Repository\Values\Content\Location;
1314
use eZ\Publish\API\Repository\Values\Content\Query;
1415
use eZ\Publish\API\Repository\Values\Content\Search\SearchHit;
1516
use eZ\Publish\API\Repository\Values\ContentType\FieldDefinition;
@@ -21,7 +22,7 @@
2122
/**
2223
* Executes a query and returns the results.
2324
*/
24-
final class QueryFieldService implements QueryFieldServiceInterface
25+
final class QueryFieldService implements QueryFieldServiceInterface, QueryFieldLocationService
2526
{
2627
/** @var \eZ\Publish\Core\QueryType\QueryTypeRegistry */
2728
private $queryTypeRegistry;
@@ -48,29 +49,33 @@ public function __construct(
4849
$this->queryTypeRegistry = $queryTypeRegistry;
4950
}
5051

51-
/**
52-
* @param \eZ\Publish\API\Repository\Values\Content\Content $content
53-
* @param string $fieldDefinitionIdentifier
54-
*
55-
* @return \eZ\Publish\API\Repository\Values\Content\Content[]
56-
*
57-
* @throws \eZ\Publish\API\Repository\Exceptions\InvalidArgumentException
58-
*/
5952
public function loadContentItems(Content $content, string $fieldDefinitionIdentifier): iterable
6053
{
61-
$query = $this->prepareQuery($content, $fieldDefinitionIdentifier);
54+
$query = $this->prepareQuery($content, $content->contentInfo->getMainLocation(), $fieldDefinitionIdentifier);
6255

63-
return array_map(
64-
function (SearchHit $searchHit) {
65-
return $searchHit->valueObject;
66-
},
67-
$this->searchService->findContent($query)->searchHits
68-
);
56+
return $this->executeQueryAndMapResult($query);
57+
}
58+
59+
public function loadContentItemsForLocation(Location $location, string $fieldDefinitionIdentifier): iterable
60+
{
61+
$query = $this->prepareQuery($location->getContent(), $location, $fieldDefinitionIdentifier);
62+
63+
return $this->executeQueryAndMapResult($query);
6964
}
7065

7166
public function countContentItems(Content $content, string $fieldDefinitionIdentifier): int
7267
{
73-
$query = $this->prepareQuery($content, $fieldDefinitionIdentifier);
68+
$query = $this->prepareQuery($content, $content->contentInfo->getMainLocation(), $fieldDefinitionIdentifier);
69+
$query->limit = 0;
70+
71+
$count = $this->searchService->findContent($query)->totalCount - $query->offset;
72+
73+
return $count < 0 ? 0 : $count;
74+
}
75+
76+
public function countContentItemsForLocation(Location $location, string $fieldDefinitionIdentifier): int
77+
{
78+
$query = $this->prepareQuery($location->getContent(), $location, $fieldDefinitionIdentifier);
7479
$query->limit = 0;
7580

7681
$count = $this->searchService->findContent($query)->totalCount - $query->offset;
@@ -80,34 +85,35 @@ public function countContentItems(Content $content, string $fieldDefinitionIdent
8085

8186
public function loadContentItemsSlice(Content $content, string $fieldDefinitionIdentifier, int $offset, int $limit): iterable
8287
{
83-
$query = $this->prepareQuery($content, $fieldDefinitionIdentifier);
84-
$query->offset += $offset;
88+
$query = $this->prepareQuery($content, $content->contentInfo->getMainLocation(), $fieldDefinitionIdentifier);
89+
$query->offset = $offset;
8590
$query->limit = $limit;
8691

87-
return array_map(
88-
function (SearchHit $searchHit) {
89-
return $searchHit->valueObject;
90-
},
91-
$this->searchService->findContent($query)->searchHits
92-
);
92+
return $this->executeQueryAndMapResult($query);
93+
}
94+
95+
public function loadContentItemsSliceForLocation(Location $location, string $fieldDefinitionIdentifier, int $offset, int $limit): iterable
96+
{
97+
$query = $this->prepareQuery($location->getContent(), $location, $fieldDefinitionIdentifier);
98+
$query->offset = $offset;
99+
$query->limit = $limit;
100+
101+
return $this->executeQueryAndMapResult($query);
93102
}
94103

95104
public function getPaginationConfiguration(Content $content, string $fieldDefinitionIdentifier): int
96105
{
97106
$fieldDefinition = $this->loadFieldDefinition($content, $fieldDefinitionIdentifier);
98107

99108
if ($fieldDefinition->fieldSettings['EnablePagination'] === false) {
100-
return false;
109+
return 0;
101110
}
102111

103112
return $fieldDefinition->fieldSettings['ItemsPerPage'];
104113
}
105114

106115
/**
107116
* @param array $expressions parameters that may include expressions to be resolved
108-
* @param array $variables
109-
*
110-
* @return array
111117
*/
112118
private function resolveParameters(array $expressions, array $variables): array
113119
{
@@ -130,11 +136,6 @@ private function isExpression($expression): bool
130136
}
131137

132138
/**
133-
* @param string $expression
134-
* @param array $variables
135-
*
136-
* @return mixed
137-
*
138139
* @throws \eZ\Publish\Core\Base\Exceptions\InvalidArgumentException if $expression is not an expression.
139140
*/
140141
private function resolveExpression(string $expression, array $variables)
@@ -146,20 +147,10 @@ private function resolveExpression(string $expression, array $variables)
146147
return (new ExpressionLanguage())->evaluate(substr($expression, 2), $variables);
147148
}
148149

149-
/**
150-
* @param \eZ\Publish\API\Repository\Values\Content\Content $content
151-
* @param string $fieldDefinitionIdentifier
152-
*
153-
* @return \eZ\Publish\API\Repository\Values\Content\Query
154-
*
155-
* @throws \eZ\Publish\Core\Base\Exceptions\InvalidArgumentException
156-
* @throws \eZ\Publish\API\Repository\Exceptions\NotFoundException
157-
*/
158-
private function prepareQuery(Content $content, string $fieldDefinitionIdentifier, array $extraParameters = []): Query
150+
private function prepareQuery(Content $content, Location $location, string $fieldDefinitionIdentifier, array $extraParameters = []): Query
159151
{
160152
$fieldDefinition = $this->loadFieldDefinition($content, $fieldDefinitionIdentifier);
161153

162-
$location = $this->locationService->loadLocation($content->contentInfo->mainLocationId);
163154
$queryType = $this->queryTypeRegistry->getQueryType($fieldDefinition->fieldSettings['QueryType']);
164155
$parameters = $this->resolveParameters(
165156
$fieldDefinition->fieldSettings['Parameters'],
@@ -168,7 +159,8 @@ private function prepareQuery(Content $content, string $fieldDefinitionIdentifie
168159
[
169160
'content' => $content,
170161
'contentInfo' => $content->contentInfo,
171-
'mainLocation' => $location,
162+
'location' => $location,
163+
'mainLocation' => $location->id === $content->contentInfo->mainLocationId ? $location : $content->contentInfo->getMainLocation(),
172164
'returnedType' => $fieldDefinition->fieldSettings['ReturnedType'],
173165
]
174166
)
@@ -178,11 +170,6 @@ private function prepareQuery(Content $content, string $fieldDefinitionIdentifie
178170
}
179171

180172
/**
181-
* @param \eZ\Publish\API\Repository\Values\Content\Content $content
182-
* @param string $fieldDefinitionIdentifier
183-
*
184-
* @return \eZ\Publish\API\Repository\Values\ContentType\FieldDefinition|null
185-
*
186173
* @throws \eZ\Publish\API\Repository\Exceptions\NotFoundException
187174
*/
188175
private function loadFieldDefinition(Content $content, string $fieldDefinitionIdentifier): FieldDefinition
@@ -199,4 +186,19 @@ private function loadFieldDefinition(Content $content, string $fieldDefinitionId
199186

200187
return $fieldDefinition;
201188
}
189+
190+
/**
191+
* @return \eZ\Publish\API\Repository\Values\Content\Content[]
192+
*
193+
* @throws \eZ\Publish\API\Repository\Exceptions\InvalidArgumentException
194+
*/
195+
private function executeQueryAndMapResult(Query $query): array
196+
{
197+
return array_map(
198+
static function (SearchHit $searchHit): Content {
199+
return $searchHit->valueObject;
200+
},
201+
$this->searchService->findContent($query)->searchHits
202+
);
203+
}
202204
}

src/API/QueryFieldServiceInterface.php

+27-3
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,14 @@
99
use eZ\Publish\API\Repository\Values\Content\Content;
1010

1111
/**
12-
* Executes a query and returns the results.
12+
* Executes queries for a query field.
1313
*/
1414
interface QueryFieldServiceInterface
1515
{
1616
/**
17-
* @param \eZ\Publish\API\Repository\Values\Content\Content $content
17+
* Executes the query without pagination and returns the content items.
18+
*
19+
* @param \eZ\Publish\API\Repository\Values\Content\Location $content
1820
* @param string $fieldDefinitionIdentifier
1921
*
2022
* @return \eZ\Publish\API\Repository\Values\Content\Content[]
@@ -24,16 +26,38 @@ interface QueryFieldServiceInterface
2426
public function loadContentItems(Content $content, string $fieldDefinitionIdentifier): iterable;
2527

2628
/**
29+
* Counts the total results of a query.
30+
*
2731
* @param \eZ\Publish\API\Repository\Values\Content\Content $content
2832
* @param string $fieldDefinitionIdentifier
2933
*
30-
* @return \eZ\Publish\API\Repository\Values\Content\Content[]
34+
* @return int
3135
*
3236
* @throws \eZ\Publish\API\Repository\Exceptions\InvalidArgumentException
3337
*/
3438
public function countContentItems(Content $content, string $fieldDefinitionIdentifier): int;
3539

40+
/**
41+
* Executes a paginated query and return the requested content items slice.
42+
*
43+
* @param \eZ\Publish\API\Repository\Values\Content\Content $content
44+
* @param string $fieldDefinitionIdentifier
45+
* @param int $offset
46+
* @param int $limit
47+
*
48+
* @return \eZ\Publish\API\Repository\Values\Content\Content[]
49+
*
50+
* @throws \eZ\Publish\API\Repository\Exceptions\InvalidArgumentException
51+
*/
3652
public function loadContentItemsSlice(Content $content, string $fieldDefinitionIdentifier, int $offset, int $limit): iterable;
3753

54+
/**
55+
* @param \eZ\Publish\API\Repository\Values\Content\Content $content
56+
* @param string $fieldDefinitionIdentifier
57+
*
58+
* @return int The page size, or 0 if pagination is disabled.
59+
*
60+
* @throws \eZ\Publish\API\Repository\Exceptions\InvalidArgumentException
61+
*/
3862
public function getPaginationConfiguration(Content $content, string $fieldDefinitionIdentifier): int;
3963
}

0 commit comments

Comments
 (0)