Block API Updates in 5.5

Coauthored by @aduth and @gziolo.

BlockBlock Block is the abstract term used to describe units of markup that, composed together, form the content or layout of a webpage using the WordPress editor. The idea combines concepts of what in the past may have achieved with shortcodes, custom HTML, and embed discovery into a single consistent API and user experience. Categories

The block categoryCategory The 'category' taxonomy lets you group posts / content together that share a common bond. Categories are pre-defined and broad ranging. is no longer mandatory or doesn’t have to match an existing category slug during blocks’ registration. When that happens, a block is rendered in the inserter under the Uncategorized section.

The default set of block categories was updated.

The new set of block categories is:

  • Text
  • Media
  • Design
  • Widgets
  • Embeds
  • Reusable

Of the above, a few have remained unchanged: Widgets, Embeds, Reusable.

Mappings have been added to ensure that existing blocks will be assigned to as close as possible to an equivalent category in the new set:

  • Common → Text
  • Formatting → Text
  • Layout → Design

Note that if you update your blocks to one of the new block categories, your block may no longer register correctly in older versions of WordPress. If your pluginPlugin A plugin is a piece of software containing a group of functions that can be added to a WordPress website. They can extend functionality or add new features to your WordPress websites. WordPress plugins are written in the PHP programming language and integrate seamlessly with WordPress. These can be free in the WordPress.org Plugin Directory https://wordpress.org/plugins/ or can be cost-based plugin from a third-party supports older versions, you should consider to check if a category is registered before using it:

In PHPPHP The web scripting language in which WordPress is primarily architected. WordPress requires PHP 5.6.20 or higher:

global $post;
$has_formatting_category = in_array( 'formatting', wp_list_pluck( get_block_categories( $post ), 'slug' ) );

register_block_type( 'my-plugin/my-block', array(
   'category' => $has_formatting_category ? 'formatting' : 'media',
   
   // ...
) );

In JavaScriptJavaScript JavaScript or JS is an object-oriented computer programming language commonly used to create interactive effects within web browsers. WordPress makes extensive use of JS for a better user experience. While PHP is executed on the server, JS executes within a user’s browser. https://www.javascript.com/.:

var hasFormattingCategory = wp.blocks.getCategories().some( function( category ) {
   return category.slug === 'formatting';
} );

wp.blocks.registerBlockType( 'my-plugin/my-block', {
   category: hasFormattingCategory ? 'formatting' : 'media',

   // ...
} );

Block Type Metadata

To register a new block type using metadata that can be shared between JavaScript and PHP code, start by creating a block.json file. This file:

  • Gives a name to the block type.
  • Defines some important metadata about the registered block type (title, category, icon, description, keywords).
  • Defines the attributes of the block type.
  • Registers all the scripts and styles for your block type.

Example:

{
	"name": "my-plugin/notice",
	"title": "Notice",
	"category": "text",
	"parent": [ "core/group" ],
	"icon": "star",
	"description": "Shows warning, error or success notices…",
	"keywords": [ "alert", "message" ],
	"textdomain": "my-plugin",
	"attributes": {
		"message": {
			"type": "string",
			"source": "html",
			"selector": ".message"
		}
	},
	"providesContext": {
		"my-plugin/message": "message"
	},
	"usesContext": [ "groupId" ],
	"supports": {
		"align": true,
		"lightBlockWrapper": true
	},
	"styles": [
		{ "name": "default", "label": "Default", "isDefault": true },
		{ "name": "other", "label": "Other" }
	],
	"example": {
		"attributes": {
			"message": "This is a notice!"
		}
	},
	"editorScript": "file:./build/index.js",
	"script": "file:./build/script.js",
	"editorStyle": "file:./build/index.css",
	"style": "file:./build/style.css"
}

For more information on the APIAPI An API or Application Programming Interface is a software intermediary that allows programs to interact with each other and share data in limited, clearly defined ways., see the documentation.

Block Context

Block context is a feature which enables ancestor blocks to provide values which can be consumed by descendant blocks within its own hierarchy. Those descendant blocks can inherit these values without resorting to hard-coded values and without an explicit awareness of the block which provides those values.

This is especially useful in full-site editing where, for example, the contents of a block may depend on the context of the post in which it is displayed. A blogroll template may show excerpts of many different posts. Using block context, there can still be one single “Post ExcerptExcerpt An excerpt is the description of the blog post or page that will by default show on the blog archive page, in search results (SERPs), and on social media. With an SEO plugin, the excerpt may also be in that plugin’s metabox.” block which displays the contents of the post based on an inherited post ID.

If you are familiar with React Context, block context adopts many of the same ideas. In fact, the client-side block editor implementation of block context is a very simple application of ReactReact React is a JavaScript library that makes it easy to reason about, construct, and maintain stateless and stateful user interfaces. https://reactjs.org/. Context. Block context is also supported in server-side render_callback implementations, demonstrated in the examples below.

Defining Block Context

Block context is defined in the registered settings of a block. A block can provide a context value, or consume a value it seeks to inherit.

Providing Block Context

A block can provide a context value by assigning a providesContext property in its registered settings. This is an object which maps a context name to one of the block’s own attributes. The value corresponding to that attribute value is made available to descendant blocks and can be referenced by the same context name. Currently, block context only supports values derived from the block’s own attributes. This could be enhanced in the future to support additional sources of context values.

record/block.json

{
	"name": "my-plugin/record",
	"attributes": {
		"recordId": {
			"type": "number"
		}
	},
	"providesContext": {
		"my-plugin/recordId": "recordId"
	}
}

As seen in the above example, it is recommended that you include a namespace as part of the name of the context key so as to avoid potential conflicts with other plugins or default context values provided by WordPress. The context namespace should be specific to your plugin, and in most cases can be the same as used in the name of the block itself.

Consuming Block Context

A block can inherit a context value from an ancestor provider by assigning a usesContext property in its registered settings. This should be assigned as an array of the context names the block seeks to inherit.

record-title/block.json

{
	"name": "my-plugin/record-title",
	"usesContext": [ "my-plugin/recordId" ]
}

Using Block Context

Once a block has defined the context it seeks to inherit, this can be accessed in the implementation of edit (JavaScript) and render_callback (PHP). It is provided as an object (JavaScript) or associative array (PHP) of the context values which have been defined for the block. Note that a context value will only be made available if the block explicitly defines a desire to inherit that value.

JavaScript

record-title/index.js

registerBlockType( 'my-plugin/record-title', {
	edit( { context } ) {
		return 'The current record ID is: ' + context[ 'my-plugin/recordId' ];
	},
} );

PHP

A block’s context values are available from the context property of the $block argument passed as the third argument to the render_callback function.

record-title/index.php

register_block_type( 'my-plugin/record-title', array(
	'render_callback' => function( $attributes, $content, $block ) {
		return 'The current record ID is: ' . $block->context['my-plugin/recordId'];
	},
) );

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

Various changes to WordPress React Components in WordPress 5.5

BlockPreview component

In previous versions, when using the BlockPreview component, setting a height for the container was necessary in order to show the blockBlock Block is the abstract term used to describe units of markup that, composed together, form the content or layout of a webpage using the WordPress editor. The idea combines concepts of what in the past may have achieved with shortcodes, custom HTML, and embed discovery into a single consistent API and user experience. preview properly. This was not working properly in situations where the height of the content was dynamic and changing from preview to another.

In WordPress 5.5, the BlockPreview component automatically scales the content to the available width and adapts its height to its content height.

In most situations, this will improve the rendering of BlockPreview components but if you used to rely on the fixed heights, you should consider checking whether the new behavior is working properly.

Popover component

On WordPress 5.5, the Popover component has different default values for the noArrow and position props. If you relied on the previous default behavior, you must explicitly assign these props.

<Popover noArrow={ false } position="top center" /> 

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

Miscellaneous Developer Focused Changes in WordPress 5.5


Edit 7/29/2020: a call out specific to Twenty Ten was added for the comment_type change.

Edit 8/10/2020: add wp_slash() and adminadmin (and super admin) viewport changes in “Additional developer changes” section.


WordPress 5.5 comes with a number of small developer-focused changes. Here’s a summary of what you can expect.

Upgrade/Install: updating a pluginPlugin A plugin is a piece of software containing a group of functions that can be added to a WordPress website. They can extend functionality or add new features to your WordPress websites. WordPress plugins are written in the PHP programming language and integrate seamlessly with WordPress. These can be free in the WordPress.org Plugin Directory https://wordpress.org/plugins/ or can be cost-based plugin from a third-party or theme by uploading a ZIP file

Starting in WordPress 5.5, it will be possible to update a plugin or theme by uploading a ZIP file. After uploading the ZIP file, a comparison table will be displayed to the user, detailing the differences between the uploaded ZIP and the version of the plugin currently installed.

The majority of this process is handled by the new do_overwrite() methods within the Theme_Installer_Skin and Plugin_Installer_Skin classes. However, there are a few hooksHooks In WordPress theme and development, hooks are functions that can be applied to an action or a Filter in WordPress. Actions are functions performed when a certain event occurs in WordPress. Filters allow you to modify certain functions. Arguments used to hook both filters and actions look the same. that can be used to adjust the output of this feature:

  • The install_plugin_overwrite_comparison and install_theme_overwrite_comparison filters can be used to modify the output of the comparison tables.
  • The install_plugin_overwrite_actions and install_theme_overwrite_actions filters can be used to modify the actions displayed after an update has failed when overwriting is allowed.
  • The upgrader_overwrote_package action is fired when a plugin or theme has been successfully been upgraded/replaced with a new version uploaded by ZIP.

For more information, refer to #9757 on TracTrac An open source project by Edgewall Software that serves as a bug tracker and project management tool for WordPress..

Themes: functions calling locate_template()now have a return value

The template loading functions have historically not returned any values. When called, they execute silently, even if the desired template file is missing. This makes it difficult to debug situations where there is a typo in the template name details passed to the function.

Starting in 5.5, the following functions now return false if the template file is not found, and void if the template is found and loaded:

  • get_header()
  • get_footer()
  • get_sidebar()
  • get_template_part()

This could also be used for themes to check for missing template files and execute code when one is missing. For example:

<?php
if ( false === get_header( 'post' ) ) {
    // Do something when the `header-post.php` file is missing or cannot be loaded.
}

Note: Previously, returning a value when the template was loaded successfully was explored. However, this approach is not feasible. It was discovered that many themes in the wild are printing the return value of get_template_part(), leading to unexpected (and potentially compromising) content being sent to the browser.

For more information, check out the related ticketticket Created for both bug reports and feature development on the bug tracker. on Trac: #40969.

TaxonomyTaxonomy A taxonomy is a way to group things together. In WordPress, some common taxonomies are category, link, tag, or post format. https://codex.wordpress.org/Taxonomies#Default_Taxonomies.: default categories for custom post types

For the post post type, a default categoryCategory The 'category' taxonomy lets you group posts / content together that share a common bond. Categories are pre-defined and broad ranging. term (“Uncategorized” by default) is applied to every published post. Starting in 5.5, this default term can be applied to posts of any custom post typeCustom Post Type WordPress can hold and display many different types of content. A single item of such a content is generally called a post, although post is also a specific post type. Custom Post Types gives your site the ability to have templated posts, to simplify the concept. with the category taxonomy registered to it. This can be accomplished using the new default_category_post_types filterFilter Filters are one of the two types of Hooks https://codex.wordpress.org/Plugin_API/Hooks. They provide a way for functions to modify data of other functions. They are the counterpart to Actions. Unlike Actions, filters are meant to work in an isolated manner, and should never have side effects such as affecting global variables and output..

For more information, refer to #43516 on Trac.

Taxonomy: support for default terms in custom taxonomies

A new default_term argument has also been added to register_taxonomy(). Using this argument, a default term name (and optionally slug and description) can be defined. If the defined term does not exist, it will be created automatically.

Additionally, a default_term_$taxonomy option will be added to the database for easy access, and parity with default_category.

For more information, see #43517 on Trac.

Comments: default comment_type value now enforced

Since [9541], an empty string has been used as the default value of a comment’s comment_type field (though it was possible for this to be empty sooner). While examining the possibility of introducing custom comment types in #35214, this was identified as something that would potentially be problematic.

Starting in WordPress 5.5, comment will be enforced as the default comment_type for all comments going forward. This change is one of the first step to open the door to potentially supporting custom comment types.

After upgrading to 5.5, an upgrade routine will be scheduled via cron and run to update all preexisting comments with an empty comment_type to comment. This process will batch comments 100 at a time. The batch size can be adjusted using the wp_update_comment_type_batch_size filter.

If a conditional checks that $comment->comment_type is an empty string in your plugin or theme, it is possible that this change could cause comments to stop displaying on your site. Twenty Ten was the only default theme affected by this. Though it has been fixed and the theme will be updated along with 5.5, any theme built off of Twenty Ten should be updated.

For more information, see the related tickets on Trac (#49236, #35214).

Comments: Changes to return values

With the aim of consistency and WordPress 5.5 will bring a few changes to the values wp_update_comment() returns.

First, a new parameter, $wp_error, has been added to control whether a WP_Error is returned when an error is encountered. This is optional, and will default to false (do not return a WP_Error object).

Second, the return values for an invalidinvalid A resolution on the bug tracker (and generally common in software development, sometimes also notabug) that indicates the ticket is not a bug, is a support request, or is generally invalid. comment or post ID has been changed from 0 to false. This addresses an issue where 0 could be returned for three different scenarios.

Any code checking explicitly for 0 as a returned value of wp_update_comment() will need to be updated to instead explicitly check for false.

For more information, see the related ticket on Trac (#39732).

Additional developer changes

  • Build/Test Tools: The documentation for the Docker environment included with CoreCore Core is the set of software required to run WordPress. The Core Development Team builds WordPress. for local development and the environment overall has been improved. Contributors are encouraged to give it a try and report any breakage they experience. (see #50058).
  • Docs: All instances of @staticvar within inline PHPPHP The web scripting language in which WordPress is primarily architected. WordPress requires PHP 5.6.20 or higher docs have been removed. This tagtag A directory in Subversion. WordPress uses tags to store a single snapshot of a version (3.6, 3.6.1, etc.), the common convention of tags in version control systems. (Not to be confused with post tags.) is no longer supported in phpDocumentor (see #50426).
  • Formatting: loading has been added as an allowed attribute for the <img> tag in the KSES functions (see #50731).
  • Formatting: wp_filter_object_list() now properly returns an array when passed an object with magic methods (see #50095).
  • General: The logic in add_magic_quotes() has been adjusted to prevent inappropriately recasting non-string data types to strings. This was noticeable in the REQUEST_TIME and REQUEST_TIME_FLOAT values in the $_SERVER super global (see #48605).
  • Login and Registration: The new lostpassword_errors filter in retrieve_password() allows developers to add or modify the errors generated during a password reset request (see #49521).
  • Media: the media grid frame is now exposed via the wp-media-grid-ready trigger for easier customization (see #50185).
  • Query: A new set_404 action has been introduced, firing after a 404 is triggered (see #48061).
  • Query: The found_posts property of WP_Query will now always be an integer (#42469).
  • Site Health: The error messages displayed to a user when the site does not meet the PHP or WordPress requirements of the plugin being activated have been improved to list those requirements and include a link to support documentation for updating PHP (see #48245).
  • TinyMCE: TinyMCE has been updated to version 4.9.10 (see #50431).
  • Upgrade/Install: an additional hook_extra parameter has been added to the upgrader_pre_download filter. This will provide additional context to code hooked onto this filter, such as which plugin or theme update will be downloaded (see #49686).
  • Upload: a new pre_wp_unique_filename_file_list filter has been added to wp_unique_filename(). This can be used to short-circuit the scandir() call to provide performance improvements for large directories (see #50587).
  • Administration: Remove multiple viewport metaMeta Meta is a term that refers to the inside workings of a group. For us, this is the team that works on internal WordPress sites like WordCamp Central and Make WordPress. tags from mobile pages (see #47369).
  • Administration: Introduce the wp_admin_viewport_meta() function, paired to the admin_viewport_meta filter to control attributes of the meta tag (see #47369).
  • Formatting: Prevent wp_slash from returning non-strings as strings (see #42195).

Props @desrosj and @sergeybiryukov for reviewing/helping providing some sections.

#5-5, #dev-notes

Themes: changes related to get_custom_logo() in WordPress 5.5

Update (August 7): Removing the link from the homepage logo will be optional for WordPress 5.5, and a description of how to implement that in themes is now included below. The CSSCSS Cascading Style Sheets. selector change is still recommended for some themes.

Unlinking the custom logo on the homepage

A new unlink-homepage-logo parameter is added for the custom-logo theme support option. By default, unlink-homepage-logo is set to false, and theme authors can opt-in for the change by setting it to true. This would be the array for Twenty Twenty:

add_theme_support(
	'custom-logo',
	array(
		'height'               => $logo_height,
		'width'                => $logo_width,
		'flex-height'          => true,
		'flex-width'           => true,
		'unlink-homepage-logo' => true, // Add Here!
	)
);

If the unlink-homepage-logo parameter is set to true, logo images inserted using get_custom_logo() or the_custom_logo() will no longer link to the homepage when visitors are on that page. In an effort to maintain the styling given to the linked image, the unlinked logo image is inside a span tagtag A directory in Subversion. WordPress uses tags to store a single snapshot of a version (3.6, 3.6.1, etc.), the common convention of tags in version control systems. (Not to be confused with post tags.) with the same “custom-logo-link” class.

Many themes include both a logo and a site title, and then the logo is decoration alongside the site title. Because decorative images do not need their purpose to be described, the unlinked logo’s alt attribute would be empty. In cases where the site title is not present, the logo alt text may require custom handling. See code examples below for ways to override the default behavior.

Theme authors who use the a tag as a CSS selector instead of the .custom-logo-link class are encouraged to duplicate their selector to also select the span tag, or to directly select the .custom-logo-link class. A theme directory search found 183 themes that use a.custom-logo-link for styling.

Please verify whether this change makes the logo display any differently on the homepage, as well as whether the empty alt text should be appropriate.

For more details about the homepage logo link, see the related ticketticket Created for both bug reports and feature development on the bug tracker. on TracTrac An open source project by Edgewall Software that serves as a bug tracker and project management tool for WordPress.: #37011

New logo image attributes filterFilter Filters are one of the two types of Hooks https://codex.wordpress.org/Plugin_API/Hooks. They provide a way for functions to modify data of other functions. They are the counterpart to Actions. Unlike Actions, filters are meant to work in an isolated manner, and should never have side effects such as affecting global variables and output.

Themes can use the get_custom_logo_image_attributes filter to override default attributes for the logo image or to set additional attributes.

For example, if a theme combines the logo image plus the site title (as actual text) within a link and/or heading tag, then having the site title as the logo’s alt text would be redundant. In that case, this is one way to empty the alt text so screen readers only announce the actual text:

add_filter( 'get_custom_logo_image_attributes', 'my_logo_remove_alt_text', 10, 1 );
function my_logo_remove_alt_text( $custom_logo_attr ) {
	$custom_logo_attr["alt"] = "";
	return $custom_logo_attr;
}

To check whether a user has customized the alt text before emptying it, the filter could be similar to this:

add_filter( 'get_custom_logo_image_attributes', 'my_logo_alt_custom_or_empty', 10, 2 );
function my_logo_alt_custom_or_empty( $custom_logo_attr, $custom_logo_id ) {
	$logo_alt = get_post_meta( $custom_logo_id, '_wp_attachment_image_alt', true );
	if ( empty( $logo_alt ) ) {
		$custom_logo_attr["alt"] = "";
	}
	return $custom_logo_attr;
}

If a user has customized the alt text value, this can restore it on the homepage:

add_filter( 'get_custom_logo_image_attributes', 'my_logo_homepage_maybe_alt', 10, 2 );
function my_logo_homepage_maybe_alt( $custom_logo_attr, $custom_logo_id ) {
	$logo_alt = get_post_meta( $custom_logo_id, '_wp_attachment_image_alt', true );
	if ( ! empty ( $logo_alt ) && is_front_page() ) {
		$custom_logo_attr["alt"] = $logo_alt;
	}
	return $custom_logo_attr;
}

If the site title is appropriate as a fallback on the homepage in a certain theme, a filter like this could be used:

add_filter( 'get_custom_logo_image_attributes', 'my_logo_homepage_restore_alt', 10, 2 );
function my_logo_homepage_restore_alt( $custom_logo_attr, $custom_logo_id ) {
	$logo_alt = get_post_meta( $custom_logo_id, '_wp_attachment_image_alt', true );
	if ( is_front_page() ) {
		if ( ! empty ( $logo_alt ) ) {
			$custom_logo_attr["alt"] = $logo_alt;
		} else {
			$custom_logo_attr["alt"] = get_bloginfo( 'name', 'display' );
		}
	}
	return $custom_logo_attr;
}

For more details about the filter, see the related ticket on Trac: #36640


Props: @joedolson for adding to the explanation and for review; also @audrasjb, @desrosj, @williampatton, and @poena for review

#5-5, #dev-notes

New Block Tools on WordPress 5.5

In WordPress 5.5, the coreCore Core is the set of software required to run WordPress. The Core Development Team builds WordPress. blocks continue to evolve with the addition of new blockBlock Block is the abstract term used to describe units of markup that, composed together, form the content or layout of a webpage using the WordPress editor. The idea combines concepts of what in the past may have achieved with shortcodes, custom HTML, and embed discovery into a single consistent API and user experience. tools.

Custom Line Heights

Users can define custom line heights for headings and paragraphs. Themes can opt-in into this feature by defining the custom-line-height theme support flag.

add_theme_support( 'custom-line-height' );

Custom Units

In addition to pixels, users can now use other units to define the height of Cover blocks. The available units are: px, em, rem, vh, vw. Themes can opt-in into this feature by defining the custom-units theme support flag.

add_theme_support( 'custom-units' );

Themes can also filterFilter Filters are one of the two types of Hooks https://codex.wordpress.org/Plugin_API/Hooks. They provide a way for functions to modify data of other functions. They are the counterpart to Actions. Unlike Actions, filters are meant to work in an isolated manner, and should never have side effects such as affecting global variables and output. the available custom units.

add_theme_support( 'custom-units', 'rem', 'em' );

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

Opcode Cache Invalidation in WordPress 5.5

Before 5.5, WordPress relied on hosting provider or user settings and plugins to handle purging or invalidating of coreCore Core is the set of software required to run WordPress. The Core Development Team builds WordPress., pluginPlugin A plugin is a piece of software containing a group of functions that can be added to a WordPress website. They can extend functionality or add new features to your WordPress websites. WordPress plugins are written in the PHP programming language and integrate seamlessly with WordPress. These can be free in the WordPress.org Plugin Directory https://wordpress.org/plugins/ or can be cost-based plugin from a third-party, and theme PHPPHP The web scripting language in which WordPress is primarily architected. WordPress requires PHP 5.6.20 or higher changes. This resulted in problems for users like PHP fatal errors when a cached file included a file that had been deleted during an update.

As of [48160], WordPress attempts to invalidate PHP files when Core, Plugins, or Themes are updated.

To help with this, a new function is available, wp_opcache_invalidate(), a safe-to-call-directly wrapper for PHP’s native opcache_invalidate(). In order to avoid PHP warnings, the function handles the checks necessary to see whether OPcache is available, and whether invalidation is allowed by the current PHP settings.

function wp_opcache_invalidate( $filepath, $force = false ) 

The function includes a new filterFilter Filters are one of the two types of Hooks https://codex.wordpress.org/Plugin_API/Hooks. They provide a way for functions to modify data of other functions. They are the counterpart to Actions. Unlike Actions, filters are meant to work in an isolated manner, and should never have side effects such as affecting global variables and output., wp_opcache_invalidate_file, which allows disabling WordPress’ invalidation by file, in case it is necessary due to platform concerns, or there are certain files that a user wants to keep from being invalidated.

You can skip invalidation for one file like this:

// Disable opcode cache invalidation for `/path/to/myfile.php`.
function disable_myfile_invalidation( $will_invalidate, $filename ) {
    if ( '/path/to/myfile.php' === $filename ) {
        return false;
    }

    return true;
}
add_filter( 'wp_opcache_invalidate_file', 'disable_myfile_invalidation', 10, 3 );

Or disable it entirely:

// Disable all of WordPress' opcode cache invalidation:
add_filter( 'wp_opcache_invalidate_file', '__return_false' );

Does this change fix the issues you’ve been having with opcode cache invalidation?

Please test and leave a comment here or open a ticket if you run into problems, have concerns, or need additional hooksHooks In WordPress theme and development, hooks are functions that can be applied to an action or a Filter in WordPress. Actions are functions performed when a certain event occurs in WordPress. Filters allow you to modify certain functions. Arguments used to hook both filters and actions look the same. for your use-case.

Thanks to @aaroncampbell for review!

#5-5, #dev-notes

New wp_get_environment_type() function in WordPress 5.5

Edit: 7/28/2020: Previously, this feature included filters to modify the environment type and available environment types. These were removed in [48662] as the function is called too early for any plugins to properly hook into these filters. This post was updated to remove mention of those filters appropriately.

Edit: 8/28/2020: Previously, this feature a way to modify the allowed environment types. This option was removed in [48895] as this made it unreliable to use. This post was updated to remove the mention of the previously available constants. Read the post.

WordPress 5.5 introduces a new wp_get_environment_type() function that retrieves a site’s current environment type. This allows pluginPlugin A plugin is a piece of software containing a group of functions that can be added to a WordPress website. They can extend functionality or add new features to your WordPress websites. WordPress plugins are written in the PHP programming language and integrate seamlessly with WordPress. These can be free in the WordPress.org Plugin Directory https://wordpress.org/plugins/ or can be cost-based plugin from a third-party and theme authors to more easily differentiate how they handle specific functionality between production and development sites in a standardized way.

By default, this function will return production. Other values supported are local, development and staging.

Below is an example of how this new function can be used to determine a site’s environment type.

switch ( wp_get_environment_type() ) {
    case 'local':
    case 'development':
        do_nothing();
        break;
    
    case 'staging':
        do_staging_thing();
        break;
    
    case 'production':
    default:
        do_production_thing();
        break;
}

Of course care should be taken with this kind of functionality to test all the possible routes.

Setting the environment type

There are two ways to set the environment type for a site. They are processed in the following order with each sequential option overriding any previous values: the WP_ENVIRONMENT_TYPE PHPPHP The web scripting language in which WordPress is primarily architected. WordPress requires PHP 5.6.20 or higher environment variable, and the WP_ENVIRONMENT_TYPE constant.

For both of them, if the environment value is not in the list of allowed environments, the default production value will be returned.

The simplest way is probably through defining the constant:

define( 'WP_ENVIRONMENT_TYPE', 'staging' );

Note: When development is returned by wp_get_environment_type(), WP_DEBUG will be set to true if it is not defined in the site’s wp-config.php file.

Request to all hosts and development environments

All hosts that support setting up staging environments are requested to set this feature to staging on those staging environments. Similarly we ask all developers with development environments to set this value to development appropriately.

Plugin and theme developers should also add support for this feature and adjust functionality appropriately based on the specified environment.


For reference, see the related ticketticket Created for both bug reports and feature development on the bug tracker. on TracTrac An open source project by Edgewall Software that serves as a bug tracker and project management tool for WordPress.: #33161

Props @desrosj, @audrasjb, and @sergeybiryukov for reviewing.

#5-5, #dev-notes

Codebase language improvements in 5.5

Edit: 7/23/2020: A note was added to make developers aware that one of the option keys renamed prior to betaBeta A pre-release of software that is given out to a large group of users to trial under real conditions. Beta versions have gone through alpha testing in-house and are generally fairly close in look, feel and function to the final product; however, design changes often occur as part of the process. 1 was renamed again after beta 3 to avoid confusion with the blockBlock Block is the abstract term used to describe units of markup that, composed together, form the content or layout of a webpage using the WordPress editor. The idea combines concepts of what in the past may have achieved with shortcodes, custom HTML, and embed discovery into a single consistent API and user experience. editor. – @desrosj

In version 5.5, WordPress will see several changes aimed at maintaining a welcoming environment for all contributors while improving the clarity and inclusivity of the codebase. This is a separate but related effort to a recent proposal to update the default branches for all of the project’s GIT repositories.

The WordPress open sourceOpen Source Open Source denotes software for which the original source code is made freely available and may be redistributed and modified. Open Source **must be** delivered via a licensing model, see GPL. community cares about diversity. We strive to maintain a welcoming environment where everyone can feel included, by keeping communication free of discrimination, incitement to violence, promotion of hate, and unwelcoming behavior.

WordPress Etiquette

“Whitelist” and “Blacklist”

Whitelist and blacklist are terms that specify allowed and disallowed or blocked things. However, many times when these two words are used, what is being allowed or blocked is not clear. This ambiguity can make for poor readability, and can also make it harder for non-native English speakers to understand the purpose of the variable, or how to properly translate a string.

In WordPress 5.5, these words have been removed from CoreCore Core is the set of software required to run WordPress. The Core Development Team builds WordPress. and only remain where absolutely necessary for backwards compatibility. A large percentage of the occurrences existed within inline documentation and the names of locally scoped variable, but a few instances were found in function names, option keys, action/filterFilter Filters are one of the two types of Hooks https://codex.wordpress.org/Plugin_API/Hooks. They provide a way for functions to modify data of other functions. They are the counterpart to Actions. Unlike Actions, filters are meant to work in an isolated manner, and should never have side effects such as affecting global variables and output. hooksHooks In WordPress theme and development, hooks are functions that can be applied to an action or a Filter in WordPress. Actions are functions performed when a certain event occurs in WordPress. Filters allow you to modify certain functions. Arguments used to hook both filters and actions look the same., and global variables.

While most of the changes made do not require any action to be taken, a few may need some small adjustments to plugins, themes, or custom code.

Here is what you need to know!

Renamed Options

The following options have been renamed:

  • blacklist_keys has been renamed to disallowed_keys.
  • comment_whitelist has been renamed to comment_previously_approved.

Upon upgrading to WordPress 5.5, these options will be renamed as part of the normal upgrade process and no action is required.

However, when using the Options APIAPI An API or Application Programming Interface is a software intermediary that allows programs to interact with each other and share data in limited, clearly defined ways. (add_option(), delete_option(), update_option(), get_option()), specifying one of the deprecated options will trigger a deprecated warning but the value for the new option name will be correctly returned.

Example

These two examples will return the same values.

$option_value = get_option( 'disallowed_keys' );

// This produces the same result, but will also trigger a deprecated warning.
$option_value = get_option( 'blacklist_keys' );

Any Options API function calls should be adjusted to look for the new option name whenever possible. For code that still needs to support support WordPress < 5.5, the following snippet will do the trick:

if ( false === get_option( 'disallowed_keys' ) ) {
    // Assume this is WP < 5.5. Option does not exist.
} else {
    // Assume this is WP >= 5.5
}

If disallowed_keys exists in the database, the stored value will be returned (which is an empty string by default, or a space separated list of keys and/or IP addresses). get_option() will return explicit false by default, which is a good indicator that the option does not exist.

There are a few things to be aware of, though.

  • Options API related filters associated with deprecated option keys will not be triggered. For example, the pre_option_blacklist_keys filter. Some basic text searches of the pluginPlugin A plugin is a piece of software containing a group of functions that can be added to a WordPress website. They can extend functionality or add new features to your WordPress websites. WordPress plugins are written in the PHP programming language and integrate seamlessly with WordPress. These can be free in the WordPress.org Plugin Directory https://wordpress.org/plugins/ or can be cost-based plugin from a third-party directory found that the usage of any Options API hooks specific to the two changed option keys was almost none.
  • Direct Cache API calls for these options will not be reliable. For example, wp_cache_get( 'blacklist_keys', 'options ). Instead of accessing the option directly from the Cache API, get_option() should be used instead.
  • Queries directly modifying, updating, retrieving these options form the database will potentially cause issues. This is incorrect usage and the Options API functions should always be used instead.
  • Prior to 5.5 beta 1, blacklist_keys was renamed to blocklist_keys. However, to avoid any potential confusion with block editor related features or functionality, it was renamed to disallowed_keys after 5.5 beta 3. This will be fixed automatically when updating to the next development version or installing 5.5, but any code that was changed to use blocklist_keys will need to be updated once more.

In 5.6, adding a more proper _deprecate_option() will be explored to handle future occurrences like this.

For more information, see #50413 on TracTrac An open source project by Edgewall Software that serves as a bug tracker and project management tool for WordPress..

Deprecated functions

The following functions have been deprecated in 5.5. Though this should not cause any problems in your code, the following functions will now trigger a _deprecated_function() warning:

  • add_option_whitelist() has been replaced with add_allowed_options().
  • remove_option_whitelist() has been replaced with remove_allowed_options().
  • wp_blacklist_check() has been replaced with wp_check_comment_disallowed_list().
  • _wp_register_meta_args_whitelist() has been replaced with _wp_register_meta_args_allowed_list() (this is a private function, so should not be used outside of Core).
  • wp.passwordStrength.userInputBlacklist() was replaced with wp.passwordStrength.userInputDisallowedList() (JavaScriptJavaScript JavaScript or JS is an object-oriented computer programming language commonly used to create interactive effects within web browsers. WordPress makes extensive use of JS for a better user experience. While PHP is executed on the server, JS executes within a user’s browser. https://www.javascript.com/.)

For more information, see #50413 on Trac.

Deprecated actions and filters

The following action and filter hooks have been deprecated in 5.5. Any code hooked to them will still be executed. However, a deprecated warning will now be triggered. The replacement hooks will run after the deprecated hooks.

  • The whitelist_options filter hook has been replaced with allowed_options.
  • The wp_blacklist_check action hook has been replaced with wp_check_comment_disallowed_list.

For more information, see #50413 on Trac.

Deprecated global Variables

  • $whitelist_options has been replaced with $allowed_options.
  • $new_whitelist_options has been replaced with $new_allowed_options (more information below)

A scan of the plugin directory showed that only 2 plugins are explicitly accessing the $whitelist_options global and performing no modifications.

A second scan of the plugin directory showed a small number of plugins with a low amount of active installs potentially manipulating the value of $new_whitelist_options. However, it was enough to require consideration.

Because of this, the new $new_allowed_options variable is now passed by reference to the old $new_whitelist_options variable.

Unless a plugin is intentionally destroying this global variable and recreating it from scratch, this will create a seamless transition to a more inclusive name until a standardized way to deprecate a global variable can be created (such as _deprecate_global()), or the implementation can be revised to not require a global variable at all.

For more information on this change, see #50434 and #50413 on Trac.

“Webmaster”

In addition to potentially having racist undertones, the word “webmaster” has become dated and quite cryptic. One person managing all aspects of a site is, for the most part, no longer the norm. The term has also become ambiguous, potentially referring to anyone fulfilling any of the following duties involved with managing a website: web architects, web developers, site authors, website administrators, website owners, etc..

The two occurrences of this string have been replaced with alternatives that better communicate who is being referenced.

See #50394 on Trac for more information.

Props @cbringmann and @jorbin for pre-publishing review.

#5-5, #dev-notes

New XML Sitemaps Functionality in WordPress 5.5

In WordPress 5.5, a new feature is being introduced that adds basic, extensibleExtensible This is the ability to add additional functionality to the code. Plugins extend the WordPress core software. XML sitemaps functionality into WordPress coreCore Core is the set of software required to run WordPress. The Core Development Team builds WordPress..

While web crawlers are able to discover pages from links within the site and from other sites, sitemaps supplement this approach by allowing crawlers to quickly and comprehensively identify all URLs included in the sitemap and learn other signals about those URLs using the associated metadata.

For more background information on this new feature, check out the merge announcement, or the corresponding TracTrac An open source project by Edgewall Software that serves as a bug tracker and project management tool for WordPress. ticketticket Created for both bug reports and feature development on the bug tracker. #50117.

This article explains in detail the various ways in which this new feature can be customized by developers. For example, if you are developing a pluginPlugin A plugin is a piece of software containing a group of functions that can be added to a WordPress website. They can extend functionality or add new features to your WordPress websites. WordPress plugins are written in the PHP programming language and integrate seamlessly with WordPress. These can be free in the WordPress.org Plugin Directory https://wordpress.org/plugins/ or can be cost-based plugin from a third-party with some similar functionality, this post will show you how you can integrate it with the core’s new sitemaps feature.

Key Takeways

With version 5.5., WordPress will expose a sitemap index at /wp-sitemap.xml. This is the main XML file that contains the listing of all the sitemap pages exposed by a WordPress site.

The sitemap index can hold a maximum of 50000 sitemaps, and a single sitemap can hold a (filterable) maximum of 2000 entries.

By default, sitemaps are created for all public and publicly queryable post types and taxonomies, as well as for author archives and of course the homepage of the site.

The robots.txt file exposed by WordPress will reference the sitemap index so that i can be easily discovered by search engines.

Technical Requirements

Rendering sitemaps on the frontend requires the SimpleXML PHPPHP The web scripting language in which WordPress is primarily architected. WordPress requires PHP 5.6.20 or higher extension. If this extension is not available, an error message will be displayed instead of the sitemap. The HTTPHTTP HTTP is an acronym for Hyper Text Transfer Protocol. HTTP is the underlying protocol used by the World Wide Web and this protocol defines how messages are formatted and transmitted, and what actions Web servers and browsers should take in response to various commands. status code 501 (“Not implemented”) will be sent accordingly.

Configuring Sitemaps Behavior

Adding Custom Sitemaps

WordPress provides sitemaps for built-in content types like pages and author archives out of the box. If you are developing a plugin that adds custom features beyond those standard ones, or just want to include some custom URLs on your site, it might make sense to add a custom sitemap provider.

To do so, all you need to do is create a custom PHP class that extends the abstract WP_Sitemaps_Provider class in core. Then, you can use the wp_register_sitemap_provider() function to register it. Here’s an example:

add_filter(
	'init',
	function() {
		$provider = new Awesome_Plugin_Sitemaps_Provider();
		wp_register_sitemap_provider( 'awesome-plugin', $provider );
	}
);

The provider will be responsible for getting all sitemaps and sitemap entries, as well as determining pagination.

Removing Certain Sitemaps

There are three existing sitemaps providers for WordPress object types like posts, taxonomies, and users. If you want to remove one of them, let’s say the “users” provider, you can leverage the wp_sitemaps_add_provider filterFilter Filters are one of the two types of Hooks https://codex.wordpress.org/Plugin_API/Hooks. They provide a way for functions to modify data of other functions. They are the counterpart to Actions. Unlike Actions, filters are meant to work in an isolated manner, and should never have side effects such as affecting global variables and output. to do so. Here’s an example:

add_filter(
	'wp_sitemaps_add_provider',
	function( $provider, $name ) {
		if ( 'users' === $name ) {
			return false;
		}

		return $provider;
	},
	10,
	2
);

If instead you want to disable sitemap generation for a specific post type or taxonomyTaxonomy A taxonomy is a way to group things together. In WordPress, some common taxonomies are category, link, tag, or post format. https://codex.wordpress.org/Taxonomies#Default_Taxonomies., use the wp_sitemaps_post_types or wp_sitemaps_taxonomies filter, respectively.

Example: Disabling sitemaps for the page post type

add_filter(
	'wp_sitemaps_post_types',
	function( $post_types ) {
		unset( $post_types['page'] );
		return $post_types;
	}
);

Example: Disabling sitemaps for the post_tag taxonomy

add_filter(
	'wp_sitemaps_taxonomies',
	function( $taxonomies ) {
		unset( $taxonomies['post_tag'] );
		return $taxonomies;
	}
);

Adding Additional Tags to Sitemap Entries

The sitemaps protocol specifies a certain set of supported attributes for sitemap entries. Of those, only the URLURL A specific web address of a website or web page on the Internet, such as a website’s URL www.wordpress.org (loc) tagtag A directory in Subversion. WordPress uses tags to store a single snapshot of a version (3.6, 3.6.1, etc.), the common convention of tags in version control systems. (Not to be confused with post tags.) is required. All others (e.g. changefreq and priority) are optional tags in the sitemaps protocol and not typically consumed by search engines, which is why WordPress only lists the URL itself. Developers can still add those tags if they really want to.

You can use the wp_sitemaps_posts_entry / wp_sitemaps_users_entry / wp_sitemaps_taxonomies_entry filters to add additional tags like changefreq, priority, or lastmod to single items in the sitemap.

Example: Adding the last modified date for posts

add_filter(
    'wp_sitemaps_posts_entry',
    function( $entry, $post ) {
        $entry['lastmod'] = gmdate( DATE_W3C, strtotime( $post->post_modified_gmt );
        return $entry;
    },
    10,
    2
);

Similarly, you can use the wp_sitemaps_index_entry filter to add lastmod on the sitemap index. Note: the sitemaps protocal does not support on the sitemap index.

Trying to add any unsupported tags will result in a _doing_it_wrong notice.

Excluding a Single Post from the Sitemap

If you are developing a plugin that allows setting specific posts or pages to noindex, it’s a good idea to exclude those from the sitemap too.

The wp_sitemaps_posts_query_args filter can be used to exclude specific posts from the sitemap. Here’s an example:

add_filter(
	'wp_sitemaps_posts_query_args',
	function( $args, $post_type ) {
		if ( 'post' !== $post_type ) {
			return $args;
		}

		$args['post__not_in'] = isset( $args['post__not_in'] ) ? $args['post__not_in'] : array();
		$args['post__not_in'][] = 123; // 123 is the ID of the post to exclude.
		return $args;
	},
	10,
	2
);

Disabling Sitemaps Functionality Completely

If you update the Site Visibility settings in WordPress adminadmin (and super admin) to discourage search engines from indexing your site, sitemaps will be disabled. You can use the wp_sitemaps_enabled filter to override the default behavior.

Here’s an example of how to disable sitemaps completely, no matter what:

add_filter( 'wp_sitemaps_enabled', '__return_false' );

Note: Doing that will not remove the rewrite rules used for the sitemaps, as they are needed in order to send appropriate responses when sitemaps are disabled.

Want to know whether sitemaps are currently enabled or not? Use wp_sitemaps_get_server()->sitemaps_enabled().

Image/Video/News Sitemaps

WordPress currently implements and supports the core sitemaps format as defined on sitemaps.org. Sitemap extensions like image, video, and news sitemaps are not covered by this feature, as these are usually only useful for a small number of websites. In future versions of WordPress, filters and hooksHooks In WordPress theme and development, hooks are functions that can be applied to an action or a Filter in WordPress. Actions are functions performed when a certain event occurs in WordPress. Filters allow you to modify certain functions. Arguments used to hook both filters and actions look the same. may be added to enable adding such functionality. For now this will still be left to plugins to implement.

New Classes and Functions

As of this writing, this is the full list of new classes and functions introduced with this feature.

Functions:

  • wp_sitemaps_get_server – Retrieves the current Sitemaps server instance.
  • wp_get_sitemap_providers – Gets an array of sitemap providers.
  • wp_register_sitemap_provider – Registers a new sitemap provider.
  • wp_sitemaps_get_max_urls – Gets the maximum number of URLs for a sitemap.

Classes:

  • WP_Sitemaps – Main class responsible for setting up rewrites and registering all providers.
  • WP_Sitemaps_Index – Builds the sitemap index page that lists the links to all of the sitemaps.
  • WP_Sitemaps_Provider – Base class for other sitemap providers to extend and contains shared functionality.
  • WP_Sitemaps_Registry – Handles registering sitemap providers.
  • WP_Sitemaps_Renderer – Responsible for rendering Sitemaps data to XML in accordance with sitemap protocol.
  • WP_Sitemaps_Stylesheet – This class provides the XSL stylesheets to style all sitemaps.
  • WP_Sitemaps_Posts – Builds the sitemaps for the ‘post’ object type and its sub types (custom post types).
  • WP_Sitemaps_Taxonomies – Builds the sitemaps for the ‘taxonomy’ object type and its sub types (custom taxonomies).
  • WP_Sitemaps_Users – Builds the sitemaps for the ‘user’ object type.

Available Hooks and Filters

As of this writing, this is the full list of available hooks and filters.

General:

  • wp_sitemaps_enabled – Filters whether XML Sitemaps are enabled or not.
  • wp_sitemaps_max_urls – Filters the maximum number of URLs displayed on a sitemap.
  • wp_sitemaps_init – Fires when initializing sitemaps.
  • wp_sitemaps_index_entry – Filters the sitemap entry for the sitemap index.

Providers:

  • wp_sitemaps_add_provider – Filters the sitemap provider before it is added.
  • wp_sitemaps_post_types – Filters the list of post types to include in the sitemaps.
  • wp_sitemaps_posts_entry – Filters the sitemap entry for an individual post.
  • wp_sitemaps_posts_show_on_front_entry – Filters the sitemap entry for the home page when the ‘show_on_front’ option equals ‘posts’.
  • wp_sitemaps_posts_query_args – Filters the query arguments for post type sitemap queries.
  • wp_sitemaps_posts_pre_url_list – Filters the posts URL list before it is generated (short-circuit).
  • wp_sitemaps_posts_pre_max_num_pages – Filters the max number of pages before it is generated (short-circuit).
  • wp_sitemaps_taxonomies – Filters the list of taxonomies to include in the sitemaps.
  • wp_sitemaps_taxonomies_entry – Filters the sitemap entry for an individual term.
  • wp_sitemaps_taxonomies_query_args – Filters the query arguments for taxonomy terms sitemap queries.
  • wp_sitemaps_taxonomies_pre_url_list – Filters the taxonomies URL list before it is generated (short-circuit).
  • wp_sitemaps_taxonomies_pre_max_num_pages – Filters the max number of pages before it is generated (short-circuit).
  • wp_sitemaps_users_entry – Filters the sitemap entry for an individual user.
  • wp_sitemaps_users_query_args – Filters the query arguments for user sitemap queries.
  • wp_sitemaps_users_pre_url_list – Filters the users URL list before it is generated (short-circuit).
  • wp_sitemaps_users_pre_max_num_pages – Filters the max number of pages before it is generated (short-circuit).

Stylesheets:

  • wp_sitemaps_stylesheet_css – Filters the CSSCSS Cascading Style Sheets. for the sitemap stylesheet.
  • wp_sitemaps_stylesheet_url – Filters the URL for the sitemap stylesheet.
  • wp_sitemaps_stylesheet_content – Filters the content of the sitemap stylesheet.
  • wp_sitemaps_stylesheet_index_url – Filters the URL for the sitemap index stylesheet.
  • wp_sitemaps_stylesheet_index_content – Filters the content of the sitemap index stylesheet.

#5-5, #dev-notes, #sitemaps, #xml-sitemaps

REST API changes in WordPress 5.5

The REST APIREST API The REST API is an acronym for the RESTful Application Program Interface (API) that uses HTTP requests to GET, PUT, POST and DELETE data. It is how the front end of an application (think “phone app” or “website”) can communicate with the data store (think “database” or “file system”) https://developer.wordpress.org/rest-api/. will see a lot of changes in WordPress 5.5. In an effort to explain each change adequately, a number of these were split out and covered by other dev notesdev note Each important change in WordPress Core is documented in a developers note, (usually called dev note). Good dev notes generally include a description of the change, the decision that led to this change, and a description of how developers are supposed to work with that change. Dev notes are published on Make/Core blog during the beta phase of WordPress release cycle. Publishing dev notes is particularly important when plugin/theme authors and WordPress developers need to be aware of those changes.In general, all dev notes are compiled into a Field Guide at the beginning of the release candidate phase..

Below are some other noteworthy changes that deserve a call out.

Discoverable REST resource links

To aid automated and human discovery of the REST API, a link was added in the <head> of the document and as a Link headerHeader The header of your site is typically the first thing people will experience. The masthead or header art located across the top of your page is part of the look and feel of your website. It can influence a visitor’s opinion about your content and you/ your organization’s brand. It may also look different on different screen sizes. to the REST route for the currently queried document in [48273].

For example, in the <head> of this post, the following <link> appears.

<link rel="alternate" type="application/json" href="https://make.wordpress.org/core/wp-json/wp/v2/posts/82428">

Links are added for post, pages, and other custom post types, as well as terms and author pages. Links are not currently output for post archives or search results.

See #49116 for more information.

APIAPI An API or Application Programming Interface is a software intermediary that allows programs to interact with each other and share data in limited, clearly defined ways.

Three new functions are introduced.

  • rest_get_route_for_post() retrieves the route for the given post. For instance, /wp/v2/posts/1.
  • rest_get_route_for_term() retrieves the route for the given term. For instance, /wp/v2/tags/1.
  • rest_get_queried_resource_route() retrieves the route for the currently queried resource. For instance, /wp/v2/users/1 when on the author page for the user with ID of 1.

All three functions return an empty string if a REST API route cannot be determined. To convert the route to a link, pass the result to the rest_url() function.

For more information, see #49116.

Customization

For custom post types, only routes using the built-in WP_REST_Posts_Controller controller class will work by default. For custom controllers, the rest_route_for_post filterFilter Filters are one of the two types of Hooks https://codex.wordpress.org/Plugin_API/Hooks. They provide a way for functions to modify data of other functions. They are the counterpart to Actions. Unlike Actions, filters are meant to work in an isolated manner, and should never have side effects such as affecting global variables and output. can be used to supply the correct route.

function my_plugin_rest_route_for_post( $route, $post ) {
	if ( $post->post_type === 'my-cpt' ) {
		$route = '/wp/v2/my-cpt/' . $post->ID;
	}

	return $route;
}
add_filter( 'rest_route_for_post', 'my_plugin_rest_route_for_post', 10, 2 );

Similar logic applies to taxonomies, only the built in WP_REST_Terms_Controller is supported by default. The rest_route_for_term filter can be used for custom controller classes.

function my_plugin_rest_route_for_term( $route, $term ) {
	if ( $term->taxonomy === 'my-tax' ) {
		$route = '/wp/v2/my-tax/' . $term->term_id;
	}

	return $route;
}
add_filter( 'rest_route_for_term', 'my_plugin_rest_route_for_term', 10, 2 );

The rest_get_queried_resource_route() function is filterable to allow for identification of custom resources.

function my_plugin_rest_queried_resource_route( $route ) {
	$id = get_query_var( 'my-route' );
	if ( ! $route && $id ) {
		$route = '/my-ns/v1/items/' . $id;
	}

	return $route;
}
add_filter( 'rest_queried_resource_route', 'my_plugin_rest_queried_resource_route' );

These links are output using the existing rest_output_link_wp_head and rest_output_link_header functions. As such, if API discovery has already been disabled, these links will not be rendered.

For more information, see #49116.

CORS changes

In [48112], the Link header was added to the list of exposed CORS response headers. Previously, only the X-WP-Total and X-WP-TotalPages headers were exposed which means that clients would have to manually construct the URLURL A specific web address of a website or web page on the Internet, such as a website’s URL www.wordpress.org to implement pagination instead of using the prev and next Links.

In [48452], the Content-Disposition, Content-MD5 and X-WP-Nonce were added to the list of allowed cors request headers. The Content-Disposition and Content-MD5 headers allow for easier file uploading across domains by using a File/Blob object directly. The X-WP-Nonce header is allowed for making authenticated cross-origin and same-origin requests consistently.

Two filters are introduced, rest_exposed_cors_headers and rest_allowed_cors_headers to simplify the process of plugins modifying the list of cors headers.

For more information, see #50369 and #41696.

Miscellaneous

Warn when omitting a permission_callback

The REST API treats routes without a permission_callback as public. Because this happens without any warning to the user, if the permission callback is unintentionally omitted or misspelled, the endpoint can end up being available to the public. Such a scenario has happened multiple times in the wild, and the results can be catastrophic when it occurs.

In [48526] a _doing_it_wrong notice has been added when a permission callback is omitted. For REST API routes that are intended to be public, it is recommended to set the permission callback to the __return_true built in function.

So for instance, this route registration will cause the following warning to appear.

register_rest_route(
	'my-ns',
	'echo',
	array(
		'methods'  => WP_REST_Server::EDITABLE,
		'callback' => function ( WP_REST_Request $request ) {
			return new WP_REST_Response( $request->get_param( 'echo' ) );
		},
	)
);
The REST API route definition for my-ns/echo is missing the required permission_callback argument. For REST API routes that are intended to be public, use __return_true as the permission callback.

If it was intended for this endpoint to be public, you could fix it like this.

register_rest_route(
	'my-ns',
	'echo',
	array(
		'methods'  => WP_REST_Server::EDITABLE,
		'callback' => function ( WP_REST_Request $request ) {
			return new WP_REST_Response( $request->get_param( 'echo' ) );
		},
		'permission_callback' => '__return_true',
	)
);

If you wanted to check the user’s capabilities, you could do it like this.

register_rest_route(
	'my-ns',
	'echo',
	array(
		'methods'  => WP_REST_Server::EDITABLE,
		'callback' => function ( WP_REST_Request $request ) {
			return new WP_REST_Response( $request->get_param( 'echo' ) );
		},
		'permission_callback' => function( WP_REST_Request $request ) {
			return current_user_can( 'manage_options' );
		},
	)
);

For more information, see #50075.

Using wp_send_json() is doing it wrong

When building a REST API route, it is important for the route callback (and permission_callback) to return data instead of directly sending it to the browser. This ensures that the additional processing that the REST API server does, like handling linking/embedding, sending headers, etc… takes place.

// This is incorrect.
echo wp_json_encode( $data );
die;

// And this.
wp_send_json( $data );

// And this.
wp_send_json_error( 'My Error' );

// Instead do this.
return new WP_REST_Response( $data );

// Or this.
return new WP_Error( 'my_error_code', 'My Error Message' );

After [48361], a _doing_it_wrong notice is now issued when any of the wp_send_json family of functions are used during a REST API request.

For more information, see #36271.

Preloading silenced deprecation errors

When using rest_preload_api_request any deprecation errors encountered when processing the request were silenced because the REST API handling took over as soon as the API server was booted.

After [48150], the REST API handling will only apply for actual REST API requests.

For more information, see #50318.

Props @desrosj and @justinahinon for proofreading.

#5-5, #dev-notes, #rest-api