Ticket #36982: media-srcset-sizes.2.patch
File media-srcset-sizes.2.patch, 13.3 KB (added by , 7 years ago) |
---|
-
src/wp-includes/media.php
893 893 894 894 if ( is_array( $image_meta ) ) { 895 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 );896 $srcset = wp_calculate_image_srcset( $size_array, $src, $image_meta, $attachment_id, $attr ); 897 $sizes = wp_calculate_image_sizes( $size_array, $src, $image_meta, $attachment_id, $attr ); 898 898 899 899 if ( $srcset && ( $sizes || ! empty( $attr['sizes'] ) ) ) { 900 900 $attr['srcset'] = $srcset; … … 1010 1010 * width and height values in pixels (in that order). Default 'medium'. 1011 1011 * @param array $image_meta Optional. The image meta data as returned by 'wp_get_attachment_metadata()'. 1012 1012 * Default null. 1013 * @param array $image_attr Optional. An array of image attributes to be passed to 'wp_calculate_image_srcset()'. 1013 1014 * @return string|bool A 'srcset' value string or false. 1014 1015 */ 1015 function wp_get_attachment_image_srcset( $attachment_id, $size = 'medium', $image_meta = null ) {1016 function wp_get_attachment_image_srcset( $attachment_id, $size = 'medium', $image_meta = null, $image_attr = array() ) { 1016 1017 if ( ! $image = wp_get_attachment_image_src( $attachment_id, $size ) ) { 1017 1018 return false; 1018 1019 } … … 1027 1028 absint( $image[2] ) 1028 1029 ); 1029 1030 1030 return wp_calculate_image_srcset( $size_array, $image_src, $image_meta, $attachment_id );1031 return wp_calculate_image_srcset( $size_array, $image_src, $image_meta, $attachment_id, $image_attr ); 1031 1032 } 1032 1033 1033 1034 /** … … 1039 1040 * @param string $image_src The 'src' of the image. 1040 1041 * @param array $image_meta The image meta data as returned by 'wp_get_attachment_metadata()'. 1041 1042 * @param int $attachment_id Optional. The image attachment ID to pass to the filter. Default 0. 1043 * @param array $image_attr Optional. Image attributes. 1042 1044 * @return string|bool The 'srcset' attribute value. False on error or when only one source exists. 1043 1045 */ 1044 function wp_calculate_image_srcset( $size_array, $image_src, $image_meta, $attachment_id = 0 ) {1046 function wp_calculate_image_srcset( $size_array, $image_src, $image_meta, $attachment_id = 0, $image_attr = array() ) { 1045 1047 /** 1046 1048 * Let plugins pre-filter the image meta to be able to fix inconsistencies in the stored data. 1047 1049 * … … 1199 1201 * @param string $image_src The 'src' of the image. 1200 1202 * @param array $image_meta The image meta data as returned by 'wp_get_attachment_metadata()'. 1201 1203 * @param int $attachment_id Image attachment ID or 0. 1204 * @param array $image_attr Image attributes. 1202 1205 */ 1203 $sources = apply_filters( 'wp_calculate_image_srcset', $sources, $size_array, $image_src, $image_meta, $attachment_id );1206 $sources = apply_filters( 'wp_calculate_image_srcset', $sources, $size_array, $image_src, $image_meta, $attachment_id, $image_attr ); 1204 1207 1205 1208 // Only return a 'srcset' value if there is more than one source. 1206 1209 if ( ! $src_matched || count( $sources ) < 2 ) { … … 1228 1231 * and height values in pixels (in that order). Default 'medium'. 1229 1232 * @param array $image_meta Optional. The image meta data as returned by 'wp_get_attachment_metadata()'. 1230 1233 * Default null. 1234 * @param array $image_attr Optional. An array of image attributes to be passed to 'wp_calculate_image_sizes()'. 1231 1235 * @return string|bool A valid source size value for use in a 'sizes' attribute or false. 1232 1236 */ 1233 function wp_get_attachment_image_sizes( $attachment_id, $size = 'medium', $image_meta = null ) {1237 function wp_get_attachment_image_sizes( $attachment_id, $size = 'medium', $image_meta = null, $image_attr = array() ) { 1234 1238 if ( ! $image = wp_get_attachment_image_src( $attachment_id, $size ) ) { 1235 1239 return false; 1236 1240 } … … 1245 1249 absint( $image[2] ) 1246 1250 ); 1247 1251 1248 return wp_calculate_image_sizes( $size_array, $image_src, $image_meta, $attachment_id );1252 return wp_calculate_image_sizes( $size_array, $image_src, $image_meta, $attachment_id, $image_attr ); 1249 1253 } 1250 1254 1251 1255 /** … … 1260 1264 * Default null. 1261 1265 * @param int $attachment_id Optional. Image attachment ID. Either `$image_meta` or `$attachment_id` 1262 1266 * is needed when using the image size name as argument for `$size`. Default 0. 1267 * @param array $image_attr Optional. Image attributes. 1263 1268 * @return string|bool A valid source size value for use in a 'sizes' attribute or false. 1264 1269 */ 1265 function wp_calculate_image_sizes( $size, $image_src = null, $image_meta = null, $attachment_id = 0 ) {1270 function wp_calculate_image_sizes( $size, $image_src = null, $image_meta = null, $attachment_id = 0, $image_attr = array() ) { 1266 1271 $width = 0; 1267 1272 1268 1273 if ( is_array( $size ) ) { … … 1297 1302 * in pixels (in that order). 1298 1303 * @param string|null $image_src The URL to the image file or null. 1299 1304 * @param array|null $image_meta The image meta data as returned by wp_get_attachment_metadata() or null. 1305 * @param array $image_attr Image attributes. 1300 1306 * @param int $attachment_id Image attachment ID of the original image or 0. 1301 1307 */ 1302 return apply_filters( 'wp_calculate_image_sizes', $sizes, $size, $image_src, $image_meta, $attachment_id );1308 return apply_filters( 'wp_calculate_image_sizes', $sizes, $size, $image_src, $image_meta, $attachment_id, $image_attr ); 1303 1309 } 1304 1310 1305 1311 /** … … 1414 1420 } 1415 1421 1416 1422 $size_array = array( $width, $height ); 1417 $srcset = wp_calculate_image_srcset( $size_array, $image_src, $image_meta, $attachment_id ); 1423 $image_attr = preg_match_all( '/\s([\w-]+)([=\s]([\'\"])((?!\3).+?[^\\\])\3)?/', $image, $match_attr ) ? array_combine( array_map( 'esc_attr', $match_attr[1] ), array_map( 'esc_attr', $match_attr[4] ) ) : array(); 1424 $srcset = wp_calculate_image_srcset( $size_array, $image_src, $image_meta, $attachment_id, $image_attr ); 1418 1425 1419 1426 if ( $srcset ) { 1420 1427 // Check if there is already a 'sizes' attribute. … … 1421 1428 $sizes = strpos( $image, ' sizes=' ); 1422 1429 1423 1430 if ( ! $sizes ) { 1424 $sizes = wp_calculate_image_sizes( $size_array, $image_src, $image_meta, $attachment_id );1431 $sizes = wp_calculate_image_sizes( $size_array, $image_src, $image_meta, $attachment_id, $image_attr ); 1425 1432 } 1426 1433 } 1427 1434 -
tests/phpunit/tests/media.php
2062 2062 $attachment_id = wp_insert_attachment( $data, '', 0 ); 2063 2063 $this->assertSame( 0, $attachment_id ); 2064 2064 } 2065 2066 /** 2067 * @ticket 36982 2068 */ 2069 public function test_filter_image_srcset_and_sizes_by_image_attributes() { 2070 2071 $image_meta = wp_get_attachment_metadata( self::$large_id ); 2072 $class_attribute_string = 'test-class-string test-image-full'; 2073 2074 // Add a filter to remove srcset and sizes from the generated image. 2075 add_filter( 'wp_calculate_image_srcset', '__return_false' ); 2076 add_filter( 'wp_calculate_image_sizes', '__return_false' ); 2077 2078 $image_with_class_attribute_no_srcset_sizes = wp_get_attachment_image( self::$large_id, 'full', false, array( 'class' => $class_attribute_string, 'alt' => 'Full size test image' ) ); 2079 $image_without_class_attribute_no_srcset_sizes = wp_get_attachment_image( self::$large_id, 'full', false, array( 'class' => '', 'alt' => 'Full size test image' ) ); 2080 2081 // Remove the filter to restore srcset and sizes from the generated image. 2082 remove_filter( 'wp_calculate_image_srcset', '__return_false' ); 2083 remove_filter( 'wp_calculate_image_sizes', '__return_false' ); 2084 2085 $default_image_without_class_attribute = wp_get_attachment_image( self::$large_id, 'full', false, array( 'class' => '', 'alt' => 'Full size test image' ) ); 2086 $default_srcset_string_without_class_attribute = wp_get_attachment_image_srcset( self::$large_id, 'full', false, array( 'class' => '', 'alt' => 'Full size test image' ) ); 2087 $default_sizes_string_without_class_attribute = wp_get_attachment_image_sizes( self::$large_id, 'full', false, array( 'class' => '', 'alt' => 'Full size test image' ) ); 2088 2089 // Filter the srcset and sizes values. 2090 add_filter( 'wp_calculate_image_srcset', array( $this, '_filter_36982_srcset' ), 10, 6 ); 2091 add_filter( 'wp_calculate_image_sizes', array( $this, '_filter_36982_sizes' ), 10, 6 ); 2092 2093 // Generate an image with srcset and sizes values that should match the filtered image. 2094 $uploads_dir_url = 'http://' . WP_TESTS_DOMAIN . '/wp-content/uploads/'; 2095 $image_file_date_dir = preg_replace( '/(\d{4}\/\d{2}\/).+/', '$1', $image_meta['file'] ); 2096 2097 // Set sources that will match the filtered values. 2098 $expected_sources = array( 2099 $image_meta['width'] => array( 2100 'url' => $uploads_dir_url . $image_meta['file'], 2101 'descriptor' => 'w', 2102 'value' => $image_meta['width'], 2103 'width' => $image_meta['width'], 2104 'height' => $image_meta['height'], 2105 ), 2106 ); 2107 2108 foreach( $image_meta['sizes'] as $size ) { 2109 $expected_sources[ $size['width'] ] = array( 2110 'url' => $uploads_dir_url . $image_file_date_dir . $size['file'], 2111 'descriptor' => 'w', 2112 'value' => $size['width'], 2113 'width' => $size['width'], 2114 'height' => $size['height'], 2115 ); 2116 } 2117 2118 $expected_sources = array_slice( array_filter( array_map( function( $source, $image_meta ) { 2119 if ( ! wp_image_matches_ratio( $image_meta['width'], $image_meta['height'], $source['width'], $source['height'] ) || $source['value'] > apply_filters( 'max_srcset_image_width', 1600, array( $image_meta['width'], $image_meta['height'] ) ) ) { 2120 return false; 2121 } 2122 return $source['url'] . ' ' . $source['value'] . $source['descriptor']; 2123 }, $expected_sources, array_fill( 0, count( $expected_sources ), $image_meta ) ) ), 2 ); 2124 2125 // Set a sizes sting value that will match the arbitrary value set in the filter. 2126 $expected_sizes_string = sprintf( '(max-width: %1$dpx) 100vw, %1$dpx', 9999 ); 2127 2128 $expected_image = '<img width="' . $image_meta['width'] . '" height="' . $image_meta['height'] . '" src="' . $uploads_dir_url . $image_meta['file'] . '" class="' . $class_attribute_string . '" alt="Full size test image" srcset="' . implode( ', ', $expected_sources ) . '" sizes="' . $expected_sizes_string . '" />'; 2129 2130 // Images without a class attribute that will match the test filter. Should match the default image with unfiltered srcset and sizes values. 2131 $this->assertSame( $default_image_without_class_attribute, wp_get_attachment_image( self::$large_id, 'full', false, array( 'class' => '', 'alt' => 'Full size test image' ) ) ); 2132 $this->assertSame( $default_image_without_class_attribute, wp_image_add_srcset_and_sizes( $image_without_class_attribute_no_srcset_sizes, $image_meta, self::$large_id ) ); 2133 2134 // Images with a class attribute that will match the test filter. Should match the expected image with filtered srcset and sizes values. 2135 $this->assertSame( $expected_image, wp_image_add_srcset_and_sizes( $image_with_class_attribute_no_srcset_sizes, $image_meta, self::$large_id ) ); 2136 $this->assertSame( $expected_image, wp_get_attachment_image( self::$large_id, 'full', false, array( 'class' => $class_attribute_string, 'alt' => 'Full size test image' ) ) ); 2137 2138 // Srcset and sizes strings with class attribute string. Should match the filtered string. 2139 $this->assertSame( implode( ', ', $expected_sources ), wp_get_attachment_image_srcset( self::$large_id, 'full', false, array( 'class' => $class_attribute_string, 'alt' => 'Full size test image' ) ) ); 2140 $this->assertSame( $expected_sizes_string, wp_get_attachment_image_sizes( self::$large_id, 'full', false, array( 'class' => $class_attribute_string, 'alt' => 'Full size test image' ) ) ); 2141 2142 // Srcset and sizes strings without class attribute string. Should match the unfiltered default string. 2143 $this->assertSame( $default_srcset_string_without_class_attribute, wp_get_attachment_image_srcset( self::$large_id, 'full', false, array( 'class' => '', 'alt' => 'Full size test image' ) ) ); 2144 $this->assertSame( $default_sizes_string_without_class_attribute, wp_get_attachment_image_sizes( self::$large_id, 'full', false, array( 'class' => '', 'alt' => 'Full size test image' ) ) ); 2145 2146 2147 } 2148 2149 public function _filter_36982_srcset( $sources, $size_array, $image_src, $image_meta, $attachment_id, $image_attr ) { 2150 2151 if ( empty( $image_attr ) ) { 2152 return $sources; 2153 } 2154 2155 if ( empty( $image_attr['class'] ) ) { 2156 return $sources; 2157 } 2158 2159 $class_array = explode( ' ', $image_attr['class'] ); 2160 2161 if ( in_array( 'test-image-full', $class_array, true ) ) { 2162 return array_slice( $sources, 2 ); 2163 } 2164 2165 return $sources; 2166 } 2167 public function _filter_36982_sizes( $sizes, $size_array, $image_src, $image_meta, $attachment_id, $image_attr ) { 2168 2169 if ( empty( $image_attr ) ) { 2170 return $sizes; 2171 } 2172 2173 if ( empty( $image_attr['class'] ) ) { 2174 return $sizes; 2175 } 2176 2177 $class_array = explode( ' ', $image_attr['class'] ); 2178 2179 if ( in_array( 'test-image-full', $class_array, true ) ) { 2180 return sprintf( '(max-width: %1$dpx) 100vw, %1$dpx', 9999 ); 2181 } 2182 2183 return $sizes; 2184 } 2065 2185 } 2066 2186 2067 2187 /**