Web design, programming, graphics, and pretty much anything else I care about.

Install taxonomy, with terms and hierarchy, on module installation

Getting a module to install a vocabulary, and even import terms, is not terribly difficult; however, getting it to accept an existing hierarchy can be tricky.

(I was working with a taxonomy for academic departments and schools.)

Create an include file. I name them module name.taxonomy.def.inc. In the file create an array that will define the vocabulary, and one that will include the terms.

<?php
$vocabulary
= array(
 
'name' => 'Departments',
 
//array of the nodes the vocabulary will be attached to
 
'nodes' => array('my_content_type' => 'my_content_type'),
 
'description' => 'Campus departments and schools.',
 
'help' => 'Select a term.',
 
'tags' => 0,
 
'hierarchy' => 1,
 
'relations' => 0,
 
'multiple' => 1,
 
'required' => 1,
 
'weight' => -5,
);

$terms = array();
$terms[] = array(
 
'name' => 'CSDM Seminars',
 
'parent' => 'School of Mathematics',
);
$terms[] = array(
 
'name' => 'School of Mathematics',
);
$terms[] = array(
 
'name' => 'Facilities',
);
$terms[] = array(
 
'name' => 'School of Social Science',
);
...
?>

In the .install file, include the following code:

<?php
// Include the pre-defined vocabulary and terms.
include "my_module.taxonomy.def.inc";

// Install vocabulary.
taxonomy_save_vocabulary($vocabulary);
drupal_set_message('The vocabulary <em>' . $vocabulary['name'] . '</em> has been added.');

// Install terms. After the vocabulary is installed, get the vid.
$vid = db_result(db_query("SELECT vid FROM {vocabulary} WHERE name = '%s'", $vocabulary['name']));
foreach (
$terms as $term) {
 
// Proceed if the term does not exist already.
  // This is needed so the .inc file does not have to worry about the order of terms and parents.
 
if (!db_result(db_query("SELECT 1 FROM {term_data} WHERE name = '%s' AND vid = %d", $term['name'], $vid))) {
   
$term['vid'] = $vid;
    if (isset(
$term['parent'])) {
     
// Parent term is set, but it does not exist in the vocabulary, so create it.
      // If it does exist, use the value in $parent.
      // A temp variable ($tmp) is used, because it is passed by reference.
     
if (!$parent = db_result(db_query("SELECT tid FROM {term_data} WHERE name = '%s' AND vid = %d", $term['parent'], $vid))) {
       
taxonomy_save_term($tmp = array('name' => $term['parent'], 'vid' => $vid));
       
$parent = db_result(db_query("SELECT tid FROM {term_data} WHERE name = '%s' AND vid = %d", $term['parent'], $vid));
      }
     
$term['parent'] = array($parent);
    }
   
taxonomy_save_term($term);
  }
}
drupal_set_message('The terms have been added.');
?>

This will install all the terms, and produce the required hierarchy. The complexity of the code is to also eliminate the need for the include file to list the terms in any specific order.

If no hierarchy is needed, you can just loop taxonomy_save_term($term).