-
Notifications
You must be signed in to change notification settings - Fork 3.3k
REST API: Add finalize endpoint to WP_REST_Attachments_Controller #11168
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: trunk
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -103,6 +103,26 @@ | |||||
| 'schema' => array( $this, 'get_public_item_schema' ), | ||||||
| ) | ||||||
| ); | ||||||
|
|
||||||
| register_rest_route( | ||||||
| $this->namespace, | ||||||
| '/' . $this->rest_base . '/(?P<id>[\d]+)/finalize', | ||||||
| array( | ||||||
| array( | ||||||
| 'methods' => WP_REST_Server::CREATABLE, | ||||||
| 'callback' => array( $this, 'finalize_item' ), | ||||||
| 'permission_callback' => array( $this, 'finalize_item_permissions_check' ), | ||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Shell we use |
||||||
| 'args' => array( | ||||||
| 'id' => array( | ||||||
| 'description' => __( 'Unique identifier for the attachment.' ), | ||||||
| 'type' => 'integer', | ||||||
| ), | ||||||
| ), | ||||||
| ), | ||||||
| 'allow_batch' => $this->allow_batch, | ||||||
| 'schema' => array( $this, 'get_public_item_schema' ), | ||||||
| ) | ||||||
| ); | ||||||
| } | ||||||
| } | ||||||
|
|
||||||
|
|
@@ -2176,4 +2196,63 @@ | |||||
|
|
||||||
| return $filename; | ||||||
| } | ||||||
|
|
||||||
| /** | ||||||
| * Checks if a given request has access to finalize an attachment. | ||||||
| * | ||||||
| * @since 7.0.0 | ||||||
| * | ||||||
| * @param WP_REST_Request $request Full details about the request. | ||||||
| * @return true|WP_Error True if the request has access, WP_Error object otherwise. | ||||||
| */ | ||||||
| public function finalize_item_permissions_check( $request ) { | ||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
| return $this->edit_media_item_permissions_check( $request ); | ||||||
| } | ||||||
|
|
||||||
| /** | ||||||
| * Finalizes an attachment after client-side media processing. | ||||||
| * | ||||||
| * Triggers the 'wp_generate_attachment_metadata' filter so that | ||||||
| * server-side plugins can process the attachment after all client-side | ||||||
| * operations (upload, thumbnail generation, sideloads) are complete. | ||||||
| * | ||||||
| * @since 7.0.0 | ||||||
| * | ||||||
| * @param WP_REST_Request $request Full details about the request. | ||||||
| * @return WP_REST_Response|WP_Error Response object on success, WP_Error object on failure. | ||||||
| */ | ||||||
| public function finalize_item( WP_REST_Request $request ) { | ||||||
| $attachment_id = $request['id']; | ||||||
|
|
||||||
| $post = $this->get_post( $attachment_id ); | ||||||
|
|
||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
| if ( is_wp_error( $post ) ) { | ||||||
| return $post; | ||||||
| } | ||||||
|
|
||||||
| $metadata = wp_get_attachment_metadata( $attachment_id ); | ||||||
|
|
||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
| if ( ! is_array( $metadata ) ) { | ||||||
| $metadata = array(); | ||||||
| } | ||||||
|
|
||||||
| /** This filter is documented in wp-admin/includes/image.php */ | ||||||
| $metadata = apply_filters( 'wp_generate_attachment_metadata', $metadata, $attachment_id, 'update' ); | ||||||
|
|
||||||
| wp_update_attachment_metadata( $attachment_id, $metadata ); | ||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I guess it doesn't make sense to check the return value here for failure since it returns |
||||||
|
|
||||||
| $response_request = new WP_REST_Request( | ||||||
| WP_REST_Server::READABLE, | ||||||
| rest_get_route_for_post( $attachment_id ) | ||||||
| ); | ||||||
|
|
||||||
| $response_request['context'] = 'edit'; | ||||||
|
|
||||||
| if ( isset( $request['_fields'] ) ) { | ||||||
| $response_request['_fields'] = $request['_fields']; | ||||||
| } | ||||||
|
|
||||||
| return $this->prepare_item_for_response( get_post( $attachment_id ), $response_request ); | ||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can this re-use the
Suggested change
|
||||||
| } | ||||||
|
|
||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
| } | ||||||
| Original file line number | Diff line number | Diff line change | ||
|---|---|---|---|---|
|
|
@@ -3343,4 +3343,87 @@ | |||
| $basename = wp_basename( $new_file ); | ||||
| $this->assertMatchesRegularExpression( '/canola-scaled-\d+\.jpg$/', $basename, 'Scaled filename should have numeric suffix when file conflicts with a different attachment.' ); | ||||
| } | ||||
|
|
||||
| /** | ||||
| * Tests that the finalize endpoint triggers wp_generate_attachment_metadata. | ||||
| * | ||||
| * @ticket 62243 | ||||
| * @requires function imagejpeg | ||||
| */ | ||||
| public function test_finalize_item() { | ||||
| wp_set_current_user( self::$author_id ); | ||||
|
|
||||
| // Create an attachment. | ||||
| $request = new WP_REST_Request( 'POST', '/wp/v2/media' ); | ||||
| $request->set_header( 'Content-Type', 'image/jpeg' ); | ||||
| $request->set_header( 'Content-Disposition', 'attachment; filename=canola.jpg' ); | ||||
| $request->set_body( file_get_contents( self::$test_file ) ); | ||||
| $response = rest_get_server()->dispatch( $request ); | ||||
| $attachment_id = $response->get_data()['id']; | ||||
|
|
||||
| $this->assertSame( 201, $response->get_status() ); | ||||
|
|
||||
| // Track whether wp_generate_attachment_metadata filter fires. | ||||
| $filter_called = false; | ||||
| $filter_context = null; | ||||
| add_filter( | ||||
| 'wp_generate_attachment_metadata', | ||||
| function ( $metadata, $id, $context ) use ( &$filter_called, &$filter_context ) { | ||||
| $filter_called = true; | ||||
| $filter_context = $context; | ||||
| return $metadata; | ||||
| }, | ||||
| 10, | ||||
| 3 | ||||
| ); | ||||
|
|
||||
| // Call the finalize endpoint. | ||||
| $request = new WP_REST_Request( 'POST', "/wp/v2/media/{$attachment_id}/finalize" ); | ||||
| $response = rest_get_server()->dispatch( $request ); | ||||
|
|
||||
| $this->assertSame( 200, $response->get_status(), 'Finalize endpoint should return 200.' ); | ||||
| $this->assertTrue( $filter_called, 'wp_generate_attachment_metadata filter should have been called.' ); | ||||
| $this->assertSame( 'update', $filter_context, 'Filter context should be "update".' ); | ||||
| } | ||||
|
|
||||
| /** | ||||
| * Tests that the finalize endpoint requires authentication. | ||||
| * | ||||
| * @ticket 62243 | ||||
| * @requires function imagejpeg | ||||
| */ | ||||
| public function test_finalize_item_requires_auth() { | ||||
| wp_set_current_user( self::$author_id ); | ||||
|
|
||||
| // Create an attachment. | ||||
| $request = new WP_REST_Request( 'POST', '/wp/v2/media' ); | ||||
| $request->set_header( 'Content-Type', 'image/jpeg' ); | ||||
| $request->set_header( 'Content-Disposition', 'attachment; filename=canola.jpg' ); | ||||
| $request->set_body( file_get_contents( self::$test_file ) ); | ||||
| $response = rest_get_server()->dispatch( $request ); | ||||
| $attachment_id = $response->get_data()['id']; | ||||
|
|
||||
| // Try finalizing without authentication. | ||||
| wp_set_current_user( 0 ); | ||||
|
|
||||
| $request = new WP_REST_Request( 'POST', "/wp/v2/media/{$attachment_id}/finalize" ); | ||||
| $response = rest_get_server()->dispatch( $request ); | ||||
|
|
||||
| $this->assertErrorResponse( 'rest_cannot_edit_image', $response, 401 ); | ||||
| } | ||||
|
|
||||
| /** | ||||
| * Tests that the finalize endpoint returns error for invalid attachment ID. | ||||
| * | ||||
| * @ticket 62243 | ||||
| */ | ||||
| public function test_finalize_item_invalid_id() { | ||||
| wp_set_current_user( self::$author_id ); | ||||
|
|
||||
| $request = new WP_REST_Request( 'POST', '/wp/v2/media/999999/finalize' ); | ||||
| $response = rest_get_server()->dispatch( $request ); | ||||
|
|
||||
| $this->assertErrorResponse( 'rest_post_invalid_id', $response, 404 ); | ||||
| } | ||||
|
|
||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||
| } | ||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The brackets aren't necessary.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
But I guess the other endpoints have the similar pattern.