Commit 67f30bc0 authored by Dries's avatar Dries

Migrate in core #2125717 by mikeryan, chx, marvil07, bdone, jessehs, mpgeek,...

Migrate in core #2125717 by mikeryan, chx, marvil07, bdone, jessehs, mpgeek, BTMash, fastangel, mongolito404, Moshe Weitzman, eliza411, YesCT, dawehner, cosmicdreams
parent 40e903f8
id: d6_system_cron
source:
plugin: drupal6_variable
variables:
- cron_threshold_warning
- cron_threshold_error
- cron_last
process:
'threshold:warning': cron_threshold_warning
'threshold:error': cron_threshold_error
destination:
plugin: d8_config
config_name: system.cron
id: d6_system_rss
source:
plugin: drupal6_variable
variables:
- feed_default_items
process:
'items:limit': feed_default_items
destination:
plugin: d8_config
config_name: system.rss
id: d6_system_site
source:
plugin: drupal6_variable
variables:
- site_name
- site_mail
- site_slogan
- site_frontpage
- site_403
- site_404
- drupal_weight_select_max
- admin_compact_mode
process:
name: site_name
mail: site_mail
slogan: site_slogan
'page:front': site_frontpage
'page:403': site_403
'page:404': site_404
weight_select_max: drupal_weight_select_max
admin_compact_mode: admin_compact_mode
destination:
plugin: d8_config
config_name: system.site
<?php
/**
* @file
* Contains \Drupal\migrate\Entity\Migration.
*/
namespace Drupal\migrate\Entity;
use Drupal\Core\Config\Entity\ConfigEntityBase;
use Drupal\migrate\MigrateException;
use Drupal\migrate\Plugin\MigrateIdMapInterface;
/**
* Defines the Migration entity.
*
* The migration entity stores the information about a single migration, like
* the source, process and destination plugins.
*
* @EntityType(
* id = "migration",
* label = @Translation("Migration"),
* module = "migrate",
* controllers = {
* "storage" = "Drupal\Core\Config\Entity\ConfigStorageController",
* "list" = "Drupal\Core\Config\Entity\DraggableListController",
* "access" = "Drupal\Core\Entity\EntityAccessController",
* "form" = {
* "add" = "Drupal\Core\Entity\EntityFormController",
* "edit" = "Drupal\Core\Entity\EntityFormController",
* "delete" = "Drupal\Core\Entity\EntityFormController"
* }
* },
* config_prefix = "migrate.migration",
* entity_keys = {
* "id" = "id",
* "label" = "label",
* "weight" = "weight",
* "uuid" = "uuid"
* }
* )
*/
class Migration extends ConfigEntityBase implements MigrationInterface {
/**
* The migration ID (machine name).
*
* @var string
*/
public $id;
/**
* The migration UUID.
*
* This is assigned automatically when the migration is created.
*
* @var string
*/
public $uuid;
/**
* The human-readable label for the migration.
*
* @var string
*/
public $label;
/**
* The plugin ID for the row.
*
* @var string
*/
public $row;
/**
* The source configuration, with at least a 'plugin' key.
*
* Used to initialize the $sourcePlugin.
*
* @var array
*/
public $source;
/**
* The source plugin.
*
* @var \Drupal\migrate\Plugin\MigrateSourceInterface
*/
protected $sourcePlugin;
/**
* The configuration describing the process plugins.
*
* @var array
*/
public $process;
/**
* The destination configuration, with at least a 'plugin' key.
*
* Used to initialize $destinationPlugin.
*
* @var array
*/
public $destination;
/**
* The destination plugin.
*
* @var \Drupal\migrate\Plugin\MigrateDestinationInterface
*/
protected $destinationPlugin;
/**
* The identifier map data.
*
* Used to initialize $idMapPlugin.
*
* @var string
*/
public $idMap = array();
/**
* The identifier map.
*
* @var \Drupal\migrate\Plugin\MigrateIdMapInterface
*/
protected $idMapPlugin;
/**
* The source identifiers.
*
* An array of source identifiers: the keys are the name of the properties,
* the values are dependent on the ID map plugin.
*
* @var array
*/
public $sourceIds = array();
/**
* The destination identifiers.
*
* An array of destination identifiers: the keys are the name of the
* properties, the values are dependent on the ID map plugin.
*
* @var array
*/
public $destinationIds = array();
/**
* Information on the highwater mark.
*
* @var array
*/
public $highwaterProperty;
/**
* Indicate whether the primary system of record for this migration is the
* source, or the destination (Drupal). In the source case, migration of
* an existing object will completely replace the Drupal object with data from
* the source side. In the destination case, the existing Drupal object will
* be loaded, then changes from the source applied; also, rollback will not be
* supported.
*
* @var string
*/
public $systemOfRecord = self::SOURCE;
/**
* Specify value of needs_update for current map row. Usually set by
* MigrateFieldHandler implementations.
*
* @var int
*/
public $needsUpdate = MigrateIdMapInterface::STATUS_IMPORTED;
/**
* @var \Drupal\Core\KeyValueStore\KeyValueStoreInterface
*/
protected $highwaterStorage;
/**
* @var bool
*/
public $trackLastImported = FALSE;
/**
* {@inheritdoc}
*/
public function getSourcePlugin() {
if (!isset($this->sourcePlugin)) {
$this->sourcePlugin = \Drupal::service('plugin.manager.migrate.source')->createInstance($this->source['plugin'], $this->source, $this);
}
return $this->sourcePlugin;
}
/**
* {@inheritdoc}
*/
public function getProcessPlugins(array $process = NULL) {
if (!isset($process)) {
$process = $this->process;
}
$process_plugins = array();
foreach ($this->getProcessNormalized($process) as $property => $configurations) {
$process_plugins[$property] = array();
foreach ($configurations as $configuration) {
if (isset($configuration['source'])) {
$process_plugins[$property][] = \Drupal::service('plugin.manager.migrate.process')->createInstance('get', $configuration, $this);
}
// Get is already handled.
if ($configuration['plugin'] != 'get') {
$process_plugins[$property][] = \Drupal::service('plugin.manager.migrate.process')->createInstance($configuration['plugin'], $configuration, $this);
}
if (!$process_plugins[$property]) {
throw new MigrateException("Invalid process configuration for $property");
}
}
}
return $process_plugins;
}
/**
* Resolve shorthands into a list of plugin configurations.
*
* @param array $process
* A process configuration array.
*
* @return array
* The normalized process configuration.
*/
protected function getProcessNormalized(array $process) {
$normalized_configurations = array();
foreach ($process as $destination => $configuration) {
if (is_string($configuration)) {
$configuration = array(
'plugin' => 'get',
'source' => $configuration,
);
}
if (isset($configuration['plugin'])) {
$configuration = array($configuration);
}
$normalized_configurations[$destination] = $configuration;
}
return $normalized_configurations;
}
/**
* {@inheritdoc}
*/
public function getDestinationPlugin() {
if (!isset($this->destinationPlugin)) {
$this->destinationPlugin = \Drupal::service('plugin.manager.migrate.destination')->createInstance($this->destination['plugin'], $this->destination, $this);
}
return $this->destinationPlugin;
}
/**
* {@inheritdoc}
*/
public function getIdMap() {
if (!isset($this->idMapPlugin)) {
$configuration = $this->idMap;
$plugin = isset($configuration['plugin']) ? $configuration['plugin'] : 'sql';
$this->idMapPlugin = \Drupal::service('plugin.manager.migrate.id_map')->createInstance($plugin, $configuration, $this);
}
return $this->idMapPlugin;
}
/**
* @return \Drupal\Core\KeyValueStore\KeyValueStoreInterface
*/
protected function getHighWaterStorage() {
if (!isset($this->highwaterStorage)) {
$this->highwaterStorage = \Drupal::keyValue('migrate:highwater');
}
return $this->highwaterStorage;
}
public function getHighwater() {
return $this->getHighWaterStorage()->get($this->id());
}
public function saveHighwater($highwater) {
$this->getHighWaterStorage()->set($this->id(), $highwater);
}
}
<?php
/**
* @file
* Contains \Drupal\migrate\Entity\MigrationInterface.
*/
namespace Drupal\migrate\Entity;
use Drupal\Core\Config\Entity\ConfigEntityInterface;
/**
* Interface for migrations.
*/
interface MigrationInterface extends ConfigEntityInterface {
const SOURCE = 'source';
const DESTINATION = 'destination';
/**
* Codes representing the current status of a migration, and stored in the
* migrate_status table.
*/
const STATUS_IDLE = 0;
const STATUS_IMPORTING = 1;
const STATUS_ROLLING_BACK = 2;
const STATUS_STOPPING = 3;
const STATUS_DISABLED = 4;
/**
* Message types to be passed to saveMessage() and saved in message tables.
* MESSAGE_INFORMATIONAL represents a condition that did not prevent the
* operation from succeeding - all others represent different severities of
* conditions resulting in a source record not being imported.
*/
const MESSAGE_ERROR = 1;
const MESSAGE_WARNING = 2;
const MESSAGE_NOTICE = 3;
const MESSAGE_INFORMATIONAL = 4;
/**
* Codes representing the result of a rollback or import process.
*/
const RESULT_COMPLETED = 1; // All records have been processed
const RESULT_INCOMPLETE = 2; // The process has interrupted itself (e.g., the
// memory limit is approaching)
const RESULT_STOPPED = 3; // The process was stopped externally (e.g., via
// drush migrate-stop)
const RESULT_FAILED = 4; // The process had a fatal error
const RESULT_SKIPPED = 5; // Dependencies are unfulfilled - skip the process
const RESULT_DISABLED = 6; // This migration is disabled, skipping
/**
* Returns the initialized source plugin.
*
* @return \Drupal\migrate\Plugin\MigrateSourceInterface
*/
public function getSourcePlugin();
/**
* Returns the process plugins.
*
* @param array $process
* A process configuration array.
*
* @return array
* A list of process plugins.
*/
public function getProcessPlugins(array $process = NULL);
/**
* Returns the initialized destination plugin.
*
* @return \Drupal\migrate\Plugin\MigrateDestinationInterface
*/
public function getDestinationPlugin();
/**
* Returns the initialized id_map plugin.
*
* @return \Drupal\migrate\Plugin\MigrateIdMapInterface
*/
public function getIdMap();
/**
* @return int
*/
public function getHighwater();
public function saveHighwater($highwater);
}
<?php
/**
* @file
* Contains \Drupal\migrate\MigrateException.
*/
namespace Drupal\migrate;
use Drupal\migrate\Entity\MigrationInterface;
use Drupal\migrate\Plugin\MigrateIdMapInterface;
/**
* Defines the migrate exception class.
*/
class MigrateException extends \Exception {
/**
* The level of the error being reported.
*
* The value is a Migration::MESSAGE_* constant.
*
* @var int
*/
protected $level;
/**
* The status to record in the map table for the current item.
*
* The value is a MigrateMap::STATUS_* constant.
*
* @var int
*/
protected $status;
/**
* Constructs a MigrateException object.
*
* @param string $message
* The message for the exception.
* @param int $code
* The Exception code.
* @param \Exception $previous
* The previous exception used for the exception chaining.
* @param int $level
* The level of the error, a Migration::MESSAGE_* constant.
* @param int $status
* The status of the item for the map table, a MigrateMap::STATUS_*
* constant.
*/
public function __construct($message = null, $code = 0, \Exception $previous = null, $level = MigrationInterface::MESSAGE_ERROR, $status = MigrateIdMapInterface::STATUS_FAILED) {
$this->level = $level;
$this->status = $status;
parent::__construct($message);
}
/**
* Gets the level.
*
* @return int
*/
public function getLevel() {
return $this->level;
}
/**
* Gets the status of the current item.
*
* @return int
*/
public function getStatus() {
return $this->status;
}
}
This diff is collapsed.
<?php
/**
* @file
* Contains \Drupal\migrate\MigrateMessage.
*/
namespace Drupal\migrate;
/**
* Defines a migrate message class.
*/
class MigrateMessage implements MigrateMessageInterface {
/**
* Displays a migrate message.
*
* @param string $message
* The message to display.
* @param string $type
* The type of message, for example: status or warning.
*/
function display($message, $type = 'status') {
drupal_set_message($message, $type);
}
}
<?php
/**
* @file
* Contains
*/
namespace Drupal\migrate;
interface MigrateMessageInterface {
/**
* @param $message
* @param string $type
*
* @return mixed
*/
function display($message, $type = 'status');
}
<?php
/**
* @file
* Contains \Drupal\migrate\Plugin\MigrateDestinationInterface.
*/
namespace Drupal\migrate\Plugin;
use Drupal\Component\Plugin\PluginInspectionInterface;
use Drupal\migrate\Entity\Migration;
use Drupal\migrate\Row;
/**
* Destinations are responsible for persisting source data into the destination
* Drupal.
*/
interface MigrateDestinationInterface extends PluginInspectionInterface {
/**
* To support MigrateIdMap maps, derived destination classes should return
* schema field definition(s) corresponding to the primary key of the destination
* being implemented. These are used to construct the destination key fields
* of the map table for a migration using this destination.
*/
public function getIdsSchema();
/**
* Derived classes must implement fields(), returning a list of available
* destination fields.
*
* @todo Review the cases where we need the Migration parameter, can we avoid that?
*
* @param Migration $migration
* Optionally, the migration containing this destination.
* @return array
* - Keys: machine names of the fields
* - Values: Human-friendly descriptions of the fields.
*/
public function fields(Migration $migration = NULL);
/**
* Derived classes may implement preImport() and/or postImport(), to do any
* processing they need done before or after looping over all source rows.
* Similarly, preRollback() or postRollback() may be implemented.
*/
public function preImport();
public function preRollback();
public function postImport();
public function postRollback();
/**
* Derived classes must implement import(), to construct one new object (pre-populated
* using ID mappings in the Migration).
*/
public function import(Row $row);
/**
* Delete the specified IDs from the target Drupal.
* @param array $destination_identifiers
*/
public function rollbackMultiple(array $destination_identifiers);
}
<?php
/**
* @file
* Contains \Drupal\migrate\Plugin\MigrateIdMapInterface.
*/
namespace Drupal\migrate\Plugin;
use Drupal\Component\Plugin\PluginInspectionInterface;
use Drupal\migrate\Entity\MigrationInterface;
use Drupal\migrate\MigrateMessageInterface;
use Drupal\migrate\Row;
/**
* Defines an interface for migrate ID mappings.
*
* Migrate ID mappings maintain a relation between source ID and destination ID
* for audit and rollback purposes.
*/
interface MigrateIdMapInterface extends PluginInspectionInterface {
/**
* Codes reflecting the current status of a map row.
*/
const STATUS_IMPORTED = 0;
const STATUS_NEEDS_UPDATE = 1;
const STATUS_IGNORED = 2;
const STATUS_FAILED = 3;
/**
* Codes reflecting how to handle the destination item on rollback.
*/
const ROLLBACK_DELETE = 0;
const ROLLBACK_PRESERVE = 1;
/**
* Saves a mapping from the source identifiers to the destination identifiers.
*
* Called upon import of one row, we record a mapping from the source ID
* to the destination ID. Also may be called, setting the third parameter to
* NEEDS_UPDATE, to signal an existing record should be re-migrated.
*
* @param \Drupal\migrate\Row $row
* The raw source data. We use the ID map derived from the source object
* to get the source identifier values.
* @param array $destination_id_values
* An array of destination identifier values.
* @param int $status
* Status of the source row in the map.
* @param int $rollback_action
* How to handle the destination object on rollback.
*/
public function saveIdMapping(Row $row, array $destination_id_values, $status = self::STATUS_IMPORTED, $rollback_action = self::ROLLBACK_DELETE);
/**
* Saves a message related to a source record in the migration message table.
*
* @param array $source_id_values
* The source identifier values of the record in error.
* @param string $message
* The message to record.
* @param int $level
* Optional message severity (defaults to MESSAGE_ERROR).
*/
public function saveMessage(array $source_id_values, $message, $level = MigrationInterface::MESSAGE_ERROR);
/**
* Prepares to run a full update.
*
* Prepares this migration to run as an update - that is, in addition to
* unmigrated content (source records not in the map table) being imported,
* previously-migrated content will also be updated in place by marking all
* previously-imported content as ready to be re-imported.
*/
public function prepareUpdate();