_Activity::hide_all_for_user( $user_id ); } /** * Take content, remove images, and replace them with a single thumbnail image. * * The format of items in the activity stream is such that we do not want to * allow an arbitrary number of arbitrarily large images to be rendered. * However, the activity stream is built to elegantly display a single * thumbnail corresponding to the activity comment. This function looks * through the content, grabs the first image and converts it to a thumbnail, * and removes the rest of the images from the string. * * As of BuddyPress 2.3, this function is no longer in use. * * @since 1.2.0 * * @param string $content The content of the activity item. * @param string|bool $link Optional. The unescaped URL that the image should link * to. If absent, the image will not be a link. * @param array|bool $args Optional. The args passed to the activity * creation function (eg bp_blogs_record_activity()). * @return string $content The content with images stripped and replaced with a * single thumb. */ function bp_activity_thumbnail_content_images( $content, $link = false, $args = false ) { preg_match_all( '/]*>/Ui', $content, $matches ); // Remove tags. Also remove caption shortcodes and caption text if present. $content = preg_replace('|(\[caption(.*?)\])?]*>([^\[\[]*\[\/caption\])?|', '', $content ); if ( !empty( $matches ) && !empty( $matches[0] ) ) { // Get the SRC value. preg_match( '/]{1}/i', $matches[0][0], $src ); // Get the width and height. preg_match( '/]{1}/i', $matches[0][0], $height ); preg_match( '/]{1}/i', $matches[0][0], $width ); if ( ! empty( $src ) ) { $src = substr( substr( str_replace( 'src=', '', $src[1] ), 0, -1 ), 1 ); if ( isset( $width[1] ) ) { $width = substr( substr( str_replace( 'width=', '', $width[1] ), 0, -1 ), 1 ); } if ( isset( $height[1] ) ) { $height = substr( substr( str_replace( 'height=', '', $height[1] ), 0, -1 ), 1 ); } if ( empty( $width ) || empty( $height ) ) { $width = 100; $height = 100; } $ratio = (int) $width / (int) $height; $new_height = (int) $height >= 100 ? 100 : $height; $new_width = $new_height * $ratio; $image = '' . __( 'Thumbnail', 'buddypress' ) . ''; if ( !empty( $link ) ) { $image = '' . $image . ''; } $content = $image . $content; } } /** * Filters the activity content that had a thumbnail replace images. * * @since 1.2.0 * * @param string $content Activity content that had images replaced in. * @param array $matches Array of all image tags found in the posted content. * @param array $args Arguments passed into function creating the activity update. */ return apply_filters( 'bp_activity_thumbnail_content_images', $content, $matches, $args ); } /** * Gets the excerpt length for activity items. * * @since 2.8.0 * * @return int Character length for activity excerpts. */ function bp_activity_get_excerpt_length() { /** * Filters the excerpt length for the activity excerpt. * * @since 1.5.0 * * @param int Character length for activity excerpts. */ return (int) apply_filters( 'bp_activity_excerpt_length', 358 ); } /** * Create a rich summary of an activity item for the activity stream. * * More than just a simple excerpt, the summary could contain oEmbeds and other types of media. * Currently, it's only used for blog post items, but it will probably be used for all types of * activity in the future. * * @since 2.3.0 * * @param string $content The content of the activity item. * @param array $activity The data passed to bp_activity_add() or the values * from an Activity obj. * @return string $summary */ function bp_activity_create_summary( $content, $activity ) { $args = array( 'width' => isset( $GLOBALS['content_width'] ) ? (int) $GLOBALS['content_width'] : 'medium', ); $post_url = ''; $post_title = ''; $bp_excerpt_args = array( 'html' => false, 'filter_shortcodes' => true, 'strip_tags' => true, 'remove_links' => true, ); // Get the WP_Post object if this activity type is a blog post. if ( $activity['type'] === 'new_blog_post' ) { $content = get_post( $activity['secondary_item_id'] ); $post_url = $content->guid; $post_title = sprintf( '%2$s', esc_url( $post_url ), esc_html( $content->post_title ) ); $more_text = sprintf( '%s', trim( __( ' […]', 'buddypress' ) ) ); /** This filter is documented in wp-admin/includes/post-template.php */ $bp_excerpt_args['ending'] = apply_filters( 'the_content_more_link', sprintf( ' %2$s', esc_url( $post_url ), $more_text ), $more_text ); } /** * Filter the class name of the media extractor when creating an Activity summary. * * Use this filter to change the media extractor used to extract media info for the activity item. * * @since 2.3.0 * * @param string $extractor Class name. * @param string $content The content of the activity item. * @param array $activity The data passed to bp_activity_add() or the values from an Activity obj. */ $extractor = apply_filters( 'bp_activity_create_summary_extractor_class', 'BP_Media_Extractor', $content, $activity ); $extractor = new $extractor; /** * Filter the arguments passed to the media extractor when creating an Activity summary. * * @since 2.3.0 * * @param array $args Array of bespoke data for the media extractor. * @param string $content The content of the activity item. * @param array $activity The data passed to bp_activity_add() or the values from an Activity obj. * @param BP_Media_Extractor $extractor The media extractor object. */ $args = apply_filters( 'bp_activity_create_summary_extractor_args', $args, $content, $activity, $extractor ); // Extract media information from the $content. $media = $extractor->extract( $content, BP_Media_Extractor::ALL, $args ); // If we converted $content to an object earlier, flip it back to a string. if ( is_a( $content, 'WP_Post' ) ) { $content = $content->post_content; } $para_count = substr_count( strtolower( wpautop( $content ) ), '

' ); $has_audio = ! empty( $media['has']['audio'] ) && $media['has']['audio']; $has_videos = ! empty( $media['has']['videos'] ) && $media['has']['videos']; $has_feat_image = ! empty( $media['has']['featured_images'] ) && $media['has']['featured_images']; $has_galleries = ! empty( $media['has']['galleries'] ) && $media['has']['galleries']; $has_images = ! empty( $media['has']['images'] ) && $media['has']['images']; $has_embeds = false; // Embeds must be subtracted from the paragraph count. if ( ! empty( $media['has']['embeds'] ) ) { $has_embeds = $media['has']['embeds'] > 0; $para_count -= $media['has']['embeds']; } $extracted_media = array(); $use_media_type = ''; $image_source = ''; // If it's a short article and there's an embed/audio/video, use it. if ( $para_count <= 3 ) { if ( $has_embeds ) { $use_media_type = 'embeds'; } elseif ( $has_audio ) { $use_media_type = 'audio'; } elseif ( $has_videos ) { $use_media_type = 'videos'; } } // If not, or in any other situation, try to use an image. if ( ! $use_media_type && $has_images ) { $use_media_type = 'images'; $image_source = 'html'; // Featured Image > Galleries > inline . if ( $has_feat_image ) { $image_source = 'featured_images'; } elseif ( $has_galleries ) { $image_source = 'galleries'; } } // Extract an item from the $media results. if ( $use_media_type ) { if ( $use_media_type === 'images' ) { $extracted_media = wp_list_filter( $media[ $use_media_type ], array( 'source' => $image_source ) ); $extracted_media = array_shift( $extracted_media ); } else { $extracted_media = array_shift( $media[ $use_media_type ] ); } /** * Filter the results of the media extractor when creating an Activity summary. * * @since 2.3.0 * * @param array $extracted_media Extracted media item. See {@link BP_Media_Extractor::extract()} for format. * @param string $content Content of the activity item. * @param array $activity The data passed to bp_activity_add() or the values from an Activity obj. * @param array $media All results from the media extraction. * See {@link BP_Media_Extractor::extract()} for format. * @param string $use_media_type The kind of media item that was preferentially extracted. * @param string $image_source If $use_media_type was "images", the preferential source of the image. * Otherwise empty. */ $extracted_media = apply_filters( 'bp_activity_create_summary_extractor_result', $extracted_media, $content, $activity, $media, $use_media_type, $image_source ); } // Generate a text excerpt for this activity item (and remove any oEmbeds URLs). $summary_parts = array( str_replace( array( "\n", "\r" ), ' ', trim( bp_create_excerpt( html_entity_decode( $content ), 225, $bp_excerpt_args ) ) ), ); if ( $use_media_type === 'embeds' ) { $summary_parts[] = PHP_EOL . PHP_EOL . $extracted_media['url']; } elseif ( $use_media_type === 'images' ) { $extracted_media_url = isset( $extracted_media['url'] ) ? $extracted_media['url'] : ''; $image_tag = sprintf( ' ', esc_url( $extracted_media_url ) ); if ( $post_url ) { $image_tag = sprintf( '%2$s ', esc_url( $post_url ), trim( $image_tag ) ); array_unshift( $summary_parts, $image_tag ); } } elseif ( in_array( $use_media_type, array( 'audio', 'videos' ), true ) ) { $summary_parts[] = PHP_EOL . PHP_EOL . $extracted_media['original']; // Full shortcode. } if ( $post_title ) { array_unshift( $summary_parts, $post_title ); } // Join summary parts. $summary = implode( '', $summary_parts ); /** * Filters the newly-generated summary for the activity item. * * @since 2.3.0 * * @param string $summary Activity summary HTML. * @param string $content Content of the activity item. * @param array $activity The data passed to bp_activity_add() or the values from an Activity obj. * @param array $extracted_media Media item extracted. See {@link BP_Media_Extractor::extract()} for format. */ return apply_filters( 'bp_activity_create_summary', $summary, $content, $activity, $extracted_media ); } /** * Fetch whether the current user is allowed to mark items as spam. * * @since 1.6.0 * * @return bool True if user is allowed to mark activity items as spam. */ function bp_activity_user_can_mark_spam() { /** * Filters whether the current user should be able to mark items as spam. * * @since 1.6.0 * * @param bool $moderate Whether or not the current user has bp_moderate capability. */ return apply_filters( 'bp_activity_user_can_mark_spam', bp_current_user_can( 'bp_moderate' ) ); } /** * Mark an activity item as spam. * * @since 1.6.0 * * @todo We should probably save $source to activity meta. * * @param BP_Activity_Activity $activity The activity item to be spammed. * @param string $source Optional. Default is "by_a_person" (ie, a person has * manually marked the activity as spam). BP core also * accepts 'by_akismet'. */ function bp_activity_mark_as_spam( &$activity, $source = 'by_a_person' ) { $bp = buddypress(); $activity->is_spam = 1; // Clear the activity stream first page cache. wp_cache_delete( 'bp_activity_sitewide_front', 'bp' ); if ( 'activity_comment' === $activity->type ) { $activity_id = $activity->item_id; } else { $activity_id = $activity->id; } // Clear the activity comment cache for this activity item. wp_cache_delete( $activity_id, 'bp_activity_comments' ); // If Akismet is active, and this was a manual spam/ham request, stop Akismet checking the activity. if ( 'by_a_person' == $source && !empty( $bp->activity->akismet ) ) { remove_action( 'bp_activity_before_save', array( $bp->activity->akismet, 'check_activity' ), 4 ); // Build data package for Akismet. $activity_data = BP_Akismet::build_akismet_data_package( $activity ); // Tell Akismet this is spam. $activity_data = $bp->activity->akismet->send_akismet_request( $activity_data, 'submit', 'spam' ); // Update meta. add_action( 'bp_activity_after_save', array( $bp->activity->akismet, 'update_activity_spam_meta' ), 1, 1 ); } /** * Fires at the end of the process to mark an activity item as spam. * * @since 1.6.0 * * @param BP_Activity_Activity $activity Activity item being marked as spam. * @param string $source Source of determination of spam status. For example * "by_a_person" or "by_akismet". */ do_action( 'bp_activity_mark_as_spam', $activity, $source ); } /** * Mark an activity item as ham. * * @since 1.6.0 * * @param BP_Activity_Activity $activity The activity item to be hammed. Passed by reference. * @param string $source Optional. Default is "by_a_person" (ie, a person has * manually marked the activity as spam). BP core also accepts * 'by_akismet'. */ function bp_activity_mark_as_ham( &$activity, $source = 'by_a_person' ) { $bp = buddypress(); $activity->is_spam = 0; // Clear the activity stream first page cache. wp_cache_delete( 'bp_activity_sitewide_front', 'bp' ); if ( 'activity_comment' === $activity->type ) { $activity_id = $activity->item_id; } else { $activity_id = $activity->id; } // Clear the activity comment cache for this activity item. wp_cache_delete( $activity_id, 'bp_activity_comments' ); // If Akismet is active, and this was a manual spam/ham request, stop Akismet checking the activity. if ( 'by_a_person' == $source && !empty( $bp->activity->akismet ) ) { remove_action( 'bp_activity_before_save', array( $bp->activity->akismet, 'check_activity' ), 4 ); // Build data package for Akismet. $activity_data = BP_Akismet::build_akismet_data_package( $activity ); // Tell Akismet this is spam. $activity_data = $bp->activity->akismet->send_akismet_request( $activity_data, 'submit', 'ham' ); // Update meta. add_action( 'bp_activity_after_save', array( $bp->activity->akismet, 'update_activity_ham_meta' ), 1, 1 ); } /** * Fires at the end of the process to mark an activity item as ham. * * @since 1.6.0 * * @param BP_Activity_Activity $activity Activity item being marked as ham. * @param string $source Source of determination of ham status. For example * "by_a_person" or "by_akismet". */ do_action( 'bp_activity_mark_as_ham', $activity, $source ); } /* Emails *********************************************************************/ /** * Send email and BP notifications when a user is mentioned in an update. * * @since 1.2.0 * * @param int $activity_id The ID of the activity update. * @param int $receiver_user_id The ID of the user who is receiving the update. */ function bp_activity_at_message_notification( $activity_id, $receiver_user_id ) { $notifications = BP_Core_Notification::get_all_for_user( $receiver_user_id, 'all' ); // Don't leave multiple notifications for the same activity item. foreach ( $notifications as $notification ) { if ( $activity_id == $notification->item_id ) { return; } } $activity = new BP_Activity_Activity( $activity_id ); $email_type = 'activity-at-message'; $group_name = ''; $message_link = bp_activity_get_permalink( $activity_id ); $poster_name = bp_core_get_user_displayname( $activity->user_id ); remove_filter( 'bp_get_activity_content_body', 'convert_smilies' ); remove_filter( 'bp_get_activity_content_body', 'wpautop' ); remove_filter( 'bp_get_activity_content_body', 'bp_activity_truncate_entry', 5 ); /** This filter is documented in bp-activity/bp-activity-template.php */ $content = apply_filters_ref_array( 'bp_get_activity_content_body', array( $activity->content, &$activity ) ); add_filter( 'bp_get_activity_content_body', 'convert_smilies' ); add_filter( 'bp_get_activity_content_body', 'wpautop' ); add_filter( 'bp_get_activity_content_body', 'bp_activity_truncate_entry', 5 ); // Now email the user with the contents of the message (if they have enabled email notifications). if ( 'no' != bp_get_user_meta( $receiver_user_id, 'notification_activity_new_mention', true ) ) { if ( bp_is_active( 'groups' ) && bp_is_group() ) { $email_type = 'groups-at-message'; $group_name = bp_get_current_group_name(); } $unsubscribe_args = array( 'user_id' => $receiver_user_id, 'notification_type' => $email_type, ); $args = array( 'tokens' => array( 'activity' => $activity, 'usermessage' => wp_strip_all_tags( $content ), 'group.name' => $group_name, 'mentioned.url' => $message_link, 'poster.name' => $poster_name, 'receiver-user.id' => $receiver_user_id, 'unsubscribe' => esc_url( bp_email_get_unsubscribe_link( $unsubscribe_args ) ), ), ); bp_send_email( $email_type, $receiver_user_id, $args ); } /** * Fires after the sending of an @mention email notification. * * @since 1.5.0 * @since 2.5.0 $subject, $message, $content arguments unset and deprecated. * * @param BP_Activity_Activity $activity Activity Item object. * @param string $deprecated Removed in 2.5; now an empty string. * @param string $deprecated Removed in 2.5; now an empty string. * @param string $deprecated Removed in 2.5; now an empty string. * @param int $receiver_user_id The ID of the user who is receiving the update. */ do_action( 'bp_activity_sent_mention_email', $activity, '', '', '', $receiver_user_id ); } /** * Send email and BP notifications when an activity item receives a comment. * * @since 1.2.0 * @since 2.5.0 Updated to use new email APIs. * * @param int $comment_id The comment id. * @param int $commenter_id The ID of the user who posted the comment. * @param array $params {@link bp_activity_new_comment()}. */ function bp_activity_new_comment_notification( $comment_id = 0, $commenter_id = 0, $params = array() ) { $original_activity = new BP_Activity_Activity( $params['activity_id'] ); $poster_name = bp_core_get_user_displayname( $commenter_id ); $thread_link = bp_activity_get_permalink( $params['activity_id'] ); remove_filter( 'bp_get_activity_content_body', 'convert_smilies' ); remove_filter( 'bp_get_activity_content_body', 'wpautop' ); remove_filter( 'bp_get_activity_content_body', 'bp_activity_truncate_entry', 5 ); /** This filter is documented in bp-activity/bp-activity-template.php */ $content = apply_filters_ref_array( 'bp_get_activity_content_body', array( $params['content'], &$original_activity ) ); add_filter( 'bp_get_activity_content_body', 'convert_smilies' ); add_filter( 'bp_get_activity_content_body', 'wpautop' ); add_filter( 'bp_get_activity_content_body', 'bp_activity_truncate_entry', 5 ); if ( $original_activity->user_id != $commenter_id ) { // Send an email if the user hasn't opted-out. if ( 'no' != bp_get_user_meta( $original_activity->user_id, 'notification_activity_new_reply', true ) ) { $unsubscribe_args = array( 'user_id' => $original_activity->user_id, 'notification_type' => 'activity-comment', ); $args = array( 'tokens' => array( 'comment.id' => $comment_id, 'commenter.id' => $commenter_id, 'usermessage' => wp_strip_all_tags( $content ), 'original_activity.user_id' => $original_activity->user_id, 'poster.name' => $poster_name, 'thread.url' => esc_url( $thread_link ), 'unsubscribe' => esc_url( bp_email_get_unsubscribe_link( $unsubscribe_args ) ), ), ); bp_send_email( 'activity-comment', $original_activity->user_id, $args ); } /** * Fires at the point that notifications should be sent for activity comments. * * @since 2.6.0 * * @param BP_Activity_Activity $original_activity The original activity. * @param int $comment_id ID for the newly received comment. * @param int $commenter_id ID of the user who made the comment. * @param array $params Arguments used with the original activity comment. */ do_action( 'bp_activity_sent_reply_to_update_notification', $original_activity, $comment_id, $commenter_id, $params ); } /* * If this is a reply to another comment, send an email notification to the * author of the immediate parent comment. */ if ( empty( $params['parent_id'] ) || ( $params['activity_id'] == $params['parent_id'] ) ) { return; } $parent_comment = new BP_Activity_Activity( $params['parent_id'] ); if ( $parent_comment->user_id != $commenter_id && $original_activity->user_id != $parent_comment->user_id ) { // Send an email if the user hasn't opted-out. if ( 'no' != bp_get_user_meta( $parent_comment->user_id, 'notification_activity_new_reply', true ) ) { $unsubscribe_args = array( 'user_id' => $parent_comment->user_id, 'notification_type' => 'activity-comment-author', ); $args = array( 'tokens' => array( 'comment.id' => $comment_id, 'commenter.id' => $commenter_id, 'usermessage' => wp_strip_all_tags( $content ), 'parent-comment-user.id' => $parent_comment->user_id, 'poster.name' => $poster_name, 'thread.url' => esc_url( $thread_link ), 'unsubscribe' => esc_url( bp_email_get_unsubscribe_link( $unsubscribe_args ) ), ), ); bp_send_email( 'activity-comment-author', $parent_comment->user_id, $args ); } /** * Fires at the point that notifications should be sent for comments on activity replies. * * @since 2.6.0 * * @param BP_Activity_Activity $parent_comment The parent activity. * @param int $comment_id ID for the newly received comment. * @param int $commenter_id ID of the user who made the comment. * @param array $params Arguments used with the original activity comment. */ do_action( 'bp_activity_sent_reply_to_reply_notification', $parent_comment, $comment_id, $commenter_id, $params ); } } /** * Helper method to map action arguments to function parameters. * * @since 1.9.0 * * @param int $comment_id ID of the comment being notified about. * @param array $params Parameters to use with notification. */ function bp_activity_new_comment_notification_helper( $comment_id, $params ) { bp_activity_new_comment_notification( $comment_id, $params['user_id'], $params ); } add_action( 'bp_activity_comment_posted', 'bp_activity_new_comment_notification_helper', 10, 2 ); /** Embeds *******************************************************************/ /** * Set up activity oEmbed cache during the activity loop. * * During an activity loop, this function sets up the hooks necessary to grab * each item's embeds from the cache, or put them in the cache if they are * not there yet. * * This does not cover recursive activity comments, as they do not use a real loop. * For that, see {@link bp_activity_comment_embed()}. * * @since 1.5.0 * * @see BP_Embed * @see bp_embed_activity_cache() * @see bp_embed_activity_save_cache() * */ function bp_activity_embed() { add_filter( 'embed_post_id', 'bp_get_activity_id' ); add_filter( 'oembed_dataparse', 'bp_activity_oembed_dataparse', 10, 2 ); add_filter( 'bp_embed_get_cache', 'bp_embed_activity_cache', 10, 3 ); add_action( 'bp_embed_update_cache', 'bp_embed_activity_save_cache', 10, 3 ); } add_action( 'activity_loop_start', 'bp_activity_embed' ); /** * Cache full oEmbed response from oEmbed. * * @since 2.6.0 * * @param string $retval Current oEmbed result. * @param object $data Full oEmbed response. * @param string $url URL used for the oEmbed request. * @return string */ function bp_activity_oembed_dataparse( $retval, $data ) { buddypress()->activity->oembed_response = $data; return $retval; } /** * Set up activity oEmbed cache while recursing through activity comments. * * While crawling through an activity comment tree * ({@link bp_activity_recurse_comments}), this function sets up the hooks * necessary to grab each comment's embeds from the cache, or put them in * the cache if they are not there yet. * * @since 1.5.0 * * @see BP_Embed * @see bp_embed_activity_cache() * @see bp_embed_activity_save_cache() * */ function bp_activity_comment_embed() { add_filter( 'embed_post_id', 'bp_get_activity_comment_id' ); add_filter( 'bp_embed_get_cache', 'bp_embed_activity_cache', 10, 3 ); add_action( 'bp_embed_update_cache', 'bp_embed_activity_save_cache', 10, 3 ); } add_action( 'bp_before_activity_comment', 'bp_activity_comment_embed' ); /** * When a user clicks on a "Read More" item, make sure embeds are correctly parsed and shown for the expanded content. * * @since 1.5.0 * * @see BP_Embed * * @param object $activity The activity that is being expanded. */ function bp_dtheme_embed_read_more( $activity ) { buddypress()->activity->read_more_id = $activity->id; add_filter( 'embed_post_id', function () { return buddypress()->activity->read_more_id; } ); add_filter( 'bp_embed_get_cache', 'bp_embed_activity_cache', 10, 3 ); add_action( 'bp_embed_update_cache', 'bp_embed_activity_save_cache', 10, 3 ); } add_action( 'bp_dtheme_get_single_activity_content', 'bp_dtheme_embed_read_more' ); add_action( 'bp_legacy_theme_get_single_activity_content', 'bp_dtheme_embed_read_more' ); /** * Clean up 'embed_post_id' filter after comment recursion. * * This filter must be removed so that the non-comment filters take over again * once the comments are done being processed. * * @since 1.5.0 * * @see bp_activity_comment_embed() */ function bp_activity_comment_embed_after_recurse() { remove_filter( 'embed_post_id', 'bp_get_activity_comment_id' ); } add_action( 'bp_after_activity_comment', 'bp_activity_comment_embed_after_recurse' ); /** * Fetch an activity item's cached embeds. * * Used during {@link BP_Embed::parse_oembed()} via {@link bp_activity_embed()}. * * @since 1.5.0 * * @see BP_Embed::parse_oembed() * * @param string $cache An empty string passed by BP_Embed::parse_oembed() for * functions like this one to filter. * @param int $id The ID of the activity item. * @param string $cachekey The cache key generated in BP_Embed::parse_oembed(). * @return mixed The cached embeds for this activity item. */ function bp_embed_activity_cache( $cache, $id, $cachekey ) { return bp_activity_get_meta( $id, $cachekey ); } /** * Set an activity item's embed cache. * * Used during {@link BP_Embed::parse_oembed()} via {@link bp_activity_embed()}. * * @since 1.5.0 * * @see BP_Embed::parse_oembed() * * @param string $cache An empty string passed by BP_Embed::parse_oembed() for * functions like this one to filter. * @param string $cachekey The cache key generated in BP_Embed::parse_oembed(). * @param int $id The ID of the activity item. */ function bp_embed_activity_save_cache( $cache, $cachekey, $id ) { bp_activity_update_meta( $id, $cachekey, $cache ); // Cache full oEmbed response. if ( true === isset( buddypress()->activity->oembed_response ) ) { $cachekey = str_replace( '_oembed', '_oembed_response', $cachekey ); bp_activity_update_meta( $id, $cachekey, buddypress()->activity->oembed_response ); } } /** * Should we use Heartbeat to refresh activities? * * @since 2.0.0 * * @return bool True if activity heartbeat is enabled, otherwise false. */ function bp_activity_do_heartbeat() { $retval = false; if ( bp_is_activity_heartbeat_active() && ( bp_is_activity_directory() || bp_is_group_activity() ) ) { $retval = true; } /** * Filters whether the heartbeat feature in the activity stream should be active. * * @since 2.8.0 * * @param bool $retval Whether or not activity heartbeat is active. */ return (bool) apply_filters( 'bp_activity_do_heartbeat', $retval ); } /** * Detect a change in post type status, and initiate an activity update if necessary. * * @since 2.2.0 * * @todo Support untrashing better. * * @param string $new_status New status for the post. * @param string $old_status Old status for the post. * @param object $post Post data. */ function bp_activity_catch_transition_post_type_status( $new_status, $old_status, $post ) { if ( ! post_type_supports( $post->post_type, 'buddypress-activity' ) ) { return; } // This is an edit. if ( $new_status === $old_status ) { // An edit of an existing post should update the existing activity item. if ( $new_status == 'publish' ) { $edit = bp_activity_post_type_update( $post ); // Post was never recorded into activity stream, so record it now! if ( null === $edit ) { bp_activity_post_type_publish( $post->ID, $post ); } // Allow plugins to eventually deal with other post statuses. } else { /** * Fires when editing the post and the new status is not 'publish'. * * This is a variable filter that is dependent on the post type * being untrashed. * * @since 2.5.0 * * @param WP_Post $post Post data. * @param string $new_status New status for the post. * @param string $old_status Old status for the post. */ do_action( 'bp_activity_post_type_edit_' . $post->post_type, $post, $new_status, $old_status ); } return; } // Publishing a previously unpublished post. if ( 'publish' === $new_status ) { // Untrashing the post type - nothing here yet. if ( 'trash' == $old_status ) { /** * Fires if untrashing post in a post type. * * This is a variable filter that is dependent on the post type * being untrashed. * * @since 2.2.0 * * @param WP_Post $post Post data. */ do_action( 'bp_activity_post_type_untrash_' . $post->post_type, $post ); } else { // Record the post. bp_activity_post_type_publish( $post->ID, $post ); } // Unpublishing a previously published post. } elseif ( 'publish' === $old_status ) { // Some form of pending status - only remove the activity entry. bp_activity_post_type_unpublish( $post->ID, $post ); // For any other cases, allow plugins to eventually deal with it. } else { /** * Fires when the old and the new post status are not 'publish'. * * This is a variable filter that is dependent on the post type * being untrashed. * * @since 2.5.0 * * @param WP_Post $post Post data. * @param string $new_status New status for the post. * @param string $old_status Old status for the post. */ do_action( 'bp_activity_post_type_transition_status_' . $post->post_type, $post, $new_status, $old_status ); } } add_action( 'transition_post_status', 'bp_activity_catch_transition_post_type_status', 10, 3 ); /** * 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 allowed activity types, so that the activity's Akismet history is generated. $post_type_comment_action = $activity_comment_object->action_id; $comment_akismet_history = function ( $activity_types ) use ( $post_type_comment_action ) { $activity_types[] = $post_type_comment_action; return $activity_types; }; 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 dynamic permitting of the "new_blog_comment" activity type so we don't break anything. remove_filter( 'bp_akismet_get_activity_types', $comment_akismet_history ); } add_action( 'transition_comment_status', 'bp_activity_transition_post_type_comment_status', 10, 3 ); /** * Finds and exports personal data associated with an email address from the Activity tables. * * @since 4.0.0 * * @param string $email_address The user's email address. * @param int $page Batch number. * @return array An array of personal data. */ function bp_activity_personal_data_exporter( $email_address, $page ) { $number = 50; $email_address = trim( $email_address ); $user_data_to_export = array(); $user = get_user_by( 'email', $email_address ); if ( ! $user ) { return array( 'data' => array(), 'done' => true, ); } $activities = bp_activity_get( array( 'display_comments' => 'stream', 'per_page' => $number, 'page' => $page, 'show_hidden' => true, 'filter' => array( 'user_id' => $user->ID, ), ) ); $activity_actions = bp_activity_get_actions(); foreach ( $activities['activities'] as $activity ) { if ( ! empty( $activity_actions->{$activity->component}->{$activity->type}['format_callback'] ) ) { $description = call_user_func( $activity_actions->{$activity->component}->{$activity->type}['format_callback'], '', $activity ); } elseif ( ! empty( $activity->action ) ) { $description = $activity->action; } else { $description = $activity->type; } $item_data = array( array( 'name' => __( 'Activity Date', 'buddypress' ), 'value' => $activity->date_recorded, ), array( 'name' => __( 'Activity Description', 'buddypress' ), 'value' => $description, ), array( 'name' => __( 'Activity URL', 'buddypress' ), 'value' => bp_activity_get_permalink( $activity->id, $activity ), ), ); if ( ! empty( $activity->content ) ) { $item_data[] = array( 'name' => __( 'Activity Content', 'buddypress' ), 'value' => $activity->content, ); } /** * Filters the data associated with an activity item when assembled for a WP personal data export. * * Plugins that register activity types whose `action` string doesn't adequately * describe the activity item for the purposes of data export may filter the activity * item data here. * * @since 4.0.0 * * @param array $item_data Array of data describing the activity item. * @param BP_Activity_Activity $activity Activity item. */ $item_data = apply_filters( 'bp_activity_personal_data_export_item_data', $item_data, $activity ); $user_data_to_export[] = array( 'group_id' => 'bp_activity', 'group_label' => __( 'Activity', 'buddypress' ), 'item_id' => "bp-activity-{$activity->id}", 'data' => $item_data, ); } // Tell core if we have more items to process. $done = count( $activities['activities'] ) < $number; return array( 'data' => $user_data_to_export, 'done' => $done, ); } /** * Checks whether an activity feed is enabled. * * @since 8.0.0 * @since 12.0.0 Added bp_current_user_can( 'bp_view' ) check. * * @param string $feed_id The feed identifier. Possible values are: * 'sitewide', 'personal', 'friends', 'mygroups', 'mentions', 'favorites'. */ function bp_activity_is_feed_enable( $feed_id = '' ) { $retval = bp_current_user_can( 'bp_view', array( 'bp_component' => 'activity' ) ); /** * Filters if BuddyPress should consider feeds enabled. If disabled, it will return early. * * @since 1.8.0 * @since 8.0.0 Adds the `$feed_id` parameter. * * @param bool $retval Whether this feed is enabled or not. * @param string $feed_id The feed identifier. */ return (bool) apply_filters( 'bp_activity_enable_feeds', $retval, $feed_id ); }
Fatal error: Uncaught Error: Call to undefined function bp_activity_do_mentions() in /home/nimaghor/public_html/wp-content/plugins/buddypress/bp-activity/classes/class-bp-activity-component.php:280 Stack trace: #0 /home/nimaghor/public_html/wp-includes/class-wp-hook.php(324): BP_Activity_Component->register_nav(Array) #1 /home/nimaghor/public_html/wp-includes/class-wp-hook.php(348): WP_Hook->apply_filters(NULL, Array) #2 /home/nimaghor/public_html/wp-includes/plugin.php(517): WP_Hook->do_action(Array) #3 /home/nimaghor/public_html/wp-content/plugins/buddypress/bp-core/bp-core-dependency.php(169): do_action('bp_register_nav') #4 /home/nimaghor/public_html/wp-includes/class-wp-hook.php(324): bp_register_nav('') #5 /home/nimaghor/public_html/wp-includes/class-wp-hook.php(348): WP_Hook->apply_filters(NULL, Array) #6 /home/nimaghor/public_html/wp-includes/plugin.php(517): WP_Hook->do_action(Array) #7 /home/nimaghor/public_html/wp-content/plugins/buddypress/bp-core/bp-core-dependency.php(291): do_action('bp_init') #8 /home/nima in /home/nimaghor/public_html/wp-content/plugins/buddypress/bp-activity/classes/class-bp-activity-component.php on line 280