PluginProbe
Gutenberg / 24.0.0
Gutenberg v24.0.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 12.6.0 All 403 releases
gutenberg / build / pages / experiments / page.php

page.php in Gutenberg 24.0.0, at build/pages/experiments/page.php

358 lines 10.9 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Page: experiments
4 * Auto-generated by build process.
5 * Do not edit this file manually.
6 *
7 * @package gutenberg
8 */
9
10 // Global storage for experiments routes and menu items
11 global $gutenberg_experiments_routes, $gutenberg_experiments_menu_items;
12 $gutenberg_experiments_routes = array();
13 $gutenberg_experiments_menu_items = array();
14
15 /**
16 * Register a route for the experiments page.
17 *
18 * @param string $path Route path (e.g., '/types/$type/edit/$id').
19 * @param string|null $content_module Script module ID for content (stage/inspector).
20 * @param string|null $route_module Script module ID for route lifecycle hooks.
21 */
22 function gutenberg_register_experiments_route( $path, $content_module = null, $route_module = null ) {
23 global $gutenberg_experiments_routes;
24
25 $route = array( 'path' => $path );
26 if ( ! empty( $content_module ) ) {
27 $route['content_module'] = $content_module;
28 }
29 if ( ! empty( $route_module ) ) {
30 $route['route_module'] = $route_module;
31 }
32
33 $gutenberg_experiments_routes[] = $route;
34 }
35
36 /**
37 * Register a menu item for the experiments page.
38 *
39 * @param string $id Menu item ID.
40 * @param string $label Display label.
41 * @param string $to Route path to navigate to.
42 * @param string $parent_id Optional. Parent menu item ID.
43 * @param string $parent_type Optional. Parent type: 'drilldown' or 'dropdown'.
44 */
45 function gutenberg_register_experiments_menu_item( $id, $label, $to, $parent_id = '', $parent_type = '' ) {
46 global $gutenberg_experiments_menu_items;
47
48 $menu_item = array(
49 'id' => $id,
50 'label' => $label,
51 'to' => $to,
52 );
53
54 if ( ! empty( $parent_id ) ) {
55 $menu_item['parent'] = $parent_id;
56 }
57
58 if ( ! empty( $parent_type ) && in_array( $parent_type, array( 'drilldown', 'dropdown' ), true ) ) {
59 $menu_item['parent_type'] = $parent_type;
60 }
61
62 $gutenberg_experiments_menu_items[] = $menu_item;
63 }
64
65 /**
66 * Get all registered routes for the experiments page.
67 *
68 * @return array Array of route objects.
69 */
70 function gutenberg_get_experiments_routes() {
71 global $gutenberg_experiments_routes;
72 return $gutenberg_experiments_routes ?? array();
73 }
74
75 /**
76 * Get all registered menu items for the experiments page.
77 *
78 * @return array Array of menu item objects.
79 */
80 function gutenberg_get_experiments_menu_items() {
81 global $gutenberg_experiments_menu_items;
82 return $gutenberg_experiments_menu_items ?? array();
83 }
84
85 /**
86 * Preload REST API data for the experiments page.
87 * Automatically called during page rendering.
88 */
89 function gutenberg_experiments_preload_data() {
90 // Define paths to preload - same for all pages
91 // This must exactly match the _fields list in packages/core-data/src/entities.js,
92 // same fields in the same order, or the preload is never consumed.
93 $preload_paths = array(
94 '/?_fields=description,gmt_offset,home,image_max_bit_depth,image_sizes,image_size_threshold,image_strip_meta,name,site_icon,site_icon_url,site_logo,timezone_string,url,page_for_posts,page_on_front,show_on_front',
95 array( '/wp/v2/settings', 'OPTIONS' ),
96 );
97
98 // Use rest_preload_api_request to gather the preloaded data
99 $preload_data = array_reduce(
100 $preload_paths,
101 'rest_preload_api_request',
102 array()
103 );
104
105 // Register the preloading middleware with wp-api-fetch
106 wp_add_inline_script(
107 'wp-api-fetch',
108 sprintf(
109 'wp.apiFetch.use( wp.apiFetch.createPreloadingMiddleware( %s ) );',
110 wp_json_encode( $preload_data )
111 ),
112 'after'
113 );
114 }
115
116 /**
117 * Render the experiments page.
118 * Call this function from add_menu_page or add_submenu_page.
119 */
120 function gutenberg_experiments_render_page() {
121 // Load build constants
122 $build_constants = require __DIR__ . '/../../constants.php';
123
124 // Set current screen
125 set_current_screen();
126
127 // Remove unwanted deprecated handler
128 remove_action( 'admin_head', 'wp_admin_bar_header' );
129
130 // Remove unwanted scripts and styles that were enqueued during `admin_init`
131 foreach ( wp_scripts()->queue as $script ) {
132 wp_dequeue_script( $script );
133 }
134 foreach ( wp_styles()->queue as $style ) {
135 wp_dequeue_style( $style );
136 }
137
138 /**
139 * Fires when the experiments page is initialized so extensions can register routes and menu items.
140 */
141 do_action( 'experiments_init' );
142
143 // Enqueue command palette assets for boot-based pages
144 if ( function_exists( 'wp_enqueue_command_palette_assets' ) ) {
145 wp_enqueue_command_palette_assets();
146 }
147
148 // Preload REST API data
149 gutenberg_experiments_preload_data();
150
151 // Get all registered routes and menu items
152 $menu_items = gutenberg_get_experiments_menu_items();
153 $routes = gutenberg_get_experiments_routes();
154
155 // Get boot module asset file for dependencies. Plugins that build their own
156 // boot module use it; everyone else falls back to the copy bundled with Core.
157 $asset_file = __DIR__ . '/../../modules/boot/index.min.asset.php';
158 if ( ! file_exists( $asset_file ) ) {
159 $asset_file = ABSPATH . WPINC . '/js/dist/script-modules/boot/index.min.asset.php';
160 }
161 if ( file_exists( $asset_file ) ) {
162 $asset = require $asset_file;
163
164 // This script serves two purposes:
165 // 1. It ensures all the globals that are made available to the modules are loaded.
166 // 2. It initializes the boot module as an inline script.
167 wp_register_script( 'experiments-prerequisites', '', $asset['dependencies'], $asset['version'], true );
168
169 // Add inline script to initialize the app
170 $init_modules = [];
171 wp_add_inline_script(
172 'experiments-prerequisites',
173 sprintf(
174 'import("@wordpress/boot").then(mod => mod.init({mountId: "%s", menuItems: %s, routes: %s, initModules: %s, dashboardLink: "%s"}));',
175 'experiments-app',
176 wp_json_encode( $menu_items, JSON_HEX_TAG | JSON_UNESCAPED_SLASHES ),
177 wp_json_encode( $routes, JSON_HEX_TAG | JSON_UNESCAPED_SLASHES ),
178 wp_json_encode( $init_modules, JSON_HEX_TAG | JSON_UNESCAPED_SLASHES ),
179 esc_url( admin_url( '/' ) )
180 )
181 );
182
183 // Register prerequisites style by filtering script dependencies to find registered styles
184 $style_dependencies = array_filter(
185 $asset['dependencies'],
186 function ( $handle ) {
187 return wp_style_is( $handle, 'registered' );
188 }
189 );
190 wp_register_style( 'experiments-prerequisites', false, $style_dependencies, $asset['version'] );
191
192 // Build dependencies for experiments module
193 $boot_dependencies = array(
194 array(
195 'import' => 'static',
196 'id' => '@wordpress/boot',
197 ),
198 );
199
200 // Add init modules as static dependencies
201 // No init modules configured
202
203 // Add all registered routes as dependencies
204 foreach ( $routes as $route ) {
205 if ( isset( $route['route_module'] ) ) {
206 $boot_dependencies[] = array(
207 'import' => 'static',
208 'id' => $route['route_module'],
209 );
210 }
211 if ( isset( $route['content_module'] ) ) {
212 $boot_dependencies[] = array(
213 'import' => 'dynamic',
214 'id' => $route['content_module'],
215 );
216 }
217 }
218
219 /**
220 * Filters the boot script-module dependencies for the
221 * experiments page.
222 *
223 * Surfaces extending this page can append entries to the boot
224 * dependency list. Each entry is an array with 'import' (string
225 * 'static' or 'dynamic') and 'id' (script-module handle) keys.
226 *
227 * @param array $boot_dependencies Boot dependencies for the page.
228 */
229 $boot_dependencies = apply_filters(
230 'experiments_boot_dependencies',
231 $boot_dependencies
232 );
233
234 // Dummy script module to ensure dependencies are loaded
235 wp_register_script_module(
236 'experiments',
237 $build_constants['build_url'] . 'pages/experiments/loader.js',
238 $boot_dependencies
239 );
240
241 // Enqueue the boot scripts and styles
242 wp_enqueue_script( 'experiments-prerequisites' );
243 wp_enqueue_script_module( 'experiments' );
244 wp_enqueue_style( 'experiments-prerequisites' );
245 }
246
247 // Output the HTML
248 ?>
249 <!DOCTYPE html>
250 <html <?php language_attributes(); ?>>
251 <head>
252 <meta charset="<?php bloginfo( 'charset' ); ?>">
253 <meta name="viewport" content="width=device-width, initial-scale=1">
254 <title><?php echo esc_html( get_admin_page_title() ); ?></title>
255 <style>
256 html {
257 background: #f1f1f1;
258 color: #444;
259 font-family: -apple-system, system-ui, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", sans-serif;
260 font-size: 13px;
261 line-height: 1.4em;
262 }
263 body {
264 margin: 0;
265 }
266 #wpadminbar { display: none; }
267 </style>
268 <?php
269 global $hook_suffix;
270 // phpcs:ignore WordPress.WP.GlobalVariablesOverride.Prohibited
271 $hook_suffix = 'experiments';
272
273 // BEGIN see wp-admin/admin-header.php
274 print_admin_styles();
275 print_head_scripts();
276
277 /** This action is documented in wp-admin/admin-header.php */
278 do_action( "admin_head-{$hook_suffix}" ); // phpcs:ignore WordPress.NamingConventions.ValidHookName.UseUnderscores
279
280 /** This action is documented in wp-admin/admin-header.php */
281 do_action( 'admin_head' );
282 // END see wp-admin/admin-header.php
283 ?>
284 </head>
285 <body class="experiments no-js">
286 <?php
287 // BEGIN see wp-admin/admin-header.php
288 ?>
289 <script type="text/javascript">
290 document.body.className = document.body.className.replace( 'no-js', 'js' );
291 </script>
292 <?php
293 // END see wp-admin/admin-header.php
294 ?>
295 <div class="wrap hide-if-js" style="margin: 20px;">
296 <h1 class="wp-heading-inline"><?php echo esc_html( get_admin_page_title() ); ?></h1>
297 <?php
298 wp_admin_notice(
299 __( 'This screen requires JavaScript. Enable JavaScript in your browser settings and reload the page.' ),
300 array( 'type' => 'error' )
301 );
302 ?>
303 </div>
304 <div id="experiments-app" style="height: 100vh; box-sizing: border-box;"></div>
305 <?php
306 // BEGIN see wp-admin/admin-footer.php
307
308 /** This action is documented in wp-admin/admin-footer.php */
309 do_action( 'admin_footer', $hook_suffix );
310
311 // Print import map first so it's available for inline scripts
312 wp_script_modules()->print_import_map();
313 print_footer_scripts();
314 wp_script_modules()->print_enqueued_script_modules();
315 wp_script_modules()->print_script_module_preloads();
316 wp_script_modules()->print_script_module_data();
317
318 /** This action is documented in wp-admin/admin-footer.php */
319 do_action( "admin_footer-{$hook_suffix}" ); // phpcs:ignore WordPress.NamingConventions.ValidHookName.UseUnderscores
320 // END see wp-admin/admin-footer.php
321 ?>
322 </body>
323 </html>
324 <?php
325 exit;
326 }
327
328 /**
329 * Intercept admin_init to render the page early.
330 * This bypasses the default WordPress admin template.
331 */
332 function gutenberg_experiments_intercept_render() {
333 // phpcs:ignore WordPress.Security.NonceVerification.Recommended
334 if ( isset( $_GET['page'] ) && 'experiments' === $_GET['page'] ) {
335 // The page renders outside the menu page callback flow, so it must
336 // enforce authentication and capability checks itself. Without this,
337 // any admin entry point firing `admin_init` (such as admin-post.php,
338 // which serves logged-out requests) would render the page for
339 // unauthenticated visitors.
340 if ( ! is_user_logged_in() ) {
341 auth_redirect();
342 }
343
344 if ( ! current_user_can( 'manage_options' ) ) {
345 wp_die(
346 __( 'Sorry, you are not allowed to access this page.' ),
347 403
348 );
349 }
350
351 gutenberg_experiments_render_page();
352 exit;
353 }
354 }
355
356 // Hook the interceptor to admin_init
357 add_action( 'admin_init', 'gutenberg_experiments_intercept_render' );
358