Set up and migration to use BlockTemplate classes (#39814)

* Initial set up and migration for the BlockTemplate

* Migrate remaining fields to the new SimpleProductTemplate

* Remove re-usable functions and clean up

* Add interfaces

* Add changelogs

* Remove unused id from block attributes

* Update changelog

* Address refactor suggestions

* Fix lint errors

* Add tests

* Address PR feedback

* Extend from BlockContainerInterface instead of BlockInterface
This commit is contained in:
louwie17 2023-08-24 16:04:44 -03:00 committed by GitHub
parent 79edab17bc
commit 9198596918
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
20 changed files with 1253 additions and 590 deletions

View File

@ -0,0 +1,5 @@
Significance: patch
Type: tweak
Comment: Fix mis spelling of variable name visibility.

View File

@ -12,7 +12,7 @@
"type": "string",
"__experimentalRole": "content"
},
"visibilty": {
"visibility": {
"type": "string",
"enum": [ "visible", "catalog", "search", "hidden" ],
"default": "visible"

View File

@ -17,7 +17,7 @@ export function Edit( {
}: {
attributes: CatalogVisibilityBlockAttributes;
} ) {
const { label, visibilty } = attributes;
const { label, visibility } = attributes;
const blockProps = useBlockProps();
@ -26,22 +26,22 @@ export function Edit( {
>( 'postType', 'product', 'catalog_visibility' );
const checked =
catalogVisibility === visibilty || catalogVisibility === 'hidden';
catalogVisibility === visibility || catalogVisibility === 'hidden';
function handleChange( selected: boolean ) {
if ( selected ) {
if ( catalogVisibility === 'visible' ) {
setCatalogVisibility( visibilty );
setCatalogVisibility( visibility );
return;
}
setCatalogVisibility( 'hidden' );
} else {
if ( catalogVisibility === 'hidden' ) {
if ( visibilty === 'catalog' ) {
if ( visibility === 'catalog' ) {
setCatalogVisibility( 'search' );
return;
}
if ( visibilty === 'search' ) {
if ( visibility === 'search' ) {
setCatalogVisibility( 'catalog' );
return;
}

View File

@ -6,5 +6,5 @@ import { BlockAttributes } from '@wordpress/blocks';
export interface CatalogVisibilityBlockAttributes extends BlockAttributes {
label: string;
visibilty: Product[ 'catalog_visibility' ];
visibility: Product[ 'catalog_visibility' ];
}

View File

@ -8,9 +8,6 @@
"keywords": [ "products", "notice" ],
"textdomain": "default",
"attributes": {
"id": {
"type": "string"
},
"title": {
"type": "string"
},

View File

@ -0,0 +1,4 @@
Significance: major
Type: update
Update the simple product template implementation to use the product form template API.

View File

@ -6,6 +6,7 @@
namespace Automattic\WooCommerce\Admin\Features\ProductBlockEditor;
use Automattic\WooCommerce\Admin\Features\Features;
use Automattic\WooCommerce\Admin\Features\ProductBlockEditor\ProductTemplates\SimpleProductTemplate;
use Automattic\WooCommerce\Admin\Features\TransientNotices;
use Automattic\WooCommerce\Admin\PageController;
use Automattic\WooCommerce\Internal\Admin\Loader;
@ -34,15 +35,23 @@ class Init {
*/
private $redirection_controller;
/**
* Simple product block template.
*
* @var AbstractBlockTemplate
*/
public $simple_product_template;
/**
* Constructor
*/
public function __construct() {
if ( Features::is_enabled( 'product-variation-management' ) ) {
array_push($this->supported_post_types, 'variable');
array_push( $this->supported_post_types, 'variable' );
}
$this->redirection_controller = new RedirectionController( $this->supported_post_types );
$this->simple_product_template = new SimpleProductTemplate();
$this->redirection_controller = new RedirectionController( $this->supported_post_types );
if ( \Automattic\WooCommerce\Utilities\FeaturesUtil::feature_is_enabled( 'product_block_editor' ) ) {
if ( ! Features::is_enabled( 'new-product-management-experience' ) ) {
@ -257,555 +266,7 @@ class Init {
public function add_product_template( $args ) {
if ( ! isset( $args['template'] ) ) {
$args['template_lock'] = 'all';
$args['template'] = array(
array(
'woocommerce/product-tab',
array(
'id' => 'general',
'title' => __( 'General', 'woocommerce' ),
'order' => 10,
),
array(
array(
'woocommerce/product-section',
array(
'title' => __( 'Basic details', 'woocommerce' ),
'description' => __( 'This info will be displayed on the product page, category pages, social media, and search results.', 'woocommerce' ),
),
array(
array(
'woocommerce/product-name-field',
array(
'name' => 'Product name',
'autoFocus' => true,
),
),
array(
'woocommerce/product-summary-field',
),
array(
'core/columns',
array(),
array(
array(
'core/column',
array(
'templateLock' => 'all',
),
array(
array(
'woocommerce/product-regular-price-field',
array(
'name' => 'regular_price',
'label' => __( 'List price', 'woocommerce' ),
'help' => __( 'Manage more settings in <PricingTab>Pricing.</PricingTab>', 'woocommerce' ),
),
),
),
),
array(
'core/column',
array(
'templateLock' => 'all',
),
array(
array(
'woocommerce/product-sale-price-field',
array(
'label' => __( 'Sale price', 'woocommerce' ),
),
),
),
),
),
),
),
),
array(
'woocommerce/product-section',
array(
'title' => __( 'Description', 'woocommerce' ),
'description' => __( 'What makes this product unique? What are its most important features? Enrich the product page by adding rich content using blocks.', 'woocommerce' ),
),
array(
array(
'woocommerce/product-description-field',
),
),
),
array(
'woocommerce/product-section',
array(
'title' => __( 'Images', 'woocommerce' ),
'description' => sprintf(
/* translators: %1$s: Images guide link opening tag. %2$s: Images guide link closing tag.*/
__( 'Drag images, upload new ones or select files from your library. For best results, use JPEG files that are 1000 by 1000 pixels or larger. %1$sHow to prepare images?%2$s', 'woocommerce' ),
'<a href="http://woocommerce.com/#" target="_blank" rel="noreferrer">',
'</a>'
),
),
array(
array(
'woocommerce/product-images-field',
array(
'images' => array(),
),
),
),
),
),
),
array(
'woocommerce/product-tab',
array(
'id' => 'organization',
'title' => __( 'Organization', 'woocommerce' ),
'order' => 15,
),
array(
array(
'woocommerce/product-section',
array(
'title' => __( 'Product catalog', 'woocommerce' ),
),
array(
array(
'woocommerce/product-category-field',
array(
'name' => 'categories',
),
),
array(
'woocommerce/product-catalog-visibility-field',
array(
'label' => __( 'Hide in product catalog', 'woocommerce' ),
'visibilty' => 'search',
),
),
array(
'woocommerce/product-catalog-visibility-field',
array(
'label' => __( 'Hide from search results', 'woocommerce' ),
'visibilty' => 'catalog',
),
),
array(
'woocommerce/product-checkbox-field',
array(
'label' => __( 'Enable product reviews', 'woocommerce' ),
'property' => 'reviews_allowed',
),
),
array(
'woocommerce/product-password-field',
array(
'label' => __( 'Require a password', 'woocommerce' ),
),
),
),
),
array(
'woocommerce/product-section',
array(
'title' => __( 'Attributes', 'woocommerce' ),
),
array(
array(
'woocommerce/product-attributes-field',
),
),
),
),
),
array(
'woocommerce/product-tab',
array(
'id' => 'pricing',
'title' => __( 'Pricing', 'woocommerce' ),
'order' => 20,
),
array(
array(
'woocommerce/product-has-variations-notice',
array(
'id' => 'wc-product-notice-has-options',
'content' => __( 'This product has options, such as size or color. You can now manage each variation\'s price and other details individually.', 'woocommerce' ),
'buttonText' => __( 'Go to Variations', 'woocommerce' ),
'type' => 'info',
),
),
array(
'woocommerce/product-section',
array(
'title' => __( 'Pricing', 'woocommerce' ),
'description' => sprintf(
/* translators: %1$s: Images guide link opening tag. %2$s: Images guide link closing tag.*/
__( 'Set a competitive price, put the product on sale, and manage tax calculations. %1$sHow to price your product?%2$s', 'woocommerce' ),
'<a href="https://woocommerce.com/posts/how-to-price-products-strategies-expert-tips/" target="_blank" rel="noreferrer">',
'</a>'
),
'blockGap' => 'unit-40',
),
array(
array(
'woocommerce/product-section',
array(),
array(
array(
'core/columns',
array(),
array(
array(
'core/column',
array(
'templateLock' => 'all',
),
array(
array(
'woocommerce/product-regular-price-field',
array(
'name' => 'regular_price',
'label' => __( 'List price', 'woocommerce' ),
),
),
),
),
array(
'core/column',
array(
'templateLock' => 'all',
),
array(
array(
'woocommerce/product-sale-price-field',
array(
'label' => __( 'Sale price', 'woocommerce' ),
),
),
),
),
),
),
array(
'woocommerce/product-schedule-sale-fields',
),
),
),
array(
'woocommerce/product-radio-field',
array(
'title' => __( 'Charge sales tax on', 'woocommerce' ),
'property' => 'tax_status',
'options' => array(
array(
'label' => __( 'Product and shipping', 'woocommerce' ),
'value' => 'taxable',
),
array(
'label' => __( 'Only shipping', 'woocommerce' ),
'value' => 'shipping',
),
array(
'label' => __( "Don't charge tax", 'woocommerce' ),
'value' => 'none',
),
),
),
),
array(
'woocommerce/product-collapsible',
array(
'toggleText' => __( 'Advanced', 'woocommerce' ),
'initialCollapsed' => true,
'persistRender' => true,
),
array(
array(
'woocommerce/product-radio-field',
array(
'title' => __( 'Tax class', 'woocommerce' ),
'description' => sprintf(
/* translators: %1$s: Learn more link opening tag. %2$s: Learn more link closing tag.*/
__( 'Apply a tax rate if this product qualifies for tax reduction or exemption. %1$sLearn more%2$s.', 'woocommerce' ),
'<a href="https://woocommerce.com/document/setting-up-taxes-in-woocommerce/#shipping-tax-class" target="_blank" rel="noreferrer">',
'</a>'
),
'property' => 'tax_class',
'options' => array(
array(
'label' => __( 'Standard', 'woocommerce' ),
'value' => '',
),
array(
'label' => __( 'Reduced rate', 'woocommerce' ),
'value' => 'reduced-rate',
),
array(
'label' => __( 'Zero rate', 'woocommerce' ),
'value' => 'zero-rate',
),
),
),
),
),
),
),
),
),
),
array(
'woocommerce/product-tab',
array(
'id' => 'inventory',
'title' => __( 'Inventory', 'woocommerce' ),
'order' => 30,
),
array(
array(
'woocommerce/product-has-variations-notice',
array(
'id' => 'wc-product-notice-has-options',
'content' => __( 'This product has options, such as size or color. You can now manage each variation\'s price and other details individually.', 'woocommerce' ),
'buttonText' => __( 'Go to Variations', 'woocommerce' ),
'type' => 'info',
),
),
array(
'woocommerce/product-section',
array(
'title' => __( 'Inventory', 'woocommerce' ),
'description' => sprintf(
/* translators: %1$s: Inventory settings link opening tag. %2$s: Inventory settings link closing tag.*/
__( 'Set up and manage inventory for this product, including status and available quantity. %1$sManage store inventory settings%2$s', 'woocommerce' ),
'<a href="' . admin_url( 'admin.php?page=wc-settings&tab=products&section=inventory' ) . '" target="_blank" rel="noreferrer">',
'</a>'
),
'blockGap' => 'unit-40',
),
array(
array(
'woocommerce/product-section',
array(),
array(
array(
'woocommerce/product-sku-field',
),
array(
'woocommerce/product-toggle-field',
array(
'label' => __( 'Track stock quantity for this product', 'woocommerce' ),
'property' => 'manage_stock',
'disabled' => 'yes' !== get_option( 'woocommerce_manage_stock' ),
),
),
array(
'woocommerce/conditional',
array(
'mustMatch' => array(
'manage_stock' => array( true ),
),
),
array(
array(
'woocommerce/product-inventory-quantity-field',
),
),
),
),
),
array(
'woocommerce/conditional',
array(
'mustMatch' => array(
'manage_stock' => array( false ),
),
),
array(
array(
'woocommerce/product-radio-field',
array(
'title' => __( 'Stock status', 'woocommerce' ),
'property' => 'stock_status',
'options' => array(
array(
'label' => __( 'In stock', 'woocommerce' ),
'value' => 'instock',
),
array(
'label' => __( 'Out of stock', 'woocommerce' ),
'value' => 'outofstock',
),
array(
'label' => __( 'On backorder', 'woocommerce' ),
'value' => 'onbackorder',
),
),
),
),
),
),
array(
'woocommerce/product-collapsible',
array(
'toggleText' => __( 'Advanced', 'woocommerce' ),
'initialCollapsed' => true,
'persistRender' => true,
),
array(
array(
'woocommerce/product-section',
array(
'blockGap' => 'unit-40',
),
array(
array(
'woocommerce/conditional',
array(
'mustMatch' => array(
'manage_stock' => array( true ),
),
),
array(
array(
'woocommerce/product-radio-field',
array(
'title' => __( 'When out of stock', 'woocommerce' ),
'property' => 'backorders',
'options' => array(
array(
'label' => __( 'Allow purchases', 'woocommerce' ),
'value' => 'yes',
),
array(
'label' => __(
'Allow purchases, but notify customers',
'woocommerce'
),
'value' => 'notify',
),
array(
'label' => __( "Don't allow purchases", 'woocommerce' ),
'value' => 'no',
),
),
),
),
array(
'woocommerce/product-inventory-email-field',
),
),
),
array(
'woocommerce/product-checkbox-field',
array(
'title' => __(
'Restrictions',
'woocommerce'
),
'label' => __(
'Limit purchases to 1 item per order',
'woocommerce'
),
'property' => 'sold_individually',
'tooltip' => __(
'When checked, customers will be able to purchase only 1 item in a single order. This is particularly useful for items that have limited quantity, like art or handmade goods.',
'woocommerce'
),
),
),
),
),
),
),
),
),
),
),
array(
'woocommerce/product-tab',
array(
'id' => 'shipping',
'title' => __( 'Shipping', 'woocommerce' ),
'order' => 40,
),
array(
array(
'woocommerce/product-has-variations-notice',
array(
'id' => 'wc-product-notice-has-options',
'content' => __( 'This product has options, such as size or color. You can now manage each variation\'s price and other details individually.', 'woocommerce' ),
'buttonText' => __( 'Go to Variations', 'woocommerce' ),
'type' => 'info',
),
),
array(
'woocommerce/product-section',
array(
'title' => __( 'Fees & dimensions', 'woocommerce' ),
'description' => sprintf(
/* translators: %1$s: How to get started? link opening tag. %2$s: How to get started? link closing tag.*/
__( 'Set up shipping costs and enter dimensions used for accurate rate calculations. %1$sHow to get started?%2$s.', 'woocommerce' ),
'<a href="https://woocommerce.com/posts/how-to-calculate-shipping-costs-for-your-woocommerce-store/" target="_blank" rel="noreferrer">',
'</a>'
),
),
array(
array(
'woocommerce/product-shipping-class-field',
),
array(
'woocommerce/product-shipping-dimensions-fields',
),
),
),
),
),
);
if ( Features::is_enabled( 'product-variation-management' ) ) {
array_push(
$args['template'],
array(
'woocommerce/product-tab',
array(
'id' => 'variations',
'title' => __( 'Variations', 'woocommerce' ),
'order' => 40,
),
array(
array(
'woocommerce/product-variations-fields',
array(
'description' => sprintf(
/* translators: %1$s: Sell your product in multiple variations like size or color. strong opening tag. %2$s: Sell your product in multiple variations like size or color. strong closing tag.*/
__( '%1$sSell your product in multiple variations like size or color.%2$s Get started by adding options for the buyers to choose on the product page.', 'woocommerce' ),
'<strong>',
'</strong>'
),
),
array(
array(
'woocommerce/product-section',
array(
'title' => __( 'Variation options', 'woocommerce' ),
),
array( array( 'woocommerce/product-variations-options-field' ) ),
),
array(
'woocommerce/product-section',
array(
'title' => __( 'Variations', 'woocommerce' ),
),
array( array( 'woocommerce/product-variation-items-field' ) ),
),
),
),
),
)
);
}
$args['template'] = $this->simple_product_template->get_formatted_template();
}
return $args;
}

View File

@ -0,0 +1,58 @@
<?php
namespace Automattic\WooCommerce\Admin\Features\ProductBlockEditor\ProductTemplates;
use Automattic\WooCommerce\Admin\BlockTemplates\BlockInterface;
use Automattic\WooCommerce\Internal\Admin\BlockTemplates\AbstractBlockTemplate;
/**
* Block template class.
*/
abstract class AbstractProductFormTemplate extends AbstractBlockTemplate implements ProductFormTemplateInterface {
/**
* Get a group block by ID.
*
* @param string $group_id The group block ID.
* @throws \UnexpectedValueException If block is not of type GroupInterface.
*/
public function get_group_by_id( string $group_id ): ?GroupInterface {
$group = $this->get_block( $group_id );
if ( $group && ! $group instanceof GroupInterface ) {
throw new \UnexpectedValueException( 'Block with specified ID is not a group.' );
}
return $group;
}
/**
* Get a section block by ID.
*
* @param string $section_id The section block ID.
* @throws \UnexpectedValueException If block is not of type SectionInterface.
*/
public function get_section_by_id( string $section_id ): ?SectionInterface {
$section = $this->get_block( $section_id );
if ( $section && ! $section instanceof SectionInterface ) {
throw new \UnexpectedValueException( 'Block with specified ID is not a section.' );
}
return $section;
}
/**
* Get a block by ID.
*
* @param string $block_id The block block ID.
*/
public function get_block_by_id( string $block_id ): ?BlockInterface {
return $this->get_block( $block_id );
}
/**
* Add a custom block type to this template.
*
* @param array $block_config The block data.
*/
public function add_group( array $block_config ): GroupInterface {
$block = new Group( $block_config, $this->get_root_template(), $this );
return $this->add_inner_block( $block );
}
}

View File

@ -0,0 +1,49 @@
<?php
/**
* WooCommerce Product Group Block class.
*/
namespace Automattic\WooCommerce\Admin\Features\ProductBlockEditor\ProductTemplates;
use Automattic\WooCommerce\Admin\BlockTemplates\BlockTemplateInterface;
use Automattic\WooCommerce\Admin\BlockTemplates\ContainerInterface;
use Automattic\WooCommerce\Internal\Admin\BlockTemplates\BlockContainerTrait;
/**
* Class for Group block.
*/
class Group extends ProductBlock implements GroupInterface {
use BlockContainerTrait;
/**
* Group Block constructor.
*
* @param array $config The block configuration.
* @param BlockTemplateInterface $root_template The block template that this block belongs to.
* @param ContainerInterface|null $parent The parent block container.
*
* @throws \ValueError If the block configuration is invalid.
* @throws \ValueError If the parent block container does not belong to the same template as the block.
* @throws \InvalidArgumentException If blockName key and value are passed into block configuration.
*/
public function __construct( array $config, BlockTemplateInterface &$root_template, ContainerInterface &$parent = null ) {
if ( ! empty( $config['blockName'] ) ) {
throw new \InvalidArgumentException( 'Unexpected key "blockName", this defaults to "woocommerce/product-tab".' );
}
if ( $config['id'] && ( empty( $config['attributes'] ) || empty( $config['attributes']['id'] ) ) ) {
$config['attributes'] = empty( $config['attributes'] ) ? [] : $config['attributes'];
$config['attributes']['id'] = $config['id'];
}
parent::__construct( array_merge( array( 'blockName' => 'woocommerce/product-tab' ), $config ), $root_template, $parent );
}
/**
* Add a section block type to this template.
*
* @param array $block_config The block data.
*/
public function add_section( array $block_config ): SectionInterface {
$block = new Section( $block_config, $this->get_root_template(), $this );
return $this->add_inner_block( $block );
}
}

View File

@ -0,0 +1,19 @@
<?php
namespace Automattic\WooCommerce\Admin\Features\ProductBlockEditor\ProductTemplates;
use Automattic\WooCommerce\Admin\BlockTemplates\BlockContainerInterface;
/**
* Interface for block containers.
*/
interface GroupInterface extends BlockContainerInterface {
/**
* Adds a new section block.
*
* @param array $block_config block config.
* @return SectionInterface new block section.
*/
public function add_section( array $block_config ): SectionInterface;
}

View File

@ -0,0 +1,27 @@
<?php
/**
* WooCommerce Product Block class.
*/
namespace Automattic\WooCommerce\Admin\Features\ProductBlockEditor\ProductTemplates;
use Automattic\WooCommerce\Admin\BlockTemplates\BlockInterface;
use Automattic\WooCommerce\Admin\BlockTemplates\ContainerInterface;
use Automattic\WooCommerce\Internal\Admin\BlockTemplates\AbstractBlock;
use Automattic\WooCommerce\Internal\Admin\BlockTemplates\BlockContainerTrait;
/**
* Class for Product block.
*/
class ProductBlock extends AbstractBlock implements ContainerInterface {
use BlockContainerTrait;
/**
* Adds block to the section block.
*
* @param array $block_config The block data.
*/
public function &add_block( array $block_config ): BlockInterface {
$block = new ProductBlock( $block_config, $this->get_root_template(), $this );
return $this->add_inner_block( $block );
}
}

View File

@ -0,0 +1,44 @@
<?php
namespace Automattic\WooCommerce\Admin\Features\ProductBlockEditor\ProductTemplates;
use Automattic\WooCommerce\Admin\BlockTemplates\BlockInterface;
use Automattic\WooCommerce\Admin\BlockTemplates\BlockTemplateInterface;
/**
* Interface for block containers.
*/
interface ProductFormTemplateInterface extends BlockTemplateInterface {
/**
* Adds a new group block.
*
* @param array $block_config block config.
* @return BlockInterface new block section.
*/
public function add_group( array $block_config ): GroupInterface;
/**
* Gets Group block by id.
*
* @param string $group_id group id.
* @return GroupInterface|null
*/
public function get_group_by_id( string $group_id ): ?GroupInterface;
/**
* Gets Section block by id.
*
* @param string $section_id section id.
* @return SectionInterface|null
*/
public function get_section_by_id( string $section_id ): ?SectionInterface;
/**
* Gets Block by id.
*
* @param string $block_id block id.
* @return BlockInterface|null
*/
public function get_block_by_id( string $block_id ): ?BlockInterface;
}

View File

@ -0,0 +1,43 @@
<?php
/**
* WooCommerce Section Block class.
*/
namespace Automattic\WooCommerce\Admin\Features\ProductBlockEditor\ProductTemplates;
use Automattic\WooCommerce\Admin\BlockTemplates\BlockTemplateInterface;
use Automattic\WooCommerce\Admin\BlockTemplates\ContainerInterface;
/**
* Class for Section block.
*/
class Section extends ProductBlock implements SectionInterface {
/**
* Section Block constructor.
*
* @param array $config The block configuration.
* @param BlockTemplateInterface $root_template The block template that this block belongs to.
* @param ContainerInterface|null $parent The parent block container.
*
* @throws \ValueError If the block configuration is invalid.
* @throws \ValueError If the parent block container does not belong to the same template as the block.
* @throws \InvalidArgumentException If blockName key and value are passed into block configuration.
*/
public function __construct( array $config, BlockTemplateInterface &$root_template, ContainerInterface &$parent = null ) {
if ( ! empty( $config['blockName'] ) ) {
throw new \InvalidArgumentException( 'Unexpected key "blockName", this defaults to "woocommerce/product-section".' );
}
parent::__construct( array_merge( array( 'blockName' => 'woocommerce/product-section' ), $config ), $root_template, $parent );
}
/**
* Add a section block type to this template.
*
* @param array $block_config The block data.
*/
public function add_section( array $block_config ): SectionInterface {
$block = new Section( $block_config, $this->get_root_template(), $this );
return $this->add_inner_block( $block );
}
}

View File

@ -0,0 +1,19 @@
<?php
namespace Automattic\WooCommerce\Admin\Features\ProductBlockEditor\ProductTemplates;
use Automattic\WooCommerce\Admin\BlockTemplates\BlockContainerInterface;
/**
* Interface for block containers.
*/
interface SectionInterface extends BlockContainerInterface {
/**
* Adds a new section block.
*
* @param array $block_config block config.
* @return SectionInterface new block section.
*/
public function add_section( array $block_config ): SectionInterface;
}

View File

@ -0,0 +1,754 @@
<?php
/**
* SimpleProductTemplate
*/
namespace Automattic\WooCommerce\Admin\Features\ProductBlockEditor\ProductTemplates;
use Automattic\WooCommerce\Admin\Features\Features;
/**
* Simple Product Template.
*/
class SimpleProductTemplate extends AbstractProductFormTemplate implements ProductFormTemplateInterface {
/**
* The context name used to identify the editor.
*/
const GROUP_IDS = array(
'GENERAL' => 'general',
'ORGANIZATION' => 'organization',
'PRICING' => 'pricing',
'INVENTORY' => 'inventory',
'SHIPPING' => 'shipping',
'VARIATIONS' => 'variations',
);
/**
* SimpleProductTemplate constructor.
*/
public function __construct() {
$this->add_group_blocks();
$this->add_general_group_blocks();
$this->add_organization_group_blocks();
$this->add_pricing_group_blocks();
$this->add_inventory_group_blocks();
$this->add_shipping_group_blocks();
$this->add_variation_group_blocks();
}
/**
* Get the template ID.
*/
public function get_id(): string {
return 'simple-product';
}
/**
* Get the template title.
*/
public function get_title(): string {
return __( 'Simple Product Template', 'woocommerce' );
}
/**
* Get the template description.
*/
public function get_description(): string {
return __( 'Template for the simple product form', 'woocommerce' );
}
/**
* Adds the group blocks to the template.
*/
private function add_group_blocks() {
$this->add_group(
[
'id' => $this::GROUP_IDS['GENERAL'],
'order' => 10,
'attributes' => [
'title' => __( 'General', 'woocommerce' ),
],
]
);
$this->add_group(
[
'id' => $this::GROUP_IDS['ORGANIZATION'],
'order' => 15,
'attributes' => [
'title' => __( 'Organization', 'woocommerce' ),
],
]
);
$this->add_group(
[
'id' => $this::GROUP_IDS['PRICING'],
'order' => 20,
'attributes' => [
'title' => __( 'Pricing', 'woocommerce' ),
],
]
);
$this->add_group(
[
'id' => $this::GROUP_IDS['INVENTORY'],
'order' => 30,
'attributes' => [
'title' => __( 'Inventory', 'woocommerce' ),
],
]
);
$this->add_group(
[
'id' => $this::GROUP_IDS['SHIPPING'],
'order' => 40,
'attributes' => [
'title' => __( 'Shipping', 'woocommerce' ),
],
]
);
if ( Features::is_enabled( 'product-variation-management' ) ) {
$this->add_group(
[
'id' => $this::GROUP_IDS['VARIATIONS'],
'order' => 50,
'attributes' => [
'title' => __( 'Variations', 'woocommerce' ),
],
]
);
}
}
/**
* Adds the general group blocks to the template.
*/
private function add_general_group_blocks() {
$general_group = $this->get_group_by_id( $this::GROUP_IDS['GENERAL'] );
// Basic Details Section.
$basic_details = $general_group->add_section(
[
'id' => 'basic-details',
'attributes' => [
'title' => __( 'Basic details', 'woocommerce' ),
'description' => __( 'This info will be displayed on the product page, category pages, social media, and search results.', 'woocommerce' ),
],
]
);
$basic_details->add_block(
[
'id' => 'product-name',
'blockName' => 'woocommerce/product-name-field',
'attributes' => [
'name' => 'Product name',
'autoFocus' => true,
],
]
);
$basic_details->add_block(
[
'id' => 'product-summary',
'blockName' => 'woocommerce/product-summary-field',
]
);
$pricing_columns = $basic_details->add_block(
[
'id' => 'product-pricing-columns',
'blockName' => 'core/columns',
]
);
$pricing_column_1 = $pricing_columns->add_block(
[
'id' => 'product-pricing-column-1',
'blockName' => 'core/column',
'attributes' => [
'templateLock' => 'all',
],
]
);
$pricing_column_1->add_block(
[
'id' => 'product-regular-price',
'blockName' => 'woocommerce/product-regular-price-field',
'attributes' => [
'name' => 'regular_price',
'label' => __( 'List price', 'woocommerce' ),
/* translators: PricingTab: This is a link tag to the pricing tab. */
'help' => __( 'Manage more settings in <PricingTab>Pricing.</PricingTab>', 'woocommerce' ),
],
]
);
$pricing_column_2 = $pricing_columns->add_block(
[
'id' => 'product-pricing-column-2',
'blockName' => 'core/column',
'attributes' => [
'templateLock' => 'all',
],
]
);
$pricing_column_2->add_block(
[
'id' => 'product-sale-price',
'blockName' => 'woocommerce/product-sale-price-field',
'attributes' => [
'label' => __( 'Sale price', 'woocommerce' ),
],
]
);
// Description section.
$description_section = $general_group->add_section(
[
'id' => 'product-description-section',
'attributes' => [
'title' => __( 'Description', 'woocommerce' ),
'description' => __( 'What makes this product unique? What are its most important features? Enrich the product page by adding rich content using blocks.', 'woocommerce' ),
],
]
);
$description_section->add_block(
[
'id' => 'product-description',
'blockName' => 'woocommerce/product-description-field',
]
);
// Images section.
$images_section = $general_group->add_section(
[
'id' => 'product-images-section',
'attributes' => [
'title' => __( 'Images', 'woocommerce' ),
'description' => sprintf(
/* translators: %1$s: Images guide link opening tag. %2$s: Images guide link closing tag. */
__( 'Drag images, upload new ones or select files from your library. For best results, use JPEG files that are 1000 by 1000 pixels or larger. %1$sHow to prepare images?%2$s', 'woocommerce' ),
'<a href="http://woocommerce.com/#" target="_blank" rel="noreferrer">',
'</a>'
),
],
]
);
$images_section->add_block(
[
'id' => 'product-images',
'blockName' => 'woocommerce/product-images-field',
'attributes' => [
'images' => [],
],
]
);
}
/**
* Adds the organization group blocks to the template.
*/
private function add_organization_group_blocks() {
$organization_group = $this->get_group_by_id( $this::GROUP_IDS['ORGANIZATION'] );
// Product Catalog Section.
$product_catalog_section = $organization_group->add_section(
[
'id' => 'product-catalog-section',
'attributes' => [
'title' => __( 'Product catalog', 'woocommerce' ),
],
]
);
$product_catalog_section->add_block(
[
'id' => 'product-categories',
'blockName' => 'woocommerce/product-category-field',
'attributes' => [
'name' => 'categories',
],
]
);
$product_catalog_section->add_block(
[
'id' => 'product-catalog-search-visibility',
'blockName' => 'woocommerce/product-catalog-visibility-field',
'attributes' => [
'label' => __( 'Hide in product catalog', 'woocommerce' ),
'visibility' => 'search',
],
]
);
$product_catalog_section->add_block(
[
'id' => 'product-catalog-catalog-visibility',
'blockName' => 'woocommerce/product-catalog-visibility-field',
'attributes' => [
'label' => __( 'Hide from search results', 'woocommerce' ),
'visibility' => 'catalog',
],
]
);
$product_catalog_section->add_block(
[
'id' => 'product-enable-product-reviews',
'blockName' => 'woocommerce/product-checkbox-field',
'attributes' => [
'label' => __( 'Enable product reviews', 'woocommerce' ),
'property' => 'reviews_allowed',
],
]
);
$product_catalog_section->add_block(
[
'id' => 'product-post-password',
'blockName' => 'woocommerce/product-password-field',
'attributes' => [
'label' => __( 'Require a password', 'woocommerce' ),
],
]
);
// Attributes section.
$product_catalog_section = $organization_group->add_section(
[
'id' => 'product-attributes-section',
'attributes' => [
'title' => __( 'Attributes', 'woocommerce' ),
],
]
);
$product_catalog_section->add_block(
[
'id' => 'product-attributes',
'blockName' => 'woocommerce/product-attributes-field',
]
);
}
/**
* Adds the pricing group blocks to the template.
*/
private function add_pricing_group_blocks() {
$pricing_group = $this->get_group_by_id( $this::GROUP_IDS['PRICING'] );
$pricing_group->add_block(
[
'id' => 'pricing-has-variations-notice',
'blockName' => 'woocommerce/product-has-variations-notice',
'attributes' => [
'content' => __( 'This product has options, such as size or color. You can now manage each variation\'s price and other details individually.', 'woocommerce' ),
'buttonText' => __( 'Go to Variations', 'woocommerce' ),
'type' => 'info',
],
]
);
// Product Pricing Section.
$product_pricing_section = $pricing_group->add_section(
[
'id' => 'product-pricing-section',
'attributes' => [
'title' => __( 'Pricing', 'woocommerce' ),
'description' => sprintf(
/* translators: %1$s: Images guide link opening tag. %2$s: Images guide link closing tag.*/
__( 'Set a competitive price, put the product on sale, and manage tax calculations. %1$sHow to price your product?%2$s', 'woocommerce' ),
'<a href="https://woocommerce.com/posts/how-to-price-products-strategies-expert-tips/" target="_blank" rel="noreferrer">',
'</a>'
),
'blockGap' => 'unit-40',
],
]
);
$pricing_columns = $product_pricing_section->add_block(
[
'id' => 'product-pricing-group-pricing-columns',
'blockName' => 'core/columns',
]
);
$pricing_column_1 = $pricing_columns->add_block(
[
'id' => 'product-pricing-group-pricing-column-1',
'blockName' => 'core/column',
'attributes' => [
'templateLock' => 'all',
],
]
);
$pricing_column_1->add_block(
[
'id' => 'product-pricing-regular-price',
'blockName' => 'woocommerce/product-regular-price-field',
'attributes' => [
'name' => 'regular_price',
'label' => __( 'List price', 'woocommerce' ),
],
]
);
$pricing_column_2 = $pricing_columns->add_block(
[
'id' => 'product-pricing-group-pricing-column-2',
'blockName' => 'core/column',
'attributes' => [
'templateLock' => 'all',
],
]
);
$pricing_column_2->add_block(
[
'id' => 'product-pricing-sale-price',
'blockName' => 'woocommerce/product-sale-price-field',
'attributes' => [
'label' => __( 'Sale price', 'woocommerce' ),
],
]
);
$product_pricing_section->add_block(
[
'id' => 'product-pricing-schedule-sale-fields',
'blockName' => 'woocommerce/product-schedule-sale-fields',
]
);
$product_pricing_section->add_block(
[
'id' => 'product-sale-tax',
'blockName' => 'woocommerce/product-radio-field',
'attributes' => [
'title' => __( 'Charge sales tax on', 'woocommerce' ),
'property' => 'tax_status',
'options' => [
[
'label' => __( 'Product and shipping', 'woocommerce' ),
'value' => 'taxable',
],
[
'label' => __( 'Only shipping', 'woocommerce' ),
'value' => 'shipping',
],
[
'label' => __( "Don't charge tax", 'woocommerce' ),
'value' => 'none',
],
],
],
]
);
$pricing_advanced_block = $product_pricing_section->add_block(
[
'id' => 'product-pricing-advanced',
'blockName' => 'woocommerce/product-collapsible',
'attributes' => [
'toggleText' => __( 'Advanced', 'woocommerce' ),
'initialCollapsed' => true,
'persistRender' => true,
],
]
);
$pricing_advanced_block->add_block(
[
'id' => 'product-tax-class',
'blockName' => 'woocommerce/product-radio-field',
'attributes' => [
'title' => __( 'Tax class', 'woocommerce' ),
'description' => sprintf(
/* translators: %1$s: Learn more link opening tag. %2$s: Learn more link closing tag.*/
__( 'Apply a tax rate if this product qualifies for tax reduction or exemption. %1$sLearn more%2$s.', 'woocommerce' ),
'<a href="https://woocommerce.com/document/setting-up-taxes-in-woocommerce/#shipping-tax-class" target="_blank" rel="noreferrer">',
'</a>'
),
'property' => 'tax_class',
'options' => [
[
'label' => __( 'Standard', 'woocommerce' ),
'value' => '',
],
[
'label' => __( 'Reduced rate', 'woocommerce' ),
'value' => 'reduced-rate',
],
[
'label' => __( 'Zero rate', 'woocommerce' ),
'value' => 'zero-rate',
],
],
],
]
);
}
/**
* Adds the inventory group blocks to the template.
*/
private function add_inventory_group_blocks() {
$inventory_group = $this->get_group_by_id( $this::GROUP_IDS['INVENTORY'] );
$inventory_group->add_block(
[
'id' => 'product_variation_notice_inventory_tab',
'blockName' => 'woocommerce/product-has-variations-notice',
'attributes' => [
'content' => __( 'This product has options, such as size or color. You can now manage each variation\'s price and other details individually.', 'woocommerce' ),
'buttonText' => __( 'Go to Variations', 'woocommerce' ),
'type' => 'info',
],
]
);
// Product Pricing Section.
$product_inventory_section = $inventory_group->add_section(
[
'id' => 'product-inventory-section',
'attributes' => [
'title' => __( 'Inventory', 'woocommerce' ),
'description' => sprintf(
/* translators: %1$s: Inventory settings link opening tag. %2$s: Inventory settings link closing tag.*/
__( 'Set up and manage inventory for this product, including status and available quantity. %1$sManage store inventory settings%2$s', 'woocommerce' ),
'<a href="' . admin_url( 'admin.php?page=wc-settings&tab=products&section=inventory' ) . '" target="_blank" rel="noreferrer">',
'</a>'
),
'blockGap' => 'unit-40',
],
]
);
$product_inventory_inner_section = $product_inventory_section->add_section(
[
'id' => 'product-inventory-inner-section',
]
);
$product_inventory_inner_section->add_block(
[
'id' => 'product-sku-field',
'blockName' => 'woocommerce/product-sku-field',
]
);
$product_inventory_inner_section->add_block(
[
'id' => 'product-track-stock',
'blockName' => 'woocommerce/product-toggle-field',
'attributes' => [
'label' => __( 'Track stock quantity for this product', 'woocommerce' ),
'property' => 'manage_stock',
'disabled' => 'yes' !== get_option( 'woocommerce_manage_stock' ),
],
]
);
$product_inventory_quantity_conditional = $product_inventory_inner_section->add_block(
[
'id' => 'product-inventory-quantity-conditional-wrapper',
'blockName' => 'woocommerce/conditional',
'attributes' => [
'mustMatch' => [
'manage_stock' => [ true ],
],
],
]
);
$product_inventory_quantity_conditional->add_block(
[
'id' => 'product-inventory-quantity',
'blockName' => 'woocommerce/product-inventory-quantity-field',
]
);
$product_stock_status_conditional = $product_inventory_section->add_block(
[
'id' => 'product-stock-status-conditional-wrapper',
'blockName' => 'woocommerce/conditional',
'attributes' => [
'mustMatch' => [
'manage_stock' => [ false ],
],
],
]
);
$product_stock_status_conditional->add_block(
[
'id' => 'product-stock-status',
'blockName' => 'woocommerce/product-radio-field',
'attributes' => [
'title' => __( 'Stock status', 'woocommerce' ),
'property' => 'stock_status',
'options' => [
[
'label' => __( 'In stock', 'woocommerce' ),
'value' => 'instock',
],
[
'label' => __( 'Out of stock', 'woocommerce' ),
'value' => 'outofstock',
],
[
'label' => __( 'On backorder', 'woocommerce' ),
'value' => 'onbackorder',
],
],
],
]
);
$product_inventory_advanced = $product_inventory_section->add_block(
[
'id' => 'product-inventory-advanced',
'blockName' => 'woocommerce/product-collapsible',
'attributes' => [
'toggleText' => __( 'Advanced', 'woocommerce' ),
'initialCollapsed' => true,
'persistRender' => true,
],
]
);
$product_inventory_advanced_wrapper = $product_inventory_advanced->add_block(
[
'blockName' => 'woocommerce/product-section',
'attributes' => [
'blockGap' => 'unit-40',
],
]
);
$product_out_of_stock_conditional = $product_inventory_advanced_wrapper->add_block(
[
'id' => 'product-out-of-stock-conditional-wrapper',
'blockName' => 'woocommerce/conditional',
'attributes' => [
'mustMatch' => [
'manage_stock' => [ true ],
],
],
]
);
$product_out_of_stock_conditional->add_block(
[
'id' => 'product-out-of-stock',
'blockName' => 'woocommerce/product-radio-field',
'attributes' => [
'title' => __( 'When out of stock', 'woocommerce' ),
'property' => 'backorders',
'options' => [
[
'label' => __( 'Allow purchases', 'woocommerce' ),
'value' => 'yes',
],
[
'label' => __(
'Allow purchases, but notify customers',
'woocommerce'
),
'value' => 'notify',
],
[
'label' => __( "Don't allow purchases", 'woocommerce' ),
'value' => 'no',
],
],
],
]
);
$product_out_of_stock_conditional->add_block(
[
'id' => 'product-inventory-email',
'blockName' => 'woocommerce/product-inventory-email-field',
]
);
$product_inventory_advanced_wrapper->add_block(
[
'id' => 'product-limit-purchase',
'blockName' => 'woocommerce/product-checkbox-field',
'attributes' => [
'title' => __(
'Restrictions',
'woocommerce'
),
'label' => __(
'Limit purchases to 1 item per order',
'woocommerce'
),
'property' => 'sold_individually',
'tooltip' => __(
'When checked, customers will be able to purchase only 1 item in a single order. This is particularly useful for items that have limited quantity, like art or handmade goods.',
'woocommerce'
),
],
]
);
}
/**
* Adds the shipping group blocks to the template.
*/
private function add_shipping_group_blocks() {
$shipping_group = $this->get_group_by_id( $this::GROUP_IDS['SHIPPING'] );
$shipping_group->add_block(
[
'id' => 'product_variation_notice_shipping_tab',
'blockName' => 'woocommerce/product-has-variations-notice',
'attributes' => [
'content' => __( 'This product has options, such as size or color. You can now manage each variation\'s price and other details individually.', 'woocommerce' ),
'buttonText' => __( 'Go to Variations', 'woocommerce' ),
'type' => 'info',
],
]
);
// Product Pricing Section.
$product_fee_and_dimensions_section = $shipping_group->add_section(
[
'id' => 'product-fee-and-dimensions-section',
'attributes' => [
'title' => __( 'Fees & dimensions', 'woocommerce' ),
'description' => sprintf(
/* translators: %1$s: How to get started? link opening tag. %2$s: How to get started? link closing tag.*/
__( 'Set up shipping costs and enter dimensions used for accurate rate calculations. %1$sHow to get started?%2$s.', 'woocommerce' ),
'<a href="https://woocommerce.com/posts/how-to-calculate-shipping-costs-for-your-woocommerce-store/" target="_blank" rel="noreferrer">',
'</a>'
),
],
]
);
$product_fee_and_dimensions_section->add_block(
[
'id' => 'product-shipping-class',
'blockName' => 'woocommerce/product-shipping-class-field',
]
);
$product_fee_and_dimensions_section->add_block(
[
'id' => 'product-shipping-dimensions',
'blockName' => 'woocommerce/product-shipping-dimensions-fields',
]
);
}
/**
* Adds the variation group blocks to the template.
*/
private function add_variation_group_blocks() {
$variation_group = $this->get_group_by_id( $this::GROUP_IDS['VARIATIONS'] );
if ( ! $variation_group ) {
return;
}
$variation_fields = $variation_group->add_block(
[
'id' => 'product_variation-field-group',
'blockName' => 'woocommerce/product-variations-fields',
'attributes' => [
'description' => sprintf(
/* translators: %1$s: Sell your product in multiple variations like size or color. strong opening tag. %2$s: Sell your product in multiple variations like size or color. strong closing tag.*/
__( '%1$sSell your product in multiple variations like size or color.%2$s Get started by adding options for the buyers to choose on the product page.', 'woocommerce' ),
'<strong>',
'</strong>'
),
],
]
);
$variation_fields->add_block(
[
'id' => 'product-variation-options',
'blockName' => 'woocommerce/product-variations-options-field',
'attributes' => [
'title' => __( 'Variation options', 'woocommerce' ),
],
]
);
$variation_section = $variation_fields->add_block(
[
'id' => 'product-variation-section',
'blockName' => 'woocommerce/product-section',
'attributes' => [
'title' => __( 'Variations', 'woocommerce' ),
],
]
);
$variation_section->add_block(
[
'id' => 'product-variation-items',
'blockName' => 'woocommerce/product-variation-items-field',
]
);
}
}

View File

@ -2,7 +2,6 @@
namespace Automattic\WooCommerce\Internal\Admin\BlockTemplates;
use Automattic\WooCommerce\Admin\BlockTemplates\ContainerInterface;
use Automattic\WooCommerce\Admin\BlockTemplates\BlockInterface;
use Automattic\WooCommerce\Admin\BlockTemplates\BlockTemplateInterface;
@ -15,7 +14,7 @@ abstract class AbstractBlockTemplate implements BlockTemplateInterface {
/**
* Get the template ID.
*/
public abstract function get_id(): string;
abstract public function get_id(): string;
/**
* Get the template title.
@ -110,7 +109,7 @@ abstract class AbstractBlockTemplate implements BlockTemplateInterface {
$inner_blocks = $this->get_inner_blocks_sorted_by_order();
$inner_blocks_formatted_template = array_map(
function( Block $block ) {
function( BlockInterface $block ) {
return $block->get_formatted_template();
},
$inner_blocks

View File

@ -12,31 +12,6 @@ use Automattic\WooCommerce\Admin\BlockTemplates\BlockTemplateInterface;
class Block extends AbstractBlock implements BlockContainerInterface {
use BlockContainerTrait;
/**
* Get the block configuration as a formatted template.
*
* @return array The block configuration as a formatted template.
*/
public function get_formatted_template(): array {
$arr = [
$this->get_name(),
$this->get_attributes(),
];
$inner_blocks = $this->get_inner_blocks_sorted_by_order();
if ( ! empty( $inner_blocks ) ) {
$arr[] = array_map(
function( BlockInterface $block ) {
return $block->get_formatted_template();
},
$inner_blocks
);
}
return $arr;
}
/**
* Add an inner block to this block.
*

View File

@ -52,7 +52,7 @@ trait BlockContainerTrait {
usort(
$sorted_inner_blocks,
function( Block $a, Block $b ) {
function( BlockInterface $a, BlockInterface $b ) {
return $a->get_order() <=> $b->get_order();
}
);

View File

@ -0,0 +1,80 @@
<?php
namespace Automattic\WooCommerce\Tests\Admin\ProductBlockEditor\ProductTemplates;
use Automattic\WooCommerce\Admin\Features\ProductBlockEditor\ProductTemplates\AbstractProductFormTemplate;
use Automattic\WooCommerce\Admin\Features\ProductBlockEditor\ProductTemplates\ProductFormTemplateInterface;
class CustomProductFormTemplate extends AbstractProductFormTemplate implements ProductFormTemplateInterface {
/**
* SimpleProductTemplate constructor.
*/
public function __construct() {
$general_group = $this->add_group(
[
'id' => 'general',
'order' => 10,
'attributes' => [
'title' => 'General',
],
]
);
$basic_details = $general_group->add_section(
[
'id' => 'basic-details',
'attributes' => [
'title' => 'Basic details',
'description' => 'Description',
],
]
);
$basic_details->add_block(
[
'id' => 'product-name',
'blockName' => 'woocommerce/product-name-field',
'attributes' => [
'name' => 'Product name',
'autoFocus' => true,
],
]
);
$pricing_group = $this->add_group(
[
'id' => 'pricing',
'order' => 20,
'attributes' => [
'title' => 'Pricing',
],
]
);
$product_pricing_section = $pricing_group->add_section(
[
'id' => 'product-pricing-section',
'attributes' => [
'title' => 'Pricing',
'description' => '',
'blockGap' => 'unit-40',
],
]
);
$product_pricing_section->add_block(
[
'id' => 'product-pricing-group-pricing-columns',
'blockName' => 'core/columns',
]
);
}
/**
* Get the template ID.
*/
public function get_id(): string {
return 'custom-product';
}
/**
* Get the template title.
*/
public function get_title(): string {
return 'Custom Product Template';
}
}

View File

@ -0,0 +1,129 @@
<?php
namespace Automattic\WooCommerce\Tests\Admin\ProductBlockEditor\ProductTemplates;
use WC_Unit_Test_Case;
/**
* Tests for the CustomBlockTemplate class.
*/
class CustomProductFormTemplateTest extends WC_Unit_Test_Case {
/**
* Test getting the template ID.
*/
public function test_get_id() {
$template = new CustomProductFormTemplate();
$this->assertEquals( $template->get_id(), 'custom-product' );
}
/**
* Test get group block by id.
*/
public function test_get_group_by_id() {
$template = new CustomProductFormTemplate();
$block = $template->get_group_by_id( 'general' );
$this->assertEquals( $block->get_attributes()['title'], 'General' );
}
/**
* Test throw error get group block with section id.
*/
public function test_get_group_by_id_with_section_id() {
$template = new CustomProductFormTemplate();
$this->expectException( \UnexpectedValueException::class );
$template->get_group_by_id('basic-details' );
}
/**
* Test get section block by id.
*/
public function test_get_section_by_id() {
$template = new CustomProductFormTemplate();
$block = $template->get_section_by_id( 'product-pricing-section' );
$this->assertEquals( $block->get_attributes()['title'], 'Pricing' );
}
/**
* Test throw error get section block with section id.
*/
public function test_get_section_by_id_with_block_id() {
$template = new CustomProductFormTemplate();
$this->expectException( \UnexpectedValueException::class );
$template->get_section_by_id( 'product-pricing-group-pricing-columns' );
}
/**
* Test get block by id.
*/
public function test_get_block_by_id() {
$template = new CustomProductFormTemplate();
$block = $template->get_block_by_id( 'product-name' );
$this->assertEquals( $block->get_attributes()['name'], 'Product name' );
}
/**
* Test add custom block to section.
*/
public function test_add_custom_block_to_section() {
$template = new CustomProductFormTemplate();
$block = $template->get_section_by_id( 'product-pricing-section' );
$new_block = $block->add_block( [
'id' => 'test-block-id',
'blockName' => 'test-block-name',
'attributes' => [
'name' => 'A name'
]
] );
$this->assertEquals( $new_block->get_parent(), $block );
}
/**
* Test add custom group.
*/
public function test_add_custom_group() {
$template = new CustomProductFormTemplate();
$new_group = $template->add_group( [
'id' => 'new-group',
'order' => 0,
'attributes' => [
'title' => 'Group title'
]
] );
$this->assertEquals( $new_group->get_parent(), $template );
}
/**
* Test throw error when passing blockName to add_group.
*/
public function test_passing_blockname_to_add_group() {
$template = new CustomProductFormTemplate();
$this->expectException( \InvalidArgumentException::class );
$template->add_group( [
'id' => 'new-group',
'blockName' => 'block-name',
'order' => 0,
'attributes' => [
'title' => 'Group title'
]
] );
}
/**
* Test throw error when passing blockName to add_section.
*/
public function test_passing_blockname_to_add_section() {
$template = new CustomProductFormTemplate();
$group = $template->get_group_by_id( 'general' );
$this->expectException( \InvalidArgumentException::class );
$group->add_section( [
'id' => 'new-section',
'blockName' => 'block-name',
'attributes' => [
'title' => 'Section title'
]
] );
}
}