Making WordPress.org


Ignore:
Timestamp:
01/08/2015 06:29:55 PM (10 years ago)
Author:
iandunn
Message:

Central Theme: Replace sessions on the homepage with latest tweets.

Props mj12982 for the design

File:
1 edited

Legend:

Unmodified
Added
Removed
  • sites/trunk/wordcamp.org/public_html/wp-content/themes/wordcamp-central-2012/functions.php

    r1085 r1105  
    3636        add_action( 'init', array( __CLASS__, 'process_forms' ) );
    3737        add_action( 'wp_enqueue_scripts', array( __CLASS__, 'enqueue_scripts' ) );
     38        add_action( 'wp_ajax_get_latest_wordcamp_tweets', array( __CLASS__, 'get_latest_tweets' ) );
     39        add_action( 'wp_ajax_nopriv_get_latest_wordcamp_tweets', array( __CLASS__, 'get_latest_tweets' ) );
    3840
    3941        add_filter( 'excerpt_more', array( __CLASS__, 'excerpt_more' ), 11 );
     
    181183    static function enqueue_scripts() {
    182184        wp_enqueue_style( 'central', get_stylesheet_uri(), array(), 3 );
    183         wp_enqueue_script( 'wordcamp-central', get_stylesheet_directory_uri() . '/js/central.js', array(), '20140909', true );
     185        wp_enqueue_script( 'wordcamp-central', get_stylesheet_directory_uri() . '/js/central.js', array( 'jquery', 'underscore' ), 1, true );
     186
     187        wp_localize_script( 'wordcamp-central', 'wordcampCentralOptions', array( 'ajaxURL' => admin_url( 'admin-ajax.php' ) ) );
    184188
    185189        /* We add some JavaScript to pages with the comment form
     
    425429    public static function can_subscribe() {
    426430        return class_exists( 'Jetpack_Subscriptions' ) && is_callable( array( 'Jetpack_Subscriptions', 'subscribe' ) );
     431    }
     432
     433    /**
     434     * Fetch the latest tweets from the @WordCamp account
     435     *
     436     * This is an AJAX callback returning JSON-formatted data.
     437     *
     438     * We're manually expiring/refreshing the transient to ensure that we only ever update it when we have a
     439     * valid response from the API. If there is a problem retrieving new data from the API, then we want to
     440     * continue displaying the valid cached data until we can successfully retrieve new data. The data is still
     441     * stored in a transient instead of an option, though, so that it can be cached in memory.
     442     *
     443     * Under certain unlikely conditions, this could cause an API rate limit violation. If the data is expired
     444     * and we can connect to the API at the network level, but then the request fails at the application level
     445     * (invalid credentials, etc), then we'll be hitting the API every time this function is called. If that
     446     * does ever happen, it could be fixed by setting the timestamp of the last attempt in a transient and only
     447     * issuing another attempt if ~2 minutes have passed.
     448     */
     449    public static function get_latest_tweets() {
     450        $transient_key = 'wcc_latest_tweets';
     451        $tweets        = get_transient( $transient_key );
     452        $expired       = $tweets['last_update'] < strtotime( 'now - 15 minutes' );
     453
     454        if ( ! $tweets || $expired ) {
     455            $response = wp_remote_get(
     456                'https://api.twitter.com/1.1/statuses/user_timeline.json?count=6&trim_user=true&exclude_replies=true&include_rts=false&screen_name=wordcamp',
     457                array(
     458                    'headers' => array( 'Authorization' => 'Bearer ' . TWITTER_BEARER_TOKEN_WORDCAMP_CENTRAL ),
     459                )
     460            );
     461
     462            if ( ! is_wp_error( $response ) ) {
     463                $tweets['tweets'] = json_decode( wp_remote_retrieve_body( $response ) );
     464
     465                /*
     466                 * Remove all but the first 3 tweets
     467                 *
     468                 * The Twitter API includes retweets in the `count` parameter, even if include_rts=false is passed,
     469                 * so we have to request more tweets than we actually want and then cut it down here.
     470                 */
     471                if ( $tweets['tweets'] ) {
     472                    $tweets['tweets']      = array_slice( $tweets['tweets'], 0, 3 );
     473                    $tweets['tweets']      = self::sanitize_format_tweets( $tweets['tweets'] );
     474                    $tweets['last_update'] = time();
     475
     476                    set_transient( $transient_key, $tweets );
     477                }
     478            }
     479        }
     480
     481        wp_send_json_success( $tweets );
     482    }
     483
     484    /**
     485     * Sanitize and format the tweet objects
     486     *
     487     * Whitelist the fields to cut down on how much data we're storing/transmitting, but also to force
     488     * future devs to manually enable/sanitize any new fields that are used, which avoids the risk of
     489     * accidentally using an unsafe value.
     490     *
     491     * @param array $tweets
     492     *
     493     * @return array
     494     */
     495    protected static function sanitize_format_tweets( $tweets ) {
     496        $whitelisted_fields = array( 'id_str' => '', 'text' => '', 'created_at' => '' );
     497
     498        foreach ( $tweets as & $tweet ) {
     499            $tweet           = (object) shortcode_atts( $whitelisted_fields, $tweet );
     500            $tweet->id_str   = sanitize_text_field( $tweet->id_str );
     501            $tweet->text     = wp_kses( $tweet->text, wp_kses_allowed_html( 'data' ), array( 'http', 'https', 'mailto' ) );
     502            $tweet->text     = make_clickable( $tweet->text );
     503            $tweet->text     = self::link_hashtags_and_usernames( $tweet->text );
     504            $tweet->time_ago = human_time_diff( strtotime( $tweet->created_at ) );
     505        }
     506
     507        return $tweets;
     508    }
     509
     510    /**
     511     * Convert usernames and hashtags to links
     512     *
     513     * Based on Tagregator's TGGRSourceTwitter::link_hashtags_and_usernames().
     514     *
     515     * @param string $text
     516     *
     517     * @return string
     518     */
     519    protected static function link_hashtags_and_usernames( $content ) {
     520        $content = preg_replace( '/@(\w+)/',       '<a href="https://twitter.com/\\1"          class="wc-tweets-username">@\\1</a>', $content );
     521        $content = preg_replace( '/(?<!&)#(\w+)/', '<a href="https://twitter.com/search?q=\\1" class="wc-tweets-tag"     >#\\1</a>', $content );
     522
     523        return $content;
    427524    }
    428525
Note: See TracChangeset for help on using the changeset viewer.