Completed
Pull Request — 8.x-3.x (#490)
by Sebastian
07:32 queued 04:49
created

PluggableSchemaBuilder::find()   C

Complexity

Conditions 11
Paths 3

Size

Total Lines 42
Code Lines 23

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 11
eloc 23
nc 3
nop 2
dl 0
loc 42
rs 5.2653
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
   * PluggableSchemaBuilder 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
    $cid = $this->getCacheIdentifier($pluginType, $pluginId, $pluginConfiguration);
42
    if (!isset($this->instances[$cid])) {
43
      $manager = $this->pluginManagers->getPluginManager($pluginType);
44
      if (empty($manager)) {
45
        throw new \LogicException(sprintf('Could not find %s plugin manager for plugin %s.', $pluginType, $pluginId));
46
      }
47
48
      // We do not allow plugin configuration for now.
49
      $instance = $manager->createInstance($pluginId, $pluginConfiguration);
50
      if (empty($instance)) {
51
        throw new \LogicException(sprintf('Failed to instantiate plugin %s of type %s.', $pluginId, $pluginType));
52
      }
53
54
      $this->instances[$cid] = $instance;
55
    }
56
57
    return $this->instances[$cid];
58
  }
59
60
  /**
61
   * {@inheritdoc}
62
   */
63
  public function find(callable $selector, array $types) {
64
    $items = [];
65
66
    /** @var \Drupal\graphql\Plugin\GraphQL\TypeSystemPluginManagerInterface $manager */
67
    foreach ($this->pluginManagers as $type => $manager) {
68
      if (!in_array($type, $types)) {
69
        continue;
70
      }
71
72
      foreach ($manager->getDefinitions() as $id => $definition) {
73
        $name = $definition['name'];
74
75
        if (!array_key_exists($name, $items) || $items[$name]['weight'] < $definition['weight']) {
76
          if (($priority = $selector($definition)) !== NULL) {
77
            $items[$name] = [
78
              'weight' => $definition['weight'],
79
              'id' => $id,
80
              'type' => $type,
81
              'priority' => (int) $priority,
82
            ];
83
          }
84
        }
85
      }
86
    }
87
88
    // Sort the plugins so that the ones with higher weight come first.
89
    usort($items, function (array $a, array $b) {
90
      if ($a['priority'] === $b['priority']) {
91
        if ($a['weight'] === $b['weight']) {
92
          return 0;
93
        }
94
95
        return ($a['weight'] < $b['weight']) ? 1 : -1;
96
      }
97
98
      return ($a['priority'] < $b['priority']) ? 1 : -1;
99
    });
100
101
    return array_map(function (array $item) {
102
      return $this->getInstance($item['type'], $item['id']);
103
    }, $items);
104
  }
105
106
  /**
107
   * {@inheritdoc}
108
   */
109
  public function findByName($name, array $types) {
110
    $parts = explode(':', $name);
111
    $chain = array_reverse(array_reduce($parts, function ($carry, $current) {
112
      return $carry + [implode(':', array_filter([end($carry), $current]))];
113
    }, []), TRUE);
114
115
    $result = $this->find(function($definition) use ($name, $chain) {
116
      if (!empty($definition['type'])) {
117
        foreach ($chain as $priority => $part) {
118
          if ($definition['type'] === $part) {
119
            return $priority + 1;
120
          }
121
        }
122
      }
123
124
      if ($definition['name'] === $name) {
125
        return 0;
126
      }
127
128
      return NULL;
129
    }, $types);
130
131
    if (empty($result)) {
132
      return $this->getInstance('scalar', 'undefined');
133
    }
134
135
    return array_pop($result);
136
  }
137
138
  /**
139
   * Creates a plugin instance cache identifier.
140
   *
141
   * @param string $pluginType
142
   *   The plugin type.
143
   * @param string $pluginId
144
   *   The plugin id.
145
   * @param array $pluginConfiguration
146
   *   The plugin configuration.
147
   *
148
   * @return string
149
   */
150
  protected function getCacheIdentifier($pluginType, $pluginId, array $pluginConfiguration) {
151
    if (empty($pluginConfiguration)) {
152
      return "$pluginType:::$pluginId";
153
    }
154
155
    $configCid = md5(serialize($this->sortRecursive($pluginConfiguration)));
156
    return "$pluginType:::$pluginId:::$configCid";
157
  }
158
159
  /**
160
   * Recursively sorts an array.
161
   *
162
   * Useful for generating a cache identifiers.
163
   *
164
   * @param array $subject
165
   *   The array to sort.
166
   *
167
   * @return array
168
   *   The sorted array.
169
   */
170
  protected function sortRecursive(array $subject) {
171
    asort($subject);
172
    foreach ($subject as $key => $item) {
173
      if (is_array($item)) {
174
        $subject[$key] = $this->sortRecursive($item);
175
      }
176
    }
177
178
    return $subject;
179
  }
180
181
  /**
182
   * {@inheritdoc}
183
   */
184
  public function __sleep() {
185
    // Don't write the plugin instances into the cache.
186
    return array_diff($this->sleepDependencies(), ['instances']);
187
  }
188
189
}
190