mirror of
https://github.com/gosticks/wordpress-develop.git
synced 2025-10-16 12:05:38 +00:00
Editor: Support deferred block variation initialization on the server.
When registering blocks on the server using `register_block_type()` or similar functions, a set of block type variations can also be registered. However, in some cases building this variation data during block registration can be an expensive process, which is not needed in most contexts. To address this problem, this adds support to the `WP_Block_Type` object for a new property, `variation_callback`, which can be used to register a callback for building variation data only when the block variations data is needed. The `WP_Block_Type::variations` property has been changed to a private property that is now accessed through the magic `__get()` method. The magic getter makes use of a new public method, `WP_Block_Type::get_variations` which will build variations from a registered callback if variations have not already been built. Props spacedmonkey, thekt12, Mamaduka, gaambo, gziolo, mukesh27, joemcgill. Fixes #59969. git-svn-id: https://develop.svn.wordpress.org/trunk@57315 602fd350-edb4-49c9-b593-d223f7449a82
This commit is contained in:
parent
ecbd1376a6
commit
5815624ead
@ -113,9 +113,18 @@ class WP_Block_Type {
|
||||
* Block variations.
|
||||
*
|
||||
* @since 5.8.0
|
||||
* @var array[]
|
||||
* @since 6.5.0 Only accessible through magic getter. null by default.
|
||||
* @var array[]|null
|
||||
*/
|
||||
public $variations = array();
|
||||
private $variations = null;
|
||||
|
||||
/**
|
||||
* Block variations callback.
|
||||
*
|
||||
* @since 6.5.0
|
||||
* @var callable|null
|
||||
*/
|
||||
public $variation_callback = null;
|
||||
|
||||
/**
|
||||
* Custom CSS selectors for theme.json style generation.
|
||||
@ -296,6 +305,7 @@ class WP_Block_Type {
|
||||
* @type array|null $supports Supported features.
|
||||
* @type array|null $example Structured data for the block preview.
|
||||
* @type callable|null $render_callback Block type render callback.
|
||||
* @type callable|null $variation_callback Block type variations callback.
|
||||
* @type array|null $attributes Block type attributes property schemas.
|
||||
* @type string[] $uses_context Context values inherited by blocks of this type.
|
||||
* @type string[]|null $provides_context Context provided by blocks of this type.
|
||||
@ -325,6 +335,10 @@ class WP_Block_Type {
|
||||
* null when value not found, or void when unknown property name provided.
|
||||
*/
|
||||
public function __get( $name ) {
|
||||
if ( 'variations' === $name ) {
|
||||
return $this->get_variations();
|
||||
}
|
||||
|
||||
if ( ! in_array( $name, $this->deprecated_properties, true ) ) {
|
||||
return;
|
||||
}
|
||||
@ -353,6 +367,10 @@ class WP_Block_Type {
|
||||
* or false otherwise.
|
||||
*/
|
||||
public function __isset( $name ) {
|
||||
if ( 'variations' === $name ) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if ( ! in_array( $name, $this->deprecated_properties, true ) ) {
|
||||
return false;
|
||||
}
|
||||
@ -372,6 +390,11 @@ class WP_Block_Type {
|
||||
* @param mixed $value Property value.
|
||||
*/
|
||||
public function __set( $name, $value ) {
|
||||
if ( 'variations' === $name ) {
|
||||
$this->variations = $value;
|
||||
return;
|
||||
}
|
||||
|
||||
if ( ! in_array( $name, $this->deprecated_properties, true ) ) {
|
||||
$this->{$name} = $value;
|
||||
return;
|
||||
@ -540,4 +563,30 @@ class WP_Block_Type {
|
||||
$this->attributes :
|
||||
array();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get block variations.
|
||||
*
|
||||
* @since 6.5.0
|
||||
*
|
||||
* @return array[]
|
||||
*/
|
||||
public function get_variations() {
|
||||
if ( ! isset( $this->variations ) ) {
|
||||
$this->variations = array();
|
||||
if ( is_callable( $this->variation_callback ) ) {
|
||||
$this->variations = call_user_func( $this->variation_callback );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Filters the registered variations for a block type.
|
||||
*
|
||||
* @since 6.5.0
|
||||
*
|
||||
* @param array $variations Array of registered variations for a block type.
|
||||
* @param WP_Block_Type $block_type The full block type object.
|
||||
*/
|
||||
return apply_filters( 'get_block_type_variations', $this->variations, $this );
|
||||
}
|
||||
}
|
||||
|
||||
@ -460,4 +460,196 @@ class Tests_Blocks_wpBlockType extends WP_UnitTestCase {
|
||||
array( '<!- - wp:core/separator -->', 0 ),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @ticket 59969
|
||||
*/
|
||||
public function test_variation_callback() {
|
||||
$block_type = new WP_Block_Type(
|
||||
'test/block',
|
||||
array(
|
||||
'title' => 'Test title',
|
||||
'variation_callback' => array( $this, 'mock_variation_callback' ),
|
||||
)
|
||||
);
|
||||
|
||||
$this->assertSameSets( $this->mock_variation_callback(), $block_type->variations );
|
||||
}
|
||||
|
||||
/**
|
||||
* @ticket 59969
|
||||
* @covers WP_Block_Type::get_variations
|
||||
*/
|
||||
public function test_get_variations() {
|
||||
$block_type = new WP_Block_Type(
|
||||
'test/block',
|
||||
array(
|
||||
'title' => 'Test title',
|
||||
'variation_callback' => array( $this, 'mock_variation_callback' ),
|
||||
)
|
||||
);
|
||||
|
||||
$this->assertSameSets( $this->mock_variation_callback(), $block_type->get_variations() );
|
||||
}
|
||||
|
||||
/**
|
||||
* @ticket 59969
|
||||
*/
|
||||
public function test_variations_precedence_over_callback() {
|
||||
$test_variations = array( 'name' => 'test1' );
|
||||
|
||||
$block_type = new WP_Block_Type(
|
||||
'test/block',
|
||||
array(
|
||||
'title' => 'Test title',
|
||||
'variations' => $test_variations,
|
||||
'variation_callback' => array( $this, 'mock_variation_callback' ),
|
||||
)
|
||||
);
|
||||
|
||||
// If the variations are defined, the callback should not be used.
|
||||
$this->assertSameSets( $test_variations, $block_type->variations );
|
||||
}
|
||||
|
||||
/**
|
||||
* @ticket 59969
|
||||
*/
|
||||
public function test_variations_callback_are_lazy_loaded() {
|
||||
$callback_called = false;
|
||||
|
||||
$block_type = new WP_Block_Type(
|
||||
'test/block',
|
||||
array(
|
||||
'title' => 'Test title',
|
||||
'variation_callback' => function () use ( &$callback_called ) {
|
||||
$callback_called = true;
|
||||
return $this->mock_variation_callback();
|
||||
},
|
||||
)
|
||||
);
|
||||
|
||||
$this->assertSame( false, $callback_called, 'The callback should not be called before the variations are accessed.' );
|
||||
$block_type->variations; // access the variations.
|
||||
$this->assertSame( true, $callback_called, 'The callback should be called when the variations are accessed.' );
|
||||
}
|
||||
|
||||
/**
|
||||
* @ticket 59969
|
||||
* @covers WP_Block_Type::get_variations
|
||||
*/
|
||||
public function test_variations_precedence_over_callback_post_registration() {
|
||||
$test_variations = array( 'name' => 'test1' );
|
||||
$callback_called = false;
|
||||
|
||||
$block_type = new WP_Block_Type(
|
||||
'test/block',
|
||||
array(
|
||||
'title' => 'Test title',
|
||||
'variation_callback' => function () use ( &$callback_called ) {
|
||||
$callback_called = true;
|
||||
return $this->mock_variation_callback();
|
||||
},
|
||||
)
|
||||
);
|
||||
$block_type->variations = $test_variations;
|
||||
|
||||
// If the variations are defined after registration but before first access, the callback should not override it.
|
||||
$this->assertSameSets( $test_variations, $block_type->get_variations(), 'Variations are same as variations set' );
|
||||
$this->assertSame( false, $callback_called, 'The callback was never called.' );
|
||||
}
|
||||
|
||||
/**
|
||||
* @ticket 59969
|
||||
* @covers WP_Block_Type::get_variations
|
||||
*/
|
||||
public function test_variations_callback_happens_only_once() {
|
||||
$callback_count = 0;
|
||||
|
||||
$block_type = new WP_Block_Type(
|
||||
'test/block',
|
||||
array(
|
||||
'title' => 'Test title',
|
||||
'variation_callback' => function () use ( &$callback_count ) {
|
||||
$callback_count++;
|
||||
return $this->mock_variation_callback();
|
||||
},
|
||||
)
|
||||
);
|
||||
|
||||
$this->assertSame( 0, $callback_count, 'The callback should not be called before the variations are accessed.' );
|
||||
$block_type->get_variations(); // access the variations.
|
||||
$this->assertSame( 1, $callback_count, 'The callback should be called when the variations are accessed.' );
|
||||
$block_type->get_variations(); // access the variations again.
|
||||
$this->assertSame( 1, $callback_count, 'The callback should not be called again.' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Test filter function for get_block_type_variations filter.
|
||||
*
|
||||
* @param array $variations Block variations before filter.
|
||||
* @param WP_Block_Type $block_type Block type.
|
||||
*
|
||||
* @return array Block variations after filter.
|
||||
*/
|
||||
public function filter_test_variations( $variations, $block_type ) {
|
||||
return array( array( 'name' => 'test1' ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* @ticket 59969
|
||||
*/
|
||||
public function test_get_block_type_variations_filter_with_variation_callback() {
|
||||
// Filter will override the variations obtained from the callback.
|
||||
add_filter( 'get_block_type_variations', array( $this, 'filter_test_variations' ), 10, 2 );
|
||||
$expected_variations = array( array( 'name' => 'test1' ) );
|
||||
|
||||
$callback_called = false;
|
||||
$block_type = new WP_Block_Type(
|
||||
'test/block',
|
||||
array(
|
||||
'title' => 'Test title',
|
||||
'variation_callback' => function () use ( &$callback_called ) {
|
||||
$callback_called = true;
|
||||
return $this->mock_variation_callback();
|
||||
},
|
||||
)
|
||||
);
|
||||
|
||||
$obtained_variations = $block_type->variations; // access the variations.
|
||||
|
||||
$this->assertSame( true, $callback_called, 'The callback should be called when the variations are accessed.' );
|
||||
$this->assertSameSets( $obtained_variations, $expected_variations, 'The variations obtained from the callback should be filtered.' );
|
||||
}
|
||||
|
||||
/**
|
||||
* @ticket 59969
|
||||
*/
|
||||
public function test_get_block_type_variations_filter_variations() {
|
||||
// Filter will override the variations set during registration.
|
||||
add_filter( 'get_block_type_variations', array( $this, 'filter_test_variations' ), 10, 2 );
|
||||
$expected_variations = array( array( 'name' => 'test1' ) );
|
||||
|
||||
$block_type = new WP_Block_Type(
|
||||
'test/block',
|
||||
array(
|
||||
'title' => 'Test title',
|
||||
'variations' => $this->mock_variation_callback(),
|
||||
)
|
||||
);
|
||||
|
||||
$obtained_variations = $block_type->variations; // access the variations.
|
||||
$this->assertSameSets( $obtained_variations, $expected_variations, 'The variations that was initially set should be filtered.' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Mock variation callback.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function mock_variation_callback() {
|
||||
return array(
|
||||
array( 'name' => 'var1' ),
|
||||
array( 'name' => 'var2' ),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@ -734,6 +734,35 @@ class REST_Block_Type_Controller_Test extends WP_Test_REST_Controller_Testcase {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @ticket 59969
|
||||
*/
|
||||
public function test_variation_callback() {
|
||||
$block_type = 'test/block';
|
||||
$settings = array(
|
||||
'title' => true,
|
||||
'variation_callback' => array( $this, 'mock_variation_callback' ),
|
||||
);
|
||||
register_block_type( $block_type, $settings );
|
||||
wp_set_current_user( self::$admin_id );
|
||||
$request = new WP_REST_Request( 'GET', '/wp/v2/block-types/' . $block_type );
|
||||
$response = rest_get_server()->dispatch( $request );
|
||||
$data = $response->get_data();
|
||||
$this->assertSameSets( $this->mock_variation_callback(), $data['variations'] );
|
||||
}
|
||||
|
||||
/**
|
||||
* Mock variation callback.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function mock_variation_callback() {
|
||||
return array(
|
||||
array( 'name' => 'var1' ),
|
||||
array( 'name' => 'var2' ),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* The create_item() method does not exist for block types.
|
||||
*
|
||||
|
||||
Loading…
Reference in New Issue
Block a user