Completed
Pull Request — 8.x-3.x (#525)
by Philipp
05:17
created

SchemaPluginBase::getSubTypes()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 4
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 3
nc 2
nop 1
dl 0
loc 4
rs 10
c 0
b 0
f 0
1
<?php
2
3
namespace Drupal\graphql\Plugin\GraphQL\Schemas;
4
5
use Drupal\Component\Plugin\PluginBase;
6
use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
7
use Drupal\graphql\Plugin\FieldPluginManager;
8
use Drupal\graphql\Plugin\MutationPluginManager;
9
use Drupal\graphql\Plugin\SchemaBuilderInterface;
10
use Drupal\graphql\Plugin\SchemaPluginInterface;
11
use Drupal\graphql\Plugin\TypePluginManagerAggregator;
12
use GraphQL\Type\Definition\ObjectType;
13
use GraphQL\Type\Schema;
14
use GraphQL\Type\SchemaConfig;
15
use Symfony\Component\DependencyInjection\ContainerInterface;
16
17
abstract class SchemaPluginBase extends PluginBase implements SchemaPluginInterface, SchemaBuilderInterface, ContainerFactoryPluginInterface {
18
19
  /**
20
   * @var \Drupal\graphql\Plugin\FieldPluginManager
21
   */
22
  protected $fieldManager;
23
24
  /**
25
   * @var \Drupal\graphql\Plugin\MutationPluginManager
26
   */
27
  protected $mutationManager;
28
29
  /**
30
   * @var \Drupal\graphql\Plugin\TypePluginManagerAggregator
31
   */
32
  protected $typeManagers;
33
34
  /**
35
   * @var array
36
   */
37
  protected $fields = [];
38
39
  /**
40
   * @var array
41
   */
42
  protected $mutations = [];
43
44
  /**
45
   * @var array
46
   */
47
  protected $types = [];
48
49
  /**
50
   * {@inheritdoc}
51
   */
52
  public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
53
    return new static(
54
      $configuration,
55
      $plugin_id,
56
      $plugin_definition,
57
      $container->get('plugin.manager.graphql.field'),
58
      $container->get('plugin.manager.graphql.mutation'),
59
      $container->get('graphql.type_manager_aggregator')
60
    );
61
  }
62
63
  /**
64
   * SchemaPluginBase constructor.
65
   *
66
   * @param array $configuration
67
   *   The plugin configuration array.
68
   * @param string $pluginId
69
   *   The plugin id.
70
   * @param array $pluginDefinition
71
   *   The plugin definition array.
72
   * @param \Drupal\graphql\Plugin\FieldPluginManager $fieldManager
73
   * @param \Drupal\graphql\Plugin\MutationPluginManager $mutationManager
74
   * @param \Drupal\graphql\Plugin\TypePluginManagerAggregator $typeManagers
75
   */
76 View Code Duplication
  public function __construct(
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
77
    $configuration,
78
    $pluginId,
79
    $pluginDefinition,
80
    FieldPluginManager $fieldManager,
81
    MutationPluginManager $mutationManager,
82
    TypePluginManagerAggregator $typeManagers
83
  ) {
84
    parent::__construct($configuration, $pluginId, $pluginDefinition);
85
    $this->fieldManager = $fieldManager;
86
    $this->mutationManager = $mutationManager;
87
    $this->typeManagers = $typeManagers;
88
  }
89
90
  /**
91
   * {@inheritdoc}
92
   */
93
  public function getSchema() {
94
    $config = new SchemaConfig();
95
96
    if ($this->hasMutations()) {
97
      $config->setMutation(new ObjectType([
98
        'name' => 'MutationRoot',
99
        'fields' => function () {
100
          return $this->getMutations();
101
        },
102
      ]));
103
    }
104
105
    $config->setQuery(new ObjectType([
106
      'name' => 'QueryRoot',
107
      'fields' => function () {
108
        return $this->getFields('Root');
109
      },
110
    ]));
111
112
    $config->setTypes(function () {
113
      return $this->getTypes();
114
    });
115
116
    $config->setTypeLoader(function ($name) {
117
      return $this->getType($name);
118
    });
119
120
    return new Schema($config);
121
  }
122
123
  /**
124
   * @return bool
125
   */
126
  public function hasFields($type) {
127
    return isset($this->pluginDefinition['field_association_map'][$type]);
128
  }
129
130
  /**
131
   * @return bool
132
   */
133
  public function hasMutations() {
134
    return !empty($this->pluginDefinition['mutation_map']);
135
  }
136
137
  /**
138
   * @return bool
139
   */
140
  public function hasType($name) {
141
    return isset($this->pluginDefinition['type_map'][$name]);
142
  }
143
144
  /**
145
   * @return array
146
   */
147
  public function getFields($type) {
148
    $association = $this->pluginDefinition['field_association_map'];
149
    $fields = $this->pluginDefinition['field_map'];
150
151
    if (isset($association[$type])) {
152
      return $this->processFields(array_map(function ($id) use ($fields) {
153
        return $fields[$id];
154
      }, $association[$type]));
155
    }
156
157
    return [];
158
  }
159
160
  /**
161
   * @return array
162
   */
163
  public function getMutations() {
164
    return $this->processMutations($this->pluginDefinition['mutation_map']);
165
  }
166
167
  /**
168
   * @return array
169
   */
170
  public function getTypes() {
171
    return array_map(function ($name) {
172
      return $this->getType($name);
173
    }, array_keys($this->pluginDefinition['type_map']));
174
  }
175
176
  /**
177
   * Retrieve the list of derivatives associated with a composite type.
178
   *
179
   * @return string[]
180
   *   The list of possible sub typenames.
181
   */
182
  public function getSubTypes($name) {
183
    $association = $this->pluginDefinition['type_association_map'];
184
    return isset($association[$name]) ? $association[$name] : [];
185
  }
186
187
  /**
188
   * Resolve the matching type.
189
   */
190
  public function resolveType($name, $value, $context, $info) {
191
    $association = $this->pluginDefinition['type_association_map'];
192
    $types = $this->pluginDefinition['type_map'];
193
    if (!isset($association[$name])) {
194
      return NULL;
195
    }
196
197
    foreach ($association[$name] as $type) {
198
      // TODO: Avoid loading the type for the check. Make it static!
199
      if (isset($types[$type]) && $instance = $this->buildType($types[$type])) {
200
        if ($instance->isTypeOf($value, $context, $info)) {
201
          return $instance;
202
        }
203
      }
204
    }
205
206
    return NULL;
207
  }
208
209
  /**
210
   * @param $name
211
   *
212
   * @return mixed
213
   */
214
  public function getType($name) {
215
    $types = $this->pluginDefinition['type_map'];
216
    $references = $this->pluginDefinition['type_reference_map'];
217
    if (isset($types[$name])) {
218
      return $this->buildType($this->pluginDefinition['type_map'][$name]);
219
    }
220
221
    do {
222
      if (isset($references[$name])) {
223
        return $this->buildType($types[$references[$name]]);
224
      }
225
    } while (($pos = strpos($name, ':')) !== FALSE && $name = substr($name, 0, $pos));
226
227
    throw new \LogicException(sprintf('Missing type %s.', $name));
228
  }
229
230
  /**
231
   * @param $mutations
232
   *
233
   * @return array
234
   */
235
  public function processMutations($mutations) {
236
    return array_map([$this, 'buildMutation'], $mutations);
237
  }
238
239
  /**
240
   * @param $fields
241
   *
242
   * @return array
243
   */
244
  public function processFields($fields) {
245
    return array_map([$this, 'buildField'], $fields);
246
  }
247
248
  /**
249
   * @param $args
250
   *
251
   * @return array
252
   */
253
  public function processArguments($args) {
254
    return array_map(function ($arg) {
255
      return [
256
        'type' => $this->processType($arg['type']),
257
      ] + $arg;
258
    }, $args);
259
  }
260
261
  /**
262
   * @param $type
263
   *
264
   * @return mixed
265
   */
266
  public function processType($type) {
267
    list($type, $decorators) = $type;
268
269
    return array_reduce($decorators, function ($type, $decorator) {
270
      return $decorator($type);
271
    }, $this->getType($type));
272
  }
273
274
  /**
275
   * @param $type
276
   *
277
   * @return \Drupal\graphql\Plugin\GraphQL\Types\TypePluginBase
278
   */
279
  protected function buildType($type) {
280
    if (!isset($this->types[$type['id']])) {
281
      $creator = [$type['class'], 'createInstance'];
282
      $manager = $this->typeManagers->getTypeManager($type['type']);
283
      $this->types[$type['id']] = $creator($this, $manager, $type['definition'], $type['id']);
284
    }
285
286
    return $this->types[$type['id']];
287
  }
288
289
  /**
290
   * @param $field
291
   *
292
   * @return mixed
293
   */
294 View Code Duplication
  protected function buildField($field) {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
295
    if (!isset($this->fields[$field['id']])) {
296
      $creator = [$field['class'], 'createInstance'];
297
      $this->fields[$field['id']] = $creator($this, $this->fieldManager, $field['definition'], $field['id']);
298
    }
299
300
    return $this->fields[$field['id']];
301
  }
302
303
  /**
304
   * @param $mutation
305
   *
306
   * @return mixed
307
   */
308 View Code Duplication
  protected function buildMutation($mutation) {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
309
    if (!isset($this->mutations[$mutation['id']])) {
310
      $creator = [$mutation['class'], 'createInstance'];
311
      $this->mutations[$mutation['id']] = $creator($this, $this->mutationManager, $mutation['definition'], $mutation['id']);
312
    }
313
314
    return $this->mutations[$mutation['id']];
315
  }
316
}
317