You are here

notifications_tags.module in Notifications 6

Subscriptions to taxonomy terms

File

notifications_tags/notifications_tags.module
View source
<?php

/**
 * @file
 * Subscriptions to taxonomy terms
 */

/**
 * Implementation of hook_menu_()
 */
function notifications_tags_menu() {
  $items['notifications_tags/autocomplete'] = array(
    'title' => 'Autocomplete taxonomy',
    'page callback' => 'notifications_tags_autocomplete',
    'access arguments' => array(
      'access content',
    ),
    'type' => MENU_CALLBACK,
  );

  // Hidden user account tab
  $items['user/%user/notifications/taxonomy'] = array(
    'type' => MENU_LOCAL_TASK,
    'access callback' => FALSE,
    'title' => t('Tags'),
    'page callback' => 'notifications_tags_user_page',
    'page arguments' => array(
      1,
    ),
    'weight' => 10,
  );
  return $items;
}

/**
 * Implementation of hook_perm()
 */
function notifications_tags_perm() {
  return array(
    'subscribe to taxonomy terms',
  );
}

/**
 * Implementation of hook_notifications().
 */
function notifications_tags_notifications($op, &$arg0, $arg1 = NULL, $arg2 = NULL) {
  switch ($op) {
    case 'names':
      $subs =& $arg0;
      if ($subs->event_type == 'node') {
        if (!empty($subs->fields['tid'])) {
          $term = taxonomy_get_term($subs->fields['tid']);
          $subs->names['term'] = t('Term: %name', array(
            '%name' => $term->name,
          ));
        }
      }
      break;
    case 'subscription types':
      $types['taxonomy'] = array(
        'event_type' => 'node',
        'title' => t('Tags'),
        'description' => t('Subscribe to content tagged with a given taxonomy term.'),
        'access' => 'subscribe to taxonomy terms',
        'fields' => array(
          'tid',
        ),
        'page callback' => 'notifications_tags_user_page',
        'user page' => 'user/%user/notifications/taxonomy',
      );
      return $types;
    case 'subscription fields':

      // Information about available fields for subscriptions
      $fields['tid'] = array(
        'name' => t('Taxonomy term'),
        'field' => 'tid',
        'type' => 'int',
        'autocomplete path' => 'notifications_tags/autocomplete/single',
        'format callback' => 'notifications_tags_term_name',
        'value callback' => 'notifications_tags_term_tid',
      );
      return $fields;
    case 'query':
      if ($arg0 == 'event' && $arg1 == 'node' && ($node = $arg2->node) || $arg0 == 'user' && $arg1 == 'node' && ($node = $arg2)) {
        if ($tids = notifications_tags_node_get_terms($node->nid)) {
          $query[]['fields']['tid'] = $tids;
          return $query;
        }
      }
      break;
  }
}

/**
 * Fields information, translate term tid to name
 */
function notifications_tags_term_name($tid, $html = FALSE) {
  if ($term = taxonomy_get_term($tid)) {
    return $html ? l($term->name, "taxonomy/term/{$tid}") : check_plain($term->name);
  }
}

/**
 * Fields information, translate term name to tid
 */
function notifications_tags_term_tid($name, $field = NULL) {
  if ($vocabs = notifications_tags_vocabularies()) {

    // Add vids and name to args
    $args = array_keys($vocabs);
    $args[] = $name;
    $tid = db_result(db_query_range(db_rewrite_sql("SELECT t.tid FROM {term_data} t WHERE t.vid IN (" . db_placeholders($vocabs) . ") AND LOWER(t.name) = LOWER('%s')", 't', 'tid'), $args, 0, 1));
    if ($tid) {
      return $tid;
    }
    elseif ($field) {
      form_set_error($field, t('Term name not found.'));
    }
  }
}

/**
 * Implementation of hook_form_alter().
 * 
 * Admin settings form. Omitted taxonomy vocabularies.
 */
function notifications_tags_form_alter(&$form, $form_state, $form_id) {
  if ($form_id == 'notifications_content_settings_form') {
    $vocabularies = taxonomy_get_vocabularies();
    foreach ($vocabularies as $vocabulary) {
      $select[$vocabulary->vid] = check_plain($vocabulary->name);
    }
    $form['tags'] = array(
      '#type' => 'fieldset',
      '#title' => t('Tag subscriptions'),
      '#collapsible' => TRUE,
      '#weight' => 0,
    );
    $form['tags']['notifications_tags_vocabularies'] = array(
      '#type' => 'checkboxes',
      '#title' => t('Allowed vocabularies'),
      '#default_value' => notifications_tags_vocabularies('vid'),
      '#options' => $select,
      '#description' => t('Select vocabularies to which subscriptions should be <em>allowed</em>.'),
      '#multiple' => TRUE,
    );
  }
}

/**
 * Returns a list of taxonomy subscriptions
 */
function notifications_tags_user_page($account = NULL) {
  global $user;
  module_load_include('inc', 'notifications_content', 'notifications_content.pages');
  if (is_null($account)) {
    $account = $user;
  }
  return drupal_get_form('notifications_tags_user_form', $account);
}

/**
 * Returns the taxonomy subscription form
 */
function notifications_tags_user_form($form_state, $account) {

  // query string for category subscriptions
  $vocabularies = notifications_tags_vocabularies();

  // Get subscriptions indexed by tid
  $subscriptions = array();
  $existing = notifications_get_subscriptions(array(
    'type' => 'taxonomy',
    'uid' => $account->uid,
  ), array(
    'tid' => NULL,
  ), TRUE);
  foreach ($existing as $subs) {
    $subscriptions[$subs->fields['tid']] = $subs;
  }

  // Complete defaults
  $defaults = array(
    'sid' => 0,
    'send_interval' => notifications_user_setting('send_interval', $account),
    'send_method' => notifications_user_setting('send_method', $account),
    'type' => 'taxonomy',
    'event_type' => 'node',
  );
  $form['defaults'] = array(
    '#type' => 'value',
    '#value' => $defaults,
  );
  $form['account'] = array(
    '#type' => 'value',
    '#value' => $account,
  );
  $form['current'] = array(
    '#type' => 'value',
    '#value' => $subscriptions,
  );
  $form['subscription_fields'] = array(
    '#type' => 'value',
    '#value' => array(),
  );

  //$subsrows['subform'][] = array('#value' => t('Current subscriptions:'));
  $form['subscriptions'] = array(
    '#tree' => TRUE,
  );

  // Hide send methods if only one
  $send_methods = _notifications_send_methods();
  $header = array(
    theme('table_select_header_cell'),
    t('Term'),
    t('Send interval'),
  );
  if (count($send_methods) > 1) {
    $header[] = t('Send method');
  }
  foreach ($vocabularies as $vid => $vocab) {

    // display vocabulary name and group terms together
    $form['subscriptions'][$vid] = array(
      '#type' => 'fieldset',
      '#title' => check_plain($vocab->name),
      '#tree' => TRUE,
      '#collapsible' => TRUE,
      '#collapsed' => FALSE,
      '#theme' => 'notifications_form_table',
      '#header' => $header,
      '#parents' => array(
        'subscriptions',
      ),
    );

    // @ TODO create mechanism to allow users to
    //        subscribe to all terms under this vocabulary
    $tree = taxonomy_get_tree($vocab->vid);
    $field = 'tid';
    foreach ($tree as $term) {
      $key = $term->tid;
      $rowdefaults = isset($subscriptions[$key]) ? (array) $subscriptions[$key] : array();
      $rowdefaults += $defaults;
      $form['subscriptions'][$vid]['checkbox'][$key] = array(
        '#type' => 'checkbox',
        '#default_value' => $rowdefaults['sid'],
      );
      $form['subscriptions'][$vid]['title'][$key] = array(
        '#value' => check_plain($term->name),
      );
      $form['subscriptions'][$vid]['send_interval'][$key] = array(
        '#type' => 'select',
        '#options' => _notifications_send_intervals(),
        '#default_value' => $rowdefaults['send_interval'],
      );
      if (count($send_methods) > 1) {
        $form['subscriptions'][$vid]['send_method'][$key] = array(
          '#type' => 'select',
          '#options' => _notifications_send_methods(),
          '#default_value' => $rowdefaults['send_method'],
        );
      }
      else {
        $form['subscriptions'][$vid]['send_method'][$key] = array(
          '#type' => 'value',
          '#value' => $rowdefaults['send_method'],
        );
      }

      // Pass on the fields for processing
      $form['subscription_fields']['#value'][$key] = array(
        $field => $key,
      );
    }
  }
  $form['submit'] = array(
    '#type' => 'submit',
    '#value' => t('Save'),
  );
  $form['#submit'][] = 'notifications_content_form_submit';
  return $form;
}

/**
 * Get list of allowed vocabularies
 * 
 * @param $field
 *   Optional field to retrieve as array value.
 *   If empty the whole vocalubary object will be returned.
 */
function notifications_tags_vocabularies($field = NULL) {
  if ($allowed = variable_get('notifications_tags_vocabularies', array())) {
    $allvocab = taxonomy_get_vocabularies();
    $vocabularies = array();
    foreach (array_filter($allowed) as $vid) {
      $vocabularies[$vid] = $allvocab[$vid];
    }
  }
  else {

    // They're disallowed by default
    $vocabularies = array();
  }
  if ($field) {
    $list = array();
    foreach ($vocabularies as $vid => $vocab) {
      $list[$vid] = $vocab->{$field};
    }
    return $list;
  }
  else {
    return $vocabularies;
  }
}

/**
 * Helper function to get latest node terms.
 * 
 * We cannot use the one from taxonomy module because it has static caching and we'll be sending
 * notifications right after the node has been updated
 */
function notifications_tags_node_get_terms($nid) {
  static $terms;
  if (!isset($terms[$nid])) {
    $result = db_query('SELECT tid FROM {term_node} WHERE nid = %d', $nid);
    $terms[$nid] = array();
    while ($term = db_fetch_object($result)) {
      $terms[$nid][] = $term->tid;
    }
  }
  return $terms[$nid];
}

/**
 * Helper function for term name autocompletion
 * 
 * It is similar to taxonomy_autocomplete but:
 * - Just searches terms in allowed vocabularies
 * - Has single/multiple switch in the path
 * 
 * @param $type
 *   'single' or 'multiple'
 */
function notifications_tags_autocomplete($type, $string = '') {
  $matches = array();
  if ($vocabs = notifications_tags_vocabularies()) {

    // If multiple, the user enters a comma-separated list of tags. We only autocomplete the last tag.
    if ($type == 'multiple') {
      $array = drupal_explode_tags($string);
    }
    else {
      $array = array(
        $string,
      );
    }

    // Fetch last tag
    $last_string = trim(array_pop($array));
    if ($last_string != '') {

      // Add vids and name to args
      $args = array_keys($vocabs);
      $args[] = $last_string;
      $result = db_query_range(db_rewrite_sql("SELECT t.tid, t.name FROM {term_data} t WHERE t.vid IN (" . db_placeholders($vocabs) . ") AND LOWER(t.name) LIKE LOWER('%%%s%%')", 't', 'tid'), $args, 0, 10);
      $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);
}

Functions

Namesort descending Description
notifications_tags_autocomplete Helper function for term name autocompletion
notifications_tags_form_alter Implementation of hook_form_alter().
notifications_tags_menu Implementation of hook_menu_()
notifications_tags_node_get_terms Helper function to get latest node terms.
notifications_tags_notifications Implementation of hook_notifications().
notifications_tags_perm Implementation of hook_perm()
notifications_tags_term_name Fields information, translate term tid to name
notifications_tags_term_tid Fields information, translate term name to tid
notifications_tags_user_form Returns the taxonomy subscription form
notifications_tags_user_page Returns a list of taxonomy subscriptions
notifications_tags_vocabularies Get list of allowed vocabularies