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

ViewDeriver::getDerivativeDefinitions()   B

Complexity

Conditions 5
Paths 2

Size

Total Lines 40
Code Lines 29

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 5
eloc 29
nc 2
nop 1
dl 0
loc 40
rs 8.439
c 0
b 0
f 0
1
<?php
2
3
namespace Drupal\graphql_core\Plugin\Deriver\Fields;
4
5
use Drupal\Core\Plugin\Discovery\ContainerDeriverInterface;
6
use Drupal\graphql\Utility\StringHelper;
7
use Drupal\graphql_core\Plugin\Deriver\ViewDeriverBase;
8
use Drupal\views\Plugin\views\display\DisplayPluginInterface;
9
use Drupal\views\Views;
10
11
/**
12
 * Derive fields from configured views.
13
 */
14
class ViewDeriver extends ViewDeriverBase implements ContainerDeriverInterface {
15
16
  /**
17
   * {@inheritdoc}
18
   */
19
  public function getDerivativeDefinitions($basePluginDefinition) {
20
    if ($this->entityTypeManager->hasDefinition('view')) {
21
      $viewStorage = $this->entityTypeManager->getStorage('view');
22
23
      foreach (Views::getApplicableViews('graphql_display') as list($viewId, $displayId)) {
24
        /** @var \Drupal\views\ViewEntityInterface $view */
25
        $view = $viewStorage->load($viewId);
26
        if (!$this->getRowResolveType($view, $displayId)) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $this->getRowResolveType($view, $displayId) of type null|string is loosely compared to false; this is ambiguous if the string can be empty. You might want to explicitly use === null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
27
          continue;
28
        }
29
30
        /** @var \Drupal\graphql\Plugin\views\display\GraphQL $display */
31
        $display = $this->getViewDisplay($view, $displayId);
32
33
        $id = implode('-', [$viewId, $displayId, 'view']);
34
        $info = $this->getArgumentsInfo($display->getOption('arguments') ?: []);
35
        $arguments = [];
36
        $arguments += $this->getContextualArguments($info, $id);
37
        $arguments += $this->getPagerArguments($display);
38
        $arguments += $this->getSortArguments($display, $id);
39
        $arguments += $this->getFilterArguments($display, $id);
40
        $types = $this->getTypes($info);
41
42
        $this->derivatives[$id] = [
43
            'id' => $id,
44
            'name' => $display->getGraphQLQueryName(),
45
            'type' => $display->getGraphQLResultName(),
46
            'parents' => $types,
47
            'multi' => FALSE,
48
            'arguments' => $arguments,
49
            'view' => $viewId,
50
            'display' => $displayId,
51
            'paged' => $this->isPaged($display),
52
            'arguments_info' => $info,
53
          ] + $this->getCacheMetadataDefinition($view) + $basePluginDefinition;
54
      }
55
    }
56
57
    return parent::getDerivativeDefinitions($basePluginDefinition);
58
  }
59
60
  /**
61
   * Helper function to return the contextual filter argument if any exist.
62
   *
63
   * @param array $arguments
64
   *   The array of available arguments.
65
   * @param $id
66
   *   The plugin derivative id.
67
   *
68
   * @return array
69
   *   The contextual filter argument if applicable.
70
   */
71
  protected function getContextualArguments(array $arguments, $id) {
72
    if (!empty($arguments)) {
73
      return [
74
        'contextualFilter' => [
75
          'type' => StringHelper::camelCase([$id, 'contextual', 'filter', 'input']),
76
          'multi' => FALSE,
77
          'nullable' => TRUE,
78
        ],
79
      ];
80
    }
81
82
    return [];
83
  }
84
85
  /**
86
   * Helper function to retrieve the sort arguments if any are exposed.
87
   *
88
   * @param \Drupal\views\Plugin\views\display\DisplayPluginInterface $display
89
   *   The display plugin.
90
   * @param $id
91
   *   The plugin derivative id.
92
   *
93
   * @return array
94
   *   The sort arguments if any exposed sorts are available.
95
   */
96
  protected function getSortArguments(DisplayPluginInterface $display, $id) {
97
    $sorts = array_filter($display->getOption('sorts') ?: [], function($sort) {
98
      return $sort['exposed'];
99
    });
100
101
    return !empty($sorts) ? [
102
      'sortDirection' => [
103
        'enum_type_name' => 'ViewsSortDirectionEnum',
104
        'type' => [
105
          'ASC' => 'Ascending',
106
          'DESC' => 'Descending',
107
        ],
108
        'default' => TRUE,
109
      ],
110
      'sortBy' => [
111
        'enum_type_name' => StringHelper::camelCase(['sort', 'by', $id, 'enum']),
112
        'type' => array_map(function($sort) {
113
          return $sort['expose']['label'];
114
        }, $sorts),
115
        'nullable' => TRUE,
116
      ],
117
    ] : [];
118
  }
119
120
  /**
121
   * Helper function to return the filter argument if applicable.
122
   *
123
   * @param \Drupal\views\Plugin\views\display\DisplayPluginInterface $display
124
   *   The display plugin.
125
   * @param $id
126
   *   The plugin derivative id.
127
   *
128
   * @return array
129
   *   The filter argument if any exposed filters are available.
130
   */
131
  protected function getFilterArguments(DisplayPluginInterface $display, $id) {
132
    $filters = array_filter($display->getOption('filters') ?: [], function($filter) {
133
      return array_key_exists('exposed', $filter) && $filter['exposed'];
134
    });
135
136
    return !empty($filters) ? [
137
      'filter' => [
138
        'type' => StringHelper::camelCase([$id, 'filter', 'input']),
139
        'multi' => FALSE,
140
        'nullable' => TRUE,
141
      ],
142
    ] : [];
143
  }
144
145
  /**
146
   * Helper function to retrieve the pager arguments if the display is paged.
147
   *
148
   * @param \Drupal\views\Plugin\views\display\DisplayPluginInterface $display
149
   *   The display plugin.
150
   *
151
   * @return array
152
   *   An array of pager arguments if the view display is paged.
153
   */
154
  protected function getPagerArguments(DisplayPluginInterface $display) {
155
    return $this->isPaged($display) ? [
156
      'page' => ['type' => 'Int', 'default' => $this->getPagerOffset($display)],
157
      'pageSize' => ['type' => 'Int', 'default' => $this->getPagerLimit($display)],
158
    ] : [];
159
  }
160
161
  /**
162
   * Helper function to retrieve the types that the view can be attached to.
163
   *
164
   * @param array $arguments
165
   *   An array containing information about the available arguments.
166
   * @return array
167
   *   An array of additional types the view can be embedded in.
168
   */
169
  protected function getTypes(array $arguments) {
170
    $types = ['Root'];
171
172
    if (empty($arguments)) {
173
      return $types;
174
    }
175
176
    foreach ($arguments as $argument) {
177
      // Depending on whether bundles are known, we expose the view field
178
      // either on the interface (e.g. Node) or on the type (e.g. NodePage)
179
      // level. Here we specify types managed by other graphql_* modules,
180
      // yet we don't define these modules as dependencies. If types are not
181
      // in the schema, the resulting GraphQL field will be attached to
182
      // nowhere, so it won't go into the schema.
183
      if (empty($argument['bundles']) && empty($argument['entity_type'])) {
184
        continue;
185
      }
186
187
      if (empty($argument['bundles'])) {
188
        $types = array_merge($types, [StringHelper::camelCase($argument['entity_type'])]);
189
      }
190
      else {
191
        $types = array_merge($types, array_map(function($bundle) use ($argument) {
192
          return StringHelper::camelCase([$argument['entity_type'], $bundle]);
193
        }, array_keys($argument['bundles'])));
194
      }
195
    }
196
197
    return $types;
198
  }
199
200
}
201