taxonomy.module 54 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
  }
Dries's avatar
 
Dries committed
312

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

Dries's avatar
 
Dries committed
322 323
  cache_clear_all();

324
  return $status;
Kjartan's avatar
Kjartan committed
325
}
Dries's avatar
 
Dries committed
326

Kjartan's avatar
Kjartan committed
327
function taxonomy_del_term($tid) {
328 329 330 331 332 333 334 335 336 337 338 339 340 341
  $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
342

343
      $term = taxonomy_get_term($tid);
Dries's avatar
 
Dries committed
344

345 346 347 348 349
      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
350

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

355 356
    $tids = $orphans;
  }
Dries's avatar
 
Dries committed
357

Dries's avatar
 
Dries committed
358
  cache_clear_all();
Dries's avatar
 
Dries committed
359 360 361 362 363
}

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

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

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

381
  // Show all vocabularies, and a "view terms" link to the pagers.
Dries's avatar
Dries committed
382
  if (!$vid) {
383
    $header = array(t('Name'), t('Type'), array('data' => t('Operations'), 'colspan' => '2'));
Dries's avatar
Dries committed
384 385
    $vocabularies = taxonomy_get_vocabularies();
    foreach ($vocabularies as $vocabulary) {
386 387
      $types = array();
      foreach ($vocabulary->nodes as $type) {
388
        $node_type = node_get_name($type);
389 390
        $types[] = $node_type ? $node_type : $type;
      }
Dries's avatar
Dries committed
391
      $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
392 393 394
    }

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

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

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

Dries's avatar
Dries committed
406 407 408 409 410 411 412 413 414 415
    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; }
416
      $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
417 418 419 420 421 422
      $displayed_count++; // we're counting tids displayed
    }

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

Dries's avatar
Dries committed
424 425
    $GLOBALS['pager_page_array'][] = $start_from;  // FIXME
    $GLOBALS['pager_total'][] = intval($total_entries / $page_increment) + 1; // FIXME
426

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

Dries's avatar
Dries committed
432
  return theme('table', $header, $rows, array('id' => 'taxonomy'));
Kjartan's avatar
Kjartan committed
433 434
}

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

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

451
/**
452 453 454
 * Generate a set of options for selecting a term from all vocabularies. Can be
 * passed to form_select.
 */
Dries's avatar
Dries committed
455
function taxonomy_form_all($free_tags = 0) {
456 457 458
  $vocabularies = taxonomy_get_vocabularies();
  $options = array();
  foreach ($vocabularies as $vid => $vocabulary) {
Dries's avatar
Dries committed
459
    if ($vocabulary->tags && !$free_tags) { continue; }
460 461 462 463 464 465 466 467 468 469 470
    $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
471 472 473 474 475 476
/**
 * 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
477
function taxonomy_get_vocabularies($type = NULL) {
Kjartan's avatar
Kjartan committed
478
  if ($type) {
479
    $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
480 481
  }
  else {
482
    $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
483
  }
Dries's avatar
 
Dries committed
484

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

Kjartan's avatar
Kjartan committed
494 495
  return $vocabularies;
}
Dries's avatar
 
Dries committed
496

Dries's avatar
 
Dries committed
497 498 499
/**
 * Generate a form for selecting terms to associate with a node.
 */
500
function taxonomy_node_form($node) {
Dries's avatar
Dries committed
501
  if (!array_key_exists('taxonomy', $node)) {
Kjartan's avatar
Kjartan committed
502
    if ($node->nid) {
Dries's avatar
Dries committed
503
      $terms = taxonomy_node_get_terms($node->nid);
Kjartan's avatar
Kjartan committed
504 505
    }
    else {
Dries's avatar
Dries committed
506
      $terms = array();
Dries's avatar
 
Dries committed
507
    }
Kjartan's avatar
Kjartan committed
508 509 510 511
  }
  else {
    $terms = $node->taxonomy;
  }
Dries's avatar
 
Dries committed
512

513
  $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
514
  while ($vocabulary = db_fetch_object($c)) {
Dries's avatar
Dries committed
515 516 517 518 519 520 521 522 523 524 525 526 527 528
    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);
529

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

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

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

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

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

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

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

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

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

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

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

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

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

Kjartan's avatar
Kjartan committed
753
  $depth++;
Dries's avatar
 
Dries committed
754

Dries's avatar
 
Dries committed
755 756 757 758
  // 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
759

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

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

Dries's avatar
 
Dries committed
785
  return $tree ? $tree : array();
Kjartan's avatar
Kjartan committed
786
}
Dries's avatar
 
Dries committed
787

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

Dries's avatar
 
Dries committed
804 805 806 807 808
/**
 * 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
809
}
Dries's avatar
 
Dries committed
810