diff --git a/src/wp-includes/entity-actions.php b/src/wp-includes/entity-actions.php index 13ec78bc03e33..426fd1d30943a 100644 --- a/src/wp-includes/entity-actions.php +++ b/src/wp-includes/entity-actions.php @@ -189,13 +189,16 @@ function _wp_add_entity_action_modules_to_editor_script( $scripts = null ) { } /** - * Preloads the actions of the post type the post editor edits. + * Preloads the actions of the post types the editors list. * - * The actions menu of the post editor reads them from the `wp/v2/entity-actions` - * route as it loads, see `useEntityActions()` in - * packages/editor/src/dataviews/entity-actions-loader.ts. The path must match the - * request of the `getEntityActionsConfig` core data resolver, see - * packages/core-data/src/resolvers.js. + * The editors read them from the `/wp/v2/entity-actions` route as they load, + * see `useEntityActions()` in + * packages/editor/src/dataviews/entity-actions-loader.ts in Gutenberg. The + * post editor reads those of the edited post in its actions menu. The site + * editor reads those of the edited post, if any, and of the post types of the + * screen it opens on, whose lists show the actions of their items. A path must + * match the request of the `getEntityActionsConfig` core data resolver, see + * packages/core-data/src/resolvers.js in Gutenberg. * * @since 7.2.0 * @@ -204,11 +207,24 @@ function _wp_add_entity_action_modules_to_editor_script( $scripts = null ) { * @return array Filtered preload paths. */ function _wp_preload_entity_actions( $paths, $context ) { + $post_types = array(); if ( 'core/edit-post' === $context->name && isset( $context->post ) ) { + $post_types[] = $context->post->post_type; + } elseif ( 'core/edit-site' === $context->name ) { + if ( isset( $context->post ) ) { + $post_types[] = $context->post->post_type; + } + $post_types = array_merge( $post_types, _wp_get_site_editor_screen_post_types() ); + } + + foreach ( array_unique( $post_types ) as $post_type ) { + if ( ! post_type_exists( $post_type ) ) { + continue; + } $paths[] = add_query_arg( array( 'kind' => 'postType', - 'name' => $context->post->post_type, + 'name' => $post_type, ), '/wp/v2/entity-actions' ); diff --git a/src/wp-includes/entity-fields.php b/src/wp-includes/entity-fields.php index 91a0547557a3e..779a32f7fe3f2 100644 --- a/src/wp-includes/entity-fields.php +++ b/src/wp-includes/entity-fields.php @@ -288,8 +288,8 @@ function _wp_get_post_type_fields_preload_paths( $post_types ) { } /** - * Returns the post types whose fields the screen of the site editor being - * loaded lists, from its `p` query arg. + * Returns the post types whose items the screen of the site editor being + * loaded lists or edits, from its `p` query arg. * * The screens are the routes in * packages/edit-site/src/components/site-editor-routes in Gutenberg: the @@ -323,16 +323,13 @@ function _wp_get_site_editor_screen_post_types() { } /** - * Preloads the fields of the post types the site editor lists. + * Preloads the fields of the post types the editors list. * - * The site editor reads them from the `/wp/v2/entity-fields` route before it - * can list the post fields, see `useFields` in - * packages/editor/src/dataviews/fields-loader/index.ts in Gutenberg: those of - * the edited post, if any, and of the post types of the screen it opens on. - * - * The post editor is left untouched: it only reads the fields in the - * DataForm-based inspector, an experiment of the Gutenberg plugin which - * preloads them on its own. + * The editors read them from the `/wp/v2/entity-fields` route, see `useFields` + * in packages/editor/src/dataviews/fields-loader/index.ts in Gutenberg. The + * post editor reads those of the edited post in the post summary of its + * inspector. The site editor reads those of the edited post, if any, and of + * the post types of the screen it opens on. * * @since 7.2.0 * @access private @@ -342,15 +339,15 @@ function _wp_get_site_editor_screen_post_types() { * @return array Filtered preload paths. */ function _wp_preload_entity_fields( $paths, $context ) { - if ( 'core/edit-site' !== $context->name ) { - return $paths; - } - $post_types = array(); - if ( isset( $context->post ) ) { + if ( 'core/edit-post' === $context->name && isset( $context->post ) ) { $post_types[] = $context->post->post_type; + } elseif ( 'core/edit-site' === $context->name ) { + if ( isset( $context->post ) ) { + $post_types[] = $context->post->post_type; + } + $post_types = array_merge( $post_types, _wp_get_site_editor_screen_post_types() ); } - $post_types = array_merge( $post_types, _wp_get_site_editor_screen_post_types() ); return array_merge( $paths, diff --git a/tests/phpunit/tests/entity-actions.php b/tests/phpunit/tests/entity-actions.php index 4625df3f4a205..5643906778bc2 100644 --- a/tests/phpunit/tests/entity-actions.php +++ b/tests/phpunit/tests/entity-actions.php @@ -42,6 +42,7 @@ public function set_up() { * the actions WordPress registers back. */ public function tear_down() { + unset( $_GET['p'] ); self::reset_registry(); parent::tear_down(); @@ -428,15 +429,83 @@ public function test_the_preloaded_actions_path_serves_the_actions() { } /** - * Only the post editor preloads the actions: the other editors have no - * post type of their own. + * The site editor preloads the actions of the post types its screen lists, + * from the `p` query arg. + * + * @ticket 66343 + * + * @dataProvider data_site_editor_screens + * + * @param string $path The `p` query arg. + * @param string[] $post_types The post types whose actions are preloaded. + */ + public function test_the_site_editor_preloads_the_actions_of_its_screen( $path, $post_types ) { + $_GET['p'] = $path; + $context = new WP_Block_Editor_Context( array( 'name' => 'core/edit-site' ) ); + + $expected = array(); + foreach ( $post_types as $post_type ) { + $expected[] = '/wp/v2/entity-actions?kind=postType&name=' . $post_type; + } + $this->assertSame( $expected, _wp_preload_entity_actions( array(), $context ), 'The actions of the post types of the screen are preloaded.' ); + } + + /** + * Data provider for test_the_site_editor_preloads_the_actions_of_its_screen(). + * + * @return array[] + */ + public static function data_site_editor_screens() { + return array( + 'pages' => array( '/page', array( 'page' ) ), + 'page' => array( '/page/12', array( 'page' ) ), + 'templates' => array( '/template', array( 'wp_template' ) ), + 'template' => array( '/wp_template/emptytheme//index', array( 'wp_template' ) ), + 'patterns' => array( '/pattern', array( 'wp_block', 'wp_template_part' ) ), + 'pattern' => array( '/wp_block/12', array( 'wp_block' ) ), + 'template part' => array( '/wp_template_part/emptytheme//header', array( 'wp_template_part' ) ), + 'root' => array( '/', array() ), + 'styles' => array( '/styles', array() ), + 'navigation' => array( '/navigation', array() ), + ); + } + + /** + * The site editor preloads the actions of the edited post, once, next to + * those of its screen. + * + * @ticket 66343 + */ + public function test_the_site_editor_preloads_the_actions_of_the_edited_post() { + $_GET['p'] = '/page'; + $context = new WP_Block_Editor_Context( + array( + 'name' => 'core/edit-site', + 'post' => self::factory()->post->create_and_get( array( 'post_type' => 'page' ) ), + ) + ); + + $this->assertSame( + array( '/wp/v2/entity-actions?kind=postType&name=page' ), + _wp_preload_entity_actions( array(), $context ), + 'The actions of pages are preloaded once.' + ); + } + + /** + * Other editors, a post editor context without a post, and a site editor + * screen that lists no posts are left untouched. * * @ticket 66343 */ public function test_other_editors_do_not_preload_the_actions() { - $context = new WP_Block_Editor_Context( array( 'name' => 'core/edit-site' ) ); + $site_editor = new WP_Block_Editor_Context( array( 'name' => 'core/edit-site' ) ); + $no_post = new WP_Block_Editor_Context( array( 'name' => 'core/edit-post' ) ); + $widgets = new WP_Block_Editor_Context( array( 'name' => 'core/edit-widgets' ) ); - $this->assertSame( array( '/wp/v2/types' ), _wp_preload_entity_actions( array( '/wp/v2/types' ), $context ), 'The paths are unchanged.' ); + $this->assertSame( array( '/wp/v2/types' ), _wp_preload_entity_actions( array( '/wp/v2/types' ), $site_editor ), 'The paths of the site editor root are unchanged.' ); + $this->assertSame( array( '/wp/v2/types' ), _wp_preload_entity_actions( array( '/wp/v2/types' ), $no_post ), 'The paths of a post editor without a post are unchanged.' ); + $this->assertSame( array( '/wp/v2/types' ), _wp_preload_entity_actions( array( '/wp/v2/types' ), $widgets ), 'The paths of the widgets editor are unchanged.' ); } /** diff --git a/tests/phpunit/tests/entity-fields/wpPreloadEntityFields.php b/tests/phpunit/tests/entity-fields/wpPreloadEntityFields.php index 064fbbf063566..58593c5727c36 100644 --- a/tests/phpunit/tests/entity-fields/wpPreloadEntityFields.php +++ b/tests/phpunit/tests/entity-fields/wpPreloadEntityFields.php @@ -32,12 +32,13 @@ public function test_the_fields_are_preloaded_on_the_block_editor_preload_paths( } /** - * The post editor does not preload the fields, whatever its `p` query arg. + * The post editor preloads the fields of the edited post type, which the + * post summary of its inspector reads, whatever its `p` query arg. * * @ticket 66229 */ - public function test_the_post_editor_does_not_preload_the_fields() { - $_GET['p'] = '/page'; + public function test_the_post_editor_preloads_the_fields_of_the_post_type() { + $_GET['p'] = '/wp_template'; $post = self::factory()->post->create_and_get( array( 'post_type' => 'page' ) ); $context = new WP_Block_Editor_Context( array( @@ -46,7 +47,7 @@ public function test_the_post_editor_does_not_preload_the_fields() { ) ); - $this->assertSame( array(), _wp_preload_entity_fields( array(), $context ) ); + $this->assertSame( array( '/wp/v2/entity-fields?kind=postType&name=page' ), _wp_preload_entity_fields( array(), $context ) ); } /**