* Filters the `loading` attribute value to add to an iframe. Default `lazy`.
* Returning `false` or an empty string will not add the attribute.
* Returning `true` will add the default value.
* @param string|bool $value The `loading` attribute value. Returning a falsey value will result in
* the attribute being omitted for the iframe. Default 'lazy'.
* @param string $iframe The HTML `iframe` tag to be filtered.
* @param string $context Additional context about how the function was called or where the iframe tag is.
$value = apply_filters( 'wp_iframe_tag_add_loading_attr', 'lazy', $iframe, $context );
if ( ! in_array( $value, array( 'lazy', 'eager' ), true ) ) {
return str_replace( '<iframe', '<iframe loading="' . esc_attr( $value ) . '"', $iframe );
* Adds a 'wp-post-image' class to post thumbnails. Internal use only.
* Uses the {@see 'begin_fetch_post_thumbnail_html'} and {@see 'end_fetch_post_thumbnail_html'}
* action hooks to dynamically add/remove itself so as to only filter post thumbnails.
* @param string[] $attr Array of thumbnail attributes including src, class, alt, title, keyed by attribute name.
* @return string[] Modified array of attributes including the new 'wp-post-image' class.
function _wp_post_thumbnail_class_filter( $attr ) {
$attr['class'] .= ' wp-post-image';
* Adds '_wp_post_thumbnail_class_filter' callback to the 'wp_get_attachment_image_attributes'
* filter hook. Internal use only.
* @param string[] $attr Array of thumbnail attributes including src, class, alt, title, keyed by attribute name.
function _wp_post_thumbnail_class_filter_add( $attr ) {
add_filter( 'wp_get_attachment_image_attributes', '_wp_post_thumbnail_class_filter' );
* Removes the '_wp_post_thumbnail_class_filter' callback from the 'wp_get_attachment_image_attributes'
* filter hook. Internal use only.
* @param string[] $attr Array of thumbnail attributes including src, class, alt, title, keyed by attribute name.
function _wp_post_thumbnail_class_filter_remove( $attr ) {
remove_filter( 'wp_get_attachment_image_attributes', '_wp_post_thumbnail_class_filter' );
add_shortcode( 'wp_caption', 'img_caption_shortcode' );
add_shortcode( 'caption', 'img_caption_shortcode' );
* Builds the Caption shortcode output.
* Allows a plugin to replace the content that would otherwise be returned. The
* filter is {@see 'img_caption_shortcode'} and passes an empty string, the attr
* parameter and the content parameter values.
* The supported attributes for the shortcode are 'id', 'caption_id', 'align',
* 'width', 'caption', and 'class'.
* @since 3.9.0 The `class` attribute was added.
* @since 5.1.0 The `caption_id` attribute was added.
* Attributes of the caption shortcode.
* @type string $id ID of the image and caption container element, i.e. `<figure>` or `<div>`.
* @type string $caption_id ID of the caption element, i.e. `<figcaption>` or `<p>`.
* @type string $align Class name that aligns the caption. Default 'alignnone'. Accepts 'alignleft',
* 'aligncenter', alignright', 'alignnone'.
* @type int $width The width of the caption, in pixels.
* @type string $caption The caption text.
* @type string $class Additional class name(s) added to the caption container.
* @param string $content Shortcode content.
* @return string HTML content to display the caption.
function img_caption_shortcode( $attr, $content = null ) {
// New-style shortcode with the caption inside the shortcode with the link and image tags.
if ( ! isset( $attr['caption'] ) ) {
if ( preg_match( '#((?:<a [^>]+>\s*)?<img [^>]+>(?:\s*</a>)?)(.*)#is', $content, $matches ) ) {
$attr['caption'] = trim( $matches[2] );
} elseif ( strpos( $attr['caption'], '<' ) !== false ) {
$attr['caption'] = wp_kses( $attr['caption'], 'post' );
* Filters the default caption shortcode output.
* If the filtered output isn't empty, it will be used instead of generating
* the default caption template.
* @see img_caption_shortcode()
* @param string $output The caption output. Default empty.
* @param array $attr Attributes of the caption shortcode.
* @param string $content The image element, possibly wrapped in a hyperlink.
$output = apply_filters( 'img_caption_shortcode', '', $attr, $content );
if ( ! empty( $output ) ) {
$atts['width'] = (int) $atts['width'];
if ( $atts['width'] < 1 || empty( $atts['caption'] ) ) {
$atts['id'] = sanitize_html_class( $atts['id'] );
$id = 'id="' . esc_attr( $atts['id'] ) . '" ';
if ( $atts['caption_id'] ) {
$atts['caption_id'] = sanitize_html_class( $atts['caption_id'] );
} elseif ( $atts['id'] ) {
$atts['caption_id'] = 'caption-' . str_replace( '_', '-', $atts['id'] );
if ( $atts['caption_id'] ) {
$caption_id = 'id="' . esc_attr( $atts['caption_id'] ) . '" ';
$describedby = 'aria-describedby="' . esc_attr( $atts['caption_id'] ) . '" ';
$class = trim( 'wp-caption ' . $atts['align'] . ' ' . $atts['class'] );
$html5 = current_theme_supports( 'html5', 'caption' );
// HTML5 captions never added the extra 10px to the image width.
$width = $html5 ? $atts['width'] : ( 10 + $atts['width'] );
* Filters the width of an image's caption.
* By default, the caption is 10 pixels greater than the width of the image,
* to prevent post content from running up against a floated image.
* @see img_caption_shortcode()
* @param int $width Width of the caption in pixels. To remove this inline style,
* @param array $atts Attributes of the caption shortcode.
* @param string $content The image element, possibly wrapped in a hyperlink.
$caption_width = apply_filters( 'img_caption_shortcode_width', $width, $atts, $content );
$style = 'style="width: ' . (int) $caption_width . 'px" ';
'<figure %s%s%sclass="%s">%s%s</figure>',
do_shortcode( $content ),
'<figcaption %sclass="wp-caption-text">%s</figcaption>',
'<div %s%sclass="%s">%s%s</div>',
str_replace( '<img ', '<img ' . $describedby, do_shortcode( $content ) ),
'<p %sclass="wp-caption-text">%s</p>',
add_shortcode( 'gallery', 'gallery_shortcode' );
* Builds the Gallery shortcode output.
* This implements the functionality of the Gallery Shortcode for displaying
* WordPress images on a post.
* Attributes of the gallery shortcode.
* @type string $order Order of the images in the gallery. Default 'ASC'. Accepts 'ASC', 'DESC'.
* @type string $orderby The field to use when ordering the images. Default 'menu_order ID'.
* Accepts any valid SQL ORDERBY statement.
* @type string $itemtag HTML tag to use for each image in the gallery.
* Default 'dl', or 'figure' when the theme registers HTML5 gallery support.
* @type string $icontag HTML tag to use for each image's icon.
* Default 'dt', or 'div' when the theme registers HTML5 gallery support.
* @type string $captiontag HTML tag to use for each image's caption.
* Default 'dd', or 'figcaption' when the theme registers HTML5 gallery support.
* @type int $columns Number of columns of images to display. Default 3.
* @type string|int[] $size Size of the images to display. Accepts any registered image size name, or an array
* of width and height values in pixels (in that order). Default 'thumbnail'.
* @type string $ids A comma-separated list of IDs of attachments to display. Default empty.
* @type string $include A comma-separated list of IDs of attachments to include. Default empty.
* @type string $exclude A comma-separated list of IDs of attachments to exclude. Default empty.
* @type string $link What to link each image to. Default empty (links to the attachment page).
* Accepts 'file', 'none'.
* @return string HTML content to display gallery.
function gallery_shortcode( $attr ) {
if ( ! empty( $attr['ids'] ) ) {
// 'ids' is explicitly ordered, unless you specify otherwise.
if ( empty( $attr['orderby'] ) ) {
$attr['orderby'] = 'post__in';
$attr['include'] = $attr['ids'];
* Filters the default gallery shortcode output.
* If the filtered output isn't empty, it will be used instead of generating
* the default gallery template.
* @since 4.2.0 The `$instance` parameter was added.
* @see gallery_shortcode()
* @param string $output The gallery output. Default empty.
* @param array $attr Attributes of the gallery shortcode.
* @param int $instance Unique numeric ID of this gallery shortcode instance.
$output = apply_filters( 'post_gallery', '', $attr, $instance );
if ( ! empty( $output ) ) {
$html5 = current_theme_supports( 'html5', 'gallery' );
'orderby' => 'menu_order ID',
'id' => $post ? $post->ID : 0,
'itemtag' => $html5 ? 'figure' : 'dl',
'icontag' => $html5 ? 'div' : 'dt',
'captiontag' => $html5 ? 'figcaption' : 'dd',
if ( ! empty( $atts['include'] ) ) {
$_attachments = get_posts(
'include' => $atts['include'],
'post_status' => 'inherit',
'post_type' => 'attachment',
'post_mime_type' => 'image',
'order' => $atts['order'],
'orderby' => $atts['orderby'],
foreach ( $_attachments as $key => $val ) {
$attachments[ $val->ID ] = $_attachments[ $key ];
} elseif ( ! empty( $atts['exclude'] ) ) {
$attachments = get_children(
'exclude' => $atts['exclude'],
'post_status' => 'inherit',
'post_type' => 'attachment',
'post_mime_type' => 'image',
'order' => $atts['order'],
'orderby' => $atts['orderby'],
$attachments = get_children(
'post_status' => 'inherit',
'post_type' => 'attachment',
'post_mime_type' => 'image',
'order' => $atts['order'],
'orderby' => $atts['orderby'],
if ( ! empty( $post_parent_id ) ) {
$post_parent = get_post( $post_parent_id );
// terminate the shortcode execution if user cannot read the post or password-protected
( ! is_post_publicly_viewable( $post_parent->ID ) && ! current_user_can( 'read_post', $post_parent->ID ) )
|| post_password_required( $post_parent ) ) {
if ( empty( $attachments ) ) {
foreach ( $attachments as $att_id => $attachment ) {
if ( ! empty( $atts['link'] ) ) {
if ( 'none' === $atts['link'] ) {
$output .= wp_get_attachment_image( $att_id, $atts['size'], false, $attr );
$output .= wp_get_attachment_link( $att_id, $atts['size'], false );
$output .= wp_get_attachment_link( $att_id, $atts['size'], true );
$itemtag = tag_escape( $atts['itemtag'] );
$captiontag = tag_escape( $atts['captiontag'] );
$icontag = tag_escape( $atts['icontag'] );
$valid_tags = wp_kses_allowed_html( 'post' );
if ( ! isset( $valid_tags[ $itemtag ] ) ) {
if ( ! isset( $valid_tags[ $captiontag ] ) ) {
if ( ! isset( $valid_tags[ $icontag ] ) ) {
$columns = (int) $atts['columns'];
$itemwidth = $columns > 0 ? floor( 100 / $columns ) : 100;
$float = is_rtl() ? 'right' : 'left';
$selector = "gallery-{$instance}";
* Filters whether to print default gallery styles.
* @param bool $print Whether to print default gallery styles.
* Defaults to false if the theme supports HTML5 galleries.
* Otherwise, defaults to true.
if ( apply_filters( 'use_default_gallery_style', ! $html5 ) ) {
$type_attr = current_theme_supports( 'html5', 'style' ) ? '' : ' type="text/css"';
#{$selector} .gallery-item {
border: 2px solid #cfcfcf;
#{$selector} .gallery-caption {
/* see gallery_shortcode() in wp-includes/media.php */
$size_class = sanitize_html_class( is_array( $atts['size'] ) ? implode( 'x', $atts['size'] ) : $atts['size'] );
$gallery_div = "<div id='$selector' class='gallery galleryid-{$id} gallery-columns-{$columns} gallery-size-{$size_class}'>";
* Filters the default gallery shortcode CSS styles.
* @param string $gallery_style Default CSS styles and opening HTML div container
* for the gallery shortcode output.
$output = apply_filters( 'gallery_style', $gallery_style . $gallery_div );
foreach ( $attachments as $id => $attachment ) {
$attr = ( trim( $attachment->post_excerpt ) ) ? array( 'aria-describedby' => "$selector-$id" ) : '';
if ( ! empty( $atts['link'] ) && 'file' === $atts['link'] ) {
$image_output = wp_get_attachment_link( $id, $atts['size'], false, false, false, $attr );
} elseif ( ! empty( $atts['link'] ) && 'none' === $atts['link'] ) {
$image_output = wp_get_attachment_image( $id, $atts['size'], false, $attr );
$image_output = wp_get_attachment_link( $id, $atts['size'], true, false, false, $attr );
$image_meta = wp_get_attachment_metadata( $id );
if ( isset( $image_meta['height'], $image_meta['width'] ) ) {
$orientation = ( $image_meta['height'] > $image_meta['width'] ) ? 'portrait' : 'landscape';
$output .= "<{$itemtag} class='gallery-item'>";
<{$icontag} class='gallery-icon {$orientation}'>
if ( $captiontag && trim( $attachment->post_excerpt ) ) {
<{$captiontag} class='wp-caption-text gallery-caption' id='$selector-$id'>
" . wptexturize( $attachment->post_excerpt ) . "