You are here

taxonomy_manager.admin.inc in Taxonomy Manager 6.2

Same filename and directory in other branches
  1. 6 taxonomy_manager.admin.inc
  2. 7 taxonomy_manager.admin.inc

Taxonomy Manager Admin

contains all forms and saving function for the Taxonomy Manager

File

taxonomy_manager.admin.inc
View source
<?php

/**
 *
 * @file
 * Taxonomy Manager Admin
 *
 * contains all forms and saving function for the Taxonomy Manager
 *
 */

/**
 * list of vocabularies, which link to Taxonomy Manager interface
 */
function taxonomy_manager_voc_list() {
  $output = l(t('Add new vocabulary'), 'admin/content/taxonomy/add/vocabulary') . ' | ';
  $output .= l(t('Edit vocabulary settings'), 'admin/content/taxonomy') . '<br /><br />';
  $vocabularies = taxonomy_get_vocabularies();
  $voc_list = array();
  foreach ($vocabularies as $vocabulary) {
    $voc_list[] = l($vocabulary->name, 'admin/content/taxonomy_manager/voc/' . $vocabulary->vid);
  }
  if (!count($voc_list)) {
    $voc_list[] = t('No Vocabularies available');
  }
  $output .= theme('item_list', $voc_list, t("Vocabularies:"));
  return $output;
}

/**
 * defines forms for taxonomy manager interface
 *
 * @param $vid vocabulary id
 * @param $tid a term id, if not 0, displays term editing from for given tid on right side
 * @param $search_string a string to filter root level terms
 */
function taxonomy_manager_form(&$form_state, $vid, $tid = 0, $filter = NULL) {

  // Check for confirmation forms.
  if (isset($form_state['confirm_delete'])) {
    return taxonomy_manager_term_confirm_delete($form_state, $vid);
  }
  $module_path = drupal_get_path('module', 'taxonomy_manager') . '/';
  drupal_add_css($module_path . 'css/taxonomy_manager.css');
  drupal_add_js($module_path . 'js/hideForm.js');
  drupal_add_js($module_path . 'js/updateWeight.js');
  drupal_add_js($module_path . 'js/termData.js');
  drupal_add_js(array(
    'termData' => array(
      'url' => url("admin/content/taxonomy_manager/termdata/edit/" . $vid),
      'tid' => $tid,
      'term_url' => url('admin/content/taxonomy_manager/termdata/' . $vid),
    ),
  ), 'setting');

  //TODO check if values necessary and correct
  drupal_add_js(array(
    'updateWeight' => array(
      'up' => 'edit-weight-up',
      'down' => 'edit-weight-down',
      'url' => url('admin/content/taxonomy_manager/weight/'),
      'disable_mouseover' => variable_get('taxonomy_manager_disable_mouseover', 0),
    ),
  ), 'setting');
  drupal_add_js(array(
    'TMAjaxThrobber' => array(
      'add' => TRUE,
    ),
  ), 'setting');
  drupal_add_js(array(
    'taxonomy_manager' => array(
      'modulePath' => url($module_path) == $module_path ? $module_path : base_path() . $module_path,
    ),
  ), 'setting');
  $form = array();
  $voc = taxonomy_vocabulary_load($vid);
  drupal_set_title(t("Taxonomy Manager - %voc_name", array(
    "%voc_name" => $voc->name,
  )));
  if (!is_numeric($voc->vid)) {
    $text = t('No vocabulary with this ID available! Check this <a href="!list">list</a> for available vocabularies or <a href="!create">create</a> a new one', array(
      '!list' => url('admin/content/taxonomy_manager'),
      '!create' => url('admin/content/taxonomy/add/vocabulary'),
    ));
    $form['text'] = array(
      '#value' => $text,
    );
    return $form;
  }
  $form['vid'] = array(
    '#type' => 'value',
    "#value" => $vid,
  );
  if (_taxonomy_manager_voc_is_empty($vid)) {
    $text = t('No terms available');
    $form['text'] = array(
      '#value' => $text,
    );
    $form += taxonomy_manager_add_form($voc, FALSE);
    return $form;
  }
  $form['#cache'] = TRUE;
  $form['taxonomy']['#tree'] = TRUE;
  $form['taxonomy']['manager'] = array(
    '#type' => 'fieldset',
    '#title' => check_plain($voc->name),
    '#weight' => 10,
    '#tree' => TRUE,
  );
  $form['taxonomy']['manager']['top'] = array(
    '#value' => '',
    '#prefix' => '<div class="taxonomy-manager-tree-top">',
    '#suffix' => '</div>',
  );
  if (module_exists('i18ntaxonomy')) {
    if (i18ntaxonomy_vocabulary($vid) == I18N_TAXONOMY_TRANSLATE) {
      if ($tid) {
        $language = _taxonomy_manager_term_get_lang($tid);
      }
      else {
        $lang = language_default();
        $language = $lang->language;
      }
      $form['taxonomy']['manager']['top']['language'] = array(
        '#type' => 'select',
        '#title' => t('Language'),
        '#default_value' => $language,
        '#options' => array(
          '' => t('All'),
          'no language' => t('no language'),
        ) + locale_language_list('name'),
        '#attributes' => array(
          'class' => 'language-selector',
        ),
      );
    }
  }
  $form['taxonomy']['manager']['top']['size'] = array(
    '#value' => '<div class="taxonomy-manager-tree-size">' . theme("image", $module_path . "images/grippie.png", t("Resize tree"), t("Resize tree"), array(
      'class' => "div-grippie",
    )) . '</div>',
  );
  $form['taxonomy']['manager']['tree'] = array(
    '#type' => 'taxonomy_manager_tree',
    '#vid' => $vid,
    '#pager' => TRUE,
    '#search_string' => $tid ? NULL : $filter,
    '#language' => isset($language) ? $language : '',
    '#term_to_expand' => $tid,
  );
  $search_description = t("You can search directly for exisiting terms.\n      If your input doesn't match an existing term, it will be used for filtering root level terms (useful for non-hierarchical vocabularies).");
  $form['search'] = array(
    '#type' => 'fieldset',
    '#attributes' => array(
      'id' => 'taxonomy-manager-search',
    ),
    '#title' => t('Search'),
    '#description' => $search_description,
    '#collapsible' => TRUE,
    '#collapsed' => TRUE,
    '#tree' => TRUE,
  );
  $form['search']['field'] = array(
    '#type' => 'textfield',
    '#title' => t('Search String'),
    '#autocomplete_path' => 'taxonomy_manager/autocomplete/' . $voc->vid,
    '#prefix' => '<div id="edit-find-field">',
    '#suffix' => '</div>',
  );
  $form['search']['button'] = array(
    '#type' => 'submit',
    '#attributes' => array(
      'class' => 'taxonomy-manager-buttons search',
    ),
    '#value' => t('Search'),
    '#suffix' => '<div class="clear"></div>',
  );
  $search_options = array(
    'synonyms' => t('Include synonyms'),
    'subtrees' => t('Search under selected terms'),
  );
  if (module_exists('i18ntaxonomy')) {
    if (i18ntaxonomy_vocabulary($vid) == I18N_TAXONOMY_TRANSLATE) {
      $search_options['language'] = t('Search within selected language');
    }
  }
  $form['search']['options'] = array(
    '#type' => 'checkboxes',
    '#title' => t('Search options'),
    '#options' => $search_options,
  );
  $form['toolbar'] = array(
    '#type' => 'fieldset',
    '#title' => t('Toolbar'),
    '#attributes' => array(
      'id' => 'taxonomy-manager-toolbar',
    ),
  );
  $form['toolbar']['weight_up'] = array(
    '#type' => 'button',
    '#attributes' => array(
      'class' => 'taxonomy-manager-buttons',
    ),
    '#value' => t('Up'),
    '#theme' => 'no_submit_button',
    '#prefix' => '<div id="taxonomy-manager-toolbar-buttons">',
  );
  $form['toolbar']['weight-down'] = array(
    '#type' => 'button',
    '#attributes' => array(
      'class' => 'taxonomy-manager-buttons',
    ),
    '#value' => t('Down'),
    '#theme' => 'no_submit_button',
  );
  $form['toolbar']['delete_confirm'] = array(
    '#type' => 'button',
    '#attributes' => array(
      'class' => 'taxonomy-manager-buttons delete',
    ),
    '#value' => t('Delete'),
    '#theme' => 'no_submit_button',
  );
  $form['toolbar']['add_show'] = array(
    '#type' => 'button',
    '#attributes' => array(
      'class' => 'taxonomy-manager-buttons add',
    ),
    '#value' => t('Add'),
    '#theme' => 'no_submit_button',
  );
  $form['toolbar']['move_show'] = array(
    '#type' => 'button',
    '#value' => t('Move'),
    '#attributes' => array(
      'class' => 'taxonomy-manager-buttons move',
    ),
    '#theme' => 'no_submit_button',
  );
  $form['toolbar']['merge_show'] = array(
    '#type' => 'button',
    '#attributes' => array(
      'class' => 'taxonomy-manager-buttons merge',
    ),
    '#value' => t('Merge'),
    '#theme' => 'no_submit_button',
  );
  $form['toolbar']['export_show'] = array(
    '#type' => 'button',
    '#attributes' => array(
      'class' => 'taxonomy-manager-buttons export',
    ),
    '#value' => t('CSV Export'),
    '#theme' => 'no_submit_button',
  );
  $form['toolbar']['double_tree_show'] = array(
    '#type' => 'button',
    '#attributes' => array(
      'class' => 'taxonomy-manager-buttons double-tree',
    ),
    '#value' => t('Double Tree'),
    '#theme' => 'no_submit_button',
  );
  $form['toolbar']['wrapper'] = array(
    '#type' => 'markup',
    '#value' => '<div id="taxonomy-manager-toolbar-throbber"></div><div class="clear"></div>',
    '#weight' => 20,
    '#prefix' => '</div>',
  );
  $form['toolbar_forms_wrapper'] = array(
    '#type' => 'markup',
    '#value' => '<div id="taxonomy-manager-toolbar-forms"></div>',
  );
  $form += taxonomy_manager_add_form($voc);
  $form += taxonomy_manager_merge_form($voc);
  $form += taxonomy_manager_move_form($voc);
  $form += taxonomy_manager_confirm_delete($voc);
  $form += taxonomy_manager_export_form($voc);
  $form += taxonomy_manager_double_tree_settings_form($voc);
  if ($tid) {
    $form += taxonomy_manager_form_term_data($tid);
  }
  else {
    $form['term_data'] = array(
      '#tree' => TRUE,
    );
  }

  // add save button for term_data already to the form array,
  // but do not render (see theme_taxonomy_manager_form) if not needed
  // otherwise an #ahah callback on dynamically added forms makes problems
  $form['term_data']['save'] = array(
    '#type' => 'submit',
    '#value' => t('Save changes'),
    '#submit' => array(
      '',
    ),
    '#attributes' => array(
      'class' => 'taxonomy-manager-buttons save',
    ),
    '#ahah' => array(
      'path' => 'admin/content/taxonomy_manager/termdata/edit',
      'method' => 'replace',
      'event' => 'click',
      'wrapper' => 'taxonomy-term-data',
      'progress' => array(
        'type' => '',
      ),
    ),
    '#weight' => 20,
  );
  return $form;
}
function taxonomy_manager_double_tree_form(&$form_state, $vid1, $vid2, $tid = 0, $filter = NULL) {

  // Check for confirmation forms.
  if (isset($form_state['confirm_delete'])) {
    return taxonomy_manager_term_confirm_delete($form_state, $vid1, $vid2);
  }
  $module_path = drupal_get_path('module', 'taxonomy_manager') . '/';
  $form = taxonomy_manager_form($form_state, $vid1, $tid, $filter);
  drupal_add_js(array(
    'DoubleTree' => array(
      'enabled' => TRUE,
      'url' => url('admin/content/taxonomy_manager/double-tree/edit'),
    ),
  ), 'setting');
  drupal_add_js($module_path . 'js/doubleTree.js');
  $form['disable'] = array(
    '#value' => l(t('Disable Double Tree'), 'admin/content/taxonomy_manager/voc/' . $vid1),
    '#weight' => -100,
  );
  $voc2 = taxonomy_vocabulary_load($vid2);
  $form['vid2'] = array(
    '#type' => 'value',
    "#value" => $vid2,
  );
  $form['taxonomy2'] = array(
    '#tree' => TRUE,
  );
  $form['taxonomy2']['manager'] = array(
    '#type' => 'fieldset',
    '#title' => check_plain($voc2->name),
    '#weight' => 10,
    '#tree' => TRUE,
  );
  $form['taxonomy2']['manager']['top'] = array(
    '#value' => '',
    '#prefix' => '<div class="taxonomy-manager-tree-top">',
    '#suffix' => '</div>',
  );
  if (module_exists('i18ntaxonomy')) {
    if (i18ntaxonomy_vocabulary($vid2) == I18N_TAXONOMY_TRANSLATE) {
      if ($tid) {
        $language = _taxonomy_manager_term_get_lang($tid);
      }
      else {
        $lang = language_default();
        $language = $lang->language;
      }
      $form['taxonomy2']['manager']['top']['language'] = array(
        '#type' => 'select',
        '#title' => t('Language'),
        '#default_value' => $language,
        '#options' => array(
          '' => t('All'),
          'no language' => t('no language'),
        ) + locale_language_list('name'),
        '#attributes' => array(
          'class' => 'language-selector',
        ),
      );
    }
  }
  $form['taxonomy2']['manager']['top']['size'] = array(
    '#value' => '<div class="taxonomy-manager-tree-size">' . theme("image", $module_path . "images/grippie.png", t("Resize tree"), t("Resize tree"), array(
      'class' => "div-grippie",
    )) . '</div>',
  );
  $form['taxonomy2']['manager']['tree'] = array(
    '#type' => 'taxonomy_manager_tree',
    '#vid' => $vid2,
    '#pager' => TRUE,
    '#search_string' => $tid ? NULL : $filter,
    '#language' => isset($language) ? $language : '',
    '#term_to_expand' => $tid,
  );
  $form['double-tree']['operations'] = array(
    '#tree' => TRUE,
  );
  $form['double-tree']['operations']['move_right'] = array(
    '#type' => 'image_button',
    '#value' => 'Move right',
    '#attributes' => array(
      'title' => t('Move right'),
    ),
    '#src' => $module_path . "images/go-next.png",
    //'#executes_submit_callback' => FALSE,
    '#prefix' => '<div class="taxonomy-manager-double-tree-operations-buttons">',
    '#suffix' => '</div>',
  );
  $form['double-tree']['operations']['move_left'] = array(
    '#type' => 'image_button',
    '#value' => 'Move left',
    '#attributes' => array(
      'title' => t('Move left'),
    ),
    '#src' => $module_path . "images/go-previous.png",
    //'#executes_submit_callback' => FALSE,
    '#prefix' => '<div class="taxonomy-manager-double-tree-operations-buttons">',
    '#suffix' => '</div>',
  );

  //switch operations
  if ($vid1 != $vid2) {
    $form['double-tree']['operations']['move_right']['#value'] = 'Switch right';
    $form['double-tree']['operations']['move_right']['#attributes']['title'] = t('Switch selected terms and its children to the right voc');
    $form['double-tree']['operations']['move_left']['#value'] = 'Switch left';
    $form['double-tree']['operations']['move_left']['#attributes']['title'] = t('Switch selected terms and its children to the left voc');
  }
  else {
    if (isset($language)) {
      $form['double-tree']['operations']['add_translation'] = array(
        '#type' => 'image_button',
        '#value' => 'translation',
        '#attributes' => array(
          'title' => t('Add Translation'),
        ),
        '#src' => $module_path . "images/connect.png",
        //'#executes_submit_callback' => FALSE,
        '#prefix' => '<div class="taxonomy-manager-double-tree-operations-buttons">',
        '#suffix' => '</div>',
      );
    }
  }
  return $form;
}
function taxonomy_manager_toolbar_forms() {

  /*$params = $_GET;
    $form = array();
    $form_state = array('submitted' => FALSE);
    $form = form_get_cache($params['form_build_id'], $form_state);

    $form += taxonomy_manager_confirm_delete($form['vid']);
    $form = form_builder($param['form_id'], $form, $form_state);
    drupal_prepare_form($param['form_id'], $form, $form_state);
    $form = form_builder($param['form_id'], $form, $form_state);
    form_set_cache($params['form_build_id'], $form, $form_state);

    $output = drupal_render($form['delete']);


    print drupal_to_js(array('status' => TRUE, 'data' => $output));
    exit;*/
}

/**
 * confirmation form for deleting selected terms
 */
function taxonomy_manager_confirm_delete($voc) {
  drupal_add_js(array(
    'hideForm' => array(
      'show_button' => 'edit-delete-confirm',
      'hide_button' => 'edit-delete-cancel',
      'div' => 'del-confirm-form',
    ),
  ), 'setting');
  $form = array();
  $form['delete'] = array(
    '#type' => 'fieldset',
    '#attributes' => array(
      'id' => 'del-confirm-form',
      'style' => 'display:none;',
    ),
    '#tree' => TRUE,
    '#title' => t('Confirmation'),
  );
  $question = t('Are you sure you want to delete all selected terms? ');
  $info = t('Remember all term specific data will be lost. This action cannot be undone.');
  $form['delete']['text'] = array(
    '#value' => "<b>" . $question . "</b><br/>" . $info,
  );
  $options = array(
    'delete_orphans' => t('Delete children of selected terms, if there are any'),
  );
  $form['delete']['options'] = array(
    '#type' => 'checkboxes',
    '#title' => t('Options'),
    '#options' => $options,
  );
  $form['delete']['delete'] = array(
    '#type' => 'submit',
    '#value' => t('Delete'),
    '#attributes' => array(
      'class' => 'taxonomy-manager-buttons delete',
    ),
    '#submit' => array(
      'taxonomy_manager_form_delete_submit',
    ),
    '#validate' => array(
      'taxonomy_manager_form_delete_validate',
    ),
  );
  $form['delete']['cancel'] = array(
    '#type' => 'button',
    '#attributes' => array(
      'class' => 'taxonomy-manager-buttons cancel',
    ),
    '#value' => t('Cancel'),
    '#theme' => 'no_submit_button',
  );
  return $form;
}

/**
 * form for adding terms
 */
function taxonomy_manager_add_form($voc, $hide_form = TRUE) {
  if ($hide_form) {
    drupal_add_js(array(
      'hideForm' => array(
        'show_button' => 'edit-add-show',
        'hide_button' => 'edit-add-cancel',
        'div' => 'add-form',
      ),
    ), 'setting');
    $attributes = array(
      'id' => 'add-form',
      'style' => 'display:none;',
    );
  }
  else {
    $attributes = array(
      'id' => 'add-form',
    );
  }
  $form = array();
  $description = "";
  $description = t("If you have selected one or more terms in the tree view, the new terms are automatically children of those.");
  $form['add'] = array(
    '#type' => 'fieldset',
    '#tree' => TRUE,
    '#attributes' => $attributes,
    '#title' => t('Add new terms'),
    '#description' => $description,
  );
  for ($i = 0; $i < 6; $i++) {
    $form['add']['term'][$i] = array(
      '#type' => 'textfield',
    );
  }
  $form['add']['mass'] = array(
    '#type' => 'fieldset',
    '#tree' => TRUE,
    '#title' => t('Mass term import (with textarea)'),
    '#collapsible' => TRUE,
    '#collapsed' => TRUE,
  );
  $form['add']['mass']['mass_add'] = array(
    '#type' => 'textarea',
    '#title' => t('Terms'),
    '#description' => t('One term per line'),
    '#rows' => 10,
  );
  $form['add']['add'] = array(
    '#type' => 'submit',
    '#attributes' => array(
      'class' => 'taxonomy-manager-buttons add',
    ),
    '#value' => t('Add'),
    '#validate' => array(
      'taxonomy_manager_form_add_validate',
    ),
    '#submit' => array(
      'taxonomy_manager_form_add_submit',
    ),
  );
  $form['add']['cancel'] = array(
    '#type' => 'button',
    '#value' => t('Cancel'),
    '#theme' => 'no_submit_button',
    '#attributes' => array(
      'class' => 'taxonomy-manager-buttons cancel',
    ),
  );
  return $form;
}

/**
 * form for merging terms
 */
function taxonomy_manager_merge_form($voc) {
  drupal_add_js(array(
    'hideForm' => array(
      'show_button' => 'edit-merge-show',
      'hide_button' => 'edit-merge-cancel',
      'div' => 'merge-form',
    ),
  ), 'setting');
  $form = array();
  $description .= t("The selected terms get merged into one term.\n    This resulting merged term can either be an exisiting term or a completely new term.\n    The selected terms will automatically get synomyms of the merged term and will be deleted afterwards.");
  $form['merge'] = array(
    '#type' => 'fieldset',
    '#tree' => TRUE,
    '#attributes' => array(
      'id' => 'merge-form',
      'style' => 'display:none;',
    ),
    '#title' => t('Merging of terms'),
    '#description' => $description,
  );
  $form['merge']['main_term'] = array(
    '#type' => 'textfield',
    '#title' => t('Resulting merged term'),
    '#description' => t("Enter a unique term name or a term id with 'term-id:[tid]'"),
    '#required' => FALSE,
    '#autocomplete_path' => 'taxonomy_manager/autocomplete/' . $voc->vid,
  );
  $options = array();
  $options['collect_parents'] = t('Collect all parents of selected terms an add it to the merged term');
  $options['collect_children'] = t('Collect all children of selected terms an add it to the merged term');
  $options['collect_relations'] = t('Collect all relations of selected terms an add it to the merged term');
  if (count($options) > 0) {
    $form['merge']['options'] = array(
      '#type' => 'checkboxes',
      '#title' => t('Options'),
      '#options' => $options,
    );
  }
  $form['merge']['submit'] = array(
    '#type' => 'submit',
    '#value' => t('Merge'),
    '#attributes' => array(
      'class' => 'taxonomy-manager-buttons merge',
    ),
    '#validate' => array(
      'taxonomy_manager_form_merge_validate',
    ),
    '#submit' => array(
      'taxonomy_manager_form_merge_submit',
    ),
  );
  $form['merge']['cancel'] = array(
    '#type' => 'button',
    '#value' => t('Cancel'),
    '#attributes' => array(
      'class' => 'taxonomy-manager-buttons cancel',
    ),
    '#theme' => 'no_submit_button',
  );
  return $form;
}

/**
 * form for moving terms in hierarchies
 */
function taxonomy_manager_move_form($voc) {
  drupal_add_js(array(
    'hideForm' => array(
      'show_button' => 'edit-move-show',
      'hide_button' => 'edit-move-cancel',
      'div' => 'move-form',
    ),
  ), 'setting');
  $form = array();
  $description = t("You can change the parent of one or more selected terms.\n      If you leave the autocomplete field empty, the term will be a root term.");
  $form['move'] = array(
    '#type' => 'fieldset',
    '#tree' => TRUE,
    '#attributes' => array(
      'id' => 'move-form',
      'style' => 'display:none;',
    ),
    '#title' => t('Moving of terms'),
    '#description' => $description,
  );
  $form['move']['parents'] = array(
    '#type' => 'textfield',
    '#title' => t('Parent term(s)'),
    '#description' => t("Enter a unique term name or a term id with 'term-id:[tid]'. Separate multiple parent terms with commas."),
    '#required' => FALSE,
    '#autocomplete_path' => 'taxonomy_manager/autocomplete/' . $voc->vid,
  );
  $options = array();
  $options['keep_old_parents'] = t('Keep old parents and add new ones (multi-parent). Otherwise old parents get replaced.');
  $form['move']['options'] = array(
    '#type' => 'checkboxes',
    '#title' => t('Options'),
    '#options' => $options,
  );
  $form['move']['submit'] = array(
    '#type' => 'submit',
    '#attributes' => array(
      'class' => 'taxonomy-manager-buttons move',
    ),
    '#value' => t('Move'),
    '#validate' => array(
      'taxonomy_manager_form_move_validate',
    ),
    '#submit' => array(
      'taxonomy_manager_form_move_submit',
    ),
  );
  $form['move']['cancel'] = array(
    '#type' => 'button',
    '#value' => t('Cancel'),
    '#attributes' => array(
      'class' => 'taxonomy-manager-buttons cancel',
    ),
    '#theme' => 'no_submit_button',
  );
  return $form;
}

/**
 * form for exporting terms
 */
function taxonomy_manager_export_form($voc) {
  drupal_add_js(array(
    'hideForm' => array(
      'show_button' => 'edit-export-show',
      'hide_button' => 'edit-export-cancel',
      'div' => 'export-form',
    ),
  ), 'setting');
  $module_path = drupal_get_path('module', 'taxonomy_manager') . '/';
  drupal_add_js($module_path . 'js/csv_export.js');
  drupal_add_js(array(
    'exportCSV' => array(
      'url' => url("admin/content/taxonomy_manager/export"),
    ),
  ), 'setting');
  $form = array();
  $form['export'] = array(
    '#type' => 'fieldset',
    '#tree' => TRUE,
    '#attributes' => array(
      'id' => 'export-form',
      'style' => 'display:none;',
    ),
    '#title' => t('CSV Export'),
    '#description' => $description,
  );
  $form['export']['delimiter'] = array(
    '#type' => 'textfield',
    '#title' => t('Delimiter for CSV File'),
    '#required' => FALSE,
    '#default_value' => ";",
  );
  $options['whole_voc'] = t('Whole Vocabulary');
  $options['children'] = t('Child terms of a selected term');
  $options['root_terms'] = t('Root level terms only');
  $form['export']['options'] = array(
    '#type' => 'radios',
    '#title' => t('Terms to export'),
    '#options' => $options,
    '#default_value' => 'whole_voc',
    '#prefix' => '<div id="taxonomy_manager_export_options">',
    '#suffix' => '</div>',
  );
  $form['export']['depth'] = array(
    '#type' => 'textfield',
    '#title' => t('Depth of tree'),
    '#description' => t('The number of levels of the tree to export. Leave empty to return all levels.'),
  );
  $form['export']['csv'] = array(
    '#type' => 'textarea',
    '#title' => t('Exported CSV'),
    '#description' => t('The generated code will appear here (per AJAX). You can copy and paste the code into a .csv file. The csv has following columns: voc id | term id | term name | description | parent id 1 | ... | parent id n'),
    '#rows' => 8,
  );
  $form['export']['submit'] = array(
    '#type' => 'submit',
    '#attributes' => array(
      'class' => 'taxonomy-manager-buttons export',
    ),
    '#value' => t('Export now'),
    '#theme' => 'no_submit_button',
  );
  $form['export']['cancel'] = array(
    '#type' => 'button',
    '#value' => t('Cancel'),
    '#attributes' => array(
      'class' => 'taxonomy-manager-buttons cancel',
    ),
    '#theme' => 'no_submit_button',
  );
  return $form;
}
function taxonomy_manager_double_tree_settings_form($voc) {
  drupal_add_js(array(
    'hideForm' => array(
      'show_button' => 'edit-double-tree-show',
      'hide_button' => 'edit-double-tree-cancel',
      'div' => 'double-tree-settings-form',
    ),
  ), 'setting');
  $form = array();
  $form['double_tree'] = array(
    '#type' => 'fieldset',
    '#tree' => TRUE,
    '#attributes' => array(
      'id' => 'double-tree-settings-form',
      'style' => 'display:none;',
    ),
    '#title' => t('Double Tree Settings'),
    '#description' => t('Specify settings for second tree. Choose the same vocabulary if you want to move terms in the hierarchy or if you want to add new translations within a multilingual vocabulary. Choose a different vocabulary if you want to switch terms among these vocabularies.'),
  );
  $options = array();
  $vocs = taxonomy_get_vocabularies();
  foreach ($vocs as $v) {
    $options[$v->vid] = $v->name;
  }
  $form['double_tree']['voc2'] = array(
    '#type' => 'select',
    '#title' => t('Vocabulary for second tree'),
    '#options' => $options,
    '#default_value' => $voc->vid,
  );
  $form['double_tree']['submit'] = array(
    '#type' => 'submit',
    '#attributes' => array(
      'class' => 'taxonomy-manager-buttons double-tree',
    ),
    '#value' => t('Enable Double Tree'),
    '#submit' => array(
      'taxonomy_manager_form_double_tree_submit',
    ),
  );
  if (arg(3) == "double-tree") {
    $form['double_tree']['disable'] = array(
      '#type' => 'submit',
      '#attributes' => array(
        'class' => 'taxonomy-manager-buttons double-tree-disable',
      ),
      '#value' => t('Disable Double Tree'),
      '#submit' => array(
        'taxonomy_manager_form_double_tree_disable_submit',
      ),
    );
  }
  $form['double_tree']['cancel'] = array(
    '#type' => 'button',
    '#value' => t('Cancel'),
    '#attributes' => array(
      'class' => 'taxonomy-manager-buttons cancel',
    ),
    '#theme' => 'no_submit_button',
  );
  return $form;
}

/**
 * menu callback for displaying term data form
 *
 * if this function gets called by ahah, then the term data form gets
 * generated, rendered and return
 * otherwise, if no ahah call, redirect to original form with $vid and $tid as parameters
 *
 * @param $vid
 * @param $tid
 * @param $ahah if true, return rendered form, else redirect
 */
function taxonomy_manager_update_term_data_form($vid, $tid, $ahah = FALSE, $print = TRUE, $msg = "", $is_error_msg = FALSE) {
  if (!$ahah) {
    drupal_goto('admin/content/taxonomy_manager/voc/' . $vid . '/' . $tid);
  }
  $GLOBALS['devel_shutdown'] = FALSE;

  //prevent devel queries footprint
  $params = $_GET;

  //actually we don not need do use the caching because the saving only happens through a AJAX callback

  //and it's a bit faster, cache loading, form building and cache saving needs some time else.

  /*$form_state = array('submitted' => FALSE);
    $form = form_get_cache($params['form_build_id'], $form_state);
    unset($form['term_data']);
    $form = form_builder($param['form_id'], $form, $form_state);*/
  $form_state = array();
  $term_form = taxonomy_manager_form_term_data($tid);
  $term_form['term_data']['save'] = array(
    '#type' => 'submit',
    '#value' => t('Save changes'),
    '#submit' => array(
      '',
    ),
    '#attributes' => array(
      'class' => 'taxonomy-manager-buttons save',
    ),
    '#ahah' => array(
      'path' => 'admin/content/taxonomy_manager/termdata/edit',
      'method' => 'replace',
      'event' => 'click',
      'wrapper' => 'taxonomy-term-data',
      'progress' => array(
        'type' => '',
      ),
    ),
    '#weight' => 20,
  );
  if ($msg != "") {
    $term_form['term_data']['msg'] = array(
      '#type' => 'markup',
      '#prefix' => '<div class="messages status">',
      '#suffix' => '</div>',
      '#value' => $msg,
      '#weight' => -20,
    );
    if ($is_error_msg) {
      $term_form['term_data']['msg']['#value'] = t("Error! Your last operation couldn't be performed because of following problem:") . " " . $msg;
      $term_form['term_data']['msg']['#prefix'] = '<div class="message error">';
    }
  }
  $form = $term_form;
  drupal_prepare_form('taxonomy_manager_form', $form, $form_state);
  $form = form_builder('taxonomy_manager_form', $form, $form_state);

  //form_set_cache($params['form_build_id'], $form, $form_state);
  $output = drupal_render($form['term_data']);
  if ($print) {
    print $output;
    exit;
  }
  return $output;
}

/**
 * term data editing form
 *
 * @param $tid
 */
function taxonomy_manager_form_term_data($tid) {
  $term = taxonomy_get_term($tid);
  $module_path = drupal_get_path('module', 'taxonomy_manager') . '/';
  $vocabulary = taxonomy_vocabulary_load($term->vid);

  //prevent that title of the fieldset is too long
  $title = $term->name;
  if (drupal_strlen($title) >= 33) {
    $title = drupal_substr($title, 0, 33) . "...";
  }
  $title .= " (" . $term->tid . ")";
  $title = check_plain($title);
  $form['term_data'] = array(
    '#type' => 'fieldset',
    '#title' => $title,
    '#attributes' => array(
      'id' => 'taxonomy-term-data-fieldset',
    ),
    '#tree' => TRUE,
  );
  $form['term_data']['close'] = array(
    '#value' => '<div id="term-data-close"><span title="' . t('Close') . '">&nbsp;&nbsp;&nbsp;&nbsp;</span></div>',
    '#weight' => -100,
  );
  $form['term_data']['tid'] = array(
    '#type' => 'hidden',
    '#value' => $tid,
  );
  $form['term_data']['name'] = array(
    '#type' => 'textfield',
    '#title' => t('Name'),
    '#default_value' => $term->name,
    '#size' => 35,
    '#maxlength' => 255,
    '#required' => TRUE,
    '#weight' => -20,
  );
  $form['term_data']['description'] = array(
    '#type' => 'textarea',
    '#title' => t('Description'),
    '#default_value' => $term->description,
    '#cols' => 35,
    '#rows' => 3,
  );
  $synonyms = taxonomy_get_synonyms($term->tid);
  asort($synonyms);
  $form['term_data']['synonyms'] = _taxonomy_manager_form_term_data_lists($term, $synonyms, t('Synonyms'), 'synonym', FALSE);
  $form['term_data']['synonyms']['#tree'] = TRUE;
  $form['term_data']['synonyms']['#weight'] = '50';
  $form['term_data']['relations'] = _taxonomy_manager_form_term_data_lists($term, taxonomy_get_related($term->tid), t('Relations'), 'related');
  $form['term_data']['relations']['#tree'] = TRUE;
  $form['term_data']['relations']['#weight'] = '51';
  $parents = taxonomy_get_parents($term->tid);
  $form['term_data']['parents'] = _taxonomy_manager_form_term_data_lists($term, $parents, t('Parents'), 'parent', TRUE);
  $form['term_data']['parents']['#tree'] = TRUE;
  $form['term_data']['parents']['#weight'] = '52';
  if (module_exists('i18ntaxonomy')) {
    if (i18ntaxonomy_vocabulary($term->vid) == I18N_TAXONOMY_TRANSLATE) {
      $translations = i18ntaxonomy_term_get_translations(array(
        'tid' => $term->tid,
      ), FALSE);
      $form['term_data']['translations'] = _taxonomy_manager_form_term_data_translations($term, $translations, t('Translations'), 'translation', TRUE);
      $form['term_data']['translations']['#tree'] = TRUE;
      $form['term_data']['translations']['#weight'] = '53';
      $form['term_data']['language'] = array(
        '#type' => 'select',
        '#title' => t('Language'),
        '#default_value' => isset($term) && !empty($term->language) ? $term->language : '',
        '#options' => array(
          '' => '',
        ) + locale_language_list('name'),
        '#description' => t('This term belongs to a multilingual vocabulary. You can set a language for it.'),
        '#weight' => 54,
      );
    }
  }
  $form['term_data']['weight'] = array(
    '#type' => 'weight',
    '#default_value' => $term->weight,
    '#delta' => 50,
    '#prefix' => '<div id="term-data-weight">',
    '#suffix' => '</div>',
    '#title' => t('Weight'),
    '#weight' => 55,
  );
  $link_img = theme("image", $module_path . "images/link-small.png", "link to term page");
  $form['term_data']['link'] = array(
    '#value' => '<br />' . l($link_img . '&nbsp;' . t('Go to the term page'), taxonomy_term_path($term), array(
      'attributes' => array(
        'rel' => 'tag',
        'title' => strip_tags($term->description),
        'target' => '_blank',
      ),
      'html' => TRUE,
    )),
    '#weight' => '56',
  );
  $form['term_data']['vid'] = array(
    '#type' => 'hidden',
    '#value' => $term->vid,
  );
  return $form;
}

/**
 * helper function for generating tables with values and delete op and field for adding
 *
 * @param $term term object which is going to be displayed
 * @param $values array of values to show, e.g related terms, synonyms, parents, children
 * @param $header_type string to display as header
 * @param $attr attribute type to show, can be 'related', 'synonym', 'parent', 'child'
 * @param $autocomplete if true, adds autocomplete, else a textfield
 * @param $add if true, shows add operation
 * @return an form array
 */
function _taxonomy_manager_form_term_data_lists($term, $values, $header_type, $attr, $autocomplete = TRUE, $add = TRUE) {
  $module_path = drupal_get_path('module', 'taxonomy_manager') . '/';
  $rows = array();
  $form['#theme'] = 'taxonomy_manager_term_data_extra';
  $form['data'] = array();
  foreach ($values as $tid => $value) {
    if (is_object($value)) {
      $name = $value->name;
      $id = $value->tid;
      $vid = $value->vid;
      $extra_info = taxonomy_manager_tree_term_extra_info($value);
    }
    else {
      $name = $value;
      $id = $value;
    }
    $form['data'][$id][] = array(
      '#value' => isset($vid) && $vid > 0 ? l($name, 'admin/content/taxonomy_manager/termdata/' . $vid . "/" . $id, array(
        'attributes' => array(
          'title' => $extra_info,
          'class' => 'taxonomy-term-data-name-link',
        ),
      )) : check_plain($name),
      '#row-class' => 'taxonomy-term-data-name',
      '#row-id' => 'term-' . $id,
    );
    $form['data'][$id][] = array(
      '#value' => '<span class="' . $attr . '" title="' . t('Remove') . '">&nbsp;</span>',
      '#row-class' => 'taxonomy-term-data-operations',
    );
  }
  $form['headers'][] = array(
    '#value' => $header_type,
  );
  $form['headers'][] = array(
    '#value' => '',
  );
  $form['op'] = array();
  if ($add) {
    $form['op']['add'] = array(
      '#type' => 'textfield',
      '#prefix' => '<div class="term-data-autocomplete">',
      '#suffix' => '</div>',
      '#size' => 35,
    );
    if ($autocomplete) {
      $form['op']['add']['#autocomplete_path'] = 'taxonomy_manager/autocomplete/' . $term->vid;
    }
    $form['op']['add_button'] = array(
      '#value' => '<span class="' . $attr . '" title="' . t('Add') . '">&nbsp;</span>',
      '#prefix' => '<div class="term-data-autocomplete-add">',
      '#suffix' => '</div>',
    );
  }
  return $form;
}

/**
 * helper function for generating a table listing the translations
 */
function _taxonomy_manager_form_term_data_translations($term, $translations, $header_type, $attr, $autocomplete = TRUE, $add = TRUE) {
  $module_path = drupal_get_path('module', 'taxonomy_manager') . '/';
  $rows = array();
  $form['#theme'] = 'taxonomy_manager_term_data_extra';
  $form['data'] = array();
  foreach ($translations as $tid => $value) {
    if (is_object($value)) {
      $name = $value->name;
      $id = $value->tid;
      $vid = $value->vid;
      $lang = $value->language;
      $trid = $value->trid;
      $extra_info = taxonomy_manager_tree_term_extra_info($value);
    }
    $form['data'][$id][] = array(
      '#value' => isset($vid) && $vid > 0 ? l($name, 'admin/content/taxonomy_manager/termdata/' . $vid . "/" . $id, array(
        'attributes' => array(
          'title' => $extra_info,
        ),
      )) : check_plain($name),
      '#row-class' => 'taxonomy-term-data-name',
      '#row-id' => 'term-' . $id,
    );
    $form['data'][$id][] = array(
      '#value' => check_plain(locale_language_name($lang)),
      '#row-class' => 'taxonomy-term-data-lang',
      '#row-id' => 'term-lang-' . $id,
    );
    $form['data'][$id][] = array(
      '#value' => '<span class="' . $attr . '" title="' . t('Remove') . '">&nbsp;</span>',
      '#row-class' => 'taxonomy-term-data-operations',
    );
  }
  $form['headers'][] = array(
    '#value' => $header_type,
  );
  $form['headers'][] = array(
    '#value' => t('Language'),
  );
  $form['headers'][] = array(
    '#value' => '',
  );
  $form['op'] = array();
  if ($add) {
    $form['op']['add'] = array(
      '#type' => 'textfield',
      '#prefix' => '<div class="term-data-autocomplete">',
      '#suffix' => '</div>',
      '#size' => 35,
    );
    $form['op']['lang'] = array(
      '#type' => 'select',
      '#options' => array(
        '' => '',
      ) + locale_language_list('name'),
      '#default value' => '',
    );
    if ($autocomplete) {
      $form['op']['add']['#autocomplete_path'] = 'taxonomy_manager/autocomplete/' . $term->vid;
    }
    $form['op']['add_button'] = array(
      '#value' => '<span class="' . $attr . '" title="' . t('Add') . '">&nbsp;</span>',
      '#prefix' => '<div class="term-data-autocomplete-add">',
      '#suffix' => '</div>',
    );
  }
  return $form;
}

/**
 * validates the form (only search button)
 **/
function taxonomy_manager_form_validate($form, &$form_state) {
  if ($form_state['clicked_button']['#value'] == t('Search') && empty($form_state['values']['search']['field'])) {
    form_set_error('search', t('Search field is empty'));
    $form_state['rebuild'] = TRUE;
  }
}

/**
 * submits the taxonomy manager form (only search button)
 **/
function taxonomy_manager_form_submit($form, &$form_state) {
  if ($form_state['values']['delete'] === TRUE) {
    return taxonomy_manager_term_confirm_delete_submit($form, $form_state);
  }
  if (isset($form_state['values']['vid2'])) {
    $url_prefix = 'admin/content/taxonomy_manager/double-tree/' . $form_state['values']['vid'] . '/' . $form_state['values']['vid2'];
  }
  else {
    $url_prefix = 'admin/content/taxonomy_manager/voc/' . $form_state['values']['vid'];
  }
  $search_string = $form_state['values']['search']['field'];
  $terms = array();
  $include_synonyms = FALSE;
  $selected_tids = array();
  if ($form_state['values']['search']['options']['synonyms']) {
    $include_synonyms = TRUE;
  }
  if ($form_state['values']['search']['options']['subtrees']) {
    $selected_tids = $form_state['values']['taxonomy']['manager']['tree']['selected_terms'];
  }
  if ($form_state['values']['search']['options']['language']) {
    $language = $form_state['values']['taxonomy']['manager']['top']['language'];
  }
  $terms = taxonomy_manager_autocomplete_search_terms($search_string, $form_state['values']['vid'], $include_synonyms, $selected_tids, $language);
  if (count($terms) == 1) {
    $tid = $terms[0];
    drupal_set_message(t("Your search string matches exactly one term"));
    drupal_goto($url_prefix . '/' . $tid);
  }
  else {
    if (count($terms) > 1) {
      $matched_text_list = array();
      foreach ($terms as $matched_tid) {
        $matched_term = taxonomy_get_term($matched_tid);
        $parents = array();
        foreach (taxonomy_get_parents($matched_tid) as $parent) {
          $parents[] = check_plain($parent->name);
        }
        $parent_text = count($parents) ? implode(' | ', $parents) . " › " : "";
        $term = taxonomy_get_term($t['tid']);
        $matched_text_list[] = $parent_text . "" . l($matched_term->name, $url_prefix . '/' . $matched_term->tid, array(
          'attributes' => array(
            'title' => taxonomy_manager_tree_term_extra_info($matched_term),
          ),
        )) . " (" . $matched_term->tid . (!empty($matched_term->language) ? '-' . check_plain($matched_term->language) : '') . ")";
      }
      drupal_set_message(t("Your search string matches !count terms:", array(
        '!count' => count($terms),
      )) . "" . theme('item_list', $matched_text_list));
      $form_state['rebuild'] = TRUE;
    }
    else {
      drupal_set_message(t("No match found. Filtering root level terms starting with @search_string.", array(
        '@search_string' => $search_string,
      )));
      drupal_set_message(l(t("Show unfiltered tree"), $url_prefix));
      drupal_goto($url_prefix . '/0/' . $search_string);
    }
  }
}

/**
 * validates taxonomy manager double tree
 **/
function taxonomy_manager_double_tree_form_validate($form, &$form_state) {
  return taxonomy_manager_form_validate($form, $form_state);
}

/**
 * submits the taxonomy manager double tree
**/
function taxonomy_manager_double_tree_form_submit($form, &$form_state) {
  return taxonomy_manager_form_submit($form, $form_state);
}

/**
 * Submit handler for adding terms
 */
function taxonomy_manager_form_add_submit($form, &$form_state) {
  $terms = array();
  $selected_tids = array();
  $selected_tids = $form_state['values']['taxonomy']['manager']['tree']['selected_terms'];
  foreach ($form_state['values']['add']['term'] as $value) {
    if (!empty($value)) {
      $terms[] = $value;
    }
  }
  if ($form_state['values']['add']['mass']['mass_add']) {
    foreach (explode("\n", str_replace("\r", '', $form_state['values']['add']['mass']['mass_add'])) as $term) {
      if ($term) {
        $terms[] = $term;
      }
    }
  }
  foreach ($terms as $name) {
    $term = array();
    $term['name'] = $name;
    $term['vid'] = $form_state['values']['vid'];
    $term['parent'] = $selected_tids;
    taxonomy_save_term($term);
    if (module_exists('i18ntaxonomy')) {
      if (i18ntaxonomy_vocabulary($form_state['values']['vid']) == I18N_TAXONOMY_TRANSLATE && $form_state['values']['taxonomy']['manager']['top']['language'] != "") {
        _i18ntaxonomy_term_set_lang($term['tid'], $form_state['values']['taxonomy']['manager']['top']['language']);
        $updated_lang = TRUE;
      }
    }
  }
  taxonomy_manager_update_voc($form_state['values']['vid'], $selected_tids);
  if (isset($updated_lang) && $updated_lang == TRUE) {
    drupal_set_message(t("Saving terms to language @lang", array(
      '@lang' => locale_language_name($form_state['values']['taxonomy']['manager']['top']['language']),
    )));
  }
  drupal_set_message(t("Terms added: %terms", array(
    '%terms' => implode(', ', $terms),
  )));
}

/**
 * Validation handler for deleting terms
 */
function taxonomy_manager_form_delete_validate($form, &$form_state) {
  $selected_tids = array();
  $selected_tids = $form_state['values']['taxonomy']['manager']['tree']['selected_terms'];
  if (count($selected_tids) < 1) {
    form_set_error('delete', t("No terms for deleting selected"));
    $form_state['rebuild'] = TRUE;
  }
}

/**
 * Submit handler for deleting terms
 */
function taxonomy_manager_form_delete_submit($form, &$form_state) {
  $selected_tids = array();
  $selected_tids = $form_state['values']['taxonomy']['manager']['tree']['selected_terms'];
  if ($form_state['values']['delete'] === TRUE) {
    return taxonomy_manager_term_confirm_delete_submit($form, $form_state);
  }

  // Rebuild the form to confirm term deletion.
  $form_state['rebuild'] = TRUE;
  $form_state['confirm_delete'] = TRUE;
}

/**
 * Form builder for the term delete form.
 *
 */
function taxonomy_manager_term_confirm_delete(&$form_state, $vid, $vid2 = NULL) {
  if (isset($vid2)) {
    $form['vid2'] = array(
      '#type' => 'value',
      '#value' => $vid2,
    );
    $url = 'admin/content/taxonomy_manager/double-tree/' . $vid . '/' . $vid2;
  }
  else {
    $url = 'admin/content/taxonomy_manager/voc/' . $vid;
  }
  $selected = $form_state['values']['taxonomy']['manager']['tree']['selected_terms'];
  $form['selected_terms'] = array(
    '#prefix' => '<ul>',
    '#suffix' => '</ul>',
    '#tree' => TRUE,
  );
  foreach ($selected as $tid) {
    $term = taxonomy_get_term($tid);
    $form['selected_terms'][$tid] = array(
      '#type' => 'hidden',
      '#value' => $tid,
      '#prefix' => '<li>',
      '#suffix' => check_plain($term->name) . "</li>\n",
    );
  }
  $form['delete'] = array(
    '#type' => 'value',
    '#value' => TRUE,
  );
  $form['vid'] = array(
    '#type' => 'value',
    '#value' => $vid,
  );
  $form['options'] = array(
    '#type' => 'value',
    '#value' => $form_state['values']['delete']['options'],
  );
  $msg = !empty($form_state['values']['delete']['options']['delete_orphans']) ? t('Deleting a term will delete all its children if there are any. ') : '';
  $msg .= t('This action cannot be undone.');
  return confirm_form($form, t('Are you sure you want to delete the following terms: '), $url, $msg, t('Delete'), t('Cancel'));
}

/**
 * Submit handler to delete a term after confirmation.
 *
 */
function taxonomy_manager_term_confirm_delete_submit($form, &$form_state) {
  taxonomy_manager_delete_terms($form_state['values']['selected_terms'], $form_state['values']['options']);
  if (isset($form_state['values']['vid2'])) {
    $form_state['redirect'] = 'admin/content/taxonomy_manager/double-tree/' . $form_state['values']['vid'] . '/' . $form_state['values']['vid2'];
  }
  else {
    $form_state['redirect'] = 'admin/content/taxonomy_manager/voc/' . $form_state['values']['vid'];
  }
  drupal_set_message(t("Selected terms deleted"));
  return;
}

/**
 * Validation handler for moving terms
 */
function taxonomy_manager_form_move_validate($form, &$form_state) {
  $selected_tids = array();
  $selected_tids = $form_state['values']['taxonomy']['manager']['tree']['selected_terms'];
  $error_msg = "";
  if (count($selected_tids) < 1) {
    form_set_error('move', t("Please selected terms you want to move in the hierarchy"));
    $form_state['rebuild'] = TRUE;
  }
  else {
    if (_taxonomy_manager_check_duplicates($form_state['values']['vid'], $form_state['values']['move']['parents'], $error_msg)) {
      form_set_error('move', t("Warning: Your input matches with multiple terms, because of duplicated term names. Please enter a unique term name or the term id with 'term-id:[tid]'") . " (" . $error_msg . ").");
      $form_state['rebuild'] = TRUE;
    }
  }
  $typed_parents = taxonomy_manager_autocomplete_tags_get_tids($form_state['values']['move']['parents'], $form_state['values']['vid'], FALSE);
  $parents = array();
  foreach ($typed_parents as $parent_info) {
    $parents[(int) $parent_info['tid']] = (int) $parent_info['tid'];
  }
  if (!taxonomy_manager_check_circular_hierarchy($selected_tids, $parents)) {
    form_set_error('move', t('Invalid selection. The resulting hierarchy would contain circles, which is not allowed. A term cannot be a parent of itself.'));
    $form_state['rebuild'] = TRUE;
  }
  else {
    if (!taxonomy_manager_check_language($form_state['values']['vid'], $selected_tids, $typed_parents)) {
      form_set_error('move', t('Terms must be of the same language'));
      $form_state['rebuild'] = TRUE;
    }
  }
}

/**
 * checks for circles in the hierarchy, e.g. 1 -> 2 -> 3 -> 1
 * a term can't contain itself as a parent
 *
 * returns TRUE if resulting hierarchy is valid, else FALSE
 */
function taxonomy_manager_check_circular_hierarchy($tids, $new_parents_tids) {
  if (is_array($tids) && is_array($new_parents_tids)) {

    //directly same term
    foreach ($tids as $tid) {
      if (in_array($tid, $new_parents_tids)) {
        return FALSE;
      }
    }

    //same term over more hierarchy levels
    $all_parents = array();
    foreach ($new_parents_tids as $parent_tid) {
      $parents = taxonomy_get_parents_all($parent_tid);
      foreach ($parents as $parent) {
        $all_parents[$parent->tid] = $parent->tid;
      }
    }
    foreach ($tids as $tid) {
      if (in_array($tid, $all_parents)) {
        return FALSE;
      }
    }
  }
  return TRUE;
}

/**
 * checks if terms in move or merge operation are of the same language
 *
 * returns TRUE if operation allowed, else FALSE (different languages)
 */
function taxonomy_manager_check_language($vid, $selected_tids, $parents) {
  if (module_exists('i18ntaxonomy')) {
    if (count($parents) && count($selected_tids)) {
      $term = array_pop($parents);
      $lang = _taxonomy_manager_term_get_lang($term['tid']);
      if (i18ntaxonomy_vocabulary($vid) == I18N_TAXONOMY_TRANSLATE) {
        foreach ($parents as $parent) {
          if (_taxonomy_manager_term_get_lang($parent['tid']) != $lang) {
            return FALSE;
          }
        }
        foreach ($selected_tids as $tid) {
          if (_taxonomy_manager_term_get_lang($tid) != $lang) {
            return FALSE;
          }
        }
      }
    }
  }
  return TRUE;
}

/**
 * Submit handler for moving terms
 */
function taxonomy_manager_form_move_submit($form, $form_state) {
  $selected_tids = array();
  $selected_tids = $form_state['values']['taxonomy']['manager']['tree']['selected_terms'];
  $typed_parents = taxonomy_manager_autocomplete_tags_get_tids($form_state['values']['move']['parents'], $form_state['values']['vid'], TRUE, $form_state['values']['taxonomy']['manager']['top']['language']);
  $parents = array();
  foreach ($typed_parents as $parent_info) {
    $parents[] = $parent_info['tid'];
  }
  if (count($parents) == 0) {
    $parents[0] = 0;
  }

  //if empty, delete all parents
  taxonomy_manager_move($parents, $selected_tids, $form_state['values']['move']['options']);
  if ($form_state['values']['move']['options']['keep_old_parents']) {
    $parents[] = 1;

    //++ parent count for hierarchy update (-> multi hierarchy)
  }
  taxonomy_manager_update_voc($form_state['values']['vid'], $parents);
  $term_names_array = array();
  foreach ($selected_tids as $selected_tid) {
    $term = taxonomy_get_term($selected_tid);
    $term_names_array[] = $term->name;
  }
  $term_names = implode(', ', $term_names_array);
  $parent_names = "";
  if (count($typed_parents) == 0) {
    $parent_names = t("root level");
  }
  else {
    $parent_names = $form_state['values']['move']['parents'];
  }
  drupal_set_message(t("Terms %term_names moved to %parent_names", array(
    '%term_names' => $term_names,
    '%parent_names' => $parent_names,
  )));
}

/**
 * Validation handler for validating terms
 */
function taxonomy_manager_form_merge_validate($form, &$form_state) {
  $selected_tids = array();
  $selected_tids = $form_state['values']['taxonomy']['manager']['tree']['selected_terms'];
  $main_terms = array();
  $regexp = '%(?:^|,\\ *)("(?>[^"]*)(?>""[^"]* )*"|(?: [^",]*))%x';
  preg_match_all($regexp, $form_state['values']['merge']['main_term'], $matches);
  $main_terms = $matches[1];
  $error_msg = "";
  $typed_terms = taxonomy_manager_autocomplete_tags_get_tids($form_state['values']['merge']['main_term'], $form_state['values']['vid'], FALSE);
  if (!is_array($main_terms) || count($main_terms) == 0 || empty($main_terms[0])) {
    form_set_error('merge][main_term', t('Please enter a name into "Resulting merged term"'));
    $form_state['rebuild'] = TRUE;
  }
  else {
    if (count($main_terms) > 1) {
      form_set_error('merge][main_term', t('Please only enter single names into "Resulting merged term"'));
      $form_state['rebuild'] = TRUE;
    }
  }
  if (count($selected_tids) < 1) {
    form_set_error('merge', t("Please selected terms you want to merge"));
    $form_state['rebuild'] = TRUE;
  }
  else {
    if (count($selected_tids) > 50) {
      form_set_error('merge', t("Please select less than 50 terms to merge. Merging of too many terms in one step can cause timeouts and inconsistent database states"));
      $form_state['rebuild'] = TRUE;
    }
    else {
      if (_taxonomy_manager_check_duplicates($form_state['values']['vid'], $form_state['values']['merge']['main_term'], $error_msg)) {
        form_set_error('merge', t("Warning: Your input matches with multiple terms, because of duplicated term names. Please enter a unique term name or the term id with 'term-id:[tid]'") . " (" . $error_msg . ").");
        $form_state['rebuild'] = TRUE;
      }
      else {
        if ($form_state['values']['merge']['options']['collect_parents']) {
          $main_terms = array();
          foreach ($typed_terms as $term_info) {
            $main_terms[$term_info['tid']] = $term_info['tid'];
          }
          if (count($main_terms) == 1) {
            if (!taxonomy_manager_check_circular_hierarchy($main_terms, $selected_tids)) {
              form_set_error('merge', t('Invalid selection. The resulting hierarchy would contain circles, which is not allowed. A term cannot be a parent of itself. Unselect "Collect all parents of selected terms an add it to the merged term" or specify a different resulting term.'));
              $form_state['rebuild'] = TRUE;
            }
          }
        }
        else {
          if (!taxonomy_manager_check_language($form_state['values']['vid'], $selected_tids, $typed_terms)) {
            form_set_error('merge', t('Terms must be of the same language'));
            $form_state['rebuild'] = TRUE;
          }
        }
      }
    }
  }
}

/**
 * Submit handler for merging terms
 */
function taxonomy_manager_form_merge_submit($form, $form_state) {
  $selected_tids = array();
  $selected_tids = $form_state['values']['taxonomy']['manager']['tree']['selected_terms'];
  $main_terms = taxonomy_manager_autocomplete_tags_get_tids($form_state['values']['merge']['main_term'], $form_state['values']['vid'], TRUE, $form_state['values']['taxonomy']['manager']['top']['language']);
  $main_term = array_shift($main_terms);
  $new_inserted = FALSE;
  if ($main_term['new']) {
    $new_inserted = TRUE;
  }
  $main_term_tid = $main_term['tid'];
  taxonomy_manager_merge($main_term_tid, $selected_tids, $form_state['values']['merge']['options'], $new_inserted);
  $term_names_array = array();
  foreach ($selected_tids as $selected_tid) {
    $term = taxonomy_get_term($selected_tid);
    $term_names_array[] = $term->name;
  }
  $term_names = implode($term_names_array, ', ');
  drupal_set_message(t("Terms %term_names merged into %main_term", array(
    '%term_names' => $term_names,
    '%main_term' => $form_state['values']['merge']['main_term'],
  )));
}

/**
 * returns TRUE if term with same name exists more often
 */
function _taxonomy_manager_check_duplicates($vid, $autocomplete_value, &$msg) {
  $regexp = '%(?:^|,\\ *)("(?>[^"]*)(?>""[^"]* )*"|(?: [^",]*))%x';
  preg_match_all($regexp, $autocomplete_value, $matches);
  foreach ($matches[1] as $match) {
    $terms = array();
    $terms = taxonomy_manager_autocomplete_tags_get_tids($match, $vid, FALSE);
    if (count($terms) > 1) {
      $tids = array();
      foreach ($terms as $t) {
        $term = taxonomy_get_term($t['tid']);
        $tids[] = $term->tid . (!empty($term->language) ? '-' . check_plain($term->language) : '');
      }
      $msg .= check_plain($match) . ": " . implode(", ", $tids);
      return TRUE;
    }
  }
  return FALSE;
}
function taxonomy_manager_form_double_tree_submit($form, $form_state) {
  $voc1 = $form_state['values']['vid'];
  $voc2 = $form_state['values']['double_tree']['voc2'];
  drupal_goto('admin/content/taxonomy_manager/double-tree/' . $voc1 . '/' . $voc2);
}
function taxonomy_manager_form_double_tree_disable_submit($form, $form_state) {
  drupal_goto('admin/content/taxonomy_manager/voc/' . $form_state['values']['vid']);
}

/**
 * Defines a settings form.
 */
function taxonomy_manager_settings() {
  $form['taxonomy_manager_disable_mouseover'] = array(
    '#type' => 'checkbox',
    '#title' => t('Disable mouse-over effect for terms (weights and direct link)'),
    '#default_value' => variable_get('taxonomy_manager_disable_mouseover', 0),
    '#description' => t('Disabeling this feature speeds up the Taxonomy Manager'),
  );
  $form['taxonomy_manager_disable_merge_redirect'] = array(
    '#type' => 'checkbox',
    '#title' => t('Disable redirect of the taxonomy term page to merged terms '),
    '#default_value' => variable_get('taxonomy_manager_disable_merge_redirect', TRUE),
    '#description' => t('When using the merging feature, the selected terms get merged into one term. All selected terms will be deleted afterwards. Normally the Taxonomy Manager redirects calls to taxonomy/term/$tid of the deleted terms (through merging) to the resulting merged term. This feature might conflict with other modules (e.g. Taxonomy Breadcrumb, Panels), which implement hook_menu_alter to change the taxonomy_manager_term_page callback. Disable this feature if it conflicts with other modules or if you do not need it. Changing this setting requires a (menu) cache flush to become active.'),
  );
  $form['taxonomy_manager_pager_tree_page_size'] = array(
    '#type' => 'select',
    '#title' => t('Pager count'),
    '#options' => array(
      25 => 25,
      50 => 50,
      75 => 75,
      100 => 100,
      150 => 150,
      200 => 200,
      250 => 250,
      300 => 300,
      400 => 400,
      500 => 500,
    ),
    '#default_value' => variable_get('taxonomy_manager_pager_tree_page_size', 50),
    '#description' => t('Select how many terms should be listed on one page. Huge page counts can slow down the Taxonomy Manager'),
  );
  return system_settings_form($form);
}

/**
 * Validates a custom AJAX callback by ensuring that the request contains a
 * valid form token, which prevents CSRF.
 *
 * @param $submitted_data
 *   An array containing the submitted data, usually $_POST. Needs to contain
 *   form_token and form_id.
 *
 * @return
 *   TRUE if a valid token is provided, else FALSE.
 */
function taxonomy_manager_valid_ajax_callback($submitted_data) {
  if (isset($submitted_data['form_token']) && isset($submitted_data['form_id']) && drupal_valid_token($submitted_data['form_token'], $submitted_data['form_id'])) {
    return TRUE;
  }
  return FALSE;
}

/**
 * callback handler for updating term data
 *
 * @param $vid
 */
function taxonomy_manager_term_data_edit() {
  $param = $_POST;
  if (!taxonomy_manager_valid_ajax_callback($param)) {
    return;
  }
  $msg = t("Changes successfully saved");
  $is_error_msg = FALSE;
  $tid = $param['tid'];
  if (!$tid) {
    $tid = $param['term_data']['tid'];
  }
  $vid = $param['vid'];
  if (!$vid) {
    $vid = $param['term_data']['vid'];
  }
  $values = $param['value'];
  $attr_type = $param['attr_type'];
  $op = $param['op'];
  if ($op == t("Save changes")) {
    db_query("UPDATE {term_data} SET name = '%s' WHERE tid = %d", $param['term_data']['name'], $tid);
    db_query("UPDATE {term_data} SET description = '%s' WHERE tid = %d", $param['term_data']['description'], $tid);
  }
  if ($op == 'add') {
    $typed_terms = taxonomy_manager_autocomplete_tags_get_tids($values, $vid, FALSE);
  }
  if ($op == 'add' && ($attr_type == 'parent' || $attr_type == 'related')) {

    //check for unique names
    $error_msg = "";
    if (_taxonomy_manager_check_duplicates($vid, $values, $error_msg)) {
      $msg = t("Warning: Your input matches with multiple terms, because of duplicated term names. Please enter a unique term name or the term id with 'term-id:[tid]'") . " (" . $error_msg . ").";
      $is_error_msg = TRUE;
    }
    if (!taxonomy_manager_check_language($vid, array(
      $tid,
    ), $typed_terms)) {
      $msg = t("Terms must be of the same language");
      $is_error_msg = TRUE;
    }
    if ($attr_type == 'parent') {

      //validation for consistent hierarchy
      $parents = array();
      foreach ($typed_terms as $parent_info) {
        $parents[$parent_info['tid']] = $parent_info['tid'];
      }
      $tids = array();
      $tids[$tid] = $tid;
      if (!taxonomy_manager_check_circular_hierarchy($tids, $parents)) {
        $msg = t('Invalid parent. The resulting hierarchy would contain circles, which is not allowed. A term cannot be a parent of itself.');
        $is_error_msg = TRUE;
      }
    }
  }
  else {
    if ($op == 'add' && $attr_type == 'translation') {
      $regexp = '%(?:^|,\\ *)("(?>[^"]*)(?>""[^"]* )*"|(?: [^",]*))%x';
      preg_match_all($regexp, $values, $matches);
      $translation_terms = array_unique($matches[1]);
      if (count($translation_terms) > 1) {
        $msg = t('Please provide only one term for translation');
        $is_error_msg = TRUE;
      }
      else {
        if ($param['edit-term-data-translations-op-lang'] == $param['edit-term-data-language']) {
          $msg = t('Invalid language selection');
          $is_error_msg = TRUE;
        }
        else {
          if (empty($param['edit-term-data-translations-op-lang'])) {
            $msg = t('Missing language for new term');
            $is_error_msg = TRUE;
          }
          else {
            $translations = i18ntaxonomy_term_get_translations(array(
              'tid' => $tid,
            ), FALSE);
            foreach ($translations as $translation) {
              if ($translation->language == $param['edit-term-data-translations-op-lang']) {
                $msg = t('Invalid language selection. Translation already exists');
                $is_error_msg = TRUE;
                break;
              }
            }
          }
        }
      }
    }
    else {
      if ($attr_type == "language") {
        $translations = i18ntaxonomy_term_get_translations(array(
          'tid' => $tid,
        ), FALSE);
        foreach ($translations as $translation) {
          if ($translation->language == $values) {
            $msg = t('Invalid language selection.');
            $is_error_msg = TRUE;
            break;
          }
        }
      }
    }
  }
  if (!$is_error_msg) {
    if ($op == 'add') {
      if ($attr_type == 'synonym') {
        $regexp = '%(?:^|,\\ *)("(?>[^"]*)(?>""[^"]* )*"|(?: [^",]*))%x';
        preg_match_all($regexp, $values, $matches);
        $synonyms = array_unique($matches[1]);
        $values = array();
        foreach ($synonyms as $syn) {
          $values[] = trim($syn);
        }
      }
      else {
        $typed_term_tids = array();
        if ($attr_type == "translation") {
          $typed_term_tids = taxonomy_manager_autocomplete_tags_get_tids($values, $vid, TRUE, $param['edit-term-data-translations-op-lang']);
        }
        else {
          $typed_term_tids = taxonomy_manager_autocomplete_tags_get_tids($values, $vid, TRUE, $param['edit-term-data-language']);
        }
        $values = array();
        foreach ($typed_term_tids as $term_info) {
          $values[] = $term_info['tid'];
        }
      }
    }
    switch ($attr_type) {
      case 'parent':
        if (!is_array($values)) {
          $values = array(
            $values,
          );
        }
        foreach ($values as $value) {
          db_query("DELETE FROM {term_hierarchy} WHERE parent = %d AND tid = %d", $value, $tid);
          if ($op == 'add') {
            db_query("INSERT INTO {term_hierarchy} (parent, tid) VALUES (%d, %d)", $value, $tid);
          }
        }
        if ($op == 'delete') {
          $parents = taxonomy_get_parents($tid);
          if (count($parents) == 0) {

            //ensure that a term has a least parent 0
            db_query("DELETE FROM {term_hierarchy} WHERE parent = 0 AND tid = %d", $tid);
            db_query("INSERT INTO {term_hierarchy} (parent, tid) VALUES (0, %d)", $tid);
          }
        }
        else {
          if ($op == 'add') {
            db_query("DELETE FROM {term_hierarchy} WHERE parent = 0 AND tid = %d", $tid);
          }
        }
        taxonomy_manager_update_voc($vid, taxonomy_get_parents($tid));
        $msg = t("Successfully updated parents");
        break;
      case 'related':
        if (!is_array($values)) {
          $values = array(
            $values,
          );
        }
        foreach ($values as $value) {
          if ($value != 0) {
            db_query("DELETE FROM {term_relation} WHERE tid1 = %d AND tid2 = %d", $tid, $value);

            //  db_query("DELETE FROM {term_relation} WHERE tid2 = %d AND tid1 = %d", $tid, $value);
            if ($op == 'add') {
              db_query('INSERT INTO {term_relation} (tid1, tid2) VALUES (%d, %d)', $tid, $value);
            }
          }
        }
        $msg = t("Successfully updated related terms");
        break;
      case 'synonym':
        if (!is_array($values)) {
          $values = array(
            $values,
          );
        }
        foreach ($values as $value) {
          db_query("DELETE FROM {term_synonym} WHERE tid = %d AND name = '%s'", $tid, $value);
          if ($op == 'add') {
            db_query("INSERT INTO {term_synonym} (tid, name) VALUES (%d, '%s')", $tid, $value);
          }
        }
        $msg = t("Successfully updated synonyms");
        break;
      case 'weight':
        if (is_numeric($values)) {
          db_query("UPDATE {term_data} SET weight = %d WHERE tid = %d", $values, $tid);
          $msg = t("Successfully updated weight to !weight", array(
            '!weight' => $values,
          ));
        }
        break;
      case 'language':
        if (module_exists('i18ntaxonomy')) {
          _i18ntaxonomy_term_set_lang($tid, $values);
          $msg = t("Successfully updated language");
        }
        else {
          $is_error_msg = TRUE;
          $msg = t("Module i18ntaxonomy not enabled");
        }
        break;
      case 'translation':
        if (module_exists('i18ntaxonomy')) {
          if ($op == "add") {
            taxonomy_manager_add_translation($tid, $values[0]);
            $msg = t("Successfully added translation");
          }
          else {
            if ($op == "delete") {
              db_query('UPDATE {term_data} SET trid = 0 WHERE tid = %d', $values);
              if (count(i18ntaxonomy_term_get_translations(array(
                'tid' => $tid,
              ), FALSE)) == 0) {
                db_query('UPDATE {term_data} SET trid = 0 WHERE tid = %d', $tid);
              }
              $msg = t("Successfully removed translation");
            }
          }
        }
        else {
          $is_error_msg = TRUE;
          $msg = t("Module i18ntaxonomy not enabled");
        }
        break;
    }
    $term = (array) taxonomy_get_term($tid);
    $term['fields'] = $param['term_data']['fields'];
    module_invoke_all('taxonomy', 'update', 'term', $term);
    module_invoke_all('taxonomy_manager_term_data_submit', $param, $values);
  }
  drupal_json(array(
    'data' => taxonomy_manager_update_term_data_form($vid, $tid, TRUE, FALSE, $msg, $is_error_msg),
  ));

  //taxonomy_manager_update_term_data_form($vid, $tid, TRUE);
  exit;
}

/**
 * AJAX Callback for Double Tree operations
 */
function taxonomy_manager_double_tree_edit() {
  $params = $_POST;
  if (!taxonomy_manager_valid_ajax_callback($params)) {
    return;
  }
  $op = $params['op'];
  $msg = "";
  $is_error_msg = FALSE;
  if ($op == "move") {
    taxonomy_manager_double_tree_edit_move($params, $msg, $is_error_msg);
  }
  else {
    if ($op == "translation") {
      taxonomy_manager_doube_tree_edit_translate($params, $msg, $is_error_msg);
    }
    else {
      if ($op == "switch") {
        taxonomy_manager_double_tree_edit_switch($params, $msg, $is_error_msg);
      }
    }
  }
  if ($msg == "") {
    $msg = t("Invalid operation.");
    $is_error_msg = TRUE;
  }
  $msg_type = $is_error_msg ? "error" : "status";
  drupal_json(array(
    'data' => $msg,
    'type' => $msg_type,
  ));
}
function taxonomy_manager_double_tree_edit_move($params, &$msg, &$is_error_msg) {
  $selected_terms = $params['selected_terms'];
  $selected_parents = $params['selected_parents'];
  if (!is_array($selected_terms) || !count($selected_terms)) {
    $msg = t("No terms selected.");
    $is_error_msg = TRUE;
    return;
  }
  $selected_terms_names = array();
  foreach ($selected_terms as $tid) {
    $term = taxonomy_get_term($tid);
    $vid = $term->vid;
    $selected_terms_names[] = $term->name;
  }
  if (is_array($selected_parents) && count($selected_parents)) {
    $p_array = array();
    foreach ($selected_parents as $parent) {
      $p_array[$parent]['tid'] = $parent;
    }
    if (!taxonomy_manager_check_language($vid, $selected_terms, $p_array)) {
      $msg = t("Terms must be of the same language.");
      $is_error_msg = TRUE;
      return;
    }
    else {
      if (!taxonomy_manager_check_circular_hierarchy($selected_terms, $selected_parents)) {
        $msg = t('Invalid parent. The resulting hierarchy would contain circles, which is not allowed. A term cannot be a parent of itself.');
        $is_error_msg = TRUE;
        return;
      }
    }
  }
  foreach ($selected_terms as $tid) {

    //reset all parents, except the direct parent in the tree
    $term_parents = taxonomy_get_parents($tid);
    $term_parents_array = array();
    $direct_parent = is_numeric($params['selected_terms_parent'][$tid]) ? $params['selected_terms_parent'][$tid] : 0;
    foreach ($term_parents as $term_parent) {
      if ($direct_parent != $term_parent->tid) {
        $term_parents_array[$term_parent->tid] = $term_parent->tid;
      }
    }
    $selected_parent_names = array();
    if (count($selected_parents)) {
      foreach ($selected_parents as $parent) {
        $term = taxonomy_get_term($parent);
        $selected_parent_names[] = $term->name;
        $term_parents_array[$term->tid] = $term->tid;
      }
    }
    if (count($term_parents_array) == 0) {
      $term_parents_array[0] = 0;
    }
    taxonomy_manager_move($term_parents_array, array(
      $tid,
    ), array(
      'keep_old_parents' => FALSE,
    ));
    taxonomy_manager_update_voc($vid, $term_parents_array);
  }
  $term_names = implode(', ', $selected_terms_names);
  if (count($selected_parents) == 0) {
    $msg = t("Removed current parent form terms %terms.", array(
      '%terms' => $term_names,
    ));
  }
  else {
    $msg = t("Terms %terms moved to parents %parents.", array(
      '%terms' => $term_names,
      '%parents' => implode(', ', $selected_parent_names),
    ));
  }
  $is_error_msg = FALSE;
}
function taxonomy_manager_doube_tree_edit_translate($params, &$msg, &$is_error_msg) {
  $term1 = taxonomy_get_term(array_pop($params['selected_terms']));
  $term2 = taxonomy_get_term(array_pop($params['selected_parents']));
  $vid = $term1->vid;
  if (module_exists('i18ntaxonomy')) {
    if (i18ntaxonomy_vocabulary($vid) == I18N_TAXONOMY_TRANSLATE) {
      if ($term1->language == $term2->language) {
        $msg = t("Selected terms are of the same language.");
        $is_error_msg = TRUE;
      }
      else {
        $translations = i18ntaxonomy_term_get_translations(array(
          'tid' => $term1->tid,
        ), FALSE);
        foreach ($translations as $translation) {
          if ($translation->language == $term2->language) {
            $msg = t('Translation for this language already exists.');
            $is_error_msg = TRUE;
            break;
          }
        }
        $translations = i18ntaxonomy_term_get_translations(array(
          'tid' => $term2->tid,
        ), FALSE);
        foreach ($translations as $translation) {
          if ($translation->language == $term1->language) {
            $msg = t('Translation for this language already exists.');
            $is_error_msg = TRUE;
            break;
          }
        }
      }
    }
    else {
      $msg = t("This is not a multilingual vocabulary.");
      $is_error_msg = TRUE;
    }
  }
  else {
    $msg = t("Module i18ntaxonomy not enabled.");
    $is_error_msg = TRUE;
  }
  if (!$is_error_msg) {
    taxonomy_manager_add_translation($term1->tid, $term2->tid);
    $msg = t("Translation for %term2 - %term1 added.", array(
      '%term2' => $term2->name,
      '%term1' => $term1->name,
    ));
  }
}
function taxonomy_manager_double_tree_edit_switch($params, &$msg, &$is_error_msg) {
  $selected_terms = $params['selected_terms'];
  $selected_parents = $params['selected_parents'];
  $voc1 = taxonomy_vocabulary_load($params['voc1']);
  $voc2 = taxonomy_vocabulary_load($params['voc2']);
  taxonomy_manager_switch($selected_terms, $voc1->vid, $voc2->vid, $selected_parents);
  $selected_terms_names = array();
  foreach ($selected_terms as $tid) {
    $term = taxonomy_get_term($tid);
    $selected_terms_names[] = $term->name;
  }
  $selected_parent_names = array();
  if (count($selected_parents)) {
    foreach ($selected_parents as $parent) {
      $term = taxonomy_get_term($parent);
      $selected_parent_names[] = $term->name;
      $term_parents_array[$term->tid] = $term->tid;
    }
  }
  $term_names = implode(', ', $selected_terms_names);
  if (count($selected_parents) == 0) {
    $msg = t("Terms %terms moved to vocabulary %voc.", array(
      '%terms' => $term_names,
      '%voc' => $voc2->name,
    ));
  }
  else {
    $msg = t("Terms %terms moved to vocabulary %voc under parents %parents.", array(
      '%terms' => $term_names,
      '%voc' => $voc2->name,
      '%parents' => implode(', ', $selected_parent_names),
    ));
  }
  $is_error_msg = FALSE;
}

/**
 * adds translation between two terms
 */
function taxonomy_manager_add_translation($tid1, $tid2) {
  $trid1 = db_result(db_query("SELECT trid FROM {term_data} WHERE tid = %d", $tid1));
  $trid2 = db_result(db_query("SELECT trid FROM {term_data} WHERE tid = %d", $tid2));
  if ($trid1 == 0 && $trid2 == 0) {
    $trid = (int) db_result(db_query('SELECT max(trid) FROM {term_data}')) + 1;
    db_query('UPDATE {term_data} SET trid = %d WHERE tid = %d OR tid = %d', $trid, $tid1, $tid2);
  }
  else {
    if ($trid1 != 0 && $trid2 == 0) {
      db_query('UPDATE {term_data} SET trid = %d WHERE tid = %d', $trid1, $tid2);
    }
    else {
      if ($trid2 != 0 && $trid1 == 0) {
        db_query('UPDATE {term_data} SET trid = %d WHERE tid = %d', $trid2, $tid1);
      }
      else {
        $trid = max($trid1, $trid2);
        db_query('UPDATE {term_data} SET trid = %d WHERE trid = %d OR trid = %d', $trid, $trid1, $trid2);
      }
    }
  }
}

/**
 * Changes vocabulary of given terms and its children
 * conflicts might be possible with multi-parent terms!
 */
function taxonomy_manager_switch($tids, $from_voc, $to_voc, $parents = array()) {
  foreach ($tids as $tid) {

    //hook to inform modules about the changes
    module_invoke_all('taxonomy_manager_term', 'switch', $tid, $from_voc, $to_voc);
    $children = taxonomy_get_tree($from_voc, $tid);
    $place_holder = array();
    $terms_to_switch = array();
    foreach ($children as $child) {
      $placeholder[] = '%d';
      $terms_to_switch[] = $child->tid;
    }
    $placeholder[] = '%d';
    $terms_to_switch[] = $tid;
    db_query("UPDATE {term_data} SET vid = %d WHERE tid IN (" . implode(', ', $placeholder) . ")", array_merge(array(
      $to_voc,
    ), $terms_to_switch));

    //delete references to parents from the old voc
    foreach ($children as $child) {
      $term_parents = taxonomy_get_parents($child->tid);
      foreach ($term_parents as $term_parent) {
        if ($term_parent->vid != $to_voc) {
          db_query("DELETE FROM {term_hierarchy} WHERE tid = %d AND parent = %d", $child->tid, $term_parent->tid);
        }
      }
    }

    //set parent of the selected term
    if (!count($parents)) {
      $parents[0] = 0;
    }
    taxonomy_manager_move($parents, array(
      $tid,
    ));
    taxonomy_manager_update_voc($to_voc, $parents);
  }
}

/**
 * checks if voc has terms
 *
 * @param $vid voc id
 * @return true, if terms already exists, else false
 */
function _taxonomy_manager_voc_is_empty($vid) {
  $count = db_result(db_query_range("SELECT t.* FROM {term_data} t INNER JOIN {term_hierarchy} h ON t.tid = h.tid WHERE vid = %d AND h.parent = 0", $vid, 0, 1));
  if ($count == 0) {
    return TRUE;
  }
  return FALSE;
}

/**
 * deletes terms from the database
 * optional orphans (terms where parent get deleted) can be deleted as well
 *
 * (difference to taxonomy_del_term: deletion of orphans optional)
 *
 * @param $tids array of term id to delete
 * @param $options associative array with options
 *   if $options['delete_orphans'] is true, orphans get deleted
 */
function taxonomy_manager_delete_terms($tids, $options = array()) {
  if (!is_array($tids)) {
    array(
      $tids,
    );
  }
  while (count($tids) > 0) {
    $orphans = array();
    foreach ($tids as $tid) {
      if ($children = taxonomy_get_children($tid)) {
        foreach ($children as $child) {
          $parents = taxonomy_get_parents($child->tid);
          if ($options['delete_orphans']) {
            if (count($parents) == 1) {
              $orphans[] = $child->tid;
            }
          }
          else {
            db_query("DELETE FROM {term_hierarchy} WHERE tid = %d AND parent = %d", $child->tid, $tid);
            if (count($parents) == 1) {
              if (!db_result(db_query("SELECT COUNT(*) FROM {term_hierarchy} WHERE tid = %d AND parent = 0", $child->tid))) {
                db_query("INSERT INTO {term_hierarchy} (parent, tid) VALUES(0, %d)", $child->tid);
              }
            }
          }
        }
      }
      $term = (array) taxonomy_get_term($tid);
      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);
      module_invoke_all('taxonomy', 'delete', 'term', $term);
      $tids = $orphans;
    }
  }
}

/**
 * moves terms in hierarchies to other parents
 *
 * @param $parents
 *   array of parent term ids to where children can be moved
 *   array should only contain more parents if multi hiearchy enabled
 *   if array contains 0, terms get placed to first (root) level
 * @param $children
 *   array of term ids to move
 * @param $options
 *   array of additional options for moving
 *   'keep_old_parents': if true, exisiting parents doesn't get deleted (only possible with multi hierarchies)
 */
function taxonomy_manager_move($parents, $children, $options = array()) {
  if (!is_array($parents)) {
    array(
      $parents,
    );
  }
  foreach ($children as $child) {
    if (!$options['keep_old_parents']) {
      db_query("DELETE FROM {term_hierarchy} WHERE tid = %d", $child);
    }
    foreach ($parents as $parent) {
      db_query("DELETE FROM {term_hierarchy} WHERE parent = %d AND tid = %d", $parent, $child);

      //prevent duplicated sql errors
      db_query("INSERT INTO {term_hierarchy} (parent, tid) VALUES (%d, %d)", $parent, $child);
    }
  }
}

/**
 * merges terms into another term (main term), all merged term get added
 * to the main term as synonyms.
 * term_node relations are updated automatically (node with one of merging terms gets main term assigned)
 * after all opterions are done (adding of hierarchies, relations is optional) merging
 * terms get deleted
 *
 * @param $main_term
 *   id of term where other terms get merged into
 * @param $merging_terms
 *   array of term ids, which get merged into main term and afterwards deleted
 * @param $options
 *   array with additional options, possible values:
 *   'collect_parents': if true, all parents of merging terms get added to main term (only possible with multi hierarchies)
 *   'collect_children': if true, all children of merging terms get added to main term
 *   'collect_relations': if true, all relations of merging terms are transfered to main term
 */
function taxonomy_manager_merge($main_term, $merging_terms, $options = array(), $new_inserted = TRUE) {
  $vid = db_result(db_query("SELECT vid FROM {term_data} WHERE tid = %d", $main_term));
  $voc = taxonomy_vocabulary_load($vid);
  $merging_terms_parents = array();
  foreach ($merging_terms as $merge_term) {
    if ($merge_term != $main_term) {

      //hook, to inform other modules about the changes
      module_invoke_all('taxonomy_manager_term', 'merge', $main_term, $merge_term);

      //update node-relations
      $sql = db_query("SELECT * FROM {term_node} WHERE tid = %d", $merge_term);
      while ($obj = db_fetch_object($sql)) {
        db_query("DELETE FROM {term_node} WHERE tid = %d AND vid = %d", $obj->tid, $obj->vid);
        if (!db_result(db_query("SELECT COUNT(*) FROM {term_node} WHERE tid = %d AND vid = %d", $main_term, $obj->vid))) {
          $obj->tid = $main_term;
          drupal_write_record('term_node', $obj);
        }
      }
      if ($options['collect_parents']) {
        $parents = taxonomy_get_parents($merge_term);
        foreach ($parents as $parent_tid => $parent_term) {
          $merging_terms_parents[$parent_tid] = $parent_tid;
          if (!db_result(db_query("SELECT COUNT(*) FROM {term_hierarchy} WHERE tid = %d AND parent = %d", $main_term, $parent_tid))) {
            db_query("INSERT INTO {term_hierarchy} (tid, parent) VALUES (%d, %d)", $main_term, $parent_tid);
          }
        }
      }
      if ($options['collect_children']) {
        $children = taxonomy_get_children($merge_term);
        foreach ($children as $child_tid => $child_term) {
          if (!db_result(db_query("SELECT COUNT(*) FROM {term_hierarchy} WHERE tid = %d AND parent = %d", $child_tid, $main_term))) {
            db_query("INSERT INTO {term_hierarchy} (tid, parent) VALUES (%d, %d)", $child_tid, $main_term);
          }
        }
      }
      if ($options['collect_relations']) {
        $relations = taxonomy_get_related($merge_term);
        foreach ($relations as $related_tid => $relation) {
          if ($relation->tid1 == $merge_term) {
            if (!db_result(db_query("SELECT COUNT(*) FROM {term_relation} WHERE tid1 = %d AND tid2 = %d", $main_term, $related_tid))) {
              db_query("INSERT INTO {term_relation} (tid1, tid2) VALUES (%d, %d)", $main_term, $related_tid);
            }
          }
          else {
            if ($relation->tid2 == $merge_term) {
              if (!db_result(db_query("SELECT COUNT(*) FROM {term_relation} WHERE tid2 = %d AND tid1 = %d", $main_term, $related_tid))) {
                db_query("INSERT INTO {term_relation} (tid2, tid1) VALUES (%d, %d)", $main_term, $related_tid);
              }
            }
          }
        }
      }

      //save merged term (and synonomys of merged term) as synonym
      $term = taxonomy_get_term($merge_term);
      $merge_term_synonyms = taxonomy_get_synonyms($merge_term);
      $merge_term_synonyms[] = $term->name;
      foreach ($merge_term_synonyms as $syn) {
        if (!db_result(db_query("SELECT COUNT(*) FROM {term_synonym} WHERE tid = %d AND name = '%s'", $main_term, $syn))) {
          db_query("INSERT INTO {term_synonym} (tid, name) VALUES (%d, '%s')", $main_term, $syn);
        }
      }
      taxonomy_manager_delete_terms(array(
        $merge_term,
      ));
    }
  }
  taxonomy_manager_update_voc($vid, $merging_terms_parents);
  if ($options['collect_parents'] && db_result(db_query("SELECT COUNT(*) FROM {term_hierarchy} WHERE tid = %d", $main_term)) > 1) {
    db_query("DELETE FROM {term_hierarchy} WHERE parent = 0 AND tid = %d", $main_term);
  }
  taxonomy_manager_merge_history_update($main_term, $merging_terms);
}

/**
 * inserts merging information (main_tid - merged_tid ) into taxonomy_manager_merge
 * and updates cache, which is used to reconstructs taxonomy/term pages
 *
 * @param $main_tid term if of main term
 * @param $merged_tids array of merged term ids
 */
function taxonomy_manager_merge_history_update($main_tid, $merged_tids) {
  if (!is_array($merged_tids)) {
    (array) $merged_tids;
  }
  foreach ($merged_tids as $merged_tid) {
    if ($merged_tid != $main_tid) {

      //check if merged term has been a main term once before
      $check_merged = db_result(db_query("SELECT COUNT(*) FROM {taxonomy_manager_merge} WHERE main_tid = %d", $merged_tid));
      if ($check_merged) {
        db_query("UPDATE {taxonomy_manager_merge} SET main_tid = %d WHERE main_tid = %d", $main_tid, $merged_tid);
      }

      //insert into merging history
      db_query("INSERT INTO {taxonomy_manager_merge} (main_tid, merged_tid) VALUES (%d, %d)", $main_tid, $merged_tid);
    }
  }
  taxonomy_manager_merge_history_update_cache();
}

/**
 * helper function for getting out of term ids from autocomplete fields
 * non-exsiting terms get inserted autmatically
 * the input gets parsed for term names, optional a term id can be directly passed with prefixing the input with 'term-id:'
 *
 * @param $typed_input input string of form field
 * @param $vid vocabulary id
 * @param $insert_new TRUE if non-existing terms should be inserted
 * @param $lang define the language (optional)
 * @return array of term ids
 */
function taxonomy_manager_autocomplete_tags_get_tids($typed_input, $vid, $insert_new = TRUE, $lang = NULL) {
  $tids = array();
  $regexp = '%(?:^|,\\ *)("(?>[^"]*)(?>""[^"]* )*"|(?: [^",]*))%x';
  preg_match_all($regexp, $typed_input, $matches);
  $typed_terms = array_unique($matches[1]);
  foreach ($typed_terms as $typed_term) {
    $typed_term = str_replace('""', '"', preg_replace('/^"(.*)"$/', '\\1', $typed_term));
    $typed_term = trim($typed_term);
    if ($typed_term != "") {
      if (substr($typed_term, 0, 8) == "term-id:") {
        $id = substr($typed_term, 8);
        $term = taxonomy_get_term($id);
        if ($term->vid == $vid) {
          $tids[$term->tid]['tid'] = $term->tid;
        }
      }
      else {
        $possibilities = taxonomy_get_term_by_name($typed_term);
        $typed_term_tid = NULL;

        // tid match if any.
        foreach ($possibilities as $possibility) {
          if ($possibility->vid == $vid && !($lang && $lang != $possibility->language)) {
            $typed_term_tid = $possibility->tid;
            $tids[$typed_term_tid]['tid'] = $typed_term_tid;
          }
        }
        if (!$typed_term_tid && $insert_new) {
          $edit = array(
            'vid' => $vid,
            'name' => $typed_term,
          );
          $status = taxonomy_save_term($edit);
          if (module_exists('i18ntaxonomy') && $lang != "") {
            _i18ntaxonomy_term_set_lang($edit['tid'], $lang);
          }
          $typed_term_tid = $edit['tid'];
          $tids[$typed_term_tid]['tid'] = $typed_term_tid;
          $tids[$typed_term_tid]['new'] = TRUE;
        }
      }
    }
  }
  return $tids;
}

/**
 * similar to taxonomy_manager_autocomplete_tags_get_tids, but used for searching terms
 * takes synonyms and selected subtrees into account
 *
 * @param $typed_input input string of form field
 * @param $vid vocabulary id
 * @param $include_synonyms TRUE if search should include synonyms
 * @param $parents array of parents
 * @return array of term ids
 */
function taxonomy_manager_autocomplete_search_terms($typed_input, $vid, $include_synonyms = FALSE, $parents = array(), $language = NULL) {
  $tids = array();
  if ($language != NULL && $language == "no language") {
    $language = "";
  }
  $regexp = '%(?:^|,\\ *)("(?>[^"]*)(?>""[^"]* )*"|(?: [^",]*))%x';
  preg_match_all($regexp, $typed_input, $matches);
  $typed_terms = array_unique($matches[1]);
  foreach ($typed_terms as $typed_term) {
    $typed_term = str_replace('""', '"', preg_replace('/^"(.*)"$/', '\\1', $typed_term));
    $typed_term = trim($typed_term);
    if ($typed_term == "") {
      continue;
    }
    if ($include_synonyms) {
      if ($language != NULL) {
        $search_sql = db_query("SELECT td.tid FROM {term_data} td LEFT JOIN {term_synonym} ts ON td.tid = ts.tid WHERE td.vid = %d AND (td.name = '%s' OR ts.name = '%s') AND td.language = '%s'", $vid, $typed_term, $typed_term, $language);
      }
      else {
        $search_sql = db_query("SELECT td.tid FROM {term_data} td LEFT JOIN {term_synonym} ts ON td.tid = ts.tid WHERE td.vid = %d AND (td.name = '%s' OR ts.name = '%s')", $vid, $typed_term, $typed_term);
      }
    }
    else {
      if ($language != NULL) {
        $search_sql = db_query("SELECT td.tid FROM {term_data} td WHERE td.vid = %d AND td.name = '%s' AND td.language = '%s'", $vid, $typed_term, $language);
      }
      else {
        $search_sql = db_query("SELECT td.tid FROM {term_data} td WHERE td.vid = %d AND td.name = '%s'", $vid, $typed_term);
      }
    }
    while ($obj = db_fetch_object($search_sql)) {
      $tids[] = $obj->tid;
    }
    if (count($parents)) {
      $filtered_tids = array();
      foreach ($tids as $tid) {
        $parents_all = taxonomy_get_parents_all($tid);
        foreach ($parents_all as $key => $parent) {
          if (in_array($parent->tid, $parents)) {
            $filtered_tids[] = $tid;
            break;
          }
        }
      }
      $tids = $filtered_tids;
    }
  }
  return $tids;
}

/**
 * callback for updating weights
 * data send through AJAX, $_POST
 * $_POST[$tid] => $weight
 *
 */
function taxonomy_manager_update_weights() {
  $submitted_data = $_POST;
  if (taxonomy_manager_valid_ajax_callback($submitted_data) && is_array($submitted_data['weights'])) {
    foreach ($submitted_data['weights'] as $tid => $weight) {
      if (is_numeric($tid) && is_numeric($weight)) {
        db_query("UPDATE {term_data} SET weight = %d WHERE tid = %d", $weight, $tid);
      }
    }
  }
  exit;
}

/**
 * AJAX Callback that returns the CSV Output
 */
function taxonomy_manager_export() {
  $edit = $_POST;
  $depth = empty($edit['depth']) ? NULL : $edit['depth'];
  $output = taxonomy_manager_export_csv($edit['delimiter'], $edit['vid'], $edit['tid'], $depth, array(
    $edit['option'] => TRUE,
  ));
  print $output;
  exit;
}

/**
 * Generates the CVS Ouput
 */
function taxonomy_manager_export_csv($delimiter = ";", $vid, $selected_tid = 0, $depth = NULL, $options = array()) {
  $tree = taxonomy_manager_export_get_tree($vid, $selected_tid, $depth, $options);
  foreach ($tree as $term) {
    $array = array();
    $array[] = '"' . $term->vid . '"';
    $array[] = '"' . $term->tid . '"';
    $array[] = '"' . $term->name . '"';
    $array[] = '"' . $term->description . '"';
    foreach ($term->parents as $parent) {
      $array[] = '"' . $parent . '"';
    }
    $output .= implode($delimiter, $array) . "\n";
  }
  return $output;
}

/**
 * Helper for cvs export to get taxonomy tree
 */
function taxonomy_manager_export_get_tree($vid, $selected_tid, $depth, $options) {
  $tree = array();
  if ($options['whole_voc']) {
    $tree = taxonomy_get_tree($vid, 0, -1, $depth);
  }
  else {
    if ($options['children'] && $selected_tid) {
      $tree = taxonomy_get_tree($vid, $selected_tid, -1, $depth);
    }
    else {
      if ($options['root_terms']) {
        $tree = taxonomy_get_tree($vid, 0, -1, 1);
      }
    }
  }
  return $tree;
}

/**
 * Helper function that updates the hierarchy settings of a voc
 */
function taxonomy_manager_update_voc($vid, $parents = array()) {
  $voc = (array) taxonomy_vocabulary_load($vid);
  if ($voc->vid == $vid) {
    $current_hierarchy = count($parents);
    if ($current_hierarchy > 2) {
      $current_hierarchy = 2;
    }
    if ($current_hierarchy > $voc['hierarchy']) {
      $voc['hierarchy'] = $current_hierarchy;
      taxonomy_save_vocabulary($voc);
    }
  }
}

/**
 * Retrieve a pipe delimited string of autocomplete suggestions (+synonyms)
 */
function taxonomy_manager_autocomplete_load($vid, $string = '') {

  // The user enters a comma-separated list of tags. We only autocomplete the last tag.
  $array = drupal_explode_tags($string);

  // Fetch last tag
  $last_string = trim(array_pop($array));
  $matches = array();
  if ($last_string != '') {
    $result = db_query_range("SELECT t.name FROM {term_data} t\n      LEFT JOIN {term_synonym} s ON t.tid = s.tid\n      WHERE t.vid = %d\n      AND (LOWER(t.name) LIKE LOWER('%%%s%%') OR LOWER(s.name) LIKE LOWER('%%%s%%'))", $vid, $last_string, $last_string, 0, 30);
    $prefix = count($array) ? '"' . implode('", "', $array) . '", ' : '';
    while ($tag = db_fetch_object($result)) {
      $n = $tag->name;

      // Commas and quotes in terms are special cases, so encode 'em.
      if (strpos($tag->name, ',') !== FALSE || strpos($tag->name, '"') !== FALSE) {
        $n = '"' . str_replace('"', '""', $tag->name) . '"';
      }
      $matches[$prefix . $n] = check_plain($tag->name);
    }
  }
  drupal_json($matches);
}

/**
 * theme function for taxonomy manager form
 */
function theme_taxonomy_manager_form($form) {
  $pager = theme('pager', NULL, TAXONOMY_MANAGER_TREE_PAGE_SIZE, 0);
  $tree = drupal_render($form['taxonomy']);
  $term_data = drupal_render($form['term_data']);
  $top = drupal_render($form);
  $output = $top . $pager;
  $output .= '<div id="taxonomy-manager" class="admin clear-block">';
  $output .= '<div id="taxonomy-manager-tree-outer-div" class="left clear-block">';
  $output .= $tree;
  $output .= '</div>';
  $output .= '<div id="taxonomy-term-data" class="right clear-block">';
  $output .= is_array($form['term_data']['tid']) ? $term_data : '';
  $output .= '</div>';
  $output .= '</div>';
  return $output;
}

/**
 * theme function for taxonomy manager form
 */
function theme_taxonomy_manager_double_tree_form($form) {
  $pager = theme('pager', NULL, TAXONOMY_MANAGER_TREE_PAGE_SIZE, 0);
  $tree1 = drupal_render($form['taxonomy']);
  $tree2 = drupal_render($form['taxonomy2']);
  $operations = drupal_render($form['double-tree']);
  $term_data = drupal_render($form['term_data']);
  $top = drupal_render($form);
  $output = $top . $pager;
  $output .= '<div id="taxonomy-manager" class="admin clear-block">';
  $output .= '<div id="taxonomy-manager-tree-outer-div" class="left clear-block">';
  $output .= $tree1;
  $output .= '</div>';
  $output .= '<div id="taxonomy-manager-double-tree-operations">';
  $output .= $operations;
  $output .= '</div>';
  $output .= '<div id="taxonomy2-manager-tree-outer-div" class="left clear-block">';
  $output .= $tree2;
  $output .= '</div>';
  $output .= '<div id="taxonomy-term-data" class="term-data-overlay">';
  $output .= is_array($form['term_data']['tid']) ? $term_data : '';
  $output .= '</div>';
  $output .= '</div>';
  return $output;
}

/**
 * themes a real button form type (no form submit)
 */
function theme_no_submit_button($element) {

  // Make sure not to overwrite classes.
  if (isset($element['#attributes']['class'])) {
    $element['#attributes']['class'] = 'form-' . $element['#button_type'] . ' ' . $element['#attributes']['class'];
  }
  else {
    $element['#attributes']['class'] = 'form-' . $element['#button_type'];
  }
  return '<input type="button" ' . (empty($element['#name']) ? '' : 'name="' . $element['#name'] . '" ') . 'id="' . $element['#id'] . '" value="' . check_plain($element['#value']) . '" ' . drupal_attributes($element['#attributes']) . " />\n";
}

/**
 * themes a image type button
 */
function theme_taxonomy_manager_image_button($element) {

  //Make sure not to overwrite classes
  if (isset($element['#attributes']['class'])) {
    $element['#attributes']['class'] = 'form-' . $element['#button_type'] . ' ' . $element['#attributes']['class'];
  }
  else {
    $element['#attributes']['class'] = 'form-' . $element['#button_type'];
  }

  // here the novelty begins: check if #button_type is normal submit button or image button
  $return_string = '<input ';
  if ($element['#button_type'] == 'image') {
    $return_string .= 'type="image" ';
  }
  else {
    $return_string .= 'type="submit" ';
  }
  $return_string .= empty($element['#id']) ? '' : 'id="' . $element['#id'] . '" ';
  $return_string .= empty($element['#name']) ? '' : 'name="' . $element['#name'] . '" ';
  $return_string .= 'value="' . check_plain($element['#value']) . '" ';
  $return_string .= drupal_attributes($element['#attributes']) . " />\n";
  return $return_string;
}
function theme_taxonomy_manager_term_data_extra($element) {
  $rows = array();
  $headers = array();
  foreach (element_children($element['headers']) as $key) {
    if (is_array($element['headers'][$key])) {
      $headers[] = drupal_render($element['headers'][$key]);
    }
  }
  foreach ($element['data'] as $tid => $entries) {
    $row = array();
    foreach (element_children($element['data'][$tid]) as $key) {
      if (is_array($element['data'][$tid][$key])) {
        $row[] = array(
          'data' => drupal_render($element['data'][$tid][$key]),
          'class' => $element['data'][$tid][$key]['#row-class'],
          'id' => $element['data'][$tid][$key]['#row-id'],
        );
      }
    }
    $rows[] = $row;
  }
  $row = array();
  foreach (element_children($element['op']) as $key) {
    if (is_array($element['op'][$key])) {
      $row[] = drupal_render($element['op'][$key]);
    }
  }
  $rows[] = $row;
  return theme('table', $headers, $rows);
}

Functions

Namesort descending Description
taxonomy_manager_add_form form for adding terms
taxonomy_manager_add_translation adds translation between two terms
taxonomy_manager_autocomplete_load Retrieve a pipe delimited string of autocomplete suggestions (+synonyms)
taxonomy_manager_autocomplete_search_terms similar to taxonomy_manager_autocomplete_tags_get_tids, but used for searching terms takes synonyms and selected subtrees into account
taxonomy_manager_autocomplete_tags_get_tids helper function for getting out of term ids from autocomplete fields non-exsiting terms get inserted autmatically the input gets parsed for term names, optional a term id can be directly passed with prefixing the input with 'term-id:'
taxonomy_manager_check_circular_hierarchy checks for circles in the hierarchy, e.g. 1 -> 2 -> 3 -> 1 a term can't contain itself as a parent
taxonomy_manager_check_language checks if terms in move or merge operation are of the same language
taxonomy_manager_confirm_delete confirmation form for deleting selected terms
taxonomy_manager_delete_terms deletes terms from the database optional orphans (terms where parent get deleted) can be deleted as well
taxonomy_manager_doube_tree_edit_translate
taxonomy_manager_double_tree_edit AJAX Callback for Double Tree operations
taxonomy_manager_double_tree_edit_move
taxonomy_manager_double_tree_edit_switch
taxonomy_manager_double_tree_form
taxonomy_manager_double_tree_form_submit submits the taxonomy manager double tree
taxonomy_manager_double_tree_form_validate validates taxonomy manager double tree
taxonomy_manager_double_tree_settings_form
taxonomy_manager_export AJAX Callback that returns the CSV Output
taxonomy_manager_export_csv Generates the CVS Ouput
taxonomy_manager_export_form form for exporting terms
taxonomy_manager_export_get_tree Helper for cvs export to get taxonomy tree
taxonomy_manager_form defines forms for taxonomy manager interface
taxonomy_manager_form_add_submit Submit handler for adding terms
taxonomy_manager_form_delete_submit Submit handler for deleting terms
taxonomy_manager_form_delete_validate Validation handler for deleting terms
taxonomy_manager_form_double_tree_disable_submit
taxonomy_manager_form_double_tree_submit
taxonomy_manager_form_merge_submit Submit handler for merging terms
taxonomy_manager_form_merge_validate Validation handler for validating terms
taxonomy_manager_form_move_submit Submit handler for moving terms
taxonomy_manager_form_move_validate Validation handler for moving terms
taxonomy_manager_form_submit submits the taxonomy manager form (only search button)
taxonomy_manager_form_term_data term data editing form
taxonomy_manager_form_validate validates the form (only search button)
taxonomy_manager_merge merges terms into another term (main term), all merged term get added to the main term as synonyms. term_node relations are updated automatically (node with one of merging terms gets main term assigned) after all opterions are done (adding of…
taxonomy_manager_merge_form form for merging terms
taxonomy_manager_merge_history_update inserts merging information (main_tid - merged_tid ) into taxonomy_manager_merge and updates cache, which is used to reconstructs taxonomy/term pages
taxonomy_manager_move moves terms in hierarchies to other parents
taxonomy_manager_move_form form for moving terms in hierarchies
taxonomy_manager_settings Defines a settings form.
taxonomy_manager_switch Changes vocabulary of given terms and its children conflicts might be possible with multi-parent terms!
taxonomy_manager_term_confirm_delete Form builder for the term delete form.
taxonomy_manager_term_confirm_delete_submit Submit handler to delete a term after confirmation.
taxonomy_manager_term_data_edit callback handler for updating term data
taxonomy_manager_toolbar_forms
taxonomy_manager_update_term_data_form menu callback for displaying term data form
taxonomy_manager_update_voc Helper function that updates the hierarchy settings of a voc
taxonomy_manager_update_weights callback for updating weights data send through AJAX, $_POST $_POST[$tid] => $weight
taxonomy_manager_valid_ajax_callback Validates a custom AJAX callback by ensuring that the request contains a valid form token, which prevents CSRF.
taxonomy_manager_voc_list list of vocabularies, which link to Taxonomy Manager interface
theme_no_submit_button themes a real button form type (no form submit)
theme_taxonomy_manager_double_tree_form theme function for taxonomy manager form
theme_taxonomy_manager_form theme function for taxonomy manager form
theme_taxonomy_manager_image_button themes a image type button
theme_taxonomy_manager_term_data_extra
_taxonomy_manager_check_duplicates returns TRUE if term with same name exists more often
_taxonomy_manager_form_term_data_lists helper function for generating tables with values and delete op and field for adding
_taxonomy_manager_form_term_data_translations helper function for generating a table listing the translations
_taxonomy_manager_voc_is_empty checks if voc has terms