diff --git a/core/modules/block/block.install b/core/modules/block/block.install index 106815c..7e54e3f 100644 --- a/core/modules/block/block.install +++ b/core/modules/block/block.install @@ -124,5 +124,29 @@ function block_update_8003() { } /** + * Disables blocks that are placed into the "disabled" region. + */ +function block_update_8004() { + // Find all blocks in the disabled region. + /** @var \Drupal\block\BlockInterface[] $blocks */ + $block_ids = \Drupal::entityManager() + ->getStorage('block') + ->getQuery() + ->condition('region', -1) + ->execute(); + + $config_factory = \Drupal::configFactory(); + + // Disable each block and assign them to the default region. + foreach ($block_ids as $block_id) { + $block_config = $config_factory->getEditable('block.block.' . $block_id); + $block_config + ->set('region', system_default_region($block_config->get('theme'))) + ->set('status', FALSE) + ->save(); + } +} + +/** * @} End of "addtogroup updates-8.0.0-beta". */ diff --git a/core/modules/block/block.module b/core/modules/block/block.module index 29c6e16..bcf323c 100644 --- a/core/modules/block/block.module +++ b/core/modules/block/block.module @@ -141,17 +141,9 @@ function block_rebuild() { $blocks = entity_load_multiple_by_properties('block', ['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()]) && $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->disable()->save(); } } } diff --git a/core/modules/block/block.routing.yml b/core/modules/block/block.routing.yml index 396bf0d..e12cd8b 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 ed12038..7fde3d7 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 50e4d38..6a7f023 100644 --- a/core/modules/block/src/BlockForm.php +++ b/core/modules/block/src/BlockForm.php @@ -177,7 +177,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' => '
', '#suffix' => '
', diff --git a/core/modules/block/src/BlockInterface.php b/core/modules/block/src/BlockInterface.php index 8955be1..02cede6 100644 --- a/core/modules/block/src/BlockInterface.php +++ b/core/modules/block/src/BlockInterface.php @@ -20,11 +20,6 @@ const BLOCK_LABEL_VISIBLE = 'visible'; /** - * Denotes that a block is not enabled in any region and should not be shown. - */ - const BLOCK_REGION_NONE = -1; - - /** * Returns the plugin instance. * * @return \Drupal\Core\Block\BlockPluginInterface diff --git a/core/modules/block/src/BlockListBuilder.php b/core/modules/block/src/BlockListBuilder.php index 907889c..95868db 100644 --- a/core/modules/block/src/BlockListBuilder.php +++ b/core/modules/block/src/BlockListBuilder.php @@ -161,6 +161,7 @@ protected function buildBlocksForm() { 'weight' => $entity->getWeight(), 'entity' => $entity, 'category' => $definition['category'], + 'status' => $entity->status(), ); } @@ -191,8 +192,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', @@ -219,9 +219,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 in the %region region', ['%region' => $block_regions_with_disabled[$region]]), + '#title' => $this->t('Place block in the %region region', ['%region' => $title]), '#url' => Url::fromRoute('block.admin_library', ['theme' => $this->getThemeName()], ['query' => ['region' => $region]]), '#wrapper_attributes' => array( 'colspan' => 5, @@ -260,12 +260,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'), ), @@ -276,7 +277,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, @@ -366,12 +367,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 2779a9b..93d0b8b5 100644 --- a/core/modules/block/src/Controller/BlockController.php +++ b/core/modules/block/src/Controller/BlockController.php @@ -8,6 +8,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; @@ -44,6 +45,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. * * @param string $theme diff --git a/core/modules/block/src/Entity/Block.php b/core/modules/block/src/Entity/Block.php index 8a65843..fe1868c 100644 --- a/core/modules/block/src/Entity/Block.php +++ b/core/modules/block/src/Entity/Block.php @@ -33,11 +33,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", @@ -75,7 +78,7 @@ class Block extends ConfigEntityBase implements BlockInterface, EntityWithPlugin * * @var string */ - protected $region = self::BLOCK_REGION_NONE; + protected $region; /** * The block weight. @@ -214,13 +217,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()); } diff --git a/core/modules/block/src/Tests/BlockStorageUnitTest.php b/core/modules/block/src/Tests/BlockStorageUnitTest.php index 140f746..88ce756 100644 --- a/core/modules/block/src/Tests/BlockStorageUnitTest.php +++ b/core/modules/block/src/Tests/BlockStorageUnitTest.php @@ -89,7 +89,7 @@ protected function createTests() { 'dependencies' => array('module' => array('block_test'), 'theme' => array('stark')), 'id' => 'test_block', 'theme' => 'stark', - 'region' => '-1', + 'region' => NULL, 'weight' => NULL, 'provider' => NULL, 'plugin' => 'test_html', @@ -116,7 +116,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->assertEqual($entity->getRegion(), NULL); $this->assertTrue($entity->status()); $this->assertEqual($entity->getTheme(), 'stark'); $this->assertTrue($entity->uuid()); diff --git a/core/modules/block/src/Tests/BlockTest.php b/core/modules/block/src/Tests/BlockTest.php index c98b042..17987ec 100644 --- a/core/modules/block/src/Tests/BlockTest.php +++ b/core/modules/block/src/Tests/BlockTest.php @@ -138,6 +138,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'; @@ -158,13 +162,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'); @@ -177,7 +180,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]']))); @@ -185,7 +188,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 5320942..a5b73f2 100644 --- a/core/modules/block/src/Tests/BlockUiTest.php +++ b/core/modules/block/src/Tests/BlockUiTest.php @@ -226,12 +226,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); 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 0000000..6f56975 --- /dev/null +++ b/core/modules/block/src/Tests/Update/BlockRemoveDisabledRegionUpdateTest.php @@ -0,0 +1,51 @@ +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(); + + // Verify that a block is in the default region. + $this->drupalGet('admin/structure/block'); + $element = $this->xpath('//tr[contains(@class, :class)]', [':class' => 'region-title-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 f7b3ffe..6759518 100644 --- a/core/modules/block/src/Tests/Views/DisplayBlockTest.php +++ b/core/modules/block/src/Tests/Views/DisplayBlockTest.php @@ -190,8 +190,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.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 @@ -200,7 +202,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. @@ -209,7 +211,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')); @@ -227,7 +229,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_content/src/Tests/BlockContentCreationTest.php b/core/modules/block_content/src/Tests/BlockContentCreationTest.php index fdd1124..6edfdc3 100644 --- a/core/modules/block_content/src/Tests/BlockContentCreationTest.php +++ b/core/modules/block_content/src/Tests/BlockContentCreationTest.php @@ -112,7 +112,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'); @@ -139,6 +139,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 e669a72..586ea2f 100644 --- a/core/modules/block_content/src/Tests/BlockContentTypeTest.php +++ b/core/modules/block_content/src/Tests/BlockContentTypeTest.php @@ -218,7 +218,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/system/src/Tests/System/AccessDeniedTest.php b/core/modules/system/src/Tests/System/AccessDeniedTest.php index b068802..16d32fb 100644 --- a/core/modules/system/src/Tests/System/AccessDeniedTest.php +++ b/core/modules/system/src/Tests/System/AccessDeniedTest.php @@ -60,7 +60,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(); @@ -85,10 +85,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.testfor2513534.yml b/core/modules/system/tests/fixtures/update/block.block.testfor2513534.yml new file mode 100644 index 0000000..2ee1401 --- /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 +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 0000000..057613b --- /dev/null +++ b/core/modules/system/tests/fixtures/update/drupal-8.update-test-block-disabled-2513534.php @@ -0,0 +1,49 @@ +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();