Commit 262b7fcc authored by catch's avatar catch
Browse files

Issue #3084472 by Berdir, JeroenT, ravi.shankar, rpsu: Remove Place Blocks module

parent 89d0409f
......@@ -517,7 +517,6 @@
"drupal/big_pipe": "self.version",
"drupal/block": "self.version",
"drupal/block_content": "self.version",
"drupal/block_place": "self.version",
"drupal/book": "self.version",
"drupal/breakpoint": "self.version",
"drupal/ckeditor": "self.version",
......
......@@ -61,7 +61,6 @@
"drupal/big_pipe": "self.version",
"drupal/block": "self.version",
"drupal/block_content": "self.version",
"drupal/block_place": "self.version",
"drupal/book": "self.version",
"drupal/breakpoint": "self.version",
"drupal/ckeditor": "self.version",
......
name: Place Blocks
type: module
description: 'Allow administrators to place blocks from any Drupal page. This module is deprecated in Drupal 8.8.0 and will be removed in Drupal 9.0.0. See the change record for a list of alternatives. See https://www.drupal.org/node/3081957.'
package: Core (Experimental)
version: VERSION
hidden: true
dependencies:
- drupal:block
<?php
/**
* @file
* Contains install and update functions for Place Blocks.
*/
/**
* Implements hook_requirements().
*/
function block_place_requirements($phase) {
$requirements = [];
// Notify about the module being deprecated.
if ($phase == 'runtime') {
$requirements['block_place'] = [
'title' => t('Place blocks'),
'severity' => REQUIREMENT_INFO,
'description' => t('Place Blocks (Core, Experimental) is deprecated in Drupal 8.8.0 and will be removed in Drupal 9.0.0. See <a href=":change-record">See the change record for a list of alternatives</a>.', [
':change-record' => 'https://www.drupal.org/node/3081957',
]),
];
}
return $requirements;
}
/**
* Implements hook_install().
*/
function block_place_install() {
\Drupal::messenger()->addWarning(t('Place Blocks (Core, Experimental) is deprecated in Drupal 8.8.0 and will be removed in Drupal 9.0.0. See the change record for a list of alternatives. See <a href=":change-record">the change record</a>.', [
':change-record' => 'https://www.drupal.org/node/3081957',
]));
}
drupal.block_place:
version: VERSION
css:
theme:
css/block-place.css: {}
deprecated: The "%library_id%" asset is deprecated in drupal:8.8.0 and will be removed in drupal:9.0.0. See the change record for a list of alternatives. See https://www.drupal.org/node/3081957.
drupal.block_place.icons:
version: VERSION
css:
theme:
css/block-place.icons.theme.css: {}
deprecated: The "%library_id%" asset is deprecated in drupal:8.8.0 and will be removed in drupal:9.0.0. See the change record for a list of alternatives. See https://www.drupal.org/node/3081957.
<?php
/**
* @file
* Controls the placement of blocks from all pages.
*
* @deprecated in drupal:8.8.0 and is removed from drupal:9.0.0. See the
* change record for a list of alternatives.
*
* @see https://www.drupal.org/node/3081957
*/
use Drupal\Core\Routing\RouteMatchInterface;
use Drupal\Core\Url;
@trigger_error('The Place Blocks module is deprecated in drupal:8.8.0 and will be removed from drupal:9.0.0. See the change record for a list of alternatives. See https://www.drupal.org/node/3081957.', E_USER_DEPRECATED);
/**
* Implements hook_help().
*/
function block_place_help($route_name, RouteMatchInterface $route_match) {
switch ($route_name) {
case 'help.page.block_place':
$output = '<h3>' . t('About') . '</h3>';
$output .= '<p><strong>' . t('Place Blocks (Core, Experimental) is deprecated in Drupal 8.8.0 and will be removed in Drupal 9.0.0. See the change record for a list of alternatives. See <a href=":change-record">the change record</a>.', [
':change-record' => 'https://www.drupal.org/node/3081957',
]) . '</strong></p>';
$output .= '<p>' . t('The Place Blocks module allows you to place blocks from every page. For more information, see the <a href=":blocks-documentation">online documentation for the Place Blocks module</a>.', [':blocks-documentation' => 'https://www.drupal.org/documentation/modules/block_place/']) . '</p>';
$output .= '<h3>' . t('Uses') . '</h3>';
$output .= '<p>' . t('Block placement is specific to each theme on your site. This module allows you to place blocks in the context of your content pages.') . '</p>';
return $output;
}
}
/**
* Implements hook_toolbar().
*/
function block_place_toolbar() {
// Link to the current page with a query parameter.
$query = \Drupal::request()->query->all();
$wrapper_class = '';
$status_class = '';
$description = '';
if (isset($query['block-place'])) {
$status_class = 'active';
$wrapper_class = 'is-active';
$description = t('Exit Place block mode.');
unset($query['block-place']);
unset($query['destination']);
}
else {
$status_class = 'inactive';
$description = t('Show regions to Place blocks.');
$query['block-place'] = '1';
// Setting destination is both a work-around for the toolbar "Back to site"
// link in escapeAdmin.js and used for the destination after picking a
// block.
$query['destination'] = Url::fromRoute('<current>')->toString();
}
// Remove on Admin routes.
$admin_route = \Drupal::service('router.admin_context')->isAdminRoute();
// Remove on Block Demo page.
$admin_demo = \Drupal::routeMatch()->getRouteName() === 'block.admin_demo';
$access = (\Drupal::currentUser()->hasPermission('administer blocks') && !$admin_route && !$admin_demo);
// The 'Place Block' tab is a simple link, with no corresponding tray.
$items['block_place'] = [
'#cache' => [
'contexts' => ['user.permissions', 'url.query_args'],
],
'#type' => 'toolbar_item',
'tab' => [
'#access' => $access,
'#type' => 'link',
'#title' => t('Place block'),
'#url' => Url::fromRoute('<current>', [], ['query' => $query]),
'#attributes' => [
'title' => $description,
'class' => ['toolbar-icon', 'toolbar-icon-place-block-' . $status_class],
],
],
'#wrapper_attributes' => [
'class' => ['toolbar-tab', 'block-place-toolbar-tab', $wrapper_class],
],
'#weight' => 100,
'#attached' => [
'library' => [
'block_place/drupal.block_place.icons',
],
],
];
return $items;
}
services:
block_place.page_display_variant_subscriber.block:
class: Drupal\block_place\EventSubscriber\BlockPlaceEventSubscriber
arguments: ['@request_stack', '@current_user']
tags:
- { name: event_subscriber }
deprecated: The "%service_id%" service is deprecated in drupal:8.8.0 and will be removed in drupal:9.0.0. See the change record for a list of alternatives. See https://www.drupal.org/node/3081957.
/**
* @file
* Styling for block_place module regions and buttons during block placement.
*/
.block-place-region {
margin: 1em 0;
padding: 5px;
text-align: center;
outline: 1px dashed rgba(0, 0, 0, 0.5);
box-shadow: 0 0 0 1px rgba(255, 255, 255, 0.7);
text-shadow: none;
}
.block-place-region a.button {
position: relative;
box-sizing: border-box;
width: 26px;
height: 26px;
padding: 0;
white-space: nowrap;
border: 1px solid #ccc;
background: url(../../../misc/icons/bebebe/plus.svg) #fff center center / 16px 16px no-repeat;
font-size: 1rem;
}
.block-place-region:hover a.button,
.block-place-region:focus a.button {
background-image: url(../../../misc/icons/787878/plus.svg);
}
.block-place-region .ajax-progress {
position: relative;
top: -10px;
right: 26px; /* LTR */
overflow: visible;
width: 0;
height: 0;
padding: 0;
}
[dir="rtl"] .block-place-region .ajax-progress {
right: inherit;
left: 26px;
float: inherit;
}
.block-place-region .ajax-progress-throbber .throbber {
display: block;
box-sizing: border-box;
width: 26px;
height: 26px;
padding: 0;
border: 1px solid #ddd;
border-radius: 100px;
background-color: #fff;
background-position: center 6px;
}
/**
* @file
* Styling for block_place module toolbar icons.
*/
.toolbar .block-place-toolbar-tab.is-active {
background-image: -webkit-linear-gradient(rgba(255, 255, 255, 0.25) 20%, transparent 200%);
background-image: linear-gradient(rgba(255, 255, 255, 0.25) 20%, transparent 200%);
}
.toolbar .toolbar-bar .block-place-toolbar-tab {
float: right;
}
[dir="rtl"] .toolbar .toolbar-bar .block-place-toolbar-tab {
float: left;
}
.toolbar-bar .toolbar-icon-place-block-active:before {
background-image: url(../icons/ffffff/place-block.svg);
}
.toolbar-bar .toolbar-icon-place-block-inactive:before {
background-image: url(../icons/bebebe/place-block.svg);
}
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" id="Layer_1" x="0" y="0" width="16" height="16" viewBox="0 0 16 16" enable-background="new 0 0 16 16" xml:space="preserve"><rect x="1" y="6" fill="#bebebe" width="14" height="9"/><ellipse fill="#bebebe" cx="11.48" cy="3.68" rx="2.23" ry="0.61"/><rect x="9.25" y="3.68" fill="#bebebe" width="4.45" height="3.35"/><ellipse fill="#bebebe" cx="4.48" cy="3.68" rx="2.23" ry="0.61"/><rect x="2.25" y="3.68" fill="#bebebe" width="4.45" height="3.35"/></svg>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" id="Layer_1" x="0" y="0" width="16" height="16" viewBox="0 0 16 16" enable-background="new 0 0 16 16" xml:space="preserve"><rect x="1" y="6" fill="#ffffff" width="14" height="9"/><ellipse fill="#ffffff" cx="11.48" cy="3.68" rx="2.23" ry="0.61"/><rect x="9.25" y="3.68" fill="#ffffff" width="4.45" height="3.35"/><ellipse fill="#ffffff" cx="4.48" cy="3.68" rx="2.23" ry="0.61"/><rect x="2.25" y="3.68" fill="#ffffff" width="4.45" height="3.35"/></svg>
<?php
namespace Drupal\block_place\EventSubscriber;
use Drupal\Core\Render\PageDisplayVariantSelectionEvent;
use Drupal\Core\Render\RenderEvents;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpFoundation\RequestStack;
use Drupal\Core\Session\AccountInterface;
/**
* @see \Drupal\block_place\Plugin\DisplayVariant\PlaceBlockPageVariant
*/
class BlockPlaceEventSubscriber implements EventSubscriberInterface {
/**
* The request stack.
*
* @var \Symfony\Component\HttpFoundation\RequestStack
*/
protected $requestStack;
/**
* The current user.
*
* @var \Drupal\Core\Session\AccountInterface
*/
protected $account;
/**
* Constructs a \Drupal\block_place\EventSubscriber\BlockPlaceEventSubscriber object.
*
* @param \Symfony\Component\HttpFoundation\RequestStack $request_stack
* The request stack used to retrieve the current request.
* @param \Drupal\Core\Session\AccountInterface $account
* The current user.
*/
public function __construct(RequestStack $request_stack, AccountInterface $account) {
$this->requestStack = $request_stack;
$this->account = $account;
}
/**
* Selects the block place override of the block page display variant.
*
* @param \Drupal\Core\Render\PageDisplayVariantSelectionEvent $event
* The event to process.
*/
public function onBlockPageDisplayVariantSelected(PageDisplayVariantSelectionEvent $event) {
if ($event->getPluginId() === 'block_page') {
if ($this->requestStack->getCurrentRequest()->query->has('block-place') && $this->account->hasPermission('administer blocks')) {
$event->setPluginId('block_place_page');
}
$event->addCacheContexts(['user.permissions', 'url.query_args']);
}
}
/**
* {@inheritdoc}
*/
public static function getSubscribedEvents() {
// Set a very low priority, so that it runs last.
$events[RenderEvents::SELECT_PAGE_DISPLAY_VARIANT][] = ['onBlockPageDisplayVariantSelected', -1000];
return $events;
}
}
<?php
namespace Drupal\block_place\Plugin\DisplayVariant;
use Drupal\block\BlockRepositoryInterface;
use Drupal\block\Plugin\DisplayVariant\BlockPageVariant;
use Drupal\Component\Serialization\Json;
use Drupal\Core\Entity\EntityViewBuilderInterface;
use Drupal\Core\Routing\RedirectDestinationInterface;
use Drupal\Core\Theme\ThemeManagerInterface;
use Drupal\Core\Link;
use Symfony\Component\DependencyInjection\ContainerInterface;
/**
* Allows blocks to be placed directly within a region.
*
* @PageDisplayVariant(
* id = "block_place_page",
* admin_label = @Translation("Page with blocks and place block buttons")
* )
*
* @deprecated in drupal:8.8.0 and is removed from drupal:9.0.0. See the
* change record for a list of alternatives.
*
* @see https://www.drupal.org/node/3081957
*/
class PlaceBlockPageVariant extends BlockPageVariant {
/**
* The theme manager.
*
* @var \Drupal\Core\Theme\ThemeManagerInterface
*/
protected $themeManager;
/**
* The redirect destination.
*
* @var \Drupal\Core\Routing\RedirectDestinationInterface
*/
protected $redirectDestination;
/**
* Constructs a new PlaceBlockPageVariant.
*
* @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.
* @param \Drupal\Core\Theme\ThemeManagerInterface $theme_manager
* The theme manager.
* @param \Drupal\Core\Routing\RedirectDestinationInterface $redirect_destination
* The redirect destination.
*/
public function __construct(array $configuration, $plugin_id, $plugin_definition, BlockRepositoryInterface $block_repository, EntityViewBuilderInterface $block_view_builder, array $block_list_cache_tags, ThemeManagerInterface $theme_manager, RedirectDestinationInterface $redirect_destination) {
@trigger_error('The ' . __NAMESPACE__ . '\PlaceBlockPageVariant is deprecated in drupal:8.8.0 and will be removed from drupal:9.0.0. See the change record for a list of alternatives. See https://www.drupal.org/node/3081957.', E_USER_DEPRECATED);
parent::__construct($configuration, $plugin_id, $plugin_definition, $block_repository, $block_view_builder, $block_list_cache_tags);
$this->themeManager = $theme_manager;
$this->redirectDestination = $redirect_destination;
}
/**
* {@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_type.manager')->getViewBuilder('block'),
$container->get('entity_type.manager')->getDefinition('block')->getListCacheTags(),
$container->get('theme.manager'),
$container->get('redirect.destination')
);
}
/**
* {@inheritdoc}
*/
public function build() {
$build = parent::build();
$active_theme = $this->themeManager->getActiveTheme();
$theme_name = $active_theme->getName();
$destination = $this->redirectDestination->get();
$visible_regions = $this->getVisibleRegionNames($theme_name);
// Build an array of the region names in the right order.
$build += array_fill_keys(array_keys($visible_regions), []);
foreach ($visible_regions as $region => $region_name) {
$query = [
'region' => $region,
];
if ($destination) {
$query['destination'] = $destination;
}
$title = $this->t('<span class="visually-hidden">Place block in the %region region</span>', ['%region' => $region_name]);
$operations['block_description'] = [
'#type' => 'inline_template',
'#template' => '<div class="block-place-region">{{ link }}</div>',
'#context' => [
'link' => Link::createFromRoute($title, 'block.admin_library', ['theme' => $theme_name], [
'query' => $query,
'attributes' => [
'title' => $title,
'class' => ['use-ajax', 'button', 'button--small'],
'data-dialog-type' => 'modal',
'data-dialog-options' => Json::encode([
'width' => 700,
]),
],
]),
],
];
$build[$region] = ['block_place_operations' => $operations] + $build[$region];
}
$build['#attached']['library'][] = 'block_place/drupal.block_place';
return $build;
}
/**
* 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);
}
}
<?php
namespace Drupal\Tests\block_place\Functional;
use Drupal\Core\Url;
use Drupal\Tests\BrowserTestBase;
/**
* Tests the placing a block.
*
* @group block_place
* @group legacy
*/
class BlockPlaceTest extends BrowserTestBase {
/**
* Modules to install.
*
* @var array
*/
public static $modules = ['block', 'block_place', 'toolbar'];
/**
* {@inheritdoc}
*/
protected $defaultTheme = 'stark';
/**
* Tests placing blocks as an admin.
*/
public function testPlacingBlocksAdmin() {
// Create administrative user.
$this->drupalLogin($this->drupalCreateUser([
'access administration pages',
'access toolbar',
'administer blocks',
'view the administration theme',
]));
$this->drupalGet(Url::fromRoute('<front>'));
$this->clickLink('Place block');
// Each region should have one link to place a block.
$theme_name = $this->container->get('theme.manager')->getActiveTheme()->getName();
$visible_regions = system_region_list($theme_name, REGIONS_VISIBLE);
$this->assertGreaterThan(0, count($visible_regions));
$default_theme = $this->config('system.theme')->get('default');
$block_library_url = Url::fromRoute('block.admin_library', ['theme' => $default_theme]);
foreach ($visible_regions as $region => $name) {
$block_library_url->setOption('query', ['region' => $region]);
$links = $this->xpath('//a[contains(@href, :href)]', [':href' => $block_library_url->toString()]);
$this->assertEquals(1, count($links));
list(, $query_string) = explode('?', $links[0]->getAttribute('href'), 2);
parse_str($query_string, $query_parts);
$this->assertNotEmpty($query_parts['destination']);
// Get the text inside the div->a->span->em.
$demo_block = $this->xpath('//div[@class="block-place-region"]/a/span[text()="Place block in the "]/em[text()="' . $name . '"]');
$this->assertEquals(1, count($demo_block));
}
}
/**
* Tests placing blocks as an unprivileged user.
*/
public function testPlacingBlocksUnprivileged() {
// Create a user who cannot administer blocks.
$this->drupalLogin($this->drupalCreateUser([
'access administration pages',
'access toolbar',
'view the administration theme',
]));
$this->drupalGet(Url::fromRoute('<front>'));
$links = $this->xpath('//a[text()=:label]', [':label' => 'Place block']);
$this->assertEmpty($links);
$this->drupalGet(Url::fromRoute('block.admin_library', ['theme' => 'classy']));
$this->assertSession()->statusCodeEquals(403);
}
}
......@@ -6,7 +6,6 @@
use Drupal\Core\Extension\ExtensionDiscovery;
use Drupal\Core\Field\BaseFieldDefinition;
use Drupal\entity_test\Entity\EntityTest;
use Drupal\Tests\DeprecatedModulesTestTrait;
/**
* Tests the field type manager.
......@@ -15,8 +14,6 @@
*/
class FieldTypePluginManagerTest extends FieldKernelTestBase {
use DeprecatedModulesTestTrait;
/**
* Tests the default settings convenience methods.
*/
......