Passed
Pull Request — 8.x-1.x (#40)
by
unknown
02:16
created

Views::extractExposedInput()   A

Complexity

Conditions 4
Paths 4

Size

Total Lines 23
Code Lines 12

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 4
eloc 12
c 0
b 0
f 0
nc 4
nop 4
dl 0
loc 23
rs 9.8666
1
<?php
2
3
namespace Drupal\graphql_views\Plugin\GraphQL\DataProducer;
4
5
use Drupal\Component\Utility\NestedArray;
0 ignored issues
show
Bug introduced by
The type Drupal\Component\Utility\NestedArray was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
6
use Drupal\Core\Entity\EntityTypeManagerInterface;
0 ignored issues
show
Bug introduced by
The type Drupal\Core\Entity\EntityTypeManagerInterface was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
7
use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
0 ignored issues
show
Bug introduced by
The type Drupal\Core\Plugin\ContainerFactoryPluginInterface was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
8
use Drupal\graphql\GraphQL\Execution\FieldContext;
0 ignored issues
show
Bug introduced by
The type Drupal\graphql\GraphQL\Execution\FieldContext was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
9
use Drupal\graphql\Plugin\GraphQL\DataProducer\DataProducerPluginBase;
0 ignored issues
show
Bug introduced by
The type Drupal\graphql\Plugin\Gr...\DataProducerPluginBase was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
10
use Drupal\views\Plugin\views\display\DisplayPluginInterface;
0 ignored issues
show
Bug introduced by
The type Drupal\views\Plugin\view...\DisplayPluginInterface was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
11
use Symfony\Component\DependencyInjection\ContainerInterface;
0 ignored issues
show
Bug introduced by
The type Symfony\Component\Depend...tion\ContainerInterface was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
12
13
/**
14
 * GraphQL data producer for views.
15
 *
16
 * @DataProducer(
17
 *   id = "views",
18
 *   name = @Translation("Views"),
19
 *   description = @Translation("Views."),
20
 *   produces = @ContextDefinition("entity",
21
 *     label = @Translation("Entity")
22
 *   ),
23
 *   consumes = {
24
 *     "view_id" = @ContextDefinition("string",
25
 *       label = @Translation("View ID")
26
 *     ),
27
 *     "display_id" = @ContextDefinition("string",
28
 *       label = @Translation("Display ID")
29
 *     ),
30
 *     "offset" = @ContextDefinition("integer",
31
 *       label = @Translation("Offset"),
32
 *       required = FALSE
33
 *     ),
34
 *     "page_size" = @ContextDefinition("integer",
35
 *       label = @Translation("Page size"),
36
 *       required = FALSE
37
 *     ),
38
 *     "page" = @ContextDefinition("integer",
39
 *       label = @Translation("Current page"),
40
 *       required = FALSE
41
 *     ),
42
 *     "sort_by" = @ContextDefinition("string",
43
 *       label = @Translation("Sort by"),
44
 *       required = FALSE
45
 *     ),
46
 *     "sort_direction" = @ContextDefinition("string",
47
 *       label = @Translation("Sort direction"),
48
 *       required = FALSE
49
 *     ),
50
 *     "filter" = @ContextDefinition("any",
51
 *       label = @Translation("Sort direction"),
52
 *       required = FALSE,
53
 *       default_value = {}
54
 *     )
55
 *   }
56
 * )
57
 */
58
class Views extends DataProducerPluginBase implements ContainerFactoryPluginInterface {
59
60
  /**
61
   * The entity type manager.
62
   *
63
   * @var \Drupal\Core\Entity\EntityTypeManagerInterface
64
   */
65
  protected $entityTypeManager;
66
67
  /**
68
   * {@inheritdoc}
69
   */
70
  public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
71
    return new static($configuration, $plugin_id, $plugin_definition, $container->get('entity_type.manager'));
72
  }
73
74
  /**
75
   * {@inheritdoc}
76
   */
77
  public function __construct(array $configuration, $plugin_id, $plugin_definition, EntityTypeManagerInterface $entityTypeManager) {
78
    parent::__construct($configuration, $plugin_id, $plugin_definition);
79
    $this->entityTypeManager = $entityTypeManager;
80
  }
81
82
  /**
83
   * Resolve the data.
84
   *
85
   * @param string $view_id
86
   *   The view ID.
87
   * @param string $display_id
88
   *   The display ID.
89
   * @param int|null $offset
90
   *   Offset of the query.
91
   * @param int|null $page_size
92
   *   Number of items on page.
93
   * @param int|null $page
94
   *   Number of page.
95
   *
96
   * @return array|null
97
   *   List of entities.
98
   *
99
   * @throws \Drupal\Component\Plugin\Exception\InvalidPluginDefinitionException
100
   * @throws \Drupal\Component\Plugin\Exception\PluginNotFoundException
101
   */
102
  public function resolve(string $view_id, string $display_id, int $offset = NULL, int $page_size = NULL, int $page = NULL, string $sort_by = NULL, string $sort_direction = NULL, array $filter = [], FieldContext $fieldContext) {
103
104
    /** @var \Drupal\views\Entity\View $view */
105
    $view = \Drupal::entityTypeManager()->getStorage('view')->load($view_id);
106
107
    $executable = $view->getExecutable();
108
    $executable->setDisplay($display_id);
109
110
    // Set paging parameters.
111
    if (empty($page_size)) {
112
      $page_size = $this->getPagerLimit($executable->getDisplay());
113
    }
114
    if (empty($page)) {
115
      $page = $this->getPagerOffset($executable->getDisplay());
116
    }
117
    if ($this->isPaged($executable->getDisplay())) {
118
      $executable->setItemsPerPage($page_size);
119
      $executable->setCurrentPage($page);
120
    }
121
122
    if ($offset) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $offset of type integer|null is loosely compared to true; this is ambiguous if the integer can be 0. 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 integer values, zero is a special case, in particular the following results might be unexpected:

0   == false // true
0   == null  // true
123 == false // false
123 == null  // false

// It is often better to use strict comparison
0 === false // false
0 === null  // false
Loading history...
123
      $executable->setOffset($offset);
124
    }
125
126
    $available_filters = $executable->getDisplay()->getOption('filters');
127
    $input = $this->extractExposedInput($sort_by, $sort_direction, $filter, $available_filters);
128
    $executable->setExposedInput($input);
129
130
    // This is a workaround for the Taxonomy Term filter which requires a full
131
    // exposed form to be sent OR the display being an attachment to just
132
    // accept input values.
133
    $executable->is_attachment = TRUE;
134
    $executable->exposed_raw_input = $input;
135
136
    $executable->preExecute();
137
    $executable->execute();
138
139
    $result = $executable->render($display_id);
140
141
142
    /** @var \Drupal\Core\Cache\CacheableMetadata $cache */
143
    if ($cache = $result['cache']) {
144
      $cache->setCacheContexts(
145
        array_filter($cache->getCacheContexts(), function ($context) {
146
          // Don't emit the url cache contexts.
147
          return $context !== 'url' && strpos($context, 'url.') !== 0;
148
        })
149
      );
150
      $fieldContext->addCacheableDependency($cache);
151
    }
152
153
    return [
154
      'results' => $result['rows'],
155
      'count' => $result['view']->total_rows,
156
    ];
157
  }
158
159
  /**
160
   * Check if a pager is configured.
161
   *
162
   * @param \Drupal\views\Plugin\views\display\DisplayPluginInterface $display
163
   *   The display configuration.
164
   *
165
   * @return bool
166
   *   Flag indicating if the view is configured with a pager.
167
   */
168
  protected function isPaged(DisplayPluginInterface $display) {
169
    $pagerOptions = $display->getOption('pager');
170
    return isset($pagerOptions['type']) && in_array($pagerOptions['type'], [
171
      'full',
172
      'mini',
173
    ]);
174
  }
175
176
  /**
177
   * Get the configured default limit.
178
   *
179
   * @param \Drupal\views\Plugin\views\display\DisplayPluginInterface $display
180
   *   The display configuration.
181
   *
182
   * @return int
183
   *   The default limit.
184
   */
185
  protected function getPagerLimit(DisplayPluginInterface $display) {
186
    $pagerOptions = $display->getOption('pager');
187
    return NestedArray::getValue($pagerOptions, [
188
      'options',
189
      'items_per_page',
190
    ]) ?: 0;
191
  }
192
193
  /**
194
   * Get the configured default offset.
195
   *
196
   * @param \Drupal\views\Plugin\views\display\DisplayPluginInterface $display
197
   *   The display configuration.
198
   *
199
   * @return int
200
   *   The default offset.
201
   */
202
  protected function getPagerOffset(DisplayPluginInterface $display) {
203
    $pagerOptions = $display->getOption('pager');
204
    return NestedArray::getValue($pagerOptions, [
205
      'options',
206
      'offset',
207
    ]) ?: 0;
208
  }
209
210
  /**
211
   * Retrieves sort and filter arguments from the provided field args.
212
   *
213
   * @param $value
214
   *   The resolved parent value.
215
   * @param $args
216
   *   The array of arguments provided to the field.
217
   * @param $available_filters
218
   *   The available filters for the configured view.
219
   *
220
   * @return array
221
   *   The array of sort and filter arguments to execute the view with.
222
   */
223
  protected function extractExposedInput($sort_by, $sort_direction, $filter, $available_filters) {
224
    // Prepare arguments for use as exposed form input.
225
    $input = array_filter([
226
      // Sorting arguments.
227
      'sort_by' => $sort_by,
228
      'sort_order' => $sort_direction,
229
    ]);
230
231
    // If some filters are missing from the input, set them to an empty string
232
    // explicitly. Otherwise views module generates "Undefined index" notice.
233
    foreach ($available_filters as $filterRow) {
234
      if (!isset($filterRow['expose']['identifier'])) {
235
        continue;
236
      }
237
238
      $inputKey = $filterRow['expose']['identifier'];
239
      if (!isset($filter[$inputKey])) {
240
        $input[$inputKey] = $filterRow['value'];
241
      } else {
242
        $input[$inputKey] = $filter[$inputKey];
243
      }
244
    }
245
    return $input;
246
  }
247
248
}
249