1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
namespace Drupal\graphql\Plugin\GraphQL; |
4
|
|
|
|
5
|
|
|
use Drupal\Component\Plugin\Exception\InvalidPluginDefinitionException; |
6
|
|
|
use Drupal\Core\DependencyInjection\DependencySerializationTrait; |
7
|
|
|
|
8
|
|
|
class PluggableSchemaBuilder implements PluggableSchemaBuilderInterface { |
9
|
|
|
use DependencySerializationTrait { |
10
|
|
|
__sleep as sleepDependencies; |
11
|
|
|
} |
12
|
|
|
|
13
|
|
|
/** |
14
|
|
|
* The type system plugin manager aggregator service. |
15
|
|
|
* |
16
|
|
|
* @var \Drupal\graphql\Plugin\GraphQL\TypeSystemPluginManagerAggregator |
17
|
|
|
*/ |
18
|
|
|
protected $pluginManagers; |
19
|
|
|
|
20
|
|
|
/** |
21
|
|
|
* Static cache of type system plugin instances. |
22
|
|
|
* |
23
|
|
|
* @var \Drupal\graphql\Plugin\GraphQL\TypeSystemPluginInterface |
24
|
|
|
*/ |
25
|
|
|
protected $instances = []; |
26
|
|
|
|
27
|
|
|
/** |
28
|
|
|
* Static cache of plugin definitions. |
29
|
|
|
* |
30
|
|
|
* @var array |
31
|
|
|
*/ |
32
|
|
|
protected $definitions; |
33
|
|
|
|
34
|
|
|
/** |
35
|
|
|
* PluggableSchemaBuilderInterface constructor. |
36
|
|
|
* |
37
|
|
|
* @param \Drupal\graphql\Plugin\GraphQL\TypeSystemPluginManagerAggregator $pluginManagers |
38
|
|
|
* Type system plugin manager aggregator service. |
39
|
|
|
*/ |
40
|
|
|
public function __construct(TypeSystemPluginManagerAggregator $pluginManagers) { |
41
|
|
|
$this->pluginManagers = $pluginManagers; |
42
|
|
|
} |
43
|
|
|
|
44
|
|
|
/** |
45
|
|
|
* {@inheritdoc} |
46
|
|
|
*/ |
47
|
|
|
public function getInstance($pluginType, $pluginId, array $pluginConfiguration = []) { |
48
|
|
|
asort($pluginConfiguration); |
49
|
|
|
$configCid = md5(json_encode($pluginConfiguration)); |
50
|
|
|
|
51
|
|
|
if (!isset($this->instances[$pluginType][$pluginId][$configCid])) { |
52
|
|
|
$manager = $this->pluginManagers->getPluginManager($pluginType); |
53
|
|
|
if (empty($manager)) { |
54
|
|
|
throw new \LogicException(sprintf('Could not find %s plugin manager for plugin %s.', $pluginType, $pluginId)); |
55
|
|
|
} |
56
|
|
|
|
57
|
|
|
// We do not allow plugin configuration for now. |
58
|
|
|
$instance = $manager->createInstance($pluginId, $pluginConfiguration); |
59
|
|
|
if (empty($instance)) { |
60
|
|
|
throw new \LogicException(sprintf('Could not instantiate plugin %s of type %s.', $pluginId, $pluginType)); |
61
|
|
|
} |
62
|
|
|
|
63
|
|
|
if (!$instance instanceof TypeSystemPluginInterface) { |
64
|
|
|
throw new \LogicException(sprintf('Plugin %s of type %s does not implement \Drupal\graphql\Plugin\GraphQL\TypeSystemPluginInterface.', $pluginId, $pluginType)); |
65
|
|
|
} |
66
|
|
|
|
67
|
|
|
// Initialize the static cache array if necessary. |
68
|
|
|
$this->instances[$pluginType] = isset($this->instances[$pluginType]) ? $this->instances[$pluginType] : []; |
69
|
|
|
$this->instances[$pluginType][$pluginId] = isset($this->instances[$pluginType][$pluginId]) ? $this->instances[$pluginType][$pluginId] : []; |
70
|
|
|
$this->instances[$pluginType][$pluginId][$configCid] = $instance; |
71
|
|
|
} |
72
|
|
|
|
73
|
|
|
return $this->instances[$pluginType][$pluginId][$configCid]; |
74
|
|
|
} |
75
|
|
|
|
76
|
|
|
/** |
77
|
|
|
* {@inheritdoc} |
78
|
|
|
*/ |
79
|
|
|
public function find(callable $selector, array $types, $invert = FALSE) { |
80
|
|
|
$instances = []; |
81
|
|
|
foreach ($this->getDefinitions() as $index => $definition) { |
82
|
|
|
$name = $definition['definition']['name']; |
83
|
|
|
if (empty($name)) { |
84
|
|
|
throw new InvalidPluginDefinitionException('Invalid GraphQL plugin definition. No name defined.'); |
85
|
|
|
} |
86
|
|
|
|
87
|
|
|
if (!array_key_exists($name, $instances) && in_array($definition['definition']['pluginType'], $types)) { |
88
|
|
|
if ((($invert && !$selector($definition['definition'])) || $selector($definition['definition']))) { |
89
|
|
|
$instances[$name] = $this->getInstance($definition['type'], $definition['id']); |
90
|
|
|
} |
91
|
|
|
} |
92
|
|
|
} |
93
|
|
|
|
94
|
|
|
return $instances; |
95
|
|
|
} |
96
|
|
|
|
97
|
|
|
/** |
98
|
|
|
* {@inheritdoc} |
99
|
|
|
*/ |
100
|
|
|
public function findByName($name, array $types) { |
101
|
|
|
$result = $this->find(function($definition) use ($name) { |
102
|
|
|
return $definition['name'] === $name; |
103
|
|
|
}, $types); |
104
|
|
|
|
105
|
|
|
if (empty($result)) { |
106
|
|
|
throw new InvalidPluginDefinitionException(sprintf('GraphQL plugin with name %s could not be found.', $name)); |
107
|
|
|
} |
108
|
|
|
|
109
|
|
|
return array_pop($result); |
110
|
|
|
} |
111
|
|
|
|
112
|
|
|
/** |
113
|
|
|
* {@inheritdoc} |
114
|
|
|
*/ |
115
|
|
|
public function findByDataType($dataType, array $types = [ |
116
|
|
|
GRAPHQL_UNION_TYPE_PLUGIN, |
117
|
|
|
GRAPHQL_TYPE_PLUGIN, |
118
|
|
|
GRAPHQL_INTERFACE_PLUGIN, |
119
|
|
|
GRAPHQL_SCALAR_PLUGIN, |
120
|
|
|
]) { |
121
|
|
|
$chain = explode(':', $dataType); |
122
|
|
|
|
123
|
|
|
while ($chain) { |
|
|
|
|
124
|
|
|
$dataType = implode(':', $chain); |
125
|
|
|
|
126
|
|
|
$types = $this->find(function($definition) use ($dataType) { |
127
|
|
|
return isset($definition['data_type']) && $definition['data_type'] == $dataType; |
128
|
|
|
}, $types); |
129
|
|
|
|
130
|
|
|
if (!empty($types)) { |
131
|
|
|
return array_pop($types); |
132
|
|
|
} |
133
|
|
|
|
134
|
|
|
array_pop($chain); |
135
|
|
|
} |
136
|
|
|
|
137
|
|
|
return NULL; |
138
|
|
|
} |
139
|
|
|
|
140
|
|
|
/** |
141
|
|
|
* Collects and aggregates all plugin definitions. |
142
|
|
|
* |
143
|
|
|
* |
144
|
|
|
* @return array |
145
|
|
|
* The plugin definitions array. |
146
|
|
|
*/ |
147
|
|
|
protected function getDefinitions() { |
148
|
|
|
$this->definitions = []; |
149
|
|
|
|
150
|
|
|
/** @var \Drupal\graphql\Plugin\GraphQL\TypeSystemPluginManagerInterface $manager */ |
151
|
|
|
foreach ($this->pluginManagers as $manager) { |
152
|
|
|
foreach ($manager->getDefinitions() as $pluginId => $definition) { |
153
|
|
|
$this->definitions[] = [ |
154
|
|
|
'id' => $pluginId, |
155
|
|
|
'type' => $definition['pluginType'], |
156
|
|
|
'weight' => $definition['weight'], |
157
|
|
|
'definition' => $definition, |
158
|
|
|
]; |
159
|
|
|
} |
160
|
|
|
} |
161
|
|
|
|
162
|
|
|
uasort($this->definitions, '\Drupal\Component\Utility\SortArray::sortByWeightElement'); |
163
|
|
|
$this->definitions = array_reverse($this->definitions); |
164
|
|
|
|
165
|
|
|
return $this->definitions; |
166
|
|
|
} |
167
|
|
|
|
168
|
|
|
/** |
169
|
|
|
* {@inheritdoc} |
170
|
|
|
*/ |
171
|
|
|
public function __sleep() { |
172
|
|
|
// Don't write the plugin instances into the cache. |
173
|
|
|
return array_diff($this->sleepDependencies(), ['instances']); |
174
|
|
|
} |
175
|
|
|
} |
176
|
|
|
|
This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.
Consider making the comparison explicit by using
empty(..)
or! empty(...)
instead.