taxonomy.module 31.5 KB
Newer Older
Dries's avatar
 
Dries committed
1
<?php
Kjartan's avatar
Kjartan committed
2
// $Id$
Dries's avatar
 
Dries committed
3

4
function taxonomy_system($field){
Kjartan's avatar
Kjartan committed
5
  $system["description"] = t("Enables the organization of content into categories.");
6 7 8
  return $system[$field];
}

Kjartan's avatar
Kjartan committed
9 10
function taxonomy_feed() {
  global $id, $or, $and, $type;
Dries's avatar
 
Dries committed
11

Kjartan's avatar
Kjartan committed
12 13 14 15 16 17 18
  if ($type == "voc") {
    //TODO - vocabulary feed. How to represent an outline in XML?
  }
  else {
    if ($or) {
      foreach ((explode(",", $or)) as $t) {
        $terms[] = "'". check_query($t) ."'";
Dries's avatar
 
Dries committed
19
      }
Kjartan's avatar
Kjartan committed
20 21 22 23 24 25
      $result = db_query("SELECT DISTINCT(n.nid), type FROM node n LEFT JOIN term_node r ON n.nid = r.nid WHERE tid IN (". implode(",", $terms) .") AND status = '1' ORDER BY static DESC, created DESC LIMIT 15");
      $term = taxonomy_get_term($or);
    }
    else if ($and) {
      foreach ((explode(",", $and)) as $t) {
        $terms[] = "'". check_query($t) ."'";
Dries's avatar
 
Dries committed
26
      }
27
      $result = db_query("SELECT n.nid, type, count(*) AS c FROM node n LEFT JOIN term_node r ON n.nid = r.nid WHERE tid IN (". implode(",", $terms) .") AND status = '1' GROUP BY n.nid, n.type HAVING c = ". count($terms) ." ORDER BY static DESC, created DESC LIMIT 15");
Kjartan's avatar
Kjartan committed
28 29 30 31 32
      $term = taxonomy_get_term($and);
    }
    else {
      return node_feed();
    }
Dries's avatar
 
Dries committed
33

Kjartan's avatar
Kjartan committed
34 35 36
    $channel["title"] = variable_get("site_name", "drupal") ." - ". $term->name;
    $channel["link"] = path_uri() ."index.php?or=$or";
    $channel["description"] = $term->description;
Dries's avatar
 
Dries committed
37

Kjartan's avatar
Kjartan committed
38
    node_feed($result, $channel);
Dries's avatar
 
Dries committed
39
  }
Kjartan's avatar
Kjartan committed
40
}
Dries's avatar
 
Dries committed
41

Kjartan's avatar
Kjartan committed
42 43 44
function taxonomy_perm() {
  return array("administer taxonomy");
}
Dries's avatar
 
Dries committed
45

Kjartan's avatar
Kjartan committed
46 47
function taxonomy_link($type) {
  if ($type == "admin" && user_access("administer taxonomy")) {
Dries's avatar
 
Dries committed
48 49
    $help["taxonomy"] = "The taxonomy module allows you to classify post into categories and subcategories; it allows multiple lists of categories for classification (controlled vocabularies) and offers the possibility of creating thesauri (controlled vocabularies that indicate the relationship of terms) and taxonomies (controlled vocabularies where relationships are indicated hierarchically).";
    $help["vocabulary"] = "When you create a controlled vocabulary you are creating a set of terms to use for describing content (known as descriptors in indexing lingo).  Drupal allows you to describe each node of content (blog, story, etc.) using one or many of these terms. For simple implementations, you might create a set of categories without subcategories, similar to Slashdot.org's or Kuro5hin.org's sections. For more complex implementations, you might create a hierarchical list of categories.";
Dries's avatar
 
Dries committed
50

Dries's avatar
 
Dries committed
51
    menu_add("taxonomy", "admin.php?mod=taxonomy", "Administer taxonomies.", $help["taxonomy"], "content management", 1, 1);
Dries's avatar
 
Dries committed
52 53 54
    menu_add("add new vocabulary", "admin.php?mod=taxonomy&op=add&type=vocabulary", "Add a new vocabulary.", $help["vocabulary"], "taxonomy");
    menu_add("help", "admin.php?mod=taxonomy&op=help", "More information about taxonomies.", NULL, "taxonomy", 9);
  }
Kjartan's avatar
Kjartan committed
55 56
}

Dries's avatar
 
Dries committed
57 58 59 60
/*
** admin pages (form, save, overview)
*/

Kjartan's avatar
Kjartan committed
61 62 63 64
function taxonomy_form_vocabulary($edit = array()) {
  foreach (module_list() as $name) {
    if (module_hook($name, "node")) {
      $nodetypes[$name] = $name;
Dries's avatar
 
Dries committed
65
    }
Kjartan's avatar
Kjartan committed
66
  }
Dries's avatar
 
Dries committed
67

Dries's avatar
 
Dries committed
68 69 70 71 72 73 74
  $form .= form_textfield(t("Vocabulary name"), "name", $edit["name"], 50, 64, t("Required") . ". " . t("The name for this vocabulary.  Example: 'Topic'") . ".");
  $form .= form_textarea(t("Description"), "description", $edit["description"], 60, 5, t("Optional") . ". " . t("Description of the vocabulary, can be used by modules."));
  $form .= form_select(t("Types"), "types", explode(",", $edit["types"]), $nodetypes, t("Required") . ". " . t("A list of node types you want to associate this vocabulary with."), "", 1);
  $form .= form_checkbox(t("Related terms"), "relations", 1, $edit["relations"], t("Optional") . ". " . t("Allows ". la("related terms", array("mod" => "taxonomy", "op" => "help"), "relatedterms") ." in this vocabulary."));
  $form .= form_select(t("Hierarchy"), "hierarchy", $edit["hierarchy"], array(t("Disabled"), t("Single"), t("Multiple")), t("Optional") . ". ". t("Allows ". la("a tree-like hierarchy", array("mod" => "taxonomy", "op" => "help"), "hierarchy") ." between terms of this vocabulary."), "", 0);
  $form .= form_checkbox(t("Multiple select"), "multiple", 1, $edit["multiple"], t("Optional") . ". " . t("Allows nodes to have more than one term in this vocabulary."));
  $form .= form_checkbox(t("Required"), "required", 1, $edit["required"], t("If enabled every node <b>must</b> have at least one term in this vocabulary"));
Dries's avatar
 
Dries committed
75
  $form .= form_weight(t("Weight"), "weight", $edit["weight"], 10, t("Optional. In listings, the heavier vocabularies will sink and the lighter vocabularies will be positioned nearer the top."));
Dries's avatar
 
Dries committed
76
  $form .= form_submit(t("Submit"));
Dries's avatar
 
Dries committed
77

Kjartan's avatar
Kjartan committed
78
  if ($edit["vid"]) {
Dries's avatar
 
Dries committed
79
    $form .= form_submit(t("Delete"));
Kjartan's avatar
Kjartan committed
80
    $form .= form_hidden("vid", $edit["vid"]);
Dries's avatar
 
Dries committed
81 82
  }

Kjartan's avatar
Kjartan committed
83 84
  return form($form);
}
Kjartan's avatar
Kjartan committed
85

Kjartan's avatar
Kjartan committed
86 87 88 89
function taxonomy_save_vocabulary($edit) {
  $data = array("name" => $edit["name"], "types" => @implode(",", $edit["types"]), "description" => $edit["description"], "multiple" => $edit["multiple"], "required" => $edit["required"], "hierarchy" => $edit["hierarchy"], "relations" => $edit["relations"], "weight" => $edit["weight"]);

  if ($edit["vid"] && $edit["name"]) {
Dries's avatar
 
Dries committed
90
    db_query("UPDATE vocabulary SET ". _prepare_update($data) ." WHERE vid = '". check_query($edit["vid"]) ."'");
Dries's avatar
 
Dries committed
91 92
    module_invoke_all("taxonomy", "update", "vocabulary", $edit);
    $message = t("updated vocabulary '%name'.", array("%name" => $edit["name"]));
Dries's avatar
 
Dries committed
93
  }
Kjartan's avatar
Kjartan committed
94
  else if ($edit["vid"]) {
Dries's avatar
 
Dries committed
95
    $message = taxonomy_del_vocabulary($edit["vid"]);
Kjartan's avatar
Kjartan committed
96 97
  }
  else {
Dries's avatar
 
Dries committed
98
    $data["vid"] = db_next_id("vocabulary");
Kjartan's avatar
Kjartan committed
99
    db_query("INSERT INTO vocabulary ". _prepare_insert($data, 1) ." VALUES ". _prepare_insert($data, 2));
Dries's avatar
 
Dries committed
100 101
    module_invoke_all("taxonomy", "insert", "vocabulary", $edit);
    $message = t("created new vocabulary '%name'.", array("%name" => $edit["name"]));
Kjartan's avatar
Kjartan committed
102
  }
Dries's avatar
 
Dries committed
103 104

  cache_clear_all();
Dries's avatar
 
Dries committed
105 106

  return $message;
Kjartan's avatar
Kjartan committed
107
}
Dries's avatar
 
Dries committed
108

Kjartan's avatar
Kjartan committed
109
function taxonomy_del_vocabulary($vid) {
Dries's avatar
 
Dries committed
110 111
  $vocabulary = taxonomy_get_vocabulary($vid);

Dries's avatar
 
Dries committed
112 113
  db_query("DELETE FROM vocabulary WHERE vid = '%d'", $vid);
  $result = db_query("SELECT tid FROM term_data WHERE vid = '%d'", $vid);
Kjartan's avatar
Kjartan committed
114 115
  while ($term = db_fetch_object($result)) {
    taxonomy_del_term($term->tid);
Dries's avatar
 
Dries committed
116
  }
Dries's avatar
 
Dries committed
117

Dries's avatar
 
Dries committed
118 119
  module_invoke_all("taxonomy", "delete", "vocabulary", $vocabulary);

Dries's avatar
 
Dries committed
120 121
  cache_clear_all();

Dries's avatar
 
Dries committed
122 123 124 125 126 127 128 129 130 131 132 133 134
  return t("deleted vocabulary '%name'.", array("%name" => $vocabulary->name));
}

function _taxonomy_confirm_del_vocabulary($vid) {
  $vocabulary = taxonomy_get_vocabulary($vid);

  $form .= form_hidden("confirm", 1);
  $form .= form_hidden("type", "vocabulary");
  $form .= form_hidden("vid", $vid);
  $form .= form_submit(t("Delete"));
  $form .= form_submit(t("Cancel"));

  return form(form_item(t("Delete vocabulary '%name'", array("%name" => $vocabulary->name)), $form, t("Are you sure you want to delete the vocabulary and all its terms?")));
Kjartan's avatar
Kjartan committed
135
}
Dries's avatar
 
Dries committed
136

Kjartan's avatar
Kjartan committed
137 138 139 140 141 142
function taxonomy_form_term($edit = array()) {
  global $vocabulary_id;
  if (!$vocabulary_id) {
    $vocabulary_id = $edit["vid"];
  }
  $vocabulary = taxonomy_get_vocabulary($vocabulary_id);
Dries's avatar
 
Dries committed
143 144
  $form = form_textfield(t("Term name"), "name", $edit["name"], 50, 64, t("Required") . ". " . t("The name for this term.  Example: 'Linux'."));
  $form .= form_textarea(t("Description"), "description", $edit["description"], 60, 5, t("Optional") . ". " . t("A description of the term."));
Dries's avatar
 
Dries committed
145

Kjartan's avatar
Kjartan committed
146
  if ($vocabulary->relations) {
Dries's avatar
 
Dries committed
147
    $form .= _taxonomy_term_select(t("Related terms"), "relations", array_keys(taxonomy_get_related($edit["tid"])), $vocabulary_id, t("Optional") . ". ", 1, "<" . t("none") . ">", array($edit["tid"]));
Kjartan's avatar
Kjartan committed
148
  }
Dries's avatar
 
Dries committed
149 150


Kjartan's avatar
Kjartan committed
151 152
  if ($vocabulary->hierarchy) {
    $parent = array_keys(taxonomy_get_parents($edit["tid"]));
Dries's avatar
 
Dries committed
153
    $children = taxonomy_get_tree($vocabulary_id, $edit["tid"]);
Kjartan's avatar
Kjartan committed
154 155 156 157
    // you can't be son of yourself or your children
    $exclude = array_keys($children);
    $exclude[] = $edit["tid"];
    if ($vocabulary->hierarchy == 1) {
Dries's avatar
 
Dries committed
158
      $form .= _taxonomy_term_select(t("Parent"), "parent", $parent, $vocabulary_id, t("Required") . ". " . la(t("Parent term"), array("mod" => "taxonomy", "op" => "help"), "parent") .".", 0, "<" . t("root") . ">", $exclude);
Dries's avatar
 
Dries committed
159
    }
Kjartan's avatar
Kjartan committed
160
    elseif ($vocabulary->hierarchy == 2) {
Dries's avatar
 
Dries committed
161
      $form .= _taxonomy_term_select(t("Parents"), "parent", $parent, $vocabulary_id, t("Required") . ". ". la(t("Parent terms"), array("mod" => "taxonomy", "op" => "help"), "parent") .".", 1, "<" . t("root") . ">", $exclude);
Dries's avatar
 
Dries committed
162
    }
Kjartan's avatar
Kjartan committed
163
  }
Dries's avatar
 
Dries committed
164

Dries's avatar
 
Dries committed
165 166
  $form .= form_textarea(t("Synonyms"), "synonyms", implode("\n", taxonomy_get_synonyms($edit["tid"])), 30, 5, t("Optional") . ". ". t(la("Synonyms", array("mod" => "taxonomy", "op" => "help"), "synonyms") ." of this term, one synonym per line."));
  $form .= form_weight(t("Weight"), "weight", $edit["weight"], 10, t("Optional. In listings, the heavier terms will sink and the lighter terms will be positioned nearer the top."));
Kjartan's avatar
Kjartan committed
167
  $form .= form_hidden("vid", $vocabulary->vid);
Dries's avatar
 
Dries committed
168
  $form .= form_submit(t("Submit"));
Kjartan's avatar
Kjartan committed
169 170

  if ($edit["tid"]) {
Dries's avatar
 
Dries committed
171
    $form .= form_submit(t("Delete"));
Kjartan's avatar
Kjartan committed
172
    $form .= form_hidden("tid", $edit["tid"]);
Dries's avatar
 
Dries committed
173 174
  }

Kjartan's avatar
Kjartan committed
175 176
  return form($form);
}
Dries's avatar
 
Dries committed
177

Kjartan's avatar
Kjartan committed
178 179 180
function taxonomy_save_term($edit) {
 if ($edit["tid"] && $edit["name"]) {
    $data = array("name" => $edit["name"], "description" => $edit["description"], "weight" => $edit["weight"]);
Dries's avatar
 
Dries committed
181

Dries's avatar
 
Dries committed
182
    db_query("UPDATE term_data SET ". _prepare_update($data) ." WHERE tid = '%d'", $edit["tid"]);
Dries's avatar
 
Dries committed
183
    module_invoke_all("taxonomy", "update", "term", $edit);
Dries's avatar
 
Dries committed
184
    $message = t("the term '%a' has been updated.", array("%a" => $edit["name"]));
Kjartan's avatar
Kjartan committed
185 186
  }
  else if ($edit["tid"]) {
Dries's avatar
 
Dries committed
187
    return taxonomy_del_term($edit["tid"]);
Kjartan's avatar
Kjartan committed
188 189
  }
  else {
Dries's avatar
 
Dries committed
190
    $edit["tid"] = db_next_id("term_data");
Kjartan's avatar
Kjartan committed
191 192
    $data = array("tid" => $edit["tid"], "name" => $edit["name"], "description" => $edit["description"], "vid" => $edit["vid"], "weight" => $edit["weight"]);
    db_query("INSERT INTO term_data ". _prepare_insert($data, 1) ." VALUES ". _prepare_insert($data, 2));
Dries's avatar
 
Dries committed
193
    module_invoke_all("taxonomy", "insert", "term", $edit);
Dries's avatar
 
Dries committed
194
    $message = t("created new term '%name'.", array("%name" => $edit["name"]));
Kjartan's avatar
Kjartan committed
195
  }
Dries's avatar
 
Dries committed
196

Kjartan's avatar
Kjartan committed
197
  // relations (seem very powerful, but I have to understand it completely)
Dries's avatar
 
Dries committed
198
  db_query("DELETE FROM term_relation WHERE tid1 = '%d' OR tid2 = '%d'", $edit["tid"], $edit["tid"]);
Kjartan's avatar
Kjartan committed
199 200 201
  if ($edit["relations"]) {
    foreach ($edit["relations"] as $related_id) {
      if ($related_id != 0) {
Dries's avatar
 
Dries committed
202
        db_query("INSERT INTO term_relation (tid1, tid2) VALUES ('%d', '%d')", $edit["tid"], $related_id);
Dries's avatar
 
Dries committed
203
      }
Kjartan's avatar
Kjartan committed
204
    }
Kjartan's avatar
Kjartan committed
205
  }
Dries's avatar
 
Dries committed
206

Kjartan's avatar
Kjartan committed
207
  // hierarchy
Dries's avatar
 
Dries committed
208
  db_query("DELETE FROM term_hierarchy WHERE tid = '%d'", $edit["tid"]);
Kjartan's avatar
Kjartan committed
209 210 211 212 213
  if (!isset($edit["parent"])) {
    $edit["parent"] = 0;
  }
  if (is_array($edit["parent"])) {
    foreach ($edit["parent"] as $parent) {
Dries's avatar
 
Dries committed
214
      db_query("INSERT INTO term_hierarchy (tid, parent) VALUES ('%d', '%d')", $edit["tid"], $parent);
Dries's avatar
 
Dries committed
215
    }
Kjartan's avatar
Kjartan committed
216 217
  }
  else {
Dries's avatar
 
Dries committed
218
    db_query("INSERT INTO term_hierarchy (tid, parent) VALUES ('%d', '%d')", $edit["tid"], $edit["parent"][0]);
Dries's avatar
 
Dries committed
219 220
  }

Dries's avatar
 
Dries committed
221
  db_query("DELETE FROM term_synonym WHERE tid = '%d'", $edit["tid"]);
Kjartan's avatar
Kjartan committed
222
  if ($edit["synonyms"]) {
Dries's avatar
 
Dries committed
223 224 225 226
    foreach (explode ("\n", str_replace("\r", "", $edit["synonyms"])) as $synonym) {
      if ($synonym) {
        db_query("INSERT INTO term_synonym (tid, name) VALUES ('%d', '%s')", $edit["tid"], chop($synonym));
      }
Kjartan's avatar
Kjartan committed
227
    }
Dries's avatar
 
Dries committed
228
  }
Dries's avatar
 
Dries committed
229

Dries's avatar
 
Dries committed
230 231
  cache_clear_all();

Dries's avatar
 
Dries committed
232
  return $message;
Kjartan's avatar
Kjartan committed
233
}
Dries's avatar
 
Dries committed
234

Kjartan's avatar
Kjartan committed
235
function taxonomy_del_term($tid) {
Dries's avatar
 
Dries committed
236 237
  $term = taxonomy_get_term($tid);

Dries's avatar
 
Dries committed
238 239 240 241 242
  db_query("DELETE FROM term_data WHERE tid = '%d'", $tid);
  db_query("DELETE FROM term_hierarchy WHERE tid = '%d'", $tid);
  db_query("DELETE FROM term_relation WHERE tid1 = '%d' OR tid2 = '%d'", $tid, $tid);
  db_query("DELETE FROM term_synonym WHERE tid = '%d'", $tid);
  db_query("DELETE FROM term_node WHERE tid = '%d'", $tid);
Dries's avatar
 
Dries committed
243

Dries's avatar
 
Dries committed
244
  module_invoke_all("taxonomy", "delete", "term", $term);
Dries's avatar
 
Dries committed
245 246
  cache_clear_all();

Dries's avatar
 
Dries committed
247 248 249 250 251 252 253 254 255 256 257 258 259
  return t("deleted term '%name'.", array("%name" => $term->name));
}

function _taxonomy_confirm_del_term($tid) {
  $term = taxonomy_get_term($tid);

  $form .= form_hidden("confirm", 1);
  $form .= form_hidden("type", "term");
  $form .= form_hidden("tid", $tid);
  $form .= form_submit(t("Delete"));
  $form .= form_submit(t("Cancel"));

  return form(form_item(t("Delete term '%name'", array("%name" => $term->name)), $form, t("Are you sure you want to delete the term?")));
Kjartan's avatar
Kjartan committed
260
}
Dries's avatar
 
Dries committed
261

Kjartan's avatar
Kjartan committed
262 263
function taxonomy_overview() {
  global $tree;
Dries's avatar
 
Dries committed
264

Dries's avatar
 
Dries committed
265
  $output .= "<h3>" . t("Vocabularies overview") . "</h3>";
Dries's avatar
 
Dries committed
266 267

  $header = array(t("name"), t("node types"), array("data" => t("operations"), "colspan" => 3));
Dries's avatar
 
Dries committed
268

Kjartan's avatar
Kjartan committed
269 270 271
  $vocabularies = taxonomy_get_vocabularies();
  foreach ($vocabularies as $vocabulary) {
    $links = array();
Dries's avatar
 
Dries committed
272

Dries's avatar
 
Dries committed
273
    $rows[] = array($vocabulary->name, array("data" => $vocabulary->types, "align" => "center"), la(t("edit vocabulary"), array("mod" => "taxonomy", "type" => "vocabulary", "op" => "edit", "id" => $vocabulary->vid)), la(t("add term"), array("mod" => "taxonomy", "op" => "add", "type" => "leaf", "vocabulary_id" => $vocabulary->vid)), la(t("preview form"), array("mod" => "taxonomy", "type" => "vocabulary", "op" => "preview", "id" => $vocabulary->vid)));
Kjartan's avatar
Kjartan committed
274

Dries's avatar
 
Dries committed
275
    $tree = taxonomy_get_tree($vocabulary->vid);
Kjartan's avatar
Kjartan committed
276
    if ($tree) {
Dries's avatar
 
Dries committed
277
      unset($data);
Kjartan's avatar
Kjartan committed
278
      foreach ($tree as $term) {
Dries's avatar
 
Dries committed
279
        $data .= _taxonomy_depth($term->depth) ." ". $term->name ." (". la(t("edit term"), array("mod" => "taxonomy", "op" => "edit", "type" => "term", "id" => $term->tid)) .")<br />";
Dries's avatar
 
Dries committed
280
      }
Dries's avatar
 
Dries committed
281
      $rows[] = array(array("data" => $data, "colspan" => 5));
Dries's avatar
 
Dries committed
282 283 284
    }
  }

Dries's avatar
 
Dries committed
285
  return table($header, $rows);
Kjartan's avatar
Kjartan committed
286 287 288 289 290 291 292 293 294 295
}

function taxonomy_form($vocabulary_id, $value = 0) {
  $vocabulary = taxonomy_get_vocabulary($vocabulary_id);
  if ($vocabulary->required) {
    $verb = "must";
    $blank = 0;
  }
  else {
    $verb = "can";
Dries's avatar
 
Dries committed
296
    $blank = "<" . t("none") . ">";
Kjartan's avatar
Kjartan committed
297
  }
Dries's avatar
 
Dries committed
298

Kjartan's avatar
Kjartan committed
299
  if ($vocabulary->multiple) {
Dries's avatar
 
Dries committed
300
    $description = t("You $verb choose one or more terms for this node.");
Kjartan's avatar
Kjartan committed
301
    $multiple = 1;
Dries's avatar
 
Dries committed
302
  }
Kjartan's avatar
Kjartan committed
303
  else {
Dries's avatar
 
Dries committed
304
    $description = t("You $verb choose one term for this node.");
Kjartan's avatar
Kjartan committed
305 306 307 308
    $multiple = 0;
  }
  return _taxonomy_term_select($vocabulary->name, "taxonomy", $value, $vocabulary_id, $description, $multiple, $blank);
}
Dries's avatar
 
Dries committed
309 310 311 312 313

/*
** API functions
*/

Kjartan's avatar
Kjartan committed
314 315 316 317 318 319 320 321 322 323 324
// return array of vocabularies, as objects
function taxonomy_get_vocabularies($type = '', $key = "vid") {
  if ($type) {
    $result = db_query("SELECT * FROM vocabulary WHERE types LIKE '%%%s%%' ORDER BY weight, name", $type);
  }
  else {
    $result = db_query("SELECT * FROM vocabulary ORDER BY weight, name");
  }
  $vocabularies = array();
  while ($voc = db_fetch_object($result)) {
    $vocabularies[$voc->$key] = $voc;
Dries's avatar
 
Dries committed
325
  }
Kjartan's avatar
Kjartan committed
326 327
  return $vocabularies;
}
Dries's avatar
 
Dries committed
328

Kjartan's avatar
Kjartan committed
329 330 331 332 333
// return form with current term
function taxonomy_node_form($type, $node = '') {
  if (!$node->taxonomy) {
    if ($node->nid) {
      $terms = array_keys(taxonomy_node_get_terms($node->nid));
Kjartan's avatar
Kjartan committed
334 335
    }
    else {
Kjartan's avatar
Kjartan committed
336
      $terms = 0;
Dries's avatar
 
Dries committed
337
    }
Kjartan's avatar
Kjartan committed
338 339 340 341
  }
  else {
    $terms = $node->taxonomy;
  }
Dries's avatar
 
Dries committed
342

Kjartan's avatar
Kjartan committed
343 344 345
  $c = db_query("SELECT * FROM vocabulary WHERE types LIKE '%%%s%%' ORDER BY weight, name", $type);
  while ($vocabulary = db_fetch_object($c)) {
    $result[] .= taxonomy_form($vocabulary->vid, $terms);
Dries's avatar
 
Dries committed
346
  }
Kjartan's avatar
Kjartan committed
347 348
  return $result ? $result : array();
}
Dries's avatar
 
Dries committed
349

Kjartan's avatar
Kjartan committed
350 351 352
// return 1 if node identified by $nid contains a taxonomy term identified by $tid in his body or title
function taxonomy_node_has_term($nid, $tid) {
  $term_name = db_result(db_query("SELECT name FROM term_data WHERE tid = '%s'", $tid));
Dries's avatar
 
Dries committed
353

Dries's avatar
 
Dries committed
354
  return db_result(db_query("SELECT COUNT(n.nid) FROM node n WHERE n.nid = '%d' AND ((n.body LIKE '%%%s%%') OR (n.body LIKE '%%%s%%'))", $nid, $term_name, $term_name));
Kjartan's avatar
Kjartan committed
355 356 357 358
}

// return array of terms of a node beloging to a particular vocabulary identified by $vid
function taxonomy_node_get_terms_by_vocabulary($nid, $vid, $key = "tid") {
Dries's avatar
 
Dries committed
359
  $result = db_query("SELECT t.* FROM term_data t, term_node r WHERE t.tid = r.tid AND t.vid = '%d' AND r.nid = '%d' ORDER BY weight", $vid, $nid);
Kjartan's avatar
Kjartan committed
360 361 362
  $terms = array();
  while ($term = db_fetch_object($result)) {
    $terms[$term->$key] = $term;
Dries's avatar
 
Dries committed
363
  }
Kjartan's avatar
Kjartan committed
364 365 366 367 368 369
  return $terms;
}

// return array of terms of a node
function taxonomy_node_get_terms($nid, $key = "tid") {
  static $terms;
Dries's avatar
 
Dries committed
370

Dries's avatar
 
Dries committed
371
  if (!isset($terms[$nid])) {
Dries's avatar
 
Dries committed
372
    $result = db_query("SELECT t.* FROM term_data t, term_node r WHERE r.tid = t.tid AND r.nid = '%d' ORDER BY weight, name", $nid);
Kjartan's avatar
Kjartan committed
373
    $terms[$nid] = array();
Dries's avatar
 
Dries committed
374
    while ($term = db_fetch_object($result)) {
Kjartan's avatar
Kjartan committed
375
      $terms[$nid][$term->$key] = $term;
Dries's avatar
 
Dries committed
376 377
    }
  }
Kjartan's avatar
Kjartan committed
378 379
  return $terms[$nid];
}
Dries's avatar
 
Dries committed
380

Kjartan's avatar
Kjartan committed
381 382 383
// save terms of a node
function taxonomy_node_save($nid, $terms) {
  taxonomy_node_delete($nid);
Dries's avatar
 
Dries committed
384

Kjartan's avatar
Kjartan committed
385
  if ($terms) {
Dries's avatar
 
Dries committed
386 387
    foreach ($terms as $term) {
      db_query("INSERT INTO term_node (nid, tid) VALUES ('%d', '%d')", $nid, $term);
Dries's avatar
 
Dries committed
388 389
    }
  }
Kjartan's avatar
Kjartan committed
390
}
Dries's avatar
 
Dries committed
391

Kjartan's avatar
Kjartan committed
392 393
// clean up terms
function taxonomy_node_delete($nid) {
Dries's avatar
 
Dries committed
394
  db_query("DELETE FROM term_node WHERE nid = '%d'", $nid);
Kjartan's avatar
Kjartan committed
395
}
Dries's avatar
 
Dries committed
396

Kjartan's avatar
Kjartan committed
397 398 399
// relations: return array of related terms
function taxonomy_get_related($tid, $key = "tid") {
  if ($tid) {
Dries's avatar
 
Dries committed
400
    $result = db_query("SELECT t.*, tid1, tid2 FROM term_relation, term_data t WHERE (t.tid = tid1 OR t.tid = tid2) AND (tid1 = '%d' OR tid2 = '%d') AND t.tid != '%d' ORDER BY weight, name", $tid, $tid, $tid);
Kjartan's avatar
Kjartan committed
401 402 403
    $related = array();
    while ($term = db_fetch_object($result)) {
      $related[$term->$key] = $term;
Dries's avatar
 
Dries committed
404
    }
Kjartan's avatar
Kjartan committed
405
    return $related;
Dries's avatar
 
Dries committed
406
  }
Kjartan's avatar
Kjartan committed
407 408
  else {
    return array();
Dries's avatar
 
Dries committed
409
  }
Kjartan's avatar
Kjartan committed
410
}
Dries's avatar
 
Dries committed
411

Kjartan's avatar
Kjartan committed
412 413 414
// hierarchy: get parent terms
function taxonomy_get_parents($tid, $key = "tid") {
  if ($tid) {
Dries's avatar
 
Dries committed
415
    $result = db_query("SELECT t.* FROM term_hierarchy h, term_data t WHERE h.parent = t.tid AND h.tid = '%d' ORDER BY weight, name", $tid);
Kjartan's avatar
Kjartan committed
416 417 418
    $parents = array();
    while ($parent = db_fetch_object($result)) {
      $parents[$parent->$key] = $parent;
Dries's avatar
 
Dries committed
419
    }
Kjartan's avatar
Kjartan committed
420
    return $parents;
Dries's avatar
 
Dries committed
421
  }
Kjartan's avatar
Kjartan committed
422 423 424 425
  else {
    return array();
  }
}
Dries's avatar
 
Dries committed
426

Kjartan's avatar
Kjartan committed
427 428 429
// hierarchy: get children
function taxonomy_get_children($tid, $vid = 0, $key = "tid") {
  if ($vid) {
Dries's avatar
 
Dries committed
430
    $result = db_query("SELECT t.* FROM term_hierarchy h, term_data t WHERE t.vid = '%d' AND h.tid = t.tid AND h.parent = '%d' ORDER BY weight, name", $vid, $tid);
Dries's avatar
 
Dries committed
431
  }
Kjartan's avatar
Kjartan committed
432
  else {
Dries's avatar
 
Dries committed
433
    $result = db_query("SELECT t.* FROM term_hierarchy h, term_data t WHERE h.tid = t.tid AND parent = '%d' ORDER BY weight", $tid);
Kjartan's avatar
Kjartan committed
434 435 436 437 438 439 440
  }
  $children = array();
  while ($term = db_fetch_object($result)) {
    $children[$term->$key] = $term;
  }
  return $children;
}
Dries's avatar
 
Dries committed
441

Kjartan's avatar
Kjartan committed
442
// hierarchy: get whole family, with tid, parent and depth; useful to show
Dries's avatar
 
Dries committed
443
function taxonomy_get_tree($vocabulary_id, $parent = 0, $depth = -1, $key = "tid") {
Dries's avatar
 
Dries committed
444
  static $children, $parents, $terms;
Dries's avatar
 
Dries committed
445

Kjartan's avatar
Kjartan committed
446
  $depth++;
Dries's avatar
 
Dries committed
447

Dries's avatar
 
Dries committed
448 449 450 451
  // we cache trees, so it's not cpu-intensive to call get_tree on a term and its children too
  if (!isset($children[$vocabulary_id])) {
    $children[$vocabulary_id] = array();

Dries's avatar
 
Dries committed
452 453
    $result = db_query("SELECT t.*, parent FROM term_data t, term_hierarchy h WHERE t.tid = h.tid AND t.vid = '%d' ORDER BY weight, name", $vocabulary_id);
    while ($term = db_fetch_object($result)) {
Dries's avatar
 
Dries committed
454 455 456
      $children[$vocabulary_id][$term->parent][] = $term->tid;
      $parents[$vocabulary_id][$term->tid][] = $term->parent;
      $terms[$vocabulary_id][$term->tid] = $term;
Dries's avatar
 
Dries committed
457 458
    }
  }
Dries's avatar
 
Dries committed
459

Dries's avatar
 
Dries committed
460 461 462 463 464 465
  if ($children[$vocabulary_id][$parent]) {
    foreach ($children[$vocabulary_id][$parent] as $child) {
      $terms[$vocabulary_id][$child]->depth = $depth;
      unset($terms[$vocabulary_id][$child]->parent); // this is not useful as it would show one parent only
      $terms[$vocabulary_id][$child]->parents = $parents[$vocabulary_id][$child];
      $tree[] = $terms[$vocabulary_id][$child];
Dries's avatar
 
Dries committed
466

Dries's avatar
 
Dries committed
467
      $tree = array_merge($tree, taxonomy_get_tree($vocabulary_id, $child, $depth));
Dries's avatar
 
Dries committed
468
    }
Kjartan's avatar
Kjartan committed
469
  }
Dries's avatar
 
Dries committed
470

Dries's avatar
 
Dries committed
471
  return $tree ? $tree : array();
Kjartan's avatar
Kjartan committed
472
}
Dries's avatar
 
Dries committed
473

Kjartan's avatar
Kjartan committed
474 475 476
// synonyms: return array of synonyms
function taxonomy_get_synonyms($tid) {
  if ($tid) {
Dries's avatar
 
Dries committed
477
    $result = db_query("SELECT name FROM term_synonym WHERE tid = '%d'", $tid);
Kjartan's avatar
Kjartan committed
478 479
    while ($synonym = db_fetch_array($result)) {
      $synonyms[] = $synonym["name"];
Dries's avatar
 
Dries committed
480
    }
Kjartan's avatar
Kjartan committed
481
    return $synonyms ? $synonyms : array();
Dries's avatar
 
Dries committed
482
  }
Kjartan's avatar
Kjartan committed
483 484
  else {
    return array();
Dries's avatar
 
Dries committed
485
  }
Kjartan's avatar
Kjartan committed
486
}
Dries's avatar
 
Dries committed
487

Kjartan's avatar
Kjartan committed
488 489 490 491
// synonyms: return original term
function taxonomy_get_synonym_root($term) {
  return db_fetch_object(db_query("SELECT * FROM term_synonym s, term_data t WHERE t.tid = s.tid AND s.name = '%s'", $term));
}
Dries's avatar
 
Dries committed
492

Kjartan's avatar
Kjartan committed
493
// given a term id, count number of nodes in it
Dries's avatar
 
Dries committed
494
function taxonomy_term_count_nodes($tid, $type = 0) {
Kjartan's avatar
Kjartan committed
495
  static $count;
Dries's avatar
 
Dries committed
496

Dries's avatar
 
Dries committed
497 498 499
  if (!isset($count[$type])) {
    // $type == 0 always evaluates true is $type is a string
    if (is_numeric($type)) {
Dries's avatar
 
Dries committed
500
      $result = db_query("SELECT t.tid, COUNT(*) AS c FROM term_node t GROUP BY t.tid");
Dries's avatar
 
Dries committed
501 502
    }
    else {
Dries's avatar
 
Dries committed
503
      $result = db_query("SELECT t.tid, COUNT(*) AS c FROM term_node t, node n WHERE t.nid = n.nid AND n.type = '%s' GROUP BY t.tid", $type);
Dries's avatar
 
Dries committed
504
    }
Kjartan's avatar
Kjartan committed
505
    while ($term = db_fetch_object($result)) {
Dries's avatar
 
Dries committed
506
      $count[$type][$term->tid] = $term->c;
Dries's avatar
 
Dries committed
507 508 509
    }
  }

Kjartan's avatar
Kjartan committed
510
  foreach (_taxonomy_term_children($tid) as $c) {
Dries's avatar
 
Dries committed
511
    $children_count += taxonomy_term_count_nodes($c, $type);
Kjartan's avatar
Kjartan committed
512
  }
Dries's avatar
 
Dries committed
513
  return $count[$type][$tid] + $children_count;
Kjartan's avatar
Kjartan committed
514 515 516 517 518
}

// helper for above function
function _taxonomy_term_children($tid) {
  static $children;
Dries's avatar
 
Dries committed
519

Dries's avatar
 
Dries committed
520
  if (!isset($children)) {
Kjartan's avatar
Kjartan committed
521 522 523
    $result = db_query("SELECT tid, parent FROM term_hierarchy");
    while ($term = db_fetch_object($result)) {
      $children[$term->parent][] = $term->tid;
Dries's avatar
 
Dries committed
524
    }
Dries's avatar
 
Dries committed
525
  }
Kjartan's avatar
Kjartan committed
526 527
  return $children[$tid] ? $children[$tid] : array();
}
Dries's avatar
 
Dries committed
528

Dries's avatar
 
Dries committed
529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566
/**
 * Try to map a string to existing vocabularies
 * Provide case insensitive and trimmed map so as to
 * maximize likelihood of successful mapping.
 *
 * @param   string  $name  Name of the vocabulary to search
 * @return  array   array of matching vocabularies, as objects
 */
function taxonomy_get_vocabulary_by_name($name) {
  // LOWER is ANSI SQL-92
  $db_result = db_query("SELECT * FROM vocabulary WHERE LOWER('%s') LIKE LOWER(name)", trim($name));
  $result = array();
  while ($vocabulary = db_fetch_object($db_result)) {
    $result[] = $vocabulary;
  }

  return $result;
}

/**
 * Try to map a string to existing terms
 * Provide case insensitive and trimmed map so as to
 * maximize likelihood of successful mapping.
 *
 * @param   string  $name  Name of the term to search
 * @return  array   array of matching terms, as objects
 */
function taxonomy_get_term_by_name($name) {
  // LOWER is ANSI SQL-92
  $db_result = db_query("SELECT * FROM term_data WHERE LOWER('%s') LIKE LOWER(name)", trim($name));
  $result = array();
  while ($term = db_fetch_object($db_result)) {
    $result[] = $term;
  }

  return $result;
}

Kjartan's avatar
Kjartan committed
567 568
function taxonomy_get_vocabulary($vid) {
  // simple cache using a static var?
Dries's avatar
 
Dries committed
569
  return db_fetch_object(db_query("SELECT * FROM vocabulary WHERE vid = '%d'", $vid));
Kjartan's avatar
Kjartan committed
570
}
Dries's avatar
 
Dries committed
571

Kjartan's avatar
Kjartan committed
572 573
function taxonomy_get_term($tid) {
  // simple cache using a static var?
Dries's avatar
 
Dries committed
574
  return db_fetch_object(db_query("SELECT * FROM term_data WHERE tid = '%d'", $tid));
Kjartan's avatar
Kjartan committed
575
}
Dries's avatar
 
Dries committed
576 577 578 579 580

/*
** service functions
*/

Kjartan's avatar
Kjartan committed
581
function _taxonomy_term_select($title, $name, $value, $vocabulary_id, $description, $multiple, $blank, $exclude = array()) {
Dries's avatar
 
Dries committed
582
  $tree = taxonomy_get_tree($vocabulary_id);
Dries's avatar
 
Dries committed
583

Kjartan's avatar
Kjartan committed
584
  if ($blank) {
Dries's avatar
 
Dries committed
585
    $options[] = array("tid" => 0, "name" => $blank);
Kjartan's avatar
Kjartan committed
586
  }
Dries's avatar
 
Dries committed
587

Kjartan's avatar
Kjartan committed
588 589 590
  if ($tree) {
    foreach ($tree as $term) {
      if (!in_array($term->tid, $exclude)) {
Dries's avatar
 
Dries committed
591
        $options[] = array("tid" => $term->tid, "name" => _taxonomy_depth($term->depth, '-').$term->name);
Dries's avatar
 
Dries committed
592 593
      }
    }
Kjartan's avatar
Kjartan committed
594 595 596 597 598
    if (!$blank && !$value) {
      // required but without a predefined value, so set first as predefined
      $value = $tree[0]->tid;
    }
  }
Dries's avatar
 
Dries committed
599

Kjartan's avatar
Kjartan committed
600
  if (count($options) > 0) {
Dries's avatar
 
Dries committed
601 602
    foreach ($options as $option) {
      $select .= "<option value=\"".$option["tid"]."\"". (is_array($value) ? (in_array($option["tid"], $value) ? " selected=\"selected\"" : "") : ($option["tid"] == $value ? " selected=\"selected\"" : "")) .">". check_form($option["name"]) ."</option>";
Kjartan's avatar
Kjartan committed
603
    }
Dries's avatar
 
Dries committed
604

Dries's avatar
 
Dries committed
605
    $size = min(12, count($options));
Dries's avatar
 
Dries committed
606

Kjartan's avatar
Kjartan committed
607
    return form_item($title, "<select name=\"edit[$name][]\"". ($multiple ? " multiple size=\"$size\"" : "") . ($extra ? " $extra" : "") .">$select</select>", $description);
Dries's avatar
 
Dries committed
608
  }
Kjartan's avatar
Kjartan committed
609
}
Dries's avatar
 
Dries committed
610

Kjartan's avatar
Kjartan committed
611 612 613
function _taxonomy_depth($depth, $graphic = '--') {
  for ($n = 0; $n < $depth; $n++) {
    $result .= $graphic;
Dries's avatar
 
Dries committed
614
  }
Kjartan's avatar
Kjartan committed
615 616
  return $result;
}
Dries's avatar
 
Dries committed
617

Kjartan's avatar
Kjartan committed
618 619 620
function _prepare_update($data) {
  foreach ($data as $key => $value) {
    $q[] = "$key = '". check_query($value) ."'";
Dries's avatar
 
Dries committed
621
  }
Kjartan's avatar
Kjartan committed
622 623 624
  $result = implode(", ", $q);
  return $result;
}
Dries's avatar
 
Dries committed
625

Kjartan's avatar
Kjartan committed
626 627 628 629 630 631 632
function _prepare_insert($data, $stage) {
  if ($stage == 1) {
    $result = implode(", ", array_keys($data));
  }
  else {
    foreach (array_values($data) as $value) {
      $q[] = "'". check_query($value) ."'";
Dries's avatar
 
Dries committed
633
    }
Kjartan's avatar
Kjartan committed
634
    $result = implode(", ", $q);
Dries's avatar
 
Dries committed
635
  }
Kjartan's avatar
Kjartan committed
636 637
  return "($result)";
}
Dries's avatar
 
Dries committed
638

Kjartan's avatar
Kjartan committed
639 640
function taxonomy_page() {
  global $op;
Dries's avatar
 
Dries committed
641

Kjartan's avatar
Kjartan committed
642 643 644 645 646 647
  switch ($op) {
    case "feed":
      taxonomy_feed();
      break;
    default:
       // TODO: pretty display of all vocabularies
Dries's avatar
 
Dries committed
648
  }
Kjartan's avatar
Kjartan committed
649
}
Dries's avatar
 
Dries committed
650

Kjartan's avatar
Kjartan committed
651
/*
Dries's avatar
 
Dries committed
652 653 654
** admin
*/

Kjartan's avatar
Kjartan committed
655
function taxonomy_admin() {
Dries's avatar
 
Dries committed
656
  global $edit, $type, $op, $id, $theme;
Kjartan's avatar
Kjartan committed
657 658 659 660

  if (user_access("administer taxonomy")) {
    switch ($op) {
      case "add":
Kjartan's avatar
Kjartan committed
661
        if ($type == "vocabulary") {
Kjartan's avatar
Kjartan committed
662
          print taxonomy_form_vocabulary();
Kjartan's avatar
Kjartan committed
663 664
        }
        else {
Kjartan's avatar
Kjartan committed
665
          print taxonomy_form_term();
Kjartan's avatar
Kjartan committed
666
        }
Kjartan's avatar
Kjartan committed
667 668
        break;
      case "edit":
Kjartan's avatar
Kjartan committed
669
        if ($type == "vocabulary") {
Kjartan's avatar
Kjartan committed
670
          print taxonomy_form_vocabulary(object2array(taxonomy_get_vocabulary($id)));
Kjartan's avatar
Kjartan committed
671 672
        }
        else {
Kjartan's avatar
Kjartan committed
673
          print taxonomy_form_term(object2array(taxonomy_get_term($id)));
Kjartan's avatar
Kjartan committed
674
        }
Kjartan's avatar
Kjartan committed
675 676
        break;
      case "preview":
Kjartan's avatar
Kjartan committed
677
        print taxonomy_form($id);
Kjartan's avatar
Kjartan committed
678 679 680 681
        break;
      case "help":
        print taxonomy_help();
        break;
Dries's avatar
 
Dries committed
682
      case t("Delete"):
Dries's avatar
 
Dries committed
683 684 685 686 687 688 689 690 691 692 693 694 695
        if (!$edit["confirm"]) {
          if ($type == "vocabulary") {
            echo _taxonomy_confirm_del_vocabulary($edit["vid"]);
          }
          else {
            echo _taxonomy_confirm_del_term($edit["tid"]);
          }
          break;
        }
        else {
          $edit["name"] = 0;
          // fall through:
        }
Dries's avatar
 
Dries committed
696
      case t("Submit"):
Kjartan's avatar
Kjartan committed
697
        if ($type == "vocabulary") {
Kjartan's avatar
Kjartan committed
698
          print status(taxonomy_save_vocabulary($edit));
Kjartan's avatar
Kjartan committed
699 700
        }
        else {
Kjartan's avatar
Kjartan committed
701
          print status(taxonomy_save_term($edit));
Dries's avatar
 
Dries committed
702 703 704 705 706 707
          if (!$edit["tid"]) {
            // if INSERT show form again
            print taxonomy_form_term();
            break;
          }
          // else (UPDATE or DELETE) fall through
Kjartan's avatar
Kjartan committed
708
        }
Kjartan's avatar
Kjartan committed
709 710 711 712 713 714 715 716 717 718 719 720
        // fall through:
      default:
        print taxonomy_overview();
    }
  }
  else {
    print message_access();
  }
}

function taxonomy_help() {
  ?>
Dries's avatar
 
Dries committed
721 722 723 724 725 726

  <h3>Background</h3>
  <p>Classifying nodes allows for the organization of content into categories and subcategories of description. These categories can be used to organize and retrieve similarly described content. Drupal's <i>taxonomy.module</i> is an extremely flexible classification system that allows for multiple lists of categories for classification (controlled vocabularies) and offers the possibility of creating thesauri (controlled vocabularies that indicate the relationship of terms) and taxonomies (controlled vocabularies where relationships are indicated hierarchically). For details about <a href="http://www.eleganthack.com/archives/002165.html#002165">classification types</a> and insight into the development of <i>taxonomy.module</i>, see this <a href="http://www.drupal.org/node.php?id=55">drupal.org discussion</a>.</p>

  <h3>An example taxonomy: food</h3>
  <p>Dairy <br />
Kjartan's avatar
Kjartan committed
727 728 729 730 731 732 733 734 735 736 737
  --Milk <br />
  Drink <br />
  --Alchohol <br />
  --Pop <br />
  --Milk<br />
  Meat <br />
  --Beef <br />
  --Chicken <br />
  --Lamb <br />
  Spices <br />
  --Sugar</p>
Dries's avatar
 
Dries committed
738 739 740 741 742 743
  <p><b>Notes</b></p>
   <ul>
   <li>The term <i>Milk</i> appears within both <i>Dairy</i> and <i>Drink</i>.  This is an example of <i>nmultiple parents</i> for a term.</li>
   <li>The order of siblings (e.g. <i>Beef</i>, <i>Chicken</i>, <i>Lamb</i>) in the taxonomy may be controlled with the <i>weight</i> parameter. </li>
  </ul>

Kjartan's avatar
Kjartan committed
744
  <h3>Vocabularies</h3>
Dries's avatar
 
Dries committed
745
  <p>When you create a controlled vocabulary you are creating a set of terms to use for describing content (known as descriptors in indexing lingo). Drupal allows you to describe each node of content (blog, story, etc.) using one or many of these terms. For simple implementations, you might create a set of categories without subcategories, similar to <a href="http://www.slashdot.com/">Slashdot's</a> sections.  For more complex implementations, you might create a hierarchical list of categories such as the example <i>Food</i> taxonomy above.</p>
Kjartan's avatar
Kjartan committed
746 747

  <h4>Setting up a vocabulary</h4>
Dries's avatar
 
Dries committed
748 749 750
  <p>When you set up a controlled vocabulary, you will be asked to enter some descriptive data and define the attributes of this vocabulary. For example, if you select the <i>hierarchy</i> option, you will be defining a taxonomy or a thesaurus. If you select <i>related terms</i> option, you are allowing the definition of related terms as in a thesaurus. Selecting <i>multiple select</i> will allow you to describe a node using more than one term. That node will then appear in each term's page, thus increasing the chance that a user will find it.</p>

  <i>Vocabulary name</i><br />Required. The name for this vocabulary. Example: <i>Dairy</i>.<br />
Kjartan's avatar
Kjartan committed
751
  <br />
Dries's avatar
 
Dries committed
752
  <i>Description</i><br />Optional. Description of the vocabulary, can be used by modules and feeds.<br />
Kjartan's avatar
Kjartan committed
753
  <br />
Dries's avatar
 
Dries committed
754
  <i>Types</i><br />Required. The list of node types you want to associate this vocabulary with. Some available types are: blog, book, forum, page, story.<br />
Kjartan's avatar
Kjartan committed
755
  <br />
Dries's avatar
 
Dries committed
756
  <i><a name="relatedterms"></a>Related terms</i><br />Allows relationships between terms within this vocabulary. Think of these as <i>see also</i>-references.<br />
Kjartan's avatar
Kjartan committed
757
  <br />
Dries's avatar
 
Dries committed
758
  <i><a name="hierarchy"></a>Hierarchy</i><br />Allows a tree-like taxonomy, as in our <i>Foods</i> example above<br />
Kjartan's avatar
Kjartan committed
759
  <br />
Dries's avatar
 
Dries committed
760 761
  <i>Multiple select</i><br />Allows nodes to be described using more than one term. Nodes may then appear on multiple taxonomy pages.<br />

Kjartan's avatar
Kjartan committed
762
  <h4>Adding terms to a vocabulary</h4>
Dries's avatar
 
Dries committed
763 764 765
<p>The options you see when adding a term to a vocabulary will depend on what you selected for <i>related terms</i>, <i>hierarchy </i>and <i>multiple select</i> when you created the corrosponding vocabulary.</p>

  <i>Term name</i><br />Required. The name for this term. Example: <i>Milk</i><br />
Kjartan's avatar
Kjartan committed
766
  <br />
Dries's avatar
 
Dries committed
767
  <i>Description</i><br />Optional. Description of the term that may be used by modules and RSS feeds.  This is synonymous with a 'scope note'.<br />
Kjartan's avatar
Kjartan committed
768
  <br />
Dries's avatar
 
Dries committed
769
  <i><a name="parent"></a>Parent</i><br />Required. Select the term under which this term is a subset -- the branch of the hierarchy that this term belongs under. This is also known as the "Broader term" indicator used in thesauri.<br />
Kjartan's avatar
Kjartan committed
770
  <br />
Dries's avatar
 
Dries committed
771 772 773
  <i><a name="synonyms"></a>Synonyms</i><br />Optional. Enter synonyms for this term, one synonym per line. Synonyms can be used for variant spellings, acronyms, and other terms that have the same meaning as the added term, but which are not explicitly listed in this thesaurus (i.e. <i>unauthorized terms</i>).<br />

  <h3>Displaying nodes organized by term(s)</h3>
Dries's avatar
 
Dries committed
774
  <p>In order to view the nodes associated with a term or a collection of terms, you should browse to a properly formed URL. For example, see <a href="<?php print path_uri().drupal_url(array("mod" => "node", "or" => "1,2"), "module"); ?>"><?php print path_uri().drupal_url(array("mod" => "node", "or" => "1,2"), "module"); ?></a>.  Taxonomy URLs always contain  a term ID or list of term IDs at the end of the URL (aka <i>querystring</i>). You may learn the term ID for a given term by hovering over that term in the <?php echo la("taxonomy overview", array("mod" => "taxonomy")) ?> page in the Admin and noting the number after the querystring parameter called <i>tid</i>.  If you wish to see nodes from a collection of term IDs, separate each term ID with a comma.  Also, the name of the querystring parameter may be <i>or</i> or <i>and</i>: <i>or</i> shows nodes which appear in <b>any</b> of the term IDs while <i>and</i> shows nodes in <b>all</b> the specified term IDs.  Thus, <i>or</i> is less specific than <i>and</i>.</p>
Dries's avatar
 
Dries committed
775 776 777 778

  <h3>RSS feeds</h3>
  <p>Every term, or collection of terms, provides an <a href="http://backend.userland.com/stories/rss091">RSS</a> feed to which interested users may subscribe. The URL format for an sample RSS feed is <a href="<?php print path_uri().drupal_url(array("mod" => "node", "op" => "feed", "or" => "1,2"), "module"); ?>"><?php print path_uri().drupal_url(array("mod" => "node", "op" => "feed", "or" => "1,2"), "module"); ?></a>.</p>
 <?php
Kjartan's avatar
Kjartan committed
779
}
Dries's avatar
 
Dries committed
780
?>