Move into nested docroot

This commit is contained in:
Rob Davies 2017-02-13 15:31:17 +00:00
parent 83a0d3a149
commit c8b70abde9
13405 changed files with 0 additions and 0 deletions

View file

@ -0,0 +1,8 @@
name: Migrate Drupal
type: module
description: 'Contains migrations from older Drupal versions.'
package: Core (Experimental)
version: VERSION
core: 8.x
dependencies:
- migrate

View file

@ -0,0 +1,76 @@
<?php
/**
* @file
* Provides migration from other Drupal sites.
*/
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;
/**
* 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>.', array(':migrate' => \Drupal::url('help.page', array('name' => 'migrate')), ':migrate_drupal' => 'https://www.drupal.org/documentation/modules/migrate_drupal')) . '</p>';
return $output;
}
}
/**
* Implements hook_migration_plugins_alter().
*/
function migrate_drupal_migration_plugins_alter(&$definitions) {
// 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',
],
];
$vocabulary_migration = \Drupal::service('plugin.manager.migration')->createStubMigration($vocabulary_migration_definition);
try {
$source_plugin = $vocabulary_migration->getSourcePlugin();
if ($source_plugin instanceof RequirementsInterface) {
$source_plugin->checkRequirements();
}
$executable = new MigrateExecutable($vocabulary_migration, new MigrateMessage());
$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];
foreach ($plugin_ids as $plugin_id) {
if (isset($definitions[$plugin_id])) {
$definitions[$plugin_id]['process'][$row->getDestinationProperty('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.
}
}
}

View file

@ -0,0 +1,9 @@
services:
plugin.manager.migrate.cckfield:
class: Drupal\migrate_drupal\Plugin\MigrateCckFieldPluginManager
arguments:
- cckfield
- '@container.namespaces'
- '@cache.discovery'
- '@module_handler'
- '\Drupal\migrate_drupal\Annotation\MigrateCckField'

View file

@ -0,0 +1,54 @@
<?php
namespace Drupal\migrate_drupal\Annotation;
use Drupal\Component\Annotation\Plugin;
/**
* Defines a cckfield plugin annotation object.
*
* cckfield plugins are variously responsible for handling the migration of
* CCK fields from Drupal 6 to Drupal 8, and Field API fields from Drupal 7
* to Drupal 8. They are allowed to alter CCK-related migrations when migrations
* are being generated, and can compute destination field types for individual
* fields during the actual migration process.
*
* Plugin Namespace: Plugin\migrate\cckfield
*
* @Annotation
*/
class MigrateCckField 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 = [];
}

View file

@ -0,0 +1,170 @@
<?php
namespace Drupal\migrate_drupal;
use Drupal\Core\Database\Connection;
use Drupal\Core\Database\Database;
use Drupal\migrate\Exception\RequirementsException;
use Drupal\migrate\Plugin\RequirementsInterface;
/**
* Configures the appropriate migrations for a given source Drupal database.
*/
trait MigrationConfigurationTrait {
/**
* 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 (\Exception $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;
\Drupal::state()->set($database_state_key, $database_state);
\Drupal::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;
$plugin_manager = \Drupal::service('plugin.manager.migration');
/** @var \Drupal\migrate\Plugin\Migration[] $all_migrations */
$all_migrations = $plugin_manager->createInstancesByTag($version_tag);
$migrations = [];
foreach ($all_migrations as $migration) {
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;
}
/**
* Determines what version of Drupal the source database contains.
*
* @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
* Drupal 6.x), or FALSE if no valid version is matched.
*/
protected 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')) {
$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);
}
else {
$version_string = FALSE;
}
return $version_string ? substr($version_string, 0, 1) : FALSE;
}
}

View file

@ -0,0 +1,13 @@
<?php
namespace Drupal\migrate_drupal;
/**
* @deprecated in Drupal 8.1.x, will be removed before Drupal 9.0.0. Use
* \Drupal\migrate_drupal\MigrationConfigurationTrait instead.
*/
trait MigrationCreationTrait {
use MigrationConfigurationTrait;
}

View file

@ -0,0 +1,87 @@
<?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 CCK field type plugins.
*/
interface MigrateCckFieldInterface extends PluginInspectionInterface {
/**
* Apply any custom processing to the field migration.
*
* @param \Drupal\migrate\Plugin\MigrationInterface $migration
* The migration entity.
*/
public function processField(MigrationInterface $migration);
/**
* Apply any custom processing to the field instance migration.
*
* @param \Drupal\migrate\Plugin\MigrationInterface $migration
* The migration entity.
*/
public function processFieldInstance(MigrationInterface $migration);
/**
* Apply any custom processing to the field widget migration.
*
* @param \Drupal\migrate\Plugin\MigrationInterface $migration
* The migration entity.
*/
public function processFieldWidget(MigrationInterface $migration);
/**
* Apply any custom processing to the field formatter migration.
*
* @param \Drupal\migrate\Plugin\MigrationInterface $migration
* The migration entity.
*/
public function processFieldFormatter(MigrationInterface $migration);
/**
* Get a map between D6 formatters and D8 formatters for this field type.
*
* This is used by static::processFieldFormatter() in the base class.
*
* @return array
* The keys are D6 formatters and the values are D8 formatters.
*/
public function getFieldFormatterMap();
/**
* 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 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);
/**
* 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);
}

View file

@ -0,0 +1,55 @@
<?php
namespace Drupal\migrate_drupal\Plugin;
use Drupal\Component\Plugin\Exception\PluginNotFoundException;
use Drupal\migrate\Plugin\MigratePluginManager;
use Drupal\migrate\Plugin\MigrationInterface;
/**
* Plugin manager for migrate cckfield plugins.
*
* @see \Drupal\migrate_drupal\Plugin\MigrateCckFieldInterface
* @see \Drupal\migrate\Annotation\MigrateCckField
* @see plugin_api
*
* @ingroup migration
*/
class MigrateCckFieldPluginManager extends MigratePluginManager implements MigrateCckFieldPluginManagerInterface {
/**
* The default version of core to use for cck 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;
/**
* {@inheritdoc}
*/
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;
}
}
}
foreach ($this->getDefinitions() 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);
}
}

View file

@ -0,0 +1,28 @@
<?php
namespace Drupal\migrate_drupal\Plugin;
use Drupal\migrate\Plugin\MigratePluginManagerInterface;
use Drupal\migrate\Plugin\MigrationInterface;
interface MigrateCckFieldPluginManagerInterface 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);
}

View file

@ -0,0 +1,132 @@
<?php
namespace Drupal\migrate_drupal\Plugin\migrate;
use Drupal\Component\Plugin\Exception\PluginNotFoundException;
use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
use Drupal\migrate\Exception\RequirementsException;
use Drupal\migrate\Plugin\MigrateDestinationPluginManager;
use Drupal\migrate\Plugin\MigratePluginManagerInterface;
use Drupal\migrate\Plugin\Migration;
use Drupal\migrate\Plugin\MigrationPluginManagerInterface;
use Drupal\migrate\Plugin\RequirementsInterface;
use Drupal\migrate_drupal\Plugin\MigrateCckFieldPluginManagerInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
/**
* Migration plugin class for migrations dealing with CCK field values.
*/
class CckMigration extends Migration implements ContainerFactoryPluginInterface {
/**
* Flag indicating whether the CCK data has been filled already.
*
* @var bool
*/
protected $init = FALSE;
/**
* List of cckfield plugin IDs which have already run.
*
* @var string[]
*/
protected $processedFieldTypes = [];
/**
* Already-instantiated cckfield plugins, keyed by ID.
*
* @var \Drupal\migrate_drupal\Plugin\MigrateCckFieldInterface[]
*/
protected $cckPluginCache;
/**
* The cckfield plugin manager.
*
* @var \Drupal\migrate_drupal\Plugin\MigrateCckFieldPluginManagerInterface
*/
protected $cckPluginManager;
/**
* Constructs a CckMigration.
*
* @param array $configuration
* Plugin configuration.
* @param string $plugin_id
* The plugin ID.
* @param mixed $plugin_definition
* The plugin definition.
* @param \Drupal\migrate_drupal\Plugin\MigrateCckFieldPluginManagerInterface $cck_manager
* The cckfield plugin manager.
* @param \Drupal\migrate\Plugin\MigrationPluginManagerInterface $migration_plugin_manager
* The migration plugin manager.
* @param \Drupal\migrate\Plugin\MigratePluginManagerInterface $source_plugin_manager
* The source migration plugin manager.
* @param \Drupal\migrate\Plugin\MigratePluginManagerInterface $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\MigratePluginManagerInterface $idmap_plugin_manager
* The ID map migration plugin manager.
*/
public function __construct(array $configuration, $plugin_id, $plugin_definition, MigrateCckFieldPluginManagerInterface $cck_manager, MigrationPluginManagerInterface $migration_plugin_manager, MigratePluginManagerInterface $source_plugin_manager, MigratePluginManagerInterface $process_plugin_manager, MigrateDestinationPluginManager $destination_plugin_manager, MigratePluginManagerInterface $idmap_plugin_manager) {
parent::__construct($configuration, $plugin_id, $plugin_definition, $migration_plugin_manager, $source_plugin_manager, $process_plugin_manager, $destination_plugin_manager, $idmap_plugin_manager);
$this->cckPluginManager = $cck_manager;
}
/**
* {@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.migrate.cckfield'),
$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')
);
}
/**
* {@inheritdoc}
*/
public function getProcess() {
if (!$this->init) {
$this->init = TRUE;
$source_plugin = $this->migrationPluginManager->createInstance($this->pluginId)->getSourcePlugin();
if ($source_plugin instanceof RequirementsInterface) {
try {
$source_plugin->checkRequirements();
}
catch (RequirementsException $e) {
// Kill the rest of the method.
$source_plugin = [];
}
}
foreach ($source_plugin as $row) {
$field_type = $row->getSourceProperty('type');
try {
$plugin_id = $this->cckPluginManager->getPluginIdFromFieldType($field_type, [], $this);
}
catch (PluginNotFoundException $ex) {
continue;
}
if (!isset($this->processedFieldTypes[$field_type])) {
$this->processedFieldTypes[$field_type] = TRUE;
// Allow the cckfield plugin to alter the migration as necessary so
// that it knows how to handle fields of this type.
if (!isset($this->cckPluginCache[$field_type])) {
$this->cckPluginCache[$field_type] = $this->cckPluginManager->createInstance($plugin_id, [], $this);
}
call_user_func([$this->cckPluginCache[$field_type], $this->pluginDefinition['cck_plugin_method']], $this);
}
}
}
return parent::getProcess();
}
}

View file

@ -0,0 +1,83 @@
<?php
namespace Drupal\migrate_drupal\Plugin\migrate\cckfield;
use Drupal\Core\Plugin\PluginBase;
use Drupal\migrate\Plugin\MigrationInterface;
use Drupal\migrate\Row;
use Drupal\migrate_drupal\Plugin\MigrateCckFieldInterface;
/**
* The base class for all cck field plugins.
*
* @see \Drupal\migrate\Plugin\MigratePluginManager
* @see \Drupal\migrate_drupal\Annotation\MigrateCckField
* @see \Drupal\migrate_drupal\Plugin\MigrateCckFieldInterface
* @see plugin_api
*
* @ingroup migration
*/
abstract class CckFieldPluginBase extends PluginBase implements MigrateCckFieldInterface {
/**
* {@inheritdoc}
*/
public function processField(MigrationInterface $migration) {
$process[0]['map'][$this->pluginId][$this->pluginId] = $this->pluginId;
$migration->mergeProcessOfProperty('type', $process);
}
/**
* {@inheritdoc}
*/
public function processFieldInstance(MigrationInterface $migration) {
// Nothing to do by default with field instances.
}
/**
* {@inheritdoc}
*/
public function processFieldWidget(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 getFieldWidgetMap() {
// By default, use the plugin ID for the widget types.
return [
$this->pluginId => $this->pluginId . '_default',
];
}
/**
* {@inheritdoc}
*/
public function processFieldFormatter(MigrationInterface $migration) {
$process = [];
foreach ($this->getFieldFormatterMap() as $source_format => $destination_format) {
$process[0]['map'][$this->pluginId][$source_format] = $destination_format;
}
$migration->mergeProcessOfProperty('options/type', $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;
}
}
}

View file

@ -0,0 +1,94 @@
<?php
namespace Drupal\migrate_drupal\Plugin\migrate\destination;
use Drupal\Core\Entity\EntityStorageInterface;
use Drupal\Core\Field\FieldTypePluginManagerInterface;
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.x and will be removed in Drupal 9.0.x. 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 EntityStorageInterface $storage
* The storage for this entity type.
* @param array $bundles
* The list of bundles this entity type has.
* @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, FieldTypePluginManagerInterface $field_type_plugin_manager) {
parent::__construct($configuration, $plugin_id, $plugin_definition, $migration, $storage, $bundles);
$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.manager')->getStorage($entity_type_id),
array_keys($container->get('entity.manager')->getBundleInfo($entity_type_id)),
$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';
}
}

View file

@ -0,0 +1,178 @@
<?php
namespace Drupal\migrate_drupal\Plugin\migrate\source;
use Drupal\Component\Plugin\DependentPluginInterface;
use Drupal\Core\Entity\DependencyTrait;
use Drupal\Core\Entity\EntityManagerInterface;
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 Drupal\migrate\Plugin\RequirementsInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
/**
* A base source class for Drupal migrate sources.
*
* Mainly to let children retrieve information from the origin system in an
* easier way.
*/
abstract class DrupalSqlBase extends SqlBase implements ContainerFactoryPluginInterface, RequirementsInterface, DependentPluginInterface {
use DependencyTrait;
/**
* The contents of the system table.
*
* @var array
*/
protected $systemData;
/**
* If the source provider is missing.
*
* @var bool
*/
protected $requirements = TRUE;
/**
* The entity manager.
*
* @var \Drupal\Core\Entity\EntityManagerInterface
*/
protected $entityManager;
/**
* {@inheritdoc}
*/
public function __construct(array $configuration, $plugin_id, $plugin_definition, MigrationInterface $migration, StateInterface $state, EntityManagerInterface $entity_manager) {
parent::__construct($configuration, $plugin_id, $plugin_definition, $migration, $state);
$this->entityManager = $entity_manager;
}
/**
* Retrieves all system data information from origin system.
*
* @return array
* List of system table information keyed by type and name.
*/
public function getSystemData() {
if (!isset($this->systemData)) {
$this->systemData = array();
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.manager')
);
}
/**
* {@inheritdoc}
*/
public function checkRequirements() {
if ($this->pluginDefinition['requirements_met'] === TRUE) {
if (isset($this->pluginDefinition['source_provider'])) {
if ($this->moduleExists($this->pluginDefinition['source_provider'])) {
if (isset($this->pluginDefinition['minimum_schema_version']) && !$this->getModuleSchemaVersion($this->pluginDefinition['source_provider']) < $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_provider'] . ' is not enabled in the source site.', ['source_provider' => $this->pluginDefinition['source_provider']]);
}
}
}
}
/**
* Get a module schema_version value in the source installation.
*
* @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;
}
/**
* Check to see if a given module is enabled in the source installation.
*
* @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']);
}
/**
* Read a variable from a 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', array('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->entityManager->getDefinition($this->configuration['constants']['entity_type'])->getProvider());
}
if (isset($this->configuration['constants']['module'])) {
$this->addDependency('module', $this->configuration['constants']['module']);
}
return $this->dependencies;
}
}

View file

@ -0,0 +1,64 @@
<?php
namespace Drupal\migrate_drupal\Plugin\migrate\source;
use Drupal\Component\Plugin\DependentPluginInterface;
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\EntityManagerInterface;
use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
/**
* Source returning an empty row with Drupal specific config dependencies.
*
* @MigrateSource(
* id = "md_empty"
* )
*/
class EmptySource extends BaseEmptySource implements ContainerFactoryPluginInterface, DependentPluginInterface {
use DependencyTrait;
/**
* The entity manager.
*
* @var \Drupal\Core\Entity\EntityManagerInterface
*/
protected $entityManager;
/**
* {@inheritdoc}
*/
public function __construct(array $configuration, $plugin_id, $plugin_definition, MigrationInterface $migration, EntityManagerInterface $entity_manager) {
parent::__construct($configuration, $plugin_id, $plugin_definition, $migration);
$this->entityManager = $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.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->entityManager->getDefinition($this->configuration['constants']['entity_type'])->getProvider());
}
return $this->dependencies;
}
}

View file

@ -0,0 +1,90 @@
<?php
namespace Drupal\migrate_drupal\Plugin\migrate\source;
use Drupal\Core\Entity\EntityManagerInterface;
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"
* )
*/
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, EntityManagerInterface $entity_manager) {
parent::__construct($configuration, $plugin_id, $plugin_definition, $migration, $state, $entity_manager);
$this->variables = $this->configuration['variables'];
}
/**
* {@inheritdoc}
*/
protected function initializeIterator() {
return new \ArrayIterator(array($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() {
return intval($this->query()->countQuery()->execute()->fetchField() > 0);
}
/**
* {@inheritdoc}
*/
public function fields() {
return array_combine($this->variables, $this->variables);
}
/**
* {@inheritdoc}
*/
public function query() {
return $this->getDatabase()
->select('variable', 'v')
->fields('v', array('name', 'value'))
->condition('name', $this->variables, 'IN');
}
/**
* {@inheritdoc}
*/
public function getIds() {
$ids['id']['type'] = 'string';
return $ids;
}
}

View file

@ -0,0 +1,57 @@
<?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"
* )
*/
class VariableMultiRow extends DrupalSqlBase {
/**
* {@inheritdoc}
*/
public function query() {
return $this->select('variable', 'v')
->fields('v', array('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 array(
'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;
}
}

View file

@ -0,0 +1,100 @@
<?php
namespace Drupal\migrate_drupal\Plugin\migrate\source\d6;
use Drupal\Core\Entity\EntityManagerInterface;
use Drupal\Core\State\StateInterface;
use Drupal\migrate\Plugin\MigrationInterface;
use Drupal\migrate_drupal\Plugin\migrate\source\DrupalSqlBase;
/**
* Drupal i18n_variable source from database.
*
* @MigrateSource(
* id = "i18n_variable"
* )
*/
class i18nVariable 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, EntityManagerInterface $entity_manager) {
parent::__construct($configuration, $plugin_id, $plugin_definition, $migration, $state, $entity_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() {
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;
}
}

View file

@ -0,0 +1,74 @@
<?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) {
return $this->select('field_config_instance', 'fci')
->fields('fci')
->condition('entity_type', $entity_type)
->condition('bundle', isset($bundle) ? $bundle : $entity_type)
->condition('deleted', 0)
->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.
*
* @return array
* The raw field values, keyed by delta.
*
* @todo Support multilingual field values.
*/
protected function getFieldValues($entity_type, $field, $entity_id, $revision_id = 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);
}
$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;
}
}

View file

@ -0,0 +1,59 @@
<?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"
* )
*/
class Config extends DrupalSqlBase {
/**
* {@inheritdoc}
*/
public function query() {
$query = $this->select('config', 'c')
->fields('c', array('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;
}
}

View file

@ -0,0 +1,74 @@
<?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->createStub($entity_type_id);
$this->assertTrue($entity_id, 'Stub successfully created');
if ($entity_id) {
$violations = $this->validateStub($entity_type_id, $entity_id);
if (!$this->assertIdentical(count($violations), 0, 'Stub is a valid entity')) {
foreach ($violations as $violation) {
$this->fail((string) $violation->getMessage());
}
}
}
}
/**
* 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 createStub($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::entityManager()->getStorage($entity_type_id);
/** @var \Drupal\Core\Entity\ContentEntityInterface $stub_entity */
$stub_entity = $controller->load($entity_id);
return $stub_entity->validate();
}
}

File diff suppressed because it is too large Load diff

File diff suppressed because one or more lines are too long

View file

@ -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

View file

@ -0,0 +1,29 @@
<?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"
* }
* )
*/
class D6FileField extends CckFieldPluginBase {
/**
* {@inheritdoc}
*/
public function getFieldFormatterMap() {}
/**
* {@inheritdoc}
*/
public function processCckFieldValues(MigrationInterface $migration, $field_name, $data) {}
}

View file

@ -0,0 +1,25 @@
<?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"
* )
*/
class D6NoCoreVersionSpecified extends CckFieldPluginBase {
/**
* {@inheritdoc}
*/
public function getFieldFormatterMap() {}
/**
* {@inheritdoc}
*/
public function processCckFieldValues(MigrationInterface $migration, $field_name, $data) {}
}

View file

@ -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

View file

@ -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'

View file

@ -0,0 +1,59 @@
<?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 = array('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');
$plugin_id = $plugin_manager->getPluginIdFromFieldType('filefield', ['core' => 6]);
$this->assertIdentical('Drupal\\file\\Plugin\\migrate\\cckfield\\d6\\FileField', get_class($plugin_manager->createInstance($plugin_id, ['core' => 6])));
try {
// If this test passes, getPluginIdFromFieldType will raise a
// PluginNotFoundException and we'll never reach fail().
$plugin_manager->getPluginIdFromFieldType('filefield', ['core' => 7]);
$this->fail('Expected Drupal\Component\Plugin\Exception\PluginNotFoundException.');
}
catch (PluginNotFoundException $e) {
$this->assertIdentical($e->getMessage(), "Plugin ID 'filefield' was not found.");
}
$this->assertIdentical('image', $plugin_manager->getPluginIdFromFieldType('image', ['core' => 7]));
$this->assertIdentical('file', $plugin_manager->getPluginIdFromFieldType('file', ['core' => 7]));
$this->assertIdentical('d6_file', $plugin_manager->getPluginIdFromFieldType('file', ['core' => 6]));
$this->assertIdentical('text', $plugin_manager->getPluginIdFromFieldType('text', ['core' => 6]));
$this->assertIdentical('text', $plugin_manager->getPluginIdFromFieldType('text', ['core' => 7]));
// Test fallback when no core version is specified.
$this->assertIdentical('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->assertIdentical($e->getMessage(), "Plugin ID 'd6_no_core_version_specified' was not found.");
}
}
}

View file

@ -0,0 +1,47 @@
<?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 = array('system', 'user', 'field', 'migrate_drupal', 'options', 'file');
/**
* {@inheritdoc}
*/
protected function setUp() {
parent::setUp();
$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);
}
}

View file

@ -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;
}
}

View 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' => array(
array(
'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, "This entity type does not support translation") !== FALSE;
});
$message->display($argument, Argument::any())
->shouldBeCalled();
$executable = new MigrateExecutable($migration, $message->reveal());
$executable->import();
}
}

View file

@ -0,0 +1,130 @@
<?php
namespace Drupal\Tests\migrate_drupal\Kernel\d6;
use Drupal\Tests\migrate_drupal\Kernel\MigrateDrupalTestBase;
/**
* Base class for Drupal 6 migration tests.
*/
abstract class MigrateDrupal6TestBase extends MigrateDrupalTestBase {
/**
* {@inheritdoc}
*/
public static $modules = [
'datetime',
'filter',
'image',
'link',
'node',
'options',
'telephone',
'text',
];
/**
* {@inheritdoc}
*/
protected function setUp() {
parent::setUp();
$this->loadFixture($this->getFixtureFilePath());
}
/**
* Gets the path to the fixture file.
*/
protected function getFixtureFilePath() {
return __DIR__ . '/../../../fixtures/drupal6.php';
}
/**
* Executes all user migrations.
*
* @param bool $include_pictures
* If TRUE, migrates user pictures.
*/
protected function migrateUsers($include_pictures = TRUE) {
$this->executeMigrations(['d6_filter_format', 'd6_user_role']);
if ($include_pictures) {
$this->installEntitySchema('file');
$this->executeMigrations([
'd6_file',
'd6_user_picture_file',
'user_picture_field',
'user_picture_field_instance',
'user_picture_entity_display',
'user_picture_entity_form_display',
]);
}
$this->executeMigration('d6_user');
}
/**
* Migrates node types.
*/
protected function migrateContentTypes() {
$this->installConfig(['node']);
$this->executeMigration('d6_node_type');
}
/**
* Executes all field migrations.
*/
protected function migrateFields() {
$this->migrateContentTypes();
$this->executeMigrations([
'd6_field',
'd6_field_instance',
'd6_field_instance_widget_settings',
'd6_view_modes',
'd6_field_formatter_settings',
'd6_upload_field',
'd6_upload_field_instance',
]);
}
/**
* Executes all content migrations.
*
* @param array $include
* Extra things to include as part of the migrations. Values may be
* 'revisions' or 'translations'.
*/
protected function migrateContent($include = []) {
if (in_array('translations', $include)) {
$this->executeMigrations(['language']);
}
$this->migrateUsers(FALSE);
$this->migrateFields();
$this->installEntitySchema('node');
$this->executeMigrations(['d6_node_settings', 'd6_node']);
if (in_array('translations', $include)) {
$this->executeMigrations(['translations']);
}
if (in_array('revisions', $include)) {
$this->executeMigrations(['d6_node_revision']);
}
}
/**
* Executes all taxonomy migrations.
*/
protected function migrateTaxonomy() {
$this->migrateContentTypes();
$this->installEntitySchema('taxonomy_term');
$this->executeMigrations([
'd6_taxonomy_vocabulary',
'd6_vocabulary_field',
'd6_vocabulary_field_instance',
'd6_vocabulary_entity_display',
'd6_vocabulary_entity_form_display',
'd6_taxonomy_term',
]);
}
}

View file

@ -0,0 +1,27 @@
<?php
namespace Drupal\Tests\migrate_drupal\Kernel\d7;
use Drupal\Tests\migrate_drupal\Kernel\MigrateDrupalTestBase;
/**
* Base class for Drupal 7 migration tests.
*/
abstract class MigrateDrupal7TestBase extends MigrateDrupalTestBase {
/**
* {@inheritdoc}
*/
protected function setUp() {
parent::setUp();
$this->loadFixture($this->getFixtureFilePath());
}
/**
* Gets the path to the fixture file.
*/
protected function getFixtureFilePath() {
return __DIR__ . '/../../../fixtures/drupal7.php';
}
}

View file

@ -0,0 +1,73 @@
<?php
namespace Drupal\Tests\migrate_drupal\Kernel\dependencies;
use Drupal\Component\Utility\SafeMarkup;
use Drupal\migrate\MigrateExecutable;
use Drupal\Tests\migrate_drupal\Kernel\d6\MigrateDrupal6TestBase;
/**
* Ensure the consistency among the dependencies for migrate.
*
* @group migrate_drupal
*/
class MigrateDependenciesTest extends MigrateDrupal6TestBase {
/**
* {@inheritdoc}
*/
public static $modules = ['aggregator', 'comment'];
/**
* Tests that the order is correct when loading several migrations.
*/
public function testMigrateDependenciesOrder() {
$migration_items = array('d6_comment', 'd6_filter_format', 'd6_node:page');
$migrations = $this->container->get('plugin.manager.migration')->createInstances($migration_items);
$expected_order = array('d6_filter_format', 'd6_node:page', 'd6_comment');
$this->assertIdentical(array_keys($migrations), $expected_order);
$expected_requirements = array(
// d6_comment depends on d6_node:*, which the deriver expands into every
// variant of d6_node.
'd6_node:article',
'd6_node:company',
'd6_node:employee',
'd6_node:event',
'd6_node:page',
'd6_node:sponsor',
'd6_node:story',
'd6_node:test_event',
'd6_node:test_page',
'd6_node:test_planet',
'd6_node:test_story',
'd6_node_type',
'd6_node_settings',
'd6_filter_format',
'd6_user',
'd6_comment_type',
'd6_comment_entity_display',
'd6_comment_entity_form_display',
);
// Migration dependencies for comment include dependencies for node
// migration as well.
$actual_requirements = $migrations['d6_comment']->get('requirements');
$this->assertIdentical(count($actual_requirements), count($expected_requirements));
foreach ($expected_requirements as $requirement) {
$this->assertIdentical($actual_requirements[$requirement], $requirement);
}
}
/**
* Tests dependencies on the migration of aggregator feeds & items.
*/
public function testAggregatorMigrateDependencies() {
/** @var \Drupal\migrate\Plugin\Migration $migration */
$migration = $this->getMigration('d6_aggregator_item');
$executable = new MigrateExecutable($migration, $this);
$this->startCollectingMessages();
$executable->import();
$this->assertEqual($this->migrateMessages['error'], array(SafeMarkup::format('Migration @id did not meet the requirements. Missing migrations d6_aggregator_feed. requirements: d6_aggregator_feed.', array('@id' => $migration->id()))));
$this->collectMessages = FALSE;
}
}

View file

@ -0,0 +1,110 @@
<?php
namespace Drupal\Tests\migrate_drupal\Unit\source;
use Drupal\Tests\migrate\Unit\MigrateTestCase;
use Drupal\migrate\Exception\RequirementsException;
/**
* @coversDefaultClass Drupal\migrate_drupal\Plugin\migrate\source\DrupalSqlBase
* @group migrate_drupal
*/
class DrupalSqlBaseTest extends MigrateTestCase {
/**
* Define bare minimum migration configuration.
*/
protected $migrationConfiguration = array(
'id' => 'DrupalSqlBase',
);
/**
* @var \Drupal\migrate_drupal\Plugin\migrate\source\DrupalSqlBase
*/
protected $base;
/**
* Minimum database contents needed to test DrupalSqlBase.
*/
protected $databaseContents = array(
'system' => array(
array(
'filename' => 'sites/all/modules/module1',
'name' => 'module1',
'type' => 'module',
'status' => 0,
'schema_version' => -1,
),
),
);
/**
* @covers ::checkRequirements
*/
public function testSourceProviderNotActive() {
$plugin_definition['requirements_met'] = TRUE;
$plugin_definition['source_provider'] = 'module1';
/** @var \Drupal\Core\State\StateInterface $state */
$state = $this->getMock('Drupal\Core\State\StateInterface');
/** @var \Drupal\Core\Entity\EntityManagerInterface $entity_manager */
$entity_manager = $this->getMock('Drupal\Core\Entity\EntityManagerInterface');
$plugin = new TestDrupalSqlBase([], 'placeholder_id', $plugin_definition, $this->getMigration(), $state, $entity_manager);
$plugin->setDatabase($this->getDatabase($this->databaseContents));
$system_data = $plugin->getSystemData();
$this->setExpectedException(RequirementsException::class, 'The module module1 is not enabled in the source site.');
try {
$plugin->checkRequirements();
}
catch (RequirementsException $e) {
// Ensure requirements are set on the exception.
$this->assertEquals(['source_provider' => 'module1'], $e->getRequirements());
// Re-throw so PHPUnit can assert the exception.
throw $e;
}
}
}
namespace Drupal\Tests\migrate_drupal\Unit\source;
use Drupal\Core\Database\Connection;
use Drupal\migrate_drupal\Plugin\migrate\source\DrupalSqlBase;
/**
* Extends the DrupalSqlBase abstract class.
*/
class TestDrupalSqlBase extends DrupalSqlBase {
/**
* {@inheritdoc}
*/
public function fields() {
return [];
}
/**
* {@inheritdoc}
*/
public function query() {
}
/**
* Tweaks DrupalSqlBase to set a new database connection for tests.
*
* @param \Drupal\Core\Database\Connection $database
* The new connection to use.
*
* @see \Drupal\Tests\migrate\Unit\MigrateSourceSqlTestCase
*/
public function setDatabase(Connection $database) {
$this->database = $database;
}
/**
* {@inheritdoc}
*/
public function getIds() {
return [];
}
}

View file

@ -0,0 +1,20 @@
<?php
namespace Drupal\Tests\migrate_drupal\Unit\source;
/**
* Tests variable multirow source w/ high water handling.
*
* @group migrate_drupal
*/
class VariableMultiRowSourceWithHighwaterTest extends VariableMultiRowTestBase {
/**
* {@inheritdoc}
*/
protected function setUp() {
$this->migrationConfiguration['highWaterProperty']['field'] = 'test';
parent::setup();
}
}

View file

@ -0,0 +1,12 @@
<?php
namespace Drupal\Tests\migrate_drupal\Unit\source;
/**
* Tests D6 variable multirow source plugin.
*
* @group migrate_drupal
*/
class VariableMultiRowTest extends VariableMultiRowTestBase {
}

View file

@ -0,0 +1,40 @@
<?php
namespace Drupal\Tests\migrate_drupal\Unit\source;
use Drupal\Tests\migrate\Unit\MigrateSqlSourceTestCase;
/**
* Base class for variable multirow source unit tests.
*/
abstract class VariableMultiRowTestBase extends MigrateSqlSourceTestCase {
// The plugin system is not working during unit testing so the source plugin
// class needs to be manually specified.
const PLUGIN_CLASS = 'Drupal\migrate_drupal\Plugin\migrate\source\VariableMultiRow';
// The fake Migration configuration entity.
protected $migrationConfiguration = array(
'id' => 'test',
'source' => array(
'plugin' => 'd6_variable_multirow',
'variables' => array(
'foo',
'bar',
),
),
);
protected $expectedResults = array(
array('name' => 'foo', 'value' => 1),
array('name' => 'bar', 'value' => FALSE),
);
protected $databaseContents = array(
'variable' => array(
array('name' => 'foo', 'value' => 'i:1;'),
array('name' => 'bar', 'value' => 'b:0;'),
),
);
}

View file

@ -0,0 +1,43 @@
<?php
namespace Drupal\Tests\migrate_drupal\Unit\source;
use Drupal\Tests\migrate\Unit\MigrateSqlSourceTestCase;
/**
* Tests the variable source plugin.
*
* @group migrate_drupal
*/
class VariableTest extends MigrateSqlSourceTestCase {
const PLUGIN_CLASS = 'Drupal\migrate_drupal\Plugin\migrate\source\Variable';
protected $migrationConfiguration = array(
'id' => 'test',
'highWaterProperty' => array('field' => 'test'),
'source' => array(
'plugin' => 'd6_variable',
'variables' => array(
'foo',
'bar',
),
),
);
protected $expectedResults = array(
array(
'id' => 'foo',
'foo' => 1,
'bar' => FALSE,
),
);
protected $databaseContents = array(
'variable' => array(
array('name' => 'foo', 'value' => 'i:1;'),
array('name' => 'bar', 'value' => 'b:0;'),
),
);
}

View file

@ -0,0 +1,222 @@
<?php
/**
* @file
* Contains \Drupal\Tests\migrate_drupal\Unit\source\d6\Drupal6SqlBaseTest.
*/
namespace Drupal\Tests\migrate_drupal\Unit\source\d6;
use Drupal\Tests\migrate\Unit\MigrateTestCase;
/**
* Tests the D6 SQL base class.
*
* @group migrate_drupal
*/
class Drupal6SqlBaseTest extends MigrateTestCase {
/**
* Define bare minimum migration configuration.
*/
protected $migrationConfiguration = array(
'id' => 'Drupal6SqlBase',
);
/**
* @var \Drupal\migrate_drupal\Plugin\migrate\source\DrupalSqlBase
*/
protected $base;
/**
* Minimum database contents needed to test Drupal6SqlBase.
*/
protected $databaseContents = array(
'system' => array(
array(
'filename' => 'sites/all/modules/module1',
'name' => 'module1',
'type' => 'module',
'status' => 1,
'schema_version' => -1,
),
array(
'filename' => 'sites/all/modules/module2',
'name' => 'module2',
'type' => 'module',
'status' => 0,
'schema_version' => 7201,
),
array(
'filename' => 'sites/all/modules/test2',
'name' => 'test2',
'type' => 'theme',
'status' => 1,
'schema_version' => -1,
),
),
'variable' => array(
array(
'name' => 'my_variable',
'value' => 'b:1;',
),
),
);
/**
* {@inheritdoc}
*/
protected function setUp() {
$plugin = 'placeholder_id';
/** @var \Drupal\Core\State\StateInterface $state */
$state = $this->getMock('Drupal\Core\State\StateInterface');
/** @var \Drupal\Core\Entity\EntityManagerInterface $entity_manager */
$entity_manager = $this->getMock('Drupal\Core\Entity\EntityManagerInterface');
$this->base = new TestDrupal6SqlBase($this->migrationConfiguration, $plugin, array(), $this->getMigration(), $state, $entity_manager);
$this->base->setDatabase($this->getDatabase($this->databaseContents));
}
/**
* Tests for Drupal6SqlBase::getSystemData().
*/
public function testGetSystemData() {
$system_data = $this->base->getSystemData();
// Should be 1 theme and 2 modules.
$this->assertEquals(1, count($system_data['theme']));
$this->assertEquals(2, count($system_data['module']));
// Calling again should be identical.
$this->assertSame($system_data, $this->base->getSystemData());
}
/**
* Tests for Drupal6SqlBase::moduleExists().
*/
public function testDrupal6ModuleExists() {
// This module should exist.
$this->assertTrue($this->base->moduleExistsWrapper('module1'));
// These modules should not exist.
$this->assertFalse($this->base->moduleExistsWrapper('module2'));
$this->assertFalse($this->base->moduleExistsWrapper('module3'));
}
/**
* Tests for Drupal6SqlBase::getModuleSchemaVersion().
*/
public function testGetModuleSchemaVersion() {
// Non-existent module.
$this->assertFalse($this->base->getModuleSchemaVersionWrapper('module3'));
// Disabled module should still return schema version.
$this->assertEquals(7201, $this->base->getModuleSchemaVersionWrapper('module2'));
// Enabled module.
$this->assertEquals(-1, $this->base->getModuleSchemaVersionWrapper('module1'));
}
/**
* Tests for Drupal6SqlBase::variableGet().
*/
public function testVariableGet() {
// Test default value.
$this->assertEquals('my_default', $this->base->variableGetWrapper('non_existent_variable', 'my_default'));
// Test non-default.
$this->assertSame(TRUE, $this->base->variableGetWrapper('my_variable', FALSE));
}
}
namespace Drupal\Tests\migrate_drupal\Unit\source\d6;
use Drupal\Core\Database\Connection;
use Drupal\Core\Extension\ModuleHandlerInterface;
use Drupal\migrate_drupal\Plugin\migrate\source\DrupalSqlBase;
/**
* Extends the Drupal6SqlBase abstract class.
*/
class TestDrupal6SqlBase extends DrupalSqlBase {
/**
* {@inheritdoc}
*/
public function fields() {
return array(
'filename' => t('The path of the primary file for this item.'),
'name' => t('The name of the item; e.g. node.'),
'type' => t('The type of the item, either module, theme, or theme_engine.'),
'owner' => t("A theme's 'parent'. Can be either a theme or an engine."),
'status' => t('Boolean indicating whether or not this item is enabled.'),
'throttle' => t('Boolean indicating whether this item is disabled when the throttle.module disables throttleable items.'),
'bootstrap' => t('Boolean indicating whether this module is loaded during Drupal\'s early bootstrapping phase (e.g. even before the page cache is consulted).'),
'schema_version' => t('The module\'s database schema version number.'),
'weight' => t('The order in which this module\'s hooks should be invoked.'),
'info' => t('A serialized array containing information from the module\'s .info file.'),
);
}
/**
* {@inheritdoc}
*/
public function query() {
$query = $this->database
->select('system', 's')
->fields('s', array('filename', 'name', 'schema_version'));
return $query;
}
/**
* Tweaks Drupal6SqlBase to set a new database connection for tests.
*
* @param \Drupal\Core\Database\Connection $database
* The new connection to use.
*
* @see \Drupal\Tests\migrate\Unit\MigrateSqlTestCase
*/
public function setDatabase(Connection $database) {
$this->database = $database;
}
/**
* Tweaks Drupal6SqlBase to set a new module handler for tests.
*
* @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler
* The new module handler to use.
*
* @see \Drupal\Tests\migrate\Unit\MigrateSqlTestCase
*/
public function setModuleHandler(ModuleHandlerInterface $module_handler) {
$this->moduleHandler = $module_handler;
}
/**
* Wrapper method to test protected method moduleExists().
*/
public function moduleExistsWrapper($module) {
return parent::moduleExists($module);
}
/**
* Wrapper method to test protected method getModuleSchemaVersion().
*/
public function getModuleSchemaVersionWrapper($module) {
return parent::getModuleSchemaVersion($module);
}
/**
* Wrapper method to test protected method variableGet().
*/
public function variableGetWrapper($name, $default) {
return parent::variableGet($name, $default);
}
/**
* {@inheritdoc}
*/
public function getIds() {
return array();
}
}

View file

@ -0,0 +1,61 @@
<?php
namespace Drupal\Tests\migrate_drupal\Unit\source\d6;
use Drupal\Tests\migrate\Unit\MigrateSqlSourceTestCase;
/**
* Tests the variable source plugin.
*
* @group migrate_drupal
*/
class i18nVariableTest extends MigrateSqlSourceTestCase {
// The plugin system is not working during unit testing so the source plugin
// class needs to be manually specified.
const PLUGIN_CLASS = 'Drupal\migrate_drupal\Plugin\migrate\source\d6\i18nVariable';
/**
* Define bare minimum migration configuration.
*/
protected $migrationConfiguration = [
'id' => 'test',
'highWaterProperty' => array('field' => 'test'),
'source' => [
'plugin' => 'i18n_variable',
'variables' => [
'site_slogan',
'site_name',
],
],
];
/**
* Expected results from the source.
*/
protected $expectedResults = [
[
'language' => 'fr',
'site_slogan' => 'Migrate est génial',
'site_name' => 'nom de site',
],
[
'language' => 'mi',
'site_slogan' => 'Ko whakamataku heke',
'site_name' => 'ingoa_pae',
]
];
/**
* Database contents for tests.
*/
protected $databaseContents = [
'i18n_variable' => [
array('name' => 'site_slogan', 'language' => 'fr', 'value' => 's:19:"Migrate est génial";'),
array('name' => 'site_name', 'language' => 'fr', 'value' => 's:11:"nom de site";'),
array('name' => 'site_slogan', 'language' => 'mi', 'value' => 's:19:"Ko whakamataku heke";'),
array('name' => 'site_name', 'language' => 'mi', 'value' => 's:9:"ingoa_pae";'),
],
];
}