wp_ajax_crop_image()WP 4.3.0

Handles cropping an image via AJAX.

Return

null. Nothing (null).

Usage

wp_ajax_crop_image();

Changelog

Since 4.3.0 Introduced.

wp_ajax_crop_image() code WP 6.4.3

function wp_ajax_crop_image() {
	$attachment_id = absint( $_POST['id'] );

	check_ajax_referer( 'image_editor-' . $attachment_id, 'nonce' );

	if ( empty( $attachment_id ) || ! current_user_can( 'edit_post', $attachment_id ) ) {
		wp_send_json_error();
	}

	$context = str_replace( '_', '-', $_POST['context'] );
	$data    = array_map( 'absint', $_POST['cropDetails'] );
	$cropped = wp_crop_image( $attachment_id, $data['x1'], $data['y1'], $data['width'], $data['height'], $data['dst_width'], $data['dst_height'] );

	if ( ! $cropped || is_wp_error( $cropped ) ) {
		wp_send_json_error( array( 'message' => __( 'Image could not be processed.' ) ) );
	}

	switch ( $context ) {
		case 'site-icon':
			require_once ABSPATH . 'wp-admin/includes/class-wp-site-icon.php';
			$wp_site_icon = new WP_Site_Icon();

			// Skip creating a new attachment if the attachment is a Site Icon.
			if ( get_post_meta( $attachment_id, '_wp_attachment_context', true ) == $context ) {

				// Delete the temporary cropped file, we don't need it.
				wp_delete_file( $cropped );

				// Additional sizes in wp_prepare_attachment_for_js().
				add_filter( 'image_size_names_choose', array( $wp_site_icon, 'additional_sizes' ) );
				break;
			}

			/** This filter is documented in wp-admin/includes/class-custom-image-header.php */
			$cropped    = apply_filters( 'wp_create_file_in_uploads', $cropped, $attachment_id ); // For replication.
			$attachment = $wp_site_icon->create_attachment_object( $cropped, $attachment_id );
			unset( $attachment['ID'] );

			// Update the attachment.
			add_filter( 'intermediate_image_sizes_advanced', array( $wp_site_icon, 'additional_sizes' ) );
			$attachment_id = $wp_site_icon->insert_attachment( $attachment, $cropped );
			remove_filter( 'intermediate_image_sizes_advanced', array( $wp_site_icon, 'additional_sizes' ) );

			// Additional sizes in wp_prepare_attachment_for_js().
			add_filter( 'image_size_names_choose', array( $wp_site_icon, 'additional_sizes' ) );
			break;

		default:
			/**
			 * Fires before a cropped image is saved.
			 *
			 * Allows to add filters to modify the way a cropped image is saved.
			 *
			 * @since 4.3.0
			 *
			 * @param string $context       The Customizer control requesting the cropped image.
			 * @param int    $attachment_id The attachment ID of the original image.
			 * @param string $cropped       Path to the cropped image file.
			 */
			do_action( 'wp_ajax_crop_image_pre_save', $context, $attachment_id, $cropped );

			/** This filter is documented in wp-admin/includes/class-custom-image-header.php */
			$cropped = apply_filters( 'wp_create_file_in_uploads', $cropped, $attachment_id ); // For replication.

			$parent_url      = wp_get_attachment_url( $attachment_id );
			$parent_basename = wp_basename( $parent_url );
			$url             = str_replace( $parent_basename, wp_basename( $cropped ), $parent_url );

			$size       = wp_getimagesize( $cropped );
			$image_type = ( $size ) ? $size['mime'] : 'image/jpeg';

			// Get the original image's post to pre-populate the cropped image.
			$original_attachment  = get_post( $attachment_id );
			$sanitized_post_title = sanitize_file_name( $original_attachment->post_title );
			$use_original_title   = (
				( '' !== trim( $original_attachment->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( $original_attachment->post_content ) );

			$attachment = array(
				'post_title'     => $use_original_title ? $original_attachment->post_title : wp_basename( $cropped ),
				'post_content'   => $use_original_description ? $original_attachment->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( $original_attachment->post_excerpt ) ) {
				$attachment['post_excerpt'] = $original_attachment->post_excerpt;
			}

			// Copy the image alt text attribute from the original image.
			if ( '' !== trim( $original_attachment->_wp_attachment_image_alt ) ) {
				$attachment['meta_input'] = array(
					'_wp_attachment_image_alt' => wp_slash( $original_attachment->_wp_attachment_image_alt ),
				);
			}

			$attachment_id = wp_insert_attachment( $attachment, $cropped );
			$metadata      = wp_generate_attachment_metadata( $attachment_id, $cropped );

			/**
			 * Filters the cropped image attachment metadata.
			 *
			 * @since 4.3.0
			 *
			 * @see wp_generate_attachment_metadata()
			 *
			 * @param array $metadata Attachment metadata.
			 */
			$metadata = apply_filters( 'wp_ajax_cropped_attachment_metadata', $metadata );
			wp_update_attachment_metadata( $attachment_id, $metadata );

			/**
			 * Filters the attachment ID for a cropped image.
			 *
			 * @since 4.3.0
			 *
			 * @param int    $attachment_id The attachment ID of the cropped image.
			 * @param string $context       The Customizer control requesting the cropped image.
			 */
			$attachment_id = apply_filters( 'wp_ajax_cropped_attachment_id', $attachment_id, $context );
	}

	wp_send_json_success( wp_prepare_attachment_for_js( $attachment_id ) );
}