PluginProbe
Gutenberg / 24.1.0
Gutenberg v24.1.0
24.1.0 24.0.0 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 All 404 releases
gutenberg / lib / experimental / class-wp-rest-block-editor-settings-controller.php

class-wp-rest-block-editor-settings-controller.php in Gutenberg 24.1.0, at lib/experimental/class-wp-rest-block-editor-settings-controller.php

681 lines 24.8 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * REST API: WP_REST_Block_Editor_Settings_Controller class
4 *
5 * @package WordPress
6 * @subpackage REST_API
7 */
8
9 if ( ! class_exists( 'WP_REST_Block_Editor_Settings_Controller' ) ) {
10
11 /**
12 * Core class used to retrieve the block editor settings via the REST API.
13 *
14 * @see WP_REST_Controller
15 */
16 class WP_REST_Block_Editor_Settings_Controller extends WP_REST_Controller {
17 /**
18 * Constructs the controller.
19 */
20 public function __construct() {
21 $this->namespace = 'wp-block-editor/v1';
22 $this->rest_base = 'settings';
23 }
24
25 /**
26 * Registers the necessary REST API routes.
27 */
28 public function register_routes() {
29 register_rest_route(
30 $this->namespace,
31 '/' . $this->rest_base,
32 array(
33 array(
34 'methods' => WP_REST_Server::READABLE,
35 'callback' => array( $this, 'get_items' ),
36 'permission_callback' => array( $this, 'get_items_permissions_check' ),
37 ),
38 'schema' => array( $this, 'get_public_item_schema' ),
39 )
40 );
41
42 register_rest_route(
43 $this->namespace,
44 '/assets',
45 array(
46 array(
47 'methods' => WP_REST_Server::READABLE,
48 'callback' => array( $this, 'get_assets' ),
49 'permission_callback' => array( $this, 'get_items_permissions_check' ),
50 ),
51 'schema' => array( $this, 'get_assets_schema' ),
52 )
53 );
54 }
55
56 /**
57 * Checks whether a given request has permission to read block editor settings
58 *
59 * @since 5.8.0
60 *
61 * @param WP_REST_Request $request Full details about the request.
62 *
63 * @return WP_Error|bool True if the request has permission, WP_Error object otherwise.
64 */
65 public function get_items_permissions_check( $request ) {// phpcs:ignore VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable
66 if ( current_user_can( 'edit_posts' ) ) {
67 return true;
68 }
69
70 foreach ( get_post_types( array( 'show_in_rest' => true ), 'objects' ) as $post_type ) {
71 if ( current_user_can( $post_type->cap->edit_posts ) ) {
72 return true;
73 }
74 }
75
76 return new WP_Error(
77 'rest_cannot_read_block_editor_settings',
78 __( 'Sorry, you are not allowed to read the block editor settings.', 'gutenberg' ),
79 array( 'status' => rest_authorization_required_code() )
80 );
81 }
82
83 /**
84 * Returns the block editor's settings
85 *
86 * @since 5.8.0
87 *
88 * @param WP_REST_Request $request Full details about the request.
89 *
90 * @return WP_Error|WP_REST_Response Response object on success, or WP_Error object on failure.
91 */
92 public function get_items( $request ) { // phpcs:ignore VariableAnalysis.CodeAnalysis.VariableAnalysis
93 // Simplified context handling: mobile vs default.
94 // Only 'mobile' context is special; everything else uses the default editor context.
95 $context_param = $request->get_param( 'context' );
96 $editor_context_name = 'mobile' === $context_param ? 'core/mobile' : 'core/edit-post';
97
98 // Apply mobile-specific settings filter only for mobile context.
99 if ( 'mobile' === $context_param ) {
100 add_filter( 'block_editor_settings_all', 'gutenberg_get_block_editor_settings_mobile', PHP_INT_MAX );
101 }
102
103 $editor_context = new WP_Block_Editor_Context( array( 'name' => $editor_context_name ) );
104 $settings = get_block_editor_settings( array(), $editor_context );
105
106 if ( 'mobile' === $context_param ) {
107 remove_filter( 'block_editor_settings_all', 'gutenberg_get_block_editor_settings_mobile', PHP_INT_MAX );
108 }
109
110 return rest_ensure_response( $settings );
111 }
112
113 /**
114 * Retrieves the block editor's settings schema, conforming to JSON Schema.
115 *
116 * @since 5.8.0
117 *
118 * @return array Item schema data.
119 */
120 public function get_item_schema() {
121 if ( $this->schema ) {
122 return $this->add_additional_fields_schema( $this->schema );
123 }
124
125 $schema = array(
126 '$schema' => 'http://json-schema.org/draft-04/schema#',
127 'title' => 'block-editor-settings-item',
128 'type' => 'object',
129 'properties' => array(
130 '__unstableEnableFullSiteEditingBlocks' => array(
131 'description' => __( 'Enables experimental Site Editor blocks', 'gutenberg' ),
132 'type' => 'boolean',
133 'context' => array( 'default' ),
134 ),
135
136 'styles' => array(
137 'description' => __( 'Editor styles', 'gutenberg' ),
138 'type' => 'array',
139 'context' => array( 'default' ),
140 ),
141
142 'supportsTemplateMode' => array(
143 'description' => __( 'Indicates whether the current theme supports block-based templates.', 'gutenberg' ),
144 'type' => 'boolean',
145 'context' => array( 'default' ),
146 ),
147
148 'supportsLayout' => array(
149 'description' => __( 'Enable/disable layouts support in container blocks.', 'gutenberg' ),
150 'type' => 'boolean',
151 'context' => array( 'default' ),
152 ),
153
154 'widgetTypesToHideFromLegacyWidgetBlock' => array(
155 'description' => __( 'Widget types to hide from Legacy Widget block.', 'gutenberg' ),
156 'type' => 'array',
157 'context' => array( 'default' ),
158 ),
159
160 '__experimentalFeatures' => array(
161 'description' => __( 'Settings consolidated from core, theme, and user origins.', 'gutenberg' ),
162 'type' => 'object',
163 'context' => array( 'default', 'mobile' ),
164 ),
165
166 '__experimentalStyles' => array(
167 'description' => __( 'Styles consolidated from core, theme, and user origins.', 'gutenberg' ),
168 'type' => 'object',
169 'context' => array( 'mobile' ),
170 ),
171
172 '__experimentalEnableQuoteBlockV2' => array(
173 'description' => __( 'Whether the V2 of the quote block that uses inner blocks should be enabled.', 'gutenberg' ),
174 'type' => 'boolean',
175 'context' => array( 'mobile' ),
176 ),
177
178 '__experimentalEnableListBlockV2' => array(
179 'description' => __( 'Whether the V2 of the list block that uses inner blocks should be enabled.', 'gutenberg' ),
180 'type' => 'boolean',
181 'context' => array( 'mobile' ),
182 ),
183
184 'alignWide' => array(
185 'description' => __( 'Enable/Disable Wide/Full Alignments.', 'gutenberg' ),
186 'type' => 'boolean',
187 'context' => array( 'default' ),
188 ),
189
190 'allowedBlockTypes' => array(
191 'description' => __( 'List of allowed block types.', 'gutenberg' ),
192 'type' => 'boolean',
193 'context' => array( 'default' ),
194 ),
195
196 'allowedMimeTypes' => array(
197 'description' => __( 'List of allowed mime types and file extensions.', 'gutenberg' ),
198 'type' => 'object',
199 'context' => array( 'default' ),
200 ),
201
202 'blockCategories' => array(
203 'description' => __( 'Returns all the categories for block types that will be shown in the block editor.', 'gutenberg' ),
204 'type' => 'array',
205 'context' => array( 'default' ),
206 ),
207
208 'blockInspectorTabs' => array(
209 'description' => __( 'Block inspector tab display overrides.', 'gutenberg' ),
210 'type' => 'object',
211 'context' => array( 'default' ),
212 ),
213
214 'disableCustomColors' => array(
215 'description' => __( 'Disables custom colors.', 'gutenberg' ),
216 'type' => 'boolean',
217 'context' => array( 'default' ),
218 ),
219
220 'disableCustomFontSizes' => array(
221 'description' => __( 'Disables custom font size.', 'gutenberg' ),
222 'type' => 'boolean',
223 'context' => array( 'default' ),
224 ),
225
226 'disableCustomGradients' => array(
227 'description' => __( 'Disables custom font size.', 'gutenberg' ),
228 'type' => 'boolean',
229 'context' => array( 'default' ),
230 ),
231
232 'disableLayoutStyles' => array(
233 'description' => __( 'Disables output of layout styles.', 'gutenberg' ),
234 'type' => 'boolean',
235 'context' => array( 'default' ),
236 ),
237
238 'enableCustomLineHeight' => array(
239 'description' => __( 'Enables custom line height.', 'gutenberg' ),
240 'type' => 'boolean',
241 'context' => array( 'default' ),
242 ),
243
244 'enableCustomSpacing' => array(
245 'description' => __( 'Enables custom spacing.', 'gutenberg' ),
246 'type' => 'boolean',
247 'context' => array( 'default' ),
248 ),
249
250 'enableCustomUnits' => array(
251 'description' => __( 'Enables custom units.', 'gutenberg' ),
252 'type' => 'boolean',
253 'context' => array( 'default' ),
254 ),
255
256 'isRTL' => array(
257 'description' => __( 'Determines whether the current locale is right-to-left (RTL).', 'gutenberg' ),
258 'type' => 'boolean',
259 'context' => array( 'default' ),
260 ),
261
262 'imageDefaultSize' => array(
263 'description' => __( 'Default size for images.', 'gutenberg' ),
264 'type' => 'string',
265 'context' => array( 'default' ),
266 ),
267
268 'imageDimensions' => array(
269 'description' => __( 'Available image dimensions.', 'gutenberg' ),
270 'type' => 'object',
271 'context' => array( 'default' ),
272 ),
273
274 'imageEditing' => array(
275 'description' => __( 'Determines whether the image editing feature is enabled.', 'gutenberg' ),
276 'type' => 'boolean',
277 'context' => array( 'default' ),
278 ),
279
280 'imageSizes' => array(
281 'description' => __( 'Available image sizes.', 'gutenberg' ),
282 'type' => 'array',
283 'context' => array( 'default' ),
284 ),
285
286 'maxUploadFileSize' => array(
287 'description' => __( 'Maximum upload size in bytes allowed for the site.', 'gutenberg' ),
288 'type' => 'number',
289 'context' => array( 'default' ),
290 ),
291
292 'colors' => array(
293 'description' => __( 'Active theme color palette.', 'gutenberg' ),
294 'type' => 'array',
295 'context' => array( 'default' ),
296 ),
297
298 'fontSizes' => array(
299 'description' => __( 'Active theme font sizes.', 'gutenberg' ),
300 'type' => 'array',
301 'context' => array( 'default' ),
302 ),
303
304 'gradients' => array(
305 'description' => __( 'Active theme gradients.', 'gutenberg' ),
306 'type' => 'array',
307 'context' => array( 'default' ),
308 ),
309 'spacingSizes' => array(
310 'description' => __( 'Active theme spacing sizes.', 'gutenberg' ),
311 'type' => 'array',
312 'context' => array( 'default' ),
313 ),
314 'spacingScale' => array(
315 'description' => __( 'Active theme spacing scale.', 'gutenberg' ),
316 'type' => 'array',
317 'context' => array( 'default' ),
318 ),
319 'disableCustomSpacingSizes' => array(
320 'description' => __( 'Disables custom spacing sizes.', 'gutenberg' ),
321 'type' => 'boolean',
322 'context' => array( 'default' ),
323 ),
324 ),
325 );
326
327 $this->schema = $schema;
328
329 return $this->add_additional_fields_schema( $this->schema );
330 }
331
332 /**
333 * Retrieves editor assets (scripts, styles, and inline content).
334 *
335 * @since Gutenberg 5.8.0
336 *
337 * @param WP_REST_Request $request Full details about the request.
338 * @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure.
339 */
340 public function get_assets( $request ) { // phpcs:ignore VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable
341 // Load WordPress admin environment.
342 $this->load_admin_environment();
343
344 // Set up the block editor context.
345 set_current_screen();
346 $current_screen = get_current_screen();
347 if ( $current_screen ) {
348 $current_screen->is_block_editor( true );
349 }
350
351 // phpcs:ignore WordPress.WP.GlobalVariablesOverride.Prohibited
352 $hook_suffix = 'block-editor-assets';
353
354 // Remove unwanted scripts/styles.
355 remove_action( 'admin_enqueue_scripts', 'wp_enqueue_command_palette_assets' );
356 remove_action( 'admin_enqueue_scripts', 'wp_auth_check_load' );
357 remove_action( 'admin_print_scripts', 'print_emoji_detection_script' );
358 remove_action( 'admin_print_styles', 'print_emoji_styles' );
359
360 // Preload blocks - this creates inline scripts.
361 $server_block_settings = get_block_editor_server_block_settings();
362 wp_add_inline_script(
363 'wp-block-library',
364 'wp.blocks.unstable__bootstrapServerSideBlockDefinitions(' . wp_json_encode( $server_block_settings, JSON_HEX_TAG | JSON_UNESCAPED_SLASHES ) . ');',
365 'before'
366 );
367
368 // Preload server-registered block bindings sources.
369 $registered_sources = get_all_registered_block_bindings_sources();
370 if ( ! empty( $registered_sources ) ) {
371 $filtered_sources = array();
372 foreach ( $registered_sources as $source ) {
373 $filtered_sources[] = array(
374 'name' => $source->name,
375 'label' => $source->label,
376 'usesContext' => $source->uses_context,
377 );
378 }
379 $script = sprintf( 'for ( const source of %s ) { wp.blocks.registerBlockBindingsSource( source ); }', wp_json_encode( $filtered_sources, JSON_HEX_TAG | JSON_UNESCAPED_SLASHES ) );
380 wp_add_inline_script(
381 'wp-block-library',
382 $script,
383 'before'
384 );
385 }
386
387 $load_blocks_scripts = 'wp.blockLibrary.registerCoreBlocks( wp.blockLibrary.__experimentalGetCoreBlocks().filter( ( block ) => block.name !== "core/freeform" ) );';
388 wp_add_inline_script(
389 'wp-block-library',
390 $load_blocks_scripts,
391 'after'
392 );
393
394 // Enqueue editor assets.
395 wp_enqueue_script( 'wp-format-library' );
396 wp_enqueue_script( 'wp-block-library' );
397 wp_enqueue_style( 'wp-editor' );
398 wp_enqueue_style( 'wp-block-library' );
399 wp_enqueue_style( 'wp-format-library' );
400 wp_enqueue_media();
401
402 /*
403 * Block style variations provided by the theme's theme.json
404 * partials are registered lazily, when the theme JSON resolver
405 * first runs in a request. Nothing has run it in this REST
406 * request yet, so prime it — otherwise the block styles registry
407 * is still empty when `enqueue_editor_block_styles_assets()`
408 * serializes it into the `wp-block-styles` inline script below.
409 */
410 WP_Theme_JSON_Resolver_Gutenberg::get_theme_data();
411
412 do_action( 'enqueue_block_editor_assets' ); // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound
413
414 // Never allow old admin styles as a dependency.
415 wp_deregister_style( 'common' );
416 wp_deregister_style( 'forms' );
417
418 // Trigger rendering hooks to capture all assets.
419 ob_start();
420 do_action( 'admin_enqueue_scripts', $hook_suffix ); // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound
421 do_action( "admin_print_styles-{$hook_suffix}" ); // phpcs:ignore WordPress.NamingConventions.ValidHookName.UseUnderscores, WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound
422 do_action( 'admin_print_styles' ); // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound
423 do_action( "admin_print_scripts-{$hook_suffix}" ); // phpcs:ignore WordPress.NamingConventions.ValidHookName.UseUnderscores, WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound
424 do_action( 'admin_print_scripts' ); // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound
425 do_action( "admin_head-{$hook_suffix}" ); // phpcs:ignore WordPress.NamingConventions.ValidHookName.UseUnderscores, WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound
426 do_action( 'admin_head' ); // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound
427 do_action( 'admin_footer', '' ); // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound
428 do_action( 'wp_print_footer_scripts' ); // phpcs:ignore WordPress.NamingConventions.ValidHookName.UseUnderscores,WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound
429 do_action( "admin_print_footer_scripts-{$hook_suffix}" ); // phpcs:ignore WordPress.NamingConventions.ValidHookName.UseUnderscores, WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound
430 do_action( 'admin_print_footer_scripts' ); // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound
431 do_action( "admin_footer-{$hook_suffix}" ); // phpcs:ignore WordPress.NamingConventions.ValidHookName.UseUnderscores, WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound
432 $html_output = ob_get_clean();
433 // Extract all script tags with type="text/html" (WordPress media templates use text/html, not text/template).
434 // Templates are already in html_output from the admin_footer hook.
435 $html_templates = array();
436 if ( preg_match_all( '/<script[^>]*type\s*=\s*["\']text\/html["\'][^>]*>.*?<\/script>/is', $html_output, $matches ) ) {
437 $html_templates = $matches[0];
438 }
439
440 // Process the captured assets.
441 return rest_ensure_response( $this->process_assets( $html_templates ) );
442 }
443
444 /**
445 * Process WordPress assets and return structured data.
446 *
447 * @since Gutenberg 5.8.0
448 *
449 * @global WP_Scripts $wp_scripts WordPress scripts objects.
450 * @global WP_Styles $wp_styles WordPress styles objects.
451 *
452 * @param array $html_templates Optional. Array of HTML template strings.
453 * @return array Structured asset data.
454 */
455 private function process_assets( $html_templates = array() ) {
456 global $wp_scripts, $wp_styles;
457
458 $styles_data = array();
459 $scripts_data = array();
460 $inline_styles = array(
461 'before' => array(),
462 'after' => array(),
463 );
464 $inline_scripts = array(
465 'before' => array(),
466 'after' => array(),
467 );
468
469 // Get boot module asset file for dependencies.
470 $boot_asset_file = include __DIR__ . '/../../build/modules/boot/index.min.asset.php';
471 $boot_dependencies = $boot_asset_file['dependencies'] ?? array();
472
473 // Get all dependencies that should be excluded (boot dependencies + their deep dependencies).
474 $excluded_scripts = $this->get_all_dependencies( $boot_dependencies, $wp_scripts );
475 $excluded_styles = $this->get_all_dependencies( array( 'wp-components', 'wp-commands', 'dashicons' ), $wp_styles );
476
477 // Process styles - include all dependencies of queued styles.
478 $all_needed_styles = array();
479 foreach ( $wp_styles->queue as $handle ) {
480 $all_needed_styles = array_merge( $all_needed_styles, $this->get_all_dependencies( array( $handle ), $wp_styles ) );
481 }
482 $all_needed_styles = array_unique( $all_needed_styles );
483
484 foreach ( $all_needed_styles as $handle ) {
485 // Skip styles that are already loaded by the boot module.
486 if ( in_array( $handle, $excluded_styles, true ) ) {
487 continue;
488 }
489
490 if ( isset( $wp_styles->registered[ $handle ] ) ) {
491 $style = $wp_styles->registered[ $handle ];
492 $styles_data[ $handle ] = array(
493 'src' => $style->src,
494 'deps' => $style->deps,
495 'version' => $style->ver,
496 'media' => $style->args,
497 );
498
499 $inline_style = $wp_styles->get_data( $handle, 'after' );
500 if ( ! empty( $inline_style ) ) {
501 $inline_styles['after'][ $handle ] = $inline_style;
502 }
503 $inline_style = $wp_styles->get_data( $handle, 'before' );
504 if ( ! empty( $inline_style ) ) {
505 $inline_styles['before'][ $handle ] = $inline_style;
506 }
507 }
508 }
509
510 // Process scripts - include all dependencies of queued scripts.
511 $all_needed_scripts = array();
512 foreach ( $wp_scripts->queue as $handle ) {
513 $all_needed_scripts = array_merge( $all_needed_scripts, $this->get_all_dependencies( array( $handle ), $wp_scripts ) );
514 }
515 $all_needed_scripts = array_unique( $all_needed_scripts );
516
517 foreach ( $all_needed_scripts as $handle ) {
518 // Skip scripts that are already loaded by the boot module.
519 if ( in_array( $handle, $excluded_scripts, true ) ) {
520 continue;
521 }
522
523 if ( isset( $wp_scripts->registered[ $handle ] ) ) {
524 $script = $wp_scripts->registered[ $handle ];
525 $scripts_data[ $handle ] = array(
526 'src' => $script->src,
527 'deps' => $script->deps,
528 'version' => $script->ver,
529 'in_footer' => isset( $script->extra['group'] ) && 1 === $script->extra['group'],
530 );
531
532 // Get inline scripts using proper WordPress methods.
533 $before_script = $wp_scripts->get_inline_script_data( $handle, 'before' );
534 $after_script = $wp_scripts->get_inline_script_data( $handle, 'after' );
535
536 // Get extra script data (localized data).
537 $extra_script = $wp_scripts->print_extra_script( $handle, false );
538
539 // Store before scripts (includes extra/localized data).
540 $before_content = '';
541 if ( ! empty( $before_script ) ) {
542 $before_content .= $before_script . "\n";
543 }
544 if ( ! empty( $extra_script ) ) {
545 $before_content .= $extra_script . "\n";
546 }
547
548 if ( ! empty( $before_content ) ) {
549 $inline_scripts['before'][ $handle ] = trim( $before_content );
550 }
551
552 // Store after scripts separately.
553 if ( ! empty( $after_script ) ) {
554 $inline_scripts['after'][ $handle ] = trim( $after_script );
555 }
556 }
557 }
558
559 // Build an import map from registered script modules.
560 // the import map need to be dynamically extended in the frontend.
561 $script_modules = wp_script_modules();
562 $registered = array();
563 $reflection = new ReflectionClass( $script_modules );
564 $property = $reflection->getProperty( 'registered' );
565 /*
566 * ReflectionProperty::setAccessible is:
567 * - needed until 8.1.0, as property `registered` is private.
568 * - redundant as of 8.1.0, which made non-public reflection accessible by default.
569 * - deprecated as of 8.5.0.
570 */
571 if ( PHP_VERSION_ID < 80100 ) {
572 $property->setAccessible( true );
573 }
574 $registered = $property->getValue( $script_modules );
575 $import_map = array();
576 foreach ( $registered as $id => $module ) {
577 // Handle both array and object formats.
578 if ( is_array( $module ) && isset( $module['src'] ) ) {
579 $import_map[ $id ] = $module['src'];
580 } elseif ( is_object( $module ) && isset( $module->src ) ) {
581 $import_map[ $id ] = $module->src;
582 }
583 }
584
585 return array(
586 'scripts' => $scripts_data,
587 'styles' => $styles_data,
588 'inline_scripts' => $inline_scripts,
589 'inline_styles' => $inline_styles,
590 'html_templates' => $html_templates,
591 'script_modules' => $import_map,
592 );
593 }
594
595 /**
596 * Get all dependencies recursively (works for both scripts and styles).
597 *
598 * @since Gutenberg 5.8.0
599 *
600 * @param array|string $handles The handles to get dependencies for.
601 * @param WP_Dependencies $wp_assets The WordPress dependencies object.
602 * @return array Array of all dependencies.
603 */
604 private function get_all_dependencies( $handles, $wp_assets ) {
605 $all_deps = array();
606 $handles = (array) $handles;
607
608 foreach ( $handles as $handle ) {
609 if ( isset( $wp_assets->registered[ $handle ] ) ) {
610 $asset = $wp_assets->registered[ $handle ];
611 $all_deps[] = $handle;
612
613 if ( ! empty( $asset->deps ) ) {
614 $child_deps = $this->get_all_dependencies( $asset->deps, $wp_assets );
615 $all_deps = array_merge( $all_deps, $child_deps );
616 }
617 }
618 }
619
620 return array_unique( $all_deps );
621 }
622
623 /**
624 * Load WordPress admin environment and required functions.
625 *
626 * This mirrors the initialization that happens in wp-admin context
627 * to ensure all necessary functions and hooks are available.
628 *
629 * @since Gutenberg 5.8.0
630 */
631 private function load_admin_environment() {
632 // Load core admin files that provide essential functions.
633 require_once ABSPATH . 'wp-admin/includes/admin.php';
634 }
635
636 /**
637 * Retrieves the editor assets schema, conforming to JSON Schema.
638 *
639 * @since Gutenberg 5.8.0
640 *
641 * @return array Item schema data.
642 */
643 public function get_assets_schema() {
644 $schema = array(
645 '$schema' => 'http://json-schema.org/draft-04/schema#',
646 'title' => 'block-editor-assets',
647 'type' => 'object',
648 'properties' => array(
649 'scripts' => array(
650 'description' => __( 'Editor scripts data.', 'gutenberg' ),
651 'type' => 'object',
652 'readonly' => true,
653 ),
654 'styles' => array(
655 'description' => __( 'Editor styles data.', 'gutenberg' ),
656 'type' => 'object',
657 'readonly' => true,
658 ),
659 'inline_scripts' => array(
660 'description' => __( 'Inline scripts for editor assets.', 'gutenberg' ),
661 'type' => 'object',
662 'readonly' => true,
663 ),
664 'inline_styles' => array(
665 'description' => __( 'Inline styles for editor assets.', 'gutenberg' ),
666 'type' => 'object',
667 'readonly' => true,
668 ),
669 'script_modules' => array(
670 'description' => __( 'Script modules to load into the import map.', 'gutenberg' ),
671 'type' => 'object',
672 'readonly' => true,
673 ),
674 ),
675 );
676
677 return $this->add_additional_fields_schema( $schema );
678 }
679 }
680 }
681