40 /** |
41 /** |
41 * Registers a block pattern. |
42 * Registers a block pattern. |
42 * |
43 * |
43 * @since 5.5.0 |
44 * @since 5.5.0 |
44 * @since 5.8.0 Added support for the `blockTypes` property. |
45 * @since 5.8.0 Added support for the `blockTypes` property. |
|
46 * @since 6.1.0 Added support for the `postTypes` property. |
|
47 * @since 6.2.0 Added support for the `templateTypes` property. |
|
48 * @since 6.5.0 Added support for the `filePath` property. |
45 * |
49 * |
46 * @param string $pattern_name Block pattern name including namespace. |
50 * @param string $pattern_name Block pattern name including namespace. |
47 * @param array $pattern_properties { |
51 * @param array $pattern_properties { |
48 * List of properties for the block pattern. |
52 * List of properties for the block pattern. |
49 * |
53 * |
50 * @type string $title Required. A human-readable title for the pattern. |
54 * @type string $title Required. A human-readable title for the pattern. |
51 * @type string $content Required. Block HTML markup for the pattern. |
55 * @type string $content Optional. Block HTML markup for the pattern. |
52 * @type string $description Optional. Visually hidden text used to describe the pattern in the |
56 * If not provided, the content will be retrieved from the `filePath` if set. |
53 * inserter. A description is optional, but is strongly |
57 * If both `content` and `filePath` are not set, the pattern will not be registered. |
54 * encouraged when the title does not fully describe what the |
58 * @type string $description Optional. Visually hidden text used to describe the pattern |
55 * pattern does. The description will help users discover the |
59 * in the inserter. A description is optional, but is strongly |
56 * pattern while searching. |
60 * encouraged when the title does not fully describe what the |
57 * @type int $viewportWidth Optional. The intended width of the pattern to allow for a scaled |
61 * pattern does. The description will help users discover the |
58 * preview within the pattern inserter. |
62 * pattern while searching. |
59 * @type array $categories Optional. A list of registered pattern categories used to group block |
63 * @type int $viewportWidth Optional. The intended width of the pattern to allow for a scaled |
60 * patterns. Block patterns can be shown on multiple categories. |
64 * preview within the pattern inserter. |
61 * A category must be registered separately in order to be used |
65 * @type bool $inserter Optional. Determines whether the pattern is visible in inserter. |
62 * here. |
66 * To hide a pattern so that it can only be inserted programmatically, |
63 * @type array $blockTypes Optional. A list of block names including namespace that could use |
67 * set this to false. Default true. |
64 * the block pattern in certain contexts (placeholder, transforms). |
68 * @type string[] $categories Optional. A list of registered pattern categories used to group |
65 * The block pattern is available in the block editor inserter |
69 * block patterns. Block patterns can be shown on multiple categories. |
66 * regardless of this list of block names. |
70 * A category must be registered separately in order to be used here. |
67 * Certain blocks support further specificity besides the block name |
71 * @type string[] $keywords Optional. A list of aliases or keywords that help users discover |
68 * (e.g. for `core/template-part` you can specify areas |
72 * the pattern while searching. |
69 * like `core/template-part/header` or `core/template-part/footer`). |
73 * @type string[] $blockTypes Optional. A list of block names including namespace that could use |
70 * @type array $keywords Optional. A list of aliases or keywords that help users discover the |
74 * the block pattern in certain contexts (placeholder, transforms). |
71 * pattern while searching. |
75 * The block pattern is available in the block editor inserter |
|
76 * regardless of this list of block names. |
|
77 * Certain blocks support further specificity besides the block name |
|
78 * (e.g. for `core/template-part` you can specify areas |
|
79 * like `core/template-part/header` or `core/template-part/footer`). |
|
80 * @type string[] $postTypes Optional. An array of post types that the pattern is restricted |
|
81 * to be used with. The pattern will only be available when editing one |
|
82 * of the post types passed on the array. For all the other post types |
|
83 * not part of the array the pattern is not available at all. |
|
84 * @type string[] $templateTypes Optional. An array of template types where the pattern fits. |
|
85 * @type string $filePath Optional. The full path to the file containing the block pattern content. |
72 * } |
86 * } |
73 * @return bool True if the pattern was registered with success and false otherwise. |
87 * @return bool True if the pattern was registered with success and false otherwise. |
74 */ |
88 */ |
75 public function register( $pattern_name, $pattern_properties ) { |
89 public function register( $pattern_name, $pattern_properties ) { |
76 if ( ! isset( $pattern_name ) || ! is_string( $pattern_name ) ) { |
90 if ( ! isset( $pattern_name ) || ! is_string( $pattern_name ) ) { |
89 '5.5.0' |
103 '5.5.0' |
90 ); |
104 ); |
91 return false; |
105 return false; |
92 } |
106 } |
93 |
107 |
94 if ( ! isset( $pattern_properties['content'] ) || ! is_string( $pattern_properties['content'] ) ) { |
108 if ( ! isset( $pattern_properties['filePath'] ) ) { |
95 _doing_it_wrong( |
109 if ( ! isset( $pattern_properties['content'] ) || ! is_string( $pattern_properties['content'] ) ) { |
96 __METHOD__, |
110 _doing_it_wrong( |
97 __( 'Pattern content must be a string.' ), |
111 __METHOD__, |
98 '5.5.0' |
112 __( 'Pattern content must be a string.' ), |
99 ); |
113 '5.5.0' |
100 return false; |
114 ); |
|
115 return false; |
|
116 } |
101 } |
117 } |
102 |
118 |
103 $pattern = array_merge( |
119 $pattern = array_merge( |
104 $pattern_properties, |
120 $pattern_properties, |
105 array( 'name' => $pattern_name ) |
121 array( 'name' => $pattern_name ) |
106 ); |
122 ); |
|
123 |
107 $this->registered_patterns[ $pattern_name ] = $pattern; |
124 $this->registered_patterns[ $pattern_name ] = $pattern; |
108 |
125 |
109 // If the pattern is registered inside an action other than `init`, store it |
126 // If the pattern is registered inside an action other than `init`, store it |
110 // also to a dedicated array. Used to detect deprecated registrations inside |
127 // also to a dedicated array. Used to detect deprecated registrations inside |
111 // `admin_init` or `current_screen`. |
128 // `admin_init` or `current_screen`. |
140 |
157 |
141 return true; |
158 return true; |
142 } |
159 } |
143 |
160 |
144 /** |
161 /** |
|
162 * Prepares the content of a block pattern. If hooked blocks are registered, they get injected into the pattern, |
|
163 * when they met the defined criteria. |
|
164 * |
|
165 * @since 6.4.0 |
|
166 * |
|
167 * @param array $pattern Registered pattern properties. |
|
168 * @param array $hooked_blocks The list of hooked blocks. |
|
169 * @return string The content of the block pattern. |
|
170 */ |
|
171 private function prepare_content( $pattern, $hooked_blocks ) { |
|
172 $content = $pattern['content']; |
|
173 |
|
174 $before_block_visitor = '_inject_theme_attribute_in_template_part_block'; |
|
175 $after_block_visitor = null; |
|
176 if ( ! empty( $hooked_blocks ) || has_filter( 'hooked_block_types' ) ) { |
|
177 $before_block_visitor = make_before_block_visitor( $hooked_blocks, $pattern, 'insert_hooked_blocks_and_set_ignored_hooked_blocks_metadata' ); |
|
178 $after_block_visitor = make_after_block_visitor( $hooked_blocks, $pattern, 'insert_hooked_blocks_and_set_ignored_hooked_blocks_metadata' ); |
|
179 } |
|
180 $blocks = parse_blocks( $content ); |
|
181 $content = traverse_and_serialize_blocks( $blocks, $before_block_visitor, $after_block_visitor ); |
|
182 |
|
183 return $content; |
|
184 } |
|
185 |
|
186 /** |
|
187 * Retrieves the content of a registered block pattern. |
|
188 * |
|
189 * @since 6.5.0 |
|
190 * |
|
191 * @param string $pattern_name Block pattern name including namespace. |
|
192 * @param bool $outside_init_only Optional. Return only patterns registered outside the `init` action. Default false. |
|
193 * @return string The content of the block pattern. |
|
194 */ |
|
195 private function get_content( $pattern_name, $outside_init_only = false ) { |
|
196 if ( $outside_init_only ) { |
|
197 $patterns = &$this->registered_patterns_outside_init; |
|
198 } else { |
|
199 $patterns = &$this->registered_patterns; |
|
200 } |
|
201 if ( ! isset( $patterns[ $pattern_name ]['content'] ) && isset( $patterns[ $pattern_name ]['filePath'] ) ) { |
|
202 ob_start(); |
|
203 include $patterns[ $pattern_name ]['filePath']; |
|
204 $patterns[ $pattern_name ]['content'] = ob_get_clean(); |
|
205 unset( $patterns[ $pattern_name ]['filePath'] ); |
|
206 } |
|
207 return $patterns[ $pattern_name ]['content']; |
|
208 } |
|
209 |
|
210 /** |
145 * Retrieves an array containing the properties of a registered block pattern. |
211 * Retrieves an array containing the properties of a registered block pattern. |
146 * |
212 * |
147 * @since 5.5.0 |
213 * @since 5.5.0 |
148 * |
214 * |
149 * @param string $pattern_name Block pattern name including namespace. |
215 * @param string $pattern_name Block pattern name including namespace. |
165 * @param bool $outside_init_only Return only patterns registered outside the `init` action. |
235 * @param bool $outside_init_only Return only patterns registered outside the `init` action. |
166 * @return array[] Array of arrays containing the registered block patterns properties, |
236 * @return array[] Array of arrays containing the registered block patterns properties, |
167 * and per style. |
237 * and per style. |
168 */ |
238 */ |
169 public function get_all_registered( $outside_init_only = false ) { |
239 public function get_all_registered( $outside_init_only = false ) { |
170 return array_values( |
240 $patterns = $outside_init_only |
171 $outside_init_only |
|
172 ? $this->registered_patterns_outside_init |
241 ? $this->registered_patterns_outside_init |
173 : $this->registered_patterns |
242 : $this->registered_patterns; |
174 ); |
243 $hooked_blocks = get_hooked_blocks(); |
|
244 |
|
245 foreach ( $patterns as $index => $pattern ) { |
|
246 $pattern['content'] = $this->get_content( $pattern['name'], $outside_init_only ); |
|
247 $patterns[ $index ]['content'] = $this->prepare_content( $pattern, $hooked_blocks ); |
|
248 } |
|
249 |
|
250 return array_values( $patterns ); |
175 } |
251 } |
176 |
252 |
177 /** |
253 /** |
178 * Checks if a block pattern is registered. |
254 * Checks if a block pattern is registered. |
179 * |
255 * |
182 * @param string $pattern_name Block pattern name including namespace. |
258 * @param string $pattern_name Block pattern name including namespace. |
183 * @return bool True if the pattern is registered, false otherwise. |
259 * @return bool True if the pattern is registered, false otherwise. |
184 */ |
260 */ |
185 public function is_registered( $pattern_name ) { |
261 public function is_registered( $pattern_name ) { |
186 return isset( $this->registered_patterns[ $pattern_name ] ); |
262 return isset( $this->registered_patterns[ $pattern_name ] ); |
|
263 } |
|
264 |
|
265 public function __wakeup() { |
|
266 if ( ! $this->registered_patterns ) { |
|
267 return; |
|
268 } |
|
269 if ( ! is_array( $this->registered_patterns ) ) { |
|
270 throw new UnexpectedValueException(); |
|
271 } |
|
272 foreach ( $this->registered_patterns as $value ) { |
|
273 if ( ! is_array( $value ) ) { |
|
274 throw new UnexpectedValueException(); |
|
275 } |
|
276 } |
|
277 $this->registered_patterns_outside_init = array(); |
187 } |
278 } |
188 |
279 |
189 /** |
280 /** |
190 * Utility method to retrieve the main instance of the class. |
281 * Utility method to retrieve the main instance of the class. |
191 * |
282 * |