register_routes(); } add_action( 'rest_api_init', 'gutenberg_register_block_patterns_controller_endpoints' ); /** * Registers the Registered Templates REST API routes. * The template activation experiment registers its own routes, so we only register the registered templates controller if the experiment is not enabled. * See: lib/compat/wordpress-7.0/template-activate.php * * @see Gutenberg_REST_Registered_Templates_Controller * @see Gutenberg_REST_Templates_Controller_7_0 */ if ( ! gutenberg_is_experiment_enabled( 'active_templates' ) ) { function gutenberg_modify_wp_template_post_type_args_7_0( $args ) { $args['rest_controller_class'] = 'Gutenberg_REST_Templates_Controller_7_0'; $args['late_route_registration'] = true; return $args; } add_filter( 'register_wp_template_post_type_args', 'gutenberg_modify_wp_template_post_type_args_7_0' ); } /** * Registers the Registered Templates Parts REST API routes. * The template activation experiment does not, however, register the routes for the wp_template_part post type, * so we need to register the routes for that post type here. * See: lib/compat/wordpress-7.0/template-activate.php * * @see Gutenberg_REST_Registered_Templates_Controller * @see Gutenberg_REST_Templates_Controller_7_0 */ function gutenberg_modify_wp_template_part_post_type_args_7_0( $args ) { $args['rest_controller_class'] = 'Gutenberg_REST_Templates_Controller_7_0'; $args['late_route_registration'] = true; return $args; } add_filter( 'register_wp_template_part_post_type_args', 'gutenberg_modify_wp_template_part_post_type_args_7_0' ); /** * Registers the 'navigation-overlay' template part area. * * @param array $areas Array of template part area definitions. * @return array Modified array of template part area definitions. */ function gutenberg_register_overlay_template_part_area( $areas ) { foreach ( $areas as $area ) { if ( isset( $area['area'] ) && 'navigation-overlay' === $area['area'] ) { return $areas; } } $areas[] = array( 'area' => 'navigation-overlay', 'label' => __( 'Navigation Overlay', 'gutenberg' ), 'description' => __( 'The Navigation Overlay template defines an overlay area that typically contains navigation links and can be toggled open and closed.' ), 'icon' => 'navigation-overlay', 'area_tag' => 'div', ); return $areas; } add_filter( 'default_wp_template_part_areas', 'gutenberg_register_overlay_template_part_area' ); /** * Adds user global styles link relation to all theme responses. * * This ensures that all themes (including classic themes) have access to the * wp:user-global-styles link, which is required for the font library to function. * * WordPress core only adds this link for block themes with theme.json support. * This filter extends that functionality to all themes. * * @param WP_REST_Response $response The response object. * @param WP_Theme $theme Theme object used to create response. * @return WP_REST_Response Modified response object. */ function gutenberg_rest_theme_global_styles_link_rel_7_0( $response, $theme ) { // Only add the link for the active theme to match WordPress core behavior. if ( $theme->get_stylesheet() !== get_stylesheet() ) { return $response; } // Check if the link already exists (WordPress core adds it for block themes). $all_links = $response->get_links(); if ( isset( $all_links['https://api.w.org/user-global-styles'] ) ) { return $response; } // Get or create the global styles post ID for this theme. // Now that we've removed the theme.json check, this works for all themes. $global_styles_id = WP_Theme_JSON_Resolver_Gutenberg::get_user_global_styles_post_id(); if ( ! $global_styles_id ) { return $response; } // Add the wp:user-global-styles link. $response->add_link( 'https://api.w.org/user-global-styles', rest_url( 'wp/v2/global-styles/' . $global_styles_id ) ); return $response; } add_filter( 'rest_prepare_theme', 'gutenberg_rest_theme_global_styles_link_rel_7_0', 10, 2 ); /** * Overrides the default REST controller for autosaves to fix real-time * collaboration on draft posts. * * When RTC is enabled, draft autosaves from all users update the post directly * instead of creating per-user autosave revisions depending on post lock and * assigned author. * * Only overrides when autosave_rest_controller_class is not explicitly set, * i.e. when WP_REST_Autosaves_Controller would be used by default. Post types * with their own specialized autosave controller (e.g. templates) are left alone. */ function gutenberg_override_autosaves_rest_controller( $args ) { if ( empty( $args['autosave_rest_controller_class'] ) ) { $args['autosave_rest_controller_class'] = 'Gutenberg_REST_Autosaves_Controller'; } return $args; } add_filter( 'register_post_type_args', 'gutenberg_override_autosaves_rest_controller', 10, 1 ); /** * Overrides the default REST controller for revisions to support nested * _fields parameters (e.g. content.raw without content.rendered). * * The core WP_REST_Revisions_Controller uses in_array() checks for content, * title, excerpt, and guid fields, which prevents sub-field filtering via * the _fields parameter. The Gutenberg override uses rest_is_field_included() * so that clients can avoid expensive server-side rendering when only raw * data is needed. * * Only overrides when revisions_rest_controller_class is not explicitly set. */ function gutenberg_override_revisions_rest_controller( $args ) { if ( empty( $args['revisions_rest_controller_class'] ) ) { $args['revisions_rest_controller_class'] = 'Gutenberg_REST_Revisions_Controller'; } return $args; } add_filter( 'register_post_type_args', 'gutenberg_override_revisions_rest_controller', 10, 1 );