You are here

tweet.module in Tweet 7.4

Builds links to post pages to Twitter API sites.

File

tweet.module
View source
<?php

/**
 * @file
 *   Builds links to post pages to Twitter API sites.
 */

/**
 * Implements hook_help().
 */
function tweet_help($path, $arg) {
  $output = '';
  switch ($path) {
    case "admin/help#tweet":
      $output = '<p>' . t("This module builds links to post pages to twitter.") . '</p>';
      break;
  }
  return $output;
}

/**
 * Implements hook_node_view().
 */
function tweet_node_view($node, $view_mode) {
  $types = variable_get('tweet_types', _tweet_node_types());
  if ((in_array($node->type, $types) || empty($types)) && !_tweet_exclude($node->nid)) {
    if ($view_mode == 'full') {
      $link_type = variable_get('tweet_node', 'icon');
    }
    else {
      $link_type = variable_get('tweet_teaser', 'none');
    }
    if ($link_type != 'none') {
      $links = array();
      foreach (tweet_sites(TRUE) as $site => $info) {
        $links['tweet_' . $site] = _tweet_to_twitter($site, $link_type, '', $node->nid);
      }
      $node->content['links']['tweet'] = array(
        '#theme' => 'links',
        '#links' => $links,
        '#attributes' => array(
          'class' => array(
            'links',
            'inline',
          ),
        ),
      );
    }
  }
}

/**
 * Implements hook_menu().
 */
function tweet_menu() {
  $items = array();
  $items['admin/config/services/tweet'] = array(
    'title' => 'Tweet',
    'description' => 'Adjust certain display settings for Tweet.',
    'page callback' => 'drupal_get_form',
    'page arguments' => array(
      'tweet_admin',
    ),
    'access arguments' => array(
      'administer site configuration',
    ),
    'file' => 'tweet.admin.inc',
  );
  return $items;
}

/**
 * Implements hook_block_info().
 */
function tweet_block_info() {
  $block['tweet']['info'] = t('Tweet link');
  return $block;
}

/**
 * Implements hook_block_view().
 */
function tweet_block_view($delta) {
  if ($delta == 'tweet') {
    $block['subject'] = t('Tweet this');
    $links = array();
    foreach (tweet_sites(TRUE) as $site => $info) {
      $links[$site] = tweet_to_twitter($site);
    }
    $block['content'] = theme('item_list', array(
      'items' => $links,
    ));
    return $block;
  }
}

/**
 * Implements hook_tweet_sites().
 */
function tweet_tweet_sites() {
  $path = drupal_get_path('module', 'tweet');
  return array(
    'Twitter' => array(
      'path' => 'http://twitter.com/',
      'query_key' => 'status',
      'image' => variable_get('tweet_image', $path . '/twitter.png'),
    ),
    'Identi.ca' => array(
      'path' => 'http://identi.ca/notice/new',
      'query_key' => 'status_textarea',
      'image' => variable_get('tweet_identica_image', $path . '/identica.png'),
    ),
  );
}

/**
 * Builds a list of sites to which we can tweet.
 *
 * @param $enabled_only
 *   If TRUE, only enabled sites are returned. Otherwise, all defined sites are
 *   returned.
 * @param $reset
 *   Reset and rebuild the static cache.
 * @return
 *   An array of sites to which we can tweet with associated information.
 */
function tweet_sites($enabled_only = FALSE, $reset = FALSE) {
  static $sites = array();
  if ($reset || empty($sites)) {
    $sites = module_invoke_all('tweet_sites');
    drupal_alter('tweet_sites', $sites);
  }
  $allowed = $sites;
  if ($enabled_only) {
    foreach ($sites as $site => $info) {
      if (!in_array($site, variable_get('tweet_sites', array(
        'Twitter' => 'Twitter',
      )))) {
        unset($allowed[$site]);
      }
    }
  }
  return $allowed;
}

/**
 * Returns a link from _tweet_to_twitter().
 */
function tweet_to_twitter($site = 'Twitter', $type = '', $format = '', $nid = '') {
  if (!$type && variable_get('tweet_node', 'icon') == 'none') {
    $type = 'icon_text';
  }
  $array = _tweet_to_twitter($site, $type, $format, $nid);
  return l($array['title'], $array['href'], array(
    'attributes' => $array['attributes'],
    'query' => $array['query'],
    'absolute' => TRUE,
    'html' => $array['html'],
  ));
}

/**
 * Creates a link to post a URL and optionally title to twitter.  Uses the
 * current page by default.
 *
 * @param $site
 *   The site to which the generated Tweet link leads. Twitter by default.
 * @param $type
 *   Specifies what will show up in the link: the twitter icon, the twitter icon
 *   and text, or just text. Pass 'icon' to show just the icon, 'icon_text' to
 *   show the icon and text, and 'text' to show just the text. Required if
 *   display options for nodes are set to 'none' on the settings page.
 * @param $format
 *   A string representing the tweet text, optionally with the case-insensitive
 *   tokens [url], [title], and [node-tags]. If not passed, the format from the settings page
 *   will be used.
 * @param $nid
 *   The NID of the node for which the twitter link should be constructed, or
 *   the absolute URL of the page for which the twitter link should be
 *   constructed. If the URL given is not the current URL, and if $nid is not a
 *   NID, the title must be set manually (instead of using the [title] token) or
 *   it will be incorrect.
 * @return
 *   A themed link to post the specified or current page to twitter.
 */
function _tweet_to_twitter($site = 'Twitter', $type = '', $format = '', $nid = '') {
  $q = '';
  $node_tags = '';
  $teaser = '';
  if (!$format) {
    $format = variable_get('tweet_format', '[url] [title] [node-tags]');
  }
  $sites = tweet_sites();
  $site_info = $sites[$site];
  if (empty($nid) && arg(0) == 'node' && is_numeric(arg(1))) {
    $nid = arg(1);
  }
  if (is_numeric($nid)) {
    $q = url('node/' . $nid, array(
      'absolute' => TRUE,
    ));
    if (module_exists('taxonomy') && strpos($format, '[node-tags]') !== FALSE) {
      $node_tag_vocabs = variable_get('tweet_node_vocabs', array());
      $tags = array();
      foreach ($node_tag_vocabs as $vid => $enabled) {
        if ($enabled) {

          // In Drupal 6, we had taxonomy_node_get_terms_by_vocabulary().
          // That doesn't exist in Drupal 7, so it is ported below.
          $query = db_select('taxonomy_term_data', 't')
            ->addTag('node_access')
            ->fields('t', array(
            'tid',
            'vid',
            'name',
            'description',
            'format',
            'weight',
          ));
          $query
            ->innerJoin('taxonomy_index', 'r', 'r.tid = t.tid');
          $terms = $query
            ->condition('t.vid', $vid)
            ->condition('r.nid', $nid)
            ->orderBy('weight')
            ->execute()
            ->fetchAll();
          foreach ($terms as $term) {
            $tags[] = '#' . check_plain($term->name);
          }
        }
      }
      $node_tags = implode(' ', $tags);
    }
    if (strpos($format, '[node-teaser]') !== FALSE) {
      if (!isset($node)) {
        $node = node_load($nid);
      }

      // Don't execute PHP -- doing so can cause WSODs.
      $filters = filter_list_format($node->format);
      if (isset($filters['php/0']) && strpos($node->teaser, '<?') !== FALSE) {
        $teaser = '';
      }
      else {
        $teaser = html_entity_decode(filter_xss(check_markup($node->teaser, $node->format, FALSE), array()), ENT_QUOTES);
      }
    }
    $url = $q;
  }
  elseif (is_string($nid)) {
    $url = $nid;
    $q = $nid;
  }
  else {
    $url = url($_GET['q'], array(
      'absolute' => TRUE,
    ));
  }
  if (module_exists('shorten')) {
    $url = shorten_url($q);
  }
  $title = _tweet_get_title($nid);
  $tweet = _tweet_process($format, array(
    '[url]' => $url,
    '[title]' => $title,
    '[node-teaser]' => $teaser,
    '[node-tags]' => check_plain($node_tags),
  ));
  $path = $site_info['path'];
  $text = _tweet_text($site);
  $image_location = $site_info['image'];
  $image = theme('image', array(
    'path' => $image_location,
    'alt' => $text,
    'title' => $text,
  ));
  if (!$type) {

    // Note that $type can be 'none', in which case nothing shows up.
    $type = variable_get('tweet_node', 'icon');
  }
  if ($type == 'icon') {
    $show = $image;
  }
  elseif ($type == 'icon_text') {
    $show = t('!tweeticon !tweettext', array(
      '!tweeticon' => $image,
      '!tweettext' => $text,
    ));
  }
  elseif ($type == 'text') {
    $show = $text;
  }
  $attributes = array(
    'class' => 'tweet',
    'rel' => 'nofollow',
  );
  if (variable_get('tweet_new_window', 'target') == 'target') {
    $attributes['target'] = '_blank';
  }
  elseif (variable_get('tweet_new_window', 'target') == 'js') {
    $attributes['onclick'] = "window.open(this.href); return false;";
  }
  return array(
    'title' => $show,
    'href' => $path,
    'attributes' => $attributes,
    'query' => array(
      $site_info['query_key'] => $tweet,
    ),
    'html' => TRUE,
  );
}

/**
 * Determines what will be in the tweet itself.
 *
 * @param $format
 *   A string containing the text of the tweet before it gets processed.
 * @param $tokens
 *   An associative array where keys represent text that will be replaced by
 *   their value in $format. Because only 140 characters are allowed, it is
 *   possible that values will be truncated or not included. Tokens are
 *   assumed to be ordered by importance (most important first).
 * @return
 *   The URL-ready tweet text.
 */
function _tweet_process($format = '', $tokens = array()) {
  if (!$format) {
    $format = variable_get('tweet_format', '[url] [title] [node-tags]');
  }

  // The major downside of the way we're counting characters here is that we
  // can't guarantee a minimum number of characters for a given token. However
  // in order to do that, the process would need to be much more complex. It
  // just seems like overkill.
  $len = 140 - drupal_strlen(str_replace(array_keys($tokens), array(), $format));
  foreach ($tokens as $search => $replace) {

    // In order to include text for a token, we want at least 3 letters and an ellipsis.
    if ($len < 5 || strpos($format, $search) === FALSE) {
      $replace = '';
    }
    elseif (drupal_strlen($replace) > $len) {

      // "\xE2\x80\xA6" is the UTF8 character sequence for the ellipsis, which must be enclosed in double quotes.
      
      $replace = drupal_substr($replace, 0, $len - 1) . "…";
    }
    $len -= drupal_strlen($replace);
    $format = str_replace($search, $replace, $format);
  }

  // Collapse whitespace (multiple spaces can occur if any token is empty).
  if (strpos($format, '  ') !== FALSE) {
    $format = preg_replace('/\\s\\s+/', ' ', $format);
  }

  // Drupal does not automatically urlencode links.

  //$format = drupal_encode_path($format);

  // The #, &, and / characters get double-encoded by drupal_urlencode,
  // but they must appear single-encoded for Twitter to recognize them.
  // We replace urlencoded spaces with plus signs here for clarity.

  //$format = str_replace(array('%2523', '%2526', '%252F', '%20'), array('%23', '%26', '%2F', '+'), $format);
  return $format;
}

/**
 * Returns the title of the node for which the NID was passed or the current
 * page. Note that there is no good way to get the page title for a page that is
 * not the current page. We assume the title is the same as the title of the
 * node if a node is being viewed, but this is often not the case when certain
 * modules are being used. In this case, it is recommended that you manually
 * pass the title to tweet_to_twitter().
 *
 * @param $nid
 *   The NID of the node for which to return the title.  If not passed, uses the
 *   current page.
 * @return
 *   The title of the node for the NID passed or the title of the current page.
 */
function _tweet_get_title($nid = '') {
  if (is_numeric($nid)) {
    $node = node_load($nid);
    $title = $node->title;
  }
  else {
    $title = drupal_get_title();
  }
  return $title;
}

/**
 * Excludes certain Node IDs from displaying links.
 *
 * @param $nid
 *   The NID to check for exclusion.
 * @return
 *   TRUE if the node should be excluded, or FALSE if it should not.
 */
function _tweet_exclude($nid) {
  $exclude = explode(',', variable_get('tweet_exclude', ''));
  $excludes = array();
  foreach ($exclude as $check) {
    $excludes[] = trim($check);
  }
  if (!empty($excludes)) {
    if (in_array($nid, $excludes)) {
      return TRUE;
    }
  }
  return FALSE;
}

/**
 * Helper function to provide node types in the format array(TYPE => TYPE).
 */
function _tweet_node_types() {
  $a = array_keys(node_type_get_types());
  $return = drupal_map_assoc($a);
  return $return;
}

/**
 * Helper function to figure out what text to display with a Tweet link.
 */
function _tweet_text($site) {
  return str_replace('[site]', check_plain($site), variable_get('tweet_text', t('Post to [site]')));
}

/**
 * Implements hook_views_api().
 */
function tweet_views_api() {
  return array(
    'api' => '2',
    'path' => drupal_get_path('module', 'tweet'),
  );
}

Functions

Namesort descending Description
tweet_block_info Implements hook_block_info().
tweet_block_view Implements hook_block_view().
tweet_help Implements hook_help().
tweet_menu Implements hook_menu().
tweet_node_view Implements hook_node_view().
tweet_sites Builds a list of sites to which we can tweet.
tweet_to_twitter Returns a link from _tweet_to_twitter().
tweet_tweet_sites Implements hook_tweet_sites().
tweet_views_api Implements hook_views_api().
_tweet_exclude Excludes certain Node IDs from displaying links.
_tweet_get_title Returns the title of the node for which the NID was passed or the current page. Note that there is no good way to get the page title for a page that is not the current page. We assume the title is the same as the title of the node if a node is being…
_tweet_node_types Helper function to provide node types in the format array(TYPE => TYPE).
_tweet_process Determines what will be in the tweet itself.
_tweet_text Helper function to figure out what text to display with a Tweet link.
_tweet_to_twitter Creates a link to post a URL and optionally title to twitter. Uses the current page by default.