WordPress.org

Make WordPress Core

Ticket #33641: 33641.2.patch

File 33641.2.patch, 40.7 KB (added by DrewAPicture, 6 years ago)

Docs / standards fixes

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

     
    129129add_filter( 'the_title', 'convert_chars' );
    130130add_filter( 'the_title', 'trim'          );
    131131
    132 add_filter( 'the_content', 'wptexturize'        );
    133 add_filter( 'the_content', 'convert_smilies'    );
    134 add_filter( 'the_content', 'convert_chars'      );
    135 add_filter( 'the_content', 'wpautop'            );
    136 add_filter( 'the_content', 'shortcode_unautop'  );
    137 add_filter( 'the_content', 'prepend_attachment' );
     132add_filter( 'the_content', 'wptexturize'                       );
     133add_filter( 'the_content', 'convert_smilies'                   );
     134add_filter( 'the_content', 'convert_chars'                     );
     135add_filter( 'the_content', 'wpautop'                           );
     136add_filter( 'the_content', 'shortcode_unautop'                 );
     137add_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

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

     
    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

     
    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() {
     
    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                }
     
    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                }
     
    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                }
     
    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                }
     
    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
     
    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
     
    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

     
    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

     
    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'] ) );
     129                $attachment_id = $this->factory->attachment->create_upload_object( $filename, $post_id );
    132130
    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 );
    140 
    141131                // add post thumbnail to post that does not have one
    142132                $post2 = array( 'wp_post_thumbnail' => $attachment_id );
    143133                $result = $this->myxmlrpcserver->mw_editPost( array( $post_id, 'author', 'author', $post2 ) );
     
    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

     
    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'] ) );
     98                $attachment_id = $this->factory->attachment->create_upload_object( $filename );
    10199
    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 );
    109 
    110100                set_post_thumbnail( $this->post_id, $attachment_id );
    111101
    112102                $fields = array( 'post' );
  • tests/phpunit/tests/xmlrpc/mw/getRecentPosts.php

     
    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
     
    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

     
    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'] ) );
     120                $attachment_id = $this->factory->attachment->create_upload_object( $filename );
    123121
    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'] );
    131 
    132122                $post = array( 'title' => 'Post Thumbnail Test', 'wp_post_thumbnail' => $attachment_id );
    133123                $result = $this->myxmlrpcserver->mw_newPost( array( 1, 'author', 'author', $post ) );
    134124                $this->assertNotInstanceOf( 'IXR_Error', $result );
  • tests/phpunit/tests/xmlrpc/wp/editPost.php

     
    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
     
    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'] ) );
     129                $attachment_id = $this->factory->attachment->create_upload_object( $filename, $post_id );
    132130
    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 );
    140 
    141131                // add post thumbnail to post that does not have one
    142132                $post2 = array( 'post_thumbnail' => $attachment_id );
    143133                $result = $this->myxmlrpcserver->wp_editPost( array( 1, 'author', 'author', $post_id, $post2 ) );
     
    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

     
    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'] ) );
     131                $attachment_id = $this->factory->attachment->create_upload_object( $filename );
    134132
    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'] );
    142 
    143133                $post = array( 'post_title' => 'Post Thumbnail Test', 'post_thumbnail' => $attachment_id );
    144134                $result = $this->myxmlrpcserver->wp_newPost( array( 1, 'author', 'author', $post ) );
    145135                $this->assertNotInstanceOf( 'IXR_Error', $result );