Issue #2252763 by damiankloip, skipyT, martin107, dawehner, dashaforbes: Views exposed filter form causes enormous form state cache entries

8.0.x
Alex Pott 2015-03-09 15:26:26 +00:00
parent b5500b6129
commit d1c03228f1
10 changed files with 165 additions and 65 deletions

View File

@ -62,18 +62,15 @@ class BulkFormTest extends NodeTestBase {
$this->assertTrue($node->isPublished(), 'Node has been published'); $this->assertTrue($node->isPublished(), 'Node has been published');
// Make sticky action. // Make sticky action.
$node->setPublished(FALSE);
$node->save();
$this->assertFalse($node->isSticky(), 'Node is not sticky'); $this->assertFalse($node->isSticky(), 'Node is not sticky');
$edit = array( $edit = array(
'node_bulk_form[0]' => TRUE, 'node_bulk_form[0]' => TRUE,
'action' => 'node_make_sticky_action', 'action' => 'node_make_sticky_action',
); );
$this->drupalPostForm(NULL, $edit, t('Apply')); $this->drupalPostForm(NULL, $edit, t('Apply'));
// Re-load the node and check the status and sticky flag. // Re-load the node and check the sticky flag.
$node_storage->resetCache(array($node->id())); $node_storage->resetCache(array($node->id()));
$node = $node_storage->load($node->id()); $node = $node_storage->load($node->id());
$this->assertTrue($node->isPublished(), 'Node has been published');
$this->assertTrue($node->isSticky(), 'Node has been made sticky'); $this->assertTrue($node->isSticky(), 'Node has been made sticky');
// Make unsticky action. // Make unsticky action.
@ -88,18 +85,15 @@ class BulkFormTest extends NodeTestBase {
$this->assertFalse($node->isSticky(), 'Node is not sticky anymore'); $this->assertFalse($node->isSticky(), 'Node is not sticky anymore');
// Promote to front page. // Promote to front page.
$node->setPublished(FALSE);
$node->save();
$this->assertFalse($node->isPromoted(), 'Node is not promoted to the front page'); $this->assertFalse($node->isPromoted(), 'Node is not promoted to the front page');
$edit = array( $edit = array(
'node_bulk_form[0]' => TRUE, 'node_bulk_form[0]' => TRUE,
'action' => 'node_promote_action', 'action' => 'node_promote_action',
); );
$this->drupalPostForm(NULL, $edit, t('Apply')); $this->drupalPostForm(NULL, $edit, t('Apply'));
// Re-load the node and check the status and promoted flag. // Re-load the node and check the promoted flag.
$node_storage->resetCache(array($node->id())); $node_storage->resetCache(array($node->id()));
$node = $node_storage->load($node->id()); $node = $node_storage->load($node->id());
$this->assertTrue($node->isPublished(), 'Node has been published');
$this->assertTrue($node->isPromoted(), 'Node has been promoted to the front page'); $this->assertTrue($node->isPromoted(), 'Node has been promoted to the front page');
// Demote from front page. // Demote from front page.

View File

@ -433,4 +433,13 @@ class View extends ConfigEntityBase implements ViewEntityInterface {
return (bool) \Drupal::service('views.views_data')->get($this->base_table); return (bool) \Drupal::service('views.views_data')->get($this->base_table);
} }
/**
* {@inheritdoc}
*/
public function __sleep() {
$keys = parent::__sleep();
unset($keys[array_search('executable', $keys)]);
return $keys;
}
} }

View File

@ -121,7 +121,7 @@ class ViewsExposedForm extends FormBase {
$form['#id'] = Html::cleanCssIdentifier('views_exposed_form-' . String::checkPlain($view->storage->id()) . '-' . String::checkPlain($display['id'])); $form['#id'] = Html::cleanCssIdentifier('views_exposed_form-' . String::checkPlain($view->storage->id()) . '-' . String::checkPlain($display['id']));
/** @var \Drupal\views\Plugin\views\exposed_form\ExposedFormPluginBase $exposed_form_plugin */ /** @var \Drupal\views\Plugin\views\exposed_form\ExposedFormPluginBase $exposed_form_plugin */
$exposed_form_plugin = $form_state->get('exposed_form_plugin'); $exposed_form_plugin = $view->display_handler->getPlugin('exposed_form');
$exposed_form_plugin->exposedFormAlter($form, $form_state); $exposed_form_plugin->exposedFormAlter($form, $form_state);
// Save the form. // Save the form.
@ -134,15 +134,17 @@ class ViewsExposedForm extends FormBase {
* {@inheritdoc} * {@inheritdoc}
*/ */
public function validateForm(array &$form, FormStateInterface $form_state) { public function validateForm(array &$form, FormStateInterface $form_state) {
$view = $form_state->get('view');
foreach (array('field', 'filter') as $type) { foreach (array('field', 'filter') as $type) {
/** @var \Drupal\views\Plugin\views\ViewsHandlerInterface[] $handlers */ /** @var \Drupal\views\Plugin\views\ViewsHandlerInterface[] $handlers */
$handlers = &$form_state->get('view')->$type; $handlers = &$view->$type;
foreach ($handlers as $key => $handler) { foreach ($handlers as $key => $handler) {
$handlers[$key]->validateExposed($form, $form_state); $handlers[$key]->validateExposed($form, $form_state);
} }
} }
/** @var \Drupal\views\Plugin\views\exposed_form\ExposedFormPluginBase $exposed_form_plugin */ /** @var \Drupal\views\Plugin\views\exposed_form\ExposedFormPluginBase $exposed_form_plugin */
$exposed_form_plugin = $form_state->get('exposed_form_plugin'); $exposed_form_plugin = $view->display_handler->getPlugin('exposed_form');
$exposed_form_plugin->exposedFormValidate($form, $form_state); $exposed_form_plugin->exposedFormValidate($form, $form_state);
} }
@ -157,13 +159,14 @@ class ViewsExposedForm extends FormBase {
$handlers[$key]->submitExposed($form, $form_state); $handlers[$key]->submitExposed($form, $form_state);
} }
} }
$view = $form_state->get('view'); $view = $form_state->get('view');
$view->exposed_data = $form_state->getValues(); $view->exposed_data = $form_state->getValues();
$view->exposed_raw_input = []; $view->exposed_raw_input = [];
$exclude = array('submit', 'form_build_id', 'form_id', 'form_token', 'exposed_form_plugin', '', 'reset'); $exclude = array('submit', 'form_build_id', 'form_id', 'form_token', 'exposed_form_plugin', 'reset');
/** @var \Drupal\views\Plugin\views\exposed_form\ExposedFormPluginBase $exposed_form_plugin */ /** @var \Drupal\views\Plugin\views\exposed_form\ExposedFormPluginBase $exposed_form_plugin */
$exposed_form_plugin = $form_state->get('exposed_form_plugin'); $exposed_form_plugin = $view->display_handler->getPlugin('exposed_form');
$exposed_form_plugin->exposedFormSubmit($form, $form_state, $exclude); $exposed_form_plugin->exposedFormSubmit($form, $form_state, $exclude);
foreach ($form_state->getValues() as $key => $value) { foreach ($form_state->getValues() as $key => $value) {

View File

@ -150,7 +150,6 @@ abstract class ExposedFormPluginBase extends PluginBase {
$form_state->set('ajax', TRUE); $form_state->set('ajax', TRUE);
} }
$form_state->set('exposed_form_plugin', $this);
$form = \Drupal::formBuilder()->buildForm('\Drupal\views\Form\ViewsExposedForm', $form_state); $form = \Drupal::formBuilder()->buildForm('\Drupal\views\Form\ViewsExposedForm', $form_state);
if (!$this->view->display_handler->displaysExposed() || (!$block && $this->view->display_handler->getOption('exposed_block'))) { if (!$this->view->display_handler->displaysExposed() || (!$block && $this->view->display_handler->getOption('exposed_block'))) {

View File

@ -54,6 +54,13 @@ use Drupal\views\Views;
*/ */
abstract class RelationshipPluginBase extends HandlerBase { abstract class RelationshipPluginBase extends HandlerBase {
/**
* The relationship alias.
*
* @var string
*/
public $alias;
/** /**
* Overrides \Drupal\views\Plugin\views\HandlerBase::init(). * Overrides \Drupal\views\Plugin\views\HandlerBase::init().
* *

View File

@ -449,6 +449,7 @@ class ViewExecutableTest extends ViewUnitTestBase {
$errors = $executable->validate(); $errors = $executable->validate();
$total_error_count = array_reduce($errors, function ($carry, $item) { $total_error_count = array_reduce($errors, function ($carry, $item) {
$carry += count($item); $carry += count($item);
return $carry; return $carry;
}); });
// Assert that there were 9 total errors across 3 displays. // Assert that there were 9 total errors across 3 displays.
@ -456,4 +457,29 @@ class ViewExecutableTest extends ViewUnitTestBase {
$this->assertIdentical(3, count($errors)); $this->assertIdentical(3, count($errors));
} }
/**
* Tests serialization of the ViewExecutable object.
*/
public function testSerialization() {
$view = Views::getView('test_executable_displays');
$view->setDisplay('page_1');
$view->setArguments(['test']);
$view->setCurrentPage(2);
$serialized = serialize($view);
// Test the view storage object is not present in the actual serialized
// string.
$this->assertIdentical(strpos($serialized, '"Drupal\views\Entity\View"'), FALSE, 'The Drupal\views\Entity\View class was not found in the serialized string.');
/** @var \Drupal\views\ViewExecutable $unserialized */
$unserialized = unserialize($serialized);
$this->assertTrue($unserialized instanceof ViewExecutable);
$this->assertIdentical($view->storage->id(), $unserialized->storage->id(), 'The expected storage entity was loaded on the unserialized view.');
$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.');
}
} }

View File

@ -26,7 +26,7 @@ use Symfony\Component\HttpFoundation\Response;
* An object to contain all of the data to generate a view, plus the member * 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. * functions to build the view query, execute the query and render the output.
*/ */
class ViewExecutable { class ViewExecutable implements \Serializable {
use DependencySerializationTrait; use DependencySerializationTrait;
/** /**
@ -2295,4 +2295,49 @@ class ViewExecutable {
return $this->storage->calculateDependencies(); return $this->storage->calculateDependencies();
} }
/**
* {@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,
]);
}
/**
* {@inheritdoc}
*/
public function unserialize($serialized) {
list($storage, $current_display, $args, $current_page, $exposed_input, $exposed_raw_input, $exposed_data, $dom_id, $executed) = unserialize($serialized);
$this->setRequest(\Drupal::request());
$this->user = \Drupal::currentUser();
$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 ($executed) {
$this->execute($this->current_display);
}
}
} }

View File

@ -266,6 +266,7 @@ class ViewEditForm extends ViewFormBase {
public function save(array $form, FormStateInterface $form_state) { public function save(array $form, FormStateInterface $form_state) {
$view = $this->entity; $view = $this->entity;
$executable = $view->getExecutable(); $executable = $view->getExecutable();
$executable->initDisplay();
// Go through and remove displayed scheduled for removal. // Go through and remove displayed scheduled for removal.
$displays = $view->get('display'); $displays = $view->get('display');

View File

@ -115,13 +115,6 @@ class ViewUI implements ViewEntityInterface {
*/ */
protected $storage; protected $storage;
/**
* The View executable object.
*
* @var \Drupal\views\ViewExecutable
*/
protected $executable;
/** /**
* Stores a list of database queries run beside the main one from views. * Stores a list of database queries run beside the main one from views.
* *
@ -170,13 +163,9 @@ class ViewUI implements ViewEntityInterface {
* @param \Drupal\views\ViewEntityInterface $storage * @param \Drupal\views\ViewEntityInterface $storage
* The View storage object to wrap. * The View storage object to wrap.
*/ */
public function __construct(ViewEntityInterface $storage, ViewExecutable $executable = NULL) { public function __construct(ViewEntityInterface $storage) {
$this->entityType = 'view'; $this->entityType = 'view';
$this->storage = $storage; $this->storage = $storage;
if (!isset($executable)) {
$executable = Views::executableFactory()->get($this);
}
$this->executable = $executable;
} }
/** /**
@ -259,7 +248,7 @@ class ViewUI implements ViewEntityInterface {
$display_id = $form_state->get('display_id'); $display_id = $form_state->get('display_id');
if ($revert) { if ($revert) {
// If it's revert just change the override and return. // If it's revert just change the override and return.
$display = &$this->executable->displayHandlers->get($display_id); $display = &$this->getExecutable()->displayHandlers->get($display_id);
$display->optionsOverride($form, $form_state); $display->optionsOverride($form, $form_state);
// Don't execute the normal submit handling but still store the changed view into cache. // Don't execute the normal submit handling but still store the changed view into cache.
@ -273,7 +262,7 @@ class ViewUI implements ViewEntityInterface {
elseif ($was_defaulted && !$is_defaulted) { elseif ($was_defaulted && !$is_defaulted) {
// We were using the default display's values, but we're now overriding // We were using the default display's values, but we're now overriding
// the default display and saving values specific to this display. // the default display and saving values specific to this display.
$display = &$this->executable->displayHandlers->get($display_id); $display = &$this->getExecutable()->displayHandlers->get($display_id);
// optionsOverride toggles the override of this section. // optionsOverride toggles the override of this section.
$display->optionsOverride($form, $form_state); $display->optionsOverride($form, $form_state);
$display->submitOptionsForm($form, $form_state); $display->submitOptionsForm($form, $form_state);
@ -283,7 +272,7 @@ class ViewUI implements ViewEntityInterface {
// to go back to the default display. // to go back to the default display.
// Overwrite the default display with the current form values, and make // Overwrite the default display with the current form values, and make
// the current display use the new default values. // the current display use the new default values.
$display = &$this->executable->displayHandlers->get($display_id); $display = &$this->getExecutable()->displayHandlers->get($display_id);
// optionsOverride toggles the override of this section. // optionsOverride toggles the override of this section.
$display->optionsOverride($form, $form_state); $display->optionsOverride($form, $form_state);
$display->submitOptionsForm($form, $form_state); $display->submitOptionsForm($form, $form_state);
@ -481,7 +470,7 @@ class ViewUI implements ViewEntityInterface {
if ($was_defaulted && !$is_defaulted) { if ($was_defaulted && !$is_defaulted) {
// We were using the default display's values, but we're now overriding // We were using the default display's values, but we're now overriding
// the default display and saving values specific to this display. // the default display and saving values specific to this display.
$display = &$this->executable->displayHandlers->get($display_id); $display = &$this->getExecutable()->displayHandlers->get($display_id);
// setOverride toggles the override of this section. // setOverride toggles the override of this section.
$display->setOverride($section); $display->setOverride($section);
} }
@ -490,7 +479,7 @@ class ViewUI implements ViewEntityInterface {
// to go back to the default display. // to go back to the default display.
// Overwrite the default display with the current form values, and make // Overwrite the default display with the current form values, and make
// the current display use the new default values. // the current display use the new default values.
$display = &$this->executable->displayHandlers->get($display_id); $display = &$this->getExecutable()->displayHandlers->get($display_id);
// optionsOverride toggles the override of this section. // optionsOverride toggles the override of this section.
$display->setOverride($section); $display->setOverride($section);
} }
@ -503,7 +492,7 @@ class ViewUI implements ViewEntityInterface {
if ($cut = strpos($field, '$')) { if ($cut = strpos($field, '$')) {
$field = substr($field, 0, $cut); $field = substr($field, 0, $cut);
} }
$id = $this->executable->addHandler($display_id, $type, $table, $field); $id = $this->getExecutable()->addHandler($display_id, $type, $table, $field);
// check to see if we have group by settings // check to see if we have group by settings
$key = $type; $key = $type;
@ -516,7 +505,7 @@ class ViewUI implements ViewEntityInterface {
'field' => $field, 'field' => $field,
); );
$handler = Views::handlerManager($key)->getHandler($item); $handler = Views::handlerManager($key)->getHandler($item);
if ($this->executable->displayHandlers->get('default')->useGroupBy() && $handler->usesGroupBy()) { if ($this->getExecutable()->displayHandlers->get('default')->useGroupBy() && $handler->usesGroupBy()) {
$this->addFormToStack('handler-group', $display_id, $type, $id); $this->addFormToStack('handler-group', $display_id, $type, $id);
} }
@ -564,6 +553,7 @@ class ViewUI implements ViewEntityInterface {
// Save the current path so it can be restored before returning from this function. // Save the current path so it can be restored before returning from this function.
$request_stack = \Drupal::requestStack(); $request_stack = \Drupal::requestStack();
$current_request = $request_stack->getCurrentRequest(); $current_request = $request_stack->getCurrentRequest();
$executable = $this->getExecutable();
// Determine where the query and performance statistics should be output. // Determine where the query and performance statistics should be output.
$config = \Drupal::config('views.settings'); $config = \Drupal::config('views.settings');
@ -580,11 +570,11 @@ class ViewUI implements ViewEntityInterface {
$rows = array('query' => array(), 'statistics' => array()); $rows = array('query' => array(), 'statistics' => array());
$errors = $this->executable->validate(); $errors = $this->getExecutable()->validate();
$this->executable->destroy(); $executable->destroy();
if (empty($errors)) { if (empty($errors)) {
$this->ajax = TRUE; $this->ajax = TRUE;
$this->executable->live_preview = TRUE; $executable->live_preview = TRUE;
// AJAX happens via HTTP POST but everything expects exposed data to // AJAX happens via HTTP POST but everything expects exposed data to
// be in GET. Copy stuff but remove ajax-framework specific keys. // be in GET. Copy stuff but remove ajax-framework specific keys.
@ -597,19 +587,19 @@ class ViewUI implements ViewEntityInterface {
unset($exposed_input[$key]); unset($exposed_input[$key]);
} }
} }
$this->executable->setExposedInput($exposed_input); $executable->setExposedInput($exposed_input);
if (!$this->executable->setDisplay($display_id)) { if (!$executable->setDisplay($display_id)) {
return [ return [
'#markup' => t('Invalid display id @display', array('@display' => $display_id)), '#markup' => t('Invalid display id @display', array('@display' => $display_id)),
]; ];
} }
$this->executable->setArguments($args); $executable->setArguments($args);
// Store the current view URL for later use: // Store the current view URL for later use:
if ($this->executable->display_handler->getOption('path')) { if ($executable->display_handler->getOption('path')) {
$path = $this->executable->getUrl(); $path = $executable->getUrl();
} }
// Make view links come back to preview. // Make view links come back to preview.
@ -646,7 +636,7 @@ class ViewUI implements ViewEntityInterface {
} }
// Execute/get the view preview. // Execute/get the view preview.
$preview = $this->executable->preview($display_id, $args); $preview = $executable->preview($display_id, $args);
if ($show_additional_queries) { if ($show_additional_queries) {
$this->endQueryCapture(); $this->endQueryCapture();
@ -660,13 +650,13 @@ class ViewUI implements ViewEntityInterface {
// below the view preview. // below the view preview.
if ($show_info || $show_query || $show_stats) { if ($show_info || $show_query || $show_stats) {
// Get information from the preview for display. // Get information from the preview for display.
if (!empty($this->executable->build_info['query'])) { if (!empty($executable->build_info['query'])) {
if ($show_query) { if ($show_query) {
$query_string = $this->executable->build_info['query']; $query_string = $executable->build_info['query'];
// Only the sql default class has a method getArguments. // Only the sql default class has a method getArguments.
$quoted = array(); $quoted = array();
if ($this->executable->query instanceof Sql) { if ($executable->query instanceof Sql) {
$quoted = $query_string->getArguments(); $quoted = $query_string->getArguments();
$connection = Database::getConnection(); $connection = Database::getConnection();
foreach ($quoted as $key => $val) { foreach ($quoted as $key => $val) {
@ -722,7 +712,7 @@ class ViewUI implements ViewEntityInterface {
'#template' => "<strong>{% trans 'Title' %}</strong>", '#template' => "<strong>{% trans 'Title' %}</strong>",
), ),
), ),
Xss::filterAdmin($this->executable->getTitle()), Xss::filterAdmin($executable->getTitle()),
); );
if (isset($path)) { if (isset($path)) {
// @todo Views should expect and store a leading /. See: // @todo Views should expect and store a leading /. See:
@ -743,7 +733,7 @@ class ViewUI implements ViewEntityInterface {
'#template' => "<strong>{% trans 'Query build time' %}</strong>", '#template' => "<strong>{% trans 'Query build time' %}</strong>",
), ),
), ),
t('@time ms', array('@time' => intval($this->executable->build_time * 100000) / 100)), t('@time ms', array('@time' => intval($this->getExecutable()->build_time * 100000) / 100)),
); );
$rows['statistics'][] = array( $rows['statistics'][] = array(
@ -753,7 +743,7 @@ class ViewUI implements ViewEntityInterface {
'#template' => "<strong>{% trans 'Query execute time' %}</strong>", '#template' => "<strong>{% trans 'Query execute time' %}</strong>",
), ),
), ),
t('@time ms', array('@time' => intval($this->executable->execute_time * 100000) / 100)), t('@time ms', array('@time' => intval($this->getExecutable()->execute_time * 100000) / 100)),
); );
$rows['statistics'][] = array( $rows['statistics'][] = array(
@ -763,10 +753,10 @@ class ViewUI implements ViewEntityInterface {
'#template' => "<strong>{% trans 'View render time' %}</strong>", '#template' => "<strong>{% trans 'View render time' %}</strong>",
), ),
), ),
t('@time ms', array('@time' => intval($this->executable->render_time * 100000) / 100)), t('@time ms', array('@time' => intval($executable->render_time * 100000) / 100)),
); );
} }
\Drupal::moduleHandler()->alter('views_preview_info', $rows, $this->executable); \Drupal::moduleHandler()->alter('views_preview_info', $rows, $executable);
} }
else { else {
// No query was run. Display that information in place of either the // No query was run. Display that information in place of either the
@ -873,14 +863,14 @@ class ViewUI implements ViewEntityInterface {
if (isset($executable->current_display)) { if (isset($executable->current_display)) {
// Add the knowledge of the changed display, too. // Add the knowledge of the changed display, too.
$this->changed_display[$executable->current_display] = TRUE; $this->changed_display[$executable->current_display] = TRUE;
unset($executable->current_display); $executable->current_display = NULL;
} }
// Unset handlers; we don't want to write these into the cache. // Unset handlers. We don't want to write these into the cache.
unset($executable->display_handler); $executable->display_handler = NULL;
unset($executable->default_display); $executable->default_display = NULL;
$executable->query = NULL; $executable->query = NULL;
unset($executable->displayHandlers); $executable->displayHandlers = NULL;
\Drupal::service('user.shared_tempstore')->get('views')->set($this->id(), $this); \Drupal::service('user.shared_tempstore')->get('views')->set($this->id(), $this);
} }
@ -1239,13 +1229,6 @@ class ViewUI implements ViewEntityInterface {
return $this->storage->addDisplay($plugin_id, $title, $id); return $this->storage->addDisplay($plugin_id, $title, $id);
} }
/**
* {@inheritdoc}
*/
public function getViewExecutable() {
return $this->storage->getViewExecutable();
}
/** /**
* {@inheritdoc} * {@inheritdoc}
*/ */
@ -1287,4 +1270,5 @@ class ViewUI implements ViewEntityInterface {
public function getThirdPartyProviders() { public function getThirdPartyProviders() {
return $this->storage->getThirdPartyProviders(); return $this->storage->getThirdPartyProviders();
} }
} }

View File

@ -9,6 +9,7 @@ namespace Drupal\Tests\views_ui\Unit;
use Drupal\Core\Language\LanguageInterface; use Drupal\Core\Language\LanguageInterface;
use Drupal\Tests\UnitTestCase; use Drupal\Tests\UnitTestCase;
use Drupal\views\Entity\View;
use Drupal\views\ViewExecutable; use Drupal\views\ViewExecutable;
use Drupal\views_ui\ViewUI; use Drupal\views_ui\ViewUI;
use Symfony\Component\DependencyInjection\Container; use Symfony\Component\DependencyInjection\Container;
@ -54,8 +55,9 @@ class ViewUIObjectTest extends UnitTestCase {
->disableOriginalConstructor() ->disableOriginalConstructor()
->setConstructorArgs(array($storage)) ->setConstructorArgs(array($storage))
->getMock(); ->getMock();
$storage->set('executable', $executable);
$view_ui = new ViewUI($storage, $executable); $view_ui = new ViewUI($storage);
foreach ($method_args as $method => $args) { foreach ($method_args as $method => $args) {
$method_mock = $storage->expects($this->once()) $method_mock = $storage->expects($this->once())
@ -80,6 +82,7 @@ class ViewUIObjectTest extends UnitTestCase {
->disableOriginalConstructor() ->disableOriginalConstructor()
->setConstructorArgs(array($storage)) ->setConstructorArgs(array($storage))
->getMock(); ->getMock();
$storage->set('executable', $executable);
$account = $this->getMock('Drupal\Core\Session\AccountInterface'); $account = $this->getMock('Drupal\Core\Session\AccountInterface');
$account->expects($this->exactly(2)) $account->expects($this->exactly(2))
->method('id') ->method('id')
@ -89,7 +92,7 @@ class ViewUIObjectTest extends UnitTestCase {
$container->set('current_user', $account); $container->set('current_user', $account);
\Drupal::setContainer($container); \Drupal::setContainer($container);
$view_ui = new ViewUI($storage, $executable); $view_ui = new ViewUI($storage);
// A view_ui without a lock object is not locked. // A view_ui without a lock object is not locked.
$this->assertFalse($view_ui->isLocked()); $this->assertFalse($view_ui->isLocked());
@ -113,4 +116,33 @@ class ViewUIObjectTest extends UnitTestCase {
$this->assertFalse($view_ui->isLocked()); $this->assertFalse($view_ui->isLocked());
} }
/**
* Tests serialization of the ViewUI object.
*/
public function testSerialization() {
// Set a container so the DependencySerializationTrait has it.
$container = new ContainerBuilder();
\Drupal::setContainer($container);
$storage = new View([], 'view');
$executable = $this->getMockBuilder('Drupal\views\ViewExecutable')
->disableOriginalConstructor()
->setConstructorArgs([$storage])
->getMock();
$storage->set('executable', $executable);
$view_ui = new ViewUI($storage);
// Make sure the executable is returned before serializing.
$this->assertInstanceOf('Drupal\views\ViewExecutable', $view_ui->getExecutable());
$serialized = serialize($view_ui);
// Make sure the ViewExecutable class is not found in the serialized string.
$this->assertSame(strpos($serialized, '"Drupal\views\ViewExecutable"'), FALSE);
$unserialized = unserialize($serialized);
$this->assertInstanceOf('Drupal\views_ui\ViewUI', $unserialized);
}
} }