Commit 111e9b80 authored by tim.plunkett's avatar tim.plunkett
Browse files

Issue #1751358 by tim.plunkett, dawehner: Allow ViewStorage and ViewExecutable...

Issue #1751358 by tim.plunkett, dawehner: Allow ViewStorage and ViewExecutable to access each other's properties.
parent ad514aea
......@@ -1722,9 +1722,6 @@ function views_ui_edit_form_get_build_from_option($id, $option, $view, $display)
}
}
$option_build['#attributes']['class'][] = drupal_clean_css_identifier($display_id . '-' . $id);
if (!empty($view->changed_sections[$display_id . '-' . $id])) {
$option_build['#changed'] = TRUE;
}
return $option_build;
}
......@@ -2259,10 +2256,6 @@ function views_ui_edit_form_get_bucket($type, $view, $display) {
}
$build['fields'][$id]['#link'] = l($link_text, "admin/structure/views/nojs/config-item/$view->name/$display->id/$type/$id", array('attributes' => $link_attributes, 'html' => TRUE));
$build['fields'][$id]['#class'][] = drupal_clean_css_identifier($display->id . '-' . $type . '-' . $id);
if (!empty($view->changed_sections[$display->id . '-' . $type . '-' . $id])) {
// @TODO: #changed is no longer being used?
$build['fields'][$id]['#changed'] = TRUE;
}
if ($display->handler->useGroupBy() && $handler->usesGroupBy()) {
$build['fields'][$id]['#settings_links'][] = l('<span class="label">' . t('Aggregation settings') . '</span>', "admin/structure/views/nojs/config-item-group/$view->name/$display->id/$type/$id", array('attributes' => array('class' => 'views-button-configure views-ajax-link', 'title' => t('Aggregation settings')), 'html' => TRUE));
......@@ -2458,12 +2451,6 @@ function views_ui_standard_submit($form, &$form_state) {
list($was_defaulted, $is_defaulted, $revert) = views_ui_standard_override_values($form, $form_state);
// Mark the changed section of the view as changed.
// TODO: Document why we are doing this, and see if we still need it.
if (!empty($form['#section'])) {
$form_state['view']->changed_sections[$form['#section']] = TRUE;
}
// Based on the user's choice in the display dropdown, determine which display
// these changes apply to.
if ($revert) {
......
......@@ -32,7 +32,7 @@ class Analyzer {
* @param Drupal\views\ViewExecutable $view
* (optional) The view to analyze.
*/
function __construct(View $view = NULL) {
function __construct(ViewExecutable $view = NULL) {
if (isset($view)) {
$this->view = $view;
}
......@@ -44,7 +44,7 @@ function __construct(View $view = NULL) {
* @param Drupal\views\ViewExecutable
* The view to analyze.
*/
public function setView(View $view = NULL) {
public function setView(ViewExecutable $view = NULL) {
$this->view = $view;
}
......
......@@ -786,7 +786,7 @@ function default_summary() {
// Summaries have their own sorting and fields, so tell the View not
// to build these.
$this->view->build_sort = $this->view->build_fields = FALSE;
$this->view->build_sort = FALSE;
return TRUE;
}
......
......@@ -244,7 +244,6 @@ public function attachTo($display_id) {
// Get a fresh view because our current one has a lot of stuff on it because it's
// already been executed.
$view = $this->view->cloneView();
$view->original_args = $view->args;
$args = $this->getOption('inherit_arguments') ? $this->view->args : array();
$view->setArguments($args);
......
......@@ -1061,7 +1061,7 @@ protected function retrieve_validated_view(array $form, array &$form_state, $uns
* @param Drupal\views\ViewExecutable $view
* The validated view object.
*/
protected function set_validated_view(array $form, array &$form_state, View $view) {
protected function set_validated_view(array $form, array &$form_state, ViewExecutable $view) {
$key = hash('sha256', serialize($form_state['values']));
$this->validated_views[$key] = $view;
}
......
......@@ -41,7 +41,7 @@ function testAnalyzeBasic() {
$this->drupalLogin($this->admin);
// Enable the frontpage view and click the analyse button.
$view = views_get_view('frontpage');
$view->save();
$view = $view->createDuplicate();
$this->drupalGet('admin/structure/views/view/frontpage/edit');
$this->assertLink(t('analyze view'));
......
......@@ -92,6 +92,7 @@ public function testQuery() {
*/
public function testClickSorting() {
$this->drupalGet('test_click_sort');
$this->assertResponse(200);
// Only the id and name should be click sortable, but not the name.
$this->assertLinkByHref(url('test_click_sort', array('query' => array('order' => 'id', 'sort' => 'asc'))));
$this->assertLinkByHref(url('test_click_sort', array('query' => array('order' => 'name', 'sort' => 'desc'))));
......
......@@ -37,8 +37,7 @@ protected function setUp() {
*/
protected function getBasicView() {
// Create the basic view.
$view = new View(array(), 'view');
$view->name = 'test_view';
$view = $this->createViewFromConfig('test_view');
$view->addDisplay('default');
$view->base_table = 'views_test_data';
......@@ -169,12 +168,11 @@ function testHeaderStorage() {
));
$view->preview();
$view->destroy();
unset($view->pre_render_called);
drupal_static_reset('drupal_add_css');
drupal_static_reset('drupal_add_js');
$view->initDisplay();
$view = $this->getView($view);
$view->preview();
$css = drupal_add_css();
$css_path = drupal_get_path('module', 'views_test_data') . '/views_cache.test.css';
......@@ -183,8 +181,7 @@ function testHeaderStorage() {
$this->assertTrue(isset($css[$css_path]), 'Make sure the css is added for cached views.');
$this->assertTrue(isset($js[$js_path]), 'Make sure the js is added for cached views.');
$this->assertFalse(!empty($view->pre_render_called), 'Make sure hook_views_pre_render is not called for the cached view.');
$view->destroy();
$this->assertFalse(!empty($view->build_info['pre_render_called']), 'Make sure hook_views_pre_render is not called for the cached view.');
// Now add some css/jss before running the view.
// Make sure that this css is not added when running the cached view.
......@@ -195,13 +192,12 @@ function testHeaderStorage() {
$system_js_path = drupal_get_path('module', 'system') . '/system.cron.js';
drupal_add_js($system_js_path);
$view->initDisplay();
$view = $this->getView($view);
$view->preview();
$view->destroy();
drupal_static_reset('drupal_add_css');
drupal_static_reset('drupal_add_js');
$view->initDisplay();
$view = $this->getView($view);
$view->preview();
$css = drupal_add_css();
......@@ -209,7 +205,6 @@ function testHeaderStorage() {
$this->assertFalse(isset($css[$system_css_path]), 'Make sure that unrelated css is not added.');
$this->assertFalse(isset($js[$system_js_path]), 'Make sure that unrelated js is not added.');
}
}
......@@ -62,6 +62,7 @@ public function testRenameResetButton() {
// Look whether ther reset button label changed.
$this->drupalGet('test_rename_reset_button');
$this->assertResponse(200);
$this->helperButtonHasLabel('edit-reset', $expected_label);
}
......
......@@ -52,6 +52,7 @@ function testDefaultViews() {
$this->drupalPost('admin/structure/views/nojs/display/frontpage/page/title', $edit, t('Apply'));
$this->drupalPost('admin/structure/views/view/frontpage/edit/page', array(), t('Save'));
$this->drupalGet('frontpage');
$this->assertResponse(200);
$this->assertText($new_title);
// It should now be possible to revert the view. Do that, and make sure the
......
......@@ -62,6 +62,7 @@ function testOverrideDisplays() {
// Make sure the title appears in both the page and the block.
$this->drupalGet($view_path);
$this->assertResponse(200);
$this->assertText($original_title);
$this->drupalGet('');
$this->assertText($original_title);
......@@ -74,6 +75,7 @@ function testOverrideDisplays() {
$this->drupalPost("admin/structure/views/nojs/display/{$view['name']}/page/title", $edit, t('Apply'));
$this->drupalPost("admin/structure/views/view/{$view['name']}/edit/page", array(), t('Save'));
$this->drupalGet($view_path);
$this->assertResponse(200);
$this->assertText($new_title);
$this->assertNoText($original_title);
$this->drupalGet('');
......@@ -119,9 +121,11 @@ function testWizardMixedDefaultOverriddenDisplays() {
// Make sure that the feed, page and block all start off with the correct
// titles.
$this->drupalGet($view['page[path]']);
$this->assertResponse(200);
$this->assertText($view['page[title]']);
$this->assertNoText($view['block[title]']);
$this->drupalGet($view['page[feed_properties][path]']);
$this->assertResponse(200);
$this->assertText($view['page[title]']);
$this->assertNoText($view['block[title]']);
$this->drupalGet('');
......@@ -135,10 +139,12 @@ function testWizardMixedDefaultOverriddenDisplays() {
$this->drupalPost("admin/structure/views/nojs/display/{$view['name']}/page/title", $edit, t('Apply'));
$this->drupalPost("admin/structure/views/view/{$view['name']}/edit/page", array(), t('Save'));
$this->drupalGet($view['page[path]']);
$this->assertResponse(200);
$this->assertText($new_default_title);
$this->assertNoText($view['page[title]']);
$this->assertNoText($view['block[title]']);
$this->drupalGet($view['page[feed_properties][path]']);
$this->assertResponse(200);
$this->assertText($new_default_title);
$this->assertNoText($view['page[title]']);
$this->assertNoText($view['block[title]']);
......@@ -154,9 +160,11 @@ function testWizardMixedDefaultOverriddenDisplays() {
$this->drupalPost("admin/structure/views/nojs/display/{$view['name']}/block/title", $edit, t('Apply'));
$this->drupalPost("admin/structure/views/view/{$view['name']}/edit/block", array(), t('Save'));
$this->drupalGet($view['page[path]']);
$this->assertResponse(200);
$this->assertText($new_default_title);
$this->assertNoText($new_block_title);
$this->drupalGet($view['page[feed_properties][path]']);
$this->assertResponse(200);
$this->assertText($new_default_title);
$this->assertNoText($new_block_title);
$this->drupalGet('');
......
......@@ -61,8 +61,7 @@ public function testProperties() {
$view = $this->getView();
$storage = $view->storage;
foreach ($this->configProperties as $property) {
$this->assertTrue(isset($view->{$property}));
$this->assertIdentical($view->{$property}, $storage->{$storage});
$this->assertIdentical($view->{$property}, $storage->{$property}, format_string("Property '%property' is set on the stored view.", array('%property' => $property)));
}
foreach ($this->executableProperties as $property) {
$this->assertTrue(isset($view->{$property}));
......
......@@ -9,7 +9,7 @@
use Drupal\simpletest\WebTestBase;
use Drupal\views\ViewStorageController;
use Drupal\views\ViewExecutable;
use Drupal\views\ViewStorage;
use Drupal\views\ViewDisplay;
use Drupal\views\Plugin\views\display\Page;
......@@ -91,8 +91,7 @@ function testConfigurationEntityCRUD() {
* Tests loading configuration entities.
*/
protected function loadTests() {
$storage = $this->loadView('archive');
$view = new ViewExecutable();
$view = $this->loadView('archive');
$data = config('views.view.archive')->get();
// Confirm that an actual view object is loaded and that it returns all of
......@@ -150,7 +149,7 @@ protected function createTests() {
// Create a new View instance with empty values.
$created = $this->controller->create(array());
$this->assertTrue($created instanceof View, 'Created object is a View.');
$this->assertTrue($created instanceof ViewStorage, 'Created object is a View.');
// Check that the View contains all of the properties.
foreach ($this->config_properties as $property) {
$this->assertTrue(property_exists($created, $property), format_string('Property: @property created on View.', array('@property' => $property)));
......@@ -160,7 +159,7 @@ protected function createTests() {
$values = config('views.view.glossary')->get();
$created = $this->controller->create($values);
$this->assertTrue($created instanceof View, 'Created object is a View.');
$this->assertTrue($created instanceof ViewStorage, 'Created object is a View.');
// Check that the View contains all of the properties.
$properties = $this->config_properties;
// Remove display from list.
......@@ -251,7 +250,6 @@ protected function displayTests() {
// Ensure the right display_plugin is created/instantiated.
$this->assertEqual($new_display->display_plugin, 'page', 'New page display "test" uses the right display plugin.');
$view->initDisplay();
$this->assertTrue($new_display->handler instanceof Page, 'New page display "test" uses the right display plugin.');
......
......@@ -8,6 +8,7 @@
namespace Drupal\views\Tests;
use Drupal\views\ViewExecutable;
use Drupal\views\ViewStorage;
/**
* Views class tests.
......@@ -112,7 +113,7 @@ public function testCreateDuplicate() {
$view = views_get_view('archive');
$copy = $view->createDuplicate();
$this->assertTrue($copy instanceof View, 'The copied object is a View.');
$this->assertTrue($copy instanceof ViewStorage, 'The copied object is a View.');
// Check that the original view and the copy have different uuids.
$this->assertNotIdentical($view->uuid(), $copy->uuid(), 'The copied view has a new uuid.');
......
......@@ -5,6 +5,8 @@
*/
namespace Drupal\views\Tests;
use Drupal\views\ViewExecutable;
use Drupal\simpletest\WebTestBase;
/**
......@@ -413,6 +415,7 @@ protected function createViewFromConfig($view_name) {
$data = config("views.view.$view_name")->get();
$view = entity_create('view', $data);
$view = new ViewExecutable($view);
$view->setDisplay();
return $view;
......@@ -425,7 +428,7 @@ protected function createViewFromConfig($view_name) {
* (optional) The view to clone. If not specified, the default view for the
* test will be used.
*
* @return Drupal\views\ViewStorage
* @return Drupal\views\ViewExecutable
* A clone of the view.
*/
protected function getView($original_view = NULL) {
......
......@@ -21,16 +21,19 @@
* functions to build the view query, execute the query and render the output.
*/
class ViewExecutable {
/**
* The config entity in which the view is stored.
*
* @var Drupal\views\ViewStorage
*/
protected $storage;
public $storage;
/**
* Whether or not the view has been built.
*
* @todo Group with other static properties.
*
* @var bool
*/
public $built = FALSE;
......@@ -38,6 +41,8 @@ class ViewExecutable {
/**
* Whether the view has been executed/query has been run.
*
* @todo Group with other static properties.
*
* @var bool
*/
public $executed = FALSE;
......@@ -45,6 +50,8 @@ class ViewExecutable {
/**
* Indicates if a view is currently being edited.
*
* @todo Group with other UI-only properties.
*
* @var bool
*/
public $editing = FALSE;
......@@ -208,14 +215,6 @@ class ViewExecutable {
*/
public $style_plugin;
/**
* Stored the changed options of the style plugin.
*
* @deprecated Better use $view->style_plugin->options
* @var array
*/
public $style_options;
/**
* Stores the current active row while rendering.
*
......@@ -329,42 +328,217 @@ class ViewExecutable {
*/
protected $response = NULL;
/**
* Stores an array of errors for any displays.
*
* @todo Group with other UI-only properties.
*
* @var array
*/
public $display_errors;
/**
* Stores an array of displays that have been changed.
*
* @todo Group with other UI-only properties.
*
* @var array
*/
public $changed_display;
/**
* Does this view already have loaded it's handlers.
*
* @todo Group with other static properties.
*
* @var bool
*/
public $inited;
/**
* The name of the active style plugin of the view.
*
* @todo remove this and just use $this->style_plugin
*
* @var string
*/
public $plugin_name;
/**
* The options used by the style plugin of this running view.
*
* @todo To be able to remove it, Drupal\views\Plugin\views\argument\ArgumentPluginBase::default_summary()
* should instantiate the style plugin.
* @var array
*/
public $style_options;
/**
* The rendered output of the exposed form.
*
* @var string
*/
public $exposed_widgets;
/**
* If this view has been previewed.
*
* @var bool
*/
public $preview;
/**
* Force the query to calculate the total number of results.
*
* @todo Move to the query.
*
* @var bool
*/
public $get_total_rows;
/**
* Indicates if the sorts have been built.
*
* @todo Group with other static properties.
*
* @var bool
*/
public $build_sort;
/**
* How long the view takes to build.
*
* @todo Group with other UI-only properties.
*
* @var int
*/
public $build_time;
/**
* How long the view takes to render.
*
* @todo Group with other UI-only properties.
*
* @var int
*/
public $render_time;
/**
* How long the view takes to execute.
*
* @todo Group with other UI-only properties.
*
* @var int
*/
public $execute_time;
/**
* If this view is locked for editing.
*
* @todo Group with other UI-only properties.
*
* @var bool
*/
public $locked;
/**
* If this view has been changed.
*
* @todo Group with other UI-only properties.
*
* @var bool
*/
public $changed;
/**
* Stores options temporarily while editing.
*
* @todo Group with other UI-only properties.
*
* @var array
*/
public $temporary_options;
/**
* Stores a stack of UI forms to display.
*
* @todo Group with other UI-only properties.
*
* @var array
*/
public $stack;
/**
* Stores the many-to-one tables for performance.
*
* @var array
*/
public $many_to_one_tables;
/**
* Is the view runned in a context of the preview in the admin interface.
*
* @todo Group with other UI-only properties.
*
* @var bool
*/
public $live_preview;
/**
* A unique identifier which allows to update multiple views output via js.
*
* @var string
*/
public $dom_id;
/**
* Constructs a new ViewExecutable object.
*
* @param Drupal\views\ViewStorage $storage
* The view config entity the actual information is stored on.
*/
function __construct(ViewStorage $storage) {
public function __construct(ViewStorage $storage) {
// Reference the storage and the executable to each other.
$this->storage = $storage;
$this->storage->setExecutable($this);
}
/**
* @todo
* Implements the magic __get() method.
*
* @todo Remove this once all calls are changed to use storage directly.
*/
function __get($name) {
public function &__get($name) {
if (property_exists($this->storage, $name)) {
return $this->storage->{$name};
}
elseif (property_exists($this, $name)) {
return $this->{$name};
}
}
/**
* @todo
* Implements the magic __set() method.
*
* @todo Remove this once all calls are changed to use storage directly.
*/
function __set($name, $value) {
if (property_exists($this->storage, $name)) {
public function __set($name, $value) {
if (property_exists($this, $name)) {
$this->{$name} = $value;
}
elseif (property_exists($this->storage, $name)) {
$this->storage->{$name} = $value;
}
}
/**
* @todo
* Implements the magic __call() method.
*
* @todo Remove this once all calls are changed to use storage directly.
*/
function __call($name, $arguments) {
public function __call($name, $arguments) {
if (method_exists($this->storage, $name)) {
call_user_func_array(array($this->storage, $name), $arguments);
return call_user_func_array(array($this->storage, $name), $arguments);
}
}
......@@ -378,10 +552,9 @@ function __call($name, $arguments) {
public function update() {
// When views are converted automatically the base_table should be renamed
// to have a working query.
$this->base_table = views_move_table($this->base_table);
$this->storage->base_table = views_move_table($this->storage->base_table);
}
/**
* Returns a list of the sub-object types used by this view. These types are
* stored on the display, and are used in the build process.
......@@ -525,8 +698,8 @@ public function getExposedInput() {
// remember settings.
$display_id = ($this->display_handler->isDefaulted('filters')) ? 'default' : $this->current_display;