Commit 8d783b7c authored by catch's avatar catch

Issue #2669978 by Jo Fitzgerald, arturs.v, phenaproxima: Migrate D7 Menu Links

parent e2d04052
id: menu_links
id: d6_menu_links
label: Menu links
migration_tags:
- Drupal 6
- Drupal 7
source:
plugin: menu_link
process:
......@@ -13,8 +12,11 @@ process:
-
plugin: migration
# The menu migration is in the system module.
migration: menu
migration: d6_menu
source: menu_name
-
plugin: skip_on_empty
method: row
-
plugin: static_map
map:
......@@ -51,4 +53,4 @@ destination:
no_stub: true
migration_dependencies:
required:
- menu
- d6_menu
id: d7_menu_links
label: Menu links
migration_tags:
- Drupal 7
source:
plugin: menu_link
constants:
bundle: menu_link_content
process:
id: mlid
bundle: 'constants/bundle'
title: link_title
description: description
menu_name:
-
plugin: migration
migration: d7_menu
source: menu_name
-
plugin: skip_on_empty
method: row
'link/uri':
plugin: d7_internal_uri
source:
- link_path
'link/options': options
route:
plugin: route
source:
- link_path
- options
route_name: '@route/route_name'
route_parameters: '@route/route_parameters'
url: '@route/url'
options: '@route/options'
external: external
weight: weight
expanded: expanded
enabled: enabled
parent:
plugin: menu_link_parent
source:
- plid
- '@menu_name'
- parent_link_path
changed: updated
destination:
plugin: entity:menu_link_content
no_stub: true
migration_dependencies:
required:
- d7_menu
<?php
namespace Drupal\menu_link_content\Plugin\migrate\process\d7;
use Drupal\migrate\MigrateExecutableInterface;
use Drupal\migrate\ProcessPluginBase;
use Drupal\migrate\Row;
/**
* Process a path into an 'internal:' URI.
*
* @MigrateProcessPlugin(
* id = "d7_internal_uri"
* )
*/
class InternalUri extends ProcessPluginBase {
/**
* {@inheritdoc}
*/
public function transform($value, MigrateExecutableInterface $migrate_executable, Row $row, $destination_property) {
list($path) = $value;
$path = ltrim($path, '/');
if (parse_url($path, PHP_URL_SCHEME) == NULL) {
// If $path is the node page (i.e. node/[nid]) then return entity path.
if (preg_match('/^node\/\d+$/', $path)) {
// "entity: URI"s enable the menu link to appear in the Menu Settings
// section on the node edit page. Other entities (e.g. taxonomy terms,
// users) do not have the Menu Settings section.
return 'entity:' . $path;
}
elseif ($path == '<front>') {
return 'internal:/';
}
else {
return 'internal:/' . $path;
}
}
return $path;
}
}
......@@ -23,7 +23,7 @@ class MigrateMenuLinkTest extends MigrateDrupal6TestBase {
protected function setUp() {
parent::setUp();
$this->installEntitySchema('menu_link_content');
$this->executeMigrations(['menu', 'menu_links']);
$this->executeMigrations(['d6_menu', 'd6_menu_links']);
}
/**
......
......@@ -2,7 +2,6 @@
namespace Drupal\Tests\menu_link_content\Kernel\Migrate\d7;
use Drupal\Core\Database\Database;
use Drupal\Core\Menu\MenuTreeParameters;
use Drupal\menu_link_content\Entity\MenuLinkContent;
use Drupal\menu_link_content\MenuLinkContentInterface;
......@@ -27,7 +26,7 @@ class MigrateMenuLinkTest extends MigrateDrupal7TestBase {
protected function setUp() {
parent::setUp();
$this->installEntitySchema('menu_link_content');
$this->executeMigration('menu');
$this->executeMigrations(['d7_menu', 'd7_menu_links']);
\Drupal::service('router.builder')->rebuild();
}
......@@ -52,21 +51,24 @@ protected function setUp() {
* The expected URI of the link.
* @param int $weight
* The expected weight of the link.
*
* @return \Drupal\menu_link_content\MenuLinkContentInterface
* The menu link content.
*/
protected function assertEntity($id, $title, $menu, $description, $enabled, $expanded, array $attributes, $uri, $weight) {
/** @var \Drupal\menu_link_content\MenuLinkContentInterface $menu_link */
$menu_link = MenuLinkContent::load($id);
$this->assertTrue($menu_link instanceof MenuLinkContentInterface);
$this->assertIdentical($title, $menu_link->getTitle());
$this->assertIdentical($menu, $menu_link->getMenuName());
$this->assertSame($title, $menu_link->getTitle());
$this->assertSame($menu, $menu_link->getMenuName());
// The migration sets the description of the link to the value of the
// 'title' attribute. Bit strange, but there you go.
$this->assertIdentical($description, $menu_link->getDescription());
$this->assertIdentical($enabled, $menu_link->isEnabled());
$this->assertIdentical($expanded, $menu_link->isExpanded());
$this->assertIdentical($attributes, $menu_link->link->options);
$this->assertIdentical($uri, $menu_link->link->uri);
$this->assertIdentical($weight, $menu_link->getWeight());
$this->assertSame($description, $menu_link->getDescription());
$this->assertSame($enabled, $menu_link->isEnabled());
$this->assertSame($expanded, $menu_link->isExpanded());
$this->assertSame($attributes, $menu_link->link->options);
$this->assertSame($uri, $menu_link->link->uri);
$this->assertSame($weight, $menu_link->getWeight());
return $menu_link;
}
......@@ -74,31 +76,36 @@ protected function assertEntity($id, $title, $menu, $description, $enabled, $exp
* Tests migration of menu links.
*/
public function testMenuLinks() {
$this->executeMigration('menu_links');
$this->assertEntity(469, 'Bing', static::MENU_NAME, 'Bing', TRUE, FALSE, ['attributes' => ['title' => 'Bing']], 'http://bing.com', 0);
$this->assertEntity(467, 'Google', static::MENU_NAME, 'Google', TRUE, FALSE, ['attributes' => ['title' => 'Google']], 'http://google.com', 0);
$this->assertEntity(468, 'Yahoo', static::MENU_NAME, 'Yahoo', TRUE, FALSE, ['attributes' => ['title' => 'Yahoo']], 'http://yahoo.com', 0);
// Tests migrating an external link with an undefined title attribute.
$this->assertEntity(470, 'Ask', static::MENU_NAME, NULL, TRUE, FALSE, [], 'http://ask.com', 0);
$this->assertEntity(245, 'Home', 'main', NULL, TRUE, FALSE, [], 'internal:/', 0);
$this->assertEntity(478, 'custom link test', 'admin', NULL, TRUE, FALSE, ['attributes' => ['title' => '']], 'internal:/admin/content/book', 0);
$this->assertEntity(479, 'node link test', 'tools', 'node 3', TRUE, FALSE, ['attributes' => ['title' => 'node 3']], 'entity:node/3', 3);
$menu_link_tree_service = \Drupal::service('menu.link_tree');
$parameters = new MenuTreeParameters();
$tree = $menu_link_tree_service->load(static::MENU_NAME, $parameters);
$this->assertEqual(2, count($tree));
$this->assertCount(2, $tree);
$children = 0;
$google_found = FALSE;
foreach ($tree as $menu_link_tree_element) {
$children += $menu_link_tree_element->hasChildren;
if ($menu_link_tree_element->link->getUrlObject()->toString() == 'http://bing.com') {
$this->assertEqual(reset($menu_link_tree_element->subtree)->link->getUrlObject()->toString(), 'http://google.com');
$this->assertEquals(reset($menu_link_tree_element->subtree)->link->getUrlObject()->toString(), 'http://google.com');
$google_found = TRUE;
}
}
$this->assertEqual(1, $children);
$this->assertEquals(1, $children);
$this->assertTrue($google_found);
// Now find the custom link under a system link.
$parameters->root = 'system.admin_structure';
$tree = $menu_link_tree_service->load(static::MENU_NAME, $parameters);
$found = FALSE;
foreach ($tree as $menu_link_tree_element) {
$this->pass($menu_link_tree_element->link->getUrlObject()->toString());
$this->assertTrue($menu_link_tree_element->link->getUrlObject()->toString());
if ($menu_link_tree_element->link->getTitle() == 'custom link test') {
$found = TRUE;
break;
......@@ -107,20 +114,4 @@ public function testMenuLinks() {
$this->assertTrue($found);
}
/**
* Tests migrating a link with an undefined title attribute.
*/
public function testUndefinedLinkTitle() {
Database::getConnection('default', 'migrate')
->update('menu_links')
->fields(array(
'options' => 'a:0:{}',
))
->condition('mlid', 467)
->execute();
$this->executeMigration('menu_links');
$this->assertEntity(467, 'Google', static::MENU_NAME, NULL, TRUE, FALSE, [], 'http://google.com', 0);
}
}
<?php
namespace Drupal\Tests\menu_link_content\Unit\Plugin\migrate\process\d7;
use Drupal\menu_link_content\Plugin\migrate\process\d7\InternalUri;
use Drupal\migrate\MigrateExecutableInterface;
use Drupal\migrate\Row;
use Drupal\Tests\UnitTestCase;
/**
* Tests \Drupal\menu_link_content\Plugin\migrate\process\d7\InternalUri.
*
* @group menu_link_content
*
* @coversDefaultClass \Drupal\menu_link_content\Plugin\migrate\process\d7\InternalUri
*/
class InternalUriTest extends UnitTestCase {
/**
* The 'd7_internal_uri' process plugin being tested.
*
* @var \Drupal\menu_link_content\Plugin\migrate\process\d7\InternalUri
*/
protected $processPlugin;
/**
* {@inheritdoc}
*/
protected function setUp() {
parent::setUp();
$this->processPlugin = new InternalUri([], 'd7_internal_uri', []);
}
/**
* Tests InternalUri::transform().
*
* @param array $value
* The value to pass to InternalUri::transform().
* @param string $expected
* The expected return value of InternalUri::transform().
*
* @dataProvider providerTestTransform
*
* @covers ::transform
*/
public function testTransform(array $value, $expected) {
$migrate_executable = $this->prophesize(MigrateExecutableInterface::class);
$row = $this->prophesize(Row::class);
$actual = $this->processPlugin->transform($value, $migrate_executable->reveal(), $row->reveal(), 'link/uri');
$this->assertEquals($expected, $actual);
}
/**
* Provides test cases for InternalUriTest::testTransform().
*
* @return array
* An array of test cases, each which the following values:
* - The value array to pass to InternalUri::transform().
* - The expected path returned by InternalUri::transform().
*/
public function providerTestTransform() {
$tests = [];
$tests['with_scheme'] = [['http://example.com'], 'http://example.com'];
$tests['leading_slash'] = [['/test'], 'internal:/test'];
$tests['without_scheme'] = [['test'], 'internal:/test'];
$tests['front'] = [['<front>'], 'internal:/'];
$tests['node'] = [['node/27'], 'entity:node/27'];
return $tests;
}
}
......@@ -19199,6 +19199,33 @@
'p9' => '0',
'updated' => '0',
))
->values(array(
'menu_name' => 'menu-test-menu',
'mlid' => '470',
'plid' => '469',
'link_path' => 'http://ask.com',
'router_path' => '',
'link_title' => 'Ask',
'options' => 'a:0:{}',
'module' => 'menu',
'hidden' => '0',
'external' => '1',
'has_children' => '0',
'expanded' => '0',
'weight' => '0',
'depth' => '2',
'customized' => '1',
'p1' => '469',
'p2' => '470',
'p3' => '0',
'p4' => '0',
'p5' => '0',
'p6' => '0',
'p7' => '0',
'p8' => '0',
'p9' => '0',
'updated' => '0',
))
->values(array(
'menu_name' => 'shortcut-set-2',
'mlid' => '472',
......@@ -19334,6 +19361,33 @@
'p9' => '0',
'updated' => '0',
))
->values(array(
'menu_name' => 'navigation',
'mlid' => '479',
'plid' => '0',
'link_path' => 'node/3',
'router_path' => 'node/3',
'link_title' => 'node link test',
'options' => 'a:1:{s:10:"attributes";a:1:{s:5:"title";s:6:"node 3";}}',
'module' => 'menu',
'hidden' => '0',
'external' => '0',
'has_children' => '0',
'expanded' => '0',
'weight' => '3',
'depth' => '1',
'customized' => '1',
'p1' => '479',
'p2' => '0',
'p3' => '0',
'p4' => '0',
'p5' => '0',
'p6' => '0',
'p7' => '0',
'p8' => '0',
'p9' => '0',
'updated' => '0',
))
->execute();
$connection->schema()->createTable('menu_router', array(
......@@ -290,7 +290,7 @@ class MigrateUpgradeForm extends ConfirmFormBase {
'source_module' => 'locale',
'destination_module' => 'locale',
],
'menu_links' => [
'd6_menu_links' => [
'source_module' => 'menu',
'destination_module' => 'menu_link_content',
],
......@@ -298,6 +298,10 @@ class MigrateUpgradeForm extends ConfirmFormBase {
'source_module' => 'menu',
'destination_module' => 'menu_ui',
],
'd7_menu_links' => [
'source_module' => 'menu',
'destination_module' => 'menu_link_content',
],
'd6_node' => [
'source_module' => 'node',
'destination_module' => 'node',
......@@ -474,7 +478,11 @@ class MigrateUpgradeForm extends ConfirmFormBase {
'source_module' => 'system',
'destination_module' => 'system',
],
'menu' => [
'd6_menu' => [
'source_module' => 'menu',
'destination_module' => 'system',
],
'd7_menu' => [
'source_module' => 'menu',
'destination_module' => 'system',
],
......
......@@ -57,13 +57,13 @@ protected function getEntityCounts() {
'shortcut' => 6,
'shortcut_set' => 2,
'action' => 16,
'menu' => 10,
'menu' => 6,
'taxonomy_term' => 18,
'taxonomy_vocabulary' => 3,
'tour' => 4,
'user' => 4,
'user_role' => 3,
'menu_link_content' => 9,
'menu_link_content' => 7,
'view' => 12,
'date_format' => 11,
'entity_form_display' => 16,
......
......@@ -23,4 +23,4 @@ destination:
migration_dependencies:
required:
- d7_shortcut_set
- menu_links
- d7_menu_links
......@@ -34,8 +34,8 @@ protected function setUp() {
$this->installEntitySchema('menu_link_content');
\Drupal::service('router.builder')->rebuild();
$this->executeMigration('d7_shortcut_set');
$this->executeMigration('menu');
$this->executeMigration('menu_links');
$this->executeMigration('d7_menu');
$this->executeMigration('d7_menu_links');
$this->executeMigration('d7_shortcut');
}
......
......@@ -36,8 +36,8 @@ protected function setUp() {
$this->executeMigration('d7_user_role');
$this->executeMigration('d7_user');
$this->executeMigration('d7_shortcut_set');
$this->executeMigration('menu');
$this->executeMigration('menu_links');
$this->executeMigration('d7_menu');
$this->executeMigration('d7_menu_links');
$this->executeMigration('d7_shortcut');
$this->executeMigration('d7_shortcut_set_users');
}
......
......@@ -34,8 +34,8 @@ protected function setUp() {
$this->installEntitySchema('menu_link_content');
\Drupal::service('router.builder')->rebuild();
$this->executeMigration('d7_shortcut_set');
$this->executeMigration('menu');
$this->executeMigration('menu_links');
$this->executeMigration('d7_menu');
$this->executeMigration('d7_menu_links');
$this->executeMigration('d7_shortcut');
}
......
# The menu_settings migration is in the menu_ui module.
id: menu
id: d6_menu
label: Menus
migration_tags:
- Drupal 6
- Drupal 7
source:
plugin: menu
process:
......
id: d7_menu
label: Menus
migration_tags:
- Drupal 7
source:
plugin: menu
process:
id:
plugin: static_map
bypass: true
source: menu_name
map:
main-menu: main
management: admin
navigation: tools
user-menu: account
label: title
description: description
destination:
plugin: entity:menu
<?php
namespace Drupal\Tests\system\Kernel\Migrate;
namespace Drupal\Tests\system\Kernel\Migrate\d6;
use Drupal\Core\Database\Database;
use Drupal\Tests\migrate_drupal\Kernel\d6\MigrateDrupal6TestBase;
......@@ -18,7 +18,7 @@ class MigrateMenuTest extends MigrateDrupal6TestBase {
*/
protected function setUp() {
parent::setUp();
$this->executeMigration('menu');
$this->executeMigration('d6_menu');
}
/**
......@@ -26,12 +26,12 @@ protected function setUp() {
*/
public function testMenu() {
$navigation_menu = Menu::load('navigation');
$this->assertIdentical('navigation', $navigation_menu->id());
$this->assertIdentical('Navigation', $navigation_menu->label());
$this->assertSame('navigation', $navigation_menu->id());
$this->assertSame('Navigation', $navigation_menu->label());
$expected = <<<EOT
The navigation menu is provided by Drupal and is the main interactive menu for any site. It is usually the only menu that contains personalized links for authenticated users, and is often not even visible to anonymous users.
EOT;
$this->assertIdentical($expected, $navigation_menu->getDescription());
$this->assertSame($expected, $navigation_menu->getDescription());
// Test that we can re-import using the ConfigEntityBase destination.
Database::getConnection('default', 'migrate')
......@@ -40,14 +40,14 @@ public function testMenu() {
->condition('menu_name', 'navigation')
->execute();
$migration = $this->getMigration('menu');
$migration = $this->getMigration('d6_menu');
\Drupal::database()
->truncate($migration->getIdMap()->mapTableName())
->execute();
$this->executeMigration($migration);
$navigation_menu = Menu::load('navigation');
$this->assertIdentical('Home Navigation', $navigation_menu->label());
$this->assertSame('Home Navigation', $navigation_menu->label());
}
}
<?php
namespace Drupal\Tests\system\Kernel\Migrate\d7;
use Drupal\Core\Database\Database;
use Drupal\Tests\migrate_drupal\Kernel\d7\MigrateDrupal7TestBase;
use Drupal\system\Entity\Menu;
/**
* Upgrade menus to system.menu.*.yml.
*
* @group migrate_drupal_7
*/
class MigrateMenuTest extends MigrateDrupal7TestBase {
/**
* {@inheritdoc}
*/
protected function setUp() {
parent::setUp();
$this->executeMigration('d7_menu');
}
/**
* Asserts various aspects of a menu.
*
* @param $id
* The menu ID.
* @param $label
* The menu label.
* @param $description
* The menu description.
*/
protected function assertEntity($id, $label, $description) {
$navigation_menu = Menu::load($id);
$this->assertSame($id, $navigation_menu->id());
$this->assertSame($label, $navigation_menu->label());
$this->assertSame($description, $navigation_menu->getDescription());
}
/**
* Tests the Drupal 7 menu to Drupal 8 migration.
*/