/**
 * Get fully configured and authenticated Twitter API client.
 * @return TwitterApiClient
 */
function twitter_api_client($id = null)
{
    static $clients = array();
    if (!isset($clients[$id])) {
        twitter_api_include('core');
        $clients[$id] = TwitterApiClient::create_instance(is_null($id));
    }
    return $clients[$id];
}
Beispiel #2
0
/**
 * Pull latest tweets with some caching of raw data.
 * @param string account whose tweets we're pulling
 * @param int number of tweets to get and display
 * @param bool whether to show retweets
 * @param bool whether to show at replies
 * @return array blocks of html expected by the widget
 */
function latest_tweets_render($screen_name, $count, $rts, $ats, $pop = 0)
{
    try {
        if (!function_exists('twitter_api_get')) {
            require_once dirname(__FILE__) . '/api/twitter-api.php';
            twitter_api_load_textdomain();
        }
        // caching full data set, not just twitter api caching
        // caching is disabled by default in debug mode, but still filtered.
        $cachettl = (int) apply_filters('latest_tweets_cache_seconds', WP_DEBUG ? 0 : 300);
        if ($cachettl) {
            $arguments = func_get_args();
            $cachekey = 'latest_tweets_' . implode('_', $arguments);
            if (!function_exists('_twitter_api_cache_get')) {
                twitter_api_include('core');
            }
            if ($rendered = _twitter_api_cache_get($cachekey)) {
                return $rendered;
            }
        }
        // Check configuration before use
        if (!twitter_api_configured()) {
            throw new Exception(__('Plugin not fully configured', 'twitter-api'));
        }
        // Build API params for "statuses/user_timeline" // https://dev.twitter.com/docs/api/1.1/get/statuses/user_timeline
        $trim_user = false;
        $include_rts = !empty($rts);
        $exclude_replies = empty($ats);
        $params = compact('exclude_replies', 'include_rts', 'trim_user', 'screen_name');
        // Stripping tweets means we may get less than $count tweets.
        // we'll keep going until we get the amount we need, but may as well get more each time.
        if ($exclude_replies || !$include_rts || $pop) {
            $params['count'] = 100;
        } else {
            $params['count'] = max($count, 2);
        }
        // pull tweets until we either have enough, or there are no more
        $tweets = array();
        while ($batch = twitter_api_get('statuses/user_timeline', $params)) {
            $max_id = null;
            foreach ($batch as $tweet) {
                if (isset($params['max_id']) && $tweet['id_str'] === $params['max_id']) {
                    // previous max included in results, even though docs say it won't be
                    continue;
                }
                $max_id = $tweet['id_str'];
                if (!$include_rts && preg_match('/^(?:RT|MT)[ :\\-]*@/i', $tweet['text'])) {
                    // skipping manual RT
                    continue;
                }
                if ($pop > $tweet['retweet_count'] + $tweet['favorite_count']) {
                    // skipping tweets not deemed popular enough
                    continue;
                }
                $tweets[] = $tweet;
            }
            if (isset($tweets[$count])) {
                $tweets = array_slice($tweets, 0, $count);
                break;
            }
            if (!$max_id) {
                // infinite loop would occur if user had only tweeted once, ever.
                break;
            }
            $params['max_id'] = $max_id;
        }
        // Fix Wordpress's broken timezone implementation
        $os_timezone = date_default_timezone_get() or $os_timezone = 'UTC';
        $wp_timezone = get_option('timezone_string') or $wp_timezone = $os_timezone;
        if ($os_timezone !== $wp_timezone) {
            date_default_timezone_set($wp_timezone);
        }
        // Let theme disable or override emoji rendering
        $emoji_callback = apply_filters('latest_tweets_emoji_callback', 'twitter_api_replace_emoji_callback');
        // render each tweet as a block of html for the widget list items
        $rendered = array();
        foreach ($tweets as $tweet) {
            extract($tweet);
            $handle = $user['screen_name'] or $handle = $screen_name;
            $link = esc_html('http://twitter.com/' . $handle . '/status/' . $id_str);
            // render nice datetime, unless theme overrides with filter
            $date = apply_filters('latest_tweets_render_date', $created_at);
            if ($date === $created_at) {
                function_exists('twitter_api_relative_date') or twitter_api_include('utils');
                $time = strtotime($created_at);
                $date = esc_html(twitter_api_relative_date($time));
                $date = '<time datetime="' . date_i18n('Y-m-d H:i:sO', $time) . '">' . $date . '</time>';
            }
            // handle original retweet text as RT may be truncated
            if ($include_rts && isset($retweeted_status) && preg_match('/^RT\\s+@[a-z0-9_]{1,15}[\\s:]+/i', $text, $prefix)) {
                $text = $prefix[0] . $retweeted_status['text'];
                unset($retweeted_status);
            }
            // render and linkify tweet, unless theme overrides with filter
            $html = apply_filters('latest_tweets_render_text', $text);
            if ($html === $text) {
                if (!function_exists('twitter_api_html')) {
                    twitter_api_include('utils');
                }
                // htmlify tweet, using entities if we can
                if (isset($entities) && is_array($entities)) {
                    $html = twitter_api_html_with_entities($text, $entities);
                    unset($entities);
                } else {
                    $html = twitter_api_html($text);
                }
                // render emoji, unless filtered out
                if ($emoji_callback) {
                    $html = twitter_api_replace_emoji($html, $emoji_callback);
                }
                // strip characters that will choke mysql cache.
                if ($cachettl && !TWITTER_CACHE_APC) {
                    $html = twitter_api_strip_quadruple_bytes($html);
                }
            }
            // piece together the whole tweet, allowing override
            $final = apply_filters('latest_tweets_render_tweet', $html, $date, $link, $tweet);
            if ($final === $html) {
                // SOFI SPECIFIC EDIT - INCLUDE TWEET ICON
                $final = '<p class="tweet-text"><a href="' . $link . '" target="_blank" class="tweeticn"></a>' . $html . '</p>' . '<p class="tweet-details"><a href="' . $link . '" target="_blank">' . $date . '</a></p>';
            }
            $rendered[] = $final;
        }
        // cache rendered tweets
        if ($cachettl) {
            _twitter_api_cache_set($cachekey, $rendered, $cachettl);
        }
        // put altered timezone back
        if ($os_timezone !== $wp_timezone) {
            date_default_timezone_set($os_timezone);
        }
        return $rendered;
    } catch (Exception $Ex) {
        return array('<p class="tweet-text"><strong>Error:</strong> ' . esc_html($Ex->getMessage()) . '</p>');
    }
}
<?php

/**
 * Unit test bootstrapper.
 * This is nothing close to an accurate simulation of WordPress environment, it's just for testing utils.
 */
function is_admin()
{
    return false;
}
function esc_html($text)
{
    return htmlspecialchars($text, ENT_COMPAT, 'UTF-8');
}
function esc_attr($text)
{
    return esc_html($text);
}
require __DIR__ . '/../twitter-api.php';
twitter_api_include('utils', 'core', 'unicode');