628408e997fde5837e1c4ad0f67108783314afad
[yaffs-website] / web / core / modules / views_ui / src / ViewListBuilder.php
1 <?php
2
3 namespace Drupal\views_ui;
4
5 use Drupal\Component\Plugin\PluginManagerInterface;
6 use Drupal\Core\Entity\EntityInterface;
7 use Drupal\Core\Config\Entity\ConfigEntityListBuilder;
8 use Drupal\Core\Entity\EntityStorageInterface;
9 use Drupal\Core\Entity\EntityTypeInterface;
10 use Drupal\Core\Url;
11 use Symfony\Component\DependencyInjection\ContainerInterface;
12 use Symfony\Component\HttpKernel\Exception\NotAcceptableHttpException;
13
14 /**
15  * Defines a class to build a listing of view entities.
16  *
17  * @see \Drupal\views\Entity\View
18  */
19 class ViewListBuilder extends ConfigEntityListBuilder {
20
21   /**
22    * The views display plugin manager to use.
23    *
24    * @var \Drupal\Component\Plugin\PluginManagerInterface
25    */
26   protected $displayManager;
27
28   /**
29    * {@inheritdoc}
30    */
31   protected $limit;
32
33   /**
34    * {@inheritdoc}
35    */
36   public static function createInstance(ContainerInterface $container, EntityTypeInterface $entity_type) {
37     return new static(
38       $entity_type,
39       $container->get('entity.manager')->getStorage($entity_type->id()),
40       $container->get('plugin.manager.views.display')
41     );
42   }
43
44   /**
45    * Constructs a new ViewListBuilder object.
46    *
47    * @param \Drupal\Core\Entity\EntityTypeInterface $entity_type
48    *   The entity type definition.
49    * @param \Drupal\Core\Entity\EntityStorageInterface $storage
50    *   The entity storage class.
51    * @param \Drupal\Component\Plugin\PluginManagerInterface $display_manager
52    *   The views display plugin manager to use.
53    */
54   public function __construct(EntityTypeInterface $entity_type, EntityStorageInterface $storage, PluginManagerInterface $display_manager) {
55     parent::__construct($entity_type, $storage);
56
57     $this->displayManager = $display_manager;
58     // This list builder uses client-side filters which requires all entities to
59     // be listed, disable the pager.
60     // @todo https://www.drupal.org/node/2536826 change the filtering to support
61     //   a pager.
62     $this->limit = FALSE;
63   }
64
65   /**
66    * {@inheritdoc}
67    */
68   public function load() {
69     $entities = [
70       'enabled' => [],
71       'disabled' => [],
72     ];
73     foreach (parent::load() as $entity) {
74       if ($entity->status()) {
75         $entities['enabled'][] = $entity;
76       }
77       else {
78         $entities['disabled'][] = $entity;
79       }
80     }
81     return $entities;
82   }
83
84   /**
85    * {@inheritdoc}
86    */
87   public function buildRow(EntityInterface $view) {
88     $row = parent::buildRow($view);
89     return [
90       'data' => [
91         'view_name' => [
92           'data' => [
93             '#plain_text' => $view->label(),
94           ],
95         ],
96         'machine_name' => [
97           'data' => [
98             '#plain_text' => $view->id(),
99           ],
100         ],
101         'description' => [
102           'data' => [
103             '#plain_text' => $view->get('description'),
104           ],
105         ],
106         'displays' => [
107           'data' => [
108             '#theme' => 'views_ui_view_displays_list',
109             '#displays' => $this->getDisplaysList($view),
110           ],
111         ],
112         'operations' => $row['operations'],
113       ],
114       '#attributes' => [
115         'class' => [$view->status() ? 'views-ui-list-enabled' : 'views-ui-list-disabled'],
116       ],
117     ];
118   }
119
120   /**
121    * {@inheritdoc}
122    */
123   public function buildHeader() {
124     return [
125       'view_name' => [
126         'data' => $this->t('View name'),
127         '#attributes' => [
128           'class' => ['views-ui-name'],
129         ],
130       ],
131       'machine_name' => [
132         'data' => $this->t('Machine name'),
133         '#attributes' => [
134           'class' => ['views-ui-machine-name'],
135         ],
136       ],
137       'description' => [
138         'data' => $this->t('Description'),
139         '#attributes' => [
140           'class' => ['views-ui-description'],
141         ],
142       ],
143       'displays' => [
144         'data' => $this->t('Displays'),
145         '#attributes' => [
146           'class' => ['views-ui-displays'],
147         ],
148       ],
149       'operations' => [
150         'data' => $this->t('Operations'),
151         '#attributes' => [
152           'class' => ['views-ui-operations'],
153         ],
154       ],
155     ];
156   }
157
158   /**
159    * {@inheritdoc}
160    */
161   public function getDefaultOperations(EntityInterface $entity) {
162     $operations = parent::getDefaultOperations($entity);
163
164     if ($entity->hasLinkTemplate('duplicate-form')) {
165       $operations['duplicate'] = [
166         'title' => $this->t('Duplicate'),
167         'weight' => 15,
168         'url' => $entity->urlInfo('duplicate-form'),
169       ];
170     }
171
172     // Add AJAX functionality to enable/disable operations.
173     foreach (['enable', 'disable'] as $op) {
174       if (isset($operations[$op])) {
175         $operations[$op]['url'] = $entity->urlInfo($op);
176         // Enable and disable operations should use AJAX.
177         $operations[$op]['attributes']['class'][] = 'use-ajax';
178       }
179     }
180
181     return $operations;
182   }
183
184   /**
185    * {@inheritdoc}
186    */
187   public function render() {
188     $entities = $this->load();
189     $list['#type'] = 'container';
190     $list['#attributes']['id'] = 'views-entity-list';
191
192     $list['#attached']['library'][] = 'core/drupal.ajax';
193     $list['#attached']['library'][] = 'views_ui/views_ui.listing';
194
195     $form['filters'] = [
196       '#type' => 'container',
197       '#attributes' => [
198         'class' => ['table-filter', 'js-show'],
199       ],
200     ];
201
202     $list['filters']['text'] = [
203       '#type' => 'search',
204       '#title' => $this->t('Filter'),
205       '#title_display' => 'invisible',
206       '#size' => 60,
207       '#placeholder' => $this->t('Filter by view name, machine name, description, or display path'),
208       '#attributes' => [
209         'class' => ['views-filter-text'],
210         'data-table' => '.views-listing-table',
211         'autocomplete' => 'off',
212         'title' => $this->t('Enter a part of the view name, machine name, description, or display path to filter by.'),
213       ],
214     ];
215
216     $list['enabled']['heading']['#markup'] = '<h2>' . $this->t('Enabled', [], ['context' => 'Plural']) . '</h2>';
217     $list['disabled']['heading']['#markup'] = '<h2>' . $this->t('Disabled', [], ['context' => 'Plural']) . '</h2>';
218     foreach (['enabled', 'disabled'] as $status) {
219       $list[$status]['#type'] = 'container';
220       $list[$status]['#attributes'] = ['class' => ['views-list-section', $status]];
221       $list[$status]['table'] = [
222         '#theme' => 'views_ui_views_listing_table',
223         '#headers' => $this->buildHeader(),
224         '#attributes' => ['class' => ['views-listing-table', $status]],
225       ];
226       foreach ($entities[$status] as $entity) {
227         $list[$status]['table']['#rows'][$entity->id()] = $this->buildRow($entity);
228       }
229     }
230     // @todo Use a placeholder for the entity label if this is abstracted to
231     // other entity types.
232     $list['enabled']['table']['#empty'] = $this->t('There are no enabled views.');
233     $list['disabled']['table']['#empty'] = $this->t('There are no disabled views.');
234
235     return $list;
236   }
237
238   /**
239    * Gets a list of displays included in the view.
240    *
241    * @param \Drupal\Core\Entity\EntityInterface $view
242    *   The view entity instance to get a list of displays for.
243    *
244    * @return array
245    *   An array of display types that this view includes.
246    */
247   protected function getDisplaysList(EntityInterface $view) {
248     $displays = [];
249
250     $executable = $view->getExecutable();
251     $executable->initDisplay();
252     foreach ($executable->displayHandlers as $display) {
253       $rendered_path = FALSE;
254       $definition = $display->getPluginDefinition();
255       if (!empty($definition['admin'])) {
256         if ($display->hasPath()) {
257           $path = $display->getPath();
258           if ($view->status() && strpos($path, '%') === FALSE) {
259             // Wrap this in a try/catch as trying to generate links to some
260             // routes may throw a NotAcceptableHttpException if they do not
261             // respond to HTML, such as RESTExports.
262             try {
263               // @todo Views should expect and store a leading /. See:
264               //   https://www.drupal.org/node/2423913
265               $rendered_path = \Drupal::l('/' . $path, Url::fromUserInput('/' . $path));
266             }
267             catch (NotAcceptableHttpException $e) {
268               $rendered_path = '/' . $path;
269             }
270           }
271           else {
272             $rendered_path = '/' . $path;
273           }
274         }
275         $displays[] = [
276           'display' => $definition['admin'],
277           'path' => $rendered_path,
278         ];
279       }
280     }
281
282     sort($displays);
283     return $displays;
284   }
285
286 }