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

PluggableSchemaBuilder::getTypeByName()   B

Complexity

Conditions 5
Paths 4

Size

Total Lines 14
Code Lines 8

Duplication

Lines 6
Ratio 42.86 %

Importance

Changes 0
Metric Value
cc 5
eloc 8
nc 4
nop 1
dl 6
loc 14
rs 8.8571
c 0
b 0
f 0
1
<?php
2
3
namespace Drupal\graphql\Plugin\GraphQL;
4
5
use Drupal\Component\Plugin\Factory\DefaultFactory;
6
use Drupal\Core\DependencyInjection\DependencySerializationTrait;
7
8
/**
9
 * TODO: This thing was just quickly put together to make the PoC work. Fix it!
10
 */
11
class PluggableSchemaBuilder implements PluggableSchemaBuilderInterface {
12
  use DependencySerializationTrait;
13
14
  /**
15
   * The type system plugin manager aggregator service.
16
   *
17
   * @var \Drupal\graphql\Plugin\GraphQL\TypeSystemPluginManagerAggregator
18
   */
19
  protected $pluginManagers;
20
21
  /**
22
   * PluggableSchemaBuilder constructor.
23
   *
24
   * @param \Drupal\graphql\Plugin\GraphQL\TypeSystemPluginManagerAggregator $pluginManagers
25
   *   Type system plugin manager aggregator service.
26
   */
27
  public function __construct(TypeSystemPluginManagerAggregator $pluginManagers) {
28
    $this->pluginManagers = $pluginManagers;
29
  }
30
31
  /**
32
   * @param $type
33
   * @param $id
34
   *
35
   * @return \Drupal\graphql\Plugin\GraphQL\TypeSystemPluginManagerInterface
36
   */
37
  public function getPluginManager($type, $id) {
38
    $managers = $this->pluginManagers->getPluginManagers($type);
39
    foreach ($managers as $manager) {
40
      if ($manager->hasDefinition($id)) {
41
        return $manager;
42
      }
43
    }
44
45
    throw new \LogicException('Could not find plugin manager.');
46
  }
47
48
  /**
49
   * @param $type
50
   * @param $id
51
   *
52
   * @return mixed
53
   */
54
  public function getPluginDefinition($type, $id) {
55
    return $this->getPluginManager($type, $id)->getDefinition($id);
56
  }
57
58
  /**
59
   * @param $type
60
   * @param $id
61
   *
62
   * @return object
63
   */
64
  public function getPluginInstance($type, $id) {
65
    if (!isset($this->plugins[$type][$id])) {
66
      return $this->plugins[$type][$id] = $this->getPluginManager($type, $id)->createInstance($id);
67
    }
68
69
    return $this->plugins[$type][$id];
70
  }
71
72
  /**
73
   * @param $type
74
   * @param $id
75
   *
76
   * @return mixed
77
   */
78
  public function getDefinition($type, $id) {
79
    return $this->getPluginInstance($type, $id)->getDefinition();
80
  }
81
82
  /**
83
   * @param $type
84
   * @param $id
85
   *
86
   * @return mixed
87
   */
88
  public function getType($type, $id) {
89
    if (!isset($this->instances[$type][$id])) {
90
      $class = DefaultFactory::getPluginClass($id, $this->getPluginDefinition($type, $id));
91
      $definition = $this->getDefinition($type, $id);
92
      return $this->instances[$type][$id] = call_user_func([$class, 'createInstance'], $this, $definition, $id);
93
    }
94
95
    return $this->instances[$type][$id];
96
  }
97
98
  /**
99
   * @return array
100
   */
101
  public function getTypeMap() {
102
    if (isset($this->typeMap)) {
103
      return $this->typeMap;
104
    }
105
106
    foreach ($this->pluginManagers as $type => $managers) {
107
      if ($type === GRAPHQL_FIELD_PLUGIN || $type === GRAPHQL_MUTATION_PLUGIN) {
108
        continue;
109
      }
110
111
      /** @var \Drupal\graphql\Plugin\GraphQL\TypeSystemPluginManagerInterface $manager */
112
      foreach ($managers as $manager) {
113
        foreach ($manager->getDefinitions() as $id => $definition) {
114
          $placeholder = &$this->typeMap[$definition['name']];
115
116
          if (!empty($placeholder)) {
117
            $existing = $this->getPluginDefinition($placeholder[0], $placeholder[1]);
118
            // Do not override if the existing plugin has a higher weight.
119
            if ($existing['weight'] > $definition['weight']) {
120
              continue;
121
            }
122
          }
123
124
          $placeholder = [$type, $id];
125
          if (isset($definition['type'])) {
126
            $this->typeMap[$definition['type']] = &$placeholder;
127
          }
128
        }
129
      }
130
    }
131
132
    return $this->typeMap = array_filter($this->typeMap);
133
  }
134
135
  /**
136
   * @return array
137
   */
138
  public function getFieldMap() {
139
    if (isset($this->fieldMap)) {
140
      return $this->fieldMap;
141
    }
142
143
    $this->fieldMap = [];
144
    foreach ($this->pluginManagers->getPluginManagers(GRAPHQL_FIELD_PLUGIN) as $manager) {
145
      foreach ($manager->getDefinitions() as $id => $definition) {
146
        $parents = $definition['parents'] ?: ['Root'];
147
148 View Code Duplication
        foreach ($parents as $parent) {
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...
149
          $placeholder = &$this->fieldMap[$parent][$definition['name']];
150
151
          if (!empty($placeholder)) {
152
            // Do not override if the existing plugin has a higher weight.
153
            $existing = $this->getPluginDefinition(GRAPHQL_FIELD_PLUGIN, $placeholder);
154
            if ($existing['weight'] > $definition['weight']) {
155
              continue;
156
            }
157
          }
158
159
          $placeholder = $id;
160
        }
161
      }
162
    }
163
164
    return $this->fieldMap;
165
  }
166
167
  /**
168
   * @return array
169
   */
170
  public function getMutationMap() {
171
    if (isset($this->mutationMap)) {
172
      return $this->mutationMap;
173
    }
174
175
    $this->mutationMap = [];
176
    foreach ($this->pluginManagers->getPluginManagers(GRAPHQL_MUTATION_PLUGIN) as $manager) {
177 View Code Duplication
      foreach ($manager->getDefinitions() as $id => $definition) {
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...
178
        $placeholder = &$this->mutationMap[$definition['name']];
179
180
        if (!empty($placeholder)) {
181
          // Do not override if the existing plugin has a higher weight.
182
          $existing = $this->getPluginDefinition(GRAPHQL_MUTATION_PLUGIN, $placeholder);
183
          if ($existing['weight'] > $definition['weight']) {
184
            continue;
185
          }
186
        }
187
188
        $placeholder = $id;
189
      }
190
    }
191
192
    return $this->mutationMap;
193
  }
194
195
  /**
196
   * @param $name
197
   *
198
   * @return mixed
199
   */
200
  public function getTypeByName($name) {
201
    $map = $this->getTypeMap();
202 View Code Duplication
    if (isset($map[$name])) {
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...
203
      return $this->getType($map[$name][0], $map[$name][1]);
204
    }
205
206
    while (($pos = strpos($name, ':')) !== FALSE && $name = substr($name, 0, $pos)) {
207 View Code Duplication
      if (isset($map[$name])) {
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...
208
        return $this->getType($map[$name][0], $map[$name][1]);
209
      }
210
    }
211
212
    throw new \LogicException('Could not find type in type map.');
213
  }
214
215
  /**
216
   * @param $name
217
   *
218
   * @return array
219
   */
220
  public function getFieldsByType($name) {
221
    $map = $this->getFieldMap();
222
    if (empty($map[$name])) {
223
      return [];
224
    }
225
226
    return $this->resolveFields($map[$name]);
227
  }
228
229
  /**
230
   * @param $fields
231
   *
232
   * @return array
233
   */
234
  public function resolveFields($fields, $pluginType = GRAPHQL_FIELD_PLUGIN) {
235
    return array_map(function ($id) use ($fields, $pluginType) {
236
      $field = $this->getType($pluginType, $id);
237
      list($type, $decorators) = $field['type'];
238
239
      $type = array_reduce($decorators, function ($a, $decorator) use ($type) {
240
        return $decorator($a);
241
      }, $this->getTypeByName($type));
242
243
      return [
244
        'type' => $type,
245
      ] + $field;
246
    }, $fields);
247
  }
248
249
  /**
250
   * @param $args
251
   *
252
   * @return array
253
   */
254
  public function resolveArgs($args) {
255
    return array_map(function ($arg) {
256
      list($type, $decorators) = $arg['type'];
257
258
      $type = array_reduce($decorators, function ($a, $decorator) use ($type) {
259
        return $decorator($a);
260
      }, $this->getTypeByName($type));
261
262
      return [
263
        'type' => $type,
264
      ] + $arg;
265
    }, $args);
266
  }
267
268
}
269