diff --git a/src/wp-admin/site-editor.php b/src/wp-admin/site-editor.php index d27f461c9f595..5fc06a40788b5 100644 --- a/src/wp-admin/site-editor.php +++ b/src/wp-admin/site-editor.php @@ -182,7 +182,6 @@ static function ( $classes ) { array( rest_get_route_for_post_type_items( 'attachment' ), 'OPTIONS' ), array( rest_get_route_for_post_type_items( 'page' ), 'OPTIONS' ), '/wp/v2/types?context=view', - '/wp/v2/wp_registered_template?context=edit', '/wp/v2/types/wp_template?context=edit', '/wp/v2/types/wp_template_part?context=edit', '/wp/v2/templates?context=edit&per_page=-1', diff --git a/src/wp-includes/block-template-utils.php b/src/wp-includes/block-template-utils.php index b0ca8c6caff43..53954b7ff48ee 100644 --- a/src/wp-includes/block-template-utils.php +++ b/src/wp-includes/block-template-utils.php @@ -1358,8 +1358,6 @@ function get_block_template( $id, $template_type = 'wp_template' ) { return $template; } } - } elseif ( false === $active_templates[ $slug ] ) { - return null; } } @@ -1882,3 +1880,57 @@ function wp_maybe_activate_template( $post_id ) { $active_templates[ $post->post_name ] = $post->ID; update_option( 'active_templates', $active_templates ); } + +function _wp_migrate_active_templates() { + // Do not run during installation when the database is not yet available. + if ( wp_installing() ) { + return; + } + + $active_templates = get_option( 'active_templates', false ); + + if ( false !== $active_templates ) { + return; + } + + // Query all templates in the database. See `get_block_templates`. + $wp_query_args = array( + 'post_status' => 'publish', + 'post_type' => 'wp_template', + 'posts_per_page' => -1, + 'no_found_rows' => true, + 'lazy_load_term_meta' => false, + 'tax_query' => array( + array( + 'taxonomy' => 'wp_theme', + 'field' => 'name', + 'terms' => get_stylesheet(), + ), + ), + // Only get templates that are not inactive by default. We check these + // meta to make sure we don't fill the option with inactive templates + // created after the 6.9 release when for some reason the option is + // deleted. + 'meta_query' => array( + 'relation' => 'OR', + array( + 'key' => 'is_inactive_by_default', + 'compare' => 'NOT EXISTS', + ), + array( + 'key' => 'is_inactive_by_default', + 'value' => false, + 'compare' => '=', + ), + ), + ); + + $template_query = new WP_Query( $wp_query_args ); + $active_templates = array(); + + foreach ( $template_query->posts as $post ) { + $active_templates[ $post->post_name ] = $post->ID; + } + + update_option( 'active_templates', $active_templates ); +} diff --git a/src/wp-includes/block-template.php b/src/wp-includes/block-template.php index 2dd7b2e3c099d..220cb0b2a2c72 100644 --- a/src/wp-includes/block-template.php +++ b/src/wp-includes/block-template.php @@ -164,20 +164,10 @@ function resolve_block_template( $template_type, $template_hierarchy, $fallback_ $template_hierarchy ); - $object = get_queried_object(); - $specific_template = $object ? get_page_template_slug( $object ) : null; + $object_id = get_queried_object_id(); + $specific_template = $object_id && get_post( $object_id ) ? get_page_template_slug( $object_id ) : null; $active_templates = (array) get_option( 'active_templates', array() ); - // Remove templates slugs that are deactivated, except if it's the specific - // template or index. - $slugs = array_filter( - $slugs, - function ( $slug ) use ( $specific_template, $active_templates ) { - $should_ignore = $slug === $specific_template || 'index' === $slug; - return $should_ignore || ( ! isset( $active_templates[ $slug ] ) || false !== $active_templates[ $slug ] ); - } - ); - // We expect one template for each slug. Use the active template if it is // set and exists. Otherwise use the static template. $templates = array(); @@ -232,7 +222,7 @@ function ( $template ) { ); $templates = array_merge( $templates, get_registered_block_templates( $query ) ); - if ( $specific_template ) { + if ( $specific_template && in_array( $specific_template, $remaining_slugs, true ) ) { $templates = array_merge( $templates, get_block_templates( array( 'slug__in' => array( $specific_template ) ) ) ); } diff --git a/src/wp-includes/default-filters.php b/src/wp-includes/default-filters.php index 4a386eb53cb65..5dc54c3686b3a 100644 --- a/src/wp-includes/default-filters.php +++ b/src/wp-includes/default-filters.php @@ -570,6 +570,7 @@ // Post. add_action( 'init', 'create_initial_post_types', 0 ); // Highest priority. +add_action( 'init', '_wp_migrate_active_templates', 0 ); // Highest priority. add_action( 'admin_menu', '_add_post_type_submenus' ); add_action( 'before_delete_post', '_reset_front_page_settings_for_post' ); add_action( 'wp_trash_post', '_reset_front_page_settings_for_post' ); diff --git a/src/wp-includes/post.php b/src/wp-includes/post.php index 3940519d4dc15..1ab71ae53a2b4 100644 --- a/src/wp-includes/post.php +++ b/src/wp-includes/post.php @@ -398,7 +398,7 @@ function create_initial_post_types() { 'show_in_menu' => false, 'show_in_rest' => true, 'rewrite' => false, - 'rest_base' => 'wp_template', + 'rest_base' => 'created-templates', 'rest_controller_class' => 'WP_REST_Posts_Controller', 'late_route_registration' => true, 'capability_type' => array( 'template', 'templates' ), diff --git a/src/wp-includes/rest-api.php b/src/wp-includes/rest-api.php index d23931a589eed..7e3ed578ec792 100644 --- a/src/wp-includes/rest-api.php +++ b/src/wp-includes/rest-api.php @@ -263,15 +263,6 @@ function rest_api_default_filters() { * @since 4.7.0 */ function create_initial_rest_routes() { - global $wp_post_types; - - // Register the registered templates endpoint. For that we need to copy the - // wp_template post type so that it's available as an entity in core-data. - $wp_post_types['wp_registered_template'] = clone $wp_post_types['wp_template']; - $wp_post_types['wp_registered_template']->name = 'wp_registered_template'; - $wp_post_types['wp_registered_template']->rest_base = 'wp_registered_template'; - $wp_post_types['wp_registered_template']->rest_controller_class = 'WP_REST_Registered_Templates_Controller'; - foreach ( get_post_types( array( 'show_in_rest' => true ), 'objects' ) as $post_type ) { $controller = $post_type->get_rest_controller(); @@ -298,11 +289,14 @@ function create_initial_rest_routes() { } } + global $wp_post_types; + // Register the old templates endpoints. The WP_REST_Templates_Controller // and sub-controllers used linked to the wp_template post type, but are no // longer. They still require a post type object when contructing the class. // To maintain backward and changes to these controller classes, we make use // that the wp_template post type has the right information it needs. + $current_wp_template_rest_base = $wp_post_types['wp_template']->rest_base; $wp_post_types['wp_template']->rest_base = 'templates'; // Store the classes so they can be restored. $original_rest_controller_class = $wp_post_types['wp_template']->rest_controller_class; @@ -328,7 +322,7 @@ function create_initial_rest_routes() { $wp_post_types['wp_template']->autosave_rest_controller_class = $original_autosave_rest_controller_class; $wp_post_types['wp_template']->revisions_rest_controller_class = $original_revisions_rest_controller_class; // Restore the original base. - $wp_post_types['wp_template']->rest_base = 'wp_template'; + $wp_post_types['wp_template']->rest_base = $current_wp_template_rest_base; // Register the old routes. $autosaves_controller->register_routes(); @@ -356,6 +350,10 @@ function create_initial_rest_routes() { ) ); + // Registered templates. + $controller = new WP_REST_Registered_Templates_Controller(); + $controller->register_routes(); + // Post types. $controller = new WP_REST_Post_Types_Controller(); $controller->register_routes(); diff --git a/src/wp-includes/rest-api/endpoints/class-wp-rest-registered-templates-controller.php b/src/wp-includes/rest-api/endpoints/class-wp-rest-registered-templates-controller.php index 97b65af75742d..fd912bfb45048 100644 --- a/src/wp-includes/rest-api/endpoints/class-wp-rest-registered-templates-controller.php +++ b/src/wp-includes/rest-api/endpoints/class-wp-rest-registered-templates-controller.php @@ -1,6 +1,12 @@ rest_base = 'registered-templates'; + $this->namespace = 'wp/v2'; + } + public function register_routes() { // Lists all templates. register_rest_route( @@ -81,9 +87,8 @@ public function get_items( $request ) { $query_result = get_registered_block_templates( $query ); $templates = array(); foreach ( $query_result as $template ) { - $item = $this->prepare_item_for_response( $template, $request ); - $item->data['type'] = 'wp_registered_template'; - $templates[] = $this->prepare_response_for_collection( $item ); + $item = $this->prepare_item_for_response( $template, $request ); + $templates[] = $this->prepare_response_for_collection( $item ); } return rest_ensure_response( $templates ); @@ -97,8 +102,6 @@ public function get_item( $request ) { } $item = $this->prepare_item_for_response( $template, $request ); - // adjust the template type here instead - $item->data['type'] = 'wp_registered_template'; return rest_ensure_response( $item ); } } diff --git a/tests/phpunit/tests/rest-api/rest-schema-setup.php b/tests/phpunit/tests/rest-api/rest-schema-setup.php index 2946949d9d84d..bf3d0d4703f37 100644 --- a/tests/phpunit/tests/rest-api/rest-schema-setup.php +++ b/tests/phpunit/tests/rest-api/rest-schema-setup.php @@ -157,14 +157,14 @@ public function test_expected_routes_in_schema() { '/wp/v2/templates/(?P([^\/:<>\*\?"\|]+(?:\/[^\/:<>\*\?"\|]+)?)[\/\w%-]+)/autosaves/(?P[\d]+)', '/wp/v2/templates/(?P([^\/:<>\*\?"\|]+(?:\/[^\/:<>\*\?"\|]+)?)[\/\w%-]+)/revisions', '/wp/v2/templates/(?P([^\/:<>\*\?"\|]+(?:\/[^\/:<>\*\?"\|]+)?)[\/\w%-]+)/revisions/(?P[\d]+)', - '/wp/v2/wp_registered_template', - '/wp/v2/wp_registered_template/(?P([^\/:<>\*\?"\|]+(?:\/[^\/:<>\*\?"\|]+)?)[\/\w%-]+)', - '/wp/v2/wp_template', - '/wp/v2/wp_template/(?P[\d]+)', - '/wp/v2/wp_template/(?P[\d]+)/autosaves', - '/wp/v2/wp_template/(?P[\d]+)/autosaves/(?P[\d]+)', - '/wp/v2/wp_template/(?P[\d]+)/revisions', - '/wp/v2/wp_template/(?P[\d]+)/revisions/(?P[\d]+)', + '/wp/v2/registered-templates', + '/wp/v2/registered-templates/(?P([^\/:<>\*\?"\|]+(?:\/[^\/:<>\*\?"\|]+)?)[\/\w%-]+)', + '/wp/v2/created-templates', + '/wp/v2/created-templates/(?P[\d]+)', + '/wp/v2/created-templates/(?P[\d]+)/autosaves', + '/wp/v2/created-templates/(?P[\d]+)/autosaves/(?P[\d]+)', + '/wp/v2/created-templates/(?P[\d]+)/revisions', + '/wp/v2/created-templates/(?P[\d]+)/revisions/(?P[\d]+)', '/wp/v2/templates/lookup', '/wp/v2/themes', '/wp/v2/themes/(?P[^\/:<>\*\?"\|]+(?:\/[^\/:<>\*\?"\|]+)?)', diff --git a/tests/qunit/fixtures/wp-api-generated.js b/tests/qunit/fixtures/wp-api-generated.js index 329ecf84f3030..de83c1248e3db 100644 --- a/tests/qunit/fixtures/wp-api-generated.js +++ b/tests/qunit/fixtures/wp-api-generated.js @@ -5508,7 +5508,7 @@ mockedApiResponse.Schema = { } ] }, - "/wp/v2/wp_template/(?P[\\d]+)/revisions": { + "/wp/v2/created-templates/(?P[\\d]+)/revisions": { "namespace": "wp/v2", "methods": [ "GET" @@ -5606,7 +5606,7 @@ mockedApiResponse.Schema = { } ] }, - "/wp/v2/wp_template/(?P[\\d]+)/revisions/(?P[\\d]+)": { + "/wp/v2/created-templates/(?P[\\d]+)/revisions/(?P[\\d]+)": { "namespace": "wp/v2", "methods": [ "GET", @@ -5666,7 +5666,7 @@ mockedApiResponse.Schema = { } ] }, - "/wp/v2/wp_template/(?P[\\d]+)/autosaves": { + "/wp/v2/created-templates/(?P[\\d]+)/autosaves": { "namespace": "wp/v2", "methods": [ "GET", @@ -5865,7 +5865,7 @@ mockedApiResponse.Schema = { } ] }, - "/wp/v2/wp_template/(?P[\\d]+)/autosaves/(?P[\\d]+)": { + "/wp/v2/created-templates/(?P[\\d]+)/autosaves/(?P[\\d]+)": { "namespace": "wp/v2", "methods": [ "GET" @@ -5901,7 +5901,7 @@ mockedApiResponse.Schema = { } ] }, - "/wp/v2/wp_template": { + "/wp/v2/created-templates": { "namespace": "wp/v2", "methods": [ "GET", @@ -6265,12 +6265,12 @@ mockedApiResponse.Schema = { "_links": { "self": [ { - "href": "http://example.org/index.php?rest_route=/wp/v2/wp_template" + "href": "http://example.org/index.php?rest_route=/wp/v2/created-templates" } ] } }, - "/wp/v2/wp_template/(?P[\\d]+)": { + "/wp/v2/created-templates/(?P[\\d]+)": { "namespace": "wp/v2", "methods": [ "GET", @@ -8671,85 +8671,6 @@ mockedApiResponse.Schema = { } ] }, - "/wp/v2/wp_registered_template": { - "namespace": "wp/v2", - "methods": [ - "GET" - ], - "endpoints": [ - { - "methods": [ - "GET" - ], - "args": { - "context": { - "description": "Scope under which the request is made; determines fields present in response.", - "type": "string", - "enum": [ - "view", - "embed", - "edit" - ], - "default": "view", - "required": false - }, - "wp_id": { - "description": "Limit to the specified post id.", - "type": "integer", - "required": false - }, - "area": { - "description": "Limit to the specified template part area.", - "type": "string", - "required": false - }, - "post_type": { - "description": "Post type to get the templates for.", - "type": "string", - "required": false - } - } - } - ], - "_links": { - "self": [ - { - "href": "http://example.org/index.php?rest_route=/wp/v2/wp_registered_template" - } - ] - } - }, - "/wp/v2/wp_registered_template/(?P([^\\/:<>\\*\\?\"\\|]+(?:\\/[^\\/:<>\\*\\?\"\\|]+)?)[\\/\\w%-]+)": { - "namespace": "wp/v2", - "methods": [ - "GET" - ], - "endpoints": [ - { - "methods": [ - "GET" - ], - "args": { - "id": { - "description": "The id of a template", - "type": "string", - "required": false - }, - "context": { - "description": "Scope under which the request is made; determines fields present in response.", - "type": "string", - "enum": [ - "view", - "embed", - "edit" - ], - "default": "view", - "required": false - } - } - } - ] - }, "/wp/v2/templates/(?P([^\\/:<>\\*\\?\"\\|]+(?:\\/[^\\/:<>\\*\\?\"\\|]+)?)[\\/\\w%-]+)/autosaves": { "namespace": "wp/v2", "methods": [ @@ -9434,6 +9355,85 @@ mockedApiResponse.Schema = { } ] }, + "/wp/v2/registered-templates": { + "namespace": "wp/v2", + "methods": [ + "GET" + ], + "endpoints": [ + { + "methods": [ + "GET" + ], + "args": { + "context": { + "description": "Scope under which the request is made; determines fields present in response.", + "type": "string", + "enum": [ + "view", + "embed", + "edit" + ], + "default": "view", + "required": false + }, + "wp_id": { + "description": "Limit to the specified post id.", + "type": "integer", + "required": false + }, + "area": { + "description": "Limit to the specified template part area.", + "type": "string", + "required": false + }, + "post_type": { + "description": "Post type to get the templates for.", + "type": "string", + "required": false + } + } + } + ], + "_links": { + "self": [ + { + "href": "http://example.org/index.php?rest_route=/wp/v2/registered-templates" + } + ] + } + }, + "/wp/v2/registered-templates/(?P([^\\/:<>\\*\\?\"\\|]+(?:\\/[^\\/:<>\\*\\?\"\\|]+)?)[\\/\\w%-]+)": { + "namespace": "wp/v2", + "methods": [ + "GET" + ], + "endpoints": [ + { + "methods": [ + "GET" + ], + "args": { + "id": { + "description": "The id of a template", + "type": "string", + "required": false + }, + "context": { + "description": "Scope under which the request is made; determines fields present in response.", + "type": "string", + "enum": [ + "view", + "embed", + "edit" + ], + "default": "view", + "required": false + } + } + } + ] + }, "/wp/v2/types": { "namespace": "wp/v2", "methods": [ @@ -10809,8 +10809,7 @@ mockedApiResponse.Schema = { "wp_global_styles": "wp_global_styles", "wp_navigation": "wp_navigation", "wp_font_family": "wp_font_family", - "wp_font_face": "wp_font_face", - "wp_registered_template": "wp_registered_template" + "wp_font_face": "wp_font_face" } }, "required": false @@ -14768,7 +14767,7 @@ mockedApiResponse.TypesCollection = { "slug": "wp_template", "icon": null, "taxonomies": [], - "rest_base": "wp_template", + "rest_base": "created-templates", "rest_namespace": "wp/v2", "template": [], "template_lock": false, @@ -14780,7 +14779,7 @@ mockedApiResponse.TypesCollection = { ], "wp:items": [ { - "href": "http://example.org/index.php?rest_route=/wp/v2/wp_template" + "href": "http://example.org/index.php?rest_route=/wp/v2/created-templates" } ], "curies": [ @@ -14951,38 +14950,6 @@ mockedApiResponse.TypesCollection = { } ] } - }, - "wp_registered_template": { - "description": "Templates to include in your theme.", - "hierarchical": false, - "has_archive": false, - "name": "Templates", - "slug": "wp_registered_template", - "icon": null, - "taxonomies": [], - "rest_base": "wp_registered_template", - "rest_namespace": "wp/v2", - "template": [], - "template_lock": false, - "_links": { - "collection": [ - { - "href": "http://example.org/index.php?rest_route=/wp/v2/types" - } - ], - "wp:items": [ - { - "href": "http://example.org/index.php?rest_route=/wp/v2/wp_registered_template" - } - ], - "curies": [ - { - "name": "wp", - "href": "https://api.w.org/{rel}", - "templated": true - } - ] - } } }; @@ -15590,7 +15557,7 @@ mockedApiResponse.settings = { "page_for_posts": 0, "default_ping_status": "open", "default_comment_status": "open", - "active_templates": null, + "active_templates": [], "site_logo": null, "site_icon": 0 };