Skip to:
Content

BuddyPress.org


Ignore:
Timestamp:
06/12/2013 10:08:10 PM (11 years ago)
Author:
boonebgorges
Message:

Introduces BP_Activity_Feed class, and migrates existing feeds

RSS feeds for BP activity have historically been generated on a one-by-one
basis, with separate template files used for each theme. This resulted in a
huge amount of unnecessarily duplicated code. Moreover, it made the process
of customizing feeds, or providing new feeds, unnecessarily cumbersome.

BP_Activity_Feed abstracts the central parts of RSS feed building, allowing for
easier customization, and fewer points of failure.

This changeset also fixes our RSS implementation to match best practices with
respect to encoding content inside of the <description> element.

Fixes #5020

Props r-a-y

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/bp-activity/bp-activity-classes.php

    r7149 r7207  
    257257            $activity_user_ids = implode( ',', wp_parse_id_list( $activity_user_ids ) );
    258258
    259             if ( !empty( $activity_user_ids ) ) {               
     259            if ( !empty( $activity_user_ids ) ) {
    260260                if ( $names = $wpdb->get_results( "SELECT user_id, value AS user_fullname FROM {$bp->profile->table_name_data} WHERE field_id = 1 AND user_id IN ({$activity_user_ids})" ) ) {
    261261                    foreach ( (array) $names as $name )
     
    731731    }
    732732}
     733
     734/**
     735 * Create a RSS feed using the activity component.
     736 *
     737 * You should only construct a new feed when you've validated that you're on
     738 * the appropriate screen.
     739 *
     740 * See {@link bp_activity_action_sitewide_feed()} as an example.
     741 *
     742 * Accepted parameters:
     743 *   id               - internal id for the feed; should be alphanumeric only
     744 *                      (required)
     745 *   title            - RSS feed title
     746 *   link             - Relevant link for the RSS feed
     747 *   description      - RSS feed description
     748 *   ttl              - Time-to-live (see inline doc in constructor)
     749 *   update_period    - Part of the syndication module (see inline doc in
     750 *                      constructor for more info)
     751 *   update_frequency - Part of the syndication module (see inline doc in
     752 *                      constructor for more info)
     753 *   max              - Number of feed items to display
     754 *   activity_args    - Arguments passed to {@link bp_has_activities()}
     755 *
     756 * @since BuddyPress (1.8)
     757 */
     758class BP_Activity_Feed {
     759    /**
     760     * Holds our custom class properties.
     761     *
     762     * These variables are stored in a protected array that is magically
     763     * updated using PHP 5.2+ methods.
     764     *
     765     * @see BP_Feed::__construct() This is where $data is added
     766     * @var array
     767     */
     768    protected $data;
     769
     770    /**
     771     * Magic method for checking the existence of a certain data variable.
     772     *
     773     * @param string $key
     774     */
     775    public function __isset( $key ) { return isset( $this->data[$key] ); }
     776
     777    /**
     778     * Magic method for getting a certain data variable.
     779     *
     780     * @param string $key
     781     */
     782    public function __get( $key ) { return isset( $this->data[$key] ) ? $this->data[$key] : null; }
     783
     784    /**
     785     * Constructor.
     786     *
     787     * @param $args Array
     788     */
     789    public function __construct( $args = array() ) {
     790        // If feeds are disabled, stop now!
     791        if ( false === (bool) apply_filters( 'bp_activity_enable_feeds', true ) ) {
     792            global $wp_query;
     793
     794            // set feed flag to false
     795            $wp_query->is_feed = false;
     796
     797            return false;
     798        }
     799
     800        // Setup data
     801        $this->data = wp_parse_args( $args, array(
     802            // Internal identifier for the RSS feed - should be alphanumeric only
     803            'id'               => '',
     804
     805            // RSS title - should be plain-text
     806            'title'            => '',
     807
     808            // relevant link for the RSS feed
     809            'link'             => '',
     810
     811            // RSS description - should be plain-text
     812            'description'      => '',
     813
     814            // Time-to-live - number of minutes to cache the data before an aggregator
     815            // requests it again.  This is only acknowledged if the RSS client supports it
     816            //
     817            // See: http://www.rssboard.org/rss-profile#element-channel-ttl
     818            //      http://www.kbcafe.com/rss/rssfeedstate.html#ttl
     819            'ttl'              => '30',
     820
     821            // Syndication module - similar to ttl, but not really supported by RSS
     822            // clients
     823            //
     824            // See: http://web.resource.org/rss/1.0/modules/syndication/#description
     825            //      http://www.kbcafe.com/rss/rssfeedstate.html#syndicationmodule
     826            'update_period'    => 'hourly',
     827            'update_frequency' => 2,
     828
     829            // Number of items to display
     830            'max'              => 50,
     831
     832            // Activity arguments passed to bp_has_activities()
     833            'activity_args'    => array()
     834        ) );
     835
     836        // Plugins can use this filter to modify the feed before it is setup
     837        do_action_ref_array( 'bp_activity_feed_prefetch', array( &$this ) );
     838
     839        // Setup class properties
     840        $this->setup_properties();
     841
     842        // Check if id is valid
     843        if ( empty( $this->id ) ) {
     844            _doing_it_wrong( 'BP_Activity_Feed', __( "RSS feed 'id' must be defined", 'buddypress' ), 'BP 1.8' );
     845            return false;
     846        }
     847
     848        // Plugins can use this filter to modify the feed after it's setup
     849        do_action_ref_array( 'bp_activity_feed_postfetch', array( &$this ) );
     850
     851        // Setup feed hooks
     852        $this->setup_hooks();
     853
     854        // Output the feed
     855        $this->output();
     856
     857        // Kill the rest of the output
     858        die();
     859    }
     860
     861    /** SETUP ****************************************************************/
     862
     863    /**
     864     * Setup and validate the class properties.
     865     */
     866    protected function setup_properties() {
     867        $this->id               = sanitize_title( $this->id );
     868        $this->title            = strip_tags( $this->title );
     869        $this->link             = esc_url_raw( $this->link );
     870        $this->description      = strip_tags( $this->description );
     871        $this->ttl              = (int) $this->ttl;
     872        $this->update_period    = strip_tags( $this->update_period );
     873        $this->update_frequency = (int) $this->update_frequency;
     874
     875        $this->activity_args    = wp_parse_args( $this->activity_args, array(
     876            'max'              => $this->max,
     877            'display_comments' => 'stream'
     878        ) );
     879
     880    }
     881
     882    /**
     883     * Setup some hooks that are used in the feed.
     884     *
     885     * Currently, these hooks are used to maintain backwards compatibility with
     886     * the RSS feeds previous to BP 1.8.
     887     */
     888    protected function setup_hooks() {
     889        add_action( 'bp_activity_feed_rss_attributes',   array( $this, 'backpat_rss_attributes' ) );
     890        add_action( 'bp_activity_feed_channel_elements', array( $this, 'backpat_channel_elements' ) );
     891        add_action( 'bp_activity_feed_item_elements',    array( $this, 'backpat_item_elements' ) );
     892    }
     893
     894    /** BACKPAT HOOKS ********************************************************/
     895
     896    public function backpat_rss_attributes() {
     897        do_action( 'bp_activity_' . $this->id . '_feed' );
     898    }
     899
     900    public function backpat_channel_elements() {
     901        do_action( 'bp_activity_' . $this->id . '_feed_head' );
     902    }
     903
     904    public function backpat_item_elements() {
     905        switch ( $this->id ) {
     906
     907            // sitewide and friends feeds use the 'personal' hook
     908            case 'sitewide' :
     909            case 'friends' :
     910                $id = 'personal';
     911
     912                break;
     913
     914            default :
     915                $id = $this->id;
     916
     917                break;
     918        }
     919
     920        do_action( 'bp_activity_' . $id . '_feed_item' );
     921    }
     922
     923    /** HELPERS **************************************************************/
     924
     925    /**
     926     * Output the feed's item content.
     927     */
     928    protected function feed_content() {
     929        bp_activity_content_body();
     930
     931        switch ( $this->id ) {
     932
     933            // also output parent activity item if we're on a specific feed
     934            case 'favorites' :
     935            case 'friends' :
     936            case 'mentions' :
     937            case 'personal' :
     938
     939                if ( 'activity_comment' == bp_get_activity_action_name() ) :
     940            ?>
     941                <strong><?php _e( 'In reply to', 'buddypress' ) ?></strong> -
     942                <?php bp_activity_parent_content() ?>
     943            <?php
     944                endif;
     945
     946                break;
     947        }
     948    }
     949
     950    /** OUTPUT ***************************************************************/
     951
     952    /**
     953     * Output the RSS feed.
     954     */
     955    protected function output() {
     956        // set up some additional headers if not on a directory page
     957        // this is done b/c BP uses pseudo-pages
     958        if ( ! bp_is_directory() ) {
     959            global $wp_query;
     960
     961            $wp_query->is_404 = false;
     962            status_header( 200 );
     963        }
     964
     965        header( 'Content-Type: text/xml; charset=' . get_option( 'blog_charset' ), true );
     966        echo '<?xml version="1.0" encoding="' . get_option( 'blog_charset' ) . '"?'.'>';
     967    ?>
     968
     969<rss version="2.0"
     970    xmlns:content="http://purl.org/rss/1.0/modules/content/"
     971    xmlns:atom="http://www.w3.org/2005/Atom"
     972    xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
     973    xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
     974    <?php do_action( 'bp_activity_feed_rss_attributes' ); ?>
     975>
     976
     977<channel>
     978    <title><?php echo $this->title; ?></title>
     979    <link><?php echo $this->link; ?></link>
     980    <atom:link href="<?php self_link(); ?>" rel="self" type="application/rss+xml" />
     981    <description><?php echo $this->description ?></description>
     982    <lastBuildDate><?php echo mysql2date( 'D, d M Y H:i:s O', bp_activity_get_last_updated(), false ); ?></lastBuildDate>
     983    <generator>http://buddypress.org/?v=<?php bp_version(); ?></generator>
     984    <language><?php bloginfo_rss( 'language' ); ?></language>
     985    <ttl><?php echo $this->ttl; ?></ttl>
     986    <sy:updatePeriod><?php echo $this->update_period; ?></sy:updatePeriod>
     987    <sy:updateFrequency><?php echo $this->update_frequency; ?></sy:updateFrequency>
     988    <?php do_action( 'bp_activity_feed_channel_elements' ); ?>
     989
     990    <?php if ( bp_has_activities( $this->activity_args ) ) : ?>
     991        <?php while ( bp_activities() ) : bp_the_activity(); ?>
     992            <item>
     993                <guid isPermaLink="false"><?php bp_activity_feed_item_guid(); ?></guid>
     994                <title><?php echo stripslashes( bp_get_activity_feed_item_title() ); ?></title>
     995                <link><?php bp_activity_thread_permalink() ?></link>
     996                <pubDate><?php echo mysql2date( 'D, d M Y H:i:s O', bp_get_activity_feed_item_date(), false ); ?></pubDate>
     997
     998                <?php if ( bp_get_activity_feed_item_description() ) : ?>
     999                    <content:encoded><![CDATA[<?php $this->feed_content(); ?>]]></content:encoded>
     1000                <?php endif; ?>
     1001
     1002                <?php if ( bp_activity_can_comment() ) : ?>
     1003                    <slash:comments><?php bp_activity_comment_count(); ?></slash:comments>
     1004                <?php endif; ?>
     1005
     1006                <?php do_action( 'bp_activity_feed_item_elements' ); ?>
     1007            </item>
     1008        <?php endwhile; ?>
     1009
     1010    <?php endif; ?>
     1011</channel>
     1012</rss><?php
     1013    }
     1014}
Note: See TracChangeset for help on using the changeset viewer.