Security update for Core, with self-updated composer
[yaffs-website] / web / core / modules / views / src / Views.php
1 <?php
2
3 namespace Drupal\views;
4
5 /**
6  * Static service container wrapper for views.
7  */
8 class Views {
9
10   /**
11    * The translation manager.
12    *
13    * @var \Drupal\Core\StringTranslation\TranslationInterface
14    */
15   protected static $translationManager;
16
17   /**
18    * A static cache for handler types data.
19    *
20    * @var array
21    */
22   protected static $handlerTypes;
23
24   /**
25    * A list of all available views plugin types.
26    *
27    * @var array
28    */
29   protected static $plugins = [
30     'access' => 'plugin',
31     'area' => 'handler',
32     'argument' => 'handler',
33     'argument_default' => 'plugin',
34     'argument_validator' => 'plugin',
35     'cache' => 'plugin',
36     'display_extender' => 'plugin',
37     'display' => 'plugin',
38     'exposed_form' => 'plugin',
39     'field' => 'handler',
40     'filter' => 'handler',
41     'join' => 'plugin',
42     'pager' => 'plugin',
43     'query' => 'plugin',
44     'relationship' => 'handler',
45     'row' => 'plugin',
46     'sort' => 'handler',
47     'style' => 'plugin',
48     'wizard' => 'plugin',
49   ];
50
51   /**
52    * Returns the views data service.
53    *
54    * @return \Drupal\views\ViewsData
55    *   Returns a views data cache object.
56    */
57   public static function viewsData() {
58     return \Drupal::service('views.views_data');
59   }
60
61   /**
62    * Returns the views data helper service.
63    *
64    * @return \Drupal\views\ViewsDataHelper
65    *   Returns a views data helper object.
66    */
67   public static function viewsDataHelper() {
68     return \Drupal::service('views.views_data_helper');
69   }
70
71   /**
72    * Returns the view executable factory service.
73    *
74    * @return \Drupal\views\ViewExecutableFactory
75    *   Returns a views executable factory.
76    */
77   public static function executableFactory() {
78     return \Drupal::service('views.executable');
79   }
80
81   /**
82    * Returns the view analyzer.
83    *
84    * @return \Drupal\views\Analyzer
85    *   Returns a view analyzer object.
86    */
87   public static function analyzer() {
88     return \Drupal::service('views.analyzer');
89   }
90
91   /**
92    * Returns the plugin manager for a certain views plugin type.
93    *
94    * @param string $type
95    *   The plugin type, for example filter.
96    *
97    * @return \Drupal\views\Plugin\ViewsPluginManager
98    */
99   public static function pluginManager($type) {
100     return \Drupal::service('plugin.manager.views.' . $type);
101   }
102
103   /**
104    * Returns the plugin manager for a certain views handler type.
105    *
106    * @return \Drupal\views\Plugin\ViewsHandlerManager
107    */
108   public static function handlerManager($type) {
109     return \Drupal::service('plugin.manager.views.' . $type);
110   }
111
112   /**
113    * Loads a view from configuration and returns its executable object.
114    *
115    * @param string $id
116    *   The view ID to load.
117    *
118    * @return \Drupal\views\ViewExecutable
119    *   A view executable instance, from the loaded entity.
120    */
121   public static function getView($id) {
122     $view = \Drupal::service('entity.manager')->getStorage('view')->load($id);
123     if ($view) {
124       return static::executableFactory()->get($view);
125     }
126   }
127
128   /**
129    * Fetches a list of all base tables available
130    *
131    * @param string $type
132    *   Either 'display', 'style' or 'row'.
133    * @param string $key
134    *   For style plugins, this is an optional type to restrict to. May be
135    *   'normal', 'summary', 'feed' or others based on the needs of the display.
136    * @param array $base
137    *   An array of possible base tables.
138    *
139    * @return
140    *   A keyed array of in the form of 'base_table' => 'Description'.
141    */
142   public static function fetchPluginNames($type, $key = NULL, array $base = []) {
143     $definitions = static::pluginManager($type)->getDefinitions();
144     $plugins = [];
145
146     foreach ($definitions as $id => $plugin) {
147       // Skip plugins that don't conform to our key, if they have one.
148       if ($key && isset($plugin['display_types']) && !in_array($key, $plugin['display_types'])) {
149         continue;
150       }
151
152       if (empty($plugin['no_ui']) && (empty($base) || empty($plugin['base']) || array_intersect($base, $plugin['base']))) {
153         $plugins[$id] = $plugin['title'];
154       }
155     }
156
157     if (!empty($plugins)) {
158       asort($plugins);
159       return $plugins;
160     }
161
162     return $plugins;
163   }
164
165   /**
166    * Gets all the views plugin definitions.
167    *
168    * @return array
169    *   An array of plugin definitions for all types.
170    */
171   public static function getPluginDefinitions() {
172     $plugins = [];
173     foreach (ViewExecutable::getPluginTypes() as $plugin_type) {
174       $plugins[$plugin_type] = static::pluginManager($plugin_type)->getDefinitions();
175     }
176
177     return $plugins;
178   }
179
180   /**
181    * Gets enabled display extenders.
182    */
183   public static function getEnabledDisplayExtenders() {
184     $enabled = array_filter((array) \Drupal::config('views.settings')->get('display_extenders'));
185
186     return array_combine($enabled, $enabled);
187   }
188
189   /**
190    * Return a list of all view IDs and display IDs that have a particular
191    * setting in their display's plugin settings.
192    *
193    * @param string $type
194    *   A flag from the display plugin definitions (e.g, 'uses_menu_links').
195    *
196    * @return array
197    *   A list of arrays containing the $view_id and $display_id.
198    * @code
199    * array(
200    *   array($view_id, $display_id),
201    *   array($view_id, $display_id),
202    * );
203    * @endcode
204    */
205   public static function getApplicableViews($type) {
206     // Get all display plugins which provides the type.
207     $display_plugins = static::pluginManager('display')->getDefinitions();
208
209     $plugin_ids = [];
210     foreach ($display_plugins as $id => $definition) {
211       if (!empty($definition[$type])) {
212         $plugin_ids[$id] = $id;
213       }
214     }
215
216     $entity_ids = \Drupal::entityQuery('view')
217       ->condition('status', TRUE)
218       ->condition("display.*.display_plugin", $plugin_ids, 'IN')
219       ->execute();
220
221     $result = [];
222     foreach (\Drupal::entityTypeManager()->getStorage('view')->loadMultiple($entity_ids) as $view) {
223       // Check each display to see if it meets the criteria and is enabled.
224
225       foreach ($view->get('display') as $id => $display) {
226         // If the key doesn't exist, enabled is assumed.
227         $enabled = !empty($display['display_options']['enabled']) || !array_key_exists('enabled', $display['display_options']);
228
229         if ($enabled && in_array($display['display_plugin'], $plugin_ids)) {
230           $result[] = [$view->id(), $id];
231         }
232       }
233     }
234
235     return $result;
236   }
237
238   /**
239    * Returns an array of all views as fully loaded $view objects.
240    *
241    * @return \Drupal\views\Entity\View[]
242    *   An array of loaded view entities.
243    */
244   public static function getAllViews() {
245     return \Drupal::entityManager()->getStorage('view')->loadMultiple();
246   }
247
248   /**
249    * Returns an array of all enabled views.
250    *
251    * @return \Drupal\views\Entity\View[]
252    *   An array of loaded enabled view entities.
253    */
254   public static function getEnabledViews() {
255     $query = \Drupal::entityQuery('view')
256       ->condition('status', TRUE)
257       ->execute();
258
259     return \Drupal::entityManager()->getStorage('view')->loadMultiple($query);
260   }
261
262   /**
263    * Returns an array of all disabled views.
264    *
265    * @return \Drupal\views\Entity\View[]
266    *   An array of loaded disabled view entities.
267    */
268   public static function getDisabledViews() {
269     $query = \Drupal::entityQuery('view')
270       ->condition('status', FALSE)
271       ->execute();
272
273     return \Drupal::entityManager()->getStorage('view')->loadMultiple($query);
274   }
275
276   /**
277    * Returns an array of view as options array, that can be used by select,
278    * checkboxes and radios as #options.
279    *
280    * @param bool $views_only
281    *   If TRUE, only return views, not displays.
282    * @param string $filter
283    *   Filters the views on status. Can either be 'all' (default), 'enabled' or
284    *   'disabled'
285    * @param mixed $exclude_view
286    *   View or current display to exclude.
287    *   Either a:
288    *   - views object (containing $exclude_view->storage->name and $exclude_view->current_display)
289    *   - views name as string:  e.g. my_view
290    *   - views name and display id (separated by ':'): e.g. my_view:default
291    * @param bool $optgroup
292    *   If TRUE, returns an array with optgroups for each view (will be ignored for
293    *   $views_only = TRUE). Can be used by select
294    * @param bool $sort
295    *   If TRUE, the list of views is sorted ascending.
296    *
297    * @return array
298    *   An associative array for use in select.
299    *   - key: view name and display id separated by ':', or the view name only.
300    */
301   public static function getViewsAsOptions($views_only = FALSE, $filter = 'all', $exclude_view = NULL, $optgroup = FALSE, $sort = FALSE) {
302
303     // Filter the big views array.
304     switch ($filter) {
305       case 'all':
306       case 'disabled':
307       case 'enabled':
308         $filter = ucfirst($filter);
309         $views = call_user_func("static::get{$filter}Views");
310         break;
311       default:
312         return [];
313     }
314
315     // Prepare exclude view strings for comparison.
316     if (empty($exclude_view)) {
317       $exclude_view_name = '';
318       $exclude_view_display = '';
319     }
320     elseif (is_object($exclude_view)) {
321       $exclude_view_name = $exclude_view->storage->id();
322       $exclude_view_display = $exclude_view->current_display;
323     }
324     else {
325       // Append a ':' to the $exclude_view string so we always have more than one
326       // item to explode.
327       list($exclude_view_name, $exclude_view_display) = explode(':', "$exclude_view:");
328     }
329
330     $options = [];
331     foreach ($views as $view) {
332       $id = $view->id();
333       // Return only views.
334       if ($views_only && $id != $exclude_view_name) {
335         $options[$id] = $view->label();
336       }
337       // Return views with display ids.
338       else {
339         foreach ($view->get('display') as $display_id => $display) {
340           if (!($id == $exclude_view_name && $display_id == $exclude_view_display)) {
341             if ($optgroup) {
342               $options[$id][$id . ':' . $display['id']] = t('@view : @display', ['@view' => $id, '@display' => $display['id']]);
343             }
344             else {
345               $options[$id . ':' . $display['id']] = t('View: @view - Display: @display', ['@view' => $id, '@display' => $display['id']]);
346             }
347           }
348         }
349       }
350     }
351     if ($sort) {
352       ksort($options);
353     }
354     return $options;
355   }
356
357   /**
358    * Returns a list of plugins and metadata about them.
359    *
360    * @return array
361    *   An array keyed by PLUGIN_TYPE:PLUGIN_NAME, like 'display:page' or
362    *   'pager:full', containing an array with the following keys:
363    *   - title: The plugin's title.
364    *   - type: The plugin type.
365    *   - module: The module providing the plugin.
366    *   - views: An array of enabled Views that are currently using this plugin,
367    *     keyed by machine name.
368    */
369   public static function pluginList() {
370     $plugin_data = static::getPluginDefinitions();
371     $plugins = [];
372     foreach (static::getEnabledViews() as $view) {
373       foreach ($view->get('display') as $display) {
374         foreach ($plugin_data as $type => $info) {
375           if ($type == 'display' && isset($display['display_plugin'])) {
376             $name = $display['display_plugin'];
377           }
378           elseif (isset($display['display_options']["{$type}_plugin"])) {
379             $name = $display['display_options']["{$type}_plugin"];
380           }
381           elseif (isset($display['display_options'][$type]['type'])) {
382             $name = $display['display_options'][$type]['type'];
383           }
384           else {
385             continue;
386           }
387
388           // Key first by the plugin type, then the name.
389           $key = $type . ':' . $name;
390           // Add info for this plugin.
391           if (!isset($plugins[$key])) {
392             $plugins[$key] = [
393               'type' => $type,
394               'title' => $info[$name]['title'],
395               'provider' => $info[$name]['provider'],
396               'views' => [],
397             ];
398           }
399
400           // Add this view to the list for this plugin.
401           $plugins[$key]['views'][$view->id()] = $view->id();
402         }
403       }
404     }
405     return $plugins;
406   }
407
408   /**
409    * Provide a list of views handler types used in a view, with some information
410    * about them.
411    *
412    * @return array
413    *   An array of associative arrays containing:
414    *   - title: The title of the handler type.
415    *   - ltitle: The lowercase title of the handler type.
416    *   - stitle: A singular title of the handler type.
417    *   - lstitle: A singular lowercase title of the handler type.
418    *   - plural: Plural version of the handler type.
419    *   - (optional) type: The actual internal used handler type. This key is
420    *     just used for header,footer,empty to link to the internal type: area.
421    */
422   public static function getHandlerTypes() {
423     // Statically cache this so translation only occurs once per request for all
424     // of these values.
425     if (!isset(static::$handlerTypes)) {
426       static::$handlerTypes = [
427         'field' => [
428           // title
429           'title' => static::t('Fields'),
430           // Lowercase title for mid-sentence.
431           'ltitle' => static::t('fields'),
432           // Singular title.
433           'stitle' => static::t('Field'),
434           // Singular lowercase title for mid sentence
435           'lstitle' => static::t('field'),
436           'plural' => 'fields',
437         ],
438         'argument' => [
439           'title' => static::t('Contextual filters'),
440           'ltitle' => static::t('contextual filters'),
441           'stitle' => static::t('Contextual filter'),
442           'lstitle' => static::t('contextual filter'),
443           'plural' => 'arguments',
444         ],
445         'sort' => [
446           'title' => static::t('Sort criteria'),
447           'ltitle' => static::t('sort criteria'),
448           'stitle' => static::t('Sort criterion'),
449           'lstitle' => static::t('sort criterion'),
450           'plural' => 'sorts',
451         ],
452         'filter' => [
453           'title' => static::t('Filter criteria'),
454           'ltitle' => static::t('filter criteria'),
455           'stitle' => static::t('Filter criterion'),
456           'lstitle' => static::t('filter criterion'),
457           'plural' => 'filters',
458         ],
459         'relationship' => [
460           'title' => static::t('Relationships'),
461           'ltitle' => static::t('relationships'),
462           'stitle' => static::t('Relationship'),
463           'lstitle' => static::t('Relationship'),
464           'plural' => 'relationships',
465         ],
466         'header' => [
467           'title' => static::t('Header'),
468           'ltitle' => static::t('header'),
469           'stitle' => static::t('Header'),
470           'lstitle' => static::t('Header'),
471           'plural' => 'header',
472           'type' => 'area',
473         ],
474         'footer' => [
475           'title' => static::t('Footer'),
476           'ltitle' => static::t('footer'),
477           'stitle' => static::t('Footer'),
478           'lstitle' => static::t('Footer'),
479           'plural' => 'footer',
480           'type' => 'area',
481         ],
482         'empty' => [
483           'title' => static::t('No results behavior'),
484           'ltitle' => static::t('no results behavior'),
485           'stitle' => static::t('No results behavior'),
486           'lstitle' => static::t('No results behavior'),
487           'plural' => 'empty',
488           'type' => 'area',
489         ],
490       ];
491     }
492
493     return static::$handlerTypes;
494   }
495
496   /**
497    * Returns a list of plugin types.
498    *
499    * @param string $type
500    *   (optional) filter the list of plugins by type. Available options are
501    *   'plugin' or 'handler'.
502    *
503    * @return array
504    *   An array of plugin types.
505    */
506   public static function getPluginTypes($type = NULL) {
507     if ($type === NULL) {
508       return array_keys(static::$plugins);
509     }
510
511     if (!in_array($type, ['plugin', 'handler'])) {
512       throw new \Exception('Invalid plugin type used. Valid types are "plugin" or "handler".');
513     }
514
515     return array_keys(array_filter(static::$plugins, function ($plugin_type) use ($type) {
516       return $plugin_type == $type;
517     }));
518   }
519
520   /**
521    * Translates a string to the current language or to a given language.
522    *
523    * See the t() documentation for details.
524    */
525   protected static function t($string, array $args = [], array $options = []) {
526     if (empty(static::$translationManager)) {
527       static::$translationManager = \Drupal::service('string_translation');
528     }
529
530     return static::$translationManager->translate($string, $args, $options);
531   }
532
533 }