36 } |
36 } |
37 } |
37 } |
38 |
38 |
39 register_block_pattern_category( 'buttons', array( 'label' => _x( 'Buttons', 'Block pattern category' ) ) ); |
39 register_block_pattern_category( 'buttons', array( 'label' => _x( 'Buttons', 'Block pattern category' ) ) ); |
40 register_block_pattern_category( 'columns', array( 'label' => _x( 'Columns', 'Block pattern category' ) ) ); |
40 register_block_pattern_category( 'columns', array( 'label' => _x( 'Columns', 'Block pattern category' ) ) ); |
|
41 register_block_pattern_category( 'featured', array( 'label' => _x( 'Featured', 'Block pattern category' ) ) ); |
41 register_block_pattern_category( 'gallery', array( 'label' => _x( 'Gallery', 'Block pattern category' ) ) ); |
42 register_block_pattern_category( 'gallery', array( 'label' => _x( 'Gallery', 'Block pattern category' ) ) ); |
42 register_block_pattern_category( 'header', array( 'label' => _x( 'Headers', 'Block pattern category' ) ) ); |
43 register_block_pattern_category( 'header', array( 'label' => _x( 'Headers', 'Block pattern category' ) ) ); |
43 register_block_pattern_category( 'text', array( 'label' => _x( 'Text', 'Block pattern category' ) ) ); |
44 register_block_pattern_category( 'text', array( 'label' => _x( 'Text', 'Block pattern category' ) ) ); |
44 register_block_pattern_category( 'query', array( 'label' => _x( 'Query', 'Block pattern category' ) ) ); |
45 register_block_pattern_category( 'query', array( 'label' => _x( 'Query', 'Block pattern category' ) ) ); |
45 } |
46 } |
46 |
47 |
47 /** |
48 /** |
48 * Register Core's official patterns from wordpress.org/patterns. |
49 * Register Core's official patterns from wordpress.org/patterns. |
49 * |
50 * |
50 * @since 5.8.0 |
51 * @since 5.8.0 |
51 * |
52 * @since 5.9.0 The $current_screen argument was removed. |
52 * @param WP_Screen $current_screen The screen that the current request was triggered from. |
53 * |
53 */ |
54 * @param WP_Screen $deprecated Unused. Formerly the screen that the current request was triggered from. |
54 function _load_remote_block_patterns( $current_screen ) { |
55 */ |
55 if ( ! $current_screen->is_block_editor ) { |
56 function _load_remote_block_patterns( $deprecated = null ) { |
56 return; |
57 if ( ! empty( $deprecated ) ) { |
|
58 _deprecated_argument( __FUNCTION__, '5.9.0' ); |
|
59 $current_screen = $deprecated; |
|
60 if ( ! $current_screen->is_block_editor ) { |
|
61 return; |
|
62 } |
57 } |
63 } |
58 |
64 |
59 $supports_core_patterns = get_theme_support( 'core-block-patterns' ); |
65 $supports_core_patterns = get_theme_support( 'core-block-patterns' ); |
60 |
66 |
61 /** |
67 /** |
81 $pattern_name = 'core/' . sanitize_title( $settings['title'] ); |
87 $pattern_name = 'core/' . sanitize_title( $settings['title'] ); |
82 register_block_pattern( $pattern_name, (array) $settings ); |
88 register_block_pattern( $pattern_name, (array) $settings ); |
83 } |
89 } |
84 } |
90 } |
85 } |
91 } |
|
92 |
|
93 /** |
|
94 * Register `Featured` (category) patterns from wordpress.org/patterns. |
|
95 * |
|
96 * @since 5.9.0 |
|
97 */ |
|
98 function _load_remote_featured_patterns() { |
|
99 $supports_core_patterns = get_theme_support( 'core-block-patterns' ); |
|
100 |
|
101 /** This filter is documented in wp-includes/block-patterns.php */ |
|
102 $should_load_remote = apply_filters( 'should_load_remote_block_patterns', true ); |
|
103 |
|
104 if ( ! $should_load_remote || ! $supports_core_patterns ) { |
|
105 return; |
|
106 } |
|
107 |
|
108 $request = new WP_REST_Request( 'GET', '/wp/v2/pattern-directory/patterns' ); |
|
109 $featured_cat_id = 26; // This is the `Featured` category id from pattern directory. |
|
110 $request->set_param( 'category', $featured_cat_id ); |
|
111 $response = rest_do_request( $request ); |
|
112 if ( $response->is_error() ) { |
|
113 return; |
|
114 } |
|
115 $patterns = $response->get_data(); |
|
116 |
|
117 foreach ( $patterns as $pattern ) { |
|
118 $pattern_name = sanitize_title( $pattern['title'] ); |
|
119 $registry = WP_Block_Patterns_Registry::get_instance(); |
|
120 // Some patterns might be already registered as core patterns with the `core` prefix. |
|
121 $is_registered = $registry->is_registered( $pattern_name ) || $registry->is_registered( "core/$pattern_name" ); |
|
122 if ( ! $is_registered ) { |
|
123 register_block_pattern( $pattern_name, (array) $pattern ); |
|
124 } |
|
125 } |
|
126 } |
|
127 |
|
128 /** |
|
129 * Registers patterns from Pattern Directory provided by a theme's |
|
130 * `theme.json` file. |
|
131 * |
|
132 * @since 6.0.0 |
|
133 * @access private |
|
134 */ |
|
135 function _register_remote_theme_patterns() { |
|
136 /** This filter is documented in wp-includes/block-patterns.php */ |
|
137 if ( ! apply_filters( 'should_load_remote_block_patterns', true ) ) { |
|
138 return; |
|
139 } |
|
140 |
|
141 if ( ! WP_Theme_JSON_Resolver::theme_has_support() ) { |
|
142 return; |
|
143 } |
|
144 |
|
145 $pattern_settings = WP_Theme_JSON_Resolver::get_theme_data()->get_patterns(); |
|
146 if ( empty( $pattern_settings ) ) { |
|
147 return; |
|
148 } |
|
149 |
|
150 $request = new WP_REST_Request( 'GET', '/wp/v2/pattern-directory/patterns' ); |
|
151 $request['slug'] = $pattern_settings; |
|
152 $response = rest_do_request( $request ); |
|
153 if ( $response->is_error() ) { |
|
154 return; |
|
155 } |
|
156 $patterns = $response->get_data(); |
|
157 $patterns_registry = WP_Block_Patterns_Registry::get_instance(); |
|
158 foreach ( $patterns as $pattern ) { |
|
159 $pattern_name = sanitize_title( $pattern['title'] ); |
|
160 // Some patterns might be already registered as core patterns with the `core` prefix. |
|
161 $is_registered = $patterns_registry->is_registered( $pattern_name ) || $patterns_registry->is_registered( "core/$pattern_name" ); |
|
162 if ( ! $is_registered ) { |
|
163 register_block_pattern( $pattern_name, (array) $pattern ); |
|
164 } |
|
165 } |
|
166 } |
|
167 |
|
168 /** |
|
169 * Register any patterns that the active theme may provide under its |
|
170 * `./patterns/` directory. Each pattern is defined as a PHP file and defines |
|
171 * its metadata using plugin-style headers. The minimum required definition is: |
|
172 * |
|
173 * /** |
|
174 * * Title: My Pattern |
|
175 * * Slug: my-theme/my-pattern |
|
176 * * |
|
177 * |
|
178 * The output of the PHP source corresponds to the content of the pattern, e.g.: |
|
179 * |
|
180 * <main><p><?php echo "Hello"; ?></p></main> |
|
181 * |
|
182 * If applicable, this will collect from both parent and child theme. |
|
183 * |
|
184 * Other settable fields include: |
|
185 * |
|
186 * - Description |
|
187 * - Viewport Width |
|
188 * - Categories (comma-separated values) |
|
189 * - Keywords (comma-separated values) |
|
190 * - Block Types (comma-separated values) |
|
191 * - Inserter (yes/no) |
|
192 * |
|
193 * @since 6.0.0 |
|
194 * @access private |
|
195 */ |
|
196 function _register_theme_block_patterns() { |
|
197 $default_headers = array( |
|
198 'title' => 'Title', |
|
199 'slug' => 'Slug', |
|
200 'description' => 'Description', |
|
201 'viewportWidth' => 'Viewport Width', |
|
202 'categories' => 'Categories', |
|
203 'keywords' => 'Keywords', |
|
204 'blockTypes' => 'Block Types', |
|
205 'inserter' => 'Inserter', |
|
206 ); |
|
207 |
|
208 /* |
|
209 * Register patterns for the active theme. If the theme is a child theme, |
|
210 * let it override any patterns from the parent theme that shares the same slug. |
|
211 */ |
|
212 $themes = array(); |
|
213 $stylesheet = get_stylesheet(); |
|
214 $template = get_template(); |
|
215 if ( $stylesheet !== $template ) { |
|
216 $themes[] = wp_get_theme( $stylesheet ); |
|
217 } |
|
218 $themes[] = wp_get_theme( $template ); |
|
219 |
|
220 foreach ( $themes as $theme ) { |
|
221 $dirpath = $theme->get_stylesheet_directory() . '/patterns/'; |
|
222 if ( ! is_dir( $dirpath ) || ! is_readable( $dirpath ) ) { |
|
223 continue; |
|
224 } |
|
225 if ( file_exists( $dirpath ) ) { |
|
226 $files = glob( $dirpath . '*.php' ); |
|
227 if ( $files ) { |
|
228 foreach ( $files as $file ) { |
|
229 $pattern_data = get_file_data( $file, $default_headers ); |
|
230 |
|
231 if ( empty( $pattern_data['slug'] ) ) { |
|
232 _doing_it_wrong( |
|
233 '_register_theme_block_patterns', |
|
234 sprintf( |
|
235 /* translators: %s: file name. */ |
|
236 __( 'Could not register file "%s" as a block pattern ("Slug" field missing)' ), |
|
237 $file |
|
238 ), |
|
239 '6.0.0' |
|
240 ); |
|
241 continue; |
|
242 } |
|
243 |
|
244 if ( ! preg_match( '/^[A-z0-9\/_-]+$/', $pattern_data['slug'] ) ) { |
|
245 _doing_it_wrong( |
|
246 '_register_theme_block_patterns', |
|
247 sprintf( |
|
248 /* translators: %1s: file name; %2s: slug value found. */ |
|
249 __( 'Could not register file "%1$s" as a block pattern (invalid slug "%2$s")' ), |
|
250 $file, |
|
251 $pattern_data['slug'] |
|
252 ), |
|
253 '6.0.0' |
|
254 ); |
|
255 } |
|
256 |
|
257 if ( WP_Block_Patterns_Registry::get_instance()->is_registered( $pattern_data['slug'] ) ) { |
|
258 continue; |
|
259 } |
|
260 |
|
261 // Title is a required property. |
|
262 if ( ! $pattern_data['title'] ) { |
|
263 _doing_it_wrong( |
|
264 '_register_theme_block_patterns', |
|
265 sprintf( |
|
266 /* translators: %1s: file name; %2s: slug value found. */ |
|
267 __( 'Could not register file "%s" as a block pattern ("Title" field missing)' ), |
|
268 $file |
|
269 ), |
|
270 '6.0.0' |
|
271 ); |
|
272 continue; |
|
273 } |
|
274 |
|
275 // For properties of type array, parse data as comma-separated. |
|
276 foreach ( array( 'categories', 'keywords', 'blockTypes' ) as $property ) { |
|
277 if ( ! empty( $pattern_data[ $property ] ) ) { |
|
278 $pattern_data[ $property ] = array_filter( |
|
279 preg_split( |
|
280 '/[\s,]+/', |
|
281 (string) $pattern_data[ $property ] |
|
282 ) |
|
283 ); |
|
284 } else { |
|
285 unset( $pattern_data[ $property ] ); |
|
286 } |
|
287 } |
|
288 |
|
289 // Parse properties of type int. |
|
290 foreach ( array( 'viewportWidth' ) as $property ) { |
|
291 if ( ! empty( $pattern_data[ $property ] ) ) { |
|
292 $pattern_data[ $property ] = (int) $pattern_data[ $property ]; |
|
293 } else { |
|
294 unset( $pattern_data[ $property ] ); |
|
295 } |
|
296 } |
|
297 |
|
298 // Parse properties of type bool. |
|
299 foreach ( array( 'inserter' ) as $property ) { |
|
300 if ( ! empty( $pattern_data[ $property ] ) ) { |
|
301 $pattern_data[ $property ] = in_array( |
|
302 strtolower( $pattern_data[ $property ] ), |
|
303 array( 'yes', 'true' ), |
|
304 true |
|
305 ); |
|
306 } else { |
|
307 unset( $pattern_data[ $property ] ); |
|
308 } |
|
309 } |
|
310 |
|
311 // Translate the pattern metadata. |
|
312 $text_domain = $theme->get( 'TextDomain' ); |
|
313 //phpcs:ignore WordPress.WP.I18n.NonSingularStringLiteralText, WordPress.WP.I18n.NonSingularStringLiteralContext, WordPress.WP.I18n.NonSingularStringLiteralDomain, WordPress.WP.I18n.LowLevelTranslationFunction |
|
314 $pattern_data['title'] = translate_with_gettext_context( $pattern_data['title'], 'Pattern title', $text_domain ); |
|
315 if ( ! empty( $pattern_data['description'] ) ) { |
|
316 //phpcs:ignore WordPress.WP.I18n.NonSingularStringLiteralText, WordPress.WP.I18n.NonSingularStringLiteralContext, WordPress.WP.I18n.NonSingularStringLiteralDomain, WordPress.WP.I18n.LowLevelTranslationFunction |
|
317 $pattern_data['description'] = translate_with_gettext_context( $pattern_data['description'], 'Pattern description', $text_domain ); |
|
318 } |
|
319 |
|
320 // The actual pattern content is the output of the file. |
|
321 ob_start(); |
|
322 include $file; |
|
323 $pattern_data['content'] = ob_get_clean(); |
|
324 if ( ! $pattern_data['content'] ) { |
|
325 continue; |
|
326 } |
|
327 |
|
328 register_block_pattern( $pattern_data['slug'], $pattern_data ); |
|
329 } |
|
330 } |
|
331 } |
|
332 } |
|
333 } |
|
334 add_action( 'init', '_register_theme_block_patterns' ); |