class CRMCoreMigrateSQLMap in CRM Core 7
@file Defines a CRMCore extention of MigrateSQLMap
Hierarchy
- class \MigrateMap implements \Iterator
- class \MigrateSQLMap
- class \CRMCoreMigrateSQLMap
- class \MigrateSQLMap
Expanded class hierarchy of CRMCoreMigrateSQLMap
File
- modules/
crm_core_data_import/ includes/ controllers/ CRMCoreMigrateSQLMap.inc, line 7 - Defines a CRMCore extention of MigrateSQLMap
View source
class CRMCoreMigrateSQLMap extends MigrateSQLMap {
// We need importer to get info about related migrations.
// This will allow us to add relation_id fields to migrate map table schema.
/** @var CRMCoreDataImport */
protected $importer;
protected $options;
public function __construct($machine_name, array $source_key, array $destination_key, $connection_key = 'default', $options = array()) {
if (!empty($options['importer']) && $options['importer'] instanceof CRMCoreDataImport) {
$this->importer = $options['importer'];
unset($options['importer']);
}
$this->options = $options;
parent::__construct($machine_name, $source_key, $destination_key, $connection_key, $options);
}
protected function ensureTables() {
if (!$this->ensured) {
if (!$this->connection
->schema()
->tableExists($this->mapTable)) {
// Generate appropriate schema info for the map and message tables,
// and map from the source field names to the map/msg field names
$count = 1;
$source_key_schema = array();
$pks = array();
foreach ($this->sourceKey as $field_schema) {
$mapkey = 'sourceid' . $count++;
// Make source key case sensitive
$field_schema['binary'] = TRUE;
$source_key_schema[$mapkey] = $field_schema;
$pks[] = $mapkey;
}
$fields = $source_key_schema;
// Add destination keys to map table
// TODO: How do we discover the destination schema?
$count = 1;
foreach ($this->destinationKey as $field_schema) {
// Allow dest key fields to be NULL (for IGNORED/FAILED cases)
$field_schema['not null'] = FALSE;
$mapkey = 'destid' . $count++;
$fields[$mapkey] = $field_schema;
}
$fields['needs_update'] = array(
'type' => 'int',
'size' => 'tiny',
'unsigned' => TRUE,
'not null' => TRUE,
'default' => MigrateMap::STATUS_IMPORTED,
'description' => 'Indicates current status of the source row',
);
$fields['rollback_action'] = array(
'type' => 'int',
'size' => 'tiny',
'unsigned' => TRUE,
'not null' => TRUE,
'default' => MigrateMap::ROLLBACK_DELETE,
'description' => 'Flag indicating what to do for this item on rollback',
);
$fields['last_imported'] = array(
'type' => 'int',
'unsigned' => TRUE,
'not null' => TRUE,
'default' => 0,
'description' => 'UNIX timestamp of the last time this row was imported',
);
$fields['hash'] = array(
'type' => 'varchar',
'length' => '32',
'not null' => FALSE,
'description' => 'Hash of source row data, for detecting changes',
);
// Find out if we need to add relation ids to schema.
// Add source id for relations that we import.
// We need source id only for one endpoint of relationship.
// Let it be source endpoint.
$destinations = $this->importer
->getRelationDestinationEndPoints(implode(':', array(
$this->options['entity_type'],
$this->options['entity_bundle'],
$this->options['delta'],
)));
foreach ($destinations as $key => $destination) {
$fields['relation_id' . ($key + 1)] = array(
'type' => 'varchar',
'length' => '32',
'binary' => TRUE,
'not null' => FALSE,
'description' => 'ID of relation endpoint entity',
);
}
$schema = array(
'description' => t('Mappings from source key to destination key'),
'fields' => $fields,
'primary key' => $pks,
);
$this->connection
->schema()
->createTable($this->mapTable, $schema);
// Now for the message table
$fields = array();
$fields['msgid'] = array(
'type' => 'serial',
'unsigned' => TRUE,
'not null' => TRUE,
);
$fields += $source_key_schema;
$fields['level'] = array(
'type' => 'int',
'unsigned' => TRUE,
'not null' => TRUE,
'default' => 1,
);
$fields['message'] = array(
'type' => 'text',
'size' => 'medium',
'not null' => TRUE,
);
$schema = array(
'description' => t('Messages generated during a migration process'),
'fields' => $fields,
'primary key' => array(
'msgid',
),
'indexes' => array(
'sourcekey' => $pks,
),
);
$this->connection
->schema()
->createTable($this->messageTable, $schema);
}
else {
// Add any missing columns to the map table
if (!$this->connection
->schema()
->fieldExists($this->mapTable, 'rollback_action')) {
$this->connection
->schema()
->addField($this->mapTable, 'rollback_action', array(
'type' => 'int',
'size' => 'tiny',
'unsigned' => TRUE,
'not null' => TRUE,
'default' => 0,
'description' => 'Flag indicating what to do for this item on rollback',
));
}
if (!$this->connection
->schema()
->fieldExists($this->mapTable, 'hash')) {
$this->connection
->schema()
->addField($this->mapTable, 'hash', array(
'type' => 'varchar',
'length' => '32',
'not null' => FALSE,
'description' => 'Hash of source row data, for detecting changes',
));
}
}
$this->ensured = TRUE;
}
}
/**
* Called upon import of one record, we record a mapping from the source key
* to the destination key. Also may be called, setting the third parameter to
* NEEDS_UPDATE, to signal an existing record should be remigrated.
*
* @param stdClass $source_row
* The raw source data. We use the key map derived from the source object
* to get the source key values.
* @param array $dest_ids
* The destination key values.
* @param int $needs_update
* Status of the source row in the map. Defaults to STATUS_IMPORTED.
* @param int $rollback_action
* How to handle the destination object on rollback. Defaults to
* ROLLBACK_DELETE.
* $param string $hash
* If hashing is enabled, the hash of the raw source row.
*/
public function saveIDMapping(stdClass $source_row, array $dest_ids, $needs_update = MigrateMap::STATUS_IMPORTED, $rollback_action = MigrateMap::ROLLBACK_DELETE, $hash = NULL) {
migrate_instrument_start('saveIDMapping');
// Construct the source key
$keys = array();
foreach ($this->sourceKeyMap as $field_name => $key_name) {
// A NULL key value will fail.
if (is_null($source_row->{$field_name})) {
Migration::displayMessage(t('Could not save to map table due to NULL value for key field !field', array(
'!field' => $field_name,
)));
migrate_instrument_stop('saveIDMapping');
return;
}
$keys[$key_name] = $source_row->{$field_name};
}
$fields = array(
'needs_update' => (int) $needs_update,
'rollback_action' => (int) $rollback_action,
'hash' => $hash,
);
// Add relation ids when present.
foreach ($this->importer
->getRelationDestinationEndPoints(implode(':', array(
$this->options['entity_type'],
$this->options['entity_bundle'],
$this->options['delta'],
))) as $key => $ep) {
list($ep_entity_type, $ep_bundle, $ep_importer_id) = explode(':', $ep);
$endpoint_machine_name = _crm_core_data_import_migration_machine_name($ep_importer_id, $ep_entity_type, $ep_bundle, $this->options['delta']);
$endpoint_migration = Migration::getInstance($endpoint_machine_name);
$ep_source_map = array_keys($endpoint_migration
->getMap()
->getSourceKeyMap());
$fields['relation_id' . ($key + 1)] = $source_row->{$ep_source_map[0]};
}
$count = 1;
if (!empty($dest_ids)) {
foreach ($dest_ids as $dest_id) {
$fields['destid' . $count++] = $dest_id;
}
}
if ($this->trackLastImported) {
$fields['last_imported'] = time();
}
$this->connection
->merge($this->mapTable)
->key($keys)
->fields($fields)
->execute();
migrate_instrument_stop('saveIDMapping');
}
}
Members
Name![]() |
Modifiers | Type | Description | Overrides |
---|---|---|---|---|
CRMCoreMigrateSQLMap:: |
protected | property | @var CRMCoreDataImport | |
CRMCoreMigrateSQLMap:: |
protected | property | ||
CRMCoreMigrateSQLMap:: |
protected | function |
Create the map and message tables if they don't already exist. Overrides MigrateSQLMap:: |
|
CRMCoreMigrateSQLMap:: |
public | function |
Called upon import of one record, we record a mapping from the source key
to the destination key. Also may be called, setting the third parameter to
NEEDS_UPDATE, to signal an existing record should be remigrated. Overrides MigrateSQLMap:: |
|
CRMCoreMigrateSQLMap:: |
public | function |
Constructor. Overrides MigrateSQLMap:: |
|
MigrateMap:: |
protected | property | Arrays of key fields for the source and destination. Array keys are the field names - array values are specific to the concrete map class. | |
MigrateMap:: |
protected | property | Mapping from field names to the map/message table key names (e.g., from input_field to sourceid1, or from nid to destid1) | |
MigrateMap:: |
protected | property | Boolean determining whether to track last_imported times in map tables | |
MigrateMap:: |
public | function | Get the source key map. | |
MigrateMap:: |
public | function | ||
MigrateMap:: |
constant | Codes reflecting how to handle the destination item on rollback. | ||
MigrateMap:: |
constant | |||
MigrateMap:: |
public | function | ||
MigrateMap:: |
constant | |||
MigrateMap:: |
constant | |||
MigrateMap:: |
constant | Codes reflecting the current status of a map row. | ||
MigrateMap:: |
constant | |||
MigrateSQLMap:: |
protected | property | Provide caching for Source or Desination Map Lookups. | |
MigrateSQLMap:: |
protected | property | Drupal connection object on which to create the map/message tables. | |
MigrateSQLMap:: |
protected | property | ||
MigrateSQLMap:: |
protected | property | ||
MigrateSQLMap:: |
protected | property | We don't need to check the tables more than once per request. | |
MigrateSQLMap:: |
protected | property | Names of tables created for tracking the migration. | |
MigrateSQLMap:: |
protected | property | ||
MigrateSQLMap:: |
public | function |
Clear all messages from the message table. Overrides MigrateMap:: |
|
MigrateSQLMap:: |
public | function | Implementation of Iterator::current() - called when entering a loop iteration, returning the current row. | |
MigrateSQLMap:: |
public | function |
Delete the map entry and any message table entries for the specified
source row. Overrides MigrateMap:: |
|
MigrateSQLMap:: |
public | function |
Delete all map and message table entries specified. Overrides MigrateMap:: |
|
MigrateSQLMap:: |
public | function |
Delete the map entry and any message table entries for the specified
destination row. Overrides MigrateMap:: |
|
MigrateSQLMap:: |
public | function |
Remove the associated map and message tables. Overrides MigrateMap:: |
|
MigrateSQLMap:: |
public | function |
Get the number of source records which failed to import. Overrides MigrateMap:: |
|
MigrateSQLMap:: |
public | function | ||
MigrateSQLMap:: |
public | function | ||
MigrateSQLMap:: |
public | function |
Overrides MigrateMap:: |
|
MigrateSQLMap:: |
public | function | ||
MigrateSQLMap:: |
public | function | ||
MigrateSQLMap:: |
public | function | Qualifying the map table name with the database name makes cross-db joins possible. Note that, because prefixes are applied after we do this (i.e., it will prefix the string we return), we do not qualify the table if it has a prefix. This will work… | |
MigrateSQLMap:: |
public | function |
Retrieve a row from the map table, given a destination ID. Overrides MigrateMap:: |
|
MigrateSQLMap:: |
public | function |
Retrieve a row from the map table, given a source ID. Overrides MigrateMap:: |
|
MigrateSQLMap:: |
public | function |
Retrieve an array of map rows marked as needing update. Overrides MigrateMap:: |
|
MigrateSQLMap:: |
public | function |
sourceKey and destinationKey arrays are keyed by the field names; values
are the Drupal schema definition for the field. Overrides MigrateMap:: |
|
MigrateSQLMap:: |
public | function |
Returns a count of imported records in the map table. Overrides MigrateMap:: |
|
MigrateSQLMap:: |
public | function | Implementation of Iterator::key - called when entering a loop iteration, returning the key of the current row. It must be a scalar - we will serialize to fulfill the requirement, but using getCurrentKey() is preferable. | |
MigrateSQLMap:: |
public | function |
Given a (possibly multi-field) source key, return the (possibly
multi-field) destination key it is mapped to. Overrides MigrateMap:: |
|
MigrateSQLMap:: |
public | function |
Given a (possibly multi-field) destination key, return the (possibly
multi-field) source key mapped to it. Overrides MigrateMap:: |
|
MigrateSQLMap:: |
public | function |
Get the number of messages saved. Overrides MigrateMap:: |
|
MigrateSQLMap:: |
public | function | Implementation of Iterator::next() - called at the bottom of the loop implicitly, as well as explicitly from rewind(). | |
MigrateSQLMap:: |
public | function |
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. Overrides MigrateMap:: |
|
MigrateSQLMap:: |
public | function |
Returns a count of records in the map table (i.e., the number of
source records which have been processed for this migration). Overrides MigrateMap:: |
|
MigrateSQLMap:: |
public | function | Implementation of Iterator::rewind() - called before beginning a foreach loop. TODO: Support idlist, itemlimit. | |
MigrateSQLMap:: |
public | function |
Record a message in the migration's message table. Overrides MigrateMap:: |
|
MigrateSQLMap:: |
public | function | Set the specified row to be updated, if it exists. | |
MigrateSQLMap:: |
public | function | Returns a count of records which are marked as needing update. | |
MigrateSQLMap:: |
public | function | Implementation of Iterator::valid() - called at the top of the loop, returning TRUE to process the loop and FALSE to terminate it. |