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

PluggableSchemaPluginBase::getRootFields()   A

Complexity

Conditions 4
Paths 1

Size

Total Lines 12
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Importance

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