edit-form-blocks.php (10642B)
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 die( '-1' ); 14 } 15 16 /** 17 * @global string $post_type 18 * @global WP_Post_Type $post_type_object 19 * @global WP_Post $post Global post object. 20 * @global string $title 21 * @global array $wp_meta_boxes 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 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_base = ! empty( $post_type_object->rest_base ) ? $post_type_object->rest_base : $post_type_object->name; 53 54 // Preload common data. 55 $preload_paths = array( 56 '/', 57 '/wp/v2/types?context=edit', 58 '/wp/v2/taxonomies?per_page=-1&context=edit', 59 '/wp/v2/themes?status=active', 60 sprintf( '/wp/v2/%s/%s?context=edit', $rest_base, $post->ID ), 61 sprintf( '/wp/v2/types/%s?context=edit', $post_type ), 62 sprintf( '/wp/v2/users/me?post_type=%s&context=edit', $post_type ), 63 array( '/wp/v2/media', 'OPTIONS' ), 64 array( '/wp/v2/blocks', 'OPTIONS' ), 65 sprintf( '/wp/v2/%s/%d/autosaves?context=edit', $rest_base, $post->ID ), 66 ); 67 68 block_editor_rest_api_preload( $preload_paths, $block_editor_context ); 69 70 wp_add_inline_script( 71 'wp-blocks', 72 sprintf( 'wp.blocks.setCategories( %s );', wp_json_encode( get_block_categories( $post ) ) ), 73 'after' 74 ); 75 76 /* 77 * Assign initial edits, if applicable. These are not initially assigned to the persisted post, 78 * but should be included in its save payload. 79 */ 80 $initial_edits = null; 81 $is_new_post = false; 82 if ( 'auto-draft' === $post->post_status ) { 83 $is_new_post = true; 84 // Override "(Auto Draft)" new post default title with empty string, or filtered value. 85 $initial_edits = array( 86 'title' => $post->post_title, 87 'content' => $post->post_content, 88 'excerpt' => $post->post_excerpt, 89 ); 90 } 91 92 // Preload server-registered block schemas. 93 wp_add_inline_script( 94 'wp-blocks', 95 'wp.blocks.unstable__bootstrapServerSideBlockDefinitions(' . wp_json_encode( get_block_editor_server_block_settings() ) . ');' 96 ); 97 98 // Get admin url for handling meta boxes. 99 $meta_box_url = admin_url( 'post.php' ); 100 $meta_box_url = add_query_arg( 101 array( 102 'post' => $post->ID, 103 'action' => 'edit', 104 'meta-box-loader' => true, 105 'meta-box-loader-nonce' => wp_create_nonce( 'meta-box-loader' ), 106 ), 107 $meta_box_url 108 ); 109 wp_add_inline_script( 110 'wp-editor', 111 sprintf( 'var _wpMetaBoxUrl = %s;', wp_json_encode( $meta_box_url ) ), 112 'before' 113 ); 114 115 /* 116 * Get all available templates for the post/page attributes meta-box. 117 * The "Default template" array element should only be added if the array is 118 * not empty so we do not trigger the template select element without any options 119 * besides the default value. 120 */ 121 $available_templates = wp_get_theme()->get_page_templates( get_post( $post->ID ) ); 122 $available_templates = ! empty( $available_templates ) ? array_replace( 123 array( 124 /** This filter is documented in wp-admin/includes/meta-boxes.php */ 125 '' => apply_filters( 'default_page_template_title', __( 'Default template' ), 'rest-api' ), 126 ), 127 $available_templates 128 ) : $available_templates; 129 130 // Lock settings. 131 $user_id = wp_check_post_lock( $post->ID ); 132 if ( $user_id ) { 133 $locked = false; 134 135 /** This filter is documented in wp-admin/includes/post.php */ 136 if ( apply_filters( 'show_post_locked_dialog', true, $post, $user_id ) ) { 137 $locked = true; 138 } 139 140 $user_details = null; 141 if ( $locked ) { 142 $user = get_userdata( $user_id ); 143 $user_details = array( 144 'name' => $user->display_name, 145 ); 146 $avatar = get_avatar_url( $user_id, array( 'size' => 64 ) ); 147 } 148 149 $lock_details = array( 150 'isLocked' => $locked, 151 'user' => $user_details, 152 ); 153 } else { 154 // Lock the post. 155 $active_post_lock = wp_set_post_lock( $post->ID ); 156 if ( $active_post_lock ) { 157 $active_post_lock = esc_attr( implode( ':', $active_post_lock ) ); 158 } 159 160 $lock_details = array( 161 'isLocked' => false, 162 'activePostLock' => $active_post_lock, 163 ); 164 } 165 166 /** 167 * Filters the body placeholder text. 168 * 169 * @since 5.0.0 170 * @since 5.8.0 Changed the default placeholder text. 171 * 172 * @param string $text Placeholder text. Default 'Type / to choose a block'. 173 * @param WP_Post $post Post object. 174 */ 175 $body_placeholder = apply_filters( 'write_your_story', __( 'Type / to choose a block' ), $post ); 176 177 $editor_settings = array( 178 'availableTemplates' => $available_templates, 179 'disablePostFormats' => ! current_theme_supports( 'post-formats' ), 180 /** This filter is documented in wp-admin/edit-form-advanced.php */ 181 'titlePlaceholder' => apply_filters( 'enter_title_here', __( 'Add title' ), $post ), 182 'bodyPlaceholder' => $body_placeholder, 183 'autosaveInterval' => AUTOSAVE_INTERVAL, 184 'styles' => get_block_editor_theme_styles(), 185 'richEditingEnabled' => user_can_richedit(), 186 'postLock' => $lock_details, 187 'postLockUtils' => array( 188 'nonce' => wp_create_nonce( 'lock-post_' . $post->ID ), 189 'unlockNonce' => wp_create_nonce( 'update-post_' . $post->ID ), 190 'ajaxUrl' => admin_url( 'admin-ajax.php' ), 191 ), 192 'supportsLayout' => WP_Theme_JSON_Resolver::theme_has_support(), 193 '__experimentalBlockPatterns' => WP_Block_Patterns_Registry::get_instance()->get_all_registered(), 194 '__experimentalBlockPatternCategories' => WP_Block_Pattern_Categories_Registry::get_instance()->get_all_registered(), 195 'supportsTemplateMode' => current_theme_supports( 'block-templates' ), 196 197 // Whether or not to load the 'postcustom' meta box is stored as a user meta 198 // field so that we're not always loading its assets. 199 'enableCustomFields' => (bool) get_user_meta( get_current_user_id(), 'enable_custom_fields', true ), 200 ); 201 202 $autosave = wp_get_post_autosave( $post->ID ); 203 if ( $autosave ) { 204 if ( mysql2date( 'U', $autosave->post_modified_gmt, false ) > mysql2date( 'U', $post->post_modified_gmt, false ) ) { 205 $editor_settings['autosave'] = array( 206 'editLink' => get_edit_post_link( $autosave->ID ), 207 ); 208 } else { 209 wp_delete_post_revision( $autosave->ID ); 210 } 211 } 212 213 if ( ! empty( $post_type_object->template ) ) { 214 $editor_settings['template'] = $post_type_object->template; 215 $editor_settings['templateLock'] = ! empty( $post_type_object->template_lock ) ? $post_type_object->template_lock : false; 216 } 217 218 // If there's no template set on a new post, use the post format, instead. 219 if ( $is_new_post && ! isset( $editor_settings['template'] ) && 'post' === $post->post_type ) { 220 $post_format = get_post_format( $post ); 221 if ( in_array( $post_format, array( 'audio', 'gallery', 'image', 'quote', 'video' ), true ) ) { 222 $editor_settings['template'] = array( array( "core/$post_format" ) ); 223 } 224 } 225 226 /** 227 * Scripts 228 */ 229 wp_enqueue_media( 230 array( 231 'post' => $post->ID, 232 ) 233 ); 234 wp_tinymce_inline_scripts(); 235 wp_enqueue_editor(); 236 237 /** 238 * Styles 239 */ 240 wp_enqueue_style( 'wp-edit-post' ); 241 242 /** 243 * Fires after block assets have been enqueued for the editing interface. 244 * 245 * Call `add_action` on any hook before 'admin_enqueue_scripts'. 246 * 247 * In the function call you supply, simply use `wp_enqueue_script` and 248 * `wp_enqueue_style` to add your functionality to the block editor. 249 * 250 * @since 5.0.0 251 */ 252 do_action( 'enqueue_block_editor_assets' ); 253 254 // In order to duplicate classic meta box behaviour, we need to run the classic meta box actions. 255 require_once ABSPATH . 'wp-admin/includes/meta-boxes.php'; 256 register_and_do_post_meta_boxes( $post ); 257 258 // Check if the Custom Fields meta box has been removed at some point. 259 $core_meta_boxes = $wp_meta_boxes[ $current_screen->id ]['normal']['core']; 260 if ( ! isset( $core_meta_boxes['postcustom'] ) || ! $core_meta_boxes['postcustom'] ) { 261 unset( $editor_settings['enableCustomFields'] ); 262 } 263 264 $editor_settings = get_block_editor_settings( $editor_settings, $block_editor_context ); 265 266 $init_script = <<<JS 267 ( function() { 268 window._wpLoadBlockEditor = new Promise( function( resolve ) { 269 wp.domReady( function() { 270 resolve( wp.editPost.initializeEditor( 'editor', "%s", %d, %s, %s ) ); 271 } ); 272 } ); 273 } )(); 274 JS; 275 276 $script = sprintf( 277 $init_script, 278 $post->post_type, 279 $post->ID, 280 wp_json_encode( $editor_settings ), 281 wp_json_encode( $initial_edits ) 282 ); 283 wp_add_inline_script( 'wp-edit-post', $script ); 284 285 if ( (int) get_option( 'page_for_posts' ) === $post->ID ) { 286 add_action( 'admin_enqueue_scripts', '_wp_block_editor_posts_page_notice' ); 287 } 288 289 require_once ABSPATH . 'wp-admin/admin-header.php'; 290 ?> 291 292 <div class="block-editor"> 293 <h1 class="screen-reader-text hide-if-no-js"><?php echo esc_html( $title ); ?></h1> 294 <div id="editor" class="block-editor__container hide-if-no-js"></div> 295 <div id="metaboxes" class="hidden"> 296 <?php the_block_editor_meta_boxes(); ?> 297 </div> 298 299 <?php // JavaScript is disabled. ?> 300 <div class="wrap hide-if-js block-editor-no-js"> 301 <h1 class="wp-heading-inline"><?php echo esc_html( $title ); ?></h1> 302 <div class="notice notice-error notice-alt"> 303 <p> 304 <?php 305 $message = sprintf( 306 /* translators: %s: A link to install the Classic Editor plugin. */ 307 __( 'The block editor requires JavaScript. Please enable JavaScript in your browser settings, or try the <a href="%s">Classic Editor plugin</a>.' ), 308 esc_url( wp_nonce_url( self_admin_url( 'plugin-install.php?tab=favorites&user=wordpressdotorg&save=0' ), 'save_wporg_username_' . get_current_user_id() ) ) 309 ); 310 311 /** 312 * Filters the message displayed in the block editor interface when JavaScript is 313 * not enabled in the browser. 314 * 315 * @since 5.0.3 316 * 317 * @param string $message The message being displayed. 318 * @param WP_Post $post The post being edited. 319 */ 320 echo apply_filters( 'block_editor_no_javascript_message', $message, $post ); 321 ?> 322 </p> 323 </div> 324 </div> 325 </div>