ViewFormBase.php 6.68 KB
Newer Older
1
2
3
4
<?php

/**
 * @file
5
 * Contains Drupal\views_ui\ViewFormBase.
6
7
8
9
 */

namespace Drupal\views_ui;

10
use Drupal\Core\Entity\EntityForm;
11
use Drupal\Core\Form\FormStateInterface;
12
13
14
15
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;

/**
16
 * Base form for Views forms.
17
 */
18
abstract class ViewFormBase extends EntityForm {
19

20
  /**
21
22
23
24
25
26
27
   * The name of the display used by the form.
   *
   * @var string
   */
  protected $displayID;

  /**
28
   * {@inheritdoc}
29
   */
30
  public function init(FormStateInterface $form_state) {
31
32
    parent::init($form_state);

33
    // @todo Remove the need for this.
34
    $form_state->loadInclude('views_ui', 'inc', 'admin');
35
    $form_state->set('view', $this->entity);
36
37
  }

38
39
40
41
42
43
44
45
46
47
48
  /**
   * {@inheritdoc}
   */
  public function buildForm(array $form, FormStateInterface $form_state, $display_id = NULL) {
    if (isset($display_id) && $form_state->has('display_id') && ($display_id !== $form_state->get('display_id'))) {
      throw new \InvalidArgumentException('Mismatch between $form_state->get(\'display_id\') and $display_id.');
    }
    $this->displayID = $form_state->has('display_id') ? $form_state->get('display_id') : $display_id;
    return parent::buildForm($form, $form_state);
  }

49
  /**
50
   * {@inheritdoc}
51
   */
52
  protected function prepareEntity() {
53
    // Determine the displays available for editing.
54
    if ($tabs = $this->getDisplayTabs($this->entity)) {
55
      if (empty($this->displayID)) {
56
57
58
        // If a display isn't specified, use the first one after sorting by
        // #weight.
        uasort($tabs, 'Drupal\Component\Utility\SortArray::sortByWeightProperty');
59
60
        foreach ($tabs as $id => $tab) {
          if (!isset($tab['#access']) || $tab['#access']) {
61
            $this->displayID = $id;
62
63
64
65
66
67
            break;
          }
        }
      }
      // If a display is specified, but we don't have access to it, return
      // an access denied page.
68
      if ($this->displayID && !isset($tabs[$this->displayID])) {
69
70
        throw new NotFoundHttpException();
      }
71
      elseif ($this->displayID && (isset($tabs[$this->displayID]['#access']) && !$tabs[$this->displayID]['#access'])) {
72
73
74
75
        throw new AccessDeniedHttpException();
      }

    }
76
    elseif ($this->displayID) {
77
78
79
80
81
82
83
84
85
      throw new NotFoundHttpException();
    }
  }

  /**
   * Creates an array of Views admin CSS for adding or attaching.
   *
   * This returns an array of arrays. Each array represents a single
   * file. The array format is:
86
87
   * - file: The fully qualified name of the file to send to _drupal_add_css
   * - options: An array of options to pass to _drupal_add_css.
88
89
90
91
   */
  public static function getAdminCSS() {
    $module_path = drupal_get_path('module', 'views_ui');
    $list = array();
92
93
    $list[$module_path . '/css/views_ui.admin.css'] = array();
    $list[$module_path . '/css/views_ui.admin.theme.css'] = array();
94

95
    if (\Drupal::moduleHandler()->moduleExists('contextual')) {
96
      $list[$module_path . '/css/views_ui.contextual.css'] = array();
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
    }

    return $list;
  }

  /**
   * Adds tabs for navigating across Displays when editing a View.
   *
   * This function can be called from hook_menu_local_tasks_alter() to implement
   * these tabs as secondary local tasks, or it can be called from elsewhere if
   * having them as secondary local tasks isn't desired. The caller is responsible
   * for setting the active tab's #active property to TRUE.
   *
   * @param $display_id
   *   The display_id which is edited on the current request.
   */
  public function getDisplayTabs(ViewUI $view) {
114
    $executable = $view->getExecutable();
115
    $executable->initDisplay();
116
    $display_id = $this->displayID;
117
118
119
    $tabs = array();

    // Create a tab for each display.
120
121
122
123
124
125
126
127
    foreach ($view->get('display') as $id => $display) {
      // Get an instance of the display plugin, to make sure it will work in the
      // UI.
      $display_plugin = $executable->displayHandlers->get($id);
      if (empty($display_plugin)) {
        continue;
      }

128
129
      $tabs[$id] = array(
        '#theme' => 'menu_local_task',
130
        '#weight' => $display['position'],
131
132
133
        '#link' => array(
          'title' => $this->getDisplayLabel($view, $id),
          'localized_options' => array(),
134
135
          'url' => $view->urlInfo('edit-display-form')->setRouteParameter('display_id', $id),
        ),
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
      );
      if (!empty($display['deleted'])) {
        $tabs[$id]['#link']['localized_options']['attributes']['class'][] = 'views-display-deleted-link';
      }
      if (isset($display['display_options']['enabled']) && !$display['display_options']['enabled']) {
        $tabs[$id]['#link']['localized_options']['attributes']['class'][] = 'views-display-disabled-link';
      }
    }

    // If the default display isn't supposed to be shown, don't display its tab, unless it's the only display.
    if ((!$this->isDefaultDisplayShown($view) && $display_id != 'default') && count($tabs) > 1) {
      $tabs['default']['#access'] = FALSE;
    }

    // Mark the display tab as red to show validation errors.
151
    $errors = $executable->validate();
152
    foreach ($view->get('display') as $id => $display) {
153
      if (!empty($errors[$id])) {
154
155
156
157
        // Always show the tab.
        $tabs[$id]['#access'] = TRUE;
        // Add a class to mark the error and a title to make a hover tip.
        $tabs[$id]['#link']['localized_options']['attributes']['class'][] = 'error';
158
        $tabs[$id]['#link']['localized_options']['attributes']['title'] = $this->t('This display has one or more validation errors.');
159
160
161
162
163
164
165
166
167
168
169
      }
    }

    return $tabs;
  }

  /**
   * Controls whether or not the default display should have its own tab on edit.
   */
  public function isDefaultDisplayShown(ViewUI $view) {
    // Always show the default display for advanced users who prefer that mode.
170
    $advanced_mode = \Drupal::config('views.settings')->get('ui.show.master_display');
171
172
    // For other users, show the default display only if there are no others, and
    // hide it if there's at least one "real" display.
173
    $additional_displays = (count($view->getExecutable()->displayHandlers) == 1);
174
175
176
177
178
179
180
181
182
183
184

    return $advanced_mode || $additional_displays;
  }

  /**
   * Placeholder function for overriding $display['display_title'].
   *
   * @todo Remove this function once editing the display title is possible.
   */
  public function getDisplayLabel(ViewUI $view, $display_id, $check_changed = TRUE) {
    $display = $view->get('display');
185
    $title = $display_id == 'default' ? $this->t('Master') : $display[$display_id]['display_title'];
186
187
188
189
190
191
192
193
194
195
196
    $title = views_ui_truncate($title, 25);

    if ($check_changed && !empty($view->changed_display[$display_id])) {
      $changed = '*';
      $title = $title . $changed;
    }

    return $title;
  }

}