Skip to content

Commit 0a24da8

Browse files
blazeyofubhy
authored andcommitted
Reduced single-property fields to scalars. (#385)
1 parent 44d7d6d commit 0a24da8

9 files changed

Lines changed: 204 additions & 179 deletions

File tree

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
<?php
2+
3+
namespace Drupal\graphql_core\Plugin\Deriver;
4+
5+
use Drupal\Core\Entity\EntityFieldManagerInterface;
6+
use Drupal\Core\Entity\EntityTypeBundleInfoInterface;
7+
use Drupal\Core\Entity\EntityTypeManagerInterface;
8+
use Drupal\Core\Field\BaseFieldDefinition;
9+
use Drupal\Core\Field\FieldStorageDefinitionInterface;
10+
use Drupal\graphql_core\Plugin\Deriver\Fields\EntityFieldDeriverBase;
11+
use Drupal\graphql_core\TypeMapper;
12+
use Symfony\Component\DependencyInjection\ContainerInterface;
13+
14+
abstract class EntityFieldDeriverWithTypeMapping extends EntityFieldDeriverBase {
15+
16+
/**
17+
* Provide plugin definition values from both base and config fields.
18+
*
19+
* @param string $entityTypeId
20+
* The host entity type.
21+
* @param \Drupal\Core\Field\FieldStorageDefinitionInterface $definition
22+
* Field definition object.
23+
* @param array $basePluginDefinition
24+
* Base plugin definition array.
25+
* @param null|string $bundleId
26+
* Bundle id.
27+
*/
28+
abstract protected function getDerivativesFromPropertyDefinitions($entityTypeId, FieldStorageDefinitionInterface $definition, array $basePluginDefinition, $bundleId = NULL);
29+
30+
/**
31+
* The type mapper service.
32+
*
33+
* @var \Drupal\graphql_core\TypeMapper
34+
*/
35+
protected $typeMapper;
36+
37+
/**
38+
* {@inheritdoc}
39+
*/
40+
public static function create(ContainerInterface $container, $basePluginId) {
41+
return new static(
42+
$container->get('entity_type.manager'),
43+
$container->get('entity_field.manager'),
44+
$container->get('entity_type.bundle.info'),
45+
$container->get('graphql_core.type_mapper'),
46+
$basePluginId
47+
);
48+
}
49+
50+
/**
51+
* EntityFieldDeriverBase constructor.
52+
*
53+
* @param \Drupal\Core\Entity\EntityTypeManagerInterface $entityTypeManager
54+
* The entity type manager.
55+
* @param \Drupal\Core\Entity\EntityFieldManagerInterface $entityFieldManager
56+
* The entity field manager.
57+
* @param \Drupal\Core\Entity\EntityTypeBundleInfoInterface $entityTypeBundleInfo
58+
* The bundle info service.
59+
* @param \Drupal\graphql_core\TypeMapper $typeMapper
60+
* The graphql type mapper service.
61+
* @param string $basePluginId
62+
* The base plugin id.
63+
*/
64+
public function __construct(
65+
EntityTypeManagerInterface $entityTypeManager,
66+
EntityFieldManagerInterface $entityFieldManager,
67+
EntityTypeBundleInfoInterface $entityTypeBundleInfo,
68+
TypeMapper $typeMapper,
69+
$basePluginId
70+
) {
71+
parent::__construct($entityTypeManager, $entityFieldManager, $entityTypeBundleInfo, $basePluginId);
72+
$this->typeMapper = $typeMapper;
73+
}
74+
75+
/**
76+
* {@inheritdoc}
77+
*/
78+
protected function getBaseFieldDefinition($entityTypeId, BaseFieldDefinition $baseFieldDefinition, array $basePluginDefinition) {
79+
$this->getDerivativesFromPropertyDefinitions($entityTypeId, $baseFieldDefinition, $basePluginDefinition);
80+
}
81+
82+
/**
83+
* {@inheritdoc}
84+
*/
85+
protected function getConfigFieldDefinition($entityTypeId, $bundleId, FieldStorageDefinitionInterface $storage, array $basePluginDefinition) {
86+
$this->getDerivativesFromPropertyDefinitions($entityTypeId, $storage, $basePluginDefinition, $bundleId);
87+
}
88+
89+
}

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
* Create GraphQL context fields based on available Drupal contexts.
1313
*/
1414
class ContextDeriver extends DeriverBase implements ContainerDeriverInterface {
15+
1516
/**
1617
* The context repository service.
1718
*

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

Lines changed: 26 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -2,49 +2,52 @@
22

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

5-
use Drupal\Core\Field\BaseFieldDefinition;
65
use Drupal\Core\Field\FieldStorageDefinitionInterface;
76
use Drupal\graphql\Utility\StringHelper;
7+
use Drupal\graphql_core\Plugin\Deriver\EntityFieldDeriverWithTypeMapping;
88
use Drupal\graphql_core\Plugin\GraphQL\Fields\Entity\EntityField;
99
use Drupal\graphql_core\Plugin\GraphQL\Types\Entity\EntityFieldType;
1010

11-
// TODO Reduce single-property fields to scalars.
11+
// TODO Write tests for entity reference graph traversal.
12+
13+
// TODO Should we expose config entities?
1214
1315
// TODO Convert timestamps to strings?
1416
1517
/**
1618
* Deriver for RawValue fields.
1719
*/
18-
class EntityFieldDeriver extends EntityFieldDeriverBase {
20+
class EntityFieldDeriver extends EntityFieldDeriverWithTypeMapping {
1921

2022
/**
2123
* {@inheritdoc}
2224
*/
23-
protected function getBaseFieldDefinition($entityTypeId, BaseFieldDefinition $baseFieldDefinition, array $basePluginDefinition) {
24-
$fieldName = $baseFieldDefinition->getName();
25+
protected function getDerivativesFromPropertyDefinitions($entityTypeId, FieldStorageDefinitionInterface $definition, array $basePluginDefinition, $bundleId = NULL) {
26+
$fieldName = $definition->getName();
2527

26-
$this->derivatives["$entityTypeId-$fieldName"] = [
28+
$derivative = [
2729
'types' => [StringHelper::camelCase([$entityTypeId])],
2830
'name' => EntityField::getId($fieldName),
29-
'multi' => $baseFieldDefinition->isMultiple(),
31+
'multi' => $definition->isMultiple(),
3032
'field' => $fieldName,
31-
'type' => EntityFieldType::getId($entityTypeId, $fieldName),
32-
] + $basePluginDefinition;
33-
}
33+
];
3434

35-
/**
36-
* {@inheritdoc}
37-
*/
38-
protected function getConfigFieldDefinition($entityTypeId, $bundleId, FieldStorageDefinitionInterface $storage, array $basePluginDefinition) {
39-
$fieldName = $storage->getName();
35+
$properties = $definition->getPropertyDefinitions();
36+
if (count($properties) === 1) {
37+
// Flatten the structure for single-property fields.
38+
/** @var \Drupal\Core\TypedData\DataDefinitionInterface $property */
39+
$property = reset($properties);
40+
$keys = array_keys($properties);
4041

41-
$this->derivatives["$entityTypeId-$bundleId-$fieldName"] = [
42-
'types' => [StringHelper::camelCase([$entityTypeId, $bundleId])],
43-
'name' => EntityField::getId($fieldName),
44-
'multi' => $storage ? $storage->getCardinality() != 1 : FALSE,
45-
'field' => $fieldName,
46-
'type' => EntityFieldType::getId($entityTypeId, $fieldName),
47-
] + $basePluginDefinition;
48-
}
42+
$derivative['type'] = $this->typeMapper->typedDataToGraphQLFieldType($property);
43+
$derivative['property'] = reset($keys);
44+
}
45+
else {
46+
$derivative['type'] = EntityFieldType::getId($entityTypeId, $fieldName);
47+
}
4948

49+
$key = is_null($bundleId) ? "$entityTypeId-$fieldName" : "$entityTypeId-$bundleId-$fieldName";
50+
51+
$this->derivatives[$key] = $derivative + $basePluginDefinition;
52+
}
5053
}

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

Lines changed: 6 additions & 75 deletions
Original file line numberDiff line numberDiff line change
@@ -2,92 +2,23 @@
22

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

5-
use Drupal\Core\Entity\EntityFieldManagerInterface;
6-
use Drupal\Core\Entity\EntityTypeBundleInfoInterface;
7-
use Drupal\Core\Entity\EntityTypeManagerInterface;
8-
use Drupal\Core\Field\BaseFieldDefinition;
95
use Drupal\Core\Field\FieldStorageDefinitionInterface;
106
use Drupal\graphql\Utility\StringHelper;
11-
use Drupal\graphql_core\TypeMapper;
7+
use Drupal\graphql_core\Plugin\Deriver\EntityFieldDeriverWithTypeMapping;
128
use Drupal\graphql_core\Plugin\GraphQL\Types\Entity\EntityFieldType;
13-
use Symfony\Component\DependencyInjection\ContainerInterface;
149

15-
class EntityFieldItemDeriver extends EntityFieldDeriverBase {
16-
17-
/**
18-
* The type mapper service.
19-
*
20-
* @var \Drupal\graphql_core\TypeMapper
21-
*/
22-
protected $typeMapper;
23-
24-
/**
25-
* {@inheritdoc}
26-
*/
27-
public static function create(ContainerInterface $container, $basePluginId) {
28-
return new static(
29-
$container->get('entity_type.manager'),
30-
$container->get('entity_field.manager'),
31-
$container->get('entity_type.bundle.info'),
32-
$container->get('graphql_core.type_mapper'),
33-
$basePluginId
34-
);
35-
}
36-
37-
/**
38-
* RawValueFieldItemDeriver constructor.
39-
*
40-
* @param \Drupal\Core\Entity\EntityTypeManagerInterface $entityTypeManager
41-
* The entity type manager.
42-
* @param \Drupal\Core\Entity\EntityFieldManagerInterface $entityFieldManager
43-
* The entity field manager.
44-
* @param \Drupal\Core\Entity\EntityTypeBundleInfoInterface $entityTypeBundleInfo
45-
* The bundle info service.
46-
* @param \Drupal\graphql_core\TypeMapper $typeMapper
47-
* The graphql type mapper service.
48-
* @param string $basePluginId
49-
* The base plugin id.
50-
*/
51-
public function __construct(
52-
EntityTypeManagerInterface $entityTypeManager,
53-
EntityFieldManagerInterface $entityFieldManager,
54-
EntityTypeBundleInfoInterface $entityTypeBundleInfo,
55-
TypeMapper $typeMapper,
56-
$basePluginId
57-
) {
58-
parent::__construct($entityTypeManager, $entityFieldManager, $entityTypeBundleInfo, $basePluginId);
59-
$this->typeMapper = $typeMapper;
60-
}
61-
62-
/**
63-
* {@inheritdoc}
64-
*/
65-
protected function getBaseFieldDefinition($entityTypeId, BaseFieldDefinition $baseFieldDefinition, array $basePluginDefinition) {
66-
$this->getDerivativesFromPropertyDefinitions($entityTypeId, $baseFieldDefinition, $basePluginDefinition);
67-
}
10+
class EntityFieldItemDeriver extends EntityFieldDeriverWithTypeMapping {
6811

6912
/**
7013
* {@inheritdoc}
7114
*/
72-
protected function getConfigFieldDefinition($entityTypeId, $bundleId, FieldStorageDefinitionInterface $storage, array $basePluginDefinition) {
73-
$this->getDerivativesFromPropertyDefinitions($entityTypeId, $storage, $basePluginDefinition);
74-
}
75-
76-
/**
77-
* Provide plugin definition values from base fields.
78-
*
79-
* @param string $entityTypeId
80-
* The host entity type.
81-
* @param \Drupal\Core\Field\FieldStorageDefinitionInterface $definition
82-
* Field definition object.
83-
* @param array $basePluginDefinition
84-
* Base plugin definition array.
85-
*/
86-
protected function getDerivativesFromPropertyDefinitions($entityTypeId, FieldStorageDefinitionInterface $definition, array $basePluginDefinition) {
15+
protected function getDerivativesFromPropertyDefinitions($entityTypeId, FieldStorageDefinitionInterface $definition, array $basePluginDefinition, $bundleId = NULL) {
8716
$fieldName = $definition->getName();
8817
$dataType = EntityFieldType::getId($entityTypeId, $fieldName);
8918

90-
foreach ($definition->getPropertyDefinitions() as $property => $definition) {
19+
$definitions = $definition->getPropertyDefinitions();
20+
21+
foreach ($definitions as $property => $definition) {
9122
if ($definition->getDataType() == 'map') {
9223
// TODO Is it possible to get the keys of a map (eg. the options array for link field) here?
9324
continue;

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

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,10 @@
33
namespace Drupal\graphql_core\Plugin\GraphQL\Fields\Entity;
44

55
use Drupal\Core\Entity\FieldableEntityInterface;
6+
use Drupal\Core\Field\Plugin\DataType\FieldItem;
67
use Drupal\graphql\Plugin\GraphQL\Fields\FieldPluginBase;
78
use Drupal\graphql\Utility\StringHelper;
9+
use Drupal\graphql_core\Plugin\GraphQL\Fields\EntityFieldBase;
810
use Youshido\GraphQL\Execution\ResolveInfo;
911

1012
/**
@@ -18,7 +20,7 @@
1820
* deriver = "Drupal\graphql_core\Plugin\Deriver\Fields\EntityFieldDeriver",
1921
* )
2022
*/
21-
class EntityField extends FieldPluginBase {
23+
class EntityField extends EntityFieldBase {
2224

2325
/**
2426
* Returns a string if for the plugin.
@@ -39,8 +41,15 @@ public function resolveValues($value, array $args, ResolveInfo $info) {
3941
if ($value instanceof FieldableEntityInterface) {
4042
$fieldName = $this->getPluginDefinition()['field'];
4143
if ($value->hasField($fieldName)) {
44+
/** @var \Drupal\Core\Field\FieldItemBase $item */
4245
foreach ($value->get($fieldName) as $item) {
43-
yield $item;
46+
$properties = $item->getProperties(TRUE);
47+
if (count($properties) === 1) {
48+
yield $this->resolveItem($item);
49+
}
50+
else {
51+
yield $item;
52+
}
4453
}
4554
}
4655
}

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

Lines changed: 3 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
use Drupal\Core\Field\FieldItemBase;
66
use Drupal\graphql\Plugin\GraphQL\Fields\FieldPluginBase;
7+
use Drupal\graphql_core\Plugin\GraphQL\Fields\EntityFieldBase;
78
use Youshido\GraphQL\Execution\ResolveInfo;
89

910
/**
@@ -17,27 +18,13 @@
1718
* deriver = "Drupal\graphql_core\Plugin\Deriver\Fields\EntityFieldItemDeriver",
1819
* )
1920
*/
20-
class EntityFieldItem extends FieldPluginBase {
21+
class EntityFieldItem extends EntityFieldBase {
2122

2223
/**
2324
* {@inheritdoc}
2425
*/
2526
protected function resolveValues($value, array $args, ResolveInfo $info) {
26-
if ($value instanceof FieldItemBase) {
27-
$definition = $this->getPluginDefinition();
28-
$property = $definition['property'];
29-
$type = $definition['type'];
30-
$result = $value->$property;
31-
32-
if ($type == 'Int') {
33-
$result = (int) $result;
34-
}
35-
elseif ($type == 'Float') {
36-
$result = (float) $result;
37-
}
38-
39-
yield $result;
40-
}
27+
yield $this->resolveItem($value);
4128
}
4229

4330
}
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
<?php
2+
3+
namespace Drupal\graphql_core\Plugin\GraphQL\Fields;
4+
5+
use Drupal\Core\Field\FieldItemBase;
6+
use Drupal\graphql\Plugin\GraphQL\Fields\FieldPluginBase;
7+
use Youshido\GraphQL\Execution\ResolveInfo;
8+
9+
/**
10+
* Base class for entity field plugins.
11+
*/
12+
class EntityFieldBase extends FieldPluginBase {
13+
14+
/**
15+
* {@inheritdoc}
16+
*/
17+
protected function resolveItem($item) {
18+
if ($item instanceof FieldItemBase) {
19+
$definition = $this->getPluginDefinition();
20+
$property = $definition['property'];
21+
$type = $definition['type'];
22+
$result = $item->get($property)->getValue();
23+
24+
if ($type === 'Int') {
25+
$result = (int) $result;
26+
}
27+
elseif ($type === 'Float') {
28+
$result = (float) $result;
29+
}
30+
31+
return $result;
32+
}
33+
}
34+
35+
}

0 commit comments

Comments
 (0)