Skip to content

Commit 9009883

Browse files
authored
Also collect cache metadata from types. (#548)
1 parent 58a9b74 commit 9009883

12 files changed

Lines changed: 112 additions & 26 deletions

File tree

graphql.module

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
<?php
22

3+
use Drupal\Core\Cache\Cache;
34
use Drupal\Core\Url;
45
use Drupal\graphql\Utility\StringHelper;
56

@@ -63,7 +64,7 @@ function graphql_graphql_interfaces_alter(&$definitions) {
6364
}, $definitions);
6465

6566
foreach ($interfaces as $index => $list) {
66-
$definition['interfaces'] = $list;
67+
$definitions[$index]['interfaces'] = $list;
6768
}
6869
}
6970

modules/graphql_core/src/Plugin/Deriver/Interfaces/EntityTypeDeriver.php

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ public function getDerivativeDefinitions($basePluginDefinition) {
2424
continue;
2525
}
2626

27-
$this->derivatives[$typeId] = [
27+
$derivative = [
2828
'name' => StringHelper::camelCase($typeId),
2929
'description' => $this->t("The '@type' entity type.", [
3030
'@type' => $type->getLabel(),
@@ -33,6 +33,13 @@ public function getDerivativeDefinitions($basePluginDefinition) {
3333
'interfaces' => $this->getInterfaces($type, $basePluginDefinition),
3434
'entity_type' => $typeId,
3535
] + $basePluginDefinition;
36+
37+
if ($typeId === 'node') {
38+
// TODO: Make this more generic somehow.
39+
$derivative['response_cache_contexts'][] = 'user.node_grants:view';
40+
}
41+
42+
$this->derivatives[$typeId] = $derivative;
3643
}
3744

3845
return parent::getDerivativeDefinitions($basePluginDefinition);

modules/graphql_core/src/Plugin/Deriver/Types/EntityBundleDeriver.php

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ public function getDerivativeDefinitions($basePluginDefinition) {
7373
}
7474

7575
foreach ($bundles[$typeId] as $bundle => $bundleDefinition) {
76-
$this->derivatives[$typeId . '-' . $bundle] = [
76+
$derivative = [
7777
'name' => StringHelper::camelCase($typeId, $bundle),
7878
'description' => $this->t("The '@bundle' bundle of the '@type' entity type.", [
7979
'@bundle' => $bundleDefinition['label'],
@@ -84,6 +84,13 @@ public function getDerivativeDefinitions($basePluginDefinition) {
8484
'entity_type' => $typeId,
8585
'entity_bundle' => $bundle,
8686
] + $basePluginDefinition;
87+
88+
if ($typeId === 'node') {
89+
// TODO: Make this more generic somehow.
90+
$derivative['response_cache_contexts'][] = 'user.node_grants:view';
91+
}
92+
93+
$this->derivatives[$typeId . '-' . $bundle] = $derivative;
8794
}
8895
}
8996

modules/graphql_core/src/Plugin/Deriver/Types/EntityTypeDeriver.php

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ public function getDerivativeDefinitions($basePluginDefinition) {
2525
continue;
2626
}
2727

28-
$this->derivatives[$typeId] = [
28+
$derivative = [
2929
'name' => StringHelper::camelCase($typeId),
3030
'description' => $this->t("The '@type' entity type.", [
3131
'@type' => $type->getLabel(),
@@ -34,6 +34,13 @@ public function getDerivativeDefinitions($basePluginDefinition) {
3434
'interfaces' => $this->getInterfaces($type, $basePluginDefinition),
3535
'entity_type' => $typeId,
3636
] + $basePluginDefinition;
37+
38+
if ($typeId === 'node') {
39+
// TODO: Make this more generic somehow.
40+
$derivative['response_cache_contexts'][] = 'user.node_grants:view';
41+
}
42+
43+
$this->derivatives[$typeId] = $derivative;
3744
}
3845

3946
return parent::getDerivativeDefinitions($basePluginDefinition);

src/Annotation/GraphQLAnnotationBase.php

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,27 @@ abstract class GraphQLAnnotationBase extends Plugin {
6969
*/
7070
public $schema_cache_max_age = CacheBackendInterface::CACHE_PERMANENT;
7171

72+
/**
73+
* The cache contexts for caching the response.
74+
*
75+
* @var array
76+
*/
77+
public $response_cache_contexts = ['user.permissions'];
78+
79+
/**
80+
* The cache tags for caching theresponse.
81+
*
82+
* @var array
83+
*/
84+
public $response_cache_tags = [];
85+
86+
/**
87+
* The cache max age for caching the response.
88+
*
89+
* @var array
90+
*/
91+
public $response_cache_max_age = CacheBackendInterface::CACHE_PERMANENT;
92+
7293
/**
7394
* GraphQLAnnotationBase constructor.
7495
*

src/Annotation/GraphQLField.php

Lines changed: 0 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -61,25 +61,4 @@ class GraphQLField extends GraphQLAnnotationBase {
6161
*/
6262
public $deprecated = FALSE;
6363

64-
/**
65-
* The cache contexts for caching the response.
66-
*
67-
* @var array
68-
*/
69-
public $response_cache_contexts = ['user.permissions'];
70-
71-
/**
72-
* The cache tags for caching theresponse.
73-
*
74-
* @var array
75-
*/
76-
public $response_cache_tags = [];
77-
78-
/**
79-
* The cache max age for caching the response.
80-
*
81-
* @var array
82-
*/
83-
public $response_cache_max_age = CacheBackendInterface::CACHE_PERMANENT;
84-
8564
}

src/GraphQL/Visitors/CacheContextsCollector.php

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,10 @@
22

33
namespace Drupal\graphql\GraphQL\Visitors;
44

5+
use Drupal\Core\Cache\Cache;
56
use GraphQL\Language\AST\FieldNode;
67
use GraphQL\Language\AST\NodeKind;
8+
use GraphQL\Type\Definition\LeafType;
79
use GraphQL\Utils\TypeInfo;
810

911
class CacheContextsCollector {
@@ -17,10 +19,38 @@ public function getVisitor(TypeInfo $info, array &$contexts) {
1719
'leave' => function (FieldNode $field) use ($info, &$contexts) {
1820
$definition = $info->getFieldDef();
1921
if (!empty($definition->config['contexts'])) {
20-
$contexts = array_unique(array_merge($contexts, $definition->config['contexts']));
22+
$contexts = Cache::mergeContexts($contexts, $this->collectCacheContexts($definition->config['contexts']));
23+
}
24+
25+
$parent = $info->getParentType();
26+
if (!empty($parent->config['contexts'])) {
27+
$contexts = Cache::mergeContexts($contexts, $this->collectCacheContexts($parent->config['contexts']));
28+
}
29+
30+
$type = $info->getType();
31+
// Collect cache metadata from leaf types.
32+
if ($type instanceof LeafType && !empty($type->config['contexts'])) {
33+
$contexts = Cache::mergeContexts($contexts, $this->collectCacheContexts($type->config['contexts']));
2134
}
2235
},
2336
],
2437
];
2538
}
39+
40+
/**
41+
* Collects the cache contexts from a type or field config.
42+
*
43+
* @param array|callable $contexts
44+
* The cache contexts array or a callable to return cache contexts.
45+
*
46+
* @return array
47+
* The collected cache contexts.
48+
*/
49+
protected function collectCacheContexts($contexts) {
50+
if (is_callable($contexts)) {
51+
return $contexts();
52+
}
53+
54+
return $contexts;
55+
}
2656
}

src/Plugin/GraphQL/Enums/EnumPluginBase.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,15 @@
33
namespace Drupal\graphql\Plugin\GraphQL\Enums;
44

55
use Drupal\Component\Plugin\PluginBase;
6+
use Drupal\graphql\Plugin\GraphQL\Traits\CacheablePluginTrait;
67
use Drupal\graphql\Plugin\GraphQL\Traits\DescribablePluginTrait;
78
use Drupal\graphql\Plugin\SchemaBuilderInterface;
89
use Drupal\graphql\Plugin\TypePluginInterface;
910
use Drupal\graphql\Plugin\TypePluginManager;
1011
use GraphQL\Type\Definition\EnumType;
1112

1213
abstract class EnumPluginBase extends PluginBase implements TypePluginInterface {
14+
use CacheablePluginTrait;
1315
use DescribablePluginTrait;
1416

1517
/**
@@ -20,6 +22,7 @@ public static function createInstance(SchemaBuilderInterface $builder, TypePlugi
2022
'name' => $definition['name'],
2123
'description' => $definition['description'],
2224
'values' => $definition['values'],
25+
'contexts' => $definition['contexts'],
2326
]);
2427
}
2528

@@ -33,6 +36,7 @@ public function getDefinition() {
3336
'name' => $definition['name'],
3437
'description' => $this->buildDescription($definition),
3538
'values' => $this->buildEnumValues($definition),
39+
'contexts' => $this->buildCacheContexts($definition),
3640
];
3741
}
3842

src/Plugin/GraphQL/InputTypes/InputTypePluginBase.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
namespace Drupal\graphql\Plugin\GraphQL\InputTypes;
44

55
use Drupal\Component\Plugin\PluginBase;
6+
use Drupal\graphql\Plugin\GraphQL\Traits\CacheablePluginTrait;
67
use Drupal\graphql\Plugin\GraphQL\Traits\DescribablePluginTrait;
78
use Drupal\graphql\Plugin\GraphQL\Traits\TypedPluginTrait;
89
use Drupal\graphql\Plugin\SchemaBuilderInterface;
@@ -12,6 +13,7 @@
1213
use GraphQL\Type\Definition\InputObjectType;
1314

1415
abstract class InputTypePluginBase extends PluginBase implements TypePluginInterface {
16+
use CacheablePluginTrait;
1517
use DescribablePluginTrait;
1618
use TypedPluginTrait;
1719

@@ -22,6 +24,7 @@ public static function createInstance(SchemaBuilderInterface $builder, TypePlugi
2224
return new InputObjectType([
2325
'name' => $definition['name'],
2426
'description' => $definition['description'],
27+
'contexts' => $definition['contexts'],
2528
'fields' => function () use ($builder, $definition) {
2629
return $builder->processArguments($definition['fields']);
2730
},
@@ -38,6 +41,7 @@ public function getDefinition() {
3841
'name' => $definition['name'],
3942
'description' => $this->buildDescription($definition),
4043
'fields' => $this->buildFields($definition),
44+
'contexts' => $this->buildCacheContexts($definition),
4145
];
4246
}
4347

src/Plugin/GraphQL/Interfaces/InterfacePluginBase.php

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,16 @@
33
namespace Drupal\graphql\Plugin\GraphQL\Interfaces;
44

55
use Drupal\Component\Plugin\PluginBase;
6+
use Drupal\Core\Cache\Cache;
7+
use Drupal\graphql\Plugin\GraphQL\Traits\CacheablePluginTrait;
68
use Drupal\graphql\Plugin\GraphQL\Traits\DescribablePluginTrait;
79
use Drupal\graphql\Plugin\SchemaBuilderInterface;
810
use Drupal\graphql\Plugin\TypePluginInterface;
911
use Drupal\graphql\Plugin\TypePluginManager;
1012
use GraphQL\Type\Definition\InterfaceType;
1113

1214
abstract class InterfacePluginBase extends PluginBase implements TypePluginInterface {
15+
use CacheablePluginTrait;
1316
use DescribablePluginTrait;
1417

1518
/**
@@ -19,6 +22,20 @@ public static function createInstance(SchemaBuilderInterface $builder, TypePlugi
1922
return new InterfaceType([
2023
'name' => $definition['name'],
2124
'description' => $definition['description'],
25+
'contexts' => function () use ($builder, $definition) {
26+
$types = $builder->getSubTypes($definition['name']);
27+
28+
return array_reduce($types, function ($carry, $current) use ($builder) {
29+
$type = $builder->getType($current);
30+
if (!empty($type->config['contexts'])) {
31+
$contexts = $type->config['contexts'];
32+
$contexts = is_callable($contexts) ? $contexts() : $contexts;
33+
return Cache::mergeContexts($carry, $contexts);
34+
}
35+
36+
return $carry;
37+
}, $definition['contexts']);
38+
},
2239
'fields' => function () use ($builder, $definition) {
2340
$fields = $builder->getFields($definition['name']);
2441

@@ -49,6 +66,7 @@ public function getDefinition() {
4966
'name' => $definition['name'],
5067
'description' => $this->buildDescription($definition),
5168
'interfaces' => $this->buildInterfaces($definition),
69+
'contexts' => $this->buildCacheContexts($definition),
5270
];
5371
}
5472

0 commit comments

Comments
 (0)