block-editor.php 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696
  1. <?php
  2. /**
  3. * Block Editor API.
  4. *
  5. * @package WordPress
  6. * @subpackage Editor
  7. * @since 5.8.0
  8. */
  9. /**
  10. * Returns the list of default categories for block types.
  11. *
  12. * @since 5.8.0
  13. *
  14. * @return array[] Array of categories for block types.
  15. */
  16. function get_default_block_categories() {
  17. return array(
  18. array(
  19. 'slug' => 'text',
  20. 'title' => _x( 'Text', 'block category' ),
  21. 'icon' => null,
  22. ),
  23. array(
  24. 'slug' => 'media',
  25. 'title' => _x( 'Media', 'block category' ),
  26. 'icon' => null,
  27. ),
  28. array(
  29. 'slug' => 'design',
  30. 'title' => _x( 'Design', 'block category' ),
  31. 'icon' => null,
  32. ),
  33. array(
  34. 'slug' => 'widgets',
  35. 'title' => _x( 'Widgets', 'block category' ),
  36. 'icon' => null,
  37. ),
  38. array(
  39. 'slug' => 'theme',
  40. 'title' => _x( 'Theme', 'block category' ),
  41. 'icon' => null,
  42. ),
  43. array(
  44. 'slug' => 'embed',
  45. 'title' => _x( 'Embeds', 'block category' ),
  46. 'icon' => null,
  47. ),
  48. array(
  49. 'slug' => 'reusable',
  50. 'title' => _x( 'Reusable Blocks', 'block category' ),
  51. 'icon' => null,
  52. ),
  53. );
  54. }
  55. /**
  56. * Returns all the categories for block types that will be shown in the block editor.
  57. *
  58. * @since 5.0.0
  59. * @since 5.8.0 It is possible to pass the block editor context as param.
  60. *
  61. * @param WP_Post|WP_Block_Editor_Context $post_or_block_editor_context The current post object or
  62. * the block editor context.
  63. *
  64. * @return array[] Array of categories for block types.
  65. */
  66. function get_block_categories( $post_or_block_editor_context ) {
  67. $block_categories = get_default_block_categories();
  68. $block_editor_context = $post_or_block_editor_context instanceof WP_Post ?
  69. new WP_Block_Editor_Context(
  70. array(
  71. 'post' => $post_or_block_editor_context,
  72. )
  73. ) : $post_or_block_editor_context;
  74. /**
  75. * Filters the default array of categories for block types.
  76. *
  77. * @since 5.8.0
  78. *
  79. * @param array[] $block_categories Array of categories for block types.
  80. * @param WP_Block_Editor_Context $block_editor_context The current block editor context.
  81. */
  82. $block_categories = apply_filters( 'block_categories_all', $block_categories, $block_editor_context );
  83. if ( ! empty( $block_editor_context->post ) ) {
  84. $post = $block_editor_context->post;
  85. /**
  86. * Filters the default array of categories for block types.
  87. *
  88. * @since 5.0.0
  89. * @deprecated 5.8.0 Use the {@see 'block_categories_all'} filter instead.
  90. *
  91. * @param array[] $block_categories Array of categories for block types.
  92. * @param WP_Post $post Post being loaded.
  93. */
  94. $block_categories = apply_filters_deprecated( 'block_categories', array( $block_categories, $post ), '5.8.0', 'block_categories_all' );
  95. }
  96. return $block_categories;
  97. }
  98. /**
  99. * Gets the list of allowed block types to use in the block editor.
  100. *
  101. * @since 5.8.0
  102. *
  103. * @param WP_Block_Editor_Context $block_editor_context The current block editor context.
  104. *
  105. * @return bool|string[] Array of block type slugs, or boolean to enable/disable all.
  106. */
  107. function get_allowed_block_types( $block_editor_context ) {
  108. $allowed_block_types = true;
  109. /**
  110. * Filters the allowed block types for all editor types.
  111. *
  112. * @since 5.8.0
  113. *
  114. * @param bool|string[] $allowed_block_types Array of block type slugs, or boolean to enable/disable all.
  115. * Default true (all registered block types supported).
  116. * @param WP_Block_Editor_Context $block_editor_context The current block editor context.
  117. */
  118. $allowed_block_types = apply_filters( 'allowed_block_types_all', $allowed_block_types, $block_editor_context );
  119. if ( ! empty( $block_editor_context->post ) ) {
  120. $post = $block_editor_context->post;
  121. /**
  122. * Filters the allowed block types for the editor.
  123. *
  124. * @since 5.0.0
  125. * @deprecated 5.8.0 Use the {@see 'allowed_block_types_all'} filter instead.
  126. *
  127. * @param bool|string[] $allowed_block_types Array of block type slugs, or boolean to enable/disable all.
  128. * Default true (all registered block types supported)
  129. * @param WP_Post $post The post resource data.
  130. */
  131. $allowed_block_types = apply_filters_deprecated( 'allowed_block_types', array( $allowed_block_types, $post ), '5.8.0', 'allowed_block_types_all' );
  132. }
  133. return $allowed_block_types;
  134. }
  135. /**
  136. * Returns the default block editor settings.
  137. *
  138. * @since 5.8.0
  139. *
  140. * @return array The default block editor settings.
  141. */
  142. function get_default_block_editor_settings() {
  143. // Media settings.
  144. // wp_max_upload_size() can be expensive, so only call it when relevant for the current user.
  145. $max_upload_size = 0;
  146. if ( current_user_can( 'upload_files' ) ) {
  147. $max_upload_size = wp_max_upload_size();
  148. if ( ! $max_upload_size ) {
  149. $max_upload_size = 0;
  150. }
  151. }
  152. /** This filter is documented in wp-admin/includes/media.php */
  153. $image_size_names = apply_filters(
  154. 'image_size_names_choose',
  155. array(
  156. 'thumbnail' => __( 'Thumbnail' ),
  157. 'medium' => __( 'Medium' ),
  158. 'large' => __( 'Large' ),
  159. 'full' => __( 'Full Size' ),
  160. )
  161. );
  162. $available_image_sizes = array();
  163. foreach ( $image_size_names as $image_size_slug => $image_size_name ) {
  164. $available_image_sizes[] = array(
  165. 'slug' => $image_size_slug,
  166. 'name' => $image_size_name,
  167. );
  168. }
  169. $default_size = get_option( 'image_default_size', 'large' );
  170. $image_default_size = in_array( $default_size, array_keys( $image_size_names ), true ) ? $default_size : 'large';
  171. $image_dimensions = array();
  172. $all_sizes = wp_get_registered_image_subsizes();
  173. foreach ( $available_image_sizes as $size ) {
  174. $key = $size['slug'];
  175. if ( isset( $all_sizes[ $key ] ) ) {
  176. $image_dimensions[ $key ] = $all_sizes[ $key ];
  177. }
  178. }
  179. // These styles are used if the "no theme styles" options is triggered or on
  180. // themes without their own editor styles.
  181. $default_editor_styles_file = ABSPATH . WPINC . '/css/dist/block-editor/default-editor-styles.css';
  182. static $default_editor_styles_file_contents = false;
  183. if ( ! $default_editor_styles_file_contents && file_exists( $default_editor_styles_file ) ) {
  184. $default_editor_styles_file_contents = file_get_contents( $default_editor_styles_file );
  185. }
  186. $default_editor_styles = array();
  187. if ( $default_editor_styles_file_contents ) {
  188. $default_editor_styles = array(
  189. array( 'css' => $default_editor_styles_file_contents ),
  190. );
  191. }
  192. $editor_settings = array(
  193. 'alignWide' => get_theme_support( 'align-wide' ),
  194. 'allowedBlockTypes' => true,
  195. 'allowedMimeTypes' => get_allowed_mime_types(),
  196. 'defaultEditorStyles' => $default_editor_styles,
  197. 'blockCategories' => get_default_block_categories(),
  198. 'disableCustomColors' => get_theme_support( 'disable-custom-colors' ),
  199. 'disableCustomFontSizes' => get_theme_support( 'disable-custom-font-sizes' ),
  200. 'disableCustomGradients' => get_theme_support( 'disable-custom-gradients' ),
  201. 'disableLayoutStyles' => get_theme_support( 'disable-layout-styles' ),
  202. 'enableCustomLineHeight' => get_theme_support( 'custom-line-height' ),
  203. 'enableCustomSpacing' => get_theme_support( 'custom-spacing' ),
  204. 'enableCustomUnits' => get_theme_support( 'custom-units' ),
  205. 'isRTL' => is_rtl(),
  206. 'imageDefaultSize' => $image_default_size,
  207. 'imageDimensions' => $image_dimensions,
  208. 'imageEditing' => true,
  209. 'imageSizes' => $available_image_sizes,
  210. 'maxUploadFileSize' => $max_upload_size,
  211. // The following flag is required to enable the new Gallery block format on the mobile apps in 5.9.
  212. '__unstableGalleryWithImageBlocks' => true,
  213. );
  214. // Theme settings.
  215. $color_palette = current( (array) get_theme_support( 'editor-color-palette' ) );
  216. if ( false !== $color_palette ) {
  217. $editor_settings['colors'] = $color_palette;
  218. }
  219. $font_sizes = current( (array) get_theme_support( 'editor-font-sizes' ) );
  220. if ( false !== $font_sizes ) {
  221. $editor_settings['fontSizes'] = $font_sizes;
  222. }
  223. $gradient_presets = current( (array) get_theme_support( 'editor-gradient-presets' ) );
  224. if ( false !== $gradient_presets ) {
  225. $editor_settings['gradients'] = $gradient_presets;
  226. }
  227. return $editor_settings;
  228. }
  229. /**
  230. * Returns the block editor settings needed to use the Legacy Widget block which
  231. * is not registered by default.
  232. *
  233. * @since 5.8.0
  234. *
  235. * @return array Settings to be used with get_block_editor_settings().
  236. */
  237. function get_legacy_widget_block_editor_settings() {
  238. $editor_settings = array();
  239. /**
  240. * Filters the list of widget-type IDs that should **not** be offered by the
  241. * Legacy Widget block.
  242. *
  243. * Returning an empty array will make all widgets available.
  244. *
  245. * @since 5.8.0
  246. *
  247. * @param string[] $widgets An array of excluded widget-type IDs.
  248. */
  249. $editor_settings['widgetTypesToHideFromLegacyWidgetBlock'] = apply_filters(
  250. 'widget_types_to_hide_from_legacy_widget_block',
  251. array(
  252. 'pages',
  253. 'calendar',
  254. 'archives',
  255. 'media_audio',
  256. 'media_image',
  257. 'media_gallery',
  258. 'media_video',
  259. 'search',
  260. 'text',
  261. 'categories',
  262. 'recent-posts',
  263. 'recent-comments',
  264. 'rss',
  265. 'tag_cloud',
  266. 'custom_html',
  267. 'block',
  268. )
  269. );
  270. return $editor_settings;
  271. }
  272. /**
  273. * Collect the block editor assets that need to be loaded into the editor's iframe.
  274. *
  275. * @since 6.0.0
  276. * @access private
  277. *
  278. * @global string $pagenow The filename of the current screen.
  279. *
  280. * @return array {
  281. * The block editor assets.
  282. *
  283. * @type string|false $styles String containing the HTML for styles.
  284. * @type string|false $scripts String containing the HTML for scripts.
  285. * }
  286. */
  287. function _wp_get_iframed_editor_assets() {
  288. global $pagenow;
  289. $script_handles = array();
  290. $style_handles = array(
  291. 'wp-block-editor',
  292. 'wp-block-library',
  293. 'wp-edit-blocks',
  294. );
  295. if ( current_theme_supports( 'wp-block-styles' ) ) {
  296. $style_handles[] = 'wp-block-library-theme';
  297. }
  298. if ( 'widgets.php' === $pagenow || 'customize.php' === $pagenow ) {
  299. $style_handles[] = 'wp-widgets';
  300. $style_handles[] = 'wp-edit-widgets';
  301. }
  302. $block_registry = WP_Block_Type_Registry::get_instance();
  303. foreach ( $block_registry->get_all_registered() as $block_type ) {
  304. $style_handles = array_merge(
  305. $style_handles,
  306. $block_type->style_handles,
  307. $block_type->editor_style_handles
  308. );
  309. $script_handles = array_merge(
  310. $script_handles,
  311. $block_type->script_handles
  312. );
  313. }
  314. $style_handles = array_unique( $style_handles );
  315. $done = wp_styles()->done;
  316. ob_start();
  317. // We do not need reset styles for the iframed editor.
  318. wp_styles()->done = array( 'wp-reset-editor-styles' );
  319. wp_styles()->do_items( $style_handles );
  320. wp_styles()->done = $done;
  321. $styles = ob_get_clean();
  322. $script_handles = array_unique( $script_handles );
  323. $done = wp_scripts()->done;
  324. ob_start();
  325. wp_scripts()->done = array();
  326. wp_scripts()->do_items( $script_handles );
  327. wp_scripts()->done = $done;
  328. $scripts = ob_get_clean();
  329. return array(
  330. 'styles' => $styles,
  331. 'scripts' => $scripts,
  332. );
  333. }
  334. /**
  335. * Returns the contextualized block editor settings for a selected editor context.
  336. *
  337. * @since 5.8.0
  338. *
  339. * @param array $custom_settings Custom settings to use with the given editor type.
  340. * @param WP_Block_Editor_Context $block_editor_context The current block editor context.
  341. *
  342. * @return array The contextualized block editor settings.
  343. */
  344. function get_block_editor_settings( array $custom_settings, $block_editor_context ) {
  345. $editor_settings = array_merge(
  346. get_default_block_editor_settings(),
  347. array(
  348. 'allowedBlockTypes' => get_allowed_block_types( $block_editor_context ),
  349. 'blockCategories' => get_block_categories( $block_editor_context ),
  350. ),
  351. $custom_settings
  352. );
  353. $global_styles = array();
  354. $presets = array(
  355. array(
  356. 'css' => 'variables',
  357. '__unstableType' => 'presets',
  358. 'isGlobalStyles' => true,
  359. ),
  360. array(
  361. 'css' => 'presets',
  362. '__unstableType' => 'presets',
  363. 'isGlobalStyles' => true,
  364. ),
  365. );
  366. foreach ( $presets as $preset_style ) {
  367. $actual_css = wp_get_global_stylesheet( array( $preset_style['css'] ) );
  368. if ( '' !== $actual_css ) {
  369. $preset_style['css'] = $actual_css;
  370. $global_styles[] = $preset_style;
  371. }
  372. }
  373. if ( WP_Theme_JSON_Resolver::theme_has_support() ) {
  374. $block_classes = array(
  375. 'css' => 'styles',
  376. '__unstableType' => 'theme',
  377. 'isGlobalStyles' => true,
  378. );
  379. $actual_css = wp_get_global_stylesheet( array( $block_classes['css'] ) );
  380. if ( '' !== $actual_css ) {
  381. $block_classes['css'] = $actual_css;
  382. $global_styles[] = $block_classes;
  383. }
  384. } else {
  385. // If there is no `theme.json` file, ensure base layout styles are still available.
  386. $block_classes = array(
  387. 'css' => 'base-layout-styles',
  388. '__unstableType' => 'base-layout',
  389. 'isGlobalStyles' => true,
  390. );
  391. $actual_css = wp_get_global_stylesheet( array( $block_classes['css'] ) );
  392. if ( '' !== $actual_css ) {
  393. $block_classes['css'] = $actual_css;
  394. $global_styles[] = $block_classes;
  395. }
  396. }
  397. $editor_settings['styles'] = array_merge( $global_styles, get_block_editor_theme_styles() );
  398. $editor_settings['__experimentalFeatures'] = wp_get_global_settings();
  399. // These settings may need to be updated based on data coming from theme.json sources.
  400. if ( isset( $editor_settings['__experimentalFeatures']['color']['palette'] ) ) {
  401. $colors_by_origin = $editor_settings['__experimentalFeatures']['color']['palette'];
  402. $editor_settings['colors'] = isset( $colors_by_origin['custom'] ) ?
  403. $colors_by_origin['custom'] : (
  404. isset( $colors_by_origin['theme'] ) ?
  405. $colors_by_origin['theme'] :
  406. $colors_by_origin['default']
  407. );
  408. }
  409. if ( isset( $editor_settings['__experimentalFeatures']['color']['gradients'] ) ) {
  410. $gradients_by_origin = $editor_settings['__experimentalFeatures']['color']['gradients'];
  411. $editor_settings['gradients'] = isset( $gradients_by_origin['custom'] ) ?
  412. $gradients_by_origin['custom'] : (
  413. isset( $gradients_by_origin['theme'] ) ?
  414. $gradients_by_origin['theme'] :
  415. $gradients_by_origin['default']
  416. );
  417. }
  418. if ( isset( $editor_settings['__experimentalFeatures']['typography']['fontSizes'] ) ) {
  419. $font_sizes_by_origin = $editor_settings['__experimentalFeatures']['typography']['fontSizes'];
  420. $editor_settings['fontSizes'] = isset( $font_sizes_by_origin['custom'] ) ?
  421. $font_sizes_by_origin['custom'] : (
  422. isset( $font_sizes_by_origin['theme'] ) ?
  423. $font_sizes_by_origin['theme'] :
  424. $font_sizes_by_origin['default']
  425. );
  426. }
  427. if ( isset( $editor_settings['__experimentalFeatures']['color']['custom'] ) ) {
  428. $editor_settings['disableCustomColors'] = ! $editor_settings['__experimentalFeatures']['color']['custom'];
  429. unset( $editor_settings['__experimentalFeatures']['color']['custom'] );
  430. }
  431. if ( isset( $editor_settings['__experimentalFeatures']['color']['customGradient'] ) ) {
  432. $editor_settings['disableCustomGradients'] = ! $editor_settings['__experimentalFeatures']['color']['customGradient'];
  433. unset( $editor_settings['__experimentalFeatures']['color']['customGradient'] );
  434. }
  435. if ( isset( $editor_settings['__experimentalFeatures']['typography']['customFontSize'] ) ) {
  436. $editor_settings['disableCustomFontSizes'] = ! $editor_settings['__experimentalFeatures']['typography']['customFontSize'];
  437. unset( $editor_settings['__experimentalFeatures']['typography']['customFontSize'] );
  438. }
  439. if ( isset( $editor_settings['__experimentalFeatures']['typography']['lineHeight'] ) ) {
  440. $editor_settings['enableCustomLineHeight'] = $editor_settings['__experimentalFeatures']['typography']['lineHeight'];
  441. unset( $editor_settings['__experimentalFeatures']['typography']['lineHeight'] );
  442. }
  443. if ( isset( $editor_settings['__experimentalFeatures']['spacing']['units'] ) ) {
  444. $editor_settings['enableCustomUnits'] = $editor_settings['__experimentalFeatures']['spacing']['units'];
  445. unset( $editor_settings['__experimentalFeatures']['spacing']['units'] );
  446. }
  447. if ( isset( $editor_settings['__experimentalFeatures']['spacing']['padding'] ) ) {
  448. $editor_settings['enableCustomSpacing'] = $editor_settings['__experimentalFeatures']['spacing']['padding'];
  449. unset( $editor_settings['__experimentalFeatures']['spacing']['padding'] );
  450. }
  451. if ( isset( $editor_settings['__experimentalFeatures']['spacing']['customSpacingSize'] ) ) {
  452. $editor_settings['disableCustomSpacingSizes'] = ! $editor_settings['__experimentalFeatures']['spacing']['customSpacingSize'];
  453. unset( $editor_settings['__experimentalFeatures']['spacing']['customSpacingSize'] );
  454. }
  455. if ( isset( $editor_settings['__experimentalFeatures']['spacing']['spacingSizes'] ) ) {
  456. $spacing_sizes_by_origin = $editor_settings['__experimentalFeatures']['spacing']['spacingSizes'];
  457. $editor_settings['spacingSizes'] = isset( $spacing_sizes_by_origin['custom'] ) ?
  458. $spacing_sizes_by_origin['custom'] : (
  459. isset( $spacing_sizes_by_origin['theme'] ) ?
  460. $spacing_sizes_by_origin['theme'] :
  461. $spacing_sizes_by_origin['default']
  462. );
  463. }
  464. $editor_settings['__unstableResolvedAssets'] = _wp_get_iframed_editor_assets();
  465. $editor_settings['localAutosaveInterval'] = 15;
  466. $editor_settings['disableLayoutStyles'] = current_theme_supports( 'disable-layout-styles' );
  467. $editor_settings['__experimentalDiscussionSettings'] = array(
  468. 'commentOrder' => get_option( 'comment_order' ),
  469. 'commentsPerPage' => get_option( 'comments_per_page' ),
  470. 'defaultCommentsPage' => get_option( 'default_comments_page' ),
  471. 'pageComments' => get_option( 'page_comments' ),
  472. 'threadComments' => get_option( 'thread_comments' ),
  473. 'threadCommentsDepth' => get_option( 'thread_comments_depth' ),
  474. 'defaultCommentStatus' => get_option( 'default_comment_status' ),
  475. 'avatarURL' => get_avatar_url(
  476. '',
  477. array(
  478. 'size' => 96,
  479. 'force_default' => true,
  480. 'default' => get_option( 'avatar_default' ),
  481. )
  482. ),
  483. );
  484. /**
  485. * Filters the settings to pass to the block editor for all editor type.
  486. *
  487. * @since 5.8.0
  488. *
  489. * @param array $editor_settings Default editor settings.
  490. * @param WP_Block_Editor_Context $block_editor_context The current block editor context.
  491. */
  492. $editor_settings = apply_filters( 'block_editor_settings_all', $editor_settings, $block_editor_context );
  493. if ( ! empty( $block_editor_context->post ) ) {
  494. $post = $block_editor_context->post;
  495. /**
  496. * Filters the settings to pass to the block editor.
  497. *
  498. * @since 5.0.0
  499. * @deprecated 5.8.0 Use the {@see 'block_editor_settings_all'} filter instead.
  500. *
  501. * @param array $editor_settings Default editor settings.
  502. * @param WP_Post $post Post being edited.
  503. */
  504. $editor_settings = apply_filters_deprecated( 'block_editor_settings', array( $editor_settings, $post ), '5.8.0', 'block_editor_settings_all' );
  505. }
  506. return $editor_settings;
  507. }
  508. /**
  509. * Preloads common data used with the block editor by specifying an array of
  510. * REST API paths that will be preloaded for a given block editor context.
  511. *
  512. * @since 5.8.0
  513. *
  514. * @global WP_Post $post Global post object.
  515. * @global WP_Scripts $wp_scripts The WP_Scripts object for printing scripts.
  516. * @global WP_Styles $wp_styles The WP_Styles object for printing styles.
  517. *
  518. * @param string[] $preload_paths List of paths to preload.
  519. * @param WP_Block_Editor_Context $block_editor_context The current block editor context.
  520. */
  521. function block_editor_rest_api_preload( array $preload_paths, $block_editor_context ) {
  522. global $post, $wp_scripts, $wp_styles;
  523. /**
  524. * Filters the array of REST API paths that will be used to preloaded common data for the block editor.
  525. *
  526. * @since 5.8.0
  527. *
  528. * @param string[] $preload_paths Array of paths to preload.
  529. * @param WP_Block_Editor_Context $block_editor_context The current block editor context.
  530. */
  531. $preload_paths = apply_filters( 'block_editor_rest_api_preload_paths', $preload_paths, $block_editor_context );
  532. if ( ! empty( $block_editor_context->post ) ) {
  533. $selected_post = $block_editor_context->post;
  534. /**
  535. * Filters the array of paths that will be preloaded.
  536. *
  537. * Preload common data by specifying an array of REST API paths that will be preloaded.
  538. *
  539. * @since 5.0.0
  540. * @deprecated 5.8.0 Use the {@see 'block_editor_rest_api_preload_paths'} filter instead.
  541. *
  542. * @param string[] $preload_paths Array of paths to preload.
  543. * @param WP_Post $selected_post Post being edited.
  544. */
  545. $preload_paths = apply_filters_deprecated( 'block_editor_preload_paths', array( $preload_paths, $selected_post ), '5.8.0', 'block_editor_rest_api_preload_paths' );
  546. }
  547. if ( empty( $preload_paths ) ) {
  548. return;
  549. }
  550. /*
  551. * Ensure the global $post, $wp_scripts, and $wp_styles remain the same after
  552. * API data is preloaded.
  553. * Because API preloading can call the_content and other filters, plugins
  554. * can unexpectedly modify the global $post or enqueue assets which are not
  555. * intended for the block editor.
  556. */
  557. $backup_global_post = ! empty( $post ) ? clone $post : $post;
  558. $backup_wp_scripts = ! empty( $wp_scripts ) ? clone $wp_scripts : $wp_scripts;
  559. $backup_wp_styles = ! empty( $wp_styles ) ? clone $wp_styles : $wp_styles;
  560. foreach ( $preload_paths as &$path ) {
  561. if ( is_string( $path ) && ! str_starts_with( $path, '/' ) ) {
  562. $path = '/' . $path;
  563. continue;
  564. }
  565. if ( is_array( $path ) && is_string( $path[0] ) && ! str_starts_with( $path[0], '/' ) ) {
  566. $path[0] = '/' . $path[0];
  567. }
  568. }
  569. unset( $path );
  570. $preload_data = array_reduce(
  571. $preload_paths,
  572. 'rest_preload_api_request',
  573. array()
  574. );
  575. // Restore the global $post, $wp_scripts, and $wp_styles as they were before API preloading.
  576. $post = $backup_global_post;
  577. $wp_scripts = $backup_wp_scripts;
  578. $wp_styles = $backup_wp_styles;
  579. wp_add_inline_script(
  580. 'wp-api-fetch',
  581. sprintf(
  582. 'wp.apiFetch.use( wp.apiFetch.createPreloadingMiddleware( %s ) );',
  583. wp_json_encode( $preload_data )
  584. ),
  585. 'after'
  586. );
  587. }
  588. /**
  589. * Creates an array of theme styles to load into the block editor.
  590. *
  591. * @since 5.8.0
  592. *
  593. * @global array $editor_styles
  594. *
  595. * @return array An array of theme styles for the block editor.
  596. */
  597. function get_block_editor_theme_styles() {
  598. global $editor_styles;
  599. $styles = array();
  600. if ( $editor_styles && current_theme_supports( 'editor-styles' ) ) {
  601. foreach ( $editor_styles as $style ) {
  602. if ( preg_match( '~^(https?:)?//~', $style ) ) {
  603. $response = wp_remote_get( $style );
  604. if ( ! is_wp_error( $response ) ) {
  605. $styles[] = array(
  606. 'css' => wp_remote_retrieve_body( $response ),
  607. '__unstableType' => 'theme',
  608. 'isGlobalStyles' => false,
  609. );
  610. }
  611. } else {
  612. $file = get_theme_file_path( $style );
  613. if ( is_file( $file ) ) {
  614. $styles[] = array(
  615. 'css' => file_get_contents( $file ),
  616. 'baseURL' => get_theme_file_uri( $style ),
  617. '__unstableType' => 'theme',
  618. 'isGlobalStyles' => false,
  619. );
  620. }
  621. }
  622. }
  623. }
  624. return $styles;
  625. }