Tech Blog :: Drupal: Automating CCK field creation with update hook/deployment


Jan 11 '10 11:46am
Tags

Drupal: Automating CCK field creation with update hook/deployment

I had a Drupal (6) project recently that involved adding a new computed field to a content type. The field could be added manually on each deployment, or automated with an update hook. I decided to try out the automatic method, here's how to do it:
<?php
// update hook
// see http://api.drupal.org/api/function/hook_update_N for function name, return value
// only works in 6.11+, see http://drupal.org/node/297972
function MYMODULE_update_6101() {
  $ret = array();
 
  $content_type = 'article';
  $new_field_name = 'some_field_name';    // w/o field_
 
  // depends on a bunch of widget modules -- just load them all
  module_load_all();
  // make sure cck admin file is loaded
  include_once drupal_get_path('module', 'content') . '/includes/content.admin.inc';
 
  if (!function_exists('content_field_overview_form') or !function_exists('content_help')) {    // will fail if includes didn't work
    $ret[] = array('success'=>false, 'query'=>'Unable to load necessary include files');
    return $ret;
  }
 
  // does the field already exist?
  // (content_fields() ignores inactive fields, but should be ok - see content.admin.inc for alternative)
  if (content_fields('field_'.$new_field_name, $content_type)) {
    $ret[] = array('success'=>true, 'query'=>"field_{$new_field_name} already exists");
    return $ret;
  }
 
  // enable the 'computed field' module if not already running
  if (! module_exists('computed_field')) {
    module_enable( array('computed_field') );   // (doesn't return anything)
 
    // if not running now, there was an error
    if (! module_exists('computed_field')) {
      $ret[] = array('success'=>false, 'query'=>'Unable to enable computed_field module, can\'t continue.');
      return $ret;
    }
  }
  $ret[] = array('success'=>true, 'query'=>'Computed Field module is enabled.');
 
 
  // simulate the content type add-field form
  $form = array();
 
  // for testing, load the form to view it
  // $form = drupal_retrieve_form('content_field_overview_form', $form_state, $content_type);    // $content_type=>$type_name
  // $ret[]['query'] = '<pre>'.print_r($form,true).'</pre>';
 
  $form_state['values']['_add_new_field']['label'] = 'Name of New Field';
  $form_state['values']['_add_new_field']['field_name'] = $new_field_name;
  $form_state['values']['_add_new_field']['type'] = 'computed';
  $form_state['values']['_add_new_field']['widget_type'] = 'computed';
  $form_state['values']['_add_new_field']['parent'] = 'group_some_group';  // put under fieldgroup (optional)
 
  // generate & submit the form
  drupal_execute('content_field_overview_form', $form_state, $content_type);          // $content_type goes into $type_name
 
  // check if exists now
  if ($new_field = content_fields('field_'.$new_field_name, $content_type)) {
    $ret[] = array('success'=>true, 'query'=>'NEW '.$new_field_name.': <pre>'.print_r($new_field,true).'</pre>');
    return $ret;
  }
  else {
    $ret[] = array('success'=>false, 'query'=>"An error occured creating the new {$new_field_name}, does not exist.");
  }
 
  // for testing
  // $ret[] = array('success'=>true, 'query'=>l('Run update again', 'update.php'));
      // -- reset system.`schema_version` where name='MYMODULE' to run again
 
  return $ret;
}
One major caveat: I discovered the hard way that this doesn't work prior to 6.11. (Fixed: #297972: make the batch API compatible with drupal_execute(), so things like creating a CCK type or adding fields to it (by submitting forms programatically) are possible in update functions). So if for some reason you're stuck on a pre-6.11 core, you're probably best making the fields manually. (In my case it would have been faster to do that from the start, but I wanted to see how this could be done.)

Post new comment

Don't bother putting in spam links. They'll be set to rel=nofollow and will be removed and reported as spam shortly after submitting.

The content of this field is kept private and will not be shown publicly.
CAPTCHA
Are you human?