Issue #2381973 by Gábor Hojtsy, vijaycs85, dawehner: View wizard creates 'invalid' views out of the box, missing plugin_ids, insecure permissions

8.0.x
Alex Pott 2014-11-28 09:51:24 +00:00
parent ec465933bb
commit bbcc4623a5
36 changed files with 167 additions and 188 deletions

View File

@ -1,13 +1,5 @@
# Schema for the views plugins of the Aggregator module.
"views.row.entity:aggregator_feed":
type: views_entity_row
label: 'Entity options'
"views.row.entity:aggregator_item":
type: views_entity_row
label: 'Entity options'
views.argument.aggregator_fid:
type: views.argument.numeric
label: 'Aggregator feed ID'

View File

@ -98,20 +98,6 @@ views.filter.comment_user_uid:
type: views_filter
label: 'Node user posted comment'
"views.row.entity:comment":
type: mapping
label: 'Entity options'
mapping:
view_mode:
type: string
label: 'View mode'
relationship:
type: string
label: 'Relationship'
links:
type: boolean
label: 'Display links'
views.row.comment_rss:
type: views_row
label: 'Comment'
@ -119,9 +105,6 @@ views.row.comment_rss:
view_mode:
type: string
label: 'Display type'
links:
type: boolean
label: 'Display links'
views.sort.comment_ces_last_comment_name:
type: views_sort

View File

@ -43,6 +43,7 @@ class Comment extends WizardPluginBase {
'alter_text' => TRUE,
'text' => 'comment/[cid]#comment-[cid]'
),
'plugin_id' => 'comment',
);
/**
@ -53,15 +54,15 @@ class Comment extends WizardPluginBase {
'value' => TRUE,
'table' => 'comment_field_data',
'field' => 'status',
'provider' => 'comment'
'plugin_id' => 'boolean',
),
'status_node' => array(
'value' => TRUE,
'table' => 'node_field_data',
'field' => 'status',
'provider' => 'node',
'plugin_id' => 'boolean',
'relationship' => 'node',
)
),
);
/**
@ -74,31 +75,6 @@ class Comment extends WizardPluginBase {
return $options;
}
protected function buildFormStyle(array &$form, FormStateInterface $form_state, $type) {
parent::buildFormStyle($form, $form_state, $type);
$style_form =& $form['displays'][$type]['options']['style'];
// Some style plugins don't support row plugins so stop here if that's the
// case.
if (!isset($style_form['row_plugin']['#default_value'])) {
return;
}
$row_plugin = $style_form['row_plugin']['#default_value'];
switch ($row_plugin) {
case 'comment':
$style_form['row_options']['links'] = array(
'#type' => 'select',
'#title' => $this->t('Should links be displayed below each comment'),
'#title_display' => 'invisible',
'#options' => array(
1 => $this->t('with links (allow users to reply to the comment, etc.)'),
0 => $this->t('without links'),
),
'#default_value' => 1,
);
break;
}
}
/**
* {@inheritdoc}
*/
@ -128,7 +104,6 @@ class Comment extends WizardPluginBase {
switch ($row_plugin) {
case 'comment':
$display_options['row']['type'] = 'entity:comment';
$display_options['row']['options']['links'] = !empty($row_options['links']);
break;
}
}
@ -168,6 +143,7 @@ class Comment extends WizardPluginBase {
$display_options['fields']['subject']['hide_empty'] = 0;
$display_options['fields']['subject']['empty_zero'] = 0;
$display_options['fields']['subject']['link_to_comment'] = 1;
$display_options['fields']['subject']['plugin_id'] = 'comment';
return $display_options;
}

View File

@ -33,7 +33,8 @@ class File extends WizardPluginBase {
'table' => 'file_managed',
'field' => 'uri',
'exclude' => TRUE,
'file_download_path' => TRUE
'file_download_path' => TRUE,
'plugin_id' => 'file_uri',
);
/**
@ -64,6 +65,7 @@ class File extends WizardPluginBase {
$display_options['fields']['filename']['hide_empty'] = 0;
$display_options['fields']['filename']['empty_zero'] = 0;
$display_options['fields']['filename']['link_to_file'] = 1;
$display_options['fields']['filename']['plugin_id'] = 'file';
return $display_options;
}

View File

@ -153,7 +153,6 @@ display:
type: 'entity:node'
options:
view_mode: teaser
comments: false
header: { }
footer: { }
empty: { }

View File

@ -182,8 +182,6 @@ display:
row:
type: 'entity:node'
options:
build_mode: teaser
comments: false
view_mode: teaser
sorts:
sticky:

View File

@ -1,16 +1,5 @@
# Schema for the views plugins of the Node module.
"views.row.entity:node":
type: views_entity_row
label: 'Entity options'
mapping:
comments:
type: boolean
label: 'Show comments'
build_mode:
type: string
label: 'Build mode'
views.area.node_listing_empty:
type: views_area
label: 'Node link'
@ -157,7 +146,7 @@ views.field.node_path:
label: 'Use absolute link (begins with "http://")'
views.field.node_revision:
type: views_field
type: views.field.node
label: 'Node revision'
mapping:
link_to_node_revision:
@ -234,8 +223,8 @@ views.filter_value.node_status:
label: 'Status'
views.row.node_rss:
type: "views.row.entity:node"
label: 'Content'
type: views_row
label: 'Content options'
mapping:
view_mode:
type: string

View File

@ -42,7 +42,8 @@ class Node extends WizardPluginBase {
'alter' => array(
'alter_text' => TRUE,
'text' => 'node/[nid]'
)
),
'plugin_id' => 'node',
);
/**
@ -53,7 +54,7 @@ class Node extends WizardPluginBase {
'value' => TRUE,
'table' => 'node_field_data',
'field' => 'status',
'provider' => 'node'
'plugin_id' => 'boolean'
)
);
@ -82,42 +83,6 @@ class Node extends WizardPluginBase {
return $options;
}
/**
* Adds the style options to the wizard form.
*
* @param array $form
* The full wizard form array.
* @param \Drupal\Core\Form\FormStateInterface $form_state
* The current state of the wizard form.
* @param string $type
* The display ID (e.g. 'page' or 'block').
*/
protected function buildFormStyle(array &$form, FormStateInterface $form_state, $type) {
parent::buildFormStyle($form, $form_state, $type);
$style_form =& $form['displays'][$type]['options']['style'];
// Some style plugins don't support row plugins so stop here if that's the
// case.
if (!isset($style_form['row_plugin']['#default_value'])) {
return;
}
$row_plugin = $style_form['row_plugin']['#default_value'];
switch ($row_plugin) {
case 'full_posts':
case 'teasers':
$style_form['row_options']['links'] = array(
'#type' => 'select',
'#title' => $this->t('Should links be displayed below each node'),
'#title_display' => 'invisible',
'#options' => array(
1 => $this->t('with links (allow users to add comments, etc.)'),
0 => $this->t('without links'),
),
'#default_value' => 1,
);
break;
}
}
/**
* Overrides Drupal\views\Plugin\views\wizard\WizardPluginBase::defaultDisplayOptions().
*/
@ -148,6 +113,7 @@ class Node extends WizardPluginBase {
$display_options['fields']['title']['hide_empty'] = 0;
$display_options['fields']['title']['empty_zero'] = 0;
$display_options['fields']['title']['link_to_node'] = 1;
$display_options['fields']['title']['plugin_id'] = 'node';
return $display_options;
}
@ -165,7 +131,8 @@ class Node extends WizardPluginBase {
'table' => 'taxonomy_index',
'field' => 'tid',
'value' => $tids,
'vocabulary' => $form_state->getValue(array('show', 'tagged_with', 'vocabulary')),
'vid' => $form_state->getValue(array('show', 'tagged_with', 'vocabulary')),
'plugin_id' => 'taxonomy_index_tid',
);
// If the user entered more than one valid term in the autocomplete
// field, they probably intended both of them to be applied.
@ -209,21 +176,20 @@ class Node extends WizardPluginBase {
switch ($row_plugin) {
case 'full_posts':
$display_options['row']['type'] = 'entity:node';
$display_options['row']['options']['build_mode'] = 'full';
$display_options['row']['options']['links'] = !empty($row_options['links']);
$display_options['row']['options']['view_mode'] = 'full';
break;
case 'teasers':
$display_options['row']['type'] = 'entity:node';
$display_options['row']['options']['build_mode'] = 'teaser';
$display_options['row']['options']['links'] = !empty($row_options['links']);
$display_options['row']['options']['view_mode'] = 'teaser';
break;
case 'titles_linked':
$display_options['row']['type'] = 'fields';
$display_options['field']['title']['link_to_node'] = 1;
break;
case 'titles':
$display_options['row']['type'] = 'fields';
$display_options['field']['title']['link_to_node'] = 0;
$display_options['fields']['title']['id'] = 'title';
$display_options['fields']['title']['table'] = 'node_field_data';
$display_options['fields']['title']['field'] = 'title';
$display_options['fields']['title']['link_to_node'] = ($row_plugin == 'titles_linked');
$display_options['fields']['title']['plugin_id'] = 'node';
break;
}
}

View File

@ -40,7 +40,8 @@ class NodeRevision extends WizardPluginBase {
'alter' => array(
'alter_text' => TRUE,
'text' => 'node/[nid]/revisions/[vid]/view'
)
),
'plugin_id' => 'node_revision',
);
/**
@ -52,7 +53,8 @@ class NodeRevision extends WizardPluginBase {
'table' => 'node',
'field' => 'nid',
'exclude' => TRUE,
'link_to_node' => FALSE
'link_to_node' => FALSE,
'plugin_id' => 'node',
)
);
@ -64,7 +66,7 @@ class NodeRevision extends WizardPluginBase {
'value' => TRUE,
'table' => 'node_field_revision',
'field' => 'status',
'provider' => 'node'
'plugin_id' => 'boolean'
)
);
@ -88,7 +90,7 @@ class NodeRevision extends WizardPluginBase {
// Add permission-based access control.
$display_options['access']['type'] = 'perm';
$display_options['access']['perm'] = 'view revisions';
$display_options['access']['options']['perm'] = 'view revisions';
// Remove the default fields, since we are customizing them here.
unset($display_options['fields']);
@ -107,6 +109,7 @@ class NodeRevision extends WizardPluginBase {
$display_options['fields']['changed']['alter']['html'] = FALSE;
$display_options['fields']['changed']['hide_empty'] = FALSE;
$display_options['fields']['changed']['empty_zero'] = FALSE;
$display_options['fields']['changed']['plugin_id'] = 'date';
/* Field: Content revision: Title */
$display_options['fields']['title']['id'] = 'title';
@ -125,6 +128,7 @@ class NodeRevision extends WizardPluginBase {
$display_options['fields']['title']['empty_zero'] = 0;
$display_options['fields']['title']['link_to_node'] = 0;
$display_options['fields']['title']['link_to_node_revision'] = 1;
$display_options['fields']['title']['plugin_id'] = 'node_revision';
return $display_options;
}

View File

@ -54,8 +54,6 @@ display:
row:
type: 'entity:node'
options:
build_mode: teaser
comments: false
view_mode: teaser
style:
type: default

View File

@ -54,8 +54,6 @@ display:
row:
type: 'entity:node'
options:
build_mode: teaser
links: false
view_mode: teaser
rendering_language: translation_language_renderer
fields:

View File

@ -39,8 +39,7 @@ display:
type: views_query
row:
options:
build_mode: teaser
comments: false
view_mode: teaser
type: 'entity:node'
sorts: { }
style:

View File

@ -4,10 +4,6 @@ views.display.rest_export:
type: views_display_path
label: 'REST display options'
views.row.data_entity:
type: views_row
label: 'Entity row'
views.row.data_field:
type: views_row
label: 'Field row'
@ -27,7 +23,7 @@ views.row.data_field:
label: 'Raw output for ID'
views.style.serializer:
type: viwes_style
type: views_style
label: 'Serialized output format'
mapping:
formats:

View File

@ -24,7 +24,7 @@ views.filter.search:
label: 'On empty input'
views.row.search_view:
type: views.field.numeric
type: views_row
label: 'Source link'
mapping:
score:

View File

@ -215,7 +215,6 @@ display:
type: 'entity:node'
options:
view_mode: teaser
comments: false
header:
entity_taxonomy_term:
id: entity_taxonomy_term

View File

@ -31,7 +31,8 @@ class TaxonomyTerm extends WizardPluginBase {
'alter' => array(
'alter_text' => TRUE,
'text' => 'taxonomy/term/[tid]'
)
),
'plugin_id' => 'taxonomy',
);
/**
@ -62,6 +63,7 @@ class TaxonomyTerm extends WizardPluginBase {
$display_options['fields']['name']['hide_empty'] = 0;
$display_options['fields']['name']['empty_zero'] = 0;
$display_options['fields']['name']['link_to_taxonomy'] = 1;
$display_options['fields']['name']['plugin_id'] = 'taxonomy';
return $display_options;
}

View File

@ -60,10 +60,6 @@ views.argument_default.node:
type: boolean
label: 'Content ID from URL'
"views.row.entity:user":
type: views_entity_row
label: 'Entity options'
views_field_user:
type: views_field
mapping:

View File

@ -41,7 +41,8 @@ class Users extends WizardPluginBase {
'alter' => array(
'alter_text' => TRUE,
'text' => 'user/[uid]'
)
),
'plugin_id' => 'user',
);
/**
@ -52,7 +53,7 @@ class Users extends WizardPluginBase {
'value' => TRUE,
'table' => 'users_field_data',
'field' => 'status',
'provider' => 'user'
'plugin_id' => 'boolean',
)
);
@ -64,7 +65,7 @@ class Users extends WizardPluginBase {
// Add permission-based access control.
$display_options['access']['type'] = 'perm';
$display_options['access']['perm'] = 'access user profiles';
$display_options['access']['options']['perm'] = 'access user profiles';
// Remove the default fields, since we are customizing them here.
unset($display_options['fields']);
@ -86,6 +87,7 @@ class Users extends WizardPluginBase {
$display_options['fields']['name']['empty_zero'] = 0;
$display_options['fields']['name']['link_to_user'] = 1;
$display_options['fields']['name']['overwrite_anonymous'] = 0;
$display_options['fields']['name']['plugin_id'] = 'user_name';
return $display_options;
}

View File

@ -823,7 +823,7 @@ views_query:
views_row:
type: mapping
label: 'Row'
label: 'Row options'
mapping:
relationship:
type: string
@ -835,6 +835,9 @@ views_entity_row:
view_mode:
type: string
label: 'View mode'
rendering_language:
type: string
label: 'Rendering language'
views_cache:
type: mapping

View File

@ -1,5 +1,12 @@
# Schema for the views row.
views.row.*:
type: views_row
"views.row.entity:*":
type: views_entity_row
label: 'Entity options'
views.row.fields:
type: views_row
label: 'Field options'
@ -21,7 +28,7 @@ views.row.fields:
label: 'Hide empty'
views.row.rss_fields:
type: mapping
type: views_row
label: 'RSS field options'
mapping:
title_field:

View File

@ -114,3 +114,14 @@ views.view.*:
label: 'Position'
display_options:
type: views.display.[%parent.display_plugin]
block.settings.views_block:*:
type: block_settings
label: 'View block'
mapping:
views_label:
type: label
lable: 'Title'
items_per_page:
type: string
label: 'Items per block'

View File

@ -171,6 +171,7 @@ abstract class ViewsBlockBase extends BlockBase implements ContainerFactoryPlugi
else {
$this->configuration['views_label'] = '';
}
$form_state->unsetValue('views_label_checkbox');
}
/**

View File

@ -332,6 +332,7 @@ class Block extends DisplayPluginBase {
if ($items_per_page = $form_state->getValue(array('override', 'items_per_page'))) {
$block->setConfigurationValue('items_per_page', $items_per_page);
}
$form_state->unsetValue(array('override', 'items_per_page'));
}
/**

View File

@ -848,9 +848,16 @@ abstract class WizardPluginBase extends PluginBase implements WizardInterface {
// 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.
$data = Views::viewsData()->get($this->base_table);
$default_table = $this->base_table;
$data = Views::viewsData()->get($default_table);
if (isset($data['table']['base']['defaults']['field'])) {
$default_field = $data['table']['base']['defaults']['field'];
// If the table for the default field is different to the base table,
// load the view table data for this table.
if (isset($data['table']['base']['defaults']['table']) && $data['table']['base']['defaults']['table'] != $default_table) {
$default_table = $data['table']['base']['defaults']['table'];
$data = Views::viewsData()->get($default_table);
}
}
else {
foreach ($data as $default_field => $field_data) {
@ -860,15 +867,12 @@ abstract class WizardPluginBase extends PluginBase implements WizardInterface {
}
}
$display_options['fields'][$default_field] = array(
'table' => $this->base_table,
'table' => $default_table,
'field' => $default_field,
'id' => $default_field,
'plugin_id' => $data[$default_field]['field']['id'],
);
// Load the plugin ID and module.
$base_field = $data['table']['base']['field'];
$display_options['fields'][$base_field]['plugin_id'] = $data[$base_field]['field']['id'];
return $display_options;
}
@ -951,6 +955,7 @@ abstract class WizardPluginBase extends PluginBase implements WizardInterface {
'table' => $table,
'field' => $bundle_key,
'value' => $value,
'plugin_id' => $handler,
);
}
@ -1027,6 +1032,7 @@ abstract class WizardPluginBase extends PluginBase implements WizardInterface {
'table' => $table,
'field' => $column,
'order' => $sort,
'plugin_id' => $data[$column]['sort']['id'],
);
}
}

View File

@ -14,6 +14,15 @@ use Drupal\views\Tests\ViewTestBase;
*/
abstract class WizardTestBase extends ViewTestBase {
/**
* Set to TRUE to strict check all configuration saved.
*
* @see \Drupal\Core\Config\Testing\ConfigSchemaChecker
*
* @var bool
*/
protected $strictConfigSchema = TRUE;
/**
* Modules to enable.
*

View File

@ -85,7 +85,8 @@ display:
type: full
query:
type: views_query
row_plugin: fields
row:
type: fields
style_plugin: default
field_langcode: '***LANGUAGE_language_content***'
field_langcode_add_to_query: null

View File

@ -41,11 +41,10 @@ display:
type: full
query:
type: views_query
row_options:
build_mode: teaser
comments: '0'
links: '1'
row_plugin: node
row:
type: 'entity:node'
options:
view_mode: teaser
sorts:
created:
field: created
@ -66,11 +65,9 @@ display:
defaults:
pager: false
pager_options: false
row_options: '0'
row_plugin: '0'
style_options: '0'
style_plugin: '0'
field:
fields:
title:
link_to_node: '1'
plugin_id: node
@ -79,11 +76,8 @@ display:
items_per_page: 5
type: some
pager_options: { }
row_options:
build_mode: teaser
comments: '0'
links: '1'
row_plugin: fields
row:
type: fields
style_options: { }
style_plugin: default
field_langcode: '***LANGUAGE_language_content***'

View File

@ -58,9 +58,7 @@ display:
type: views_query
row:
options:
build_mode: teaser
comments: false
links: '1'
view_mode: teaser
type: 'entity:node'
sorts:
created:

View File

@ -34,7 +34,6 @@ display:
relationship: none
view_mode: teaser
rendering_language: translation_language_renderer
links: 0
sorts:
title:
id: title

View File

@ -84,9 +84,6 @@ display:
type: default
row:
type: 'entity:node'
options:
comments: false
links: '1'
field_langcode: '***LANGUAGE_language_content***'
field_langcode_add_to_query: null
display_plugin: default

View File

@ -44,9 +44,6 @@ display:
type: default
row:
type: 'entity:node'
options:
comments: false
links: '1'
field_langcode: '***LANGUAGE_language_content***'
field_langcode_add_to_query: null
display_plugin: default

View File

@ -44,9 +44,6 @@ display:
type: default
row:
type: 'entity:node'
options:
comments: false
links: '1'
field_langcode: '***LANGUAGE_language_content***'
field_langcode_add_to_query: null
display_plugin: default

View File

@ -36,9 +36,7 @@ display:
row:
type: 'entity:node'
options:
build_mode: teaser
links: '1'
comments: false
view_mode: teaser
fields:
title:
id: title

View File

@ -50,9 +50,7 @@ display:
row:
type: 'entity:node'
options:
build_mode: teaser
links: '1'
comments: false
view_mode: teaser
fields:
title:
id: title

View File

@ -36,9 +36,7 @@ display:
row:
type: 'entity:node'
options:
build_mode: teaser
links: '1'
comments: false
view_mode: teaser
fields:
title:
id: title

View File

@ -0,0 +1,65 @@
<?php
/**
* @file
* Contains \Drupal\views_ui\Tests\NewViewConfigSchemaTest.
*/
namespace Drupal\views_ui\Tests;
use Drupal\simpletest\WebTestBase;
/**
* Tests configuration schema against new views.
*
* @group views_ui
*/
class NewViewConfigSchemaTest extends WebTestBase {
/**
* Set to TRUE to strict check all configuration saved.
*
* @see \Drupal\Core\Config\Testing\ConfigSchemaChecker
*
* @var bool
*/
protected $strictConfigSchema = TRUE;
/**
* Modules to enable.
*
* @var array
*/
public static $modules = array('views_ui', 'node', 'comment', 'file', 'taxonomy', 'dblog', 'aggregator');
/**
* Tests creating brand new views.
*/
public function testNewViews() {
$this->drupalLogin($this->drupalCreateUser(array('administer views')));
// Create views with all core Views wizards.
$wizards = array(
// Wizard with their own classes.
'node',
'node_revision',
'users',
'comment',
'file_managed',
'taxonomy_term',
'watchdog',
// Standard derivative classes.
'standard:aggregator_feed',
'standard:aggregator_item',
);
foreach($wizards as $wizard_key) {
$edit = array();
$edit['label'] = $this->randomString();
$edit['id'] = strtolower($this->randomMachineName());
$edit['show[wizard_key]'] = $wizard_key;
$edit['description'] = $this->randomString();
$this->drupalPostForm('admin/structure/views/add', $edit, t('Save and edit'));
}
}
}