Index: migrate/hosting_migrate.module
===================================================================
RCS file: /cvs/drupal/contributions/modules/hosting/migrate/hosting_migrate.module,v
retrieving revision 1.24
diff -u -p -r1.24 hosting_migrate.module
--- migrate/hosting_migrate.module	23 Sep 2009 13:11:34 -0000	1.24
+++ migrate/hosting_migrate.module	25 Sep 2009 12:28:54 -0000
@@ -1,17 +1,10 @@
 <?php
+// $Id$
 
-function hosting_migrate_hosting_tasks($type, $task = null) {
-  $options = array();
+/**
+ * @file Migration forms for Aegir
+ */
 
-  if ($type == 'site') {
-    $options['migrate'] = array(
-      'title' => t('Migrate'),
-      'description' => t('Move the site to a new platform.'),
-      'weight' => 7
-    );
-  }
-  return $options;
-}
 
 
 function hosting_migrate_perm() {
@@ -30,18 +23,179 @@ function hosting_migrate_menu() {
     'type' => MENU_CALLBACK
   );
 
+  $items['node/%hosting_task_platform/task_migrate'] = array(
+    'title' => t('Migrate'),
+    'description' => t('Migrate sites to a new platform'),
+    'page callback' => 'drupal_get_form',
+    'page arguments' => array('hosting_migrate_platform', 1),
+    'access arguments' => array('access content'),
+    'type' => MENU_LOCAL_TASK,
+    'weight' => ($info['weight']) ? $info['weight'] : 0, 
+  );
+
+ return $items;
+}
+
+/**
+ * Implementation of hook_hosting_tasks()
+ */
+function hosting_migrate_hosting_tasks($type, $task = null) {
+  $options = array();
+
+  if ($type == 'site') {
+    $options['migrate'] = array(
+      'title' => t('Migrate'),
+      'description' => t('Move the site to a new platform.'),
+      'weight' => 7
+    );
+  }
+  return $options;
+}
+
+/**
+ * Batch migration of sites between platforms
+ */
+function hosting_migrate_platform($form_state, $node) {
+  $step = isset($form_state['storage']['step']) ? $form_state['storage']['step'] : 1;
+
+  // Step 1 - choose target platform
+  if ($step == 1) {
+    $platforms = _hosting_get_platforms();
+    unset($platforms[$node->nid]);
+    $form['#current_platform'] = $node;
+    $form['target_platform'] = array(
+      '#type' => 'radios',
+      '#required' => TRUE,
+      '#title' => t('Platform'),
+      '#description' => t('Choose where you want to migrate the sites on this platform to'),
+      '#options' => $platforms,
+    );
+    $form['status'] = array('#type' => 'value');
+  }
 
-  return $items;
+  // Step 2 - review sites that pass or fail the requirements to be migrated
+  if ($step == 2) {
+    $title = array(
+      'passed' => t("The following sites will be migrated"),
+      'failed' => t("The following sites will not be migrated")
+    );
+    foreach (array('passed', 'failed') as $type) {
+      if (sizeof($form_state['storage'][$type])) {
+        foreach ($form_state['storage'][$type] as $site_id => $url) {
+          $form['output'][$type]['title'] = array(
+            '#type' => 'markup',
+            '#value' => '<h2>' . $title[$type] . '</h2>',
+          );
+          $status = $form_state['storage']['status'][$site_id];
+
+          $description = t("Upgrades: !upgrades, Warnings: !missing, Errors: !errors", array(
+            '!upgrades' => $status['upgrade'],
+            '!missing' => $status['missing'],
+            '!errors' => $status['error']));
+
+          $form['output'][$type][$site_id] = array(
+            '#type' => 'item',
+            '#title' => $url,
+            '#description' => $description,
+          );
+        }  
+      }
+    }
+  }
+  $form['submit'] = array(
+    '#type' => 'submit',
+    '#value' => 'Submit',
+  );
+  return $form;
 }
 
+/**
+ * Implementation of hook_submit()
+ */
+function hosting_migrate_platform_submit($form, &$form_state) {
+  $step = isset($form_state['storage']['step']) ? $form_state['storage']['step'] : 1;
+  switch ($step) {
+    case 1:
+      $form_state['storage']['target_platform'] = $form_state['values']['target_platform']; 
+      $max_per_batch = 5;
+      $result = db_query("SELECT nid FROM  {hosting_site}  WHERE platform = %d AND status = %d", $form['#current_platform']->nid, HOSTING_SITE_ENABLED);
+      $operations = array();
+      while ($site = db_fetch_object($result)) {
+        $operations[] = array('hosting_migrate_platform_batch', 
+          array($site->nid, $form_state['values']['target_platform'], $form_state)); 
+      }
+      if (sizeof($operations)) {
+        $batch = array(
+          'operations' => $operations,
+          'finished' => 'hosting_migrate_platform_finished',
+          'title' => t('Checking for sites that can be migrated.'),
+          'init_message' => t('Retrieving list of sites.'),
+          'progress_message' => t('Evaluated @current out of @total sites.'),
+          'error_message' => t('Bulk migration has encountered an error.'),
+        );
+        batch_set($batch);
+      } 
+      break;
+    case 2:
+      if ($form_state['storage']['passed']) {
+        foreach ($form_state['storage']['passed'] as $nid => $url) {
+          hosting_add_task($nid, 'migrate', array('target_platform' => $form_state['storage']['target_platform']));
+        }
+        $form_state['redirect'] = 'node/' . $form_state['storage']['target_platform'];
+        unset($form_state['rebuild']);
+        unset($form_state['storage']);
+        drupal_set_message(t('The sites have been added to the task queue to be migrated'));
+        return false; 
+        // this does not seem to work ?
+        break;
+      }
+      else {
+        form_set_error('', t('Unmet site dependencies prevent a batch migration to this target platform.'));
+      }
+  }
+  $form_state['storage']['step'] = $step + 1;
+}
 
+/**
+ * Batch comparison of site packages between platforms to determine
+ * if the site can be migrated to the target platform or not.
+ */
+function hosting_migrate_platform_batch($site_id, $target_platform, &$context) {
+  if (!isset($context['sandbox']['progress'])) {
+    $context['sandbox']['progress'] = 0;
+  }
 
+  $site = node_load($site_id);
+  $batch =& batch_get();
+  // Determine whether the install profile is available on the target platform
+  $profile_instance = hosting_package_instance_load(
+    array('i.rid' => $target_platform, 
+          'r.type' => 'platform',
+          'n.nid' => $site->profile));
+  if ($profile_instance) {
+    $status = hosting_package_comparison($site->nid, $profile_instance->iid);
+    $batch['form_state']['storage']['status'][$site->nid] = $status;
+    // If there were no errors, this site passes and can be migrated
+    if (!$status['error']) {
+      $batch['form_state']['storage']['passed'][$site->nid] = $site->title;
+      return true;
+    }
+  }
+  $batch['form_state']['storage']['failed'][$site->nid] = $site->title;
+}
+
+/**
+ * Implementation of hook_validate()
+ */
 function hosting_task_migrate_form_validate($form, &$form_state) {
   if (!$form_state['values']['parameters']['target_platform'] || $form_state['values']['parameters']['hidden']) {
     form_set_error('parameters][target_platform', t('You may not select your current platform to migrate your site to.'));
   }
 }
 
+/**
+ * Implementation of hook_theme()
+ */
 function hosting_migrate_theme($existing, $type, $theme, $path) {
   return array(
   'hosting_migrate_comparison' => array(
@@ -49,6 +203,9 @@ function hosting_migrate_theme($existing
   ));
 }
 
+/**
+ * Implementation of hook_form()
+ */
 function hosting_task_migrate_form($node) {
 
   $packages = array();
@@ -104,24 +261,11 @@ function hosting_task_migrate_form($node
 
   $form['#node'] = $node;
   return $form;
-  $table = array();
-
-  if (sizeof($options)) {
-    $form['target_platform'] = array(
-      '#type' => 'radios',
-      '#title' => t('Migrate to'),
-      '#options' => $options,
-      '#required' => TRUE
-    );
-  }
-  else {
-    $form['target_text'] = array('#type' => 'item',
-      '#value' => t('<strong>No valid platforms to migrate to.</strong>')
-    );
-  }
-  return $form;
 }
 
+/**
+ * Compare package schema versions between the current and target platform in temp tables
+ */
 function hosting_migrate_comparison($current, $target) {
 
   _hosting_package_temporary_table("current", $current);
