1<?php
2/**
3 * Blocks API: WP_Block_Styles_Registry class
4 *
5 * @package WordPress
6 * @subpackage Blocks
7 * @since 5.3.0
8 */
9
10/**
11 * Class used for interacting with block styles.
12 *
13 * @since 5.3.0
14 */
15#[AllowDynamicProperties]
16final class WP_Block_Styles_Registry {
17 /**
18 * Registered block styles, as `$block_name => $block_style_name => $block_style_properties` multidimensional arrays.
19 *
20 * @since 5.3.0
21 *
22 * @var array[]
23 */
24 private $registered_block_styles = array();
25
26 /**
27 * Container for the main instance of the class.
28 *
29 * @since 5.3.0
30 *
31 * @var WP_Block_Styles_Registry|null
32 */
33 private static $instance = null;
34
35 /**
36 * Registers a block style for the given block type.
37 *
38 * If the block styles are present in a standalone stylesheet, register it and pass
39 * its handle as the `style_handle` argument. If the block styles should be inline,
40 * use the `inline_style` argument. Usually, one of them would be used to pass CSS
41 * styles. However, you could also skip them and provide CSS styles in any stylesheet
42 * or with an inline tag.
43 *
44 * @since 5.3.0
45 * @since 6.6.0 Added ability to register style across multiple block types along with theme.json-like style data.
46 *
47 * @link https://developer.wordpress.org/block-editor/reference-guides/block-api/block-styles/
48 *
49 * @param string|string[] $block_name Block type name including namespace or array of namespaced block type names.
50 * @param array $style_properties {
51 * Array containing the properties of the style.
52 *
53 * @type string $name The identifier of the style used to compute a CSS class.
54 * @type string $label A human-readable label for the style.
55 * @type string $inline_style Inline CSS code that registers the CSS class required
56 * for the style.
57 * @type string $style_handle The handle to an already registered style that should be
58 * enqueued in places where block styles are needed.
59 * @type bool $is_default Whether this is the default style for the block type.
60 * @type array $style_data Theme.json-like object to generate CSS from.
61 * }
62 * @return bool True if the block style was registered with success and false otherwise.
63 */
64 public function register( $block_name, $style_properties ) {
65
66 if ( ! is_string( $block_name ) && ! is_array( $block_name ) ) {
67 _doing_it_wrong(
68 __METHOD__,
69 __( 'Block name must be a string or array.' ),
70 '6.6.0'
71 );
72 return false;
73 }
74
75 if ( ! isset( $style_properties['name'] ) || ! is_string( $style_properties['name'] ) ) {
76 _doing_it_wrong(
77 __METHOD__,
78 __( 'Block style name must be a string.' ),
79 '5.3.0'
80 );
81 return false;
82 }
83
84 if ( str_contains( $style_properties['name'], ' ' ) ) {
85 _doing_it_wrong(
86 __METHOD__,
87 __( 'Block style name must not contain any spaces.' ),
88 '5.9.0'
89 );
90 return false;
91 }
92
93 $block_style_name = $style_properties['name'];
94 $block_names = is_string( $block_name ) ? array( $block_name ) : $block_name;
95
96 // Ensure there is a label defined.
97 if ( empty( $style_properties['label'] ) ) {
98 $style_properties['label'] = $block_style_name;
99 }
100
101 foreach ( $block_names as $name ) {
102 if ( ! isset( $this->registered_block_styles[ $name ] ) ) {
103 $this->registered_block_styles[ $name ] = array();
104 }
105 $this->registered_block_styles[ $name ][ $block_style_name ] = $style_properties;
106 }
107
108 return true;
109 }
110
111 /**
112 * Unregisters a block style of the given block type.
113 *
114 * @since 5.3.0
115 *
116 * @param string $block_name Block type name including namespace.
117 * @param string $block_style_name Block style name.
118 * @return bool True if the block style was unregistered with success and false otherwise.
119 */
120 public function unregister( $block_name, $block_style_name ) {
121 if ( ! $this->is_registered( $block_name, $block_style_name ) ) {
122 _doing_it_wrong(
123 __METHOD__,
124 /* translators: 1: Block name, 2: Block style name. */
125 sprintf( __( 'Block "%1$s" does not contain a style named "%2$s".' ), $block_name, $block_style_name ),
126 '5.3.0'
127 );
128 return false;
129 }
130
131 unset( $this->registered_block_styles[ $block_name ][ $block_style_name ] );
132
133 return true;
134 }
135
136 /**
137 * Retrieves the properties of a registered block style for the given block type.
138 *
139 * @since 5.3.0
140 *
141 * @param string $block_name Block type name including namespace.
142 * @param string $block_style_name Block style name.
143 * @return array|null Registered block style properties or `null` if the block style is not registered.
144 */
145 public function get_registered( $block_name, $block_style_name ) {
146 if ( ! $this->is_registered( $block_name, $block_style_name ) ) {
147 return null;
148 }
149
150 return $this->registered_block_styles[ $block_name ][ $block_style_name ];
151 }
152
153 /**
154 * Retrieves all registered block styles.
155 *
156 * @since 5.3.0
157 *
158 * @return array[] Array of arrays containing the registered block styles properties grouped by block type.
159 */
160 public function get_all_registered() {
161 return $this->registered_block_styles;
162 }
163
164 /**
165 * Retrieves registered block styles for a specific block type.
166 *
167 * @since 5.3.0
168 *
169 * @param string $block_name Block type name including namespace.
170 * @return array[] Array whose keys are block style names and whose values are block style properties.
171 */
172 public function get_registered_styles_for_block( $block_name ) {
173 if ( isset( $this->registered_block_styles[ $block_name ] ) ) {
174 return $this->registered_block_styles[ $block_name ];
175 }
176 return array();
177 }
178
179 /**
180 * Checks if a block style is registered for the given block type.
181 *
182 * @since 5.3.0
183 *
184 * @param string|null $block_name Block type name including namespace.
185 * @param string|null $block_style_name Block style name.
186 * @return bool True if the block style is registered, false otherwise.
187 */
188 public function is_registered( $block_name, $block_style_name ) {
189 return isset( $block_name, $block_style_name, $this->registered_block_styles[ $block_name ][ $block_style_name ] );
190 }
191
192 /**
193 * Utility method to retrieve the main instance of the class.
194 *
195 * The instance will be created if it does not exist yet.
196 *
197 * @since 5.3.0
198 *
199 * @return WP_Block_Styles_Registry The main instance.
200 */
201 public static function get_instance() {
202 if ( null === self::$instance ) {
203 self::$instance = new self();
204 }
205
206 return self::$instance;
207 }
208}
209