taxonomy.module 38.4 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

Kjartan Mannes's avatar
Kjartan Mannes committed
77
function taxonomy_form_vocabulary($edit = array()) {
Dries Buytaert's avatar
   
Dries Buytaert committed
78
  foreach (node_list() as $type) {
Dries Buytaert's avatar
   
Dries Buytaert committed
79
    $nodetypes[$type] = node_invoke($type, 'node_name');
Kjartan Mannes's avatar
Kjartan Mannes committed
80
  }
Dries Buytaert's avatar
   
Dries Buytaert committed
81

Dries Buytaert's avatar
   
Dries Buytaert committed
82
83
84
85
86
87
88
89
90
91
  $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_textfield(t('Help text'), 'help', $edit['help'], 50, 255, t('Optional') .'. '. t('Instructions to present to the user when choosing a term.') .'.');
  $form .= form_checkboxes(t('Types'), 'nodes', explode(',', $edit['nodes']), $nodetypes, t('Required') .'. '. t('A list of node types you want to associate with this vocabulary.'));
  $form .= form_checkbox(t('Related terms'), 'relations', 1, $edit['relations'], t('Optional') .'. '. 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('Optional') .'. '. 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('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 <strong>must</strong> have at least one term in this vocabulary.'));
  $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.'));
  $form .= form_submit(t('Submit'));
Dries Buytaert's avatar
 
Dries Buytaert committed
92

Dries Buytaert's avatar
   
Dries Buytaert committed
93
94
95
  if ($edit['vid']) {
    $form .= form_submit(t('Delete'));
    $form .= form_hidden('vid', $edit['vid']);
Dries Buytaert's avatar
 
Dries Buytaert committed
96
97
  }

Kjartan Mannes's avatar
Kjartan Mannes committed
98
99
  return form($form);
}
Kjartan Mannes's avatar
Kjartan Mannes committed
100

Kjartan Mannes's avatar
Kjartan Mannes committed
101
function taxonomy_save_vocabulary($edit) {
Dries Buytaert's avatar
   
Dries Buytaert committed
102
103
  if (!$edit['nodes']) {
    $edit['nodes'] = array();
Dries Buytaert's avatar
   
Dries Buytaert committed
104
105
  }

Dries Buytaert's avatar
   
Dries Buytaert committed
106
107
108
109
110
  $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
111
  }
Dries Buytaert's avatar
   
Dries Buytaert committed
112
113
  else if ($edit['vid']) {
    $message = taxonomy_del_vocabulary($edit['vid']);
Kjartan Mannes's avatar
Kjartan Mannes committed
114
115
  }
  else {
Dries Buytaert's avatar
   
Dries Buytaert committed
116
117
118
119
    $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
120
  }
Dries Buytaert's avatar
   
Dries Buytaert committed
121
122

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

Dries Buytaert's avatar
   
Dries Buytaert committed
124
125
  drupal_set_message($message);
  return $edit;
Kjartan Mannes's avatar
Kjartan Mannes committed
126
}
Dries Buytaert's avatar
 
Dries Buytaert committed
127

Kjartan Mannes's avatar
Kjartan Mannes committed
128
function taxonomy_del_vocabulary($vid) {
Dries Buytaert's avatar
   
Dries Buytaert committed
129
130
  $vocabulary = taxonomy_get_vocabulary($vid);

Dries Buytaert's avatar
   
Dries Buytaert committed
131
132
  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
133
134
  while ($term = db_fetch_object($result)) {
    taxonomy_del_term($term->tid);
Dries Buytaert's avatar
 
Dries Buytaert committed
135
  }
Dries Buytaert's avatar
   
Dries Buytaert committed
136

Dries Buytaert's avatar
   
Dries Buytaert committed
137
  module_invoke_all('taxonomy', 'delete', 'vocabulary', $vocabulary);
Dries Buytaert's avatar
   
Dries Buytaert committed
138

Dries Buytaert's avatar
   
Dries Buytaert committed
139
140
  cache_clear_all();

Dries Buytaert's avatar
   
Dries Buytaert committed
141
  return t('deleted vocabulary "%name".', array('%name' => $vocabulary->name));
Dries Buytaert's avatar
   
Dries Buytaert committed
142
143
144
145
146
}

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

Dries Buytaert's avatar
   
Dries Buytaert committed
147
148
149
150
151
  $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
152

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

Kjartan Mannes's avatar
Kjartan Mannes committed
156
function taxonomy_form_term($edit = array()) {
Dries Buytaert's avatar
   
Dries Buytaert committed
157
  $vocabulary_id = isset($edit['vid']) ? $edit['vid'] : arg(4);
Kjartan Mannes's avatar
Kjartan Mannes committed
158
  $vocabulary = taxonomy_get_vocabulary($vocabulary_id);
Dries Buytaert's avatar
   
Dries Buytaert committed
159

Dries Buytaert's avatar
   
Dries Buytaert committed
160
161
  $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 Buytaert's avatar
 
Dries Buytaert committed
162

Kjartan Mannes's avatar
Kjartan Mannes committed
163
  if ($vocabulary->hierarchy) {
Dries Buytaert's avatar
   
Dries Buytaert committed
164
165
    $parent = array_keys(taxonomy_get_parents($edit['tid']));
    $children = taxonomy_get_tree($vocabulary_id, $edit['tid']);
Dries Buytaert's avatar
   
Dries Buytaert committed
166

Dries Buytaert's avatar
   
Dries Buytaert committed
167
    // A term can't be the child of itself, nor of its children.
Dries Buytaert's avatar
   
Dries Buytaert committed
168
169
170
    foreach ($children as $child) {
      $exclude[] = $child->tid;
    }
Dries Buytaert's avatar
   
Dries Buytaert committed
171
    $exclude[] = $edit['tid'];
Dries Buytaert's avatar
   
Dries Buytaert committed
172

Kjartan Mannes's avatar
Kjartan Mannes committed
173
    if ($vocabulary->hierarchy == 1) {
Dries Buytaert's avatar
   
Dries Buytaert committed
174
      $form .= _taxonomy_term_select(t('Parent'), 'parent', $parent, $vocabulary_id, t('Required') .'. '. l(t('Parent term'), 'admin/taxonomy/help', NULL, NULL, 'parent') .'.', 0, '<'. t('root') .'>', $exclude);
Dries Buytaert's avatar
 
Dries Buytaert committed
175
    }
Kjartan Mannes's avatar
Kjartan Mannes committed
176
    elseif ($vocabulary->hierarchy == 2) {
Dries Buytaert's avatar
   
Dries Buytaert committed
177
      $form .= _taxonomy_term_select(t('Parents'), 'parent', $parent, $vocabulary_id, t('Required') .'. '. l(t('Parent terms'), 'admin/taxonomy/help', NULL, NULL, 'parent') .'.', 1, '<'. t('root') .'>', $exclude);
Dries Buytaert's avatar
 
Dries Buytaert committed
178
    }
Kjartan Mannes's avatar
Kjartan Mannes committed
179
  }
Dries Buytaert's avatar
 
Dries Buytaert committed
180

181
  if ($vocabulary->relations) {
Dries Buytaert's avatar
   
Dries Buytaert committed
182
    $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']));
183
184
  }

Dries Buytaert's avatar
   
Dries Buytaert committed
185
186
187
188
  $form .= form_textarea(t('Synonyms'), 'synonyms', implode("\n", taxonomy_get_synonyms($edit['tid'])), 30, 5, t('Optional') . '. '. 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('Optional. In listings, the heavier terms will sink and the lighter terms will be positioned nearer the top.'));
  $form .= form_hidden('vid', $vocabulary->vid);
  $form .= form_submit(t('Submit'));
Kjartan Mannes's avatar
Kjartan Mannes committed
189

Dries Buytaert's avatar
   
Dries Buytaert committed
190
191
192
  if ($edit['tid']) {
    $form .= form_submit(t('Delete'));
    $form .= form_hidden('tid', $edit['tid']);
Dries Buytaert's avatar
 
Dries Buytaert committed
193
194
  }

Kjartan Mannes's avatar
Kjartan Mannes committed
195
196
  return form($form);
}
Dries Buytaert's avatar
 
Dries Buytaert committed
197

Kjartan Mannes's avatar
Kjartan Mannes committed
198
function taxonomy_save_term($edit) {
Dries Buytaert's avatar
   
Dries Buytaert committed
199
200
  if ($edit['tid'] && $edit['name']) {
    $data = array('name' => $edit['name'], 'description' => $edit['description'], 'weight' => $edit['weight']);
Dries Buytaert's avatar
 
Dries Buytaert committed
201

Dries Buytaert's avatar
   
Dries Buytaert committed
202
203
204
    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
205
  }
Dries Buytaert's avatar
   
Dries Buytaert committed
206
207
  else if ($edit['tid']) {
    return taxonomy_del_term($edit['tid']);
Kjartan Mannes's avatar
Kjartan Mannes committed
208
209
  }
  else {
Dries Buytaert's avatar
   
Dries Buytaert committed
210
211
212
213
214
    $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
215
  }
Dries Buytaert's avatar
 
Dries Buytaert committed
216

Dries Buytaert's avatar
   
Dries Buytaert committed
217
218
219
  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
220
      if ($related_id != 0) {
Dries Buytaert's avatar
   
Dries Buytaert committed
221
        db_query('INSERT INTO {term_relation} (tid1, tid2) VALUES (%d, %d)', $edit['tid'], $related_id);
Dries Buytaert's avatar
 
Dries Buytaert committed
222
      }
Kjartan Mannes's avatar
Kjartan Mannes committed
223
    }
Kjartan Mannes's avatar
Kjartan Mannes committed
224
  }
Dries Buytaert's avatar
 
Dries Buytaert committed
225

Dries Buytaert's avatar
   
Dries Buytaert committed
226
227
228
  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
229
  }
Dries Buytaert's avatar
   
Dries Buytaert committed
230
231
232
  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
233
    }
Kjartan Mannes's avatar
Kjartan Mannes committed
234
235
  }
  else {
Dries Buytaert's avatar
   
Dries Buytaert committed
236
    db_query('INSERT INTO {term_hierarchy} (tid, parent) VALUES (%d, %d)', $edit['tid'], $edit['parent'][0]);
Dries Buytaert's avatar
 
Dries Buytaert committed
237
238
  }

Dries Buytaert's avatar
   
Dries Buytaert committed
239
240
241
  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
242
      if ($synonym) {
Dries Buytaert's avatar
   
Dries Buytaert committed
243
        db_query("INSERT INTO {term_synonym} (tid, name) VALUES (%d, '%s')", $edit['tid'], chop($synonym));
Dries Buytaert's avatar
   
Dries Buytaert committed
244
      }
Kjartan Mannes's avatar
Kjartan Mannes committed
245
    }
Dries Buytaert's avatar
 
Dries Buytaert committed
246
  }
Dries Buytaert's avatar
   
Dries Buytaert committed
247

Dries Buytaert's avatar
   
Dries Buytaert committed
248
249
  cache_clear_all();

Dries Buytaert's avatar
   
Dries Buytaert committed
250
  drupal_set_message($message);
Dries Buytaert's avatar
   
Dries Buytaert committed
251
  return $edit;
Kjartan Mannes's avatar
Kjartan Mannes committed
252
}
Dries Buytaert's avatar
 
Dries Buytaert committed
253

Kjartan Mannes's avatar
Kjartan Mannes committed
254
function taxonomy_del_term($tid) {
Dries Buytaert's avatar
   
Dries Buytaert committed
255
256
  $term = taxonomy_get_term($tid);

Dries Buytaert's avatar
   
Dries Buytaert committed
257
258
259
260
261
  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
262

Dries Buytaert's avatar
   
Dries Buytaert committed
263
  module_invoke_all('taxonomy', 'delete', 'term', $term);
Dries Buytaert's avatar
   
Dries Buytaert committed
264

Dries Buytaert's avatar
   
Dries Buytaert committed
265
266
  cache_clear_all();

Dries Buytaert's avatar
   
Dries Buytaert committed
267
  return t('deleted term "%name".', array('%name' => $term->name));
Dries Buytaert's avatar
   
Dries Buytaert committed
268
269
270
271
272
}

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

Dries Buytaert's avatar
   
Dries Buytaert committed
273
274
275
276
277
  $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
278

Dries Buytaert's avatar
   
Dries Buytaert committed
279
  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
280
}
Dries Buytaert's avatar
 
Dries Buytaert committed
281

Dries Buytaert's avatar
   
Dries Buytaert committed
282
283
284
/**
 * Generate a tabular listing of administrative functions for vocabularies.
 */
Kjartan Mannes's avatar
Kjartan Mannes committed
285
function taxonomy_overview() {
Dries Buytaert's avatar
   
Dries Buytaert committed
286
  $header = array(t('name'), t('node types'), array('data' => t('operations'), 'colspan' => 3));
Dries Buytaert's avatar
   
Dries Buytaert committed
287

Kjartan Mannes's avatar
Kjartan Mannes committed
288
  $vocabularies = taxonomy_get_vocabularies();
Dries Buytaert's avatar
   
Dries Buytaert committed
289

Kjartan Mannes's avatar
Kjartan Mannes committed
290
291
  foreach ($vocabularies as $vocabulary) {
    $links = array();
Dries Buytaert's avatar
   
Dries Buytaert committed
292
    $types = array();
Dries Buytaert's avatar
   
Dries Buytaert committed
293
294
    foreach(explode(',', $vocabulary->nodes) as $type) {
      $types[] = node_invoke($type, 'node_name');
Dries Buytaert's avatar
   
Dries Buytaert committed
295
    }
Dries Buytaert's avatar
   
Dries Buytaert committed
296
    $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
297

Dries Buytaert's avatar
   
Dries Buytaert committed
298
    $tree = taxonomy_get_tree($vocabulary->vid);
Kjartan Mannes's avatar
Kjartan Mannes committed
299
    if ($tree) {
Dries Buytaert's avatar
   
Dries Buytaert committed
300
      unset($data);
Kjartan Mannes's avatar
Kjartan Mannes committed
301
      foreach ($tree as $term) {
Dries Buytaert's avatar
   
Dries Buytaert committed
302
        $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
303
      }
Dries Buytaert's avatar
   
Dries Buytaert committed
304
      $rows[] = array(array('data' => $data, 'colspan' => 5));
Dries Buytaert's avatar
 
Dries Buytaert committed
305
306
307
    }
  }

Dries Buytaert's avatar
   
Dries Buytaert committed
308
  return theme('table', $header, $rows);
Kjartan Mannes's avatar
Kjartan Mannes committed
309
310
}

Dries Buytaert's avatar
   
Dries Buytaert committed
311
312
313
/**
 * Generate a form element for selecting terms from a vocabulary.
 */
Dries Buytaert's avatar
   
Dries Buytaert committed
314
function taxonomy_form($vid, $value = 0, $help = NULL, $name = 'taxonomy') {
Dries Buytaert's avatar
   
Dries Buytaert committed
315
  $vocabulary = taxonomy_get_vocabulary($vid);
316
  $help = ($help) ? $help : $vocabulary->help;
Kjartan Mannes's avatar
Kjartan Mannes committed
317
318
319
320
  if ($vocabulary->required) {
    $blank = 0;
  }
  else {
Dries Buytaert's avatar
   
Dries Buytaert committed
321
    $blank = '<'. t('none') .'>';
Kjartan Mannes's avatar
Kjartan Mannes committed
322
  }
Dries Buytaert's avatar
   
Dries Buytaert committed
323

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

Dries Buytaert's avatar
   
Dries Buytaert committed
327
328
329
330
331
332
333
/**
 * 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
334
  if ($type) {
Dries Buytaert's avatar
   
Dries Buytaert committed
335
    $result = db_query("SELECT * FROM {vocabulary} WHERE nodes LIKE '%%%s%%' ORDER BY weight, name", $type);
Kjartan Mannes's avatar
Kjartan Mannes committed
336
337
  }
  else {
Dries Buytaert's avatar
   
Dries Buytaert committed
338
    $result = db_query('SELECT * FROM {vocabulary} ORDER BY weight, name');
Kjartan Mannes's avatar
Kjartan Mannes committed
339
340
341
342
  }
  $vocabularies = array();
  while ($voc = db_fetch_object($result)) {
    $vocabularies[$voc->$key] = $voc;
Dries Buytaert's avatar
 
Dries Buytaert committed
343
  }
Dries Buytaert's avatar
   
Dries Buytaert committed
344

Kjartan Mannes's avatar
Kjartan Mannes committed
345
346
  return $vocabularies;
}
Dries Buytaert's avatar
 
Dries Buytaert committed
347

Dries Buytaert's avatar
   
Dries Buytaert committed
348
349
350
/**
 * Generate a form for selecting terms to associate with a node.
 */
Dries Buytaert's avatar
   
Dries Buytaert committed
351
function taxonomy_node_form($type, $node = '', $help = NULL, $name = 'taxonomy') {
Kjartan Mannes's avatar
Kjartan Mannes committed
352
353
354
  if (!$node->taxonomy) {
    if ($node->nid) {
      $terms = array_keys(taxonomy_node_get_terms($node->nid));
Kjartan Mannes's avatar
Kjartan Mannes committed
355
356
    }
    else {
Kjartan Mannes's avatar
Kjartan Mannes committed
357
      $terms = 0;
Dries Buytaert's avatar
 
Dries Buytaert committed
358
    }
Kjartan Mannes's avatar
Kjartan Mannes committed
359
360
361
362
  }
  else {
    $terms = $node->taxonomy;
  }
Dries Buytaert's avatar
 
Dries Buytaert committed
363

Dries Buytaert's avatar
   
Dries Buytaert committed
364
  $c = db_query("SELECT * FROM {vocabulary} WHERE nodes LIKE '%%%s%%' ORDER BY weight, name", $type);
Kjartan Mannes's avatar
Kjartan Mannes committed
365
  while ($vocabulary = db_fetch_object($c)) {
Dries Buytaert's avatar
   
Dries Buytaert committed
366
    $result[] = taxonomy_form($vocabulary->vid, $terms, $help, $name);
Dries Buytaert's avatar
 
Dries Buytaert committed
367
  }
Kjartan Mannes's avatar
Kjartan Mannes committed
368
369
  return $result ? $result : array();
}
Dries Buytaert's avatar
 
Dries Buytaert committed
370

Dries Buytaert's avatar
   
Dries Buytaert committed
371
372
373
/**
 * Determine whether a node mentions the name of a term.
 */
Kjartan Mannes's avatar
Kjartan Mannes committed
374
function taxonomy_node_has_term($nid, $tid) {
Dries Buytaert's avatar
   
Dries Buytaert committed
375
  $term_name = db_result(db_query('SELECT name FROM {term_data} WHERE tid = %d', $tid));
Dries Buytaert's avatar
 
Dries Buytaert committed
376

Dries Buytaert's avatar
   
Dries Buytaert committed
377
  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
378
379
}

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

Dries Buytaert's avatar
   
Dries Buytaert committed
392
393
394
395
/**
 * Find all terms associated to the given node.
 */
function taxonomy_node_get_terms($nid, $key = 'tid') {
Kjartan Mannes's avatar
Kjartan Mannes committed
396
  static $terms;
Dries Buytaert's avatar
 
Dries Buytaert committed
397

Dries Buytaert's avatar
   
Dries Buytaert committed
398
  if (!isset($terms[$nid])) {
Dries Buytaert's avatar
   
Dries Buytaert committed
399
    $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
400
    $terms[$nid] = array();
Dries Buytaert's avatar
 
Dries Buytaert committed
401
    while ($term = db_fetch_object($result)) {
Kjartan Mannes's avatar
Kjartan Mannes committed
402
      $terms[$nid][$term->$key] = $term;
Dries Buytaert's avatar
 
Dries Buytaert committed
403
404
    }
  }
Kjartan Mannes's avatar
Kjartan Mannes committed
405
406
  return $terms[$nid];
}
Dries Buytaert's avatar
 
Dries Buytaert committed
407

Dries Buytaert's avatar
   
Dries Buytaert committed
408
409
410
/**
 * Save term associations for a given node.
 */
Kjartan Mannes's avatar
Kjartan Mannes committed
411
412
function taxonomy_node_save($nid, $terms) {
  taxonomy_node_delete($nid);
Dries Buytaert's avatar
 
Dries Buytaert committed
413

Kjartan Mannes's avatar
Kjartan Mannes committed
414
  if ($terms) {
Dries Buytaert's avatar
   
Dries Buytaert committed
415
    foreach ($terms as $term) {
416
      if ($term) {
Dries Buytaert's avatar
   
Dries Buytaert committed
417
        db_query('INSERT INTO {term_node} (nid, tid) VALUES (%d, %d)', $nid, $term);
418
      }
Dries Buytaert's avatar
 
Dries Buytaert committed
419
420
    }
  }
Kjartan Mannes's avatar
Kjartan Mannes committed
421
}
Dries Buytaert's avatar
 
Dries Buytaert committed
422

Dries Buytaert's avatar
   
Dries Buytaert committed
423
424
425
/**
 * Remove associations of a node to its terms.
 */
Kjartan Mannes's avatar
Kjartan Mannes committed
426
function taxonomy_node_delete($nid) {
Dries Buytaert's avatar
   
Dries Buytaert committed
427
  db_query('DELETE FROM {term_node} WHERE nid = %d', $nid);
Kjartan Mannes's avatar
Kjartan Mannes committed
428
}
Dries Buytaert's avatar
 
Dries Buytaert committed
429

Dries Buytaert's avatar
   
Dries Buytaert committed
430
431
432
433
/**
 * Find all term objects related to a given term ID.
 */
function taxonomy_get_related($tid, $key = 'tid') {
Kjartan Mannes's avatar
Kjartan Mannes committed
434
  if ($tid) {
Dries Buytaert's avatar
   
Dries Buytaert committed
435
    $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
436
437
438
    $related = array();
    while ($term = db_fetch_object($result)) {
      $related[$term->$key] = $term;
Dries Buytaert's avatar
 
Dries Buytaert committed
439
    }
Kjartan Mannes's avatar
Kjartan Mannes committed
440
    return $related;
Dries Buytaert's avatar
 
Dries Buytaert committed
441
  }
Kjartan Mannes's avatar
Kjartan Mannes committed
442
443
  else {
    return array();
Dries Buytaert's avatar
 
Dries Buytaert committed
444
  }
Kjartan Mannes's avatar
Kjartan Mannes committed
445
}
Dries Buytaert's avatar
 
Dries Buytaert committed
446

Dries Buytaert's avatar
   
Dries Buytaert committed
447
448
449
450
/**
 * Find all parents of a given term ID.
 */
function taxonomy_get_parents($tid, $key = 'tid') {
Kjartan Mannes's avatar
Kjartan Mannes committed
451
  if ($tid) {
Dries Buytaert's avatar
   
Dries Buytaert committed
452
    $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
453
454
455
    $parents = array();
    while ($parent = db_fetch_object($result)) {
      $parents[$parent->$key] = $parent;
Dries Buytaert's avatar
   
Dries Buytaert committed
456
    }
Kjartan Mannes's avatar
Kjartan Mannes committed
457
    return $parents;
Dries Buytaert's avatar
 
Dries Buytaert committed
458
  }
Kjartan Mannes's avatar
Kjartan Mannes committed
459
460
461
462
  else {
    return array();
  }
}
Dries Buytaert's avatar
 
Dries Buytaert committed
463

Dries Buytaert's avatar
   
Dries Buytaert committed
464
465
466
467
/**
 * Find all ancestors of a given term ID.
 */
function taxonomy_get_parents_all($tid) {
Dries Buytaert's avatar
   
Dries Buytaert committed
468
469
470
471
472
473
474
475
476
477
478
479
  $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
480
481
482
483
/**
 * Find all children of a term ID.
 */
function taxonomy_get_children($tid, $vid = 0, $key = 'tid') {
Kjartan Mannes's avatar
Kjartan Mannes committed
484
  if ($vid) {
Dries Buytaert's avatar
   
Dries Buytaert committed
485
    $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
486
  }
Kjartan Mannes's avatar
Kjartan Mannes committed
487
  else {
Dries Buytaert's avatar
   
Dries Buytaert committed
488
    $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
489
490
491
492
493
494
495
  }
  $children = array();
  while ($term = db_fetch_object($result)) {
    $children[$term->$key] = $term;
  }
  return $children;
}
Dries Buytaert's avatar
 
Dries Buytaert committed
496

Dries Buytaert's avatar
   
Dries Buytaert committed
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
/**
 * 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
515
  static $children, $parents, $terms;
Dries Buytaert's avatar
   
Dries Buytaert committed
516

Kjartan Mannes's avatar
Kjartan Mannes committed
517
  $depth++;
Dries Buytaert's avatar
   
Dries Buytaert committed
518

Dries Buytaert's avatar
   
Dries Buytaert committed
519
520
521
522
  // 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
523

Dries Buytaert's avatar
   
Dries Buytaert committed
524
    $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
525
    while ($term = db_fetch_object($result)) {
Dries Buytaert's avatar
   
Dries Buytaert committed
526
527
528
      $children[$vid][$term->parent][] = $term->tid;
      $parents[$vid][$term->tid][] = $term->parent;
      $terms[$vid][$term->tid] = $term;
Dries Buytaert's avatar
 
Dries Buytaert committed
529
530
    }
  }
Dries Buytaert's avatar
   
Dries Buytaert committed
531

Dries Buytaert's avatar
   
Dries Buytaert committed
532
533
534
  $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
535
      if ($max_depth > $depth) {
Dries Buytaert's avatar
   
Dries Buytaert committed
536
537
538
539
540
        $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
541

Dries Buytaert's avatar
   
Dries Buytaert committed
542
        $tree = array_merge($tree, taxonomy_get_tree($vid, $child, $depth, $max_depth));
Dries Buytaert's avatar
   
Dries Buytaert committed
543
      }
Dries Buytaert's avatar
   
Dries Buytaert committed
544
    }
Kjartan Mannes's avatar
Kjartan Mannes committed
545
  }
Dries Buytaert's avatar
   
Dries Buytaert committed
546

Dries Buytaert's avatar
   
Dries Buytaert committed
547
  return $tree ? $tree : array();
Kjartan Mannes's avatar
Kjartan Mannes committed
548
}
Dries Buytaert's avatar
 
Dries Buytaert committed
549

Dries Buytaert's avatar
   
Dries Buytaert committed
550
551
552
/**
 * Return an array of synonyms of the given term ID.
 */
Kjartan Mannes's avatar
Kjartan Mannes committed
553
554
function taxonomy_get_synonyms($tid) {
  if ($tid) {
Dries Buytaert's avatar
   
Dries Buytaert committed
555
    $result = db_query('SELECT name FROM {term_synonym} WHERE tid = %d', $tid);
Kjartan Mannes's avatar
Kjartan Mannes committed
556
    while ($synonym = db_fetch_array($result)) {
Dries Buytaert's avatar
   
Dries Buytaert committed
557
      $synonyms[] = $synonym['name'];
Dries Buytaert's avatar
 
Dries Buytaert committed
558
    }
Kjartan Mannes's avatar
Kjartan Mannes committed
559
    return $synonyms ? $synonyms : array();
Dries Buytaert's avatar
 
Dries Buytaert committed
560
  }
Kjartan Mannes's avatar
Kjartan Mannes committed
561
562
  else {
    return array();
Dries Buytaert's avatar
   
Dries Buytaert committed
563
  }
Kjartan Mannes's avatar
Kjartan Mannes committed
564
}
Dries Buytaert's avatar
   
Dries Buytaert committed
565

Dries Buytaert's avatar
   
Dries Buytaert committed
566
567
568
569
570
/**
 * 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
571
}
Dries Buytaert's avatar
   
Dries Buytaert committed
572

Dries Buytaert's avatar
   
Dries Buytaert committed
573
574
575
/**
 * Given a term id, count the number of published nodes in it.
 */
Dries Buytaert's avatar
   
Dries Buytaert committed
576
function taxonomy_term_count_nodes($tid, $type = 0) {
Kjartan Mannes's avatar
Kjartan Mannes committed
577
  static $count;
Dries Buytaert's avatar
   
Dries Buytaert committed
578

Dries Buytaert's avatar
   
Dries Buytaert committed
579
580
581
  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
582
      $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
583
584
    }
    else {
Dries Buytaert's avatar
   
Dries Buytaert committed
585
      $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
586
    }
Kjartan Mannes's avatar
Kjartan Mannes committed
587
    while ($term = db_fetch_object($result)) {
Dries Buytaert's avatar
   
Dries Buytaert committed
588
      $count[$type][$term->tid] = $term->c;
Dries Buytaert's avatar
   
Dries Buytaert committed
589
590
591
    }
  }

Kjartan Mannes's avatar
Kjartan Mannes committed
592
  foreach (_taxonomy_term_children($tid) as $c) {
Dries Buytaert's avatar
   
Dries Buytaert committed
593
    $children_count += taxonomy_term_count_nodes($c, $type);
Kjartan Mannes's avatar
Kjartan Mannes committed
594
  }
Dries Buytaert's avatar
   
Dries Buytaert committed
595
  return $count[$type][$tid] + $children_count;
Kjartan Mannes's avatar
Kjartan Mannes committed
596
597
}

Dries Buytaert's avatar
   
Dries Buytaert committed
598
599
600
/**
 * Helper for taxonomy_term_count_nodes().
 */
Kjartan Mannes's avatar
Kjartan Mannes committed
601
602
function _taxonomy_term_children($tid) {
  static $children;
Dries Buytaert's avatar
   
Dries Buytaert committed
603

Dries Buytaert's avatar
   
Dries Buytaert committed
604
  if (!isset($children)) {
Dries Buytaert's avatar
   
Dries Buytaert committed
605
    $result = db_query('SELECT tid, parent FROM {term_hierarchy}');
Kjartan Mannes's avatar
Kjartan Mannes committed
606
607
    while ($term = db_fetch_object($result)) {
      $children[$term->parent][] = $term->tid;
Dries Buytaert's avatar
   
Dries Buytaert committed
608
    }
Dries Buytaert's avatar
 
Dries Buytaert committed
609
  }
Kjartan Mannes's avatar
Kjartan Mannes committed
610
611
  return $children[$tid] ? $children[$tid] : array();
}
Dries Buytaert's avatar
 
Dries Buytaert committed
612

Dries Buytaert's avatar
   
Dries Buytaert committed
613
/**
Dries Buytaert's avatar
   
Dries Buytaert committed
614
615
616
617
618
619
620
 * 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
621
 *
Dries Buytaert's avatar
   
Dries Buytaert committed
622
623
 * @return
 *   An array of matching vocabulary objects.
Dries Buytaert's avatar
   
Dries Buytaert committed
624
625
 */
function taxonomy_get_vocabulary_by_name($name) {
Dries Buytaert's avatar
   
Dries Buytaert committed
626
  $db_result = db_query("SELECT * FROM {vocabulary} WHERE LOWER('%s') LIKE LOWER(name)", trim($name));
Dries Buytaert's avatar
   
Dries Buytaert committed
627
628
629
630
631
632
633
634
635
  $result = array();
  while ($vocabulary = db_fetch_object($db_result)) {
    $result[] = $vocabulary;
  }

  return $result;
}

/**
Dries Buytaert's avatar
   
Dries Buytaert committed
636
 * Try to map a string to an existing term, as for glossary use.
Dries Buytaert's avatar
   
Dries Buytaert committed
637
 *
Dries Buytaert's avatar
   
Dries Buytaert committed
638
639
640
641
642
643
644
645
 * 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
646
647
 */
function taxonomy_get_term_by_name($name) {
Dries Buytaert's avatar
   
Dries Buytaert committed
648
  $db_result = db_query("SELECT * FROM {term_data} WHERE LOWER('%s') LIKE LOWER(name)", trim($name));
Dries Buytaert's avatar
   
Dries Buytaert committed
649
650
651
652
653
654
655
656
  $result = array();
  while ($term = db_fetch_object($db_result)) {
    $result[] = $term;
  }

  return $result;
}

Dries Buytaert's avatar
   
Dries Buytaert committed
657
658
659
/**
 * Return the vocabulary object matching a vocabulary ID.
 */
Kjartan Mannes's avatar
Kjartan Mannes committed
660
function taxonomy_get_vocabulary($vid) {
Dries Buytaert's avatar
   
Dries Buytaert committed
661
  return db_fetch_object(db_query('SELECT * FROM {vocabulary} WHERE vid = %d', $vid));
Kjartan Mannes's avatar
Kjartan Mannes committed
662
}
Dries Buytaert's avatar
 
Dries Buytaert committed
663

Dries Buytaert's avatar
   
Dries Buytaert committed
664
665
666
/**
 * Return the term object matching a term ID.
 */
Kjartan Mannes's avatar
Kjartan Mannes committed
667
668
function taxonomy_get_term($tid) {
  // simple cache using a static var?
Dries Buytaert's avatar
   
Dries Buytaert committed
669
  return db_fetch_object(db_query('SELECT * FROM {term_data} WHERE tid = %d', $tid));
Kjartan Mannes's avatar
Kjartan Mannes committed
670
}
Dries Buytaert's avatar
 
Dries Buytaert committed
671

Kjartan Mannes's avatar
Kjartan Mannes committed
672
function _taxonomy_term_select($title, $name, $value, $vocabulary_id, $description, $multiple, $blank, $exclude = array()) {
Dries Buytaert's avatar
   
Dries Buytaert committed
673
  $tree = taxonomy_get_tree($vocabulary_id);
Dries Buytaert's avatar
Dries Buytaert committed
674
675
676
  if ($blank) {
    $options[] = array('tid' => 0, 'name' => $blank);
  }
Kjartan Mannes's avatar
Kjartan Mannes committed
677
678
679
  if ($tree) {
    foreach ($tree as $term) {
      if (!in_array($term->tid, $exclude)) {
Dries Buytaert's avatar
   
Dries Buytaert committed
680
        $options[] = array('tid' => $term->tid, 'name' => _taxonomy_depth($term->depth, '-').$term->name);
Dries Buytaert's avatar
 
Dries Buytaert committed
681
682
      }
    }
Kjartan Mannes's avatar
Kjartan Mannes committed
683
684
685
686
687
    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
688

Kjartan Mannes's avatar
Kjartan Mannes committed
689
  if (count($options) > 0) {
Dries Buytaert's avatar
   
Dries Buytaert committed
690
    foreach ($options as $option) {
Dries Buytaert's avatar
   
Dries Buytaert committed
691
      $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
692
    }
Dries Buytaert's avatar
 
Dries Buytaert committed
693

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

Dries Buytaert's avatar
   
Dries Buytaert committed
696
    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
697
  }
Kjartan Mannes's avatar
Kjartan Mannes committed
698
}
Dries Buytaert's avatar
 
Dries Buytaert committed
699

Kjartan Mannes's avatar
Kjartan Mannes committed
700
701
702
function _taxonomy_depth($depth, $graphic = '--') {
  for ($n = 0; $n < $depth; $n++) {
    $result .= $graphic;
Dries Buytaert's avatar
 
Dries Buytaert committed
703
  }
Kjartan Mannes's avatar
Kjartan Mannes committed
704
705
  return $result;
}
Dries Buytaert's avatar
 
Dries Buytaert committed
706

Kjartan Mannes's avatar
Kjartan Mannes committed
707
708
709
function _prepare_update($data) {
  foreach ($data as $key => $value) {
    $q[] = "$key = '". check_query($value) ."'";
Dries Buytaert's avatar
 
Dries Buytaert committed
710
  }
Dries Buytaert's avatar
   
Dries Buytaert committed
711
  $result = implode(', ', $q);
Kjartan Mannes's avatar
Kjartan Mannes committed
712
713
  return $result;
}
Dries Buytaert's avatar
 
Dries Buytaert committed
714

Kjartan Mannes's avatar
Kjartan Mannes committed
715
716
function _prepare_insert($data, $stage) {
  if ($stage == 1) {
Dries Buytaert's avatar
   
Dries Buytaert committed
717
    $result = implode(', ', array_keys($data));
Kjartan Mannes's avatar
Kjartan Mannes committed
718
719
720
721
  }
  else {
    foreach (array_values($data) as $value) {
      $q[] = "'". check_query($value) ."'";
Dries Buytaert's avatar
 
Dries Buytaert committed
722
    }
Dries Buytaert's avatar
   
Dries Buytaert committed
723
    $result = implode(', ', $q);
Dries Buytaert's avatar
 
Dries Buytaert committed
724
  }
Kjartan Mannes's avatar
Kjartan Mannes committed
725
726
  return "($result)";
}
Dries Buytaert's avatar
   
Dries Buytaert committed
727

Dries Buytaert's avatar
   
Dries Buytaert committed
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
/**
 * 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) {
747
  if ($taxonomy->str_tids) {
Dries Buytaert's avatar
   
Dries Buytaert committed
748
    if ($taxonomy->operator == 'or') {
Dries Buytaert's avatar
   
Dries Buytaert committed
749
      $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
750
      $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";
751
752
    }
    else {
Dries Buytaert's avatar
   
Dries Buytaert committed
753
      $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
754

755
      // Special trick as we could not find anything better:
Dries Buytaert's avatar
   
Dries Buytaert committed
756
      $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)));
757
758
      $sql_count = "SELECT $count";
    }
Dries Buytaert's avatar
   
Dries Buytaert committed
759

760
    if ($pager) {
Dries Buytaert's avatar
   
Dries Buytaert committed
761
      $result = pager_query($sql, variable_get('default_nodes_main', 10) , 0, $sql_count);
762
763
764
765
    }
    else {
      $result = db_query_range($sql, 0, 15);
    }
Dries Buytaert's avatar
   
Dries Buytaert committed
766
767
768
769
770
  }

  return $result;
}

Dries Buytaert's avatar
   
Dries Buytaert committed
771
772
773
/**
 * 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
774
775
776
777
*/
function taxonomy_render_nodes($result) {

  while ($node = db_fetch_object($result)) {
Dries Buytaert's avatar
   
Dries Buytaert committed
778
    $output .= node_view(node_load(array('nid' => $node->nid, 'type' => $node->type)), 1);
Dries Buytaert's avatar
   
Dries Buytaert committed
779
  }
Dries Buytaert's avatar
   
Dries Buytaert committed
780
  $output .= theme('pager', NULL, variable_get('default_nodes_main', 10), 0);
Dries Buytaert's avatar
   
Dries Buytaert committed
781
  return $output;
Dries Buytaert's avatar
   
Dries Buytaert committed
782
783
}

Dries Buytaert's avatar
   
Dries Buytaert committed
784
785
786
/**
 * Implementation of hook_nodeapi().
 */
Dries Buytaert's avatar
   
Dries Buytaert committed
787
788
function taxonomy_nodeapi($node, $op, $arg = 0) {
  switch ($op) {
Dries Buytaert's avatar
   
Dries Buytaert committed
789
    case 'insert':
Dries Buytaert's avatar
   
Dries Buytaert committed
790
791
      taxonomy_node_save($node->nid, $node->taxonomy);
      break;
Dries Buytaert's avatar
   
Dries Buytaert committed
792
    case 'update':
Dries Buytaert's avatar
   
Dries Buytaert committed
793
794
      taxonomy_node_save($node->nid, $node->taxonomy);
      break;
Dries Buytaert's avatar
   
Dries Buytaert committed
795
    case 'delete':
Dries Buytaert's avatar
   
Dries Buytaert committed
796
797
798
799
800
      taxonomy_node_delete($node->nid);
      break;
  }
}

Kjartan Mannes's avatar
Kjartan Mannes committed
801
function taxonomy_page() {
Dries Buytaert's avatar
   
Dries Buytaert committed
802

Dries Buytaert's avatar
   
Dries Buytaert committed
803
804
  $taxonomy->operator = arg(2);
  $taxonomy->str_tids = check_query(arg(3));
Dries Buytaert's avatar
   
Dries Buytaert committed
805
  $taxonomy->tids = explode(',', $taxonomy->str_tids);
Dries Buytaert's avatar
   
Dries Buytaert committed
806

Dries Buytaert's avatar
   
Dries Buytaert committed
807
  if (ereg('^([0-9]+,){0,}[0-9]+$', $taxonomy->str_tids)) {
Dries Buytaert's avatar
   
Dries Buytaert committed
808
    switch (arg(1)) {
Dries Buytaert's avatar
   
Dries Buytaert committed
809
      case 'feed':
Dries Buytaert's avatar
   
Dries Buytaert committed
810
        taxonomy_feed($taxonomy);
Kjartan Mannes's avatar
Kjartan Mannes committed
811
      break;
Dries Buytaert's avatar
   
Dries Buytaert committed
812
      default:
Dries Buytaert's avatar
   
Dries Buytaert committed
813
      // Build title:
814
      $sql = 'SELECT name FROM {term_data} WHERE tid IN (%s)';
Dries Buytaert's avatar
   
Dries Buytaert committed
815
      $result = db_query($sql, $taxonomy->str_tids);
Kjartan Mannes's avatar
Kjartan Mannes committed
816
      $names = array();
Dries Buytaert's avatar
   
Dries Buytaert committed
817
818
819
      while ($term = db_fetch_object($result)) {
        $names[] = $term->name;
      }
Dries Buytaert's avatar
   
Dries Buytaert committed
820
821
822

      // Build breadcrumb based on first hierarchy of first term:
      $current->tid = $taxonomy->tids[0];
Dries Buytaert's avatar
   
Dries Buytaert committed
823
      $breadcrumbs = array(array('path' => $_GET['q']));
Dries Buytaert's avatar
   
Dries Buytaert committed
824
825
      while ($parents = taxonomy_get_parents($current->tid)) {
        $current = array_shift($parents);
Dries Buytaert's avatar
   
Dries Buytaert committed
826
        $breadcrumbs[] = array('path' => 'taxonomy/view/or/'. $current->tid, 'title' => $current->name);
Dries Buytaert's avatar
   
Dries Buytaert committed
827
828
      }
      $breadcrumbs = array_reverse($breadcrumbs);
Dries Buytaert's avatar
   
Dries Buytaert committed
829
      menu_set_location($breadcrumbs);
Dries Buytaert's avatar
   
Dries Buytaert committed
830

Dries Buytaert's avatar
   
Dries Buytaert committed
831
      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
832

Dries Buytaert's avatar
   
Dries Buytaert committed
833
      $output = taxonomy_render_nodes(taxonomy_select_nodes($taxonomy));
Dries Buytaert's avatar
   
Dries Buytaert committed
834
      print theme('page', $output, implode(', ', $names));
Dries Buytaert's avatar
   
Dries Buytaert committed
835
      break;
Dries Buytaert's avatar
   
Dries Buytaert committed
836
837
838
839
    }
  }
  else {
    drupal_not_found();
Dries Buytaert's avatar
   
Dries Buytaert committed
840
  }
Kjartan Mannes's avatar
Kjartan Mannes committed
841
}
Dries Buytaert's avatar
   
Dries Buytaert committed
842

Dries Buytaert's avatar
   
Dries Buytaert committed
843
844
845
/**
 * Menu callback; dispatches to the proper taxonomy administration function.
 */
Kjartan Mannes's avatar
Kjartan Mannes committed
846
function taxonomy_admin() {
Dries Buytaert's avatar
   
Dries Buytaert committed
847
848
  $op = $_POST['op'];
  $edit = $_POST['edit'];
Kjartan Mannes's avatar
Kjartan Mannes committed
849

Dries Buytaert's avatar
   
Dries Buytaert committed
850
851
852
  if (empty($op)) {
    $op = arg(2);
  }
Dries Buytaert's avatar
   
Dries Buytaert committed
853

Dries Buytaert's avatar
   
Dries Buytaert committed
854
  switch ($op) {
Dries Buytaert's avatar
   
Dries Buytaert committed
855
856
    case 'add':
      if (arg(3) == 'vocabulary') {
Dries Buytaert's avatar
   
Dries Buytaert committed
857
858
        $output .= taxonomy_form_vocabulary();
      }
Dries Buytaert's avatar
   
Dries Buytaert committed
859
      else if (arg(3) == 'term') {
Dries Buytaert's avatar
   
Dries Buytaert committed
860
861
862
        $output .= taxonomy_form_term();
      }
      break;
Dries Buytaert's avatar
   
Dries Buytaert committed
863
864
    case 'edit':
      if (arg(3) == 'vocabulary') {
Dries Buytaert's avatar
   
Dries Buytaert committed
865
866
        $output .= taxonomy_form_vocabulary(object2array(taxonomy_get_vocabulary(arg(4))));
      }
Dries Buytaert's avatar
   
Dries Buytaert committed
867
      else if (arg(3) == 'term') {
Dries Buytaert's avatar
   
Dries Buytaert committed
868
869
870
        $output .= taxonomy_form_term(object2array(taxonomy_get_term(arg(4))));
      }
      break;
Dries Buytaert's avatar
   
Dries Buytaert committed
871
    case 'preview':
Dries Buytaert's avatar