first import
This commit is contained in:
1015
sites/all/modules/migrate/includes/base.inc
Normal file
1015
sites/all/modules/migrate/includes/base.inc
Normal file
File diff suppressed because it is too large
Load Diff
115
sites/all/modules/migrate/includes/destination.inc
Normal file
115
sites/all/modules/migrate/includes/destination.inc
Normal file
@@ -0,0 +1,115 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Defines base for migration destinations.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Abstract base class for destination handling.
|
||||
*
|
||||
* Derived classes are expected to define __toString(), returning a string
|
||||
* describing the type of destination and significant options. See
|
||||
* MigrateDestinationEntity for an example.
|
||||
*/
|
||||
abstract class MigrateDestination {
|
||||
/**
|
||||
* To support MigrateSQLMap 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.
|
||||
*
|
||||
* abstract static public function getKeySchema()
|
||||
*/
|
||||
|
||||
/**
|
||||
* Derived classes must implement __toString().
|
||||
*
|
||||
* @return string
|
||||
* Description of the destination being migrated into
|
||||
*/
|
||||
abstract public function __toString();
|
||||
|
||||
/**
|
||||
* Derived classes must implement fields(), returning a list of available
|
||||
* destination fields.
|
||||
*
|
||||
* @param Migration $migration
|
||||
* Optionally, the migration containing this destination.
|
||||
* @return array
|
||||
* Keys: machine names of the fields (to be passed to addFieldMapping)
|
||||
* Values: Human-friendly descriptions of the fields.
|
||||
*/
|
||||
abstract public function fields();
|
||||
|
||||
/**
|
||||
* Derived classes must implement either bulkRollback or rollback() according to
|
||||
* the signatures below, to rollback (usually by deletion) previously-migrated
|
||||
* items.
|
||||
*
|
||||
* $ids is an array of single-field keys to be deleted
|
||||
* abstract public function bulkRollback(array $ids);
|
||||
*
|
||||
* $key is an array of fields keying a single entry to delete
|
||||
* abstract public function rollback(array $key);
|
||||
*/
|
||||
|
||||
/**
|
||||
* Derived classes must implement import(), to construct one new object (pre-pppulated
|
||||
* using field mappings in the Migration). It is expected to call prepare and
|
||||
* complete handlers, passing them $row (the raw data from the source).
|
||||
*/
|
||||
abstract public function import(stdClass $object, stdClass $row);
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*
|
||||
* abstract public function preImport();
|
||||
* abstract public function postImport();
|
||||
* abstract public function preRollback();
|
||||
* abstract public function postRollback();
|
||||
*/
|
||||
|
||||
/**
|
||||
* Maintain stats on the number of destination objects created or updated.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
protected $numCreated = 0;
|
||||
public function getCreated() {
|
||||
return $this->numCreated;
|
||||
}
|
||||
protected $numUpdated = 0;
|
||||
public function getUpdated() {
|
||||
return $this->numUpdated;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset numCreated and numUpdated back to 0.
|
||||
*/
|
||||
public function resetStats() {
|
||||
$this->numCreated = 0;
|
||||
$this->numUpdated = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Null constructor
|
||||
*/
|
||||
public function __construct() {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* All destination handlers should be derived from MigrateDestinationHandler
|
||||
*/
|
||||
abstract class MigrateDestinationHandler extends MigrateHandler {
|
||||
// abstract function arguments(...)
|
||||
/**
|
||||
* Any one or more of these methods may be implemented
|
||||
*/
|
||||
//abstract public function fields();
|
||||
//abstract public function prepare($entity, stdClass $row);
|
||||
//abstract public function complete($entity, stdClass $row);
|
||||
}
|
18
sites/all/modules/migrate/includes/exception.inc
Normal file
18
sites/all/modules/migrate/includes/exception.inc
Normal file
@@ -0,0 +1,18 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Custom exception class for the migrate module.
|
||||
*/
|
||||
|
||||
class MigrateException extends Exception {
|
||||
protected $level;
|
||||
public function getLevel() {
|
||||
return $this->level;
|
||||
}
|
||||
|
||||
public function __construct($message, $level = Migration::MESSAGE_ERROR) {
|
||||
$this->level = $level;
|
||||
parent::__construct($message);
|
||||
}
|
||||
}
|
202
sites/all/modules/migrate/includes/field_mapping.inc
Normal file
202
sites/all/modules/migrate/includes/field_mapping.inc
Normal file
@@ -0,0 +1,202 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* The MigrateFieldMapping class - tracking mappings between source and
|
||||
* destination.
|
||||
*/
|
||||
|
||||
class MigrateFieldMapping {
|
||||
/**
|
||||
* Destination field name for the mapping. If empty, the mapping is just a
|
||||
* stub for annotating the source field.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $destinationField;
|
||||
public function getDestinationField() {
|
||||
return $this->destinationField;
|
||||
}
|
||||
|
||||
/**
|
||||
* Source field name for the mapping. If empty, the defaultValue will be
|
||||
* applied.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $sourceField;
|
||||
public function getSourceField() {
|
||||
return $this->sourceField;
|
||||
}
|
||||
|
||||
/**
|
||||
* Default value for simple mappings, when there is no source mapping or the
|
||||
* source field is empty. If both this and the sourceField are omitted, the
|
||||
* mapping is just a stub for annotating the destination field.
|
||||
*
|
||||
* @var mixed
|
||||
*/
|
||||
protected $defaultValue;
|
||||
public function getDefaultValue() {
|
||||
return $this->defaultValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Separator string. If present, the destination field will be set up as an
|
||||
* array of values exploded from the corresponding source field.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $separator;
|
||||
public function getSeparator() {
|
||||
return $this->separator;
|
||||
}
|
||||
|
||||
/**
|
||||
* Class name of source migration for a field. If present, the value in the
|
||||
* source field is considered to be a source ID in the mapping table of this
|
||||
* migration, and the corresponding destination ID will be retrieved.
|
||||
*
|
||||
* @var mixed
|
||||
* An array of source migrations, or string for a single migration.
|
||||
*/
|
||||
protected $sourceMigration;
|
||||
public function getSourceMigration() {
|
||||
return $this->sourceMigration;
|
||||
}
|
||||
|
||||
/**
|
||||
* Array of callbacks to be called on a source value.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $callbacks = array();
|
||||
public function getCallbacks() {
|
||||
return $this->callbacks;
|
||||
}
|
||||
|
||||
/**
|
||||
* An associative array with keys:
|
||||
* - table: The table for querying for a duplicate.
|
||||
* - column: The column for querying for a duplicate.
|
||||
*
|
||||
* @todo: Let fields declare this data and a replacement pattern. Then
|
||||
* developers won't have to specify this.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $dedupe;
|
||||
public function getDedupe() {
|
||||
return $this->dedupe;
|
||||
}
|
||||
|
||||
/**
|
||||
* Argument overrides. If present this will be an array, keyed by
|
||||
* a field API array key, with one or both of these entries:
|
||||
* 'source_field' - Name of the source field in the incoming row containing the
|
||||
* value to be assigned
|
||||
* 'default_value' - A constant value to be assigned in the absence of source_field
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $arguments;
|
||||
public function getArguments() {
|
||||
return $this->arguments;
|
||||
}
|
||||
|
||||
protected $description = '';
|
||||
public function getDescription() {
|
||||
return $this->description;
|
||||
}
|
||||
|
||||
protected $issueGroup;
|
||||
public function getIssueGroup() {
|
||||
return $this->issueGroup;
|
||||
}
|
||||
|
||||
protected $issueNumber;
|
||||
public function getIssueNumber() {
|
||||
return $this->issueNumber;
|
||||
}
|
||||
|
||||
protected $issuePriority = self::ISSUE_PRIORITY_OK;
|
||||
public function getIssuePriority() {
|
||||
return $this->issuePriority;
|
||||
}
|
||||
|
||||
const ISSUE_PRIORITY_OK = 1;
|
||||
const ISSUE_PRIORITY_LOW = 2;
|
||||
const ISSUE_PRIORITY_MEDIUM = 3;
|
||||
const ISSUE_PRIORITY_BLOCKER = 4;
|
||||
|
||||
public static $priorities = array();
|
||||
|
||||
public function __construct($destination_field, $source_field) {
|
||||
// Must have one or the other
|
||||
if (!$destination_field && !$source_field) {
|
||||
throw new Exception('Field mappings must have a destination field or a source field');
|
||||
}
|
||||
$this->destinationField = $destination_field;
|
||||
$this->sourceField = $source_field;
|
||||
$this->issueGroup = t('Done');
|
||||
if (count(self::$priorities) == 0) {
|
||||
self::$priorities[self::ISSUE_PRIORITY_OK] = t('OK');
|
||||
self::$priorities[self::ISSUE_PRIORITY_LOW] = t('Low');
|
||||
self::$priorities[self::ISSUE_PRIORITY_MEDIUM] = t('Medium');
|
||||
self::$priorities[self::ISSUE_PRIORITY_BLOCKER] = t('Blocker');
|
||||
}
|
||||
}
|
||||
|
||||
public function defaultValue($default_value) {
|
||||
$this->defaultValue = $default_value;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function separator($separator) {
|
||||
$this->separator = $separator;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function sourceMigration($source_migration) {
|
||||
$this->sourceMigration = $source_migration;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function callbacks($callbacks) {
|
||||
$this->callbacks = func_get_args();
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function dedupe($table, $column) {
|
||||
$this->dedupe = array('table' => $table, 'column' => $column);
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function arguments($arguments) {
|
||||
$this->arguments = $arguments;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function description($text) {
|
||||
$this->description = $text;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function issueGroup($group) {
|
||||
if (!$group) {
|
||||
$group = t('Done');
|
||||
}
|
||||
$this->issueGroup = $group;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function issueNumber($number) {
|
||||
$this->issueNumber = $number;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function issuePriority($priority) {
|
||||
$this->issuePriority = $priority;
|
||||
return $this;
|
||||
}
|
||||
}
|
109
sites/all/modules/migrate/includes/group.inc
Normal file
109
sites/all/modules/migrate/includes/group.inc
Normal file
@@ -0,0 +1,109 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Definition for a migration group.
|
||||
*/
|
||||
|
||||
class MigrateGroup {
|
||||
/**
|
||||
* The name of the group - used to identify it in drush commands.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $name;
|
||||
public function getName() {
|
||||
return $this->name;
|
||||
}
|
||||
|
||||
/**
|
||||
* List of groups this group is dependent on.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $dependencies = array();
|
||||
public function getDependencies() {
|
||||
return $this->dependencies;
|
||||
}
|
||||
|
||||
/**
|
||||
* The central list of all known groups, keyed by group name.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
static protected $groupList = array();
|
||||
static public function groups() {
|
||||
$groups = array();
|
||||
$dependent_groups = array();
|
||||
$required_groups = array();
|
||||
foreach (self::$groupList as $name => $group) {
|
||||
$dependencies = $group->getDependencies();
|
||||
if (count($dependencies) > 0) {
|
||||
// Set groups with dependencies aside for reordering
|
||||
$dependent_groups[$name] = $group;
|
||||
$required_groups += $dependencies;
|
||||
}
|
||||
else {
|
||||
// No dependencies, just add
|
||||
$groups[$name] = $group;
|
||||
}
|
||||
}
|
||||
$iterations = 0;
|
||||
while (count($dependent_groups) > 0) {
|
||||
if ($iterations++ > 20) {
|
||||
$group_names = implode(',', array_keys($dependent_groups));
|
||||
throw new MigrateException(t('Failure to sort migration list - most likely due ' .
|
||||
'to circular dependencies involving groups !group_names',
|
||||
array('!group_names' => $group_names)));
|
||||
}
|
||||
foreach ($dependent_groups as $name => $group) {
|
||||
$ready = TRUE;
|
||||
// Scan all the dependencies for this group and make sure they're all
|
||||
// in the final list
|
||||
foreach ($group->getDependencies() as $dependency) {
|
||||
if (!isset($groups[$dependency])) {
|
||||
$ready = FALSE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ($ready) {
|
||||
// Yes they are! Move this group to the final list
|
||||
$groups[$name] = $group;
|
||||
unset($dependent_groups[$name]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $groups;
|
||||
}
|
||||
|
||||
/**
|
||||
* Basic constructor.
|
||||
*
|
||||
* @param string $name
|
||||
* Group name.
|
||||
*
|
||||
* @param array $dependencies
|
||||
* List of dependent groups.
|
||||
*/
|
||||
public function __construct($name, $dependencies = array()) {
|
||||
$this->name = $name;
|
||||
$this->dependencies = $dependencies;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve (creating if necessary) an instance of the named group.
|
||||
*
|
||||
* @param string $name
|
||||
* Group name.
|
||||
*
|
||||
* @param array $dependencies
|
||||
* List of dependent groups.
|
||||
*/
|
||||
static public function getInstance($name, $dependencies = array()) {
|
||||
if (empty(self::$groupList[$name])) {
|
||||
self::$groupList[$name] = new MigrateGroup($name, $dependencies);
|
||||
}
|
||||
return self::$groupList[$name];
|
||||
}
|
||||
}
|
57
sites/all/modules/migrate/includes/handler.inc
Normal file
57
sites/all/modules/migrate/includes/handler.inc
Normal file
@@ -0,0 +1,57 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Defines the base class for destination handlers.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Abstract base class for destination handlers. Handler objects are expected
|
||||
* to implement appropriate methods (e.g., prepare, complete, or fields).
|
||||
*/
|
||||
abstract class MigrateHandler {
|
||||
/**
|
||||
* List of other handler classes which should be invoked before the current one.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $dependencies = array();
|
||||
public function getDependencies() {
|
||||
return $this->dependencies;
|
||||
}
|
||||
|
||||
/**
|
||||
* List of "types" handled by this handler. Depending on the kind of handler,
|
||||
* these may be destination types, field types, etc.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $typesHandled = array();
|
||||
public function getTypesHandled() {
|
||||
return $this->typesHandled;
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a list of types handled by this class
|
||||
*
|
||||
* @param array $types
|
||||
*/
|
||||
protected function registerTypes(array $types) {
|
||||
// Make the type names the keys
|
||||
foreach ($types as $type) {
|
||||
$type = drupal_strtolower($type);
|
||||
$this->typesHandled[$type] = $type;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Does this handler handle the given type?
|
||||
*
|
||||
* @param boolean $type
|
||||
*/
|
||||
public function handlesType($type) {
|
||||
return isset($this->typesHandled[strtolower($type)]);
|
||||
}
|
||||
|
||||
abstract public function __construct();
|
||||
}
|
158
sites/all/modules/migrate/includes/map.inc
Normal file
158
sites/all/modules/migrate/includes/map.inc
Normal file
@@ -0,0 +1,158 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Defines the framework for map and message handling.
|
||||
*/
|
||||
|
||||
/**
|
||||
* We implement the Iterator interface to support iteration over the map table
|
||||
* for the purpose of rollback.
|
||||
*/
|
||||
abstract class MigrateMap implements Iterator {
|
||||
/**
|
||||
* 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;
|
||||
|
||||
/**
|
||||
* Arrays of key fields for the source and destination. Array keys are the
|
||||
* field names - array values are specific to the concrete map class.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $sourceKey, $destinationKey;
|
||||
abstract public function getSourceKey();
|
||||
abstract public function getDestinationKey();
|
||||
|
||||
/**
|
||||
* Mapping from field names to the map/message table key names (e.g.,
|
||||
* from input_field to sourceid1, or from nid to destid1)
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $sourceKeyMap, $destinationKeyMap;
|
||||
|
||||
/**
|
||||
* Boolean determining whether to track last_imported times in map tables
|
||||
*
|
||||
* @var boolean
|
||||
*/
|
||||
protected $trackLastImported = FALSE;
|
||||
|
||||
/**
|
||||
* Save a mapping from the key values in the source row to the destination
|
||||
* keys.
|
||||
*
|
||||
* @param $source_row
|
||||
* @param $dest_ids
|
||||
* @param $status
|
||||
*/
|
||||
abstract public function saveIDMapping(stdClass $source_row, array $dest_ids,
|
||||
$status = MigrateMap::STATUS_IMPORTED);
|
||||
|
||||
/**
|
||||
* Record a message related to a source record
|
||||
*
|
||||
* @param array $source_key
|
||||
* Source ID of the record in error
|
||||
* @param string $message
|
||||
* The message to record.
|
||||
* @param int $level
|
||||
* Optional message severity (defaults to MESSAGE_ERROR).
|
||||
*/
|
||||
abstract public function saveMessage($source_key, $message, $level = MigrationBase::MESSAGE_ERROR);
|
||||
|
||||
/**
|
||||
* Prepare to run a full update - mark all previously-imported content as
|
||||
* ready to be re-imported.
|
||||
*/
|
||||
abstract public function prepareUpdate();
|
||||
|
||||
/**
|
||||
* Report the number of processed items in the map
|
||||
*/
|
||||
abstract public function processedCount();
|
||||
|
||||
/**
|
||||
* Report the number of imported items in the map
|
||||
*/
|
||||
abstract public function importedCount();
|
||||
|
||||
/**
|
||||
* Report the number of items that failed to import
|
||||
*/
|
||||
abstract public function errorCount();
|
||||
|
||||
/**
|
||||
* Report the number of messages
|
||||
*/
|
||||
abstract public function messageCount();
|
||||
|
||||
/**
|
||||
* Delete the map and message entries for a given source record
|
||||
*
|
||||
* @param array $source_key
|
||||
*/
|
||||
abstract public function delete(array $source_key, $messages_only = FALSE);
|
||||
|
||||
/**
|
||||
* Delete the map and message entries for a given destination record
|
||||
*
|
||||
* @param array $destination_key
|
||||
*/
|
||||
abstract public function deleteDestination(array $destination_key);
|
||||
|
||||
/**
|
||||
* Delete the map and message entries for a set of given source records.
|
||||
*
|
||||
* @param array $source_keys
|
||||
*/
|
||||
abstract public function deleteBulk(array $source_keys);
|
||||
|
||||
/**
|
||||
* Clear all messages from the map.
|
||||
*/
|
||||
abstract public function clearMessages();
|
||||
|
||||
/**
|
||||
* Retrieve map data for a given source or destination item
|
||||
*/
|
||||
abstract public function getRowBySource(array $source_id);
|
||||
abstract public function getRowByDestination(array $destination_id);
|
||||
|
||||
/**
|
||||
* Retrieve an array of map rows marked as needing update.
|
||||
*/
|
||||
abstract public function getRowsNeedingUpdate($count);
|
||||
|
||||
/**
|
||||
* Given a (possibly multi-field) destination key, return the (possibly multi-field)
|
||||
* source key mapped to it.
|
||||
*
|
||||
* @param array $destination_id
|
||||
* Array of destination key values.
|
||||
* @return array
|
||||
* Array of source key values, or NULL on failure.
|
||||
*/
|
||||
abstract public function lookupSourceID(array $destination_id);
|
||||
|
||||
/**
|
||||
* Given a (possibly multi-field) source key, return the (possibly multi-field)
|
||||
* destination key it is mapped to.
|
||||
*
|
||||
* @param array $source_id
|
||||
* Array of source key values.
|
||||
* @return array
|
||||
* Array of destination key values, or NULL on failure.
|
||||
*/
|
||||
abstract public function lookupDestinationID(array $source_id);
|
||||
|
||||
/**
|
||||
* Remove any persistent storage used by this map (e.g., map and message tables)
|
||||
*/
|
||||
abstract public function destroy();
|
||||
}
|
1288
sites/all/modules/migrate/includes/migration.inc
Normal file
1288
sites/all/modules/migrate/includes/migration.inc
Normal file
File diff suppressed because it is too large
Load Diff
368
sites/all/modules/migrate/includes/source.inc
Normal file
368
sites/all/modules/migrate/includes/source.inc
Normal file
@@ -0,0 +1,368 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Define base for migration sources.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Abstract base class for source handling.
|
||||
*
|
||||
* Derived classes are expected to define __toString(), returning a string
|
||||
* describing the source and significant options. See
|
||||
* MigrateSourceSQL for an example.
|
||||
*/
|
||||
abstract class MigrateSource implements Iterator {
|
||||
/**
|
||||
* The current row from the quey
|
||||
*
|
||||
* @var stdClass
|
||||
*/
|
||||
protected $currentRow;
|
||||
|
||||
/**
|
||||
* The primary key of the current row
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $currentKey;
|
||||
public function getCurrentKey() {
|
||||
return $this->currentKey;
|
||||
}
|
||||
|
||||
/**
|
||||
* The Migration class currently invoking us, during rewind() and next().
|
||||
*
|
||||
* @var Migration
|
||||
*/
|
||||
protected $activeMigration;
|
||||
|
||||
/**
|
||||
* The MigrateMap class for the current migration.
|
||||
*
|
||||
* @var MigrateMap
|
||||
*/
|
||||
protected $activeMap;
|
||||
|
||||
/**
|
||||
* Number of rows intentionally ignored (prepareRow() returned FALSE)
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
protected $numIgnored = 0;
|
||||
public function getIgnored() {
|
||||
return $this->numIgnored;
|
||||
}
|
||||
|
||||
/**
|
||||
* Number of rows we've at least looked at.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
protected $numProcessed = 0;
|
||||
public function getProcessed() {
|
||||
return $this->numProcessed;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset numIgnored back to 0.
|
||||
*/
|
||||
public function resetStats() {
|
||||
$this->numIgnored = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Information on the highwater mark for the current migration, if any.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $highwaterField;
|
||||
|
||||
/**
|
||||
* List of source IDs to process.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $idList = array();
|
||||
|
||||
/**
|
||||
* Derived classes must implement fields(), returning a list of available
|
||||
* source fields.
|
||||
*
|
||||
* @return array
|
||||
* Keys: machine names of the fields (to be passed to addFieldMapping)
|
||||
* Values: Human-friendly descriptions of the fields.
|
||||
*/
|
||||
abstract public function fields();
|
||||
|
||||
/**
|
||||
* Whether this instance should cache the source count.
|
||||
*
|
||||
* @var boolean
|
||||
*/
|
||||
protected $cacheCounts = FALSE;
|
||||
|
||||
/**
|
||||
* Key to use for caching counts.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $cacheKey;
|
||||
|
||||
/**
|
||||
* Whether this instance should not attempt to count the source.
|
||||
*
|
||||
* @var boolean
|
||||
*/
|
||||
protected $skipCount = FALSE;
|
||||
|
||||
/**
|
||||
* By default, next() will directly read the map row and add it to the data
|
||||
* row. A source plugin implementation may do this itself (in particular, the
|
||||
* SQL source can incorporate the map table into the query) - if so, it should
|
||||
* set this TRUE so we don't duplicate the effort.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
protected $mapRowAdded = FALSE;
|
||||
|
||||
/**
|
||||
* Return a count of available source records, from the cache if appropriate.
|
||||
* Returns -1 if the source is not countable.
|
||||
*
|
||||
* @param boolean $refresh
|
||||
*/
|
||||
public function count($refresh = FALSE) {
|
||||
if ($this->skipCount) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!isset($this->cacheKey)) {
|
||||
$this->cacheKey = md5((string)$this);
|
||||
}
|
||||
|
||||
// If a refresh is requested, or we're not caching counts, ask the derived
|
||||
// class to get the count from the source.
|
||||
if ($refresh || !$this->cacheCounts) {
|
||||
$count = $this->computeCount();
|
||||
cache_set($this->cacheKey, $count, 'cache');
|
||||
}
|
||||
else {
|
||||
// Caching is in play, first try to retrieve a cached count.
|
||||
$cache_object = cache_get($this->cacheKey, 'cache');
|
||||
if (is_object($cache_object)) {
|
||||
// Success
|
||||
$count = $cache_object->data;
|
||||
}
|
||||
else {
|
||||
// No cached count, ask the derived class to count 'em up, and cache
|
||||
// the result
|
||||
$count = $this->computeCount();
|
||||
cache_set($this->cacheKey, $count, 'cache');
|
||||
}
|
||||
}
|
||||
return $count;
|
||||
}
|
||||
|
||||
/**
|
||||
* Derived classes must implement computeCount(), to retrieve a fresh count of
|
||||
* source records.
|
||||
*/
|
||||
//abstract public function computeCount();
|
||||
|
||||
/**
|
||||
* Class constructor.
|
||||
*
|
||||
* @param array $options
|
||||
* Optional array of options.
|
||||
*/
|
||||
public function __construct($options = array()) {
|
||||
if (!empty($options['cache_counts'])) {
|
||||
$this->cacheCounts = TRUE;
|
||||
}
|
||||
if (!empty($options['skip_count'])) {
|
||||
$this->skipCount = TRUE;
|
||||
}
|
||||
if (!empty($options['cache_key'])) {
|
||||
$this->cacheKey = $options['cache_key'];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Default implementations of Iterator methods - many derivations will find
|
||||
* these adequate and will only need to implement rewind() and next()
|
||||
*/
|
||||
|
||||
/**
|
||||
* Implementation of Iterator::current() - called when entering a loop
|
||||
* iteration, returning the current row
|
||||
*/
|
||||
public function current() {
|
||||
return $this->currentRow;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
public function key() {
|
||||
return serialize($this->currentKey);
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of Iterator::valid() - called at the top of the loop, returning
|
||||
* TRUE to process the loop and FALSE to terminate it
|
||||
*/
|
||||
public function valid() {
|
||||
return !is_null($this->currentRow);
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of Iterator::rewind() - subclasses of MigrateSource should
|
||||
* implement performRewind() to do any class-specific setup for iterating
|
||||
* source records.
|
||||
*/
|
||||
public function rewind() {
|
||||
$this->activeMigration = Migration::currentMigration();
|
||||
$this->activeMap = $this->activeMigration->getMap();
|
||||
$this->numProcessed = 0;
|
||||
$this->numIgnored = 0;
|
||||
$this->highwaterField = $this->activeMigration->getHighwaterField();
|
||||
if ($this->activeMigration->getOption('idlist')) {
|
||||
$this->idList = explode(',', $this->activeMigration->getOption('idlist'));
|
||||
}
|
||||
else {
|
||||
$this->idList = array();
|
||||
}
|
||||
migrate_instrument_start(get_class($this) . ' performRewind');
|
||||
$this->performRewind();
|
||||
migrate_instrument_stop(get_class($this) . ' performRewind');
|
||||
$this->next();
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of Iterator::next() - subclasses of MigrateSource should
|
||||
* implement getNextRow() to retrieve the next valid source rocord to process.
|
||||
*/
|
||||
public function next() {
|
||||
$this->currentKey = NULL;
|
||||
$this->currentRow = NULL;
|
||||
migrate_instrument_start(get_class($this) . ' getNextRow');
|
||||
while ($row = $this->getNextRow()) {
|
||||
migrate_instrument_stop(get_class($this) . ' getNextRow');
|
||||
// Populate the source key for this row
|
||||
foreach ($this->activeMap->getSourceKey() as $field_name => $field_schema) {
|
||||
$this->currentKey[$field_name] = $row->$field_name;
|
||||
}
|
||||
|
||||
// Pick up the existing map row, if any, unless getNextRow() did it.
|
||||
if (!$this->mapRowAdded) {
|
||||
$map_row = $this->activeMap->getRowBySource($this->currentKey);
|
||||
// Add map info to the row, if present
|
||||
if ($map_row) {
|
||||
foreach ($map_row as $field => $value) {
|
||||
$field = 'migrate_map_' . $field;
|
||||
$row->$field = $value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// First, determine if this row should be passed to prepareRow(), or skipped
|
||||
// entirely. The rules are:
|
||||
// 1. If there's an explicit idlist, that's all we care about (ignore
|
||||
// highwaters and map rows).
|
||||
$prepared = FALSE;
|
||||
if (!empty($this->idList)) {
|
||||
if (in_array(reset($this->currentKey), $this->idList)) {
|
||||
// In the list, fall through.
|
||||
}
|
||||
else {
|
||||
// Not in the list, skip it
|
||||
$this->currentRow = NULL;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
// 2. If the row is not in the map (we have never tried to import it before),
|
||||
// we always want to try it.
|
||||
elseif (!isset($row->migrate_map_sourceid1)) {
|
||||
// Fall through
|
||||
}
|
||||
// 3. If the row is marked as needing update, pass it.
|
||||
elseif ($row->migrate_map_needs_update == MigrateMap::STATUS_NEEDS_UPDATE) {
|
||||
// Fall through
|
||||
}
|
||||
// 4. At this point, we have a row which has previously been imported and
|
||||
// not marked for update. If we're not using highwater marks, then we
|
||||
// will not take this row.
|
||||
elseif (empty($this->highwaterField)) {
|
||||
// No highwater, skip
|
||||
$this->currentRow = NULL;
|
||||
continue;
|
||||
}
|
||||
// 5. So, we are using highwater marks. Take the row if its highwater field
|
||||
// value is greater than the saved marked, otherwise skip it.
|
||||
else {
|
||||
// Call prepareRow() here, in case the highwaterField needs preparation
|
||||
if ($this->prepareRow($row) !== FALSE) {
|
||||
if ($row->{$this->highwaterField['name']} > $this->activeMigration->getHighwater()) {
|
||||
$this->currentRow = $row;
|
||||
break;
|
||||
}
|
||||
else {
|
||||
// Skip
|
||||
$this->currentRow = NULL;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else {
|
||||
$this->currentRow = NULL;
|
||||
}
|
||||
$prepared = TRUE;
|
||||
}
|
||||
|
||||
// Allow the Migration to prepare this row. prepareRow() can return boolean
|
||||
// FALSE to ignore this row.
|
||||
if (!$prepared) {
|
||||
if ($this->prepareRow($row) !== FALSE) {
|
||||
// Finally, we've got a keeper.
|
||||
$this->currentRow = $row;
|
||||
break;
|
||||
}
|
||||
else {
|
||||
$this->currentRow = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
migrate_instrument_stop(get_class($this) . ' getNextRow');
|
||||
if (!$this->currentRow) {
|
||||
$this->currentKey = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Give the calling migration a shot at manipulating, and possibly rejecting,
|
||||
* the source row.
|
||||
*
|
||||
* @return bool
|
||||
* FALSE if the row is to be skipped.
|
||||
*/
|
||||
protected function prepareRow($row) {
|
||||
migrate_instrument_start(get_class($this->activeMigration) . ' prepareRow');
|
||||
$return = $this->activeMigration->prepareRow($row);
|
||||
migrate_instrument_stop(get_class($this->activeMigration) . ' prepareRow');
|
||||
// We're explicitly skipping this row - keep track in the map table
|
||||
if ($return === FALSE) {
|
||||
$this->activeMigration->getMap()->saveIDMapping($row, array(NULL),
|
||||
MigrateMap::STATUS_IGNORED);
|
||||
$this->numIgnored++;
|
||||
$this->currentRow = NULL;
|
||||
$this->currentKey = NULL;
|
||||
}
|
||||
else {
|
||||
$return = TRUE;
|
||||
}
|
||||
$this->numProcessed++;
|
||||
return $return;
|
||||
}
|
||||
}
|
34
sites/all/modules/migrate/includes/team.inc
Normal file
34
sites/all/modules/migrate/includes/team.inc
Normal file
@@ -0,0 +1,34 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Info on migration team members. Display-only at the moment, but eventually
|
||||
* there should be notification features.
|
||||
*/
|
||||
|
||||
class MigrateTeamMember {
|
||||
protected $name;
|
||||
public function getName() {
|
||||
return $this->name;
|
||||
}
|
||||
|
||||
protected $emailAddress;
|
||||
public function getEmailAddress() {
|
||||
return $this->emailAddress;
|
||||
}
|
||||
|
||||
protected $group;
|
||||
public function getGroup() {
|
||||
return $this->group;
|
||||
}
|
||||
|
||||
public function __construct($name, $email_address, $group) {
|
||||
$this->name = $name;
|
||||
$this->emailAddress = $email_address;
|
||||
$this->group = $group;
|
||||
}
|
||||
|
||||
public function contact($subject, $text) {
|
||||
// TODO
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user