annotate core/modules/views_ui/src/ViewUI.php @ 19:fa3358dc1485 tip

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