From 445132dfbd98b59349fc3bbf21c27e6e665f0cce Mon Sep 17 00:00:00 2001 From: Lee Rowlands Date: Fri, 11 Oct 2019 17:50:02 +1000 Subject: [PATCH] Issue #3009014 by amateescu, mikelutz, quietone, heddn: Convert path alias migrations to use entity:path_alias destination --- .../Plugin/migrate/process/NullCoalesce.php | 57 +++++++++ .../src/Unit/process/NullCoalesceTest.php | 92 ++++++++++++++ core/modules/path/migrations/d6_url_alias.yml | 25 +++- core/modules/path/migrations/d7_url_alias.yml | 18 ++- .../Plugin/migrate/destination/UrlAlias.php | 91 ++++---------- .../migrate/process/PathSetTranslated.php | 75 ++++++++++++ .../Migrate/d6/LegacyMigrateUrlAliasTest.php | 115 ++++++++++++++++++ .../Migrate/d7/LegacyMigrateUrlAliasTest.php | 110 +++++++++++++++++ .../migrate/process/PathSetTranslatedTest.php | 71 +++++++++++ 9 files changed, 576 insertions(+), 78 deletions(-) create mode 100644 core/modules/migrate/src/Plugin/migrate/process/NullCoalesce.php create mode 100644 core/modules/migrate/tests/src/Unit/process/NullCoalesceTest.php create mode 100644 core/modules/path/src/Plugin/migrate/process/PathSetTranslated.php create mode 100644 core/modules/path/tests/src/Kernel/Migrate/d6/LegacyMigrateUrlAliasTest.php create mode 100644 core/modules/path/tests/src/Kernel/Migrate/d7/LegacyMigrateUrlAliasTest.php create mode 100644 core/modules/path/tests/src/Unit/migrate/process/PathSetTranslatedTest.php diff --git a/core/modules/migrate/src/Plugin/migrate/process/NullCoalesce.php b/core/modules/migrate/src/Plugin/migrate/process/NullCoalesce.php new file mode 100644 index 00000000000..eda70f988e2 --- /dev/null +++ b/core/modules/migrate/src/Plugin/migrate/process/NullCoalesce.php @@ -0,0 +1,57 @@ +configuration['default_value'])) { + return $this->configuration['default_value']; + } + return NULL; + } + +} diff --git a/core/modules/migrate/tests/src/Unit/process/NullCoalesceTest.php b/core/modules/migrate/tests/src/Unit/process/NullCoalesceTest.php new file mode 100644 index 00000000000..8779be98fa9 --- /dev/null +++ b/core/modules/migrate/tests/src/Unit/process/NullCoalesceTest.php @@ -0,0 +1,92 @@ +expectException(MigrateException::class); + (new NullCoalesce([], 'null_coalesce', []))->transform('invalid', $this->migrateExecutable, $this->row, 'destinationproperty'); + } + + /** + * Tests null_coalesce. + * + * @param array $source + * The source value. + * @param mixed $expected_result + * The expected result. + * + * @covers ::transform + * + * @dataProvider transformDataProvider + * + * @throws \Drupal\migrate\MigrateException + */ + public function testTransform(array $source, $expected_result) { + $plugin = new NullCoalesce([], 'null_coalesce', []); + $result = $plugin->transform($source, $this->migrateExecutable, $this->row, 'destinationproperty'); + $this->assertSame($expected_result, $result); + } + + /** + * Provides Data for ::testTransform. + */ + public function transformDataProvider() { + return [ + 'all null' => [ + 'source' => [NULL, NULL, NULL], + 'expected_result' => NULL, + ], + 'false first' => [ + 'source' => [FALSE, NULL, NULL], + 'expected_result' => FALSE, + ], + 'no null' => [ + 'source' => ['test', 'test2'], + 'expected_result' => 'test', + ], + 'string first' => [ + 'source' => ['test', NULL, 'test2'], + 'expected_result' => 'test', + ], + 'empty string' => [ + 'source' => [NULL, '', NULL], + 'expected_result' => '', + ], + 'array' => [ + 'source' => [NULL, NULL, [1, 2, 3]], + 'expected_result' => [1, 2, 3], + ], + ]; + } + + /** + * Tests null_coalesce with default value. + * + * @covers ::transform + */ + public function testTransformWithDefault() { + $plugin = new NullCoalesce(['default_value' => 'default'], 'null_coalesce', []); + $result = $plugin->transform([NULL, NULL, 'Test', 'Test 2'], $this->migrateExecutable, $this->row, 'destinationproperty'); + $this->assertSame('Test', $result); + + $this->assertSame('default', $plugin->transform([NULL, NULL], $this->migrateExecutable, $this->row, 'destinationproperty')); + } + +} diff --git a/core/modules/path/migrations/d6_url_alias.yml b/core/modules/path/migrations/d6_url_alias.yml index 6263ae2a024..747a06805b0 100644 --- a/core/modules/path/migrations/d6_url_alias.yml +++ b/core/modules/path/migrations/d6_url_alias.yml @@ -8,7 +8,10 @@ source: constants: slash: '/' process: - source: + # If you are using this file to build a custom migration consider removing + # the id field to allow incremental migrations. + id: pid + _path: plugin: concat source: - constants/slash @@ -18,9 +21,7 @@ process: source: - constants/slash - dst - langcode: - plugin: d6_url_alias_language - source: language + node_translation: - plugin: explode @@ -35,5 +36,19 @@ process: - plugin: migration_lookup migration: d6_node_translation + langcode: + - + plugin: null_coalesce + source: + - '@node_translation/1' + - language + - + plugin: default_value + default_value: 'und' + path: + plugin: path_set_translated + source: + - '@_path' + - '@node_translation' destination: - plugin: url_alias + plugin: entity:path_alias diff --git a/core/modules/path/migrations/d7_url_alias.yml b/core/modules/path/migrations/d7_url_alias.yml index a4172dcf26c..b49686a7fbf 100644 --- a/core/modules/path/migrations/d7_url_alias.yml +++ b/core/modules/path/migrations/d7_url_alias.yml @@ -8,7 +8,10 @@ source: constants: slash: '/' process: - source: + # If you are using this file to build a custom migration consider removing + # the id field to allow incremental migrations. + id: pid + _path: plugin: concat source: - constants/slash @@ -18,7 +21,6 @@ process: source: - constants/slash - alias - langcode: language node_translation: - plugin: explode @@ -33,5 +35,15 @@ process: - plugin: migration_lookup migration: d7_node_translation + langcode: + plugin: null_coalesce + source: + - '@node_translation/1' + - language + path: + plugin: path_set_translated + source: + - '@_path' + - '@node_translation' destination: - plugin: url_alias + plugin: entity:path_alias diff --git a/core/modules/path/src/Plugin/migrate/destination/UrlAlias.php b/core/modules/path/src/Plugin/migrate/destination/UrlAlias.php index 15f5c21a03e..99517c67b32 100644 --- a/core/modules/path/src/Plugin/migrate/destination/UrlAlias.php +++ b/core/modules/path/src/Plugin/migrate/destination/UrlAlias.php @@ -2,100 +2,51 @@ namespace Drupal\path\Plugin\migrate\destination; -use Drupal\Core\Path\AliasStorageInterface; -use Drupal\migrate\Plugin\MigrationInterface; +use Drupal\migrate\Plugin\migrate\destination\EntityContentBase; use Drupal\migrate\Row; -use Drupal\migrate\Plugin\migrate\destination\DestinationBase; -use Symfony\Component\DependencyInjection\ContainerInterface; -use Drupal\Core\Plugin\ContainerFactoryPluginInterface; + +@trigger_error('UrlAlias is deprecated in drupal:8.8.0 and is removed from drupal:9.0.0. Use the entity:path_alias destination instead. See https://www.drupal.org/node/3013865', E_USER_DEPRECATED); /** + * Legacy destination class for non-entity path aliases. + * * @MigrateDestination( * id = "url_alias" * ) + * + * @deprecated in drupal:8.8.0 and is removed from drupal:9.0.0. Use + * the entity:path_alias destination instead. + * + * @see https://www.drupal.org/node/3013865 */ -class UrlAlias extends DestinationBase implements ContainerFactoryPluginInterface { - - /** - * The alias storage service. - * - * @var \Drupal\Core\Path\AliasStorageInterface - */ - protected $aliasStorage; - - /** - * Constructs an entity destination plugin. - * - * @param array $configuration - * A configuration array containing information about the plugin instance. - * @param string $plugin_id - * The plugin_id for the plugin instance. - * @param mixed $plugin_definition - * The plugin implementation definition. - * @param \Drupal\migrate\Plugin\MigrationInterface $migration - * The migration. - * @param \Drupal\Core\Path\AliasStorageInterface $alias_storage - * The alias storage service. - */ - public function __construct(array $configuration, $plugin_id, $plugin_definition, MigrationInterface $migration, AliasStorageInterface $alias_storage) { - parent::__construct($configuration, $plugin_id, $plugin_definition, $migration); - $this->aliasStorage = $alias_storage; - } - - /** - * {@inheritdoc} - */ - public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition, MigrationInterface $migration = NULL) { - return new static( - $configuration, - $plugin_id, - $plugin_definition, - $migration, - $container->get('path.alias_storage') - ); - } +class UrlAlias extends EntityContentBase { /** * {@inheritdoc} */ public function import(Row $row, array $old_destination_id_values = []) { - $source = $row->getDestinationProperty('source'); - $alias = $row->getDestinationProperty('alias'); - $langcode = $row->getDestinationProperty('langcode'); - $pid = $old_destination_id_values ? $old_destination_id_values[0] : NULL; + if ($row->getDestinationProperty('source')) { + $row->setDestinationProperty('path', $row->getDestinationProperty('source')); + } + $path = $row->getDestinationProperty('path'); // Check if this alias is for a node and if that node is a translation. - if (preg_match('/^\/node\/\d+$/', $source) && $row->hasDestinationProperty('node_translation')) { + if (preg_match('/^\/node\/\d+$/', $path) && $row->hasDestinationProperty('node_translation')) { // Replace the alias source with the translation source path. $node_translation = $row->getDestinationProperty('node_translation'); - $source = '/node/' . $node_translation[0]; - $langcode = $node_translation[1]; + $row->setDestinationProperty('path', '/node/' . $node_translation[0]); + $row->setDestinationProperty('langcode', $node_translation[1]); } - $path = $this->aliasStorage->save($source, $alias, $langcode, $pid); - - return [$path['pid']]; + return parent::import($row, $old_destination_id_values); } /** * {@inheritdoc} */ - public function getIds() { - $ids['pid']['type'] = 'integer'; - return $ids; - } - - /** - * {@inheritdoc} - */ - public function fields(MigrationInterface $migration = NULL) { - return [ - 'pid' => 'The path id', - 'source' => 'The source path.', - 'alias' => 'The URL alias.', - 'langcode' => 'The language code for the URL.', - ]; + protected static function getEntityTypeId($plugin_id) { + return 'path_alias'; } } diff --git a/core/modules/path/src/Plugin/migrate/process/PathSetTranslated.php b/core/modules/path/src/Plugin/migrate/process/PathSetTranslated.php new file mode 100644 index 00000000000..74ed9652d96 --- /dev/null +++ b/core/modules/path/src/Plugin/migrate/process/PathSetTranslated.php @@ -0,0 +1,75 @@ +' will pass through unchanged, as will any inputs with invalid + * or missing translated nodes. + * + * This plugin will return the correct path for the translated node if the above + * conditions are met, and will return the original path otherwise. + * + * Example: + * node_translation: + * - + * plugin: explode + * source: source + * delimiter: / + * - + * # If the source path has no slashes return a dummy default value. + * plugin: extract + * default: 'INVALID_NID' + * index: + * - 1 + * - + * plugin: migration_lookup + * migration: d7_node_translation + * _path: + * plugin: concat + * source: + * - constants/slash + * - source + * path: + * plugin: path_set_translated + * source: + * - '@_path' + * - '@node_translation' + * + * In the example above, if the node_translation lookup succeeds and the + * original path is of the format '/node/', then the new path + * will be set to '/node/' + * + * @MigrateProcessPlugin( + * id = "path_set_translated" + * ) + */ +class PathSetTranslated extends ProcessPluginBase { + + /** + * {@inheritdoc} + */ + public function transform($value, MigrateExecutableInterface $migrate_executable, Row $row, $destination_property) { + if (!is_array($value)) { + throw new MigrateException("The input value should be an array."); + } + + $path = isset($value[0]) ? $value[0] : ''; + $nid = (is_array($value[1]) && isset($value[1][0])) ? $value[1][0] : FALSE; + if (preg_match('/^\/node\/\d+$/', $path) && $nid) { + return '/node/' . $nid; + } + return $path; + } + +} diff --git a/core/modules/path/tests/src/Kernel/Migrate/d6/LegacyMigrateUrlAliasTest.php b/core/modules/path/tests/src/Kernel/Migrate/d6/LegacyMigrateUrlAliasTest.php new file mode 100644 index 00000000000..9570f16b407 --- /dev/null +++ b/core/modules/path/tests/src/Kernel/Migrate/d6/LegacyMigrateUrlAliasTest.php @@ -0,0 +1,115 @@ + 'd6_url_alias', + 'label' => 'URL aliases', + 'migration_tags' => + [ + 0 => 'Drupal 6', + 1 => 'Content', + ], + 'source' => + [ + 'plugin' => 'd6_url_alias', + 'constants' => + [ + 'slash' => '/', + ], + ], + 'process' => + [ + 'source' => + [ + 'plugin' => 'concat', + 'source' => + [ + 0 => 'constants/slash', + 1 => 'src', + ], + ], + 'alias' => + [ + 'plugin' => 'concat', + 'source' => + [ + 0 => 'constants/slash', + 1 => 'dst', + ], + ], + 'langcode' => + [ + 'plugin' => 'd6_url_alias_language', + 'source' => 'language', + ], + 'node_translation' => + [ + 0 => + [ + 'plugin' => 'explode', + 'source' => 'src', + 'delimiter' => '/', + ], + 1 => + [ + 'plugin' => 'extract', + 'default' => 'INVALID_NID', + 'index' => + [ + 0 => 1, + ], + ], + 2 => + [ + 'plugin' => 'migration_lookup', + 'migration' => 'd6_node_translation', + ], + ], + ], + 'destination' => + [ + 'plugin' => 'url_alias', + ], + ]; + + /** + * {@inheritdoc} + */ + protected function setUp() { + MigrateDrupal6TestBase::setUp(); + $this->installEntitySchema('node'); + $this->installEntitySchema('path_alias'); + $this->installConfig(['node']); + $this->installSchema('node', ['node_access']); + $this->migrateUsers(FALSE); + $this->migrateFields(); + + $this->executeMigrations([ + 'language', + 'd6_node_settings', + 'd6_node', + 'd6_node_translation', + ]); + $this->executeMigration(\Drupal::service('plugin.manager.migration')->createStubMigration($this->stubMigration)); + $this->expectDeprecation('UrlAlias is deprecated in drupal:8.8.0 and is removed from drupal:9.0.0. Use the entity:path_alias destination instead. See https://www.drupal.org/node/3013865'); + } + +} diff --git a/core/modules/path/tests/src/Kernel/Migrate/d7/LegacyMigrateUrlAliasTest.php b/core/modules/path/tests/src/Kernel/Migrate/d7/LegacyMigrateUrlAliasTest.php new file mode 100644 index 00000000000..27eb2021561 --- /dev/null +++ b/core/modules/path/tests/src/Kernel/Migrate/d7/LegacyMigrateUrlAliasTest.php @@ -0,0 +1,110 @@ + 'd7_url_alias', + 'label' => 'URL aliases', + 'migration_tags' => + [ + 0 => 'Drupal 7', + 1 => 'Content', + ], + 'source' => + [ + 'plugin' => 'd7_url_alias', + 'constants' => + [ + 'slash' => '/', + ], + ], + 'process' => + [ + 'source' => + [ + 'plugin' => 'concat', + 'source' => + [ + 0 => 'constants/slash', + 1 => 'source', + ], + ], + 'alias' => + [ + 'plugin' => 'concat', + 'source' => + [ + 0 => 'constants/slash', + 1 => 'alias', + ], + ], + 'langcode' => 'language', + 'node_translation' => + [ + 0 => + [ + 'plugin' => 'explode', + 'source' => 'source', + 'delimiter' => '/', + ], + 1 => + [ + 'plugin' => 'extract', + 'default' => 'INVALID_NID', + 'index' => + [ + 0 => 1, + ], + ], + 2 => + [ + 'plugin' => 'migration_lookup', + 'migration' => 'd7_node_translation', + ], + ], + ], + 'destination' => + [ + 'plugin' => 'url_alias', + ], + ]; + + /** + * {@inheritdoc} + */ + protected function setUp() { + MigrateDrupal7TestBase::setUp(); + + $this->installEntitySchema('node'); + $this->installEntitySchema('path_alias'); + $this->installConfig('node'); + $this->installSchema('node', ['node_access']); + + $this->migrateUsers(FALSE); + $this->migrateContentTypes(); + $this->executeMigrations([ + 'language', + 'd7_node', + 'd7_node_translation', + ]); + $this->executeMigration(\Drupal::service('plugin.manager.migration')->createStubMigration($this->stubMigration)); + $this->expectDeprecation('UrlAlias is deprecated in drupal:8.8.0 and is removed from drupal:9.0.0. Use the entity:path_alias destination instead. See https://www.drupal.org/node/3013865'); + } + +} diff --git a/core/modules/path/tests/src/Unit/migrate/process/PathSetTranslatedTest.php b/core/modules/path/tests/src/Unit/migrate/process/PathSetTranslatedTest.php new file mode 100644 index 00000000000..1af7e53e4c8 --- /dev/null +++ b/core/modules/path/tests/src/Unit/migrate/process/PathSetTranslatedTest.php @@ -0,0 +1,71 @@ +assertSame($expected_result, $plugin->transform([$path, $node_translation], $this->migrateExecutable, $this->row, 'destination_property')); + } + + /** + * Provides data for the testTransform method. + * + * @return array + * The data. + */ + public function transformDataProvider() { + return [ + 'non-node-path' => [ + 'path' => '/non-node-path', + 'node_translation' => [1, 'en'], + 'expected_result' => '/non-node-path', + ], + 'no_translated_node_1' => [ + 'path' => '/node/1', + 'node_translation' => 'INVALID_NID', + 'expected_result' => '/node/1', + ], + 'no_translated_node_2' => [ + 'path' => '/node/1', + 'node_translation' => NULL, + 'expected_result' => '/node/1', + ], + 'no_translated_node_3' => [ + 'path' => '/node/1', + 'node_translation' => FALSE, + 'expected_result' => '/node/1', + ], + 'valid_transform' => [ + 'path' => '/node/1', + 'node_translation' => [3, 'en'], + 'expected_result' => '/node/3', + ], + ]; + } + +}