WordPress.org

Make WordPress Core

Ticket #33641: 33641.patch

File 33641.patch, 40.2 KB (added by joemcgill, 6 years ago)

First patch for #33641

  • src/wp-includes/default-filters.php

    diff --git src/wp-includes/default-filters.php src/wp-includes/default-filters.php
    index 30974c2..fbbf594 100644
    add_filter( 'the_content', 'convert_chars' ); 
    135135add_filter( 'the_content', 'wpautop'            );
    136136add_filter( 'the_content', 'shortcode_unautop'  );
    137137add_filter( 'the_content', 'prepend_attachment' );
     138add_filter( 'the_content', 'wp_make_content_images_responsive' );
    138139
    139140add_filter( 'the_excerpt',     'wptexturize'      );
    140141add_filter( 'the_excerpt',     'convert_smilies'  );
  • src/wp-includes/media.php

    diff --git src/wp-includes/media.php src/wp-includes/media.php
    index 44e18f4..3ffcb80 100644
    function wp_get_attachment_image($attachment_id, $size = 'thumbnail', $icon = fa 
    777777
    778778                $attr = wp_parse_args($attr, $default_attr);
    779779
     780                // Generate `srcset` and `sizes` if not already present.
     781                if ( empty( $attr['srcset'] ) && $srcset = wp_get_attachment_image_srcset( $attachment_id, $size ) ) {
     782                        $attr['srcset'] = $srcset;
     783                        $sizes_args = array(
     784                                'height' => $height,
     785                                'width'  => $width,
     786                        );
     787                        $attr['sizes'] = wp_get_attachment_image_sizes( $attachment_id, $size, $sizes_args );
     788                }
     789
    780790                /**
    781791                 * Filter the list of attachment image attributes.
    782792                 *
    function wp_get_attachment_image_url( $attachment_id, $size = 'thumbnail', $icon 
    815825}
    816826
    817827/**
     828 * Return an array of urls and pixel widths representing sizes of an image for
     829 * the purpose of populating a source set when creating responsive image markup.
     830 *
     831 * @since 4.4.0
     832 *
     833 * @param  int    $id   Image attachment ID.
     834 * @param  string $size Optional. Name of image size. Default value: 'medium'.
     835 * @return array|bool {
     836 *     Array image candidate values containing a url, descriptor type, and
     837 *     descriptor value. False if none exist.
     838 *
     839 *     @type array {
     840 *        @type string $url        An image 'url'.
     841 *        @type string $descriptor A width or density descriptor used in a srcset.
     842 *        @type int    $value      The descriptor value representing a width or
     843 *                                 or pixel density.
     844 *     }
     845 * }
     846 *
     847 */
     848function wp_get_attachment_image_srcset_array( $id, $size = 'medium' ) {
     849        // Get the intermediate size.
     850        $image = image_get_intermediate_size( $id, $size );
     851        // Get the post meta.
     852        if ( ! is_array( $img_meta = wp_get_attachment_metadata( $id ) ) ) {
     853                return false;
     854        }
     855
     856        // Extract the height and width from the intermediate or the full size.
     857        $img_width = ( $image ) ? $image['width'] : $img_meta['width'];
     858        $img_height = ( $image ) ? $image['height'] : $img_meta['height'];
     859
     860        // Bail early if the width isn't greater that zero.
     861        if ( ! $img_width > 0 ) {
     862                return false;
     863        }
     864
     865        // Use the url from the intermediate size or build the url from the metadata.
     866        if ( ! empty( $image['url'] ) ) {
     867                $img_url = $image['url'];
     868        } else {
     869                $uploads_dir = wp_upload_dir();
     870                $img_file = ( $image ) ? path_join( dirname( $img_meta['file'] ) , $image['file'] ) : $img_meta['file'];
     871                $img_url = $uploads_dir['baseurl'] . '/' . $img_file;
     872        }
     873
     874        $img_sizes = $img_meta['sizes'];
     875
     876        // Add full size to the img_sizes array.
     877        $img_sizes['full'] = array(
     878                'width'  => $img_meta['width'],
     879                'height' => $img_meta['height'],
     880                'file'   => wp_basename( $img_meta['file'] )
     881        );
     882
     883        // Calculate the image aspect ratio.
     884        $img_ratio = $img_height / $img_width;
     885
     886        /*
     887         * Images that have been edited in WordPress after being uploaded will
     888         * contain a unique hash. Look for that hash and use it later to filter
     889         * out images that are leftovers from previous versions.
     890         */
     891        $img_edited = preg_match( '/-e[0-9]{13}/', $img_url, $img_edit_hash );
     892
     893        /*
     894         * Set up arrays to hold url candidates and matched image sources so
     895         * we can avoid duplicates without looping through the full sources array
     896         */
     897        $candidates = $sources = array();
     898
     899        /*
     900         * Loop through available images and only use images that are resized
     901         * versions of the same rendition.
     902         */
     903        foreach ( $img_sizes as $img ) {
     904
     905                // Filter out images that are leftovers from previous renditions.
     906                if ( $img_edited && ! strpos( $img['file'], $img_edit_hash[0] ) ) {
     907                        continue;
     908                }
     909
     910                $candidate_url = path_join( dirname( $img_url ), $img['file'] );
     911
     912                // Calculate the new image ratio.
     913                $img_ratio_compare = $img['height'] / $img['width'];
     914
     915                // If the new ratio differs by less than 0.01, use it.
     916                if ( abs( $img_ratio - $img_ratio_compare ) < 0.01 && ! in_array( $candidate_url, $candidates ) ) {
     917                        // Add the URL to our list of candidates.
     918                        $candidates[] = $candidate_url;
     919                        // Add the url, descriptor, and value to the sources array to be returned.
     920                        $sources[] = array(
     921                                        'url'        => $candidate_url,
     922                                        'descriptor' => 'w',
     923                                        'value'      => $img['width'],
     924                                );
     925                }
     926        }
     927
     928        /**
     929         * Filter the output of wp_get_attachment_image_srcset_array().
     930         *
     931         * @since 4.4.0
     932         *
     933         * @param array        $sources  An array of image urls and widths.
     934         * @param int          $id       Attachment ID for image.
     935         * @param array|string $size     Size of image, either array or string.
     936         */
     937        return apply_filters( 'wp_get_attachment_image_srcset_array', $sources, $id, $size );
     938}
     939
     940/**
     941 * Get the value for the 'srcset' attribute.
     942 *
     943 * @since 4.4.0
     944 *
     945 * @param int    $id   Image attachment ID.
     946 * @param string $size Optional. Name of image size. Default value: 'medium'.
     947 * @return string|bool A 'srcset' value string or false.
     948 */
     949function wp_get_attachment_image_srcset( $id, $size = 'medium' ) {
     950        $srcset_array = wp_get_attachment_image_srcset_array( $id, $size );
     951
     952        // Only return a srcset value if there is more than one source.
     953        if ( count( $srcset_array ) <= 1 ) {
     954                return false;
     955        } else {
     956                $srcset = '';
     957                foreach ( $srcset_array as $source ) {
     958                        $srcset .= $source['url'] . ' ' . $source['value'] . $source['descriptor'] . ', ';
     959                }
     960        }
     961
     962        /**
     963         * Filter the output of wp_get_attachment_image_srcset().
     964         *
     965         * @since 4.4.0
     966         *
     967         * @param string       $srcset  A source set formated for a `srcset` attribute.
     968         * @param int          $id      Attachment ID for image.
     969         * @param array|string $size    Size of image, either array or string.
     970         */
     971        return apply_filters( 'wp_get_attachment_image_srcset', rtrim( $srcset, ', ' ), $id, $size );
     972}
     973
     974/**
     975 * Return a source size attribute for an image from an array of values.
     976 *
     977 * @since 4.4.0
     978 *
     979 * @param int    $id   Image attachment ID.
     980 * @param string $size Optional. Name of image size. Default value: 'medium'.
     981 * @param array  $args {
     982 *     Optional. Arguments to retrieve posts.
     983 *
     984 *     @type array|string $sizes An array or string containing of size information.
     985 *     @type int          $width A single width value used in the default `sizes` string.
     986 * }
     987 * @return string|bool A valid source size value for use in a 'sizes' attribute or false.
     988 */
     989function wp_get_attachment_image_sizes( $id, $size = 'medium', $args = null ) {
     990
     991        // Try to get the image width from `$args` before calling `image_downsize()`.
     992        if ( is_array( $args ) && ! empty( $args['width'] ) ) {
     993                $img_width = (int) $args['width'];
     994        } elseif ( $img = image_get_intermediate_size( $id, $size ) ) {
     995                list( $img_width, $img_height ) = image_constrain_size_for_editor( $img['width'], $img['height'], $size );
     996        }
     997
     998        // Bail early if `$image_width` isn't set.
     999        if ( ! $img_width ) {
     1000                return false;
     1001        }
     1002
     1003        // Set the image width in pixels.
     1004        $img_width = $img_width . 'px';
     1005
     1006        // Set up our default values.
     1007        $defaults = array(
     1008                'sizes' => array(
     1009                        array(
     1010                                'size_value' => '100vw',
     1011                                'mq_value'   => $img_width,
     1012                                'mq_name'    => 'max-width'
     1013                        ),
     1014                        array(
     1015                                'size_value' => $img_width
     1016                        ),
     1017                )
     1018        );
     1019
     1020        $args = wp_parse_args( $args, $defaults );
     1021
     1022        /**
     1023        * Filter arguments used to create 'sizes' attribute.
     1024        *
     1025        * @since 2.4.0
     1026        *
     1027        * @param array   $args  An array of arguments used to create a 'sizes' attribute.
     1028        * @param int     $id    Post ID of the original image.
     1029        * @param string  $size  Name of the image size being used.
     1030        */
     1031        $args = apply_filters( 'wp_image_sizes_args', $args, $id, $size );
     1032
     1033        // If sizes is passed as a string, just use the string.
     1034        if ( is_string( $args['sizes'] ) ) {
     1035                $size_list = $args['sizes'];
     1036
     1037        // Otherwise, breakdown the array and build a sizes string.
     1038        } elseif ( is_array( $args['sizes'] ) ) {
     1039
     1040                $size_list = '';
     1041
     1042                foreach ( $args['sizes'] as $size ) {
     1043
     1044                        // Use 100vw as the size value unless something else is specified.
     1045                        $size_value = ( $size['size_value'] ) ? $size['size_value'] : '100vw';
     1046
     1047                        // If a media length is specified, build the media query.
     1048                        if ( ! empty( $size['mq_value'] ) ) {
     1049
     1050                                $media_length = $size['mq_value'];
     1051
     1052                                // Use max-width as the media condition unless min-width is specified.
     1053                                $media_condition = ( ! empty( $size['mq_name'] ) ) ? $size['mq_name'] : 'max-width';
     1054
     1055                                // If a media_length was set, create the media query.
     1056                                $media_query = '(' . $media_condition . ": " . $media_length . ') ';
     1057
     1058                        } else {
     1059                                // If no media length was set, `$media_query` is blank.
     1060                                $media_query = '';
     1061                        }
     1062
     1063                        // Add to the source size list string.
     1064                        $size_list .= $media_query . $size_value . ', ';
     1065                }
     1066
     1067                // Remove the trailing comma and space from the end of the string.
     1068                $size_list = substr( $size_list, 0, -2 );
     1069        }
     1070
     1071        // Return the `sizes` value as `$size_list` or false.
     1072        return ( $size_list ) ? $size_list : false;
     1073}
     1074
     1075/**
     1076 * Filters images in post content to add 'srcset' and 'sizes'.
     1077 *
     1078 * @since 4.4.0
     1079 *
     1080 * @param string $content The raw post content to be filtered.
     1081 * @return string Converted content with 'srcset' and 'sizes' added to images.
     1082 */
     1083function wp_make_content_images_responsive( $content ) {
     1084        $images = get_media_embedded_in_content( $content, 'img' );
     1085
     1086        $attachment_ids = array();
     1087
     1088        foreach( $images as $image ) {
     1089                if ( preg_match( '/wp-image-([0-9]+)/i', $image, $class_id ) ) {
     1090                        (int) $attachment_id = $class_id[1];
     1091                        if ( $attachment_id ) {
     1092                                $attachment_ids[] = $attachment_id;
     1093                        }
     1094                }
     1095        }
     1096
     1097        if ( 0 < count( $attachment_ids ) ) {
     1098                /*
     1099                 * Warm object caches for use with wp_get_attachment_metadata.
     1100                 *
     1101                 * To avoid making a database call for each image, a single query
     1102                 * warms the object cache with the meta information for all images.
     1103                 */
     1104                _prime_post_caches( $attachment_ids, false, true );
     1105        }
     1106
     1107        foreach( $images as $image ) {
     1108                $content = str_replace( $image, wp_img_add_srcset_and_sizes( $image ), $content );
     1109        }
     1110
     1111        return $content;
     1112}
     1113
     1114/**
     1115 * Add srcset and sizes to an 'img' element.
     1116 *
     1117 * @since 4.4.0
     1118 *
     1119 * @param string $image An HTML 'img' element to be filtered.
     1120 * @return string Converted 'img' element with 'srcset' and 'sizes' added.
     1121 */
     1122function wp_img_add_srcset_and_sizes( $image ) {
     1123        // Return early if a 'srcset' attribute already exists.
     1124        if ( false !== strpos( $image, ' srcset="' ) ) {
     1125                return $image;
     1126        }
     1127
     1128        // Parse id, size, width, and height from the `img` element.
     1129        $id = preg_match( '/wp-image-([0-9]+)/i', $image, $match_id ) ? (int) $match_id[1] : false;
     1130        $size = preg_match( '/size-([^\s|"]+)/i', $image, $match_size ) ? $match_size[1] : false;
     1131        $width = preg_match( '/ width="([0-9]+)"/', $image, $match_width ) ? (int) $match_width[1] : false;
     1132        $height = preg_match( '/ height="([0-9]+)"/', $image, $match_height ) ? (int) $match_height[1] : false;
     1133
     1134        if ( $id && false === $size ) {
     1135                $size = array(
     1136                        $width,
     1137                        $height,
     1138                );
     1139        }
     1140
     1141        /*
     1142         * If attempts to parse the size value failed, attempt to use the image
     1143         * metadata to match the 'src' against the available sizes for an attachment.
     1144         */
     1145        if ( ! $size && ! empty( $id ) && is_array( $meta = wp_get_attachment_metadata( $id ) ) ) {
     1146                // Parse the image `src` value from the `img` element.
     1147                $src = preg_match( '/src="([^"]+)"/', $image, $match_src ) ? $match_src[1] : false;
     1148
     1149                // Return early if the `src` value is empty.
     1150                if ( ! $src ) {
     1151                        return $image;
     1152                }
     1153
     1154                /*
     1155                 * First, see if the file is the full size image. If not, we loop through
     1156                 * the intermediate sizes until we find a file that matches.
     1157                 */
     1158                $image_filename = wp_basename( $src );
     1159
     1160                if ( $image_filename === basename( $meta['file'] ) ) {
     1161                        $size = 'full';
     1162                } else {
     1163                        foreach( $meta['sizes'] as $image_size => $image_size_data ) {
     1164                                if ( $image_filename === $image_size_data['file'] ) {
     1165                                        $size = $image_size;
     1166                                        break;
     1167                                }
     1168                        }
     1169                }
     1170
     1171        }
     1172
     1173        // If we have an ID and size, try for 'srcset' and 'sizes' and update the markup.
     1174        if ( $id && $size && $srcset = wp_get_attachment_image_srcset( $id, $size ) ) {
     1175
     1176                /**
     1177                 * Pass the 'height' and 'width' to 'wp_get_attachment_image_sizes()' to avoid
     1178                 * recalculating the image size.
     1179                 */
     1180                $args = array(
     1181                        'height' => $height,
     1182                        'width'  => $width,
     1183                );
     1184                $sizes = wp_get_attachment_image_sizes( $id, $size, $args );
     1185
     1186                // Format the srcset and sizes string and escape attributes.
     1187                $srcset_and_sizes = sprintf( ' srcset="%s" sizes="%s"', esc_attr( $srcset ), esc_attr( $sizes) );
     1188
     1189                // Add srcset and sizes attributes to the image markup.
     1190                $image = preg_replace( '/<img ([^>]+)[\s?][\/?]>/', '<img $1' . $srcset_and_sizes . ' />', $image );
     1191        };
     1192
     1193        return $image;
     1194}
     1195
     1196/**
    8181197 * Adds a 'wp-post-image' class to post thumbnails. Internal use only.
    8191198 *
    8201199 * Uses the 'begin_fetch_post_thumbnail_html' and 'end_fetch_post_thumbnail_html' action hooks to
    function get_media_embedded_in_content( $content, $types = null ) { 
    33083687         * @since 4.2.0
    33093688         *
    33103689         * @param array $allowed_media_types An array of allowed media types. Default media types are
    3311          *                                   'audio', 'video', 'object', 'embed', and 'iframe'.
     3690         *                                   'audio', 'video', 'object', 'embed', 'iframe', and 'img'.
    33123691         */
    3313         $allowed_media_types = apply_filters( 'media_embedded_in_content_allowed_types', array( 'audio', 'video', 'object', 'embed', 'iframe' ) );
     3692        $allowed_media_types = apply_filters( 'media_embedded_in_content_allowed_types', array( 'audio', 'video', 'object', 'embed', 'iframe', 'img' ) );
    33143693
    33153694        if ( ! empty( $types ) ) {
    33163695                if ( ! is_array( $types ) ) {
  • tests/phpunit/includes/factory.php

    diff --git tests/phpunit/data/images/test-image-large.png tests/phpunit/data/images/test-image-large.png
    new file mode 100644
    index 0000000..828c4a6
    Binary files /dev/null and tests/phpunit/data/images/test-image-large.png differ
    diff --git tests/phpunit/includes/factory.php tests/phpunit/includes/factory.php
    index 20bad89..157e99d 100644
    class WP_UnitTest_Factory_For_Attachment extends WP_UnitTest_Factory_For_Post { 
    9494        function create_object( $file, $parent = 0, $args = array() ) {
    9595                return wp_insert_attachment( $args, $file, $parent );
    9696        }
     97
     98        function create_upload_object( $file, $parent = 0 ) {
     99                $contents = file_get_contents($file);
     100                $upload = wp_upload_bits(basename($file), null, $contents);
     101
     102                $type = '';
     103                if ( ! empty($upload['type']) ) {
     104                        $type = $upload['type'];
     105                } else {
     106                        $mime = wp_check_filetype( $upload['file'] );
     107                        if ($mime)
     108                                $type = $mime['type'];
     109                }
     110
     111                $attachment = array(
     112                        'post_title' => basename( $upload['file'] ),
     113                        'post_content' => '',
     114                        'post_type' => 'attachment',
     115                        'post_parent' => $parent,
     116                        'post_mime_type' => $type,
     117                        'guid' => $upload[ 'url' ],
     118                );
     119
     120                // Save the data
     121                $id = wp_insert_attachment( $attachment, $upload[ 'file' ], $parent );
     122                wp_update_attachment_metadata( $id, wp_generate_attachment_metadata( $id, $upload['file'] ) );
     123
     124                return $id;
     125        }
    97126}
    98127
    99128class WP_UnitTest_Factory_For_User extends WP_UnitTest_Factory_For_Thing {
  • tests/phpunit/tests/media.php

    diff --git tests/phpunit/tests/media.php tests/phpunit/tests/media.php
    index d51eb92..f4888af 100644
    CAP; 
    1818                $this->img_name = 'image.jpg';
    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
    2424        function test_img_caption_shortcode_added() {
    EOF; 
    288288                                'post_mime_type' => 'image/jpeg',
    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";
    294295                }
    EOF; 
    300301                                'post_mime_type' => 'image/jpeg',
    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";
    306308                }
    BLOB; 
    329331                                'post_mime_type' => 'image/jpeg',
    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";
    335338                }
    BLOB; 
    341344                                'post_mime_type' => 'image/jpeg',
    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";
    347351                }
    VIDEO; 
    501505                $this->assertArrayHasKey( 'test-size', $_wp_additional_image_sizes );
    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        }
    506512
    VIDEO; 
    520526        function test_has_image_size() {
    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        }
    525533
    EOF; 
    737745
    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}
  • tests/phpunit/tests/post/thumbnails.php

    diff --git tests/phpunit/tests/post/thumbnails.php tests/phpunit/tests/post/thumbnails.php
    index ee6a2dc..cc8f61f 100644
    class Tests_Post_Thumbnail_Template extends WP_UnitTestCase { 
    1313
    1414                $this->post          = $this->factory->post->create_and_get();
    1515                $file                = DIR_TESTDATA . '/images/canola.jpg';
    16                 $this->attachment_id = $this->factory->attachment->create_object( $file, $this->post->ID, array(
     16                $this->attachment_id = $this->factory->attachment->create_upload_object( $file, $this->post->ID, array(
    1717                        'post_mime_type' => 'image/jpeg',
    1818                ) );
    1919        }
  • tests/phpunit/tests/xmlrpc/mw/editPost.php

    diff --git tests/phpunit/tests/xmlrpc/mw/editPost.php tests/phpunit/tests/xmlrpc/mw/editPost.php
    index 1cadb0c..acafda3 100644
    class Tests_XMLRPC_mw_editPost extends WP_XMLRPC_UnitTestCase { 
    126126
    127127                // create attachment
    128128                $filename = ( DIR_TESTDATA.'/images/a2-small.jpg' );
    129                 $contents = file_get_contents( $filename );
    130                 $upload = wp_upload_bits( $filename, null, $contents );
    131                 $this->assertTrue( empty( $upload['error'] ) );
    132 
    133                 $attachment = array(
    134                         'post_title' => 'Post Thumbnail',
    135                         'post_type' => 'attachment',
    136                         'post_mime_type' => 'image/jpeg',
    137                         'guid' => $upload['url']
    138                 );
    139                 $attachment_id = wp_insert_attachment( $attachment, $upload['file'], $post_id );
     129                $attachment_id = $this->factory->attachment->create_upload_object( $filename, $post_id );
    140130
    141131                // add post thumbnail to post that does not have one
    142132                $post2 = array( 'wp_post_thumbnail' => $attachment_id );
    class Tests_XMLRPC_mw_editPost extends WP_XMLRPC_UnitTestCase { 
    151141                $this->assertEquals( $attachment_id, get_post_meta( $post_id, '_thumbnail_id', true ) );
    152142
    153143                // create another attachment
    154                 $attachment2 = array_merge( $attachment, array( 'title' => 'Post Thumbnail 2' ) );
    155                 $attachment2_id = wp_insert_attachment( $attachment2, $upload['file'], $post_id );
     144                $attachment2_id = $this->factory->attachment->create_upload_object( $filename, $post_id );
    156145
    157146                // change the post's post_thumbnail
    158147                $post4 = array( 'wp_post_thumbnail' => $attachment2_id );
  • tests/phpunit/tests/xmlrpc/mw/getPost.php

    diff --git tests/phpunit/tests/xmlrpc/mw/getPost.php tests/phpunit/tests/xmlrpc/mw/getPost.php
    index 60797a0..b5d80f8 100644
    class Tests_XMLRPC_mw_getPost extends WP_XMLRPC_UnitTestCase { 
    9595
    9696                // create attachment
    9797                $filename = ( DIR_TESTDATA.'/images/a2-small.jpg' );
    98                 $contents = file_get_contents( $filename );
    99                 $upload = wp_upload_bits( $filename, null, $contents );
    100                 $this->assertTrue( empty( $upload['error'] ) );
    101 
    102                 $attachment = array(
    103                         'post_title' => 'Post Thumbnail',
    104                         'post_type' => 'attachment',
    105                         'post_mime_type' => 'image/jpeg',
    106                         'guid' => $upload['url']
    107                 );
    108                 $attachment_id = wp_insert_attachment( $attachment, $upload['file'], $this->post_id );
     98                $attachment_id = $this->factory->attachment->create_upload_object( $filename );
    10999
    110100                set_post_thumbnail( $this->post_id, $attachment_id );
    111101
  • tests/phpunit/tests/xmlrpc/mw/getRecentPosts.php

    diff --git tests/phpunit/tests/xmlrpc/mw/getRecentPosts.php tests/phpunit/tests/xmlrpc/mw/getRecentPosts.php
    index 7ad89fd..0f046dc 100644
    class Tests_XMLRPC_mw_getRecentPosts extends WP_XMLRPC_UnitTestCase { 
    3939                $this->assertInstanceOf( 'IXR_Error', $result );
    4040                $this->assertEquals( 401, $result->code );
    4141        }
    42        
     42
    4343        function test_no_editable_posts() {
    4444                wp_delete_post( $this->post_id );
    4545
    class Tests_XMLRPC_mw_getRecentPosts extends WP_XMLRPC_UnitTestCase { 
    100100
    101101                // create attachment
    102102                $filename = ( DIR_TESTDATA.'/images/a2-small.jpg' );
    103                 $contents = file_get_contents( $filename );
    104                 $upload = wp_upload_bits( $filename, null, $contents );
    105                 $this->assertTrue( empty( $upload['error'] ) );
    106 
    107                 $attachment = array(
    108                         'post_title' => 'Post Thumbnail',
    109                         'post_type' => 'attachment',
    110                         'post_mime_type' => 'image/jpeg',
    111                         'guid' => $upload['url']
    112                 );
    113                 $attachment_id = wp_insert_attachment( $attachment, $upload['file'], $this->post_id );
     103                $attachment_id = $this->factory->attachment->create_upload_object( $filename, $this->post_id );
    114104                set_post_thumbnail( $this->post_id, $attachment_id );
    115105
    116106                $results = $this->myxmlrpcserver->mw_getRecentPosts( array( $this->post_id, 'author', 'author' ) );
  • tests/phpunit/tests/xmlrpc/mw/newPost.php

    diff --git tests/phpunit/tests/xmlrpc/mw/newPost.php tests/phpunit/tests/xmlrpc/mw/newPost.php
    index 41b591b..4e8d57a 100644
    class Tests_XMLRPC_mw_newPost extends WP_XMLRPC_UnitTestCase { 
    117117
    118118                // create attachment
    119119                $filename = ( DIR_TESTDATA.'/images/a2-small.jpg' );
    120                 $contents = file_get_contents( $filename );
    121                 $upload = wp_upload_bits( $filename, null, $contents );
    122                 $this->assertTrue( empty( $upload['error'] ) );
    123 
    124                 $attachment = array(
    125                         'post_title' => 'Post Thumbnail',
    126                         'post_type' => 'attachment',
    127                         'post_mime_type' => 'image/jpeg',
    128                         'guid' => $upload['url']
    129                 );
    130                 $attachment_id = wp_insert_attachment( $attachment, $upload['file'] );
     120                $attachment_id = $this->factory->attachment->create_upload_object( $filename );
    131121
    132122                $post = array( 'title' => 'Post Thumbnail Test', 'wp_post_thumbnail' => $attachment_id );
    133123                $result = $this->myxmlrpcserver->mw_newPost( array( 1, 'author', 'author', $post ) );
  • tests/phpunit/tests/xmlrpc/wp/editPost.php

    diff --git tests/phpunit/tests/xmlrpc/wp/editPost.php tests/phpunit/tests/xmlrpc/wp/editPost.php
    index 05a694f..538a409 100644
    class Tests_XMLRPC_wp_editPost extends WP_XMLRPC_UnitTestCase { 
    113113                $out = get_post( $post_id );
    114114                $this->assertEquals( $editor_id, $out->post_author );
    115115        }
    116        
     116
    117117        function test_post_thumbnail() {
    118118                add_theme_support( 'post-thumbnails' );
    119119
    class Tests_XMLRPC_wp_editPost extends WP_XMLRPC_UnitTestCase { 
    126126
    127127                // create attachment
    128128                $filename = ( DIR_TESTDATA.'/images/a2-small.jpg' );
    129                 $contents = file_get_contents( $filename );
    130                 $upload = wp_upload_bits( $filename, null, $contents );
    131                 $this->assertTrue( empty( $upload['error'] ) );
    132 
    133                 $attachment = array(
    134                         'post_title' => 'Post Thumbnail',
    135                         'post_type' => 'attachment',
    136                         'post_mime_type' => 'image/jpeg',
    137                         'guid' => $upload['url']
    138                 );
    139                 $attachment_id = wp_insert_attachment( $attachment, $upload['file'], $post_id );
     129                $attachment_id = $this->factory->attachment->create_upload_object( $filename, $post_id );
    140130
    141131                // add post thumbnail to post that does not have one
    142132                $post2 = array( 'post_thumbnail' => $attachment_id );
    class Tests_XMLRPC_wp_editPost extends WP_XMLRPC_UnitTestCase { 
    158148                $this->assertEquals( $attachment_id, get_post_meta( $post_id, '_thumbnail_id', true ) );
    159149
    160150                // create another attachment
    161                 $attachment2 = array_merge( $attachment, array( 'post_title' => 'Post Thumbnail 2' ) );
    162                 $attachment2_id = wp_insert_attachment( $attachment2, $upload['file'], $post_id );
     151                $attachment2_id = $this->factory->attachment->create_upload_object( $filename, $post_id );
    163152
    164153                // change the post's post_thumbnail
    165154                $post4 = array( 'post_thumbnail' => $attachment2_id );
  • tests/phpunit/tests/xmlrpc/wp/newPost.php

    diff --git tests/phpunit/tests/xmlrpc/wp/newPost.php tests/phpunit/tests/xmlrpc/wp/newPost.php
    index 9cc2d28..5f00ddb 100644
    class Tests_XMLRPC_wp_newPost extends WP_XMLRPC_UnitTestCase { 
    128128
    129129                // create attachment
    130130                $filename = ( DIR_TESTDATA.'/images/a2-small.jpg' );
    131                 $contents = file_get_contents( $filename );
    132                 $upload = wp_upload_bits( $filename, null, $contents );
    133                 $this->assertTrue( empty( $upload['error'] ) );
    134 
    135                 $attachment = array(
    136                         'post_title' => 'Post Thumbnail',
    137                         'post_type' => 'attachment',
    138                         'post_mime_type' => 'image/jpeg',
    139                         'guid' => $upload['url']
    140                 );
    141                 $attachment_id = wp_insert_attachment( $attachment, $upload['file'] );
     131                $attachment_id = $this->factory->attachment->create_upload_object( $filename );
    142132
    143133                $post = array( 'post_title' => 'Post Thumbnail Test', 'post_thumbnail' => $attachment_id );
    144134                $result = $this->myxmlrpcserver->wp_newPost( array( 1, 'author', 'author', $post ) );