taxonomy.module 30.8 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
    return t("update vocabulary '%name'.", array("%name" => $edit["name"]));
Dries's avatar
 
Dries committed
92
  }
Kjartan's avatar
Kjartan committed
93
  else if ($edit["vid"]) {
Dries's avatar
 
Dries committed
94
    return taxonomy_del_vocabulary($edit["vid"]);
Kjartan's avatar
Kjartan committed
95 96 97
  }
  else {
    db_query("INSERT INTO vocabulary ". _prepare_insert($data, 1) ." VALUES ". _prepare_insert($data, 2));
Dries's avatar
 
Dries committed
98
    return t("created new vocabulary '%name'.", array("%name" => $edit["name"]));
Kjartan's avatar
Kjartan committed
99
  }
Dries's avatar
 
Dries committed
100 101

  cache_clear_all();
Kjartan's avatar
Kjartan committed
102
}
Dries's avatar
 
Dries committed
103

Kjartan's avatar
Kjartan committed
104
function taxonomy_del_vocabulary($vid) {
Dries's avatar
 
Dries committed
105 106
  $vocabulary = taxonomy_get_vocabulary($vid);

Dries's avatar
 
Dries committed
107 108
  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
109 110
  while ($term = db_fetch_object($result)) {
    taxonomy_del_term($term->tid);
Dries's avatar
 
Dries committed
111
  }
Dries's avatar
 
Dries committed
112

Dries's avatar
 
Dries committed
113 114
  cache_clear_all();

Dries's avatar
 
Dries committed
115 116 117 118 119 120 121 122 123 124 125 126 127
  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
128
}
Dries's avatar
 
Dries committed
129

Kjartan's avatar
Kjartan committed
130 131 132 133 134 135
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
136 137
  $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
138

Kjartan's avatar
Kjartan committed
139
  if ($vocabulary->relations) {
Dries's avatar
 
Dries committed
140
    $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
141
  }
Dries's avatar
 
Dries committed
142 143


Kjartan's avatar
Kjartan committed
144 145
  if ($vocabulary->hierarchy) {
    $parent = array_keys(taxonomy_get_parents($edit["tid"]));
Dries's avatar
 
Dries committed
146
    $children = taxonomy_get_tree($vocabulary_id, $edit["tid"]);
Kjartan's avatar
Kjartan committed
147 148 149 150
    // 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
151
      $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
152
    }
Kjartan's avatar
Kjartan committed
153
    elseif ($vocabulary->hierarchy == 2) {
Dries's avatar
 
Dries committed
154
      $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
155
    }
Kjartan's avatar
Kjartan committed
156
  }
Dries's avatar
 
Dries committed
157

Dries's avatar
 
Dries committed
158 159
  $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
160
  $form .= form_hidden("vid", $vocabulary->vid);
Dries's avatar
 
Dries committed
161
  $form .= form_submit(t("Submit"));
Kjartan's avatar
Kjartan committed
162 163

  if ($edit["tid"]) {
Dries's avatar
 
Dries committed
164
    $form .= form_submit(t("Delete"));
Kjartan's avatar
Kjartan committed
165
    $form .= form_hidden("tid", $edit["tid"]);
Dries's avatar
 
Dries committed
166 167
  }

Kjartan's avatar
Kjartan committed
168 169
  return form($form);
}
Dries's avatar
 
Dries committed
170

Kjartan's avatar
Kjartan committed
171 172 173
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
174

Dries's avatar
 
Dries committed
175
    db_query("UPDATE term_data SET ". _prepare_update($data) ." WHERE tid = '%d'", $edit["tid"]);
Dries's avatar
 
Dries committed
176
    $message = t("the term '%a' has been updated.", array("%a" => $edit["name"]));
Kjartan's avatar
Kjartan committed
177 178
  }
  else if ($edit["tid"]) {
Dries's avatar
 
Dries committed
179
    return taxonomy_del_term($edit["tid"]);
Kjartan's avatar
Kjartan committed
180 181
  }
  else {
Dries's avatar
 
Dries committed
182
    $edit["tid"] = db_next_id("term_data");
Kjartan's avatar
Kjartan committed
183 184
    $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
185
    $message = t("created new term '%name'.", array("%name" => $edit["name"]));
Kjartan's avatar
Kjartan committed
186
  }
Dries's avatar
 
Dries committed
187

Kjartan's avatar
Kjartan committed
188
  // relations (seem very powerful, but I have to understand it completely)
Dries's avatar
 
Dries committed
189
  db_query("DELETE FROM term_relation WHERE tid1 = '%d' OR tid2 = '%d'", $edit["tid"], $edit["tid"]);
Kjartan's avatar
Kjartan committed
190 191 192
  if ($edit["relations"]) {
    foreach ($edit["relations"] as $related_id) {
      if ($related_id != 0) {
Dries's avatar
 
Dries committed
193
        db_query("INSERT INTO term_relation (tid1, tid2) VALUES ('%d', '%d')", $edit["tid"], $related_id);
Dries's avatar
 
Dries committed
194
      }
Kjartan's avatar
Kjartan committed
195
    }
Kjartan's avatar
Kjartan committed
196
  }
Dries's avatar
 
Dries committed
197

Kjartan's avatar
Kjartan committed
198
  // hierarchy
Dries's avatar
 
Dries committed
199
  db_query("DELETE FROM term_hierarchy WHERE tid = '%d'", $edit["tid"]);
Kjartan's avatar
Kjartan committed
200 201 202 203 204
  if (!isset($edit["parent"])) {
    $edit["parent"] = 0;
  }
  if (is_array($edit["parent"])) {
    foreach ($edit["parent"] as $parent) {
Dries's avatar
 
Dries committed
205
      db_query("INSERT INTO term_hierarchy (tid, parent) VALUES ('%d', '%d')", $edit["tid"], $parent);
Dries's avatar
 
Dries committed
206
    }
Kjartan's avatar
Kjartan committed
207 208
  }
  else {
Dries's avatar
 
Dries committed
209
    db_query("INSERT INTO term_hierarchy (tid, parent) VALUES ('%d', '%d')", $edit["tid"], $edit["parent"][0]);
Dries's avatar
 
Dries committed
210 211
  }

Dries's avatar
 
Dries committed
212
  db_query("DELETE FROM term_synonym WHERE tid = '%d'", $edit["tid"]);
Kjartan's avatar
Kjartan committed
213
  if ($edit["synonyms"]) {
Dries's avatar
 
Dries committed
214 215 216 217
    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
218
    }
Dries's avatar
 
Dries committed
219
  }
Dries's avatar
 
Dries committed
220

Dries's avatar
 
Dries committed
221 222
  cache_clear_all();

Dries's avatar
 
Dries committed
223
  return $message;
Kjartan's avatar
Kjartan committed
224
}
Dries's avatar
 
Dries committed
225

Kjartan's avatar
Kjartan committed
226
function taxonomy_del_term($tid) {
Dries's avatar
 
Dries committed
227 228
  $term = taxonomy_get_term($tid);

Dries's avatar
 
Dries committed
229 230 231 232 233
  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
234

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

Dries's avatar
 
Dries committed
237 238 239 240 241 242 243 244 245 246 247 248 249
  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
250
}
Dries's avatar
 
Dries committed
251

Kjartan's avatar
Kjartan committed
252 253
function taxonomy_overview() {
  global $tree;
Dries's avatar
 
Dries committed
254

Dries's avatar
 
Dries committed
255
  $output .= "<h3>" . t("Vocabularies overview") . "</h3>";
Dries's avatar
 
Dries committed
256 257

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

Kjartan's avatar
Kjartan committed
259 260 261
  $vocabularies = taxonomy_get_vocabularies();
  foreach ($vocabularies as $vocabulary) {
    $links = array();
Dries's avatar
 
Dries committed
262

Dries's avatar
 
Dries committed
263
    $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
264

Dries's avatar
 
Dries committed
265
    $tree = taxonomy_get_tree($vocabulary->vid);
Kjartan's avatar
Kjartan committed
266
    if ($tree) {
Dries's avatar
 
Dries committed
267
      unset($data);
Kjartan's avatar
Kjartan committed
268
      foreach ($tree as $term) {
Dries's avatar
 
Dries committed
269
        $data .= _taxonomy_depth($term->depth) ." ". $term->name ." (". la(t("edit term"), array("mod" => "taxonomy", "op" => "edit", "type" => "term", "id" => check_output($term->tid))) .")<br />";
Dries's avatar
 
Dries committed
270
      }
Dries's avatar
 
Dries committed
271
      $rows[] = array(array("data" => $data, "colspan" => 5));
Dries's avatar
 
Dries committed
272 273 274
    }
  }

Dries's avatar
 
Dries committed
275
  return table($header, $rows);
Kjartan's avatar
Kjartan committed
276 277 278 279 280 281 282 283 284 285
}

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

Kjartan's avatar
Kjartan committed
289
  if ($vocabulary->multiple) {
Dries's avatar
 
Dries committed
290
    $description = t("You $verb choose one or more terms for this node.");
Kjartan's avatar
Kjartan committed
291
    $multiple = 1;
Dries's avatar
 
Dries committed
292
  }
Kjartan's avatar
Kjartan committed
293
  else {
Dries's avatar
 
Dries committed
294
    $description = t("You $verb choose one term for this node.");
Kjartan's avatar
Kjartan committed
295 296 297 298
    $multiple = 0;
  }
  return _taxonomy_term_select($vocabulary->name, "taxonomy", $value, $vocabulary_id, $description, $multiple, $blank);
}
Dries's avatar
 
Dries committed
299 300 301 302 303

/*
** API functions
*/

Kjartan's avatar
Kjartan committed
304 305 306 307 308 309 310 311 312 313 314
// 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
315
  }
Kjartan's avatar
Kjartan committed
316 317
  return $vocabularies;
}
Dries's avatar
 
Dries committed
318

Kjartan's avatar
Kjartan committed
319 320 321 322 323
// 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
324 325
    }
    else {
Kjartan's avatar
Kjartan committed
326
      $terms = 0;
Dries's avatar
 
Dries committed
327
    }
Kjartan's avatar
Kjartan committed
328 329 330 331
  }
  else {
    $terms = $node->taxonomy;
  }
Dries's avatar
 
Dries committed
332

Kjartan's avatar
Kjartan committed
333 334 335
  $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
336
  }
Kjartan's avatar
Kjartan committed
337 338
  return $result ? $result : array();
}
Dries's avatar
 
Dries committed
339

Kjartan's avatar
Kjartan committed
340 341 342
// 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
343

Dries's avatar
 
Dries committed
344
  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
345 346 347 348
}

// 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
349
  $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
350 351 352
  $terms = array();
  while ($term = db_fetch_object($result)) {
    $terms[$term->$key] = $term;
Dries's avatar
 
Dries committed
353
  }
Kjartan's avatar
Kjartan committed
354 355 356 357 358 359
  return $terms;
}

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

Dries's avatar
 
Dries committed
361
  if (!isset($terms[$nid])) {
Dries's avatar
 
Dries committed
362
    $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
363
    $terms[$nid] = array();
Dries's avatar
 
Dries committed
364
    while ($term = db_fetch_object($result)) {
Kjartan's avatar
Kjartan committed
365
      $terms[$nid][$term->$key] = $term;
Dries's avatar
 
Dries committed
366 367
    }
  }
Kjartan's avatar
Kjartan committed
368 369
  return $terms[$nid];
}
Dries's avatar
 
Dries committed
370

Kjartan's avatar
Kjartan committed
371 372 373
// save terms of a node
function taxonomy_node_save($nid, $terms) {
  taxonomy_node_delete($nid);
Dries's avatar
 
Dries committed
374

Kjartan's avatar
Kjartan committed
375
  if ($terms) {
Dries's avatar
 
Dries committed
376 377
    foreach ($terms as $term) {
      db_query("INSERT INTO term_node (nid, tid) VALUES ('%d', '%d')", $nid, $term);
Dries's avatar
 
Dries committed
378 379
    }
  }
Kjartan's avatar
Kjartan committed
380
}
Dries's avatar
 
Dries committed
381

Kjartan's avatar
Kjartan committed
382 383
// clean up terms
function taxonomy_node_delete($nid) {
Dries's avatar
 
Dries committed
384
  db_query("DELETE FROM term_node WHERE nid = '%d'", $nid);
Kjartan's avatar
Kjartan committed
385
}
Dries's avatar
 
Dries committed
386

Kjartan's avatar
Kjartan committed
387 388 389
// relations: return array of related terms
function taxonomy_get_related($tid, $key = "tid") {
  if ($tid) {
Dries's avatar
 
Dries committed
390
    $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
391 392 393
    $related = array();
    while ($term = db_fetch_object($result)) {
      $related[$term->$key] = $term;
Dries's avatar
 
Dries committed
394
    }
Kjartan's avatar
Kjartan committed
395
    return $related;
Dries's avatar
 
Dries committed
396
  }
Kjartan's avatar
Kjartan committed
397 398
  else {
    return array();
Dries's avatar
 
Dries committed
399
  }
Kjartan's avatar
Kjartan committed
400
}
Dries's avatar
 
Dries committed
401

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

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

Kjartan's avatar
Kjartan committed
432
// hierarchy: get whole family, with tid, parent and depth; useful to show
Dries's avatar
 
Dries committed
433 434
function taxonomy_get_tree($vocabulary_id, $parent = 0, $depth = -1, $key = "tid") {
  static $children, $parents, $terms, $tree;
Kjartan's avatar
Kjartan committed
435
  if ($depth == -1) {
Dries's avatar
 
Dries committed
436
    $children = array();
Dries's avatar
 
Dries committed
437 438
    $parents = array();
    $terms = array();
Kjartan's avatar
Kjartan committed
439
    $tree = array();
Dries's avatar
 
Dries committed
440
  }
Dries's avatar
 
Dries committed
441

Kjartan's avatar
Kjartan committed
442
  $depth++;
Dries's avatar
 
Dries committed
443 444 445 446 447 448 449

  if (!count($children)) {
    $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)) {
      $children[$term->parent][] = $term->tid;
      $parents[$term->tid][] = $term->parent;
      $terms[$term->tid] = $term;
Dries's avatar
 
Dries committed
450 451
    }
  }
Dries's avatar
 
Dries committed
452 453 454 455 456 457 458 459 460 461

  if ($children[$parent]) {
    foreach ($children[$parent] as $child) {
      $terms[$child]->depth = $depth;
      unset($terms[$child]->parent); // this would show just one parent
      $terms[$child]->parents = $parents[$child];
      $tree[] = $terms[$child];

      taxonomy_get_tree($vocabulary_id, $child, $depth, $key);
    }
Kjartan's avatar
Kjartan committed
462
  }
Dries's avatar
 
Dries committed
463 464

  return $tree;
Kjartan's avatar
Kjartan committed
465
}
Dries's avatar
 
Dries committed
466

Kjartan's avatar
Kjartan committed
467 468 469
// synonyms: return array of synonyms
function taxonomy_get_synonyms($tid) {
  if ($tid) {
Dries's avatar
 
Dries committed
470
    $result = db_query("SELECT name FROM term_synonym WHERE tid = '%d'", $tid);
Kjartan's avatar
Kjartan committed
471 472
    while ($synonym = db_fetch_array($result)) {
      $synonyms[] = $synonym["name"];
Dries's avatar
 
Dries committed
473
    }
Kjartan's avatar
Kjartan committed
474
    return $synonyms ? $synonyms : array();
Dries's avatar
 
Dries committed
475
  }
Kjartan's avatar
Kjartan committed
476 477
  else {
    return array();
Dries's avatar
 
Dries committed
478
  }
Kjartan's avatar
Kjartan committed
479
}
Dries's avatar
 
Dries committed
480

Kjartan's avatar
Kjartan committed
481 482 483 484
// 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
485

Kjartan's avatar
Kjartan committed
486
// given a term id, count number of nodes in it
Dries's avatar
 
Dries committed
487
function taxonomy_term_count_nodes($tid, $type = 0) {
Kjartan's avatar
Kjartan committed
488
  static $count;
Dries's avatar
 
Dries committed
489

Dries's avatar
 
Dries committed
490 491 492
  if (!isset($count[$type])) {
    // $type == 0 always evaluates true is $type is a string
    if (is_numeric($type)) {
Dries's avatar
 
Dries committed
493
      $result = db_query("SELECT t.tid, COUNT(*) AS c FROM term_node t GROUP BY t.tid");
Dries's avatar
 
Dries committed
494 495
    }
    else {
Dries's avatar
 
Dries committed
496
      $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
497
    }
Kjartan's avatar
Kjartan committed
498
    while ($term = db_fetch_object($result)) {
Dries's avatar
 
Dries committed
499
      $count[$type][$term->tid] = $term->c;
Dries's avatar
 
Dries committed
500 501 502
    }
  }

Kjartan's avatar
Kjartan committed
503
  foreach (_taxonomy_term_children($tid) as $c) {
Dries's avatar
 
Dries committed
504
    $children_count += taxonomy_term_count_nodes($c, $type);
Kjartan's avatar
Kjartan committed
505
  }
Dries's avatar
 
Dries committed
506
  return $count[$type][$tid] + $children_count;
Kjartan's avatar
Kjartan committed
507 508 509 510 511
}

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

Dries's avatar
 
Dries committed
513
  if (!isset($children)) {
Kjartan's avatar
Kjartan committed
514 515 516
    $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
517
    }
Dries's avatar
 
Dries committed
518
  }
Kjartan's avatar
Kjartan committed
519 520
  return $children[$tid] ? $children[$tid] : array();
}
Dries's avatar
 
Dries committed
521

Dries's avatar
 
Dries committed
522 523 524 525 526 527 528 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
/**
 * 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
560 561
function taxonomy_get_vocabulary($vid) {
  // simple cache using a static var?
Dries's avatar
 
Dries committed
562
  return db_fetch_object(db_query("SELECT * FROM vocabulary WHERE vid = '%d'", $vid));
Kjartan's avatar
Kjartan committed
563
}
Dries's avatar
 
Dries committed
564

Kjartan's avatar
Kjartan committed
565 566
function taxonomy_get_term($tid) {
  // simple cache using a static var?
Dries's avatar
 
Dries committed
567
  return db_fetch_object(db_query("SELECT * FROM term_data WHERE tid = '%d'", $tid));
Kjartan's avatar
Kjartan committed
568
}
Dries's avatar
 
Dries committed
569 570 571 572 573

/*
** service functions
*/

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

Kjartan's avatar
Kjartan committed
577 578 579
  if ($blank) {
    $options[0] = $blank;
  }
Dries's avatar
 
Dries committed
580

Kjartan's avatar
Kjartan committed
581 582 583 584
  if ($tree) {
    foreach ($tree as $term) {
      if (!in_array($term->tid, $exclude)) {
        $options[$term->tid] = _taxonomy_depth($term->depth, '-').$term->name;
Dries's avatar
 
Dries committed
585 586
      }
    }
Kjartan's avatar
Kjartan committed
587 588 589 590 591
    if (!$blank && !$value) {
      // required but without a predefined value, so set first as predefined
      $value = $tree[0]->tid;
    }
  }
Dries's avatar
 
Dries committed
592

Kjartan's avatar
Kjartan committed
593 594 595 596
  if (count($options) > 0) {
    foreach ($options as $key=>$choice) {
      $select .= "<option value=\"$key\"". (is_array($value) ? (in_array($key, $value) ? " selected=\"selected\"" : "") : ($key == $value ? " selected=\"selected\"" : "")) .">". check_form($choice) ."</option>";
    }
Dries's avatar
 
Dries committed
597

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

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

Kjartan's avatar
Kjartan committed
604 605 606
function _taxonomy_depth($depth, $graphic = '--') {
  for ($n = 0; $n < $depth; $n++) {
    $result .= $graphic;
Dries's avatar
 
Dries committed
607
  }
Kjartan's avatar
Kjartan committed
608 609
  return $result;
}
Dries's avatar
 
Dries committed
610

Kjartan's avatar
Kjartan committed
611 612 613
function _prepare_update($data) {
  foreach ($data as $key => $value) {
    $q[] = "$key = '". check_query($value) ."'";
Dries's avatar
 
Dries committed
614
  }
Kjartan's avatar
Kjartan committed
615 616 617
  $result = implode(", ", $q);
  return $result;
}
Dries's avatar
 
Dries committed
618

Kjartan's avatar
Kjartan committed
619 620 621 622 623 624 625
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
626
    }
Kjartan's avatar
Kjartan committed
627
    $result = implode(", ", $q);
Dries's avatar
 
Dries committed
628
  }
Kjartan's avatar
Kjartan committed
629 630
  return "($result)";
}
Dries's avatar
 
Dries committed
631

Kjartan's avatar
Kjartan committed
632 633
function taxonomy_page() {
  global $op;
Dries's avatar
 
Dries committed
634

Kjartan's avatar
Kjartan committed
635 636 637 638 639 640
  switch ($op) {
    case "feed":
      taxonomy_feed();
      break;
    default:
       // TODO: pretty display of all vocabularies
Dries's avatar
 
Dries committed
641
  }
Kjartan's avatar
Kjartan committed
642
}
Dries's avatar
 
Dries committed
643

Kjartan's avatar
Kjartan committed
644
/*
Dries's avatar
 
Dries committed
645 646 647
** admin
*/

Kjartan's avatar
Kjartan committed
648
function taxonomy_admin() {
Dries's avatar
 
Dries committed
649
  global $edit, $type, $op, $id, $theme;
Kjartan's avatar
Kjartan committed
650 651 652 653

  if (user_access("administer taxonomy")) {
    switch ($op) {
      case "add":
Kjartan's avatar
Kjartan committed
654
        if ($type == "vocabulary") {
Kjartan's avatar
Kjartan committed
655
          print taxonomy_form_vocabulary();
Kjartan's avatar
Kjartan committed
656 657
        }
        else {
Kjartan's avatar
Kjartan committed
658
          print taxonomy_form_term();
Kjartan's avatar
Kjartan committed
659
        }
Kjartan's avatar
Kjartan committed
660 661
        break;
      case "edit":
Kjartan's avatar
Kjartan committed
662
        if ($type == "vocabulary") {
Kjartan's avatar
Kjartan committed
663
          print taxonomy_form_vocabulary(object2array(taxonomy_get_vocabulary($id)));
Kjartan's avatar
Kjartan committed
664 665
        }
        else {
Kjartan's avatar
Kjartan committed
666
          print taxonomy_form_term(object2array(taxonomy_get_term($id)));
Kjartan's avatar
Kjartan committed
667
        }
Kjartan's avatar
Kjartan committed
668 669
        break;
      case "preview":
Kjartan's avatar
Kjartan committed
670
        print taxonomy_form($id);
Kjartan's avatar
Kjartan committed
671 672 673 674
        break;
      case "help":
        print taxonomy_help();
        break;
Dries's avatar
 
Dries committed
675
      case t("Delete"):
Dries's avatar
 
Dries committed
676 677 678 679 680 681 682 683 684 685 686 687 688
        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
689
      case t("Submit"):
Kjartan's avatar
Kjartan committed
690
        if ($type == "vocabulary") {
Kjartan's avatar
Kjartan committed
691
          print status(taxonomy_save_vocabulary($edit));
Kjartan's avatar
Kjartan committed
692 693
        }
        else {
Kjartan's avatar
Kjartan committed
694
          print status(taxonomy_save_term($edit));
Dries's avatar
 
Dries committed
695 696 697 698 699 700
          if (!$edit["tid"]) {
            // if INSERT show form again
            print taxonomy_form_term();
            break;
          }
          // else (UPDATE or DELETE) fall through
Kjartan's avatar
Kjartan committed
701
        }
Kjartan's avatar
Kjartan committed
702 703 704 705 706 707 708 709 710 711 712 713
        // fall through:
      default:
        print taxonomy_overview();
    }
  }
  else {
    print message_access();
  }
}

function taxonomy_help() {
  ?>
Dries's avatar
 
Dries committed
714 715 716 717 718 719

  <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
720 721 722 723 724 725 726 727 728 729 730
  --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
731 732 733 734 735 736
  <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
737
  <h3>Vocabularies</h3>
Dries's avatar
 
Dries committed
738
  <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
739 740

  <h4>Setting up a vocabulary</h4>
Dries's avatar
 
Dries committed
741 742 743
  <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
744
  <br />
Dries's avatar
 
Dries committed
745
  <i>Description</i><br />Optional. Description of the vocabulary, can be used by modules and feeds.<br />
Kjartan's avatar
Kjartan committed
746
  <br />
Dries's avatar
 
Dries committed
747
  <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
748
  <br />
Dries's avatar
 
Dries committed
749
  <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
750
  <br />
Dries's avatar
 
Dries committed
751
  <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
752
  <br />
Dries's avatar
 
Dries committed
753 754
  <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
755
  <h4>Adding terms to a vocabulary</h4>
Dries's avatar
 
Dries committed
756 757 758
<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
759
  <br />
Dries's avatar
 
Dries committed
760
  <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
761
  <br />
Dries's avatar
 
Dries committed
762
  <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
763
  <br />
Dries's avatar
 
Dries committed
764 765 766
  <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
767
  <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
768 769 770 771

  <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
772
}
Dries's avatar
 
Dries committed
773
?>