You are here

twitter.module in Twitter 7.6

Provides API integration with the Twitter microblogging service.

File

twitter.module
View source
<?php

/**
 * @file
 * Provides API integration with the Twitter microblogging service.
 */
define('TWITTER_HOST', 'https://twitter.com');
define('TWITTER_API', 'https://api.twitter.com');
define('TWITTER_SEARCH', 'https://search.twitter.com');
define('TWITTER_TINYURL', 'http://tinyurl.com');
define('TWITTER_OAUTH_CALLBACK_URL', 'twitter/oauth');

/**
 * Implements hook_help().
 */
function twitter_help($path, $arg) {
  switch ($path) {
    case 'admin/help#twitter':
      $output = '';
      $output .= '<p>' . t('This module provides API integration with the Twitter microblogging service.') . '</p>';
      $output .= '<p>' . t('For more information, please visit the official <a href="@url">project page</a> on Drupal.org.', array(
        '@url' => 'https://www.drupal.org/project/twitter',
      )) . '</p>';
      return $output;
  }
}

/**
 * Implements hook_entity_info().
 */
function twitter_entity_info() {
  return array(
    'twitter_status' => array(
      'label' => t('Twitter Status'),
      'module' => 'twitter',
      'entity class' => 'TwitterStatus',
      'controller class' => 'EntityAPIController',
      'base table' => 'twitter',
      'entity keys' => array(
        'id' => 'twitter_id',
      ),
      'label callback' => 'entity_class_label',
      'uri callback' => 'entity_class_uri',
    ),
    'twitter_account' => array(
      'label' => t('Twitter Account'),
      'module' => 'twitter',
      'entity class' => 'TwitterAccount',
      'controller class' => 'EntityAPIController',
      'base table' => 'twitter_account',
      'entity keys' => array(
        'id' => 'twitter_uid',
        'label' => 'screen_name',
      ),
      'uri callback' => 'entity_class_uri',
    ),
  );
}

/**
 * Implements hook_menu().
 */
function twitter_menu() {
  $items[variable_get('twitter_oauth_callback_url', TWITTER_OAUTH_CALLBACK_URL)] = array(
    'title' => 'Twitter OAuth',
    // Allow all requests to this URL so that OAuth may work correctly.
    'access callback' => TRUE,
    'page callback' => 'drupal_get_form',
    'page arguments' => array(
      'twitter_oauth_callback',
    ),
    'type' => MENU_CALLBACK,
    'file' => 'twitter.pages.inc',
  );
  $items['admin/config/services/twitter'] = array(
    'title' => 'Twitter',
    'description' => 'Twitter accounts and settings.',
    'page callback' => 'twitter_user_settings',
    'access arguments' => array(
      'administer twitter accounts',
    ),
    'file' => 'twitter.pages.inc',
  );
  $items['admin/config/services/twitter/default'] = array(
    'title' => 'Twitter',
    'type' => MENU_DEFAULT_LOCAL_TASK,
  );
  $items['admin/config/services/twitter/settings'] = array(
    'title' => 'Settings',
    'description' => 'Twitter settings.',
    'page callback' => 'drupal_get_form',
    'page arguments' => array(
      'twitter_admin_form',
    ),
    'access arguments' => array(
      'administer twitter',
    ),
    'file' => 'twitter.pages.inc',
    'type' => MENU_LOCAL_TASK,
  );
  $items['user/%user/edit/twitter'] = array(
    'title' => 'Twitter accounts',
    'page callback' => 'twitter_user_settings',
    'page arguments' => array(
      1,
    ),
    'access callback' => 'twitter_account_access',
    'access arguments' => array(
      1,
    ),
    'weight' => 10,
    'file' => 'twitter.pages.inc',
    'type' => MENU_LOCAL_TASK,
  );
  return $items;
}

/**
 * Implements hook_permission().
 */
function twitter_permission() {
  return array(
    'administer twitter' => array(
      'title' => t('Administer Twitter configuration'),
    ),
    'add twitter accounts' => array(
      'title' => t('Add Twitter accounts'),
    ),
    'add authenticated twitter accounts' => array(
      'title' => t('Add authenticated Twitter accounts'),
    ),
    'administer twitter accounts' => array(
      'title' => t('Administer Twitter accounts'),
    ),
  );
}

/**
 * Access callback for the Twitter accounts page.
 *
 * @param object $account
 *   The user account that 'owns' this Twitter accounts page.
 *
 * @return
 *   Boolean TRUE if the current user has access.
 */
function twitter_account_access($account) {
  global $user;

  // First off, verify that the current user has one of the required
  // permissions and is viewing their own user account.
  if ($user->uid == $account->uid && (user_access('add twitter accounts') || user_access('add authenticated twitter accounts'))) {
    return TRUE;
  }

  // Otherwise, verify that they have the 'administer users' permission.
  if (user_access('administer users')) {
    return TRUE;
  }

  // If neither of the above permission checks are approved, they do not have
  // permission to access this page.
  return FALSE;
}

/**
 * Implements hook_theme().
 */
function twitter_theme() {
  return array(
    'twitter_account_list_form' => array(
      'render element' => 'form',
    ),
    'twitter_status' => array(
      'variables' => array(
        'status' => NULL,
        'author' => NULL,
        'reply' => NULL,
        'retweet' => NULL,
        'favorite' => NULL,
      ),
      'template' => 'twitter_status',
      'path' => drupal_get_path('module', 'twitter'),
    ),
    'twitter_user_accounts' => array(
      'variables' => array(
        'accounts' => array(),
      ),
    ),
  );
}

/**
 * Initialize variables for theme twitter_status.
 */
function template_preprocess_twitter_status(&$variables) {
  if (isset($variables['status'])) {
    $status =& $variables['status'];

    // Format the timestamp.
    $time_diff = REQUEST_TIME - $status->created_time;
    $status->time_ago = t('%time ago', array(
      '%time' => format_interval($time_diff, 2),
    ));

    // Format the message.
    $status->text = twitter_filter_message($status->text);
  }
}

/**
 * Default callback for theme('twitter_user_accounts');
 *
 * Renders a list of Twitter accounts for the user profile page.
 */
function theme_twitter_user_accounts($variables) {
  $accounts = $variables['accounts'];
  $items = array();
  module_load_include('inc', 'twitter');
  foreach ($accounts as $twitter_account) {

    // If we have tweets for this Twitter account, link to the View. If not, link to Twitter.
    if (module_exists('views') && twitter_tweets($twitter_account->screen_name)) {
      $items[] = l('@' . $twitter_account->screen_name, 'tweets/' . $twitter_account->screen_name);
    }
    else {
      $items[] = _twitter_user_profile($twitter_account->screen_name);
    }
  }
  return theme('item_list', array(
    'items' => $items,
  ));
}

/**
 * Very lightweight helper function to generate a TinyURL for a given post.
 */
function twitter_shorten_url($url) {
  if (module_exists('shorten')) {
    return shorten_url($url);
  }
  else {
    $response = drupal_http_request(variable_get('twitter_tinyurl', TWITTER_TINYURL) . "/api-create.php?url=" . $url);
    if ($response->code == 200) {
      return $response->data;
    }
    else {
      return $url;
    }
  }
}

/**
 * Implements hook_cron().
 *
 * Imports new Twitter statuses for site users, and deletes expired tweets.
 */
function twitter_cron() {
  if (!variable_get('twitter_import', TRUE)) {
    watchdog('twitter', 'The Twitter module is configured to not download tweets right now.');
    return;
  }
  module_load_include('inc', 'twitter');

  // Verify that there's at least one authenticated account that can be used to
  // do API calls.
  $twitter = twitter_connect(NULL, TRUE, TRUE);
  if (empty($twitter)) {
    watchdog('twitter', 'Unable to find an authenticated account to do API calls from.');
    return FALSE;
  }
  watchdog('twitter', 'Starting to download tweets.');

  // Pull up a list of Twitter accounts that are flagged for updating, sorted
  // by how long it's been since we last updated them. This ensures that the
  // most out-of-date accounts get updated first.
  $query = new EntityFieldQuery();
  $query
    ->entityCondition('entity_type', 'twitter_account')
    ->propertyCondition('uid', 0, '>')
    ->propertyCondition('import', 1)
    ->propertyOrderBy('last_refresh')
    ->range(0, 20);
  $result = $query
    ->execute();
  $ids = !empty($result['twitter_account']) ? array_keys($result['twitter_account']) : array();
  if (count($ids)) {
    $twitter_accounts = entity_load('twitter_account', $ids);

    // Iterate over Twitter accounts and fetch tweets.
    try {
      foreach ($twitter_accounts as $twitter_account) {

        // Fetch tweets for this account.
        twitter_fetch_user_timeline($twitter_account->twitter_uid);

        // Optionally fetch mentions.
        if ($twitter_account
          ->is_auth() && $twitter_account->mentions) {
          twitter_fetch_mentions_timeline($twitter_account->twitter_uid);
        }

        // Mark the time this account was updated.
        $twitter_account->last_refresh = REQUEST_TIME;
        twitter_account_save($twitter_account);
      }
    } catch (TwitterException $e) {

      // The exception has already been logged so we do not need to do anything
      // here apart from catching it.
      watchdog('twitter', 'There was a problem loading tweets during cron.');
    }
  }

  // Nuke old statuses.
  if ($age = variable_get('twitter_expire', 0)) {
    $query = new EntityFieldQuery();
    $query
      ->entityCondition('entity_type', 'twitter_status')
      ->propertyCondition('created_time', REQUEST_TIME - $age, '<');
    $result = $query
      ->execute();
    entity_delete_multiple('twitter_status', array_keys($result['twitter_status']));
  }
  watchdog('twitter', 'Finished downloading tweets.');
}

/**
 * Implements hook_filter_info()
 */
function twitter_filter_info() {
  $filters['twitter_username'] = array(
    'title' => t('Twitter @username converter'),
    'description' => t('Converts Twitter-style @usernames into links to Twitter account pages.'),
    'process callback' => '_twitter_filter_username',
    'tips callback' => '_twitter_filter_tip_username',
  );
  $filters['twitter_hashtag'] = array(
    'title' => t('Twitter #hashtag converter'),
    'description' => t('Converts Twitter-style #hashtags into links to twitter.com. Note: this converts all text prefixed by a "#" symbol into a hashtag link, so it can cause problems with other text.'),
    'process callback' => '_twitter_filter_hashtag',
    'tips callback' => '_twitter_filter_tip_hashtag',
  );
  $filters['twitter_links'] = array(
    'title' => t('Twitter link converter'),
    'description' => t('Makes links in Twitter messages to be opened in new windows and adds rel="nofollow" so these links do not penalize SEO.'),
    'process callback' => '_twitter_filter_link',
    'tips callback' => '_twitter_filter_tip_link',
  );
  $filters['twitter_embed'] = array(
    'title' => t('Embed Tweets'),
    'description' => t('Converts URLs for Twitter status updates into embedded Tweets. Should be sorted after the "Limit allowed HTML tags" filter, if used.'),
    'process callback' => '_twitter_filter_embed_tweet',
    'tips callback' => '_twitter_filter_tip_embed_tweet',
  );
  return $filters;
}

/**
 * Filter tips callback function for Twitter usernames.
 */
function _twitter_filter_tip_username($filter, $format, $long = FALSE) {
  return t('Twitter-style @usernames are linked to their Twitter account pages.');
}

/**
 * Filter tips callback function for Twitter hashtags.
 */
function _twitter_filter_tip_hashtag($format, $long = FALSE) {
  return t('Twitter-style #hashtags are linked to !url.', array(
    '!url' => '<a href="https://search.twitter.com/">search.twitter.com</a>',
  ));
}

/**
 * Filter tips callback function for Twitter links.
 */
function _twitter_filter_tip_link($filter, $format, $long = FALSE) {
  return t('Twitter message links are opened in new windows and rel="nofollow" is added.');
}

/**
 * Filter tips callback function for Embedded Tweets.
 */
function _twitter_filter_tip_embed_tweet($filter, $format, $long = FALSE) {
  return t('Links to Twitter status updates are converted to Embedded Tweets.');
}

/**
 * Callback for twitter @username converter.
 *
 * @param string $text
 *   The text to be filtered.
 * @param mixed $filter
 *   The filter configuration.
 *
 * @return string
 *   The processed string.
 */
function _twitter_filter_username($text, $filter = NULL) {
  $prefix = '@';
  $destination = variable_get('twitter_host', TWITTER_HOST) . '/';
  return _twitter_filter_text($text, $prefix, $destination);
}

/**
 * Callback for twitter #hashtag converter.
 *
 * @param string $text
 *   The text to be filtered.
 * @param mixed $filter
 *   The filter configuration.
 *
 * @return string
 *   The processed string.
 */
function _twitter_filter_hashtag($text, $filter = NULL) {
  $prefix = '#';
  $destination = variable_get('twitter_search', TWITTER_SEARCH) . '/search?q=%23';
  return _twitter_filter_text($text, $prefix, $destination);
}

/**
 * Callback for Twitter link converter.
 *
 * @param string $text
 *   The text to be filtered.
 * @param mixed $filter
 *   The filter configuration.
 *
 * @return string
 *   The processed string.
 */
function _twitter_filter_link($text, $filter = NULL) {
  return str_replace('<a ', '<a target="_blank" rel="nofollow" class="twitter-timeline-link" ', $text);
}

/**
 * This helper function converts Twitter-style @usernames and #hashtags into
 * actual links.
 *
 * @param string $text
 *   The text to be filtered.
 * @param string $prefix
 *   The string to search for.
 * @param string $destination
 *   The URL that the links will point to.
 * @param string $class
 *   An optional class to insert into the link.
 *
 * @return string
 *   The processed string.
 */
function _twitter_filter_text($text, $prefix, $destination, $class = '') {
  $match = '/(?<!\\w)' . preg_quote($prefix, '/') . '(\\w+)/ui';
  if (!empty($class)) {
    $class = " class=\"{$class}\"";
  }
  $replacement = '<a href="' . $destination . '$1"' . $class . '>' . $prefix . '$1</a>';
  return preg_replace($match, $replacement, $text);
}

/**
 * Convert embedded URLs, hashtags and usernames in a tweet to links.
 *
 * @param string $message
 *   The tweet's text.
 * @param bool $usernames
 *   Whether or not to convert usernames to links. Defaults to TRUE.
 * @param bool $hashtags
 *   Whether or not to convert hashtags to links. Defaults to TRUE.
 * @param bool $attributes
 *   Whether or not to add extra attributes to links. Defaults to TRUE.
 * @param bool $urls
 *   Whether or not to convert other URLs to links. Defaults to TRUE.
 *
 * @return string
 *   The filtered tweet text.
 */
function twitter_filter_message($message, $usernames = TRUE, $hashtags = TRUE, $attributes = TRUE, $urls = TRUE) {

  // Link usernames with their profiles.
  if ($usernames) {
    $message = _twitter_filter_username($message);
  }

  // Link hashtags.
  if ($hashtags) {
    $message = _twitter_filter_hashtag($message);
  }

  // Add extra attributes to links.
  if ($attributes) {
    $message = _twitter_filter_link($message);
  }

  // Standard URLs.
  if ($urls) {
    $filter = new stdClass();
    $filter->settings = array(
      'filter_url_length' => 496,
    );
    $message = _filter_url($message, $filter);
  }

  // Avoid XSS within the message.
  return filter_xss($message);
}

/**
 * Callback for Embedded Tweets.
 */
function _twitter_filter_embed_tweet($text, $filter) {
  module_load_include('inc', 'twitter');

  // Tags to skip and not recurse into.
  $ignore_tags = 'a|script|style|code|pre';

  // Split at all tags; ensures that no tags or attributes are processed.
  $chunks = preg_split('/(<.+?>)/is', $text, -1, PREG_SPLIT_DELIM_CAPTURE);

  // PHP ensures that the array consists of alternating delimiters and
  // literals, and begins and ends with a literal (inserting NULL as required).
  // Therefore, the first chunk is always text:
  $chunk_type = 'text';

  // If a tag of $ignore_tags is found, it is stored in $open_tag and only
  // removed when the closing tag is found. Until the closing tag is found, no
  // replacements are made.
  $open_tag = '';

  // Loop through all of the text chunks.
  foreach ($chunks as $i => $chunk) {
    if ($chunk_type == 'text') {

      // Only process this text if there are no unclosed $ignore_tags.
      if ($open_tag == '') {

        // Check for links to Tweets to replace with embed code.
        $tweets = array();
        preg_match_all('/https?:\\/\\/(www\\.)?twitter.com\\/.+?\\/status(es)?\\/(.*)/i', $chunks[$i], $tweets, PREG_SET_ORDER);
        foreach ($tweets as $tweet) {
          $url = $tweet[0];
          $id = $tweet[3];
          $embed = twitter_statuses_oembed($id);
          $chunks[$i] = str_replace($url, $embed['html'], $chunks[$i]);
        }
      }

      // Text chunk is done, so next chunk must be a tag.
      $chunk_type = 'tag';
    }
    else {

      // Only process this tag if there are no unclosed $ignore_tags.
      if ($open_tag == '') {

        // Check whether this tag is contained in $ignore_tags.
        if (preg_match("`<({$ignore_tags})(?:\\s|>)`i", $chunks[$i], $matches)) {
          $open_tag = $matches[1];
        }
      }
      else {
        if (preg_match("`<\\/{$open_tag}>`i", $chunks[$i], $matches)) {
          $open_tag = '';
        }
      }

      // Tag chunk is done, so next chunk must be text.
      $chunk_type = 'text';
    }
  }
  return implode($chunks);
}

/**
 * Implements hook_views_api().
 */
function twitter_views_api() {
  return array(
    'api' => 2,
  );
}

/**
 * Implements hook_user_load().
 */
function twitter_user_load($accounts) {
  foreach ($accounts as $twitter_uid => $account) {
    $accounts[$twitter_uid]->twitter_accounts = module_invoke_all('twitter_accounts', $account);
  }
}

/**
 * Implements hook_twitter_accounts().
 *
 * @return array
 *   All Twitter accounts for this user; the anonymous user will return an
 *   empty array.
 */
function twitter_twitter_accounts($account) {
  if ($account->uid == 0) {
    return array();
  }
  $query = new EntityFieldQuery();
  $query
    ->entityCondition('entity_type', 'twitter_account')
    ->propertyCondition('uid', $account->uid);
  $result = $query
    ->execute();
  $ids = !empty($result['twitter_account']) ? array_keys($result['twitter_account']) : array();
  $twitter_accounts = entity_load('twitter_account', $ids);
  return $twitter_accounts;
}

/**
 * Implements hook_user_delete().
 *
 * Removes user's Twitter accounts and tweets
 */
function twitter_user_delete($account) {
  $twitter_accounts = twitter_twitter_accounts($account);
  entity_delete_multiple('twitter_account', array_keys($twitter_accounts));
}

/**
 * Implements hook_user_view_alter()
 *
 * Adds Twitter account information to the user profile.
 */
function twitter_user_view_alter(&$build) {
  $user = $build['#account'];
  if (!empty($user->twitter_accounts)) {
    $build['twitter'] = array(
      '#type' => 'user_profile_item',
      '#title' => t('Twitter accounts'),
      '#markup' => theme('twitter_user_accounts', array(
        'accounts' => $user->twitter_accounts,
      )),
      '#weight' => 10,
    );
  }
}

/**
 * Checks if the Twitter Application keys are set.
 *
 * @return
 *   boolean TRUE if both the Twitter Application key and secret are set.
 */
function twitter_api_keys() {
  $key = variable_get('twitter_consumer_key');
  $secret = variable_get('twitter_consumer_secret');
  return !(empty($key) && empty($secret));
}

/**
 * Helper to build a Twitter profile URL
 */
function _twitter_user_profile($screen_name) {
  return l('@' . $screen_name, TWITTER_HOST . '/' . $screen_name);
}

/**
 * Helper to build a Twitter status URL.
 *
 * @param object $status
 *   A TwitterStatus object.
 */
function _twitter_status_url($status) {
  if ($status) {
    return TWITTER_HOST . '/' . $status->user->screen_name . '/status/' . $status->id;
  }
}

/**
 * Class for containing an individual twitter status.
 */
class TwitterStatus extends Entity {

  /**
   * @var created_at
   */
  public $created_at;
  public $id;
  public $text;
  public $source;
  public $truncated;
  public $favorited;
  public $in_reply_to_status_id;
  public $in_reply_to_user_id;
  public $in_reply_to_screen_name;
  public $user;
  public $retweeted_status;
  public $retweet_count;

  /**
   * Constructor for TwitterStatus
   */
  public function __construct($values = array()) {
    if (isset($values['user'])) {
      $this->user = new TwitterAccount($values['user']);
      unset($values['user']);
    }

    // Load full retweeted_status (original tweet) if retweet detected.
    if (isset($values['retweeted_status'])) {
      $this->retweeted_status = new TwitterStatus($values['retweeted_status']);
    }
    parent::__construct($values, 'twitter_status');
  }

  /**
   * {@inheritdoc}
   */
  protected function defaultLabel() {
    $label = t('No label defined for this tweet.');
    if (isset($this->text)) {
      $text = truncate_utf8($this->text, 140, TRUE, TRUE);
      if (isset($this->screen_name)) {
        $screen_name = t('Tweet by @screen_name', array(
          '@screen_name' => $this->screen_name,
        ));
      }
      if (isset($this->created_time)) {
        $created_time = t('on @created_time', array(
          '@created_time' => format_date($this->created_time),
        ));
      }
      $label = $text;
      if (!empty($screen_name)) {
        if (!empty($created_time)) {
          $label = $screen_name . ' ' . $created_time . ': ' . $text;
        }
        else {
          $label = $screen_name . ': ' . $text;
        }
      }
    }
    elseif (isset($this->screen_name)) {
      $label = t('Tweet by @screen_name.', array(
        '@screen_name' => $this->screen_name,
      ));
    }

    // Add in the translated specified label property.
    return $label;
  }

}

/**
 * Class to define the structure of a Twitter account.
 */
class TwitterAccount extends Entity {

  /**
   * Constructor
   */
  public function __construct($values = array()) {

    // Prepare values to match twitter_account table fields.
    if (!empty($values['id'])) {
      $values['twitter_uid'] = $values['id'];
      unset($values['id']);
    }
    if (!empty($values['created_at']) && ($created_time = strtotime($values['created_at']))) {
      $values['created_time'] = $created_time;
    }
    $values['utc_offset'] = isset($values['utc_offset']) ? $values['utc_offset'] : 0;
    if (isset($values['status'])) {
      $this->status = new TwitterStatus($values['status']);
      unset($values['status']);
    }
    parent::__construct($values, 'twitter_account');
  }

  /**
   * Returns an array with the authentication tokens.
   *
   * @return
   *   array with the oauth token key and secret.
   */
  public function get_auth() {
    return array(
      'oauth_token' => $this->oauth_token,
      'oauth_token_secret' => $this->oauth_token_secret,
    );
  }

  /**
   * Sets the authentication tokens to a user.
   *
   * @param array $values
   *   Array with 'oauth_token' and 'oauth_token_secret' keys.
   */
  public function set_auth($values) {
    $this->oauth_token = isset($values['oauth_token']) ? $values['oauth_token'] : NULL;
    $this->oauth_token_secret = isset($values['oauth_token_secret']) ? $values['oauth_token_secret'] : NULL;
  }

  /**
   * Checks whether the account is authenticated or not.
   *
   * @return
   *   boolean TRUE when the account is authenticated.
   */
  public function is_auth() {
    return !empty($this->oauth_token) && !empty($this->oauth_token_secret);
  }

}

Functions

Namesort descending Description
template_preprocess_twitter_status Initialize variables for theme twitter_status.
theme_twitter_user_accounts Default callback for theme('twitter_user_accounts');
twitter_account_access Access callback for the Twitter accounts page.
twitter_api_keys Checks if the Twitter Application keys are set.
twitter_cron Implements hook_cron().
twitter_entity_info Implements hook_entity_info().
twitter_filter_info Implements hook_filter_info()
twitter_filter_message Convert embedded URLs, hashtags and usernames in a tweet to links.
twitter_help Implements hook_help().
twitter_menu Implements hook_menu().
twitter_permission Implements hook_permission().
twitter_shorten_url Very lightweight helper function to generate a TinyURL for a given post.
twitter_theme Implements hook_theme().
twitter_twitter_accounts Implements hook_twitter_accounts().
twitter_user_delete Implements hook_user_delete().
twitter_user_load Implements hook_user_load().
twitter_user_view_alter Implements hook_user_view_alter()
twitter_views_api Implements hook_views_api().
_twitter_filter_embed_tweet Callback for Embedded Tweets.
_twitter_filter_hashtag Callback for twitter #hashtag converter.
_twitter_filter_link Callback for Twitter link converter.
_twitter_filter_text This helper function converts Twitter-style @usernames and #hashtags into actual links.
_twitter_filter_tip_embed_tweet Filter tips callback function for Embedded Tweets.
_twitter_filter_tip_hashtag Filter tips callback function for Twitter hashtags.
_twitter_filter_tip_link Filter tips callback function for Twitter links.
_twitter_filter_tip_username Filter tips callback function for Twitter usernames.
_twitter_filter_username Callback for twitter @username converter.
_twitter_status_url Helper to build a Twitter status URL.
_twitter_user_profile Helper to build a Twitter profile URL

Constants

Namesort descending Description
TWITTER_API
TWITTER_HOST @file Provides API integration with the Twitter microblogging service.
TWITTER_OAUTH_CALLBACK_URL
TWITTER_SEARCH
TWITTER_TINYURL

Classes

Namesort descending Description
TwitterAccount Class to define the structure of a Twitter account.
TwitterStatus Class for containing an individual twitter status.