wp/wp-includes/media.php
changeset 7 cf61fcea0001
parent 5 5e2f62d02dcd
child 9 177826044cd9
equal deleted inserted replaced
6:490d5cc509ed 7:cf61fcea0001
     3  * WordPress API for media display.
     3  * WordPress API for media display.
     4  *
     4  *
     5  * @package WordPress
     5  * @package WordPress
     6  * @subpackage Media
     6  * @subpackage Media
     7  */
     7  */
       
     8 
       
     9 /**
       
    10  * Retrieve additional image sizes.
       
    11  *
       
    12  * @since 4.7.0
       
    13  *
       
    14  * @global array $_wp_additional_image_sizes
       
    15  *
       
    16  * @return array Additional images size data.
       
    17  */
       
    18 function wp_get_additional_image_sizes() {
       
    19 	global $_wp_additional_image_sizes;
       
    20 	if ( ! $_wp_additional_image_sizes ) {
       
    21 		$_wp_additional_image_sizes = array();
       
    22 	}
       
    23 	return $_wp_additional_image_sizes;
       
    24 }
     8 
    25 
     9 /**
    26 /**
    10  * Scale down the default size of an image.
    27  * Scale down the default size of an image.
    11  *
    28  *
    12  * This is so that the image is a better fit for the editor and theme.
    29  * This is so that the image is a better fit for the editor and theme.
    13  *
    30  *
    14  * The `$size` parameter accepts either an array or a string. The supported string
    31  * The `$size` parameter accepts either an array or a string. The supported string
    15  * values are 'thumb' or 'thumbnail' for the given thumbnail size or defaults at
    32  * values are 'thumb' or 'thumbnail' for the given thumbnail size or defaults at
    16  * 128 width and 96 height in pixels. Also supported for the string value is
    33  * 128 width and 96 height in pixels. Also supported for the string value is
    17  * 'medium' and 'full'. The 'full' isn't actually supported, but any value other
    34  * 'medium', 'medium_large' and 'full'. The 'full' isn't actually supported, but any value other
    18  * than the supported will result in the content_width size or 500 if that is
    35  * than the supported will result in the content_width size or 500 if that is
    19  * not set.
    36  * not set.
    20  *
    37  *
    21  * Finally, there is a filter named {@see 'editor_max_image_size'}, that will be
    38  * Finally, there is a filter named {@see 'editor_max_image_size'}, that will be
    22  * called on the calculated array for width and height, respectively. The second
    39  * called on the calculated array for width and height, respectively. The second
    24  * type for the hook is an array with the width as the first element and the
    41  * type for the hook is an array with the width as the first element and the
    25  * height as the second element.
    42  * height as the second element.
    26  *
    43  *
    27  * @since 2.5.0
    44  * @since 2.5.0
    28  *
    45  *
       
    46  * @global int   $content_width
       
    47  *
    29  * @param int          $width   Width of the image in pixels.
    48  * @param int          $width   Width of the image in pixels.
    30  * @param int          $height  Height of the image in pixels.
    49  * @param int          $height  Height of the image in pixels.
    31  * @param string|array $size    Optional. Size or array of sizes of what the result image
    50  * @param string|array $size    Optional. Image size. Accepts any valid image size, or an array
    32  *                              should be. Accepts any valid image size name. Default 'medium'.
    51  *                              of width and height values in pixels (in that order).
       
    52  *                              Default 'medium'.
    33  * @param string       $context Optional. Could be 'display' (like in a theme) or 'edit'
    53  * @param string       $context Optional. Could be 'display' (like in a theme) or 'edit'
    34  *                              (like inserting into an editor). Default null.
    54  *                              (like inserting into an editor). Default null.
    35  * @return array Width and height of what the result image should resize to.
    55  * @return array Width and height of what the result image should resize to.
    36  */
    56  */
    37 function image_constrain_size_for_editor( $width, $height, $size = 'medium', $context = null ) {
    57 function image_constrain_size_for_editor( $width, $height, $size = 'medium', $context = null ) {
    38 	global $content_width, $_wp_additional_image_sizes;
    58 	global $content_width;
       
    59 
       
    60 	$_wp_additional_image_sizes = wp_get_additional_image_sizes();
    39 
    61 
    40 	if ( ! $context )
    62 	if ( ! $context )
    41 		$context = is_admin() ? 'edit' : 'display';
    63 		$context = is_admin() ? 'edit' : 'display';
    42 
    64 
    43 	if ( is_array($size) ) {
    65 	if ( is_array($size) ) {
    54 		}
    76 		}
    55 	}
    77 	}
    56 	elseif ( $size == 'medium' ) {
    78 	elseif ( $size == 'medium' ) {
    57 		$max_width = intval(get_option('medium_size_w'));
    79 		$max_width = intval(get_option('medium_size_w'));
    58 		$max_height = intval(get_option('medium_size_h'));
    80 		$max_height = intval(get_option('medium_size_h'));
    59 		// if no width is set, default to the theme content width if available
    81 
       
    82 	}
       
    83 	elseif ( $size == 'medium_large' ) {
       
    84 		$max_width = intval( get_option( 'medium_large_size_w' ) );
       
    85 		$max_height = intval( get_option( 'medium_large_size_h' ) );
       
    86 
       
    87 		if ( intval( $content_width ) > 0 ) {
       
    88 			$max_width = min( intval( $content_width ), $max_width );
       
    89 		}
    60 	}
    90 	}
    61 	elseif ( $size == 'large' ) {
    91 	elseif ( $size == 'large' ) {
    62 		/*
    92 		/*
    63 		 * We're inserting a large size image into the editor. If it's a really
    93 		 * We're inserting a large size image into the editor. If it's a really
    64 		 * big image we'll scale it down to fit reasonably within the editor
    94 		 * big image we'll scale it down to fit reasonably within the editor
    65 		 * itself, and within the theme's content width if it's known. The user
    95 		 * itself, and within the theme's content width if it's known. The user
    66 		 * can resize it in the editor if they wish.
    96 		 * can resize it in the editor if they wish.
    67 		 */
    97 		 */
    68 		$max_width = intval(get_option('large_size_w'));
    98 		$max_width = intval(get_option('large_size_w'));
    69 		$max_height = intval(get_option('large_size_h'));
    99 		$max_height = intval(get_option('large_size_h'));
    70 		if ( intval($content_width) > 0 )
   100 		if ( intval($content_width) > 0 ) {
    71 			$max_width = min( intval($content_width), $max_width );
   101 			$max_width = min( intval($content_width), $max_width );
    72 	} elseif ( isset( $_wp_additional_image_sizes ) && count( $_wp_additional_image_sizes ) && in_array( $size, array_keys( $_wp_additional_image_sizes ) ) ) {
   102 		}
       
   103 	} elseif ( ! empty( $_wp_additional_image_sizes ) && in_array( $size, array_keys( $_wp_additional_image_sizes ) ) ) {
    73 		$max_width = intval( $_wp_additional_image_sizes[$size]['width'] );
   104 		$max_width = intval( $_wp_additional_image_sizes[$size]['width'] );
    74 		$max_height = intval( $_wp_additional_image_sizes[$size]['height'] );
   105 		$max_height = intval( $_wp_additional_image_sizes[$size]['height'] );
    75 		if ( intval($content_width) > 0 && 'edit' == $context ) // Only in admin. Assume that theme authors know what they're doing.
   106 		// Only in admin. Assume that theme authors know what they're doing.
    76 			$max_width = min( intval($content_width), $max_width );
   107 		if ( intval( $content_width ) > 0 && 'edit' === $context ) {
       
   108 			$max_width = min( intval( $content_width ), $max_width );
       
   109 		}
    77 	}
   110 	}
    78 	// $size == 'full' has no constraint
   111 	// $size == 'full' has no constraint
    79 	else {
   112 	else {
    80 		$max_width = $width;
   113 		$max_width = $width;
    81 		$max_height = $height;
   114 		$max_height = $height;
    82 	}
   115 	}
    83 
   116 
    84 	/**
   117 	/**
    85 	 * Filter the maximum image size dimensions for the editor.
   118 	 * Filters the maximum image size dimensions for the editor.
    86 	 *
   119 	 *
    87 	 * @since 2.5.0
   120 	 * @since 2.5.0
    88 	 *
   121 	 *
    89 	 * @param array        $max_image_size An array with the width as the first element,
   122 	 * @param array        $max_image_size An array with the width as the first element,
    90 	 *                                     and the height as the second element.
   123 	 *                                     and the height as the second element.
   133  *
   166  *
   134  * The URL might be the original image, or it might be a resized version. This
   167  * The URL might be the original image, or it might be a resized version. This
   135  * function won't create a new resized copy, it will just return an already
   168  * function won't create a new resized copy, it will just return an already
   136  * resized one if it exists.
   169  * resized one if it exists.
   137  *
   170  *
   138  * A plugin may use the 'image_downsize' filter to hook into and offer image
   171  * A plugin may use the {@see 'image_downsize'} filter to hook into and offer image
   139  * resizing services for images. The hook must return an array with the same
   172  * resizing services for images. The hook must return an array with the same
   140  * elements that are returned in the function. The first element being the URL
   173  * elements that are returned in the function. The first element being the URL
   141  * to the new image that was resized.
   174  * to the new image that was resized.
   142  *
   175  *
   143  * @since 2.5.0
   176  * @since 2.5.0
   144  *
   177  *
   145  * @param int          $id   Attachment ID for image.
   178  * @param int          $id   Attachment ID for image.
   146  * @param array|string $size Optional. Image size to scale to. Accepts a registered image size
   179  * @param array|string $size Optional. Image size to scale to. Accepts any valid image size,
   147  *                           or flat array of height and width values. Default 'medium'.
   180  *                           or an array of width and height values in pixels (in that order).
   148  * @return bool|array False on failure, array on success.
   181  *                           Default 'medium'.
       
   182  * @return false|array Array containing the image URL, width, height, and boolean for whether
       
   183  *                     the image is an intermediate size. False on failure.
   149  */
   184  */
   150 function image_downsize( $id, $size = 'medium' ) {
   185 function image_downsize( $id, $size = 'medium' ) {
   151 
   186 	$is_image = wp_attachment_is_image( $id );
   152 	if ( !wp_attachment_is_image($id) )
   187 
   153 		return false;
   188 	/**
   154 
   189 	 * Filters whether to preempt the output of image_downsize().
   155 	/**
       
   156 	 * Filter whether to preempt the output of image_downsize().
       
   157 	 *
   190 	 *
   158 	 * Passing a truthy value to the filter will effectively short-circuit
   191 	 * Passing a truthy value to the filter will effectively short-circuit
   159 	 * down-sizing the image, returning that value as output instead.
   192 	 * down-sizing the image, returning that value as output instead.
   160 	 *
   193 	 *
   161 	 * @since 2.5.0
   194 	 * @since 2.5.0
   162 	 *
   195 	 *
   163 	 * @param bool         $downsize Whether to short-circuit the image downsize. Default false.
   196 	 * @param bool         $downsize Whether to short-circuit the image downsize. Default false.
   164 	 * @param int          $id       Attachment ID for image.
   197 	 * @param int          $id       Attachment ID for image.
   165 	 * @param array|string $size     Size of image, either array or string. Default 'medium'.
   198 	 * @param array|string $size     Size of image. Image size or array of width and height values (in that order).
       
   199 	 *                               Default 'medium'.
   166 	 */
   200 	 */
   167 	if ( $out = apply_filters( 'image_downsize', false, $id, $size ) ) {
   201 	if ( $out = apply_filters( 'image_downsize', false, $id, $size ) ) {
   168 		return $out;
   202 		return $out;
   169 	}
   203 	}
   170 
   204 
   171 	$img_url = wp_get_attachment_url($id);
   205 	$img_url = wp_get_attachment_url($id);
   172 	$meta = wp_get_attachment_metadata($id);
   206 	$meta = wp_get_attachment_metadata($id);
   173 	$width = $height = 0;
   207 	$width = $height = 0;
   174 	$is_intermediate = false;
   208 	$is_intermediate = false;
   175 	$img_url_basename = wp_basename($img_url);
   209 	$img_url_basename = wp_basename($img_url);
       
   210 
       
   211 	// If the file isn't an image, attempt to replace its URL with a rendered image from its meta.
       
   212 	// Otherwise, a non-image type could be returned.
       
   213 	if ( ! $is_image ) {
       
   214 		if ( ! empty( $meta['sizes'] ) ) {
       
   215 			$img_url = str_replace( $img_url_basename, $meta['sizes']['full']['file'], $img_url );
       
   216 			$img_url_basename = $meta['sizes']['full']['file'];
       
   217 			$width = $meta['sizes']['full']['width'];
       
   218 			$height = $meta['sizes']['full']['height'];
       
   219 		} else {
       
   220 			return false;
       
   221 		}
       
   222 	}
   176 
   223 
   177 	// try for a new style intermediate size
   224 	// try for a new style intermediate size
   178 	if ( $intermediate = image_get_intermediate_size($id, $size) ) {
   225 	if ( $intermediate = image_get_intermediate_size($id, $size) ) {
   179 		$img_url = str_replace($img_url_basename, $intermediate['file'], $img_url);
   226 		$img_url = str_replace($img_url_basename, $intermediate['file'], $img_url);
   180 		$width = $intermediate['width'];
   227 		$width = $intermediate['width'];
   222  * @global array $_wp_additional_image_sizes Associative array of additional image sizes.
   269  * @global array $_wp_additional_image_sizes Associative array of additional image sizes.
   223  *
   270  *
   224  * @param string     $name   Image size identifier.
   271  * @param string     $name   Image size identifier.
   225  * @param int        $width  Image width in pixels.
   272  * @param int        $width  Image width in pixels.
   226  * @param int        $height Image height in pixels.
   273  * @param int        $height Image height in pixels.
   227  * @param bool|array $crop   Optional. Whether to crop images to specified height and width or resize.
   274  * @param bool|array $crop   Optional. Whether to crop images to specified width and height or resize.
   228  *                           An array can specify positioning of the crop area. Default false.
   275  *                           An array can specify positioning of the crop area. Default false.
   229  */
   276  */
   230 function add_image_size( $name, $width = 0, $height = 0, $crop = false ) {
   277 function add_image_size( $name, $width = 0, $height = 0, $crop = false ) {
   231 	global $_wp_additional_image_sizes;
   278 	global $_wp_additional_image_sizes;
   232 
   279 
   244  *
   291  *
   245  * @param string $name The image size to check.
   292  * @param string $name The image size to check.
   246  * @return bool True if the image size exists, false if not.
   293  * @return bool True if the image size exists, false if not.
   247  */
   294  */
   248 function has_image_size( $name ) {
   295 function has_image_size( $name ) {
   249 	global $_wp_additional_image_sizes;
   296 	$sizes = wp_get_additional_image_sizes();
   250 
   297 	return isset( $sizes[ $name ] );
   251 	return isset( $_wp_additional_image_sizes[ $name ] );
       
   252 }
   298 }
   253 
   299 
   254 /**
   300 /**
   255  * Remove a new image size.
   301  * Remove a new image size.
   256  *
   302  *
   257  * @since 3.9.0
   303  * @since 3.9.0
       
   304  *
       
   305  * @global array $_wp_additional_image_sizes
   258  *
   306  *
   259  * @param string $name The image size to remove.
   307  * @param string $name The image size to remove.
   260  * @return bool True if the image size was successfully removed, false on failure.
   308  * @return bool True if the image size was successfully removed, false on failure.
   261  */
   309  */
   262 function remove_image_size( $name ) {
   310 function remove_image_size( $name ) {
   277  *
   325  *
   278  * @see add_image_size() for details on cropping behavior.
   326  * @see add_image_size() for details on cropping behavior.
   279  *
   327  *
   280  * @param int        $width  Image width in pixels.
   328  * @param int        $width  Image width in pixels.
   281  * @param int        $height Image height in pixels.
   329  * @param int        $height Image height in pixels.
   282  * @param bool|array $crop   Optional. Whether to crop images to specified height and width or resize.
   330  * @param bool|array $crop   Optional. Whether to crop images to specified width and height or resize.
   283  *                           An array can specify positioning of the crop area. Default false.
   331  *                           An array can specify positioning of the crop area. Default false.
   284  */
   332  */
   285 function set_post_thumbnail_size( $width = 0, $height = 0, $crop = false ) {
   333 function set_post_thumbnail_size( $width = 0, $height = 0, $crop = false ) {
   286 	add_image_size( 'post-thumbnail', $width, $height, $crop );
   334 	add_image_size( 'post-thumbnail', $width, $height, $crop );
   287 }
   335 }
   288 
   336 
   289 /**
   337 /**
   290  * Gets an img tag for an image attachment, scaling it down if requested.
   338  * Gets an img tag for an image attachment, scaling it down if requested.
   291  *
   339  *
   292  * The filter 'get_image_tag_class' allows for changing the class name for the
   340  * The {@see 'get_image_tag_class'} filter allows for changing the class name for the
   293  * image without having to use regular expressions on the HTML content. The
   341  * image without having to use regular expressions on the HTML content. The
   294  * parameters are: what WordPress will use for the class, the Attachment ID,
   342  * parameters are: what WordPress will use for the class, the Attachment ID,
   295  * image align value, and the size the image should be.
   343  * image align value, and the size the image should be.
   296  *
   344  *
   297  * The second filter 'get_image_tag' has the HTML content, which can then be
   345  * The second filter, {@see 'get_image_tag'}, has the HTML content, which can then be
   298  * further manipulated by a plugin to change all attribute values and even HTML
   346  * further manipulated by a plugin to change all attribute values and even HTML
   299  * content.
   347  * content.
   300  *
   348  *
   301  * @since 2.5.0
   349  * @since 2.5.0
   302  *
   350  *
   303  * @param int          $id    Attachment ID.
   351  * @param int          $id    Attachment ID.
   304  * @param string       $alt   Image Description for the alt attribute.
   352  * @param string       $alt   Image Description for the alt attribute.
   305  * @param string       $title Image Description for the title attribute.
   353  * @param string       $title Image Description for the title attribute.
   306  * @param string       $align Part of the class name for aligning the image.
   354  * @param string       $align Part of the class name for aligning the image.
   307  * @param string|array $size  Optional. Registered image size to retrieve a tag for, or flat array
   355  * @param string|array $size  Optional. Registered image size to retrieve a tag for. Accepts any
   308  *                            of height and width values. Default 'medium'.
   356  *                            valid image size, or an array of width and height values in pixels
       
   357  *                            (in that order). Default 'medium'.
   309  * @return string HTML IMG element for given image attachment
   358  * @return string HTML IMG element for given image attachment
   310  */
   359  */
   311 function get_image_tag( $id, $alt, $title, $align, $size = 'medium' ) {
   360 function get_image_tag( $id, $alt, $title, $align, $size = 'medium' ) {
   312 
   361 
   313 	list( $img_src, $width, $height ) = image_downsize($id, $size);
   362 	list( $img_src, $width, $height ) = image_downsize($id, $size);
   316 	$title = $title ? 'title="' . esc_attr( $title ) . '" ' : '';
   365 	$title = $title ? 'title="' . esc_attr( $title ) . '" ' : '';
   317 
   366 
   318 	$class = 'align' . esc_attr($align) .' size-' . esc_attr($size) . ' wp-image-' . $id;
   367 	$class = 'align' . esc_attr($align) .' size-' . esc_attr($size) . ' wp-image-' . $id;
   319 
   368 
   320 	/**
   369 	/**
   321 	 * Filter the value of the attachment's image tag class attribute.
   370 	 * Filters the value of the attachment's image tag class attribute.
   322 	 *
   371 	 *
   323 	 * @since 2.6.0
   372 	 * @since 2.6.0
   324 	 *
   373 	 *
   325 	 * @param string $class CSS class name or space-separated list of classes.
   374 	 * @param string       $class CSS class name or space-separated list of classes.
   326 	 * @param int    $id    Attachment ID.
   375 	 * @param int          $id    Attachment ID.
   327 	 * @param string $align Part of the class name for aligning the image.
   376 	 * @param string       $align Part of the class name for aligning the image.
   328 	 * @param string $size  Optional. Default is 'medium'.
   377 	 * @param string|array $size  Size of image. Image size or array of width and height values (in that order).
       
   378 	 *                            Default 'medium'.
   329 	 */
   379 	 */
   330 	$class = apply_filters( 'get_image_tag_class', $class, $id, $align, $size );
   380 	$class = apply_filters( 'get_image_tag_class', $class, $id, $align, $size );
   331 
   381 
   332 	$html = '<img src="' . esc_attr($img_src) . '" alt="' . esc_attr($alt) . '" ' . $title . $hwstring . 'class="' . $class . '" />';
   382 	$html = '<img src="' . esc_attr($img_src) . '" alt="' . esc_attr($alt) . '" ' . $title . $hwstring . 'class="' . $class . '" />';
   333 
   383 
   334 	/**
   384 	/**
   335 	 * Filter the HTML content for the image tag.
   385 	 * Filters the HTML content for the image tag.
   336 	 *
   386 	 *
   337 	 * @since 2.6.0
   387 	 * @since 2.6.0
   338 	 *
   388 	 *
   339 	 * @param string $html  HTML content for the image.
   389 	 * @param string       $html  HTML content for the image.
   340 	 * @param int    $id    Attachment ID.
   390 	 * @param int          $id    Attachment ID.
   341 	 * @param string $alt   Alternate text.
   391 	 * @param string       $alt   Alternate text.
   342 	 * @param string $title Attachment title.
   392 	 * @param string       $title Attachment title.
   343 	 * @param string $align Part of the class name for aligning the image.
   393 	 * @param string       $align Part of the class name for aligning the image.
   344 	 * @param string $size  Optional. Default is 'medium'.
   394 	 * @param string|array $size  Size of image. Image size or array of width and height values (in that order).
   345 	 */
   395 	 *                            Default 'medium'.
   346 	$html = apply_filters( 'get_image_tag', $html, $id, $alt, $title, $align, $size );
   396 	 */
   347 
   397 	return apply_filters( 'get_image_tag', $html, $id, $alt, $title, $align, $size );
   348 	return $html;
       
   349 }
   398 }
   350 
   399 
   351 /**
   400 /**
   352  * Calculates the new dimensions for a down-sampled image.
   401  * Calculates the new dimensions for a down-sampled image.
   353  *
   402  *
   408 	if ( $did_height && $h == $max_height - 1 ) {
   457 	if ( $did_height && $h == $max_height - 1 ) {
   409 		$h = $max_height; // Round it up
   458 		$h = $max_height; // Round it up
   410 	}
   459 	}
   411 
   460 
   412 	/**
   461 	/**
   413 	 * Filter dimensions to constrain down-sampled images to.
   462 	 * Filters dimensions to constrain down-sampled images to.
   414 	 *
   463 	 *
   415 	 * @since 4.1.0
   464 	 * @since 4.1.0
   416 	 *
   465 	 *
   417 	 * @param array $dimensions     The image width and height.
   466 	 * @param array $dimensions     The image width and height.
   418 	 * @param int 	$current_width  The current width of the image.
   467 	 * @param int 	$current_width  The current width of the image.
   441  *
   490  *
   442  * @param int        $orig_w Original width in pixels.
   491  * @param int        $orig_w Original width in pixels.
   443  * @param int        $orig_h Original height in pixels.
   492  * @param int        $orig_h Original height in pixels.
   444  * @param int        $dest_w New width in pixels.
   493  * @param int        $dest_w New width in pixels.
   445  * @param int        $dest_h New height in pixels.
   494  * @param int        $dest_h New height in pixels.
   446  * @param bool|array $crop   Optional. Whether to crop image to specified height and width or resize.
   495  * @param bool|array $crop   Optional. Whether to crop image to specified width and height or resize.
   447  *                           An array can specify positioning of the crop area. Default false.
   496  *                           An array can specify positioning of the crop area. Default false.
   448  * @return bool|array False on failure. Returned array matches parameters for `imagecopyresampled()`.
   497  * @return false|array False on failure. Returned array matches parameters for `imagecopyresampled()`.
   449  */
   498  */
   450 function image_resize_dimensions($orig_w, $orig_h, $dest_w, $dest_h, $crop = false) {
   499 function image_resize_dimensions( $orig_w, $orig_h, $dest_w, $dest_h, $crop = false ) {
   451 
   500 
   452 	if ($orig_w <= 0 || $orig_h <= 0)
   501 	if ($orig_w <= 0 || $orig_h <= 0)
   453 		return false;
   502 		return false;
   454 	// at least one of dest_w or dest_h must be specific
   503 	// at least one of dest_w or dest_h must be specific
   455 	if ($dest_w <= 0 && $dest_h <= 0)
   504 	if ($dest_w <= 0 && $dest_h <= 0)
   456 		return false;
   505 		return false;
   457 
   506 
   458 	/**
   507 	/**
   459 	 * Filter whether to preempt calculating the image resize dimensions.
   508 	 * Filters whether to preempt calculating the image resize dimensions.
   460 	 *
   509 	 *
   461 	 * Passing a non-null value to the filter will effectively short-circuit
   510 	 * Passing a non-null value to the filter will effectively short-circuit
   462 	 * image_resize_dimensions(), returning that value instead.
   511 	 * image_resize_dimensions(), returning that value instead.
   463 	 *
   512 	 *
   464 	 * @since 3.4.0
   513 	 * @since 3.4.0
   466 	 * @param null|mixed $null   Whether to preempt output of the resize dimensions.
   515 	 * @param null|mixed $null   Whether to preempt output of the resize dimensions.
   467 	 * @param int        $orig_w Original width in pixels.
   516 	 * @param int        $orig_w Original width in pixels.
   468 	 * @param int        $orig_h Original height in pixels.
   517 	 * @param int        $orig_h Original height in pixels.
   469 	 * @param int        $dest_w New width in pixels.
   518 	 * @param int        $dest_w New width in pixels.
   470 	 * @param int        $dest_h New height in pixels.
   519 	 * @param int        $dest_h New height in pixels.
   471 	 * @param bool|array $crop   Whether to crop image to specified height and width or resize.
   520 	 * @param bool|array $crop   Whether to crop image to specified width and height or resize.
   472 	 *                           An array can specify positioning of the crop area. Default false.
   521 	 *                           An array can specify positioning of the crop area. Default false.
   473 	 */
   522 	 */
   474 	$output = apply_filters( 'image_resize_dimensions', null, $orig_w, $orig_h, $dest_w, $dest_h, $crop );
   523 	$output = apply_filters( 'image_resize_dimensions', null, $orig_w, $orig_h, $dest_w, $dest_h, $crop );
   475 	if ( null !== $output )
   524 	if ( null !== $output )
   476 		return $output;
   525 		return $output;
   539 
   588 
   540 /**
   589 /**
   541  * Resizes an image to make a thumbnail or intermediate size.
   590  * Resizes an image to make a thumbnail or intermediate size.
   542  *
   591  *
   543  * The returned array has the file size, the image width, and image height. The
   592  * The returned array has the file size, the image width, and image height. The
   544  * filter 'image_make_intermediate_size' can be used to hook in and change the
   593  * {@see 'image_make_intermediate_size'} filter can be used to hook in and change the
   545  * values of the returned array. The only parameter is the resized file path.
   594  * values of the returned array. The only parameter is the resized file path.
   546  *
   595  *
   547  * @since 2.5.0
   596  * @since 2.5.0
   548  *
   597  *
   549  * @param string $file   File path.
   598  * @param string $file   File path.
   550  * @param int    $width  Image width.
   599  * @param int    $width  Image width.
   551  * @param int    $height Image height.
   600  * @param int    $height Image height.
   552  * @param bool   $crop   Optional. Whether to crop image to specified height and width or resize.
   601  * @param bool   $crop   Optional. Whether to crop image to specified width and height or resize.
   553  *                       Default false.
   602  *                       Default false.
   554  * @return bool|array False, if no image was created. Metadata array on success.
   603  * @return false|array False, if no image was created. Metadata array on success.
   555  */
   604  */
   556 function image_make_intermediate_size( $file, $width, $height, $crop = false ) {
   605 function image_make_intermediate_size( $file, $width, $height, $crop = false ) {
   557 	if ( $width || $height ) {
   606 	if ( $width || $height ) {
   558 		$editor = wp_get_image_editor( $file );
   607 		$editor = wp_get_image_editor( $file );
   559 
   608 
   566 			unset( $resized_file['path'] );
   615 			unset( $resized_file['path'] );
   567 			return $resized_file;
   616 			return $resized_file;
   568 		}
   617 		}
   569 	}
   618 	}
   570 	return false;
   619 	return false;
       
   620 }
       
   621 
       
   622 /**
       
   623  * Helper function to test if aspect ratios for two images match.
       
   624  *
       
   625  * @since 4.6.0
       
   626  *
       
   627  * @param int $source_width  Width of the first image in pixels.
       
   628  * @param int $source_height Height of the first image in pixels.
       
   629  * @param int $target_width  Width of the second image in pixels.
       
   630  * @param int $target_height Height of the second image in pixels.
       
   631  * @return bool True if aspect ratios match within 1px. False if not.
       
   632  */
       
   633 function wp_image_matches_ratio( $source_width, $source_height, $target_width, $target_height ) {
       
   634 	/*
       
   635 	 * To test for varying crops, we constrain the dimensions of the larger image
       
   636 	 * to the dimensions of the smaller image and see if they match.
       
   637 	 */
       
   638 	if ( $source_width > $target_width ) {
       
   639 		$constrained_size = wp_constrain_dimensions( $source_width, $source_height, $target_width );
       
   640 		$expected_size = array( $target_width, $target_height );
       
   641 	} else {
       
   642 		$constrained_size = wp_constrain_dimensions( $target_width, $target_height, $source_width );
       
   643 		$expected_size = array( $source_width, $source_height );
       
   644 	}
       
   645 
       
   646 	// If the image dimensions are within 1px of the expected size, we consider it a match.
       
   647 	$matched = ( abs( $constrained_size[0] - $expected_size[0] ) <= 1 && abs( $constrained_size[1] - $expected_size[1] ) <= 1 );
       
   648 
       
   649 	return $matched;
   571 }
   650 }
   572 
   651 
   573 /**
   652 /**
   574  * Retrieves the image's intermediate size (resized) path, width, and height.
   653  * Retrieves the image's intermediate size (resized) path, width, and height.
   575  *
   654  *
   590  * browser scale down the image.
   669  * browser scale down the image.
   591  *
   670  *
   592  * @since 2.5.0
   671  * @since 2.5.0
   593  *
   672  *
   594  * @param int          $post_id Attachment ID.
   673  * @param int          $post_id Attachment ID.
   595  * @param array|string $size    Optional. Registered image size to retrieve or flat array of height
   674  * @param array|string $size    Optional. Image size. Accepts any valid image size, or an array
   596  *                              and width dimensions. Default 'thumbnail'.
   675  *                              of width and height values in pixels (in that order).
   597  * @return bool|array False on failure or array of file path, width, and height on success.
   676  *                              Default 'thumbnail'.
       
   677  * @return false|array $data {
       
   678  *     Array of file relative path, width, and height on success. Additionally includes absolute
       
   679  *     path and URL if registered size is passed to $size parameter. False on failure.
       
   680  *
       
   681  *     @type string $file   Image's path relative to uploads directory
       
   682  *     @type int    $width  Width of image
       
   683  *     @type int    $height Height of image
       
   684  *     @type string $path   Image's absolute filesystem path.
       
   685  *     @type string $url    Image's URL.
       
   686  * }
   598  */
   687  */
   599 function image_get_intermediate_size( $post_id, $size = 'thumbnail' ) {
   688 function image_get_intermediate_size( $post_id, $size = 'thumbnail' ) {
   600 	if ( !is_array( $imagedata = wp_get_attachment_metadata( $post_id ) ) )
   689 	if ( ! $size || ! is_array( $imagedata = wp_get_attachment_metadata( $post_id ) ) || empty( $imagedata['sizes'] )  ) {
   601 		return false;
   690 		return false;
   602 
   691 	}
   603 	// get the best one for a specified set of dimensions
   692 
   604 	if ( is_array($size) && !empty($imagedata['sizes']) ) {
   693 	$data = array();
   605 		$areas = array();
   694 
       
   695 	// Find the best match when '$size' is an array.
       
   696 	if ( is_array( $size ) ) {
       
   697 		$candidates = array();
       
   698 
       
   699 		if ( ! isset( $imagedata['file'] ) && isset( $imagedata['sizes']['full'] ) ) {
       
   700 			$imagedata['height'] = $imagedata['sizes']['full']['height'];
       
   701 			$imagedata['width']  = $imagedata['sizes']['full']['width'];
       
   702 		}
   606 
   703 
   607 		foreach ( $imagedata['sizes'] as $_size => $data ) {
   704 		foreach ( $imagedata['sizes'] as $_size => $data ) {
   608 			// already cropped to width or height; so use this size
   705 			// If there's an exact match to an existing image size, short circuit.
   609 			if ( ( $data['width'] == $size[0] && $data['height'] <= $size[1] ) || ( $data['height'] == $size[1] && $data['width'] <= $size[0] ) ) {
   706 			if ( $data['width'] == $size[0] && $data['height'] == $size[1] ) {
   610 				$file = $data['file'];
   707 				$candidates[ $data['width'] * $data['height'] ] = $data;
   611 				list($width, $height) = image_constrain_size_for_editor( $data['width'], $data['height'], $size );
   708 				break;
   612 				return compact( 'file', 'width', 'height' );
       
   613 			}
   709 			}
   614 			// add to lookup table: area => size
   710 
   615 			$areas[$data['width'] * $data['height']] = $_size;
   711 			// If it's not an exact match, consider larger sizes with the same aspect ratio.
   616 		}
   712 			if ( $data['width'] >= $size[0] && $data['height'] >= $size[1] ) {
   617 		if ( !$size || !empty($areas) ) {
   713 				// If '0' is passed to either size, we test ratios against the original file.
   618 			// find for the smallest image not smaller than the desired size
   714 				if ( 0 === $size[0] || 0 === $size[1] ) {
   619 			ksort($areas);
   715 					$same_ratio = wp_image_matches_ratio( $data['width'], $data['height'], $imagedata['width'], $imagedata['height'] );
   620 			foreach ( $areas as $_size ) {
   716 				} else {
   621 				$data = $imagedata['sizes'][$_size];
   717 					$same_ratio = wp_image_matches_ratio( $data['width'], $data['height'], $size[0], $size[1] );
   622 				if ( $data['width'] >= $size[0] || $data['height'] >= $size[1] ) {
   718 				}
   623 					// Skip images with unexpectedly divergent aspect ratios (crops)
   719 
   624 					// First, we calculate what size the original image would be if constrained to a box the size of the current image in the loop
   720 				if ( $same_ratio ) {
   625 					$maybe_cropped = image_resize_dimensions($imagedata['width'], $imagedata['height'], $data['width'], $data['height'], false );
   721 					$candidates[ $data['width'] * $data['height'] ] = $data;
   626 					// If the size doesn't match within one pixel, then it is of a different aspect ratio, so we skip it, unless it's the thumbnail size
       
   627 					if ( 'thumbnail' != $_size && ( !$maybe_cropped || ( $maybe_cropped[4] != $data['width'] && $maybe_cropped[4] + 1 != $data['width'] ) || ( $maybe_cropped[5] != $data['height'] && $maybe_cropped[5] + 1 != $data['height'] ) ) )
       
   628 						continue;
       
   629 					// If we're still here, then we're going to use this size
       
   630 					$file = $data['file'];
       
   631 					list($width, $height) = image_constrain_size_for_editor( $data['width'], $data['height'], $size );
       
   632 					return compact( 'file', 'width', 'height' );
       
   633 				}
   722 				}
   634 			}
   723 			}
   635 		}
   724 		}
   636 	}
   725 
   637 
   726 		if ( ! empty( $candidates ) ) {
   638 	if ( is_array($size) || empty($size) || empty($imagedata['sizes'][$size]) )
   727 			// Sort the array by size if we have more than one candidate.
       
   728 			if ( 1 < count( $candidates ) ) {
       
   729 				ksort( $candidates );
       
   730 			}
       
   731 
       
   732 			$data = array_shift( $candidates );
       
   733 		/*
       
   734 		 * When the size requested is smaller than the thumbnail dimensions, we
       
   735 		 * fall back to the thumbnail size to maintain backwards compatibility with
       
   736 		 * pre 4.6 versions of WordPress.
       
   737 		 */
       
   738 		} elseif ( ! empty( $imagedata['sizes']['thumbnail'] ) && $imagedata['sizes']['thumbnail']['width'] >= $size[0] && $imagedata['sizes']['thumbnail']['width'] >= $size[1] ) {
       
   739 			$data = $imagedata['sizes']['thumbnail'];
       
   740 		} else {
       
   741 			return false;
       
   742 		}
       
   743 
       
   744 		// Constrain the width and height attributes to the requested values.
       
   745 		list( $data['width'], $data['height'] ) = image_constrain_size_for_editor( $data['width'], $data['height'], $size );
       
   746 
       
   747 	} elseif ( ! empty( $imagedata['sizes'][ $size ] ) ) {
       
   748 		$data = $imagedata['sizes'][ $size ];
       
   749 	}
       
   750 
       
   751 	// If we still don't have a match at this point, return false.
       
   752 	if ( empty( $data ) ) {
   639 		return false;
   753 		return false;
   640 
   754 	}
   641 	$data = $imagedata['sizes'][$size];
   755 
   642 	// include the full filesystem path of the intermediate file
   756 	// include the full filesystem path of the intermediate file
   643 	if ( empty($data['path']) && !empty($data['file']) ) {
   757 	if ( empty( $data['path'] ) && ! empty( $data['file'] ) && ! empty( $imagedata['file'] ) ) {
   644 		$file_url = wp_get_attachment_url($post_id);
   758 		$file_url = wp_get_attachment_url($post_id);
   645 		$data['path'] = path_join( dirname($imagedata['file']), $data['file'] );
   759 		$data['path'] = path_join( dirname($imagedata['file']), $data['file'] );
   646 		$data['url'] = path_join( dirname($file_url), $data['file'] );
   760 		$data['url'] = path_join( dirname($file_url), $data['file'] );
   647 	}
   761 	}
   648 	return $data;
   762 
       
   763 	/**
       
   764 	 * Filters the output of image_get_intermediate_size()
       
   765 	 *
       
   766 	 * @since 4.4.0
       
   767 	 *
       
   768 	 * @see image_get_intermediate_size()
       
   769 	 *
       
   770 	 * @param array        $data    Array of file relative path, width, and height on success. May also include
       
   771 	 *                              file absolute path and URL.
       
   772 	 * @param int          $post_id The post_id of the image attachment
       
   773 	 * @param string|array $size    Registered image size or flat array of initially-requested height and width
       
   774 	 *                              dimensions (in that order).
       
   775 	 */
       
   776 	return apply_filters( 'image_get_intermediate_size', $data, $post_id, $size );
   649 }
   777 }
   650 
   778 
   651 /**
   779 /**
   652  * Gets the available intermediate image sizes.
   780  * Gets the available intermediate image sizes.
   653  *
   781  *
   654  * @since 3.0.0
   782  * @since 3.0.0
   655  *
   783  *
   656  * @global array $_wp_additional_image_sizes
       
   657  *
       
   658  * @return array Returns a filtered array of image size strings.
   784  * @return array Returns a filtered array of image size strings.
   659  */
   785  */
   660 function get_intermediate_image_sizes() {
   786 function get_intermediate_image_sizes() {
   661 	global $_wp_additional_image_sizes;
   787 	$_wp_additional_image_sizes = wp_get_additional_image_sizes();
   662 	$image_sizes = array('thumbnail', 'medium', 'large'); // Standard sizes
   788 	$image_sizes = array('thumbnail', 'medium', 'medium_large', 'large'); // Standard sizes
   663 	if ( isset( $_wp_additional_image_sizes ) && count( $_wp_additional_image_sizes ) )
   789 	if ( ! empty( $_wp_additional_image_sizes ) ) {
   664 		$image_sizes = array_merge( $image_sizes, array_keys( $_wp_additional_image_sizes ) );
   790 		$image_sizes = array_merge( $image_sizes, array_keys( $_wp_additional_image_sizes ) );
   665 
   791 	}
   666 	/**
   792 
   667 	 * Filter the list of intermediate image sizes.
   793 	/**
       
   794 	 * Filters the list of intermediate image sizes.
   668 	 *
   795 	 *
   669 	 * @since 2.5.0
   796 	 * @since 2.5.0
   670 	 *
   797 	 *
   671 	 * @param array $image_sizes An array of intermediate image sizes. Defaults
   798 	 * @param array $image_sizes An array of intermediate image sizes. Defaults
   672 	 *                           are 'thumbnail', 'medium', 'large'.
   799 	 *                           are 'thumbnail', 'medium', 'medium_large', 'large'.
   673 	 */
   800 	 */
   674 	return apply_filters( 'intermediate_image_sizes', $image_sizes );
   801 	return apply_filters( 'intermediate_image_sizes', $image_sizes );
   675 }
   802 }
   676 
   803 
   677 /**
   804 /**
   678  * Retrieve an image to represent an attachment.
   805  * Retrieve an image to represent an attachment.
   679  *
   806  *
   680  * A mime icon for files, thumbnail or intermediate size for images.
   807  * A mime icon for files, thumbnail or intermediate size for images.
   681  *
   808  *
       
   809  * The returned array contains four values: the URL of the attachment image src,
       
   810  * the width of the image file, the height of the image file, and a boolean
       
   811  * representing whether the returned array describes an intermediate (generated)
       
   812  * image size or the original, full-sized upload.
       
   813  *
   682  * @since 2.5.0
   814  * @since 2.5.0
   683  *
   815  *
   684  * @param int          $attachment_id Image attachment ID.
   816  * @param int          $attachment_id Image attachment ID.
   685  * @param string|array $size          Optional. Registered image size to retrieve the source for or a flat
   817  * @param string|array $size          Optional. Image size. Accepts any valid image size, or an array of width
   686  *                                    array of height and width dimensions. Default 'thumbnail'.
   818  *                                    and height values in pixels (in that order). Default 'thumbnail'.
   687  * @param bool         $icon          Optional. Whether the image should be treated as an icon. Default false.
   819  * @param bool         $icon          Optional. Whether the image should be treated as an icon. Default false.
   688  * @return bool|array Returns an array (url, width, height), or false, if no image is available.
   820  * @return false|array Returns an array (url, width, height, is_intermediate), or false, if no image is available.
   689  */
   821  */
   690 function wp_get_attachment_image_src( $attachment_id, $size = 'thumbnail', $icon = false ) {
   822 function wp_get_attachment_image_src( $attachment_id, $size = 'thumbnail', $icon = false ) {
   691 
       
   692 	// get a thumbnail or intermediate image if there is one
   823 	// get a thumbnail or intermediate image if there is one
   693 	if ( $image = image_downsize($attachment_id, $size) )
   824 	$image = image_downsize( $attachment_id, $size );
   694 		return $image;
   825 	if ( ! $image ) {
   695 
   826 		$src = false;
   696 	$src = false;
   827 
   697 
   828 		if ( $icon && $src = wp_mime_type_icon( $attachment_id ) ) {
   698 	if ( $icon && $src = wp_mime_type_icon($attachment_id) ) {
   829 			/** This filter is documented in wp-includes/post.php */
   699 		/** This filter is documented in wp-includes/post.php */
   830 			$icon_dir = apply_filters( 'icon_dir', ABSPATH . WPINC . '/images/media' );
   700 		$icon_dir = apply_filters( 'icon_dir', ABSPATH . WPINC . '/images/media' );
   831 
   701 
   832 			$src_file = $icon_dir . '/' . wp_basename( $src );
   702 		$src_file = $icon_dir . '/' . wp_basename($src);
   833 			@list( $width, $height ) = getimagesize( $src_file );
   703 		@list($width, $height) = getimagesize($src_file);
   834 		}
   704 	}
   835 
   705 	if ( $src && $width && $height )
   836 		if ( $src && $width && $height ) {
   706 		return array( $src, $width, $height );
   837 			$image = array( $src, $width, $height );
   707 	return false;
   838 		}
       
   839 	}
       
   840 	/**
       
   841 	 * Filters the image src result.
       
   842 	 *
       
   843 	 * @since 4.3.0
       
   844 	 *
       
   845 	 * @param array|false  $image         Either array with src, width & height, icon src, or false.
       
   846 	 * @param int          $attachment_id Image attachment ID.
       
   847 	 * @param string|array $size          Size of image. Image size or array of width and height values
       
   848 	 *                                    (in that order). Default 'thumbnail'.
       
   849 	 * @param bool         $icon          Whether the image should be treated as an icon. Default false.
       
   850 	 */
       
   851 	return apply_filters( 'wp_get_attachment_image_src', $image, $attachment_id, $size, $icon );
   708 }
   852 }
   709 
   853 
   710 /**
   854 /**
   711  * Get an HTML img element representing an image attachment
   855  * Get an HTML img element representing an image attachment
   712  *
   856  *
   716  * browser scale down the image.
   860  * browser scale down the image.
   717  *
   861  *
   718  * @since 2.5.0
   862  * @since 2.5.0
   719  *
   863  *
   720  * @param int          $attachment_id Image attachment ID.
   864  * @param int          $attachment_id Image attachment ID.
   721  * @param string|array $size          Optional. Registered image size or flat array of height and width
   865  * @param string|array $size          Optional. Image size. Accepts any valid image size, or an array of width
   722  *                                    dimensions. Default 'thumbnail'.
   866  *                                    and height values in pixels (in that order). Default 'thumbnail'.
   723  * @param bool         $icon          Optional. Whether the image should be treated as an icon. Default false.
   867  * @param bool         $icon          Optional. Whether the image should be treated as an icon. Default false.
   724  * @param string|array $attr          Optional. Attributes for the image markup. Default empty.
   868  * @param string|array $attr          Optional. Attributes for the image markup. Default empty.
   725  * @return string HTML img element or empty string on failure.
   869  * @return string HTML img element or empty string on failure.
   726  */
   870  */
   727 function wp_get_attachment_image($attachment_id, $size = 'thumbnail', $icon = false, $attr = '') {
   871 function wp_get_attachment_image($attachment_id, $size = 'thumbnail', $icon = false, $attr = '') {
   728 
       
   729 	$html = '';
   872 	$html = '';
   730 	$image = wp_get_attachment_image_src($attachment_id, $size, $icon);
   873 	$image = wp_get_attachment_image_src($attachment_id, $size, $icon);
   731 	if ( $image ) {
   874 	if ( $image ) {
   732 		list($src, $width, $height) = $image;
   875 		list($src, $width, $height) = $image;
   733 		$hwstring = image_hwstring($width, $height);
   876 		$hwstring = image_hwstring($width, $height);
   736 			$size_class = join( 'x', $size_class );
   879 			$size_class = join( 'x', $size_class );
   737 		}
   880 		}
   738 		$attachment = get_post($attachment_id);
   881 		$attachment = get_post($attachment_id);
   739 		$default_attr = array(
   882 		$default_attr = array(
   740 			'src'	=> $src,
   883 			'src'	=> $src,
   741 			'class'	=> "attachment-$size_class",
   884 			'class'	=> "attachment-$size_class size-$size_class",
   742 			'alt'	=> trim(strip_tags( get_post_meta($attachment_id, '_wp_attachment_image_alt', true) )), // Use Alt field first
   885 			'alt'	=> trim( strip_tags( get_post_meta( $attachment_id, '_wp_attachment_image_alt', true ) ) ),
   743 		);
   886 		);
   744 		if ( empty($default_attr['alt']) )
   887 
   745 			$default_attr['alt'] = trim(strip_tags( $attachment->post_excerpt )); // If not, Use the Caption
   888 		$attr = wp_parse_args( $attr, $default_attr );
   746 		if ( empty($default_attr['alt']) )
   889 
   747 			$default_attr['alt'] = trim(strip_tags( $attachment->post_title )); // Finally, use the title
   890 		// Generate 'srcset' and 'sizes' if not already present.
   748 
   891 		if ( empty( $attr['srcset'] ) ) {
   749 		$attr = wp_parse_args($attr, $default_attr);
   892 			$image_meta = wp_get_attachment_metadata( $attachment_id );
       
   893 
       
   894 			if ( is_array( $image_meta ) ) {
       
   895 				$size_array = array( absint( $width ), absint( $height ) );
       
   896 				$srcset = wp_calculate_image_srcset( $size_array, $src, $image_meta, $attachment_id );
       
   897 				$sizes = wp_calculate_image_sizes( $size_array, $src, $image_meta, $attachment_id );
       
   898 
       
   899 				if ( $srcset && ( $sizes || ! empty( $attr['sizes'] ) ) ) {
       
   900 					$attr['srcset'] = $srcset;
       
   901 
       
   902 					if ( empty( $attr['sizes'] ) ) {
       
   903 						$attr['sizes'] = $sizes;
       
   904 					}
       
   905 				}
       
   906 			}
       
   907 		}
   750 
   908 
   751 		/**
   909 		/**
   752 		 * Filter the list of attachment image attributes.
   910 		 * Filters the list of attachment image attributes.
   753 		 *
   911 		 *
   754 		 * @since 2.8.0
   912 		 * @since 2.8.0
   755 		 *
   913 		 *
   756 		 * @param array        $attr       Attributes for the image markup.
   914 		 * @param array        $attr       Attributes for the image markup.
   757 		 * @param WP_Post      $attachment Image attachment post.
   915 		 * @param WP_Post      $attachment Image attachment post.
   758 		 * @param string|array $size       Requested size.
   916 		 * @param string|array $size       Requested size. Image size or array of width and height values
       
   917 		 *                                 (in that order). Default 'thumbnail'.
   759 		 */
   918 		 */
   760 		$attr = apply_filters( 'wp_get_attachment_image_attributes', $attr, $attachment, $size );
   919 		$attr = apply_filters( 'wp_get_attachment_image_attributes', $attr, $attachment, $size );
   761 		$attr = array_map( 'esc_attr', $attr );
   920 		$attr = array_map( 'esc_attr', $attr );
   762 		$html = rtrim("<img $hwstring");
   921 		$html = rtrim("<img $hwstring");
   763 		foreach ( $attr as $name => $value ) {
   922 		foreach ( $attr as $name => $value ) {
   768 
   927 
   769 	return $html;
   928 	return $html;
   770 }
   929 }
   771 
   930 
   772 /**
   931 /**
       
   932  * Get the URL of an image attachment.
       
   933  *
       
   934  * @since 4.4.0
       
   935  *
       
   936  * @param int          $attachment_id Image attachment ID.
       
   937  * @param string|array $size          Optional. Image size to retrieve. Accepts any valid image size, or an array
       
   938  *                                    of width and height values in pixels (in that order). Default 'thumbnail'.
       
   939  * @param bool         $icon          Optional. Whether the image should be treated as an icon. Default false.
       
   940  * @return string|false Attachment URL or false if no image is available.
       
   941  */
       
   942 function wp_get_attachment_image_url( $attachment_id, $size = 'thumbnail', $icon = false ) {
       
   943 	$image = wp_get_attachment_image_src( $attachment_id, $size, $icon );
       
   944 	return isset( $image['0'] ) ? $image['0'] : false;
       
   945 }
       
   946 
       
   947 /**
       
   948  * Get the attachment path relative to the upload directory.
       
   949  *
       
   950  * @since 4.4.1
       
   951  * @access private
       
   952  *
       
   953  * @param string $file Attachment file name.
       
   954  * @return string Attachment path relative to the upload directory.
       
   955  */
       
   956 function _wp_get_attachment_relative_path( $file ) {
       
   957 	$dirname = dirname( $file );
       
   958 
       
   959 	if ( '.' === $dirname ) {
       
   960 		return '';
       
   961 	}
       
   962 
       
   963 	if ( false !== strpos( $dirname, 'wp-content/uploads' ) ) {
       
   964 		// Get the directory name relative to the upload directory (back compat for pre-2.7 uploads)
       
   965 		$dirname = substr( $dirname, strpos( $dirname, 'wp-content/uploads' ) + 18 );
       
   966 		$dirname = ltrim( $dirname, '/' );
       
   967 	}
       
   968 
       
   969 	return $dirname;
       
   970 }
       
   971 
       
   972 /**
       
   973  * Get the image size as array from its meta data.
       
   974  *
       
   975  * Used for responsive images.
       
   976  *
       
   977  * @since 4.4.0
       
   978  * @access private
       
   979  *
       
   980  * @param string $size_name  Image size. Accepts any valid image size name ('thumbnail', 'medium', etc.).
       
   981  * @param array  $image_meta The image meta data.
       
   982  * @return array|bool Array of width and height values in pixels (in that order)
       
   983  *                    or false if the size doesn't exist.
       
   984  */
       
   985 function _wp_get_image_size_from_meta( $size_name, $image_meta ) {
       
   986 	if ( $size_name === 'full' ) {
       
   987 		return array(
       
   988 			absint( $image_meta['width'] ),
       
   989 			absint( $image_meta['height'] ),
       
   990 		);
       
   991 	} elseif ( ! empty( $image_meta['sizes'][$size_name] ) ) {
       
   992 		return array(
       
   993 			absint( $image_meta['sizes'][$size_name]['width'] ),
       
   994 			absint( $image_meta['sizes'][$size_name]['height'] ),
       
   995 		);
       
   996 	}
       
   997 
       
   998 	return false;
       
   999 }
       
  1000 
       
  1001 /**
       
  1002  * Retrieves the value for an image attachment's 'srcset' attribute.
       
  1003  *
       
  1004  * @since 4.4.0
       
  1005  *
       
  1006  * @see wp_calculate_image_srcset()
       
  1007  *
       
  1008  * @param int          $attachment_id Image attachment ID.
       
  1009  * @param array|string $size          Optional. Image size. Accepts any valid image size, or an array of
       
  1010  *                                    width and height values in pixels (in that order). Default 'medium'.
       
  1011  * @param array        $image_meta    Optional. The image meta data as returned by 'wp_get_attachment_metadata()'.
       
  1012  *                                    Default null.
       
  1013  * @return string|bool A 'srcset' value string or false.
       
  1014  */
       
  1015 function wp_get_attachment_image_srcset( $attachment_id, $size = 'medium', $image_meta = null ) {
       
  1016 	if ( ! $image = wp_get_attachment_image_src( $attachment_id, $size ) ) {
       
  1017 		return false;
       
  1018 	}
       
  1019 
       
  1020 	if ( ! is_array( $image_meta ) ) {
       
  1021 		$image_meta = wp_get_attachment_metadata( $attachment_id );
       
  1022 	}
       
  1023 
       
  1024 	$image_src = $image[0];
       
  1025 	$size_array = array(
       
  1026 		absint( $image[1] ),
       
  1027 		absint( $image[2] )
       
  1028 	);
       
  1029 
       
  1030 	return wp_calculate_image_srcset( $size_array, $image_src, $image_meta, $attachment_id );
       
  1031 }
       
  1032 
       
  1033 /**
       
  1034  * A helper function to calculate the image sources to include in a 'srcset' attribute.
       
  1035  *
       
  1036  * @since 4.4.0
       
  1037  *
       
  1038  * @param array  $size_array    Array of width and height values in pixels (in that order).
       
  1039  * @param string $image_src     The 'src' of the image.
       
  1040  * @param array  $image_meta    The image meta data as returned by 'wp_get_attachment_metadata()'.
       
  1041  * @param int    $attachment_id Optional. The image attachment ID to pass to the filter. Default 0.
       
  1042  * @return string|bool          The 'srcset' attribute value. False on error or when only one source exists.
       
  1043  */
       
  1044 function wp_calculate_image_srcset( $size_array, $image_src, $image_meta, $attachment_id = 0 ) {
       
  1045 	/**
       
  1046 	 * Let plugins pre-filter the image meta to be able to fix inconsistencies in the stored data.
       
  1047 	 *
       
  1048 	 * @since 4.5.0
       
  1049 	 *
       
  1050 	 * @param array  $image_meta    The image meta data as returned by 'wp_get_attachment_metadata()'.
       
  1051 	 * @param array  $size_array    Array of width and height values in pixels (in that order).
       
  1052 	 * @param string $image_src     The 'src' of the image.
       
  1053 	 * @param int    $attachment_id The image attachment ID or 0 if not supplied.
       
  1054 	 */
       
  1055 	$image_meta = apply_filters( 'wp_calculate_image_srcset_meta', $image_meta, $size_array, $image_src, $attachment_id );
       
  1056 
       
  1057 	if ( empty( $image_meta['sizes'] ) || ! isset( $image_meta['file'] ) || strlen( $image_meta['file'] ) < 4 ) {
       
  1058 		return false;
       
  1059 	}
       
  1060 
       
  1061 	$image_sizes = $image_meta['sizes'];
       
  1062 
       
  1063 	// Get the width and height of the image.
       
  1064 	$image_width = (int) $size_array[0];
       
  1065 	$image_height = (int) $size_array[1];
       
  1066 
       
  1067 	// Bail early if error/no width.
       
  1068 	if ( $image_width < 1 ) {
       
  1069 		return false;
       
  1070 	}
       
  1071 
       
  1072 	$image_basename = wp_basename( $image_meta['file'] );
       
  1073 
       
  1074 	/*
       
  1075 	 * WordPress flattens animated GIFs into one frame when generating intermediate sizes.
       
  1076 	 * To avoid hiding animation in user content, if src is a full size GIF, a srcset attribute is not generated.
       
  1077 	 * If src is an intermediate size GIF, the full size is excluded from srcset to keep a flattened GIF from becoming animated.
       
  1078 	 */
       
  1079 	if ( ! isset( $image_sizes['thumbnail']['mime-type'] ) || 'image/gif' !== $image_sizes['thumbnail']['mime-type'] ) {
       
  1080 		$image_sizes[] = array(
       
  1081 			'width'  => $image_meta['width'],
       
  1082 			'height' => $image_meta['height'],
       
  1083 			'file'   => $image_basename,
       
  1084 		);
       
  1085 	} elseif ( strpos( $image_src, $image_meta['file'] ) ) {
       
  1086 		return false;
       
  1087 	}
       
  1088 
       
  1089 	// Retrieve the uploads sub-directory from the full size image.
       
  1090 	$dirname = _wp_get_attachment_relative_path( $image_meta['file'] );
       
  1091 
       
  1092 	if ( $dirname ) {
       
  1093 		$dirname = trailingslashit( $dirname );
       
  1094 	}
       
  1095 
       
  1096 	$upload_dir = wp_get_upload_dir();
       
  1097 	$image_baseurl = trailingslashit( $upload_dir['baseurl'] ) . $dirname;
       
  1098 
       
  1099 	/*
       
  1100 	 * If currently on HTTPS, prefer HTTPS URLs when we know they're supported by the domain
       
  1101 	 * (which is to say, when they share the domain name of the current request).
       
  1102 	 */
       
  1103 	if ( is_ssl() && 'https' !== substr( $image_baseurl, 0, 5 ) && parse_url( $image_baseurl, PHP_URL_HOST ) === $_SERVER['HTTP_HOST'] ) {
       
  1104 		$image_baseurl = set_url_scheme( $image_baseurl, 'https' );
       
  1105 	}
       
  1106 
       
  1107 	/*
       
  1108 	 * Images that have been edited in WordPress after being uploaded will
       
  1109 	 * contain a unique hash. Look for that hash and use it later to filter
       
  1110 	 * out images that are leftovers from previous versions.
       
  1111 	 */
       
  1112 	$image_edited = preg_match( '/-e[0-9]{13}/', wp_basename( $image_src ), $image_edit_hash );
       
  1113 
       
  1114 	/**
       
  1115 	 * Filters the maximum image width to be included in a 'srcset' attribute.
       
  1116 	 *
       
  1117 	 * @since 4.4.0
       
  1118 	 *
       
  1119 	 * @param int   $max_width  The maximum image width to be included in the 'srcset'. Default '1600'.
       
  1120 	 * @param array $size_array Array of width and height values in pixels (in that order).
       
  1121 	 */
       
  1122 	$max_srcset_image_width = apply_filters( 'max_srcset_image_width', 1600, $size_array );
       
  1123 
       
  1124 	// Array to hold URL candidates.
       
  1125 	$sources = array();
       
  1126 
       
  1127 	/**
       
  1128 	 * To make sure the ID matches our image src, we will check to see if any sizes in our attachment
       
  1129 	 * meta match our $image_src. If no matches are found we don't return a srcset to avoid serving
       
  1130 	 * an incorrect image. See #35045.
       
  1131 	 */
       
  1132 	$src_matched = false;
       
  1133 
       
  1134 	/*
       
  1135 	 * Loop through available images. Only use images that are resized
       
  1136 	 * versions of the same edit.
       
  1137 	 */
       
  1138 	foreach ( $image_sizes as $image ) {
       
  1139 		$is_src = false;
       
  1140 
       
  1141 		// Check if image meta isn't corrupted.
       
  1142 		if ( ! is_array( $image ) ) {
       
  1143 			continue;
       
  1144 		}
       
  1145 
       
  1146 		// If the file name is part of the `src`, we've confirmed a match.
       
  1147 		if ( ! $src_matched && false !== strpos( $image_src, $dirname . $image['file'] ) ) {
       
  1148 			$src_matched = $is_src = true;
       
  1149 		}
       
  1150 
       
  1151 		// Filter out images that are from previous edits.
       
  1152 		if ( $image_edited && ! strpos( $image['file'], $image_edit_hash[0] ) ) {
       
  1153 			continue;
       
  1154 		}
       
  1155 
       
  1156 		/*
       
  1157 		 * Filters out images that are wider than '$max_srcset_image_width' unless
       
  1158 		 * that file is in the 'src' attribute.
       
  1159 		 */
       
  1160 		if ( $max_srcset_image_width && $image['width'] > $max_srcset_image_width && ! $is_src ) {
       
  1161 			continue;
       
  1162 		}
       
  1163 
       
  1164 		// If the image dimensions are within 1px of the expected size, use it.
       
  1165 		if ( wp_image_matches_ratio( $image_width, $image_height, $image['width'], $image['height'] ) ) {
       
  1166 			// Add the URL, descriptor, and value to the sources array to be returned.
       
  1167 			$source = array(
       
  1168 				'url'        => $image_baseurl . $image['file'],
       
  1169 				'descriptor' => 'w',
       
  1170 				'value'      => $image['width'],
       
  1171 			);
       
  1172 
       
  1173 			// The 'src' image has to be the first in the 'srcset', because of a bug in iOS8. See #35030.
       
  1174 			if ( $is_src ) {
       
  1175 				$sources = array( $image['width'] => $source ) + $sources;
       
  1176 			} else {
       
  1177 				$sources[ $image['width'] ] = $source;
       
  1178 			}
       
  1179 		}
       
  1180 	}
       
  1181 
       
  1182 	/**
       
  1183 	 * Filters an image's 'srcset' sources.
       
  1184 	 *
       
  1185 	 * @since 4.4.0
       
  1186 	 *
       
  1187 	 * @param array  $sources {
       
  1188 	 *     One or more arrays of source data to include in the 'srcset'.
       
  1189 	 *
       
  1190 	 *     @type array $width {
       
  1191 	 *         @type string $url        The URL of an image source.
       
  1192 	 *         @type string $descriptor The descriptor type used in the image candidate string,
       
  1193 	 *                                  either 'w' or 'x'.
       
  1194 	 *         @type int    $value      The source width if paired with a 'w' descriptor, or a
       
  1195 	 *                                  pixel density value if paired with an 'x' descriptor.
       
  1196 	 *     }
       
  1197 	 * }
       
  1198 	 * @param array  $size_array    Array of width and height values in pixels (in that order).
       
  1199 	 * @param string $image_src     The 'src' of the image.
       
  1200 	 * @param array  $image_meta    The image meta data as returned by 'wp_get_attachment_metadata()'.
       
  1201 	 * @param int    $attachment_id Image attachment ID or 0.
       
  1202 	 */
       
  1203 	$sources = apply_filters( 'wp_calculate_image_srcset', $sources, $size_array, $image_src, $image_meta, $attachment_id );
       
  1204 
       
  1205 	// Only return a 'srcset' value if there is more than one source.
       
  1206 	if ( ! $src_matched || ! is_array( $sources ) || count( $sources ) < 2 ) {
       
  1207 		return false;
       
  1208 	}
       
  1209 
       
  1210 	$srcset = '';
       
  1211 
       
  1212 	foreach ( $sources as $source ) {
       
  1213 		$srcset .= str_replace( ' ', '%20', $source['url'] ) . ' ' . $source['value'] . $source['descriptor'] . ', ';
       
  1214 	}
       
  1215 
       
  1216 	return rtrim( $srcset, ', ' );
       
  1217 }
       
  1218 
       
  1219 /**
       
  1220  * Retrieves the value for an image attachment's 'sizes' attribute.
       
  1221  *
       
  1222  * @since 4.4.0
       
  1223  *
       
  1224  * @see wp_calculate_image_sizes()
       
  1225  *
       
  1226  * @param int          $attachment_id Image attachment ID.
       
  1227  * @param array|string $size          Optional. Image size. Accepts any valid image size, or an array of width
       
  1228  *                                    and height values in pixels (in that order). Default 'medium'.
       
  1229  * @param array        $image_meta    Optional. The image meta data as returned by 'wp_get_attachment_metadata()'.
       
  1230  *                                    Default null.
       
  1231  * @return string|bool A valid source size value for use in a 'sizes' attribute or false.
       
  1232  */
       
  1233 function wp_get_attachment_image_sizes( $attachment_id, $size = 'medium', $image_meta = null ) {
       
  1234 	if ( ! $image = wp_get_attachment_image_src( $attachment_id, $size ) ) {
       
  1235 		return false;
       
  1236 	}
       
  1237 
       
  1238 	if ( ! is_array( $image_meta ) ) {
       
  1239 		$image_meta = wp_get_attachment_metadata( $attachment_id );
       
  1240 	}
       
  1241 
       
  1242 	$image_src = $image[0];
       
  1243 	$size_array = array(
       
  1244 		absint( $image[1] ),
       
  1245 		absint( $image[2] )
       
  1246 	);
       
  1247 
       
  1248 	return wp_calculate_image_sizes( $size_array, $image_src, $image_meta, $attachment_id );
       
  1249 }
       
  1250 
       
  1251 /**
       
  1252  * Creates a 'sizes' attribute value for an image.
       
  1253  *
       
  1254  * @since 4.4.0
       
  1255  *
       
  1256  * @param array|string $size          Image size to retrieve. Accepts any valid image size, or an array
       
  1257  *                                    of width and height values in pixels (in that order). Default 'medium'.
       
  1258  * @param string       $image_src     Optional. The URL to the image file. Default null.
       
  1259  * @param array        $image_meta    Optional. The image meta data as returned by 'wp_get_attachment_metadata()'.
       
  1260  *                                    Default null.
       
  1261  * @param int          $attachment_id Optional. Image attachment ID. Either `$image_meta` or `$attachment_id`
       
  1262  *                                    is needed when using the image size name as argument for `$size`. Default 0.
       
  1263  * @return string|bool A valid source size value for use in a 'sizes' attribute or false.
       
  1264  */
       
  1265 function wp_calculate_image_sizes( $size, $image_src = null, $image_meta = null, $attachment_id = 0 ) {
       
  1266 	$width = 0;
       
  1267 
       
  1268 	if ( is_array( $size ) ) {
       
  1269 		$width = absint( $size[0] );
       
  1270 	} elseif ( is_string( $size ) ) {
       
  1271 		if ( ! $image_meta && $attachment_id ) {
       
  1272 			$image_meta = wp_get_attachment_metadata( $attachment_id );
       
  1273 		}
       
  1274 
       
  1275 		if ( is_array( $image_meta ) ) {
       
  1276 			$size_array = _wp_get_image_size_from_meta( $size, $image_meta );
       
  1277 			if ( $size_array ) {
       
  1278 				$width = absint( $size_array[0] );
       
  1279 			}
       
  1280 		}
       
  1281 	}
       
  1282 
       
  1283 	if ( ! $width ) {
       
  1284 		return false;
       
  1285 	}
       
  1286 
       
  1287 	// Setup the default 'sizes' attribute.
       
  1288 	$sizes = sprintf( '(max-width: %1$dpx) 100vw, %1$dpx', $width );
       
  1289 
       
  1290 	/**
       
  1291 	 * Filters the output of 'wp_calculate_image_sizes()'.
       
  1292 	 *
       
  1293 	 * @since 4.4.0
       
  1294 	 *
       
  1295 	 * @param string       $sizes         A source size value for use in a 'sizes' attribute.
       
  1296 	 * @param array|string $size          Requested size. Image size or array of width and height values
       
  1297 	 *                                    in pixels (in that order).
       
  1298 	 * @param string|null  $image_src     The URL to the image file or null.
       
  1299 	 * @param array|null   $image_meta    The image meta data as returned by wp_get_attachment_metadata() or null.
       
  1300 	 * @param int          $attachment_id Image attachment ID of the original image or 0.
       
  1301 	 */
       
  1302 	return apply_filters( 'wp_calculate_image_sizes', $sizes, $size, $image_src, $image_meta, $attachment_id );
       
  1303 }
       
  1304 
       
  1305 /**
       
  1306  * Filters 'img' elements in post content to add 'srcset' and 'sizes' attributes.
       
  1307  *
       
  1308  * @since 4.4.0
       
  1309  *
       
  1310  * @see wp_image_add_srcset_and_sizes()
       
  1311  *
       
  1312  * @param string $content The raw post content to be filtered.
       
  1313  * @return string Converted content with 'srcset' and 'sizes' attributes added to images.
       
  1314  */
       
  1315 function wp_make_content_images_responsive( $content ) {
       
  1316 	if ( ! preg_match_all( '/<img [^>]+>/', $content, $matches ) ) {
       
  1317 		return $content;
       
  1318 	}
       
  1319 
       
  1320 	$selected_images = $attachment_ids = array();
       
  1321 
       
  1322 	foreach( $matches[0] as $image ) {
       
  1323 		if ( false === strpos( $image, ' srcset=' ) && preg_match( '/wp-image-([0-9]+)/i', $image, $class_id ) &&
       
  1324 			( $attachment_id = absint( $class_id[1] ) ) ) {
       
  1325 
       
  1326 			/*
       
  1327 			 * If exactly the same image tag is used more than once, overwrite it.
       
  1328 			 * All identical tags will be replaced later with 'str_replace()'.
       
  1329 			 */
       
  1330 			$selected_images[ $image ] = $attachment_id;
       
  1331 			// Overwrite the ID when the same image is included more than once.
       
  1332 			$attachment_ids[ $attachment_id ] = true;
       
  1333 		}
       
  1334 	}
       
  1335 
       
  1336 	if ( count( $attachment_ids ) > 1 ) {
       
  1337 		/*
       
  1338 		 * Warm the object cache with post and meta information for all found
       
  1339 		 * images to avoid making individual database calls.
       
  1340 		 */
       
  1341 		_prime_post_caches( array_keys( $attachment_ids ), false, true );
       
  1342 	}
       
  1343 
       
  1344 	foreach ( $selected_images as $image => $attachment_id ) {
       
  1345 		$image_meta = wp_get_attachment_metadata( $attachment_id );
       
  1346 		$content = str_replace( $image, wp_image_add_srcset_and_sizes( $image, $image_meta, $attachment_id ), $content );
       
  1347 	}
       
  1348 
       
  1349 	return $content;
       
  1350 }
       
  1351 
       
  1352 /**
       
  1353  * Adds 'srcset' and 'sizes' attributes to an existing 'img' element.
       
  1354  *
       
  1355  * @since 4.4.0
       
  1356  *
       
  1357  * @see wp_calculate_image_srcset()
       
  1358  * @see wp_calculate_image_sizes()
       
  1359  *
       
  1360  * @param string $image         An HTML 'img' element to be filtered.
       
  1361  * @param array  $image_meta    The image meta data as returned by 'wp_get_attachment_metadata()'.
       
  1362  * @param int    $attachment_id Image attachment ID.
       
  1363  * @return string Converted 'img' element with 'srcset' and 'sizes' attributes added.
       
  1364  */
       
  1365 function wp_image_add_srcset_and_sizes( $image, $image_meta, $attachment_id ) {
       
  1366 	// Ensure the image meta exists.
       
  1367 	if ( empty( $image_meta['sizes'] ) ) {
       
  1368 		return $image;
       
  1369 	}
       
  1370 
       
  1371 	$image_src = preg_match( '/src="([^"]+)"/', $image, $match_src ) ? $match_src[1] : '';
       
  1372 	list( $image_src ) = explode( '?', $image_src );
       
  1373 
       
  1374 	// Return early if we couldn't get the image source.
       
  1375 	if ( ! $image_src ) {
       
  1376 		return $image;
       
  1377 	}
       
  1378 
       
  1379 	// Bail early if an image has been inserted and later edited.
       
  1380 	if ( preg_match( '/-e[0-9]{13}/', $image_meta['file'], $img_edit_hash ) &&
       
  1381 		strpos( wp_basename( $image_src ), $img_edit_hash[0] ) === false ) {
       
  1382 
       
  1383 		return $image;
       
  1384 	}
       
  1385 
       
  1386 	$width  = preg_match( '/ width="([0-9]+)"/',  $image, $match_width  ) ? (int) $match_width[1]  : 0;
       
  1387 	$height = preg_match( '/ height="([0-9]+)"/', $image, $match_height ) ? (int) $match_height[1] : 0;
       
  1388 
       
  1389 	if ( ! $width || ! $height ) {
       
  1390 		/*
       
  1391 		 * If attempts to parse the size value failed, attempt to use the image meta data to match
       
  1392 		 * the image file name from 'src' against the available sizes for an attachment.
       
  1393 		 */
       
  1394 		$image_filename = wp_basename( $image_src );
       
  1395 
       
  1396 		if ( $image_filename === wp_basename( $image_meta['file'] ) ) {
       
  1397 			$width = (int) $image_meta['width'];
       
  1398 			$height = (int) $image_meta['height'];
       
  1399 		} else {
       
  1400 			foreach( $image_meta['sizes'] as $image_size_data ) {
       
  1401 				if ( $image_filename === $image_size_data['file'] ) {
       
  1402 					$width = (int) $image_size_data['width'];
       
  1403 					$height = (int) $image_size_data['height'];
       
  1404 					break;
       
  1405 				}
       
  1406 			}
       
  1407 		}
       
  1408 	}
       
  1409 
       
  1410 	if ( ! $width || ! $height ) {
       
  1411 		return $image;
       
  1412 	}
       
  1413 
       
  1414 	$size_array = array( $width, $height );
       
  1415 	$srcset = wp_calculate_image_srcset( $size_array, $image_src, $image_meta, $attachment_id );
       
  1416 
       
  1417 	if ( $srcset ) {
       
  1418 		// Check if there is already a 'sizes' attribute.
       
  1419 		$sizes = strpos( $image, ' sizes=' );
       
  1420 
       
  1421 		if ( ! $sizes ) {
       
  1422 			$sizes = wp_calculate_image_sizes( $size_array, $image_src, $image_meta, $attachment_id );
       
  1423 		}
       
  1424 	}
       
  1425 
       
  1426 	if ( $srcset && $sizes ) {
       
  1427 		// Format the 'srcset' and 'sizes' string and escape attributes.
       
  1428 		$attr = sprintf( ' srcset="%s"', esc_attr( $srcset ) );
       
  1429 
       
  1430 		if ( is_string( $sizes ) ) {
       
  1431 			$attr .= sprintf( ' sizes="%s"', esc_attr( $sizes ) );
       
  1432 		}
       
  1433 
       
  1434 		// Add 'srcset' and 'sizes' attributes to the image markup.
       
  1435 		$image = preg_replace( '/<img ([^>]+?)[\/ ]*>/', '<img $1' . $attr . ' />', $image );
       
  1436 	}
       
  1437 
       
  1438 	return $image;
       
  1439 }
       
  1440 
       
  1441 /**
   773  * Adds a 'wp-post-image' class to post thumbnails. Internal use only.
  1442  * Adds a 'wp-post-image' class to post thumbnails. Internal use only.
   774  *
  1443  *
   775  * Uses the 'begin_fetch_post_thumbnail_html' and 'end_fetch_post_thumbnail_html' action hooks to
  1444  * Uses the {@see 'begin_fetch_post_thumbnail_html'} and {@see 'end_fetch_post_thumbnail_html'}
   776  * dynamically add/remove itself so as to only filter post thumbnails.
  1445  * action hooks to dynamically add/remove itself so as to only filter post thumbnails.
   777  *
  1446  *
   778  * @ignore
  1447  * @ignore
   779  * @since 2.9.0
  1448  * @since 2.9.0
   780  *
  1449  *
   781  * @param array $attr Thumbnail attributes including src, class, alt, title.
  1450  * @param array $attr Thumbnail attributes including src, class, alt, title.
   817 
  1486 
   818 /**
  1487 /**
   819  * Builds the Caption shortcode output.
  1488  * Builds the Caption shortcode output.
   820  *
  1489  *
   821  * Allows a plugin to replace the content that would otherwise be returned. The
  1490  * Allows a plugin to replace the content that would otherwise be returned. The
   822  * filter is 'img_caption_shortcode' and passes an empty string, the attr
  1491  * filter is {@see 'img_caption_shortcode'} and passes an empty string, the attr
   823  * parameter and the content parameter values.
  1492  * parameter and the content parameter values.
   824  *
  1493  *
   825  * The supported attributes for the shortcode are 'id', 'align', 'width', and
  1494  * The supported attributes for the shortcode are 'id', 'align', 'width', and
   826  * 'caption'.
  1495  * 'caption'.
   827  *
  1496  *
   845 	if ( ! isset( $attr['caption'] ) ) {
  1514 	if ( ! isset( $attr['caption'] ) ) {
   846 		if ( preg_match( '#((?:<a [^>]+>\s*)?<img [^>]+>(?:\s*</a>)?)(.*)#is', $content, $matches ) ) {
  1515 		if ( preg_match( '#((?:<a [^>]+>\s*)?<img [^>]+>(?:\s*</a>)?)(.*)#is', $content, $matches ) ) {
   847 			$content = $matches[1];
  1516 			$content = $matches[1];
   848 			$attr['caption'] = trim( $matches[2] );
  1517 			$attr['caption'] = trim( $matches[2] );
   849 		}
  1518 		}
   850 	}
  1519 	} elseif ( strpos( $attr['caption'], '<' ) !== false ) {
   851 
  1520 		$attr['caption'] = wp_kses( $attr['caption'], 'post' );
   852 	/**
  1521 	}
   853 	 * Filter the default caption shortcode output.
  1522 
       
  1523 	/**
       
  1524 	 * Filters the default caption shortcode output.
   854 	 *
  1525 	 *
   855 	 * If the filtered output isn't empty, it will be used instead of generating
  1526 	 * If the filtered output isn't empty, it will be used instead of generating
   856 	 * the default caption template.
  1527 	 * the default caption template.
   857 	 *
  1528 	 *
   858 	 * @since 2.6.0
  1529 	 * @since 2.6.0
   878 	$atts['width'] = (int) $atts['width'];
  1549 	$atts['width'] = (int) $atts['width'];
   879 	if ( $atts['width'] < 1 || empty( $atts['caption'] ) )
  1550 	if ( $atts['width'] < 1 || empty( $atts['caption'] ) )
   880 		return $content;
  1551 		return $content;
   881 
  1552 
   882 	if ( ! empty( $atts['id'] ) )
  1553 	if ( ! empty( $atts['id'] ) )
   883 		$atts['id'] = 'id="' . esc_attr( $atts['id'] ) . '" ';
  1554 		$atts['id'] = 'id="' . esc_attr( sanitize_html_class( $atts['id'] ) ) . '" ';
   884 
  1555 
   885 	$class = trim( 'wp-caption ' . $atts['align'] . ' ' . $atts['class'] );
  1556 	$class = trim( 'wp-caption ' . $atts['align'] . ' ' . $atts['class'] );
   886 
  1557 
   887 	if ( current_theme_supports( 'html5', 'caption' ) ) {
  1558 	$html5 = current_theme_supports( 'html5', 'caption' );
   888 		return '<figure ' . $atts['id'] . 'style="width: ' . (int) $atts['width'] . 'px;" class="' . esc_attr( $class ) . '">'
  1559 	// HTML5 captions never added the extra 10px to the image width
   889 		. do_shortcode( $content ) . '<figcaption class="wp-caption-text">' . $atts['caption'] . '</figcaption></figure>';
  1560 	$width = $html5 ? $atts['width'] : ( 10 + $atts['width'] );
   890 	}
  1561 
   891 
  1562 	/**
   892 	$caption_width = 10 + $atts['width'];
  1563 	 * Filters the width of an image's caption.
   893 
       
   894 	/**
       
   895 	 * Filter the width of an image's caption.
       
   896 	 *
  1564 	 *
   897 	 * By default, the caption is 10 pixels greater than the width of the image,
  1565 	 * By default, the caption is 10 pixels greater than the width of the image,
   898 	 * to prevent post content from running up against a floated image.
  1566 	 * to prevent post content from running up against a floated image.
   899 	 *
  1567 	 *
   900 	 * @since 3.7.0
  1568 	 * @since 3.7.0
   901 	 *
  1569 	 *
   902 	 * @see img_caption_shortcode()
  1570 	 * @see img_caption_shortcode()
   903 	 *
  1571 	 *
   904 	 * @param int    $caption_width Width of the caption in pixels. To remove this inline style,
  1572 	 * @param int    $width    Width of the caption in pixels. To remove this inline style,
   905 	 *                              return zero.
  1573 	 *                         return zero.
   906 	 * @param array  $atts          Attributes of the caption shortcode.
  1574 	 * @param array  $atts     Attributes of the caption shortcode.
   907 	 * @param string $content       The image element, possibly wrapped in a hyperlink.
  1575 	 * @param string $content  The image element, possibly wrapped in a hyperlink.
   908 	 */
  1576 	 */
   909 	$caption_width = apply_filters( 'img_caption_shortcode_width', $caption_width, $atts, $content );
  1577 	$caption_width = apply_filters( 'img_caption_shortcode_width', $width, $atts, $content );
   910 
  1578 
   911 	$style = '';
  1579 	$style = '';
   912 	if ( $caption_width )
  1580 	if ( $caption_width ) {
   913 		$style = 'style="width: ' . (int) $caption_width . 'px" ';
  1581 		$style = 'style="width: ' . (int) $caption_width . 'px" ';
   914 
  1582 	}
   915 	return '<div ' . $atts['id'] . $style . 'class="' . esc_attr( $class ) . '">'
  1583 
   916 	. do_shortcode( $content ) . '<p class="wp-caption-text">' . $atts['caption'] . '</p></div>';
  1584 	if ( $html5 ) {
       
  1585 		$html = '<figure ' . $atts['id'] . $style . 'class="' . esc_attr( $class ) . '">'
       
  1586 		. do_shortcode( $content ) . '<figcaption class="wp-caption-text">' . $atts['caption'] . '</figcaption></figure>';
       
  1587 	} else {
       
  1588 		$html = '<div ' . $atts['id'] . $style . 'class="' . esc_attr( $class ) . '">'
       
  1589 		. do_shortcode( $content ) . '<p class="wp-caption-text">' . $atts['caption'] . '</p></div>';
       
  1590 	}
       
  1591 
       
  1592 	return $html;
   917 }
  1593 }
   918 
  1594 
   919 add_shortcode('gallery', 'gallery_shortcode');
  1595 add_shortcode('gallery', 'gallery_shortcode');
   920 
  1596 
   921 /**
  1597 /**
   924  * This implements the functionality of the Gallery Shortcode for displaying
  1600  * This implements the functionality of the Gallery Shortcode for displaying
   925  * WordPress images on a post.
  1601  * WordPress images on a post.
   926  *
  1602  *
   927  * @since 2.5.0
  1603  * @since 2.5.0
   928  *
  1604  *
       
  1605  * @staticvar int $instance
       
  1606  *
   929  * @param array $attr {
  1607  * @param array $attr {
   930  *     Attributes of the gallery shortcode.
  1608  *     Attributes of the gallery shortcode.
   931  *
  1609  *
   932  *     @type string $order      Order of the images in the gallery. Default 'ASC'. Accepts 'ASC', 'DESC'.
  1610  *     @type string       $order      Order of the images in the gallery. Default 'ASC'. Accepts 'ASC', 'DESC'.
   933  *     @type string $orderby    The field to use when ordering the images. Default 'menu_order ID'.
  1611  *     @type string       $orderby    The field to use when ordering the images. Default 'menu_order ID'.
   934  *                              Accepts any valid SQL ORDERBY statement.
  1612  *                                    Accepts any valid SQL ORDERBY statement.
   935  *     @type int    $id         Post ID.
  1613  *     @type int          $id         Post ID.
   936  *     @type string $itemtag    HTML tag to use for each image in the gallery.
  1614  *     @type string       $itemtag    HTML tag to use for each image in the gallery.
   937  *                              Default 'dl', or 'figure' when the theme registers HTML5 gallery support.
  1615  *                                    Default 'dl', or 'figure' when the theme registers HTML5 gallery support.
   938  *     @type string $icontag    HTML tag to use for each image's icon.
  1616  *     @type string       $icontag    HTML tag to use for each image's icon.
   939  *                              Default 'dt', or 'div' when the theme registers HTML5 gallery support.
  1617  *                                    Default 'dt', or 'div' when the theme registers HTML5 gallery support.
   940  *     @type string $captiontag HTML tag to use for each image's caption.
  1618  *     @type string       $captiontag HTML tag to use for each image's caption.
   941  *                              Default 'dd', or 'figcaption' when the theme registers HTML5 gallery support.
  1619  *                                    Default 'dd', or 'figcaption' when the theme registers HTML5 gallery support.
   942  *     @type int    $columns    Number of columns of images to display. Default 3.
  1620  *     @type int          $columns    Number of columns of images to display. Default 3.
   943  *     @type string $size       Size of the images to display. Default 'thumbnail'.
  1621  *     @type string|array $size       Size of the images to display. Accepts any valid image size, or an array of width
   944  *     @type string $ids        A comma-separated list of IDs of attachments to display. Default empty.
  1622  *                                    and height values in pixels (in that order). Default 'thumbnail'.
   945  *     @type string $include    A comma-separated list of IDs of attachments to include. Default empty.
  1623  *     @type string       $ids        A comma-separated list of IDs of attachments to display. Default empty.
   946  *     @type string $exclude    A comma-separated list of IDs of attachments to exclude. Default empty.
  1624  *     @type string       $include    A comma-separated list of IDs of attachments to include. Default empty.
   947  *     @type string $link       What to link each image to. Default empty (links to the attachment page).
  1625  *     @type string       $exclude    A comma-separated list of IDs of attachments to exclude. Default empty.
   948  *                              Accepts 'file', 'none'.
  1626  *     @type string       $link       What to link each image to. Default empty (links to the attachment page).
       
  1627  *                                    Accepts 'file', 'none'.
   949  * }
  1628  * }
   950  * @return string HTML content to display gallery.
  1629  * @return string HTML content to display gallery.
   951  */
  1630  */
   952 function gallery_shortcode( $attr ) {
  1631 function gallery_shortcode( $attr ) {
   953 	$post = get_post();
  1632 	$post = get_post();
   962 		}
  1641 		}
   963 		$attr['include'] = $attr['ids'];
  1642 		$attr['include'] = $attr['ids'];
   964 	}
  1643 	}
   965 
  1644 
   966 	/**
  1645 	/**
   967 	 * Filter the default gallery shortcode output.
  1646 	 * Filters the default gallery shortcode output.
   968 	 *
  1647 	 *
   969 	 * If the filtered output isn't empty, it will be used instead of generating
  1648 	 * If the filtered output isn't empty, it will be used instead of generating
   970 	 * the default gallery template.
  1649 	 * the default gallery template.
   971 	 *
  1650 	 *
   972 	 * @since 2.5.0
  1651 	 * @since 2.5.0
  1046 	$selector = "gallery-{$instance}";
  1725 	$selector = "gallery-{$instance}";
  1047 
  1726 
  1048 	$gallery_style = '';
  1727 	$gallery_style = '';
  1049 
  1728 
  1050 	/**
  1729 	/**
  1051 	 * Filter whether to print default gallery styles.
  1730 	 * Filters whether to print default gallery styles.
  1052 	 *
  1731 	 *
  1053 	 * @since 3.1.0
  1732 	 * @since 3.1.0
  1054 	 *
  1733 	 *
  1055 	 * @param bool $print Whether to print default gallery styles.
  1734 	 * @param bool $print Whether to print default gallery styles.
  1056 	 *                    Defaults to false if the theme supports HTML5 galleries.
  1735 	 *                    Defaults to false if the theme supports HTML5 galleries.
  1080 
  1759 
  1081 	$size_class = sanitize_html_class( $atts['size'] );
  1760 	$size_class = sanitize_html_class( $atts['size'] );
  1082 	$gallery_div = "<div id='$selector' class='gallery galleryid-{$id} gallery-columns-{$columns} gallery-size-{$size_class}'>";
  1761 	$gallery_div = "<div id='$selector' class='gallery galleryid-{$id} gallery-columns-{$columns} gallery-size-{$size_class}'>";
  1083 
  1762 
  1084 	/**
  1763 	/**
  1085 	 * Filter the default gallery shortcode CSS styles.
  1764 	 * Filters the default gallery shortcode CSS styles.
  1086 	 *
  1765 	 *
  1087 	 * @since 2.5.0
  1766 	 * @since 2.5.0
  1088 	 *
  1767 	 *
  1089 	 * @param string $gallery_style Default CSS styles and opening HTML div container
  1768 	 * @param string $gallery_style Default CSS styles and opening HTML div container
  1090 	 *                              for the gallery shortcode output.
  1769 	 *                              for the gallery shortcode output.
  1143  */
  1822  */
  1144 function wp_underscore_playlist_templates() {
  1823 function wp_underscore_playlist_templates() {
  1145 ?>
  1824 ?>
  1146 <script type="text/html" id="tmpl-wp-playlist-current-item">
  1825 <script type="text/html" id="tmpl-wp-playlist-current-item">
  1147 	<# if ( data.image ) { #>
  1826 	<# if ( data.image ) { #>
  1148 	<img src="{{ data.thumb.src }}"/>
  1827 	<img src="{{ data.thumb.src }}" alt="" />
  1149 	<# } #>
  1828 	<# } #>
  1150 	<div class="wp-playlist-caption">
  1829 	<div class="wp-playlist-caption">
  1151 		<span class="wp-playlist-item-meta wp-playlist-item-title">&#8220;{{ data.title }}&#8221;</span>
  1830 		<span class="wp-playlist-item-meta wp-playlist-item-title"><?php
       
  1831 			/* translators: playlist item title */
       
  1832 			printf( _x( '&#8220;%s&#8221;', 'playlist item title' ), '{{ data.title }}' );
       
  1833 		?></span>
  1152 		<# if ( data.meta.album ) { #><span class="wp-playlist-item-meta wp-playlist-item-album">{{ data.meta.album }}</span><# } #>
  1834 		<# if ( data.meta.album ) { #><span class="wp-playlist-item-meta wp-playlist-item-album">{{ data.meta.album }}</span><# } #>
  1153 		<# if ( data.meta.artist ) { #><span class="wp-playlist-item-meta wp-playlist-item-artist">{{ data.meta.artist }}</span><# } #>
  1835 		<# if ( data.meta.artist ) { #><span class="wp-playlist-item-meta wp-playlist-item-artist">{{ data.meta.artist }}</span><# } #>
  1154 	</div>
  1836 	</div>
  1155 </script>
  1837 </script>
  1156 <script type="text/html" id="tmpl-wp-playlist-item">
  1838 <script type="text/html" id="tmpl-wp-playlist-item">
  1158 		<a class="wp-playlist-caption" href="{{ data.src }}">
  1840 		<a class="wp-playlist-caption" href="{{ data.src }}">
  1159 			{{ data.index ? ( data.index + '. ' ) : '' }}
  1841 			{{ data.index ? ( data.index + '. ' ) : '' }}
  1160 			<# if ( data.caption ) { #>
  1842 			<# if ( data.caption ) { #>
  1161 				{{ data.caption }}
  1843 				{{ data.caption }}
  1162 			<# } else { #>
  1844 			<# } else { #>
  1163 				<span class="wp-playlist-item-title">&#8220;{{{ data.title }}}&#8221;</span>
  1845 				<span class="wp-playlist-item-title"><?php
       
  1846 					/* translators: playlist item title */
       
  1847 					printf( _x( '&#8220;%s&#8221;', 'playlist item title' ), '{{{ data.title }}}' );
       
  1848 				?></span>
  1164 				<# if ( data.artists && data.meta.artist ) { #>
  1849 				<# if ( data.artists && data.meta.artist ) { #>
  1165 				<span class="wp-playlist-item-artist"> &mdash; {{ data.meta.artist }}</span>
  1850 				<span class="wp-playlist-item-artist"> &mdash; {{ data.meta.artist }}</span>
  1166 				<# } #>
  1851 				<# } #>
  1167 			<# } #>
  1852 			<# } #>
  1168 		</a>
  1853 		</a>
  1196  *
  1881  *
  1197  * This implements the functionality of the playlist shortcode for displaying
  1882  * This implements the functionality of the playlist shortcode for displaying
  1198  * a collection of WordPress audio or video files in a post.
  1883  * a collection of WordPress audio or video files in a post.
  1199  *
  1884  *
  1200  * @since 3.9.0
  1885  * @since 3.9.0
       
  1886  *
       
  1887  * @global int $content_width
       
  1888  * @staticvar int $instance
  1201  *
  1889  *
  1202  * @param array $attr {
  1890  * @param array $attr {
  1203  *     Array of default playlist attributes.
  1891  *     Array of default playlist attributes.
  1204  *
  1892  *
  1205  *     @type string  $type         Type of playlist to display. Accepts 'audio' or 'video'. Default 'audio'.
  1893  *     @type string  $type         Type of playlist to display. Accepts 'audio' or 'video'. Default 'audio'.
  1239 		}
  1927 		}
  1240 		$attr['include'] = $attr['ids'];
  1928 		$attr['include'] = $attr['ids'];
  1241 	}
  1929 	}
  1242 
  1930 
  1243 	/**
  1931 	/**
  1244 	 * Filter the playlist output.
  1932 	 * Filters the playlist output.
  1245 	 *
  1933 	 *
  1246 	 * Passing a non-empty value to the filter will short-circuit generation
  1934 	 * Passing a non-empty value to the filter will short-circuit generation
  1247 	 * of the default playlist output, returning the passed value instead.
  1935 	 * of the default playlist output, returning the passed value instead.
  1248 	 *
  1936 	 *
  1249 	 * @since 3.9.0
  1937 	 * @since 3.9.0
  1399 
  2087 
  1400 	ob_start();
  2088 	ob_start();
  1401 
  2089 
  1402 	if ( 1 === $instance ) {
  2090 	if ( 1 === $instance ) {
  1403 		/**
  2091 		/**
  1404 		 * Print and enqueue playlist scripts, styles, and JavaScript templates.
  2092 		 * Prints and enqueues playlist scripts, styles, and JavaScript templates.
  1405 		 *
  2093 		 *
  1406 		 * @since 3.9.0
  2094 		 * @since 3.9.0
  1407 		 *
  2095 		 *
  1408 		 * @param string $type  Type of playlist. Possible values are 'audio' or 'video'.
  2096 		 * @param string $type  Type of playlist. Possible values are 'audio' or 'video'.
  1409 		 * @param string $style The 'theme' for the playlist. Core provides 'light' and 'dark'.
  2097 		 * @param string $style The 'theme' for the playlist. Core provides 'light' and 'dark'.
  1416 	<?php endif ?>
  2104 	<?php endif ?>
  1417 	<<?php echo $safe_type ?> controls="controls" preload="none" width="<?php
  2105 	<<?php echo $safe_type ?> controls="controls" preload="none" width="<?php
  1418 		echo (int) $theme_width;
  2106 		echo (int) $theme_width;
  1419 	?>"<?php if ( 'video' === $safe_type ):
  2107 	?>"<?php if ( 'video' === $safe_type ):
  1420 		echo ' height="', (int) $theme_height, '"';
  2108 		echo ' height="', (int) $theme_height, '"';
  1421 	else:
       
  1422 		echo ' style="visibility: hidden"';
       
  1423 	endif; ?>></<?php echo $safe_type ?>>
  2109 	endif; ?>></<?php echo $safe_type ?>>
  1424 	<div class="wp-playlist-next"></div>
  2110 	<div class="wp-playlist-next"></div>
  1425 	<div class="wp-playlist-prev"></div>
  2111 	<div class="wp-playlist-prev"></div>
  1426 	<noscript>
  2112 	<noscript>
  1427 	<ol><?php
  2113 	<ol><?php
  1445  * @param string $url The media element URL.
  2131  * @param string $url The media element URL.
  1446  * @return string Fallback HTML.
  2132  * @return string Fallback HTML.
  1447  */
  2133  */
  1448 function wp_mediaelement_fallback( $url ) {
  2134 function wp_mediaelement_fallback( $url ) {
  1449 	/**
  2135 	/**
  1450 	 * Filter the Mediaelement fallback output for no-JS.
  2136 	 * Filters the Mediaelement fallback output for no-JS.
  1451 	 *
  2137 	 *
  1452 	 * @since 3.6.0
  2138 	 * @since 3.6.0
  1453 	 *
  2139 	 *
  1454 	 * @param string $output Fallback output for no-JS.
  2140 	 * @param string $output Fallback output for no-JS.
  1455 	 * @param string $url    Media file URL.
  2141 	 * @param string $url    Media file URL.
  1464  *
  2150  *
  1465  * @return array Supported audio formats.
  2151  * @return array Supported audio formats.
  1466  */
  2152  */
  1467 function wp_get_audio_extensions() {
  2153 function wp_get_audio_extensions() {
  1468 	/**
  2154 	/**
  1469 	 * Filter the list of supported audio formats.
  2155 	 * Filters the list of supported audio formats.
  1470 	 *
  2156 	 *
  1471 	 * @since 3.6.0
  2157 	 * @since 3.6.0
  1472 	 *
  2158 	 *
  1473 	 * @param array $extensions An array of support audio formats. Defaults are
  2159 	 * @param array $extensions An array of support audio formats. Defaults are
  1474 	 *                          'mp3', 'ogg', 'wma', 'm4a', 'wav'.
  2160 	 *                          'mp3', 'ogg', 'flac', 'm4a', 'wav'.
  1475 	 */
  2161 	 */
  1476 	return apply_filters( 'wp_audio_extensions', array( 'mp3', 'ogg', 'wma', 'm4a', 'wav' ) );
  2162 	return apply_filters( 'wp_audio_extensions', array( 'mp3', 'ogg', 'flac', 'm4a', 'wav' ) );
  1477 }
  2163 }
  1478 
  2164 
  1479 /**
  2165 /**
  1480  * Returns useful keys to use to lookup data from an attachment's stored metadata.
  2166  * Returns useful keys to use to lookup data from an attachment's stored metadata.
  1481  *
  2167  *
  1499 		$fields['bitrate']          = __( 'Bitrate' );
  2185 		$fields['bitrate']          = __( 'Bitrate' );
  1500 		$fields['bitrate_mode']     = __( 'Bitrate Mode' );
  2186 		$fields['bitrate_mode']     = __( 'Bitrate Mode' );
  1501 	}
  2187 	}
  1502 
  2188 
  1503 	/**
  2189 	/**
  1504 	 * Filter the editable list of keys to look up data from an attachment's metadata.
  2190 	 * Filters the editable list of keys to look up data from an attachment's metadata.
  1505 	 *
  2191 	 *
  1506 	 * @since 3.9.0
  2192 	 * @since 3.9.0
  1507 	 *
  2193 	 *
  1508 	 * @param array   $fields     Key/value pairs of field keys to labels.
  2194 	 * @param array   $fields     Key/value pairs of field keys to labels.
  1509 	 * @param WP_Post $attachment Attachment object.
  2195 	 * @param WP_Post $attachment Attachment object.
  1517  * This implements the functionality of the Audio Shortcode for displaying
  2203  * This implements the functionality of the Audio Shortcode for displaying
  1518  * WordPress mp3s in a post.
  2204  * WordPress mp3s in a post.
  1519  *
  2205  *
  1520  * @since 3.6.0
  2206  * @since 3.6.0
  1521  *
  2207  *
       
  2208  * @staticvar int $instance
       
  2209  *
  1522  * @param array  $attr {
  2210  * @param array  $attr {
  1523  *     Attributes of the audio shortcode.
  2211  *     Attributes of the audio shortcode.
  1524  *
  2212  *
  1525  *     @type string $src      URL to the source of the audio file. Default empty.
  2213  *     @type string $src      URL to the source of the audio file. Default empty.
  1526  *     @type string $loop     The 'loop' attribute for the `<audio>` element. Default empty.
  2214  *     @type string $loop     The 'loop' attribute for the `<audio>` element. Default empty.
  1527  *     @type string $autoplay The 'autoplay' attribute for the `<audio>` element. Default empty.
  2215  *     @type string $autoplay The 'autoplay' attribute for the `<audio>` element. Default empty.
  1528  *     @type string $preload  The 'preload' attribute for the `<audio>` element. Default empty.
  2216  *     @type string $preload  The 'preload' attribute for the `<audio>` element. Default 'none'.
  1529  *     @type string $class    The 'class' attribute for the `<audio>` element. Default 'wp-audio-shortcode'.
  2217  *     @type string $class    The 'class' attribute for the `<audio>` element. Default 'wp-audio-shortcode'.
  1530  *     @type string $id       The 'id' attribute for the `<audio>` element. Default 'audio-{$post_id}-{$instance}'.
  2218  *     @type string $style    The 'style' attribute for the `<audio>` element. Default 'width: 100%;'.
  1531  *     @type string $style    The 'style' attribute for the `<audio>` element. Default 'width: 100%'.
       
  1532  * }
  2219  * }
  1533  * @param string $content Shortcode content.
  2220  * @param string $content Shortcode content.
  1534  * @return string HTML content to display audio.
  2221  * @return string|void HTML content to display audio.
  1535  */
  2222  */
  1536 function wp_audio_shortcode( $attr, $content = '' ) {
  2223 function wp_audio_shortcode( $attr, $content = '' ) {
  1537 	$post_id = get_post() ? get_the_ID() : 0;
  2224 	$post_id = get_post() ? get_the_ID() : 0;
  1538 
  2225 
  1539 	static $instance = 0;
  2226 	static $instance = 0;
  1540 	$instance++;
  2227 	$instance++;
  1541 
  2228 
  1542 	/**
  2229 	/**
  1543 	 * Filter the default audio shortcode output.
  2230 	 * Filters the default audio shortcode output.
  1544 	 *
  2231 	 *
  1545 	 * If the filtered output isn't empty, it will be used instead of generating the default audio template.
  2232 	 * If the filtered output isn't empty, it will be used instead of generating the default audio template.
  1546 	 *
  2233 	 *
  1547 	 * @since 3.6.0
  2234 	 * @since 3.6.0
  1548 	 *
  2235 	 *
  1561 	$default_types = wp_get_audio_extensions();
  2248 	$default_types = wp_get_audio_extensions();
  1562 	$defaults_atts = array(
  2249 	$defaults_atts = array(
  1563 		'src'      => '',
  2250 		'src'      => '',
  1564 		'loop'     => '',
  2251 		'loop'     => '',
  1565 		'autoplay' => '',
  2252 		'autoplay' => '',
  1566 		'preload'  => 'none'
  2253 		'preload'  => 'none',
       
  2254 		'class'    => 'wp-audio-shortcode',
       
  2255 		'style'    => 'width: 100%;'
  1567 	);
  2256 	);
  1568 	foreach ( $default_types as $type ) {
  2257 	foreach ( $default_types as $type ) {
  1569 		$defaults_atts[$type] = '';
  2258 		$defaults_atts[$type] = '';
  1570 	}
  2259 	}
  1571 
  2260 
  1604 
  2293 
  1605 		array_unshift( $default_types, 'src' );
  2294 		array_unshift( $default_types, 'src' );
  1606 	}
  2295 	}
  1607 
  2296 
  1608 	/**
  2297 	/**
  1609 	 * Filter the media library used for the audio shortcode.
  2298 	 * Filters the media library used for the audio shortcode.
  1610 	 *
  2299 	 *
  1611 	 * @since 3.6.0
  2300 	 * @since 3.6.0
  1612 	 *
  2301 	 *
  1613 	 * @param string $library Media library used for the audio shortcode.
  2302 	 * @param string $library Media library used for the audio shortcode.
  1614 	 */
  2303 	 */
  1617 		wp_enqueue_style( 'wp-mediaelement' );
  2306 		wp_enqueue_style( 'wp-mediaelement' );
  1618 		wp_enqueue_script( 'wp-mediaelement' );
  2307 		wp_enqueue_script( 'wp-mediaelement' );
  1619 	}
  2308 	}
  1620 
  2309 
  1621 	/**
  2310 	/**
  1622 	 * Filter the class attribute for the audio shortcode output container.
  2311 	 * Filters the class attribute for the audio shortcode output container.
  1623 	 *
  2312 	 *
  1624 	 * @since 3.6.0
  2313 	 * @since 3.6.0
       
  2314 	 * @since 4.9.0 The `$atts` parameter was added.
  1625 	 *
  2315 	 *
  1626 	 * @param string $class CSS class or list of space-separated classes.
  2316 	 * @param string $class CSS class or list of space-separated classes.
  1627 	 */
  2317 	 * @param array  $atts  Array of audio shortcode attributes.
       
  2318 	 */
       
  2319 	$atts['class'] = apply_filters( 'wp_audio_shortcode_class', $atts['class'], $atts );
       
  2320 
  1628 	$html_atts = array(
  2321 	$html_atts = array(
  1629 		'class'    => apply_filters( 'wp_audio_shortcode_class', 'wp-audio-shortcode' ),
  2322 		'class'    => $atts['class'],
  1630 		'id'       => sprintf( 'audio-%d-%d', $post_id, $instance ),
  2323 		'id'       => sprintf( 'audio-%d-%d', $post_id, $instance ),
  1631 		'loop'     => wp_validate_boolean( $atts['loop'] ),
  2324 		'loop'     => wp_validate_boolean( $atts['loop'] ),
  1632 		'autoplay' => wp_validate_boolean( $atts['autoplay'] ),
  2325 		'autoplay' => wp_validate_boolean( $atts['autoplay'] ),
  1633 		'preload'  => $atts['preload'],
  2326 		'preload'  => $atts['preload'],
  1634 		'style'    => 'width: 100%; visibility: hidden;',
  2327 		'style'    => $atts['style'],
  1635 	);
  2328 	);
  1636 
  2329 
  1637 	// These ones should just be omitted altogether if they are blank
  2330 	// These ones should just be omitted altogether if they are blank
  1638 	foreach ( array( 'loop', 'autoplay', 'preload' ) as $a ) {
  2331 	foreach ( array( 'loop', 'autoplay', 'preload' ) as $a ) {
  1639 		if ( empty( $html_atts[$a] ) ) {
  2332 		if ( empty( $html_atts[$a] ) ) {
  1669 		$html .= wp_mediaelement_fallback( $fileurl );
  2362 		$html .= wp_mediaelement_fallback( $fileurl );
  1670 	}
  2363 	}
  1671 	$html .= '</audio>';
  2364 	$html .= '</audio>';
  1672 
  2365 
  1673 	/**
  2366 	/**
  1674 	 * Filter the audio shortcode output.
  2367 	 * Filters the audio shortcode output.
  1675 	 *
  2368 	 *
  1676 	 * @since 3.6.0
  2369 	 * @since 3.6.0
  1677 	 *
  2370 	 *
  1678 	 * @param string $html    Audio shortcode HTML output.
  2371 	 * @param string $html    Audio shortcode HTML output.
  1679 	 * @param array  $atts    Array of audio shortcode attributes.
  2372 	 * @param array  $atts    Array of audio shortcode attributes.
  1692  *
  2385  *
  1693  * @return array List of supported video formats.
  2386  * @return array List of supported video formats.
  1694  */
  2387  */
  1695 function wp_get_video_extensions() {
  2388 function wp_get_video_extensions() {
  1696 	/**
  2389 	/**
  1697 	 * Filter the list of supported video formats.
  2390 	 * Filters the list of supported video formats.
  1698 	 *
  2391 	 *
  1699 	 * @since 3.6.0
  2392 	 * @since 3.6.0
  1700 	 *
  2393 	 *
  1701 	 * @param array $extensions An array of support video formats. Defaults are
  2394 	 * @param array $extensions An array of support video formats. Defaults are
  1702 	 *                          'mp4', 'm4v', 'webm', 'ogv', 'wmv', 'flv'.
  2395 	 *                          'mp4', 'm4v', 'webm', 'ogv', 'flv'.
  1703 	 */
  2396 	 */
  1704 	return apply_filters( 'wp_video_extensions', array( 'mp4', 'm4v', 'webm', 'ogv', 'wmv', 'flv' ) );
  2397 	return apply_filters( 'wp_video_extensions', array( 'mp4', 'm4v', 'webm', 'ogv', 'flv' ) );
  1705 }
  2398 }
  1706 
  2399 
  1707 /**
  2400 /**
  1708  * Builds the Video shortcode output.
  2401  * Builds the Video shortcode output.
  1709  *
  2402  *
  1710  * This implements the functionality of the Video Shortcode for displaying
  2403  * This implements the functionality of the Video Shortcode for displaying
  1711  * WordPress mp4s in a post.
  2404  * WordPress mp4s in a post.
  1712  *
  2405  *
  1713  * @since 3.6.0
  2406  * @since 3.6.0
       
  2407  *
       
  2408  * @global int $content_width
       
  2409  * @staticvar int $instance
  1714  *
  2410  *
  1715  * @param array  $attr {
  2411  * @param array  $attr {
  1716  *     Attributes of the shortcode.
  2412  *     Attributes of the shortcode.
  1717  *
  2413  *
  1718  *     @type string $src      URL to the source of the video file. Default empty.
  2414  *     @type string $src      URL to the source of the video file. Default empty.
  1723  *     @type string $autoplay The 'autoplay' attribute for the `<video>` element. Default empty.
  2419  *     @type string $autoplay The 'autoplay' attribute for the `<video>` element. Default empty.
  1724  *     @type string $preload  The 'preload' attribute for the `<video>` element.
  2420  *     @type string $preload  The 'preload' attribute for the `<video>` element.
  1725  *                            Default 'metadata'.
  2421  *                            Default 'metadata'.
  1726  *     @type string $class    The 'class' attribute for the `<video>` element.
  2422  *     @type string $class    The 'class' attribute for the `<video>` element.
  1727  *                            Default 'wp-video-shortcode'.
  2423  *                            Default 'wp-video-shortcode'.
  1728  *     @type string $id       The 'id' attribute for the `<video>` element.
       
  1729  *                            Default 'video-{$post_id}-{$instance}'.
       
  1730  * }
  2424  * }
  1731  * @param string $content Shortcode content.
  2425  * @param string $content Shortcode content.
  1732  * @return string HTML content to display video.
  2426  * @return string|void HTML content to display video.
  1733  */
  2427  */
  1734 function wp_video_shortcode( $attr, $content = '' ) {
  2428 function wp_video_shortcode( $attr, $content = '' ) {
  1735 	global $content_width;
  2429 	global $content_width;
  1736 	$post_id = get_post() ? get_the_ID() : 0;
  2430 	$post_id = get_post() ? get_the_ID() : 0;
  1737 
  2431 
  1738 	static $instance = 0;
  2432 	static $instance = 0;
  1739 	$instance++;
  2433 	$instance++;
  1740 
  2434 
  1741 	/**
  2435 	/**
  1742 	 * Filter the default video shortcode output.
  2436 	 * Filters the default video shortcode output.
  1743 	 *
  2437 	 *
  1744 	 * If the filtered output isn't empty, it will be used instead of generating
  2438 	 * If the filtered output isn't empty, it will be used instead of generating
  1745 	 * the default video template.
  2439 	 * the default video template.
  1746 	 *
  2440 	 *
  1747 	 * @since 3.6.0
  2441 	 * @since 3.6.0
  1748 	 *
  2442 	 *
  1749 	 * @see wp_video_shortcode()
  2443 	 * @see wp_video_shortcode()
  1750 	 *
  2444 	 *
  1751 	 * @param string $html     Empty variable to be replaced with shortcode markup.
  2445 	 * @param string $html     Empty variable to be replaced with shortcode markup.
  1752 	 * @param array  $attr     Attributes of the video shortcode.
  2446 	 * @param array  $attr     Attributes of the shortcode. @see wp_video_shortcode()
  1753 	 * @param string $content  Video shortcode content.
  2447 	 * @param string $content  Video shortcode content.
  1754 	 * @param int    $instance Unique numeric ID of this video shortcode instance.
  2448 	 * @param int    $instance Unique numeric ID of this video shortcode instance.
  1755 	 */
  2449 	 */
  1756 	$override = apply_filters( 'wp_video_shortcode_override', '', $attr, $content, $instance );
  2450 	$override = apply_filters( 'wp_video_shortcode_override', '', $attr, $content, $instance );
  1757 	if ( '' !== $override ) {
  2451 	if ( '' !== $override ) {
  1767 		'loop'     => '',
  2461 		'loop'     => '',
  1768 		'autoplay' => '',
  2462 		'autoplay' => '',
  1769 		'preload'  => 'metadata',
  2463 		'preload'  => 'metadata',
  1770 		'width'    => 640,
  2464 		'width'    => 640,
  1771 		'height'   => 360,
  2465 		'height'   => 360,
       
  2466 		'class'    => 'wp-video-shortcode',
  1772 	);
  2467 	);
  1773 
  2468 
  1774 	foreach ( $default_types as $type ) {
  2469 	foreach ( $default_types as $type ) {
  1775 		$defaults_atts[$type] = '';
  2470 		$defaults_atts[$type] = '';
  1776 	}
  2471 	}
  1805 				return sprintf( '<a class="wp-embedded-video" href="%s">%s</a>', esc_url( $atts['src'] ), esc_html( $atts['src'] ) );
  2500 				return sprintf( '<a class="wp-embedded-video" href="%s">%s</a>', esc_url( $atts['src'] ), esc_html( $atts['src'] ) );
  1806 			}
  2501 			}
  1807 		}
  2502 		}
  1808 
  2503 
  1809 		if ( $is_vimeo ) {
  2504 		if ( $is_vimeo ) {
  1810 			wp_enqueue_script( 'froogaloop' );
  2505 		    wp_enqueue_script( 'mediaelement-vimeo' );
  1811 		}
  2506 		}
  1812 
  2507 
  1813 		$primary = true;
  2508 		$primary = true;
  1814 		array_unshift( $default_types, 'src' );
  2509 		array_unshift( $default_types, 'src' );
  1815 	} else {
  2510 	} else {
  1837 
  2532 
  1838 		array_unshift( $default_types, 'src' );
  2533 		array_unshift( $default_types, 'src' );
  1839 	}
  2534 	}
  1840 
  2535 
  1841 	/**
  2536 	/**
  1842 	 * Filter the media library used for the video shortcode.
  2537 	 * Filters the media library used for the video shortcode.
  1843 	 *
  2538 	 *
  1844 	 * @since 3.6.0
  2539 	 * @since 3.6.0
  1845 	 *
  2540 	 *
  1846 	 * @param string $library Media library used for the video shortcode.
  2541 	 * @param string $library Media library used for the video shortcode.
  1847 	 */
  2542 	 */
  1848 	$library = apply_filters( 'wp_video_shortcode_library', 'mediaelement' );
  2543 	$library = apply_filters( 'wp_video_shortcode_library', 'mediaelement' );
  1849 	if ( 'mediaelement' === $library && did_action( 'init' ) ) {
  2544 	if ( 'mediaelement' === $library && did_action( 'init' ) ) {
  1850 		wp_enqueue_style( 'wp-mediaelement' );
  2545 		wp_enqueue_style( 'wp-mediaelement' );
  1851 		wp_enqueue_script( 'wp-mediaelement' );
  2546 		wp_enqueue_script( 'wp-mediaelement' );
  1852 	}
  2547 		wp_enqueue_script( 'mediaelement-vimeo' );
  1853 
  2548 	}
  1854 	/**
  2549 
  1855 	 * Filter the class attribute for the video shortcode output container.
  2550 	// Mediaelement has issues with some URL formats for Vimeo and YouTube, so
       
  2551 	// update the URL to prevent the ME.js player from breaking.
       
  2552 	if ( 'mediaelement' === $library ) {
       
  2553 		if ( $is_youtube ) {
       
  2554 			// Remove `feature` query arg and force SSL - see #40866.
       
  2555 			$atts['src'] = remove_query_arg( 'feature', $atts['src'] );
       
  2556 			$atts['src'] = set_url_scheme( $atts['src'], 'https' );
       
  2557 		} elseif ( $is_vimeo ) {
       
  2558 			// Remove all query arguments and force SSL - see #40866.
       
  2559 			$parsed_vimeo_url = wp_parse_url( $atts['src'] );
       
  2560 			$vimeo_src = 'https://' . $parsed_vimeo_url['host'] . $parsed_vimeo_url['path'];
       
  2561 
       
  2562 			// Add loop param for mejs bug - see #40977, not needed after #39686.
       
  2563 			$loop = $atts['loop'] ? '1' : '0';
       
  2564 			$atts['src'] = add_query_arg( 'loop', $loop, $vimeo_src );
       
  2565 		}
       
  2566 	}
       
  2567 
       
  2568 	/**
       
  2569 	 * Filters the class attribute for the video shortcode output container.
  1856 	 *
  2570 	 *
  1857 	 * @since 3.6.0
  2571 	 * @since 3.6.0
       
  2572 	 * @since 4.9.0 The `$atts` parameter was added.
  1858 	 *
  2573 	 *
  1859 	 * @param string $class CSS class or list of space-separated classes.
  2574 	 * @param string $class CSS class or list of space-separated classes.
  1860 	 */
  2575 	 * @param array  $atts  Array of video shortcode attributes.
       
  2576 	 */
       
  2577 	$atts['class'] = apply_filters( 'wp_video_shortcode_class', $atts['class'], $atts );
       
  2578 
  1861 	$html_atts = array(
  2579 	$html_atts = array(
  1862 		'class'    => apply_filters( 'wp_video_shortcode_class', 'wp-video-shortcode' ),
  2580 		'class'    => $atts['class'],
  1863 		'id'       => sprintf( 'video-%d-%d', $post_id, $instance ),
  2581 		'id'       => sprintf( 'video-%d-%d', $post_id, $instance ),
  1864 		'width'    => absint( $atts['width'] ),
  2582 		'width'    => absint( $atts['width'] ),
  1865 		'height'   => absint( $atts['height'] ),
  2583 		'height'   => absint( $atts['height'] ),
  1866 		'poster'   => esc_url( $atts['poster'] ),
  2584 		'poster'   => esc_url( $atts['poster'] ),
  1867 		'loop'     => wp_validate_boolean( $atts['loop'] ),
  2585 		'loop'     => wp_validate_boolean( $atts['loop'] ),
  1918 	}
  2636 	}
  1919 	$html .= '</video>';
  2637 	$html .= '</video>';
  1920 
  2638 
  1921 	$width_rule = '';
  2639 	$width_rule = '';
  1922 	if ( ! empty( $atts['width'] ) ) {
  2640 	if ( ! empty( $atts['width'] ) ) {
  1923 		$width_rule = sprintf( 'width: %dpx; ', $atts['width'] );
  2641 		$width_rule = sprintf( 'width: %dpx;', $atts['width'] );
  1924 	}
  2642 	}
  1925 	$output = sprintf( '<div style="%s" class="wp-video">%s</div>', $width_rule, $html );
  2643 	$output = sprintf( '<div style="%s" class="wp-video">%s</div>', $width_rule, $html );
  1926 
  2644 
  1927 	/**
  2645 	/**
  1928 	 * Filter the output of the video shortcode.
  2646 	 * Filters the output of the video shortcode.
  1929 	 *
  2647 	 *
  1930 	 * @since 3.6.0
  2648 	 * @since 3.6.0
  1931 	 *
  2649 	 *
  1932 	 * @param string $output  Video shortcode HTML output.
  2650 	 * @param string $output  Video shortcode HTML output.
  1933 	 * @param array  $atts    Array of video shortcode attributes.
  2651 	 * @param array  $atts    Array of video shortcode attributes.
  1944  *
  2662  *
  1945  * @since 2.5.0
  2663  * @since 2.5.0
  1946  *
  2664  *
  1947  * @see adjacent_image_link()
  2665  * @see adjacent_image_link()
  1948  *
  2666  *
  1949  * @param string|array $size Optional. Registered image size or flat array of height and width dimensions.
  2667  * @param string|array $size Optional. Image size. Accepts any valid image size, an array of width and
  1950  *                           0 or 'none' will default to 'post_title' or `$text`. Default 'thumbnail'.
  2668  *                           height values in pixels (in that order), 0, or 'none'. 0 or 'none' will
       
  2669  *                           default to 'post_title' or `$text`. Default 'thumbnail'.
  1951  * @param string       $text Optional. Link text. Default false.
  2670  * @param string       $text Optional. Link text. Default false.
  1952  * @return string HTML output for the previous image link.
       
  1953  */
  2671  */
  1954 function previous_image_link( $size = 'thumbnail', $text = false ) {
  2672 function previous_image_link( $size = 'thumbnail', $text = false ) {
  1955 	adjacent_image_link(true, $size, $text);
  2673 	adjacent_image_link(true, $size, $text);
  1956 }
  2674 }
  1957 
  2675 
  1960  *
  2678  *
  1961  * @since 2.5.0
  2679  * @since 2.5.0
  1962  *
  2680  *
  1963  * @see adjacent_image_link()
  2681  * @see adjacent_image_link()
  1964  *
  2682  *
  1965  * @param string|array $size Optional. Registered image size or flat array of height and width dimensions.
  2683  * @param string|array $size Optional. Image size. Accepts any valid image size, an array of width and
  1966  *                           0 or 'none' will default to 'post_title' or `$text`. Default 'thumbnail'.
  2684  *                           height values in pixels (in that order), 0, or 'none'. 0 or 'none' will
       
  2685  *                           default to 'post_title' or `$text`. Default 'thumbnail'.
  1967  * @param string       $text Optional. Link text. Default false.
  2686  * @param string       $text Optional. Link text. Default false.
  1968  * @return string HTML output for the next image link.
  2687  */
  1969  */
  2688 function next_image_link( $size = 'thumbnail', $text = false ) {
  1970 function next_image_link($size = 'thumbnail', $text = false) {
       
  1971 	adjacent_image_link(false, $size, $text);
  2689 	adjacent_image_link(false, $size, $text);
  1972 }
  2690 }
  1973 
  2691 
  1974 /**
  2692 /**
  1975  * Displays next or previous image link that has the same post parent.
  2693  * Displays next or previous image link that has the same post parent.
  1977  * Retrieves the current attachment object from the $post global.
  2695  * Retrieves the current attachment object from the $post global.
  1978  *
  2696  *
  1979  * @since 2.5.0
  2697  * @since 2.5.0
  1980  *
  2698  *
  1981  * @param bool         $prev Optional. Whether to display the next (false) or previous (true) link. Default true.
  2699  * @param bool         $prev Optional. Whether to display the next (false) or previous (true) link. Default true.
  1982  * @param string|array $size Optional. Registered image size or flat array of height and width dimensions.
  2700  * @param string|array $size Optional. Image size. Accepts any valid image size, or an array of width and height
  1983  *                                     Default 'thumbnail'.
  2701  *                           values in pixels (in that order). Default 'thumbnail'.
  1984  * @param bool         $text Optional. Link text. Default false.
  2702  * @param bool         $text Optional. Link text. Default false.
  1985  * @return string The adjacent image link.
       
  1986  */
  2703  */
  1987 function adjacent_image_link( $prev = true, $size = 'thumbnail', $text = false ) {
  2704 function adjacent_image_link( $prev = true, $size = 'thumbnail', $text = false ) {
  1988 	$post = get_post();
  2705 	$post = get_post();
  1989 	$attachments = array_values( get_children( array( 'post_parent' => $post->post_parent, 'post_status' => 'inherit', 'post_type' => 'attachment', 'post_mime_type' => 'image', 'order' => 'ASC', 'orderby' => 'menu_order ID' ) ) );
  2706 	$attachments = array_values( get_children( array( 'post_parent' => $post->post_parent, 'post_status' => 'inherit', 'post_type' => 'attachment', 'post_mime_type' => 'image', 'order' => 'ASC', 'orderby' => 'menu_order ID' ) ) );
  1990 
  2707 
  2007 	}
  2724 	}
  2008 
  2725 
  2009 	$adjacent = $prev ? 'previous' : 'next';
  2726 	$adjacent = $prev ? 'previous' : 'next';
  2010 
  2727 
  2011 	/**
  2728 	/**
  2012 	 * Filter the adjacent image link.
  2729 	 * Filters the adjacent image link.
  2013 	 *
  2730 	 *
  2014 	 * The dynamic portion of the hook name, `$adjacent`, refers to the type of adjacency,
  2731 	 * The dynamic portion of the hook name, `$adjacent`, refers to the type of adjacency,
  2015 	 * either 'next', or 'previous'.
  2732 	 * either 'next', or 'previous'.
  2016 	 *
  2733 	 *
  2017 	 * @since 3.5.0
  2734 	 * @since 3.5.0
  2026 
  2743 
  2027 /**
  2744 /**
  2028  * Retrieves taxonomies attached to given the attachment.
  2745  * Retrieves taxonomies attached to given the attachment.
  2029  *
  2746  *
  2030  * @since 2.5.0
  2747  * @since 2.5.0
       
  2748  * @since 4.7.0 Introduced the `$output` parameter.
  2031  *
  2749  *
  2032  * @param int|array|object $attachment Attachment ID, data array, or data object.
  2750  * @param int|array|object $attachment Attachment ID, data array, or data object.
       
  2751  * @param string           $output     Output type. 'names' to return an array of taxonomy names,
       
  2752  *                                     or 'objects' to return an array of taxonomy objects.
       
  2753  *                                     Default is 'names'.
  2033  * @return array Empty array on failure. List of taxonomies on success.
  2754  * @return array Empty array on failure. List of taxonomies on success.
  2034  */
  2755  */
  2035 function get_attachment_taxonomies( $attachment ) {
  2756 function get_attachment_taxonomies( $attachment, $output = 'names' ) {
  2036 	if ( is_int( $attachment ) ) {
  2757 	if ( is_int( $attachment ) ) {
  2037 		$attachment = get_post( $attachment );
  2758 		$attachment = get_post( $attachment );
  2038 	} elseif ( is_array( $attachment ) ) {
  2759 	} elseif ( is_array( $attachment ) ) {
  2039 		$attachment = (object) $attachment;
  2760 		$attachment = (object) $attachment;
  2040 	}
  2761 	}
  2041 	if ( ! is_object($attachment) )
  2762 	if ( ! is_object($attachment) )
  2042 		return array();
  2763 		return array();
  2043 
  2764 
  2044 	$filename = basename($attachment->guid);
  2765 	$file = get_attached_file( $attachment->ID );
       
  2766 	$filename = basename( $file );
  2045 
  2767 
  2046 	$objects = array('attachment');
  2768 	$objects = array('attachment');
  2047 
  2769 
  2048 	if ( false !== strpos($filename, '.') )
  2770 	if ( false !== strpos($filename, '.') )
  2049 		$objects[] = 'attachment:' . substr($filename, strrpos($filename, '.') + 1);
  2771 		$objects[] = 'attachment:' . substr($filename, strrpos($filename, '.') + 1);
  2054 				if ( !empty($token) )
  2776 				if ( !empty($token) )
  2055 					$objects[] = "attachment:$token";
  2777 					$objects[] = "attachment:$token";
  2056 	}
  2778 	}
  2057 
  2779 
  2058 	$taxonomies = array();
  2780 	$taxonomies = array();
  2059 	foreach ( $objects as $object )
  2781 	foreach ( $objects as $object ) {
  2060 		if ( $taxes = get_object_taxonomies($object) )
  2782 		if ( $taxes = get_object_taxonomies( $object, $output ) ) {
  2061 			$taxonomies = array_merge($taxonomies, $taxes);
  2783 			$taxonomies = array_merge( $taxonomies, $taxes );
  2062 
  2784 		}
  2063 	return array_unique($taxonomies);
  2785 	}
       
  2786 
       
  2787 	if ( 'names' === $output ) {
       
  2788 		$taxonomies = array_unique( $taxonomies );
       
  2789 	}
       
  2790 
       
  2791 	return $taxonomies;
  2064 }
  2792 }
  2065 
  2793 
  2066 /**
  2794 /**
  2067  * Retrieves all of the taxonomy names that are registered for attachments.
  2795  * Retrieves all of the taxonomy names that are registered for attachments.
  2068  *
  2796  *
  2112 	}
  2840 	}
  2113 	return $img;
  2841 	return $img;
  2114 }
  2842 }
  2115 
  2843 
  2116 /**
  2844 /**
  2117  * Registers an embed handler.
       
  2118  *
       
  2119  * Should probably only be used for sites that do not support oEmbed.
       
  2120  *
       
  2121  * @since 2.9.0
       
  2122  *
       
  2123  * @see WP_Embed::register_handler()
       
  2124  *
       
  2125  * @param string   $id       An internal ID/name for the handler. Needs to be unique.
       
  2126  * @param string   $regex    The regex that will be used to see if this handler should be used for a URL.
       
  2127  * @param callback $callback The callback function that will be called if the regex is matched.
       
  2128  * @param int      $priority Optional. Used to specify the order in which the registered handlers will
       
  2129  *                           be tested. Default 10.
       
  2130  */
       
  2131 function wp_embed_register_handler( $id, $regex, $callback, $priority = 10 ) {
       
  2132 	global $wp_embed;
       
  2133 	$wp_embed->register_handler( $id, $regex, $callback, $priority );
       
  2134 }
       
  2135 
       
  2136 /**
       
  2137  * Unregisters a previously-registered embed handler.
       
  2138  *
       
  2139  * @since 2.9.0
       
  2140  *
       
  2141  * @see WP_Embed::unregister_handler()
       
  2142  *
       
  2143  * @param string $id       The handler ID that should be removed.
       
  2144  * @param int    $priority Optional. The priority of the handler to be removed. Default 10.
       
  2145  */
       
  2146 function wp_embed_unregister_handler( $id, $priority = 10 ) {
       
  2147 	global $wp_embed;
       
  2148 	$wp_embed->unregister_handler( $id, $priority );
       
  2149 }
       
  2150 
       
  2151 /**
       
  2152  * Create default array of embed parameters.
       
  2153  *
       
  2154  * The width defaults to the content width as specified by the theme. If the
       
  2155  * theme does not specify a content width, then 500px is used.
       
  2156  *
       
  2157  * The default height is 1.5 times the width, or 1000px, whichever is smaller.
       
  2158  *
       
  2159  * The 'embed_defaults' filter can be used to adjust either of these values.
       
  2160  *
       
  2161  * @since 2.9.0
       
  2162  *
       
  2163  * @param string $url Optional. The URL that should be embedded. Default empty.
       
  2164  *
       
  2165  * @return array Default embed parameters.
       
  2166  */
       
  2167 function wp_embed_defaults( $url = '' ) {
       
  2168 	if ( ! empty( $GLOBALS['content_width'] ) )
       
  2169 		$width = (int) $GLOBALS['content_width'];
       
  2170 
       
  2171 	if ( empty( $width ) )
       
  2172 		$width = 500;
       
  2173 
       
  2174 	$height = min( ceil( $width * 1.5 ), 1000 );
       
  2175 
       
  2176 	/**
       
  2177 	 * Filter the default array of embed dimensions.
       
  2178 	 *
       
  2179 	 * @since 2.9.0
       
  2180 	 *
       
  2181 	 * @param int    $width  Width of the embed in pixels.
       
  2182 	 * @param int    $height Height of the embed in pixels.
       
  2183 	 * @param string $url    The URL that should be embedded.
       
  2184 	 */
       
  2185 	return apply_filters( 'embed_defaults', compact( 'width', 'height' ), $url );
       
  2186 }
       
  2187 
       
  2188 /**
       
  2189  * Based on a supplied width/height example, return the biggest possible dimensions based on the max width/height.
  2845  * Based on a supplied width/height example, return the biggest possible dimensions based on the max width/height.
  2190  *
  2846  *
  2191  * @since 2.9.0
  2847  * @since 2.9.0
  2192  *
  2848  *
  2193  * @see wp_constrain_dimensions()
  2849  * @see wp_constrain_dimensions()
  2206 
  2862 
  2207 	return wp_constrain_dimensions( $example_width * 1000000, $example_height * 1000000, $max_width, $max_height );
  2863 	return wp_constrain_dimensions( $example_width * 1000000, $example_height * 1000000, $max_width, $max_height );
  2208 }
  2864 }
  2209 
  2865 
  2210 /**
  2866 /**
  2211  * Attempts to fetch the embed HTML for a provided URL using oEmbed.
       
  2212  *
       
  2213  * @since 2.9.0
       
  2214  *
       
  2215  * @see WP_oEmbed
       
  2216  *
       
  2217  * @param string $url  The URL that should be embedded.
       
  2218  * @param array  $args Optional. Additional arguments and parameters for retrieving embed HTML.
       
  2219  *                     Default empty.
       
  2220  * @return false|string False on failure or the embed HTML on success.
       
  2221  */
       
  2222 function wp_oembed_get( $url, $args = '' ) {
       
  2223 	require_once( ABSPATH . WPINC . '/class-oembed.php' );
       
  2224 	$oembed = _wp_oembed_get_object();
       
  2225 	return $oembed->get_html( $url, $args );
       
  2226 }
       
  2227 
       
  2228 /**
       
  2229  * Adds a URL format and oEmbed provider URL pair.
       
  2230  *
       
  2231  * @since 2.9.0
       
  2232  *
       
  2233  * @see WP_oEmbed
       
  2234  *
       
  2235  * @param string  $format   The format of URL that this provider can handle. You can use asterisks
       
  2236  *                          as wildcards.
       
  2237  * @param string  $provider The URL to the oEmbed provider.
       
  2238  * @param boolean $regex    Optional. Whether the `$format` parameter is in a RegEx format. Default false.
       
  2239  */
       
  2240 function wp_oembed_add_provider( $format, $provider, $regex = false ) {
       
  2241 	require_once( ABSPATH . WPINC . '/class-oembed.php' );
       
  2242 
       
  2243 	if ( did_action( 'plugins_loaded' ) ) {
       
  2244 		$oembed = _wp_oembed_get_object();
       
  2245 		$oembed->providers[$format] = array( $provider, $regex );
       
  2246 	} else {
       
  2247 		WP_oEmbed::_add_provider_early( $format, $provider, $regex );
       
  2248 	}
       
  2249 }
       
  2250 
       
  2251 /**
       
  2252  * Removes an oEmbed provider.
       
  2253  *
       
  2254  * @since 3.5.0
       
  2255  *
       
  2256  * @see WP_oEmbed
       
  2257  *
       
  2258  * @param string $format The URL format for the oEmbed provider to remove.
       
  2259  * @return bool Was the provider removed successfully?
       
  2260  */
       
  2261 function wp_oembed_remove_provider( $format ) {
       
  2262 	require_once( ABSPATH . WPINC . '/class-oembed.php' );
       
  2263 
       
  2264 	if ( did_action( 'plugins_loaded' ) ) {
       
  2265 		$oembed = _wp_oembed_get_object();
       
  2266 
       
  2267 		if ( isset( $oembed->providers[ $format ] ) ) {
       
  2268 			unset( $oembed->providers[ $format ] );
       
  2269 			return true;
       
  2270 		}
       
  2271 	} else {
       
  2272 		WP_oEmbed::_remove_provider_early( $format );
       
  2273 	}
       
  2274 
       
  2275 	return false;
       
  2276 }
       
  2277 
       
  2278 /**
       
  2279  * Determines if default embed handlers should be loaded.
       
  2280  *
       
  2281  * Checks to make sure that the embeds library hasn't already been loaded. If
       
  2282  * it hasn't, then it will load the embeds library.
       
  2283  *
       
  2284  * @since 2.9.0
       
  2285  *
       
  2286  * @see wp_embed_register_handler()
       
  2287  */
       
  2288 function wp_maybe_load_embeds() {
       
  2289 	/**
       
  2290 	 * Filter whether to load the default embed handlers.
       
  2291 	 *
       
  2292 	 * Returning a falsey value will prevent loading the default embed handlers.
       
  2293 	 *
       
  2294 	 * @since 2.9.0
       
  2295 	 *
       
  2296 	 * @param bool $maybe_load_embeds Whether to load the embeds library. Default true.
       
  2297 	 */
       
  2298 	if ( ! apply_filters( 'load_default_embeds', true ) ) {
       
  2299 		return;
       
  2300 	}
       
  2301 
       
  2302 	wp_embed_register_handler( 'youtube_embed_url', '#https?://(www.)?youtube\.com/embed/([^/]+)#i', 'wp_embed_handler_youtube' );
       
  2303 
       
  2304 	wp_embed_register_handler( 'googlevideo', '#http://video\.google\.([A-Za-z.]{2,5})/videoplay\?docid=([\d-]+)(.*?)#i', 'wp_embed_handler_googlevideo' );
       
  2305 
       
  2306 	/**
       
  2307 	 * Filter the audio embed handler callback.
       
  2308 	 *
       
  2309 	 * @since 3.6.0
       
  2310 	 *
       
  2311 	 * @param callback $handler Audio embed handler callback function.
       
  2312 	 */
       
  2313 	wp_embed_register_handler( 'audio', '#^https?://.+?\.(' . join( '|', wp_get_audio_extensions() ) . ')$#i', apply_filters( 'wp_audio_embed_handler', 'wp_embed_handler_audio' ), 9999 );
       
  2314 
       
  2315 	/**
       
  2316 	 * Filter the video embed handler callback.
       
  2317 	 *
       
  2318 	 * @since 3.6.0
       
  2319 	 *
       
  2320 	 * @param callback $handler Video embed handler callback function.
       
  2321 	 */
       
  2322 	wp_embed_register_handler( 'video', '#^https?://.+?\.(' . join( '|', wp_get_video_extensions() ) . ')$#i', apply_filters( 'wp_video_embed_handler', 'wp_embed_handler_video' ), 9999 );
       
  2323 }
       
  2324 
       
  2325 /**
       
  2326  * The Google Video embed handler callback.
       
  2327  *
       
  2328  * Google Video does not support oEmbed.
       
  2329  *
       
  2330  * @see WP_Embed::register_handler()
       
  2331  * @see WP_Embed::shortcode()
       
  2332  *
       
  2333  * @param array  $matches The RegEx matches from the provided regex when calling wp_embed_register_handler().
       
  2334  * @param array  $attr    Embed attributes.
       
  2335  * @param string $url     The original URL that was matched by the regex.
       
  2336  * @param array  $rawattr The original unmodified attributes.
       
  2337  * @return string The embed HTML.
       
  2338  */
       
  2339 function wp_embed_handler_googlevideo( $matches, $attr, $url, $rawattr ) {
       
  2340 	// If the user supplied a fixed width AND height, use it
       
  2341 	if ( !empty($rawattr['width']) && !empty($rawattr['height']) ) {
       
  2342 		$width  = (int) $rawattr['width'];
       
  2343 		$height = (int) $rawattr['height'];
       
  2344 	} else {
       
  2345 		list( $width, $height ) = wp_expand_dimensions( 425, 344, $attr['width'], $attr['height'] );
       
  2346 	}
       
  2347 
       
  2348 	/**
       
  2349 	 * Filter the Google Video embed output.
       
  2350 	 *
       
  2351 	 * @since 2.9.0
       
  2352 	 *
       
  2353 	 * @param string $html    Google Video HTML embed markup.
       
  2354 	 * @param array  $matches The RegEx matches from the provided regex.
       
  2355 	 * @param array  $attr    An array of embed attributes.
       
  2356 	 * @param string $url     The original URL that was matched by the regex.
       
  2357 	 * @param array  $rawattr The original unmodified attributes.
       
  2358 	 */
       
  2359 	return apply_filters( 'embed_googlevideo', '<embed type="application/x-shockwave-flash" src="http://video.google.com/googleplayer.swf?docid=' . esc_attr($matches[2]) . '&amp;hl=en&amp;fs=true" style="width:' . esc_attr($width) . 'px;height:' . esc_attr($height) . 'px" allowFullScreen="true" allowScriptAccess="always" />', $matches, $attr, $url, $rawattr );
       
  2360 }
       
  2361 
       
  2362 /**
       
  2363  * YouTube iframe embed handler callback.
       
  2364  *
       
  2365  * Catches YouTube iframe embed URLs that are not parsable by oEmbed but can be translated into a URL that is.
       
  2366  *
       
  2367  * @since 4.0.0
       
  2368  *
       
  2369  * @param array  $matches The RegEx matches from the provided regex when calling
       
  2370  *                        wp_embed_register_handler().
       
  2371  * @param array  $attr    Embed attributes.
       
  2372  * @param string $url     The original URL that was matched by the regex.
       
  2373  * @param array  $rawattr The original unmodified attributes.
       
  2374  * @return string The embed HTML.
       
  2375  */
       
  2376 function wp_embed_handler_youtube( $matches, $attr, $url, $rawattr ) {
       
  2377 	global $wp_embed;
       
  2378 	$embed = $wp_embed->autoembed( "https://youtube.com/watch?v={$matches[2]}" );
       
  2379 
       
  2380 	/**
       
  2381 	 * Filter the YoutTube embed output.
       
  2382 	 *
       
  2383 	 * @since 4.0.0
       
  2384 	 *
       
  2385 	 * @see wp_embed_handler_youtube()
       
  2386 	 *
       
  2387 	 * @param string $embed   YouTube embed output.
       
  2388 	 * @param array  $attr    An array of embed attributes.
       
  2389 	 * @param string $url     The original URL that was matched by the regex.
       
  2390 	 * @param array  $rawattr The original unmodified attributes.
       
  2391 	 */
       
  2392 	return apply_filters( 'wp_embed_handler_youtube', $embed, $attr, $url, $rawattr );
       
  2393 }
       
  2394 
       
  2395 /**
       
  2396  * Audio embed handler callback.
       
  2397  *
       
  2398  * @since 3.6.0
       
  2399  *
       
  2400  * @param array $matches The RegEx matches from the provided regex when calling wp_embed_register_handler().
       
  2401  * @param array $attr Embed attributes.
       
  2402  * @param string $url The original URL that was matched by the regex.
       
  2403  * @param array $rawattr The original unmodified attributes.
       
  2404  * @return string The embed HTML.
       
  2405  */
       
  2406 function wp_embed_handler_audio( $matches, $attr, $url, $rawattr ) {
       
  2407 	$audio = sprintf( '[audio src="%s" /]', esc_url( $url ) );
       
  2408 
       
  2409 	/**
       
  2410 	 * Filter the audio embed output.
       
  2411 	 *
       
  2412 	 * @since 3.6.0
       
  2413 	 *
       
  2414 	 * @param string $audio   Audio embed output.
       
  2415 	 * @param array  $attr    An array of embed attributes.
       
  2416 	 * @param string $url     The original URL that was matched by the regex.
       
  2417 	 * @param array  $rawattr The original unmodified attributes.
       
  2418 	 */
       
  2419 	return apply_filters( 'wp_embed_handler_audio', $audio, $attr, $url, $rawattr );
       
  2420 }
       
  2421 
       
  2422 /**
       
  2423  * Video embed handler callback.
       
  2424  *
       
  2425  * @since 3.6.0
       
  2426  *
       
  2427  * @param array  $matches The RegEx matches from the provided regex when calling wp_embed_register_handler().
       
  2428  * @param array  $attr    Embed attributes.
       
  2429  * @param string $url     The original URL that was matched by the regex.
       
  2430  * @param array  $rawattr The original unmodified attributes.
       
  2431  * @return string The embed HTML.
       
  2432  */
       
  2433 function wp_embed_handler_video( $matches, $attr, $url, $rawattr ) {
       
  2434 	$dimensions = '';
       
  2435 	if ( ! empty( $rawattr['width'] ) && ! empty( $rawattr['height'] ) ) {
       
  2436 		$dimensions .= sprintf( 'width="%d" ', (int) $rawattr['width'] );
       
  2437 		$dimensions .= sprintf( 'height="%d" ', (int) $rawattr['height'] );
       
  2438 	}
       
  2439 	$video = sprintf( '[video %s src="%s" /]', $dimensions, esc_url( $url ) );
       
  2440 
       
  2441 	/**
       
  2442 	 * Filter the video embed output.
       
  2443 	 *
       
  2444 	 * @since 3.6.0
       
  2445 	 *
       
  2446 	 * @param string $video   Video embed output.
       
  2447 	 * @param array  $attr    An array of embed attributes.
       
  2448 	 * @param string $url     The original URL that was matched by the regex.
       
  2449 	 * @param array  $rawattr The original unmodified attributes.
       
  2450 	 */
       
  2451 	return apply_filters( 'wp_embed_handler_video', $video, $attr, $url, $rawattr );
       
  2452 }
       
  2453 
       
  2454 /**
       
  2455  * Converts a shorthand byte value to an integer byte value.
       
  2456  *
       
  2457  * @since 2.3.0
       
  2458  *
       
  2459  * @param string $size A shorthand byte value.
       
  2460  * @return int An integer byte value.
       
  2461  */
       
  2462 function wp_convert_hr_to_bytes( $size ) {
       
  2463 	$size  = strtolower( $size );
       
  2464 	$bytes = (int) $size;
       
  2465 	if ( strpos( $size, 'k' ) !== false )
       
  2466 		$bytes = intval( $size ) * 1024;
       
  2467 	elseif ( strpos( $size, 'm' ) !== false )
       
  2468 		$bytes = intval($size) * 1024 * 1024;
       
  2469 	elseif ( strpos( $size, 'g' ) !== false )
       
  2470 		$bytes = intval( $size ) * 1024 * 1024 * 1024;
       
  2471 	return $bytes;
       
  2472 }
       
  2473 
       
  2474 /**
       
  2475  * Determines the maximum upload size allowed in php.ini.
  2867  * Determines the maximum upload size allowed in php.ini.
  2476  *
  2868  *
  2477  * @since 2.5.0
  2869  * @since 2.5.0
  2478  *
  2870  *
  2479  * @return int Allowed upload size.
  2871  * @return int Allowed upload size.
  2481 function wp_max_upload_size() {
  2873 function wp_max_upload_size() {
  2482 	$u_bytes = wp_convert_hr_to_bytes( ini_get( 'upload_max_filesize' ) );
  2874 	$u_bytes = wp_convert_hr_to_bytes( ini_get( 'upload_max_filesize' ) );
  2483 	$p_bytes = wp_convert_hr_to_bytes( ini_get( 'post_max_size' ) );
  2875 	$p_bytes = wp_convert_hr_to_bytes( ini_get( 'post_max_size' ) );
  2484 
  2876 
  2485 	/**
  2877 	/**
  2486 	 * Filter the maximum upload size allowed in php.ini.
  2878 	 * Filters the maximum upload size allowed in php.ini.
  2487 	 *
  2879 	 *
  2488 	 * @since 2.5.0
  2880 	 * @since 2.5.0
  2489 	 *
  2881 	 *
  2490 	 * @param int $size    Max upload size limit in bytes.
  2882 	 * @param int $size    Max upload size limit in bytes.
  2491 	 * @param int $u_bytes Maximum upload filesize in bytes.
  2883 	 * @param int $u_bytes Maximum upload filesize in bytes.
  2550  *
  2942  *
  2551  * @ignore
  2943  * @ignore
  2552  * @since 3.5.0
  2944  * @since 3.5.0
  2553  *
  2945  *
  2554  * @param array $args Optional. Array of arguments for choosing a capable editor. Default empty array.
  2946  * @param array $args Optional. Array of arguments for choosing a capable editor. Default empty array.
  2555  * @return string|bool Class name for the first editor that claims to support the request. False if no
  2947  * @return string|false Class name for the first editor that claims to support the request. False if no
  2556  *                     editor claims to support the request.
  2948  *                     editor claims to support the request.
  2557  */
  2949  */
  2558 function _wp_image_editor_choose( $args = array() ) {
  2950 function _wp_image_editor_choose( $args = array() ) {
  2559 	require_once ABSPATH . WPINC . '/class-wp-image-editor.php';
  2951 	require_once ABSPATH . WPINC . '/class-wp-image-editor.php';
  2560 	require_once ABSPATH . WPINC . '/class-wp-image-editor-gd.php';
  2952 	require_once ABSPATH . WPINC . '/class-wp-image-editor-gd.php';
  2561 	require_once ABSPATH . WPINC . '/class-wp-image-editor-imagick.php';
  2953 	require_once ABSPATH . WPINC . '/class-wp-image-editor-imagick.php';
  2562 
  2954 	/**
  2563 	/**
  2955 	 * Filters the list of image editing library classes.
  2564 	 * Filter the list of image editing library classes.
       
  2565 	 *
  2956 	 *
  2566 	 * @since 3.5.0
  2957 	 * @since 3.5.0
  2567 	 *
  2958 	 *
  2568 	 * @param array $image_editors List of available image editors. Defaults are
  2959 	 * @param array $image_editors List of available image editors. Defaults are
  2569 	 *                             'WP_Image_Editor_Imagick', 'WP_Image_Editor_GD'.
  2960 	 *                             'WP_Image_Editor_Imagick', 'WP_Image_Editor_GD'.
  2591 
  2982 
  2592 	return false;
  2983 	return false;
  2593 }
  2984 }
  2594 
  2985 
  2595 /**
  2986 /**
  2596  * Prints default plupload arguments.
  2987  * Prints default Plupload arguments.
  2597  *
  2988  *
  2598  * @since 3.4.0
  2989  * @since 3.4.0
  2599  */
  2990  */
  2600 function wp_plupload_default_settings() {
  2991 function wp_plupload_default_settings() {
  2601 	global $wp_scripts;
  2992 	$wp_scripts = wp_scripts();
  2602 
  2993 
  2603 	$data = $wp_scripts->get_data( 'wp-plupload', 'data' );
  2994 	$data = $wp_scripts->get_data( 'wp-plupload', 'data' );
  2604 	if ( $data && false !== strpos( $data, '_wpPluploadSettings' ) )
  2995 	if ( $data && false !== strpos( $data, '_wpPluploadSettings' ) )
  2605 		return;
  2996 		return;
  2606 
  2997 
  2607 	$max_upload_size = wp_max_upload_size();
  2998 	$max_upload_size = wp_max_upload_size();
  2608 
  2999 	$allowed_extensions = array_keys( get_allowed_mime_types() );
       
  3000 	$extensions = array();
       
  3001 	foreach ( $allowed_extensions as $extension ) {
       
  3002 		$extensions = array_merge( $extensions, explode( '|', $extension ) );
       
  3003 	}
       
  3004 
       
  3005 	/*
       
  3006 	 * Since 4.9 the `runtimes` setting is hardcoded in our version of Plupload to `html5,html4`,
       
  3007 	 * and the `flash_swf_url` and `silverlight_xap_url` are not used.
       
  3008 	 */
  2609 	$defaults = array(
  3009 	$defaults = array(
  2610 		'runtimes'            => 'html5,flash,silverlight,html4',
       
  2611 		'file_data_name'      => 'async-upload', // key passed to $_FILE.
  3010 		'file_data_name'      => 'async-upload', // key passed to $_FILE.
  2612 		'url'                 => admin_url( 'async-upload.php', 'relative' ),
  3011 		'url'                 => admin_url( 'async-upload.php', 'relative' ),
  2613 		'flash_swf_url'       => includes_url( 'js/plupload/plupload.flash.swf' ),
       
  2614 		'silverlight_xap_url' => includes_url( 'js/plupload/plupload.silverlight.xap' ),
       
  2615 		'filters' => array(
  3012 		'filters' => array(
  2616 			'max_file_size'   => $max_upload_size . 'b',
  3013 			'max_file_size'   => $max_upload_size . 'b',
       
  3014 			'mime_types'      => array( array( 'extensions' => implode( ',', $extensions ) ) ),
  2617 		),
  3015 		),
  2618 	);
  3016 	);
  2619 
  3017 
  2620 	// Currently only iOS Safari supports multiple files uploading but iOS 7.x has a bug that prevents uploading of videos
  3018 	// Currently only iOS Safari supports multiple files uploading but iOS 7.x has a bug that prevents uploading of videos
  2621 	// when enabled. See #29602.
  3019 	// when enabled. See #29602.
  2624 
  3022 
  2625 		$defaults['multi_selection'] = false;
  3023 		$defaults['multi_selection'] = false;
  2626 	}
  3024 	}
  2627 
  3025 
  2628 	/**
  3026 	/**
  2629 	 * Filter the Plupload default settings.
  3027 	 * Filters the Plupload default settings.
  2630 	 *
  3028 	 *
  2631 	 * @since 3.4.0
  3029 	 * @since 3.4.0
  2632 	 *
  3030 	 *
  2633 	 * @param array $defaults Default Plupload settings array.
  3031 	 * @param array $defaults Default Plupload settings array.
  2634 	 */
  3032 	 */
  2637 	$params = array(
  3035 	$params = array(
  2638 		'action' => 'upload-attachment',
  3036 		'action' => 'upload-attachment',
  2639 	);
  3037 	);
  2640 
  3038 
  2641 	/**
  3039 	/**
  2642 	 * Filter the Plupload default parameters.
  3040 	 * Filters the Plupload default parameters.
  2643 	 *
  3041 	 *
  2644 	 * @since 3.4.0
  3042 	 * @since 3.4.0
  2645 	 *
  3043 	 *
  2646 	 * @param array $params Default Plupload parameters array.
  3044 	 * @param array $params Default Plupload parameters array.
  2647 	 */
  3045 	 */
  2671  * to be JSON-encoded and fit into an Attachment model.
  3069  * to be JSON-encoded and fit into an Attachment model.
  2672  *
  3070  *
  2673  * @since 3.5.0
  3071  * @since 3.5.0
  2674  *
  3072  *
  2675  * @param mixed $attachment Attachment ID or object.
  3073  * @param mixed $attachment Attachment ID or object.
  2676  * @return array Array of attachment details.
  3074  * @return array|void Array of attachment details.
  2677  */
  3075  */
  2678 function wp_prepare_attachment_for_js( $attachment ) {
  3076 function wp_prepare_attachment_for_js( $attachment ) {
  2679 	if ( ! $attachment = get_post( $attachment ) )
  3077 	if ( ! $attachment = get_post( $attachment ) )
  2680 		return;
  3078 		return;
  2681 
  3079 
  2687 		list( $type, $subtype ) = explode( '/', $attachment->post_mime_type );
  3085 		list( $type, $subtype ) = explode( '/', $attachment->post_mime_type );
  2688 	else
  3086 	else
  2689 		list( $type, $subtype ) = array( $attachment->post_mime_type, '' );
  3087 		list( $type, $subtype ) = array( $attachment->post_mime_type, '' );
  2690 
  3088 
  2691 	$attachment_url = wp_get_attachment_url( $attachment->ID );
  3089 	$attachment_url = wp_get_attachment_url( $attachment->ID );
       
  3090 	$base_url = str_replace( wp_basename( $attachment_url ), '', $attachment_url );
  2692 
  3091 
  2693 	$response = array(
  3092 	$response = array(
  2694 		'id'          => $attachment->ID,
  3093 		'id'          => $attachment->ID,
  2695 		'title'       => $attachment->post_title,
  3094 		'title'       => $attachment->post_title,
  2696 		'filename'    => wp_basename( $attachment->guid ),
  3095 		'filename'    => wp_basename( get_attached_file( $attachment->ID ) ),
  2697 		'url'         => $attachment_url,
  3096 		'url'         => $attachment_url,
  2698 		'link'        => get_attachment_link( $attachment->ID ),
  3097 		'link'        => get_attachment_link( $attachment->ID ),
  2699 		'alt'         => get_post_meta( $attachment->ID, '_wp_attachment_image_alt', true ),
  3098 		'alt'         => get_post_meta( $attachment->ID, '_wp_attachment_image_alt', true ),
  2700 		'author'      => $attachment->post_author,
  3099 		'author'      => $attachment->post_author,
  2701 		'description' => $attachment->post_content,
  3100 		'description' => $attachment->post_content,
  2708 		'menuOrder'   => $attachment->menu_order,
  3107 		'menuOrder'   => $attachment->menu_order,
  2709 		'mime'        => $attachment->post_mime_type,
  3108 		'mime'        => $attachment->post_mime_type,
  2710 		'type'        => $type,
  3109 		'type'        => $type,
  2711 		'subtype'     => $subtype,
  3110 		'subtype'     => $subtype,
  2712 		'icon'        => wp_mime_type_icon( $attachment->ID ),
  3111 		'icon'        => wp_mime_type_icon( $attachment->ID ),
  2713 		'dateFormatted' => mysql2date( get_option('date_format'), $attachment->post_date ),
  3112 		'dateFormatted' => mysql2date( __( 'F j, Y' ), $attachment->post_date ),
  2714 		'nonces'      => array(
  3113 		'nonces'      => array(
  2715 			'update' => false,
  3114 			'update' => false,
  2716 			'delete' => false,
  3115 			'delete' => false,
  2717 			'edit'   => false
  3116 			'edit'   => false
  2718 		),
  3117 		),
  2719 		'editLink'   => false,
  3118 		'editLink'   => false,
  2720 		'meta'       => false,
  3119 		'meta'       => false,
  2721 	);
  3120 	);
  2722 
  3121 
  2723 	$author = new WP_User( $attachment->post_author );
  3122 	$author = new WP_User( $attachment->post_author );
  2724 	$response['authorName'] = $author->display_name;
  3123 	if ( $author->exists() ) {
       
  3124 		$response['authorName'] = html_entity_decode( $author->display_name, ENT_QUOTES, get_bloginfo( 'charset' ) );
       
  3125 	} else {
       
  3126 		$response['authorName'] = __( '(no author)' );
       
  3127 	}
  2725 
  3128 
  2726 	if ( $attachment->post_parent ) {
  3129 	if ( $attachment->post_parent ) {
  2727 		$post_parent = get_post( $attachment->post_parent );
  3130 		$post_parent = get_post( $attachment->post_parent );
  2728 	} else {
  3131 	} else {
  2729 		$post_parent = false;
  3132 		$post_parent = false;
  2730 	}
  3133 	}
  2731 
  3134 
  2732 	if ( $post_parent ) {
  3135 	if ( $post_parent ) {
  2733 		$parent_type = get_post_type_object( $post_parent->post_type );
  3136 		$parent_type = get_post_type_object( $post_parent->post_type );
       
  3137 
  2734 		if ( $parent_type && $parent_type->show_ui && current_user_can( 'edit_post', $attachment->post_parent ) ) {
  3138 		if ( $parent_type && $parent_type->show_ui && current_user_can( 'edit_post', $attachment->post_parent ) ) {
  2735 			$response['uploadedToLink'] = get_edit_post_link( $attachment->post_parent, 'raw' );
  3139 			$response['uploadedToLink'] = get_edit_post_link( $attachment->post_parent, 'raw' );
  2736 		}
  3140 		}
  2737 		$response['uploadedToTitle'] = $post_parent->post_title ? $post_parent->post_title : __( '(no title)' );
  3141 
       
  3142 		if ( $parent_type && current_user_can( 'read_post', $attachment->post_parent ) ) {
       
  3143 			$response['uploadedToTitle'] = $post_parent->post_title ? $post_parent->post_title : __( '(no title)' );
       
  3144 		}
  2738 	}
  3145 	}
  2739 
  3146 
  2740 	$attached_file = get_attached_file( $attachment->ID );
  3147 	$attached_file = get_attached_file( $attachment->ID );
  2741 	if ( file_exists( $attached_file ) ) {
  3148 
       
  3149 	if ( isset( $meta['filesize'] ) ) {
       
  3150 		$bytes = $meta['filesize'];
       
  3151 	} elseif ( file_exists( $attached_file ) ) {
  2742 		$bytes = filesize( $attached_file );
  3152 		$bytes = filesize( $attached_file );
       
  3153 	} else {
       
  3154 		$bytes = '';
       
  3155 	}
       
  3156 
       
  3157 	if ( $bytes ) {
  2743 		$response['filesizeInBytes'] = $bytes;
  3158 		$response['filesizeInBytes'] = $bytes;
  2744 		$response['filesizeHumanReadable'] = size_format( $bytes );
  3159 		$response['filesizeHumanReadable'] = size_format( $bytes );
  2745 	}
  3160 	}
       
  3161 
       
  3162 	$context = get_post_meta( $attachment->ID, '_wp_attachment_context', true );
       
  3163 	$response['context'] = ( $context ) ? $context : '';
  2746 
  3164 
  2747 	if ( current_user_can( 'edit_post', $attachment->ID ) ) {
  3165 	if ( current_user_can( 'edit_post', $attachment->ID ) ) {
  2748 		$response['nonces']['update'] = wp_create_nonce( 'update-post_' . $attachment->ID );
  3166 		$response['nonces']['update'] = wp_create_nonce( 'update-post_' . $attachment->ID );
  2749 		$response['nonces']['edit'] = wp_create_nonce( 'image_editor-' . $attachment->ID );
  3167 		$response['nonces']['edit'] = wp_create_nonce( 'image_editor-' . $attachment->ID );
  2750 		$response['editLink'] = get_edit_post_link( $attachment->ID, 'raw' );
  3168 		$response['editLink'] = get_edit_post_link( $attachment->ID, 'raw' );
  2751 	}
  3169 	}
  2752 
  3170 
  2753 	if ( current_user_can( 'delete_post', $attachment->ID ) )
  3171 	if ( current_user_can( 'delete_post', $attachment->ID ) )
  2754 		$response['nonces']['delete'] = wp_create_nonce( 'delete-post_' . $attachment->ID );
  3172 		$response['nonces']['delete'] = wp_create_nonce( 'delete-post_' . $attachment->ID );
  2755 
  3173 
  2756 	if ( $meta && 'image' === $type ) {
  3174 	if ( $meta && ( 'image' === $type || ! empty( $meta['sizes'] ) ) ) {
  2757 		$sizes = array();
  3175 		$sizes = array();
  2758 
  3176 
  2759 		/** This filter is documented in wp-admin/includes/media.php */
  3177 		/** This filter is documented in wp-admin/includes/media.php */
  2760 		$possible_sizes = apply_filters( 'image_size_names_choose', array(
  3178 		$possible_sizes = apply_filters( 'image_size_names_choose', array(
  2761 			'thumbnail' => __('Thumbnail'),
  3179 			'thumbnail' => __('Thumbnail'),
  2771 		// way to check the image metadata, which we do second.
  3189 		// way to check the image metadata, which we do second.
  2772 		foreach ( $possible_sizes as $size => $label ) {
  3190 		foreach ( $possible_sizes as $size => $label ) {
  2773 
  3191 
  2774 			/** This filter is documented in wp-includes/media.php */
  3192 			/** This filter is documented in wp-includes/media.php */
  2775 			if ( $downsize = apply_filters( 'image_downsize', false, $attachment->ID, $size ) ) {
  3193 			if ( $downsize = apply_filters( 'image_downsize', false, $attachment->ID, $size ) ) {
  2776 				if ( ! $downsize[3] )
  3194 				if ( empty( $downsize[3] ) ) {
  2777 					continue;
  3195 					continue;
       
  3196 				}
       
  3197 
  2778 				$sizes[ $size ] = array(
  3198 				$sizes[ $size ] = array(
  2779 					'height'      => $downsize[2],
  3199 					'height'      => $downsize[2],
  2780 					'width'       => $downsize[1],
  3200 					'width'       => $downsize[1],
  2781 					'url'         => $downsize[0],
  3201 					'url'         => $downsize[0],
  2782 					'orientation' => $downsize[2] > $downsize[1] ? 'portrait' : 'landscape',
  3202 					'orientation' => $downsize[2] > $downsize[1] ? 'portrait' : 'landscape',
  2783 				);
  3203 				);
  2784 			} elseif ( isset( $meta['sizes'][ $size ] ) ) {
  3204 			} elseif ( isset( $meta['sizes'][ $size ] ) ) {
  2785 				if ( ! isset( $base_url ) )
       
  2786 					$base_url = str_replace( wp_basename( $attachment_url ), '', $attachment_url );
       
  2787 
       
  2788 				// Nothing from the filter, so consult image metadata if we have it.
  3205 				// Nothing from the filter, so consult image metadata if we have it.
  2789 				$size_meta = $meta['sizes'][ $size ];
  3206 				$size_meta = $meta['sizes'][ $size ];
  2790 
  3207 
  2791 				// We have the actual image size, but might need to further constrain it if content_width is narrower.
  3208 				// We have the actual image size, but might need to further constrain it if content_width is narrower.
  2792 				// Thumbnail, medium, and full sizes are also checked against the site's height/width options.
  3209 				// Thumbnail, medium, and full sizes are also checked against the site's height/width options.
  2799 					'orientation' => $height > $width ? 'portrait' : 'landscape',
  3216 					'orientation' => $height > $width ? 'portrait' : 'landscape',
  2800 				);
  3217 				);
  2801 			}
  3218 			}
  2802 		}
  3219 		}
  2803 
  3220 
  2804 		$sizes['full'] = array( 'url' => $attachment_url );
  3221 		if ( 'image' === $type ) {
  2805 
  3222 			$sizes['full'] = array( 'url' => $attachment_url );
  2806 		if ( isset( $meta['height'], $meta['width'] ) ) {
  3223 
  2807 			$sizes['full']['height'] = $meta['height'];
  3224 			if ( isset( $meta['height'], $meta['width'] ) ) {
  2808 			$sizes['full']['width'] = $meta['width'];
  3225 				$sizes['full']['height'] = $meta['height'];
  2809 			$sizes['full']['orientation'] = $meta['height'] > $meta['width'] ? 'portrait' : 'landscape';
  3226 				$sizes['full']['width'] = $meta['width'];
  2810 		}
  3227 				$sizes['full']['orientation'] = $meta['height'] > $meta['width'] ? 'portrait' : 'landscape';
  2811 
  3228 			}
  2812 		$response = array_merge( $response, array( 'sizes' => $sizes ), $sizes['full'] );
  3229 
  2813 	} elseif ( $meta && 'video' === $type ) {
  3230 			$response = array_merge( $response, $sizes['full'] );
       
  3231 		} elseif ( $meta['sizes']['full']['file'] ) {
       
  3232 			$sizes['full'] = array(
       
  3233 				'url'         => $base_url . $meta['sizes']['full']['file'],
       
  3234 				'height'      => $meta['sizes']['full']['height'],
       
  3235 				'width'       => $meta['sizes']['full']['width'],
       
  3236 				'orientation' => $meta['sizes']['full']['height'] > $meta['sizes']['full']['width'] ? 'portrait' : 'landscape'
       
  3237 			);
       
  3238 		}
       
  3239 
       
  3240 		$response = array_merge( $response, array( 'sizes' => $sizes ) );
       
  3241 	}
       
  3242 
       
  3243 	if ( $meta && 'video' === $type ) {
  2814 		if ( isset( $meta['width'] ) )
  3244 		if ( isset( $meta['width'] ) )
  2815 			$response['width'] = (int) $meta['width'];
  3245 			$response['width'] = (int) $meta['width'];
  2816 		if ( isset( $meta['height'] ) )
  3246 		if ( isset( $meta['height'] ) )
  2817 			$response['height'] = (int) $meta['height'];
  3247 			$response['height'] = (int) $meta['height'];
  2818 	}
  3248 	}
  2847 
  3277 
  2848 	if ( function_exists('get_compat_media_markup') )
  3278 	if ( function_exists('get_compat_media_markup') )
  2849 		$response['compat'] = get_compat_media_markup( $attachment->ID, array( 'in_modal' => true ) );
  3279 		$response['compat'] = get_compat_media_markup( $attachment->ID, array( 'in_modal' => true ) );
  2850 
  3280 
  2851 	/**
  3281 	/**
  2852 	 * Filter the attachment data prepared for JavaScript.
  3282 	 * Filters the attachment data prepared for JavaScript.
  2853 	 *
  3283 	 *
  2854 	 * @since 3.5.0
  3284 	 * @since 3.5.0
  2855 	 *
  3285 	 *
  2856 	 * @param array      $response   Array of prepared attachment data.
  3286 	 * @param array      $response   Array of prepared attachment data.
  2857 	 * @param int|object $attachment Attachment ID or object.
  3287 	 * @param int|object $attachment Attachment ID or object.
  2864  * Enqueues all scripts, styles, settings, and templates necessary to use
  3294  * Enqueues all scripts, styles, settings, and templates necessary to use
  2865  * all media JS APIs.
  3295  * all media JS APIs.
  2866  *
  3296  *
  2867  * @since 3.5.0
  3297  * @since 3.5.0
  2868  *
  3298  *
       
  3299  * @global int       $content_width
       
  3300  * @global wpdb      $wpdb
       
  3301  * @global WP_Locale $wp_locale
       
  3302  *
  2869  * @param array $args {
  3303  * @param array $args {
  2870  *     Arguments for enqueuing media scripts.
  3304  *     Arguments for enqueuing media scripts.
  2871  *
  3305  *
  2872  *     @type int|WP_Post A post object or ID.
  3306  *     @type int|WP_Post A post object or ID.
  2873  * }
  3307  * }
  2874  * @return array List of media view settings.
       
  2875  */
  3308  */
  2876 function wp_enqueue_media( $args = array() ) {
  3309 function wp_enqueue_media( $args = array() ) {
  2877 
       
  2878 	// Enqueue me just once per page, please.
  3310 	// Enqueue me just once per page, please.
  2879 	if ( did_action( 'wp_enqueue_media' ) )
  3311 	if ( did_action( 'wp_enqueue_media' ) )
  2880 		return;
  3312 		return;
  2881 
  3313 
  2882 	global $content_width, $wpdb, $wp_locale;
  3314 	global $content_width, $wpdb, $wp_locale;
  2916 				break;
  3348 				break;
  2917 			}
  3349 			}
  2918 		}
  3350 		}
  2919 	}
  3351 	}
  2920 
  3352 
  2921 	$has_audio = $wpdb->get_var( "
  3353 	/**
  2922 		SELECT ID
  3354 	 * Allows showing or hiding the "Create Audio Playlist" button in the media library.
  2923 		FROM $wpdb->posts
  3355 	 *
  2924 		WHERE post_type = 'attachment'
  3356 	 * By default, the "Create Audio Playlist" button will always be shown in
  2925 		AND post_mime_type LIKE 'audio%'
  3357 	 * the media library.  If this filter returns `null`, a query will be run
  2926 		LIMIT 1
  3358 	 * to determine whether the media library contains any audio items.  This
  2927 	" );
  3359 	 * was the default behavior prior to version 4.8.0, but this query is
  2928 	$has_video = $wpdb->get_var( "
  3360 	 * expensive for large media libraries.
  2929 		SELECT ID
  3361 	 *
  2930 		FROM $wpdb->posts
  3362 	 * @since 4.7.4
  2931 		WHERE post_type = 'attachment'
  3363 	 * @since 4.8.0 The filter's default value is `true` rather than `null`.
  2932 		AND post_mime_type LIKE 'video%'
  3364 	 *
  2933 		LIMIT 1
  3365 	 * @link https://core.trac.wordpress.org/ticket/31071
  2934 	" );
  3366 	 *
  2935 	$months = $wpdb->get_results( $wpdb->prepare( "
  3367 	 * @param bool|null Whether to show the button, or `null` to decide based
  2936 		SELECT DISTINCT YEAR( post_date ) AS year, MONTH( post_date ) AS month
  3368 	 *                  on whether any audio files exist in the media library.
  2937 		FROM $wpdb->posts
  3369 	 */
  2938 		WHERE post_type = %s
  3370 	$show_audio_playlist = apply_filters( 'media_library_show_audio_playlist', true );
  2939 		ORDER BY post_date DESC
  3371 	if ( null === $show_audio_playlist ) {
  2940 	", 'attachment' ) );
  3372 		$show_audio_playlist = $wpdb->get_var( "
       
  3373 			SELECT ID
       
  3374 			FROM $wpdb->posts
       
  3375 			WHERE post_type = 'attachment'
       
  3376 			AND post_mime_type LIKE 'audio%'
       
  3377 			LIMIT 1
       
  3378 		" );
       
  3379 	}
       
  3380 
       
  3381 	/**
       
  3382 	 * Allows showing or hiding the "Create Video Playlist" button in the media library.
       
  3383 	 *
       
  3384 	 * By default, the "Create Video Playlist" button will always be shown in
       
  3385 	 * the media library.  If this filter returns `null`, a query will be run
       
  3386 	 * to determine whether the media library contains any video items.  This
       
  3387 	 * was the default behavior prior to version 4.8.0, but this query is
       
  3388 	 * expensive for large media libraries.
       
  3389 	 *
       
  3390 	 * @since 4.7.4
       
  3391 	 * @since 4.8.0 The filter's default value is `true` rather than `null`.
       
  3392 	 *
       
  3393 	 * @link https://core.trac.wordpress.org/ticket/31071
       
  3394 	 *
       
  3395 	 * @param bool|null Whether to show the button, or `null` to decide based
       
  3396 	 *                  on whether any video files exist in the media library.
       
  3397 	 */
       
  3398 	$show_video_playlist = apply_filters( 'media_library_show_video_playlist', true );
       
  3399 	if ( null === $show_video_playlist ) {
       
  3400 		$show_video_playlist = $wpdb->get_var( "
       
  3401 			SELECT ID
       
  3402 			FROM $wpdb->posts
       
  3403 			WHERE post_type = 'attachment'
       
  3404 			AND post_mime_type LIKE 'video%'
       
  3405 			LIMIT 1
       
  3406 		" );
       
  3407 	}
       
  3408 
       
  3409 	/**
       
  3410 	 * Allows overriding the list of months displayed in the media library.
       
  3411 	 *
       
  3412 	 * By default (if this filter does not return an array), a query will be
       
  3413 	 * run to determine the months that have media items.  This query can be
       
  3414 	 * expensive for large media libraries, so it may be desirable for sites to
       
  3415 	 * override this behavior.
       
  3416 	 *
       
  3417 	 * @since 4.7.4
       
  3418 	 *
       
  3419 	 * @link https://core.trac.wordpress.org/ticket/31071
       
  3420 	 *
       
  3421 	 * @param array|null An array of objects with `month` and `year`
       
  3422 	 *                   properties, or `null` (or any other non-array value)
       
  3423 	 *                   for default behavior.
       
  3424 	 */
       
  3425 	$months = apply_filters( 'media_library_months_with_files', null );
       
  3426 	if ( ! is_array( $months ) ) {
       
  3427 		$months = $wpdb->get_results( $wpdb->prepare( "
       
  3428 			SELECT DISTINCT YEAR( post_date ) AS year, MONTH( post_date ) AS month
       
  3429 			FROM $wpdb->posts
       
  3430 			WHERE post_type = %s
       
  3431 			ORDER BY post_date DESC
       
  3432 		", 'attachment' ) );
       
  3433 	}
  2941 	foreach ( $months as $month_year ) {
  3434 	foreach ( $months as $month_year ) {
  2942 		$month_year->text = sprintf( __( '%1$s %2$d' ), $wp_locale->get_month( $month_year->month ), $month_year->year );
  3435 		$month_year->text = sprintf( __( '%1$s %2$d' ), $wp_locale->get_month( $month_year->month ), $month_year->year );
  2943 	}
  3436 	}
  2944 
  3437 
  2945 	$settings = array(
  3438 	$settings = array(
  2954 		'post'    => array(
  3447 		'post'    => array(
  2955 			'id' => 0,
  3448 			'id' => 0,
  2956 		),
  3449 		),
  2957 		'defaultProps' => $props,
  3450 		'defaultProps' => $props,
  2958 		'attachmentCounts' => array(
  3451 		'attachmentCounts' => array(
  2959 			'audio' => ( $has_audio ) ? 1 : 0,
  3452 			'audio' => ( $show_audio_playlist ) ? 1 : 0,
  2960 			'video' => ( $has_video ) ? 1 : 0
  3453 			'video' => ( $show_video_playlist ) ? 1 : 0,
  2961 		),
  3454 		),
       
  3455 		'oEmbedProxyUrl' => rest_url( 'oembed/1.0/proxy' ),
  2962 		'embedExts'    => $exts,
  3456 		'embedExts'    => $exts,
  2963 		'embedMimes'   => $ext_mimes,
  3457 		'embedMimes'   => $ext_mimes,
  2964 		'contentWidth' => $content_width,
  3458 		'contentWidth' => $content_width,
  2965 		'months'       => $months,
  3459 		'months'       => $months,
  2966 		'mediaTrash'   => MEDIA_TRASH ? 1 : 0
  3460 		'mediaTrash'   => MEDIA_TRASH ? 1 : 0,
  2967 	);
  3461 	);
  2968 
  3462 
  2969 	$post = null;
  3463 	$post = null;
  2970 	if ( isset( $args['post'] ) ) {
  3464 	if ( isset( $args['post'] ) ) {
  2971 		$post = get_post( $args['post'] );
  3465 		$post = get_post( $args['post'] );
  2987 			$featured_image_id = get_post_meta( $post->ID, '_thumbnail_id', true );
  3481 			$featured_image_id = get_post_meta( $post->ID, '_thumbnail_id', true );
  2988 			$settings['post']['featuredImageId'] = $featured_image_id ? $featured_image_id : -1;
  3482 			$settings['post']['featuredImageId'] = $featured_image_id ? $featured_image_id : -1;
  2989 		}
  3483 		}
  2990 	}
  3484 	}
  2991 
  3485 
  2992 	$hier = $post && is_post_type_hierarchical( $post->post_type );
  3486 	if ( $post ) {
       
  3487 		$post_type_object = get_post_type_object( $post->post_type );
       
  3488 	} else {
       
  3489 		$post_type_object = get_post_type_object( 'post' );
       
  3490 	}
  2993 
  3491 
  2994 	$strings = array(
  3492 	$strings = array(
  2995 		// Generic
  3493 		// Generic
  2996 		'url'         => __( 'URL' ),
  3494 		'url'         => __( 'URL' ),
  2997 		'addMedia'    => __( 'Add Media' ),
  3495 		'addMedia'    => __( 'Add Media' ),
  3013 		'uploadFilesTitle'  => __( 'Upload Files' ),
  3511 		'uploadFilesTitle'  => __( 'Upload Files' ),
  3014 		'uploadImagesTitle' => __( 'Upload Images' ),
  3512 		'uploadImagesTitle' => __( 'Upload Images' ),
  3015 
  3513 
  3016 		// Library
  3514 		// Library
  3017 		'mediaLibraryTitle'      => __( 'Media Library' ),
  3515 		'mediaLibraryTitle'      => __( 'Media Library' ),
  3018 		'insertMediaTitle'       => __( 'Insert Media' ),
  3516 		'insertMediaTitle'       => __( 'Add Media' ),
  3019 		'createNewGallery'       => __( 'Create a new gallery' ),
  3517 		'createNewGallery'       => __( 'Create a new gallery' ),
  3020 		'createNewPlaylist'      => __( 'Create a new playlist' ),
  3518 		'createNewPlaylist'      => __( 'Create a new playlist' ),
  3021 		'createNewVideoPlaylist' => __( 'Create a new video playlist' ),
  3519 		'createNewVideoPlaylist' => __( 'Create a new video playlist' ),
  3022 		'returnToLibrary'        => __( '&#8592; Return to library' ),
  3520 		'returnToLibrary'        => __( '&#8592; Return to library' ),
  3023 		'allMediaItems'          => __( 'All media items' ),
  3521 		'allMediaItems'          => __( 'All media items' ),
  3024 		'allDates'               => __( 'All dates' ),
  3522 		'allDates'               => __( 'All dates' ),
  3025 		'noItemsFound'           => __( 'No items found.' ),
  3523 		'noItemsFound'           => __( 'No items found.' ),
  3026 		'insertIntoPost'         => $hier ? __( 'Insert into page' ) : __( 'Insert into post' ),
  3524 		'insertIntoPost'         => $post_type_object->labels->insert_into_item,
  3027 		'unattached'             => __( 'Unattached' ),
  3525 		'unattached'             => __( 'Unattached' ),
       
  3526 		'mine'                   => _x( 'Mine', 'media items' ),
  3028 		'trash'                  => _x( 'Trash', 'noun' ),
  3527 		'trash'                  => _x( 'Trash', 'noun' ),
  3029 		'uploadedToThisPost'     => $hier ? __( 'Uploaded to this page' ) : __( 'Uploaded to this post' ),
  3528 		'uploadedToThisPost'     => $post_type_object->labels->uploaded_to_this_item,
  3030 		'warnDelete'             => __( "You are about to permanently delete this item.\n  'Cancel' to stop, 'OK' to delete." ),
  3529 		'warnDelete'             => __( "You are about to permanently delete this item from your site.\nThis action cannot be undone.\n 'Cancel' to stop, 'OK' to delete." ),
  3031 		'warnBulkDelete'         => __( "You are about to permanently delete these items.\n  'Cancel' to stop, 'OK' to delete." ),
  3530 		'warnBulkDelete'         => __( "You are about to permanently delete these items from your site.\nThis action cannot be undone.\n 'Cancel' to stop, 'OK' to delete." ),
  3032 		'warnBulkTrash'          => __( "You are about to trash these items.\n  'Cancel' to stop, 'OK' to delete." ),
  3531 		'warnBulkTrash'          => __( "You are about to trash these items.\n  'Cancel' to stop, 'OK' to delete." ),
  3033 		'bulkSelect'             => __( 'Bulk Select' ),
  3532 		'bulkSelect'             => __( 'Bulk Select' ),
  3034 		'cancelSelection'        => __( 'Cancel Selection' ),
  3533 		'cancelSelection'        => __( 'Cancel Selection' ),
  3035 		'trashSelected'          => __( 'Trash Selected' ),
  3534 		'trashSelected'          => __( 'Trash Selected' ),
  3036 		'untrashSelected'        => __( 'Untrash Selected' ),
  3535 		'untrashSelected'        => __( 'Untrash Selected' ),
  3038 		'deletePermanently'      => __( 'Delete Permanently' ),
  3537 		'deletePermanently'      => __( 'Delete Permanently' ),
  3039 		'apply'                  => __( 'Apply' ),
  3538 		'apply'                  => __( 'Apply' ),
  3040 		'filterByDate'           => __( 'Filter by date' ),
  3539 		'filterByDate'           => __( 'Filter by date' ),
  3041 		'filterByType'           => __( 'Filter by type' ),
  3540 		'filterByType'           => __( 'Filter by type' ),
  3042 		'searchMediaLabel'       => __( 'Search Media' ),
  3541 		'searchMediaLabel'       => __( 'Search Media' ),
  3043 		'noMedia'                => __( 'No media attachments found.' ),
  3542 		'searchMediaPlaceholder' => __( 'Search media items...' ), // placeholder (no ellipsis)
       
  3543 		'noMedia'                => __( 'No media files found.' ),
  3044 
  3544 
  3045 		// Library Details
  3545 		// Library Details
  3046 		'attachmentDetails'  => __( 'Attachment Details' ),
  3546 		'attachmentDetails'  => __( 'Attachment Details' ),
  3047 
  3547 
  3048 		// From URL
  3548 		// From URL
  3049 		'insertFromUrlTitle' => __( 'Insert from URL' ),
  3549 		'insertFromUrlTitle' => __( 'Insert from URL' ),
  3050 
  3550 
  3051 		// Featured Images
  3551 		// Featured Images
  3052 		'setFeaturedImageTitle' => __( 'Set Featured Image' ),
  3552 		'setFeaturedImageTitle' => $post_type_object->labels->featured_image,
  3053 		'setFeaturedImage'    => __( 'Set featured image' ),
  3553 		'setFeaturedImage'      => $post_type_object->labels->set_featured_image,
  3054 
  3554 
  3055 		// Gallery
  3555 		// Gallery
  3056 		'createGalleryTitle' => __( 'Create Gallery' ),
  3556 		'createGalleryTitle' => __( 'Create Gallery' ),
  3057 		'editGalleryTitle'   => __( 'Edit Gallery' ),
  3557 		'editGalleryTitle'   => __( 'Edit Gallery' ),
  3058 		'cancelGalleryTitle' => __( '&#8592; Cancel Gallery' ),
  3558 		'cancelGalleryTitle' => __( '&#8592; Cancel Gallery' ),
  3073 		'selectAndCrop' => __( 'Select and Crop' ),
  3573 		'selectAndCrop' => __( 'Select and Crop' ),
  3074 		'skipCropping' => __( 'Skip Cropping' ),
  3574 		'skipCropping' => __( 'Skip Cropping' ),
  3075 		'cropImage' => __( 'Crop Image' ),
  3575 		'cropImage' => __( 'Crop Image' ),
  3076 		'cropYourImage' => __( 'Crop your image' ),
  3576 		'cropYourImage' => __( 'Crop your image' ),
  3077 		'cropping' => __( 'Cropping&hellip;' ),
  3577 		'cropping' => __( 'Cropping&hellip;' ),
  3078 		'suggestedDimensions' => __( 'Suggested image dimensions:' ),
  3578 		/* translators: 1: suggested width number, 2: suggested height number. */
       
  3579 		'suggestedDimensions' => __( 'Suggested image dimensions: %1$s by %2$s pixels.' ),
  3079 		'cropError' => __( 'There has been an error cropping your image.' ),
  3580 		'cropError' => __( 'There has been an error cropping your image.' ),
  3080 
  3581 
  3081 		// Edit Audio
  3582 		// Edit Audio
  3082 		'audioDetailsTitle'     => __( 'Audio Details' ),
  3583 		'audioDetailsTitle'     => __( 'Audio Details' ),
  3083 		'audioReplaceTitle'     => __( 'Replace Audio' ),
  3584 		'audioReplaceTitle'     => __( 'Replace Audio' ),
  3112  		'addToVideoPlaylist'       => __( 'Add to video playlist' ),
  3613  		'addToVideoPlaylist'       => __( 'Add to video playlist' ),
  3113  		'addToVideoPlaylistTitle'  => __( 'Add to Video Playlist' ),
  3614  		'addToVideoPlaylistTitle'  => __( 'Add to Video Playlist' ),
  3114 	);
  3615 	);
  3115 
  3616 
  3116 	/**
  3617 	/**
  3117 	 * Filter the media view settings.
  3618 	 * Filters the media view settings.
  3118 	 *
  3619 	 *
  3119 	 * @since 3.5.0
  3620 	 * @since 3.5.0
  3120 	 *
  3621 	 *
  3121 	 * @param array   $settings List of media view settings.
  3622 	 * @param array   $settings List of media view settings.
  3122 	 * @param WP_Post $post     Post object.
  3623 	 * @param WP_Post $post     Post object.
  3123 	 */
  3624 	 */
  3124 	$settings = apply_filters( 'media_view_settings', $settings, $post );
  3625 	$settings = apply_filters( 'media_view_settings', $settings, $post );
  3125 
  3626 
  3126 	/**
  3627 	/**
  3127 	 * Filter the media view strings.
  3628 	 * Filters the media view strings.
  3128 	 *
  3629 	 *
  3129 	 * @since 3.5.0
  3630 	 * @since 3.5.0
  3130 	 *
  3631 	 *
  3131 	 * @param array   $strings List of media view strings.
  3632 	 * @param array   $strings List of media view strings.
  3132 	 * @param WP_Post $post    Post object.
  3633 	 * @param WP_Post $post    Post object.
  3183 		'orderby' => 'menu_order',
  3684 		'orderby' => 'menu_order',
  3184 		'order' => 'ASC',
  3685 		'order' => 'ASC',
  3185 	);
  3686 	);
  3186 
  3687 
  3187 	/**
  3688 	/**
  3188 	 * Filter arguments used to retrieve media attached to the given post.
  3689 	 * Filters arguments used to retrieve media attached to the given post.
  3189 	 *
  3690 	 *
  3190 	 * @since 3.6.0
  3691 	 * @since 3.6.0
  3191 	 *
  3692 	 *
  3192 	 * @param array  $args Post query arguments.
  3693 	 * @param array  $args Post query arguments.
  3193 	 * @param string $type Mime type of the desired media.
  3694 	 * @param string $type Mime type of the desired media.
  3196 	$args = apply_filters( 'get_attached_media_args', $args, $type, $post );
  3697 	$args = apply_filters( 'get_attached_media_args', $args, $type, $post );
  3197 
  3698 
  3198 	$children = get_children( $args );
  3699 	$children = get_children( $args );
  3199 
  3700 
  3200 	/**
  3701 	/**
  3201 	 * Filter the list of media attached to the given post.
  3702 	 * Filters the list of media attached to the given post.
  3202 	 *
  3703 	 *
  3203 	 * @since 3.6.0
  3704 	 * @since 3.6.0
  3204 	 *
  3705 	 *
  3205 	 * @param array  $children Associative array of media attached to the given post.
  3706 	 * @param array  $children Associative array of media attached to the given post.
  3206 	 * @param string $type     Mime type of the media desired.
  3707 	 * @param string $type     Mime type of the media desired.
  3220  */
  3721  */
  3221 function get_media_embedded_in_content( $content, $types = null ) {
  3722 function get_media_embedded_in_content( $content, $types = null ) {
  3222 	$html = array();
  3723 	$html = array();
  3223 
  3724 
  3224 	/**
  3725 	/**
  3225 	 * Filter the embedded media types that are allowed to be returned from the content blob.
  3726 	 * Filters the embedded media types that are allowed to be returned from the content blob.
  3226 	 *
  3727 	 *
  3227 	 * @since 4.2.0
  3728 	 * @since 4.2.0
  3228 	 *
  3729 	 *
  3229 	 * @param array $allowed_media_types An array of allowed media types. Default media types are
  3730 	 * @param array $allowed_media_types An array of allowed media types. Default media types are
  3230 	 *                                   'audio', 'video', 'object', 'embed', and 'iframe'.
  3731 	 *                                   'audio', 'video', 'object', 'embed', and 'iframe'.
  3270 	$galleries = array();
  3771 	$galleries = array();
  3271 	if ( preg_match_all( '/' . get_shortcode_regex() . '/s', $post->post_content, $matches, PREG_SET_ORDER ) ) {
  3772 	if ( preg_match_all( '/' . get_shortcode_regex() . '/s', $post->post_content, $matches, PREG_SET_ORDER ) ) {
  3272 		foreach ( $matches as $shortcode ) {
  3773 		foreach ( $matches as $shortcode ) {
  3273 			if ( 'gallery' === $shortcode[2] ) {
  3774 			if ( 'gallery' === $shortcode[2] ) {
  3274 				$srcs = array();
  3775 				$srcs = array();
       
  3776 
       
  3777 				$shortcode_attrs = shortcode_parse_atts( $shortcode[3] );
       
  3778 				if ( ! is_array( $shortcode_attrs ) ) {
       
  3779 					$shortcode_attrs = array();
       
  3780 				}
       
  3781 
       
  3782 				// Specify the post id of the gallery we're viewing if the shortcode doesn't reference another post already.
       
  3783 				if ( ! isset( $shortcode_attrs['id'] ) ) {
       
  3784 					$shortcode[3] .= ' id="' . intval( $post->ID ) . '"';
       
  3785 				}
  3275 
  3786 
  3276 				$gallery = do_shortcode_tag( $shortcode );
  3787 				$gallery = do_shortcode_tag( $shortcode );
  3277 				if ( $html ) {
  3788 				if ( $html ) {
  3278 					$galleries[] = $gallery;
  3789 					$galleries[] = $gallery;
  3279 				} else {
  3790 				} else {
  3280 					preg_match_all( '#src=([\'"])(.+?)\1#is', $gallery, $src, PREG_SET_ORDER );
  3791 					preg_match_all( '#src=([\'"])(.+?)\1#is', $gallery, $src, PREG_SET_ORDER );
  3281 					if ( ! empty( $src ) ) {
  3792 					if ( ! empty( $src ) ) {
  3282 						foreach ( $src as $s )
  3793 						foreach ( $src as $s ) {
  3283 							$srcs[] = $s[2];
  3794 							$srcs[] = $s[2];
       
  3795 						}
  3284 					}
  3796 					}
  3285 
  3797 
  3286 					$data = shortcode_parse_atts( $shortcode[3] );
  3798 					$galleries[] = array_merge(
  3287 					$data['src'] = array_values( array_unique( $srcs ) );
  3799 						$shortcode_attrs,
  3288 					$galleries[] = $data;
  3800 						array(
       
  3801 							'src' => array_values( array_unique( $srcs ) )
       
  3802 						)
       
  3803 					);
  3289 				}
  3804 				}
  3290 			}
  3805 			}
  3291 		}
  3806 		}
  3292 	}
  3807 	}
  3293 
  3808 
  3294 	/**
  3809 	/**
  3295 	 * Filter the list of all found galleries in the given post.
  3810 	 * Filters the list of all found galleries in the given post.
  3296 	 *
  3811 	 *
  3297 	 * @since 3.6.0
  3812 	 * @since 3.6.0
  3298 	 *
  3813 	 *
  3299 	 * @param array   $galleries Associative array of all found post galleries.
  3814 	 * @param array   $galleries Associative array of all found post galleries.
  3300 	 * @param WP_Post $post      Post object.
  3815 	 * @param WP_Post $post      Post object.
  3314 function get_post_gallery( $post = 0, $html = true ) {
  3829 function get_post_gallery( $post = 0, $html = true ) {
  3315 	$galleries = get_post_galleries( $post, $html );
  3830 	$galleries = get_post_galleries( $post, $html );
  3316 	$gallery = reset( $galleries );
  3831 	$gallery = reset( $galleries );
  3317 
  3832 
  3318 	/**
  3833 	/**
  3319 	 * Filter the first-found post gallery.
  3834 	 * Filters the first-found post gallery.
  3320 	 *
  3835 	 *
  3321 	 * @since 3.6.0
  3836 	 * @since 3.6.0
  3322 	 *
  3837 	 *
  3323 	 * @param array       $gallery   The first-found post gallery.
  3838 	 * @param array       $gallery   The first-found post gallery.
  3324 	 * @param int|WP_Post $post      Post ID or object.
  3839 	 * @param int|WP_Post $post      Post ID or object.
  3394  * @return int The found post ID, or 0 on failure.
  3909  * @return int The found post ID, or 0 on failure.
  3395  */
  3910  */
  3396 function attachment_url_to_postid( $url ) {
  3911 function attachment_url_to_postid( $url ) {
  3397 	global $wpdb;
  3912 	global $wpdb;
  3398 
  3913 
  3399 	$dir = wp_upload_dir();
  3914 	$dir = wp_get_upload_dir();
  3400 	$path = $url;
  3915 	$path = $url;
       
  3916 
       
  3917 	$site_url = parse_url( $dir['url'] );
       
  3918 	$image_path = parse_url( $path );
       
  3919 
       
  3920 	//force the protocols to match if needed
       
  3921 	if ( isset( $image_path['scheme'] ) && ( $image_path['scheme'] !== $site_url['scheme'] ) ) {
       
  3922 		$path = str_replace( $image_path['scheme'], $site_url['scheme'], $path );
       
  3923 	}
  3401 
  3924 
  3402 	if ( 0 === strpos( $path, $dir['baseurl'] . '/' ) ) {
  3925 	if ( 0 === strpos( $path, $dir['baseurl'] . '/' ) ) {
  3403 		$path = substr( $path, strlen( $dir['baseurl'] . '/' ) );
  3926 		$path = substr( $path, strlen( $dir['baseurl'] . '/' ) );
  3404 	}
  3927 	}
  3405 
  3928 
  3408 		$path
  3931 		$path
  3409 	);
  3932 	);
  3410 	$post_id = $wpdb->get_var( $sql );
  3933 	$post_id = $wpdb->get_var( $sql );
  3411 
  3934 
  3412 	/**
  3935 	/**
  3413 	 * Filter an attachment id found by URL.
  3936 	 * Filters an attachment id found by URL.
  3414 	 *
  3937 	 *
  3415 	 * @since 4.2.0
  3938 	 * @since 4.2.0
  3416 	 *
  3939 	 *
  3417 	 * @param int|null $post_id The post_id (if any) found by the function.
  3940 	 * @param int|null $post_id The post_id (if any) found by the function.
  3418 	 * @param string   $url     The URL being looked up.
  3941 	 * @param string   $url     The URL being looked up.
  3419 	 */
  3942 	 */
  3420 	$post_id = apply_filters( 'attachment_url_to_postid', $post_id, $url );
  3943 	return (int) apply_filters( 'attachment_url_to_postid', $post_id, $url );
  3421 
       
  3422 	return (int) $post_id;
       
  3423 }
  3944 }
  3424 
  3945 
  3425 /**
  3946 /**
  3426  * Returns the URLs for CSS files used in an iframe-sandbox'd TinyMCE media view.
  3947  * Returns the URLs for CSS files used in an iframe-sandbox'd TinyMCE media view.
  3427  *
  3948  *
  3428  * @since 4.0.0
  3949  * @since 4.0.0
  3429  *
  3950  *
  3430  * @global $wp_version
       
  3431  *
       
  3432  * @return array The relevant CSS file URLs.
  3951  * @return array The relevant CSS file URLs.
  3433  */
  3952  */
  3434 function wpview_media_sandbox_styles() {
  3953 function wpview_media_sandbox_styles() {
  3435  	$version = 'ver=' . $GLOBALS['wp_version'];
  3954  	$version = 'ver=' . get_bloginfo( 'version' );
  3436  	$mediaelement = includes_url( "js/mediaelement/mediaelementplayer.min.css?$version" );
  3955  	$mediaelement = includes_url( "js/mediaelement/mediaelementplayer-legacy.min.css?$version" );
  3437  	$wpmediaelement = includes_url( "js/mediaelement/wp-mediaelement.css?$version" );
  3956  	$wpmediaelement = includes_url( "js/mediaelement/wp-mediaelement.css?$version" );
  3438 
  3957 
  3439 	return array( $mediaelement, $wpmediaelement );
  3958 	return array( $mediaelement, $wpmediaelement );
  3440 }
  3959 }
       
  3960 
       
  3961 /**
       
  3962  * Registers the personal data exporter for media
       
  3963  *
       
  3964  * @param array   $exporters   An array of personal data exporters.
       
  3965  * @return array  An array of personal data exporters.
       
  3966  */
       
  3967 function wp_register_media_personal_data_exporter( $exporters ) {
       
  3968 	$exporters['wordpress-media'] = array(
       
  3969 		'exporter_friendly_name' => __( 'WordPress Media' ),
       
  3970 		'callback'               => 'wp_media_personal_data_exporter',
       
  3971 	);
       
  3972 
       
  3973 	return $exporters;
       
  3974 }
       
  3975 
       
  3976 /**
       
  3977  * Finds and exports attachments associated with an email address.
       
  3978  *
       
  3979  * @since 4.9.6
       
  3980  *
       
  3981  * @param  string $email_address The attachment owner email address.
       
  3982  * @param  int    $page          Attachment page.
       
  3983  * @return array  $return        An array of personal data.
       
  3984  */
       
  3985 function wp_media_personal_data_exporter( $email_address, $page = 1 ) {
       
  3986 	// Limit us to 50 attachments at a time to avoid timing out.
       
  3987 	$number = 50;
       
  3988 	$page   = (int) $page;
       
  3989 
       
  3990 	$data_to_export = array();
       
  3991 
       
  3992 	$user = get_user_by( 'email' , $email_address );
       
  3993 	if ( false === $user ) {
       
  3994 		return array(
       
  3995 			'data' => $data_to_export,
       
  3996 			'done' => true,
       
  3997 		);
       
  3998 	}
       
  3999 
       
  4000 	$post_query = new WP_Query(
       
  4001 		array(
       
  4002 			'author'         => $user->ID,
       
  4003 			'posts_per_page' => $number,
       
  4004 			'paged'          => $page,
       
  4005 			'post_type'      => 'attachment',
       
  4006 			'post_status'    => 'any',
       
  4007 			'orderby'        => 'ID',
       
  4008 			'order'          => 'ASC',
       
  4009 		)
       
  4010 	);
       
  4011 
       
  4012 	foreach ( (array) $post_query->posts as $post ) {
       
  4013 		$attachment_url = wp_get_attachment_url( $post->ID );
       
  4014 
       
  4015 		if ( $attachment_url ) {
       
  4016 			$post_data_to_export = array(
       
  4017 				array( 'name'  => __( 'URL' ), 'value' => $attachment_url ),
       
  4018 			);
       
  4019 
       
  4020 			$data_to_export[] = array(
       
  4021 				'group_id'    => 'media',
       
  4022 				'group_label' => __( 'Media' ),
       
  4023 				'item_id'     => "post-{$post->ID}",
       
  4024 				'data'        => $post_data_to_export,
       
  4025 			);
       
  4026 		}
       
  4027 	}
       
  4028 
       
  4029 	$done = $post_query->max_num_pages <= $page;
       
  4030 
       
  4031 	return array(
       
  4032 		'data' => $data_to_export,
       
  4033 		'done' => $done,
       
  4034 	);
       
  4035 }