1<?php
2/**
3 * Used to set up all core blocks used with the block editor.
4 *
5 * @package WordPress
6 */
7
8// Don't load directly.
9if ( ! defined( 'ABSPATH' ) ) {
10 die( '-1' );
11}
12
13define( 'BLOCKS_PATH', ABSPATH . WPINC . '/blocks/' );
14
15// Include files required for core blocks registration.
16require BLOCKS_PATH . 'legacy-widget.php';
17require BLOCKS_PATH . 'widget-group.php';
18require BLOCKS_PATH . 'require-dynamic-blocks.php';
19
20/**
21 * Registers core block style handles.
22 *
23 * While {@see register_block_style_handle()} is typically used for that, the way it is
24 * implemented is inefficient for core block styles. Registering those style handles here
25 * avoids unnecessary logic and filesystem lookups in the other function.
26 *
27 * @since 6.3.0
28 */
29function register_core_block_style_handles() {
30 $wp_version = wp_get_wp_version();
31
32 if ( ! wp_should_load_separate_core_block_assets() ) {
33 return;
34 }
35
36 $blocks_url = includes_url( 'blocks/' );
37 $suffix = wp_scripts_get_suffix();
38 $wp_styles = wp_styles();
39 $style_fields = array(
40 'style' => 'style',
41 'editorStyle' => 'editor',
42 );
43
44 static $core_blocks_meta;
45 if ( ! $core_blocks_meta ) {
46 $core_blocks_meta = require BLOCKS_PATH . 'blocks-json.php';
47 }
48
49 $files = false;
50 $transient_name = 'wp_core_block_css_files';
51
52 /*
53 * Ignore transient cache when the development mode is set to 'core'. Why? To avoid interfering with
54 * the core developer's workflow.
55 */
56 $can_use_cached = ! wp_is_development_mode( 'core' );
57
58 if ( $can_use_cached ) {
59 $cached_files = get_transient( $transient_name );
60
61 // Check the validity of cached values by checking against the current WordPress version.
62 if (
63 is_array( $cached_files )
64 && isset( $cached_files['version'] )
65 && $cached_files['version'] === $wp_version
66 && isset( $cached_files['files'] )
67 ) {
68 $files = $cached_files['files'];
69 }
70 }
71
72 if ( ! $files ) {
73 $files = glob( wp_normalize_path( BLOCKS_PATH . '**/**.css' ) );
74
75 // Normalize BLOCKS_PATH prior to substitution for Windows environments.
76 $normalized_blocks_path = wp_normalize_path( BLOCKS_PATH );
77
78 $files = array_map(
79 static function ( $file ) use ( $normalized_blocks_path ) {
80 return str_replace( $normalized_blocks_path, '', $file );
81 },
82 $files
83 );
84
85 // Save core block style paths in cache when not in development mode.
86 if ( $can_use_cached ) {
87 set_transient(
88 $transient_name,
89 array(
90 'version' => $wp_version,
91 'files' => $files,
92 )
93 );
94 }
95 }
96
97 $register_style = static function ( $name, $filename, $style_handle ) use ( $blocks_url, $suffix, $wp_styles, $files ) {
98 $style_path = "{$name}/{$filename}{$suffix}.css";
99 $path = wp_normalize_path( BLOCKS_PATH . $style_path );
100
101 if ( ! in_array( $style_path, $files, true ) ) {
102 $wp_styles->add(
103 $style_handle,
104 false
105 );
106 return;
107 }
108
109 $wp_styles->add( $style_handle, $blocks_url . $style_path );
110 $wp_styles->add_data( $style_handle, 'path', $path );
111
112 $rtl_file = "{$name}/{$filename}-rtl{$suffix}.css";
113 if ( is_rtl() && in_array( $rtl_file, $files, true ) ) {
114 $wp_styles->add_data( $style_handle, 'rtl', 'replace' );
115 $wp_styles->add_data( $style_handle, 'suffix', $suffix );
116 $wp_styles->add_data( $style_handle, 'path', str_replace( "{$suffix}.css", "-rtl{$suffix}.css", $path ) );
117 }
118 };
119
120 foreach ( $core_blocks_meta as $name => $schema ) {
121 /** This filter is documented in wp-includes/blocks.php */
122 $schema = apply_filters( 'block_type_metadata', $schema );
123
124 // Backfill these properties similar to `register_block_type_from_metadata()`.
125 if ( ! isset( $schema['style'] ) ) {
126 $schema['style'] = "wp-block-{$name}";
127 }
128 if ( ! isset( $schema['editorStyle'] ) ) {
129 $schema['editorStyle'] = "wp-block-{$name}-editor";
130 }
131
132 // Register block theme styles.
133 $register_style( $name, 'theme', "wp-block-{$name}-theme" );
134
135 foreach ( $style_fields as $style_field => $filename ) {
136 $style_handle = $schema[ $style_field ];
137 if ( is_array( $style_handle ) ) {
138 continue;
139 }
140 $register_style( $name, $filename, $style_handle );
141 }
142 }
143}
144add_action( 'init', 'register_core_block_style_handles', 9 );
145
146/**
147 * Registers core block types using metadata files.
148 * Dynamic core blocks are registered separately.
149 *
150 * @since 5.5.0
151 */
152function register_core_block_types_from_metadata() {
153 $block_folders = require BLOCKS_PATH . 'require-static-blocks.php';
154 foreach ( $block_folders as $block_folder ) {
155 register_block_type_from_metadata(
156 BLOCKS_PATH . $block_folder
157 );
158 }
159}
160add_action( 'init', 'register_core_block_types_from_metadata' );
161
162/**
163 * Registers the core block metadata collection.
164 *
165 * This function is hooked into the 'init' action with a priority of 9,
166 * ensuring that the core block metadata is registered before the regular
167 * block initialization that happens at priority 10.
168 *
169 * @since 6.7.0
170 */
171function wp_register_core_block_metadata_collection() {
172 wp_register_block_metadata_collection(
173 BLOCKS_PATH,
174 BLOCKS_PATH . 'blocks-json.php'
175 );
176}
177add_action( 'init', 'wp_register_core_block_metadata_collection', 9 );
178