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));
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));
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 119 120 121 122 123 124 125 126 127 128
  $form['name'] = array('#type' => 'textfield', '#title' => t('Vocabulary name'), '#default_value' => $edit['name'], '#size' => 60, '#maxlength' => 64, '#description' => t('The name for this vocabulary.  Example: "Topic".'), '#required' => TRUE);

  $form['description'] = array('#type' => 'textarea', '#title' => t('Description'), '#default_value' => $edit['description'], '#cols' => 60, '#rows' => 5, '#description' => t('Description of the vocabulary; can be used by modules.'));
  $form['help'] = array('#type' => 'textfield', '#title' => t('Help text'), '#default_value' => $edit['help'], '#size' => 60, '#maxlength' => 255, '#description' => t('Instructions to present to the user when choosing a term.'));
  $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'))));
  $form['relations'] = array('#type' => 'checkbox', '#title' => t('Related terms'), '#default_value' => $edit['relations'], '#return_value' => 1, '#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'], '#return_value' => 1, '#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'], '#return_value' => 1, '#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'], '#return_value' => 1, '#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'], '#delta' => 10, '#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'], '#size' => 60, '#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'], '#cols' => 60, '#rows' => 5, '#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'])), '#cols' => 60, '#rows' => 5, '#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'], '#delta' => 10, '#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

454
/**
455 456 457
 * Generate a set of options for selecting a term from all vocabularies. Can be
 * passed to form_select.
 */
Dries's avatar
Dries committed
458
function taxonomy_form_all($free_tags = 0) {
459 460 461
  $vocabularies = taxonomy_get_vocabularies();
  $options = array();
  foreach ($vocabularies as $vid => $vocabulary) {
Dries's avatar
Dries committed
462
    if ($vocabulary->tags && !$free_tags) { continue; }
463 464 465 466 467 468 469 470 471 472 473
    $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
function taxonomy_node_form($node) {
Dries's avatar
Dries committed
504
  if (!array_key_exists('taxonomy', $node)) {
Kjartan's avatar
Kjartan committed
505
    if ($node->nid) {
Dries's avatar
Dries committed
506
      $terms = taxonomy_node_get_terms($node->nid);
Kjartan's avatar
Kjartan committed
507 508
    }
    else {
Dries's avatar
Dries committed
509
      $terms = array();
Dries's avatar
 
Dries committed
510
    }
Kjartan's avatar
Kjartan committed
511 512 513 514
  }
  else {
    $terms = $node->taxonomy;
  }
Dries's avatar
 
Dries committed
515

516
  $c = db_query(db_rewrite_sql("SELECT v.*, n.type 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);
Kjartan's avatar
Kjartan committed
517
  while ($vocabulary = db_fetch_object($c)) {
Dries's avatar
Dries committed
518 519 520 521 522 523 524 525 526 527 528 529 530 531
    if ($vocabulary->tags) {
      $typed_terms = array();
      foreach ($terms as $term) {
        if ($term->vid == $vocabulary->vid) {

          // 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;
        }
      }
      $typed_string = implode(', ', $typed_terms) . (array_key_exists('tags', $terms) ? $terms['tags'][$vocabulary->vid] : NULL);
532

533
      $form['taxonomy']['tags'][$vocabulary->vid] = array('#type' => 'textfield', '#default_value' => $typed_string, '#size' => 60, '#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.").'));
Dries's avatar
Dries committed
534 535 536
    }
    else {
      $ntterms = array_key_exists('taxonomy', $node) ? $terms : array_keys($terms);
537
      $form['taxonomy'][$vocabulary->vid] = taxonomy_form($vocabulary->vid, $ntterms, $help, 'taxonomy');
Dries's avatar
Dries committed
538
    }
Dries's avatar
 
Dries committed
539
  }
540 541 542 543 544 545 546 547
  if ($form) {
    $form['taxonomy']['#tree'] = TRUE;
    $form['taxonomy']['#weight'] = -15;
    return $form;
  }
  else {
    return array();
  }
Kjartan's avatar
Kjartan committed
548
}
Dries's avatar
 
Dries committed
549

Dries's avatar
 
Dries committed
550 551 552 553
/**
 * Find all terms associated to the given node, within one vocabulary.
 */
function taxonomy_node_get_terms_by_vocabulary($nid, $vid, $key = 'tid') {
554
  $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
555 556 557
  $terms = array();
  while ($term = db_fetch_object($result)) {
    $terms[$term->$key] = $term;
Dries's avatar
 
Dries committed
558
  }
Kjartan's avatar
Kjartan committed
559 560 561
  return $terms;
}

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

Dries's avatar
 
Dries committed
568
  if (!isset($terms[$nid])) {
569
    $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
570
    $terms[$nid] = array();
Dries's avatar
 
Dries committed
571
    while ($term = db_fetch_object($result)) {
Kjartan's avatar
Kjartan committed
572
      $terms[$nid][$term->$key] = $term;
Dries's avatar
 
Dries committed
573 574
    }
  }
Kjartan's avatar
Kjartan committed
575 576
  return $terms[$nid];
}
Dries's avatar
 
Dries committed
577

Dries's avatar
Dries committed
578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594
/**
 * 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
595 596 597
/**
 * Save term associations for a given node.
 */
Kjartan's avatar
Kjartan committed
598
function taxonomy_node_save($nid, $terms) {
599
  taxonomy_node_delete($nid);
Dries's avatar
Dries committed
600 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

  // 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) {
633 634 635
          $edit = array('vid' => $vid, 'name' => $typed_term);
          $status = taxonomy_save_term($edit);
          $typed_term_tid = $edit['tid'];
Dries's avatar
Dries committed
636 637 638 639 640 641
        }

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

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

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

Dries's avatar
 
Dries committed
666 667 668 669
/**
 * Find all term objects related to a given term ID.
 */
function taxonomy_get_related($tid, $key = 'tid') {
Kjartan's avatar
Kjartan committed
670
  if ($tid) {
Dries's avatar
 
Dries committed
671
    $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
672 673 674
    $related = array();
    while ($term = db_fetch_object($result)) {
      $related[$term->$key] = $term;
Dries's avatar
 
Dries committed
675
    }
Kjartan's avatar
Kjartan committed
676
    return $related;
Dries's avatar
 
Dries committed
677
  }
Kjartan's avatar
Kjartan committed
678 679
  else {
    return array();
Dries's avatar
 
Dries committed
680
  }
Kjartan's avatar
Kjartan committed
681
}
Dries's avatar
 
Dries committed
682

Dries's avatar
 
Dries committed
683 684 685 686
/**
 * Find all parents of a given term ID.
 */
function taxonomy_get_parents($tid, $key = 'tid') {
Kjartan's avatar
Kjartan committed
687
  if ($tid) {
688
    $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
689 690 691
    $parents = array();
    while ($parent = db_fetch_object($result)) {
      $parents[$parent->$key] = $parent;
Dries's avatar
 
Dries committed
692
    }
Kjartan's avatar
Kjartan committed
693
    return $parents;
Dries's avatar
 
Dries committed
694
  }
Kjartan's avatar
Kjartan committed
695 696 697 698
  else {
    return array();
  }
}
Dries's avatar
 
Dries committed
699

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

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

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

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

763
    $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
764
    while ($term = db_fetch_object($result)) {
Dries's avatar
 
Dries committed
765 766 767
      $children[$vid][$term->parent][] = $term->tid;
      $parents[$vid][$term->tid][] = $term->parent;
      $terms[$vid][$term->tid] = $term;
Dries's avatar
 
Dries committed
768 769
    }
  }
Dries's avatar
 
Dries committed
770

Dries's avatar
 
Dries committed
771
  $max_depth = (is_null($max_depth)) ? count($children[$vid]) : $max_depth;
Dries's avatar
Dries committed
772 773 774 775 776 777 778 779 780 781 782 783
  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
784
      }
Dries's avatar
 
Dries committed
785
    }
Kjartan's avatar
Kjartan committed
786
  }
Dries's avatar
 
Dries committed
787

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

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

Dries's avatar
 
Dries committed
807 808 809 810 811
/**
 * 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));