Make WordPress Core

Opened 11 hours ago

Last modified 98 minutes ago

#66027 new enhancement

REST API: let the media create endpoint record the attachment an upload was edited from

Reported by: adamsilverstein Owned by:
Priority: normal Milestone: 7.2
Component: REST API Version: trunk
Severity: normal Keywords: has-patch has-unit-tests
Cc: Focuses: rest-api

Description

Claude Code drafted this ticket from the Gutenberg change, forwarded along:

With client-side media processing, Gutenberg is moving image edits (crop, rotate, flip) from the server media/<id>/edit endpoint into the browser: the edit is applied with libvips and the result is uploaded through POST /wp/v2/media as a new attachment, the same way the editor has always created edited images. See https://github.com/WordPress/gutenberg/pull/82362 (fixes https://github.com/WordPress/gutenberg/issues/82295, where server-side edits strip the gain map from HDR JPEGs).

One thing the /edit endpoint does that the upload endpoint cannot is record where the new image came from: it stores a parent_image entry (attachment_id and the source's relative file path) in the new attachment's metadata, copies the source's EXIF image_meta for any field the new file lacks, and resets the orientation to 1. Edits made in the browser should relate to their source the same way.

Proposed change: add an optional parent_image integer parameter to the media create endpoint. When set, it must reference an existing image attachment the current user can edit (matching the /edit permission check), and after the upload the new attachment's metadata gets the same parent_image entry and EXIF carry-over that edit_media_item() writes. Without the parameter nothing changes.

Related: #65367 (client-side media processing endpoints).

Patch incoming.

Change History (2)

This ticket was mentioned in PR #13372 on WordPress/wordpress-develop by @adamsilverstein.


11 hours ago
#1

Companion to https://github.com/WordPress/gutenberg/pull/82362.

_Claude Code wrote this up from the Gutenberg change:_

With client-side media processing, image edits (crop, rotate, flip) made in the editor are moving from the server media/<id>/edit endpoint into the browser: the edit is applied with libvips and the result is uploaded through POST /wp/v2/media as a new attachment. The one thing /edit records that the upload endpoint could not is where the new image came from.

This adds an optional parent_image integer parameter to the media create endpoint. When set it must reference an existing image attachment the current user can edit (the same check the /edit endpoint applies), and after the upload the new attachment's metadata gets what edit_media_item() writes for its new attachment: the parent_image entry (attachment_id and the source's relative file), the source's EXIF image_meta for any field the new file lacks, and an orientation reset to 1. Without the parameter nothing changes.

Tests cover the recorded metadata and response, the no-parameter case, a parent_image that is not an image (400), and an author who cannot edit the source attachment (403).

## AI Use

Code and description both written with 🤖 Claude Code. I will review and test.

@ugyensupport commented on PR #13372:


98 minutes ago
#2

Manually tested against a local WP 7.1-trunk install (Studio site, real DB/uploads, no git checkout available so I hand-applied this diff — context matched cleanly).

Ran the PR's own scenarios via wp eval-file directly through the REST dispatcher (rest_get_server()->dispatch()), same as the added PHPUnit tests:

Scenario Result
Upload with parent_image set → metadata + response carry parent_image, EXIF credit copied from source, orientation reset to 1 ✅ 201
Upload with no parent_image → nothing recorded ✅ 201, key absent
parent_image points at a non-image post ✅ 400 rest_invalid_param
parent_image points at another user's attachment the current user can't edit ✅ 403 rest_cannot_edit_image
Schema exposes parent_image (type: integer, minimum: 1) in CREATABLE args

All 5 passed. php -l clean. Behavior matches the ticket description and mirrors edit_media_item()'s handling faithfully.

🤖 Generated with Claude Code

Note: See TracTickets for help on using tickets.