Blocks: Introduce `WP_Block_Type` and `WP_Block_Type_Registry` classes.
These are the foundational classes allowing blocks to be registered and used throughout WordPress. This commit also includes the `has_block()` and `has_blocks()` functions, which are required for unit testing these classes. Merges [43742] from the 5.0 branch to trunk. Props adamsilverstein, danielbachhuber, desrosj. Fixes #45097. See #45109. Built from https://develop.svn.wordpress.org/trunk@44108 git-svn-id: http://core.svn.wordpress.org/trunk@43938 1a063a9b-81f0-0310-95a4-ce76da25c4cd
This commit is contained in:
parent
6cbb6f9bd2
commit
2d3f734847
|
@ -0,0 +1,61 @@
|
|||
<?php
|
||||
/**
|
||||
* Functions related to registering and parsing blocks.
|
||||
*
|
||||
* @package WordPress
|
||||
* @subpackage Blocks
|
||||
* @since 5.0.0
|
||||
*/
|
||||
|
||||
/**
|
||||
* Determine whether a post or content string has blocks.
|
||||
*
|
||||
* This test optimizes for performance rather than strict accuracy, detecting
|
||||
* the pattern of a block but not validating its structure. For strict accuracy,
|
||||
* you should use the block parser on post content.
|
||||
*
|
||||
* @since 5.0.0
|
||||
* @see parse_blocks()
|
||||
*
|
||||
* @param int|string|WP_Post|null $post Optional. Post content, post ID, or post object. Defaults to global $post.
|
||||
* @return bool Whether the post has blocks.
|
||||
*/
|
||||
function has_blocks( $post = null ) {
|
||||
if ( ! is_string( $post ) ) {
|
||||
$wp_post = get_post( $post );
|
||||
if ( $wp_post instanceof WP_Post ) {
|
||||
$post = $wp_post->post_content;
|
||||
}
|
||||
}
|
||||
|
||||
return false !== strpos( (string) $post, '<!-- wp:' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether a $post or a string contains a specific block type.
|
||||
*
|
||||
* This test optimizes for performance rather than strict accuracy, detecting
|
||||
* the block type exists but not validating its structure. For strict accuracy,
|
||||
* you should use the block parser on post content.
|
||||
*
|
||||
* @since 5.0.0
|
||||
* @see parse_blocks()
|
||||
*
|
||||
* @param string $block_type Full Block type to look for.
|
||||
* @param int|string|WP_Post|null $post Optional. Post content, post ID, or post object. Defaults to global $post.
|
||||
* @return bool Whether the post content contains the specified block.
|
||||
*/
|
||||
function has_block( $block_type, $post = null ) {
|
||||
if ( ! has_blocks( $post ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( ! is_string( $post ) ) {
|
||||
$wp_post = get_post( $post );
|
||||
if ( $wp_post instanceof WP_Post ) {
|
||||
$post = $wp_post->post_content;
|
||||
}
|
||||
}
|
||||
|
||||
return false !== strpos( $post, '<!-- wp:' . $block_type . ' ' );
|
||||
}
|
|
@ -0,0 +1,173 @@
|
|||
<?php
|
||||
/**
|
||||
* Blocks API: WP_Block_Type_Registry class
|
||||
*
|
||||
* @package WordPress
|
||||
* @subpackage Blocks
|
||||
* @since 5.0.0
|
||||
*/
|
||||
|
||||
/**
|
||||
* Core class used for interacting with block types.
|
||||
*
|
||||
* @since 5.0.0
|
||||
*/
|
||||
final class WP_Block_Type_Registry {
|
||||
/**
|
||||
* Registered block types, as `$name => $instance` pairs.
|
||||
*
|
||||
* @since 5.0.0
|
||||
* @var WP_Block_Type[]
|
||||
*/
|
||||
private $registered_block_types = array();
|
||||
|
||||
/**
|
||||
* Container for the main instance of the class.
|
||||
*
|
||||
* @since 5.0.0
|
||||
* @var WP_Block_Type_Registry|null
|
||||
*/
|
||||
private static $instance = null;
|
||||
|
||||
/**
|
||||
* Registers a block type.
|
||||
*
|
||||
* @since 5.0.0
|
||||
*
|
||||
* @param string|WP_Block_Type $name Block type name including namespace, or alternatively a
|
||||
* complete WP_Block_Type instance. In case a WP_Block_Type
|
||||
* is provided, the $args parameter will be ignored.
|
||||
* @param array $args {
|
||||
* Optional. Array of block type arguments. Any arguments may be defined, however the
|
||||
* ones described below are supported by default. Default empty array.
|
||||
*
|
||||
* @type callable $render_callback Callback used to render blocks of this block type.
|
||||
* @type array $attributes Block attributes mapping, property name to schema.
|
||||
* }
|
||||
* @return WP_Block_Type|false The registered block type on success, or false on failure.
|
||||
*/
|
||||
public function register( $name, $args = array() ) {
|
||||
$block_type = null;
|
||||
if ( $name instanceof WP_Block_Type ) {
|
||||
$block_type = $name;
|
||||
$name = $block_type->name;
|
||||
}
|
||||
|
||||
if ( ! is_string( $name ) ) {
|
||||
$message = __( 'Block type names must be strings.' );
|
||||
_doing_it_wrong( __METHOD__, $message, '5.0.0' );
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( preg_match( '/[A-Z]+/', $name ) ) {
|
||||
$message = __( 'Block type names must not contain uppercase characters.' );
|
||||
_doing_it_wrong( __METHOD__, $message, '5.0.0' );
|
||||
return false;
|
||||
}
|
||||
|
||||
$name_matcher = '/^[a-z0-9-]+\/[a-z0-9-]+$/';
|
||||
if ( ! preg_match( $name_matcher, $name ) ) {
|
||||
$message = __( 'Block type names must contain a namespace prefix. Example: my-plugin/my-custom-block-type' );
|
||||
_doing_it_wrong( __METHOD__, $message, '5.0.0' );
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( $this->is_registered( $name ) ) {
|
||||
/* translators: %s: block name */
|
||||
$message = sprintf( __( 'Block type "%s" is already registered.' ), $name );
|
||||
_doing_it_wrong( __METHOD__, $message, '5.0.0' );
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( ! $block_type ) {
|
||||
$block_type = new WP_Block_Type( $name, $args );
|
||||
}
|
||||
|
||||
$this->registered_block_types[ $name ] = $block_type;
|
||||
|
||||
return $block_type;
|
||||
}
|
||||
|
||||
/**
|
||||
* Unregisters a block type.
|
||||
*
|
||||
* @since 5.0.0
|
||||
*
|
||||
* @param string|WP_Block_Type $name Block type name including namespace, or alternatively a
|
||||
* complete WP_Block_Type instance.
|
||||
* @return WP_Block_Type|false The unregistered block type on success, or false on failure.
|
||||
*/
|
||||
public function unregister( $name ) {
|
||||
if ( $name instanceof WP_Block_Type ) {
|
||||
$name = $name->name;
|
||||
}
|
||||
|
||||
if ( ! $this->is_registered( $name ) ) {
|
||||
/* translators: %s: block name */
|
||||
$message = sprintf( __( 'Block type "%s" is not registered.' ), $name );
|
||||
_doing_it_wrong( __METHOD__, $message, '5.0.0' );
|
||||
return false;
|
||||
}
|
||||
|
||||
$unregistered_block_type = $this->registered_block_types[ $name ];
|
||||
unset( $this->registered_block_types[ $name ] );
|
||||
|
||||
return $unregistered_block_type;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves a registered block type.
|
||||
*
|
||||
* @since 5.0.0
|
||||
*
|
||||
* @param string $name Block type name including namespace.
|
||||
* @return WP_Block_Type|null The registered block type, or null if it is not registered.
|
||||
*/
|
||||
public function get_registered( $name ) {
|
||||
if ( ! $this->is_registered( $name ) ) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $this->registered_block_types[ $name ];
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves all registered block types.
|
||||
*
|
||||
* @since 5.0.0
|
||||
*
|
||||
* @return WP_Block_Type[] Associative array of `$block_type_name => $block_type` pairs.
|
||||
*/
|
||||
public function get_all_registered() {
|
||||
return $this->registered_block_types;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if a block type is registered.
|
||||
*
|
||||
* @since 5.0.0
|
||||
*
|
||||
* @param string $name Block type name including namespace.
|
||||
* @return bool True if the block type is registered, false otherwise.
|
||||
*/
|
||||
public function is_registered( $name ) {
|
||||
return isset( $this->registered_block_types[ $name ] );
|
||||
}
|
||||
|
||||
/**
|
||||
* Utility method to retrieve the main instance of the class.
|
||||
*
|
||||
* The instance will be created if it does not exist yet.
|
||||
*
|
||||
* @since 5.0.0
|
||||
*
|
||||
* @return WP_Block_Type_Registry The main instance.
|
||||
*/
|
||||
public static function get_instance() {
|
||||
if ( null === self::$instance ) {
|
||||
self::$instance = new self();
|
||||
}
|
||||
|
||||
return self::$instance;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,205 @@
|
|||
<?php
|
||||
/**
|
||||
* Blocks API: WP_Block_Type class
|
||||
*
|
||||
* @package WordPress
|
||||
* @subpackage Blocks
|
||||
* @since 5.0.0
|
||||
*/
|
||||
|
||||
/**
|
||||
* Core class representing a block type.
|
||||
*
|
||||
* @since 5.0.0
|
||||
*
|
||||
* @see register_block_type()
|
||||
*/
|
||||
class WP_Block_Type {
|
||||
/**
|
||||
* Block type key.
|
||||
*
|
||||
* @since 5.0.0
|
||||
* @var string
|
||||
*/
|
||||
public $name;
|
||||
|
||||
/**
|
||||
* Block type render callback.
|
||||
*
|
||||
* @since 5.0.0
|
||||
* @var callable
|
||||
*/
|
||||
public $render_callback;
|
||||
|
||||
/**
|
||||
* Block type attributes property schemas.
|
||||
*
|
||||
* @since 5.0.0
|
||||
* @var array
|
||||
*/
|
||||
public $attributes;
|
||||
|
||||
/**
|
||||
* Block type editor script handle.
|
||||
*
|
||||
* @since 5.0.0
|
||||
* @var string
|
||||
*/
|
||||
public $editor_script;
|
||||
|
||||
/**
|
||||
* Block type front end script handle.
|
||||
*
|
||||
* @since 5.0.0
|
||||
* @var string
|
||||
*/
|
||||
public $script;
|
||||
|
||||
/**
|
||||
* Block type editor style handle.
|
||||
*
|
||||
* @since 5.0.0
|
||||
* @var string
|
||||
*/
|
||||
public $editor_style;
|
||||
|
||||
/**
|
||||
* Block type front end style handle.
|
||||
*
|
||||
* @since 5.0.0
|
||||
* @var string
|
||||
*/
|
||||
public $style;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* Will populate object properties from the provided arguments.
|
||||
*
|
||||
* @since 5.0.0
|
||||
*
|
||||
* @see register_block_type()
|
||||
*
|
||||
* @param string $block_type Block type name including namespace.
|
||||
* @param array|string $args Optional. Array or string of arguments for registering a block type.
|
||||
* Default empty array.
|
||||
*/
|
||||
public function __construct( $block_type, $args = array() ) {
|
||||
$this->name = $block_type;
|
||||
|
||||
$this->set_props( $args );
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders the block type output for given attributes.
|
||||
*
|
||||
* @since 5.0.0
|
||||
*
|
||||
* @param array $attributes Optional. Block attributes. Default empty array.
|
||||
* @param string $content Optional. Block content. Default empty string.
|
||||
* @return string Rendered block type output.
|
||||
*/
|
||||
public function render( $attributes = array(), $content = '' ) {
|
||||
if ( ! $this->is_dynamic() ) {
|
||||
return '';
|
||||
}
|
||||
|
||||
$attributes = $this->prepare_attributes_for_render( $attributes );
|
||||
|
||||
return (string) call_user_func( $this->render_callback, $attributes, $content );
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the block type is dynamic, or false otherwise. A dynamic
|
||||
* block is one which defers its rendering to occur on-demand at runtime.
|
||||
*
|
||||
* @since 5.0.0
|
||||
*
|
||||
* @return boolean Whether block type is dynamic.
|
||||
*/
|
||||
public function is_dynamic() {
|
||||
return is_callable( $this->render_callback );
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates attributes against the current block schema, populating
|
||||
* defaulted and missing values, and omitting unknown attributes.
|
||||
*
|
||||
* @since 5.0.0
|
||||
*
|
||||
* @param array $attributes Original block attributes.
|
||||
* @return array Prepared block attributes.
|
||||
*/
|
||||
public function prepare_attributes_for_render( $attributes ) {
|
||||
if ( ! isset( $this->attributes ) ) {
|
||||
return $attributes;
|
||||
}
|
||||
|
||||
$prepared_attributes = array();
|
||||
|
||||
foreach ( $this->attributes as $attribute_name => $schema ) {
|
||||
$value = null;
|
||||
|
||||
if ( isset( $attributes[ $attribute_name ] ) ) {
|
||||
$is_valid = rest_validate_value_from_schema( $attributes[ $attribute_name ], $schema );
|
||||
if ( ! is_wp_error( $is_valid ) ) {
|
||||
$value = rest_sanitize_value_from_schema( $attributes[ $attribute_name ], $schema );
|
||||
}
|
||||
}
|
||||
|
||||
if ( is_null( $value ) && isset( $schema['default'] ) ) {
|
||||
$value = $schema['default'];
|
||||
}
|
||||
|
||||
$prepared_attributes[ $attribute_name ] = $value;
|
||||
}
|
||||
|
||||
return $prepared_attributes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets block type properties.
|
||||
*
|
||||
* @since 5.0.0
|
||||
*
|
||||
* @param array|string $args Array or string of arguments for registering a block type.
|
||||
*/
|
||||
public function set_props( $args ) {
|
||||
$args = wp_parse_args(
|
||||
$args,
|
||||
array(
|
||||
'render_callback' => null,
|
||||
)
|
||||
);
|
||||
|
||||
$args['name'] = $this->name;
|
||||
|
||||
foreach ( $args as $property_name => $property_value ) {
|
||||
$this->$property_name = $property_value;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all available block attributes including possible layout attribute from Columns block.
|
||||
*
|
||||
* @since 5.0.0
|
||||
*
|
||||
* @return array Array of attributes.
|
||||
*/
|
||||
public function get_attributes() {
|
||||
return is_array( $this->attributes ) ?
|
||||
array_merge(
|
||||
$this->attributes,
|
||||
array(
|
||||
'layout' => array(
|
||||
'type' => 'string',
|
||||
),
|
||||
)
|
||||
) :
|
||||
array(
|
||||
'layout' => array(
|
||||
'type' => 'string',
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
|
@ -13,7 +13,7 @@
|
|||
*
|
||||
* @global string $wp_version
|
||||
*/
|
||||
$wp_version = '5.1-alpha-44107';
|
||||
$wp_version = '5.1-alpha-44108';
|
||||
|
||||
/**
|
||||
* Holds the WordPress DB revision, increments when changes are made to the WordPress DB schema.
|
||||
|
|
|
@ -244,6 +244,9 @@ require( ABSPATH . WPINC . '/rest-api/fields/class-wp-rest-term-meta-fields.php'
|
|||
require( ABSPATH . WPINC . '/rest-api/fields/class-wp-rest-user-meta-fields.php' );
|
||||
require( ABSPATH . WPINC . '/rest-api/search/class-wp-rest-search-handler.php' );
|
||||
require( ABSPATH . WPINC . '/rest-api/search/class-wp-rest-post-search-handler.php' );
|
||||
require( ABSPATH . WPINC . '/class-wp-block-type.php' );
|
||||
require( ABSPATH . WPINC . '/class-wp-block-type-registry.php' );
|
||||
require( ABSPATH . WPINC . '/blocks.php' );
|
||||
|
||||
$GLOBALS['wp_embed'] = new WP_Embed();
|
||||
|
||||
|
|
Loading…
Reference in New Issue