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

Dries Buytaert's avatar
   
Dries Buytaert committed
4
5
function taxonomy_feed($taxonomy) {
  global $id, $type;
Dries Buytaert's avatar
   
Dries Buytaert committed
6

Dries Buytaert's avatar
   
Dries Buytaert committed
7
  if ($type == 'voc') {
Dries Buytaert's avatar
   
Dries Buytaert committed
8
    //TODO - vocabulary feed.
Kjartan Mannes's avatar
Kjartan Mannes committed
9
10
  }
  else {
Dries Buytaert's avatar
   
Dries Buytaert committed
11
12
    $result = taxonomy_select_nodes($taxonomy, 0);
    $term = taxonomy_get_term($taxonomy->tids[0]);
Dries Buytaert's avatar
   
Dries Buytaert committed
13
14
15
    $channel['link'] = url("taxonomy/view/$taxonomy->operator/$taxonomy->str_tids", NULL, NULL, TRUE);
    $channel['title'] = variable_get('site_name', 'drupal') .' - '. $term->name;
    $channel['description'] = $term->description;
Kjartan Mannes's avatar
Kjartan Mannes committed
16
    node_feed($result, $channel);
Dries Buytaert's avatar
   
Dries Buytaert committed
17
  }
Kjartan Mannes's avatar
Kjartan Mannes committed
18
}
Dries Buytaert's avatar
   
Dries Buytaert committed
19

Dries Buytaert's avatar
   
Dries Buytaert committed
20
21
22
/**
 * Implementation of hook_perm().
 */
Kjartan Mannes's avatar
Kjartan Mannes committed
23
function taxonomy_perm() {
Dries Buytaert's avatar
   
Dries Buytaert committed
24
  return array('administer taxonomy');
Kjartan Mannes's avatar
Kjartan Mannes committed
25
}
Dries Buytaert's avatar
 
Dries Buytaert committed
26

Dries Buytaert's avatar
   
Dries Buytaert committed
27
28
29
30
31
32
33
34
35
36
37
/**
 * Implementation of hook_link().
 *
 * This hook is extended with $type = 'taxonomy terms' to allow themes to
 * print lists of terms associated with a node. Themes can print taxonomy
 * links with:
 *
 * if (module_exist('taxonomy')) {
 *   $this->links(taxonomy_link('taxonomy terms', $node));
 * }
 */
Dries Buytaert's avatar
   
Dries Buytaert committed
38
function taxonomy_link($type, $node = NULL) {
Dries Buytaert's avatar
   
Dries Buytaert committed
39
  if ($type == 'taxonomy terms' && $node != NULL) {
Kjartan Mannes's avatar
   
Kjartan Mannes committed
40
    $links = array();
Dries Buytaert's avatar
   
Dries Buytaert committed
41
    if (array_key_exists('taxonomy', $node)) {
Dries Buytaert's avatar
   
Dries Buytaert committed
42
43
      foreach ($node->taxonomy as $tid) {
        $term = taxonomy_get_term($tid);
44
        $links[] = l($term->name, "taxonomy/page/or/$term->tid", $term->description ? array ('title' => $term->description) : array());
Dries Buytaert's avatar
   
Dries Buytaert committed
45
46
47
48
49
      }
    }
    else {
      $links = array();
      foreach (taxonomy_node_get_terms($node->nid) as $term) {
50
        $links[] = l($term->name, "taxonomy/page/or/$term->tid", $term->description ? array ('title' => $term->description) : array());
Dries Buytaert's avatar
   
Dries Buytaert committed
51
      }
Dries Buytaert's avatar
   
Dries Buytaert committed
52
53
54
55

    }
    return $links;
  }
Kjartan Mannes's avatar
Kjartan Mannes committed
56
57
}

Dries Buytaert's avatar
   
Dries Buytaert committed
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
/**
 * Implementation of hook_menu().
 */
function taxonomy_menu() {
  $items = array();
  $items[] = array('path' => 'admin/taxonomy', 'title' => t('categories'),
    'callback' => 'taxonomy_admin',
    'access' => user_access('administer taxonomy'));
  $items[] = array('path' => 'admin/taxonomy/add/vocabulary', 'title' => t('add vocabulary'),
    'callback' => 'taxonomy_admin',
    'access' => user_access('administer taxonomy'),
    'type' => MENU_LOCAL_TASK);
  $items[] = array('path' => 'taxonomy', 'title' => t('taxonomy'),
    'callback' => 'taxonomy_page',
    'access' => user_access('access content'),
    'type' => MENU_CALLBACK);
  return $items;
}
Dries Buytaert's avatar
 
Dries Buytaert committed
76

77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
/**
 * Implementation of hook_block().
 *
 * Generates a block with all categories.
 */
function taxonomy_block($op = 'list', $delta = 0) {
  if ($op == 'list') {
    $blocks[0]['info'] = t('Categories');
    return $blocks;
  }
  else if (user_access('access content')) {
    $result = db_query("SELECT d.tid, d.name, MAX(n.created) AS updated, COUNT(*) AS count FROM {term_data} d INNER JOIN {term_node} USING (tid) INNER JOIN {node} n USING (nid) WHERE n.status = 1 GROUP BY d.tid ORDER BY updated DESC, d.name");
    $items = array();
    while ($category = db_fetch_object($result)) {
      $items[] = l("$category->name ($category->count)", "taxonomy/page/or/$category->tid") .'<br />'. format_interval(time() - $category->updated) .' '. t('ago');
    }

    $block['subject'] = t('Categories');
    $block['content'] = theme('item_list', $items);
    return $block;
  }
}

Kjartan Mannes's avatar
Kjartan Mannes committed
100
function taxonomy_form_vocabulary($edit = array()) {
Dries Buytaert's avatar
   
Dries Buytaert committed
101
  foreach (node_list() as $type) {
Dries Buytaert's avatar
   
Dries Buytaert committed
102
    $nodetypes[$type] = node_invoke($type, 'node_name');
Kjartan Mannes's avatar
Kjartan Mannes committed
103
  }
Dries Buytaert's avatar
   
Dries Buytaert committed
104

Dries Buytaert's avatar
   
Dries Buytaert committed
105
106
107
108
109
110
111
  $form .= form_textfield(t('Vocabulary name'), 'name', $edit['name'], 50, 64, t('The name for this vocabulary.  Example: "Topic".'), NULL, TRUE);
  $form .= form_textarea(t('Description'), 'description', $edit['description'], 60, 5, t('Description of the vocabulary; can be used by modules.'));
  $form .= form_textfield(t('Help text'), 'help', $edit['help'], 50, 255, t('Instructions to present to the user when choosing a term.'));
  $form .= form_checkboxes(t('Types'), 'nodes', explode(',', $edit['nodes']), $nodetypes, t('A list of node types you want to associate with this vocabulary.'), NULL, TRUE);
  $form .= form_checkbox(t('Related terms'), 'relations', 1, $edit['relations'], t('Allows <a href="%help-url">related terms</a> in this vocabulary.', array('%help-url' => url('admin/taxonomy/help', NULL, NULL, 'related-terms'))));
  $form .= form_radios(t('Hierarchy'), 'hierarchy', $edit['hierarchy'], array(t('Disabled'), t('Single'), t('Multiple')), t('Allows <a href="%help-url">a tree-like hierarchy</a> between terms of this vocabulary.', array('%help-url' => url('admin/taxonomy/help', NULL, NULL, 'hierarchy'))));
  $form .= form_checkbox(t('Multiple select'), 'multiple', 1, $edit['multiple'], t('Allows nodes to have more than one term in this vocabulary.'));
Dries Buytaert's avatar
   
Dries Buytaert committed
112
  $form .= form_checkbox(t('Required'), 'required', 1, $edit['required'], t('If enabled, every node <strong>must</strong> have at least one term in this vocabulary.'));
Dries Buytaert's avatar
   
Dries Buytaert committed
113
  $form .= form_weight(t('Weight'), 'weight', $edit['weight'], 10, t('In listings, the heavier vocabularies will sink and the lighter vocabularies will be positioned nearer the top.'));
Dries Buytaert's avatar
   
Dries Buytaert committed
114
  $form .= form_submit(t('Submit'));
Dries Buytaert's avatar
 
Dries Buytaert committed
115

Dries Buytaert's avatar
   
Dries Buytaert committed
116
117
118
  if ($edit['vid']) {
    $form .= form_submit(t('Delete'));
    $form .= form_hidden('vid', $edit['vid']);
Dries Buytaert's avatar
 
Dries Buytaert committed
119
120
  }

Kjartan Mannes's avatar
Kjartan Mannes committed
121
122
  return form($form);
}
Kjartan Mannes's avatar
Kjartan Mannes committed
123

Kjartan Mannes's avatar
Kjartan Mannes committed
124
function taxonomy_save_vocabulary($edit) {
Dries Buytaert's avatar
   
Dries Buytaert committed
125
126
  if (!$edit['nodes']) {
    $edit['nodes'] = array();
Dries Buytaert's avatar
   
Dries Buytaert committed
127
128
  }

Dries Buytaert's avatar
   
Dries Buytaert committed
129
130
131
132
133
  $data = array('name' => $edit['name'], 'nodes' => implode(',', $edit['nodes']), 'description' => $edit['description'], 'help' => $edit['help'], 'multiple' => $edit['multiple'], 'required' => $edit['required'], 'hierarchy' => $edit['hierarchy'], 'relations' => $edit['relations'], 'weight' => $edit['weight']);
  if ($edit['vid'] && $edit['name']) {
    db_query('UPDATE {vocabulary} SET '. _prepare_update($data) .' WHERE vid = %d', $edit['vid']);
    module_invoke_all('taxonomy', 'update', 'vocabulary', $edit);
    $message = t('updated vocabulary "%name".', array('%name' => $edit['name']));
Dries Buytaert's avatar
 
Dries Buytaert committed
134
  }
Dries Buytaert's avatar
   
Dries Buytaert committed
135
136
  else if ($edit['vid']) {
    $message = taxonomy_del_vocabulary($edit['vid']);
Kjartan Mannes's avatar
Kjartan Mannes committed
137
138
  }
  else {
Dries Buytaert's avatar
   
Dries Buytaert committed
139
140
141
142
    $data['vid'] = $edit['vid'] = db_next_id('{vocabulary}_vid');
    db_query('INSERT INTO {vocabulary} '. _prepare_insert($data, 1) .' VALUES '. _prepare_insert($data, 2));
    module_invoke_all('taxonomy', 'insert', 'vocabulary', $edit);
    $message = t('created new vocabulary "%name".', array('%name' => $edit['name']));
Kjartan Mannes's avatar
Kjartan Mannes committed
143
  }
Dries Buytaert's avatar
   
Dries Buytaert committed
144
145

  cache_clear_all();
Dries Buytaert's avatar
   
Dries Buytaert committed
146

Dries Buytaert's avatar
   
Dries Buytaert committed
147
148
  drupal_set_message($message);
  return $edit;
Kjartan Mannes's avatar
Kjartan Mannes committed
149
}
Dries Buytaert's avatar
 
Dries Buytaert committed
150

Kjartan Mannes's avatar
Kjartan Mannes committed
151
function taxonomy_del_vocabulary($vid) {
Dries Buytaert's avatar
   
Dries Buytaert committed
152
153
  $vocabulary = taxonomy_get_vocabulary($vid);

Dries Buytaert's avatar
   
Dries Buytaert committed
154
155
  db_query('DELETE FROM {vocabulary} WHERE vid = %d', $vid);
  $result = db_query('SELECT tid FROM {term_data} WHERE vid = %d', $vid);
Kjartan Mannes's avatar
Kjartan Mannes committed
156
157
  while ($term = db_fetch_object($result)) {
    taxonomy_del_term($term->tid);
Dries Buytaert's avatar
 
Dries Buytaert committed
158
  }
Dries Buytaert's avatar
   
Dries Buytaert committed
159

Dries Buytaert's avatar
   
Dries Buytaert committed
160
  module_invoke_all('taxonomy', 'delete', 'vocabulary', $vocabulary);
Dries Buytaert's avatar
   
Dries Buytaert committed
161

Dries Buytaert's avatar
   
Dries Buytaert committed
162
163
  cache_clear_all();

Dries Buytaert's avatar
   
Dries Buytaert committed
164
  return t('deleted vocabulary "%name".', array('%name' => $vocabulary->name));
Dries Buytaert's avatar
   
Dries Buytaert committed
165
166
167
168
169
}

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

Dries Buytaert's avatar
   
Dries Buytaert committed
170
171
172
173
174
  $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'));
Dries Buytaert's avatar
   
Dries Buytaert committed
175

Dries Buytaert's avatar
   
Dries Buytaert committed
176
  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 Mannes's avatar
Kjartan Mannes committed
177
}
Dries Buytaert's avatar
 
Dries Buytaert committed
178

Kjartan Mannes's avatar
Kjartan Mannes committed
179
function taxonomy_form_term($edit = array()) {
Dries Buytaert's avatar
   
Dries Buytaert committed
180
  $vocabulary_id = isset($edit['vid']) ? $edit['vid'] : arg(4);
Kjartan Mannes's avatar
Kjartan Mannes committed
181
  $vocabulary = taxonomy_get_vocabulary($vocabulary_id);
Dries Buytaert's avatar
   
Dries Buytaert committed
182

Dries Buytaert's avatar
   
Dries Buytaert committed
183
184
  $form = form_textfield(t('Term name'), 'name', $edit['name'], 50, 64, t('The name for this term.  Example: "Linux".'), NULL, TRUE);
  $form .= form_textarea(t('Description'), 'description', $edit['description'], 60, 5, t('A description of the term.'));
Dries Buytaert's avatar
 
Dries Buytaert committed
185

Kjartan Mannes's avatar
Kjartan Mannes committed
186
  if ($vocabulary->hierarchy) {
Dries Buytaert's avatar
   
Dries Buytaert committed
187
188
    $parent = array_keys(taxonomy_get_parents($edit['tid']));
    $children = taxonomy_get_tree($vocabulary_id, $edit['tid']);
Dries Buytaert's avatar
   
Dries Buytaert committed
189

Dries Buytaert's avatar
   
Dries Buytaert committed
190
    // A term can't be the child of itself, nor of its children.
Dries Buytaert's avatar
   
Dries Buytaert committed
191
192
193
    foreach ($children as $child) {
      $exclude[] = $child->tid;
    }
Dries Buytaert's avatar
   
Dries Buytaert committed
194
    $exclude[] = $edit['tid'];
Dries Buytaert's avatar
   
Dries Buytaert committed
195

Kjartan Mannes's avatar
Kjartan Mannes committed
196
    if ($vocabulary->hierarchy == 1) {
Dries Buytaert's avatar
   
Dries Buytaert committed
197
      $form .= _taxonomy_term_select(t('Parent'), 'parent', $parent, $vocabulary_id, l(t('Parent term'), 'admin/taxonomy/help', NULL, NULL, 'parent') .'.', 0, '<'. t('root') .'>', $exclude);
Dries Buytaert's avatar
 
Dries Buytaert committed
198
    }
Kjartan Mannes's avatar
Kjartan Mannes committed
199
    elseif ($vocabulary->hierarchy == 2) {
Dries Buytaert's avatar
   
Dries Buytaert committed
200
      $form .= _taxonomy_term_select(t('Parents'), 'parent', $parent, $vocabulary_id, l(t('Parent terms'), 'admin/taxonomy/help', NULL, NULL, 'parent') .'.', 1, '<'. t('root') .'>', $exclude);
Dries Buytaert's avatar
 
Dries Buytaert committed
201
    }
Kjartan Mannes's avatar
Kjartan Mannes committed
202
  }
Dries Buytaert's avatar
 
Dries Buytaert committed
203

204
  if ($vocabulary->relations) {
Dries Buytaert's avatar
   
Dries Buytaert committed
205
    $form .= _taxonomy_term_select(t('Related terms'), 'relations', array_keys(taxonomy_get_related($edit['tid'])), $vocabulary_id, NULL, 1, '<'. t('none') .'>', array($edit['tid']));
206
207
  }

Dries Buytaert's avatar
   
Dries Buytaert committed
208
209
  $form .= form_textarea(t('Synonyms'), 'synonyms', implode("\n", taxonomy_get_synonyms($edit['tid'])), 30, 5, t('<a href="%help-url">Synonyms</a> of this term, one synonym per line.', array('%help-url' => url('admin/taxonomy/help', NULL, NULL, 'synonyms'))));
  $form .= form_weight(t('Weight'), 'weight', $edit['weight'], 10, t('In listings, the heavier terms will sink and the lighter terms will be positioned nearer the top.'));
Dries Buytaert's avatar
   
Dries Buytaert committed
210
211
  $form .= form_hidden('vid', $vocabulary->vid);
  $form .= form_submit(t('Submit'));
Kjartan Mannes's avatar
Kjartan Mannes committed
212

Dries Buytaert's avatar
   
Dries Buytaert committed
213
214
215
  if ($edit['tid']) {
    $form .= form_submit(t('Delete'));
    $form .= form_hidden('tid', $edit['tid']);
Dries Buytaert's avatar
 
Dries Buytaert committed
216
217
  }

Kjartan Mannes's avatar
Kjartan Mannes committed
218
219
  return form($form);
}
Dries Buytaert's avatar
 
Dries Buytaert committed
220

Kjartan Mannes's avatar
Kjartan Mannes committed
221
function taxonomy_save_term($edit) {
Dries Buytaert's avatar
   
Dries Buytaert committed
222
223
  if ($edit['tid'] && $edit['name']) {
    $data = array('name' => $edit['name'], 'description' => $edit['description'], 'weight' => $edit['weight']);
Dries Buytaert's avatar
 
Dries Buytaert committed
224

Dries Buytaert's avatar
   
Dries Buytaert committed
225
226
227
    db_query('UPDATE {term_data} SET '. _prepare_update($data) .' WHERE tid = %d', $edit['tid']);
    module_invoke_all('taxonomy', 'update', 'term', $edit);
    $message = t('the term "%a" has been updated.', array('%a' => $edit['name']));
Kjartan Mannes's avatar
Kjartan Mannes committed
228
  }
Dries Buytaert's avatar
   
Dries Buytaert committed
229
230
  else if ($edit['tid']) {
    return taxonomy_del_term($edit['tid']);
Kjartan Mannes's avatar
Kjartan Mannes committed
231
232
  }
  else {
Dries Buytaert's avatar
   
Dries Buytaert committed
233
234
235
236
237
    $edit['tid'] = db_next_id('{term_data}_tid');
    $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));
    module_invoke_all('taxonomy', 'insert', 'term', $edit);
    $message = t('created new term "%name".', array('%name' => $edit['name']));
Kjartan Mannes's avatar
Kjartan Mannes committed
238
  }
Dries Buytaert's avatar
 
Dries Buytaert committed
239

Dries Buytaert's avatar
   
Dries Buytaert committed
240
241
242
  db_query('DELETE FROM {term_relation} WHERE tid1 = %d OR tid2 = %d', $edit['tid'], $edit['tid']);
  if ($edit['relations']) {
    foreach ($edit['relations'] as $related_id) {
Kjartan Mannes's avatar
Kjartan Mannes committed
243
      if ($related_id != 0) {
Dries Buytaert's avatar
   
Dries Buytaert committed
244
        db_query('INSERT INTO {term_relation} (tid1, tid2) VALUES (%d, %d)', $edit['tid'], $related_id);
Dries Buytaert's avatar
 
Dries Buytaert committed
245
      }
Kjartan Mannes's avatar
Kjartan Mannes committed
246
    }
Kjartan Mannes's avatar
Kjartan Mannes committed
247
  }
Dries Buytaert's avatar
 
Dries Buytaert committed
248

Dries Buytaert's avatar
   
Dries Buytaert committed
249
250
251
  db_query('DELETE FROM {term_hierarchy} WHERE tid = %d', $edit['tid']);
  if (!isset($edit['parent'])) {
    $edit['parent'] = 0;
Kjartan Mannes's avatar
Kjartan Mannes committed
252
  }
Dries Buytaert's avatar
   
Dries Buytaert committed
253
254
255
  if (is_array($edit['parent'])) {
    foreach ($edit['parent'] as $parent) {
      db_query('INSERT INTO {term_hierarchy} (tid, parent) VALUES (%d, %d)', $edit['tid'], $parent);
Dries Buytaert's avatar
 
Dries Buytaert committed
256
    }
Kjartan Mannes's avatar
Kjartan Mannes committed
257
258
  }
  else {
Dries Buytaert's avatar
   
Dries Buytaert committed
259
    db_query('INSERT INTO {term_hierarchy} (tid, parent) VALUES (%d, %d)', $edit['tid'], $edit['parent'][0]);
Dries Buytaert's avatar
 
Dries Buytaert committed
260
261
  }

Dries Buytaert's avatar
   
Dries Buytaert committed
262
263
264
  db_query('DELETE FROM {term_synonym} WHERE tid = %d', $edit['tid']);
  if ($edit['synonyms']) {
    foreach (explode ("\n", str_replace("\r", '', $edit['synonyms'])) as $synonym) {
Dries Buytaert's avatar
   
Dries Buytaert committed
265
      if ($synonym) {
Dries Buytaert's avatar
   
Dries Buytaert committed
266
        db_query("INSERT INTO {term_synonym} (tid, name) VALUES (%d, '%s')", $edit['tid'], chop($synonym));
Dries Buytaert's avatar
   
Dries Buytaert committed
267
      }
Kjartan Mannes's avatar
Kjartan Mannes committed
268
    }
Dries Buytaert's avatar
 
Dries Buytaert committed
269
  }
Dries Buytaert's avatar
   
Dries Buytaert committed
270

Dries Buytaert's avatar
   
Dries Buytaert committed
271
272
  cache_clear_all();

Dries Buytaert's avatar
   
Dries Buytaert committed
273
  drupal_set_message($message);
Dries Buytaert's avatar
   
Dries Buytaert committed
274
  return $edit;
Kjartan Mannes's avatar
Kjartan Mannes committed
275
}
Dries Buytaert's avatar
 
Dries Buytaert committed
276

Kjartan Mannes's avatar
Kjartan Mannes committed
277
function taxonomy_del_term($tid) {
Dries Buytaert's avatar
   
Dries Buytaert committed
278
279
  $term = taxonomy_get_term($tid);

Dries Buytaert's avatar
   
Dries Buytaert committed
280
281
282
283
284
  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 Buytaert's avatar
   
Dries Buytaert committed
285

Dries Buytaert's avatar
   
Dries Buytaert committed
286
  module_invoke_all('taxonomy', 'delete', 'term', $term);
Dries Buytaert's avatar
   
Dries Buytaert committed
287

Dries Buytaert's avatar
   
Dries Buytaert committed
288
289
  cache_clear_all();

Dries Buytaert's avatar
   
Dries Buytaert committed
290
  return t('deleted term "%name".', array('%name' => $term->name));
Dries Buytaert's avatar
   
Dries Buytaert committed
291
292
293
294
295
}

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

Dries Buytaert's avatar
   
Dries Buytaert committed
296
297
298
299
300
  $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'));
Dries Buytaert's avatar
   
Dries Buytaert committed
301

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

Dries Buytaert's avatar
   
Dries Buytaert committed
305
306
307
/**
 * Generate a tabular listing of administrative functions for vocabularies.
 */
Kjartan Mannes's avatar
Kjartan Mannes committed
308
function taxonomy_overview() {
Dries Buytaert's avatar
   
Dries Buytaert committed
309
  $header = array(t('name'), t('node types'), array('data' => t('operations'), 'colspan' => 3));
Dries Buytaert's avatar
   
Dries Buytaert committed
310

Kjartan Mannes's avatar
Kjartan Mannes committed
311
  $vocabularies = taxonomy_get_vocabularies();
Dries Buytaert's avatar
   
Dries Buytaert committed
312

Kjartan Mannes's avatar
Kjartan Mannes committed
313
314
  foreach ($vocabularies as $vocabulary) {
    $links = array();
Dries Buytaert's avatar
   
Dries Buytaert committed
315
    $types = array();
Dries Buytaert's avatar
   
Dries Buytaert committed
316
317
    foreach(explode(',', $vocabulary->nodes) as $type) {
      $types[] = node_invoke($type, 'node_name');
Dries Buytaert's avatar
   
Dries Buytaert committed
318
    }
Dries Buytaert's avatar
   
Dries Buytaert committed
319
    $rows[] = array($vocabulary->name, array('data' => implode(', ', $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 Mannes's avatar
Kjartan Mannes committed
320

Dries Buytaert's avatar
   
Dries Buytaert committed
321
    $tree = taxonomy_get_tree($vocabulary->vid);
Kjartan Mannes's avatar
Kjartan Mannes committed
322
    if ($tree) {
Dries Buytaert's avatar
   
Dries Buytaert committed
323
      unset($data);
Kjartan Mannes's avatar
Kjartan Mannes committed
324
      foreach ($tree as $term) {
Dries Buytaert's avatar
   
Dries Buytaert committed
325
        $data .= _taxonomy_depth($term->depth) .' '. $term->name .' ('. l(t('edit term'), "admin/taxonomy/edit/term/$term->tid") .')<br />';
Dries Buytaert's avatar
 
Dries Buytaert committed
326
      }
Dries Buytaert's avatar
   
Dries Buytaert committed
327
      $rows[] = array(array('data' => $data, 'colspan' => 5));
Dries Buytaert's avatar
 
Dries Buytaert committed
328
329
330
    }
  }

Dries Buytaert's avatar
   
Dries Buytaert committed
331
  return theme('table', $header, $rows);
Kjartan Mannes's avatar
Kjartan Mannes committed
332
333
}

Dries Buytaert's avatar
   
Dries Buytaert committed
334
335
336
/**
 * Generate a form element for selecting terms from a vocabulary.
 */
Dries Buytaert's avatar
   
Dries Buytaert committed
337
function taxonomy_form($vid, $value = 0, $help = NULL, $name = 'taxonomy') {
Dries Buytaert's avatar
   
Dries Buytaert committed
338
  $vocabulary = taxonomy_get_vocabulary($vid);
339
  $help = ($help) ? $help : $vocabulary->help;
Kjartan Mannes's avatar
Kjartan Mannes committed
340
341
342
343
  if ($vocabulary->required) {
    $blank = 0;
  }
  else {
Dries Buytaert's avatar
   
Dries Buytaert committed
344
    $blank = '<'. t('none') .'>';
Kjartan Mannes's avatar
Kjartan Mannes committed
345
  }
Dries Buytaert's avatar
   
Dries Buytaert committed
346

Dries Buytaert's avatar
   
Dries Buytaert committed
347
  return _taxonomy_term_select($vocabulary->name, $name, $value, $vid, $help, intval($vocabulary->multiple), $blank);
Kjartan Mannes's avatar
Kjartan Mannes committed
348
}
Dries Buytaert's avatar
 
Dries Buytaert committed
349

Dries Buytaert's avatar
   
Dries Buytaert committed
350
351
352
353
354
355
356
/**
 * Return an array of all vocabulary objects.
 *
 * @param $type
 *   If set, return only those vocabularies associated with this node type.
 */
function taxonomy_get_vocabularies($type = '', $key = 'vid') {
Kjartan Mannes's avatar
Kjartan Mannes committed
357
  if ($type) {
Dries Buytaert's avatar
   
Dries Buytaert committed
358
    $result = db_query("SELECT * FROM {vocabulary} WHERE nodes LIKE '%%%s%%' ORDER BY weight, name", $type);
Kjartan Mannes's avatar
Kjartan Mannes committed
359
360
  }
  else {
Dries Buytaert's avatar
   
Dries Buytaert committed
361
    $result = db_query('SELECT * FROM {vocabulary} ORDER BY weight, name');
Kjartan Mannes's avatar
Kjartan Mannes committed
362
363
364
365
  }
  $vocabularies = array();
  while ($voc = db_fetch_object($result)) {
    $vocabularies[$voc->$key] = $voc;
Dries Buytaert's avatar
 
Dries Buytaert committed
366
  }
Dries Buytaert's avatar
   
Dries Buytaert committed
367

Kjartan Mannes's avatar
Kjartan Mannes committed
368
369
  return $vocabularies;
}
Dries Buytaert's avatar
 
Dries Buytaert committed
370

Dries Buytaert's avatar
   
Dries Buytaert committed
371
372
373
/**
 * Generate a form for selecting terms to associate with a node.
 */
Dries Buytaert's avatar
   
Dries Buytaert committed
374
function taxonomy_node_form($type, $node = '', $help = NULL, $name = 'taxonomy') {
Kjartan Mannes's avatar
Kjartan Mannes committed
375
376
377
  if (!$node->taxonomy) {
    if ($node->nid) {
      $terms = array_keys(taxonomy_node_get_terms($node->nid));
Kjartan Mannes's avatar
Kjartan Mannes committed
378
379
    }
    else {
Kjartan Mannes's avatar
Kjartan Mannes committed
380
      $terms = 0;
Dries Buytaert's avatar
 
Dries Buytaert committed
381
    }
Kjartan Mannes's avatar
Kjartan Mannes committed
382
383
384
385
  }
  else {
    $terms = $node->taxonomy;
  }
Dries Buytaert's avatar
 
Dries Buytaert committed
386

Dries Buytaert's avatar
   
Dries Buytaert committed
387
  $c = db_query("SELECT * FROM {vocabulary} WHERE nodes LIKE '%%%s%%' ORDER BY weight, name", $type);
Kjartan Mannes's avatar
Kjartan Mannes committed
388
  while ($vocabulary = db_fetch_object($c)) {
Dries Buytaert's avatar
   
Dries Buytaert committed
389
    $result[] = taxonomy_form($vocabulary->vid, $terms, $help, $name);
Dries Buytaert's avatar
 
Dries Buytaert committed
390
  }
Kjartan Mannes's avatar
Kjartan Mannes committed
391
392
  return $result ? $result : array();
}
Dries Buytaert's avatar
 
Dries Buytaert committed
393

Dries Buytaert's avatar
   
Dries Buytaert committed
394
395
396
/**
 * Determine whether a node mentions the name of a term.
 */
Kjartan Mannes's avatar
Kjartan Mannes committed
397
function taxonomy_node_has_term($nid, $tid) {
Dries Buytaert's avatar
   
Dries Buytaert committed
398
  $term_name = db_result(db_query('SELECT name FROM {term_data} WHERE tid = %d', $tid));
Dries Buytaert's avatar
 
Dries Buytaert committed
399

Dries Buytaert's avatar
   
Dries Buytaert committed
400
  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 Mannes's avatar
Kjartan Mannes committed
401
402
}

Dries Buytaert's avatar
   
Dries Buytaert committed
403
404
405
406
407
/**
 * Find all terms associated to the given node, within one vocabulary.
 */
function taxonomy_node_get_terms_by_vocabulary($nid, $vid, $key = 'tid') {
  $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 Mannes's avatar
Kjartan Mannes committed
408
409
410
  $terms = array();
  while ($term = db_fetch_object($result)) {
    $terms[$term->$key] = $term;
Dries Buytaert's avatar
 
Dries Buytaert committed
411
  }
Kjartan Mannes's avatar
Kjartan Mannes committed
412
413
414
  return $terms;
}

Dries Buytaert's avatar
   
Dries Buytaert committed
415
416
417
418
/**
 * Find all terms associated to the given node.
 */
function taxonomy_node_get_terms($nid, $key = 'tid') {
Kjartan Mannes's avatar
Kjartan Mannes committed
419
  static $terms;
Dries Buytaert's avatar
 
Dries Buytaert committed
420

Dries Buytaert's avatar
   
Dries Buytaert committed
421
  if (!isset($terms[$nid])) {
Dries Buytaert's avatar
   
Dries Buytaert committed
422
    $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 Mannes's avatar
Kjartan Mannes committed
423
    $terms[$nid] = array();
Dries Buytaert's avatar
 
Dries Buytaert committed
424
    while ($term = db_fetch_object($result)) {
Kjartan Mannes's avatar
Kjartan Mannes committed
425
      $terms[$nid][$term->$key] = $term;
Dries Buytaert's avatar
 
Dries Buytaert committed
426
427
    }
  }
Kjartan Mannes's avatar
Kjartan Mannes committed
428
429
  return $terms[$nid];
}
Dries Buytaert's avatar
 
Dries Buytaert committed
430

Dries Buytaert's avatar
   
Dries Buytaert committed
431
432
433
/**
 * Save term associations for a given node.
 */
Kjartan Mannes's avatar
Kjartan Mannes committed
434
435
function taxonomy_node_save($nid, $terms) {
  taxonomy_node_delete($nid);
Dries Buytaert's avatar
 
Dries Buytaert committed
436

Kjartan Mannes's avatar
Kjartan Mannes committed
437
  if ($terms) {
Dries Buytaert's avatar
   
Dries Buytaert committed
438
    foreach ($terms as $term) {
439
      if ($term) {
Dries Buytaert's avatar
   
Dries Buytaert committed
440
        db_query('INSERT INTO {term_node} (nid, tid) VALUES (%d, %d)', $nid, $term);
441
      }
Dries Buytaert's avatar
 
Dries Buytaert committed
442
443
    }
  }
Kjartan Mannes's avatar
Kjartan Mannes committed
444
}
Dries Buytaert's avatar
 
Dries Buytaert committed
445

Dries Buytaert's avatar
   
Dries Buytaert committed
446
447
448
/**
 * Remove associations of a node to its terms.
 */
Kjartan Mannes's avatar
Kjartan Mannes committed
449
function taxonomy_node_delete($nid) {
Dries Buytaert's avatar
   
Dries Buytaert committed
450
  db_query('DELETE FROM {term_node} WHERE nid = %d', $nid);
Kjartan Mannes's avatar
Kjartan Mannes committed
451
}
Dries Buytaert's avatar
 
Dries Buytaert committed
452

Dries Buytaert's avatar
   
Dries Buytaert committed
453
454
455
456
/**
 * Find all term objects related to a given term ID.
 */
function taxonomy_get_related($tid, $key = 'tid') {
Kjartan Mannes's avatar
Kjartan Mannes committed
457
  if ($tid) {
Dries Buytaert's avatar
   
Dries Buytaert committed
458
    $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 Mannes's avatar
Kjartan Mannes committed
459
460
461
    $related = array();
    while ($term = db_fetch_object($result)) {
      $related[$term->$key] = $term;
Dries Buytaert's avatar
 
Dries Buytaert committed
462
    }
Kjartan Mannes's avatar
Kjartan Mannes committed
463
    return $related;
Dries Buytaert's avatar
 
Dries Buytaert committed
464
  }
Kjartan Mannes's avatar
Kjartan Mannes committed
465
466
  else {
    return array();
Dries Buytaert's avatar
 
Dries Buytaert committed
467
  }
Kjartan Mannes's avatar
Kjartan Mannes committed
468
}
Dries Buytaert's avatar
 
Dries Buytaert committed
469

Dries Buytaert's avatar
   
Dries Buytaert committed
470
471
472
473
/**
 * Find all parents of a given term ID.
 */
function taxonomy_get_parents($tid, $key = 'tid') {
Kjartan Mannes's avatar
Kjartan Mannes committed
474
  if ($tid) {
Dries Buytaert's avatar
   
Dries Buytaert committed
475
    $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 Mannes's avatar
Kjartan Mannes committed
476
477
478
    $parents = array();
    while ($parent = db_fetch_object($result)) {
      $parents[$parent->$key] = $parent;
Dries Buytaert's avatar
   
Dries Buytaert committed
479
    }
Kjartan Mannes's avatar
Kjartan Mannes committed
480
    return $parents;
Dries Buytaert's avatar
 
Dries Buytaert committed
481
  }
Kjartan Mannes's avatar
Kjartan Mannes committed
482
483
484
485
  else {
    return array();
  }
}
Dries Buytaert's avatar
 
Dries Buytaert committed
486

Dries Buytaert's avatar
   
Dries Buytaert committed
487
488
489
490
/**
 * Find all ancestors of a given term ID.
 */
function taxonomy_get_parents_all($tid) {
Dries Buytaert's avatar
   
Dries Buytaert committed
491
492
493
494
495
496
497
498
499
500
501
502
  $parents = array();
  if ($tid) {
    $parents[] = taxonomy_get_term($tid);
    $n = 0;
    while ($parent = taxonomy_get_parents($parents[$n]->tid)) {
      $parents = array_merge($parents, $parent);
      $n++;
    }
  }
  return $parents;
}

Dries Buytaert's avatar
   
Dries Buytaert committed
503
504
505
506
/**
 * Find all children of a term ID.
 */
function taxonomy_get_children($tid, $vid = 0, $key = 'tid') {
Kjartan Mannes's avatar
Kjartan Mannes committed
507
  if ($vid) {
Dries Buytaert's avatar
   
Dries Buytaert committed
508
    $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 Buytaert's avatar
 
Dries Buytaert committed
509
  }
Kjartan Mannes's avatar
Kjartan Mannes committed
510
  else {
Dries Buytaert's avatar
   
Dries Buytaert committed
511
    $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 Mannes's avatar
Kjartan Mannes committed
512
513
514
515
516
517
518
  }
  $children = array();
  while ($term = db_fetch_object($result)) {
    $children[$term->$key] = $term;
  }
  return $children;
}
Dries Buytaert's avatar
 
Dries Buytaert committed
519

Dries Buytaert's avatar
   
Dries Buytaert committed
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
/**
 * Create a hierarchical representation of a vocabulary.
 *
 * @param $vid
 *   Which vocabulary to generate the tree for.
 *
 * @param $parent
 *   The term ID under which to generate the tree. If 0, generate the tree
 *   for the entire vocabulary.
 *
 * @param $depth
 *   Internal use only.
 *
 * @return
 *   An array of all term objects in the tree. Each term object is extended
 *   to have "depth" and "parents" attributes in addition to its normal ones.
 */
function taxonomy_get_tree($vid, $parent = 0, $depth = -1, $max_depth = NULL) {
Dries Buytaert's avatar
   
Dries Buytaert committed
538
  static $children, $parents, $terms;
Dries Buytaert's avatar
   
Dries Buytaert committed
539

Kjartan Mannes's avatar
Kjartan Mannes committed
540
  $depth++;
Dries Buytaert's avatar
   
Dries Buytaert committed
541

Dries Buytaert's avatar
   
Dries Buytaert committed
542
543
544
545
  // We cache trees, so it's not CPU-intensive to call get_tree() on a term
  // and its children, too.
  if (!isset($children[$vid])) {
    $children[$vid] = array();
Dries Buytaert's avatar
   
Dries Buytaert committed
546

Dries Buytaert's avatar
   
Dries Buytaert committed
547
    $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', $vid);
Dries Buytaert's avatar
   
Dries Buytaert committed
548
    while ($term = db_fetch_object($result)) {
Dries Buytaert's avatar
   
Dries Buytaert committed
549
550
551
      $children[$vid][$term->parent][] = $term->tid;
      $parents[$vid][$term->tid][] = $term->parent;
      $terms[$vid][$term->tid] = $term;
Dries Buytaert's avatar
 
Dries Buytaert committed
552
553
    }
  }
Dries Buytaert's avatar
   
Dries Buytaert committed
554

Dries Buytaert's avatar
   
Dries Buytaert committed
555
556
557
  $max_depth = ($max_depth == '') ? count($children[$vid]) : $max_depth;
  if ($children[$vid][$parent]) {
    foreach ($children[$vid][$parent] as $child) {
Dries Buytaert's avatar
   
Dries Buytaert committed
558
      if ($max_depth > $depth) {
Dries Buytaert's avatar
   
Dries Buytaert committed
559
560
561
562
563
        $terms[$vid][$child]->depth = $depth;
        // The "parent" attribute is not useful, as it would show one parent only.
        unset($terms[$vid][$child]->parent);
        $terms[$vid][$child]->parents = $parents[$vid][$child];
        $tree[] = $terms[$vid][$child];
Dries Buytaert's avatar
   
Dries Buytaert committed
564

Dries Buytaert's avatar
   
Dries Buytaert committed
565
        $tree = array_merge($tree, taxonomy_get_tree($vid, $child, $depth, $max_depth));
Dries Buytaert's avatar
   
Dries Buytaert committed
566
      }
Dries Buytaert's avatar
   
Dries Buytaert committed
567
    }
Kjartan Mannes's avatar
Kjartan Mannes committed
568
  }
Dries Buytaert's avatar
   
Dries Buytaert committed
569

Dries Buytaert's avatar
   
Dries Buytaert committed
570
  return $tree ? $tree : array();
Kjartan Mannes's avatar
Kjartan Mannes committed
571
}
Dries Buytaert's avatar
 
Dries Buytaert committed
572

Dries Buytaert's avatar
   
Dries Buytaert committed
573
574
575
/**
 * Return an array of synonyms of the given term ID.
 */
Kjartan Mannes's avatar
Kjartan Mannes committed
576
577
function taxonomy_get_synonyms($tid) {
  if ($tid) {
Dries Buytaert's avatar
   
Dries Buytaert committed
578
    $result = db_query('SELECT name FROM {term_synonym} WHERE tid = %d', $tid);
Kjartan Mannes's avatar
Kjartan Mannes committed
579
    while ($synonym = db_fetch_array($result)) {
Dries Buytaert's avatar
   
Dries Buytaert committed
580
      $synonyms[] = $synonym['name'];
Dries Buytaert's avatar
 
Dries Buytaert committed
581
    }
Kjartan Mannes's avatar
Kjartan Mannes committed
582
    return $synonyms ? $synonyms : array();
Dries Buytaert's avatar
 
Dries Buytaert committed
583
  }
Kjartan Mannes's avatar
Kjartan Mannes committed
584
585
  else {
    return array();
Dries Buytaert's avatar
   
Dries Buytaert committed
586
  }
Kjartan Mannes's avatar
Kjartan Mannes committed
587
}
Dries Buytaert's avatar
   
Dries Buytaert committed
588

Dries Buytaert's avatar
   
Dries Buytaert committed
589
590
591
592
593
/**
 * Return the term object that has the given string as a synonym.
 */
function taxonomy_get_synonym_root($synonym) {
  return db_fetch_object(db_query("SELECT * FROM {term_synonym} s, {term_data} t WHERE t.tid = s.tid AND s.name = '%s'", $synonym));
Kjartan Mannes's avatar
Kjartan Mannes committed
594
}
Dries Buytaert's avatar
   
Dries Buytaert committed
595

Dries Buytaert's avatar
   
Dries Buytaert committed
596
597
598
/**
 * Given a term id, count the number of published nodes in it.
 */
Dries Buytaert's avatar
   
Dries Buytaert committed
599
function taxonomy_term_count_nodes($tid, $type = 0) {
Kjartan Mannes's avatar
Kjartan Mannes committed
600
  static $count;
Dries Buytaert's avatar
   
Dries Buytaert committed
601

Dries Buytaert's avatar
   
Dries Buytaert committed
602
603
604
  if (!isset($count[$type])) {
    // $type == 0 always evaluates true is $type is a string
    if (is_numeric($type)) {
Dries Buytaert's avatar
   
Dries Buytaert committed
605
      $result = db_query('SELECT t.tid, COUNT(*) AS c FROM {term_node} t INNER JOIN {node} n ON t.nid = n.nid WHERE n.status = 1 GROUP BY t.tid');
Dries Buytaert's avatar
   
Dries Buytaert committed
606
607
    }
    else {
Dries Buytaert's avatar
   
Dries Buytaert committed
608
      $result = db_query("SELECT t.tid, COUNT(*) AS c FROM {term_node} t, {node} n WHERE t.nid = n.nid AND n.status = 1 AND n.type = '%s' GROUP BY t.tid", $type);
Dries Buytaert's avatar
   
Dries Buytaert committed
609
    }
Kjartan Mannes's avatar
Kjartan Mannes committed
610
    while ($term = db_fetch_object($result)) {
Dries Buytaert's avatar
   
Dries Buytaert committed
611
      $count[$type][$term->tid] = $term->c;
Dries Buytaert's avatar
   
Dries Buytaert committed
612
613
614
    }
  }

Kjartan Mannes's avatar
Kjartan Mannes committed
615
  foreach (_taxonomy_term_children($tid) as $c) {
Dries Buytaert's avatar
   
Dries Buytaert committed
616
    $children_count += taxonomy_term_count_nodes($c, $type);
Kjartan Mannes's avatar
Kjartan Mannes committed
617
  }
Dries Buytaert's avatar
   
Dries Buytaert committed
618
  return $count[$type][$tid] + $children_count;
Kjartan Mannes's avatar
Kjartan Mannes committed
619
620
}

Dries Buytaert's avatar
   
Dries Buytaert committed
621
622
623
/**
 * Helper for taxonomy_term_count_nodes().
 */
Kjartan Mannes's avatar
Kjartan Mannes committed
624
625
function _taxonomy_term_children($tid) {
  static $children;
Dries Buytaert's avatar
   
Dries Buytaert committed
626

Dries Buytaert's avatar
   
Dries Buytaert committed
627
  if (!isset($children)) {
Dries Buytaert's avatar
   
Dries Buytaert committed
628
    $result = db_query('SELECT tid, parent FROM {term_hierarchy}');
Kjartan Mannes's avatar
Kjartan Mannes committed
629
630
    while ($term = db_fetch_object($result)) {
      $children[$term->parent][] = $term->tid;
Dries Buytaert's avatar
   
Dries Buytaert committed
631
    }
Dries Buytaert's avatar
 
Dries Buytaert committed
632
  }
Kjartan Mannes's avatar
Kjartan Mannes committed
633
634
  return $children[$tid] ? $children[$tid] : array();
}
Dries Buytaert's avatar
 
Dries Buytaert committed
635

Dries Buytaert's avatar
   
Dries Buytaert committed
636
/**
Dries Buytaert's avatar
   
Dries Buytaert committed
637
638
639
640
641
642
643
 * Try to map a string to an existing vocabulary.
 *
 * Provides a case-insensitive and trimmed mapping, to maximize the
 * likelihood of a successful match.
 *
 * @param name
 *   Name of the vocabulary to search for.
Dries Buytaert's avatar
   
Dries Buytaert committed
644
 *
Dries Buytaert's avatar
   
Dries Buytaert committed
645
646
 * @return
 *   An array of matching vocabulary objects.
Dries Buytaert's avatar
   
Dries Buytaert committed
647
648
 */
function taxonomy_get_vocabulary_by_name($name) {
Dries Buytaert's avatar
   
Dries Buytaert committed
649
  $db_result = db_query("SELECT * FROM {vocabulary} WHERE LOWER('%s') LIKE LOWER(name)", trim($name));
Dries Buytaert's avatar
   
Dries Buytaert committed
650
651
652
653
654
655
656
657
658
  $result = array();
  while ($vocabulary = db_fetch_object($db_result)) {
    $result[] = $vocabulary;
  }

  return $result;
}

/**
Dries Buytaert's avatar
   
Dries Buytaert committed
659
 * Try to map a string to an existing term, as for glossary use.
Dries Buytaert's avatar
   
Dries Buytaert committed
660
 *
Dries Buytaert's avatar
   
Dries Buytaert committed
661
662
663
664
665
666
667
668
 * Provides a case-insensitive and trimmed mapping, to maximize the
 * likelihood of a successful match.
 *
 * @param name
 *   Name of the term to search for.
 *
 * @return
 *   An array of matching term objects.
Dries Buytaert's avatar
   
Dries Buytaert committed
669
670
 */
function taxonomy_get_term_by_name($name) {
Dries Buytaert's avatar
   
Dries Buytaert committed
671
  $db_result = db_query("SELECT * FROM {term_data} WHERE LOWER('%s') LIKE LOWER(name)", trim($name));
Dries Buytaert's avatar
   
Dries Buytaert committed
672
673
674
675
676
677
678
679
  $result = array();
  while ($term = db_fetch_object($db_result)) {
    $result[] = $term;
  }

  return $result;
}

Dries Buytaert's avatar
   
Dries Buytaert committed
680
681
682
/**
 * Return the vocabulary object matching a vocabulary ID.
 */
Kjartan Mannes's avatar
Kjartan Mannes committed
683
function taxonomy_get_vocabulary($vid) {
Dries Buytaert's avatar
   
Dries Buytaert committed
684
  return db_fetch_object(db_query('SELECT * FROM {vocabulary} WHERE vid = %d', $vid));
Kjartan Mannes's avatar
Kjartan Mannes committed
685
}
Dries Buytaert's avatar
 
Dries Buytaert committed
686

Dries Buytaert's avatar
   
Dries Buytaert committed
687
688
689
/**
 * Return the term object matching a term ID.
 */
Kjartan Mannes's avatar
Kjartan Mannes committed
690
691
function taxonomy_get_term($tid) {
  // simple cache using a static var?
Dries Buytaert's avatar
   
Dries Buytaert committed
692
  return db_fetch_object(db_query('SELECT * FROM {term_data} WHERE tid = %d', $tid));
Kjartan Mannes's avatar
Kjartan Mannes committed
693
}
Dries Buytaert's avatar
 
Dries Buytaert committed
694

Kjartan Mannes's avatar
Kjartan Mannes committed
695
function _taxonomy_term_select($title, $name, $value, $vocabulary_id, $description, $multiple, $blank, $exclude = array()) {
Dries Buytaert's avatar
   
Dries Buytaert committed
696
  $tree = taxonomy_get_tree($vocabulary_id);
Dries Buytaert's avatar
Dries Buytaert committed
697
698
699
  if ($blank) {
    $options[] = array('tid' => 0, 'name' => $blank);
  }
Kjartan Mannes's avatar
Kjartan Mannes committed
700
701
702
  if ($tree) {
    foreach ($tree as $term) {
      if (!in_array($term->tid, $exclude)) {
Dries Buytaert's avatar
   
Dries Buytaert committed
703
        $options[] = array('tid' => $term->tid, 'name' => _taxonomy_depth($term->depth, '-').$term->name);
Dries Buytaert's avatar
 
Dries Buytaert committed
704
705
      }
    }
Kjartan Mannes's avatar
Kjartan Mannes committed
706
707
708
709
710
    if (!$blank && !$value) {
      // required but without a predefined value, so set first as predefined
      $value = $tree[0]->tid;
    }
  }
Dries Buytaert's avatar
 
Dries Buytaert committed
711

Kjartan Mannes's avatar
Kjartan Mannes committed
712
  if (count($options) > 0) {
Dries Buytaert's avatar
   
Dries Buytaert committed
713
    foreach ($options as $option) {
Dries Buytaert's avatar
   
Dries Buytaert committed
714
      $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 Mannes's avatar
Kjartan Mannes committed
715
    }
Dries Buytaert's avatar
 
Dries Buytaert committed
716

Dries Buytaert's avatar
   
Dries Buytaert committed
717
    $size = min(12, count($options));
Dries Buytaert's avatar
 
Dries Buytaert committed
718

Dries Buytaert's avatar
   
Dries Buytaert committed
719
    return form_item($title, "<select name=\"edit[$name][]\"". ($multiple ? " multiple=\"multiple\" size=\"$size\"" : '') . ($extra ? " $extra" : '') .' class="'. _form_get_class('', false, _form_get_error($name)) ."\">$select</select>", $description, NULL, false, _form_get_error($name));
Dries Buytaert's avatar
 
Dries Buytaert committed
720
  }
Kjartan Mannes's avatar
Kjartan Mannes committed
721
}
Dries Buytaert's avatar
 
Dries Buytaert committed
722

Kjartan Mannes's avatar
Kjartan Mannes committed
723
724
725
function _taxonomy_depth($depth, $graphic = '--') {
  for ($n = 0; $n < $depth; $n++) {
    $result .= $graphic;
Dries Buytaert's avatar
 
Dries Buytaert committed
726
  }
Kjartan Mannes's avatar
Kjartan Mannes committed
727
728
  return $result;
}
Dries Buytaert's avatar
 
Dries Buytaert committed
729

Kjartan Mannes's avatar
Kjartan Mannes committed
730
731
732
function _prepare_update($data) {
  foreach ($data as $key => $value) {
    $q[] = "$key = '". check_query($value) ."'";
Dries Buytaert's avatar
 
Dries Buytaert committed
733
  }
Dries Buytaert's avatar
   
Dries Buytaert committed
734
  $result = implode(', ', $q);
Kjartan Mannes's avatar
Kjartan Mannes committed
735
736
  return $result;
}
Dries Buytaert's avatar
 
Dries Buytaert committed
737

Kjartan Mannes's avatar
Kjartan Mannes committed
738
739
function _prepare_insert($data, $stage) {
  if ($stage == 1) {
Dries Buytaert's avatar
   
Dries Buytaert committed
740
    $result = implode(', ', array_keys($data));
Kjartan Mannes's avatar
Kjartan Mannes committed
741
742
743
744
  }
  else {
    foreach (array_values($data) as $value) {
      $q[] = "'". check_query($value) ."'";
Dries Buytaert's avatar
 
Dries Buytaert committed
745
    }
Dries Buytaert's avatar
   
Dries Buytaert committed
746
    $result = implode(', ', $q);
Dries Buytaert's avatar
 
Dries Buytaert committed
747
  }
Kjartan Mannes's avatar
Kjartan Mannes committed
748
749
  return "($result)";
}
Dries Buytaert's avatar
   
Dries Buytaert committed
750

Dries Buytaert's avatar
   
Dries Buytaert committed
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
/**
 * Finds all nodes that match selected taxonomy conditions.
 *
 * @param $taxonomy
 *   An object containing the conditions to match. The attributes of this
 *   object are:
 *   - "tids": An array of term IDs to match.
 *   - "str_tids": A comma-separated list of the same IDs.
 *   - "operator": How to interpret multiple IDs in the array. Can be
 *     "or" or "and".
 *
 * @param $pager
 *   Whether the nodes are to be used with a pager (the case on most Drupal
 *   pages) or not (in an XML feed, for example).
 *
 * @return
 *   A resource identifier pointing to the query results.
 */
function taxonomy_select_nodes($taxonomy, $pager = TRUE) {
770
  if ($taxonomy->str_tids) {
Dries Buytaert's avatar
   
Dries Buytaert committed
771
    if ($taxonomy->operator == 'or') {
Dries Buytaert's avatar
   
Dries Buytaert committed
772
      $sql = "SELECT DISTINCT(n.nid), n.title, n.type, n.created, n.changed, n.uid, n.sticky, n.created, u.name FROM {node} n INNER JOIN {term_node} r ON n.nid = r.nid INNER JOIN {users} u ON n.uid = u.uid WHERE r.tid IN ($taxonomy->str_tids) AND n.status = 1 ORDER BY sticky DESC, created DESC";
Dries Buytaert's avatar
   
Dries Buytaert committed
773
      $sql_count = "SELECT COUNT(DISTINCT(n.nid)) FROM {node} n INNER JOIN {term_node} r ON n.nid = r.nid INNER JOIN {users} u ON n.uid = u.uid WHERE r.tid IN ($taxonomy->str_tids) AND n.status = 1";
774
775
    }
    else {
Dries Buytaert's avatar
   
Dries Buytaert committed
776
      $sql = "SELECT n.nid, n.title, n.type, n.created, n.changed, n.uid, u.name FROM {node} n INNER JOIN {term_node} r ON n.nid = r.nid INNER JOIN {users} u ON n.uid = u.uid WHERE r.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 sticky DESC, created DESC";
Dries Buytaert's avatar
   
Dries Buytaert committed
777

778
      // Special trick as we could not find anything better:
Dries Buytaert's avatar
   
Dries Buytaert committed
779
      $count = db_num_rows(db_query("SELECT n.nid FROM {node} n INNER JOIN {term_node} r ON n.nid = r.nid WHERE r.tid IN ($taxonomy->str_tids) AND n.status = 1 GROUP BY n.nid HAVING COUNT(n.nid) = ". count($taxonomy->tids)));
780
781
      $sql_count = "SELECT $count";
    }
Dries Buytaert's avatar
   
Dries Buytaert committed
782

783
    if ($pager) {
Dries Buytaert's avatar
   
Dries Buytaert committed
784
      $result = pager_query($sql, variable_get('default_nodes_main', 10) , 0, $sql_count);
785
786
787
788
    }
    else {
      $result = db_query_range($sql, 0, 15);
    }
Dries Buytaert's avatar
   
Dries Buytaert committed
789
790
791
792
793
  }

  return $result;
}

Dries Buytaert's avatar
   
Dries Buytaert committed
794
795
796
/**
 * Accepts the result of a pager_query() call, such as that performed by
 * taxonomy_select_nodes(), and formats each node along with a pager.
Dries Buytaert's avatar
   
Dries Buytaert committed
797
798
799
800
*/
function taxonomy_render_nodes($result) {

  while ($node = db_fetch_object($result)) {
Dries Buytaert's avatar
   
Dries Buytaert committed
801
    $output .= node_view(node_load(array('nid' => $node->nid, 'type' => $node->type)), 1);
Dries Buytaert's avatar
   
Dries Buytaert committed
802
  }
Dries Buytaert's avatar
   
Dries Buytaert committed
803
  $output .= theme('pager', NULL, variable_get('default_nodes_main', 10), 0);
Dries Buytaert's avatar
   
Dries Buytaert committed
804
  return $output;
Dries Buytaert's avatar
   
Dries Buytaert committed
805
806
}

Dries Buytaert's avatar
   
Dries Buytaert committed
807
808
809
/**
 * Implementation of hook_nodeapi().
 */
Dries Buytaert's avatar
   
Dries Buytaert committed
810
811
function taxonomy_nodeapi($node, $op, $arg = 0) {
  switch ($op) {
Dries Buytaert's avatar
   
Dries Buytaert committed
812
    case 'insert':
Dries Buytaert's avatar
   
Dries Buytaert committed
813
814
      taxonomy_node_save($node->nid, $node->taxonomy);
      break;
Dries Buytaert's avatar
   
Dries Buytaert committed
815
    case 'update':
Dries Buytaert's avatar
   
Dries Buytaert committed
816
817
      taxonomy_node_save($node->nid, $node->taxonomy);
      break;
Dries Buytaert's avatar
   
Dries Buytaert committed
818
    case 'delete':
Dries Buytaert's avatar
   
Dries Buytaert committed
819
820
821
822
823
      taxonomy_node_delete($node->nid);
      break;
  }
}

Kjartan Mannes's avatar
Kjartan Mannes committed
824
function taxonomy_page() {
Dries Buytaert's avatar
   
Dries Buytaert committed
825

Dries Buytaert's avatar
   
Dries Buytaert committed
826
827
  $taxonomy->operator = arg(2);
  $taxonomy->str_tids = check_query(arg(3));
Dries Buytaert's avatar
   
Dries Buytaert committed
828
  $taxonomy->tids = explode(',', $taxonomy->str_tids);
Dries Buytaert's avatar
   
Dries Buytaert committed
829

Dries Buytaert's avatar
   
Dries Buytaert committed
830
  if (ereg('^([0-9]+,){0,}[0-9]+$', $taxonomy->str_tids)) {
Dries Buytaert's avatar
   
Dries Buytaert committed
831
    switch (arg(1)) {
Dries Buytaert's avatar
   
Dries Buytaert committed
832
      case 'feed':
Dries Buytaert's avatar
   
Dries Buytaert committed
833
        taxonomy_feed($taxonomy);
Kjartan Mannes's avatar
Kjartan Mannes committed
834
      break;
Dries Buytaert's avatar
   
Dries Buytaert committed
835
      default:
Dries Buytaert's avatar
   
Dries Buytaert committed
836
      // Build title:
837
      $sql = 'SELECT name FROM {term_data} WHERE tid IN (%s)';
Dries Buytaert's avatar
   
Dries Buytaert committed
838
      $result = db_query($sql, $taxonomy->str_tids);
Kjartan Mannes's avatar
Kjartan Mannes committed
839
      $names = array();
Dries Buytaert's avatar
   
Dries Buytaert committed
840
841
842
      while ($term = db_fetch_object($result)) {
        $names[] = $term->name;
      }
Dries Buytaert's avatar
   
Dries Buytaert committed
843
844
845

      // Build breadcrumb based on first hierarchy of first term:
      $current->tid = $taxonomy->tids[0];
Dries Buytaert's avatar
   
Dries Buytaert committed
846
      $breadcrumbs = array(array('path' => $_GET['q']));
Dries Buytaert's avatar
   
Dries Buytaert committed
847
848
      while ($parents = taxonomy_get_parents($current->tid)) {
        $current = array_shift($parents);
Dries Buytaert's avatar
   
Dries Buytaert committed
849
        $breadcrumbs[] = array('path' => 'taxonomy/view/or/'. $current->tid, 'title' => $current->name);
Dries Buytaert's avatar
   
Dries Buytaert committed
850
851
      }
      $breadcrumbs = array_reverse($breadcrumbs);
Dries Buytaert's avatar
   
Dries Buytaert committed
852
      menu_set_location($breadcrumbs);
Dries Buytaert's avatar
   
Dries Buytaert committed
853

Dries Buytaert's avatar
   
Dries Buytaert committed
854
      drupal_set_html_head('<link rel="alternate" type="application/rss+xml" title="RSS - '. implode(' : ', $names) .'" href="'. url("taxonomy/feed/or/$taxonomy->str_tids") .'" />');
Dries Buytaert's avatar
Dries Buytaert committed
855

Dries Buytaert's avatar
   
Dries Buytaert committed
856
      $output = taxonomy_render_nodes(taxonomy_select_nodes($taxonomy));
Dries Buytaert's avatar
   
Dries Buytaert committed
857
      print theme('page', $output, implode(', ', $names));
Dries Buytaert's avatar
   
Dries Buytaert committed
858
      break;
Dries Buytaert's avatar
   
Dries Buytaert committed
859
860
861
862
    }
  }
  else {
    drupal_not_found();
Dries Buytaert's avatar
   
Dries Buytaert committed
863
  }
Kjartan Mannes's avatar
Kjartan Mannes committed
864
}
Dries Buytaert's avatar
   
Dries Buytaert committed
865

Dries Buytaert's avatar
   
Dries Buytaert committed
866
867
868
/**
 * Menu callback; dispatches to the proper taxonomy administration function.
 */
Kjartan Mannes's avatar
Kjartan Mannes committed
869
function taxonomy_admin() {
Dries Buytaert's avatar
   
Dries Buytaert committed
870
871
  $op = $_POST['op'];
  $edit = $_POST['edit'];
Kjartan Mannes's avatar
Kjartan Mannes committed
872

Dries Buytaert's avatar
   
Dries Buytaert committed
873
874
875
  if (empty($op)) {
    $op = arg(2);
  }
Dries Buytaert's avatar
   
Dries Buytaert committed
876

Dries Buytaert's avatar
   
Dries Buytaert committed
877
  switch ($op) {
Dries Buytaert's avatar
   
Dries Buytaert committed
878
879
    case 'add':
      if (arg(3) == 'vocabulary') {
Dries Buytaert's avatar
   
Dries Buytaert committed
880
881
        $output .= taxonomy_form_vocabulary();
      }
Dries Buytaert's avatar
   
Dries Buytaert committed
882
      else if (arg(3) == 'term') {