You are here

taxonomy_tools_publisher.module in Taxonomy Tools 8

Same filename and directory in other branches
  1. 7 taxonomy_tools_publisher/taxonomy_tools_publisher.module

Drupal hooks and functions to manipulate taxonomy terms.

This is the main file for Taxonomy Publisher. Taxonomy terms now use a status token. It is considered when user tries to access taxonomy term page taxonomy/term/xxx. Taxonomy terms also use a scheduler, which is run every time cron is run. This module also implements Drupal node access system to control access to nodes that are associated with taxonomy terms.

File

taxonomy_tools_publisher/taxonomy_tools_publisher.module
View source
<?php

/**
 * @file
 * Drupal hooks and functions to manipulate taxonomy terms.
 *
 * This is the main file for Taxonomy Publisher.
 * Taxonomy terms now use a status token. It is considered when user tries
 * to access taxonomy term page taxonomy/term/xxx. Taxonomy terms also use
 * a scheduler, which is run every time cron is run. This module also
 * implements Drupal node access system to control access to nodes
 * that are associated with taxonomy terms.
 */

/**
 * Date format for Taxonomy Publisher messages.
 */
define('TAXONOMY_PUBLISHER_MESSAGE_DATE_FORMAT', 'd.m.Y H:i:s');

/**
 * Taxonomt term is published;
 */
define('TERM_PUBLISHED', 1);

/**
 * Taxonomy term is not published.
 */
define('TERM_NOT_PUBLISHED', 0);

/**
 * Implements hook_menu().
 */
function taxonomy_tools_publisher_menu() {
  $items['admin/config/taxonomy-tools/publisher'] = array(
    'title' => 'Taxonomy Publisher',
    'description' => 'Configure which vocabularies will use Taxonomy Publisher.',
    'page callback' => 'drupal_get_form',
    'page arguments' => array(
      'taxonomy_tools_publisher_admin_form',
    ),
    'access arguments' => array(
      'administer taxonomy publisher configuration',
    ),
    'file' => 'taxonomy_tools_publisher.admin.inc',
    'file path' => drupal_get_path('module', 'taxonomy_tools_publisher'),
  );
  return $items;
}

/**
 * Implements hook_form_FORM_ID_alter().
 */
function taxonomy_tools_publisher_form_taxonomy_form_term_alter(&$form, &$form_state) {
  $config = array_filter(variable_get('taxonomy_tools_publisher_config', array()));
  if (!empty($config) && in_array($form['#vocabulary']->machine_name, $config)) {

    // Only for terms that are from vocabularies that use Taxonomy Publisher.
    if (user_access('administer term schedule')) {

      // Add js files that adds custom controls for jQuery datepicker.
      $form['#attached']['js'][] = array(
        'data' => 'http://datejs.googlecode.com/files/date.js',
        'type' => 'external',
      );

      // Datepicker localization.
      global $language;
      if ($language->language != 'en') {
        $form['#attached']['js'][] = drupal_get_path('module', 'jquery_update') . '/replace/ui/ui/i18n/jquery.ui.datepicker-' . $language->language . '.js';
      }
      $form['#attached']['js'][] = drupal_get_path('module', 'taxonomy_tools_publisher') . '/js/taxonomy_tools_publisher.js';

      // Add additional validation function.
      $form['#validate'][] = 'taxonomy_tools_publisher_taxonomy_term_form_validate';

      // Add buttons for clearing date values.
      if (isset($form['field_taxonomy_term_publish_on'])) {
        $form['field_taxonomy_term_publish_on']['#suffix'] = '<input type="button" value="' . t('Clear publishing date & time') . '" class="form-submit" onClick="clearpub();">';
      }
      if (isset($form['field_taxonomy_term_unpublish_on'])) {
        $form['field_taxonomy_term_unpublish_on']['#suffix'] = '<input type="button" value="' . t('Clear unpublishing date & time') . '" class="form-submit" onClick="clearunpub();">';
      }

      // Checkbox default value when date fields are available but no values
      // exist in database; happens when editing terms from vocabulary for
      // which Taxonomy Publisher was enabled when terms already exist in it.
      if (empty($form_state['build_info']['args'][0]->field_taxonomy_term_status)) {
        $form['field_taxonomy_term_status'][LANGUAGE_NONE]['#default_value'] = TERM_PUBLISHED;
      }
    }
    else {

      // User is not allowed to use taxonomy scheduler.
      $form['field_taxonomy_term_status']['#access'] = FALSE;
      $form['field_taxonomy_term_publish_on']['#access'] = FALSE;
      $form['field_taxonomy_term_unpublish_on']['#access'] = FALSE;
    }
  }
}

/**
 * Validates the user input of Taxonomy Publisher fields.
 *
 * @see taxonomy_tools_publisher_form_taxonomy_form_term_alter()
 */
function taxonomy_tools_publisher_taxonomy_term_form_validate($form, &$form_state) {
  if (!empty($form_state['values']['field_taxonomy_term_publish_on'][LANGUAGE_NONE][0]['value'])) {
    $publish_on = $form_state['values']['field_taxonomy_term_publish_on'][LANGUAGE_NONE][0]['value'];
    if ($publish_on < REQUEST_TIME) {

      // Publish on value must be in future.
      form_set_error('field_taxonomy_term_publish_on', t('The "Publish on:" date must be in the future.'));
    }
  }
  if (!empty($form_state['values']['field_taxonomy_term_unpublish_on'][LANGUAGE_NONE][0]['value'])) {
    $unpublish_on = $form_state['values']['field_taxonomy_term_unpublish_on'][LANGUAGE_NONE][0]['value'];
    if ($unpublish_on < REQUEST_TIME) {

      // Unpublish on value must be in future.
      form_set_error('field_taxonomy_term_unpublish_on', t('The "Unpublish on:" date must be in the future.'));
    }
  }
  if (isset($publish_on) && isset($unpublish_on) && $publish_on > $unpublish_on) {

    // Unpublish on value must be after publish on value.
    form_set_error('field_taxonomy_term_unpublish_on', t('The "Unpublish on:" date must be later than the "Publish on;" date.'));
  }
}

/**
 * Implements hook_taxonomy_term_presave().
 */
function taxonomy_tools_publisher_taxonomy_term_presave($term) {
  if (in_array($term->vocabulary_machine_name, array_filter(variable_get('taxonomy_tools_publisher_config', array())))) {

    // Clear unpublish value if term status is set to unpublished and
    // publish value is not set.
    if (isset($term->field_taxonomy_term_status) && $term->field_taxonomy_term_status[LANGUAGE_NONE][0]['value'] == TERM_NOT_PUBLISHED && isset($term->field_taxonomy_term_publish_on) && empty($term->field_taxonomy_term_publish_on[LANGUAGE_NONE]) && isset($term->field_taxonomy_term_unpublish_on) && !empty($term->field_taxonomy_term_unpublish_on[LANGUAGE_NONE])) {
      $term->field_taxonomy_term_unpublish_on[LANGUAGE_NONE] = array();
    }

    // Set term status to unpublished if publish and unpublish values are set.
    if (isset($term->field_taxonomy_term_status) && $term->field_taxonomy_term_status[LANGUAGE_NONE][0]['value'] == TERM_PUBLISHED && isset($term->field_taxonomy_term_publish_on) && !empty($term->field_taxonomy_term_publish_on[LANGUAGE_NONE]) && isset($term->field_taxonomy_term_unpublish_on) && !empty($term->field_taxonomy_term_unpublish_on[LANGUAGE_NONE])) {
      $term->field_taxonomy_term_status[LANGUAGE_NONE][0]['value'] = TERM_NOT_PUBLISHED;
    }

    // Show term status message.
    if (isset($term->field_taxonomy_term_status)) {
      $message = '';
      if ($term->field_taxonomy_term_status[LANGUAGE_NONE][0]['value'] == TERM_PUBLISHED) {
        $message .= t('The term @name is published.', array(
          '@name' => $term->name,
        ));
        if (isset($term->field_taxonomy_term_unpublish_on) && !empty($term->field_taxonomy_term_unpublish_on[LANGUAGE_NONE])) {
          $message .= ' ';
          $message .= t('It will be unpublished on @unpublish_on', array(
            '@unpublish_on' => format_date($term->field_taxonomy_term_unpublish_on[LANGUAGE_NONE][0]['value'], 'custom', TAXONOMY_PUBLISHER_MESSAGE_DATE_FORMAT),
          ));
        }
      }
      else {
        $message .= t('The term @name is unpublished.', array(
          '@name' => $term->name,
        ));
        if (isset($term->field_taxonomy_term_publish_on) && !empty($term->field_taxonomy_term_publish_on[LANGUAGE_NONE])) {
          $message .= ' ';
          $message .= t('It will be published on @publish_on', array(
            '@publish_on' => format_date($term->field_taxonomy_term_publish_on[LANGUAGE_NONE][0]['value'], 'custom', TAXONOMY_PUBLISHER_MESSAGE_DATE_FORMAT),
          ));
        }
      }
      drupal_set_message(check_plain($message));
    }
  }
}

/**
 * Implements hook_cron().
 */
function taxonomy_tools_publisher_cron() {

  // Publish terms.
  taxonomy_tools_publisher_publish();

  // Allow other modules to act upon scheduled term publishing.
  module_invoke_all('taxonomy_tools_publisher_terms_publish');

  // Unpublish terms.
  taxonomy_tools_publisher_unpublish();

  // Allow other modules to act upon scheduled term publishing.
  module_invoke_all('taxonomy_tools_publisher_terms_unpublish');
}

/**
 * Publishes scheduled taxonomy terms.
 */
function taxonomy_tools_publisher_publish() {

  // Collect term ID's of terms which publish on value is before now.
  $config = array_filter(variable_get('taxonomy_tools_publisher_config', array()));
  $query = db_select('field_data_field_taxonomy_term_publish_on', 'foo');
  $query
    ->addField('foo', 'entity_id', 'tid');
  $query
    ->addField('foo', 'field_taxonomy_term_publish_on_value', 'publish_on');
  $query
    ->leftJoin('taxonomy_term_data', 'bar', 'foo.entity_id = bar.tid');
  $query
    ->join('taxonomy_vocabulary', 'baz', 'baz.vid = bar.vid');
  $query
    ->condition('baz.machine_name', $config, 'IN');
  $result = $query
    ->execute()
    ->fetchAll();
  $tids = array();
  foreach ($result as $data) {
    if ($data->publish_on < REQUEST_TIME) {
      $tids[] = $data->tid;
    }
  }
  foreach ($tids as $tid) {

    // Publish the term.
    taxonomy_tools_publisher_publish_term($tid);
  }
}

/**
 * Unpublishes scheduled taxonomy terms.
 */
function taxonomy_tools_publisher_unpublish() {

  // Collect term ID's of terms which publish on value is before now.
  $config = array_filter(variable_get('taxonomy_tools_publisher_config', array()));
  $query = db_select('field_data_field_taxonomy_term_unpublish_on', 'foo');
  $query
    ->addField('foo', 'entity_id', 'tid');
  $query
    ->addField('foo', 'field_taxonomy_term_unpublish_on_value', 'unpublish_on');
  $query
    ->leftJoin('taxonomy_term_data', 'bar', 'foo.entity_id = bar.tid');
  $query
    ->join('taxonomy_vocabulary', 'baz', 'baz.vid = bar.vid');
  $query
    ->condition('baz.machine_name', $config, 'IN');
  $result = $query
    ->execute()
    ->fetchAll();
  $tids = array();
  foreach ($result as $data) {
    if ($data->unpublish_on < REQUEST_TIME) {
      $tids[] = $data->tid;
    }
  }
  foreach ($tids as $tid) {

    // Unpublish the term.
    taxonomy_tools_publisher_unpublish_term($tid);
  }
}

/**
 * Implements hook_permission().
 */
function taxonomy_tools_publisher_permission() {
  return array(
    'administer term schedule' => array(
      'title' => t('Administer term schedule'),
      'description' => t('User is able set scheduler times and change term status.'),
    ),
    'bypass taxonomy publisher' => array(
      'title' => t('Bypass Taxonomy Publisher settings'),
      'description' => t('User is able to bypass restrictions set by Taxonomy Publisher.'),
    ),
    'administer taxonomy publisher configuration' => array(
      'title' => t('Administer Taxonomy Publisher configuration'),
      'description' => t('User is able to access and use Taxonomy Publisher configuration page.'),
    ),
  );
}

/**
 * Checks the taxonomy term and it's ancestors for availability.
 *
 * @param string $tid
 *   A string containing taxonomy term ID.
 *
 * @return bool
 *   TRUE if taxonomy term is published and none of it's parents is unpublished,
 *   FALSE either if the taxonomy term itself or at least one of it's
 *   parents is unpublished.
 */
function taxonomy_tools_publisher_check_branch($tid) {

  // Get term status value from DB.
  $query = db_select('field_data_field_taxonomy_term_status', 'foo');
  $query
    ->addField('foo', 'field_taxonomy_term_status_value', 'term_status');
  $query
    ->condition(db_and()
    ->condition('foo.entity_id', $tid)
    ->condition('entity_type', 'taxonomy_term'));
  $status_result = $query
    ->execute()
    ->fetchField();

  // Term status is set to "Unpublished".
  if ($status_result !== FALSE && !$status_result) {
    $status = 0;
  }
  else {
    $query = db_select('taxonomy_term_hierarchy', 'foo');
    $query
      ->addField('foo', 'parent');
    $query
      ->condition('foo.tid', $tid);
    $parent_result = $query
      ->execute()
      ->fetchField();

    // If term has a parent it must also be checked for availability.
    if ($parent_result != 0) {
      $status = taxonomy_tools_publisher_check_branch($parent_result);
    }
    else {
      $status = 1;
    }
  }
  return $status;
}

/**
 * Implements hook_term_copy_alter().
 */
function taxonomy_tools_publisher_term_copy_alter(&$term) {

  // Only for terms that are from a vocabulary that uses Taxonomy Publisher.
  if (in_array($term->vocabulary_machine_name, array_filter(variable_get('taxonomy_tools_publisher_config', array())))) {

    // Set the status to "unpublished".
    $term->field_taxonomy_term_status[LANGUAGE_NONE][0]['value'] = TERM_NOT_PUBLISHED;

    // No scheduling.
    $term->field_taxonomy_term_publish_on[LANGUAGE_NONE] = array();
    $term->field_taxonomy_term_unpublish_on[LANGUAGE_NONE] = array();
  }
  else {

    // Remove Taxonomy Publisher fields if destination vocabulary does
    // not use them.
    if (isset($term->field_taxonomy_term_status)) {
      unset($term->field_taxonomy_term_status);
    }
    if (isset($term->field_taxonomy_term_publish_on)) {
      unset($term->field_taxonomy_term_publish_on);
    }
    if (isset($term->field_taxonomy_term_unpublish_on)) {
      unset($term->field_taxonomy_term_unpublish_on);
    }
  }
}

/**
 * Returns term reference fields.
 *
 * @param string $bundle
 *   Node type.
 */
function taxonomy_tools_publisher_reference_fields($bundle) {
  $fields = array();

  // Get term reference fields.
  $query = db_select('field_config', 'fc');
  $query
    ->addField('fc', 'field_name');
  $query
    ->addField('fc', 'data');
  $query
    ->condition('fc.deleted', 0);
  $query
    ->condition('fc.type', 'taxonomy_term_reference');
  $query
    ->join('field_config_instance', 'fci', 'fci.field_name = fc.field_name');
  $query
    ->condition('fci.entity_type', 'node');
  $query
    ->condition('fci.bundle', $bundle);
  $result = $query
    ->execute()
    ->fetchAll();
  $vocabularies = array_filter(variable_get('taxonomy_tools_publisher_config', array()));
  foreach ($result as $key => $field) {
    $data = unserialize($field->data);
    if (in_array($data['settings']['allowed_values'][0]['vocabulary'], $vocabularies)) {
      $fields[] = $field->field_name;
    }
  }
  return $fields;
}

/**
 * Implements hook_node_update().
 */
function taxonomy_tools_publisher_node_update($node) {
  $fields = taxonomy_tools_publisher_reference_fields($node->type);

  // Publish taxonomy terms that use this node.
  if (!empty($fields) && $node->status == 1 && variable_get('taxonomy_tools_publisher_automatic_publishing', 0) == 1) {
    foreach ($fields as $field) {
      $terms = $node->{$field}[LANGUAGE_NONE];
      foreach ($terms as $term) {
        taxonomy_tools_publisher_publish_term($term['tid']);
      }
    }
  }
}

/**
 * Implements hook_node_insert().
 */
function taxonomy_tools_publisher_node_insert($node) {
  $fields = taxonomy_tools_publisher_reference_fields($node->type);

  // Publish taxonomy terms that use this node.
  if (!empty($fields) && $node->status == 1 && variable_get('taxonomy_tools_publisher_automatic_publishing', 0) == 1) {
    foreach ($fields as $field) {
      $terms = $node->{$field}[LANGUAGE_NONE];
      foreach ($terms as $term) {
        taxonomy_tools_publisher_publish_term($term['tid']);
      }
    }
  }
}

/**
 * Publishes taxonomy term.
 *
 * @param int $tid
 *   Taxonomy term ID.
 */
function taxonomy_tools_publisher_publish_term($tid) {
  $term = taxonomy_term_load($tid);
  if ($term->field_taxonomy_term_status[LANGUAGE_NONE][0]['value'] == TERM_NOT_PUBLISHED) {

    // Set taxonomy term status to "Published".
    $term->field_taxonomy_term_status[LANGUAGE_NONE][0]['value'] = TERM_PUBLISHED;

    // Remove publish on time.
    if (!empty($term->field_taxonomy_term_publish_on)) {
      $term->field_taxonomy_term_publish_on = array();
    }
    taxonomy_term_save($term);

    // Allow other modules to act upon term publishing.
    module_invoke_all('taxonomy_tools_publisher_term_publish', $term);
  }
}

/**
 * Unpublishes taxonomy term.
 *
 * @param int $tid
 *   Taxonomy term ID.
 */
function taxonomy_tools_publisher_unpublish_term($tid) {
  $term = taxonomy_term_load($tid);
  if ($term->field_taxonomy_term_status[LANGUAGE_NONE][0]['value'] == TERM_PUBLISHED) {

    // Set taxonomy term status to "Unpublished".
    $term->field_taxonomy_term_status[LANGUAGE_NONE][0]['value'] = TERM_NOT_PUBLISHED;

    // Remove unpublish on time.
    if (!empty($term->field_taxonomy_term_publish_on)) {
      $term->field_taxonomy_term_unpublish_on = array();
    }
    taxonomy_term_save($term);

    // Allow other modules to act upon term unpublishing.
    module_invoke_all('taxonomy_tools_publisher_term_unpublish', $term);
  }
}

/**
 * Implements hook_preprocess_html().
 */
function taxonomy_tools_publisher_preprocess_html(&$variables) {
  if (arg(0) == 'taxonomy' && arg(1) == 'term' && is_numeric(arg(2))) {
    $term = taxonomy_term_load(arg(2));
    $vocabularies = array_filter(variable_get('taxonomy_tools_publisher_config', array()));
    if (in_array($term->vocabulary_machine_name, $vocabularies)) {

      // Add a html class to the body depending on term status.
      if (!empty($term->field_taxonomy_term_status) && $term->field_taxonomy_term_status[LANGUAGE_NONE][0]['value'] == TERM_NOT_PUBLISHED) {
        $variables['classes_array'][] = check_plain('term-unpublished');
      }
      else {
        $variables['classes_array'][] = check_plain('term-published');
      }
    }
  }
}

Functions

Namesort descending Description
taxonomy_tools_publisher_check_branch Checks the taxonomy term and it's ancestors for availability.
taxonomy_tools_publisher_cron Implements hook_cron().
taxonomy_tools_publisher_form_taxonomy_form_term_alter Implements hook_form_FORM_ID_alter().
taxonomy_tools_publisher_menu Implements hook_menu().
taxonomy_tools_publisher_node_insert Implements hook_node_insert().
taxonomy_tools_publisher_node_update Implements hook_node_update().
taxonomy_tools_publisher_permission Implements hook_permission().
taxonomy_tools_publisher_preprocess_html Implements hook_preprocess_html().
taxonomy_tools_publisher_publish Publishes scheduled taxonomy terms.
taxonomy_tools_publisher_publish_term Publishes taxonomy term.
taxonomy_tools_publisher_reference_fields Returns term reference fields.
taxonomy_tools_publisher_taxonomy_term_form_validate Validates the user input of Taxonomy Publisher fields.
taxonomy_tools_publisher_taxonomy_term_presave Implements hook_taxonomy_term_presave().
taxonomy_tools_publisher_term_copy_alter Implements hook_term_copy_alter().
taxonomy_tools_publisher_unpublish Unpublishes scheduled taxonomy terms.
taxonomy_tools_publisher_unpublish_term Unpublishes taxonomy term.

Constants

Namesort descending Description
TAXONOMY_PUBLISHER_MESSAGE_DATE_FORMAT Date format for Taxonomy Publisher messages.
TERM_NOT_PUBLISHED Taxonomy term is not published.
TERM_PUBLISHED Taxonomt term is published;