first commit
This commit is contained in:
@@ -0,0 +1,10 @@
|
||||
# Migrations with any of these tags will raise an exception if their source
|
||||
# plugin is missing the source_module property in their annotation.
|
||||
enforce_source_module_tags:
|
||||
- Drupal 6
|
||||
- Drupal 7
|
||||
# Migrations with any of these tags will not be derived and executed with the
|
||||
# other migrations. They will be derived and executed after the migrations on
|
||||
# which they depend have been successfully executed.
|
||||
follow_up_migration_tags:
|
||||
- Follow-up migration
|
||||
@@ -0,0 +1,16 @@
|
||||
migrate_drupal.settings:
|
||||
type: config_object
|
||||
label: 'Migrate Drupal settings'
|
||||
mapping:
|
||||
enforce_source_module_tags:
|
||||
type: sequence
|
||||
label: 'source_module enforcement tags'
|
||||
sequence:
|
||||
type: string
|
||||
label: 'Tag'
|
||||
follow_up_migration_tags:
|
||||
type: sequence
|
||||
label: 'Follow-up migration tags'
|
||||
sequence:
|
||||
type: string
|
||||
label: 'Tag'
|
||||
@@ -0,0 +1,8 @@
|
||||
name: Migrate Drupal
|
||||
type: module
|
||||
description: 'Contains migrations from older Drupal versions.'
|
||||
package: Migration
|
||||
version: VERSION
|
||||
core: 8.x
|
||||
dependencies:
|
||||
- drupal:migrate
|
||||
@@ -0,0 +1,33 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains install and update functions for Migrate Drupal
|
||||
*/
|
||||
|
||||
/**
|
||||
* Creates migrate_drupal.settings config object.
|
||||
*/
|
||||
function migrate_drupal_update_8501() {
|
||||
\Drupal::configFactory()
|
||||
->getEditable('migrate_drupal.settings')
|
||||
->set('enforce_source_module_tags', ['Drupal 6', 'Drupal 7'])
|
||||
->save();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the follow-up migration tags.
|
||||
*/
|
||||
function migrate_drupal_update_8502() {
|
||||
\Drupal::configFactory()
|
||||
->getEditable('migrate_drupal.settings')
|
||||
->set('follow_up_migration_tags', ['Follow-up migration'])
|
||||
->save();
|
||||
}
|
||||
|
||||
/**
|
||||
* Install migrate_drupal_multilingual since migrate_drupal is installed.
|
||||
*/
|
||||
function migrate_drupal_update_8601() {
|
||||
\Drupal::service('module_installer')->install(['migrate_drupal_multilingual']);
|
||||
}
|
||||
@@ -0,0 +1,142 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Provides migration from other Drupal sites.
|
||||
*/
|
||||
|
||||
use Drupal\Core\Database\DatabaseExceptionWrapper;
|
||||
use Drupal\Core\Routing\RouteMatchInterface;
|
||||
use Drupal\Core\Url;
|
||||
use Drupal\migrate\Exception\RequirementsException;
|
||||
use Drupal\migrate\MigrateExecutable;
|
||||
use Drupal\migrate\Plugin\RequirementsInterface;
|
||||
use Drupal\migrate_drupal\MigrationConfigurationTrait;
|
||||
use Drupal\migrate_drupal\NodeMigrateType;
|
||||
|
||||
/**
|
||||
* Implements hook_help().
|
||||
*/
|
||||
function migrate_drupal_help($route_name, RouteMatchInterface $route_match) {
|
||||
switch ($route_name) {
|
||||
case 'help.page.migrate_drupal':
|
||||
$output = '';
|
||||
$output .= '<h3>' . t('About') . '</h3>';
|
||||
$output .= '<p>' . t('The Migrate Drupal module provides a framework based on the <a href=":migrate">Migrate module</a> to facilitate migration from a Drupal (6, 7, or 8) site to your website. It does not provide a user interface. For more information, see the <a href=":migrate_drupal">online documentation for the Migrate Drupal module</a>.', [':migrate' => Url::fromRoute('help.page', ['name' => 'migrate'])->toString(), ':migrate_drupal' => 'https://www.drupal.org/documentation/modules/migrate_drupal']) . '</p>';
|
||||
return $output;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_migration_plugins_alter().
|
||||
*/
|
||||
function migrate_drupal_migration_plugins_alter(array &$definitions) {
|
||||
$module_handler = \Drupal::service('module_handler');
|
||||
$migration_plugin_manager = \Drupal::service('plugin.manager.migration');
|
||||
|
||||
// This is why the deriver can't do this: the 'd6_taxonomy_vocabulary'
|
||||
// definition is not available to the deriver as it is running inside
|
||||
// getDefinitions().
|
||||
if (isset($definitions['d6_taxonomy_vocabulary'])) {
|
||||
$vocabulary_migration_definition = [
|
||||
'source' => [
|
||||
'ignore_map' => TRUE,
|
||||
'plugin' => 'd6_taxonomy_vocabulary',
|
||||
],
|
||||
'destination' => [
|
||||
'plugin' => 'null',
|
||||
],
|
||||
'idMap' => [
|
||||
'plugin' => 'null',
|
||||
],
|
||||
];
|
||||
$vocabulary_migration = $migration_plugin_manager->createStubMigration($vocabulary_migration_definition);
|
||||
$translation_active = $module_handler->moduleExists('content_translation');
|
||||
|
||||
try {
|
||||
$source_plugin = $vocabulary_migration->getSourcePlugin();
|
||||
if ($source_plugin instanceof RequirementsInterface) {
|
||||
$source_plugin->checkRequirements();
|
||||
}
|
||||
$executable = new MigrateExecutable($vocabulary_migration);
|
||||
$process = ['vid' => $definitions['d6_taxonomy_vocabulary']['process']['vid']];
|
||||
foreach ($source_plugin as $row) {
|
||||
$executable->processRow($row, $process);
|
||||
$source_vid = $row->getSourceProperty('vid');
|
||||
$plugin_ids = [
|
||||
'd6_term_node:' . $source_vid,
|
||||
'd6_term_node_revision:' . $source_vid,
|
||||
];
|
||||
if ($translation_active) {
|
||||
$plugin_ids[] = 'd6_term_node_translation:' . $source_vid;
|
||||
}
|
||||
foreach (array_intersect($plugin_ids, array_keys($definitions)) as $plugin_id) {
|
||||
// Match the field name derivation in d6_vocabulary_field.yml.
|
||||
$field_name = substr('field_' . $row->getDestinationProperty('vid'), 0, 32);
|
||||
|
||||
// The Forum module is expecting 'taxonomy_forums' as the field name
|
||||
// for the forum nodes. The 'forum_vocabulary' source property is
|
||||
// evaluated in Drupal\taxonomy\Plugin\migrate\source\d6\Vocabulary
|
||||
// and is set to true if the vocabulary vid being migrated is the
|
||||
// same as the one in the 'forum_nav_vocabulary' variable on the
|
||||
// source site.
|
||||
$destination_vid = $row->getSourceProperty('forum_vocabulary') ? 'taxonomy_forums' : $field_name;
|
||||
$definitions[$plugin_id]['process'][$destination_vid] = 'tid';
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (RequirementsException $e) {
|
||||
// This code currently runs whenever the definitions are being loaded and
|
||||
// if you have a Drupal 7 source site then the requirements will not be
|
||||
// met for the d6_taxonomy_vocabulary migration.
|
||||
}
|
||||
catch (DatabaseExceptionWrapper $e) {
|
||||
// When the definitions are loaded it is possible the tables will not
|
||||
// exist.
|
||||
}
|
||||
}
|
||||
|
||||
if (!$module_handler->moduleExists('node')) {
|
||||
return;
|
||||
}
|
||||
|
||||
$connection = \Drupal::database();
|
||||
// We need to get the version of the source database in order to check
|
||||
// if the classic or complete node tables have been used in a migration.
|
||||
if (isset($definitions['system_site'])) {
|
||||
// Use the source plugin of the system_site migration to get the
|
||||
// database connection.
|
||||
$migration = $definitions['system_site'];
|
||||
/** @var \Drupal\migrate\Plugin\migrate\source\SqlBase $source_plugin */
|
||||
$source_plugin = $migration_plugin_manager->createStubMigration($migration)
|
||||
->getSourcePlugin();
|
||||
|
||||
try {
|
||||
$source_connection = $source_plugin->getDatabase();
|
||||
$version = MigrationConfigurationTrait::getLegacyDrupalVersion($source_connection);
|
||||
}
|
||||
catch (\Exception $e) {
|
||||
\Drupal::messenger()
|
||||
->addError(t('Failed to connect to your database server. The server reports the following message: %error.<ul><li>Is the database server running?</li><li>Does the database exist, and have you entered the correct database name?</li><li>Have you entered the correct username and password?</li><li>Have you entered the correct database hostname?</li></ul>', ['%error' => $e->getMessage()]));
|
||||
}
|
||||
}
|
||||
// If this is a complete node migration then for all migrations, except the
|
||||
// classic node migrations, replace any dependency on a classic node migration
|
||||
// with a dependency on the complete node migration.
|
||||
if (NodeMigrateType::getNodeMigrateType($connection, $version ?? FALSE) === NodeMigrateType::NODE_MIGRATE_TYPE_COMPLETE) {
|
||||
$classic_migration_match = '/d([67])_(node|node_translation|node_revision|node_entity_translation)($|:.*)/';
|
||||
$replace_with_complete_migration = function (&$value, $key, $classic_migration_match) {
|
||||
if (is_string($value)) {
|
||||
$value = preg_replace($classic_migration_match, 'd$1_node_complete$3', $value);
|
||||
}
|
||||
};
|
||||
|
||||
foreach ($definitions as &$definition) {
|
||||
$is_node_classic_migration = preg_match($classic_migration_match, $definition['id']);
|
||||
if (!$is_node_classic_migration && isset($definition['migration_dependencies'])) {
|
||||
array_walk_recursive($definition['migration_dependencies'], $replace_with_complete_migration, $classic_migration_match);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Post update functions for migrate_drupal.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Force MigrateField plugin definitions to be cleared.
|
||||
*
|
||||
* @see https://www.drupal.org/node/3006470
|
||||
*/
|
||||
function drupal_migrate_post_update_clear_migrate_field_plugin_cache() {
|
||||
// Empty post-update hook.
|
||||
}
|
||||
|
||||
/**
|
||||
* Uninstall migrate_drupal_multilingual since migrate_drupal is installed.
|
||||
*/
|
||||
function migrate_drupal_post_update_uninstall_multilingual() {
|
||||
\Drupal::service('module_installer')->uninstall(['migrate_drupal_multilingual']);
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
services:
|
||||
plugin.manager.migrate.field:
|
||||
class: Drupal\migrate_drupal\Plugin\MigrateFieldPluginManager
|
||||
arguments:
|
||||
- field
|
||||
- '@container.namespaces'
|
||||
- '@cache.discovery'
|
||||
- '@module_handler'
|
||||
- '\Drupal\migrate_drupal\Annotation\MigrateField'
|
||||
plugin.manager.migrate.cckfield:
|
||||
class: Drupal\migrate_drupal\Plugin\MigrateCckFieldPluginManager
|
||||
arguments:
|
||||
- cckfield
|
||||
- '@container.namespaces'
|
||||
- '@cache.discovery'
|
||||
- '@module_handler'
|
||||
- '\Drupal\migrate_drupal\Annotation\MigrateCckField'
|
||||
deprecated: The "%service_id%" service is deprecated. You should use the 'plugin.manager.migrate.field' service instead. See https://www.drupal.org/node/2751897
|
||||
logger.channel.migrate_drupal:
|
||||
parent: logger.channel_base
|
||||
arguments: ['migrate_drupal']
|
||||
migrate_drupal.field_discovery:
|
||||
class: Drupal\migrate_drupal\FieldDiscovery
|
||||
arguments:
|
||||
- '@plugin.manager.migrate.field'
|
||||
- '@plugin.manager.migration'
|
||||
- '@logger.channel.migrate_drupal'
|
||||
migrate_drupal.migration_state:
|
||||
class: Drupal\migrate_drupal\MigrationState
|
||||
arguments: ['@plugin.manager.migrate.field', '@module_handler', '@messenger', '@string_translation']
|
||||
@@ -0,0 +1,95 @@
|
||||
# The modules listed here do not have an migration. A status of finished is
|
||||
# assigned so that they appear in the will not be upgraded list on the Review
|
||||
# form.
|
||||
finished:
|
||||
6:
|
||||
nodereference: core
|
||||
userreference: core
|
||||
# Blog requires node.
|
||||
blog: node
|
||||
# The following do not have an upgrade path.
|
||||
blogapi: core
|
||||
calendarsignup: core
|
||||
color: core
|
||||
content_copy: core
|
||||
content_multigroup: core
|
||||
content_permissions: core
|
||||
date_api: core
|
||||
date_locale: core
|
||||
date_php4: core
|
||||
date_popup: core
|
||||
date_repeat: core
|
||||
date_timezone: core
|
||||
date_tools: core
|
||||
datepicker: core
|
||||
ddblock: core
|
||||
event: core
|
||||
fieldgroup: core
|
||||
filefield_meta: core
|
||||
help: core
|
||||
# i18n modules require content_translation.
|
||||
i18ncontent: content_translation
|
||||
i18npoll: content_translation
|
||||
i18nstrings: content_translation
|
||||
i18nsync: content_translation
|
||||
imageapi: core
|
||||
imageapi_gd: core
|
||||
imageapi_imagemagick: core
|
||||
imagecache_ui: core
|
||||
nodeaccess: core
|
||||
number: core
|
||||
openid: core
|
||||
php: core
|
||||
ping: core
|
||||
poll: core
|
||||
throttle: core
|
||||
tracker: core
|
||||
translation: core
|
||||
trigger: core
|
||||
variable: core
|
||||
variable_admin: core
|
||||
views_export: core
|
||||
views_ui: core
|
||||
7:
|
||||
# Blog requires node.
|
||||
blog: node
|
||||
# The following do not need have an upgrade path.
|
||||
bulk_export: core
|
||||
contextual: core
|
||||
ctools: core
|
||||
ctools_access_ruleset: core
|
||||
ctools_ajax_sample: core
|
||||
ctools_custom_content: core
|
||||
dashboard: core
|
||||
date_all_day: core
|
||||
date_api: core
|
||||
date_context: core
|
||||
date_migrate: core
|
||||
date_popup: core
|
||||
date_repeat: core
|
||||
date_repeat_field: core
|
||||
date_tools: core
|
||||
date_views: core
|
||||
entity: core
|
||||
entity_feature: core
|
||||
entity_token: core
|
||||
entityreference: core
|
||||
field_ui: core
|
||||
help: core
|
||||
openid: core
|
||||
overlay: core
|
||||
page_manager: core
|
||||
php: core
|
||||
poll: core
|
||||
search_embedded_form: core
|
||||
search_extra_type: core
|
||||
search_node_tags: core
|
||||
simpletest: core
|
||||
stylizer: core
|
||||
term_depth: core
|
||||
title: core
|
||||
toolbar: core
|
||||
translation: core
|
||||
trigger: core
|
||||
views_content: core
|
||||
views_ui: core
|
||||
@@ -0,0 +1,21 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\migrate_drupal\Annotation;
|
||||
|
||||
@trigger_error('MigrateCckField is deprecated in Drupal 8.3.x and will be removed before Drupal 9.0.x. Use \Drupal\migrate_drupal\Annotation\MigrateField instead.', E_USER_DEPRECATED);
|
||||
|
||||
/**
|
||||
* Deprecated: Defines a cckfield plugin annotation object.
|
||||
*
|
||||
* @deprecated in drupal:8.3.0 and is removed from drupal:9.0.0. Use
|
||||
* \Drupal\migrate_drupal\Annotation\MigrateField instead.
|
||||
*
|
||||
* Plugin Namespace: Plugin\migrate\cckfield
|
||||
*
|
||||
* @see https://www.drupal.org/node/2751897
|
||||
*
|
||||
* @Annotation
|
||||
*/
|
||||
class MigrateCckField extends MigrateField {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,85 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\migrate_drupal\Annotation;
|
||||
|
||||
use Drupal\Component\Annotation\Plugin;
|
||||
|
||||
/**
|
||||
* Defines a field plugin annotation object.
|
||||
*
|
||||
* Field plugins are responsible for handling the migration of custom fields
|
||||
* (provided by CCK in Drupal 6 and Field API in Drupal 7) to Drupal 8. They are
|
||||
* allowed to alter fieldable entity migrations when these migrations are being
|
||||
* generated, and can compute destination field types for individual fields
|
||||
* during the actual migration process.
|
||||
*
|
||||
* Plugin Namespace: Plugin\migrate\field
|
||||
*
|
||||
* @Annotation
|
||||
*/
|
||||
class MigrateField extends Plugin {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function __construct($values) {
|
||||
parent::__construct($values);
|
||||
// Provide default value for core property, in case it's missing.
|
||||
if (empty($this->definition['core'])) {
|
||||
$this->definition['core'] = [6];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The plugin ID.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $id;
|
||||
|
||||
/**
|
||||
* Map of D6 and D7 field types to D8 field type plugin IDs.
|
||||
*
|
||||
* @var string[]
|
||||
*/
|
||||
public $type_map = [];
|
||||
|
||||
/**
|
||||
* The Drupal core version(s) this plugin applies to.
|
||||
*
|
||||
* @var int[]
|
||||
*/
|
||||
public $core;
|
||||
|
||||
/**
|
||||
* Identifies the system providing the data the field plugin will read.
|
||||
*
|
||||
* The source_module is expected to be the name of a Drupal module that must
|
||||
* be installed in the source database.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $source_module;
|
||||
|
||||
/**
|
||||
* Identifies the system handling the data the destination plugin will write.
|
||||
*
|
||||
* The destination_module is expected to be the name of a Drupal module on the
|
||||
* destination site that must be installed.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $destination_module;
|
||||
|
||||
/**
|
||||
* The weight of this plugin relative to other plugins.
|
||||
*
|
||||
* The weight of this plugin relative to other plugins servicing the same
|
||||
* field type and core version. The lowest weighted applicable plugin will be
|
||||
* used for each field.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
public $weight = 0;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,385 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\migrate_drupal;
|
||||
|
||||
use Drupal\Component\Plugin\Exception\PluginNotFoundException;
|
||||
use Drupal\migrate\Exception\RequirementsException;
|
||||
use Drupal\migrate\Plugin\MigrationInterface;
|
||||
use Drupal\migrate\Plugin\MigrationPluginManagerInterface;
|
||||
use Drupal\migrate\Plugin\RequirementsInterface;
|
||||
use Drupal\migrate_drupal\Plugin\MigrateCckFieldInterface;
|
||||
use Drupal\migrate_drupal\Plugin\MigrateFieldPluginManagerInterface;
|
||||
use Psr\Log\LoggerInterface;
|
||||
|
||||
/**
|
||||
* Provides field discovery for Drupal 6 & 7 migrations.
|
||||
*/
|
||||
class FieldDiscovery implements FieldDiscoveryInterface {
|
||||
|
||||
/**
|
||||
* The CCK plugin manager.
|
||||
*
|
||||
* @var \Drupal\migrate_drupal\Plugin\MigrateCckFieldPluginManagerInterface
|
||||
*/
|
||||
protected $cckPluginManager;
|
||||
|
||||
/**
|
||||
* An array of already discovered field plugin information.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $fieldPluginCache;
|
||||
|
||||
/**
|
||||
* The field plugin manager.
|
||||
*
|
||||
* @var \Drupal\migrate_drupal\Plugin\MigrateFieldPluginManagerInterface
|
||||
*/
|
||||
protected $fieldPluginManager;
|
||||
|
||||
/**
|
||||
* The migration plugin manager.
|
||||
*
|
||||
* @var \Drupal\migrate\Plugin\MigrationPluginManagerInterface
|
||||
*/
|
||||
protected $migrationPluginManager;
|
||||
|
||||
/**
|
||||
* The logger channel service.
|
||||
*
|
||||
* @var \Psr\Log\LoggerInterface
|
||||
*/
|
||||
protected $logger;
|
||||
|
||||
/**
|
||||
* A cache of discovered fields.
|
||||
*
|
||||
* It is an array of arrays. If the entity type is bundleable, a third level
|
||||
* of arrays is added to account for fields discovered at the bundle level.
|
||||
*
|
||||
* [{core}][{entity_type}][{bundle}]
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $discoveredFieldsCache = [];
|
||||
|
||||
/**
|
||||
* An array of bundle keys, keyed by drupal core version.
|
||||
*
|
||||
* In Drupal 6, only nodes were fieldable, and the bundles were called
|
||||
* 'type_name'. In Drupal 7, everything became entities, and the more
|
||||
* generic 'bundle' was used.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $bundleKeys = [
|
||||
FieldDiscoveryInterface::DRUPAL_6 => 'type_name',
|
||||
FieldDiscoveryInterface::DRUPAL_7 => 'bundle',
|
||||
];
|
||||
|
||||
/**
|
||||
* An array of source plugin ids, keyed by Drupal core version.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $sourcePluginIds = [
|
||||
FieldDiscoveryInterface::DRUPAL_6 => 'd6_field_instance',
|
||||
FieldDiscoveryInterface::DRUPAL_7 => 'd7_field_instance',
|
||||
];
|
||||
|
||||
/**
|
||||
* An array of supported Drupal core versions.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $supportedCoreVersions = [
|
||||
FieldDiscoveryInterface::DRUPAL_6,
|
||||
FieldDiscoveryInterface::DRUPAL_7,
|
||||
];
|
||||
|
||||
/**
|
||||
* Constructs a FieldDiscovery object.
|
||||
*
|
||||
* @param \Drupal\migrate_drupal\Plugin\MigrateFieldPluginManagerInterface $field_plugin_manager
|
||||
* The field plugin manager.
|
||||
* @param \Drupal\migrate\Plugin\MigrationPluginManagerInterface $migration_plugin_manager
|
||||
* The migration plugin manager.
|
||||
* @param \Psr\Log\LoggerInterface $logger
|
||||
* The logger channel service.
|
||||
*/
|
||||
public function __construct(MigrateFieldPluginManagerInterface $field_plugin_manager, MigrationPluginManagerInterface $migration_plugin_manager, LoggerInterface $logger) {
|
||||
$this->fieldPluginManager = $field_plugin_manager;
|
||||
$this->migrationPluginManager = $migration_plugin_manager;
|
||||
$this->logger = $logger;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function addAllFieldProcesses(MigrationInterface $migration) {
|
||||
$core = $this->getCoreVersion($migration);
|
||||
$fields = $this->getAllFields($core);
|
||||
foreach ($fields as $entity_type_id => $bundle) {
|
||||
$this->addEntityFieldProcesses($migration, $entity_type_id);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function addEntityFieldProcesses(MigrationInterface $migration, $entity_type_id) {
|
||||
$core = $this->getCoreVersion($migration);
|
||||
$fields = $this->getAllFields($core);
|
||||
if (!empty($fields[$entity_type_id]) && is_array($fields[$entity_type_id])) {
|
||||
foreach ($fields[$entity_type_id] as $bundle => $fields) {
|
||||
$this->addBundleFieldProcesses($migration, $entity_type_id, $bundle);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function addBundleFieldProcesses(MigrationInterface $migration, $entity_type_id, $bundle) {
|
||||
$core = $this->getCoreVersion($migration);
|
||||
$fields = $this->getAllFields($core);
|
||||
$plugin_definition = $migration->getPluginDefinition();
|
||||
if (empty($fields[$entity_type_id][$bundle])) {
|
||||
return;
|
||||
}
|
||||
$bundle_fields = $fields[$entity_type_id][$bundle];
|
||||
foreach ($bundle_fields as $field_name => $field_info) {
|
||||
$plugin = $this->getFieldPlugin($field_info['type'], $migration);
|
||||
if ($plugin) {
|
||||
$method = isset($plugin_definition['field_plugin_method']) ? $plugin_definition['field_plugin_method'] : 'defineValueProcessPipeline';
|
||||
|
||||
// @todo Remove the following 3 lines of code prior to Drupal 9.0.0.
|
||||
// https://www.drupal.org/node/3032317
|
||||
if ($plugin instanceof MigrateCckFieldInterface) {
|
||||
$method = isset($plugin_definition['cck_plugin_method']) ? $plugin_definition['cck_plugin_method'] : 'processCckFieldValues';
|
||||
}
|
||||
|
||||
call_user_func_array([
|
||||
$plugin,
|
||||
$method,
|
||||
], [
|
||||
$migration,
|
||||
$field_name,
|
||||
$field_info,
|
||||
]);
|
||||
}
|
||||
else {
|
||||
// Default to a get process plugin if this is a value migration.
|
||||
if ((empty($plugin_definition['field_plugin_method']) || $plugin_definition['field_plugin_method'] === 'defineValueProcessPipeline') && (empty($plugin_definition['cck_plugin_method']) || $plugin_definition['cck_plugin_method'] === 'processCckFieldValues')) {
|
||||
$migration->setProcessOfProperty($field_name, $field_name);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the appropriate field plugin for a given field type.
|
||||
*
|
||||
* @param string $field_type
|
||||
* The field type.
|
||||
* @param \Drupal\migrate\Plugin\MigrationInterface $migration
|
||||
* The migration to retrieve the plugin for.
|
||||
*
|
||||
* @return \Drupal\migrate_drupal\Plugin\MigrateCckFieldInterface|\Drupal\migrate_drupal\Plugin\MigrateFieldInterface|bool
|
||||
* The appropriate field or cck plugin to process this field type.
|
||||
*
|
||||
* @throws \Drupal\Component\Plugin\Exception\PluginException
|
||||
* @throws \InvalidArgumentException
|
||||
*/
|
||||
protected function getFieldPlugin($field_type, MigrationInterface $migration) {
|
||||
$core = $this->getCoreVersion($migration);
|
||||
if (!isset($this->fieldPluginCache[$core][$field_type])) {
|
||||
try {
|
||||
$plugin_id = $this->fieldPluginManager->getPluginIdFromFieldType($field_type, ['core' => $core], $migration);
|
||||
$plugin = $this->fieldPluginManager->createInstance($plugin_id, ['core' => $core], $migration);
|
||||
}
|
||||
catch (PluginNotFoundException $ex) {
|
||||
// @todo Replace try/catch block with $plugin = FALSE for Drupal 9.
|
||||
// https://www.drupal.org/project/drupal/issues/3033733
|
||||
try {
|
||||
/** @var \Drupal\migrate_drupal\Plugin\MigrateCckFieldPluginManager $cck_plugin_manager */
|
||||
$cck_plugin_manager = $this->getCckPluginManager();
|
||||
$plugin_id = $cck_plugin_manager->getPluginIdFromFieldType($field_type, ['core' => $core], $migration);
|
||||
$plugin = $cck_plugin_manager->createInstance($plugin_id, ['core' => $core], $migration);
|
||||
}
|
||||
catch (PluginNotFoundException $ex) {
|
||||
$plugin = FALSE;
|
||||
}
|
||||
}
|
||||
$this->fieldPluginCache[$core][$field_type] = $plugin;
|
||||
}
|
||||
return $this->fieldPluginCache[$core][$field_type];
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets all field information related to this migration.
|
||||
*
|
||||
* @param string $core
|
||||
* The Drupal core version to get fields for.
|
||||
*
|
||||
* @return array
|
||||
* A multidimensional array of source data from the relevant field instance
|
||||
* migration, keyed first by entity type, then by bundle and finally by
|
||||
* field name.
|
||||
*/
|
||||
protected function getAllFields($core) {
|
||||
if (empty($this->discoveredFieldsCache[$core])) {
|
||||
$this->discoveredFieldsCache[$core] = [];
|
||||
$source_plugin = $this->getSourcePlugin($core);
|
||||
foreach ($source_plugin as $row) {
|
||||
/** @var \Drupal\migrate\Row $row */
|
||||
if ($core === FieldDiscoveryInterface::DRUPAL_7) {
|
||||
$entity_type_id = $row->get('entity_type');
|
||||
}
|
||||
else {
|
||||
$entity_type_id = 'node';
|
||||
}
|
||||
$bundle = $row->getSourceProperty($this->bundleKeys[$core]);
|
||||
$this->discoveredFieldsCache[$core][$entity_type_id][$bundle][$row->getSourceProperty('field_name')] = $row->getSource();
|
||||
}
|
||||
}
|
||||
return $this->discoveredFieldsCache[$core];
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets all field information for a particular entity type.
|
||||
*
|
||||
* @param string $core
|
||||
* The Drupal core version.
|
||||
* @param string $entity_type_id
|
||||
* The legacy entity type ID.
|
||||
*
|
||||
* @return array
|
||||
* A multidimensional array of source data from the relevant field instance
|
||||
* migration for the entity type, keyed first by bundle and then by field
|
||||
* name.
|
||||
*/
|
||||
protected function getEntityFields($core, $entity_type_id) {
|
||||
$fields = $this->getAllFields($core);
|
||||
if (!empty($fields[$entity_type_id])) {
|
||||
return $fields[$entity_type_id];
|
||||
}
|
||||
return [];
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets all field information for a particular entity type and bundle.
|
||||
*
|
||||
* @param string $core
|
||||
* The Drupal core version.
|
||||
* @param string $entity_type_id
|
||||
* The legacy entity type ID.
|
||||
* @param string $bundle
|
||||
* The legacy bundle (or content_type).
|
||||
*
|
||||
* @return array
|
||||
* An array of source data from the relevant field instance migration for
|
||||
* the bundle, keyed by field name.
|
||||
*/
|
||||
protected function getBundleFields($core, $entity_type_id, $bundle) {
|
||||
$fields = $this->getEntityFields($core, $entity_type_id);
|
||||
if (!empty($fields[$bundle])) {
|
||||
return $fields[$bundle];
|
||||
}
|
||||
return [];
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the deprecated CCK Plugin Manager service as a BC shim.
|
||||
*
|
||||
* We don't inject this service directly because it is deprecated, and we
|
||||
* don't want to instantiate the plugin manager unless we have to, to avoid
|
||||
* triggering deprecation errors.
|
||||
*
|
||||
* @return \Drupal\migrate_drupal\Plugin\MigrateCckFieldPluginManagerInterface
|
||||
* The CCK Plugin Manager.
|
||||
*/
|
||||
protected function getCckPluginManager() {
|
||||
if (!$this->cckPluginManager) {
|
||||
$this->cckPluginManager = \Drupal::service('plugin.manager.migrate.cckfield');
|
||||
}
|
||||
return $this->cckPluginManager;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the source plugin to use to gather field information.
|
||||
*
|
||||
* @param string $core
|
||||
* The Drupal core version.
|
||||
*
|
||||
* @return array|\Drupal\migrate\Plugin\MigrateSourceInterface
|
||||
* The source plugin, or an empty array if none can be found that meets
|
||||
* requirements.
|
||||
*/
|
||||
protected function getSourcePlugin($core) {
|
||||
$definition = $this->getFieldInstanceStubMigrationDefinition($core);
|
||||
$source_plugin = $this->migrationPluginManager
|
||||
->createStubMigration($definition)
|
||||
->getSourcePlugin();
|
||||
if ($source_plugin instanceof RequirementsInterface) {
|
||||
try {
|
||||
$source_plugin->checkRequirements();
|
||||
}
|
||||
catch (RequirementsException $e) {
|
||||
// If checkRequirements() failed, the source database did not support
|
||||
// fields (i.e., CCK is not installed in D6 or Field is not installed in
|
||||
// D7). Therefore, $fields will be empty and below we'll return an empty
|
||||
// array. The migration will proceed without adding fields.
|
||||
$this->logger->notice('Field discovery failed for Drupal core version @core. Did this site have the CCK or Field module installed? Error: @message', [
|
||||
'@core' => $core,
|
||||
'@message' => $e->getMessage(),
|
||||
]);
|
||||
return [];
|
||||
}
|
||||
}
|
||||
return $source_plugin;
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides the stub migration definition for a given Drupal core version.
|
||||
*
|
||||
* @param string $core
|
||||
* The Drupal core version.
|
||||
*
|
||||
* @return array
|
||||
* The stub migration definition.
|
||||
*/
|
||||
protected function getFieldInstanceStubMigrationDefinition($core) {
|
||||
return [
|
||||
'destination' => ['plugin' => 'null'],
|
||||
'idMap' => ['plugin' => 'null'],
|
||||
'source' => [
|
||||
'ignore_map' => TRUE,
|
||||
'plugin' => $this->sourcePluginIds[$core],
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds the core version of a Drupal migration.
|
||||
*
|
||||
* @param \Drupal\migrate\Plugin\MigrationInterface $migration
|
||||
* The migration.
|
||||
*
|
||||
* @return string|bool
|
||||
* A string representation of the Drupal version, or FALSE.
|
||||
*
|
||||
* @throws \InvalidArgumentException
|
||||
*/
|
||||
protected function getCoreVersion(MigrationInterface $migration) {
|
||||
$tags = $migration->getMigrationTags();
|
||||
if (in_array('Drupal 7', $tags, TRUE)) {
|
||||
return FieldDiscoveryInterface::DRUPAL_7;
|
||||
}
|
||||
elseif (in_array('Drupal 6', $tags, TRUE)) {
|
||||
return FieldDiscoveryInterface::DRUPAL_6;
|
||||
}
|
||||
throw new \InvalidArgumentException("Drupal Core version not found for this migration");
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\migrate_drupal;
|
||||
|
||||
use Drupal\migrate\Plugin\MigrationInterface;
|
||||
|
||||
/**
|
||||
* Provides field discovery for Drupal 6 & 7 migrations.
|
||||
*/
|
||||
interface FieldDiscoveryInterface {
|
||||
|
||||
const DRUPAL_6 = '6';
|
||||
|
||||
const DRUPAL_7 = '7';
|
||||
|
||||
/**
|
||||
* Adds the field processes to a migration.
|
||||
*
|
||||
* This method is used in field migrations to execute the migration process
|
||||
* alter method specified by the 'field_plugin_method' key of the migration
|
||||
* for all field plugins applicable to this Drupal to Drupal migration. This
|
||||
* method is used internally for field, field instance, widget, and formatter
|
||||
* migrations to allow field plugins to alter the process for these
|
||||
* migrations.
|
||||
*
|
||||
* @param \Drupal\migrate\Plugin\MigrationInterface $migration
|
||||
* The migration to add process plugins to.
|
||||
*
|
||||
* @throws \InvalidArgumentException
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
public function addAllFieldProcesses(MigrationInterface $migration);
|
||||
|
||||
/**
|
||||
* Adds the field processes for an entity to a migration.
|
||||
*
|
||||
* This method is used in field migrations to execute the migration process
|
||||
* alter method specified by the 'field_plugin_method' key of the migration
|
||||
* for all field plugins applicable to this Drupal to Drupal migration. This
|
||||
* method is used internally for field, field instance, widget, and formatter
|
||||
* migrations to allow field plugins to alter the process for these
|
||||
* migrations.
|
||||
*
|
||||
* @param \Drupal\migrate\Plugin\MigrationInterface $migration
|
||||
* The migration to add processes to.
|
||||
* @param string $entity_type_id
|
||||
* The legacy entity type to add processes for.
|
||||
*
|
||||
* @throws \InvalidArgumentException
|
||||
*/
|
||||
public function addEntityFieldProcesses(MigrationInterface $migration, $entity_type_id);
|
||||
|
||||
/**
|
||||
* Adds the field processes for a bundle to a migration.
|
||||
*
|
||||
* @param \Drupal\migrate\Plugin\MigrationInterface $migration
|
||||
* The migration to add processes to.
|
||||
* @param string $entity_type_id
|
||||
* The legacy entity type to add processes for.
|
||||
* @param string $bundle
|
||||
* The legacy bundle (or content_type) to add processes for.
|
||||
*
|
||||
* @throws \InvalidArgumentException
|
||||
*/
|
||||
public function addBundleFieldProcesses(MigrationInterface $migration, $entity_type_id, $bundle);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\migrate_drupal;
|
||||
|
||||
use Drupal\Core\DependencyInjection\ContainerBuilder;
|
||||
use Drupal\Core\DependencyInjection\ServiceProviderBase;
|
||||
use Symfony\Component\DependencyInjection\Reference;
|
||||
|
||||
/**
|
||||
* Alters container services.
|
||||
*/
|
||||
class MigrateDrupalServiceProvider extends ServiceProviderBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function alter(ContainerBuilder $container) {
|
||||
parent::alter($container);
|
||||
|
||||
$container->getDefinition('plugin.manager.migration')
|
||||
->setClass(MigrationPluginManager::class)
|
||||
->addArgument(new Reference('plugin.manager.migrate.source'))
|
||||
->addArgument(new Reference('config.factory'));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,292 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\migrate_drupal;
|
||||
|
||||
use Drupal\Core\Database\Connection;
|
||||
use Drupal\Core\Database\Database;
|
||||
use Drupal\Core\Database\DatabaseExceptionWrapper;
|
||||
use Drupal\migrate\Exception\RequirementsException;
|
||||
use Drupal\migrate\Plugin\RequirementsInterface;
|
||||
|
||||
/**
|
||||
* Configures the appropriate migrations for a given source Drupal database.
|
||||
*/
|
||||
trait MigrationConfigurationTrait {
|
||||
|
||||
/**
|
||||
* The config factory service.
|
||||
*
|
||||
* @var \Drupal\Core\Config\ConfigFactoryInterface
|
||||
*/
|
||||
protected $configFactory;
|
||||
|
||||
/**
|
||||
* The migration plugin manager service.
|
||||
*
|
||||
* @var \Drupal\migrate\Plugin\MigrationPluginManagerInterface
|
||||
*/
|
||||
protected $migrationPluginManager;
|
||||
|
||||
/**
|
||||
* The state service.
|
||||
*
|
||||
* @var \Drupal\Core\State\StateInterface
|
||||
*/
|
||||
protected $state;
|
||||
|
||||
/**
|
||||
* The follow-up migration tags.
|
||||
*
|
||||
* @var string[]
|
||||
*/
|
||||
protected $followUpMigrationTags;
|
||||
|
||||
/**
|
||||
* Gets the database connection for the source Drupal database.
|
||||
*
|
||||
* @param array $database
|
||||
* Database array representing the source Drupal database.
|
||||
*
|
||||
* @return \Drupal\Core\Database\Connection
|
||||
* The database connection for the source Drupal database.
|
||||
*/
|
||||
protected function getConnection(array $database) {
|
||||
// Set up the connection.
|
||||
Database::addConnectionInfo('upgrade', 'default', $database);
|
||||
$connection = Database::getConnection('default', 'upgrade');
|
||||
return $connection;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the system data from the system table of the source Drupal database.
|
||||
*
|
||||
* @param \Drupal\Core\Database\Connection $connection
|
||||
* Database connection to the source Drupal database.
|
||||
*
|
||||
* @return array
|
||||
* The system data from the system table of the source Drupal database.
|
||||
*/
|
||||
protected function getSystemData(Connection $connection) {
|
||||
$system_data = [];
|
||||
try {
|
||||
$results = $connection->select('system', 's', [
|
||||
'fetch' => \PDO::FETCH_ASSOC,
|
||||
])
|
||||
->fields('s')
|
||||
->execute();
|
||||
foreach ($results as $result) {
|
||||
$system_data[$result['type']][$result['name']] = $result;
|
||||
}
|
||||
}
|
||||
catch (DatabaseExceptionWrapper $e) {
|
||||
// The table might not exist for example in tests.
|
||||
}
|
||||
return $system_data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the necessary state entries for SqlBase::getDatabase() to work.
|
||||
*
|
||||
* The state entities created here have to exist before migration plugin
|
||||
* instances are created so that derivers such as
|
||||
* \Drupal\taxonomy\Plugin\migrate\D6TermNodeDeriver can access the source
|
||||
* database.
|
||||
*
|
||||
* @param array $database
|
||||
* The source database settings.
|
||||
* @param string $drupal_version
|
||||
* The Drupal version.
|
||||
*
|
||||
* @see \Drupal\migrate\Plugin\migrate\source\SqlBase::getDatabase()
|
||||
*/
|
||||
protected function createDatabaseStateSettings(array $database, $drupal_version) {
|
||||
$database_state['key'] = 'upgrade';
|
||||
$database_state['database'] = $database;
|
||||
$database_state_key = 'migrate_drupal_' . $drupal_version;
|
||||
$state = $this->getState();
|
||||
$state->set($database_state_key, $database_state);
|
||||
$state->set('migrate.fallback_state_key', $database_state_key);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the migrations for import.
|
||||
*
|
||||
* @param string $database_state_key
|
||||
* The state key.
|
||||
* @param int $drupal_version
|
||||
* The version of Drupal we're getting the migrations for.
|
||||
*
|
||||
* @return \Drupal\migrate\Plugin\MigrationInterface[]
|
||||
* The migrations for import.
|
||||
*/
|
||||
protected function getMigrations($database_state_key, $drupal_version) {
|
||||
$version_tag = 'Drupal ' . $drupal_version;
|
||||
/** @var \Drupal\migrate\Plugin\MigrationInterface[] $all_migrations */
|
||||
$all_migrations = $this->getMigrationPluginManager()->createInstancesByTag($version_tag);
|
||||
|
||||
// Unset the node migrations that should not run based on the type of node
|
||||
// migration. That is, if this is a complete node migration then unset the
|
||||
// classic node migrations and if this is a classic node migration then
|
||||
// unset the complete node migrations.
|
||||
$type = NodeMigrateType::getNodeMigrateType(\Drupal::database(), $drupal_version);
|
||||
switch ($type) {
|
||||
case NodeMigrateType::NODE_MIGRATE_TYPE_COMPLETE:
|
||||
$patterns = '/(d' . $drupal_version . '_node:)|(d' . $drupal_version . '_node_translation:)|(d' . $drupal_version . '_node_revision:)|(d7_node_entity_translation:)/';
|
||||
break;
|
||||
|
||||
case NodeMigrateType::NODE_MIGRATE_TYPE_CLASSIC:
|
||||
$patterns = '/(d' . $drupal_version . '_node_complete:)/';
|
||||
break;
|
||||
}
|
||||
foreach ($all_migrations as $key => $migrations) {
|
||||
if (preg_match($patterns, $key)) {
|
||||
unset($all_migrations[$key]);
|
||||
}
|
||||
}
|
||||
|
||||
$migrations = [];
|
||||
foreach ($all_migrations as $migration) {
|
||||
// Skip migrations tagged with any of the follow-up migration tags. They
|
||||
// will be derived and executed after the migrations on which they depend
|
||||
// have been successfully executed.
|
||||
// @see Drupal\migrate_drupal\Plugin\MigrationWithFollowUpInterface
|
||||
if (!empty(array_intersect($migration->getMigrationTags(), $this->getFollowUpMigrationTags()))) {
|
||||
continue;
|
||||
}
|
||||
|
||||
try {
|
||||
// @todo https://drupal.org/node/2681867 We should be able to validate
|
||||
// the entire migration at this point.
|
||||
$source_plugin = $migration->getSourcePlugin();
|
||||
if ($source_plugin instanceof RequirementsInterface) {
|
||||
$source_plugin->checkRequirements();
|
||||
}
|
||||
$destination_plugin = $migration->getDestinationPlugin();
|
||||
if ($destination_plugin instanceof RequirementsInterface) {
|
||||
$destination_plugin->checkRequirements();
|
||||
}
|
||||
$migrations[] = $migration;
|
||||
}
|
||||
catch (RequirementsException $e) {
|
||||
// Migrations which are not applicable given the source and destination
|
||||
// site configurations (e.g., what modules are enabled) will be silently
|
||||
// ignored.
|
||||
}
|
||||
}
|
||||
|
||||
return $migrations;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the follow-up migration tags.
|
||||
*
|
||||
* @return string[]
|
||||
*/
|
||||
protected function getFollowUpMigrationTags() {
|
||||
if ($this->followUpMigrationTags === NULL) {
|
||||
$this->followUpMigrationTags = $this->getConfigFactory()
|
||||
->get('migrate_drupal.settings')
|
||||
->get('follow_up_migration_tags') ?: [];
|
||||
}
|
||||
return $this->followUpMigrationTags;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines what version of Drupal the source database contains.
|
||||
*
|
||||
* @param \Drupal\Core\Database\Connection $connection
|
||||
* The database connection object.
|
||||
*
|
||||
* @return string|false
|
||||
* A string representing the major branch of Drupal core (e.g. '6' for
|
||||
* Drupal 6.x), or FALSE if no valid version is matched.
|
||||
*/
|
||||
public static function getLegacyDrupalVersion(Connection $connection) {
|
||||
// Don't assume because a table of that name exists, that it has the columns
|
||||
// we're querying. Catch exceptions and report that the source database is
|
||||
// not Drupal.
|
||||
// Drupal 5/6/7 can be detected by the schema_version in the system table.
|
||||
if ($connection->schema()->tableExists('system')) {
|
||||
try {
|
||||
$version_string = $connection
|
||||
->query('SELECT schema_version FROM {system} WHERE name = :module', [':module' => 'system'])
|
||||
->fetchField();
|
||||
if ($version_string && $version_string[0] == '1') {
|
||||
if ((int) $version_string >= 1000) {
|
||||
$version_string = '5';
|
||||
}
|
||||
else {
|
||||
$version_string = FALSE;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (\PDOException $e) {
|
||||
$version_string = FALSE;
|
||||
}
|
||||
}
|
||||
// For Drupal 8 (and we're predicting beyond) the schema version is in the
|
||||
// key_value store.
|
||||
elseif ($connection->schema()->tableExists('key_value')) {
|
||||
try {
|
||||
$result = $connection
|
||||
->query("SELECT value FROM {key_value} WHERE collection = :system_schema and name = :module", [
|
||||
':system_schema' => 'system.schema',
|
||||
':module' => 'system',
|
||||
])
|
||||
->fetchField();
|
||||
$version_string = unserialize($result);
|
||||
}
|
||||
catch (DatabaseExceptionWrapper $e) {
|
||||
$version_string = FALSE;
|
||||
}
|
||||
}
|
||||
else {
|
||||
$version_string = FALSE;
|
||||
}
|
||||
|
||||
return $version_string ? substr($version_string, 0, 1) : FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the config factory service.
|
||||
*
|
||||
* @return \Drupal\Core\Config\ConfigFactoryInterface
|
||||
* The config factory service.
|
||||
*/
|
||||
protected function getConfigFactory() {
|
||||
if (!$this->configFactory) {
|
||||
$this->configFactory = \Drupal::service('config.factory');
|
||||
}
|
||||
|
||||
return $this->configFactory;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the migration plugin manager service.
|
||||
*
|
||||
* @return \Drupal\migrate\Plugin\MigrationPluginManagerInterface
|
||||
* The migration plugin manager service.
|
||||
*/
|
||||
protected function getMigrationPluginManager() {
|
||||
if (!$this->migrationPluginManager) {
|
||||
$this->migrationPluginManager = \Drupal::service('plugin.manager.migration');
|
||||
}
|
||||
|
||||
return $this->migrationPluginManager;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the state service.
|
||||
*
|
||||
* @return \Drupal\Core\State\StateInterface
|
||||
* The state service.
|
||||
*/
|
||||
protected function getState() {
|
||||
if (!$this->state) {
|
||||
$this->state = \Drupal::service('state');
|
||||
}
|
||||
|
||||
return $this->state;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\migrate_drupal;
|
||||
|
||||
/**
|
||||
* @deprecated in drupal:8.1.0 and is removed from drupal:9.0.0. Use
|
||||
* \Drupal\migrate_drupal\MigrationConfigurationTrait instead.
|
||||
*
|
||||
* @see https://www.drupal.org/node/2873794
|
||||
*/
|
||||
trait MigrationCreationTrait {
|
||||
use MigrationConfigurationTrait;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,109 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\migrate_drupal;
|
||||
|
||||
use Drupal\Core\Cache\CacheBackendInterface;
|
||||
use Drupal\Core\Config\ConfigFactoryInterface;
|
||||
use Drupal\Core\Extension\ModuleHandlerInterface;
|
||||
use Drupal\Core\Language\LanguageManagerInterface;
|
||||
use Drupal\migrate\Plugin\Exception\BadPluginDefinitionException;
|
||||
use Drupal\migrate\Plugin\MigrateSourcePluginManager;
|
||||
use Drupal\migrate\Plugin\MigrationPluginManager as BaseMigrationPluginManager;
|
||||
|
||||
/**
|
||||
* Manages migration plugins.
|
||||
*
|
||||
* Analyzes migration definitions to ensure that the source plugin of any
|
||||
* migration tagged with particular tags ('Drupal 6' or 'Drupal 7' by default)
|
||||
* defines a source_module property in its plugin annotation. This is done in
|
||||
* order to support the Migrate Drupal UI, which needs to know which modules
|
||||
* "own" the data being migrated into Drupal 8, on both the source and
|
||||
* destination sides.
|
||||
*
|
||||
* @todo Enforce the destination_module property too, in
|
||||
* https://www.drupal.org/project/drupal/issues/2923810.
|
||||
*/
|
||||
class MigrationPluginManager extends BaseMigrationPluginManager {
|
||||
|
||||
/**
|
||||
* The Migrate source plugin manager service.
|
||||
*
|
||||
* @var \Drupal\migrate\Plugin\MigrateSourcePluginManager
|
||||
*/
|
||||
protected $sourceManager;
|
||||
|
||||
/**
|
||||
* The config factory service.
|
||||
*
|
||||
* @var \Drupal\Core\Config\ConfigFactoryInterface
|
||||
*/
|
||||
protected $configFactory;
|
||||
|
||||
/**
|
||||
* The migration tags which will trigger source_module enforcement.
|
||||
*
|
||||
* @var string[]
|
||||
*/
|
||||
protected $enforcedSourceModuleTags;
|
||||
|
||||
/**
|
||||
* MigrationPluginManager constructor.
|
||||
*
|
||||
* @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler
|
||||
* The module handler service.
|
||||
* @param \Drupal\Core\Cache\CacheBackendInterface $cache_backend
|
||||
* The cache backend.
|
||||
* @param \Drupal\Core\Language\LanguageManagerInterface $language_manager
|
||||
* The language manager service.
|
||||
* @param \Drupal\migrate\Plugin\MigrateSourcePluginManager $source_manager
|
||||
* The Migrate source plugin manager service.
|
||||
* @param \Drupal\Core\Config\ConfigFactoryInterface $config_factory
|
||||
* The config factory service.
|
||||
*/
|
||||
public function __construct(ModuleHandlerInterface $module_handler, CacheBackendInterface $cache_backend, LanguageManagerInterface $language_manager, MigrateSourcePluginManager $source_manager, ConfigFactoryInterface $config_factory) {
|
||||
parent::__construct($module_handler, $cache_backend, $language_manager);
|
||||
$this->sourceManager = $source_manager;
|
||||
$this->configFactory = $config_factory;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the migration tags that trigger source_module enforcement.
|
||||
*
|
||||
* @return string[]
|
||||
*/
|
||||
protected function getEnforcedSourceModuleTags() {
|
||||
if ($this->enforcedSourceModuleTags === NULL) {
|
||||
$this->enforcedSourceModuleTags = $this->configFactory
|
||||
->get('migrate_drupal.settings')
|
||||
->get('enforce_source_module_tags') ?: [];
|
||||
}
|
||||
return $this->enforcedSourceModuleTags;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function processDefinition(&$definition, $plugin_id) {
|
||||
parent::processDefinition($definition, $plugin_id);
|
||||
|
||||
// If the migration has no tags, we don't need to enforce the source_module
|
||||
// annotation property.
|
||||
if (empty($definition['migration_tags'])) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Check if the migration has any of the tags that trigger source_module
|
||||
// enforcement.
|
||||
$applied_tags = array_intersect($this->getEnforcedSourceModuleTags(), $definition['migration_tags']);
|
||||
if ($applied_tags) {
|
||||
// Throw an exception if the source plugin definition does not define a
|
||||
// source_module.
|
||||
$source_id = $definition['source']['plugin'];
|
||||
$source_definition = $this->sourceManager->getDefinition($source_id);
|
||||
if (empty($source_definition['source_module'])) {
|
||||
throw new BadPluginDefinitionException($source_id, 'source_module');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,494 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\migrate_drupal;
|
||||
|
||||
use Drupal\Core\Discovery\YamlDiscovery;
|
||||
use Drupal\Core\Extension\ModuleHandlerInterface;
|
||||
use Drupal\Core\Messenger\MessengerInterface;
|
||||
use Drupal\Core\Messenger\MessengerTrait;
|
||||
use Drupal\Core\StringTranslation\StringTranslationTrait;
|
||||
use Drupal\Core\StringTranslation\TranslationInterface;
|
||||
use Drupal\migrate_drupal\Plugin\MigrateFieldPluginManagerInterface;
|
||||
|
||||
/**
|
||||
* Determines the migrate state for all modules enabled on the source.
|
||||
*
|
||||
* Retrieves migrate info from *.migrate_drupal.yml files.
|
||||
*
|
||||
* Knowing which modules will be upgraded and those that will not is needed by
|
||||
* anyone upgrading a legacy Drupal version. This service provides that
|
||||
* information by analyzing the existing migrations and data in
|
||||
* migrate_drupal.yml files. Modules that are enabled or disabled in the source
|
||||
* are included in the analysis modules that are uninstalled are ignored.
|
||||
*
|
||||
* Deciding the upgrade state of a source module is a complicated task. A
|
||||
* destination module is not limited in any way to the source modules or the
|
||||
* current major version destination modules it is providing migrations for. We
|
||||
* see this in core where the Drupal 6 Menu module is upgraded by having
|
||||
* migrations in three Drupal 8 modules; menu_link_content, menu_ui and system.
|
||||
* If migrations for any of those three modules are not complete or if any of
|
||||
* them are not installed on the destination site then the Drupal 6 Menu module
|
||||
* cannot be listed as upgraded. If any one of the conditions are not met then
|
||||
* it should be listed as will not be upgraded.
|
||||
*
|
||||
* Another challenge is to ensure that legacy source modules that do not need an
|
||||
* upgrade path are handled correctly. These will not have migrations but should
|
||||
* be listed as will be upgraded, which even though there are not migrations
|
||||
* under the hood, it lets a site admin know that upgrading with this module
|
||||
* enabled is safe.
|
||||
*
|
||||
* There is not enough information in the existing system to determine the
|
||||
* correct state of the upgrade path for these, and other scenarios.
|
||||
*
|
||||
* The solution is for every destination module that is the successor to a
|
||||
* module built for a legacy Drupal version to declare the state of the upgrade
|
||||
* path(s) for the module. A module's upgrade path from a previous version may
|
||||
* consist of one or more migrations sets. Each migration set definition
|
||||
* consists of a source module supporting a legacy Drupal version, and one or
|
||||
* more current destination modules. This allows a module to indicate that a
|
||||
* provided migration set requires additional modules to be enabled in the
|
||||
* destination.
|
||||
*
|
||||
* A migration set can be marked 'finished', which indicates that all
|
||||
* migrations that are going to be provided by this destination module for this
|
||||
* migration set have been written and are complete. A migration set may also
|
||||
* be marked 'not_finished' which indicates that the module either has not
|
||||
* provided any migrations for the set, or needs to provide additional
|
||||
* migrations to complete the set. Note that other modules may still provide
|
||||
* additional finished or not_finished migrations for the same migration set.
|
||||
*
|
||||
* Modules inform the upgrade process of the migration sets by adding them to
|
||||
* their <module_name>.migrate_drupal.yml file.
|
||||
*
|
||||
* The <module_name>.migrate_drupal.yml file uses the following structure:
|
||||
*
|
||||
* # (optional) List of the source_module/destination_module(s) for the
|
||||
* # migration sets that this module provides and are complete.
|
||||
* finished:
|
||||
* # One or more Drupal legacy version number mappings (i.e. 6 and/or 7).
|
||||
* 6:
|
||||
* # A mapping of legacy module machine names to either an array of modules
|
||||
* # or a single destination module machine name to define this migration
|
||||
* # set.
|
||||
* <source_module_1>: <destination_module_1>
|
||||
* <source_module_2>:
|
||||
* - <destination_module_1>
|
||||
* - <destination_module_2>
|
||||
* 7:
|
||||
* <source_module_1>: <destination_module_1>
|
||||
* <source_module_2>:
|
||||
* - <destination_module_1>
|
||||
* - <destination_module_2>
|
||||
* # (optional) List of the migration sets that this module provides, or will be
|
||||
* # providing, that are incomplete or do not yet exist.
|
||||
* not_finished:
|
||||
* 6:
|
||||
* <source_module_1>: <destination_module_1>
|
||||
* <source_module_2>:
|
||||
* - <destination_module_1>
|
||||
* - <destination_module_2>
|
||||
*
|
||||
* Examples:
|
||||
*
|
||||
* @code
|
||||
* finished:
|
||||
* 6:
|
||||
* node: node
|
||||
* 7:
|
||||
* node: node
|
||||
* entity_translation: node
|
||||
* not_finished:
|
||||
* 7:
|
||||
* commerce_product: commerce_product
|
||||
* other_module:
|
||||
* - other_module
|
||||
* - further_module
|
||||
* @endcode
|
||||
*
|
||||
* In this example the module has completed the upgrade path for data from the
|
||||
* Drupal 6 and Drupal 7 Node modules to the Drupal 8 Node module and for data
|
||||
* from the Drupal 7 Entity Translation module to the Drupal 8 Node module.
|
||||
*
|
||||
* @code
|
||||
* finished:
|
||||
* 6:
|
||||
* pirate: pirate
|
||||
* 7:
|
||||
* pirate: pirate
|
||||
* @endcode
|
||||
*
|
||||
* The Pirate module does not require an upgrade path. By declaring the upgrade
|
||||
* finished the Pirate module will be included in the finished list. That is,
|
||||
* as long as no other module has an entry "pirate: <any module name>' in its
|
||||
* not_finished section.
|
||||
*/
|
||||
class MigrationState {
|
||||
|
||||
use MessengerTrait;
|
||||
use StringTranslationTrait;
|
||||
|
||||
/**
|
||||
* Source module upgrade state when all its migrations are complete.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
const FINISHED = 'finished';
|
||||
|
||||
/**
|
||||
* Source module upgrade state when all its migrations are not complete.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
const NOT_FINISHED = 'not_finished';
|
||||
|
||||
/**
|
||||
* The field plugin manager service.
|
||||
*
|
||||
* @var \Drupal\Core\Extension\ModuleHandler
|
||||
*/
|
||||
protected $moduleHandler;
|
||||
|
||||
/**
|
||||
* The field plugin manager service.
|
||||
*
|
||||
* @var \Drupal\migrate_drupal\Plugin\MigrateFieldPluginManagerInterface
|
||||
*/
|
||||
protected $fieldPluginManager;
|
||||
|
||||
/**
|
||||
* Source modules that will not be migrated determined using legacy method.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $unmigratedSourceModules = [];
|
||||
|
||||
/**
|
||||
* Source modules that will be migrated determined using legacy method, keyed
|
||||
* by version.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $migratedSourceModules = [];
|
||||
|
||||
/**
|
||||
* An array of migration states declared for each source migration.
|
||||
*
|
||||
* States are keyed by version. Each value is an array keyed by name of the
|
||||
* source module and the value is an array of all the states declared for this
|
||||
* source module.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $stateBySource;
|
||||
|
||||
/**
|
||||
* An array of destinations declared for each source migration.
|
||||
*
|
||||
* Destinations are keyed by version. Each value is an array keyed by the name
|
||||
* of the source module and the value is an array of the destination modules.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $declaredBySource;
|
||||
|
||||
/**
|
||||
* An array of migration source and destinations derived from migrations.
|
||||
*
|
||||
* The key is the source version and the value is an array where the key is
|
||||
* the source module and the value is an array of destinations derived from
|
||||
* migration plugins.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $discoveredBySource;
|
||||
|
||||
/**
|
||||
* An array of migration source and destinations.
|
||||
*
|
||||
* Values are derived from migration plugins and declared states. The key is
|
||||
* the source version and the value is an array where the key is the source
|
||||
* module and the value is an array of declared or derived destinations.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $destinations = [];
|
||||
|
||||
/**
|
||||
* Array of enabled modules.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $enabledModules = [];
|
||||
|
||||
/**
|
||||
* Construct a new MigrationState object.
|
||||
*
|
||||
* @param \Drupal\migrate_drupal\Plugin\MigrateFieldPluginManagerInterface $fieldPluginManager
|
||||
* Field plugin manager.
|
||||
* @param \Drupal\Core\Extension\ModuleHandlerInterface $moduleHandler
|
||||
* Module handler.
|
||||
* @param \Drupal\Core\Messenger\MessengerInterface $messenger
|
||||
* Messenger sevice.
|
||||
* @param \Drupal\Core\StringTranslation\TranslationInterface $stringTranslation
|
||||
* String translation service.
|
||||
*/
|
||||
public function __construct(MigrateFieldPluginManagerInterface $fieldPluginManager, ModuleHandlerInterface $moduleHandler, MessengerInterface $messenger, TranslationInterface $stringTranslation) {
|
||||
$this->fieldPluginManager = $fieldPluginManager;
|
||||
$this->moduleHandler = $moduleHandler;
|
||||
$this->enabledModules = array_keys($this->moduleHandler->getModuleList());
|
||||
$this->enabledModules[] = 'core';
|
||||
$this->messenger = $messenger;
|
||||
$this->stringTranslation = $stringTranslation;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the upgrade states for all enabled source modules.
|
||||
*
|
||||
* @param string $version
|
||||
* The legacy drupal version.
|
||||
* @param array $source_system_data
|
||||
* The data from the source site system table.
|
||||
* @param array $migrations
|
||||
* An array of migrations.
|
||||
*
|
||||
* @return array
|
||||
* An associative array of data with keys of state, source modules and a
|
||||
* value which is a comma separated list of destination modules.
|
||||
*/
|
||||
public function getUpgradeStates($version, array $source_system_data, array $migrations) {
|
||||
return $this->buildUpgradeState($version, $source_system_data, $migrations);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets migration state information from *.migrate_drupal.yml.
|
||||
*
|
||||
* @return array
|
||||
* An association array keyed by module of the finished and not_finished
|
||||
* migrations for each module.
|
||||
* */
|
||||
protected function getMigrationStates() {
|
||||
// Always instantiate a new YamlDiscovery object so that we always search on
|
||||
// the up-to-date list of modules.
|
||||
$discovery = new YamlDiscovery('migrate_drupal', array_map(function (&$value) {
|
||||
return $value . '/migrations/state';
|
||||
}, $this->moduleHandler->getModuleDirectories()));
|
||||
return $discovery->findAll();
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines migration state for each source module enabled on the source.
|
||||
*
|
||||
* If there are no migrations for a module and no declared state the state is
|
||||
* set to NOT_FINISHED. When a module does not need any migrations, such as
|
||||
* Overlay, a state of finished is declared in system.migrate_drupal.yml.
|
||||
*
|
||||
* If there are migrations for a module the following happens. If the
|
||||
* destination module is 'core' the state is set to FINISHED. If there are
|
||||
* any occurrences of 'not_finished' in the *.migrate_drupal.yml information
|
||||
* for this source module then the state is set to NOT_FINISHED. And finally,
|
||||
* if there is an occurrence of 'finished' the state is set to FINISHED.
|
||||
*
|
||||
* @param string $version
|
||||
* The legacy drupal version.
|
||||
* @param array $source_system_data
|
||||
* The data from the source site system table.
|
||||
* @param array $migrations
|
||||
* An array of migrations.
|
||||
*
|
||||
* @return array
|
||||
* An associative array of data with keys of state, source modules and a
|
||||
* value which is a comma separated list of destination modules.
|
||||
* Example.
|
||||
*
|
||||
* @code
|
||||
* [
|
||||
* 'finished' => [
|
||||
* 'menu' => [
|
||||
* 'menu_link_content','menu_ui','system'
|
||||
* ]
|
||||
* ],
|
||||
* ]
|
||||
* @endcode
|
||||
*/
|
||||
protected function buildUpgradeState($version, array $source_system_data, array $migrations) {
|
||||
// Remove core profiles from the system data.
|
||||
unset($source_system_data['module']['standard'], $source_system_data['module']['minimal']);
|
||||
$this->buildDiscoveredDestinationsBySource($version, $migrations, $source_system_data);
|
||||
$this->buildDeclaredStateBySource($version);
|
||||
|
||||
$upgrade_state = [];
|
||||
// Loop through every source module that is enabled on the source site.
|
||||
foreach ($source_system_data['module'] as $module) {
|
||||
// The source plugins check requirements requires that all
|
||||
// source_modules are enabled so do the same here.
|
||||
if ($module['status']) {
|
||||
$source_module = $module['name'];
|
||||
// If there is not a declared state for this source module then use the
|
||||
// legacy method for determining the migration state.
|
||||
if (!isset($this->stateBySource[$version][$source_module])) {
|
||||
// No migrations found for this source module.
|
||||
if (!empty($this->unmigratedSourceModules[$version]) && array_key_exists($source_module, $this->unmigratedSourceModules[$version])) {
|
||||
$upgrade_state[static::NOT_FINISHED][$source_module] = '';
|
||||
continue;
|
||||
}
|
||||
if (!empty($this->migratedSourceModules[$version]) && array_key_exists($source_module, $this->migratedSourceModules[$version])) {
|
||||
@trigger_error(sprintf("Using migration plugin definitions to determine the migration state of the module '%s' is deprecated in Drupal 8.7. Add the module to a migrate_drupal.yml file. See https://www.drupal.org/node/2929443", $source_module), E_USER_DEPRECATED);
|
||||
if (array_diff(array_keys($this->migratedSourceModules[$version][$source_module]), $this->enabledModules)) {
|
||||
$upgrade_state[static::NOT_FINISHED][$source_module] = implode(', ', array_keys($this->migratedSourceModules[$version][$source_module]));
|
||||
continue;
|
||||
}
|
||||
$upgrade_state[static::FINISHED][$source_module] = implode(', ', array_keys($this->migratedSourceModules[$version][$source_module]));
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
$upgrade_state[$this->getSourceState($version, $source_module)][$source_module] = implode(', ', $this->getDestinationsForSource($version, $source_module));
|
||||
}
|
||||
|
||||
}
|
||||
foreach ($upgrade_state as $key => $value) {
|
||||
ksort($upgrade_state[$key]);
|
||||
}
|
||||
return $upgrade_state;
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds migration source and destination module information.
|
||||
*
|
||||
* @param string $version
|
||||
* The legacy Drupal version.
|
||||
* @param array $migrations
|
||||
* The discovered migrations.
|
||||
* @param array $source_system_data
|
||||
* The data from the source site system table.
|
||||
*/
|
||||
protected function buildDiscoveredDestinationsBySource($version, array $migrations, array $source_system_data) {
|
||||
$discovered_upgrade_paths = [];
|
||||
$table_data = [];
|
||||
foreach ($migrations as $migration) {
|
||||
$migration_id = $migration->getPluginId();
|
||||
$source_module = $migration->getSourcePlugin()->getSourceModule();
|
||||
if (!$source_module) {
|
||||
$this->messenger()
|
||||
->addError($this->t('Source module not found for @migration_id.', ['@migration_id' => $migration_id]));
|
||||
}
|
||||
$destination_module = $migration->getDestinationPlugin()
|
||||
->getDestinationModule();
|
||||
if (!$destination_module) {
|
||||
$this->messenger()
|
||||
->addError($this->t('Destination module not found for @migration_id.', ['@migration_id' => $migration_id]));
|
||||
}
|
||||
|
||||
if ($source_module && $destination_module) {
|
||||
$discovered_upgrade_paths[$source_module][] = $destination_module;
|
||||
$table_data[$source_module][$destination_module][$migration_id] = $migration->label();
|
||||
}
|
||||
}
|
||||
|
||||
// Add entries for the field plugins to discovered_upgrade_paths.
|
||||
$definitions = $this->fieldPluginManager->getDefinitions();
|
||||
foreach ($definitions as $definition) {
|
||||
// This is not strict so that we find field plugins with an annotation
|
||||
// where the Drupal core version is an integer and when it is a string.
|
||||
if (in_array($version, $definition['core'])) {
|
||||
$source_module = $definition['source_module'];
|
||||
$destination_module = $definition['destination_module'];
|
||||
$discovered_upgrade_paths[$source_module][] = $destination_module;
|
||||
$table_data[$source_module][$destination_module][$definition['id']] = $definition['id'];
|
||||
}
|
||||
}
|
||||
ksort($table_data);
|
||||
foreach ($table_data as $source_module => $destination_module_info) {
|
||||
ksort($table_data[$source_module]);
|
||||
}
|
||||
$tmp = array_diff_key($source_system_data['module'], $table_data);
|
||||
foreach ($tmp as $source_module => $module_data) {
|
||||
if ($module_data['status']) {
|
||||
$this->unmigratedSourceModules[$version][$source_module] = $module_data;
|
||||
}
|
||||
}
|
||||
$this->migratedSourceModules[$version] = $table_data;
|
||||
$this->discoveredBySource[$version] = array_map('array_unique', $discovered_upgrade_paths);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets migration data from *.migrate_drupal.yml sorted by source module.
|
||||
*
|
||||
* @param string $version
|
||||
* The legacy Drupal version.
|
||||
*/
|
||||
protected function buildDeclaredStateBySource($version) {
|
||||
$migration_states = $this->getMigrationStates();
|
||||
|
||||
$state_by_source = [];
|
||||
$dest_by_source = [];
|
||||
$states = [static::FINISHED, static::NOT_FINISHED];
|
||||
foreach ($migration_states as $module => $info) {
|
||||
foreach ($states as $state) {
|
||||
if (isset($info[$state][$version])) {
|
||||
foreach ($info[$state][$version] as $source => $destination) {
|
||||
// Add the state.
|
||||
$state_by_source[$source][] = $state;
|
||||
// Add the destination modules.
|
||||
$dest_by_source += [$source => []];
|
||||
$dest_by_source[$source] = array_merge($dest_by_source[$source], (array) $destination);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
$this->stateBySource[$version] = array_map('array_unique', $state_by_source);
|
||||
$this->declaredBySource[$version] = array_map('array_unique', $dest_by_source);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests if a destination exists for the given source module.
|
||||
*
|
||||
* @param string $version
|
||||
* Source version of Drupal.
|
||||
* @param string $source_module
|
||||
* Source module.
|
||||
*
|
||||
* @return string
|
||||
* Migration state, either 'finished' or 'not_finished'.
|
||||
*/
|
||||
protected function getSourceState($version, $source_module) {
|
||||
// The state is finished only when no declarations of 'not_finished'
|
||||
// were found and each destination module is enabled.
|
||||
if (!$destinations = $this->getDestinationsForSource($version, $source_module)) {
|
||||
// No discovered or declared state.
|
||||
return MigrationState::NOT_FINISHED;
|
||||
}
|
||||
if (in_array(MigrationState::NOT_FINISHED, $this->stateBySource[$version][$source_module], TRUE) || !in_array(MigrationState::FINISHED, $this->stateBySource[$version][$source_module], TRUE)) {
|
||||
return MigrationState::NOT_FINISHED;
|
||||
}
|
||||
if (array_diff($destinations, $this->enabledModules)) {
|
||||
return MigrationState::NOT_FINISHED;
|
||||
}
|
||||
return MigrationState::FINISHED;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get net destinations for source module.
|
||||
*
|
||||
* @param string $version
|
||||
* Source version.
|
||||
* @param string $source_module
|
||||
* Source module.
|
||||
*
|
||||
* @return array
|
||||
* Destination modules either declared by {modulename}.migrate_drupal.yml
|
||||
* files or discovered from migration plugins.
|
||||
*/
|
||||
protected function getDestinationsForSource($version, $source_module) {
|
||||
if (!isset($this->destinations[$version][$source_module])) {
|
||||
$this->discoveredBySource[$version] += [$source_module => []];
|
||||
$this->declaredBySource[$version] += [$source_module => []];
|
||||
$destination = array_unique(array_merge($this->discoveredBySource[$version][$source_module], $this->declaredBySource[$version][$source_module]));
|
||||
sort($destination);
|
||||
$this->destinations[$version][$source_module] = $destination;
|
||||
}
|
||||
return $this->destinations[$version][$source_module];
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,88 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\migrate_drupal;
|
||||
|
||||
use Drupal\Core\Database\Connection;
|
||||
use Drupal\Core\Site\Settings;
|
||||
|
||||
/**
|
||||
* Provides a class to determine the type of migration.
|
||||
*/
|
||||
final class NodeMigrateType {
|
||||
|
||||
use MigrationConfigurationTrait;
|
||||
|
||||
/**
|
||||
* Only the complete node migration map tables are in use.
|
||||
*/
|
||||
const NODE_MIGRATE_TYPE_COMPLETE = 'COMPLETE';
|
||||
|
||||
/**
|
||||
* Only the classic node migration map tables are in use.
|
||||
*/
|
||||
const NODE_MIGRATE_TYPE_CLASSIC = 'CLASSIC';
|
||||
|
||||
/**
|
||||
* Determines the type of node migration to be used.
|
||||
*
|
||||
* The node complete migration is the default. It is not used when there
|
||||
* are existing tables for dN_node.
|
||||
*
|
||||
* @param \Drupal\Core\Database\Connection $connection
|
||||
* The connection to the target database.
|
||||
* @param string|false $version
|
||||
* The Drupal version of the source database, FALSE if it cannot be
|
||||
* determined.
|
||||
*
|
||||
* @return string
|
||||
* The migrate type.
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
public static function getNodeMigrateType(Connection $connection, $version) {
|
||||
$migrate_node_migrate_type_classic = Settings::get('migrate_node_migrate_type_classic', FALSE);
|
||||
if ($migrate_node_migrate_type_classic) {
|
||||
return static::NODE_MIGRATE_TYPE_CLASSIC;
|
||||
}
|
||||
|
||||
$migrate_type = static::NODE_MIGRATE_TYPE_COMPLETE;
|
||||
if ($version) {
|
||||
// Create the variable name, 'node_has_rows' or 'node_complete_exists' and
|
||||
// set it the default value, FALSE.
|
||||
$node_has_rows = FALSE;
|
||||
$node_complete_has_rows = FALSE;
|
||||
|
||||
// Find out what migrate map tables have rows for the node migrations.
|
||||
// It is either the classic, 'dN_node', or the complete,
|
||||
// 'dN_node_complete', or both. This is used to determine which migrations
|
||||
// are run and if migrations using the node migrations in a
|
||||
// migration_lookup are altered.
|
||||
$bases = ['node', 'node_complete'];
|
||||
$tables = $connection->schema()
|
||||
->findTables('migrate_map_d' . $version . '_node%');
|
||||
foreach ($bases as $base) {
|
||||
$has_rows = $base . '_has_rows';
|
||||
$base_tables = preg_grep('/^migrate_map_d' . $version . '_' . $base . '_{2}.*$/', $tables);
|
||||
// Set the has_rows True when a map table has rows with a positive
|
||||
// count for the matched migration.
|
||||
foreach ($base_tables as $base_table) {
|
||||
if ($connection->schema()->tableExists($base_table)) {
|
||||
$count = $connection->select($base_table)->countQuery()
|
||||
->execute()->fetchField();
|
||||
if ($count > 0) {
|
||||
$$has_rows = TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Set the node migration type to use.
|
||||
if ($node_has_rows && !$node_complete_has_rows) {
|
||||
$migrate_type = static::NODE_MIGRATE_TYPE_CLASSIC;
|
||||
}
|
||||
}
|
||||
return $migrate_type;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\migrate_drupal\Plugin;
|
||||
|
||||
@trigger_error('MigrateCckFieldInterface is deprecated in Drupal 8.3.x and will be removed before Drupal 9.0.x. Use \Drupal\migrate_drupal\Annotation\MigrateField instead.', E_USER_DEPRECATED);
|
||||
|
||||
use Drupal\migrate\Plugin\MigrationInterface;
|
||||
|
||||
/**
|
||||
* Provides an interface for all CCK field type plugins.
|
||||
*
|
||||
* @deprecated in drupal:8.3.0 and is removed from drupal:9.0.0. Use
|
||||
* \Drupal\migrate_drupal\Annotation\MigrateField instead.
|
||||
*
|
||||
* @see https://www.drupal.org/node/2751897
|
||||
*/
|
||||
interface MigrateCckFieldInterface extends MigrateFieldInterface {
|
||||
|
||||
/**
|
||||
* Apply any custom processing to the cck bundle migrations.
|
||||
*
|
||||
* @param \Drupal\migrate\Plugin\MigrationInterface $migration
|
||||
* The migration entity.
|
||||
* @param string $field_name
|
||||
* The field name we're processing the value for.
|
||||
* @param array $data
|
||||
* The array of field data from CckFieldValues::fieldData().
|
||||
*/
|
||||
public function processCckFieldValues(MigrationInterface $migration, $field_name, $data);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\migrate_drupal\Plugin;
|
||||
|
||||
@trigger_error('MigrateCckFieldPluginManager is deprecated in Drupal 8.3.x and will be removed before Drupal 9.0.x. Use \Drupal\migrate_drupal\Annotation\MigrateFieldPluginManager instead.', E_USER_DEPRECATED);
|
||||
|
||||
/**
|
||||
* Deprecated: Plugin manager for migrate field plugins.
|
||||
*
|
||||
* @deprecated in drupal:8.3.0 and is removed from drupal:9.0.0. Use
|
||||
* \Drupal\migrate_drupal\Plugin\MigrateFieldPluginManager instead.
|
||||
*
|
||||
* @see https://www.drupal.org/node/2751897
|
||||
*
|
||||
* @ingroup migration
|
||||
*/
|
||||
class MigrateCckFieldPluginManager extends MigrateFieldPluginManager implements MigrateCckFieldPluginManagerInterface {}
|
||||
@@ -0,0 +1,15 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\migrate_drupal\Plugin;
|
||||
|
||||
@trigger_error('MigrateCckFieldPluginManagerInterface is deprecated in Drupal 8.3.x and will be removed before Drupal 9.0.x. Use \Drupal\migrate_drupal\Annotation\MigrateFieldPluginManagerInterface instead.', E_USER_DEPRECATED);
|
||||
|
||||
/**
|
||||
* Provides an interface for cck field plugin manager.
|
||||
*
|
||||
* @deprecated in drupal:8.3.0 and is removed from drupal:9.0.0. Use
|
||||
* \Drupal\migrate_drupal\Plugin\MigrateFieldPluginManagerInterface instead.
|
||||
*
|
||||
* @see https://www.drupal.org/node/2751897
|
||||
*/
|
||||
interface MigrateCckFieldPluginManagerInterface extends MigrateFieldPluginManagerInterface {}
|
||||
@@ -0,0 +1,109 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\migrate_drupal\Plugin;
|
||||
|
||||
use Drupal\Component\Plugin\PluginInspectionInterface;
|
||||
use Drupal\migrate\Plugin\MigrationInterface;
|
||||
use Drupal\migrate\Row;
|
||||
|
||||
/**
|
||||
* Provides an interface for all field type plugins.
|
||||
*/
|
||||
interface MigrateFieldInterface extends PluginInspectionInterface {
|
||||
|
||||
/**
|
||||
* Apply any custom processing to the field migration.
|
||||
*
|
||||
* @param \Drupal\migrate\Plugin\MigrationInterface $migration
|
||||
* The migration entity.
|
||||
*/
|
||||
public function alterFieldMigration(MigrationInterface $migration);
|
||||
|
||||
/**
|
||||
* Apply any custom processing to the field instance migration.
|
||||
*
|
||||
* @param \Drupal\migrate\Plugin\MigrationInterface $migration
|
||||
* The migration entity.
|
||||
*/
|
||||
public function alterFieldInstanceMigration(MigrationInterface $migration);
|
||||
|
||||
/**
|
||||
* Apply any custom processing to the field widget migration.
|
||||
*
|
||||
* @param \Drupal\migrate\Plugin\MigrationInterface $migration
|
||||
* The migration entity.
|
||||
*/
|
||||
public function alterFieldWidgetMigration(MigrationInterface $migration);
|
||||
|
||||
/**
|
||||
* Apply any custom processing to the field formatter migration.
|
||||
*
|
||||
* @param \Drupal\migrate\Plugin\MigrationInterface $migration
|
||||
* The migration entity.
|
||||
*/
|
||||
public function alterFieldFormatterMigration(MigrationInterface $migration);
|
||||
|
||||
/**
|
||||
* Get the field formatter type from the source.
|
||||
*
|
||||
* @param \Drupal\migrate\Row $row
|
||||
* The field being migrated.
|
||||
*
|
||||
* @return string
|
||||
* The field formatter type.
|
||||
*/
|
||||
public function getFieldFormatterType(Row $row);
|
||||
|
||||
/**
|
||||
* Get a map between D6 formatters and D8 formatters for this field type.
|
||||
*
|
||||
* This is used by static::alterFieldFormatterMigration() in the base class.
|
||||
*
|
||||
* @return array
|
||||
* The keys are D6 formatters and the values are D8 formatters.
|
||||
*/
|
||||
public function getFieldFormatterMap();
|
||||
|
||||
/**
|
||||
* Get the field widget type from the source.
|
||||
*
|
||||
* @param \Drupal\migrate\Row $row
|
||||
* The field being migrated.
|
||||
*
|
||||
* @return string
|
||||
* The field widget type.
|
||||
*/
|
||||
public function getFieldWidgetType(Row $row);
|
||||
|
||||
/**
|
||||
* Get a map between D6 and D8 widgets for this field type.
|
||||
*
|
||||
* @return array
|
||||
* The keys are D6 field widget types and the values D8 widgets.
|
||||
*/
|
||||
public function getFieldWidgetMap();
|
||||
|
||||
/**
|
||||
* Apply any custom processing to the field bundle migrations.
|
||||
*
|
||||
* @param \Drupal\migrate\Plugin\MigrationInterface $migration
|
||||
* The migration entity.
|
||||
* @param string $field_name
|
||||
* The field name we're processing the value for.
|
||||
* @param array $data
|
||||
* The array of field data from FieldValues::fieldData().
|
||||
*/
|
||||
public function defineValueProcessPipeline(MigrationInterface $migration, $field_name, $data);
|
||||
|
||||
/**
|
||||
* Computes the destination type of a migrated field.
|
||||
*
|
||||
* @param \Drupal\migrate\Row $row
|
||||
* The field being migrated.
|
||||
*
|
||||
* @return string
|
||||
* The destination field type.
|
||||
*/
|
||||
public function getFieldType(Row $row);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,113 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\migrate_drupal\Plugin;
|
||||
|
||||
use Drupal\Component\Plugin\Exception\PluginNotFoundException;
|
||||
use Drupal\migrate\Plugin\Exception\BadPluginDefinitionException;
|
||||
use Drupal\migrate\Plugin\MigratePluginManager;
|
||||
use Drupal\migrate\Plugin\MigrationInterface;
|
||||
|
||||
/**
|
||||
* Plugin manager for migrate field plugins.
|
||||
*
|
||||
* @see \Drupal\migrate_drupal\Plugin\MigrateFieldInterface
|
||||
* @see \Drupal\migrate\Annotation\MigrateField
|
||||
* @see plugin_api
|
||||
*
|
||||
* @ingroup migration
|
||||
*/
|
||||
class MigrateFieldPluginManager extends MigratePluginManager implements MigrateFieldPluginManagerInterface {
|
||||
|
||||
/**
|
||||
* The default version of core to use for field plugins.
|
||||
*
|
||||
* These plugins were initially only built and used for Drupal 6 fields.
|
||||
* Having been extended for Drupal 7 with a "core" annotation, we fall back to
|
||||
* Drupal 6 where none exists.
|
||||
*/
|
||||
const DEFAULT_CORE_VERSION = 6;
|
||||
|
||||
/**
|
||||
* Get the plugin ID from the field type.
|
||||
*
|
||||
* This method determines which field plugin should be used for a given field
|
||||
* type and Drupal core version, returning the lowest weighted plugin
|
||||
* supporting the provided core version, and which matches the field type
|
||||
* either by plugin ID, or in the type_map annotation keys.
|
||||
*
|
||||
* @param string $field_type
|
||||
* The field type being migrated.
|
||||
* @param array $configuration
|
||||
* (optional) An array of configuration relevant to the plugin instance.
|
||||
* @param \Drupal\migrate\Plugin\MigrationInterface $migration
|
||||
* (optional) The current migration instance.
|
||||
*
|
||||
* @return string
|
||||
* The ID of the plugin for the field type if available.
|
||||
*
|
||||
* @throws \Drupal\Component\Plugin\Exception\PluginNotFoundException
|
||||
* If the plugin cannot be determined, such as if the field type is invalid.
|
||||
*
|
||||
* @see \Drupal\migrate_drupal\Annotation\MigrateField
|
||||
*/
|
||||
public function getPluginIdFromFieldType($field_type, array $configuration = [], MigrationInterface $migration = NULL) {
|
||||
$core = static::DEFAULT_CORE_VERSION;
|
||||
if (!empty($configuration['core'])) {
|
||||
$core = $configuration['core'];
|
||||
}
|
||||
elseif (!empty($migration->getPluginDefinition()['migration_tags'])) {
|
||||
foreach ($migration->getPluginDefinition()['migration_tags'] as $tag) {
|
||||
if ($tag == 'Drupal 7') {
|
||||
$core = 7;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$definitions = $this->getDefinitions();
|
||||
foreach ($definitions as $plugin_id => $definition) {
|
||||
if (in_array($core, $definition['core'])) {
|
||||
if (array_key_exists($field_type, $definition['type_map']) || $field_type === $plugin_id) {
|
||||
return $plugin_id;
|
||||
}
|
||||
}
|
||||
}
|
||||
throw new PluginNotFoundException($field_type);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function processDefinition(&$definition, $plugin_id) {
|
||||
parent::processDefinition($definition, $plugin_id);
|
||||
|
||||
foreach (['core', 'source_module', 'destination_module'] as $required_property) {
|
||||
if (empty($definition[$required_property])) {
|
||||
throw new BadPluginDefinitionException($plugin_id, $required_property);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function findDefinitions() {
|
||||
$definitions = parent::findDefinitions();
|
||||
$this->sortDefinitions($definitions);
|
||||
return $definitions;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sorts a definitions array.
|
||||
*
|
||||
* This sorts the definitions array first by the weight column, and then by
|
||||
* the plugin ID, ensuring a stable, deterministic, and testable ordering of
|
||||
* plugins.
|
||||
*
|
||||
* @param array $definitions
|
||||
* The definitions array to sort.
|
||||
*/
|
||||
protected function sortDefinitions(array &$definitions) {
|
||||
array_multisort(array_column($definitions, 'weight'), SORT_ASC, SORT_NUMERIC, array_keys($definitions), SORT_ASC, SORT_NATURAL, $definitions);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\migrate_drupal\Plugin;
|
||||
|
||||
use Drupal\migrate\Plugin\MigratePluginManagerInterface;
|
||||
use Drupal\migrate\Plugin\MigrationInterface;
|
||||
|
||||
interface MigrateFieldPluginManagerInterface extends MigratePluginManagerInterface {
|
||||
|
||||
/**
|
||||
* Get the plugin ID from the field type.
|
||||
*
|
||||
* @param string $field_type
|
||||
* The field type being migrated.
|
||||
* @param array $configuration
|
||||
* (optional) An array of configuration relevant to the plugin instance.
|
||||
* @param \Drupal\migrate\Plugin\MigrationInterface|null $migration
|
||||
* (optional) The current migration instance.
|
||||
*
|
||||
* @return string
|
||||
* The ID of the plugin for the field_type if available.
|
||||
*
|
||||
* @throws \Drupal\Component\Plugin\Exception\PluginNotFoundException
|
||||
* If the plugin cannot be determined, such as if the field type is invalid.
|
||||
*/
|
||||
public function getPluginIdFromFieldType($field_type, array $configuration = [], MigrationInterface $migration = NULL);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\migrate_drupal\Plugin;
|
||||
|
||||
/**
|
||||
* Interface for migrations with follow-up migrations.
|
||||
*
|
||||
* Some migrations need to be derived and executed after other migrations have
|
||||
* been successfully executed. For example, a migration might need to be derived
|
||||
* based on previously migrated data. For such a case, the migration dependency
|
||||
* system is not enough since all migrations would still be derived before any
|
||||
* one of them has been executed.
|
||||
*
|
||||
* Those "follow-up" migrations need to be tagged with the "Follow-up migration"
|
||||
* tag (or any tag in the "follow_up_migration_tags" configuration) and thus
|
||||
* they won't be derived with the other migrations.
|
||||
*
|
||||
* To get those follow-up migrations derived at the right time, the migrations
|
||||
* on which they depend must implement this interface and generate them in the
|
||||
* generateFollowUpMigrations() method.
|
||||
*
|
||||
* When the migrations implementing this interface have been successfully
|
||||
* executed, the follow-up migrations will then be derived having access to the
|
||||
* now migrated data.
|
||||
*/
|
||||
interface MigrationWithFollowUpInterface {
|
||||
|
||||
/**
|
||||
* Generates follow-up migrations.
|
||||
*
|
||||
* When the migration implementing this interface has been successfully
|
||||
* executed, this method will be used to generate the follow-up migrations
|
||||
* which depends on the now migrated data.
|
||||
*
|
||||
* @return \Drupal\migrate\Plugin\MigrationInterface[]
|
||||
* The follow-up migrations.
|
||||
*/
|
||||
public function generateFollowUpMigrations();
|
||||
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\migrate_drupal\Plugin\migrate;
|
||||
|
||||
@trigger_error('CckMigration is deprecated in Drupal 8.3.x and will be removed before Drupal 9.0.x. Use \Drupal\migrate_drupal\Plugin\migrate\FieldMigration instead.', E_USER_DEPRECATED);
|
||||
|
||||
/**
|
||||
* Migration plugin class for migrations dealing with CCK field values.
|
||||
*
|
||||
* @deprecated in drupal:8.3.0 and is removed from drupal:9.0.0. Use
|
||||
* \Drupal\migrate_drupal\Plugin\migrate\FieldMigration instead.
|
||||
*
|
||||
* @see https://www.drupal.org/node/2751897
|
||||
*/
|
||||
class CckMigration extends FieldMigration {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
const PLUGIN_METHOD = 'cck_plugin_method';
|
||||
|
||||
}
|
||||
+193
@@ -0,0 +1,193 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\migrate_drupal\Plugin\migrate;
|
||||
|
||||
use Drupal\Component\Plugin\Derivative\DeriverBase;
|
||||
use Drupal\Component\Plugin\PluginBase;
|
||||
use Drupal\Core\Entity\EntityFieldManagerInterface;
|
||||
use Drupal\Core\Entity\EntityTypeManagerInterface;
|
||||
use Drupal\Core\Plugin\Discovery\ContainerDeriverInterface;
|
||||
use Drupal\Core\StringTranslation\StringTranslationTrait;
|
||||
use Symfony\Component\DependencyInjection\ContainerInterface;
|
||||
|
||||
/**
|
||||
* Deriver for entity reference field translations.
|
||||
*
|
||||
* A migration will be created for every bundle with at least one entity
|
||||
* reference field that is configured to point to one of the supported target
|
||||
* entity types. The migrations will update the entity reference fields with
|
||||
* values found in the mapping tables of the migrations associated with the
|
||||
* target types.
|
||||
*
|
||||
* Example:
|
||||
*
|
||||
* @code
|
||||
* id: d7_entity_reference_translation
|
||||
* label: Entity reference translations
|
||||
* migration_tags:
|
||||
* - Drupal 7
|
||||
* - Follow-up migration
|
||||
* deriver: Drupal\migrate_drupal\Plugin\migrate\EntityReferenceTranslationDeriver
|
||||
* target_types:
|
||||
* node:
|
||||
* - d7_node_translation
|
||||
* source:
|
||||
* plugin: empty
|
||||
* key: default
|
||||
* target: default
|
||||
* process: []
|
||||
* destination:
|
||||
* plugin: null
|
||||
* @endcode
|
||||
*
|
||||
* In this example, the only supported target type is 'node' and the associated
|
||||
* migration for the mapping table lookup is 'd7_node_translation'.
|
||||
*/
|
||||
class EntityReferenceTranslationDeriver extends DeriverBase implements ContainerDeriverInterface {
|
||||
|
||||
use StringTranslationTrait;
|
||||
|
||||
/**
|
||||
* The entity field manager.
|
||||
*
|
||||
* @var \Drupal\Core\Entity\EntityFieldManagerInterface
|
||||
*/
|
||||
protected $entityFieldManager;
|
||||
|
||||
/**
|
||||
* The entity type manager.
|
||||
*
|
||||
* @var \Drupal\Core\Entity\EntityTypeManagerInterface
|
||||
*/
|
||||
protected $entityTypeManager;
|
||||
|
||||
/**
|
||||
* EntityReferenceTranslationDeriver constructor.
|
||||
*
|
||||
* @param string $base_plugin_id
|
||||
* The base plugin ID.
|
||||
* @param \Drupal\Core\Entity\EntityFieldManagerInterface $entity_field_manager
|
||||
* The entity field manager.
|
||||
* @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
|
||||
* The entity type manager.
|
||||
*/
|
||||
public function __construct($base_plugin_id, EntityFieldManagerInterface $entity_field_manager, EntityTypeManagerInterface $entity_type_manager) {
|
||||
$this->entityFieldManager = $entity_field_manager;
|
||||
$this->entityTypeManager = $entity_type_manager;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function create(ContainerInterface $container, $base_plugin_id) {
|
||||
return new static(
|
||||
$base_plugin_id,
|
||||
$container->get('entity_field.manager'),
|
||||
$container->get('entity_type.manager')
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getDerivativeDefinitions($base_plugin_definition) {
|
||||
// Get all entity reference fields.
|
||||
$field_map = $this->entityFieldManager->getFieldMapByFieldType('entity_reference');
|
||||
|
||||
foreach ($field_map as $entity_type => $fields) {
|
||||
foreach ($fields as $field_name => $field) {
|
||||
foreach ($field['bundles'] as $bundle) {
|
||||
$field_definitions = $this->entityFieldManager->getFieldDefinitions($entity_type, $bundle);
|
||||
$target_type = $field_definitions[$field_name]->getSetting('target_type');
|
||||
|
||||
// If the field's target type is not supported, skip it.
|
||||
if (!array_key_exists($target_type, $base_plugin_definition['target_types'])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Key derivatives by entity types and bundles.
|
||||
$derivative_key = $entity_type . '__' . $bundle;
|
||||
|
||||
$derivative = $base_plugin_definition;
|
||||
$entity_type_definition = $this->entityTypeManager->getDefinition($entity_type);
|
||||
|
||||
// Set the migration label.
|
||||
$derivative['label'] = $this->t('@label (@derivative)', [
|
||||
'@label' => $base_plugin_definition['label'],
|
||||
'@derivative' => $derivative_key,
|
||||
]);
|
||||
|
||||
// Set the source plugin.
|
||||
$derivative['source']['plugin'] = 'content_entity' . PluginBase::DERIVATIVE_SEPARATOR . $entity_type;
|
||||
if ($entity_type_definition->hasKey('bundle')) {
|
||||
$derivative['source']['bundle'] = $bundle;
|
||||
}
|
||||
|
||||
// Set the process pipeline.
|
||||
$id_key = $entity_type_definition->getKey('id');
|
||||
$derivative['process'][$id_key] = $id_key;
|
||||
if ($entity_type_definition->isRevisionable()) {
|
||||
$revision_key = $entity_type_definition->getKey('revision');
|
||||
$derivative['process'][$revision_key] = $revision_key;
|
||||
}
|
||||
if ($entity_type_definition->isTranslatable()) {
|
||||
$langcode_key = $entity_type_definition->getKey('langcode');
|
||||
$derivative['process'][$langcode_key] = $langcode_key;
|
||||
}
|
||||
|
||||
// Set the destination plugin.
|
||||
$derivative['destination']['plugin'] = 'entity' . PluginBase::DERIVATIVE_SEPARATOR . $entity_type;
|
||||
if ($entity_type_definition->hasKey('bundle')) {
|
||||
$derivative['destination']['default_bundle'] = $bundle;
|
||||
}
|
||||
if ($entity_type_definition->isTranslatable()) {
|
||||
$derivative['destination']['translations'] = TRUE;
|
||||
}
|
||||
|
||||
// Allow overwriting the entity reference field so we can update its
|
||||
// values with the ones found in the mapping table.
|
||||
$derivative['destination']['overwrite_properties'][$field_name] = $field_name;
|
||||
|
||||
// Add the entity reference field to the process pipeline.
|
||||
$derivative['process'][$field_name] = [
|
||||
'plugin' => 'sub_process',
|
||||
'source' => $field_name,
|
||||
'process' => [
|
||||
'target_id' => [
|
||||
[
|
||||
'plugin' => 'migration_lookup',
|
||||
'source' => 'target_id',
|
||||
'migration' => $base_plugin_definition['target_types'][$target_type],
|
||||
'no_stub' => TRUE,
|
||||
],
|
||||
[
|
||||
'plugin' => 'skip_on_empty',
|
||||
'method' => 'row',
|
||||
],
|
||||
[
|
||||
'plugin' => 'extract',
|
||||
'index' => [0],
|
||||
],
|
||||
],
|
||||
],
|
||||
];
|
||||
|
||||
if (!isset($this->derivatives[$derivative_key])) {
|
||||
// If this is a new derivative, add it to the returned derivatives.
|
||||
$this->derivatives[$derivative_key] = $derivative;
|
||||
}
|
||||
else {
|
||||
// If this is an existing derivative, it means this bundle has more
|
||||
// than one entity reference field. In that case, we only want to add
|
||||
// the field to the process pipeline and make it overwritable.
|
||||
$this->derivatives[$derivative_key]['process'] += $derivative['process'];
|
||||
$this->derivatives[$derivative_key]['destination']['overwrite_properties'] += $derivative['destination']['overwrite_properties'];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $this->derivatives;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,99 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\migrate_drupal\Plugin\migrate;
|
||||
|
||||
use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
|
||||
use Drupal\migrate\Plugin\MigrateDestinationPluginManager;
|
||||
use Drupal\migrate\Plugin\MigratePluginManager;
|
||||
use Drupal\migrate\Plugin\Migration;
|
||||
use Drupal\migrate\Plugin\MigrationPluginManagerInterface;
|
||||
use Drupal\migrate_drupal\FieldDiscoveryInterface;
|
||||
use Symfony\Component\DependencyInjection\ContainerInterface;
|
||||
|
||||
/**
|
||||
* Migration plugin class for migrations dealing with field config and values.
|
||||
*/
|
||||
class FieldMigration extends Migration implements ContainerFactoryPluginInterface {
|
||||
|
||||
/**
|
||||
* Defines which configuration option has the migration processing function.
|
||||
*
|
||||
* Default method is 'field_plugin_method'. For backwards compatibility,
|
||||
* this constant is overridden in the CckMigration class, in order to
|
||||
* fallback to the old 'cck_plugin_method'.
|
||||
*
|
||||
* @const string
|
||||
* @deprecated in drupal:8.7.0 and is removed from drupal:9.0.0. Use the migrate_drupal.field_discovery service instead. See https://www.drupal.org/node/3006076.
|
||||
*/
|
||||
const PLUGIN_METHOD = 'field_plugin_method';
|
||||
|
||||
/**
|
||||
* Flag indicating whether the field data has been filled already.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
protected $init = FALSE;
|
||||
|
||||
/**
|
||||
* The migration field discovery service.
|
||||
*
|
||||
* @var \Drupal\migrate_drupal\FieldDiscoveryInterface
|
||||
*/
|
||||
protected $fieldDiscovery;
|
||||
|
||||
/**
|
||||
* Constructs a FieldMigration.
|
||||
*
|
||||
* @param array $configuration
|
||||
* Plugin configuration.
|
||||
* @param string $plugin_id
|
||||
* The plugin ID.
|
||||
* @param mixed $plugin_definition
|
||||
* The plugin definition.
|
||||
* @param \Drupal\migrate\Plugin\MigrationPluginManagerInterface $migration_plugin_manager
|
||||
* The migration plugin manager.
|
||||
* @param \Drupal\migrate\Plugin\MigratePluginManager $source_plugin_manager
|
||||
* The source migration plugin manager.
|
||||
* @param \Drupal\migrate\Plugin\MigratePluginManager $process_plugin_manager
|
||||
* The process migration plugin manager.
|
||||
* @param \Drupal\migrate\Plugin\MigrateDestinationPluginManager $destination_plugin_manager
|
||||
* The destination migration plugin manager.
|
||||
* @param \Drupal\migrate\Plugin\MigratePluginManager $idmap_plugin_manager
|
||||
* The ID map migration plugin manager.
|
||||
* @param \Drupal\migrate_drupal\FieldDiscoveryInterface $field_discovery
|
||||
* The migration field discovery service.
|
||||
*/
|
||||
public function __construct(array $configuration, $plugin_id, $plugin_definition, MigrationPluginManagerInterface $migration_plugin_manager, MigratePluginManager $source_plugin_manager, MigratePluginManager $process_plugin_manager, MigrateDestinationPluginManager $destination_plugin_manager, MigratePluginManager $idmap_plugin_manager, FieldDiscoveryInterface $field_discovery) {
|
||||
parent::__construct($configuration, $plugin_id, $plugin_definition, $migration_plugin_manager, $source_plugin_manager, $process_plugin_manager, $destination_plugin_manager, $idmap_plugin_manager);
|
||||
$this->fieldDiscovery = $field_discovery;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
|
||||
return new static(
|
||||
$configuration,
|
||||
$plugin_id,
|
||||
$plugin_definition,
|
||||
$container->get('plugin.manager.migration'),
|
||||
$container->get('plugin.manager.migrate.source'),
|
||||
$container->get('plugin.manager.migrate.process'),
|
||||
$container->get('plugin.manager.migrate.destination'),
|
||||
$container->get('plugin.manager.migrate.id_map'),
|
||||
$container->get('migrate_drupal.field_discovery')
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getProcess() {
|
||||
if (!$this->init) {
|
||||
$this->init = TRUE;
|
||||
$this->fieldDiscovery->addAllFieldProcesses($this);
|
||||
}
|
||||
return parent::getProcess();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\migrate_drupal\Plugin\migrate\cckfield;
|
||||
|
||||
@trigger_error('CckFieldPluginBase is deprecated in Drupal 8.3.x and will be be removed before Drupal 9.0.x. Use \Drupal\migrate_drupal\Plugin\migrate\field\FieldPluginBase instead.', E_USER_DEPRECATED);
|
||||
|
||||
use Drupal\migrate\Plugin\MigrationInterface;
|
||||
use Drupal\migrate_drupal\Plugin\migrate\field\FieldPluginBase;
|
||||
use Drupal\migrate_drupal\Plugin\MigrateCckFieldInterface;
|
||||
|
||||
/**
|
||||
* The base class for all field plugins.
|
||||
*
|
||||
* @deprecated in drupal:8.4.0 and is removed from drupal:9.0.0. Use
|
||||
* \Drupal\migrate_drupal\Plugin\migrate\field\FieldPluginBase instead.
|
||||
*
|
||||
* @see https://www.drupal.org/node/2751897
|
||||
*
|
||||
* @ingroup migration
|
||||
*/
|
||||
abstract class CckFieldPluginBase extends FieldPluginBase implements MigrateCckFieldInterface {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function defineValueProcessPipeline(MigrationInterface $migration, $field_name, $data) {
|
||||
// Provide a bridge to the old method declared on the interface and now an
|
||||
// abstract method in this class.
|
||||
return $this->processCckFieldValues($migration, $field_name, $data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply any custom processing to the field bundle migrations.
|
||||
*
|
||||
* @param \Drupal\migrate\Plugin\MigrationInterface $migration
|
||||
* The migration entity.
|
||||
* @param string $field_name
|
||||
* The field name we're processing the value for.
|
||||
* @param array $data
|
||||
* The array of field data from FieldValues::fieldData().
|
||||
*/
|
||||
abstract public function processCckFieldValues(MigrationInterface $migration, $field_name, $data);
|
||||
|
||||
}
|
||||
+104
@@ -0,0 +1,104 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\migrate_drupal\Plugin\migrate\destination;
|
||||
|
||||
use Drupal\Core\Config\ConfigFactoryInterface;
|
||||
use Drupal\Core\Entity\EntityStorageInterface;
|
||||
use Drupal\Core\Field\FieldTypePluginManagerInterface;
|
||||
use Drupal\Core\Language\LanguageManagerInterface;
|
||||
use Symfony\Component\DependencyInjection\ContainerInterface;
|
||||
use Drupal\migrate\Plugin\MigrationInterface;
|
||||
use Drupal\migrate\Plugin\migrate\destination\EntityFieldStorageConfig as BaseEntityFieldStorageConfig;
|
||||
|
||||
/**
|
||||
* Deprecated. Destination with Drupal specific config dependencies.
|
||||
*
|
||||
* @MigrateDestination(
|
||||
* id = "md_entity:field_storage_config"
|
||||
* )
|
||||
*
|
||||
* @deprecated in drupal:8.2.0 and is removed from drupal:9.0.0. Use
|
||||
* \Drupal\migrate\Plugin\migrate\destination\EntityFieldStorageConfig
|
||||
* instead.
|
||||
*
|
||||
* @see \Drupal\migrate\Plugin\migrate\destination\EntityFieldStorageConfig
|
||||
*/
|
||||
class EntityFieldStorageConfig extends BaseEntityFieldStorageConfig {
|
||||
|
||||
/**
|
||||
* The field type plugin manager.
|
||||
*
|
||||
* @var \Drupal\Core\Field\FieldTypePluginManagerInterface
|
||||
*/
|
||||
protected $fieldTypePluginManager;
|
||||
|
||||
/**
|
||||
* Construct a new 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\Entity\EntityStorageInterface $storage
|
||||
* The storage for this entity type.
|
||||
* @param array $bundles
|
||||
* The list of bundles this entity type has.
|
||||
* @param \Drupal\Core\Language\LanguageManagerInterface $language_manager
|
||||
* The language manager.
|
||||
* @param \Drupal\Core\Config\ConfigFactoryInterface $config_factory
|
||||
* The configuration factory.
|
||||
* @param \Drupal\Core\Field\FieldTypePluginManagerInterface $field_type_plugin_manager
|
||||
* The field type plugin manager.
|
||||
*/
|
||||
public function __construct(array $configuration, $plugin_id, $plugin_definition, MigrationInterface $migration, EntityStorageInterface $storage, array $bundles, LanguageManagerInterface $language_manager, ConfigFactoryInterface $config_factory, FieldTypePluginManagerInterface $field_type_plugin_manager) {
|
||||
parent::__construct($configuration, $plugin_id, $plugin_definition, $migration, $storage, $bundles, $language_manager, $config_factory, $field_type_plugin_manager);
|
||||
$this->languageManager = $language_manager;
|
||||
$this->configFactory = $config_factory;
|
||||
$this->fieldTypePluginManager = $field_type_plugin_manager;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition, MigrationInterface $migration = NULL) {
|
||||
$entity_type_id = static::getEntityTypeId($plugin_id);
|
||||
return new static(
|
||||
$configuration,
|
||||
$plugin_id,
|
||||
$plugin_definition,
|
||||
$migration,
|
||||
$container->get('entity_type.manager')->getStorage($entity_type_id),
|
||||
array_keys($container->get('entity_type.bundle.info')->getBundleInfo($entity_type_id)),
|
||||
$container->get('language_manager'),
|
||||
$container->get('config.factory'),
|
||||
$container->get('plugin.manager.field.field_type')
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function calculateDependencies() {
|
||||
$this->dependencies = parent::calculateDependencies();
|
||||
// Add a dependency on the module that provides the field type using the
|
||||
// source plugin configuration.
|
||||
$source_configuration = $this->migration->getSourceConfiguration();
|
||||
if (isset($source_configuration['constants']['type'])) {
|
||||
$field_type = $this->fieldTypePluginManager->getDefinition($source_configuration['constants']['type']);
|
||||
$this->addDependency('module', $field_type['provider']);
|
||||
}
|
||||
return $this->dependencies;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static function getEntityTypeId($plugin_id) {
|
||||
return 'field_storage_config';
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,189 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\migrate_drupal\Plugin\migrate\field;
|
||||
|
||||
use Drupal\Core\Plugin\PluginBase;
|
||||
use Drupal\migrate\Plugin\MigrationInterface;
|
||||
use Drupal\migrate\Row;
|
||||
use Drupal\migrate_drupal\Plugin\MigrateFieldInterface;
|
||||
|
||||
/**
|
||||
* The base class for all field plugins.
|
||||
*
|
||||
* @see \Drupal\migrate\Plugin\MigratePluginManager
|
||||
* @see \Drupal\migrate_drupal\Annotation\MigrateField
|
||||
* @see \Drupal\migrate_drupal\Plugin\MigrateFieldInterface
|
||||
* @see plugin_api
|
||||
*
|
||||
* @ingroup migration
|
||||
*/
|
||||
abstract class FieldPluginBase extends PluginBase implements MigrateFieldInterface {
|
||||
|
||||
/**
|
||||
* Alters the migration for field definitions.
|
||||
*
|
||||
* @deprecated in drupal:8.6.0 and is removed from drupal:9.0.0. Use
|
||||
* alterFieldMigration() instead.
|
||||
*
|
||||
* @see https://www.drupal.org/node/2944598
|
||||
* @see ::alterFieldMigration()
|
||||
*/
|
||||
public function processField(MigrationInterface $migration) {
|
||||
@trigger_error('Deprecated in Drupal 8.6.0, to be removed before Drupal 9.0.0. Use alterFieldMigration() instead. See https://www.drupal.org/node/2944598.', E_USER_DEPRECATED);
|
||||
$this->alterFieldMigration($migration);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function alterFieldMigration(MigrationInterface $migration) {
|
||||
$process[0]['map'][$this->pluginId][$this->pluginId] = $this->pluginId;
|
||||
$migration->mergeProcessOfProperty('type', $process);
|
||||
}
|
||||
|
||||
/**
|
||||
* Alert field instance migration.
|
||||
*
|
||||
* @deprecated in drupal:8.6.0 and is removed from drupal:9.0.0. Use
|
||||
* alterFieldInstanceMigration() instead.
|
||||
*
|
||||
* @see https://www.drupal.org/node/2944598
|
||||
* @see ::alterFieldInstanceMigration()
|
||||
*/
|
||||
public function processFieldInstance(MigrationInterface $migration) {
|
||||
@trigger_error('Deprecated in Drupal 8.6.0, to be removed before Drupal 9.0.0. Use alterFieldInstanceMigration() instead. See https://www.drupal.org/node/2944598.', E_USER_DEPRECATED);
|
||||
$this->alterFieldInstanceMigration($migration);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function alterFieldInstanceMigration(MigrationInterface $migration) {
|
||||
// Nothing to do by default with field instances.
|
||||
}
|
||||
|
||||
/**
|
||||
* Alter field widget migration.
|
||||
*
|
||||
* @deprecated in drupal:8.6.0 and is removed from drupal:9.0.0. Use
|
||||
* alterFieldWidgetMigration() instead.
|
||||
*
|
||||
* @see https://www.drupal.org/node/2944598
|
||||
* @see ::alterFieldWidgetMigration()
|
||||
*/
|
||||
public function processFieldWidget(MigrationInterface $migration) {
|
||||
@trigger_error('Deprecated in Drupal 8.6.0, to be removed before Drupal 9.0.0. Use alterFieldWidgetMigration() instead. See https://www.drupal.org/node/2944598.', E_USER_DEPRECATED);
|
||||
$this->alterFieldWidgetMigration($migration);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function alterFieldWidgetMigration(MigrationInterface $migration) {
|
||||
$process = [];
|
||||
foreach ($this->getFieldWidgetMap() as $source_widget => $destination_widget) {
|
||||
$process['type']['map'][$source_widget] = $destination_widget;
|
||||
}
|
||||
$migration->mergeProcessOfProperty('options/type', $process);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getFieldFormatterType(Row $row) {
|
||||
return $row->getSourceProperty('formatter/type');
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getFieldFormatterMap() {
|
||||
return [];
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getFieldWidgetType(Row $row) {
|
||||
return $row->getSourceProperty('widget/type');
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getFieldWidgetMap() {
|
||||
// By default, use the plugin ID for the widget types.
|
||||
return [
|
||||
$this->pluginId => $this->pluginId . '_default',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Alter field formatter migration.
|
||||
*
|
||||
* @deprecated in drupal:8.6.0 and is removed from drupal:9.0.0. Use
|
||||
* alterFieldFormatterMigration() instead.
|
||||
*
|
||||
* @see https://www.drupal.org/node/2944598
|
||||
* @see ::processFieldFormatter()
|
||||
*/
|
||||
public function processFieldFormatter(MigrationInterface $migration) {
|
||||
@trigger_error('Deprecated in Drupal 8.6.0, to be removed before Drupal 9.0.0. Use alterFieldFormatterMigration() instead. See https://www.drupal.org/node/2944598.', E_USER_DEPRECATED);
|
||||
$this->alterFieldFormatterMigration($migration);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function alterFieldFormatterMigration(MigrationInterface $migration) {
|
||||
$process = [];
|
||||
// Some migrate field plugin IDs are prefixed with 'd6_' or 'd7_'. Since the
|
||||
// plugin ID is used in the static map as the module name, we have to remove
|
||||
// this prefix from the plugin ID.
|
||||
$plugin_id = preg_replace('/d[67]_/', '', $this->pluginId);
|
||||
foreach ($this->getFieldFormatterMap() as $source_format => $destination_format) {
|
||||
$process[0]['map'][$plugin_id][$source_format] = $destination_format;
|
||||
}
|
||||
$migration->mergeProcessOfProperty('options/type', $process);
|
||||
}
|
||||
|
||||
/**
|
||||
* Defines the process pipeline for field values.
|
||||
*
|
||||
* @deprecated in drupal:8.6.0 and is removed from drupal:9.0.0. Use
|
||||
* defineValueProcessPipeline() instead.
|
||||
*
|
||||
* @see https://www.drupal.org/node/2944598
|
||||
* @see ::defineValueProcessPipeline()
|
||||
*/
|
||||
public function processFieldValues(MigrationInterface $migration, $field_name, $data) {
|
||||
@trigger_error('Deprecated in Drupal 8.6.0, to be removed before Drupal 9.0.0. Use defineValueProcessPipeline() instead. See https://www.drupal.org/node/2944598.', E_USER_DEPRECATED);
|
||||
return $this->defineValueProcessPipeline($migration, $field_name, $data);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function defineValueProcessPipeline(MigrationInterface $migration, $field_name, $data) {
|
||||
$process = [
|
||||
'plugin' => 'get',
|
||||
'source' => $field_name,
|
||||
];
|
||||
$migration->mergeProcessOfProperty($field_name, $process);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getFieldType(Row $row) {
|
||||
$field_type = $row->getSourceProperty('type');
|
||||
|
||||
if (isset($this->pluginDefinition['type_map'][$field_type])) {
|
||||
return $this->pluginDefinition['type_map'][$field_type];
|
||||
}
|
||||
else {
|
||||
return $field_type;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\migrate_drupal\Plugin\migrate\field;
|
||||
|
||||
use Drupal\migrate\Plugin\MigrationInterface;
|
||||
|
||||
/**
|
||||
* @MigrateField(
|
||||
* id = "nodereference",
|
||||
* core = {6},
|
||||
* type_map = {
|
||||
* "nodereference" = "entity_reference",
|
||||
* },
|
||||
* source_module = "nodereference",
|
||||
* destination_module = "core",
|
||||
* )
|
||||
*/
|
||||
class NodeReference extends FieldPluginBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function defineValueProcessPipeline(MigrationInterface $migration, $field_name, $data) {
|
||||
$process = [
|
||||
'plugin' => 'sub_process',
|
||||
'source' => $field_name,
|
||||
'process' => [
|
||||
'target_id' => [
|
||||
'plugin' => 'get',
|
||||
'source' => 'nid',
|
||||
],
|
||||
],
|
||||
];
|
||||
$migration->setProcessOfProperty($field_name, $process);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\migrate_drupal\Plugin\migrate\field;
|
||||
|
||||
use Drupal\migrate\Plugin\MigrationInterface;
|
||||
|
||||
/**
|
||||
* @MigrateField(
|
||||
* id = "userreference",
|
||||
* core = {6},
|
||||
* type_map = {
|
||||
* "userreference" = "entity_reference",
|
||||
* },
|
||||
* source_module = "userreference",
|
||||
* destination_module = "core",
|
||||
* )
|
||||
*/
|
||||
class UserReference extends FieldPluginBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function defineValueProcessPipeline(MigrationInterface $migration, $field_name, $data) {
|
||||
$process = [
|
||||
'plugin' => 'sub_process',
|
||||
'source' => $field_name,
|
||||
'process' => [
|
||||
'target_id' => [
|
||||
'plugin' => 'migration_lookup',
|
||||
'migration' => 'd6_user',
|
||||
'source' => 'uid',
|
||||
],
|
||||
],
|
||||
];
|
||||
$migration->setProcessOfProperty($field_name, $process);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\migrate_drupal\Plugin\migrate\process;
|
||||
|
||||
use Drupal\migrate\MigrateExecutableInterface;
|
||||
use Drupal\migrate\ProcessPluginBase;
|
||||
use Drupal\migrate\Row;
|
||||
|
||||
/**
|
||||
* Returns only the nid from migration_lookup on node_complete migration.
|
||||
*
|
||||
* It is possible that migration_lookups that use the classic node migrations
|
||||
* in the migration key have been altered to include the complete node
|
||||
* migration. The classic node migration and complete node migration have a
|
||||
* different number of destination keys. This process plugin will ensure that
|
||||
* when the complete node migration is used in the lookup the nid value is
|
||||
* returned. This keeps the behavior the same as the classic node migration.
|
||||
*
|
||||
* @see \Drupal\migrate\Plugin\MigrateProcessInterface
|
||||
*
|
||||
* @MigrateProcessPlugin(
|
||||
* id = "node_complete_node_lookup"
|
||||
* )
|
||||
*/
|
||||
class NodeCompleteNodeLookup extends ProcessPluginBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function transform($value, MigrateExecutableInterface $migrate_executable, Row $row, $destination_property) {
|
||||
if (is_array($value) && count($value) === 3) {
|
||||
return $value[0];
|
||||
}
|
||||
return $value;
|
||||
}
|
||||
|
||||
}
|
||||
+37
@@ -0,0 +1,37 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\migrate_drupal\Plugin\migrate\process;
|
||||
|
||||
use Drupal\migrate\MigrateExecutableInterface;
|
||||
use Drupal\migrate\ProcessPluginBase;
|
||||
use Drupal\migrate\Row;
|
||||
|
||||
/**
|
||||
* Returns only the vid from migration_lookup on node_complete migration.
|
||||
*
|
||||
* It is possible that migration_lookups that use the classic node migrations
|
||||
* in the migration key have been altered to include the complete node
|
||||
* migration. The classic node migration and complete node migration have a
|
||||
* different number of destination keys. This process plugin will ensure that
|
||||
* when the complete node migration is used in the lookup the vid value is
|
||||
* returned. This keeps the behavior the same as the classic node migration.
|
||||
*
|
||||
* @see \Drupal\migrate\Plugin\MigrateProcessInterface
|
||||
*
|
||||
* @MigrateProcessPlugin(
|
||||
* id = "node_complete_node_revision_lookup"
|
||||
* )
|
||||
*/
|
||||
class NodeCompleteNodeRevisionLookup extends ProcessPluginBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function transform($value, MigrateExecutableInterface $migrate_executable, Row $row, $destination_property) {
|
||||
if (is_array($value) && count($value) === 3) {
|
||||
return $value[1];
|
||||
}
|
||||
return $value;
|
||||
}
|
||||
|
||||
}
|
||||
+39
@@ -0,0 +1,39 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\migrate_drupal\Plugin\migrate\process;
|
||||
|
||||
use Drupal\migrate\MigrateExecutableInterface;
|
||||
use Drupal\migrate\ProcessPluginBase;
|
||||
use Drupal\migrate\Row;
|
||||
|
||||
/**
|
||||
* Returns nid and langcode from migration_lookup on node_complete migration.
|
||||
*
|
||||
* It is possible that migration_lookups that use the classic node migrations
|
||||
* in the migration key have been altered to include the complete node
|
||||
* migration. The classic node migration and complete node migration have a
|
||||
* different number of destination keys. This process plugin will ensure that
|
||||
* when the complete node migration is used in the lookup the nid and langcode
|
||||
* values are returned. This keeps the behavior the same as the classic node
|
||||
* migration.
|
||||
*
|
||||
* @see \Drupal\migrate\Plugin\MigrateProcessInterface
|
||||
*
|
||||
* @MigrateProcessPlugin(
|
||||
* id = "node_complete_node_translation_lookup"
|
||||
* )
|
||||
*/
|
||||
class NodeCompleteNodeTranslationLookup extends ProcessPluginBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function transform($value, MigrateExecutableInterface $migrate_executable, Row $row, $destination_property) {
|
||||
if (is_array($value) && count($value) === 3) {
|
||||
unset($value[1]);
|
||||
return array_values($value);
|
||||
}
|
||||
return $value;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,279 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\migrate_drupal\Plugin\migrate\source;
|
||||
|
||||
use Drupal\Component\Plugin\Exception\InvalidPluginDefinitionException;
|
||||
use Drupal\Core\Entity\ContentEntityInterface;
|
||||
use Drupal\Core\Entity\ContentEntityTypeInterface;
|
||||
use Drupal\Core\Entity\EntityFieldManagerInterface;
|
||||
use Drupal\Core\Entity\EntityTypeBundleInfoInterface;
|
||||
use Drupal\Core\Entity\EntityTypeManagerInterface;
|
||||
use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
|
||||
use Drupal\migrate\EntityFieldDefinitionTrait;
|
||||
use Drupal\migrate\Plugin\migrate\source\SourcePluginBase;
|
||||
use Drupal\migrate\Plugin\MigrationInterface;
|
||||
use Symfony\Component\DependencyInjection\ContainerInterface;
|
||||
|
||||
/**
|
||||
* Source plugin to get content entities from the current version of Drupal.
|
||||
*
|
||||
* This plugin uses the Entity API to export entity data. If the source entity
|
||||
* type has custom field storage fields or computed fields, this class will need
|
||||
* to be extended and the new class will need to load/calculate the values for
|
||||
* those fields.
|
||||
*
|
||||
* Available configuration keys:
|
||||
* - entity_type: The entity type ID of the entities being exported. This is
|
||||
* calculated dynamically by the deriver so it is only needed if the deriver
|
||||
* is not utilized, i.e., a custom source plugin.
|
||||
* - bundle: (optional) If the entity type is bundleable, only return entities
|
||||
* of this bundle.
|
||||
* - include_translations: (optional) Indicates if the entity translations
|
||||
* should be included, defaults to TRUE.
|
||||
*
|
||||
* Examples:
|
||||
*
|
||||
* This will return all nodes, from every bundle and every translation. It does
|
||||
* not return all revisions, just the default one.
|
||||
* @code
|
||||
* source:
|
||||
* plugin: content_entity:node
|
||||
* @endcode
|
||||
*
|
||||
* This will only return nodes of type 'article' in their default language.
|
||||
* @code
|
||||
* source:
|
||||
* plugin: content_entity:node
|
||||
* bundle: article
|
||||
* include_translations: false
|
||||
* @endcode
|
||||
*
|
||||
* @MigrateSource(
|
||||
* id = "content_entity",
|
||||
* source_module = "migrate_drupal",
|
||||
* deriver = "\Drupal\migrate_drupal\Plugin\migrate\source\ContentEntityDeriver",
|
||||
* )
|
||||
*/
|
||||
class ContentEntity extends SourcePluginBase implements ContainerFactoryPluginInterface {
|
||||
use EntityFieldDefinitionTrait;
|
||||
|
||||
/**
|
||||
* The entity type manager.
|
||||
*
|
||||
* @var \Drupal\Core\Entity\EntityTypeManagerInterface
|
||||
*/
|
||||
protected $entityTypeManager;
|
||||
|
||||
/**
|
||||
* The entity field manager.
|
||||
*
|
||||
* @var \Drupal\Core\Entity\EntityFieldManagerInterface
|
||||
*/
|
||||
protected $entityFieldManager;
|
||||
|
||||
/**
|
||||
* The entity type bundle info service.
|
||||
*
|
||||
* @var \Drupal\Core\Entity\EntityTypeBundleInfoInterface
|
||||
*/
|
||||
protected $entityTypeBundleInfo;
|
||||
|
||||
/**
|
||||
* The entity type definition.
|
||||
*
|
||||
* @var \Drupal\Core\Entity\EntityTypeInterface
|
||||
*/
|
||||
protected $entityType;
|
||||
|
||||
/**
|
||||
* The plugin's default configuration.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $defaultConfiguration = [
|
||||
'bundle' => NULL,
|
||||
'include_translations' => TRUE,
|
||||
];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function __construct(array $configuration, $plugin_id, $plugin_definition, MigrationInterface $migration, EntityTypeManagerInterface $entity_type_manager, EntityFieldManagerInterface $entity_field_manager, EntityTypeBundleInfoInterface $entity_type_bundle_info) {
|
||||
if (empty($plugin_definition['entity_type'])) {
|
||||
throw new InvalidPluginDefinitionException($plugin_id, 'Missing required "entity_type" definition.');
|
||||
}
|
||||
$this->entityTypeManager = $entity_type_manager;
|
||||
$this->entityFieldManager = $entity_field_manager;
|
||||
$this->entityTypeBundleInfo = $entity_type_bundle_info;
|
||||
$this->entityType = $this->entityTypeManager->getDefinition($plugin_definition['entity_type']);
|
||||
if (!$this->entityType instanceof ContentEntityTypeInterface) {
|
||||
throw new InvalidPluginDefinitionException($plugin_id, sprintf('The entity type (%s) is not supported. The "content_entity" source plugin only supports content entities.', $plugin_definition['entity_type']));
|
||||
}
|
||||
if (!empty($configuration['bundle'])) {
|
||||
if (!$this->entityType->hasKey('bundle')) {
|
||||
throw new \InvalidArgumentException(sprintf('A bundle was provided but the entity type (%s) is not bundleable.', $plugin_definition['entity_type']));
|
||||
}
|
||||
$bundle_info = array_keys($this->entityTypeBundleInfo->getBundleInfo($this->entityType->id()));
|
||||
if (!in_array($configuration['bundle'], $bundle_info, TRUE)) {
|
||||
throw new \InvalidArgumentException(sprintf('The provided bundle (%s) is not valid for the (%s) entity type.', $configuration['bundle'], $plugin_definition['entity_type']));
|
||||
}
|
||||
}
|
||||
parent::__construct($configuration + $this->defaultConfiguration, $plugin_id, $plugin_definition, $migration);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@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('entity_type.manager'),
|
||||
$container->get('entity_field.manager'),
|
||||
$container->get('entity_type.bundle.info')
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function __toString() {
|
||||
return (string) $this->entityType->getPluralLabel();
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes the iterator with the source data.
|
||||
*
|
||||
* @return \Generator
|
||||
* A data generator for this source.
|
||||
*/
|
||||
protected function initializeIterator() {
|
||||
$ids = $this->query()->execute();
|
||||
return $this->yieldEntities($ids);
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads and yields entities, one at a time.
|
||||
*
|
||||
* @param array $ids
|
||||
* The entity IDs.
|
||||
*
|
||||
* @return \Generator
|
||||
* An iterable of the loaded entities.
|
||||
*/
|
||||
protected function yieldEntities(array $ids) {
|
||||
$storage = $this->entityTypeManager
|
||||
->getStorage($this->entityType->id());
|
||||
foreach ($ids as $id) {
|
||||
/** @var \Drupal\Core\Entity\ContentEntityInterface $entity */
|
||||
$entity = $storage->load($id);
|
||||
yield $this->toArray($entity);
|
||||
if ($this->configuration['include_translations']) {
|
||||
foreach ($entity->getTranslationLanguages(FALSE) as $language) {
|
||||
yield $this->toArray($entity->getTranslation($language->getId()));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts an entity to an array.
|
||||
*
|
||||
* Makes all IDs into flat values. All other values are returned as per
|
||||
* $entity->toArray(), which is a nested array.
|
||||
*
|
||||
* @param \Drupal\Core\Entity\ContentEntityInterface $entity
|
||||
* The entity to convert.
|
||||
*
|
||||
* @return array
|
||||
* The entity, represented as an array.
|
||||
*/
|
||||
protected function toArray(ContentEntityInterface $entity) {
|
||||
$return = $entity->toArray();
|
||||
// This is necessary because the IDs must be flat. They cannot be nested for
|
||||
// the ID map.
|
||||
foreach (array_keys($this->getIds()) as $id) {
|
||||
/** @var \Drupal\Core\TypedData\Plugin\DataType\ItemList $value */
|
||||
$value = $entity->get($id);
|
||||
// Force the IDs on top of the previous values.
|
||||
$return[$id] = $value->first()->getString();
|
||||
}
|
||||
return $return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Query to retrieve the entities.
|
||||
*
|
||||
* @return \Drupal\Core\Entity\Query\QueryInterface
|
||||
* The query.
|
||||
*/
|
||||
public function query() {
|
||||
$query = $this->entityTypeManager
|
||||
->getStorage($this->entityType->id())
|
||||
->getQuery()
|
||||
->accessCheck(FALSE);
|
||||
if (!empty($this->configuration['bundle'])) {
|
||||
$query->condition($this->entityType->getKey('bundle'), $this->configuration['bundle']);
|
||||
}
|
||||
return $query;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function count($refresh = FALSE) {
|
||||
// If no translations are included, then a simple query is possible.
|
||||
if (!$this->configuration['include_translations']) {
|
||||
return parent::count($refresh);
|
||||
}
|
||||
// @TODO: Determine a better way to retrieve a valid count for translations.
|
||||
// https://www.drupal.org/project/drupal/issues/2937166
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function doCount() {
|
||||
return $this->query()->count()->execute();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function fields() {
|
||||
// Retrieving fields from a non-fieldable content entity will throw a
|
||||
// LogicException. Return an empty list of fields instead.
|
||||
if (!$this->entityType->entityClassImplements('Drupal\Core\Entity\FieldableEntityInterface')) {
|
||||
return [];
|
||||
}
|
||||
$field_definitions = $this->entityFieldManager->getBaseFieldDefinitions($this->entityType->id());
|
||||
if (!empty($this->configuration['bundle'])) {
|
||||
$field_definitions += $this->entityFieldManager->getFieldDefinitions($this->entityType->id(), $this->configuration['bundle']);
|
||||
}
|
||||
$fields = array_map(function ($definition) {
|
||||
return (string) $definition->getLabel();
|
||||
}, $field_definitions);
|
||||
return $fields;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getIds() {
|
||||
$id_key = $this->entityType->getKey('id');
|
||||
$ids[$id_key] = $this->getDefinitionFromEntity($id_key);
|
||||
if ($this->entityType->isRevisionable()) {
|
||||
$revision_key = $this->entityType->getKey('revision');
|
||||
$ids[$revision_key] = $this->getDefinitionFromEntity($revision_key);
|
||||
}
|
||||
if ($this->entityType->isTranslatable()) {
|
||||
$langcode_key = $this->entityType->getKey('langcode');
|
||||
$ids[$langcode_key] = $this->getDefinitionFromEntity($langcode_key);
|
||||
}
|
||||
return $ids;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\migrate_drupal\Plugin\migrate\source;
|
||||
|
||||
use Drupal\Component\Plugin\Derivative\DeriverBase;
|
||||
use Drupal\Core\Entity\ContentEntityTypeInterface;
|
||||
use Drupal\Core\Entity\EntityTypeManagerInterface;
|
||||
use Drupal\Core\Plugin\Discovery\ContainerDeriverInterface;
|
||||
use Symfony\Component\DependencyInjection\ContainerInterface;
|
||||
|
||||
/**
|
||||
* Deriver for content entity source plugins.
|
||||
*/
|
||||
class ContentEntityDeriver extends DeriverBase implements ContainerDeriverInterface {
|
||||
|
||||
/**
|
||||
* The entity type manager.
|
||||
*
|
||||
* @var \Drupal\Core\Entity\EntityTypeManagerInterface
|
||||
*/
|
||||
protected $entityTypeManager;
|
||||
|
||||
/**
|
||||
* Constructs a new ContentEntityDeriver.
|
||||
*
|
||||
* @param string $base_plugin_id
|
||||
* The base plugin ID.
|
||||
* @param \Drupal\Core\Entity\EntityTypeManagerInterface $entityTypeManager
|
||||
* The entity type manager.
|
||||
*/
|
||||
public function __construct($base_plugin_id, EntityTypeManagerInterface $entityTypeManager) {
|
||||
$this->entityTypeManager = $entityTypeManager;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function create(ContainerInterface $container, $base_plugin_id) {
|
||||
return new static(
|
||||
$base_plugin_id,
|
||||
$container->get('entity_type.manager')
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getDerivativeDefinitions($base_plugin_definition) {
|
||||
$this->derivatives = [];
|
||||
foreach ($this->entityTypeManager->getDefinitions() as $id => $definition) {
|
||||
if ($definition instanceof ContentEntityTypeInterface) {
|
||||
$this->derivatives[$id] = $base_plugin_definition;
|
||||
// Provide entity_type so the source can be used apart from a deriver.
|
||||
$this->derivatives[$id]['entity_type'] = $id;
|
||||
}
|
||||
}
|
||||
return parent::getDerivativeDefinitions($base_plugin_definition);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,194 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\migrate_drupal\Plugin\migrate\source;
|
||||
|
||||
use Drupal\Component\Plugin\DependentPluginInterface;
|
||||
use Drupal\Core\DependencyInjection\DeprecatedServicePropertyTrait;
|
||||
use Drupal\Core\Entity\DependencyTrait;
|
||||
use Drupal\Core\Entity\EntityTypeManagerInterface;
|
||||
use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
|
||||
use Drupal\Core\State\StateInterface;
|
||||
use Drupal\migrate\Plugin\MigrationInterface;
|
||||
use Drupal\migrate\Exception\RequirementsException;
|
||||
use Drupal\migrate\Plugin\migrate\source\SqlBase;
|
||||
use Symfony\Component\DependencyInjection\ContainerInterface;
|
||||
|
||||
/**
|
||||
* A base class for source plugins using a Drupal database as a source.
|
||||
*
|
||||
* Provides general purpose helper methods that are commonly needed
|
||||
* when writing source plugins that use a Drupal database as a source, for
|
||||
* example:
|
||||
* - Check if the given module exists in the source database.
|
||||
* - Read Drupal configuration variables from the source database.
|
||||
*
|
||||
* For a full list, refer to the methods of this class.
|
||||
*
|
||||
* For available configuration keys, refer to the parent classes:
|
||||
* @see \Drupal\migrate\Plugin\migrate\source\SqlBase
|
||||
* @see \Drupal\migrate\Plugin\migrate\source\SourcePluginBase
|
||||
*/
|
||||
abstract class DrupalSqlBase extends SqlBase implements ContainerFactoryPluginInterface, DependentPluginInterface {
|
||||
|
||||
use DependencyTrait;
|
||||
use DeprecatedServicePropertyTrait;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected $deprecatedProperties = ['entityManager' => 'entity.manager'];
|
||||
|
||||
/**
|
||||
* The contents of the system table.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $systemData;
|
||||
|
||||
/**
|
||||
* If the source provider is missing.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
protected $requirements = TRUE;
|
||||
|
||||
/**
|
||||
* The entity type manager.
|
||||
*
|
||||
* @var \Drupal\Core\Entity\EntityTypeManagerInterface
|
||||
*/
|
||||
protected $entityTypeManager;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function __construct(array $configuration, $plugin_id, $plugin_definition, MigrationInterface $migration, StateInterface $state, EntityTypeManagerInterface $entity_type_manager) {
|
||||
parent::__construct($configuration, $plugin_id, $plugin_definition, $migration, $state);
|
||||
$this->entityTypeManager = $entity_type_manager;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves all system data information from the source Drupal database.
|
||||
*
|
||||
* @return array
|
||||
* List of system table information keyed by type and name.
|
||||
*/
|
||||
public function getSystemData() {
|
||||
if (!isset($this->systemData)) {
|
||||
$this->systemData = [];
|
||||
try {
|
||||
$results = $this->select('system', 's')
|
||||
->fields('s')
|
||||
->execute();
|
||||
foreach ($results as $result) {
|
||||
$this->systemData[$result['type']][$result['name']] = $result;
|
||||
}
|
||||
}
|
||||
catch (\Exception $e) {
|
||||
// The table might not exist for example in tests.
|
||||
}
|
||||
}
|
||||
return $this->systemData;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@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('state'),
|
||||
$container->get('entity_type.manager')
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function checkRequirements() {
|
||||
parent::checkRequirements();
|
||||
if ($this->pluginDefinition['requirements_met'] === TRUE) {
|
||||
if (isset($this->pluginDefinition['source_module'])) {
|
||||
if ($this->moduleExists($this->pluginDefinition['source_module'])) {
|
||||
if (isset($this->pluginDefinition['minimum_schema_version']) && !$this->getModuleSchemaVersion($this->pluginDefinition['source_module']) < $this->pluginDefinition['minimum_schema_version']) {
|
||||
throw new RequirementsException('Required minimum schema version ' . $this->pluginDefinition['minimum_schema_version'], ['minimum_schema_version' => $this->pluginDefinition['minimum_schema_version']]);
|
||||
}
|
||||
}
|
||||
else {
|
||||
throw new RequirementsException('The module ' . $this->pluginDefinition['source_module'] . ' is not enabled in the source site.', ['source_module' => $this->pluginDefinition['source_module']]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves a module schema_version from the source Drupal database.
|
||||
*
|
||||
* @param string $module
|
||||
* Name of module.
|
||||
*
|
||||
* @return mixed
|
||||
* The current module schema version on the origin system table or FALSE if
|
||||
* not found.
|
||||
*/
|
||||
protected function getModuleSchemaVersion($module) {
|
||||
$system_data = $this->getSystemData();
|
||||
return isset($system_data['module'][$module]['schema_version']) ? $system_data['module'][$module]['schema_version'] : FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if a given module is enabled in the source Drupal database.
|
||||
*
|
||||
* @param string $module
|
||||
* Name of module to check.
|
||||
*
|
||||
* @return bool
|
||||
* TRUE if module is enabled on the origin system, FALSE if not.
|
||||
*/
|
||||
protected function moduleExists($module) {
|
||||
$system_data = $this->getSystemData();
|
||||
return !empty($system_data['module'][$module]['status']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads a variable from a source Drupal database.
|
||||
*
|
||||
* @param $name
|
||||
* Name of the variable.
|
||||
* @param $default
|
||||
* The default value.
|
||||
* @return mixed
|
||||
*/
|
||||
protected function variableGet($name, $default) {
|
||||
try {
|
||||
$result = $this->select('variable', 'v')
|
||||
->fields('v', ['value'])
|
||||
->condition('name', $name)
|
||||
->execute()
|
||||
->fetchField();
|
||||
}
|
||||
// The table might not exist.
|
||||
catch (\Exception $e) {
|
||||
$result = FALSE;
|
||||
}
|
||||
return $result !== FALSE ? unserialize($result) : $default;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function calculateDependencies() {
|
||||
// Generic handling for Drupal source plugin constants.
|
||||
if (isset($this->configuration['constants']['entity_type'])) {
|
||||
$this->addDependency('module', $this->entityTypeManager->getDefinition($this->configuration['constants']['entity_type'])->getProvider());
|
||||
}
|
||||
if (isset($this->configuration['constants']['module'])) {
|
||||
$this->addDependency('module', $this->configuration['constants']['module']);
|
||||
}
|
||||
return $this->dependencies;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\migrate_drupal\Plugin\migrate\source;
|
||||
|
||||
use Drupal\Component\Plugin\DependentPluginInterface;
|
||||
use Drupal\Core\DependencyInjection\DeprecatedServicePropertyTrait;
|
||||
use Drupal\Core\Entity\DependencyTrait;
|
||||
use Symfony\Component\DependencyInjection\ContainerInterface;
|
||||
use Drupal\migrate\Plugin\MigrationInterface;
|
||||
use Drupal\migrate\Plugin\migrate\source\EmptySource as BaseEmptySource;
|
||||
use Drupal\Core\Entity\EntityTypeManagerInterface;
|
||||
use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
|
||||
|
||||
/**
|
||||
* Source returning an empty row with Drupal specific config dependencies.
|
||||
*
|
||||
* @MigrateSource(
|
||||
* id = "md_empty",
|
||||
* source_module = "system",
|
||||
* )
|
||||
*/
|
||||
class EmptySource extends BaseEmptySource implements ContainerFactoryPluginInterface, DependentPluginInterface {
|
||||
|
||||
use DependencyTrait;
|
||||
use DeprecatedServicePropertyTrait;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected $deprecatedProperties = ['entityManager' => 'entity.manager'];
|
||||
|
||||
/**
|
||||
* The entity type manager.
|
||||
*
|
||||
* @var \Drupal\Core\Entity\EntityTypeManagerInterface
|
||||
*/
|
||||
protected $entityTypeManager;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function __construct(array $configuration, $plugin_id, $plugin_definition, MigrationInterface $migration, EntityTypeManagerInterface $entity_manager) {
|
||||
parent::__construct($configuration, $plugin_id, $plugin_definition, $migration);
|
||||
$this->entityTypeManager = $entity_manager;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@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('entity_type.manager')
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function calculateDependencies() {
|
||||
// The empty source plugin supports the entity_type constant.
|
||||
if (isset($this->configuration['constants']['entity_type'])) {
|
||||
$this->addDependency('module', $this->entityTypeManager->getDefinition($this->configuration['constants']['entity_type'])->getProvider());
|
||||
}
|
||||
return $this->dependencies;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,92 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\migrate_drupal\Plugin\migrate\source;
|
||||
|
||||
use Drupal\Core\Entity\EntityTypeManagerInterface;
|
||||
use Drupal\Core\State\StateInterface;
|
||||
use Drupal\migrate\Plugin\MigrationInterface;
|
||||
|
||||
/**
|
||||
* Drupal variable source from database.
|
||||
*
|
||||
* This source class always returns a single row and as such is not a good
|
||||
* example for any normal source class returning multiple rows.
|
||||
*
|
||||
* @MigrateSource(
|
||||
* id = "variable",
|
||||
* source_module = "system",
|
||||
* )
|
||||
*/
|
||||
class Variable extends DrupalSqlBase {
|
||||
|
||||
/**
|
||||
* The variable names to fetch.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $variables;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function __construct(array $configuration, $plugin_id, $plugin_definition, MigrationInterface $migration, StateInterface $state, EntityTypeManagerInterface $entity_type_manager) {
|
||||
parent::__construct($configuration, $plugin_id, $plugin_definition, $migration, $state, $entity_type_manager);
|
||||
$this->variables = $this->configuration['variables'];
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function initializeIterator() {
|
||||
return new \ArrayIterator([$this->values()]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the values of the variables specified in the plugin configuration.
|
||||
*
|
||||
* @return array
|
||||
* An associative array where the keys are the variables specified in the
|
||||
* plugin configuration and the values are the values found in the source.
|
||||
* Only those values are returned that are actually in the database.
|
||||
*/
|
||||
protected function values() {
|
||||
// Create an ID field so we can record migration in the map table.
|
||||
// Arbitrarily, use the first variable name.
|
||||
$values['id'] = reset($this->variables);
|
||||
return $values + array_map('unserialize', $this->prepareQuery()->execute()->fetchAllKeyed());
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function count($refresh = FALSE) {
|
||||
// Variable always returns a single row with at minimum an 'id' property.
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function fields() {
|
||||
return array_combine($this->variables, $this->variables);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function query() {
|
||||
return $this->getDatabase()
|
||||
->select('variable', 'v')
|
||||
->fields('v', ['name', 'value'])
|
||||
->condition('name', $this->variables, 'IN');
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getIds() {
|
||||
$ids['id']['type'] = 'string';
|
||||
return $ids;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\migrate_drupal\Plugin\migrate\source;
|
||||
|
||||
use Drupal\migrate\Row;
|
||||
|
||||
/**
|
||||
* Multiple variables source from database.
|
||||
*
|
||||
* Unlike the variable source plugin, this one returns one row per
|
||||
* variable.
|
||||
*
|
||||
* @MigrateSource(
|
||||
* id = "variable_multirow",
|
||||
* source_module = "system",
|
||||
* )
|
||||
*/
|
||||
class VariableMultiRow extends DrupalSqlBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function query() {
|
||||
return $this->select('variable', 'v')
|
||||
->fields('v', ['name', 'value'])
|
||||
// Cast scalars to array so we can consistently use an IN condition.
|
||||
->condition('name', (array) $this->configuration['variables'], 'IN');
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function fields() {
|
||||
return [
|
||||
'name' => $this->t('Name'),
|
||||
'value' => $this->t('Value'),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function prepareRow(Row $row) {
|
||||
if ($value = $row->getSourceProperty('value')) {
|
||||
$row->setSourceProperty('value', unserialize($value));
|
||||
}
|
||||
return parent::prepareRow($row);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getIds() {
|
||||
$ids['name']['type'] = 'string';
|
||||
return $ids;
|
||||
}
|
||||
|
||||
}
|
||||
+32
@@ -0,0 +1,32 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\migrate_drupal\Plugin\migrate\source\d6;
|
||||
|
||||
use Drupal\Core\Entity\EntityTypeManagerInterface;
|
||||
use Drupal\Core\State\StateInterface;
|
||||
use Drupal\migrate\Plugin\MigrationInterface;
|
||||
|
||||
/**
|
||||
* Gets Drupal i18n_variable source from database.
|
||||
*
|
||||
* @deprecated in drupal:8.7.0 and is removed from drupal:9.0.0.
|
||||
* Use \Drupal\migrate_drupal\Plugin\migrate\source\d6\VariableTranslation.
|
||||
*
|
||||
* @see https://www.drupal.org/node/3006487
|
||||
*
|
||||
* @MigrateSource(
|
||||
* id = "variable_translation",
|
||||
* source_module = "system",
|
||||
* )
|
||||
*/
|
||||
class D6VariableTranslation extends VariableTranslation {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function __construct(array $configuration, $plugin_id, $plugin_definition, MigrationInterface $migration, StateInterface $state, EntityTypeManagerInterface $entity_type_manager) {
|
||||
@trigger_error('The ' . __NAMESPACE__ . '\D6VariableTranslation is deprecated in Drupal 8.7.0 and will be removed before Drupal 9.0.0. Instead, use ' . __NAMESPACE__ . '\VariableTranslation. See https://www.drupal.org/node/3006487.', E_USER_DEPRECATED);
|
||||
parent::__construct($configuration, $plugin_id, $plugin_definition, $migration, $state, $entity_type_manager);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,112 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\migrate_drupal\Plugin\migrate\source\d6;
|
||||
|
||||
use Drupal\Core\Entity\EntityTypeManagerInterface;
|
||||
use Drupal\Core\State\StateInterface;
|
||||
use Drupal\migrate\Exception\RequirementsException;
|
||||
use Drupal\migrate\Plugin\MigrationInterface;
|
||||
use Drupal\migrate_drupal\Plugin\migrate\source\DrupalSqlBase;
|
||||
|
||||
/**
|
||||
* Drupal i18n_variable source from database.
|
||||
*
|
||||
* @MigrateSource(
|
||||
* id = "d6_variable_translation",
|
||||
* source_module = "i18n",
|
||||
* )
|
||||
*/
|
||||
class VariableTranslation extends DrupalSqlBase {
|
||||
|
||||
/**
|
||||
* The variable names to fetch.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $variables;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function __construct(array $configuration, $plugin_id, $plugin_definition, MigrationInterface $migration, StateInterface $state, EntityTypeManagerInterface $entity_type_manager) {
|
||||
parent::__construct($configuration, $plugin_id, $plugin_definition, $migration, $state, $entity_type_manager);
|
||||
$this->variables = $this->configuration['variables'];
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function initializeIterator() {
|
||||
return new \ArrayIterator($this->values());
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the values of the variables specified in the plugin configuration.
|
||||
*
|
||||
* @return array
|
||||
* An associative array where the keys are the variables specified in the
|
||||
* plugin configuration and the values are the values found in the source.
|
||||
* A key/value pair is added for the language code. Only those values are
|
||||
* returned that are actually in the database.
|
||||
*/
|
||||
protected function values() {
|
||||
$values = [];
|
||||
$result = $this->prepareQuery()->execute()->FetchAllAssoc('language');
|
||||
foreach ($result as $i18n_variable) {
|
||||
$values[]['language'] = $i18n_variable->language;
|
||||
}
|
||||
$result = $this->prepareQuery()->execute()->FetchAll();
|
||||
foreach ($result as $i18n_variable) {
|
||||
foreach ($values as $key => $value) {
|
||||
if ($values[$key]['language'] === $i18n_variable->language) {
|
||||
$values[$key][$i18n_variable->name] = unserialize($i18n_variable->value);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return $values;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function count($refresh = FALSE) {
|
||||
return $this->initializeIterator()->count();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function fields() {
|
||||
return array_combine($this->variables, $this->variables);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function query() {
|
||||
return $this->getDatabase()
|
||||
->select('i18n_variable', 'v')
|
||||
->fields('v')
|
||||
->condition('name', (array) $this->configuration['variables'], 'IN');
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getIds() {
|
||||
$ids['language']['type'] = 'string';
|
||||
return $ids;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function checkRequirements() {
|
||||
if (!$this->getDatabase()->schema()->tableExists('i18n_variable')) {
|
||||
throw new RequirementsException("Source database table 'i18n_variable' does not exist");
|
||||
}
|
||||
parent::checkRequirements();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\migrate_drupal\Plugin\migrate\source\d6;
|
||||
|
||||
@trigger_error('The ' . __NAMESPACE__ . '\i18nVariable is deprecated in Drupal 8.4.0 and will be removed before Drupal 9.0.0. Instead, use ' . __NAMESPACE__ . '\VariableTranslation', E_USER_DEPRECATED);
|
||||
|
||||
/**
|
||||
* Drupal i18n_variable source from database.
|
||||
*
|
||||
* @MigrateSource(
|
||||
* id = "i18n_variable",
|
||||
* source_module = "system",
|
||||
* )
|
||||
*
|
||||
* @deprecated in drupal:8.4.0 and is removed from drupal:9.0.0. Use
|
||||
* \Drupal\migrate_drupal\Plugin\migrate\source\d6\VariableTranslation instead.
|
||||
*
|
||||
* @see https://www.drupal.org/node/2898649
|
||||
*/
|
||||
class i18nVariable extends VariableTranslation {}
|
||||
@@ -0,0 +1,124 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\migrate_drupal\Plugin\migrate\source\d7;
|
||||
|
||||
use Drupal\migrate_drupal\Plugin\migrate\source\DrupalSqlBase;
|
||||
|
||||
/**
|
||||
* Base class for D7 source plugins which need to collect field values from
|
||||
* the Field API.
|
||||
*/
|
||||
abstract class FieldableEntity extends DrupalSqlBase {
|
||||
|
||||
/**
|
||||
* Returns all non-deleted field instances attached to a specific entity type.
|
||||
*
|
||||
* @param string $entity_type
|
||||
* The entity type ID.
|
||||
* @param string|null $bundle
|
||||
* (optional) The bundle.
|
||||
*
|
||||
* @return array[]
|
||||
* The field instances, keyed by field name.
|
||||
*/
|
||||
protected function getFields($entity_type, $bundle = NULL) {
|
||||
$query = $this->select('field_config_instance', 'fci')
|
||||
->fields('fci')
|
||||
->condition('fci.entity_type', $entity_type)
|
||||
->condition('fci.bundle', isset($bundle) ? $bundle : $entity_type)
|
||||
->condition('fci.deleted', 0);
|
||||
|
||||
// Join the 'field_config' table and add the 'translatable' setting to the
|
||||
// query.
|
||||
$query->leftJoin('field_config', 'fc', 'fci.field_id = fc.id');
|
||||
$query->addField('fc', 'translatable');
|
||||
|
||||
return $query->execute()->fetchAllAssoc('field_name');
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves field values for a single field of a single entity.
|
||||
*
|
||||
* @param string $entity_type
|
||||
* The entity type.
|
||||
* @param string $field
|
||||
* The field name.
|
||||
* @param int $entity_id
|
||||
* The entity ID.
|
||||
* @param int|null $revision_id
|
||||
* (optional) The entity revision ID.
|
||||
* @param string $language
|
||||
* (optional) The field language.
|
||||
*
|
||||
* @return array
|
||||
* The raw field values, keyed by delta.
|
||||
*/
|
||||
protected function getFieldValues($entity_type, $field, $entity_id, $revision_id = NULL, $language = NULL) {
|
||||
$table = (isset($revision_id) ? 'field_revision_' : 'field_data_') . $field;
|
||||
$query = $this->select($table, 't')
|
||||
->fields('t')
|
||||
->condition('entity_type', $entity_type)
|
||||
->condition('entity_id', $entity_id)
|
||||
->condition('deleted', 0);
|
||||
if (isset($revision_id)) {
|
||||
$query->condition('revision_id', $revision_id);
|
||||
}
|
||||
// Add 'language' as a query condition if it has been defined by Entity
|
||||
// Translation.
|
||||
if ($language) {
|
||||
$query->condition('language', $language);
|
||||
}
|
||||
$values = [];
|
||||
foreach ($query->execute() as $row) {
|
||||
foreach ($row as $key => $value) {
|
||||
$delta = $row['delta'];
|
||||
if (strpos($key, $field) === 0) {
|
||||
$column = substr($key, strlen($field) + 1);
|
||||
$values[$delta][$column] = $value;
|
||||
}
|
||||
}
|
||||
}
|
||||
return $values;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if an entity type uses Entity Translation.
|
||||
*
|
||||
* @param string $entity_type
|
||||
* The entity type.
|
||||
*
|
||||
* @return bool
|
||||
* Whether the entity type uses entity translation.
|
||||
*/
|
||||
protected function isEntityTranslatable($entity_type) {
|
||||
return in_array($entity_type, $this->variableGet('entity_translation_entity_types', []), TRUE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets an entity source language from the 'entity_translation' table.
|
||||
*
|
||||
* @param string $entity_type
|
||||
* The entity type.
|
||||
* @param int $entity_id
|
||||
* The entity ID.
|
||||
*
|
||||
* @return string|bool
|
||||
* The entity source language or FALSE if no source language was found.
|
||||
*/
|
||||
protected function getEntityTranslationSourceLanguage($entity_type, $entity_id) {
|
||||
try {
|
||||
return $this->select('entity_translation', 'et')
|
||||
->fields('et', ['language'])
|
||||
->condition('entity_type', $entity_type)
|
||||
->condition('entity_id', $entity_id)
|
||||
->condition('source', '')
|
||||
->execute()
|
||||
->fetchField();
|
||||
}
|
||||
// The table might not exist.
|
||||
catch (\Exception $e) {
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,106 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\migrate_drupal\Plugin\migrate\source\d7;
|
||||
|
||||
use Drupal\Core\Entity\EntityTypeManagerInterface;
|
||||
use Drupal\Core\State\StateInterface;
|
||||
use Drupal\migrate\Plugin\MigrationInterface;
|
||||
use Drupal\migrate_drupal\Plugin\migrate\source\DrupalSqlBase;
|
||||
|
||||
/**
|
||||
* Gets Drupal variable_store source from database.
|
||||
*
|
||||
* @MigrateSource(
|
||||
* id = "d7_variable_translation",
|
||||
* source_module = "i18n_variable",
|
||||
* )
|
||||
*/
|
||||
class VariableTranslation extends DrupalSqlBase {
|
||||
/**
|
||||
* The variable names to fetch.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $variables;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function __construct(array $configuration, $plugin_id, $plugin_definition, MigrationInterface $migration, StateInterface $state, EntityTypeManagerInterface $entity_type_manager) {
|
||||
parent::__construct($configuration, $plugin_id, $plugin_definition, $migration, $state, $entity_type_manager);
|
||||
$this->variables = $this->configuration['variables'];
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function initializeIterator() {
|
||||
return new \ArrayIterator($this->values());
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the values of the variables specified in the plugin configuration.
|
||||
*
|
||||
* @return array
|
||||
* An associative array where the keys are the variables specified in the
|
||||
* plugin configuration and the values are the values found in the source.
|
||||
* A key/value pair is added for the language code. Only those values are
|
||||
* returned that are actually in the database.
|
||||
*/
|
||||
protected function values() {
|
||||
$values = [];
|
||||
$result = $this->prepareQuery()->execute()->FetchAllAssoc('realm_key');
|
||||
foreach ($result as $variable_store) {
|
||||
$values[]['language'] = $variable_store['realm_key'];
|
||||
}
|
||||
$result = $this->prepareQuery()->execute()->FetchAll();
|
||||
foreach ($result as $variable_store) {
|
||||
foreach ($values as $key => $value) {
|
||||
if ($values[$key]['language'] === $variable_store['realm_key']) {
|
||||
if ($variable_store['serialized']) {
|
||||
$values[$key][$variable_store['name']] = unserialize($variable_store['value']);
|
||||
break;
|
||||
}
|
||||
else {
|
||||
$values[$key][$variable_store['name']] = $variable_store['value'];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return $values;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function count($refresh = FALSE) {
|
||||
return $this->initializeIterator()->count();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function fields() {
|
||||
return array_combine($this->variables, $this->variables);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getIds() {
|
||||
$ids['language']['type'] = 'string';
|
||||
return $ids;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function query() {
|
||||
return $this->select('variable_store', 'vs')
|
||||
->fields('vs')
|
||||
->condition('realm', 'language')
|
||||
->condition('name', (array) $this->configuration['variables'], 'IN');
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\migrate_drupal\Plugin\migrate\source\d8;
|
||||
|
||||
use Drupal\migrate\Row;
|
||||
use Drupal\migrate_drupal\Plugin\migrate\source\DrupalSqlBase;
|
||||
|
||||
/**
|
||||
* Drupal config source from database.
|
||||
*
|
||||
* @MigrateSource(
|
||||
* id = "d8_config",
|
||||
* source_module = "system",
|
||||
* )
|
||||
*/
|
||||
class Config extends DrupalSqlBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function query() {
|
||||
$query = $this->select('config', 'c')
|
||||
->fields('c', ['collection', 'name', 'data']);
|
||||
if (!empty($this->configuration['collections'])) {
|
||||
$query->condition('collection', (array) $this->configuration['collections'], 'IN');
|
||||
}
|
||||
if (!empty($this->configuration['names'])) {
|
||||
$query->condition('name', (array) $this->configuration['names'], 'IN');
|
||||
}
|
||||
return $query;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function prepareRow(Row $row) {
|
||||
$row->setSourceProperty('data', unserialize($row->getSourceProperty('data')));
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function fields() {
|
||||
return [
|
||||
'collection' => $this->t('The config object collection.'),
|
||||
'name' => $this->t('The config object name.'),
|
||||
'data' => $this->t('Serialized configuration object data.'),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getIds() {
|
||||
$ids['collection']['type'] = 'string';
|
||||
$ids['name']['type'] = 'string';
|
||||
return $ids;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\migrate_drupal\Tests;
|
||||
|
||||
use Drupal\migrate\Row;
|
||||
|
||||
/**
|
||||
* Provides common functionality for testing stubbing.
|
||||
*/
|
||||
trait StubTestTrait {
|
||||
|
||||
/**
|
||||
* Test that creating a stub of the given entity type results in a valid
|
||||
* entity.
|
||||
*
|
||||
* @param string $entity_type_id
|
||||
* The entity type we are stubbing.
|
||||
*/
|
||||
protected function performStubTest($entity_type_id) {
|
||||
$entity_id = $this->createEntityStub($entity_type_id);
|
||||
$this->assertNotEmpty($entity_id, 'Stub successfully created');
|
||||
// When validateStub fails, it will return an array with the violations.
|
||||
$this->assertEmpty($this->validateStub($entity_type_id, $entity_id));
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a stub of the given entity type.
|
||||
*
|
||||
* @param string $entity_type_id
|
||||
* The entity type we are stubbing.
|
||||
*
|
||||
* @return int
|
||||
* ID of the created entity.
|
||||
*/
|
||||
protected function createEntityStub($entity_type_id) {
|
||||
// Create a dummy migration to pass to the destination plugin.
|
||||
$definition = [
|
||||
'migration_tags' => ['Stub test'],
|
||||
'source' => ['plugin' => 'empty'],
|
||||
'process' => [],
|
||||
'destination' => ['plugin' => 'entity:' . $entity_type_id],
|
||||
];
|
||||
$migration = \Drupal::service('plugin.manager.migration')->createStubMigration($definition);
|
||||
$destination_plugin = $migration->getDestinationPlugin(TRUE);
|
||||
$stub_row = new Row([], [], TRUE);
|
||||
$destination_ids = $destination_plugin->import($stub_row);
|
||||
return reset($destination_ids);
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform validation on a stub entity.
|
||||
*
|
||||
* @param string $entity_type_id
|
||||
* The entity type we are stubbing.
|
||||
* @param string $entity_id
|
||||
* ID of the stubbed entity to validate.
|
||||
*
|
||||
* @return \Drupal\Core\Entity\EntityConstraintViolationListInterface
|
||||
* List of constraint violations identified.
|
||||
*/
|
||||
protected function validateStub($entity_type_id, $entity_id) {
|
||||
$controller = \Drupal::entityTypeManager()->getStorage($entity_type_id);
|
||||
/** @var \Drupal\Core\Entity\ContentEntityInterface $stub_entity */
|
||||
$stub_entity = $controller->load($entity_id);
|
||||
return $stub_entity->validate();
|
||||
}
|
||||
|
||||
}
|
||||
Vendored
+36
@@ -0,0 +1,36 @@
|
||||
<?php
|
||||
// @codingStandardsIgnoreFile
|
||||
|
||||
use Drupal\Core\Database\Database;
|
||||
|
||||
$connection = Database::getConnection();
|
||||
|
||||
// Set the schema version.
|
||||
$connection->merge('key_value')
|
||||
->fields([
|
||||
'value' => 'i:8000;',
|
||||
'name' => 'migrate_drupal_multilingual',
|
||||
'collection' => 'system.schema',
|
||||
])
|
||||
->condition('collection', 'system.schema')
|
||||
->condition('name', 'migrate_drupal_multilingual')
|
||||
->execute();
|
||||
|
||||
// Update core.extension.
|
||||
$extensions = $connection->select('config')
|
||||
->fields('config', ['data'])
|
||||
->condition('collection', '')
|
||||
->condition('name', 'core.extension')
|
||||
->execute()
|
||||
->fetchField();
|
||||
$extensions = unserialize($extensions);
|
||||
$extensions['module']['migrate_drupal_multilingual'] = 8000;
|
||||
$connection->update('config')
|
||||
->fields([
|
||||
'data' => serialize($extensions),
|
||||
'collection' => '',
|
||||
'name' => 'core.extension',
|
||||
])
|
||||
->condition('collection', '')
|
||||
->condition('name', 'core.extension')
|
||||
->execute();
|
||||
+50442
File diff suppressed because it is too large
Load Diff
+57799
File diff suppressed because one or more lines are too long
+6
@@ -0,0 +1,6 @@
|
||||
name: 'Migrate drupal field discovery tet'
|
||||
type: module
|
||||
description: 'Module containing a test class exposing protected field discovery methods'
|
||||
package: Testing
|
||||
version: VERSION
|
||||
core: 8.x
|
||||
+93
@@ -0,0 +1,93 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\field_discovery_test;
|
||||
|
||||
use Drupal\migrate\Plugin\MigrationPluginManagerInterface;
|
||||
use Drupal\migrate_drupal\FieldDiscovery;
|
||||
use Drupal\migrate\Plugin\MigrationInterface;
|
||||
use Drupal\migrate_drupal\Plugin\MigrateFieldPluginManagerInterface;
|
||||
use Psr\Log\LoggerInterface;
|
||||
|
||||
/**
|
||||
* A test class to expose protected methods.
|
||||
*/
|
||||
class FieldDiscoveryTestClass extends FieldDiscovery {
|
||||
|
||||
/**
|
||||
* An array of test data.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $testData;
|
||||
|
||||
/**
|
||||
* Constructs a FieldDiscoveryTestClass object.
|
||||
*
|
||||
* @param \Drupal\migrate_drupal\Plugin\MigrateFieldPluginManagerInterface $field_plugin_manager
|
||||
* The field plugin manager.
|
||||
* @param \Drupal\migrate\Plugin\MigrationPluginManagerInterface $migration_plugin_manager
|
||||
* The migration plugin manager.
|
||||
* @param \Psr\Log\LoggerInterface $logger
|
||||
* The logger.
|
||||
* @param array $test_data
|
||||
* An array of test data, keyed by method name, for overridden methods to
|
||||
* return for the purposes of testing other methods.
|
||||
*/
|
||||
public function __construct(MigrateFieldPluginManagerInterface $field_plugin_manager, MigrationPluginManagerInterface $migration_plugin_manager, LoggerInterface $logger, array $test_data = []) {
|
||||
parent::__construct($field_plugin_manager, $migration_plugin_manager, $logger);
|
||||
$this->testData = $test_data;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getAllFields($core) {
|
||||
if (!empty($this->testData['getAllFields'][$core])) {
|
||||
return $this->testData['getAllFields'][$core];
|
||||
}
|
||||
return parent::getAllFields($core);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getBundleFields($core, $entity_type_id, $bundle) {
|
||||
return parent::getBundleFields($core, $entity_type_id, $bundle);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getEntityFields($core, $entity_type_id) {
|
||||
return parent::getEntityFields($core, $entity_type_id);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getFieldInstanceStubMigrationDefinition($core) {
|
||||
return parent::getFieldInstanceStubMigrationDefinition($core);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getCoreVersion(MigrationInterface $migration) {
|
||||
return parent::getCoreVersion($migration);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getFieldPlugin($field_type, MigrationInterface $migration) {
|
||||
return parent::getFieldPlugin($field_type, $migration);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getSourcePlugin($core) {
|
||||
return parent::getSourcePlugin($core);
|
||||
}
|
||||
|
||||
}
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
name: 'Migrate cck field plugin manager test'
|
||||
type: module
|
||||
description: 'Example module demonstrating the cck field plugin manager in the Migrate API.'
|
||||
package: Testing
|
||||
version: VERSION
|
||||
core: 8.x
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Module for Migrate CCK Field Plugin Manager testing.
|
||||
*/
|
||||
|
||||
use Drupal\migrate_cckfield_plugin_manager_test\Plugin\migrate\cckfield\D6FileField;
|
||||
|
||||
function migrate_cckfield_plugin_manager_test_migrate_field_info_alter(array &$definitions) {
|
||||
if (isset($definitions['filefield'])) {
|
||||
$definitions['filefield']['class'] = D6FileField::class;
|
||||
}
|
||||
}
|
||||
+30
@@ -0,0 +1,30 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\migrate_cckfield_plugin_manager_test\Plugin\migrate\cckfield;
|
||||
|
||||
use Drupal\migrate_drupal\Plugin\migrate\cckfield\CckFieldPluginBase;
|
||||
use Drupal\migrate\Plugin\MigrationInterface;
|
||||
|
||||
/**
|
||||
* @MigrateCckField(
|
||||
* id = "d6_file",
|
||||
* core = {6},
|
||||
* type_map = {
|
||||
* "file" = "file"
|
||||
* },
|
||||
* source_module = "foo",
|
||||
* destination_module = "bar"
|
||||
* )
|
||||
*/
|
||||
class D6FileField extends CckFieldPluginBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function processCckFieldValues(MigrationInterface $migration, $field_name, $data) {
|
||||
$migration->setProcessOfProperty($field_name, [
|
||||
'class' => static::class,
|
||||
]);
|
||||
}
|
||||
|
||||
}
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\migrate_cckfield_plugin_manager_test\Plugin\migrate\cckfield;
|
||||
|
||||
use Drupal\migrate_drupal\Plugin\migrate\cckfield\CckFieldPluginBase;
|
||||
use Drupal\migrate\Plugin\MigrationInterface;
|
||||
|
||||
/**
|
||||
* @MigrateCckField(
|
||||
* id = "d6_no_core_version_specified",
|
||||
* source_module = "foo",
|
||||
* destination_module = "bar",
|
||||
* )
|
||||
*/
|
||||
class D6NoCoreVersionSpecified extends CckFieldPluginBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function processCckFieldValues(MigrationInterface $migration, $field_name, $data) {}
|
||||
|
||||
}
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
name: 'Migrate field plugin manager test'
|
||||
type: module
|
||||
description: 'Example module demonstrating the field plugin manager in the Migrate API.'
|
||||
package: Testing
|
||||
version: VERSION
|
||||
core: 8.x
|
||||
+18
@@ -0,0 +1,18 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\migrate_field_plugin_manager_test\Plugin\migrate\field;
|
||||
|
||||
use Drupal\migrate_drupal\Plugin\migrate\field\FieldPluginBase;
|
||||
|
||||
/**
|
||||
* @MigrateField(
|
||||
* id = "d6_file",
|
||||
* core = {6},
|
||||
* type_map = {
|
||||
* "file" = "file"
|
||||
* },
|
||||
* source_module = "foo",
|
||||
* destination_module = "bar"
|
||||
* )
|
||||
*/
|
||||
class D6FileField extends FieldPluginBase {}
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\migrate_field_plugin_manager_test\Plugin\migrate\field;
|
||||
|
||||
use Drupal\migrate_drupal\Plugin\migrate\field\FieldPluginBase;
|
||||
|
||||
/**
|
||||
* @MigrateField(
|
||||
* id = "d6_no_core_version_specified",
|
||||
* source_module = "foo",
|
||||
* destination_module = "bar",
|
||||
* )
|
||||
*/
|
||||
class D6NoCoreVersionSpecified extends FieldPluginBase {}
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
name: 'Migrate property overwrite test'
|
||||
type: module
|
||||
description: 'Example module demonstrating property overwrite support in the Migrate API.'
|
||||
package: Testing
|
||||
version: VERSION
|
||||
core: 8.x
|
||||
+31
@@ -0,0 +1,31 @@
|
||||
id: users
|
||||
label: User migration
|
||||
migration_tags:
|
||||
- Drupal 6
|
||||
- Drupal 7
|
||||
source:
|
||||
plugin: d6_user
|
||||
process:
|
||||
# If the entity's ID is migrated, the Migrate API will try to update
|
||||
# an existing entity with that ID. If no entity with that ID already
|
||||
# exists, it will be created.
|
||||
uid: uid
|
||||
name: name
|
||||
mail: mail
|
||||
password: password
|
||||
'signature/value':
|
||||
plugin: default_value
|
||||
default_value: 'The answer is 42.'
|
||||
destination:
|
||||
plugin: entity:user
|
||||
# If the destination is going to update an existing user, you can optionally
|
||||
# specify the properties that should be overwritten. For example, if the
|
||||
# migration tries to import user 31 and user 31 already exists in the
|
||||
# destination database, only the 'name' and 'mail' properties of the user
|
||||
# will be overwritten. If user 31 doesn't exist, it will be created and
|
||||
# the overwrite_properties list will be ignored.
|
||||
overwrite_properties:
|
||||
- name
|
||||
- mail
|
||||
# It's possible to overwrite nested properties too.
|
||||
- 'signature/value'
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
name: Migrate state active test
|
||||
type: module
|
||||
description: Tests the 'active' migrate state
|
||||
package: Testing
|
||||
version: VERSION
|
||||
core: 8.x
|
||||
+19
@@ -0,0 +1,19 @@
|
||||
id: migrate_state_finished_test
|
||||
label: Block content body field configuration
|
||||
migration_tags:
|
||||
- Drupal 6
|
||||
- Drupal 7
|
||||
- Configuration
|
||||
source:
|
||||
plugin: embedded_data
|
||||
data_rows:
|
||||
-
|
||||
id: 1
|
||||
ids:
|
||||
id:
|
||||
type: string
|
||||
source_module: action
|
||||
process: []
|
||||
destination:
|
||||
plugin: entity:field_config
|
||||
destination_module: migrate_state_finished_test
|
||||
+19
@@ -0,0 +1,19 @@
|
||||
id: migrate_state_finished_test1
|
||||
label: Block content body field configuration
|
||||
migration_tags:
|
||||
- Drupal 6
|
||||
- Drupal 7
|
||||
- Configuration
|
||||
source:
|
||||
plugin: embedded_data
|
||||
data_rows:
|
||||
-
|
||||
id: 1
|
||||
ids:
|
||||
id:
|
||||
type: string
|
||||
source_module: action
|
||||
process: []
|
||||
destination:
|
||||
plugin: entity:field_config
|
||||
destination_module: migrate_state_not_finished_test
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
finished:
|
||||
6:
|
||||
# A field migration
|
||||
# migrate_state_finished_test: migrate_state_finished_test
|
||||
aggregator: migrate_state_finished_test
|
||||
action:
|
||||
- migrate_state_finished_test
|
||||
- migrate_state_not_finished_test
|
||||
7:
|
||||
# A field migration
|
||||
# migrate_state_finished_test: migrate_state_finished_test
|
||||
aggregator: migrate_state_finished_test
|
||||
# Migrations
|
||||
action:
|
||||
- migrate_state_finished_test
|
||||
- migrate_state_not_finished_test
|
||||
not_finished:
|
||||
7:
|
||||
# Migrations
|
||||
action: system
|
||||
+18
@@ -0,0 +1,18 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\migrate_state_active_test\Plugin\migrate\field\d7;
|
||||
|
||||
use Drupal\migrate_drupal\Plugin\migrate\field\FieldPluginBase;
|
||||
|
||||
/**
|
||||
* Field migration for testing migration states.
|
||||
*
|
||||
* @MigrateField(
|
||||
* id = "fieldleft",
|
||||
* core = {6,7},
|
||||
* source_module = "aggregator",
|
||||
* destination_module = "migrate_state_finished_test"
|
||||
* )
|
||||
*/
|
||||
class FieldLeft extends FieldPluginBase {
|
||||
}
|
||||
+18
@@ -0,0 +1,18 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\migrate_state_active_test\Plugin\migrate\field\d7;
|
||||
|
||||
use Drupal\migrate_drupal\Plugin\migrate\field\FieldPluginBase;
|
||||
|
||||
/**
|
||||
* Field migration for testing migration states.
|
||||
*
|
||||
* @MigrateField(
|
||||
* id = "fieldright",
|
||||
* core = {6,7},
|
||||
* source_module = "aggregator",
|
||||
* destination_module = "migrate_state_finished_test"
|
||||
* )
|
||||
*/
|
||||
class FieldRight extends FieldPluginBase {
|
||||
}
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
name: Migrate state no migrate_drupal.yml file test
|
||||
type: module
|
||||
description: Has a migration but Does not have a migrate_drupal.yml file.
|
||||
package: Testing
|
||||
version: VERSION
|
||||
core: 8.x
|
||||
+19
@@ -0,0 +1,19 @@
|
||||
id: migrate_state_no_file_test
|
||||
label: Test
|
||||
migration_tags:
|
||||
- Drupal 6
|
||||
- Drupal 7
|
||||
- Configuration
|
||||
source:
|
||||
plugin: embedded_data
|
||||
data_rows:
|
||||
-
|
||||
id: 1
|
||||
ids:
|
||||
id:
|
||||
type: string
|
||||
source_module: migrate_state_no_file_test
|
||||
process: []
|
||||
destination:
|
||||
plugin: entity:field_config
|
||||
destination_module: migrate_state_no_file_test
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
name: Migrate state no migration and no migrate_drupal.yml file test
|
||||
type: module
|
||||
description: Does not have a migration or migrate_drupal.yml file.
|
||||
package: Testing
|
||||
version: VERSION
|
||||
core: 8.x
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
name: Migrate state incomplete test
|
||||
type: module
|
||||
description: Tests the 'incomplete' migrate state
|
||||
package: Testing
|
||||
version: VERSION
|
||||
core: 8.x
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
id: migrate_state_not_finished_test
|
||||
label: Migrate state incomplete test
|
||||
migration_tags:
|
||||
- Drupal 6
|
||||
- Drupal 7
|
||||
- Configuration
|
||||
source:
|
||||
plugin: embedded_data
|
||||
data_rows:
|
||||
-
|
||||
entity_type: block_content
|
||||
ids:
|
||||
entity_type:
|
||||
type: string
|
||||
source_module: block
|
||||
process:
|
||||
entity_type: entity_type
|
||||
destination:
|
||||
plugin: entity:field_config
|
||||
destination_module: migrate_state_not_finished_test
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
not_finished:
|
||||
6:
|
||||
block: migrate_state_not_finished_test
|
||||
7:
|
||||
# Override any finished declarations for this field plugin.
|
||||
aggregator: field_left
|
||||
# Override any finished declarations for this migration.
|
||||
action: migrate_state_not_finished_test
|
||||
block: migrate_state_not_finished_test
|
||||
@@ -0,0 +1,38 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\Tests\migrate_drupal\Functional;
|
||||
|
||||
use Drupal\FunctionalTests\Update\UpdatePathTestBase;
|
||||
|
||||
/**
|
||||
* Tests that migrate_drupal_multilingual is uninstalled.
|
||||
*
|
||||
* @group migrate_drupal
|
||||
* @group legacy
|
||||
*/
|
||||
class MigrateDrupalUpdateTest extends UpdatePathTestBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setDatabaseDumpFiles() {
|
||||
$this->databaseDumpFiles = [
|
||||
__DIR__ . '/../../../../system/tests/fixtures/update/drupal-8.8.0.filled.standard.php.gz',
|
||||
__DIR__ . '/../../fixtures/drupal-8.migrate-drupal-multilingual-enabled.php',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests migrate_drupal_multilingual uninstallation.
|
||||
*
|
||||
* @see migrate_drupal_post_update_uninstall_multilingual()
|
||||
*/
|
||||
public function testSourceFeedRequired() {
|
||||
$this->assertTrue(\Drupal::moduleHandler()->moduleExists('migrate_drupal_multilingual'));
|
||||
// Run updates.
|
||||
$this->runUpdates();
|
||||
|
||||
$this->assertFalse(\Drupal::moduleHandler()->moduleExists('migrate_drupal_multilingual'));
|
||||
}
|
||||
|
||||
}
|
||||
+32
@@ -0,0 +1,32 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\Tests\migrate_drupal\Kernel;
|
||||
|
||||
use Drupal\migrate_cckfield_plugin_manager_test\Plugin\migrate\cckfield\D6FileField;
|
||||
use Drupal\Tests\migrate_drupal\Kernel\d6\MigrateDrupal6TestBase;
|
||||
|
||||
/**
|
||||
* @group migrate_drupal
|
||||
* @group legacy
|
||||
*/
|
||||
class CckFieldBackwardsCompatibilityTest extends MigrateDrupal6TestBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static $modules = ['file', 'migrate_cckfield_plugin_manager_test'];
|
||||
|
||||
/**
|
||||
* Ensures that the cckfield backwards compatibility layer is invoked.
|
||||
*
|
||||
* @expectedDeprecation MigrateCckFieldInterface is deprecated in Drupal 8.3.x and will be removed before Drupal 9.0.x. Use \Drupal\migrate_drupal\Annotation\MigrateField instead.
|
||||
*/
|
||||
public function testBackwardsCompatibility() {
|
||||
$migration = $this->container
|
||||
->get('plugin.manager.migration')
|
||||
->getDefinition('d6_node:story');
|
||||
|
||||
$this->assertSame(D6FileField::class, $migration['process']['field_test_filefield']['class']);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\Tests\migrate_drupal\Kernel;
|
||||
|
||||
use Drupal\Tests\migrate_drupal\Kernel\d6\MigrateDrupal6TestBase;
|
||||
|
||||
/**
|
||||
* Test that no dummy migrate_map tables are created.
|
||||
*
|
||||
* @group migrate_drupal
|
||||
*/
|
||||
class IdMapTableNoDummyTest extends MigrateDrupal6TestBase {
|
||||
|
||||
/**
|
||||
* The migration plugin manager.
|
||||
*
|
||||
* @var \Drupal\migrate\Plugin\MigrationPluginManagerInterface
|
||||
*/
|
||||
protected $pluginManager;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function setUp() {
|
||||
parent::setUp();
|
||||
$this->pluginManager = $this->container->get('plugin.manager.migration');
|
||||
$this->pluginManager->createInstance('d6_user');
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that dummy map tables do not exist.
|
||||
*/
|
||||
public function testNoDummyTables() {
|
||||
$database = \Drupal::database();
|
||||
$tables = $database->schema()->findTables('%migrate_map%');
|
||||
$dummy_tables = preg_grep("/.*migrate_map_([0-9a-fA-F]){13}/", $tables);
|
||||
$this->assertCount(0, $dummy_tables);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\Tests\migrate_drupal\Kernel;
|
||||
|
||||
/**
|
||||
* Extends StateFileExists to test with deprecated modules.
|
||||
*
|
||||
* @see \Drupal\Tests\DeprecatedModulesTestTrait::removeDeprecatedModules()
|
||||
*
|
||||
* @group migrate_drupal
|
||||
* @group legacy
|
||||
*/
|
||||
class LegacyStateFileExists extends StateFileExists {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected $excludeDeprecated = FALSE;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\Tests\migrate_drupal\Kernel;
|
||||
|
||||
use Drupal\Component\Plugin\Exception\PluginNotFoundException;
|
||||
|
||||
/**
|
||||
* Tests the cck field plugin manager.
|
||||
*
|
||||
* @group migrate_drupal
|
||||
*/
|
||||
class MigrateCckFieldPluginManagerTest extends MigrateDrupalTestBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static $modules = [
|
||||
'system',
|
||||
'user',
|
||||
'field',
|
||||
'migrate_drupal',
|
||||
'options',
|
||||
'file',
|
||||
'text',
|
||||
'migrate_cckfield_plugin_manager_test',
|
||||
];
|
||||
|
||||
/**
|
||||
* Tests that the correct MigrateCckField plugins are used.
|
||||
*/
|
||||
public function testPluginSelection() {
|
||||
$plugin_manager = \Drupal::service('plugin.manager.migrate.cckfield');
|
||||
|
||||
$this->assertSame('d6_file', $plugin_manager->getPluginIdFromFieldType('file', ['core' => 6]));
|
||||
|
||||
try {
|
||||
// If this test passes, getPluginIdFromFieldType will raise a
|
||||
// PluginNotFoundException and we'll never reach fail().
|
||||
$plugin_manager->getPluginIdFromFieldType('d6_file', ['core' => 7]);
|
||||
$this->fail('Expected Drupal\Component\Plugin\Exception\PluginNotFoundException.');
|
||||
}
|
||||
catch (PluginNotFoundException $e) {
|
||||
$this->assertSame($e->getMessage(), "Plugin ID 'd6_file' was not found.");
|
||||
}
|
||||
|
||||
// Test fallback when no core version is specified.
|
||||
$this->assertSame('d6_no_core_version_specified', $plugin_manager->getPluginIdFromFieldType('d6_no_core_version_specified', ['core' => 6]));
|
||||
|
||||
try {
|
||||
// If this test passes, getPluginIdFromFieldType will raise a
|
||||
// PluginNotFoundException and we'll never reach fail().
|
||||
$plugin_manager->getPluginIdFromFieldType('d6_no_core_version_specified', ['core' => 7]);
|
||||
$this->fail('Expected Drupal\Component\Plugin\Exception\PluginNotFoundException.');
|
||||
}
|
||||
catch (PluginNotFoundException $e) {
|
||||
$this->assertSame($e->getMessage(), "Plugin ID 'd6_no_core_version_specified' was not found.");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\Tests\migrate_drupal\Kernel;
|
||||
|
||||
use Drupal\Core\Database\Database;
|
||||
use Drupal\Tests\migrate\Kernel\MigrateTestBase;
|
||||
|
||||
/**
|
||||
* Base class for Drupal migration tests.
|
||||
*/
|
||||
abstract class MigrateDrupalTestBase extends MigrateTestBase {
|
||||
|
||||
/**
|
||||
* Modules to enable.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $modules = [
|
||||
'system',
|
||||
'user',
|
||||
'field',
|
||||
'migrate_drupal',
|
||||
'options',
|
||||
'file',
|
||||
];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
|
||||
$module_handler = \Drupal::moduleHandler();
|
||||
if ($module_handler->moduleExists('node')) {
|
||||
$this->installEntitySchema('node');
|
||||
}
|
||||
if ($module_handler->moduleExists('comment')) {
|
||||
$this->installEntitySchema('comment');
|
||||
}
|
||||
if ($module_handler->moduleExists('taxonomy')) {
|
||||
$this->installEntitySchema('taxonomy_term');
|
||||
}
|
||||
if ($module_handler->moduleExists('user')) {
|
||||
$this->installEntitySchema('user');
|
||||
}
|
||||
|
||||
$this->installConfig(['migrate_drupal', 'system']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads a database fixture into the source database connection.
|
||||
*
|
||||
* @param string $path
|
||||
* Path to the dump file.
|
||||
*/
|
||||
protected function loadFixture($path) {
|
||||
$default_db = Database::getConnection()->getKey();
|
||||
Database::setActiveConnection($this->sourceDatabase->getKey());
|
||||
|
||||
if (substr($path, -3) == '.gz') {
|
||||
$path = 'compress.zlib://' . $path;
|
||||
}
|
||||
require $path;
|
||||
|
||||
Database::setActiveConnection($default_db);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,141 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\Tests\migrate_drupal\Kernel;
|
||||
|
||||
use Drupal\Component\Plugin\Exception\PluginNotFoundException;
|
||||
|
||||
/**
|
||||
* Tests the field plugin manager.
|
||||
*
|
||||
* @group migrate_drupal
|
||||
* @coversDefaultClass \Drupal\migrate_drupal\Plugin\MigrateFieldPluginManager
|
||||
*/
|
||||
class MigrateFieldPluginManagerTest extends MigrateDrupalTestBase {
|
||||
|
||||
/**
|
||||
* The field plugin manager.
|
||||
*
|
||||
* @var \Drupal\migrate_drupal\Plugin\MigrateFieldPluginManagerInterface
|
||||
*/
|
||||
protected $pluginManager;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static $modules = [
|
||||
'datetime',
|
||||
'system',
|
||||
'user',
|
||||
'field',
|
||||
'migrate_drupal',
|
||||
'options',
|
||||
'file',
|
||||
'image',
|
||||
'text',
|
||||
'link',
|
||||
'migrate_field_plugin_manager_test',
|
||||
];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function setUp() {
|
||||
parent::setUp();
|
||||
$this->pluginManager = $this->container->get('plugin.manager.migrate.field');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that the correct MigrateField plugins are used.
|
||||
*
|
||||
* @covers ::getPluginIdFromFieldType
|
||||
*/
|
||||
public function testPluginSelection() {
|
||||
$this->assertSame('link', $this->pluginManager->getPluginIdFromFieldType('link', ['core' => 6]));
|
||||
$this->assertSame('link_field', $this->pluginManager->getPluginIdFromFieldType('link_field', ['core' => 7]));
|
||||
$this->assertSame('image', $this->pluginManager->getPluginIdFromFieldType('image', ['core' => 7]));
|
||||
$this->assertSame('file', $this->pluginManager->getPluginIdFromFieldType('file', ['core' => 7]));
|
||||
$this->assertSame('d6_file', $this->pluginManager->getPluginIdFromFieldType('file', ['core' => 6]));
|
||||
$this->assertSame('d6_text', $this->pluginManager->getPluginIdFromFieldType('text', ['core' => 6]));
|
||||
$this->assertSame('d7_text', $this->pluginManager->getPluginIdFromFieldType('text', ['core' => 7]));
|
||||
|
||||
// Test that the deprecated d6 'date' plugin is not returned.
|
||||
$this->assertSame('datetime', $this->pluginManager->getPluginIdFromFieldType('date', ['core' => 6]));
|
||||
|
||||
// Test fallback when no core version is specified.
|
||||
$this->assertSame('d6_no_core_version_specified', $this->pluginManager->getPluginIdFromFieldType('d6_no_core_version_specified', ['core' => 6]));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that a PluginNotFoundException is thrown when a plugin isn't found.
|
||||
*
|
||||
* @covers ::getPluginIdFromFieldType
|
||||
* @dataProvider nonExistentPluginExceptionsData
|
||||
*/
|
||||
public function testNonExistentPluginExceptions($core, $field_type) {
|
||||
$this->expectException(PluginNotFoundException::class);
|
||||
$this->expectExceptionMessage(sprintf("Plugin ID '%s' was not found.", $field_type));
|
||||
$this->pluginManager->getPluginIdFromFieldType($field_type, ['core' => $core]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides data for testNonExistentPluginExceptions.
|
||||
*
|
||||
* @return array
|
||||
* The data.
|
||||
*/
|
||||
public function nonExistentPluginExceptionsData() {
|
||||
return [
|
||||
'D7 Filefield' => [
|
||||
'core' => 7,
|
||||
'field_type' => 'filefield',
|
||||
],
|
||||
'D6 linkfield' => [
|
||||
'core' => 6,
|
||||
'field_type' => 'link_field',
|
||||
],
|
||||
'D7 link' => [
|
||||
'core' => 7,
|
||||
'field_type' => 'link',
|
||||
],
|
||||
'D7 no core version' => [
|
||||
'core' => 7,
|
||||
'field_type' => 'd6_no_core_version_specified',
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that deprecated plugins can still be directly created.
|
||||
*
|
||||
* Tests that a deprecated plugin triggers an error on instantiation. This
|
||||
* test has an implicit assertion that the deprecation error will be triggered
|
||||
* and does not need an explicit assertion to pass.
|
||||
*
|
||||
* @covers ::createInstance
|
||||
* @group legacy
|
||||
* @expectedDeprecation DateField is deprecated in Drupal 8.4.x and will be removed before Drupal 9.0.x. Use \Drupal\datetime\Plugin\migrate\field\DateField instead.
|
||||
*/
|
||||
public function testDeprecatedPluginDirectAccess() {
|
||||
$this->pluginManager->createInstance('date');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that plugins with no explicit weight are given a weight of 0.
|
||||
*/
|
||||
public function testDefaultWeight() {
|
||||
$definitions = $this->pluginManager->getDefinitions();
|
||||
$deprecated_plugins = [
|
||||
'date',
|
||||
];
|
||||
foreach ($definitions as $id => $definition) {
|
||||
$this->assertArrayHasKey('weight', $definition);
|
||||
if (in_array($id, $deprecated_plugins, TRUE)) {
|
||||
$this->assertSame(9999999, $definition['weight']);
|
||||
}
|
||||
else {
|
||||
$this->assertSame(0, $definition['weight']);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\Tests\migrate_drupal\Kernel;
|
||||
|
||||
use Drupal\KernelTests\KernelTestBase;
|
||||
|
||||
/**
|
||||
* Defines a class for testing deprecation error from MigrationState.
|
||||
*
|
||||
* @group migrate_drupal
|
||||
* @group legacy
|
||||
*/
|
||||
class MigrationStateDeprecationTest extends KernelTestBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $modules = [
|
||||
'migrate_drupal',
|
||||
'migrate',
|
||||
'migrate_state_no_file_test',
|
||||
];
|
||||
|
||||
/**
|
||||
* Tests migration state deprecation notice.
|
||||
*
|
||||
* Test that a module with a migration but without a .migrate_drupal.yml
|
||||
* trigger deprecation errors.
|
||||
*
|
||||
* @doesNotPerformAssertions
|
||||
* @expectedDeprecation Using migration plugin definitions to determine the migration state of the module 'migrate_state_no_file_test' is deprecated in Drupal 8.7. Add the module to a migrate_drupal.yml file. See https://www.drupal.org/node/2929443
|
||||
*/
|
||||
public function testUndeclaredDestinationDeprecation() {
|
||||
$plugin_manager = \Drupal::service('plugin.manager.migration');
|
||||
$all_migrations = $plugin_manager->createInstancesByTag('Drupal 7');
|
||||
|
||||
\Drupal::service('migrate_drupal.migration_state')
|
||||
->getUpgradeStates(7, [
|
||||
'module' => [
|
||||
'migrate_state_no_file_test' => [
|
||||
'name' => 'migrate_state_no_file_test',
|
||||
'status' => TRUE,
|
||||
],
|
||||
],
|
||||
], ['import' => $all_migrations['migrate_state_no_file_test']]);
|
||||
}
|
||||
|
||||
}
|
||||
+169
@@ -0,0 +1,169 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\Tests\migrate_drupal\Kernel;
|
||||
|
||||
use Drupal\migrate_drupal\NodeMigrateType;
|
||||
use Drupal\Tests\migrate\Kernel\MigrateTestBase;
|
||||
use Drupal\Tests\migrate_drupal\Traits\NodeMigrateTypeTestTrait;
|
||||
|
||||
/**
|
||||
* Tests the assignment of the node migration type in migrations_plugin_alter.
|
||||
*
|
||||
* @group migrate_drupal
|
||||
*/
|
||||
class NodeMigrationTypePluginAlterTest extends MigrateTestBase {
|
||||
|
||||
use NodeMigrateTypeTestTrait;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static $modules = ['migrate_drupal', 'node'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
$this->setupDb();
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the assignment of the node migration type.
|
||||
*
|
||||
* @param string $type
|
||||
* The type of node migration, 'classic' or 'complete'.
|
||||
* @param array $migration_definitions
|
||||
* An array of migration definitions.
|
||||
* @param array $expected
|
||||
* The expected results.
|
||||
*
|
||||
* @dataProvider providerMigrationPluginAlter
|
||||
*
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function testMigrationPluginAlter($type, array $migration_definitions, array $expected) {
|
||||
$this->makeNodeMigrateMapTable($type, '7');
|
||||
migrate_drupal_migration_plugins_alter($migration_definitions);
|
||||
$this->assertSame($expected, $migration_definitions);
|
||||
}
|
||||
|
||||
/**
|
||||
* Data provider for testMigrationPluginAlter().
|
||||
*/
|
||||
public function providerMigrationPluginAlter() {
|
||||
$tests = [];
|
||||
|
||||
$migrations = [
|
||||
// The 'system_site' migration is needed to get the legacy Drupal version.
|
||||
'system_site' => [
|
||||
'id' => 'system_site',
|
||||
'source' => [
|
||||
'plugin' => 'variable',
|
||||
'variables' => [
|
||||
'site_name',
|
||||
'site_mail',
|
||||
],
|
||||
'source_module' => 'system',
|
||||
],
|
||||
'process' => [],
|
||||
],
|
||||
'no_dependencies_not_altered' => [
|
||||
'id' => 'no_dependencies_not_altered',
|
||||
'no_dependencies' => 'test',
|
||||
'process' => [
|
||||
'nid' => 'nid',
|
||||
],
|
||||
],
|
||||
'dependencies_altered_if_complete' => [
|
||||
'id' => 'test',
|
||||
'migration_dependencies' => [
|
||||
'required' => [
|
||||
'd7_node',
|
||||
],
|
||||
'optional' => [
|
||||
'd7_node_translation',
|
||||
],
|
||||
],
|
||||
],
|
||||
'dependencies_not_altered' => [
|
||||
'id' => 'd7_node',
|
||||
'migration_dependencies' => [
|
||||
'required' => [
|
||||
'd7_node',
|
||||
],
|
||||
'optional' => [
|
||||
'd7_node_translation',
|
||||
],
|
||||
],
|
||||
],
|
||||
];
|
||||
|
||||
// Test migrations are not altered when classic node migrations is in use.
|
||||
$tests[0]['type'] = NodeMigrateType::NODE_MIGRATE_TYPE_CLASSIC;
|
||||
$tests[0]['migrations'] = $migrations;
|
||||
$tests[0]['expected_data'] = $tests[0]['migrations'];
|
||||
|
||||
// Test migrations are altered when complete node migrations is in use.
|
||||
$tests[1] = $tests[0];
|
||||
$tests[1]['type'] = NodeMigrateType::NODE_MIGRATE_TYPE_COMPLETE;
|
||||
$tests[1]['expected_data']['dependencies_altered_if_complete']['migration_dependencies'] = [
|
||||
'required' => [
|
||||
'd7_node_complete',
|
||||
],
|
||||
'optional' => [
|
||||
'd7_node_complete',
|
||||
],
|
||||
];
|
||||
return $tests;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates data in the source database.
|
||||
*/
|
||||
protected function setupDb() {
|
||||
$this->sourceDatabase->schema()->createTable('system', [
|
||||
'fields' => [
|
||||
'name' => [
|
||||
'type' => 'varchar',
|
||||
'not null' => TRUE,
|
||||
'length' => '255',
|
||||
'default' => '',
|
||||
],
|
||||
'type' => [
|
||||
'type' => 'varchar',
|
||||
'not null' => TRUE,
|
||||
'length' => '255',
|
||||
'default' => '',
|
||||
],
|
||||
'status' => [
|
||||
'type' => 'int',
|
||||
'not null' => TRUE,
|
||||
'size' => 'normal',
|
||||
'default' => '0',
|
||||
],
|
||||
'schema_version' => [
|
||||
'type' => 'int',
|
||||
'not null' => TRUE,
|
||||
'size' => 'normal',
|
||||
'default' => '-1',
|
||||
],
|
||||
],
|
||||
]);
|
||||
$this->sourceDatabase->insert('system')
|
||||
->fields([
|
||||
'name',
|
||||
'type',
|
||||
'status',
|
||||
'schema_version',
|
||||
])
|
||||
->values([
|
||||
'name' => 'system',
|
||||
'type' => 'module',
|
||||
'status' => '1',
|
||||
'schema_version' => '7001',
|
||||
])
|
||||
->execute();
|
||||
}
|
||||
|
||||
}
|
||||
+133
@@ -0,0 +1,133 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\Tests\migrate_drupal\Kernel\Plugin\migrate;
|
||||
|
||||
use Drupal\ban\Plugin\migrate\destination\BlockedIp;
|
||||
use Drupal\color\Plugin\migrate\destination\Color;
|
||||
use Drupal\KernelTests\FileSystemModuleDiscoveryDataProviderTrait;
|
||||
use Drupal\migrate\Plugin\migrate\destination\ComponentEntityDisplayBase;
|
||||
use Drupal\migrate\Plugin\migrate\destination\Config;
|
||||
use Drupal\migrate\Plugin\migrate\destination\EntityConfigBase;
|
||||
use Drupal\migrate\Plugin\migrate\destination\EntityContentBase;
|
||||
use Drupal\path\Plugin\migrate\destination\UrlAlias;
|
||||
use Drupal\shortcut\Plugin\migrate\destination\ShortcutSetUsers;
|
||||
use Drupal\statistics\Plugin\migrate\destination\NodeCounter;
|
||||
use Drupal\system\Plugin\migrate\destination\d7\ThemeSettings;
|
||||
use Drupal\Tests\DeprecatedModulesTestTrait;
|
||||
use Drupal\Tests\migrate_drupal\Kernel\MigrateDrupalTestBase;
|
||||
use Drupal\Tests\migrate_drupal\Traits\CreateMigrationsTrait;
|
||||
use Drupal\user\Plugin\migrate\destination\UserData;
|
||||
|
||||
/**
|
||||
* Tests that all migrations are tagged as either content or configuration.
|
||||
*
|
||||
* @group migrate_drupal
|
||||
*/
|
||||
class DestinationCategoryTest extends MigrateDrupalTestBase {
|
||||
|
||||
use FileSystemModuleDiscoveryDataProviderTrait;
|
||||
use CreateMigrationsTrait;
|
||||
use DeprecatedModulesTestTrait;
|
||||
|
||||
/**
|
||||
* The migration plugin manager.
|
||||
*
|
||||
* @var \Drupal\migrate\Plugin\MigrationPluginManager
|
||||
*/
|
||||
protected $migrationManager;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp() {
|
||||
// Enable all modules.
|
||||
self::$modules = array_keys($this->coreModuleListDataProvider());
|
||||
self::$modules = $this->removeDeprecatedModules(self::$modules);
|
||||
parent::setUp();
|
||||
$this->migrationManager = \Drupal::service('plugin.manager.migration');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that all D6 migrations are tagged as either Configuration or Content.
|
||||
*/
|
||||
public function testD6Categories() {
|
||||
$migrations = $this->drupal6Migrations();
|
||||
$this->assertArrayHasKey('d6_node:page', $migrations);
|
||||
$this->assertCategories($migrations);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that all D7 migrations are tagged as either Configuration or Content.
|
||||
*/
|
||||
public function testD7Categories() {
|
||||
$migrations = $this->drupal7Migrations();
|
||||
$this->assertArrayHasKey('d7_node:page', $migrations);
|
||||
$this->assertCategories($migrations);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Asserts that all migrations are tagged as either Configuration or Content.
|
||||
*
|
||||
* @param \Drupal\migrate\Plugin\MigrationInterface[] $migrations
|
||||
* The migrations.
|
||||
*/
|
||||
protected function assertCategories($migrations) {
|
||||
foreach ($migrations as $id => $migration) {
|
||||
$object_classes = class_parents($migration->getDestinationPlugin());
|
||||
$object_classes[] = get_class($migration->getDestinationPlugin());
|
||||
|
||||
// Ensure that the destination plugin is an instance of at least one of
|
||||
// the expected classes.
|
||||
if (in_array('Configuration', $migration->getMigrationTags(), TRUE)) {
|
||||
$this->assertNotEmpty(array_intersect($object_classes, $this->getConfigurationClasses()), "The migration $id is tagged as Configuration.");
|
||||
}
|
||||
elseif (in_array('Content', $migration->getMigrationTags(), TRUE)) {
|
||||
$this->assertNotEmpty(array_intersect($object_classes, $this->getContentClasses()), "The migration $id is tagged as Content.");
|
||||
}
|
||||
else {
|
||||
$this->fail("The migration $id is not tagged as either 'Content' or 'Configuration'.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get configuration classes.
|
||||
*
|
||||
* Configuration migrations should have a destination plugin that is an
|
||||
* instance of one of the following classes.
|
||||
*
|
||||
* @return array
|
||||
* The configuration class names.
|
||||
*/
|
||||
protected function getConfigurationClasses() {
|
||||
return [
|
||||
Color::class,
|
||||
Config::class,
|
||||
EntityConfigBase::class,
|
||||
ThemeSettings::class,
|
||||
ComponentEntityDisplayBase::class,
|
||||
ShortcutSetUsers::class,
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get content classes.
|
||||
*
|
||||
* Content migrations should have a destination plugin that is an instance
|
||||
* of one of the following classes.
|
||||
*
|
||||
* @return array
|
||||
* The content class names.
|
||||
*/
|
||||
protected function getContentClasses() {
|
||||
return [
|
||||
EntityContentBase::class,
|
||||
UrlAlias::class,
|
||||
BlockedIp::class,
|
||||
NodeCounter::class,
|
||||
UserData::class,
|
||||
];
|
||||
}
|
||||
|
||||
}
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\Tests\migrate_drupal\Kernel\Plugin\migrate;
|
||||
|
||||
/**
|
||||
* Extends DestinationCategoryTest to test with deprecated modules.
|
||||
*
|
||||
* @see \Drupal\Tests\DeprecatedModulesTestTrait::removeDeprecatedModules()
|
||||
*
|
||||
* @group migrate_drupal
|
||||
* @group legacy
|
||||
*/
|
||||
class LegacyDestinationCategoryTest extends DestinationCategoryTest {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected $excludeDeprecated = FALSE;
|
||||
|
||||
}
|
||||
+453
@@ -0,0 +1,453 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\Tests\migrate_drupal\Kernel\Plugin\migrate\source;
|
||||
|
||||
use Drupal\Component\Plugin\Exception\InvalidPluginDefinitionException;
|
||||
use Drupal\Core\Field\FieldStorageDefinitionInterface;
|
||||
use Drupal\Core\Language\LanguageInterface;
|
||||
use Drupal\file\Entity\File;
|
||||
use Drupal\KernelTests\KernelTestBase;
|
||||
use Drupal\language\Entity\ConfigurableLanguage;
|
||||
use Drupal\media\Entity\Media;
|
||||
use Drupal\migrate\Plugin\MigrationInterface;
|
||||
use Drupal\migrate_drupal\Plugin\migrate\source\ContentEntity;
|
||||
use Drupal\node\Entity\Node;
|
||||
use Drupal\node\Entity\NodeType;
|
||||
use Drupal\taxonomy\Entity\Term;
|
||||
use Drupal\taxonomy\Entity\Vocabulary;
|
||||
use Drupal\Tests\field\Traits\EntityReferenceTestTrait;
|
||||
use Drupal\Tests\media\Traits\MediaTypeCreationTrait;
|
||||
use Drupal\user\Entity\User;
|
||||
|
||||
/**
|
||||
* Tests the entity content source plugin.
|
||||
*
|
||||
* @group migrate_drupal
|
||||
*/
|
||||
class ContentEntityTest extends KernelTestBase {
|
||||
|
||||
use EntityReferenceTestTrait;
|
||||
use MediaTypeCreationTrait;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static $modules = [
|
||||
'user',
|
||||
'migrate',
|
||||
'migrate_drupal',
|
||||
'system',
|
||||
'node',
|
||||
'taxonomy',
|
||||
'field',
|
||||
'file',
|
||||
'image',
|
||||
'media',
|
||||
'media_test_source',
|
||||
'text',
|
||||
'filter',
|
||||
'language',
|
||||
'content_translation',
|
||||
];
|
||||
|
||||
/**
|
||||
* The bundle used in this test.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $bundle = 'article';
|
||||
|
||||
/**
|
||||
* The name of the field used in this test.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $fieldName = 'field_entity_reference';
|
||||
|
||||
/**
|
||||
* The vocabulary ID.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $vocabulary = 'fruit';
|
||||
|
||||
/**
|
||||
* The test user.
|
||||
*
|
||||
* @var \Drupal\user\Entity\User
|
||||
*/
|
||||
protected $user;
|
||||
|
||||
/**
|
||||
* The migration plugin manager.
|
||||
*
|
||||
* @var \Drupal\migrate\Plugin\MigrationPluginManagerInterface
|
||||
*/
|
||||
protected $migrationPluginManager;
|
||||
|
||||
/**
|
||||
* The source plugin manager.
|
||||
*
|
||||
* @var \Drupal\migrate\Plugin\MigrateSourcePluginManager
|
||||
*/
|
||||
protected $sourcePluginManager;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
$this->installEntitySchema('node');
|
||||
$this->installEntitySchema('file');
|
||||
$this->installEntitySchema('media');
|
||||
$this->installEntitySchema('taxonomy_term');
|
||||
$this->installEntitySchema('taxonomy_vocabulary');
|
||||
$this->installEntitySchema('user');
|
||||
$this->installSchema('system', ['sequences']);
|
||||
$this->installSchema('user', 'users_data');
|
||||
$this->installSchema('file', 'file_usage');
|
||||
$this->installSchema('node', ['node_access']);
|
||||
$this->installConfig($this->modules);
|
||||
|
||||
ConfigurableLanguage::createFromLangcode('fr')->save();
|
||||
|
||||
// Create article content type.
|
||||
$node_type = NodeType::create(['type' => $this->bundle, 'name' => 'Article']);
|
||||
$node_type->save();
|
||||
|
||||
// Create a vocabulary.
|
||||
$vocabulary = Vocabulary::create([
|
||||
'name' => $this->vocabulary,
|
||||
'description' => $this->vocabulary,
|
||||
'vid' => $this->vocabulary,
|
||||
'langcode' => LanguageInterface::LANGCODE_NOT_SPECIFIED,
|
||||
]);
|
||||
$vocabulary->save();
|
||||
|
||||
// Create a term reference field on node.
|
||||
$this->createEntityReferenceField(
|
||||
'node',
|
||||
$this->bundle,
|
||||
$this->fieldName,
|
||||
'Term reference',
|
||||
'taxonomy_term',
|
||||
'default',
|
||||
['target_bundles' => [$this->vocabulary]],
|
||||
FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED
|
||||
);
|
||||
// Create a term reference field on user.
|
||||
$this->createEntityReferenceField(
|
||||
'user',
|
||||
'user',
|
||||
$this->fieldName,
|
||||
'Term reference',
|
||||
'taxonomy_term',
|
||||
'default',
|
||||
['target_bundles' => [$this->vocabulary]],
|
||||
FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED
|
||||
);
|
||||
|
||||
// Create some data.
|
||||
$this->user = User::create([
|
||||
'name' => 'user123',
|
||||
'uid' => 1,
|
||||
'mail' => 'example@example.com',
|
||||
]);
|
||||
$this->user->save();
|
||||
|
||||
$term = Term::create([
|
||||
'vid' => $this->vocabulary,
|
||||
'name' => 'Apples',
|
||||
'uid' => $this->user->id(),
|
||||
]);
|
||||
$term->save();
|
||||
$this->user->set($this->fieldName, $term->id());
|
||||
$this->user->save();
|
||||
$node = Node::create([
|
||||
'type' => $this->bundle,
|
||||
'title' => 'Apples',
|
||||
$this->fieldName => $term->id(),
|
||||
'uid' => $this->user->id(),
|
||||
]);
|
||||
$node->save();
|
||||
$node->addTranslation('fr', [
|
||||
'title' => 'Pommes',
|
||||
$this->fieldName => $term->id(),
|
||||
])->save();
|
||||
|
||||
$this->sourcePluginManager = $this->container->get('plugin.manager.migrate.source');
|
||||
$this->migrationPluginManager = $this->container->get('plugin.manager.migration');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the constructor for missing entity_type.
|
||||
*/
|
||||
public function testConstructorEntityTypeMissing() {
|
||||
$migration = $this->prophesize(MigrationInterface::class)->reveal();
|
||||
$configuration = [];
|
||||
$plugin_definition = [
|
||||
'entity_type' => '',
|
||||
];
|
||||
$this->expectException(InvalidPluginDefinitionException::class);
|
||||
$this->expectExceptionMessage('Missing required "entity_type" definition.');
|
||||
ContentEntity::create($this->container, $configuration, 'content_entity', $plugin_definition, $migration);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the constructor for non content entity.
|
||||
*/
|
||||
public function testConstructorNonContentEntity() {
|
||||
$migration = $this->prophesize(MigrationInterface::class)->reveal();
|
||||
$configuration = [];
|
||||
$plugin_definition = [
|
||||
'entity_type' => 'node_type',
|
||||
];
|
||||
$this->expectException(InvalidPluginDefinitionException::class);
|
||||
$this->expectExceptionMessage('The entity type (node_type) is not supported. The "content_entity" source plugin only supports content entities.');
|
||||
ContentEntity::create($this->container, $configuration, 'content_entity:node_type', $plugin_definition, $migration);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the constructor for not bundleable entity.
|
||||
*/
|
||||
public function testConstructorNotBundable() {
|
||||
$migration = $this->prophesize(MigrationInterface::class)->reveal();
|
||||
$configuration = [
|
||||
'bundle' => 'foo',
|
||||
];
|
||||
$plugin_definition = [
|
||||
'entity_type' => 'user',
|
||||
];
|
||||
$this->expectException(\InvalidArgumentException::class);
|
||||
$this->expectExceptionMessage('A bundle was provided but the entity type (user) is not bundleable');
|
||||
ContentEntity::create($this->container, $configuration, 'content_entity:user', $plugin_definition, $migration);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the constructor for invalid entity bundle.
|
||||
*/
|
||||
public function testConstructorInvalidBundle() {
|
||||
$migration = $this->prophesize(MigrationInterface::class)->reveal();
|
||||
$configuration = [
|
||||
'bundle' => 'foo',
|
||||
];
|
||||
$plugin_definition = [
|
||||
'entity_type' => 'node',
|
||||
];
|
||||
$this->expectException(\InvalidArgumentException::class);
|
||||
$this->expectExceptionMessage('The provided bundle (foo) is not valid for the (node) entity type.');
|
||||
ContentEntity::create($this->container, $configuration, 'content_entity:node', $plugin_definition, $migration);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests user source plugin.
|
||||
*/
|
||||
public function testUserSource() {
|
||||
$configuration = [
|
||||
'include_translations' => FALSE,
|
||||
];
|
||||
$migration = $this->migrationPluginManager->createStubMigration($this->migrationDefinition('content_entity:user'));
|
||||
$user_source = $this->sourcePluginManager->createInstance('content_entity:user', $configuration, $migration);
|
||||
$this->assertSame('users', $user_source->__toString());
|
||||
$this->assertEquals(1, $user_source->count());
|
||||
$ids = $user_source->getIds();
|
||||
$this->assertArrayHasKey('langcode', $ids);
|
||||
$this->assertArrayHasKey('uid', $ids);
|
||||
$fields = $user_source->fields();
|
||||
$this->assertArrayHasKey('name', $fields);
|
||||
$this->assertArrayHasKey('pass', $fields);
|
||||
$this->assertArrayHasKey('mail', $fields);
|
||||
$this->assertArrayHasKey('uid', $fields);
|
||||
$this->assertArrayHasKey('roles', $fields);
|
||||
$user_source->rewind();
|
||||
$values = $user_source->current()->getSource();
|
||||
$this->assertEquals('example@example.com', $values['mail'][0]['value']);
|
||||
$this->assertEquals('user123', $values['name'][0]['value']);
|
||||
$this->assertEquals(1, $values['uid']);
|
||||
$this->assertEquals(1, $values['field_entity_reference'][0]['target_id']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests file source plugin.
|
||||
*/
|
||||
public function testFileSource() {
|
||||
$file = File::create([
|
||||
'filename' => 'foo.txt',
|
||||
'uid' => $this->user->id(),
|
||||
'uri' => 'public://foo.txt',
|
||||
]);
|
||||
$file->save();
|
||||
|
||||
$configuration = [
|
||||
'include_translations' => FALSE,
|
||||
];
|
||||
$migration = $this->migrationPluginManager->createStubMigration($this->migrationDefinition('content_entity:file'));
|
||||
$file_source = $this->sourcePluginManager->createInstance('content_entity:file', $configuration, $migration);
|
||||
$this->assertSame('files', $file_source->__toString());
|
||||
$this->assertEquals(1, $file_source->count());
|
||||
$ids = $file_source->getIds();
|
||||
$this->assertArrayHasKey('fid', $ids);
|
||||
$fields = $file_source->fields();
|
||||
$this->assertArrayHasKey('fid', $fields);
|
||||
$this->assertArrayHasKey('filemime', $fields);
|
||||
$this->assertArrayHasKey('filename', $fields);
|
||||
$this->assertArrayHasKey('uid', $fields);
|
||||
$this->assertArrayHasKey('uri', $fields);
|
||||
$file_source->rewind();
|
||||
$values = $file_source->current()->getSource();
|
||||
$this->assertEquals('text/plain', $values['filemime'][0]['value']);
|
||||
$this->assertEquals('public://foo.txt', $values['uri'][0]['value']);
|
||||
$this->assertEquals('foo.txt', $values['filename'][0]['value']);
|
||||
$this->assertEquals(1, $values['fid']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests node source plugin.
|
||||
*/
|
||||
public function testNodeSource() {
|
||||
$migration = $this->migrationPluginManager->createStubMigration($this->migrationDefinition('content_entity:node'));
|
||||
$node_source = $this->sourcePluginManager->createInstance('content_entity:node', ['bundle' => $this->bundle], $migration);
|
||||
$this->assertSame('content items', $node_source->__toString());
|
||||
$ids = $node_source->getIds();
|
||||
$this->assertArrayHasKey('langcode', $ids);
|
||||
$this->assertArrayHasKey('nid', $ids);
|
||||
$fields = $node_source->fields();
|
||||
$this->assertArrayHasKey('nid', $fields);
|
||||
$this->assertArrayHasKey('vid', $fields);
|
||||
$this->assertArrayHasKey('title', $fields);
|
||||
$this->assertArrayHasKey('uid', $fields);
|
||||
$this->assertArrayHasKey('sticky', $fields);
|
||||
$node_source->rewind();
|
||||
$values = $node_source->current()->getSource();
|
||||
$this->assertEquals($this->bundle, $values['type'][0]['target_id']);
|
||||
$this->assertEquals(1, $values['nid']);
|
||||
$this->assertEquals(1, $values['vid']);
|
||||
$this->assertEquals('en', $values['langcode']);
|
||||
$this->assertEquals(1, $values['status'][0]['value']);
|
||||
$this->assertEquals('Apples', $values['title'][0]['value']);
|
||||
$this->assertEquals(1, $values['default_langcode'][0]['value']);
|
||||
$this->assertEquals(1, $values['field_entity_reference'][0]['target_id']);
|
||||
$node_source->next();
|
||||
$values = $node_source->current()->getSource();
|
||||
$this->assertEquals($this->bundle, $values['type'][0]['target_id']);
|
||||
$this->assertEquals(1, $values['nid']);
|
||||
$this->assertEquals(1, $values['vid']);
|
||||
$this->assertEquals('fr', $values['langcode']);
|
||||
$this->assertEquals(1, $values['status'][0]['value']);
|
||||
$this->assertEquals('Pommes', $values['title'][0]['value']);
|
||||
$this->assertEquals(0, $values['default_langcode'][0]['value']);
|
||||
$this->assertEquals(1, $values['field_entity_reference'][0]['target_id']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests media source plugin.
|
||||
*/
|
||||
public function testMediaSource() {
|
||||
$values = [
|
||||
'id' => 'image',
|
||||
'label' => 'Image',
|
||||
'source' => 'test',
|
||||
'new_revision' => FALSE,
|
||||
];
|
||||
$media_type = $this->createMediaType('test', $values);
|
||||
$media = Media::create([
|
||||
'name' => 'Foo media',
|
||||
'uid' => $this->user->id(),
|
||||
'bundle' => $media_type->id(),
|
||||
]);
|
||||
$media->save();
|
||||
|
||||
$configuration = [
|
||||
'include_translations' => FALSE,
|
||||
'bundle' => 'image',
|
||||
];
|
||||
$migration = $this->migrationPluginManager->createStubMigration($this->migrationDefinition('content_entity:media'));
|
||||
$media_source = $this->sourcePluginManager->createInstance('content_entity:media', $configuration, $migration);
|
||||
$this->assertSame('media items', $media_source->__toString());
|
||||
$this->assertEquals(1, $media_source->count());
|
||||
$ids = $media_source->getIds();
|
||||
$this->assertArrayHasKey('langcode', $ids);
|
||||
$this->assertArrayHasKey('mid', $ids);
|
||||
$fields = $media_source->fields();
|
||||
$this->assertArrayHasKey('bundle', $fields);
|
||||
$this->assertArrayHasKey('mid', $fields);
|
||||
$this->assertArrayHasKey('vid', $fields);
|
||||
$this->assertArrayHasKey('name', $fields);
|
||||
$this->assertArrayHasKey('status', $fields);
|
||||
$media_source->rewind();
|
||||
$values = $media_source->current()->getSource();
|
||||
$this->assertEquals(1, $values['mid']);
|
||||
$this->assertEquals(1, $values['vid']);
|
||||
$this->assertEquals('Foo media', $values['name'][0]['value']);
|
||||
$this->assertNull($values['thumbnail'][0]['title']);
|
||||
$this->assertEquals(1, $values['uid'][0]['target_id']);
|
||||
$this->assertEquals('image', $values['bundle'][0]['target_id']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests term source plugin.
|
||||
*/
|
||||
public function testTermSource() {
|
||||
$term2 = Term::create([
|
||||
'vid' => $this->vocabulary,
|
||||
'name' => 'Granny Smith',
|
||||
'uid' => $this->user->id(),
|
||||
'parent' => 1,
|
||||
]);
|
||||
$term2->save();
|
||||
|
||||
$configuration = [
|
||||
'include_translations' => FALSE,
|
||||
'bundle' => $this->vocabulary,
|
||||
];
|
||||
$migration = $this->migrationPluginManager->createStubMigration($this->migrationDefinition('content_entity:taxonomy_term'));
|
||||
$term_source = $this->sourcePluginManager->createInstance('content_entity:taxonomy_term', $configuration, $migration);
|
||||
$this->assertSame('taxonomy terms', $term_source->__toString());
|
||||
$this->assertEquals(2, $term_source->count());
|
||||
$ids = $term_source->getIds();
|
||||
$this->assertArrayHasKey('langcode', $ids);
|
||||
$this->assertArrayHasKey('revision_id', $ids);
|
||||
$this->assertArrayHasKey('tid', $ids);
|
||||
$fields = $term_source->fields();
|
||||
$this->assertArrayHasKey('vid', $fields);
|
||||
$this->assertArrayHasKey('revision_id', $fields);
|
||||
$this->assertArrayHasKey('tid', $fields);
|
||||
$this->assertArrayHasKey('name', $fields);
|
||||
$term_source->rewind();
|
||||
$values = $term_source->current()->getSource();
|
||||
$this->assertEquals($this->vocabulary, $values['vid'][0]['target_id']);
|
||||
$this->assertEquals(1, $values['tid']);
|
||||
// @TODO: Add test coverage for parent in
|
||||
// https://www.drupal.org/project/drupal/issues/2940198
|
||||
$this->assertEquals('Apples', $values['name'][0]['value']);
|
||||
$term_source->next();
|
||||
$values = $term_source->current()->getSource();
|
||||
$this->assertEquals($this->vocabulary, $values['vid'][0]['target_id']);
|
||||
$this->assertEquals(2, $values['tid']);
|
||||
// @TODO: Add test coverage for parent in
|
||||
// https://www.drupal.org/project/drupal/issues/2940198
|
||||
$this->assertEquals('Granny Smith', $values['name'][0]['value']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a migration definition.
|
||||
*
|
||||
* @param string $plugin_id
|
||||
* The plugin id.
|
||||
*
|
||||
* @return array
|
||||
* The definition.
|
||||
*/
|
||||
protected function migrationDefinition($plugin_id) {
|
||||
return [
|
||||
'source' => [
|
||||
'plugin' => $plugin_id,
|
||||
],
|
||||
'process' => [],
|
||||
'destination' => [
|
||||
'plugin' => 'null',
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
}
|
||||
+57
@@ -0,0 +1,57 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\Tests\migrate_drupal\Kernel\Plugin\migrate\source;
|
||||
|
||||
use Drupal\Tests\migrate\Kernel\MigrateSqlSourceTestBase;
|
||||
|
||||
/**
|
||||
* Tests the variable multirow source plugin.
|
||||
*
|
||||
* @covers \Drupal\migrate_drupal\Plugin\migrate\source\VariableMultiRow
|
||||
*
|
||||
* @group migrate_drupal
|
||||
*/
|
||||
class VariableMultiRowTest extends MigrateSqlSourceTestBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static $modules = ['migrate_drupal'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function providerSource() {
|
||||
$tests = [];
|
||||
|
||||
// The source data.
|
||||
$tests[0]['source_data']['variable'] = [
|
||||
['name' => 'foo', 'value' => 'i:1;'],
|
||||
['name' => 'bar', 'value' => 'b:0;'],
|
||||
];
|
||||
|
||||
// The expected results.
|
||||
$tests[0]['expected_data'] = [
|
||||
[
|
||||
'name' => 'foo',
|
||||
'value' => 1,
|
||||
],
|
||||
[
|
||||
'name' => 'bar',
|
||||
'value' => FALSE,
|
||||
],
|
||||
];
|
||||
|
||||
// The expected count.
|
||||
$tests[0]['expected_count'] = NULL;
|
||||
|
||||
// The source plugin configuration.
|
||||
$tests[0]['configuration']['variables'] = [
|
||||
'foo',
|
||||
'bar',
|
||||
];
|
||||
|
||||
return $tests;
|
||||
}
|
||||
|
||||
}
|
||||
+90
@@ -0,0 +1,90 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\Tests\migrate_drupal\Kernel\Plugin\migrate\source;
|
||||
|
||||
use Drupal\Tests\migrate\Kernel\MigrateSqlSourceTestBase;
|
||||
|
||||
/**
|
||||
* Tests the variable source plugin.
|
||||
*
|
||||
* @covers \Drupal\migrate_drupal\Plugin\migrate\source\Variable
|
||||
*
|
||||
* @group migrate_drupal
|
||||
*/
|
||||
class VariableTest extends MigrateSqlSourceTestBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static $modules = ['migrate_drupal'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function providerSource() {
|
||||
$tests = [];
|
||||
|
||||
// The source data.
|
||||
$tests[0]['source_data']['variable'] = [
|
||||
['name' => 'foo', 'value' => 'i:1;'],
|
||||
['name' => 'bar', 'value' => 'b:0;'],
|
||||
];
|
||||
|
||||
// The expected results.
|
||||
$tests[0]['expected_data'] = [
|
||||
[
|
||||
'id' => 'foo',
|
||||
'foo' => 1,
|
||||
'bar' => FALSE,
|
||||
],
|
||||
];
|
||||
|
||||
// The expected count.
|
||||
$tests[0]['expected_count'] = NULL;
|
||||
|
||||
// The source plugin configuration.
|
||||
$tests[0]['configuration']['variables'] = [
|
||||
'foo',
|
||||
'bar',
|
||||
];
|
||||
|
||||
// Tests getting one of two variables.
|
||||
$tests[1]['source_data']['variable'] = [
|
||||
['name' => 'foo', 'value' => 'i:1;'],
|
||||
['name' => 'bar', 'value' => 'b:0;'],
|
||||
];
|
||||
|
||||
$tests[1]['expected_data'] = [
|
||||
[
|
||||
'id' => 'foo',
|
||||
'foo' => 1,
|
||||
],
|
||||
];
|
||||
|
||||
$tests[1]['expected_count'] = NULL;
|
||||
|
||||
$tests[1]['configuration']['variables'] = [
|
||||
'foo',
|
||||
'bar0',
|
||||
];
|
||||
|
||||
// Tests requesting mis-spelled variable names.
|
||||
$tests[2]['source_data']['variable'] = [
|
||||
['name' => 'foo', 'value' => 'i:1;'],
|
||||
['name' => 'bar', 'value' => 'b:0;'],
|
||||
];
|
||||
$tests[2]['expected_data'] = [
|
||||
[
|
||||
'id' => 'foo0',
|
||||
],
|
||||
];
|
||||
$tests[2]['expected_count'] = NULL;
|
||||
$tests[2]['configuration']['variables'] = [
|
||||
'foo0',
|
||||
'bar0',
|
||||
];
|
||||
|
||||
return $tests;
|
||||
}
|
||||
|
||||
}
|
||||
+77
@@ -0,0 +1,77 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\Tests\migrate_drupal\Kernel\Plugin\migrate\source\d6;
|
||||
|
||||
use Drupal\Tests\migrate\Kernel\MigrateSqlSourceTestBase;
|
||||
|
||||
/**
|
||||
* Tests the variable source plugin.
|
||||
*
|
||||
* @covers \Drupal\migrate_drupal\Plugin\migrate\source\d6\VariableTranslation
|
||||
*
|
||||
* @group migrate_drupal
|
||||
*/
|
||||
class VariableTranslationTest extends MigrateSqlSourceTestBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static $modules = ['migrate_drupal'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function providerSource() {
|
||||
$tests = [];
|
||||
|
||||
// The source data.
|
||||
$tests[0]['source_data']['i18n_variable'] = [
|
||||
[
|
||||
'name' => 'site_slogan',
|
||||
'language' => 'fr',
|
||||
'value' => 's:19:"Migrate est génial";',
|
||||
],
|
||||
[
|
||||
'name' => 'site_name',
|
||||
'language' => 'fr',
|
||||
'value' => 's:11:"nom de site";',
|
||||
],
|
||||
[
|
||||
'name' => 'site_slogan',
|
||||
'language' => 'mi',
|
||||
'value' => 's:19:"Ko whakamataku heke";',
|
||||
],
|
||||
[
|
||||
'name' => 'site_name',
|
||||
'language' => 'mi',
|
||||
'value' => 's:9:"ingoa_pae";',
|
||||
],
|
||||
];
|
||||
|
||||
// The expected results.
|
||||
$tests[0]['expected_data'] = [
|
||||
[
|
||||
'language' => 'fr',
|
||||
'site_slogan' => 'Migrate est génial',
|
||||
'site_name' => 'nom de site',
|
||||
],
|
||||
[
|
||||
'language' => 'mi',
|
||||
'site_slogan' => 'Ko whakamataku heke',
|
||||
'site_name' => 'ingoa_pae',
|
||||
],
|
||||
];
|
||||
|
||||
// The expected count.
|
||||
$tests[0]['expected_count'] = NULL;
|
||||
|
||||
// The migration configuration.
|
||||
$tests[0]['configuration']['variables'] = [
|
||||
'site_slogan',
|
||||
'site_name',
|
||||
];
|
||||
|
||||
return $tests;
|
||||
}
|
||||
|
||||
}
|
||||
+89
@@ -0,0 +1,89 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\Tests\migrate_drupal\Kernel\Plugin\migrate\source\d6;
|
||||
|
||||
use Drupal\Tests\migrate\Kernel\MigrateSqlSourceTestBase;
|
||||
|
||||
/**
|
||||
* Tests the variable source plugin.
|
||||
*
|
||||
* @covers \Drupal\migrate_drupal\Plugin\migrate\source\d6\i18nVariable
|
||||
*
|
||||
* @group migrate_drupal
|
||||
* @group legacy
|
||||
*/
|
||||
class i18nVariableTest extends MigrateSqlSourceTestBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static $modules = ['migrate_drupal'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* @dataProvider providerSource
|
||||
* @requires extension pdo_sqlite
|
||||
* @expectedDeprecation The Drupal\migrate_drupal\Plugin\migrate\source\d6\i18nVariable is deprecated in Drupal 8.4.0 and will be removed before Drupal 9.0.0. Instead, use Drupal\migrate_drupal\Plugin\migrate\source\d6\VariableTranslation
|
||||
*/
|
||||
public function testSource(array $source_data, array $expected_data, $expected_count = NULL, array $configuration = [], $high_water = NULL) {
|
||||
parent::testSource($source_data, $expected_data, $expected_count, $configuration, $high_water);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function providerSource() {
|
||||
$tests = [];
|
||||
|
||||
// The source data.
|
||||
$tests[0]['source_data']['i18n_variable'] = [
|
||||
[
|
||||
'name' => 'site_slogan',
|
||||
'language' => 'fr',
|
||||
'value' => 's:19:"Migrate est génial";',
|
||||
],
|
||||
[
|
||||
'name' => 'site_name',
|
||||
'language' => 'fr',
|
||||
'value' => 's:11:"nom de site";',
|
||||
],
|
||||
[
|
||||
'name' => 'site_slogan',
|
||||
'language' => 'mi',
|
||||
'value' => 's:19:"Ko whakamataku heke";',
|
||||
],
|
||||
[
|
||||
'name' => 'site_name',
|
||||
'language' => 'mi',
|
||||
'value' => 's:9:"ingoa_pae";',
|
||||
],
|
||||
];
|
||||
|
||||
// The expected results.
|
||||
$tests[0]['expected_data'] = [
|
||||
[
|
||||
'language' => 'fr',
|
||||
'site_slogan' => 'Migrate est génial',
|
||||
'site_name' => 'nom de site',
|
||||
],
|
||||
[
|
||||
'language' => 'mi',
|
||||
'site_slogan' => 'Ko whakamataku heke',
|
||||
'site_name' => 'ingoa_pae',
|
||||
],
|
||||
];
|
||||
|
||||
// The expected count.
|
||||
$tests[0]['expected_count'] = NULL;
|
||||
|
||||
// The migration configuration.
|
||||
$tests[0]['configuration']['variables'] = [
|
||||
'site_slogan',
|
||||
'site_name',
|
||||
];
|
||||
|
||||
return $tests;
|
||||
}
|
||||
|
||||
}
|
||||
+77
@@ -0,0 +1,77 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\Tests\migrate_drupal\Kernel\Plugin\migrate\source\d7;
|
||||
|
||||
use Drupal\Tests\migrate\Kernel\MigrateSqlSourceTestBase;
|
||||
|
||||
/**
|
||||
* Tests the variable source plugin.
|
||||
*
|
||||
* @covers \Drupal\migrate_drupal\Plugin\migrate\source\d7\VariableTranslation
|
||||
*
|
||||
* @group migrate_drupal
|
||||
*/
|
||||
class VariableTranslationTest extends MigrateSqlSourceTestBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static $modules = ['migrate_drupal'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function providerSource() {
|
||||
$tests = [];
|
||||
|
||||
// The source data.
|
||||
$tests[0]['source_data']['variable_store'] = [
|
||||
[
|
||||
'realm' => 'language',
|
||||
'realm_key' => 'fr',
|
||||
'name' => 'site_slogan',
|
||||
'value' => 'fr - site slogan',
|
||||
'serialized' => '0',
|
||||
],
|
||||
[
|
||||
'realm' => 'language',
|
||||
'realm_key' => 'fr',
|
||||
'name' => 'user_mail_status_blocked_subject',
|
||||
'value' => 'fr - BEGONE!',
|
||||
'serialized' => '0',
|
||||
],
|
||||
[
|
||||
'realm' => 'language',
|
||||
'realm_key' => 'is',
|
||||
'name' => 'site_slogan',
|
||||
'value' => 's:16:"is - site slogan";',
|
||||
'serialized' => '1',
|
||||
],
|
||||
];
|
||||
|
||||
// The expected results.
|
||||
$tests[0]['expected_data'] = [
|
||||
[
|
||||
'language' => 'fr',
|
||||
'site_slogan' => 'fr - site slogan',
|
||||
'user_mail_status_blocked_subject' => 'fr - BEGONE!',
|
||||
],
|
||||
[
|
||||
'language' => 'is',
|
||||
'site_slogan' => 'is - site slogan',
|
||||
],
|
||||
];
|
||||
|
||||
// The expected count.
|
||||
$tests[0]['expected_count'] = NULL;
|
||||
|
||||
// The migration configuration.
|
||||
$tests[0]['configuration']['variables'] = [
|
||||
'site_slogan',
|
||||
'user_mail_status_blocked_subject',
|
||||
];
|
||||
|
||||
return $tests;
|
||||
}
|
||||
|
||||
}
|
||||
+115
@@ -0,0 +1,115 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\Tests\migrate_drupal\Kernel\Plugin\migrate\source\d8;
|
||||
|
||||
use Drupal\Tests\migrate\Kernel\MigrateSqlSourceTestBase;
|
||||
|
||||
/**
|
||||
* Tests the config source plugin.
|
||||
*
|
||||
* @covers \Drupal\migrate_drupal\Plugin\migrate\source\d8\Config
|
||||
* @group migrate_drupal
|
||||
*/
|
||||
class ConfigTest extends MigrateSqlSourceTestBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static $modules = ['migrate_drupal'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function providerSource() {
|
||||
$data = [];
|
||||
|
||||
// The source database tables.
|
||||
$data[0]['source_data'] = [
|
||||
'config' => [
|
||||
[
|
||||
'collection' => 'language.af',
|
||||
'name' => 'user.settings',
|
||||
'data' => 'a:1:{s:9:"anonymous";s:14:"af - Anonymous";}',
|
||||
],
|
||||
[
|
||||
'collection' => '',
|
||||
'name' => 'user.settings',
|
||||
'data' => 'a:1:{s:9:"anonymous";s:9:"Anonymous";}',
|
||||
],
|
||||
[
|
||||
'collection' => 'language.de',
|
||||
'name' => 'user.settings',
|
||||
'data' => 'a:1:{s:9:"anonymous";s:14:"de - Anonymous";}',
|
||||
],
|
||||
[
|
||||
'collection' => 'language.af',
|
||||
'name' => 'bar',
|
||||
'data' => 'b:0;',
|
||||
],
|
||||
],
|
||||
];
|
||||
|
||||
// The expected results.
|
||||
$data[0]['expected_results'] = [
|
||||
[
|
||||
'collection' => 'language.af',
|
||||
'name' => 'user.settings',
|
||||
'data' => [
|
||||
'anonymous' => 'af - Anonymous',
|
||||
],
|
||||
],
|
||||
[
|
||||
'collection' => 'language.af',
|
||||
'name' => 'bar',
|
||||
'data' => FALSE,
|
||||
],
|
||||
];
|
||||
$data[0]['expected_count'] = NULL;
|
||||
$data[0]['configuration'] = [
|
||||
'names' => [
|
||||
'user.settings',
|
||||
'bar',
|
||||
],
|
||||
'collections' => [
|
||||
'language.af',
|
||||
],
|
||||
];
|
||||
|
||||
// Test with name and no collection in configuration.
|
||||
$data[1]['source_data'] = $data[0]['source_data'];
|
||||
$data[1]['expected_results'] = [
|
||||
[
|
||||
'collection' => 'language.af',
|
||||
'name' => 'bar',
|
||||
'data' => FALSE,
|
||||
],
|
||||
];
|
||||
$data[1]['expected_count'] = NULL;
|
||||
$data[1]['configuration'] = [
|
||||
'names' => [
|
||||
'bar',
|
||||
],
|
||||
];
|
||||
|
||||
// Test with collection and no name in configuration.
|
||||
$data[2]['source_data'] = $data[0]['source_data'];
|
||||
$data[2]['expected_results'] = [
|
||||
[
|
||||
'collection' => 'language.de',
|
||||
'name' => 'user.settings',
|
||||
'data' => [
|
||||
'anonymous' => 'de - Anonymous',
|
||||
],
|
||||
],
|
||||
];
|
||||
$data[2]['expected_count'] = NULL;
|
||||
$data[2]['configuration'] = [
|
||||
'collections' => [
|
||||
'language.de',
|
||||
],
|
||||
];
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,109 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\Tests\migrate_drupal\Kernel;
|
||||
|
||||
use Drupal\Component\Discovery\YamlDiscovery;
|
||||
use Drupal\KernelTests\FileSystemModuleDiscoveryDataProviderTrait;
|
||||
use Drupal\migrate_drupal\MigrationConfigurationTrait;
|
||||
use Drupal\Tests\DeprecatedModulesTestTrait;
|
||||
|
||||
/**
|
||||
* Tests that core modules have a migrate_drupal.yml file as needed.
|
||||
*
|
||||
* Checks that each module that requires a migrate_drupal.yml has the file.
|
||||
* Because more that one migrate_drupal.yml file may have the same entry the
|
||||
* ValidateMigrationStateTest, which validates the file contents, is not able
|
||||
* to determine that all the required files exits.
|
||||
*
|
||||
* @group migrate_drupal
|
||||
*/
|
||||
class StateFileExists extends MigrateDrupalTestBase {
|
||||
|
||||
use DeprecatedModulesTestTrait;
|
||||
use FileSystemModuleDiscoveryDataProviderTrait;
|
||||
use MigrationConfigurationTrait;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static $modules = [
|
||||
// Test migrations states.
|
||||
'migrate_state_finished_test',
|
||||
'migrate_state_not_finished_test',
|
||||
// Test missing migrate_drupal.yml.
|
||||
'migrate_state_no_file_test',
|
||||
];
|
||||
|
||||
/**
|
||||
* Modules that should have a migrate_drupal.yml file.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $stateFileRequired = [
|
||||
'action',
|
||||
'aggregator',
|
||||
'ban',
|
||||
'block',
|
||||
'block_content',
|
||||
'book',
|
||||
'color',
|
||||
'comment',
|
||||
'config_translation',
|
||||
'contact',
|
||||
'content_translation',
|
||||
'datetime',
|
||||
'dblog',
|
||||
'field',
|
||||
'file',
|
||||
'filter',
|
||||
'forum',
|
||||
'image',
|
||||
'language',
|
||||
'link',
|
||||
'locale',
|
||||
'menu_link_content',
|
||||
'migrate_state_finished_test',
|
||||
'migrate_state_not_finished_test',
|
||||
'menu_ui',
|
||||
'migrate_drupal',
|
||||
'node',
|
||||
'options',
|
||||
'path',
|
||||
'rdf',
|
||||
'search',
|
||||
'shortcut',
|
||||
'simpletest',
|
||||
'statistics',
|
||||
'syslog',
|
||||
'system',
|
||||
'taxonomy',
|
||||
'telephone',
|
||||
'text',
|
||||
'tracker',
|
||||
'update',
|
||||
'user',
|
||||
];
|
||||
|
||||
/**
|
||||
* Tests that the migrate_drupal.yml files exist as needed.
|
||||
*/
|
||||
public function testMigrationState() {
|
||||
// Install all available modules.
|
||||
$module_handler = $this->container->get('module_handler');
|
||||
$all_modules = $this->coreModuleListDataProvider();
|
||||
$modules_enabled = $module_handler->getModuleList();
|
||||
$modules_to_enable = array_keys(array_diff_key($all_modules, $modules_enabled));
|
||||
$this->enableModules($modules_to_enable);
|
||||
|
||||
// Modules with a migrate_drupal.yml file.
|
||||
$has_state_file = (new YamlDiscovery('migrate_drupal', array_map(function (&$value) {
|
||||
return $value . '/migrations/state';
|
||||
}, $module_handler->getModuleDirectories())))->findAll();
|
||||
|
||||
foreach ($this->stateFileRequired as $module) {
|
||||
$this->assertArrayHasKey($module, $has_state_file, sprintf("Module '%s' should have a migrate_drupal.yml file", $module));
|
||||
}
|
||||
$this->assertEquals(count($this->stateFileRequired), count($has_state_file));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,127 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\Tests\migrate_drupal\Kernel\d6;
|
||||
|
||||
use Drupal\field\Entity\FieldConfig;
|
||||
use Drupal\field\Entity\FieldStorageConfig;
|
||||
use Drupal\migrate\MigrateExecutable;
|
||||
use Drupal\migrate\MigrateMessageInterface;
|
||||
use Drupal\user\Entity\User;
|
||||
use Prophecy\Argument;
|
||||
|
||||
/**
|
||||
* @group migrate_drupal
|
||||
*/
|
||||
class EntityContentBaseTest extends MigrateDrupal6TestBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static $modules = ['migrate_overwrite_test'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
|
||||
// Create a field on the user entity so that we can test nested property
|
||||
// overwrites.
|
||||
// @see static::testOverwriteSelectedNestedProperty()
|
||||
FieldStorageConfig::create([
|
||||
'field_name' => 'signature',
|
||||
'entity_type' => 'user',
|
||||
'type' => 'text_long',
|
||||
])->save();
|
||||
|
||||
FieldConfig::create([
|
||||
'field_name' => 'signature',
|
||||
'entity_type' => 'user',
|
||||
'bundle' => 'user',
|
||||
])->save();
|
||||
|
||||
User::create([
|
||||
'uid' => 2,
|
||||
'name' => 'Ford Prefect',
|
||||
'mail' => 'ford.prefect@localhost',
|
||||
'signature' => [
|
||||
[
|
||||
'value' => 'Bring a towel.',
|
||||
'format' => 'filtered_html',
|
||||
],
|
||||
],
|
||||
'init' => 'proto@zo.an',
|
||||
])->save();
|
||||
|
||||
$this->executeMigrations(['d6_filter_format', 'd6_user_role']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests overwriting all mapped properties in the destination entity (default
|
||||
* behavior).
|
||||
*/
|
||||
public function testOverwriteAllMappedProperties() {
|
||||
$this->executeMigration('d6_user');
|
||||
/** @var \Drupal\user\UserInterface $account */
|
||||
$account = User::load(2);
|
||||
$this->assertIdentical('john.doe', $account->label());
|
||||
$this->assertIdentical('john.doe@example.com', $account->getEmail());
|
||||
$this->assertIdentical('doe@example.com', $account->getInitialEmail());
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests overwriting selected properties in the destination entity, specified
|
||||
* in the destination configuration.
|
||||
*/
|
||||
public function testOverwriteProperties() {
|
||||
// Execute the migration in migrate_overwrite_test, which documents how
|
||||
// property overwrites work.
|
||||
$this->executeMigration('users');
|
||||
|
||||
/** @var \Drupal\user\UserInterface $account */
|
||||
$account = User::load(2);
|
||||
$this->assertIdentical('john.doe', $account->label());
|
||||
$this->assertIdentical('john.doe@example.com', $account->getEmail());
|
||||
$this->assertIdentical('The answer is 42.', $account->signature->value);
|
||||
// This value is not overwritten because it's not listed in
|
||||
// overwrite_properties.
|
||||
$this->assertIdentical('proto@zo.an', $account->getInitialEmail());
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that translation destination fails for untranslatable entities.
|
||||
*/
|
||||
public function testUntranslatable() {
|
||||
$this->enableModules(['language_test']);
|
||||
$this->installEntitySchema('no_language_entity_test');
|
||||
|
||||
/** @var MigrationInterface $migration */
|
||||
$migration = \Drupal::service('plugin.manager.migration')->createStubMigration([
|
||||
'source' => [
|
||||
'plugin' => 'embedded_data',
|
||||
'ids' => ['id' => ['type' => 'integer']],
|
||||
'data_rows' => [['id' => 1]],
|
||||
],
|
||||
'process' => [
|
||||
'id' => 'id',
|
||||
],
|
||||
'destination' => [
|
||||
'plugin' => 'entity:no_language_entity_test',
|
||||
'translations' => TRUE,
|
||||
],
|
||||
]);
|
||||
|
||||
$message = $this->prophesize(MigrateMessageInterface::class);
|
||||
// Match the expected message. Can't use default argument types, because
|
||||
// we need to convert to string from TranslatableMarkup.
|
||||
$argument = Argument::that(function ($msg) {
|
||||
return strpos((string) $msg, htmlentities('The "no_language_entity_test" entity type does not support translations.')) !== FALSE;
|
||||
});
|
||||
$message->display($argument, Argument::any())
|
||||
->shouldBeCalled();
|
||||
|
||||
$executable = new MigrateExecutable($migration, $message->reveal());
|
||||
$executable->import();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,304 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\Tests\migrate_drupal\Kernel\d6;
|
||||
|
||||
use Drupal\field\Plugin\migrate\source\d6\FieldInstance;
|
||||
use Drupal\field_discovery_test\FieldDiscoveryTestClass;
|
||||
use Drupal\migrate_drupal\FieldDiscoveryInterface;
|
||||
use Drupal\Tests\migrate_drupal\Traits\FieldDiscoveryTestTrait;
|
||||
|
||||
/**
|
||||
* Tests FieldDiscovery service against Drupal 6.
|
||||
*
|
||||
* @group migrate_drupal
|
||||
* @coversDefaultClass \Drupal\migrate_drupal\FieldDiscovery
|
||||
*/
|
||||
class FieldDiscoveryTest extends MigrateDrupal6TestBase {
|
||||
|
||||
use FieldDiscoveryTestTrait;
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static $modules = [
|
||||
'menu_ui',
|
||||
'comment',
|
||||
'datetime',
|
||||
'file',
|
||||
'image',
|
||||
'link',
|
||||
'node',
|
||||
'system',
|
||||
'taxonomy',
|
||||
'telephone',
|
||||
'text',
|
||||
];
|
||||
|
||||
/**
|
||||
* The Field discovery service.
|
||||
*
|
||||
* @var \Drupal\migrate_drupal\FieldDiscoveryInterface
|
||||
*/
|
||||
protected $fieldDiscovery;
|
||||
|
||||
/**
|
||||
* The field plugin manager.
|
||||
*
|
||||
* @var \Drupal\migrate_drupal\Plugin\MigrateFieldPluginManagerInterface
|
||||
*/
|
||||
protected $fieldPluginManager;
|
||||
|
||||
/**
|
||||
* The migration plugin manager.
|
||||
*
|
||||
* @var \Drupal\migrate\Plugin\MigrationPluginManagerInterface
|
||||
*/
|
||||
protected $migrationPluginManager;
|
||||
/**
|
||||
* The logger.
|
||||
*
|
||||
* @var \Drupal\Core\Logger\LoggerChannelInterface
|
||||
*/
|
||||
protected $logger;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function setUp() {
|
||||
parent::setUp();
|
||||
$this->installConfig(['node']);
|
||||
$this->executeMigration('d6_node_type');
|
||||
$this->executeMigration('d6_field');
|
||||
$this->executeMigration('d6_field_instance');
|
||||
$this->fieldDiscovery = $this->container->get('migrate_drupal.field_discovery');
|
||||
$this->migrationPluginManager = $this->container->get('plugin.manager.migration');
|
||||
$this->fieldPluginManager = $this->container->get('plugin.manager.migrate.field');
|
||||
$this->logger = $this->container->get('logger.channel.migrate_drupal');
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the addAllFieldProcesses method.
|
||||
*
|
||||
* @covers ::addAllFieldProcesses
|
||||
*/
|
||||
public function testAddAllFieldProcesses() {
|
||||
$expected_process_keys = [
|
||||
'field_commander',
|
||||
'field_company',
|
||||
'field_company_2',
|
||||
'field_company_3',
|
||||
'field_sync',
|
||||
'field_multivalue',
|
||||
'field_test_text_single_checkbox',
|
||||
'field_reference',
|
||||
'field_reference_2',
|
||||
'field_test',
|
||||
'field_test_date',
|
||||
'field_test_datestamp',
|
||||
'field_test_datetime',
|
||||
'field_test_decimal_radio_buttons',
|
||||
'field_test_email',
|
||||
'field_test_exclude_unset',
|
||||
'field_test_filefield',
|
||||
'field_test_float_single_checkbox',
|
||||
'field_test_four',
|
||||
'field_test_identical1',
|
||||
'field_test_identical2',
|
||||
'field_test_imagefield',
|
||||
'field_test_integer_selectlist',
|
||||
'field_test_link',
|
||||
'field_test_phone',
|
||||
'field_test_string_selectlist',
|
||||
'field_test_text_single_checkbox2',
|
||||
'field_test_three',
|
||||
'field_test_two',
|
||||
];
|
||||
$this->assertFieldProcessKeys($this->fieldDiscovery, $this->migrationPluginManager, FieldDiscoveryInterface::DRUPAL_6, $expected_process_keys);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the addAllFieldProcesses method for field migrations.
|
||||
*
|
||||
* @covers ::addAllFieldProcesses
|
||||
* @dataProvider addAllFieldProcessesAltersData
|
||||
*/
|
||||
public function testAddAllFieldProcessesAlters($field_plugin_method, $expected_process) {
|
||||
$this->assertFieldProcess($this->fieldDiscovery, $this->migrationPluginManager, FieldDiscoveryInterface::DRUPAL_6, $field_plugin_method, $expected_process);
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides data for testAddAllFieldProcessesAlters.
|
||||
*
|
||||
* @return array
|
||||
* The data.
|
||||
*/
|
||||
public function addAllFieldProcessesAltersData() {
|
||||
return [
|
||||
'Field Formatter' => [
|
||||
'field_plugin_method' => 'alterFieldFormatterMigration',
|
||||
'expected_process' => [
|
||||
'options/type' => [
|
||||
0 => [
|
||||
'map' => [
|
||||
'email' => [
|
||||
'email_formatter_default' => 'email_mailto',
|
||||
'email_formatter_contact' => 'basic_string',
|
||||
'email_formatter_plain' => 'basic_string',
|
||||
'email_formatter_spamspan' => 'basic_string',
|
||||
'email_default' => 'email_mailto',
|
||||
'email_contact' => 'basic_string',
|
||||
'email_plain' => 'basic_string',
|
||||
'email_spamspan' => 'basic_string',
|
||||
],
|
||||
'text' => [
|
||||
'default' => 'text_default',
|
||||
'trimmed' => 'text_trimmed',
|
||||
'plain' => 'basic_string',
|
||||
],
|
||||
'datetime' => [
|
||||
'date_default' => 'datetime_default',
|
||||
],
|
||||
'filefield' => [
|
||||
'default' => 'file_default',
|
||||
'url_plain' => 'file_url_plain',
|
||||
'path_plain' => 'file_url_plain',
|
||||
'image_plain' => 'image',
|
||||
'image_nodelink' => 'image',
|
||||
'image_imagelink' => 'image',
|
||||
],
|
||||
'link' => [
|
||||
'default' => 'link',
|
||||
'plain' => 'link',
|
||||
'absolute' => 'link',
|
||||
'title_plain' => 'link',
|
||||
'url' => 'link',
|
||||
'short' => 'link',
|
||||
'label' => 'link',
|
||||
'separate' => 'link_separate',
|
||||
],
|
||||
],
|
||||
],
|
||||
],
|
||||
],
|
||||
],
|
||||
'Field Widget' => [
|
||||
'field_plugin_method' => 'alterFieldWidgetMigration',
|
||||
'expected_process' => [
|
||||
'options/type' => [
|
||||
'type' => [
|
||||
'map' => [
|
||||
'userreference' => 'userreference_default',
|
||||
'nodereference' => 'nodereference_default',
|
||||
'email_textfield' => 'email_default',
|
||||
'text_textfield' => 'text_textfield',
|
||||
'date' => 'datetime_default',
|
||||
'datetime' => 'datetime_default',
|
||||
'datestamp' => 'datetime_timestamp',
|
||||
'filefield_widget' => 'file_generic',
|
||||
'link' => 'link_default',
|
||||
],
|
||||
],
|
||||
],
|
||||
],
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the addFields method.
|
||||
*
|
||||
* @covers ::addAllFieldProcesses
|
||||
*/
|
||||
public function testAddFields() {
|
||||
$this->migrateFields();
|
||||
$field_discovery = $this->container->get('migrate_drupal.field_discovery');
|
||||
$migration_plugin_manager = $this->container->get('plugin.manager.migration');
|
||||
$definition = [
|
||||
'migration_tags' => ['Drupal 6'],
|
||||
];
|
||||
$migration = $migration_plugin_manager->createStubMigration($definition);
|
||||
$field_discovery->addBundleFieldProcesses($migration, 'node', 'test_planet');
|
||||
$actual_process = $migration->getProcess();
|
||||
$expected_process = [
|
||||
'field_multivalue' => [
|
||||
0 => [
|
||||
'plugin' => 'get',
|
||||
'source' => 'field_multivalue',
|
||||
],
|
||||
],
|
||||
'field_test_text_single_checkbox' => [
|
||||
0 => [
|
||||
'plugin' => 'sub_process',
|
||||
'source' => 'field_test_text_single_checkbox',
|
||||
'process' => [
|
||||
'value' => 'value',
|
||||
'format' => [
|
||||
0 => [
|
||||
'plugin' => 'static_map',
|
||||
'bypass' => TRUE,
|
||||
'source' => 'format',
|
||||
'map' => [
|
||||
0 => NULL,
|
||||
],
|
||||
],
|
||||
1 => [
|
||||
'plugin' => 'skip_on_empty',
|
||||
'method' => 'process',
|
||||
],
|
||||
2 => [
|
||||
'plugin' => 'migration_lookup',
|
||||
'migration' => [
|
||||
0 => 'd6_filter_format',
|
||||
1 => 'd7_filter_format',
|
||||
],
|
||||
'source' => 'format',
|
||||
],
|
||||
],
|
||||
],
|
||||
],
|
||||
],
|
||||
];
|
||||
$this->assertEquals($expected_process, $actual_process);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the getAllFields method.
|
||||
*
|
||||
* @covers ::getAllFields
|
||||
*/
|
||||
public function testGetAllFields() {
|
||||
$field_discovery_test = new FieldDiscoveryTestClass($this->fieldPluginManager, $this->migrationPluginManager, $this->logger);
|
||||
$actual_fields = $field_discovery_test->getAllFields('6');
|
||||
$this->assertSame(['node'], array_keys($actual_fields));
|
||||
$this->assertSame(['employee', 'test_planet', 'page', 'story', 'test_page'], array_keys($actual_fields['node']));
|
||||
$this->assertCount(21, $actual_fields['node']['story']);
|
||||
foreach ($actual_fields['node'] as $bundle => $fields) {
|
||||
foreach ($fields as $field_name => $field_info) {
|
||||
$this->assertArrayHasKey('type', $field_info);
|
||||
$this->assertCount(22, $field_info);
|
||||
$this->assertEquals($bundle, $field_info['type_name']);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the getSourcePlugin method.
|
||||
*
|
||||
* @covers ::getSourcePlugin
|
||||
*/
|
||||
public function testGetSourcePlugin() {
|
||||
$this->assertSourcePlugin('6', FieldInstance::class, [
|
||||
'requirements_met' => TRUE,
|
||||
'id' => 'd6_field_instance',
|
||||
'source_module' => 'content',
|
||||
'class' => 'Drupal\\field\\Plugin\\migrate\\source\\d6\\FieldInstance',
|
||||
'provider' => [
|
||||
0 => 'field',
|
||||
1 => 'migrate_drupal',
|
||||
2 => 'migrate',
|
||||
4 => 'core',
|
||||
],
|
||||
]);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\Tests\migrate_drupal\Kernel\d6;
|
||||
|
||||
use Drupal\node\Entity\Node;
|
||||
use Drupal\Tests\node\Kernel\Migrate\d6\MigrateNodeTestBase;
|
||||
|
||||
/**
|
||||
* Tests follow-up migrations.
|
||||
*
|
||||
* @group migrate_drupal
|
||||
*/
|
||||
class FollowUpMigrationsTest extends MigrateNodeTestBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static $modules = [
|
||||
'content_translation',
|
||||
'language',
|
||||
'menu_ui',
|
||||
// A requirement for d6_node_translation.
|
||||
'migrate_drupal_multilingual',
|
||||
];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
$this->executeMigrations([
|
||||
'language',
|
||||
'd6_language_content_settings',
|
||||
'd6_node',
|
||||
'd6_node_translation',
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test entity reference translations.
|
||||
*/
|
||||
public function testEntityReferenceTranslations() {
|
||||
// Test the entity reference field before the follow-up migrations.
|
||||
$node = Node::load(10);
|
||||
$this->assertSame('13', $node->get('field_reference')->target_id);
|
||||
$this->assertSame('13', $node->get('field_reference_2')->target_id);
|
||||
$translation = $node->getTranslation('fr');
|
||||
$this->assertSame('20', $translation->get('field_reference')->target_id);
|
||||
$this->assertSame('20', $translation->get('field_reference_2')->target_id);
|
||||
|
||||
$node = Node::load(12)->getTranslation('en');
|
||||
$this->assertSame('10', $node->get('field_reference')->target_id);
|
||||
$this->assertSame('10', $node->get('field_reference_2')->target_id);
|
||||
$translation = $node->getTranslation('fr');
|
||||
$this->assertSame('11', $translation->get('field_reference')->target_id);
|
||||
$this->assertSame('11', $translation->get('field_reference_2')->target_id);
|
||||
|
||||
// Run the follow-up migrations.
|
||||
$migration_plugin_manager = $this->container->get('plugin.manager.migration');
|
||||
$migration_plugin_manager->clearCachedDefinitions();
|
||||
$follow_up_migrations = $migration_plugin_manager->createInstances('d6_entity_reference_translation');
|
||||
$this->executeMigrations(array_keys($follow_up_migrations));
|
||||
|
||||
// Test the entity reference field after the follow-up migrations.
|
||||
$node = Node::load(10);
|
||||
$this->assertSame('12', $node->get('field_reference')->target_id);
|
||||
$this->assertSame('12', $node->get('field_reference_2')->target_id);
|
||||
$translation = $node->getTranslation('fr');
|
||||
$this->assertSame('12', $translation->get('field_reference')->target_id);
|
||||
$this->assertSame('12', $translation->get('field_reference_2')->target_id);
|
||||
|
||||
$node = Node::load(12)->getTranslation('en');
|
||||
$this->assertSame('10', $node->get('field_reference')->target_id);
|
||||
$this->assertSame('10', $node->get('field_reference_2')->target_id);
|
||||
$translation = $node->getTranslation('fr');
|
||||
$this->assertSame('10', $translation->get('field_reference')->target_id);
|
||||
$this->assertSame('10', $translation->get('field_reference_2')->target_id);
|
||||
}
|
||||
|
||||
}
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\Tests\migrate_drupal\Kernel\d6;
|
||||
|
||||
/**
|
||||
* Extends MigrateDrupal6AuditIdsTest to test with deprecated modules.
|
||||
*
|
||||
* @see \Drupal\Tests\DeprecatedModulesTestTrait::removeDeprecatedModules()
|
||||
*
|
||||
* @group migrate_drupal
|
||||
* @group legacy
|
||||
*/
|
||||
class LegacyMigrateDrupal6AuditIdsTest extends MigrateDrupal6AuditIdsTest {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected $excludeDeprecated = FALSE;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\Tests\migrate_drupal\Kernel\d6;
|
||||
|
||||
/**
|
||||
* Extends Drupal\Tests\migrate_drupal\Kernel\d6\MigrationProcessTest to test
|
||||
* with deprecated modules.
|
||||
*
|
||||
* @see \Drupal\Tests\DeprecatedModulesTestTrait::removeDeprecatedModules()
|
||||
*
|
||||
* @group migrate_drupal
|
||||
* @group legacy
|
||||
*/
|
||||
class LegacyMigrationProcessTest extends MigrationProcessTest {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected $excludeDeprecated = FALSE;
|
||||
|
||||
}
|
||||
+21
@@ -0,0 +1,21 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\Tests\migrate_drupal\Kernel\d6;
|
||||
|
||||
/**
|
||||
* Extends Drupal\Tests\migrate_drupal\Kernel\d6\ValidateMigrationStateTest
|
||||
* to test with deprecated modules.
|
||||
*
|
||||
* @see \Drupal\Tests\DeprecatedModulesTestTrait::removeDeprecatedModules()
|
||||
*
|
||||
* @group migrate_drupal
|
||||
* @group legacy
|
||||
*/
|
||||
class LegacyValidateMigrationStateTest extends ValidateMigrationStateTest {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected $excludeDeprecated = FALSE;
|
||||
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user