wp/wp-includes/media.php
changeset 22 8c2e4d02f4ef
parent 21 48c4eec2b7e6
equal deleted inserted replaced
21:48c4eec2b7e6 22:8c2e4d02f4ef
     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 // Don't load directly.
       
    10 if ( ! defined( 'ABSPATH' ) ) {
       
    11 	die( '-1' );
       
    12 }
     8 
    13 
     9 /**
    14 /**
    10  * Retrieves additional image sizes.
    15  * Retrieves additional image sizes.
    11  *
    16  *
    12  * @since 4.7.0
    17  * @since 4.7.0
   286  * @param bool|array $crop   {
   291  * @param bool|array $crop   {
   287  *     Optional. Image cropping behavior. If false, the image will be scaled (default).
   292  *     Optional. Image cropping behavior. If false, the image will be scaled (default).
   288  *     If true, image will be cropped to the specified dimensions using center positions.
   293  *     If true, image will be cropped to the specified dimensions using center positions.
   289  *     If an array, the image will be cropped using the array to specify the crop location:
   294  *     If an array, the image will be cropped using the array to specify the crop location:
   290  *
   295  *
   291  *     @type string $0 The x crop position. Accepts 'left' 'center', or 'right'.
   296  *     @type string $0 The x crop position. Accepts 'left', 'center', or 'right'.
   292  *     @type string $1 The y crop position. Accepts 'top', 'center', or 'bottom'.
   297  *     @type string $1 The y crop position. Accepts 'top', 'center', or 'bottom'.
   293  * }
   298  * }
   294  */
   299  */
   295 function add_image_size( $name, $width = 0, $height = 0, $crop = false ) {
   300 function add_image_size( $name, $width = 0, $height = 0, $crop = false ) {
   296 	global $_wp_additional_image_sizes;
   301 	global $_wp_additional_image_sizes;
   348  * @param bool|array $crop   {
   353  * @param bool|array $crop   {
   349  *     Optional. Image cropping behavior. If false, the image will be scaled (default).
   354  *     Optional. Image cropping behavior. If false, the image will be scaled (default).
   350  *     If true, image will be cropped to the specified dimensions using center positions.
   355  *     If true, image will be cropped to the specified dimensions using center positions.
   351  *     If an array, the image will be cropped using the array to specify the crop location:
   356  *     If an array, the image will be cropped using the array to specify the crop location:
   352  *
   357  *
   353  *     @type string $0 The x crop position. Accepts 'left' 'center', or 'right'.
   358  *     @type string $0 The x crop position. Accepts 'left', 'center', or 'right'.
   354  *     @type string $1 The y crop position. Accepts 'top', 'center', or 'bottom'.
   359  *     @type string $1 The y crop position. Accepts 'top', 'center', or 'bottom'.
   355  * }
   360  * }
   356  */
   361  */
   357 function set_post_thumbnail_size( $width = 0, $height = 0, $crop = false ) {
   362 function set_post_thumbnail_size( $width = 0, $height = 0, $crop = false ) {
   358 	add_image_size( 'post-thumbnail', $width, $height, $crop );
   363 	add_image_size( 'post-thumbnail', $width, $height, $crop );
   528  * @param bool|array $crop   {
   533  * @param bool|array $crop   {
   529  *     Optional. Image cropping behavior. If false, the image will be scaled (default).
   534  *     Optional. Image cropping behavior. If false, the image will be scaled (default).
   530  *     If true, image will be cropped to the specified dimensions using center positions.
   535  *     If true, image will be cropped to the specified dimensions using center positions.
   531  *     If an array, the image will be cropped using the array to specify the crop location:
   536  *     If an array, the image will be cropped using the array to specify the crop location:
   532  *
   537  *
   533  *     @type string $0 The x crop position. Accepts 'left' 'center', or 'right'.
   538  *     @type string $0 The x crop position. Accepts 'left', 'center', or 'right'.
   534  *     @type string $1 The y crop position. Accepts 'top', 'center', or 'bottom'.
   539  *     @type string $1 The y crop position. Accepts 'top', 'center', or 'bottom'.
   535  * }
   540  * }
   536  * @return array|false Returned array matches parameters for `imagecopyresampled()`. False on failure.
   541  * @return array|false Returned array matches parameters for `imagecopyresampled()`. False on failure.
   537  */
   542  */
   538 function image_resize_dimensions( $orig_w, $orig_h, $dest_w, $dest_h, $crop = false ) {
   543 function image_resize_dimensions( $orig_w, $orig_h, $dest_w, $dest_h, $crop = false ) {
   682  * @param bool|array $crop   {
   687  * @param bool|array $crop   {
   683  *     Optional. Image cropping behavior. If false, the image will be scaled (default).
   688  *     Optional. Image cropping behavior. If false, the image will be scaled (default).
   684  *     If true, image will be cropped to the specified dimensions using center positions.
   689  *     If true, image will be cropped to the specified dimensions using center positions.
   685  *     If an array, the image will be cropped using the array to specify the crop location:
   690  *     If an array, the image will be cropped using the array to specify the crop location:
   686  *
   691  *
   687  *     @type string $0 The x crop position. Accepts 'left' 'center', or 'right'.
   692  *     @type string $0 The x crop position. Accepts 'left', 'center', or 'right'.
   688  *     @type string $1 The y crop position. Accepts 'top', 'center', or 'bottom'.
   693  *     @type string $1 The y crop position. Accepts 'top', 'center', or 'bottom'.
   689  * }
   694  * }
   690  * @return array|false Metadata array on success. False if no image was created.
   695  * @return array|false Metadata array on success. False if no image was created.
   691  */
   696  */
   692 function image_make_intermediate_size( $file, $width, $height, $crop = false ) {
   697 function image_make_intermediate_size( $file, $width, $height, $crop = false ) {
  1063 
  1068 
  1064 	if ( $image ) {
  1069 	if ( $image ) {
  1065 		list( $src, $width, $height ) = $image;
  1070 		list( $src, $width, $height ) = $image;
  1066 
  1071 
  1067 		$attachment = get_post( $attachment_id );
  1072 		$attachment = get_post( $attachment_id );
  1068 		$hwstring   = image_hwstring( $width, $height );
       
  1069 		$size_class = $size;
  1073 		$size_class = $size;
  1070 
  1074 
  1071 		if ( is_array( $size_class ) ) {
  1075 		if ( is_array( $size_class ) ) {
  1072 			$size_class = implode( 'x', $size_class );
  1076 			$size_class = implode( 'x', $size_class );
  1073 		}
  1077 		}
  1083 		 *
  1087 		 *
  1084 		 * @since 6.3.0
  1088 		 * @since 6.3.0
  1085 		 *
  1089 		 *
  1086 		 * @param string $context The context. Default 'wp_get_attachment_image'.
  1090 		 * @param string $context The context. Default 'wp_get_attachment_image'.
  1087 		 */
  1091 		 */
  1088 		$context = apply_filters( 'wp_get_attachment_image_context', 'wp_get_attachment_image' );
  1092 		$context        = apply_filters( 'wp_get_attachment_image_context', 'wp_get_attachment_image' );
  1089 		$attr    = wp_parse_args( $attr, $default_attr );
  1093 		$attr           = wp_parse_args( $attr, $default_attr );
  1090 
  1094 		$attr['width']  = $width;
  1091 		$loading_attr              = $attr;
  1095 		$attr['height'] = $height;
  1092 		$loading_attr['width']     = $width;
  1096 
  1093 		$loading_attr['height']    = $height;
       
  1094 		$loading_optimization_attr = wp_get_loading_optimization_attributes(
  1097 		$loading_optimization_attr = wp_get_loading_optimization_attributes(
  1095 			'img',
  1098 			'img',
  1096 			$loading_attr,
  1099 			$attr,
  1097 			$context
  1100 			$context
  1098 		);
  1101 		);
  1099 
  1102 
  1100 		// Add loading optimization attributes if not available.
  1103 		// Add loading optimization attributes if not available.
  1101 		$attr = array_merge( $attr, $loading_optimization_attr );
  1104 		$attr = array_merge( $attr, $loading_optimization_attr );
  1133 					if ( empty( $attr['sizes'] ) ) {
  1136 					if ( empty( $attr['sizes'] ) ) {
  1134 						$attr['sizes'] = $sizes;
  1137 						$attr['sizes'] = $sizes;
  1135 					}
  1138 					}
  1136 				}
  1139 				}
  1137 			}
  1140 			}
       
  1141 		}
       
  1142 
       
  1143 		/** This filter is documented in wp-includes/media.php */
       
  1144 		$add_auto_sizes = apply_filters( 'wp_img_tag_add_auto_sizes', true );
       
  1145 
       
  1146 		// Adds 'auto' to the sizes attribute if applicable.
       
  1147 		if (
       
  1148 			$add_auto_sizes &&
       
  1149 			isset( $attr['loading'] ) &&
       
  1150 			'lazy' === $attr['loading'] &&
       
  1151 			isset( $attr['sizes'] ) &&
       
  1152 			! wp_sizes_attribute_includes_valid_auto( $attr['sizes'] )
       
  1153 		) {
       
  1154 			$attr['sizes'] = 'auto, ' . $attr['sizes'];
  1138 		}
  1155 		}
  1139 
  1156 
  1140 		/**
  1157 		/**
  1141 		 * Filters the list of attachment image attributes.
  1158 		 * Filters the list of attachment image attributes.
  1142 		 *
  1159 		 *
  1148 		 * @param string|int[] $size       Requested image size. Can be any registered image size name, or
  1165 		 * @param string|int[] $size       Requested image size. Can be any registered image size name, or
  1149 		 *                                 an array of width and height values in pixels (in that order).
  1166 		 *                                 an array of width and height values in pixels (in that order).
  1150 		 */
  1167 		 */
  1151 		$attr = apply_filters( 'wp_get_attachment_image_attributes', $attr, $attachment, $size );
  1168 		$attr = apply_filters( 'wp_get_attachment_image_attributes', $attr, $attachment, $size );
  1152 
  1169 
  1153 		$attr = array_map( 'esc_attr', $attr );
  1170 		if ( isset( $attr['height'] ) && is_numeric( $attr['height'] ) ) {
  1154 		$html = rtrim( "<img $hwstring" );
  1171 			$height = absint( $attr['height'] );
       
  1172 		}
       
  1173 		if ( isset( $attr['width'] ) && is_numeric( $attr['width'] ) ) {
       
  1174 			$width = absint( $attr['width'] );
       
  1175 		}
       
  1176 		unset( $attr['height'], $attr['width'] );
       
  1177 		$attr     = array_map( 'esc_attr', $attr );
       
  1178 		$hwstring = image_hwstring( $width, $height );
       
  1179 		$html     = rtrim( "<img $hwstring" );
  1155 
  1180 
  1156 		foreach ( $attr as $name => $value ) {
  1181 		foreach ( $attr as $name => $value ) {
  1157 			$html .= " $name=" . '"' . $value . '"';
  1182 			$html .= " $name=" . '"' . $value . '"';
  1158 		}
  1183 		}
  1159 
  1184 
  1915 			}
  1940 			}
  1916 
  1941 
  1917 			// Add loading optimization attributes if applicable.
  1942 			// Add loading optimization attributes if applicable.
  1918 			$filtered_image = wp_img_tag_add_loading_optimization_attrs( $filtered_image, $context );
  1943 			$filtered_image = wp_img_tag_add_loading_optimization_attrs( $filtered_image, $context );
  1919 
  1944 
       
  1945 			// Adds 'auto' to the sizes attribute if applicable.
       
  1946 			$filtered_image = wp_img_tag_add_auto_sizes( $filtered_image );
       
  1947 
  1920 			/**
  1948 			/**
  1921 			 * Filters an img tag within the content for a given context.
  1949 			 * Filters an img tag within the content for a given context.
  1922 			 *
  1950 			 *
  1923 			 * @since 6.0.0
  1951 			 * @since 6.0.0
  1924 			 *
  1952 			 *
  1962 
  1990 
  1963 	return $content;
  1991 	return $content;
  1964 }
  1992 }
  1965 
  1993 
  1966 /**
  1994 /**
       
  1995  * Adds 'auto' to the sizes attribute to the image, if the image is lazy loaded and does not already include it.
       
  1996  *
       
  1997  * @since 6.7.0
       
  1998  *
       
  1999  * @param string $image The image tag markup being filtered.
       
  2000  * @return string The filtered image tag markup.
       
  2001  */
       
  2002 function wp_img_tag_add_auto_sizes( string $image ): string {
       
  2003 	/**
       
  2004 	 * Filters whether auto-sizes for lazy loaded images is enabled.
       
  2005 	 *
       
  2006 	 * @since 6.7.1
       
  2007 	 *
       
  2008 	 * @param boolean $enabled Whether auto-sizes for lazy loaded images is enabled.
       
  2009 	 */
       
  2010 	if ( ! apply_filters( 'wp_img_tag_add_auto_sizes', true ) ) {
       
  2011 		return $image;
       
  2012 	}
       
  2013 
       
  2014 	$processor = new WP_HTML_Tag_Processor( $image );
       
  2015 
       
  2016 	// Bail if there is no IMG tag.
       
  2017 	if ( ! $processor->next_tag( array( 'tag_name' => 'IMG' ) ) ) {
       
  2018 		return $image;
       
  2019 	}
       
  2020 
       
  2021 	// Bail early if the image is not lazy-loaded.
       
  2022 	$loading = $processor->get_attribute( 'loading' );
       
  2023 	if ( ! is_string( $loading ) || 'lazy' !== strtolower( trim( $loading, " \t\f\r\n" ) ) ) {
       
  2024 		return $image;
       
  2025 	}
       
  2026 
       
  2027 	/*
       
  2028 	 * Bail early if the image doesn't have a width attribute.
       
  2029 	 * Per WordPress Core itself, lazy-loaded images should always have a width attribute.
       
  2030 	 * However, it is possible that lazy-loading could be added by a plugin, where we don't have that guarantee.
       
  2031 	 * As such, it still makes sense to ensure presence of a width attribute here in order to use `sizes=auto`.
       
  2032 	 */
       
  2033 	$width = $processor->get_attribute( 'width' );
       
  2034 	if ( ! is_string( $width ) || '' === $width ) {
       
  2035 		return $image;
       
  2036 	}
       
  2037 
       
  2038 	$sizes = $processor->get_attribute( 'sizes' );
       
  2039 
       
  2040 	// Bail early if the image is not responsive.
       
  2041 	if ( ! is_string( $sizes ) ) {
       
  2042 		return $image;
       
  2043 	}
       
  2044 
       
  2045 	// Don't add 'auto' to the sizes attribute if it already exists.
       
  2046 	if ( wp_sizes_attribute_includes_valid_auto( $sizes ) ) {
       
  2047 		return $image;
       
  2048 	}
       
  2049 
       
  2050 	$processor->set_attribute( 'sizes', "auto, $sizes" );
       
  2051 	return $processor->get_updated_html();
       
  2052 }
       
  2053 
       
  2054 /**
       
  2055  * Checks whether the given 'sizes' attribute includes the 'auto' keyword as the first item in the list.
       
  2056  *
       
  2057  * Per the HTML spec, if present it must be the first entry.
       
  2058  *
       
  2059  * @since 6.7.0
       
  2060  *
       
  2061  * @param string $sizes_attr The 'sizes' attribute value.
       
  2062  * @return bool True if the 'auto' keyword is present, false otherwise.
       
  2063  */
       
  2064 function wp_sizes_attribute_includes_valid_auto( string $sizes_attr ): bool {
       
  2065 	list( $first_size ) = explode( ',', $sizes_attr, 2 );
       
  2066 	return 'auto' === strtolower( trim( $first_size, " \t\f\r\n" ) );
       
  2067 }
       
  2068 
       
  2069 /**
       
  2070  * Prints a CSS rule to fix potential visual issues with images using `sizes=auto`.
       
  2071  *
       
  2072  * This rule overrides the similar rule in the default user agent stylesheet, to avoid images that use e.g.
       
  2073  * `width: auto` or `width: fit-content` to appear smaller.
       
  2074  *
       
  2075  * @since 6.7.1
       
  2076  * @see https://html.spec.whatwg.org/multipage/rendering.html#img-contain-size
       
  2077  * @see https://core.trac.wordpress.org/ticket/62413
       
  2078  */
       
  2079 function wp_print_auto_sizes_contain_css_fix() {
       
  2080 	/** This filter is documented in wp-includes/media.php */
       
  2081 	$add_auto_sizes = apply_filters( 'wp_img_tag_add_auto_sizes', true );
       
  2082 	if ( ! $add_auto_sizes ) {
       
  2083 		return;
       
  2084 	}
       
  2085 
       
  2086 	?>
       
  2087 	<style>img:is([sizes="auto" i], [sizes^="auto," i]) { contain-intrinsic-size: 3000px 1500px }</style>
       
  2088 	<?php
       
  2089 }
       
  2090 
       
  2091 /**
  1967  * Adds optimization attributes to an `img` HTML tag.
  2092  * Adds optimization attributes to an `img` HTML tag.
  1968  *
  2093  *
  1969  * @since 6.3.0
  2094  * @since 6.3.0
  1970  *
  2095  *
  1971  * @param string $image   The HTML `img` tag where the attribute should be added.
  2096  * @param string $image   The HTML `img` tag where the attribute should be added.
  1972  * @param string $context Additional context to pass to the filters.
  2097  * @param string $context Additional context to pass to the filters.
  1973  * @return string Converted `img` tag with optimization attributes added.
  2098  * @return string Converted `img` tag with optimization attributes added.
  1974  */
  2099  */
  1975 function wp_img_tag_add_loading_optimization_attrs( $image, $context ) {
  2100 function wp_img_tag_add_loading_optimization_attrs( $image, $context ) {
       
  2101 	$src               = preg_match( '/ src=["\']?([^"\']*)/i', $image, $matche_src ) ? $matche_src[1] : null;
  1976 	$width             = preg_match( '/ width=["\']([0-9]+)["\']/', $image, $match_width ) ? (int) $match_width[1] : null;
  2102 	$width             = preg_match( '/ width=["\']([0-9]+)["\']/', $image, $match_width ) ? (int) $match_width[1] : null;
  1977 	$height            = preg_match( '/ height=["\']([0-9]+)["\']/', $image, $match_height ) ? (int) $match_height[1] : null;
  2103 	$height            = preg_match( '/ height=["\']([0-9]+)["\']/', $image, $match_height ) ? (int) $match_height[1] : null;
  1978 	$loading_val       = preg_match( '/ loading=["\']([A-Za-z]+)["\']/', $image, $match_loading ) ? $match_loading[1] : null;
  2104 	$loading_val       = preg_match( '/ loading=["\']([A-Za-z]+)["\']/', $image, $match_loading ) ? $match_loading[1] : null;
  1979 	$fetchpriority_val = preg_match( '/ fetchpriority=["\']([A-Za-z]+)["\']/', $image, $match_fetchpriority ) ? $match_fetchpriority[1] : null;
  2105 	$fetchpriority_val = preg_match( '/ fetchpriority=["\']([A-Za-z]+)["\']/', $image, $match_fetchpriority ) ? $match_fetchpriority[1] : null;
  1980 	$decoding_val      = preg_match( '/ decoding=["\']([A-Za-z]+)["\']/', $image, $match_decoding ) ? $match_decoding[1] : null;
  2106 	$decoding_val      = preg_match( '/ decoding=["\']([A-Za-z]+)["\']/', $image, $match_decoding ) ? $match_decoding[1] : null;
  1985 	 * that are ineligible for being lazy-loaded are considered.
  2111 	 * that are ineligible for being lazy-loaded are considered.
  1986 	 */
  2112 	 */
  1987 	$optimization_attrs = wp_get_loading_optimization_attributes(
  2113 	$optimization_attrs = wp_get_loading_optimization_attributes(
  1988 		'img',
  2114 		'img',
  1989 		array(
  2115 		array(
       
  2116 			'src'           => $src,
  1990 			'width'         => $width,
  2117 			'width'         => $width,
  1991 			'height'        => $height,
  2118 			'height'        => $height,
  1992 			'loading'       => $loading_val,
  2119 			'loading'       => $loading_val,
  1993 			'fetchpriority' => $fetchpriority_val,
  2120 			'fetchpriority' => $fetchpriority_val,
  1994 			'decoding'      => $decoding_val,
  2121 			'decoding'      => $decoding_val,
  3222  *
  3349  *
  3223  * This implements the functionality of the Audio Shortcode for displaying
  3350  * This implements the functionality of the Audio Shortcode for displaying
  3224  * WordPress mp3s in a post.
  3351  * WordPress mp3s in a post.
  3225  *
  3352  *
  3226  * @since 3.6.0
  3353  * @since 3.6.0
       
  3354  * @since 6.8.0 Added the 'muted' attribute.
  3227  *
  3355  *
  3228  * @param array  $attr {
  3356  * @param array  $attr {
  3229  *     Attributes of the audio shortcode.
  3357  *     Attributes of the audio shortcode.
  3230  *
  3358  *
  3231  *     @type string $src      URL to the source of the audio file. Default empty.
  3359  *     @type string $src      URL to the source of the audio file. Default empty.
  3232  *     @type string $loop     The 'loop' attribute for the `<audio>` element. Default empty.
  3360  *     @type string $loop     The 'loop' attribute for the `<audio>` element. Default empty.
  3233  *     @type string $autoplay The 'autoplay' attribute for the `<audio>` element. Default empty.
  3361  *     @type string $autoplay The 'autoplay' attribute for the `<audio>` element. Default empty.
       
  3362  *     @type string $muted    The 'muted' attribute for the `<audio>` element. Default 'false'.
  3234  *     @type string $preload  The 'preload' attribute for the `<audio>` element. Default 'none'.
  3363  *     @type string $preload  The 'preload' attribute for the `<audio>` element. Default 'none'.
  3235  *     @type string $class    The 'class' attribute for the `<audio>` element. Default 'wp-audio-shortcode'.
  3364  *     @type string $class    The 'class' attribute for the `<audio>` element. Default 'wp-audio-shortcode'.
  3236  *     @type string $style    The 'style' attribute for the `<audio>` element. Default 'width: 100%;'.
  3365  *     @type string $style    The 'style' attribute for the `<audio>` element. Default 'width: 100%;'.
  3237  * }
  3366  * }
  3238  * @param string $content Shortcode content.
  3367  * @param string $content Shortcode content.
  3267 	$default_types = wp_get_audio_extensions();
  3396 	$default_types = wp_get_audio_extensions();
  3268 	$defaults_atts = array(
  3397 	$defaults_atts = array(
  3269 		'src'      => '',
  3398 		'src'      => '',
  3270 		'loop'     => '',
  3399 		'loop'     => '',
  3271 		'autoplay' => '',
  3400 		'autoplay' => '',
       
  3401 		'muted'    => 'false',
  3272 		'preload'  => 'none',
  3402 		'preload'  => 'none',
  3273 		'class'    => 'wp-audio-shortcode',
  3403 		'class'    => 'wp-audio-shortcode',
  3274 		'style'    => 'width: 100%;',
  3404 		'style'    => 'width: 100%;',
  3275 	);
  3405 	);
  3276 	foreach ( $default_types as $type ) {
  3406 	foreach ( $default_types as $type ) {
  3346 	$html_atts = array(
  3476 	$html_atts = array(
  3347 		'class'    => $atts['class'],
  3477 		'class'    => $atts['class'],
  3348 		'id'       => sprintf( 'audio-%d-%d', $post_id, $instance ),
  3478 		'id'       => sprintf( 'audio-%d-%d', $post_id, $instance ),
  3349 		'loop'     => wp_validate_boolean( $atts['loop'] ),
  3479 		'loop'     => wp_validate_boolean( $atts['loop'] ),
  3350 		'autoplay' => wp_validate_boolean( $atts['autoplay'] ),
  3480 		'autoplay' => wp_validate_boolean( $atts['autoplay'] ),
       
  3481 		'muted'    => wp_validate_boolean( $atts['muted'] ),
  3351 		'preload'  => $atts['preload'],
  3482 		'preload'  => $atts['preload'],
  3352 		'style'    => $atts['style'],
  3483 		'style'    => $atts['style'],
  3353 	);
  3484 	);
  3354 
  3485 
  3355 	// These ones should just be omitted altogether if they are blank.
  3486 	// These ones should just be omitted altogether if they are blank.
  3356 	foreach ( array( 'loop', 'autoplay', 'preload' ) as $a ) {
  3487 	foreach ( array( 'loop', 'autoplay', 'preload', 'muted' ) as $a ) {
  3357 		if ( empty( $html_atts[ $a ] ) ) {
  3488 		if ( empty( $html_atts[ $a ] ) ) {
  3358 			unset( $html_atts[ $a ] );
  3489 			unset( $html_atts[ $a ] );
  3359 		}
  3490 		}
  3360 	}
  3491 	}
  3361 
  3492 
  3362 	$attr_strings = array();
  3493 	$attr_strings = array();
  3363 
  3494 
  3364 	foreach ( $html_atts as $k => $v ) {
  3495 	foreach ( $html_atts as $attribute_name => $attribute_value ) {
  3365 		$attr_strings[] = $k . '="' . esc_attr( $v ) . '"';
  3496 		if ( in_array( $attribute_name, array( 'loop', 'autoplay', 'muted' ), true ) && true === $attribute_value ) {
       
  3497 			// Add boolean attributes without a value.
       
  3498 			$attr_strings[] = esc_attr( $attribute_name );
       
  3499 		} elseif ( 'preload' === $attribute_name && ! empty( $attribute_value ) ) {
       
  3500 			// Handle the preload attribute with specific allowed values.
       
  3501 			$allowed_preload_values = array( 'none', 'metadata', 'auto' );
       
  3502 			if ( in_array( $attribute_value, $allowed_preload_values, true ) ) {
       
  3503 				$attr_strings[] = sprintf( '%s="%s"', esc_attr( $attribute_name ), esc_attr( $attribute_value ) );
       
  3504 			}
       
  3505 		} else {
       
  3506 			// For other attributes, include the value.
       
  3507 			$attr_strings[] = sprintf( '%s="%s"', esc_attr( $attribute_name ), esc_attr( $attribute_value ) );
       
  3508 		}
  3366 	}
  3509 	}
  3367 
  3510 
  3368 	$html = '';
  3511 	$html = '';
  3369 
  3512 
  3370 	if ( 'mediaelement' === $library && 1 === $instance ) {
  3513 	if ( 'mediaelement' === $library && 1 === $instance ) {
  3632 			unset( $html_atts[ $a ] );
  3775 			unset( $html_atts[ $a ] );
  3633 		}
  3776 		}
  3634 	}
  3777 	}
  3635 
  3778 
  3636 	$attr_strings = array();
  3779 	$attr_strings = array();
  3637 	foreach ( $html_atts as $k => $v ) {
  3780 	foreach ( $html_atts as $attribute_name => $attribute_value ) {
  3638 		$attr_strings[] = $k . '="' . esc_attr( $v ) . '"';
  3781 		if ( in_array( $attribute_name, array( 'loop', 'autoplay', 'muted' ), true ) && true === $attribute_value ) {
       
  3782 			// Add boolean attributes without their value for true.
       
  3783 			$attr_strings[] = esc_attr( $attribute_name );
       
  3784 		} elseif ( 'preload' === $attribute_name && ! empty( $attribute_value ) ) {
       
  3785 			// Handle the preload attribute with specific allowed values.
       
  3786 			$allowed_preload_values = array( 'none', 'metadata', 'auto' );
       
  3787 			if ( in_array( $attribute_value, $allowed_preload_values, true ) ) {
       
  3788 				$attr_strings[] = sprintf( '%s="%s"', esc_attr( $attribute_name ), esc_attr( $attribute_value ) );
       
  3789 			}
       
  3790 		} elseif ( ! empty( $attribute_value ) ) {
       
  3791 			// For non-boolean attributes, add them with their value.
       
  3792 			$attr_strings[] = sprintf( '%s="%s"', esc_attr( $attribute_name ), esc_attr( $attribute_value ) );
       
  3793 		}
  3639 	}
  3794 	}
  3640 
  3795 
  3641 	$html = '';
  3796 	$html = '';
  3642 
  3797 
  3643 	if ( 'mediaelement' === $library && 1 === $instance ) {
  3798 	if ( 'mediaelement' === $library && 1 === $instance ) {
  4062 		}
  4217 		}
  4063 	}
  4218 	}
  4064 
  4219 
  4065 	// Check and set the output mime type mapped to the input type.
  4220 	// Check and set the output mime type mapped to the input type.
  4066 	if ( isset( $args['mime_type'] ) ) {
  4221 	if ( isset( $args['mime_type'] ) ) {
  4067 		/** This filter is documented in wp-includes/class-wp-image-editor.php */
  4222 		$output_format = wp_get_image_editor_output_format( $path, $args['mime_type'] );
  4068 		$output_format = apply_filters( 'image_editor_output_format', array(), $path, $args['mime_type'] );
       
  4069 		if ( isset( $output_format[ $args['mime_type'] ] ) ) {
  4223 		if ( isset( $output_format[ $args['mime_type'] ] ) ) {
  4070 			$args['output_mime_type'] = $output_format[ $args['mime_type'] ];
  4224 			$args['output_mime_type'] = $output_format[ $args['mime_type'] ];
  4071 		}
  4225 		}
  4072 	}
  4226 	}
  4073 
  4227 
  4122 	 *
  4276 	 *
  4123 	 * @param string[] $image_editors Array of available image editor class names. Defaults are
  4277 	 * @param string[] $image_editors Array of available image editor class names. Defaults are
  4124 	 *                                'WP_Image_Editor_Imagick', 'WP_Image_Editor_GD'.
  4278 	 *                                'WP_Image_Editor_Imagick', 'WP_Image_Editor_GD'.
  4125 	 */
  4279 	 */
  4126 	$implementations = apply_filters( 'wp_image_editors', array( 'WP_Image_Editor_Imagick', 'WP_Image_Editor_GD' ) );
  4280 	$implementations = apply_filters( 'wp_image_editors', array( 'WP_Image_Editor_Imagick', 'WP_Image_Editor_GD' ) );
  4127 	$supports_input  = false;
  4281 
       
  4282 	$editors = wp_cache_get( 'wp_image_editor_choose', 'image_editor' );
       
  4283 
       
  4284 	if ( ! is_array( $editors ) ) {
       
  4285 		$editors = array();
       
  4286 	}
       
  4287 
       
  4288 	// Cache the chosen editor implementation based on specific args and available implementations.
       
  4289 	$cache_key = md5( serialize( array( $args, $implementations ) ) );
       
  4290 
       
  4291 	if ( isset( $editors[ $cache_key ] ) ) {
       
  4292 		return $editors[ $cache_key ];
       
  4293 	}
       
  4294 
       
  4295 	// Assume no support until a capable implementation is identified.
       
  4296 	$editor = false;
  4128 
  4297 
  4129 	foreach ( $implementations as $implementation ) {
  4298 	foreach ( $implementations as $implementation ) {
  4130 		if ( ! call_user_func( array( $implementation, 'test' ), $args ) ) {
  4299 		if ( ! call_user_func( array( $implementation, 'test' ), $args ) ) {
  4131 			continue;
  4300 			continue;
  4132 		}
  4301 		}
  4156 		) {
  4325 		) {
  4157 			/*
  4326 			/*
  4158 			 * This implementation supports the input type but not the output type.
  4327 			 * This implementation supports the input type but not the output type.
  4159 			 * Keep looking to see if we can find an implementation that supports both.
  4328 			 * Keep looking to see if we can find an implementation that supports both.
  4160 			 */
  4329 			 */
  4161 			$supports_input = $implementation;
  4330 			$editor = $implementation;
  4162 			continue;
  4331 			continue;
  4163 		}
  4332 		}
  4164 
  4333 
  4165 		// Favor the implementation that supports both input and output mime types.
  4334 		// Favor the implementation that supports both input and output mime types.
  4166 		return $implementation;
  4335 		$editor = $implementation;
  4167 	}
  4336 		break;
  4168 
  4337 	}
  4169 	return $supports_input;
  4338 
       
  4339 	$editors[ $cache_key ] = $editor;
       
  4340 
       
  4341 	wp_cache_set( 'wp_image_editor_choose', $editors, 'image_editor', DAY_IN_SECONDS );
       
  4342 
       
  4343 	return $editor;
  4170 }
  4344 }
  4171 
  4345 
  4172 /**
  4346 /**
  4173  * Prints default Plupload arguments.
  4347  * Prints default Plupload arguments.
  4174  *
  4348  *
  4220 	}
  4394 	}
  4221 
  4395 
  4222 	// Check if AVIF images can be edited.
  4396 	// Check if AVIF images can be edited.
  4223 	if ( ! wp_image_editor_supports( array( 'mime_type' => 'image/avif' ) ) ) {
  4397 	if ( ! wp_image_editor_supports( array( 'mime_type' => 'image/avif' ) ) ) {
  4224 		$defaults['avif_upload_error'] = true;
  4398 		$defaults['avif_upload_error'] = true;
       
  4399 	}
       
  4400 
       
  4401 	// Check if HEIC images can be edited.
       
  4402 	if ( ! wp_image_editor_supports( array( 'mime_type' => 'image/heic' ) ) ) {
       
  4403 		$defaults['heic_upload_error'] = true;
  4225 	}
  4404 	}
  4226 
  4405 
  4227 	/**
  4406 	/**
  4228 	 * Filters the Plupload default settings.
  4407 	 * Filters the Plupload default settings.
  4229 	 *
  4408 	 *
  4313  *     @type string $uploadedToLink        URL to the edit page of the parent post of the attachment.
  4492  *     @type string $uploadedToLink        URL to the edit page of the parent post of the attachment.
  4314  *     @type string $uploadedToTitle       Post title of the parent of the attachment.
  4493  *     @type string $uploadedToTitle       Post title of the parent of the attachment.
  4315  *     @type string $url                   Direct URL to the attachment file (from wp-content).
  4494  *     @type string $url                   Direct URL to the attachment file (from wp-content).
  4316  *     @type int    $width                 If the attachment is an image, represents the width of the image in pixels.
  4495  *     @type int    $width                 If the attachment is an image, represents the width of the image in pixels.
  4317  * }
  4496  * }
  4318  *
       
  4319  */
  4497  */
  4320 function wp_prepare_attachment_for_js( $attachment ) {
  4498 function wp_prepare_attachment_for_js( $attachment ) {
  4321 	$attachment = get_post( $attachment );
  4499 	$attachment = get_post( $attachment );
  4322 
  4500 
  4323 	if ( ! $attachment ) {
  4501 	if ( ! $attachment ) {
  5309  * @return int The found post ID, or 0 on failure.
  5487  * @return int The found post ID, or 0 on failure.
  5310  */
  5488  */
  5311 function attachment_url_to_postid( $url ) {
  5489 function attachment_url_to_postid( $url ) {
  5312 	global $wpdb;
  5490 	global $wpdb;
  5313 
  5491 
       
  5492 	/**
       
  5493 	 * Filters the attachment ID to allow short-circuit the function.
       
  5494 	 *
       
  5495 	 * Allows plugins to short-circuit attachment ID lookups. Plugins making
       
  5496 	 * use of this function should return:
       
  5497 	 *
       
  5498 	 * - 0 (integer) to indicate the attachment is not found,
       
  5499 	 * - attachment ID (integer) to indicate the attachment ID found,
       
  5500 	 * - null to indicate WordPress should proceed with the lookup.
       
  5501 	 *
       
  5502 	 * Warning: The post ID may be null or zero, both of which cast to a
       
  5503 	 * boolean false. For information about casting to booleans see the
       
  5504 	 * {@link https://www.php.net/manual/en/language.types.boolean.php PHP documentation}.
       
  5505 	 * Use the === operator for testing the post ID when developing filters using
       
  5506 	 * this hook.
       
  5507 	 *
       
  5508 	 * @since 6.7.0
       
  5509 	 *
       
  5510 	 * @param int|null $post_id The result of the post ID lookup. Null to indicate
       
  5511 	 *                          no lookup has been attempted. Default null.
       
  5512 	 * @param string   $url     The URL being looked up.
       
  5513 	 */
       
  5514 	$post_id = apply_filters( 'pre_attachment_url_to_postid', null, $url );
       
  5515 	if ( null !== $post_id ) {
       
  5516 		return (int) $post_id;
       
  5517 	}
       
  5518 
  5314 	$dir  = wp_get_upload_dir();
  5519 	$dir  = wp_get_upload_dir();
  5315 	$path = $url;
  5520 	$path = $url;
  5316 
  5521 
  5317 	$site_url   = parse_url( $dir['url'] );
  5522 	$site_url   = parse_url( $dir['url'] );
  5318 	$image_path = parse_url( $path );
  5523 	$image_path = parse_url( $path );
  5481 
  5686 
  5482 /**
  5687 /**
  5483  * Callback to enable showing of the user error when uploading .heic images.
  5688  * Callback to enable showing of the user error when uploading .heic images.
  5484  *
  5689  *
  5485  * @since 5.5.0
  5690  * @since 5.5.0
       
  5691  * @since 6.7.0 The default behavior is to enable heic uploads as long as the server
       
  5692  *              supports the format. The uploads are converted to JPEG's by default.
  5486  *
  5693  *
  5487  * @param array[] $plupload_settings The settings for Plupload.js.
  5694  * @param array[] $plupload_settings The settings for Plupload.js.
  5488  * @return array[] Modified settings for Plupload.js.
  5695  * @return array[] Modified settings for Plupload.js.
  5489  */
  5696  */
  5490 function wp_show_heic_upload_error( $plupload_settings ) {
  5697 function wp_show_heic_upload_error( $plupload_settings ) {
  5491 	$plupload_settings['heic_upload_error'] = true;
  5698 	// Check if HEIC images can be edited.
       
  5699 	if ( ! wp_image_editor_supports( array( 'mime_type' => 'image/heic' ) ) ) {
       
  5700 		$plupload_init['heic_upload_error'] = true;
       
  5701 	}
  5492 	return $plupload_settings;
  5702 	return $plupload_settings;
  5493 }
  5703 }
  5494 
  5704 
  5495 /**
  5705 /**
  5496  * Allows PHP's getimagesize() to be debuggable when necessary.
  5706  * Allows PHP's getimagesize() to be debuggable when necessary.
  5503  * @param array  $image_info Optional. Extended image information (passed by reference).
  5713  * @param array  $image_info Optional. Extended image information (passed by reference).
  5504  * @return array|false Array of image information or false on failure.
  5714  * @return array|false Array of image information or false on failure.
  5505  */
  5715  */
  5506 function wp_getimagesize( $filename, ?array &$image_info = null ) {
  5716 function wp_getimagesize( $filename, ?array &$image_info = null ) {
  5507 	// Don't silence errors when in debug mode, unless running unit tests.
  5717 	// Don't silence errors when in debug mode, unless running unit tests.
  5508 	if ( defined( 'WP_DEBUG' ) && WP_DEBUG
  5718 	if ( defined( 'WP_DEBUG' ) && WP_DEBUG && ! defined( 'WP_RUN_CORE_TESTS' ) ) {
  5509 		&& ! defined( 'WP_RUN_CORE_TESTS' )
       
  5510 	) {
       
  5511 		if ( 2 === func_num_args() ) {
  5719 		if ( 2 === func_num_args() ) {
  5512 			$info = getimagesize( $filename, $image_info );
  5720 			$info = getimagesize( $filename, $image_info );
  5513 		} else {
  5721 		} else {
  5514 			$info = getimagesize( $filename );
  5722 			$info = getimagesize( $filename );
  5515 		}
  5723 		}
  5536 		! ( empty( $info[0] ) && empty( $info[1] ) )
  5744 		! ( empty( $info[0] ) && empty( $info[1] ) )
  5537 	) {
  5745 	) {
  5538 		return $info;
  5746 		return $info;
  5539 	}
  5747 	}
  5540 
  5748 
       
  5749 	$image_mime_type = wp_get_image_mime( $filename );
       
  5750 
       
  5751 	// Not an image?
       
  5752 	if ( false === $image_mime_type ) {
       
  5753 		return false;
       
  5754 	}
       
  5755 
  5541 	/*
  5756 	/*
  5542 	 * For PHP versions that don't support WebP images,
  5757 	 * For PHP versions that don't support WebP images,
  5543 	 * extract the image size info from the file headers.
  5758 	 * extract the image size info from the file headers.
  5544 	 */
  5759 	 */
  5545 	if ( 'image/webp' === wp_get_image_mime( $filename ) ) {
  5760 	if ( 'image/webp' === $image_mime_type ) {
  5546 		$webp_info = wp_get_webp_info( $filename );
  5761 		$webp_info = wp_get_webp_info( $filename );
  5547 		$width     = $webp_info['width'];
  5762 		$width     = $webp_info['width'];
  5548 		$height    = $webp_info['height'];
  5763 		$height    = $webp_info['height'];
  5549 
  5764 
  5550 		// Mimic the native return format.
  5765 		// Mimic the native return format.
  5562 			);
  5777 			);
  5563 		}
  5778 		}
  5564 	}
  5779 	}
  5565 
  5780 
  5566 	// For PHP versions that don't support AVIF images, extract the image size info from the file headers.
  5781 	// For PHP versions that don't support AVIF images, extract the image size info from the file headers.
  5567 	if ( 'image/avif' === wp_get_image_mime( $filename ) ) {
  5782 	if ( 'image/avif' === $image_mime_type ) {
  5568 		$avif_info = wp_get_avif_info( $filename );
  5783 		$avif_info = wp_get_avif_info( $filename );
  5569 
  5784 
  5570 		$width  = $avif_info['width'];
  5785 		$width  = $avif_info['width'];
  5571 		$height = $avif_info['height'];
  5786 		$height = $avif_info['height'];
  5572 
  5787 
  5580 					'width="%d" height="%d"',
  5795 					'width="%d" height="%d"',
  5581 					$width,
  5796 					$width,
  5582 					$height
  5797 					$height
  5583 				),
  5798 				),
  5584 				'mime' => 'image/avif',
  5799 				'mime' => 'image/avif',
       
  5800 			);
       
  5801 		}
       
  5802 	}
       
  5803 
       
  5804 	// For PHP versions that don't support HEIC images, extract the size info using Imagick when available.
       
  5805 	if ( wp_is_heic_image_mime_type( $image_mime_type ) ) {
       
  5806 		$editor = wp_get_image_editor( $filename );
       
  5807 
       
  5808 		if ( is_wp_error( $editor ) ) {
       
  5809 			return false;
       
  5810 		}
       
  5811 
       
  5812 		// If the editor for HEICs is Imagick, use it to get the image size.
       
  5813 		if ( $editor instanceof WP_Image_Editor_Imagick ) {
       
  5814 			$size = $editor->get_size();
       
  5815 			return array(
       
  5816 				$size['width'],
       
  5817 				$size['height'],
       
  5818 				IMAGETYPE_HEIC,
       
  5819 				sprintf(
       
  5820 					'width="%d" height="%d"',
       
  5821 					$size['width'],
       
  5822 					$size['height']
       
  5823 				),
       
  5824 				'mime' => 'image/heic',
  5585 			);
  5825 			);
  5586 		}
  5826 		}
  5587 	}
  5827 	}
  5588 
  5828 
  5589 	// The image could not be parsed.
  5829 	// The image could not be parsed.
  6067 		$high_priority_element = $value;
  6307 		$high_priority_element = $value;
  6068 	}
  6308 	}
  6069 
  6309 
  6070 	return $high_priority_element;
  6310 	return $high_priority_element;
  6071 }
  6311 }
       
  6312 
       
  6313 /**
       
  6314  * Determines the output format for the image editor.
       
  6315  *
       
  6316  * @since 6.7.0
       
  6317  * @access private
       
  6318  *
       
  6319  * @param string $filename  Path to the image.
       
  6320  * @param string $mime_type The source image mime type.
       
  6321  * @return string[] An array of mime type mappings.
       
  6322  */
       
  6323 function wp_get_image_editor_output_format( $filename, $mime_type ) {
       
  6324 	$output_format = array(
       
  6325 		'image/heic'          => 'image/jpeg',
       
  6326 		'image/heif'          => 'image/jpeg',
       
  6327 		'image/heic-sequence' => 'image/jpeg',
       
  6328 		'image/heif-sequence' => 'image/jpeg',
       
  6329 	);
       
  6330 
       
  6331 	/**
       
  6332 	 * Filters the image editor output format mapping.
       
  6333 	 *
       
  6334 	 * Enables filtering the mime type used to save images. By default HEIC/HEIF images
       
  6335 	 * are converted to JPEGs.
       
  6336 	 *
       
  6337 	 * @see WP_Image_Editor::get_output_format()
       
  6338 	 *
       
  6339 	 * @since 5.8.0
       
  6340 	 * @since 6.7.0 The default was changed from an empty array to an array
       
  6341 	 *              containing the HEIC/HEIF images mime types.
       
  6342 	 *
       
  6343 	 * @param string[] $output_format {
       
  6344 	 *     An array of mime type mappings. Maps a source mime type to a new
       
  6345 	 *     destination mime type. By default maps HEIC/HEIF input to JPEG output.
       
  6346 	 *
       
  6347 	 *     @type string ...$0 The new mime type.
       
  6348 	 * }
       
  6349 	 * @param string $filename  Path to the image.
       
  6350 	 * @param string $mime_type The source image mime type.
       
  6351 	 */
       
  6352 	return apply_filters( 'image_editor_output_format', $output_format, $filename, $mime_type );
       
  6353 }