Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 4141327

Browse files
authoredFeb 22, 2020
Added entity reference layout revisions plugin. (#968)
1 parent bbe602a commit 4141327

File tree

1 file changed

+211
-0
lines changed

1 file changed

+211
-0
lines changed
 
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,211 @@
1+
<?php
2+
3+
namespace Drupal\graphql\Plugin\GraphQL\DataProducer\Field;
4+
5+
use Drupal\Core\Cache\RefinableCacheableDependencyInterface;
6+
use Drupal\Core\Entity\EntityInterface;
7+
use Drupal\Core\Entity\EntityTypeManager;
8+
use Drupal\Core\Entity\FieldableEntityInterface;
9+
use Drupal\Core\Entity\TranslatableInterface;
10+
use Drupal\Core\Field\EntityReferenceFieldItemListInterface;
11+
use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
12+
use Drupal\Core\Session\AccountInterface;
13+
use Drupal\graphql\GraphQL\Execution\FieldContext;
14+
use Drupal\graphql\Plugin\GraphQL\DataProducer\DataProducerPluginBase;
15+
use Drupal\graphql\GraphQL\Buffers\EntityRevisionBuffer;
16+
use GraphQL\Deferred;
17+
use Symfony\Component\DependencyInjection\ContainerInterface;
18+
19+
/**
20+
* Loads the entity reference layout revisions.
21+
*
22+
* @DataProducer(
23+
* id = "entity_reference_layout_revisions",
24+
* name = @Translation("Entity reference layout revisions"),
25+
* description = @Translation("Loads entities from an entity reference layout revisions field."),
26+
* provider = "entity_reference_layout",
27+
* produces = @ContextDefinition("entity",
28+
* label = @Translation("Entity"),
29+
* multiple = TRUE
30+
* ),
31+
* consumes = {
32+
* "entity" = @ContextDefinition("entity",
33+
* label = @Translation("Parent entity")
34+
* ),
35+
* "field" = @ContextDefinition("string",
36+
* label = @Translation("Field name")
37+
* ),
38+
* "language" = @ContextDefinition("string",
39+
* label = @Translation("Language"),
40+
* multiple = TRUE,
41+
* required = FALSE
42+
* ),
43+
* "bundle" = @ContextDefinition("string",
44+
* label = @Translation("Entity bundle(s)"),
45+
* multiple = TRUE,
46+
* required = FALSE
47+
* ),
48+
* "access" = @ContextDefinition("boolean",
49+
* label = @Translation("Check access"),
50+
* required = FALSE,
51+
* default_value = TRUE
52+
* ),
53+
* "access_user" = @ContextDefinition("entity:user",
54+
* label = @Translation("User"),
55+
* required = FALSE,
56+
* default_value = NULL
57+
* ),
58+
* "access_operation" = @ContextDefinition("string",
59+
* label = @Translation("Operation"),
60+
* required = FALSE,
61+
* default_value = "view"
62+
* )
63+
* }
64+
* )
65+
*/
66+
class EntityReferenceLayoutRevisions extends DataProducerPluginBase implements ContainerFactoryPluginInterface {
67+
68+
/**
69+
* The entity type manager service.
70+
*
71+
* @var \Drupal\Core\Entity\EntityTypeManager
72+
*/
73+
protected $entityTypeManager;
74+
75+
/**
76+
* The entity revision buffer service.
77+
*
78+
* @var \Drupal\graphql\GraphQL\Buffers\EntityRevisionBuffer
79+
*/
80+
protected $entityRevisionBuffer;
81+
82+
/**
83+
* {@inheritdoc}
84+
*
85+
* @codeCoverageIgnore
86+
*/
87+
public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
88+
return new static(
89+
$configuration,
90+
$plugin_id,
91+
$plugin_definition,
92+
$container->get('entity_type.manager'),
93+
$container->get('graphql.buffer.entity_revision')
94+
);
95+
}
96+
97+
/**
98+
* EntityLoad constructor.
99+
*
100+
* @param array $configuration
101+
* The plugin configuration array.
102+
* @param string $pluginId
103+
* The plugin id.
104+
* @param array $pluginDefinition
105+
* The plugin definition array.
106+
* @param \Drupal\Core\Entity\EntityTypeManager $entityTypeManager
107+
* The entity type manager service.
108+
* @param \Drupal\graphql\GraphQL\Buffers\EntityRevisionBuffer $entityRevisionBuffer
109+
* The entity revision buffer service.
110+
*
111+
* @codeCoverageIgnore
112+
*/
113+
public function __construct(
114+
array $configuration,
115+
string $pluginId,
116+
array $pluginDefinition,
117+
EntityTypeManager $entityTypeManager,
118+
EntityRevisionBuffer $entityRevisionBuffer
119+
) {
120+
parent::__construct($configuration, $pluginId, $pluginDefinition);
121+
$this->entityTypeManager = $entityTypeManager;
122+
$this->entityRevisionBuffer = $entityRevisionBuffer;
123+
}
124+
125+
/**
126+
* Resolves entity reference layout revisions for a given field of a given entity.
127+
*
128+
* May optionally respect the entity bundles and language.
129+
*
130+
* @param \Drupal\Core\Entity\EntityInterface $entity
131+
* The entity.
132+
* @param string $field
133+
* The field of a given entity to get entity reference layout revisions for.
134+
* @param string|null $language
135+
* Optional. Language to be respected for retrieved entities.
136+
* @param array|null $bundles
137+
* Optional. List of bundles to be respected for retrieved entities.
138+
* @param bool $access
139+
* Whether check for access or not. Default is true.
140+
* @param \Drupal\Core\Session\AccountInterface|null $accessUser
141+
* User entity to check access for. Default is null.
142+
* @param string $accessOperation
143+
* Operation to check access for. Default is view.
144+
* @param \Drupal\graphql\GraphQL\Execution\FieldContext $context
145+
* The caching context related to the current field.
146+
*
147+
* @return \GraphQL\Deferred|null
148+
* A promise that will return entities or NULL if there aren't any.
149+
*/
150+
public function resolve(EntityInterface $entity, string $field, ?string $language, ?array $bundles, ?bool $access, ?AccountInterface $accessUser, ?string $accessOperation, FieldContext $context): ?Deferred {
151+
if (!$entity instanceof FieldableEntityInterface || !$entity->hasField($field)) {
152+
return NULL;
153+
}
154+
155+
$definition = $entity->getFieldDefinition($field);
156+
if ($definition->getType() !== 'entity_reference_layout_revisioned') {
157+
return NULL;
158+
}
159+
160+
$definition = $entity->getFieldDefinition($field);
161+
$type = $definition->getSetting('target_type');
162+
if (($values = $entity->get($field)) && $values instanceof EntityReferenceFieldItemListInterface) {
163+
$vids = array_map(function ($value) {
164+
return $value['target_revision_id'];
165+
}, $values->getValue());
166+
167+
$resolver = $this->entityRevisionBuffer->add($type, $vids);
168+
return new Deferred(function () use ($type, $language, $bundles, $access, $accessUser, $accessOperation, $resolver, $context) {
169+
$entities = $resolver() ?: [];
170+
171+
$entities = array_filter($entities, function (EntityInterface $entity) use ($language, $bundles, $access, $accessOperation, $accessUser, $context) {
172+
if (isset($bundles) && !in_array($entity->bundle(), $bundles)) {
173+
return FALSE;
174+
}
175+
176+
// Get the correct translation.
177+
if (isset($language) && $language != $entity->language()->getId() && $entity instanceof TranslatableInterface) {
178+
$entity = $entity->getTranslation($language);
179+
$entity->addCacheContexts(["static:language:{$language}"]);
180+
}
181+
182+
// Check if the passed user (or current user if none is passed) has
183+
// access to the entity, if not return NULL.
184+
if ($access) {
185+
/* @var $accessResult \Drupal\Core\Access\AccessResultInterface */
186+
$accessResult = $entity->access($accessOperation, $accessUser, TRUE);
187+
$context->addCacheableDependency($accessResult);
188+
if (!$accessResult->isAllowed()) {
189+
return FALSE;
190+
}
191+
}
192+
193+
return TRUE;
194+
});
195+
196+
if (empty($entities)) {
197+
$type = $this->entityTypeManager->getDefinition($type);
198+
/** @var \Drupal\Core\Entity\EntityTypeInterface $type */
199+
$tags = $type->getListCacheTags();
200+
$context->addCacheTags($tags);
201+
return NULL;
202+
}
203+
204+
return $entities;
205+
});
206+
}
207+
208+
return NULL;
209+
}
210+
211+
}

0 commit comments

Comments
 (0)
Please sign in to comment.