-
Notifications
You must be signed in to change notification settings - Fork 3.3k
Editor: PHP backports for Client Side Media #10868
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?
Editor: PHP backports for Client Side Media #10868
Conversation
Test using WordPress PlaygroundThe 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
For more details about these limitations and more, check out the Limitations page in the WordPress Playground documentation. |
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.
Add exif_orientation field to the attachments REST endpoint for client-side EXIF rotation handling. Values 1-8 follow the EXIF specification, where 1 means no rotation is needed.
Add generate_sub_sizes and convert_format parameters to the attachments POST endpoint for client-side media processing control. When generate_sub_sizes is false, server-side sub-size generation and EXIF rotation are disabled. When convert_format is false, automatic image format conversion is disabled.
Add sideload endpoint at /wp/v2/media/{id}/sideload 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.
Add PDF-specific handling for the missing_image_sizes field in the attachments endpoint. PDFs use fallback_intermediate_image_sizes filter to determine which thumbnail sizes should be generated, unlike regular images which use wp_get_missing_image_subsizes().
Add COOP and COEP headers in the block editor to enable SharedArrayBuffer for WebAssembly-based client-side media processing. Includes output buffer to automatically add crossorigin="anonymous" attributes to external resources.
Add AddType directive for WebAssembly files to the mod_rewrite_rules filter. This enables serving .wasm files for client-side media processing using libraries like wasm-vips.
Override wp_print_media_templates to add crossorigin="anonymous" attributes to audio, img, and video tags. Required for cross-origin isolation compliance in the media library modal.
Update test_get_item_schema to expect 32 properties instead of 29, adding assertions for the new filename, filesize, and exif_orientation fields. Add the sideload endpoint to expected routes in schema test. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
westonruter
left a comment
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.
Sorry for what may be an unsolicited early review, as the PR is still a draft.
| $user_id = get_current_user_id(); | ||
| if ( ! $user_id ) { | ||
| return; | ||
| } | ||
|
|
||
| // Cross-origin isolation is not needed if users can't upload files anyway. | ||
| if ( ! user_can( $user_id, 'upload_files' ) ) { |
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.
| $user_id = get_current_user_id(); | |
| if ( ! $user_id ) { | |
| return; | |
| } | |
| // Cross-origin isolation is not needed if users can't upload files anyway. | |
| if ( ! user_can( $user_id, 'upload_files' ) ) { | |
| // Cross-origin isolation is not needed if users can't upload files anyway. | |
| if ( ! current_user_can( 'upload_files' ) ) { |
| $tag_names = array_keys( $tags ); | ||
|
|
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.
| $tag_names = array_keys( $tags ); |
| while ( $processor->next_tag() ) { | ||
| $tag = $processor->get_tag(); | ||
|
|
||
| if ( ! in_array( $tag, $tag_names, true ) ) { |
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.
| if ( ! in_array( $tag, $tag_names, true ) ) { | |
| if ( ! isset( $tags[ $tag ] ) ) { |
| } | ||
|
|
||
| /** | ||
| * Filters the list of rewrite rules formatted for output to an .htaccess file. |
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.
What about for Nginx?
| foreach ( $tags as $tag ) { | ||
| $html = (string) str_replace( "<$tag", "<$tag crossorigin=\"anonymous\"", $html ); | ||
| } |
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.
This should use the HTML Tag Processor too as it has been leveraged above.
| $sizes = wp_get_registered_image_subsizes(); | ||
| foreach ( $sizes as $name => &$size ) { | ||
| $size['height'] = (int) $size['height']; | ||
| $size['width'] = (int) $size['width']; | ||
| $size['name'] = $name; | ||
| } | ||
| unset( $size ); | ||
| $available['image_sizes'] = $sizes; |
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.
| $sizes = wp_get_registered_image_subsizes(); | |
| foreach ( $sizes as $name => &$size ) { | |
| $size['height'] = (int) $size['height']; | |
| $size['width'] = (int) $size['width']; | |
| $size['name'] = $name; | |
| } | |
| unset( $size ); | |
| $available['image_sizes'] = $sizes; | |
| $available['image_sizes'] = array(); | |
| foreach ( wp_get_registered_image_subsizes() as $name => $size ) { | |
| $available['image_sizes'][] = array( | |
| 'height' => (int) $size['height'], | |
| 'width' => (int) $size['width'], | |
| 'name' => $name, | |
| ); | |
| } |
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 configurationsimage_size_threshold- Big image size threshold (default 2560px)image_output_formats- Output format mappings for image conversionjpeg_interlaced- Whether to use progressive/interlaced JPEG encodingpng_interlaced- Whether to use interlaced PNG encodinggif_interlaced- Whether to use interlaced GIF encodingREST 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 settingsimage_size_threshold- Big image size thresholdimage_output_formats- Format conversion mappingsREST API: Attachments Endpoint
New Fields
filename- Original attachment file namefilesize- File size in bytesexif_orientation- EXIF orientation value (1-8) for client-side rotation handlingNew Parameters
generate_sub_sizes- When false, disables server-side sub-size generation and EXIF rotationconvert_format- When false, disables automatic image format conversionNew Sideload Endpoint
Added
/wp/v2/media/{id}/sideloadendpoint 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_sizesfield handling for PDFs, which use thefallback_intermediate_image_sizesfilter instead ofwp_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:
crossorigin="anonymous"attributes to external resourcesWASM Support
Added
AddTypedirective for WebAssembly files to.htaccessrules, enabling serving.wasmfiles 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.