[drupal-devel] Question on taxonomy_form() function -- SOLVED

Scott Courtney scott at 4th.com
Thu Mar 31 16:22:16 UTC 2005

On Wednesday 30 March 2005 09:49, Morbus Iff wrote:
> > Your comments do raise another possibility, though, in that I could simply
> > walk through the complex array and make a simple one containing *all* the
> > tids for *all* the vocabs represented on my page. Presumably taxonomy_form
> > does an array search as it emits each <OPTION> tag, to see if that particular
> > tid should get SELECTED or not. If there are extra tids listed in the array,
> > one would presume that they would simply never match on the searches, and would
> I believe that is correct, yes. I remember noticing this in one of my 
> fiddly sessions with folksonomy [...]

It does work as Morbus and I had presumed. You can safely pass a simple array
with *all* the tids (not vids) to taxonomy_form() and it behaves as expected.

I wrote a function that extracts the tids from a complex taxonomy array, with
the assumption that the any non-array element is a tid. Here is the code:

 * Scans a multi-level array with term ID numbers buried inside arrays
 * inside arrays inside arrays...etc., and returns a simple array with just
 * the tid numbers linearized plus, optionally, any free-tags entered by the
 * user if a free-tag string is present in the input array.
 * WARNING: This function uses recursion; modify with care or an infinite
 * recursion loop is possible.
 * For the outermost (non-recursed) invocation only, the parameter $keep_tags
 * (default TRUE) tells the function to retain, unmodified, any element of
 * the $tid_array whose subscript is 'tags'. This causes the subarray placed
 * by the free-tag patch to taxonomy.module to work correctly across previews.
 * Note that $tid_array['tags'] is a single-element sub-array containing one
 * string element with the free-form tags.
 * If your installation does not have the free-tag support, the $keep_tags
 * parameter has no effect since $tid_array['tags'] will not be present.
 * It is necessary to disable $keep_tags only if you want to ensure that the
 * returned array from this function has only existing tids in it.
function _image_import_extract_tids($tid_array, $keep_tags=TRUE) {
  $tids = array();
  if (is_array($tid_array)) {
    foreach ($tid_array as $key=>$element) {
      if (is_int($key)) {
        if (is_array($element)) {
          // $keep_tags is NEVER useful when recursing
          $tids = array_merge($tids, _image_import_extract_tids($element, FALSE));
        } else {
          $tids[] = $element;
  if ($keep_tags && isset($tid_array['tags'])) {
    $tids['tags'] = $tid_array['tags'];
  return $tids;

This might be a useful function (if renamed) to include in taxonomy.module
as an externally-callable API. I suspect this wheel will otherwise need to be
invented by other modules that need to use term selection forms without an
extant node object.

My immediate issue, though, solves the problem by calling a different function
from Morbus' patched taxonomy.module. I realized that I could jig up a dummy
node pretty easily, and then call 

So my form generation code now looks like this:

function _image_import_form() {
  $html = '';
  $group = '';
  $dummy_node =& new image_import_node();
  $dummy_node->type = IMAGE_IMPORT_IMAGE_NODETYPE;
  $dummy_node->taxonomy =& _image_import_extract_tids($_POST['edit']['taxonomy']);
  $taxonomy_fields_array = taxonomy_node_form(IMAGE_IMPORT_IMAGE_NODETYPE, $dummy_node);
  foreach($taxonomy_fields_array as $field) {
    $group .= $field;
  $html .= form_group(t('Categories'),$group,t(' .... explanatory text ....'));
// ...snip...
  $html .= form_submit(t('Import images'));
  return form($html,'POST');
class image_import_node {
  // dummy class

image_import_node is a trivial (as in, empty!) class that I added to my module
just so I'd have an empty object. Interestingly, there seems to be no actual
definition of an object class called "node" or "Node" in Drupal. We are relying
on mysql_fetch_object() and the corresponding functions for other databases to
create an object on node load, and then we treat that object as a node.

The above works like a charm, and even has Morbus' free-tag text box so that the
user can enter their tags. It was tricky to get the free-tags to persist across
the call to _image_import_extract_tids(), but I've solved that by making the
array element "tags" a special case. If the free-tag patch isn't installed, no
harm is done because that special case simply never occurs.

I haven't tried the following yet, but I believe that calling
taxonomy_node_save() after I've imported each new node will properly update
{term_node} and {term_data} tables. From looking at the code, it seems that this
function does exactly what I need it to do.

Anyway, I wanted to thank those who posted suggestions, and to let others know
how I solved the problem. Since Morbus' patch is new, it seemed relevant to
let other coders know that this is a soluble issue and to share the solution.

If all goes well, the new "walkah" image.module will have a mass import feature
very soon.


Scott Courtney   | "I don't mind Microsoft making money. I mind them
scott at 4th.com    | having a bad operating system."    -- Linus Torvalds
http://4th.com/  | ("The Rebel Code," NY Times, 21 February 1999)
           | PGP Public Key at http://4th.com/keys/scott.pubkey

More information about the drupal-devel mailing list