|
@@ -8,20 +8,24 @@
|
|
/**
|
|
/**
|
|
* The base class for all import objects. This is where most of the smarts
|
|
* The base class for all import objects. This is where most of the smarts
|
|
* of the migrate module resides. Migrations are created by deriving from this
|
|
* of the migrate module resides. Migrations are created by deriving from this
|
|
- * class, and in the constructor (after calling parent::__construct()) initializing
|
|
|
|
- * at a minimum the name, description, source, and destination properties. The constructor
|
|
|
|
- * will also usually make several calls to addFieldMapping().
|
|
|
|
|
|
+ * class, and in the constructor (after calling parent::__construct())
|
|
|
|
+ * initializing at a minimum the name, description, source, and destination
|
|
|
|
+ * properties. The constructor will also usually make several calls to
|
|
|
|
+ * addFieldMapping().
|
|
*/
|
|
*/
|
|
abstract class Migration extends MigrationBase {
|
|
abstract class Migration extends MigrationBase {
|
|
|
|
+
|
|
/**
|
|
/**
|
|
* Source object for the migration, derived from MigrateSource.
|
|
* Source object for the migration, derived from MigrateSource.
|
|
*
|
|
*
|
|
* @var MigrateSource
|
|
* @var MigrateSource
|
|
*/
|
|
*/
|
|
protected $source;
|
|
protected $source;
|
|
|
|
+
|
|
public function getSource() {
|
|
public function getSource() {
|
|
return $this->source;
|
|
return $this->source;
|
|
}
|
|
}
|
|
|
|
+
|
|
public function setSource(MigrateSource $source) {
|
|
public function setSource(MigrateSource $source) {
|
|
$this->source = $source;
|
|
$this->source = $source;
|
|
}
|
|
}
|
|
@@ -32,9 +36,11 @@ abstract class Migration extends MigrationBase {
|
|
* @var MigrateDestination
|
|
* @var MigrateDestination
|
|
*/
|
|
*/
|
|
protected $destination;
|
|
protected $destination;
|
|
|
|
+
|
|
public function getDestination() {
|
|
public function getDestination() {
|
|
return $this->destination;
|
|
return $this->destination;
|
|
}
|
|
}
|
|
|
|
+
|
|
public function setDestination(MigrateDestination $destination) {
|
|
public function setDestination(MigrateDestination $destination) {
|
|
$this->destination = $destination;
|
|
$this->destination = $destination;
|
|
}
|
|
}
|
|
@@ -45,9 +51,11 @@ abstract class Migration extends MigrationBase {
|
|
* @var MigrateMap
|
|
* @var MigrateMap
|
|
*/
|
|
*/
|
|
protected $map;
|
|
protected $map;
|
|
|
|
+
|
|
public function getMap() {
|
|
public function getMap() {
|
|
return $this->map;
|
|
return $this->map;
|
|
}
|
|
}
|
|
|
|
+
|
|
public function setMap(MigrateMap $map) {
|
|
public function setMap(MigrateMap $map) {
|
|
$this->map = $map;
|
|
$this->map = $map;
|
|
}
|
|
}
|
|
@@ -63,11 +71,15 @@ abstract class Migration extends MigrationBase {
|
|
* @var int
|
|
* @var int
|
|
*/
|
|
*/
|
|
const SOURCE = 1;
|
|
const SOURCE = 1;
|
|
|
|
+
|
|
const DESTINATION = 2;
|
|
const DESTINATION = 2;
|
|
|
|
+
|
|
protected $systemOfRecord = Migration::SOURCE;
|
|
protected $systemOfRecord = Migration::SOURCE;
|
|
|
|
+
|
|
public function getSystemOfRecord() {
|
|
public function getSystemOfRecord() {
|
|
return $this->systemOfRecord;
|
|
return $this->systemOfRecord;
|
|
}
|
|
}
|
|
|
|
+
|
|
public function setSystemOfRecord($system_of_record) {
|
|
public function setSystemOfRecord($system_of_record) {
|
|
$this->systemOfRecord = $system_of_record;
|
|
$this->systemOfRecord = $system_of_record;
|
|
}
|
|
}
|
|
@@ -87,9 +99,11 @@ abstract class Migration extends MigrationBase {
|
|
* @var int
|
|
* @var int
|
|
*/
|
|
*/
|
|
protected $defaultRollbackAction = MigrateMap::ROLLBACK_DELETE;
|
|
protected $defaultRollbackAction = MigrateMap::ROLLBACK_DELETE;
|
|
|
|
+
|
|
public function getDefaultRollbackAction() {
|
|
public function getDefaultRollbackAction() {
|
|
return $this->defaultRollbackAction;
|
|
return $this->defaultRollbackAction;
|
|
}
|
|
}
|
|
|
|
+
|
|
public function setDefaultRollbackAction($rollback_action) {
|
|
public function setDefaultRollbackAction($rollback_action) {
|
|
$this->defaultRollbackAction = $rollback_action;
|
|
$this->defaultRollbackAction = $rollback_action;
|
|
}
|
|
}
|
|
@@ -107,7 +121,9 @@ abstract class Migration extends MigrationBase {
|
|
* @var array
|
|
* @var array
|
|
*/
|
|
*/
|
|
protected $storedFieldMappings = array();
|
|
protected $storedFieldMappings = array();
|
|
|
|
+
|
|
protected $storedFieldMappingsRetrieved = FALSE;
|
|
protected $storedFieldMappingsRetrieved = FALSE;
|
|
|
|
+
|
|
public function getStoredFieldMappings() {
|
|
public function getStoredFieldMappings() {
|
|
if (!$this->storedFieldMappingsRetrieved) {
|
|
if (!$this->storedFieldMappingsRetrieved) {
|
|
$this->loadFieldMappings();
|
|
$this->loadFieldMappings();
|
|
@@ -122,6 +138,7 @@ abstract class Migration extends MigrationBase {
|
|
* @var array
|
|
* @var array
|
|
*/
|
|
*/
|
|
protected $codedFieldMappings = array();
|
|
protected $codedFieldMappings = array();
|
|
|
|
+
|
|
public function getCodedFieldMappings() {
|
|
public function getCodedFieldMappings() {
|
|
return $this->codedFieldMappings;
|
|
return $this->codedFieldMappings;
|
|
}
|
|
}
|
|
@@ -133,10 +150,11 @@ abstract class Migration extends MigrationBase {
|
|
* @var array
|
|
* @var array
|
|
*/
|
|
*/
|
|
protected $allFieldMappings = array();
|
|
protected $allFieldMappings = array();
|
|
|
|
+
|
|
public function getFieldMappings() {
|
|
public function getFieldMappings() {
|
|
if (empty($allFieldMappings)) {
|
|
if (empty($allFieldMappings)) {
|
|
$this->allFieldMappings = array_merge($this->getCodedFieldMappings(),
|
|
$this->allFieldMappings = array_merge($this->getCodedFieldMappings(),
|
|
- $this->getStoredFieldMappings());
|
|
|
|
|
|
+ $this->getStoredFieldMappings());
|
|
// If there are multiple mappings of a given source field to no
|
|
// If there are multiple mappings of a given source field to no
|
|
// destination field, keep only the last (so the UI can override a source
|
|
// destination field, keep only the last (so the UI can override a source
|
|
// field DNM that was defined in code).
|
|
// field DNM that was defined in code).
|
|
@@ -193,21 +211,25 @@ abstract class Migration extends MigrationBase {
|
|
* @var array
|
|
* @var array
|
|
*/
|
|
*/
|
|
protected $highwaterField = array();
|
|
protected $highwaterField = array();
|
|
|
|
+
|
|
public function getHighwaterField() {
|
|
public function getHighwaterField() {
|
|
return $this->highwaterField;
|
|
return $this->highwaterField;
|
|
}
|
|
}
|
|
|
|
+
|
|
public function setHighwaterField(array $highwater_field) {
|
|
public function setHighwaterField(array $highwater_field) {
|
|
$this->highwaterField = $highwater_field;
|
|
$this->highwaterField = $highwater_field;
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
/**
|
|
* The object currently being constructed
|
|
* The object currently being constructed
|
|
|
|
+ *
|
|
* @var stdClass
|
|
* @var stdClass
|
|
*/
|
|
*/
|
|
protected $destinationValues;
|
|
protected $destinationValues;
|
|
|
|
|
|
/**
|
|
/**
|
|
* The current data row retrieved from the source.
|
|
* The current data row retrieved from the source.
|
|
|
|
+ *
|
|
* @var stdClass
|
|
* @var stdClass
|
|
*/
|
|
*/
|
|
protected $sourceValues;
|
|
protected $sourceValues;
|
|
@@ -238,7 +260,7 @@ abstract class Migration extends MigrationBase {
|
|
* @param array $arguments
|
|
* @param array $arguments
|
|
*/
|
|
*/
|
|
static public function registerMigration($class_name, $machine_name = NULL,
|
|
static public function registerMigration($class_name, $machine_name = NULL,
|
|
- array $arguments = array()) {
|
|
|
|
|
|
+ array $arguments = array()) {
|
|
// Record any field mappings provided via arguments.
|
|
// Record any field mappings provided via arguments.
|
|
if (isset($arguments['field_mappings'])) {
|
|
if (isset($arguments['field_mappings'])) {
|
|
self::saveFieldMappings($machine_name, $arguments['field_mappings']);
|
|
self::saveFieldMappings($machine_name, $arguments['field_mappings']);
|
|
@@ -270,14 +292,13 @@ abstract class Migration extends MigrationBase {
|
|
|
|
|
|
// Remove stored field mappings for this migration
|
|
// Remove stored field mappings for this migration
|
|
$rows_deleted = db_delete('migrate_field_mapping')
|
|
$rows_deleted = db_delete('migrate_field_mapping')
|
|
- ->condition('machine_name', $machine_name)
|
|
|
|
- ->execute();
|
|
|
|
|
|
+ ->condition('machine_name', $machine_name)
|
|
|
|
+ ->execute();
|
|
|
|
|
|
// Call the parent deregistration (which clears migrate_status) last, the
|
|
// Call the parent deregistration (which clears migrate_status) last, the
|
|
// above will reference it.
|
|
// above will reference it.
|
|
parent::deregisterMigration($machine_name);
|
|
parent::deregisterMigration($machine_name);
|
|
- }
|
|
|
|
- catch (Exception $e) {
|
|
|
|
|
|
+ } catch (Exception $e) {
|
|
// Fail silently if it's already gone
|
|
// Fail silently if it's already gone
|
|
}
|
|
}
|
|
}
|
|
}
|
|
@@ -298,11 +319,11 @@ abstract class Migration extends MigrationBase {
|
|
$source_field = $field_mapping->getSourceField();
|
|
$source_field = $field_mapping->getSourceField();
|
|
db_insert('migrate_field_mapping')
|
|
db_insert('migrate_field_mapping')
|
|
->fields(array(
|
|
->fields(array(
|
|
- 'machine_name' => $machine_name,
|
|
|
|
- 'destination_field' => is_null($destination_field) ? '' : $destination_field,
|
|
|
|
- 'source_field' => is_null($source_field) ? '' : $source_field,
|
|
|
|
- 'options' => serialize($field_mapping)
|
|
|
|
- ))
|
|
|
|
|
|
+ 'machine_name' => $machine_name,
|
|
|
|
+ 'destination_field' => is_null($destination_field) ? '' : $destination_field,
|
|
|
|
+ 'source_field' => is_null($source_field) ? '' : $source_field,
|
|
|
|
+ 'options' => serialize($field_mapping),
|
|
|
|
+ ))
|
|
->execute();
|
|
->execute();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
@@ -312,9 +333,9 @@ abstract class Migration extends MigrationBase {
|
|
*/
|
|
*/
|
|
public function loadFieldMappings() {
|
|
public function loadFieldMappings() {
|
|
$result = db_select('migrate_field_mapping', 'mfm')
|
|
$result = db_select('migrate_field_mapping', 'mfm')
|
|
- ->fields('mfm', array('destination_field', 'source_field', 'options'))
|
|
|
|
- ->condition('machine_name', $this->machineName)
|
|
|
|
- ->execute();
|
|
|
|
|
|
+ ->fields('mfm', array('destination_field', 'source_field', 'options'))
|
|
|
|
+ ->condition('machine_name', $this->machineName)
|
|
|
|
+ ->execute();
|
|
foreach ($result as $row) {
|
|
foreach ($result as $row) {
|
|
$field_mapping = unserialize($row->options);
|
|
$field_mapping = unserialize($row->options);
|
|
$field_mapping->setMappingSource(MigrateFieldMapping::MAPPING_SOURCE_DB);
|
|
$field_mapping->setMappingSource(MigrateFieldMapping::MAPPING_SOURCE_DB);
|
|
@@ -346,11 +367,14 @@ abstract class Migration extends MigrationBase {
|
|
$warn_on_override = TRUE) {
|
|
$warn_on_override = TRUE) {
|
|
// Warn of duplicate mappings
|
|
// Warn of duplicate mappings
|
|
if ($warn_on_override && !is_null($destination_field) &&
|
|
if ($warn_on_override && !is_null($destination_field) &&
|
|
- isset($this->codedFieldMappings[$destination_field])) {
|
|
|
|
|
|
+ isset($this->codedFieldMappings[$destination_field])) {
|
|
self::displayMessage(
|
|
self::displayMessage(
|
|
t('!name addFieldMapping: !dest was previously mapped from !source, overridden',
|
|
t('!name addFieldMapping: !dest was previously mapped from !source, overridden',
|
|
- array('!name' => $this->machineName, '!dest' => $destination_field,
|
|
|
|
- '!source' => $this->codedFieldMappings[$destination_field]->getSourceField())),
|
|
|
|
|
|
+ array(
|
|
|
|
+ '!name' => $this->machineName,
|
|
|
|
+ '!dest' => $destination_field,
|
|
|
|
+ '!source' => $this->codedFieldMappings[$destination_field]->getSourceField(),
|
|
|
|
+ )),
|
|
'warning');
|
|
'warning');
|
|
}
|
|
}
|
|
$mapping = new MigrateFieldMapping($destination_field, $source_field);
|
|
$mapping = new MigrateFieldMapping($destination_field, $source_field);
|
|
@@ -413,7 +437,7 @@ abstract class Migration extends MigrationBase {
|
|
}
|
|
}
|
|
foreach ($fields as $field) {
|
|
foreach ($fields as $field) {
|
|
$this->addFieldMapping($field, NULL, $warn_on_override)
|
|
$this->addFieldMapping($field, NULL, $warn_on_override)
|
|
- ->issueGroup($issue_group);
|
|
|
|
|
|
+ ->issueGroup($issue_group);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
@@ -433,7 +457,7 @@ abstract class Migration extends MigrationBase {
|
|
}
|
|
}
|
|
foreach ($fields as $field) {
|
|
foreach ($fields as $field) {
|
|
$this->addFieldMapping(NULL, $field, $warn_on_override)
|
|
$this->addFieldMapping(NULL, $field, $warn_on_override)
|
|
- ->issueGroup($issue_group);
|
|
|
|
|
|
+ ->issueGroup($issue_group);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
@@ -464,7 +488,7 @@ abstract class Migration extends MigrationBase {
|
|
|
|
|
|
// Do some standard setup
|
|
// Do some standard setup
|
|
if (isset($this->options['feedback']) && isset($this->options['feedback']['value']) &&
|
|
if (isset($this->options['feedback']) && isset($this->options['feedback']['value']) &&
|
|
- isset($this->options['feedback']['unit'])) {
|
|
|
|
|
|
+ isset($this->options['feedback']['unit'])) {
|
|
$this->feedback = $this->options['feedback']['value'];
|
|
$this->feedback = $this->options['feedback']['value'];
|
|
$this->feedback_unit = $this->options['feedback']['unit'];
|
|
$this->feedback_unit = $this->options['feedback']['unit'];
|
|
if ($this->feedback_unit == 'item') {
|
|
if ($this->feedback_unit == 'item') {
|
|
@@ -477,7 +501,7 @@ abstract class Migration extends MigrationBase {
|
|
$this->lastfeedback = $this->starttime;
|
|
$this->lastfeedback = $this->starttime;
|
|
|
|
|
|
$this->total_processed = $this->total_successes =
|
|
$this->total_processed = $this->total_successes =
|
|
- $this->processed_since_feedback = $this->successes_since_feedback = 0;
|
|
|
|
|
|
+ $this->processed_since_feedback = $this->successes_since_feedback = 0;
|
|
|
|
|
|
// Call pre-process methods
|
|
// Call pre-process methods
|
|
if ($this->status == Migration::STATUS_IMPORTING) {
|
|
if ($this->status == Migration::STATUS_IMPORTING) {
|
|
@@ -572,7 +596,7 @@ abstract class Migration extends MigrationBase {
|
|
// Note that bulk rollback is only supported for single-column keys
|
|
// Note that bulk rollback is only supported for single-column keys
|
|
$sourceids[] = $current_source_key;
|
|
$sourceids[] = $current_source_key;
|
|
if (!empty($destination_key->destid1)) {
|
|
if (!empty($destination_key->destid1)) {
|
|
- $map_row = $this->map->getRowByDestination((array)$destination_key);
|
|
|
|
|
|
+ $map_row = $this->map->getRowByDestination((array) $destination_key);
|
|
if ($map_row['rollback_action'] == MigrateMap::ROLLBACK_DELETE) {
|
|
if ($map_row['rollback_action'] == MigrateMap::ROLLBACK_DELETE) {
|
|
$destids[] = $destination_key->destid1;
|
|
$destids[] = $destination_key->destid1;
|
|
}
|
|
}
|
|
@@ -594,8 +618,7 @@ abstract class Migration extends MigrationBase {
|
|
migrate_instrument_stop('rollback map/message update');
|
|
migrate_instrument_stop('rollback map/message update');
|
|
$this->total_successes += $batch_count;
|
|
$this->total_successes += $batch_count;
|
|
$this->successes_since_feedback += $batch_count;
|
|
$this->successes_since_feedback += $batch_count;
|
|
- }
|
|
|
|
- catch (Exception $e) {
|
|
|
|
|
|
+ } catch (Exception $e) {
|
|
$this->handleException($e, FALSE);
|
|
$this->handleException($e, FALSE);
|
|
migrate_instrument_stop('bulkRollback');
|
|
migrate_instrument_stop('bulkRollback');
|
|
migrate_instrument_stop('rollback map/message update');
|
|
migrate_instrument_stop('rollback map/message update');
|
|
@@ -656,10 +679,10 @@ abstract class Migration extends MigrationBase {
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if (!$skip) {
|
|
if (!$skip) {
|
|
- $map_row = $this->map->getRowByDestination((array)$destination_key);
|
|
|
|
|
|
+ $map_row = $this->map->getRowByDestination((array) $destination_key);
|
|
if ($map_row['rollback_action'] == MigrateMap::ROLLBACK_DELETE) {
|
|
if ($map_row['rollback_action'] == MigrateMap::ROLLBACK_DELETE) {
|
|
migrate_instrument_start('destination rollback');
|
|
migrate_instrument_start('destination rollback');
|
|
- $this->destination->rollback((array)$destination_key);
|
|
|
|
|
|
+ $this->destination->rollback((array) $destination_key);
|
|
migrate_instrument_stop('destination rollback');
|
|
migrate_instrument_stop('destination rollback');
|
|
}
|
|
}
|
|
}
|
|
}
|
|
@@ -670,8 +693,7 @@ abstract class Migration extends MigrationBase {
|
|
migrate_instrument_stop('rollback map/message update');
|
|
migrate_instrument_stop('rollback map/message update');
|
|
$this->total_successes++;
|
|
$this->total_successes++;
|
|
$this->successes_since_feedback++;
|
|
$this->successes_since_feedback++;
|
|
- }
|
|
|
|
- catch (Exception $e) {
|
|
|
|
|
|
+ } catch (Exception $e) {
|
|
// TODO: At least count failures
|
|
// TODO: At least count failures
|
|
continue;
|
|
continue;
|
|
}
|
|
}
|
|
@@ -701,11 +723,15 @@ abstract class Migration extends MigrationBase {
|
|
|
|
|
|
try {
|
|
try {
|
|
$this->source->rewind();
|
|
$this->source->rewind();
|
|
- }
|
|
|
|
- catch (Exception $e) {
|
|
|
|
|
|
+ } catch (Exception $e) {
|
|
self::displayMessage(
|
|
self::displayMessage(
|
|
- t('Migration failed with source plugin exception: %e, in %file:%line',
|
|
|
|
- array('%e' => $e->getMessage(), '%file' => $e->getFile(), '%line' => $e->getLine())));
|
|
|
|
|
|
+ t('Migration for %class failed with source plugin exception: %e, in %file:%line',
|
|
|
|
+ array(
|
|
|
|
+ '%class' => get_class($this),
|
|
|
|
+ '%e' => $e->getMessage(),
|
|
|
|
+ '%file' => $e->getFile(),
|
|
|
|
+ '%line' => $e->getLine(),
|
|
|
|
+ )));
|
|
return MigrationBase::RESULT_FAILED;
|
|
return MigrationBase::RESULT_FAILED;
|
|
}
|
|
}
|
|
while ($this->source->valid()) {
|
|
while ($this->source->valid()) {
|
|
@@ -732,24 +758,22 @@ abstract class Migration extends MigrationBase {
|
|
else {
|
|
else {
|
|
$this->map->saveIDMapping($this->sourceValues, array(),
|
|
$this->map->saveIDMapping($this->sourceValues, array(),
|
|
MigrateMap::STATUS_FAILED, $this->rollbackAction,
|
|
MigrateMap::STATUS_FAILED, $this->rollbackAction,
|
|
- $data_row->migrate_map_hash);
|
|
|
|
|
|
+ NULL);
|
|
if ($this->map->messageCount() == 0) {
|
|
if ($this->map->messageCount() == 0) {
|
|
$message = t('New object was not saved, no error provided');
|
|
$message = t('New object was not saved, no error provided');
|
|
$this->saveMessage($message);
|
|
$this->saveMessage($message);
|
|
self::displayMessage($message);
|
|
self::displayMessage($message);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
- }
|
|
|
|
- catch (MigrateException $e) {
|
|
|
|
|
|
+ } catch (MigrateException $e) {
|
|
$this->map->saveIDMapping($this->sourceValues, array(),
|
|
$this->map->saveIDMapping($this->sourceValues, array(),
|
|
$e->getStatus(), $this->rollbackAction, $data_row->migrate_map_hash);
|
|
$e->getStatus(), $this->rollbackAction, $data_row->migrate_map_hash);
|
|
$this->saveMessage($e->getMessage(), $e->getLevel());
|
|
$this->saveMessage($e->getMessage(), $e->getLevel());
|
|
self::displayMessage($e->getMessage());
|
|
self::displayMessage($e->getMessage());
|
|
- }
|
|
|
|
- catch (Exception $e) {
|
|
|
|
|
|
+ } catch (Exception $e) {
|
|
$this->map->saveIDMapping($this->sourceValues, array(),
|
|
$this->map->saveIDMapping($this->sourceValues, array(),
|
|
MigrateMap::STATUS_FAILED, $this->rollbackAction,
|
|
MigrateMap::STATUS_FAILED, $this->rollbackAction,
|
|
- $data_row->migrate_map_hash);
|
|
|
|
|
|
+ NULL);
|
|
$this->handleException($e);
|
|
$this->handleException($e);
|
|
}
|
|
}
|
|
$this->total_processed++;
|
|
$this->total_processed++;
|
|
@@ -779,11 +803,15 @@ abstract class Migration extends MigrationBase {
|
|
}
|
|
}
|
|
try {
|
|
try {
|
|
$this->source->next();
|
|
$this->source->next();
|
|
- }
|
|
|
|
- catch (Exception $e) {
|
|
|
|
|
|
+ } catch (Exception $e) {
|
|
self::displayMessage(
|
|
self::displayMessage(
|
|
- t('Migration failed with source plugin exception: %e, in %file:%line',
|
|
|
|
- array('%e' => $e->getMessage(), '%file' => $e->getFile(), '%line' => $e->getLine())));
|
|
|
|
|
|
+ t('Migration for %class failed with source plugin exception: %e, in %file:%line',
|
|
|
|
+ array(
|
|
|
|
+ '%class' => get_class($this),
|
|
|
|
+ '%e' => $e->getMessage(),
|
|
|
|
+ '%file' => $e->getFile(),
|
|
|
|
+ '%line' => $e->getLine(),
|
|
|
|
+ )));
|
|
return MigrationBase::RESULT_FAILED;
|
|
return MigrationBase::RESULT_FAILED;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
@@ -805,8 +833,7 @@ abstract class Migration extends MigrationBase {
|
|
self::$currentMigration = $this;
|
|
self::$currentMigration = $this;
|
|
try {
|
|
try {
|
|
$this->source->rewind();
|
|
$this->source->rewind();
|
|
- }
|
|
|
|
- catch (Exception $e) {
|
|
|
|
|
|
+ } catch (Exception $e) {
|
|
self::displayMessage(
|
|
self::displayMessage(
|
|
t('Migration analysis failed with source plugin exception: !e',
|
|
t('Migration analysis failed with source plugin exception: !e',
|
|
array('!e' => $e->getMessage())));
|
|
array('!e' => $e->getMessage())));
|
|
@@ -901,8 +928,7 @@ abstract class Migration extends MigrationBase {
|
|
|
|
|
|
try {
|
|
try {
|
|
$this->source->next();
|
|
$this->source->next();
|
|
- }
|
|
|
|
- catch (Exception $e) {
|
|
|
|
|
|
+ } catch (Exception $e) {
|
|
self::displayMessage(
|
|
self::displayMessage(
|
|
t('Migration analysis failed with source plugin exception: !e. Partial results follow:',
|
|
t('Migration analysis failed with source plugin exception: !e. Partial results follow:',
|
|
array('!e' => $e->getMessage())));
|
|
array('!e' => $e->getMessage())));
|
|
@@ -940,17 +966,18 @@ abstract class Migration extends MigrationBase {
|
|
public function prepareKey($source_key, $row) {
|
|
public function prepareKey($source_key, $row) {
|
|
$key = array();
|
|
$key = array();
|
|
foreach ($source_key as $field_name => $field_schema) {
|
|
foreach ($source_key as $field_name => $field_schema) {
|
|
- $key[$field_name] = $row->$field_name;
|
|
|
|
|
|
+ $key[$field_name] = $row->{$field_name};
|
|
}
|
|
}
|
|
return $key;
|
|
return $key;
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
/**
|
|
- * Default implementation of prepareRow(). This method is called from the source
|
|
|
|
- * plugin upon first pulling the raw data from the source.
|
|
|
|
|
|
+ * Default implementation of prepareRow(). This method is called from the
|
|
|
|
+ * source plugin upon first pulling the raw data from the source.
|
|
*
|
|
*
|
|
* @param $row
|
|
* @param $row
|
|
* Object containing raw source data.
|
|
* Object containing raw source data.
|
|
|
|
+ *
|
|
* @return bool
|
|
* @return bool
|
|
* TRUE to process this row, FALSE to have the source skip it.
|
|
* TRUE to process this row, FALSE to have the source skip it.
|
|
*/
|
|
*/
|
|
@@ -971,8 +998,7 @@ abstract class Migration extends MigrationBase {
|
|
public function sourceCount($refresh = FALSE) {
|
|
public function sourceCount($refresh = FALSE) {
|
|
try {
|
|
try {
|
|
$count = $this->source->count($refresh);
|
|
$count = $this->source->count($refresh);
|
|
- }
|
|
|
|
- catch (Exception $e) {
|
|
|
|
|
|
+ } catch (Exception $e) {
|
|
$count = t('N/A');
|
|
$count = t('N/A');
|
|
self::displayMessage($e->getMessage());
|
|
self::displayMessage($e->getMessage());
|
|
}
|
|
}
|
|
@@ -981,14 +1007,14 @@ abstract class Migration extends MigrationBase {
|
|
|
|
|
|
/**
|
|
/**
|
|
* Get the number of source records processed.
|
|
* Get the number of source records processed.
|
|
|
|
+ *
|
|
* @return int
|
|
* @return int
|
|
* Number of processed records.
|
|
* Number of processed records.
|
|
*/
|
|
*/
|
|
public function processedCount() {
|
|
public function processedCount() {
|
|
try {
|
|
try {
|
|
$count = $this->map->processedCount();
|
|
$count = $this->map->processedCount();
|
|
- }
|
|
|
|
- catch (Exception $e) {
|
|
|
|
|
|
+ } catch (Exception $e) {
|
|
$count = t('N/A');
|
|
$count = t('N/A');
|
|
self::displayMessage($e->getMessage());
|
|
self::displayMessage($e->getMessage());
|
|
}
|
|
}
|
|
@@ -997,14 +1023,14 @@ abstract class Migration extends MigrationBase {
|
|
|
|
|
|
/**
|
|
/**
|
|
* Get the number of records successfully imported.
|
|
* Get the number of records successfully imported.
|
|
|
|
+ *
|
|
* @return int
|
|
* @return int
|
|
* Number of imported records.
|
|
* Number of imported records.
|
|
*/
|
|
*/
|
|
public function importedCount() {
|
|
public function importedCount() {
|
|
try {
|
|
try {
|
|
$count = $this->map->importedCount();
|
|
$count = $this->map->importedCount();
|
|
- }
|
|
|
|
- catch (Exception $e) {
|
|
|
|
|
|
+ } catch (Exception $e) {
|
|
$count = t('N/A');
|
|
$count = t('N/A');
|
|
self::displayMessage($e->getMessage());
|
|
self::displayMessage($e->getMessage());
|
|
}
|
|
}
|
|
@@ -1013,13 +1039,13 @@ abstract class Migration extends MigrationBase {
|
|
|
|
|
|
/**
|
|
/**
|
|
* Get the number of records marked as needing update.
|
|
* Get the number of records marked as needing update.
|
|
|
|
+ *
|
|
* @return int
|
|
* @return int
|
|
*/
|
|
*/
|
|
public function updateCount() {
|
|
public function updateCount() {
|
|
try {
|
|
try {
|
|
$count = $this->map->updateCount();
|
|
$count = $this->map->updateCount();
|
|
- }
|
|
|
|
- catch (Exception $e) {
|
|
|
|
|
|
+ } catch (Exception $e) {
|
|
$count = t('N/A');
|
|
$count = t('N/A');
|
|
self::displayMessage($e->getMessage());
|
|
self::displayMessage($e->getMessage());
|
|
}
|
|
}
|
|
@@ -1072,15 +1098,17 @@ abstract class Migration extends MigrationBase {
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
/**
|
|
- * Outputs a progress message, reflecting the current status of a migration process.
|
|
|
|
|
|
+ * Outputs a progress message, reflecting the current status of a migration
|
|
|
|
+ * process.
|
|
*
|
|
*
|
|
* @param int $result
|
|
* @param int $result
|
|
- * Status of the process, represented by one of the Migration::RESULT_* constants.
|
|
|
|
|
|
+ * Status of the process, represented by one of the Migration::RESULT_*
|
|
|
|
+ * constants.
|
|
*/
|
|
*/
|
|
protected function progressMessage($result) {
|
|
protected function progressMessage($result) {
|
|
$time = microtime(TRUE) - $this->lastfeedback;
|
|
$time = microtime(TRUE) - $this->lastfeedback;
|
|
if ($time > 0) {
|
|
if ($time > 0) {
|
|
- $perminute = round(60*$this->processed_since_feedback/$time);
|
|
|
|
|
|
+ $perminute = round(60 * $this->processed_since_feedback / $time);
|
|
$time = round($time, 1);
|
|
$time = round($time, 1);
|
|
}
|
|
}
|
|
else {
|
|
else {
|
|
@@ -1129,31 +1157,37 @@ abstract class Migration extends MigrationBase {
|
|
}
|
|
}
|
|
$numitems = $this->processed_since_feedback + $this->source->getIgnored();
|
|
$numitems = $this->processed_since_feedback + $this->source->getIgnored();
|
|
$message = t($basetext,
|
|
$message = t($basetext,
|
|
- array('!numitems' => $numitems,
|
|
|
|
- '!successes' => $this->successes_since_feedback,
|
|
|
|
- '!failed' => $this->processed_since_feedback - $this->successes_since_feedback,
|
|
|
|
- '!created' => $this->destination->getCreated(),
|
|
|
|
- '!updated' => $this->destination->getUpdated(),
|
|
|
|
- '!ignored' => $this->source->getIgnored(),
|
|
|
|
- '!time' => $time,
|
|
|
|
- '!perminute' => $perminute,
|
|
|
|
- '!name' => $this->machineName));
|
|
|
|
|
|
+ array(
|
|
|
|
+ '!numitems' => $numitems,
|
|
|
|
+ '!successes' => $this->successes_since_feedback,
|
|
|
|
+ '!failed' => $this->processed_since_feedback - $this->successes_since_feedback,
|
|
|
|
+ '!created' => $this->destination->getCreated(),
|
|
|
|
+ '!updated' => $this->destination->getUpdated(),
|
|
|
|
+ '!ignored' => $this->source->getIgnored(),
|
|
|
|
+ '!time' => $time,
|
|
|
|
+ '!perminute' => $perminute,
|
|
|
|
+ '!name' => $this->machineName,
|
|
|
|
+ ));
|
|
self::displayMessage($message, $type);
|
|
self::displayMessage($message, $type);
|
|
|
|
|
|
// Report on lookup_cache hit rate. Only visible at 'debug' level.
|
|
// Report on lookup_cache hit rate. Only visible at 'debug' level.
|
|
if ($result != Migration::RESULT_INCOMPLETE && !empty($this->counts['lookup_cache'])) {
|
|
if ($result != Migration::RESULT_INCOMPLETE && !empty($this->counts['lookup_cache'])) {
|
|
foreach ($this->counts['lookup_cache'] as $name => $tallies) {
|
|
foreach ($this->counts['lookup_cache'] as $name => $tallies) {
|
|
- $tallies += array('hit' => 0, 'miss_hit' => 0, 'miss_miss' => 0); // Set defaults to avoid NOTICE.
|
|
|
|
- $sum = $tallies['hit']+$tallies['miss_hit']+$tallies['miss_miss'];
|
|
|
|
|
|
+ $tallies += array(
|
|
|
|
+ 'hit' => 0,
|
|
|
|
+ 'miss_hit' => 0,
|
|
|
|
+ 'miss_miss' => 0,
|
|
|
|
+ ); // Set defaults to avoid NOTICE.
|
|
|
|
+ $sum = $tallies['hit'] + $tallies['miss_hit'] + $tallies['miss_miss'];
|
|
self::displayMessage(
|
|
self::displayMessage(
|
|
t('Lookup cache: !mn SM=!name !hit hit, !miss_hit miss_hit, !miss_miss miss_miss (!total total).', array(
|
|
t('Lookup cache: !mn SM=!name !hit hit, !miss_hit miss_hit, !miss_miss miss_miss (!total total).', array(
|
|
- '!mn' => $this->machineName,
|
|
|
|
- '!name' => $name,
|
|
|
|
- '!hit' => round((100*$tallies['hit'])/$sum) . '%',
|
|
|
|
- '!miss_hit' => round((100*$tallies['miss_hit'])/$sum) . '%',
|
|
|
|
- '!miss_miss' => round((100*$tallies['miss_miss'])/$sum) . '%',
|
|
|
|
- '!total' => $sum
|
|
|
|
- )), 'debug');
|
|
|
|
|
|
+ '!mn' => $this->machineName,
|
|
|
|
+ '!name' => $name,
|
|
|
|
+ '!hit' => round((100 * $tallies['hit']) / $sum) . '%',
|
|
|
|
+ '!miss_hit' => round((100 * $tallies['miss_hit']) / $sum) . '%',
|
|
|
|
+ '!miss_miss' => round((100 * $tallies['miss_miss']) / $sum) . '%',
|
|
|
|
+ '!total' => $sum,
|
|
|
|
+ )), 'debug');
|
|
}
|
|
}
|
|
$this->counts['lookup_cache'] = array();
|
|
$this->counts['lookup_cache'] = array();
|
|
}
|
|
}
|
|
@@ -1182,7 +1216,7 @@ abstract class Migration extends MigrationBase {
|
|
// If feedback is requested, produce a progress message at the proper time
|
|
// If feedback is requested, produce a progress message at the proper time
|
|
if (isset($this->feedback)) {
|
|
if (isset($this->feedback)) {
|
|
if (($this->feedback_unit == 'seconds' && time() - $this->lastfeedback >= $this->feedback) ||
|
|
if (($this->feedback_unit == 'seconds' && time() - $this->lastfeedback >= $this->feedback) ||
|
|
- ($this->feedback_unit == 'items' && $this->processed_since_feedback >= $this->feedback)) {
|
|
|
|
|
|
+ ($this->feedback_unit == 'items' && $this->processed_since_feedback >= $this->feedback)) {
|
|
$this->progressMessage(MigrationBase::RESULT_INCOMPLETE);
|
|
$this->progressMessage(MigrationBase::RESULT_INCOMPLETE);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
@@ -1214,7 +1248,7 @@ abstract class Migration extends MigrationBase {
|
|
// If there's a source mapping, and a source value in the data row, copy
|
|
// If there's a source mapping, and a source value in the data row, copy
|
|
// to the destination
|
|
// to the destination
|
|
if ($source && isset($this->sourceValues->{$source})) {
|
|
if ($source && isset($this->sourceValues->{$source})) {
|
|
- $destination_values = $this->sourceValues->$source;
|
|
|
|
|
|
+ $destination_values = $this->sourceValues->{$source};
|
|
}
|
|
}
|
|
// Otherwise, apply the default value (if any)
|
|
// Otherwise, apply the default value (if any)
|
|
elseif (!is_null($default)) {
|
|
elseif (!is_null($default)) {
|
|
@@ -1225,7 +1259,25 @@ abstract class Migration extends MigrationBase {
|
|
// will be populated as an array exploded from the source value
|
|
// will be populated as an array exploded from the source value
|
|
$separator = $mapping->getSeparator();
|
|
$separator = $mapping->getSeparator();
|
|
if ($separator && isset($destination_values)) {
|
|
if ($separator && isset($destination_values)) {
|
|
- $destination_values = explode($separator, $destination_values);
|
|
|
|
|
|
+ if (is_array($separator)) {
|
|
|
|
+ if (isset($separator['group separator'])) {
|
|
|
|
+ $destination_values = explode($separator['group separator'], $destination_values);
|
|
|
|
+ }
|
|
|
|
+ else {
|
|
|
|
+ $destination_values = array($destination_values);
|
|
|
|
+ }
|
|
|
|
+ foreach ($destination_values as $group => $value) {
|
|
|
|
+ if (isset($separator['key separator'])) {
|
|
|
|
+ $destination_values[$group] = explode($separator['key separator'], $value);
|
|
|
|
+ }
|
|
|
|
+ else {
|
|
|
|
+ $destination_values[$group] = array($value);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ else {
|
|
|
|
+ $destination_values = explode($separator, $destination_values);
|
|
|
|
+ }
|
|
}
|
|
}
|
|
|
|
|
|
// If a source migration is supplied, use the current value for this field
|
|
// If a source migration is supplied, use the current value for this field
|
|
@@ -1239,7 +1291,7 @@ abstract class Migration extends MigrationBase {
|
|
$callbacks = $mapping->getCallbacks();
|
|
$callbacks = $mapping->getCallbacks();
|
|
foreach ($callbacks as $callback) {
|
|
foreach ($callbacks as $callback) {
|
|
if (isset($destination_values)) {
|
|
if (isset($destination_values)) {
|
|
- $destination_values = call_user_func($callback, $destination_values);
|
|
|
|
|
|
+ $destination_values = call_user_func_array($callback['callback'], array_merge(array($destination_values), $callback['params']));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
@@ -1262,7 +1314,7 @@ abstract class Migration extends MigrationBase {
|
|
$destination_values['arguments'] = array();
|
|
$destination_values['arguments'] = array();
|
|
foreach ($arguments as $argname => $destarg) {
|
|
foreach ($arguments as $argname => $destarg) {
|
|
if (is_array($destarg) && isset($destarg['source_field']) && property_exists($this->sourceValues, $destarg['source_field'])) {
|
|
if (is_array($destarg) && isset($destarg['source_field']) && property_exists($this->sourceValues, $destarg['source_field'])) {
|
|
- $destination_values['arguments'][$argname] = $this->sourceValues->$destarg['source_field'];
|
|
|
|
|
|
+ $destination_values['arguments'][$argname] = $this->sourceValues->{$destarg['source_field']};
|
|
}
|
|
}
|
|
elseif (is_array($destarg) && isset($destarg['default_value'])) {
|
|
elseif (is_array($destarg) && isset($destarg['default_value'])) {
|
|
$destination_values['arguments'][$argname] = $destarg['default_value'];
|
|
$destination_values['arguments'][$argname] = $destarg['default_value'];
|
|
@@ -1281,47 +1333,47 @@ abstract class Migration extends MigrationBase {
|
|
// last one.
|
|
// last one.
|
|
$destination_count = count($destination);
|
|
$destination_count = count($destination);
|
|
$destination_field = $destination[0];
|
|
$destination_field = $destination[0];
|
|
- if ($destination_count == 2) {
|
|
|
|
|
|
+ if ($destination_count == 2) {
|
|
$subfield = $destination[1];
|
|
$subfield = $destination[1];
|
|
// We're processing the subfield before the primary value, initialize it
|
|
// We're processing the subfield before the primary value, initialize it
|
|
if (!property_exists($this->destinationValues, $destination_field)) {
|
|
if (!property_exists($this->destinationValues, $destination_field)) {
|
|
- $this->destinationValues->$destination_field = array();
|
|
|
|
|
|
+ $this->destinationValues->{$destination_field} = array();
|
|
}
|
|
}
|
|
// We have a value, and need to convert to an array so we can add
|
|
// We have a value, and need to convert to an array so we can add
|
|
// arguments.
|
|
// arguments.
|
|
- elseif (!is_array($this->destinationValues->$destination_field)) {
|
|
|
|
- $this->destinationValues->$destination_field = array($this->destinationValues->$destination_field);
|
|
|
|
|
|
+ elseif (!is_array($this->destinationValues->{$destination_field})) {
|
|
|
|
+ $this->destinationValues->{$destination_field} = array($this->destinationValues->{$destination_field});
|
|
}
|
|
}
|
|
// Add the subfield value to the arguments array.
|
|
// Add the subfield value to the arguments array.
|
|
$this->destinationValues->{$destination_field}['arguments'][$subfield] = $destination_values;
|
|
$this->destinationValues->{$destination_field}['arguments'][$subfield] = $destination_values;
|
|
}
|
|
}
|
|
elseif ($destination_count == 3) {
|
|
elseif ($destination_count == 3) {
|
|
- $subfield2 = $destination[2];
|
|
|
|
- // We're processing the subfield before the primary value, initialize it
|
|
|
|
- if (!property_exists($this->destinationValues, $destination_field)) {
|
|
|
|
- $this->destinationValues->$destination_field = array();
|
|
|
|
- }
|
|
|
|
- // We have a value, and need to convert to an array so we can add
|
|
|
|
- // arguments.
|
|
|
|
- elseif (!is_array($this->destinationValues->$destination_field)) {
|
|
|
|
- $this->destinationValues->$destination_field = array($this->destinationValues->$destination_field);
|
|
|
|
- }
|
|
|
|
- if (!is_array($this->destinationValues->{$destination_field}['arguments'][$destination[1]])) {
|
|
|
|
- // Convert first subfield level to an array so we can add to it.
|
|
|
|
- $this->destinationValues->{$destination_field}['arguments'][$destination[1]] = array( $this->destinationValues->{$destination_field}['arguments'][$destination[1]] );
|
|
|
|
- }
|
|
|
|
- // Add the subfield value to the arguments array.
|
|
|
|
- $this->destinationValues->{$destination_field}['arguments'][$destination[1]]['arguments'][$subfield2] = $destination_values;
|
|
|
|
|
|
+ $subfield2 = $destination[2];
|
|
|
|
+ // We're processing the subfield before the primary value, initialize it
|
|
|
|
+ if (!property_exists($this->destinationValues, $destination_field)) {
|
|
|
|
+ $this->destinationValues->{$destination_field} = array();
|
|
|
|
+ }
|
|
|
|
+ // We have a value, and need to convert to an array so we can add
|
|
|
|
+ // arguments.
|
|
|
|
+ elseif (!is_array($this->destinationValues->{$destination_field})) {
|
|
|
|
+ $this->destinationValues->{$destination_field} = array($this->destinationValues->{$destination_field});
|
|
|
|
+ }
|
|
|
|
+ if (!is_array($this->destinationValues->{$destination_field}['arguments'][$destination[1]])) {
|
|
|
|
+ // Convert first subfield level to an array so we can add to it.
|
|
|
|
+ $this->destinationValues->{$destination_field}['arguments'][$destination[1]] = array($this->destinationValues->{$destination_field}['arguments'][$destination[1]]);
|
|
|
|
+ }
|
|
|
|
+ // Add the subfield value to the arguments array.
|
|
|
|
+ $this->destinationValues->{$destination_field}['arguments'][$destination[1]]['arguments'][$subfield2] = $destination_values;
|
|
}
|
|
}
|
|
// Just the primary value, the first time through for this field, simply
|
|
// Just the primary value, the first time through for this field, simply
|
|
// set it.
|
|
// set it.
|
|
elseif (!property_exists($this->destinationValues, $destination_field)) {
|
|
elseif (!property_exists($this->destinationValues, $destination_field)) {
|
|
- $this->destinationValues->$destination_field = $destination_values;
|
|
|
|
|
|
+ $this->destinationValues->{$destination_field} = $destination_values;
|
|
}
|
|
}
|
|
// We've seen a subfield, so add as an array value.
|
|
// We've seen a subfield, so add as an array value.
|
|
else {
|
|
else {
|
|
$this->destinationValues->{$destination_field} = array_merge(
|
|
$this->destinationValues->{$destination_field} = array_merge(
|
|
- (array)$destination_values, $this->destinationValues->{$destination_field});
|
|
|
|
|
|
+ (array) $destination_values, $this->destinationValues->{$destination_field});
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
@@ -1333,14 +1385,15 @@ abstract class Migration extends MigrationBase {
|
|
* @param mixed $source_migrations
|
|
* @param mixed $source_migrations
|
|
* An array of source migrations, or string for a single migration.
|
|
* An array of source migrations, or string for a single migration.
|
|
* @param mixed $source_keys
|
|
* @param mixed $source_keys
|
|
- * Key(s) to be looked up against the source migration(s). This may be a simple
|
|
|
|
- * value (one single-field key), an array of values (multiple single-field keys
|
|
|
|
- * to each be looked up), or an array of arrays (multiple multi-field keys to
|
|
|
|
- * each be looked up).
|
|
|
|
|
|
+ * Key(s) to be looked up against the source migration(s). This may be a
|
|
|
|
+ * simple value (one single-field key), an array of values (multiple
|
|
|
|
+ * single-field keys to each be looked up), or an array of arrays (multiple
|
|
|
|
+ * multi-field keys to each be looked up).
|
|
* @param mixed $default
|
|
* @param mixed $default
|
|
* The default value, if no ID was found.
|
|
* The default value, if no ID was found.
|
|
* @param $migration
|
|
* @param $migration
|
|
* The implementing migration.
|
|
* The implementing migration.
|
|
|
|
+ *
|
|
* @return
|
|
* @return
|
|
* Destination value(s) from the source migration(s), as a single value if
|
|
* Destination value(s) from the source migration(s), as a single value if
|
|
* a single key was passed in, or an array of values if there were multiple
|
|
* a single key was passed in, or an array of values if there were multiple
|
|
@@ -1377,6 +1430,11 @@ abstract class Migration extends MigrationBase {
|
|
// Instantiate each migration, and store back in the array.
|
|
// Instantiate each migration, and store back in the array.
|
|
foreach ($source_migrations as $key => $source_migration) {
|
|
foreach ($source_migrations as $key => $source_migration) {
|
|
$source_migrations[$key] = Migration::getInstance($source_migration);
|
|
$source_migrations[$key] = Migration::getInstance($source_migration);
|
|
|
|
+ if (!isset($source_migrations[$key])) {
|
|
|
|
+ MigrationBase::displayMessage(t('The @source cannot be resolved to a migration instance.',
|
|
|
|
+ array('@source' => $source_migration)));
|
|
|
|
+ unset($source_migrations[$key]);
|
|
|
|
+ }
|
|
}
|
|
}
|
|
|
|
|
|
$results = array();
|
|
$results = array();
|
|
@@ -1398,7 +1456,8 @@ abstract class Migration extends MigrationBase {
|
|
// Loop through each source migration, checking for an existing dest ID.
|
|
// Loop through each source migration, checking for an existing dest ID.
|
|
foreach ($source_migrations as $source_migration) {
|
|
foreach ($source_migrations as $source_migration) {
|
|
// Break out of the loop as soon as a destination ID is found.
|
|
// Break out of the loop as soon as a destination ID is found.
|
|
- if ($destids = $source_migration->getMap()->lookupDestinationID($source_key)) {
|
|
|
|
|
|
+ if ($destids = $source_migration->getMap()
|
|
|
|
+ ->lookupDestinationID($source_key)) {
|
|
if (!empty($destids['destid1'])) {
|
|
if (!empty($destids['destid1'])) {
|
|
break;
|
|
break;
|
|
}
|
|
}
|
|
@@ -1448,16 +1507,18 @@ abstract class Migration extends MigrationBase {
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
/**
|
|
- * For fields which require uniqueness, assign a new unique value if necessary.
|
|
|
|
|
|
+ * For fields which require uniqueness, assign a new unique value if
|
|
|
|
+ * necessary.
|
|
*
|
|
*
|
|
* @param array $dedupe
|
|
* @param array $dedupe
|
|
* An array with two keys, 'table' the name of the Drupal table and 'column'
|
|
* An array with two keys, 'table' the name of the Drupal table and 'column'
|
|
* the column within that table where uniqueness must be maintained.
|
|
* the column within that table where uniqueness must be maintained.
|
|
* @param $original
|
|
* @param $original
|
|
* The value coming in, which must be checked for uniqueness.
|
|
* The value coming in, which must be checked for uniqueness.
|
|
|
|
+ *
|
|
* @return string
|
|
* @return string
|
|
- * The value to use - either the original, or a variation created by appending
|
|
|
|
- * a sequence number.
|
|
|
|
|
|
+ * The value to use - either the original, or a variation created by
|
|
|
|
+ * appending a sequence number.
|
|
*/
|
|
*/
|
|
protected function handleDedupe($dedupe, $original) {
|
|
protected function handleDedupe($dedupe, $original) {
|
|
// If we're remigrating a previously-existing value, simply running through
|
|
// If we're remigrating a previously-existing value, simply running through
|
|
@@ -1468,11 +1529,11 @@ abstract class Migration extends MigrationBase {
|
|
if (isset($this->sourceValues->migrate_map_destid1)) {
|
|
if (isset($this->sourceValues->migrate_map_destid1)) {
|
|
$key_field = key($this->destination->getKeySchema());
|
|
$key_field = key($this->destination->getKeySchema());
|
|
$existing_value = db_select($dedupe['table'], 't')
|
|
$existing_value = db_select($dedupe['table'], 't')
|
|
- ->fields('t', array($dedupe['column']))
|
|
|
|
- ->range(0, 1)
|
|
|
|
- ->condition($key_field, $this->sourceValues->migrate_map_destid1)
|
|
|
|
- ->execute()
|
|
|
|
- ->fetchField();
|
|
|
|
|
|
+ ->fields('t', array($dedupe['column']))
|
|
|
|
+ ->range(0, 1)
|
|
|
|
+ ->condition($key_field, $this->sourceValues->migrate_map_destid1)
|
|
|
|
+ ->execute()
|
|
|
|
+ ->fetchField();
|
|
// Note that if, for some reason, we don't find a value, fall through
|
|
// Note that if, for some reason, we don't find a value, fall through
|
|
// to the normal deduping process
|
|
// to the normal deduping process
|
|
if ($existing_value) {
|
|
if ($existing_value) {
|
|
@@ -1481,12 +1542,12 @@ abstract class Migration extends MigrationBase {
|
|
}
|
|
}
|
|
$i = 1;
|
|
$i = 1;
|
|
$candidate = $original;
|
|
$candidate = $original;
|
|
- while ($candidate_found = db_select($dedupe['table'], 't')
|
|
|
|
- ->fields('t', array($dedupe['column']))
|
|
|
|
- ->range(0, 1)
|
|
|
|
- ->condition('t.' . $dedupe['column'], $candidate)
|
|
|
|
- ->execute()
|
|
|
|
- ->fetchField()) {
|
|
|
|
|
|
+ while (db_select($dedupe['table'], 't')
|
|
|
|
+ ->fields('t', array($dedupe['column']))
|
|
|
|
+ ->range(0, 1)
|
|
|
|
+ ->condition('t.' . $dedupe['column'], $candidate)
|
|
|
|
+ ->execute()
|
|
|
|
+ ->rowCount() > 0) {
|
|
// We already have the candidate value. Find a non-existing value.
|
|
// We already have the candidate value. Find a non-existing value.
|
|
$i++;
|
|
$i++;
|
|
// @TODO: support custom replacement pattern instead of just append.
|
|
// @TODO: support custom replacement pattern instead of just append.
|
|
@@ -1494,9 +1555,11 @@ abstract class Migration extends MigrationBase {
|
|
}
|
|
}
|
|
if ($i > 1) {
|
|
if ($i > 1) {
|
|
$message = t('Replacing !column !original with !candidate',
|
|
$message = t('Replacing !column !original with !candidate',
|
|
- array('!column' => $dedupe['column'],
|
|
|
|
- '!original' => $original,
|
|
|
|
- '!candidate' => $candidate));
|
|
|
|
|
|
+ array(
|
|
|
|
+ '!column' => $dedupe['column'],
|
|
|
|
+ '!original' => $original,
|
|
|
|
+ '!candidate' => $candidate,
|
|
|
|
+ ));
|
|
$migration = Migration::currentMigration();
|
|
$migration = Migration::currentMigration();
|
|
$migration->saveMessage($message, Migration::MESSAGE_INFORMATIONAL);
|
|
$migration->saveMessage($message, Migration::MESSAGE_INFORMATIONAL);
|
|
}
|
|
}
|
|
@@ -1515,7 +1578,7 @@ abstract class Migration extends MigrationBase {
|
|
$data_row = new stdClass;
|
|
$data_row = new stdClass;
|
|
$i = 0;
|
|
$i = 0;
|
|
foreach ($map_source_key as $key => $definition) {
|
|
foreach ($map_source_key as $key => $definition) {
|
|
- $data_row->$key = $source_key[$i++];
|
|
|
|
|
|
+ $data_row->{$key} = $source_key[$i++];
|
|
}
|
|
}
|
|
$this->map->saveIDMapping($data_row, $destids,
|
|
$this->map->saveIDMapping($data_row, $destids,
|
|
MigrateMap::STATUS_NEEDS_UPDATE, $this->defaultRollbackAction);
|
|
MigrateMap::STATUS_NEEDS_UPDATE, $this->defaultRollbackAction);
|
|
@@ -1577,15 +1640,18 @@ abstract class Migration extends MigrationBase {
|
|
* Migration instead.
|
|
* Migration instead.
|
|
*/
|
|
*/
|
|
abstract class DynamicMigration extends Migration {
|
|
abstract class DynamicMigration extends Migration {
|
|
|
|
+
|
|
static $deprecationWarning = FALSE;
|
|
static $deprecationWarning = FALSE;
|
|
|
|
+
|
|
public function __construct($arguments) {
|
|
public function __construct($arguments) {
|
|
parent::__construct($arguments);
|
|
parent::__construct($arguments);
|
|
if (variable_get('migrate_deprecation_warnings', 1) &&
|
|
if (variable_get('migrate_deprecation_warnings', 1) &&
|
|
- !self::$deprecationWarning) {
|
|
|
|
|
|
+ !self::$deprecationWarning) {
|
|
self::displayMessage(t('The DynamicMigration class is no longer necessary and is now deprecated - please derive your migration classes directly from Migration.'));
|
|
self::displayMessage(t('The DynamicMigration class is no longer necessary and is now deprecated - please derive your migration classes directly from Migration.'));
|
|
self::$deprecationWarning = TRUE;
|
|
self::$deprecationWarning = TRUE;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
+
|
|
/**
|
|
/**
|
|
* Overrides default of FALSE
|
|
* Overrides default of FALSE
|
|
*/
|
|
*/
|