Skip to content
......@@ -2,9 +2,7 @@
/**
* @file
* Provide views data and handlers for file.module.
*
* @ingroup views_module_handlers
* Provide views data for file.module.
*/
use Drupal\Core\Entity\FieldableDatabaseStorageController;
......
......@@ -2,9 +2,7 @@
/**
* @file
* Provide views data and handlers for forum.module.
*
* @ingroup views_module_handlers
* Provide views data for forum.module.
*/
/**
......
......@@ -2,9 +2,7 @@
/**
* @file
* Provide views data and handlers for history.module.
*
* @ingroup views_module_handlers
* Provide views data for history.module.
*/
/**
......
......@@ -2,9 +2,7 @@
/**
* @file
* Provide views data and handlers for image.module.
*
* @ingroup views_module_handlers
* Provide views data for image.module.
*/
use Drupal\Core\Entity\FieldableDatabaseStorageController;
......
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;
}
}
<?php
/**
* @file
* Contains \Drupal\migrate\MigrateExecutable.
*/
namespace Drupal\migrate;
use Drupal\migrate\Entity\MigrationInterface;
use Drupal\migrate\Plugin\MigrateIdMapInterface;
/**
* Defines a migrate executable class.
*/
class MigrateExecutable {
/**
* The migration to do.
*
* @var \Drupal\migrate\Entity\MigrationInterface
*/
protected $migration;
/**
* The number of successfully imported rows since feedback was given.
*
* @var int
*/
protected $successes_since_feedback;
/**
* The number of rows that were successfully processed.
*
* @var int
*/
protected $total_successes;
/**
* Status of one row.
*
* The value is a MigrateIdMapInterface::STATUS_* constant, for example:
* STATUS_IMPORTED.
*
* @var int
*/
protected $needsUpdate;
/**
* The number of rows processed.
*
* The total attempted, whether or not they were successful.
*
* @var int
*/
protected $total_processed;
/**
* The queued messages not yet saved.
*
* Each element in the array is an array with two keys:
* - 'message': The message string.
* - 'level': The level, a MigrationInterface::MESSAGE_* constant.
*
* @var array
*/
protected $queuedMessages = array();
/**
* The options that can be set when executing the migration.
*
* Values can be set for:
* - 'limit': Sets a time limit.
*
* @var array
*/
protected $options;
/**
* The fraction of the memory limit at which an operation will be interrupted.
* Can be overridden by a Migration subclass if one would like to push the
* envelope. Defaults to 85%.
*
* @var float
*/
protected $memoryThreshold = 0.85;
/**
* The PHP memory_limit expressed in bytes.
*
* @var int
*/
protected $memoryLimit;
/**
* The fraction of the time limit at which an operation will be interrupted.
* Can be overridden by a Migration subclass if one would like to push the
* envelope. Defaults to 90%.
*
* @var float
*/
protected $timeThreshold = 0.90;
/**
* The PHP max_execution_time.
*
* @var int
*/
protected $timeLimit;
/**
* @var array
*/
protected $sourceIdValues;
/**
* @var int
*/
protected $processed_since_feedback = 0;
/**
* The translation manager.
*
* @var \Drupal\Core\StringTranslation\TranslationInterface
*/
protected $translationManager;
/**
* @param MigrationInterface $migration
* @param MigrateMessageInterface $message
*
* @throws \Drupal\migrate\MigrateException
*/
public function __construct(MigrationInterface $migration, MigrateMessageInterface $message) {
$this->migration = $migration;
$this->message = $message;
$this->migration->getIdMap()->setMessage($message);
// Record the memory limit in bytes
$limit = trim(ini_get('memory_limit'));
if ($limit == '-1') {
$this->memoryLimit = PHP_INT_MAX;
}
else {
if (!is_numeric($limit)) {
$last = strtolower(substr($limit, -1));
switch ($last) {
case 'g':
$limit *= 1024;
case 'm':
$limit *= 1024;
case 'k':
$limit *= 1024;
break;
default:
throw new MigrateException($this->t('Invalid PHP memory_limit !limit',
array('!limit' => $limit)));
}
}
$this->memoryLimit = $limit;
}
}
/**
* @return \Drupal\migrate\Source
*/
public function getSource() {
if (!isset($this->source)) {
$this->source = new Source($this->migration, $this);
}
return $this->source;
}
/**
* The rollback action to be saved for the current row.
*
* @var int
*/
public $rollbackAction;
/**
* An array of counts. Initially used for cache hit/miss tracking.
*
* @var array
*/
protected $counts = array();
/**
* When performing a bulkRollback(), the maximum number of items to pass in
* a single call. Can be overridden in derived class constructor.
*
* @var int
*/
protected $rollbackBatchSize = 50;
/**
* The object currently being constructed
* @var \stdClass
*/
protected $destinationValues;
/**
* The current data row retrieved from the source.
* @var \stdClass
*/
protected $sourceValues;
/**
* Perform an import operation - migrate items from source to destination.
*/
public function import() {
$return = MigrationInterface::RESULT_COMPLETED;
$source = $this->getSource();
$destination = $this->migration->getDestinationPlugin();
$id_map = $this->migration->getIdMap();
try {
$source->rewind();
}
catch (\Exception $e) {
$this->message->display(
$this->t('Migration failed with source plugin exception: !e',
array('!e' => $e->getMessage())));
return MigrationInterface::RESULT_FAILED;
}
while ($source->valid()) {
$row = $source->current();
if ($this->sourceIdValues = $row->getSourceIdValues()) {
// Wipe old messages, and save any new messages.
$id_map->delete($row->getSourceIdValues(), TRUE);
$this->saveQueuedMessages();
}
$this->processRow($row);
try {
$destination_id_values = $destination->import($row);
// @TODO handle the successful but no ID case like config.
if ($destination_id_values) {
$id_map->saveIdMapping($row, $destination_id_values, $this->needsUpdate, $this->rollbackAction);
$this->successes_since_feedback++;
$this->total_successes++;
}
else {
$id_map->saveIdMapping($row, array(), MigrateIdMapInterface::STATUS_FAILED, $this->rollbackAction);
if ($id_map->messageCount() == 0) {
$message = $this->t('New object was not saved, no error provided');
$this->saveMessage($message);
$this->message->display($message);
}
}
}
catch (MigrateException $e) {
$this->migration->getIdMap()->saveIdMapping($row, array(), $e->getStatus(), $this->rollbackAction);
$this->saveMessage($e->getMessage(), $e->getLevel());
$this->message->display($e->getMessage());
}
catch (\Exception $e) {
$this->migration->getIdMap()->saveIdMapping($row, array(), MigrateIdMapInterface::STATUS_FAILED, $this->rollbackAction);
$this->handleException($e);
}
$this->total_processed++;
$this->processed_since_feedback++;
if ($highwater_property = $this->migration->get('highwaterProperty')) {
$this->migration->saveHighwater($row->getSourceProperty($highwater_property['name']));
}
// Reset row properties.
unset($sourceValues, $destinationValues);
$this->needsUpdate = MigrateIdMapInterface::STATUS_IMPORTED;
// TODO: Temporary. Remove when http://drupal.org/node/375494 is committed.
// TODO: Should be done in MigrateDestinationEntity
if (!empty($destination->entityType)) {
entity_get_controller($destination->entityType)->resetCache();
}
if (($return = $this->checkStatus()) != MigrationInterface::RESULT_COMPLETED) {
break;
}
if ($this->timeOptionExceeded()) {
break;
}
try {
$source->next();
}
catch (\Exception $e) {
$this->message->display(
$this->t('Migration failed with source plugin exception: !e',
array('!e' => $e->getMessage())));
return MigrationInterface::RESULT_FAILED;
}
}
/**
* @TODO uncomment this
*/
#$this->progressMessage($return);
return $return;
}
/**
* @param Row $row
* The $row to be processed.
* @param array $process
* A process pipeline configuration. If not set, the top level process
* configuration in the migration entity is used.
* @param mixed $value
* Optional initial value of the pipeline for the first destination.
* Usually setting this is not necessary as $process typically starts with
* a 'get'. This is useful only when the $process contains a single
* destination and needs to access a value outside of the source. See
* \Drupal\migrate\Plugin\migrate\process\Iterator::transformKey for an
* example.
*/
public function processRow(Row $row, array $process = NULL, $value = NULL) {
foreach ($this->migration->getProcessPlugins($process) as $destination => $plugins) {
foreach ($plugins as $plugin) {
$value = $plugin->transform($value, $this, $row, $destination);
}
$row->setDestinationProperty($destination, $value);
// Reset the value.
$value = NULL;
}
}
/**
* Fetch the key array for the current source record.
*
* @return array
*/
protected function currentSourceIds() {
return $this->getSource()->getCurrentIds();
}
/**
* Test whether we've exceeded the designated time limit.
*
* @return boolean
* TRUE if the threshold is exceeded, FALSE if not.
*/
protected function timeOptionExceeded() {
if (!$time_limit = $this->getTimeLimit()) {
return FALSE;
}
$time_elapsed = time() - REQUEST_TIME;
if ($time_elapsed >= $time_limit) {
return TRUE;
}
else {
return FALSE;
}
}
public function getTimeLimit() {
if (isset($this->options['limit']) &&
($this->options['limit']['unit'] == 'seconds' || $this->options['limit']['unit'] == 'second')) {
return $this->options['limit']['value'];
}
else {
return NULL;
}
}
/**
* Pass messages through to the map class.
*
* @param string $message
* The message to record.
* @param int $level
* Optional message severity (defaults to MESSAGE_ERROR).
*/
public function saveMessage($message, $level = MigrationInterface::MESSAGE_ERROR) {
$this->migration->getIdMap()->saveMessage($this->sourceIdValues, $message, $level);
}
/**
* Queue messages to be later saved through the map class.
*
* @param string $message
* The message to record.
* @param int $level
* Optional message severity (defaults to MESSAGE_ERROR).
*/
public function queueMessage($message, $level = MigrationInterface::MESSAGE_ERROR) {
$this->queuedMessages[] = array('message' => $message, 'level' => $level);
}
/**
* Save any messages we've queued up to the message table.
*/
public function saveQueuedMessages() {
foreach ($this->queuedMessages as $queued_message) {
$this->saveMessage($queued_message['message'], $queued_message['level']);
}
$this->queuedMessages = array();
}
/**
* Standard top-of-loop stuff, common between rollback and import - check
* for exceptional conditions, and display feedback.
*/
protected function checkStatus() {
if ($this->memoryExceeded()) {
return MigrationInterface::RESULT_INCOMPLETE;
}
if ($this->timeExceeded()) {
return MigrationInterface::RESULT_INCOMPLETE;
}
/*
* @TODO uncomment this
if ($this->getStatus() == MigrationInterface::STATUS_STOPPING) {
return MigrationBase::RESULT_STOPPED;
}
*/
// If feedback is requested, produce a progress message at the proper time
/*
* @TODO uncomment this
if (isset($this->feedback)) {
if (($this->feedback_unit == 'seconds' && time() - $this->lastfeedback >= $this->feedback) ||
($this->feedback_unit == 'items' && $this->processed_since_feedback >= $this->feedback)) {
$this->progressMessage(MigrationInterface::RESULT_INCOMPLETE);
}
}
*/
return MigrationInterface::RESULT_COMPLETED;
}
/**
* Test whether we've exceeded the desired memory threshold. If so, output a message.
*
* @return boolean
* TRUE if the threshold is exceeded, FALSE if not.
*/
protected function memoryExceeded() {
$usage = memory_get_usage();
$pct_memory = $usage / $this->memoryLimit;
if ($pct_memory > $this->memoryThreshold) {
$this->message->display(
$this->t('Memory usage is !usage (!pct% of limit !limit), resetting statics',
array('!pct' => round($pct_memory*100),
'!usage' => format_size($usage),
'!limit' => format_size($this->memoryLimit))),
'warning');
// First, try resetting Drupal's static storage - this frequently releases
// plenty of memory to continue
drupal_static_reset();
$usage = memory_get_usage();
$pct_memory = $usage/$this->memoryLimit;
// Use a lower threshold - we don't want to be in a situation where we keep
// coming back here and trimming a tiny amount
if ($pct_memory > (.90 * $this->memoryThreshold)) {
$this->message->display(
$this->t('Memory usage is now !usage (!pct% of limit !limit), not enough reclaimed, starting new batch',
array('!pct' => round($pct_memory*100),
'!usage' => format_size($usage),
'!limit' => format_size($this->memoryLimit))),
'warning');
return TRUE;
}
else {
$this->message->display(
$this->t('Memory usage is now !usage (!pct% of limit !limit), reclaimed enough, continuing',
array('!pct' => round($pct_memory*100),
'!usage' => format_size($usage),
'!limit' => format_size($this->memoryLimit))),
'warning');
return FALSE;
}
}
else {
return FALSE;
}
}
/**
* Test whether we're approaching the PHP time limit.
*
* @return boolean
* TRUE if the threshold is exceeded, FALSE if not.
*/
protected function timeExceeded() {
if ($this->timeLimit == 0) {
return FALSE;
}
$time_elapsed = time() - REQUEST_TIME;
$pct_time = $time_elapsed / $this->timeLimit;
if ($pct_time > $this->timeThreshold) {
return TRUE;
}
else {
return FALSE;
}
}
/**
* Takes an Exception object and both saves and displays it, pulling additional
* information on the location triggering the exception.
*
* @param \Exception $exception
* Object representing the exception.
* @param boolean $save
* Whether to save the message in the migration's mapping table. Set to FALSE
* in contexts where this doesn't make sense.
*/
public function handleException($exception, $save = TRUE) {
$result = _drupal_decode_exception($exception);
$message = $result['!message'] . ' (' . $result['%file'] . ':' . $result['%line'] . ')';
if ($save) {
$this->saveMessage($message);
}
$this->message->display($message);
}
/**
* Translates a string to the current language or to a given language.
*
* See the t() documentation for details.
*/
protected function t($string, array $args = array(), array $options = array()) {
return $this->translationManager()->translate($string, $args, $options);
}
/**
* Gets the translation manager.
*
* @return \Drupal\Core\StringTranslation\TranslationInterface
* The translation manager.
*/
protected function translationManager() {
if (!$this->translationManager) {
$this->translationManager = \Drupal::translation();
}
return $this->translationManager;
}
}
<?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();
/**
* Returns the number of processed items in the map.
*
* @return int
* The count of records in the map table.
*/
public function processedCount();
/**
* Returns the number of imported items in the map.
*
* @return int
* The number of imported items.
*/
public function importedCount();
/**
* Returns a count of items which are marked as needing update.
*
* @return int
* The number of items which need updating.
*/
public function updateCount();
/**
* Returns the number of items that failed to import.
*
* @return int
* The number of items that errored out.
*/
public function errorCount();
/**
* Returns the number of messages saved.
*
* @return int
* The number of messages.
*/
public function messageCount();
/**
* Deletes the map and message entries for a given source record.
*
* @param array $source_id_values
* The source identifier values of the record to delete.
* @param bool $messages_only
* TRUE to only delete the migrate messages.
*/
public function delete(array $source_id_values, $messages_only = FALSE);
/**
* Deletes the map and message table entries for a given destination row.
*
* @param array $destination_id_values
* The destination identifier values we should do the deletes for.
*/
public function deleteDestination(array $destination_id_values);
/**
* Deletes the map and message entries for a set of given source records.
*
* @param array $source_id_values
* The identifier values of the sources we should do the deletes for. Each
* array member is an array of identifier values for one source row.
*/
public function deleteBulk(array $source_id_values);
/**
* Clears all messages from the map.
*/
public function clearMessages();
/**
* Retrieves a row from the map table based on source identifier values.
*
* @param array $source_id_values
* The source identifier values of the record to retrieve.
*
* @return array
* The raw row data as an associative array.
*/
public function getRowBySource(array $source_id_values);
/**
* Retrieves a row by the destination identifiers.
*
* @param array $destination_id_values
* The destination identifier values of the record to retrieve.
*
* @return array
* The row(s) of data.
*/
public function getRowByDestination(array $destination_id_values);
/**
* Retrieves an array of map rows marked as needing update.
*
* @param int $count
* The maximum number of rows to return.
*
* @return array
* Array of map row objects that need updating.
*/
public function getRowsNeedingUpdate($count);
/**
* Looks up the source identifier.
*
* Given a (possibly multi-field) destination identifier value, return the
* (possibly multi-field) source identifier value mapped to it.
*
* @param array $destination_id_values
* The destination identifier values of the record.
*
* @return array
* The source identifier values of the record, or NULL on failure.
*/
public function lookupSourceID(array $destination_id_values);
/**
* Looks up the destination identifier.
*
* Given a (possibly multi-field) source identifier value, return the
* (possibly multi-field) destination identifier value it is mapped to.
*
* @param array $destination_id_values
* The source identifier values of the record.
*
* @return array
* The destination identifier values of the record, or NULL on failure.
*/
public function lookupDestinationID(array $source_id_values);
/**
* Removes any persistent storage used by this map.
*
* For example, remove the map and message tables.
*/
public function destroy();
/**
* Gets the qualified map table.
*
* @todo Remove this as this is SQL only and so doesn't belong to the interface.
*/
public function getQualifiedMapTable();
/**
* Sets the migrate message.
*
* @param \Drupal\migrate\MigrateMessageInterface $message
* The message to display.
*/
public function setMessage(MigrateMessageInterface $message);
/**
* Sets a specified record to be updated, if it exists.
*
* @param $source_id_values
* The source identifier values of the record.
*/
public function setUpdate(array $source_id_values);
}
<?php
/**
* @file
* Contains \Drupal\migrate\MigraterPluginManager.
*/
namespace Drupal\migrate\Plugin;
use Drupal\Component\Plugin\Factory\DefaultFactory;
use Drupal\Core\Cache\CacheBackendInterface;
use Drupal\Core\Extension\ModuleHandlerInterface;
use Drupal\Core\Language\LanguageManager;
use Drupal\Core\Plugin\DefaultPluginManager;
use Drupal\migrate\Entity\MigrationInterface;
/**
* Manages migrate sources and steps.
*
* @see hook_migrate_info_alter()
*/
class MigratePluginManager extends DefaultPluginManager {
/**
* Constructs a MigraterPluginManager object.
*
* @param string $type
* The type of the plugin: row, source, process, destination, entity_field, id_map.
* @param \Traversable $namespaces
* An object that implements \Traversable which contains the root paths
* keyed by the corresponding namespace to look for plugin implementations.
* @param \Drupal\Core\Cache\CacheBackendInterface $cache_backend
* Cache backend instance to use.
* @param \Drupal\Core\Language\LanguageManager $language_manager
* The language manager.
* @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler
* The module handler to invoke the alter hook with.
*/
public function __construct($type, \Traversable $namespaces, CacheBackendInterface $cache_backend, LanguageManager $language_manager, ModuleHandlerInterface $module_handler) {
parent::__construct("Plugin/migrate/$type", $namespaces, 'Drupal\Component\Annotation\PluginID');
$this->alterInfo($module_handler, 'migrate_' . $type . '_info');
$this->setCacheBackend($cache_backend, $language_manager, 'migrate_plugins_' . $type);
}
/**
* {@inheritdoc}
*
* A specific createInstance method is necessary to pass the migration on.
*/
public function createInstance($plugin_id, array $configuration = array(), MigrationInterface $migration = NULL) {
$plugin_definition = $this->discovery->getDefinition($plugin_id);
$plugin_class = DefaultFactory::getPluginClass($plugin_id, $plugin_definition);
// If the plugin provides a factory method, pass the container to it.
if (is_subclass_of($plugin_class, 'Drupal\Core\Plugin\ContainerFactoryPluginInterface')) {
return $plugin_class::create(\Drupal::getContainer(), $configuration, $plugin_id, $plugin_definition, $migration);
}
return new $plugin_class($configuration, $plugin_id, $plugin_definition, $migration);
}
}
<?php
/**
* @file
* Contains \Drupal\migrate\Plugin\MigrateProcessInterface.
*/
namespace Drupal\migrate\Plugin;
use Drupal\Component\Plugin\PluginInspectionInterface;
use Drupal\migrate\MigrateExecutable;
use Drupal\migrate\Row;
/**
* An interface for migrate processes.
*/
interface MigrateProcessInterface extends PluginInspectionInterface {
/**
* Performs the associated process.
*
* @param $value
* The value to be transformed.
* @param \Drupal\migrate\MigrateExecutable $migrate_executable
* The migration in which this process is being executed.
* @param \Drupal\migrate\Row $row
* The row from the source to process. Normally, just transforming the
* value is adequate but very rarely you might need to change two columns
* at the same time or something like that.
* @param string $destination_property
* The destination property currently worked on. This is only used
* together with the $row above.
*/
public function transform($value, MigrateExecutable $migrate_executable, Row $row, $destination_property);
}
<?php
/**
* @file
* Contains \Drupal\migrate\Plugin\MigrateSourceInterface.
*/
namespace Drupal\migrate\Plugin;
use Drupal\Component\Plugin\PluginInspectionInterface;
use Drupal\migrate\Row;
/**
* Defines an interface for migrate sources.
*/
interface MigrateSourceInterface extends \Countable, PluginInspectionInterface {
/**
* Returns available fields on the source.
*
* @return array
* Available fields in the source, keys are the field machine names as used
* in field mappings, values are descriptions.
*/
public function fields();
/**
* Returns the iterator that will yield the row arrays to be processed.
*
* @return \Iterator
*/
public function getIterator();
/**
* Add additional data to the row.
*
* @param \Drupal\Migrate\Row $row
*
* @return bool
* FALSE if this row needs to be skipped.
*/
public function prepareRow(Row $row);
public function __toString();
}
<?php
/**
* @file
* Contains \Drupal\migrate\Plugin\RequirementsInterface.
*/
namespace Drupal\migrate\Plugin;
/**
* An interface to check for a migrate plugin requirements.
*/
interface RequirementsInterface {
/**
* Checks if requirements for this plugin are OK.
*
* @return boolean
* TRUE if it is possible to use the plugin, FALSE if not.
*/
public function checkRequirements();
}
<?php
/**
* @file
* Provides Configuration Management destination plugin.
*/
namespace Drupal\migrate\Plugin\migrate\destination;
use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
use Drupal\migrate\Entity\Migration;
use Drupal\migrate\MigrateException;
use Drupal\migrate\Row;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Drupal\Core\Config\Config as ConfigObject;
/**
* Persist data to the config system.
*
* @PluginID("d8_config")
*/
class Config extends DestinationBase implements ContainerFactoryPluginInterface {
/**
* The config object.
*
* @var \Drupal\Core\Config\Config
*/
protected $config;
/**
* @param array $configuration
* @param string $plugin_id
* @param array $plugin_definition
* @param ConfigObject $config
*/
public function __construct(array $configuration, $plugin_id, array $plugin_definition, ConfigObject $config) {
parent::__construct($configuration, $plugin_id, $plugin_definition);
$this->config = $config;
}
public static function create(ContainerInterface $container, array $configuration, $plugin_id, array $plugin_definition) {
return new static(
$configuration,
$plugin_id,
$plugin_definition,
$container->get('config.factory')->get($configuration['config_name'])
);
}
/**
* {@inheritdoc}
*/
public function import(Row $row) {
$this->config
->setData($row->getDestination())
->save();
}
/**
* @param array $destination_keys
*
* @throws \Drupal\migrate\MigrateException
*/
public function rollbackMultiple(array $destination_keys) {
throw new MigrateException('Configuration can not be rolled back');
}
/**
* 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) {
// @todo Dynamically fetch fields using Config Schema API.
}
public function getIdsSchema() {
return array($this->config->getName() => array());
}
}