Layout templates REST API (#43067)

* Endpoint shell

* Single layout template route

* Add area query arg

* Fix BlockTemplateRegistry::get_registered() return type

* Check if templates are registered before registering

* Use json format for layout templates response

* Remove unused use

* Use json format for layout templates response for get_items

* Consolidate processing for get_items and get_item

* LayoutTemplateRegistry

* Fix matching by id

* Get templates from LayoutTemplateRegistry

* Remove unused method

* Fix typo in code doc

* Move template instantiation to registry

* Return template instance, not json when instantiating

* Use LayoutTemplateRegistry instead of BlockTemplateRegistry

* Add code docs for rest controller

* Fix code doc in BlockTemplateRegistry

* Code docs for LayoutTemplateRegistry

* Changelog

* Add code doc for LayoutTemplatesServiceProvider

* Unit test for registering a layout template

* Unit tests for invalid params when registering layout template

* Unit test for layout template instantiation

* Unit test for instantiating layout templates with query params

* Unit test for layout template instance caching

* Cache layout template instances

* Refactor layout template info querying

* Add unit test for layout template instantiation actions

* Add before and after layout template instantiation actions

* Use layout template ID for array key

* REST API unit test to get all items

* Unit test for unregister_all

* Method to unregister all layout templates

* REST API unit test to get all items for a specific area

* Fix to_json() in TestLayoutTemplate

* REST API unit test to get single item

* Fix get_item

* REST API unit test for single item with invalid id

* REST API unit test for get all items for invalid area

* Fix test_cached_instances - array access

* Test that old register hook is called

* Call old register hook

* Remove before hook (will put in separate PR)
This commit is contained in:
Matt Sherman 2024-01-03 20:02:38 -05:00 committed by GitHub
parent 280fe7cd51
commit a8dab20997
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 844 additions and 10 deletions

View File

@ -0,0 +1,4 @@
Significance: minor
Type: add
Template layout REST API endpoints.

View File

@ -0,0 +1,146 @@
<?php
/**
* REST API Layout Templates controller
*
* Handles requests to /layout-templates.
*
* @package WooCommerce\RestApi
* @since 8.6.0
*/
defined( 'ABSPATH' ) || exit;
use Automattic\WooCommerce\LayoutTemplates\LayoutTemplateRegistry;
/**
* REST API Layout Templates controller class.
*/
class WC_REST_Layout_Templates_Controller extends WC_REST_Controller {
/**
* Endpoint namespace.
*
* @var string
*/
protected $namespace = 'wc/v3';
/**
* Route base.
*
* @var string
*/
protected $rest_base = 'layout-templates';
/**
* Register the routes for template layouts.
*/
public function register_routes() {
register_rest_route(
$this->namespace,
'/' . $this->rest_base,
array(
'methods' => WP_REST_Server::READABLE,
'callback' => array( $this, 'get_items' ),
'permission_callback' => array( $this, 'get_items_permissions_check' ),
'args' => array(
'area' => array(
'description' => __( 'Area to get templates for.', 'woocommerce' ),
'type' => 'string',
'default' => '',
),
),
)
);
register_rest_route(
$this->namespace,
'/' . $this->rest_base . '/(?P<id>\w[\w\s\-]*)',
array(
'args' => array(
'id' => array(
'description' => __( 'Unique identifier for the resource.', 'woocommerce' ),
'type' => 'string',
),
),
array(
'methods' => WP_REST_Server::READABLE,
'callback' => array( $this, 'get_item' ),
'permission_callback' => array( $this, 'get_item_permissions_check' ),
'args' => array(),
),
)
);
}
/**
* Check if a given request has access to read template layouts.
*
* @param WP_REST_Request $request The request.
*/
public function get_items_permissions_check( $request ): bool {
return true;
}
/**
* Check if a given request has access to read a template layout.
*
* @param WP_REST_Request $request The request.
*/
public function get_item_permissions_check( $request ): bool {
return true;
}
/**
* Handle request for template layouts.
*
* @param WP_REST_Request $request The request.
*/
public function get_items( $request ) {
$layout_templates = $this->get_layout_templates(
array(
'area' => $request['area'],
)
);
$response = rest_ensure_response( $layout_templates );
return $response;
}
/**
* Handle request for a single template layout.
*
* @param WP_REST_Request $request The request.
*/
public function get_item( $request ) {
$layout_templates = $this->get_layout_templates(
array(
'id' => $request['id'],
)
);
if ( count( $layout_templates ) !== 1 ) {
return new WP_Error( 'woocommerce_rest_layout_template_invalid_id', __( 'Invalid layout template ID.', 'woocommerce' ), array( 'status' => 404 ) );
}
$response = rest_ensure_response( current( $layout_templates ) );
return $response;
}
/**
* Get layout templates.
*
* @param array $query_params Query params.
*/
private function get_layout_templates( array $query_params ): array {
$layout_template_registry = wc_get_container()->get( LayoutTemplateRegistry::class );
return array_map(
function( $layout_template ) {
return $layout_template->to_json();
},
$layout_template_registry->instantiate_layout_templates( $query_params )
);
}
}

View File

@ -143,6 +143,7 @@ class Server {
'coupons' => 'WC_REST_Coupons_Controller',
'customer-downloads' => 'WC_REST_Customer_Downloads_Controller',
'customers' => 'WC_REST_Customers_Controller',
'layout-templates' => 'WC_REST_Layout_Templates_Controller',
'network-orders' => 'WC_REST_Network_Orders_Controller',
'order-notes' => 'WC_REST_Order_Notes_Controller',
'order-refunds' => 'WC_REST_Order_Refunds_Controller',

View File

@ -6,13 +6,14 @@
namespace Automattic\WooCommerce\Admin\Features\ProductBlockEditor;
use Automattic\WooCommerce\Admin\Features\Features;
use Automattic\WooCommerce\Internal\Admin\Features\ProductBlockEditor\ProductTemplates\SimpleProductTemplate;
use Automattic\WooCommerce\Internal\Admin\Features\ProductBlockEditor\ProductTemplates\ProductVariationTemplate;
use Automattic\WooCommerce\Admin\Features\ProductBlockEditor\ProductTemplate;
use Automattic\WooCommerce\Admin\PageController;
use Automattic\WooCommerce\Internal\Admin\BlockTemplateRegistry\BlockTemplateRegistry;
use Automattic\WooCommerce\Internal\Admin\BlockTemplates\Block;
use Automattic\WooCommerce\LayoutTemplates\LayoutTemplateRegistry;
use Automattic\WooCommerce\Internal\Admin\BlockTemplates\BlockTemplateLogger;
use Automattic\WooCommerce\Internal\Admin\Features\ProductBlockEditor\ProductTemplates\SimpleProductTemplate;
use Automattic\WooCommerce\Internal\Admin\Features\ProductBlockEditor\ProductTemplates\ProductVariationTemplate;
use WP_Block_Editor_Context;
/**
@ -68,6 +69,8 @@ class Init {
add_action( 'current_screen', array( $this, 'set_current_screen_to_block_editor_if_wc_admin' ) );
add_action( 'rest_api_init', array( $this, 'register_product_editor_templates' ) );
// Make sure the block registry is initialized so that core blocks are registered.
BlockRegistry::get_instance();
@ -211,12 +214,12 @@ class Init {
* Get the product editor settings.
*/
private function get_product_editor_settings() {
$layout_template_registry = wc_get_container()->get( BlockTemplateRegistry::class );
$layout_template_registry = wc_get_container()->get( LayoutTemplateRegistry::class );
$layout_template_logger = BlockTemplateLogger::get_instance();
$editor_settings = array();
foreach ( $layout_template_registry->get_all_registered() as $layout_template ) {
foreach ( $layout_template_registry->instantiate_layout_templates() as $layout_template ) {
$editor_settings['layoutTemplates'][] = $layout_template->to_json();
$layout_template_logger->log_template_events_to_file( $layout_template->get_id() );
@ -370,9 +373,23 @@ class Init {
/**
* Register product editor templates.
*/
private function register_product_editor_templates() {
$template_registry = wc_get_container()->get( BlockTemplateRegistry::class );
$template_registry->register( new SimpleProductTemplate() );
$template_registry->register( new ProductVariationTemplate() );
public function register_product_editor_templates() {
$layout_template_registry = wc_get_container()->get( LayoutTemplateRegistry::class );
if ( ! $layout_template_registry->is_registered( 'simple-product' ) ) {
$layout_template_registry->register(
'simple-product',
'product-form',
SimpleProductTemplate::class
);
}
if ( ! $layout_template_registry->is_registered( 'product-variation' ) ) {
$layout_template_registry->register(
'product-variation',
'product-form',
ProductVariationTemplate::class
);
}
}
}

View File

@ -30,6 +30,7 @@ use Automattic\WooCommerce\Internal\DependencyManagement\ServiceProviders\Restoc
use Automattic\WooCommerce\Internal\DependencyManagement\ServiceProviders\UtilsClassesServiceProvider;
use Automattic\WooCommerce\Internal\DependencyManagement\ServiceProviders\BatchProcessingServiceProvider;
use Automattic\WooCommerce\Internal\DependencyManagement\ServiceProviders\BlockTemplatesServiceProvider;
use Automattic\WooCommerce\Internal\DependencyManagement\ServiceProviders\LayoutTemplatesServiceProvider;
/**
* PSR11 compliant dependency injection container for WooCommerce.
@ -77,6 +78,7 @@ final class Container {
MarketingServiceProvider::class,
MarketplaceServiceProvider::class,
BlockTemplatesServiceProvider::class,
LayoutTemplatesServiceProvider::class,
LoggingServiceProvider::class,
EnginesServiceProvider::class,
);

View File

@ -0,0 +1,28 @@
<?php
namespace Automattic\WooCommerce\Internal\DependencyManagement\ServiceProviders;
use Automattic\WooCommerce\Internal\DependencyManagement\AbstractServiceProvider;
use Automattic\WooCommerce\LayoutTemplates\LayoutTemplateRegistry;
/**
* Service provider for layout templates.
*/
class LayoutTemplatesServiceProvider extends AbstractServiceProvider {
/**
* The classes/interfaces that are serviced by this service provider.
*
* @var array
*/
protected $provides = array(
LayoutTemplateRegistry::class,
);
/**
* Register the classes.
*/
public function register() {
$this->share( LayoutTemplateRegistry::class );
}
}

View File

@ -0,0 +1,190 @@
<?php
namespace Automattic\WooCommerce\LayoutTemplates;
use Automattic\WooCommerce\Admin\BlockTemplates\BlockTemplateInterface;
/**
* Layout template registry.
*/
final class LayoutTemplateRegistry {
/**
* Class instance.
*
* @var LayoutTemplateRegistry|null
*/
private static $instance = null;
/**
* Layout templates info.
*
* @var array
*/
protected $layout_templates_info = array();
/**
* Layout template instances.
*
* @var array
*/
protected $layout_template_instances = array();
/**
* Get the instance of the class.
*/
public static function get_instance(): LayoutTemplateRegistry {
if ( null === self::$instance ) {
self::$instance = new self();
}
return self::$instance;
}
/**
* Unregister all layout templates.
*/
public function unregister_all() {
$this->layout_templates_info = array();
$this->layout_template_instances = array();
}
/**
* Check if a layout template is registered.
*
* @param string $layout_template_id Layout template ID.
*/
public function is_registered( $layout_template_id ): bool {
return isset( $this->layout_templates_info[ $layout_template_id ] );
}
/**
* Register a single layout template.
*
* @param string $layout_template_id Layout template ID.
* @param string $layout_template_area Layout template area.
* @param string $layout_template_class_name Layout template class to register.
*
* @throws \ValueError If a layout template with the same ID already exists.
* @throws \ValueError If the specified layout template area is empty.
* @throws \ValueError If the specified layout template class does not exist.
* @throws \ValueError If the specified layout template class does not implement the BlockTemplateInterface.
*/
public function register( $layout_template_id, $layout_template_area, $layout_template_class_name ) {
if ( $this->is_registered( $layout_template_id ) ) {
throw new \ValueError( 'A layout template with the specified ID already exists in the registry.' );
}
if ( empty( $layout_template_area ) ) {
throw new \ValueError( 'The specified layout template area is empty.' );
}
if ( ! class_exists( $layout_template_class_name ) ) {
throw new \ValueError( 'The specified layout template class does not exist.' );
}
if ( ! is_subclass_of( $layout_template_class_name, BlockTemplateInterface::class ) ) {
throw new \ValueError( 'The specified layout template class does not implement the BlockTemplateInterface.' );
}
$this->layout_templates_info[ $layout_template_id ] = array(
'id' => $layout_template_id,
'area' => $layout_template_area,
'class_name' => $layout_template_class_name,
);
}
/**
* Instantiate the matching layout templates and return them.
*
* @param array $query_params Query params.
*/
public function instantiate_layout_templates( array $query_params = array() ): array {
$layout_templates = array();
$layout_templates_info = $this->get_matching_layout_templates_info( $query_params );
foreach ( $layout_templates_info as $layout_template_info ) {
$layout_template = $this->get_layout_template_instance( $layout_template_info );
$layout_templates[ $layout_template->get_id() ] = $layout_template;
}
return $layout_templates;
}
/**
* Instantiate a single layout template and return it.
*
* @param array $layout_template_info Layout template info.
*/
private function get_layout_template_instance( $layout_template_info ): BlockTemplateInterface {
$class_name = $layout_template_info['class_name'];
// Return the instance if it already exists.
$layout_template_instance = isset( $this->layout_template_instances[ $class_name ] )
? $this->layout_template_instances[ $class_name ]
: null;
if ( ! empty( $layout_template_instance ) ) {
return $layout_template_instance;
}
// Instantiate the layout template.
$layout_template_instance = new $class_name();
$this->layout_template_instances[ $class_name ] = $layout_template_instance;
// Call the after instantiation hooks.
/**
* Fires after a layout template is instantiated.
*
* @param string $layout_template_id Layout template ID.
* @param string $layout_template_area Layout template area.
* @param BlockTemplateInterface $layout_template Layout template instance.
*
* @since 8.6.0
*/
do_action( 'woocommerce_layout_template_after_instantiation', $layout_template_info['id'], $layout_template_info['area'], $layout_template_instance );
// Call the old, soon-to-be-deprecated, register hook.
/**
* Fires when a template is registered.
*
* @param BlockTemplateInterface $template Template that was registered.
*
* @since 8.2.0
*/
do_action( 'woocommerce_block_template_register', $layout_template_instance );
return $layout_template_instance;
}
/**
* Get matching layout templates info.
*
* @param array $query_params Query params.
*/
private function get_matching_layout_templates_info( array $query_params = array() ): array {
$area_to_match = isset( $query_params['area'] ) ? $query_params['area'] : null;
$id_to_match = isset( $query_params['id'] ) ? $query_params['id'] : null;
$matching_layout_templates_info = array();
foreach ( $this->layout_templates_info as $layout_template_info ) {
if ( ! empty( $area_to_match ) && $layout_template_info['area'] !== $area_to_match ) {
continue;
}
if ( ! empty( $id_to_match ) && $layout_template_info['id'] !== $id_to_match ) {
continue;
}
$matching_layout_templates_info[] = $layout_template_info;
}
return $matching_layout_templates_info;
}
}

View File

@ -0,0 +1,108 @@
<?php
use Automattic\WooCommerce\LayoutTemplates\LayoutTemplateRegistry;
use Automattic\WooCommerce\Internal\Admin\Features\ProductBlockEditor\ProductTemplates\SimpleProductTemplate;
use Automattic\WooCommerce\Internal\Admin\Features\ProductBlockEditor\ProductTemplates\ProductVariationTemplate;
use Automattic\WooCommerce\Tests\LayoutTemplates\TestLayoutTemplate;
/**
* class WC_REST_Layout_Templates_Controller_Tests.
* Layout Templates Controller tests for V3 REST API.
*/
class WC_REST_Layout_Templates_Controller_Tests extends WC_REST_Unit_Test_Case {
/**
* Runs before each test.
*/
public function setUp(): void {
parent::setUp();
$layout_template_registry = wc_get_container()->get( LayoutTemplateRegistry::class );
$layout_template_registry->unregister_all();
$layout_template_registry->register( 'test-layout-template', 'test', TestLayoutTemplate::class );
$layout_template_registry->register( 'simple-product', 'product-form', SimpleProductTemplate::class );
$layout_template_registry->register( 'product-variation', 'product-form', ProductVariationTemplate::class );
}
/**
* Test getting all layout templates.
*/
public function test_get_all_items() {
$response = $this->do_rest_get_request( 'layout-templates' );
$this->assertEquals( 200, $response->get_status() );
$data = $response->get_data();
$this->assertNotEmpty( $data );
$this->assertCount( 3, $data );
$this->assertArrayHasKey( 'test-layout-template', $data );
$this->assertArrayHasKey( 'simple-product', $data );
$this->assertArrayHasKey( 'product-variation', $data );
}
/**
* Test getting all layout templates for a specific area.
*/
public function test_get_all_items_for_area() {
$response = $this->do_rest_get_request( 'layout-templates', array( 'area' => 'product-form' ) );
$this->assertEquals( 200, $response->get_status() );
$data = $response->get_data();
$this->assertNotEmpty( $data );
$this->assertCount( 2, $data );
$this->assertArrayHasKey( 'simple-product', $data );
$this->assertArrayHasKey( 'product-variation', $data );
}
/**
* Test getting all layout templates for an invalid area.
*/
public function test_get_all_items_for_invalid_area() {
$response = $this->do_rest_get_request( 'layout-templates', array( 'area' => 'invalid-area' ) );
$this->assertEquals( 200, $response->get_status() );
$data = $response->get_data();
$this->assertEmpty( $data );
}
/**
* Test getting a single layout template.
*/
public function test_get_single_item() {
$response = $this->do_rest_get_request( 'layout-templates/test-layout-template' );
$this->assertEquals( 200, $response->get_status() );
$data = $response->get_data();
$this->assertNotEmpty( $data );
$this->assertEquals( 'test-layout-template', $data['id'] );
$this->assertEquals( 'test', $data['area'] );
$this->assertArrayHasKey( 'title', $data );
$this->assertArrayHasKey( 'description', $data );
$this->assertArrayHasKey( 'blockTemplates', $data );
}
/**
* Test getting a single layout template with invalid id.
*/
public function test_get_single_item_with_invalid_id() {
$response = $this->do_rest_get_request( 'layout-templates/invalid-layout-template' );
$this->assertEquals( 404, $response->get_status() );
}
}

View File

@ -0,0 +1,240 @@
<?php
namespace Automattic\WooCommerce\Tests\LayoutTemplates;
use Automattic\WooCommerce\LayoutTemplates\LayoutTemplateRegistry;
use Automattic\WooCommerce\Internal\Admin\Features\ProductBlockEditor\ProductTemplates\SimpleProductTemplate;
use Automattic\WooCommerce\Internal\Admin\Features\ProductBlockEditor\ProductTemplates\ProductVariationTemplate;
use WC_Unit_Test_Case;
/**
* Tests for the LayoutTemplateRegistry class.
*/
class LayoutTemplateRegistryTest extends WC_Unit_Test_Case {
/**
* Layout template registry.
*
* @var LayoutTemplateRegistry
*/
protected $layout_template_registry;
/**
* Layout templates to register.
*
* @var array
*/
protected $layout_templates_to_register;
/**
* Runs before each test.
*/
public function setUp(): void {
$this->layout_template_registry = new LayoutTemplateRegistry();
$this->layout_templates_to_register = array(
'test-layout-template' => array(
'area' => 'test',
'class_name' => TestLayoutTemplate::class,
),
'simple-product' => array(
'area' => 'product-form',
'class_name' => SimpleProductTemplate::class,
),
'product-variation' => array(
'area' => 'product-form',
'class_name' => ProductVariationTemplate::class,
),
);
}
/**
* Test registering a layout template.
*/
public function test_register() {
$this->assertFalse( $this->layout_template_registry->is_registered( 'test-layout-template' ) );
$this->layout_template_registry->register( 'test-layout-template', 'test', TestLayoutTemplate::class );
$this->assertTrue( $this->layout_template_registry->is_registered( 'test-layout-template' ) );
}
/**
* Test registering a layout template with an existing ID.
*/
public function test_register_duplicate_id() {
$this->expectException( \ValueError::class );
$this->layout_template_registry->register( 'test-layout-template', 'test', TestLayoutTemplate::class );
$this->layout_template_registry->register( 'test-layout-template', 'test', TestLayoutTemplate::class );
}
/**
* Test registering a layout template with an empty area.
*/
public function test_register_empty_area() {
$this->expectException( \ValueError::class );
$this->layout_template_registry->register( 'test-layout-template', '', TestLayoutTemplate::class );
}
/**
* Test registering a layout template with a non-existing class.
*/
public function test_register_non_existing_class() {
$this->expectException( \ValueError::class );
$this->layout_template_registry->register( 'test-layout-template', 'test', 'NonExistingClass' );
}
/**
* Test registering a layout template with a class that does not implement the BlockTemplateInterface.
*/
public function test_register_non_block_template_class() {
$this->expectException( \ValueError::class );
$this->layout_template_registry->register( 'test-layout-template', 'test', \stdClass::class );
}
/**
* Test unregistering a layout template.
*/
public function test_unregister() {
$this->layout_template_registry->register( 'test-layout-template', 'test', TestLayoutTemplate::class );
$this->assertTrue( $this->layout_template_registry->is_registered( 'test-layout-template' ) );
$this->layout_template_registry->unregister_all( 'test-layout-template' );
$this->assertFalse( $this->layout_template_registry->is_registered( 'test-layout-template' ) );
}
/**
* Test instantiating layout templates.
*/
public function test_instantiate() {
foreach ( $this->layout_templates_to_register as $template_id => $template_info ) {
$this->layout_template_registry->register( $template_id, $template_info['area'], $template_info['class_name'] );
}
$layout_templates = $this->layout_template_registry->instantiate_layout_templates();
$this->assertCount( 3, $layout_templates );
foreach ( $layout_templates as $layout_template ) {
$template_info = $this->layout_templates_to_register[ $layout_template->get_id() ];
$this->assertInstanceOf( $template_info['class_name'], $layout_template );
}
}
/**
* Test instantiating layout templates with area query param.
*/
public function test_instantiate_with_area_query_param() {
foreach ( $this->layout_templates_to_register as $template_id => $template_info ) {
$this->layout_template_registry->register( $template_id, $template_info['area'], $template_info['class_name'] );
}
$layout_templates = $this->layout_template_registry->instantiate_layout_templates(
array( 'area' => 'product-form' )
);
$this->assertCount( 2, $layout_templates );
foreach ( $layout_templates as $layout_template ) {
$template_info = $this->layout_templates_to_register[ $layout_template->get_id() ];
$this->assertInstanceOf( $template_info['class_name'], $layout_template );
}
}
/**
* Test instantiating layout templates with id query param.
*/
public function test_instantiate_with_id_query_param() {
foreach ( $this->layout_templates_to_register as $template_id => $template_info ) {
$this->layout_template_registry->register( $template_id, $template_info['area'], $template_info['class_name'] );
}
$layout_templates = $this->layout_template_registry->instantiate_layout_templates(
array( 'id' => 'simple-product' )
);
$this->assertCount( 1, $layout_templates );
foreach ( $layout_templates as $layout_template ) {
$template_info = $this->layout_templates_to_register[ $layout_template->get_id() ];
$this->assertInstanceOf( $template_info['class_name'], $layout_template );
}
}
/**
* Test layout templates are only instantiated once.
*/
public function test_cached_instances() {
$this->layout_template_registry->register( 'test-layout-template', 'test', TestLayoutTemplate::class );
$layout_templates = $this->layout_template_registry->instantiate_layout_templates(
array( 'id' => 'test-layout-template' )
);
$layout_templates_again = $this->layout_template_registry->instantiate_layout_templates(
array( 'id' => 'test-layout-template' )
);
$this->assertCount( 1, $layout_templates );
$this->assertCount( 1, $layout_templates_again );
$this->assertSame( current( $layout_templates_again ), current( $layout_templates ) );
}
/**
* Test layout template instantiation actions are fired.
*/
public function test_instantiation_actions() {
$after_instantiation_hook_called = false;
$after_instantiation_hook = function( string $layout_template_id, string $area, $layout_template ) use ( &$after_instantiation_hook_called ) {
$after_instantiation_hook_called = true;
$this->assertEquals( 'test-layout-template', $layout_template_id );
$this->assertEquals( 'test', $area );
$this->assertInstanceOf( TestLayoutTemplate::class, $layout_template );
};
$deprecated_register_hook_called = false;
$deprecated_register_hook = function( $layout_template ) use ( &$deprecated_register_hook_called ) {
$deprecated_register_hook_called = true;
$this->assertInstanceOf( TestLayoutTemplate::class, $layout_template );
$this->assertEquals( 'test-layout-template', $layout_template->get_id() );
$this->assertEquals( 'test', $layout_template->get_area() );
};
try {
add_action( 'woocommerce_layout_template_after_instantiation', $after_instantiation_hook, 10, 3 );
add_action( 'woocommerce_block_template_register', $deprecated_register_hook );
$this->layout_template_registry->register( 'test-layout-template', 'test', TestLayoutTemplate::class );
$this->layout_template_registry->instantiate_layout_templates(
array( 'id' => 'test-layout-template' )
);
$this->assertTrue(
$after_instantiation_hook_called,
'woocommerce_layout_template_after_instantiation hook was not called.'
);
$this->assertTrue(
$deprecated_register_hook_called,
'woocommerce_block_template_register hook was not called.'
);
} finally {
remove_action( 'woocommerce_layout_template_after_instantiation', $after_instantiation_hook );
remove_action( 'woocommerce_block_template_register', $deprecated_register_hook );
}
}
}

View File

@ -0,0 +1,98 @@
<?php
namespace Automattic\WooCommerce\Tests\LayoutTemplates;
use Automattic\WooCommerce\Admin\BlockTemplates\BlockInterface;
use Automattic\WooCommerce\Admin\BlockTemplates\BlockTemplateInterface;
/**
* Test layout template.
*/
class TestLayoutTemplate implements BlockTemplateInterface {
/**
* Get the layout template ID.
*/
public function get_id(): string {
return 'test-layout-template';
}
/**
* Get the layout template title.
*/
public function get_title(): string {
return 'Test layout template';
}
/**
* Get the layout template description.
*/
public function get_description(): string {
return 'A test layout template';
}
/**
* Get the layout template area.
*/
public function get_area(): string {
return 'test';
}
/**
* Get the layout template blocks.
*
* @param string $id_base Block ID base.
*/
public function generate_block_id( string $id_base ): string {
return $id_base . '-test';
}
/**
* Get the layout template blocks.
*/
public function &get_root_template(): BlockTemplateInterface {
return $this;
}
/**
* Get the layout template blocks.
*
* @param string $block_id Block ID.
*/
public function get_block( string $block_id ): ?BlockInterface {
return null;
}
/**
* Get the layout template blocks.
*
* @param string $block_id Block ID.
*/
public function remove_block( string $block_id ) {
}
/**
* Get the layout template blocks.
*/
public function remove_blocks() {
}
/**
* Get the layout template blocks.
*/
public function get_formatted_template(): array {
return array();
}
/**
* Get the layout template blocks.
*/
public function to_json(): array {
return array(
'id' => $this->get_id(),
'title' => $this->get_title(),
'description' => $this->get_description(),
'area' => $this->get_area(),
'blockTemplates' => array(),
);
}
}