| @@ -87,11 +87,12 @@ | ||
| 87 | 87 | * Automatically called during page rendering. |
| 88 | 88 | */ |
| 89 | 89 | function gutenberg_guidelines_preload_data() { |
| 90 | 90 | // Define paths to preload - same for all pages |
| 91 | - // Please also change packages/core-data/src/entities.js when changing this. | |
| 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. | |
| 92 | 93 | $preload_paths = array( |
| 93 | - '/?_fields=description,gmt_offset,home,image_sizes,image_size_threshold,name,site_icon,site_icon_url,site_logo,timezone_string,url,page_for_posts,page_on_front,show_on_front', | |
| 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', | |
| 94 | 95 | array( '/wp/v2/settings', 'OPTIONS' ), |
| 95 | 96 | ); |
| 96 | 97 | |
| 97 | 98 | // Use rest_preload_api_request to gather the preloaded data |
| @@ -133,9 +134,11 @@ | ||
| 133 | 134 | foreach ( wp_styles()->queue as $style ) { |
| 134 | 135 | wp_dequeue_style( $style ); |
| 135 | 136 | } |
| 136 | 137 | |
| 137 | - // Fire init action for extensions to register routes and menu items | |
| 138 | + /** | |
| 139 | + * Fires when the guidelines page is initialized so extensions can register routes and menu items. | |
| 140 | + */ | |
| 138 | 141 | do_action( 'guidelines_init' ); |
| 139 | 142 | |
| 140 | 143 | // Enqueue command palette assets for boot-based pages |
| 141 | 144 | if ( function_exists( 'wp_enqueue_command_palette_assets' ) ) { |
| @@ -148,10 +151,14 @@ | ||
| 148 | 151 | // Get all registered routes and menu items |
| 149 | 152 | $menu_items = gutenberg_get_guidelines_menu_items(); |
| 150 | 153 | $routes = gutenberg_get_guidelines_routes(); |
| 151 | 154 | |
| 152 | - // Get boot module asset file for dependencies | |
| 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. | |
| 153 | 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 | + } | |
| 154 | 161 | if ( file_exists( $asset_file ) ) { |
| 155 | 162 | $asset = require $asset_file; |
| 156 | 163 | |
| 157 | 164 | // This script serves two purposes: |
| @@ -248,9 +255,9 @@ | ||
| 248 | 255 | <style> |
| 249 | 256 | html { |
| 250 | 257 | background: #f1f1f1; |
| 251 | 258 | color: #444; |
| 252 | - font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", sans-serif; | |
| 259 | + font-family: -apple-system, system-ui, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", sans-serif; | |
| 253 | 260 | font-size: 13px; |
| 254 | 261 | line-height: 1.4em; |
| 255 | 262 | } |
| 256 | 263 | body { |
| @@ -266,35 +273,41 @@ | ||
| 266 | 273 | // BEGIN see wp-admin/admin-header.php |
| 267 | 274 | print_admin_styles(); |
| 268 | 275 | print_head_scripts(); |
| 269 | 276 | |
| 270 | - /** | |
| 271 | - * Fires in head section for a specific admin page. | |
| 272 | - * | |
| 273 | - * @since 2.1.0 | |
| 274 | - */ | |
| 277 | + /** This action is documented in wp-admin/admin-header.php */ | |
| 275 | 278 | do_action( "admin_head-{$hook_suffix}" ); // phpcs:ignore WordPress.NamingConventions.ValidHookName.UseUnderscores |
| 276 | 279 | |
| 277 | - /** | |
| 278 | - * Fires in head section for all admin pages. | |
| 279 | - * | |
| 280 | - * @since 2.1.0 | |
| 281 | - */ | |
| 280 | + /** This action is documented in wp-admin/admin-header.php */ | |
| 282 | 281 | do_action( 'admin_head' ); |
| 283 | 282 | // END see wp-admin/admin-header.php |
| 284 | 283 | ?> |
| 285 | 284 | </head> |
| 286 | - <body class="guidelines"> | |
| 285 | + <body class="guidelines 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> | |
| 287 | 304 | <div id="guidelines-app" style="height: 100vh; box-sizing: border-box;"></div> |
| 288 | 305 | <?php |
| 289 | 306 | // BEGIN see wp-admin/admin-footer.php |
| 290 | 307 | |
| 291 | - /** | |
| 292 | - * Prints scripts or data before the default footer scripts. | |
| 293 | - * | |
| 294 | - * @since 1.2.0 | |
| 295 | - */ | |
| 296 | - do_action( 'admin_footer', '' ); | |
| 308 | + /** This action is documented in wp-admin/admin-footer.php */ | |
| 309 | + do_action( 'admin_footer', $hook_suffix ); | |
| 297 | 310 | |
| 298 | 311 | // Print import map first so it's available for inline scripts |
| 299 | 312 | wp_script_modules()->print_import_map(); |
| 300 | 313 | print_footer_scripts(); |
| @@ -301,13 +314,9 @@ | ||
| 301 | 314 | wp_script_modules()->print_enqueued_script_modules(); |
| 302 | 315 | wp_script_modules()->print_script_module_preloads(); |
| 303 | 316 | wp_script_modules()->print_script_module_data(); |
| 304 | 317 | |
| 305 | - /** | |
| 306 | - * Prints scripts or data after the default footer scripts. | |
| 307 | - * | |
| 308 | - * @since 2.8.0 | |
| 309 | - */ | |
| 318 | + /** This action is documented in wp-admin/admin-footer.php */ | |
| 310 | 319 | do_action( "admin_footer-{$hook_suffix}" ); // phpcs:ignore WordPress.NamingConventions.ValidHookName.UseUnderscores |
| 311 | 320 | // END see wp-admin/admin-footer.php |
| 312 | 321 | ?> |
| 313 | 322 | </body> |
| @@ -322,8 +331,24 @@ | ||
| 322 | 331 | */ |
| 323 | 332 | function gutenberg_guidelines_intercept_render() { |
| 324 | 333 | // phpcs:ignore WordPress.Security.NonceVerification.Recommended |
| 325 | 334 | if ( isset( $_GET['page'] ) && 'guidelines' === $_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 | + | |
| 326 | 351 | gutenberg_guidelines_render_page(); |
| 327 | 352 | exit; |
| 328 | 353 | } |
| 329 | 354 | } |