Skip to:
Content

BuddyPress.org


Ignore:
Timestamp:
03/13/2014 06:34:06 PM (11 years ago)
Author:
boonebgorges
Message:

Generate activity actions dynamically, instead of using static values stored in the database

Activity actions - like 'Joe became a registered member' - have always been
stored as static strings in the activity table. This has been a perennial thorn
in the side of BP site administrators. For one thing, static strings cannot be
translated for multilingual audiences (without unreasonable workarounds).
For another, information in these static strings becomes out of date as users
change their display names, groups change their names, and so on.

This changeset makes it possible for activity types to be registered with a
new $format_callback function, passed to bp_activity_set_action(), which BP
will use to generate the action dynamically when building the activity loop.
This makes the activity stream fully localizable, continually up-to-date, and
generally the bomb dot com.

Existing plugins that do not register format_callback functions will continue
to have their actions pulled directly from the database. Likewise, since a copy
of the static string is saved in the activity table, static strings can be
served if the given component is disabled at any point (and thus the callback
is no longer available).

The original argument for caching the action strings was that generating them
inline was too resource intensive; it often requires pulling up display names,
user permalinks, group links, blog post names, and so forth. To address this
problem, each component can now prefetch required data at the beginning of an
activity loop by hooking to bp_activity_prefetch_object_data, and loading any
relevant data into the cache. The Activity, Friends, Groups, and Blogs
component now do this natively. It's likely that this prefetching will have
other performance benefits, as plugin authors will now be able to access user
data etc inline without performance penalties.

The case of the Blogs component is a special one; it's not practical to
prefetch data from multiple blogs at the beginning of a loop, due to the
resources required by switch_to_blog(). For this reason, the format_callback
functions in the blog component cache some relevant data (like the post name)
in blogmeta, where it's readily accessible within the loop.

Fixes #3856

File:
1 edited

Legend:

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

    r7555 r8125  
    2929
    3030    if ( is_multisite() ) {
    31         bp_activity_set_action( $bp->blogs->id, 'new_blog', __( 'New site created',        'buddypress' ) );
    32     }
    33 
    34     bp_activity_set_action( $bp->blogs->id, 'new_blog_post',    __( 'New post published',      'buddypress' ) );
    35     bp_activity_set_action( $bp->blogs->id, 'new_blog_comment', __( 'New post comment posted', 'buddypress' ) );
     31        bp_activity_set_action(
     32            $bp->blogs->id,
     33            'new_blog',
     34            __( 'New site created', 'buddypress' ),
     35            'bp_blogs_format_activity_action_new_blog'
     36        );
     37    }
     38
     39    bp_activity_set_action(
     40        $bp->blogs->id,
     41        'new_blog_post',
     42        __( 'New post published', 'buddypress' ),
     43        'bp_blogs_format_activity_action_new_blog_post'
     44    );
     45
     46    bp_activity_set_action(
     47        $bp->blogs->id,
     48        'new_blog_comment',
     49        __( 'New post comment posted', 'buddypress' ),
     50        'bp_blogs_format_activity_action_new_blog_comment'
     51    );
    3652
    3753    do_action( 'bp_blogs_register_activity_actions' );
    3854}
    3955add_action( 'bp_register_activity_actions', 'bp_blogs_register_activity_actions' );
     56
     57/**
     58 * Format 'new_blog' activity actions.
     59 *
     60 * @since BuddyPress (2.0.0)
     61 *
     62 * @param obj $activity Activity data object.
     63 */
     64function bp_blogs_format_activity_action_new_blog( $activity ) {
     65    $blog_url  = bp_blogs_get_blogmeta( $activity->item_id, 'url' );
     66    $blog_name = bp_blogs_get_blogmeta( $activity->item_id, 'name' );
     67
     68    $action = sprintf( __( '%s created the site %s', 'buddypress' ), bp_core_get_userlink( $activity->user_id ), '<a href="' . esc_url( $blog_url ) . '">' . esc_html( $blog_name ) . '</a>' );
     69
     70    // Legacy filter - requires the BP_Blogs_Blog object
     71    if ( has_filter( 'bp_blogs_activity_created_blog_action' ) ) {
     72        $user_blog = BP_Blogs_Blog::get_user_blog( $activity->user_id, $activity->item_id );
     73        if ( $user_blog ) {
     74            $recorded_blog = new BP_Blogs_Blog( $user_blog );
     75        }
     76
     77        if ( isset( $recorded_blog ) ) {
     78            $action = apply_filters( 'bp_blogs_activity_created_blog_action', $action, $recorded_blog, $blog_name, bp_blogs_get_blogmeta( $activity->item_id, 'description' ) );
     79        }
     80    }
     81
     82    return apply_filters( 'bp_blogs_format_activity_action_new_blog', $action, $activity );
     83}
     84
     85/**
     86 * Format 'new_blog_post' activity actions.
     87 *
     88 * @since BuddyPress (2.0.0)
     89 *
     90 * @param obj $activity Activity data object.
     91 */
     92function bp_blogs_format_activity_action_new_blog_post( $activity ) {
     93    $blog_url  = bp_blogs_get_blogmeta( $activity->item_id, 'url' );
     94    $blog_name = bp_blogs_get_blogmeta( $activity->item_id, 'name' );
     95
     96    if ( empty( $blog_url ) || empty( $blog_name ) ) {
     97        $blog_url  = get_home_url( $activity->item_id );
     98        $blog_name = get_blog_option( $activity->item_id, 'blogname' );
     99
     100        bp_blogs_update_blogmeta( $activity->item_id, 'url', $blog_url );
     101        bp_blogs_update_blogmeta( $activity->item_id, 'name', $blog_name );
     102    }
     103
     104    $post_url = add_query_arg( 'p', $activity->secondary_item_id, trailingslashit( $blog_url ) );
     105
     106    $post_title = bp_activity_get_meta( $activity->id, 'post_title' );
     107
     108    // Should only be empty at the time of post creation
     109    if ( empty( $post_title ) ) {
     110        switch_to_blog( $activity->item_id );
     111
     112        $post = get_post( $activity->secondary_item_id );
     113        if ( is_a( $post, 'WP_Post' ) ) {
     114            $post_title = $post->post_title;
     115            bp_activity_update_meta( $activity->id, 'post_title', $post_title );
     116        }
     117
     118        restore_current_blog();
     119    }
     120
     121    $post_link  = '<a href="' . $post_url . '">' . $post_title . '</a>';
     122
     123    $user_link = bp_core_get_userlink( $activity->user_id );
     124
     125    if ( is_multisite() ) {
     126        $action  = sprintf( __( '%1$s wrote a new post, %2$s, on the site %3$s', 'buddypress' ), $user_link, $post_link, '<a href="' . esc_url( $blog_url ) . '">' . esc_html( $blog_name ) . '</a>' );
     127    } else {
     128        $action  = sprintf( __( '%1$s wrote a new post, %2$s', 'buddypress' ), $user_link, $post_link );
     129    }
     130
     131    // Legacy filter - requires the post object
     132    if ( has_filter( 'bp_blogs_activity_new_post_action' ) ) {
     133        switch_to_blog( $activity->item_id );
     134        $post = get_post( $activity->secondary_item_id );
     135        restore_current_blog();
     136
     137        if ( ! empty( $post ) && ! is_wp_error( $post ) ) {
     138            $action = apply_filters( 'bp_blogs_activity_new_post_action', $action, $post, $post_url );
     139        }
     140    }
     141
     142    return apply_filters( 'bp_blogs_format_activity_action_new_blog_post', $action, $activity );
     143}
     144
     145/**
     146 * Format 'new_blog_comment' activity actions.
     147 *
     148 * @since BuddyPress (2.0.0)
     149 *
     150 * @param obj $activity Activity data object.
     151 */
     152function bp_blogs_format_activity_action_new_blog_comment( $activity ) {
     153    $blog_url  = bp_blogs_get_blogmeta( $activity->item_id, 'url' );
     154    $blog_name = bp_blogs_get_blogmeta( $activity->item_id, 'name' );
     155
     156    if ( empty( $blog_url ) || empty( $blog_name ) ) {
     157        $blog_url  = get_home_url( $activity->item_id );
     158        $blog_name = get_blog_option( $activity->item_id, 'blogname' );
     159
     160        bp_blogs_update_blogmeta( $activity->item_id, 'url', $blog_url );
     161        bp_blogs_update_blogmeta( $activity->item_id, 'name', $blog_name );
     162    }
     163
     164    $post_url   = bp_activity_get_meta( $activity->id, 'post_url' );
     165    $post_title = bp_activity_get_meta( $activity->id, 'post_title' );
     166
     167    // Should only be empty at the time of post creation
     168    if ( empty( $post_url ) || empty( $post_title ) ) {
     169        switch_to_blog( $activity->item_id );
     170
     171        $comment = get_comment( $activity->secondary_item_id );
     172
     173        if ( ! empty( $comment->comment_post_ID ) ) {
     174            $post_url = add_query_arg( 'p', $comment->comment_post_ID, trailingslashit( $blog_url ) );
     175            bp_activity_update_meta( $activity->id, 'post_url', $post_url );
     176
     177            $post = get_post( $comment->comment_post_ID );
     178
     179            if ( is_a( $post, 'WP_Post' ) ) {
     180                $post_title = $post->post_title;
     181                bp_activity_update_meta( $activity->id, 'post_title', $post_title );
     182            }
     183        }
     184
     185        restore_current_blog();
     186    }
     187
     188    $post_link = '<a href="' . $post_url . '">' . $post_title . '</a>';
     189    $user_link = bp_core_get_userlink( $activity->user_id );
     190
     191    if ( is_multisite() ) {
     192        $action  = sprintf( __( '%1$s commented on the post, %2$s, on the site %3$s', 'buddypress' ), $user_link, $post_link, '<a href="' . esc_url( $blog_url ) . '">' . esc_html( $blog_name ) . '</a>' );
     193    } else {
     194        $action  = sprintf( __( '%1$s commented on the post, %2$s', 'buddypress' ), $user_link, $post_link );
     195    }
     196
     197    // Legacy filter - requires the comment object
     198    if ( has_filter( 'bp_blogs_activity_new_comment_action' ) ) {
     199        switch_to_blog( $activity->item_id );
     200        $comment = get_comment( $activity->secondary_item_id );
     201        restore_current_blog();
     202
     203        if ( ! empty( $comment ) && ! is_wp_error( $comment ) ) {
     204            $action = apply_filters( 'bp_blogs_activity_new_comment_action', $action, $comment, $post_url . '#' . $activity->secondary_item_id );
     205        }
     206    }
     207
     208    return apply_filters( 'bp_blogs_format_activity_action_new_blog_comment', $action, $activity );
     209}
     210
     211/**
     212 * Fetch data related to blogs at the beginning of an activity loop.
     213 *
     214 * This reduces database overhead during the activity loop.
     215 *
     216 * @since BuddyPress (2.0.0)
     217 *
     218 * @param array $activities Array of activity items.
     219 * @return array
     220 */
     221function bp_blogs_prefetch_activity_object_data( $activities ) {
     222    if ( empty( $activities ) ) {
     223        return $activities;
     224    }
     225
     226    $blog_ids = array();
     227
     228    foreach ( $activities as $activity ) {
     229        if ( buddypress()->blogs->id !== $activity->component ) {
     230            continue;
     231        }
     232
     233        $blog_ids[] = $activity->item_id;
     234    }
     235
     236    if ( ! empty( $blog_ids ) ) {
     237        bp_blogs_update_meta_cache( $blog_ids );
     238    }
     239}
     240add_filter( 'bp_activity_prefetch_object_data', 'bp_blogs_prefetch_activity_object_data' );
    40241
    41242/**
Note: See TracChangeset for help on using the changeset viewer.