diff --git a/core/modules/block/block.install b/core/modules/block/block.install index 645f357..41e1cdd 100644 --- a/core/modules/block/block.install +++ b/core/modules/block/block.install @@ -6,7 +6,7 @@ */ /** - * @addtogroup updates-8.0.x-beta + * @addtogroup updates-8.0.0-beta * @{ */ @@ -20,29 +20,42 @@ function block_update_8001() { 'user' => 'user.current_user_context', ]; + $condition_plugin_id_ui_label_map = [ + 'node_type' => \Drupal::translation()->translate('Content types'), + 'request_path' => \Drupal::translation()->translate('Pages'), + 'user_role' => \Drupal::translation()->translate('Roles'), + ]; + $config_factory = \Drupal::configFactory(); $message = NULL; + $disabled_blocks = $problematic_visibility_plugins = []; + // We deal with config objects directly in order to avoid invoking Entity API + // hooks. They can be problematic when two modules implement a specific hook, + // their code is updated at the same time, yet the update functions run + // sequentially so the second hook implementation can not rely on the data not + // being altered by the first hook. foreach ($config_factory->listAll('block.block.') as $block_config_name) { - // We deal with config objects directly to avoid the config entity API. $block = $config_factory->getEditable($block_config_name); - $disable_block = FALSE; if ($visibility = $block->get('visibility')) { - foreach ($visibility as &$condition) { + foreach ($visibility as $condition_plugin_id => &$condition) { foreach ($condition['context_mapping'] as $key => $context) { if (!isset($context_service_id_map[$key])) { - // Skip unknown entries, so the update process itself runs through - // and users can fix their block placements manually OR - // alternatively contrib modules can run their own update functions - // to update mappings that they provide. - $message = \Drupal::translation()->translate('Encountered an unexpected context mapping key, one or more mappings could not be updated. Please manually review your block placements.'); - $disable_block = TRUE; + // Remove the visibility condition for unknown context mapping + // entries, so the update process itself runs through and users can + // fix their block placements manually OR alternatively contrib + // modules can run their own update functions to update mappings + // that they provide. + $disabled_blocks[$block->get('id')] = $block->get('settings.label'); + $problematic_visibility_plugins[$block->get('id')][] = $condition_plugin_id_ui_label_map[$condition_plugin_id]; + + unset($visibility[$condition_plugin_id]); continue; } $new_context_id = explode('.', $context, 2); $condition['context_mapping'][$key] = '@' . $context_service_id_map[$key] . ':' . $new_context_id[1]; } } - if ($disable_block) { + if (isset($disabled_blocks[$block->get('id')])) { // This block will have an invalid context mapping service and must be // disabled to avoid the 'You must provide the context IDs in the // @{service_id}:{unqualified_context_id} format' exception. @@ -53,9 +66,19 @@ function block_update_8001() { $block->save(); } + + if ($disabled_blocks) { + $message = \Drupal::translation()->translate('Encountered an unexpected context mapping key, one or more mappings could not be updated. Please manually review your visibility settings for the following blocks:'); + $message .= ''; + } + return $message; } /** - * @} End of "addtogroup updates-8.0.x-beta". + * @} End of "addtogroup updates-8.0.0-beta". */ diff --git a/core/modules/block/src/Tests/Update/BlockContextMappingUpdateTest.php b/core/modules/block/src/Tests/Update/BlockContextMappingUpdateTest.php index 1a89537..6e2b65b 100644 --- a/core/modules/block/src/Tests/Update/BlockContextMappingUpdateTest.php +++ b/core/modules/block/src/Tests/Update/BlockContextMappingUpdateTest.php @@ -7,6 +7,7 @@ namespace Drupal\block\Tests\Update; +use Drupal\block\Entity\Block; use Drupal\node\Entity\Node; use Drupal\system\Tests\Update\UpdatePathTestBase; @@ -35,7 +36,7 @@ protected function setUp() { */ public function testUpdateHookN() { $this->runUpdates(); - $this->assertText(t('Encountered an unexpected context mapping key, one or more mappings could not be updated. Please manually review your block placements.')); + $this->assertRaw('Encountered an unexpected context mapping key, one or more mappings could not be updated. Please manually review your visibility settings for the following blocks:'); // Disable maintenance mode. \Drupal::state()->set('system.maintenance_mode', FALSE); @@ -73,6 +74,20 @@ public function testUpdateHookN() { $this->drupalGet('node/' . $article->id()); $this->assertNoRaw($block_title, 'Test block is not visible on a Article node as an anonymous user.'); + + // Check that a block with invalid context is being disabled and that it can + // still be edited afterward. + $disabled_block = Block::load('thirdtestfor2354889'); + $this->assertFalse($disabled_block->status(), 'Block with invalid context is disabled'); + + $disabled_block_visibility = $disabled_block->get('visibility'); + $this->assertTrue(!isset($disabled_block_visibility['node_type']), 'The problematic visibility condition has been removed.'); + + $admin_user = $this->drupalCreateUser(['administer blocks']); + $this->drupalLogin($admin_user); + + $this->drupalGet('admin/structure/block/manage/thirdtestfor2354889'); + $this->assertResponse('200'); } }