Create taxonomy tree programmatically including vocabulary creation
Sometimes setting up all the taxonomy tree manually it's a complex task, especially if you have hundreds of terms to create, re-parent.
Bellow is a code snippet I created to manage a fast and clear taxonomy term creation.
It can support unlimited nested tree as the job is done recursively.
Comments in snippet are self-explanatory.
/**
* Example of how to use functionality.
*
* Usually it will be called in hook_install() or hook_update()
*/
function _taxonomy_tree_generate_example() {
$trees = array(
'Article Type' => array(
'News',
'Reviews',
),
'Category' => array(
'Level 1' => array(
'Level 2 1',
'Level 2 2' => array(
'Level 3 1',
'Level 3 2',
'Level 3 3' => array(
'Level 4 1',
'Level 4 2'
),
),
'Level 2 3',
),
'Events',
'Destinations' => array(
'More terms',
),
'And so on...',
),
);
taxonomy_tree_generate($trees);
}
/**
* Loop through the Vocabularies and generate all the taxonomy tree.
*/
function taxonomy_tree_generate($trees) {
foreach ($trees as $vocabulary_name => $vocabulary_tree) {
_taxonomy_tree_generate_create_vocabulary_tree($vocabulary_name, $vocabulary_tree);
}
}
/**
* Initial preparing for processing the nested array.
*/
function _taxonomy_tree_generate_create_vocabulary_tree($vocabulary_name, $vocabulary_tree) {
// Create vocabulary if it doesn't exist.
$vocabulary = _taxonomy_tree_generate_get_vocabulary_by_name($vocabulary_name);
if (!isset($vocabulary->vid)) {
if (!function_exists('pathauto_cleanstring')) {
module_load_include('inc', 'pathauto');
}
$vocabulary = new stdClass();
$vocabulary->name = $vocabulary_name;
if (function_exists('pathauto_cleanstring')) {
$vocabulary_machine_name = pathauto_cleanstring($vocabulary_name);
}
else {
$vocabulary_machine_name = drupal_strtolower(preg_replace('/[^a-z\d ]/i', '', check_plain($vocabulary_name)));
}
$vocabulary->machine_name = str_replace('-', '_', $vocabulary_machine_name);
taxonomy_vocabulary_save($vocabulary);
}
// Test purpose, delete all terms before create them.
//foreach (taxonomy_get_tree($vocabulary->vid) as $term) {
// taxonomy_term_delete($term->tid);
//}
// Create taxonomy tree recursively.
_taxonomy_tree_generate_create_one_level_tree($vocabulary_tree, $vocabulary);
}
/**
* Create taxonomy tree recursively.
*/
function _taxonomy_tree_generate_create_one_level_tree($vocabulary_tree, $vocabulary, $parent = 0) {
$weight = 0;
foreach ($vocabulary_tree as $parent_term_name => $term_name) {
// If one level.
if (!is_array($term_name)) {
$term = _taxonomy_tree_generate_create_term($term_name, $vocabulary, $parent, $weight);
}
// If two levels or more.
else {
$term = _taxonomy_tree_generate_create_term($parent_term_name, $vocabulary, $parent, $weight);
// Go deeper.
_taxonomy_tree_generate_create_one_level_tree($term_name, $vocabulary, $term->tid);
}
++$weight;
}
return;
}
function _taxonomy_tree_generate_create_term($name, $vocabulary, $parent, $weight) {
$term = taxonomy_get_term_by_name($name, $vocabulary->machine_name);
if (empty($term)) {
$term = new stdClass();
$term->name = $name;
$term->vid = $vocabulary->vid;
}
else {
$term = reset($term);
}
// Even if term exist already, we want to push our parent and weight.
$term->parent = $parent;
$term->weight = $weight;
taxonomy_term_save($term);
return $term;
}
/**
* Get vocabulary object by vocabulary name.
*/
function _taxonomy_tree_generate_get_vocabulary_by_name($vocabulary_name) {
$query = db_select('taxonomy_vocabulary', 'tv');
$query->fields('tv', array(
'machine_name',
'vid',
));
$query->condition('tv.name', $vocabulary_name, '=');
$vocabulary = $query->execute()->fetchObject();
return $vocabulary;
}