33namespace Drupal \graphql_core \Plugin \GraphQL \Fields \EntityQuery ;
44
55use Drupal \Core \DependencyInjection \DependencySerializationTrait ;
6+ use Drupal \Core \Entity \ContentEntityInterface ;
7+ use Drupal \Core \Entity \EntityInterface ;
8+ use Drupal \Core \Entity \EntityRepositoryInterface ;
69use Drupal \Core \Entity \EntityTypeManagerInterface ;
710use Drupal \Core \Entity \Query \QueryInterface ;
811use Drupal \Core \Plugin \ContainerFactoryPluginInterface ;
12+ use Drupal \Core \TypedData \TranslatableInterface ;
913use Drupal \graphql \GraphQL \Buffers \EntityBuffer ;
1014use Drupal \graphql \GraphQL \Cache \CacheableValue ;
1115use Drupal \graphql \Plugin \GraphQL \Fields \FieldPluginBase ;
2024 * secure = true,
2125 * name = "entities",
2226 * type = "[Entity]",
23- * parents = {"EntityQueryResult"}
27+ * parents = {"EntityQueryResult"},
28+ * arguments = {
29+ * "language" = "LanguageId"
30+ * }
2431 * )
2532 */
2633class EntityQueryEntities extends FieldPluginBase implements ContainerFactoryPluginInterface {
@@ -40,6 +47,13 @@ class EntityQueryEntities extends FieldPluginBase implements ContainerFactoryPlu
4047 */
4148 protected $ entityTypeManager ;
4249
50+ /**
51+ * The entity repository service.
52+ *
53+ * @var \Drupal\Core\Entity\EntityRepositoryInterface
54+ */
55+ protected $ entityRepository ;
56+
4357 /**
4458 * {@inheritdoc}
4559 */
@@ -49,6 +63,7 @@ public static function create(ContainerInterface $container, array $configuratio
4963 $ pluginId ,
5064 $ pluginDefinition ,
5165 $ container ->get ('entity_type.manager ' ),
66+ $ container ->get ('entity.repository ' ),
5267 $ container ->get ('graphql.buffer.entity ' )
5368 );
5469 }
@@ -64,6 +79,8 @@ public static function create(ContainerInterface $container, array $configuratio
6479 * The plugin definition array.
6580 * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entityTypeManager
6681 * The entity type manager service.
82+ * @param \Drupal\Core\Entity\EntityRepositoryInterface $entityRepository
83+ * The entity repository service.
6784 * @param \Drupal\graphql\GraphQL\Buffers\EntityBuffer $entityBuffer
6885 * The entity buffer service.
6986 */
@@ -72,11 +89,13 @@ public function __construct(
7289 $ pluginId ,
7390 $ pluginDefinition ,
7491 EntityTypeManagerInterface $ entityTypeManager ,
92+ EntityRepositoryInterface $ entityRepository ,
7593 EntityBuffer $ entityBuffer
7694 ) {
7795 parent ::__construct ($ configuration , $ pluginId , $ pluginDefinition );
78- $ this ->entityBuffer = $ entityBuffer ;
7996 $ this ->entityTypeManager = $ entityTypeManager ;
97+ $ this ->entityRepository = $ entityRepository ;
98+ $ this ->entityBuffer = $ entityBuffer ;
8099 }
81100
82101 /**
@@ -86,13 +105,14 @@ public function resolveValues($value, array $args, ResolveInfo $info) {
86105 if ($ value instanceof QueryInterface) {
87106 $ type = $ value ->getEntityTypeId ();
88107 $ result = $ value ->execute ();
108+ $ context = $ value ->getMetaData ('graphql_context ' );
89109
90110 if ($ value ->hasTag ('revisions ' )) {
91- return $ this ->resolveFromRevisionIds ($ type , array_keys ($ result ));
111+ return $ this ->resolveFromRevisionIds ($ type , array_keys ($ result ), $ context , $ args , $ info );
92112 }
93113
94114 // If this is a revision query, the version ids are the array keys.
95- return $ this ->resolveFromEntityIds ($ type , array_values ($ result ));
115+ return $ this ->resolveFromEntityIds ($ type , array_values ($ result ), $ context , $ args , $ info );
96116 }
97117 }
98118
@@ -103,14 +123,20 @@ public function resolveValues($value, array $args, ResolveInfo $info) {
103123 * The entity type.
104124 * @param array $ids
105125 * The entity ids to load.
126+ * @param mixed $context
127+ * The query context.
128+ * @param array $args
129+ * The field arguments array.
130+ * @param \Youshido\GraphQL\Execution\ResolveInfo $info
131+ * The resolve info object.
106132 *
107133 * @return \Closure
108134 * The deferred resolver.
109135 */
110- protected function resolveFromEntityIds ($ type , $ ids ) {
136+ protected function resolveFromEntityIds ($ type , $ ids, $ context , array $ args , ResolveInfo $ info ) {
111137 $ resolve = $ this ->entityBuffer ->add ($ type , $ ids );
112- return function ($ value , array $ args , ResolveInfo $ info ) use ($ resolve ) {
113- return $ this ->resolveEntities ($ resolve ());
138+ return function ($ value , array $ args , ResolveInfo $ info ) use ($ resolve, $ context ) {
139+ return $ this ->resolveEntities ($ resolve (), $ context , $ args , $ info );
114140 };
115141 }
116142
@@ -121,33 +147,51 @@ protected function resolveFromEntityIds($type, $ids) {
121147 * The entity type.
122148 * @param array $ids
123149 * The entity revision ids to load.
150+ * @param mixed $context
151+ * The query context.
152+ * @param array $args
153+ * The field arguments array.
154+ * @param \Youshido\GraphQL\Execution\ResolveInfo $info
155+ * The resolve info object.
124156 *
125157 * @return \Generator
126158 * The resolved revisions.
127159 */
128- protected function resolveFromRevisionIds ($ type , $ ids ) {
160+ protected function resolveFromRevisionIds ($ type , $ ids, $ context , array $ args , ResolveInfo $ info ) {
129161 $ storage = $ this ->entityTypeManager ->getStorage ($ type );
130162 $ entities = array_map (function ($ id ) use ($ storage ) {
131163 return $ storage ->loadRevision ($ id );
132164 }, $ ids );
133165
134- return $ this ->resolveEntities ($ entities );
166+ return $ this ->resolveEntities ($ entities, $ context , $ args , $ info );
135167 }
136168
137169 /**
138170 * Resolves entity objects and checks view permissions.
139171 *
140172 * @param array $entities
141173 * The entities to resolve.
174+ * @param mixed $context
175+ * The query context.
176+ * @param array $args
177+ * The field arguments array.
178+ * @param \Youshido\GraphQL\Execution\ResolveInfo $info
179+ * The resolve info object.
142180 *
143181 * @return \Generator
144182 * The resolved entities.
145183 */
146- protected function resolveEntities (array $ entities ) {
184+ protected function resolveEntities (array $ entities , $ context , array $ args , ResolveInfo $ info ) {
185+ $ language = $ this ->negotiateLanguage ($ context , $ args , $ info );
186+
147187 /** @var \Drupal\Core\Entity\EntityInterface $entity */
148188 foreach ($ entities as $ entity ) {
149- $ access = $ entity ->access ('view ' , NULL , TRUE );
189+ // Translate the entity if it is translatable and a language was given.
190+ if ($ language && $ entity instanceof TranslatableInterface && $ entity ->isTranslatable ()) {
191+ $ entity = $ this ->entityRepository ->getTranslationFromContext ($ entity , $ language );
192+ }
150193
194+ $ access = $ entity ->access ('view ' , NULL , TRUE );
151195 if ($ access ->isAllowed ()) {
152196 yield $ entity ->addCacheableDependency ($ access );
153197 }
@@ -157,4 +201,29 @@ protected function resolveEntities(array $entities) {
157201 }
158202 }
159203
204+ /**
205+ * Negotiate the language for the resolved entities.
206+ *
207+ * @param mixed $context
208+ * The query context.
209+ * @param array $args
210+ * The field arguments array.
211+ * @param \Youshido\GraphQL\Execution\ResolveInfo $info
212+ * The resolve info object.
213+ *
214+ * @return string|null
215+ * The negotiated language id.
216+ */
217+ protected function negotiateLanguage ($ context , $ args , ResolveInfo $ info ) {
218+ if (!empty ($ args ['language ' ])) {
219+ return $ args ['language ' ];
220+ }
221+
222+ if (isset ($ context ['parent ' ]) && ($ parent = $ context ['parent ' ]) && $ parent instanceof EntityInterface) {
223+ return $ parent ->language ()->getId ();
224+ }
225+
226+ return NULL ;
227+ }
228+
160229}
0 commit comments