This project does not seem to handle request data directly as such no vulnerable execution paths were found.
include
, or for example
via PHP's auto-loading mechanism.
These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
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) { |
||
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
|
|||
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
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. ![]() |
|||
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 |
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.