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.

Comments

kourge’s picture

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


/**
  * 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


/**
  * 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.

derhasi’s picture

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.


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;
        }
      }
    }
  }
}

chx’s picture

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. |

--
Drupal development: making the world better, one patch at a time. | A bedroom without a teddy is like a face without a smile.

add1sun’s picture

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

}
else {

Drupalize.Me, The best Drupal training, available all the time, anywhere!