Making WordPress.org

Ticket #400: 400.diff

File 400.diff, 16.1 KB (added by iandunn, 9 years ago)
  • bootstrap.php

     
    5656        require_once( dirname( __FILE__ ) . '/classes/tggr-source-instagram.php' );
    5757        require_once( dirname( __FILE__ ) . '/classes/tggr-source-flickr.php' );
    5858        require_once( dirname( __FILE__ ) . '/classes/tggr-source-google.php' );
     59        require_once( dirname( __FILE__ ) . '/classes/tggr-source-facebook.php' );
    5960}
    6061
    6162/*
  • classes/tagregator.php

     
    3636                                'TGGRSourceInstagram'     => TGGRSourceInstagram::get_instance(),
    3737                                'TGGRSourceFlickr'        => TGGRSourceFlickr::get_instance(),
    3838                                'TGGRSourceGoogle'        => TGGRSourceGoogle::get_instance(),
     39                                'TGGRSourceFacebook'      => TGGRSourceFacebook::get_instance(),
    3940                        ) );
    4041                }
    4142
  • classes/tggr-source-facebook.php

     
     1<?php
     2
     3if ( $_SERVER['SCRIPT_FILENAME'] == __FILE__ )
     4        die( 'Access denied.' );
     5
     6if ( ! class_exists( 'TGGRSourceFacebook' ) ) {
     7        /**
     8         * Creates a custom post type and associated taxonomies
     9         * @package Tagregator
     10         */
     11        class TGGRSourceFacebook extends TGGRMediaSource {
     12                protected static $readable_properties  = array( 'view_folder' );
     13                protected static $writeable_properties = array();
     14                protected $setting_names, $default_settings, $view_folder;
     15
     16                const POST_TYPE_NAME_SINGULAR = 'Facebook Activity';
     17                const POST_TYPE_NAME_PLURAL   = 'Facebook Activities';
     18                const POST_TYPE_SLUG          = 'tggr-facebook';
     19                const SETTINGS_TITLE          = 'Facebook';
     20                const SETTINGS_PREFIX         = 'tggr_facebook_';
     21                const API_URL                 = 'https://www.api.facebook.com'; // It's important to use HTTPS for security
     22
     23                /**
     24                 * Constructor
     25                 * @mvc Controller
     26                 */
     27                protected function __construct() {
     28                        $this->view_folder   = dirname( __DIR__ ) . '/views/'. str_replace( '.php', '', basename( __FILE__ ) );
     29                        $this->setting_names = array( 'Access Token', 'Highlighted Accounts' );
     30
     31                        foreach ( $this->setting_names as $key ) {
     32                                $this->default_settings[ strtolower( str_replace( ' ', '_', $key ) ) ] = '';
     33                        }
     34                        $this->default_settings[ '_newest_activity_date' ] = 0;
     35
     36                        $this->register_hook_callbacks();
     37                }
     38
     39                /**
     40                 * Prepares site to use the plugin during activation
     41                 * @mvc Controller
     42                 *
     43                 * @param bool $network_wide
     44                 */
     45                public function activate( $network_wide ) {
     46                        $this->init();
     47                }
     48
     49                /**
     50                 * Rolls back activation procedures when de-activating the plugin
     51                 * @mvc Controller
     52                 */
     53                public function deactivate() {}
     54
     55                /**
     56                 * Register callbacks for actions and filters
     57                 * @mvc Controller
     58                 */
     59                public function register_hook_callbacks() {
     60                        add_action( 'init',                                       array( $this, 'init' ) );
     61                        add_action( 'admin_init',                                 array( $this, 'register_settings' ) );
     62                        add_filter( 'excerpt_length',                             __CLASS__ . '::get_excerpt_length' );
     63
     64                        add_filter( Tagregator::PREFIX . 'default_settings',      __CLASS__ . '::register_default_settings' );
     65                }
     66
     67                /**
     68                 * Initializes variables
     69                 * @mvc Controller
     70                 */
     71                public function init() {
     72                        self::register_post_type(
     73                                self::POST_TYPE_SLUG,
     74                                $this->get_post_type_params(
     75                                        self::POST_TYPE_SLUG,
     76                                        self::POST_TYPE_NAME_SINGULAR,
     77                                        self::POST_TYPE_NAME_PLURAL
     78                                )
     79                        );
     80                        self::create_post_author();   // It should already exist from the first time this class was instantiated, but we need to make sure it still exists now
     81                        self::get_post_author_user_id();
     82                }
     83
     84                /**
     85                 * Executes the logic of upgrading from specific older versions of the plugin to the current version
     86                 * @mvc Model
     87                 *
     88                 * @param string $db_version
     89                 */
     90                public function upgrade( $db_version = 0 ) {}
     91
     92                /**
     93                 * Validates submitted setting values before they get saved to the database.
     94                 * Invalid data will be overwritten with defaults.
     95                 * @mvc Model
     96                 *
     97                 * @param array $new_settings
     98                 * @return array
     99                 */
     100                public function validate_settings( $new_settings ) {
     101                        $new_settings = shortcode_atts( $this->default_settings, $new_settings, TGGRSettings::SETTING_SLUG );
     102
     103                        foreach ( $new_settings as $setting => $value ) {
     104                                switch ( $setting ) {
     105                                        case '_newest_activity_date':
     106                                                $new_settings[ $setting ] = absint( $value );
     107                                                break;
     108                                        default:
     109                                                $new_settings[ $setting ] = $this->default_settings[ $setting ];
     110                                                if ( is_string( $value ) ) {
     111                                                        $new_settings[ $setting ] = sanitize_text_field( $value );
     112                                                }
     113                                                break;
     114                                }
     115                        }
     116
     117                        return $new_settings;
     118                }
     119
     120                /**
     121                 * Fetches new items from an external sources and saves them as posts in the local database
     122                 * @mvc Controller
     123                 *
     124                 * @param string $hashtag
     125                 */
     126                public function import_new_items( $hashtag ) {
     127                        $activities = self::get_new_activities(
     128                                TGGRSettings::get_instance()->settings[ __CLASS__ ]['api_key'],
     129                                $hashtag,
     130                                TGGRSettings::get_instance()->settings[ __CLASS__ ]['_newest_activity_date']
     131                        );
     132
     133                        $this->import_new_posts( $this->convert_items_to_posts( $activities, $hashtag ) );
     134                        self::update_newest_activity_date( $hashtag );
     135                }
     136
     137                /**
     138                 * Retrieves activities containing the given hashtag that were posted since the last import
     139                 * @mvc Model
     140                 *
     141                 * @param string $api_key
     142                 * @param string $hashtag
     143                 * @param string $last_updated_activities The timestamp of the most recent item that is already saved in the database
     144                 * @return mixed string|false
     145                 */
     146                protected static function get_new_activities( $api_key, $hashtag, $last_updated_activities ) {
     147                        $response = $activities = false;
     148
     149                        if ( $api_key && $hashtag ) {
     150                                $url = sprintf(
     151                                        '%s/v1/activities?query=%s&key=%s',
     152                                        self::API_URL,
     153                                        urlencode( $hashtag ),
     154                                        urlencode( $api_key )
     155                                );
     156
     157                                $response = wp_remote_get( $url );
     158                                $body     = json_decode( wp_remote_retrieve_body( $response ) );
     159
     160                                if ( isset( $body->updated ) && strtotime( $body->updated ) > $last_updated_activities && ! empty( $body->items ) ) {
     161                                        $activities = $body->items;
     162                                }
     163                        }
     164
     165                        self::log( __METHOD__, 'Results', compact( 'api_key', 'hashtag', 'last_updated_activities', 'response' ) );
     166
     167                        return $activities;
     168                }
     169
     170                /**
     171                 * Converts data from external source into a post/postmeta format so it can be saved in the local database
     172                 * @mvc Model
     173                 *
     174                 * @param array $items
     175                 * @param string $term
     176                 * @return array
     177                 */
     178                public function convert_items_to_posts( $items, $term ) {
     179                        $posts = array();
     180
     181                        if ( $items ) {
     182                                foreach ( $items as $item ) {
     183                                        $post_timestamp_gmt   = strtotime( $item->published );
     184                                        $post_timestamp_local = self::convert_gmt_timestamp_to_local( $post_timestamp_gmt );
     185                                       
     186                                        $post = array(
     187                                                'post_author'   => TGGRMediaSource::$post_author_id,
     188                                                'post_content'  => wp_kses( $item->object->content, wp_kses_allowed_html( 'data' ), array( 'http', 'https', 'mailto' ) ),
     189                                                'post_date'     => date( 'Y-m-d H:i:s', $post_timestamp_local ),
     190                                                'post_date_gmt' => date( 'Y-m-d H:i:s', $post_timestamp_gmt ),
     191                                                'post_status'   => 'publish',
     192                                                'post_title'    => sanitize_text_field( $item->title ),
     193                                                'post_type'     => self::POST_TYPE_SLUG,
     194                                        );
     195
     196                                        $post_meta = array(
     197                                                'source_id'        => sanitize_text_field( $item->id ),
     198                                                'post_permalink'   => esc_url_raw( $item->url ),
     199                                                'author_id'        => sanitize_text_field( $item->actor->id ),
     200                                                'author_name'      => sanitize_text_field( $item->actor->displayName ),
     201                                                'author_url'       => esc_url( $item->actor->url ),
     202                                                'author_image_url' => esc_url( $item->actor->image->url ),
     203                                                'media'            => array(
     204                                                        array(
     205                                                                'small_url' => isset( $item->object->attachments[0]->image ) ? esc_url_raw( $item->object->attachments[0]->image->url ) : false,
     206                                                                'large_url' => isset( $item->object->attachments[0]->fullImage ) ? esc_url_raw( $item->object->attachments[0]->fullImage->url ) : false,
     207                                                                'type'      => 'image',
     208                                                        ),
     209                                                ),
     210                                        );
     211
     212                                        $posts[] = array(
     213                                                'post'       => $post,
     214                                                'post_meta'  => $post_meta,
     215                                                'term_name'  => $term,
     216                                        );
     217                                }
     218                        }
     219
     220                        return $posts;
     221                }
     222
     223                /**
     224                 * Updates the _newest_activity_date setting with the timestamp of the most recent
     225                 * @mvc Model
     226                 *
     227                 * @param string $hashtag
     228                 */
     229                protected static function update_newest_activity_date( $hashtag ) {
     230                        $latest_post = self::get_latest_hashtagged_post( self::POST_TYPE_SLUG, $hashtag );
     231                       
     232                        if ( isset( $latest_post->ID ) ) {
     233                                $settings = TGGRSettings::get_instance()->settings;
     234                                $settings[ __CLASS__ ]['_newest_activity_date'] = strtotime( $latest_post->post_date_gmt . ' GMT' );
     235                                TGGRSettings::get_instance()->settings = $settings;
     236                        }
     237                }
     238
     239                /**
     240                 * Gathers the data that the media-item view will need
     241                 * @mvc Model
     242                 *
     243                 * @param WP_Post $post
     244                 *
     245                 * @return array
     246                 */
     247                public function get_item_view_data( $post ) {
     248                        $postmeta = get_post_custom( $post->ID );
     249                        $necessary_data = array(
     250                                'source_id'        => $postmeta['source_id'][0],
     251                                'post_permalink'   => $postmeta['post_permalink'][0],
     252                                'author_name'      => $postmeta['author_name'][0],
     253                                'author_url'       => $postmeta['author_url'][0],
     254                                'author_image_url' => $postmeta['author_image_url'][0],
     255                                'media'            => isset( $postmeta['media'][0] ) ? maybe_unserialize( $postmeta['media'][0] ) : array(),
     256                                'logo_url'         => plugins_url( 'images/source-logos/facebook.png', __DIR__ ),
     257                                'css_classes'      => self::get_css_classes( $post->ID, $postmeta['author_name'][0] ),
     258                                'show_excerpt'     => self::show_excerpt( $post ),
     259                        );
     260
     261                        return $necessary_data;
     262                }
     263        } // end TGGRSourceFacebook
     264}
  • images/source-logos/facebook.png

    Property changes on: classes/tggr-source-facebook.php
    ___________________________________________________________________
    Added: svn:executable
    ## -0,0 +1 ##
    +*
    \ No newline at end of property
    Cannot display: file marked as a binary type.
    svn:mime-type = image/png
  • readme.txt

    Property changes on: images/source-logos/facebook.png
    ___________________________________________________________________
    Added: svn:mime-type
    ## -0,0 +1 ##
    +image/png
    \ No newline at end of property
    Added: svn:executable
    ## -0,0 +1 ##
    +*
    \ No newline at end of property
     
    11=== Tagregator ===
    22Contributors:      wordpressdotorg, iandunn, shaunandrews, ryelle, melchoyce
    33Donate link:       http://wordpressfoundation.org
    4 Tags:              hashtag, social media, aggregation, stream, twitter, instagram, flickr, google+, google plus
     4Tags:              hashtag, social media, aggregation, stream, twitter, facebook, instagram, flickr, google+, google plus
    55Requires at least: 3.9
    66Tested up to:      4.2
    77Stable tag:        0.6
     
    1616
    1717= Included Social Media Sources: =
    1818* Twitter
     19* Facebook
    1920* Instagram
    2021* Flickr
    2122* Google+
     
    99100
    100101== Changelog ==
    101102
     103= v0.7 (todo) =
     104* [NEW] Add a Facebook media source (props [prateek312](https://profiles.wordpress.org/prateek312)).
     105
    102106= v0.6 (2014-11-10) =
    103107* [NEW] Switch back to Masonry layout, with several improvements (props [ryelle](https://profiles.wordpress.org/ryelle), [melchoyce](https://profiles.wordpress.org/melchoyce)).
    104108* [NEW] Added settings field for highlighted accounts, which get an extra CSS class so they can be styled differently than normal posts (props [ryelle](https://profiles.wordpress.org/ryelle)).
     
    142146
    143147== Upgrade Notice ==
    144148
     149= 0.7 =
     150Version 0.7 adds support for Facebook.
     151
    145152= 0.6 =
    146153Version 0.6 returns to a Masonry layout.
    147154
     
    158165Version 0.2 displayed images attached to tweets and ignores retweets.
    159166
    160167= 0.1 =
    161 Initial release.
    162  No newline at end of file
     168Initial release.
  • views/tggr-source-facebook/page-settings-fields.php

     
     1<input
     2        type="text"
     3        id="<?php echo esc_attr( $class::SETTINGS_PREFIX . $setting ); ?>"
     4        name="<?php echo esc_attr( Tagregator::PREFIX ); ?>settings[<?php echo esc_attr( $class ); ?>][<?php echo esc_attr( $setting ); ?>] ); ?>"
     5        class="regular-text"
     6        value="<?php echo esc_attr( TGGRSettings::get_instance()->settings[ $class ][ $setting ] ); ?>"
     7/>
     8 No newline at end of file
  • views/tggr-source-facebook/page-settings-section-header.php

    Property changes on: views/tggr-source-facebook/page-settings-fields.php
    ___________________________________________________________________
    Added: svn:executable
    ## -0,0 +1 ##
    +*
    \ No newline at end of property
     
     1<p>You can obtain the Access Token by creating a Facebook account and then applying for one at <a href="https://developers.facebook.com/apps/">Facebook Developers</a>.</p>
  • views/tggr-source-facebook/shortcode-tagregator-media-item.php

    Property changes on: views/tggr-source-facebook/page-settings-section-header.php
    ___________________________________________________________________
    Added: svn:executable
    ## -0,0 +1 ##
    +*
    \ No newline at end of property
     
     1<?php $post = get_post(); ?>
     2
     3<div id="<?php echo esc_attr( Tagregator::CSS_PREFIX . get_the_ID() ); ?>" class="<?php echo esc_attr( $css_classes ); ?>">
     4
     5        <a href="<?php echo esc_attr( $author_url ); ?>" class="<?php echo esc_attr( Tagregator::CSS_PREFIX ); ?>author-profile clearfix">
     6                <?php if ( $author_image_url ) : ?>
     7                        <img src="<?php echo esc_attr( $author_image_url ); ?>" alt="<?php echo esc_attr( $author_name ); ?>" class="<?php echo esc_attr( Tagregator::CSS_PREFIX ); ?>author-avatar">
     8                <?php endif; ?>
     9                <span class="<?php echo esc_attr( Tagregator::CSS_PREFIX ); ?>author-name"><?php echo esc_html( $author_name ); ?></span>
     10        </a>
     11
     12        <div class="<?php echo esc_attr( Tagregator::CSS_PREFIX ); ?>item-content">
     13                <?php if ( $show_excerpt ) : ?>
     14                        <?php the_excerpt(); ?>
     15                        <p><a href="<?php echo esc_attr( $post_permalink ); ?>">Read the rest of this post on Google+</a></p>
     16                <?php else : ?>
     17                        <?php the_content(); ?>
     18                <?php endif; ?>
     19
     20                <?php if ( $media ) : ?>
     21                        <?php foreach ( $media as $media_item ) : ?>
     22                                <?php if ( 'image' == $media_item['type'] ) : ?>
     23                                        <a href="<?php echo esc_url( $post_permalink ); ?>"><img src="<?php echo esc_url( $media_item['small_url'] ); ?>" alt="" /></a>
     24                                <?php endif; ?>
     25                        <?php endforeach; ?>
     26                <?php endif; ?>
     27        </div>
     28
     29        <a href="<?php echo esc_url( $post_permalink ); ?>" class="<?php echo esc_attr( Tagregator::CSS_PREFIX ); ?>timestamp">
     30                <?php echo human_time_diff( get_the_time( 'U' ), current_time( 'timestamp' ) ) . ' ago'; ?>
     31        </a>
     32
     33        <img class="tggr-source-logo" src="<?php echo esc_attr( $logo_url ); ?>" alt="Facebook" />
     34</div>