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();
- } );
- }
} );