migrate_d2d.migrate.inc in Drupal-to-Drupal data migration 7.2
Base classes for all Drupal-to-Drupal migration classes.
File
migrate_d2d.migrate.incView source
<?php
/**
* @file
* Base classes for all Drupal-to-Drupal migration classes.
*/
abstract class DrupalMigration extends Migration {
/**
* Connection key for the DatabaseConnection holding the source Drupal
* installation.
*
* @var
*/
protected $sourceConnection;
/**
* The major version of the Drupal install serving as the migration
* source, e.g. '6'.
*
* @var int
*/
protected $sourceVersion;
/**
* Options to be passed to source constructors.
*
* @var array
*/
protected $sourceOptions = array();
/**
* An array of available source fields, beyond those in the base query.
* Derived classes should populate this before calling the parent
* constructor.
*
* @var array
*/
protected $sourceFields = array();
/**
* Source type (bundle), if any.
*
* @var string
*/
protected $sourceType = '';
/**
* While much of the version-specific work can be done in the leaf classes,
* to share data and behavior among all classes for a given Drupal version
* we use this helper object.
*
* @var DrupalVersion
*/
protected $version;
/**
* Map format mappings from the source system to the destination. Automated
* generation of these mappings is version-dependent (through Drupal 6 they
* were identified by numeric IDs, Drupal 7 introduced machine names).
*
* @var array
*/
protected $formatMappings = array();
/**
* Set to TRUE to suppress highwater marks or track_changes (i.e., to only
* import new items, skipping updated items, on subsequent imports).
*
* @var bool
*/
protected $newOnly = FALSE;
/**
* Controls what db connection the MigrateSQLMaps use.
*
* Pass $arguments['map_connection'] to change this variable.
*
* @var string
*/
protected $mapConnection = 'default';
/**
* Required arguments:
*
* source_connection - Connection key for the DatabaseConnection holding the
* source Drupal installation.
* source_version - Major version number (as an integer) of the source install.
* machine_name - Machine name under which a particular migration is registered.
* description - Description of the migration.
* group_name - The group (import job) containing this migration (import
* task).
*
* Optional arguments:
*
* source_database - Array describing the source connection, to be defined in
* the constructor. If absent, the source connection is assumed to be established
* elsewhere (typically settings.php).
* group - Migration group to add this migration to.
* dependencies - Array of migrations that must be run before this one.
* soft_dependencies - Array of migrations that should be listed before this one.
* format_mappings - Array keyed by source format IDs or machine names, with
* the values being the corresponding D7 machine name. If unspecified,
* source_options - Array to be passed as options to source constructors,
* overriding the defaults (map_joinable FALSE, cache_counts TRUE, cache_key
* derived from the machine name).
* version_class - The name of a custom DrupalVersion class overriding the
* default derived from source_version.
* new_only - For any destination types that support highwater marks or
* track_changes, suppress that support so repeated migrations only import
* new items.
*
* @param array $arguments
*/
public function __construct($arguments) {
parent::__construct($arguments);
if (empty($this->arguments['source_version'])) {
throw new MigrateException(t('No source_version provided in migrate_d2d migration arguments.'));
}
else {
$this->sourceVersion = $this->arguments['source_version'];
}
if (isset($this->arguments['version_class'])) {
$version_class = $this->arguments['version_class'];
}
else {
$version_class = 'DrupalVersion' . $this->sourceVersion;
}
$this->version = new $version_class($this->arguments);
if (!isset($this->arguments['group'])) {
$this->arguments['group'] = MigrateGroup::getInstance($this->arguments['group_name']);
}
elseif (!is_object($this->arguments['group'])) {
$this->arguments['group'] = MigrateGroup::getInstance($this->arguments['group']);
}
$this->sourceConnection = $this->arguments['source_connection'];
if (!empty($this->arguments['source_database'])) {
Database::addConnectionInfo($this->sourceConnection, 'default', $this->arguments['source_database']);
}
if (!empty($this->arguments['source_type'])) {
$this->sourceType = $this->arguments['source_type'];
}
$this->description = $this->arguments['description'];
if (!empty($this->arguments['dependencies'])) {
$this->dependencies = $this->arguments['dependencies'];
}
if (!empty($this->arguments['soft_dependencies'])) {
$this->softDependencies = $this->arguments['soft_dependencies'];
}
$this->sourceOptions = array(
'map_joinable' => FALSE,
'cache_counts' => TRUE,
'cache_key' => 'migrate_' . $this->machineName,
);
if (!empty($this->arguments['source_options'])) {
$this->sourceOptions = array_merge($this->sourceOptions, $this->arguments['source_options']);
}
if (!empty($this->arguments['format_mappings'])) {
$this->formatMappings = $this->arguments['format_mappings'];
}
else {
$this->formatMappings = $this->version
->getDefaultFormatMappings();
}
if (!empty($this->arguments['new_only'])) {
$this->newOnly = $this->arguments['new_only'];
}
if (!empty($this->arguments['map_connection'])) {
$this->mapConnection = $this->arguments['map_connection'];
}
}
/**
* @abstract
* The base source query for this migration.
*
* @return QueryConditionInterface
*/
protected abstract function query();
/**
* Field mapping callback: translate an incoming format ID (through D6) or
* machine name (D7+) to a D7 format machine name.
*
* @param $format
* @return string|array
*/
protected function mapFormat($format) {
if (!is_array($format)) {
$format = array(
$format,
);
}
$result = array();
foreach ($format as $format_value) {
if (isset($format_value) && isset($this->formatMappings[$format_value])) {
$result[] = $this->formatMappings[$format_value];
}
else {
$result[] = NULL;
}
}
// Only return an array if we have to
if (count($result) > 1) {
return $result;
}
else {
return reset($result);
}
}
/**
* Check to see if a given module is enabled in the source installation.
* @todo: move to DrupalVersion?
*
* @param $module
* Name of module to check.
* @return boolean
* 1 if it is enabled, 0 if not.
*/
protected function moduleExists($module) {
$exists = Database::getConnection('default', $this->sourceConnection)
->select('system', 's')
->fields('s', array(
'status',
))
->condition('name', $module)
->condition('type', 'module')
->execute()
->fetchField();
// Convert NULL to 0
if (!$exists) {
$exists = 0;
}
return $exists;
}
}
/**
* There should be an implementation of this abstract class, named
* DrupalVersion{version #}, for each Drupal version supported as a source. It
* will implement any functions needed by multiple version-specific classes
* (e.g., nodes as well as users).
*/
abstract class DrupalVersion {
/**
* Arguments for the containing migration. Primarily of interest for
* the source_connection.
*
* @var array
*/
protected $arguments;
/**
* An array of information on CCK/core fields.
*
* @var array
* key - field -name
* value - array of information:
* label: User-visible description of the field
* type: type of the field
* columns: array of database columns for the field
*/
protected $sourceFieldInfo = array();
public function getSourceFieldInfo() {
return $this->sourceFieldInfo;
}
/**
* The entity type (node, user, etc.)
*
* @var string
*/
protected $entityType;
/**
* The bundle (node type pre-D7) - article, blog, etc.
*
* @var string
*/
protected $bundle;
/**
* Pass the migration class arguments through to the version class.
*
* @param $arguments
*/
public function __construct($arguments) {
$this->arguments = $arguments;
}
/**
* @abstract
* Returns an array keyed by the source system's format identifier (integer ID
* or machine name), with the destination Drupal 7 machine name as the value.
*/
public abstract function getDefaultFormatMappings();
/**
* @abstract
* Given a source path (e.g., node/1234 or user/35), return the alias from
* the source database.
*
* @param $pattern
* @param $id
*/
public abstract function getPath($source);
/**
* @abstract
* Return the names and labels of all custom fields (CCK pre-D7, core fields
* D7 and later) attached to the given entity type and bundle.
*
* @param $entity_type
* Type of entity ('node', 'user', etc.) for which to retrieve field info.
* @param $bundle
* Bundle within the entity type (e.g., 'article', 'blog', etc.).
* @param $include_body
* Treat a node body as if it were a custom field (for supporting
* content_profile).
*
* @return array
* An array keyed by field name, with field labels as the values.
*/
public function getSourceFields($entity_type, $bundle, $include_body = FALSE) {
$this
->populateSourceFieldInfo($entity_type, $bundle);
$fields = array();
foreach ($this->sourceFieldInfo as $field_name => $info) {
$fields[$field_name] = $info['label'];
$i = 0;
if (isset($info['columns'])) {
foreach ($info['columns'] as $display_name => $column_name) {
// We skip the first column, which we've covered with the field name
// itself.
if ($i > 0) {
$fields[$display_name] = t('!label subfield', array(
'!label' => $info['label'],
));
}
$i++;
}
}
}
return $fields;
}
/**
* Get any core profile values associated with this user.
*
* @param $row
* @param $entity_id
*/
public function getProfileValues($row, $entity_id) {
$query = Database::getConnection('default', $this->arguments['source_connection'])
->select('profile_values', 'v')
->fields('v', array(
'value',
))
->condition('uid', $entity_id)
->condition('value', '', '<>');
$query
->innerJoin('profile_fields', 'f', 'v.fid=f.fid');
$query
->fields('f', array(
'name',
'type',
));
$result = $query
->execute();
foreach ($result as $data_row) {
switch ($data_row->type) {
case 'checkbox':
switch (trim(strtolower($data_row->value))) {
case 'n':
$data_row->value = 0;
break;
case 'y':
$data_row->value = 1;
break;
default:
break;
}
break;
case 'date':
// Dates may be serialized arrays or NULLs.
if (strpos($data_row->value, 'a:') === 0) {
$date_array = unserialize($data_row->value);
$data_row->value = $date_array['year'] . '-' . $date_array['month'] . '-' . $date_array['day'];
}
elseif (strpos($data_row->value, 'N;') === 0) {
$data_row->value = NULL;
}
break;
}
$row->{$data_row->name} = $data_row->value;
}
return $row;
}
/**
* @abstract
* Add CCK/core field values to the source row.
*
* @param $row
* @param $entity_id
*
* @return array
*/
public abstract function getSourceValues($row, $entity_id);
}
/**
* Implements hook_migrate_api().
*/
function migrate_d2d_migrate_api() {
$api = array(
'api' => 2,
);
return $api;
}
Functions
Name | Description |
---|---|
migrate_d2d_migrate_api | Implements hook_migrate_api(). |
Classes
Name | Description |
---|---|
DrupalMigration | @file Base classes for all Drupal-to-Drupal migration classes. |
DrupalVersion | There should be an implementation of this abstract class, named DrupalVersion{version #}, for each Drupal version supported as a source. It will implement any functions needed by multiple version-specific classes (e.g., nodes as well as users). |