Create multiple nodes with the same (persistent) taxonomy categories.

Last modified: July 17, 2007 - 02:52

Say a site has a very deep taxonomy structure, and a user wants to create a number of nodes in the same category. This can be rather frustrating for them to have to scroll through and select the correct taxonomy for each node added.

This mini-module was based on the taxonomy_defaults.module but saves taxonomy submitted in a session variable for re-use rather than overriding all node creations with admin configured values. Of course, as a result you might get unwanted conflicts between the two (check their weights).

I called this taxonomy_session_defaults.module, but anything suitable will do.

1. Create a directory under modules named taxonomy_session_defaults.

2. Put the following in taxonomy_session_defaults.module:

<?php

/**
* Adds the last saved session values for active vocabularies as preselected terms to '$node->taxonomy'
* This requires a weight lower than taxonomy.module.
*
* This may well conflict with taxonomy_defaults.module, you may want to tweak the weights of these.
*/
function taxonomy_session_defaults_form_alter($form_id, &$form) {
 
// Only alter node forms
 
if (isset($form['type']) && $form['type']['#value'] .'_node_form' == $form_id) {
   
$node = $form['#node'];
   
// Do not override terms on nodes that already have been edited
   
if (!isset($node->nid)) {
     
// Add the default session terms to this form
     
foreach (taxonomy_get_vocabularies($node->type) as $vid => $vocab) {
        if (
$_SESSION["taxses_{$node->type}_{$vid}"]) {
         
$session_tids = split(",", $_SESSION["taxses_{$node->type}_{$vid}"]);
          foreach (
$session_tids as $tid) {
           
$term = taxonomy_get_term($tid);
           
$form['#node']->taxonomy[$tid] = $term;
          }
        }
      }
    }
  }
}

/**
* Saves the selected taxonomy so it's used again in the next node created.
*/
function taxonomy_session_defaults_nodeapi(&$node, $op, $teaser = NULL, $page = NULL) {
  if (
$op == 'submit') {
   
$taxonomy = $node->taxonomy;

    foreach (
$taxonomy as $vid => $terms) {
      if (
is_array($terms)) {
       
// Save the array of terms
       
$_SESSION["taxses_{$node->type}_{$vid}"] = join(",", $terms);
      } else if (
$terms != 0) {
       
// Save a single term
       
$_SESSION["taxses_{$node->type}_{$vid}"] = $terms;
      } else {
       
// Remove anything previously saved
       
unset($_SESSION["taxses_{$node->type}_{$vid}"]);
      }
    }
  }
}

?>

3. Put the following in taxonomy_session_defaults.info:

name = Taxonomy Session Defaults
description = Assign default taxonomy terms per node-type based on last saved node.
dependencies = taxonomy
version = "5.x-0.1"

4. Put the following in taxonomy_session_defaults.install:

<?php

/**
* Hook sets taxonomy_session_defaults 'weight' to -2.
* This ensures that it's hook_form_alter runs before taxonomy & taxonomy_defaults.
* Admins may wish to tweak this weight.
*
*/
function taxonomy_session_defaults_install() {
 
$ret = array();
 
$ret[] = db_query("UPDATE {system} SET weight = -2 WHERE name = 'taxonomy_session_defaults'");
  return
$ret;
}

?>

5. Visit modules admin page and enable the new module.

Revised code

kourge - December 14, 2007 - 07:12

Here is a revised version of this mini module as per this GHOP issue. It adheres more to the coding convention.

taxonomy_session_defaults.module

<?php
/**
  * Adds the last saved session values for active vocabularies as preselected
  * terms to '$node->taxonomy'.
  * This requires a weight lower than taxonomy.module.
  *
  * This may well conflict with taxonomy_defaults.module, you may want to tweak
  * the weights of these.
  */
function taxonomy_session_defaults_form_alter($form_id, &$form) {
 
// Only alter node forms
 
if (isset($form['type']) && $form['type']['#value'] .'_node_form' == $form_id) {
   
$node = $form['#node'];
   
// Do not override terms on nodes that already have been edited
   
if (!isset($node->nid)) {
     
// Add the default session terms to this form
     
foreach (taxonomy_get_vocabularies($node->type) as $vid => $vocab) {
       
$key = 'taxonomy_session_'. $node->type .'_'. $vid;
        if (
$_SESSION[$key]) {
         
$session_tids = split(',', $_SESSION[$key]);
          foreach (
$session_tids as $tid) {
           
$term = taxonomy_get_term($tid);
           
$form['#node']->taxonomy[$tid] = $term;
          }
        }
      }
    }
  }
}

/**
  * Saves the selected taxonomy so it's used again in the next node created.
  */
function taxonomy_session_defaults_nodeapi(&$node, $op, $teaser = NULL, $page = NULL) {
  if (
$op == 'submit') {
    foreach (
$node->taxonomy as $vid => $terms) {
     
$key = 'taxonomy_session_'. $node->type .'_'. $vid;
      if (
is_array($terms)) {
       
// Save the array of terms
       
$_SESSION[$key] = join(',', $terms);
      }
      else if (
$terms != 0) {
       
// Save a single term
       
$_SESSION[$key] = $terms;
      }
      else {
       
// Remove anything previously saved
       
unset($_SESSION[$key]);
      }
    }
  }
}
?>

Don't forget to leave out the ?> at the end, as it is known to cause problems.

taxonomy_session_defaults.install

<?php
/**
  * Hook sets taxonomy_session_defaults 'weight' to -2.
  * This ensures that its hook_form_alter runs before taxonomy and
  * taxonomy_defaults.
  * Admins may wish to tweak this weight.
  */
function taxonomy_session_defaults_install() {
 
$ret = array();
 
$ret[] = db_query("UPDATE {system} SET weight = -2 WHERE name = 'taxonomy_session_defaults'");
  return
$ret;
}
?>

Again, don't forget to leave out the ?> at the end, as it is known to cause problems.

taxonomy_session_defaults.info can be left as it is.

I changed

derhasi - January 18, 2008 - 17:17

I changed taxonomy_session_defaults_form_alter for being able to also set Taxonomy via GETs.

E.g. it's useful for giving the user an oppurtunity to post a picture in the current gallery - without the need of selecting the gallery's term. Therefore just place a link like node/add/picture?tax_1=23 (1 is the number of the vocabulary and 23 the number of the gallery's taxonomy term.) in your gallery's node view.

<?php
function taxonomy_session_defaults_form_alter($form_id, &$form) {
 
// Only alter node forms
 
if (isset($form['type']) && $form['type']['#value'] .'_node_form' == $form_id) {
   
$node = $form['#node'];
   
// Do not override terms on nodes that already have been edited
   
if (!isset($node->nid)) {
     
// Add the default session terms to this form
     
foreach (taxonomy_get_vocabularies($node->type) as $vid => $vocab) {
       
$key = 'taxonomy_session_'. $node->type .'_'. $vid;
       
$session_tids = array();
        if (
$_GET['tax_'.$vid]){// GET-request is handled before SESSION-value
         
$session_tids = split(',', $_GET['tax_'.$vid]);
        }
        elseif (
$_SESSION[$key]) {
         
$session_tids = split(',', $_SESSION[$key]);
        }
        foreach (
$session_tids as $tid) {
           
$term = taxonomy_get_term($tid);
           
$form['#node']->taxonomy[$tid] = $term;
        }
      }
    }
  }
}
?>

Some coding style issues

chx - December 4, 2007 - 14:38

If you want to save session storage then simply use t_ unlikely someone else does the same with the same key structure. If you want to be readable then use taxonomy_session_ as prefix. Aka: "do or do not, there is no try". Use if (isset()) instead of if() to avoid notices. Finally, "t_{$node->type}_{$vid}" is just plain ugly, use single quotes and concat with a dot.
--
The news is Now Public | Drupal development: making the world better, one patch at a time. | A bedroom without a teddy is like a face without a smile. |

Minor style

add1sun - December 4, 2007 - 14:42

One last little style issue is that in Drupal code we prefer that
} else {
actually be done:

}
else {

 
 

Drupal is a registered trademark of Dries Buytaert.