Update to Drupal 8.0.0-beta15. For more information, see: https://www.drupal.org/node/2563023
This commit is contained in:
parent
2720a9ec4b
commit
f3791f1da3
1898 changed files with 54300 additions and 11481 deletions
|
@ -8,11 +8,16 @@
|
|||
"use strict";
|
||||
|
||||
/**
|
||||
* Ajax command for highlighting elements.
|
||||
*
|
||||
* @param {Drupal.Ajax} [ajax]
|
||||
* An Ajax object.
|
||||
* @param {object} response
|
||||
* The Ajax response.
|
||||
* @param {string} response.selector
|
||||
* The selector in question.
|
||||
* @param {number} [status]
|
||||
* The HTTP status code.
|
||||
*/
|
||||
Drupal.AjaxCommands.prototype.viewsHighlight = function (ajax, response, status) {
|
||||
$('.hilited').removeClass('hilited');
|
||||
|
@ -20,11 +25,16 @@
|
|||
};
|
||||
|
||||
/**
|
||||
* Ajax command to show certain buttons in the views edit form.
|
||||
*
|
||||
* @param {Drupal.Ajax} [ajax]
|
||||
* An Ajax object.
|
||||
* @param {object} response
|
||||
* The Ajax response.
|
||||
* @param {bool} response.changed
|
||||
* Whether the state changed for the buttons or not.
|
||||
* @param {number} [status]
|
||||
* The HTTP status code.
|
||||
*/
|
||||
Drupal.AjaxCommands.prototype.viewsShowButtons = function (ajax, response, status) {
|
||||
$('div.views-edit-view div.form-actions').removeClass('js-hide');
|
||||
|
@ -34,10 +44,14 @@
|
|||
};
|
||||
|
||||
/**
|
||||
* Ajax command for triggering preview.
|
||||
*
|
||||
* @param {Drupal.Ajax} [ajax]
|
||||
* An Ajax object.
|
||||
* @param {object} [response]
|
||||
* The Ajax response.
|
||||
* @param {number} [status]
|
||||
* The HTTP status code.
|
||||
*/
|
||||
Drupal.AjaxCommands.prototype.viewsTriggerPreview = function (ajax, response, status) {
|
||||
if ($('input#edit-displays-live-preview').is(':checked')) {
|
||||
|
@ -46,12 +60,18 @@
|
|||
};
|
||||
|
||||
/**
|
||||
* Ajax command to replace the title of a page.
|
||||
*
|
||||
* @param {Drupal.Ajax} [ajax]
|
||||
* An Ajax object.
|
||||
* @param {object} response
|
||||
* The Ajax response.
|
||||
* @param {string} response.siteName
|
||||
* The site name.
|
||||
* @param {string} response.title
|
||||
* The new page title.
|
||||
* @param {number} [status]
|
||||
* The HTTP status code.
|
||||
*/
|
||||
Drupal.AjaxCommands.prototype.viewsReplaceTitle = function (ajax, response, status) {
|
||||
var doc = document;
|
||||
|
@ -72,6 +92,7 @@
|
|||
* Get rid of irritating tabledrag messages.
|
||||
*
|
||||
* @return {Array}
|
||||
* An array of messages. Always empty array, to get rid of the messages.
|
||||
*/
|
||||
Drupal.theme.tableDragChangedWarning = function () {
|
||||
return [];
|
||||
|
@ -81,6 +102,10 @@
|
|||
* Trigger preview when the "live preview" checkbox is checked.
|
||||
*
|
||||
* @type {Drupal~behavior}
|
||||
*
|
||||
* @prop {Drupal~behaviorAttach} attach
|
||||
* Attaches behavior to trigger live preview if the live preview option is
|
||||
* checked.
|
||||
*/
|
||||
Drupal.behaviors.livePreview = {
|
||||
attach: function (context) {
|
||||
|
@ -96,6 +121,9 @@
|
|||
* Sync preview display.
|
||||
*
|
||||
* @type {Drupal~behavior}
|
||||
*
|
||||
* @prop {Drupal~behaviorAttach} attach
|
||||
* Attaches behavior to sync the preview display when needed.
|
||||
*/
|
||||
Drupal.behaviors.syncPreviewDisplay = {
|
||||
attach: function (context) {
|
||||
|
@ -110,15 +138,19 @@
|
|||
};
|
||||
|
||||
/**
|
||||
* Ajax behaviors for the views_ui module.
|
||||
*
|
||||
* @type {Drupal~behavior}
|
||||
*
|
||||
* @prop {Drupal~behaviorAttach} attach
|
||||
* Attaches ajax behaviors to the elements with the classes in question.
|
||||
*/
|
||||
Drupal.behaviors.viewsAjax = {
|
||||
collapseReplaced: false,
|
||||
attach: function (context, settings) {
|
||||
var base_element_settings = {
|
||||
'event': 'click',
|
||||
'progress': {'type': 'fullscreen'}
|
||||
event: 'click',
|
||||
progress: {type: 'fullscreen'}
|
||||
};
|
||||
// Bind AJAX behaviors to all items showing the class.
|
||||
$('a.views-ajax-link', context).once('views-ajax').each(function () {
|
||||
|
|
|
@ -31,8 +31,14 @@
|
|||
}
|
||||
|
||||
/**
|
||||
* Functionality for views modals.
|
||||
*
|
||||
* @type {Drupal~behavior}
|
||||
*
|
||||
* @prop {Drupal~behaviorAttach} attach
|
||||
* Attaches modal functionality for views.
|
||||
* @prop {Drupal~behaviorDetach} detach
|
||||
* Detaches the modal functionality.
|
||||
*/
|
||||
Drupal.behaviors.viewsModalContent = {
|
||||
attach: function (context) {
|
||||
|
|
|
@ -16,6 +16,9 @@
|
|||
* Improve the user experience of the views edit interface.
|
||||
*
|
||||
* @type {Drupal~behavior}
|
||||
*
|
||||
* @prop {Drupal~behaviorAttach} attach
|
||||
* Attaches toggling of SQL rewrite warning on the corresponding checkbox.
|
||||
*/
|
||||
Drupal.behaviors.viewsUiEditView = {
|
||||
attach: function () {
|
||||
|
@ -32,6 +35,10 @@
|
|||
* as page title and menu link.
|
||||
*
|
||||
* @type {Drupal~behavior}
|
||||
*
|
||||
* @prop {Drupal~behaviorAttach} attach
|
||||
* Attaches behavior for prepopulating page title and menu links, based on
|
||||
* view name.
|
||||
*/
|
||||
Drupal.behaviors.viewsUiAddView = {
|
||||
attach: function (context) {
|
||||
|
@ -142,14 +149,18 @@
|
|||
var self = this;
|
||||
|
||||
/**
|
||||
* Populate the target form field with the altered source field value.
|
||||
*
|
||||
* @return {*}
|
||||
* The result of the _populate call, which should be undefined.
|
||||
*/
|
||||
this.populate = function () { return self._populate.call(self); };
|
||||
|
||||
/**
|
||||
* Stop prepopulating the form fields.
|
||||
*
|
||||
* @return {*}
|
||||
* The result of the _unbind call, which should be undefined.
|
||||
*/
|
||||
this.unbind = function () { return self._unbind.call(self); };
|
||||
|
||||
|
@ -174,6 +185,7 @@
|
|||
* Get the source form field value as altered by the passed-in parameters.
|
||||
*
|
||||
* @return {string}
|
||||
* The source form field value.
|
||||
*/
|
||||
getTransliterated: function () {
|
||||
var from = this.source.val();
|
||||
|
@ -208,6 +220,7 @@
|
|||
* Bind event handlers to new form fields, after they're replaced via Ajax.
|
||||
*
|
||||
* @param {jQuery} $fields
|
||||
* Fields to rebind functionality to.
|
||||
*/
|
||||
rebind: function ($fields) {
|
||||
this.target = $fields;
|
||||
|
@ -216,8 +229,13 @@
|
|||
});
|
||||
|
||||
/**
|
||||
* Adds functionality for the add item form.
|
||||
*
|
||||
* @type {Drupal~behavior}
|
||||
*
|
||||
* @prop {Drupal~behaviorAttach} attach
|
||||
* Attaches the functionality in {@link Drupal.viewsUi.AddItemForm} to the
|
||||
* forms in question.
|
||||
*/
|
||||
Drupal.behaviors.addItemForm = {
|
||||
attach: function (context) {
|
||||
|
@ -236,10 +254,12 @@
|
|||
};
|
||||
|
||||
/**
|
||||
* Constructs a new AddItemForm.
|
||||
*
|
||||
* @constructor
|
||||
*
|
||||
* @param {jQuery} $form
|
||||
* The form element used.
|
||||
*/
|
||||
Drupal.viewsUi.AddItemForm = function ($form) {
|
||||
|
||||
|
@ -264,8 +284,10 @@
|
|||
};
|
||||
|
||||
/**
|
||||
* Handles a checkbox check.
|
||||
*
|
||||
* @param {jQuery.Event} event
|
||||
* The event triggered.
|
||||
*/
|
||||
Drupal.viewsUi.AddItemForm.prototype.handleCheck = function (event) {
|
||||
var $target = $(event.target);
|
||||
|
@ -311,6 +333,9 @@
|
|||
* tabs.
|
||||
*
|
||||
* @type {Drupal~behavior}
|
||||
*
|
||||
* @prop {Drupal~behaviorAttach} attach
|
||||
* Fixes the input elements needed.
|
||||
*/
|
||||
Drupal.behaviors.viewsUiRenderAddViewButton = {
|
||||
attach: function (context) {
|
||||
|
@ -359,7 +384,10 @@
|
|||
};
|
||||
|
||||
/**
|
||||
* Toggle menu visibility.
|
||||
*
|
||||
* @param {jQuery} $trigger
|
||||
* The element where the toggle was triggered.
|
||||
*
|
||||
*
|
||||
* @note [@jessebeach] I feel like the following should be a more generic
|
||||
|
@ -372,8 +400,13 @@
|
|||
};
|
||||
|
||||
/**
|
||||
* Add search options to the views ui.
|
||||
*
|
||||
* @type {Drupal~behavior}
|
||||
*
|
||||
* @prop {Drupal~behaviorAttach} attach
|
||||
* Attaches {@link Drupal.viewsUi.OptionsSearch} to the views ui filter
|
||||
* options.
|
||||
*/
|
||||
Drupal.behaviors.viewsUiSearchOptions = {
|
||||
attach: function (context) {
|
||||
|
@ -400,6 +433,7 @@
|
|||
* @constructor
|
||||
*
|
||||
* @param {jQuery} $form
|
||||
* The form element.
|
||||
*/
|
||||
Drupal.viewsUi.OptionsSearch = function ($form) {
|
||||
|
||||
|
@ -441,6 +475,7 @@
|
|||
* shown and hidden depending on the user's search terms.
|
||||
*
|
||||
* @return {Array}
|
||||
* An array of all the filterable options.
|
||||
*/
|
||||
getOptions: function ($allOptions) {
|
||||
var $label;
|
||||
|
@ -454,11 +489,11 @@
|
|||
$description = $option.find('div.description');
|
||||
options[i] = {
|
||||
// Search on the lowercase version of the label text + description.
|
||||
'searchText': $label.text().toLowerCase() + " " + $description.text().toLowerCase(),
|
||||
searchText: $label.text().toLowerCase() + " " + $description.text().toLowerCase(),
|
||||
// Maintain a reference to the jQuery object for each row, so we don't
|
||||
// have to create a new object inside the performance-sensitive keyup
|
||||
// handler.
|
||||
'$div': $option
|
||||
$div: $option
|
||||
};
|
||||
}
|
||||
return options;
|
||||
|
@ -469,6 +504,7 @@
|
|||
* options.
|
||||
*
|
||||
* @param {jQuery.Event} event
|
||||
* The keyup event.
|
||||
*/
|
||||
handleKeyup: function (event) {
|
||||
var found;
|
||||
|
@ -514,8 +550,12 @@
|
|||
});
|
||||
|
||||
/**
|
||||
* Preview functionality in the views edit form.
|
||||
*
|
||||
* @type {Drupal~behavior}
|
||||
*
|
||||
* @prop {Drupal~behaviorAttach} attach
|
||||
* Attaches the preview functionality to the view edit form.
|
||||
*/
|
||||
Drupal.behaviors.viewsUiPreview = {
|
||||
attach: function (context) {
|
||||
|
@ -544,8 +584,14 @@
|
|||
};
|
||||
|
||||
/**
|
||||
* Rearranges the filters.
|
||||
*
|
||||
* @type {Drupal~behavior}
|
||||
*
|
||||
* @prop {Drupal~behaviorAttach} attach
|
||||
* Attach handlers to make it possible to rearange the filters in the form
|
||||
* in question.
|
||||
* @see Drupal.viewsUi.RearrangeFilterHandler
|
||||
*/
|
||||
Drupal.behaviors.viewsUiRearrangeFilter = {
|
||||
attach: function (context) {
|
||||
|
@ -568,7 +614,9 @@
|
|||
* @constructor
|
||||
*
|
||||
* @param {jQuery} $table
|
||||
* The table in the filter form.
|
||||
* @param {jQuery} $operator
|
||||
* The filter groups operator element.
|
||||
*/
|
||||
Drupal.viewsUi.RearrangeFilterHandler = function ($table, $operator) {
|
||||
|
||||
|
@ -688,6 +736,7 @@
|
|||
* Dynamically click the button that adds a new filter group.
|
||||
*
|
||||
* @param {jQuery.Event} event
|
||||
* The event triggered.
|
||||
*/
|
||||
clickAddGroupButton: function (event) {
|
||||
// Due to conflicts between Drupal core's AJAX system and the Views AJAX
|
||||
|
@ -716,6 +765,7 @@
|
|||
* duplicate it between any subsequent groups.
|
||||
*
|
||||
* @return {jQuery}
|
||||
* An operator element.
|
||||
*/
|
||||
duplicateGroupsOperator: function () {
|
||||
var dropdowns;
|
||||
|
@ -778,6 +828,7 @@
|
|||
* Forces all operator dropdowns to have the same value.
|
||||
*
|
||||
* @param {jQuery.Event} event
|
||||
* The event triggered.
|
||||
*/
|
||||
operatorChangeHandler: function (event) {
|
||||
var $target = $(event.target);
|
||||
|
@ -804,15 +855,13 @@
|
|||
* - The operator cells that span multiple rows need their rowspan
|
||||
* attributes updated to reflect the number of rows in each group.
|
||||
* - The operator labels that are displayed next to each filter need to
|
||||
* be
|
||||
* redrawn, to account for the row's new location.
|
||||
* be redrawn, to account for the row's new location.
|
||||
*/
|
||||
tableDrag.row.prototype.onSwap = function () {
|
||||
if (filterHandler.hasGroupOperator) {
|
||||
// Make sure the row that just got moved (this.group) is inside one
|
||||
// of
|
||||
// the filter groups (i.e. below an empty marker row or a draggable).
|
||||
// If it isn't, move it down one.
|
||||
// of the filter groups (i.e. below an empty marker row or a
|
||||
// draggable). If it isn't, move it down one.
|
||||
var thisRow = $(this.group);
|
||||
var previousRow = thisRow.prev('tr');
|
||||
if (previousRow.length && !previousRow.hasClass('group-message') && !previousRow.hasClass('draggable')) {
|
||||
|
@ -947,6 +996,9 @@
|
|||
* Add a select all checkbox, which checks each checkbox at once.
|
||||
*
|
||||
* @type {Drupal~behavior}
|
||||
*
|
||||
* @prop {Drupal~behaviorAttach} attach
|
||||
* Attaches select all functionality to the views filter form.
|
||||
*/
|
||||
Drupal.behaviors.viewsFilterConfigSelectAll = {
|
||||
attach: function (context) {
|
||||
|
@ -978,6 +1030,9 @@
|
|||
* Remove icon class from elements that are themed as buttons or dropbuttons.
|
||||
*
|
||||
* @type {Drupal~behavior}
|
||||
*
|
||||
* @prop {Drupal~behaviorAttach} attach
|
||||
* Removes the icon class from certain views elements.
|
||||
*/
|
||||
Drupal.behaviors.viewsRemoveIconClass = {
|
||||
attach: function (context) {
|
||||
|
@ -989,6 +1044,9 @@
|
|||
* Change "Expose filter" buttons into checkboxes.
|
||||
*
|
||||
* @type {Drupal~behavior}
|
||||
*
|
||||
* @prop {Drupal~behaviorAttach} attach
|
||||
* Changes buttons into checkboxes via {@link Drupal.viewsUi.Checkboxifier}.
|
||||
*/
|
||||
Drupal.behaviors.viewsUiCheckboxify = {
|
||||
attach: function (context, settings) {
|
||||
|
@ -1006,6 +1064,9 @@
|
|||
* selected widget for the exposed group.
|
||||
*
|
||||
* @type {Drupal~behavior}
|
||||
*
|
||||
* @prop {Drupal~behaviorAttach} attach
|
||||
* Changes the default widget based on user input.
|
||||
*/
|
||||
Drupal.behaviors.viewsUiChangeDefaultWidget = {
|
||||
attach: function (context) {
|
||||
|
@ -1056,6 +1117,7 @@
|
|||
* When the checkbox is checked or unchecked, simulate a button press.
|
||||
*
|
||||
* @param {jQuery.Event} e
|
||||
* The event triggered.
|
||||
*/
|
||||
Drupal.viewsUi.Checkboxifier.prototype.clickHandler = function (e) {
|
||||
this.$button
|
||||
|
@ -1067,6 +1129,10 @@
|
|||
* Change the Apply button text based upon the override select state.
|
||||
*
|
||||
* @type {Drupal~behavior}
|
||||
*
|
||||
* @prop {Drupal~behaviorAttach} attach
|
||||
* Attaches behavior to change the Apply button according to the current
|
||||
* state.
|
||||
*/
|
||||
Drupal.behaviors.viewsUiOverrideSelect = {
|
||||
attach: function (context) {
|
||||
|
@ -1103,8 +1169,12 @@
|
|||
};
|
||||
|
||||
/**
|
||||
* Functionality for the remove link in the views UI.
|
||||
*
|
||||
* @type {Drupal~behavior}
|
||||
*
|
||||
* @prop {Drupal~behaviorAttach} attach
|
||||
* Attaches behavior for the remove view and remove display links.
|
||||
*/
|
||||
Drupal.behaviors.viewsUiHandlerRemoveLink = {
|
||||
attach: function (context) {
|
||||
|
|
|
@ -15,6 +15,9 @@
|
|||
* Source text: .views-table-filter-text-source
|
||||
*
|
||||
* @type {Drupal~behavior}
|
||||
*
|
||||
* @prop {Drupal~behaviorAttach} attach
|
||||
* Attaches the filter functionality to the views admin text search field.
|
||||
*/
|
||||
Drupal.behaviors.viewTableFilterByText = {
|
||||
attach: function (context, settings) {
|
||||
|
|
|
@ -7,7 +7,6 @@
|
|||
|
||||
namespace Drupal\views_ui\Controller;
|
||||
|
||||
use Drupal\Component\Utility\SafeMarkup;
|
||||
use Drupal\Core\Controller\ControllerBase;
|
||||
use Drupal\Core\Url;
|
||||
use Drupal\views\ViewExecutable;
|
||||
|
@ -89,11 +88,16 @@ class ViewsUIController extends ControllerBase {
|
|||
$header = array(t('Field name'), t('Used in'));
|
||||
$rows = array();
|
||||
foreach ($fields as $field_name => $views) {
|
||||
$rows[$field_name]['data'][0] = SafeMarkup::checkPlain($field_name);
|
||||
$rows[$field_name]['data'][0]['data']['#plain_text'] = $field_name;
|
||||
foreach ($views as $view) {
|
||||
$rows[$field_name]['data'][1][] = $this->l($view, new Url('entity.view.edit_form', array('view' => $view)));
|
||||
}
|
||||
$rows[$field_name]['data'][1] = SafeMarkup::set(implode(', ', $rows[$field_name]['data'][1]));
|
||||
$item_list = [
|
||||
'#theme' => 'item_list',
|
||||
'#items' => $rows[$field_name]['data'][1],
|
||||
'#context' => ['list_style' => 'comma-list'],
|
||||
];
|
||||
$rows[$field_name]['data'][1] = ['data' => $item_list];
|
||||
}
|
||||
|
||||
// Sort rows by field name.
|
||||
|
@ -121,7 +125,11 @@ class ViewsUIController extends ControllerBase {
|
|||
foreach ($row['views'] as $row_name => $view) {
|
||||
$row['views'][$row_name] = $this->l($view, new Url('entity.view.edit_form', array('view' => $view)));
|
||||
}
|
||||
$row['views'] = SafeMarkup::set(implode(', ', $row['views']));
|
||||
$row['views']['data'] = [
|
||||
'#theme' => 'item_list',
|
||||
'#items' => $row['views'],
|
||||
'#context' => ['list_style' => 'comma-list'],
|
||||
];
|
||||
}
|
||||
|
||||
// Sort rows by field name.
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
|
||||
namespace Drupal\views_ui\Form\Ajax;
|
||||
|
||||
use Drupal\Component\Utility\SafeMarkup;
|
||||
use Drupal\Component\Utility\Html;
|
||||
use Drupal\Core\Form\FormStateInterface;
|
||||
use Drupal\views\ViewExecutable;
|
||||
|
||||
|
@ -52,7 +52,7 @@ class RearrangeFilter extends ViewsFormBase {
|
|||
return $form;
|
||||
}
|
||||
$display = $executable->displayHandlers->get($display_id);
|
||||
$form['#title'] = SafeMarkup::checkPlain($display->display['display_title']) . ': ';
|
||||
$form['#title'] = Html::escape($display->display['display_title']) . ': ';
|
||||
$form['#title'] .= $this->t('Rearrange @type', array('@type' => $types[$type]['ltitle']));
|
||||
$form['#section'] = $display_id . 'rearrange-item';
|
||||
|
||||
|
|
|
@ -35,6 +35,7 @@ class DisplayPathTest extends UITestBase {
|
|||
public function testPathUI() {
|
||||
$this->doBasicPathUITest();
|
||||
$this->doAdvancedPathsValidationTest();
|
||||
$this->doPathXssFilterTest();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -59,6 +60,28 @@ class DisplayPathTest extends UITestBase {
|
|||
$this->assertLink(t('View @display', array('@display' => 'Page')), 0, 'view page link found on the page.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that View paths are properly filtered for XSS.
|
||||
*/
|
||||
public function doPathXssFilterTest() {
|
||||
$this->drupalGet('admin/structure/views/view/test_view');
|
||||
$this->drupalPostForm(NULL, array(), 'Add Page');
|
||||
$this->drupalPostForm('admin/structure/views/nojs/display/test_view/page_2/path', array('path' => '<object>malformed_path</object>'), t('Apply'));
|
||||
$this->drupalPostForm(NULL, array(), 'Add Page');
|
||||
$this->drupalPostForm('admin/structure/views/nojs/display/test_view/page_3/path', array('path' => '<script>alert("hello");</script>'), t('Apply'));
|
||||
$this->drupalPostForm(NULL, array(), 'Add Page');
|
||||
$this->drupalPostForm('admin/structure/views/nojs/display/test_view/page_4/path', array('path' => '<script>alert("hello I have placeholders %");</script>'), t('Apply'));
|
||||
$this->drupalPostForm('admin/structure/views/view/test_view', array(), t('Save'));
|
||||
$this->drupalGet('admin/structure/views');
|
||||
// The anchor text should be escaped.
|
||||
$this->assertEscaped('/<object>malformed_path</object>');
|
||||
$this->assertEscaped('/<script>alert("hello");</script>');
|
||||
$this->assertEscaped('/<script>alert("hello I have placeholders %");</script>');
|
||||
// Links should be url-encoded.
|
||||
$this->assertRaw('/%3Cobject%3Emalformed_path%3C/object%3E');
|
||||
$this->assertRaw('/%3Cscript%3Ealert%28%22hello%22%29%3B%3C/script%3E');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests a couple of invalid path patterns.
|
||||
*/
|
||||
|
|
|
@ -7,6 +7,8 @@
|
|||
|
||||
namespace Drupal\views_ui\Tests;
|
||||
|
||||
use Drupal\views\Entity\View;
|
||||
|
||||
/**
|
||||
* Tests exposed forms UI functionality.
|
||||
*
|
||||
|
@ -151,5 +153,25 @@ class ExposedFormUITest extends UITestBase {
|
|||
// Check the label of the expose button.
|
||||
$this->helperButtonHasLabel('edit-options-expose-button-button', t('Hide sort'));
|
||||
$this->assertFieldById('edit-options-expose-label', '', 'Make sure a label field is shown');
|
||||
|
||||
// Test adding a new exposed sort criteria.
|
||||
$view_id = $this->randomView()['id'];
|
||||
$this->drupalGet("admin/structure/views/nojs/add-handler/$view_id/default/sort");
|
||||
$this->drupalPostForm(NULL, ['name[node_field_data.created]' => 1], t('Add and configure @handler', ['@handler' => t('sort criteria')]));
|
||||
$this->assertFieldByXPath('//input[@name="options[order]" and @checked="checked"]', 'ASC', 'The default order is set.');
|
||||
// Change the order and expose the sort.
|
||||
$this->drupalPostForm(NULL, ['options[order]' => 'DESC'], t('Apply'));
|
||||
$this->drupalPostForm("admin/structure/views/nojs/handler/$view_id/default/sort/created", [], t('Expose sort'));
|
||||
$this->assertFieldByXPath('//input[@name="options[order]" and @checked="checked"]', 'DESC');
|
||||
$this->assertFieldByName('options[expose][label]', 'Authored on', 'The default label is set.');
|
||||
// Change the label and save the view.
|
||||
$edit = ['options[expose][label]' => $this->randomString()];
|
||||
$this->drupalPostForm(NULL, $edit, t('Apply'));
|
||||
$this->drupalPostForm(NULL, [], t('Save'));
|
||||
// Check that the values were saved.
|
||||
$display = View::load($view_id)->getDisplay('default');
|
||||
$this->assertTrue($display['display_options']['sorts']['created']['exposed']);
|
||||
$this->assertEqual($display['display_options']['sorts']['created']['expose'], ['label' => $edit['options[expose][label]']]);
|
||||
$this->assertEqual($display['display_options']['sorts']['created']['order'], 'DESC');
|
||||
}
|
||||
}
|
||||
|
|
|
@ -150,7 +150,7 @@ class HandlerTest extends UITestBase {
|
|||
$result = $this->xpath('//a[contains(@href, :href)]', array(':href' => $href));
|
||||
$this->assertEqual(count($result), 1, SafeMarkup::format('Handler (%type) edit link found.', array('%type' => $type)));
|
||||
|
||||
$text = t('Broken/missing handler');
|
||||
$text = 'Broken/missing handler';
|
||||
|
||||
$this->assertIdentical((string) $result[0], $text, 'Ensure the broken handler text was found.');
|
||||
|
||||
|
|
60
core/modules/views_ui/src/Tests/ReportFieldsTest.php
Normal file
60
core/modules/views_ui/src/Tests/ReportFieldsTest.php
Normal file
|
@ -0,0 +1,60 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\views_ui\Tests\ReportFieldsTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\views_ui\Tests;
|
||||
|
||||
use Drupal\field\Entity\FieldConfig;
|
||||
use Drupal\field\Entity\FieldStorageConfig;
|
||||
|
||||
/**
|
||||
* Tests the Views fields report page.
|
||||
*
|
||||
* @group views_ui
|
||||
*/
|
||||
class ReportFieldsTest extends UITestBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static $testViews = ['test_field_field_test'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static $modules = ['entity_test'];
|
||||
|
||||
/**
|
||||
* Tests the Views fields report page.
|
||||
*/
|
||||
public function testReportFields() {
|
||||
$this->drupalGet('admin/reports/fields/views-fields');
|
||||
$this->assertRaw('Used in views', 'Title appears correctly');
|
||||
$this->assertRaw('No fields have been used in views yet.', 'No results message appears correctly.');
|
||||
|
||||
// Set up the field_test field.
|
||||
$field_storage = FieldStorageConfig::create([
|
||||
'field_name' => 'field_test',
|
||||
'type' => 'integer',
|
||||
'entity_type' => 'entity_test',
|
||||
]);
|
||||
$field_storage->save();
|
||||
|
||||
$field = FieldConfig::create([
|
||||
'field_name' => 'field_test',
|
||||
'entity_type' => 'entity_test',
|
||||
'bundle' => 'entity_test',
|
||||
]);
|
||||
$field->save();
|
||||
|
||||
$this->drupalGet('admin/reports/fields/views-fields');
|
||||
// Assert that the newly created field appears in the overview.
|
||||
$this->assertRaw('<td>field_test</td>', 'Field name appears correctly');
|
||||
$this->assertRaw('>test_field_field_test</a>', 'View name appears correctly');
|
||||
$this->assertRaw('Used in views', 'Title appears correctly');
|
||||
}
|
||||
|
||||
}
|
|
@ -21,6 +21,14 @@ class SettingsTest extends UITestBase {
|
|||
*/
|
||||
protected $adminUser;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
$this->drupalPlaceBlock('local_tasks_block');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the settings for the edit ui.
|
||||
*/
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
|
||||
namespace Drupal\views_ui\Tests;
|
||||
|
||||
use Drupal\views\Tests\ViewUnitTestBase;
|
||||
use Drupal\views\Tests\ViewKernelTestBase;
|
||||
use Drupal\views_ui\Controller\ViewsUIController;
|
||||
|
||||
/**
|
||||
|
@ -15,7 +15,7 @@ use Drupal\views_ui\Controller\ViewsUIController;
|
|||
*
|
||||
* @group views_ui
|
||||
*/
|
||||
class TagTest extends ViewUnitTestBase {
|
||||
class TagTest extends ViewKernelTestBase {
|
||||
|
||||
/**
|
||||
* Modules to enable.
|
||||
|
|
74
core/modules/views_ui/src/Tests/ViewsListTest.php
Normal file
74
core/modules/views_ui/src/Tests/ViewsListTest.php
Normal file
|
@ -0,0 +1,74 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\views_ui\Tests\ViewsListTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\views_ui\Tests;
|
||||
|
||||
use Drupal\simpletest\WebTestBase;
|
||||
use Drupal\views\Entity\View;
|
||||
use Drupal\views\Views;
|
||||
|
||||
/**
|
||||
* Tests the views list.
|
||||
*
|
||||
* @group views_ui
|
||||
*/
|
||||
class ViewsListTest extends WebTestBase {
|
||||
|
||||
/**
|
||||
* Modules to enable.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $modules = array('block', 'views_ui');
|
||||
|
||||
/**
|
||||
* A user with permission to administer views.
|
||||
*
|
||||
* @var \Drupal\user\Entity\User
|
||||
*/
|
||||
protected $adminUser;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
|
||||
$this->drupalPlaceBlock('local_tasks_block');
|
||||
$this->drupalPlaceBlock('local_actions_block');
|
||||
$this->adminUser = $this->drupalCreateUser(['administer views']);
|
||||
$this->drupalLogin($this->adminUser);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that the views list does not use a pager.
|
||||
*/
|
||||
public function testViewsListLimit() {
|
||||
// Check if we can access the main views admin page.
|
||||
$this->drupalGet('admin/structure/views');
|
||||
$this->assertResponse(200);
|
||||
$this->assertLink(t('Add new view'));
|
||||
|
||||
// Count default views to be subtracted from the limit.
|
||||
$views = count(Views::getEnabledViews());
|
||||
|
||||
// Create multiples views.
|
||||
$limit = 51;
|
||||
$values = $this->config('views.view.test_view_storage')->get();
|
||||
for ($i = 1; $i <= $limit - $views; $i++) {
|
||||
$values['id'] = 'test_view_storage_new' . $i;
|
||||
unset($values['uuid']);
|
||||
$created = View::create($values);
|
||||
$created->save();
|
||||
}
|
||||
$this->drupalGet('admin/structure/views');
|
||||
|
||||
// Check that all the rows are listed.
|
||||
$this->assertEqual(count($this->xpath('//tbody/tr[contains(@class,"views-ui-list-enabled")]')), $limit);
|
||||
}
|
||||
|
||||
}
|
|
@ -23,10 +23,10 @@ class XssTest extends UITestBase {
|
|||
|
||||
public function testViewsUi() {
|
||||
$this->drupalGet('admin/structure/views');
|
||||
$this->assertRaw('<script>alert("foo");</script>, <marquee>test</marquee>', 'The view tag is properly escaped.');
|
||||
$this->assertEscaped('<script>alert("foo");</script>, <marquee>test</marquee>', 'The view tag is properly escaped.');
|
||||
|
||||
$this->drupalGet('admin/structure/views/view/sa_contrib_2013_035');
|
||||
$this->assertRaw('&lt;marquee&gt;test&lt;/marquee&gt;', 'Field admin label is properly escaped.');
|
||||
$this->assertEscaped('<marquee>test</marquee>', 'Field admin label is properly escaped.');
|
||||
|
||||
$this->drupalGet('admin/structure/views/nojs/handler/sa_contrib_2013_035/page_1/header/area');
|
||||
$this->assertRaw('[title] == &lt;marquee&gt;test&lt;/marquee&gt;', 'Token label is properly escaped.');
|
||||
|
|
|
@ -192,7 +192,7 @@ class ViewAddForm extends ViewFormBase {
|
|||
return;
|
||||
}
|
||||
$this->entity->save();
|
||||
|
||||
drupal_set_message($this->t('The view %name has been saved.', array('%name' => $form_state->getValue('label'))));
|
||||
$form_state->setRedirectUrl($this->entity->urlInfo('edit-form'));
|
||||
}
|
||||
|
||||
|
|
|
@ -414,13 +414,20 @@ class ViewEditForm extends ViewFormBase {
|
|||
elseif ($view->status() && $view->getExecutable()->displayHandlers->get($display['id'])->hasPath()) {
|
||||
$path = $view->getExecutable()->displayHandlers->get($display['id'])->getPath();
|
||||
if ($path && (strpos($path, '%') === FALSE)) {
|
||||
$uri = "base:$path";
|
||||
if (!parse_url($path, PHP_URL_SCHEME)) {
|
||||
// @todo Views should expect and store a leading /. See:
|
||||
// https://www.drupal.org/node/2423913
|
||||
$url = Url::fromUserInput('/' . ltrim($uri, '/'));
|
||||
}
|
||||
else {
|
||||
$url = Url::fromUri($uri);
|
||||
}
|
||||
$build['top']['actions']['path'] = array(
|
||||
'#type' => 'link',
|
||||
'#title' => $this->t('View !display_title', array('!display_title' => $display_title)),
|
||||
'#options' => array('alt' => array($this->t("Go to the real page for this display"))),
|
||||
// @todo Use Url::fromPath() once
|
||||
// https://www.drupal.org/node/2351379 is resolved.
|
||||
'#url' => Url::fromUri("base:$path"),
|
||||
'#url' => $url,
|
||||
'#prefix' => '<li class="view">',
|
||||
"#suffix" => '</li>',
|
||||
);
|
||||
|
@ -487,7 +494,7 @@ class ViewEditForm extends ViewFormBase {
|
|||
$build['top']['display_title'] = array(
|
||||
'#theme' => 'views_ui_display_tab_setting',
|
||||
'#description' => $this->t('Display name'),
|
||||
'#link' => $view->getExecutable()->displayHandlers->get($display['id'])->optionLink(SafeMarkup::checkPlain($display_title), 'display_title'),
|
||||
'#link' => $view->getExecutable()->displayHandlers->get($display['id'])->optionLink($display_title, 'display_title'),
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -661,12 +668,10 @@ class ViewEditForm extends ViewFormBase {
|
|||
|
||||
// Regenerate the main display area.
|
||||
$build = $this->getDisplayTab($view);
|
||||
static::addMicroweights($build);
|
||||
$response->addCommand(new HtmlCommand('#views-tab-' . $display_id, $build));
|
||||
|
||||
// Regenerate the top area so changes to display names and order will appear.
|
||||
$build = $this->renderDisplayTop($view);
|
||||
static::addMicroweights($build);
|
||||
$response->addCommand(new ReplaceCommand('#views-display-top', $build));
|
||||
}
|
||||
|
||||
|
@ -1055,7 +1060,7 @@ class ViewEditForm extends ViewFormBase {
|
|||
continue;
|
||||
}
|
||||
|
||||
$field_name = SafeMarkup::checkPlain($handler->adminLabel(TRUE));
|
||||
$field_name = $handler->adminLabel(TRUE);
|
||||
if (!empty($field['relationship']) && !empty($relationships[$field['relationship']])) {
|
||||
$field_name = '(' . $relationships[$field['relationship']] . ') ' . $field_name;
|
||||
}
|
||||
|
@ -1141,22 +1146,4 @@ class ViewEditForm extends ViewFormBase {
|
|||
return $build;
|
||||
}
|
||||
|
||||
/**
|
||||
* Recursively adds microweights to a render array, similar to what
|
||||
* \Drupal::formBuilder()->doBuildForm() does for forms.
|
||||
*
|
||||
* @todo Submit a core patch to fix drupal_render() to do this, so that all
|
||||
* render arrays automatically preserve array insertion order, as forms do.
|
||||
*/
|
||||
public static function addMicroweights(&$build) {
|
||||
$count = 0;
|
||||
foreach (Element::children($build) as $key) {
|
||||
if (!isset($build[$key]['#weight'])) {
|
||||
$build[$key]['#weight'] = $count/1000;
|
||||
}
|
||||
static::addMicroweights($build[$key]);
|
||||
$count++;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -7,7 +7,6 @@
|
|||
|
||||
namespace Drupal\views_ui;
|
||||
|
||||
use Drupal\Component\Utility\SafeMarkup;
|
||||
use Drupal\Component\Plugin\PluginManagerInterface;
|
||||
use Drupal\Core\Entity\EntityInterface;
|
||||
use Drupal\Core\Config\Entity\ConfigEntityListBuilder;
|
||||
|
@ -30,6 +29,11 @@ class ViewListBuilder extends ConfigEntityListBuilder {
|
|||
*/
|
||||
protected $displayManager;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected $limit;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
|
@ -55,6 +59,11 @@ class ViewListBuilder extends ConfigEntityListBuilder {
|
|||
parent::__construct($entity_type, $storage);
|
||||
|
||||
$this->displayManager = $display_manager;
|
||||
// This list builder uses client-side filters which requires all entities to
|
||||
// be listed, disable the pager.
|
||||
// @todo https://www.drupal.org/node/2536826 change the filtering to support
|
||||
// a pager.
|
||||
$this->limit = FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -81,12 +90,6 @@ class ViewListBuilder extends ConfigEntityListBuilder {
|
|||
*/
|
||||
public function buildRow(EntityInterface $view) {
|
||||
$row = parent::buildRow($view);
|
||||
$display_paths = '';
|
||||
$separator = '';
|
||||
foreach ($this->getDisplayPaths($view) as $display_path) {
|
||||
$display_paths .= $separator . SafeMarkup::escape($display_path);
|
||||
$separator = ', ';
|
||||
}
|
||||
return array(
|
||||
'data' => array(
|
||||
'view_name' => array(
|
||||
|
@ -98,12 +101,18 @@ class ViewListBuilder extends ConfigEntityListBuilder {
|
|||
),
|
||||
'description' => array(
|
||||
'data' => array(
|
||||
'#markup' => SafeMarkup::checkPlain($view->get('description')),
|
||||
'#plain_text' => $view->get('description'),
|
||||
),
|
||||
'class' => array('views-table-filter-text-source'),
|
||||
),
|
||||
'tag' => $view->get('tag'),
|
||||
'path' => SafeMarkup::set($display_paths),
|
||||
'path' => array(
|
||||
'data' => array(
|
||||
'#theme' => 'item_list',
|
||||
'#items' => $this->getDisplayPaths($view),
|
||||
'#context' => ['list_style' => 'comma-list'],
|
||||
),
|
||||
),
|
||||
'operations' => $row['operations'],
|
||||
),
|
||||
'title' => $this->t('Machine name: @name', array('@name' => $view->id())),
|
||||
|
@ -268,7 +277,7 @@ class ViewListBuilder extends ConfigEntityListBuilder {
|
|||
$all_paths[] = \Drupal::l('/' . $path, Url::fromUserInput('/' . $path));
|
||||
}
|
||||
else {
|
||||
$all_paths[] = SafeMarkup::checkPlain('/' . $path);
|
||||
$all_paths[] = '/' . $path;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
|
||||
namespace Drupal\Tests\views_ui\Unit;
|
||||
|
||||
use Drupal\Component\Utility\SafeMarkup;
|
||||
use Drupal\Core\DependencyInjection\ContainerBuilder;
|
||||
use Drupal\Core\Entity\EntityInterface;
|
||||
use Drupal\Tests\UnitTestCase;
|
||||
|
@ -89,7 +90,10 @@ class ViewListBuilderTest extends UnitTestCase {
|
|||
);
|
||||
$page_display->expects($this->any())
|
||||
->method('getPath')
|
||||
->will($this->returnValue('test_page'));
|
||||
->will($this->onConsecutiveCalls(
|
||||
$this->returnValue('test_page'),
|
||||
$this->returnValue('<object>malformed_path</object>'),
|
||||
$this->returnValue('<script>alert("placeholder_page/%")</script>')));
|
||||
|
||||
$embed_display = $this->getMock('Drupal\views\Plugin\views\display\Embed', array('initDisplay'),
|
||||
array(array(), 'default', $display_manager->getDefinition('embed'))
|
||||
|
@ -106,6 +110,16 @@ class ViewListBuilderTest extends UnitTestCase {
|
|||
$values['display']['page_1']['display_plugin'] = 'page';
|
||||
$values['display']['page_1']['display_options']['path'] = 'test_page';
|
||||
|
||||
$values['display']['page_2']['id'] = 'page_2';
|
||||
$values['display']['page_2']['display_title'] = 'Page 2';
|
||||
$values['display']['page_2']['display_plugin'] = 'page';
|
||||
$values['display']['page_2']['display_options']['path'] = '<object>malformed_path</object>';
|
||||
|
||||
$values['display']['page_3']['id'] = 'page_3';
|
||||
$values['display']['page_3']['display_title'] = 'Page 3';
|
||||
$values['display']['page_3']['display_plugin'] = 'page';
|
||||
$values['display']['page_3']['display_options']['path'] = '<script>alert("placeholder_page/%")</script>';
|
||||
|
||||
$values['display']['embed']['id'] = 'embed';
|
||||
$values['display']['embed']['display_title'] = 'Embedded';
|
||||
$values['display']['embed']['display_plugin'] = 'embed';
|
||||
|
@ -115,6 +129,8 @@ class ViewListBuilderTest extends UnitTestCase {
|
|||
->will($this->returnValueMap(array(
|
||||
array('default', $values['display']['default'], $default_display),
|
||||
array('page', $values['display']['page_1'], $page_display),
|
||||
array('page', $values['display']['page_2'], $page_display),
|
||||
array('page', $values['display']['page_3'], $page_display),
|
||||
array('embed', $values['display']['embed'], $embed_display),
|
||||
)));
|
||||
|
||||
|
@ -141,8 +157,19 @@ class ViewListBuilderTest extends UnitTestCase {
|
|||
|
||||
$row = $view_list_builder->buildRow($view);
|
||||
|
||||
$this->assertEquals(array('Embed admin label', 'Page admin label'), $row['data']['view_name']['data']['#displays'], 'Wrong displays got added to view list');
|
||||
$this->assertEquals($row['data']['path'], '/test_page', 'The path of the page display is not added.');
|
||||
$expected_displays = array(
|
||||
'Embed admin label',
|
||||
'Page admin label',
|
||||
'Page admin label',
|
||||
'Page admin label',
|
||||
);
|
||||
$this->assertEquals($expected_displays, $row['data']['view_name']['data']['#displays']);
|
||||
|
||||
$display_paths = $row['data']['path']['data']['#items'];
|
||||
// These values will be escaped by Twig when rendered.
|
||||
$this->assertEquals('/test_page, /<object>malformed_path</object>, /<script>alert("placeholder_page/%")</script>', implode(', ', $display_paths));
|
||||
$this->assertFalse(SafeMarkup::isSafe('/<object>malformed_path</object>'), '/<script>alert("/<object>malformed_path</object> is not marked safe.');
|
||||
$this->assertFalse(SafeMarkup::isSafe('/<script>alert("placeholder_page/%")'), '/<script>alert("/<script>alert("placeholder_page/%") is not marked safe.');
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Reference in a new issue