Make WordPress Core

Changeset 34855


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

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

New functions in media.php:

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

Modifies existing core functions:

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

Tests:

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

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

Location:
trunk
Files:
1 added
11 edited

Legend:

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

    r34711 r34855  
    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'      );
  • trunk/src/wp-includes/media.php

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

    r34828 r34855  
    9494    function create_object( $file, $parent = 0, $args = array() ) {
    9595        return wp_insert_attachment( $args, $file, $parent );
     96    }
     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;
    96125    }
    97126}
  • trunk/tests/phpunit/tests/media.php

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

    r34664 r34855  
    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        ) );
  • trunk/tests/phpunit/tests/xmlrpc/mw/editPost.php

    r34682 r34855  
    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
     
    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
  • trunk/tests/phpunit/tests/xmlrpc/mw/getPost.php

    r25002 r34855  
    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 );
  • trunk/tests/phpunit/tests/xmlrpc/mw/getRecentPosts.php

    r25002 r34855  
    4040        $this->assertEquals( 401, $result->code );
    4141    }
    42    
     42
    4343    function test_no_editable_posts() {
    4444        wp_delete_post( $this->post_id );
     
    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
  • trunk/tests/phpunit/tests/xmlrpc/mw/newPost.php

    r34681 r34855  
    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 );
  • trunk/tests/phpunit/tests/xmlrpc/wp/editPost.php

    r31983 r34855  
    114114        $this->assertEquals( $editor_id, $out->post_author );
    115115    }
    116    
     116
    117117    function test_post_thumbnail() {
    118118        add_theme_support( 'post-thumbnails' );
     
    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
     
    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
  • trunk/tests/phpunit/tests/xmlrpc/wp/newPost.php

    r34681 r34855  
    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 );
Note: See TracChangeset for help on using the changeset viewer.