Issue #1164530 Add messaging system to the content migration process. Display message...
authorKaren Stevenson
Sat, 21 May 2011 14:08:44 +0000 (09:08 -0500)
committerKaren Stevenson
Sat, 21 May 2011 14:08:44 +0000 (09:08 -0500)
modules/content_migrate/content_migrate.module
modules/content_migrate/includes/content_migrate.admin.inc
modules/content_migrate/includes/content_migrate.values.inc
modules/content_migrate/modules/content_migrate.number.inc
modules/content_migrate/modules/content_migrate.text.inc

index 90e2ace..6c409b5 100644 (file)
@@ -88,6 +88,12 @@ function content_migrate_storage_type($field_value) {
   }
   else {
     $instance_values = content_migrate_get_instance_values(NULL, $field_value['field_name']);
+    foreach ($instance_values as $bundle => $instance_value) {
+      if (isset($instance_value['messages'])) { 
+        $messages = array_merge($messages, $instance_value['messages']);    
+        unset($instance_values[$bundle]['messages']);
+      }
+    }
     if (count($instance_values) > 1) {
       $storage = CONTENT_DB_STORAGE_PER_FIELD;
     }
index adf1b3d..fca3870 100644 (file)
@@ -9,9 +9,11 @@
  * unable to be migrated due to missing modules.
  */
 function content_migrate_get_options() {
+
   $options = array('available' => array(), 'converted' => array(), 'missing' => array());
   
   $field_values = content_migrate_get_field_values();
+
   if (empty($field_values)) {
     drupal_set_message(t('There is no D6 field information in this database.'));
     return FALSE;
@@ -24,31 +26,36 @@ function content_migrate_get_options() {
   $available_modules = array_unique(array_merge(module_implements('field_info'), module_implements('field_widget_info')));
   
   foreach ($field_values as $field_name => $field_value) {
+    $messages = array();
     $bundles = array();
     $missing_module = !in_array($field_value['module'], $available_modules);
-    $missing_modules = $missing_module ? array($field_value['module']) : array();
+    if ($missing_module) {
+      $messages[] = '<span class="error">' . t("Missing field module: '@field'. This field cannot be migrated.", array('@field' => $field_value['module'])) . '</span>';
+    }
+    if (isset($field_value['messages'])) {
+      $messages = array_merge($messages, $field_value['messages']);
+      unset($field_value['messages']);
+    }
+
     $instance_values = content_migrate_get_instance_values(NULL, $field_name);
-    
+
     // Debug
     //dsm($field_value);
     //dsm($instance_values);
     
     foreach ($instance_values as $bundle => $instance_value) {
+      if (isset($instance_value['messages'])) { 
+        $messages = array_merge($messages, $instance_value['messages']);    
+        unset($instance_values[$bundle]['messages']);
+      }
       $bundles[] = $type_names[$bundle];
       $label = $instance_value['label'];
-      if (!in_array($instance_value['widget']['module'], $available_modules)) {
-        // A missing widget module is not fatal, but we should warn the user.
-        //$missing_module = TRUE;
-        if ($instance_value['widget']['module'] != $field_value['module']) {
-          $missing_modules[] = $instance_value['widget']['module'];
-        }
-      }
     }
     $data = array(
       0 => $field_name,
       1 => $field_value['type'],
-      2 => implode(', ', $bundles),
-      3 => empty($missing_modules) ? '' : t('Missing modules: @list', array('@list' => implode(', ', $missing_modules))),
+      2 => theme('item_list', array('items' => $bundles)),
+      3 => theme('item_list', array('items' => $messages)),
     );
     if (in_array($field_name, $new_fields)) {
       $options['converted'][$field_name] = $data;
@@ -85,7 +92,7 @@ function content_migrate_select($form, &$form_state) {
     '#collapsible' => TRUE,
     '#collapsed' => count($options['available']) < 1,
     '#title' => t('Available fields'),
-    '#description' => t('Fields that have not yet been migrated but are available for migration.'),
+    '#description' => t('Fields that have not yet been migrated but are available for migration. <strong>Please carefully read the messages next to each field before migrating it to understand changes that might be made.</strong>'),
   );
   $form['available']['data'] = array(
     '#type' => 'tableselect',
@@ -206,6 +213,8 @@ function _content_migrate_batch($field_names) {
  * Batch operation callback to create fields.
  */
 function _content_migrate_batch_process_create_fields($field_name, &$context) {
+  $messages = array();
+  $errors = array();
   $type_names = node_type_get_names();
   $allowed_fields = field_info_field_types();
   $allowed_widgets = field_info_widget_types();
@@ -213,6 +222,10 @@ function _content_migrate_batch_process_create_fields($field_name, &$context) {
   
   $context['message'] = t('"Creating field: %field', array('%field' => $field_name));
   $field_value = content_migrate_get_field_values($field_name);
+  if (isset($field_value['messages'])) {
+    $messages = $field_value['messages'];
+    unset($field_value['messages']);
+  }
   $instance_info = field_info_instances('node');
 
   // Create the field and store the new field 
@@ -225,7 +238,7 @@ function _content_migrate_batch_process_create_fields($field_name, &$context) {
       unset($field_value['db_storage']);   
       $field = field_create_field($field_value);
       $context['fields'][$field_name] = $field;
-      drupal_set_message(t("Created field @field_name", array('@field_name' => $field_name)));
+      $messages[] = t("Created field @field_name", array('@field_name' => $field_name));
     }
  
     // Create each of the new instances and store 
@@ -235,38 +248,39 @@ function _content_migrate_batch_process_create_fields($field_name, &$context) {
     foreach ($instance_values as $bundle => $instance_value) {
       try {
 
-        // Warn about missing or invalid widgets or formatters.
-        if (!array_key_exists($instance_value['widget']['type'], $allowed_widgets)) {
-          drupal_set_message(t('The @widget widget is not available for the @field field, setting to default widget.', array('@widget' => $instance_value['widget']['type'], '@field' => $field_name)), 'warning');
-        }
-
-        foreach ($instance_value['display'] as $view_mode => $settings) {
-          if (!array_key_exists( $settings['type'], $allowed_formatters)) {
-            drupal_set_message(t('The @formatter formatter used in the @view_mode view mode is not available for the @field field, setting to default formatter.', array('@formatter' => $settings['type'], '@view_mode' => $view_mode, '@field' => $field_name)), 'warning');
-          }
+        if (isset($instance_value['messages'])) { 
+          $messages = array_merge($messages, $instance_value['messages']);    
+          unset($instance_value['messages']);
         }
 
         if (!isset($instance_info[$bundle][$field_name])) {
           $instance = field_create_instance($instance_value); 
           $context['instances'][$field_name][$bundle] = $instance;
-          drupal_set_message(t("Created instance of @field_name in bundle @bundle.", array(
-            '@field_name' => $field_name, '@bundle' => $type_names[$bundle])));
+          $messages[] = t("Created instance of @field_name in bundle @bundle.", array(
+            '@field_name' => $field_name, '@bundle' => $type_names[$bundle]));
         }
         
       }
       catch (Exception $e) {
-        drupal_set_message(t('Error creating instance of @field_name in bundle @bundle.', array(
-          '@field_name' => $field_name, '@bundle' => $type_names[$bundle])), 'error');
-        drupal_set_message($e, 'error');
+        $errors[] = t('Error creating instance of @field_name in bundle @bundle.', array(
+          '@field_name' => $field_name, '@bundle' => $type_names[$bundle]));
+        $errors[] = $e;
       }
     }
   }
   catch (Exception $e) {
-    drupal_set_message(t("Error creating field @field_name", array('@field_name' => $field_name)), 'error'); 
-    drupal_set_message($e, 'error');
+    $errors[] = t("Error creating field @field_name", array('@field_name' => $field_name)); 
+    $errors[] = $e;
   }
   field_info_cache_clear();
 
+  foreach ($messages as $message) {
+    drupal_set_message($message, 'warning');
+  }
+  foreach ($errors as $error) {
+    drupal_set_message($error, 'error');
+  }
+
   $context['finished'] = TRUE;
 } 
 
@@ -280,7 +294,13 @@ function _content_migrate_batch_process_migrate_data($field_name, &$context) {
   if (!isset($context['sandbox']['progress'])) {
 
     $field_value = content_migrate_get_field_values($field_name);
+    if (isset($field_value['messages'])) {
+      unset($field_value['messages']);
+    }
     $instance_values = content_migrate_get_instance_values(NULL, $field_name);
+    if (isset($instance_values['messages'])) {
+      unset($instance_values['messages']);
+    }
     $types = array();
     foreach ($instance_values as $bundle => $instance_value) {
       $types[] = $bundle;
index beee5b7..9189a84 100644 (file)
@@ -21,15 +21,33 @@ function _content_migrate_get_field_values($field_name = NULL) {
     $query = db_select('content_node_field', 'nf', array('fetch' => PDO::FETCH_ASSOC));
     $node_instance_alias = $query->join('content_node_field_instance', 'ni', 'ni.field_name=nf.field_name');
     $result = $query
-      ->fields($node_instance_alias, array('widget_module', 'widget_type', 'widget_settings', 'display_settings'))
+      ->fields($node_instance_alias, array('type_name', 'widget_module', 'widget_type', 'widget_settings', 'display_settings'))
       ->fields('nf')
+      ->orderBy('type_name')
       ->execute();
     
     foreach ($result as $row) {
       $field_value = $row;
     
+      $query2 = db_select('content_node_field_instance', 'nfi', array('fetch' => PDO::FETCH_ASSOC));
+      $result2 = $query2
+        ->fields('nfi')
+        ->orderBy('type_name')
+        ->condition('field_name', $field_value['field_name'])
+        ->execute();
+
+      $widget_types = array();
+      foreach ($result2 as $row2) {
+        $widget_types[] = $row2['widget_type'];
+      }
+      $widget_types = array_unique($widget_types);
+      if (count($widget_types) > 1) {
+        $field_value['messages'][] = '<span class="error">' . t("Caution: The '@field' field is a shared field that uses different widgets. The '@widget' widget is sometimes used to determine the destination field type for the new field. The migration may not work correctly if other widgets used by this shared field would create different results.", array('@field' => $field_value['field_name'], '@widget' => $row['widget_type'])) .'</span>';
+      }
+
       // Pass instance settings to the field, in case they are needed.
       $instance_value = array(
+        'bundle' => $row['type_name'],
         'widget' => array(
           'type' => $row['widget_type'],
           'module' => $row['widget_module'],
@@ -95,7 +113,13 @@ function _content_migrate_get_instance_values($bundle = NULL, $field_name = NULL
   $instance_values = &drupal_static(__FUNCTION__);
 
   if (empty($instance_values) && db_table_exists('content_node_field_instance')) {
+
+    $allowed_fields = field_info_field_types();
+    $allowed_widgets = field_info_widget_types();
+    $allowed_formatters = field_info_formatter_types();
+  
     $instance_values = array();
+  
     $query = db_select('content_node_field_instance', 'ni', array('fetch' => PDO::FETCH_ASSOC));
     $node_field_alias = $query->join('content_node_field', 'nf', 'ni.field_name=nf.field_name');
     $result = $query
@@ -106,7 +130,8 @@ function _content_migrate_get_instance_values($bundle = NULL, $field_name = NULL
     
     foreach ($result as $row) { 
       $instance_value = $row;
-      
+      $instance_value['messages'] = array();
+
       // Pass field settings to the instance, in case they are needed.
       $field_value = array(
         'require' => $instance_value['required'],
@@ -150,6 +175,7 @@ function _content_migrate_get_instance_values($bundle = NULL, $field_name = NULL
       // Build display values.
       $instance_value['display'] = array();
       $label = $instance_value['display_settings']['label'];
+      $missing_formatters = array();
       foreach ($instance_value['display_settings'] as $context => $settings) {
         if ($context == 'label') {
           continue;
@@ -168,7 +194,7 @@ function _content_migrate_get_instance_values($bundle = NULL, $field_name = NULL
         $instance_value['display'][$context]['module'] = $instance_value['widget_module'];
 
       }
-      
+
       // Unset unneeded values.
       unset($instance_value['type_name'], $instance_value['global_settings'], $instance_value['widget_settings'], $instance_value['display_settings'], $instance_value['widget_module'], $instance_value['widget_active']);
       
@@ -181,6 +207,21 @@ function _content_migrate_get_instance_values($bundle = NULL, $field_name = NULL
       // Get rid of this value once CCK or some other module has handled it.
       if (isset($instance_value['widget']['settings']['default_value_php'])) unset($instance_value['widget']['settings']['default_value_php']);
 
+      // Warn about missing or invalid widgets.
+      if (!array_key_exists($instance_value['widget']['type'], $allowed_widgets)) {
+        $instance_value['messages'][] = t("Missing widget: The '@widget' widget is not available for the @field field, it will be set to the default widget.", array('@widget' => $instance_value['widget']['type'], '@field' => $instance_value['field_name']));
+      }
+
+      // Warn about missing or invalid formatters.
+      foreach ($instance_value['display'] as $context => $settings) {
+        if ($settings['type'] != 'default' && !array_key_exists($settings['type'], $allowed_formatters)) {
+          $missing_formatters[$settings['type']][] = $context;
+        }
+      }
+      foreach ($missing_formatters as $formatter => $context) {
+        $instance_value['messages'][] = t("Missing formatter: The '@formatter' formatter used in @view_mode view modes for the @field field is not available, these displays will be reset to the default formatter.", array('@formatter' => $formatter, '@view_mode' => count($context), '@field' => $instance_value['field_name']));
+      }
+
       // Add instance information to instance array.
       $instance_values['instances'][$instance_value['bundle']][$instance_value['field_name']] = $instance_value;
       $instance_values['fields'][$instance_value['field_name']][$instance_value['bundle']] = $instance_value;
index 9417b3e..0115f70 100644 (file)
@@ -37,14 +37,17 @@ function content_migrate_number_field_alter(&$field_value, $instance_value) {
         case 'optionwidgets_buttons':
         case 'optionwidgets_select':
           if ($field_value['type'] == 'number_integer') {
+            $field_value['messages'][] = t("Changed field type: The '@field' field uses a '@widget' widget. The field type will be changed from '@type' to 'list_integer'.", array('@type' => $field_value['type'], '@field' => $field_value['field_name'], '@widget' => $instance_value['widget']['type']));
             $field_value['type'] = 'list_integer';
           }
           else {
+            $field_value['messages'][] = t("Changed field type: The '@field' field uses a '@widget' widget. The field type will be changed from '@type' to 'list_float'.", array('@type' => $field_value['type'], '@field' => $field_value['field_name'], '@widget' => $instance_value['widget']['type']));
             $field_value['type'] = 'list_float';
           }
           $field_value['module'] = 'list';
           break;
         case 'optionwidgets_onoff':
+          $field_value['messages'][] = t("Changed field type: The '@field' field uses a '@widget' widget. The field type will be changed from '@type' to 'list_boolean'.", array('@type' => $field_value['type'], '@field' => $field_value['field_name'], '@widget' => $instance_value['widget']['type']));
           $field_value['type'] = 'list_boolean';
           $field_value['module'] = 'list';
           break;
index 7ee635f..6855e86 100644 (file)
@@ -20,29 +20,53 @@ function content_migrate_text_field_alter(&$field_value, $instance_value) {
       // Text fields are translatable.      
       $field_value['translatable'] = TRUE;
 
-      // The max_length field can no longer be empty 
-      // or it will create a SQL error.
-      if (empty($field_value['settings']['max_length'])) {
-        $field_value['type'] = 'text_long';
-        unset($field_value['settings']['max_length']);
-      }
-
-      // Text fields using optionwidgets are
-      // now List fields.
       switch ($instance_value['widget']['type']) {
+
+        // Text fields using optionwidgets are
+        // now List fields.
         case 'optionwidgets_buttons':
         case 'optionwidgets_select':
+          $field_value['messages'][] = t("Changed field type: The '@field' field uses a '@widget' widget. The field type will be changed from '@type' to 'list_text'.", array('@type' => $field_value['type'], '@field' => $field_value['field_name'], '@widget' => $instance_value['widget']['type']));
           $field_value['type'] = 'list_text';
           $field_value['module'] = 'list';
+          // Lists don't have a max_length setting.
+          if (isset($field_value['settings']['max_length'])) {
+            unset($field_value['settings']['max_length']);
+          }
           break;
 
         case 'optionwidgets_onoff':
+          $field_value['messages'][] = t("Changed field type: The '@field' field uses a '@widget' widget. The field type will be changed from '@type' to 'list_boolean'.", array('@type' => $field_value['type'], '@field' => $field_value['field_name'], '@widget' => $instance_value['widget']['type']));
           $field_value['type'] = 'list_boolean';
           $field_value['module'] = 'list';
+          // Lists don't have a max_length setting.
+          if (isset($field_value['settings']['max_length'])) {
+            unset($field_value['settings']['max_length']);
+          }
           break;
 
+        // The max_length field can no longer be empty 
+        // or it will create a SQL error. There also have been
+        // changes to the way text fields and widgets are configured.
+        // In D6, if you left max_length empty CCK would create a long_text field,
+        // even if you were using a textfield widget. In D7 it is not
+        // possible to have a long_text field with a textfield widget.
+        // We are now forced to figure out what to do with this data.
+    
+        // It is so easy to leave the length unset that it is likely that any
+        // any field with a missing length that uses a textfield widget 
+        // was intended to be a varchar field, so we will make that change.    
         case 'text_textarea':
+          if (empty($field_value['settings']['max_length'])) {
+            $field_value['type'] = 'text_long';
+          }
+          break;
         case 'text_textfield':
+          if (empty($field_value['settings']['max_length'])) {
+            $field_value['type'] = 'text';
+            $field_value['settings']['max_length'] = 255;
+            $field_value['messages'][] = t("Invalid field/widget combination: The field '@field' in the bundle '@bundle' is an unlimited length field using a textfield widget, not allowed in D7. The field length will be set to 255.", array('@field' => $field_value['field_name'], '@bundle' => $instance_value['bundle']));
+          }
           break;
 
       }