updated core from 8.4 to 8.5 : bug with login_destination

This commit is contained in:
Bachir Soussi Chiadmi
2018-03-13 14:01:21 +01:00
parent 0d78da249b
commit e668535a4e
3486 changed files with 89604 additions and 33283 deletions
@@ -0,0 +1,5 @@
# 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
@@ -0,0 +1,10 @@
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'
@@ -7,8 +7,8 @@ package: Core (Experimental)
dependencies:
- migrate
# Information added by Drupal.org packaging script on 2018-01-03
version: '8.4.4'
# Information added by Drupal.org packaging script on 2018-03-07
version: '8.5.0'
core: '8.x'
project: 'drupal'
datestamp: 1515021228
datestamp: 1520457825
@@ -0,0 +1,16 @@
<?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();
}
@@ -9,7 +9,6 @@ use Drupal\Core\Database\DatabaseExceptionWrapper;
use Drupal\Core\Routing\RouteMatchInterface;
use Drupal\migrate\Exception\RequirementsException;
use Drupal\migrate\MigrateExecutable;
use Drupal\migrate\MigrateMessage;
use Drupal\migrate\Plugin\RequirementsInterface;
/**
@@ -41,6 +40,9 @@ function migrate_drupal_migration_plugins_alter(&$definitions) {
'destination' => [
'plugin' => 'null',
],
'idMap' => [
'plugin' => 'null',
],
];
$vocabulary_migration = \Drupal::service('plugin.manager.migration')->createStubMigration($vocabulary_migration_definition);
@@ -49,7 +51,7 @@ function migrate_drupal_migration_plugins_alter(&$definitions) {
if ($source_plugin instanceof RequirementsInterface) {
$source_plugin->checkRequirements();
}
$executable = new MigrateExecutable($vocabulary_migration, new MigrateMessage());
$executable = new MigrateExecutable($vocabulary_migration);
$process = ['vid' => $definitions['d6_taxonomy_vocabulary']['process']['vid']];
foreach ($source_plugin as $row) {
$executable->processRow($row, $process);
@@ -49,6 +49,26 @@ class MigrateField extends Plugin {
*
* @var int[]
*/
public $core = [];
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
* 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;
}
@@ -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'));
}
}
@@ -125,8 +125,8 @@ trait MigrationConfigurationTrait {
* @param \Drupal\Core\Database\Connection $connection
* The database connection object.
*
* @return int|false
* An integer representing the major branch of Drupal core (e.g. '6' for
* @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.
*/
protected function getLegacyDrupalVersion(Connection $connection) {
@@ -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');
}
}
}
}
@@ -3,6 +3,7 @@
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;
@@ -53,4 +54,17 @@ class MigrateFieldPluginManager extends MigratePluginManager implements MigrateF
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);
}
}
}
}
@@ -11,6 +11,8 @@ use Drupal\migrate\Plugin\MigrationInterface;
* type_map = {
* "nodereference" = "entity_reference",
* },
* source_module = "nodereference",
* destination_module = "core",
* )
*/
class NodeReference extends FieldPluginBase {
@@ -11,6 +11,8 @@ use Drupal\migrate\Plugin\MigrationInterface;
* type_map = {
* "userreference" = "entity_reference",
* },
* source_module = "userreference",
* destination_module = "core",
* )
*/
class UserReference extends FieldPluginBase {
@@ -0,0 +1,294 @@
<?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\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 {
/**
* 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->isTranslatable()) {
$langcode_key = $this->entityType->getKey('langcode');
$ids[$langcode_key] = $this->getDefinitionFromEntity($langcode_key);
}
return $ids;
}
/**
* Gets the field definition from a specific entity base field.
*
* @param string $key
* The field ID key.
*
* @return array
* An associative array with a structure that contains the field type, keyed
* as 'type', together with field storage settings as they are returned by
* FieldStorageDefinitionInterface::getSettings().
*
* @see \Drupal\migrate\Plugin\migrate\destination\EntityContentBase::getDefinitionFromEntity()
*/
protected function getDefinitionFromEntity($key) {
/** @var \Drupal\Core\Field\FieldDefinitionInterface $field_definition */
$field_definition = $this->entityFieldManager->getBaseFieldDefinitions($this->entityType->id())[$key];
return [
'type' => $field_definition->getType(),
] + $field_definition->getSettings();
}
}
@@ -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);
}
}
@@ -14,7 +14,8 @@ use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
* Source returning an empty row with Drupal specific config dependencies.
*
* @MigrateSource(
* id = "md_empty"
* id = "md_empty",
* source_module = "system",
* )
*/
class EmptySource extends BaseEmptySource implements ContainerFactoryPluginInterface, DependentPluginInterface {
@@ -13,7 +13,8 @@ use Drupal\migrate\Plugin\MigrationInterface;
* example for any normal source class returning multiple rows.
*
* @MigrateSource(
* id = "variable"
* id = "variable",
* source_module = "system",
* )
*/
class Variable extends DrupalSqlBase {
@@ -11,7 +11,8 @@ use Drupal\migrate\Row;
* variable.
*
* @MigrateSource(
* id = "variable_multirow"
* id = "variable_multirow",
* source_module = "system",
* )
*/
class VariableMultiRow extends DrupalSqlBase {
@@ -11,7 +11,8 @@ use Drupal\migrate_drupal\Plugin\migrate\source\DrupalSqlBase;
* Drupal i18n_variable source from database.
*
* @MigrateSource(
* id = "variable_translation"
* id = "variable_translation",
* source_module = "system",
* )
*/
class VariableTranslation extends DrupalSqlBase {
@@ -8,7 +8,8 @@ namespace Drupal\migrate_drupal\Plugin\migrate\source\d6;
* Drupal i18n_variable source from database.
*
* @MigrateSource(
* id = "i18n_variable"
* id = "i18n_variable",
* source_module = "system",
* )
*
* @deprecated in Drupal 8.4.x and will be removed in Drupal 9.0.x. Use
@@ -9,7 +9,8 @@ use Drupal\migrate_drupal\Plugin\migrate\source\DrupalSqlBase;
* Drupal config source from database.
*
* @MigrateSource(
* id = "d8_config"
* id = "d8_config",
* source_module = "system",
* )
*/
class Config extends DrupalSqlBase {
+47 -3
View File
@@ -3780,9 +3780,9 @@ $connection->insert('content_type_story')
'field_test_phone_value' => NULL,
'field_test_exclude_unset_value' => 'text for default value',
'field_test_exclude_unset_format' => '1',
'field_test_imagefield_fid' => NULL,
'field_test_imagefield_list' => NULL,
'field_test_imagefield_data' => NULL,
'field_test_imagefield_fid' => '2',
'field_test_imagefield_list' => '1',
'field_test_imagefield_data' => 'a:2:{s:3:"alt";s:8:"Test alt";s:5:"title";s:10:"Test title";}',
'field_test_text_single_checkbox2_value' => 'Off',
'field_test_datestamp_value2' => '1391357160',
'field_test_datetime_value2' => '2015-03-04 06:07:00',
@@ -43534,6 +43534,36 @@ $connection->insert('node_counter')
'daycount',
'timestamp',
))
->values(array(
'nid' => '1',
'totalcount' => '2',
'daycount' => '0',
'timestamp' => '1421727536',
))
->values(array(
'nid' => '2',
'totalcount' => '1',
'daycount' => '0',
'timestamp' => '1471428059',
))
->values(array(
'nid' => '3',
'totalcount' => '1',
'daycount' => '0',
'timestamp' => '1471428153',
))
->values(array(
'nid' => '4',
'totalcount' => '1',
'daycount' => '1',
'timestamp' => '1478755275',
))
->values(array(
'nid' => '5',
'totalcount' => '1',
'daycount' => '1',
'timestamp' => '1478755314',
))
->values(array(
'nid' => '14',
'totalcount' => '1',
@@ -46469,6 +46499,14 @@ $connection->insert('upload')
'list' => '0',
'weight' => '1',
))
->values(array(
'fid' => '3',
'nid' => '12',
'vid' => '15',
'description' => 'file 12-15-3',
'list' => '0',
'weight' => '0',
))
->execute();
$connection->schema()->createTable('url_alias', array(
@@ -46553,6 +46591,12 @@ $connection->insert('url_alias')
'dst' => 'the-zulu-people',
'language' => 'en',
))
->values(array(
'pid' => '8',
'src' => 'admin',
'dst' => 'source-noslash',
'language' => '',
))
->execute();
$connection->schema()->createTable('users', array(
@@ -45982,6 +45982,12 @@ $connection->insert('url_alias')
'alias' => 'firefly',
'language' => 'en',
))
->values(array(
'pid' => '6',
'source' => 'admin',
'alias' => 'source-noslash',
'language' => 'und',
))
->execute();
$connection->schema()->createTable('users', array(
@@ -5,8 +5,8 @@ package: Testing
# version: VERSION
# core: 8.x
# Information added by Drupal.org packaging script on 2018-01-03
version: '8.4.4'
# Information added by Drupal.org packaging script on 2018-03-07
version: '8.5.0'
core: '8.x'
project: 'drupal'
datestamp: 1515021228
datestamp: 1520457825
@@ -11,7 +11,9 @@ use Drupal\migrate\Plugin\MigrationInterface;
* core = {6},
* type_map = {
* "file" = "file"
* }
* },
* source_module = "foo",
* destination_module = "bar"
* )
*/
class D6FileField extends CckFieldPluginBase {
@@ -7,7 +7,9 @@ use Drupal\migrate\Plugin\MigrationInterface;
/**
* @MigrateCckField(
* id = "d6_no_core_version_specified"
* id = "d6_no_core_version_specified",
* source_module = "foo",
* destination_module = "bar",
* )
*/
class D6NoCoreVersionSpecified extends CckFieldPluginBase {
@@ -5,8 +5,8 @@ package: Testing
# version: VERSION
# core: 8.x
# Information added by Drupal.org packaging script on 2018-01-03
version: '8.4.4'
# Information added by Drupal.org packaging script on 2018-03-07
version: '8.5.0'
core: '8.x'
project: 'drupal'
datestamp: 1515021228
datestamp: 1520457825
@@ -10,7 +10,9 @@ use Drupal\migrate_drupal\Plugin\migrate\field\FieldPluginBase;
* core = {6},
* type_map = {
* "file" = "file"
* }
* },
* source_module = "foo",
* destination_module = "bar"
* )
*/
class D6FileField extends FieldPluginBase {}
@@ -6,10 +6,9 @@ use Drupal\migrate_drupal\Plugin\migrate\field\FieldPluginBase;
/**
* @MigrateField(
* id = "d6_no_core_version_specified"
* id = "d6_no_core_version_specified",
* source_module = "foo",
* destination_module = "bar",
* )
*/
class D6NoCoreVersionSpecified extends FieldPluginBase {
}
class D6NoCoreVersionSpecified extends FieldPluginBase {}
@@ -5,8 +5,8 @@ package: Testing
# version: VERSION
# core: 8.x
# Information added by Drupal.org packaging script on 2018-01-03
version: '8.4.4'
# Information added by Drupal.org packaging script on 2018-03-07
version: '8.5.0'
core: '8.x'
project: 'drupal'
datestamp: 1515021228
datestamp: 1520457825
@@ -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);
}
}
@@ -14,7 +14,7 @@ class MigrateFieldPluginManagerTest extends MigrateDrupalTestBase {
/**
* {@inheritdoc}
*/
public static $modules = ['system', 'user', 'field', 'migrate_drupal', 'options', 'file', 'text', 'link', 'migrate_field_plugin_manager_test'];
public static $modules = ['system', 'user', 'field', 'migrate_drupal', 'options', 'file', 'image', 'text', 'link', 'migrate_field_plugin_manager_test'];
/**
* Tests that the correct MigrateField plugins are used.
@@ -0,0 +1,128 @@
<?php
namespace Drupal\Tests\migrate_drupal\Kernel\Plugin\migrate;
use Drupal\ban\Plugin\migrate\destination\BlockedIP;
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\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;
/**
* The migration plugin manager.
*
* @var \Drupal\migrate\Plugin\MigrationPluginManager
*/
protected $migrationManager;
/**
* {@inheritdoc}
*/
protected function setUp() {
// Enable all modules.
self::$modules = array_keys($this->coreModuleListDataProvider());
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 [
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,
];
}
}
@@ -0,0 +1,444 @@
<?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\field\Tests\EntityReference\EntityReferenceTestTrait;
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\media\Functional\MediaFunctionalTestCreateMediaTypeTrait;
use Drupal\user\Entity\User;
/**
* Tests the entity content source plugin.
*
* @group migrate_drupal
*/
class ContentEntityTest extends KernelTestBase {
use EntityReferenceTestTrait;
use MediaFunctionalTestCreateMediaTypeTrait;
/**
* {@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->setExpectedException(InvalidPluginDefinitionException::class, '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->setExpectedException(InvalidPluginDefinitionException::class, '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->setExpectedException(\InvalidArgumentException::class, '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->setExpectedException(\InvalidArgumentException::class, '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('user entities', $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('file entities', $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('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('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',
'bundle' => 'image',
'label' => 'Image',
'source' => 'test',
'new_revision' => FALSE,
];
$media_type = $this->createMediaType($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('name', $fields);
$this->assertArrayHasKey('status', $fields);
$media_source->rewind();
$values = $media_source->current()->getSource();
$this->assertEquals(1, $values['mid']);
$this->assertEquals('Foo media', $values['name'][0]['value']);
$this->assertEquals('Foo media', $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 term entities', $term_source->__toString());
$this->assertEquals(2, $term_source->count());
$ids = $term_source->getIds();
$this->assertArrayHasKey('langcode', $ids);
$this->assertArrayHasKey('tid', $ids);
$fields = $term_source->fields();
$this->assertArrayHasKey('vid', $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',
],
];
}
}
@@ -0,0 +1,197 @@
<?php
namespace Drupal\Tests\migrate_drupal\Kernel\d6;
use Drupal\KernelTests\FileSystemModuleDiscoveryDataProviderTrait;
use Drupal\migrate\Audit\AuditResult;
use Drupal\migrate\Audit\IdAuditor;
use Drupal\node\Entity\Node;
use Drupal\node\Entity\NodeType;
use Drupal\Tests\migrate_drupal\Traits\CreateTestContentEntitiesTrait;
use Drupal\workflows\Entity\Workflow;
/**
* Tests the migration auditor for ID conflicts.
*
* @group migrate_drupal
*/
class MigrateDrupal6AuditIdsTest extends MigrateDrupal6TestBase {
use FileSystemModuleDiscoveryDataProviderTrait;
use CreateTestContentEntitiesTrait;
/**
* {@inheritdoc}
*/
protected function setUp() {
// Enable all modules.
self::$modules = array_keys($this->coreModuleListDataProvider());
parent::setUp();
// Install required entity schemas.
$this->installEntitySchemas();
// Install required schemas.
$this->installSchema('book', ['book']);
$this->installSchema('dblog', ['watchdog']);
$this->installSchema('forum', ['forum_index']);
$this->installSchema('node', ['node_access']);
$this->installSchema('search', ['search_dataset']);
$this->installSchema('system', ['sequences']);
$this->installSchema('tracker', ['tracker_node', 'tracker_user']);
// Enable content moderation for nodes of type page.
$this->installEntitySchema('content_moderation_state');
$this->installConfig('content_moderation');
NodeType::create(['type' => 'page'])->save();
$workflow = Workflow::load('editorial');
$workflow->getTypePlugin()->addEntityTypeAndBundle('node', 'page');
$workflow->save();
}
/**
* Tests multiple migrations to the same destination with no ID conflicts.
*/
public function testMultipleMigrationWithoutIdConflicts() {
// Create a node of type page.
$node = Node::create(['type' => 'page', 'title' => 'foo']);
$node->moderation_state->value = 'published';
$node->save();
// Insert data in the d6_node:page migration mappping table to simulate a
// previously migrated node.
$table_name = $this->getMigration('d6_node:page')->getIdMap()->mapTableName();
$this->container->get('database')->insert($table_name)
->fields([
'source_ids_hash' => 1,
'sourceid1' => 1,
'destid1' => 1,
])
->execute();
// Audit the IDs of the d6_node migrations for the page & article node type.
// There should be no conflicts since the highest destination ID should be
// equal to the highest migrated ID, as found in the aggregated mapping
// tables of the two node migrations.
$migrations = [
$this->getMigration('d6_node:page'),
$this->getMigration('d6_node:article'),
];
$results = (new IdAuditor())->auditMultiple($migrations);
/** @var \Drupal\migrate\Audit\AuditResult $result */
foreach ($results as $result) {
$this->assertInstanceOf(AuditResult::class, $result);
$this->assertTrue($result->passed());
}
}
/**
* Tests all migrations with no ID conflicts.
*/
public function testAllMigrationsWithNoIdConflicts() {
$migrations = $this->container
->get('plugin.manager.migration')
->createInstancesByTag('Drupal 6');
// Audit all Drupal 6 migrations that support it. There should be no
// conflicts since no content has been created.
$results = (new IdAuditor())->auditMultiple($migrations);
/** @var \Drupal\migrate\Audit\AuditResult $result */
foreach ($results as $result) {
$this->assertInstanceOf(AuditResult::class, $result);
$this->assertTrue($result->passed());
}
}
/**
* Tests all migrations with ID conflicts.
*/
public function testAllMigrationsWithIdConflicts() {
// Get all Drupal 6 migrations.
$migrations = $this->container
->get('plugin.manager.migration')
->createInstancesByTag('Drupal 6');
// Create content.
$this->createContent();
// Audit the IDs of all migrations. There should be conflicts since content
// has been created.
$conflicts = array_map(
function (AuditResult $result) {
return $result->passed() ? NULL : $result->getMigration()->getBaseId();
},
(new IdAuditor())->auditMultiple($migrations)
);
$expected = [
'd6_aggregator_feed',
'd6_aggregator_item',
'd6_comment',
'd6_custom_block',
'd6_file',
'd6_menu_links',
'd6_node',
'd6_node_revision',
'd6_taxonomy_term',
'd6_term_node_revision',
'd6_user',
];
$this->assertEmpty(array_diff(array_filter($conflicts), $expected));
}
/**
* Tests draft revisions ID conflicts.
*/
public function testDraftRevisionIdConflicts() {
// Create a published node of type page.
$node = Node::create(['type' => 'page', 'title' => 'foo']);
$node->moderation_state->value = 'published';
$node->save();
// Create a draft revision.
$node->moderation_state->value = 'draft';
$node->setNewRevision(TRUE);
$node->save();
// Insert data in the d6_node_revision:page migration mappping table to
// simulate a previously migrated node revison.
$table_name = $this->getMigration('d6_node_revision:page')->getIdMap()->mapTableName();
$this->container->get('database')->insert($table_name)
->fields([
'source_ids_hash' => 1,
'sourceid1' => 1,
'destid1' => 1,
])
->execute();
// Audit the IDs of the d6_node_revision migration. There should be
// conflicts since a draft revision has been created.
/** @var \Drupal\migrate\Audit\AuditResult $result */
$result = (new IdAuditor())->audit($this->getMigration('d6_node_revision:page'));
$this->assertInstanceOf(AuditResult::class, $result);
$this->assertFalse($result->passed());
}
/**
* Tests ID conflicts for inaccessible nodes.
*/
public function testNodeGrantsIdConflicts() {
// Enable the node_test module to restrict access to page nodes.
$this->enableModules(['node_test']);
// Create a published node of type page.
$node = Node::create(['type' => 'page', 'title' => 'foo']);
$node->moderation_state->value = 'published';
$node->save();
// Audit the IDs of the d6_node migration. There should be conflicts
// even though the new node is not accessible.
/** @var \Drupal\migrate\Audit\AuditResult $result */
$result = (new IdAuditor())->audit($this->getMigration('d6_node:page'));
$this->assertInstanceOf(AuditResult::class, $result);
$this->assertFalse($result->passed());
}
}
@@ -0,0 +1,196 @@
<?php
namespace Drupal\Tests\migrate_drupal\Kernel\d7;
use Drupal\KernelTests\FileSystemModuleDiscoveryDataProviderTrait;
use Drupal\migrate\Audit\AuditResult;
use Drupal\migrate\Audit\IdAuditor;
use Drupal\node\Entity\Node;
use Drupal\node\Entity\NodeType;
use Drupal\Tests\migrate_drupal\Traits\CreateTestContentEntitiesTrait;
use Drupal\workflows\Entity\Workflow;
/**
* Tests the migration auditor for ID conflicts.
*
* @group migrate_drupal
*/
class MigrateDrupal7AuditIdsTest extends MigrateDrupal7TestBase {
use FileSystemModuleDiscoveryDataProviderTrait;
use CreateTestContentEntitiesTrait;
/**
* {@inheritdoc}
*/
protected function setUp() {
// Enable all modules.
self::$modules = array_keys($this->coreModuleListDataProvider());
parent::setUp();
// Install required entity schemas.
$this->installEntitySchemas();
// Install required schemas.
$this->installSchema('book', ['book']);
$this->installSchema('dblog', ['watchdog']);
$this->installSchema('forum', ['forum_index']);
$this->installSchema('node', ['node_access']);
$this->installSchema('search', ['search_dataset']);
$this->installSchema('system', ['sequences']);
$this->installSchema('tracker', ['tracker_node', 'tracker_user']);
// Enable content moderation for nodes of type page.
$this->installEntitySchema('content_moderation_state');
$this->installConfig('content_moderation');
NodeType::create(['type' => 'page'])->save();
$workflow = Workflow::load('editorial');
$workflow->getTypePlugin()->addEntityTypeAndBundle('node', 'page');
$workflow->save();
}
/**
* Tests multiple migrations to the same destination with no ID conflicts.
*/
public function testMultipleMigrationWithoutIdConflicts() {
// Create a node of type page.
$node = Node::create(['type' => 'page', 'title' => 'foo']);
$node->moderation_state->value = 'published';
$node->save();
// Insert data in the d7_node:page migration mappping table to simulate a
// previously migrated node.
$table_name = $this->getMigration('d7_node:page')->getIdMap()->mapTableName();
$this->container->get('database')->insert($table_name)
->fields([
'source_ids_hash' => 1,
'sourceid1' => 1,
'destid1' => 1,
])
->execute();
// Audit the IDs of the d7_node migrations for the page & article node type.
// There should be no conflicts since the highest destination ID should be
// equal to the highest migrated ID, as found in the aggregated mapping
// tables of the two node migrations.
$migrations = [
$this->getMigration('d7_node:page'),
$this->getMigration('d7_node:article'),
];
$results = (new IdAuditor())->auditMultiple($migrations);
/** @var \Drupal\migrate\Audit\AuditResult $result */
foreach ($results as $result) {
$this->assertInstanceOf(AuditResult::class, $result);
$this->assertTrue($result->passed());
}
}
/**
* Tests all migrations with no ID conflicts.
*/
public function testAllMigrationsWithNoIdConflicts() {
$migrations = $this->container
->get('plugin.manager.migration')
->createInstancesByTag('Drupal 7');
// Audit the IDs of all Drupal 7 migrations. There should be no conflicts
// since no content has been created.
$results = (new IdAuditor())->auditMultiple($migrations);
/** @var \Drupal\migrate\Audit\AuditResult $result */
foreach ($results as $result) {
$this->assertInstanceOf(AuditResult::class, $result);
$this->assertTrue($result->passed());
}
}
/**
* Tests all migrations with ID conflicts.
*/
public function testAllMigrationsWithIdConflicts() {
$migrations = $this->container
->get('plugin.manager.migration')
->createInstancesByTag('Drupal 7');
// Create content.
$this->createContent();
// Audit the IDs of all Drupal 7 migrations. There should be conflicts since
// content has been created.
$conflicts = array_map(
function (AuditResult $result) {
return $result->passed() ? NULL : $result->getMigration()->getBaseId();
},
(new IdAuditor())->auditMultiple($migrations)
);
$expected = [
'd7_aggregator_feed',
'd7_aggregator_item',
'd7_comment',
'd7_custom_block',
'd7_file',
'd7_file_private',
'd7_menu_links',
'd7_node',
'd7_node_revision',
'd7_taxonomy_term',
'd7_user',
];
$this->assertEmpty(array_diff(array_filter($conflicts), $expected));
}
/**
* Tests draft revisions ID conflicts.
*/
public function testDraftRevisionIdConflicts() {
// Create a published node of type page.
$node = Node::create(['type' => 'page', 'title' => 'foo']);
$node->moderation_state->value = 'published';
$node->save();
// Create a draft revision.
$node->moderation_state->value = 'draft';
$node->setNewRevision(TRUE);
$node->save();
// Insert data in the d7_node_revision:page migration mappping table to
// simulate a previously migrated node revison.
$table_name = $this->getMigration('d7_node_revision:page')->getIdMap()->mapTableName();
$this->container->get('database')->insert($table_name)
->fields([
'source_ids_hash' => 1,
'sourceid1' => 1,
'destid1' => 1,
])
->execute();
// Audit the IDs of the d7_node_revision migration. There should be
// conflicts since a draft revision has been created.
/** @var \Drupal\migrate\Audit\AuditResult $result */
$result = (new IdAuditor())->audit($this->getMigration('d7_node_revision:page'));
$this->assertInstanceOf(AuditResult::class, $result);
$this->assertFalse($result->passed());
}
/**
* Tests ID conflicts for inaccessible nodes.
*/
public function testNodeGrantsIdConflicts() {
// Enable the node_test module to restrict access to page nodes.
$this->enableModules(['node_test']);
// Create a published node of type page.
$node = Node::create(['type' => 'page', 'title' => 'foo']);
$node->moderation_state->value = 'published';
$node->save();
// Audit the IDs of the d7_node migration. There should be conflicts
// even though the new node is not accessible.
/** @var \Drupal\migrate\Audit\AuditResult $result */
$result = (new IdAuditor())->audit($this->getMigration('d7_node:page'));
$this->assertInstanceOf(AuditResult::class, $result);
$this->assertFalse($result->passed());
}
}
@@ -0,0 +1,33 @@
<?php
namespace Drupal\Tests\migrate_drupal\Traits;
trait CreateMigrationsTrait {
/**
* Create instances of all Drupal 6 migrations.
*
* @return \Drupal\migrate\Plugin\MigrationInterface[]
* The migrations
*/
public function drupal6Migrations() {
$dirs = \Drupal::service('module_handler')->getModuleDirectories();
$migrate_drupal_directory = $dirs['migrate_drupal'];
$this->loadFixture("$migrate_drupal_directory/tests/fixtures/drupal6.php");
return \Drupal::service('plugin.manager.migration')->createInstancesByTag('Drupal 6');
}
/**
* Create instances of all Drupal 7 migrations.
*
* @return \Drupal\migrate\Plugin\MigrationInterface[]
* The migrations
*/
public function drupal7Migrations() {
$dirs = \Drupal::service('module_handler')->getModuleDirectories();
$migrate_drupal_directory = $dirs['migrate_drupal'];
$this->loadFixture("$migrate_drupal_directory/tests/fixtures/drupal7.php");
return \Drupal::service('plugin.manager.migration')->createInstancesByTag('Drupal 7');
}
}
@@ -0,0 +1,210 @@
<?php
namespace Drupal\Tests\migrate_drupal\Traits;
/**
* Provides helper methods for creating test content.
*/
trait CreateTestContentEntitiesTrait {
/**
* Gets required modules.
*
* @return array
*/
protected function getRequiredModules() {
return [
'aggregator',
'block_content',
'comment',
'field',
'file',
'link',
'menu_link_content',
'migrate_drupal',
'node',
'options',
'system',
'taxonomy',
'text',
'user',
];
}
/**
* Install required entity schemas.
*/
protected function installEntitySchemas() {
$this->installEntitySchema('aggregator_feed');
$this->installEntitySchema('aggregator_item');
$this->installEntitySchema('block_content');
$this->installEntitySchema('comment');
$this->installEntitySchema('file');
$this->installEntitySchema('menu_link_content');
$this->installEntitySchema('node');
$this->installEntitySchema('taxonomy_term');
$this->installEntitySchema('user');
}
/**
* Create several pieces of generic content.
*/
protected function createContent() {
$entity_type_manager = \Drupal::entityTypeManager();
// Create an aggregator feed.
if ($entity_type_manager->hasDefinition('aggregator_feed')) {
$feed = $entity_type_manager->getStorage('aggregator_feed')->create([
'title' => 'feed',
'url' => 'http://www.example.com',
]);
$feed->save();
// Create an aggregator feed item.
$item = $entity_type_manager->getStorage('aggregator_item')->create([
'title' => 'feed item',
'fid' => $feed->id(),
'link' => 'http://www.example.com',
]);
$item->save();
}
// Create a block content.
if ($entity_type_manager->hasDefinition('block_content')) {
$block = $entity_type_manager->getStorage('block_content')->create([
'info' => 'block',
'type' => 'block',
]);
$block->save();
}
// Create a node.
if ($entity_type_manager->hasDefinition('node')) {
$node = $entity_type_manager->getStorage('node')->create([
'type' => 'page',
'title' => 'page',
]);
$node->save();
// Create a comment.
if ($entity_type_manager->hasDefinition('comment')) {
$comment = $entity_type_manager->getStorage('comment')->create([
'comment_type' => 'comment',
'field_name' => 'comment',
'entity_type' => 'node',
'entity_id' => $node->id(),
]);
$comment->save();
}
}
// Create a file.
if ($entity_type_manager->hasDefinition('file')) {
$file = $entity_type_manager->getStorage('file')->create([
'uri' => 'public://example.txt',
]);
$file->save();
}
// Create a menu link.
if ($entity_type_manager->hasDefinition('menu_link_content')) {
$menu_link = $entity_type_manager->getStorage('menu_link_content')->create([
'title' => 'menu link',
'link' => ['uri' => 'http://www.example.com'],
'menu_name' => 'tools',
]);
$menu_link->save();
}
// Create a taxonomy term.
if ($entity_type_manager->hasDefinition('taxonomy_term')) {
$term = $entity_type_manager->getStorage('taxonomy_term')->create([
'name' => 'term',
'vid' => 'term',
]);
$term->save();
}
// Create a user.
if ($entity_type_manager->hasDefinition('user')) {
$user = $entity_type_manager->getStorage('user')->create([
'name' => 'user',
'mail' => 'user@example.com',
]);
$user->save();
}
}
/**
* Create several pieces of generic content.
*/
protected function createContentPostUpgrade() {
$entity_type_manager = \Drupal::entityTypeManager();
// Create a block content.
if ($entity_type_manager->hasDefinition('block_content')) {
$block = $entity_type_manager->getStorage('block_content')->create([
'info' => 'Post upgrade block',
'type' => 'block',
]);
$block->save();
}
// Create a node.
if ($entity_type_manager->hasDefinition('node')) {
$node = $entity_type_manager->getStorage('node')->create([
'type' => 'page',
'title' => 'Post upgrade page',
]);
$node->save();
// Create a comment.
if ($entity_type_manager->hasDefinition('comment')) {
$comment = $entity_type_manager->getStorage('comment')->create([
'comment_type' => 'comment',
'field_name' => 'comment',
'entity_type' => 'node',
'entity_id' => $node->id(),
]);
$comment->save();
}
}
// Create a file.
if ($entity_type_manager->hasDefinition('file')) {
$file = $entity_type_manager->getStorage('file')->create([
'uri' => 'public://post_upgrade_example.txt',
]);
$file->save();
}
// Create a menu link.
if ($entity_type_manager->hasDefinition('menu_link_content')) {
$menu_link = $entity_type_manager->getStorage('menu_link_content')->create([
'title' => 'post upgrade menu link',
'link' => ['uri' => 'http://www.drupal.org'],
'menu_name' => 'tools',
]);
$menu_link->save();
}
// Create a taxonomy term.
if ($entity_type_manager->hasDefinition('taxonomy_term')) {
$term = $entity_type_manager->getStorage('taxonomy_term')->create([
'name' => 'post upgrade term',
'vid' => 'term',
]);
$term->save();
}
// Create a user.
if ($entity_type_manager->hasDefinition('user')) {
$user = $entity_type_manager->getStorage('user')->create([
'name' => 'universe',
'mail' => 'universe@example.com',
]);
$user->save();
}
}
}