Skip to content

Commit 42351ce

Browse files
author
Mateusz Dębiński
committed
IBX-8417: Added the ability to enable pagination for ezobjectrelationlist field
1 parent e3e2a90 commit 42351ce

File tree

5 files changed

+79
-21
lines changed

5 files changed

+79
-21
lines changed

src/bundle/Resources/config/default_settings.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
parameters:
22
ibexa.graphql.schema.should.extend.ezurl: false
3+
ibexa.graphql.schema.ezobjectrelationlist.enable_pagination: false
34
ibexa.graphql.schema.content.field_name.override:
45
id: id_
56
ibexa.graphql.schema.content.mapping.field_definition_type:

src/bundle/Resources/config/graphql/Field.types.yaml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -279,3 +279,13 @@ UrlFieldValue:
279279
type: String
280280
description: "The link's name or description"
281281
resolve: "@=value.text"
282+
283+
RelationsConnection:
284+
type: relay-connection
285+
config:
286+
nodeType: Item
287+
connectionFields:
288+
sliceSize:
289+
type: Int!
290+
orderBy:
291+
type: String

src/bundle/Resources/config/services/schema.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ services:
4343
arguments:
4444
$contentTypeService: '@ibexa.siteaccessaware.service.content_type'
4545
$innerMapper: '@Ibexa\GraphQL\Schema\Domain\Content\Mapper\FieldDefinition\RelationFieldDefinitionMapper.inner'
46+
$enablePagination: '%ibexa.graphql.schema.ezobjectrelationlist.enable_pagination%'
4647

4748
Ibexa\GraphQL\Schema\Domain\Content\Mapper\FieldDefinition\SelectionFieldDefinitionMapper:
4849
decorates: Ibexa\Contracts\GraphQL\Schema\Domain\Content\Mapper\FieldDefinition\FieldDefinitionMapper

src/lib/Resolver/RelationFieldResolver.php

Lines changed: 34 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,15 @@
1111
use Ibexa\Core\FieldType;
1212
use Ibexa\GraphQL\DataLoader\ContentLoader;
1313
use Ibexa\GraphQL\ItemFactory;
14+
use Ibexa\GraphQL\Relay\PageAwareConnection;
1415
use Ibexa\GraphQL\Value\Field;
16+
use Overblog\GraphQLBundle\Definition\Argument;
17+
use Overblog\GraphQLBundle\Relay\Connection\Paginator;
1518

1619
final class RelationFieldResolver
1720
{
21+
public const DEFAULT_LIMIT = 25;
22+
1823
/** @var \Ibexa\GraphQL\DataLoader\ContentLoader */
1924
private $contentLoader;
2025

@@ -27,29 +32,48 @@ public function __construct(ContentLoader $contentLoader, ItemFactory $relatedCo
2732
$this->itemFactory = $relatedContentItemFactory;
2833
}
2934

30-
public function resolveRelationFieldValue(Field $field, $multiple = false)
35+
public function resolveRelationFieldValue(Field $field, $multiple = false, Argument $args)
3136
{
3237
$destinationContentIds = $this->getContentIds($field);
3338

3439
if (empty($destinationContentIds) || array_key_exists(0, $destinationContentIds) && null === $destinationContentIds[0]) {
3540
return $multiple ? [] : null;
3641
}
3742

38-
$contentItems = $this->contentLoader->find(new Query(
43+
$query = new Query(
3944
['filter' => new Query\Criterion\ContentId($destinationContentIds)]
40-
));
45+
);
4146

4247
if ($multiple) {
43-
return array_map(
44-
function ($contentId) use ($contentItems) {
45-
return $this->itemFactory->fromContent(
46-
$contentItems[array_search($contentId, array_column($contentItems, 'id'))]
47-
);
48-
},
49-
$destinationContentIds
48+
$paginator = new Paginator(function ($offset, $limit) use ($query) {
49+
$query->offset = $offset;
50+
$query->limit = $limit ?? self::DEFAULT_LIMIT;
51+
$contentItems = $this->contentLoader->find($query);
52+
53+
return array_map(
54+
function ($content) {
55+
return $this->itemFactory->fromContent(
56+
$content
57+
);
58+
},
59+
$contentItems
60+
);
61+
});
62+
63+
return PageAwareConnection::fromConnection(
64+
$paginator->auto(
65+
$args,
66+
function () use ($query) {
67+
return $this->contentLoader->count($query);
68+
}
69+
),
70+
$args
5071
);
5172
}
5273

74+
$query->limit = 1;
75+
$contentItems = $this->contentLoader->find($query);
76+
5377
return $contentItems[0] ? $this->itemFactory->fromContent($contentItems[0]) : null;
5478
}
5579

src/lib/Schema/Domain/Content/Mapper/FieldDefinition/RelationFieldDefinitionMapper.php

Lines changed: 33 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -14,24 +14,22 @@
1414

1515
class RelationFieldDefinitionMapper extends DecoratingFieldDefinitionMapper implements FieldDefinitionMapper
1616
{
17-
/**
18-
* @var \Ibexa\GraphQL\Schema\Domain\Content\NameHelper
19-
*/
20-
private $nameHelper;
17+
private NameHelper $nameHelper;
2118

22-
/**
23-
* @var \Ibexa\Contracts\Core\Repository\ContentTypeService
24-
*/
25-
private $contentTypeService;
19+
private ContentTypeService $contentTypeService;
20+
21+
private bool $enablePagination;
2622

2723
public function __construct(
2824
FieldDefinitionMapper $innerMapper,
2925
NameHelper $nameHelper,
30-
ContentTypeService $contentTypeService
26+
ContentTypeService $contentTypeService,
27+
bool $enablePagination
3128
) {
3229
parent::__construct($innerMapper);
3330
$this->nameHelper = $nameHelper;
3431
$this->contentTypeService = $contentTypeService;
32+
$this->enablePagination = $enablePagination;
3533
}
3634

3735
public function mapToFieldValueType(FieldDefinition $fieldDefinition): ?string
@@ -54,7 +52,18 @@ public function mapToFieldValueType(FieldDefinition $fieldDefinition): ?string
5452
}
5553

5654
if ($this->isMultiple($fieldDefinition)) {
57-
$type = "[$type]";
55+
if ($this->enablePagination) {
56+
$type = 'RelationsConnection';
57+
} else {
58+
@trigger_error(
59+
'Disable pagination for ezobjectrelationlist has been deprecated since version 4.6 ' .
60+
'and will be removed in version 5.0. To start receiving `RelationsConnection` instead of the deprecated ' .
61+
'`[' . $type . ']`, set the parameter `ibexa.graphql.schema.ezobjectrelationlist.enable_pagination` to `true`.',
62+
E_USER_DEPRECATED
63+
);
64+
65+
$type = "[$type]";
66+
}
5867
}
5968

6069
return $type;
@@ -68,14 +77,27 @@ public function mapToFieldValueResolver(FieldDefinition $fieldDefinition): ?stri
6877

6978
$isMultiple = $this->isMultiple($fieldDefinition) ? 'true' : 'false';
7079

71-
return sprintf('@=resolver("RelationFieldValue", [field, %s])', $isMultiple);
80+
return sprintf('@=resolver("RelationFieldValue", [field, %s, args])', $isMultiple);
7281
}
7382

7483
protected function canMap(FieldDefinition $fieldDefinition)
7584
{
7685
return in_array($fieldDefinition->fieldTypeIdentifier, ['ezobjectrelation', 'ezobjectrelationlist']);
7786
}
7887

88+
public function mapToFieldValueArgsBuilder(FieldDefinition $fieldDefinition): ?string
89+
{
90+
if (!$this->canMap($fieldDefinition)) {
91+
return parent::mapToFieldValueArgsBuilder($fieldDefinition);
92+
}
93+
94+
if ($this->isMultiple($fieldDefinition) && $this->enablePagination) {
95+
return 'Relay::Connection';
96+
}
97+
98+
return parent::mapToFieldValueArgsBuilder($fieldDefinition);
99+
}
100+
79101
/**
80102
* Not implemented since we don't use it (canMap is overridden).
81103
*/

0 commit comments

Comments
 (0)