Commit ff557bf450 for woocommerce

commit ff557bf4504d6ba35444b7651a8f0efadb989bf1
Author: Luigi Teschio <gigitux@gmail.com>
Date:   Thu Sep 18 15:49:40 2025 +0200

    Classic Template Block: Hide from inserter and simplify logic (#60993)

    * Classic Template Block: Hide from inserter and simplify logic

    * Add changefile(s) from automation for the following project(s): woocommerce

    * fix lint errors

    * fix error

    * fix E2E test

    * fix e2e test

    * fix logic

    * remove console.log

    ---------

    Co-authored-by: github-actions <github-actions@github.com>

diff --git a/plugins/woocommerce/changelog/60993-fix-template-slug-check b/plugins/woocommerce/changelog/60993-fix-template-slug-check
new file mode 100644
index 0000000000..4187736ae2
--- /dev/null
+++ b/plugins/woocommerce/changelog/60993-fix-template-slug-check
@@ -0,0 +1,4 @@
+Significance: minor
+Type: update
+
+Classic Template Block: Hide from inserter and simplify logic
\ No newline at end of file
diff --git a/plugins/woocommerce/client/blocks/assets/js/blocks/classic-template/index.tsx b/plugins/woocommerce/client/blocks/assets/js/blocks/classic-template/index.tsx
index d16e607851..2f8861bfe5 100644
--- a/plugins/woocommerce/client/blocks/assets/js/blocks/classic-template/index.tsx
+++ b/plugins/woocommerce/client/blocks/assets/js/blocks/classic-template/index.tsx
@@ -4,9 +4,7 @@
 import {
 	BlockInstance,
 	createBlock,
-	getBlockType,
 	registerBlockType,
-	unregisterBlockType,
 } from '@wordpress/blocks';
 import type { BlockEditProps } from '@wordpress/blocks';
 import { WC_BLOCKS_IMAGE_URL } from '@woocommerce/block-settings';
@@ -18,7 +16,7 @@ import {
 import { Button, Placeholder, Popover } from '@wordpress/components';
 import { __ } from '@wordpress/i18n';
 import { box, Icon } from '@wordpress/icons';
-import { useDispatch, subscribe, useSelect, select } from '@wordpress/data';
+import { useDispatch, useSelect } from '@wordpress/data';
 import { useEffect, useState } from '@wordpress/element';
 import { store as noticesStore } from '@wordpress/notices';
 import { useEntityRecord } from '@wordpress/core-data';
@@ -30,11 +28,7 @@ import { store as editorStore } from '@wordpress/editor';
 import './editor.scss';
 import './style.scss';
 import { BLOCK_SLUG, TEMPLATES, TYPES } from './constants';
-import {
-	isClassicTemplateBlockRegisteredWithAnotherTitle,
-	hasTemplateSupportForClassicTemplateBlock,
-	getTemplateDetailsBySlug,
-} from './utils';
+import { getTemplateDetailsBySlug } from './utils';
 import {
 	blockifiedProductCatalogConfig,
 	blockifiedProductTaxonomyConfig,
@@ -194,18 +188,16 @@ const Edit = ( {
 		};
 	}, [] );

-	const template = useEntityRecord< {
-		slug: string;
-		title: {
-			rendered?: string;
-			row: string;
-		};
-	} >( 'postType', 'wp_template', currentPostId );
-
-	const templateDetails = getTemplateDetailsBySlug(
-		attributes.template,
-		TEMPLATES
+	const template = useEntityRecord(
+		'postType',
+		'wp_template',
+		currentPostId
 	);
+
+	const templateSlug = template.record?.slug as string;
+
+	const templateDetails = getTemplateDetailsBySlug( templateSlug, TEMPLATES );
+
 	const templateTitle =
 		template.record?.title.rendered?.toLowerCase() ?? attributes.template;
 	const templatePlaceholder = templateDetails?.placeholder ?? 'fallback';
@@ -214,7 +206,7 @@ const Edit = ( {
 	useEffect(
 		() =>
 			setAttributes( {
-				template: attributes.template,
+				template: templateSlug ?? attributes.template,
 				align: attributes.align ?? 'wide',
 			} ),
 		[ attributes.align, attributes.template, setAttributes ]
@@ -278,166 +270,53 @@ const Edit = ( {
 	);
 };

-const registerClassicTemplateBlock = ( {
-	template,
-	inserter,
-}: {
-	template?: string | null;
-	inserter: boolean;
-} ) => {
-	/**
-	 * The 'WooCommerce Legacy Template' block was renamed to 'WooCommerce Classic Template', however, the internal block
-	 * name 'woocommerce/legacy-template' needs to remain the same. Otherwise, it would result in a corrupt block when
-	 * loaded for users who have customized templates using the legacy-template (since the internal block name is
-	 * stored in the database).
-	 *
-	 * See https://github.com/woocommerce/woocommerce-gutenberg-products-block/issues/5861 for more context
-	 */
-	registerBlockType( BLOCK_SLUG, {
-		title:
-			template && TEMPLATES[ template ]
-				? TEMPLATES[ template ].title
-				: __( 'WooCommerce Classic Template', 'woocommerce' ),
-		icon: (
-			<Icon
-				icon={ box }
-				className="wc-block-editor-components-block-icon"
-			/>
-		),
-		category: 'woocommerce',
-		apiVersion: 3,
-		keywords: [ __( 'WooCommerce', 'woocommerce' ) ],
-		description:
-			template && TEMPLATES[ template ]
-				? TEMPLATES[ template ].description
-				: __(
-						'Renders classic WooCommerce PHP templates.',
-						'woocommerce'
-				  ),
-		supports: {
-			interactivity: {
-				clientNavigation: false,
-			},
-			align: [ 'wide', 'full' ],
-			html: false,
-			multiple: false,
-			reusable: false,
-			inserter,
+registerBlockType( BLOCK_SLUG, {
+	title: __( 'WooCommerce Classic Template', 'woocommerce' ),
+	icon: (
+		<Icon icon={ box } className="wc-block-editor-components-block-icon" />
+	),
+	category: 'woocommerce',
+	apiVersion: 3,
+	keywords: [ __( 'WooCommerce', 'woocommerce' ) ],
+	description: __(
+		'Renders classic WooCommerce PHP template.',
+		'woocommerce'
+	),
+	supports: {
+		interactivity: {
+			clientNavigation: false,
 		},
-		attributes: {
-			/**
-			 * Template attribute is used to determine which core PHP template gets rendered.
-			 */
-			template: {
-				type: 'string',
-				default: 'any',
-			},
-			align: {
-				type: 'string',
-				default: 'wide',
-			},
+		align: [ 'wide', 'full' ],
+		html: false,
+		multiple: false,
+		reusable: false,
+		inserter: false,
+	},
+	attributes: {
+		/**
+		 * Template attribute is used to determine which core PHP template gets rendered.
+		 */
+		template: {
+			type: 'string',
+			default: 'any',
 		},
-		edit: ( {
-			attributes,
-			clientId,
-			setAttributes,
-		}: BlockEditProps< Attributes > ) => {
-			const newTemplate = template ?? attributes.template;
-
-			return (
-				<Edit
-					attributes={ {
-						...attributes,
-						template: newTemplate,
-					} }
-					setAttributes={ setAttributes }
-					clientId={ clientId }
-				/>
-			);
+		align: {
+			type: 'string',
+			default: 'wide',
 		},
-		save: () => null,
-	} );
-};
-
-// @todo Refactor when there will be possible to show a block according on a template/post with a Gutenberg API. https://github.com/WordPress/gutenberg/pull/41718
-let previousEditedTemplate: string | number | null = null;
-let isBlockRegistered = false;
-let isBlockInInserter = false;
-const handleRegisterClassicTemplateBlock = ( {
-	template,
-	inserter,
-}: {
-	template: string | null;
-	inserter: boolean;
-} ) => {
-	if ( isBlockRegistered ) {
-		unregisterBlockType( BLOCK_SLUG );
-	}
-	isBlockInInserter = inserter;
-	isBlockRegistered = true;
-	registerClassicTemplateBlock( {
-		template,
-		inserter,
-	} );
-};
-
-subscribe( () => {
-	// We use blockCount to know if we are editing a template or in the navigation.
-	const blockCount = select( blockEditorStore )?.getBlockCount() as number;
-	const templateSlug = select( 'core/editor' )?.getEditedPostSlug() as
-		| string
-		| null;
-	const editedTemplate = blockCount && blockCount > 0 ? templateSlug : null;
-
-	// Skip if we are in the same template, except if the block hasn't been registered yet.
-	if ( isBlockRegistered && previousEditedTemplate === editedTemplate ) {
-		return;
-	}
-	previousEditedTemplate = editedTemplate;
-
-	// Handle the case when we are not editing a template (ie: in the navigation screen).
-	if ( ! editedTemplate ) {
-		if ( ! isBlockRegistered ) {
-			handleRegisterClassicTemplateBlock( {
-				template: editedTemplate,
-				inserter: false,
-			} );
-		}
-		return;
-	}
-
-	const templateSupportsClassicTemplateBlock =
-		hasTemplateSupportForClassicTemplateBlock( editedTemplate, TEMPLATES );
-
-	// Handle the case when we are editing a template that doesn't support the Classic Template block (ie: Blog Home).
-	if ( ! templateSupportsClassicTemplateBlock && isBlockInInserter ) {
-		handleRegisterClassicTemplateBlock( {
-			template: editedTemplate,
-			inserter: false,
-		} );
-		return;
-	}
-
-	// Handle the case when we are editing a template that does support the Classic Template block (ie: Product Catalog).
-	if ( templateSupportsClassicTemplateBlock && ! isBlockInInserter ) {
-		handleRegisterClassicTemplateBlock( {
-			template: editedTemplate,
-			inserter: true,
-		} );
-		return;
-	}
-
-	// Handle the case when we are editing a template that does support the Classic Template block but it's currently registered with another title (ie: navigating from the Product Catalog template to the Product Search Results template).
-	if (
-		templateSupportsClassicTemplateBlock &&
-		isClassicTemplateBlockRegisteredWithAnotherTitle(
-			getBlockType( BLOCK_SLUG ),
-			editedTemplate
-		)
-	) {
-		handleRegisterClassicTemplateBlock( {
-			template: editedTemplate,
-			inserter: true,
-		} );
-	}
-}, 'core/blocks-editor' );
+	},
+	edit: ( {
+		attributes,
+		clientId,
+		setAttributes,
+	}: BlockEditProps< Attributes > ) => {
+		return (
+			<Edit
+				attributes={ attributes }
+				setAttributes={ setAttributes }
+				clientId={ clientId }
+			/>
+		);
+	},
+	save: () => null,
+} );
diff --git a/plugins/woocommerce/client/blocks/assets/js/blocks/classic-template/utils.ts b/plugins/woocommerce/client/blocks/assets/js/blocks/classic-template/utils.ts
index 02bab2c0b1..133ee8c953 100644
--- a/plugins/woocommerce/client/blocks/assets/js/blocks/classic-template/utils.ts
+++ b/plugins/woocommerce/client/blocks/assets/js/blocks/classic-template/utils.ts
@@ -2,7 +2,6 @@
  * External dependencies
  */
 import {
-	type Block,
 	type BlockInstance,
 	getBlockType,
 	createBlock,
@@ -11,14 +10,17 @@ import {
 /**
  * Internal dependencies
  */
-import { TEMPLATES } from './constants';
 import { TemplateDetails, InheritedAttributes } from './types';

 // Finds the most appropriate template details object for specific template keys such as single-product-hoodie.
 export function getTemplateDetailsBySlug(
-	parsedTemplate: string,
+	parsedTemplate: string | null,
 	templates: TemplateDetails
 ) {
+	if ( ! parsedTemplate ) {
+		return null;
+	}
+
 	const templateKeys = Object.keys( templates );
 	let templateDetails = null;

@@ -34,25 +36,6 @@ export function getTemplateDetailsBySlug(
 	return templateDetails;
 }

-export function isClassicTemplateBlockRegisteredWithAnotherTitle(
-	// eslint-disable-next-line @typescript-eslint/no-explicit-any
-	block: Block< any > | undefined,
-	parsedTemplate: string
-) {
-	const templateDetails = getTemplateDetailsBySlug(
-		parsedTemplate,
-		TEMPLATES
-	);
-	return block?.title !== templateDetails?.title;
-}
-
-export function hasTemplateSupportForClassicTemplateBlock(
-	parsedTemplate: string,
-	templates: TemplateDetails
-): boolean {
-	return getTemplateDetailsBySlug( parsedTemplate, templates ) ? true : false;
-}
-
 export const createArchiveTitleBlock = (
 	variationName: string,
 	inheritedAttributes: InheritedAttributes
diff --git a/plugins/woocommerce/client/blocks/tests/e2e/tests/classic-template/classic-template.block_theme.spec.ts b/plugins/woocommerce/client/blocks/tests/e2e/tests/classic-template/classic-template.block_theme.spec.ts
index 362c730706..778d38de3d 100644
--- a/plugins/woocommerce/client/blocks/tests/e2e/tests/classic-template/classic-template.block_theme.spec.ts
+++ b/plugins/woocommerce/client/blocks/tests/e2e/tests/classic-template/classic-template.block_theme.spec.ts
@@ -18,56 +18,6 @@ const blockData: Partial< BlockData > = {
 	name: 'woocommerce/legacy-template',
 };

-const classicTemplateBlockNames = [
-	'WooCommerce Classic Template',
-	'Product (Classic)',
-	'Product Attribute (Classic)',
-	'Product Category (Classic)',
-	'Product Tag (Classic)',
-	"Product's Custom Taxonomy (Classic)",
-	'Product Search Results (Classic)',
-	'Product Grid (Classic)',
-];
-
-const templates = [
-	{
-		title: 'Single Product',
-		slug: 'single-product',
-		path: '/product/hoodie',
-		needsCreation: false,
-	},
-	{
-		title: 'Products by Attribute',
-		slug: 'taxonomy-product_attribute',
-		path: '/color/blue',
-		needsCreation: false,
-	},
-	{
-		title: 'Products by Category',
-		slug: 'taxonomy-product_cat',
-		path: '/product-category/clothing',
-		needsCreation: true,
-	},
-	{
-		title: 'Products by Tag',
-		slug: 'taxonomy-product_tag',
-		path: '/product-tag/recommended/',
-		needsCreation: true,
-	},
-	{
-		title: 'Product Catalog',
-		slug: 'archive-product',
-		path: '/shop/',
-		needsCreation: false,
-	},
-	{
-		title: 'Product Search Results',
-		slug: 'product-search-results',
-		path: '/?s=shirt&post_type=product',
-		needsCreation: false,
-	},
-];
-
 const getClassicTemplateBlocksInInserter = async ( {
 	editor,
 }: {
@@ -94,142 +44,24 @@ const getClassicTemplateBlocksInInserter = async ( {
 	const options = inserterBlocks.locator( 'role=option' );

 	// Filter out blocks that don't match one of the possible Classic Template block names (case-insensitive).
-	const classicTemplateBlocks = await options.evaluateAll(
-		( elements, blockNames ) => {
-			const blockOptions = elements.filter( ( element ) => {
-				return blockNames.some(
-					( name ) => element.textContent === name
-				);
-			} );
-			return blockOptions.map( ( element ) => element.textContent );
-		},
-		classicTemplateBlockNames
-	);
+	const classicTemplateBlocks = await options.evaluateAll( ( elements ) => {
+		const blockOptions = elements.filter( ( element ) => {
+			return element.textContent === 'WooCommerce Classic Template';
+		} );
+		return blockOptions.map( ( element ) => element.textContent );
+	} );

 	return classicTemplateBlocks;
 };

 test.describe( `${ blockData.name } Block `, () => {
-	test.beforeEach( async () => {
-		await wpCLI(
-			'option update wc_blocks_use_blockified_product_grid_block_as_template false'
-		);
-	} );
-
-	test( `is registered/unregistered when navigating from a non-WC template to a WC template and back`, async ( {
-		admin,
-		editor,
-	} ) => {
-		await admin.visitSiteEditor( {
-			postId: `twentytwentyfour//home`,
-			postType: 'wp_template',
-			canvas: 'edit',
-		} );
-
-		let classicTemplateBlocks = await getClassicTemplateBlocksInInserter( {
-			editor,
-		} );
-
-		expect( classicTemplateBlocks ).toHaveLength( 0 );
-
-		await editor.page.getByLabel( 'Open Navigation' ).click();
-		await editor.page
-			.getByLabel( 'Product Catalog', { exact: true } )
-			.click();
-
-		classicTemplateBlocks = await getClassicTemplateBlocksInInserter( {
-			editor,
-		} );
-
-		expect( classicTemplateBlocks ).toHaveLength( 1 );
-
-		await editor.page.getByLabel( 'Open Navigation' ).click();
-		await editor.page.getByLabel( 'Blog Home', { exact: true } ).click();
-
-		classicTemplateBlocks = await getClassicTemplateBlocksInInserter( {
-			editor,
-		} );
-
-		expect( classicTemplateBlocks ).toHaveLength( 0 );
-	} );
-
-	test( `is registered/unregistered when navigating from a WC template to a non-WC template and back`, async ( {
-		admin,
-		editor,
-	} ) => {
-		await admin.visitSiteEditor( {
-			postId: `${ BLOCK_THEME_SLUG }//archive-product`,
-			postType: 'wp_template',
-			canvas: 'edit',
-		} );
-
-		let classicTemplateBlocks = await getClassicTemplateBlocksInInserter( {
-			editor,
-		} );
-
-		expect( classicTemplateBlocks ).toHaveLength( 1 );
-
-		await editor.page.getByLabel( 'Open Navigation' ).click();
-		await editor.page.getByLabel( 'Blog Home', { exact: true } ).click();
-
-		classicTemplateBlocks = await getClassicTemplateBlocksInInserter( {
-			editor,
-		} );
-
-		expect( classicTemplateBlocks ).toHaveLength( 0 );
-
-		await editor.page.getByLabel( 'Open Navigation' ).click();
-		await editor.page
-			.getByLabel( 'Product Catalog', { exact: true } )
-			.click();
-
-		classicTemplateBlocks = await getClassicTemplateBlocksInInserter( {
-			editor,
-		} );
-
-		expect( classicTemplateBlocks ).toHaveLength( 1 );
-	} );
-
-	test( `updates block title when navigating between WC templates`, async ( {
-		admin,
-		editor,
-	} ) => {
+	test( `is not available in the inserter`, async ( { admin, editor } ) => {
 		await admin.visitSiteEditor( {
 			postId: `${ BLOCK_THEME_SLUG }//archive-product`,
 			postType: 'wp_template',
 			canvas: 'edit',
 		} );

-		let classicTemplateBlocks = await getClassicTemplateBlocksInInserter( {
-			editor,
-		} );
-
-		expect( classicTemplateBlocks[ 0 ] ).toBe( 'Product Grid (Classic)' );
-
-		await editor.page.getByLabel( 'Open Navigation' ).click();
-		await editor.page
-			.getByLabel( 'Product Search Results', { exact: true } )
-			.click();
-
-		classicTemplateBlocks = await getClassicTemplateBlocksInInserter( {
-			editor,
-		} );
-
-		expect( classicTemplateBlocks[ 0 ] ).toBe(
-			'Product Search Results (Classic)'
-		);
-	} );
-
-	test( `is not available when editing template parts`, async ( {
-		admin,
-		editor,
-	} ) => {
-		await admin.visitSiteEditor( {
-			postId: `twentytwentyfour//header`,
-			postType: 'wp_template_part',
-			canvas: 'edit',
-		} );
-
 		const classicTemplateBlocks = await getClassicTemplateBlocksInInserter(
 			{
 				editor,
@@ -239,93 +71,26 @@ test.describe( `${ blockData.name } Block `, () => {
 		expect( classicTemplateBlocks ).toHaveLength( 0 );
 	} );

-	// @see https://github.com/woocommerce/woocommerce-blocks/issues/9637
-	test( `is still available after resetting a modified WC template`, async ( {
+	test( `is visible as default block when wc_blocks_use_blockified_product_grid_block_as_template is false`, async ( {
 		admin,
 		editor,
-		wpCoreVersion,
+		page,
 	} ) => {
+		await wpCLI(
+			'option update wc_blocks_use_blockified_product_grid_block_as_template false'
+		);
 		await admin.visitSiteEditor( {
-			postId: `${ BLOCK_THEME_SLUG }//single-product`,
+			postId: `${ BLOCK_THEME_SLUG }//archive-product`,
 			postType: 'wp_template',
 			canvas: 'edit',
 		} );

-		await editor.insertBlock( {
-			name: 'core/paragraph',
-			attributes: { content: 'Hello World' },
-		} );
-
-		await editor.saveSiteEditorEntities( {
-			isOnlyCurrentEntityDirty: true,
-		} );
-
-		await editor.page.getByLabel( 'Open Navigation' ).click();
-
-		await editor.revertTemplate( {
-			templateName: 'Single Product',
-		} );
+		await expect(
+			await editor.getBlockByName( blockData.name )
+		).toBeVisible();

-		if ( wpCoreVersion >= 6.8 ) {
-			const actionsButton = editor.page.getByRole( 'button', {
-				name: 'Actions',
-			} );
-			await actionsButton.click();
-		}
+		await page.goto( '/shop/' );

-		const editButton = editor.page.getByRole( 'menuitem', {
-			name: 'Edit',
-		} );
-
-		// Edit the template again.
-		await editButton.click();
-
-		// Verify the Classic Template block is still registered.
-		const classicTemplateBlocks = await getClassicTemplateBlocksInInserter(
-			{
-				editor,
-			}
-		);
-
-		expect( classicTemplateBlocks ).toHaveLength( 1 );
+		await expect( page.locator( 'div[data-template]' ) ).toBeVisible();
 	} );
-
-	for ( const template of templates ) {
-		test( `is rendered on ${ template.title } template`, async ( {
-			admin,
-			editor,
-			page,
-		} ) => {
-			if ( template.needsCreation ) {
-				await admin.visitSiteEditor( {
-					postType: 'wp_template',
-				} );
-				await editor.createTemplate( {
-					templateName: template.title,
-				} );
-			} else {
-				await admin.visitSiteEditor( {
-					postId: `${ BLOCK_THEME_SLUG }//${ template.slug }`,
-					postType: 'wp_template',
-					canvas: 'edit',
-				} );
-			}
-
-			const block = editor.canvas.locator(
-				`[data-type="${ blockData.name }"]`
-			);
-
-			await expect( block ).toBeVisible();
-
-			if ( template.needsCreation ) {
-				await editor.saveSiteEditorEntities( {
-					isOnlyCurrentEntityDirty: true,
-				} );
-			}
-
-			await page.goto( template.path );
-
-			await expect( page.locator( 'div[data-template]' ) ).toBeVisible();
-		} );
-	}
 } );