Backup of db before drupal security update
[yaffs-website] / web / core / modules / views_ui / src / Form / Ajax / ConfigHandler.php
1 <?php
2
3 namespace Drupal\views_ui\Form\Ajax;
4
5 use Drupal\Core\Form\FormStateInterface;
6 use Drupal\views\ViewEntityInterface;
7 use Drupal\views\ViewExecutable;
8 use Drupal\views\Views;
9 use Symfony\Component\HttpFoundation\Request;
10
11 /**
12  * Provides a form for configuring an item in the Views UI.
13  */
14 class ConfigHandler extends ViewsFormBase {
15
16   /**
17    * Constructs a new ConfigHandler object.
18    */
19   public function __construct($type = NULL, $id = NULL) {
20     $this->setType($type);
21     $this->setID($id);
22   }
23
24   /**
25    * {@inheritdoc}
26    */
27   public function getFormKey() {
28     return 'handler';
29   }
30
31   /**
32    * {@inheritdoc}
33    */
34   public function getForm(ViewEntityInterface $view, $display_id, $js, $type = NULL, $id = NULL) {
35     $this->setType($type);
36     $this->setID($id);
37     return parent::getForm($view, $display_id, $js);
38   }
39
40   /**
41    * {@inheritdoc}
42    */
43   public function getFormId() {
44     return 'views_ui_config_item_form';
45   }
46
47   /**
48    * {@inheritdoc}
49    */
50   public function buildForm(array $form, FormStateInterface $form_state, Request $request = NULL) {
51     /** @var \Drupal\views\Entity\View $view */
52     $view = $form_state->get('view');
53     $display_id = $form_state->get('display_id');
54     $type = $form_state->get('type');
55     $id = $form_state->get('id');
56
57     $form = [
58       'options' => [
59         '#tree' => TRUE,
60         '#theme_wrappers' => ['container'],
61         '#attributes' => ['class' => ['scroll'], 'data-drupal-views-scroll' => TRUE],
62       ],
63     ];
64     $executable = $view->getExecutable();
65     $save_ui_cache = FALSE;
66     if (!$executable->setDisplay($display_id)) {
67       $form['markup'] = ['#markup' => $this->t('Invalid display id @display', ['@display' => $display_id])];
68       return $form;
69     }
70     $item = $executable->getHandler($display_id, $type, $id);
71
72     if ($item) {
73       $handler = $executable->display_handler->getHandler($type, $id);
74       if (empty($handler)) {
75         $form['markup'] = ['#markup' => $this->t("Error: handler for @table > @field doesn't exist!", ['@table' => $item['table'], '@field' => $item['field']])];
76       }
77       else {
78         $types = ViewExecutable::getHandlerTypes();
79
80         // If this item can come from the default display, show a dropdown
81         // that lets the user choose which display the changes should apply to.
82         if ($executable->display_handler->defaultableSections($types[$type]['plural'])) {
83           $section = $types[$type]['plural'];
84           $form_state->set('section', $section);
85           views_ui_standard_display_dropdown($form, $form_state, $section);
86         }
87
88         // A whole bunch of code to figure out what relationships are valid for
89         // this item.
90         $relationships = $executable->display_handler->getOption('relationships');
91         $relationship_options = [];
92
93         foreach ($relationships as $relationship) {
94           // relationships can't link back to self. But also, due to ordering,
95           // relationships can only link to prior relationships.
96           if ($type == 'relationship' && $id == $relationship['id']) {
97             break;
98           }
99           $relationship_handler = Views::handlerManager('relationship')->getHandler($relationship);
100           // ignore invalid/broken relationships.
101           if (empty($relationship_handler)) {
102             continue;
103           }
104
105           // If this relationship is valid for this type, add it to the list.
106           $data = Views::viewsData()->get($relationship['table']);
107           if (isset($data[$relationship['field']]['relationship']['base']) && $base = $data[$relationship['field']]['relationship']['base']) {
108             $base_fields = Views::viewsDataHelper()->fetchFields($base, $type, $executable->display_handler->useGroupBy());
109             if (isset($base_fields[$item['table'] . '.' . $item['field']])) {
110               $relationship_handler->init($executable, $executable->display_handler, $relationship);
111               $relationship_options[$relationship['id']] = $relationship_handler->adminLabel();
112             }
113           }
114         }
115
116         if (!empty($relationship_options)) {
117           // Make sure the existing relationship is even valid. If not, force
118           // it to none.
119           $base_fields = Views::viewsDataHelper()->fetchFields($view->get('base_table'), $type, $executable->display_handler->useGroupBy());
120           if (isset($base_fields[$item['table'] . '.' . $item['field']])) {
121             $relationship_options = array_merge(['none' => $this->t('Do not use a relationship')], $relationship_options);
122           }
123           $rel = empty($item['relationship']) ? 'none' : $item['relationship'];
124           if (empty($relationship_options[$rel])) {
125             // Pick the first relationship.
126             $rel = key($relationship_options);
127             // We want this relationship option to get saved even if the user
128             // skips submitting the form.
129             $executable->setHandlerOption($display_id, $type, $id, 'relationship', $rel);
130             $save_ui_cache = TRUE;
131             // Re-initialize with new relationship.
132             $item['relationship'] = $rel;
133             $handler->init($executable, $executable->display_handler, $item);
134           }
135
136           $form['options']['relationship'] = [
137             '#type' => 'select',
138             '#title' => $this->t('Relationship'),
139             '#options' => $relationship_options,
140             '#default_value' => $rel,
141             '#weight' => -500,
142           ];
143         }
144         else {
145           $form['options']['relationship'] = [
146             '#type' => 'value',
147             '#value' => 'none',
148           ];
149         }
150
151         $form['#title'] = $this->t('Configure @type: @item', ['@type' => $types[$type]['lstitle'], '@item' => $handler->adminLabel()]);
152
153         if (!empty($handler->definition['help'])) {
154           $form['options']['form_description'] = [
155             '#markup' => $handler->definition['help'],
156             '#theme_wrappers' => ['container'],
157             '#attributes' => ['class' => ['js-form-item form-item description']],
158             '#weight' => -1000,
159           ];
160         }
161
162         $form['#section'] = $display_id . '-' . $type . '-' . $id;
163
164         // Get form from the handler.
165         $handler->buildOptionsForm($form['options'], $form_state);
166         $form_state->set('handler', $handler);
167       }
168
169       $name = $form_state->get('update_name');
170
171       $view->getStandardButtons($form, $form_state, 'views_ui_config_item_form', $name);
172       // Add a 'remove' button.
173       $form['actions']['remove'] = [
174         '#type' => 'submit',
175         '#value' => $this->t('Remove'),
176         '#submit' => [[$this, 'remove']],
177         '#limit_validation_errors' => [['override']],
178         '#button_type' => 'danger',
179       ];
180     }
181
182     if ($save_ui_cache) {
183       $view->cacheSet();
184     }
185
186     return $form;
187   }
188
189   /**
190    * {@inheritdoc}
191    */
192   public function validateForm(array &$form, FormStateInterface $form_state) {
193     $form_state->get('handler')->validateOptionsForm($form['options'], $form_state);
194
195     if ($form_state->getErrors()) {
196       $form_state->set('rerender', TRUE);
197     }
198   }
199
200   /**
201    * {@inheritdoc}
202    */
203   public function submitForm(array &$form, FormStateInterface $form_state) {
204     $view = $form_state->get('view');
205     $display_id = $form_state->get('display_id');
206     $id = $form_state->get('id');
207     $handler = $form_state->get('handler');
208
209     // Run it through the handler's submit function.
210     $handler->submitOptionsForm($form['options'], $form_state);
211     $item = $handler->options;
212     $types = ViewExecutable::getHandlerTypes();
213
214     // For footer/header $handler_type is area but $type is footer/header.
215     // For all other handle types it's the same.
216     $handler_type = $type = $form_state->get('type');
217     if (!empty($types[$type]['type'])) {
218       $handler_type = $types[$type]['type'];
219     }
220
221     $override = NULL;
222     $executable = $view->getExecutable();
223     if ($executable->display_handler->useGroupBy() && !empty($item['group_type'])) {
224       if (empty($executable->query)) {
225         $executable->initQuery();
226       }
227       $aggregate = $executable->query->getAggregationInfo();
228       if (!empty($aggregate[$item['group_type']]['handler'][$type])) {
229         $override = $aggregate[$item['group_type']]['handler'][$type];
230       }
231     }
232
233     // Create a new handler and unpack the options from the form onto it. We
234     // can use that for storage.
235     $handler = Views::handlerManager($handler_type)->getHandler($item, $override);
236     $handler->init($executable, $executable->display_handler, $item);
237
238     // Add the incoming options to existing options because items using
239     // the extra form may not have everything in the form here.
240     $options = $handler->submitFormCalculateOptions($handler->options, $form_state->getValue('options', []));
241
242     // This unpacks only options that are in the definition, ensuring random
243     // extra stuff on the form is not sent through.
244     $handler->unpackOptions($handler->options, $options, NULL, FALSE);
245
246     // Store the item back on the view
247     $executable->setHandler($display_id, $type, $id, $handler->options);
248
249     // Ensure any temporary options are removed.
250     if (isset($view->temporary_options[$type][$id])) {
251       unset($view->temporary_options[$type][$id]);
252     }
253
254     // Write to cache
255     $view->cacheSet();
256   }
257
258   /**
259    * Submit handler for removing an item from a view
260    */
261   public function remove(&$form, FormStateInterface $form_state) {
262     $view = $form_state->get('view');
263     $display_id = $form_state->get('display_id');
264     $type = $form_state->get('type');
265     $id = $form_state->get('id');
266     // Store the item back on the view
267     list($was_defaulted, $is_defaulted) = $view->getOverrideValues($form, $form_state);
268     $executable = $view->getExecutable();
269     // If the display selection was changed toggle the override value.
270     if ($was_defaulted != $is_defaulted) {
271       $display = &$executable->displayHandlers->get($display_id);
272       $display->optionsOverride($form, $form_state);
273     }
274     $executable->removeHandler($display_id, $type, $id);
275
276     // Write to cache
277     $view->cacheSet();
278   }
279
280 }