Builds the Video shortcode output.
Description
This implements the functionality of the Video Shortcode for displaying WordPress mp4s in a post.
Parameters
$attr
arrayrequired- Attributes of the shortcode.
src
stringURL to the source of the video file. Default empty.height
intHeight of the video embed in pixels. Default 360.width
intWidth of the video embed in pixels. Default $content_width or 640.poster
stringThe'poster'
attribute for the<video>
element. Default empty.loop
stringThe'loop'
attribute for the<video>
element. Default empty.autoplay
stringThe'autoplay'
attribute for the<video>
element. Default empty.muted
stringThe'muted'
attribute for the<video>
element. Default false.preload
stringThe'preload'
attribute for the<video>
element.
Default'metadata'
.class
stringThe'class'
attribute for the<video>
element.
Default'wp-video-shortcode'
.
$content
stringoptional- Shortcode content.
Default:
''
Source
* @param string $content Shortcode content.
* @return string|void HTML content to display video.
*/
function wp_video_shortcode( $attr, $content = '' ) {
global $content_width;
$post_id = get_post() ? get_the_ID() : 0;
static $instance = 0;
++$instance;
/**
* Filters the default video shortcode output.
*
* If the filtered output isn't empty, it will be used instead of generating
* the default video template.
*
* @since 3.6.0
*
* @see wp_video_shortcode()
*
* @param string $html Empty variable to be replaced with shortcode markup.
* @param array $attr Attributes of the shortcode. See wp_video_shortcode().
* @param string $content Video shortcode content.
* @param int $instance Unique numeric ID of this video shortcode instance.
*/
$override = apply_filters( 'wp_video_shortcode_override', '', $attr, $content, $instance );
if ( '' !== $override ) {
return $override;
}
$video = null;
$default_types = wp_get_video_extensions();
$defaults_atts = array(
'src' => '',
'poster' => '',
'loop' => '',
'autoplay' => '',
'muted' => 'false',
'preload' => 'metadata',
'width' => 640,
'height' => 360,
'class' => 'wp-video-shortcode',
);
foreach ( $default_types as $type ) {
$defaults_atts[ $type ] = '';
}
$atts = shortcode_atts( $defaults_atts, $attr, 'video' );
if ( is_admin() ) {
// Shrink the video so it isn't huge in the admin.
if ( $atts['width'] > $defaults_atts['width'] ) {
$atts['height'] = round( ( $atts['height'] * $defaults_atts['width'] ) / $atts['width'] );
$atts['width'] = $defaults_atts['width'];
}
} else {
// If the video is bigger than the theme.
if ( ! empty( $content_width ) && $atts['width'] > $content_width ) {
$atts['height'] = round( ( $atts['height'] * $content_width ) / $atts['width'] );
$atts['width'] = $content_width;
}
}
$is_vimeo = false;
$is_youtube = false;
$yt_pattern = '#^https?://(?:www\.)?(?:youtube\.com/watch|youtu\.be/)#';
$vimeo_pattern = '#^https?://(.+\.)?vimeo\.com/.*#';
$primary = false;
if ( ! empty( $atts['src'] ) ) {
$is_vimeo = ( preg_match( $vimeo_pattern, $atts['src'] ) );
$is_youtube = ( preg_match( $yt_pattern, $atts['src'] ) );
if ( ! $is_youtube && ! $is_vimeo ) {
$type = wp_check_filetype( $atts['src'], wp_get_mime_types() );
if ( ! in_array( strtolower( $type['ext'] ), $default_types, true ) ) {
return sprintf( '<a class="wp-embedded-video" href="%s">%s</a>', esc_url( $atts['src'] ), esc_html( $atts['src'] ) );
}
}
if ( $is_vimeo ) {
wp_enqueue_script( 'mediaelement-vimeo' );
}
$primary = true;
array_unshift( $default_types, 'src' );
} else {
foreach ( $default_types as $ext ) {
if ( ! empty( $atts[ $ext ] ) ) {
$type = wp_check_filetype( $atts[ $ext ], wp_get_mime_types() );
if ( strtolower( $type['ext'] ) === $ext ) {
$primary = true;
}
}
}
}
if ( ! $primary ) {
$videos = get_attached_media( 'video', $post_id );
if ( empty( $videos ) ) {
return;
}
$video = reset( $videos );
$atts['src'] = wp_get_attachment_url( $video->ID );
if ( empty( $atts['src'] ) ) {
return;
}
array_unshift( $default_types, 'src' );
}
/**
* Filters the media library used for the video shortcode.
*
* @since 3.6.0
*
* @param string $library Media library used for the video shortcode.
*/
$library = apply_filters( 'wp_video_shortcode_library', 'mediaelement' );
if ( 'mediaelement' === $library && did_action( 'init' ) ) {
wp_enqueue_style( 'wp-mediaelement' );
wp_enqueue_script( 'wp-mediaelement' );
wp_enqueue_script( 'mediaelement-vimeo' );
}
/*
* MediaElement.js has issues with some URL formats for Vimeo and YouTube,
* so update the URL to prevent the ME.js player from breaking.
*/
if ( 'mediaelement' === $library ) {
if ( $is_youtube ) {
// Remove `feature` query arg and force SSL - see #40866.
$atts['src'] = remove_query_arg( 'feature', $atts['src'] );
$atts['src'] = set_url_scheme( $atts['src'], 'https' );
} elseif ( $is_vimeo ) {
// Remove all query arguments and force SSL - see #40866.
$parsed_vimeo_url = wp_parse_url( $atts['src'] );
$vimeo_src = 'https://' . $parsed_vimeo_url['host'] . $parsed_vimeo_url['path'];
// Add loop param for mejs bug - see #40977, not needed after #39686.
$loop = $atts['loop'] ? '1' : '0';
$atts['src'] = add_query_arg( 'loop', $loop, $vimeo_src );
}
}
/**
* Filters the class attribute for the video shortcode output container.
*
* @since 3.6.0
* @since 4.9.0 The `$atts` parameter was added.
*
* @param string $class CSS class or list of space-separated classes.
* @param array $atts Array of video shortcode attributes.
*/
$atts['class'] = apply_filters( 'wp_video_shortcode_class', $atts['class'], $atts );
$html_atts = array(
'class' => $atts['class'],
'id' => sprintf( 'video-%d-%d', $post_id, $instance ),
'width' => absint( $atts['width'] ),
'height' => absint( $atts['height'] ),
'poster' => esc_url( $atts['poster'] ),
'loop' => wp_validate_boolean( $atts['loop'] ),
'autoplay' => wp_validate_boolean( $atts['autoplay'] ),
'muted' => wp_validate_boolean( $atts['muted'] ),
'preload' => $atts['preload'],
);
// These ones should just be omitted altogether if they are blank.
foreach ( array( 'poster', 'loop', 'autoplay', 'preload', 'muted' ) as $a ) {
if ( empty( $html_atts[ $a ] ) ) {
unset( $html_atts[ $a ] );
}
}
$attr_strings = array();
foreach ( $html_atts as $k => $v ) {
$attr_strings[] = $k . '="' . esc_attr( $v ) . '"';
}
$html = '';
if ( 'mediaelement' === $library && 1 === $instance ) {
$html .= "<!--[if lt IE 9]><script>document.createElement('video');</script><![endif]-->\n";
}
$html .= sprintf( '<video %s controls="controls">', implode( ' ', $attr_strings ) );
$fileurl = '';
$source = '<source type="%s" src="%s" />';
foreach ( $default_types as $fallback ) {
if ( ! empty( $atts[ $fallback ] ) ) {
if ( empty( $fileurl ) ) {
$fileurl = $atts[ $fallback ];
}
if ( 'src' === $fallback && $is_youtube ) {
$type = array( 'type' => 'video/youtube' );
} elseif ( 'src' === $fallback && $is_vimeo ) {
$type = array( 'type' => 'video/vimeo' );
} else {
$type = wp_check_filetype( $atts[ $fallback ], wp_get_mime_types() );
}
$url = add_query_arg( '_', $instance, $atts[ $fallback ] );
$html .= sprintf( $source, $type['type'], esc_url( $url ) );
}
}
if ( ! empty( $content ) ) {
if ( str_contains( $content, "\n" ) ) {
$content = str_replace( array( "\r\n", "\n", "\t" ), '', $content );
}
$html .= trim( $content );
}
if ( 'mediaelement' === $library ) {
$html .= wp_mediaelement_fallback( $fileurl );
}
$html .= '</video>';
$width_rule = '';
if ( ! empty( $atts['width'] ) ) {
$width_rule = sprintf( 'width: %dpx;', $atts['width'] );
}
$output = sprintf( '<div style="%s" class="wp-video">%s</div>', $width_rule, $html );
/**
* Filters the output of the video shortcode.
*
* @since 3.6.0
*
* @param string $output Video shortcode HTML output.
* @param array $atts Array of video shortcode attributes.
* @param string $video Video file.
* @param int $post_id Post ID.
* @param string $library Media library used for the video shortcode.
Changelog
Version | Description |
---|---|
3.6.0 | Introduced. |
An example on how to use this function with all the attributes in an array.