3 namespace Drupal\views_ui;
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;
11 use Symfony\Component\DependencyInjection\ContainerInterface;
12 use Symfony\Component\HttpKernel\Exception\NotAcceptableHttpException;
15 * Defines a class to build a listing of view entities.
17 * @see \Drupal\views\Entity\View
19 class ViewListBuilder extends ConfigEntityListBuilder {
22 * The views display plugin manager to use.
24 * @var \Drupal\Component\Plugin\PluginManagerInterface
26 protected $displayManager;
36 public static function createInstance(ContainerInterface $container, EntityTypeInterface $entity_type) {
39 $container->get('entity.manager')->getStorage($entity_type->id()),
40 $container->get('plugin.manager.views.display')
45 * Constructs a new ViewListBuilder object.
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.
54 public function __construct(EntityTypeInterface $entity_type, EntityStorageInterface $storage, PluginManagerInterface $display_manager) {
55 parent::__construct($entity_type, $storage);
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
68 public function load() {
73 foreach (parent::load() as $entity) {
74 if ($entity->status()) {
75 $entities['enabled'][] = $entity;
78 $entities['disabled'][] = $entity;
87 public function buildRow(EntityInterface $view) {
88 $row = parent::buildRow($view);
93 '#plain_text' => $view->label(),
98 '#plain_text' => $view->id(),
103 '#plain_text' => $view->get('description'),
108 '#theme' => 'views_ui_view_displays_list',
109 '#displays' => $this->getDisplaysList($view),
112 'operations' => $row['operations'],
115 'class' => [$view->status() ? 'views-ui-list-enabled' : 'views-ui-list-disabled'],
123 public function buildHeader() {
126 'data' => $this->t('View name'),
128 'class' => ['views-ui-name'],
132 'data' => $this->t('Machine name'),
134 'class' => ['views-ui-machine-name'],
138 'data' => $this->t('Description'),
140 'class' => ['views-ui-description'],
144 'data' => $this->t('Displays'),
146 'class' => ['views-ui-displays'],
150 'data' => $this->t('Operations'),
152 'class' => ['views-ui-operations'],
161 public function getDefaultOperations(EntityInterface $entity) {
162 $operations = parent::getDefaultOperations($entity);
164 if ($entity->hasLinkTemplate('duplicate-form')) {
165 $operations['duplicate'] = [
166 'title' => $this->t('Duplicate'),
168 'url' => $entity->urlInfo('duplicate-form'),
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';
187 public function render() {
188 $entities = $this->load();
189 $list['#type'] = 'container';
190 $list['#attributes']['id'] = 'views-entity-list';
192 $list['#attached']['library'][] = 'core/drupal.ajax';
193 $list['#attached']['library'][] = 'views_ui/views_ui.listing';
196 '#type' => 'container',
198 'class' => ['table-filter', 'js-show'],
202 $list['filters']['text'] = [
204 '#title' => $this->t('Filter'),
205 '#title_display' => 'invisible',
207 '#placeholder' => $this->t('Filter by view name, machine name, description, or display path'),
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.'),
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]],
226 foreach ($entities[$status] as $entity) {
227 $list[$status]['table']['#rows'][$entity->id()] = $this->buildRow($entity);
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.');
239 * Gets a list of displays included in the view.
241 * @param \Drupal\Core\Entity\EntityInterface $view
242 * The view entity instance to get a list of displays for.
245 * An array of display types that this view includes.
247 protected function getDisplaysList(EntityInterface $view) {
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.
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));
267 catch (NotAcceptableHttpException $e) {
268 $rendered_path = '/' . $path;
272 $rendered_path = '/' . $path;
276 'display' => $definition['admin'],
277 'path' => $rendered_path,