Chris@0
|
1 <?php
|
Chris@0
|
2
|
Chris@0
|
3 namespace Drupal\views_ui;
|
Chris@0
|
4
|
Chris@0
|
5 use Drupal\Component\Utility\Html;
|
Chris@0
|
6 use Drupal\Component\Utility\Timer;
|
Chris@0
|
7 use Drupal\Core\EventSubscriber\AjaxResponseSubscriber;
|
Chris@0
|
8 use Drupal\Core\Form\FormStateInterface;
|
Chris@0
|
9 use Drupal\views\Views;
|
Chris@0
|
10 use Drupal\Core\Entity\EntityStorageInterface;
|
Chris@0
|
11 use Drupal\views\ViewExecutable;
|
Chris@0
|
12 use Drupal\Core\Database\Database;
|
Chris@0
|
13 use Drupal\Core\Session\AccountInterface;
|
Chris@0
|
14 use Drupal\views\Plugin\views\query\Sql;
|
Chris@0
|
15 use Drupal\views\Entity\View;
|
Chris@0
|
16 use Drupal\views\ViewEntityInterface;
|
Chris@0
|
17 use Symfony\Cmf\Component\Routing\RouteObjectInterface;
|
Chris@0
|
18 use Symfony\Component\HttpFoundation\ParameterBag;
|
Chris@0
|
19 use Symfony\Component\HttpFoundation\Request;
|
Chris@0
|
20
|
Chris@0
|
21 /**
|
Chris@0
|
22 * Stores UI related temporary settings.
|
Chris@0
|
23 */
|
Chris@0
|
24 class ViewUI implements ViewEntityInterface {
|
Chris@0
|
25
|
Chris@0
|
26 /**
|
Chris@0
|
27 * Indicates if a view is currently being edited.
|
Chris@0
|
28 *
|
Chris@0
|
29 * @var bool
|
Chris@0
|
30 */
|
Chris@0
|
31 public $editing = FALSE;
|
Chris@0
|
32
|
Chris@0
|
33 /**
|
Chris@0
|
34 * Stores an array of displays that have been changed.
|
Chris@0
|
35 *
|
Chris@0
|
36 * @var array
|
Chris@0
|
37 */
|
Chris@0
|
38 public $changed_display;
|
Chris@0
|
39
|
Chris@0
|
40 /**
|
Chris@0
|
41 * How long the view takes to render in microseconds.
|
Chris@0
|
42 *
|
Chris@0
|
43 * @var float
|
Chris@0
|
44 */
|
Chris@0
|
45 public $render_time;
|
Chris@0
|
46
|
Chris@0
|
47 /**
|
Chris@0
|
48 * If this view is locked for editing.
|
Chris@0
|
49 *
|
Chris@0
|
50 * If this view is locked it will contain the result of
|
Chris@0
|
51 * \Drupal\Core\TempStore\SharedTempStore::getMetadata(). Which can be a stdClass or
|
Chris@0
|
52 * NULL.
|
Chris@0
|
53 *
|
Chris@0
|
54 * @var stdClass
|
Chris@0
|
55 */
|
Chris@0
|
56 public $lock;
|
Chris@0
|
57
|
Chris@0
|
58 /**
|
Chris@0
|
59 * If this view has been changed.
|
Chris@0
|
60 *
|
Chris@0
|
61 * @var bool
|
Chris@0
|
62 */
|
Chris@0
|
63 public $changed;
|
Chris@0
|
64
|
Chris@0
|
65 /**
|
Chris@0
|
66 * Stores options temporarily while editing.
|
Chris@0
|
67 *
|
Chris@0
|
68 * @var array
|
Chris@0
|
69 */
|
Chris@0
|
70 public $temporary_options;
|
Chris@0
|
71
|
Chris@0
|
72 /**
|
Chris@0
|
73 * Stores a stack of UI forms to display.
|
Chris@0
|
74 *
|
Chris@0
|
75 * @var array
|
Chris@0
|
76 */
|
Chris@0
|
77 public $stack;
|
Chris@0
|
78
|
Chris@0
|
79 /**
|
Chris@0
|
80 * Is the view run in a context of the preview in the admin interface.
|
Chris@0
|
81 *
|
Chris@0
|
82 * @var bool
|
Chris@0
|
83 */
|
Chris@0
|
84 public $live_preview;
|
Chris@0
|
85
|
Chris@0
|
86 public $renderPreview = FALSE;
|
Chris@0
|
87
|
Chris@0
|
88 /**
|
Chris@0
|
89 * The View storage object.
|
Chris@0
|
90 *
|
Chris@0
|
91 * @var \Drupal\views\ViewEntityInterface
|
Chris@0
|
92 */
|
Chris@0
|
93 protected $storage;
|
Chris@0
|
94
|
Chris@0
|
95 /**
|
Chris@0
|
96 * Stores a list of database queries run beside the main one from views.
|
Chris@0
|
97 *
|
Chris@0
|
98 * @var array
|
Chris@0
|
99 *
|
Chris@0
|
100 * @see \Drupal\Core\Database\Log
|
Chris@0
|
101 */
|
Chris@0
|
102 protected $additionalQueries;
|
Chris@0
|
103
|
Chris@0
|
104 /**
|
Chris@0
|
105 * Contains an array of form keys and their respective classes.
|
Chris@0
|
106 *
|
Chris@0
|
107 * @var array
|
Chris@0
|
108 */
|
Chris@0
|
109 public static $forms = [
|
Chris@0
|
110 'add-handler' => '\Drupal\views_ui\Form\Ajax\AddItem',
|
Chris@0
|
111 'analyze' => '\Drupal\views_ui\Form\Ajax\Analyze',
|
Chris@0
|
112 'handler' => '\Drupal\views_ui\Form\Ajax\ConfigHandler',
|
Chris@0
|
113 'handler-extra' => '\Drupal\views_ui\Form\Ajax\ConfigHandlerExtra',
|
Chris@0
|
114 'handler-group' => '\Drupal\views_ui\Form\Ajax\ConfigHandlerGroup',
|
Chris@0
|
115 'display' => '\Drupal\views_ui\Form\Ajax\Display',
|
Chris@0
|
116 'edit-details' => '\Drupal\views_ui\Form\Ajax\EditDetails',
|
Chris@0
|
117 'rearrange' => '\Drupal\views_ui\Form\Ajax\Rearrange',
|
Chris@0
|
118 'rearrange-filter' => '\Drupal\views_ui\Form\Ajax\RearrangeFilter',
|
Chris@0
|
119 'reorder-displays' => '\Drupal\views_ui\Form\Ajax\ReorderDisplays',
|
Chris@0
|
120 ];
|
Chris@0
|
121
|
Chris@0
|
122 /**
|
Chris@0
|
123 * Whether the config is being created, updated or deleted through the
|
Chris@0
|
124 * import process.
|
Chris@0
|
125 *
|
Chris@0
|
126 * @var bool
|
Chris@0
|
127 */
|
Chris@0
|
128 private $isSyncing = FALSE;
|
Chris@0
|
129
|
Chris@0
|
130 /**
|
Chris@0
|
131 * Whether the config is being deleted through the uninstall process.
|
Chris@0
|
132 *
|
Chris@0
|
133 * @var bool
|
Chris@0
|
134 */
|
Chris@0
|
135 private $isUninstalling = FALSE;
|
Chris@0
|
136
|
Chris@0
|
137 /**
|
Chris@0
|
138 * Constructs a View UI object.
|
Chris@0
|
139 *
|
Chris@0
|
140 * @param \Drupal\views\ViewEntityInterface $storage
|
Chris@0
|
141 * The View storage object to wrap.
|
Chris@0
|
142 */
|
Chris@0
|
143 public function __construct(ViewEntityInterface $storage) {
|
Chris@0
|
144 $this->entityType = 'view';
|
Chris@0
|
145 $this->storage = $storage;
|
Chris@0
|
146 }
|
Chris@0
|
147
|
Chris@0
|
148 /**
|
Chris@0
|
149 * {@inheritdoc}
|
Chris@0
|
150 */
|
Chris@0
|
151 public function get($property_name, $langcode = NULL) {
|
Chris@0
|
152 if (property_exists($this->storage, $property_name)) {
|
Chris@0
|
153 return $this->storage->get($property_name, $langcode);
|
Chris@0
|
154 }
|
Chris@0
|
155
|
Chris@0
|
156 return isset($this->{$property_name}) ? $this->{$property_name} : NULL;
|
Chris@0
|
157 }
|
Chris@0
|
158
|
Chris@0
|
159 /**
|
Chris@0
|
160 * {@inheritdoc}
|
Chris@0
|
161 */
|
Chris@0
|
162 public function setStatus($status) {
|
Chris@0
|
163 return $this->storage->setStatus($status);
|
Chris@0
|
164 }
|
Chris@0
|
165
|
Chris@0
|
166 /**
|
Chris@0
|
167 * {@inheritdoc}
|
Chris@0
|
168 */
|
Chris@0
|
169 public function set($property_name, $value, $notify = TRUE) {
|
Chris@0
|
170 if (property_exists($this->storage, $property_name)) {
|
Chris@0
|
171 $this->storage->set($property_name, $value);
|
Chris@0
|
172 }
|
Chris@0
|
173 else {
|
Chris@0
|
174 $this->{$property_name} = $value;
|
Chris@0
|
175 }
|
Chris@0
|
176 }
|
Chris@0
|
177
|
Chris@0
|
178 /**
|
Chris@0
|
179 * {@inheritdoc}
|
Chris@0
|
180 */
|
Chris@0
|
181 public function setSyncing($syncing) {
|
Chris@0
|
182 $this->isSyncing = $syncing;
|
Chris@0
|
183 }
|
Chris@0
|
184
|
Chris@0
|
185 /**
|
Chris@0
|
186 * {@inheritdoc}
|
Chris@0
|
187 */
|
Chris@0
|
188 public function setUninstalling($isUninstalling) {
|
Chris@0
|
189 $this->isUninstalling = $isUninstalling;
|
Chris@0
|
190 }
|
Chris@0
|
191
|
Chris@0
|
192 /**
|
Chris@0
|
193 * {@inheritdoc}
|
Chris@0
|
194 */
|
Chris@0
|
195 public function isSyncing() {
|
Chris@0
|
196 return $this->isSyncing;
|
Chris@0
|
197 }
|
Chris@0
|
198
|
Chris@0
|
199 /**
|
Chris@0
|
200 * {@inheritdoc}
|
Chris@0
|
201 */
|
Chris@0
|
202 public function isUninstalling() {
|
Chris@0
|
203 return $this->isUninstalling;
|
Chris@0
|
204 }
|
Chris@0
|
205
|
Chris@0
|
206 /**
|
Chris@0
|
207 * Basic submit handler applicable to all 'standard' forms.
|
Chris@0
|
208 *
|
Chris@0
|
209 * This submit handler determines whether the user wants the submitted changes
|
Chris@0
|
210 * to apply to the default display or to the current display, and dispatches
|
Chris@0
|
211 * control appropriately.
|
Chris@0
|
212 */
|
Chris@0
|
213 public function standardSubmit($form, FormStateInterface $form_state) {
|
Chris@0
|
214 // Determine whether the values the user entered are intended to apply to
|
Chris@0
|
215 // the current display or the default display.
|
Chris@0
|
216
|
Chris@0
|
217 list($was_defaulted, $is_defaulted, $revert) = $this->getOverrideValues($form, $form_state);
|
Chris@0
|
218
|
Chris@0
|
219 // Based on the user's choice in the display dropdown, determine which display
|
Chris@0
|
220 // these changes apply to.
|
Chris@0
|
221 $display_id = $form_state->get('display_id');
|
Chris@0
|
222 if ($revert) {
|
Chris@0
|
223 // If it's revert just change the override and return.
|
Chris@0
|
224 $display = &$this->getExecutable()->displayHandlers->get($display_id);
|
Chris@0
|
225 $display->optionsOverride($form, $form_state);
|
Chris@0
|
226
|
Chris@0
|
227 // Don't execute the normal submit handling but still store the changed view into cache.
|
Chris@0
|
228 $this->cacheSet();
|
Chris@0
|
229 return;
|
Chris@0
|
230 }
|
Chris@0
|
231 elseif ($was_defaulted === $is_defaulted) {
|
Chris@0
|
232 // We're not changing which display these form values apply to.
|
Chris@0
|
233 // Run the regular submit handler for this form.
|
Chris@0
|
234 }
|
Chris@0
|
235 elseif ($was_defaulted && !$is_defaulted) {
|
Chris@0
|
236 // We were using the default display's values, but we're now overriding
|
Chris@0
|
237 // the default display and saving values specific to this display.
|
Chris@0
|
238 $display = &$this->getExecutable()->displayHandlers->get($display_id);
|
Chris@0
|
239 // optionsOverride toggles the override of this section.
|
Chris@0
|
240 $display->optionsOverride($form, $form_state);
|
Chris@0
|
241 $display->submitOptionsForm($form, $form_state);
|
Chris@0
|
242 }
|
Chris@0
|
243 elseif (!$was_defaulted && $is_defaulted) {
|
Chris@0
|
244 // We used to have an override for this display, but the user now wants
|
Chris@0
|
245 // to go back to the default display.
|
Chris@0
|
246 // Overwrite the default display with the current form values, and make
|
Chris@0
|
247 // the current display use the new default values.
|
Chris@0
|
248 $display = &$this->getExecutable()->displayHandlers->get($display_id);
|
Chris@0
|
249 // optionsOverride toggles the override of this section.
|
Chris@0
|
250 $display->optionsOverride($form, $form_state);
|
Chris@0
|
251 $display->submitOptionsForm($form, $form_state);
|
Chris@0
|
252 }
|
Chris@0
|
253
|
Chris@0
|
254 $submit_handler = [$form_state->getFormObject(), 'submitForm'];
|
Chris@0
|
255 call_user_func_array($submit_handler, [&$form, $form_state]);
|
Chris@0
|
256 }
|
Chris@0
|
257
|
Chris@0
|
258 /**
|
Chris@0
|
259 * Submit handler for cancel button
|
Chris@0
|
260 */
|
Chris@0
|
261 public function standardCancel($form, FormStateInterface $form_state) {
|
Chris@0
|
262 if (!empty($this->changed) && isset($this->form_cache)) {
|
Chris@0
|
263 unset($this->form_cache);
|
Chris@0
|
264 $this->cacheSet();
|
Chris@0
|
265 }
|
Chris@0
|
266
|
Chris@0
|
267 $form_state->setRedirectUrl($this->urlInfo('edit-form'));
|
Chris@0
|
268 }
|
Chris@0
|
269
|
Chris@0
|
270 /**
|
Chris@0
|
271 * Provide a standard set of Apply/Cancel/OK buttons for the forms. Also provide
|
Chris@0
|
272 * a hidden op operator because the forms plugin doesn't seem to properly
|
Chris@0
|
273 * provide which button was clicked.
|
Chris@0
|
274 *
|
Chris@0
|
275 * TODO: Is the hidden op operator still here somewhere, or is that part of the
|
Chris@0
|
276 * docblock outdated?
|
Chris@0
|
277 */
|
Chris@0
|
278 public function getStandardButtons(&$form, FormStateInterface $form_state, $form_id, $name = NULL) {
|
Chris@0
|
279 $form['actions'] = [
|
Chris@0
|
280 '#type' => 'actions',
|
Chris@0
|
281 ];
|
Chris@0
|
282
|
Chris@0
|
283 if (empty($name)) {
|
Chris@0
|
284 $name = t('Apply');
|
Chris@0
|
285 if (!empty($this->stack) && count($this->stack) > 1) {
|
Chris@0
|
286 $name = t('Apply and continue');
|
Chris@0
|
287 }
|
Chris@0
|
288 $names = [t('Apply'), t('Apply and continue')];
|
Chris@0
|
289 }
|
Chris@0
|
290
|
Chris@0
|
291 // Forms that are purely informational set an ok_button flag, so we know not
|
Chris@0
|
292 // to create an "Apply" button for them.
|
Chris@0
|
293 if (!$form_state->get('ok_button')) {
|
Chris@0
|
294 $form['actions']['submit'] = [
|
Chris@0
|
295 '#type' => 'submit',
|
Chris@0
|
296 '#value' => $name,
|
Chris@0
|
297 '#id' => 'edit-submit-' . Html::getUniqueId($form_id),
|
Chris@0
|
298 // The regular submit handler ($form_id . '_submit') does not apply if
|
Chris@0
|
299 // we're updating the default display. It does apply if we're updating
|
Chris@0
|
300 // the current display. Since we have no way of knowing at this point
|
Chris@0
|
301 // which display the user wants to update, views_ui_standard_submit will
|
Chris@0
|
302 // take care of running the regular submit handler as appropriate.
|
Chris@0
|
303 '#submit' => [[$this, 'standardSubmit']],
|
Chris@0
|
304 '#button_type' => 'primary',
|
Chris@0
|
305 ];
|
Chris@0
|
306 // Form API button click detection requires the button's #value to be the
|
Chris@0
|
307 // same between the form build of the initial page request, and the
|
Chris@0
|
308 // initial form build of the request processing the form submission.
|
Chris@0
|
309 // Ideally, the button's #value shouldn't change until the form rebuild
|
Chris@0
|
310 // step. However, \Drupal\views_ui\Form\Ajax\ViewsFormBase::getForm()
|
Chris@0
|
311 // implements a different multistep form workflow than the Form API does,
|
Chris@0
|
312 // and adjusts $view->stack prior to form processing, so we compensate by
|
Chris@0
|
313 // extending button click detection code to support any of the possible
|
Chris@0
|
314 // button labels.
|
Chris@0
|
315 if (isset($names)) {
|
Chris@0
|
316 $form['actions']['submit']['#values'] = $names;
|
Chris@0
|
317 $form['actions']['submit']['#process'] = array_merge(['views_ui_form_button_was_clicked'], \Drupal::service('element_info')->getInfoProperty($form['actions']['submit']['#type'], '#process', []));
|
Chris@0
|
318 }
|
Chris@0
|
319 // If a validation handler exists for the form, assign it to this button.
|
Chris@0
|
320 $form['actions']['submit']['#validate'][] = [$form_state->getFormObject(), 'validateForm'];
|
Chris@0
|
321 }
|
Chris@0
|
322
|
Chris@0
|
323 // Create a "Cancel" button. For purely informational forms, label it "OK".
|
Chris@0
|
324 $cancel_submit = function_exists($form_id . '_cancel') ? $form_id . '_cancel' : [$this, 'standardCancel'];
|
Chris@0
|
325 $form['actions']['cancel'] = [
|
Chris@0
|
326 '#type' => 'submit',
|
Chris@0
|
327 '#value' => !$form_state->get('ok_button') ? t('Cancel') : t('Ok'),
|
Chris@0
|
328 '#submit' => [$cancel_submit],
|
Chris@0
|
329 '#validate' => [],
|
Chris@0
|
330 '#limit_validation_errors' => [],
|
Chris@0
|
331 ];
|
Chris@0
|
332
|
Chris@0
|
333 // Compatibility, to be removed later: // TODO: When is "later"?
|
Chris@0
|
334 // We used to set these items on the form, but now we want them on the $form_state:
|
Chris@0
|
335 if (isset($form['#title'])) {
|
Chris@0
|
336 $form_state->set('title', $form['#title']);
|
Chris@0
|
337 }
|
Chris@0
|
338 if (isset($form['#section'])) {
|
Chris@0
|
339 $form_state->set('#section', $form['#section']);
|
Chris@0
|
340 }
|
Chris@0
|
341 // Finally, we never want these cached -- our object cache does that for us.
|
Chris@0
|
342 $form['#no_cache'] = TRUE;
|
Chris@0
|
343 }
|
Chris@0
|
344
|
Chris@0
|
345 /**
|
Chris@0
|
346 * Return the was_defaulted, is_defaulted and revert state of a form.
|
Chris@0
|
347 */
|
Chris@0
|
348 public function getOverrideValues($form, FormStateInterface $form_state) {
|
Chris@0
|
349 // Make sure the dropdown exists in the first place.
|
Chris@0
|
350 if ($form_state->hasValue(['override', 'dropdown'])) {
|
Chris@0
|
351 // #default_value is used to determine whether it was the default value or not.
|
Chris@0
|
352 // So the available options are: $display, 'default' and 'default_revert', not 'defaults'.
|
Chris@0
|
353 $was_defaulted = ($form['override']['dropdown']['#default_value'] === 'defaults');
|
Chris@0
|
354 $dropdown = $form_state->getValue(['override', 'dropdown']);
|
Chris@0
|
355 $is_defaulted = ($dropdown === 'default');
|
Chris@0
|
356 $revert = ($dropdown === 'default_revert');
|
Chris@0
|
357
|
Chris@0
|
358 if ($was_defaulted !== $is_defaulted && isset($form['#section'])) {
|
Chris@0
|
359 // We're changing which display these values apply to.
|
Chris@0
|
360 // Update the #section so it knows what to mark changed.
|
Chris@0
|
361 $form['#section'] = str_replace('default-', $form_state->get('display_id') . '-', $form['#section']);
|
Chris@0
|
362 }
|
Chris@0
|
363 }
|
Chris@0
|
364 else {
|
Chris@0
|
365 // The user didn't get the dropdown for overriding the default display.
|
Chris@0
|
366 $was_defaulted = FALSE;
|
Chris@0
|
367 $is_defaulted = FALSE;
|
Chris@0
|
368 $revert = FALSE;
|
Chris@0
|
369 }
|
Chris@0
|
370
|
Chris@0
|
371 return [$was_defaulted, $is_defaulted, $revert];
|
Chris@0
|
372 }
|
Chris@0
|
373
|
Chris@0
|
374 /**
|
Chris@0
|
375 * Add another form to the stack; clicking 'apply' will go to this form
|
Chris@0
|
376 * rather than closing the ajax popup.
|
Chris@0
|
377 */
|
Chris@0
|
378 public function addFormToStack($key, $display_id, $type, $id = NULL, $top = FALSE, $rebuild_keys = FALSE) {
|
Chris@0
|
379 // Reset the cache of IDs. Drupal rather aggressively prevents ID
|
Chris@0
|
380 // duplication but this causes it to remember IDs that are no longer even
|
Chris@0
|
381 // being used.
|
Chris@0
|
382 Html::resetSeenIds();
|
Chris@0
|
383
|
Chris@0
|
384 if (empty($this->stack)) {
|
Chris@0
|
385 $this->stack = [];
|
Chris@0
|
386 }
|
Chris@0
|
387
|
Chris@0
|
388 $stack = [implode('-', array_filter([$key, $this->id(), $display_id, $type, $id])), $key, $display_id, $type, $id];
|
Chris@0
|
389 // If we're being asked to add this form to the bottom of the stack, no
|
Chris@0
|
390 // special logic is required. Our work is equally easy if we were asked to add
|
Chris@0
|
391 // to the top of the stack, but there's nothing in it yet.
|
Chris@0
|
392 if (!$top || empty($this->stack)) {
|
Chris@0
|
393 $this->stack[] = $stack;
|
Chris@0
|
394 }
|
Chris@0
|
395 // If we're adding to the top of an existing stack, we have to maintain the
|
Chris@0
|
396 // existing integer keys, so they can be used for the "2 of 3" progress
|
Chris@0
|
397 // indicator (which will now read "2 of 4").
|
Chris@0
|
398 else {
|
Chris@0
|
399 $keys = array_keys($this->stack);
|
Chris@0
|
400 $first = current($keys);
|
Chris@0
|
401 $last = end($keys);
|
Chris@0
|
402 for ($i = $last; $i >= $first; $i--) {
|
Chris@0
|
403 if (!isset($this->stack[$i])) {
|
Chris@0
|
404 continue;
|
Chris@0
|
405 }
|
Chris@0
|
406 // Move form number $i to the next position in the stack.
|
Chris@0
|
407 $this->stack[$i + 1] = $this->stack[$i];
|
Chris@0
|
408 unset($this->stack[$i]);
|
Chris@0
|
409 }
|
Chris@0
|
410 // Now that the previously $first slot is free, move the new form into it.
|
Chris@0
|
411 $this->stack[$first] = $stack;
|
Chris@0
|
412 ksort($this->stack);
|
Chris@0
|
413
|
Chris@0
|
414 // Start the keys from 0 again, if requested.
|
Chris@0
|
415 if ($rebuild_keys) {
|
Chris@0
|
416 $this->stack = array_values($this->stack);
|
Chris@0
|
417 }
|
Chris@0
|
418 }
|
Chris@0
|
419 }
|
Chris@0
|
420
|
Chris@0
|
421 /**
|
Chris@0
|
422 * Submit handler for adding new item(s) to a view.
|
Chris@0
|
423 */
|
Chris@0
|
424 public function submitItemAdd($form, FormStateInterface $form_state) {
|
Chris@0
|
425 $type = $form_state->get('type');
|
Chris@0
|
426 $types = ViewExecutable::getHandlerTypes();
|
Chris@0
|
427 $section = $types[$type]['plural'];
|
Chris@0
|
428 $display_id = $form_state->get('display_id');
|
Chris@0
|
429
|
Chris@0
|
430 // Handle the override select.
|
Chris@0
|
431 list($was_defaulted, $is_defaulted) = $this->getOverrideValues($form, $form_state);
|
Chris@0
|
432 if ($was_defaulted && !$is_defaulted) {
|
Chris@0
|
433 // We were using the default display's values, but we're now overriding
|
Chris@0
|
434 // the default display and saving values specific to this display.
|
Chris@0
|
435 $display = &$this->getExecutable()->displayHandlers->get($display_id);
|
Chris@0
|
436 // setOverride toggles the override of this section.
|
Chris@0
|
437 $display->setOverride($section);
|
Chris@0
|
438 }
|
Chris@0
|
439 elseif (!$was_defaulted && $is_defaulted) {
|
Chris@0
|
440 // We used to have an override for this display, but the user now wants
|
Chris@0
|
441 // to go back to the default display.
|
Chris@0
|
442 // Overwrite the default display with the current form values, and make
|
Chris@0
|
443 // the current display use the new default values.
|
Chris@0
|
444 $display = &$this->getExecutable()->displayHandlers->get($display_id);
|
Chris@0
|
445 // optionsOverride toggles the override of this section.
|
Chris@0
|
446 $display->setOverride($section);
|
Chris@0
|
447 }
|
Chris@0
|
448
|
Chris@0
|
449 if (!$form_state->isValueEmpty('name') && is_array($form_state->getValue('name'))) {
|
Chris@0
|
450 // Loop through each of the items that were checked and add them to the view.
|
Chris@0
|
451 foreach (array_keys(array_filter($form_state->getValue('name'))) as $field) {
|
Chris@0
|
452 list($table, $field) = explode('.', $field, 2);
|
Chris@0
|
453
|
Chris@0
|
454 if ($cut = strpos($field, '$')) {
|
Chris@0
|
455 $field = substr($field, 0, $cut);
|
Chris@0
|
456 }
|
Chris@0
|
457 $id = $this->getExecutable()->addHandler($display_id, $type, $table, $field);
|
Chris@0
|
458
|
Chris@0
|
459 // check to see if we have group by settings
|
Chris@0
|
460 $key = $type;
|
Chris@0
|
461 // Footer,header and empty text have a different internal handler type(area).
|
Chris@0
|
462 if (isset($types[$type]['type'])) {
|
Chris@0
|
463 $key = $types[$type]['type'];
|
Chris@0
|
464 }
|
Chris@0
|
465 $item = [
|
Chris@0
|
466 'table' => $table,
|
Chris@0
|
467 'field' => $field,
|
Chris@0
|
468 ];
|
Chris@0
|
469 $handler = Views::handlerManager($key)->getHandler($item);
|
Chris@0
|
470 if ($this->getExecutable()->displayHandlers->get('default')->useGroupBy() && $handler->usesGroupBy()) {
|
Chris@0
|
471 $this->addFormToStack('handler-group', $display_id, $type, $id);
|
Chris@0
|
472 }
|
Chris@0
|
473
|
Chris@0
|
474 // check to see if this type has settings, if so add the settings form first
|
Chris@0
|
475 if ($handler && $handler->hasExtraOptions()) {
|
Chris@0
|
476 $this->addFormToStack('handler-extra', $display_id, $type, $id);
|
Chris@0
|
477 }
|
Chris@0
|
478 // Then add the form to the stack
|
Chris@0
|
479 $this->addFormToStack('handler', $display_id, $type, $id);
|
Chris@0
|
480 }
|
Chris@0
|
481 }
|
Chris@0
|
482
|
Chris@0
|
483 if (isset($this->form_cache)) {
|
Chris@0
|
484 unset($this->form_cache);
|
Chris@0
|
485 }
|
Chris@0
|
486
|
Chris@0
|
487 // Store in cache
|
Chris@0
|
488 $this->cacheSet();
|
Chris@0
|
489 }
|
Chris@0
|
490
|
Chris@0
|
491 /**
|
Chris@0
|
492 * Set up query capturing.
|
Chris@0
|
493 *
|
Chris@0
|
494 * \Drupal\Core\Database\Database stores the queries that it runs, if logging
|
Chris@0
|
495 * is enabled.
|
Chris@0
|
496 *
|
Chris@0
|
497 * @see ViewUI::endQueryCapture()
|
Chris@0
|
498 */
|
Chris@0
|
499 public function startQueryCapture() {
|
Chris@0
|
500 Database::startLog('views');
|
Chris@0
|
501 }
|
Chris@0
|
502
|
Chris@0
|
503 /**
|
Chris@0
|
504 * Add the list of queries run during render to buildinfo.
|
Chris@0
|
505 *
|
Chris@0
|
506 * @see ViewUI::startQueryCapture()
|
Chris@0
|
507 */
|
Chris@0
|
508 public function endQueryCapture() {
|
Chris@0
|
509 $queries = Database::getLog('views');
|
Chris@0
|
510
|
Chris@0
|
511 $this->additionalQueries = $queries;
|
Chris@0
|
512 }
|
Chris@0
|
513
|
Chris@0
|
514 public function renderPreview($display_id, $args = []) {
|
Chris@0
|
515 // Save the current path so it can be restored before returning from this function.
|
Chris@0
|
516 $request_stack = \Drupal::requestStack();
|
Chris@0
|
517 $current_request = $request_stack->getCurrentRequest();
|
Chris@0
|
518 $executable = $this->getExecutable();
|
Chris@0
|
519
|
Chris@0
|
520 // Determine where the query and performance statistics should be output.
|
Chris@0
|
521 $config = \Drupal::config('views.settings');
|
Chris@0
|
522 $show_query = $config->get('ui.show.sql_query.enabled');
|
Chris@0
|
523 $show_info = $config->get('ui.show.preview_information');
|
Chris@0
|
524 $show_location = $config->get('ui.show.sql_query.where');
|
Chris@0
|
525
|
Chris@0
|
526 $show_stats = $config->get('ui.show.performance_statistics');
|
Chris@0
|
527 if ($show_stats) {
|
Chris@0
|
528 $show_stats = $config->get('ui.show.sql_query.where');
|
Chris@0
|
529 }
|
Chris@0
|
530
|
Chris@0
|
531 $combined = $show_query && $show_stats;
|
Chris@0
|
532
|
Chris@0
|
533 $rows = ['query' => [], 'statistics' => []];
|
Chris@0
|
534
|
Chris@0
|
535 $errors = $executable->validate();
|
Chris@0
|
536 $executable->destroy();
|
Chris@0
|
537 if (empty($errors)) {
|
Chris@0
|
538 $this->ajax = TRUE;
|
Chris@0
|
539 $executable->live_preview = TRUE;
|
Chris@0
|
540
|
Chris@0
|
541 // AJAX happens via HTTP POST but everything expects exposed data to
|
Chris@0
|
542 // be in GET. Copy stuff but remove ajax-framework specific keys.
|
Chris@0
|
543 // If we're clicking on links in a preview, though, we could actually
|
Chris@0
|
544 // have some input in the query parameters, so we merge request() and
|
Chris@0
|
545 // query() to ensure we get it all.
|
Chris@0
|
546 $exposed_input = array_merge(\Drupal::request()->request->all(), \Drupal::request()->query->all());
|
Chris@0
|
547 foreach (['view_name', 'view_display_id', 'view_args', 'view_path', 'view_dom_id', 'pager_element', 'view_base_path', AjaxResponseSubscriber::AJAX_REQUEST_PARAMETER, 'ajax_page_state', 'form_id', 'form_build_id', 'form_token'] as $key) {
|
Chris@0
|
548 if (isset($exposed_input[$key])) {
|
Chris@0
|
549 unset($exposed_input[$key]);
|
Chris@0
|
550 }
|
Chris@0
|
551 }
|
Chris@0
|
552 $executable->setExposedInput($exposed_input);
|
Chris@0
|
553
|
Chris@0
|
554 if (!$executable->setDisplay($display_id)) {
|
Chris@0
|
555 return [
|
Chris@0
|
556 '#markup' => t('Invalid display id @display', ['@display' => $display_id]),
|
Chris@0
|
557 ];
|
Chris@0
|
558 }
|
Chris@0
|
559
|
Chris@0
|
560 $executable->setArguments($args);
|
Chris@0
|
561
|
Chris@0
|
562 // Store the current view URL for later use:
|
Chris@0
|
563 if ($executable->hasUrl() && $executable->display_handler->getOption('path')) {
|
Chris@0
|
564 $path = $executable->getUrl();
|
Chris@0
|
565 }
|
Chris@0
|
566
|
Chris@0
|
567 // Make view links come back to preview.
|
Chris@0
|
568
|
Chris@0
|
569 // Also override the current path so we get the pager, and make sure the
|
Chris@0
|
570 // Request object gets all of the proper values from $_SERVER.
|
Chris@0
|
571 $request = Request::createFromGlobals();
|
Chris@0
|
572 $request->attributes->set(RouteObjectInterface::ROUTE_NAME, 'entity.view.preview_form');
|
Chris@0
|
573 $request->attributes->set(RouteObjectInterface::ROUTE_OBJECT, \Drupal::service('router.route_provider')->getRouteByName('entity.view.preview_form'));
|
Chris@0
|
574 $request->attributes->set('view', $this->storage);
|
Chris@0
|
575 $request->attributes->set('display_id', $display_id);
|
Chris@0
|
576 $raw_parameters = new ParameterBag();
|
Chris@0
|
577 $raw_parameters->set('view', $this->id());
|
Chris@0
|
578 $raw_parameters->set('display_id', $display_id);
|
Chris@0
|
579 $request->attributes->set('_raw_variables', $raw_parameters);
|
Chris@0
|
580
|
Chris@0
|
581 foreach ($args as $key => $arg) {
|
Chris@0
|
582 $request->attributes->set('arg_' . $key, $arg);
|
Chris@0
|
583 }
|
Chris@0
|
584 $request_stack->push($request);
|
Chris@0
|
585
|
Chris@0
|
586 // Suppress contextual links of entities within the result set during a
|
Chris@0
|
587 // Preview.
|
Chris@0
|
588 // @todo We'll want to add contextual links specific to editing the View, so
|
Chris@0
|
589 // the suppression may need to be moved deeper into the Preview pipeline.
|
Chris@0
|
590 views_ui_contextual_links_suppress_push();
|
Chris@0
|
591
|
Chris@0
|
592 $show_additional_queries = $config->get('ui.show.additional_queries');
|
Chris@0
|
593
|
Chris@0
|
594 Timer::start('entity.view.preview_form');
|
Chris@0
|
595
|
Chris@0
|
596 if ($show_additional_queries) {
|
Chris@0
|
597 $this->startQueryCapture();
|
Chris@0
|
598 }
|
Chris@0
|
599
|
Chris@0
|
600 // Execute/get the view preview.
|
Chris@0
|
601 $preview = $executable->preview($display_id, $args);
|
Chris@0
|
602
|
Chris@0
|
603 if ($show_additional_queries) {
|
Chris@0
|
604 $this->endQueryCapture();
|
Chris@0
|
605 }
|
Chris@0
|
606
|
Chris@0
|
607 $this->render_time = Timer::stop('entity.view.preview_form')['time'];
|
Chris@0
|
608
|
Chris@0
|
609 views_ui_contextual_links_suppress_pop();
|
Chris@0
|
610
|
Chris@0
|
611 // Prepare the query information and statistics to show either above or
|
Chris@0
|
612 // below the view preview.
|
Chris@0
|
613 // Initialise the empty rows arrays so we can safely merge them later.
|
Chris@0
|
614 $rows['query'] = [];
|
Chris@0
|
615 $rows['statistics'] = [];
|
Chris@0
|
616 if ($show_info || $show_query || $show_stats) {
|
Chris@0
|
617 // Get information from the preview for display.
|
Chris@0
|
618 if (!empty($executable->build_info['query'])) {
|
Chris@0
|
619 if ($show_query) {
|
Chris@0
|
620 $query_string = $executable->build_info['query'];
|
Chris@0
|
621 // Only the sql default class has a method getArguments.
|
Chris@0
|
622 $quoted = [];
|
Chris@0
|
623
|
Chris@0
|
624 if ($executable->query instanceof Sql) {
|
Chris@0
|
625 $quoted = $query_string->getArguments();
|
Chris@0
|
626 $connection = Database::getConnection();
|
Chris@0
|
627 foreach ($quoted as $key => $val) {
|
Chris@0
|
628 if (is_array($val)) {
|
Chris@0
|
629 $quoted[$key] = implode(', ', array_map([$connection, 'quote'], $val));
|
Chris@0
|
630 }
|
Chris@0
|
631 else {
|
Chris@0
|
632 $quoted[$key] = $connection->quote($val);
|
Chris@0
|
633 }
|
Chris@0
|
634 }
|
Chris@0
|
635 }
|
Chris@0
|
636 $rows['query'][] = [
|
Chris@0
|
637 [
|
Chris@0
|
638 'data' => [
|
Chris@0
|
639 '#type' => 'inline_template',
|
Chris@0
|
640 '#template' => "<strong>{% trans 'Query' %}</strong>",
|
Chris@0
|
641 ],
|
Chris@0
|
642 ],
|
Chris@0
|
643 [
|
Chris@0
|
644 'data' => [
|
Chris@0
|
645 '#type' => 'inline_template',
|
Chris@0
|
646 '#template' => '<pre>{{ query }}</pre>',
|
Chris@0
|
647 '#context' => ['query' => strtr($query_string, $quoted)],
|
Chris@0
|
648 ],
|
Chris@0
|
649 ],
|
Chris@0
|
650 ];
|
Chris@0
|
651 if (!empty($this->additionalQueries)) {
|
Chris@0
|
652 $queries[] = [
|
Chris@0
|
653 '#prefix' => '<strong>',
|
Chris@0
|
654 '#markup' => t('These queries were run during view rendering:'),
|
Chris@0
|
655 '#suffix' => '</strong>',
|
Chris@0
|
656 ];
|
Chris@0
|
657 foreach ($this->additionalQueries as $query) {
|
Chris@0
|
658 $query_string = strtr($query['query'], $query['args']);
|
Chris@0
|
659 $queries[] = [
|
Chris@0
|
660 '#prefix' => "\n",
|
Chris@0
|
661 '#markup' => t('[@time ms] @query', ['@time' => round($query['time'] * 100000, 1) / 100000.0, '@query' => $query_string]),
|
Chris@0
|
662 ];
|
Chris@0
|
663 }
|
Chris@0
|
664
|
Chris@0
|
665 $rows['query'][] = [
|
Chris@0
|
666 [
|
Chris@0
|
667 'data' => [
|
Chris@0
|
668 '#type' => 'inline_template',
|
Chris@0
|
669 '#template' => "<strong>{% trans 'Other queries' %}</strong>",
|
Chris@0
|
670 ],
|
Chris@0
|
671 ],
|
Chris@0
|
672 [
|
Chris@0
|
673 'data' => [
|
Chris@0
|
674 '#prefix' => '<pre>',
|
Chris@0
|
675 'queries' => $queries,
|
Chris@0
|
676 '#suffix' => '</pre>',
|
Chris@0
|
677 ],
|
Chris@0
|
678 ],
|
Chris@0
|
679 ];
|
Chris@0
|
680 }
|
Chris@0
|
681 }
|
Chris@0
|
682 if ($show_info) {
|
Chris@0
|
683 $rows['query'][] = [
|
Chris@0
|
684 [
|
Chris@0
|
685 'data' => [
|
Chris@0
|
686 '#type' => 'inline_template',
|
Chris@0
|
687 '#template' => "<strong>{% trans 'Title' %}</strong>",
|
Chris@0
|
688 ],
|
Chris@0
|
689 ],
|
Chris@0
|
690 [
|
Chris@0
|
691 'data' => [
|
Chris@0
|
692 '#markup' => $executable->getTitle(),
|
Chris@0
|
693 ],
|
Chris@0
|
694 ],
|
Chris@0
|
695 ];
|
Chris@0
|
696 if (isset($path)) {
|
Chris@0
|
697 // @todo Views should expect and store a leading /. See:
|
Chris@0
|
698 // https://www.drupal.org/node/2423913
|
Chris@0
|
699 $path = \Drupal::l($path->toString(), $path);
|
Chris@0
|
700 }
|
Chris@0
|
701 else {
|
Chris@0
|
702 $path = t('This display has no path.');
|
Chris@0
|
703 }
|
Chris@0
|
704 $rows['query'][] = [
|
Chris@0
|
705 [
|
Chris@0
|
706 'data' => [
|
Chris@0
|
707 '#prefix' => '<strong>',
|
Chris@0
|
708 '#markup' => t('Path'),
|
Chris@0
|
709 '#suffix' => '</strong>',
|
Chris@0
|
710 ],
|
Chris@0
|
711 ],
|
Chris@0
|
712 [
|
Chris@0
|
713 'data' => [
|
Chris@0
|
714 '#markup' => $path,
|
Chris@0
|
715 ],
|
Chris@0
|
716 ]
|
Chris@0
|
717 ];
|
Chris@0
|
718 }
|
Chris@0
|
719 if ($show_stats) {
|
Chris@0
|
720 $rows['statistics'][] = [
|
Chris@0
|
721 [
|
Chris@0
|
722 'data' => [
|
Chris@0
|
723 '#type' => 'inline_template',
|
Chris@0
|
724 '#template' => "<strong>{% trans 'Query build time' %}</strong>",
|
Chris@0
|
725 ],
|
Chris@0
|
726 ],
|
Chris@0
|
727 t('@time ms', ['@time' => intval($executable->build_time * 100000) / 100]),
|
Chris@0
|
728 ];
|
Chris@0
|
729
|
Chris@0
|
730 $rows['statistics'][] = [
|
Chris@0
|
731 [
|
Chris@0
|
732 'data' => [
|
Chris@0
|
733 '#type' => 'inline_template',
|
Chris@0
|
734 '#template' => "<strong>{% trans 'Query execute time' %}</strong>",
|
Chris@0
|
735 ],
|
Chris@0
|
736 ],
|
Chris@0
|
737 t('@time ms', ['@time' => intval($executable->execute_time * 100000) / 100]),
|
Chris@0
|
738 ];
|
Chris@0
|
739
|
Chris@0
|
740 $rows['statistics'][] = [
|
Chris@0
|
741 [
|
Chris@0
|
742 'data' => [
|
Chris@0
|
743 '#type' => 'inline_template',
|
Chris@0
|
744 '#template' => "<strong>{% trans 'View render time' %}</strong>",
|
Chris@0
|
745 ],
|
Chris@0
|
746 ],
|
Chris@0
|
747 t('@time ms', ['@time' => intval($this->render_time * 100) / 100]),
|
Chris@0
|
748 ];
|
Chris@0
|
749 }
|
Chris@0
|
750 \Drupal::moduleHandler()->alter('views_preview_info', $rows, $executable);
|
Chris@0
|
751 }
|
Chris@0
|
752 else {
|
Chris@0
|
753 // No query was run. Display that information in place of either the
|
Chris@0
|
754 // query or the performance statistics, whichever comes first.
|
Chris@0
|
755 if ($combined || ($show_location === 'above')) {
|
Chris@0
|
756 $rows['query'][] = [
|
Chris@0
|
757 [
|
Chris@0
|
758 'data' => [
|
Chris@0
|
759 '#prefix' => '<strong>',
|
Chris@0
|
760 '#markup' => t('Query'),
|
Chris@0
|
761 '#suffix' => '</strong>',
|
Chris@0
|
762 ],
|
Chris@0
|
763 ],
|
Chris@0
|
764 [
|
Chris@0
|
765 'data' => [
|
Chris@0
|
766 '#markup' => t('No query was run'),
|
Chris@0
|
767 ],
|
Chris@0
|
768 ],
|
Chris@0
|
769 ];
|
Chris@0
|
770 }
|
Chris@0
|
771 else {
|
Chris@0
|
772 $rows['statistics'][] = [
|
Chris@0
|
773 [
|
Chris@0
|
774 'data' => [
|
Chris@0
|
775 '#prefix' => '<strong>',
|
Chris@0
|
776 '#markup' => t('Query'),
|
Chris@0
|
777 '#suffix' => '</strong>',
|
Chris@0
|
778 ],
|
Chris@0
|
779 ],
|
Chris@0
|
780 [
|
Chris@0
|
781 'data' => [
|
Chris@0
|
782 '#markup' => t('No query was run'),
|
Chris@0
|
783 ],
|
Chris@0
|
784 ],
|
Chris@0
|
785 ];
|
Chris@0
|
786 }
|
Chris@0
|
787 }
|
Chris@0
|
788 }
|
Chris@0
|
789 }
|
Chris@0
|
790 else {
|
Chris@0
|
791 foreach ($errors as $display_errors) {
|
Chris@0
|
792 foreach ($display_errors as $error) {
|
Chris@0
|
793 drupal_set_message($error, 'error');
|
Chris@0
|
794 }
|
Chris@0
|
795 }
|
Chris@0
|
796 $preview = ['#markup' => t('Unable to preview due to validation errors.')];
|
Chris@0
|
797 }
|
Chris@0
|
798
|
Chris@0
|
799 // Assemble the preview, the query info, and the query statistics in the
|
Chris@0
|
800 // requested order.
|
Chris@0
|
801 $table = [
|
Chris@0
|
802 '#type' => 'table',
|
Chris@0
|
803 '#prefix' => '<div class="views-query-info">',
|
Chris@0
|
804 '#suffix' => '</div>',
|
Chris@0
|
805 '#rows' => array_merge($rows['query'], $rows['statistics']),
|
Chris@0
|
806 ];
|
Chris@0
|
807
|
Chris@0
|
808 if ($show_location == 'above') {
|
Chris@0
|
809 $output = [
|
Chris@0
|
810 'table' => $table,
|
Chris@0
|
811 'preview' => $preview,
|
Chris@0
|
812 ];
|
Chris@0
|
813 }
|
Chris@0
|
814 else {
|
Chris@0
|
815 $output = [
|
Chris@0
|
816 'preview' => $preview,
|
Chris@0
|
817 'table' => $table,
|
Chris@0
|
818 ];
|
Chris@0
|
819 }
|
Chris@0
|
820
|
Chris@0
|
821 // Ensure that we just remove an additional request we pushed earlier.
|
Chris@0
|
822 // This could happen if $errors was not empty.
|
Chris@0
|
823 if ($request_stack->getCurrentRequest() != $current_request) {
|
Chris@0
|
824 $request_stack->pop();
|
Chris@0
|
825 }
|
Chris@0
|
826 return $output;
|
Chris@0
|
827 }
|
Chris@0
|
828
|
Chris@0
|
829 /**
|
Chris@0
|
830 * Get the user's current progress through the form stack.
|
Chris@0
|
831 *
|
Chris@0
|
832 * @return
|
Chris@0
|
833 * FALSE if the user is not currently in a multiple-form stack. Otherwise,
|
Chris@0
|
834 * an associative array with the following keys:
|
Chris@0
|
835 * - current: The number of the current form on the stack.
|
Chris@0
|
836 * - total: The total number of forms originally on the stack.
|
Chris@0
|
837 */
|
Chris@0
|
838 public function getFormProgress() {
|
Chris@0
|
839 $progress = FALSE;
|
Chris@0
|
840 if (!empty($this->stack)) {
|
Chris@0
|
841 // The forms on the stack have integer keys that don't change as the forms
|
Chris@0
|
842 // are completed, so we can see which ones are still left.
|
Chris@0
|
843 $keys = array_keys($this->stack);
|
Chris@0
|
844 // Add 1 to the array keys for the benefit of humans, who start counting
|
Chris@0
|
845 // from 1 and not 0.
|
Chris@0
|
846 $current = reset($keys) + 1;
|
Chris@0
|
847 $total = end($keys) + 1;
|
Chris@0
|
848 if ($total > 1) {
|
Chris@0
|
849 $progress = [];
|
Chris@0
|
850 $progress['current'] = $current;
|
Chris@0
|
851 $progress['total'] = $total;
|
Chris@0
|
852 }
|
Chris@0
|
853 }
|
Chris@0
|
854 return $progress;
|
Chris@0
|
855 }
|
Chris@0
|
856
|
Chris@0
|
857 /**
|
Chris@0
|
858 * Sets a cached view object in the shared tempstore.
|
Chris@0
|
859 */
|
Chris@0
|
860 public function cacheSet() {
|
Chris@0
|
861 if ($this->isLocked()) {
|
Chris@0
|
862 drupal_set_message(t('Changes cannot be made to a locked view.'), 'error');
|
Chris@0
|
863 return;
|
Chris@0
|
864 }
|
Chris@0
|
865
|
Chris@0
|
866 // Let any future object know that this view has changed.
|
Chris@0
|
867 $this->changed = TRUE;
|
Chris@0
|
868
|
Chris@0
|
869 $executable = $this->getExecutable();
|
Chris@0
|
870 if (isset($executable->current_display)) {
|
Chris@0
|
871 // Add the knowledge of the changed display, too.
|
Chris@0
|
872 $this->changed_display[$executable->current_display] = TRUE;
|
Chris@0
|
873 $executable->current_display = NULL;
|
Chris@0
|
874 }
|
Chris@0
|
875
|
Chris@0
|
876 // Unset handlers. We don't want to write these into the cache.
|
Chris@0
|
877 $executable->display_handler = NULL;
|
Chris@0
|
878 $executable->default_display = NULL;
|
Chris@0
|
879 $executable->query = NULL;
|
Chris@0
|
880 $executable->displayHandlers = NULL;
|
Chris@0
|
881 \Drupal::service('tempstore.shared')->get('views')->set($this->id(), $this);
|
Chris@0
|
882 }
|
Chris@0
|
883
|
Chris@0
|
884 /**
|
Chris@0
|
885 * Returns whether the current view is locked.
|
Chris@0
|
886 *
|
Chris@0
|
887 * @return bool
|
Chris@0
|
888 * TRUE if the view is locked, FALSE otherwise.
|
Chris@0
|
889 */
|
Chris@0
|
890 public function isLocked() {
|
Chris@0
|
891 return is_object($this->lock) && ($this->lock->owner != \Drupal::currentUser()->id());
|
Chris@0
|
892 }
|
Chris@0
|
893
|
Chris@0
|
894 /**
|
Chris@0
|
895 * Passes through all unknown calls onto the storage object.
|
Chris@0
|
896 */
|
Chris@0
|
897 public function __call($method, $args) {
|
Chris@0
|
898 return call_user_func_array([$this->storage, $method], $args);
|
Chris@0
|
899 }
|
Chris@0
|
900
|
Chris@0
|
901 /**
|
Chris@0
|
902 * {@inheritdoc}
|
Chris@0
|
903 */
|
Chris@0
|
904 public function &getDisplay($display_id) {
|
Chris@0
|
905 return $this->storage->getDisplay($display_id);
|
Chris@0
|
906 }
|
Chris@0
|
907
|
Chris@0
|
908 /**
|
Chris@0
|
909 * {@inheritdoc}
|
Chris@0
|
910 */
|
Chris@0
|
911 public function id() {
|
Chris@0
|
912 return $this->storage->id();
|
Chris@0
|
913 }
|
Chris@0
|
914
|
Chris@0
|
915 /**
|
Chris@0
|
916 * {@inheritdoc}
|
Chris@0
|
917 */
|
Chris@0
|
918 public function uuid() {
|
Chris@0
|
919 return $this->storage->uuid();
|
Chris@0
|
920 }
|
Chris@0
|
921
|
Chris@0
|
922 /**
|
Chris@0
|
923 * {@inheritdoc}
|
Chris@0
|
924 */
|
Chris@0
|
925 public function isNew() {
|
Chris@0
|
926 return $this->storage->isNew();
|
Chris@0
|
927 }
|
Chris@0
|
928
|
Chris@0
|
929 /**
|
Chris@0
|
930 * {@inheritdoc}
|
Chris@0
|
931 */
|
Chris@0
|
932 public function getEntityTypeId() {
|
Chris@0
|
933 return $this->storage->getEntityTypeId();
|
Chris@0
|
934 }
|
Chris@0
|
935
|
Chris@0
|
936 /**
|
Chris@0
|
937 * {@inheritdoc}
|
Chris@0
|
938 */
|
Chris@0
|
939 public function bundle() {
|
Chris@0
|
940 return $this->storage->bundle();
|
Chris@0
|
941 }
|
Chris@0
|
942
|
Chris@0
|
943 /**
|
Chris@0
|
944 * {@inheritdoc}
|
Chris@0
|
945 */
|
Chris@0
|
946 public function getEntityType() {
|
Chris@0
|
947 return $this->storage->getEntityType();
|
Chris@0
|
948 }
|
Chris@0
|
949
|
Chris@0
|
950 /**
|
Chris@0
|
951 * {@inheritdoc}
|
Chris@0
|
952 */
|
Chris@0
|
953 public function createDuplicate() {
|
Chris@0
|
954 return $this->storage->createDuplicate();
|
Chris@0
|
955 }
|
Chris@0
|
956
|
Chris@0
|
957 /**
|
Chris@0
|
958 * {@inheritdoc}
|
Chris@0
|
959 */
|
Chris@0
|
960 public static function load($id) {
|
Chris@0
|
961 return View::load($id);
|
Chris@0
|
962 }
|
Chris@0
|
963
|
Chris@0
|
964 /**
|
Chris@0
|
965 * {@inheritdoc}
|
Chris@0
|
966 */
|
Chris@0
|
967 public static function loadMultiple(array $ids = NULL) {
|
Chris@0
|
968 return View::loadMultiple($ids);
|
Chris@0
|
969 }
|
Chris@0
|
970
|
Chris@0
|
971 /**
|
Chris@0
|
972 * {@inheritdoc}
|
Chris@0
|
973 */
|
Chris@0
|
974 public static function create(array $values = []) {
|
Chris@0
|
975 return View::create($values);
|
Chris@0
|
976 }
|
Chris@0
|
977
|
Chris@0
|
978 /**
|
Chris@0
|
979 * {@inheritdoc}
|
Chris@0
|
980 */
|
Chris@0
|
981 public function delete() {
|
Chris@0
|
982 return $this->storage->delete();
|
Chris@0
|
983 }
|
Chris@0
|
984
|
Chris@0
|
985 /**
|
Chris@0
|
986 * {@inheritdoc}
|
Chris@0
|
987 */
|
Chris@0
|
988 public function save() {
|
Chris@0
|
989 return $this->storage->save();
|
Chris@0
|
990 }
|
Chris@0
|
991
|
Chris@0
|
992 /**
|
Chris@0
|
993 * {@inheritdoc}
|
Chris@0
|
994 */
|
Chris@0
|
995 public function urlInfo($rel = 'edit-form', array $options = []) {
|
Chris@0
|
996 return $this->storage->urlInfo($rel, $options);
|
Chris@0
|
997 }
|
Chris@0
|
998
|
Chris@0
|
999 /**
|
Chris@0
|
1000 * {@inheritdoc}
|
Chris@0
|
1001 */
|
Chris@0
|
1002 public function toUrl($rel = 'edit-form', array $options = []) {
|
Chris@0
|
1003 return $this->storage->toUrl($rel, $options);
|
Chris@0
|
1004 }
|
Chris@0
|
1005
|
Chris@0
|
1006 /**
|
Chris@0
|
1007 * {@inheritdoc}
|
Chris@0
|
1008 */
|
Chris@0
|
1009 public function link($text = NULL, $rel = 'edit-form', array $options = []) {
|
Chris@0
|
1010 return $this->storage->link($text, $rel, $options);
|
Chris@0
|
1011 }
|
Chris@0
|
1012
|
Chris@0
|
1013 /**
|
Chris@0
|
1014 * {@inheritdoc}
|
Chris@0
|
1015 */
|
Chris@0
|
1016 public function toLink($text = NULL, $rel = 'edit-form', array $options = []) {
|
Chris@0
|
1017 return $this->storage->toLink($text, $rel, $options);
|
Chris@0
|
1018 }
|
Chris@0
|
1019
|
Chris@0
|
1020 /**
|
Chris@0
|
1021 * {@inheritdoc}
|
Chris@0
|
1022 */
|
Chris@0
|
1023 public function label() {
|
Chris@0
|
1024 return $this->storage->label();
|
Chris@0
|
1025 }
|
Chris@0
|
1026
|
Chris@0
|
1027 /**
|
Chris@0
|
1028 * {@inheritdoc}
|
Chris@0
|
1029 */
|
Chris@0
|
1030 public function enforceIsNew($value = TRUE) {
|
Chris@0
|
1031 return $this->storage->enforceIsNew($value);
|
Chris@0
|
1032 }
|
Chris@0
|
1033
|
Chris@0
|
1034 /**
|
Chris@0
|
1035 * {@inheritdoc}
|
Chris@0
|
1036 */
|
Chris@0
|
1037 public function toArray() {
|
Chris@0
|
1038 return $this->storage->toArray();
|
Chris@0
|
1039 }
|
Chris@0
|
1040
|
Chris@0
|
1041 /**
|
Chris@0
|
1042 * {@inheritdoc}
|
Chris@0
|
1043 */
|
Chris@0
|
1044 public function language() {
|
Chris@0
|
1045 return $this->storage->language();
|
Chris@0
|
1046 }
|
Chris@0
|
1047
|
Chris@0
|
1048 /**
|
Chris@0
|
1049 * {@inheritdoc}
|
Chris@0
|
1050 */
|
Chris@0
|
1051 public function access($operation = 'view', AccountInterface $account = NULL, $return_as_object = FALSE) {
|
Chris@0
|
1052 return $this->storage->access($operation, $account, $return_as_object);
|
Chris@0
|
1053 }
|
Chris@0
|
1054
|
Chris@0
|
1055 /**
|
Chris@0
|
1056 * {@inheritdoc}
|
Chris@0
|
1057 */
|
Chris@0
|
1058 public function enable() {
|
Chris@0
|
1059 return $this->storage->enable();
|
Chris@0
|
1060 }
|
Chris@0
|
1061
|
Chris@0
|
1062 /**
|
Chris@0
|
1063 * {@inheritdoc}
|
Chris@0
|
1064 */
|
Chris@0
|
1065 public function disable() {
|
Chris@0
|
1066 return $this->storage->disable();
|
Chris@0
|
1067 }
|
Chris@0
|
1068
|
Chris@0
|
1069 /**
|
Chris@0
|
1070 * {@inheritdoc}
|
Chris@0
|
1071 */
|
Chris@0
|
1072 public function status() {
|
Chris@0
|
1073 return $this->storage->status();
|
Chris@0
|
1074 }
|
Chris@0
|
1075
|
Chris@0
|
1076 /**
|
Chris@0
|
1077 * {@inheritdoc}
|
Chris@0
|
1078 */
|
Chris@0
|
1079 public function getOriginalId() {
|
Chris@0
|
1080 return $this->storage->getOriginalId();
|
Chris@0
|
1081 }
|
Chris@0
|
1082
|
Chris@0
|
1083 /**
|
Chris@0
|
1084 * {@inheritdoc}
|
Chris@0
|
1085 */
|
Chris@0
|
1086 public function setOriginalId($id) {
|
Chris@0
|
1087 return $this->storage->setOriginalId($id);
|
Chris@0
|
1088 }
|
Chris@0
|
1089
|
Chris@0
|
1090 /**
|
Chris@0
|
1091 * {@inheritdoc}
|
Chris@0
|
1092 */
|
Chris@0
|
1093 public function preSave(EntityStorageInterface $storage) {
|
Chris@0
|
1094 $this->storage->presave($storage);
|
Chris@0
|
1095 }
|
Chris@0
|
1096
|
Chris@0
|
1097 /**
|
Chris@0
|
1098 * {@inheritdoc}
|
Chris@0
|
1099 */
|
Chris@0
|
1100 public function postSave(EntityStorageInterface $storage, $update = TRUE) {
|
Chris@0
|
1101 $this->storage->postSave($storage, $update);
|
Chris@0
|
1102 }
|
Chris@0
|
1103
|
Chris@0
|
1104 /**
|
Chris@0
|
1105 * {@inheritdoc}
|
Chris@0
|
1106 */
|
Chris@0
|
1107 public static function preCreate(EntityStorageInterface $storage, array &$values) {
|
Chris@0
|
1108 }
|
Chris@0
|
1109
|
Chris@0
|
1110 /**
|
Chris@0
|
1111 * {@inheritdoc}
|
Chris@0
|
1112 */
|
Chris@0
|
1113 public function postCreate(EntityStorageInterface $storage) {
|
Chris@0
|
1114 $this->storage->postCreate($storage);
|
Chris@0
|
1115 }
|
Chris@0
|
1116
|
Chris@0
|
1117 /**
|
Chris@0
|
1118 * {@inheritdoc}
|
Chris@0
|
1119 */
|
Chris@0
|
1120 public static function preDelete(EntityStorageInterface $storage, array $entities) {
|
Chris@0
|
1121 }
|
Chris@0
|
1122
|
Chris@0
|
1123 /**
|
Chris@0
|
1124 * {@inheritdoc}
|
Chris@0
|
1125 */
|
Chris@0
|
1126 public static function postDelete(EntityStorageInterface $storage, array $entities) {
|
Chris@0
|
1127 }
|
Chris@0
|
1128
|
Chris@0
|
1129 /**
|
Chris@0
|
1130 * {@inheritdoc}
|
Chris@0
|
1131 */
|
Chris@0
|
1132 public static function postLoad(EntityStorageInterface $storage, array &$entities) {
|
Chris@0
|
1133 }
|
Chris@0
|
1134
|
Chris@0
|
1135 /**
|
Chris@0
|
1136 * {@inheritdoc}
|
Chris@0
|
1137 */
|
Chris@0
|
1138 public function getExecutable() {
|
Chris@0
|
1139 return $this->storage->getExecutable();
|
Chris@0
|
1140 }
|
Chris@0
|
1141
|
Chris@0
|
1142 /**
|
Chris@0
|
1143 * {@inheritdoc}
|
Chris@0
|
1144 */
|
Chris@0
|
1145 public function duplicateDisplayAsType($old_display_id, $new_display_type) {
|
Chris@0
|
1146 return $this->storage->duplicateDisplayAsType($old_display_id, $new_display_type);
|
Chris@0
|
1147 }
|
Chris@0
|
1148
|
Chris@0
|
1149 /**
|
Chris@0
|
1150 * {@inheritdoc}
|
Chris@0
|
1151 */
|
Chris@0
|
1152 public function mergeDefaultDisplaysOptions() {
|
Chris@0
|
1153 $this->storage->mergeDefaultDisplaysOptions();
|
Chris@0
|
1154 }
|
Chris@0
|
1155
|
Chris@0
|
1156 /**
|
Chris@0
|
1157 * {@inheritdoc}
|
Chris@0
|
1158 */
|
Chris@0
|
1159 public function uriRelationships() {
|
Chris@0
|
1160 return $this->storage->uriRelationships();
|
Chris@0
|
1161 }
|
Chris@0
|
1162
|
Chris@0
|
1163 /**
|
Chris@0
|
1164 * {@inheritdoc}
|
Chris@0
|
1165 */
|
Chris@0
|
1166 public function referencedEntities() {
|
Chris@0
|
1167 return $this->storage->referencedEntities();
|
Chris@0
|
1168 }
|
Chris@0
|
1169
|
Chris@0
|
1170 /**
|
Chris@0
|
1171 * {@inheritdoc}
|
Chris@0
|
1172 */
|
Chris@0
|
1173 public function url($rel = 'edit-form', $options = []) {
|
Chris@0
|
1174 return $this->storage->url($rel, $options);
|
Chris@0
|
1175 }
|
Chris@0
|
1176
|
Chris@0
|
1177 /**
|
Chris@0
|
1178 * {@inheritdoc}
|
Chris@0
|
1179 */
|
Chris@0
|
1180 public function hasLinkTemplate($key) {
|
Chris@0
|
1181 return $this->storage->hasLinkTemplate($key);
|
Chris@0
|
1182 }
|
Chris@0
|
1183
|
Chris@0
|
1184 /**
|
Chris@0
|
1185 * {@inheritdoc}
|
Chris@0
|
1186 */
|
Chris@0
|
1187 public function calculateDependencies() {
|
Chris@0
|
1188 $this->storage->calculateDependencies();
|
Chris@0
|
1189 return $this;
|
Chris@0
|
1190 }
|
Chris@0
|
1191
|
Chris@0
|
1192 /**
|
Chris@0
|
1193 * {@inheritdoc}
|
Chris@0
|
1194 */
|
Chris@0
|
1195 public function getConfigDependencyKey() {
|
Chris@0
|
1196 return $this->storage->getConfigDependencyKey();
|
Chris@0
|
1197 }
|
Chris@0
|
1198
|
Chris@0
|
1199 /**
|
Chris@0
|
1200 * {@inheritdoc}
|
Chris@0
|
1201 */
|
Chris@0
|
1202 public function getConfigDependencyName() {
|
Chris@0
|
1203 return $this->storage->getConfigDependencyName();
|
Chris@0
|
1204 }
|
Chris@0
|
1205
|
Chris@0
|
1206 /**
|
Chris@0
|
1207 * {@inheritdoc}
|
Chris@0
|
1208 */
|
Chris@0
|
1209 public function getConfigTarget() {
|
Chris@0
|
1210 return $this->storage->getConfigTarget();
|
Chris@0
|
1211 }
|
Chris@0
|
1212
|
Chris@0
|
1213 /**
|
Chris@0
|
1214 * {@inheritdoc}
|
Chris@0
|
1215 */
|
Chris@0
|
1216 public function onDependencyRemoval(array $dependencies) {
|
Chris@0
|
1217 return $this->storage->onDependencyRemoval($dependencies);
|
Chris@0
|
1218 }
|
Chris@0
|
1219
|
Chris@0
|
1220 /**
|
Chris@0
|
1221 * {@inheritdoc}
|
Chris@0
|
1222 */
|
Chris@0
|
1223 public function getDependencies() {
|
Chris@0
|
1224 return $this->storage->getDependencies();
|
Chris@0
|
1225 }
|
Chris@0
|
1226
|
Chris@0
|
1227 /**
|
Chris@0
|
1228 * {@inheritdoc}
|
Chris@0
|
1229 */
|
Chris@0
|
1230 public function getCacheContexts() {
|
Chris@0
|
1231 return $this->storage->getCacheContexts();
|
Chris@0
|
1232 }
|
Chris@0
|
1233
|
Chris@0
|
1234 /**
|
Chris@0
|
1235 * {@inheritdoc}
|
Chris@0
|
1236 */
|
Chris@0
|
1237 public function getCacheTags() {
|
Chris@0
|
1238 return $this->storage->getCacheTags();
|
Chris@0
|
1239 }
|
Chris@0
|
1240
|
Chris@0
|
1241 /**
|
Chris@0
|
1242 * {@inheritdoc}
|
Chris@0
|
1243 */
|
Chris@0
|
1244 public function getCacheMaxAge() {
|
Chris@0
|
1245 return $this->storage->getCacheMaxAge();
|
Chris@0
|
1246 }
|
Chris@0
|
1247
|
Chris@0
|
1248 /**
|
Chris@0
|
1249 * {@inheritdoc}
|
Chris@0
|
1250 */
|
Chris@0
|
1251 public function getTypedData() {
|
Chris@0
|
1252 $this->storage->getTypedData();
|
Chris@0
|
1253 }
|
Chris@0
|
1254
|
Chris@0
|
1255 /**
|
Chris@0
|
1256 * {@inheritdoc}
|
Chris@0
|
1257 */
|
Chris@0
|
1258 public function addDisplay($plugin_id = 'page', $title = NULL, $id = NULL) {
|
Chris@0
|
1259 return $this->storage->addDisplay($plugin_id, $title, $id);
|
Chris@0
|
1260 }
|
Chris@0
|
1261
|
Chris@0
|
1262 /**
|
Chris@0
|
1263 * {@inheritdoc}
|
Chris@0
|
1264 */
|
Chris@0
|
1265 public function isInstallable() {
|
Chris@0
|
1266 return $this->storage->isInstallable();
|
Chris@0
|
1267 }
|
Chris@0
|
1268
|
Chris@0
|
1269 /**
|
Chris@0
|
1270 * {@inheritdoc}
|
Chris@0
|
1271 */
|
Chris@0
|
1272 public function setThirdPartySetting($module, $key, $value) {
|
Chris@0
|
1273 return $this->storage->setThirdPartySetting($module, $key, $value);
|
Chris@0
|
1274 }
|
Chris@0
|
1275
|
Chris@0
|
1276 /**
|
Chris@0
|
1277 * {@inheritdoc}
|
Chris@0
|
1278 */
|
Chris@0
|
1279 public function getThirdPartySetting($module, $key, $default = NULL) {
|
Chris@0
|
1280 return $this->storage->getThirdPartySetting($module, $key, $default);
|
Chris@0
|
1281 }
|
Chris@0
|
1282
|
Chris@0
|
1283 /**
|
Chris@0
|
1284 * {@inheritdoc}
|
Chris@0
|
1285 */
|
Chris@0
|
1286 public function getThirdPartySettings($module) {
|
Chris@0
|
1287 return $this->storage->getThirdPartySettings($module);
|
Chris@0
|
1288 }
|
Chris@0
|
1289
|
Chris@0
|
1290 /**
|
Chris@0
|
1291 * {@inheritdoc}
|
Chris@0
|
1292 */
|
Chris@0
|
1293 public function unsetThirdPartySetting($module, $key) {
|
Chris@0
|
1294 return $this->storage->unsetThirdPartySetting($module, $key);
|
Chris@0
|
1295 }
|
Chris@0
|
1296
|
Chris@0
|
1297 /**
|
Chris@0
|
1298 * {@inheritdoc}
|
Chris@0
|
1299 */
|
Chris@0
|
1300 public function getThirdPartyProviders() {
|
Chris@0
|
1301 return $this->storage->getThirdPartyProviders();
|
Chris@0
|
1302 }
|
Chris@0
|
1303
|
Chris@0
|
1304 /**
|
Chris@0
|
1305 * {@inheritdoc}
|
Chris@0
|
1306 */
|
Chris@0
|
1307 public function trustData() {
|
Chris@0
|
1308 return $this->storage->trustData();
|
Chris@0
|
1309 }
|
Chris@0
|
1310
|
Chris@0
|
1311 /**
|
Chris@0
|
1312 * {@inheritdoc}
|
Chris@0
|
1313 */
|
Chris@0
|
1314 public function hasTrustedData() {
|
Chris@0
|
1315 return $this->storage->hasTrustedData();
|
Chris@0
|
1316 }
|
Chris@0
|
1317
|
Chris@0
|
1318 /**
|
Chris@0
|
1319 * {@inheritdoc}
|
Chris@0
|
1320 */
|
Chris@0
|
1321 public function addCacheableDependency($other_object) {
|
Chris@0
|
1322 $this->storage->addCacheableDependency($other_object);
|
Chris@0
|
1323 return $this;
|
Chris@0
|
1324 }
|
Chris@0
|
1325
|
Chris@0
|
1326 /**
|
Chris@0
|
1327 * {@inheritdoc}
|
Chris@0
|
1328 */
|
Chris@0
|
1329 public function addCacheContexts(array $cache_contexts) {
|
Chris@0
|
1330 return $this->storage->addCacheContexts($cache_contexts);
|
Chris@0
|
1331 }
|
Chris@0
|
1332
|
Chris@0
|
1333 /**
|
Chris@0
|
1334 * {@inheritdoc}
|
Chris@0
|
1335 */
|
Chris@0
|
1336 public function mergeCacheMaxAge($max_age) {
|
Chris@0
|
1337 return $this->storage->mergeCacheMaxAge($max_age);
|
Chris@0
|
1338 }
|
Chris@0
|
1339
|
Chris@0
|
1340 /**
|
Chris@0
|
1341 * {@inheritdoc}
|
Chris@0
|
1342 */
|
Chris@0
|
1343 public function getCacheTagsToInvalidate() {
|
Chris@0
|
1344 return $this->storage->getCacheTagsToInvalidate();
|
Chris@0
|
1345 }
|
Chris@0
|
1346
|
Chris@0
|
1347 /**
|
Chris@0
|
1348 * {@inheritdoc}
|
Chris@0
|
1349 */
|
Chris@0
|
1350 public function addCacheTags(array $cache_tags) {
|
Chris@0
|
1351 return $this->storage->addCacheTags($cache_tags);
|
Chris@0
|
1352 }
|
Chris@0
|
1353
|
Chris@0
|
1354 }
|