Skip to content

Commit d1c3cc3

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

File tree

6 files changed

+104
-27
lines changed

6 files changed

+104
-27
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/resolvers.yaml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,8 @@ services:
4949
- { name: overblog_graphql.resolver, alias: "ItemsOfTypeAsConnection", method: "resolveItemsOfTypeAsConnection" }
5050

5151
Ibexa\GraphQL\Resolver\RelationFieldResolver:
52+
arguments:
53+
$enablePagination: '%ibexa.graphql.schema.ezobjectrelationlist.enable_pagination%'
5254
tags:
5355
- { name: overblog_graphql.resolver, alias: "RelationFieldValue", method: "resolveRelationFieldValue" }
5456

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: 57 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -11,45 +11,86 @@
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
{
18-
/** @var \Ibexa\GraphQL\DataLoader\ContentLoader */
19-
private $contentLoader;
21+
public const DEFAULT_LIMIT = 25;
2022

21-
/** @var \Ibexa\GraphQL\ItemFactory */
22-
private $itemFactory;
23+
private ContentLoader $contentLoader;
2324

24-
public function __construct(ContentLoader $contentLoader, ItemFactory $relatedContentItemFactory)
25-
{
25+
private ItemFactory $itemFactory;
26+
27+
private bool $enablePagination;
28+
29+
public function __construct(
30+
ContentLoader $contentLoader,
31+
ItemFactory $relatedContentItemFactory,
32+
bool $enablePagination
33+
) {
2634
$this->contentLoader = $contentLoader;
2735
$this->itemFactory = $relatedContentItemFactory;
36+
$this->enablePagination = $enablePagination;
2837
}
2938

30-
public function resolveRelationFieldValue(Field $field, $multiple = false)
39+
public function resolveRelationFieldValue(Field $field, $multiple = false, Argument $args)
3140
{
3241
$destinationContentIds = $this->getContentIds($field);
3342

3443
if (empty($destinationContentIds) || array_key_exists(0, $destinationContentIds) && null === $destinationContentIds[0]) {
3544
return $multiple ? [] : null;
3645
}
3746

38-
$contentItems = $this->contentLoader->find(new Query(
47+
$query = new Query(
3948
['filter' => new Query\Criterion\ContentId($destinationContentIds)]
40-
));
49+
);
4150

4251
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
52+
if (!$this->enablePagination) {
53+
$contentItems = $this->contentLoader->find($query);
54+
55+
return array_map(
56+
function ($contentId) use ($contentItems) {
57+
return $this->itemFactory->fromContent(
58+
$contentItems[array_search($contentId, array_column($contentItems, 'id'))]
59+
);
60+
},
61+
$destinationContentIds
62+
);
63+
}
64+
65+
$paginator = new Paginator(function ($offset, $limit) use ($query) {
66+
$query->offset = $offset;
67+
$query->limit = $limit ?? self::DEFAULT_LIMIT;
68+
$contentItems = $this->contentLoader->find($query);
69+
70+
return array_map(
71+
function ($content) {
72+
return $this->itemFactory->fromContent(
73+
$content
74+
);
75+
},
76+
$contentItems
77+
);
78+
});
79+
80+
return PageAwareConnection::fromConnection(
81+
$paginator->auto(
82+
$args,
83+
function () use ($query) {
84+
return $this->contentLoader->count($query);
85+
}
86+
),
87+
$args
5088
);
5189
}
5290

91+
$query->limit = 1;
92+
$contentItems = $this->contentLoader->find($query);
93+
5394
return $contentItems[0] ? $this->itemFactory->fromContent($contentItems[0]) : null;
5495
}
5596

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)