taxonomy.module 31.1 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
    $channel["title"] = variable_get("site_name", "drupal") ." - ". $term->name;
Dries's avatar
 
Dries committed
35
    $channel["link"] = path_uri() ."?or=$or";
Kjartan's avatar
Kjartan committed
36
    $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", url("admin/taxonomy"), "Administer taxonomies.", $help["taxonomy"], "content management", 1);
Dries's avatar
 
Dries committed
52 53
    menu_add("add new vocabulary", url("admin/taxonomy/add/vocabulary"), "Add a new vocabulary.", $help["vocabulary"], "taxonomy");
    menu_add("help", url("admin/taxonomy/help"), "More information about taxonomies.", NULL, "taxonomy", 9);
Dries's avatar
 
Dries committed
54
  }
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
  $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);
Dries's avatar
 
Dries committed
71 72
  $form .= form_checkbox(t("Related terms"), "relations", 1, $edit["relations"], t("Optional") . ". " . t("Allows ". l("related terms", "admin/taxonomy/help#relatedterms") ." in this vocabulary."));
  $form .= form_select(t("Hierarchy"), "hierarchy", $edit["hierarchy"], array(t("Disabled"), t("Single"), t("Multiple")), t("Optional") . ". ". t("Allows ". l("a tree-like hierarchy", "admin/taxonomy/help#hierarchy") ." between terms of this vocabulary."), "", 0);
Dries's avatar
 
Dries committed
73 74
  $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 = '%d'", $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"] = $edit["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
function taxonomy_form_term($edit = array()) {
Dries's avatar
 
Dries committed
138
  $vocabulary_id = arg(4);
Dries's avatar
 
Dries committed
139

Kjartan's avatar
Kjartan committed
140 141 142 143
  if (!$vocabulary_id) {
    $vocabulary_id = $edit["vid"];
  }
  $vocabulary = taxonomy_get_vocabulary($vocabulary_id);
Dries's avatar
 
Dries committed
144

Dries's avatar
 
Dries committed
145 146
  $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
147

Kjartan's avatar
Kjartan committed
148
  if ($vocabulary->relations) {
Dries's avatar
 
Dries committed
149
    $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
150
  }
Dries's avatar
 
Dries committed
151

Kjartan's avatar
Kjartan committed
152 153
  if ($vocabulary->hierarchy) {
    $parent = array_keys(taxonomy_get_parents($edit["tid"]));
Dries's avatar
 
Dries committed
154
    $children = taxonomy_get_tree($vocabulary_id, $edit["tid"]);
Dries's avatar
 
Dries committed
155 156 157 158 159

    // you can't be son of yourself nor of your children
    foreach ($children as $child) {
      $exclude[] = $child->tid;
    }
Kjartan's avatar
Kjartan committed
160
    $exclude[] = $edit["tid"];
Dries's avatar
 
Dries committed
161

Kjartan's avatar
Kjartan committed
162
    if ($vocabulary->hierarchy == 1) {
Dries's avatar
 
Dries committed
163
      $form .= _taxonomy_term_select(t("Parent"), "parent", $parent, $vocabulary_id, t("Required") . ". " . l(t("Parent term"), "admin/taxonomy/help#parent") .".", 0, "<" . t("root") . ">", $exclude);
Dries's avatar
 
Dries committed
164
    }
Kjartan's avatar
Kjartan committed
165
    elseif ($vocabulary->hierarchy == 2) {
Dries's avatar
 
Dries committed
166
      $form .= _taxonomy_term_select(t("Parents"), "parent", $parent, $vocabulary_id, t("Required") . ". ". l(t("Parent terms"), "admin/taxonomy/help#parent") .".", 1, "<" . t("root") . ">", $exclude);
Dries's avatar
 
Dries committed
167
    }
Kjartan's avatar
Kjartan committed
168
  }
Dries's avatar
 
Dries committed
169

Dries's avatar
 
Dries committed
170
  $form .= form_textarea(t("Synonyms"), "synonyms", implode("\n", taxonomy_get_synonyms($edit["tid"])), 30, 5, t("Optional") . ". ". t(l("Synonyms", "admin/taxonomy/help#synonyms") ." of this term, one synonym per line."));
Dries's avatar
 
Dries committed
171
  $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
172
  $form .= form_hidden("vid", $vocabulary->vid);
Dries's avatar
 
Dries committed
173
  $form .= form_submit(t("Submit"));
Kjartan's avatar
Kjartan committed
174 175

  if ($edit["tid"]) {
Dries's avatar
 
Dries committed
176
    $form .= form_submit(t("Delete"));
Kjartan's avatar
Kjartan committed
177
    $form .= form_hidden("tid", $edit["tid"]);
Dries's avatar
 
Dries committed
178 179
  }

Kjartan's avatar
Kjartan committed
180 181
  return form($form);
}
Dries's avatar
 
Dries committed
182

Kjartan's avatar
Kjartan committed
183 184 185
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
186

Dries's avatar
 
Dries committed
187
    db_query("UPDATE term_data SET ". _prepare_update($data) ." WHERE tid = '%d'", $edit["tid"]);
Dries's avatar
 
Dries committed
188
    module_invoke_all("taxonomy", "update", "term", $edit);
Dries's avatar
 
Dries committed
189
    $message = t("the term '%a' has been updated.", array("%a" => $edit["name"]));
Kjartan's avatar
Kjartan committed
190 191
  }
  else if ($edit["tid"]) {
Dries's avatar
 
Dries committed
192
    return taxonomy_del_term($edit["tid"]);
Kjartan's avatar
Kjartan committed
193 194
  }
  else {
Dries's avatar
 
Dries committed
195
    $edit["tid"] = db_next_id("term_data");
Kjartan's avatar
Kjartan committed
196 197
    $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
198
    module_invoke_all("taxonomy", "insert", "term", $edit);
Dries's avatar
 
Dries committed
199
    $message = t("created new term '%name'.", array("%name" => $edit["name"]));
Kjartan's avatar
Kjartan committed
200
  }
Dries's avatar
 
Dries committed
201

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

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

Dries's avatar
 
Dries committed
226
  db_query("DELETE FROM term_synonym WHERE tid = '%d'", $edit["tid"]);
Kjartan's avatar
Kjartan committed
227
  if ($edit["synonyms"]) {
Dries's avatar
 
Dries committed
228 229 230 231
    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
232
    }
Dries's avatar
 
Dries committed
233
  }
Dries's avatar
 
Dries committed
234

Dries's avatar
 
Dries committed
235 236
  cache_clear_all();

Dries's avatar
 
Dries committed
237
  return $message;
Kjartan's avatar
Kjartan committed
238
}
Dries's avatar
 
Dries committed
239

Kjartan's avatar
Kjartan committed
240
function taxonomy_del_term($tid) {
Dries's avatar
 
Dries committed
241 242
  $term = taxonomy_get_term($tid);

Dries's avatar
 
Dries committed
243 244 245 246 247
  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
248

Dries's avatar
 
Dries committed
249
  module_invoke_all("taxonomy", "delete", "term", $term);
Dries's avatar
 
Dries committed
250 251
  cache_clear_all();

Dries's avatar
 
Dries committed
252 253 254 255 256 257 258 259 260 261 262 263 264
  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
265
}
Dries's avatar
 
Dries committed
266

Kjartan's avatar
Kjartan committed
267 268
function taxonomy_overview() {
  global $tree;
Dries's avatar
 
Dries committed
269

Dries's avatar
 
Dries committed
270
  $output .= "<h3>" . t("Vocabularies overview") . "</h3>";
Dries's avatar
 
Dries committed
271 272

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

Kjartan's avatar
Kjartan committed
274 275 276
  $vocabularies = taxonomy_get_vocabularies();
  foreach ($vocabularies as $vocabulary) {
    $links = array();
Dries's avatar
 
Dries committed
277

Dries's avatar
 
Dries committed
278
    $rows[] = array($vocabulary->name, array("data" => $vocabulary->types, "align" => "center"), l(t("edit vocabulary"), "admin/taxonomy/edit/vocabulary/$vocabulary->vid"), l(t("add term"), "admin/taxonomy/add/term/$vocabulary->vid"), l(t("preview form"), "admin/taxonomy/preview/vocabulary/$vocabulary->vid"));
Kjartan's avatar
Kjartan committed
279

Dries's avatar
 
Dries committed
280
    $tree = taxonomy_get_tree($vocabulary->vid);
Kjartan's avatar
Kjartan committed
281
    if ($tree) {
Dries's avatar
 
Dries committed
282
      unset($data);
Kjartan's avatar
Kjartan committed
283
      foreach ($tree as $term) {
Dries's avatar
 
Dries committed
284
        $data .= _taxonomy_depth($term->depth) ." ". $term->name ." (". l(t("edit term"), "admin/taxonomy/edit/term/$term->tid") .")<br />";
Dries's avatar
 
Dries committed
285
      }
Dries's avatar
 
Dries committed
286
      $rows[] = array(array("data" => $data, "colspan" => 5));
Dries's avatar
 
Dries committed
287 288 289
    }
  }

Dries's avatar
 
Dries committed
290
  return table($header, $rows);
Kjartan's avatar
Kjartan committed
291 292 293 294 295 296 297 298 299 300
}

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
301
    $blank = "<" . t("none") . ">";
Kjartan's avatar
Kjartan committed
302
  }
Dries's avatar
 
Dries committed
303

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

/*
** API functions
*/

Kjartan's avatar
Kjartan committed
319 320 321 322 323 324 325 326 327 328 329
// 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
330
  }
Kjartan's avatar
Kjartan committed
331 332
  return $vocabularies;
}
Dries's avatar
 
Dries committed
333

Kjartan's avatar
Kjartan committed
334 335 336 337 338
// 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
339 340
    }
    else {
Kjartan's avatar
Kjartan committed
341
      $terms = 0;
Dries's avatar
 
Dries committed
342
    }
Kjartan's avatar
Kjartan committed
343 344 345 346
  }
  else {
    $terms = $node->taxonomy;
  }
Dries's avatar
 
Dries committed
347

Kjartan's avatar
Kjartan committed
348 349 350
  $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
351
  }
Kjartan's avatar
Kjartan committed
352 353
  return $result ? $result : array();
}
Dries's avatar
 
Dries committed
354

Kjartan's avatar
Kjartan committed
355 356 357
// 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
358

Dries's avatar
 
Dries committed
359
  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
360 361 362 363
}

// 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
364
  $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
365 366 367
  $terms = array();
  while ($term = db_fetch_object($result)) {
    $terms[$term->$key] = $term;
Dries's avatar
 
Dries committed
368
  }
Kjartan's avatar
Kjartan committed
369 370 371 372 373 374
  return $terms;
}

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

Dries's avatar
 
Dries committed
376
  if (!isset($terms[$nid])) {
Dries's avatar
 
Dries committed
377
    $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
378
    $terms[$nid] = array();
Dries's avatar
 
Dries committed
379
    while ($term = db_fetch_object($result)) {
Kjartan's avatar
Kjartan committed
380
      $terms[$nid][$term->$key] = $term;
Dries's avatar
 
Dries committed
381 382
    }
  }
Kjartan's avatar
Kjartan committed
383 384
  return $terms[$nid];
}
Dries's avatar
 
Dries committed
385

Kjartan's avatar
Kjartan committed
386 387 388
// save terms of a node
function taxonomy_node_save($nid, $terms) {
  taxonomy_node_delete($nid);
Dries's avatar
 
Dries committed
389

Kjartan's avatar
Kjartan committed
390
  if ($terms) {
Dries's avatar
 
Dries committed
391 392
    foreach ($terms as $term) {
      db_query("INSERT INTO term_node (nid, tid) VALUES ('%d', '%d')", $nid, $term);
Dries's avatar
 
Dries committed
393 394
    }
  }
Kjartan's avatar
Kjartan committed
395
}
Dries's avatar
 
Dries committed
396

Kjartan's avatar
Kjartan committed
397 398
// clean up terms
function taxonomy_node_delete($nid) {
Dries's avatar
 
Dries committed
399
  db_query("DELETE FROM term_node WHERE nid = '%d'", $nid);
Kjartan's avatar
Kjartan committed
400
}
Dries's avatar
 
Dries committed
401

Kjartan's avatar
Kjartan committed
402 403 404
// relations: return array of related terms
function taxonomy_get_related($tid, $key = "tid") {
  if ($tid) {
Dries's avatar
 
Dries committed
405
    $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
406 407 408
    $related = array();
    while ($term = db_fetch_object($result)) {
      $related[$term->$key] = $term;
Dries's avatar
 
Dries committed
409
    }
Kjartan's avatar
Kjartan committed
410
    return $related;
Dries's avatar
 
Dries committed
411
  }
Kjartan's avatar
Kjartan committed
412 413
  else {
    return array();
Dries's avatar
 
Dries committed
414
  }
Kjartan's avatar
Kjartan committed
415
}
Dries's avatar
 
Dries committed
416

Kjartan's avatar
Kjartan committed
417 418 419
// hierarchy: get parent terms
function taxonomy_get_parents($tid, $key = "tid") {
  if ($tid) {
Dries's avatar
 
Dries committed
420
    $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
421 422 423
    $parents = array();
    while ($parent = db_fetch_object($result)) {
      $parents[$parent->$key] = $parent;
Dries's avatar
 
Dries committed
424
    }
Kjartan's avatar
Kjartan committed
425
    return $parents;
Dries's avatar
 
Dries committed
426
  }
Kjartan's avatar
Kjartan committed
427 428 429 430
  else {
    return array();
  }
}
Dries's avatar
 
Dries committed
431

Kjartan's avatar
Kjartan committed
432 433 434
// hierarchy: get children
function taxonomy_get_children($tid, $vid = 0, $key = "tid") {
  if ($vid) {
Dries's avatar
 
Dries committed
435
    $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
436
  }
Kjartan's avatar
Kjartan committed
437
  else {
Dries's avatar
 
Dries committed
438
    $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
439 440 441 442 443 444 445
  }
  $children = array();
  while ($term = db_fetch_object($result)) {
    $children[$term->$key] = $term;
  }
  return $children;
}
Dries's avatar
 
Dries committed
446

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

Kjartan's avatar
Kjartan committed
451
  $depth++;
Dries's avatar
 
Dries committed
452

Dries's avatar
 
Dries committed
453 454 455 456
  // 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
457 458
    $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
459 460 461
      $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
462 463
    }
  }
Dries's avatar
 
Dries committed
464

Dries's avatar
 
Dries committed
465 466 467 468 469 470
  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
471

Dries's avatar
 
Dries committed
472
      $tree = array_merge($tree, taxonomy_get_tree($vocabulary_id, $child, $depth));
Dries's avatar
 
Dries committed
473
    }
Kjartan's avatar
Kjartan committed
474
  }
Dries's avatar
 
Dries committed
475

Dries's avatar
 
Dries committed
476
  return $tree ? $tree : array();
Kjartan's avatar
Kjartan committed
477
}
Dries's avatar
 
Dries committed
478

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

Kjartan's avatar
Kjartan committed
493 494 495 496
// 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
497

Kjartan's avatar
Kjartan committed
498
// given a term id, count number of nodes in it
Dries's avatar
 
Dries committed
499
function taxonomy_term_count_nodes($tid, $type = 0) {
Kjartan's avatar
Kjartan committed
500
  static $count;
Dries's avatar
 
Dries committed
501

Dries's avatar
 
Dries committed
502 503 504
  if (!isset($count[$type])) {
    // $type == 0 always evaluates true is $type is a string
    if (is_numeric($type)) {
Dries's avatar
 
Dries committed
505
      $result = db_query("SELECT t.tid, COUNT(*) AS c FROM term_node t GROUP BY t.tid");
Dries's avatar
 
Dries committed
506 507
    }
    else {
Dries's avatar
 
Dries committed
508
      $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
509
    }
Kjartan's avatar
Kjartan committed
510
    while ($term = db_fetch_object($result)) {
Dries's avatar
 
Dries committed
511
      $count[$type][$term->tid] = $term->c;
Dries's avatar
 
Dries committed
512 513 514
    }
  }

Kjartan's avatar
Kjartan committed
515
  foreach (_taxonomy_term_children($tid) as $c) {
Dries's avatar
 
Dries committed
516
    $children_count += taxonomy_term_count_nodes($c, $type);
Kjartan's avatar
Kjartan committed
517
  }
Dries's avatar
 
Dries committed
518
  return $count[$type][$tid] + $children_count;
Kjartan's avatar
Kjartan committed
519 520 521 522 523
}

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

Dries's avatar
 
Dries committed
525
  if (!isset($children)) {
Kjartan's avatar
Kjartan committed
526 527 528
    $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
529
    }
Dries's avatar
 
Dries committed
530
  }
Kjartan's avatar
Kjartan committed
531 532
  return $children[$tid] ? $children[$tid] : array();
}
Dries's avatar
 
Dries committed
533

Dries's avatar
 
Dries committed
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 567 568 569 570 571
/**
 * 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
572 573
function taxonomy_get_vocabulary($vid) {
  // simple cache using a static var?
Dries's avatar
 
Dries committed
574
  return db_fetch_object(db_query("SELECT * FROM vocabulary WHERE vid = '%d'", $vid));
Kjartan's avatar
Kjartan committed
575
}
Dries's avatar
 
Dries committed
576

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

/*
** service functions
*/

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

Kjartan's avatar
Kjartan committed
589
  if ($blank) {
Dries's avatar
 
Dries committed
590
    $options[] = array("tid" => 0, "name" => $blank);
Kjartan's avatar
Kjartan committed
591
  }
Dries's avatar
 
Dries committed
592

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

Kjartan's avatar
Kjartan committed
605
  if (count($options) > 0) {
Dries's avatar
 
Dries committed
606 607
    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
608
    }
Dries's avatar
 
Dries committed
609

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

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

Kjartan's avatar
Kjartan committed
616 617 618
function _taxonomy_depth($depth, $graphic = '--') {
  for ($n = 0; $n < $depth; $n++) {
    $result .= $graphic;
Dries's avatar
 
Dries committed
619
  }
Kjartan's avatar
Kjartan committed
620 621
  return $result;
}
Dries's avatar
 
Dries committed
622

Kjartan's avatar
Kjartan committed
623 624 625
function _prepare_update($data) {
  foreach ($data as $key => $value) {
    $q[] = "$key = '". check_query($value) ."'";
Dries's avatar
 
Dries committed
626
  }
Kjartan's avatar
Kjartan committed
627 628 629
  $result = implode(", ", $q);
  return $result;
}
Dries's avatar
 
Dries committed
630

Kjartan's avatar
Kjartan committed
631 632 633 634 635 636 637
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
638
    }
Kjartan's avatar
Kjartan committed
639
    $result = implode(", ", $q);
Dries's avatar
 
Dries committed
640
  }
Kjartan's avatar
Kjartan committed
641 642
  return "($result)";
}
Dries's avatar
 
Dries committed
643

Kjartan's avatar
Kjartan committed
644
function taxonomy_page() {
Dries's avatar
 
Dries committed
645

Dries's avatar
 
Dries committed
646
  switch (arg(1)) {
Kjartan's avatar
Kjartan committed
647 648 649 650 651
    case "feed":
      taxonomy_feed();
      break;
    default:
       // TODO: pretty display of all vocabularies
Dries's avatar
 
Dries committed
652
  }
Kjartan's avatar
Kjartan committed
653
}
Dries's avatar
 
Dries committed
654

Kjartan's avatar
Kjartan committed
655
/*
Dries's avatar
 
Dries committed
656 657 658
** admin
*/

Kjartan's avatar
Kjartan committed
659
function taxonomy_admin() {
Dries's avatar
 
Dries committed
660
  global $op, $edit, $theme;
Kjartan's avatar
Kjartan committed
661 662

  if (user_access("administer taxonomy")) {
Dries's avatar
 
Dries committed
663 664 665 666
    if (empty($op)) {
      $op = arg(2);
    }

Kjartan's avatar
Kjartan committed
667 668
    switch ($op) {
      case "add":
Dries's avatar
 
Dries committed
669
        if (arg(3) == "vocabulary") {
Kjartan's avatar
Kjartan committed
670
          print taxonomy_form_vocabulary();
Kjartan's avatar
Kjartan committed
671 672
        }
        else {
Kjartan's avatar
Kjartan committed
673
          print taxonomy_form_term();
Kjartan's avatar
Kjartan committed
674
        }
Kjartan's avatar
Kjartan committed
675 676
        break;
      case "edit":
Dries's avatar
 
Dries committed
677 678
        if (arg(3) == "vocabulary") {
          print taxonomy_form_vocabulary(object2array(taxonomy_get_vocabulary(arg(4))));
Kjartan's avatar
Kjartan committed
679 680
        }
        else {
Dries's avatar
 
Dries committed
681
          print taxonomy_form_term(object2array(taxonomy_get_term(arg(4))));
Kjartan's avatar
Kjartan committed
682
        }
Kjartan's avatar
Kjartan committed
683 684
        break;
      case "preview":
Dries's avatar
 
Dries committed
685
        print taxonomy_form(arg(4));
Kjartan's avatar
Kjartan committed
686 687 688 689
        break;
      case "help":
        print taxonomy_help();
        break;
Dries's avatar
 
Dries committed
690
      case t("Delete"):
Dries's avatar
 
Dries committed
691
        if (!$edit["confirm"]) {
Dries's avatar
 
Dries committed
692
          if (arg(3) == "vocabulary") {
Dries's avatar
 
Dries committed
693 694 695 696 697 698 699 700 701 702 703
            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
704
      case t("Submit"):
Dries's avatar
 
Dries committed
705
        if (arg(3) == "vocabulary") {
Kjartan's avatar
Kjartan committed
706
          print status(taxonomy_save_vocabulary($edit));
Kjartan's avatar
Kjartan committed
707 708
        }
        else {
Kjartan's avatar
Kjartan committed
709
          print status(taxonomy_save_term($edit));
Dries's avatar
 
Dries committed
710 711 712 713 714 715
          if (!$edit["tid"]) {
            // if INSERT show form again
            print taxonomy_form_term();
            break;
          }
          // else (UPDATE or DELETE) fall through
Kjartan's avatar
Kjartan committed
716
        }
Kjartan's avatar
Kjartan committed
717 718 719 720 721 722 723 724 725 726 727 728
        // fall through:
      default:
        print taxonomy_overview();
    }
  }
  else {
    print message_access();
  }
}

function taxonomy_help() {
  ?>
Dries's avatar
 
Dries committed
729 730

  <h3>Background</h3>
Dries's avatar
 
Dries committed
731
  <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/view/55">drupal.org discussion</a>.</p>
Dries's avatar
 
Dries committed
732 733

  <h3>An example taxonomy: food</h3>
Dries's avatar
 
Dries committed
734 735 736 737 738
  <p>Dairy<br />
  --Milk<br />
  Drink<br />
  --Alchohol<br />
  --Pop<br />
Kjartan's avatar
Kjartan committed
739
  --Milk<br />
Dries's avatar
 
Dries committed
740 741 742 743 744
  Meat<br />
  --Beef<br />
  --Chicken<br />
  --Lamb<br />
  Spices<br />
Kjartan's avatar
Kjartan committed
745
  --Sugar</p>
Dries's avatar
 
Dries committed
746 747 748 749 750 751
  <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
752
  <h3>Vocabularies</h3>
Dries's avatar
 
Dries committed
753
  <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
754 755

  <h4>Setting up a vocabulary</h4>
Dries's avatar
 
Dries committed
756 757
  <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>

Dries's avatar
Dries committed
758
  <p><i>Vocabulary name</i><br />Required. The name for this vocabulary. Example: <i>Dairy</i>.<br />
Kjartan's avatar
Kjartan committed
759
  <br />
Dries's avatar
 
Dries committed
760
  <i>Description</i><br />Optional. Description of the vocabulary, can be used by modules and feeds.<br />
Kjartan's avatar
Kjartan committed
761
  <br />
Dries's avatar
 
Dries committed
762
  <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
763
  <br />
Dries's avatar
 
Dries committed
764
  <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
765
  <br />
Dries's avatar
 
Dries committed
766
  <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
767
  <br />
Dries's avatar
Dries committed
768
  <i>Multiple select</i><br />Allows nodes to be described using more than one term. Nodes may then appear on multiple taxonomy pages.</p>
Dries's avatar
 
Dries committed
769

Kjartan's avatar
Kjartan committed
770
  <h4>Adding terms to a vocabulary</h4>
Dries's avatar
 
Dries committed
771 772
<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>

Dries's avatar
Dries committed
773
  <p><i>Term name</i><br />Required. The name for this term. Example: <i>Milk</i><br />
Kjartan's avatar
Kjartan committed
774
  <br />
Dries's avatar
 
Dries committed
775
  <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
776
  <br />
Dries's avatar
 
Dries committed
777
  <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 />