ViewsUIController.php 7.18 KB
Newer Older
1 2
<?php

3
namespace Drupal\views_ui\Controller;
4

5
use Drupal\Core\Controller\ControllerBase;
6
use Drupal\Core\Url;
7
use Drupal\views\ViewExecutable;
8
use Drupal\views\ViewEntityInterface;
9
use Drupal\views\Views;
10
use Drupal\views_ui\ViewUI;
11
use Drupal\views\ViewsData;
12
use Symfony\Component\DependencyInjection\ContainerInterface;
13 14 15 16
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\JsonResponse;
use Drupal\Core\Ajax\AjaxResponse;
use Drupal\Core\Ajax\ReplaceCommand;
17
use Drupal\Component\Utility\Html;
18 19 20 21

/**
 * Returns responses for Views UI routes.
 */
22
class ViewsUIController extends ControllerBase {
23 24 25 26

  /**
   * Stores the Views data cache object.
   *
27
   * @var \Drupal\views\ViewsData
28 29 30 31
   */
  protected $viewsData;

  /**
32
   * Constructs a new \Drupal\views_ui\Controller\ViewsUIController object.
33
   *
34
   * @param \Drupal\views\ViewsData $views_data
35 36
   *   The Views data cache object.
   */
37
  public function __construct(ViewsData $views_data) {
38 39 40
    $this->viewsData = $views_data;
  }

41
  /**
42
   * {@inheritdoc}
43 44 45
   */
  public static function create(ContainerInterface $container) {
    return new static(
46
      $container->get('views.views_data')
47 48 49
    );
  }

50 51 52 53 54 55 56
  /**
   * Lists all instances of fields on any views.
   *
   * @return array
   *   The Views fields report page.
   */
  public function reportFields() {
57
    $views = $this->entityManager()->getStorage('view')->loadMultiple();
58 59 60 61

    // Fetch all fieldapi fields which are used in views
    // Therefore search in all views, displays and handler-types.
    $fields = array();
62
    $handler_types = ViewExecutable::getHandlerTypes();
63
    foreach ($views as $view) {
64
      $executable = $view->getExecutable();
65 66 67 68
      $executable->initDisplay();
      foreach ($executable->displayHandlers as $display_id => $display) {
        if ($executable->setDisplay($display_id)) {
          foreach ($handler_types as $type => $info) {
69
            foreach ($executable->getHandlers($type, $display_id) as $item) {
70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86
              $table_data = $this->viewsData->get($item['table']);
              if (isset($table_data[$item['field']]) && isset($table_data[$item['field']][$type])
                && $field_data = $table_data[$item['field']][$type]) {
                // The final check that we have a fieldapi field now.
                if (isset($field_data['field_name'])) {
                  $fields[$field_data['field_name']][$view->id()] = $view->id();
                }
              }
            }
          }
        }
      }
    }

    $header = array(t('Field name'), t('Used in'));
    $rows = array();
    foreach ($fields as $field_name => $views) {
87
      $rows[$field_name]['data'][0]['data']['#plain_text'] = $field_name;
88
      foreach ($views as $view) {
89
        $rows[$field_name]['data'][1][] = $this->l($view, new Url('entity.view.edit_form', array('view' => $view)));
90
      }
91 92 93 94 95 96
      $item_list = [
        '#theme' => 'item_list',
        '#items' => $rows[$field_name]['data'][1],
        '#context' => ['list_style' => 'comma-list'],
      ];
      $rows[$field_name]['data'][1] = ['data' => $item_list];
97 98 99 100 101
    }

    // Sort rows by field name.
    ksort($rows);
    $output = array(
102
      '#type' => 'table',
103 104 105 106 107 108 109 110 111 112 113 114 115 116 117
      '#header' => $header,
      '#rows' => $rows,
      '#empty' => t('No fields have been used in views yet.'),
    );

    return $output;
  }

  /**
   * Lists all plugins and what enabled Views use them.
   *
   * @return array
   *   The Views plugins report page.
   */
  public function reportPlugins() {
118
    $rows = Views::pluginList();
119
    foreach ($rows as &$row) {
120
      $views = [];
121 122
      // Link each view name to the view itself.
      foreach ($row['views'] as $row_name => $view) {
123
        $views[] = $this->l($view, new Url('entity.view.edit_form', array('view' => $view)));
124
      }
125
      unset($row['views']);
126 127
      $row['views']['data'] = [
        '#theme' => 'item_list',
128
        '#items' => $views,
129 130
        '#context' => ['list_style' => 'comma-list'],
      ];
131 132 133 134 135
    }

    // Sort rows by field name.
    ksort($rows);
    return array(
136
      '#type' => 'table',
137 138 139 140 141 142 143 144 145
      '#header' => array(t('Type'), t('Name'), t('Provided by'), t('Used in')),
      '#rows' => $rows,
      '#empty' => t('There are no enabled views.'),
    );
  }

  /**
   * Calls a method on a view and reloads the listing page.
   *
146
   * @param \Drupal\views\ViewEntityInterface $view
147 148 149
   *   The view being acted upon.
   * @param string $op
   *   The operation to perform, e.g., 'enable' or 'disable'.
150 151
   * @param \Symfony\Component\HttpFoundation\Request $request
   *   The current request.
152 153 154 155 156
   *
   * @return \Drupal\Core\Ajax\AjaxResponse|\Symfony\Component\HttpFoundation\RedirectResponse
   *   Either returns a rebuilt listing page as an AJAX response, or redirects
   *   back to the listing page.
   */
157
  public function ajaxOperation(ViewEntityInterface $view, $op, Request $request) {
158 159 160 161 162
    // Perform the operation.
    $view->$op()->save();

    // If the request is via AJAX, return the rendered list as JSON.
    if ($request->request->get('js')) {
163
      $list = $this->entityManager()->getListBuilder('view')->render();
164
      $response = new AjaxResponse();
165
      $response->addCommand(new ReplaceCommand('#views-entity-list', $list));
166 167 168 169
      return $response;
    }

    // Otherwise, redirect back to the page.
170
    return $this->redirect('entity.view.collection');
171 172 173 174 175 176 177 178 179 180 181 182 183 184 185
  }

  /**
   * Menu callback for Views tag autocompletion.
   *
   * Like other autocomplete functions, this function inspects the 'q' query
   * parameter for the string to use to search for suggestions.
   *
   * @return \Symfony\Component\HttpFoundation\JsonResponse
   *   A JSON response containing the autocomplete suggestions for Views tags.
   */
  public function autocompleteTag(Request $request) {
    $matches = array();
    $string = $request->query->get('q');
    // Get matches from default views.
186
    $views = $this->entityManager()->getStorage('view')->loadMultiple();
187 188
    // Keep track of previously processed tags so they can be skipped.
    $tags = [];
189 190
    foreach ($views as $view) {
      $tag = $view->get('tag');
191 192 193 194 195 196 197
      if ($tag && !in_array($tag, $tags)) {
        $tags[] = $tag;
        if (strpos($tag, $string) === 0) {
          $matches[] = ['value' => $tag, 'label' => Html::escape($tag)];
          if (count($matches) >= 10) {
            break;
          }
198 199 200 201 202 203 204 205 206 207
        }
      }
    }

    return new JsonResponse($matches);
  }

  /**
   * Returns the form to edit a view.
   *
208
   * @param \Drupal\views_ui\ViewUI $view
209
   *   The view to be edited.
210 211 212 213 214 215 216
   * @param string|null $display_id
   *   (optional) The display ID being edited. Defaults to NULL, which will load
   *   the first available display.
   *
   * @return array
   *   An array containing the Views edit and preview forms.
   */
217
  public function edit(ViewUI $view, $display_id = NULL) {
218
    $name = $view->label();
219
    $data = $this->viewsData->get($view->get('base_table'));
220

221 222 223
    if (isset($data['table']['base']['title'])) {
      $name .= ' (' . $data['table']['base']['title'] . ')';
    }
224
    $build['#title'] = $name;
225

226 227
    $build['edit'] = $this->entityFormBuilder()->getForm($view, 'edit', array('display_id' => $display_id));
    $build['preview'] = $this->entityFormBuilder()->getForm($view, 'preview', array('display_id' => $display_id));
228 229 230 231
    return $build;
  }

}