Skip to content

Commit

Permalink
Introduce proper PHP classes for interacting with block types (#1322)
Browse files Browse the repository at this point in the history
  • Loading branch information
felixarntz authored and nylen committed Jul 26, 2017
1 parent 2314faa commit ae91fca
Show file tree
Hide file tree
Showing 11 changed files with 571 additions and 143 deletions.
2 changes: 2 additions & 0 deletions gutenberg.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@
require_once dirname( __FILE__ ) . '/lib/init-checks.php';
if ( gutenberg_can_init() ) {
// Load API functions, register scripts and actions, etc.
require_once dirname( __FILE__ ) . '/lib/class-wp-block-type.php';
require_once dirname( __FILE__ ) . '/lib/class-wp-block-type-registry.php';
require_once dirname( __FILE__ ) . '/lib/blocks.php';
require_once dirname( __FILE__ ) . '/lib/client-assets.php';
require_once dirname( __FILE__ ) . '/lib/compat.php';
Expand Down
95 changes: 34 additions & 61 deletions lib/blocks.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,64 +9,39 @@
die( 'Silence is golden.' );
}

$wp_registered_blocks = array();

/**
* Registers a block.
* Registers a block type.
*
* @param string $name Block name including namespace.
* @param array $settings Block settings.
* @return array The block, if it has been successfully registered.
* @since 0.1.0
* @since 0.6.0 Now also accepts a WP_Block_Type instance as first parameter.
*
* @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.
* }
* @return WP_Block_Type|false The registered block type on success, or false on failure.
*/
function register_block_type( $name, $settings ) {
global $wp_registered_blocks;

if ( ! is_string( $name ) ) {
$message = __( 'Block names must be strings.', 'gutenberg' );
_doing_it_wrong( __FUNCTION__, $message, '0.1.0' );
return false;
}

$name_matcher = '/^[a-z0-9-]+\/[a-z0-9-]+$/';
if ( ! preg_match( $name_matcher, $name ) ) {
$message = __( 'Block names must contain a namespace prefix. Example: my-plugin/my-custom-block', 'gutenberg' );
_doing_it_wrong( __FUNCTION__, $message, '0.1.0' );
return false;
}

if ( isset( $wp_registered_blocks[ $name ] ) ) {
/* translators: 1: block name */
$message = sprintf( __( 'Block "%s" is already registered.', 'gutenberg' ), $name );
_doing_it_wrong( __FUNCTION__, $message, '0.1.0' );
return false;
}

$settings['name'] = $name;
$wp_registered_blocks[ $name ] = $settings;

return $settings;
function register_block_type( $name, $args = array() ) {
return WP_Block_Type_Registry::get_instance()->register( $name, $args );
}

/**
* Unregisters a block.
* Unregisters a block type.
*
* @param string $name Block name.
* @return array The previous block value, if it has been
* successfully unregistered; otherwise `null`.
* @since 0.1.0
* @since 0.6.0 Now also accepts a WP_Block_Type instance as first parameter.
*
* @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.
*/
function unregister_block_type( $name ) {
global $wp_registered_blocks;
if ( ! isset( $wp_registered_blocks[ $name ] ) ) {
/* translators: 1: block name */
$message = sprintf( __( 'Block "%s" is not registered.', 'gutenberg' ), $name );
_doing_it_wrong( __FUNCTION__, $message, '0.1.0' );
return false;
}
$unregistered_block = $wp_registered_blocks[ $name ];
unset( $wp_registered_blocks[ $name ] );

return $unregistered_block;
return WP_Block_Type_Registry::get_instance()->unregister( $name );
}

/**
Expand All @@ -91,7 +66,7 @@ function gutenberg_parse_blocks( $content ) {
* @return string Updated post content.
*/
function do_blocks( $content ) {
global $wp_registered_blocks;
$registry = WP_Block_Type_Registry::get_instance();

$blocks = gutenberg_parse_blocks( $content );

Expand All @@ -100,20 +75,18 @@ function do_blocks( $content ) {
foreach ( $blocks as $block ) {
$block_name = isset( $block['blockName'] ) ? $block['blockName'] : null;
$attributes = is_array( $block['attrs'] ) ? $block['attrs'] : array();
if ( $block_name && isset( $wp_registered_blocks[ $block_name ] ) ) {
$raw_content = isset( $block['rawContent'] ) ? $block['rawContent'] : null;

$content = null;
if ( isset( $block['rawContent'] ) ) {
$content = $block['rawContent'];
if ( $block_name ) {
$block_type = $registry->get_registered( $block_name );
if ( null !== $block_type ) {
$content_after_blocks .= $block_type->render( $attributes, $raw_content );
continue;
}
}

$content_after_blocks .= call_user_func(
$wp_registered_blocks[ $block_name ]['render'],
$attributes,
$content
);
} else {
$content_after_blocks .= $block['rawContent'];
if ( $raw_content ) {
$content_after_blocks .= $raw_content;
}
}

Expand Down
2 changes: 1 addition & 1 deletion lib/blocks/latest-posts.php
Original file line number Diff line number Diff line change
Expand Up @@ -85,5 +85,5 @@ function gutenberg_render_block_core_latest_posts( $attributes ) {
}

register_block_type( 'core/latest-posts', array(
'render' => 'gutenberg_render_block_core_latest_posts',
'render_callback' => 'gutenberg_render_block_core_latest_posts',
) );
175 changes: 175 additions & 0 deletions lib/class-wp-block-type-registry.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,175 @@
<?php
/**
* Blocks API: WP_Block_Type_Registry class
*
* @package gutenberg
* @since 0.6.0
*/

/**
* Core class used for interacting with block types.
*
* @since 0.6.0
*/
final class WP_Block_Type_Registry {
/**
* Registered block types, as `$name => $instance` pairs.
*
* @since 0.6.0
* @access private
* @var array
*/
private $registered_block_types = array();

/**
* Container for the main instance of the class.
*
* @since 0.6.0
* @access private
* @static
* @var WP_Block_Type_Registry|null
*/
private static $instance = null;

/**
* Registers a block type.
*
* @since 0.6.0
* @access public
*
* @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.
* }
* @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 ( is_a( $name, 'WP_Block_Type' ) ) {
$block_type = $name;
$name = $block_type->name;
}

if ( ! is_string( $name ) ) {
$message = __( 'Block type names must be strings.', 'gutenberg' );
_doing_it_wrong( __METHOD__, $message, '0.1.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', 'gutenberg' );
_doing_it_wrong( __METHOD__, $message, '0.1.0' );
return false;
}

if ( $this->is_registered( $name ) ) {
/* translators: 1: block name */
$message = sprintf( __( 'Block type "%s" is already registered.', 'gutenberg' ), $name );
_doing_it_wrong( __METHOD__, $message, '0.1.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 0.6.0
* @access public
*
* @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 ( is_a( $name, 'WP_Block_Type' ) ) {
$name = $name->name;
}

if ( ! $this->is_registered( $name ) ) {
/* translators: 1: block name */
$message = sprintf( __( 'Block type "%s" is not registered.', 'gutenberg' ), $name );
_doing_it_wrong( __METHOD__, $message, '0.1.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 0.6.0
* @access public
*
* @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 0.6.0
* @access public
*
* @return array 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 0.6.0
* @access public
*
* @param tring $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 0.6.0
* @access public
* @static
*
* @return WP_Block_Type_Registry The main instance.
*/
public static function get_instance() {
if ( null === self::$instance ) {
self::$instance = new self();
}

return self::$instance;
}
}
Loading

0 comments on commit ae91fca

Please sign in to comment.