Skip to content

Commit e821381

Browse files
author
Mateusz Dębiński
committed
Merge remote-tracking branch 'origin/4.6' into IBX-8417-cant-get-all-contents-from-Multiple-relations
# Conflicts: # spec/Schema/Domain/Content/Mapper/FieldDefinition/RelationFieldDefinitionMapperSpec.php # src/bundle/Resources/config/default_settings.yaml # src/lib/Resolver/RelationFieldResolver.php # src/lib/Schema/Domain/Content/Mapper/FieldDefinition/RelationFieldDefinitionMapper.php
2 parents dda310f + 0e057ff commit e821381

File tree

6 files changed

+87
-20
lines changed

6 files changed

+87
-20
lines changed

spec/Schema/Domain/Content/Mapper/FieldDefinition/RelationFieldDefinitionMapperSpec.php

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -61,19 +61,19 @@ public function it_maps_single_selection_with_a_unique_type_limitations_to_a_sin
6161
public function it_maps_multi_selection_without_type_limitations_to_an_array_of_generic_content(): void
6262
{
6363
$fieldDefinition = $this->createFieldDefinition(self::DEF_LIMIT_MULTI, []);
64-
$this->mapToFieldValueType($fieldDefinition)->shouldReturn('[Item]');
64+
$this->mapToFieldValueType($fieldDefinition)->shouldReturn('RelationsConnection');
6565
}
6666

6767
public function it_maps_multi_selection_with_multiple_type_limitations_to_an_array_of_generic_content(): void
6868
{
6969
$fieldDefinition = $this->createFieldDefinition(self::DEF_LIMIT_NONE, ['article', 'blog_post']);
70-
$this->mapToFieldValueType($fieldDefinition)->shouldReturn('[Item]');
70+
$this->mapToFieldValueType($fieldDefinition)->shouldReturn('RelationsConnection');
7171
}
7272

7373
public function it_maps_multi_selection_with_a_unique_type_limitations_to_an_array_of_that_type(): void
7474
{
7575
$fieldDefinition = $this->createFieldDefinition(self::DEF_LIMIT_MULTI, ['article']);
76-
$this->mapToFieldValueType($fieldDefinition)->shouldReturn('[ArticleItem]');
76+
$this->mapToFieldValueType($fieldDefinition)->shouldReturn('RelationsConnection');
7777
}
7878

7979
public function it_delegates_the_field_definition_type_to_the_inner_mapper(FieldDefinitionMapper $innerMapper): void
@@ -86,13 +86,13 @@ public function it_delegates_the_field_definition_type_to_the_inner_mapper(Field
8686
public function it_maps_multi_selection_to_resolve_multiple(): void
8787
{
8888
$fieldDefinition = $this->createFieldDefinition(self::DEF_LIMIT_MULTI);
89-
$this->mapToFieldValueResolver($fieldDefinition)->shouldReturn('@=query("RelationFieldValue", field, true)');
89+
$this->mapToFieldValueResolver($fieldDefinition)->shouldReturn('@=query("RelationFieldValue", field, true, args)');
9090
}
9191

9292
public function it_maps_single_selection_to_resolve_single(): void
9393
{
9494
$fieldDefinition = $this->createFieldDefinition(self::DEF_LIMIT_SINGLE);
95-
$this->mapToFieldValueResolver($fieldDefinition)->shouldReturn('@=query("RelationFieldValue", field, false)');
95+
$this->mapToFieldValueResolver($fieldDefinition)->shouldReturn('@=query("RelationFieldValue", field, false, args)');
9696
}
9797

9898
private function createFieldDefinition(int $selectionLimit = 0, array $selectionContentTypes = []): FieldDefinition

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
@@ -47,6 +47,8 @@ services:
4747
- { name: overblog_graphql.query, alias: "ItemsOfTypeAsConnection", method: "resolveItemsOfTypeAsConnection" }
4848

4949
Ibexa\GraphQL\Resolver\RelationFieldResolver:
50+
arguments:
51+
$enablePagination: '%ibexa.graphql.schema.ibexa_object_relation_list.enable_pagination%'
5052
tags:
5153
- { name: overblog_graphql.query, alias: "RelationFieldValue", method: "resolveRelationFieldValue" }
5254

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.ibexa_object_relation_list.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: 54 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -8,15 +8,22 @@
88
namespace Ibexa\GraphQL\Resolver;
99

1010
use GraphQL\Error\UserError;
11+
use Ibexa\Contracts\Core\Repository\Values\Content\Content;
1112
use Ibexa\Contracts\Core\Repository\Values\Content\Query;
1213
use Ibexa\Core\FieldType;
1314
use Ibexa\GraphQL\DataLoader\ContentLoader;
1415
use Ibexa\GraphQL\ItemFactory;
16+
use Ibexa\GraphQL\Relay\PageAwareConnection;
1517
use Ibexa\GraphQL\Value\Field;
1618
use Overblog\GraphQLBundle\Definition\Resolver\QueryInterface;
19+
use Ibexa\GraphQL\Value\Item;
20+
use Overblog\GraphQLBundle\Definition\Argument;
21+
use Overblog\GraphQLBundle\Relay\Connection\Paginator;
1722

1823
final class RelationFieldResolver implements QueryInterface
1924
{
25+
public const DEFAULT_LIMIT = 25;
26+
2027
private ContentLoader $contentLoader;
2128

2229
private ItemFactory $itemFactory;
@@ -27,29 +34,61 @@ public function __construct(ContentLoader $contentLoader, ItemFactory $relatedCo
2734
$this->itemFactory = $relatedContentItemFactory;
2835
}
2936

30-
public function resolveRelationFieldValue(Field $field, $multiple = false)
37+
public function resolveRelationFieldValue(Field $field, $multiple = false, ?Argument $args = null)
3138
{
3239
$destinationContentIds = $this->getContentIds($field);
3340

3441
if (empty($destinationContentIds) || array_key_exists(0, $destinationContentIds) && null === $destinationContentIds[0]) {
3542
return $multiple ? [] : null;
3643
}
3744

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

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

89+
$query->limit = 1;
90+
$contentItems = $this->contentLoader->find($query);
91+
5392
return $contentItems[0] ? $this->itemFactory->fromContent($contentItems[0]) : null;
5493
}
5594

@@ -62,10 +101,12 @@ private function getContentIds(Field $field): array
62101
{
63102
if ($field->value instanceof FieldType\RelationList\Value) {
64103
return $field->value->destinationContentIds;
65-
} elseif ($field->value instanceof FieldType\Relation\Value) {
104+
}
105+
106+
if ($field->value instanceof FieldType\Relation\Value) {
66107
return [$field->value->destinationContentId];
67-
} else {
68-
throw new UserError('\$field does not contain a RelationList or Relation Field value');
69108
}
109+
110+
throw new UserError('\$field does not contain a RelationList or Relation Field value');
70111
}
71112
}

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

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ public function mapToFieldValueType(FieldDefinition $fieldDefinition): ?string
4949
}
5050

5151
if ($this->isMultiple($fieldDefinition)) {
52-
$type = "[$type]";
52+
$type = "RelationsConnection";
5353
}
5454

5555
return $type;
@@ -63,14 +63,27 @@ public function mapToFieldValueResolver(FieldDefinition $fieldDefinition): ?stri
6363

6464
$isMultiple = $this->isMultiple($fieldDefinition) ? 'true' : 'false';
6565

66-
return sprintf('@=query("RelationFieldValue", field, %s)', $isMultiple);
66+
return sprintf('@=query("RelationFieldValue", field, %s, args)', $isMultiple);
6767
}
6868

6969
protected function canMap(FieldDefinition $fieldDefinition): bool
7070
{
7171
return in_array($fieldDefinition->fieldTypeIdentifier, ['ibexa_object_relation', 'ibexa_object_relation_list']);
7272
}
7373

74+
public function mapToFieldValueArgsBuilder(FieldDefinition $fieldDefinition): ?string
75+
{
76+
if (!$this->canMap($fieldDefinition)) {
77+
return parent::mapToFieldValueArgsBuilder($fieldDefinition);
78+
}
79+
80+
if ($this->isMultiple($fieldDefinition)) {
81+
return 'Relay::Connection';
82+
}
83+
84+
return parent::mapToFieldValueArgsBuilder($fieldDefinition);
85+
}
86+
7487
/**
7588
* Not implemented since we don't use it (canMap is overridden).
7689
*/

0 commit comments

Comments
 (0)