diff --git a/core/modules/views/src/ViewExecutable.php b/core/modules/views/src/ViewExecutable.php index f13c0e752db8..b1861f7b367f 100644 --- a/core/modules/views/src/ViewExecutable.php +++ b/core/modules/views/src/ViewExecutable.php @@ -4,6 +4,7 @@ namespace Drupal\views; 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; @@ -16,14 +17,9 @@ 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 { +class ViewExecutable implements \Serializable { + use DependencySerializationTrait; /** * The config entity in which the view is stored. @@ -438,13 +434,6 @@ class ViewExecutable { */ protected $baseEntityType; - /** - * Holds all necessary data for proper unserialization. - * - * @var array - */ - protected $serializationData; - /** * Constructs a new ViewExecutable object. * @@ -2477,68 +2466,52 @@ class ViewExecutable { } /** - * Magic method implementation to serialize the view executable. - * - * @return array - * The names of all variables that should be serialized. + * {@inheritdoc} */ - 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']; + 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 unserialize the view executable. + * {@inheritdoc} */ - public function __wakeup() { - // There are cases, like in testing where we don't have a container + 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 // available. - 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); - - // Attach all necessary services. + if (\Drupal::hasContainer()) { + $this->setRequest(\Drupal::request()); $this->user = \Drupal::currentUser(); - $this->viewsData = \Drupal::service($this->serializationData['views_data']); - $this->routeProvider = \Drupal::service($this->serializationData['route_provider']); - // 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->storage = \Drupal::entityManager()->getStorage('view')->load($storage); + + $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; $this->initHandlers(); // If the display was previously executed, execute it now. - if ($this->serializationData['executed']) { + if ($executed) { $this->execute($this->current_display); } } - // Unset serializationData since it serves no further purpose. - unset($this->serializationData); } } diff --git a/core/modules/views/tests/modules/user_batch_action_test/config/install/system.action.user_batch_action_test_action.yml b/core/modules/views/tests/modules/user_batch_action_test/config/install/system.action.user_batch_action_test_action.yml deleted file mode 100644 index 6b256637a7d2..000000000000 --- a/core/modules/views/tests/modules/user_batch_action_test/config/install/system.action.user_batch_action_test_action.yml +++ /dev/null @@ -1,10 +0,0 @@ -langcode: en -status: true -dependencies: - module: - - user -id: user_batch_action_test_action -label: 'Process user in batch' -type: user -plugin: user_batch_action_test_action -configuration: { } diff --git a/core/modules/views/tests/modules/user_batch_action_test/config/schema/user_batch_action_test.schema.yml b/core/modules/views/tests/modules/user_batch_action_test/config/schema/user_batch_action_test.schema.yml deleted file mode 100644 index 0730941986d7..000000000000 --- a/core/modules/views/tests/modules/user_batch_action_test/config/schema/user_batch_action_test.schema.yml +++ /dev/null @@ -1,3 +0,0 @@ -action.configuration.user_batch_action_test_action: - type: action_configuration_default - label: 'Process user in batch' diff --git a/core/modules/views/tests/modules/user_batch_action_test/src/Plugin/Action/BatchUserAction.php b/core/modules/views/tests/modules/user_batch_action_test/src/Plugin/Action/BatchUserAction.php deleted file mode 100644 index e4bed32f4dd9..000000000000 --- a/core/modules/views/tests/modules/user_batch_action_test/src/Plugin/Action/BatchUserAction.php +++ /dev/null @@ -1,87 +0,0 @@ - $entity->getEntityTypeId(), - 'entity_id' => $entity->id(), - ]], - ]; - } - - if ($operations) { - $batch = [ - 'operations' => $operations, - 'finished' => [get_class($this), 'finishBatch'], - ]; - batch_set($batch); - } - } - - /** - * {@inheritdoc} - */ - public function execute(ContentEntityInterface $entity = NULL) { - $this->executeMultiple([$entity]); - } - - /** - * {@inheritdoc} - */ - public function access($object, AccountInterface $account = NULL, $return_as_object = FALSE) { - return TRUE; - } - - /** - * Processes the batch item. - * - * @param array $data - * Keyed array of data to process. - * @param array $context - * The batch context. - */ - public static function processBatch($data, &$context) { - if (!isset($context['results']['processed'])) { - $context['results']['processed'] = 0; - } - $context['results']['processed']++; - } - - /** - * Finish batch. - * - * @param bool $success - * Indicates whether the batch process was successful. - * @param array $results - * Results information passed from the processing callback. - */ - public static function finishBatch($success, $results) { - drupal_set_message(\Drupal::translation() - ->formatPlural($results['processed'], 'One item has been processed.', '@count items have been processed.')); - } - -} diff --git a/core/modules/views/tests/modules/user_batch_action_test/user_batch_action_test.info.yml b/core/modules/views/tests/modules/user_batch_action_test/user_batch_action_test.info.yml deleted file mode 100644 index 931dfc2b6cc8..000000000000 --- a/core/modules/views/tests/modules/user_batch_action_test/user_batch_action_test.info.yml +++ /dev/null @@ -1,9 +0,0 @@ -name: 'User batch action test' -type: module -description: 'Support module for user batch action testing.' -package: Testing -version: VERSION -core: 8.x -dependencies: - - views - - user diff --git a/core/modules/views/tests/src/Functional/UserBatchActionTest.php b/core/modules/views/tests/src/Functional/UserBatchActionTest.php deleted file mode 100644 index 7b59dcc579fa..000000000000 --- a/core/modules/views/tests/src/Functional/UserBatchActionTest.php +++ /dev/null @@ -1,45 +0,0 @@ -drupalLogin($this->rootUser); - - $themes = ['classy', 'seven', 'bartik']; - - /** @var \Drupal\Core\Extension\ThemeInstallerInterface $theme_installer */ - $theme_installer = $this->container->get('theme_installer'); - $theme_installer->install($themes); - - foreach ($themes as $theme) { - \Drupal::configFactory()->getEditable('system.theme')->set('default', $theme)->save(); - $this->drupalGet('admin/people'); - $edit = [ - 'user_bulk_form[0]' => TRUE, - 'action' => 'user_batch_action_test_action', - ]; - $this->drupalPostForm(NULL, $edit, t('Apply to selected items')); - $this->checkForMetaRefresh(); - $this->assertSession()->pageTextContains('One item has been processed.'); - } - } - -} diff --git a/core/modules/views/tests/src/Kernel/ViewExecutableTest.php b/core/modules/views/tests/src/Kernel/ViewExecutableTest.php index 6ef104cc1ace..f843892e5da1 100644 --- a/core/modules/views/tests/src/Kernel/ViewExecutableTest.php +++ b/core/modules/views/tests/src/Kernel/ViewExecutableTest.php @@ -487,35 +487,6 @@ class ViewExecutableTest extends ViewsKernelTestBase { $this->assertIdentical($unserialized->current_display, 'page_1', 'The expected display was set on the unserialized view.'); $this->assertIdentical($unserialized->args, ['test'], 'The expected argument was set on the unserialized view.'); $this->assertIdentical($unserialized->getCurrentPage(), 2, 'The expected current page was set on the unserialized view.'); - - // Get the definition of node's nid field, for example. Only get it not from - // the field manager directly, but from the item data definition. It should - // be the same base field definition object (the field and item definitions - // refer to each other). - // See https://bugs.php.net/bug.php?id=66052 - $field_manager = \Drupal::service('entity_field.manager'); - $nid_definition_before = $field_manager->getBaseFieldDefinitions('node')['nid'] - ->getItemDefinition() - ->getFieldDefinition(); - - // Load and execute a view. - $view_entity = View::load('content'); - $view_executable = $view_entity->getExecutable(); - $view_executable->execute('page_1'); - - // Reset static cache, but leave possibility to use database cache. - $field_manager->useCaches(FALSE); - $field_manager->useCaches(TRUE); - - // Magic line. - unserialize(serialize(['SOMETHING UNEXPECTED', $view_executable])); - - // Make sure the serialisation of the ViewExecutable didn't influence the - // field definitions. - $nid_definition_after = $field_manager->getBaseFieldDefinitions('node')['nid'] - ->getItemDefinition() - ->getFieldDefinition(); - $this->assertEquals($nid_definition_before->getPropertyDefinitions(), $nid_definition_after->getPropertyDefinitions()); } }