Skip to content

Editor: PHP backports for Client Side Media#10868

Closed
adamsilverstein wants to merge 49 commits intoWordPress:trunkfrom
adamsilverstein:backport-preload-changes-for-csm-70
Closed

Editor: PHP backports for Client Side Media#10868
adamsilverstein wants to merge 49 commits intoWordPress:trunkfrom
adamsilverstein:backport-preload-changes-for-csm-70

Conversation

@adamsilverstein
Copy link
Member

@adamsilverstein adamsilverstein commented Feb 4, 2026

This PR contains the PHP backports for the client-side media processing feature, enabling the editor to perform client-side image resizing, thumbnail generation, and format conversion using WebAssembly.

Preloaded Settings

The following site settings are now preloaded in both the post editor and site editor:

  • image_sizes - Available image size configurations
  • image_size_threshold - Big image size threshold (default 2560px)
  • image_output_formats - Output format mappings for image conversion
  • jpeg_interlaced - Whether to use progressive/interlaced JPEG encoding
  • png_interlaced - Whether to use interlaced PNG encoding
  • gif_interlaced - Whether to use interlaced GIF encoding

REST API: Index Endpoint

Added media processing settings to the REST API index (/wp-json/wp/v2/):

  • image_sizes - All registered image sizes with dimensions and crop settings
  • image_size_threshold - Big image size threshold
  • image_output_formats - Format conversion mappings

REST API: Attachments Endpoint

New Fields

  • filename - Original attachment file name
  • filesize - File size in bytes
  • exif_orientation - EXIF orientation value (1-8) for client-side rotation handling

New Parameters

  • generate_sub_sizes - When false, disables server-side sub-size generation and EXIF rotation
  • convert_format - When false, disables automatic image format conversion

New Sideload Endpoint

Added /wp/v2/media/{id}/sideload endpoint for uploading sub-sized images to an existing attachment. Used by client-side media processing to upload generated image sizes without creating new attachments. Supports both images and PDFs.

PDF Improvements

Improved missing_image_sizes field handling for PDFs, which use the fallback_intermediate_image_sizes filter instead of wp_get_missing_image_subsizes().

Cross-Origin Isolation

Added COOP (Cross-Origin-Opener-Policy) and COEP (Cross-Origin-Embedder-Policy) headers in the block editor to enable SharedArrayBuffer for WebAssembly-based processing. Includes:

  • Output buffer to automatically add crossorigin="anonymous" attributes to external resources
  • Media templates updated with crossorigin attributes for audio, img, and video tags

WASM Support

Added AddType directive for WebAssembly files to .htaccess rules, enabling serving .wasm files for client-side media processing libraries like wasm-vips.

Tests

Updated REST API tests for the new attachment fields and sideload endpoint.


Gutenberg PRs:

Gutenberg tracking issue: WordPress/gutenberg#75062

Trac ticket: https://core.trac.wordpress.org/ticket/62243


This Pull Request is for code review only. Please keep all other discussion in the Trac ticket. Do not merge this Pull Request. See GitHub Pull Requests for Code Review in the Core Handbook for more details.

@github-actions
Copy link

github-actions bot commented Feb 4, 2026

Test using WordPress Playground

The changes in this pull request can previewed and tested using a WordPress Playground instance.

WordPress Playground is an experimental project that creates a full WordPress instance entirely within the browser.

Some things to be aware of

  • The Plugin and Theme Directories cannot be accessed within Playground.
  • All changes will be lost when closing a tab with a Playground instance.
  • All changes will be lost when refreshing the page.
  • A fresh instance is created each time the link below is clicked.
  • Every time this pull request is updated, a new ZIP file containing all changes is created. If changes are not reflected in the Playground instance,
    it's possible that the most recent build failed, or has not completed. Check the list of workflow runs to be sure.

For more details about these limitations and more, check out the Limitations page in the WordPress Playground documentation.

Test this pull request with WordPress Playground.

@adamsilverstein adamsilverstein changed the title Editor: Add REST API preloaded paths for client-side media processing Editor: PHP back posrts for client-side media Feb 5, 2026
@adamsilverstein adamsilverstein changed the title Editor: PHP back posrts for client-side media Editor: PHP backports for client-side media Feb 5, 2026
@adamsilverstein adamsilverstein changed the title Editor: PHP backports for client-side media Editor: PHP backports for Client Side Media Feb 5, 2026
@adamsilverstein adamsilverstein self-assigned this Feb 5, 2026
Copy link
Member

@westonruter westonruter left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry for what may be an unsolicited early review, as the PR is still a draft.

@adamsilverstein
Copy link
Member Author

Sorry for what may be an unsolicited early review, as the PR is still a draft.

No worries, happy to have your feedback. Indeed I started working on this pr before the Gutenberg work had merged to get ahead and be more prepared - so it may change a bit, but probably not much at this point.

@adamsilverstein adamsilverstein marked this pull request as ready for review February 19, 2026 07:33
@github-actions
Copy link

github-actions bot commented Feb 19, 2026

The following accounts have interacted with this PR and/or linked issues. I will continue to update these lists as activity occurs. You can also manually ask me to refresh this list by adding the props-bot label.

Core Committers: Use this line as a base for the props when committing in SVN:

Props adamsilverstein, westonruter, mamaduka, mukesh27, swissspidy, andrewserong.

To understand the WordPress project's expectations around crediting contributors, please review the Contributor Attribution page in the Core Handbook.

Comment on lines +1371 to +1372
// Add media processing settings for users who can upload files.
if ( current_user_can( 'upload_files' ) ) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not a blocker (can be changed post-beta), but maybe the attachments controller is a better place for these settings.

We had a similar discussion for template-related settings during WP 6.8 - https://core.trac.wordpress.org/ticket/62574#comment:29

cc @peterwilsoncc

@andrewserong
Copy link
Contributor

Just a quick comment: it looks like this accidentally removes the ca-bundle.crt file, so I assume needs a rebase?

@adamsilverstein
Copy link
Member Author

Just a quick comment: it looks like this accidentally removes the ca-bundle.crt file, so I assume needs a rebase?

oh, i thought i had added that file. will fix. Also figured out why this isn't working, fix incoming.

Add filename and filesize REST fields to the attachments endpoint
for client-side media processing. The filename returns the original
attachment file name, and filesize returns the file size in bytes.
adamsilverstein and others added 6 commits February 20, 2026 16:11
Rename $tags to $cross_origin_tag_attributes and restructure
it as a mapping of tag name to attributes with boolean values
indicating whether each is a srcset. This replaces the
hardcoded IMG srcset special case with a generic loop,
making it easier to extend (e.g. for imagesrcset on LINK).
LINK elements can have imagesrcset for preloading responsive
images, and VIDEO elements can have a poster image URL. Both
need cross-origin handling.
WASM files are now inlined as base64 data URLs at build
time, so the .htaccess AddType rule is no longer needed.
Skip setting crossorigin when already present, and document why
the simpler approach (vs wp_add_crossorigin_attributes) is needed
for Underscore.js template placeholders.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The $ext, $unique_filename_callback, and $alt_filenames parameters
were not used in the method body. The closure still receives all 6
filter args positionally but now only passes the 4 that are needed.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@adamsilverstein
Copy link
Member Author

@westonruter I believe I have addressed all outstanding feedback (except the output mapping one I will work on in a follow up). Can you give it another spin?

Instead of using a separate wp_override_media_templates function
that removes and re-adds the admin_footer action with an anonymous
closure, add the crossorigin attribute processing directly within
wp_print_media_templates itself. This simplifies the approach and
eliminates the indirection of action hook manipulation.
@mukeshpanchal27
Copy link
Member

@adamsilverstein have you checked why unit tests are failed?

@adamsilverstein
Copy link
Member Author

@adamsilverstein have you checked why unit tests are failed?

looking now...

@adamsilverstein
Copy link
Member Author

@adamsilverstein have you checked why unit tests are failed?

looks like I just needed to update the wp-api fixtures which i did in 57c4f00 (by running the test_build_wp_api_client_fixtures test locally)

The previous fixture regeneration included spurious meta fields
(footnotes, _wp_note_status) and changed authentication format,
causing both QUnit and PHPUnit CI failures. Reset to trunk's fixture
and re-apply only the legitimate CSM changes (sideload endpoint,
generate_sub_sizes, convert_format, image_sizes, filename, filesize).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@github-actions
Copy link

A commit was made that fixes the Trac ticket referenced in the description of this pull request.

SVN changeset: 61703
GitHub commit: 0544d56

This PR will be closed, but please confirm the accuracy of this and reopen if there is more work to be done.

@github-actions github-actions bot closed this Feb 20, 2026
adamsilverstein added a commit to WordPress/gutenberg that referenced this pull request Feb 20, 2026
After WordPress/wordpress-develop#10868 (r61703), the core
`WP_REST_Attachments_Controller::filter_wp_unique_filename()` method
was changed to `private static`. This causes a fatal error in the
Gutenberg subclass which declares it as non-static.

Aligns the Gutenberg method signature with core by making it static
and simplifying the parameters to match.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
adamsilverstein added a commit to WordPress/gutenberg that referenced this pull request Feb 20, 2026
… avoid duplicate routes (#75782)

* REST API: Make `filter_wp_unique_filename()` static to match core

After WordPress/wordpress-develop#10868 (r61703), the core
`WP_REST_Attachments_Controller::filter_wp_unique_filename()` method
was changed to `private static`. This causes a fatal error in the
Gutenberg subclass which declares it as non-static.

Aligns the Gutenberg method signature with core by making it static
and simplifying the parameters to match.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Avoid duplicate sideload route registration when core already has it

Since core trunk now registers the sideload route in
`WP_REST_Attachments_Controller::register_routes()`, only register
it in the Gutenberg subclass when the parent class doesn't already
have the `sideload_item` method. Updates the test accordingly.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
peterwilsoncc pushed a commit to peterwilsoncc/gutenberg-build that referenced this pull request Feb 22, 2026
… avoid duplicate routes (#75782)

* REST API: Make `filter_wp_unique_filename()` static to match core

After WordPress/wordpress-develop#10868 (r61703), the core
`WP_REST_Attachments_Controller::filter_wp_unique_filename()` method
was changed to `private static`. This causes a fatal error in the
Gutenberg subclass which declares it as non-static.

Aligns the Gutenberg method signature with core by making it static
and simplifying the parameters to match.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Avoid duplicate sideload route registration when core already has it

Since core trunk now registers the sideload route in
`WP_REST_Attachments_Controller::register_routes()`, only register
it in the Gutenberg subclass when the parent class doesn't already
have the `sideload_item` method. Updates the test accordingly.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>

Source: WordPress/gutenberg@03a4bf9
scruffian pushed a commit to WordPress/gutenberg that referenced this pull request Feb 23, 2026
… avoid duplicate routes (#75782)

* REST API: Make `filter_wp_unique_filename()` static to match core

After WordPress/wordpress-develop#10868 (r61703), the core
`WP_REST_Attachments_Controller::filter_wp_unique_filename()` method
was changed to `private static`. This causes a fatal error in the
Gutenberg subclass which declares it as non-static.

Aligns the Gutenberg method signature with core by making it static
and simplifying the parameters to match.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Avoid duplicate sideload route registration when core already has it

Since core trunk now registers the sideload route in
`WP_REST_Attachments_Controller::register_routes()`, only register
it in the Gutenberg subclass when the parent class doesn't already
have the `sideload_item` method. Updates the test accordingly.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
ockham pushed a commit to WordPress/gutenberg that referenced this pull request Feb 24, 2026
… avoid duplicate routes (#75782)

* REST API: Make `filter_wp_unique_filename()` static to match core

After WordPress/wordpress-develop#10868 (r61703), the core
`WP_REST_Attachments_Controller::filter_wp_unique_filename()` method
was changed to `private static`. This causes a fatal error in the
Gutenberg subclass which declares it as non-static.

Aligns the Gutenberg method signature with core by making it static
and simplifying the parameters to match.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Avoid duplicate sideload route registration when core already has it

Since core trunk now registers the sideload route in
`WP_REST_Attachments_Controller::register_routes()`, only register
it in the Gutenberg subclass when the parent class doesn't already
have the `sideload_item` method. Updates the test accordingly.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
peterwilsoncc pushed a commit to peterwilsoncc/gutenberg-build that referenced this pull request Feb 24, 2026
… avoid duplicate routes (#75782)

* REST API: Make `filter_wp_unique_filename()` static to match core

After WordPress/wordpress-develop#10868 (r61703), the core
`WP_REST_Attachments_Controller::filter_wp_unique_filename()` method
was changed to `private static`. This causes a fatal error in the
Gutenberg subclass which declares it as non-static.

Aligns the Gutenberg method signature with core by making it static
and simplifying the parameters to match.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Avoid duplicate sideload route registration when core already has it

Since core trunk now registers the sideload route in
`WP_REST_Attachments_Controller::register_routes()`, only register
it in the Gutenberg subclass when the parent class doesn't already
have the `sideload_item` method. Updates the test accordingly.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>

Source: WordPress/gutenberg@f6e37c0
gutenbergplugin pushed a commit to WordPress/gutenberg that referenced this pull request Feb 25, 2026
… avoid duplicate routes (#75782)

* REST API: Make `filter_wp_unique_filename()` static to match core

After WordPress/wordpress-develop#10868 (r61703), the core
`WP_REST_Attachments_Controller::filter_wp_unique_filename()` method
was changed to `private static`. This causes a fatal error in the
Gutenberg subclass which declares it as non-static.

Aligns the Gutenberg method signature with core by making it static
and simplifying the parameters to match.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Avoid duplicate sideload route registration when core already has it

Since core trunk now registers the sideload route in
`WP_REST_Attachments_Controller::register_routes()`, only register
it in the Gutenberg subclass when the parent class doesn't already
have the `sideload_item` method. Updates the test accordingly.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
peterwilsoncc pushed a commit to peterwilsoncc/gutenberg-build that referenced this pull request Feb 25, 2026
… avoid duplicate routes (#75782)

* REST API: Make `filter_wp_unique_filename()` static to match core

After WordPress/wordpress-develop#10868 (r61703), the core
`WP_REST_Attachments_Controller::filter_wp_unique_filename()` method
was changed to `private static`. This causes a fatal error in the
Gutenberg subclass which declares it as non-static.

Aligns the Gutenberg method signature with core by making it static
and simplifying the parameters to match.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Avoid duplicate sideload route registration when core already has it

Since core trunk now registers the sideload route in
`WP_REST_Attachments_Controller::register_routes()`, only register
it in the Gutenberg subclass when the parent class doesn't already
have the `sideload_item` method. Updates the test accordingly.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>

Source: WordPress/gutenberg@21b607c
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants