[ Index ]

PHP Cross Reference of WordPress Trunk (Updated Daily)

Search

title

Body

[close]

/wp-admin/ -> edit-form-blocks.php (source)

   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        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      // @see packages/core-data/src/entities.js
  89      '/?_fields=' . implode(
  90          ',',
  91          array(
  92              'description',
  93              'gmt_offset',
  94              'home',
  95              'image_sizes',
  96              'image_size_threshold',
  97              'image_output_formats',
  98              'jpeg_interlaced',
  99              'png_interlaced',
 100              'gif_interlaced',
 101              'name',
 102              'site_icon',
 103              'site_icon_url',
 104              'site_logo',
 105              'timezone_string',
 106              'url',
 107              'page_for_posts',
 108              'page_on_front',
 109              'show_on_front',
 110          )
 111      ),
 112      $paths[] = add_query_arg(
 113          'slug',
 114          // @link https://github.com/WordPress/gutenberg/blob/e093fefd041eb6cc4a4e7f67b92ab54fd75c8858/packages/core-data/src/private-selectors.ts#L244-L254
 115          $template_lookup_slug,
 116          '/wp/v2/templates/lookup'
 117      ),
 118  );
 119  
 120  block_editor_rest_api_preload( $preload_paths, $block_editor_context );
 121  
 122  wp_add_inline_script(
 123      'wp-blocks',
 124      sprintf( 'wp.blocks.setCategories( %s );', wp_json_encode( get_block_categories( $post ), JSON_HEX_TAG | JSON_UNESCAPED_SLASHES ) ),
 125      'after'
 126  );
 127  
 128  /*
 129   * Assign initial edits, if applicable. These are not initially assigned to the persisted post,
 130   * but should be included in its save payload.
 131   */
 132  $initial_edits = array();
 133  $is_new_post   = false;
 134  if ( 'auto-draft' === $post->post_status ) {
 135      $is_new_post = true;
 136      // Override "(Auto Draft)" new post default title with empty string, or filtered value.
 137      if ( post_type_supports( $post->post_type, 'title' ) ) {
 138          $initial_edits['title'] = $post->post_title;
 139      }
 140  
 141      if ( post_type_supports( $post->post_type, 'editor' ) ) {
 142          $initial_edits['content'] = $post->post_content;
 143      }
 144  
 145      if ( post_type_supports( $post->post_type, 'excerpt' ) ) {
 146          $initial_edits['excerpt'] = $post->post_excerpt;
 147      }
 148  }
 149  
 150  // Preload server-registered block schemas.
 151  wp_add_inline_script(
 152      'wp-blocks',
 153      'wp.blocks.unstable__bootstrapServerSideBlockDefinitions(' . wp_json_encode( get_block_editor_server_block_settings(), JSON_HEX_TAG | JSON_UNESCAPED_SLASHES ) . ');'
 154  );
 155  
 156  // Preload server-registered block bindings sources.
 157  $registered_sources = get_all_registered_block_bindings_sources();
 158  if ( ! empty( $registered_sources ) ) {
 159      $filtered_sources = array();
 160      foreach ( $registered_sources as $source ) {
 161          $filtered_sources[] = array(
 162              'name'        => $source->name,
 163              'label'       => $source->label,
 164              'usesContext' => $source->uses_context,
 165          );
 166      }
 167      $script = sprintf( 'for ( const source of %s ) { wp.blocks.registerBlockBindingsSource( source ); }', wp_json_encode( $filtered_sources, JSON_HEX_TAG | JSON_UNESCAPED_SLASHES ) );
 168      wp_add_inline_script(
 169          'wp-blocks',
 170          $script
 171      );
 172  }
 173  
 174  // Get admin url for handling meta boxes.
 175  $meta_box_url = admin_url( 'post.php' );
 176  $meta_box_url = add_query_arg(
 177      array(
 178          'post'                  => $post->ID,
 179          'action'                => 'edit',
 180          'meta-box-loader'       => true,
 181          'meta-box-loader-nonce' => wp_create_nonce( 'meta-box-loader' ),
 182      ),
 183      $meta_box_url
 184  );
 185  wp_add_inline_script(
 186      'wp-editor',
 187      sprintf( 'var _wpMetaBoxUrl = %s;', wp_json_encode( $meta_box_url, JSON_HEX_TAG | JSON_UNESCAPED_SLASHES ) ),
 188      'before'
 189  );
 190  
 191  // Set Heartbeat interval to 10 seconds, used to refresh post locks.
 192  wp_add_inline_script(
 193      'heartbeat',
 194      'jQuery( function() {
 195          wp.heartbeat.interval( 10 );
 196      } );',
 197      'after'
 198  );
 199  
 200  /*
 201   * Get all available templates for the post/page attributes meta-box.
 202   * The "Default template" array element should only be added if the array is
 203   * not empty so we do not trigger the template select element without any options
 204   * besides the default value.
 205   */
 206  $available_templates = wp_get_theme()->get_page_templates( get_post( $post->ID ) );
 207  $available_templates = ! empty( $available_templates ) ? array_replace(
 208      array(
 209          /** This filter is documented in wp-admin/includes/meta-boxes.php */
 210          '' => apply_filters( 'default_page_template_title', __( 'Default template' ), 'rest-api' ),
 211      ),
 212      $available_templates
 213  ) : $available_templates;
 214  
 215  // Lock settings.
 216  $user_id = wp_check_post_lock( $post->ID );
 217  if ( $user_id ) {
 218      $locked = false;
 219  
 220      /** This filter is documented in wp-admin/includes/post.php */
 221      if ( apply_filters( 'show_post_locked_dialog', true, $post, $user_id ) ) {
 222          $locked = true;
 223      }
 224  
 225      $user_details = null;
 226      if ( $locked ) {
 227          $user         = get_userdata( $user_id );
 228          $user_details = array(
 229              'name' => $user->display_name,
 230          );
 231  
 232          if ( get_option( 'show_avatars' ) ) {
 233              $user_details['avatar'] = get_avatar_url( $user_id, array( 'size' => 128 ) );
 234          }
 235      }
 236  
 237      $lock_details = array(
 238          'isLocked' => $locked,
 239          'user'     => $user_details,
 240      );
 241  } else {
 242      // Lock the post.
 243      $active_post_lock = wp_set_post_lock( $post->ID );
 244      if ( $active_post_lock ) {
 245          $active_post_lock = esc_attr( implode( ':', $active_post_lock ) );
 246      }
 247  
 248      $lock_details = array(
 249          'isLocked'       => false,
 250          'activePostLock' => $active_post_lock,
 251      );
 252  }
 253  
 254  /**
 255   * Filters the body placeholder text.
 256   *
 257   * @since 5.0.0
 258   * @since 5.8.0 Changed the default placeholder text.
 259   *
 260   * @param string  $text Placeholder text. Default 'Type / to choose a block'.
 261   * @param WP_Post $post Post object.
 262   */
 263  $body_placeholder = apply_filters( 'write_your_story', __( 'Type / to choose a block' ), $post );
 264  
 265  $editor_settings = array(
 266      'availableTemplates'   => $available_templates,
 267      'disablePostFormats'   => ! current_theme_supports( 'post-formats' ),
 268      /** This filter is documented in wp-admin/edit-form-advanced.php */
 269      'titlePlaceholder'     => apply_filters( 'enter_title_here', __( 'Add title' ), $post ),
 270      'bodyPlaceholder'      => $body_placeholder,
 271      'autosaveInterval'     => AUTOSAVE_INTERVAL,
 272      'richEditingEnabled'   => user_can_richedit(),
 273      'postLock'             => $lock_details,
 274      'postLockUtils'        => array(
 275          'nonce'       => wp_create_nonce( 'lock-post_' . $post->ID ),
 276          'unlockNonce' => wp_create_nonce( 'update-post_' . $post->ID ),
 277          'ajaxUrl'     => admin_url( 'admin-ajax.php' ),
 278      ),
 279      'supportsLayout'       => wp_theme_has_theme_json(),
 280      'supportsTemplateMode' => current_theme_supports( 'block-templates' ),
 281  
 282      // Whether or not to load the 'postcustom' meta box is stored as a user meta
 283      // field so that we're not always loading its assets.
 284      'enableCustomFields'   => (bool) get_user_meta( get_current_user_id(), 'enable_custom_fields', true ),
 285  );
 286  
 287  // Add additional back-compat patterns registered by `current_screen` et al.
 288  $editor_settings['__experimentalAdditionalBlockPatterns']          = WP_Block_Patterns_Registry::get_instance()->get_all_registered( true );
 289  $editor_settings['__experimentalAdditionalBlockPatternCategories'] = WP_Block_Pattern_Categories_Registry::get_instance()->get_all_registered( true );
 290  
 291  $autosave = wp_get_post_autosave( $post->ID );
 292  if ( $autosave ) {
 293      if ( mysql2date( 'U', $autosave->post_modified_gmt, false ) > mysql2date( 'U', $post->post_modified_gmt, false ) ) {
 294          $editor_settings['autosave'] = array(
 295              'editLink' => get_edit_post_link( $autosave->ID ),
 296          );
 297      } else {
 298          wp_delete_post_revision( $autosave->ID );
 299      }
 300  }
 301  
 302  if ( ! empty( $post_type_object->template ) ) {
 303      $editor_settings['template']     = $post_type_object->template;
 304      $editor_settings['templateLock'] = ! empty( $post_type_object->template_lock ) ? $post_type_object->template_lock : false;
 305  }
 306  
 307  // If there's no template set on a new post, use the post format, instead.
 308  if ( $is_new_post && ! isset( $editor_settings['template'] ) && 'post' === $post->post_type ) {
 309      $post_format = get_post_format( $post );
 310      if ( in_array( $post_format, array( 'audio', 'gallery', 'image', 'quote', 'video' ), true ) ) {
 311          $editor_settings['template'] = array( array( "core/$post_format" ) );
 312      }
 313  }
 314  
 315  if ( wp_is_block_theme() && $editor_settings['supportsTemplateMode'] ) {
 316      $editor_settings['defaultTemplatePartAreas'] = get_allowed_block_template_part_areas();
 317  }
 318  
 319  /**
 320   * Scripts
 321   */
 322  wp_enqueue_media(
 323      array(
 324          'post' => $post->ID,
 325      )
 326  );
 327  wp_tinymce_inline_scripts();
 328  wp_enqueue_editor();
 329  
 330  /**
 331   * Styles
 332   */
 333  wp_enqueue_style( 'wp-edit-post' );
 334  
 335  /**
 336   * Fires after block assets have been enqueued for the editing interface.
 337   *
 338   * Call `add_action` on any hook before 'admin_enqueue_scripts'.
 339   *
 340   * In the function call you supply, simply use `wp_enqueue_script` and
 341   * `wp_enqueue_style` to add your functionality to the block editor.
 342   *
 343   * @since 5.0.0
 344   */
 345  do_action( 'enqueue_block_editor_assets' );
 346  
 347  // In order to duplicate classic meta box behavior, we need to run the classic meta box actions.
 348  require_once  ABSPATH . 'wp-admin/includes/meta-boxes.php';
 349  register_and_do_post_meta_boxes( $post );
 350  
 351  // Check if the Custom Fields meta box has been removed at some point.
 352  $core_meta_boxes = $wp_meta_boxes[ $current_screen->id ]['normal']['core'];
 353  if ( ! isset( $core_meta_boxes['postcustom'] ) || ! $core_meta_boxes['postcustom'] ) {
 354      unset( $editor_settings['enableCustomFields'] );
 355  }
 356  
 357  $editor_settings = get_block_editor_settings( $editor_settings, $block_editor_context );
 358  
 359  $init_script = <<<JS
 360  ( function() {
 361      window._wpLoadBlockEditor = new Promise( function( resolve ) {
 362          wp.domReady( function() {
 363              resolve( wp.editPost.initializeEditor( 'editor', "%s", %d, %s, %s ) );
 364          } );
 365      } );
 366  } )();
 367  JS;
 368  
 369  $script = sprintf(
 370      $init_script,
 371      $post->post_type,
 372      $post->ID,
 373      wp_json_encode( $editor_settings, JSON_HEX_TAG | JSON_UNESCAPED_SLASHES ),
 374      wp_json_encode( $initial_edits, JSON_HEX_TAG | JSON_UNESCAPED_SLASHES )
 375  );
 376  wp_add_inline_script( 'wp-edit-post', $script );
 377  
 378  if ( (int) get_option( 'page_for_posts' ) === $post->ID ) {
 379      add_action( 'admin_enqueue_scripts', '_wp_block_editor_posts_page_notice' );
 380  }
 381  
 382  require_once  ABSPATH . 'wp-admin/admin-header.php';
 383  ?>
 384  
 385  <div class="block-editor">
 386      <h1 class="screen-reader-text hide-if-no-js"><?php echo esc_html( $title ); ?></h1>
 387      <div id="editor" class="block-editor__container hide-if-no-js"></div>
 388      <div id="metaboxes" class="hidden">
 389          <?php the_block_editor_meta_boxes(); ?>
 390      </div>
 391  
 392      <?php // JavaScript is disabled. ?>
 393      <div class="wrap hide-if-js block-editor-no-js">
 394          <h1 class="wp-heading-inline"><?php echo esc_html( $title ); ?></h1>
 395          <?php
 396          if ( file_exists( WP_PLUGIN_DIR . '/classic-editor/classic-editor.php' ) ) {
 397              // If Classic Editor is already installed, provide a link to activate the plugin.
 398              $installed           = true;
 399              $plugin_activate_url = wp_nonce_url( 'plugins.php?action=activate&amp;plugin=classic-editor/classic-editor.php', 'activate-plugin_classic-editor/classic-editor.php' );
 400              $message             = sprintf(
 401                  /* translators: %s: Link to activate the Classic Editor plugin. */
 402                  __( 'The block editor requires JavaScript. Please enable JavaScript in your browser settings, or activate the <a href="%s">Classic Editor plugin</a>.' ),
 403                  esc_url( $plugin_activate_url )
 404              );
 405          } else {
 406              // If Classic Editor is not installed, provide a link to install it.
 407              $installed          = false;
 408              $plugin_install_url = wp_nonce_url( self_admin_url( 'update.php?action=install-plugin&plugin=classic-editor' ), 'install-plugin_classic-editor' );
 409              $message            = sprintf(
 410                  /* translators: %s: Link to install the Classic Editor plugin. */
 411                  __( 'The block editor requires JavaScript. Please enable JavaScript in your browser settings, or install the <a href="%s">Classic Editor plugin</a>.' ),
 412                  esc_url( $plugin_install_url )
 413              );
 414          }
 415  
 416          /**
 417           * Filters the message displayed in the block editor interface when JavaScript is
 418           * not enabled in the browser.
 419           *
 420           * @since 5.0.3
 421           * @since 6.4.0 Added `$installed` parameter.
 422           *
 423           * @param string  $message   The message being displayed.
 424           * @param WP_Post $post      The post being edited.
 425           * @param bool    $installed Whether the classic editor is installed.
 426           */
 427          $message = apply_filters( 'block_editor_no_javascript_message', $message, $post, $installed );
 428          wp_admin_notice(
 429              $message,
 430              array(
 431                  'type' => 'error',
 432              )
 433          );
 434          ?>
 435      </div>
 436  </div>


Generated : Wed Apr 15 08:20:10 2026 Cross-referenced by PHPXref