Completed
Pull Request — 8.x-3.x (#401)
by Sebastian
02:28
created

PluggableSchemaManager::find()   B

Complexity

Conditions 8
Paths 5

Size

Total Lines 19
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 8
eloc 11
nc 5
nop 3
dl 0
loc 19
rs 7.7777
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\Component\Plugin\PluginManagerInterface;
7
8
/**
9
 * GraphQL plugin manager.
10
 */
11
class PluggableSchemaManager implements PluggableSchemaManagerInterface {
12
13
  /**
14
   * Plugin managers, used to collect GraphQL schema plugins.
15
   *
16
   * @var \Drupal\Component\Plugin\PluginManagerInterface[]
17
   */
18
  protected $pluginManagers = [];
19
20
  /**
21
   * Static cache for sorted definitions.
22
   *
23
   * @var array
24
   */
25
  protected $definitions = NULL;
26
27
  /**
28
   * PluggableSchemaManager constructor.
29
   *
30
   * @param \Drupal\Component\Plugin\PluginManagerInterface[] $pluginManagers
31
   *   The list of type system plugin managers.
32
   */
33
  public function __construct(array $pluginManagers) {
34
    $this->pluginManagers = $pluginManagers;
35
  }
36
37
  /**
38
   * Returns the list of sorted plugin definitions.
39
   *
40
   * @return array
41
   *   The list of sorted plugin definitions.
42
   */
43
  protected function getDefinitions() {
44
    if ($this->definitions == NULL) {
45
      foreach ($this->pluginManagers as $manager) {
46
        foreach ($manager->getDefinitions() as $pluginId => $definition) {
47
          $this->definitions[] = [
48
            'plugin_id' => $pluginId,
49
            'definition' => $definition,
50
            'weight' => $definition['weight'],
51
            'manager' => $manager,
52
          ];
53
        }
54
      }
55
56
      uasort($this->definitions, '\Drupal\Component\Utility\SortArray::sortByWeightElement');
57
      $this->definitions = array_reverse($this->definitions);
58
    }
59
60
    return $this->definitions;
61
  }
62
63
  /**
64
   * {@inheritdoc}
65
   */
66
  public function find(callable $selector, array $types, $invert = FALSE) {
67
    $instances = [];
68
    foreach ($this->getDefinitions() as $index => $definition) {
69
      $name = $definition['definition']['name'];
70
      if (empty($name)) {
71
        throw new InvalidPluginDefinitionException("Invalid GraphQL plugin definition. No name defined.");
72
      }
73
74
      if (!array_key_exists($name, $instances) && in_array($definition['definition']['pluginType'], $types)) {
75
        if ((($invert && !$selector($definition['definition'])) || $selector($definition['definition']))) {
76
          /** @var PluginManagerInterface $manager */
77
          $manager = $definition['manager'];
78
          $instances[$name] = $manager->createInstance($definition['plugin_id'], ['schema_manager' => $this]);
79
        }
80
      }
81
    }
82
83
    return $instances;
84
  }
85
86
  /**
87
   * {@inheritdoc}
88
   */
89
  public function findByName($name, array $types) {
90
    $result = $this->find(function($definition) use ($name) {
91
      return $definition['name'] === $name;
92
    }, $types);
93
94
    if (empty($result)) {
95
      throw new InvalidPluginDefinitionException('GraphQL plugin with name ' . $name . ' could not be found.');
96
    }
97
98
    return array_pop($result);
99
  }
100
101
  /**
102
   * {@inheritdoc}
103
   */
104
  public function findByDataType($dataType, array $types = [
105
    GRAPHQL_UNION_TYPE_PLUGIN,
106
    GRAPHQL_TYPE_PLUGIN,
107
    GRAPHQL_INTERFACE_PLUGIN,
108
    GRAPHQL_SCALAR_PLUGIN,
109
  ]) {
110
    $chain = explode(':', $dataType);
111
112
    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...
113
      $dataType = implode(':', $chain);
114
115
      $types = $this->find(function($definition) use ($dataType) {
116
        return isset($definition['data_type']) && $definition['data_type'] == $dataType;
117
      }, $types);
118
119
      if (!empty($types)) {
120
        return array_pop($types);
121
      }
122
123
      array_pop($chain);
124
    }
125
126
    return NULL;
127
  }
128
129
  /**
130
   * {@inheritdoc}
131
   */
132
  public function getMutations() {
133
    return $this->find(function() {
134
      return TRUE;
135
    }, [GRAPHQL_MUTATION_PLUGIN]);
136
  }
137
138
  /**
139
   * {@inheritdoc}
140
   */
141
  public function getRootFields() {
142
    // Retrieve the list of fields that are explicitly attached to a type.
143
    $attachedFields = array_reduce(array_filter(array_map(function($definition) {
144
      return array_key_exists('fields', $definition['definition']) ? $definition['definition']['fields'] : NULL;
145
    }, $this->getDefinitions())), 'array_merge', []);
146
147
    // Retrieve the list of fields that are not attached in any way or
148
    // explicitly attached to the artificial "Root" type.
149
    return $this->find(function($definition) use ($attachedFields) {
150
      return (!in_array($definition['name'], $attachedFields) && empty($definition['parents'])) || in_array('Root', $definition['parents']);
151
    }, [GRAPHQL_FIELD_PLUGIN]);
152
  }
153
154
}
155