ViewDeriverHelperTrait::getFilterArguments()   A
last analyzed

Complexity

Conditions 4
Paths 2

Size

Total Lines 11

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 11
rs 9.9
c 0
b 0
f 0
cc 4
nc 2
nop 2
1
<?php
2
3
namespace Drupal\graphql_views;
4
5
use Drupal\Component\Plugin\PluginManagerInterface;
6
use Drupal\Component\Utility\NestedArray;
7
use Drupal\graphql\Utility\StringHelper;
8
use Drupal\graphql_views\Plugin\views\row\GraphQLEntityRow;
9
use Drupal\graphql_views\Plugin\views\row\GraphQLFieldRow;
10
use Drupal\views\Plugin\views\display\DisplayPluginInterface;
11
use Drupal\views\ViewEntityInterface;
12
13
/**
14
 * Helper functions fot view derivers.
15
 */
16
trait ViewDeriverHelperTrait {
17
18
  /**
19
   * Helper function to return the contextual filter argument if any exist.
20
   *
21
   * @param array $arguments
22
   *   The array of available arguments.
23
   * @param string $id
24
   *   The plugin derivative id.
25
   *
26
   * @return array
27
   *   The contextual filter argument if applicable.
28
   */
29
  protected function getContextualArguments(array $arguments, $id) {
30
    if (!empty($arguments)) {
31
      return [
32
        'contextualFilter' => [
33
          'type' => StringHelper::camelCase($id, 'contextual', 'filter', 'input'),
34
        ],
35
      ];
36
    }
37
38
    return [];
39
  }
40
41
  /**
42
   * Helper function to retrieve the sort arguments if any are exposed.
43
   *
44
   * @param \Drupal\views\Plugin\views\display\DisplayPluginInterface $display
45
   *   The display plugin.
46
   * @param string $id
47
   *   The plugin derivative id.
48
   *
49
   * @return array
50
   *   The sort arguments if any exposed sorts are available.
51
   */
52
  protected function getSortArguments(DisplayPluginInterface $display, $id) {
53
    $sorts = array_filter($display->getOption('sorts') ?: [], function ($sort) {
54
      return $sort['exposed'];
55
    });
56
    return $sorts ? [
57
      'sortDirection' => [
58
        'type' => 'ViewSortDirection',
59
        'default' => 'asc',
60
      ],
61
      'sortBy' => [
62
        'type' => StringHelper::camelCase($id, 'sort', 'by'),
63
      ],
64
    ] : [];
65
  }
66
67
  /**
68
   * Helper function to return the filter argument if applicable.
69
   *
70
   * @param \Drupal\views\Plugin\views\display\DisplayPluginInterface $display
71
   *   The display plugin.
72
   * @param string $id
73
   *   The plugin derivative id.
74
   *
75
   * @return array
76
   *   The filter argument if any exposed filters are available.
77
   */
78
  protected function getFilterArguments(DisplayPluginInterface $display, $id) {
0 ignored issues
show
Unused Code introduced by
The parameter $id is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
79
    $filters = array_filter($display->getOption('filters') ?: [], function ($filter) {
80
      return array_key_exists('exposed', $filter) && $filter['exposed'];
81
    });
82
83
    return !empty($filters) ? [
84
      'filter' => [
85
        'type' => $display->getGraphQLFilterInputName(),
86
      ],
87
    ] : [];
88
  }
89
90
  /**
91
   * Helper function to retrieve the pager arguments if the display is paged.
92
   *
93
   * @param \Drupal\views\Plugin\views\display\DisplayPluginInterface $display
94
   *   The display plugin.
95
   *
96
   * @return array
97
   *   An array of pager arguments if the view display is paged.
98
   */
99
  protected function getPagerArguments(DisplayPluginInterface $display) {
100
    return $this->isPaged($display) ? [
101
      'page' => ['type' => 'Int', 'default' => $this->getPagerOffset($display)],
102
      'pageSize' => [
103
        'type' => 'Int',
104
        'default' => $this->getPagerLimit($display),
105
      ],
106
    ] : [];
107
  }
108
109
  /**
110
   * Helper function to retrieve the types that the view can be attached to.
111
   *
112
   * @param array $arguments
113
   *   An array containing information about the available arguments.
114
   * @param array $types
115
   *   Types where it needs to be added.
116
   *
117
   * @return array
118
   *   An array of additional types the view can be embedded in.
119
   */
120
  protected function getTypes(array $arguments, array $types = ['Root']) {
121
122
    if (empty($arguments)) {
123
      return $types;
124
    }
125
126
    foreach ($arguments as $argument) {
127
      // Depending on whether bundles are known, we expose the view field
128
      // either on the interface (e.g. Node) or on the type (e.g. NodePage)
129
      // level. Here we specify types managed by other graphql_* modules,
130
      // yet we don't define these modules as dependencies. If types are not
131
      // in the schema, the resulting GraphQL field will be attached to
132
      // nowhere, so it won't go into the schema.
133
      if (empty($argument['bundles']) && empty($argument['entity_type'])) {
134
        continue;
135
      }
136
137
      if (empty($argument['bundles'])) {
138
        $types = array_merge($types, [StringHelper::camelCase($argument['entity_type'])]);
139
      }
140
      else {
141
        $types = array_merge($types, array_map(function ($bundle) use ($argument) {
142
          return StringHelper::camelCase($argument['entity_type'], $bundle);
143
        }, array_keys($argument['bundles'])));
144
      }
145
    }
146
147
    return $types;
148
  }
149
150
  /**
151
   * Check if a pager is configured.
152
   *
153
   * @param \Drupal\views\Plugin\views\display\DisplayPluginInterface $display
154
   *   The display configuration.
155
   *
156
   * @return bool
157
   *   Flag indicating if the view is configured with a pager.
158
   */
159
  protected function isPaged(DisplayPluginInterface $display) {
160
    $pagerOptions = $display->getOption('pager');
161
    return isset($pagerOptions['type']) && in_array($pagerOptions['type'], [
162
        'full',
163
        'mini',
164
      ]);
165
  }
166
167
  /**
168
   * Returns a view display object.
169
   *
170
   * @param \Drupal\views\ViewEntityInterface $view
171
   *   The view object.
172
   * @param string $displayId
173
   *   The display ID to use.
174
   *
175
   * @return \Drupal\views\Plugin\views\display\DisplayPluginInterface
176
   *   The view display object.
177
   */
178
  protected function getViewDisplay(ViewEntityInterface $view, $displayId) {
179
    $viewExecutable = $view->getExecutable();
180
    $viewExecutable->setDisplay($displayId);
181
    return $viewExecutable->getDisplay();
182
  }
183
184
  /**
185
   * Get the configured default limit.
186
   *
187
   * @param \Drupal\views\Plugin\views\display\DisplayPluginInterface $display
188
   *   The display configuration.
189
   *
190
   * @return int
191
   *   The default limit.
192
   */
193 View Code Duplication
  protected function getPagerLimit(DisplayPluginInterface $display) {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in 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...
194
    $pagerOptions = $display->getOption('pager');
195
    return NestedArray::getValue($pagerOptions, [
196
      'options',
197
      'items_per_page',
198
    ]) ?: 0;
199
  }
200
201
  /**
202
   * Get the configured default offset.
203
   *
204
   * @param \Drupal\views\Plugin\views\display\DisplayPluginInterface $display
205
   *   The display configuration.
206
   *
207
   * @return int
208
   *   The default offset.
209
   */
210 View Code Duplication
  protected function getPagerOffset(DisplayPluginInterface $display) {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in 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...
211
    $pagerOptions = $display->getOption('pager');
212
    return NestedArray::getValue($pagerOptions, [
213
      'options',
214
      'offset',
215
    ]) ?: 0;
216
  }
217
218
  /**
219
   * Check if a certain interface exists.
220
   *
221
   * @param string $interface
222
   *   The GraphQL interface name.
223
   * @param \Drupal\Component\Plugin\PluginManagerInterface $interfacePluginManager
224
   *   Plugin interface manager.
225
   *
226
   * @return bool
227
   *   Boolean flag indicating if the interface exists.
228
   */
229
  protected function interfaceExists($interface, PluginManagerInterface $interfacePluginManager) {
230
    return (bool) array_filter($interfacePluginManager->getDefinitions(), function ($definition) use ($interface) {
231
      return $definition['name'] === $interface;
232
    });
233
  }
234
235
  /**
236
   * Retrieves the type the view's rows resolve to.
237
   *
238
   * @param \Drupal\views\ViewEntityInterface $view
239
   *   The view entity.
240
   * @param string $displayId
241
   *   The id of the current display.
242
   * @param \Drupal\Component\Plugin\PluginManagerInterface $interfacePluginManager
243
   *   Interface plugin manager.
244
   *
245
   * @return null|string
246
   *   The name of the type or NULL if the type could not be derived.
247
   */
248
  protected function getRowResolveType(ViewEntityInterface $view, $displayId, PluginManagerInterface $interfacePluginManager) {
249
    /** @var \Drupal\graphql_views\Plugin\views\display\GraphQL $display */
250
    $display = $this->getViewDisplay($view, $displayId);
251
    $rowPlugin = $display->getPlugin('row');
252
253
    if ($rowPlugin instanceof GraphQLFieldRow) {
254
      return StringHelper::camelCase($display->getGraphQLRowName());
255
    }
256
257
    if ($rowPlugin instanceof GraphQLEntityRow) {
258
      $executable = $view->getExecutable();
259
      $executable->setDisplay($displayId);
260
261
      if ($entityType = $executable->getBaseEntityType()) {
262
        $typeName = $entityType->id();
263
        $typeNameCamel = StringHelper::camelCase($typeName);
264
        if ($this->interfaceExists($typeNameCamel, $interfacePluginManager)) {
265
          $filters = $executable->getDisplay()->getOption('filters');
266
          $dataTable = $entityType->getDataTable();
267
          $bundleKey = $entityType->getKey('bundle');
268
269
          foreach ($filters as $filter) {
270
            $isBundleFilter = $filter['table'] == $dataTable && $filter['field'] == $bundleKey;
271
            $isSingleValued = is_array($filter['value']) && count($filter['value']) == 1;
272
            $isExposed = isset($filter['exposed']) && $filter['exposed'];
273
            if ($isBundleFilter && $isSingleValued && !$isExposed) {
274
              $bundle = reset($filter['value']);
275
              $typeName .= "_$bundle";
276
              break;
277
            }
278
          }
279
280
          return StringHelper::camelCase($typeName);
281
        }
282
      }
283
284
      return 'Entity';
285
    }
286
287
    return NULL;
288
  }
289
290
  /**
291
   * Returns a view style object.
292
   *
293
   * @param \Drupal\views\ViewEntityInterface $view
294
   *   The view object.
295
   * @param string $displayId
296
   *   The display ID to use.
297
   *
298
   * @return \Drupal\views\Plugin\views\style\StylePluginBase
299
   *   The view style object.
300
   */
301
  protected function getViewStyle(ViewEntityInterface $view, $displayId) {
302
    $viewExecutable = $view->getExecutable();
303
    $viewExecutable->setDisplay($displayId);
304
    return $viewExecutable->getStyle();
305
  }
306
307
  /**
308
   * Returns cache metadata plugin definitions.
309
   *
310
   * @param \Drupal\views\ViewEntityInterface $view
311
   *   The view object.
312
   * @param \Drupal\views\Plugin\views\display\DisplayPluginInterface $display
313
   *   The view display.
314
   *
315
   * @return array
316
   *   The cache metadata definitions for the plugin definition.
317
   */
318
  protected function getCacheMetadataDefinition(ViewEntityInterface $view, DisplayPluginInterface $display) {
319
    $metadata = $display->getCacheMetadata()
320
      ->addCacheTags($view->getCacheTags())
321
      ->addCacheContexts($view->getCacheContexts())
322
      ->mergeCacheMaxAge($view->getCacheMaxAge());
323
324
    return [
325
      'schema_cache_tags' => $metadata->getCacheTags(),
326
      'schema_cache_max_age' => $metadata->getCacheMaxAge(),
327
      'response_cache_contexts' => array_filter($metadata->getCacheContexts(), function ($context) {
328
        // Don't emit the url cache contexts.
329
        return $context !== 'url' && strpos($context, 'url.') !== 0;
330
      }),
331
    ];
332
  }
333
334
  /**
335
   * Returns information about view arguments (contextual filters).
336
   *
337
   * @param array $viewArguments
338
   *   The "arguments" option of a view display.
339
   *
340
   * @return array
341
   *   Arguments information keyed by the argument ID. Subsequent array keys:
342
   *     - index: argument index.
343
   *     - entity_type: target entity type.
344
   *     - bundles: target bundles (can be empty).
345
   *
346
   * @throws \Drupal\Component\Plugin\Exception\PluginNotFoundException
347
   */
348
  protected function getArgumentsInfo(array $viewArguments) {
349
    $argumentsInfo = [];
350
    /* @var \Drupal\Core\Entity\EntityTypeManager $entityTypeManager */
351
    $entityTypeManager = \Drupal::service('entity_type.manager');
352
353
    $index = 0;
354
    foreach ($viewArguments as $argumentId => $argument) {
355
      $info = [
356
        'index' => $index,
357
        'entity_type' => NULL,
358
        'bundles' => [],
359
      ];
360
361
      if (isset($argument['entity_type']) && isset($argument['entity_field'])) {
362
        $entityType = $entityTypeManager->getDefinition($argument['entity_type']);
363
        if ($entityType) {
364
          $idField = $entityType->getKey('id');
365
          if ($idField === $argument['entity_field']) {
366
            $info['entity_type'] = $argument['entity_type'];
367
            if (
368
              $argument['specify_validation'] &&
369
              strpos($argument['validate']['type'], 'entity:') === 0 &&
370
              !empty($argument['validate_options']['bundles'])
371
            ) {
372
              $info['bundles'] = $argument['validate_options']['bundles'];
373
            }
374
          }
375
        }
376
      }
377
378
      $argumentsInfo[$argumentId] = $info;
379
      $index++;
380
    }
381
382
    return $argumentsInfo;
383
  }
384
385
}
386