diff --git a/docs/designers-developers/developers/block-api/block-patterns.md b/docs/designers-developers/developers/block-api/block-patterns.md index 9587628c6b29c..9d06a01cb1098 100644 --- a/docs/designers-developers/developers/block-api/block-patterns.md +++ b/docs/designers-developers/developers/block-api/block-patterns.md @@ -4,15 +4,19 @@ Patterns are predefined block layouts, ready to insert and tweak. **Note** Patterns are still under heavy development and the APIs are subject to change. -#### register_block_pattern +## Patterns Registration + +### register_block_pattern The editor comes with a list of built-in patterns. Theme and plugin authors can register addition custom patterns using the `register_block_pattern` function. The `register_block_pattern` function receives the name of the pattern as the first argument and an array describing properties of the pattern as the second argument. -The properties of the style array must include `name` and `label`: - - `title`: A human-readable title for the pattern. - - `content`: Raw HTML content for the pattern. +The properties of the pattern include: + - `title` (required): A human-readable title for the pattern. + - `content` (required): Raw HTML content for the pattern. + - `categories`: A list of pattern categories used to group patterns. Patterns can be shown on multiple categories. + - `keywords`: Aliases or keywords that help users discover it while searching. ```php register_block_pattern( @@ -24,7 +28,7 @@ register_block_pattern( ); ``` -#### unregister_block_pattern +### unregister_block_pattern `unregister_block_pattern` allows unregistering a pattern previously registered on the server using `register_block_pattern`. @@ -35,3 +39,33 @@ The following code sample unregisters the style named 'my-plugin/my-awesome-patt ```php unregister_block_pattern( 'my-plugin/my-awesome-pattern' ); ``` + +## Pattern Categories + +Patterns can be grouped using categories. The block editor comes with bundled categories you can use on your custom patterns. You can also register your own pattern categories. + +### register_block_pattern_category + +The `register_block_pattern_category` function receives the name of the category as the first argument and an array describing properties of the category as the second argument. + +The properties of the pattern categories include: + - `label` (required): A human-readable label for the pattern category. + +```php +register_block_pattern_category( + 'hero', + array( 'label' => __( 'Hero', 'my-plugin' ) ) +); +``` + +### unregister_block_pattern_category + +`unregister_block_pattern_category` allows unregistering a pattern category. + +The function's argument is the name of the pattern category to unregister. + +The following code sample unregisters the category named 'hero': + +```php +unregister_block_pattern_category( 'hero' ); +``` diff --git a/lib/class-wp-block-pattern-categories-registry.php b/lib/class-wp-block-pattern-categories-registry.php new file mode 100644 index 0000000000000..157f00ae24f56 --- /dev/null +++ b/lib/class-wp-block-pattern-categories-registry.php @@ -0,0 +1,139 @@ +registered_categories[ $category_name ] = array_merge( + array( 'name' => $category_name ), + $category_properties + ); + + return true; + } + + /** + * Unregisters a pattern category. + * + * @param string $category_name Pattern name including namespace. + * @return boolean True if the pattern was unregistered with success and false otherwise. + */ + public function unregister( $category_name ) { + if ( ! $this->is_registered( $category_name ) ) { + /* translators: 1: Block pattern name. */ + $message = sprintf( __( 'Block pattern category "%1$s" not found.', 'gutenberg' ), $category_name ); + _doing_it_wrong( __METHOD__, $message, '8.1.0' ); + return false; + } + + unset( $this->registered_categories[ $category_name ] ); + + return true; + } + + /** + * Retrieves an array containing the properties of a registered pattern category. + * + * @param string $category_name Pattern category name. + * @return array Registered pattern properties. + */ + public function get_registered( $category_name ) { + if ( ! $this->is_registered( $category_name ) ) { + return null; + } + + return $this->registered_categories[ $category_name ]; + } + + /** + * Retrieves all registered pattern categories. + * + * @return array Array of arrays containing the registered pattern categories properties. + */ + public function get_all_registered() { + return array_values( $this->registered_categories ); + } + + /** + * Checks if a pattern category is registered. + * + * @param string $category_name Pattern category name. + * @return bool True if the pattern category is registered, false otherwise. + */ + public function is_registered( $category_name ) { + return isset( $this->registered_categories[ $category_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_Pattern_Categories_Registry The main instance. + */ + public static function get_instance() { + if ( null === self::$instance ) { + self::$instance = new self(); + } + + return self::$instance; + } +} + +/** + * Registers a new pattern category. + * + * @param string $category_name Pattern category name. + * @param array $category_properties Array containing the properties of the category. + * + * @return boolean True if the pattern category was registered with success and false otherwise. + */ +function register_block_pattern_category( $category_name, $category_properties ) { + return WP_Block_Pattern_Categories_Registry::get_instance()->register( $category_name, $category_properties ); +} + +/** + * Unregisters a pattern category. + * + * @param string $category_name Pattern category name including namespace. + * + * @return boolean True if the pattern category was unregistered with success and false otherwise. + */ +function unregister_block_pattern_category( $category_name ) { + return WP_Block_Pattern_Categories_Registry::get_instance()->unregister( $category_name ); +} diff --git a/lib/client-assets.php b/lib/client-assets.php index 5427ee3abfdf3..e53a05a2f64ff 100644 --- a/lib/client-assets.php +++ b/lib/client-assets.php @@ -649,6 +649,15 @@ function gutenberg_extend_settings_block_patterns( $settings ) { $settings['__experimentalBlockPatterns'] ); + if ( empty( $settings['__experimentalBlockPatternCategories'] ) ) { + $settings['__experimentalBlockPatternCategories'] = array(); + } + + $settings['__experimentalBlockPatternCategories'] = array_merge( + WP_Block_Pattern_Categories_Registry::get_instance()->get_all_registered(), + $settings['__experimentalBlockPatternCategories'] + ); + return $settings; } add_filter( 'block_editor_settings', 'gutenberg_extend_settings_block_patterns', 0 ); @@ -695,3 +704,16 @@ function gutenberg_extend_settings_custom_units( $settings ) { register_block_pattern( 'core/hero-right-column', gutenberg_load_block_pattern( 'hero-right-column' ) ); register_block_pattern( 'core/testimonials', gutenberg_load_block_pattern( 'testimonials' ) ); } + +/* + * Register default pattern categories if not registered in Core already. + */ +if ( class_exists( 'WP_Block_Pattern_Categories_Registry' ) ) { + register_block_pattern_category( 'text', array( 'label' => __( 'Text', 'gutenberg' ) ) ); + register_block_pattern_category( 'hero', array( 'label' => __( 'Hero', 'gutenberg' ) ) ); + register_block_pattern_category( 'columns', array( 'label' => __( 'Columns', 'gutenberg' ) ) ); + register_block_pattern_category( 'buttons', array( 'label' => __( 'Buttons', 'gutenberg' ) ) ); + register_block_pattern_category( 'gallery', array( 'label' => __( 'Gallery', 'gutenberg' ) ) ); + register_block_pattern_category( 'features', array( 'label' => __( 'Features', 'gutenberg' ) ) ); + register_block_pattern_category( 'testimonials', array( 'label' => __( 'Testimonials', 'gutenberg' ) ) ); +} diff --git a/lib/load.php b/lib/load.php index e0dbcd56431a8..71f5c0191068b 100644 --- a/lib/load.php +++ b/lib/load.php @@ -63,6 +63,10 @@ function gutenberg_is_experiment_enabled( $name ) { require dirname( __FILE__ ) . '/class-wp-block-patterns-registry.php'; } +if ( ! class_exists( 'WP_Block_Pattern_Categories_Registry' ) ) { + require dirname( __FILE__ ) . '/class-wp-block-pattern-categories-registry.php'; +} + if ( ! class_exists( 'WP_Block' ) ) { require dirname( __FILE__ ) . '/class-wp-block.php'; } diff --git a/lib/patterns/cover-abc.php b/lib/patterns/cover-abc.php index b2a50cadcdd33..c8fc8fa6a7e1c 100644 --- a/lib/patterns/cover-abc.php +++ b/lib/patterns/cover-abc.php @@ -6,6 +6,7 @@ */ return array( - 'title' => __( 'Cover', 'gutenberg' ), - 'content' => "\n
" . _x( 'abc!', 'pattern', 'gutenberg' ) . "
\n" . _x( 'abc!', 'pattern', 'gutenberg' ) . "
\nEasy & Accessible
\nExtend it with over 54,000 plugins to help your website meet your needs. Hundreds of thousands of developers and site owners trust it worldwide. Add an online store, galleries, mailing lists, forums, analytics, and much more.
\n\n\n\nHundreds of thousands of developers and site owners trust it worldwide. Add an online store, galleries, mailing lists, forums, analytics, and much more.
\n\n\n\n\n\n\n\n \nEasy & Accessible
\nExtend it with over 54,000 plugins to help your website meet your needs. Hundreds of thousands of developers and site owners trust it worldwide. Add an online store, galleries, mailing lists, forums, analytics, and much more.
\n\n\n\nHundreds of thousands of developers and site owners trust it worldwide. Add an online store, galleries, mailing lists, forums, analytics, and much more.
\n\n\n\n\n\n\n\n \nEnjoy a wide variety of
\n\n\n\nCustom Designs
\n\n\n\nExtend it with over 54,000 plugins to help your website meet your needs. Add an online store, galleries, mailing lists, forums, analytics, and much more. Hundreds of thousands of developers and site owners trust it worldwide.
\nHundreds of thousands of developers and site owners trust it worldwide. Extend it with over 54,000 plugins to help your website meet your needs. Add an online store, galleries, mailing lists, forums, analytics, and much more.
\nEnjoy a wide variety of
\n\n\n\nCustom Designs
\n\n\n\nExtend it with over 54,000 plugins to help your website meet your needs. Add an online store, galleries, mailing lists, forums, analytics, and much more. Hundreds of thousands of developers and site owners trust it worldwide.
\nHundreds of thousands of developers and site owners trust it worldwide. Extend it with over 54,000 plugins to help your website meet your needs. Add an online store, galleries, mailing lists, forums, analytics, and much more.
\nNEW
\n\n\n\nJohn Lenwood \"Jackie\" McLean was an American jazz alto saxophonist, composer, bandleader, and educator, and is one of the few musicians to be elected to the DownBeat Hall of Fame in the year of their death.
\nspace
\n\n\n\nDerek Ansell's full-length biography of McLean, Sugar Free Saxophone (London: Northway Books, 2012), details the story of his career and provides a full analysis of his music on record.
\nit's time
\nNEW
\n\n\n\nJohn Lenwood \"Jackie\" McLean was an American jazz alto saxophonist, composer, bandleader, and educator, and is one of the few musicians to be elected to the DownBeat Hall of Fame in the year of their death.
\nspace
\n\n\n\nDerek Ansell's full-length biography of McLean, Sugar Free Saxophone (London: Northway Books, 2012), details the story of his career and provides a full analysis of his music on record.
\nit's time
\n1
\nCustom Designs
\n\n\n\nExtend it with over 54,000 plugins to help your website meet your needs.
\n\n\n\n\n2
\nHigh Performance
\n\n\n\nAdd an online store, galleries, mailing lists, forums, analytics, and much more.
\n\n\n\n\n3
\nEasy and Accessible
\n\n\n\nHundreds of thousands of developers and site owners trust it worldwide.
\n1
\nCustom Designs
\n\n\n\nExtend it with over 54,000 plugins to help your website meet your needs.
\n\n\n\n\n2
\nHigh Performance
\n\n\n\nAdd an online store, galleries, mailing lists, forums, analytics, and much more.
\n\n\n\n\n3
\nEasy and Accessible
\n\n\n\nHundreds of thousands of developers and site owners trust it worldwide.
\n\"This software is designed for everyone, emphasizing accessibility, performance, security, and ease of use.\"
\nDoris Som
\n\"We believe great software should work with minimum set up, so you can focus on sharing your story, or services freely.\"
\nWalt Art
\n\"The product is simple and predictable so you can easily get started. It also offers powerful features for success.\"
\nMoly Neo
\n\"This software is designed for everyone, emphasizing accessibility, performance, security, and ease of use.\"
\nDoris Som
\n\"We believe great software should work with minimum set up, so you can focus on sharing your story, or services freely.\"
\nWalt Art
\n\"The product is simple and predictable so you can easily get started. It also offers powerful features for success.\"
\nMoly Neo
\nCHAPTER 1. Loomings
\n\n\n\nCall me Ishmael. Some years ago—never mind how long precisely—having little or no money in my purse, and nothing particular to interest me on shore, I thought I would sail about a little and see the watery part of the world. It is a way I have of driving off the spleen and regulating the circulation.
\nWhenever I find myself growing grim about the mouth; whenever it is a damp, drizzly November in my soul; whenever I find myself involuntarily pausing before coffin warehouses, and bringing up the rear of every funeral I meet; and especially whenever my hypos get such an upper hand of me, that it requires a strong moral principle to prevent me from deliberately stepping into the street, and methodically knocking people’s hats off—then, I account it high time to get to sea as soon as I can.
\nCHAPTER 1. Loomings
\n\n\n\nCall me Ishmael. Some years ago—never mind how long precisely—having little or no money in my purse, and nothing particular to interest me on shore, I thought I would sail about a little and see the watery part of the world. It is a way I have of driving off the spleen and regulating the circulation.
\nWhenever I find myself growing grim about the mouth; whenever it is a damp, drizzly November in my soul; whenever I find myself involuntarily pausing before coffin warehouses, and bringing up the rear of every funeral I meet; and especially whenever my hypos get such an upper hand of me, that it requires a strong moral principle to prevent me from deliberately stepping into the street, and methodically knocking people’s hats off—then, I account it high time to get to sea as soon as I can.
\n