Completed
Push — 8.x-3.x ( 4bc053...679bcf )
by Sebastian
16:30 queued 06:25
created

SchemaPluginBase::getSubscriptions()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 2
nc 1
nop 0
dl 0
loc 3
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\Cache\CacheableDependencyInterface;
7
use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
8
use Drupal\graphql\GraphQL\Execution\ResolveContext;
9
use Drupal\graphql\Plugin\FieldPluginManager;
10
use Drupal\graphql\Plugin\MutationPluginManager;
11
use Drupal\graphql\Plugin\SubscriptionPluginManager;
12
use Drupal\graphql\Plugin\SchemaBuilderInterface;
13
use Drupal\graphql\Plugin\SchemaPluginInterface;
14
use Drupal\graphql\Plugin\TypePluginManagerAggregator;
15
use GraphQL\Type\Definition\ObjectType;
16
use GraphQL\Type\Definition\ResolveInfo;
17
use GraphQL\Type\Schema;
18
use GraphQL\Type\SchemaConfig;
19
use Symfony\Component\DependencyInjection\ContainerInterface;
20
21
abstract class SchemaPluginBase extends PluginBase implements SchemaPluginInterface, SchemaBuilderInterface, ContainerFactoryPluginInterface, CacheableDependencyInterface {
22
23
  /**
24
   * The field plugin manager.
25
   *
26
   * @var \Drupal\graphql\Plugin\FieldPluginManager
27
   */
28
  protected $fieldManager;
29
30
  /**
31
   * The mutation plugin manager.
32
   *
33
   * @var \Drupal\graphql\Plugin\MutationPluginManager
34
   */
35
  protected $mutationManager;
36
37
  /**
38
   * The subscription plugin manager.
39
   *
40
   * @var \Drupal\graphql\Plugin\SubscriptionPluginManager
41
   */
42
  protected $subscriptionManager;
43
44
  /**
45
   * The type manager aggregator service.
46
   *
47
   * @var \Drupal\graphql\Plugin\TypePluginManagerAggregator
48
   */
49
  protected $typeManagers;
50
51
  /**
52
   * Static cache of field definitions.
53
   *
54
   * @var array
55
   */
56
  protected $fields = [];
57
58
  /**
59
   * Static cache of mutation definitions.
60
   *
61
   * @var array
62
   */
63
  protected $mutations = [];
64
65
  /**
66
   * Static cache of subscription definitions.
67
   *
68
   * @var array
69
   */
70
  protected $subscriptions = [];
71
72
  /**
73
   * Static cache of type instances.
74
   *
75
   * @var array
76
   */
77
  protected $types = [];
78
79
  /**
80
   * {@inheritdoc}
81
   */
82 View Code Duplication
  public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
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...
83
    return new static(
84
      $configuration,
85
      $plugin_id,
86
      $plugin_definition,
87
      $container->get('plugin.manager.graphql.field'),
88
      $container->get('plugin.manager.graphql.mutation'),
89
      $container->get('plugin.manager.graphql.subscription'),
90
      $container->get('graphql.type_manager_aggregator')
91
    );
92
  }
93
94
  /**
95
   * SchemaPluginBase constructor.
96
   *
97
   * @param array $configuration
98
   *   The plugin configuration array.
99
   * @param string $pluginId
100
   *   The plugin id.
101
   * @param array $pluginDefinition
102
   *   The plugin definition array.
103
   * @param \Drupal\graphql\Plugin\FieldPluginManager $fieldManager
104
   *   The field plugin manager.
105
   * @param \Drupal\graphql\Plugin\MutationPluginManager $mutationManager
106
   *   The mutation plugin manager.
107
   * @param \Drupal\graphql\Plugin\SubscriptionPluginManager $subscriptionManager
108
   *   The subscription plugin manager.
109
   * @param \Drupal\graphql\Plugin\TypePluginManagerAggregator $typeManagers
110
   *   The type manager aggregator service.
111
   */
112 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...
113
    $configuration,
114
    $pluginId,
115
    $pluginDefinition,
116
    FieldPluginManager $fieldManager,
117
    MutationPluginManager $mutationManager,
118
    SubscriptionPluginManager $subscriptionManager,
119
    TypePluginManagerAggregator $typeManagers
120
  ) {
121
    parent::__construct($configuration, $pluginId, $pluginDefinition);
122
    $this->fieldManager = $fieldManager;
123
    $this->mutationManager = $mutationManager;
124
    $this->subscriptionManager = $subscriptionManager;
125
    $this->typeManagers = $typeManagers;
126
  }
127
128
  /**
129
   * {@inheritdoc}
130
   */
131
  public function getSchema() {
132
    $config = new SchemaConfig();
133
134
    if ($this->hasMutations()) {
135
      $config->setMutation(new ObjectType([
136
        'name' => 'MutationRoot',
137
        'fields' => function () {
138
          return $this->getMutations();
139
        },
140
      ]));
141
    }
142
143
    if ($this->hasSubscriptions()) {
144
      $config->setSubscription(new ObjectType([
145
        'name' => 'SubscriptionRoot',
146
        'fields' => function () {
147
          return $this->getSubscriptions();
148
        },
149
      ]));
150
    }
151
152
    $config->setQuery(new ObjectType([
153
      'name' => 'QueryRoot',
154
      'fields' => function () {
155
        return $this->getFields('Root');
156
      },
157
    ]));
158
159
    $config->setTypes(function () {
160
      return $this->getTypes();
161
    });
162
163
    $config->setTypeLoader(function ($name) {
164
      return $this->getType($name);
165
    });
166
167
    return new Schema($config);
168
  }
169
170
  /**
171
   * {@inheritdoc}
172
   */
173
  public function hasFields($type) {
174
    return isset($this->pluginDefinition['field_association_map'][$type]);
175
  }
176
177
  /**
178
   * {@inheritdoc}
179
   */
180
  public function hasMutations() {
181
    return !empty($this->pluginDefinition['mutation_map']);
182
  }
183
184
  /**
185
   * {@inheritdoc}
186
   */
187
  public function hasSubscriptions() {
188
    return !empty($this->pluginDefinition['subscription_map']);
189
  }
190
191
  /**
192
   * {@inheritdoc}
193
   */
194
  public function hasType($name) {
195
    return isset($this->pluginDefinition['type_map'][$name]);
196
  }
197
198
  /**
199
   * {@inheritdoc}
200
   */
201
  public function getFields($type) {
202
    $association = $this->pluginDefinition['field_association_map'];
203
    $fields = $this->pluginDefinition['field_map'];
204
205
    if (isset($association[$type])) {
206
      return $this->processFields(array_map(function ($id) use ($fields) {
207
        return $fields[$id];
208
      }, $association[$type]));
209
    }
210
211
    return [];
212
  }
213
214
  /**
215
   * {@inheritdoc}
216
   */
217
  public function getMutations() {
218
    return $this->processMutations($this->pluginDefinition['mutation_map']);
219
  }
220
221
  /**
222
   * {@inheritdoc}
223
   */
224
  public function getSubscriptions() {
225
    return $this->processSubscriptions($this->pluginDefinition['subscription_map']);
226
  }
227
228
  /**
229
   * {@inheritdoc}
230
   */
231
  public function getTypes() {
232
    return array_map(function ($name) {
233
      return $this->getType($name);
234
    }, array_keys($this->pluginDefinition['type_map']));
235
  }
236
237
  /**
238
   * {@inheritdoc}
239
   */
240
  public function getSubTypes($name) {
241
    $association = $this->pluginDefinition['type_association_map'];
242
    return isset($association[$name]) ? $association[$name] : [];
243
  }
244
245
  /**
246
   * {@inheritdoc}
247
   */
248
  public function resolveType($name, $value, ResolveContext $context, ResolveInfo $info) {
249
    $association = $this->pluginDefinition['type_association_map'];
250
    $types = $this->pluginDefinition['type_map'];
251
    if (!isset($association[$name])) {
252
      return NULL;
253
    }
254
255
    foreach ($association[$name] as $type) {
256
      // TODO: Try to avoid loading the type for the check. Consider to make it static!
257
      if (isset($types[$type]) && $instance = $this->buildType($types[$type])) {
258
        if ($instance->isTypeOf($value, $context, $info)) {
259
          return $instance;
260
        }
261
      }
262
    }
263
264
    return NULL;
265
  }
266
267
  /**
268
   * {@inheritdoc}
269
   */
270
  public function getType($name) {
271
    $types = $this->pluginDefinition['type_map'];
272
    $references = $this->pluginDefinition['type_reference_map'];
273
    if (isset($types[$name])) {
274
      return $this->buildType($this->pluginDefinition['type_map'][$name]);
275
    }
276
277
    do {
278
      if (isset($references[$name])) {
279
        return $this->buildType($types[$references[$name]]);
280
      }
281
    } while (($pos = strpos($name, ':')) !== FALSE && $name = substr($name, 0, $pos));
282
283
    throw new \LogicException(sprintf('Missing type %s.', $name));
284
  }
285
286
  /**
287
   * {@inheritdoc}
288
   */
289
  public function processMutations($mutations) {
290
    return array_map([$this, 'buildMutation'], $mutations);
291
  }
292
293
  /**
294
   * {@inheritdoc}
295
   */
296
  public function processSubscriptions($subscriptions) {
297
    return array_map([$this, 'buildSubscription'], $subscriptions);
298
  }
299
300
  /**
301
   * {@inheritdoc}
302
   */
303
  public function processFields($fields) {
304
    return array_map([$this, 'buildField'], $fields);
305
  }
306
307
  /**
308
   * {@inheritdoc}
309
   */
310
  public function processArguments($args) {
311
    return array_map(function ($arg) {
312
      return [
313
        'type' => $this->processType($arg['type']),
314
      ] + $arg;
315
    }, $args);
316
  }
317
318
  /**
319
   * {@inheritdoc}
320
   */
321
  public function processType($type) {
322
    list($type, $decorators) = $type;
323
324
    return array_reduce($decorators, function ($type, $decorator) {
325
      return $decorator($type);
326
    }, $this->getType($type));
327
  }
328
329
  /**
330
   * Retrieves the type instance for the given reference.
331
   *
332
   * @param array $type
333
   *   The type reference.
334
   *
335
   * @return \GraphQL\Type\Definition\Type
336
   *   The type instance.
337
   */
338
  protected function buildType($type) {
339
    if (!isset($this->types[$type['id']])) {
340
      $creator = [$type['class'], 'createInstance'];
341
      $manager = $this->typeManagers->getTypeManager($type['type']);
342
      $this->types[$type['id']] = $creator($this, $manager, $type['definition'], $type['id']);
343
    }
344
345
    return $this->types[$type['id']];
346
  }
347
348
  /**
349
   * Retrieves the field definition for a given field reference.
350
   *
351
   * @param array $field
352
   *   The type reference.
353
   *
354
   * @return array
355
   *   The field definition.
356
   */
357 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...
358
    if (!isset($this->fields[$field['id']])) {
359
      $creator = [$field['class'], 'createInstance'];
360
      $this->fields[$field['id']] = $creator($this, $this->fieldManager, $field['definition'], $field['id']);
361
    }
362
363
    return $this->fields[$field['id']];
364
  }
365
366
  /**
367
   * Retrieves the mutation definition for a given field reference.
368
   *
369
   * @param array $mutation
370
   *   The mutation reference.
371
   *
372
   * @return array
373
   *   The mutation definition.
374
   */
375 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...
376
    if (!isset($this->mutations[$mutation['id']])) {
377
      $creator = [$mutation['class'], 'createInstance'];
378
      $this->mutations[$mutation['id']] = $creator($this, $this->mutationManager, $mutation['definition'], $mutation['id']);
379
    }
380
381
    return $this->mutations[$mutation['id']];
382
  }
383
384
  /**
385
   * Retrieves the subscription definition for a given field reference.
386
   *
387
   * @param array $mutation
0 ignored issues
show
Bug introduced by
There is no parameter named $mutation. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
388
   *   The subscription reference.
389
   *
390
   * @return array
391
   *   The subscription definition.
392
   */
393 View Code Duplication
  protected function buildSubscription($subscription) {
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...
394
    if (!isset($this->subscriptions[$subscription['id']])) {
395
      $creator = [$subscription['class'], 'createInstance'];
396
      $this->subscriptions[$subscription['id']] = $creator($this, $this->subscriptionManager, $subscription['definition'], $subscription['id']);
397
    }
398
399
    return $this->subscriptions[$subscription['id']];
400
  }
401
402
  /**
403
   * {@inheritdoc}
404
   */
405
  public function getCacheContexts() {
406
    return [];
407
  }
408
409
  /**
410
   * {@inheritdoc}
411
   */
412
  public function getCacheTags() {
413
    return $this->pluginDefinition['schema_cache_tags'];
414
  }
415
416
  /**
417
   * {@inheritdoc}
418
   */
419
  public function getCacheMaxAge() {
420
    return $this->pluginDefinition['schema_cache_max_age'];
421
  }
422
}
423