taxonomy.module 33.6 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
function taxonomy_save_vocabulary($edit) {
Dries's avatar
   
Dries committed
96
97
98
99
100
  if (!$edit["types"]) {
    $edit["types"] = array();
  }

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

  cache_clear_all();
Dries's avatar
   
Dries committed
117
118

  return $message;
Kjartan's avatar
Kjartan committed
119
}
Dries's avatar
   
Dries committed
120

Kjartan's avatar
Kjartan committed
121
function taxonomy_del_vocabulary($vid) {
Dries's avatar
   
Dries committed
122
123
  $vocabulary = taxonomy_get_vocabulary($vid);

Dries's avatar
   
Dries committed
124
125
  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
126
127
  while ($term = db_fetch_object($result)) {
    taxonomy_del_term($term->tid);
Dries's avatar
   
Dries committed
128
  }
Dries's avatar
   
Dries committed
129

Dries's avatar
   
Dries committed
130
131
  module_invoke_all("taxonomy", "delete", "vocabulary", $vocabulary);

Dries's avatar
   
Dries committed
132
133
  cache_clear_all();

Dries's avatar
   
Dries committed
134
135
136
137
138
139
140
141
142
143
144
145
146
  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
147
}
Dries's avatar
   
Dries committed
148

Kjartan's avatar
Kjartan committed
149
function taxonomy_form_term($edit = array()) {
150
  $vocabulary_id = isset($edit["vid"]) ? $edit["vid"] : arg(4);
Kjartan's avatar
Kjartan committed
151
  $vocabulary = taxonomy_get_vocabulary($vocabulary_id);
Dries's avatar
   
Dries committed
152

Dries's avatar
   
Dries committed
153
154
  $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
155

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

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

Kjartan's avatar
Kjartan committed
166
    if ($vocabulary->hierarchy == 1) {
Dries's avatar
   
Dries committed
167
      $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
168
    }
Kjartan's avatar
Kjartan committed
169
    elseif ($vocabulary->hierarchy == 2) {
Dries's avatar
   
Dries committed
170
      $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
171
    }
Kjartan's avatar
Kjartan committed
172
  }
Dries's avatar
   
Dries committed
173

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

  if ($edit["tid"]) {
Dries's avatar
   
Dries committed
184
    $form .= form_submit(t("Delete"));
Kjartan's avatar
Kjartan committed
185
    $form .= form_hidden("tid", $edit["tid"]);
Dries's avatar
   
Dries committed
186
187
  }

Kjartan's avatar
Kjartan committed
188
189
  return form($form);
}
Dries's avatar
   
Dries committed
190

Kjartan's avatar
Kjartan committed
191
function taxonomy_save_term($edit) {
Dries's avatar
   
Dries committed
192
  if ($edit["tid"] && $edit["name"]) {
Kjartan's avatar
Kjartan committed
193
    $data = array("name" => $edit["name"], "description" => $edit["description"], "weight" => $edit["weight"]);
Dries's avatar
   
Dries committed
194

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

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

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

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

Dries's avatar
   
Dries committed
243
244
  cache_clear_all();

Dries's avatar
   
Dries committed
245
  return $message;
Kjartan's avatar
Kjartan committed
246
}
Dries's avatar
   
Dries committed
247

Kjartan's avatar
Kjartan committed
248
function taxonomy_del_term($tid) {
Dries's avatar
   
Dries committed
249
250
  $term = taxonomy_get_term($tid);

Dries's avatar
   
Dries committed
251
252
253
254
255
  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
256

Dries's avatar
   
Dries committed
257
  module_invoke_all("taxonomy", "delete", "term", $term);
Dries's avatar
   
Dries committed
258
259
  cache_clear_all();

Dries's avatar
   
Dries committed
260
261
262
263
264
265
266
267
268
269
270
271
272
  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
273
}
Dries's avatar
   
Dries committed
274

Kjartan's avatar
Kjartan committed
275
function taxonomy_overview() {
Dries's avatar
   
Dries committed
276

Dries's avatar
   
Dries committed
277
  $output .= "<h3>" . t("Vocabularies overview") . "</h3>";
Dries's avatar
   
Dries committed
278
279

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

Kjartan's avatar
Kjartan committed
281
282
283
  $vocabularies = taxonomy_get_vocabularies();
  foreach ($vocabularies as $vocabulary) {
    $links = array();
284
    $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
285

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

Dries's avatar
   
Dries committed
296
  return table($header, $rows);
Kjartan's avatar
Kjartan committed
297
298
299
300
301
302
303
304
305
306
}

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

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

/*
** API functions
*/

Kjartan's avatar
Kjartan committed
325
326
327
328
329
330
331
332
333
334
335
// 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
336
  }
Kjartan's avatar
Kjartan committed
337
338
  return $vocabularies;
}
Dries's avatar
   
Dries committed
339

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

Kjartan's avatar
Kjartan committed
354
355
356
  $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
357
  }
Kjartan's avatar
Kjartan committed
358
359
  return $result ? $result : array();
}
Dries's avatar
   
Dries committed
360

Kjartan's avatar
Kjartan committed
361
362
// 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
363
  $term_name = db_result(db_query("SELECT name FROM term_data WHERE tid = %d", $tid));
Dries's avatar
   
Dries committed
364

Dries's avatar
   
Dries committed
365
  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
366
367
368
369
}

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

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

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

Kjartan's avatar
Kjartan committed
392
393
394
// save terms of a node
function taxonomy_node_save($nid, $terms) {
  taxonomy_node_delete($nid);
Dries's avatar
   
Dries committed
395

Kjartan's avatar
Kjartan committed
396
  if ($terms) {
Dries's avatar
   
Dries committed
397
    foreach ($terms as $term) {
Dries's avatar
   
Dries committed
398
      db_query("INSERT INTO term_node (nid, tid) VALUES (%d, %d)", $nid, $term);
Dries's avatar
   
Dries committed
399
400
    }
  }
Kjartan's avatar
Kjartan committed
401
}
Dries's avatar
   
Dries committed
402

Kjartan's avatar
Kjartan committed
403
404
// clean up terms
function taxonomy_node_delete($nid) {
Dries's avatar
   
Dries committed
405
  db_query("DELETE FROM term_node WHERE nid = %d", $nid);
Kjartan's avatar
Kjartan committed
406
}
Dries's avatar
   
Dries committed
407

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

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

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

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

Kjartan's avatar
Kjartan committed
457
  $depth++;
Dries's avatar
   
Dries committed
458

Dries's avatar
   
Dries committed
459
460
461
462
  // 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
463
    $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
464
    while ($term = db_fetch_object($result)) {
Dries's avatar
   
Dries committed
465
466
467
      $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
468
469
    }
  }
Dries's avatar
   
Dries committed
470

Dries's avatar
   
Dries committed
471
472
473
474
475
476
  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
477

Dries's avatar
   
Dries committed
478
      $tree = array_merge($tree, taxonomy_get_tree($vocabulary_id, $child, $depth));
Dries's avatar
   
Dries committed
479
    }
Kjartan's avatar
Kjartan committed
480
  }
Dries's avatar
   
Dries committed
481

Dries's avatar
   
Dries committed
482
  return $tree ? $tree : array();
Kjartan's avatar
Kjartan committed
483
}
Dries's avatar
   
Dries committed
484

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

Kjartan's avatar
Kjartan committed
499
500
501
502
// 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
503

Kjartan's avatar
Kjartan committed
504
// given a term id, count number of nodes in it
Dries's avatar
   
Dries committed
505
function taxonomy_term_count_nodes($tid, $type = 0) {
Kjartan's avatar
Kjartan committed
506
  static $count;
Dries's avatar
   
Dries committed
507

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

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

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

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

Dries's avatar
   
Dries committed
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
574
575
576
577
/**
 * 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
578
579
function taxonomy_get_vocabulary($vid) {
  // simple cache using a static var?
Dries's avatar
   
Dries committed
580
  return db_fetch_object(db_query("SELECT * FROM vocabulary WHERE vid = %d", $vid));
Kjartan's avatar
Kjartan committed
581
}
Dries's avatar
   
Dries committed
582

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

/*
** service functions
*/

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

Kjartan's avatar
Kjartan committed
595
  if ($blank) {
Dries's avatar
   
Dries committed
596
    $options[] = array("tid" => 0, "name" => $blank);
Kjartan's avatar
Kjartan committed
597
  }
Dries's avatar
   
Dries committed
598

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

Kjartan's avatar
Kjartan committed
611
  if (count($options) > 0) {
Dries's avatar
   
Dries committed
612
613
    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
614
    }
Dries's avatar
   
Dries committed
615

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

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

Kjartan's avatar
Kjartan committed
622
623
624
function _taxonomy_depth($depth, $graphic = '--') {
  for ($n = 0; $n < $depth; $n++) {
    $result .= $graphic;
Dries's avatar
   
Dries committed
625
  }
Kjartan's avatar
Kjartan committed
626
627
  return $result;
}
Dries's avatar
   
Dries committed
628

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

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

Dries's avatar
   
Dries committed
650
651
652
653
654
655
656
657
658
/*
** 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
659
    $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
660
661
662
663
664
665
666
667
668
669
670
671
672
673
    $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
674
    $result = db_query_range($sql, 0, 15);
Dries's avatar
   
Dries committed
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
  }

  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
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
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
707
function taxonomy_page() {
Dries's avatar
   
Dries committed
708

Dries's avatar
   
Dries committed
709
710
711
712
713
714

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

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

Kjartan's avatar
Kjartan committed
728
/*
Dries's avatar
   
Dries committed
729
730
731
** admin
*/

Kjartan's avatar
Kjartan committed
732
function taxonomy_admin() {
Dries's avatar
   
Dries committed
733
  global $op, $edit;
Kjartan's avatar
Kjartan committed
734
735

  if (user_access("administer taxonomy")) {
Dries's avatar
   
Dries committed
736
737
738
739
    if (empty($op)) {
      $op = arg(2);
    }

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

795
  return $output;
Kjartan's avatar
Kjartan committed
796
797
798
}

function taxonomy_help() {
799
?>
Dries's avatar
   
Dries committed
800
  <h3>Background</h3>
Dries's avatar
   
Dries committed
801
  <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
802
803

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

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

Kjartan's avatar
Kjartan committed
840
  <h4>Adding terms to a vocabulary</h4>
Dries's avatar
   
Dries committed
841
842
<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
843
  <p><i>Term name</i><br />Required. The name for this term. Example: <i>Milk</i><br />
Kjartan's avatar
Kjartan committed
844
  <br />
Dries's avatar
   
Dries committed
845
  <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
846
  <br />
Dries's avatar
   
Dries committed
847
  <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
848
  <br />
Dries's avatar
Dries committed
849
  <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
850
  <h3>Displaying nodes organized by term(s)</h3>
Dries's avatar
   
Dries committed
851
  <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
852
853

  <h3>RSS feeds</h3>
Dries's avatar
   
Dries committed
854
  <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
855
 <?php
Kjartan's avatar
Kjartan committed
856
}
Dries's avatar
   
Dries committed
857
?>