diff --git a/core/modules/views/lib/Drupal/views/Plugin/views/display/DisplayPluginBase.php b/core/modules/views/lib/Drupal/views/Plugin/views/display/DisplayPluginBase.php index 76713c2..040ff47 100644 --- a/core/modules/views/lib/Drupal/views/Plugin/views/display/DisplayPluginBase.php +++ b/core/modules/views/lib/Drupal/views/Plugin/views/display/DisplayPluginBase.php @@ -554,42 +554,49 @@ protected function defineOptions() { 'type' => array('default' => 'none'), 'options' => array('default' => array()), ), + 'merge_defaults' => 'mergePlugin', ), 'cache' => array( 'contains' => array( 'type' => array('default' => 'none'), 'options' => array('default' => array()), ), + 'merge_defaults' => 'mergePlugin', ), 'query' => array( 'contains' => array( 'type' => array('default' => 'views_query'), 'options' => array('default' => array()), ), + 'merge_defaults' => 'mergePlugin', ), 'exposed_form' => array( 'contains' => array( 'type' => array('default' => 'basic'), 'options' => array('default' => array()), ), + 'merge_defaults' => 'mergePlugin', ), 'pager' => array( 'contains' => array( 'type' => array('default' => 'mini'), 'options' => array('default' => array()), ), + 'merge_defaults' => 'mergePlugin', ), 'style' => array( 'contains' => array( 'type' => array('default' => 'default'), 'options' => array('default' => array()), ), + 'merge_defaults' => 'mergePlugin', ), 'row' => array( 'contains' => array( 'type' => array('default' => 'fields'), 'options' => array('default' => array()), ), + 'merge_defaults' => 'mergePlugin', ), 'exposed_block' => array( @@ -598,27 +605,34 @@ protected function defineOptions() { 'header' => array( 'default' => array(), + 'merge_defaults' => 'mergeHandler', ), 'footer' => array( 'default' => array(), + 'merge_defaults' => 'mergeHandler', ), 'empty' => array( 'default' => array(), + 'merge_defaults' => 'mergeHandler', ), // We want these to export last. // These are the 5 handler types. 'relationships' => array( 'default' => array(), + 'merge_defaults' => 'mergeHandler', ), 'fields' => array( 'default' => array(), + 'merge_defaults' => 'mergeHandler', ), 'sorts' => array( 'default' => array(), + 'merge_defaults' => 'mergeHandler', ), 'arguments' => array( 'default' => array(), + 'merge_defaults' => 'mergeHandler', ), 'filter_groups' => array( 'contains' => array( @@ -2725,6 +2739,65 @@ public function getPagerText() { ); } + /** + * Merges default values for all plugin types. + */ + public function mergeDefaults() { + $defined_options = $this->defineOptions(); + + // Build a map of plural => singular for handler types. + $type_map = array(); + foreach (ViewExecutable::viewsHandlerTypes() as $type => $info) { + $type_map[$info['plural']] = $type; + } + + // Find all defined options, that have specified a merge_defaults callback. + foreach ($defined_options as $type => $definition) { + if (!isset($definition['merge_defaults']) || !method_exists($this, $definition['merge_defaults'])) { + continue; + } + // Switch the type to singular, if it's a plural handler. + if (isset($type_map[$type])) { + $type = $type_map[$type]; + } + + $this->{$definition['merge_defaults']}($type); + } + } + + /** + * Merges plugins default values. + * + * @param string $type + * The name of the plugin type option. + */ + protected function mergePlugin($type) { + if (($options = $this->getOption($type)) && isset($options['options'])) { + $plugin = $this->getPlugin($type); + $options['options'] = $options['options'] + $plugin->options; + $this->setOption($type, $options); + } + } + + /** + * Merges handlers default values. + * + * @param string $type + * The name of the handler type option. + */ + protected function mergeHandler($type) { + $types = ViewExecutable::viewsHandlerTypes(); + + $options = $this->getOption($types[$type]['plural']); + foreach ($this->getHandlers($type) as $id => $handler) { + if (isset($options[$id])) { + $options[$id] = $options[$id] + $handler->options; + } + } + + $this->setOption($types[$type]['plural'], $options); + } + } /** diff --git a/core/modules/views/lib/Drupal/views/Plugin/views/wizard/WizardPluginBase.php b/core/modules/views/lib/Drupal/views/Plugin/views/wizard/WizardPluginBase.php index 9b88bb8..b0048e5 100644 --- a/core/modules/views/lib/Drupal/views/Plugin/views/wizard/WizardPluginBase.php +++ b/core/modules/views/lib/Drupal/views/Plugin/views/wizard/WizardPluginBase.php @@ -749,6 +749,11 @@ protected function default_display_options() { $display_options['style']['type'] = 'default'; $display_options['row']['type'] = 'fields'; + // Add default options array to each plugin type. + foreach ($display_options as &$options) { + $options['options'] = array(); + } + // Add a least one field so the view validates and the user has a preview. // The base field can provide a default in its base settings; otherwise, // choose the first field with a field handler. diff --git a/core/modules/views/lib/Drupal/views/Tests/Plugin/DisplayUnitTest.php b/core/modules/views/lib/Drupal/views/Tests/Plugin/DisplayUnitTest.php new file mode 100644 index 0000000..86ab3f8 --- /dev/null +++ b/core/modules/views/lib/Drupal/views/Tests/Plugin/DisplayUnitTest.php @@ -0,0 +1,91 @@ + 'Display unit tests', + 'description' => 'Unit tests for the DisplayPluginBase class.', + 'group' => 'Views Plugins' + ); + } + + /** + * Test the default display options. + */ + public function testDefaultOptions() { + // Save the view. + $view = views_get_view('test_display_defaults'); + $view->save(); + // Reload to get saved storage values. + $view = views_get_view('test_display_defaults'); + $view->initDisplay(); + $display_data = $view->storage->get('display'); + + foreach ($view->displayHandlers as $id => $display) { + // Test the view plugin options against the storage. + foreach ($this->pluginTypes as $type) { + $options = $display->getOption($type); + $this->assertIdentical($display_data[$id]['display_options'][$type]['options'], $options['options']); + } + // Test the view handler options against the storage. + foreach ($this->handlerTypes as $type) { + $options = $display->getOption($type); + $this->assertIdentical($display_data[$id]['display_options'][$type], $options); + } + } + + } + +} diff --git a/core/modules/views/lib/Drupal/views/ViewStorageController.php b/core/modules/views/lib/Drupal/views/ViewStorageController.php index 3ac6731..739a624 100644 --- a/core/modules/views/lib/Drupal/views/ViewStorageController.php +++ b/core/modules/views/lib/Drupal/views/ViewStorageController.php @@ -42,6 +42,18 @@ protected function attachLoad(&$queried_entities, $revision_id = FALSE) { } /** + * Overrides \Drupal\config\ConfigStorageController::preSave(). + */ + protected function preSave(EntityInterface $entity) { + $executable = $entity->get('executable'); + $executable->initDisplay(); + + foreach ($executable->displayHandlers as $display) { + $display->mergeDefaults(); + } + } + + /** * Overrides Drupal\config\ConfigStorageController::postSave(). */ protected function postSave(EntityInterface $entity, $update) { diff --git a/core/modules/views/tests/views_test_config/test_views/views.view.test_display_defaults.yml b/core/modules/views/tests/views_test_config/test_views/views.view.test_display_defaults.yml new file mode 100644 index 0000000..e2f5288 --- /dev/null +++ b/core/modules/views/tests/views_test_config/test_views/views.view.test_display_defaults.yml @@ -0,0 +1,49 @@ +base_field: id +base_table: views_test_data +core: 8.x +description: '' +status: '1' +display: + default: + display_plugin: default + id: default + display_title: Master + position: '' + display_options: + access: + type: none + options: { } + cache: + type: none + options: { } + query: + type: views_query + options: { } + exposed_form: + type: basic + options: { } + pager: + type: full + options: { } + style: + type: default + options: { } + row: + type: fields + options: { } + fields: + name: + id: name + table: views_test_data + field: name + sorts: + created: + id: created + table: views_test_data + field: created + order: DESC +label: '' +module: views +id: test_display_defaults +tag: '' +langcode: en