Update to Drupal 8.0.0-beta15. For more information, see: https://www.drupal.org/node/2563023
This commit is contained in:
parent
2720a9ec4b
commit
f3791f1da3
1898 changed files with 54300 additions and 11481 deletions
|
@ -126,6 +126,61 @@ function hook_block_view_BASE_BLOCK_ID_alter(array &$build, \Drupal\Core\Block\B
|
|||
$build['#title'] = t('New title of the block');
|
||||
}
|
||||
|
||||
/**
|
||||
* Alter the result of \Drupal\Core\Block\BlockBase::build().
|
||||
*
|
||||
* Unlike hook_block_view_alter(), this hook is called very early, before the
|
||||
* block is being assembled. Therefore, it is early enough to alter the
|
||||
* cacheability metadata (change #cache), or to explicitly placeholder the block
|
||||
* (set #create_placeholder).
|
||||
*
|
||||
* In addition to hook_block_build_alter(), which is called for all blocks,
|
||||
* there is hook_block_build_BASE_BLOCK_ID_alter(), which can be used to target
|
||||
* a specific block or set of similar blocks.
|
||||
*
|
||||
* @param array &$build
|
||||
* A renderable array of data, only containing #cache.
|
||||
* @param \Drupal\Core\Block\BlockPluginInterface $block
|
||||
* The block plugin instance.
|
||||
*
|
||||
* @see hook_block_build_BASE_BLOCK_ID_alter()
|
||||
* @see entity_crud
|
||||
*
|
||||
* @ingroup block_api
|
||||
*/
|
||||
function hook_block_build_alter(array &$build, \Drupal\Core\Block\BlockPluginInterface $block) {
|
||||
// Add the 'user' cache context to some blocks.
|
||||
if ($some_condition) {
|
||||
$build['#contexts'][] = 'user';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Provide a block plugin specific block_build alteration.
|
||||
*
|
||||
* In this hook name, BASE_BLOCK_ID refers to the block implementation's plugin
|
||||
* id, regardless of whether the plugin supports derivatives. For example, for
|
||||
* the \Drupal\system\Plugin\Block\SystemPoweredByBlock block, this would be
|
||||
* 'system_powered_by_block' as per that class's annotation. And for the
|
||||
* \Drupal\system\Plugin\Block\SystemMenuBlock block, it would be
|
||||
* 'system_menu_block' as per that class's annotation, regardless of which menu
|
||||
* the derived block is for.
|
||||
*
|
||||
* @param array $build
|
||||
* A renderable array of data, only containing #cache.
|
||||
* @param \Drupal\Core\Block\BlockPluginInterface $block
|
||||
* The block plugin instance.
|
||||
*
|
||||
* @see hook_block_build_alter()
|
||||
* @see entity_crud
|
||||
*
|
||||
* @ingroup block_api
|
||||
*/
|
||||
function hook_block_build_BASE_BLOCK_ID_alter(array &$build, \Drupal\Core\Block\BlockPluginInterface $block) {
|
||||
// Explicitly enable placeholdering of the specific block.
|
||||
$build['#create_placeholder'] = TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Control access to a block instance.
|
||||
*
|
||||
|
@ -136,7 +191,7 @@ function hook_block_view_BASE_BLOCK_ID_alter(array &$build, \Drupal\Core\Block\B
|
|||
* The block instance.
|
||||
* @param string $operation
|
||||
* The operation to be performed, e.g., 'view', 'create', 'delete', 'update'.
|
||||
* @param \Drupal\user\Entity\User $account
|
||||
* @param \Drupal\Core\Session\AccountInterface $account
|
||||
* The user object to perform the access check operation on.
|
||||
* @param string $langcode
|
||||
* The language code to perform the access check operation on.
|
||||
|
@ -151,7 +206,7 @@ function hook_block_view_BASE_BLOCK_ID_alter(array &$build, \Drupal\Core\Block\B
|
|||
* @see \Drupal\block\BlockAccessControlHandler::checkAccess()
|
||||
* @ingroup block_api
|
||||
*/
|
||||
function hook_block_access(\Drupal\block\Entity\Block $block, $operation, \Drupal\user\Entity\User $account, $langcode) {
|
||||
function hook_block_access(\Drupal\block\Entity\Block $block, $operation, \Drupal\Core\Session\AccountInterface $account, $langcode) {
|
||||
// Example code that would prevent displaying the 'Powered by Drupal' block in
|
||||
// a region different than the footer.
|
||||
if ($operation == 'view' && $block->getPluginId() == 'system_powered_by_block') {
|
||||
|
|
|
@ -245,7 +245,7 @@ function block_user_role_delete($role) {
|
|||
$visibility = $block->getVisibility();
|
||||
if (isset($visibility['user_role']['roles'][$role->id()])) {
|
||||
unset($visibility['user_role']['roles'][$role->id()]);
|
||||
$block->getPlugin()->setVisibilityConfig('user_role', $visibility['user_role']);
|
||||
$block->setVisibilityConfig('user_role', $visibility['user_role']);
|
||||
$block->save();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,11 +10,18 @@
|
|||
/**
|
||||
* Filters the block list by a text input search string.
|
||||
*
|
||||
* Text search input: input.block-filter-text
|
||||
* Target element: input.block-filter-text[data-element]
|
||||
* Source text: .block-filter-text-source
|
||||
* 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: function (context, settings) {
|
||||
|
@ -22,14 +29,22 @@
|
|||
var $table = $($input.attr('data-element'));
|
||||
var $filter_rows;
|
||||
|
||||
/**
|
||||
* 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 of the block.
|
||||
* @param {HTMLElement} label The label of the block.
|
||||
* @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);
|
||||
|
@ -60,6 +75,9 @@
|
|||
* 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) {
|
||||
|
|
|
@ -11,6 +11,9 @@
|
|||
* 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 () {
|
||||
|
@ -21,6 +24,15 @@
|
|||
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');
|
||||
|
@ -49,12 +61,15 @@
|
|||
};
|
||||
|
||||
/**
|
||||
* Move a block in the blocks table from one region to another via select list.
|
||||
* 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) {
|
||||
|
@ -71,7 +86,8 @@
|
|||
checkEmptyRegions(table, this);
|
||||
};
|
||||
|
||||
// Add a handler so when a row is dropped, update fields dropped into new regions.
|
||||
// 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);
|
||||
|
@ -82,48 +98,82 @@
|
|||
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.
|
||||
// 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.
|
||||
// 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');
|
||||
}
|
||||
else if ($rowElement.prev('tr').is('.region-message')) {
|
||||
|
||||
// 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');
|
||||
|
||||
if (!regionField.is('.block-region-' + regionName)) {
|
||||
regionField.removeClass('block-region-' + oldRegionName).addClass('block-region-' + regionName);
|
||||
weightField.removeClass('block-weight-' + oldRegionName).addClass('block-weight-' + regionName);
|
||||
regionField.val(regionName);
|
||||
}
|
||||
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').each(function () {
|
||||
$(this).on('change', function (event) {
|
||||
$(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);
|
||||
tableDrag.rowObject = new tableDrag.row(row);
|
||||
|
||||
// Find the correct region and insert the row as the last in the region.
|
||||
// Find the correct region and insert the row as the last in the
|
||||
// region.
|
||||
table.find('.region-' + select[0].value + '-message').nextUntil('.region-message').eq(-1).before(row);
|
||||
|
||||
updateBlockWeights(table, select[0].value);
|
||||
// Modify empty regions with added or removed fields.
|
||||
checkEmptyRegions(table, row);
|
||||
// Remove focus from selectbox.
|
||||
select.trigger('blur');
|
||||
});
|
||||
});
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
var updateBlockWeights = function ($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;
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Checks empty regions and toggles 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.
|
||||
*/
|
||||
var checkEmptyRegions = function (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 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.
|
||||
// Prevent a recursion problem when using the keyboard to move rows
|
||||
// up.
|
||||
if ((rowObject.method !== 'keyboard' || rowObject.direction === 'down')) {
|
||||
rowObject.swap('after', this);
|
||||
}
|
||||
|
|
|
@ -89,6 +89,6 @@ destination:
|
|||
plugin: entity:block
|
||||
migration_dependencies:
|
||||
required:
|
||||
- d6_menu
|
||||
- menu
|
||||
- d6_custom_block
|
||||
- d6_user_role
|
||||
|
|
|
@ -9,7 +9,6 @@ namespace Drupal\block;
|
|||
|
||||
use Drupal\Component\Utility\Html;
|
||||
use Drupal\Component\Serialization\Json;
|
||||
use Drupal\Component\Utility\SafeMarkup;
|
||||
use Drupal\Core\Config\Entity\ConfigEntityListBuilder;
|
||||
use Drupal\Core\Entity\EntityInterface;
|
||||
use Drupal\Core\Entity\EntityStorageInterface;
|
||||
|
@ -261,7 +260,7 @@ class BlockListBuilder extends ConfigEntityListBuilder implements FormInterface
|
|||
$form[$entity_id]['#attributes']['class'][] = 'js-block-placed';
|
||||
}
|
||||
$form[$entity_id]['info'] = array(
|
||||
'#markup' => SafeMarkup::checkPlain($info['label']),
|
||||
'#plain_text' => $info['label'],
|
||||
'#wrapper_attributes' => array(
|
||||
'class' => array('block'),
|
||||
),
|
||||
|
|
|
@ -7,19 +7,59 @@
|
|||
|
||||
namespace Drupal\block;
|
||||
|
||||
use Drupal\Component\Utility\SafeMarkup;
|
||||
use Drupal\Core\Block\MainContentBlockPluginInterface;
|
||||
use Drupal\Core\Cache\Cache;
|
||||
use Drupal\Core\Cache\CacheableMetadata;
|
||||
use Drupal\Core\Entity\EntityManagerInterface;
|
||||
use Drupal\Core\Entity\EntityTypeInterface;
|
||||
use Drupal\Core\Entity\EntityViewBuilder;
|
||||
use Drupal\Core\Entity\EntityViewBuilderInterface;
|
||||
use Drupal\Core\Entity\EntityInterface;
|
||||
use Drupal\Core\Extension\ModuleHandlerInterface;
|
||||
use Drupal\Core\Language\LanguageManagerInterface;
|
||||
use Drupal\Core\Render\Element;
|
||||
use Symfony\Component\DependencyInjection\ContainerInterface;
|
||||
|
||||
/**
|
||||
* Provides a Block view builder.
|
||||
*/
|
||||
class BlockViewBuilder extends EntityViewBuilder {
|
||||
|
||||
/**
|
||||
* The module handler.
|
||||
*
|
||||
* @var \Drupal\Core\Extension\ModuleHandlerInterface
|
||||
*/
|
||||
protected $moduleHandler;
|
||||
|
||||
/**
|
||||
* Constructs a new BlockViewBuilder.
|
||||
*
|
||||
* @param \Drupal\Core\Entity\EntityTypeInterface $entity_type
|
||||
* The entity type definition.
|
||||
* @param \Drupal\Core\Entity\EntityManagerInterface $entity_manager
|
||||
* The entity manager service.
|
||||
* @param \Drupal\Core\Language\LanguageManagerInterface $language_manager
|
||||
* The language manager.
|
||||
* @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler
|
||||
* The module handler.
|
||||
*/
|
||||
public function __construct(EntityTypeInterface $entity_type, EntityManagerInterface $entity_manager, LanguageManagerInterface $language_manager, ModuleHandlerInterface $module_handler) {
|
||||
parent::__construct($entity_type, $entity_manager, $language_manager);
|
||||
$this->moduleHandler = $module_handler;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function createInstance(ContainerInterface $container, EntityTypeInterface $entity_type) {
|
||||
return new static(
|
||||
$entity_type,
|
||||
$container->get('entity.manager'),
|
||||
$container->get('language_manager'),
|
||||
$container->get('module_handler')
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
|
@ -40,13 +80,9 @@ class BlockViewBuilder extends EntityViewBuilder {
|
|||
public function viewMultiple(array $entities = array(), $view_mode = 'full', $langcode = NULL) {
|
||||
/** @var \Drupal\block\BlockInterface[] $entities */
|
||||
$build = array();
|
||||
foreach ($entities as $entity) {
|
||||
foreach ($entities as $entity) {
|
||||
$entity_id = $entity->id();
|
||||
$plugin = $entity->getPlugin();
|
||||
$plugin_id = $plugin->getPluginId();
|
||||
$base_id = $plugin->getBaseId();
|
||||
$derivative_id = $plugin->getDerivativeId();
|
||||
$configuration = $plugin->getConfiguration();
|
||||
|
||||
$cache_tags = Cache::mergeTags($this->getCacheTags(), $entity->getCacheTags());
|
||||
$cache_tags = Cache::mergeTags($cache_tags, $plugin->getCacheTags());
|
||||
|
@ -54,20 +90,6 @@ class BlockViewBuilder extends EntityViewBuilder {
|
|||
// Create the render array for the block as a whole.
|
||||
// @see template_preprocess_block().
|
||||
$build[$entity_id] = array(
|
||||
'#theme' => 'block',
|
||||
'#attributes' => array(),
|
||||
// All blocks get a "Configure block" contextual link.
|
||||
'#contextual_links' => array(
|
||||
'block' => array(
|
||||
'route_parameters' => array('block' => $entity->id()),
|
||||
),
|
||||
),
|
||||
'#weight' => $entity->getWeight(),
|
||||
'#configuration' => $configuration,
|
||||
'#plugin_id' => $plugin_id,
|
||||
'#base_plugin_id' => $base_id,
|
||||
'#derivative_plugin_id' => $derivative_id,
|
||||
'#id' => $entity->id(),
|
||||
'#cache' => [
|
||||
'keys' => ['entity_view', 'block', $entity->id()],
|
||||
'contexts' => Cache::mergeContexts(
|
||||
|
@ -77,22 +99,94 @@ class BlockViewBuilder extends EntityViewBuilder {
|
|||
'tags' => $cache_tags,
|
||||
'max-age' => $plugin->getCacheMaxAge(),
|
||||
],
|
||||
'#pre_render' => [
|
||||
[$this, 'buildBlock'],
|
||||
],
|
||||
// Add the entity so that it can be used in the #pre_render method.
|
||||
'#block' => $entity,
|
||||
);
|
||||
$build[$entity_id]['#configuration']['label'] = SafeMarkup::checkPlain($configuration['label']);
|
||||
|
||||
// Don't run in ::buildBlock() to ensure cache keys can be altered. If an
|
||||
// alter hook wants to modify the block contents, it can append another
|
||||
// #pre_render hook.
|
||||
$this->moduleHandler()->alter(array('block_view', "block_view_$base_id"), $build[$entity_id], $plugin);
|
||||
// Allow altering of cacheability metadata or setting #create_placeholder.
|
||||
$this->moduleHandler->alter(['block_build', "block_build_" . $plugin->getBaseId()], $build[$entity_id], $plugin);
|
||||
|
||||
if ($plugin instanceof MainContentBlockPluginInterface) {
|
||||
// Immediately build a #pre_render-able block, since this block cannot
|
||||
// be built lazily.
|
||||
$build[$entity_id] += static::buildPreRenderableBlock($entity, $this->moduleHandler());
|
||||
}
|
||||
else {
|
||||
// Assign a #lazy_builder callback, which will generate a #pre_render-
|
||||
// able block lazily (when necessary).
|
||||
$build[$entity_id] += [
|
||||
'#lazy_builder' => [static::class . '::lazyBuilder', [$entity_id, $view_mode, $langcode]],
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
return $build;
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds a #pre_render-able block render array.
|
||||
*
|
||||
* @param \Drupal\block\BlockInterface $entity
|
||||
* A block config entity.
|
||||
* @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler
|
||||
* The module handler service.
|
||||
*
|
||||
* @return array
|
||||
* A render array with a #pre_render callback to render the block.
|
||||
*/
|
||||
protected static function buildPreRenderableBlock($entity, ModuleHandlerInterface $module_handler) {
|
||||
$plugin = $entity->getPlugin();
|
||||
$plugin_id = $plugin->getPluginId();
|
||||
$base_id = $plugin->getBaseId();
|
||||
$derivative_id = $plugin->getDerivativeId();
|
||||
$configuration = $plugin->getConfiguration();
|
||||
|
||||
// Create the render array for the block as a whole.
|
||||
// @see template_preprocess_block().
|
||||
$build = [
|
||||
'#theme' => 'block',
|
||||
'#attributes' => [],
|
||||
// All blocks get a "Configure block" contextual link.
|
||||
'#contextual_links' => [
|
||||
'block' => [
|
||||
'route_parameters' => ['block' => $entity->id()],
|
||||
],
|
||||
],
|
||||
'#weight' => $entity->getWeight(),
|
||||
'#configuration' => $configuration,
|
||||
'#plugin_id' => $plugin_id,
|
||||
'#base_plugin_id' => $base_id,
|
||||
'#derivative_plugin_id' => $derivative_id,
|
||||
'#id' => $entity->id(),
|
||||
'#pre_render' => [
|
||||
static::class . '::preRender',
|
||||
],
|
||||
// Add the entity so that it can be used in the #pre_render method.
|
||||
'#block' => $entity,
|
||||
];
|
||||
|
||||
// If an alter hook wants to modify the block contents, it can append
|
||||
// another #pre_render hook.
|
||||
$module_handler->alter(['block_view', "block_view_$base_id"], $build, $plugin);
|
||||
|
||||
return $build;
|
||||
}
|
||||
|
||||
/**
|
||||
* #lazy_builder callback; builds a #pre_render-able block.
|
||||
*
|
||||
* @param $entity_id
|
||||
* A block config entity ID.
|
||||
* @param $view_mode
|
||||
* The view mode the block is being viewed in.
|
||||
* @param $langcode
|
||||
* The langcode the block is being viewed in.
|
||||
*
|
||||
* @return array
|
||||
* A render array with a #pre_render callback to render the block.
|
||||
*/
|
||||
public static function lazyBuilder($entity_id, $view_mode, $langcode) {
|
||||
return static::buildPreRenderableBlock(entity_load('block', $entity_id), \Drupal::service('module_handler'));
|
||||
}
|
||||
|
||||
/**
|
||||
* #pre_render callback for building a block.
|
||||
*
|
||||
|
@ -102,7 +196,7 @@ class BlockViewBuilder extends EntityViewBuilder {
|
|||
* - if there is content, moves the contextual links from the block content to
|
||||
* the block itself.
|
||||
*/
|
||||
public function buildBlock($build) {
|
||||
public static function preRender($build) {
|
||||
$content = $build['#block']->getPlugin()->build();
|
||||
// Remove the block entity from the render array, to ensure that blocks
|
||||
// can be rendered without the block config entity.
|
||||
|
|
|
@ -8,7 +8,6 @@
|
|||
namespace Drupal\block\Controller;
|
||||
|
||||
use Drupal\Component\Serialization\Json;
|
||||
use Drupal\Component\Utility\SafeMarkup;
|
||||
use Drupal\Core\Block\BlockManagerInterface;
|
||||
use Drupal\Core\Controller\ControllerBase;
|
||||
use Drupal\Core\EventSubscriber\MainContentViewSubscriber;
|
||||
|
@ -109,7 +108,7 @@ class BlockLibraryController extends ControllerBase {
|
|||
'#prefix' => '<div class="block-filter-text-source">',
|
||||
'#suffix' => '</div>',
|
||||
];
|
||||
$row['category']['data'] = SafeMarkup::checkPlain($plugin_definition['category']);
|
||||
$row['category']['data'] = $plugin_definition['category'];
|
||||
$links['add'] = [
|
||||
'title' => $this->t('Place block'),
|
||||
'url' => Url::fromRoute('block.admin_add', ['plugin_id' => $plugin_id, 'theme' => $theme]),
|
||||
|
|
|
@ -8,7 +8,6 @@
|
|||
namespace Drupal\block\Plugin\Derivative;
|
||||
|
||||
use Drupal\Component\Plugin\Derivative\DeriverBase;
|
||||
use Drupal\Core\Config\ConfigFactoryInterface;
|
||||
use Drupal\Core\Extension\ThemeHandlerInterface;
|
||||
use Drupal\Core\Plugin\Discovery\ContainerDeriverInterface;
|
||||
use Symfony\Component\DependencyInjection\ContainerInterface;
|
||||
|
@ -18,13 +17,6 @@ use Symfony\Component\DependencyInjection\ContainerInterface;
|
|||
*/
|
||||
class ThemeLocalTask extends DeriverBase implements ContainerDeriverInterface {
|
||||
|
||||
/**
|
||||
* Stores the theme settings config object.
|
||||
*
|
||||
* @var \Drupal\Core\Config\Config
|
||||
*/
|
||||
protected $config;
|
||||
|
||||
/**
|
||||
* The theme handler.
|
||||
*
|
||||
|
@ -35,13 +27,10 @@ class ThemeLocalTask extends DeriverBase implements ContainerDeriverInterface {
|
|||
/**
|
||||
* Constructs a new ThemeLocalTask.
|
||||
*
|
||||
* @param \Drupal\Core\Config\ConfigFactoryInterface $config_factory
|
||||
* The config factory.
|
||||
* @param \Drupal\Core\Extension\ThemeHandlerInterface $theme_handler
|
||||
* The theme handler.
|
||||
*/
|
||||
public function __construct(ConfigFactoryInterface $config_factory, ThemeHandlerInterface $theme_handler) {
|
||||
$this->config = $config_factory->get('system.theme');
|
||||
public function __construct(ThemeHandlerInterface $theme_handler) {
|
||||
$this->themeHandler = $theme_handler;
|
||||
}
|
||||
|
||||
|
@ -50,7 +39,6 @@ class ThemeLocalTask extends DeriverBase implements ContainerDeriverInterface {
|
|||
*/
|
||||
public static function create(ContainerInterface $container, $base_plugin_id) {
|
||||
return new static(
|
||||
$container->get('config.factory'),
|
||||
$container->get('theme_handler')
|
||||
);
|
||||
}
|
||||
|
@ -59,7 +47,7 @@ class ThemeLocalTask extends DeriverBase implements ContainerDeriverInterface {
|
|||
* {@inheritdoc}
|
||||
*/
|
||||
public function getDerivativeDefinitions($base_plugin_definition) {
|
||||
$default_theme = $this->config->get('default');
|
||||
$default_theme = $this->themeHandler->getDefault();
|
||||
|
||||
foreach ($this->themeHandler->listInfo() as $theme_name => $theme) {
|
||||
if ($theme->status) {
|
||||
|
|
|
@ -24,7 +24,7 @@ class BlockAdminThemeTest extends WebTestBase {
|
|||
public static $modules = array('block');
|
||||
|
||||
/**
|
||||
* Check for the accessibility of the admin theme on the block admin page.
|
||||
* Check for the accessibility of the admin theme on the block admin page.
|
||||
*/
|
||||
function testAdminTheme() {
|
||||
// Create administrative user.
|
||||
|
|
76
core/modules/block/src/Tests/BlockFormInBlockTest.php
Normal file
76
core/modules/block/src/Tests/BlockFormInBlockTest.php
Normal file
|
@ -0,0 +1,76 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\block\Tests\BlockFormInBlockTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\block\Tests;
|
||||
|
||||
use Drupal\simpletest\WebTestBase;
|
||||
|
||||
/**
|
||||
* Tests form in block caching.
|
||||
*
|
||||
* @group block
|
||||
*/
|
||||
class BlockFormInBlockTest extends WebTestBase {
|
||||
|
||||
/**
|
||||
* Modules to install.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $modules = ['block', 'block_test', 'test_page_test'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
|
||||
// Enable our test block.
|
||||
$this->drupalPlaceBlock('test_form_in_block');
|
||||
}
|
||||
|
||||
/**
|
||||
* Test to see if form in block's redirect isn't cached.
|
||||
*/
|
||||
function testCachePerPage() {
|
||||
$form_values = ['email' => 'test@example.com'];
|
||||
|
||||
// Go to "test-page" and test if the block is enabled.
|
||||
$this->drupalGet('test-page');
|
||||
$this->assertResponse(200);
|
||||
$this->assertText('Your .com email address.', 'form found');
|
||||
|
||||
// Make sure that we're currently still on /test-page after submitting the
|
||||
// form.
|
||||
$this->drupalPostForm(NULL, $form_values, t('Submit'));
|
||||
$this->assertUrl('test-page');
|
||||
$this->assertText(t('Your email address is @email', ['@email' => 'test@example.com']));
|
||||
|
||||
// Go to a different page and see if the block is enabled there as well.
|
||||
$this->drupalGet('test-render-title');
|
||||
$this->assertResponse(200);
|
||||
$this->assertText('Your .com email address.', 'form found');
|
||||
|
||||
// Make sure that submitting the form didn't redirect us to the first page
|
||||
// we submitted the form from after submitting the form from
|
||||
// /test-render-title.
|
||||
$this->drupalPostForm(NULL, $form_values, t('Submit'));
|
||||
$this->assertUrl('test-render-title');
|
||||
$this->assertText(t('Your email address is @email', ['@email' => 'test@example.com']));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test the actual placeholders
|
||||
*/
|
||||
public function testPlaceholders() {
|
||||
$this->drupalGet('test-multiple-forms');
|
||||
|
||||
$placeholder = 'form_action_' . hash('crc32b', 'Drupal\Core\Form\FormBuilder::prepareForm');
|
||||
$this->assertText('Form action: ' . $placeholder, 'placeholder found.');
|
||||
}
|
||||
|
||||
}
|
|
@ -42,6 +42,7 @@ class BlockHiddenRegionTest extends WebTestBase {
|
|||
|
||||
$this->drupalLogin($this->adminUser);
|
||||
$this->drupalPlaceBlock('search_form_block');
|
||||
$this->drupalPlaceBlock('local_tasks_block');
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -8,7 +8,6 @@
|
|||
namespace Drupal\block\Tests;
|
||||
|
||||
use Drupal\Core\Cache\Cache;
|
||||
use Drupal\Component\Utility\SafeMarkup;
|
||||
use Drupal\Core\Form\FormState;
|
||||
use Drupal\simpletest\KernelTestBase;
|
||||
use Drupal\block\BlockInterface;
|
||||
|
@ -73,7 +72,7 @@ class BlockInterfaceTest extends KernelTestBase {
|
|||
'admin_label' => array(
|
||||
'#type' => 'item',
|
||||
'#title' => t('Block description'),
|
||||
'#markup' => SafeMarkup::checkPlain($definition['admin_label']),
|
||||
'#plain_text' => $definition['admin_label'],
|
||||
),
|
||||
'label' => array(
|
||||
'#type' => 'textfield',
|
||||
|
|
|
@ -8,8 +8,8 @@
|
|||
namespace Drupal\block\Tests;
|
||||
|
||||
use Drupal\Component\Utility\Html;
|
||||
use Drupal\simpletest\WebTestBase;
|
||||
use Drupal\block\Entity\Block;
|
||||
use Drupal\user\Entity\Role;
|
||||
use Drupal\user\RoleInterface;
|
||||
|
||||
/**
|
||||
|
@ -222,6 +222,7 @@ class BlockTest extends BlockTestBase {
|
|||
function testThemeName() {
|
||||
// Enable the help block.
|
||||
$this->drupalPlaceBlock('help_block', array('region' => 'help'));
|
||||
$this->drupalPlaceBlock('local_tasks_block');
|
||||
// Explicitly set the default and admin themes.
|
||||
$theme = 'block_test_specialchars_theme';
|
||||
\Drupal::service('theme_handler')->install(array($theme));
|
||||
|
@ -409,6 +410,22 @@ class BlockTest extends BlockTestBase {
|
|||
$this->assertEqual($this->drupalGetHeader('X-Drupal-Cache'), 'MISS');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that a link exists to block layout from the appearance form.
|
||||
*/
|
||||
public function testThemeAdminLink() {
|
||||
$this->drupalPlaceBlock('help_block', ['region' => 'help']);
|
||||
$theme_admin = $this->drupalCreateUser([
|
||||
'administer blocks',
|
||||
'administer themes',
|
||||
'access administration pages',
|
||||
]);
|
||||
$this->drupalLogin($theme_admin);
|
||||
$this->drupalGet('admin/appearance');
|
||||
$this->assertText('You can place blocks for each theme on the block layout page');
|
||||
$this->assertLinkByHref('admin/structure/block');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that uninstalling a theme removes its block configuration.
|
||||
*/
|
||||
|
@ -443,4 +460,41 @@ class BlockTest extends BlockTestBase {
|
|||
$this->assertText('Hello test world');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests block_user_role_delete.
|
||||
*/
|
||||
public function testBlockUserRoleDelete() {
|
||||
$role1 = Role::create(['id' => 'test_role1', 'name' => $this->randomString()]);
|
||||
$role1->save();
|
||||
|
||||
$role2 = Role::create(['id' => 'test_role2', 'name' => $this->randomString()]);
|
||||
$role2->save();
|
||||
|
||||
$block = Block::create([
|
||||
'id' => $this->randomMachineName(),
|
||||
'plugin' => 'system_powered_by_block',
|
||||
]);
|
||||
|
||||
$block->setVisibilityConfig('user_role', [
|
||||
'roles' => [
|
||||
$role1->id() => $role1->id(),
|
||||
$role2->id() => $role2->id(),
|
||||
],
|
||||
]);
|
||||
|
||||
$block->save();
|
||||
|
||||
$this->assertEqual($block->getVisibility()['user_role']['roles'], [
|
||||
$role1->id() => $role1->id(),
|
||||
$role2->id() => $role2->id()
|
||||
]);
|
||||
|
||||
$role1->delete();
|
||||
|
||||
$block = Block::load($block->id());
|
||||
$this->assertEqual($block->getVisibility()['user_role']['roles'], [
|
||||
$role2->id() => $role2->id()
|
||||
]);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -186,61 +186,27 @@ class BlockViewBuilderTest extends KernelTestBase {
|
|||
|
||||
/**
|
||||
* Tests block view altering.
|
||||
*
|
||||
* @see hook_block_view_alter()
|
||||
* @see hook_block_view_BASE_BLOCK_ID_alter()
|
||||
*/
|
||||
public function testBlockViewBuilderAlter() {
|
||||
public function testBlockViewBuilderViewAlter() {
|
||||
// Establish baseline.
|
||||
$build = $this->getBlockRenderArray();
|
||||
$this->assertIdentical((string) $this->renderer->renderRoot($build), 'Llamas > unicorns!');
|
||||
$this->setRawContent((string) $this->renderer->renderRoot($build));
|
||||
$this->assertIdentical(trim((string) $this->cssSelect('div')[0]), 'Llamas > unicorns!');
|
||||
|
||||
// Enable the block view alter hook that adds a suffix, for basic testing.
|
||||
// Enable the block view alter hook that adds a foo=bar attribute.
|
||||
\Drupal::state()->set('block_test_view_alter_suffix', TRUE);
|
||||
Cache::invalidateTags($this->block->getCacheTagsToInvalidate());
|
||||
$build = $this->getBlockRenderArray();
|
||||
$this->assertTrue(isset($build['#suffix']) && $build['#suffix'] === '<br>Goodbye!', 'A block with content is altered.');
|
||||
$this->assertIdentical((string) $this->renderer->renderRoot($build), 'Llamas > unicorns!<br>Goodbye!');
|
||||
$this->setRawContent((string) $this->renderer->renderRoot($build));
|
||||
$this->assertIdentical(trim((string) $this->cssSelect('[foo=bar]')[0]), 'Llamas > unicorns!');
|
||||
\Drupal::state()->set('block_test_view_alter_suffix', FALSE);
|
||||
|
||||
// Force a request via GET so we can test the render cache.
|
||||
$request = \Drupal::request();
|
||||
$request_method = $request->server->get('REQUEST_METHOD');
|
||||
$request->setMethod('GET');
|
||||
|
||||
\Drupal::state()->set('block_test.content', NULL);
|
||||
Cache::invalidateTags($this->block->getCacheTagsToInvalidate());
|
||||
|
||||
$default_keys = array('entity_view', 'block', 'test_block');
|
||||
$default_tags = array('block_view', 'config:block.block.test_block');
|
||||
|
||||
// Advanced: cached block, but an alter hook adds an additional cache key.
|
||||
$alter_add_key = $this->randomMachineName();
|
||||
\Drupal::state()->set('block_test_view_alter_cache_key', $alter_add_key);
|
||||
$cid = 'entity_view:block:test_block:' . $alter_add_key . ':' . implode(':', \Drupal::service('cache_contexts_manager')->convertTokensToKeys(['languages:' . LanguageInterface::TYPE_INTERFACE, 'theme', 'user.permissions'])->getKeys());
|
||||
$expected_keys = array_merge($default_keys, array($alter_add_key));
|
||||
$build = $this->getBlockRenderArray();
|
||||
$this->assertIdentical($expected_keys, $build['#cache']['keys'], 'An altered cacheable block has the expected cache keys.');
|
||||
$this->assertIdentical((string) $this->renderer->renderRoot($build), '');
|
||||
$cache_entry = $this->container->get('cache.render')->get($cid);
|
||||
$this->assertTrue($cache_entry, 'The block render element has been cached with the expected cache ID.');
|
||||
$expected_tags = array_merge($default_tags, ['rendered']);
|
||||
sort($expected_tags);
|
||||
$this->assertIdentical($cache_entry->tags, $expected_tags, 'The block render element has been cached with the expected cache tags.');
|
||||
$this->container->get('cache.render')->delete($cid);
|
||||
|
||||
// Advanced: cached block, but an alter hook adds an additional cache tag.
|
||||
$alter_add_tag = $this->randomMachineName();
|
||||
\Drupal::state()->set('block_test_view_alter_cache_tag', $alter_add_tag);
|
||||
$expected_tags = Cache::mergeTags($default_tags, array($alter_add_tag));
|
||||
$build = $this->getBlockRenderArray();
|
||||
sort($build['#cache']['tags']);
|
||||
$this->assertIdentical($expected_tags, $build['#cache']['tags'], 'An altered cacheable block has the expected cache tags.');
|
||||
$this->assertIdentical((string) $this->renderer->renderRoot($build), '');
|
||||
$cache_entry = $this->container->get('cache.render')->get($cid);
|
||||
$this->assertTrue($cache_entry, 'The block render element has been cached with the expected cache ID.');
|
||||
$expected_tags = array_merge($default_tags, [$alter_add_tag, 'rendered']);
|
||||
sort($expected_tags);
|
||||
$this->assertIdentical($cache_entry->tags, $expected_tags, 'The block render element has been cached with the expected cache tags.');
|
||||
$this->container->get('cache.render')->delete($cid);
|
||||
|
||||
// Advanced: cached block, but an alter hook adds a #pre_render callback to
|
||||
// alter the eventual content.
|
||||
\Drupal::state()->set('block_test_view_alter_append_pre_render_prefix', TRUE);
|
||||
|
@ -248,11 +214,114 @@ class BlockViewBuilderTest extends KernelTestBase {
|
|||
$this->assertFalse(isset($build['#prefix']), 'The appended #pre_render callback has not yet run before rendering.');
|
||||
$this->assertIdentical((string) $this->renderer->renderRoot($build), 'Hiya!<br>');
|
||||
$this->assertTrue(isset($build['#prefix']) && $build['#prefix'] === 'Hiya!<br>', 'A cached block without content is altered.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests block build altering.
|
||||
*
|
||||
* @see hook_block_build_alter()
|
||||
* @see hook_block_build_BASE_BLOCK_ID_alter()
|
||||
*/
|
||||
public function testBlockViewBuilderBuildAlter() {
|
||||
// Force a request via GET so we can test the render cache.
|
||||
$request = \Drupal::request();
|
||||
$request_method = $request->server->get('REQUEST_METHOD');
|
||||
$request->setMethod('GET');
|
||||
|
||||
$default_keys = ['entity_view', 'block', 'test_block'];
|
||||
$default_contexts = [];
|
||||
$default_tags = ['block_view', 'config:block.block.test_block'];
|
||||
$default_max_age = Cache::PERMANENT;
|
||||
|
||||
// hook_block_build_alter() adds an additional cache key.
|
||||
$alter_add_key = $this->randomMachineName();
|
||||
\Drupal::state()->set('block_test_block_alter_cache_key', $alter_add_key);
|
||||
$this->assertBlockRenderedWithExpectedCacheability(array_merge($default_keys, [$alter_add_key]), $default_contexts, $default_tags, $default_max_age);
|
||||
\Drupal::state()->set('block_test_block_alter_cache_key', NULL);
|
||||
|
||||
// hook_block_build_alter() adds an additional cache context.
|
||||
$alter_add_context = 'url.query_args:' . $this->randomMachineName();
|
||||
\Drupal::state()->set('block_test_block_alter_cache_context', $alter_add_context);
|
||||
$this->assertBlockRenderedWithExpectedCacheability($default_keys, Cache::mergeContexts($default_contexts, [$alter_add_context]), $default_tags, $default_max_age);
|
||||
\Drupal::state()->set('block_test_block_alter_cache_context', NULL);
|
||||
|
||||
// hook_block_build_alter() adds an additional cache tag.
|
||||
$alter_add_tag = $this->randomMachineName();
|
||||
\Drupal::state()->set('block_test_block_alter_cache_tag', $alter_add_tag);
|
||||
$this->assertBlockRenderedWithExpectedCacheability($default_keys, $default_contexts, Cache::mergeTags($default_tags, [$alter_add_tag]), $default_max_age);
|
||||
\Drupal::state()->set('block_test_block_alter_cache_tag', NULL);
|
||||
|
||||
// hook_block_build_alter() alters the max-age.
|
||||
$alter_max_age = 300;
|
||||
\Drupal::state()->set('block_test_block_alter_cache_max_age', $alter_max_age);
|
||||
$this->assertBlockRenderedWithExpectedCacheability($default_keys, $default_contexts, $default_tags, $alter_max_age);
|
||||
\Drupal::state()->set('block_test_block_alter_cache_max_age', NULL);
|
||||
|
||||
// hook_block_build_alter() alters cache keys, contexts, tags and max-age.
|
||||
\Drupal::state()->set('block_test_block_alter_cache_key', $alter_add_key);
|
||||
\Drupal::state()->set('block_test_block_alter_cache_context', $alter_add_context);
|
||||
\Drupal::state()->set('block_test_block_alter_cache_tag', $alter_add_tag);
|
||||
\Drupal::state()->set('block_test_block_alter_cache_max_age', $alter_max_age);
|
||||
$this->assertBlockRenderedWithExpectedCacheability(array_merge($default_keys, [$alter_add_key]), Cache::mergeContexts($default_contexts, [$alter_add_context]), Cache::mergeTags($default_tags, [$alter_add_tag]), $alter_max_age);
|
||||
\Drupal::state()->set('block_test_block_alter_cache_key', NULL);
|
||||
\Drupal::state()->set('block_test_block_alter_cache_context', NULL);
|
||||
\Drupal::state()->set('block_test_block_alter_cache_tag', NULL);
|
||||
\Drupal::state()->set('block_test_block_alter_cache_max_age', NULL);
|
||||
|
||||
// hook_block_build_alter() sets #create_placeholder.
|
||||
foreach ([TRUE, FALSE] as $value) {
|
||||
\Drupal::state()->set('block_test_block_alter_create_placeholder', $value);
|
||||
$build = $this->getBlockRenderArray();
|
||||
$this->assertTrue(isset($build['#create_placeholder']));
|
||||
$this->assertIdentical($value, $build['#create_placeholder']);
|
||||
}
|
||||
\Drupal::state()->set('block_test_block_alter_create_placeholder', NULL);
|
||||
|
||||
// Restore the previous request method.
|
||||
$request->setMethod($request_method);
|
||||
}
|
||||
|
||||
/**
|
||||
* Asserts that a block is built/rendered/cached with expected cacheability.
|
||||
*
|
||||
* @param string[] $expected_keys
|
||||
* The expected cache keys.
|
||||
* @param string[] $expected_contexts
|
||||
* The expected cache contexts.
|
||||
* @param string[] $expected_tags
|
||||
* The expected cache tags.
|
||||
* @param int $expected_max_age
|
||||
* The expected max-age.
|
||||
*/
|
||||
protected function assertBlockRenderedWithExpectedCacheability(array $expected_keys, array $expected_contexts, array $expected_tags, $expected_max_age) {
|
||||
$required_cache_contexts = ['languages:' . LanguageInterface::TYPE_INTERFACE, 'theme', 'user.permissions'];
|
||||
|
||||
// Check that the expected cacheability metadata is present in:
|
||||
// - the built render array;
|
||||
$this->pass('Built render array');
|
||||
$build = $this->getBlockRenderArray();
|
||||
$this->assertIdentical($expected_keys, $build['#cache']['keys']);
|
||||
$this->assertIdentical($expected_contexts, $build['#cache']['contexts']);
|
||||
$this->assertIdentical($expected_tags, $build['#cache']['tags']);
|
||||
$this->assertIdentical($expected_max_age, $build['#cache']['max-age']);
|
||||
$this->assertFalse(isset($build['#create_placeholder']));
|
||||
// - the rendered render array;
|
||||
$this->pass('Rendered render array');
|
||||
$this->renderer->renderRoot($build);
|
||||
// - the render cache item.
|
||||
$this->pass('Render cache item');
|
||||
$final_cache_contexts = Cache::mergeContexts($expected_contexts, $required_cache_contexts);
|
||||
$cid = implode(':', $expected_keys) . ':' . implode(':', \Drupal::service('cache_contexts_manager')->convertTokensToKeys($final_cache_contexts)->getKeys());
|
||||
$cache_item = $this->container->get('cache.render')->get($cid);
|
||||
$this->assertTrue($cache_item, 'The block render element has been cached with the expected cache ID.');
|
||||
$this->assertIdentical(Cache::mergeTags($expected_tags, ['rendered']), $cache_item->tags);
|
||||
$this->assertIdentical($final_cache_contexts, $cache_item->data['#cache']['contexts']);
|
||||
$this->assertIdentical($expected_tags, $cache_item->data['#cache']['tags']);
|
||||
$this->assertIdentical($expected_max_age, $cache_item->data['#cache']['max-age']);
|
||||
|
||||
$this->container->get('cache.render')->delete($cid);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a fully built render array for a block.
|
||||
*
|
||||
|
@ -260,12 +329,7 @@ class BlockViewBuilderTest extends KernelTestBase {
|
|||
* The render array.
|
||||
*/
|
||||
protected function getBlockRenderArray() {
|
||||
$build = $this->container->get('entity.manager')->getViewBuilder('block')->view($this->block, 'block');
|
||||
|
||||
// Mock the build array to not require the theme registry.
|
||||
unset($build['#theme']);
|
||||
|
||||
return $build;
|
||||
return $this->container->get('entity.manager')->getViewBuilder('block')->view($this->block, 'block');
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -13,7 +13,7 @@ use Drupal\migrate_drupal\Tests\d6\MigrateDrupal6TestBase;
|
|||
/**
|
||||
* Upgrade block settings to block.block.*.yml.
|
||||
*
|
||||
* @group block
|
||||
* @group migrate_drupal_6
|
||||
*/
|
||||
class MigrateBlockTest extends MigrateDrupal6TestBase {
|
||||
|
||||
|
@ -53,7 +53,7 @@ class MigrateBlockTest extends MigrateDrupal6TestBase {
|
|||
array(array(1), array(1)),
|
||||
array(array(2), array(2)),
|
||||
),
|
||||
'd6_menu' => array(
|
||||
'menu' => array(
|
||||
array(array('menu1'), array('menu')),
|
||||
),
|
||||
'd6_user_role' => array(
|
||||
|
@ -71,7 +71,6 @@ class MigrateBlockTest extends MigrateDrupal6TestBase {
|
|||
// Install one of D8's test themes.
|
||||
\Drupal::service('theme_handler')->install(array('test_theme'));
|
||||
|
||||
$this->loadDumps(['Blocks.php', 'BlocksRoles.php', 'AggregatorFeed.php']);
|
||||
$this->executeMigration('d6_block');
|
||||
}
|
||||
|
||||
|
|
|
@ -23,6 +23,15 @@ class NonDefaultBlockAdminTest extends WebTestBase {
|
|||
*/
|
||||
public static $modules = array('block');
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
|
||||
$this->drupalPlaceBlock('local_tasks_block');
|
||||
}
|
||||
|
||||
/**
|
||||
* Test non-default theme admin.
|
||||
*/
|
||||
|
|
|
@ -0,0 +1,25 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\block\Tests\Update\BlockContextMappingUpdateFilledTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\block\Tests\Update;
|
||||
|
||||
/**
|
||||
* Runs BlockContextMappingUpdateTest with a dump filled with content.
|
||||
*
|
||||
* @group Update
|
||||
*/
|
||||
class BlockContextMappingUpdateFilledTest extends BlockContextMappingUpdateTest {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setDatabaseDumpFiles() {
|
||||
parent::setDatabaseDumpFiles();
|
||||
$this->databaseDumpFiles[0] = __DIR__ . '/../../../../system/tests/fixtures/update/drupal-8.filled.standard.php.gz';
|
||||
}
|
||||
|
||||
}
|
|
@ -28,12 +28,13 @@ class BlockContextMappingUpdateTest extends UpdatePathTestBase {
|
|||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp() {
|
||||
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',
|
||||
];
|
||||
parent::setUp();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -95,7 +96,7 @@ class BlockContextMappingUpdateTest extends UpdatePathTestBase {
|
|||
$disabled_block = Block::load('thirdtestfor2354889');
|
||||
$this->assertFalse($disabled_block->status(), 'Block with invalid context is disabled');
|
||||
|
||||
$this->assertEqual(['thirdtestfor2354889' => ['missing_context_ids' => ['baloney.spam' => ['node_type']], 'status' => TRUE]], \Drupal::keyValue('update_backup')->get('block_update_8001'));
|
||||
$this->assertEqual(['thirdtestfor2354889' => ['missing_context_ids' => ['baloney_spam' => ['node_type']], 'status' => TRUE]], \Drupal::keyValue('update_backup')->get('block_update_8001'));
|
||||
|
||||
$disabled_block_visibility = $disabled_block->get('visibility');
|
||||
$this->assertTrue(!isset($disabled_block_visibility['node_type']), 'The problematic visibility condition has been removed.');
|
||||
|
|
|
@ -8,6 +8,8 @@
|
|||
namespace Drupal\block\Tests\Views;
|
||||
|
||||
use Drupal\Component\Serialization\Json;
|
||||
use Drupal\system\Tests\Cache\AssertPageCacheContextsAndTagsTrait;
|
||||
use Drupal\views\Entity\View;
|
||||
use Drupal\views\Views;
|
||||
use Drupal\views\Tests\ViewTestBase;
|
||||
use Drupal\views\Tests\ViewTestData;
|
||||
|
@ -21,6 +23,8 @@ use Drupal\Core\Template\Attribute;
|
|||
*/
|
||||
class DisplayBlockTest extends ViewTestBase {
|
||||
|
||||
use AssertPageCacheContextsAndTagsTrait;
|
||||
|
||||
/**
|
||||
* Modules to install.
|
||||
*
|
||||
|
@ -259,6 +263,87 @@ class DisplayBlockTest extends ViewTestBase {
|
|||
$this->drupalGet('');
|
||||
$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' ,'rendered']));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the various testcases of empty block rendering.
|
||||
*/
|
||||
public function testBlockEmptyRendering() {
|
||||
// Remove all views_test_data entries.
|
||||
\Drupal::database()->truncate('views_test_data')->execute();
|
||||
/** @var \Drupal\views\ViewEntityInterface $view */
|
||||
$view = View::load('test_view_block');
|
||||
$view->invalidateCaches();
|
||||
|
||||
$block = $this->drupalPlaceBlock('views_block:test_view_block-block_1', array('label' => 'test_view_block-block_1:1', 'views_label' => 'Custom title'));
|
||||
$this->drupalGet('');
|
||||
$this->assertEqual(1, count($this->xpath('//div[contains(@class, "block-views-blocktest-view-block-block-1")]')));
|
||||
|
||||
$display = &$view->getDisplay('block_1');
|
||||
$display['display_options']['block_hide_empty'] = TRUE;
|
||||
$view->save();
|
||||
|
||||
$this->drupalGet('');
|
||||
$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
|
||||
// empty block.
|
||||
$this->assertCacheTags(array_merge($block->getCacheTags(), ['block_view', 'config:block_list', 'config:system.site', 'config:views.view.test_view_block' ,'rendered']));
|
||||
$this->assertCacheContexts(['url.path', 'url.query_args', 'user.roles:authenticated']);
|
||||
|
||||
// Add a header displayed on empty result.
|
||||
$display = &$view->getDisplay('block_1');
|
||||
$display['display_options']['defaults']['header'] = FALSE;
|
||||
$display['display_options']['header']['example'] = [
|
||||
'field' => 'area_text_custom',
|
||||
'id' => 'area_text_custom',
|
||||
'table' => 'views',
|
||||
'plugin_id' => 'text_custom',
|
||||
'content' => 'test header',
|
||||
'empty' => TRUE,
|
||||
];
|
||||
$view->save();
|
||||
|
||||
$this->drupalGet('');
|
||||
$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:system.site', 'config:views.view.test_view_block' ,'rendered']));
|
||||
$this->assertCacheContexts(['url.path', 'url.query_args', 'user.roles:authenticated']);
|
||||
|
||||
// Hide the header on empty results.
|
||||
$display = &$view->getDisplay('block_1');
|
||||
$display['display_options']['defaults']['header'] = FALSE;
|
||||
$display['display_options']['header']['example'] = [
|
||||
'field' => 'area_text_custom',
|
||||
'id' => 'area_text_custom',
|
||||
'table' => 'views',
|
||||
'plugin_id' => 'text_custom',
|
||||
'content' => 'test header',
|
||||
'empty' => FALSE,
|
||||
];
|
||||
$view->save();
|
||||
|
||||
$this->drupalGet('');
|
||||
$this->assertEqual(0, 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:system.site', 'config:views.view.test_view_block' ,'rendered']));
|
||||
$this->assertCacheContexts(['url.path', 'url.query_args', 'user.roles:authenticated']);
|
||||
|
||||
// Add an empty text.
|
||||
$display = &$view->getDisplay('block_1');
|
||||
$display['display_options']['defaults']['empty'] = FALSE;
|
||||
$display['display_options']['empty']['example'] = [
|
||||
'field' => 'area_text_custom',
|
||||
'id' => 'area_text_custom',
|
||||
'table' => 'views',
|
||||
'plugin_id' => 'text_custom',
|
||||
'content' => 'test empty',
|
||||
];
|
||||
$view->save();
|
||||
|
||||
$this->drupalGet('');
|
||||
$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:system.site', 'config:views.view.test_view_block' ,'rendered']));
|
||||
$this->assertCacheContexts(['url.path', 'url.query_args', 'user.roles:authenticated']);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -12,12 +12,6 @@
|
|||
* - module: The module that provided this block plugin.
|
||||
* - cache: The cache settings.
|
||||
* - Block plugin specific settings will also be stored here.
|
||||
* - block - The full block entity.
|
||||
* - label_hidden: The hidden block title value if the block was
|
||||
* configured to hide the title ('label' is empty in this case).
|
||||
* - module: The module that generated the block.
|
||||
* - delta: An ID for the block, unique within each module.
|
||||
* - region: The block region embedding the current block.
|
||||
* - content: The content of this block.
|
||||
* - attributes: array of HTML attributes populated by modules, intended to
|
||||
* be added to the main container tag of this template.
|
||||
|
|
|
@ -22,19 +22,37 @@ function block_test_block_alter(&$block_info) {
|
|||
*/
|
||||
function block_test_block_view_test_cache_alter(array &$build, BlockPluginInterface $block) {
|
||||
if (\Drupal::state()->get('block_test_view_alter_suffix') !== NULL) {
|
||||
$build['#suffix'] = '<br>Goodbye!';
|
||||
}
|
||||
if (\Drupal::state()->get('block_test_view_alter_cache_key') !== NULL) {
|
||||
$build['#cache']['keys'][] = \Drupal::state()->get('block_test_view_alter_cache_key');
|
||||
}
|
||||
if (\Drupal::state()->get('block_test_view_alter_cache_tag') !== NULL) {
|
||||
$build['#cache']['tags'][] = \Drupal::state()->get('block_test_view_alter_cache_tag');
|
||||
$build['#attributes']['foo'] = 'bar';
|
||||
}
|
||||
if (\Drupal::state()->get('block_test_view_alter_append_pre_render_prefix') !== NULL) {
|
||||
$build['#pre_render'][] = 'block_test_pre_render_alter_content';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_block_build_BASE_BLOCK_ID_alter().
|
||||
*/
|
||||
function block_test_block_build_test_cache_alter(array &$build, BlockPluginInterface $block) {
|
||||
// Test altering cache keys, contexts, tags and max-age.
|
||||
if (\Drupal::state()->get('block_test_block_alter_cache_key') !== NULL) {
|
||||
$build['#cache']['keys'][] = \Drupal::state()->get('block_test_block_alter_cache_key');
|
||||
}
|
||||
if (\Drupal::state()->get('block_test_block_alter_cache_context') !== NULL) {
|
||||
$build['#cache']['contexts'][] = \Drupal::state()->get('block_test_block_alter_cache_context');
|
||||
}
|
||||
if (\Drupal::state()->get('block_test_block_alter_cache_tag') !== NULL) {
|
||||
$build['#cache']['tags'] = Cache::mergeTags($build['#cache']['tags'], [\Drupal::state()->get('block_test_block_alter_cache_tag')]);
|
||||
}
|
||||
if (\Drupal::state()->get('block_test_block_alter_cache_max_age') !== NULL) {
|
||||
$build['#cache']['max-age'] = \Drupal::state()->get('block_test_block_alter_cache_max_age');
|
||||
}
|
||||
|
||||
// Test setting #create_placeholder.
|
||||
if (\Drupal::state()->get('block_test_block_alter_create_placeholder') !== NULL) {
|
||||
$build['#create_placeholder'] = \Drupal::state()->get('block_test_block_alter_create_placeholder');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* #pre_render callback for a block to alter its content.
|
||||
*/
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
block_test.test_multipleforms:
|
||||
path: '/test-multiple-forms'
|
||||
defaults:
|
||||
_controller: '\Drupal\block_test\Controller\TestMultipleFormController::testMultipleForms'
|
||||
_title: 'Multiple forms'
|
||||
requirements:
|
||||
_access: 'TRUE'
|
|
@ -5,3 +5,6 @@ block.settings.test_block_instantiation:
|
|||
display_message:
|
||||
type: string
|
||||
label: 'Message text'
|
||||
|
||||
condition.plugin.baloney_spam:
|
||||
type: condition.plugin
|
||||
|
|
|
@ -0,0 +1,43 @@
|
|||
<?php
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\block_test\Controller\TestMultipleFormController.
|
||||
*/
|
||||
|
||||
namespace Drupal\block_test\Controller;
|
||||
|
||||
use Drupal\Core\Controller\ControllerBase;
|
||||
use Drupal\Core\Form\FormState;
|
||||
|
||||
/**
|
||||
* Controller for block_test module
|
||||
*/
|
||||
class TestMultipleFormController extends ControllerBase {
|
||||
|
||||
public function testMultipleForms() {
|
||||
$form_state = new FormState();
|
||||
$build = [
|
||||
'form1' => $this->formBuilder()->buildForm('\Drupal\block_test\Form\TestForm', $form_state),
|
||||
'form2' => $this->formBuilder()->buildForm('\Drupal\block_test\Form\FavoriteAnimalTestForm', $form_state),
|
||||
];
|
||||
|
||||
// Output all attached placeholders trough drupal_set_message(), so we can
|
||||
// see if there's only one in the tests.
|
||||
$post_render_callable = function ($elements) {
|
||||
$matches = [];
|
||||
preg_match_all('<form\s(.*?)action="(.*?)"(.*)>', $elements, $matches);
|
||||
|
||||
$action_values = $matches[2];
|
||||
|
||||
foreach ($action_values as $action_value) {
|
||||
drupal_set_message('Form action: ' . $action_value);
|
||||
}
|
||||
return $elements;
|
||||
};
|
||||
|
||||
$build['#post_render'] = [$post_render_callable];
|
||||
|
||||
return $build;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,46 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\block_test\Form\FavoriteAnimalTestForm.
|
||||
*/
|
||||
|
||||
namespace Drupal\block_test\Form;
|
||||
|
||||
use Drupal\Core\Form\FormBase;
|
||||
use Drupal\Core\Form\FormStateInterface;
|
||||
|
||||
class FavoriteAnimalTestForm extends FormBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getFormId() {
|
||||
return 'block_test_form_favorite_animal_test';
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function buildForm(array $form, FormStateInterface $form_state) {
|
||||
$form['favorite_animal'] = [
|
||||
'#type' => 'textfield',
|
||||
'#title' => $this->t('Your favorite animal.')
|
||||
];
|
||||
|
||||
$form['submit_animal'] = [
|
||||
'#type' => 'submit',
|
||||
'#value' => $this->t('Submit your chosen animal'),
|
||||
];
|
||||
|
||||
return $form;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@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']]));
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,55 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\block_test\Form\TestForm.
|
||||
*/
|
||||
|
||||
namespace Drupal\block_test\Form;
|
||||
|
||||
use Drupal\Core\Form\FormBase;
|
||||
use Drupal\Core\Form\FormStateInterface;
|
||||
|
||||
class TestForm extends FormBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getFormId() {
|
||||
return 'block_test_form_test';
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function buildForm(array $form, FormStateInterface $form_state) {
|
||||
$form['email'] = [
|
||||
'#type' => 'email',
|
||||
'#title' => $this->t('Your .com email address.')
|
||||
];
|
||||
|
||||
$form['show'] = [
|
||||
'#type' => 'submit',
|
||||
'#value' => $this->t('Submit'),
|
||||
];
|
||||
|
||||
return $form;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function validateForm(array &$form, FormStateInterface $form_state) {
|
||||
if (strpos($form_state->getValue('email'), '.com') === FALSE) {
|
||||
$form_state->setErrorByName('email', $this->t('This is not a .com email address.'));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function submitForm(array &$form, FormStateInterface $form_state) {
|
||||
drupal_set_message($this->t('Your email address is @email', ['@email' => $form['email']['#value']]));
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\block_test\Plugin\Block\TestFormBlock.
|
||||
*/
|
||||
|
||||
namespace Drupal\block_test\Plugin\Block;
|
||||
|
||||
use Drupal\Core\Block\BlockBase;
|
||||
|
||||
/**
|
||||
* Provides a block to test caching.
|
||||
*
|
||||
* @Block(
|
||||
* id = "test_form_in_block",
|
||||
* admin_label = @Translation("Test form block caching")
|
||||
* )
|
||||
*/
|
||||
class TestFormBlock extends BlockBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function build() {
|
||||
return \Drupal::formBuilder()->getForm('Drupal\block_test\Form\TestForm');
|
||||
}
|
||||
|
||||
}
|
|
@ -10,10 +10,10 @@ namespace Drupal\block_test\Plugin\Condition;
|
|||
use Drupal\Core\Condition\ConditionPluginBase;
|
||||
|
||||
/**
|
||||
* Provides a 'baloney.spam' condition.
|
||||
* Provides a 'baloney_spam' condition.
|
||||
*
|
||||
* @Condition(
|
||||
* id = "baloney.spam",
|
||||
* id = "baloney_spam",
|
||||
* label = @Translation("Baloney spam"),
|
||||
* )
|
||||
*
|
||||
|
|
|
@ -25,7 +25,6 @@ class BlockTest extends MigrateSqlSourceTestCase {
|
|||
protected $migrationConfiguration = array(
|
||||
// The ID of the entity, can be any string.
|
||||
'id' => 'test',
|
||||
'idlist' => array(),
|
||||
'source' => array(
|
||||
'plugin' => 'd6_block',
|
||||
),
|
||||
|
|
Reference in a new issue