diff --git a/src/wp-includes/blocks.php b/src/wp-includes/blocks.php index 6032159fb9..057648935f 100644 --- a/src/wp-includes/blocks.php +++ b/src/wp-includes/blocks.php @@ -356,3 +356,31 @@ function _restore_wpautop_hook( $content ) { function block_version( $content ) { return has_blocks( $content ) ? 1 : 0; } + +/** + * Registers a new block style. + * + * @since 5.3.0 + * + * @param string $block_name Block type name including namespace. + * @param array $style_properties Array containing the properties of the style name, label, style (name of the stylesheet to be enqueued), inline_style (string containing the CSS to be added). + * + * @return boolean True if the block style was registered with success and false otherwise. + */ +function register_block_style( $block_name, $style_properties ) { + return WP_Block_Styles_Registry::get_instance()->register( $block_name, $style_properties ); +} + +/** + * Unregisters a block style. + * + * @since 5.3.0 + * + * @param string $block_name Block type name including namespace. + * @param array $block_style_name Block style name. + * + * @return boolean True if the block style was unregistered with success and false otherwise. + */ +function unregister_block_style( $block_name, $block_style_name ) { + return WP_Block_Styles_Registry::get_instance()->unregister( $block_name, $block_style_name ); +} diff --git a/src/wp-includes/class-wp-block-styles-registry.php b/src/wp-includes/class-wp-block-styles-registry.php new file mode 100644 index 0000000000..4f4b57ba50 --- /dev/null +++ b/src/wp-includes/class-wp-block-styles-registry.php @@ -0,0 +1,161 @@ + $block_style_name => $block_style_properties` multidimensional arrays. + * + * @since 5.3.0 + * @var array + */ + private $registered_block_styles = array(); + + /** + * Container for the main instance of the class. + * + * @since 5.3.0 + * @var WP_Block_Styles_Registry|null + */ + private static $instance = null; + + /** + * Registers a block style. + * + * @since 5.3.0 + * + * @param string $block_name Block type name including namespace. + * @param array $style_properties Array containing the properties of the style name, label, style (name of the stylesheet to be enqueued), inline_style (string containing the CSS to be added). + * + * @return boolean True if the block style was registered with success and false otherwise. + */ + public function register( $block_name, $style_properties ) { + + if ( ! isset( $block_name ) || ! is_string( $block_name ) ) { + $message = __( 'Block name name must be a string.', 'gutenberg' ); + _doing_it_wrong( __METHOD__, $message, '6.2.0' ); + return false; + } + + if ( ! isset( $style_properties['name'] ) || ! is_string( $style_properties['name'] ) ) { + $message = __( 'Block style name must be a string.', 'gutenberg' ); + _doing_it_wrong( __METHOD__, $message, '6.2.0' ); + return false; + } + + $block_style_name = $style_properties['name']; + + if ( ! isset( $this->registered_block_styles[ $block_name ] ) ) { + $this->registered_block_styles[ $block_name ] = array(); + } + $this->registered_block_styles[ $block_name ][ $block_style_name ] = $style_properties; + + return true; + } + + /** + * Unregisters a block style. + * + * @param string $block_name Block type name including namespace. + * @param array $block_style_name Block style name. + * + * @return boolean True if the block style was unregistered with success and false otherwise. + */ + public function unregister( $block_name, $block_style_name ) { + if ( ! $this->is_registered( $block_name, $block_style_name ) ) { + /* translators: 1: block name, 2: block style name */ + $message = sprintf( __( 'Block "%1$s" does not contain a style named "%2$s.".', 'gutenberg' ), $block_name, $block_style_name ); + _doing_it_wrong( __METHOD__, $message, '6.2.0' ); + return false; + } + + unset( $this->registered_block_styles[ $block_name ][ $block_style_name ] ); + + return true; + } + + /** + * Retrieves an array containing the properties of a registered block style. + * + * @since 5.3.0 + * + * @param string $block_name Block type name including namespace. + * @param array $block_style_name Block style name. + * + * @return array Registered block style properties. + */ + public function get_registered( $block_name, $block_style_name ) { + if ( ! $this->is_registered( $block_name, $block_style_name ) ) { + return null; + } + + return $this->registered_block_styles[ $block_name ][ $block_style_name ]; + } + + /** + * Retrieves all registered block styles. + * + * @since 5.3.0 + * + * @return array Array of arrays containing the registered block styles properties grouped per block, and per style. + */ + public function get_all_registered() { + return $this->registered_block_styles; + } + + /** + * Retrieves registered block styles for a specific block. + * + * @since 5.3.0 + * + * @param string $block_name Block type name including namespace. + * + * @return array Array whose keys are block style names and whose value are block style properties. + */ + public function get_registered_styles_for_block( $block_name ) { + if ( isset( $this->registered_block_styles[ $block_name ] ) ) { + return $this->registered_block_styles[ $block_name ]; + } + return array(); + } + + /** + * Checks if a block style is registered. + * + * @since 5.3.0 + * + * @param string $block_name Block type name including namespace. + * @param array $block_style_name Block style name. + * + * @return bool True if the block style is registered, false otherwise. + */ + public function is_registered( $block_name, $block_style_name ) { + return isset( $this->registered_block_styles[ $block_name ][ $block_style_name ] ); + } + + /** + * Utility method to retrieve the main instance of the class. + * + * The instance will be created if it does not exist yet. + * + * @since 5.3.0 + * + * @return WP_Block_Styles_Registry The main instance. + */ + public static function get_instance() { + if ( null === self::$instance ) { + self::$instance = new self(); + } + + return self::$instance; + } +} diff --git a/src/wp-includes/default-filters.php b/src/wp-includes/default-filters.php index fc0f4408f7..423db4d540 100644 --- a/src/wp-includes/default-filters.php +++ b/src/wp-includes/default-filters.php @@ -501,6 +501,8 @@ add_action( 'admin_print_scripts-index.php', 'wp_localize_community_events' ); add_filter( 'wp_print_scripts', 'wp_just_in_time_script_localization' ); add_filter( 'print_scripts_array', 'wp_prototype_before_jquery' ); add_filter( 'customize_controls_print_styles', 'wp_resource_hints', 1 ); +add_action( 'enqueue_block_assets', 'enqueue_block_styles_assets', 30 ); +add_action( 'enqueue_block_editor_assets', 'enqueue_editor_block_styles_assets' ); add_action( 'wp_default_styles', 'wp_default_styles' ); add_filter( 'style_loader_src', 'wp_style_loader_src', 10, 2 ); diff --git a/src/wp-includes/script-loader.php b/src/wp-includes/script-loader.php index 4ad643008c..5366bfbcd0 100644 --- a/src/wp-includes/script-loader.php +++ b/src/wp-includes/script-loader.php @@ -2780,3 +2780,54 @@ function wp_enqueue_registered_block_scripts_and_styles() { } } } + +/** + * Function responsible for enqueuing the styles required for block styles functionality on the editor and on the frontend. + * + * @since 5.3.0 + */ +function enqueue_block_styles_assets() { + $block_styles = WP_Block_Styles_Registry::get_instance()->get_all_registered(); + + foreach ( $block_styles as $styles ) { + foreach ( $styles as $style_properties ) { + if ( isset( $style_properties['style_handle'] ) ) { + wp_enqueue_style( $style_properties['style_handle'] ); + } + if ( isset( $style_properties['inline_style'] ) ) { + wp_add_inline_style( 'wp-block-library', $style_properties['inline_style'] ); + } + } + } +} + +/** + * Function responsible for enqueuing the assets required for block styles functionality on the editor. + * + * @since 5.3.0 + */ +function enqueue_editor_block_styles_assets() { + $block_styles = WP_Block_Styles_Registry::get_instance()->get_all_registered(); + + $register_script_lines = array( '( function() {' ); + foreach ( $block_styles as $block_name => $styles ) { + foreach ( $styles as $style_properties ) { + $register_script_lines[] = sprintf( + ' wp.blocks.registerBlockStyle( \'%s\', %s );', + $block_name, + wp_json_encode( + array( + 'name' => $style_properties['name'], + 'label' => $style_properties['label'], + ) + ) + ); + } + } + $register_script_lines[] = '} )();'; + $inline_script = implode( "\n", $register_script_lines ); + + wp_register_script( 'wp-block-styles', false, array( 'wp-blocks' ), true, true ); + wp_add_inline_script( 'wp-block-styles', $inline_script ); + wp_enqueue_script( 'wp-block-styles' ); +} diff --git a/src/wp-settings.php b/src/wp-settings.php index 681053a0d4..5822ebde5b 100644 --- a/src/wp-settings.php +++ b/src/wp-settings.php @@ -256,6 +256,7 @@ 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-styles-registry.php' ); require( ABSPATH . WPINC . '/class-wp-block-type-registry.php' ); require( ABSPATH . WPINC . '/class-wp-block-parser.php' ); require( ABSPATH . WPINC . '/blocks.php' );