Skip to content

Commit

Permalink
Blocks: Introduce WP_Block_Type and WP_Block_Type_Registry classes.
Browse files Browse the repository at this point in the history
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
  • Loading branch information
pento committed Dec 13, 2018
1 parent 6cbb6f9 commit 2d3f734
Show file tree
Hide file tree
Showing 5 changed files with 443 additions and 1 deletion.
61 changes: 61 additions & 0 deletions wp-includes/blocks.php
@@ -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 . ' ' );
}
173 changes: 173 additions & 0 deletions wp-includes/class-wp-block-type-registry.php
@@ -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 comments on commit 2d3f734

Please sign in to comment.