Move all files to 2017/
This commit is contained in:
parent
ac7370f67f
commit
2875863330
15717 changed files with 0 additions and 0 deletions
167
2017/web/core/modules/block/src/BlockAccessControlHandler.php
Normal file
167
2017/web/core/modules/block/src/BlockAccessControlHandler.php
Normal file
|
@ -0,0 +1,167 @@
|
|||
<?php
|
||||
|
||||
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;
|
||||
use Drupal\Core\Condition\ConditionAccessResolverTrait;
|
||||
use Drupal\Core\Entity\EntityAccessControlHandler;
|
||||
use Drupal\Core\Entity\EntityHandlerInterface;
|
||||
use Drupal\Core\Entity\EntityInterface;
|
||||
use Drupal\Core\Entity\EntityTypeInterface;
|
||||
use Drupal\Core\Plugin\Context\ContextHandlerInterface;
|
||||
use Drupal\Core\Plugin\Context\ContextRepositoryInterface;
|
||||
use Drupal\Core\Plugin\ContextAwarePluginInterface;
|
||||
use Drupal\Core\Session\AccountInterface;
|
||||
use Symfony\Component\DependencyInjection\ContainerInterface;
|
||||
|
||||
/**
|
||||
* Defines the access control handler for the block entity type.
|
||||
*
|
||||
* @see \Drupal\block\Entity\Block
|
||||
*/
|
||||
class BlockAccessControlHandler extends EntityAccessControlHandler implements EntityHandlerInterface {
|
||||
|
||||
use ConditionAccessResolverTrait;
|
||||
|
||||
/**
|
||||
* The plugin context handler.
|
||||
*
|
||||
* @var \Drupal\Core\Plugin\Context\ContextHandlerInterface
|
||||
*/
|
||||
protected $contextHandler;
|
||||
|
||||
/**
|
||||
* The context manager service.
|
||||
*
|
||||
* @var \Drupal\Core\Plugin\Context\ContextRepositoryInterface
|
||||
*/
|
||||
protected $contextRepository;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function createInstance(ContainerInterface $container, EntityTypeInterface $entity_type) {
|
||||
return new static(
|
||||
$entity_type,
|
||||
$container->get('context.handler'),
|
||||
$container->get('context.repository')
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs the block access control handler instance
|
||||
*
|
||||
* @param \Drupal\Core\Entity\EntityTypeInterface $entity_type
|
||||
* The entity type definition.
|
||||
* @param \Drupal\Core\Plugin\Context\ContextHandlerInterface $context_handler
|
||||
* The ContextHandler for applying contexts to conditions properly.
|
||||
* @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) {
|
||||
parent::__construct($entity_type);
|
||||
$this->contextHandler = $context_handler;
|
||||
$this->contextRepository = $context_repository;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function checkAccess(EntityInterface $entity, $operation, AccountInterface $account) {
|
||||
/** @var \Drupal\block\BlockInterface $entity */
|
||||
if ($operation != 'view') {
|
||||
return parent::checkAccess($entity, $operation, $account);
|
||||
}
|
||||
|
||||
// Don't grant access to disabled blocks.
|
||||
if (!$entity->status()) {
|
||||
return AccessResult::forbidden()->addCacheableDependency($entity);
|
||||
}
|
||||
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;
|
||||
}
|
||||
}
|
||||
$conditions[$condition_id] = $condition;
|
||||
}
|
||||
|
||||
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. 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();
|
||||
try {
|
||||
if ($block_plugin instanceof ContextAwarePluginInterface) {
|
||||
$contexts = $this->contextRepository->getRuntimeContexts(array_values($block_plugin->getContextMapping()));
|
||||
$this->contextHandler->applyContextMapping($block_plugin, $contexts);
|
||||
}
|
||||
$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) {
|
||||
// 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);
|
||||
}
|
||||
}
|
||||
else {
|
||||
$access = AccessResult::forbidden();
|
||||
}
|
||||
|
||||
$this->mergeCacheabilityFromConditions($access, $conditions);
|
||||
|
||||
// Ensure that access is evaluated again when the block changes.
|
||||
return $access->addCacheableDependency($entity);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Merges cacheable metadata from conditions onto the access result object.
|
||||
*
|
||||
* @param \Drupal\Core\Access\AccessResult $access
|
||||
* The access result object.
|
||||
* @param \Drupal\Core\Condition\ConditionInterface[] $conditions
|
||||
* List of visibility conditions.
|
||||
*/
|
||||
protected function mergeCacheabilityFromConditions(AccessResult $access, array $conditions) {
|
||||
foreach ($conditions as $condition) {
|
||||
if ($condition instanceof CacheableDependencyInterface) {
|
||||
$access->addCacheTags($condition->getCacheTags());
|
||||
$access->addCacheContexts($condition->getCacheContexts());
|
||||
$access->setCacheMaxAge(Cache::mergeMaxAges($access->getCacheMaxAge(), $condition->getCacheMaxAge()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
451
2017/web/core/modules/block/src/BlockForm.php
Normal file
451
2017/web/core/modules/block/src/BlockForm.php
Normal file
|
@ -0,0 +1,451 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\block;
|
||||
|
||||
use Drupal\Component\Utility\Html;
|
||||
use Drupal\Core\Plugin\PluginFormFactoryInterface;
|
||||
use Drupal\Core\Block\BlockPluginInterface;
|
||||
use Drupal\Core\Entity\EntityForm;
|
||||
use Drupal\Core\Entity\EntityManagerInterface;
|
||||
use Drupal\Core\Executable\ExecutableManagerInterface;
|
||||
use Drupal\Core\Extension\ThemeHandlerInterface;
|
||||
use Drupal\Core\Form\FormStateInterface;
|
||||
use Drupal\Core\Form\SubformState;
|
||||
use Drupal\Core\Language\LanguageManagerInterface;
|
||||
use Drupal\Core\Plugin\ContextAwarePluginInterface;
|
||||
use Drupal\Core\Plugin\Context\ContextRepositoryInterface;
|
||||
use Drupal\Core\Plugin\PluginWithFormsInterface;
|
||||
use Symfony\Component\DependencyInjection\ContainerInterface;
|
||||
|
||||
/**
|
||||
* Provides form for block instance forms.
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
class BlockForm extends EntityForm {
|
||||
|
||||
/**
|
||||
* The block entity.
|
||||
*
|
||||
* @var \Drupal\block\BlockInterface
|
||||
*/
|
||||
protected $entity;
|
||||
|
||||
/**
|
||||
* The block storage.
|
||||
*
|
||||
* @var \Drupal\Core\Entity\EntityStorageInterface
|
||||
*/
|
||||
protected $storage;
|
||||
|
||||
/**
|
||||
* The condition plugin manager.
|
||||
*
|
||||
* @var \Drupal\Core\Condition\ConditionManager
|
||||
*/
|
||||
protected $manager;
|
||||
|
||||
/**
|
||||
* The event dispatcher service.
|
||||
*
|
||||
* @var \Symfony\Component\EventDispatcher\EventDispatcherInterface
|
||||
*/
|
||||
protected $dispatcher;
|
||||
|
||||
/**
|
||||
* The language manager service.
|
||||
*
|
||||
* @var \Drupal\Core\Language\LanguageManagerInterface
|
||||
*/
|
||||
protected $language;
|
||||
|
||||
/**
|
||||
* The theme handler.
|
||||
*
|
||||
* @var \Drupal\Core\Extension\ThemeHandler
|
||||
*/
|
||||
protected $themeHandler;
|
||||
|
||||
/**
|
||||
* The context repository service.
|
||||
*
|
||||
* @var \Drupal\Core\Plugin\Context\ContextRepositoryInterface
|
||||
*/
|
||||
protected $contextRepository;
|
||||
|
||||
/**
|
||||
* The plugin form manager.
|
||||
*
|
||||
* @var \Drupal\Core\Plugin\PluginFormFactoryInterface
|
||||
*/
|
||||
protected $pluginFormFactory;
|
||||
|
||||
/**
|
||||
* Constructs a BlockForm object.
|
||||
*
|
||||
* @param \Drupal\Core\Entity\EntityManagerInterface $entity_manager
|
||||
* The entity manager.
|
||||
* @param \Drupal\Core\Executable\ExecutableManagerInterface $manager
|
||||
* The ConditionManager for building the visibility UI.
|
||||
* @param \Drupal\Core\Plugin\Context\ContextRepositoryInterface $context_repository
|
||||
* The lazy context repository service.
|
||||
* @param \Drupal\Core\Language\LanguageManagerInterface $language
|
||||
* The language manager.
|
||||
* @param \Drupal\Core\Extension\ThemeHandlerInterface $theme_handler
|
||||
* The theme handler.
|
||||
* @param \Drupal\Core\Plugin\PluginFormFactoryInterface $plugin_form_manager
|
||||
* The plugin form manager.
|
||||
*/
|
||||
public function __construct(EntityManagerInterface $entity_manager, ExecutableManagerInterface $manager, ContextRepositoryInterface $context_repository, LanguageManagerInterface $language, ThemeHandlerInterface $theme_handler, PluginFormFactoryInterface $plugin_form_manager) {
|
||||
$this->storage = $entity_manager->getStorage('block');
|
||||
$this->manager = $manager;
|
||||
$this->contextRepository = $context_repository;
|
||||
$this->language = $language;
|
||||
$this->themeHandler = $theme_handler;
|
||||
$this->pluginFormFactory = $plugin_form_manager;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function create(ContainerInterface $container) {
|
||||
return new static(
|
||||
$container->get('entity.manager'),
|
||||
$container->get('plugin.manager.condition'),
|
||||
$container->get('context.repository'),
|
||||
$container->get('language_manager'),
|
||||
$container->get('theme_handler'),
|
||||
$container->get('plugin_form.factory')
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function form(array $form, FormStateInterface $form_state) {
|
||||
$entity = $this->entity;
|
||||
|
||||
// Store theme settings in $form_state for use below.
|
||||
if (!$theme = $entity->getTheme()) {
|
||||
$theme = $this->config('system.theme')->get('default');
|
||||
}
|
||||
$form_state->set('block_theme', $theme);
|
||||
|
||||
// Store the gathered contexts in the form state for other objects to use
|
||||
// during form building.
|
||||
$form_state->setTemporaryValue('gathered_contexts', $this->contextRepository->getAvailableContexts());
|
||||
|
||||
$form['#tree'] = TRUE;
|
||||
$form['settings'] = [];
|
||||
$subform_state = SubformState::createForSubform($form['settings'], $form, $form_state);
|
||||
$form['settings'] = $this->getPluginForm($entity->getPlugin())->buildConfigurationForm($form['settings'], $subform_state);
|
||||
$form['visibility'] = $this->buildVisibilityInterface([], $form_state);
|
||||
|
||||
// If creating a new block, calculate a safe default machine name.
|
||||
$form['id'] = [
|
||||
'#type' => 'machine_name',
|
||||
'#maxlength' => 64,
|
||||
'#description' => $this->t('A unique name for this block instance. Must be alpha-numeric and underscore separated.'),
|
||||
'#default_value' => !$entity->isNew() ? $entity->id() : $this->getUniqueMachineName($entity),
|
||||
'#machine_name' => [
|
||||
'exists' => '\Drupal\block\Entity\Block::load',
|
||||
'replace_pattern' => '[^a-z0-9_.]+',
|
||||
'source' => ['settings', 'label'],
|
||||
],
|
||||
'#required' => TRUE,
|
||||
'#disabled' => !$entity->isNew(),
|
||||
];
|
||||
|
||||
// Theme settings.
|
||||
if ($entity->getTheme()) {
|
||||
$form['theme'] = [
|
||||
'#type' => 'value',
|
||||
'#value' => $theme,
|
||||
];
|
||||
}
|
||||
else {
|
||||
$theme_options = [];
|
||||
foreach ($this->themeHandler->listInfo() as $theme_name => $theme_info) {
|
||||
if (!empty($theme_info->status)) {
|
||||
$theme_options[$theme_name] = $theme_info->info['name'];
|
||||
}
|
||||
}
|
||||
$form['theme'] = [
|
||||
'#type' => 'select',
|
||||
'#options' => $theme_options,
|
||||
'#title' => t('Theme'),
|
||||
'#default_value' => $theme,
|
||||
'#ajax' => [
|
||||
'callback' => '::themeSwitch',
|
||||
'wrapper' => 'edit-block-region-wrapper',
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
// Hidden weight setting.
|
||||
$weight = $entity->isNew() ? $this->getRequest()->query->get('weight', 0) : $entity->getWeight();
|
||||
$form['weight'] = [
|
||||
'#type' => 'hidden',
|
||||
'#default_value' => $weight,
|
||||
];
|
||||
|
||||
// Region settings.
|
||||
$entity_region = $entity->getRegion();
|
||||
$region = $entity->isNew() ? $this->getRequest()->query->get('region', $entity_region) : $entity_region;
|
||||
$form['region'] = [
|
||||
'#type' => 'select',
|
||||
'#title' => $this->t('Region'),
|
||||
'#description' => $this->t('Select the region where this block should be displayed.'),
|
||||
'#default_value' => $region,
|
||||
'#required' => TRUE,
|
||||
'#options' => system_region_list($theme, REGIONS_VISIBLE),
|
||||
'#prefix' => '<div id="edit-block-region-wrapper">',
|
||||
'#suffix' => '</div>',
|
||||
];
|
||||
$form['#attached']['library'][] = 'block/drupal.block.admin';
|
||||
return $form;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles switching the available regions based on the selected theme.
|
||||
*/
|
||||
public function themeSwitch($form, FormStateInterface $form_state) {
|
||||
$form['region']['#options'] = system_region_list($form_state->getValue('theme'), REGIONS_VISIBLE);
|
||||
return $form['region'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function for building the visibility UI form.
|
||||
*
|
||||
* @param array $form
|
||||
* An associative array containing the structure of the form.
|
||||
* @param \Drupal\Core\Form\FormStateInterface $form_state
|
||||
* The current state of the form.
|
||||
*
|
||||
* @return array
|
||||
* The form array with the visibility UI added in.
|
||||
*/
|
||||
protected function buildVisibilityInterface(array $form, FormStateInterface $form_state) {
|
||||
$form['visibility_tabs'] = [
|
||||
'#type' => 'vertical_tabs',
|
||||
'#title' => $this->t('Visibility'),
|
||||
'#parents' => ['visibility_tabs'],
|
||||
'#attached' => [
|
||||
'library' => [
|
||||
'block/drupal.block',
|
||||
],
|
||||
],
|
||||
];
|
||||
// @todo Allow list of conditions to be configured in
|
||||
// https://www.drupal.org/node/2284687.
|
||||
$visibility = $this->entity->getVisibility();
|
||||
$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;
|
||||
}
|
||||
// Don't display the language condition until we have multiple languages.
|
||||
if ($condition_id == 'language' && !$this->language->isMultilingual()) {
|
||||
continue;
|
||||
}
|
||||
/** @var \Drupal\Core\Condition\ConditionInterface $condition */
|
||||
$condition = $this->manager->createInstance($condition_id, isset($visibility[$condition_id]) ? $visibility[$condition_id] : []);
|
||||
$form_state->set(['conditions', $condition_id], $condition);
|
||||
$condition_form = $condition->buildConfigurationForm([], $form_state);
|
||||
$condition_form['#type'] = 'details';
|
||||
$condition_form['#title'] = $condition->getPluginDefinition()['label'];
|
||||
$condition_form['#group'] = 'visibility_tabs';
|
||||
$form[$condition_id] = $condition_form;
|
||||
}
|
||||
|
||||
if (isset($form['node_type'])) {
|
||||
$form['node_type']['#title'] = $this->t('Content types');
|
||||
$form['node_type']['bundles']['#title'] = $this->t('Content types');
|
||||
$form['node_type']['negate']['#type'] = 'value';
|
||||
$form['node_type']['negate']['#title_display'] = 'invisible';
|
||||
$form['node_type']['negate']['#value'] = $form['node_type']['negate']['#default_value'];
|
||||
}
|
||||
if (isset($form['user_role'])) {
|
||||
$form['user_role']['#title'] = $this->t('Roles');
|
||||
unset($form['user_role']['roles']['#description']);
|
||||
$form['user_role']['negate']['#type'] = 'value';
|
||||
$form['user_role']['negate']['#value'] = $form['user_role']['negate']['#default_value'];
|
||||
}
|
||||
if (isset($form['request_path'])) {
|
||||
$form['request_path']['#title'] = $this->t('Pages');
|
||||
$form['request_path']['negate']['#type'] = 'radios';
|
||||
$form['request_path']['negate']['#default_value'] = (int) $form['request_path']['negate']['#default_value'];
|
||||
$form['request_path']['negate']['#title_display'] = 'invisible';
|
||||
$form['request_path']['negate']['#options'] = [
|
||||
$this->t('Show for the listed pages'),
|
||||
$this->t('Hide for the listed pages'),
|
||||
];
|
||||
}
|
||||
if (isset($form['language'])) {
|
||||
$form['language']['negate']['#type'] = 'value';
|
||||
$form['language']['negate']['#value'] = $form['language']['negate']['#default_value'];
|
||||
}
|
||||
return $form;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function actions(array $form, FormStateInterface $form_state) {
|
||||
$actions = parent::actions($form, $form_state);
|
||||
$actions['submit']['#value'] = $this->t('Save block');
|
||||
$actions['delete']['#title'] = $this->t('Remove block');
|
||||
return $actions;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function validateForm(array &$form, FormStateInterface $form_state) {
|
||||
parent::validateForm($form, $form_state);
|
||||
|
||||
$form_state->setValue('weight', (int) $form_state->getValue('weight'));
|
||||
// The Block Entity form puts all block plugin form elements in the
|
||||
// settings form element, so just pass that to the block for validation.
|
||||
$this->getPluginForm($this->entity->getPlugin())->validateConfigurationForm($form['settings'], SubformState::createForSubform($form['settings'], $form, $form_state));
|
||||
$this->validateVisibility($form, $form_state);
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function to independently validate the visibility UI.
|
||||
*
|
||||
* @param array $form
|
||||
* A nested array form elements comprising the form.
|
||||
* @param \Drupal\Core\Form\FormStateInterface $form_state
|
||||
* The current state of the form.
|
||||
*/
|
||||
protected function validateVisibility(array $form, FormStateInterface $form_state) {
|
||||
// Validate visibility condition settings.
|
||||
foreach ($form_state->getValue('visibility') as $condition_id => $values) {
|
||||
// All condition plugins use 'negate' as a Boolean in their schema.
|
||||
// However, certain form elements may return it as 0/1. Cast here to
|
||||
// ensure the data is in the expected type.
|
||||
if (array_key_exists('negate', $values)) {
|
||||
$form_state->setValue(['visibility', $condition_id, 'negate'], (bool) $values['negate']);
|
||||
}
|
||||
|
||||
// Allow the condition to validate the form.
|
||||
$condition = $form_state->get(['conditions', $condition_id]);
|
||||
$condition->validateConfigurationForm($form['visibility'][$condition_id], SubformState::createForSubform($form['visibility'][$condition_id], $form, $form_state));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function submitForm(array &$form, FormStateInterface $form_state) {
|
||||
parent::submitForm($form, $form_state);
|
||||
|
||||
$entity = $this->entity;
|
||||
// The Block Entity form puts all block plugin form elements in the
|
||||
// settings form element, so just pass that to the block for submission.
|
||||
$sub_form_state = SubformState::createForSubform($form['settings'], $form, $form_state);
|
||||
// Call the plugin submit handler.
|
||||
$block = $entity->getPlugin();
|
||||
$this->getPluginForm($block)->submitConfigurationForm($form, $sub_form_state);
|
||||
// If this block is context-aware, set the context mapping.
|
||||
if ($block instanceof ContextAwarePluginInterface && $block->getContextDefinitions()) {
|
||||
$context_mapping = $sub_form_state->getValue('context_mapping', []);
|
||||
$block->setContextMapping($context_mapping);
|
||||
}
|
||||
|
||||
$this->submitVisibility($form, $form_state);
|
||||
|
||||
// Save the settings of the plugin.
|
||||
$entity->save();
|
||||
|
||||
$this->messenger()->addStatus($this->t('The block configuration has been saved.'));
|
||||
$form_state->setRedirect(
|
||||
'block.admin_display_theme',
|
||||
[
|
||||
'theme' => $form_state->getValue('theme'),
|
||||
],
|
||||
['query' => ['block-placement' => Html::getClass($this->entity->id())]]
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function to independently submit the visibility UI.
|
||||
*
|
||||
* @param array $form
|
||||
* A nested array form elements comprising the form.
|
||||
* @param \Drupal\Core\Form\FormStateInterface $form_state
|
||||
* The current state of the form.
|
||||
*/
|
||||
protected function submitVisibility(array $form, FormStateInterface $form_state) {
|
||||
foreach ($form_state->getValue('visibility') as $condition_id => $values) {
|
||||
// Allow the condition to submit the form.
|
||||
$condition = $form_state->get(['conditions', $condition_id]);
|
||||
$condition->submitConfigurationForm($form['visibility'][$condition_id], SubformState::createForSubform($form['visibility'][$condition_id], $form, $form_state));
|
||||
|
||||
// Setting conditions' context mappings is the plugins' responsibility.
|
||||
// This code exists for backwards compatibility, because
|
||||
// \Drupal\Core\Condition\ConditionPluginBase::submitConfigurationForm()
|
||||
// did not set its own mappings until Drupal 8.2
|
||||
// @todo Remove the code that sets context mappings in Drupal 9.0.0.
|
||||
if ($condition instanceof ContextAwarePluginInterface) {
|
||||
$context_mapping = isset($values['context_mapping']) ? $values['context_mapping'] : [];
|
||||
$condition->setContextMapping($context_mapping);
|
||||
}
|
||||
|
||||
$condition_configuration = $condition->getConfiguration();
|
||||
// Update the visibility conditions on the block.
|
||||
$this->entity->getVisibilityConditions()->addInstanceId($condition_id, $condition_configuration);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a unique machine name for a block.
|
||||
*
|
||||
* @param \Drupal\block\BlockInterface $block
|
||||
* The block entity.
|
||||
*
|
||||
* @return string
|
||||
* Returns the unique name.
|
||||
*/
|
||||
public function getUniqueMachineName(BlockInterface $block) {
|
||||
$suggestion = $block->getPlugin()->getMachineNameSuggestion();
|
||||
|
||||
// Get all the blocks which starts with the suggested machine name.
|
||||
$query = $this->storage->getQuery();
|
||||
$query->condition('id', $suggestion, 'CONTAINS');
|
||||
$block_ids = $query->execute();
|
||||
|
||||
$block_ids = array_map(function ($block_id) {
|
||||
$parts = explode('.', $block_id);
|
||||
return end($parts);
|
||||
}, $block_ids);
|
||||
|
||||
// Iterate through potential IDs until we get a new one. E.g.
|
||||
// 'plugin', 'plugin_2', 'plugin_3', etc.
|
||||
$count = 1;
|
||||
$machine_default = $suggestion;
|
||||
while (in_array($machine_default, $block_ids)) {
|
||||
$machine_default = $suggestion . '_' . ++$count;
|
||||
}
|
||||
return $machine_default;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the plugin form for a given block and operation.
|
||||
*
|
||||
* @param \Drupal\Core\Block\BlockPluginInterface $block
|
||||
* The block plugin.
|
||||
*
|
||||
* @return \Drupal\Core\Plugin\PluginFormInterface
|
||||
* The plugin form for the block.
|
||||
*/
|
||||
protected function getPluginForm(BlockPluginInterface $block) {
|
||||
if ($block instanceof PluginWithFormsInterface) {
|
||||
return $this->pluginFormFactory->createInstance($block, 'configure');
|
||||
}
|
||||
return $block;
|
||||
}
|
||||
|
||||
}
|
143
2017/web/core/modules/block/src/BlockInterface.php
Normal file
143
2017/web/core/modules/block/src/BlockInterface.php
Normal file
|
@ -0,0 +1,143 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\block;
|
||||
|
||||
use Drupal\Core\Block\BlockPluginInterface;
|
||||
use Drupal\Core\Config\Entity\ConfigEntityInterface;
|
||||
|
||||
/**
|
||||
* Provides an interface defining a block entity.
|
||||
*/
|
||||
interface BlockInterface extends ConfigEntityInterface {
|
||||
|
||||
/**
|
||||
* Indicates the block label (title) should be displayed to end users.
|
||||
*
|
||||
* @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;
|
||||
|
||||
/**
|
||||
* Denotes that a block is not enabled in any region and should not be shown.
|
||||
*
|
||||
* @deprecated Scheduled for removal in Drupal 9.0.0.
|
||||
*/
|
||||
const BLOCK_REGION_NONE = -1;
|
||||
|
||||
/**
|
||||
* Returns the plugin instance.
|
||||
*
|
||||
* @return \Drupal\Core\Block\BlockPluginInterface
|
||||
* The plugin instance for this block.
|
||||
*/
|
||||
public function getPlugin();
|
||||
|
||||
/**
|
||||
* Returns the plugin ID.
|
||||
*
|
||||
* @return string
|
||||
* The plugin ID for this block.
|
||||
*/
|
||||
public function getPluginId();
|
||||
|
||||
/**
|
||||
* Returns the region this block is placed in.
|
||||
*
|
||||
* @return string
|
||||
* The region this block is placed in.
|
||||
*/
|
||||
public function getRegion();
|
||||
|
||||
/**
|
||||
* Returns the theme ID.
|
||||
*
|
||||
* @return string
|
||||
* The theme ID for this block instance.
|
||||
*/
|
||||
public function getTheme();
|
||||
|
||||
/**
|
||||
* Returns an array of visibility condition configurations.
|
||||
*
|
||||
* @return array
|
||||
* An array of visibility condition configuration keyed by the condition ID.
|
||||
*/
|
||||
public function getVisibility();
|
||||
|
||||
/**
|
||||
* Gets conditions for this block.
|
||||
*
|
||||
* @return \Drupal\Core\Condition\ConditionInterface[]|\Drupal\Core\Condition\ConditionPluginCollection
|
||||
* An array or collection of configured condition plugins.
|
||||
*/
|
||||
public function getVisibilityConditions();
|
||||
|
||||
/**
|
||||
* Gets a visibility condition plugin instance.
|
||||
*
|
||||
* @param string $instance_id
|
||||
* The condition plugin instance ID.
|
||||
*
|
||||
* @return \Drupal\Core\Condition\ConditionInterface
|
||||
* A condition plugin.
|
||||
*/
|
||||
public function getVisibilityCondition($instance_id);
|
||||
|
||||
/**
|
||||
* Sets the visibility condition configuration.
|
||||
*
|
||||
* @param string $instance_id
|
||||
* The condition instance ID.
|
||||
* @param array $configuration
|
||||
* The condition configuration.
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setVisibilityConfig($instance_id, array $configuration);
|
||||
|
||||
/**
|
||||
* Returns the weight of this block (used for sorting).
|
||||
*
|
||||
* @return int
|
||||
* The block weight.
|
||||
*/
|
||||
public function getWeight();
|
||||
|
||||
/**
|
||||
* Sets the region this block is placed in.
|
||||
*
|
||||
* @param string $region
|
||||
* The region to place this block in.
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setRegion($region);
|
||||
|
||||
/**
|
||||
* Sets the block weight.
|
||||
*
|
||||
* @param int $weight
|
||||
* The desired weight.
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setWeight($weight);
|
||||
|
||||
/**
|
||||
* Creates a duplicate of the block entity.
|
||||
*
|
||||
* @param string $new_id
|
||||
* (optional) The new ID on the duplicate block.
|
||||
* @param string $new_theme
|
||||
* (optional) The theme on the duplicate block.
|
||||
*
|
||||
* @return static
|
||||
* A clone of $this with all identifiers unset, so saving it inserts a new
|
||||
* entity into the storage system.
|
||||
*/
|
||||
public function createDuplicateBlock($new_id = NULL, $new_theme = NULL);
|
||||
|
||||
}
|
393
2017/web/core/modules/block/src/BlockListBuilder.php
Normal file
393
2017/web/core/modules/block/src/BlockListBuilder.php
Normal file
|
@ -0,0 +1,393 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\block;
|
||||
|
||||
use Drupal\Component\Utility\Html;
|
||||
use Drupal\Component\Serialization\Json;
|
||||
use Drupal\Core\Config\Entity\ConfigEntityListBuilder;
|
||||
use Drupal\Core\Entity\EntityInterface;
|
||||
use Drupal\Core\Entity\EntityStorageInterface;
|
||||
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;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
|
||||
/**
|
||||
* Defines a class to build a listing of block entities.
|
||||
*
|
||||
* @see \Drupal\block\Entity\Block
|
||||
*/
|
||||
class BlockListBuilder extends ConfigEntityListBuilder implements FormInterface {
|
||||
|
||||
/**
|
||||
* The theme containing the blocks.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $theme;
|
||||
|
||||
/**
|
||||
* The current request.
|
||||
*
|
||||
* @var \Symfony\Component\HttpFoundation\Request
|
||||
*/
|
||||
protected $request;
|
||||
|
||||
/**
|
||||
* The theme manager.
|
||||
*
|
||||
* @var \Drupal\Core\Theme\ThemeManagerInterface
|
||||
*/
|
||||
protected $themeManager;
|
||||
|
||||
/**
|
||||
* The form builder.
|
||||
*
|
||||
* @var \Drupal\Core\Form\FormBuilderInterface
|
||||
*/
|
||||
protected $formBuilder;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected $limit = FALSE;
|
||||
|
||||
/**
|
||||
* The messenger.
|
||||
*
|
||||
* @var \Drupal\Core\Messenger\MessengerInterface
|
||||
*/
|
||||
protected $messenger;
|
||||
|
||||
/**
|
||||
* Constructs a new BlockListBuilder object.
|
||||
*
|
||||
* @param \Drupal\Core\Entity\EntityTypeInterface $entity_type
|
||||
* The entity type definition.
|
||||
* @param \Drupal\Core\Entity\EntityStorageInterface $storage
|
||||
* The entity storage class.
|
||||
* @param \Drupal\Core\Theme\ThemeManagerInterface $theme_manager
|
||||
* The theme manager.
|
||||
* @param \Drupal\Core\Form\FormBuilderInterface $form_builder
|
||||
* The 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;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function createInstance(ContainerInterface $container, EntityTypeInterface $entity_type) {
|
||||
return new static(
|
||||
$entity_type,
|
||||
$container->get('entity.manager')->getStorage($entity_type->id()),
|
||||
$container->get('theme.manager'),
|
||||
$container->get('form_builder'),
|
||||
$container->get('messenger')
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* @param string|null $theme
|
||||
* (optional) The theme to display the blocks for. If NULL, the current
|
||||
* theme will be used.
|
||||
* @param \Symfony\Component\HttpFoundation\Request $request
|
||||
* The current request.
|
||||
*
|
||||
* @return array
|
||||
* The block list as a renderable array.
|
||||
*/
|
||||
public function render($theme = NULL, Request $request = NULL) {
|
||||
$this->request = $request;
|
||||
$this->theme = $theme;
|
||||
|
||||
return $this->formBuilder->getForm($this);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getFormId() {
|
||||
return 'block_admin_display_form';
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function buildForm(array $form, FormStateInterface $form_state) {
|
||||
$form['#attached']['library'][] = 'core/drupal.tableheader';
|
||||
$form['#attached']['library'][] = 'block/drupal.block';
|
||||
$form['#attached']['library'][] = 'block/drupal.block.admin';
|
||||
$form['#attributes']['class'][] = 'clearfix';
|
||||
|
||||
// Build the form tree.
|
||||
$form['blocks'] = $this->buildBlocksForm();
|
||||
|
||||
$form['actions'] = [
|
||||
'#tree' => FALSE,
|
||||
'#type' => 'actions',
|
||||
];
|
||||
$form['actions']['submit'] = [
|
||||
'#type' => 'submit',
|
||||
'#value' => $this->t('Save blocks'),
|
||||
'#button_type' => 'primary',
|
||||
];
|
||||
|
||||
return $form;
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds the main "Blocks" portion of the form.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function buildBlocksForm() {
|
||||
// Build blocks first for each region.
|
||||
$blocks = [];
|
||||
$entities = $this->load();
|
||||
/** @var \Drupal\block\BlockInterface[] $entities */
|
||||
foreach ($entities as $entity_id => $entity) {
|
||||
$definition = $entity->getPlugin()->getPluginDefinition();
|
||||
$blocks[$entity->getRegion()][$entity_id] = [
|
||||
'label' => $entity->label(),
|
||||
'entity_id' => $entity_id,
|
||||
'weight' => $entity->getWeight(),
|
||||
'entity' => $entity,
|
||||
'category' => $definition['category'],
|
||||
'status' => $entity->status(),
|
||||
];
|
||||
}
|
||||
|
||||
$form = [
|
||||
'#type' => 'table',
|
||||
'#header' => [
|
||||
$this->t('Block'),
|
||||
$this->t('Category'),
|
||||
$this->t('Region'),
|
||||
$this->t('Weight'),
|
||||
$this->t('Operations'),
|
||||
],
|
||||
'#attributes' => [
|
||||
'id' => 'blocks',
|
||||
],
|
||||
];
|
||||
|
||||
// Weights range from -delta to +delta, so delta should be at least half
|
||||
// of the amount of blocks present. This makes sure all blocks in the same
|
||||
// region get an unique weight.
|
||||
$weight_delta = round(count($entities) / 2);
|
||||
|
||||
$placement = FALSE;
|
||||
if ($this->request->query->has('block-placement')) {
|
||||
$placement = $this->request->query->get('block-placement');
|
||||
$form['#attached']['drupalSettings']['blockPlacement'] = $placement;
|
||||
// Remove the block placement from the current request so that it is not
|
||||
// passed on to any redirect destinations.
|
||||
$this->request->query->remove('block-placement');
|
||||
}
|
||||
|
||||
// Loop over each region and build blocks.
|
||||
$regions = $this->systemRegionList($this->getThemeName(), REGIONS_VISIBLE);
|
||||
foreach ($regions as $region => $title) {
|
||||
$form['#tabledrag'][] = [
|
||||
'action' => 'match',
|
||||
'relationship' => 'sibling',
|
||||
'group' => 'block-region-select',
|
||||
'subgroup' => 'block-region-' . $region,
|
||||
'hidden' => FALSE,
|
||||
];
|
||||
$form['#tabledrag'][] = [
|
||||
'action' => 'order',
|
||||
'relationship' => 'sibling',
|
||||
'group' => 'block-weight',
|
||||
'subgroup' => 'block-weight-' . $region,
|
||||
];
|
||||
|
||||
$form['region-' . $region] = [
|
||||
'#attributes' => [
|
||||
'class' => ['region-title', 'region-title-' . $region],
|
||||
'no_striping' => TRUE,
|
||||
],
|
||||
];
|
||||
$form['region-' . $region]['title'] = [
|
||||
'#theme_wrappers' => [
|
||||
'container' => [
|
||||
'#attributes' => ['class' => 'region-title__action'],
|
||||
],
|
||||
],
|
||||
'#prefix' => $title,
|
||||
'#type' => 'link',
|
||||
'#title' => $this->t('Place block <span class="visually-hidden">in the %region region</span>', ['%region' => $title]),
|
||||
'#url' => Url::fromRoute('block.admin_library', ['theme' => $this->getThemeName()], ['query' => ['region' => $region]]),
|
||||
'#wrapper_attributes' => [
|
||||
'colspan' => 5,
|
||||
],
|
||||
'#attributes' => [
|
||||
'class' => ['use-ajax', 'button', 'button--small'],
|
||||
'data-dialog-type' => 'modal',
|
||||
'data-dialog-options' => Json::encode([
|
||||
'width' => 700,
|
||||
]),
|
||||
],
|
||||
];
|
||||
|
||||
$form['region-' . $region . '-message'] = [
|
||||
'#attributes' => [
|
||||
'class' => [
|
||||
'region-message',
|
||||
'region-' . $region . '-message',
|
||||
empty($blocks[$region]) ? 'region-empty' : 'region-populated',
|
||||
],
|
||||
],
|
||||
];
|
||||
$form['region-' . $region . '-message']['message'] = [
|
||||
'#markup' => '<em>' . $this->t('No blocks in this region') . '</em>',
|
||||
'#wrapper_attributes' => [
|
||||
'colspan' => 5,
|
||||
],
|
||||
];
|
||||
|
||||
if (isset($blocks[$region])) {
|
||||
foreach ($blocks[$region] as $info) {
|
||||
$entity_id = $info['entity_id'];
|
||||
|
||||
$form[$entity_id] = [
|
||||
'#attributes' => [
|
||||
'class' => ['draggable'],
|
||||
],
|
||||
];
|
||||
$form[$entity_id]['#attributes']['class'][] = $info['status'] ? 'block-enabled' : 'block-disabled';
|
||||
if ($placement && $placement == Html::getClass($entity_id)) {
|
||||
$form[$entity_id]['#attributes']['class'][] = 'color-success';
|
||||
$form[$entity_id]['#attributes']['class'][] = 'js-block-placed';
|
||||
}
|
||||
$form[$entity_id]['info'] = [
|
||||
'#plain_text' => $info['status'] ? $info['label'] : $this->t('@label (disabled)', ['@label' => $info['label']]),
|
||||
'#wrapper_attributes' => [
|
||||
'class' => ['block'],
|
||||
],
|
||||
];
|
||||
$form[$entity_id]['type'] = [
|
||||
'#markup' => $info['category'],
|
||||
];
|
||||
$form[$entity_id]['region-theme']['region'] = [
|
||||
'#type' => 'select',
|
||||
'#default_value' => $region,
|
||||
'#required' => TRUE,
|
||||
'#title' => $this->t('Region for @block block', ['@block' => $info['label']]),
|
||||
'#title_display' => 'invisible',
|
||||
'#options' => $regions,
|
||||
'#attributes' => [
|
||||
'class' => ['block-region-select', 'block-region-' . $region],
|
||||
],
|
||||
'#parents' => ['blocks', $entity_id, 'region'],
|
||||
];
|
||||
$form[$entity_id]['region-theme']['theme'] = [
|
||||
'#type' => 'hidden',
|
||||
'#value' => $this->getThemeName(),
|
||||
'#parents' => ['blocks', $entity_id, 'theme'],
|
||||
];
|
||||
$form[$entity_id]['weight'] = [
|
||||
'#type' => 'weight',
|
||||
'#default_value' => $info['weight'],
|
||||
'#delta' => $weight_delta,
|
||||
'#title' => $this->t('Weight for @block block', ['@block' => $info['label']]),
|
||||
'#title_display' => 'invisible',
|
||||
'#attributes' => [
|
||||
'class' => ['block-weight', 'block-weight-' . $region],
|
||||
],
|
||||
];
|
||||
$form[$entity_id]['operations'] = $this->buildOperations($info['entity']);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Do not allow disabling the main system content block when it is present.
|
||||
if (isset($form['system_main']['region'])) {
|
||||
$form['system_main']['region']['#required'] = TRUE;
|
||||
}
|
||||
return $form;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the name of the theme used for this block listing.
|
||||
*
|
||||
* @return string
|
||||
* The name of the theme.
|
||||
*/
|
||||
protected function getThemeName() {
|
||||
// If no theme was specified, use the current theme.
|
||||
if (!$this->theme) {
|
||||
$this->theme = $this->themeManager->getActiveTheme()->getName();
|
||||
}
|
||||
return $this->theme;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function getEntityIds() {
|
||||
return $this->getStorage()->getQuery()
|
||||
->condition('theme', $this->getThemeName())
|
||||
->sort($this->entityType->getKey('id'))
|
||||
->execute();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getDefaultOperations(EntityInterface $entity) {
|
||||
$operations = parent::getDefaultOperations($entity);
|
||||
|
||||
if (isset($operations['edit'])) {
|
||||
$operations['edit']['title'] = $this->t('Configure');
|
||||
}
|
||||
|
||||
if (isset($operations['delete'])) {
|
||||
$operations['delete']['title'] = $this->t('Remove');
|
||||
}
|
||||
return $operations;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function validateForm(array &$form, FormStateInterface $form_state) {
|
||||
// No validation.
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function submitForm(array &$form, FormStateInterface $form_state) {
|
||||
$entities = $this->storage->loadMultiple(array_keys($form_state->getValue('blocks')));
|
||||
/** @var \Drupal\block\BlockInterface[] $entities */
|
||||
foreach ($entities as $entity_id => $entity) {
|
||||
$entity_values = $form_state->getValue(['blocks', $entity_id]);
|
||||
$entity->setWeight($entity_values['weight']);
|
||||
$entity->setRegion($entity_values['region']);
|
||||
$entity->save();
|
||||
}
|
||||
$this->messenger->addStatus($this->t('The block settings have been updated.'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Wraps system_region_list().
|
||||
*/
|
||||
protected function systemRegionList($theme, $show = REGIONS_ALL) {
|
||||
return system_region_list($theme, $show);
|
||||
}
|
||||
|
||||
}
|
70
2017/web/core/modules/block/src/BlockPluginCollection.php
Normal file
70
2017/web/core/modules/block/src/BlockPluginCollection.php
Normal file
|
@ -0,0 +1,70 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\block;
|
||||
|
||||
use Drupal\Component\Plugin\Exception\PluginException;
|
||||
use Drupal\Component\Plugin\PluginManagerInterface;
|
||||
use Drupal\Core\Plugin\DefaultSingleLazyPluginCollection;
|
||||
|
||||
/**
|
||||
* Provides a collection of block plugins.
|
||||
*/
|
||||
class BlockPluginCollection extends DefaultSingleLazyPluginCollection {
|
||||
|
||||
/**
|
||||
* The block ID this plugin collection belongs to.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $blockId;
|
||||
|
||||
/**
|
||||
* Constructs a new BlockPluginCollection.
|
||||
*
|
||||
* @param \Drupal\Component\Plugin\PluginManagerInterface $manager
|
||||
* The manager to be used for instantiating plugins.
|
||||
* @param string $instance_id
|
||||
* The ID of the plugin instance.
|
||||
* @param array $configuration
|
||||
* An array of configuration.
|
||||
* @param string $block_id
|
||||
* The unique ID of the block entity using this plugin.
|
||||
*/
|
||||
public function __construct(PluginManagerInterface $manager, $instance_id, array $configuration, $block_id) {
|
||||
parent::__construct($manager, $instance_id, $configuration);
|
||||
|
||||
$this->blockId = $block_id;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* @return \Drupal\Core\Block\BlockPluginInterface
|
||||
*/
|
||||
public function &get($instance_id) {
|
||||
return parent::get($instance_id);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function initializePlugin($instance_id) {
|
||||
if (!$instance_id) {
|
||||
throw new PluginException("The block '{$this->blockId}' did not specify a plugin.");
|
||||
}
|
||||
|
||||
try {
|
||||
parent::initializePlugin($instance_id);
|
||||
}
|
||||
catch (PluginException $e) {
|
||||
$module = $this->configuration['provider'];
|
||||
// Ignore blocks belonging to uninstalled modules, but re-throw valid
|
||||
// exceptions when the module is installed and the plugin is
|
||||
// misconfigured.
|
||||
if (!$module || \Drupal::moduleHandler()->moduleExists($module)) {
|
||||
throw $e;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
81
2017/web/core/modules/block/src/BlockRepository.php
Normal file
81
2017/web/core/modules/block/src/BlockRepository.php
Normal file
|
@ -0,0 +1,81 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\block;
|
||||
|
||||
use Drupal\Core\Cache\CacheableMetadata;
|
||||
use Drupal\Core\Entity\EntityManagerInterface;
|
||||
use Drupal\Core\Plugin\Context\ContextHandlerInterface;
|
||||
use Drupal\Core\Theme\ThemeManagerInterface;
|
||||
|
||||
/**
|
||||
* Provides a repository for Block config entities.
|
||||
*/
|
||||
class BlockRepository implements BlockRepositoryInterface {
|
||||
|
||||
/**
|
||||
* The block storage.
|
||||
*
|
||||
* @var \Drupal\Core\Entity\EntityStorageInterface
|
||||
*/
|
||||
protected $blockStorage;
|
||||
|
||||
/**
|
||||
* The theme manager.
|
||||
*
|
||||
* @var \Drupal\Core\Theme\ThemeManagerInterface
|
||||
*/
|
||||
protected $themeManager;
|
||||
|
||||
/**
|
||||
* Constructs a new BlockRepository.
|
||||
*
|
||||
* @param \Drupal\Core\Entity\EntityManagerInterface $entity_manager
|
||||
* The entity manager.
|
||||
* @param \Drupal\Core\Theme\ThemeManagerInterface $theme_manager
|
||||
* The theme manager.
|
||||
* @param \Drupal\Core\Plugin\Context\ContextHandlerInterface $context_handler
|
||||
* The plugin context handler.
|
||||
*/
|
||||
public function __construct(EntityManagerInterface $entity_manager, ThemeManagerInterface $theme_manager, ContextHandlerInterface $context_handler) {
|
||||
$this->blockStorage = $entity_manager->getStorage('block');
|
||||
$this->themeManager = $theme_manager;
|
||||
$this->contextHandler = $context_handler;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getVisibleBlocksPerRegion(array &$cacheable_metadata = []) {
|
||||
$active_theme = $this->themeManager->getActiveTheme();
|
||||
// Build an array of the region names in the right order.
|
||||
$empty = array_fill_keys($active_theme->getRegions(), []);
|
||||
|
||||
$full = [];
|
||||
foreach ($this->blockStorage->loadByProperties(['theme' => $active_theme->getName()]) as $block_id => $block) {
|
||||
/** @var \Drupal\block\BlockInterface $block */
|
||||
$access = $block->access('view', NULL, TRUE);
|
||||
$region = $block->getRegion();
|
||||
if (!isset($cacheable_metadata[$region])) {
|
||||
$cacheable_metadata[$region] = CacheableMetadata::createFromObject($access);
|
||||
}
|
||||
else {
|
||||
$cacheable_metadata[$region] = $cacheable_metadata[$region]->merge(CacheableMetadata::createFromObject($access));
|
||||
}
|
||||
|
||||
// Set the contexts on the block before checking access.
|
||||
if ($access->isAllowed()) {
|
||||
$full[$region][$block_id] = $block;
|
||||
}
|
||||
}
|
||||
|
||||
// Merge it with the actual values to maintain the region ordering.
|
||||
$assignments = array_intersect_key(array_merge($empty, $full), $empty);
|
||||
foreach ($assignments as &$assignment) {
|
||||
// Suppress errors because PHPUnit will indirectly modify the contents,
|
||||
// triggering https://bugs.php.net/bug.php?id=50688.
|
||||
@uasort($assignment, 'Drupal\block\Entity\Block::sort');
|
||||
}
|
||||
return $assignments;
|
||||
}
|
||||
|
||||
}
|
34
2017/web/core/modules/block/src/BlockRepositoryInterface.php
Normal file
34
2017/web/core/modules/block/src/BlockRepositoryInterface.php
Normal file
|
@ -0,0 +1,34 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\block;
|
||||
|
||||
interface BlockRepositoryInterface {
|
||||
|
||||
/**
|
||||
* Return only visible regions.
|
||||
*
|
||||
* @see system_region_list()
|
||||
*/
|
||||
const REGIONS_VISIBLE = 'visible';
|
||||
|
||||
/**
|
||||
* Return all regions.
|
||||
*
|
||||
* @see system_region_list()
|
||||
*/
|
||||
const REGIONS_ALL = 'all';
|
||||
|
||||
/**
|
||||
* Returns an array of regions and their block entities.
|
||||
*
|
||||
* @param \Drupal\Core\Cache\CacheableMetadata[] $cacheable_metadata
|
||||
* (optional) List of CacheableMetadata objects, keyed by region. This is
|
||||
* by reference and is used to pass this information back to the caller.
|
||||
*
|
||||
* @return array
|
||||
* The array is first keyed by region machine name, with the values
|
||||
* containing an array keyed by block ID, with block entities as the values.
|
||||
*/
|
||||
public function getVisibleBlocksPerRegion(array &$cacheable_metadata = []);
|
||||
|
||||
}
|
251
2017/web/core/modules/block/src/BlockViewBuilder.php
Normal file
251
2017/web/core/modules/block/src/BlockViewBuilder.php
Normal file
|
@ -0,0 +1,251 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\block;
|
||||
|
||||
use Drupal\Core\Block\MainContentBlockPluginInterface;
|
||||
use Drupal\Core\Block\TitleBlockPluginInterface;
|
||||
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\EntityInterface;
|
||||
use Drupal\Core\Extension\ModuleHandlerInterface;
|
||||
use Drupal\Core\Language\LanguageManagerInterface;
|
||||
use Drupal\Core\Plugin\ContextAwarePluginInterface;
|
||||
use Drupal\Core\Render\Element;
|
||||
use Drupal\block\Entity\Block;
|
||||
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}
|
||||
*/
|
||||
public function buildComponents(array &$build, array $entities, array $displays, $view_mode) {
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function view(EntityInterface $entity, $view_mode = 'full', $langcode = NULL) {
|
||||
$build = $this->viewMultiple([$entity], $view_mode, $langcode);
|
||||
return reset($build);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function viewMultiple(array $entities = [], $view_mode = 'full', $langcode = NULL) {
|
||||
/** @var \Drupal\block\BlockInterface[] $entities */
|
||||
$build = [];
|
||||
foreach ($entities as $entity) {
|
||||
$entity_id = $entity->id();
|
||||
$plugin = $entity->getPlugin();
|
||||
|
||||
$cache_tags = Cache::mergeTags($this->getCacheTags(), $entity->getCacheTags());
|
||||
$cache_tags = Cache::mergeTags($cache_tags, $plugin->getCacheTags());
|
||||
|
||||
// Create the render array for the block as a whole.
|
||||
// @see template_preprocess_block().
|
||||
$build[$entity_id] = [
|
||||
'#cache' => [
|
||||
'keys' => ['entity_view', 'block', $entity->id()],
|
||||
'contexts' => Cache::mergeContexts(
|
||||
$entity->getCacheContexts(),
|
||||
$plugin->getCacheContexts()
|
||||
),
|
||||
'tags' => $cache_tags,
|
||||
'max-age' => $plugin->getCacheMaxAge(),
|
||||
],
|
||||
'#weight' => $entity->getWeight(),
|
||||
];
|
||||
|
||||
// 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 || $plugin instanceof TitleBlockPluginInterface) {
|
||||
// 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();
|
||||
|
||||
// Inject runtime contexts.
|
||||
if ($plugin instanceof ContextAwarePluginInterface) {
|
||||
$contexts = \Drupal::service('context.repository')->getRuntimeContexts($plugin->getContextMapping());
|
||||
\Drupal::service('context.handler')->applyContextMapping($plugin, $contexts);
|
||||
}
|
||||
|
||||
// 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.
|
||||
*
|
||||
* @return array
|
||||
* A render array with a #pre_render callback to render the block.
|
||||
*/
|
||||
public static function lazyBuilder($entity_id, $view_mode) {
|
||||
return static::buildPreRenderableBlock(Block::load($entity_id), \Drupal::service('module_handler'));
|
||||
}
|
||||
|
||||
/**
|
||||
* #pre_render callback for building a block.
|
||||
*
|
||||
* Renders the content using the provided block plugin, and then:
|
||||
* - if there is no content, aborts rendering, and makes sure the block won't
|
||||
* be rendered.
|
||||
* - if there is content, moves the contextual links from the block content to
|
||||
* the block itself.
|
||||
*/
|
||||
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.
|
||||
unset($build['#block']);
|
||||
if ($content !== NULL && !Element::isEmpty($content)) {
|
||||
// Place the $content returned by the block plugin into a 'content' child
|
||||
// element, as a way to allow the plugin to have complete control of its
|
||||
// properties and rendering (for instance, its own #theme) without
|
||||
// conflicting with the properties used above, or alternate ones used by
|
||||
// alternate block rendering approaches in contrib (for instance, Panels).
|
||||
// However, the use of a child element is an implementation detail of this
|
||||
// particular block rendering approach. Semantically, the content returned
|
||||
// by the plugin "is the" block, and in particular, #attributes and
|
||||
// #contextual_links is information about the *entire* block. Therefore,
|
||||
// we must move these properties from $content and merge them into the
|
||||
// top-level element.
|
||||
foreach (['#attributes', '#contextual_links'] as $property) {
|
||||
if (isset($content[$property])) {
|
||||
$build[$property] += $content[$property];
|
||||
unset($content[$property]);
|
||||
}
|
||||
}
|
||||
$build['content'] = $content;
|
||||
}
|
||||
// Either the block's content is completely empty, or it consists only of
|
||||
// cacheability metadata.
|
||||
else {
|
||||
// Abort rendering: render as the empty string and ensure this block is
|
||||
// render cached, so we can avoid the work of having to repeatedly
|
||||
// determine whether the block is empty. For instance, modifying or adding
|
||||
// entities could cause the block to no longer be empty.
|
||||
$build = [
|
||||
'#markup' => '',
|
||||
'#cache' => $build['#cache'],
|
||||
];
|
||||
// If $content is not empty, then it contains cacheability metadata, and
|
||||
// we must merge it with the existing cacheability metadata. This allows
|
||||
// blocks to be empty, yet still bubble cacheability metadata, to indicate
|
||||
// why they are empty.
|
||||
if (!empty($content)) {
|
||||
CacheableMetadata::createFromRenderArray($build)
|
||||
->merge(CacheableMetadata::createFromRenderArray($content))
|
||||
->applyTo($build);
|
||||
}
|
||||
}
|
||||
return $build;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\block\Controller;
|
||||
|
||||
use Drupal\Core\Controller\ControllerBase;
|
||||
|
||||
/**
|
||||
* Controller for building the block instance add form.
|
||||
*/
|
||||
class BlockAddController extends ControllerBase {
|
||||
|
||||
/**
|
||||
* Build the block instance add form.
|
||||
*
|
||||
* @param string $plugin_id
|
||||
* The plugin ID for the block instance.
|
||||
* @param string $theme
|
||||
* The name of the theme for the block instance.
|
||||
*
|
||||
* @return array
|
||||
* The block instance edit form.
|
||||
*/
|
||||
public function blockAddConfigureForm($plugin_id, $theme) {
|
||||
// Create a block entity.
|
||||
$entity = $this->entityManager()->getStorage('block')->create(['plugin' => $plugin_id, 'theme' => $theme]);
|
||||
|
||||
return $this->entityFormBuilder()->getForm($entity);
|
||||
}
|
||||
|
||||
}
|
118
2017/web/core/modules/block/src/Controller/BlockController.php
Normal file
118
2017/web/core/modules/block/src/Controller/BlockController.php
Normal file
|
@ -0,0 +1,118 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\block\Controller;
|
||||
|
||||
use Drupal\Component\Utility\Html;
|
||||
use Drupal\block\BlockInterface;
|
||||
use Drupal\Core\Controller\ControllerBase;
|
||||
use Drupal\Core\Extension\ThemeHandlerInterface;
|
||||
use Symfony\Component\DependencyInjection\ContainerInterface;
|
||||
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
|
||||
|
||||
/**
|
||||
* Controller routines for admin block routes.
|
||||
*/
|
||||
class BlockController extends ControllerBase {
|
||||
|
||||
/**
|
||||
* The theme handler.
|
||||
*
|
||||
* @var \Drupal\Core\Extension\ThemeHandlerInterface
|
||||
*/
|
||||
protected $themeHandler;
|
||||
|
||||
/**
|
||||
* Constructs a new BlockController instance.
|
||||
*
|
||||
* @param \Drupal\Core\Extension\ThemeHandlerInterface $theme_handler
|
||||
* The theme handler.
|
||||
*/
|
||||
public function __construct(ThemeHandlerInterface $theme_handler) {
|
||||
$this->themeHandler = $theme_handler;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function create(ContainerInterface $container) {
|
||||
return new static(
|
||||
$container->get('theme_handler')
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Calls a method on a block and reloads the listing page.
|
||||
*
|
||||
* @param \Drupal\block\BlockInterface $block
|
||||
* The block being acted upon.
|
||||
* @param string $op
|
||||
* The operation to perform, e.g., 'enable' or 'disable'.
|
||||
*
|
||||
* @return \Symfony\Component\HttpFoundation\RedirectResponse
|
||||
* A redirect back to the listing page.
|
||||
*/
|
||||
public function performOperation(BlockInterface $block, $op) {
|
||||
$block->$op()->save();
|
||||
$this->messenger()->addStatus($this->t('The block settings have been updated.'));
|
||||
return $this->redirect('block.admin_display');
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a block theme demo page.
|
||||
*
|
||||
* @param string $theme
|
||||
* The name of the theme.
|
||||
*
|
||||
* @return array
|
||||
* A #type 'page' render array containing the block region demo.
|
||||
*/
|
||||
public function demo($theme) {
|
||||
if (!$this->themeHandler->hasUi($theme)) {
|
||||
throw new NotFoundHttpException();
|
||||
}
|
||||
|
||||
$page = [
|
||||
'#title' => Html::escape($this->themeHandler->getName($theme)),
|
||||
'#type' => 'page',
|
||||
'#attached' => [
|
||||
'drupalSettings' => [
|
||||
// The block demonstration page is not marked as an administrative
|
||||
// page by \Drupal::service('router.admin_context')->isAdminRoute()
|
||||
// function in order to use the frontend theme. Since JavaScript
|
||||
// relies on a proper separation of admin pages, it needs to know this
|
||||
// is an actual administrative page.
|
||||
'path' => ['currentPathIsAdmin' => TRUE],
|
||||
],
|
||||
'library' => [
|
||||
'block/drupal.block.admin',
|
||||
],
|
||||
],
|
||||
];
|
||||
|
||||
// Show descriptions in each visible page region, nothing else.
|
||||
$visible_regions = $this->getVisibleRegionNames($theme);
|
||||
foreach (array_keys($visible_regions) as $region) {
|
||||
$page[$region]['block_description'] = [
|
||||
'#type' => 'inline_template',
|
||||
'#template' => '<div class="block-region demo-block">{{ region_name }}</div>',
|
||||
'#context' => ['region_name' => $visible_regions[$region]],
|
||||
];
|
||||
}
|
||||
|
||||
return $page;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the human-readable list of regions keyed by machine name.
|
||||
*
|
||||
* @param string $theme
|
||||
* The name of the theme.
|
||||
*
|
||||
* @return array
|
||||
* An array of human-readable region names keyed by machine name.
|
||||
*/
|
||||
protected function getVisibleRegionNames($theme) {
|
||||
return system_region_list($theme, REGIONS_VISIBLE);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,199 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\block\Controller;
|
||||
|
||||
use Drupal\Component\Serialization\Json;
|
||||
use Drupal\Core\Block\BlockManagerInterface;
|
||||
use Drupal\Core\Controller\ControllerBase;
|
||||
use Drupal\Core\EventSubscriber\MainContentViewSubscriber;
|
||||
use Drupal\Core\Menu\LocalActionManagerInterface;
|
||||
use Drupal\Core\Plugin\Context\LazyContextRepository;
|
||||
use Drupal\Core\Routing\RouteMatchInterface;
|
||||
use Drupal\Core\Url;
|
||||
use Symfony\Component\DependencyInjection\ContainerInterface;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
|
||||
/**
|
||||
* Provides a list of block plugins to be added to the layout.
|
||||
*/
|
||||
class BlockLibraryController extends ControllerBase {
|
||||
|
||||
/**
|
||||
* The block manager.
|
||||
*
|
||||
* @var \Drupal\Core\Block\BlockManagerInterface
|
||||
*/
|
||||
protected $blockManager;
|
||||
|
||||
/**
|
||||
* The context repository.
|
||||
*
|
||||
* @var \Drupal\Core\Plugin\Context\LazyContextRepository
|
||||
*/
|
||||
protected $contextRepository;
|
||||
|
||||
/**
|
||||
* The route match.
|
||||
*
|
||||
* @var \Drupal\Core\Routing\RouteMatchInterface
|
||||
*/
|
||||
protected $routeMatch;
|
||||
|
||||
/**
|
||||
* The local action manager.
|
||||
*
|
||||
* @var \Drupal\Core\Menu\LocalActionManagerInterface
|
||||
*/
|
||||
protected $localActionManager;
|
||||
|
||||
/**
|
||||
* Constructs a BlockLibraryController object.
|
||||
*
|
||||
* @param \Drupal\Core\Block\BlockManagerInterface $block_manager
|
||||
* The block manager.
|
||||
* @param \Drupal\Core\Plugin\Context\LazyContextRepository $context_repository
|
||||
* The context repository.
|
||||
* @param \Drupal\Core\Routing\RouteMatchInterface $route_match
|
||||
* The current route match.
|
||||
* @param \Drupal\Core\Menu\LocalActionManagerInterface $local_action_manager
|
||||
* The local action manager.
|
||||
*/
|
||||
public function __construct(BlockManagerInterface $block_manager, LazyContextRepository $context_repository, RouteMatchInterface $route_match, LocalActionManagerInterface $local_action_manager) {
|
||||
$this->blockManager = $block_manager;
|
||||
$this->routeMatch = $route_match;
|
||||
$this->localActionManager = $local_action_manager;
|
||||
$this->contextRepository = $context_repository;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function create(ContainerInterface $container) {
|
||||
return new static(
|
||||
$container->get('plugin.manager.block'),
|
||||
$container->get('context.repository'),
|
||||
$container->get('current_route_match'),
|
||||
$container->get('plugin.manager.menu.local_action')
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Shows a list of blocks that can be added to a theme's layout.
|
||||
*
|
||||
* @param \Symfony\Component\HttpFoundation\Request $request
|
||||
* The current request.
|
||||
* @param string $theme
|
||||
* Theme key of the block list.
|
||||
*
|
||||
* @return array
|
||||
* A render array as expected by the renderer.
|
||||
*/
|
||||
public function listBlocks(Request $request, $theme) {
|
||||
// Since modals do not render any other part of the page, we need to render
|
||||
// them manually as part of this listing.
|
||||
if ($request->query->get(MainContentViewSubscriber::WRAPPER_FORMAT) === 'drupal_modal') {
|
||||
$build['local_actions'] = $this->buildLocalActions();
|
||||
}
|
||||
|
||||
$headers = [
|
||||
['data' => $this->t('Block')],
|
||||
['data' => $this->t('Category')],
|
||||
['data' => $this->t('Operations')],
|
||||
];
|
||||
|
||||
$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 = [];
|
||||
$row['title']['data'] = [
|
||||
'#type' => 'inline_template',
|
||||
'#template' => '<div class="block-filter-text-source">{{ label }}</div>',
|
||||
'#context' => [
|
||||
'label' => $plugin_definition['admin_label'],
|
||||
],
|
||||
];
|
||||
$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]),
|
||||
'attributes' => [
|
||||
'class' => ['use-ajax'],
|
||||
'data-dialog-type' => 'modal',
|
||||
'data-dialog-options' => Json::encode([
|
||||
'width' => 700,
|
||||
]),
|
||||
],
|
||||
];
|
||||
if ($region) {
|
||||
$links['add']['query']['region'] = $region;
|
||||
}
|
||||
if (isset($weight)) {
|
||||
$links['add']['query']['weight'] = $weight;
|
||||
}
|
||||
$row['operations']['data'] = [
|
||||
'#type' => 'operations',
|
||||
'#links' => $links,
|
||||
];
|
||||
$rows[] = $row;
|
||||
}
|
||||
|
||||
$build['#attached']['library'][] = 'block/drupal.block.admin';
|
||||
|
||||
$build['filter'] = [
|
||||
'#type' => 'search',
|
||||
'#title' => $this->t('Filter'),
|
||||
'#title_display' => 'invisible',
|
||||
'#size' => 30,
|
||||
'#placeholder' => $this->t('Filter by block name'),
|
||||
'#attributes' => [
|
||||
'class' => ['block-filter-text'],
|
||||
'data-element' => '.block-add-table',
|
||||
'title' => $this->t('Enter a part of the block name to filter by.'),
|
||||
],
|
||||
];
|
||||
|
||||
$build['blocks'] = [
|
||||
'#type' => 'table',
|
||||
'#header' => $headers,
|
||||
'#rows' => $rows,
|
||||
'#empty' => $this->t('No blocks available.'),
|
||||
'#attributes' => [
|
||||
'class' => ['block-add-table'],
|
||||
],
|
||||
];
|
||||
|
||||
return $build;
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds the local actions for this listing.
|
||||
*
|
||||
* @return array
|
||||
* An array of local actions for this listing.
|
||||
*/
|
||||
protected function buildLocalActions() {
|
||||
$build = $this->localActionManager->getActionsForRoute($this->routeMatch->getRouteName());
|
||||
// Without this workaround, the action links will be rendered as <li> with
|
||||
// no wrapping <ul> element.
|
||||
if (!empty($build)) {
|
||||
$build['#prefix'] = '<ul class="action-links">';
|
||||
$build['#suffix'] = '</ul>';
|
||||
}
|
||||
return $build;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,63 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\block\Controller;
|
||||
|
||||
use Drupal\Core\Entity\Controller\EntityListController;
|
||||
use Drupal\Core\Extension\ThemeHandlerInterface;
|
||||
use Symfony\Component\DependencyInjection\ContainerInterface;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
|
||||
|
||||
/**
|
||||
* Defines a controller to list blocks.
|
||||
*/
|
||||
class BlockListController extends EntityListController {
|
||||
|
||||
/**
|
||||
* The theme handler.
|
||||
*
|
||||
* @var \Drupal\Core\Extension\ThemeHandlerInterface
|
||||
*/
|
||||
protected $themeHandler;
|
||||
|
||||
/**
|
||||
* Constructs the BlockListController.
|
||||
*
|
||||
* @param \Drupal\Core\Extension\ThemeHandlerInterface $theme_handler
|
||||
* The theme handler.
|
||||
*/
|
||||
public function __construct(ThemeHandlerInterface $theme_handler) {
|
||||
$this->themeHandler = $theme_handler;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function create(ContainerInterface $container) {
|
||||
return new static(
|
||||
$container->get('theme_handler')
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Shows the block administration page.
|
||||
*
|
||||
* @param string|null $theme
|
||||
* Theme key of block list.
|
||||
* @param \Symfony\Component\HttpFoundation\Request $request
|
||||
* The current request.
|
||||
*
|
||||
* @return array
|
||||
* 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');
|
||||
if (!$this->themeHandler->hasUi($theme)) {
|
||||
throw new NotFoundHttpException();
|
||||
}
|
||||
|
||||
return $this->entityManager()->getListBuilder('block')->render($theme, $request);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,63 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\block\Controller;
|
||||
|
||||
use Drupal\Component\Utility\Html;
|
||||
use Drupal\Core\Block\BlockManagerInterface;
|
||||
use Drupal\Core\DependencyInjection\ContainerInjectionInterface;
|
||||
use Symfony\Component\DependencyInjection\ContainerInterface;
|
||||
use Symfony\Component\HttpFoundation\JsonResponse;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
|
||||
/**
|
||||
* Returns autocomplete responses for block categories.
|
||||
*/
|
||||
class CategoryAutocompleteController implements ContainerInjectionInterface {
|
||||
|
||||
/**
|
||||
* The block manager.
|
||||
*
|
||||
* @var \Drupal\Core\Block\BlockManagerInterface
|
||||
*/
|
||||
protected $blockManager;
|
||||
|
||||
/**
|
||||
* Constructs a new CategoryAutocompleteController.
|
||||
*
|
||||
* @param \Drupal\Core\Block\BlockManagerInterface $block_manager
|
||||
* The block manager.
|
||||
*/
|
||||
public function __construct(BlockManagerInterface $block_manager) {
|
||||
$this->blockManager = $block_manager;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function create(ContainerInterface $container) {
|
||||
return new static(
|
||||
$container->get('plugin.manager.block')
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves suggestions for block category autocompletion.
|
||||
*
|
||||
* @param \Symfony\Component\HttpFoundation\Request $request
|
||||
* The current request.
|
||||
*
|
||||
* @return \Symfony\Component\HttpFoundation\JsonResponse
|
||||
* A JSON response containing autocomplete suggestions.
|
||||
*/
|
||||
public function autocomplete(Request $request) {
|
||||
$typed_category = $request->query->get('q');
|
||||
$matches = [];
|
||||
foreach ($this->blockManager->getCategories() as $category) {
|
||||
if (stripos($category, $typed_category) === 0) {
|
||||
$matches[] = ['value' => $category, 'label' => Html::escape($category)];
|
||||
}
|
||||
}
|
||||
return new JsonResponse($matches);
|
||||
}
|
||||
|
||||
}
|
357
2017/web/core/modules/block/src/Entity/Block.php
Normal file
357
2017/web/core/modules/block/src/Entity/Block.php
Normal file
|
@ -0,0 +1,357 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\block\Entity;
|
||||
|
||||
use Drupal\Core\Cache\Cache;
|
||||
use Drupal\Core\Condition\ConditionPluginCollection;
|
||||
use Drupal\Core\Config\Entity\ConfigEntityBase;
|
||||
use Drupal\block\BlockPluginCollection;
|
||||
use Drupal\block\BlockInterface;
|
||||
use Drupal\Core\Config\Entity\ConfigEntityInterface;
|
||||
use Drupal\Core\Entity\EntityWithPluginCollectionInterface;
|
||||
use Drupal\Core\Entity\EntityStorageInterface;
|
||||
|
||||
/**
|
||||
* Defines a Block configuration entity class.
|
||||
*
|
||||
* @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",
|
||||
* "list_builder" = "Drupal\block\BlockListBuilder",
|
||||
* "form" = {
|
||||
* "default" = "Drupal\block\BlockForm",
|
||||
* "delete" = "Drupal\block\Form\BlockDeleteForm"
|
||||
* }
|
||||
* },
|
||||
* admin_permission = "administer blocks",
|
||||
* entity_keys = {
|
||||
* "id" = "id",
|
||||
* "status" = "status"
|
||||
* },
|
||||
* links = {
|
||||
* "delete-form" = "/admin/structure/block/manage/{block}/delete",
|
||||
* "edit-form" = "/admin/structure/block/manage/{block}",
|
||||
* "enable" = "/admin/structure/block/manage/{block}/enable",
|
||||
* "disable" = "/admin/structure/block/manage/{block}/disable",
|
||||
* },
|
||||
* config_export = {
|
||||
* "id",
|
||||
* "theme",
|
||||
* "region",
|
||||
* "weight",
|
||||
* "provider",
|
||||
* "plugin",
|
||||
* "settings",
|
||||
* "visibility",
|
||||
* },
|
||||
* lookup_keys = {
|
||||
* "theme"
|
||||
* }
|
||||
* )
|
||||
*/
|
||||
class Block extends ConfigEntityBase implements BlockInterface, EntityWithPluginCollectionInterface {
|
||||
|
||||
/**
|
||||
* The ID of the block.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $id;
|
||||
|
||||
/**
|
||||
* The plugin instance settings.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $settings = [];
|
||||
|
||||
/**
|
||||
* The region this block is placed in.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $region;
|
||||
|
||||
/**
|
||||
* The block weight.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
protected $weight;
|
||||
|
||||
/**
|
||||
* The plugin instance ID.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $plugin;
|
||||
|
||||
/**
|
||||
* The visibility settings for this block.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $visibility = [];
|
||||
|
||||
/**
|
||||
* The plugin collection that holds the block plugin for this entity.
|
||||
*
|
||||
* @var \Drupal\block\BlockPluginCollection
|
||||
*/
|
||||
protected $pluginCollection;
|
||||
|
||||
/**
|
||||
* The available contexts for this block and its visibility conditions.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $contexts = [];
|
||||
|
||||
/**
|
||||
* The visibility collection.
|
||||
*
|
||||
* @var \Drupal\Core\Condition\ConditionPluginCollection
|
||||
*/
|
||||
protected $visibilityCollection;
|
||||
|
||||
/**
|
||||
* The condition plugin manager.
|
||||
*
|
||||
* @var \Drupal\Core\Executable\ExecutableManagerInterface
|
||||
*/
|
||||
protected $conditionPluginManager;
|
||||
|
||||
/**
|
||||
* The theme that includes the block plugin for this entity.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $theme;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getPlugin() {
|
||||
return $this->getPluginCollection()->get($this->plugin);
|
||||
}
|
||||
|
||||
/**
|
||||
* Encapsulates the creation of the block's LazyPluginCollection.
|
||||
*
|
||||
* @return \Drupal\Component\Plugin\LazyPluginCollection
|
||||
* The block's plugin collection.
|
||||
*/
|
||||
protected function getPluginCollection() {
|
||||
if (!$this->pluginCollection) {
|
||||
$this->pluginCollection = new BlockPluginCollection(\Drupal::service('plugin.manager.block'), $this->plugin, $this->get('settings'), $this->id());
|
||||
}
|
||||
return $this->pluginCollection;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getPluginCollections() {
|
||||
return [
|
||||
'settings' => $this->getPluginCollection(),
|
||||
'visibility' => $this->getVisibilityConditions(),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getPluginId() {
|
||||
return $this->plugin;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getRegion() {
|
||||
return $this->region;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getTheme() {
|
||||
return $this->theme;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getWeight() {
|
||||
return $this->weight;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function label() {
|
||||
$settings = $this->get('settings');
|
||||
if ($settings['label']) {
|
||||
return $settings['label'];
|
||||
}
|
||||
else {
|
||||
$definition = $this->getPlugin()->getPluginDefinition();
|
||||
return $definition['admin_label'];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sorts active blocks by weight; sorts inactive blocks by name.
|
||||
*/
|
||||
public static function sort(ConfigEntityInterface $a, ConfigEntityInterface $b) {
|
||||
// Separate enabled from disabled.
|
||||
$status = (int) $b->status() - (int) $a->status();
|
||||
if ($status !== 0) {
|
||||
return $status;
|
||||
}
|
||||
|
||||
// Sort by weight.
|
||||
$weight = $a->getWeight() - $b->getWeight();
|
||||
if ($weight) {
|
||||
return $weight;
|
||||
}
|
||||
|
||||
// Sort by label.
|
||||
return strcmp($a->label(), $b->label());
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function calculateDependencies() {
|
||||
parent::calculateDependencies();
|
||||
$this->addDependency('theme', $this->theme);
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function postSave(EntityStorageInterface $storage, $update = TRUE) {
|
||||
parent::postSave($storage, $update);
|
||||
|
||||
// Entity::postSave() calls Entity::invalidateTagsOnSave(), which only
|
||||
// handles the regular cases. The Block entity has one special case: a
|
||||
// newly created block may *also* appear on any page in the current theme,
|
||||
// so we must invalidate the associated block's cache tag (which includes
|
||||
// the theme cache tag).
|
||||
if (!$update) {
|
||||
Cache::invalidateTags($this->getCacheTagsToInvalidate());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getVisibility() {
|
||||
return $this->getVisibilityConditions()->getConfiguration();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function setVisibilityConfig($instance_id, array $configuration) {
|
||||
$conditions = $this->getVisibilityConditions();
|
||||
if (!$conditions->has($instance_id)) {
|
||||
$configuration['id'] = $instance_id;
|
||||
$conditions->addInstanceId($instance_id, $configuration);
|
||||
}
|
||||
else {
|
||||
$conditions->setInstanceConfiguration($instance_id, $configuration);
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getVisibilityConditions() {
|
||||
if (!isset($this->visibilityCollection)) {
|
||||
$this->visibilityCollection = new ConditionPluginCollection($this->conditionPluginManager(), $this->get('visibility'));
|
||||
}
|
||||
return $this->visibilityCollection;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getVisibilityCondition($instance_id) {
|
||||
return $this->getVisibilityConditions()->get($instance_id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the condition plugin manager.
|
||||
*
|
||||
* @return \Drupal\Core\Executable\ExecutableManagerInterface
|
||||
* The condition plugin manager.
|
||||
*/
|
||||
protected function conditionPluginManager() {
|
||||
if (!isset($this->conditionPluginManager)) {
|
||||
$this->conditionPluginManager = \Drupal::service('plugin.manager.condition');
|
||||
}
|
||||
return $this->conditionPluginManager;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function setRegion($region) {
|
||||
$this->region = $region;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function setWeight($weight) {
|
||||
$this->weight = $weight;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function createDuplicateBlock($new_id = NULL, $new_theme = NULL) {
|
||||
$duplicate = parent::createDuplicate();
|
||||
if (!empty($new_id)) {
|
||||
$duplicate->id = $new_id;
|
||||
}
|
||||
if (!empty($new_theme)) {
|
||||
$duplicate->theme = $new_theme;
|
||||
}
|
||||
return $duplicate;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function preSave(EntityStorageInterface $storage) {
|
||||
parent::preSave($storage);
|
||||
|
||||
// Ensure the region is valid to mirror the behavior of block_rebuild().
|
||||
// This is done primarily for backwards compatibility support of
|
||||
// \Drupal\block\BlockInterface::BLOCK_REGION_NONE.
|
||||
$regions = system_region_list($this->theme);
|
||||
if (!isset($regions[$this->region]) && $this->status()) {
|
||||
$this
|
||||
->setRegion(system_default_region($this->theme))
|
||||
->disable();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\block\EventSubscriber;
|
||||
|
||||
use Drupal\Core\Render\PageDisplayVariantSelectionEvent;
|
||||
use Drupal\Core\Render\RenderEvents;
|
||||
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
||||
|
||||
/**
|
||||
* Selects the block page display variant.
|
||||
*
|
||||
* @see \Drupal\block\Plugin\DisplayVariant\BlockPageVariant
|
||||
*/
|
||||
class BlockPageDisplayVariantSubscriber implements EventSubscriberInterface {
|
||||
|
||||
/**
|
||||
* Selects the block page display variant.
|
||||
*
|
||||
* @param \Drupal\Core\Render\PageDisplayVariantSelectionEvent $event
|
||||
* The event to process.
|
||||
*/
|
||||
public function onSelectPageDisplayVariant(PageDisplayVariantSelectionEvent $event) {
|
||||
$event->setPluginId('block_page');
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function getSubscribedEvents() {
|
||||
$events[RenderEvents::SELECT_PAGE_DISPLAY_VARIANT][] = ['onSelectPageDisplayVariant'];
|
||||
return $events;
|
||||
}
|
||||
|
||||
}
|
50
2017/web/core/modules/block/src/Form/BlockDeleteForm.php
Normal file
50
2017/web/core/modules/block/src/Form/BlockDeleteForm.php
Normal file
|
@ -0,0 +1,50 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\block\Form;
|
||||
|
||||
use Drupal\Core\Entity\EntityDeleteForm;
|
||||
use Drupal\Core\Url;
|
||||
|
||||
/**
|
||||
* Provides a deletion confirmation form for the block instance deletion form.
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
class BlockDeleteForm extends EntityDeleteForm {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getCancelUrl() {
|
||||
return new Url('block.admin_display');
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getConfirmText() {
|
||||
return $this->t('Remove');
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getQuestion() {
|
||||
return $this->t('Are you sure you want to remove the @entity-type %label?', [
|
||||
'@entity-type' => $this->getEntity()->getEntityType()->getLowercaseLabel(),
|
||||
'%label' => $this->getEntity()->label(),
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function getDeletionMessage() {
|
||||
$entity = $this->getEntity();
|
||||
return $this->t('The @entity-type %label has been removed.', [
|
||||
'@entity-type' => $entity->getEntityType()->getLowercaseLabel(),
|
||||
'%label' => $entity->label(),
|
||||
]);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,66 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\block\Plugin\Derivative;
|
||||
|
||||
use Drupal\Component\Plugin\Derivative\DeriverBase;
|
||||
use Drupal\Core\Extension\ThemeHandlerInterface;
|
||||
use Drupal\Core\Plugin\Discovery\ContainerDeriverInterface;
|
||||
use Symfony\Component\DependencyInjection\ContainerInterface;
|
||||
|
||||
/**
|
||||
* Provides dynamic tabs based on active themes.
|
||||
*/
|
||||
class ThemeLocalTask extends DeriverBase implements ContainerDeriverInterface {
|
||||
|
||||
/**
|
||||
* The theme handler.
|
||||
*
|
||||
* @var \Drupal\Core\Extension\ThemeHandlerInterface
|
||||
*/
|
||||
protected $themeHandler;
|
||||
|
||||
/**
|
||||
* Constructs a new ThemeLocalTask.
|
||||
*
|
||||
* @param \Drupal\Core\Extension\ThemeHandlerInterface $theme_handler
|
||||
* The theme handler.
|
||||
*/
|
||||
public function __construct(ThemeHandlerInterface $theme_handler) {
|
||||
$this->themeHandler = $theme_handler;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function create(ContainerInterface $container, $base_plugin_id) {
|
||||
return new static(
|
||||
$container->get('theme_handler')
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getDerivativeDefinitions($base_plugin_definition) {
|
||||
$default_theme = $this->themeHandler->getDefault();
|
||||
|
||||
foreach ($this->themeHandler->listInfo() as $theme_name => $theme) {
|
||||
if ($this->themeHandler->hasUi($theme_name)) {
|
||||
$this->derivatives[$theme_name] = $base_plugin_definition;
|
||||
$this->derivatives[$theme_name]['title'] = $theme->info['name'];
|
||||
$this->derivatives[$theme_name]['route_parameters'] = ['theme' => $theme_name];
|
||||
}
|
||||
// Default task!
|
||||
if ($default_theme == $theme_name) {
|
||||
$this->derivatives[$theme_name]['route_name'] = $base_plugin_definition['parent_id'];
|
||||
// Emulate default logic because without the base plugin id we can't
|
||||
// change the base_route.
|
||||
$this->derivatives[$theme_name]['weight'] = -10;
|
||||
|
||||
unset($this->derivatives[$theme_name]['route_parameters']);
|
||||
}
|
||||
}
|
||||
return $this->derivatives;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,203 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\block\Plugin\DisplayVariant;
|
||||
|
||||
use Drupal\block\BlockRepositoryInterface;
|
||||
use Drupal\Core\Block\MainContentBlockPluginInterface;
|
||||
use Drupal\Core\Block\TitleBlockPluginInterface;
|
||||
use Drupal\Core\Block\MessagesBlockPluginInterface;
|
||||
use Drupal\Core\Cache\CacheableMetadata;
|
||||
use Drupal\Core\Display\PageVariantInterface;
|
||||
use Drupal\Core\Entity\EntityViewBuilderInterface;
|
||||
use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
|
||||
use Drupal\Core\Display\VariantBase;
|
||||
use Symfony\Component\DependencyInjection\ContainerInterface;
|
||||
|
||||
/**
|
||||
* Provides a page display variant that decorates the main content with blocks.
|
||||
*
|
||||
* To ensure essential information is displayed, each essential part of a page
|
||||
* has a corresponding block plugin interface, so that BlockPageVariant can
|
||||
* automatically provide a fallback in case no block for each of these
|
||||
* interfaces is placed.
|
||||
*
|
||||
* @see \Drupal\Core\Block\MainContentBlockPluginInterface
|
||||
* @see \Drupal\Core\Block\MessagesBlockPluginInterface
|
||||
*
|
||||
* @PageDisplayVariant(
|
||||
* id = "block_page",
|
||||
* admin_label = @Translation("Page with blocks")
|
||||
* )
|
||||
*/
|
||||
class BlockPageVariant extends VariantBase implements PageVariantInterface, ContainerFactoryPluginInterface {
|
||||
|
||||
/**
|
||||
* The block repository.
|
||||
*
|
||||
* @var \Drupal\block\BlockRepositoryInterface
|
||||
*/
|
||||
protected $blockRepository;
|
||||
|
||||
/**
|
||||
* The block view builder.
|
||||
*
|
||||
* @var \Drupal\Core\Entity\EntityViewBuilderInterface
|
||||
*/
|
||||
protected $blockViewBuilder;
|
||||
|
||||
/**
|
||||
* The Block entity type list cache tags.
|
||||
*
|
||||
* @var string[]
|
||||
*/
|
||||
protected $blockListCacheTags;
|
||||
|
||||
/**
|
||||
* The render array representing the main page content.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $mainContent = [];
|
||||
|
||||
/**
|
||||
* The page title: a string (plain title) or a render array (formatted title).
|
||||
*
|
||||
* @var string|array
|
||||
*/
|
||||
protected $title = '';
|
||||
|
||||
/**
|
||||
* Constructs a new BlockPageVariant.
|
||||
*
|
||||
* @param array $configuration
|
||||
* A configuration array containing information about the plugin instance.
|
||||
* @param string $plugin_id
|
||||
* The plugin ID for the plugin instance.
|
||||
* @param mixed $plugin_definition
|
||||
* The plugin implementation definition.
|
||||
* @param \Drupal\block\BlockRepositoryInterface $block_repository
|
||||
* The block repository.
|
||||
* @param \Drupal\Core\Entity\EntityViewBuilderInterface $block_view_builder
|
||||
* The block view builder.
|
||||
* @param string[] $block_list_cache_tags
|
||||
* The Block entity type list cache tags.
|
||||
*/
|
||||
public function __construct(array $configuration, $plugin_id, $plugin_definition, BlockRepositoryInterface $block_repository, EntityViewBuilderInterface $block_view_builder, array $block_list_cache_tags) {
|
||||
parent::__construct($configuration, $plugin_id, $plugin_definition);
|
||||
$this->blockRepository = $block_repository;
|
||||
$this->blockViewBuilder = $block_view_builder;
|
||||
$this->blockListCacheTags = $block_list_cache_tags;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
|
||||
return new static(
|
||||
$configuration,
|
||||
$plugin_id,
|
||||
$plugin_definition,
|
||||
$container->get('block.repository'),
|
||||
$container->get('entity.manager')->getViewBuilder('block'),
|
||||
$container->get('entity.manager')->getDefinition('block')->getListCacheTags()
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function setMainContent(array $main_content) {
|
||||
$this->mainContent = $main_content;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function setTitle($title) {
|
||||
$this->title = $title;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function build() {
|
||||
// Track whether blocks showing the main content and messages are displayed.
|
||||
$main_content_block_displayed = FALSE;
|
||||
$messages_block_displayed = FALSE;
|
||||
|
||||
$build = [
|
||||
'#cache' => [
|
||||
'tags' => $this->blockListCacheTags,
|
||||
],
|
||||
];
|
||||
// Load all region content assigned via blocks.
|
||||
$cacheable_metadata_list = [];
|
||||
foreach ($this->blockRepository->getVisibleBlocksPerRegion($cacheable_metadata_list) as $region => $blocks) {
|
||||
/** @var $blocks \Drupal\block\BlockInterface[] */
|
||||
foreach ($blocks as $key => $block) {
|
||||
$block_plugin = $block->getPlugin();
|
||||
if ($block_plugin instanceof MainContentBlockPluginInterface) {
|
||||
$block_plugin->setMainContent($this->mainContent);
|
||||
$main_content_block_displayed = TRUE;
|
||||
}
|
||||
elseif ($block_plugin instanceof TitleBlockPluginInterface) {
|
||||
$block_plugin->setTitle($this->title);
|
||||
}
|
||||
elseif ($block_plugin instanceof MessagesBlockPluginInterface) {
|
||||
$messages_block_displayed = TRUE;
|
||||
}
|
||||
$build[$region][$key] = $this->blockViewBuilder->view($block);
|
||||
|
||||
// The main content block cannot be cached: it is a placeholder for the
|
||||
// render array returned by the controller. It should be rendered as-is,
|
||||
// with other placed blocks "decorating" it. Analogous reasoning for the
|
||||
// title block.
|
||||
if ($block_plugin instanceof MainContentBlockPluginInterface || $block_plugin instanceof TitleBlockPluginInterface) {
|
||||
unset($build[$region][$key]['#cache']['keys']);
|
||||
}
|
||||
}
|
||||
if (!empty($build[$region])) {
|
||||
// \Drupal\block\BlockRepositoryInterface::getVisibleBlocksPerRegion()
|
||||
// returns the blocks in sorted order.
|
||||
$build[$region]['#sorted'] = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
// If no block that shows the main content is displayed, still show the main
|
||||
// content. Otherwise the end user will see all displayed blocks, but not
|
||||
// the main content they came for.
|
||||
if (!$main_content_block_displayed) {
|
||||
$build['content']['system_main'] = $this->mainContent;
|
||||
}
|
||||
|
||||
// If no block displays status messages, still render them.
|
||||
if (!$messages_block_displayed) {
|
||||
$build['content']['messages'] = [
|
||||
'#weight' => -1000,
|
||||
'#type' => 'status_messages',
|
||||
];
|
||||
}
|
||||
|
||||
// If any render arrays are manually placed, render arrays and blocks must
|
||||
// be sorted.
|
||||
if (!$main_content_block_displayed || !$messages_block_displayed) {
|
||||
unset($build['content']['#sorted']);
|
||||
}
|
||||
|
||||
// The access results' cacheability is currently added to the top level of the
|
||||
// render array. This is done to prevent issues with empty regions being
|
||||
// displayed.
|
||||
// This would need to be changed to allow caching of block regions, as each
|
||||
// region must then have the relevant cacheable metadata.
|
||||
$merged_cacheable_metadata = CacheableMetadata::createFromRenderArray($build);
|
||||
foreach ($cacheable_metadata_list as $cacheable_metadata) {
|
||||
$merged_cacheable_metadata = $merged_cacheable_metadata->merge($cacheable_metadata);
|
||||
}
|
||||
$merged_cacheable_metadata->applyTo($build);
|
||||
|
||||
return $build;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\block\Plugin\migrate\destination;
|
||||
|
||||
use Drupal\migrate\Plugin\migrate\destination\EntityConfigBase;
|
||||
use Drupal\migrate\Row;
|
||||
|
||||
/**
|
||||
* @MigrateDestination(
|
||||
* id = "entity:block"
|
||||
* )
|
||||
*/
|
||||
class EntityBlock extends EntityConfigBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function getEntityId(Row $row) {
|
||||
// Try to find the block by its plugin ID and theme.
|
||||
$properties = [
|
||||
'plugin' => $row->getDestinationProperty('plugin'),
|
||||
'theme' => $row->getDestinationProperty('theme'),
|
||||
];
|
||||
$blocks = array_keys($this->storage->loadByProperties($properties));
|
||||
return reset($blocks);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,100 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\block\Plugin\migrate\process;
|
||||
|
||||
use Drupal\Core\Entity\EntityStorageInterface;
|
||||
use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
|
||||
use Drupal\migrate\Plugin\MigrationInterface;
|
||||
use Drupal\migrate\MigrateExecutableInterface;
|
||||
use Drupal\migrate\Plugin\MigrateProcessInterface;
|
||||
use Drupal\migrate\ProcessPluginBase;
|
||||
use Drupal\migrate\Row;
|
||||
use Symfony\Component\DependencyInjection\ContainerInterface;
|
||||
|
||||
/**
|
||||
* @MigrateProcessPlugin(
|
||||
* id = "block_plugin_id"
|
||||
* )
|
||||
*/
|
||||
class BlockPluginId extends ProcessPluginBase implements ContainerFactoryPluginInterface {
|
||||
|
||||
/**
|
||||
* The migration process plugin, configured for lookups in d6_custom_block
|
||||
* and d7_custom_block.
|
||||
*
|
||||
* @var \Drupal\migrate\Plugin\MigrateProcessInterface
|
||||
*/
|
||||
protected $migrationPlugin;
|
||||
|
||||
/**
|
||||
* The block_content entity storage handler.
|
||||
*
|
||||
* @var \Drupal\Core\Entity\EntityStorageInterface
|
||||
*/
|
||||
protected $blockContentStorage;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function __construct(array $configuration, $plugin_id, array $plugin_definition, EntityStorageInterface $storage, MigrateProcessInterface $migration_plugin) {
|
||||
parent::__construct($configuration, $plugin_id, $plugin_definition);
|
||||
$this->blockContentStorage = $storage;
|
||||
$this->migrationPlugin = $migration_plugin;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition, MigrationInterface $migration = NULL) {
|
||||
$entity_manager = $container->get('entity.manager');
|
||||
$migration_configuration = [
|
||||
'migration' => [
|
||||
'd6_custom_block',
|
||||
'd7_custom_block',
|
||||
],
|
||||
];
|
||||
return new static(
|
||||
$configuration,
|
||||
$plugin_id,
|
||||
$plugin_definition,
|
||||
$entity_manager->getDefinition('block_content') ? $entity_manager->getStorage('block_content') : NULL,
|
||||
$container->get('plugin.manager.migrate.process')->createInstance('migration', $migration_configuration, $migration)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* Set the block plugin id.
|
||||
*/
|
||||
public function transform($value, MigrateExecutableInterface $migrate_executable, Row $row, $destination_property) {
|
||||
if (is_array($value)) {
|
||||
list($module, $delta) = $value;
|
||||
switch ($module) {
|
||||
case 'aggregator':
|
||||
list($type, $id) = explode('-', $delta);
|
||||
if ($type == 'feed') {
|
||||
return 'aggregator_feed_block';
|
||||
}
|
||||
break;
|
||||
case 'menu':
|
||||
return "system_menu_block:$delta";
|
||||
case 'block':
|
||||
if ($this->blockContentStorage) {
|
||||
$block_id = $this->migrationPlugin
|
||||
->transform($delta, $migrate_executable, $row, $destination_property);
|
||||
if ($block_id) {
|
||||
return 'block_content:' . $this->blockContentStorage->load($block_id)->uuid();
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
else {
|
||||
return $value;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,73 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\block\Plugin\migrate\process;
|
||||
|
||||
use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
|
||||
use Drupal\migrate\MigrateExecutableInterface;
|
||||
use Drupal\migrate\Plugin\migrate\process\StaticMap;
|
||||
use Drupal\migrate\Row;
|
||||
use Symfony\Component\DependencyInjection\ContainerInterface;
|
||||
|
||||
/**
|
||||
* @MigrateProcessPlugin(
|
||||
* id = "block_region"
|
||||
* )
|
||||
*/
|
||||
class BlockRegion extends StaticMap implements ContainerFactoryPluginInterface {
|
||||
|
||||
/**
|
||||
* List of regions, keyed by theme.
|
||||
*
|
||||
* @var array[]
|
||||
*/
|
||||
protected $regions;
|
||||
|
||||
/**
|
||||
* Constructs a BlockRegion plugin instance.
|
||||
*
|
||||
* @param array $configuration
|
||||
* The plugin configuration.
|
||||
* @param string $plugin_id
|
||||
* The plugin ID.
|
||||
* @param mixed $plugin_definition
|
||||
* The plugin definition.
|
||||
* @param array $regions
|
||||
* Array of region maps, keyed by theme.
|
||||
*/
|
||||
public function __construct(array $configuration, $plugin_id, $plugin_definition, array $regions) {
|
||||
parent::__construct($configuration, $plugin_id, $plugin_definition);
|
||||
$this->regions = $regions;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
|
||||
$regions = [];
|
||||
foreach ($container->get('theme_handler')->listInfo() as $key => $theme) {
|
||||
$regions[$key] = $theme->info['regions'];
|
||||
}
|
||||
return new static($configuration, $plugin_id, $plugin_definition, $regions);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function transform($value, MigrateExecutableInterface $migrate_executable, Row $row, $destination_property) {
|
||||
// Set the destination region, based on the source region and theme as well
|
||||
// as the current destination default theme.
|
||||
list($source_theme, $destination_theme, $region) = $value;
|
||||
|
||||
// Theme is the same on both source and destination, so ensure that the
|
||||
// region exists in the destination theme.
|
||||
if (strtolower($source_theme) == strtolower($destination_theme)) {
|
||||
if (isset($this->regions[$destination_theme][$region])) {
|
||||
return $region;
|
||||
}
|
||||
}
|
||||
|
||||
// Fall back to static mapping.
|
||||
return parent::transform($value, $migrate_executable, $row, $destination_property);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,60 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\block\Plugin\migrate\process;
|
||||
|
||||
use Drupal\Core\Block\BlockPluginInterface;
|
||||
use Drupal\migrate\MigrateExecutableInterface;
|
||||
use Drupal\migrate\ProcessPluginBase;
|
||||
use Drupal\migrate\Row;
|
||||
|
||||
/**
|
||||
* @MigrateProcessPlugin(
|
||||
* id = "block_settings"
|
||||
* )
|
||||
*/
|
||||
class BlockSettings extends ProcessPluginBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* Set the block configuration.
|
||||
*/
|
||||
public function transform($value, MigrateExecutableInterface $migrate_executable, Row $row, $destination_property) {
|
||||
list($plugin, $delta, $old_settings, $title) = $value;
|
||||
$settings = [];
|
||||
$settings['label'] = $title;
|
||||
if ($title) {
|
||||
$settings['label_display'] = BlockPluginInterface::BLOCK_LABEL_VISIBLE;
|
||||
}
|
||||
else {
|
||||
$settings['label_display'] = '0';
|
||||
}
|
||||
switch ($plugin) {
|
||||
case 'aggregator_feed_block':
|
||||
list(, $id) = explode('-', $delta);
|
||||
$settings['block_count'] = $old_settings['aggregator']['item_count'];
|
||||
$settings['feed'] = $id;
|
||||
break;
|
||||
case 'book_navigation':
|
||||
$settings['block_mode'] = $old_settings['book']['block_mode'];
|
||||
break;
|
||||
case 'forum_active_block':
|
||||
case 'forum_new_block':
|
||||
$settings['block_count'] = $old_settings['forum']['block_num'];
|
||||
break;
|
||||
case 'statistics_popular_block':
|
||||
$settings['top_day_num'] = $old_settings['statistics']['statistics_block_top_day_num'];
|
||||
$settings['top_all_num'] = $old_settings['statistics']['statistics_block_top_all_num'];
|
||||
$settings['top_last_num'] = $old_settings['statistics']['statistics_block_top_last_num'];
|
||||
break;
|
||||
case 'views_block:who_s_new-block_1':
|
||||
$settings['items_per_page'] = $old_settings['user']['block_whois_new_count'];
|
||||
break;
|
||||
case 'views_block:who_s_online-who_s_online_block':
|
||||
$settings['items_per_page'] = $old_settings['user']['max_list_count'];
|
||||
break;
|
||||
}
|
||||
return $settings;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,97 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\block\Plugin\migrate\process;
|
||||
|
||||
use Drupal\migrate\Plugin\MigrationInterface;
|
||||
use Drupal\migrate\MigrateExecutableInterface;
|
||||
use Drupal\migrate\ProcessPluginBase;
|
||||
use Drupal\migrate\Row;
|
||||
use Drupal\Core\Config\Config;
|
||||
use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
|
||||
use Symfony\Component\DependencyInjection\ContainerInterface;
|
||||
|
||||
/**
|
||||
* @MigrateProcessPlugin(
|
||||
* id = "block_theme"
|
||||
* )
|
||||
*/
|
||||
class BlockTheme extends ProcessPluginBase implements ContainerFactoryPluginInterface {
|
||||
|
||||
/**
|
||||
* Contains the configuration object factory.
|
||||
*
|
||||
* @var \Drupal\Core\Config\ConfigFactoryInterface
|
||||
*/
|
||||
protected $configFactory;
|
||||
|
||||
/**
|
||||
* Contains the system.theme configuration object.
|
||||
*
|
||||
* @var \Drupal\Core\Config\Config
|
||||
*/
|
||||
protected $themeConfig;
|
||||
|
||||
/**
|
||||
* Constructs a BlockTheme object.
|
||||
*
|
||||
* @param array $configuration
|
||||
* A configuration array containing information about the plugin instance.
|
||||
* @param string $plugin_id
|
||||
* The plugin ID for the plugin instance.
|
||||
* @param mixed $plugin_definition
|
||||
* The plugin implementation definition.
|
||||
* @param \Drupal\migrate\Plugin\MigrationInterface $migration
|
||||
* The migration entity.
|
||||
* @param \Drupal\Core\Config\Config $theme_config
|
||||
* The system.theme configuration factory object.
|
||||
* @param array $themes
|
||||
* The list of themes available on the destination.
|
||||
*/
|
||||
public function __construct(array $configuration, $plugin_id, $plugin_definition, MigrationInterface $migration, Config $theme_config, array $themes) {
|
||||
parent::__construct($configuration, $plugin_id, $plugin_definition, $migration);
|
||||
$this->themeConfig = $theme_config;
|
||||
$this->themes = $themes;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition, MigrationInterface $migration = NULL) {
|
||||
return new static(
|
||||
$configuration,
|
||||
$plugin_id,
|
||||
$plugin_definition,
|
||||
$migration,
|
||||
$container->get('config.factory')->get('system.theme'),
|
||||
$container->get('theme_handler')->listInfo()
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function transform($value, MigrateExecutableInterface $migrate_executable, Row $row, $destination_property) {
|
||||
list($theme, $default_theme, $admin_theme) = $value;
|
||||
|
||||
// If the source theme exists on the destination, we're good.
|
||||
if (isset($this->themes[$theme])) {
|
||||
return $theme;
|
||||
}
|
||||
|
||||
// If the source block is assigned to a region in the source default theme,
|
||||
// then assign it to the destination default theme.
|
||||
if (strtolower($theme) == strtolower($default_theme)) {
|
||||
return $this->themeConfig->get('default');
|
||||
}
|
||||
|
||||
// If the source block is assigned to a region in the source admin theme,
|
||||
// then assign it to the destination admin theme.
|
||||
if (strtolower($theme) == strtolower($admin_theme)) {
|
||||
return $this->themeConfig->get('admin');
|
||||
}
|
||||
|
||||
// We couldn't map it to a D8 theme so just return the incoming theme.
|
||||
return $theme;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,137 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\block\Plugin\migrate\process;
|
||||
|
||||
use Drupal\Core\Extension\ModuleHandlerInterface;
|
||||
use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
|
||||
use Drupal\migrate\Plugin\MigrationInterface;
|
||||
use Drupal\migrate\MigrateExecutableInterface;
|
||||
use Drupal\migrate\MigrateSkipRowException;
|
||||
use Drupal\migrate\Plugin\MigrateProcessInterface;
|
||||
use Drupal\migrate\ProcessPluginBase;
|
||||
use Drupal\migrate\Row;
|
||||
use Symfony\Component\DependencyInjection\ContainerInterface;
|
||||
|
||||
/**
|
||||
* @MigrateProcessPlugin(
|
||||
* id = "block_visibility"
|
||||
* )
|
||||
*/
|
||||
class BlockVisibility extends ProcessPluginBase implements ContainerFactoryPluginInterface {
|
||||
|
||||
/**
|
||||
* The module handler.
|
||||
*
|
||||
* @var \Drupal\Core\Extension\ModuleHandlerInterface
|
||||
*/
|
||||
protected $moduleHandler;
|
||||
|
||||
/**
|
||||
* The migration process plugin, configured for lookups in the d6_user_role
|
||||
* and d7_user_role migrations.
|
||||
*
|
||||
* @var \Drupal\migrate\Plugin\MigrateProcessInterface
|
||||
*/
|
||||
protected $migrationPlugin;
|
||||
|
||||
/**
|
||||
* Whether or not to skip blocks that use PHP for visibility. Only applies
|
||||
* if the PHP module is not enabled.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
protected $skipPHP = FALSE;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function __construct(array $configuration, $plugin_id, $plugin_definition, ModuleHandlerInterface $module_handler, MigrateProcessInterface $migration_plugin) {
|
||||
parent::__construct($configuration, $plugin_id, $plugin_definition);
|
||||
$this->moduleHandler = $module_handler;
|
||||
$this->migrationPlugin = $migration_plugin;
|
||||
|
||||
if (isset($configuration['skip_php'])) {
|
||||
$this->skipPHP = $configuration['skip_php'];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition, MigrationInterface $migration = NULL) {
|
||||
$migration_configuration = [
|
||||
'migration' => [
|
||||
'd6_user_role',
|
||||
'd7_user_role',
|
||||
],
|
||||
];
|
||||
return new static(
|
||||
$configuration,
|
||||
$plugin_id,
|
||||
$plugin_definition,
|
||||
$container->get('module_handler'),
|
||||
$container->get('plugin.manager.migrate.process')->createInstance('migration', $migration_configuration, $migration)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function transform($value, MigrateExecutableInterface $migrate_executable, Row $row, $destination_property) {
|
||||
list($old_visibility, $pages, $roles) = $value;
|
||||
|
||||
$visibility = [];
|
||||
|
||||
// If the block is assigned to specific roles, add the user_role condition.
|
||||
if ($roles) {
|
||||
$visibility['user_role'] = [
|
||||
'id' => 'user_role',
|
||||
'roles' => [],
|
||||
'context_mapping' => [
|
||||
'user' => '@user.current_user_context:current_user',
|
||||
],
|
||||
'negate' => FALSE,
|
||||
];
|
||||
|
||||
foreach ($roles as $key => $role_id) {
|
||||
$roles[$key] = $this->migrationPlugin->transform($role_id, $migrate_executable, $row, $destination_property);
|
||||
}
|
||||
$visibility['user_role']['roles'] = array_combine($roles, $roles);
|
||||
}
|
||||
|
||||
if ($pages) {
|
||||
// 2 == BLOCK_VISIBILITY_PHP in Drupal 6 and 7.
|
||||
if ($old_visibility == 2) {
|
||||
// If the PHP module is present, migrate the visibility code unaltered.
|
||||
if ($this->moduleHandler->moduleExists('php')) {
|
||||
$visibility['php'] = [
|
||||
'id' => 'php',
|
||||
// PHP code visibility could not be negated in Drupal 6 or 7.
|
||||
'negate' => FALSE,
|
||||
'php' => $pages,
|
||||
];
|
||||
}
|
||||
// Skip the row if we're configured to. If not, we don't need to do
|
||||
// anything else -- the block will simply have no PHP or request_path
|
||||
// visibility configuration.
|
||||
elseif ($this->skipPHP) {
|
||||
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 {
|
||||
$paths = preg_split("(\r\n?|\n)", $pages);
|
||||
foreach ($paths as $key => $path) {
|
||||
$paths[$key] = $path === '<front>' ? $path : '/' . ltrim($path, '/');
|
||||
}
|
||||
$visibility['request_path'] = [
|
||||
'id' => 'request_path',
|
||||
'negate' => !$old_visibility,
|
||||
'pages' => implode("\n", $paths),
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
return $visibility;
|
||||
}
|
||||
|
||||
}
|
177
2017/web/core/modules/block/src/Plugin/migrate/source/Block.php
Normal file
177
2017/web/core/modules/block/src/Plugin/migrate/source/Block.php
Normal file
|
@ -0,0 +1,177 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\block\Plugin\migrate\source;
|
||||
|
||||
use Drupal\migrate\Row;
|
||||
use Drupal\migrate_drupal\Plugin\migrate\source\DrupalSqlBase;
|
||||
|
||||
/**
|
||||
* Drupal block source from database.
|
||||
*
|
||||
* @MigrateSource(
|
||||
* id = "block",
|
||||
* source_module = "block"
|
||||
* )
|
||||
*/
|
||||
class Block extends DrupalSqlBase {
|
||||
|
||||
/**
|
||||
* The default theme name.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $defaultTheme;
|
||||
|
||||
/**
|
||||
* The admin theme name.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $adminTheme;
|
||||
|
||||
/**
|
||||
* Table containing block configuration.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $blockTable;
|
||||
|
||||
/**
|
||||
* Table mapping blocks to user roles.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $blockRoleTable;
|
||||
|
||||
/**
|
||||
* Table listing user roles.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $userRoleTable;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function query() {
|
||||
if ($this->getModuleSchemaVersion('system') >= 7000) {
|
||||
$this->blockTable = 'block';
|
||||
$this->blockRoleTable = 'block_role';
|
||||
}
|
||||
else {
|
||||
$this->blockTable = 'blocks';
|
||||
$this->blockRoleTable = 'blocks_roles';
|
||||
}
|
||||
// Drupal 6 & 7 both use the same name for the user roles table.
|
||||
$this->userRoleTable = 'role';
|
||||
|
||||
return $this->select($this->blockTable, 'b')->fields('b');
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function initializeIterator() {
|
||||
$this->defaultTheme = $this->variableGet('theme_default', 'Garland');
|
||||
$this->adminTheme = $this->variableGet('admin_theme', NULL);
|
||||
return parent::initializeIterator();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function fields() {
|
||||
return [
|
||||
'bid' => $this->t('The block numeric identifier.'),
|
||||
'module' => $this->t('The module providing the block.'),
|
||||
'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.'),
|
||||
'region' => $this->t('Region the block is placed in.'),
|
||||
'visibility' => $this->t('Visibility expression.'),
|
||||
'pages' => $this->t('Pages list.'),
|
||||
'title' => $this->t('Block title.'),
|
||||
'cache' => $this->t('Cache rule.'),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getIds() {
|
||||
$ids['module']['type'] = 'string';
|
||||
$ids['delta']['type'] = 'string';
|
||||
$ids['theme']['type'] = 'string';
|
||||
return $ids;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function prepareRow(Row $row) {
|
||||
$row->setSourceProperty('default_theme', $this->defaultTheme);
|
||||
$row->setSourceProperty('admin_theme', $this->adminTheme);
|
||||
|
||||
$module = $row->getSourceProperty('module');
|
||||
$delta = $row->getSourceProperty('delta');
|
||||
|
||||
$query = $this->select($this->blockRoleTable, 'br')
|
||||
->fields('br', ['rid'])
|
||||
->condition('module', $module)
|
||||
->condition('delta', $delta);
|
||||
$query->join($this->userRoleTable, 'ur', 'br.rid = ur.rid');
|
||||
$roles = $query->execute()
|
||||
->fetchCol();
|
||||
$row->setSourceProperty('roles', $roles);
|
||||
|
||||
$settings = [];
|
||||
switch ($module) {
|
||||
case 'aggregator':
|
||||
list($type, $id) = explode('-', $delta);
|
||||
if ($type == 'feed') {
|
||||
$item_count = $this->select('aggregator_feed', 'af')
|
||||
->fields('af', ['block'])
|
||||
->condition('fid', $id)
|
||||
->execute()
|
||||
->fetchField();
|
||||
}
|
||||
else {
|
||||
$item_count = $this->select('aggregator_category', 'ac')
|
||||
->fields('ac', ['block'])
|
||||
->condition('cid', $id)
|
||||
->execute()
|
||||
->fetchField();
|
||||
}
|
||||
$settings['aggregator']['item_count'] = $item_count;
|
||||
break;
|
||||
case 'book':
|
||||
$settings['book']['block_mode'] = $this->variableGet('book_block_mode', 'all pages');
|
||||
break;
|
||||
case 'forum':
|
||||
$settings['forum']['block_num'] = $this->variableGet('forum_block_num_' . $delta, 5);
|
||||
break;
|
||||
case 'statistics':
|
||||
foreach (['statistics_block_top_day_num', 'statistics_block_top_all_num', 'statistics_block_top_last_num'] as $name) {
|
||||
$settings['statistics'][$name] = $this->variableGet($name, 0);
|
||||
}
|
||||
break;
|
||||
case 'user':
|
||||
switch ($delta) {
|
||||
case 2:
|
||||
case 'new':
|
||||
$settings['user']['block_whois_new_count'] = $this->variableGet('user_block_whois_new_count', 5);
|
||||
break;
|
||||
case 3:
|
||||
case 'online':
|
||||
$settings['user']['block_seconds_online'] = $this->variableGet('user_block_seconds_online', 900);
|
||||
$settings['user']['max_list_count'] = $this->variableGet('user_block_max_list_count', 10);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
$row->setSourceProperty('settings', $settings);
|
||||
return parent::prepareRow($row);
|
||||
}
|
||||
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,99 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\block\Plugin\migrate\source\d7;
|
||||
|
||||
use Drupal\block\Plugin\migrate\source\Block;
|
||||
|
||||
/**
|
||||
* Gets i18n block data from source database.
|
||||
*
|
||||
* @MigrateSource(
|
||||
* id = "d7_block_translation",
|
||||
* source_module = "i18n_block"
|
||||
* )
|
||||
*/
|
||||
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_string', 'i18n')
|
||||
->fields('i18n')
|
||||
->fields('b', [
|
||||
'bid',
|
||||
'module',
|
||||
'delta',
|
||||
'theme',
|
||||
'status',
|
||||
'weight',
|
||||
'region',
|
||||
'custom',
|
||||
'visibility',
|
||||
'pages',
|
||||
'title',
|
||||
'cache',
|
||||
'i18n_mode',
|
||||
])
|
||||
->fields('lt', [
|
||||
'lid',
|
||||
'translation',
|
||||
'language',
|
||||
'plid',
|
||||
'plural',
|
||||
'i18n_status',
|
||||
])
|
||||
->condition('i18n_mode', 1);
|
||||
$query->leftjoin($this->blockTable, 'b', ('b.delta = i18n.objectid'));
|
||||
$query->leftjoin('locales_target', 'lt', 'lt.lid = i18n.lid');
|
||||
return $query;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function fields() {
|
||||
return [
|
||||
'bid' => $this->t('The block numeric identifier.'),
|
||||
'module' => $this->t('The module providing the block.'),
|
||||
'delta' => $this->t("The block's delta."),
|
||||
'theme' => $this->t('Which theme the block is placed in.'),
|
||||
'status' => $this->t('Block enabled status'),
|
||||
'weight' => $this->t('Block weight within region'),
|
||||
'region' => $this->t('Theme region within which the block is set'),
|
||||
'visibility' => $this->t('Visibility'),
|
||||
'pages' => $this->t('Pages list.'),
|
||||
'title' => $this->t('Block title.'),
|
||||
'cache' => $this->t('Cache rule.'),
|
||||
'i18n_mode' => $this->t('Multilingual mode'),
|
||||
'lid' => $this->t('Language string ID'),
|
||||
'textgroup' => $this->t('A module defined group of translations'),
|
||||
'context' => $this->t('Full string ID for quick search: type:objectid:property.'),
|
||||
'objectid' => $this->t('Object ID'),
|
||||
'type' => $this->t('Object type for this string'),
|
||||
'property' => $this->t('Object property for this string'),
|
||||
'objectindex' => $this->t('Integer value of Object ID'),
|
||||
'format' => $this->t('The {filter_format}.format of the string'),
|
||||
'translation' => $this->t('Translation'),
|
||||
'language' => $this->t('Language code'),
|
||||
'plid' => $this->t('Parent lid'),
|
||||
'plural' => $this->t('Plural index number'),
|
||||
'i18n_status' => $this->t('Translation needs update'),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getIds() {
|
||||
$ids['delta']['type'] = 'string';
|
||||
$ids['delta']['alias'] = 'b';
|
||||
$ids['language']['type'] = 'string';
|
||||
return $ids;
|
||||
}
|
||||
|
||||
}
|
78
2017/web/core/modules/block/src/Tests/BlockTestBase.php
Normal file
78
2017/web/core/modules/block/src/Tests/BlockTestBase.php
Normal file
|
@ -0,0 +1,78 @@
|
|||
<?php
|
||||
|
||||
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 {
|
||||
|
||||
/**
|
||||
* 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;
|
||||
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\block\Theme;
|
||||
|
||||
use Drupal\Core\Routing\RouteMatchInterface;
|
||||
use Drupal\Core\Theme\ThemeNegotiatorInterface;
|
||||
|
||||
/**
|
||||
* Negotiates the theme for the block admin demo page via the URL.
|
||||
*/
|
||||
class AdminDemoNegotiator implements ThemeNegotiatorInterface {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function applies(RouteMatchInterface $route_match) {
|
||||
return $route_match->getRouteName() == 'block.admin_demo';
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function determineActiveTheme(RouteMatchInterface $route_match) {
|
||||
// We return exactly what was passed in, to guarantee that the page will
|
||||
// always be displayed using the theme whose blocks are being configured.
|
||||
return $route_match->getParameter('theme');
|
||||
}
|
||||
|
||||
}
|
Reference in a new issue