BP_Activity_oEmbed_Extension

oEmbed handler to respond and render single activity items.

Description

Source

File: bp-activity/classes/class-bp-activity-oembed-extension.php

class BP_Activity_oEmbed_Extension extends BP_Core_oEmbed_Extension {
	/**
	 * Custom oEmbed slug endpoint.
	 *
	 * @since BuddyPress 2.6.0
	 *
	 * @var string
	 */
	public $slug_endpoint = 'activity';

	/**
	 * Custom hooks.
	 *
	 * @since BuddyPress 2.6.0
	 */
	protected function custom_hooks() {
		add_action( 'oembed_dataparse',   array( $this, 'use_custom_iframe_sandbox_attribute' ), 20, 3 );
		add_action( 'embed_content_meta', array( $this, 'embed_comments_button' ), 5 );
		add_action( 'get_template_part_assets/embeds/header', array( $this, 'on_activity_header' ), 10, 2 );

		add_filter( 'bp_activity_embed_html', array( $this, 'modify_iframe' ) );
	}

	/**
	 * Add custom endpoint arguments.
	 *
	 * Currently, includes 'hide_media'.
	 *
	 * @since BuddyPress 2.6.0
	 *
	 * @return array
	 */
	protected function set_route_args() {
		return array(
			'hide_media' => array(
				'default' => false,
				'sanitize_callback' => 'wp_validate_boolean'
			)
		);
	}

	/**
	 * Output our custom embed template part.
	 *
	 * @since BuddyPress 2.6.0
	 */
	protected function content() {
		bp_get_asset_template_part( 'embeds/activity' );
	}

	/**
	 * Check if we're on our single activity page.
	 *
	 * @since BuddyPress 2.6.0
	 *
	 * @return bool
	 */
	protected function is_page() {
		return bp_is_single_activity();
	}

	/**
	 * Validates the URL to determine if the activity item is valid.
	 *
	 * @since BuddyPress 2.6.0
	 *
	 * @param  string   $url The URL to check.
	 * @return int|bool Activity ID on success; boolean false on failure.
	 */
	protected function validate_url_to_item_id( $url ) {
		if ( bp_core_enable_root_profiles() ) {
			$domain = bp_get_root_domain();
		} else {
			$domain = bp_get_members_directory_permalink();
		}

		// Check the URL to see if this is a single activity URL.
		if ( 0 !== strpos( $url, $domain ) ) {
			return false;
		}

		// Check for activity slug.
		if ( false === strpos( $url, '/' . bp_get_activity_slug() . '/' ) ) {
			return false;
		}

		// Do more checks.
		$url = trim( untrailingslashit( $url ) );

		// Grab the activity ID.
		$activity_id = (int) substr(
			$url,
			strrpos( $url, '/' ) + 1
		);

		if ( ! empty( $activity_id ) ) {
			// Check if activity item still exists.
			$activity = new BP_Activity_Activity( $activity_id );

			// Okay, we're good to go!
			if ( ! empty( $activity->component ) && 0 === (int) $activity->is_spam ) {
				return $activity_id;
			}
		}

		return false;
	}

	/**
	 * Sets the oEmbed response data for our activity item.
	 *
	 * @since BuddyPress 2.6.0
	 *
	 * @param  int $item_id The activity ID.
	 * @return array
	 */
	protected function set_oembed_response_data( $item_id ) {
		$activity = new BP_Activity_Activity( $item_id );

		return array(
			'content'      => $activity->content,
			'title'        => __( 'Activity', 'buddyboss' ),
			'author_name'  => bp_core_get_user_displayname( $activity->user_id ),
			'author_url'   => bp_core_get_user_domain( $activity->user_id ),

			// Custom identifier.
			'x_buddypress' => 'activity'
		);
	}

	/**
	 * Sets a custom <blockquote> for our oEmbed fallback HTML.
	 *
	 * @since BuddyPress 2.6.0
	 *
	 * @param  int $item_id The activity ID.
	 * @return string
	 */
	protected function set_fallback_html( $item_id ) {
		$activity    = new BP_Activity_Activity( $item_id );
		$mentionname = bp_activity_do_mentions() ? ' (@' . bp_activity_get_user_mentionname( $activity->user_id ) . ')' : '';
		$date        = date_i18n( get_option( 'date_format' ), strtotime( $activity->date_recorded ) );

		// Make sure we can use some activity functions that depend on the loop.
		$GLOBALS['activities_template'] = new stdClass;
		$GLOBALS['activities_template']->activity = $activity;

		// 'wp-embedded-content' CSS class is necessary due to how the embed JS works.
		$blockquote = sprintf( '<blockquote class="wp-embedded-content bp-activity-item">%1$s%2$s %3$s</blockquote>',
			bp_activity_get_embed_excerpt( $activity->content ),
			'- ' . bp_core_get_user_displayname( $activity->user_id ) . $mentionname,
			'<a href="' . esc_url( bp_activity_get_permalink( $item_id ) ) . '">' . $date . '</a>'
		);

		// Clean up.
		unset( $GLOBALS['activities_template'] );

		/**
		 * Filters the fallback HTML used when embedding a BP activity item.
		 *
		 * @since BuddyPress 2.6.0
		 *
		 * @param string               $blockquote Current fallback HTML
		 * @param BP_Activity_Activity $activity   Activity object
		 */
		return apply_filters( 'bp_activity_embed_fallback_html', $blockquote, $activity );
	}

	/**
	 * Sets a custom <iframe> title for our oEmbed item.
	 *
	 * @since BuddyPress 2.6.0
	 *
	 * @param  int $item_id The activity ID
	 * @return string
	 */
	protected function set_iframe_title( $item_id ) {
		return __( 'Embedded Activity Item', 'buddyboss' );
	}

	/**
	 * Use our custom <iframe> sandbox attribute in our oEmbed response.
	 *
	 * WordPress sets the <iframe> sandbox attribute to 'allow-scripts' regardless
	 * of whatever the oEmbed response is in {@link wp_filter_oembed_result()}. We
	 * need to add back our custom sandbox value so links will work.
	 *
	 * @since BuddyPress 2.6.0
	 *
	 * @see BP_Activity_Component::modify_iframe() where our custom sandbox value is set.
	 *
	 * @param string $result The oEmbed HTML result.
	 * @param object $data   A data object result from an oEmbed provider.
	 * @param string $url    The URL of the content to be embedded.
	 * @return string
	 */
	public function use_custom_iframe_sandbox_attribute( $result, $data, $url ) {
		// Make sure we are on a BuddyBoss activity oEmbed request.
		if ( false === isset( $data->x_buddypress ) || 'activity' !== $data->x_buddypress ) {
			return $result;
		}

		// Get unfiltered sandbox attribute from our own oEmbed response.
		$sandbox_pos = strpos( $data->html, 'sandbox=' ) + 9;
		$sandbox = substr( $data->html, $sandbox_pos, strpos( $data->html, '"', $sandbox_pos ) - $sandbox_pos );

		// Replace only if our sandbox attribute contains 'allow-top-navigation'.
		if ( false !== strpos( $sandbox, 'allow-top-navigation' ) ) {
			$result = str_replace( ' sandbox="allow-scripts"', " sandbox=\"{$sandbox}\"", $result );

			// Also remove 'security' attribute; this is only used for IE < 10.
			$result = str_replace( 'security="restricted"', "", $result );
		}

		return $result;
	}

	/**
	 * Modify various IFRAME-related items if embeds are allowed.
	 *
	 * HTML modified:
	 *  - Add sandbox="allow-top-navigation" attribute. This allows links to work
	 *    within the iframe sandbox attribute.
	 *
	 * JS modified:
	 *  - Remove IFRAME height restriction of 1000px. Fixes long embed items being
	 *    truncated.
	 *
	 * @since BuddyPress 2.6.0
	 *
	 * @param  string $retval Current embed HTML.
	 * @return string
	 */
	public function modify_iframe( $retval ) {
		// Add 'allow-top-navigation' to allow links to be clicked.
		$retval = str_replace( 'sandbox="', 'sandbox="allow-top-navigation ', $retval );

		// See /wp-includes/js/wp-embed.js.
		if ( SCRIPT_DEBUG ) {
			// Removes WP's hardcoded IFRAME height restriction.
			$retval = str_replace( 'height = 1000;', 'height = height;', $retval );

		// This is for the WP build minified version.
		} else {
			$retval = str_replace( 'g=1e3', 'g=g', $retval );
		}

		return $retval;
	}

	/**
	 * Do stuff when our oEmbed activity header template part is loading.
	 *
	 * Currently, removes wpautop() from the bp_activity_action() function.
	 *
	 * @since BuddyPress 2.6.0
	 *
	 * @param string $slug Template part slug requested.
	 * @param string $name Template part name requested.
	 */
	public function on_activity_header( $slug, $name ) {
		if ( false === $this->is_page() || 'activity' !== $name ) {
			return;
		}

		remove_filter( 'bp_get_activity_action', 'wpautop' );
	}

	/**
	 * Prints the markup for the activity embed comments button.
	 *
	 * Basically a copy of {@link print_embed_comments_button()}, but modified for
	 * the BP activity component.
	 *
	 * @since BuddyPress 2.6.0
	 */
	public function embed_comments_button() {
		if ( ! did_action( 'bp_embed_content' ) || ! bp_is_single_activity() ) {
			return;
		}

		// Make sure our custom permalink shows up in the 'WordPress Embed' block.
		add_filter( 'the_permalink', array( $this, 'filter_embed_url' ) );

		// Only show comment bubble if we have some activity comments.
		$count = bp_activity_get_comment_count();
		if ( empty( $count ) ) {
			return;
		}
	?>

		<div class="wp-embed-comments">
			<a href="<?php bp_activity_thread_permalink(); ?>">
				<span class="dashicons dashicons-admin-comments"></span>
				<?php
				printf(
					_n(
						/* translators: accessibility text */
						'%s <span class="screen-reader-text">Comment</span>',
						/* translators: accessibility text */
						'%s <span class="screen-reader-text">Comments</span>',
						$count,
						'buddyboss'
					),
					number_format_i18n( $count )
				);
				?>
			</a>
		</div>

	<?php
	}
}

Changelog

Changelog
Version Description
BuddyPress 2.6.0 Introduced.

Methods

Questions?

We're always happy to help with code or other questions you might have! Search our developer docs, contact support, or connect with our sales team.