summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--CHANGELOG.txt1
-rw-r--r--includes/base.inc19
-rw-r--r--includes/group.inc109
-rw-r--r--includes/migration.inc4
-rw-r--r--migrate.drush.inc18
-rwxr-xr-xmigrate.info1
-rwxr-xr-xmigrate.module22
-rw-r--r--migrate_example/wine.inc40
8 files changed, 194 insertions, 20 deletions
diff --git a/CHANGELOG.txt b/CHANGELOG.txt
index 8d598e9..c462aa0 100644
--- a/CHANGELOG.txt
+++ b/CHANGELOG.txt
@@ -3,6 +3,7 @@ Next release
============
Features and enhancements
+- #719650 - Implemented ability to assign migrations to groups, and run by group.
- #1201762 - Implemented built-in caching for source counts, and flag to enable it.
- #1195802 - Added prepareRow() support for MSSQL plugin.
- #1195784 - Added verification of required extension to MSSQL plugin.
diff --git a/includes/base.inc b/includes/base.inc
index 72daf56..44448aa 100644
--- a/includes/base.inc
+++ b/includes/base.inc
@@ -45,6 +45,16 @@ abstract class MigrationBase {
}
/**
+ * The name of a migration group, used to collect related migrations.
+ *
+ * @var string
+ */
+ protected $group;
+ public function getGroup() {
+ return $this->group;
+ }
+
+ /**
* Detailed information describing the migration.
*
* @var string
@@ -284,9 +294,16 @@ abstract class MigrationBase {
/**
* General initialization of a MigrationBase object.
*/
- public function __construct() {
+ public function __construct($group = NULL) {
$this->machineName = $this->generateMachineName();
+ if (empty($group)) {
+ $this->group = MigrateGroup::getInstance('default');
+ }
+ else {
+ $this->group = $group;
+ }
+
// Record the memory limit in bytes
$limit = trim(ini_get('memory_limit'));
if ($limit == '-1') {
diff --git a/includes/group.inc b/includes/group.inc
new file mode 100644
index 0000000..920419b
--- /dev/null
+++ b/includes/group.inc
@@ -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];
+ }
+}
diff --git a/includes/migration.inc b/includes/migration.inc
index 8cc10f3..cb67077 100644
--- a/includes/migration.inc
+++ b/includes/migration.inc
@@ -122,8 +122,8 @@ abstract class Migration extends MigrationBase {
/**
* General initialization of a Migration object.
*/
- public function __construct() {
- parent::__construct();
+ public function __construct($group = NULL) {
+ parent::__construct($group);
}
/**
diff --git a/migrate.drush.inc b/migrate.drush.inc
index 3927d8f..72a136d 100644
--- a/migrate.drush.inc
+++ b/migrate.drush.inc
@@ -582,6 +582,13 @@ function drush_migrate_get_migrations($args) {
}
}
}
+ else if ($group = drush_get_option('group')) {
+ foreach ($migration_objects as $name => $migration) {
+ if (strtolower($group) != strtolower($migration->getGroup()->getName()) || !$migration->getEnabled()) {
+ unset($migration_objects[$name]);
+ }
+ }
+ }
else {
$named_migrations = array();
foreach (explode(',', $args) as $name) {
@@ -634,13 +641,18 @@ function drush_migrate_validate_common($args) {
$user = $user_one;
session_save_session(FALSE);
if (drush_get_option('all')) {
- if (!empty($args)) {
- return drush_set_error(NULL, dt('You must specify either a migration name or --all, not both'));
+ if (!empty($args) || drush_get_option('group')) {
+ return drush_set_error(NULL, dt('You must specify exactly one of a migration name, --all, or --group'));
+ }
+ }
+ else if (drush_get_option('group')) {
+ if (!empty($args) || drush_get_option('all')) {
+ return drush_set_error(NULL, dt('You must specify exactly one of a migration name, --all, or --group'));
}
}
else {
if (empty($args)) {
- return drush_set_error(NULL, dt('You must specify either a migration name or the --all option'));
+ return drush_set_error(NULL, dt('You must specify exactly one of a migration name, --all, or --group'));
}
$machine_names = explode(',', $args);
diff --git a/migrate.info b/migrate.info
index 7bf848e..350247b 100755
--- a/migrate.info
+++ b/migrate.info
@@ -12,6 +12,7 @@ files[] = includes/field_mapping.inc
files[] = includes/migration.inc
files[] = includes/destination.inc
files[] = includes/exception.inc
+files[] = includes/group.inc
files[] = includes/handler.inc
files[] = includes/map.inc
files[] = includes/source.inc
diff --git a/migrate.module b/migrate.module
index 5bdac4c..111828b 100755
--- a/migrate.module
+++ b/migrate.module
@@ -85,6 +85,28 @@ function migrate_migrations() {
}
}
}
+
+ // The migrations are now ordered according to their own dependencies - now order
+ // them by group
+ $groups = MigrateGroup::groups();
+ // Seed the final list by properly-ordered groups.
+ $final_migrations = array();
+ foreach ($groups as $name => $group) {
+ $final_migrations[$name] = array();
+ }
+
+ // Fill in the grouped list
+ foreach ($migrations as $machine_name => $migration) {
+ $final_migrations[$migration->getGroup()->getName()][$machine_name] = $migration;
+ }
+ // Then flatten the list
+ $migrations = array();
+ foreach ($final_migrations as $group_name => $group_migrations) {
+ foreach ($group_migrations as $machine_name => $migration) {
+ $migrations[$machine_name] = $migration;
+ }
+ }
+
return $migrations;
}
diff --git a/migrate_example/wine.inc b/migrate_example/wine.inc
index 170ab1c..02fc7b4 100644
--- a/migrate_example/wine.inc
+++ b/migrate_example/wine.inc
@@ -17,7 +17,17 @@ abstract class AdvancedExampleMigration extends Migration {
public $basicFormat;
public function __construct() {
- parent::__construct();
+ // TIP: Migrations can be organized into groups. In this case, all the migrations
+ // derived from AdvancedExampleMigration will be part of the 'wine' group.
+ // This enables us to easily run just the wine example migrations:
+ // drush migrate-import --group=wine
+ // The second argument to MigrateGroup::getInstance is an array of groups
+ // which should come before this when viewing migration statuses, or running
+ // migration operations using --all. Since the beer migrations in this module
+ // did not specify a group, it is in the 'default' group, so this constructor
+ // indicates that the wine migrations come after the beer migrations.
+ parent::__construct(MigrateGroup::getInstance('wine', array('default')));
+
$this->team = array(
new MigrateTeamMember('Jack Kramer', 'jkramer@example.com', t('Taster')),
new MigrateTeamMember('Linda Madison', 'lmadison@example.com', t('Winemaker')),
@@ -47,17 +57,13 @@ class WinePrepMigration extends MigrationBase {
public static $wasEnabled = FALSE;
public function __construct() {
- parent::__construct();
+ // Because we're derived directly from migrationBase rather than AdvancedExampleMigration,
+ // we must specify the group again here.
+ parent::__construct(MigrateGroup::getInstance('wine', array('default')));
+
$this->description = t('If auto_nodetitle is present, disable it for the duration');
- // TIP: Regular dependencies, besides enforcing (in the absence of --force)
- // the run order of migrations, affect the sorting of migrations on display.
- // You can use soft dependencies to affect just the display order when the
- // migrations aren't technically required to run in a certain order. In this
- // case, we want the wine migrations to appear after the beer migrations -
- // without this line, they would be intermingled due to their lack of
- // (formal) interdependencies.
- $this->softDependencies = array('BeerComment');
}
+
// Define isComplete(), returning a boolean, to indicate whether dependent
// migrations may proceed
public function isComplete() {
@@ -151,8 +157,14 @@ class WineBestWithMigration extends WineTermMigration {
class WineRoleMigration extends XMLMigration {
public function __construct() {
- parent::__construct();
+ parent::__construct(MigrateGroup::getInstance('wine', array('default')));
$this->description = t('XML feed (multi items) of roles (positions)');
+
+ // TIP: Regular dependencies, besides enforcing (in the absence of --force)
+ // the run order of migrations, affect the sorting of migrations on display.
+ // You can use soft dependencies to affect just the display order when the
+ // migrations aren't technically required to run in a certain order. In this
+ // case, we want the role migration to appear after the file migration.
$this->softDependencies = array('WineBestWith');
// There isn't a consistent way to automatically identify appropriate "fields"
@@ -295,7 +307,7 @@ class WineProducerMigration extends AdvancedExampleMigration {
*/
class WineProducerXMLMigration extends XMLMigration {
public function __construct() {
- parent::__construct();
+ parent::__construct(MigrateGroup::getInstance('wine', array('default')));
$this->description = t('XML feed of wine producers of the world');
$this->dependencies = array('WineRegion', 'WineUser');
@@ -365,7 +377,7 @@ class WineProducerXMLMigration extends XMLMigration {
*/
class WineProducerMultiXMLMigration extends XMLMigration {
public function __construct() {
- parent::__construct();
+ parent::__construct(MigrateGroup::getInstance('wine', array('default')));
$this->description = t('XML feed (multi items) of wine producers of the world');
$this->dependencies = array('WineRegion', 'WineUser');
@@ -671,7 +683,7 @@ class WineTableMigration extends AdvancedExampleMigration {
class WineFinishMigration extends MigrationBase {
public function __construct() {
- parent::__construct();
+ parent::__construct(MigrateGroup::getInstance('wine', array('default')));
$this->description = t('If auto_nodetitle is present and was previously enabled,
re-enable it');
$this->dependencies = array('WineComment');