Chris@0
|
1 <?php
|
Chris@0
|
2
|
Chris@0
|
3 namespace Drupal\views_ui;
|
Chris@0
|
4
|
Chris@0
|
5 use Drupal\Core\Entity\EntityForm;
|
Chris@0
|
6 use Drupal\Core\Form\FormStateInterface;
|
Chris@0
|
7 use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
|
Chris@0
|
8 use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;
|
Chris@0
|
9
|
Chris@0
|
10 /**
|
Chris@0
|
11 * Base form for Views forms.
|
Chris@0
|
12 */
|
Chris@0
|
13 abstract class ViewFormBase extends EntityForm {
|
Chris@0
|
14
|
Chris@0
|
15 /**
|
Chris@0
|
16 * The name of the display used by the form.
|
Chris@0
|
17 *
|
Chris@0
|
18 * @var string
|
Chris@0
|
19 */
|
Chris@0
|
20 protected $displayID;
|
Chris@0
|
21
|
Chris@0
|
22 /**
|
Chris@0
|
23 * {@inheritdoc}
|
Chris@0
|
24 */
|
Chris@0
|
25 public function init(FormStateInterface $form_state) {
|
Chris@0
|
26 parent::init($form_state);
|
Chris@0
|
27
|
Chris@0
|
28 // @todo Remove the need for this.
|
Chris@0
|
29 $form_state->loadInclude('views_ui', 'inc', 'admin');
|
Chris@0
|
30 $form_state->set('view', $this->entity);
|
Chris@0
|
31 }
|
Chris@0
|
32
|
Chris@0
|
33 /**
|
Chris@0
|
34 * {@inheritdoc}
|
Chris@0
|
35 */
|
Chris@0
|
36 public function buildForm(array $form, FormStateInterface $form_state, $display_id = NULL) {
|
Chris@0
|
37 if (isset($display_id) && $form_state->has('display_id') && ($display_id !== $form_state->get('display_id'))) {
|
Chris@0
|
38 throw new \InvalidArgumentException('Mismatch between $form_state->get(\'display_id\') and $display_id.');
|
Chris@0
|
39 }
|
Chris@0
|
40 $this->displayID = $form_state->has('display_id') ? $form_state->get('display_id') : $display_id;
|
Chris@0
|
41 return parent::buildForm($form, $form_state);
|
Chris@0
|
42 }
|
Chris@0
|
43
|
Chris@0
|
44 /**
|
Chris@0
|
45 * {@inheritdoc}
|
Chris@0
|
46 */
|
Chris@0
|
47 protected function prepareEntity() {
|
Chris@0
|
48 // Determine the displays available for editing.
|
Chris@0
|
49 if ($tabs = $this->getDisplayTabs($this->entity)) {
|
Chris@0
|
50 if (empty($this->displayID)) {
|
Chris@0
|
51 // If a display isn't specified, use the first one after sorting by
|
Chris@0
|
52 // #weight.
|
Chris@0
|
53 uasort($tabs, 'Drupal\Component\Utility\SortArray::sortByWeightProperty');
|
Chris@0
|
54 foreach ($tabs as $id => $tab) {
|
Chris@0
|
55 if (!isset($tab['#access']) || $tab['#access']) {
|
Chris@0
|
56 $this->displayID = $id;
|
Chris@0
|
57 break;
|
Chris@0
|
58 }
|
Chris@0
|
59 }
|
Chris@0
|
60 }
|
Chris@0
|
61 // If a display is specified, but we don't have access to it, return
|
Chris@0
|
62 // an access denied page.
|
Chris@0
|
63 if ($this->displayID && !isset($tabs[$this->displayID])) {
|
Chris@0
|
64 throw new NotFoundHttpException();
|
Chris@0
|
65 }
|
Chris@0
|
66 elseif ($this->displayID && (isset($tabs[$this->displayID]['#access']) && !$tabs[$this->displayID]['#access'])) {
|
Chris@0
|
67 throw new AccessDeniedHttpException();
|
Chris@0
|
68 }
|
Chris@0
|
69
|
Chris@0
|
70 }
|
Chris@0
|
71 elseif ($this->displayID) {
|
Chris@0
|
72 throw new NotFoundHttpException();
|
Chris@0
|
73 }
|
Chris@0
|
74 }
|
Chris@0
|
75
|
Chris@0
|
76 /**
|
Chris@0
|
77 * Adds tabs for navigating across Displays when editing a View.
|
Chris@0
|
78 *
|
Chris@0
|
79 * This function can be called from hook_menu_local_tasks_alter() to implement
|
Chris@0
|
80 * these tabs as secondary local tasks, or it can be called from elsewhere if
|
Chris@0
|
81 * having them as secondary local tasks isn't desired. The caller is responsible
|
Chris@0
|
82 * for setting the active tab's #active property to TRUE.
|
Chris@0
|
83 *
|
Chris@0
|
84 * @param $display_id
|
Chris@0
|
85 * The display_id which is edited on the current request.
|
Chris@0
|
86 */
|
Chris@0
|
87 public function getDisplayTabs(ViewUI $view) {
|
Chris@0
|
88 $executable = $view->getExecutable();
|
Chris@0
|
89 $executable->initDisplay();
|
Chris@0
|
90 $display_id = $this->displayID;
|
Chris@0
|
91 $tabs = [];
|
Chris@0
|
92
|
Chris@0
|
93 // Create a tab for each display.
|
Chris@0
|
94 foreach ($view->get('display') as $id => $display) {
|
Chris@0
|
95 // Get an instance of the display plugin, to make sure it will work in the
|
Chris@0
|
96 // UI.
|
Chris@0
|
97 $display_plugin = $executable->displayHandlers->get($id);
|
Chris@0
|
98 if (empty($display_plugin)) {
|
Chris@0
|
99 continue;
|
Chris@0
|
100 }
|
Chris@0
|
101
|
Chris@0
|
102 $tabs[$id] = [
|
Chris@0
|
103 '#theme' => 'menu_local_task',
|
Chris@0
|
104 '#weight' => $display['position'],
|
Chris@0
|
105 '#link' => [
|
Chris@0
|
106 'title' => $this->getDisplayLabel($view, $id),
|
Chris@0
|
107 'localized_options' => [],
|
Chris@18
|
108 'url' => $view->toUrl('edit-display-form')->setRouteParameter('display_id', $id),
|
Chris@0
|
109 ],
|
Chris@0
|
110 ];
|
Chris@0
|
111 if (!empty($display['deleted'])) {
|
Chris@0
|
112 $tabs[$id]['#link']['localized_options']['attributes']['class'][] = 'views-display-deleted-link';
|
Chris@0
|
113 }
|
Chris@0
|
114 if (isset($display['display_options']['enabled']) && !$display['display_options']['enabled']) {
|
Chris@0
|
115 $tabs[$id]['#link']['localized_options']['attributes']['class'][] = 'views-display-disabled-link';
|
Chris@0
|
116 }
|
Chris@0
|
117 }
|
Chris@0
|
118
|
Chris@0
|
119 // If the default display isn't supposed to be shown, don't display its tab, unless it's the only display.
|
Chris@0
|
120 if ((!$this->isDefaultDisplayShown($view) && $display_id != 'default') && count($tabs) > 1) {
|
Chris@0
|
121 $tabs['default']['#access'] = FALSE;
|
Chris@0
|
122 }
|
Chris@0
|
123
|
Chris@0
|
124 // Mark the display tab as red to show validation errors.
|
Chris@0
|
125 $errors = $executable->validate();
|
Chris@0
|
126 foreach ($view->get('display') as $id => $display) {
|
Chris@0
|
127 if (!empty($errors[$id])) {
|
Chris@0
|
128 // Always show the tab.
|
Chris@0
|
129 $tabs[$id]['#access'] = TRUE;
|
Chris@0
|
130 // Add a class to mark the error and a title to make a hover tip.
|
Chris@0
|
131 $tabs[$id]['#link']['localized_options']['attributes']['class'][] = 'error';
|
Chris@0
|
132 $tabs[$id]['#link']['localized_options']['attributes']['title'] = $this->t('This display has one or more validation errors.');
|
Chris@0
|
133 }
|
Chris@0
|
134 }
|
Chris@0
|
135
|
Chris@0
|
136 return $tabs;
|
Chris@0
|
137 }
|
Chris@0
|
138
|
Chris@0
|
139 /**
|
Chris@0
|
140 * Controls whether or not the default display should have its own tab on edit.
|
Chris@0
|
141 */
|
Chris@0
|
142 public function isDefaultDisplayShown(ViewUI $view) {
|
Chris@0
|
143 // Always show the default display for advanced users who prefer that mode.
|
Chris@0
|
144 $advanced_mode = \Drupal::config('views.settings')->get('ui.show.master_display');
|
Chris@0
|
145 // For other users, show the default display only if there are no others, and
|
Chris@0
|
146 // hide it if there's at least one "real" display.
|
Chris@0
|
147 $additional_displays = (count($view->getExecutable()->displayHandlers) == 1);
|
Chris@0
|
148
|
Chris@0
|
149 return $advanced_mode || $additional_displays;
|
Chris@0
|
150 }
|
Chris@0
|
151
|
Chris@0
|
152 /**
|
Chris@0
|
153 * Placeholder function for overriding $display['display_title'].
|
Chris@0
|
154 *
|
Chris@0
|
155 * @todo Remove this function once editing the display title is possible.
|
Chris@0
|
156 */
|
Chris@0
|
157 public function getDisplayLabel(ViewUI $view, $display_id, $check_changed = TRUE) {
|
Chris@0
|
158 $display = $view->get('display');
|
Chris@0
|
159 $title = $display_id == 'default' ? $this->t('Master') : $display[$display_id]['display_title'];
|
Chris@0
|
160 $title = views_ui_truncate($title, 25);
|
Chris@0
|
161
|
Chris@0
|
162 if ($check_changed && !empty($view->changed_display[$display_id])) {
|
Chris@0
|
163 $changed = '*';
|
Chris@0
|
164 $title = $title . $changed;
|
Chris@0
|
165 }
|
Chris@0
|
166
|
Chris@0
|
167 return $title;
|
Chris@0
|
168 }
|
Chris@0
|
169
|
Chris@0
|
170 }
|