diff --git a/core/modules/block/block.module b/core/modules/block/block.module index 2f96a90e7568218c1ad05c99f5e2bcc4a49fced6..7e39da4006866c82cd36b81c17669bae9849fa38 100644 --- a/core/modules/block/block.module +++ b/core/modules/block/block.module @@ -5,7 +5,6 @@ * Controls the visual building blocks a page is constructed with. */ -use Drupal\block\BlockInterface; use Drupal\Component\Utility\Html; use Drupal\Core\Routing\RouteMatchInterface; use Drupal\Core\Url; @@ -144,17 +143,14 @@ function block_rebuild() { $blocks = \Drupal::entityTypeManager()->getStorage('block')->loadByProperties(['theme' => $theme]); foreach ($blocks as $block_id => $block) { // Disable blocks in invalid regions. - $region = $block->getRegion(); - if ($region !== BlockInterface::BLOCK_REGION_NONE) { - if (!empty($region) && !isset($regions[$region]) && $block->status()) { - drupal_set_message(t('The block %info was assigned to the invalid region %region and has been disabled.', ['%info' => $block_id, '%region' => $region]), 'warning'); - $block->disable(); - } - // Set region to none if not enabled. - if (!$block->status()) { - $block->setRegion(BlockInterface::BLOCK_REGION_NONE); - $block->save(); + if (!isset($regions[$block->getRegion()])) { + if ($block->status()) { + drupal_set_message(t('The block %info was assigned to the invalid region %region and has been disabled.', ['%info' => $block_id, '%region' => $block->getRegion()]), 'warning'); } + $block + ->setRegion(system_default_region($theme)) + ->disable() + ->save(); } } } diff --git a/core/modules/block/block.post_update.php b/core/modules/block/block.post_update.php index f208f6518d6c89226a22dd7269c2379433834780..7bab4137d8aef899a7b4ea7baeb9e85fe792c0f8 100644 --- a/core/modules/block/block.post_update.php +++ b/core/modules/block/block.post_update.php @@ -74,6 +74,13 @@ function block_post_update_disable_blocks_with_missing_contexts() { } } +/** + * Disable blocks that are placed into the "disabled" region. + */ +function block_post_update_disabled_region_update() { + // An empty update will flush caches, forcing block_rebuild() to run. +} + /** * @} End of "addtogroup updates-8.0.0-beta". */ diff --git a/core/modules/block/block.routing.yml b/core/modules/block/block.routing.yml index 396bf0d1705532c85542c3f644a3342afd154a78..e12cd8b1af827a679d87ef72797ee110e1366439 100644 --- a/core/modules/block/block.routing.yml +++ b/core/modules/block/block.routing.yml @@ -25,6 +25,22 @@ entity.block.edit_form: requirements: _entity_access: 'block.update' +entity.block.enable: + path: '/admin/structure/block/manage/{block}/enable' + defaults: + _controller: '\Drupal\block\Controller\BlockController::performOperation' + op: enable + requirements: + _entity_access: 'block.enable' + +entity.block.disable: + path: '/admin/structure/block/manage/{block}/disable' + defaults: + _controller: '\Drupal\block\Controller\BlockController::performOperation' + op: disable + requirements: + _entity_access: 'block.disable' + block.admin_display: path: '/admin/structure/block' defaults: diff --git a/core/modules/block/css/block.admin.css b/core/modules/block/css/block.admin.css index ed120389edd4fd4fbc9fa1741db8fa7ac2a75cd6..7fde3d706344235053d44af5fb28f8d159db1415 100644 --- a/core/modules/block/css/block.admin.css +++ b/core/modules/block/css/block.admin.css @@ -40,3 +40,7 @@ a.block-demo-backlink:hover { .block-form .form-item-settings-admin-label label:after { content: ':'; } +.block-disabled:not(:hover) { + background: #fcfcfa; + opacity: 0.675; +} diff --git a/core/modules/block/src/BlockForm.php b/core/modules/block/src/BlockForm.php index 1b1f4278fec0d37b39fe92636efbb48a2515e67b..9b1b027750d8433f49918616fa044aba75b75ad5 100644 --- a/core/modules/block/src/BlockForm.php +++ b/core/modules/block/src/BlockForm.php @@ -188,7 +188,7 @@ public function form(array $form, FormStateInterface $form_state) { '#title' => $this->t('Region'), '#description' => $this->t('Select the region where this block should be displayed.'), '#default_value' => $region, - '#empty_value' => BlockInterface::BLOCK_REGION_NONE, + '#required' => TRUE, '#options' => system_region_list($theme, REGIONS_VISIBLE), '#prefix' => '<div id="edit-block-region-wrapper">', '#suffix' => '</div>', diff --git a/core/modules/block/src/BlockInterface.php b/core/modules/block/src/BlockInterface.php index bd46671db39c23776e3b1cca6ce11f90a9ed4dac..0056523a1cc2857b9bd74ae4ac9b329bece4a1e9 100644 --- a/core/modules/block/src/BlockInterface.php +++ b/core/modules/block/src/BlockInterface.php @@ -16,6 +16,8 @@ interface BlockInterface extends ConfigEntityInterface { /** * 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; diff --git a/core/modules/block/src/BlockListBuilder.php b/core/modules/block/src/BlockListBuilder.php index 3365415be5bf4498a41a2f31c09d1a8ade84a471..7858d6bb6edc3e0db2135e3278eced54b162e6f4 100644 --- a/core/modules/block/src/BlockListBuilder.php +++ b/core/modules/block/src/BlockListBuilder.php @@ -156,6 +156,7 @@ protected function buildBlocksForm() { 'weight' => $entity->getWeight(), 'entity' => $entity, 'category' => $definition['category'], + 'status' => $entity->status(), ); } @@ -186,8 +187,7 @@ protected function buildBlocksForm() { // Loop over each region and build blocks. $regions = $this->systemRegionList($this->getThemeName(), REGIONS_VISIBLE); - $block_regions_with_disabled = $regions + array(BlockInterface::BLOCK_REGION_NONE => $this->t('Disabled', array(), array('context' => 'Plural'))); - foreach ($block_regions_with_disabled as $region => $title) { + foreach ($regions as $region => $title) { $form['#tabledrag'][] = array( 'action' => 'match', 'relationship' => 'sibling', @@ -214,9 +214,9 @@ protected function buildBlocksForm() { '#attributes' => array('class' => 'region-title__action'), ) ), - '#prefix' => $region != BlockInterface::BLOCK_REGION_NONE ? $title : $block_regions_with_disabled[$region], + '#prefix' => $title, '#type' => 'link', - '#title' => $this->t('Place block <span class="visually-hidden">in the %region region</span>', ['%region' => $block_regions_with_disabled[$region]]), + '#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' => array( 'colspan' => 5, @@ -255,12 +255,13 @@ protected function buildBlocksForm() { 'class' => array('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'] = array( - '#plain_text' => $info['label'], + '#plain_text' => $info['status'] ? $info['label'] : $this->t('@label (disabled)', ['@label' => $info['label']]), '#wrapper_attributes' => array( 'class' => array('block'), ), @@ -271,7 +272,7 @@ protected function buildBlocksForm() { $form[$entity_id]['region-theme']['region'] = array( '#type' => 'select', '#default_value' => $region, - '#empty_value' => BlockInterface::BLOCK_REGION_NONE, + '#required' => TRUE, '#title' => $this->t('Region for @block block', array('@block' => $info['label'])), '#title_display' => 'invisible', '#options' => $regions, @@ -361,12 +362,6 @@ public function submitForm(array &$form, FormStateInterface $form_state) { $entity_values = $form_state->getValue(array('blocks', $entity_id)); $entity->setWeight($entity_values['weight']); $entity->setRegion($entity_values['region']); - if ($entity->getRegion() == BlockInterface::BLOCK_REGION_NONE) { - $entity->disable(); - } - else { - $entity->enable(); - } $entity->save(); } drupal_set_message(t('The block settings have been updated.')); diff --git a/core/modules/block/src/Controller/BlockController.php b/core/modules/block/src/Controller/BlockController.php index d8f4226d0169348bffcdce191c0f9bdc7b4b59dc..58417d515f422357ef27f287bd369878abd07902 100644 --- a/core/modules/block/src/Controller/BlockController.php +++ b/core/modules/block/src/Controller/BlockController.php @@ -3,6 +3,7 @@ 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; @@ -39,6 +40,23 @@ public static function create(ContainerInterface $container) { ); } + /** + * 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(); + drupal_set_message($this->t('The block settings have been updated.')); + return $this->redirect('block.admin_display'); + } + /** * Returns a block theme demo page. * diff --git a/core/modules/block/src/Entity/Block.php b/core/modules/block/src/Entity/Block.php index 9cbd30b3b3a61b876f40d05ae07ddbaa1c9ec922..63b520543337f1ad73d7008ed2780fcaff19cfb6 100644 --- a/core/modules/block/src/Entity/Block.php +++ b/core/modules/block/src/Entity/Block.php @@ -28,11 +28,14 @@ * }, * admin_permission = "administer blocks", * entity_keys = { - * "id" = "id" + * "id" = "id", + * "status" = "status" * }, * links = { * "delete-form" = "/admin/structure/block/manage/{block}/delete", - * "edit-form" = "/admin/structure/block/manage/{block}" + * "edit-form" = "/admin/structure/block/manage/{block}", + * "enable" = "/admin/structure/block/manage/{block}/enable", + * "disable" = "/admin/structure/block/manage/{block}/disable", * }, * config_export = { * "id", @@ -70,7 +73,7 @@ class Block extends ConfigEntityBase implements BlockInterface, EntityWithPlugin * * @var string */ - protected $region = self::BLOCK_REGION_NONE; + protected $region; /** * The block weight. @@ -209,13 +212,13 @@ public static function sort(ConfigEntityInterface $a, ConfigEntityInterface $b) if ($status !== 0) { return $status; } - // Sort by weight, unless disabled. - if ($a->getRegion() != static::BLOCK_REGION_NONE) { - $weight = $a->getWeight() - $b->getWeight(); - if ($weight) { - return $weight; - } + + // Sort by weight. + $weight = $a->getWeight() - $b->getWeight(); + if ($weight) { + return $weight; } + // Sort by label. return strcmp($a->label(), $b->label()); } @@ -327,4 +330,21 @@ public function createDuplicateBlock($new_id = NULL, $new_theme = NULL) { 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(); + } + } + } diff --git a/core/modules/block/src/Tests/BlockInvalidRegionTest.php b/core/modules/block/src/Tests/BlockInvalidRegionTest.php index 438a0c1c2a76c214a9ab68c3a26986e62128caaa..99ef06d5ecc20e52f0a08ab0c9c7261fbe6d1ab6 100644 --- a/core/modules/block/src/Tests/BlockInvalidRegionTest.php +++ b/core/modules/block/src/Tests/BlockInvalidRegionTest.php @@ -37,8 +37,8 @@ protected function setUp() { function testBlockInInvalidRegion() { // Enable a test block and place it in an invalid region. $block = $this->drupalPlaceBlock('test_html'); - $block->setRegion('invalid_region'); - $block->save(); + \Drupal::configFactory()->getEditable('block.block.' . $block->id())->set('region', 'invalid_region')->save(); + $block = Block::load($block->id()); $warning_message = t('The block %info was assigned to the invalid region %region and has been disabled.', array('%info' => $block->id(), '%region' => 'invalid_region')); @@ -51,9 +51,8 @@ function testBlockInInvalidRegion() { $this->assertNoRaw($warning_message, 'Disabled block in the invalid region will not trigger the warning.'); // Place disabled test block in the invalid region of the default theme. + \Drupal::configFactory()->getEditable('block.block.' . $block->id())->set('region', 'invalid_region')->save(); $block = Block::load($block->id()); - $block->setRegion('invalid_region'); - $block->save(); // Clear the cache to check if the warning message is not triggered. $this->drupalPostForm('admin/config/development/performance', array(), 'Clear all caches'); diff --git a/core/modules/block/src/Tests/BlockTest.php b/core/modules/block/src/Tests/BlockTest.php index 039aa6468158deaca8bf7af21714e09cd6785605..41d376a1a28a92414f0116471f68a5941efebe79 100644 --- a/core/modules/block/src/Tests/BlockTest.php +++ b/core/modules/block/src/Tests/BlockTest.php @@ -178,6 +178,10 @@ function testBlock() { // Place page title block to test error messages. $this->drupalPlaceBlock('page_title_block'); + // Disable the block. + $this->drupalGet('admin/structure/block'); + $this->clickLink('Disable'); + // Select the 'Powered by Drupal' block to be configured and moved. $block = array(); $block['id'] = 'system_powered_by_block'; @@ -199,13 +203,12 @@ function testBlock() { $this->moveBlockToRegion($block, $region); } - // Set the block to the disabled region. - $edit = array(); - $edit['blocks[' . $block['id'] . '][region]'] = -1; - $this->drupalPostForm('admin/structure/block', $edit, t('Save blocks')); + // Disable the block. + $this->drupalGet('admin/structure/block'); + $this->clickLink('Disable'); // Confirm that the block is now listed as disabled. - $this->assertText(t('The block settings have been updated.'), 'Block successfully move to disabled region.'); + $this->assertText(t('The block settings have been updated.'), 'Block successfully moved to disabled region.'); // Confirm that the block instance title and markup are not displayed. $this->drupalGet('node'); @@ -218,7 +221,7 @@ function testBlock() { // Test deleting the block from the edit form. $this->drupalGet('admin/structure/block/manage/' . $block['id']); $this->clickLink(t('Delete')); - $this->assertRaw(t('Are you sure you want to delete the block %name?', array('%name' => $block['settings[label]']))); + $this->assertRaw(t('Are you sure you want to delete the block @name?', array('@name' => $block['settings[label]']))); $this->drupalPostForm(NULL, array(), t('Delete')); $this->assertRaw(t('The block %name has been deleted.', array('%name' => $block['settings[label]']))); @@ -226,7 +229,7 @@ function testBlock() { $block = $this->drupalPlaceBlock('system_powered_by_block'); $this->drupalGet('admin/structure/block/manage/' . $block->id(), array('query' => array('destination' => 'admin'))); $this->clickLink(t('Delete')); - $this->assertRaw(t('Are you sure you want to delete the block %name?', array('%name' => $block->label()))); + $this->assertRaw(t('Are you sure you want to delete the block @name?', array('@name' => $block->label()))); $this->drupalPostForm(NULL, array(), t('Delete')); $this->assertRaw(t('The block %name has been deleted.', array('%name' => $block->label()))); $this->assertUrl('admin'); diff --git a/core/modules/block/src/Tests/BlockUiTest.php b/core/modules/block/src/Tests/BlockUiTest.php index ec720e9c921a77409a0d11975b4ed0f8984224b6..35c3b5f664c00a324fef4e9dd9d42b816c8d32d1 100644 --- a/core/modules/block/src/Tests/BlockUiTest.php +++ b/core/modules/block/src/Tests/BlockUiTest.php @@ -257,12 +257,15 @@ public function testMachineNameSuggestion() { $url = 'admin/structure/block/add/test_block_instantiation/classy'; $this->drupalGet($url); $this->assertFieldByName('id', 'displaymessage', 'Block form uses raw machine name suggestion when no instance already exists.'); - $this->drupalPostForm($url, array(), 'Save block'); + $edit = ['region' => 'content']; + $this->drupalPostForm($url, $edit, 'Save block'); + $this->assertText('The block configuration has been saved.'); // Now, check to make sure the form starts by autoincrementing correctly. $this->drupalGet($url); $this->assertFieldByName('id', 'displaymessage_2', 'Block form appends _2 to plugin-suggested machine name when an instance already exists.'); - $this->drupalPostForm($url, array(), 'Save block'); + $this->drupalPostForm($url, $edit, 'Save block'); + $this->assertText('The block configuration has been saved.'); // And verify that it continues working beyond just the first two. $this->drupalGet($url); @@ -292,7 +295,7 @@ public function testBlockPlacementIndicator() { * Tests if validation errors are passed plugin form to the parent form. */ public function testBlockValidateErrors() { - $this->drupalPostForm('admin/structure/block/add/test_settings_validation/classy', ['settings[digits]' => 'abc'], t('Save block')); + $this->drupalPostForm('admin/structure/block/add/test_settings_validation/classy', ['region' => 'content', 'settings[digits]' => 'abc'], t('Save block')); $arguments = [':message' => 'Only digits are allowed']; $pattern = '//div[contains(@class,"messages messages--error")]/div[contains(text()[2],:message)]'; diff --git a/core/modules/block/src/Tests/Update/BlockRemoveDisabledRegionUpdateTest.php b/core/modules/block/src/Tests/Update/BlockRemoveDisabledRegionUpdateTest.php new file mode 100644 index 0000000000000000000000000000000000000000..60ba24c712c6aefa086713c4fd405039e80d192a --- /dev/null +++ b/core/modules/block/src/Tests/Update/BlockRemoveDisabledRegionUpdateTest.php @@ -0,0 +1,57 @@ +<?php + +namespace Drupal\block\Tests\Update; + +use Drupal\system\Tests\Update\UpdatePathTestBase; + +/** + * Tests the upgrade path for removal of disabled region. + * + * @see https://www.drupal.org/node/2513534 + * + * @group Update + */ +class BlockRemoveDisabledRegionUpdateTest extends UpdatePathTestBase { + + /** + * {@inheritdoc} + */ + protected static $modules = ['block_test', 'language']; + + /** + * {@inheritdoc} + */ + protected function setDatabaseDumpFiles() { + $this->databaseDumpFiles = [ + __DIR__ . '/../../../../system/tests/fixtures/update/drupal-8.bare.standard.php.gz', + __DIR__ . '/../../../../system/tests/fixtures/update/drupal-8.update-test-block-disabled-2513534.php', + ]; + } + + /** + * Tests that block context mapping is updated properly. + */ + public function testUpdateHookN() { + $this->runUpdates(); + + // Disable maintenance mode. + \Drupal::state()->set('system.maintenance_mode', FALSE); + + // We finished updating so we can login the user now. + $this->drupalLogin($this->rootUser); + + // Verify that a disabled block is in the default region. + $this->drupalGet('admin/structure/block'); + $element = $this->xpath("//tr[contains(@data-drupal-selector, :block) and contains(@class, :status)]//select/option[@selected and @value=:region]", + [':block' => 'edit-blocks-pagetitle-1', ':status' => 'block-disabled', ':region' => 'header']); + $this->assertTrue(!empty($element)); + + // Verify that an enabled block is now disabled and in the default region. + $this->drupalGet('admin/structure/block'); + $element = $this->xpath("//tr[contains(@data-drupal-selector, :block) and contains(@class, :status)]//select/option[@selected and @value=:region]", + [':block' => 'edit-blocks-pagetitle-2', ':status' => 'block-disabled', ':region' => 'header']); + $this->assertTrue(!empty($element)); + + } + +} diff --git a/core/modules/block/src/Tests/Views/DisplayBlockTest.php b/core/modules/block/src/Tests/Views/DisplayBlockTest.php index faf68c47fdbdc74d7a1062345cbca52a88db036a..368af68ad9f1b9b7a052bc8d18f6803620ae88eb 100644 --- a/core/modules/block/src/Tests/Views/DisplayBlockTest.php +++ b/core/modules/block/src/Tests/Views/DisplayBlockTest.php @@ -185,8 +185,10 @@ public function testViewsBlockForm() { // Test that that machine name field is hidden from display and has been // saved as expected from the default value. $this->assertNoFieldById('edit-machine-name', 'views_block__test_view_block_1', 'The machine name is hidden on the views block form.'); + // Save the block. - $this->drupalPostForm(NULL, array(), t('Save block')); + $edit = ['region' => 'content']; + $this->drupalPostForm(NULL, $edit, t('Save block')); $storage = $this->container->get('entity_type.manager')->getStorage('block'); $block = $storage->load('views_block__test_view_block_block_1'); // This will only return a result if our new block has been created with the @@ -195,7 +197,7 @@ public function testViewsBlockForm() { for ($i = 2; $i <= 3; $i++) { // Place the same block again and make sure we have a new ID. - $this->drupalPostForm('admin/structure/block/add/views_block:test_view_block-block_1/' . $default_theme, array(), t('Save block')); + $this->drupalPostForm('admin/structure/block/add/views_block:test_view_block-block_1/' . $default_theme, $edit, t('Save block')); $block = $storage->load('views_block__test_view_block_block_1_' . $i); // This will only return a result if our new block has been created with the // expected machine name. @@ -204,7 +206,7 @@ public function testViewsBlockForm() { // Tests the override capability of items per page. $this->drupalGet('admin/structure/block/add/views_block:test_view_block-block_1/' . $default_theme); - $edit = array(); + $edit = ['region' => 'content']; $edit['settings[override][items_per_page]'] = 10; $this->drupalPostForm('admin/structure/block/add/views_block:test_view_block-block_1/' . $default_theme, $edit, t('Save block')); @@ -222,7 +224,7 @@ public function testViewsBlockForm() { $this->assertEqual(5, $config['items_per_page'], "'Items per page' is properly saved."); // Tests the override of the label capability. - $edit = array(); + $edit = ['region' => 'content']; $edit['settings[views_label_checkbox]'] = 1; $edit['settings[views_label]'] = 'Custom title'; $this->drupalPostForm('admin/structure/block/add/views_block:test_view_block-block_1/' . $default_theme, $edit, t('Save block')); diff --git a/core/modules/block/tests/src/Kernel/BlockRebuildTest.php b/core/modules/block/tests/src/Kernel/BlockRebuildTest.php new file mode 100644 index 0000000000000000000000000000000000000000..33de12ce87d8d69dda68e1284a56df6381d12122 --- /dev/null +++ b/core/modules/block/tests/src/Kernel/BlockRebuildTest.php @@ -0,0 +1,103 @@ +<?php + +namespace Drupal\Tests\block\Kernel; + +use Drupal\block\Entity\Block; +use Drupal\Core\StringTranslation\TranslatableMarkup; +use Drupal\KernelTests\KernelTestBase; +use Drupal\simpletest\BlockCreationTrait; + +/** + * Tests block_rebuild(). + * + * @group block + */ +class BlockRebuildTest extends KernelTestBase { + + use BlockCreationTrait; + + /** + * {@inheritdoc} + */ + public static $modules = ['block', 'system']; + + /** + * {@inheritdoc} + */ + protected function setUp() { + parent::setUp(); + + $this->container->get('theme_installer')->install(['stable', 'classy']); + $this->container->get('config.factory')->getEditable('system.theme')->set('default', 'classy')->save(); + } + + /** + * {@inheritdoc} + */ + public static function setUpBeforeClass() { + parent::setUpBeforeClass(); + + // @todo Once block_rebuild() is refactored to auto-loadable code, remove + // this require statement. + require_once static::getDrupalRoot() . '/core/modules/block/block.module'; + } + + /** + * @covers ::block_rebuild + */ + public function testRebuildNoBlocks() { + block_rebuild(); + $messages = drupal_get_messages(); + $this->assertEquals([], $messages); + } + + /** + * @covers ::block_rebuild + */ + public function testRebuildNoInvalidBlocks() { + $this->placeBlock('system_powered_by_block', ['region' => 'content']); + + block_rebuild(); + $messages = drupal_get_messages(); + $this->assertEquals([], $messages); + } + + /** + * @covers ::block_rebuild + */ + public function testRebuildInvalidBlocks() { + $this->placeBlock('system_powered_by_block', ['region' => 'content']); + $block1 = $this->placeBlock('system_powered_by_block'); + $block2 = $this->placeBlock('system_powered_by_block'); + $block2->disable()->save(); + // Use the config API directly to bypass Block::preSave(). + \Drupal::configFactory()->getEditable('block.block.' . $block1->id())->set('region', 'INVALID')->save(); + \Drupal::configFactory()->getEditable('block.block.' . $block2->id())->set('region', 'INVALID')->save(); + + // Reload block entities. + $block1 = Block::load($block1->id()); + $block2 = Block::load($block2->id()); + + $this->assertSame('INVALID', $block1->getRegion()); + $this->assertTrue($block1->status()); + $this->assertSame('INVALID', $block2->getRegion()); + $this->assertFalse($block2->status()); + + block_rebuild(); + + // Reload block entities. + $block1 = Block::load($block1->id()); + $block2 = Block::load($block2->id()); + + $messages = drupal_get_messages(); + $expected = ['warning' => [new TranslatableMarkup('The block %info was assigned to the invalid region %region and has been disabled.', ['%info' => $block1->id(), '%region' => 'INVALID'])]]; + $this->assertEquals($expected, $messages); + + $default_region = system_default_region('classy'); + $this->assertSame($default_region, $block1->getRegion()); + $this->assertFalse($block1->status()); + $this->assertSame($default_region, $block2->getRegion()); + $this->assertFalse($block2->status()); + } + +} diff --git a/core/modules/block/tests/src/Kernel/BlockStorageUnitTest.php b/core/modules/block/tests/src/Kernel/BlockStorageUnitTest.php index 6dfc66c831d3292d2474ae7a01533d11d1c4d66e..5704476a653f14fcd97e897355f0318f24e8bbc7 100644 --- a/core/modules/block/tests/src/Kernel/BlockStorageUnitTest.php +++ b/core/modules/block/tests/src/Kernel/BlockStorageUnitTest.php @@ -34,6 +34,8 @@ protected function setUp() { parent::setUp(); $this->controller = $this->container->get('entity_type.manager')->getStorage('block'); + + $this->container->get('theme_installer')->install(['stark']); } /** @@ -66,6 +68,7 @@ protected function createTests() { $entity = $this->controller->create(array( 'id' => 'test_block', 'theme' => 'stark', + 'region' => 'content', 'plugin' => 'test_html', )); $entity->save(); @@ -84,7 +87,7 @@ protected function createTests() { 'dependencies' => array('module' => array('block_test'), 'theme' => array('stark')), 'id' => 'test_block', 'theme' => 'stark', - 'region' => '-1', + 'region' => 'content', 'weight' => NULL, 'provider' => NULL, 'plugin' => 'test_html', @@ -111,7 +114,7 @@ protected function loadTests() { $this->assertTrue($entity instanceof Block, 'The loaded entity is a Block.'); // Verify several properties of the block. - $this->assertEqual($entity->getRegion(), '-1'); + $this->assertSame('content', $entity->getRegion()); $this->assertTrue($entity->status()); $this->assertEqual($entity->getTheme(), 'stark'); $this->assertTrue($entity->uuid()); diff --git a/core/modules/block/tests/src/Kernel/Migrate/d6/MigrateBlockTest.php b/core/modules/block/tests/src/Kernel/Migrate/d6/MigrateBlockTest.php index 1ceadd1237a9a940166fbdf2e6d29e96975d50cf..bc59f71828721cd20e4e1acd62a7353014f7a4e5 100644 --- a/core/modules/block/tests/src/Kernel/Migrate/d6/MigrateBlockTest.php +++ b/core/modules/block/tests/src/Kernel/Migrate/d6/MigrateBlockTest.php @@ -28,6 +28,10 @@ class MigrateBlockTest extends MigrateDrupal6TestBase { */ protected function setUp() { parent::setUp(); + + // Install the themes used for this test. + $this->container->get('theme_installer')->install(['bartik', 'seven', 'test_theme']); + $this->installConfig(['block_content']); $this->installEntitySchema('block_content'); @@ -37,9 +41,6 @@ protected function setUp() { $config->set('admin', 'seven'); $config->save(); - // Install one of D8's test themes. - \Drupal::service('theme_handler')->install(['test_theme']); - $this->executeMigrations([ 'd6_filter_format', 'block_content_type', @@ -69,13 +70,14 @@ protected function setUp() { * @param string $label_display * The block label display setting. */ - public function assertEntity($id, $visibility, $region, $theme, $weight, $label, $label_display) { + public function assertEntity($id, $visibility, $region, $theme, $weight, $label, $label_display, $status = TRUE) { $block = Block::load($id); $this->assertTrue($block instanceof Block); $this->assertIdentical($visibility, $block->getVisibility()); $this->assertIdentical($region, $block->getRegion()); $this->assertIdentical($theme, $block->getTheme()); $this->assertIdentical($weight, $block->getWeight()); + $this->assertIdentical($status, $block->status()); $config = $this->config('block.block.' . $id); $this->assertIdentical($label, $config->get('settings.label')); @@ -122,7 +124,9 @@ public function testBlockMigration() { $visibility['request_path']['id'] = 'request_path'; $visibility['request_path']['negate'] = TRUE; $visibility['request_path']['pages'] = '/node/1'; - $this->assertEntity('system', $visibility, 'footer', 'bartik', -5, '', '0'); + // @todo https://www.drupal.org/node/2753939 This block is the footer region + // but Bartik in D8 does not have this region. + $this->assertEntity('system', $visibility, 'header', 'bartik', -5, '', '0', FALSE); // Check menu blocks $visibility = []; @@ -137,7 +141,9 @@ public function testBlockMigration() { $visibility['request_path']['id'] = 'request_path'; $visibility['request_path']['negate'] = FALSE; $visibility['request_path']['pages'] = '/node'; - $this->assertEntity('block_1', $visibility, 'sidebar_second', 'bluemarine', -4, 'Another Static Block', 'visible'); + // @todo https://www.drupal.org/node/2753939 The bluemarine theme does not + // exist. + $this->assertEntity('block_1', $visibility, '', 'bluemarine', -4, 'Another Static Block', 'visible', FALSE); $visibility = []; $this->assertEntity('block_2', $visibility, 'right', 'test_theme', -7, '', '0'); diff --git a/core/modules/block/tests/src/Kernel/Migrate/d7/MigrateBlockTest.php b/core/modules/block/tests/src/Kernel/Migrate/d7/MigrateBlockTest.php index 571c210998c9b85c124f3c01b4786c859849af8b..49be0ee03ac92a503d1316e393f5647f14b88e9f 100644 --- a/core/modules/block/tests/src/Kernel/Migrate/d7/MigrateBlockTest.php +++ b/core/modules/block/tests/src/Kernel/Migrate/d7/MigrateBlockTest.php @@ -33,6 +33,10 @@ class MigrateBlockTest extends MigrateDrupal7TestBase { */ protected function setUp() { parent::setUp(); + + // Install the themes used for this test. + $this->container->get('theme_installer')->install(['bartik', 'seven']); + $this->installConfig(static::$modules); $this->installEntitySchema('block_content'); @@ -42,9 +46,6 @@ protected function setUp() { $config->set('admin', 'seven'); $config->save(); - // Install one of D8's test themes. - \Drupal::service('theme_handler')->install(['bartik']); - $this->executeMigrations([ 'd7_filter_format', 'd7_user_role', @@ -77,7 +78,7 @@ protected function setUp() { * @param string $label_display * The block label display setting. */ - public function assertEntity($id, $plugin_id, array $roles, $pages, $region, $theme, $weight, $label, $label_display) { + public function assertEntity($id, $plugin_id, array $roles, $pages, $region, $theme, $weight, $label, $label_display, $status = TRUE) { $block = Block::load($id); $this->assertTrue($block instanceof Block); /** @var \Drupal\block\BlockInterface $block */ @@ -95,6 +96,7 @@ public function assertEntity($id, $plugin_id, array $roles, $pages, $region, $th $this->assertIdentical($region, $block->getRegion()); $this->assertIdentical($theme, $block->getTheme()); $this->assertIdentical($weight, $block->getWeight()); + $this->assertIdentical($status, $block->status()); $config = $this->config('block.block.' . $id); $this->assertIdentical($label, $config->get('settings.label')); @@ -108,7 +110,9 @@ public function testBlockMigration() { $this->assertEntity('bartik_system_main', 'system_main_block', [], '', 'content', 'bartik', 0, '', '0'); $this->assertEntity('bartik_search_form', 'search_form_block', [], '', 'sidebar_first', 'bartik', -1, '', '0'); $this->assertEntity('bartik_user_login', 'user_login_block', [], '', 'sidebar_first', 'bartik', 0, '', '0'); - $this->assertEntity('bartik_system_powered_by', 'system_powered_by_block', [], '', 'footer', 'bartik', 10, '', '0'); + // @todo https://www.drupal.org/node/2753939 This block is the footer region + // but Bartik in D8 does not have this region. + $this->assertEntity('bartik_system_powered_by', 'system_powered_by_block', [], '', 'header', 'bartik', 10, '', '0', FALSE); $this->assertEntity('seven_system_main', 'system_main_block', [], '', 'content', 'seven', 0, '', '0'); $this->assertEntity('seven_user_login', 'user_login_block', [], '', 'content', 'seven', 10, '', '0'); diff --git a/core/modules/block_content/src/Tests/BlockContentCreationTest.php b/core/modules/block_content/src/Tests/BlockContentCreationTest.php index 0cca85ee87d204ec3088ac55628cbc8bde1c0b7c..e45892c5c3c1cf6d93e8c337ddc30d788728aa67 100644 --- a/core/modules/block_content/src/Tests/BlockContentCreationTest.php +++ b/core/modules/block_content/src/Tests/BlockContentCreationTest.php @@ -107,7 +107,7 @@ public function testBlockContentCreationMultipleViewModes() { )), 'Basic block created.'); // Save our block permanently - $this->drupalPostForm(NULL, NULL, t('Save block')); + $this->drupalPostForm(NULL, ['region' => 'content'], t('Save block')); // Set test_view_mode as a custom display to be available on the list. $this->drupalGet('admin/structure/block/block-content'); @@ -134,6 +134,7 @@ public function testBlockContentCreationMultipleViewModes() { $this->assertFieldByXPath('//select[@name="settings[view_mode]"]', NULL, 'View mode setting shown because multiple exist'); // Change the view mode. + $view_mode['region'] = 'content'; $view_mode['settings[view_mode]'] = 'test_view_mode'; $this->drupalPostForm(NULL, $view_mode, t('Save block')); diff --git a/core/modules/block_content/src/Tests/BlockContentTypeTest.php b/core/modules/block_content/src/Tests/BlockContentTypeTest.php index e73aa2a48ae27f73c250ed9c4fa3acf9fe5cd85c..8f6ffe19d8f5c326d523fbe944cb18000c3bcc54 100644 --- a/core/modules/block_content/src/Tests/BlockContentTypeTest.php +++ b/core/modules/block_content/src/Tests/BlockContentTypeTest.php @@ -211,7 +211,7 @@ public function testsBlockContentAddTypes() { if (!empty($blocks)) { $block = reset($blocks); $this->assertUrl(\Drupal::url('block.admin_add', array('plugin_id' => 'block_content:' . $block->uuid(), 'theme' => $theme), array('absolute' => TRUE))); - $this->drupalPostForm(NULL, array(), t('Save block')); + $this->drupalPostForm(NULL, ['region' => 'content'], t('Save block')); $this->assertUrl(\Drupal::url('block.admin_display_theme', array('theme' => $theme), array('absolute' => TRUE, 'query' => array('block-placement' => Html::getClass($edit['info[0][value]']))))); } else { diff --git a/core/modules/rest/src/Tests/RESTTestBase.php b/core/modules/rest/src/Tests/RESTTestBase.php index 584c003818745fccac9c6acc6b4ec0c09d7a5d74..1a524749d901dd359404d50579134497e63f6bfc 100644 --- a/core/modules/rest/src/Tests/RESTTestBase.php +++ b/core/modules/rest/src/Tests/RESTTestBase.php @@ -270,6 +270,15 @@ protected function entityValues($entity_type_id) { 'vid' => 'tags', 'name' => $this->randomMachineName(), ]; + case 'block': + // Block placements depend on themes, ensure Bartik is installed. + $this->container->get('theme_installer')->install(['bartik']); + return [ + 'id' => strtolower($this->randomMachineName(8)), + 'plugin' => 'system_powered_by_block', + 'theme' => 'bartik', + 'region' => 'header', + ]; default: if ($this->isConfigEntity($entity_type_id)) { return $this->configEntityValues($entity_type_id); diff --git a/core/modules/system/src/Tests/System/AccessDeniedTest.php b/core/modules/system/src/Tests/System/AccessDeniedTest.php index 81f9fad1844f98422b6e8c0c07e523ec7ed79f6c..e7f17d78b360abef3b83a427037a74a30d14492d 100644 --- a/core/modules/system/src/Tests/System/AccessDeniedTest.php +++ b/core/modules/system/src/Tests/System/AccessDeniedTest.php @@ -65,7 +65,7 @@ function testAccessDenied() { $this->drupalPostForm('admin/config/system/site-information', $edit, t('Save configuration')); // Enable the user login block. - $this->drupalPlaceBlock('user_login_block', array('id' => 'login')); + $block = $this->drupalPlaceBlock('user_login_block', array('id' => 'login')); // Log out and check that the user login block is shown on custom 403 pages. $this->drupalLogout(); @@ -90,10 +90,7 @@ function testAccessDenied() { // Log back in, set the custom 403 page to /user/login and remove the block $this->drupalLogin($this->adminUser); $this->config('system.site')->set('page.403', '/user/login')->save(); - $edit = [ - 'region' => -1, - ]; - $this->drupalPostForm('admin/structure/block/manage/login', $edit, t('Save block')); + $block->disable()->save(); // Check that we can log in from the 403 page. $this->drupalLogout(); diff --git a/core/modules/system/tests/fixtures/update/block.block.secondtestfor2513534.yml b/core/modules/system/tests/fixtures/update/block.block.secondtestfor2513534.yml new file mode 100644 index 0000000000000000000000000000000000000000..2999cab9efb495569021e3985b570bfb2963c825 --- /dev/null +++ b/core/modules/system/tests/fixtures/update/block.block.secondtestfor2513534.yml @@ -0,0 +1,18 @@ +uuid: 3c4e92c3-5fb1-408d-993c-6066559230be +langcode: en +status: true +dependencies: + theme: + - bartik +id: pagetitle_2 +theme: bartik +region: '-1' +weight: null +provider: null +plugin: page_title_block +settings: + id: page_title_block + label: 'Page title' + provider: core + label_display: '0' +visibility: { } diff --git a/core/modules/system/tests/fixtures/update/block.block.testfor2513534.yml b/core/modules/system/tests/fixtures/update/block.block.testfor2513534.yml new file mode 100644 index 0000000000000000000000000000000000000000..b8a55fadfdc4d4519b1d1f78d1c90dcf73c829e6 --- /dev/null +++ b/core/modules/system/tests/fixtures/update/block.block.testfor2513534.yml @@ -0,0 +1,18 @@ +uuid: 87097da9-29d1-441f-8b00-b93852c760d6 +langcode: en +status: false +dependencies: + theme: + - bartik +id: pagetitle_1 +theme: bartik +region: '-1' +weight: -8 +provider: null +plugin: page_title_block +settings: + id: page_title_block + label: 'Page title' + provider: core + label_display: '0' +visibility: { } diff --git a/core/modules/system/tests/fixtures/update/drupal-8.update-test-block-disabled-2513534.php b/core/modules/system/tests/fixtures/update/drupal-8.update-test-block-disabled-2513534.php new file mode 100644 index 0000000000000000000000000000000000000000..fc8e1c5612da5dcf5c61745ec59adb834a9e0ca7 --- /dev/null +++ b/core/modules/system/tests/fixtures/update/drupal-8.update-test-block-disabled-2513534.php @@ -0,0 +1,50 @@ +<?php + +/** + * @file + * Contains database additions to drupal-8.bare.standard.php.gz for testing the + * upgrade path of https://www.drupal.org/node/2513534. + */ + +use Drupal\Component\Serialization\Yaml; +use Drupal\Core\Database\Database; + +$connection = Database::getConnection(); + +// A disabled block. +$block_configs[] = Yaml::decode(file_get_contents(__DIR__ . '/block.block.testfor2513534.yml')); + +// A block placed in the default region. +$block_configs[] = Yaml::decode(file_get_contents(__DIR__ . '/block.block.secondtestfor2513534.yml')); + +foreach ($block_configs as $block_config) { + $connection->insert('config') + ->fields(array( + 'collection', + 'name', + 'data', + )) + ->values(array( + 'collection' => '', + 'name' => 'block.block.' . $block_config['id'], + 'data' => serialize($block_config), + )) + ->execute(); +} + +// Update the config entity query "index". +$existing_blocks = $connection->select('key_value') + ->fields('key_value', ['value']) + ->condition('collection', 'config.entity.key_store.block') + ->condition('name', 'theme:bartik') + ->execute() + ->fetchField(); +$existing_blocks = unserialize($existing_blocks); + +$connection->update('key_value') + ->fields([ + 'value' => serialize(array_merge($existing_blocks, ['block.block.testfor2513534', 'block.block.secondtestfor2513534'])) + ]) + ->condition('collection', 'config.entity.key_store.block') + ->condition('name', 'theme:bartik') + ->execute(); diff --git a/core/modules/views/tests/src/Kernel/Handler/AreaEntityTest.php b/core/modules/views/tests/src/Kernel/Handler/AreaEntityTest.php index af3d65837d691a74950aec92fe2f0adf2f85f96d..ebf9e054c80703d1059d94ecf0d489316acddbf2 100644 --- a/core/modules/views/tests/src/Kernel/Handler/AreaEntityTest.php +++ b/core/modules/views/tests/src/Kernel/Handler/AreaEntityTest.php @@ -2,9 +2,9 @@ namespace Drupal\Tests\views\Kernel\Handler; -use Drupal\block\Entity\Block; use Drupal\Core\Entity\EntityTypeInterface; use Drupal\Core\Form\FormState; +use Drupal\simpletest\BlockCreationTrait; use Drupal\Tests\views\Kernel\ViewsKernelTestBase; use Drupal\views\Entity\View; use Drupal\views\Views; @@ -17,6 +17,8 @@ */ class AreaEntityTest extends ViewsKernelTestBase { + use BlockCreationTrait; + /** * Modules to enable. * @@ -42,14 +44,15 @@ protected function setUp($import_test_views = TRUE) { * {@inheritdoc} */ protected function setUpFixtures() { + // Install the themes used for this test. + $this->container->get('theme_installer')->install(['bartik']); + $this->container->get('config.factory')->getEditable('system.theme')->set('default', 'bartik')->save(); + $this->installEntitySchema('user'); $this->installEntitySchema('entity_test'); $this->installConfig(['entity_test']); - Block::create([ - 'id' => 'test_block', - 'plugin' => 'system_main_block', - ])->save(); + $this->placeBlock('system_main_block', ['id' => 'test_block']); parent::setUpFixtures(); } diff --git a/core/modules/views/tests/src/Kernel/Handler/AreaOrderTest.php b/core/modules/views/tests/src/Kernel/Handler/AreaOrderTest.php index 457c63579bf5c7011e266c19e63f7ee949a0f738..9ade514b8dd7b5b921d25ac20b782e052bfa4930 100644 --- a/core/modules/views/tests/src/Kernel/Handler/AreaOrderTest.php +++ b/core/modules/views/tests/src/Kernel/Handler/AreaOrderTest.php @@ -2,7 +2,7 @@ namespace Drupal\Tests\views\Kernel\Handler; -use Drupal\block\Entity\Block; +use Drupal\simpletest\BlockCreationTrait; use Drupal\Tests\views\Kernel\ViewsKernelTestBase; use Drupal\views\Views; @@ -14,6 +14,8 @@ */ class AreaOrderTest extends ViewsKernelTestBase { + use BlockCreationTrait; + /** * Modules to enable. * @@ -32,23 +34,21 @@ class AreaOrderTest extends ViewsKernelTestBase { * {@inheritdoc} */ protected function setUpFixtures() { - Block::create( - [ - 'id' => 'bartik_branding', - 'theme' => 'bartik', - 'plugin' => 'system_branding_block', - 'weight' => 1, - ] - )->save(); + // Install the themes used for this test. + $this->container->get('theme_installer')->install(['bartik']); + + $this->placeBlock('system_branding_block', [ + 'id' => 'bartik_branding', + 'theme' => 'bartik', + 'plugin' => 'system_branding_block', + 'weight' => 1, + ]); - Block::create( - [ - 'id' => 'bartik_powered', - 'theme' => 'bartik', - 'plugin' => 'system_powered_by_block', - 'weight' => 2, - ] - )->save(); + $this->placeBlock('system_powered_by_block', [ + 'id' => 'bartik_powered', + 'theme' => 'bartik', + 'weight' => 2, + ]); parent::setUpFixtures(); }