Make WordPress Core

Ticket #17626: 17626.3.diff

File 17626.3.diff, 11.0 KB (added by joemcgill, 9 years ago)

added tests for arrays with zero heights or widths

  • src/wp-includes/media.php

    diff --git src/wp-includes/media.php src/wp-includes/media.php
    index c02aabc..6b246d1 100644
    function image_make_intermediate_size( $file, $width, $height, $crop = false ) { 
    580580 * @param array|string $size Optional, default is 'thumbnail'. Size of image, either array or string.
    581581 * @return bool|array False on failure or array of file path, width, and height on success.
    582582 */
    583 function image_get_intermediate_size($post_id, $size='thumbnail') {
     583function image_get_intermediate_size( $post_id, $size='thumbnail' ) {
    584584        if ( !is_array( $imagedata = wp_get_attachment_metadata( $post_id ) ) )
    585585                return false;
    586586
    587587        // get the best one for a specified set of dimensions
    588         if ( is_array($size) && !empty($imagedata['sizes']) ) {
    589                 $areas = array();
     588        if ( is_array($size) && !empty( $imagedata['sizes'] ) ) {
     589                $candidates = array();
    590590
    591591                foreach ( $imagedata['sizes'] as $_size => $data ) {
    592                         // already cropped to width or height; so use this size
    593                         if ( ( $data['width'] == $size[0] && $data['height'] <= $size[1] ) || ( $data['height'] == $size[1] && $data['width'] <= $size[0] ) ) {
     592                        // If there's an exact match to an existing image size, short circuit.
     593                        if ( ( $data['width'] == $size[0] && $data['height'] == $size[1] ) ) {
    594594                                $file = $data['file'];
    595595                                list($width, $height) = image_constrain_size_for_editor( $data['width'], $data['height'], $size );
    596596                                return compact( 'file', 'width', 'height' );
    597597                        }
    598                         // add to lookup table: area => size
    599                         $areas[$data['width'] * $data['height']] = $_size;
     598                        // If it's not an exact match but it's at least the dimensions requested.
     599                        if ( ( $data['width'] >= $size[0] ) && ( $data['height'] >= $size[1] ) ) {
     600                                $candidates[$data['width'] * $data['height']] = $_size;
     601                        }
    600602                }
    601                 if ( !$size || !empty($areas) ) {
     603
     604                if ( !empty($candidates) ) {
    602605                        // find for the smallest image not smaller than the desired size
    603                         ksort($areas);
    604                         foreach ( $areas as $_size ) {
     606                        ksort($candidates);
     607                        foreach ( $candidates as $_size ) {
    605608                                $data = $imagedata['sizes'][$_size];
    606                                 if ( $data['width'] >= $size[0] || $data['height'] >= $size[1] ) {
    607                                         // Skip images with unexpectedly divergent aspect ratios (crops)
    608                                         // First, we calculate what size the original image would be if constrained to a box the size of the current image in the loop
    609                                         $maybe_cropped = image_resize_dimensions($imagedata['width'], $imagedata['height'], $data['width'], $data['height'], false );
    610                                         // If the size doesn't match within one pixel, then it is of a different aspect ratio, so we skip it, unless it's the thumbnail size
    611                                         if ( 'thumbnail' != $_size && ( !$maybe_cropped || ( $maybe_cropped[4] != $data['width'] && $maybe_cropped[4] + 1 != $data['width'] ) || ( $maybe_cropped[5] != $data['height'] && $maybe_cropped[5] + 1 != $data['height'] ) ) )
    612                                                 continue;
    613                                         // If we're still here, then we're going to use this size
    614                                         $file = $data['file'];
    615                                         list($width, $height) = image_constrain_size_for_editor( $data['width'], $data['height'], $size );
    616                                         return compact( 'file', 'width', 'height' );
    617                                 }
     609
     610                                // Skip images with unexpectedly divergent aspect ratios (crops)
     611                                // First, we calculate what size the original image would be if constrained to a box the size of the current image in the loop
     612                                $maybe_cropped = image_resize_dimensions($imagedata['width'], $imagedata['height'], $data['width'], $data['height'], false );
     613                                // If the size doesn't match within one pixel, then it is of a different aspect ratio, so we skip it, unless it's the thumbnail size
     614                                if ( 'thumbnail' != $_size &&
     615                ( !$maybe_cropped
     616                  || ( $maybe_cropped[4] != $data['width'] && $maybe_cropped[4] + 1 != $data['width'] )
     617                  || ( $maybe_cropped[5] != $data['height'] && $maybe_cropped[5] + 1 != $data['height'] )
     618                ) )
     619                continue;
     620                                // If we're still here, then we're going to use this size
     621                                $file = $data['file'];
     622                                list($width, $height) = image_constrain_size_for_editor( $data['width'], $data['height'], $size );
     623                                return compact( 'file', 'width', 'height' );
    618624                        }
    619625                }
    620626        }
  • tests/phpunit/tests/image/intermediate_size.php

    diff --git tests/phpunit/tests/image/intermediate_size.php tests/phpunit/tests/image/intermediate_size.php
    index 73728e5..22031d0 100644
    class Tests_Image_Intermediate_Size extends WP_UnitTestCase { 
    1010                parent::tearDown();
    1111        }
    1212
     13        /**
     14         * Upload files and create attachements for testing
     15         */
     16        private function _make_attachment( $file, $parent_post_id = 0 ) {
     17                $contents = file_get_contents($file);
     18                $upload = wp_upload_bits(basename($file), null, $contents);
     19
     20                $type = '';
     21                if ( !empty($upload['type']) ) {
     22                        $type = $upload['type'];
     23                } else {
     24                        $mime = wp_check_filetype( $upload['file'] );
     25                        if ($mime)
     26                        $type = $mime['type'];
     27                }
     28
     29                $attachment = array(
     30                        'post_title' => basename( $upload['file'] ),
     31                        'post_content' => '',
     32                        'post_type' => 'attachment',
     33                        'post_parent' => $parent_post_id,
     34                        'post_mime_type' => $type,
     35                        'guid' => $upload[ 'url' ],
     36                );
     37
     38                // Save the data
     39                $id = wp_insert_attachment( $attachment, $upload[ 'file' ], $parent_post_id );
     40                wp_update_attachment_metadata( $id, wp_generate_attachment_metadata( $id, $upload['file'] ) );
     41
     42                return $this->ids[] = $id;
     43        }
     44
    1345        function test_make_intermediate_size_no_size() {
    1446                $image = image_make_intermediate_size( DIR_TESTDATA . '/images/a2-small.jpg', 0, 0, false );
    1547
    class Tests_Image_Intermediate_Size extends WP_UnitTestCase { 
    4981
    5082                unlink( DIR_TESTDATA . '/images/a2-small-100x75.jpg' );
    5183        }
     84
     85        /**
     86        * @ticket 17626
     87        */
     88        function test_get_intermediate_sizes_by_name() {
     89                add_image_size( 'test-size', 330, 220, true );
     90
     91                $file = DIR_TESTDATA . '/images/waffles.jpg';
     92                $id = $this->_make_attachment( $file, 0 );
     93
     94                // look for a size by name
     95                $image = image_get_intermediate_size( $id, 'test-size' );
     96
     97                // test for the expected string because the array will by definition
     98                // return with the correct height and width attributes
     99                $this->assertNotFalse( strpos( $image['file'], '330x220' ) );
     100
     101                // cleanup
     102                remove_image_size('test-size');
     103        }
     104
     105        /**
     106        * @ticket 17626
     107        */
     108        function test_get_intermediate_sizes_by_array_exact() {
     109                // Only one dimention match shouldn't return false positive (see: 17626)
     110                add_image_size( 'test-size', 330, 220, true );
     111                add_image_size( 'false-height', 330, 400, true);
     112                add_image_size( 'false-width', 600, 220, true);
     113
     114                $file = DIR_TESTDATA . '/images/waffles.jpg';
     115                $id = $this->_make_attachment( $file, 0 );
     116
     117                // look for a size by array that exists
     118                // note: staying larger than 300px to miss default medium crop
     119                $image = image_get_intermediate_size( $id, array(330,220) );
     120
     121                // test for the expected string because the array will by definition
     122                // return with the correct height and width attributes
     123                $this->assertNotFalse( strpos( $image['file'], '330x220' ) );
     124
     125                // cleanup
     126                remove_image_size('test-size');
     127                remove_image_size('false-height');
     128                remove_image_size('false-width');
     129        }
     130
     131        /**
     132        * @ticket 17626
     133        */
     134        function test_get_intermediate_sizes_by_array_nearest() {
     135                // If an exact size is not found, it should be returned
     136                // If not, find nearest size that is larger (see: 17626)
     137                add_image_size( 'test-size', 450, 300, true );
     138                add_image_size( 'false-height', 330, 100, true);
     139                add_image_size( 'false-width', 150, 220, true);
     140
     141                $file = DIR_TESTDATA . '/images/waffles.jpg';
     142                $id = $this->_make_attachment( $file, 0 );
     143
     144                // look for a size by array that doesn't exist
     145                // note: staying larger than 300px to miss default medium crop
     146                $image = image_get_intermediate_size( $id, array(330,220) );
     147
     148                // you have to test for the string because the image will by definition
     149                // return with the correct height and width attributes
     150                $this->assertNotFalse( strpos( $image['file'], '450x300' ) );
     151
     152                // cleanup
     153                remove_image_size('test-size');
     154                remove_image_size('false-height');
     155                remove_image_size('false-width');
     156
     157        }
     158
     159        /**
     160        * @ticket 17626
     161        */
     162        function test_get_intermediate_sizes_by_array_nearest_false() {
     163                // If an exact size is not found, it should be returned
     164                // If not, find nearest size that is larger, otherwise return false (see: 17626)
     165                add_image_size( 'false-height', 330, 100, true);
     166                add_image_size( 'false-width', 150, 220, true);
     167
     168                $file = DIR_TESTDATA . '/images/waffles.jpg';
     169                $id = $this->_make_attachment( $file, 0 );
     170
     171                // look for a size by array that doesn't exist
     172                // note: staying larger than 300px to miss default medium crop
     173                $image = image_get_intermediate_size( $id, array(330,220) );
     174
     175                // you have to test for the string because the image will by definition
     176                // return with the correct height and width attributes
     177                $this->assertFalse( $image );
     178
     179                // cleanup
     180                remove_image_size('false-height');
     181                remove_image_size('false-width');
     182
     183        }
     184
     185        /**
     186        * @ticket 17626
     187        */
     188        function test_get_intermediate_sizes_by_array_zero_height() {
     189                // Generate random width
     190                $random_w = rand(300,400);
     191
     192                // Only one dimention match shouldn't return false positive (see: 17626)
     193                add_image_size( 'test-size', $random_w, 0, false );
     194                add_image_size( 'false-height', $random_w, 100, true);
     195
     196                $file = DIR_TESTDATA . '/images/waffles.jpg';
     197                $id = $this->_make_attachment( $file, 0 );
     198
     199                $original = wp_get_attachment_metadata( $id );
     200                $image_w = $random_w;
     201                $image_h = ( $image_w / $original['width'] ) * $original['height'];
     202
     203                // look for a size by array that exists
     204                // note: staying larger than 300px to miss default medium crop
     205                $image = image_get_intermediate_size( $id, array($random_w,0) );
     206
     207                // test for the expected string because the array will by definition
     208                // return with the correct height and width attributes
     209                $this->assertNotFalse( strpos( $image['file'], $image_w . 'x' . $image_h ) );
     210
     211                // cleanup
     212                remove_image_size('test-size');
     213                remove_image_size('false-height');
     214        }
     215
     216        /**
     217        * @ticket 17626
     218        */
     219        function test_get_intermediate_sizes_by_array_zero_width() {
     220                // Generate random height
     221                $random_h = rand(200, 300);
     222
     223                // Only one dimention match shouldn't return false positive (see: 17626)
     224                add_image_size( 'test-size', 0, $random_h, false );
     225                add_image_size( 'false-height', 300, $random_h, true);
     226
     227                $file = DIR_TESTDATA . '/images/waffles.jpg';
     228                $id = $this->_make_attachment( $file, 0 );
     229
     230                $original = wp_get_attachment_metadata( $id );
     231                $image_h = $random_h;
     232                $image_w = round( ( $image_h / $original['height'] ) * $original['width'] );
     233
     234                // look for a size by array that exists
     235                // note: staying larger than 300px to miss default medium crop
     236                $image = image_get_intermediate_size( $id, array(0,$random_h) );
     237
     238                // test for the expected string because the array will by definition
     239                // return with the correct height and width attributes
     240                $this->assertNotFalse( strpos( $image['file'], $image_w . 'x' . $image_h ) );
     241
     242                // cleanup
     243                remove_image_size('test-size');
     244                remove_image_size('false-height');
     245        }
    52246}