More tweaking of content migrate script, starting to work correctly for at least...
[project/cck.git] / modules / content_migrate / content_migrate.module
index 4556252..0af148f 100644 (file)
@@ -3,12 +3,15 @@
 /**
  * @file
  * Code For D6 to D7 field update.
+ * 
+ * Modules can implement hook_content_migrate_field_alter()
+ * and hook_content_migrate_instance_alter()
  */
 define('CONTENT_DB_STORAGE_PER_FIELD', 0);
 define('CONTENT_DB_STORAGE_PER_CONTENT_TYPE', 1);
 
 /**
- * Implementation of hook_menu().
+ * Implements hook_menu().
  */
 function content_migrate_menu() { 
   // Demo page.
@@ -39,7 +42,9 @@ function content_migrate_get_field_values($field_name = NULL) {
   if (empty($field_values) && db_table_exists('content_node_field')) {
     $field_values = array();
     $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_type'))
       ->fields('nf')
       ->execute();
     
@@ -47,7 +52,7 @@ function content_migrate_get_field_values($field_name = NULL) {
       $field_value = $row;
     
       // All Drupal 6 fields were attached to nodes.
-      $field_value['entity_type'] = 'node';
+      $field_value['entity_types'] = array('node');
     
       $field_value['cardinality'] = $field_value['multiple'] != 1 ? $field_value['multiple'] : FIELD_CARDINALITY_UNLIMITED;
       
@@ -59,16 +64,16 @@ function content_migrate_get_field_values($field_name = NULL) {
       $field_value['settings'] = array_merge($default_settings, unserialize($field_value['global_settings']));
     
       unset($field_value['multiple'], $field_value['global_settings'], $field_value['required'], $field_value['db_columns']);
-    
-      // TODO Move this to a hook_content_migrate_field_alter on behalf of text module.
-      // The max_length field can no longer be empty or it will create a SQL error.
-      if ($field_value['type'] == 'text' && empty($field_value['settings']['max_length'])) {
-        $field_value['settings']['max_length'] = 255;
-      }
             
       // Let modules change these values.
       drupal_alter('content_migrate_field', $field_value);
-    
+      
+      // We left the widget type in the $field_value so modules
+      // could adjust the field based on that information.
+      // Needed so optionwidgets can change the field type
+      // from text or numeric to list. 
+      unset($field_value['widget_type']);
+      
       // We retain $field_value['columns'] and $field_value['db_storage']
       // even though they are not used or different in D7 
       // so we can find the old table information.
@@ -101,13 +106,19 @@ function content_migrate_get_instance_values($bundle = NULL, $field_name = NULL)
     $node_field_alias = $query->join('content_node_field', 'nf', 'ni.field_name=nf.field_name');
     $result = $query
       ->fields('ni')
-      ->fields($node_field_alias, array('required', 'type'))
+      ->fields($node_field_alias, array('required'))
       ->orderBy('label', 'ASC')
       ->execute();
     
-    foreach ($result as $row) {
-      $field_type = $row['type'];   
+    foreach ($result as $row) { 
       $instance_value = $row;
+      
+      // The instance has the same module as the field,
+      // not the widget. May have been altered
+      // from the original values, so get the altered
+      // field values.
+      $field_value = content_migrate_get_field_values($row['field_name']);
+      $instance_value['module'] = $field_value['module'];
     
       // All Drupal 6 instances were attached to nodes.
       $instance_value['entity_type'] = 'node';
@@ -120,8 +131,6 @@ function content_migrate_get_instance_values($bundle = NULL, $field_name = NULL)
       // Build instance values.
       $instance_value['bundle'] = $instance_value['type_name'];
       $instance_value['active'] = $instance_value['widget_active'];
-      $instance_value['module'] = $instance_value['widget_module'];
-      $instance_value['type']   = $instance_value['widget_type'];
       $instance_value['default_value'] = $instance_value['widget_settings']['default_value'];
       
       // Core does not support this, but retain it so 
@@ -135,9 +144,9 @@ function content_migrate_get_instance_values($bundle = NULL, $field_name = NULL)
       // TODO Some widget types have been renamed in D7.
       $instance_value['widget']['type']     = $instance_value['widget_type'];
       $instance_value['widget']['weight']   = $instance_value['weight'];
-      $instance_value['widget']['module']   = $instance_value['module'];
+      $instance_value['widget']['module']   = $instance_value['widget_module'];
     
-      $default_settings = field_info_widget_settings($row['type']);
+      $default_settings = field_info_widget_settings($field_value['type']);
       $instance_value['widget']['settings'] = array_merge($default_settings, $instance_value['widget_settings']);
     
       // Build display values.
@@ -147,14 +156,15 @@ function content_migrate_get_instance_values($bundle = NULL, $field_name = NULL)
       foreach ($instance_value['display'] as $context => $settings) {
         $instance_value['display'][$context]['label'] = $label['format'];
         
-        // TODO the format used in D6 does not match the formatter in D7.
+        // The format used in D6 may not match the formatter in D7.
+        // Fix it using drupal_alter().
         $instance_value['display'][$context]['type'] = $settings['format'];
         $instance_value['display'][$context]['settings'] = field_info_formatter_settings($settings['format']);
         unset($instance_value['display'][$context]['exclude'], $instance_value['display'][$context]['format']);
       }
     
       // 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'], $instance_value['widget_type'], $instance_value['widget']['settings']['default_value'], $instance_value['widget']['settings']['default_value_php']);
+      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'], $instance_value['widget']['settings']['default_value'], $instance_value['widget']['settings']['default_value_php']);
     
       // Let modules change these values.
       drupal_alter('content_migrate_instance', $instance_value);
@@ -188,8 +198,7 @@ function content_migrate_get_instance_values($bundle = NULL, $field_name = NULL)
  * @param $instance_value
  */
 function content_migrate_old_table($field_value, $instance_value) {
-  
-  $storage = content_migrate_storage_type($field_value, $instance_value);
+  $storage = content_migrate_storage_type($field_value);
   switch ($storage) {
     case CONTENT_DB_STORAGE_PER_CONTENT_TYPE :
       $name = $instance_value['bundle'];
@@ -207,11 +216,12 @@ function content_migrate_old_table($field_value, $instance_value) {
  * @param $field_value
  * @param $instance_value
  */
-function content_migrate_storage_type($field_value, $instance_value) {
-  if (!empty($field_value['db_storage'])) {
+function content_migrate_storage_type($field_value) {
+  $storage = CONTENT_DB_STORAGE_PER_CONTENT_TYPE;
+  if (isset($field_value['db_storage'])) {
     return $field_value['db_storage'];
   }
-  elseif ($field_value['cardinality'] > 0) {
+  elseif ($field_value['cardinality'] > 0 || $field_value['cardinality'] == FIELD_CARDINALITY_UNLIMITED) {
     $storage = CONTENT_DB_STORAGE_PER_FIELD;
   }
   else {
@@ -220,7 +230,6 @@ function content_migrate_storage_type($field_value, $instance_value) {
       $storage = CONTENT_DB_STORAGE_PER_FIELD;
     }
   }
-  $storage = CONTENT_DB_STORAGE_PER_CONTENT_TYPE;
   return $storage;
 }
 
@@ -268,14 +277,212 @@ function content_migrate_old_columns($field_value, $instance_value) {
  * @return unknown
  */
 function content_migrate_new_columns($field) {
+  $columns = array();
   if (empty($field['storage']['details'])) {
-    $columns = array();
     foreach ($field['columns'] as $col => $values) {
       $columns[] = $field['field_name'] .'_'. $col;
     }
     return $columns;
   }
   else {
-    return $field['storage']['details']['sql'][FIELD_LOAD_CURRENT];
+    foreach ($field['storage']['details']['sql'][FIELD_LOAD_CURRENT] as $table => $cols) {
+      foreach ($cols as $col) {
+        $columns[] = $col;
+      }
+    }
+    return $columns;
+  }
+}
+
+/**
+ * Implements hook_content_migrate_field_alter().
+ * 
+ * Use this to tweak the conversion of field settings
+ * from the D6 style to the D7 style for specific
+ * situations not handled by basic conversion,
+ * as when field types or settings are changed.
+ * 
+ * $field_value['widget_type'] is available to
+ * see what widget type was originally used.
+ */
+function content_migrate_content_migrate_field_alter(&$field_value) {
+  
+  switch ($field_value['type']) {
+    case 'text':
+      
+      // 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['settings']['max_length'] = 255;
+      }
+      
+      // Text fields using optionwidgets are
+      // now List fields.
+      switch ($field_value['widget_type']) {
+        case 'optionwidgets_buttons':
+        case 'optionwidgets_select':
+          $field_value['type'] = 'list_text';
+          $field_value['module'] = 'list';
+          break;
+        case 'optionwidgets_onoff':
+          $field_value['type'] = 'list_boolean';
+          $field_value['module'] = 'list';
+          break;  
+        case 'text_textarea':
+          $field_value['type'] = 'text_long';
+          unset($field_value['settings']['max_length']);
+          break;  
+      }
+      break;
+   
+    case 'number_integer':
+    case 'number_decimal':
+    case 'number_float':  
+      
+      // Changed name of setting from 'decimal' to 
+      // 'decimal_separator'.
+      if (isset($field_value['settings']['decimal'])) {
+        $field_value['settings']['decimal_separator'] = $field_value['settings']['decimal'];
+        unset($field_value['settings']['decimal']);
+      }
+      // Add a decimal_separator setting to floats.
+      if ($field_value['type'] == 'number_float') {
+        $field_value['settings']['decimal_separator'] = '.';
+      }
+      
+      // Number fields using optionwidgets are
+      // now List fields.
+      switch ($field_value['widget_type']) {
+        case 'optionwidgets_buttons':
+        case 'optionwidgets_select':
+          $field_value['type'] = 'list_number';
+          $field_value['module'] = 'list';
+          break;
+        case 'optionwidgets_onoff':
+          $field_value['type'] = 'list_boolean';
+          $field_value['module'] = 'list';
+          break;  
+      }
+      break;  
   }
 }
+
+/**
+ * Implements hook_content_migrate_instance_alter().
+ * 
+ * Use this to tweak the conversion of instance or widget settings
+ * from the D6 style to the D7 style for specific
+ * situations not handled by basic conversion, as when
+ * formatter or widget names or settings are changed.
+ */
+function content_migrate_content_migrate_instance_alter(&$instance_value) {
+  //$field = content_migrate_get_field_values($instance_value['field_name']);
+  
+  switch ($instance_value['widget']['module']) {
+    // Optionswidgets module became Options module
+    // and widget type names changed.
+    case ('optionwidgets'):
+      $replace = array(
+        'optionwidgets_select' => 'options_select',
+        'optionwidgets_buttons' => 'options_buttons',
+        'optionwidgets_onoff' => 'options_onoff',
+      );
+      $instance_value['widget']['module'] = 'options';
+      $instance_value['widget']['type'] = strtr($instance_value['widget']['type'], $replace);
+      break;
+  }
+  
+  switch ($instance_value['module']) {
+    case 'text':
+      // The formatter names changed, all are prefixed
+      // with 'text_'.
+      foreach ($instance_value['display'] as $context => $settings) {
+        $instance_value['display'][$context]['type'] = 'text_'. $settings['type'];
+      }     
+      break;
+      
+    case 'number':    
+      // The number formatters and formatter settings
+      // have changed.
+      $new_type = array(
+        'unformatted' => 'number_unformatted',
+        'default' => 'number_decimal',
+        'us_0' => 'number_integer',
+        'us_1' => 'number_decimal',
+        'us_2' => 'number_decimal',
+        'be_0' => 'number_integer',
+        'be_1' => 'number_decimal',
+        'be_2' => 'number_decimal',        
+        'fr_0' => 'number_integer',
+        'fr_1' => 'number_decimal',
+        'fr_2' => 'number_decimal',      
+      );
+      $new_settings = array(
+        'default' => array(
+          'thousand_separator' => '',
+          'decimal_separator' => '.',
+          'scale' => 0,
+          'prefix_suffix' => TRUE,
+        ),
+        'us_0' => array(
+          'thousand_separator' => ',',
+          'decimal_separator' => '.',
+          'scale' => 0,
+          'prefix_suffix' => TRUE,
+        ),        
+        'us_1' => array(
+          'thousand_separator' => ',',
+          'decimal_separator' => '.',
+          'scale' => 1,
+          'prefix_suffix' => TRUE,
+        ),
+        'us_2' => array(
+          'thousand_separator' => ',',
+          'decimal_separator' => '.',
+          'scale' => 2,
+          'prefix_suffix' => TRUE,
+        ),  
+        'be_0' => array(
+          'thousand_separator' => '',
+          'decimal_separator' => ',',
+          'scale' => 0,
+          'prefix_suffix' => TRUE,
+        ),        
+        'be_1' => array(
+          'thousand_separator' => '.',
+          'decimal_separator' => ',',
+          'scale' => 1,
+          'prefix_suffix' => TRUE,
+        ),
+        'be_2' => array(
+          'thousand_separator' => '.',
+          'decimal_separator' => ',',
+          'scale' => 2,
+          'prefix_suffix' => TRUE,
+        ),         
+        'fr_0' => array(
+          'thousand_separator' => '',
+          'decimal_separator' => ', ',
+          'scale' => 0,
+          'prefix_suffix' => TRUE,
+        ),        
+        'fr_1' => array(
+          'thousand_separator' => ' ',
+          'decimal_separator' => ', ',
+          'scale' => 1,
+          'prefix_suffix' => TRUE,
+        ),
+        'fr_2' => array(
+          'thousand_separator' => ' ',
+          'decimal_separator' => ', ',
+          'scale' => 2,
+          'prefix_suffix' => TRUE,
+        ),                          
+      );
+      foreach ($instance_value['display'] as $context => $settings) {
+        $instance_value['display'][$context]['type'] = $new_type[$settings['type']];
+        $instance_value['display'][$context]['settings'] = $new_settings[$settings['type']];
+      }
+      break;
+  }
+}
\ No newline at end of file