Block Editor Detection Improvements in 5.2

In 5.0, WP_Screen::is_block_editor() was introduced to allow developers to conditionally execute code depending on whether the block editor is being loaded. This method returns the is_block_editor property of the WP_Screen instance. However, there were some large gaps in the loading process where an incorrect value could potentially be returned.

For example, when using the current_screen action hook, the value was always false, even when the user was visiting a block editor enabled screen. This happened because block editor support is flagged much later in the loading process when edit-form-blocks.php is included.

function myplugin_current_screen( $screen ) {
	if ( $screen->is_block_editor ) {
		// This conditional would never execute.
add_action( 'current_screen', 'myplugin_current_screen' );

This has been fixed in 5.2 to account for all possible scenarios when a post is edited. However, there are still a few very narrow edge cases when a new post is created where WP_Screen::is_block_editor() may still incorrectly indicate block editor support.

Edge Cases When Creating New Posts

The use_block_editor_for_post() function and replace_editor filter require a WP_Post object to be passed as a parameter. Because a new post has not yet been created when WP_Screen is instantiated, it can only make its best guess whether the page is loading the block editor.

When creating a new post, WP_Screen will set is_block_editor property to the value returned by use_block_editor_for_post_type() for the current post type. In most cases, this guess will be correct. But, the following scenarios have edge cases to consider.

  • When the replace_editor filter is used to replace the editor, this value may be incorrect.
  • When the use_block_editor_for_post filter is used to change block editor support.

For both of these scenarios, the use_block_editor_for_post_type filter can be used to ensure the correct value in most circumstances.

function myplugin_replace_editor_filter( $replace_editor, $post ) {
	// Logic to replace editor.
add_filter( 'replace_editor', 'myplugin_replace_editor_filter', 10, 2 );

function myplugin_replace_editor_post_type( $use_block_editor, $post_type ) {
	// Similar logic to replace editor, but without a WP_Post object to work with.
add_filter( 'use_block_editor_for_post_type', 'myplugin_replace_editor_post_type', 10, 2 );

With this filter, all scenarios that do not require checking a specific property of a post (a taxonomy term, meta value, etc.) can be accounted for. For example, filtering based on user capability, site option, or user meta value for editor preference are all possible using use_block_editor_for_post_type.

When WordPress creates a new post, it uses the get_default_post_to_edit() function. This function creates a new post in the database using wp_insert_post() and then allows the default content, title, and excerpt to be filtered. When terms, post meta, or content are added to posts with actions such as save_post or wp_insert_post, it is possible that this could change the block editor support for the post being created.

This scenario would result in WP_Screen:is_block_editor possessing an incorrect value from the current_screen action until roughly the load-{$pagenow} action.

Logic should be added to the use_block_editor_for_post_type filter to account for these scenarios (which are normally post type specific) and guarantee the accuracy of WP_Screen::is_block_editor().

For more information on this, consult the ticket on Trac (#46195), or the changeset ([45224]).

#5-2, #block-editor, #dev-notes, #gutenberg

Fatal Error Recovery Mode in 5.2

WordPress 5.2 will allow administrators to fix or mitigate fatal errors on their site that would previously have been impossible to address without developer interference and modifying the codebase. Even in the case where a fatal error would commonly have made the backend completely inaccessible (for example through a so-called “white screen of death”), administrators will now still have the chance to log in and do something about the issue.

When a fatal error occurs, a user-facing error screen will display that informs the user/visitor that the site is experiencing technical difficulties. More importantly though, when such an error occurs, an email will be sent to the admin email address, informing about the issue and including a secret link to new feature called the “recovery mode”. Clicking this link will have the user enter this recovery mode, which works by placing a cookie on the current client.

When in recovery mode, plugins and themes (also referred to as “extensions”) which are causing a fatal error are paused for that client, ensuring they can work around these errors and access their admin backend as regularly. After entering recovery mode, the user needs to log in. It should be highlighted though that recovery mode itself is not tied to a specific user, but only to the cookie existing on the client.

After logging in, an admin notice will indicate that recovery mode is enabled. Furthermore, the user will be informed about which plugins/themes are currently paused due to fatal errors, and what exactly these errors are. They then have the possibility to address the issue in their preferred way:

  • They can completely deactivate the extension, e.g. when maintaining a working version of the site matters more than that extension’s functionality. This is typically a temporary solution, but provides an immediate resolution.
  • They can fix the problem if they have the technical capabilities, and afterwards resume the extension.
  • They can file a support ticket with the author of the respective extension or contact a developer, pointing out the exact error.

At any time, the user can decide to exit recovery mode, by clicking a button that permanently appears in the admin bar while in recovery mode. Exiting recovery mode will wipe the cookie from the client and thus cause all extensions to run as usual again. Keep in mind that if an extension is still broken, the fatal error will remain.

Admin backend while in recovery mode. Highlighted are the notice and the exit button in the admin bar, indicating recovery mode is active.
Admin backend while in recovery mode

The main benefit of recovery mode is to inform administrators about fatal errors on their site and allow them to still access their backend and decide what to do about the problem, rather than presenting them with the typical “white screen of death” which they cannot do anything about. It is impossible to automatically fix such errors, but recovery mode allows working around them by pausing the broken extensions. Pausing only happens for the client that is in recovery mode, and thus does not have any global implications. With a broken extension, only the user in recovery mode can access the broken areas; for the other users the site remains in a broken state until the issue has been fixed or mitigated.


There are a couple of ways that developers can integrate with the new recovery mode features:

  • Plugins that would like to enhance recovery mode can call a new function wp_is_recovery_mode() to check for whether it is active.
  • Environments can override the way that recovery mode is set up and validated if they prefer to use a different method or to purely enable it via code. A must-use plugin for example can set a constant WP_RECOVERY_MODE_SESSION_ID that needs to contain an arbitrary session ID, which will then be used to store recovery mode-specific data for that session. Having the constant available will force-enable recovery mode. However, this mechanism must be used with special care, as setting the constant unconditionally would result in recovery mode being globally enabled.
  • The template for the screen indicating that a fatal error occurred can be customized by using a php-error.php drop-in, similar to other previously existing drop-ins such as db-error.php.
  • The entire shutdown handler can be overridden by using a fatal-error-handler.php drop-in. This drop-in must return an instance of a class extending the default WP_Fatal_Error_Handler class. If that is the case, the instance will be used instead of the default one.
  • Environments that would like to disable the fatal error handler and recovery mode functionality altogether can do so by setting a WP_DISABLE_FATAL_ERROR_HANDLERconstant, typically in wp-config.php. The enabled status for the handler should be checked for by using a new function wp_is_fatal_error_handler_enabled().


The fatal error recovery mode is a revised approach for what was originally the fatal error protection mechanism slated for WordPress 5.1, but then reverted due to some critical concerns. The client-specific recovery mode mitigates these concerns, so this time it is here to stay.

For further background information, please refer to the announcement post for the revised approach, the overarching Trac ticket, and generally the list of related 5.2 tickets.

#5-2, #dev-notes, #servehappy

Dashicons in WordPress 5.2

It’s been over 3 years since Dashicons has been updated (see #34221 from version 4.5). But, they have not been forgotten about! In 5.2, the Dashicons will see several changes, including 13 awesome new icons.

New Build Process

A new build process has been implemented in the Dashicons GitHub repository to make adding new icons easier. Now, when SVG files are added for new icons they are automatically included in the font and CSS files. This change will not be noticeable from the WordPress Core code base, but it’s worth noting.

New Font File Format: WOFF 2.0

This release will see the introduction of a new font file format, WOFF2 (Web Open Font Format 2). WOFF2 is a more modern replacement for the original WOFF 1.0 format that uses an improved compression, which results in lower network consumption.

WOFF2 is supported by all modern browsers, but is not supported in Internet Explorer.

WOFF 1.0 Format

The WOFF 1.0 file will remain in WordPress Core to ensure backwards compatibility for plugins and themes loading the wp-includes/fonts/dashicons.woff file directly. This file has not been updated to include the new icons below. The new build process currently only allows one WOFF format file to be built. Since WOFF2 is more modern, that is the file format being built moving forward.

However, WOFF 1.0 is compiled and included as an embedded font directly in the dashicons.css file. The embedded WOFF format has been updated to include the new icons. If you wish to use the new Dashicons and require the WOFF 1.0 format for IE support, it is recommended that you use the dashicons.css file included in core to define the Dashicons font face.

Alternatively, you can use the Embedded OpenType format file at wp-includes/fonts/dashicons.eot (supported by all versions of IE). This file does include the new icons.

New Icons

In 5.2, 13 completely new icons were added. However, 18 additional icons that were previously included in the font files but did not have a corresponding CSS declaration are now available. These icons are marked with an asterisk (*) below.


The Buddicons were all previously included in the icon font, but each is now accompanied by new a dashicons-buddicons-* class.

Icon CSS Class Code
dashicons-buddicons-activity * f452
dashicons-buddicons-bbpress-logo * f12b
dashicons-buddicons-buddypress-logo * f448
dashicons-buddicons-community * f453
dashicons-buddicons-forums * f449
dashicons-buddicons-friends * f454
dashicons-buddicons-groups * f456
dashicons-buddicons-pm * f457
dashicons-buddicons-replies * f451
dashicons-buddicons-topics * f450
dashicons-buddicons-tracking * f455


Icon CSS Class Code
dashicons-editor-ol-rtl f12c
dashicons-editor-ltr f10c

Core Teams

Three new icons have been introduced for some newer teams: Tide, REST API, and Coding Standards.

Icon CSS Class Code
dashicons-tide f10d
dashicons-rest-api f124
dashicons-code-standards f13a


With the introduction of 3 new icons in 5.2, there are now 4 total site icons. No matter where you are located in the world, there is now an icon for you! (GH-95)

Icon CSS Class Code
dashicons-admin-site-alt f11d
dashicons-admin-site-alt2 f11e
dashicons-admin-site-alt3 f11f


Icon CSS Class Code
dashicons-menu-alt * f228
dashicons-menu-alt2 * f329
dashicons-menu-alt3 * f349


Icon CSS Class Code
dashicons-instagram f12d


Icon CSS Class Code
dashicons-businesswoman f12f
dashicons-businessperson f12e
dashicons-email-alt2 f467
dashicons-yes-alt f12a
dashicons-camera-alt * f129
dashicons-plugins-checked * f485
dashicons-update-alt * f113
dashicons-text-page * f121

A very special thanks goes out to @joen, @empireoflight, @folletto, @netweb, @aduth, @dsifford, @SergioEstevao, @cathibosco1, @jaymanpandya, @oztaser, @ryelle, @joshuawold, @nateallen, @desrosj, @bahia0019, and @liljimmi for their contributions to Dashicons since the last update!

To get a complete overview of all icons please visit

#5-2, #dashicons, #dev-notes, #ui

New Network and Sites Query Filters

WordPress 5.2 introduces new short circuit filters to WP_Site_Query and WP_Network_Query.

These two filters, sites_pre_query and network_pre_query, were introduced in [44983] and run before the database queries are executed. This enables short-circuiting the database query entirely to return custom results. Returning a non-null value from either filter will bypass WordPress’s default network and sites queries respectively (similar to the users_pre_query filter introduced in #44373).

Sites Query Filter

Developers should note that filtering functions that require pagination information are encouraged to set the found_sites property of the WP_Site_Query object (which is passed to the filter by reference). If WP_Site_Query does not perform a database query, it will not have enough information to generate these values itself.

Using the Filter

Below is a rough example of how a plugin can use the filter to replace the default behavior of WP_Site_Query with a call to a remote data store.

function myplugin_do_external_site_query( $sites, $site_query ) {
	$response = wp_remote_get( 'https://my-remote-data-store/foo/bar' );

	if ( 200 === wp_remote_response_code( $response ) ) {
		$response           = json_decode( wp_remote_retrieve_body( $response ) );
		$sites              = array_map( 'intval', $response->site_ids );
		$query->found_sites = (int) $response->found_sites;

	return $sites;
add_filter( 'sites_pre_query', 'myplugin_do_external_site_query', 10, 2 );

Networks Query Filter

Developers should note that filtering functions that require pagination information are encouraged to set the total_networks property of the WP_Network_Query object (which is passed to the filter by reference). If WP_Network_Query does not perform a database query, it will not have enough information to generate these values itself.

Using the Filter

Below is a rough example of how a plugin can use the filter to replace the default behavior of WP_Network_Query with a call to a remote data store.

function myplugin_do_external_network_query( $networks, $network_query ) {
	$response = wp_remote_get( 'https://my-remote-data-store/foo/bar' );

	if ( 200 === wp_remote_response_code( $response ) ) {
		$response              = json_decode( wp_remote_retrieve_body( $response ) );
		$networks              = array_map( 'intval', $response->network_ids );
		$query->total_networks = (int) $response->total_networks;

	return $networks;
add_filter( 'network_pre_query', 'myplugin_do_external_network_query', 10, 2 );

Other Similar Query Filters

Similar filters for WP_User_Query and count_users() were added in WordPress 5.1.

Several additional filters for similar query objects are currently being explored and worked on, and are currently slated for a future release:

  • A short circuit for WP_Comment_Query (#45800).
  • A short circuit for WP_Term_Query with a plan to add a terms_pre_query filter (#41246).

Why Add These Filters?

These query pre-filters enable plugins to use an alternate database store for queries, for example returning results from an external service such as an Elasticsearch server. The process started with the main post query, and these are now being expanded that to other queries in WordPress.

#5-2, #dev-notes, #multisite, #networks-sites

The Block Editor JavaScript module in 5.2

One of the goals of the Gutenberg project’s phase 2 is to expand the usage of the Block Editor to other WordPress admin pages like the widgets screen.

In order to achieve this goal, it’s important to be able to reuse the block editor in a context independent from the post editor without any dependency to the post object. That’s where the new block-editor module comes in.


In WordPress 5.1 and earlier, the block editor relied on the editor JavaScript module in order to fetch the post being edited and render the block editor corresponding to this post. This module is available as a registered WordPress script using the wp-editor script and style handles and under the wp.editor global variable.

WordPress 5.2 extracts some parts of the editor module into a new module called block-editor. This module is now available as a registered WordPress script using the wp-block-editor script and style handles and under the wp.blockEditor global variable.

Important distinctions about the new block-editor module:

  • The editor module is kept, but is only responsible for fetching/updating post objects, and rendering post specific UI components.
  • The block editor module is a generic module responsible for rendering block editor UI, updating the list of blocks, and providing reusable components for third-party blocks.

Backward Compatibility

There’s no backward compatibility breakage involved in this reorganization, as usage of the editor module provides proxies for APIs that were moved to the block-editor module in WordPress 5.2.

For example, in WordPress 5.1, blocks had to use the wp.editor.BlockAlignment component to support alignment. This component will continue to work as expected, but wp.editor.BlockAlignmentToolbar is now just a proxy to the block editor component wp.blockEditor.BlockAlignmentToolbar.

However, relying on the editor module as a dependency means that your block/code is loading the full editor module, which might not be needed for the block editor that will be included in the widgets screen in the future.

For this reason, it’s recommended that you make your blocks independent from the editor module and any post object. Instead of relying on the editor module proxies, you are encouraged you to your code to target the block-editor APIs instead.

This involves:

  • Using wp-block-editor instead of wp-editor as script and style dependencies for your WordPress registered/enqueued scripts and styles.
  • Using the wp.blockEditor.* components instead of wp.editor.* ones.
  • Using the core/block-editor data module selectors and actions instead of the core/editor ones.

Components and Higher-Order Components Moved to block-editor

This is the exhaustive list of the components and higher-order components that were moved to the block-editor module.

  • Autocomplete
  • AlignmentToolbar
  • BlockAlignmentToolbar
  • BlockControls
  • BlockEdit
  • BlockEditorKeyboardShortcuts
  • BlockFormatControls
  • BlockIcon
  • BlockInspector
  • BlockList
  • BlockMover
  • BlockNavigationDropdown
  • BlockSelectionClearer
  • BlockSettingsMenu
  • BlockTitle
  • BlockToolbar
  • ColorPalette
  • ContrastChecker
  • CopyHandler
  • createCustomColorsHOC
  • DefaultBlockAppender
  • FontSizePicker
  • getColorClassName
  • getColorObjectByAttributeValues
  • getColorObjectByColorValue
  • getFontSize
  • getFontSizeClass
  • Inserter
  • InnerBlocks
  • InspectorAdvancedControls
  • InspectorControls
  • PanelColorSettings
  • PlainText
  • RichText
  • RichTextShortcut
  • RichTextToolbarButton
  • RichTextInserterItem
  • UnstableRichTextInputEvent
  • MediaPlaceholder
  • MediaUpload
  • MediaUploadCheck
  • MultiBlocksSwitcher
  • MultiSelectScrollIntoView
  • NavigableToolbar
  • ObserveTyping
  • PreserveScrollInReorder
  • SkipToSelectedBlock
  • URLInput
  • URLInputButton
  • URLPopover
  • Warning
  • WritingFlow
  • withColorContext
  • withColors
  • withFontSizes

Selectors Moved to block-editor

This is the exhaustive list of the data module selectors that moved to the core/block-editor store.

  • canInsertBlockType
  • getAdjacentBlockClientId
  • getBlock
  • getBlockAttributes
  • getBlockCount
  • getBlockDependantsCacheBust
  • getBlockHierarchyRootClientId
  • getBlockIndex
  • getBlockMode
  • getBlockName
  • getBlockOrder
  • getBlockRootClientId
  • getBlockInsertionPoint
  • getBlockListSettings
  • getBlocks
  • getBlocksByClientId
  • getBlockSelectionStart
  • getBlockSelectionEnd
  • getClientIdsOfDescendants
  • getClientIdsWithDescendants
  • getFirstMultiSelectedBlockClientId
  • getGlobalBlockCount
  • getInserterItems
  • getLastMultiSelectedBlockClientId
  • getMultiSelectedBlockClientIds
  • getMultiSelectedBlocks
  • getMultiSelectedBlocksEndClientId
  • getMultiSelectedBlocksStartClientId
  • getNextBlockClientId
  • getPreviousBlockClientId
  • getSelectedBlockCount
  • getSelectedBlockClientId
  • getSelectedBlock
  • getSelectedBlocksInitialCaretPosition
  • getTemplate
  • getTemplateLock
  • hasInserterItems
  • hasMultiSelection
  • hasSelectedBlock
  • hasSelectedInnerBlock
  • isAncestorMultiSelected
  • isBlockInsertionPointVisible
  • isBlockMultiSelected
  • isBlockSelected
  • isBlockValid
  • isBlockWithinSelection
  • isCaretWithinFormattedText
  • isFirstMultiSelectedBlock
  • isMultiSelecting
  • isSelectionEnabled
  • isTyping
  • isValidTemplate

Actions Moved to block-editor

This is the exhaustive list of the data module actions that moved to the core/block-editor store.

  • clearSelectedBlock
  • enterFormattedText
  • exitFormattedText
  • hideInsertionPoint
  • insertBlock
  • insertBlocks
  • insertDefaultBlock
  • mergeBlocks
  • moveBlocksDown
  • moveBlocksUp
  • moveBlockToPosition
  • multiSelect
  • receiveBlocks
  • removeBlock
  • removeBlocks
  • replaceBlocks
  • resetBlocks
  • selectBlock
  • setTemplateValidity
  • showInsertionPoint
  • startMultiSelect
  • startTyping
  • stopMultiSelect
  • stopTyping
  • synchronizeTemplate
  • toggleBlockMode
  • toggleSelection
  • updateBlock
  • updateBlockAttributes
  • updateBlockListSettings

Styles and Class Names

The components that moved from the editor module to the block-editor module are internally using CSS class names that follow the package they’re declared in.

For example, the editor-inserter__toggle class name is now renamed block-editor-inserter__toggle.

The old class names have been retained to minimize any backward compatibility concern, but the CSS styles are now targeting the new class names.

Ideally, you should rely on components in your own code instead of the internal class names used in the WordPress admin. But if you do use those classes, make sure to rename them accordingly.

#5-2, #dev-notes, #gutenberg

Admin Tabs Semantic Improvements in 5.2

Some tabs in the WordPress Admin aren’t really ARIA tabs — they’re actually links wrapped in h2 headings and styled to look like ARIA tabs.

But since they’re just navigation menus, WordPress 5.2 changes their markup accordingly. That way, assistive technologies will react to them correctly.

With #43398, WordPress 5.2 includes the following changes:

  • changes the wrapping <h2> to a <nav> element. It’s worth remembering that <nav> elements also define ARIA landmarks.
  • adds an aria-label to the <nav> elements so they can be distinguished from other <nav> elements in the page
  • adjusts the headings level in the Credits page

Example of former markup in the about.php screen:

<h2 class="nav-tab-wrapper wp-clearfix">
	<a href="about.php" class="nav-tab nav-tab-active">What’s New</a>
	<a href="credits.php" class="nav-tab">Credits</a>
	<a href="freedoms.php" class="nav-tab">Freedoms</a>
	<a href="freedoms.php?privacy-notice" class="nav-tab">Privacy</a>

New markup for this screen:

<nav class="nav-tab-wrapper wp-clearfix" aria-label="Secondary menu">
	<a href="about.php" class="nav-tab nav-tab-active">What’s New</a>
	<a href="credits.php" class="nav-tab">Credits</a>
	<a href="freedoms.php" class="nav-tab">Freedoms</a>
	<a href="freedoms.php?privacy-notice" class="nav-tab">Privacy</a>

If your plugin or theme uses the same markup as Core, you’ll want to update it for consistency and to avoid future CSS incompatibilities.

Please note: if your plugin or theme uses items that actually toggle the visibility of in-page content instead of linking to another page, then they are not navigation items. You should not use ARIA tabs nor <nav> element in that case.

#5-2, #accessibility, #dev-notes