taxonomy.module 31 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("Term <b>%a</b> 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
186

    $message = t("created new term '%name'.", array("%name" => $edit["name"]));
Kjartan's avatar
Kjartan committed
187
  }
Dries's avatar
 
Dries committed
188

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

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

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

Dries's avatar
   
Dries committed
223
224
  cache_clear_all();

Dries's avatar
   
Dries committed
225
  return $message;
Kjartan's avatar
Kjartan committed
226
}
Dries's avatar
 
Dries committed
227

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

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

Dries's avatar
   
Dries committed
237
238
  cache_clear_all();

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

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

Dries's avatar
   
Dries committed
257
  $output .= "<h3>" . t("Vocabularies overview") . "</h3>";
Kjartan's avatar
Kjartan committed
258
  $output .= "<table border=\"1\" cellpadding=\"2\" cellspacing=\"2\">\n";
Dries's avatar
   
Dries committed
259
  $output .= " <tr><th>" . t("name") . "</th><th>" . t("node types") . "</th><th>" . t("operations") . "</th></tr>\n";
Dries's avatar
   
Dries committed
260

Kjartan's avatar
Kjartan committed
261
262
263
264
265
266
  $vocabularies = taxonomy_get_vocabularies();
  foreach ($vocabularies as $vocabulary) {
    $links = array();
    $links[] = la(t("edit vocabulary"), array("mod" => "taxonomy", "type" => "vocabulary", "op" => "edit", "id" => $vocabulary->vid));
    $links[] = la(t("add term"), array("mod" => "taxonomy", "op" => "add", "type" => "leaf", "vocabulary_id" => $vocabulary->vid));
    $links[] = la(t("preview form"), array("mod" => "taxonomy", "type" => "vocabulary", "op" => "preview", "id" => $vocabulary->vid));
Dries's avatar
 
Dries committed
267

Dries's avatar
   
Dries committed
268
    $output .= " <tr><td>". check_output($vocabulary->name) ."</td><td align=\"center\">". check_output($vocabulary->types) ."</td><td>". implode(" | ", $links) ."</td></tr>\n";
Kjartan's avatar
Kjartan committed
269

Dries's avatar
   
Dries committed
270
    $tree = taxonomy_get_tree($vocabulary->vid);
Kjartan's avatar
Kjartan committed
271
272
273
274
    if ($tree) {
      $output .= "<tr><td colspan=\"3\"><table><tr><td>";
      foreach ($tree as $term) {
        $output .= "<tr><td>". la(_taxonomy_depth($term->depth) . check_output($term->name), array("mod" => "taxonomy", "op" => "edit", "type" => "term", "id" => check_output($term->tid))) ."</td></tr>";
Dries's avatar
 
Dries committed
275
      }
Kjartan's avatar
Kjartan committed
276
      $output .= "</td></tr></table></td></tr>\n";
Dries's avatar
 
Dries committed
277
278
    }
  }
Kjartan's avatar
Kjartan committed
279
  $output .= "</table>\n";
Dries's avatar
 
Dries committed
280

Kjartan's avatar
Kjartan committed
281
282
283
284
285
286
287
288
289
290
291
  return $output;
}

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

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

/*
** API functions
*/

Kjartan's avatar
Kjartan committed
310
311
312
313
314
315
316
317
318
319
320
// 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
321
  }
Kjartan's avatar
Kjartan committed
322
323
  return $vocabularies;
}
Dries's avatar
 
Dries committed
324

Kjartan's avatar
Kjartan committed
325
326
327
328
329
// 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
330
331
    }
    else {
Kjartan's avatar
Kjartan committed
332
      $terms = 0;
Dries's avatar
 
Dries committed
333
    }
Kjartan's avatar
Kjartan committed
334
335
336
337
  }
  else {
    $terms = $node->taxonomy;
  }
Dries's avatar
 
Dries committed
338

Kjartan's avatar
Kjartan committed
339
340
341
  $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
342
  }
Kjartan's avatar
Kjartan committed
343
344
  return $result ? $result : array();
}
Dries's avatar
 
Dries committed
345

Kjartan's avatar
Kjartan committed
346
347
348
// 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
349

Dries's avatar
   
Dries committed
350
  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
351
352
353
354
}

// 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
355
  $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
356
357
358
  $terms = array();
  while ($term = db_fetch_object($result)) {
    $terms[$term->$key] = $term;
Dries's avatar
 
Dries committed
359
  }
Kjartan's avatar
Kjartan committed
360
361
362
363
364
365
  return $terms;
}

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

Dries's avatar
   
Dries committed
367
  if (!isset($terms[$nid])) {
Dries's avatar
   
Dries committed
368
    $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
369
    $terms[$nid] = array();
Dries's avatar
 
Dries committed
370
    while ($term = db_fetch_object($result)) {
Kjartan's avatar
Kjartan committed
371
      $terms[$nid][$term->$key] = $term;
Dries's avatar
 
Dries committed
372
373
    }
  }
Kjartan's avatar
Kjartan committed
374
375
  return $terms[$nid];
}
Dries's avatar
 
Dries committed
376

Kjartan's avatar
Kjartan committed
377
378
379
// save terms of a node
function taxonomy_node_save($nid, $terms) {
  taxonomy_node_delete($nid);
Dries's avatar
 
Dries committed
380

Kjartan's avatar
Kjartan committed
381
  if ($terms) {
Dries's avatar
   
Dries committed
382
383
    foreach ($terms as $term) {
      db_query("INSERT INTO term_node (nid, tid) VALUES ('%d', '%d')", $nid, $term);
Dries's avatar
 
Dries committed
384
385
    }
  }
Kjartan's avatar
Kjartan committed
386
}
Dries's avatar
 
Dries committed
387

Kjartan's avatar
Kjartan committed
388
389
// clean up terms
function taxonomy_node_delete($nid) {
Dries's avatar
   
Dries committed
390
  db_query("DELETE FROM term_node WHERE nid = '%d'", $nid);
Kjartan's avatar
Kjartan committed
391
}
Dries's avatar
 
Dries committed
392

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

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

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

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

Kjartan's avatar
Kjartan committed
448
  $depth++;
Dries's avatar
   
Dries committed
449
450
451
452
453
454
455

  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
456
457
    }
  }
Dries's avatar
   
Dries committed
458
459
460
461
462
463
464
465
466
467

  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
468
  }
Dries's avatar
   
Dries committed
469
470

  return $tree;
Kjartan's avatar
Kjartan committed
471
}
Dries's avatar
 
Dries committed
472

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

Kjartan's avatar
Kjartan committed
487
488
489
490
// 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
491

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

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

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

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

Dries's avatar
   
Dries committed
519
  if (!isset($children)) {
Kjartan's avatar
Kjartan committed
520
521
522
    $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
523
    }
Dries's avatar
 
Dries committed
524
  }
Kjartan's avatar
Kjartan committed
525
526
  return $children[$tid] ? $children[$tid] : array();
}
Dries's avatar
 
Dries committed
527

Dries's avatar
   
Dries committed
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
560
561
562
563
564
565
/**
 * 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
566
567
function taxonomy_get_vocabulary($vid) {
  // simple cache using a static var?
Dries's avatar
   
Dries committed
568
  return db_fetch_object(db_query("SELECT * FROM vocabulary WHERE vid = '%d'", $vid));
Kjartan's avatar
Kjartan committed
569
}
Dries's avatar
 
Dries committed
570

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

/*
** service functions
*/

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

Kjartan's avatar
Kjartan committed
583
584
585
  if ($blank) {
    $options[0] = $blank;
  }
Dries's avatar
 
Dries committed
586

Kjartan's avatar
Kjartan committed
587
588
589
590
  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
591
592
      }
    }
Kjartan's avatar
Kjartan committed
593
594
595
596
597
    if (!$blank && !$value) {
      // required but without a predefined value, so set first as predefined
      $value = $tree[0]->tid;
    }
  }
Dries's avatar
 
Dries committed
598

Kjartan's avatar
Kjartan committed
599
600
601
602
  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
603

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

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

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

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

Kjartan's avatar
Kjartan committed
625
626
627
628
629
630
631
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
632
    }
Kjartan's avatar
Kjartan committed
633
    $result = implode(", ", $q);
Dries's avatar
 
Dries committed
634
  }
Kjartan's avatar
Kjartan committed
635
636
  return "($result)";
}
Dries's avatar
   
Dries committed
637

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

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

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

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

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

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

  <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
726
727
728
729
730
731
732
733
734
735
736
  --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
737
738
739
740
741
742
  <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
743
  <h3>Vocabularies</h3>
Dries's avatar
   
Dries committed
744
  <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
745
746

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

  <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
778
}
Dries's avatar
   
Dries committed
779
?>