You are here

hashtags.module in Hashtags 6

File

hashtags.module
View source
<?php

// $Id$

/**
 * Implementation of hook_form_alter().
 */
function hashtags_form_alter(&$form, $form_state, $form_id) {
  $vid = variable_get('hashtags_vocabulary', '');
  $voc = taxonomy_vocabulary_load($vid);

  // Hide hashtag textfield from node edit page;
  // check only for hashtag content types.
  if (isset($form['type']) && isset($form['#node']) && in_array($form['type']['#value'], $voc->nodes) && $form['type']['#value'] . '_node_form' == $form_id) {
    drupal_add_js("if (Drupal.jsEnabled) { \$(document).ready(function() { \$('div#edit-taxonomy-tags-{$vid}-wrapper').css('display', 'none'); }); }", 'inline');
  }
  elseif (isset($form['vid']) && $form['vid']['#value'] == $vid) {

    // Hide critical options from hashtag vocabulary.
    if ($form_id == 'taxonomy_form_vocabulary') {
      $form['help_hashtags_vocab'] = array(
        '#value' => t('This is the designated hashtags vocabulary. Some of the normal vocabulary options have been removed.'),
        '#weight' => -1,
      );
      $form['identification']['description']['#access'] = FALSE;
      $form['identification']['help']['#access'] = FALSE;
      $form['content_types']['nodes']['#required'] = TRUE;
      $form['settings']['#access'] = FALSE;
      unset($form['delete']);
    }
    elseif ($form_id == 'taxonomy_form_term') {
      $form['advanced']['parent']['#access'] = FALSE;
    }
  }
}

/**
 * Implementation of hook_nodeapi().
 */
function hashtags_nodeapi(&$node, $op, $teaser, $page) {
  $vid = variable_get('hashtags_vocabulary', '');
  $voc = taxonomy_vocabulary_load($vid);
  if (!in_array($node->type, $voc->nodes)) {
    return;
  }
  switch ($op) {
    case 'presave':
      $vid = variable_get('hashtags_vocabulary', '');

      // Parse body to get all hashtags (#some_word) and pass as commas separated string.
      $hashtags_string = hashtags_get_tags($node->body);
      $node->taxonomy['tags'][$vid] = $hashtags_string;
      break;
  }
}

/**
 * Implementation of hook_filter().
 */
function hashtags_filter($op, $delta = 0, $format = -1, $text = '') {
  switch ($op) {
    case 'list':
      return array(
        0 => t('Hashtags filter'),
      );
    case 'description':
      return t('Turn #words into links which lead to taxonomy terms');
    case 'settings':

      // nothing
      break;
    case 'no cache':
      return FALSE;
    case 'prepare':
      return $text;
    case 'process':
      $hashtags_string = hashtags_get_tags($text);
      if (empty($hashtags_string)) {
        return $text;
      }
      $hashtags_tids = hashtags_get_terms_by_names($hashtags_string);

      // create a class to pass parameters and have replace logic
      $replace_parameter = new hashtags_replace_parameter();
      $replace_parameter->hashtags_tids = $hashtags_tids;

      // 1) 2+ character after #
      // 2) Don't start with or use only numbers (0-9) (#123abc, #123 etc)
      // 3) Letters - digits work correct (#abc123, #conference2013)
      // 4) No Special Characters “!, $, %, ^, &, *, +, .”
      // 5) No Spaces
      // 6) May use an underscore. Hyphens and dashes will not work.
      // 7) <p>#hashtag</p> - is valid
      // 8) <a href="#hashtag">Link</p> - is not valid
      // Bug when hashtag resides at the begining of the string
      $pattern = "/([\\s>]+?)(#[[:alpha:]][[:alnum:]_]*[^<\\s[:punct:]])/iu";
      $text = preg_replace_callback($pattern, array(
        &$replace_parameter,
        'replace',
      ), $text);
      return $text;
    case 'default':
      return $text;
  }
}

/*
 * Create and return commas separated string from hashtag words (#some_word)
 */
function hashtags_get_tags($text, $capture_position = FALSE) {
  if ($capture_position) {

    // save position to avoid replacing hashtags inside links (<a hre="#ball">)
    $flag = PREG_OFFSET_CAPTURE;
  }
  else {
    $flag = PREG_PATTERN_ORDER;
  }
  $tags_list = array();

  // 1) 2+ character after #
  // 2) Don't start with or use only numbers (0-9) (#123abc, #123 etc)
  // 3) Letters - digits work correct (#abc123, #conference2013)
  // 4) No Special Characters “!, $, %, ^, &, *, +, .”
  // 5) No Spaces
  // 6) May use an underscore. Hyphens and dashes will not work.
  // 7) <p>#hashtag</p> - is valid
  // 8) <a href="#hashtag">Link</p> - is not valid
  // Bug when hashtag resides at the begining of the string - wrap text in <htest> tags for quick solution
  $pattern = "/[\\s>]+?(#[[:alpha:]][[:alnum:]_]*[^<\\s[:punct:]])/iu";

  // add <htest> to process first #hastag - string beginning
  preg_match_all($pattern, '<htest>' . $text . '<htest>', $tags_list, $flag);

  // no hashtags has been found
  if (isset($tags_list[0]) && !sizeof($tags_list[0])) {
    return '';
  }

  // save position
  if ($capture_position) {
    foreach ($tags_list[1] as $key => $data) {

      // array[position] = hashtag
      $result[$data[1]] = strtolower($data[0]);
    }
  }
  else {

    // turn tags into lowercase
    foreach ($tags_list[1] as $key => $tag) {
      $tags_list[1][$key] = '"' . strtolower($tag) . '"';
    }
    $result = implode(',', $tags_list[1]);
  }
  return $result;
}

/*
 * Add Hashtags filter to system input formats: Filter HTML and Full HTML;
 */
function hashtags_add_filter() {
  $added_status = array();
  $filtered_html_format = 1;

  // check if hashtag filter has been added to 'Filtered HTML' input formtat
  $is_hashtag_filter_exists = db_result(db_query('SELECT COUNT(*) FROM {filters} WHERE format = %d AND module = "%s" AND delta = 0', $filtered_html_format, 'hashtags'));
  if (!$is_hashtag_filter_exists) {
    $max_filter_weight = db_result(db_query('SELECT MAX(weight) FROM {filters} WHERE format = %d', $filtered_html_format));
    db_query("INSERT INTO {filters} (format, module, delta, weight) VALUES (%d, '%s', %d, %d)", $filtered_html_format, 'hashtags', 0, $max_filter_weight + 1);
    $added_status[] = $filtered_html_format;
    drupal_set_message(t('Hashtags module: Hashtags filter has been added to "Filter HTML" input format'));
  }
  $full_html_format = 2;

  // admin can remove Full HTML format from database - need to check...
  $is_format_exists = db_result(db_query('SELECT COUNT(*) FROM {filter_formats} WHERE format = %d', $full_html_format));
  if ($is_format_exists) {
    $is_hashtag_filter_exists = db_result(db_query('SELECT COUNT(*) FROM {filters} WHERE format = %d AND module = "%s" AND delta = 0', $full_html_format, 'hashtags'));
    if (!$is_hashtag_filter_exists) {
      $max_filter_weight = db_result(db_query('SELECT MAX(weight) FROM {filters} WHERE format = %d', $full_html_format));
      db_query("INSERT INTO {filters} (format, module, delta, weight) VALUES (%d, '%s', %d, %d)", $full_html_format, 'hashtags', 0, $max_filter_weight + 1);
      $added_status[] = $full_html_format;
      drupal_set_message(t('Hashtags module: Hashtags filter has been added to "Full HTML" input format'));
    }
  }
  if (sizeof($added_status)) {
    return TRUE;
  }
  return FALSE;
}

/*
 * Remove Hashtags filter out of all input formats
 */
function hashtags_remove_filter() {
  $module = 'hashtags';
  db_query("DELETE FROM {filters} WHERE module = '%s'", $module);
  drupal_set_message(t('Hashtags module: Hashtags filter has been removed from all input format'));
}

/*
 * Returns an array of hashtags by names
 * Array['term_name'] = term_id;
 */
function hashtags_get_terms_by_names($names) {
  $terms = array();
  $vid = variable_get('hashtags_vocabulary', '');
  $sql = "SELECT td.name, td.tid FROM {term_data} td   \n  WHERE lower(td.name) IN (" . $names . ") AND td.vid = %d";
  $result = db_query($sql, $vid);
  while ($term = db_fetch_object($result)) {
    $terms[$term->name] = $term->tid;
  }
  return $terms;
}

/*
 * Returns an array of hashtags for $nid node
 * Array['term_name'] = term_id;
 */
function hashtags_node_get_terms($nid) {
  $terms = array();
  $vid = variable_get('hashtags_vocabulary', '');
  $sql = "SELECT lower(td.name), td.tid FROM {term_data} td \n  INNER JOIN {term_node} tn ON td.tid = tn.tid \n  WHERE tn.nid = %d AND td.vid = %d";
  $result = db_query($sql, $nid, $vid);
  while ($term = db_fetch_object($result)) {
    $terms[$term->name] = $term->tid;
  }
  return $terms;
}

/* 
 * Help class to pass paramters to callback function within preg_replace_callback 
 */
class hashtags_replace_parameter {
  function replace($matches) {
    if (isset($this->hashtags_tids)) {
      $hashtags_tids = $this->hashtags_tids;
    }
    $first_delimeter = $matches[1];
    $hashtag_name = $matches[2];
    $hashtag_tid = $hashtags_tids[strtolower($hashtag_name)];
    $hashtag_link = l($hashtag_name, 'taxonomy/term/' . $hashtag_tid, array(
      'attributes' => array(
        'class' => 'hashtag',
      ),
    ));
    return $first_delimeter . $hashtag_link;
  }

}