Skip to content

Editor: Guard entity preload filters and share entity actions/fields logic - #85390

Merged
oandregal merged 12 commits into
trunkfrom
fix/preload-entity-paths-guard
Oct 23, 2026
Merged

oandregal merged 12 commits into
trunkfrom
fix/preload-entity-paths-guard

Conversation

@oandregal

@oandregal oandregal commented Oct 22, 2026 •

Copy link
Copy Markdown
Member

What?

Follow up to WordPress/wordpress-develop#14716

Ports the core changes of the backport above to the plugin's 7.2 compat layer.

Why?

Keeps the compat code in sync with core. It also fixes an editor crash when an earlier block_editor_rest_api_preload_paths callback returns something other than an array.

How?

  • Numeric module ids as strings: WP_Entity_Fields_Registry::get_all_registered_field_modules() casts module ids back to strings. A numeric id became an integer as an array key. The actions registry already did this.
  • Shared preload logic: the new lib/compat/wordpress-7.2/entity-utils.php adds _wp_add_entity_preload_paths(), matching core. _wp_preload_entity_actions() and _gutenberg_preload_entity_fields() both use it.
    • _gutenberg_preload_entity_fields() moves from preload.php to entity-fields-api.php as _wp_preload_entity_fields(), guarded by function_exists() as in core. When core ships it, only the core function runs.
    • Empty non-array paths become an array. Other non-array values, or a context that isn't a WP_Block_Editor_Context, are returned unchanged. $context defaults to null.
    • _gutenberg_get_site_editor_screen_post_types() is removed. Its screen map is now in the shared helper.
    • _wp_preload_entity_actions() now preloads the site editor actions too, as core does, so _gutenberg_preload_site_editor_entity_actions() is removed. Its tests moved to phpunit/entity-actions-api-test.php.
    • _gutenberg_get_post_type_fields_preload_paths() moves from preload.php to lib/experimental/route-entity-fields-preload.php, its only user.
  • Shared editor script logic: _wp_add_entity_modules_to_editor_script(), also in entity-utils.php, declares an API's script modules as dynamic module dependencies of wp-editor. The actions and fields functions delegate to it.

Testing Instructions

  1. npm run test:unit:php:base -- --filter 'Entity|Preload|entity' passes.
  2. Open the post editor and the site editor (Pages, Templates, Patterns). The /wp/v2/entity-actions and /wp/v2/entity-fields requests for the listed post types are preloaded, so there are no network requests for them on load.
  3. Add add_filter( 'block_editor_rest_api_preload_paths', '__return_null', 5 ); and open the post editor. It loads without a fatal error.

Use of AI Tools

Ported from the core PR with Claude Code (Claude Opus 5.5).

@github-actions

github-actions Bot commented Oct 22, 2026 •

Copy link
Copy Markdown

🤖 PR meta 🤖

Preview in WordPress Playground

🎉 Props

If you're merging code through a pull request on GitHub, copy and paste the following into the bottom of the merge commit message.

Co-authored-by: oandregal <oandregal@git.wordpress.org>
Co-authored-by: jorgefilipecosta <jorgefilipecosta@git.wordpress.org>

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

Updated as activity occurs, without notifying anyone named here. Add the props-bot label to refresh.

🏁 Flaky tests

Some tests passed with failed attempts. The failures may not be related to this commit but are still reported for visibility. See the documentation for more information.

Regression: updating a specific option will only change its value and will not corrupt others in /test/e2e/specs/editor/various/core-settings.spec.js, passed after 1 failed attempt.
Error: expect(received).toStrictEqual(expected) // deep equality

- Expected  - 1
+ Received  + 1

  Array [
    "rewrite_rules",
-   "SERIALIZED DATA",
+   "",
  ]
    at forEach (/home/runner/work/gutenberg/gutenberg/test/e2e/specs/editor/various/core-settings.spec.js:46:26)
    at /home/runner/work/gutenberg/gutenberg/test/e2e/specs/editor/various/core-settings.spec.js:43:35

8ac9052 Run

@oandregal oandregal self-assigned this Oct 22, 2026
@oandregal oandregal added [Type] Enhancement A suggestion for improvement. [Feature] DataViews Work surrounding upgrading and evolving views in the site editor and beyond Backport to WP 7.2 Beta/RC Pull request that needs to be backported to the WordPress major release that's currently in beta and removed Backport to WP 7.2 Beta/RC Pull request that needs to be backported to the WordPress major release that's currently in beta labels Oct 22, 2026
@oandregal oandregal added the Backport from WordPress Core Pull request that needs to be backported to a Gutenberg release from WordPress Core label Oct 22, 2026

@jorgefilipecosta jorgefilipecosta left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Some of the comments I left at WordPress/wordpress-develop#14716, could apply here but they are not blockers the change looks good.

@oandregal
oandregal force-pushed the fix/preload-entity-paths-guard branch from 4efecfd to 0ce085b Compare October 22, 2026 15:47
@oandregal
oandregal marked this pull request as ready for review October 22, 2026 15:47
Copilot AI balanced review requested due to automatic review settings October 22, 2026 15:47

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

Comment thread lib/compat/wordpress-7.2/class-gutenberg-rest-entity-actions-controller-7-2.php Outdated
Comment on lines +164 to +168
function _gutenberg_preload_entity_actions( $paths, $context = null ) {
return _wp_add_entity_preload_paths( $paths, $context, '/wp/v2/entity-actions' );
}
remove_filter( 'block_editor_rest_api_preload_paths', '_wp_preload_entity_actions' );
add_filter( 'block_editor_rest_api_preload_paths', '_gutenberg_preload_entity_actions', 10, 2 );

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

This is a temporary measure. Once WordPress/wordpress-develop#14716 is merged and the WordPress version Gutenberg's CI runs against includes it, we can go back to defining these only when core doesn't. Keeping the swap works fine at that point; it'd just be unnecessary, since both functions would be the same.

Comment on lines +228 to +232
function _gutenberg_preload_entity_fields( $paths, $context = null ) {
return _wp_add_entity_preload_paths( $paths, $context, '/wp/v2/entity-fields' );
}
remove_filter( 'block_editor_rest_api_preload_paths', '_wp_preload_entity_fields' );
add_filter( 'block_editor_rest_api_preload_paths', '_gutenberg_preload_entity_fields', 10, 2 );

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

This is a temporary measure. Once WordPress/wordpress-develop#14716 is merged and the WordPress version Gutenberg's CI runs against includes it, we can go back to defining these only when core doesn't. Keeping the swap works fine at that point; it'd just be unnecessary, since both functions would be the same.

oandregal and others added 12 commits October 23, 2026 09:39
A numeric script module id becomes an integer as an array key, so
`get_all_registered_field_modules()` returned it as an integer. It is now
cast back to a string, as the entity actions registry already does.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Ports the changes of the WordPress core backport.

`_wp_add_entity_preload_paths()`, in the new entity-utils.php, adds the
paths of an entity route for the post types the editors list. It holds
what `_wp_preload_entity_actions()` and `_gutenberg_preload_entity_fields()`
had in common, and the site editor screens of
`_gutenberg_get_site_editor_screen_post_types()`, which is removed.

It also guards against an earlier `block_editor_rest_api_preload_paths`
callback returning something other than an array: empty values become an
array, other values and a context that is not a `WP_Block_Editor_Context`
are returned unchanged. `$context` defaults to `null`.

`_wp_preload_entity_actions()` now preloads the actions of the site
editor too, as in core, so `_gutenberg_preload_site_editor_entity_actions()`
is removed and its tests move to the entity actions API tests.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Ports the changes of the WordPress core backport.

`_wp_add_entity_action_modules_to_editor_script()` and
`_wp_add_entity_field_modules_to_editor_script()` duplicated the logic
that declares the script modules of an entity API as dynamic module
dependencies of the editor script. It now lives in
`_wp_add_entity_modules_to_editor_script()`, in entity-utils.php, which
takes the getter of the modules of the API.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
`_gutenberg_preload_entity_fields()` becomes `_wp_preload_entity_fields()`
in entity-fields-api.php, guarded by `function_exists()`, as in core and
as `_wp_preload_entity_actions()` is in entity-actions-api.php. When core
ships it, the core function runs alone instead of both adding the same
paths.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Only the experimental route preload uses
`_gutenberg_get_post_type_fields_preload_paths()` now, so it moves from
the 7.2 compat preload.php to lib/experimental/route-entity-fields-preload.php.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…d_modules().

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Also cover a call with null paths and no context.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
wp_get_registered_entity_field_modules() and
wp_get_registered_entity_action_modules() keyed their result by module id,
which PHP turns into an integer when numeric: a strict comparison misses it
and array_merge() renumbers it. They now return a list of entries with the
module id and the ids of the fields or actions it applies to, the shape the
REST controllers already return.

The controllers still accept the keyed shape, which WordPress versions that
ship the API before core#14716 return.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
empty() treats the string '0' as empty, so a field with that id was skipped
with a notice asking for a non-empty string. Check for the empty string
instead, as the entity actions registry does.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…16 changes.

WordPress trunk already ships the registries without core#14716, and the plugin registries extend them, so they listed the modules of an entity keyed by module id and refused the field id `0`. The plugin registries now override these methods, which lets the REST controllers return the modules as they are.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…nes.

WordPress trunk already ships _wp_preload_entity_fields() and _wp_preload_entity_actions() without the guards of core#14716, so the compat functions were never defined and a non-array preload paths value still crashed the editor. The plugin now hooks its own _gutenberg_preload_entity_fields() and _gutenberg_preload_entity_actions(), and unhooks the core functions.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@oandregal
oandregal force-pushed the fix/preload-entity-paths-guard branch from c43afc7 to 8ac9052 Compare October 23, 2026 07:40
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Backport from WordPress Core Pull request that needs to be backported to a Gutenberg release from WordPress Core [Feature] DataViews Work surrounding upgrading and evolving views in the site editor and beyond [Type] Enhancement A suggestion for improvement.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants