| [ Index ] |
PHP Cross Reference of WordPress Trunk (Updated Daily) |
[Summary view] [Print] [Text view]
1 <?php 2 /** 3 * The block editor page. 4 * 5 * @since 5.0.0 6 * 7 * @package WordPress 8 * @subpackage Administration 9 */ 10 11 // Don't load directly. 12 if ( ! defined( 'ABSPATH' ) ) { 13 exit; 14 } 15 16 /** 17 * @global string $post_type Global post type. 18 * @global WP_Post_Type $post_type_object Global post type object. 19 * @global WP_Post $post Global post object. 20 * @global string $title The title of the current screen. 21 * @global array $wp_meta_boxes Global meta box state. 22 */ 23 global $post_type, $post_type_object, $post, $title, $wp_meta_boxes; 24 25 $block_editor_context = new WP_Block_Editor_Context( array( 'post' => $post ) ); 26 27 // Flag that we're loading the block editor. 28 $current_screen = get_current_screen(); 29 $current_screen->is_block_editor( true ); 30 31 // Default to is-fullscreen-mode to avoid jumps in the UI. 32 add_filter( 33 'admin_body_class', 34 static function ( $classes ) { 35 return "$classes is-fullscreen-mode"; 36 } 37 ); 38 39 /* 40 * Emoji replacement is disabled for now, until it plays nicely with React. 41 */ 42 remove_action( 'admin_print_scripts', 'print_emoji_detection_script' ); 43 44 /* 45 * Block editor implements its own Options menu for toggling Document Panels. 46 */ 47 add_filter( 'screen_options_show_screen', '__return_false' ); 48 49 wp_enqueue_script( 'heartbeat' ); 50 wp_enqueue_script( 'wp-edit-post' ); 51 52 $rest_path = rest_get_route_for_post( $post ); 53 54 $active_theme = get_stylesheet(); 55 $global_styles_endpoint_context = current_user_can( 'edit_theme_options' ) ? 'edit' : 'view'; 56 $template_lookup_slug = 'page' === $post->post_type ? 'page' : 'single-' . $post->post_type; 57 if ( ! empty( $post->post_name ) ) { 58 $template_lookup_slug .= '-' . $post->post_name; 59 } 60 // Preload common data. 61 $preload_paths = array( 62 '/wp/v2/types?context=view', 63 '/wp/v2/taxonomies?context=view', 64 add_query_arg( 'context', 'edit', $rest_path ), 65 sprintf( '/wp/v2/types/%s?context=edit', $post_type ), 66 '/wp/v2/users/me', 67 array( rest_get_route_for_post_type_items( 'attachment' ), 'OPTIONS' ), 68 array( rest_get_route_for_post_type_items( 'page' ), 'OPTIONS' ), 69 array( rest_get_route_for_post_type_items( 'wp_block' ), 'OPTIONS' ), 70 array( rest_get_route_for_post_type_items( 'wp_template' ), 'OPTIONS' ), 71 sprintf( '%s/autosaves?context=edit', $rest_path ), 72 '/wp/v2/settings', 73 array( '/wp/v2/settings', 'OPTIONS' ), 74 '/wp/v2/global-styles/themes/' . $active_theme . '?context=view', 75 '/wp/v2/global-styles/themes/' . $active_theme . '/variations?context=view', 76 '/wp/v2/themes?context=edit&status=active', 77 array( '/wp/v2/global-styles/' . WP_Theme_JSON_Resolver::get_user_global_styles_post_id(), 'OPTIONS' ), 78 /* 79 * Preload the global styles path with the correct context based on user caps. 80 * NOTE: There is an equivalent conditional check in the client-side code to fetch 81 * the global styles entity using the appropriate context value. 82 * See the call to `canUser()`, under `useGlobalStylesUserConfig()` in `packages/edit-site/src/components/use-global-styles-user-config/index.js`. 83 * Please ensure that the equivalent check is kept in sync with this preload path. 84 */ 85 '/wp/v2/global-styles/' . WP_Theme_JSON_Resolver::get_user_global_styles_post_id() . '?context=' . $global_styles_endpoint_context, 86 // Used by getBlockPatternCategories in useBlockEditorSettings. 87 '/wp/v2/block-patterns/categories', 88 /** 89 * The preloaded URL must exactly match the request the client makes, 90 * including the field order. 91 * @link https://github.com/WordPress/gutenberg/blob/trunk/packages/core-data/src/entities.js 92 */ 93 '/?_fields=' . implode( 94 ',', 95 array( 96 'description', 97 'generate_animated_image_subsizes', 98 'gmt_offset', 99 'home', 100 'image_max_bit_depth', 101 'image_sizes', 102 'image_size_threshold', 103 'image_strip_meta', 104 'name', 105 'site_icon', 106 'site_icon_url', 107 'site_logo', 108 'timezone_string', 109 'url', 110 'page_for_posts', 111 'page_on_front', 112 'show_on_front', 113 ) 114 ), 115 add_query_arg( 116 'slug', 117 // @link https://github.com/WordPress/gutenberg/blob/e093fefd041eb6cc4a4e7f67b92ab54fd75c8858/packages/core-data/src/private-selectors.ts#L244-L254 118 $template_lookup_slug, 119 '/wp/v2/templates/lookup' 120 ), 121 '/wp/v2/templates/lookup?slug=front-page', 122 '/wp/v2/taxonomies?context=edit', 123 array( rest_get_route_for_post_type_items( $post_type ), 'OPTIONS' ), 124 ); 125 126 if ( post_type_supports( $post_type, 'author' ) && $post->post_author > 0 ) { 127 $preload_paths[] = sprintf( 128 '/wp/v2/users/%d?context=view&_fields=id,name', 129 (int) $post->post_author 130 ); 131 } 132 133 block_editor_rest_api_preload( $preload_paths, $block_editor_context ); 134 135 wp_add_inline_script( 136 'wp-blocks', 137 sprintf( 'wp.blocks.setCategories( %s );', wp_json_encode( get_block_categories( $post ), JSON_HEX_TAG | JSON_UNESCAPED_SLASHES ) ), 138 'after' 139 ); 140 141 /* 142 * Assign initial edits, if applicable. These are not initially assigned to the persisted post, 143 * but should be included in its save payload. 144 */ 145 $initial_edits = array(); 146 $is_new_post = false; 147 if ( 'auto-draft' === $post->post_status ) { 148 $is_new_post = true; 149 // Override "(Auto Draft)" new post default title with empty string, or filtered value. 150 if ( post_type_supports( $post->post_type, 'title' ) ) { 151 $initial_edits['title'] = $post->post_title; 152 } 153 154 if ( post_type_supports( $post->post_type, 'editor' ) ) { 155 $initial_edits['content'] = $post->post_content; 156 } 157 158 if ( post_type_supports( $post->post_type, 'excerpt' ) ) { 159 $initial_edits['excerpt'] = $post->post_excerpt; 160 } 161 } 162 163 // Preload server-registered block schemas. 164 wp_add_inline_script( 165 'wp-blocks', 166 'wp.blocks.unstable__bootstrapServerSideBlockDefinitions(' . wp_json_encode( get_block_editor_server_block_settings(), JSON_HEX_TAG | JSON_UNESCAPED_SLASHES ) . ');' 167 ); 168 169 // Preload server-registered block bindings sources. 170 $registered_sources = get_all_registered_block_bindings_sources(); 171 if ( ! empty( $registered_sources ) ) { 172 $filtered_sources = array(); 173 foreach ( $registered_sources as $source ) { 174 $filtered_sources[] = array( 175 'name' => $source->name, 176 'label' => $source->label, 177 'usesContext' => $source->uses_context, 178 ); 179 } 180 $script = sprintf( 'for ( const source of %s ) { wp.blocks.registerBlockBindingsSource( source ); }', wp_json_encode( $filtered_sources, JSON_HEX_TAG | JSON_UNESCAPED_SLASHES ) ); 181 wp_add_inline_script( 182 'wp-blocks', 183 $script 184 ); 185 } 186 187 // Get admin url for handling meta boxes. 188 $meta_box_url = admin_url( 'post.php' ); 189 $meta_box_url = add_query_arg( 190 array( 191 'post' => $post->ID, 192 'action' => 'edit', 193 'meta-box-loader' => true, 194 'meta-box-loader-nonce' => wp_create_nonce( 'meta-box-loader' ), 195 ), 196 $meta_box_url 197 ); 198 wp_add_inline_script( 199 'wp-editor', 200 sprintf( 'var _wpMetaBoxUrl = %s;', wp_json_encode( $meta_box_url, JSON_HEX_TAG | JSON_UNESCAPED_SLASHES ) ), 201 'before' 202 ); 203 204 // Set Heartbeat interval to 10 seconds, used to refresh post locks. 205 wp_add_inline_script( 206 'heartbeat', 207 'jQuery( function() { 208 wp.heartbeat.interval( 10 ); 209 } );', 210 'after' 211 ); 212 213 /* 214 * Get all available templates for the post/page attributes meta-box. 215 * The "Default template" array element should only be added if the array is 216 * not empty so we do not trigger the template select element without any options 217 * besides the default value. 218 */ 219 $available_templates = wp_get_theme()->get_page_templates( get_post( $post->ID ) ); 220 $available_templates = ! empty( $available_templates ) ? array_replace( 221 array( 222 /** This filter is documented in wp-admin/includes/meta-boxes.php */ 223 '' => apply_filters( 'default_page_template_title', __( 'Default template' ), 'rest-api' ), 224 ), 225 $available_templates 226 ) : $available_templates; 227 228 // Lock settings. 229 $user_id = wp_check_post_lock( $post->ID ); 230 if ( $user_id ) { 231 $locked = false; 232 233 /** This filter is documented in wp-admin/includes/post.php */ 234 if ( apply_filters( 'show_post_locked_dialog', true, $post, $user_id ) ) { 235 $locked = true; 236 } 237 238 $user_details = null; 239 if ( $locked ) { 240 $user = get_userdata( $user_id ); 241 $user_details = array( 242 'name' => $user->display_name, 243 ); 244 245 if ( get_option( 'show_avatars' ) ) { 246 $user_details['avatar'] = get_avatar_url( $user_id, array( 'size' => 128 ) ); 247 } 248 } 249 250 $lock_details = array( 251 'isLocked' => $locked, 252 'user' => $user_details, 253 ); 254 } else { 255 // Lock the post. 256 $active_post_lock = wp_set_post_lock( $post->ID ); 257 if ( $active_post_lock ) { 258 $active_post_lock = esc_attr( implode( ':', $active_post_lock ) ); 259 } 260 261 $lock_details = array( 262 'isLocked' => false, 263 'activePostLock' => $active_post_lock, 264 ); 265 } 266 267 /** 268 * Filters the body placeholder text. 269 * 270 * @since 5.0.0 271 * @since 5.8.0 Changed the default placeholder text. 272 * 273 * @param string $text Placeholder text. Default 'Type / to choose a block'. 274 * @param WP_Post $post Post object. 275 */ 276 $body_placeholder = apply_filters( 'write_your_story', __( 'Type / to choose a block' ), $post ); 277 278 $editor_settings = array( 279 'availableTemplates' => $available_templates, 280 'disablePostFormats' => ! current_theme_supports( 'post-formats' ), 281 /** This filter is documented in wp-admin/edit-form-advanced.php */ 282 'titlePlaceholder' => apply_filters( 'enter_title_here', __( 'Add title' ), $post ), 283 'bodyPlaceholder' => $body_placeholder, 284 'autosaveInterval' => AUTOSAVE_INTERVAL, 285 'richEditingEnabled' => user_can_richedit(), 286 'postLock' => $lock_details, 287 'postLockUtils' => array( 288 'nonce' => wp_create_nonce( 'lock-post_' . $post->ID ), 289 'unlockNonce' => wp_create_nonce( 'update-post_' . $post->ID ), 290 'ajaxUrl' => admin_url( 'admin-ajax.php' ), 291 ), 292 'supportsLayout' => wp_theme_has_theme_json(), 293 'supportsTemplateMode' => current_theme_supports( 'block-templates' ), 294 295 // Whether or not to load the 'postcustom' meta box is stored as a user meta 296 // field so that we're not always loading its assets. 297 'enableCustomFields' => (bool) get_user_meta( get_current_user_id(), 'enable_custom_fields', true ), 298 ); 299 300 // Add additional back-compat patterns registered by `current_screen` et al. 301 $editor_settings['__experimentalAdditionalBlockPatterns'] = WP_Block_Patterns_Registry::get_instance()->get_all_registered( true ); 302 $editor_settings['__experimentalAdditionalBlockPatternCategories'] = WP_Block_Pattern_Categories_Registry::get_instance()->get_all_registered( true ); 303 304 $autosave = wp_get_post_autosave( $post->ID ); 305 if ( $autosave ) { 306 if ( mysql2date( 'U', $autosave->post_modified_gmt, false ) > mysql2date( 'U', $post->post_modified_gmt, false ) ) { 307 $editor_settings['autosave'] = array( 308 'editLink' => get_edit_post_link( $autosave->ID ), 309 ); 310 } else { 311 wp_delete_post_revision( $autosave->ID ); 312 } 313 } 314 315 if ( ! empty( $post_type_object->template ) ) { 316 $editor_settings['template'] = $post_type_object->template; 317 $editor_settings['templateLock'] = ! empty( $post_type_object->template_lock ) ? $post_type_object->template_lock : false; 318 } 319 320 // If there's no template set on a new post, use the post format, instead. 321 if ( $is_new_post && ! isset( $editor_settings['template'] ) && 'post' === $post->post_type ) { 322 $post_format = get_post_format( $post ); 323 if ( in_array( $post_format, array( 'audio', 'gallery', 'image', 'quote', 'video' ), true ) ) { 324 $editor_settings['template'] = array( array( "core/$post_format" ) ); 325 } 326 } 327 328 if ( wp_is_block_theme() && $editor_settings['supportsTemplateMode'] ) { 329 $editor_settings['defaultTemplatePartAreas'] = get_allowed_block_template_part_areas(); 330 } 331 332 /** 333 * Scripts 334 */ 335 wp_enqueue_media( 336 array( 337 'post' => $post->ID, 338 ) 339 ); 340 wp_tinymce_inline_scripts(); 341 wp_enqueue_editor(); 342 343 /** 344 * Styles 345 */ 346 // Prefetched for the block editor by wp_prefetch_admin_assets(), which needs updating if this changes. 347 wp_enqueue_style( 'wp-edit-post' ); 348 349 /** 350 * Fires after block assets have been enqueued for the editing interface. 351 * 352 * Call `add_action` on any hook before 'admin_enqueue_scripts'. 353 * 354 * In the function call you supply, simply use `wp_enqueue_script` and 355 * `wp_enqueue_style` to add your functionality to the block editor. 356 * 357 * @since 5.0.0 358 */ 359 do_action( 'enqueue_block_editor_assets' ); 360 361 // In order to duplicate classic meta box behavior, we need to run the classic meta box actions. 362 require_once ABSPATH . 'wp-admin/includes/meta-boxes.php'; 363 register_and_do_post_meta_boxes( $post ); 364 365 // Check if the Custom Fields meta box has been removed at some point. 366 $core_meta_boxes = $wp_meta_boxes[ $current_screen->id ]['normal']['core']; 367 if ( ! isset( $core_meta_boxes['postcustom'] ) || ! $core_meta_boxes['postcustom'] ) { 368 unset( $editor_settings['enableCustomFields'] ); 369 } 370 371 $editor_settings = get_block_editor_settings( $editor_settings, $block_editor_context ); 372 373 $init_script = <<<JS 374 ( function() { 375 window._wpLoadBlockEditor = new Promise( function( resolve ) { 376 wp.domReady( function() { 377 resolve( wp.editPost.initializeEditor( 'editor', "%s", %d, %s, %s ) ); 378 } ); 379 } ); 380 } )(); 381 JS; 382 383 $script = sprintf( 384 $init_script, 385 $post->post_type, 386 $post->ID, 387 wp_json_encode( $editor_settings, JSON_HEX_TAG | JSON_UNESCAPED_SLASHES ), 388 wp_json_encode( $initial_edits, JSON_HEX_TAG | JSON_UNESCAPED_SLASHES ) 389 ); 390 wp_add_inline_script( 'wp-edit-post', $script ); 391 392 if ( (int) get_option( 'page_for_posts' ) === $post->ID ) { 393 add_action( 'admin_enqueue_scripts', '_wp_block_editor_posts_page_notice' ); 394 } 395 396 require_once ABSPATH . 'wp-admin/admin-header.php'; 397 ?> 398 399 <div class="block-editor"> 400 <h1 class="screen-reader-text hide-if-no-js"><?php echo esc_html( $title ); ?></h1> 401 <div id="editor" class="block-editor__container hide-if-no-js"></div> 402 <div id="metaboxes" class="hidden"> 403 <?php the_block_editor_meta_boxes(); ?> 404 </div> 405 406 <?php // JavaScript is disabled. ?> 407 <div class="wrap hide-if-js block-editor-no-js"> 408 <h1 class="wp-heading-inline"><?php echo esc_html( $title ); ?></h1> 409 <?php 410 if ( file_exists( WP_PLUGIN_DIR . '/classic-editor/classic-editor.php' ) ) { 411 // If Classic Editor is already installed, provide a link to activate the plugin. 412 $installed = true; 413 $plugin_activate_url = wp_nonce_url( 'plugins.php?action=activate&plugin=classic-editor/classic-editor.php', 'activate-plugin_classic-editor/classic-editor.php' ); 414 $message = sprintf( 415 /* translators: %s: Link to activate the Classic Editor plugin. */ 416 __( 'The block editor requires JavaScript. Please enable JavaScript in your browser settings, or activate the <a href="%s">Classic Editor plugin</a>.' ), 417 esc_url( $plugin_activate_url ) 418 ); 419 } else { 420 // If Classic Editor is not installed, provide a link to install it. 421 $installed = false; 422 $plugin_install_url = wp_nonce_url( self_admin_url( 'update.php?action=install-plugin&plugin=classic-editor' ), 'install-plugin_classic-editor' ); 423 $message = sprintf( 424 /* translators: %s: Link to install the Classic Editor plugin. */ 425 __( 'The block editor requires JavaScript. Please enable JavaScript in your browser settings, or install the <a href="%s">Classic Editor plugin</a>.' ), 426 esc_url( $plugin_install_url ) 427 ); 428 } 429 430 /** 431 * Filters the message displayed in the block editor interface when JavaScript is 432 * not enabled in the browser. 433 * 434 * @since 5.0.3 435 * @since 6.4.0 Added `$installed` parameter. 436 * 437 * @param string $message The message being displayed. 438 * @param WP_Post $post The post being edited. 439 * @param bool $installed Whether the classic editor is installed. 440 */ 441 $message = apply_filters( 'block_editor_no_javascript_message', $message, $post, $installed ); 442 wp_admin_notice( 443 $message, 444 array( 445 'type' => 'error', 446 ) 447 ); 448 ?> 449 </div> 450 </div>
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
| Generated : Fri Oct 23 08:20:34 2026 | Cross-referenced by PHPXref |