}
/**
- * Caches and returns the base URL of the uploads directory.
+ * Get the attachment path relative to the upload directory.
*
- * @since 4.4.0
+ * @since 4.4.1
* @access private
*
- * @return string The base URL, cached.
+ * @param string $file Attachment file name.
+ * @return string Attachment path relative to the upload directory.
*/
-function _wp_upload_dir_baseurl() {
- static $baseurl = array();
+function _wp_get_attachment_relative_path( $file ) {
+ $dirname = dirname( $file );
- $blog_id = get_current_blog_id();
+ if ( '.' === $dirname ) {
+ return '';
+ }
- if ( empty( $baseurl[$blog_id] ) ) {
- $uploads_dir = wp_upload_dir();
- $baseurl[$blog_id] = $uploads_dir['baseurl'];
+ if ( false !== strpos( $dirname, 'wp-content/uploads' ) ) {
+ // Get the directory name relative to the upload directory (back compat for pre-2.7 uploads)
+ $dirname = substr( $dirname, strpos( $dirname, 'wp-content/uploads' ) + 18 );
+ $dirname = ltrim( $dirname, '/' );
}
- return $baseurl[$blog_id];
+ return $dirname;
}
/**
* @return string|bool The 'srcset' attribute value. False on error or when only one source exists.
*/
function wp_calculate_image_srcset( $size_array, $image_src, $image_meta, $attachment_id = 0 ) {
- if ( empty( $image_meta['sizes'] ) ) {
+ /**
+ * Let plugins pre-filter the image meta to be able to fix inconsistencies in the stored data.
+ *
+ * @param array $image_meta The image meta data as returned by 'wp_get_attachment_metadata()'.
+ * @param array $size_array Array of width and height values in pixels (in that order).
+ * @param string $image_src The 'src' of the image.
+ * @param int $attachment_id The image attachment ID or 0 if not supplied.
+ */
+ $image_meta = apply_filters( 'wp_calculate_image_srcset_meta', $image_meta, $size_array, $image_src, $attachment_id );
+
+ if ( empty( $image_meta['sizes'] ) || ! isset( $image_meta['file'] ) || strlen( $image_meta['file'] ) < 4 ) {
return false;
}
}
$image_basename = wp_basename( $image_meta['file'] );
- $image_baseurl = _wp_upload_dir_baseurl();
/*
* WordPress flattens animated GIFs into one frame when generating intermediate sizes.
return false;
}
- // Uploads are (or have been) in year/month sub-directories.
- if ( $image_basename !== $image_meta['file'] ) {
- $dirname = dirname( $image_meta['file'] );
+ // Retrieve the uploads sub-directory from the full size image.
+ $dirname = _wp_get_attachment_relative_path( $image_meta['file'] );
- if ( $dirname !== '.' ) {
- $image_baseurl = trailingslashit( $image_baseurl ) . $dirname;
- }
+ if ( $dirname ) {
+ $dirname = trailingslashit( $dirname );
}
- $image_baseurl = trailingslashit( $image_baseurl );
+ $upload_dir = wp_get_upload_dir();
+ $image_baseurl = trailingslashit( $upload_dir['baseurl'] ) . $dirname;
- // Calculate the image aspect ratio.
- $image_ratio = $image_height / $image_width;
+ /*
+ * If currently on HTTPS, prefer HTTPS URLs when we know they're supported by the domain
+ * (which is to say, when they share the domain name of the current request).
+ */
+ if ( is_ssl() && 'https' !== substr( $image_baseurl, 0, 5 ) && parse_url( $image_baseurl, PHP_URL_HOST ) === $_SERVER['HTTP_HOST'] ) {
+ $image_baseurl = set_url_scheme( $image_baseurl, 'https' );
+ }
/*
* Images that have been edited in WordPress after being uploaded will
// Array to hold URL candidates.
$sources = array();
+ /**
+ * To make sure the ID matches our image src, we will check to see if any sizes in our attachment
+ * meta match our $image_src. If no matches are found we don't return a srcset to avoid serving
+ * an incorrect image. See #35045.
+ */
+ $src_matched = false;
+
/*
* Loop through available images. Only use images that are resized
* versions of the same edit.
*/
foreach ( $image_sizes as $image ) {
+ $is_src = false;
+
+ // Check if image meta isn't corrupted.
+ if ( ! is_array( $image ) ) {
+ continue;
+ }
+
+ // If the file name is part of the `src`, we've confirmed a match.
+ if ( ! $src_matched && false !== strpos( $image_src, $dirname . $image['file'] ) ) {
+ $src_matched = $is_src = true;
+ }
// Filter out images that are from previous edits.
if ( $image_edited && ! strpos( $image['file'], $image_edit_hash[0] ) ) {
continue;
}
- // Filter out images that are wider than '$max_srcset_image_width'.
- if ( $max_srcset_image_width && $image['width'] > $max_srcset_image_width ) {
+ /*
+ * Filter out images that are wider than '$max_srcset_image_width' unless
+ * that file is in the 'src' attribute.
+ */
+ if ( $max_srcset_image_width && $image['width'] > $max_srcset_image_width && ! $is_src ) {
continue;
}
- // Calculate the new image ratio.
- if ( $image['width'] ) {
- $image_ratio_compare = $image['height'] / $image['width'];
+ /**
+ * To check for varying crops, we calculate the expected size of the smaller
+ * image if the larger were constrained by the width of the smaller and then
+ * see if it matches what we're expecting.
+ */
+ if ( $image_width > $image['width'] ) {
+ $constrained_size = wp_constrain_dimensions( $image_width, $image_height, $image['width'] );
+ $expected_size = array( $image['width'], $image['height'] );
} else {
- $image_ratio_compare = 0;
+ $constrained_size = wp_constrain_dimensions( $image['width'], $image['height'], $image_width );
+ $expected_size = array( $image_width, $image_height );
}
- // If the new ratio differs by less than 0.002, use it.
- if ( abs( $image_ratio - $image_ratio_compare ) < 0.002 ) {
+ // If the image dimensions are within 1px of the expected size, use it.
+ if ( abs( $constrained_size[0] - $expected_size[0] ) <= 1 && abs( $constrained_size[1] - $expected_size[1] ) <= 1 ) {
// Add the URL, descriptor, and value to the sources array to be returned.
- $sources[ $image['width'] ] = array(
+ $source = array(
'url' => $image_baseurl . $image['file'],
'descriptor' => 'w',
'value' => $image['width'],
);
+
+ // The 'src' image has to be the first in the 'srcset', because of a bug in iOS8. See #35030.
+ if ( $is_src ) {
+ $sources = array( $image['width'] => $source ) + $sources;
+ } else {
+ $sources[ $image['width'] ] = $source;
+ }
}
}
$sources = apply_filters( 'wp_calculate_image_srcset', $sources, $size_array, $image_src, $image_meta, $attachment_id );
// Only return a 'srcset' value if there is more than one source.
- if ( count( $sources ) < 2 ) {
+ if ( ! $src_matched || count( $sources ) < 2 ) {
return false;
}
return $image;
}
- $base_url = trailingslashit( _wp_upload_dir_baseurl() );
- $image_base_url = $base_url;
-
- $dirname = dirname( $image_meta['file'] );
- if ( $dirname !== '.' ) {
- $image_base_url .= trailingslashit( $dirname );
- }
-
- $all_sizes = wp_list_pluck( $image_meta['sizes'], 'file' );
-
- foreach ( $all_sizes as $key => $file ) {
- $all_sizes[ $key ] = $image_base_url . $file;
- }
-
- // Add the original image.
- $all_sizes[] = $base_url . $image_meta['file'];
-
- // Bail early if the image src doesn't match any of the known image sizes.
- if ( ! in_array( $image_src, $all_sizes ) ) {
- return $image;
- }
-
$width = preg_match( '/ width="([0-9]+)"/', $image, $match_width ) ? (int) $match_width[1] : 0;
$height = preg_match( '/ height="([0-9]+)"/', $image, $match_height ) ? (int) $match_height[1] : 0;
* @type string $src URL to the source of the audio file. Default empty.
* @type string $loop The 'loop' attribute for the `<audio>` element. Default empty.
* @type string $autoplay The 'autoplay' attribute for the `<audio>` element. Default empty.
- * @type string $preload The 'preload' attribute for the `<audio>` element. Default empty.
+ * @type string $preload The 'preload' attribute for the `<audio>` element. Default 'none'.
* @type string $class The 'class' attribute for the `<audio>` element. Default 'wp-audio-shortcode'.
- * @type string $style The 'style' attribute for the `<audio>` element. Default 'width: 100%'.
+ * @type string $style The 'style' attribute for the `<audio>` element. Default 'width: 100%; visibility: hidden;'.
* }
* @param string $content Shortcode content.
* @return string|void HTML content to display audio.
'src' => '',
'loop' => '',
'autoplay' => '',
- 'preload' => 'none'
+ 'preload' => 'none',
+ 'class' => 'wp-audio-shortcode',
+ 'style' => 'width: 100%; visibility: hidden;'
);
foreach ( $default_types as $type ) {
$defaults_atts[$type] = '';
*
* @param string $class CSS class or list of space-separated classes.
*/
+ $atts['class'] = apply_filters( 'wp_audio_shortcode_class', $atts['class'] );
+
$html_atts = array(
- 'class' => apply_filters( 'wp_audio_shortcode_class', 'wp-audio-shortcode' ),
+ 'class' => $atts['class'],
'id' => sprintf( 'audio-%d-%d', $post_id, $instance ),
'loop' => wp_validate_boolean( $atts['loop'] ),
'autoplay' => wp_validate_boolean( $atts['autoplay'] ),
'preload' => $atts['preload'],
- 'style' => 'width: 100%; visibility: hidden;',
+ 'style' => $atts['style'],
);
// These ones should just be omitted altogether if they are blank
'preload' => 'metadata',
'width' => 640,
'height' => 360,
+ 'class' => 'wp-video-shortcode',
);
foreach ( $default_types as $type ) {
*
* @param string $class CSS class or list of space-separated classes.
*/
+ $atts['class'] = apply_filters( 'wp_video_shortcode_class', $atts['class'] );
+
$html_atts = array(
- 'class' => apply_filters( 'wp_video_shortcode_class', 'wp-video-shortcode' ),
+ 'class' => $atts['class'],
'id' => sprintf( 'video-%d-%d', $post_id, $instance ),
'width' => absint( $atts['width'] ),
'height' => absint( $atts['height'] ),
'type' => $type,
'subtype' => $subtype,
'icon' => wp_mime_type_icon( $attachment->ID ),
- 'dateFormatted' => mysql2date( get_option('date_format'), $attachment->post_date ),
+ 'dateFormatted' => mysql2date( __( 'F j, Y' ), $attachment->post_date ),
'nonces' => array(
'update' => false,
'delete' => false,
'filterByDate' => __( 'Filter by date' ),
'filterByType' => __( 'Filter by type' ),
'searchMediaLabel' => __( 'Search Media' ),
- 'noMedia' => __( 'No media attachments found.' ),
+ 'noMedia' => __( 'No media files found.' ),
// Library Details
'attachmentDetails' => __( 'Attachment Details' ),
function attachment_url_to_postid( $url ) {
global $wpdb;
- $dir = wp_upload_dir();
+ $dir = wp_get_upload_dir();
$path = $url;
$site_url = parse_url( $dir['url'] );