diff -r 34716fd837a4 -r be944660c56a wp/wp-includes/rest-api/endpoints/class-wp-rest-attachments-controller.php --- a/wp/wp-includes/rest-api/endpoints/class-wp-rest-attachments-controller.php Tue Dec 15 15:52:01 2020 +0100 +++ b/wp/wp-includes/rest-api/endpoints/class-wp-rest-attachments-controller.php Wed Sep 21 18:19:35 2022 +0200 @@ -34,7 +34,7 @@ 'permission_callback' => array( $this, 'post_process_item_permissions_check' ), 'args' => array( 'id' => array( - 'description' => __( 'Unique identifier for the object.' ), + 'description' => __( 'Unique identifier for the attachment.' ), 'type' => 'integer', ), 'action' => array( @@ -191,6 +191,8 @@ */ do_action( 'rest_after_insert_attachment', $attachment, $request, true ); + wp_after_insert_post( $attachment, false, null ); + if ( defined( 'REST_REQUEST' ) && REST_REQUEST ) { // Set a custom header with the attachment_id. // Used by the browser/client to resume creating image sub-sizes after a PHP fatal error. @@ -270,7 +272,7 @@ } // $post_parent is inherited from $attachment['post_parent']. - $id = wp_insert_attachment( wp_slash( (array) $attachment ), $file, 0, true ); + $id = wp_insert_attachment( wp_slash( (array) $attachment ), $file, 0, true, false ); if ( is_wp_error( $id ) ) { if ( 'db_update_error' === $id->get_error_code() ) { @@ -319,7 +321,8 @@ ); } - $response = parent::update_item( $request ); + $attachment_before = get_post( $request['id'] ); + $response = parent::update_item( $request ); if ( is_wp_error( $response ) ) { return $response; @@ -345,6 +348,8 @@ /** This action is documented in wp-includes/rest-api/endpoints/class-wp-rest-attachments-controller.php */ do_action( 'rest_after_insert_attachment', $attachment, $request, false ); + wp_after_insert_post( $attachment, true, $attachment_before ); + $response = $this->prepare_item_for_response( $attachment, $request ); $response = rest_ensure_response( $response ); @@ -433,7 +438,7 @@ ); } - $supported_types = array( 'image/jpeg', 'image/png', 'image/gif' ); + $supported_types = array( 'image/jpeg', 'image/png', 'image/gif', 'image/webp' ); $mime_type = get_post_mime_type( $attachment_id ); if ( ! in_array( $mime_type, $supported_types, true ) ) { return new WP_Error( @@ -443,25 +448,40 @@ ); } - // Check if we need to do anything. - $rotate = 0; - $crop = false; + // The `modifiers` param takes precedence over the older format. + if ( isset( $request['modifiers'] ) ) { + $modifiers = $request['modifiers']; + } else { + $modifiers = array(); - if ( ! empty( $request['rotation'] ) ) { - // Rotation direction: clockwise vs. counter clockwise. - $rotate = 0 - (int) $request['rotation']; - } + if ( ! empty( $request['rotation'] ) ) { + $modifiers[] = array( + 'type' => 'rotate', + 'args' => array( + 'angle' => $request['rotation'], + ), + ); + } - if ( isset( $request['x'], $request['y'], $request['width'], $request['height'] ) ) { - $crop = true; - } + if ( isset( $request['x'], $request['y'], $request['width'], $request['height'] ) ) { + $modifiers[] = array( + 'type' => 'crop', + 'args' => array( + 'left' => $request['x'], + 'top' => $request['y'], + 'width' => $request['width'], + 'height' => $request['height'], + ), + ); + } - if ( ! $rotate && ! $crop ) { - return new WP_Error( - 'rest_image_not_edited', - __( 'The image was not edited. Edit the image before applying the changes.' ), - array( 'status' => 400 ) - ); + if ( 0 === count( $modifiers ) ) { + return new WP_Error( + 'rest_image_not_edited', + __( 'The image was not edited. Edit the image before applying the changes.' ), + array( 'status' => 400 ) + ); + } } /* @@ -484,34 +504,49 @@ ); } - if ( 0 !== $rotate ) { - $result = $image_editor->rotate( $rotate ); + foreach ( $modifiers as $modifier ) { + $args = $modifier['args']; + switch ( $modifier['type'] ) { + case 'rotate': + // Rotation direction: clockwise vs. counter clockwise. + $rotate = 0 - $args['angle']; + + if ( 0 !== $rotate ) { + $result = $image_editor->rotate( $rotate ); - if ( is_wp_error( $result ) ) { - return new WP_Error( - 'rest_image_rotation_failed', - __( 'Unable to rotate this image.' ), - array( 'status' => 500 ) - ); - } - } + if ( is_wp_error( $result ) ) { + return new WP_Error( + 'rest_image_rotation_failed', + __( 'Unable to rotate this image.' ), + array( 'status' => 500 ) + ); + } + } + + break; - if ( $crop ) { - $size = $image_editor->get_size(); + case 'crop': + $size = $image_editor->get_size(); - $crop_x = round( ( $size['width'] * floatval( $request['x'] ) ) / 100.0 ); - $crop_y = round( ( $size['height'] * floatval( $request['y'] ) ) / 100.0 ); - $width = round( ( $size['width'] * floatval( $request['width'] ) ) / 100.0 ); - $height = round( ( $size['height'] * floatval( $request['height'] ) ) / 100.0 ); + $crop_x = round( ( $size['width'] * $args['left'] ) / 100.0 ); + $crop_y = round( ( $size['height'] * $args['top'] ) / 100.0 ); + $width = round( ( $size['width'] * $args['width'] ) / 100.0 ); + $height = round( ( $size['height'] * $args['height'] ) / 100.0 ); + + if ( $size['width'] !== $width && $size['height'] !== $height ) { + $result = $image_editor->crop( $crop_x, $crop_y, $width, $height ); - $result = $image_editor->crop( $crop_x, $crop_y, $width, $height ); + if ( is_wp_error( $result ) ) { + return new WP_Error( + 'rest_image_crop_failed', + __( 'Unable to crop this image.' ), + array( 'status' => 500 ) + ); + } + } - if ( is_wp_error( $result ) ) { - return new WP_Error( - 'rest_image_crop_failed', - __( 'Unable to crop this image.' ), - array( 'status' => 500 ) - ); + break; + } } @@ -853,12 +888,12 @@ ), 'properties' => array( 'raw' => array( - 'description' => __( 'Description for the object, as it exists in the database.' ), + 'description' => __( 'Description for the attachment, as it exists in the database.' ), 'type' => 'string', 'context' => array( 'edit' ), ), 'rendered' => array( - 'description' => __( 'HTML description for the object, transformed for display.' ), + 'description' => __( 'HTML description for the attachment, transformed for display.' ), 'type' => 'string', 'context' => array( 'view', 'edit' ), 'readonly' => true, @@ -1281,44 +1316,120 @@ */ protected function get_edit_media_item_args() { return array( - 'rotation' => array( - 'description' => __( 'The amount to rotate the image clockwise in degrees.' ), + 'src' => array( + 'description' => __( 'URL to the edited image file.' ), + 'type' => 'string', + 'format' => 'uri', + 'required' => true, + ), + 'modifiers' => array( + 'description' => __( 'Array of image edits.' ), + 'type' => 'array', + 'minItems' => 1, + 'items' => array( + 'description' => __( 'Image edit.' ), + 'type' => 'object', + 'required' => array( + 'type', + 'args', + ), + 'oneOf' => array( + array( + 'title' => __( 'Rotation' ), + 'properties' => array( + 'type' => array( + 'description' => __( 'Rotation type.' ), + 'type' => 'string', + 'enum' => array( 'rotate' ), + ), + 'args' => array( + 'description' => __( 'Rotation arguments.' ), + 'type' => 'object', + 'required' => array( + 'angle', + ), + 'properties' => array( + 'angle' => array( + 'description' => __( 'Angle to rotate clockwise in degrees.' ), + 'type' => 'number', + ), + ), + ), + ), + ), + array( + 'title' => __( 'Crop' ), + 'properties' => array( + 'type' => array( + 'description' => __( 'Crop type.' ), + 'type' => 'string', + 'enum' => array( 'crop' ), + ), + 'args' => array( + 'description' => __( 'Crop arguments.' ), + 'type' => 'object', + 'required' => array( + 'left', + 'top', + 'width', + 'height', + ), + 'properties' => array( + 'left' => array( + 'description' => __( 'Horizontal position from the left to begin the crop as a percentage of the image width.' ), + 'type' => 'number', + ), + 'top' => array( + 'description' => __( 'Vertical position from the top to begin the crop as a percentage of the image height.' ), + 'type' => 'number', + ), + 'width' => array( + 'description' => __( 'Width of the crop as a percentage of the image width.' ), + 'type' => 'number', + ), + 'height' => array( + 'description' => __( 'Height of the crop as a percentage of the image height.' ), + 'type' => 'number', + ), + ), + ), + ), + ), + ), + ), + ), + 'rotation' => array( + 'description' => __( 'The amount to rotate the image clockwise in degrees. DEPRECATED: Use `modifiers` instead.' ), 'type' => 'integer', 'minimum' => 0, 'exclusiveMinimum' => true, 'maximum' => 360, 'exclusiveMaximum' => true, ), - 'x' => array( - 'description' => __( 'As a percentage of the image, the x position to start the crop from.' ), + 'x' => array( + 'description' => __( 'As a percentage of the image, the x position to start the crop from. DEPRECATED: Use `modifiers` instead.' ), 'type' => 'number', 'minimum' => 0, 'maximum' => 100, ), - 'y' => array( - 'description' => __( 'As a percentage of the image, the y position to start the crop from.' ), + 'y' => array( + 'description' => __( 'As a percentage of the image, the y position to start the crop from. DEPRECATED: Use `modifiers` instead.' ), 'type' => 'number', 'minimum' => 0, 'maximum' => 100, ), - 'width' => array( - 'description' => __( 'As a percentage of the image, the width to crop the image to.' ), + 'width' => array( + 'description' => __( 'As a percentage of the image, the width to crop the image to. DEPRECATED: Use `modifiers` instead.' ), 'type' => 'number', 'minimum' => 0, 'maximum' => 100, ), - 'height' => array( - 'description' => __( 'As a percentage of the image, the height to crop the image to.' ), + 'height' => array( + 'description' => __( 'As a percentage of the image, the height to crop the image to. DEPRECATED: Use `modifiers` instead.' ), 'type' => 'number', 'minimum' => 0, 'maximum' => 100, ), - 'src' => array( - 'description' => __( 'URL to the edited image file.' ), - 'type' => 'string', - 'format' => 'uri', - 'required' => true, - ), ); }