WordPress.org

Make WordPress Core


Ignore:
Timestamp:
10/06/2015 04:58:21 AM (4 years ago)
Author:
wonderboymusic
Message:

Merge the Responsive Images feature plugin into core, initial commit. See: https://github.com/ResponsiveImagesCG/wp-tevko-responsive-images/

New functions in media.php:

  • wp_get_attachment_image_srcset_array() - Returns an array of image candidate string data used to build a srcset value for an attachment given an $attachement_id and $size.
  • wp_get_attachment_image_srcset() - Returns the srcset value for an attachment given an $attachement_id and $size.
  • wp_get_attachment_image_sizes() - Returns the sizes value for an attachment given an $attachement_id and $size and optional arguments used to alter its output.
  • wp_make_content_images_responsive() - A display filter for adding srcset and sizes to images embedded in content.
  • wp_img_add_srcset_and_sizes() - A utility function used by wp_make_content_images_responsive() to add srcset and sizes to a single <img> element.

Modifies existing core functions:

  • Modify wp_get_attachment_image() so the HTML returned for an image includes srcset and sizes.
  • Modify get_media_embedded_in_content() (sup, 3.6 leftover) by adding <img> to the list of accepted tags that can be matched in content. This is used in wp_make_content_images_responsive() to find all of the images embedded in content before passing them off to wp_img_add_srcset_and_sizes().

Tests:

  • Add a new factory method to WP_UnitTest_Factory_For_Attachment named create_upload_object()
  • Adds unit tests
  • Updates unit tests

Props joemcgill, tevko, jaspermdegroot, mdmcginn, barryceelen, peterwilsoncc, fsylum, wonderboymusic, chriscoyier, benjaminpick, jrfnl, #12kingkool68, janhenckens, ryanmarkel, side777, ryelle, wturrell, micahmills, mattbagwell, coliff, DrewAPicture.
See #33641.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/tests/phpunit/tests/media.php

    r34694 r34855  
    1919        $this->img_url = 'http://' . WP_TESTS_DOMAIN . '/wp-content/uploads/' . $this->img_name;
    2020        $this->img_html = '<img src="' . $this->img_url . '"/>';
    21         $this->img_dimensions = array( 'width' => 100, 'height' => 100 );
     21        $this->img_meta = array( 'width' => 100, 'height' => 100, 'sizes' => '' );
    2222    }
    2323
     
    289289                'post_type' => 'attachment'
    290290            ) );
    291             wp_update_attachment_metadata( $attachment_id, $this->img_dimensions );
     291            $metadata = array_merge( array( "file" => "image$i.jpg" ), $this->img_meta );
     292            wp_update_attachment_metadata( $attachment_id, $metadata );
    292293            $ids1[] = $attachment_id;
    293294            $ids1_srcs[] = 'http://' . WP_TESTS_DOMAIN . '/wp-content/uploads/' . "image$i.jpg";
     
    301302                'post_type' => 'attachment'
    302303            ) );
    303             wp_update_attachment_metadata( $attachment_id, $this->img_dimensions );
     304            $metadata = array_merge( array( "file" => "image$i.jpg" ), $this->img_meta );
     305            wp_update_attachment_metadata( $attachment_id, $metadata );
    304306            $ids2[] = $attachment_id;
    305307            $ids2_srcs[] = 'http://' . WP_TESTS_DOMAIN . '/wp-content/uploads/' . "image$i.jpg";
     
    330332                'post_type' => 'attachment'
    331333            ) );
    332             wp_update_attachment_metadata( $attachment_id, $this->img_dimensions );
     334            $metadata = array_merge( array( "file" => "image$i.jpg" ), $this->img_meta );
     335            wp_update_attachment_metadata( $attachment_id, $metadata );
    333336            $ids1[] = $attachment_id;
    334337            $ids1_srcs[] = 'http://' . WP_TESTS_DOMAIN . '/wp-content/uploads/' . "image$i.jpg";
     
    342345                'post_type' => 'attachment'
    343346            ) );
    344             wp_update_attachment_metadata( $attachment_id, $this->img_dimensions );
     347            $metadata = array_merge( array( "file" => "image$i.jpg" ), $this->img_meta );
     348            wp_update_attachment_metadata( $attachment_id, $metadata );
    345349            $ids2[] = $attachment_id;
    346350            $ids2_srcs[] = 'http://' . WP_TESTS_DOMAIN . '/wp-content/uploads/' . "image$i.jpg";
     
    502506        $this->assertEquals( 200, $_wp_additional_image_sizes['test-size']['width'] );
    503507        $this->assertEquals( 600, $_wp_additional_image_sizes['test-size']['height'] );
     508
     509        // Clean up
    504510        remove_image_size( 'test-size' );
    505511    }
     
    521527        add_image_size( 'test-size', 200, 600 );
    522528        $this->assertTrue( has_image_size( 'test-size' ) );
     529
     530        // Clean up
    523531        remove_image_size( 'test-size' );
    524532    }
     
    738746        $this->assertEquals( $image[0], wp_get_attachment_image_url( $attachment_id ) );
    739747    }
     748
     749    /**
     750     * @ticket 33641
     751     */
     752    function test_wp_get_attachment_image_srcset_array() {
     753        $filename = DIR_TESTDATA . '/images/test-image-large.png';
     754        $id = $this->factory->attachment->create_upload_object( $filename );
     755
     756        $year_month = date('Y/m');
     757        $image = wp_get_attachment_metadata( $id );
     758
     759        $expected = array(
     760            array(
     761                'url'        => 'http://example.org/wp-content/uploads/' . $year_month . '/' . $image['sizes']['medium']['file'],
     762                'descriptor' => 'w',
     763                'value'      => $image['sizes']['medium']['width'],
     764            ),
     765            array(
     766                'url'        => 'http://example.org/wp-content/uploads/' . $year_month . '/' . $image['sizes']['large']['file'],
     767                'descriptor' => 'w',
     768                'value'      => $image['sizes']['large']['width'],
     769            ),
     770            array(
     771                'url'        => 'http://example.org/wp-content/uploads/' . $image['file'],
     772                'descriptor' => 'w',
     773                'value'      => $image['width'],
     774            ),
     775        );
     776
     777        // Set up test cases for all expected size names and a random one.
     778        $sizes = array( 'medium', 'large', 'full', 'yoav' );
     779
     780        foreach ( $sizes as $size ) {
     781            $this->assertSame( $expected, wp_get_attachment_image_srcset_array( $id, $size ) );
     782        }
     783    }
     784
     785    /**
     786     * @ticket 33641
     787     */
     788    function test_wp_get_attachment_image_srcset_array_no_date_upoads() {
     789        // Save the current setting for uploads folders
     790        $uploads_use_yearmonth_folders = get_option( 'uploads_use_yearmonth_folders' );
     791
     792        // Disable date organized uploads
     793        update_option( 'uploads_use_yearmonth_folders', 0 );
     794
     795        // Make an image.
     796        $filename = DIR_TESTDATA . '/images/test-image-large.png';
     797        $id = $this->factory->attachment->create_upload_object( $filename );
     798
     799        $image = wp_get_attachment_metadata( $id );
     800
     801        $expected = array(
     802            array(
     803                'url'        => 'http://example.org/wp-content/uploads/' . $image['sizes']['medium']['file'],
     804                'descriptor' => 'w',
     805                'value'      => $image['sizes']['medium']['width'],
     806            ),
     807            array(
     808                'url'        => 'http://example.org/wp-content/uploads/' . $image['sizes']['large']['file'],
     809                'descriptor' => 'w',
     810                'value'      => $image['sizes']['large']['width'],
     811            ),
     812            array(
     813                'url'        => 'http://example.org/wp-content/uploads/' . $image['file'],
     814                'descriptor' => 'w',
     815                'value'      => $image['width'],
     816            ),
     817        );
     818
     819        // Set up test cases for all expected size names and a random one.
     820        $sizes = array( 'medium', 'large', 'full', 'yoav' );
     821
     822        foreach ( $sizes as $size ) {
     823            $this->assertSame( $expected, wp_get_attachment_image_srcset_array( $id, $size ) );
     824        }
     825
     826        // Leave the uploads option the way you found it.
     827        update_option( 'uploads_use_yearmonth_folders', $uploads_use_yearmonth_folders );
     828    }
     829
     830    /**
     831     * @ticket 33641
     832     */
     833    function test_wp_get_attachment_image_srcset_array_with_edits() {
     834        // Make an image.
     835        $filename = DIR_TESTDATA . '/images/test-image-large.png';
     836        $id = $this->factory->attachment->create_upload_object( $filename );
     837        // For this test we're going to mock metadata changes from an edit.
     838        // Start by getting the attachment metadata.
     839        $meta = wp_get_attachment_metadata( $id );
     840
     841        // Copy hash generation method used in wp_save_image().
     842        $hash = 'e' . time() . rand(100, 999);
     843
     844        // Replace file paths for full and medium sizes with hashed versions.
     845        $filename_base = basename( $meta['file'], '.png' );
     846        $meta['file'] = str_replace( $filename_base, $filename_base . '-' . $hash, $meta['file'] );
     847        $meta['sizes']['medium']['file'] = str_replace( $filename_base, $filename_base . '-' . $hash, $meta['sizes']['medium']['file'] );
     848
     849        // Save edited metadata.
     850        wp_update_attachment_metadata( $id, $meta );
     851
     852        // Get the edited image and observe that a hash was created.
     853        $img_url = wp_get_attachment_url( $id );
     854
     855        // Calculate a srcset array.
     856        $sizes = wp_get_attachment_image_srcset_array( $id, 'medium' );
     857
     858        // Test to confirm all sources in the array include the same edit hash.
     859        foreach ( $sizes as $size ) {
     860            $this->assertTrue( false !== strpos( $size['url'], $hash ) );
     861        }
     862    }
     863
     864    /**
     865     * @ticket 33641
     866     */
     867    function test_wp_get_attachment_image_srcset_array_false() {
     868        // Make an image.
     869        $filename = DIR_TESTDATA . '/images/test-image-large.png';
     870        $id = $this->factory->attachment->create_upload_object( $filename );
     871        $sizes = wp_get_attachment_image_srcset_array( 99999, 'foo' );
     872
     873        // For canola.jpg we should return
     874        $this->assertFalse( $sizes );
     875    }
     876
     877    /**
     878     * @ticket 33641
     879     */
     880    function test_wp_get_attachment_image_srcset_array_no_width() {
     881        // Filter image_downsize() output.
     882        add_filter( 'wp_generate_attachment_metadata', array( $this, '_test_wp_get_attachment_image_srcset_array_no_width_filter' ) );
     883
     884        // Make our attachment.
     885        $filename = DIR_TESTDATA . '/images/test-image-large.png';
     886        $id = $this->factory->attachment->create_upload_object( $filename );
     887        $srcset = wp_get_attachment_image_srcset_array( $id, 'medium' );
     888
     889        // The srcset should be false.
     890        $this->assertFalse( $srcset );
     891
     892        // Remove filter.
     893        remove_filter( 'wp_generate_attachment_metadata', array( $this, '_test_wp_get_attachment_image_srcset_array_no_width_filter' ) );
     894    }
     895
     896    /**
     897     * Helper function to filter image_downsize and return zero values for width and height.
     898     */
     899    public function _test_wp_get_attachment_image_srcset_array_no_width_filter( $meta ) {
     900        $meta['sizes']['medium']['width'] = 0;
     901        $meta['sizes']['medium']['height'] = 0;
     902        return $meta;
     903    }
     904
     905    /**
     906     * @ticket 33641
     907     */
     908    function test_wp_get_attachment_image_srcset() {
     909        // Make an image.
     910        $filename = DIR_TESTDATA . '/images/test-image-large.png';
     911        $id = $this->factory->attachment->create_upload_object( $filename );
     912        $sizes = wp_get_attachment_image_srcset( $id, 'full-size' );
     913
     914        $image = wp_get_attachment_metadata( $id );
     915        $year_month = date('Y/m');
     916
     917        $expected = 'http://example.org/wp-content/uploads/' . $year_month = date('Y/m') . '/'
     918            . $image['sizes']['medium']['file'] . ' ' . $image['sizes']['medium']['width'] . 'w, ';
     919        $expected .= 'http://example.org/wp-content/uploads/' . $year_month = date('Y/m') . '/'
     920            . $image['sizes']['large']['file'] . ' ' . $image['sizes']['large']['width'] . 'w, ';
     921        $expected .= 'http://example.org/wp-content/uploads/' . $image['file'] . ' ' . $image['width'] .'w';
     922
     923        $this->assertSame( $expected, $sizes );
     924    }
     925
     926    /**
     927     * @ticket 33641
     928     */
     929    function test_wp_get_attachment_image_srcset_single_srcset() {
     930        // Make an image.
     931        $filename = DIR_TESTDATA . '/images/test-image-large.png';
     932        $id = $this->factory->attachment->create_upload_object( $filename );
     933        /*
     934         * In our tests, thumbnails will only return a single srcset candidate,
     935         * so we shouldn't return a srcset value in order to avoid unneeded markup.
     936         */
     937        $sizes = wp_get_attachment_image_srcset( $id, 'thumbnail' );
     938
     939        $this->assertFalse( $sizes );
     940    }
     941
     942    /**
     943     * @ticket 33641
     944     */
     945    function test_wp_get_attachment_image_sizes() {
     946        // Make an image.
     947        $filename = DIR_TESTDATA . '/images/test-image-large.png';
     948        $id = $this->factory->attachment->create_upload_object( $filename );
     949
     950
     951        global $content_width;
     952
     953        // Test sizes against the default WP sizes.
     954        $intermediates = array('thumbnail', 'medium', 'large');
     955
     956        foreach( $intermediates as $int ) {
     957            $width = get_option( $int . '_size_w' );
     958
     959            // The sizes width gets constrained to $content_width by default.
     960            if ( $content_width > 0 ) {
     961                $width = ( $width > $content_width ) ? $content_width : $width;
     962            }
     963
     964            $expected = '(max-width: ' . $width . 'px) 100vw, ' . $width . 'px';
     965            $sizes = wp_get_attachment_image_sizes( $id, $int );
     966
     967            $this->assertSame($expected, $sizes);
     968        }
     969    }
     970
     971    /**
     972     * @ticket 33641
     973     */
     974    function test_wp_get_attachment_image_sizes_with_args() {
     975        // Make an image.
     976        $filename = DIR_TESTDATA . '/images/test-image-large.png';
     977        $id = $this->factory->attachment->create_upload_object( $filename );
     978
     979
     980        $args = array(
     981            'sizes' => array(
     982                array(
     983                    'size_value'    => '10em',
     984                    'mq_value'      => '60em',
     985                    'mq_name'           => 'min-width'
     986                ),
     987                array(
     988                    'size_value'    => '20em',
     989                    'mq_value'      => '30em',
     990                    'mq_name'           => 'min-width'
     991                ),
     992                array(
     993                    'size_value'    => 'calc(100vm - 30px)'
     994                ),
     995            )
     996        );
     997
     998        $expected = '(min-width: 60em) 10em, (min-width: 30em) 20em, calc(100vm - 30px)';
     999        $sizes = wp_get_attachment_image_sizes( $id, 'medium', $args );
     1000
     1001        $this->assertSame($expected, $sizes);
     1002    }
     1003
     1004    /**
     1005     * @ticket 33641
     1006     */
     1007    function test_wp_get_attachment_image_sizes_with_filtered_args() {
     1008        // Add our test filter.
     1009        add_filter( 'wp_image_sizes_args', array( $this, '_test_wp_image_sizes_args' ) );
     1010
     1011        // Make an image.
     1012        $filename = DIR_TESTDATA . '/images/test-image-large.png';
     1013        $id = $this->factory->attachment->create_upload_object( $filename );
     1014
     1015        $sizes = wp_get_attachment_image_sizes($id, 'medium');
     1016
     1017        // Evaluate that the sizes returned is what we expected.
     1018        $this->assertSame( $sizes, '100vm');
     1019
     1020        remove_filter( 'wp_image_sizes_args', array( $this, '_test_wp_image_sizes_args' ) );
     1021    }
     1022
     1023    /**
     1024     * A simple test filter for wp_get_attachment_image_sizes().
     1025     */
     1026    function _test_wp_image_sizes_args( $args ) {
     1027        $args['sizes'] = "100vm";
     1028        return $args;
     1029    }
     1030
     1031    /**
     1032     * @ticket 33641
     1033     */
     1034    function test_wp_make_content_images_responsive() {
     1035        // Make an image.
     1036        $filename = DIR_TESTDATA . '/images/test-image-large.png';
     1037        $id = $this->factory->attachment->create_upload_object( $filename );
     1038
     1039        $srcset = sprintf( 'srcset="%s"', wp_get_attachment_image_srcset( $id, 'medium' ) );
     1040        $sizes = sprintf( 'sizes="%s"', wp_get_attachment_image_sizes( $id, 'medium' ) );
     1041
     1042        // Function used to build HTML for the editor.
     1043        $img = get_image_tag( $id, '', '', '', 'medium' );
     1044        $img_no_size = str_replace( 'size-', '', $img );
     1045        $img_no_size_id = str_replace( 'wp-image-', 'id-', $img_no_size );
     1046
     1047        // Manually add srcset and sizes to the markup from get_image_tag();
     1048        $respimg = preg_replace('|<img ([^>]+) />|', '<img $1 ' . $srcset . ' ' . $sizes . ' />', $img);
     1049        $respimg_no_size = preg_replace('|<img ([^>]+) />|', '<img $1 ' . $srcset . ' ' . $sizes . ' />', $img_no_size);
     1050
     1051        $content = '<p>Welcome to WordPress!  This post contains important information.  After you read it, you can make it private to hide it from visitors but still have the information handy for future reference.</p>
     1052            <p>First things first:</p>
     1053
     1054            %1$s
     1055
     1056            <ul>
     1057            <li><a href="http://wordpress.org" title="Subscribe to the WordPress mailing list for Release Notifications">Subscribe to the WordPress mailing list for release notifications</a></li>
     1058            </ul>
     1059
     1060            %2$s
     1061
     1062            <p>As a subscriber, you will receive an email every time an update is available (and only then).  This will make it easier to keep your site up to date, and secure from evildoers.<br />
     1063            When a new version is released, <a href="http://wordpress.org" title="If you are already logged in, this will take you directly to the Dashboard">log in to the Dashboard</a> and follow the instructions.<br />
     1064            Upgrading is a couple of clicks!</p>
     1065
     1066            %3$s
     1067
     1068            <p>Then you can start enjoying the WordPress experience:</p>
     1069            <ul>
     1070            <li>Edit your personal information at <a href="http://wordpress.org" title="Edit settings like your password, your display name and your contact information">Users &#8250; Your Profile</a></li>
     1071            <li>Start publishing at <a href="http://wordpress.org" title="Create a new post">Posts &#8250; Add New</a> and at <a href="http://wordpress.org" title="Create a new page">Pages &#8250; Add New</a></li>
     1072            <li>Browse and install plugins at <a href="http://wordpress.org" title="Browse and install plugins at the official WordPress repository directly from your Dashboard">Plugins &#8250; Add New</a></li>
     1073            <li>Browse and install themes at <a href="http://wordpress.org" title="Browse and install themes at the official WordPress repository directly from your Dashboard">Appearance &#8250; Add New Themes</a></li>
     1074            <li>Modify and prettify your website&#8217;s links at <a href="http://wordpress.org" title="For example, select a link structure like: http://example.com/1999/12/post-name">Settings &#8250; Permalinks</a></li>
     1075            <li>Import content from another system or WordPress site at <a href="http://wordpress.org" title="WordPress comes with importers for the most common publishing systems">Tools &#8250; Import</a></li>
     1076            <li>Find answers to your questions at the <a href="http://wordpress.orgs" title="The official WordPress documentation, maintained by the WordPress community">WordPress Codex</a></li>
     1077            </ul>';
     1078
     1079        $content_unfiltered = sprintf( $content, $img, $img_no_size, $img_no_size_id );
     1080        $content_filtered = sprintf( $content, $respimg, $respimg_no_size, $img_no_size_id );
     1081
     1082        $this->assertSame( $content_filtered, wp_make_content_images_responsive( $content_unfiltered ) );
     1083    }
     1084
     1085    /**
     1086     * @ticket 33641
     1087     */
     1088    function test_wp_make_content_images_responsive_with_preexisting_srcset() {
     1089        // Make an image.
     1090        $filename = DIR_TESTDATA . '/images/test-image-large.png';
     1091        $id = $this->factory->attachment->create_upload_object( $filename );
     1092
     1093        // Generate HTML and add a dummy srcset attribute.
     1094        $image_html = get_image_tag( $id, '', '', '', 'medium' );
     1095        $image_html = preg_replace('|<img ([^>]+) />|', '<img $1 ' . 'srcset="image2x.jpg 2x" />', $image_html );
     1096
     1097        // The content filter should return the image unchanged.
     1098        $this->assertSame( $image_html, wp_make_content_images_responsive( $image_html ) );
     1099    }
    7401100}
Note: See TracChangeset for help on using the changeset viewer.