Completed
Push — 8.x-3.x ( 451e57...160a7b )
by Sebastian
02:00
created

PluggableSchemaBuilder::find()   C

Complexity

Conditions 12
Paths 4

Size

Total Lines 40
Code Lines 22

Duplication

Lines 7
Ratio 17.5 %

Importance

Changes 0
Metric Value
cc 12
eloc 22
nc 4
nop 3
dl 7
loc 40
rs 5.1612
c 0
b 0
f 0

How to fix   Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

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
   * PluggableSchemaBuilderInterface constructor.
29
   *
30
   * @param \Drupal\graphql\Plugin\GraphQL\TypeSystemPluginManagerAggregator $pluginManagers
31
   *   Type system plugin manager aggregator service.
32
   */
33
  public function __construct(TypeSystemPluginManagerAggregator $pluginManagers) {
34
    $this->pluginManagers = $pluginManagers;
35
  }
36
37
  /**
38
   * {@inheritdoc}
39
   */
40
  public function getInstance($pluginType, $pluginId, array $pluginConfiguration = []) {
41
    asort($pluginConfiguration);
42
    $configCid = md5(json_encode($pluginConfiguration));
43
44
    if (!isset($this->instances[$pluginType][$pluginId][$configCid])) {
45
      $manager = $this->pluginManagers->getPluginManager($pluginType);
46
      if (empty($manager)) {
47
        throw new \LogicException(sprintf('Could not find %s plugin manager for plugin %s.', $pluginType, $pluginId));
48
      }
49
50
      // We do not allow plugin configuration for now.
51
      $instance = $manager->createInstance($pluginId, $pluginConfiguration);
52
      if (empty($instance)) {
53
        throw new \LogicException(sprintf('Could not instantiate plugin %s of type %s.', $pluginId, $pluginType));
54
      }
55
56
      if (!$instance instanceof TypeSystemPluginInterface) {
57
        throw new \LogicException(sprintf('Plugin %s of type %s does not implement \Drupal\graphql\Plugin\GraphQL\TypeSystemPluginInterface.', $pluginId, $pluginType));
58
      }
59
60
      // Initialize the static cache array if necessary.
61
      $this->instances[$pluginType] = isset($this->instances[$pluginType]) ? $this->instances[$pluginType] : [];
62
      $this->instances[$pluginType][$pluginId] = isset($this->instances[$pluginType][$pluginId]) ? $this->instances[$pluginType][$pluginId] : [];
63
      $this->instances[$pluginType][$pluginId][$configCid] = $instance;
64
    }
65
66
    return $this->instances[$pluginType][$pluginId][$configCid];
67
  }
68
69
  /**
70
   * {@inheritdoc}
71
   */
72
  public function find(callable $selector, array $types, $invert = FALSE) {
73
    $items = [];
74
75
    /** @var \Drupal\graphql\Plugin\GraphQL\TypeSystemPluginManagerInterface $manager */
76
    foreach ($this->pluginManagers as $type => $manager) {
77
      if (!in_array($type, $types)) {
78
        continue;
79
      }
80
81
      foreach ($manager->getDefinitions() as $id => $definition) {
82
        $name = $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, $items) || $items[$name]['weight'] < $definition['weight']) {
88
          if ((($invert && !$selector($definition)) || $selector($definition))) {
89
            $items[$name] = [
90
              'weight' => $definition['weight'],
91
              'id' => $id,
92
              'type' => $type,
93
            ];
94
          }
95
        }
96
      }
97
    }
98
99
    // Sort the plugins so that the ones with higher weight come first.
100 View Code Duplication
    usort($items, function (array $a, array $b) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across 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...
101
      if ($a['weight'] === $b['weight']) {
102
        return 0;
103
      }
104
105
      return ($a['weight'] < $b['weight']) ? 1 : -1;
106
    });
107
108
    return array_map(function (array $item) {
109
      return $this->getInstance($item['type'], $item['id']);
110
    }, $items);
111
  }
112
113
  /**
114
   * {@inheritdoc}
115
   */
116
  public function findByName($name, array $types) {
117
    $result = $this->find(function($definition) use ($name) {
118
      return $definition['name'] === $name;
119
    }, $types);
120
121
    if (empty($result)) {
122
      throw new InvalidPluginDefinitionException(sprintf('GraphQL plugin with name %s could not be found.', $name));
123
    }
124
125
    return array_pop($result);
126
  }
127
128
  /**
129
   * {@inheritdoc}
130
   */
131
  public function findByDataType($dataType, array $types = [
132
    GRAPHQL_UNION_TYPE_PLUGIN,
133
    GRAPHQL_TYPE_PLUGIN,
134
    GRAPHQL_INTERFACE_PLUGIN,
135
    GRAPHQL_SCALAR_PLUGIN,
136
  ]) {
137
    $chain = explode(':', $dataType);
138
139
    while ($chain) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $chain of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

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.

Loading history...
140
      $dataType = implode(':', $chain);
141
142
      $types = $this->find(function($definition) use ($dataType) {
143
        return isset($definition['data_type']) && $definition['data_type'] == $dataType;
144
      }, $types);
145
146
      if (!empty($types)) {
147
        return array_pop($types);
148
      }
149
150
      array_pop($chain);
151
    }
152
153
    return NULL;
154
  }
155
156
  /**
157
   * {@inheritdoc}
158
   */
159
  public function __sleep() {
160
    // Don't write the plugin instances into the cache.
161
    return array_diff($this->sleepDependencies(), ['instances']);
162
  }
163
}
164