<?php /** * bbPress BuddyPress Activity Class * * @package bbPress * @subpackage BuddyPress */ // Exit if accessed directly defined( 'ABSPATH' ) || exit; if ( ! class_exists( 'BBP_BuddyPress_Activity' ) ) : /** * Loads BuddyPress Activity extension * * @since 2.0.0 bbPress (r3395) * * @package bbPress * @subpackage BuddyPress */ class BBP_BuddyPress_Activity { /** Variables *************************************************************/ /** * The name of the BuddyPress component, used in activity streams * * @var string */ private $component = ''; /** * Forum Create Activity Action * * @var string */ private $forum_create = ''; /** * Topic Create Activity Action * * @var string */ private $topic_create = ''; /** * Topic Close Activity Action * * @var string */ private $topic_close = ''; /** * Topic Edit Activity Action * * @var string */ private $topic_edit = ''; /** * Topic Open Activity Action * * @var string */ private $topic_open = ''; /** * Reply Create Activity Action * * @var string */ private $reply_create = ''; /** * Reply Edit Activity Action * * @var string */ private $reply_edit = ''; /** Setup Methods *********************************************************/ /** * The bbPress BuddyPress Activity loader * * @since 2.0.0 bbPress (r3395) */ public function __construct() { $this->setup_globals(); $this->setup_actions(); $this->setup_filters(); $this->fully_loaded(); } /** * Extension variables * * @since 2.0.0 bbPress (r3395) * * @access private */ private function setup_globals() { // The name of the BuddyPress component, used in activity streams $this->component = 'bbpress'; // Forums $this->forum_create = 'bbp_forum_create'; // Topics $this->topic_create = 'bbp_topic_create'; $this->topic_edit = 'bbp_topic_edit'; $this->topic_close = 'bbp_topic_close'; $this->topic_open = 'bbp_topic_open'; // Replies $this->reply_create = 'bbp_reply_create'; $this->reply_edit = 'bbp_reply_edit'; } /** * Setup the actions * * @since 2.0.0 bbPress (r3395) * * @access private */ private function setup_actions() { // Register the activity stream actions add_action( 'bp_register_activity_actions', array( $this, 'register_activity_actions' ) ); // Hook into topic and reply creation add_action( 'bbp_new_topic', array( $this, 'topic_create' ), 10, 4 ); add_action( 'bbp_new_reply', array( $this, 'reply_create' ), 10, 5 ); // Hook into topic and reply status changes add_action( 'edit_post', array( $this, 'topic_update' ), 10, 2 ); add_action( 'edit_post', array( $this, 'reply_update' ), 10, 2 ); // Hook into topic and reply deletion add_action( 'bbp_delete_topic', array( $this, 'topic_delete' ), 10, 1 ); add_action( 'bbp_delete_reply', array( $this, 'reply_delete' ), 10, 1 ); // Append forum filters in site wide activity streams add_action( 'bp_activity_filter_options', array( $this, 'activity_filter_options' ), 10 ); // Append forum filters in single member activity streams add_action( 'bp_member_activity_filter_options', array( $this, 'activity_filter_options' ), 10 ); // Append forum filters in single group activity streams add_action( 'bp_group_activity_filter_options', array( $this, 'activity_filter_options' ), 10 ); } /** * Setup the filters * * @since 2.0.0 bbPress (r3395) * * @access private */ private function setup_filters() { // Obey BuddyPress commenting rules add_filter( 'bp_activity_can_comment', array( $this, 'activity_can_comment' ) ); // Link directly to the topic or reply add_filter( 'bp_activity_get_permalink', array( $this, 'activity_get_permalink' ), 10, 2 ); } /** * Allow the variables, actions, and filters to be modified by third party * plugins and themes. * * @since 2.1.0 bbPress (r3902) */ private function fully_loaded() { do_action_ref_array( 'bbp_buddypress_activity_loaded', array( $this ) ); } /** Methods ***************************************************************/ /** * Register our activity actions with BuddyPress * * @since 2.0.0 bbPress (r3395) */ public function register_activity_actions() { // Sitewide topic bp_activity_set_action( $this->component, $this->topic_create, esc_html__( 'New forum topic', 'bbpress' ), 'bbp_format_activity_action_new_topic', esc_html__( 'Topics', 'bbpress' ), array( 'activity', 'member', 'member_groups', 'group' ) ); // Sitewide reply bp_activity_set_action( $this->component, $this->reply_create, esc_html__( 'New forum reply', 'bbpress' ), 'bbp_format_activity_action_new_reply', esc_html__( 'Replies', 'bbpress' ), array( 'activity', 'member', 'member_groups', 'group' ) ); // Group forums /** * An upstream improvement to BuddyPress is required to make these work, * but they are included here to make our lives easier later. if ( bp_is_active( 'groups' ) ) { // Topic bp_activity_set_action( buddypress()->groups->id, $this->topic_create, esc_html__( 'New forum topic', 'bbpress' ), 'bbp_format_activity_action_new_topic', esc_html__( 'Topics', 'bbpress' ), array( 'activity', 'member', 'member_groups', 'group' ) ); // Reply bp_activity_set_action( buddypress()->groups->id, $this->reply_create, esc_html__( 'New forum reply', 'bbpress' ), 'bbp_format_activity_action_new_reply', esc_html__( 'Replies', 'bbpress' ), array( 'activity', 'member', 'member_groups', 'group' ) ); } */ } /** * Wrapper for recoding bbPress actions to the BuddyPress activity stream * * @since 2.0.0 bbPress (r3395) * * @param array $args Array of arguments for bp_activity_add() * * @return int Activity ID if successful, false if not */ private function record_activity( $args = array() ) { // Default activity args $activity = bbp_parse_args( $args, array( 'id' => null, 'user_id' => bbp_get_current_user_id(), 'type' => '', 'action' => '', 'item_id' => '', 'secondary_item_id' => '', 'content' => '', 'primary_link' => '', 'component' => $this->component, 'recorded_time' => bp_core_current_time(), 'hide_sitewide' => false ), 'record_activity' ); // Add the activity return bp_activity_add( $activity ); } /** * Wrapper for deleting bbPress actions from BuddyPress activity stream * * @since 2.0.0 bbPress (r3395) * * @param array $args Array of arguments for bp_activity_add() * * @return int Activity ID if successful, false if not */ public function delete_activity( $args = array() ) { // Default activity args $activity = bbp_parse_args( $args, array( 'item_id' => false, 'component' => $this->component, 'type' => false, 'user_id' => false, 'secondary_item_id' => false ), 'delete_activity' ); // Delete the activity bp_activity_delete_by_item_id( $activity ); } /** * Check for an existing activity stream entry for a given post_id * * @param int $post_id ID of the topic or reply * @return int if an activity id is verified, false if not */ private static function get_activity_id( $post_id = 0 ) { // Try to get the activity ID of the post $activity_id = (int) get_post_meta( $post_id, '_bbp_activity_id', true ); // Bail if no activity ID is in post meta if ( empty( $activity_id ) ) { return null; } // Get the activity stream item, bail if it doesn't exist $existing = new BP_Activity_Activity( $activity_id ); if ( empty( $existing->component ) ) { return null; } // Return the activity ID since we've verified the connection return $activity_id; } /** * Maybe disable activity stream comments on select actions * * @since 2.0.0 bbPress (r3399) * * @global BP_Activity_Template $activities_template * @param boolean $can_comment * @return boolean */ public function activity_can_comment( $can_comment = true ) { global $activities_template; // Already forced off, so comply if ( false === $can_comment ) { return $can_comment; } // Check if blog & forum activity stream commenting is off if ( ! empty( $activities_template->disable_blogforum_replies ) ) { // Get the current action name $action_name = bp_get_activity_action_name(); // Setup the array of possibly disabled actions $disabled_actions = array( $this->topic_create, $this->reply_create ); // Check if this activity stream action is disabled if ( in_array( $action_name, $disabled_actions, true ) ) { $can_comment = false; } } return $can_comment; } /** * Maybe link directly to topics and replies in activity stream entries * * @since 2.0.0 bbPress (r3399) * * @param string $link * @param mixed $activity_object * @return string The link to the activity stream item */ public function activity_get_permalink( $link = '', $activity_object = false ) { // Setup the array of actions to link directly to $disabled_actions = array( $this->topic_create, $this->reply_create ); // Check if this activity stream action is directly linked if ( in_array( $activity_object->type, $disabled_actions, true ) ) { $link = $activity_object->primary_link; } return $link; } /** * Append forum options to activity filter select box * * @since 2.1.0 bbPress (r3653) */ function activity_filter_options() { ?> <option value="<?php echo $this->topic_create; ?>"><?php esc_html_e( 'Topics', 'bbpress' ); ?></option> <option value="<?php echo $this->reply_create; ?>"><?php esc_html_e( 'Replies', 'bbpress' ); ?></option> <?php } /** Topics ****************************************************************/ /** * Record an activity stream entry when a topic is created or updated * * @since 2.0.0 bbPress (r3395) * * @param int $topic_id * @param int $forum_id * @param array $anonymous_data * @param int $topic_author_id * @return Bail early if topic is by anonymous user */ public function topic_create( $topic_id = 0, $forum_id = 0, $anonymous_data = array(), $topic_author_id = 0 ) { // Bail early if topic is by anonymous user if ( ! empty( $anonymous_data ) ) { return; } // Bail if site is private if ( ! bbp_is_site_public() ) { return; } // Validate activity data $user_id = bbp_get_user_id( $topic_author_id ); $topic_id = bbp_get_topic_id( $topic_id ); $forum_id = bbp_get_forum_id( $forum_id ); // Bail if user is not active if ( bbp_is_user_inactive( $user_id ) ) { return; } // Bail if topic is not published if ( ! bbp_is_topic_published( $topic_id ) ) { return; } // User link for topic author $user_link = bbp_get_user_profile_link( $user_id ); // Topic $topic_permalink = bbp_get_topic_permalink( $topic_id ); $topic_title = get_post_field( 'post_title', $topic_id, 'raw' ); $topic_content = get_post_field( 'post_content', $topic_id, 'raw' ); $topic_link = '<a href="' . $topic_permalink . '">' . $topic_title . '</a>'; // Forum $forum_permalink = bbp_get_forum_permalink( $forum_id ); $forum_title = get_post_field( 'post_title', $forum_id, 'raw' ); $forum_link = '<a href="' . $forum_permalink . '">' . $forum_title . '</a>'; // Activity action & text $activity_text = sprintf( esc_html__( '%1$s started the topic %2$s in the forum %3$s', 'bbpress' ), $user_link, $topic_link, $forum_link ); $activity_action = apply_filters( 'bbp_activity_topic_create', $activity_text, $user_id, $topic_id, $forum_id ); $activity_content = apply_filters( 'bbp_activity_topic_create_excerpt', $topic_content ); // Compile and record the activity stream results $activity_id = $this->record_activity( array( 'id' => $this->get_activity_id( $topic_id ), 'user_id' => $user_id, 'action' => $activity_action, 'content' => $activity_content, 'primary_link' => $topic_permalink, 'type' => $this->topic_create, 'item_id' => $topic_id, 'secondary_item_id' => $forum_id, 'recorded_time' => get_post_time( 'Y-m-d H:i:s', true, $topic_id ), 'hide_sitewide' => ! bbp_is_forum_public( $forum_id, false ) ) ); // Add the activity entry ID as a meta value to the topic if ( ! empty( $activity_id ) ) { update_post_meta( $topic_id, '_bbp_activity_id', $activity_id ); } } /** * Delete the activity stream entry when a topic is spammed, trashed, or deleted * * @param int $topic_id */ public function topic_delete( $topic_id = 0 ) { // Get activity ID, bail if it doesn't exist $activity_id = $this->get_activity_id( $topic_id ); if ( ! empty( $activity_id ) ) { return bp_activity_delete( array( 'id' => $activity_id ) ); } return false; } /** * Update the activity stream entry when a topic status changes * * @param int $topic_id * @param obj $post * @return Bail early if not a topic, or topic is by anonymous user */ public function topic_update( $topic_id = 0, $post = null ) { // Bail early if not a topic if ( get_post_type( $post ) !== bbp_get_topic_post_type() ) { return; } // Bail early if revisions are off if ( ! bbp_allow_revisions() || ! post_type_supports( bbp_get_topic_post_type(), 'revisions' ) ) { return; } $topic_id = bbp_get_topic_id( $topic_id ); // Bail early if topic is by anonymous user if ( bbp_is_topic_anonymous( $topic_id ) ) { return; } // Action based on new status if ( bbp_is_topic_public( $post->ID ) ) { // Validate topic data $forum_id = bbp_get_topic_forum_id( $topic_id ); $topic_author_id = bbp_get_topic_author_id( $topic_id ); $this->topic_create( $topic_id, $forum_id, array(), $topic_author_id ); } else { $this->topic_delete( $topic_id ); } } /** Replies ***************************************************************/ /** * Record an activity stream entry when a reply is created * * @since 2.0.0 bbPress (r3395) * * @param int $topic_id * @param int $forum_id * @param array $anonymous_data * @param int $topic_author_id * @return Bail early if topic is by anonymous user */ public function reply_create( $reply_id = 0, $topic_id = 0, $forum_id = 0, $anonymous_data = array(), $reply_author_id = 0 ) { // Do not log activity of anonymous users if ( ! empty( $anonymous_data ) ) { return; } // Bail if site is private if ( ! bbp_is_site_public() ) { return; } // Validate activity data $user_id = bbp_get_user_id( $reply_author_id ); $reply_id = bbp_get_reply_id( $reply_id ); $topic_id = bbp_get_topic_id( $topic_id ); $forum_id = bbp_get_forum_id( $forum_id ); // Bail if user is not active if ( bbp_is_user_inactive( $user_id ) ) { return; } // Bail if reply is not published if ( ! bbp_is_reply_published( $reply_id ) ) { return; } // Setup links for activity stream $user_link = bbp_get_user_profile_link( $user_id ); // Reply $reply_url = bbp_get_reply_url( $reply_id ); $reply_content = get_post_field( 'post_content', $reply_id, 'raw' ); // Topic $topic_permalink = bbp_get_topic_permalink( $topic_id ); $topic_title = get_post_field( 'post_title', $topic_id, 'raw' ); $topic_link = '<a href="' . $topic_permalink . '">' . $topic_title . '</a>'; // Forum $forum_permalink = bbp_get_forum_permalink( $forum_id ); $forum_title = get_post_field( 'post_title', $forum_id, 'raw' ); $forum_link = '<a href="' . $forum_permalink . '">' . $forum_title . '</a>'; // Activity action & text $activity_text = sprintf( esc_html__( '%1$s replied to the topic %2$s in the forum %3$s', 'bbpress' ), $user_link, $topic_link, $forum_link ); $activity_action = apply_filters( 'bbp_activity_reply_create', $activity_text, $user_id, $reply_id, $topic_id ); $activity_content = apply_filters( 'bbp_activity_reply_create_excerpt', $reply_content ); // Compile and record the activity stream results $activity_id = $this->record_activity( array( 'id' => $this->get_activity_id( $reply_id ), 'user_id' => $user_id, 'action' => $activity_action, 'content' => $activity_content, 'primary_link' => $reply_url, 'type' => $this->reply_create, 'item_id' => $reply_id, 'secondary_item_id' => $topic_id, 'recorded_time' => get_post_time( 'Y-m-d H:i:s', true, $reply_id ), 'hide_sitewide' => ! bbp_is_forum_public( $forum_id, false ) ) ); // Add the activity entry ID as a meta value to the reply if ( ! empty( $activity_id ) ) { update_post_meta( $reply_id, '_bbp_activity_id', $activity_id ); } } /** * Delete the activity stream entry when a reply is spammed, trashed, or deleted * * @param int $reply_id */ public function reply_delete( $reply_id ) { // Get activity ID, bail if it doesn't exist $activity_id = $this->get_activity_id( $reply_id ); if ( ! empty( $activity_id ) ) { return bp_activity_delete( array( 'id' => $activity_id ) ); } return false; } /** * Update the activity stream entry when a reply status changes * * @param int $reply_id * @param obj $post * @return Bail early if not a reply, or reply is by anonymous user */ public function reply_update( $reply_id, $post ) { // Bail early if not a reply if ( get_post_type( $post ) !== bbp_get_reply_post_type() ) { return; } // Bail early if revisions are off if ( ! bbp_allow_revisions() || ! post_type_supports( bbp_get_reply_post_type(), 'revisions' ) ) { return; } $reply_id = bbp_get_reply_id( $reply_id ); // Bail early if reply is by anonymous user if ( bbp_is_reply_anonymous( $reply_id ) ) { return; } // Action based on new status if ( bbp_get_public_status_id() === $post->post_status ) { // Validate reply data $topic_id = bbp_get_reply_topic_id( $reply_id ); $forum_id = bbp_get_reply_forum_id( $reply_id ); $reply_author_id = bbp_get_reply_author_id( $reply_id ); $this->reply_create( $reply_id, $topic_id, $forum_id, array(), $reply_author_id ); } else { $this->reply_delete( $reply_id ); } } } endif;