Category Technology
Publication date
24 July 2009

Using Chaos Tools module to create exportables

Recently I created a patch for the migrate module so you can export content sets, paste them into your module and have them automatically imported. This works in much the same way as Views handles default views in code, with the version in the database overriding the version in code. Using the Chaos Tools (ctools) module it was, relatively, easy to add this functionality. Here are the steps involved if you want to add it to your own module.

First, for each type of exportable object you want to handle, you need to create a table in the database to store the data in. Using Drupal's schema API you can easily define your table structure. As normal you have the 'fields', 'primary key' and other properties. However you need to define one additional property called export. In our example below, we will refer to our object as 'myobj'.

The 'export' property is a keyed array which allows you to define some attributes, such as your module's current API version and the minimum one still supported. Most importantly it allows you to define the function hook name (default hook) that other modules need to use in order to define default objects, and also the base name for the include file that contains this hook (api). The default hook is analogous to Views' hook_default_view_views() and the api file base name would match the 'views_default' part of the file name of 'examplemodule.views_default.inc'.

<?php
function mymodule_schema() {
  $schema['mymodule_myobj'] = array(
    'description' => t('Table storing myobj definitions.'),
    'export' => array(
      'key' => 'oid',
      'identifier' => 'myobj',
      'default hook' => 'default_mymodule_myobj',  // Function hook name.
      'api' => array(
        'owner' => 'mymodule',
        'api' => 'default_mymodule_myobjs',  // Base name for api include files.
        'minimum_version' => 1,
        'current_version' => 1,
      ),
    ),
    'fields' => array(
      'oid' => array(
        'type' => 'serial',
        'unsigned' => TRUE,
        'not null' => TRUE,
      ),
     ......
    'primary key' => array('fooid'),
  );
  return $schema;
}
?>

In your hook_menu() you should define a path where users can export a 'myobj' object. In our example below, this is 'admin/build/mymodule/%/export' where the % matches our myobj's unique identifier. This identifier will be passed to a form called mymodule_export_myobj.

<?php
/**
 * Implementation of hook_menu().
 */
function mymodule_menu() {
  $items['admin/build/mymodule/%/export'] = array(
    'title' => 'Export',
    'page callback' => 'drupal_get_form',
    'page arguments' => array('mymodule_export_myobj', 3),
    'access arguments' => array('mymodule export permission'),
    'type' => MENU_CALLBACK,
  );

  return $items;
}

/**
 * Export a myobj and display it in a form.
 */
function mymodule_export_myobj(&$form_state, $oid) {
  $obj = mymodule_myobj_load($oid);
  drupal_set_title(check_plain($obj->description));
  $code = mymodule_myobj_export($obj);
  $lines = substr_count($code, "\n");

  $form['export'] = array(
    '#title' => t('Export data'),
    '#type' => 'textarea',
    '#value' => $code,
    '#rows' => $lines,
    '#description' => t('Copy the export text and paste it into another myobj using the import function.'),
  );
  return $form;
}
?>

The mymodule_export_myobj() form function calls two functions, mymodule_myobj_load() to fetch the object in the desired format, and mymodule_myobj_export() to generate the exportable.

<?php
/**
 * Load a single myobj.
 */
function mymodule_myobj_load($oid) {
  ctools_include('export');
  $result = ctools_export_load_object('mymodule_myobjs', 'names', array($oid));
  if (isset($result[$oid])) {
    return $result[$oid];
  }
}

/**
 * Export a myobj.
 */
function mymodule_myobj_export($obj, $indent = '') {
  ctools_include('export');
  $output = ctools_export_object('mymodule_myobjs', $obj, $indent);
  return $output;
}
?>

Both of these functions call ctools_include('export') which loads the necessary ctools file containing the functions relating to exportables. ctools_export_load_object() fetches all the definitions it has for your object from the database, using the table schema as defined in your install file. It will also load all the default object hooks (in our example this would be hook_default_mymodule_myobj()), and merge new objects into its list to return. In addition, it handles things like caching and the loading of subsidiary objects if necessary. ctools_export_object() takes the passed in loaded object and converts it into PHP code which can then be printed out in the export form.

The ctools module doesn't provide an import function. It's up to each module to carry out this task, but with Drupal's drupal_write_record() function, this isn't so big a deal.

Profile picture for user Stella Power

Stella Power Managing Director

As well as being the founder and managing director of Annertech, Stella is one of the best known Drupal contributors in the world.