You are here

taxonomy_dupecheck.module in Taxonomy dupecheck 7

Same filename and directory in other branches
  1. 6 taxonomy_dupecheck.module

Module file for the Taxonomy dupecheck module.

File

taxonomy_dupecheck.module
View source
<?php

/**
 * @file
 * Module file for the Taxonomy dupecheck module.
 */

/**
 * Implements hook_help().
 */
function taxonomy_dupecheck_help($path, $arg) {
  if ($path == 'admin/help#taxonomy_dupecheck') {
    $output = '<h3>' . t('About') . '</h3>';
    $output .= '<p>' . t("The Taxonomy dupecheck module prevents Drupal administrators from adding duplicate taxonomy vocabularies and/or terms. It's helpful when entering large amounts of terms or vocabularies in situations where each value must be unique. This saves time by preventing administrators from enforcing a unique value policy through later cleanup.") . '</p>';
    $output .= '<p>' . t("The module provides a configuration screen allowing administrators to choose which should be unique: taxonomy terms, vocabularies or both. It defaults to case-insensitive comparisons, with an option to change to case-sensitive. Based on the settings, the user will see an error message when adding a duplicate value.") . '</p>';
    return $output;
  }
}

/**
 * Implements hook_menu().
 */
function taxonomy_dupecheck_menu() {
  $items = array();
  $items['admin/config/content/taxonomy_dupecheck'] = array(
    'title' => 'Taxonomy dupecheck',
    'description' => 'Configuration for the Taxonomy dupecheck module.',
    'page callback' => 'drupal_get_form',
    'page arguments' => array(
      'taxonomy_dupecheck_form',
    ),
    'access arguments' => array(
      'administer taxonomy',
    ),
  );
  return $items;
}

/**
 * Form builder; creates and displays the Taxonomy dupecheck
 * configuration settings form.
 */
function taxonomy_dupecheck_form($form, &$form_state) {

  // Checkboxes to choose what should be checked for dupes (vocab, terms, both)
  $form['taxonomy_dupecheck_types'] = array(
    '#type' => 'checkboxes',
    '#title' => 'Check for duplicate',
    '#default_value' => variable_get('taxonomy_dupecheck_types', array()),
    '#options' => array(
      'vocab' => t('Vocabularies'),
      'term' => t('Terms (within a vocabulary)'),
    ),
  );
  $vocabs = taxonomy_get_vocabularies();
  $options = array();
  foreach ($vocabs as $v) {
    $options[$v->vid] = $v->name;
  }
  $form['taxonomy_dupecheck_vocabularies'] = array(
    '#type' => 'checkboxes',
    '#title' => 'Limit term check on specific vocabularies',
    '#default_value' => variable_get('taxonomy_dupecheck_vocabularies', array()),
    '#options' => $options,
    '#description' => t('If no option is selected, all terms will be checked for duplicates.'),
  );

  // Checkbox to indicate whether the check should be case-sensitive
  $form['taxonomy_dupecheck_case_sensitive'] = array(
    '#type' => 'checkbox',
    '#title' => "Case-sensitive comparison (e.g. 'Foo' and 'foo' are not duplicates if checked).",
    '#default_value' => variable_get('taxonomy_dupecheck_case_sensitive'),
  );
  return system_settings_form($form);
}

/**
 * Implements hook_form_FORM_ID_alter() for taxonomy_form_term().
 */
function taxonomy_dupecheck_form_taxonomy_form_term_alter(&$form, &$form_state, $form_id) {

  // Do not add the validator if Delete was hit.
  if (isset($form_state['triggering_element']['#value']) && $form_state['triggering_element']['#value'] == t('Delete')) {
    return;
  }

  // Get the types of taxonomy objects we will validate against
  $types = variable_get('taxonomy_dupecheck_types', array());

  // Add the validator if we're checking terms for dupes.
  if (!empty($types['term'])) {
    $vids = array_filter(variable_get('taxonomy_dupecheck_vocabularies', array()));
    if (count($vids) == 0 || in_array($form['vid']['#value'], $vids)) {
      $form['#validate'][] = 'taxonomy_dupecheck_term_validate';
    }
  }
}

/**
 * Implements hook_form_FORM_ID_alter() for taxonomy_form_vocabulary().
 */
function taxonomy_dupecheck_form_taxonomy_form_vocabulary_alter(&$form, &$form_state, $form_id) {

  // Do not add the validator if Delete was hit.
  if (isset($form_state['triggering_element']['#value']) && $form_state['triggering_element']['#value'] == t('Delete')) {
    return;
  }

  // Get the types of taxonomy objects we will validate against
  $types = variable_get('taxonomy_dupecheck_types', array());

  // Add the validator if we're checking vocabularies for dupes.
  if (!empty($types['vocab'])) {
    $form['#validate'][] = 'taxonomy_dupecheck_vocabulary_validate';
  }
}

/**
 * Implements _form_validate() for taxonomy_form_term().
 */
function taxonomy_dupecheck_term_validate($form, &$form_state) {
  $term = $form_state['values']['name'];
  $vid = $form_state['values']['vid'];
  $tid = $form_state['values']['tid'];
  if (taxonomy_dupecheck_is_dupe_term($term, $vid, $tid)) {
    form_set_error('name', t('The term %term already exists in this vocabulary.', array(
      '%term' => check_plain($term),
    )));
  }
}

/**
 * Implements _form_validate() for taxonomy_form_vocabulary().
 */
function taxonomy_dupecheck_vocabulary_validate($form, &$form_state) {
  $vocab = $form_state['values']['name'];
  $vid = isset($form_state['values']['vid']) ? $form_state['values']['vid'] : 0;
  if (taxonomy_dupecheck_is_dupe_vocabulary($vocab, $vid)) {
    form_set_error('name', t('The vocabulary %term already exists.', array(
      '%term' => check_plain($vocab),
    )));
  }
}

/**
 * Checks whether a term is a duplicate, based on the module preferences.
 *
 * @param $term
 *   Name of the new term to check
 *
 * @param int $vid
 *   ID of the vocabulary the new term belongs to
 *
 * @param int $tid
 *   Term ID of the new term (used when updating an existing term name)
 *
 * @return bool
 *   TRUE if the term is a duplicate, FALSE if not
 */
function taxonomy_dupecheck_is_dupe_term($term, $vid, $tid = 0) {

  // Clean up the term to check
  $term = trim($term);

  // Get matching terms in the given vocabulary (case insensitive)
  $query = new EntityFieldQuery();
  $query = $query
    ->entityCondition('entity_type', 'taxonomy_term')
    ->propertyCondition('name', $term)
    ->propertyCondition('vid', $vid);
  if ($tid) {

    // Ignore an existing term of the same name; this is needed on updates to an existing term.
    $query = $query
      ->entityCondition('entity_id', $tid, '<>');
  }
  $result = $query
    ->execute();

  // No results, term is unique
  if (is_array($result) && !$result) {
    return FALSE;
  }

  // We found a result
  if (isset($result['taxonomy_term'])) {

    // Do a case sensitive comparison if requested, but if not,
    // just return that we found a match
    if (variable_get('taxonomy_dupecheck_case_sensitive')) {
      $is_dupe = FALSE;

      // For each found result...
      foreach ($result['taxonomy_term'] as $found_term) {

        // Load the term data and see if it's a dupe
        $term_data = taxonomy_term_load($found_term->tid);
        if (!strcmp($term_data->name, $term)) {
          $is_dupe = TRUE;
          break;
        }
      }
      return $is_dupe;
    }
    else {

      // Not case sensitive
      return TRUE;
    }
  }
  return FALSE;
}

/**
 * Checks whether a vocabulary is a duplicate, based on the module preferences.
 *
 * @param $vocab
 *   Name of the new vocabulary to check
 *
 * @param int $vid
 *   ID of the vocabulary the new term belongs to (used when updating an existing vocabulary)
 *
 * @return
 *   TRUE if the vocabulary is a duplicate, FALSE if not
 */
function taxonomy_dupecheck_is_dupe_vocabulary($vocab, $vid = 0) {

  // Clean up the vocabulary to check
  $vocab = trim($vocab);

  // Get all vocabularies
  $vocabs = taxonomy_get_vocabularies();

  // Look for a vocabulary with the same name based on case-sensitivity preferences
  $case_sensitive = variable_get('taxonomy_dupecheck_case_sensitive');
  foreach ($vocabs as $found_vocab) {

    // Skip the check if the current found vocabulary is the same one we're comparing.
    // This will happen on updates to an existing vocabulary.
    if ($vid == $found_vocab->vid) {
      continue;
    }

    // Clean up the stored vocabulary. This helps for systems that
    // don't trim their vocabulary names before entry.
    $found_vocab_name = trim($found_vocab->name);
    if ($case_sensitive && !strcmp($found_vocab_name, $vocab) || !$case_sensitive && !strcasecmp($found_vocab_name, $vocab)) {
      return TRUE;
    }
  }
  return FALSE;
}

Functions

Namesort descending Description
taxonomy_dupecheck_form Form builder; creates and displays the Taxonomy dupecheck configuration settings form.
taxonomy_dupecheck_form_taxonomy_form_term_alter Implements hook_form_FORM_ID_alter() for taxonomy_form_term().
taxonomy_dupecheck_form_taxonomy_form_vocabulary_alter Implements hook_form_FORM_ID_alter() for taxonomy_form_vocabulary().
taxonomy_dupecheck_help Implements hook_help().
taxonomy_dupecheck_is_dupe_term Checks whether a term is a duplicate, based on the module preferences.
taxonomy_dupecheck_is_dupe_vocabulary Checks whether a vocabulary is a duplicate, based on the module preferences.
taxonomy_dupecheck_menu Implements hook_menu().
taxonomy_dupecheck_term_validate Implements _form_validate() for taxonomy_form_term().
taxonomy_dupecheck_vocabulary_validate Implements _form_validate() for taxonomy_form_vocabulary().