| | 2179 | |
| | 2180 | /** |
| | 2181 | * Scripts & Styles. |
| | 2182 | * |
| | 2183 | * Enqueues the needed scripts and styles when visiting the top-level page of |
| | 2184 | * the block editor. |
| | 2185 | * |
| | 2186 | * @since 5.0.0 |
| | 2187 | */ |
| | 2188 | function block_editor_scripts_and_styles() { |
| | 2189 | global $post_type, $post_type_object, $post, $editor_styles; |
| | 2190 | |
| | 2191 | wp_enqueue_script( 'heartbeat' ); |
| | 2192 | wp_enqueue_script( 'wp-edit-post' ); |
| | 2193 | wp_enqueue_script( 'wp-format-library' ); |
| | 2194 | |
| | 2195 | $rest_base = ! empty( $post_type_object->rest_base ) ? $post_type_object->rest_base : $post_type_object->name; |
| | 2196 | |
| | 2197 | // Preload common data. |
| | 2198 | $preload_paths = array( |
| | 2199 | '/', |
| | 2200 | '/wp/v2/types?context=edit', |
| | 2201 | '/wp/v2/taxonomies?per_page=-1&context=edit', |
| | 2202 | '/wp/v2/themes?status=active', |
| | 2203 | sprintf( '/wp/v2/%s/%s?context=edit', $rest_base, $post->ID ), |
| | 2204 | sprintf( '/wp/v2/types/%s?context=edit', $post_type ), |
| | 2205 | sprintf( '/wp/v2/users/me?post_type=%s&context=edit', $post_type ), |
| | 2206 | array( '/wp/v2/media', 'OPTIONS' ), |
| | 2207 | ); |
| | 2208 | |
| | 2209 | /** |
| | 2210 | * Preload common data by specifying an array of REST API paths that will be preloaded. |
| | 2211 | * |
| | 2212 | * Filters the array of paths that will be preloaded. |
| | 2213 | * |
| | 2214 | * @since 5.0.0 |
| | 2215 | * |
| | 2216 | * @param array $preload_paths Array of paths to preload. |
| | 2217 | * @param object $post The post resource data. |
| | 2218 | */ |
| | 2219 | $preload_paths = apply_filters( 'block_editor_preload_paths', $preload_paths, $post ); |
| | 2220 | |
| | 2221 | /* |
| | 2222 | * Ensure the global $post remains the same after API data is preloaded. |
| | 2223 | * Because API preloading can call the_content and other filters, plugins |
| | 2224 | * can unexpectedly modify $post. |
| | 2225 | */ |
| | 2226 | $backup_global_post = $post; |
| | 2227 | |
| | 2228 | $preload_data = array_reduce( |
| | 2229 | $preload_paths, |
| | 2230 | 'rest_preload_api_request', |
| | 2231 | array() |
| | 2232 | ); |
| | 2233 | |
| | 2234 | // Restore the global $post as it was before API preloading. |
| | 2235 | $post = $backup_global_post; |
| | 2236 | |
| | 2237 | wp_add_inline_script( |
| | 2238 | 'wp-api-fetch', |
| | 2239 | sprintf( 'wp.apiFetch.use( wp.apiFetch.createPreloadingMiddleware( %s ) );', wp_json_encode( $preload_data ) ), |
| | 2240 | 'after' |
| | 2241 | ); |
| | 2242 | |
| | 2243 | wp_add_inline_script( |
| | 2244 | 'wp-blocks', |
| | 2245 | sprintf( 'wp.blocks.setCategories( %s );', wp_json_encode( get_block_categories( $post ) ) ), |
| | 2246 | 'after' |
| | 2247 | ); |
| | 2248 | |
| | 2249 | /* |
| | 2250 | * Assign initial edits, if applicable. These are not initially assigned to the persisted post, |
| | 2251 | * but should be included in its save payload. |
| | 2252 | */ |
| | 2253 | $initial_edits = null; |
| | 2254 | $is_new_post = false; |
| | 2255 | if ( 'auto-draft' === $post->post_status ) { |
| | 2256 | $is_new_post = true; |
| | 2257 | // Override "(Auto Draft)" new post default title with empty string, or filtered value. |
| | 2258 | $initial_edits = array( |
| | 2259 | 'title' => array( |
| | 2260 | 'raw' => $post->post_title, |
| | 2261 | ), |
| | 2262 | 'content' => array( |
| | 2263 | 'raw' => $post->post_content, |
| | 2264 | ), |
| | 2265 | 'excerpt' => array( |
| | 2266 | 'raw' => $post->post_excerpt, |
| | 2267 | ), |
| | 2268 | ); |
| | 2269 | } |
| | 2270 | |
| | 2271 | // Prepare Jed locale data. |
| | 2272 | $locale_data = wp_get_jed_locale_data( 'default' ); |
| | 2273 | wp_add_inline_script( |
| | 2274 | 'wp-i18n', |
| | 2275 | 'wp.i18n.setLocaleData( ' . wp_json_encode( $locale_data ) . ' );' |
| | 2276 | ); |
| | 2277 | |
| | 2278 | // Preload server-registered block schemas. |
| | 2279 | wp_add_inline_script( |
| | 2280 | 'wp-blocks', |
| | 2281 | 'wp.blocks.unstable__bootstrapServerSideBlockDefinitions(' . wp_json_encode( get_block_editor_server_block_settings() ) . ');' |
| | 2282 | ); |
| | 2283 | |
| | 2284 | // Get admin url for handling meta boxes. |
| | 2285 | $meta_box_url = admin_url( 'post.php' ); |
| | 2286 | $meta_box_url = add_query_arg( |
| | 2287 | array( |
| | 2288 | 'post' => $post->ID, |
| | 2289 | 'action' => 'edit', |
| | 2290 | 'meta-box-loader' => true, |
| | 2291 | '_wpnonce' => wp_create_nonce( 'meta-box-loader' ), |
| | 2292 | ), |
| | 2293 | $meta_box_url |
| | 2294 | ); |
| | 2295 | wp_localize_script( 'wp-editor', '_wpMetaBoxUrl', $meta_box_url ); |
| | 2296 | |
| | 2297 | |
| | 2298 | /* |
| | 2299 | * Initialize the editor. |
| | 2300 | */ |
| | 2301 | |
| | 2302 | $align_wide = get_theme_support( 'align-wide' ); |
| | 2303 | $color_palette = current( (array) get_theme_support( 'editor-color-palette' ) ); |
| | 2304 | $font_sizes = current( (array) get_theme_support( 'editor-font-sizes' ) ); |
| | 2305 | |
| | 2306 | /** |
| | 2307 | * Filters the allowed block types for the editor, defaulting to true (all |
| | 2308 | * block types supported). |
| | 2309 | * |
| | 2310 | * @since 5.0.0 |
| | 2311 | * |
| | 2312 | * @param bool|array $allowed_block_types Array of block type slugs, or |
| | 2313 | * boolean to enable/disable all. |
| | 2314 | * @param object $post The post resource data. |
| | 2315 | */ |
| | 2316 | $allowed_block_types = apply_filters( 'allowed_block_types', true, $post ); |
| | 2317 | |
| | 2318 | // Get all available templates for the post/page attributes meta-box. |
| | 2319 | // The "Default template" array element should only be added if the array is |
| | 2320 | // not empty so we do not trigger the template select element without any options |
| | 2321 | // besides the default value. |
| | 2322 | $available_templates = wp_get_theme()->get_page_templates( get_post( $post->ID ) ); |
| | 2323 | $available_templates = ! empty( $available_templates ) ? array_merge( |
| | 2324 | array( |
| | 2325 | /** This filter is documented in wp-admin/includes/meta-boxes.php */ |
| | 2326 | '' => apply_filters( 'default_page_template_title', __( 'Default template' ), 'rest-api' ), |
| | 2327 | ), |
| | 2328 | $available_templates |
| | 2329 | ) : $available_templates; |
| | 2330 | |
| | 2331 | // Media settings. |
| | 2332 | $max_upload_size = wp_max_upload_size(); |
| | 2333 | if ( ! $max_upload_size ) { |
| | 2334 | $max_upload_size = 0; |
| | 2335 | } |
| | 2336 | |
| | 2337 | // Editor Styles. |
| | 2338 | $styles = array( |
| | 2339 | array( |
| | 2340 | 'css' => file_get_contents( |
| | 2341 | ABSPATH . WPINC . '/css/dist/editor/editor-styles.css' |
| | 2342 | ), |
| | 2343 | ), |
| | 2344 | ); |
| | 2345 | if ( $editor_styles && current_theme_supports( 'editor-styles' ) ) { |
| | 2346 | foreach ( $editor_styles as $style ) { |
| | 2347 | if ( preg_match( '~^(https?:)?//~', $style ) ) { |
| | 2348 | $response = wp_remote_get( $style ); |
| | 2349 | if ( ! is_wp_error( $response ) ) { |
| | 2350 | $styles[] = array( |
| | 2351 | 'css' => wp_remote_retrieve_body( $response ), |
| | 2352 | ); |
| | 2353 | } |
| | 2354 | } else { |
| | 2355 | $file = get_theme_file_path( $style ); |
| | 2356 | $styles[] = array( |
| | 2357 | 'css' => file_get_contents( get_theme_file_path( $style ) ), |
| | 2358 | 'baseURL' => get_theme_file_uri( $style ), |
| | 2359 | ); |
| | 2360 | } |
| | 2361 | } |
| | 2362 | } |
| | 2363 | |
| | 2364 | // Lock settings. |
| | 2365 | $user_id = wp_check_post_lock( $post->ID ); |
| | 2366 | if ( $user_id ) { |
| | 2367 | /** This filter is documented in wp-admin/includes/post.php */ |
| | 2368 | if ( apply_filters( 'show_post_locked_dialog', true, $post, $user_id ) ) { |
| | 2369 | $locked = true; |
| | 2370 | } |
| | 2371 | |
| | 2372 | $user_details = null; |
| | 2373 | if ( $locked ) { |
| | 2374 | $user = get_userdata( $user_id ); |
| | 2375 | $user_details = array( |
| | 2376 | 'name' => $user->display_name, |
| | 2377 | ); |
| | 2378 | $avatar = get_avatar_url( $user_id, array( 'size' => 64 ) ); |
| | 2379 | } |
| | 2380 | |
| | 2381 | $lock_details = array( |
| | 2382 | 'isLocked' => $locked, |
| | 2383 | 'user' => $user_details, |
| | 2384 | ); |
| | 2385 | } else { |
| | 2386 | // Lock the post. |
| | 2387 | $active_post_lock = wp_set_post_lock( $post->ID ); |
| | 2388 | $lock_details = array( |
| | 2389 | 'isLocked' => false, |
| | 2390 | 'activePostLock' => esc_attr( implode( ':', $active_post_lock ) ), |
| | 2391 | ); |
| | 2392 | } |
| | 2393 | |
| | 2394 | /** |
| | 2395 | * Filters the body placeholder text. |
| | 2396 | * |
| | 2397 | * @since 5.0.0 |
| | 2398 | * |
| | 2399 | * @param string $text Placeholder text. Default 'Write your story'. |
| | 2400 | * @param WP_Post $post Post object. |
| | 2401 | */ |
| | 2402 | $body_placeholder = apply_filters( 'write_your_story', __( 'Write your story' ), $post ); |
| | 2403 | |
| | 2404 | $editor_settings = array( |
| | 2405 | 'alignWide' => $align_wide, |
| | 2406 | 'availableTemplates' => $available_templates, |
| | 2407 | 'allowedBlockTypes' => $allowed_block_types, |
| | 2408 | 'disableCustomColors' => get_theme_support( 'disable-custom-colors' ), |
| | 2409 | 'disableCustomFontSizes' => get_theme_support( 'disable-custom-font-sizes' ), |
| | 2410 | 'disablePostFormats' => ! current_theme_supports( 'post-formats' ), |
| | 2411 | /** This filter is documented in wp-admin/edit-form-advanced.php */ |
| | 2412 | 'titlePlaceholder' => apply_filters( 'enter_title_here', __( 'Add title' ), $post ), |
| | 2413 | 'bodyPlaceholder' => $body_placeholder, |
| | 2414 | 'isRTL' => is_rtl(), |
| | 2415 | 'autosaveInterval' => 10, |
| | 2416 | 'maxUploadFileSize' => $max_upload_size, |
| | 2417 | 'allowedMimeTypes' => get_allowed_mime_types(), |
| | 2418 | 'styles' => $styles, |
| | 2419 | 'postLock' => $lock_details, |
| | 2420 | 'postLockUtils' => array( |
| | 2421 | 'nonce' => wp_create_nonce( 'lock-post_' . $post->ID ), |
| | 2422 | 'unlockNonce' => wp_create_nonce( 'update-post_' . $post->ID ), |
| | 2423 | 'ajaxUrl' => admin_url( 'admin-ajax.php' ), |
| | 2424 | ), |
| | 2425 | ); |
| | 2426 | |
| | 2427 | $autosave = wp_get_post_autosave( $post->ID ); |
| | 2428 | if ( $autosave ) { |
| | 2429 | if ( mysql2date( 'U', $autosave->post_modified_gmt, false ) > mysql2date( 'U', $post->post_modified_gmt, false ) ) { |
| | 2430 | $editor_settings['autosave'] = array( |
| | 2431 | 'editLink' => get_edit_post_link( $autosave->ID ), |
| | 2432 | ); |
| | 2433 | } else { |
| | 2434 | wp_delete_post_revision( $autosave->ID ); |
| | 2435 | } |
| | 2436 | } |
| | 2437 | |
| | 2438 | if ( false !== $color_palette ) { |
| | 2439 | $editor_settings['colors'] = $color_palette; |
| | 2440 | } |
| | 2441 | |
| | 2442 | if ( ! empty( $font_sizes ) ) { |
| | 2443 | $editor_settings['fontSizes'] = $font_sizes; |
| | 2444 | } |
| | 2445 | |
| | 2446 | if ( ! empty( $post_type_object->template ) ) { |
| | 2447 | $editor_settings['template'] = $post_type_object->template; |
| | 2448 | $editor_settings['templateLock'] = ! empty( $post_type_object->template_lock ) ? $post_type_object->template_lock : false; |
| | 2449 | } |
| | 2450 | |
| | 2451 | // If there's no template set on a new post, use the post format, instead. |
| | 2452 | if ( $is_new_post && ! isset( $editor_settings['template'] ) && 'post' === $post->post_type ) { |
| | 2453 | $post_format = get_post_format( $post ); |
| | 2454 | if ( in_array( $post_format, array( 'audio', 'gallery', 'image', 'quote', 'video' ), true ) ) { |
| | 2455 | $editor_settings['template'] = array( array( "core/$post_format" ) ); |
| | 2456 | } |
| | 2457 | } |
| | 2458 | |
| | 2459 | $init_script = <<<JS |
| | 2460 | ( function() { |
| | 2461 | window._wpLoadBlockEditor = new Promise( function( resolve ) { |
| | 2462 | wp.domReady( function() { |
| | 2463 | resolve( wp.editPost.initializeEditor( 'editor', "%s", %d, %s, %s ) ); |
| | 2464 | } ); |
| | 2465 | } ); |
| | 2466 | } )(); |
| | 2467 | JS; |
| | 2468 | |
| | 2469 | |
| | 2470 | /** |
| | 2471 | * Filters the settings to pass to the block editor. |
| | 2472 | * |
| | 2473 | * @since 5.0.0 |
| | 2474 | * |
| | 2475 | * @param array $editor_settings Default editor settings. |
| | 2476 | * @param WP_Post $post Post being edited. |
| | 2477 | */ |
| | 2478 | $editor_settings = apply_filters( 'block_editor_settings', $editor_settings, $post ); |
| | 2479 | |
| | 2480 | $script = sprintf( |
| | 2481 | $init_script, |
| | 2482 | $post->post_type, |
| | 2483 | $post->ID, |
| | 2484 | wp_json_encode( $editor_settings ), |
| | 2485 | wp_json_encode( $initial_edits ) |
| | 2486 | ); |
| | 2487 | wp_add_inline_script( 'wp-edit-post', $script ); |
| | 2488 | |
| | 2489 | /** |
| | 2490 | * Scripts |
| | 2491 | */ |
| | 2492 | wp_enqueue_media( |
| | 2493 | array( |
| | 2494 | 'post' => $post->ID, |
| | 2495 | ) |
| | 2496 | ); |
| | 2497 | wp_enqueue_editor(); |
| | 2498 | |
| | 2499 | /** |
| | 2500 | * Styles |
| | 2501 | */ |
| | 2502 | wp_enqueue_style( 'wp-edit-post' ); |
| | 2503 | wp_enqueue_style( 'wp-format-library' ); |
| | 2504 | |
| | 2505 | /** |
| | 2506 | * Fires after block assets have been enqueued for the editing interface. |
| | 2507 | * |
| | 2508 | * Call `add_action` on any hook before 'admin_enqueue_scripts'. |
| | 2509 | * |
| | 2510 | * In the function call you supply, simply use `wp_enqueue_script` and |
| | 2511 | * `wp_enqueue_style` to add your functionality to the block editor. |
| | 2512 | * |
| | 2513 | * @since 5.0.0 |
| | 2514 | */ |
| | 2515 | do_action( 'enqueue_block_editor_assets' ); |
| | 2516 | } |