wp/wp-admin/includes/image.php
changeset 21 48c4eec2b7e6
parent 19 3d72ae0968f4
child 22 8c2e4d02f4ef
--- 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