Issue #1249214 by yched: Translate D6 core numeric 'build modes'
[project/cck.git] / cck.module
index 8d53053..8f9a25e 100644 (file)
 <?php
-// $Id$
 /**
  * @file
- * Allows administrators to associate custom fields to content types.
+ * Allows administrators to use php code snippets to
+ * define allowed values or default values. The snippets
+ * are stored in a database table and retrieved in
+ * callback functions.
  */
 
 /**
- * Implementation of hook_help().
- */
-function cck_help($path, $arg) {
-  switch ($path) {
-    case 'admin/help#cck':
-      // TODO Rewrite help to refer to only the appropriate functions and files for the new system.
-      return '';
-    case 'admin/build/fields':
-      return t('The list below shows all fields currently in use for easy reference.');
-
-  }
-}
-
-/**
  * Implementation of hook_perm().
  */
-function cck_perm() {
-  return array('Use PHP input for field settings (dangerous - grant with care)');
-}
-
-/**
- * Implementation of hook_init().
- */
-function cck_init() {
-  // TODO D7 : be smarter ?
-  drupal_add_css(drupal_get_path('module', 'cck') .'/theme/cck.css');
-}
-
-/**
- * Implementation of hook_menu_alter().
- */
-function cck_menu_alter(&$items) {
-  // Customize the content types page with our own callback
-  $items['admin/build/types']['page callback'] = 'cck_types_overview';
-  $items['admin/build/types']['file'] = 'cck.admin.inc';
-  $items['admin/build/types']['file path'] = drupal_get_path('module', 'cck') .'/includes';
-}
-
-/**
- * Implementation of hook_menu().
- */
-function cck_menu() {
-  // Set up menus for both content types and user settings.
-
-  $items = array();
-  $items['admin/build/fields'] = array(
-    'title' => 'Fields',
-    'description' => 'Manage custom fields that have been added to content types or users.',
-    'page callback' => 'cck_fields_list',
-    'access arguments' => array('administer content types'),
-    'type' => MENU_NORMAL_ITEM,
-  );
-  $items['admin/build/fields/list'] = array(
-    'title' => 'Field list',
-    'page callback' => 'cck_fields_list',
-    'access arguments' => array('administer content types'),
-    'type' => MENU_DEFAULT_LOCAL_TASK,
-    'weight' => 1,
-  );
-  // TODO D7 : remove, debug code
-  $items['admin/build/fields/field-info'] = array(
-    'title' => 'Field Info (debug)',
-    'page callback' => 'cck_debug_field_info',
-    'access arguments' => array('administer content types'),
-    'type' => MENU_LOCAL_TASK,
-    'weight' => 2,
-  );
-  $items['admin/build/types/field-info'] = array(
-    'title' => 'Field Info (debug)',
-    'page callback' => 'cck_debug_field_info',
-    'access arguments' => array('administer content types'),
-    'type' => MENU_LOCAL_TASK,
-    'weight' => 2,
-  );
-  // Create an 'Edit' tab for the user.
-  $items['admin/user/settings/edit'] = array(
-    'title' => 'Edit',
-    'page callback' => 'drupal_get_form',
-    'page arguments' => array('user_admin_settings'),
-    'access arguments' => array('administer users'),
-    'type' => MENU_DEFAULT_LOCAL_TASK,
-  );
-
-
-  // Make sure this doesn't fire until field_bundles is working,
-  // and tables are updated, needed to avoid errors on initial installation.
-  if (!defined('MAINTENANCE_MODE')) {
-    // Create tabs for all possible bundles.
-    foreach (field_info_fieldable_types() as $obj_type => $info) {
-      foreach ($info['bundles'] as $bundle_name => $bundle_label) {
-        $admin_path = cck_bundle_admin_path($bundle_name);
-        $items[$admin_path .'/fields'] = array(
-          'title' => 'Manage fields',
-          'page callback' => 'drupal_get_form',
-          'page arguments' => array('cck_field_overview_form', $bundle_name),
-          'access arguments' => array('administer content types'),
-          'type' => MENU_LOCAL_TASK,
-          'weight' => 1,
-        );
-        // A dummy function to trigger a page refresh so that
-        // field menus get rebuilt correctly when new fields are added.
-        $items[$admin_path .'/fields/refresh'] = array(
-          'title' => 'Refresh menu',
-          'page callback' => 'drupal_get_form',
-          'page arguments' => array('cck_field_menu_refresh', $bundle_name),
-          'access arguments' => array('administer content types'),
-          'type' => MENU_CALLBACK,
-          'weight' => 1,
-        );
-        $items[$admin_path .'/display'] = array(
-          'title' => 'Display fields',
-          'page callback' => 'drupal_get_form',
-          'page arguments' => array('cck_display_overview_form', $bundle_name),
-          'access arguments' => array('administer content types'),
-          'type' => MENU_LOCAL_TASK,
-          'weight' => 2,
-        );
-
-        // 'Display fields' tab and context secondary tabs.
-        $tabs = cck_build_modes($obj_type);
-        foreach ($tabs as $key => $tab) {
-          $items[$admin_path .'/display/'. $key] = array(
-            'title' => $tab['title'],
-            'page arguments' => array('cck_display_overview_form', $bundle_name, $key),
-            'access arguments' => array('administer content types'),
-            'type' => $key == 'basic' ? MENU_DEFAULT_LOCAL_TASK : MENU_LOCAL_TASK,
-            'weight' => $key == 'basic' ? 0 : 1,
-          );
-        }
-
-        // Add tabs for any instances that are already created.
-        $instances = field_info_instances($bundle_name);
-        foreach ($instances as $instance) {
-          $field_name = $instance['field_name'];
-          $items[$admin_path .'/fields/'. $field_name] = array(
-            'title' => $instance['label'],
-            'page callback' => 'drupal_get_form',
-            'page arguments' => array('cck_field_edit_form', $bundle_name, $field_name),
-            'access arguments' => array('administer content types'),
-            'type' => MENU_LOCAL_TASK,
-          );
-          $items[$admin_path .'/fields/'. $field_name .'/edit'] = array(
-            'title' => 'Configure instance settings',
-            'page callback' => 'drupal_get_form',
-            'page arguments' => array('cck_field_edit_form', $bundle_name, $field_name),
-            'access arguments' => array('administer content types'),
-            'type' => MENU_DEFAULT_LOCAL_TASK,
-          );
-          $items[$admin_path .'/fields/'. $field_name .'/field-settings'] = array(
-            'title' => 'Configure field settings',
-            'page callback' => 'drupal_get_form',
-            'page arguments' => array('cck_field_settings_form', $bundle_name, $field_name),
-            'access arguments' => array('administer content types'),
-            'type' => MENU_LOCAL_TASK,
-          );
-          $items[$admin_path .'/fields/'. $field_name .'/widget-type'] = array(
-            'title' => 'Change widget type',
-            'page callback' => 'drupal_get_form',
-            'page arguments' => array('cck_widget_type_form', $bundle_name, $field_name),
-            'access arguments' => array('administer content types'),
-            'type' => MENU_LOCAL_TASK,
-          );
-          $items[$admin_path .'/fields/'. $field_name .'/remove'] = array(
-            'title' => 'Remove instance',
-            'page callback' => 'drupal_get_form',
-            'page arguments' => array('cck_field_remove_form', $bundle_name, $field_name),
-            'access arguments' => array('administer content types'),
-            'type' => MENU_LOCAL_TASK,
-          );
-        }
-      }
-    }
-  }
-  return $items;
-}
-
-function cck_debug_field_info() {
-  dsm(_field_info());
-  return '';
-}
-
-/**
- * Implementation of hook_theme().
- */
-function cck_theme() {
-  $path = drupal_get_path('module', 'cck') .'/theme';
-  require_once "./$path/theme.inc";
-
+function cck_permission() {
   return array(
-    'cck_field_overview_form' => array(
-      'template' => 'cck-admin-field-overview-form',
-      'path' => $path,
-      'arguments' => array('form' => NULL),
-    ),
-    'cck_display_overview_form' => array(
-      'template' => 'cck-admin-display-overview-form',
-      'path' => $path,
-      'arguments' => array('form' => NULL),
+    // TODO : simplify machine name and update existing perms ?
+    'Use PHP input for field settings (dangerous - grant with care)' => array(
+      'title' => t('Use PHP input for field settings'),
+      'description' => t('Enter PHP code in the field for the field settings that allow it. Warning: Give to trusted roles only; this permission has security implications.'),
     ),
   );
 }
 
 /**
- * Implementation of hook_field_attach_pre_view().
- */
-function cck_field_attach_view($output, $obj_type, &$object, $teaser) {
-  // Add identifier to the object to be used to alter extra fields in the view.
-  list($id, $vid, $bundle) = field_attach_extract_ids($obj_type, $object);
-  $object->content['#fieldable'] = TRUE;
-  $object->content['#bundle'] = $bundle;
-  return $output;
-}
-
-/**
- *
- */
-function cck_field_attach_insert($obj_type, &$object) {
-
-  // Add identifier to the object to be used to alter extra fields in the view.
-  list($id, $vid, $bundle) = field_attach_extract_ids($obj_type, $object);
-
-  // Implement hook_devel_generate(), if needed.
-  if (!empty($object->devel_generate)) {
-    include_once('./'. drupal_get_path('module', 'cck') .'/includes/cck.devel.inc');
-    cck_generate_fields($object, $bundle);
-  }
-
-}
-
-/**
- * Implementation of hook_field_attach_form().
- */
-function cck_field_attach_form($obj_type, &$object, &$form, &$form_state) {
-  // Add identifier to the object to be used to alter extra fields in the form.
-  list($id, $vid, $bundle) = field_attach_extract_ids($obj_type, $object);
-  $form['#fieldable'] = TRUE;
-  $form['#bundle'] = $bundle;
-}
-
-/**
- *  Implementation of hook_form_alter().
+ * Add fields to allowed values form to allow
+ * users to input a function or a PHP snippet
+ * that will return the allowed values.
  */
 function cck_form_alter(&$form, $form_state, $form_id) {
-  if (!empty($form['#fieldable']) && isset($form['#bundle'])) {
-    $bundle_name = $form['#bundle'];
-    $extra = cck_extra_field_values($bundle_name);
-    foreach ($extra as $key => $value) {
-      if (isset($form[$key])) {
-        $form[$key]['#weight'] = $value['weight'];
+  switch ($form_id) {
+    case 'field_ui_field_settings_form':
+      $field = field_info_field($form['field']['field_name']['#value']);
+      if ($field['module'] == 'list') {
+        // @todo : core should put that for us.
+        $form['#field'] = $field;
+        cck_allowed_values_form($form, $form_state, $field);
+        $form['#validate'][] = 'cck_allowed_values_validate';
       }
-    }
-  }
-}
-
-/**
- * Implementation of profile_alter().
- *
- * Change extra weights here after extra fields have been added.
- * Hook field_attach_post_view() is too early, other fields aren't
- * all added to the form at that point.
- *
- * TODO Can we make the view alter more generic? This requires that
- * we specifically alter each individual 'view' for all fieldable entities.
- */
-function cck_profile_alter($account) {
-  if (!empty($account->content['#fieldable']) && isset($account->content['#bundle'])) {
-    $bundle_name = $account->content['#bundle'];
-    $extra = cck_extra_field_values($bundle_name);
-    foreach ($extra as $key => $value) {
-      if (isset($account->content[$key])) {
-        $account->content[$key]['#weight'] = $value['weight'];
-      }
-    }
-  }
-}
-
-/**
- * Implementation of node_view_alter.
- *
- * Change extra weights here after extra fields have been added.
- * Hook field_attach_post_view() is too early, other fields aren't
- * all added to the form at that point.
- *
- * TODO Can we make the view alter more generic? This requires that
- * we specifically alter each individual 'view' for all fieldable entities.
- */
-function cck_node_view_alter(&$node, $teaser = FALSE, $page = FALSE) {
-  if (!empty($node->content['#fieldable']) && isset($node->content['#bundle'])) {
-    $bundle_name = $node->content['#bundle'];
-    $extra = cck_extra_field_values($bundle_name);
-    foreach ($extra as $key => $value) {
-      // Some core 'fields' use a different key in node forms and in 'view'
-      // render arrays.
-      if (isset($value['view']) && isset($node->content[$value['view']])) {
-        $node->content[$value['view']]['#weight'] = $value['weight'];
-      }
-      elseif (isset($node->content[$key])) {
-        $node->content[$key]['#weight'] = $value['weight'];
+      break;
+    case 'field_ui_field_edit_form':
+      $field = $form['#field'];
+      if ($field['module'] == 'list') {
+        cck_default_value_form($form, $form_state, $field);
+        cck_allowed_values_form($form, $form_state, $field);
+        $form['#validate'][] = 'cck_allowed_values_validate';
+        $form['#validate'][] = 'cck_default_value_validate';
       }
-    }
+      break;
   }
 }
 
 /**
- * Implementation of hook_cck_extra_fields.
+ * Add fields to allowed values form to allow
+ * users to input a function or a PHP snippet
+ * that will return the allowed values.
  */
-function cck_cck_extra_fields($bundle_name) {
-  if ($bundle_name == 'user') {
-    return _cck_user_extra_fields();
-  }
-  // TODO: we'll need to recognize other non single-mundle fieldable types.
-  else {
-    return _cck_node_extra_fields($bundle_name);
+function cck_allowed_values_form(&$form, $form_state, $field) {
+  $php_code = cck_field_get_setting('allowed_values_php', 'field', $field);
+  $allowed_values_function = $form['field']['settings']['allowed_values_function']['#value'];
+  if (!empty($php_code)) {
+    $allowed_values_function = 'cck_allowed_values_php';
   }
-}
 
-// TODO Add other user elements here.
-// How to do this for users? The form elements are totally different
-// than the view elements.
-function _cck_user_extra_fields() {
-  $extra = array();
-  $extra['account'] = array(
-    'label' => 'User name and password',
-    'description' => t('User module form element'),
-    'weight' => -10
-  );
-  $extra['timezone'] = array(
-    'label' => 'Timezone',
-    'description' => t('User module form element.'),
-    'weight' => 6
-  );
-  $extra['summary'] = array(
-    'label' => 'History',
-    'description' => t('User module view element.'),
-    'weight' => 5
+  // Add a field where users can specify some PHP
+  // code that will return the allowed values list.
+  $form['field']['settings']['allowed_values_php'] = array(
+    '#access' => user_access('Use PHP input for field settings (dangerous - grant with care)'),
+    '#type' => 'textarea',
+    '#title' => t('Allowed values PHP code'),
+    '#default_value' => $php_code,
+    '#description' => t('Advanced usage only: PHP code that returns an array of allowed values. Should not include &lt;?php ?&gt; delimiters. If this field is filled out, the value returned by this code will be used as the response to the function <strong>cck_allowed_values_php</strong> and will override any other allowed values list or function specified above. Expected format: <pre>!sample</pre>', array(
+      '!sample' => t("return array(\n  value_1 => label_1,\n  value_2 => label_2\n  ...\n);"),
+    )),
+    '#weight' => 5,
   );
-  return $extra;
-}
-
-function _cck_node_extra_fields($type_name) {
-  $extra = array();
-  if ($type = node_get_types('type', $type_name)) {
-    if ($type->has_title) {
-      $extra['title'] = array(
-        'label' => $type->title_label,
-        'description' => t('Node module element.'),
-        'weight' => -5
-      );
-    }
-    if ($type->has_body) {
-      $extra['body_field'] = array(
-        'label' => $type->body_label,
-        'description' => t('Node module element.'),
-        'weight' => 0,
-        'view' => 'body'
-      );
-    }
-    if (module_exists('locale') && variable_get("language_content_type_$type_name", 0)) {
-      $extra['language'] = array(
-        'label' => t('Language'),
-        'description' => t('Locale module element.'),
-        'weight' => 0
-      );
-    }
-    if (module_exists('menu')) {
-      $extra['menu'] = array(
-        'label' => t('Menu settings'),
-        'description' => t('Menu module element.'),
-        'weight' => -2
-      );
-    }
-    if (module_exists('taxonomy') && taxonomy_get_vocabularies($type_name)) {
-      $extra['taxonomy'] = array(
-        'label' => t('Taxonomy'),
-        'description' => t('Taxonomy module element.'),
-        'weight' => -3
-      );
-    }
-    if (module_exists('book')) {
-      $extra['book'] = array(
-        'label' => t('Book'),
-        'description' => t('Book module element.'),
-        'weight' => 10
-      );
-    }
-    if (module_exists('upload') && variable_get("upload_$type_name", TRUE)) {
-      $extra['attachments'] = array(
-        'label' => t('File attachments'),
-        'description' => t('Upload module element.'),
-        'weight' => 30,
-        'view' => 'files'
-      );
-    }
-  }
 
-  return $extra;
+  // Add a field where users can specify a function
+  // to return the allowed values list.
+  $form['field']['settings']['allowed_values_function'] = array(
+    '#type' => 'textfield',
+    '#title' => t('Allowed values function'),
+    '#default_value' => $allowed_values_function,
+    '#description' => t('The name of a function that will return the allowed values list.'),
+    '#weight' => 6,
+    '#states' => array(
+      'visible' => array(
+        ':input[name="field[settings][allowed_values_php]"]' => array('empty' => TRUE),
+      ),
+    )
+  );
 }
 
 /**
- * Retrieve the user-defined weight for non-CCK node 'fields'.
- *
- * CCK's 'Manage fields' page lets users reorder node fields, including non-CCK
- * items (body, taxonomy, other hook_nodeapi-added elements by contrib modules...).
- * Contrib modules that want to have their 'fields' supported need to expose
- * them with hook_cck_extra_fields, and use this function to retrieve the
- * user-defined weight.
- *
- * @param $type_name
- *   The content type name.
- * @param $pseudo_field_name
- *   The name of the 'field'.
- * @return
- *   The weight for the 'field', respecting the user settings stored
- *   by field.module.
+ * Add fields to default value form to allow
+ * users to input a function or a PHP snippet
+ * that will return the default values.
  */
-function cck_extra_field_weight($bundle_name, $pseudo_field_name) {
-  $extra = cck_extra_field_values($bundle_name);
-  if (isset($extra[$pseudo_field_name])) {
-    return $extra[$pseudo_field_name]['weight'];
+function cck_default_value_form(&$form, $form_state, $field) {
+  $instance = field_info_instance($form['instance']['entity_type']['#value'], $field['field_name'], $form['instance']['bundle']['#value']);
+  $default_value_function = !empty($instance['default_value_function']) ? $instance['default_value_function'] : '';
+  $php_code = cck_field_get_setting('default_value_php', 'instance', $field, $instance);
+  if (!empty($php_code)) {
+    $default_value_function = 'cck_default_value_php';
   }
-}
-
-function cck_extra_field_values($bundle_name) {
-  static $info = array();
 
-  if (empty($info)) {
-    $info = array();
-    $bundles = field_info_bundles();
-    foreach ($bundles as $bundle => $bundle_label) {
-      // Gather information about non-CCK 'fields'.
-      $extra = module_invoke_all('cck_extra_fields', $bundle);
-      drupal_alter('cck_extra_fields', $extra, $bundle);
+  // Add a field where users can specify some PHP
+  // code that will return the default value.
+  module_load_include('install', $field['module']);
+  $schema = module_invoke($field['module'], 'field_schema', $field);
+  $columns = array_keys($schema['columns']);
+  $sample = t("return array(\n  0 => array(@columns),\n  // You'll usually want to stop here. Provide more values\n  // if you want your 'default value' to be multi-valued:\n  1 => array(@columns),\n  2 => ...\n);", array('@columns' => implode(', ', $columns)));
+
+  $form['instance']['default_value_widget']['default_value_php'] = array(
+    '#access' => user_access('Use PHP input for field settings (dangerous - grant with care)'),
+    '#type' => 'textarea',
+    '#title' => t('Default value PHP code'),
+    '#default_value' => $php_code,
+    '#description' => t('Advanced usage only: PHP code that returns a default value. Should not include &lt;?php ?&gt; delimiters. If this field is filled out, the value returned by this code will be used as the response to the function <strong>cck_default_value_php</strong> and will override any other default value or function specified above. Expected format: <pre>!sample</pre>To figure out the expected format, you can use the <em>devel load</em> tab provided by <a href="@link_devel">devel module</a> on a content page.', array(
+      '!sample' => $sample,
+      '@link_devel' => 'http://www.drupal.org/project/devel',
+    )),
+    '#weight' => 5,
+    '#parents' => array('instance', 'default_value_php'),
+  );
 
-      // Add saved weights.
-      foreach (variable_get('cck_extra_weights_'. $bundle, array()) as $key => $value) {
-        // Some stored entries might not exist anymore, for instance if uploads
-        // have been disabled, or vocabularies removed...
-        if (isset($extra[$key])) {
-          $extra[$key]['weight'] = $value;
-        }
-      }
-      $info[$bundle] = $extra;
-    }
-  }
-  if (array_key_exists($bundle_name, $info)) {
-    return $info[$bundle_name];
-  }
-  else {
-    return array();
-  }
+  // Add a field where users can specify a function
+  // to return the default value.
+  $form['instance']['default_value_widget']['default_value_function'] = array(
+    '#type' => 'textfield',
+    '#title' => t('Default value function'),
+    '#default_value' => $default_value_function,
+    '#description' => t('The name of a function that will return the default value.'),
+    '#states' => array(
+      'visible' => array(
+        ':input[name="instance[default_value_php]"]' => array('empty' => TRUE),
+      ),
+    ),
+    '#weight' => 6,
+    '#parents' => array('instance', 'default_value_function'),
+  );
 }
 
+/**
+ * Validation handler to store php allowed values.
+ */
+function cck_allowed_values_validate(&$form, &$form_state) {
+  $field = $form['#field'];
 
-function cck_build_modes($obj_type, $tab_selector = NULL) {
-  static $info;
-
-  if (!isset($info[$obj_type])) {
-    $info[$obj_type] = module_invoke_all('cck_build_modes');
-    // Collect titles, and filter out non active modes.
-    $active_modes = field_build_modes($obj_type);
-    foreach ($info[$obj_type] as $tab => $values) {
-      $modes = array();
-      foreach ($info[$obj_type][$tab]['build modes'] as $mode) {
-        if (isset($active_modes[$mode])) {
-          $modes[$mode] = $active_modes[$mode];
-        }
-      }
-      if ($modes) {
-        $info[$obj_type][$tab]['build modes'] = $modes;
-      }
-      else {
-        unset($info[$obj_type][$tab]);
-      }
-    }
-  }
-  if ($tab_selector) {
-    return isset($info[$obj_type][$tab_selector]) ? $info[$obj_type][$tab_selector]['build modes'] : array();
+  $php_code = $form_state['values']['field']['settings']['allowed_values_php'];
+  $allowed_values_function = $form_state['values']['field']['settings']['allowed_values_function'];
+  if (!empty($php_code)) {
+    $allowed_values_function = 'cck_allowed_values_php';
   }
-  else {
-    return $info[$obj_type];
+  elseif (empty($php_code) && $allowed_values_function == 'cck_allowed_values_php') {
+    $allowed_values_function = '';
   }
+  form_set_value($form['field']['settings']['allowed_values_function'], $allowed_values_function, $form_state);
+  // @todo This should be done at submit time, not validate.
+  cck_field_set_setting('allowed_values_php', 'field', $php_code, $field);
 }
 
 /**
- * Implementation of hook_cck_build_modes(), on behalf of other core modules.
- *
- * @return
- * An array describing the build modes defined by the module, grouped by tabs.
- *
- * Expected format:
- * array(
- *   // A module can add its render modes to a tab defined by another module.
- *   'tab1' => array(
- *     'title' => t('The human-readable title of the tab'),
- *     'build modes' => array('mymodule_mode1', 'mymodule_mode2'),
- *   ),
- *   'tab2' => array(
- *     // ...
- *   ),
- * );
+ * Validation handler to store php default values.
  */
-function cck_cck_build_modes() {
-  $modes = array(
-    'basic' => array(
-      'title' => t('Basic'),
-      'build modes' => array('teaser', 'full'),
-    ),
-    'rss' => array(
-      'title' => t('RSS'),
-      'build modes' => array(NODE_BUILD_RSS),
-    ),
-    'print' => array(
-      'title' => t('Print'),
-      'build modes' => array(NODE_BUILD_PRINT),
-    ),
-    'search' => array(
-      'title' => t('Search'),
-      'build modes' => array(NODE_BUILD_SEARCH_INDEX, NODE_BUILD_SEARCH_RESULT),
-    ),
-  );
-  return $modes;
-}
-
-/**
- *  Implementation of hook_node_type().
- *
- *  TODO Right way to do this in D7? Not needed for users since the user type is never deleted.
- *   Content types could be deleted. Not sure about other entities.
- *   [yched] : fieldable will need to take care of calling field_rename_bundle(), field_delete_bundle()
- *     when appropriate anyway. Those functions - we don't have them yet :) - will need to call a hook
- *     so that CCK UI is notified of this.
- */
-function cck_node_type($op, $info) {
-  switch ($op) {
-    case 'insert':
-      // TODO Fix this.
-      // Trying to get the Manage Fields screen for a new content type to
-      // work immediately after the new type is created. Even this won't do it,
-      // MF screen is still 'Page not found' after the new type is created.
-      field_cache_clear();
-      menu_rebuild();
-      break;
-    
-    case 'update':
-      if ($extra = variable_get('cck_extra_weights_'. $info->old_type, array())) {
-        variable_set('cck_extra_weights_'. $info->type, $extra);
-        variable_del('cck_extra_weights_'. $info->old_type);
-      }
-      break;
-    case 'delete':
-      variable_del('cck_extra_weights_'. $info->type);
-      break;
+function cck_default_value_validate(&$form, &$form_state) {
+  $field = $form['#field'];
+  $instance = $form['#instance'];
+
+  $default_value_function = $form_state['values']['instance']['default_value_function'];
+  $php_code = $form_state['values']['instance']['default_value_php'];
+  if (!empty($php_code)) {
+    $default_value_function = 'cck_default_value_php';
   }
+  elseif (empty($php_code) && $default_value_function == 'cck_default_value_php') {
+    $default_value_function = '';
+  }
+  form_set_value($form['instance']['default_value_widget']['default_value_function'], $default_value_function, $form_state);
+  // @todo This should be done at submit time, not validate.
+  cck_field_set_setting('default_value_php', 'instance', $php_code, $field, $instance);
 }
 
-/**
- * Helper function to create the right administration path for a bundle.
- */
-function cck_bundle_admin_path($bundle_name) {
-  if ($bundle_name == 'user') {
-    return 'admin/user/settings';
+
+function cck_debug_field_info() {
+  if (function_exists('dsm')) {
+    module_load_include('inc', 'field', 'field.info');
+    dsm(_field_info_collate_types());
+    dsm(_field_info_collate_fields());
+    return '';
   }
   else {
-    return 'admin/build/node-type/' . str_replace('_', '-', $bundle_name);
+    return t('You need to enable devel.module to see this page');
   }
 }
 
@@ -584,29 +202,31 @@ function cck_serialized_settings() {
 
 /**
  * Helper function to retrieve field settings stored by CCK.
- * 
+ *
  * CCK uses the 'cck_field_settings' table to store custom settings
  * not used by core.
- * 
+ *
  * Field settings will have no $instance nor a db bundle column.
  */
-function cck_field_get_setting($setting, $setting_type, $field, $instance = NULL) {
+function cck_field_get_setting($setting, $setting_type, $field, $instance = NULL, $langcode = LANGUAGE_NONE) {
   if ($setting_type == 'field' || empty($instance)) {
     $value = db_select('cck_field_settings', 'fs')->fields('fs', array('setting_option'))
+      ->condition('fs.field_name', $field['field_name'])
       ->condition('fs.setting', $setting)
       ->condition('fs.setting_type', $setting_type)
-      ->condition('fs.field_name', $field['field_name'])
-      ->execute()->fetchField();    
+      ->execute()->fetchField();
   }
   else {
     $value = db_select('cck_field_settings', 'fs')->fields('fs', array('setting_option'))
-      ->condition('fs.setting', $setting)
-      ->condition('fs.setting_type', $setting_type)
       ->condition('fs.field_name', $field['field_name'])
+      ->condition('fs.entity_type', $instance['entity_type'])
       ->condition('fs.bundle', $instance['bundle'])
+      ->condition('fs.language', $langcode)
+      ->condition('fs.setting', $setting)
+      ->condition('fs.setting_type', $setting_type)
       ->execute()->fetchField();
   }
-  
+
   if (in_array($setting, cck_serialized_settings())) {
     $value = unserialize($value);
   }
@@ -615,15 +235,16 @@ function cck_field_get_setting($setting, $setting_type, $field, $instance = NULL
 
 /**
  * Helper function to set field settings stored by CCK.
- * 
+ *
  * CCK uses the 'cck_field_settings' table to store custom settings
  * not used by core.
- * 
+ *
  * Field settings will have no $instance nor a db bundle column.
  */
-function cck_field_set_setting($setting, $setting_type, $value, $field, $instance = NULL) {
+function cck_field_set_setting($setting, $setting_type, $value, $field, $instance = NULL, $langcode = LANGUAGE_NONE) {
   // Delete any prior values.
   $bundle = ($setting_type == 'field' || empty($instance)) ? NULL : $instance['bundle'];
+  $entity_type = ($setting_type == 'field' || empty($instance)) ? NULL : $instance['entity_type'];
   if ($setting_type == 'field' || empty($instance)) {
     db_delete('cck_field_settings')
       ->condition('field_name', $field['field_name'])
@@ -634,7 +255,9 @@ function cck_field_set_setting($setting, $setting_type, $value, $field, $instanc
   else {
     db_delete('cck_field_settings')
       ->condition('field_name', $field['field_name'])
+      ->condition('entity_type', $entity_type)
       ->condition('bundle', $bundle)
+      ->condition('language', $langcode)
       ->condition('setting', $setting)
       ->condition('setting_type', $setting_type)
       ->execute();
@@ -645,7 +268,9 @@ function cck_field_set_setting($setting, $setting_type, $value, $field, $instanc
   }
   $record = array(
     'field_name' => $field['field_name'],
+    'entity_type' => $entity_type,
     'bundle' => $bundle,
+    'language' => $langcode,
     'setting' => $setting,
     'setting_option' => $value,
     'setting_type' => $setting_type,
@@ -655,35 +280,91 @@ function cck_field_set_setting($setting, $setting_type, $value, $field, $instanc
 }
 
 /**
- * Implementation of hook_field_default_value().
- *  
- * Helper function to return the correct default value for a field
- * on behalf of fields managed in the CCK UI.
- *
- *  @param $obj_type
- *    The object type.
- *  @param $object
- *    The object.
- *  @param $field
- *    The field array.
- *  @param $instance
- *    The field array.
- *  @return
- *    The default value for that field.
+ * Callback to return default value constructed
+ * from php code snippet.
  */
-function cck_field_default_value($obj_type, $object, $field, $instance) {
+function cck_default_value_php($entity_type, $entity, $field, $instance, $langcode = LANGUAGE_NONE) {
   $default_value = array();
-  $default_setting = cck_field_get_setting('default_value', 'instance', $field, $instance);
-  $default_setting_php = cck_field_get_setting('default_value_php', 'instance', $field, $instance);
-  if (!empty($default_setting_php)) {
-    ob_start();
-    $result = eval($default_setting_php);
-    if (is_array($result)) {
-      $default_value = $result;
+  ob_start();
+  $result = eval(cck_field_get_setting('default_value_php', 'instance', $field, $instance, $langcode, $flatten = TRUE));
+  ob_end_clean();
+  if (is_array($result)) {
+    $default_value = $result;
+  }
+  return $default_value;
+}
+
+/**
+ * Callback to return allowed values constructed
+ * from php code snippet.
+ */
+function cck_allowed_values_php($field, $flatten = TRUE) {
+  $allowed_values = array();
+  ob_start();
+  $result = eval(cck_field_get_setting('allowed_values_php', 'field', $field));
+  ob_end_clean();
+  if (is_array($result)) {
+    if ($flatten) {
+      $result = cck_array_flatten($result);
     }
+    $allowed_values = $result;
   }
-  elseif (!empty($default_setting)) {
-    $default_value = $default_setting;
+  return $allowed_values;
+}
+
+/**
+ * Helper function to flatten an array of allowed values.
+ *
+ * @param $array
+ *   A single or multidimensional array.
+ * @return
+ *   A flattened array.
+ */
+function cck_array_flatten($array) {
+  $result = array();
+  if (is_array($array)) {
+    foreach ($array as $key => $value) {
+      if (is_array($value)) {
+        $result += cck_array_flatten($value);
+      }
+      else {
+        $result[$key] = $value;
+      }
+    }
+  }
+  return $result;
+}
+
+/**
+ * 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 cck_content_migrate_field_alter(&$field_value) {
+  if (!empty($field_value['settings']['allowed_values_php'])) {
+    $field_value['settings']['allowed_values_function'] = 'cck_allowed_values_php';
+    cck_field_set_setting('allowed_values_php', 'field', $field_value['settings']['allowed_values_php'], $field_value);
   }
-  return (array) $default_value;
-}
\ No newline at end of file
+}
+
+/**
+ * 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 cck_content_migrate_instance_alter(&$instance_value) {
+  if (!empty($instance_value['settings']['default_value_php'])) {
+    $field_value = content_migrate_get_field_values($instance_value['field_name']);
+    $instance_value['settings']['default_value_function'] = 'cck_default_value_php';
+    cck_field_set_setting('default_value_php', 'instance', $instance_value['settings']['default_value_php'], $field_value, $instance_value);
+  }
+}