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

Dries's avatar
 
Dries committed
4 5 6 7 8
/**
 * @file
 * Enables the organization of content into categories.
 */

Dries's avatar
 
Dries committed
9 10 11
/**
 * Implementation of hook_perm().
 */
Kjartan's avatar
Kjartan committed
12
function taxonomy_perm() {
Dries's avatar
 
Dries committed
13
  return array('administer taxonomy');
Kjartan's avatar
Kjartan committed
14
}
Dries's avatar
 
Dries committed
15

Dries's avatar
 
Dries committed
16 17 18 19 20 21 22 23 24 25 26
/**
 * 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's avatar
 
Dries committed
27
function taxonomy_link($type, $node = NULL) {
Dries's avatar
 
Dries committed
28
  if ($type == 'taxonomy terms' && $node != NULL) {
Kjartan's avatar
 
Kjartan committed
29
    $links = array();
Dries's avatar
 
Dries committed
30
    if (array_key_exists('taxonomy', $node)) {
Dries's avatar
 
Dries committed
31 32
      foreach ($node->taxonomy as $tid) {
        $term = taxonomy_get_term($tid);
33
        $links[] = l($term->name, taxonomy_term_path($term), array('rel' => 'tag', 'title' => $term->description));
Dries's avatar
 
Dries committed
34 35 36 37
      }
    }
    else {
      foreach (taxonomy_node_get_terms($node->nid) as $term) {
38
        $links[] = l($term->name, taxonomy_term_path($term), array('rel' => 'tag', 'title' => $term->description));
Dries's avatar
 
Dries committed
39
      }
Dries's avatar
 
Dries committed
40 41 42
    }
    return $links;
  }
Kjartan's avatar
Kjartan committed
43 44
}

45 46 47 48 49 50 51 52
function taxonomy_term_path($term) {
  $vocabulary = taxonomy_get_vocabulary($term->vid);
  if ($vocabulary->module != 'taxonomy' && $path = module_invoke($vocabulary->module, 'term_path', $term)) {
    return $path;
  }
  return 'taxonomy/term/'. $term->tid;
}

Dries's avatar
 
Dries committed
53 54 55
/**
 * Implementation of hook_menu().
 */
Dries's avatar
 
Dries committed
56
function taxonomy_menu($may_cache) {
Dries's avatar
 
Dries committed
57
  $items = array();
Dries's avatar
 
Dries committed
58

Dries's avatar
 
Dries committed
59 60 61 62
  if ($may_cache) {
    $items[] = array('path' => 'admin/taxonomy', 'title' => t('categories'),
      'callback' => 'taxonomy_admin',
      'access' => user_access('administer taxonomy'));
63

Dries's avatar
 
Dries committed
64 65
    $items[] = array('path' => 'admin/taxonomy/list', 'title' => t('list'),
      'type' => MENU_DEFAULT_LOCAL_TASK, 'weight' => -10);
66

Dries's avatar
 
Dries committed
67 68 69 70 71
    $items[] = array('path' => 'admin/taxonomy/add/vocabulary', 'title' => t('add vocabulary'),
      'callback' => 'taxonomy_admin',
      'access' => user_access('administer taxonomy'),
      'type' => MENU_LOCAL_TASK);

72 73 74 75 76 77 78 79 80 81 82 83 84 85 86
    $items[] = array('path' => 'admin/taxonomy/edit/vocabulary', 'title' => t('edit vocabulary'),
      'callback' => 'taxonomy_admin',
      'access' => user_access('administer taxonomy'),
      'type' => MENU_CALLBACK);

    $items[] = array('path' => 'admin/taxonomy/add/term', 'title' => t('add term'),
      'callback' => 'taxonomy_admin',
      'access' => user_access('administer taxonomy'),
      'type' => MENU_CALLBACK);

    $items[] = array('path' => 'admin/taxonomy/edit/term', 'title' => t('edit term'),
      'callback' => 'taxonomy_admin',
      'access' => user_access('administer taxonomy'),
      'type' => MENU_CALLBACK);

Dries's avatar
 
Dries committed
87 88 89 90
    $items[] = array('path' => 'taxonomy/term', 'title' => t('taxonomy term'),
      'callback' => 'taxonomy_term_page',
      'access' => user_access('access content'),
      'type' => MENU_CALLBACK);
Steven Wittens's avatar
Steven Wittens committed
91 92 93 94 95

    $items[] = array('path' => 'taxonomy/autocomplete', 'title' => t('autocomplete taxonomy'),
      'callback' => 'taxonomy_autocomplete',
      'access' => user_access('access content'),
      'type' => MENU_CALLBACK);
Dries's avatar
 
Dries committed
96
  }
Dries's avatar
Dries committed
97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112
  else {
    if (is_numeric(arg(2))) {
      $items[] = array('path' => 'admin/taxonomy/' . arg(2), 'title' => t('add term'),
        'callback' => 'taxonomy_admin',
        'access' => user_access('administer taxonomy'),
        'type' => MENU_CALLBACK);

      $items[] = array('path' => 'admin/taxonomy/' . arg(2) . '/list', 'title' => t('list'),
        'type' => MENU_DEFAULT_LOCAL_TASK, 'weight' => -10);

      $items[] = array('path' => 'admin/taxonomy/' . arg(2) . '/add/term', 'title' => t('add term'),
        'callback' => 'taxonomy_admin',
        'access' => user_access('administer taxonomy'),
        'type' => MENU_LOCAL_TASK);
    }
  }
Dries's avatar
 
Dries committed
113

Dries's avatar
 
Dries committed
114 115
  return $items;
}
Dries's avatar
 
Dries committed
116

Kjartan's avatar
Kjartan committed
117
function taxonomy_form_vocabulary($edit = array()) {
118
  $form['name'] = array('#type' => 'textfield', '#title' => t('Vocabulary name'), '#default_value' => $edit['name'], '#maxlength' => 64, '#description' => t('The name for this vocabulary.  Example: "Topic".'), '#required' => TRUE);
119

120 121
  $form['description'] = array('#type' => 'textarea', '#title' => t('Description'), '#default_value' => $edit['description'], '#description' => t('Description of the vocabulary; can be used by modules.'));
  $form['help'] = array('#type' => 'textfield', '#title' => t('Help text'), '#default_value' => $edit['help'], '#maxlength' => 255, '#description' => t('Instructions to present to the user when choosing a term.'));
122 123
  $form['nodes'] = array('#type' => 'checkboxes', '#title' => t('Types'), '#default_value' => $edit['nodes'], '#options' => node_get_types(), '#description' => t('A list of node types you want to associate with this vocabulary.'), '#required' => TRUE);
  $form['hierarchy'] = array('#type' => 'radios', '#title' => t('Hierarchy'), '#default_value' => $edit['hierarchy'], '#options' => array(t('Disabled'), t('Single'), t('Multiple')), '#description' => t('Allows <a href="%help-url">a tree-like hierarchy</a> between terms of this vocabulary.', array('%help-url' => url('admin/help/taxonomy', NULL, NULL, 'hierarchy'))));
124 125 126 127 128
  $form['relations'] = array('#type' => 'checkbox', '#title' => t('Related terms'), '#default_value' => $edit['relations'], '#description' => t('Allows <a href="%help-url">related terms</a> in this vocabulary.', array('%help-url' => url('admin/help/taxonomy', NULL, NULL, 'related-terms'))));
  $form['tags'] = array('#type' => 'checkbox', '#title' => t('Free tagging'), '#default_value' => $edit['tags'], '#description' => t('Content is categorized by typing terms instead of choosing from a list.'));
  $form['multiple'] = array('#type' => 'checkbox', '#title' => t('Multiple select'), '#default_value' => $edit['multiple'], '#description' => t('Allows nodes to have more than one term from this vocabulary (always true for free tagging).'));
  $form['required'] = array('#type' => 'checkbox', '#title' => t('Required'), '#default_value' => $edit['required'], '#description' => t('If enabled, every node <strong>must</strong> have at least one term in this vocabulary.'));
  $form['weight'] = array('#type' => 'weight', '#title' => t('Weight'), '#default_value' => $edit['weight'], '#description' => t('In listings, the heavier vocabularies will sink and the lighter vocabularies will be positioned nearer the top.'));
129

130 131 132 133
  // Add extra vocabulary form elements.
  $extra = module_invoke_all('taxonomy', 'form', 'vocabulary');
  if (is_array($extra)) {
    foreach ($extra as $key => $element) {
134
      $extra[$key]['#weight'] = isset($extra[$key]['#weight']) ? $nodeapi[$key]['#weight'] : -18;
135 136 137
    }
    $form = array_merge($form, $extra);
  }
Dries's avatar
 
Dries committed
138

139
  $form['submit'] = array('#type' => 'submit', '#value' => t('Submit'));
Dries's avatar
 
Dries committed
140
  if ($edit['vid']) {
141 142
    $form['delete'] = array('#type' => 'submit', '#value' => t('Delete'));
    $form['vid'] = array('#type' => 'hidden', '#value' => $edit['vid']);
Dries's avatar
 
Dries committed
143
  }
144
  return drupal_get_form('taxonomy_form_vocabulary', $form);
Kjartan's avatar
Kjartan committed
145
}
Kjartan's avatar
Kjartan committed
146

147
function taxonomy_save_vocabulary(&$edit) {
Dries's avatar
Dries committed
148 149
  $edit['nodes'] = ($edit['nodes']) ? $edit['nodes'] : array();
  $edit['weight'] = ($edit['weight']) ? $edit['weight'] : 0;
150
  $edit['tags'] = ($edit['tags']) ? $edit['tags'] : 0;
Dries's avatar
 
Dries committed
151

Dries's avatar
Dries committed
152
  $data = array('name' => $edit['name'], 'description' => $edit['description'], 'help' => $edit['help'], 'multiple' => $edit['multiple'], 'required' => $edit['required'], 'hierarchy' => $edit['hierarchy'], 'relations' => $edit['relations'], 'tags' => $edit['tags'], 'weight' => $edit['weight'],  'module' => isset($edit['module']) ? $edit['module'] : 'taxonomy');
Dries's avatar
 
Dries committed
153
  if ($edit['vid'] && $edit['name']) {
Dries's avatar
 
Dries committed
154
    db_query('UPDATE {vocabulary} SET '. _taxonomy_prepare_update($data) .' WHERE vid = %d', $edit['vid']);
Dries's avatar
 
Dries committed
155
    db_query("DELETE FROM {vocabulary_node_types} WHERE vid = %d", $edit['vid']);
156
    foreach ($edit['nodes'] as $type => $selected) {
Dries's avatar
 
Dries committed
157 158
      db_query("INSERT INTO {vocabulary_node_types} (vid, type) VALUES (%d, '%s')", $edit['vid'], $type);
    }
Dries's avatar
 
Dries committed
159
    module_invoke_all('taxonomy', 'update', 'vocabulary', $edit);
160
    $status = SAVED_UPDATED;
Dries's avatar
 
Dries committed
161
  }
Dries's avatar
 
Dries committed
162
  else if ($edit['vid']) {
163
    $status = taxonomy_del_vocabulary($edit['vid']);
Kjartan's avatar
Kjartan committed
164 165
  }
  else {
Dries's avatar
 
Dries committed
166
    $data['vid'] = $edit['vid'] = db_next_id('{vocabulary}_vid');
Dries's avatar
 
Dries committed
167
    db_query('INSERT INTO {vocabulary} '. _taxonomy_prepare_insert($data, 1) .' VALUES '. _taxonomy_prepare_insert($data, 2));
168
    foreach ($edit['nodes'] as $type => $selected) {
Dries's avatar
 
Dries committed
169 170
      db_query("INSERT INTO {vocabulary_node_types} (vid, type) VALUES (%d, '%s')", $edit['vid'], $type);
    }
Dries's avatar
 
Dries committed
171
    module_invoke_all('taxonomy', 'insert', 'vocabulary', $edit);
172
    $status = SAVED_NEW;
Kjartan's avatar
Kjartan committed
173
  }
Dries's avatar
 
Dries committed
174 175

  cache_clear_all();
Dries's avatar
 
Dries committed
176

177
  return $status;
Kjartan's avatar
Kjartan committed
178
}
Dries's avatar
 
Dries committed
179

Kjartan's avatar
Kjartan committed
180
function taxonomy_del_vocabulary($vid) {
Dries's avatar
 
Dries committed
181 182
  $vocabulary = taxonomy_get_vocabulary($vid);

Dries's avatar
 
Dries committed
183
  db_query('DELETE FROM {vocabulary} WHERE vid = %d', $vid);
Dries's avatar
 
Dries committed
184
  db_query('DELETE FROM {vocabulary_node_types} WHERE vid = %d', $vid);
Dries's avatar
 
Dries committed
185
  $result = db_query('SELECT tid FROM {term_data} WHERE vid = %d', $vid);
Kjartan's avatar
Kjartan committed
186 187
  while ($term = db_fetch_object($result)) {
    taxonomy_del_term($term->tid);
Dries's avatar
 
Dries committed
188
  }
Dries's avatar
 
Dries committed
189

Dries's avatar
 
Dries committed
190
  module_invoke_all('taxonomy', 'delete', 'vocabulary', $vocabulary);
Dries's avatar
 
Dries committed
191

Dries's avatar
 
Dries committed
192 193
  cache_clear_all();

194
  return SAVED_DELETED;
Dries's avatar
 
Dries committed
195 196 197 198 199
}

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

200 201 202
  $form['type'] = array('#type' => 'hidden', '#value' => 'vocabulary');
  $form['vid'] = array('#type' => 'hidden', '#value' => $vid);
  $form['name'] = array('#type' => 'hidden', '#value' => $vocabulary->name);
203 204 205 206
  return confirm_form('vocabulary_confirm_delete', $form,
                  t('Are you sure you want to delete the vocabulary %title?',
                  array('%title' => theme('placeholder', $vocabulary->name))),
                  'admin/taxonomy', t('Deleting a vocabulary will delete all the terms in it. This action cannot be undone.'),
207
                  t('Delete'),
208
                  t('Cancel'));
Kjartan's avatar
Kjartan committed
209
}
Dries's avatar
 
Dries committed
210

Kjartan's avatar
Kjartan committed
211
function taxonomy_form_term($edit = array()) {
Dries's avatar
 
Dries committed
212
  $vocabulary_id = isset($edit['vid']) ? $edit['vid'] : arg(4);
Kjartan's avatar
Kjartan committed
213
  $vocabulary = taxonomy_get_vocabulary($vocabulary_id);
Dries's avatar
 
Dries committed
214

215
  $form['name'] = array('#type' => 'textfield', '#title' => t('Term name'), '#default_value' => $edit['name'], '#maxlength' => 64, '#description' => t('The name for this term.  Example: "Linux".'), '#required' => TRUE);
216

217
  $form['description'] = array('#type' => 'textarea', '#title' => t('Description'), '#default_value' => $edit['description'], '#description' => t('A description of the term.'));
Dries's avatar
 
Dries committed
218

Kjartan's avatar
Kjartan committed
219
  if ($vocabulary->hierarchy) {
Dries's avatar
 
Dries committed
220 221
    $parent = array_keys(taxonomy_get_parents($edit['tid']));
    $children = taxonomy_get_tree($vocabulary_id, $edit['tid']);
Dries's avatar
 
Dries committed
222

Dries's avatar
 
Dries committed
223
    // A term can't be the child of itself, nor of its children.
Dries's avatar
 
Dries committed
224 225 226
    foreach ($children as $child) {
      $exclude[] = $child->tid;
    }
Dries's avatar
 
Dries committed
227
    $exclude[] = $edit['tid'];
Dries's avatar
 
Dries committed
228

Kjartan's avatar
Kjartan committed
229
    if ($vocabulary->hierarchy == 1) {
230
      $form['parent'] = _taxonomy_term_select(t('Parent'), 'parent', $parent, $vocabulary_id, l(t('Parent term'), 'admin/help/taxonomy', NULL, NULL, 'parent') .'.', 0, '<'. t('root') .'>', $exclude);
Dries's avatar
 
Dries committed
231
    }
Kjartan's avatar
Kjartan committed
232
    elseif ($vocabulary->hierarchy == 2) {
233
      $form['parent'] = _taxonomy_term_select(t('Parents'), 'parent', $parent, $vocabulary_id, l(t('Parent terms'), 'admin/help/taxonomy', NULL, NULL, 'parent') .'.', 1, '<'. t('root') .'>', $exclude);
Dries's avatar
 
Dries committed
234
    }
Kjartan's avatar
Kjartan committed
235
  }
Dries's avatar
 
Dries committed
236

237
  if ($vocabulary->relations) {
238
    $form['relations'] = _taxonomy_term_select(t('Related terms'), 'relations', array_keys(taxonomy_get_related($edit['tid'])), $vocabulary_id, NULL, 1, '<'. t('none') .'>', array($edit['tid']));
239 240
  }

241 242
  $form['synonyms'] = array('#type' => 'textarea', '#title' => t('Synonyms'), '#default_value' => implode("\n", taxonomy_get_synonyms($edit['tid'])), '#description' => t('<a href="%help-url">Synonyms</a> of this term, one synonym per line.', array('%help-url' => url('admin/help/taxonomy', NULL, NULL, 'synonyms'))));
  $form['weight'] = array('#type' => 'weight', '#title' => t('Weight'), '#default_value' => $edit['weight'], '#description' => t('In listings, the heavier terms will sink and the lighter terms will be positioned nearer the top.'));
243 244 245 246 247

  // Add extra term form elements.
  $extra = module_invoke_all('taxonomy', 'term', 'vocabulary');
  if (is_array($extra)) {
    foreach ($extra as $key => $element) {
248
      $extra[$key]['#weight'] = isset($extra[$key]['#weight']) ? $nodeapi[$key]['#weight'] : -18;
249 250 251 252 253
    }
    $form = array_merge($form, $extra);
  }


254 255
  $form['vid'] = array('#type' => 'hidden', '#value' => $vocabulary->vid);
  $form['submit'] = array('#type' => 'submit', '#value' => t('Submit'));
Kjartan's avatar
Kjartan committed
256

Dries's avatar
 
Dries committed
257
  if ($edit['tid']) {
258 259
    $form['delete'] = array('#type' => 'submit', '#value' => t('Delete'));
    $form['tid'] = array('#type' => 'hidden', '#value' => $edit['tid']);
Dries's avatar
 
Dries committed
260
  }
261
  else {
262
    $form['destination'] = array('#type' => 'hidden', '#value' => $_GET['q']);
263
  }
Dries's avatar
 
Dries committed
264

265
  return drupal_get_form('taxonomy_form_term', $form);
Kjartan's avatar
Kjartan committed
266
}
Dries's avatar
 
Dries committed
267

268
function taxonomy_save_term(&$edit) {
Dries's avatar
 
Dries committed
269 270
  if ($edit['tid'] && $edit['name']) {
    $data = array('name' => $edit['name'], 'description' => $edit['description'], 'weight' => $edit['weight']);
Dries's avatar
 
Dries committed
271

Dries's avatar
 
Dries committed
272
    db_query('UPDATE {term_data} SET '. _taxonomy_prepare_update($data) .' WHERE tid = %d', $edit['tid']);
Dries's avatar
 
Dries committed
273
    module_invoke_all('taxonomy', 'update', 'term', $edit);
274
    $status = SAVED_UPDATED;
Kjartan's avatar
Kjartan committed
275
  }
Dries's avatar
 
Dries committed
276 277
  else if ($edit['tid']) {
    return taxonomy_del_term($edit['tid']);
Kjartan's avatar
Kjartan committed
278 279
  }
  else {
Dries's avatar
 
Dries committed
280 281
    $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']);
Dries's avatar
 
Dries committed
282
    db_query('INSERT INTO {term_data} '. _taxonomy_prepare_insert($data, 1) .' VALUES '. _taxonomy_prepare_insert($data, 2));
Dries's avatar
 
Dries committed
283
    module_invoke_all('taxonomy', 'insert', 'term', $edit);
284
    $status = SAVED_NEW;
Kjartan's avatar
Kjartan committed
285
  }
Dries's avatar
 
Dries committed
286

Dries's avatar
 
Dries committed
287 288 289
  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's avatar
Kjartan committed
290
      if ($related_id != 0) {
Dries's avatar
 
Dries committed
291
        db_query('INSERT INTO {term_relation} (tid1, tid2) VALUES (%d, %d)', $edit['tid'], $related_id);
Dries's avatar
 
Dries committed
292
      }
Kjartan's avatar
Kjartan committed
293
    }
Kjartan's avatar
Kjartan committed
294
  }
Dries's avatar
 
Dries committed
295

Dries's avatar
 
Dries committed
296 297
  db_query('DELETE FROM {term_hierarchy} WHERE tid = %d', $edit['tid']);
  if (!isset($edit['parent'])) {
298
    $edit['parent'] = array(0);
Kjartan's avatar
Kjartan committed
299
  }
Dries's avatar
 
Dries committed
300 301
  if (is_array($edit['parent'])) {
    foreach ($edit['parent'] as $parent) {
302 303 304 305 306 307 308 309
      if (is_array($parent)) {
        foreach ($parent as $tid) {
          db_query('INSERT INTO {term_hierarchy} (tid, parent) VALUES (%d, %d)', $edit['tid'], $tid);
        }
      }
      else {
        db_query('INSERT INTO {term_hierarchy} (tid, parent) VALUES (%d, %d)', $edit['tid'], $parent);
      }
Dries's avatar
 
Dries committed
310
    }
Kjartan's avatar
Kjartan committed
311
  }
312 313 314
  else {
    db_query('INSERT INTO {term_hierarchy} (tid, parent) VALUES (%d, %d)', $edit['tid'], $edit['parent']);
  }
Dries's avatar
 
Dries committed
315

Dries's avatar
 
Dries committed
316 317 318
  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's avatar
 
Dries committed
319
      if ($synonym) {
Dries's avatar
 
Dries committed
320
        db_query("INSERT INTO {term_synonym} (tid, name) VALUES (%d, '%s')", $edit['tid'], chop($synonym));
Dries's avatar
 
Dries committed
321
      }
Kjartan's avatar
Kjartan committed
322
    }
Dries's avatar
 
Dries committed
323
  }
Dries's avatar
 
Dries committed
324

Dries's avatar
 
Dries committed
325 326
  cache_clear_all();

327
  return $status;
Kjartan's avatar
Kjartan committed
328
}
Dries's avatar
 
Dries committed
329

Kjartan's avatar
Kjartan committed
330
function taxonomy_del_term($tid) {
331 332 333 334 335 336 337 338 339 340 341 342 343 344
  $tids = array($tid);
  while ($tids) {
    $children_tids = $orphans = array();
    foreach ($tids as $tid) {
      // See if any of the term's children are about to be become orphans:
      if ($children = taxonomy_get_children($tid)) {
        foreach ($children as $child) {
          // If the term has multiple parents, we don't delete it.
          $parents = taxonomy_get_parents($child->tid);
          if (count($parents) == 1) {
            $orphans[] = $child->tid;
          }
        }
      }
Dries's avatar
 
Dries committed
345

346
      $term = taxonomy_get_term($tid);
Dries's avatar
 
Dries committed
347

348 349 350 351 352
      db_query('DELETE FROM {term_data} WHERE tid = %d', $tid);
      db_query('DELETE FROM {term_hierarchy} WHERE tid = %d', $tid);
      db_query('DELETE FROM {term_relation} WHERE tid1 = %d OR tid2 = %d', $tid, $tid);
      db_query('DELETE FROM {term_synonym} WHERE tid = %d', $tid);
      db_query('DELETE FROM {term_node} WHERE tid = %d', $tid);
Dries's avatar
 
Dries committed
353

354
      module_invoke_all('taxonomy', 'delete', 'term', $term);
355
      drupal_set_message(t('Deleted term %name.', array('%name' => theme('placeholder', $term->name))));
356
    }
Dries's avatar
 
Dries committed
357

358 359
    $tids = $orphans;
  }
Dries's avatar
 
Dries committed
360

Dries's avatar
 
Dries committed
361
  cache_clear_all();
Dries's avatar
 
Dries committed
362 363 364 365 366
}

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

367 368
  $form['type'] = array('#type' => 'hidden', '#value' => 'term');
  $form['tid'] = array('#type' => 'hidden', '#value' => $tid);
369 370 371
  return confirm_form('term_confirm_delete', $form,
                  t('Are you sure you want to delete the term %title?',
                  array('%title' => theme('placeholder', $term->name))),
372 373 374
                  'admin/taxonomy',
                  t('Deleting a term will delete all its children if there are any. This action cannot be undone.'),
                  t('Delete'),
375
                  t('Cancel'));
Kjartan's avatar
Kjartan committed
376
}
Dries's avatar
 
Dries committed
377

Dries's avatar
 
Dries committed
378 379 380
/**
 * Generate a tabular listing of administrative functions for vocabularies.
 */
Kjartan's avatar
Kjartan committed
381
function taxonomy_overview() {
Dries's avatar
Dries committed
382 383
  $vid = arg(2);

384
  // Show all vocabularies, and a "view terms" link to the pagers.
Dries's avatar
Dries committed
385
  if (!$vid) {
386
    $header = array(t('Name'), t('Type'), array('data' => t('Operations'), 'colspan' => '2'));
Dries's avatar
Dries committed
387 388
    $vocabularies = taxonomy_get_vocabularies();
    foreach ($vocabularies as $vocabulary) {
389 390
      $types = array();
      foreach ($vocabulary->nodes as $type) {
391
        $node_type = node_get_name($type);
392 393
        $types[] = $node_type ? $node_type : $type;
      }
Dries's avatar
Dries committed
394
      $rows[] = array(check_plain($vocabulary->name), implode(', ', $types), l(t('edit vocabulary'), "admin/taxonomy/edit/vocabulary/$vocabulary->vid"), l(t('edit terms'), "admin/taxonomy/$vocabulary->vid"));
Dries's avatar
Dries committed
395 396 397
    }

    if (!$rows) {
398
      $rows[] = array(array('data' => t('No categories available.'), 'colspan' => '4', 'class' => 'message'));
Dries's avatar
Dries committed
399 400
    }
  }
Dries's avatar
 
Dries committed
401

402
  // Show the vocabulary's terms with a pager.
Dries's avatar
Dries committed
403
  else {
404 405 406
    $destination = drupal_get_destination();

    $header = array(t('Name'), t('Operations'));
Dries's avatar
Dries committed
407
    $vocabulary = taxonomy_get_vocabulary($vid);
408

Dries's avatar
Dries committed
409 410 411 412 413 414 415 416 417 418
    drupal_set_title(check_plain($vocabulary->name));
    $start_from      = $_GET['page'] ? $_GET['page'] : 0;
    $total_entries   = 0;  // total count for pager
    $page_increment  = 25; // number of tids per page
    $displayed_count = 0;  // number of tids shown

    $tree = taxonomy_get_tree($vocabulary->vid);
    foreach ($tree as $term) {
      $total_entries++; // we're counting all-totals, not displayed
      if (($start_from && ($start_from * $page_increment) >= $total_entries) || ($displayed_count == $page_increment)) { continue; }
419
      $rows[] = array(_taxonomy_depth($term->depth) . ' ' . l(check_plain($term->name), "taxonomy/term/$term->tid"), l(t('edit'), "admin/taxonomy/edit/term/$term->tid", array(), $destination));
Dries's avatar
Dries committed
420 421 422 423 424 425
      $displayed_count++; // we're counting tids displayed
    }

    if (!$rows) {
      $rows[] = array(array('data' => t('No terms available.'), 'colspan' => '2'));
    }
Dries's avatar
 
Dries committed
426

Dries's avatar
Dries committed
427 428
    $GLOBALS['pager_page_array'][] = $start_from;  // FIXME
    $GLOBALS['pager_total'][] = intval($total_entries / $page_increment) + 1; // FIXME
429

Dries's avatar
Dries committed
430 431
    if ($total_entries >= $page_increment) {
      $rows[] = array(array('data' => theme('pager', NULL, $page_increment), 'colspan' => '2'));
Dries's avatar
Dries committed
432
    }
Dries's avatar
 
Dries committed
433 434
  }

Dries's avatar
Dries committed
435
  return theme('table', $header, $rows, array('id' => 'taxonomy'));
Kjartan's avatar
Kjartan committed
436 437
}

Dries's avatar
 
Dries committed
438 439 440
/**
 * Generate a form element for selecting terms from a vocabulary.
 */
Dries's avatar
 
Dries committed
441
function taxonomy_form($vid, $value = 0, $help = NULL, $name = 'taxonomy') {
Dries's avatar
 
Dries committed
442
  $vocabulary = taxonomy_get_vocabulary($vid);
443
  $help = ($help) ? $help : $vocabulary->help;
Kjartan's avatar
Kjartan committed
444 445 446 447
  if ($vocabulary->required) {
    $blank = 0;
  }
  else {
Dries's avatar
 
Dries committed
448
    $blank = '<'. t('none') .'>';
Kjartan's avatar
Kjartan committed
449
  }
Dries's avatar
 
Dries committed
450

451
  return _taxonomy_term_select(check_plain($vocabulary->name), $name, $value, $vid, $help, intval($vocabulary->multiple), $blank);
Kjartan's avatar
Kjartan committed
452
}
Dries's avatar
 
Dries committed
453

Dries's avatar
Dries committed
454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473
/**
 * Generate a set of options for selecting a term from all vocabularies. Can be
 * passed to form_select.
 */
function taxonomy_form_all($free_tags = 0) {
  $vocabularies = taxonomy_get_vocabularies();
  $options = array();
  foreach ($vocabularies as $vid => $vocabulary) {
    if ($vocabulary->tags && !$free_tags) { continue; }
    $tree = taxonomy_get_tree($vid);
    $options[$vocabulary->name] = array();
    if ($tree) {
      foreach ($tree as $term) {
        $options[$vocabulary->name][$term->tid] = _taxonomy_depth($term->depth, '-') . $term->name;
      }
    }
  }
  return $options;
}

Dries's avatar
 
Dries committed
474 475 476 477 478 479
/**
 * Return an array of all vocabulary objects.
 *
 * @param $type
 *   If set, return only those vocabularies associated with this node type.
 */
Dries's avatar
 
Dries committed
480
function taxonomy_get_vocabularies($type = NULL) {
Kjartan's avatar
Kjartan committed
481
  if ($type) {
482
    $result = db_query(db_rewrite_sql("SELECT v.vid, v.*, n.type FROM {vocabulary} v LEFT JOIN {vocabulary_node_types} n ON v.vid = n.vid WHERE n.type = '%s' ORDER BY v.weight, v.name", 'v', 'vid'), $type);
Kjartan's avatar
Kjartan committed
483 484
  }
  else {
485
    $result = db_query(db_rewrite_sql('SELECT v.*, n.type FROM {vocabulary} v LEFT JOIN {vocabulary_node_types} n ON v.vid = n.vid ORDER BY v.weight, v.name', 'v', 'vid'));
Kjartan's avatar
Kjartan committed
486
  }
Dries's avatar
 
Dries committed
487

Kjartan's avatar
Kjartan committed
488
  $vocabularies = array();
Dries's avatar
 
Dries committed
489
  $node_types = array();
Kjartan's avatar
Kjartan committed
490
  while ($voc = db_fetch_object($result)) {
Dries's avatar
 
Dries committed
491 492 493 494
    $node_types[$voc->vid][] = $voc->type;
    unset($voc->type);
    $voc->nodes = $node_types[$voc->vid];
    $vocabularies[$voc->vid] = $voc;
Dries's avatar
 
Dries committed
495
  }
Dries's avatar
 
Dries committed
496

Kjartan's avatar
Kjartan committed
497 498
  return $vocabularies;
}
Dries's avatar
 
Dries committed
499

Dries's avatar
 
Dries committed
500 501 502
/**
 * Generate a form for selecting terms to associate with a node.
 */
503 504 505 506 507 508 509 510 511 512 513
function taxonomy_form_alter($form_id, &$form) {
  if (isset($form['type']) && $form['type']['#value'] .'_node_form' == $form_id) {
    $node = $form['#node'];

    if (!array_key_exists('taxonomy', $node)) {
      if ($node->nid) {
        $terms = taxonomy_node_get_terms($node->nid);
      }
      else {
        $terms = array();
      }
Kjartan's avatar
Kjartan committed
514 515
    }
    else {
516
      $terms = $node->taxonomy;
Dries's avatar
 
Dries committed
517 518
    }

519
    $c = db_query(db_rewrite_sql("SELECT v.* FROM {vocabulary} v INNER JOIN {vocabulary_node_types} n ON v.vid = n.vid WHERE n.type = '%s' ORDER BY v.weight, v.name", 'v', 'vid'), $node->type);
Dries's avatar
Dries committed
520

521 522 523 524 525
    while ($vocabulary = db_fetch_object($c)) {
      if ($vocabulary->tags) {
        $typed_terms = array();
        foreach ($terms as $term) {
          if ($term->vid == $vocabulary->vid) {
Dries's avatar
Dries committed
526

527 528 529 530 531 532 533
            // Commas and quotes in terms are special cases, so encode 'em.
            if (preg_match('/,/', $term->name) || preg_match('/"/', $term->name)) {
              $term->name = '"'.preg_replace('/"/', '""', $term->name).'"';
            }

            $typed_terms[] = $term->name;
          }
Dries's avatar
Dries committed
534
        }
535
        $typed_string = implode(', ', $typed_terms) . (array_key_exists('tags', $terms) ? $terms['tags'][$vocabulary->vid] : NULL);
536

537 538 539 540 541 542
        $form['taxonomy']['tags'][$vocabulary->vid] = array('#type' => 'textfield', '#default_value' => $typed_string, '#maxlength' => 100, '#autocomplete_path' => 'taxonomy/autocomplete/'. $vocabulary->vid, '#required' => $vocabulary->required, '#title' => $vocabulary->name, '#description' => t('A comma-separated list of terms describing this content (Example: funny, bungie jumping, "Company, Inc.").'));
      }
      else {
        $ntterms = array_key_exists('taxonomy', $node) ? $terms : array_keys($terms);
        $form['taxonomy'][$vocabulary->vid] = taxonomy_form($vocabulary->vid, $ntterms, $help, 'taxonomy');
      }
Dries's avatar
Dries committed
543
    }
544 545 546
    if (isset($form['taxonomy'])) {
      $form['taxonomy']['#tree'] = TRUE;
      $form['taxonomy']['#weight'] = -15;
Dries's avatar
Dries committed
547
    }
Dries's avatar
 
Dries committed
548
  }
Kjartan's avatar
Kjartan committed
549
}
Dries's avatar
 
Dries committed
550

Dries's avatar
 
Dries committed
551 552 553 554
/**
 * Find all terms associated to the given node, within one vocabulary.
 */
function taxonomy_node_get_terms_by_vocabulary($nid, $vid, $key = 'tid') {
555
  $result = db_query(db_rewrite_sql('SELECT t.tid, t.* FROM {term_data} t, {term_node} r WHERE t.tid = r.tid AND t.vid = %d AND r.nid = %d ORDER BY weight', 't', 'tid'), $vid, $nid);
Kjartan's avatar
Kjartan committed
556 557 558
  $terms = array();
  while ($term = db_fetch_object($result)) {
    $terms[$term->$key] = $term;
Dries's avatar
 
Dries committed
559
  }
Kjartan's avatar
Kjartan committed
560 561 562
  return $terms;
}

Dries's avatar
 
Dries committed
563
/**
564
 * Find all terms associated to the given node, ordered by vocabulary and term weight.
Dries's avatar
 
Dries committed
565 566
 */
function taxonomy_node_get_terms($nid, $key = 'tid') {
Kjartan's avatar
Kjartan committed
567
  static $terms;
Dries's avatar
 
Dries committed
568

Dries's avatar
 
Dries committed
569
  if (!isset($terms[$nid])) {
570
    $result = db_query('SELECT t.* FROM {term_node} r INNER JOIN {term_data} t ON r.tid = t.tid INNER JOIN {vocabulary} v ON t.vid = v.vid WHERE r.nid = %d ORDER BY v.weight, t.weight, t.name', $nid);
Kjartan's avatar
Kjartan committed
571
    $terms[$nid] = array();
Dries's avatar
 
Dries committed
572
    while ($term = db_fetch_object($result)) {
Kjartan's avatar
Kjartan committed
573
      $terms[$nid][$term->$key] = $term;
Dries's avatar
 
Dries committed
574 575
    }
  }
Kjartan's avatar
Kjartan committed
576 577
  return $terms[$nid];
}
Dries's avatar
 
Dries committed
578

Dries's avatar
Dries committed
579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595
/**
 * Make sure incoming vids are free tagging enabled.
 */
function taxonomy_node_validate(&$node) {
  if ($node->taxonomy) {
    $terms = $node->taxonomy;
    if ($terms['tags']) {
      foreach ($terms['tags'] as $vid => $vid_value) {
        $vocabulary = taxonomy_get_vocabulary($vid);
        if (!$vocabulary->tags) {
          form_set_error("taxonomy[tags][$vid", t('The %name vocabulary can not be modified in this way.', array('%name' => theme('placeholder', $vocabulary->name))));
        }
      }
    }
  }
}

Dries's avatar
 
Dries committed
596 597 598
/**
 * Save term associations for a given node.
 */
Kjartan's avatar
Kjartan committed
599
function taxonomy_node_save($nid, $terms) {
600
  taxonomy_node_delete($nid);
Dries's avatar
Dries committed
601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633

  // Free tagging vocabularies do not send their tids in the form,
  // so we'll detect them here and process them independently.
  if ($terms['tags']) {
    $typed_input = $terms['tags'];
    unset($terms['tags']);

    foreach ($typed_input as $vid => $vid_value) {
      // This regexp allows the following types of user input:
      // this, "somecmpany, llc", "and ""this"" w,o.rks", foo bar
      $regexp = '%(?:^|,\ *)("(?>[^"]*)(?>""[^"]* )*"|(?: [^",]*))%x';
      preg_match_all($regexp, $vid_value, $matches);
      $typed_terms = $matches[1];

      foreach ($typed_terms as $typed_term) {
        // If a user has escaped a term (to demonstrate that it is a group,
        // or includes a comma or quote character), we remove the escape
        // formatting so to save the term into the DB as the user intends.
        $typed_term = str_replace('""', '"', preg_replace('/^"(.*)"$/', '\1', $typed_term));
        $typed_term = trim($typed_term);
        if ($typed_term == "") { continue; }

        // See if the term exists in the chosen vocabulary
        // and return the tid, otherwise, add a new record.
        $possibilities = taxonomy_get_term_by_name($typed_term);
        $typed_term_tid = NULL; // tid match if any.
        foreach ($possibilities as $possibility) {
          if ($possibility->vid == $vid) {
            $typed_term_tid = $possibility->tid;
          }
        }

        if (!$typed_term_tid) {
634 635 636
          $edit = array('vid' => $vid, 'name' => $typed_term);
          $status = taxonomy_save_term($edit);
          $typed_term_tid = $edit['tid'];
Dries's avatar
Dries committed
637 638 639 640 641 642
        }

        db_query('INSERT INTO {term_node} (nid, tid) VALUES (%d, %d)', $nid, $typed_term_tid);
      }
    }
  }
Dries's avatar
 
Dries committed
643

644
  if (is_array($terms)) {
Dries's avatar
 
Dries committed
645
    foreach ($terms as $term) {
646 647 648 649 650 651 652
      if (is_array($term)) {
        foreach ($term as $tid) {
          if ($tid) {
            db_query('INSERT INTO {term_node} (nid, tid) VALUES (%d, %d)', $nid, $tid);
          }
        }
      }
653
      else if ($term) {
Dries's avatar
 
Dries committed
654
        db_query('INSERT INTO {term_node} (nid, tid) VALUES (%d, %d)', $nid, $term);
655
      }
Dries's avatar
 
Dries committed
656 657
    }
  }
Kjartan's avatar
Kjartan committed
658
}
Dries's avatar
 
Dries committed
659

Dries's avatar
 
Dries committed
660 661 662
/**
 * Remove associations of a node to its terms.
 */
Kjartan's avatar
Kjartan committed
663
function taxonomy_node_delete($nid) {
Dries's avatar
 
Dries committed
664
  db_query('DELETE FROM {term_node} WHERE nid = %d', $nid);
Kjartan's avatar
Kjartan committed
665
}
Dries's avatar
 
Dries committed
666

Dries's avatar
 
Dries committed
667 668 669 670
/**
 * Find all term objects related to a given term ID.
 */
function taxonomy_get_related($tid, $key = 'tid') {
Kjartan's avatar
Kjartan committed
671
  if ($tid) {
Dries's avatar
 
Dries committed
672
    $result = db_query('SELECT t.*, tid1, tid2 FROM {term_relation}, {term_data} t WHERE (t.tid = tid1 OR t.tid = tid2) AND (tid1 = %d OR tid2 = %d) AND t.tid != %d ORDER BY weight, name', $tid, $tid, $tid);
Kjartan's avatar
Kjartan committed
673 674 675
    $related = array();
    while ($term = db_fetch_object($result)) {
      $related[$term->$key] = $term;
Dries's avatar
 
Dries committed
676
    }
Kjartan's avatar
Kjartan committed
677
    return $related;
Dries's avatar
 
Dries committed
678
  }
Kjartan's avatar
Kjartan committed
679 680
  else {
    return array();
Dries's avatar
 
Dries committed
681
  }
Kjartan's avatar
Kjartan committed
682
}
Dries's avatar
 
Dries committed
683

Dries's avatar
 
Dries committed
684 685 686 687
/**
 * Find all parents of a given term ID.
 */
function taxonomy_get_parents($tid, $key = 'tid') {
Kjartan's avatar
Kjartan committed
688
  if ($tid) {
689
    $result = db_query(db_rewrite_sql('SELECT t.tid, t.* FROM {term_hierarchy} h, {term_data} t WHERE h.parent = t.tid AND h.tid = %d ORDER BY weight, name', 't', 'tid'), $tid);
Kjartan's avatar
Kjartan committed
690 691 692
    $parents = array();
    while ($parent = db_fetch_object($result)) {
      $parents[$parent->$key] = $parent;
Dries's avatar
 
Dries committed
693
    }
Kjartan's avatar
Kjartan committed
694
    return $parents;
Dries's avatar
 
Dries committed
695
  }
Kjartan's avatar
Kjartan committed
696 697 698 699
  else {
    return array();
  }
}
Dries's avatar
 
Dries committed
700

Dries's avatar
 
Dries committed
701 702 703 704
/**
 * Find all ancestors of a given term ID.
 */
function taxonomy_get_parents_all($tid) {
Dries's avatar
 
Dries committed
705 706 707 708 709 710 711 712 713 714 715 716
  $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's avatar
 
Dries committed
717 718 719 720
/**
 * Find all children of a term ID.
 */
function taxonomy_get_children($tid, $vid = 0, $key = 'tid') {
Kjartan's avatar
Kjartan committed
721
  if ($vid) {
722
    $result = db_query(db_rewrite_sql('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', 't', 'tid'), $vid, $tid);
Dries's avatar
 
Dries committed
723
  }
Kjartan's avatar
Kjartan committed
724
  else {
725
    $result = db_query(db_rewrite_sql('SELECT t.* FROM {term_hierarchy} h, {term_data} t WHERE h.tid = t.tid AND parent = %d ORDER BY weight, name', 't', 'tid'), $tid);
Kjartan's avatar
Kjartan committed
726 727 728 729 730 731 732
  }
  $children = array();
  while ($term = db_fetch_object($result)) {
    $children[$term->$key] = $term;
  }
  return $children;
}
Dries's avatar
 
Dries committed
733

Dries's avatar
 
Dries committed
734 735 736 737 738 739 740 741 742 743 744 745 746
/**
 * 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.
 *
Dries's avatar
 
Dries committed
747 748 749
 * @param $max_depth
 *   The number of levels of the tree to return. Leave NULL to return all levels.
 *
Dries's avatar
 
Dries committed
750 751 752 753 754
 * @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's avatar
 
Dries committed
755
  static $children, $parents, $terms;
Dries's avatar
 
Dries committed
756

Kjartan's avatar
Kjartan committed
757
  $depth++;
Dries's avatar
 
Dries committed
758

Dries's avatar
 
Dries committed
759 760 761 762
  // 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's avatar
 
Dries committed
763

764
    $result = db_query(db_rewrite_sql('SELECT t.tid, t.*, parent FROM {term_data} t, {term_hierarchy} h WHERE t.tid = h.tid AND t.vid = %d ORDER BY weight, name', 't', 'tid'), $vid);
Dries's avatar
 
Dries committed
765
    while ($term = db_fetch_object($result)) {
Dries's avatar
 
Dries committed
766 767 768
      $children[$vid][$term->parent][] = $term->tid;
      $parents[$vid][$term->tid][] = $term->parent;
      $terms[$vid][$term->tid] = $term;
Dries's avatar
 
Dries committed
769 770
    }
  }
Dries's avatar
 
Dries committed
771

Dries's avatar
 
Dries committed
772
  $max_depth = (is_null($max_depth)) ? count($children[$vid]) : $max_depth;
Dries's avatar
Dries committed
773 774 775 776 777 778 779 780 781 782 783 784
  if ($children[$vid][$parent]) {
    foreach ($children[$vid][$parent] as $child) {
      if ($max_depth > $depth) {
        $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];

        if ($children[$vid][$child]) {
          $tree = array_merge($tree, taxonomy_get_tree($vid, $child, $depth, $max_depth));
        }
Dries's avatar
 
Dries committed
785
      }
Dries's avatar
 
Dries committed
786
    }
Kjartan's avatar
Kjartan committed
787
  }
Dries's avatar
 
Dries committed
788

Dries's avatar
 
Dries committed
789
  return $tree ? $tree : array();
Kjartan's avatar
Kjartan committed
790
}
Dries's avatar
 
Dries committed
791

Dries's avatar
 
Dries committed
792 793 794
/**
 * Return an array of synonyms of the given term ID.
 */
Kjartan's avatar
Kjartan committed
795 796
function taxonomy_get_synonyms($tid) {
  if ($tid) {
Dries's avatar
 
Dries committed
797
    $result = db_query('SELECT name FROM {term_synonym} WHERE tid = %d', $tid);
Kjartan's avatar
Kjartan committed
798
    while ($synonym = db_fetch_array($result)) {
Dries's avatar
 
Dries committed
799
      $synonyms[] = $synonym['name'];
Dries's avatar
 
Dries committed
800
    }
Kjartan's avatar
Kjartan committed
801
    return $synonyms ? $synonyms : array();
Dries's avatar
 
Dries committed
802
  }
Kjartan's avatar
Kjartan committed
803 804
  else {
    return array();
Dries's avatar
 
Dries committed
805
  }
Kjartan's avatar
Kjartan committed
806
}
Dries's avatar
 
Dries committed
807

Dries's avatar
 
Dries committed
808 809 810 811 812
/**
 * 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's avatar
Kjartan committed
813
}
Dries's avatar
 
Dries committed
814

Dries's avatar
 
Dries committed
815 816