Make WordPress Core

Changeset 37034


Ignore:
Timestamp:
03/18/2016 07:44:50 PM (9 years ago)
Author:
azaozz
Message:

Responsive Images: the src of the image has to be first in the srcset, because of a bug in iOS8. Update the unit tests to reflect the changes.

Props jaspermdegroot, joemcgill, azaozz.
Fixes #35030.

Location:
trunk
Files:
2 edited

Legend:

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

    r37022 r37034  
    10681068     */
    10691069    foreach ( $image_sizes as $image ) {
     1070        $is_src = false;
    10701071
    10711072        // Check if image meta isn't corrupted.
     
    10761077        // If the file name is part of the `src`, we've confirmed a match.
    10771078        if ( ! $src_matched && false !== strpos( $image_src, $dirname . $image['file'] ) ) {
    1078             $src_matched = true;
     1079            $src_matched = $is_src = true;
    10791080        }
    10801081
     
    10881089         * that file is in the 'src' attribute.
    10891090         */
    1090         if ( $max_srcset_image_width && $image['width'] > $max_srcset_image_width &&
    1091             false === strpos( $image_src, $image['file'] ) ) {
    1092 
     1091        if ( $max_srcset_image_width && $image['width'] > $max_srcset_image_width && ! $is_src ) {
    10931092            continue;
    10941093        }
     
    11101109        if ( abs( $constrained_size[0] - $expected_size[0] ) <= 1 && abs( $constrained_size[1] - $expected_size[1] ) <= 1 ) {
    11111110            // Add the URL, descriptor, and value to the sources array to be returned.
    1112             $sources[ $image['width'] ] = array(
     1111            $source = array(
    11131112                'url'        => $image_baseurl . $image['file'],
    11141113                'descriptor' => 'w',
    11151114                'value'      => $image['width'],
    11161115            );
     1116
     1117            // The 'src' image has to be the first in the 'srcset', because of a bug in iOS8. See #35030.
     1118            if ( $is_src ) {
     1119                $sources = array( $image['width'] => $source ) + $sources;
     1120            } else {
     1121                $sources[ $image['width'] ] = $source;
     1122            }
    11171123        }
    11181124    }
  • trunk/tests/phpunit/tests/media.php

    r37022 r37034  
    834834     * Helper function to get image size array from size "name"
    835835     */
    836     function _get_image_size_array_from_name( $size_name ) {
    837         switch ( $size_name ) {
    838             case 'thumbnail':
    839                 return array( 150, 150 );
    840             case 'medium':
    841                 return array( 300, 225 );
    842             case 'medium_large':
    843                 return array( 768, 576 );
    844             case 'large':
    845                 return array( 1024, 768 );
    846             case 'full':
    847                 return array( 1600, 1200 ); // actual size of ../data/images/test-image-large.png
    848             default:
    849                 return array( 800, 600 ); // soft-resized image
    850         }
     836    function _get_image_size_array_from_meta( $image_meta, $size_name ) {
     837        $array = false;
     838
     839        if ( is_array( $image_meta ) ) {
     840            if ( 'full' === $size_name && isset( $image_meta['width'] ) && isset( $image_meta['height'] ) ) {
     841                $array = array( $image_meta['width'], $image_meta['height'] );
     842            } elseif ( isset( $image_meta['sizes'][ $size_name ]['width'] ) && isset( $image_meta['sizes'][ $size_name ]['height'] ) ) {
     843                $array = array( $image_meta['sizes'][ $size_name ]['width'], $image_meta['sizes'][ $size_name ]['height'] );
     844            }
     845        }
     846
     847        return $array;
     848    }
     849
     850    /**
     851     * Helper function to move the src image to the first position in the expected srcset string.
     852     */
     853    function _src_first( $srcset, $src_url, $src_width ) {
     854        $src_string = $src_url . ' ' . $src_width . 'w';
     855        $src_not_first = ', ' . $src_string;
     856
     857        if ( strpos( $srcset, $src_not_first ) ) {
     858            $srcset = str_replace( $src_not_first, '', $srcset );
     859            $srcset = $src_string . ', ' . $srcset;
     860        }
     861
     862        return $srcset;
    851863    }
    852864
     
    871883        }
    872884
    873         $expected = "";
     885        $expected = '';
     886
     887        foreach ( $image_meta['sizes'] as $name => $size ) {
     888            // Whitelist the sizes that should be included so we pick up 'medium_large' in 4.4.
     889            if ( in_array( $name, $intermediates ) ) {
     890                $expected .= $uploads_dir_url . $year_month . '/' . $size['file'] . ' ' . $size['width'] . 'w, ';
     891            }
     892        }
     893
     894        // Add the full size width at the end.
     895        $expected .= $uploads_dir_url . $image_meta['file'] . ' ' . $image_meta['width'] .'w';
     896
     897        foreach ( $intermediates as $int ) {
     898            $image_url = wp_get_attachment_image_url( self::$large_id, $int );
     899            $size_array = $this->_get_image_size_array_from_meta( $image_meta, $int );
     900            $expected_srcset = $this->_src_first( $expected, $image_url, $size_array[0] );
     901            $this->assertSame( $expected_srcset, wp_calculate_image_srcset( $size_array, $image_url, $image_meta ) );
     902        }
     903    }
     904
     905    /**
     906     * @ticket 33641
     907     */
     908    function test_wp_calculate_image_srcset_no_date_uploads() {
     909        global $_wp_additional_image_sizes;
     910
     911        // Disable date organized uploads
     912        add_filter( 'upload_dir', '_upload_dir_no_subdir' );
     913
     914        // Make an image.
     915        $filename = DIR_TESTDATA . '/images/test-image-large.png';
     916        $id = self::factory()->attachment->create_upload_object( $filename );
     917
     918        $image_meta = wp_get_attachment_metadata( $id );
     919        $uploads_dir_url = 'http://' . WP_TESTS_DOMAIN . '/wp-content/uploads/';
     920
     921        // Set up test cases for all expected size names.
     922        $intermediates = array( 'medium', 'medium_large', 'large', 'full' );
     923
     924        foreach ( $_wp_additional_image_sizes as $name => $additional_size ) {
     925            if ( ! $_wp_additional_image_sizes[$name]['crop'] || 0 === $_wp_additional_image_sizes[$name]['height'] ) {
     926                $intermediates[] = $name;
     927            }
     928        }
     929
     930        $expected = '';
     931
     932        foreach ( $image_meta['sizes'] as $name => $size ) {
     933            // Whitelist the sizes that should be included so we pick up 'medium_large' in 4.4.
     934            if ( in_array( $name, $intermediates ) ) {
     935                $expected .= $uploads_dir_url . $size['file'] . ' ' . $size['width'] . 'w, ';
     936            }
     937        }
     938
     939        // Add the full size width at the end.
     940        $expected .= $uploads_dir_url . $image_meta['file'] . ' ' . $image_meta['width'] .'w';
     941
     942        foreach ( $intermediates as $int ) {
     943            $size_array = $this->_get_image_size_array_from_meta( $image_meta, $int );
     944            $image_url = wp_get_attachment_image_url( $id, $int );
     945            $expected_srcset = $this->_src_first( $expected, $image_url, $size_array[0] );
     946            $this->assertSame( $expected_srcset, wp_calculate_image_srcset( $size_array, $image_url, $image_meta ) );
     947        }
     948
     949        // Remove the attachment
     950        wp_delete_attachment( $id );
     951        remove_filter( 'upload_dir', '_upload_dir_no_subdir' );
     952    }
     953
     954    /**
     955     * @ticket 33641
     956     */
     957    function test_wp_calculate_image_srcset_with_edits() {
     958        // For this test we're going to mock metadata changes from an edit.
     959        // Start by getting the attachment metadata.
     960        $image_meta = wp_get_attachment_metadata( self::$large_id );
     961        $image_url = wp_get_attachment_image_url( self::$large_id, 'medium' );
     962        $size_array = $this->_get_image_size_array_from_meta( $image_meta, 'medium' );
     963
     964        // Copy hash generation method used in wp_save_image().
     965        $hash = 'e' . time() . rand(100, 999);
     966
     967        $filename_base = basename( $image_meta['file'], '.png' );
     968
     969        // Add the hash to the image URL
     970        $image_url = str_replace( $filename_base, $filename_base . '-' . $hash, $image_url );
     971
     972        // Replace file paths for full and medium sizes with hashed versions.
     973        $image_meta['file'] = str_replace( $filename_base, $filename_base . '-' . $hash, $image_meta['file'] );
     974        $image_meta['sizes']['medium']['file'] = str_replace( $filename_base, $filename_base . '-' . $hash, $image_meta['sizes']['medium']['file'] );
     975        $image_meta['sizes']['medium_large']['file'] = str_replace( $filename_base, $filename_base . '-' . $hash, $image_meta['sizes']['medium_large']['file'] );
     976        $image_meta['sizes']['large']['file'] = str_replace( $filename_base, $filename_base . '-' . $hash, $image_meta['sizes']['large']['file'] );
     977
     978        // Calculate a srcset array.
     979        $sizes = explode( ', ', wp_calculate_image_srcset( $size_array, $image_url, $image_meta ) );
     980
     981        // Test to confirm all sources in the array include the same edit hash.
     982        foreach ( $sizes as $size ) {
     983            $this->assertTrue( false !== strpos( $size, $hash ) );
     984        }
     985    }
     986
     987    /**
     988     * @ticket 35106
     989     */
     990    function test_wp_calculate_image_srcset_with_absolute_path_in_meta() {
     991        global $_wp_additional_image_sizes;
     992
     993        $year_month = date('Y/m');
     994        $image_meta = wp_get_attachment_metadata( self::$large_id );
     995        $uploads_dir_url = 'http://' . WP_TESTS_DOMAIN . '/wp-content/uploads/';
     996
     997        // Set up test cases for all expected size names.
     998        $intermediates = array( 'medium', 'medium_large', 'large', 'full' );
     999
     1000        // Add any soft crop intermediate sizes.
     1001        foreach ( $_wp_additional_image_sizes as $name => $additional_size ) {
     1002            if ( ! $_wp_additional_image_sizes[$name]['crop'] || 0 === $_wp_additional_image_sizes[$name]['height'] ) {
     1003                $intermediates[] = $name;
     1004            }
     1005        }
     1006
     1007        $expected = '';
    8741008
    8751009        foreach( $image_meta['sizes'] as $name => $size ) {
     
    8831017        $expected .= $uploads_dir_url . $image_meta['file'] . ' ' . $image_meta['width'] .'w';
    8841018
     1019        // Prepend an absolute path to simulate a pre-2.7 upload
     1020        $image_meta['file'] = 'H:\home\wordpress\trunk/wp-content/uploads/' . $image_meta['file'];
     1021
    8851022        foreach ( $intermediates as $int ) {
    8861023            $image_url = wp_get_attachment_image_url( self::$large_id, $int );
    887             $size_array = $this->_get_image_size_array_from_name( $int );
    888             $this->assertSame( $expected, wp_calculate_image_srcset( $size_array, $image_url, $image_meta ) );
    889         }
    890     }
    891 
    892     /**
    893      * @ticket 33641
    894      */
    895     function test_wp_calculate_image_srcset_no_date_uploads() {
    896         global $_wp_additional_image_sizes;
    897 
    898         // Disable date organized uploads
    899         add_filter( 'upload_dir', '_upload_dir_no_subdir' );
    900 
    901         // Make an image.
    902         $filename = DIR_TESTDATA . '/images/test-image-large.png';
    903         $id = self::factory()->attachment->create_upload_object( $filename );
    904 
    905         $image_meta = wp_get_attachment_metadata( $id );
    906         $uploads_dir_url = 'http://' . WP_TESTS_DOMAIN . '/wp-content/uploads/';
    907 
    908         // Set up test cases for all expected size names.
    909         $intermediates = array( 'medium', 'medium_large', 'large', 'full' );
    910 
    911         foreach ( $_wp_additional_image_sizes as $name => $additional_size ) {
    912             if ( ! $_wp_additional_image_sizes[$name]['crop'] || 0 === $_wp_additional_image_sizes[$name]['height'] ) {
    913                 $intermediates[] = $name;
    914             }
    915         }
    916 
    917         $expected = "";
    918 
    919         foreach( $image_meta['sizes'] as $name => $size ) {
    920             // Whitelist the sizes that should be included so we pick up 'medium_large' in 4.4.
    921             if ( in_array( $name, $intermediates ) ) {
    922                 $expected .= $uploads_dir_url . $size['file'] . ' ' . $size['width'] . 'w, ';
    923             }
    924         }
    925 
    926         // Add the full size width at the end.
    927         $expected .= $uploads_dir_url . $image_meta['file'] . ' ' . $image_meta['width'] .'w';
    928 
    929         foreach ( $intermediates as $int ) {
    930             $size_array = $this->_get_image_size_array_from_name( $int );
    931             $image_url = wp_get_attachment_image_url( $id, $int );
    932             $this->assertSame( $expected, wp_calculate_image_srcset( $size_array, $image_url, $image_meta ) );
    933         }
    934 
    935         // Remove the attachment
    936         wp_delete_attachment( $id );
    937         remove_filter( 'upload_dir', '_upload_dir_no_subdir' );
    938     }
    939 
    940     /**
    941      * @ticket 33641
    942      */
    943     function test_wp_calculate_image_srcset_with_edits() {
    944         // For this test we're going to mock metadata changes from an edit.
    945         // Start by getting the attachment metadata.
    946         $image_meta = wp_get_attachment_metadata( self::$large_id );
    947         $image_url = wp_get_attachment_image_url( self::$large_id, 'medium' );
    948         $size_array = $this->_get_image_size_array_from_name( 'medium' );
    949 
    950         // Copy hash generation method used in wp_save_image().
    951         $hash = 'e' . time() . rand(100, 999);
    952 
    953         $filename_base = basename( $image_meta['file'], '.png' );
    954 
    955         // Add the hash to the image URL
    956         $image_url = str_replace( $filename_base, $filename_base . '-' . $hash, $image_url );
    957 
    958         // Replace file paths for full and medium sizes with hashed versions.
    959         $image_meta['file'] = str_replace( $filename_base, $filename_base . '-' . $hash, $image_meta['file'] );
    960         $image_meta['sizes']['medium']['file'] = str_replace( $filename_base, $filename_base . '-' . $hash, $image_meta['sizes']['medium']['file'] );
    961         $image_meta['sizes']['medium_large']['file'] = str_replace( $filename_base, $filename_base . '-' . $hash, $image_meta['sizes']['medium_large']['file'] );
    962         $image_meta['sizes']['large']['file'] = str_replace( $filename_base, $filename_base . '-' . $hash, $image_meta['sizes']['large']['file'] );
    963 
    964         // Calculate a srcset array.
    965         $sizes = explode( ', ', wp_calculate_image_srcset( $size_array, $image_url, $image_meta ) );
    966 
    967         // Test to confirm all sources in the array include the same edit hash.
    968         foreach ( $sizes as $size ) {
    969             $this->assertTrue( false !== strpos( $size, $hash ) );
    970         }
    971     }
    972 
    973     /**
    974      * @ticket 35106
    975      */
    976     function test_wp_calculate_image_srcset_with_absolute_path_in_meta() {
    977         global $_wp_additional_image_sizes;
    978 
    979         $year_month = date('Y/m');
    980         $image_meta = wp_get_attachment_metadata( self::$large_id );
    981         $uploads_dir_url = 'http://' . WP_TESTS_DOMAIN . '/wp-content/uploads/';
    982 
    983         // Set up test cases for all expected size names.
    984         $intermediates = array( 'medium', 'medium_large', 'large', 'full' );
    985 
    986         // Add any soft crop intermediate sizes.
    987         foreach ( $_wp_additional_image_sizes as $name => $additional_size ) {
    988             if ( ! $_wp_additional_image_sizes[$name]['crop'] || 0 === $_wp_additional_image_sizes[$name]['height'] ) {
    989                 $intermediates[] = $name;
    990             }
    991         }
    992 
    993         $expected = '';
    994 
    995         foreach( $image_meta['sizes'] as $name => $size ) {
    996             // Whitelist the sizes that should be included so we pick up 'medium_large' in 4.4.
    997             if ( in_array( $name, $intermediates ) ) {
    998                 $expected .= $uploads_dir_url . $year_month . '/' . $size['file'] . ' ' . $size['width'] . 'w, ';
    999             }
    1000         }
    1001 
    1002         // Add the full size width at the end.
    1003         $expected .= $uploads_dir_url . $image_meta['file'] . ' ' . $image_meta['width'] .'w';
    1004 
    1005         // Prepend an absolute path to simulate a pre-2.7 upload
    1006         $image_meta['file'] = 'H:\home\wordpress\trunk/wp-content/uploads/' . $image_meta['file'];
    1007 
    1008         foreach ( $intermediates as $int ) {
    1009             $image_url = wp_get_attachment_image_url( self::$large_id, $int );
    1010             $size_array = $this->_get_image_size_array_from_name( $int );
    1011             $this->assertSame( $expected, wp_calculate_image_srcset( $size_array, $image_url, $image_meta ) );
    1012         }
     1024            $size_array = $this->_get_image_size_array_from_meta( $image_meta, $int );
     1025            $expected_srcset = $this->_src_first( $expected, $image_url, $size_array[0] );
     1026            $this->assertSame( $expected_srcset, wp_calculate_image_srcset( $size_array, $image_url, $image_meta ) );
     1027        }
    10131028    }
    10141029
     
    11241139        );
    11251140
    1126         $expected_srcset = 'http://' . WP_TESTS_DOMAIN . '/wp-content/uploads/2015/12/test-300x150.png 300w, http://' . WP_TESTS_DOMAIN . '/wp-content/uploads/2015/12/test-768x384.png 768w, http://' . WP_TESTS_DOMAIN . '/wp-content/uploads/2015/12/test-1024x512.png 1024w, http://' . WP_TESTS_DOMAIN . '/wp-content/uploads/2015/12/test.png 2000w';
     1141        $expected_srcset = 'http://' . WP_TESTS_DOMAIN . '/wp-content/uploads/2015/12/test.png 2000w, http://' . WP_TESTS_DOMAIN . '/wp-content/uploads/2015/12/test-300x150.png 300w, http://' . WP_TESTS_DOMAIN . '/wp-content/uploads/2015/12/test-768x384.png 768w, http://' . WP_TESTS_DOMAIN . '/wp-content/uploads/2015/12/test-1024x512.png 1024w';
    11271142
    11281143        $this->assertSame( $expected_srcset, wp_calculate_image_srcset( $size_array, $image_src, $image_meta ) );
     
    12271242        $expected = "";
    12281243
    1229         foreach( $image_meta['sizes'] as $name => $size ) {
     1244        foreach ( $image_meta['sizes'] as $name => $size ) {
    12301245            // Whitelist the sizes that should be included so we pick up 'medium_large' in 4.4.
    12311246            if ( in_array( $name, $intermediates ) ) {
     
    12361251        $expected .= $uploads_dir . $image_meta['file'] . ' ' . $image_meta['width'] .'w';
    12371252
    1238         $this->assertSame( $expected, $srcset );
     1253        $expected_srcset = $this->_src_first( $expected, $uploads_dir . $image_meta['file'], $size_array[0] );
     1254
     1255        $this->assertSame( $expected_srcset, $srcset );
    12391256    }
    12401257
     
    12741291     */
    12751292    function test_wp_get_attachment_image_sizes() {
    1276         // Test sizes against the default WP sizes.
    1277         $intermediates = array('thumbnail', 'medium', 'medium_large', 'large');
     1293        // Test sizes against the default WP sizes.
     1294        $intermediates = array('thumbnail', 'medium', 'medium_large', 'large');
    12781295
    12791296        // Make sure themes aren't filtering the sizes array.
    12801297        remove_all_filters( 'wp_calculate_image_sizes' );
    12811298
    1282         foreach( $intermediates as $int_size ) {
    1283             $image = wp_get_attachment_image_src( self::$large_id, $int_size );
     1299        foreach( $intermediates as $int_size ) {
     1300            $image = wp_get_attachment_image_src( self::$large_id, $int_size );
    12841301
    12851302            $expected = '(max-width: ' . $image[1] . 'px) 100vw, ' . $image[1] . 'px';
     
    12951312    function test_wp_calculate_image_sizes() {
    12961313        // Test sizes against the default WP sizes.
    1297         $intermediates = array('thumbnail', 'medium', 'medium_large', 'large');
    1298         $image_meta = wp_get_attachment_metadata( self::$large_id );
     1314        $intermediates = array( 'thumbnail', 'medium', 'medium_large', 'large' );
     1315        $image_meta = wp_get_attachment_metadata( self::$large_id );
    12991316
    13001317        // Make sure themes aren't filtering the sizes array.
    13011318        remove_all_filters( 'wp_calculate_image_sizes' );
    13021319
    1303         foreach( $intermediates as $int_size ) {
    1304             $size_array = $this->_get_image_size_array_from_name( $int_size );
    1305             $image_src = $image_meta['sizes'][$int_size]['file'];
     1320        foreach ( $intermediates as $int_size ) {
     1321            $size_array = $this->_get_image_size_array_from_meta( $image_meta, $int_size );
     1322            $image_src = $image_meta['sizes'][ $int_size ]['file'];
    13061323            list( $width, $height ) = $size_array;
    13071324
     
    13181335    function test_wp_make_content_images_responsive() {
    13191336        $image_meta = wp_get_attachment_metadata( self::$large_id );
    1320         $size_array = $this->_get_image_size_array_from_name( 'medium' );
     1337        $size_array = $this->_get_image_size_array_from_meta( $image_meta, 'medium' );
    13211338
    13221339        $srcset = sprintf( 'srcset="%s"', wp_get_attachment_image_srcset( self::$large_id, $size_array, $image_meta ) );
     
    14511468    function test_wp_make_content_images_responsive_schemes() {
    14521469        $image_meta = wp_get_attachment_metadata( self::$large_id );
    1453         $size_array = $this->_get_image_size_array_from_name( 'medium' );
     1470        $size_array = $this->_get_image_size_array_from_meta( $image_meta, 'medium' );
    14541471
    14551472        $srcset = sprintf( 'srcset="%s"', wp_get_attachment_image_srcset( self::$large_id, $size_array, $image_meta ) );
     
    14811498
    14821499        $this->assertSame( $expected, $actual );
    1483 }
     1500    }
    14841501
    14851502    /**
     
    15181535        $_SERVER['HTTPS'] = 'on';
    15191536
    1520         $expected = 'https://' . WP_TESTS_DOMAIN . '/wp-content/uploads/test-300x150.jpg 300w, https://' . WP_TESTS_DOMAIN . '/wp-content/uploads/test-1024x512.jpg 1024w, https://' . WP_TESTS_DOMAIN . '/wp-content/uploads/test.jpg 1200w';
     1537        $expected = 'https://' . WP_TESTS_DOMAIN . '/wp-content/uploads/test-1024x512.jpg 1024w, https://' . WP_TESTS_DOMAIN . '/wp-content/uploads/test-300x150.jpg 300w, https://' . WP_TESTS_DOMAIN . '/wp-content/uploads/test.jpg 1200w';
    15211538        $actual   = wp_calculate_image_srcset( $size_array, $image_url, $image_meta );
    15221539
Note: See TracChangeset for help on using the changeset viewer.