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

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

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

Kjartan's avatar
Kjartan committed
12
  if ($type == "voc") {
Dries's avatar
   
Dries committed
13
    //TODO - vocabulary feed.
Kjartan's avatar
Kjartan committed
14
15
  }
  else {
Dries's avatar
   
Dries committed
16
17
18
    $result = taxonomy_select_nodes($taxonomy, 0);
    $term = taxonomy_get_term($taxonomy->tids[0]);
    $channel["link"] = path_uri(). url("taxonomy/view/$taxonomy->operator/$taxonomy->str_tids");
Kjartan's avatar
Kjartan committed
19
20
21
    $channel["title"] = variable_get("site_name", "drupal") ." - ". $term->name;
    $channel["description"] = $term->description;
    node_feed($result, $channel);
Dries's avatar
   
Dries committed
22
  }
Kjartan's avatar
Kjartan committed
23
}
Dries's avatar
   
Dries committed
24

Kjartan's avatar
Kjartan committed
25
26
27
function taxonomy_perm() {
  return array("administer taxonomy");
}
Dries's avatar
 
Dries committed
28

Dries's avatar
   
Dries committed
29
function taxonomy_link($type, $node = NULL) {
Kjartan's avatar
Kjartan committed
30
  if ($type == "admin" && user_access("administer taxonomy")) {
Dries's avatar
   
Dries committed
31
32
    $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
33

Dries's avatar
   
Dries committed
34
    menu_add("taxonomy", url("admin/taxonomy"), "Administer taxonomies.", $help["taxonomy"], "content management", 1);
Dries's avatar
   
Dries committed
35
36
    menu_add("add new vocabulary", url("admin/taxonomy/add/vocabulary"), "Add a new vocabulary.", $help["vocabulary"], "taxonomy");
    menu_add("help", url("admin/taxonomy/help"), "More information about taxonomies.", NULL, "taxonomy", 9);
Dries's avatar
   
Dries committed
37
  }
Dries's avatar
   
Dries committed
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
  else if ($type == "taxonomy terms" && $node != NULL) {
    /*
    ** Themes can print taxonomy links with:
    **
    ** if (module_exist("taxonomy")) {
    **   $this->links(taxonomy_link("taxonomy terms", $node));
    ** }
    */

    $links = array();

    foreach (taxonomy_node_get_terms($node->nid) as $term) {
      $links[] = l($term->name, "taxonomy/page/or/$term->tid", $term->description ? array("title" => $term->description) : array());
    }

    return $links;
  }
Kjartan's avatar
Kjartan committed
55
56
}

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Kjartan's avatar
Kjartan committed
137
function taxonomy_form_term($edit = array()) {
Dries's avatar
   
Dries committed
138
  $vocabulary_id = arg(4);
Dries's avatar
   
Dries committed
139

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

Dries's avatar
   
Dries committed
145
146
  $form = form_textfield(t("Term name"), "name", $edit["name"], 50, 64, t("Required") . ". " . t("The name for this term.  Example: 'Linux'."));
  $form .= form_textarea(t("Description"), "description", $edit["description"], 60, 5, t("Optional") . ". " . t("A description of the term."));
Dries's avatar
 
Dries committed
147

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

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

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

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

Dries's avatar
   
Dries committed
170
  $form .= form_textarea(t("Synonyms"), "synonyms", implode("\n", taxonomy_get_synonyms($edit["tid"])), 30, 5, t("Optional") . ". ". t(l("Synonyms", "admin/taxonomy/help#synonyms") ." of this term, one synonym per line."));
Dries's avatar
   
Dries committed
171
  $form .= form_weight(t("Weight"), "weight", $edit["weight"], 10, t("Optional. In listings, the heavier terms will sink and the lighter terms will be positioned nearer the top."));
Kjartan's avatar
Kjartan committed
172
  $form .= form_hidden("vid", $vocabulary->vid);
Dries's avatar
   
Dries committed
173
  $form .= form_submit(t("Submit"));
Kjartan's avatar
Kjartan committed
174
175

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

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

Kjartan's avatar
Kjartan committed
183
184
185
function taxonomy_save_term($edit) {
 if ($edit["tid"] && $edit["name"]) {
    $data = array("name" => $edit["name"], "description" => $edit["description"], "weight" => $edit["weight"]);
Dries's avatar
 
Dries committed
186

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

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

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

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

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

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

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

Dries's avatar
   
Dries committed
243
244
245
246
247
  db_query("DELETE FROM term_data WHERE tid = '%d'", $tid);
  db_query("DELETE FROM term_hierarchy WHERE tid = '%d'", $tid);
  db_query("DELETE FROM term_relation WHERE tid1 = '%d' OR tid2 = '%d'", $tid, $tid);
  db_query("DELETE FROM term_synonym WHERE tid = '%d'", $tid);
  db_query("DELETE FROM term_node WHERE tid = '%d'", $tid);
Dries's avatar
   
Dries committed
248

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

Dries's avatar
   
Dries committed
252
253
254
255
256
257
258
259
260
261
262
263
264
  return t("deleted term '%name'.", array("%name" => $term->name));
}

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

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

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

Kjartan's avatar
Kjartan committed
267
function taxonomy_overview() {
Dries's avatar
 
Dries committed
268

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

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

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

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

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

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

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

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

/*
** API functions
*/

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Dries's avatar
   
Dries committed
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
/**
 * 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
571
572
function taxonomy_get_vocabulary($vid) {
  // simple cache using a static var?
Dries's avatar
   
Dries committed
573
  return db_fetch_object(db_query("SELECT * FROM vocabulary WHERE vid = '%d'", $vid));
Kjartan's avatar
Kjartan committed
574
}
Dries's avatar
 
Dries committed
575

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

/*
** service functions
*/

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

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

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

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

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

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

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

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

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

Dries's avatar
   
Dries committed
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
/*
** Accepts taxonomy conditions and returns a resource identifier.  If
** you intend to use the nodes without a pager (eg. in a XML feed),
** then set $pager to false.
*/
function taxonomy_select_nodes($taxonomy, $pager = 1) {
  global $user;

  if ($taxonomy->operator == "or") {
    $sql = "SELECT DISTINCT(n.nid), n.title, n.type, n.created, n.changed, n.uid, u.name FROM node n LEFT JOIN term_node r ON n.nid = r.nid LEFT JOIN users u ON n.uid = u.uid WHERE tid IN ($taxonomy->str_tids) AND n.status = '1' ORDER BY static DESC, created DESC";
    $sql_count = "SELECT COUNT(DISTINCT(n.nid)) FROM node n LEFT JOIN term_node r ON n.nid = r.nid LEFT JOIN users u ON n.uid = u.uid WHERE tid IN ($taxonomy->str_tids) AND n.status = '1'";
  }
  else {
    $sql = "SELECT n.nid, n.title, n.type, n.created, n.changed, n.uid, u.name FROM node n LEFT JOIN term_node r ON n.nid = r.nid LEFT JOIN users u ON n.uid = u.uid WHERE tid IN ($taxonomy->str_tids) AND n.status = '1' GROUP BY n.nid, n.title, n.type, n.created, n.changed, n.uid, u.name HAVING COUNT(n.nid) = ".count($taxonomy->tids)." ORDER BY static DESC, created DESC";

    // Special trick as we could not find anything better:
    $count = db_num_rows(db_query("SELECT n.nid FROM node n LEFT JOIN term_node r ON n.nid = r.nid WHERE tid IN ($taxonomy->str_tids) AND n.status = '1' GROUP BY n.nid HAVING COUNT(n.nid) = ". count($taxonomy->tids)));
    $sql_count = "SELECT $count";
  }

  if ($pager) {
    $result = pager_query($sql, variable_get("default_nodes_main", 10) , 0, $sql_count);
  }
  else {
    $result = db_query($sql ." LIMIT 15");
  }

  return $result;
}

/*
** Accepts the result of a db_query() and formats each node along
** with a pager.
*/
function taxonomy_render_nodes($result) {

  while ($node = db_fetch_object($result)) {
    node_view(node_load(array("nid" => $node->nid, "type" => $node->type)), 1);
  }
  print pager_display_default(NULL, variable_get("default_nodes_main", 10), 0);
}

Kjartan's avatar
Kjartan committed
685
function taxonomy_page() {
Dries's avatar
   
Dries committed
686

Dries's avatar
   
Dries committed
687
688
689
690
691
692

  // taxonomy querystring always parsed here
  // TODO: support term *names* in URL (e.g. taxonomy/view/or/milk,beer,red+wine)
  $taxonomy->operator = arg(2);
  $taxonomy->str_tids = check_query(arg(3));
  $taxonomy->tids = explode(",", $taxonomy->str_tids);
Dries's avatar
   
Dries committed
693

Dries's avatar
   
Dries committed
694
  switch (arg(1)) {
Kjartan's avatar
Kjartan committed
695
    case "feed":
Dries's avatar
   
Dries committed
696
      taxonomy_feed($taxonomy);
Kjartan's avatar
Kjartan committed
697
698
      break;
    default:
Dries's avatar
   
Dries committed
699
      theme("header");
Dries's avatar
   
Dries committed
700
      taxonomy_render_nodes(taxonomy_select_nodes($taxonomy));
Dries's avatar
   
Dries committed
701
      theme("footer");
Dries's avatar
   
Dries committed
702
      break;
Dries's avatar
   
Dries committed
703
  }
Kjartan's avatar
Kjartan committed
704
}
Dries's avatar
   
Dries committed
705

Kjartan's avatar
Kjartan committed
706
/*
Dries's avatar
 
Dries committed
707
708
709
** admin
*/

Kjartan's avatar
Kjartan committed
710
function taxonomy_admin() {
Dries's avatar
   
Dries committed
711
  global $op, $edit;
Kjartan's avatar
Kjartan committed
712
713

  if (user_access("administer taxonomy")) {
Dries's avatar
   
Dries committed
714
715
716
717
    if (empty($op)) {
      $op = arg(2);
    }

Kjartan's avatar
Kjartan committed
718
719
    switch ($op) {
      case "add":
Dries's avatar
   
Dries committed
720
        if (arg(3) == "vocabulary") {
Kjartan's avatar
Kjartan committed
721
          print taxonomy_form_vocabulary();
Kjartan's avatar
Kjartan committed
722
723
        }
        else {
Kjartan's avatar
Kjartan committed
724
          print taxonomy_form_term();
Kjartan's avatar
Kjartan committed
725
        }
Kjartan's avatar
Kjartan committed
726
727
        break;
      case "edit":
Dries's avatar
   
Dries committed
728
729
        if (arg(3) == "vocabulary") {
          print taxonomy_form_vocabulary(object2array(taxonomy_get_vocabulary(arg(4))));
Kjartan's avatar
Kjartan committed
730
731
        }
        else {
Dries's avatar
   
Dries committed
732
          print taxonomy_form_term(object2array(taxonomy_get_term(arg(4))));
Kjartan's avatar
Kjartan committed
733
        }
Kjartan's avatar
Kjartan committed
734
735
        break;
      case "preview":
Dries's avatar
   
Dries committed
736
        print taxonomy_form(arg(4));
Kjartan's avatar
Kjartan committed
737
738
739
740
        break;
      case "help":
        print taxonomy_help();
        break;
Dries's avatar
   
Dries committed
741
      case t("Delete"):
Dries's avatar
   
Dries committed
742
        if (!$edit["confirm"]) {
Dries's avatar
   
Dries committed
743
          if (arg(3) == "vocabulary") {
Dries's avatar
   
Dries committed
744
745
746
747
748
749
750
751
752
753
754
            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
755
      case t("Submit"):
Dries's avatar
   
Dries committed
756
        if (arg(3) == "vocabulary") {
Kjartan's avatar
Kjartan committed
757
          print status(taxonomy_save_vocabulary($edit));
Kjartan's avatar
Kjartan committed
758
759
        }
        else {
Kjartan's avatar
Kjartan committed
760
          print status(taxonomy_save_term($edit));
Dries's avatar
   
Dries committed
761
762
763
764
765
766
          if (!$edit["tid"]) {
            // if INSERT show form again
            print taxonomy_form_term();
            break;
          }
          // else (UPDATE or DELETE) fall through
Kjartan's avatar
Kjartan committed
767
        }
Kjartan's avatar
Kjartan committed
768
769
770
771
772
773
774
775
776
777
778
779
        // fall through:
      default:
        print taxonomy_overview();
    }
  }
  else {
    print message_access();
  }
}

function taxonomy_help() {
  ?>
Dries's avatar
   
Dries committed
780
781

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

  <h3>An example taxonomy: food</h3>
Dries's avatar
   
Dries committed
785
786
787
788
789
  <p>Dairy<br />
  --Milk<br />
  Drink<br />
  --Alchohol<br />
  --Pop<br />
Kjartan's avatar
Kjartan committed
790
  --Milk<br />
Dries's avatar
   
Dries committed
791
792
793
794
795
  Meat<br />
  --Beef<br />
  --Chicken<br />
  --Lamb<br />
  Spices<br />
Kjartan's avatar
Kjartan committed
796
  --Sugar</p>
Dries's avatar
   
Dries committed
797
798
799
800
801
802
  <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
803
  <h3>Vocabularies</h3>
Dries's avatar
   
Dries committed
804
  <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
805
806

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

Dries's avatar
Dries committed
809
  <p><i>Vocabulary name</i><br />Required. The name for this vocabulary. Example: <i>Dairy</i>.<br />
Kjartan's avatar
Kjartan committed
810
  <br />
Dries's avatar
   
Dries committed
811
  <i>Description</i><br />Optional. Description of the vocabulary, can be used by modules and feeds.<br />
Kjartan's avatar
Kjartan committed
812
  <br />
Dries's avatar
   
Dries committed
813
  <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
814
  <br />
Dries's avatar
   
Dries committed
815
  <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
816
  <br />
Dries's avatar
   
Dries committed
817
  <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
818
  <br />
Dries's avatar
Dries committed
819
  <i>Multiple select</i><br />Allows nodes to be described using more than one term. Nodes may then appear on multiple taxonomy pages.</p>
Dries's avatar
   
Dries committed
820

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

Dries's avatar
Dries committed
824
  <p><i>Term name</i><br />Required. The name for this term. Example: <i>Milk</i><br />
Kjartan's avatar
Kjartan committed
825
  <br />
Dries's avatar
   
Dries committed
826
  <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
827
  <br />
Dries's avatar
   
Dries committed
828
  <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
829
  <br />
Dries's avatar
Dries committed
830
  <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>).</p>
Dries's avatar
   
Dries committed
831
832

  <h3>Displaying nodes organized by term(s)</h3>
Dries's avatar
   
Dries committed
833
  <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() . url("node", "or=1,2"); ?>"><?php print path_uri() . url("node", "or=1,2"); ?></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 l("taxonomy overview", "admin/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
834
835

  <h3>RSS feeds</h3>
Dries's avatar
   
Dries committed
836
  <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() . url("node/feed", "or=1,2"); ?>"><?php print path_uri() . url("node/feed", "or=1,2"); ?></a>.</p>
Dries's avatar
   
Dries committed
837
 <?php
Kjartan's avatar
Kjartan committed
838
}
Dries's avatar
   
Dries committed
839
?>