Skip to:
Content

BuddyPress.org

Changeset 7207


Ignore:
Timestamp:
06/12/2013 10:08:10 PM (13 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

Location:
trunk
Files:
7 deleted
3 edited

Legend:

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

    r7193 r7207  
    422422 */
    423423function bp_activity_action_sitewide_feed() {
    424         global $bp, $wp_query;
    425 
    426         if ( !bp_is_activity_component() || !bp_is_current_action( 'feed' ) || bp_is_user() || !empty( $bp->groups->current_group ) )
    427                 return false;
    428 
    429         $wp_query->is_404 = false;
    430         status_header( 200 );
    431 
    432         include_once( 'feeds/bp-activity-sitewide-feed.php' );
    433         die;
     424        global $bp;
     425
     426        if ( ! bp_is_activity_component() || ! bp_is_current_action( 'feed' ) || bp_is_user() || ! empty( $bp->groups->current_group ) )
     427                return false;
     428
     429        // setup the feed
     430        buddypress()->activity->feed = new BP_Activity_Feed( array(
     431                'id'            => 'sitewide',
     432
     433                /* translators: Sitewide activity RSS title - "[Site Name] | Site Wide Activity" */
     434                'title'         => sprintf( __( '%s | Site Wide Activity', 'buddypress' ), bp_get_site_name() ),
     435
     436                'link'          => bp_get_activity_directory_permalink(),
     437                'description'   => __( 'Activity feed for the entire site.', 'buddypress' ),
     438                'activity_args' => 'display_comments=threaded'
     439        ) );
    434440}
    435441add_action( 'bp_actions', 'bp_activity_action_sitewide_feed' );
     
    448454 */
    449455function bp_activity_action_personal_feed() {
    450         global $wp_query;
    451 
    452         if ( !bp_is_user_activity() || !bp_is_current_action( 'feed' ) )
    453                 return false;
    454 
    455         $wp_query->is_404 = false;
    456         status_header( 200 );
    457 
    458         include_once( 'feeds/bp-activity-personal-feed.php' );
    459         die;
     456        if ( ! bp_is_user_activity() || ! bp_is_current_action( 'feed' ) ) {
     457                return false;
     458        }
     459
     460        // setup the feed
     461        buddypress()->activity->feed = new BP_Activity_Feed( array(
     462                'id'            => 'personal',
     463
     464                /* translators: Personal activity RSS title - "[Site Name] | [User Display Name] | Activity" */
     465                'title'         => sprintf( __( '%1$s | %2$s | Activity', 'buddypress' ), bp_get_site_name(), bp_get_displayed_user_fullname() ),
     466
     467                'link'          => trailingslashit( bp_displayed_user_domain() . bp_get_activity_slug() ),
     468                'description'   => sprintf( __( 'Activity feed for %s.', 'buddypress' ), bp_get_displayed_user_fullname() ),
     469                'activity_args' => 'user_id=' . bp_displayed_user_id()
     470        ) );
    460471}
    461472add_action( 'bp_actions', 'bp_activity_action_personal_feed' );
     
    477488 */
    478489function bp_activity_action_friends_feed() {
    479         global $wp_query;
    480 
    481         if ( !bp_is_active( 'friends' ) || !bp_is_user_activity() || !bp_is_current_action( bp_get_friends_slug() ) || !bp_is_action_variable( 'feed', 0 ) )
    482                 return false;
    483 
    484         $wp_query->is_404 = false;
    485         status_header( 200 );
    486 
    487         include_once( 'feeds/bp-activity-friends-feed.php' );
    488         die;
     490        if ( ! bp_is_active( 'friends' ) || ! bp_is_user_activity() || ! bp_is_current_action( bp_get_friends_slug() ) || ! bp_is_action_variable( 'feed', 0 ) ) {
     491                return false;
     492        }
     493
     494        // setup the feed
     495        buddypress()->activity->feed = new BP_Activity_Feed( array(
     496                'id'            => 'friends',
     497
     498                /* translators: Friends activity RSS title - "[Site Name] | [User Display Name] | Friends Activity" */
     499                'title'         => sprintf( __( '%1$s | %2$s | Friends Activity', 'buddypress' ), bp_get_site_name(), bp_get_displayed_user_fullname() ),
     500
     501                'link'          => trailingslashit( bp_displayed_user_domain() . bp_get_activity_slug() . '/' . bp_get_friends_slug() ),
     502                'description'   => sprintf( __( "Activity feed for %s' friends.", 'buddypress' ), bp_get_displayed_user_fullname() ),
     503                'activity_args' => 'scope=friends'
     504        ) );
    489505}
    490506add_action( 'bp_actions', 'bp_activity_action_friends_feed' );
     
    506522 */
    507523function bp_activity_action_my_groups_feed() {
     524        if ( ! bp_is_active( 'groups' ) || ! bp_is_user_activity() || ! bp_is_current_action( bp_get_groups_slug() ) || ! bp_is_action_variable( 'feed', 0 ) ) {
     525                return false;
     526        }
     527
     528        // get displayed user's group IDs
     529        $groups    = groups_get_user_groups();
     530        $group_ids = implode( ',', $groups['groups'] );
     531
     532        // setup the feed
     533        buddypress()->activity->feed = new BP_Activity_Feed( array(
     534                'id'            => 'mygroups',
     535
     536                /* translators: Member groups activity RSS title - "[Site Name] | [User Display Name] | Groups Activity" */
     537                'title'         => sprintf( __( '%1$s | %2$s | Group Activity', 'buddypress' ), bp_get_site_name(), bp_get_displayed_user_fullname() ),
     538
     539                'link'          => trailingslashit( bp_displayed_user_domain() . bp_get_activity_slug() . '/' . bp_get_groups_slug() ),
     540                'description'   => sprintf( __( "Public group activity feed of which %s is a member of.", 'buddypress' ), bp_get_displayed_user_fullname() ),
     541                'activity_args' => array(
     542                        'object'           => buddypress()->groups->id,
     543                        'primary_id'       => $group_ids,
     544                        'display_comments' => 'threaded'
     545                )
     546        ) );
     547}
     548add_action( 'bp_actions', 'bp_activity_action_my_groups_feed' );
     549
     550/**
     551 * Load a user's @mentions feed.
     552 *
     553 * @since BuddyPress (1.2)
     554 *
     555 * @global object $wp_query
     556 * @uses bp_is_user_activity()
     557 * @uses bp_is_current_action()
     558 * @uses bp_is_action_variable()
     559 * @uses status_header()
     560 *
     561 * @return bool False on failure
     562 */
     563function bp_activity_action_mentions_feed() {
    508564        global $wp_query;
    509565
    510         if ( !bp_is_active( 'groups' ) || !bp_is_user_activity() || !bp_is_current_action( bp_get_groups_slug() ) || !bp_is_action_variable( 'feed', 0 ) )
     566        if ( ! bp_activity_do_mentions() ) {
     567                return false;
     568        }
     569
     570        if ( !bp_is_user_activity() || !bp_is_current_action( 'mentions' ) || !bp_is_action_variable( 'feed', 0 ) )
    511571                return false;
    512572
     
    514574        status_header( 200 );
    515575
    516         include_once( 'feeds/bp-activity-mygroups-feed.php' );
     576        include_once( 'feeds/bp-activity-mentions-feed.php' );
    517577        die;
    518578}
    519 add_action( 'bp_actions', 'bp_activity_action_my_groups_feed' );
    520 
    521 /**
    522  * Load a user's @mentions feed.
     579add_action( 'bp_actions', 'bp_activity_action_mentions_feed' );
     580
     581/**
     582 * Load a user's favorites feed.
    523583 *
    524584 * @since BuddyPress (1.2)
     
    532592 * @return bool False on failure
    533593 */
    534 function bp_activity_action_mentions_feed() {
    535         global $wp_query;
    536 
    537         if ( ! bp_activity_do_mentions() ) {
    538                 return false;
    539         }
    540 
    541         if ( !bp_is_user_activity() || !bp_is_current_action( 'mentions' ) || !bp_is_action_variable( 'feed', 0 ) )
    542                 return false;
    543 
    544         $wp_query->is_404 = false;
    545         status_header( 200 );
    546 
    547         include_once( 'feeds/bp-activity-mentions-feed.php' );
    548         die;
    549 }
    550 add_action( 'bp_actions', 'bp_activity_action_mentions_feed' );
    551 
    552 /**
    553  * Load a user's favorites feed.
    554  *
    555  * @since BuddyPress (1.2)
    556  *
    557  * @global object $wp_query
    558  * @uses bp_is_user_activity()
    559  * @uses bp_is_current_action()
    560  * @uses bp_is_action_variable()
    561  * @uses status_header()
    562  *
    563  * @return bool False on failure
    564  */
    565594function bp_activity_action_favorites_feed() {
    566         global $wp_query;
    567 
    568         if ( !bp_is_user_activity() || !bp_is_current_action( 'favorites' ) || !bp_is_action_variable( 'feed', 0 ) )
    569                 return false;
    570 
    571         $wp_query->is_404 = false;
    572         status_header( 200 );
    573 
    574         include_once( 'feeds/bp-activity-favorites-feed.php' );
    575         die;
     595        if ( ! bp_is_user_activity() || ! bp_is_current_action( 'favorites' ) || ! bp_is_action_variable( 'feed', 0 ) ) {
     596                return false;
     597        }
     598
     599        // get displayed user's favorite activity IDs
     600        $favs = bp_activity_get_user_favorites( bp_displayed_user_id() );
     601        $fav_ids = implode( ',', (array) $favs );
     602
     603        // setup the feed
     604        buddypress()->activity->feed = new BP_Activity_Feed( array(
     605                'id'            => 'favorites',
     606
     607                /* translators: User activity favorites RSS title - "[Site Name] | [User Display Name] | Favorites" */
     608                'title'         => sprintf( __( '%1$s | %2$s | Favorites', 'buddypress' ), bp_get_site_name(), bp_get_displayed_user_fullname() ),
     609
     610                'link'          => bp_displayed_user_domain() . bp_get_activity_slug() . '/favorites/',
     611                'description'   => sprintf( __( "Activity feed of %s' favorites.", 'buddypress' ), bp_get_displayed_user_fullname() ),
     612                'activity_args' => 'include=' . $fav_ids
     613        ) );
    576614}
    577615add_action( 'bp_actions', 'bp_activity_action_favorites_feed' );
  • 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}
  • trunk/bp-groups/bp-groups-actions.php

    r7172 r7207  
    305305add_action( 'bp_actions', 'groups_action_redirect_to_random_group' );
    306306
     307/**
     308 * Load the activity feed for the specific group.
     309 *
     310 * @since BuddyPress (v1.2)
     311 */
    307312function groups_action_group_feed() {
    308         global $bp, $wp_query;
    309 
    310         if ( !bp_is_active( 'activity' ) || !bp_is_groups_component() || !isset( $bp->groups->current_group ) || !bp_is_current_action( 'feed' ) )
    311                 return false;
    312 
    313         $wp_query->is_404 = false;
    314         status_header( 200 );
    315 
    316         if ( 'public' != $bp->groups->current_group->status ) {
    317                 if ( !groups_is_user_member( bp_loggedin_user_id(), $bp->groups->current_group->id ) )
    318                         return false;
    319         }
    320 
    321         include_once( BP_PLUGIN_DIR . '/bp-activity/feeds/bp-activity-group-feed.php' );
    322         die;
     313
     314        // get current group
     315        $group = groups_get_current_group();
     316
     317        if ( ! bp_is_active( 'activity' ) || ! bp_is_groups_component() || ! $group || ! bp_is_current_action( 'feed' ) )
     318                return false;
     319
     320        // if group isn't public or if logged-in user is not a member of the group, do
     321        // not output the group activity feed
     322        if ( ! bp_group_is_visible( $group ) ) {
     323                return false;
     324        }
     325
     326        // setup the feed
     327        buddypress()->activity->feed = new BP_Activity_Feed( array(
     328                'id'            => 'group',
     329
     330                /* translators: Group activity RSS title - "[Site Name] | [Group Name] | Activity" */
     331                'title'         => sprintf( __( '%1$s | %2$s | Activity', 'buddypress' ), bp_get_site_name(), bp_get_current_group_name() ),
     332
     333                'link'          => bp_get_group_permalink( $group ),
     334                'description'   => sprintf( __( "Activity feed for the group, %s.", 'buddypress' ), bp_get_current_group_name() ),
     335                'activity_args' => array(
     336                        'object'           => buddypress()->groups->id,
     337                        'primary_id'       => bp_get_current_group_id(),
     338                        'display_comments' => 'threaded'
     339                )
     340        ) );
    323341}
    324342add_action( 'bp_actions', 'groups_action_group_feed' );
Note: See TracChangeset for help on using the changeset viewer.