Skip to content

Commit 3f10a44

Browse files
authored
Allow loading of entity revisions. (#496)
1 parent 202563f commit 3f10a44

13 files changed

Lines changed: 300 additions & 42 deletions

File tree

modules/graphql_core/src/Plugin/Deriver/Fields/EntityByIdDeriver.php

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,6 @@
1010
use Drupal\graphql\Utility\StringHelper;
1111
use Symfony\Component\DependencyInjection\ContainerInterface;
1212

13-
/**
14-
* Create GraphQL entityById fields based on available Drupal entity types.
15-
*/
1613
class EntityByIdDeriver extends DeriverBase implements ContainerDeriverInterface {
1714

1815
use StringTranslationTrait;
@@ -28,17 +25,13 @@ class EntityByIdDeriver extends DeriverBase implements ContainerDeriverInterface
2825
* {@inheritdoc}
2926
*/
3027
public static function create(ContainerInterface $container, $basePluginId) {
31-
return new static(
32-
$container->get('entity_type.manager')
33-
);
28+
return new static($container->get('entity_type.manager'));
3429
}
3530

3631
/**
3732
* {@inheritdoc}
3833
*/
39-
public function __construct(
40-
EntityTypeManagerInterface $entityTypeManager
41-
) {
34+
public function __construct(EntityTypeManagerInterface $entityTypeManager) {
4235
$this->entityTypeManager = $entityTypeManager;
4336
}
4437

modules/graphql_core/src/Plugin/Deriver/Fields/EntityFieldPropertyDeriver.php

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,6 @@
1010
use Drupal\graphql\Utility\StringHelper;
1111
use Symfony\Component\DependencyInjection\ContainerInterface;
1212

13-
/**
14-
* Attach new properties to field types.
15-
*/
1613
class EntityFieldPropertyDeriver extends DeriverBase implements ContainerDeriverInterface {
1714

1815
/**

modules/graphql_core/src/Plugin/Deriver/Fields/EntityQueryDeriver.php

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,6 @@
1212
use Drupal\graphql\Utility\StringHelper;
1313
use Symfony\Component\DependencyInjection\ContainerInterface;
1414

15-
/**
16-
* Create GraphQL entityQuery fields based on available Drupal entity types.
17-
*/
1815
class EntityQueryDeriver extends DeriverBase implements ContainerDeriverInterface {
1916
use StringTranslationTrait;
2017

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
<?php
2+
3+
namespace Drupal\graphql_core\Plugin\Deriver\Fields;
4+
5+
use Drupal\Component\Plugin\Derivative\DeriverBase;
6+
use Drupal\Core\Entity\ContentEntityTypeInterface;
7+
use Drupal\Core\Entity\EntityTypeManagerInterface;
8+
use Drupal\Core\Plugin\Discovery\ContainerDeriverInterface;
9+
use Drupal\Core\StringTranslation\StringTranslationTrait;
10+
use Drupal\graphql\Utility\StringHelper;
11+
use Symfony\Component\DependencyInjection\ContainerInterface;
12+
13+
class EntityRevisionByIdDeriver extends DeriverBase implements ContainerDeriverInterface {
14+
15+
use StringTranslationTrait;
16+
17+
/**
18+
* The entity type manager service.
19+
*
20+
* @var \Drupal\Core\Entity\EntityTypeManagerInterface
21+
*/
22+
protected $entityTypeManager;
23+
24+
/**
25+
* {@inheritdoc}
26+
*/
27+
public static function create(ContainerInterface $container, $basePluginId) {
28+
return new static($container->get('entity_type.manager'));
29+
}
30+
31+
/**
32+
* {@inheritdoc}
33+
*/
34+
public function __construct(EntityTypeManagerInterface $entityTypeManager) {
35+
$this->entityTypeManager = $entityTypeManager;
36+
}
37+
38+
/**
39+
* {@inheritdoc}
40+
*/
41+
public function getDerivativeDefinitions($basePluginDefinition) {
42+
foreach ($this->entityTypeManager->getDefinitions() as $id => $type) {
43+
if ($type instanceof ContentEntityTypeInterface && $type->isRevisionable()) {
44+
$derivative = [
45+
'name' => StringHelper::propCase($id, 'revision', 'by', 'id'),
46+
'type' => "entity:$id",
47+
'description' => $this->t("Loads '@type' entity revision by their revision id.", ['@type' => $type->getLabel()]),
48+
'entity_type' => $id,
49+
] + $basePluginDefinition;
50+
51+
if ($type->isTranslatable()) {
52+
$derivative['arguments']['language'] = [
53+
'type' => 'LanguageId',
54+
];
55+
}
56+
57+
$this->derivatives["entity:$id"] = $derivative;
58+
}
59+
}
60+
61+
return parent::getDerivativeDefinitions($basePluginDefinition);
62+
}
63+
64+
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
<?php
2+
3+
namespace Drupal\graphql_core\Plugin\GraphQL\Enums\EntityQuery;
4+
5+
use Drupal\graphql\Plugin\GraphQL\Enums\EnumPluginBase;
6+
7+
/**
8+
* @GraphQLEnum(
9+
* id = "entity_query_revision_mode",
10+
* name = "EntityQueryRevisionMode",
11+
* values = {
12+
* "default" = {
13+
* "name" = "default",
14+
* "description" = @Translation("Loads the current (default) revisions."),
15+
* },
16+
* "all" = {
17+
* "name" = "all",
18+
* "description" = @Translation("Loads all revisions."),
19+
* }
20+
* }
21+
* )
22+
*/
23+
class EntityQueryRevisionMode extends EnumPluginBase {
24+
25+
}

modules/graphql_core/src/Plugin/GraphQL/Fields/Entity/EntityById.php

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,6 @@
1818
* @GraphQLField(
1919
* id = "entity_by_id",
2020
* secure = true,
21-
* name = "entityById",
22-
* weight = -1,
2321
* arguments = {
2422
* "id" = "String!"
2523
* },
Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
<?php
2+
3+
namespace Drupal\graphql_core\Plugin\GraphQL\Fields\Entity;
4+
5+
use Drupal\Core\Cache\CacheableMetadata;
6+
use Drupal\Core\DependencyInjection\DependencySerializationTrait;
7+
use Drupal\Core\Entity\EntityRepositoryInterface;
8+
use Drupal\Core\Entity\EntityTypeManagerInterface;
9+
use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
10+
use Drupal\graphql\GraphQL\Buffers\EntityBuffer;
11+
use Drupal\graphql\GraphQL\Cache\CacheableValue;
12+
use Drupal\graphql\Plugin\GraphQL\Fields\FieldPluginBase;
13+
use Symfony\Component\DependencyInjection\ContainerInterface;
14+
use Youshido\GraphQL\Execution\ResolveInfo;
15+
16+
/**
17+
* @GraphQLField(
18+
* id = "entity_revision_by_id",
19+
* secure = true,
20+
* arguments = {
21+
* "id" = "String!"
22+
* },
23+
* deriver = "Drupal\graphql_core\Plugin\Deriver\Fields\EntityRevisionByIdDeriver"
24+
* )
25+
*/
26+
class EntityRevisionById extends FieldPluginBase implements ContainerFactoryPluginInterface {
27+
use DependencySerializationTrait;
28+
29+
/**
30+
* The entity type manager service.
31+
*
32+
* @var \Drupal\Core\Entity\EntityTypeManagerInterface
33+
*/
34+
protected $entityTypeManager;
35+
36+
/**
37+
* The entity repository service.
38+
*
39+
* @var \Drupal\Core\Entity\EntityRepositoryInterface
40+
*/
41+
protected $entityRepository;
42+
43+
/**
44+
* {@inheritdoc}
45+
*/
46+
public function __construct(
47+
array $configuration,
48+
$pluginId,
49+
$pluginDefinition,
50+
EntityTypeManagerInterface $entityTypeManager,
51+
EntityRepositoryInterface $entityRepository
52+
) {
53+
parent::__construct($configuration, $pluginId, $pluginDefinition);
54+
$this->entityTypeManager = $entityTypeManager;
55+
$this->entityRepository = $entityRepository;
56+
}
57+
58+
/**
59+
* {@inheritdoc}
60+
*/
61+
public static function create(ContainerInterface $container, array $configuration, $pluginId, $pluginDefinition) {
62+
return new static(
63+
$configuration,
64+
$pluginId,
65+
$pluginDefinition,
66+
$container->get('entity_type.manager'),
67+
$container->get('entity.repository')
68+
);
69+
}
70+
71+
/**
72+
* {@inheritdoc}
73+
*/
74+
protected function resolveValues($value, array $args, ResolveInfo $info) {
75+
$definition = $this->getPluginDefinition();
76+
$storage = $this->entityTypeManager->getStorage($definition['entity_type']);
77+
78+
if (!$entity = $storage->loadRevision($args['id'])) {
79+
// If there is no entity with this id, add the list cache tags so that the
80+
// cache entry is purged whenever a new entity of this type is saved.
81+
$pluginDefinition = $this->getPluginDefinition();
82+
$entityType = $this->entityTypeManager->getDefinition($pluginDefinition['entity_type']);
83+
$metadata = new CacheableMetadata();
84+
$metadata->addCacheTags($entityType->getListCacheTags());
85+
86+
yield new CacheableValue(NULL, [$metadata]);
87+
}
88+
/** @var \Drupal\Core\Access\AccessResultInterface $access */
89+
else if (($access = $entity->access('view', NULL, TRUE)) && $access->isAllowed()) {
90+
if (isset($args['language']) && $args['language'] != $entity->language()->getId()) {
91+
$entity = $this->entityRepository->getTranslationFromContext($entity, $args['language']);
92+
}
93+
94+
yield new CacheableValue($entity, [$access]);
95+
}
96+
else {
97+
// If the entity exists but we do not grant access to it, we still want
98+
// to have it's cache metadata in the output because future changes to
99+
// the entity might affect its visibility for the user.
100+
yield new CacheableValue(NULL, [$access]);
101+
}
102+
}
103+
104+
}

modules/graphql_core/src/Plugin/GraphQL/Fields/Entity/EntityTranslation.php

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@
1717
* id = "entity_translation",
1818
* secure = true,
1919
* name = "entityTranslation",
20-
* weight = -1,
2120
* type = "Entity",
2221
* parents = {"Entity"},
2322
* arguments = {

modules/graphql_core/src/Plugin/GraphQL/Fields/EntityQuery/EntityQuery.php

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,14 +11,10 @@
1111
use Youshido\GraphQL\Execution\ResolveInfo;
1212

1313
/**
14-
* Retrieve a list of entities through an entity query.
15-
*
1614
* @GraphQLField(
1715
* id = "entity_query",
1816
* secure = true,
19-
* name = "entityQuery",
2017
* type = "EntityQueryResult!",
21-
* weight = -1,
2218
* arguments = {
2319
* "offset" = {
2420
* "type" = "Int",
@@ -27,6 +23,10 @@
2723
* "limit" = {
2824
* "type" = "Int",
2925
* "default" = 10
26+
* },
27+
* "revisions" = {
28+
* "type" = "EntityQueryRevisionMode",
29+
* "default" = "default"
3030
* }
3131
* },
3232
* deriver = "Drupal\graphql_core\Plugin\Deriver\Fields\EntityQueryDeriver"
@@ -106,6 +106,14 @@ protected function getQuery($value, array $args, ResolveInfo $info) {
106106
$query->sort($entityType->getKey('id'));
107107
$query->accessCheck(TRUE);
108108

109+
// Check if this is a query for all entity revisions.
110+
if (!empty($args['revisions']) && $args['revisions'] === 'all') {
111+
// Mark the query as such and sort by the revision id too.
112+
$query->allRevisions();
113+
$query->addTag('revisions');
114+
$query->sort($entityType->getKey('revision'));
115+
}
116+
109117
if (!empty($args['filter'])) {
110118
/** @var \Youshido\GraphQL\Type\Object\AbstractObjectType $filter */
111119
$filter = $info->getField()->getArgument('filter')->getType();

0 commit comments

Comments
 (0)