Skip to content

Commit 9daffdd

Browse files
fubhyduartegarin
andcommitted
Derive fields based on field definitions instead of storage definitions. (#684)
Co-authored-by: Duarte Garin <duarte.garin@protonmail.com> Co-authored-by: Sebastian Siemssen <fubhy@fubhy.com>
1 parent ec316f1 commit 9daffdd

8 files changed

Lines changed: 94 additions & 150 deletions

File tree

modules/graphql_core/src/Plugin/Deriver/EntityFieldDeriverBase.php

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
use Drupal\Core\Entity\EntityTypeBundleInfoInterface;
88
use Drupal\Core\Entity\EntityTypeManagerInterface;
99
use Drupal\Core\Entity\FieldableEntityInterface;
10+
use Drupal\Core\Field\FieldDefinitionInterface;
1011
use Drupal\Core\Field\FieldStorageDefinitionInterface;
1112
use Drupal\Core\Plugin\Discovery\ContainerDeriverInterface;
1213
use Drupal\Core\Entity\EntityFieldManagerInterface;
@@ -21,17 +22,15 @@ abstract class EntityFieldDeriverBase extends DeriverBase implements ContainerDe
2122
/**
2223
* Provides plugin definition values from fields.
2324
*
24-
* @param string $entityTypeId
25-
* The host entity type.
26-
* @param \Drupal\Core\Field\FieldStorageDefinitionInterface $fieldDefinition
25+
* @param \Drupal\Core\Field\FieldDefinitionInterface $fieldDefinition
2726
* Field definition object.
2827
* @param array $basePluginDefinition
2928
* Base definition array.
3029
*
3130
* @return array
3231
* The derived plugin definitions for the given field.
3332
*/
34-
abstract protected function getDerivativeDefinitionsFromFieldDefinition($entityTypeId, FieldStorageDefinitionInterface $fieldDefinition, array $basePluginDefinition);
33+
abstract protected function getDerivativeDefinitionsFromFieldDefinition(FieldDefinitionInterface $fieldDefinition, array $basePluginDefinition);
3534

3635
/**
3736
* The entity type manager.
@@ -106,11 +105,19 @@ public function getDerivativeDefinitions($basePluginDefinition) {
106105
continue;
107106
}
108107

109-
foreach ($this->entityFieldManager->getFieldStorageDefinitions($entityTypeId) as $fieldStorageDefinition) {
110-
if ($derivatives = $this->getDerivativeDefinitionsFromFieldDefinition($entityTypeId, $fieldStorageDefinition, $basePluginDefinition)) {
108+
foreach ($this->entityFieldManager->getBaseFieldDefinitions($entityTypeId) as $fieldDefinition) {
109+
if ($derivatives = $this->getDerivativeDefinitionsFromFieldDefinition($fieldDefinition, $basePluginDefinition)) {
111110
$this->derivatives = array_merge($this->derivatives, $derivatives);
112111
}
113112
}
113+
114+
foreach ($this->entityBundleInfo->getBundleInfo($entityTypeId) as $bundleId => $bundleInfo) {
115+
foreach ($this->entityFieldManager->getFieldDefinitions($entityTypeId, $bundleId) as $fieldDefinition) {
116+
if ($derivatives = $this->getDerivativeDefinitionsFromFieldDefinition($fieldDefinition, $basePluginDefinition)) {
117+
$this->derivatives = array_merge($this->derivatives, $derivatives);
118+
}
119+
}
120+
}
114121
}
115122

116123
return $this->derivatives;

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

Lines changed: 20 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,9 @@
22

33
namespace Drupal\graphql_core\Plugin\Deriver\Fields;
44

5-
use Drupal\Core\Field\FieldStorageDefinitionInterface;
6-
use Drupal\field\FieldStorageConfigInterface;
5+
use Drupal\Core\Field\FieldDefinitionInterface;
6+
use Drupal\Core\TypedData\ComplexDataDefinitionInterface;
7+
use Drupal\Core\TypedData\ListDataDefinitionInterface;
78
use Drupal\graphql\Utility\StringHelper;
89
use Drupal\graphql_core\Plugin\Deriver\EntityFieldDeriverBase;
910

@@ -12,22 +13,24 @@ class EntityFieldDeriver extends EntityFieldDeriverBase {
1213
/**
1314
* {@inheritdoc}
1415
*/
15-
protected function getDerivativeDefinitionsFromFieldDefinition($entityTypeId, FieldStorageDefinitionInterface $fieldDefinition, array $basePluginDefinition) {
16-
if (!$propertyDefinitions = $fieldDefinition->getPropertyDefinitions()) {
17-
return [];
18-
}
19-
20-
$fieldName = $fieldDefinition->getName();
21-
if (!$parents = $this->getParentsForField($entityTypeId, $fieldDefinition)) {
16+
protected function getDerivativeDefinitionsFromFieldDefinition(FieldDefinitionInterface $fieldDefinition, array $basePluginDefinition) {
17+
$itemDefinition = $fieldDefinition->getItemDefinition();
18+
if (!($itemDefinition instanceof ComplexDataDefinitionInterface) || !$propertyDefinitions = $itemDefinition->getPropertyDefinitions()) {
2219
return [];
2320
}
2421

2522
$tags = array_merge($fieldDefinition->getCacheTags(), ['entity_field_info']);
2623
$maxAge = $fieldDefinition->getCacheMaxAge();
2724
$contexts = $fieldDefinition->getCacheContexts();
2825

26+
$entityTypeId = $fieldDefinition->getTargetEntityTypeId();
27+
$entityType = $this->entityTypeManager->getDefinition($entityTypeId);
28+
$supportsBundles = $entityType->hasKey('bundle');
29+
$fieldName = $fieldDefinition->getName();
30+
$fieldBundle = $fieldDefinition->getTargetBundle() ?: '';
31+
2932
$derivative = [
30-
'parents' => $parents,
33+
'parents' => [StringHelper::camelCase($entityTypeId, $supportsBundles ? $fieldBundle : '')],
3134
'name' => StringHelper::propCase($fieldName),
3235
'description' => $fieldDefinition->getDescription(),
3336
'field' => $fieldName,
@@ -37,49 +40,20 @@ protected function getDerivativeDefinitionsFromFieldDefinition($entityTypeId, Fi
3740
] + $basePluginDefinition;
3841

3942
if (count($propertyDefinitions) === 1) {
40-
// Flatten the structure for single-property fields.
41-
$derivative['type'] = reset($propertyDefinitions)->getDataType();
43+
$propertyDefinition = reset($propertyDefinitions);
44+
$derivative['type'] = $propertyDefinition->getDataType();
4245
$derivative['property'] = key($propertyDefinitions);
4346
}
4447
else {
45-
$derivative['type'] = StringHelper::camelCase('field', $entityTypeId, $fieldName);
48+
$derivative['type'] = StringHelper::camelCase('field', $entityTypeId, $supportsBundles ? $fieldBundle : '', $fieldName);
4649
}
4750

48-
if ($fieldDefinition->isMultiple()) {
51+
// Fields are usually multi-value. Simplify them for the schema if they are
52+
// configured for cardinality 1 (only works for configured fields).
53+
if (!(($storageDefinition = $fieldDefinition->getFieldStorageDefinition()) && !$storageDefinition->isMultiple())) {
4954
$derivative['type'] = StringHelper::listType($derivative['type']);
5055
}
5156

52-
return ["$entityTypeId-$fieldName" => $derivative];
53-
}
54-
55-
/**
56-
* Determines the parent types for a field.
57-
*
58-
* @param string $entityTypeId
59-
* The entity type id of the field.
60-
* @param \Drupal\Core\Field\FieldStorageDefinitionInterface $fieldDefinition
61-
* The field storage definition.
62-
*
63-
* @return array
64-
* The pareants of the field.
65-
*/
66-
protected function getParentsForField($entityTypeId, FieldStorageDefinitionInterface $fieldDefinition) {
67-
if ($fieldDefinition->isBaseField()) {
68-
return [StringHelper::camelCase($entityTypeId)];
69-
}
70-
71-
if ($fieldDefinition instanceof FieldStorageConfigInterface) {
72-
$targetType = $this->entityTypeManager->getDefinition($fieldDefinition->getTargetEntityTypeId());
73-
if ($targetType->hasKey('bundle')) {
74-
return array_values(array_map(function ($bundleId) use ($entityTypeId) {
75-
return StringHelper::camelCase($entityTypeId, $bundleId);
76-
}, $fieldDefinition->getBundles()));
77-
}
78-
else {
79-
return [StringHelper::camelCase($entityTypeId)];
80-
}
81-
}
82-
83-
return [];
57+
return ["$entityTypeId-$fieldName-$fieldBundle" => $derivative];
8458
}
8559
}

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

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,8 @@
22

33
namespace Drupal\graphql_core\Plugin\Deriver\Fields;
44

5-
use Drupal\Core\Field\FieldStorageDefinitionInterface;
5+
use Drupal\Core\Field\FieldDefinitionInterface;
6+
use Drupal\Core\TypedData\ComplexDataDefinitionInterface;
67
use Drupal\Core\TypedData\DataDefinitionInterface;
78
use Drupal\Core\TypedData\DataReferenceDefinitionInterface;
89
use Drupal\graphql\Utility\StringHelper;
@@ -13,26 +14,36 @@ class EntityFieldItemDeriver extends EntityFieldDeriverBase {
1314
/**
1415
* {@inheritdoc}
1516
*/
16-
protected function getDerivativeDefinitionsFromFieldDefinition($entityTypeId, FieldStorageDefinitionInterface $fieldDefinition, array $basePluginDefinition, $bundleId = NULL) {
17-
if (!$propertyDefinitions = $fieldDefinition->getPropertyDefinitions()) {
17+
protected function getDerivativeDefinitionsFromFieldDefinition(FieldDefinitionInterface $fieldDefinition, array $basePluginDefinition) {
18+
$itemDefinition = $fieldDefinition->getItemDefinition();
19+
if (!($itemDefinition instanceof ComplexDataDefinitionInterface) || !$propertyDefinitions = $itemDefinition->getPropertyDefinitions()) {
20+
return [];
21+
}
22+
23+
if (count($propertyDefinitions) <= 1) {
1824
return [];
1925
}
2026

2127
$tags = array_merge($fieldDefinition->getCacheTags(), ['entity_field_info']);
2228
$contexts = $fieldDefinition->getCacheContexts();
2329
$maxAge = $fieldDefinition->getCacheMaxAge();
2430

31+
$entityTypeId = $fieldDefinition->getTargetEntityTypeId();
32+
$entityType = $this->entityTypeManager->getDefinition($entityTypeId);
33+
$supportsBundles = $entityType->hasKey('bundle');
2534
$fieldName = $fieldDefinition->getName();
35+
$fieldBundle = $fieldDefinition->getTargetBundle() ?: '';
36+
2637
$commonDefinition = [
27-
'parents' => [StringHelper::camelCase('field', $entityTypeId, $fieldName)],
38+
'parents' => [StringHelper::camelCase('field', $entityTypeId, $supportsBundles ? $fieldBundle : '', $fieldName)],
2839
'schema_cache_tags' => $tags,
2940
'schema_cache_contexts' => $contexts,
3041
'schema_cache_max_age' => $maxAge,
3142
] + $basePluginDefinition;
3243

3344
$derivatives = [];
3445
foreach ($propertyDefinitions as $property => $propertyDefinition) {
35-
$derivatives["$entityTypeId-$fieldName-$property"] = [
46+
$derivatives["$entityTypeId-$fieldName-$fieldBundle-$property"] = [
3647
'name' => StringHelper::propCase($property),
3748
'description' => $propertyDefinition->getDescription(),
3849
'property' => $property,

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

Lines changed: 17 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -2,84 +2,30 @@
22

33
namespace Drupal\graphql_core\Plugin\Deriver\Fields;
44

5-
use Drupal\Component\Plugin\Derivative\DeriverBase;
6-
use Drupal\Core\Entity\EntityFieldManagerInterface;
7-
use Drupal\Core\Entity\EntityTypeManagerInterface;
8-
use Drupal\Core\Entity\FieldableEntityInterface;
9-
use Drupal\Core\Plugin\Discovery\ContainerDeriverInterface;
5+
use Drupal\Core\Field\FieldDefinitionInterface;
106
use Drupal\graphql\Utility\StringHelper;
11-
use Symfony\Component\DependencyInjection\ContainerInterface;
7+
use Drupal\graphql_core\Plugin\Deriver\EntityFieldDeriverBase;
128

13-
class EntityFieldPropertyDeriver extends DeriverBase implements ContainerDeriverInterface {
14-
15-
/**
16-
* The entity type manager.
17-
*
18-
* @var \Drupal\Core\Entity\EntityTypeManagerInterface
19-
*/
20-
protected $entityTypeManager;
21-
22-
/**
23-
* The entity field manager.
24-
*
25-
* @var \Drupal\Core\Entity\EntityFieldManagerInterface
26-
*/
27-
protected $entityFieldManager;
9+
class EntityFieldPropertyDeriver extends EntityFieldDeriverBase {
2810

2911
/**
3012
* {@inheritdoc}
3113
*/
32-
public static function create(ContainerInterface $container, $basePluginId) {
33-
return new static(
34-
$container->get('entity_type.manager'),
35-
$container->get('entity_field.manager')
36-
);
37-
}
38-
39-
/**
40-
* RawValueFieldItemDeriver constructor.
41-
*
42-
* @param \Drupal\Core\Entity\EntityTypeManagerInterface $entityTypeManager
43-
* The entity type manager.
44-
* @param \Drupal\Core\Entity\EntityFieldManagerInterface $entityFieldManager
45-
* The entity field manager.
46-
*/
47-
public function __construct(
48-
EntityTypeManagerInterface $entityTypeManager,
49-
EntityFieldManagerInterface $entityFieldManager
50-
) {
51-
$this->entityTypeManager = $entityTypeManager;
52-
$this->entityFieldManager = $entityFieldManager;
53-
}
54-
55-
/**
56-
* {@inheritdoc}
57-
*/
58-
public function getDerivativeDefinitions($basePluginDefinition) {
59-
$parents = [];
60-
foreach ($this->entityTypeManager->getDefinitions() as $entityTypeId => $entityType) {
61-
$interfaces = class_implements($entityType->getClass());
62-
if (!array_key_exists(FieldableEntityInterface::class, $interfaces)) {
63-
continue;
64-
}
65-
66-
$fieldDefinitions = $this->entityFieldManager->getFieldStorageDefinitions($entityTypeId);
67-
foreach ($fieldDefinitions as $fieldDefinition) {
68-
$fieldName = $fieldDefinition->getName();
69-
$fieldType = $fieldDefinition->getType();
70-
71-
if (isset($basePluginDefinition['field_types']) && in_array($fieldType, $basePluginDefinition['field_types'])) {
72-
$parents[] = StringHelper::camelCase('field', $entityTypeId, $fieldName);
73-
}
74-
}
75-
}
76-
77-
if (!empty($parents)) {
78-
$this->derivatives[$basePluginDefinition['id']] = [
79-
'parents' => array_merge($parents, $basePluginDefinition['parents']),
80-
] + $basePluginDefinition;
14+
protected function getDerivativeDefinitionsFromFieldDefinition(FieldDefinitionInterface $fieldDefinition, array $basePluginDefinition) {
15+
$fieldType = $fieldDefinition->getType();
16+
17+
if (isset($basePluginDefinition['field_types']) && in_array($fieldType, $basePluginDefinition['field_types'])) {
18+
$fieldName = $fieldDefinition->getName();
19+
$fieldBundle = $fieldDefinition->getTargetBundle() ?: '';
20+
$entityTypeId = $fieldDefinition->getTargetEntityTypeId();
21+
$entityType = $this->entityTypeManager->getDefinition($entityTypeId);
22+
$supportsBundles = $entityType->hasKey('bundle');
23+
24+
return ["$entityTypeId-$fieldBundle-$fieldName" => [
25+
'parents' => [StringHelper::camelCase('field', $entityTypeId, $supportsBundles ? $fieldBundle : '', $fieldName)],
26+
] + $basePluginDefinition];
8127
}
8228

83-
return $this->derivatives;
29+
return [];
8430
}
8531
}

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ public function getDerivativeDefinitions($basePluginDefinition) {
4646
$derivative['response_cache_contexts'][] = 'user.node_grants:view';
4747
}
4848

49-
$this->derivatives[$typeId . '-' . $bundle] = $derivative;
49+
$this->derivatives["$typeId-$bundle"] = $derivative;
5050
}
5151
}
5252

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

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,8 @@
22

33
namespace Drupal\graphql_core\Plugin\Deriver\Types;
44

5-
use Drupal\Core\Field\FieldStorageDefinitionInterface;
5+
use Drupal\Core\Field\FieldDefinitionInterface;
6+
use Drupal\Core\TypedData\ComplexDataDefinitionInterface;
67
use Drupal\graphql\Utility\StringHelper;
78
use Drupal\graphql_core\Plugin\Deriver\EntityFieldDeriverBase;
89

@@ -14,18 +15,28 @@ class EntityFieldTypeDeriver extends EntityFieldDeriverBase {
1415
/**
1516
* {@inheritdoc}
1617
*/
17-
protected function getDerivativeDefinitionsFromFieldDefinition($entityTypeId, FieldStorageDefinitionInterface $fieldDefinition, array $basePluginDefinition) {
18-
// Only create a type for fields with at least two properties.
19-
$propertyDefinitions = $fieldDefinition->getPropertyDefinitions();
18+
protected function getDerivativeDefinitionsFromFieldDefinition(FieldDefinitionInterface $fieldDefinition, array $basePluginDefinition) {
19+
$itemDefinition = $fieldDefinition->getItemDefinition();
20+
if (!($itemDefinition instanceof ComplexDataDefinitionInterface) || !$propertyDefinitions = $itemDefinition->getPropertyDefinitions()) {
21+
return [];
22+
}
23+
24+
$propertyDefinitions = $itemDefinition->getPropertyDefinitions();
2025
if (count($propertyDefinitions) <= 1) {
2126
return [];
2227
}
2328

29+
$entityTypeId = $fieldDefinition->getTargetEntityTypeId();
30+
$entityType = $this->entityTypeManager->getDefinition($entityTypeId);
31+
$supportsBundles = $entityType->hasKey('bundle');
2432
$fieldName = $fieldDefinition->getName();
25-
return ["$entityTypeId-$fieldName" => [
26-
'name' => StringHelper::camelCase('field', $entityTypeId, $fieldName),
33+
$fieldBundle = $fieldDefinition->getTargetBundle() ?: '';
34+
35+
return ["$entityTypeId-$fieldName-$fieldBundle" => [
36+
'name' => StringHelper::camelCase('field', $entityTypeId, $supportsBundles ? $fieldBundle : '', $fieldName),
2737
'description' => $fieldDefinition->getDescription(),
2838
'entity_type' => $entityTypeId,
39+
'entity_bundle' => $fieldBundle ?: NULL,
2940
'field_name' => $fieldName,
3041
] + $basePluginDefinition];
3142
}

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

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -35,11 +35,6 @@ public function getDerivativeDefinitions($basePluginDefinition) {
3535
'entity_type' => $typeId,
3636
] + $basePluginDefinition;
3737

38-
if ($typeId === 'node') {
39-
// TODO: Make this more generic somehow.
40-
$derivative['response_cache_contexts'][] = 'user.node_grants:view';
41-
}
42-
4338
$this->derivatives[$typeId] = $derivative;
4439
}
4540

0 commit comments

Comments
 (0)