Programmatically creating CCK nodes in PHP (interaction with the Path module)

I’ve been experimenting with the Drupal Content Construction Kit, which promised to be a more flexible way to deal with custom node types in the Drupal content management system. However, I’m a finicky sort of person who likes being able to reproduce the setup from a fresh start, and CCK isn’t well-known for that. In fact, CCK nodes aren’t well-known for being easy to move from one server to another.

Following the instructions for programmatically creating, inserting, and updating CCK nodes will get you most of the way there. Here are some of the gotchas you’ll want to watch out for.

I was using Path to define aliases for my nodes and the path aliases were just not getting created. After lots and lots of tracing with XDebug, I found out that it was checking for user_access, but no user was active during the installation process. Solution: create the admin user and load it into a global $user variable.

I also spent a fair bit of time being very annoyed with CCK and creating nodes programmatically in my install profile. Turns out that you first need to use install_add_content_type to create the base node type, _then_ follow the instructions to drupal_execute the form that adds custom fields.

Here’s a quick sketch of the code:

function profilename_profile_final() {
  // lots of other code here
  install_add_user('admin', 'admin', '[email protected]', array(), 1);
  global $user;
  $user = user_load(array('uid' => 1));
  install_add_content_type(array(
    // take this from Install Profile Wizard
  ));
  node_get_types('types', NULL, TRUE);  // flush cache
  $content = array();
  $content['type'] = array(
   // take this from content copy export
  );
  $content['fields'] = array(
   // take this from content copy export
  );
    _install_create_content($content);    
}
function _install_create_content($content) {
  global $_install_macro;
  $type_name = $content['type']['type'];
  $_install_macro[$type_name] = $content;
  include_once drupal_get_path('module', 'node') .'/content_types.inc';
  include_once drupal_get_path('module', 'content') .'/content_admin.inc';
  $macro = 'global $_install_macro; $content = $_install_macro['. $type_name .'];';
  drupal_execute('content_copy_import_form', array('type_name' => $type_name, 'macro' => $macro));
  content_clear_type_cache();
}

Now I feel more confident about CCK…