diff --git a/core/modules/block/block.install b/core/modules/block/block.install index b1fc925..47f613e 100644 --- a/core/modules/block/block.install +++ b/core/modules/block/block.install @@ -49,6 +49,61 @@ function block_update_dependencies() { } /** + * Utility function: return an array map of Drupal 7 block to Drupal 8 blocks. + * This is ugly and hard-coded. Kill @mradcliffe. + * + * @return + * An associative array of Drupal 7 blocks keyed by the module name with + * Drupal 8 block plugin information. + * + * @ingroup update_api + */ +function _update_8009_get_block_info() { + $info = array( + 'book' => array( + 'navigation' => array( + 'plugin' => 'book_navigation', + ), + ), + 'comment' => array( + 'recent' => array( + 'plugin' => 'recent_comments', + ), + ), + 'shortcut' => array( + 'shortcuts' => array( + 'plugin' => 'shortcuts', + ), + ), + 'system' => array( + 'main' => array( + 'plugin' => 'system_main_block', + ), + 'help' => array( + 'plugin' => 'system_help_block', + ), + 'powered-by' => array( + 'plugin' => 'system_powered_by_block', + ), + 'menu-tools' => array( + 'plugin' => 'system_menu_block:menu-tools', + ), + 'menu-admin' => array( + 'plugin' => 'system_menu_block:menu-admin', + ), + 'menu-account' => array( + 'plugin' => 'system_menu_block:menu-account', + ), + 'menu-main' => array( + 'plugin' => 'system_menu_block:menu-main', + ), + ), + ); + + return $info; +} + +/** * Block cache is always enabled in 8.x. * * @ingroup config_upgrade @@ -336,6 +391,151 @@ function block_update_8008() { } /** + * Migrate {block} records to configuration instances. + */ +function block_update_8009() { + $sandbox['#finished'] = 0; + + if (!isset($sandbox['total'])) { + // Initial invocation. + + $sandbox['last'] = 0; + $sandbox['count'] = 0; + + $query = db_select('block', 'b'); + $sandbox['total'] = $query + ->condition('b.module', array('block', 'profile', 'blog', 'poll', 'locale', 'language'), 'NOT IN') + ->countQuery() + ->execute() + ->fetchField(); + } + + // Subsequent invocations. + + $found = FALSE; + if ($sandbox['total']) { + // Operate on each block in turn. + + $block_info = _update_8009_get_block_info(); + $node_types = _update_7000_node_get_types(); + $node_type_keys = ($node_types) ? array_keys($node_type_keys) : array(); + // @todo: poll, profile, locale/language + $core_modules = array( + 'aggregator', 'book', 'comment', 'forum', 'menu', 'node', 'search', + 'shortcut', 'statistics', 'system', 'user' + ); + + $batch_size = 200; + $query = db_select('block', 'b'); + $query + ->fields('b') + ->condition('b.module', $core_modules, 'IN') + ->condition('b.bid', $sandbox['last'], '>') + ->orderBy('b.bid', 'ASC') + ->range(0, $batch_size); + $blocks = $query->execute(); + + foreach ($blocks as $block) { + // Try to match a plugin to block. + + $plugin_id = ''; + $id = $block->theme . '.' . $block->module . '.' . str_replace('-', '_', $block->delta); + $settings = array( + 'cache' => $block->cache, + ); + + if (isset($block_info[$block->module])) { + // Block plugin id is not consistent with Drupal 7 block delta. + + foreach (array_keys($block_info[$block->module]) as $key) { + if ($key == $block->delta) { + $plugin_id = $block_info[$block->module][$key]['plugin']; + if (isset($block_info[$block->module][$key]['settings'])) { + $settings += $block_info[$block->module][$key]['settings']; + } + break; + } + } + + if (empty($plugin_id)) { + $sandbox['count'] += 1; + $sandbox['last'] = $block->bid; + continue; + } + } + elseif ($block->module == 'menu') { + // Menu blocks have yet a different pattern. + $plugin_id = 'menu_menu_block:' . $block->delta; + } + else { + // Fallback to consistent block plugin id: module, delta, block. + $plugin_id = $block->module . '_' . str_replace('-', '_', $block->delta) . '_block'; + } + + // Set basic visibility from block table. + $visibility = array( + 'path' => array( + 'visibility' => $block->visibility, + 'pages' => $block->pages, + ), + 'visibility__active_tab' => 'edit-visibility-path', + ); + + // Set visibility by role. + $block_roles = db_select('block_role', 'br') + ->condition('br.module', $block->module) + ->condition('br.delta', $block->delta) + ->fields('br', array('rid')) + ->execute() + ->fetchAllKeyed(0, 0); + $visibility['role']['roles'] = ($block_roles) ? array_values($block_roles) : array(); + + // Set visibility by node type. + $block_node_types = db_select('block_node_type', 'bnt') + ->condition('bnt.module', $block->module) + ->condition('bnt.delta', $block->delta) + ->fields('bnt', array('type')) + ->execute() + ->fetchAllKeyed(0, 0); + + foreach ($node_type_keys as $type) { + $visibility['node_type']['types'][$type] = isset($block_node_types[$type]) ? $type : 0; + } + + // Create the block configuration entity instance. Calling the block + // container via entity_create() does not seem to work in this context. + $found = TRUE; + $entity = config('block.block.' . $id); + $uuid = new UUID(); + $label = !empty($block->title) ? $block->title : ''; + $entity + ->set('id', $id) + ->set('uuid', $uuid->generate()) + ->set('plugin', $plugin_id) + ->set('module', $block->module) + ->set('theme', $block->theme) + ->set('region', $block->region) + ->set('weight', $block->weight) + ->set('status', $block->status) + ->set('visibility', $visibility) + ->set('label', $label) + ->set('settings', $settings); + $entity->save(); + + $sandbox['count'] += 1; + $sandbox['last'] = $block->bid; + } + + $sandbox['#finished'] = min(0.99, $sandbox['count'] / $sandbox['total']); + + if (!$found) { + // We're done. + $sandbox['#finished'] = 1; + } + } +} + +/** * @} End of "addtogroup updates-7.x-to-8.x". * The next series of updates should start at 9000. */ diff --git a/core/modules/system/lib/Drupal/system/Tests/Upgrade/BlockUpgradePathTest.php b/core/modules/system/lib/Drupal/system/Tests/Upgrade/BlockUpgradePathTest.php index b9129e3..d48fa05 100644 --- a/core/modules/system/lib/Drupal/system/Tests/Upgrade/BlockUpgradePathTest.php +++ b/core/modules/system/lib/Drupal/system/Tests/Upgrade/BlockUpgradePathTest.php @@ -8,9 +8,10 @@ namespace Drupal\system\Tests\Upgrade; /** - * Tests upgrading a bare database. + * Tests upgrading a filled database with blocks. * - * Loads a bare installation of Drupal 7 and runs the upgrade process on it. + * Loads a standard installation of Drupal 7 and runs the upgrade process on + * it. */ class BlockUpgradePathTest extends UpgradePathTestBase { @@ -24,7 +25,7 @@ public static function getInfo() { public function setUp() { $this->databaseDumpFiles = array( - drupal_get_path('module', 'system') . '/tests/upgrade/drupal-7.bare.minimal.database.php.gz', + drupal_get_path('module', 'system') . '/tests/upgrade/drupal-7.filled.standard_all.database.php.gz', ); parent::setUp(); } @@ -39,6 +40,9 @@ public function testBlockUpgradeTitleLength() { // output validation errors or success messages, so create the blocks from // the UI. + $this->drupalGet('admin/structure/block'); + $this->drupalGet('admin/structure/block/list/block_plugin_ui:seven'); + // Add a block instance with a 255-character title. // Confirm that the custom block has been created, and title matches input. $settings = array(