Content type specific taxonomy settings.

Events happening in the community are now at Drupal community events on www.drupal.org.
alan d.'s picture

Hi all

Just wondering if anyone has played with the idea of content type specific taxonomy settings.

Currently, the only way to implement a 1-1 and a 1-n relationship between two different content types that I know of would be to do this manually via CCK or the fapi for the two types. Similar situation for required fields.

A quick look at the code, albeit a very very short look, seems that this would not be to hard to implement this. Free tagging could be more interesting. Has anyone tried this in the past?

A use case for this would be a sports classification. A book could optionally cover any number of sports, but a race must be assigned a singular sport.

This has probably been covered in the past, but the search simply returned far to many hits to read them all.

Thx.

Comments

I may be having a related problem

alexevasion's picture

Please tell me if this makes sense and if the solution is obvious to you? I'm building a fitness site and I have a few different types of content. I want to be able to browse the content types (exercises, routines, articles) separately. I can browse exercises by taxonomy terms using the vocabulary index module, but I can't seem to find a way to do so separately for the other content types. Exercises and routines share some common vocabulary, but articles are off on their own. I tried using wiki modules to wall off articles, but failed there too. Do you have any idea how I could accomplish this seemingly easy task? How does this relate to what you are proposing above? Thanks,
ALEX
www.youfitter.org

"Cognito Ergo Sum. Ideas rarely come along without the power to make them reality. One must, nevertheless, suffer their passions."

Have a look at views

alan d.'s picture

Views provide the easiest solution to do what you want. Create a view for each content type that is linked to the taxonomic section. If you're really keen, try writing your own views via a custom module, but requires a reasonable level of Drupal expertise.

My interest is in the desire/need to actually specify individual taxonomy settings per content type, rather than having to share these between all content types. Another example is a region vocabulary. A locatin would have a single term assigned, a trip would have multiple.

hook_form_alter

catch's picture

You could do single/multiple etc. with hook_form_alter - I think forum.module does this in core to change required settings depending on whether the node is a forum topic or something else.

Required taxonomy settings per content-type

ar-jan's picture

You mention this in the first post. I have been looking for this, found a few references of people asking about this, but no solutions. Would this be hard to accomplish? I would for example make choosing a term from 'Project' vocabulary required for content-type Project, but optional for content-type Images, or News, etc. Seems like a must-have feature to me!

Custom coding required

alan d.'s picture

The only way to do this currently is to code this up yourself using hook_form_alter or via a programmed content type.

For example, one of my types is using this in the hook_form

<?php
  $vocabulary
= taxonomy_vocabulary_load(RCTOPOS_VOCAB_REGION);
 
$form['taxonomy']['regions'] = _taxonomy_term_select(check_plain($vocabulary->name), 'not used', $node->regions, RCTOPOS_VOCAB_REGION, $vocabulary->help, 1, t('- None -'));
 
$form['taxonomy']['regions']['#weight'] = -1;
?>

This loads up the vocabulary and uses the taxonomy select (standard FAPI select element) to insert it into the fieldset that has the other "standard" taxonomy elements. This way I am able to modify it as a multi-select rather than a single select which is the default for that vocabulary.

The next step is to save the data you collect. Using hook_form_alter, you would either hook into node_insert and node_update, or add a submit handler to update a custom field in one of your tables. For a single field or two, this is how I would usually do it.

The following is overkill unless you have a large project.

In this example, I'm adding a lot of extra fields (10+), so without looking to deeply into the taxonomy module, I duplicated the code from the taxonomy module to handle the database queries, using a new table to store the data. I done this as I was worried that if I reused the taxonomy tables, the data may have been overwritten/deleted. (Notice how the taxonomy node_save works, deletes then inserts)

So I created a new table to save my data;

CREATE TABLE term_node_custom (
  nid int(10) unsigned NOT NULL default '0',
  vid int(10) unsigned NOT NULL default '0',
  tid int(10) unsigned NOT NULL default '0',
  PRIMARY KEY  (tid,vid),
  KEY vid (vid),
  KEY nid (nid)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;

and cloned the following code to do the inserts/updates

<?php
function rctopos_node_load_taxomony_extras($node, $vid) {
 
$result = db_query(db_rewrite_sql('SELECT t.tid FROM {term_data} t INNER JOIN {term_node_custom} r ON r.tid = t.tid WHERE t.vid = %d AND r.vid = %d ORDER BY weight', 't', 'tid'), $vid, $node->vid);
 
$terms = array();
  while (
$term = db_fetch_object($result)) {
   
$terms[] = $term->tid;
  }
  return
$terms;
}

/<
strong>
*
Save term associations for a given node.
*/
function
rctopos_node_save($node, $terms) {
 
rctopos_node_delete_revision($node);

  if (
is_array($terms)) {
    foreach (
$terms as $term) {
      if (
is_array($term)) {
        foreach (
$term as $tid) {
          if (
$tid) {
           
db_query('INSERT INTO {term_node_custom} (nid, vid, tid) VALUES (%d, %d, %d)', $node->nid, $node->vid, $tid);
          }
        }
      }
      else if (
is_object($term)) {
       
db_query('INSERT INTO {term_node_custom} (nid, vid, tid) VALUES (%d, %d, %d)', $node->nid, $node->vid, $term->tid);
      }
      else if (
$term) {
       
db_query('INSERT INTO {term_node_custom} (nid, vid, tid) VALUES (%d, %d, %d)', $node->nid, $node->vid, $term);
      }
    }
  }
}

/</
strong>
*
Remove associations of a node to its terms.
*/
function
rctopos_node_delete($node) {
 
db_query('DELETE FROM {term_node_custom} WHERE nid = %d', $node->nid);
}

/**
* Remove associations of a node to its terms.
*/
function rctopos_node_delete_revision($node) {
 
db_query('DELETE FROM {term_node_custom} WHERE vid = %d', $node->vid);
}
?>

Then these are called via the respective node hooks, load, save, delete, update, and hook_nodeapi operation "delete revision".

It would be nice to simply check a check box on a content type specific taxonomy setting to do all this automatically! Thus the nature of the post wondering about how much interest there is in this to help motivate the taxonomy authors to consider it.

Alan D, is this the only way

halfiranian's picture

Alan D, is this the only way to make a vocabulary multiple select for some node types and 'single select' for others?

This seems mighty complicated to my non-hardcore-coder eye.

Getting required or not is fairly simple, but multiple select or not isn't.

Cheers for posting this though.

simple work around for required

alan d.'s picture

If the vocab is not required as a whole, simply use hook_form_alter to flag the tax element as required for each node type that requires it. The node is usually in $form['#node'], and add a check on $form['#node']->type to set the elements required field.

The relevant element to set

jumpfightgo@groups.drupal.org-gdo's picture

The relevant element to set is '#required'. Print out the $form array and then find the taxonomy you want to be required. Here is an example for Drupal 6:

function YOURMODULE_form_alter(&$form, $form_state, $form_id) {
  // check form id to apply only to specific node type, in this example story node type
  if($form_id == 'story_node_form'){
    // uncomment the next line to view the entire form array
    //print_r($form); 
    // here's where you set the required element, in this case I am requiring the vocabulary 3, you'll have to find the vocabulary you want to require yourself by looking in the form array
    $form['taxonomy'][3]['#required'] = 1;
  }
}

My form doesn't have $form['taxonomy']

mattgilbert's picture

Even though the tags field shows up in the form, $form['taxonomy'] doesn't show up if I print_R($form, TRUE).

Ignoring this and setting $form['taxonomy'][1]['#required'] = 1; has no effect. The tags are still not required. I'm guessing you were using Drupal 5 and there's something different about how this is handled in Drupal 6, which is what I'm using?

Edit: Nevermind, this is only true when I tried the HOOK_form_FORM_ID_alter(), since it's called before any HOOK_form_alter()'s, including taxonomy's.

The structure was a little different though,; the variable to change for me was $form['taxonomy']['tags'][1]['#required']. Maybe because I'm using a free-tagging vocabulary.

Yes, this would be valuable

sdmaxey's picture

Yes, Alan.

I came across this need on my first site build, and I was surprised it wasn't there--the ability to set a vocabulary as required for one content type but optional for another with a simple checkbox on either the taxonomy page or the content-type editing page.

still confused about hook_form_alter

rsn8's picture

what I'm trying to do:

I have the need to have certain vocabularies be required for certain content types and optional for others. specifically, I want authenticated users to be required to categorize their articles (i.e., story) while having the same taxonomy be optional for "page" content types. can someone please explain how to create a hook_form_alter that will handle this? I'm not quite sure how to create the hook_form_alter bit at all or where it goes in my file structure. very confused. please help this newbie.

Content Taxonomy

Jim Bacon's picture

You might find that the Content Taxonomy module can help with this. It provides a CCK field type for referencing taxonomy terms which is independent from vocabulary settings.

Setting the taxonomy term for specific content type

hansyg's picture

I came across this thread during my search for the solution to my problem.

My situation: I had a vocabulary with 3 terms. 3 different content types used this taxonomy. For one specific content type I needed a specific term selected when the node was created.

The nodes are created by a module that dumps in feed elements into the custom content type. This forum helped me figure it out
instead of making the taxonomy field required using the above code

['taxonomy'][1]['#required'] = 1

I used a print_r to get the correct vocabulary id [vid] and term id [tid]
For my example the vid=56 and the tid=145279
Then just used the following to set the correct term for the content type before saving the node
$node->taxonomy[56][tid] = 145279;

Hope this helps someone else that comes along. Thanks for the thread!

Multiple select...

darnzen's picture

I know this is an old topic, but for D6 I've used in the appropriate form_alter function:

$form['taxonomy'][$vid]['#multiple'] = 1;

This converts a vocab with a single term setting (select element), to a multiple term list element.

And... that's it. All the terms are saved and loaded correctly.

Taxonomy

Group organizers

Group notifications

This group offers an RSS feed. Or subscribe to these personalized, sitewide feeds: