diff -r 7b1b88e27a20 -r 48c4eec2b7e6 wp/wp-admin/includes/image.php --- a/wp/wp-admin/includes/image.php Thu Sep 29 08:06:27 2022 +0200 +++ b/wp/wp-admin/includes/image.php Fri Sep 05 18:40:08 2025 +0200 @@ -28,8 +28,10 @@ $src_file = get_attached_file( $src ); if ( ! file_exists( $src_file ) ) { - // If the file doesn't exist, attempt a URL fopen on the src link. - // This can occur with certain file replication plugins. + /* + * If the file doesn't exist, attempt a URL fopen on the src link. + * This can occur with certain file replication plugins. + */ $src = _load_image_to_edit_path( $src, 'full' ); } else { $src = $src_file; @@ -159,8 +161,10 @@ $image_file = wp_get_original_image_path( $attachment_id ); if ( empty( $image_meta ) || ! is_array( $image_meta ) ) { - // Previously failed upload? - // If there is an uploaded file, make all sub-sizes and generate all of the attachment meta. + /* + * Previously failed upload? + * If there is an uploaded file, make all sub-sizes and generate all of the attachment meta. + */ if ( ! empty( $image_file ) ) { $image_meta = wp_create_image_subsizes( $image_file, $attachment_id ); } else { @@ -190,6 +194,7 @@ * Updates the attached file and image meta data when the original image was edited. * * @since 5.3.0 + * @since 6.0.0 The `$filesize` value was added to the returned array. * @access private * * @param array $saved_data The data returned from WP_Image_Editor after successfully saving an image. @@ -211,12 +216,12 @@ // Make the file path relative to the upload dir. $image_meta['file'] = _wp_relative_upload_path( $new_file ); + // Add image file size. + $image_meta['filesize'] = wp_filesize( $new_file ); + // Store the original image file name in image_meta. $image_meta['original_image'] = wp_basename( $original_file ); - // Add image file size. - $image_meta['filesize'] = wp_filesize( $new_file ); - return $image_meta; } @@ -282,8 +287,10 @@ */ $threshold = (int) apply_filters( 'big_image_size_threshold', 2560, $imagesize, $file, $attachment_id ); - // If the original image's dimensions are over the threshold, - // scale the image and use it as the "full" size. + /* + * If the original image's dimensions are over the threshold, + * scale the image and use it as the "full" size. + */ if ( $threshold && ( $image_meta['width'] > $threshold || $image_meta['height'] > $threshold ) ) { $editor = wp_get_image_editor( $file ); @@ -303,8 +310,10 @@ } if ( ! is_wp_error( $resized ) ) { - // Append "-scaled" to the image file name. It will look like "my_image-scaled.jpg". - // This doesn't affect the sub-sizes names as they are generated from the original image (for best quality). + /* + * Append "-scaled" to the image file name. It will look like "my_image-scaled.jpg". + * This doesn't affect the sub-sizes names as they are generated from the original image (for best quality). + */ $saved = $editor->save( $editor->generate_filename( 'scaled' ) ); if ( ! is_wp_error( $saved ) ) { @@ -474,9 +483,66 @@ } /** - * Generate attachment meta data and create image sub-sizes for images. + * Copy parent attachment properties to newly cropped image. + * + * @since 6.5.0 + * + * @param string $cropped Path to the cropped image file. + * @param int $parent_attachment_id Parent file Attachment ID. + * @param string $context Control calling the function. + * @return array Properties of attachment. + */ +function wp_copy_parent_attachment_properties( $cropped, $parent_attachment_id, $context = '' ) { + $parent = get_post( $parent_attachment_id ); + $parent_url = wp_get_attachment_url( $parent->ID ); + $parent_basename = wp_basename( $parent_url ); + $url = str_replace( wp_basename( $parent_url ), wp_basename( $cropped ), $parent_url ); + + $size = wp_getimagesize( $cropped ); + $image_type = $size ? $size['mime'] : 'image/jpeg'; + + $sanitized_post_title = sanitize_file_name( $parent->post_title ); + $use_original_title = ( + ( '' !== trim( $parent->post_title ) ) && + /* + * Check if the original image has a title other than the "filename" default, + * meaning the image had a title when originally uploaded or its title was edited. + */ + ( $parent_basename !== $sanitized_post_title ) && + ( pathinfo( $parent_basename, PATHINFO_FILENAME ) !== $sanitized_post_title ) + ); + $use_original_description = ( '' !== trim( $parent->post_content ) ); + + $attachment = array( + 'post_title' => $use_original_title ? $parent->post_title : wp_basename( $cropped ), + 'post_content' => $use_original_description ? $parent->post_content : $url, + 'post_mime_type' => $image_type, + 'guid' => $url, + 'context' => $context, + ); + + // Copy the image caption attribute (post_excerpt field) from the original image. + if ( '' !== trim( $parent->post_excerpt ) ) { + $attachment['post_excerpt'] = $parent->post_excerpt; + } + + // Copy the image alt text attribute from the original image. + if ( '' !== trim( $parent->_wp_attachment_image_alt ) ) { + $attachment['meta_input'] = array( + '_wp_attachment_image_alt' => wp_slash( $parent->_wp_attachment_image_alt ), + ); + } + + $attachment['post_parent'] = $parent_attachment_id; + + return $attachment; +} + +/** + * Generates attachment meta data and create image sub-sizes for images. * * @since 2.1.0 + * @since 6.0.0 The `$filesize` value was added to the returned array. * * @param int $attachment_id Attachment ID to process. * @param string $file Filepath of the attached image. @@ -657,7 +723,7 @@ } /** - * Convert a fraction string to a decimal. + * Converts a fraction string to a decimal. * * @since 2.5.0 * @@ -690,7 +756,7 @@ } // The denominator must not be zero. - if ( 0 == $denominator ) { // phpcs:ignore WordPress.PHP.StrictComparisons.LooseComparison -- Deliberate loose comparison. + if ( 0 == $denominator ) { // phpcs:ignore Universal.Operators.StrictComparisons.LooseEqual -- Deliberate loose comparison. return 0; } @@ -698,7 +764,7 @@ } /** - * Convert the exif date format to a unix timestamp. + * Converts the exif date format to a unix timestamp. * * @since 2.5.0 * @@ -713,7 +779,7 @@ } /** - * Get extended image metadata, exif or iptc as available. + * Gets extended image metadata, exif or iptc as available. * * Retrieves the EXIF metadata aperture, credit, camera, caption, copyright, iso * created_timestamp, focal_length, shutter_speed, and title. @@ -772,7 +838,7 @@ ) { $iptc = iptcparse( $info['APP13'] ); } else { - // phpcs:ignore WordPress.PHP.NoSilencedErrors -- Silencing notice and warning is intentional. See https://core.trac.wordpress.org/ticket/42480 + // Silencing notice and warning is intentional. See https://core.trac.wordpress.org/ticket/42480 $iptc = @iptcparse( $info['APP13'] ); } @@ -845,7 +911,7 @@ ) { $exif = exif_read_data( $file ); } else { - // phpcs:ignore WordPress.PHP.NoSilencedErrors -- Silencing notice and warning is intentional. See https://core.trac.wordpress.org/ticket/42480 + // Silencing notice and warning is intentional. See https://core.trac.wordpress.org/ticket/42480 $exif = @exif_read_data( $file ); } @@ -853,22 +919,51 @@ $exif = array(); } + $exif_description = ''; + $exif_usercomment = ''; if ( ! empty( $exif['ImageDescription'] ) ) { + $exif_description = trim( $exif['ImageDescription'] ); + } + + if ( ! empty( $exif['COMPUTED']['UserComment'] ) ) { + $exif_usercomment = trim( $exif['COMPUTED']['UserComment'] ); + } + + if ( $exif_description ) { mbstring_binary_safe_encoding(); - $description_length = strlen( $exif['ImageDescription'] ); + $description_length = strlen( $exif_description ); reset_mbstring_encoding(); - if ( empty( $meta['title'] ) && $description_length < 80 ) { // Assume the title is stored in ImageDescription. - $meta['title'] = trim( $exif['ImageDescription'] ); + $meta['title'] = $exif_description; } - if ( empty( $meta['caption'] ) && ! empty( $exif['COMPUTED']['UserComment'] ) ) { - $meta['caption'] = trim( $exif['COMPUTED']['UserComment'] ); + // If both user comments and description are present. + if ( empty( $meta['caption'] ) && $exif_description && $exif_usercomment ) { + if ( ! empty( $meta['title'] ) && $exif_description === $meta['title'] ) { + $caption = $exif_usercomment; + } else { + if ( $exif_description === $exif_usercomment ) { + $caption = $exif_description; + } else { + $caption = trim( $exif_description . ' ' . $exif_usercomment ); + } + } + $meta['caption'] = $caption; + } + + if ( empty( $meta['caption'] ) && $exif_usercomment ) { + $meta['caption'] = $exif_usercomment; } if ( empty( $meta['caption'] ) ) { - $meta['caption'] = trim( $exif['ImageDescription'] ); + $meta['caption'] = $exif_description; + } + } elseif ( empty( $meta['caption'] ) && $exif_usercomment ) { + $meta['caption'] = $exif_usercomment; + $description_length = strlen( $exif_usercomment ); + if ( empty( $meta['title'] ) && $description_length < 80 ) { + $meta['title'] = trim( $exif_usercomment ); } } elseif ( empty( $meta['caption'] ) && ! empty( $exif['Comments'] ) ) { $meta['caption'] = trim( $exif['Comments'] ); @@ -943,11 +1038,10 @@ * @param array $exif EXIF data. */ return apply_filters( 'wp_read_image_metadata', $meta, $file, $image_type, $iptc, $exif ); - } /** - * Validate that file is an image. + * Validates that file is an image. * * @since 2.5.0 * @@ -960,7 +1054,7 @@ } /** - * Validate that file is suitable for displaying within a web page. + * Validates that file is suitable for displaying within a web page. * * @since 2.5.0 * @@ -968,7 +1062,7 @@ * @return bool True if suitable, false if not suitable. */ function file_is_displayable_image( $path ) { - $displayable_image_types = array( IMAGETYPE_GIF, IMAGETYPE_JPEG, IMAGETYPE_PNG, IMAGETYPE_BMP, IMAGETYPE_ICO, IMAGETYPE_WEBP ); + $displayable_image_types = array( IMAGETYPE_GIF, IMAGETYPE_JPEG, IMAGETYPE_PNG, IMAGETYPE_BMP, IMAGETYPE_ICO, IMAGETYPE_WEBP, IMAGETYPE_AVIF ); $info = wp_getimagesize( $path ); if ( empty( $info ) ) { @@ -991,7 +1085,7 @@ } /** - * Load an image resource for editing. + * Loads an image resource for editing. * * @since 2.9.0 * @@ -1052,7 +1146,7 @@ } /** - * Retrieve the path or URL of an attachment's attached file. + * Retrieves the path or URL of an attachment's attached file. * * If the attached file is not present on the local filesystem (usually due to replication plugins), * then the URL of the file is returned if `allow_url_fopen` is supported. @@ -1120,7 +1214,7 @@ } /** - * Copy an existing image file. + * Copies an existing image file. * * @since 3.4.0 * @access private