You are here

term_merge.module in Term Merge 5

Same filename and directory in other branches
  1. 6 term_merge.module
  2. 7 term_merge.module

File

term_merge.module
View source
<?php

/**
* term_merge.module by Eli Dickinson - eli (-at-) fiercemarkets.com
* Based on Merging_Terms.txt by Aldo Hoeben (see http://drupal.org/node/113975)
* Version 0.1 - 2007-05-10
*
*
* 	This module creates a new link at the bottom of the Edit Term form that lets 
*		you merge the displayed term with another term. All nodes from the old term
*		will be tagged with the new term.
*
*		 
*/

/**
* Implementation of hook_help().
*/
function term_merge_help($section) {
  switch ($section) {
    case 'admin/modules#description':
      return t('Allows site admins to merge two terms, making one a synonym of another.');
  }
}

/**
* Implementation of hook_menu()
*/
function term_merge_menu($may_cache) {
  $items = array();
  if ($may_cache) {
    $items[] = array(
      'path' => 'term_merge/merge',
      'title' => t('Merges one Term into anothers'),
      'access' => user_access('administer taxonomy'),
      'type' => MENU_CALLBACK,
      'callback' => 'term_merge_merge',
    );
  }
  return $items;
}
function term_merge_merge($from_tid) {
  return drupal_get_form('term_merge_merge_form', $from_tid);
}

/**
 * Presents the form to select which node to merge into.
 */
function term_merge_merge_form($tid) {

  //$form[] = array('#value' => $tid);
  $from_term = taxonomy_get_term($tid);
  $from_name = check_plain($from_term->name);
  $term = taxonomy_get_term($tid);
  $form['from_tid'] = array(
    '#type' => 'value',
    '#value' => $tid,
  );
  $form['to_tid'] = _taxonomy_term_select(t("Merge all '{$from_name}' items into"), 'to_tid', -1, $term->vid, '', FALSE, NULL, array(
    $tid,
  ));
  $form['submit'] = array(
    '#type' => 'submit',
    '#value' => t('Merge'),
  );
  $form['info'] = array(
    '#value' => "<p>As a result of this operation, '{$from_name}' will be deleted and all the nodes tagged with '{$from_name}' will now be tagged with the selection in the box above. In addition '{$from_name}' will be listed as a synonym for the selected node.</p><p>Note that this operation is not reversible!</p>",
  );
  return $form;
}

/**
 * Actually merges the terms 
 */
function term_merge_merge_form_submit($form_id, $form_values) {

  //print implode(",",$form_values);
  $to_term = taxonomy_get_term($form_values['to_tid']);
  $from_term = taxonomy_get_term($form_values['from_tid']);
  $old_max_exec = ini_get('max_execution_time');
  if ($old_max_exec < 30) {
    $old_max_exec = 30;
  }
  set_time_limit(100);

  // Copy any Synonyms from from_term to to_term.
  // I'd love to do this with a Drupal func, but taxonomy_save_term() looks like way more trouble than it's worth
  db_query("INSERT INTO {term_synonym} (tid, name) (SELECT '%d',name from {term_synonym} where tid = '%d')", $to_term->tid, $from_term->tid);

  //TODO: This could lead to duplicate synonyms.

  // save a list of nodes we need to update to new term
  $nodes_to_update = _term_merge_select_nodes($from_term->tid);

  // Add from_node as a synonym to to_node to prevent future duplication
  db_query("INSERT INTO {term_synonym} (tid, name) VALUES (%d, '%s')", $to_term->tid, $from_term->name);

  //TODO: This could lead to duplicate synonyms.

  // update old nodes to new nodes
  while ($node_record = db_fetch_object($nodes_to_update)) {
    $node = node_load($node_record->nid);

    // gotta use node_load to get the taxonomies in there
    $save_node_changes = TRUE;
    $new_taxonomy = array();
    foreach ($node->taxonomy as $term) {
      if ($term->tid == $to_term->tid) {

        // If the node already has the destination tag, we don't need to change a thing!
        // (taxonomy_del_term will take care of removing the old tag)
        $save_node_changes = FALSE;
        break;
      }
      if ($term->tid == $from_term->tid) {
        $new_taxonomy[] = $to_term;

        // make the switch!
      }
      else {
        $new_taxonomy[] = $term;
      }
    }
    if ($save_node_changes) {
      taxonomy_node_save($node->nid, $new_taxonomy);
    }

    // note for 6.x: taxonomy_node_save was changed to take a $node object instead of $nid
  }
  taxonomy_del_term($from_term->tid);
  set_time_limit($old_max_exec);
  drupal_set_message(t('The terms have been merged. Have a great day.'));
  return 'admin/content/taxonomy/' . $to_term->vid;
}

/**
* Implementation of hook_form_alter().
*/
function term_merge_form_alter($form_id, &$form) {

  // Add the link to the term edit form
  if ($form_id == 'taxonomy_form_term') {
    $tid = $form['tid']['#value'];

    //$tid= arg(5);
    $form['merge'] = array(
      '#value' => '<div><strong>' . l(t('Merge this term into another another'), "term_merge/merge/{$tid}") . '</strong></div>',
    );
  }
}

/**
 *	Returns the results of a query for nodes associated for the specified $tid. (Thanks, Aldo!)
 */
function _term_merge_select_nodes($tid) {

  // I would have liked to use taxonomy_select_nodes() instead, but that function
  // either uses a pager, or returns only the latest n nodes, and we need all of them
  // (including unpublished nodes)
  // generate an array of descendant term IDs to the right depth.
  $descendant_tids = array();
  $term = taxonomy_get_term($tid);
  $tree = taxonomy_get_tree($term->vid, $tid, -1, NULL);
  $descendant_tids[] = array_merge(array(
    $tid,
  ), array_map('_taxonomy_get_tid_from_term', $tree));
  $str_tids = implode(',', call_user_func_array('array_merge', $descendant_tids));
  $sql = 'SELECT DISTINCT(n.nid), n.sticky, n.title, n.created FROM {node} n INNER JOIN {term_node} tn ON n.nid = tn.nid WHERE tn.tid IN (' . $str_tids . ')';
  $result = db_query(db_rewrite_sql($sql));
  return $result;
}

Functions

Namesort descending Description
term_merge_form_alter Implementation of hook_form_alter().
term_merge_help Implementation of hook_help().
term_merge_menu Implementation of hook_menu()
term_merge_merge
term_merge_merge_form Presents the form to select which node to merge into.
term_merge_merge_form_submit Actually merges the terms
_term_merge_select_nodes Returns the results of a query for nodes associated for the specified $tid. (Thanks, Aldo!)