Make WordPress Core


Ignore:
Timestamp:
10/28/2015 05:40:04 AM (9 years ago)
Author:
azaozz
Message:

Responsive images:

  • Introduce wp_calculate_image_srcset() that replaces wp_get_attachment_image_srcset_array() and is used as lower level function for retrieving the srcset data as array.
  • Use the new function when generating srcset and sizes on the front-end. This is faster as no (other) image API functions are used.
  • Change the wp_get_attachment_image_srcset(). Now it is meant for use in templates and is no longer used in core.
  • A few logic fixes and improvements.
  • Some names changed to be (hopefully) more descriptive.
  • Fixed/updated tests.

Props joemcgill, jaspermdegroot, azaozz.
See #34430.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/wp-includes/media.php

    r35405 r35412  
    814814        // Generate srcset and sizes if not already present.
    815815        if ( empty( $attr['srcset'] ) ) {
    816             $srcset = wp_get_attachment_image_srcset( $attachment_id, $size );
    817             $sizes  = wp_get_attachment_image_sizes( $attachment_id, $size, $width );
    818 
    819             if ( $srcset && $sizes ) {
    820                 $attr['srcset'] = $srcset;
    821 
    822                 if ( empty( $attr['sizes'] ) ) {
     816            $image_meta = wp_get_attachment_metadata( $attachment_id );
     817            $size_array = array( absint( $width ), absint( $height ) );
     818            $sources = wp_calculate_image_srcset( $src, $size_array, $image_meta, $attachment_id );
     819
     820            if ( count( $sources ) > 1 ) {
     821                $attr['srcset'] = wp_image_srcset_attr( $sources, $size_array, $image_meta, $attachment_id );
     822
     823                if ( empty( $attr['sizes'] ) && ( $sizes = wp_get_attachment_image_sizes( $size_array, $image_meta, $attachment_id ) ) ) {
    823824                    $attr['sizes'] = $sizes;
    824825                }
     
    865866
    866867/**
    867  * Retrieves an array of URLs and pixel widths representing sizes of an image.
    868  *
    869  * The purpose is to populate a source set when creating responsive image markup.
     868 * Private, do not use
     869 */
     870function _wp_upload_dir_baseurl() {
     871    static $baseurl = null;
     872
     873    if ( ! $baseurl ) {
     874        $uploads_dir = wp_upload_dir();
     875        $baseurl = $uploads_dir['baseurl'];
     876    }
     877
     878    return $baseurl;
     879}
     880
     881/**
     882 * Private, do not use
     883 */
     884function _wp_get_image_size_from_meta( $size, $image_meta ) {
     885    if ( $size === 'full' ) {
     886        return array(
     887            absint( $image_meta['width'] ),
     888            absint( $image_meta['height'] ),
     889        );
     890    } elseif ( ! empty( $image_meta['sizes'][$size] ) ) {
     891        return array(
     892            absint( $image_meta['sizes'][$size]['width'] ),
     893            absint( $image_meta['sizes'][$size]['height'] ),
     894        );
     895    }
     896
     897    return false;
     898}
     899
     900/**
     901 * Retrieves the value for an image attachment's 'srcset' attribute.
    870902 *
    871903 * @since 4.4.0
    872904 *
    873  * @param int          $attachment_id Image attachment ID.
     905
     906 * @param int          $attachment_id Optional. Image attachment ID.
    874907 * @param array|string $size          Image size. Accepts any valid image size, or an array of width and height
    875908 *                                    values in pixels (in that order). Default 'medium'.
     909 * @param array        $image_meta    Optional. The image meta data.
     910 * @return string|bool A 'srcset' value string or false.
     911 */
     912function wp_get_attachment_image_srcset( $attachment_id, $size = 'medium', $image_meta = null ) {
     913    if ( ! $image = wp_get_attachment_image_src( $attachment_id, $size ) ) {
     914        return false;
     915    }
     916
     917    if ( ! is_array( $image_meta ) ) {
     918        $image_meta = get_post_meta( $attachment_id, '_wp_attachment_metadata', true );
     919    }
     920
     921    $image_url = $image[0];
     922    $size_array = array(
     923        absint( $image[1] ),
     924        absint( $image[2] )
     925    );
     926
     927    // Calculate the sources for the srcset.
     928    $sources = wp_calculate_image_srcset( $image_url, $size_array, $image_meta, $attachment_id );
     929
     930    // Only return a srcset value if there is more than one source.
     931    if ( count( $sources ) < 2 ) {
     932        return false;
     933    }
     934
     935    return wp_image_srcset_attr( $sources, $size_array, $image_meta, $attachment_id );
     936}
     937
     938
     939/**
     940 * A helper function to concatenate and filter the srcset attribute value.
     941 *
     942 * @since 4.4.0
     943 *
     944 * @param array   $sources       The array containing image sizes data as returned by wp_calculate_image_srcset().
     945 * @param array   $size_array    Array of width and height values in pixels (in that order).
     946 * @param array   $image_meta    The image meta data.
     947 * @param int     $attachment_id The image attachment post id to pass to the filter.
     948 * @return string The srcset attribute value.
     949 */
     950function wp_image_srcset_attr( $sources, $size_array, $image_meta, $attachment_id ) {
     951    $srcset = '';
     952
     953    foreach ( $sources as $source ) {
     954        $srcset .= $source['url'] . ' ' . $source['value'] . $source['descriptor'] . ', ';
     955    }
     956
     957    /**
     958     * Filter the output of wp_get_attachment_image_srcset().
     959     *
     960     * @since 4.4.0
     961     *
     962     * @param string       $srcset        A source set formatted for a `srcset` attribute.
     963     * @param int          $attachment_id Image attachment ID.
     964     * @param array|string $size          Image size. Accepts any valid image size, or an array of width and height
     965     *                                    values in pixels (in that order). Default 'medium'.
     966     * @param array        $image_meta    The image meta data.
     967     */
     968    return apply_filters( 'wp_get_attachment_image_srcset', rtrim( $srcset, ', ' ), $attachment_id, $size_array, $image_meta );
     969}
     970
     971/**
     972 * A helper function to caclulate the image sources to include in a srcset attribute.
     973 *
     974 * @since 4.4.0
     975 *
     976 * @param string $image_name    The file name, path, URL or partial path or URL of the image being matched.
     977 * @param array  $size_array    Array of width and height values in pixels (in that order).
     978 * @param array  $image_meta    The image meta data.
     979 * @param int    $attachment_id Optional. The image attachment post id to pass to the filter.
    876980 * @return array|bool $sources {
    877981 *     Array image candidate values containing a URL, descriptor type, and
     
    887991 *
    888992 */
    889 function wp_get_attachment_image_srcset_array( $attachment_id, $size = 'medium' ) {
    890     // Get the intermediate size.
    891     $image = image_get_intermediate_size( $attachment_id, $size );
    892 
    893     // Get the post meta.
    894     $img_meta = wp_get_attachment_metadata( $attachment_id );
    895     if ( ! is_array( $img_meta ) ) {
     993function wp_calculate_image_srcset( $image_name, $size_array, $image_meta, $attachment_id = 0 ) {
     994    if ( empty( $image_meta['sizes'] ) ) {
    896995        return false;
    897996    }
    898997
    899     // Extract the height and width from the intermediate or the full size.
    900     $img_width  = ( $image ) ? $image['width']  : $img_meta['width'];
    901     $img_height = ( $image ) ? $image['height'] : $img_meta['height'];
    902 
    903     // Bail early if the width isn't greater than zero.
    904     if ( ! $img_width > 0 ) {
     998    $image_sizes = $image_meta['sizes'];
     999
     1000    // Get the height and width for the image.
     1001    $image_width = (int) $size_array[0];
     1002    $image_height = (int) $size_array[1];
     1003
     1004    // Bail early if error/no width.
     1005    if ( $image_width < 1 ) {
    9051006        return false;
    9061007    }
    9071008
    908     // Use the URL from the intermediate size or build the url from the metadata.
    909     if ( ! empty( $image['url'] ) ) {
    910         $img_url = $image['url'];
    911     } else {
    912         $uploads_dir = wp_upload_dir();
    913         $img_file = ( $image ) ? path_join( dirname( $img_meta['file'] ) , $image['file'] ) : $img_meta['file'];
    914         $img_url = $uploads_dir['baseurl'] . '/' . $img_file;
    915     }
    916 
    917     $img_sizes = $img_meta['sizes'];
    918 
    9191009    // Add full size to the img_sizes array.
    920     $img_sizes['full'] = array(
    921         'width'  => $img_meta['width'],
    922         'height' => $img_meta['height'],
    923         'file'   => wp_basename( $img_meta['file'] )
     1010    $image_sizes['full'] = array(
     1011        'width'  => $image_meta['width'],
     1012        'height' => $image_meta['height'],
     1013        'file'   => wp_basename( $image_meta['file'] ),
    9241014    );
    9251015
     1016    $image_baseurl = _wp_upload_dir_baseurl();
     1017    $dirname = dirname( $image_meta['file'] );
     1018
     1019    if ( $dirname !== '.' ) {
     1020        $image_baseurl = path_join( $image_baseurl, $dirname );
     1021    }
     1022
    9261023    // Calculate the image aspect ratio.
    927     $img_ratio = $img_height / $img_width;
     1024    $image_ratio = $image_height / $image_width;
    9281025
    9291026    /*
     
    9321029     * out images that are leftovers from previous versions.
    9331030     */
    934     $img_edited = preg_match( '/-e[0-9]{13}/', $img_url, $img_edit_hash );
    935 
    936     /**
    937      * Filter the maximum width included in a srcset attribute.
     1031    $image_edited = preg_match( '/-e[0-9]{13}/', $image_name, $image_edit_hash );
     1032
     1033    /**
     1034     * Filter the maximum width included in a 'srcset' attribute.
    9381035     *
    9391036     * @since 4.4.0
    9401037     *
    941      * @param array|string $size Size of image, either array or string.
    942      */
    943     $max_srcset_width = apply_filters( 'max_srcset_image_width', 1600, $size );
     1038     * @param int          $max_width  The maximum width to include in the 'srcset'. Default '1600'.
     1039     * @param array|string $size_array Array of width and height values in pixels (in that order).
     1040     */
     1041    $max_srcset_width = apply_filters( 'max_srcset_image_width', 1600, $size_array );
     1042
     1043    // Array to hold URL candidates.
     1044    $sources = array();
    9441045
    9451046    /*
    946      * Set up arrays to hold url candidates and matched image sources so
    947      * we can avoid duplicates without looping through the full sources array
    948      */
    949     $candidates = $sources = array();
    950 
    951     /*
    952      * Loop through available images and only use images that are resized
    953      * versions of the same rendition.
    954      */
    955     foreach ( $img_sizes as $img ) {
    956 
    957         // Filter out images that are leftovers from previous renditions.
    958         if ( $img_edited && ! strpos( $img['file'], $img_edit_hash[0] ) ) {
     1047     * Loop through available images. Only use images that are resized
     1048     * versions of the same edit.
     1049     */
     1050    foreach ( $image_sizes as $image ) {
     1051
     1052        // Filter out images that are from previous edits.
     1053        if ( $image_edited && ! strpos( $image['file'], $image_edit_hash[0] ) ) {
    9591054            continue;
    9601055        }
    9611056
    9621057        // Filter out images that are wider than $max_srcset_width.
    963         if ( $max_srcset_width && $img['width'] > $max_srcset_width ) {
     1058        if ( $max_srcset_width && $image['width'] > $max_srcset_width ) {
    9641059            continue;
    9651060        }
    9661061
    967         $candidate_url = path_join( dirname( $img_url ), $img['file'] );
     1062        $candidate_url = $image['file'];
    9681063
    9691064        // Calculate the new image ratio.
    970         if ( $img['width'] ) {
    971             $img_ratio_compare = $img['height'] / $img['width'];
     1065        if ( $image['width'] ) {
     1066            $image_ratio_compare = $image['height'] / $image['width'];
    9721067        } else {
    973             $img_ratio_compare = 0;
     1068            $image_ratio_compare = 0;
    9741069        }
    9751070
    9761071        // If the new ratio differs by less than 0.01, use it.
    977         if ( abs( $img_ratio - $img_ratio_compare ) < 0.01 && ! in_array( $candidate_url, $candidates ) ) {
    978             // Add the URL to our list of candidates.
    979             $candidates[] = $candidate_url;
    980 
    981             // Add the url, descriptor, and value to the sources array to be returned.
    982             $sources[] = array(
    983                 'url'        => $candidate_url,
     1072        if ( abs( $image_ratio - $image_ratio_compare ) < 0.01 && ! array_key_exists( $candidate_url, $sources ) ) {
     1073            // Add the URL, descriptor, and value to the sources array to be returned.
     1074            $sources[ $image['width'] ] = array(
     1075                'url'        => path_join( $image_baseurl, $candidate_url ),
    9841076                'descriptor' => 'w',
    985                 'value'      => $img['width'],
     1077                'value'      => $image['width'],
    9861078            );
    9871079        }
     
    9931085     * @since 4.4.0
    9941086     *
    995      * @param array        $sources       An array of image urls and widths.
     1087     * @param array        $sources       An array of image URLs and widths.
    9961088     * @param int          $attachment_id Attachment ID for image.
    9971089     * @param array|string $size          Image size. Accepts any valid image size, or an array of width and height
    9981090     *                                    values in pixels (in that order). Default 'medium'.
    999      */
    1000     return apply_filters( 'wp_get_attachment_image_srcset_array', $sources, $attachment_id, $size );
    1001 }
    1002 
    1003 /**
    1004  * Retrieves the value for an image attachment's 'srcset' attribute.
     1091     * @param array        $image_meta    The image meta data.
     1092
     1093     */
     1094    return apply_filters( 'wp_get_attachment_image_srcset_array', array_values( $sources ), $attachment_id, $size_array, $image_meta );
     1095}
     1096
     1097/**
     1098 * Create `sizes` attribute value for an image.
    10051099 *
    10061100 * @since 4.4.0
    10071101 *
    1008  * @param int          $attachment_id Image attachment ID.
    1009  * @param array|string $size          Image size. Accepts any valid image size, or an array of width and height
    1010  *                                    values in pixels (in that order). Default 'medium'.
    1011  * @return string|bool A 'srcset' value string or false.
    1012  */
    1013 function wp_get_attachment_image_srcset( $attachment_id, $size = 'medium' ) {
    1014     $srcset_array = wp_get_attachment_image_srcset_array( $attachment_id, $size );
    1015 
    1016     // Only return a srcset value if there is more than one source.
    1017     if ( count( $srcset_array ) <= 1 ) {
     1102 * @param array|string $size          Image size. Accepts any valid image size name (thumbnail, medium, etc.),
     1103 *                                    or an array of width and height values in pixels (in that order).
     1104 * @param array        $image_meta    Optional. The image meta data.
     1105 * @param int          $attachment_id Optional. Image attachment ID. Either $image_meta or $attachment_id is needed
     1106 *                                    when using image size name.
     1107 *
     1108 * @return string|bool A valid source size value for use in a 'sizes' attribute or false.
     1109 */
     1110function wp_get_attachment_image_sizes( $size, $image_meta = null, $attachment_id = 0 ) {
     1111    $width = 0;
     1112
     1113    if ( is_numeric( $size ) ) {
     1114        $width = absint( $size );
     1115    } elseif ( is_array( $size ) ) {
     1116        $width = absint( $size[0] );
     1117    } elseif ( is_string( $size ) ) {
     1118        if ( ! $image_meta && $attachment_id ) {
     1119            $image_meta = wp_get_attachment_metadata( $attachment_id );
     1120        }
     1121
     1122        if ( $image_meta ) {
     1123            $width = _wp_get_image_size_from_meta( $size, $image_meta );
     1124            if ( $width ) {
     1125                $width = $width[0];
     1126            }
     1127        }
     1128    }
     1129
     1130    if ( ! $width ) {
    10181131        return false;
    10191132    }
    10201133
    1021     $srcset = '';
    1022     foreach ( $srcset_array as $source ) {
    1023         $srcset .= $source['url'] . ' ' . $source['value'] . $source['descriptor'] . ', ';
    1024     }
    1025 
    1026     /**
    1027      * Filter the output of wp_get_attachment_image_srcset().
     1134    // Setup the default sizes attribute.
     1135    $sizes = sprintf( '(max-width: %1$dpx) 100vw, %1$dpx', (int) $width );
     1136
     1137    /**
     1138     * Filter the output of wp_get_attachment_image_sizes().
    10281139     *
    10291140     * @since 4.4.0
    10301141     *
    1031      * @param string       $srcset        A source set formated for a `srcset` attribute.
    1032      * @param int          $attachment_id Attachment ID for image.
     1142     * @param string       $sizes         A source size value for use in a 'sizes' attribute.
    10331143     * @param array|string $size          Image size. Accepts any valid image size, or an array of width and height
    10341144     *                                    values in pixels (in that order). Default 'medium'.
    1035      */
    1036     return apply_filters( 'wp_get_attachment_image_srcset', rtrim( $srcset, ', ' ), $attachment_id, $size );
    1037 }
    1038 
    1039 /**
    1040  * Retrieves a source size attribute for an image from an array of values.
     1145     * @param array        $image_meta    The image meta data.
     1146     * @param int          $attachment_id Post ID of the original image.
     1147     */
     1148    return apply_filters( 'wp_get_attachment_image_sizes', $sizes, $size, $image_meta, $attachment_id );
     1149}
     1150
     1151/**
     1152 * Filters 'img' elements in post content to add 'srcset' and 'sizes' attributes.
    10411153 *
    10421154 * @since 4.4.0
    10431155 *
    1044  * @param int          $attachment_id Image attachment ID.
    1045  * @param array|string $size          Image size. Accepts any valid image size, or an array of width and height
    1046  *                                    values in pixels (in that order). Default 'medium'.
    1047  * @param int          $width         Optional. Display width of the image.
    1048  * @return string|bool A valid source size value for use in a 'sizes' attribute or false.
    1049  */
    1050 function wp_get_attachment_image_sizes( $attachment_id, $size = 'medium', $width = null ) {
    1051     // Try to get the image width from the $width parameter.
    1052     if ( is_numeric( $width ) ) {
    1053         $img_width = (int) $width;
    1054     // Next, see if a width value was passed in the $size parameter.
    1055     } elseif ( is_array( $size ) ) {
    1056         $img_width = $size[0];
    1057     // Finally, use the $size name to return the width of the image.
    1058     } else {
    1059         $image = image_get_intermediate_size( $attachment_id, $size );
    1060         $img_width = $image ? $image['width'] : false;
    1061     }
    1062 
    1063     // Bail early if $img_width isn't set.
    1064     if ( ! $img_width ) {
    1065         return false;
    1066     }
    1067 
    1068     // Setup the default sizes attribute.
    1069     $sizes = sprintf( '(max-width: %1$dpx) 100vw, %1$dpx', $img_width );
    1070 
    1071     /**
    1072      * Filter the output of wp_get_attachment_image_sizes().
    1073      *
    1074      * @since 4.4.0
    1075      *
    1076      * @param string       $sizes         A source size value for use in a 'sizes' attribute.
    1077      * @param int          $attachment_id Post ID of the original image.
    1078      * @param array|string $size          Image size. Accepts any valid image size, or an array of width and height
    1079      *                                    values in pixels (in that order). Default 'medium'.
    1080      * @param int          $width         Display width of the image.
    1081      */
    1082     return apply_filters( 'wp_get_attachment_image_sizes', $sizes, $attachment_id, $size, $width );
    1083 }
    1084 
    1085 /**
    1086  * Filters 'img' elements in post content to add 'srcset' and 'sizes' attributes.
    1087  *
    1088  * @since 4.4.0
    1089  *
    1090  * @see wp_img_add_srcset_and_sizes()
     1156 * @see wp_image_add_srcset_and_sizes()
    10911157 *
    10921158 * @param string $content The raw post content to be filtered.
     
    10961162    $images = get_media_embedded_in_content( $content, 'img' );
    10971163
    1098     $attachment_ids = array();
     1164    $selected_images = $attachment_ids = array();
    10991165
    11001166    foreach( $images as $image ) {
    1101         if ( preg_match( '/wp-image-([0-9]+)/i', $image, $class_id ) ) {
    1102             $attachment_id = (int) $class_id[1];
    1103             if ( $attachment_id ) {
    1104                 $attachment_ids[] = $attachment_id;
    1105             }
    1106         }
    1107     }
    1108 
    1109     if ( 0 < count( $attachment_ids ) ) {
     1167        if ( false === strpos( $image, ' srcset="' ) && preg_match( '/wp-image-([0-9]+)/i', $image, $class_id ) &&
     1168            ( $attachment_id = absint( $class_id[1] ) ) ) {
     1169
     1170            // If exactly the same image tag is used more than once, overwrite it.
     1171            // All identical tags will be replaced later with str_replace().
     1172            $selected_images[ $image ] = $attachment_id;
     1173            // Overwrite the ID when the same image is included more than once.
     1174            $attachment_ids[ $attachment_id ] = true;
     1175        }
     1176    }
     1177
     1178    if ( count( $attachment_ids ) > 1 ) {
    11101179        /*
    1111          * Warm object caches for use with wp_get_attachment_metadata.
     1180         * Warm object cache for use with get_post_meta().
    11121181         *
    11131182         * To avoid making a database call for each image, a single query
    11141183         * warms the object cache with the meta information for all images.
    11151184         */
    1116         _prime_post_caches( $attachment_ids, false, true );
    1117     }
    1118 
    1119     foreach( $images as $image ) {
    1120         $content = str_replace( $image, wp_img_add_srcset_and_sizes( $image ), $content );
     1185        update_meta_cache( 'post', array_keys( $attachment_ids ) );
     1186    }
     1187
     1188    foreach ( $selected_images as $image => $attachment_id ) {
     1189        $image_meta = get_post_meta( $attachment_id, '_wp_attachment_metadata', true );
     1190        $content = str_replace( $image, wp_image_add_srcset_and_sizes( $image, $image_meta, $attachment_id ), $content );
    11211191    }
    11221192
     
    11321202 * @see wp_get_attachment_image_sizes()
    11331203 *
    1134  * @param string $image An HTML 'img' element to be filtered.
     1204 * @param string $image         An HTML 'img' element to be filtered.
     1205 * @param array  $image_meta    The image meta data.
     1206 * @param int    $attachment_id Image attachment ID.
    11351207 * @return string Converted 'img' element with `srcset` and `sizes` attributes added.
    11361208 */
    1137 function wp_img_add_srcset_and_sizes( $image ) {
    1138     // Return early if a 'srcset' attribute already exists.
    1139     if ( false !== strpos( $image, ' srcset="' ) ) {
     1209function wp_image_add_srcset_and_sizes( $image, $image_meta, $attachment_id ) {
     1210    // Ensure the image meta exists
     1211    if ( empty( $image_meta['sizes'] ) ) {
    11401212        return $image;
    11411213    }
    11421214
    1143     // Parse id, size, width, and height from the `img` element.
    1144     $id     = preg_match( '/wp-image-([0-9]+)/i', $image, $match_id     ) ? (int) $match_id[1]     : false;
    1145     $size   = preg_match( '/size-([^\s|"]+)/i',   $image, $match_size   ) ? $match_size[1]         : false;
    1146     $width  = preg_match( '/ width="([0-9]+)"/',  $image, $match_width  ) ? (int) $match_width[1]  : false;
    1147 
    1148     if ( $id && ! $size ) {
    1149         $height = preg_match( '/ height="([0-9]+)"/', $image, $match_height ) ? (int) $match_height[1] : false;
    1150 
    1151         if ( $width && $height ) {
    1152             $size = array( $width, $height );
    1153         }
    1154     }
    1155 
    1156     /*
    1157      * If attempts to parse the size value failed, attempt to use the image
    1158      * metadata to match the 'src' against the available sizes for an attachment.
    1159      */
    1160     if ( $id && ! $size ) {
    1161         $meta = wp_get_attachment_metadata( $id );
    1162 
    1163         // Parse the image src value from the img element.
    1164         $src = preg_match( '/src="([^"]+)"/', $image, $match_src ) ? $match_src[1] : false;
    1165 
    1166         // Return early if the metadata does not exist or the src value is empty.
    1167         if ( ! $meta || ! $src ) {
    1168             return $image;
    1169         }
    1170 
     1215    $src = preg_match( '/src="([^"]+)"/', $image, $match_src ) ? $match_src[1] : '';
     1216    list( $src ) = explode( '?', $src );
     1217
     1218    // Return early if we coudn't get the image source.
     1219    if ( ! $src ) {
     1220        return $image;
     1221    }
     1222
     1223    // Bail early when an image has been inserted and later edited.
     1224    if ( preg_match( '/-e[0-9]{13}/', $image_meta['file'], $img_edit_hash ) &&
     1225        strpos( wp_basename( $src ), $img_edit_hash[0] ) === false ) {
     1226
     1227        return $image;
     1228    }
     1229
     1230    $width  = preg_match( '/ width="([0-9]+)"/',  $image, $match_width  ) ? (int) $match_width[1]  : 0;
     1231    $height = preg_match( '/ height="([0-9]+)"/', $image, $match_height ) ? (int) $match_height[1] : 0;
     1232
     1233    if ( ! $width || ! $height ) {
    11711234        /*
    1172          * First, see if the file is the full size image. If not, loop through
    1173          * the intermediate sizes until we find a file that matches.
     1235         * If attempts to parse the size value failed, attempt to use the image
     1236         * metadata to match the image file name from 'src' against the available sizes for an attachment.
    11741237         */
    11751238        $image_filename = wp_basename( $src );
    11761239
    1177         if ( $image_filename === basename( $meta['file'] ) ) {
    1178             $size = 'full';
     1240        if ( $image_filename === wp_basename( $image_meta['file'] ) ) {
     1241            $width = (int) $image_meta['width'];
     1242            $height = (int) $image_meta['height'];
    11791243        } else {
    1180             foreach( $meta['sizes'] as $image_size => $image_size_data ) {
     1244            foreach( $image_meta['sizes'] as $image_size_data ) {
    11811245                if ( $image_filename === $image_size_data['file'] ) {
    1182                     $size = $image_size;
     1246                    $width = (int) $image_size_data['width'];
     1247                    $height = (int) $image_size_data['height'];
    11831248                    break;
    11841249                }
    11851250            }
    11861251        }
    1187 
    1188     }
    1189 
    1190     // If ID and size exist, try for 'srcset' and 'sizes' and update the markup.
    1191     if ( $id && $size ) {
    1192         $srcset = wp_get_attachment_image_srcset( $id, $size );
    1193         $sizes  = wp_get_attachment_image_sizes( $id, $size, $width );
    1194 
    1195         if ( $srcset && $sizes ) {
    1196             // Format the srcset and sizes string and escape attributes.
    1197             $srcset_and_sizes = sprintf( ' srcset="%s" sizes="%s"', esc_attr( $srcset ), esc_attr( $sizes) );
    1198 
    1199             // Add srcset and sizes attributes to the image markup.
    1200             $image = preg_replace( '/<img ([^>]+)[\s?][\/?]>/', '<img $1' . $srcset_and_sizes . ' />', $image );
    1201         }
     1252    }
     1253
     1254    if ( ! $width || ! $height ) {
     1255        return $image;
     1256    }
     1257
     1258    $size_array = array( $width, $height );
     1259    $sources = wp_calculate_image_srcset( $src, $size_array, $image_meta, $attachment_id );
     1260
     1261    $srcset = $sizes = '';
     1262    // Only calculate srcset and sizes values if there is more than one source.
     1263    if ( count( $sources ) > 1 ) {
     1264        $srcset = wp_image_srcset_attr( $sources, $size_array, $image_meta, $attachment_id );
     1265        $sizes = wp_get_attachment_image_sizes( $size_array, $image_meta, $attachment_id );
     1266    }
     1267
     1268    if ( $srcset && $sizes ) {
     1269        // Format the srcset and sizes string and escape attributes.
     1270        $srcset_and_sizes = sprintf( ' srcset="%s" sizes="%s"', esc_attr( $srcset ), esc_attr( $sizes ) );
     1271
     1272        // Add srcset and sizes attributes to the image markup.
     1273        $image = preg_replace( '/<img ([^>]+?)[\/ ]*>/', '<img $1' . $srcset_and_sizes . ' />', $image );
    12021274    }
    12031275
Note: See TracChangeset for help on using the changeset viewer.