| 1 |
<?php |
| 2 |
/** |
| 3 |
* WordPress 7.0 compatibility functions for the Gutenberg |
| 4 |
* editor plugin changes related to REST API. |
| 5 |
* |
| 6 |
* @package gutenberg |
| 7 |
*/ |
| 8 |
|
| 9 |
/** |
| 10 |
* Registers the Block Patterns REST API routes. |
| 11 |
*/ |
| 12 |
function gutenberg_register_block_patterns_controller_endpoints() { |
| 13 |
$block_patterns_controller = new Gutenberg_REST_Block_Patterns_Controller_7_0(); |
| 14 |
$block_patterns_controller->register_routes(); |
| 15 |
} |
| 16 |
add_action( 'rest_api_init', 'gutenberg_register_block_patterns_controller_endpoints' ); |
| 17 |
|
| 18 |
/** |
| 19 |
* Registers the Registered Templates REST API routes. |
| 20 |
* The template activation experiment registers its own routes, so we only register the registered templates controller if the experiment is not enabled. |
| 21 |
* See: lib/compat/wordpress-7.0/template-activate.php |
| 22 |
* |
| 23 |
* @see Gutenberg_REST_Registered_Templates_Controller |
| 24 |
* @see Gutenberg_REST_Templates_Controller_7_0 |
| 25 |
*/ |
| 26 |
if ( ! gutenberg_is_experiment_enabled( 'active_templates' ) ) { |
| 27 |
function gutenberg_modify_wp_template_post_type_args_7_0( $args ) { |
| 28 |
$args['rest_controller_class'] = 'Gutenberg_REST_Templates_Controller_7_0'; |
| 29 |
$args['late_route_registration'] = true; |
| 30 |
return $args; |
| 31 |
} |
| 32 |
add_filter( 'register_wp_template_post_type_args', 'gutenberg_modify_wp_template_post_type_args_7_0' ); |
| 33 |
} |
| 34 |
|
| 35 |
/** |
| 36 |
* Registers the Registered Templates Parts REST API routes. |
| 37 |
* The template activation experiment does not, however, register the routes for the wp_template_part post type, |
| 38 |
* so we need to register the routes for that post type here. |
| 39 |
* See: lib/compat/wordpress-7.0/template-activate.php |
| 40 |
* |
| 41 |
* @see Gutenberg_REST_Registered_Templates_Controller |
| 42 |
* @see Gutenberg_REST_Templates_Controller_7_0 |
| 43 |
*/ |
| 44 |
function gutenberg_modify_wp_template_part_post_type_args_7_0( $args ) { |
| 45 |
$args['rest_controller_class'] = 'Gutenberg_REST_Templates_Controller_7_0'; |
| 46 |
$args['late_route_registration'] = true; |
| 47 |
return $args; |
| 48 |
} |
| 49 |
add_filter( 'register_wp_template_part_post_type_args', 'gutenberg_modify_wp_template_part_post_type_args_7_0' ); |
| 50 |
|
| 51 |
/** |
| 52 |
* Registers the 'navigation-overlay' template part area. |
| 53 |
* |
| 54 |
* @param array $areas Array of template part area definitions. |
| 55 |
* @return array Modified array of template part area definitions. |
| 56 |
*/ |
| 57 |
function gutenberg_register_overlay_template_part_area( $areas ) { |
| 58 |
foreach ( $areas as $area ) { |
| 59 |
if ( isset( $area['area'] ) && 'navigation-overlay' === $area['area'] ) { |
| 60 |
return $areas; |
| 61 |
} |
| 62 |
} |
| 63 |
|
| 64 |
$areas[] = array( |
| 65 |
'area' => 'navigation-overlay', |
| 66 |
'label' => __( 'Navigation Overlay', 'gutenberg' ), |
| 67 |
'description' => __( |
| 68 |
'The Navigation Overlay template defines an overlay area that typically contains navigation links and can be toggled open and closed.' |
| 69 |
), |
| 70 |
'icon' => 'navigation-overlay', |
| 71 |
'area_tag' => 'div', |
| 72 |
); |
| 73 |
|
| 74 |
return $areas; |
| 75 |
} |
| 76 |
add_filter( 'default_wp_template_part_areas', 'gutenberg_register_overlay_template_part_area' ); |
| 77 |
|
| 78 |
/** |
| 79 |
* Adds user global styles link relation to all theme responses. |
| 80 |
* |
| 81 |
* This ensures that all themes (including classic themes) have access to the |
| 82 |
* wp:user-global-styles link, which is required for the font library to function. |
| 83 |
* |
| 84 |
* WordPress core only adds this link for block themes with theme.json support. |
| 85 |
* This filter extends that functionality to all themes. |
| 86 |
* |
| 87 |
* @param WP_REST_Response $response The response object. |
| 88 |
* @param WP_Theme $theme Theme object used to create response. |
| 89 |
* @return WP_REST_Response Modified response object. |
| 90 |
*/ |
| 91 |
function gutenberg_rest_theme_global_styles_link_rel_7_0( $response, $theme ) { |
| 92 |
// Only add the link for the active theme to match WordPress core behavior. |
| 93 |
if ( $theme->get_stylesheet() !== get_stylesheet() ) { |
| 94 |
return $response; |
| 95 |
} |
| 96 |
|
| 97 |
// Check if the link already exists (WordPress core adds it for block themes). |
| 98 |
$all_links = $response->get_links(); |
| 99 |
if ( isset( $all_links['https://api.w.org/user-global-styles'] ) ) { |
| 100 |
return $response; |
| 101 |
} |
| 102 |
|
| 103 |
// Get or create the global styles post ID for this theme. |
| 104 |
// Now that we've removed the theme.json check, this works for all themes. |
| 105 |
$global_styles_id = WP_Theme_JSON_Resolver_Gutenberg::get_user_global_styles_post_id(); |
| 106 |
if ( ! $global_styles_id ) { |
| 107 |
return $response; |
| 108 |
} |
| 109 |
|
| 110 |
// Add the wp:user-global-styles link. |
| 111 |
$response->add_link( |
| 112 |
'https://api.w.org/user-global-styles', |
| 113 |
rest_url( 'wp/v2/global-styles/' . $global_styles_id ) |
| 114 |
); |
| 115 |
|
| 116 |
return $response; |
| 117 |
} |
| 118 |
add_filter( 'rest_prepare_theme', 'gutenberg_rest_theme_global_styles_link_rel_7_0', 10, 2 ); |
| 119 |
|
| 120 |
/** |
| 121 |
* Overrides the default REST controller for autosaves to fix real-time |
| 122 |
* collaboration on draft posts. |
| 123 |
* |
| 124 |
* When RTC is enabled, draft autosaves from all users update the post directly |
| 125 |
* instead of creating per-user autosave revisions depending on post lock and |
| 126 |
* assigned author. |
| 127 |
* |
| 128 |
* Only overrides when autosave_rest_controller_class is not explicitly set, |
| 129 |
* i.e. when WP_REST_Autosaves_Controller would be used by default. Post types |
| 130 |
* with their own specialized autosave controller (e.g. templates) are left alone. |
| 131 |
*/ |
| 132 |
function gutenberg_override_autosaves_rest_controller( $args ) { |
| 133 |
if ( empty( $args['autosave_rest_controller_class'] ) ) { |
| 134 |
$args['autosave_rest_controller_class'] = 'Gutenberg_REST_Autosaves_Controller'; |
| 135 |
} |
| 136 |
return $args; |
| 137 |
} |
| 138 |
|
| 139 |
add_filter( 'register_post_type_args', 'gutenberg_override_autosaves_rest_controller', 10, 1 ); |
| 140 |
|
| 141 |
/** |
| 142 |
* Overrides the default REST controller for revisions to support nested |
| 143 |
* _fields parameters (e.g. content.raw without content.rendered). |
| 144 |
* |
| 145 |
* The core WP_REST_Revisions_Controller uses in_array() checks for content, |
| 146 |
* title, excerpt, and guid fields, which prevents sub-field filtering via |
| 147 |
* the _fields parameter. The Gutenberg override uses rest_is_field_included() |
| 148 |
* so that clients can avoid expensive server-side rendering when only raw |
| 149 |
* data is needed. |
| 150 |
* |
| 151 |
* Only overrides when revisions_rest_controller_class is not explicitly set. |
| 152 |
*/ |
| 153 |
function gutenberg_override_revisions_rest_controller( $args ) { |
| 154 |
if ( empty( $args['revisions_rest_controller_class'] ) ) { |
| 155 |
$args['revisions_rest_controller_class'] = 'Gutenberg_REST_Revisions_Controller'; |
| 156 |
} |
| 157 |
return $args; |
| 158 |
} |
| 159 |
|
| 160 |
add_filter( 'register_post_type_args', 'gutenberg_override_revisions_rest_controller', 10, 1 ); |
| 161 |
|