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

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

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
    $result = taxonomy_select_nodes($taxonomy, 0);
    $term = taxonomy_get_term($taxonomy->tids[0]);
Dries's avatar
   
Dries committed
18
    $channel["link"] = 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
    $help["taxonomy"] = "The taxonomy module allows you to classify posts 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).";
Dries's avatar
   
Dries committed
32
    $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("admin/taxonomy", "taxonomy", "taxonomy_admin", $help["taxonomy"], 3);
35
    menu("admin/taxonomy/add/vocabulary", "create new vocabulary", "taxonomy_admin", $help["vocabulary"]);
Dries's avatar
   
Dries committed
36
    menu("admin/taxonomy/help", "help", "taxonomy_admin", NULL, 9);
Dries's avatar
   
Dries committed
37
  }
Dries's avatar
   
Dries committed
38
  else if ($type == "taxonomy terms" && $node != NULL) {
Dries's avatar
   
Dries committed
39
40
41
42
43
44
45
46
47

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

Dries's avatar
   
Dries committed
48
49
50
51
52
53
54
55
    /*
    ** Themes can print taxonomy links with:
    **
    ** if (module_exist("taxonomy")) {
    **   $this->links(taxonomy_link("taxonomy terms", $node));
    ** }
    */

Dries's avatar
   
Dries committed
56
57
58
59
      $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());
      }
Dries's avatar
   
Dries committed
60
61
62
63

    }
    return $links;
  }
Kjartan's avatar
Kjartan committed
64
65
}

Dries's avatar
 
Dries committed
66
67
68
69
/*
** admin pages (form, save, overview)
*/

Kjartan's avatar
Kjartan committed
70
71
72
73
function taxonomy_form_vocabulary($edit = array()) {
  foreach (module_list() as $name) {
    if (module_hook($name, "node")) {
      $nodetypes[$name] = $name;
Dries's avatar
 
Dries committed
74
    }
Kjartan's avatar
Kjartan committed
75
  }
Dries's avatar
   
Dries committed
76

Dries's avatar
   
Dries committed
77
78
79
  $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
80
81
  $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
82
83
  $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
84
  $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
85
  $form .= form_submit(t("Submit"));
Dries's avatar
 
Dries committed
86

Kjartan's avatar
Kjartan committed
87
  if ($edit["vid"]) {
Dries's avatar
   
Dries committed
88
    $form .= form_submit(t("Delete"));
Kjartan's avatar
Kjartan committed
89
    $form .= form_hidden("vid", $edit["vid"]);
Dries's avatar
 
Dries committed
90
91
  }

Kjartan's avatar
Kjartan committed
92
93
  return form($form);
}
Kjartan's avatar
Kjartan committed
94

Kjartan's avatar
Kjartan committed
95
96
97
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
98
    db_query("UPDATE vocabulary SET ". _prepare_update($data) ." WHERE vid = %d", $edit["vid"]);
Dries's avatar
   
Dries committed
99
100
    module_invoke_all("taxonomy", "update", "vocabulary", $edit);
    $message = t("updated vocabulary '%name'.", array("%name" => $edit["name"]));
Dries's avatar
 
Dries committed
101
  }
Kjartan's avatar
Kjartan committed
102
  else if ($edit["vid"]) {
Dries's avatar
   
Dries committed
103
    $message = taxonomy_del_vocabulary($edit["vid"]);
Kjartan's avatar
Kjartan committed
104
105
  }
  else {
Dries's avatar
   
Dries committed
106
    $data["vid"] = $edit["vid"] = db_next_id("vocabulary_vid");
Kjartan's avatar
Kjartan committed
107
    db_query("INSERT INTO vocabulary ". _prepare_insert($data, 1) ." VALUES ". _prepare_insert($data, 2));
Dries's avatar
   
Dries committed
108
109
    module_invoke_all("taxonomy", "insert", "vocabulary", $edit);
    $message = t("created new vocabulary '%name'.", array("%name" => $edit["name"]));
Kjartan's avatar
Kjartan committed
110
  }
Dries's avatar
   
Dries committed
111
112

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

  return $message;
Kjartan's avatar
Kjartan committed
115
}
Dries's avatar
 
Dries committed
116

Kjartan's avatar
Kjartan committed
117
function taxonomy_del_vocabulary($vid) {
Dries's avatar
   
Dries committed
118
119
  $vocabulary = taxonomy_get_vocabulary($vid);

Dries's avatar
   
Dries committed
120
121
  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
122
123
  while ($term = db_fetch_object($result)) {
    taxonomy_del_term($term->tid);
Dries's avatar
 
Dries committed
124
  }
Dries's avatar
   
Dries committed
125

Dries's avatar
   
Dries committed
126
127
  module_invoke_all("taxonomy", "delete", "vocabulary", $vocabulary);

Dries's avatar
   
Dries committed
128
129
  cache_clear_all();

Dries's avatar
   
Dries committed
130
131
132
133
134
135
136
137
138
139
140
141
142
  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
143
}
Dries's avatar
 
Dries committed
144

Kjartan's avatar
Kjartan committed
145
function taxonomy_form_term($edit = array()) {
146
  $vocabulary_id = isset($edit["vid"]) ? $edit["vid"] : arg(4);
Kjartan's avatar
Kjartan committed
147
  $vocabulary = taxonomy_get_vocabulary($vocabulary_id);
Dries's avatar
   
Dries committed
148

Dries's avatar
   
Dries committed
149
150
  $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
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

170
171
172
173
  if ($vocabulary->relations) {
    $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"]));
  }

Dries's avatar
   
Dries committed
174
  $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
175
  $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
176
  $form .= form_hidden("vid", $vocabulary->vid);
Dries's avatar
   
Dries committed
177
  $form .= form_submit(t("Submit"));
Kjartan's avatar
Kjartan committed
178
179

  if ($edit["tid"]) {
Dries's avatar
   
Dries committed
180
    $form .= form_submit(t("Delete"));
Kjartan's avatar
Kjartan committed
181
    $form .= form_hidden("tid", $edit["tid"]);
Dries's avatar
 
Dries committed
182
183
  }

Kjartan's avatar
Kjartan committed
184
185
  return form($form);
}
Dries's avatar
 
Dries committed
186

Kjartan's avatar
Kjartan committed
187
function taxonomy_save_term($edit) {
Dries's avatar
   
Dries committed
188
  if ($edit["tid"] && $edit["name"]) {
Kjartan's avatar
Kjartan committed
189
    $data = array("name" => $edit["name"], "description" => $edit["description"], "weight" => $edit["weight"]);
Dries's avatar
 
Dries committed
190

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

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

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

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

Dries's avatar
   
Dries committed
239
240
  cache_clear_all();

Dries's avatar
   
Dries committed
241
  return $message;
Kjartan's avatar
Kjartan committed
242
}
Dries's avatar
 
Dries committed
243

Kjartan's avatar
Kjartan committed
244
function taxonomy_del_term($tid) {
Dries's avatar
   
Dries committed
245
246
  $term = taxonomy_get_term($tid);

Dries's avatar
   
Dries committed
247
248
249
250
251
  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
252

Dries's avatar
   
Dries committed
253
  module_invoke_all("taxonomy", "delete", "term", $term);
Dries's avatar
   
Dries committed
254
255
  cache_clear_all();

Dries's avatar
   
Dries committed
256
257
258
259
260
261
262
263
264
265
266
267
268
  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
269
}
Dries's avatar
 
Dries committed
270

Kjartan's avatar
Kjartan committed
271
function taxonomy_overview() {
Dries's avatar
 
Dries committed
272

Dries's avatar
   
Dries committed
273
  $output .= "<h3>" . t("Vocabularies overview") . "</h3>";
Dries's avatar
   
Dries committed
274
275

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

Kjartan's avatar
Kjartan committed
277
278
279
  $vocabularies = taxonomy_get_vocabularies();
  foreach ($vocabularies as $vocabulary) {
    $links = array();
280
    $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
281

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

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

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

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

/*
** API functions
*/

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

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

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

Kjartan's avatar
Kjartan committed
357
358
// 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) {
Dries's avatar
   
Dries committed
359
  $term_name = db_result(db_query("SELECT name FROM term_data WHERE tid = %d", $tid));
Dries's avatar
 
Dries committed
360

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

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

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

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

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

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

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

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

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

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

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

Kjartan's avatar
Kjartan committed
453
  $depth++;
Dries's avatar
   
Dries committed
454

Dries's avatar
   
Dries committed
455
456
457
458
  // 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
459
    $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);
Dries's avatar
   
Dries committed
460
    while ($term = db_fetch_object($result)) {
Dries's avatar
   
Dries committed
461
462
463
      $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
464
465
    }
  }
Dries's avatar
   
Dries committed
466

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

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

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

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

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

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

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

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

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

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

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

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

/*
** service functions
*/

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

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

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

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

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

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

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

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

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

Dries's avatar
   
Dries committed
646
647
648
649
650
651
652
653
654
/*
** 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") {
Dries's avatar
   
Dries committed
655
    $sql = "SELECT DISTINCT(n.nid), n.title, n.type, n.created, n.changed, n.uid, n.static, n.created, 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";
Dries's avatar
   
Dries committed
656
657
658
659
660
661
662
663
664
665
666
667
668
669
    $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 {
Dries's avatar
   
Dries committed
670
    $result = db_query_range($sql, 0, 15);
Dries's avatar
   
Dries committed
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
  }

  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);
}

Dries's avatar
   
Dries committed
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
function taxonomy_nodeapi($node, $op, $arg = 0) {

  switch ($op) {
    case "insert":
      taxonomy_node_save($node->nid, $node->taxonomy);
      break;
    case "update":
      taxonomy_node_save($node->nid, $node->taxonomy);
      break;
    case "delete":
      taxonomy_node_delete($node->nid);
      break;
  }
}

Kjartan's avatar
Kjartan committed
703
function taxonomy_page() {
Dries's avatar
   
Dries committed
704

Dries's avatar
   
Dries committed
705
706
707
708
709
710

  // 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
711

Dries's avatar
   
Dries committed
712
  switch (arg(1)) {
Kjartan's avatar
Kjartan committed
713
    case "feed":
Dries's avatar
   
Dries committed
714
      taxonomy_feed($taxonomy);
Kjartan's avatar
Kjartan committed
715
716
      break;
    default:
Dries's avatar
   
Dries committed
717
      theme("header");
Dries's avatar
   
Dries committed
718
      taxonomy_render_nodes(taxonomy_select_nodes($taxonomy));
Dries's avatar
   
Dries committed
719
      theme("footer");
Dries's avatar
   
Dries committed
720
      break;
Dries's avatar
   
Dries committed
721
  }
Kjartan's avatar
Kjartan committed
722
}
Dries's avatar
   
Dries committed
723

Kjartan's avatar
Kjartan committed
724
/*
Dries's avatar
 
Dries committed
725
726
727
** admin
*/

Kjartan's avatar
Kjartan committed
728
function taxonomy_admin() {
Dries's avatar
   
Dries committed
729
  global $op, $edit;
Kjartan's avatar
Kjartan committed
730
731

  if (user_access("administer taxonomy")) {
Dries's avatar
   
Dries committed
732
733
734
735
    if (empty($op)) {
      $op = arg(2);
    }

Kjartan's avatar
Kjartan committed
736
    switch ($op) {
737
738
739
740
741
      case "add":
        if (arg(3) == "vocabulary")
          $output .= taxonomy_form_vocabulary();
        else if (arg(3) == "term")
          $output .= taxonomy_form_term();
Dries's avatar
   
Dries committed
742
        break;
743
744
745
746
747
      case "edit":
        if (arg(3) == "vocabulary")
          $output .= taxonomy_form_vocabulary(object2array(taxonomy_get_vocabulary(arg(4))));
        else if (arg(3) == "term")
          $output .= taxonomy_form_term(object2array(taxonomy_get_term(arg(4))));
Kjartan's avatar
Kjartan committed
748
749
        break;
      case "preview":
750
        $output .= taxonomy_form(arg(4));
Kjartan's avatar
Kjartan committed
751
752
        break;
      case "help":
753
        $output .= taxonomy_help();
Kjartan's avatar
Kjartan committed
754
        break;
Dries's avatar
   
Dries committed
755
      case t("Delete"):
Dries's avatar
   
Dries committed
756
        if (!$edit["confirm"]) {
Dries's avatar
   
Dries committed
757
          if (arg(3) == "vocabulary") {
758
            $output .= _taxonomy_confirm_del_vocabulary($edit["vid"]);
Dries's avatar
   
Dries committed
759
760
          }
          else {
761
            $output .= _taxonomy_confirm_del_term($edit["tid"]);
Dries's avatar
   
Dries committed
762
763
764
765
766
767
768
          }
          break;
        }
        else {
          $edit["name"] = 0;
          // fall through:
        }
Dries's avatar
   
Dries committed
769
      case t("Submit"):
770
771
        if (arg(3) == "vocabulary") {
          $output .= status(taxonomy_save_vocabulary($edit));
Kjartan's avatar
Kjartan committed
772
773
        }
        else {
Dries's avatar
   
Dries committed
774
          $output .= status(taxonomy_save_term($edit));
Dries's avatar
   
Dries committed
775
776
          if (!$edit["tid"]) {
            // if INSERT show form again
777
            $output .= taxonomy_form_term();
Dries's avatar
   
Dries committed
778
779
780
            break;
          }
          // else (UPDATE or DELETE) fall through
Kjartan's avatar
Kjartan committed
781
        }
Kjartan's avatar
Kjartan committed
782
783
        // fall through:
      default:
784
        $output .= taxonomy_overview();
Kjartan's avatar
Kjartan committed
785
786
787
    }
  }
  else {
788
    $output .= message_access();
Kjartan's avatar
Kjartan committed
789
  }
Dries's avatar
   
Dries committed
790

791
  return $output;
Kjartan's avatar
Kjartan committed
792
793
794
}

function taxonomy_help() {
795
?>
Dries's avatar
   
Dries committed
796
  <h3>Background</h3>
Dries's avatar
   
Dries committed
797
  <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
798
799

  <h3>An example taxonomy: food</h3>
Dries's avatar
   
Dries committed
800
801
802
803
804
  <p>Dairy<br />
  --Milk<br />
  Drink<br />
  --Alchohol<br />
  --Pop<br />
Kjartan's avatar
Kjartan committed
805
  --Milk<br />
Dries's avatar
   
Dries committed
806
807
808
809
810
  Meat<br />
  --Beef<br />
  --Chicken<br />
  --Lamb<br />
  Spices<br />
Kjartan's avatar
Kjartan committed
811
  --Sugar</p>
Dries's avatar
   
Dries committed
812
813
814
815
816
817
  <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
818
  <h3>Vocabularies</h3>
Dries's avatar
   
Dries committed
819
  <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
820
821

  <h4>Setting up a vocabulary</h4>
Dries's avatar
   
Dries committed
822
823
  <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
824
  <p><i>Vocabulary name</i><br />Required. The name for this vocabulary. Example: <i>Dairy</i>.<br />
Kjartan's avatar
Kjartan committed
825
  <br />
Dries's avatar
   
Dries committed
826
  <i>Description</i><br />Optional. Description of the vocabulary, can be used by modules and feeds.<br />
Kjartan's avatar
Kjartan committed
827
  <br />
Dries's avatar
   
Dries committed
828
  <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
829
  <br />
Dries's avatar
   
Dries committed
830
  <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
831
  <br />
Dries's avatar
   
Dries committed
832
  <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
833
  <br />
Dries's avatar
Dries committed
834
  <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
835

Kjartan's avatar
Kjartan committed
836
  <h4>Adding terms to a vocabulary</h4>
Dries's avatar
   
Dries committed
837
838
<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
839
  <p><i>Term name</i><br />Required. The name for this term. Example: <i>Milk</i><br />
Kjartan's avatar
Kjartan committed
840
  <br />
Dries's avatar
   
Dries committed
841
  <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
842
  <br />
Dries's avatar
   
Dries committed
843
  <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
844
  <br />
Dries's avatar
Dries committed
845
  <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
846
  <h3>Displaying nodes organized by term(s)</h3>
Dries's avatar
   
Dries committed
847
  <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 url("taxonomy/page/or/1,2"); ?>"><?php print url("taxonomy/page/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
848
849

  <h3>RSS feeds</h3>
Dries's avatar
   
Dries committed
850
  <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 url("node/feed/or/1,2"); ?>"><?php print url("node/feed/or/1,2"); ?></a>.</p>
Dries's avatar
   
Dries committed
851
 <?php
Kjartan's avatar
Kjartan committed
852
}
Dries's avatar
   
Dries committed
853
?>