/**
  * Constructor.
  *
  * @since 1.6.0
  */
 public function __construct()
 {
     // See if activity commenting is enabled for blog / forum activity items.
     $this->disable_blogforum_comments = bp_disable_blogforum_comments();
     // Define singular and plural labels, as well as whether we support AJAX.
     parent::__construct(array('ajax' => false, 'plural' => 'activities', 'singular' => 'activity', 'screen' => get_current_screen()));
 }
/**
 * Allow activity comments on blog posts and forum posts
 *
 * @since BuddyPress (1.6)
 */
function bp_admin_setting_callback_blogforum_comments() {
?>

	<input id="bp-disable-blogforum-comments" name="bp-disable-blogforum-comments" type="checkbox" value="1" <?php checked( !bp_disable_blogforum_comments( false ) ); ?> />
	<label for="bp-disable-blogforum-comments"><?php _e( 'Allow activity stream commenting on blog and forum posts', 'buddypress' ); ?></label>

<?php
}
/**
 * Disable activity commenting for blog posts based on certain criteria.
 *
 * If activity commenting is enabled for blog posts, we still need to disable
 * commenting if:
 *  - comments are disabled for the WP blog post from the admin dashboard
 *  - the WP blog post is supposed to be automatically closed from comments
 *    based on a certain age
 *  - the activity entry is a 'new_blog_comment' type
 *
 * @since BuddyPress (2.0.0)
 *
 * @param bool $retval Is activity commenting enabled for this activity entry?
 * @return bool
 */
function bp_blogs_disable_activity_commenting( $retval ) {
	// if activity commenting is disabled, return current value
	if ( bp_disable_blogforum_comments() ) {
		return $retval;
	}

	// activity commenting is enabled for blog posts
	switch ( bp_get_activity_action_name() ) {

		// we still have to disable activity commenting for 'new_blog_comment' items
		// commenting should only be done on the parent 'new_blog_post' item
		case 'new_blog_comment' :
			$retval = false;

			break;

		// check if commenting is disabled for the WP blog post
		// we should extrapolate this and automate this for plugins... or not
		case 'new_blog_post' :
			global $activities_template;

			// setup some globals we'll need to reference later
			bp_blogs_setup_activity_loop_globals( $activities_template->activity );

			// if comments are closed for the WP blog post, we should disable
			// activity comments for this activity entry
			if ( empty( buddypress()->blogs->allow_comments[bp_get_activity_id()] ) ) {
				$retval = false;
			}

			break;
	}

	return $retval;
}
/**
 * Formats single activity comment entries to use the blog comment action.
 *
 * This is only done if the activity comment is associated with a blog comment.
 *
 * @since 2.0.1
 *
 * @param string               $retval   The activity action.
 * @param BP_Activity_Activity $activity Activity object.
 * @return string
 */
function bp_blogs_activity_comment_single_action($retval, $activity)
{
    if ('activity_comment' !== $activity->type) {
        return $retval;
    }
    if (bp_disable_blogforum_comments()) {
        return $retval;
    }
    $parent_activity = new BP_Activity_Activity($activity->item_id);
    if (!isset($parent_activity->type)) {
        return $retval;
    }
    $post_type = bp_activity_post_type_get_tracking_arg($parent_activity->type, 'post_type');
    if (!$post_type) {
        return $retval;
    }
    $blog_comment_id = bp_activity_get_meta($activity->id, "bp_blogs_{$post_type}_comment_id");
    if (!empty($blog_comment_id)) {
        $bp = buddypress();
        // Check if a comment action id is set for the parent activity
        $comment_action_id = bp_activity_post_type_get_tracking_arg($parent_activity->type, 'comment_action_id');
        // Use the action string callback for the activity type
        if (!empty($comment_action_id)) {
            // Fake a 'new_{post_type}_comment' by cloning the activity object.
            $object = clone $activity;
            // Set the type of the activity to be a comment about a post type
            $object->type = $comment_action_id;
            // Use the blog ID as the item_id.
            $object->item_id = $parent_activity->item_id;
            // Use comment ID as the secondary_item_id.
            $object->secondary_item_id = $blog_comment_id;
            // Get the format callback for this activity comment
            $format_callback = bp_activity_post_type_get_tracking_arg($comment_action_id, 'format_callback');
            // now format the activity action using the 'new_{post_type}_comment' action callback
            if (is_callable($format_callback)) {
                $retval = call_user_func_array($format_callback, array('', $object));
            }
        }
    }
    return $retval;
}
/**
 * Remove an activity item when a comment about a post type is deleted.
 *
 * @since 2.5.0
 *
 * @param  int    $comment_id           ID of the comment.
 * @param  object $activity_post_object The post type tracking args object.
 *
 * @return bool True on success. False on error.
 */
function bp_activity_post_type_remove_comment($comment_id = 0, $activity_post_object = null)
{
    if (empty($activity_post_object)) {
        $comment = get_comment($comment_id);
        if (!$comment) {
            return;
        }
        $post_type = get_post_type($comment->comment_post_ID);
        if (!$post_type) {
            return;
        }
        // Get the post type tracking args.
        $activity_post_object = bp_activity_get_post_type_tracking_args($post_type);
        // Bail if the activity type does not exist
        if (empty($activity_post_object->comments_tracking->action_id)) {
            return false;
        }
    }
    // Set the $activity_comment_object
    $activity_comment_object = $activity_post_object->comments_tracking;
    if (empty($activity_comment_object->action_id)) {
        return false;
    }
    $deleted = false;
    if (bp_disable_blogforum_comments()) {
        $deleted = bp_activity_delete_by_item_id(array('item_id' => get_current_blog_id(), 'secondary_item_id' => $comment_id, 'component' => $activity_comment_object->component_id, 'type' => $activity_comment_object->action_id, 'user_id' => false));
    }
    /**
     * Fires after the custom post type comment activity was removed.
     *
     * @since 2.5.0
     *
     * @param bool       $deleted              True if the activity was deleted false otherwise
     * @param WP_Comment $comment              Comment object.
     * @param object     $activity_post_object The post type tracking args object.
     * @param string     $value                The post type comment activity type.
     */
    do_action('bp_activity_post_type_remove_comment', $deleted, $comment_id, $activity_post_object, $activity_comment_object->action_id);
    return $deleted;
}
/**
 * When a blog comment status transition occurs, update the relevant activity's status.
 *
 * @since BuddyPress (1.6.0)
 *
 * @global object $bp BuddyPress global settings.
 *
 * @param string $new_status New comment status.
 * @param string $old_status Previous comment status.
 * @param object $comment Comment data.
 */
function bp_blogs_transition_activity_status($new_status, $old_status, $comment)
{
    global $bp;
    // Check the Activity component is active
    if (!bp_is_active('activity')) {
        return;
    }
    /**
     * Activity currently doesn't have any concept of a trash, or an unapproved/approved state.
     *
     * If a blog comment transitions to a "delete" or "hold" status, delete the activity item.
     * If a blog comment transitions to trashed, or spammed, mark the activity as spam.
     * If a blog comment transitions to approved (and the activity exists), mark the activity as ham.
     * If a blog comment transitions to unapproved (and the activity exists), mark the activity as spam.
     * Otherwise, record the comment into the activity stream.
     */
    // This clause was moved in from bp_blogs_remove_comment() in BuddyPress 1.6. It handles delete/hold.
    if (in_array($new_status, array('delete', 'hold'))) {
        return bp_blogs_remove_comment($comment->comment_ID);
        // These clauses handle trash, spam, and un-spams.
    } elseif (in_array($new_status, array('trash', 'spam', 'unapproved'))) {
        $action = 'spam_activity';
    } elseif ('approved' == $new_status) {
        $action = 'ham_activity';
    }
    // Get the activity
    if (bp_disable_blogforum_comments()) {
        $activity_id = bp_activity_get_activity_id(array('component' => $bp->blogs->id, 'item_id' => get_current_blog_id(), 'secondary_item_id' => $comment->comment_ID, 'type' => 'new_blog_comment'));
    } else {
        $activity_id = get_comment_meta($comment->comment_ID, 'bp_activity_comment_id', true);
    }
    // Check activity item exists
    if (empty($activity_id)) {
        // If no activity exists, but the comment has been approved, record it into the activity table.
        if ('approved' == $new_status) {
            return bp_blogs_record_comment($comment->comment_ID, true);
        }
        return;
    }
    // Create an activity object
    $activity = new BP_Activity_Activity($activity_id);
    if (empty($activity->component)) {
        return;
    }
    // Spam/ham the activity if it's not already in that state
    if ('spam_activity' == $action && !$activity->is_spam) {
        bp_activity_mark_as_spam($activity);
    } elseif ('ham_activity' == $action) {
        bp_activity_mark_as_ham($activity);
    }
    // Add "new_blog_comment" to the whitelisted activity types, so that the activity's Akismet history is generated
    $comment_akismet_history = create_function('$t', '$t[] = "new_blog_comment"; return $t;');
    add_filter('bp_akismet_get_activity_types', $comment_akismet_history);
    // Save the updated activity
    $activity->save();
    // Remove the "new_blog_comment" activity type whitelist so we don't break anything
    remove_filter('bp_akismet_get_activity_types', $comment_akismet_history);
}
/**
 * Add a notification for post comments to the post author or post commenter.
 *
 * Requires "activity stream commenting on blog and forum posts" to be enabled.
 *
 * @since 2.6.0
 *
 * @param int        $activity_id          The activity comment ID.
 * @param WP_Comment $post_type_comment    WP Comment object.
 * @param array      $activity_args        Activity comment arguments.
 * @param object     $activity_post_object The post type tracking args object.
 */
function bp_activity_add_notification_for_synced_blog_comment($activity_id, $post_type_comment, $activity_args, $activity_post_object)
{
    // If activity comments are disabled for WP posts, stop now!
    if (bp_disable_blogforum_comments() || empty($activity_id)) {
        return;
    }
    // Send a notification to the blog post author.
    if ((int) $post_type_comment->post->post_author !== (int) $activity_args['user_id']) {
        // Only add a notification if comment author is a registered user.
        // @todo Should we remove this restriction?
        if (!empty($post_type_comment->user_id)) {
            bp_notifications_add_notification(array('user_id' => $post_type_comment->post->post_author, 'item_id' => $activity_id, 'secondary_item_id' => $post_type_comment->user_id, 'component_name' => buddypress()->activity->id, 'component_action' => 'update_reply', 'date_notified' => $post_type_comment->comment_date_gmt, 'is_new' => 1));
        }
    }
    // Send a notification to the parent comment author for follow-up comments.
    if (!empty($post_type_comment->comment_parent)) {
        $parent_comment = get_comment($post_type_comment->comment_parent);
        if (!empty($parent_comment->user_id) && (int) $parent_comment->user_id !== (int) $activity_args['user_id']) {
            bp_notifications_add_notification(array('user_id' => $parent_comment->user_id, 'item_id' => $activity_id, 'secondary_item_id' => $post_type_comment->user_id, 'component_name' => buddypress()->activity->id, 'component_action' => 'comment_reply', 'date_notified' => $post_type_comment->comment_date_gmt, 'is_new' => 1));
        }
    }
}
/**
 * When a post type comment status transition occurs, update the relevant activity's status.
 *
 * @since 2.5.0
 *
 * @param string     $new_status New comment status.
 * @param string     $old_status Previous comment status.
 * @param WP_Comment $comment Comment data.
 */
function bp_activity_transition_post_type_comment_status($new_status, $old_status, $comment)
{
    $post_type = get_post_type($comment->comment_post_ID);
    if (!$post_type) {
        return;
    }
    // Get the post type tracking args.
    $activity_post_object = bp_activity_get_post_type_tracking_args($post_type);
    // Bail if the activity type does not exist
    if (empty($activity_post_object->comments_tracking->action_id)) {
        return false;
        // Set the $activity_comment_object
    } else {
        $activity_comment_object = $activity_post_object->comments_tracking;
    }
    // Init an empty activity ID
    $activity_id = 0;
    /**
     * Activity currently doesn't have any concept of a trash, or an unapproved/approved state.
     *
     * If a blog comment transitions to a "delete" or "hold" status, delete the activity item.
     * If a blog comment transitions to trashed, or spammed, mark the activity as spam.
     * If a blog comment transitions to approved (and the activity exists), mark the activity as ham.
     * If a blog comment transitions to unapproved (and the activity exists), mark the activity as spam.
     * Otherwise, record the comment into the activity stream.
     */
    // This clause handles delete/hold.
    if (in_array($new_status, array('delete', 'hold'))) {
        return bp_activity_post_type_remove_comment($comment->comment_ID, $activity_post_object);
        // These clauses handle trash, spam, and un-spams.
    } elseif (in_array($new_status, array('trash', 'spam', 'unapproved'))) {
        $action = 'spam_activity';
    } elseif ('approved' == $new_status) {
        $action = 'ham_activity';
    }
    // Get the activity
    if (bp_disable_blogforum_comments()) {
        $activity_id = bp_activity_get_activity_id(array('component' => $activity_comment_object->component_id, 'item_id' => get_current_blog_id(), 'secondary_item_id' => $comment->comment_ID, 'type' => $activity_comment_object->action_id));
    } else {
        $activity_id = get_comment_meta($comment->comment_ID, 'bp_activity_comment_id', true);
    }
    /**
     * Leave a chance to plugins to manage activity comments differently.
     *
     * @since  2.5.0
     *
     * @param bool        $value       True to override BuddyPress management.
     * @param string      $post_type   The post type name.
     * @param int         $activity_id The post type activity (0 if not found).
     * @param string      $new_status  The new status of the post type comment.
     * @param string      $old_status  The old status of the post type comment.
     * @param WP_Comment  $comment Comment data.
     */
    if (true === apply_filters('bp_activity_pre_transition_post_type_comment_status', false, $post_type, $activity_id, $new_status, $old_status, $comment)) {
        return false;
    }
    // Check activity item exists
    if (empty($activity_id)) {
        // If no activity exists, but the comment has been approved, record it into the activity table.
        if ('approved' == $new_status) {
            return bp_activity_post_type_comment($comment->comment_ID, true, $activity_post_object);
        }
        return;
    }
    // Create an activity object
    $activity = new BP_Activity_Activity($activity_id);
    if (empty($activity->component)) {
        return;
    }
    // Spam/ham the activity if it's not already in that state
    if ('spam_activity' === $action && !$activity->is_spam) {
        bp_activity_mark_as_spam($activity);
    } elseif ('ham_activity' == $action) {
        bp_activity_mark_as_ham($activity);
    }
    // Add "new_post_type_comment" to the whitelisted activity types, so that the activity's Akismet history is generated
    $post_type_comment_action = $activity_comment_object->action_id;
    $comment_akismet_history = create_function('$t', '$t[] = $post_type_comment_action; return $t;');
    add_filter('bp_akismet_get_activity_types', $comment_akismet_history);
    // Make sure the activity change won't edit the comment if sync is on
    remove_action('bp_activity_before_save', 'bp_blogs_sync_activity_edit_to_post_comment', 20);
    // Save the updated activity
    $activity->save();
    // Restore the action
    add_action('bp_activity_before_save', 'bp_blogs_sync_activity_edit_to_post_comment', 20);
    // Remove the "new_blog_comment" activity type whitelist so we don't break anything
    remove_filter('bp_akismet_get_activity_types', $comment_akismet_history);
}
/**
 * Remove a synced activity comment from the activity stream.
 *
 * @since 2.5.0
 *
 * @param bool   $deleted              True when a comment post type activity was successfully removed.
 * @param int    $comment_id           ID of the comment to be removed.
 * @param object $activity_post_object The post type tracking args object.
 * @param string $activity_type        The post type comment activity type.
 *
 * @return bool True on success. False on error.
 */
function bp_blogs_post_type_remove_comment($deleted, $comment_id, $activity_post_object, $activity_type = '')
{
    // Remove synced activity comments, if needed.
    if (!bp_disable_blogforum_comments()) {
        // Get associated activity ID from comment meta
        $activity_id = get_comment_meta($comment_id, 'bp_activity_comment_id', true);
        /**
         * Delete the associated activity comment & also remove
         * child post comments and associated activity comments.
         */
        if (!empty($activity_id)) {
            // fetch the activity comments for the activity item
            $activity = bp_activity_get(array('in' => $activity_id, 'display_comments' => 'stream', 'spam' => 'all'));
            // get all activity comment IDs for the pending deleted item
            if (!empty($activity['activities'])) {
                $activity_ids = bp_activity_recurse_comments_activity_ids($activity);
                $activity_ids[] = $activity_id;
                // delete activity items
                foreach ($activity_ids as $activity_id) {
                    bp_activity_delete(array('id' => $activity_id));
                }
                // remove associated blog comments
                bp_blogs_remove_associated_blog_comments($activity_ids);
                // rebuild activity comment tree
                BP_Activity_Activity::rebuild_activity_comment_tree($activity['activities'][0]->item_id);
                // Set the result
                $deleted = true;
            }
        }
    }
    // Backcompat for comments about the 'post' post type.
    if ('new_blog_comment' === $activity_type) {
        /**
         * Fires after a blog comment activity item was removed from activity stream.
         *
         * @since 1.0.0
         *
         * @param int $value      ID for the blog associated with the removed comment.
         * @param int $comment_id ID of the comment being removed.
         * @param int $value      ID of the current logged in user.
         */
        do_action('bp_blogs_remove_comment', get_current_blog_id(), $comment_id, bp_loggedin_user_id());
    }
    return $deleted;
}