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;
14 * Defines a class to build a listing of view entities.
16 * @see \Drupal\views\Entity\View
18 class ViewListBuilder extends ConfigEntityListBuilder {
21 * The views display plugin manager to use.
23 * @var \Drupal\Component\Plugin\PluginManagerInterface
25 protected $displayManager;
35 public static function createInstance(ContainerInterface $container, EntityTypeInterface $entity_type) {
38 $container->get('entity.manager')->getStorage($entity_type->id()),
39 $container->get('plugin.manager.views.display')
44 * Constructs a new ViewListBuilder object.
46 * @param \Drupal\Core\Entity\EntityTypeInterface $entity_type
47 * The entity type definition.
48 * @param \Drupal\Core\Entity\EntityStorageInterface $storage
49 * The entity storage class.
50 * @param \Drupal\Component\Plugin\PluginManagerInterface $display_manager
51 * The views display plugin manager to use.
53 public function __construct(EntityTypeInterface $entity_type, EntityStorageInterface $storage, PluginManagerInterface $display_manager) {
54 parent::__construct($entity_type, $storage);
56 $this->displayManager = $display_manager;
57 // This list builder uses client-side filters which requires all entities to
58 // be listed, disable the pager.
59 // @todo https://www.drupal.org/node/2536826 change the filtering to support
67 public function load() {
72 foreach (parent::load() as $entity) {
73 if ($entity->status()) {
74 $entities['enabled'][] = $entity;
77 $entities['disabled'][] = $entity;
86 public function buildRow(EntityInterface $view) {
87 $row = parent::buildRow($view);
92 '#plain_text' => $view->label(),
97 '#plain_text' => $view->id(),
102 '#plain_text' => $view->get('description'),
107 '#theme' => 'views_ui_view_displays_list',
108 '#displays' => $this->getDisplaysList($view),
111 'operations' => $row['operations'],
114 'class' => [$view->status() ? 'views-ui-list-enabled' : 'views-ui-list-disabled'],
122 public function buildHeader() {
125 'data' => $this->t('View name'),
127 'class' => ['views-ui-name'],
131 'data' => $this->t('Machine name'),
133 'class' => ['views-ui-machine-name'],
137 'data' => $this->t('Description'),
139 'class' => ['views-ui-description'],
143 'data' => $this->t('Displays'),
145 'class' => ['views-ui-displays'],
149 'data' => $this->t('Operations'),
151 'class' => ['views-ui-operations'],
160 public function getDefaultOperations(EntityInterface $entity) {
161 $operations = parent::getDefaultOperations($entity);
163 if ($entity->hasLinkTemplate('duplicate-form')) {
164 $operations['duplicate'] = [
165 'title' => $this->t('Duplicate'),
167 'url' => $entity->urlInfo('duplicate-form'),
171 // Add AJAX functionality to enable/disable operations.
172 foreach (['enable', 'disable'] as $op) {
173 if (isset($operations[$op])) {
174 $operations[$op]['url'] = $entity->urlInfo($op);
175 // Enable and disable operations should use AJAX.
176 $operations[$op]['attributes']['class'][] = 'use-ajax';
186 public function render() {
187 $entities = $this->load();
188 $list['#type'] = 'container';
189 $list['#attributes']['id'] = 'views-entity-list';
191 $list['#attached']['library'][] = 'core/drupal.ajax';
192 $list['#attached']['library'][] = 'views_ui/views_ui.listing';
195 '#type' => 'container',
197 'class' => ['table-filter', 'js-show'],
201 $list['filters']['text'] = [
203 '#title' => $this->t('Filter'),
204 '#title_display' => 'invisible',
206 '#placeholder' => $this->t('Filter by view name, machine name, description, or display path'),
208 'class' => ['views-filter-text'],
209 'data-table' => '.views-listing-table',
210 'autocomplete' => 'off',
211 'title' => $this->t('Enter a part of the view name, machine name, description, or display path to filter by.'),
215 $list['enabled']['heading']['#markup'] = '<h2>' . $this->t('Enabled', [], ['context' => 'Plural']) . '</h2>';
216 $list['disabled']['heading']['#markup'] = '<h2>' . $this->t('Disabled', [], ['context' => 'Plural']) . '</h2>';
217 foreach (['enabled', 'disabled'] as $status) {
218 $list[$status]['#type'] = 'container';
219 $list[$status]['#attributes'] = ['class' => ['views-list-section', $status]];
220 $list[$status]['table'] = [
221 '#theme' => 'views_ui_views_listing_table',
222 '#headers' => $this->buildHeader(),
223 '#attributes' => ['class' => ['views-listing-table', $status]],
225 foreach ($entities[$status] as $entity) {
226 $list[$status]['table']['#rows'][$entity->id()] = $this->buildRow($entity);
229 // @todo Use a placeholder for the entity label if this is abstracted to
230 // other entity types.
231 $list['enabled']['table']['#empty'] = $this->t('There are no enabled views.');
232 $list['disabled']['table']['#empty'] = $this->t('There are no disabled views.');
238 * Gets a list of displays included in the view.
240 * @param \Drupal\Core\Entity\EntityInterface $view
241 * The view entity instance to get a list of displays for.
244 * An array of display types that this view includes.
246 protected function getDisplaysList(EntityInterface $view) {
249 $executable = $view->getExecutable();
250 $executable->initDisplay();
251 foreach ($executable->displayHandlers as $display) {
252 $rendered_path = FALSE;
253 $definition = $display->getPluginDefinition();
254 if (!empty($definition['admin'])) {
255 if ($display->hasPath()) {
256 $path = $display->getPath();
257 if ($view->status() && strpos($path, '%') === FALSE) {
258 // @todo Views should expect and store a leading /. See:
259 // https://www.drupal.org/node/2423913
260 $rendered_path = \Drupal::l('/' . $path, Url::fromUserInput('/' . $path));
263 $rendered_path = '/' . $path;
267 'display' => $definition['admin'],
268 'path' => $rendered_path,