Skip to content

Commit 1839787

Browse files
ellatrixmcsfpriethorcostasovojkmassel
authored
Template activation: improve back compat (WordPress#72223)
Co-authored-by: ellatrix <ellatrix@git.wordpress.org> Co-authored-by: mcsf <mcsf@git.wordpress.org> Co-authored-by: priethor <priethor@git.wordpress.org> Co-authored-by: costasovo <costasovo@git.wordpress.org> Co-authored-by: jkmassel <jkmassel@git.wordpress.org>
1 parent 61199c6 commit 1839787

File tree

13 files changed

+443
-105
lines changed

13 files changed

+443
-105
lines changed

backport-changelog/6.9/8063.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,3 +9,4 @@ https://github.com/WordPress/wordpress-develop/pull/8063
99
* https://github.com/WordPress/gutenberg/pull/72049
1010
* https://github.com/WordPress/gutenberg/pull/72011
1111
* https://github.com/WordPress/gutenberg/pull/72141
12+
* https://github.com/WordPress/gutenberg/pull/72223

lib/compat/wordpress-6.9/template-activate.php

Lines changed: 270 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,9 @@ function gutenberg_maintain_templates_routes() {
4545
// templates controller, so we need to check if the id is an
4646
// integer to make sure it's the proper post type endpoint.
4747
if ( ! is_int( $post_arr['id'] ) ) {
48-
return null;
48+
// See _build_block_template_result_from_file, registered
49+
// templates always set the theme to the active theme.
50+
return get_stylesheet();
4951
}
5052
$terms = get_the_terms( $post_arr['id'], 'wp_theme' );
5153
if ( is_wp_error( $terms ) || empty( $terms ) ) {
@@ -524,3 +526,270 @@ function gutenberg_migrate_existing_templates() {
524526

525527
update_option( 'active_templates', $active_templates );
526528
}
529+
530+
add_action( 'save_post_wp_template', 'gutenberg_maybe_update_active_templates' );
531+
function gutenberg_maybe_update_active_templates( $post_id ) {
532+
$post = get_post( $post_id );
533+
$is_inactive_by_default = get_post_meta( $post_id, 'is_inactive_by_default', true );
534+
if ( $is_inactive_by_default ) {
535+
return;
536+
}
537+
$active_templates = get_option( 'active_templates', array() );
538+
$active_templates[ $post->post_name ] = $post->ID;
539+
update_option( 'active_templates', $active_templates );
540+
}
541+
542+
add_action( 'pre_get_block_template', 'gutenberg_get_block_template', 10, 3 );
543+
544+
///////////////////////////////////////////////////////////////////////
545+
// This function is a copy of core's, except for the marked section. //
546+
///////////////////////////////////////////////////////////////////////
547+
function gutenberg_get_block_template( $output, $id, $template_type ) {
548+
if ( 'wp_template' !== $template_type ) {
549+
return $output;
550+
}
551+
$parts = explode( '//', $id, 2 );
552+
if ( count( $parts ) < 2 ) {
553+
return null;
554+
}
555+
list( $theme, $slug ) = $parts;
556+
557+
//////////////////////////////
558+
// START CORE MODIFICATIONS //
559+
//////////////////////////////
560+
$active_templates = get_option( 'active_templates', array() );
561+
562+
if ( ! empty( $active_templates[ $slug ] ) ) {
563+
if ( is_int( $active_templates[ $slug ] ) ) {
564+
$post = get_post( $active_templates[ $slug ] );
565+
if ( $post && 'publish' === $post->post_status ) {
566+
$template = _build_block_template_result_from_post( $post );
567+
568+
if ( ! is_wp_error( $template ) && $theme === $template->theme ) {
569+
return $template;
570+
}
571+
}
572+
} elseif ( false === $active_templates[ $slug ] ) {
573+
return null;
574+
}
575+
}
576+
////////////////////////////
577+
// END CORE MODIFICATIONS //
578+
////////////////////////////
579+
580+
$wp_query_args = array(
581+
'post_name__in' => array( $slug ),
582+
'post_type' => $template_type,
583+
'post_status' => array( 'auto-draft', 'draft', 'publish', 'trash' ),
584+
'posts_per_page' => 1,
585+
'no_found_rows' => true,
586+
'tax_query' => array(
587+
array(
588+
'taxonomy' => 'wp_theme',
589+
'field' => 'name',
590+
'terms' => $theme,
591+
),
592+
),
593+
);
594+
$template_query = new WP_Query( $wp_query_args );
595+
$posts = $template_query->posts;
596+
597+
if ( count( $posts ) > 0 ) {
598+
$template = _build_block_template_result_from_post( $posts[0] );
599+
600+
//////////////////////////////
601+
// START CORE MODIFICATIONS //
602+
//////////////////////////////
603+
// Custom templates don't need to be activated, so if it's a custom
604+
// template, return it.
605+
if ( ! is_wp_error( $template ) && $template->is_custom ) {
606+
return $template;
607+
}
608+
////////////////////////////
609+
// END CORE MODIFICATIONS //
610+
////////////////////////////
611+
}
612+
613+
$block_template = get_block_file_template( $id, $template_type );
614+
615+
/**
616+
* Filters the queried block template object after it's been fetched.
617+
*
618+
* @since 5.9.0
619+
*
620+
* @param WP_Block_Template|null $block_template The found block template, or null if there isn't one.
621+
* @param string $id Template unique identifier (example: 'theme_slug//template_slug').
622+
* @param string $template_type Template type. Either 'wp_template' or 'wp_template_part'.
623+
*/
624+
return apply_filters( 'get_block_template', $block_template, $id, $template_type );
625+
}
626+
627+
add_action( 'pre_get_block_templates', 'gutenberg_get_block_templates', 10, 3 );
628+
629+
///////////////////////////////////////////////////////////////////////
630+
// This function is a copy of core's, except for the marked section. //
631+
///////////////////////////////////////////////////////////////////////
632+
function gutenberg_get_block_templates( $output, $query = array(), $template_type = 'wp_template' ) {
633+
if ( 'wp_template' !== $template_type ) {
634+
return $output;
635+
}
636+
637+
$post_type = isset( $query['post_type'] ) ? $query['post_type'] : '';
638+
$wp_query_args = array(
639+
'post_status' => array( 'auto-draft', 'draft', 'publish' ),
640+
'post_type' => $template_type,
641+
'posts_per_page' => -1,
642+
'no_found_rows' => true,
643+
'lazy_load_term_meta' => false,
644+
'tax_query' => array(
645+
array(
646+
'taxonomy' => 'wp_theme',
647+
'field' => 'name',
648+
'terms' => get_stylesheet(),
649+
),
650+
),
651+
);
652+
653+
if ( ! empty( $query['slug__in'] ) ) {
654+
$wp_query_args['post_name__in'] = $query['slug__in'];
655+
$wp_query_args['posts_per_page'] = count( array_unique( $query['slug__in'] ) );
656+
}
657+
658+
// This is only needed for the regular templates/template parts post type listing and editor.
659+
if ( isset( $query['wp_id'] ) ) {
660+
$wp_query_args['p'] = $query['wp_id'];
661+
} else {
662+
$wp_query_args['post_status'] = 'publish';
663+
}
664+
665+
//////////////////////////////
666+
// START CORE MODIFICATIONS //
667+
//////////////////////////////
668+
$active_templates = get_option( 'active_templates', array() );
669+
////////////////////////////
670+
// END CORE MODIFICATIONS //
671+
////////////////////////////
672+
673+
$template_query = new WP_Query( $wp_query_args );
674+
$query_result = array();
675+
foreach ( $template_query->posts as $post ) {
676+
$template = _build_block_template_result_from_post( $post );
677+
678+
if ( is_wp_error( $template ) ) {
679+
continue;
680+
}
681+
682+
if ( $post_type && ! $template->is_custom ) {
683+
continue;
684+
}
685+
686+
if (
687+
$post_type &&
688+
isset( $template->post_types ) &&
689+
! in_array( $post_type, $template->post_types, true )
690+
) {
691+
continue;
692+
}
693+
694+
//////////////////////////////
695+
// START CORE MODIFICATIONS //
696+
//////////////////////////////
697+
if ( $template->is_custom || isset( $query['wp_id'] ) ) {
698+
// Custom templates don't need to be activated, leave them be.
699+
// Also don't filter out templates when querying by wp_id.
700+
$query_result[] = $template;
701+
} elseif ( isset( $active_templates[ $template->slug ] ) && $active_templates[ $template->slug ] === $post->ID ) {
702+
// Only include active templates.
703+
$query_result[] = $template;
704+
}
705+
////////////////////////////
706+
// END CORE MODIFICATIONS //
707+
////////////////////////////
708+
}
709+
710+
if ( ! isset( $query['wp_id'] ) ) {
711+
/*
712+
* If the query has found some user templates, those have priority
713+
* over the theme-provided ones, so we skip querying and building them.
714+
*/
715+
$query['slug__not_in'] = wp_list_pluck( $query_result, 'slug' );
716+
/*
717+
* We need to unset the post_type query param because some templates
718+
* would be excluded otherwise, like `page.html` when looking for
719+
* `page` templates. We need all templates so we can exclude duplicates
720+
* from plugin-registered templates.
721+
* See: https://github.com/WordPress/gutenberg/issues/65584
722+
*/
723+
$template_files_query = $query;
724+
unset( $template_files_query['post_type'] );
725+
$template_files = _get_block_templates_files( $template_type, $template_files_query );
726+
foreach ( $template_files as $template_file ) {
727+
// If the query doesn't specify a post type, or it does and the template matches the post type, add it.
728+
if (
729+
! isset( $query['post_type'] ) ||
730+
(
731+
isset( $template_file['postTypes'] ) &&
732+
in_array( $query['post_type'], $template_file['postTypes'], true )
733+
)
734+
) {
735+
$query_result[] = _build_block_template_result_from_file( $template_file, $template_type );
736+
} elseif ( ! isset( $template_file['postTypes'] ) ) {
737+
// The custom templates with no associated post types are available for all post types as long
738+
// as they are not default templates.
739+
$candidate = _build_block_template_result_from_file( $template_file, $template_type );
740+
$default_template_types = get_default_block_template_types();
741+
if ( ! isset( $default_template_types[ $candidate->slug ] ) ) {
742+
$query_result[] = $candidate;
743+
}
744+
}
745+
}
746+
747+
if ( 'wp_template' === $template_type ) {
748+
// Add templates registered in the template registry. Filtering out the ones which have a theme file.
749+
$registered_templates = WP_Block_Templates_Registry::get_instance()->get_by_query( $query );
750+
$matching_registered_templates = array_filter(
751+
$registered_templates,
752+
function ( $registered_template ) use ( $template_files ) {
753+
foreach ( $template_files as $template_file ) {
754+
if ( $template_file['slug'] === $registered_template->slug ) {
755+
return false;
756+
}
757+
}
758+
return true;
759+
}
760+
);
761+
762+
$matching_registered_templates = array_map(
763+
function ( $template ) {
764+
$template->content = apply_block_hooks_to_content(
765+
$template->content,
766+
$template,
767+
'insert_hooked_blocks_and_set_ignored_hooked_blocks_metadata'
768+
);
769+
return $template;
770+
},
771+
$matching_registered_templates
772+
);
773+
774+
$query_result = array_merge( $query_result, $matching_registered_templates );
775+
}
776+
}
777+
778+
/**
779+
* Filters the array of queried block templates array after they've been fetched.
780+
*
781+
* @since 5.9.0
782+
*
783+
* @param WP_Block_Template[] $query_result Array of found block templates.
784+
* @param array $query {
785+
* Arguments to retrieve templates. All arguments are optional.
786+
*
787+
* @type string[] $slug__in List of slugs to include.
788+
* @type int $wp_id Post ID of customized template.
789+
* @type string $area A 'wp_template_part_area' taxonomy value to filter by (for 'wp_template_part' template type only).
790+
* @type string $post_type Post type to get the templates for.
791+
* }
792+
* @param string $template_type wp_template or wp_template_part.
793+
*/
794+
return apply_filters( 'get_block_templates', $query_result, $query, $template_type );
795+
}

packages/core-data/src/actions.js

Lines changed: 27 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -323,8 +323,20 @@ export const deleteEntityRecord =
323323
} );
324324

325325
let hasError = false;
326+
let { baseURL } = entityConfig;
327+
if (
328+
kind === 'postType' &&
329+
name === 'wp_template' &&
330+
recordId &&
331+
typeof recordId === 'string' &&
332+
! /^\d+$/.test( recordId )
333+
) {
334+
baseURL =
335+
baseURL.slice( 0, baseURL.lastIndexOf( '/' ) ) +
336+
'/templates';
337+
}
326338
try {
327-
let path = `${ entityConfig.baseURL }/${ recordId }`;
339+
let path = `${ baseURL }/${ recordId }`;
328340

329341
if ( query ) {
330342
path = addQueryArgs( path, query );
@@ -526,46 +538,6 @@ export const saveEntityRecord =
526538
const entityIdKey = entityConfig.key || DEFAULT_ENTITY_KEY;
527539
const recordId = record[ entityIdKey ];
528540

529-
// When called with a theme template ID, trigger the compatibility
530-
// logic.
531-
if (
532-
kind === 'postType' &&
533-
name === 'wp_template' &&
534-
typeof recordId === 'string' &&
535-
! /^\d+$/.test( recordId )
536-
) {
537-
// Get the theme template.
538-
const template = await select.getEntityRecord(
539-
'postType',
540-
'wp_registered_template',
541-
recordId
542-
);
543-
// Duplicate the theme template and make the edit.
544-
const newTemplate = await dispatch.saveEntityRecord(
545-
'postType',
546-
'wp_template',
547-
{
548-
...template,
549-
...record,
550-
id: undefined,
551-
type: 'wp_template',
552-
status: 'publish',
553-
}
554-
);
555-
// Make the new template active.
556-
const activeTemplates = await select.getEntityRecord(
557-
'root',
558-
'site'
559-
);
560-
await dispatch.saveEntityRecord( 'root', 'site', {
561-
active_templates: {
562-
...activeTemplates.active_templates,
563-
[ newTemplate.slug ]: newTemplate.id,
564-
},
565-
} );
566-
return newTemplate;
567-
}
568-
569541
const lock = await dispatch.__unstableAcquireStoreLock(
570542
STORE_NAME,
571543
[ 'entities', 'records', kind, name, recordId || uuid() ],
@@ -603,10 +575,21 @@ export const saveEntityRecord =
603575
let updatedRecord;
604576
let error;
605577
let hasError = false;
578+
let { baseURL } = entityConfig;
579+
// For "string" IDs, use the old templates endpoint.
580+
if (
581+
kind === 'postType' &&
582+
name === 'wp_template' &&
583+
recordId &&
584+
typeof recordId === 'string' &&
585+
! /^\d+$/.test( recordId )
586+
) {
587+
baseURL =
588+
baseURL.slice( 0, baseURL.lastIndexOf( '/' ) ) +
589+
'/templates';
590+
}
606591
try {
607-
const path = `${ entityConfig.baseURL }${
608-
recordId ? '/' + recordId : ''
609-
}`;
592+
const path = `${ baseURL }${ recordId ? '/' + recordId : '' }`;
610593
const persistedRecord = select.getRawEntityRecord(
611594
kind,
612595
name,

0 commit comments

Comments
 (0)