Completed
Pull Request — 8.x-3.x (#442)
by Sebastian
01:51
created

PluggableSchemaBuilder::getDefinitions()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 20
Code Lines 12

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 3
eloc 12
nc 3
nop 0
dl 0
loc 20
rs 9.4285
c 0
b 0
f 0
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 find(callable $selector, array $types, $invert = FALSE) {
48
    $instances = [];
49
    foreach ($this->getDefinitions() as $index => $definition) {
50
      $name = $definition['definition']['name'];
51
      if (empty($name)) {
52
        throw new InvalidPluginDefinitionException('Invalid GraphQL plugin definition. No name defined.');
53
      }
54
55
      if (!array_key_exists($name, $instances) && in_array($definition['definition']['pluginType'], $types)) {
56
        if ((($invert && !$selector($definition['definition'])) || $selector($definition['definition']))) {
57
          $instances[$name] = $this->getInstance($definition['type'], $definition['id']);
58
        }
59
      }
60
    }
61
62
    return $instances;
63
  }
64
65
  /**
66
   * {@inheritdoc}
67
   */
68
  public function findByName($name, array $types) {
69
    $result = $this->find(function($definition) use ($name) {
70
      return $definition['name'] === $name;
71
    }, $types);
72
73
    if (empty($result)) {
74
      throw new InvalidPluginDefinitionException(sprintf('GraphQL plugin with name %s could not be found.', $name));
75
    }
76
77
    return array_pop($result);
78
  }
79
80
  /**
81
   * {@inheritdoc}
82
   */
83
  public function findByDataType($dataType, array $types = [
84
    GRAPHQL_UNION_TYPE_PLUGIN,
85
    GRAPHQL_TYPE_PLUGIN,
86
    GRAPHQL_INTERFACE_PLUGIN,
87
    GRAPHQL_SCALAR_PLUGIN,
88
  ]) {
89
    $chain = explode(':', $dataType);
90
91
    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...
92
      $dataType = implode(':', $chain);
93
94
      $types = $this->find(function($definition) use ($dataType) {
95
        return isset($definition['data_type']) && $definition['data_type'] == $dataType;
96
      }, $types);
97
98
      if (!empty($types)) {
99
        return array_pop($types);
100
      }
101
102
      array_pop($chain);
103
    }
104
105
    return NULL;
106
  }
107
108
  /**
109
   * Collects and aggregates all plugin definitions.
110
   *
111
   *
112
   * @return array
113
   *   The plugin definitions array.
114
   */
115
  protected function getDefinitions() {
116
    $this->definitions = [];
117
118
    /** @var \Drupal\graphql\Plugin\GraphQL\TypeSystemPluginManagerInterface $manager */
119
    foreach ($this->pluginManagers as $manager) {
120
      foreach ($manager->getDefinitions() as $pluginId => $definition) {
121
        $this->definitions[] = [
122
          'id' => $pluginId,
123
          'type' => $definition['pluginType'],
124
          'weight' => $definition['weight'],
125
          'definition' => $definition,
126
        ];
127
      }
128
    }
129
130
    uasort($this->definitions, '\Drupal\Component\Utility\SortArray::sortByWeightElement');
131
    $this->definitions = array_reverse($this->definitions);
132
133
    return $this->definitions;
134
  }
135
136
  /**
137
   * Creates a type system plugin instance for a given plugin manager.
138
   *
139
   * @param $pluginType
140
   *   The plugin type.
141
   * @param $pluginId
142
   *   The plugin id.
143
   *
144
   * @return \Drupal\graphql\Plugin\GraphQL\TypeSystemPluginInterface
145
   *   The created plugin instance.
146
   */
147
  protected function getInstance($pluginType, $pluginId) {
148
    if (!isset($this->instances[$pluginType][$pluginId])) {
149
      $manager = $this->pluginManagers->getPluginManager($pluginType);
150
      if (empty($manager)) {
151
        throw new \LogicException(sprintf('Could not find %s plugin manager for plugin %s.', $pluginType, $pluginId));
152
      }
153
154
      // We do not allow plugin configuration for now.
155
      $instance = $manager->createInstance($pluginId);
156
      if (empty($instance)) {
157
        throw new \LogicException(sprintf('Could not instantiate plugin %s of type %s.', $pluginId, $pluginType));
158
      }
159
160
      if (!$instance instanceof TypeSystemPluginInterface) {
161
        throw new \LogicException(sprintf('Plugin %s of type %s does not implement \Drupal\graphql\Plugin\GraphQL\TypeSystemPluginInterface.', $pluginId, $pluginType));
162
      }
163
164
      // Initialize the static cache array if necessary.
165
      $this->instances[$pluginType] = isset($this->instances[$pluginType]) ? $this->instances[$pluginType] : [];
166
      $this->instances[$pluginType][$pluginId] = $instance;
167
    }
168
169
    return $this->instances[$pluginType][$pluginId];
170
  }
171
172
  /**
173
   * {@inheritdoc}
174
   */
175
  public function __sleep() {
176
    // Don't write the plugin instances into the cache.
177
    return array_diff($this->sleepDependencies(), ['instance']);
178
  }
179
}
180