* Mentions: @name
* If the Activity component is enabled, we use it to parse out any at-names. A consequence
* to note is that the "name" mentioned must match a real user account. If it's a made-up
* at-name, then it isn't extracted.
* If the Activity component is disabled, any at-name is extracted (both those matching
* real accounts, and those made-up).
* Images: , [gallery], [gallery ids="2,3"], featured images (Post thumbnails).
* If an extracted image is in the Media Library, then its resolution will be included.
* Shortcodes: Extract information about any (registered) shortcodes.
* This includes any shortcodes indirectly covered by any of the other media extraction types.
* For example, [gallery].
* Embeds: Extract any URL matching a registered oEmbed handler.
* Audio: , [audio]
* See wp_get_audio_extensions() for supported audio formats.
* Video: [video]
* See wp_get_video_extensions() for supported video formats.
*
* @see BP_Media_Extractor::extract() Use this to extract media.
*/
class BP_Media_Extractor {
/**
* Media type.
*
* @since 2.3.0
* @var int
*/
const ALL = 255;
const LINKS = 1;
const MENTIONS = 2;
const IMAGES = 4;
const SHORTCODES = 8;
const EMBEDS = 16;
const AUDIO = 32;
const VIDEOS = 64;
/**
* Extract media from text.
*
* @since 2.3.0
*
* @param string|WP_Post $richtext Content to parse.
* @param int $what_to_extract Media type to extract (optional).
* @param array $extra_args Bespoke data for a particular extractor (optional).
* @return array {
* @type array $has Extracted media counts. {
* @type int $audio
* @type int $embeds
* @type int $images
* @type int $links
* @type int $mentions
* @type int $shortcodes
* @type int $video
* }
* @type array $audio Extracted audio. {
* Array of extracted media.
*
* @type string $source Media source. Either "html" or "shortcodes".
* @type string $url Link to audio.
* }
* @type array $embeds Extracted oEmbeds. {
* Array of extracted media.
*
* @type string $url oEmbed link.
* }
* @type array $images Extracted images. {
* Array of extracted media.
*
* @type int $gallery_id Gallery ID. Optional, not always set.
* @type int $height Width of image. If unknown, set to 0.
* @type string $source Media source. Either "html" or "galleries".
* @type string $url Link to image.
* @type int $width Width of image. If unknown, set to 0.
* }
* @type array $links Extracted URLs. {
* Array of extracted media.
*
* @type string $url Link.
* }
* @type array $mentions Extracted mentions. {
* Array of extracted media.
*
* @type string $name @mention.
* @type string $user_id User ID. Optional, only set if Activity component enabled.
* }
* @type array $shortcodes Extracted shortcodes. {
* Array of extracted media.
*
* @type array $attributes Key/value pairs of the shortcodes attributes (if any).
* @type string $content Text wrapped by the shortcode.
* @type string $type Shortcode type.
* @type string $original The entire shortcode.
* }
* @type array $videos Extracted video. {
* Array of extracted media.
*
* @type string $source Media source. Currently only "shortcodes".
* @type string $url Link to audio.
* }
* }
*/
public function extract( $richtext, $what_to_extract = self::ALL, $extra_args = array() ) {
$media = array();
// Support passing a WordPress Post for the $richtext parameter.
if ( is_a( $richtext, 'WP_Post' ) ) {
$extra_args['post'] = $richtext;
$richtext = $extra_args['post']->post_content;
}
$plaintext = $this->strip_markup( $richtext );
// Extract links.
if ( self::LINKS & $what_to_extract ) {
$media = array_merge_recursive( $media, $this->extract_links( $richtext, $plaintext, $extra_args ) );
}
// Extract mentions.
if ( self::MENTIONS & $what_to_extract ) {
$media = array_merge_recursive( $media, $this->extract_mentions( $richtext, $plaintext, $extra_args ) );
}
// Extract images.
if ( self::IMAGES & $what_to_extract ) {
$media = array_merge_recursive( $media, $this->extract_images( $richtext, $plaintext, $extra_args ) );
}
// Extract shortcodes.
if ( self::SHORTCODES & $what_to_extract ) {
$media = array_merge_recursive( $media, $this->extract_shortcodes( $richtext, $plaintext, $extra_args ) );
}
// Extract oEmbeds.
if ( self::EMBEDS & $what_to_extract ) {
$media = array_merge_recursive( $media, $this->extract_embeds( $richtext, $plaintext, $extra_args ) );
}
// Extract audio.
if ( self::AUDIO & $what_to_extract ) {
$media = array_merge_recursive( $media, $this->extract_audio( $richtext, $plaintext, $extra_args ) );
}
// Extract video.
if ( self::VIDEOS & $what_to_extract ) {
$media = array_merge_recursive( $media, $this->extract_video( $richtext, $plaintext, $extra_args ) );
}
/**
* Filters media extracted from text.
*
* @since 2.3.0
*
* @param array $media Extracted media. See {@link BP_Media_Extractor::extract()} for format.
* @param string $richtext Content to parse.
* @param int $what_to_extract Media type to extract.
* @param array $extra_args Bespoke data for a particular extractor.
* @param string $plaintext Copy of $richtext without any markup.
*/
return apply_filters( 'bp_media_extractor_extract', $media, $richtext, $what_to_extract, $extra_args, $plaintext );
}
/**
* Content type specific extraction methods.
*
* You shouldn't need to use these directly; just use {@link BP_Media_Extractor::extract()}.
*/
/**
* Extract `` tags from text.
*
* @since 2.3.0
*
* @param string $richtext Content to parse.
* @param string $plaintext Sanitized version of the content.
* @param array $extra_args Bespoke data for a particular extractor (optional).
* @return array {
* @type array $has Extracted media counts. {
* @type int $links
* }
* @type array $links Extracted URLs. {
* Array of extracted media.
*
* @type string $url Link.
* }
* }
*/
protected function extract_links( $richtext, $plaintext, $extra_args = array() ) {
$data = array( 'has' => array( 'links' => 0 ), 'links' => array() );
// Matches: href="text" and href='text'.
if ( stripos( $richtext, 'href=' ) !== false ) {
preg_match_all( '#href=(["\'])([^"\']+)\1#i', $richtext, $matches );
if ( ! empty( $matches[2] ) ) {
$matches[2] = array_unique( $matches[2] );
foreach ( $matches[2] as $link_src ) {
$link_src = esc_url_raw( $link_src );
if ( $link_src ) {
$data['links'][] = array( 'url' => $link_src );
}
}
}
}
$data['has']['links'] = count( $data['links'] );
/**
* Filters links extracted from text.
*
* @since 2.3.0
*
* @param array $data Extracted links. See {@link BP_Media_Extractor::extract_links()} for format.
* @param string $richtext Content to parse.
* @param string $plaintext Copy of $richtext without any markup.
* @param array $extra_args Bespoke data for a particular extractor.
*/
return apply_filters( 'bp_media_extractor_links', $data, $richtext, $plaintext, $extra_args );
}
/**
* Extract @mentions tags from text.
*
* If the Activity component is enabled, it is used to parse @mentions.
* The mentioned "name" must match a user account, otherwise it is discarded.
*
* If the Activity component is disabled, any @mentions are extracted.
*
* @since 2.3.0
*
* @param string $richtext Content to parse.
* @param string $plaintext Sanitized version of the content.
* @param array $extra_args Bespoke data for a particular extractor.
* @return array {
* @type array $has Extracted media counts. {
* @type int $mentions
* }
* @type array $mentions Extracted mentions. {
* Array of extracted media.
*
* @type string $name @mention.
* @type string $user_id User ID. Optional, only set if Activity component enabled.
* }
* }
*/
protected function extract_mentions( $richtext, $plaintext, $extra_args = array() ) {
$data = array( 'has' => array( 'mentions' => 0 ), 'mentions' => array() );
$mentions = array();
// If the Activity component is active, use it to parse @mentions.
if ( bp_is_active( 'activity' ) ) {
$mentions = bp_activity_find_mentions( $plaintext );
if ( ! $mentions ) {
$mentions = array();
}
// If the Activity component is disabled, instead do a basic parse.
} else {
if ( strpos( $plaintext, '@' ) !== false ) {
preg_match_all( '/[@]+([A-Za-z0-9-_\.@]+)\b/', $plaintext, $matches );
if ( ! empty( $matches[1] ) ) {
$mentions = array_unique( array_map( 'strtolower', $matches[1] ) );
}
}
}
// Build results.
foreach ( $mentions as $user_id => $mention_name ) {
$mention = array( 'name' => strtolower( $mention_name ) );
// If the Activity component is active, store the User ID, too.
if ( bp_is_active( 'activity' ) ) {
$mention['user_id'] = (int) $user_id;
}
$data['mentions'][] = $mention;
}
$data['has']['mentions'] = count( $data['mentions'] );
/**
* Filters @mentions extracted from text.
*
* @since 2.3.0
*
* @param array $data Extracted @mentions. See {@link BP_Media_Extractor::extract_mentions()} for format.
* @param string $richtext Content to parse.
* @param string $plaintext Copy of $richtext without any markup.
* @param array $extra_args Bespoke data for a particular extractor (optional).
*/
return apply_filters( 'bp_media_extractor_mentions', $data, $richtext, $plaintext, $extra_args );
}
/**
* Extract images from `` tags, [galleries], and featured images from a Post.
*
* If an image is in the Media Library, then its resolution is included in the results.
*
* @since 2.3.0
*
* @param string $richtext Content to parse.
* @param string $plaintext Sanitized version of the content.
* @param array $extra_args Bespoke data for a particular extractor (optional).
* @return array {
* @type array $has Extracted media counts. {
* @type int $images
* }
* @type array $images Extracted images. {
* Array of extracted media.
*
* @type int $gallery_id Gallery ID. Optional, not always set.
* @type int $height Width of image. If unknown, set to 0.
* @type string $source Media source. Either "html" or "galleries".
* @type string $url Link to image.
* @type int $width Width of image. If unknown, set to 0.
* }
* }
*/
protected function extract_images( $richtext, $plaintext, $extra_args = array() ) {
$media = array( 'has' => array( 'images' => 0 ), 'images' => array() );
$featured_image = $this->extract_images_from_featured_images( $richtext, $plaintext, $extra_args );
$galleries = $this->extract_images_from_galleries( $richtext, $plaintext, $extra_args );
// `` tags.
if ( stripos( $richtext, 'src=' ) !== false ) {
preg_match_all( '#src=(["\'])([^"\']+)\1#i', $richtext, $img_srcs ); // Matches src="text" and src='text'.
// .
if ( ! empty( $img_srcs[2] ) ) {
$img_srcs[2] = array_unique( $img_srcs[2] );
foreach ( $img_srcs[2] as $image_src ) {
// Skip data URIs.
if ( strtolower( substr( $image_src, 0, 5 ) ) === 'data:' ) {
continue;
}
$image_src = esc_url_raw( $image_src );
if ( ! $image_src ) {
continue;
}
$media['images'][] = array(
'source' => 'html',
'url' => $image_src,
// The image resolution isn't available, but we need to set the keys anyway.
'height' => 0,
'width' => 0,
);
}
}
}
// Galleries.
if ( ! empty( $galleries ) ) {
foreach ( $galleries as $gallery ) {
foreach ( $gallery as $image ) {
$image_url = esc_url_raw( $image['url'] );
if ( ! $image_url ) {
continue;
}
$media['images'][] = array(
'gallery_id' => $image['gallery_id'],
'source' => 'galleries',
'url' => $image_url,
'width' => $image['width'],
'height' => $image['height'],
);
}
}
$media['has']['galleries'] = count( $galleries );
}
// Featured images (aka thumbnails).
if ( ! empty( $featured_image ) ) {
$image_url = esc_url_raw( $featured_image[0] );
if ( $image_url ) {
$media['images'][] = array(
'source' => 'featured_images',
'url' => $image_url,
'width' => $featured_image[1],
'height' => $featured_image[2],
);
$media['has']['featured_images'] = 1;
}
}
// Update image count.
$media['has']['images'] = count( $media['images'] );
/**
* Filters images extracted from text.
*
* @since 2.3.0
*
* @param array $media Extracted images. See {@link BP_Media_Extractor::extract_images()} for format.
* @param string $richtext Content to parse.
* @param string $plaintext Copy of $richtext without any markup.
* @param array $extra_args Bespoke data for a particular extractor.
*/
return apply_filters( 'bp_media_extractor_images', $media, $richtext, $plaintext, $extra_args );
}
/**
* Extract shortcodes from text.
*
* This includes any shortcodes indirectly used by other media extraction types.
* For example, [gallery] and [audio].
*
* @since 2.3.0
*
* @param string $richtext Content to parse.
* @param string $plaintext Sanitized version of the content.
* @param array $extra_args Bespoke data for a particular extractor (optional).
* @return array {
* @type array $has Extracted media counts. {
* @type int $shortcodes
* }
* @type array $shortcodes Extracted shortcodes. {
* Array of extracted media.
*
* @type array $attributes Key/value pairs of the shortcodes attributes (if any).
* @type string $content Text wrapped by the shortcode.
* @type string $type Shortcode type.
* @type string $original The entire shortcode.
* }
* }
*/
protected function extract_shortcodes( $richtext, $plaintext, $extra_args = array() ) {
$data = array( 'has' => array( 'shortcodes' => 0 ), 'shortcodes' => array() );
// Match any registered WordPress shortcodes.
if ( strpos( $richtext, '[' ) !== false ) {
preg_match_all( '/' . get_shortcode_regex() . '/s', $richtext, $matches );
if ( ! empty( $matches[2] ) ) {
foreach ( $matches[2] as $i => $shortcode_name ) {
$attrs = shortcode_parse_atts( $matches[3][ $i ] );
$attrs = ( ! $attrs ) ? array() : (array) $attrs;
$shortcode = array();
$shortcode['attributes'] = $attrs; // Attributes.
$shortcode['content'] = $matches[5][ $i ]; // Content.
$shortcode['type'] = $shortcode_name; // Shortcode.
$shortcode['original'] = $matches[0][ $i ]; // Entire shortcode.
$data['shortcodes'][] = $shortcode;
}
}
}
$data['has']['shortcodes'] = count( $data['shortcodes'] );
/**
* Filters shortcodes extracted from text.
*
* @since 2.3.0
*
* @param array $data Extracted shortcodes.
* See {@link BP_Media_Extractor::extract_shortcodes()} for format.
* @param string $richtext Content to parse.
* @param string $plaintext Copy of $richtext without any markup.
* @param array $extra_args Bespoke data for a particular extractor.
*/
return apply_filters( 'bp_media_extractor_shortcodes', $data, $richtext, $plaintext, $extra_args );
}
/**
* Extract any URL, matching a registered oEmbed endpoint, from text.
*
* @since 2.3.0
*
* @param string $richtext Content to parse.
* @param string $plaintext Sanitized version of the content.
* @param array $extra_args Bespoke data for a particular extractor (optional).
* @return array {
* @type array $has Extracted media counts. {
* @type int $embeds
* }
* @type array $embeds Extracted oEmbeds. {
* Array of extracted media.
*
* @type string $url oEmbed link.
* }
* }
*/
protected function extract_embeds( $richtext, $plaintext, $extra_args = array() ) {
$data = array( 'has' => array( 'embeds' => 0 ), 'embeds' => array() );
$embeds = array();
if ( ! function_exists( '_wp_oembed_get_object' ) ) {
require( ABSPATH . WPINC . '/class-oembed.php' );
}
// Matches any links on their own lines. They may be oEmbeds.
if ( stripos( $richtext, 'http' ) !== false ) {
preg_match_all( '#^\s*(https?://[^\s"]+)\s*$#im', $richtext, $matches );
if ( ! empty( $matches[1] ) ) {
$matches[1] = array_unique( $matches[1] );
$oembed = _wp_oembed_get_object();
foreach ( $matches[1] as $link ) {
// Skip data URIs.
if ( strtolower( substr( $link, 0, 5 ) ) === 'data:' ) {
continue;
}
foreach ( $oembed->providers as $matchmask => $oembed_data ) {
list( , $is_regex ) = $oembed_data;
// Turn asterisk-type provider URLs into regexs.
if ( ! $is_regex ) {
$matchmask = '#' . str_replace( '___wildcard___', '(.+)', preg_quote( str_replace( '*', '___wildcard___', $matchmask ), '#' ) ) . '#i';
$matchmask = preg_replace( '|^#http\\\://|', '#https?\://', $matchmask );
}
// Check whether this "link" is really an oEmbed.
if ( preg_match( $matchmask, $link ) ) {
$data['embeds'][] = array( 'url' => $link );
break;
}
}
}
}
}
$data['has']['embeds'] = count( $data['embeds'] );
/**
* Filters embeds extracted from text.
*
* @since 2.3.0
*
* @param array $data Extracted embeds. See {@link BP_Media_Extractor::extract_embeds()} for format.
* @param string $richtext Content to parse.
* @param string $plaintext Copy of $richtext without any markup.
* @param array $extra_args Bespoke data for a particular extractor.
*/
return apply_filters( 'bp_media_extractor_embeds', $data, $richtext, $plaintext, $extra_args );
}
/**
* Extract [audio] shortcodes and `` tags, from text.
*
* @since 2.3.0
*
* @see wp_get_audio_extensions() for supported audio formats.
*
* @param string $richtext Content to parse.
* @param string $plaintext Sanitized version of the content.
* @param array $extra_args Bespoke data for a particular extractor (optional).
* @return array {
* @type array $has Extracted media counts. {
* @type int $audio
* }
* @type array $audio Extracted audio. {
* Array of extracted media.
*
* @type string $original The entire shortcode.
* @type string $source Media source. Either "html" or "shortcodes".
* @type string $url Link to audio.
* }
* }
*/
protected function extract_audio( $richtext, $plaintext, $extra_args = array() ) {
$data = array( 'has' => array( 'audio' => 0 ), 'audio' => array() );
$audios = $this->extract_shortcodes( $richtext, $plaintext, $extra_args );
$links = $this->extract_links( $richtext, $plaintext, $extra_args );
$audio_types = wp_get_audio_extensions();
// [audio]
$audios = wp_list_filter( $audios['shortcodes'], array( 'type' => 'audio' ) );
foreach ( $audios as $audio ) {
// Media URL can appear as the first parameter inside the shortcode brackets.
if ( isset( $audio['attributes']['src'] ) ) {
$src_param = 'src';
} elseif ( isset( $audio['attributes'][0] ) ) {
$src_param = 0;
} else {
continue;
}
$path = untrailingslashit( parse_url( $audio['attributes'][ $src_param ], PHP_URL_PATH ) );
foreach ( $audio_types as $extension ) {
$extension = '.' . $extension;
// Check this URL's file extension matches that of an accepted audio format.
if ( ! $path || substr( $path, -4 ) !== $extension ) {
continue;
}
$data['audio'][] = array(
'original' => '[audio src="' . esc_url_raw( $audio['attributes'][ $src_param ] ) . '"]',
'source' => 'shortcodes',
'url' => esc_url_raw( $audio['attributes'][ $src_param ] ),
);
}
}
// tags.
foreach ( $audio_types as $extension ) {
$extension = '.' . $extension;
foreach ( $links['links'] as $link ) {
$path = untrailingslashit( parse_url( $link['url'], PHP_URL_PATH ) );
// Check this URL's file extension matches that of an accepted audio format.
if ( ! $path || substr( $path, -4 ) !== $extension ) {
continue;
}
$data['audio'][] = array(
'original' => '[audio src="' . esc_url_raw( $link['url'] ) . '"]', // Build an audio shortcode.
'source' => 'html',
'url' => esc_url_raw( $link['url'] ),
);
}
}
$data['has']['audio'] = count( $data['audio'] );
/**
* Filters audio extracted from text.
*
* @since 2.3.0
*
* @param array $data Extracted audio. See {@link BP_Media_Extractor::extract_audio()} for format.
* @param string $richtext Content to parse.
* @param string $plaintext Copy of $richtext without any markup.
* @param array $extra_args Bespoke data for a particular extractor.
*/
return apply_filters( 'bp_media_extractor_audio', $data, $richtext, $plaintext, $extra_args );
}
/**
* Extract [video] shortcodes from text.
*
* @since 2.3.0
*
* @see wp_get_video_extensions() for supported video formats.
*
* @param string $richtext Content to parse.
* @param string $plaintext Sanitized version of the content.
* @param array $extra_args Bespoke data for a particular extractor (optional).
* @return array {
* @type array $has Extracted media counts. {
* @type int $video
* }
* @type array $videos Extracted video. {
* Array of extracted media.
*
* @type string $source Media source. Currently only "shortcodes".
* @type string $url Link to audio.
* }
* }
*/
protected function extract_video( $richtext, $plaintext, $extra_args = array() ) {
$data = array( 'has' => array( 'videos' => 0 ), 'videos' => array() );
$videos = $this->extract_shortcodes( $richtext, $plaintext, $extra_args );
$video_types = wp_get_video_extensions();
// [video]
$videos = wp_list_filter( $videos['shortcodes'], array( 'type' => 'video' ) );
foreach ( $videos as $video ) {
// Media URL can appear as the first parameter inside the shortcode brackets.
if ( isset( $video['attributes']['src'] ) ) {
$src_param = 'src';
} elseif ( isset( $video['attributes'][0] ) ) {
$src_param = 0;
} else {
continue;
}
$path = untrailingslashit( parse_url( $video['attributes'][ $src_param ], PHP_URL_PATH ) );
foreach ( $video_types as $extension ) {
$extension = '.' . $extension;
// Check this URL's file extension matches that of an accepted video format (-5 for webm).
if ( ! $path || ( substr( $path, -4 ) !== $extension && substr( $path, -5 ) !== $extension ) ) {
continue;
}
$data['videos'][] = array(
'original' => $video['original'], // Entire shortcode.
'source' => 'shortcodes',
'url' => esc_url_raw( $video['attributes'][ $src_param ] ),
);
}
}
$data['has']['videos'] = count( $data['videos'] );
/**
* Filters videos extracted from text.
*
* @since 2.3.0
*
* @param array $data Extracted videos. See {@link BP_Media_Extractor::extract_videos()} for format.
* @param string $richtext Content to parse.
* @param string $plaintext Copy of $richtext without any markup.
* @param array $extra_args Bespoke data for a particular extractor.
*/
return apply_filters( 'bp_media_extractor_videos', $data, $richtext, $plaintext, $extra_args );
}
/**
* Helpers and utility methods.
*/
/**
* Extract images in [galleries] shortcodes from text.
*
* @since 2.3.0
*
* @param string $richtext Content to parse.
* @param string $plaintext Sanitized version of the content.
* @param array $extra_args Bespoke data for a particular extractor (optional).
* @return array
*/
protected function extract_images_from_galleries( $richtext, $plaintext, $extra_args = array() ) {
if ( ! isset( $extra_args['post'] ) || ! is_a( $extra_args['post'], 'WP_Post' ) ) {
$post = new WP_Post( (object) array( 'post_content' => $richtext ) );
} else {
$post = $extra_args['post'];
}
// We're not using get_post_galleries_images() because it returns thumbnails; we want the original image.
$galleries = get_post_galleries( $post, false );
$galleries_data = array();
if ( ! empty( $galleries ) ) {
// Validate the size of the images requested.
if ( isset( $extra_args['width'] ) ) {
// A width was specified but not a height, so calculate it assuming a 4:3 ratio.
if ( ! isset( $extra_args['height'] ) && ctype_digit( $extra_args['width'] ) ) {
$extra_args['height'] = round( ( $extra_args['width'] / 4 ) * 3 );
}
if ( ctype_digit( $extra_args['width'] ) ) {
$image_size = array( $extra_args['width'], $extra_args['height'] );
} else {
$image_size = $extra_args['width']; // E.g. "thumb", "medium".
}
} else {
$image_size = 'full';
}
/**
* There are two variants of gallery shortcode.
*
* One kind specifies the image (post) IDs via an `ids` parameter.
* The other gets the image IDs from post_type=attachment and post_parent=get_the_ID().
*/
foreach ( $galleries as $gallery_id => $gallery ) {
$data = array();
$images = array();
// Gallery ids= variant.
if ( isset( $gallery['ids'] ) ) {
$images = wp_parse_id_list( $gallery['ids'] );
// Gallery post_parent variant.
} elseif ( isset( $extra_args['post'] ) ) {
$images = wp_parse_id_list(
get_children( array(
'fields' => 'ids',
'order' => 'ASC',
'orderby' => 'menu_order ID',
'post_mime_type' => 'image',
'post_parent' => $extra_args['post']->ID,
'post_status' => 'inherit',
'post_type' => 'attachment',
) )
);
}
// Extract the data we need from each image in this gallery.
foreach ( $images as $image_id ) {
$image = wp_get_attachment_image_src( $image_id, $image_size );
$image_url = isset( $image[0] ) ? $image[0] : '';
$image_width = isset( $image[1] ) ? $image[1] : '';
$image_height = isset( $image[2] ) ? $image[2] : '';
$data[] = array(
'url' => $image_url,
'width' => $image_width,
'height' => $image_height,
'gallery_id' => 1 + $gallery_id,
);
}
$galleries_data[] = $data;
}
}
/**
* Filters image galleries extracted from text.
*
* @since 2.3.0
*
* @param array $galleries_data Galleries. See {@link BP_Media_Extractor::extract_images_from_galleries()}.
* @param string $richtext Content to parse.
* @param string $plaintext Copy of $richtext without any markup.
* @param array $extra_args Bespoke data for a particular extractor.
*/
return apply_filters( 'bp_media_extractor_galleries', $galleries_data, $richtext, $plaintext, $extra_args );
}
/**
* Extract the featured image from a Post.
*
* @since 2.3.0
*
* @param string $richtext Content to parse.
* @param string $plaintext Sanitized version of the content.
* @param array $extra_args Contains data that an implementation might need beyond the defaults.
* @return array
*/
protected function extract_images_from_featured_images( $richtext, $plaintext, $extra_args ) {
$image = array();
$thumb = 0;
if ( isset( $extra_args['post'] ) ) {
$thumb = (int) get_post_thumbnail_id( $extra_args['post']->ID );
}
if ( $thumb ) {
// Validate the size of the images requested.
if ( isset( $extra_args['width'] ) ) {
if ( ! isset( $extra_args['height'] ) && ctype_digit( $extra_args['width'] ) ) {
// A width was specified but not a height, so calculate it assuming a 4:3 ratio.
$extra_args['height'] = round( ( $extra_args['width'] / 4 ) * 3 );
}
if ( ctype_digit( $extra_args['width'] ) ) {
$image_size = array( $extra_args['width'], $extra_args['height'] );
} else {
$image_size = $extra_args['width']; // E.g. "thumb", "medium".
}
} else {
$image_size = 'full';
}
$image = wp_get_attachment_image_src( $thumb, $image_size );
}
/**
* Filters featured images extracted from a WordPress Post.
*
* @since 2.3.0
*
* @param array $image Extracted images. See {@link BP_Media_Extractor_Post::extract_images()} for format.
* @param string $richtext Content to parse.
* @param string $plaintext Copy of $richtext without any markup.
* @param array $extra_args Bespoke data for a particular extractor.
*/
return apply_filters( 'bp_media_extractor_featured_images', $image, $richtext, $plaintext, $extra_args );
}
/**
* Sanitize and format raw content to prepare for content extraction.
*
* HTML tags and shortcodes are removed, and HTML entities are decoded.
*
* @since 2.3.0
*
* @param string $richtext Content to sanitize.
* @return string
*/
protected function strip_markup( $richtext ) {
$plaintext = strip_shortcodes( html_entity_decode( strip_tags( $richtext ) ) );
/**
* Filters the generated plain text version of the content passed to the extractor.
*
* @since 2.3.0
*
* @param array $plaintext Generated plain text.
* @param string $richtext Original content.
*/
return apply_filters( 'bp_media_extractor_strip_markup', $plaintext, $richtext );
}
}