: str_replace(): Passing null to parameter #2 ($replace) of type array|string is deprecated in
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.
* @since 2.8.0 Added the `$attr` parameter to set the shortcode output. New attributes included
* such as `size`, `itemtag`, `icontag`, `captiontag`, and columns. Changed markup from
* `div` tags to `dl`, `dt` and `dd` tags. Support more than one gallery on the
* @since 2.9.0 Added support for `include` and `exclude` to shortcode.
* @since 3.5.0 Use get_post() instead of global `$post`. Handle mapping of `ids` to `include`
* @since 3.6.0 Added validation for tags used in gallery shortcode. Add orientation information to items.
* @since 3.7.0 Introduced the `link` attribute.
* @since 3.9.0 `html5` gallery support, accepting 'itemtag', 'icontag', and 'captiontag' attributes.
* @since 4.0.0 Removed use of `extract()`.
* @since 4.1.0 Added attribute to `wp_get_attachment_link()` to output `aria-describedby`.
* @since 4.2.0 Passed the shortcode instance ID to `post_gallery` and `post_playlist` filters.
* @since 4.6.0 Standardized filter docs to match documentation standards for PHP.
* @since 5.1.0 Code cleanup for WPCS 1.0.0 coding standards.
* @since 5.3.0 Saved progress of intermediate image creation after upload.
* @since 5.5.0 Ensured that galleries can be output as a list of links in feeds.
* @since 5.6.0 Replaced order-style PHP type conversion functions with typecasts. Fix logic for
* an array of image dimensions.
* 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 the user cannot read the post or it is password-protected.
if ( ! 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 ) . "
$output .= "</{$itemtag}>";
if ( ! $html5 && $columns > 0 && 0 === ++$i % $columns ) {
$output .= '<br style="clear: both" />';
if ( ! $html5 && $columns > 0 && 0 !== $i % $columns ) {
<br style='clear: both' />";
* Outputs the templates used by playlists.
function wp_underscore_playlist_templates() {
<script type="text/html" id="tmpl-wp-playlist-current-item">
<# if ( data.thumb && data.thumb.src ) { #>
<img src="{{ data.thumb.src }}" alt="" />
<div class="wp-playlist-caption">
<span class="wp-playlist-item-meta wp-playlist-item-title">
<# if ( data.meta.album || data.meta.artist ) { #>
/* translators: %s: Playlist item title. */
printf( _x( '“%s”', 'playlist item title' ), '{{ data.title }}' );
<# if ( data.meta.album ) { #><span class="wp-playlist-item-meta wp-playlist-item-album">{{ data.meta.album }}</span><# } #>
<# if ( data.meta.artist ) { #><span class="wp-playlist-item-meta wp-playlist-item-artist">{{ data.meta.artist }}</span><# } #>
<script type="text/html" id="tmpl-wp-playlist-item">
<div class="wp-playlist-item">
<a class="wp-playlist-caption" href="{{ data.src }}">
{{ data.index ? ( data.index + '. ' ) : '' }}
<# if ( data.caption ) { #>
<# if ( data.artists && data.meta.artist ) { #>
<span class="wp-playlist-item-title">
/* translators: %s: Playlist item title. */
printf( _x( '“%s”', 'playlist item title' ), '{{{ data.title }}}' );
<span class="wp-playlist-item-artist"> — {{ data.meta.artist }}</span>
<span class="wp-playlist-item-title">{{{ data.title }}}</span>
<# if ( data.meta.length_formatted ) { #>
<div class="wp-playlist-item-length">{{ data.meta.length_formatted }}</div>
* Outputs and enqueues default scripts and styles for playlists.
* @param string $type Type of playlist. Accepts 'audio' or 'video'.
function wp_playlist_scripts( $type ) {
wp_enqueue_style( 'wp-mediaelement' );
wp_enqueue_script( 'wp-playlist' );
<!--[if lt IE 9]><script>document.createElement('<?php echo esc_js( $type ); ?>');</script><![endif]-->
add_action( 'wp_footer', 'wp_underscore_playlist_templates', 0 );
add_action( 'admin_footer', 'wp_underscore_playlist_templates', 0 );
* Builds the Playlist shortcode output.
* This implements the functionality of the playlist shortcode for displaying
* a collection of WordPress audio or video files in a post.
* @global int $content_width
* Array of default playlist attributes.
* @type string $type Type of playlist to display. Accepts 'audio' or 'video'. Default 'audio'.
* @type string $order Designates ascending or descending order of items in the playlist.
* Accepts 'ASC', 'DESC'. Default 'ASC'.
* @type string $orderby Any column, or columns, to sort the playlist. If $ids are
* passed, this defaults to the order of the $ids array ('post__in').
* Otherwise default is 'menu_order ID'.
* @type int $id If an explicit $ids array is not present, this parameter
* will determine which attachments are used for the playlist.
* Default is the current post ID.
* @type array $ids Create a playlist out of these explicit attachment IDs. If empty,
* a playlist will be created from all $type attachments of $id.
* @type array $exclude List of specific attachment IDs to exclude from the playlist. Default empty.
* @type string $style Playlist style to use. Accepts 'light' or 'dark'. Default 'light'.
* @type bool $tracklist Whether to show or hide the playlist. Default true.
* @type bool $tracknumbers Whether to show or hide the numbers next to entries in the playlist. Default true.
* @type bool $images Show or hide the video or audio thumbnail (Featured Image/post
* thumbnail). Default true.
* @type bool $artists Whether to show or hide artist name in the playlist. Default true.
* @return string Playlist output. Empty string if the passed type is unsupported.
function wp_playlist_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 playlist output.
* Returning a non-empty value from the filter will short-circuit generation
* of the default playlist output, returning the passed value instead.
* @since 4.2.0 The `$instance` parameter was added.
* @param string $output Playlist output. Default empty.
* @param array $attr An array of shortcode attributes.
* @param int $instance Unique numeric ID of this playlist shortcode instance.
$output = apply_filters( 'post_playlist', '', $attr, $instance );
if ( ! empty( $output ) ) {
'orderby' => 'menu_order ID',
'id' => $post ? $post->ID : 0,
if ( 'audio' !== $atts['type'] ) {
'post_status' => 'inherit',
'post_type' => 'attachment',
'post_mime_type' => $atts['type'],
'order' => $atts['order'],
'orderby' => $atts['orderby'],
if ( ! empty( $atts['include'] ) ) {
$args['include'] = $atts['include'];
$_attachments = get_posts( $args );
foreach ( $_attachments as $key => $val ) {
$attachments[ $val->ID ] = $_attachments[ $key ];
} elseif ( ! empty( $atts['exclude'] ) ) {
$args['post_parent'] = $id;
$args['exclude'] = $atts['exclude'];
$attachments = get_children( $args );
$args['post_parent'] = $id;
$attachments = get_children( $args );
if ( ! empty( $args['post_parent'] ) ) {