PluginProbe
Gutenberg / 7.7.2
Gutenberg v7.7.2
23.9.1 23.9.0 23.8.0 23.7.2 23.7.1 23.7.0 23.6.1 23.6.2 23.6.0 23.5.3 23.5.2 23.5.1 23.5.0 23.4.0 23.3.2 23.3.1 23.3.0 23.2.0 23.2.1 23.2.2 23.1.1 23.1.0 23.0.1 12.6.0 7.4.0 All 402 releases
gutenberg / lib / client-assets.php

client-assets.php in Gutenberg 7.7.2, at lib/client-assets.php

662 lines 22.2 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Functions to register client-side assets (scripts and stylesheets) for the
4 * Gutenberg editor plugin.
5 *
6 * @package gutenberg
7 */
8
9 if ( ! defined( 'ABSPATH' ) ) {
10 die( 'Silence is golden.' );
11 }
12
13 /**
14 * Retrieves the root plugin path.
15 *
16 * @return string Root path to the gutenberg plugin.
17 *
18 * @since 0.1.0
19 */
20 function gutenberg_dir_path() {
21 return plugin_dir_path( dirname( __FILE__ ) );
22 }
23
24 /**
25 * Retrieves a URL to a file in the gutenberg plugin.
26 *
27 * @param string $path Relative path of the desired file.
28 *
29 * @return string Fully qualified URL pointing to the desired file.
30 *
31 * @since 0.1.0
32 */
33 function gutenberg_url( $path ) {
34 return plugins_url( $path, dirname( __FILE__ ) );
35 }
36
37 /**
38 * Registers a script according to `wp_register_script`. Honors this request by
39 * reassigning internal dependency properties of any script handle already
40 * registered by that name. It does not deregister the original script, to
41 * avoid losing inline scripts which may have been attached.
42 *
43 * @since 4.1.0
44 *
45 * @param WP_Scripts $scripts WP_Scripts instance (passed by reference).
46 * @param string $handle Name of the script. Should be unique.
47 * @param string $src Full URL of the script, or path of the script relative to the WordPress root directory.
48 * @param array $deps Optional. An array of registered script handles this script depends on. Default empty array.
49 * @param string|bool|null $ver Optional. String specifying script version number, if it has one, which is added to the URL
50 * as a query string for cache busting purposes. If version is set to false, a version
51 * number is automatically added equal to current installed WordPress version.
52 * If set to null, no version is added.
53 * @param bool $in_footer Optional. Whether to enqueue the script before </body> instead of in the <head>.
54 * Default 'false'.
55 */
56 function gutenberg_override_script( &$scripts, $handle, $src, $deps = array(), $ver = false, $in_footer = false ) {
57 $script = $scripts->query( $handle, 'registered' );
58 if ( $script ) {
59 /*
60 * In many ways, this is a reimplementation of `wp_register_script` but
61 * bypassing consideration of whether a script by the given handle had
62 * already been registered.
63 */
64
65 // See: `_WP_Dependency::__construct` .
66 $script->src = $src;
67 $script->deps = $deps;
68 $script->ver = $ver;
69 $script->args = $in_footer;
70
71 /*
72 * The script's `group` designation is an indication of whether it is
73 * to be printed in the header or footer. The behavior here defers to
74 * the arguments as passed. Specifically, group data is not assigned
75 * for a script unless it is designated to be printed in the footer.
76 */
77
78 // See: `wp_register_script` .
79 unset( $script->extra['group'] );
80 if ( $in_footer ) {
81 $script->add_data( 'group', 1 );
82 }
83 } else {
84 $scripts->add( $handle, $src, $deps, $ver, $in_footer );
85 }
86
87 /*
88 * `WP_Dependencies::set_translations` will fall over on itself if setting
89 * translations on the `wp-i18n` handle, since it internally adds `wp-i18n`
90 * as a dependency of itself, exhausting memory. The same applies for the
91 * polyfill script, which is a dependency _of_ `wp-i18n`.
92 *
93 * See: https://core.trac.wordpress.org/ticket/46089
94 */
95 if ( 'wp-i18n' !== $handle && 'wp-polyfill' !== $handle ) {
96 $scripts->set_translations( $handle, 'default' );
97 }
98 }
99
100 /**
101 * Filters the default translation file load behavior to load the Gutenberg
102 * plugin translation file, if available.
103 *
104 * @param string|false $file Path to the translation file to load. False if
105 * there isn't one.
106 * @param string $handle Name of the script to register a translation
107 * domain to.
108 *
109 * @return string|false Filtered path to the Gutenberg translation file, if
110 * available.
111 */
112 function gutenberg_override_translation_file( $file, $handle ) {
113 if ( ! $file ) {
114 return $file;
115 }
116
117 // Ignore scripts whose handle does not have the "wp-" prefix.
118 if ( 'wp-' !== substr( $handle, 0, 3 ) ) {
119 return $file;
120 }
121
122 // Ignore scripts that are not found in the expected `build/` location.
123 $script_path = gutenberg_dir_path() . 'build/' . substr( $handle, 3 ) . '/index.js';
124 if ( ! file_exists( $script_path ) ) {
125 return $file;
126 }
127
128 /*
129 * The default file will be in the plugins language directory, omitting the
130 * domain since Gutenberg assigns the script translations as the default.
131 *
132 * Example: /www/wp-content/languages/plugins/de_DE-07d88e6a803e01276b9bfcc1203e862e.json
133 *
134 * The logic of `load_script_textdomain` is such that it will assume to
135 * search in the plugins language directory, since the assigned source of
136 * the overridden Gutenberg script originates in the plugins directory.
137 *
138 * The plugin translation files each begin with the slug of the plugin, so
139 * it's a simple matter of prepending the Gutenberg plugin slug.
140 */
141 $path_parts = pathinfo( $file );
142 $plugin_translation_file = (
143 $path_parts['dirname'] .
144 '/gutenberg-' .
145 $path_parts['basename']
146 );
147
148 return $plugin_translation_file;
149 }
150 add_filter( 'load_script_translation_file', 'gutenberg_override_translation_file', 10, 2 );
151
152 /**
153 * Filters the default labels for common post types to change the case style
154 * from capitalized (e.g. "Featured Image") to sentence-style (e.g. "Featured
155 * image").
156 *
157 * See: https://github.com/WordPress/gutenberg/pull/18758
158 *
159 * @param object $labels Object with all the labels as member variables.
160 *
161 * @return object Object with all the labels, including overridden ones.
162 */
163 function gutenberg_override_posttype_labels( $labels ) {
164 $labels->featured_image = __( 'Featured image', 'gutenberg' );
165 return $labels;
166 }
167 foreach ( array( 'post', 'page' ) as $post_type ) {
168 add_filter( "post_type_labels_{$post_type}", 'gutenberg_override_posttype_labels' );
169 }
170
171 /**
172 * Registers a style according to `wp_register_style`. Honors this request by
173 * deregistering any style by the same handler before registration.
174 *
175 * @since 4.1.0
176 *
177 * @param WP_Styles $styles WP_Styles instance (passed by reference).
178 * @param string $handle Name of the stylesheet. Should be unique.
179 * @param string $src Full URL of the stylesheet, or path of the stylesheet relative to the WordPress root directory.
180 * @param array $deps Optional. An array of registered stylesheet handles this stylesheet depends on. Default empty array.
181 * @param string|bool|null $ver Optional. String specifying stylesheet version number, if it has one, which is added to the URL
182 * as a query string for cache busting purposes. If version is set to false, a version
183 * number is automatically added equal to current installed WordPress version.
184 * If set to null, no version is added.
185 * @param string $media Optional. The media for which this stylesheet has been defined.
186 * Default 'all'. Accepts media types like 'all', 'print' and 'screen', or media queries like
187 * '(orientation: portrait)' and '(max-width: 640px)'.
188 */
189 function gutenberg_override_style( &$styles, $handle, $src, $deps = array(), $ver = false, $media = 'all' ) {
190 $style = $styles->query( $handle, 'registered' );
191 if ( $style ) {
192 $styles->remove( $handle );
193 }
194 $styles->add( $handle, $src, $deps, $ver, $media );
195 }
196
197 /**
198 * Registers vendor JavaScript files to be used as dependencies of the editor
199 * and plugins.
200 *
201 * This function is called from a script during the plugin build process, so it
202 * should not call any WordPress PHP functions.
203 *
204 * @since 0.1.0
205 *
206 * @param WP_Scripts $scripts WP_Scripts instance (passed by reference).
207 */
208 function gutenberg_register_vendor_scripts( &$scripts ) { // phpcs:ignore VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable
209 // This function is intentionally left empty.
210 //
211 // Scripts such as react and react-dom are expected to be overridden soon,
212 // and it is preferred to keep this function in place so as not to disturb
213 // tooling related to the plugin build process.
214 //
215 // TODO: Remove phpcs exception in function signature once this function
216 // regains its use.
217 //
218 // See https://github.com/WordPress/gutenberg/pull/20628.
219 }
220 add_action( 'wp_default_scripts', 'gutenberg_register_vendor_scripts' );
221
222 /**
223 * Registers all the WordPress packages scripts that are in the standardized
224 * `build/` location.
225 *
226 * @since 4.5.0
227 *
228 * @param WP_Scripts $scripts WP_Scripts instance (passed by reference).
229 */
230 function gutenberg_register_packages_scripts( &$scripts ) {
231 foreach ( glob( gutenberg_dir_path() . 'build/*/index.js' ) as $path ) {
232 // Prefix `wp-` to package directory to get script handle.
233 // For example, `…/build/a11y/index.js` becomes `wp-a11y`.
234 $handle = 'wp-' . basename( dirname( $path ) );
235
236 // Replace `.js` extension with `.asset.php` to find the generated dependencies file.
237 $asset_file = substr( $path, 0, -3 ) . '.asset.php';
238 $asset = file_exists( $asset_file )
239 ? require( $asset_file )
240 : null;
241 $dependencies = isset( $asset['dependencies'] ) ? $asset['dependencies'] : array();
242 $version = isset( $asset['version'] ) ? $asset['version'] : filemtime( $path );
243
244 // Add dependencies that cannot be detected and generated by build tools.
245 switch ( $handle ) {
246 case 'wp-block-library':
247 array_push( $dependencies, 'editor' );
248 break;
249
250 case 'wp-edit-post':
251 array_push( $dependencies, 'media-models', 'media-views', 'postbox' );
252 break;
253
254 case 'wp-edit-site':
255 array_push( $dependencies, 'wp-dom-ready' );
256 break;
257 }
258
259 // Get the path from Gutenberg directory as expected by `gutenberg_url`.
260 $gutenberg_path = substr( $path, strlen( gutenberg_dir_path() ) );
261
262 gutenberg_override_script(
263 $scripts,
264 $handle,
265 gutenberg_url( $gutenberg_path ),
266 $dependencies,
267 $version,
268 true
269 );
270 }
271 }
272 add_action( 'wp_default_scripts', 'gutenberg_register_packages_scripts' );
273
274 /**
275 * Registers all the WordPress packages styles that are in the standardized
276 * `build/` location.
277 *
278 * @since 6.7.0
279
280 * @param WP_Styles $styles WP_Styles instance (passed by reference).
281 */
282 function gutenberg_register_packages_styles( &$styles ) {
283 // Editor Styles.
284 gutenberg_override_style(
285 $styles,
286 'wp-block-editor',
287 gutenberg_url( 'build/block-editor/style.css' ),
288 array( 'wp-components', 'wp-editor-font' ),
289 filemtime( gutenberg_dir_path() . 'build/editor/style.css' )
290 );
291 $styles->add_data( 'wp-block-editor', 'rtl', 'replace' );
292
293 gutenberg_override_style(
294 $styles,
295 'wp-editor',
296 gutenberg_url( 'build/editor/style.css' ),
297 array( 'wp-components', 'wp-block-editor', 'wp-nux' ),
298 filemtime( gutenberg_dir_path() . 'build/editor/style.css' )
299 );
300 $styles->add_data( 'wp-editor', 'rtl', 'replace' );
301
302 gutenberg_override_style(
303 $styles,
304 'wp-edit-post',
305 gutenberg_url( 'build/edit-post/style.css' ),
306 array( 'wp-components', 'wp-block-editor', 'wp-editor', 'wp-edit-blocks', 'wp-block-library', 'wp-nux' ),
307 filemtime( gutenberg_dir_path() . 'build/edit-post/style.css' )
308 );
309 $styles->add_data( 'wp-edit-post', 'rtl', 'replace' );
310
311 gutenberg_override_style(
312 $styles,
313 'wp-components',
314 gutenberg_url( 'build/components/style.css' ),
315 array(),
316 filemtime( gutenberg_dir_path() . 'build/components/style.css' )
317 );
318 $styles->add_data( 'wp-components', 'rtl', 'replace' );
319
320 gutenberg_override_style(
321 $styles,
322 'wp-block-library',
323 gutenberg_url( 'build/block-library/style.css' ),
324 array(),
325 filemtime( gutenberg_dir_path() . 'build/block-library/style.css' )
326 );
327 $styles->add_data( 'wp-block-library', 'rtl', 'replace' );
328
329 gutenberg_override_style(
330 $styles,
331 'wp-format-library',
332 gutenberg_url( 'build/format-library/style.css' ),
333 array( 'wp-block-editor', 'wp-components' ),
334 filemtime( gutenberg_dir_path() . 'build/format-library/style.css' )
335 );
336 $styles->add_data( 'wp-format-library', 'rtl', 'replace' );
337
338 gutenberg_override_style(
339 $styles,
340 'wp-edit-blocks',
341 gutenberg_url( 'build/block-library/editor.css' ),
342 array(
343 'wp-components',
344 'wp-editor',
345 'wp-block-library',
346 // Always include visual styles so the editor never appears broken.
347 'wp-block-library-theme',
348 ),
349 filemtime( gutenberg_dir_path() . 'build/block-library/editor.css' )
350 );
351 $styles->add_data( 'wp-edit-blocks', 'rtl', 'replace' );
352
353 gutenberg_override_style(
354 $styles,
355 'wp-nux',
356 gutenberg_url( 'build/nux/style.css' ),
357 array( 'wp-components' ),
358 filemtime( gutenberg_dir_path() . 'build/nux/style.css' )
359 );
360 $styles->add_data( 'wp-nux', 'rtl', 'replace' );
361
362 gutenberg_override_style(
363 $styles,
364 'wp-block-library-theme',
365 gutenberg_url( 'build/block-library/theme.css' ),
366 array(),
367 filemtime( gutenberg_dir_path() . 'build/block-library/theme.css' )
368 );
369 $styles->add_data( 'wp-block-library-theme', 'rtl', 'replace' );
370
371 gutenberg_override_style(
372 $styles,
373 'wp-list-reusable-blocks',
374 gutenberg_url( 'build/list-reusable-blocks/style.css' ),
375 array( 'wp-components' ),
376 filemtime( gutenberg_dir_path() . 'build/list-reusable-blocks/style.css' )
377 );
378 $styles->add_data( 'wp-list-reusable-block', 'rtl', 'replace' );
379
380 gutenberg_override_style(
381 $styles,
382 'wp-edit-site',
383 gutenberg_url( 'build/edit-site/style.css' ),
384 array( 'wp-components', 'wp-block-editor', 'wp-edit-blocks' ),
385 filemtime( gutenberg_dir_path() . 'build/edit-site/style.css' )
386 );
387 $styles->add_data( 'wp-edit-site', 'rtl', 'replace' );
388
389 gutenberg_override_style(
390 $styles,
391 'wp-edit-widgets',
392 gutenberg_url( 'build/edit-widgets/style.css' ),
393 array( 'wp-components', 'wp-block-editor', 'wp-edit-blocks' ),
394 filemtime( gutenberg_dir_path() . 'build/edit-widgets/style.css' )
395 );
396 $styles->add_data( 'wp-edit-widgets', 'rtl', 'replace' );
397
398 gutenberg_override_style(
399 $styles,
400 'wp-block-directory',
401 gutenberg_url( 'build/block-directory/style.css' ),
402 array( 'wp-block-editor', 'wp-components' ),
403 filemtime( gutenberg_dir_path() . 'build/block-directory/style.css' )
404 );
405 $styles->add_data( 'wp-block-directory', 'rtl', 'replace' );
406 }
407 add_action( 'wp_default_styles', 'gutenberg_register_packages_styles' );
408
409 /**
410 * Registers common scripts and styles to be used as dependencies of the editor
411 * and plugins.
412 *
413 * @since 0.1.0
414 */
415 function gutenberg_enqueue_block_editor_assets() {
416 wp_add_inline_script(
417 'wp-api-fetch',
418 sprintf(
419 'wp.apiFetch.nonceMiddleware = wp.apiFetch.createNonceMiddleware( "%s" );' .
420 'wp.apiFetch.use( wp.apiFetch.nonceMiddleware );' .
421 'wp.apiFetch.nonceEndpoint = "%s";' .
422 'wp.apiFetch.use( wp.apiFetch.mediaUploadMiddleware );',
423 ( wp_installing() && ! is_multisite() ) ? '' : wp_create_nonce( 'wp_rest' ),
424 admin_url( 'admin-ajax.php?action=gutenberg_rest_nonce' )
425 ),
426 'after'
427 );
428
429 if ( defined( 'GUTENBERG_LIVE_RELOAD' ) && GUTENBERG_LIVE_RELOAD ) {
430 $live_reload_url = ( GUTENBERG_LIVE_RELOAD === true ) ? 'http://localhost:35729/livereload.js' : GUTENBERG_LIVE_RELOAD;
431
432 wp_enqueue_script(
433 'gutenberg-live-reload',
434 $live_reload_url
435 );
436 }
437 }
438 add_action( 'enqueue_block_editor_assets', 'gutenberg_enqueue_block_editor_assets' );
439
440 /**
441 * Retrieves a unique and reasonably short and human-friendly filename for a
442 * vendor script based on a URL and the script handle.
443 *
444 * @param string $handle The name of the script.
445 * @param string $src Full URL of the external script.
446 *
447 * @return string Script filename suitable for local caching.
448 *
449 * @since 0.1.0
450 */
451 function gutenberg_vendor_script_filename( $handle, $src ) {
452 $filename = basename( $src );
453 $match = preg_match(
454 '/^'
455 . '(?P<ignore>.*?)'
456 . '(?P<suffix>\.min)?'
457 . '(?P<extension>\.js)'
458 . '(?P<extra>.*)'
459 . '$/',
460 $filename,
461 $filename_pieces
462 );
463
464 $prefix = $handle;
465 $suffix = $match ? $filename_pieces['suffix'] : '';
466 $hash = substr( md5( $src ), 0, 8 );
467
468 return "${prefix}${suffix}.${hash}.js";
469 }
470
471 /**
472 * Registers a vendor script from a URL, preferring a locally cached version if
473 * possible, or downloading it if the cached version is unavailable or
474 * outdated.
475 *
476 * @param WP_Scripts $scripts WP_Scripts instance (passed by reference).
477 * @param string $handle Name of the script.
478 * @param string $src Full URL of the external script.
479 * @param array $deps Optional. An array of registered script handles this
480 * script depends on.
481 * @param string|bool|null $ver Optional. String specifying script version number, if it has one, which is added to the URL
482 * as a query string for cache busting purposes. If version is set to false, a version
483 * number is automatically added equal to current installed WordPress version.
484 * If set to null, no version is added.
485 * @param bool $in_footer Optional. Whether to enqueue the script before </body> instead of in the <head>.
486 * Default 'false'.
487 *
488 * @since 0.1.0
489 */
490 function gutenberg_register_vendor_script( &$scripts, $handle, $src, $deps = array(), $ver = null, $in_footer = false ) {
491 if ( defined( 'GUTENBERG_LOAD_VENDOR_SCRIPTS' ) && ! GUTENBERG_LOAD_VENDOR_SCRIPTS ) {
492 return;
493 }
494
495 $filename = gutenberg_vendor_script_filename( $handle, $src );
496
497 if ( defined( 'GUTENBERG_LIST_VENDOR_ASSETS' ) && GUTENBERG_LIST_VENDOR_ASSETS ) {
498 echo "$src|$filename\n";
499 return;
500 }
501
502 $full_path = gutenberg_dir_path() . 'vendor/' . $filename;
503
504 $needs_fetch = (
505 defined( 'GUTENBERG_DEVELOPMENT_MODE' ) && GUTENBERG_DEVELOPMENT_MODE && (
506 ! file_exists( $full_path ) ||
507 time() - filemtime( $full_path ) >= DAY_IN_SECONDS
508 )
509 );
510
511 if ( $needs_fetch ) {
512 // Determine whether we can write to this file. If not, don't waste
513 // time doing a network request.
514 // @codingStandardsIgnoreStart
515 $f = @fopen( $full_path, 'a' );
516 // @codingStandardsIgnoreEnd
517 if ( ! $f ) {
518 // Failed to open the file for writing, probably due to server
519 // permissions. Enqueue the script directly from the URL instead.
520 gutenberg_override_script( $scripts, $handle, $src, $deps, $ver, $in_footer );
521 return;
522 }
523 fclose( $f );
524 $response = wp_remote_get( $src );
525 if ( wp_remote_retrieve_response_code( $response ) === 200 ) {
526 $f = fopen( $full_path, 'w' );
527 fwrite( $f, wp_remote_retrieve_body( $response ) );
528 fclose( $f );
529 } elseif ( ! filesize( $full_path ) ) {
530 // The request failed. If the file is already cached, continue to
531 // use this file. If not, then unlink the 0 byte file, and enqueue
532 // the script directly from the URL.
533 gutenberg_override_script( $scripts, $handle, $src, $deps, $ver, $in_footer );
534 unlink( $full_path );
535 return;
536 }
537 }
538 gutenberg_override_script(
539 $scripts,
540 $handle,
541 gutenberg_url( 'vendor/' . $filename ),
542 $deps,
543 $ver,
544 $in_footer
545 );
546 }
547
548 /**
549 * Extends block editor settings to include Gutenberg's `editor-styles.css` as
550 * taking precedent those styles shipped with core.
551 *
552 * @param array $settings Default editor settings.
553 *
554 * @return array Filtered editor settings.
555 */
556 function gutenberg_extend_block_editor_styles( $settings ) {
557 $editor_styles_file = gutenberg_dir_path() . 'build/editor/editor-styles.css';
558
559 /*
560 * If, for whatever reason, the built editor styles do not exist, avoid
561 * override and fall back to the default.
562 */
563 if ( ! file_exists( $editor_styles_file ) ) {
564 return $settings;
565 }
566
567 if ( empty( $settings['styles'] ) ) {
568 $settings['styles'] = array();
569 } else {
570 /*
571 * The styles setting is an array of CSS strings, so there is no direct
572 * way to find the default styles. To maximize stability, load (again)
573 * the default styles from disk and find its place in the array.
574 *
575 * See: https://github.com/WordPress/wordpress-develop/blob/5.0.3/src/wp-admin/edit-form-blocks.php#L168-L175
576 */
577
578 $default_styles = file_get_contents(
579 ABSPATH . WPINC . '/css/dist/editor/editor-styles.css'
580 );
581
582 /*
583 * Iterate backwards from the end of the array since the preferred
584 * insertion point in case not found is prepended as first entry.
585 */
586 for ( $i = count( $settings['styles'] ) - 1; $i >= 0; $i-- ) {
587 if ( isset( $settings['styles'][ $i ]['css'] ) &&
588 $default_styles === $settings['styles'][ $i ]['css'] ) {
589 break;
590 }
591 }
592 }
593
594 $editor_styles = array(
595 'css' => file_get_contents( $editor_styles_file ),
596 );
597
598 // Substitute default styles if found. Otherwise, prepend to setting array.
599 if ( isset( $i ) && $i >= 0 ) {
600 $settings['styles'][ $i ] = $editor_styles;
601 } else {
602 array_unshift( $settings['styles'], $editor_styles );
603 }
604
605 return $settings;
606 }
607 add_filter( 'block_editor_settings', 'gutenberg_extend_block_editor_styles' );
608
609 /**
610 * Extends block editor settings to include a list of image dimensions per size.
611 *
612 * @param array $settings Default editor settings.
613 *
614 * @return array Filtered editor settings.
615 */
616 function gutenberg_extend_settings_image_dimensions( $settings ) {
617 $image_dimensions = array();
618 $all_sizes = wp_get_registered_image_subsizes();
619 foreach ( $settings['imageSizes'] as $size ) {
620 $key = $size['slug'];
621 if ( isset( $all_sizes[ $key ] ) ) {
622 $image_dimensions[ $key ] = $all_sizes[ $key ];
623 }
624 }
625 $settings['imageDimensions'] = $image_dimensions;
626 return $settings;
627 }
628 add_filter( 'block_editor_settings', 'gutenberg_extend_settings_image_dimensions' );
629
630 /**
631 * Load a block pattern by name.
632 *
633 * @param string $name Block Pattern File name.
634 *
635 * @return array Block Pattern Array.
636 */
637 function gutenberg_load_block_pattern( $name ) {
638 return json_decode(
639 file_get_contents( __DIR__ . '/patterns/' . $name . '.json' ),
640 true
641 );
642 }
643
644 /**
645 * Extends block editor settings to include a list of default block patterns.
646 *
647 * @param array $settings Default editor settings.
648 *
649 * @return array Filtered editor settings.
650 */
651 function gutenberg_extend_settings_block_patterns( $settings ) {
652 $block_patterns = [
653 gutenberg_load_block_pattern( 'text-two-columns' ),
654 gutenberg_load_block_pattern( 'two-buttons' ),
655 gutenberg_load_block_pattern( 'cover-abc' ),
656 gutenberg_load_block_pattern( 'two-images' ),
657 ];
658 $settings['__experimentalBlockPatterns'] = $block_patterns;
659 return $settings;
660 }
661 add_filter( 'block_editor_settings', 'gutenberg_extend_settings_block_patterns' );
662