Update Composer, update everything

This commit is contained in:
Oliver Davies 2018-11-23 12:29:20 +00:00
parent ea3e94409f
commit dda5c284b6
19527 changed files with 1135420 additions and 351004 deletions

View file

@ -150,7 +150,7 @@ function hook_block_view_BASE_BLOCK_ID_alter(array &$build, \Drupal\Core\Block\B
*/
function hook_block_build_alter(array &$build, \Drupal\Core\Block\BlockPluginInterface $block) {
// Add the 'user' cache context to some blocks.
if ($some_condition) {
if ($block->label() === 'some condition') {
$build['#cache']['contexts'][] = 'user';
}
}

View file

@ -73,7 +73,7 @@ function block_update_8001() {
// their own updates.
$update_backup[$block->get('id')] = [
'missing_context_ids' => $backup_values,
'status' => $block->get('status')
'status' => $block->get('status'),
];
}
}

View file

@ -16,4 +16,6 @@ drupal.block.admin:
dependencies:
- core/jquery
- core/drupal
- core/drupal.announce
- core/drupal.debounce
- core/drupal.dialog.ajax

View file

@ -145,7 +145,11 @@ function block_rebuild() {
// Disable blocks in invalid regions.
if (!isset($regions[$block->getRegion()])) {
if ($block->status()) {
drupal_set_message(t('The block %info was assigned to the invalid region %region and has been disabled.', ['%info' => $block_id, '%region' => $block->getRegion()]), 'warning');
\Drupal::messenger()
->addWarning(t('The block %info was assigned to the invalid region %region and has been disabled.', [
'%info' => $block_id,
'%region' => $block->getRegion(),
]));
}
$block
->setRegion(system_default_region($theme))

View file

@ -60,7 +60,7 @@ function block_post_update_disable_blocks_with_missing_contexts() {
foreach ($blocks as $disabled_block_id => $disabled_block) {
$message .= '<li>' . t('@label (Visibility: @plugin_ids)', [
'@label' => $disabled_block->get('settings')['label'],
'@plugin_ids' => implode(', ', array_intersect_key($condition_plugin_id_label_map, array_flip(array_keys($block_update_8001[$disabled_block_id]['missing_context_ids']))))
'@plugin_ids' => implode(', ', array_intersect_key($condition_plugin_id_label_map, array_flip(array_keys($block_update_8001[$disabled_block_id]['missing_context_ids'])))),
]) . '</li>';
}
$message .= '</ul>';

View file

@ -52,7 +52,7 @@ block.admin_display:
_permission: 'administer blocks'
block.admin_display_theme:
path: 'admin/structure/block/list/{theme}'
path: '/admin/structure/block/list/{theme}'
defaults:
_controller: '\Drupal\block\Controller\BlockListController::listing'
_title: 'Block layout'
@ -61,7 +61,7 @@ block.admin_display_theme:
_permission: 'administer blocks'
block.admin_library:
path: 'admin/structure/block/library/{theme}'
path: '/admin/structure/block/library/{theme}'
defaults:
_controller: '\Drupal\block\Controller\BlockLibraryController::listBlocks'
_title: 'Place block'

View file

@ -30,6 +30,3 @@ block.block.*:
sequence:
type: condition.plugin.[id]
label: 'Visibility Condition'
block.settings.*:
type: block_settings

View file

@ -24,7 +24,7 @@ a.block-demo-backlink:visited {
font-family: "Lucida Grande", Verdana, sans-serif;
font-size: small;
line-height: 20px;
left: 20px; /*LTR*/
left: 20px; /* LTR */
padding: 5px 10px;
position: fixed;
z-index: 499;

View file

@ -0,0 +1,117 @@
/**
* @file
* Block admin behaviors.
*/
(function($, Drupal, debounce) {
/**
* Filters the block list by a text input search string.
*
* The text input will have the selector `input.block-filter-text`.
*
* The target element to do searching in will be in the selector
* `input.block-filter-text[data-element]`
*
* The text source where the text should be found will have the selector
* `.block-filter-text-source`
*
* @type {Drupal~behavior}
*
* @prop {Drupal~behaviorAttach} attach
* Attaches the behavior for the block filtering.
*/
Drupal.behaviors.blockFilterByText = {
attach(context, settings) {
const $input = $('input.block-filter-text').once('block-filter-text');
const $table = $($input.attr('data-element'));
let $filterRows;
/**
* Filters the block list.
*
* @param {jQuery.Event} e
* The jQuery event for the keyup event that triggered the filter.
*/
function filterBlockList(e) {
const query = $(e.target)
.val()
.toLowerCase();
/**
* Shows or hides the block entry based on the query.
*
* @param {number} index
* The index in the loop, as provided by `jQuery.each`
* @param {HTMLElement} label
* The label of the block.
*/
function toggleBlockEntry(index, label) {
const $label = $(label);
const $row = $label.parent().parent();
const textMatch =
$label
.text()
.toLowerCase()
.indexOf(query) !== -1;
$row.toggle(textMatch);
}
// Filter if the length of the query is at least 2 characters.
if (query.length >= 2) {
$filterRows.each(toggleBlockEntry);
Drupal.announce(
Drupal.formatPlural(
$table.find('tr:visible').length - 1,
'1 block is available in the modified list.',
'@count blocks are available in the modified list.',
),
);
} else {
$filterRows.each(function(index) {
$(this)
.parent()
.parent()
.show();
});
}
}
if ($table.length) {
$filterRows = $table.find('div.block-filter-text-source');
$input.on('keyup', debounce(filterBlockList, 200));
}
},
};
/**
* Highlights the block that was just placed into the block listing.
*
* @type {Drupal~behavior}
*
* @prop {Drupal~behaviorAttach} attach
* Attaches the behavior for the block placement highlighting.
*/
Drupal.behaviors.blockHighlightPlacement = {
attach(context, settings) {
if (settings.blockPlacement) {
$(context)
.find('[data-drupal-selector="edit-blocks"]')
.once('block-highlight')
.each(function() {
const $container = $(this);
// Just scrolling the document.body will not work in Firefox. The html
// element is needed as well.
$('html, body').animate(
{
scrollTop:
$('.js-block-placed').offset().top -
$container.offset().top +
$container.scrollTop(),
},
500,
);
});
}
},
};
})(jQuery, Drupal, Drupal.debounce);

View file

@ -1,51 +1,20 @@
/**
* @file
* Block admin behaviors.
*/
* DO NOT EDIT THIS FILE.
* See the following change record for more information,
* https://www.drupal.org/node/2815083
* @preserve
**/
(function ($, Drupal) {
'use strict';
/**
* Filters the block list by a text input search string.
*
* The text input will have the selector `input.block-filter-text`.
*
* The target element to do searching in will be in the selector
* `input.block-filter-text[data-element]`
*
* The text source where the text should be found will have the selector
* `.block-filter-text-source`
*
* @type {Drupal~behavior}
*
* @prop {Drupal~behaviorAttach} attach
* Attaches the behavior for the block filtering.
*/
(function ($, Drupal, debounce) {
Drupal.behaviors.blockFilterByText = {
attach: function (context, settings) {
attach: function attach(context, settings) {
var $input = $('input.block-filter-text').once('block-filter-text');
var $table = $($input.attr('data-element'));
var $filter_rows;
var $filterRows = void 0;
/**
* Filters the block list.
*
* @param {jQuery.Event} e
* The jQuery event for the keyup event that triggered the filter.
*/
function filterBlockList(e) {
var query = $(e.target).val().toLowerCase();
/**
* Shows or hides the block entry based on the query.
*
* @param {number} index
* The index in the loop, as provided by `jQuery.each`
* @param {HTMLElement} label
* The label of the block.
*/
function toggleBlockEntry(index, label) {
var $label = $(label);
var $row = $label.parent().parent();
@ -53,39 +22,29 @@
$row.toggle(textMatch);
}
// Filter if the length of the query is at least 2 characters.
if (query.length >= 2) {
$filter_rows.each(toggleBlockEntry);
}
else {
$filter_rows.each(function (index) {
$filterRows.each(toggleBlockEntry);
Drupal.announce(Drupal.formatPlural($table.find('tr:visible').length - 1, '1 block is available in the modified list.', '@count blocks are available in the modified list.'));
} else {
$filterRows.each(function (index) {
$(this).parent().parent().show();
});
}
}
if ($table.length) {
$filter_rows = $table.find('div.block-filter-text-source');
$input.on('keyup', filterBlockList);
$filterRows = $table.find('div.block-filter-text-source');
$input.on('keyup', debounce(filterBlockList, 200));
}
}
};
/**
* Highlights the block that was just placed into the block listing.
*
* @type {Drupal~behavior}
*
* @prop {Drupal~behaviorAttach} attach
* Attaches the behavior for the block placement highlighting.
*/
Drupal.behaviors.blockHighlightPlacement = {
attach: function (context, settings) {
attach: function attach(context, settings) {
if (settings.blockPlacement) {
$(context).find('[data-drupal-selector="edit-blocks"]').once('block-highlight').each(function () {
var $container = $(this);
// Just scrolling the document.body will not work in Firefox. The html
// element is needed as well.
$('html, body').animate({
scrollTop: $('.js-block-placed').offset().top - $container.offset().top + $container.scrollTop()
}, 500);
@ -93,5 +52,4 @@
}
}
};
}(jQuery, Drupal));
})(jQuery, Drupal, Drupal.debounce);

View file

@ -0,0 +1,262 @@
/**
* @file
* Block behaviors.
*/
(function($, window, Drupal) {
/**
* Provide the summary information for the block settings vertical tabs.
*
* @type {Drupal~behavior}
*
* @prop {Drupal~behaviorAttach} attach
* Attaches the behavior for the block settings summaries.
*/
Drupal.behaviors.blockSettingsSummary = {
attach() {
// The drupalSetSummary method required for this behavior is not available
// on the Blocks administration page, so we need to make sure this
// behavior is processed only if drupalSetSummary is defined.
if (typeof $.fn.drupalSetSummary === 'undefined') {
return;
}
/**
* Create a summary for checkboxes in the provided context.
*
* @param {HTMLDocument|HTMLElement} context
* A context where one would find checkboxes to summarize.
*
* @return {string}
* A string with the summary.
*/
function checkboxesSummary(context) {
const vals = [];
const $checkboxes = $(context).find(
'input[type="checkbox"]:checked + label',
);
const il = $checkboxes.length;
for (let i = 0; i < il; i++) {
vals.push($($checkboxes[i]).html());
}
if (!vals.length) {
vals.push(Drupal.t('Not restricted'));
}
return vals.join(', ');
}
$(
'[data-drupal-selector="edit-visibility-node-type"], [data-drupal-selector="edit-visibility-language"], [data-drupal-selector="edit-visibility-user-role"]',
).drupalSetSummary(checkboxesSummary);
$(
'[data-drupal-selector="edit-visibility-request-path"]',
).drupalSetSummary(context => {
const $pages = $(context).find(
'textarea[name="visibility[request_path][pages]"]',
);
if (!$pages.val()) {
return Drupal.t('Not restricted');
}
return Drupal.t('Restricted to certain pages');
});
},
};
/**
* Move a block in the blocks table between regions via select list.
*
* This behavior is dependent on the tableDrag behavior, since it uses the
* objects initialized in that behavior to update the row.
*
* @type {Drupal~behavior}
*
* @prop {Drupal~behaviorAttach} attach
* Attaches the tableDrag behaviour for blocks in block administration.
*/
Drupal.behaviors.blockDrag = {
attach(context, settings) {
// tableDrag is required and we should be on the blocks admin page.
if (
typeof Drupal.tableDrag === 'undefined' ||
typeof Drupal.tableDrag.blocks === 'undefined'
) {
return;
}
/**
* Function to check empty regions and toggle classes based on this.
*
* @param {jQuery} table
* The jQuery object representing the table to inspect.
* @param {jQuery} rowObject
* The jQuery object representing the table row.
*/
function checkEmptyRegions(table, rowObject) {
table.find('tr.region-message').each(function() {
const $this = $(this);
// If the dragged row is in this region, but above the message row,
// swap it down one space.
if ($this.prev('tr').get(0) === rowObject.element) {
// Prevent a recursion problem when using the keyboard to move rows
// up.
if (
rowObject.method !== 'keyboard' ||
rowObject.direction === 'down'
) {
rowObject.swap('after', this);
}
}
// This region has become empty.
if (
$this.next('tr').is(':not(.draggable)') ||
$this.next('tr').length === 0
) {
$this.removeClass('region-populated').addClass('region-empty');
}
// This region has become populated.
else if ($this.is('.region-empty')) {
$this.removeClass('region-empty').addClass('region-populated');
}
});
}
/**
* Function to update the last placed row with the correct classes.
*
* @param {jQuery} table
* The jQuery object representing the table to inspect.
* @param {jQuery} rowObject
* The jQuery object representing the table row.
*/
function updateLastPlaced(table, rowObject) {
// Remove the color-success class from new block if applicable.
table.find('.color-success').removeClass('color-success');
const $rowObject = $(rowObject);
if (!$rowObject.is('.drag-previous')) {
table.find('.drag-previous').removeClass('drag-previous');
$rowObject.addClass('drag-previous');
}
}
/**
* Update block weights in the given region.
*
* @param {jQuery} table
* Table with draggable items.
* @param {string} region
* Machine name of region containing blocks to update.
*/
function updateBlockWeights(table, region) {
// Calculate minimum weight.
let weight = -Math.round(table.find('.draggable').length / 2);
// Update the block weights.
table
.find(`.region-${region}-message`)
.nextUntil('.region-title')
.find('select.block-weight')
.val(
// Increment the weight before assigning it to prevent using the
// absolute minimum available weight. This way we always have an
// unused upper and lower bound, which makes manually setting the
// weights easier for users who prefer to do it that way.
() => ++weight,
);
}
const table = $('#blocks');
// Get the blocks tableDrag object.
const tableDrag = Drupal.tableDrag.blocks;
// Add a handler for when a row is swapped, update empty regions.
tableDrag.row.prototype.onSwap = function(swappedRow) {
checkEmptyRegions(table, this);
updateLastPlaced(table, this);
};
// Add a handler so when a row is dropped, update fields dropped into
// new regions.
tableDrag.onDrop = function() {
const dragObject = this;
const $rowElement = $(dragObject.rowObject.element);
// Use "region-message" row instead of "region" row because
// "region-{region_name}-message" is less prone to regexp match errors.
const regionRow = $rowElement.prevAll('tr.region-message').get(0);
const regionName = regionRow.className.replace(
/([^ ]+[ ]+)*region-([^ ]+)-message([ ]+[^ ]+)*/,
'$2',
);
const regionField = $rowElement.find('select.block-region-select');
// Check whether the newly picked region is available for this block.
if (regionField.find(`option[value=${regionName}]`).length === 0) {
// If not, alert the user and keep the block in its old region
// setting.
window.alert(Drupal.t('The block cannot be placed in this region.'));
// Simulate that there was a selected element change, so the row is
// put back to from where the user tried to drag it.
regionField.trigger('change');
}
// Update region and weight fields if the region has been changed.
if (!regionField.is(`.block-region-${regionName}`)) {
const weightField = $rowElement.find('select.block-weight');
const oldRegionName = weightField[0].className.replace(
/([^ ]+[ ]+)*block-weight-([^ ]+)([ ]+[^ ]+)*/,
'$2',
);
regionField
.removeClass(`block-region-${oldRegionName}`)
.addClass(`block-region-${regionName}`);
weightField
.removeClass(`block-weight-${oldRegionName}`)
.addClass(`block-weight-${regionName}`);
regionField.val(regionName);
}
updateBlockWeights(table, regionName);
};
// Add the behavior to each region select list.
$(context)
.find('select.block-region-select')
.once('block-region-select')
.on('change', function(event) {
// Make our new row and select field.
const row = $(this).closest('tr');
const select = $(this);
// Find the correct region and insert the row as the last in the
// region.
tableDrag.rowObject = new tableDrag.row(row[0]);
const regionMessage = table.find(
`.region-${select[0].value}-message`,
);
const regionItems = regionMessage.nextUntil(
'.region-message, .region-title',
);
if (regionItems.length) {
regionItems.last().after(row);
}
// We found that regionMessage is the last row.
else {
regionMessage.after(row);
}
updateBlockWeights(table, select[0].value);
// Modify empty regions with added or removed fields.
checkEmptyRegions(table, tableDrag.rowObject);
// Update last placed block indication.
updateLastPlaced(table, row);
// Show unsaved changes warning.
if (!tableDrag.changed) {
$(Drupal.theme('tableDragChangedWarning'))
.insertBefore(tableDrag.table)
.hide()
.fadeIn('slow');
tableDrag.changed = true;
}
// Remove focus from selectbox.
select.trigger('blur');
});
},
};
})(jQuery, window, Drupal);

View file

@ -1,38 +1,17 @@
/**
* @file
* Block behaviors.
*/
* DO NOT EDIT THIS FILE.
* See the following change record for more information,
* https://www.drupal.org/node/2815083
* @preserve
**/
(function ($, window, Drupal) {
'use strict';
/**
* Provide the summary information for the block settings vertical tabs.
*
* @type {Drupal~behavior}
*
* @prop {Drupal~behaviorAttach} attach
* Attaches the behavior for the block settings summaries.
*/
Drupal.behaviors.blockSettingsSummary = {
attach: function () {
// The drupalSetSummary method required for this behavior is not available
// on the Blocks administration page, so we need to make sure this
// behavior is processed only if drupalSetSummary is defined.
attach: function attach() {
if (typeof $.fn.drupalSetSummary === 'undefined') {
return;
}
/**
* Create a summary for checkboxes in the provided context.
*
* @param {HTMLDocument|HTMLElement} context
* A context where one would find checkboxes to summarize.
*
* @return {string}
* A string with the summary.
*/
function checkboxesSummary(context) {
var vals = [];
var $checkboxes = $(context).find('input[type="checkbox"]:checked + label');
@ -53,72 +32,37 @@
if (!$pages.val()) {
return Drupal.t('Not restricted');
}
else {
return Drupal.t('Restricted to certain pages');
}
return Drupal.t('Restricted to certain pages');
});
}
};
/**
* Move a block in the blocks table between regions via select list.
*
* This behavior is dependent on the tableDrag behavior, since it uses the
* objects initialized in that behavior to update the row.
*
* @type {Drupal~behavior}
*
* @prop {Drupal~behaviorAttach} attach
* Attaches the tableDrag behaviour for blocks in block administration.
*/
Drupal.behaviors.blockDrag = {
attach: function (context, settings) {
// tableDrag is required and we should be on the blocks admin page.
attach: function attach(context, settings) {
if (typeof Drupal.tableDrag === 'undefined' || typeof Drupal.tableDrag.blocks === 'undefined') {
return;
}
/**
* Function to check empty regions and toggle classes based on this.
*
* @param {jQuery} table
* The jQuery object representing the table to inspect.
* @param {jQuery} rowObject
* The jQuery object representing the table row.
*/
function checkEmptyRegions(table, rowObject) {
table.find('tr.region-message').each(function () {
var $this = $(this);
// If the dragged row is in this region, but above the message row,
// swap it down one space.
if ($this.prev('tr').get(0) === rowObject.element) {
// Prevent a recursion problem when using the keyboard to move rows
// up.
if ((rowObject.method !== 'keyboard' || rowObject.direction === 'down')) {
if (rowObject.method !== 'keyboard' || rowObject.direction === 'down') {
rowObject.swap('after', this);
}
}
// This region has become empty.
if ($this.next('tr').is(':not(.draggable)') || $this.next('tr').length === 0) {
$this.removeClass('region-populated').addClass('region-empty');
}
// This region has become populated.
else if ($this.is('.region-empty')) {
$this.removeClass('region-empty').addClass('region-populated');
}
} else if ($this.is('.region-empty')) {
$this.removeClass('region-empty').addClass('region-populated');
}
});
}
/**
* Function to update the last placed row with the correct classes.
*
* @param {jQuery} table
* The jQuery object representing the table to inspect.
* @param {jQuery} rowObject
* The jQuery object representing the table row.
*/
function updateLastPlaced(table, rowObject) {
// Remove the color-success class from new block if applicable.
table.find('.color-success').removeClass('color-success');
var $rowObject = $(rowObject);
@ -128,58 +72,37 @@
}
}
/**
* Update block weights in the given region.
*
* @param {jQuery} table
* Table with draggable items.
* @param {string} region
* Machine name of region containing blocks to update.
*/
function updateBlockWeights(table, region) {
// Calculate minimum weight.
var weight = -Math.round(table.find('.draggable').length / 2);
// Update the block weights.
table.find('.region-' + region + '-message').nextUntil('.region-title')
.find('select.block-weight').val(function () {
// Increment the weight before assigning it to prevent using the
// absolute minimum available weight. This way we always have an
// unused upper and lower bound, which makes manually setting the
// weights easier for users who prefer to do it that way.
return ++weight;
});
table.find('.region-' + region + '-message').nextUntil('.region-title').find('select.block-weight').val(function () {
return ++weight;
});
}
var table = $('#blocks');
// Get the blocks tableDrag object.
var tableDrag = Drupal.tableDrag.blocks;
// Add a handler for when a row is swapped, update empty regions.
tableDrag.row.prototype.onSwap = function (swappedRow) {
checkEmptyRegions(table, this);
updateLastPlaced(table, this);
};
// Add a handler so when a row is dropped, update fields dropped into
// new regions.
tableDrag.onDrop = function () {
var dragObject = this;
var $rowElement = $(dragObject.rowObject.element);
// Use "region-message" row instead of "region" row because
// "region-{region_name}-message" is less prone to regexp match errors.
var regionRow = $rowElement.prevAll('tr.region-message').get(0);
var regionName = regionRow.className.replace(/([^ ]+[ ]+)*region-([^ ]+)-message([ ]+[^ ]+)*/, '$2');
var regionField = $rowElement.find('select.block-region-select');
// Check whether the newly picked region is available for this block.
if (regionField.find('option[value=' + regionName + ']').length === 0) {
// If not, alert the user and keep the block in its old region
// setting.
window.alert(Drupal.t('The block cannot be placed in this region.'));
// Simulate that there was a selected element change, so the row is
// put back to from where the user tried to drag it.
regionField.trigger('change');
}
// Update region and weight fields if the region has been changed.
if (!regionField.is('.block-region-' + regionName)) {
var weightField = $rowElement.find('select.block-weight');
var oldRegionName = weightField[0].className.replace(/([^ ]+[ ]+)*block-weight-([^ ]+)([ ]+[^ ]+)*/, '$2');
@ -191,38 +114,31 @@
updateBlockWeights(table, regionName);
};
// Add the behavior to each region select list.
$(context).find('select.block-region-select').once('block-region-select')
.on('change', function (event) {
// Make our new row and select field.
var row = $(this).closest('tr');
var select = $(this);
// Find the correct region and insert the row as the last in the
// region.
tableDrag.rowObject = new tableDrag.row(row[0]);
var region_message = table.find('.region-' + select[0].value + '-message');
var region_items = region_message.nextUntil('.region-message, .region-title');
if (region_items.length) {
region_items.last().after(row);
$(context).find('select.block-region-select').once('block-region-select').on('change', function (event) {
var row = $(this).closest('tr');
var select = $(this);
tableDrag.rowObject = new tableDrag.row(row[0]);
var regionMessage = table.find('.region-' + select[0].value + '-message');
var regionItems = regionMessage.nextUntil('.region-message, .region-title');
if (regionItems.length) {
regionItems.last().after(row);
} else {
regionMessage.after(row);
}
// We found that region_message is the last row.
else {
region_message.after(row);
}
updateBlockWeights(table, select[0].value);
// Modify empty regions with added or removed fields.
checkEmptyRegions(table, tableDrag.rowObject);
// Update last placed block indication.
updateLastPlaced(table, row);
// Show unsaved changes warning.
if (!tableDrag.changed) {
$(Drupal.theme('tableDragChangedWarning')).insertBefore(tableDrag.table).hide().fadeIn('slow');
tableDrag.changed = true;
}
// Remove focus from selectbox.
select.trigger('blur');
});
updateBlockWeights(table, select[0].value);
checkEmptyRegions(table, tableDrag.rowObject);
updateLastPlaced(table, row);
if (!tableDrag.changed) {
$(Drupal.theme('tableDragChangedWarning')).insertBefore(tableDrag.table).hide().fadeIn('slow');
tableDrag.changed = true;
}
select.trigger('blur');
});
}
};
})(jQuery, window, Drupal);
})(jQuery, window, Drupal);

View file

@ -2,6 +2,7 @@ id: d6_block
label: Blocks
migration_tags:
- Drupal 6
- Configuration
source:
plugin: block
process:

View file

@ -2,6 +2,7 @@ id: d7_block
label: Blocks
migration_tags:
- Drupal 7
- Configuration
source:
plugin: block
process:

View file

@ -3,6 +3,7 @@
namespace Drupal\block;
use Drupal\Component\Plugin\Exception\ContextException;
use Drupal\Component\Plugin\Exception\MissingValueContextException;
use Drupal\Core\Access\AccessResult;
use Drupal\Core\Cache\Cache;
use Drupal\Core\Cache\CacheableDependencyInterface;
@ -61,13 +62,12 @@ class BlockAccessControlHandler extends EntityAccessControlHandler implements En
* @param \Drupal\Core\Plugin\Context\ContextRepositoryInterface $context_repository
* The lazy context repository service.
*/
public function __construct(EntityTypeInterface $entity_type, ContextHandlerInterface $context_handler, ContextRepositoryInterface $context_repository ) {
public function __construct(EntityTypeInterface $entity_type, ContextHandlerInterface $context_handler, ContextRepositoryInterface $context_repository) {
parent::__construct($entity_type);
$this->contextHandler = $context_handler;
$this->contextRepository = $context_repository;
}
/**
* {@inheritdoc}
*/
@ -84,12 +84,16 @@ class BlockAccessControlHandler extends EntityAccessControlHandler implements En
else {
$conditions = [];
$missing_context = FALSE;
$missing_value = FALSE;
foreach ($entity->getVisibilityConditions() as $condition_id => $condition) {
if ($condition instanceof ContextAwarePluginInterface) {
try {
$contexts = $this->contextRepository->getRuntimeContexts(array_values($condition->getContextMapping()));
$this->contextHandler->applyContextMapping($condition, $contexts);
}
catch (MissingValueContextException $e) {
$missing_value = TRUE;
}
catch (ContextException $e) {
$missing_context = TRUE;
}
@ -100,14 +104,15 @@ class BlockAccessControlHandler extends EntityAccessControlHandler implements En
if ($missing_context) {
// If any context is missing then we might be missing cacheable
// metadata, and don't know based on what conditions the block is
// accessible or not. For example, blocks that have a node type
// condition will have a missing context on any non-node route like the
// frontpage.
// @todo Avoid setting max-age 0 for some or all cases, for example by
// treating available contexts without value differently in
// https://www.drupal.org/node/2521956.
// accessible or not. Make sure the result cannot be cached.
$access = AccessResult::forbidden()->setCacheMaxAge(0);
}
elseif ($missing_value) {
// The contexts exist but have no value. Deny access without
// disabling caching. For example the node type condition will have a
// missing context on any non-node route like the frontpage.
$access = AccessResult::forbidden();
}
elseif ($this->resolveConditions($conditions, 'and') !== FALSE) {
// Delegate to the plugin.
$block_plugin = $entity->getPlugin();
@ -118,12 +123,15 @@ class BlockAccessControlHandler extends EntityAccessControlHandler implements En
}
$access = $block_plugin->access($account, TRUE);
}
catch (MissingValueContextException $e) {
// The contexts exist but have no value. Deny access without
// disabling caching.
$access = AccessResult::forbidden();
}
catch (ContextException $e) {
// Setting access to forbidden if any context is missing for the same
// reasons as with conditions (described in the comment above).
// @todo Avoid setting max-age 0 for some or all cases, for example by
// treating available contexts without value differently in
// https://www.drupal.org/node/2521956.
// If any context is missing then we might be missing cacheable
// metadata, and don't know based on what conditions the block is
// accessible or not. Make sure the result cannot be cached.
$access = AccessResult::forbidden()->setCacheMaxAge(0);
}
}

View file

@ -19,6 +19,8 @@ use Symfony\Component\DependencyInjection\ContainerInterface;
/**
* Provides form for block instance forms.
*
* @internal
*/
class BlockForm extends EntityForm {
@ -237,7 +239,8 @@ class BlockForm extends EntityForm {
// @todo Allow list of conditions to be configured in
// https://www.drupal.org/node/2284687.
$visibility = $this->entity->getVisibility();
foreach ($this->manager->getDefinitionsForContexts($form_state->getTemporaryValue('gathered_contexts')) as $condition_id => $definition) {
$definitions = $this->manager->getFilteredDefinitions('block_ui', $form_state->getTemporaryValue('gathered_contexts'), ['block' => $this->entity]);
foreach ($definitions as $condition_id => $definition) {
// Don't display the current theme condition.
if ($condition_id == 'current_theme') {
continue;
@ -357,7 +360,7 @@ class BlockForm extends EntityForm {
// Save the settings of the plugin.
$entity->save();
drupal_set_message($this->t('The block configuration has been saved.'));
$this->messenger()->addStatus($this->t('The block configuration has been saved.'));
$form_state->setRedirect(
'block.admin_display_theme',
[

View file

@ -15,6 +15,8 @@ interface BlockInterface extends ConfigEntityInterface {
*
* @deprecated in Drupal 8.3.x, will be removed before Drupal 9.0.0.
* Use \Drupal\Core\Block\BlockPluginInterface::BLOCK_LABEL_VISIBLE.
*
* @see https://www.drupal.org/node/2829775
*/
const BLOCK_LABEL_VISIBLE = BlockPluginInterface::BLOCK_LABEL_VISIBLE;

View file

@ -11,6 +11,7 @@ use Drupal\Core\Entity\EntityTypeInterface;
use Drupal\Core\Form\FormBuilderInterface;
use Drupal\Core\Form\FormInterface;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Messenger\MessengerInterface;
use Drupal\Core\Theme\ThemeManagerInterface;
use Drupal\Core\Url;
use Symfony\Component\DependencyInjection\ContainerInterface;
@ -56,6 +57,13 @@ class BlockListBuilder extends ConfigEntityListBuilder implements FormInterface
*/
protected $limit = FALSE;
/**
* The messenger.
*
* @var \Drupal\Core\Messenger\MessengerInterface
*/
protected $messenger;
/**
* Constructs a new BlockListBuilder object.
*
@ -68,11 +76,12 @@ class BlockListBuilder extends ConfigEntityListBuilder implements FormInterface
* @param \Drupal\Core\Form\FormBuilderInterface $form_builder
* The form builder.
*/
public function __construct(EntityTypeInterface $entity_type, EntityStorageInterface $storage, ThemeManagerInterface $theme_manager, FormBuilderInterface $form_builder) {
public function __construct(EntityTypeInterface $entity_type, EntityStorageInterface $storage, ThemeManagerInterface $theme_manager, FormBuilderInterface $form_builder, MessengerInterface $messenger) {
parent::__construct($entity_type, $storage);
$this->themeManager = $theme_manager;
$this->formBuilder = $form_builder;
$this->messenger = $messenger;
}
/**
@ -83,7 +92,8 @@ class BlockListBuilder extends ConfigEntityListBuilder implements FormInterface
$entity_type,
$container->get('entity.manager')->getStorage($entity_type->id()),
$container->get('theme.manager'),
$container->get('form_builder')
$container->get('form_builder'),
$container->get('messenger')
);
}
@ -212,7 +222,7 @@ class BlockListBuilder extends ConfigEntityListBuilder implements FormInterface
'#theme_wrappers' => [
'container' => [
'#attributes' => ['class' => 'region-title__action'],
]
],
],
'#prefix' => $title,
'#type' => 'link',
@ -367,7 +377,7 @@ class BlockListBuilder extends ConfigEntityListBuilder implements FormInterface
$entity->setRegion($entity_values['region']);
$entity->save();
}
drupal_set_message(t('The block settings have been updated.'));
$this->messenger->addStatus($this->t('The block settings have been updated.'));
// Remove any previously set block placement.
$this->request->query->remove('block-placement');

View file

@ -53,7 +53,7 @@ class BlockController extends ControllerBase {
*/
public function performOperation(BlockInterface $block, $op) {
$block->$op()->save();
drupal_set_message($this->t('The block settings have been updated.'));
$this->messenger()->addStatus($this->t('The block settings have been updated.'));
return $this->redirect('block.admin_display');
}

View file

@ -101,13 +101,21 @@ class BlockLibraryController extends ControllerBase {
['data' => $this->t('Operations')],
];
// Only add blocks which work without any available context.
$definitions = $this->blockManager->getDefinitionsForContexts($this->contextRepository->getAvailableContexts());
// Order by category, and then by admin label.
$definitions = $this->blockManager->getSortedDefinitions($definitions);
$region = $request->query->get('region');
$weight = $request->query->get('weight');
// Only add blocks which work without any available context.
$definitions = $this->blockManager->getFilteredDefinitions('block_ui', $this->contextRepository->getAvailableContexts(), [
'theme' => $theme,
'region' => $region,
]);
// Order by category, and then by admin label.
$definitions = $this->blockManager->getSortedDefinitions($definitions);
// Filter out definitions that are not intended to be placed by the UI.
$definitions = array_filter($definitions, function (array $definition) {
return empty($definition['_block_ui_hidden']);
});
$rows = [];
foreach ($definitions as $plugin_id => $plugin_definition) {
$row = [];

View file

@ -48,7 +48,8 @@ class BlockListController extends EntityListController {
* The current request.
*
* @return array
* A render array as expected by drupal_render().
* A render array as expected by
* \Drupal\Core\Render\RendererInterface::render().
*/
public function listing($theme = NULL, Request $request = NULL) {
$theme = $theme ?: $this->config('system.theme')->get('default');

View file

@ -17,6 +17,13 @@ use Drupal\Core\Entity\EntityStorageInterface;
* @ConfigEntityType(
* id = "block",
* label = @Translation("Block"),
* label_collection = @Translation("Blocks"),
* label_singular = @Translation("block"),
* label_plural = @Translation("blocks"),
* label_count = @PluralTranslation(
* singular = "@count block",
* plural = "@count blocks",
* ),
* handlers = {
* "access" = "Drupal\block\BlockAccessControlHandler",
* "view_builder" = "Drupal\block\BlockViewBuilder",

View file

@ -7,6 +7,8 @@ use Drupal\Core\Url;
/**
* Provides a deletion confirmation form for the block instance deletion form.
*
* @internal
*/
class BlockDeleteForm extends EntityDeleteForm {

View file

@ -115,7 +115,7 @@ class BlockVisibility extends ProcessPluginBase implements ContainerFactoryPlugi
// anything else -- the block will simply have no PHP or request_path
// visibility configuration.
elseif ($this->skipPHP) {
throw new MigrateSkipRowException();
throw new MigrateSkipRowException(sprintf("The block with bid '%d' from module '%s' will have no PHP or request_path visibility configuration.", $row->getSourceProperty('bid'), $row->getSourceProperty('module'), $destination_property));
}
}
else {

View file

@ -10,7 +10,7 @@ use Drupal\migrate_drupal\Plugin\migrate\source\DrupalSqlBase;
*
* @MigrateSource(
* id = "block",
* source_provider = "block"
* source_module = "block"
* )
*/
class Block extends DrupalSqlBase {
@ -84,7 +84,7 @@ class Block extends DrupalSqlBase {
return [
'bid' => $this->t('The block numeric identifier.'),
'module' => $this->t('The module providing the block.'),
'delta' => $this->t('The block\'s delta.'),
'delta' => $this->t("The block's delta."),
'theme' => $this->t('Which theme the block is placed in.'),
'status' => $this->t('Whether or not the block is enabled.'),
'weight' => $this->t('Weight of the block for ordering within regions.'),

View file

@ -0,0 +1,71 @@
<?php
namespace Drupal\block\Plugin\migrate\source\d6;
use Drupal\block\Plugin\migrate\source\Block;
use Drupal\migrate\Plugin\migrate\source\SourcePluginBase;
use Drupal\migrate\Row;
/**
* Gets i18n block data from source database.
*
* @MigrateSource(
* id = "d6_block_translation",
* source_module = "i18nblocks"
* )
*/
class BlockTranslation extends Block {
/**
* {@inheritdoc}
*/
public function query() {
// Let the parent set the block table to use, but do not use the parent
// query. Instead build a query so can use an inner join to the selected
// block table.
parent::query();
$query = $this->select('i18n_blocks', 'i18n')
->fields('i18n')
->fields('b', ['bid', 'module', 'delta', 'theme', 'title']);
$query->innerJoin($this->blockTable, 'b', ('b.module = i18n.module AND b.delta = i18n.delta'));
return $query;
}
/**
* {@inheritdoc}
*/
public function fields() {
return [
'bid' => $this->t('The block numeric identifier.'),
'ibid' => $this->t('The i18n_blocks block numeric identifier.'),
'module' => $this->t('The module providing the block.'),
'delta' => $this->t("The block's delta."),
'type' => $this->t('Block type'),
'language' => $this->t('Language for this field.'),
'theme' => $this->t('Which theme the block is placed in.'),
'default_theme' => $this->t('The default theme.'),
'title' => $this->t('Block title.'),
];
}
/**
* {@inheritdoc}
*/
public function prepareRow(Row $row) {
$row->setSourceProperty('default_theme', $this->defaultTheme);
return SourcePluginBase::prepareRow($row);
}
/**
* {@inheritdoc}
*/
public function getIds() {
$ids = parent::getIds();
$ids['module']['alias'] = 'b';
$ids['delta']['alias'] = 'b';
$ids['theme']['alias'] = 'b';
$ids['language']['type'] = 'string';
return $ids;
}
}

View file

@ -2,11 +2,18 @@
namespace Drupal\block\Tests;
@trigger_error(__NAMESPACE__ . '\BlockTestBase is deprecated in Drupal 8.5.0 and will be removed before Drupal 9.0.0. Instead, use \Drupal\Tests\block\Functional\BlockTestBase, see https://www.drupal.org/node/2901823.', E_USER_DEPRECATED);
use Drupal\simpletest\WebTestBase;
use Drupal\filter\Entity\FilterFormat;
/**
* Provides setup and helper methods for block module tests.
*
* @deprecated in Drupal 8.5.0 and will be removed before Drupal 9.0.0.
* Use \Drupal\Tests\block\Functional\BlockTestBase.
*
* @see https://www.drupal.org/node/2901823
*/
abstract class BlockTestBase extends WebTestBase {

View file

@ -5,4 +5,4 @@ package: Testing
version: VERSION
core: 8.x
dependencies:
- block
- drupal:block

View file

@ -4,9 +4,8 @@ namespace Drupal\block_test\ContextProvider;
use Drupal\Core\Cache\CacheableMetadata;
use Drupal\Core\Entity\EntityManagerInterface;
use Drupal\Core\Plugin\Context\Context;
use Drupal\Core\Plugin\Context\ContextDefinition;
use Drupal\Core\Plugin\Context\ContextProviderInterface;
use Drupal\Core\Plugin\Context\EntityContext;
use Drupal\Core\Session\AccountInterface;
/**
@ -47,9 +46,8 @@ class MultipleStaticContext implements ContextProviderInterface {
public function getRuntimeContexts(array $unqualified_context_ids) {
$current_user = $this->userStorage->load($this->account->id());
$context1 = new Context(new ContextDefinition('entity:user', 'User A'), $current_user);
$context2 = new Context(new ContextDefinition('entity:user', 'User B'), $current_user);
$context1 = EntityContext::fromEntity($current_user, 'User A');
$context2 = EntityContext::fromEntity($current_user, 'User B');
$cacheability = new CacheableMetadata();
$cacheability->setCacheContexts(['user']);

View file

@ -17,7 +17,8 @@ class TestMultipleFormController extends ControllerBase {
'form2' => $this->formBuilder()->buildForm('\Drupal\block_test\Form\FavoriteAnimalTestForm', $form_state),
];
// Output all attached placeholders trough drupal_set_message(), so we can
// Output all attached placeholders trough
// \Drupal\Core\Messenger\MessengerInterface::addMessage(), so we can
// see if there's only one in the tests.
$post_render_callable = function ($elements) {
$matches = [];
@ -26,7 +27,7 @@ class TestMultipleFormController extends ControllerBase {
$action_values = $matches[2];
foreach ($action_values as $action_value) {
drupal_set_message('Form action: ' . $action_value);
$this->messenger()->addStatus('Form action: ' . $action_value);
}
return $elements;
};

View file

@ -5,6 +5,11 @@ namespace Drupal\block_test\Form;
use Drupal\Core\Form\FormBase;
use Drupal\Core\Form\FormStateInterface;
/**
* Form that performs favorite animal test.
*
* @internal
*/
class FavoriteAnimalTestForm extends FormBase {
/**
@ -20,7 +25,7 @@ class FavoriteAnimalTestForm extends FormBase {
public function buildForm(array $form, FormStateInterface $form_state) {
$form['favorite_animal'] = [
'#type' => 'textfield',
'#title' => $this->t('Your favorite animal.')
'#title' => $this->t('Your favorite animal.'),
];
$form['submit_animal'] = [
@ -35,7 +40,7 @@ class FavoriteAnimalTestForm extends FormBase {
* {@inheritdoc}
*/
public function submitForm(array &$form, FormStateInterface $form_state) {
drupal_set_message($this->t('Your favorite animal is: @favorite_animal', ['@favorite_animal' => $form['favorite_animal']['#value']]));
$this->messenger()->addStatus($this->t('Your favorite animal is: @favorite_animal', ['@favorite_animal' => $form['favorite_animal']['#value']]));
}
}

View file

@ -5,6 +5,11 @@ namespace Drupal\block_test\Form;
use Drupal\Core\Form\FormBase;
use Drupal\Core\Form\FormStateInterface;
/**
* Form that performs base block form test.
*
* @internal
*/
class TestForm extends FormBase {
/**
@ -20,7 +25,7 @@ class TestForm extends FormBase {
public function buildForm(array $form, FormStateInterface $form_state) {
$form['email'] = [
'#type' => 'email',
'#title' => $this->t('Your .com email address.')
'#title' => $this->t('Your .com email address.'),
];
$form['show'] = [
@ -44,7 +49,7 @@ class TestForm extends FormBase {
* {@inheritdoc}
*/
public function submitForm(array &$form, FormStateInterface $form_state) {
drupal_set_message($this->t('Your email address is @email', ['@email' => $form['email']['#value']]));
$this->messenger()->addStatus($this->t('Your email address is @email', ['@email' => $form['email']['#value']]));
}
}

View file

@ -37,7 +37,7 @@ class TestContextAwareBlock extends BlockBase {
*/
protected function blockAccess(AccountInterface $account) {
if ($this->getContextValue('user') instanceof UserInterface) {
drupal_set_message('User context found.');
$this->messenger()->addStatus('User context found.');
}
return parent::blockAccess($account);

View file

@ -5,5 +5,5 @@ package: Testing
version: VERSION
core: 8.x
dependencies:
- block
- views
- drupal:block
- drupal:views

View file

@ -0,0 +1,50 @@
<?php
namespace Drupal\Tests\block\Functional;
use Drupal\block\Entity\Block;
use Drupal\Component\Render\FormattableMarkup;
/**
* Provides test assertions for testing block appearance.
*
* Can be used by test classes that extend \Drupal\Tests\BrowserTestBase.
*/
trait AssertBlockAppearsTrait {
/**
* Checks to see whether a block appears on the page.
*
* @param \Drupal\block\Entity\Block $block
* The block entity to find on the page.
*/
protected function assertBlockAppears(Block $block) {
$result = $this->findBlockInstance($block);
$this->assertTrue(!empty($result), new FormattableMarkup('The block @id appears on the page', ['@id' => $block->id()]));
}
/**
* Checks to see whether a block does not appears on the page.
*
* @param \Drupal\block\Entity\Block $block
* The block entity to find on the page.
*/
protected function assertNoBlockAppears(Block $block) {
$result = $this->findBlockInstance($block);
$this->assertFalse(!empty($result), new FormattableMarkup('The block @id does not appear on the page', ['@id' => $block->id()]));
}
/**
* Find a block instance on the page.
*
* @param \Drupal\block\Entity\Block $block
* The block entity to find on the page.
*
* @return array
* The result from the xpath query.
*/
protected function findBlockInstance(Block $block) {
return $this->xpath('//div[@id = :id]', [':id' => 'block-' . $block->id()]);
}
}

View file

@ -1,15 +1,15 @@
<?php
namespace Drupal\block\Tests;
namespace Drupal\Tests\block\Functional;
use Drupal\simpletest\WebTestBase;
use Drupal\Tests\BrowserTestBase;
/**
* Tests the block system with admin themes.
*
* @group block
*/
class BlockAdminThemeTest extends WebTestBase {
class BlockAdminThemeTest extends BrowserTestBase {
/**
* Modules to install.

View file

@ -0,0 +1,63 @@
<?php
namespace Drupal\Tests\block\Functional;
use Drupal\Tests\BrowserTestBase;
/**
* Tests the block demo page with admin themes.
*
* @group block
*/
class BlockDemoTest extends BrowserTestBase {
/**
* Modules to enable.
*
* @var array
*/
public static $modules = ['block'];
/**
* Check for the accessibility of the admin block demo page.
*/
public function testBlockDemo() {
// Create administrative user.
$admin_user = $this->drupalCreateUser(['administer blocks', 'administer themes']);
$this->drupalLogin($admin_user);
// Confirm we have access to the block demo page for the default theme.
$config = $this->container->get('config.factory')->get('system.theme');
$default_theme = $config->get('default');
$this->drupalGet('admin/structure/block/demo/' . $default_theme);
$this->assertResponse(200);
$this->assertLinkByHref('admin/structure/block');
$this->assertNoLinkByHref('admin/structure/block/list/' . $default_theme);
// All available themes in core.
$available_themes = [
'bartik',
'classy',
'seven',
'stark',
];
// All available themes minute minus the default theme.
$themes = array_diff($available_themes, [$default_theme]);
foreach ($themes as $theme) {
// Install theme.
$this->container->get('theme_handler')->install([$theme]);
// Confirm access to the block demo page for the theme.
$this->drupalGet('admin/structure/block/demo/' . $theme);
$this->assertResponse(200);
// Confirm existence of link for "Exit block region demonstration".
$this->assertLinkByHref('admin/structure/block/list/' . $theme);
}
// Confirm access to the block demo page is denied for an invalid theme.
$this->drupalGet('admin/structure/block/demo/invalid_theme');
$this->assertResponse(403);
}
}

View file

@ -1,17 +1,16 @@
<?php
namespace Drupal\block\Tests;
namespace Drupal\Tests\block\Functional;
use Drupal\Component\Utility\Crypt;
use Drupal\simpletest\WebTestBase;
use Drupal\Tests\BrowserTestBase;
/**
* Tests form in block caching.
*
* @group block
*/
class BlockFormInBlockTest extends WebTestBase {
class BlockFormInBlockTest extends BrowserTestBase {
/**
* Modules to install.

View file

@ -2,7 +2,6 @@
namespace Drupal\Tests\block\Functional;
use Drupal\Component\Utility\Unicode;
use Drupal\Tests\BrowserTestBase;
/**
@ -37,7 +36,7 @@ class BlockHookOperationTest extends BrowserTestBase {
public function testBlockOperationAlter() {
// Add a test block, any block will do.
// Set the machine name so the test_operation link can be built later.
$block_id = Unicode::strtolower($this->randomMachineName(16));
$block_id = mb_strtolower($this->randomMachineName(16));
$this->drupalPlaceBlock('system_powered_by_block', ['id' => $block_id]);
// Get the Block listing.

View file

@ -1,21 +1,21 @@
<?php
namespace Drupal\block\Tests;
namespace Drupal\Tests\block\Functional;
use Drupal\simpletest\WebTestBase;
use Drupal\Tests\BrowserTestBase;
/**
* Tests block module's installation.
*
* @group block
*/
class BlockInstallTest extends WebTestBase {
class BlockInstallTest extends BrowserTestBase {
public function testCacheTagInvalidationUponInstallation() {
// Warm the page cache.
$this->drupalGet('');
$this->assertNoText('Powered by Drupal');
$this->assertNoCacheTag('config:block_list');
$this->assertSession()->responseHeaderNotContains('X-Drupal-Cache-Tags', 'config:block_list');
// Install the block module, and place the "Powered by Drupal" block.
$this->container->get('module_installer')->install(['block', 'shortcut']);

View file

@ -1,17 +1,16 @@
<?php
namespace Drupal\block\Tests;
namespace Drupal\Tests\block\Functional;
use Drupal\Component\Utility\Unicode;
use Drupal\language\Entity\ConfigurableLanguage;
use Drupal\simpletest\WebTestBase;
use Drupal\Tests\BrowserTestBase;
/**
* Tests display of menu blocks with multiple languages.
*
* @group block
*/
class BlockLanguageCacheTest extends WebTestBase {
class BlockLanguageCacheTest extends BrowserTestBase {
/**
* Modules to install.
@ -57,19 +56,19 @@ class BlockLanguageCacheTest extends WebTestBase {
// Create the block cache for all languages.
foreach ($this->langcodes as $langcode) {
$this->drupalGet('admin/structure/block', ['language' => $langcode]);
$this->clickLinkPartialName('Place block');
$this->clickLink('Place block');
}
// Create a menu in the default language.
$edit['label'] = $this->randomMachineName();
$edit['id'] = Unicode::strtolower($edit['label']);
$edit['id'] = mb_strtolower($edit['label']);
$this->drupalPostForm('admin/structure/menu/add', $edit, t('Save'));
$this->assertText(t('Menu @label has been added.', ['@label' => $edit['label']]));
// Check that the block is listed for all languages.
foreach ($this->langcodes as $langcode) {
$this->drupalGet('admin/structure/block', ['language' => $langcode]);
$this->clickLinkPartialName('Place block');
$this->clickLink('Place block');
$this->assertText($edit['label']);
}
}

View file

@ -164,7 +164,7 @@ class BlockLanguageTest extends BrowserTestBase {
// Change visibility to now depend on content language for this block.
$edit = [
'visibility[language][context_mapping][language]' => '@language.current_language_context:language_content'
'visibility[language][context_mapping][language]' => '@language.current_language_context:language_content',
];
$this->drupalPostForm('admin/structure/block/manage/' . $block_id, $edit, t('Save block'));

View file

@ -1,16 +1,16 @@
<?php
namespace Drupal\block\Tests;
namespace Drupal\Tests\block\Functional;
use Drupal\Component\Utility\Html;
use Drupal\simpletest\WebTestBase;
use Drupal\Tests\BrowserTestBase;
/**
* Tests blocks are being rendered in order by weight.
*
* @group block
*/
class BlockRenderOrderTest extends WebTestBase {
class BlockRenderOrderTest extends BrowserTestBase {
/**
* Modules to install.
@ -63,7 +63,7 @@ class BlockRenderOrderTest extends WebTestBase {
}
$this->drupalGet('');
$test_content = $this->getRawContent('');
$test_content = $this->getSession()->getPage()->getContent();
$controller = $this->container->get('entity_type.manager')->getStorage('block');
foreach ($controller->loadMultiple() as $return_block) {

View file

@ -1,6 +1,6 @@
<?php
namespace Drupal\block\Tests;
namespace Drupal\Tests\block\Functional;
/**
* Tests branding block display.
@ -54,7 +54,7 @@ class BlockSystemBrandingTest extends BlockTestBase {
->save();
$this->drupalGet('');
$site_slogan_element = $this->xpath($site_slogan_xpath);
$this->assertEqual($site_slogan_element[0], 'alert("Community carpentry");', 'The site slogan was XSS-filtered.');
$this->assertEqual($site_slogan_element[0]->getText(), 'alert("Community carpentry");', 'The site slogan was XSS-filtered.');
// Turn just the logo off.
$this->config('block.block.site-branding')

View file

@ -1,6 +1,6 @@
<?php
namespace Drupal\block\Tests;
namespace Drupal\Tests\block\Functional;
use Drupal\Component\Utility\Html;
use Drupal\block\Entity\Block;
@ -146,13 +146,13 @@ class BlockTest extends BlockTestBase {
$block_name = 'system_powered_by_block';
$add_url = Url::fromRoute('block.admin_add', [
'plugin_id' => $block_name,
'theme' => $default_theme
'theme' => $default_theme,
]);
$links = $this->xpath('//a[contains(@href, :href)]', [':href' => $add_url->toString()]);
$this->assertEqual(1, count($links), 'Found one matching link.');
$this->assertEqual(t('Place block'), (string) $links[0], 'Found the expected link text.');
$this->assertEqual(t('Place block'), $links[0]->getText(), 'Found the expected link text.');
list($path, $query_string) = explode('?', $links[0]['href'], 2);
list($path, $query_string) = explode('?', $links[0]->getAttribute('href'), 2);
parse_str($query_string, $query_parts);
$this->assertEqual($weight, $query_parts['weight'], 'Found the expected weight query string.');
@ -164,7 +164,7 @@ class BlockTest extends BlockTestBase {
'settings[label]' => $title,
];
// Create the block using the link parsed from the library page.
$this->drupalPostForm($this->getAbsoluteUrl($links[0]['href']), $edit, t('Save block'));
$this->drupalPostForm($this->getAbsoluteUrl($links[0]->getAttribute('href')), $edit, t('Save block'));
// Ensure that the block was created with the expected weight.
/** @var \Drupal\block\BlockInterface $block */
@ -336,7 +336,7 @@ class BlockTest extends BlockTestBase {
$this->drupalPostForm('admin/structure/block', $edit, t('Save blocks'));
// Confirm that the block was moved to the proper region.
$this->assertText(t('The block settings have been updated.'), format_string('Block successfully moved to %region_name region.', [ '%region_name' => $region]));
$this->assertText(t('The block settings have been updated.'), format_string('Block successfully moved to %region_name region.', ['%region_name' => $region]));
// Confirm that the block is being displayed.
$this->drupalGet('');
@ -379,7 +379,7 @@ class BlockTest extends BlockTestBase {
$this->assertEqual($this->drupalGetHeader('X-Drupal-Cache'), 'HIT');
$cid_parts = [\Drupal::url('<front>', [], ['absolute' => TRUE]), 'html'];
$cid = implode(':', $cid_parts);
$cache_entry = \Drupal::cache('render')->get($cid);
$cache_entry = \Drupal::cache('page')->get($cid);
$expected_cache_tags = [
'config:block_list',
'block_view',
@ -420,7 +420,7 @@ class BlockTest extends BlockTestBase {
$this->assertEqual($this->drupalGetHeader('X-Drupal-Cache'), 'HIT');
$cid_parts = [\Drupal::url('<front>', [], ['absolute' => TRUE]), 'html'];
$cid = implode(':', $cid_parts);
$cache_entry = \Drupal::cache('render')->get($cid);
$cache_entry = \Drupal::cache('page')->get($cid);
$expected_cache_tags = [
'config:block_list',
'block_view',
@ -537,14 +537,14 @@ class BlockTest extends BlockTestBase {
$this->assertEqual($block->getVisibility()['user_role']['roles'], [
$role1->id() => $role1->id(),
$role2->id() => $role2->id()
$role2->id() => $role2->id(),
]);
$role1->delete();
$block = Block::load($block->id());
$this->assertEqual($block->getVisibility()['user_role']['roles'], [
$role2->id() => $role2->id()
$role2->id() => $role2->id(),
]);
}

View file

@ -0,0 +1,74 @@
<?php
namespace Drupal\Tests\block\Functional;
use Drupal\filter\Entity\FilterFormat;
use Drupal\Tests\BrowserTestBase;
/**
* Provides setup and helper methods for block module tests.
*/
abstract class BlockTestBase extends BrowserTestBase {
/**
* Modules to install.
*
* @var array
*/
public static $modules = ['block', 'filter', 'test_page_test', 'help', 'block_test'];
/**
* A list of theme regions to test.
*
* @var array
*/
protected $regions;
/**
* A test user with administrative privileges.
*
* @var \Drupal\user\UserInterface
*/
protected $adminUser;
/**
* {@inheritdoc}
*/
protected function setUp() {
parent::setUp();
// Use the test page as the front page.
$this->config('system.site')->set('page.front', '/test-page')->save();
// Create Full HTML text format.
$full_html_format = FilterFormat::create([
'format' => 'full_html',
'name' => 'Full HTML',
]);
$full_html_format->save();
// Create and log in an administrative user having access to the Full HTML
// text format.
$this->adminUser = $this->drupalCreateUser([
'administer blocks',
$full_html_format->getPermissionName(),
'access administration pages',
]);
$this->drupalLogin($this->adminUser);
// Define the existing regions.
$this->regions = [
'header',
'sidebar_first',
'content',
'sidebar_second',
'footer',
];
$block_storage = $this->container->get('entity_type.manager')->getStorage('block');
$blocks = $block_storage->loadByProperties(['theme' => $this->config('system.theme')->get('default')]);
foreach ($blocks as $block) {
$block->delete();
}
}
}

View file

@ -1,16 +1,16 @@
<?php
namespace Drupal\block\Tests;
namespace Drupal\Tests\block\Functional;
use Drupal\Component\Utility\Html;
use Drupal\simpletest\WebTestBase;
use Drupal\Tests\BrowserTestBase;
/**
* Tests that the block configuration UI exists and stores data correctly.
*
* @group block
*/
class BlockUiTest extends WebTestBase {
class BlockUiTest extends BrowserTestBase {
/**
* Modules to install.
@ -105,7 +105,7 @@ class BlockUiTest extends WebTestBase {
$block = $this->blocks[$delta];
$label = $block->label();
$element = $this->xpath('//*[@id="blocks"]/tbody/tr[' . $values['tr'] . ']/td[1]/text()');
$this->assertTrue((string) $element[0] == $label, 'The "' . $label . '" block title is set inside the ' . $values['settings']['region'] . ' region.');
$this->assertEquals($element[0]->getText(), $label, 'The "' . $label . '" block title is set inside the ' . $values['settings']['region'] . ' region.');
// Look for a test block region select form element.
$this->assertField('blocks[' . $values['settings']['id'] . '][region]', 'The block "' . $values['label'] . '" has a region assignment field.');
// Move the test block to the header region.
@ -171,7 +171,7 @@ class BlockUiTest extends WebTestBase {
$pattern = '//tr[.//td/div[text()=:title] and .//td[text()=:category] and .//td//a[contains(@href, :href)]]';
$this->drupalGet('admin/structure/block');
$this->clickLinkPartialName('Place block');
$this->clickLink('Place block');
$elements = $this->xpath($pattern, $arguments);
$this->assertTrue(!empty($elements), 'The test block appears in the category for its module.');
@ -180,7 +180,7 @@ class BlockUiTest extends WebTestBase {
$this->container->get('plugin.manager.block')->clearCachedDefinitions();
$this->drupalGet('admin/structure/block');
$this->clickLinkPartialName('Place block');
$this->clickLink('Place block');
$arguments[':category'] = 'Custom category';
$elements = $this->xpath($pattern, $arguments);
$this->assertTrue(!empty($elements), 'The test block appears in a custom category controlled by block_test_block_alter().');
@ -197,7 +197,7 @@ class BlockUiTest extends WebTestBase {
];
$this->drupalGet('admin/structure/block');
$this->clickLinkPartialName('Place block');
$this->clickLink('Place block');
$elements = $this->xpath('//tr[.//td/div[text()=:text] and .//td[text()=:category] and .//td//a[contains(@href, :href)]]', $arguments);
$this->assertTrue(empty($elements), 'The context-aware test block does not appear.');
@ -223,7 +223,7 @@ class BlockUiTest extends WebTestBase {
$pattern = '//tr[.//td/div[text()=:title] and .//td[text()=:category] and .//td//a[contains(@href, :href)]]';
$this->drupalGet('admin/structure/block');
$this->clickLinkPartialName('Place block');
$this->clickLink('Place block');
$elements = $this->xpath($pattern, $arguments);
$this->assertTrue(!empty($elements), 'The context-aware test block appears.');
$definition = \Drupal::service('plugin.manager.block')->getDefinition('test_context_aware');

View file

@ -1,12 +1,12 @@
<?php
namespace Drupal\block\Tests;
namespace Drupal\Tests\block\Functional;
use Drupal\block_content\Entity\BlockContent;
use Drupal\block_content\Entity\BlockContentType;
use Drupal\Core\Url;
use Drupal\simpletest\WebTestBase;
use Drupal\system\Entity\Menu;
use Drupal\Tests\BrowserTestBase;
use Drupal\views\Entity\View;
/**
@ -14,7 +14,7 @@ use Drupal\views\Entity\View;
*
* @group block
*/
class BlockXssTest extends WebTestBase {
class BlockXssTest extends BrowserTestBase {
/**
* Modules to install.
@ -29,7 +29,7 @@ class BlockXssTest extends WebTestBase {
public function testNoUnexpectedEscaping() {
$this->drupalLogin($this->drupalCreateUser(['administer blocks', 'access administration pages']));
$this->drupalGet(Url::fromRoute('block.admin_display'));
$this->clickLinkPartialName('Place block');
$this->clickLink('Place block');
$this->assertNoEscaped('<');
}
@ -58,7 +58,7 @@ class BlockXssTest extends WebTestBase {
$this->drupalPlaceBlock('test_xss_title');
$this->drupalLogin($this->drupalCreateUser(['administer blocks', 'access administration pages']));
$this->drupalGet(Url::fromRoute('block.admin_display'));
$this->clickLinkPartialName('Place block');
$this->clickLink('Place block');
$this->assertNoRaw("<script>alert('XSS category');</script>");
}
@ -73,7 +73,7 @@ class BlockXssTest extends WebTestBase {
$this->doBlockContentTest();
$this->drupalGet(Url::fromRoute('block.admin_display'));
$this->clickLinkPartialName('Place block');
$this->clickLink('Place block');
$this->assertNoRaw('&amp;lt;', 'The page does not have double escaped HTML tags.');
}
@ -101,7 +101,7 @@ class BlockXssTest extends WebTestBase {
$view->save();
$this->drupalGet(Url::fromRoute('block.admin_display'));
$this->clickLinkPartialName('Place block');
$this->clickLink('Place block');
// \Drupal\views\Plugin\Derivative\ViewsBlock::getDerivativeDefinitions()
// has a different code path for an admin label based only on the View
@ -137,7 +137,7 @@ class BlockXssTest extends WebTestBase {
])->save();
$this->drupalGet(Url::fromRoute('block.admin_display'));
$this->clickLinkPartialName('Place block');
$this->clickLink('Place block');
$this->assertEscaped('<script>alert("menu");</script>');
$this->assertNoRaw('<script>alert("menu");</script>');
@ -158,7 +158,7 @@ class BlockXssTest extends WebTestBase {
])->save();
$this->drupalGet(Url::fromRoute('block.admin_display'));
$this->clickLinkPartialName('Place block');
$this->clickLink('Place block');
$this->assertEscaped('<script>alert("block_content");</script>');
$this->assertNoRaw('<script>alert("block_content");</script>');

View file

@ -0,0 +1,30 @@
<?php
namespace Drupal\Tests\block\Functional\Hal;
use Drupal\Tests\block\Functional\Rest\BlockResourceTestBase;
use Drupal\Tests\rest\Functional\AnonResourceTestTrait;
/**
* @group hal
*/
class BlockHalJsonAnonTest extends BlockResourceTestBase {
use AnonResourceTestTrait;
/**
* {@inheritdoc}
*/
public static $modules = ['hal'];
/**
* {@inheritdoc}
*/
protected static $format = 'hal_json';
/**
* {@inheritdoc}
*/
protected static $mimeType = 'application/hal+json';
}

View file

@ -0,0 +1,35 @@
<?php
namespace Drupal\Tests\block\Functional\Hal;
use Drupal\Tests\block\Functional\Rest\BlockResourceTestBase;
use Drupal\Tests\rest\Functional\BasicAuthResourceTestTrait;
/**
* @group hal
*/
class BlockHalJsonBasicAuthTest extends BlockResourceTestBase {
use BasicAuthResourceTestTrait;
/**
* {@inheritdoc}
*/
public static $modules = ['hal', 'basic_auth'];
/**
* {@inheritdoc}
*/
protected static $format = 'hal_json';
/**
* {@inheritdoc}
*/
protected static $mimeType = 'application/hal+json';
/**
* {@inheritdoc}
*/
protected static $auth = 'basic_auth';
}

View file

@ -0,0 +1,35 @@
<?php
namespace Drupal\Tests\block\Functional\Hal;
use Drupal\Tests\block\Functional\Rest\BlockResourceTestBase;
use Drupal\Tests\rest\Functional\CookieResourceTestTrait;
/**
* @group hal
*/
class BlockHalJsonCookieTest extends BlockResourceTestBase {
use CookieResourceTestTrait;
/**
* {@inheritdoc}
*/
public static $modules = ['hal'];
/**
* {@inheritdoc}
*/
protected static $format = 'hal_json';
/**
* {@inheritdoc}
*/
protected static $mimeType = 'application/hal+json';
/**
* {@inheritdoc}
*/
protected static $auth = 'cookie';
}

View file

@ -1,15 +1,15 @@
<?php
namespace Drupal\block\Tests;
namespace Drupal\Tests\block\Functional;
use Drupal\simpletest\WebTestBase;
use Drupal\Tests\BrowserTestBase;
/**
* Tests the block administration page for a non-default theme.
*
* @group block
*/
class NonDefaultBlockAdminTest extends WebTestBase {
class NonDefaultBlockAdminTest extends BrowserTestBase {
/**
* Modules to install.

View file

@ -0,0 +1,24 @@
<?php
namespace Drupal\Tests\block\Functional\Rest;
use Drupal\Tests\rest\Functional\AnonResourceTestTrait;
/**
* @group rest
*/
class BlockJsonAnonTest extends BlockResourceTestBase {
use AnonResourceTestTrait;
/**
* {@inheritdoc}
*/
protected static $format = 'json';
/**
* {@inheritdoc}
*/
protected static $mimeType = 'application/json';
}

View file

@ -0,0 +1,34 @@
<?php
namespace Drupal\Tests\block\Functional\Rest;
use Drupal\Tests\rest\Functional\BasicAuthResourceTestTrait;
/**
* @group rest
*/
class BlockJsonBasicAuthTest extends BlockResourceTestBase {
use BasicAuthResourceTestTrait;
/**
* {@inheritdoc}
*/
public static $modules = ['basic_auth'];
/**
* {@inheritdoc}
*/
protected static $format = 'json';
/**
* {@inheritdoc}
*/
protected static $mimeType = 'application/json';
/**
* {@inheritdoc}
*/
protected static $auth = 'basic_auth';
}

View file

@ -0,0 +1,29 @@
<?php
namespace Drupal\Tests\block\Functional\Rest;
use Drupal\Tests\rest\Functional\CookieResourceTestTrait;
/**
* @group rest
*/
class BlockJsonCookieTest extends BlockResourceTestBase {
use CookieResourceTestTrait;
/**
* {@inheritdoc}
*/
protected static $format = 'json';
/**
* {@inheritdoc}
*/
protected static $mimeType = 'application/json';
/**
* {@inheritdoc}
*/
protected static $auth = 'cookie';
}

View file

@ -0,0 +1,159 @@
<?php
namespace Drupal\Tests\block\Functional\Rest;
use Drupal\block\Entity\Block;
use Drupal\Tests\rest\Functional\EntityResource\EntityResourceTestBase;
abstract class BlockResourceTestBase extends EntityResourceTestBase {
/**
* {@inheritdoc}
*/
public static $modules = ['block'];
/**
* {@inheritdoc}
*/
protected static $entityTypeId = 'block';
/**
* @var \Drupal\block\BlockInterface
*/
protected $entity;
/**
* {@inheritdoc}
*/
protected function setUpAuthorization($method) {
switch ($method) {
case 'GET':
$this->entity->setVisibilityConfig('user_role', [])->save();
break;
case 'POST':
$this->grantPermissionsToTestedRole(['administer blocks']);
break;
case 'PATCH':
$this->grantPermissionsToTestedRole(['administer blocks']);
break;
}
}
/**
* {@inheritdoc}
*/
protected function createEntity() {
$block = Block::create([
'plugin' => 'llama_block',
'region' => 'header',
'id' => 'llama',
'theme' => 'classy',
]);
// All blocks can be viewed by the anonymous user by default. An interesting
// side effect of this is that any anonymous user is also able to read the
// corresponding block config entity via REST, even if an authentication
// provider is configured for the block config entity REST resource! In
// other words: Block entities do not distinguish between 'view' as in
// "render on a page" and 'view' as in "read the configuration".
// This prevents that.
// @todo Fix this in https://www.drupal.org/node/2820315.
$block->setVisibilityConfig('user_role', [
'id' => 'user_role',
'roles' => ['non-existing-role' => 'non-existing-role'],
'negate' => FALSE,
'context_mapping' => [
'user' => '@user.current_user_context:current_user',
],
]);
$block->save();
return $block;
}
/**
* {@inheritdoc}
*/
protected function getExpectedNormalizedEntity() {
$normalization = [
'uuid' => $this->entity->uuid(),
'id' => 'llama',
'weight' => NULL,
'langcode' => 'en',
'status' => TRUE,
'dependencies' => [
'theme' => [
'classy',
],
],
'theme' => 'classy',
'region' => 'header',
'provider' => NULL,
'plugin' => 'llama_block',
'settings' => [
'id' => 'broken',
'label' => '',
'provider' => 'core',
'label_display' => 'visible',
],
'visibility' => [],
];
return $normalization;
}
/**
* {@inheritdoc}
*/
protected function getNormalizedPostEntity() {
// @todo Update in https://www.drupal.org/node/2300677.
}
/**
* {@inheritdoc}
*/
protected function getExpectedCacheContexts() {
// @see ::createEntity()
return ['url.site'];
}
/**
* {@inheritdoc}
*/
protected function getExpectedCacheTags() {
// Because the 'user.permissions' cache context is missing, the cache tag
// for the anonymous user role is never added automatically.
return array_values(array_diff(parent::getExpectedCacheTags(), ['config:user.role.anonymous']));
}
/**
* {@inheritdoc}
*/
protected function getExpectedUnauthorizedAccessMessage($method) {
if ($this->config('rest.settings')->get('bc_entity_resource_permissions')) {
return parent::getExpectedUnauthorizedAccessMessage($method);
}
switch ($method) {
case 'GET':
return "You are not authorized to view this block entity.";
default:
return parent::getExpectedUnauthorizedAccessMessage($method);
}
}
/**
* {@inheritdoc}
*/
protected function getExpectedUnauthorizedAccessCacheability() {
// @see \Drupal\block\BlockAccessControlHandler::checkAccess()
return parent::getExpectedUnauthorizedAccessCacheability()
->setCacheTags([
'4xx-response',
'config:block.block.llama',
'http_response',
static::$auth ? 'user:2' : 'user:0',
])
->setCacheContexts(['user.roles']);
}
}

View file

@ -0,0 +1,26 @@
<?php
namespace Drupal\Tests\block\Functional\Rest;
use Drupal\Tests\rest\Functional\AnonResourceTestTrait;
use Drupal\Tests\rest\Functional\EntityResource\XmlEntityNormalizationQuirksTrait;
/**
* @group rest
*/
class BlockXmlAnonTest extends BlockResourceTestBase {
use AnonResourceTestTrait;
use XmlEntityNormalizationQuirksTrait;
/**
* {@inheritdoc}
*/
protected static $format = 'xml';
/**
* {@inheritdoc}
*/
protected static $mimeType = 'text/xml; charset=UTF-8';
}

View file

@ -0,0 +1,36 @@
<?php
namespace Drupal\Tests\block\Functional\Rest;
use Drupal\Tests\rest\Functional\BasicAuthResourceTestTrait;
use Drupal\Tests\rest\Functional\EntityResource\XmlEntityNormalizationQuirksTrait;
/**
* @group rest
*/
class BlockXmlBasicAuthTest extends BlockResourceTestBase {
use BasicAuthResourceTestTrait;
use XmlEntityNormalizationQuirksTrait;
/**
* {@inheritdoc}
*/
public static $modules = ['basic_auth'];
/**
* {@inheritdoc}
*/
protected static $format = 'xml';
/**
* {@inheritdoc}
*/
protected static $mimeType = 'text/xml; charset=UTF-8';
/**
* {@inheritdoc}
*/
protected static $auth = 'basic_auth';
}

View file

@ -0,0 +1,31 @@
<?php
namespace Drupal\Tests\block\Functional\Rest;
use Drupal\Tests\rest\Functional\CookieResourceTestTrait;
use Drupal\Tests\rest\Functional\EntityResource\XmlEntityNormalizationQuirksTrait;
/**
* @group rest
*/
class BlockXmlCookieTest extends BlockResourceTestBase {
use CookieResourceTestTrait;
use XmlEntityNormalizationQuirksTrait;
/**
* {@inheritdoc}
*/
protected static $format = 'xml';
/**
* {@inheritdoc}
*/
protected static $mimeType = 'text/xml; charset=UTF-8';
/**
* {@inheritdoc}
*/
protected static $auth = 'cookie';
}

View file

@ -1,8 +1,8 @@
<?php
namespace Drupal\block\Tests\Update;
namespace Drupal\Tests\block\Functional\Update;
use Drupal\system\Tests\Update\UpdatePathTestBase;
use Drupal\FunctionalTests\Update\UpdatePathTestBase;
/**
* Tests the upgrade path for block with conditions missing context.
@ -10,6 +10,7 @@ use Drupal\system\Tests\Update\UpdatePathTestBase;
* @see https://www.drupal.org/node/2811519
*
* @group Update
* @group legacy
*/
class BlockConditionMissingSchemaUpdateTest extends UpdatePathTestBase {
@ -34,8 +35,8 @@ class BlockConditionMissingSchemaUpdateTest extends UpdatePathTestBase {
*/
protected function setDatabaseDumpFiles() {
$this->databaseDumpFiles = [
__DIR__ . '/../../../../system/tests/fixtures/update/drupal-8.bare.standard.php.gz',
__DIR__ . '/../../../tests/fixtures/update/drupal-8.block-test-enabled-missing-schema.php',
__DIR__ . '/../../../../../system/tests/fixtures/update/drupal-8.bare.standard.php.gz',
__DIR__ . '/../../../fixtures/update/drupal-8.block-test-enabled-missing-schema.php',
];
}

View file

@ -1,11 +1,12 @@
<?php
namespace Drupal\block\Tests\Update;
namespace Drupal\Tests\block\Functional\Update;
/**
* Runs BlockContextMappingUpdateTest with a dump filled with content.
*
* @group Update
* @group legacy
*/
class BlockContextMappingUpdateFilledTest extends BlockContextMappingUpdateTest {
@ -14,7 +15,7 @@ class BlockContextMappingUpdateFilledTest extends BlockContextMappingUpdateTest
*/
protected function setDatabaseDumpFiles() {
parent::setDatabaseDumpFiles();
$this->databaseDumpFiles[0] = __DIR__ . '/../../../../system/tests/fixtures/update/drupal-8.filled.standard.php.gz';
$this->databaseDumpFiles[0] = __DIR__ . '/../../../../../system/tests/fixtures/update/drupal-8.filled.standard.php.gz';
}
}

View file

@ -1,10 +1,10 @@
<?php
namespace Drupal\block\Tests\Update;
namespace Drupal\Tests\block\Functional\Update;
use Drupal\block\Entity\Block;
use Drupal\FunctionalTests\Update\UpdatePathTestBase;
use Drupal\node\Entity\Node;
use Drupal\system\Tests\Update\UpdatePathTestBase;
/**
* Tests the upgrade path for block context mapping renames.
@ -12,6 +12,7 @@ use Drupal\system\Tests\Update\UpdatePathTestBase;
* @see https://www.drupal.org/node/2354889
*
* @group Update
* @group legacy
*/
class BlockContextMappingUpdateTest extends UpdatePathTestBase {
@ -25,10 +26,10 @@ class BlockContextMappingUpdateTest extends UpdatePathTestBase {
*/
protected function setDatabaseDumpFiles() {
$this->databaseDumpFiles = [
__DIR__ . '/../../../../system/tests/fixtures/update/drupal-8.bare.standard.php.gz',
__DIR__ . '/../../../../system/tests/fixtures/update/drupal-8.block-context-manager-2354889.php',
__DIR__ . '/../../../../system/tests/fixtures/update/drupal-8.language-enabled.php',
__DIR__ . '/../../../../system/tests/fixtures/update/drupal-8.block-test-enabled.php',
__DIR__ . '/../../../../../system/tests/fixtures/update/drupal-8.bare.standard.php.gz',
__DIR__ . '/../../../../../system/tests/fixtures/update/drupal-8.block-context-manager-2354889.php',
__DIR__ . '/../../../../../system/tests/fixtures/update/drupal-8.language-enabled.php',
__DIR__ . '/../../../../../system/tests/fixtures/update/drupal-8.block-test-enabled.php',
];
}

View file

@ -1,8 +1,8 @@
<?php
namespace Drupal\block\Tests\Update;
namespace Drupal\Tests\block\Functional\Update;
use Drupal\system\Tests\Update\UpdatePathTestBase;
use Drupal\FunctionalTests\Update\UpdatePathTestBase;
/**
* Tests the upgrade path for removal of disabled region.
@ -10,6 +10,7 @@ use Drupal\system\Tests\Update\UpdatePathTestBase;
* @see https://www.drupal.org/node/2513534
*
* @group Update
* @group legacy
*/
class BlockRemoveDisabledRegionUpdateTest extends UpdatePathTestBase {
@ -23,8 +24,8 @@ class BlockRemoveDisabledRegionUpdateTest extends UpdatePathTestBase {
*/
protected function setDatabaseDumpFiles() {
$this->databaseDumpFiles = [
__DIR__ . '/../../../../system/tests/fixtures/update/drupal-8.bare.standard.php.gz',
__DIR__ . '/../../../../system/tests/fixtures/update/drupal-8.update-test-block-disabled-2513534.php',
__DIR__ . '/../../../../../system/tests/fixtures/update/drupal-8.bare.standard.php.gz',
__DIR__ . '/../../../../../system/tests/fixtures/update/drupal-8.update-test-block-disabled-2513534.php',
];
}

View file

@ -1,13 +1,16 @@
<?php
namespace Drupal\block\Tests\Views;
namespace Drupal\Tests\block\Functional\Views;
use Drupal\Component\Serialization\Json;
use Drupal\Component\Utility\Crypt;
use Drupal\Core\Site\Settings;
use Drupal\Core\Url;
use Drupal\system\Tests\Cache\AssertPageCacheContextsAndTagsTrait;
use Drupal\Tests\block\Functional\AssertBlockAppearsTrait;
use Drupal\Tests\system\Functional\Cache\AssertPageCacheContextsAndTagsTrait;
use Drupal\Tests\views\Functional\ViewTestBase;
use Drupal\views\Entity\View;
use Drupal\views\Views;
use Drupal\views\Tests\ViewTestBase;
use Drupal\views\Tests\ViewTestData;
use Drupal\Core\Template\Attribute;
@ -15,11 +18,12 @@ use Drupal\Core\Template\Attribute;
* Tests the block display plugin.
*
* @group block
* @see \Drupal\block\Plugin\views\display\Block
* @see \Drupal\views\Plugin\views\display\Block
*/
class DisplayBlockTest extends ViewTestBase {
use AssertPageCacheContextsAndTagsTrait;
use AssertBlockAppearsTrait;
/**
* Modules to install.
@ -35,8 +39,11 @@ class DisplayBlockTest extends ViewTestBase {
*/
public static $testViews = ['test_view_block', 'test_view_block2'];
protected function setUp() {
parent::setUp();
/**
* {@inheritdoc}
*/
protected function setUp($import_test_views = TRUE) {
parent::setUp($import_test_views);
ViewTestData::createTestViews(get_class($this), ['block_test_views']);
$this->enableViewsTestModule();
@ -67,10 +74,10 @@ class DisplayBlockTest extends ViewTestBase {
'plugin_id' => 'views_block:' . $edit['id'] . '-block_1',
'theme' => 'classy',
]),
':category' => t('Lists (Views)'),
':category' => 'Lists (Views)',
];
$this->drupalGet('admin/structure/block');
$this->clickLinkPartialName('Place block');
$this->clickLink('Place block');
$elements = $this->xpath($pattern, $arguments);
$this->assertTrue(!empty($elements), 'The test block appears in the category for its base table.');
@ -95,7 +102,7 @@ class DisplayBlockTest extends ViewTestBase {
// Test that the blocks are listed under the correct categories.
$arguments[':category'] = $category;
$this->drupalGet('admin/structure/block');
$this->clickLinkPartialName('Place block');
$this->clickLink('Place block');
$elements = $this->xpath($pattern, $arguments);
$this->assertTrue(!empty($elements), 'The test block appears in the custom category.');
@ -104,7 +111,7 @@ class DisplayBlockTest extends ViewTestBase {
'plugin_id' => 'views_block:' . $edit['id'] . '-block_2',
'theme' => 'classy',
]),
':category' => t('Lists (Views)'),
':category' => 'Lists (Views)',
];
$elements = $this->xpath($pattern, $arguments);
$this->assertTrue(!empty($elements), 'The first duplicated test block remains in the original category.');
@ -243,7 +250,7 @@ class DisplayBlockTest extends ViewTestBase {
$this->drupalGet('');
$result = $this->xpath('//div[contains(@class, "region-sidebar-first")]/div[contains(@class, "block-views")]/h2');
$this->assertEqual((string) $result[0], 'Custom title');
$this->assertEqual($result[0]->getText(), 'Custom title');
// Don't override the title anymore.
$plugin = $block->getPlugin();
@ -252,7 +259,7 @@ class DisplayBlockTest extends ViewTestBase {
$this->drupalGet('');
$result = $this->xpath('//div[contains(@class, "region-sidebar-first")]/div[contains(@class, "block-views")]/h2');
$this->assertEqual((string) $result[0], 'test_view_block');
$this->assertEqual($result[0]->getText(), 'test_view_block');
// Hide the title.
$block->getPlugin()->setConfigurationValue('label_display', FALSE);
@ -262,7 +269,7 @@ class DisplayBlockTest extends ViewTestBase {
$result = $this->xpath('//div[contains(@class, "region-sidebar-first")]/div[contains(@class, "block-views")]/h2');
$this->assertTrue(empty($result), 'The title is not visible.');
$this->assertCacheTags(array_merge($block->getCacheTags(), ['block_view', 'config:block_list', 'config:system.site', 'config:views.view.test_view_block' , 'http_response', 'rendered']));
$this->assertCacheTags(array_merge($block->getCacheTags(), ['block_view', 'config:block_list', 'config:system.site', 'config:views.view.test_view_block', 'http_response', 'rendered']));
}
/**
@ -286,9 +293,9 @@ class DisplayBlockTest extends ViewTestBase {
$this->drupalGet($url);
$this->assertEqual(0, count($this->xpath('//div[contains(@class, "block-views-blocktest-view-block-block-1")]')));
// Ensure that the view cachability metadata is propagated even, for an
// Ensure that the view cacheability metadata is propagated even, for an
// empty block.
$this->assertCacheTags(array_merge($block->getCacheTags(), ['block_view', 'config:block_list', 'config:views.view.test_view_block' , 'http_response', 'rendered']));
$this->assertCacheTags(array_merge($block->getCacheTags(), ['block_view', 'config:block_list', 'config:views.view.test_view_block', 'http_response', 'rendered']));
$this->assertCacheContexts(['url.query_args:_wrapper_format']);
// Add a header displayed on empty result.
@ -306,7 +313,7 @@ class DisplayBlockTest extends ViewTestBase {
$this->drupalGet($url);
$this->assertEqual(1, count($this->xpath('//div[contains(@class, "block-views-blocktest-view-block-block-1")]')));
$this->assertCacheTags(array_merge($block->getCacheTags(), ['block_view', 'config:block_list', 'config:views.view.test_view_block' , 'http_response', 'rendered']));
$this->assertCacheTags(array_merge($block->getCacheTags(), ['block_view', 'config:block_list', 'config:views.view.test_view_block', 'http_response', 'rendered']));
$this->assertCacheContexts(['url.query_args:_wrapper_format']);
// Hide the header on empty results.
@ -355,17 +362,20 @@ class DisplayBlockTest extends ViewTestBase {
$this->drupalGet('test-page');
$id = 'block:block=' . $block->id() . ':langcode=en|entity.view.edit_form:view=test_view_block:location=block&name=test_view_block&display_id=block_1&langcode=en';
$id_token = Crypt::hmacBase64($id, Settings::getHashSalt() . $this->container->get('private_key')->get());
$cached_id = 'block:block=' . $cached_block->id() . ':langcode=en|entity.view.edit_form:view=test_view_block:location=block&name=test_view_block&display_id=block_1&langcode=en';
$cached_id_token = Crypt::hmacBase64($cached_id, Settings::getHashSalt() . $this->container->get('private_key')->get());
// @see \Drupal\contextual\Tests\ContextualDynamicContextTest:assertContextualLinkPlaceHolder()
$this->assertRaw('<div' . new Attribute(['data-contextual-id' => $id]) . '></div>', format_string('Contextual link placeholder with id @id exists.', ['@id' => $id]));
$this->assertRaw('<div' . new Attribute(['data-contextual-id' => $cached_id]) . '></div>', format_string('Contextual link placeholder with id @id exists.', ['@id' => $cached_id]));
$this->assertRaw('<div' . new Attribute(['data-contextual-id' => $id, 'data-contextual-token' => $id_token]) . '></div>', format_string('Contextual link placeholder with id @id exists.', ['@id' => $id]));
$this->assertRaw('<div' . new Attribute(['data-contextual-id' => $cached_id, 'data-contextual-token' => $cached_id_token]) . '></div>', format_string('Contextual link placeholder with id @id exists.', ['@id' => $cached_id]));
// Get server-rendered contextual links.
// @see \Drupal\contextual\Tests\ContextualDynamicContextTest:renderContextualLinks()
$post = ['ids[0]' => $id, 'ids[1]' => $cached_id];
$response = $this->drupalPostWithFormat('contextual/render', 'json', $post, ['query' => ['destination' => 'test-page']]);
$post = ['ids[0]' => $id, 'ids[1]' => $cached_id, 'tokens[0]' => $id_token, 'tokens[1]' => $cached_id_token];
$url = 'contextual/render?_format=json,destination=test-page';
$this->getSession()->getDriver()->getClient()->request('POST', $url, $post);
$this->assertResponse(200);
$json = Json::decode($response);
$json = Json::decode($this->getSession()->getPage()->getContent());
$this->assertIdentical($json[$id], '<ul class="contextual-links"><li class="block-configure"><a href="' . base_path() . 'admin/structure/block/manage/' . $block->id() . '">Configure block</a></li><li class="entityviewedit-form"><a href="' . base_path() . 'admin/structure/views/view/test_view_block/edit/block_1">Edit view</a></li></ul>');
$this->assertIdentical($json[$cached_id], '<ul class="contextual-links"><li class="block-configure"><a href="' . base_path() . 'admin/structure/block/manage/' . $cached_block->id() . '">Configure block</a></li><li class="entityviewedit-form"><a href="' . base_path() . 'admin/structure/views/view/test_view_block/edit/block_1">Edit view</a></li></ul>');
}

View file

@ -0,0 +1,93 @@
<?php
namespace Drupal\Tests\block\FunctionalJavascript;
use Behat\Mink\Element\NodeElement;
use Drupal\FunctionalJavascriptTests\WebDriverTestBase;
/**
* Tests the JavaScript functionality of the block add filter.
*
* @group block
*/
class BlockFilterTest extends WebDriverTestBase {
/**
* {@inheritdoc}
*/
public static $modules = ['user', 'block'];
/**
* {@inheritdoc}
*/
protected function setUp() {
parent::setUp();
$admin_user = $this->drupalCreateUser([
'administer blocks',
]);
$this->drupalLogin($admin_user);
}
/**
* Tests block filter.
*/
public function testBlockFilter() {
$this->drupalGet('admin/structure/block');
$assertSession = $this->assertSession();
$session = $this->getSession();
$page = $session->getPage();
// Find the block filter field on the add-block dialog.
$page->find('css', '#edit-blocks-region-header-title')->click();
$filter = $assertSession->waitForElement('css', '.block-filter-text');
// Get all block rows, for assertions later.
$block_rows = $page->findAll('css', '.block-add-table tbody tr');
// Test block filter reduces the number of visible rows.
$filter->setValue('ad');
$session->wait(10000, 'jQuery("#drupal-live-announce").html().indexOf("blocks are available") > -1');
$visible_rows = $this->filterVisibleElements($block_rows);
if (count($block_rows) > 0) {
$this->assertNotEquals(count($block_rows), count($visible_rows));
}
// Test Drupal.announce() message when multiple matches are expected.
$expected_message = count($visible_rows) . ' blocks are available in the modified list.';
$assertSession->elementTextContains('css', '#drupal-live-announce', $expected_message);
// Test Drupal.announce() message when only one match is expected.
$filter->setValue('Powered by');
$session->wait(10000, 'jQuery("#drupal-live-announce").html().indexOf("block is available") > -1');
$visible_rows = $this->filterVisibleElements($block_rows);
$this->assertEquals(1, count($visible_rows));
$expected_message = '1 block is available in the modified list.';
$assertSession->elementTextContains('css', '#drupal-live-announce', $expected_message);
// Test Drupal.announce() message when no matches are expected.
$filter->setValue('Pan-Galactic Gargle Blaster');
$session->wait(10000, 'jQuery("#drupal-live-announce").html().indexOf("0 blocks are available") > -1');
$visible_rows = $this->filterVisibleElements($block_rows);
$this->assertEquals(0, count($visible_rows));
$expected_message = '0 blocks are available in the modified list.';
$assertSession->elementTextContains('css', '#drupal-live-announce', $expected_message);
}
/**
* Removes any non-visible elements from the passed array.
*
* @param \Behat\Mink\Element\NodeElement[] $elements
* An array of node elements.
*
* @return \Behat\Mink\Element\NodeElement[]
*/
protected function filterVisibleElements(array $elements) {
$elements = array_filter($elements, function (NodeElement $element) {
return $element->isVisible();
});
return $elements;
}
}

View file

@ -47,7 +47,8 @@ class BlockRebuildTest extends KernelTestBase {
*/
public function testRebuildNoBlocks() {
block_rebuild();
$messages = drupal_get_messages();
$messages = \Drupal::messenger()->all();
\Drupal::messenger()->deleteAll();
$this->assertEquals([], $messages);
}
@ -58,7 +59,8 @@ class BlockRebuildTest extends KernelTestBase {
$this->placeBlock('system_powered_by_block', ['region' => 'content']);
block_rebuild();
$messages = drupal_get_messages();
$messages = \Drupal::messenger()->all();
\Drupal::messenger()->deleteAll();
$this->assertEquals([], $messages);
}
@ -89,7 +91,8 @@ class BlockRebuildTest extends KernelTestBase {
$block1 = Block::load($block1->id());
$block2 = Block::load($block2->id());
$messages = drupal_get_messages();
$messages = \Drupal::messenger()->all();
\Drupal::messenger()->deleteAll();
$expected = ['warning' => [new TranslatableMarkup('The block %info was assigned to the invalid region %region and has been disabled.', ['%info' => $block1->id(), '%region' => 'INVALID'])]];
$this->assertEquals($expected, $messages);

View file

@ -26,7 +26,7 @@ class BlockStorageUnitTest extends KernelTestBase {
/**
* The block storage.
*
* @var \Drupal\Core\Config\Entity\ConfigEntityStorageInterface.
* @var \Drupal\Core\Config\Entity\ConfigEntityStorageInterface
*/
protected $controller;

View file

@ -0,0 +1,65 @@
<?php
namespace Drupal\Tests\block\Kernel\Migrate\d6;
use Drupal\Tests\migrate_drupal\Kernel\d6\MigrateDrupal6TestBase;
/**
* Tests migration of i18n block translations.
*
* @group migrate_drupal_6
*/
class MigrateBlockContentTranslationTest extends MigrateDrupal6TestBase {
/**
* {@inheritdoc}
*/
public static $modules = [
'aggregator',
'book',
'block',
'comment',
'forum',
'views',
'block_content',
'content_translation',
'language',
'statistics',
'taxonomy',
// Required for translation migrations.
'migrate_drupal_multilingual',
];
/**
* {@inheritdoc}
*/
protected function setUp() {
parent::setUp();
$this->installConfig(['block']);
$this->installConfig(['block_content']);
$this->installEntitySchema('block_content');
$this->executeMigrations([
'd6_filter_format',
'block_content_type',
'block_content_body_field',
'd6_custom_block',
'd6_user_role',
'd6_block',
'd6_block_translation',
]);
block_rebuild();
}
/**
* Tests the migration of block title translation.
*/
public function testBlockContentTranslation() {
/** @var \Drupal\language\ConfigurableLanguageManagerInterface $language_manager */
$language_manager = $this->container->get('language_manager');
$config = $language_manager->getLanguageConfigOverride('zu', 'block.block.user_1');
$this->assertSame('zu - Navigation', $config->get('settings.label'));
}
}

View file

@ -116,9 +116,9 @@ class MigrateBlockTest extends MigrateDrupal6TestBase {
$visibility = [];
$settings = [
'id' => 'system_menu_block',
'label' => '',
'label' => 'zu - Navigation',
'provider' => 'system',
'label_display' => '0',
'label_display' => 'visible',
'level' => 1,
'depth' => 0,
];

View file

@ -87,7 +87,7 @@ class BlockTest extends MigrateSqlSourceTestBase {
'schema_version' => '6055',
'weight' => '0',
'info' => 'a:0:{}',
]
],
];
// The expected results.
@ -104,7 +104,7 @@ class BlockTest extends MigrateSqlSourceTestBase {
'pages' => '',
'title' => 'Test Title 01',
'cache' => -1,
'roles' => [2]
'roles' => [2],
],
[
'bid' => 2,
@ -118,7 +118,7 @@ class BlockTest extends MigrateSqlSourceTestBase {
'pages' => '<front>',
'title' => 'Test Title 02',
'cache' => -1,
'roles' => [2]
'roles' => [2],
],
];
return $tests;

View file

@ -0,0 +1,79 @@
<?php
namespace Drupal\Tests\block\Kernel\Plugin\migrate\source\d6;
use Drupal\Tests\block\Kernel\Plugin\migrate\source\BlockTest;
/**
* Tests i18n block source plugin.
*
* @covers \Drupal\block\Plugin\migrate\source\d6\BlockTranslation
*
* @group content_translation
*/
class BlockTranslationTest extends BlockTest {
/**
* {@inheritdoc}
*/
public static $modules = ['block'];
/**
* {@inheritdoc}
*/
public function providerSource() {
// Test data is the same as BlockTest, but with the addition of i18n_blocks.
$tests = parent::providerSource();
// The source data.
$tests[0]['source_data']['i18n_blocks'] = [
[
'ibid' => 1,
'module' => 'block',
'delta' => '1',
'type' => 0,
'language' => 'fr',
],
[
'ibid' => 2,
'module' => 'block',
'delta' => '2',
'type' => 0,
'language' => 'zu',
],
];
$tests[0]['source_data']['variables'] = [
[
'name' => 'default_theme',
'value' => 's:7:"garland";',
],
];
// The expected results.
$tests[0]['expected_data'] = [
[
'bid' => 1,
'module' => 'block',
'delta' => '1',
'title' => 'Test Title 01',
'ibid' => 1,
'type' => '0',
'language' => 'fr',
'default_theme' => 'Garland',
],
[
'bid' => 2,
'module' => 'block',
'delta' => '2',
'theme' => 'garland',
'title' => 'Test Title 02',
'ibid' => 2,
'type' => '0',
'language' => 'zu',
'default_theme' => 'Garland',
],
];
return $tests;
}
}

View file

@ -0,0 +1,67 @@
<?php
namespace Drupal\Tests\block\Traits;
use Drupal\block\Entity\Block;
/**
* Provides methods to create and place block with default settings.
*
* This trait is meant to be used only by test classes.
*/
trait BlockCreationTrait {
/**
* Creates a block instance based on default settings.
*
* @param string $plugin_id
* The plugin ID of the block type for this block instance.
* @param array $settings
* (optional) An associative array of settings for the block entity.
* Override the defaults by specifying the key and value in the array, for
* example:
* @code
* $this->drupalPlaceBlock('system_powered_by_block', array(
* 'label' => t('Hello, world!'),
* ));
* @endcode
* The following defaults are provided:
* - label: Random string.
* - ID: Random string.
* - region: 'sidebar_first'.
* - theme: The default theme.
* - visibility: Empty array.
*
* @return \Drupal\block\Entity\Block
* The block entity.
*
* @todo
* Add support for creating custom block instances.
*/
protected function placeBlock($plugin_id, array $settings = []) {
$config = \Drupal::configFactory();
$settings += [
'plugin' => $plugin_id,
'region' => 'sidebar_first',
'id' => strtolower($this->randomMachineName(8)),
'theme' => $config->get('system.theme')->get('default'),
'label' => $this->randomMachineName(8),
'visibility' => [],
'weight' => 0,
];
$values = [];
foreach (['region', 'id', 'theme', 'plugin', 'weight', 'visibility'] as $key) {
$values[$key] = $settings[$key];
// Remove extra values that do not belong in the settings array.
unset($settings[$key]);
}
foreach ($values['visibility'] as $id => $visibility) {
$values['visibility'][$id]['id'] = $id;
}
$values['settings'] = $settings;
$block = Block::create($values);
$block->save();
return $block;
}
}

View file

@ -3,6 +3,7 @@
namespace Drupal\Tests\block\Unit;
use Drupal\Core\DependencyInjection\ContainerBuilder;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Tests\Core\Plugin\Fixtures\TestConfigurablePlugin;
use Drupal\Tests\UnitTestCase;
@ -20,11 +21,11 @@ class BlockConfigEntityUnitTest extends UnitTestCase {
protected $entityType;
/**
* The entity manager used for testing.
* The entity type manager used for testing.
*
* @var \Drupal\Core\Entity\EntityManagerInterface|\PHPUnit_Framework_MockObject_MockObject
* @var \Drupal\Core\Entity\EntityTypeManagerInterface|\PHPUnit_Framework_MockObject_MockObject
*/
protected $entityManager;
protected $entityTypeManager;
/**
* The ID of the type of the entity under test.
@ -51,8 +52,8 @@ class BlockConfigEntityUnitTest extends UnitTestCase {
->method('getProvider')
->will($this->returnValue('block'));
$this->entityManager = $this->getMock('\Drupal\Core\Entity\EntityManagerInterface');
$this->entityManager->expects($this->any())
$this->entityTypeManager = $this->getMock(EntityTypeManagerInterface::class);
$this->entityTypeManager->expects($this->any())
->method('getDefinition')
->with($this->entityTypeId)
->will($this->returnValue($this->entityType));
@ -60,7 +61,7 @@ class BlockConfigEntityUnitTest extends UnitTestCase {
$this->uuid = $this->getMock('\Drupal\Component\Uuid\UuidInterface');
$container = new ContainerBuilder();
$container->set('entity.manager', $this->entityManager);
$container->set('entity_type.manager', $this->entityTypeManager);
$container->set('uuid', $this->uuid);
\Drupal::setContainer($container);
}

View file

@ -3,6 +3,8 @@
namespace Drupal\Tests\block\Unit;
use Drupal\block\BlockForm;
use Drupal\block\Entity\Block;
use Drupal\Core\Block\BlockBase;
use Drupal\Core\Plugin\PluginFormFactoryInterface;
use Drupal\Tests\UnitTestCase;
@ -82,6 +84,32 @@ class BlockFormTest extends UnitTestCase {
$this->pluginFormFactory = $this->prophesize(PluginFormFactoryInterface::class);
}
/**
* Mocks a block with a block plugin.
*
* @param string $machine_name
* The machine name of the block plugin.
*
* @return \Drupal\block\BlockInterface|\PHPUnit_Framework_MockObject_MockObject
* The mocked block.
*/
protected function getBlockMockWithMachineName($machine_name) {
$plugin = $this->getMockBuilder(BlockBase::class)
->disableOriginalConstructor()
->getMock();
$plugin->expects($this->any())
->method('getMachineNameSuggestion')
->will($this->returnValue($machine_name));
$block = $this->getMockBuilder(Block::class)
->disableOriginalConstructor()
->getMock();
$block->expects($this->any())
->method('getPlugin')
->will($this->returnValue($plugin));
return $block;
}
/**
* Tests the unique machine name generator.
*

View file

@ -118,21 +118,21 @@ class BlockRepositoryTest extends UnitTestCase {
public function providerBlocksConfig() {
$blocks_config = [
'block1' => [
AccessResult::allowed(), 'top', 0
AccessResult::allowed(), 'top', 0,
],
// Test a block without access.
'block2' => [
AccessResult::forbidden(), 'bottom', 0
AccessResult::forbidden(), 'bottom', 0,
],
// Test some blocks in the same region with specific weight.
'block4' => [
AccessResult::allowed(), 'bottom', 5
AccessResult::allowed(), 'bottom', 5,
],
'block3' => [
AccessResult::allowed(), 'bottom', 5
AccessResult::allowed(), 'bottom', 5,
],
'block5' => [
AccessResult::allowed(), 'bottom', -5
AccessResult::allowed(), 'bottom', -5,
],
];
@ -142,7 +142,7 @@ class BlockRepositoryTest extends UnitTestCase {
'top' => ['block1'],
'center' => [],
'bottom' => ['block5', 'block3', 'block4'],
]
],
];
return $test_cases;
}

View file

@ -16,9 +16,9 @@ class BlockLocalTasksTest extends LocalTaskIntegrationTestBase {
$this->directoryList = ['block' => 'core/modules/block'];
parent::setUp();
$config_factory = $this->getConfigFactoryStub(['system.theme' => [
'default' => 'test_c',
]]);
$config_factory = $this->getConfigFactoryStub([
'system.theme' => ['default' => 'test_c'],
]);
$themes = [];
$themes['test_a'] = (object) [

View file

@ -49,6 +49,7 @@ class BlockPageVariantTest extends UnitTestCase {
$container = new Container();
$cache_context_manager = $this->getMockBuilder('Drupal\Core\Cache\CacheContextsManager')
->disableOriginalConstructor()
->setMethods(['assertValidTokens'])
->getMock();
$container->set('cache_contexts_manager', $cache_context_manager);
$cache_context_manager->expects($this->any())
@ -209,9 +210,6 @@ class BlockPageVariantTest extends UnitTestCase {
$title_block_plugin = $this->getMock('Drupal\Core\Block\TitleBlockPluginInterface');
foreach ($blocks_config as $block_id => $block_config) {
$block = $this->getMock('Drupal\block\BlockInterface');
$block->expects($this->any())
->method('getContexts')
->willReturn([]);
$block->expects($this->atLeastOnce())
->method('getPlugin')
->willReturn($block_config[1] ? $main_content_block_plugin : ($block_config[2] ? $messages_block_plugin : ($block_config[3] ? $title_block_plugin : $block_plugin)));

View file

@ -4,6 +4,7 @@ namespace Drupal\Tests\block\Unit\Plugin\migrate\process;
use Drupal\block\Plugin\migrate\process\BlockVisibility;
use Drupal\Core\Extension\ModuleHandlerInterface;
use Drupal\migrate\MigrateSkipRowException;
use Drupal\migrate\Plugin\MigrateProcessInterface;
use Drupal\Tests\migrate\Unit\process\MigrateProcessTestCase;
@ -80,4 +81,22 @@ class BlockVisibilityTest extends MigrateProcessTestCase {
$this->assertEmpty($transformed_value);
}
/**
* @covers ::transform
*/
public function testTransformException() {
$this->moduleHandler->moduleExists('php')->willReturn(FALSE);
$migration_plugin = $this->prophesize(MigrateProcessInterface::class);
$this->row = $this->getMockBuilder('Drupal\migrate\Row')
->disableOriginalConstructor()
->setMethods(['getSourceProperty'])
->getMock();
$this->row->expects($this->exactly(2))
->method('getSourceProperty')
->willReturnMap([['bid', 99], ['module', 'foobar']]);
$this->plugin = new BlockVisibility(['skip_php' => TRUE], 'block_visibility_pages', [], $this->moduleHandler->reveal(), $migration_plugin->reveal());
$this->setExpectedException(MigrateSkipRowException::class, "The block with bid '99' from module 'foobar' will have no PHP or request_path visibility configuration.");
$this->plugin->transform([2, '<?php', []], $this->migrateExecutable, $this->row, 'destinationproperty');
}
}