diff --git a/src/wp-admin/edit-form-blocks.php b/src/wp-admin/edit-form-blocks.php index ae5f0481ff..0e367eb96b 100644 --- a/src/wp-admin/edit-form-blocks.php +++ b/src/wp-admin/edit-form-blocks.php @@ -23,7 +23,8 @@ if ( ! defined( 'ABSPATH' ) ) { */ global $post_type, $post_type_object, $post, $title, $editor_styles, $wp_meta_boxes; -$editor_name = 'post-editor'; +$editor_name = 'post-editor'; +$block_editor_context = new WP_Block_Editor_Context( array( 'post' => $post ) ); // Flag that we're loading the block editor. $current_screen = get_current_screen(); @@ -58,40 +59,7 @@ $preload_paths = array( sprintf( '/wp/v2/%s/%d/autosaves?context=edit', $rest_base, $post->ID ), ); - -/** - * Preload common data by specifying an array of REST API paths that will be preloaded. - * - * Filters the array of paths that will be preloaded. - * - * @since 5.0.0 - * - * @param string[] $preload_paths Array of paths to preload. - * @param WP_Post $post Post being edited. - */ -$preload_paths = apply_filters( 'block_editor_preload_paths', $preload_paths, $post ); - -/* - * Ensure the global $post remains the same after API data is preloaded. - * Because API preloading can call the_content and other filters, plugins - * can unexpectedly modify $post. - */ -$backup_global_post = clone $post; - -$preload_data = array_reduce( - $preload_paths, - 'rest_preload_api_request', - array() -); - -// Restore the global $post as it was before API preloading. -$post = $backup_global_post; - -wp_add_inline_script( - 'wp-api-fetch', - sprintf( 'wp.apiFetch.use( wp.apiFetch.createPreloadingMiddleware( %s ) );', wp_json_encode( $preload_data ) ), - 'after' -); +block_editor_rest_api_preload( $preload_paths, $block_editor_context ); wp_add_inline_script( 'wp-blocks', diff --git a/src/wp-includes/block-editor.php b/src/wp-includes/block-editor.php index 745cdcdb65..f1ec5d2d1a 100644 --- a/src/wp-includes/block-editor.php +++ b/src/wp-includes/block-editor.php @@ -269,3 +269,75 @@ function get_block_editor_settings( $editor_name, $custom_settings = array() ) { return $editor_settings; } + +/** + * Preloads common data used with the block editor by specifying an array of + * REST API paths that will be preloaded for a given block editor context. + * + * @since 5.8.0 + * + * @global WP_Post $post Global post object. + * + * @param array $preload_paths List of paths to preload. + * @param WP_Block_Editor_Context $block_editor_context The current block editor context. + * + * @return void + */ +function block_editor_rest_api_preload( array $preload_paths, $block_editor_context ) { + global $post; + + /** + * Filters the array of REST API paths that will be used to preloaded common data + * to use with the block editor. + * + * @since 5.8.0 + * + * @param string[] $preload_paths Array of paths to preload. + */ + $preload_paths = apply_filters( 'block_editor_rest_api_preload_paths', $preload_paths, $block_editor_context ); + if ( ! empty( $block_editor_context->post ) ) { + $selected_post = $block_editor_context->post; + + /** + * Preload common data by specifying an array of REST API paths that will be preloaded. + * + * Filters the array of paths that will be preloaded. + * + * @since 5.0.0 + * @deprecated 5.8.0 The hook transitioned to support also screens that don't contain $post instance. + * + * @param string[] $preload_paths Array of paths to preload. + * @param WP_Post $selected_post Post being edited. + */ + $preload_paths = apply_filters_deprecated( 'block_editor_preload_paths', array( $preload_paths, $selected_post ), '5.8.0', 'block_editor_rest_api_preload_paths' ); + } + + if ( empty( $preload_paths ) ) { + return; + } + + /* + * Ensure the global $post remains the same after API data is preloaded. + * Because API preloading can call the_content and other filters, plugins + * can unexpectedly modify $post. + */ + $backup_global_post = ! empty( $post ) ? clone $post : $post; + + $preload_data = array_reduce( + $preload_paths, + 'rest_preload_api_request', + array() + ); + + // Restore the global $post as it was before API preloading. + $post = $backup_global_post; + + wp_add_inline_script( + 'wp-api-fetch', + sprintf( + 'wp.apiFetch.use( wp.apiFetch.createPreloadingMiddleware( %s ) );', + wp_json_encode( $preload_data ) + ), + 'after' + ); +} diff --git a/src/wp-settings.php b/src/wp-settings.php index 6a49408b79..79574e4b2f 100644 --- a/src/wp-settings.php +++ b/src/wp-settings.php @@ -284,6 +284,7 @@ require ABSPATH . WPINC . '/sitemaps/class-wp-sitemaps-stylesheet.php'; require ABSPATH . WPINC . '/sitemaps/providers/class-wp-sitemaps-posts.php'; require ABSPATH . WPINC . '/sitemaps/providers/class-wp-sitemaps-taxonomies.php'; require ABSPATH . WPINC . '/sitemaps/providers/class-wp-sitemaps-users.php'; +require ABSPATH . WPINC . '/class-wp-block-editor-context.php'; require ABSPATH . WPINC . '/class-wp-block-type.php'; require ABSPATH . WPINC . '/class-wp-block-pattern-categories-registry.php'; require ABSPATH . WPINC . '/class-wp-block-patterns-registry.php'; diff --git a/tests/phpunit/tests/blocks/block-editor.php b/tests/phpunit/tests/blocks/block-editor.php index 722c17a79f..0ffad06fa1 100644 --- a/tests/phpunit/tests/blocks/block-editor.php +++ b/tests/phpunit/tests/blocks/block-editor.php @@ -63,6 +63,24 @@ class WP_Test_Block_Editor extends WP_UnitTestCase { ); } + /** + * @ticket 52920 + */ + function test_block_editor_context_no_settings() { + $context = new WP_Block_Editor_Context(); + + $this->assertNull( $context->post ); + } + + /** + * @ticket 52920 + */ + function test_block_editor_context_post() { + $context = new WP_Block_Editor_Context( array( 'post' => $this->post ) ); + + $this->assertSame( $this->post, $context->post ); + } + /** * @ticket 52920 * @expectedDeprecated block_categories @@ -299,4 +317,71 @@ class WP_Test_Block_Editor extends WP_UnitTestCase { $settings ); } + + /** + * @ticket 52920 + */ + function test_block_editor_rest_api_preload_no_paths() { + $context = new WP_Block_Editor_Context(); + block_editor_rest_api_preload( array(), $context ); + + $after = implode( '', wp_scripts()->registered['wp-api-fetch']->extra['after'] ); + $this->assertNotContains( 'wp.apiFetch.createPreloadingMiddleware', $after ); + } + + /** + * @ticket 52920 + * @expectedDeprecated block_editor_preload_paths + */ + function test_block_editor_rest_api_preload_deprecated_filter_post_editor() { + function filter_remove_preload_paths( $preload_paths, $post ) { + if ( empty( $post ) ) { + return $preload_paths; + } + return array(); + } + add_filter( 'block_editor_preload_paths', 'filter_remove_preload_paths', 10, 2 ); + + $context = new WP_Block_Editor_Context( array( 'post' => get_post() ) ); + block_editor_rest_api_preload( + array( + array( '/wp/v2/blocks', 'OPTIONS' ), + ), + $context + ); + + remove_filter( 'block_editor_preload_paths', 'filter_remove_preload_paths' ); + + $after = implode( '', wp_scripts()->registered['wp-api-fetch']->extra['after'] ); + $this->assertNotContains( 'wp.apiFetch.createPreloadingMiddleware', $after ); + } + + /** + * @ticket 52920 + */ + function test_block_editor_rest_api_preload_filter_all() { + function filter_add_preload_paths( $preload_paths, WP_Block_Editor_Context $context ) { + if ( empty( $context->post ) ) { + array_push( $preload_paths, array( '/wp/v2/types', 'OPTIONS' ) ); + } + + return $preload_paths; + } + add_filter( 'block_editor_rest_api_preload_paths', 'filter_add_preload_paths', 10, 2 ); + + $context = new WP_Block_Editor_Context(); + block_editor_rest_api_preload( + array( + array( '/wp/v2/blocks', 'OPTIONS' ), + ), + $context + ); + + remove_filter( 'block_editor_rest_api_preload_paths', 'filter_add_preload_paths' ); + + $after = implode( '', wp_scripts()->registered['wp-api-fetch']->extra['after'] ); + $this->assertContains( 'wp.apiFetch.createPreloadingMiddleware', $after ); + $this->assertContains( '"\/wp\/v2\/blocks"', $after ); + $this->assertContains( '"\/wp\/v2\/types"', $after ); + } }