X-Git-Url: http://aleph1.co.uk/gitweb/?a=blobdiff_plain;f=web%2Fcore%2Fmodules%2Fviews%2Fsrc%2FViewExecutable.php;h=1adaf55dad39f49e3664e90d1902e4a785412c73;hb=5b8bb166bfa98770daef9de5c127fc2e6ef02340;hp=b1861f7b367f39d17c63c8d2c09c9de06765aded;hpb=a2bd1bf0c2c1f1a17d188f4dc0726a45494cefae;p=yaffs-website diff --git a/web/core/modules/views/src/ViewExecutable.php b/web/core/modules/views/src/ViewExecutable.php index b1861f7b3..1adaf55da 100644 --- a/web/core/modules/views/src/ViewExecutable.php +++ b/web/core/modules/views/src/ViewExecutable.php @@ -2,9 +2,9 @@ namespace Drupal\views; +use Drupal\Component\Render\FormattableMarkup; use Drupal\Component\Utility\Html; use Drupal\Component\Utility\Tags; -use Drupal\Core\DependencyInjection\DependencySerializationTrait; use Drupal\Core\Routing\RouteProviderInterface; use Drupal\Core\Session\AccountInterface; use Drupal\views\Plugin\views\display\DisplayRouterInterface; @@ -17,9 +17,14 @@ use Symfony\Component\Routing\Exception\RouteNotFoundException; * * An object to contain all of the data to generate a view, plus the member * functions to build the view query, execute the query and render the output. + * + * This class does not implement the Serializable interface since problems + * occurred when using the serialize method. + * + * @see https://www.drupal.org/node/2849674 + * @see https://bugs.php.net/bug.php?id=66052 */ -class ViewExecutable implements \Serializable { - use DependencySerializationTrait; +class ViewExecutable { /** * The config entity in which the view is stored. @@ -109,7 +114,7 @@ class ViewExecutable implements \Serializable { /** * Attachments to place before the view. * - * @var array() + * @var array */ public $attachment_before = []; @@ -326,7 +331,7 @@ class ViewExecutable implements \Serializable { protected $request; /** - * Does this view already have loaded it's handlers. + * Does this view already have loaded its handlers. * * @todo Group with other static properties. * @@ -434,6 +439,13 @@ class ViewExecutable implements \Serializable { */ protected $baseEntityType; + /** + * Holds all necessary data for proper unserialization. + * + * @var array + */ + protected $serializationData; + /** * Constructs a new ViewExecutable object. * @@ -607,7 +619,6 @@ class ViewExecutable implements \Serializable { $this->offset = $offset; - // If the pager is already initialized, pass it through to the pager. if (!empty($this->pager)) { $this->pager->setOffset($offset); @@ -788,7 +799,7 @@ class ViewExecutable implements \Serializable { // Ensure the requested display exists. if (!$this->displayHandlers->has($display_id)) { - debug(format_string('setDisplay() called with invalid display ID "@display".', ['@display' => $display_id])); + trigger_error(new FormattableMarkup('setDisplay() called with invalid display ID "@display".', ['@display' => $display_id]), E_USER_WARNING); return FALSE; } @@ -1085,7 +1096,8 @@ class ViewExecutable implements \Serializable { $argument->is_default = TRUE; } - // Set the argument, which will also validate that the argument can be set. + // Set the argument, which ensures that the argument is valid and + // possibly transforms the value. if (!$argument->setArgument($arg)) { $status = $argument->validateFail($arg); break; @@ -1099,9 +1111,11 @@ class ViewExecutable implements \Serializable { $argument->query($this->display_handler->useGroupBy()); } - // Add this argument's substitution + // Add this argument's substitution. $substitutions["{{ arguments.$id }}"] = $arg_title; - $substitutions["{{ raw_arguments.$id }}"] = strip_tags(Html::decodeEntities($arg)); + // Since argument validator plugins can potentially transform the value, + // use whatever value the argument handler now has, not the raw value. + $substitutions["{{ raw_arguments.$id }}"] = strip_tags(Html::decodeEntities($argument->getValue())); // Test to see if we should use this argument's title if (!empty($argument->options['title_enable']) && !empty($argument->options['title'])) { @@ -1327,8 +1341,8 @@ class ViewExecutable implements \Serializable { * @todo Some filter needs this function, even it is internal. * * @param string $key - * The type of handlers (filter etc.) which should be iterated over to - * build the relationship and query information. + * The type of handlers (filter etc.) which should be iterated over to build + * the relationship and query information. */ public function _build($key) { $handlers = &$this->$key; @@ -1508,7 +1522,7 @@ class ViewExecutable implements \Serializable { // Let modules modify the view just prior to rendering it. $module_handler->invokeAll('views_pre_render', [$this]); - // Let the themes play too, because pre render is a very themey thing. + // Let the themes play too, because prerender is a very themey thing. foreach ($themes as $theme_name) { $function = $theme_name . '_views_pre_render'; if (function_exists($function)) { @@ -1746,7 +1760,7 @@ class ViewExecutable implements \Serializable { // We can't use choose_display() here because that function // calls this one. - $displays = (array)$displays; + $displays = (array) $displays; foreach ($displays as $display_id) { if ($this->displayHandlers->has($display_id)) { if (($display = $this->displayHandlers->get($display_id)) && $display->access($account)) { @@ -2466,52 +2480,68 @@ class ViewExecutable implements \Serializable { } /** - * {@inheritdoc} - */ - public function serialize() { - return serialize([ - // Only serialize the storage entity ID. - $this->storage->id(), - $this->current_display, - $this->args, - $this->current_page, - $this->exposed_input, - $this->exposed_raw_input, - $this->exposed_data, - $this->dom_id, - $this->executed, - ]); + * Magic method implementation to serialize the view executable. + * + * @return array + * The names of all variables that should be serialized. + */ + public function __sleep() { + // Limit to only the required data which is needed to properly restore the + // state during unserialization. + $this->serializationData = [ + 'storage' => $this->storage->id(), + 'views_data' => $this->viewsData->_serviceId, + 'route_provider' => $this->routeProvider->_serviceId, + 'current_display' => $this->current_display, + 'args' => $this->args, + 'current_page' => $this->current_page, + 'exposed_input' => $this->exposed_input, + 'exposed_raw_input' => $this->exposed_raw_input, + 'exposed_data' => $this->exposed_data, + 'dom_id' => $this->dom_id, + 'executed' => $this->executed, + ]; + return ['serializationData']; } /** - * {@inheritdoc} + * Magic method implementation to unserialize the view executable. */ - public function unserialize($serialized) { - list($storage, $current_display, $args, $current_page, $exposed_input, $exposed_raw_input, $exposed_data, $dom_id, $executed) = unserialize($serialized); - - // There are cases, like in testing, where we don't have a container + public function __wakeup() { + // There are cases, like in testing where we don't have a container // available. - if (\Drupal::hasContainer()) { - $this->setRequest(\Drupal::request()); - $this->user = \Drupal::currentUser(); + if (\Drupal::hasContainer() && !empty($this->serializationData)) { + // Load and reference the storage. + $this->storage = \Drupal::entityTypeManager()->getStorage('view') + ->load($this->serializationData['storage']); + $this->storage->set('executable', $this); - $this->storage = \Drupal::entityManager()->getStorage('view')->load($storage); + // Attach all necessary services. + $this->user = \Drupal::currentUser(); + $this->viewsData = \Drupal::service($this->serializationData['views_data']); + $this->routeProvider = \Drupal::service($this->serializationData['route_provider']); - $this->setDisplay($current_display); - $this->setArguments($args); - $this->setCurrentPage($current_page); - $this->setExposedInput($exposed_input); - $this->exposed_data = $exposed_data; - $this->exposed_raw_input = $exposed_raw_input; - $this->dom_id = $dom_id; + // Restore the state of this executable. + if ($request = \Drupal::request()) { + $this->setRequest($request); + } + $this->setDisplay($this->serializationData['current_display']); + $this->setArguments($this->serializationData['args']); + $this->setCurrentPage($this->serializationData['current_page']); + $this->setExposedInput($this->serializationData['exposed_input']); + $this->exposed_data = $this->serializationData['exposed_data']; + $this->exposed_raw_input = $this->serializationData['exposed_raw_input']; + $this->dom_id = $this->serializationData['dom_id']; $this->initHandlers(); // If the display was previously executed, execute it now. - if ($executed) { + if ($this->serializationData['executed']) { $this->execute($this->current_display); } } + // Unset serializationData since it serves no further purpose. + unset($this->serializationData); } }