REST API Changes in WordPress 5.6

WordPress 5.6 introduces a number of changes to 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/., some of which have been covered in 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.

Search

The wp/v2/search endpoint introduced in WordPress 5.0 provides a unified interface for searching across multiple content types. WordPress 5.6 adds a terms and post formats search handler. For example, to search across terms in all taxonomies, make the following request: https://example.org/wp-json/wp/v2/search?type=term&search=my-term. To search post-formats, use the post-format type: https://example.org/wp-json/wp/v2/search?type=post-format&search=aside.

Additionally, the REST API search infrastructure no longer requires that the id for each item is an integer. Strings are now an acceptable id type.

See #51458, #51459, #51131.

JSONJSON JSON, or JavaScript Object Notation, is a minimal, readable format for structuring data. It is used primarily to transmit data between a server and web application, as an alternative to XML. Schema

multipleOf keyword

The multipleOf keyword allows for asserting that an integer or number type is a multiple of the given number. For example, this schema will only accept even integers.

{
  "type": "integer",
  "multipleOf": 2
}

multipleOf also supports decimals. For example, this schema could be used to accept a percentage with a maximum of 1 decimal point.

{
  "type": "number",
  "minimum": 0,
  "maximum": 100,
  "multipleOf": 0.1
}

See #51022.

minProperties and maxProperties

The minItems and maxItems keywords can be used for the array type. The minProperties and maxProperties introduces this same functionality for the object type. This is helpful when using additionalProperties to have a list of objects with unique keys.

This schema requires an object that specifies at least 1, and at most 3, colors.

{
  "type": "object",
  "additionalProperties": {
    "type": "string",
    "format": "hex-color"
  },
  "minProperties": 1,
  "maxProperties": 3
}
{
  "primary": "#52accc",
  "secondary": "#096484"
}

See #51023.

patternProperties

The patternProperties keyword is similar to the additionalProperties keyword, but allows for asserting that the property matches a regex pattern. The keyword is an object where each property is a regex pattern and its value is the JSON Schema used to validate properties that match that pattern.

For example, this schema requires that each value is a hex color and the property must only contain “word” characters.

{
  "type": "object",
  "patternProperties": {
    "^\\w+$": {
      "type": "string",
      "format": "hex-color"
    }
  },
  "additionalProperties": false
}

When the REST API validates the patternProperties schema, if a property doesn’t match any of the patterns, the property will be allowed and not have any validation applied to its contents. This behaves the same as the properties keyword. If this logic isn’t desired, add additionalProperties to the schema to disallow non-matching properties. See #51024.

oneOf and anyOf

These are advanced keywords that allow for the JSON Schema validator to choose one of many schemas to use when validating a value. The anyOf keyword allows for a value to match at least one of the given schemas. Whereas, the oneOf keyword requires the value match exactly one schema.

For example, this schema allows for submitting an array of “operations” to an endpoint. Each operation can either be a “crop” or a “rotation”.

{
  "type": "array",
  "items": {
    "oneOf": [
      {
        "title": "Crop",
        "type": "object",
        "properties": {
          "operation": {
            "type": "string",
            "enum": [
              "crop"
            ]
          },
          "x": {
            "type": "integer"
          },
          "y": {
            "type": "integer"
          }
        }
      },
      {
        "title": "Rotation",
        "type": "object",
        "properties": {
          "operation": {
            "type": "string",
            "enum": [
              "rotate"
            ]
          },
          "degrees": {
            "type": "integer",
            "minimum": 0,
            "maximum": 360
          }
        }
      }
    ]
  }
}

The REST API will loopLoop The Loop is PHP code used by WordPress to display posts. Using The Loop, WordPress processes each post to be displayed on the current page, and formats it according to how it matches specified criteria within The Loop tags. Any HTML or PHP code in the Loop will be processed on each post. https://codex.wordpress.org/The_Loop. over each schema specified in the oneOf array and look for a match. If exactly one schema matches, then validation will succeed. If more than one schema matches, validation will fail. If no schemas match, then the validator will try to find the closest matching schema and return an appropriate error message.

operations[0] is not a valid Rotation. Reason: operations[0][degrees] must be between 0 (inclusive) and 360 (inclusive)

See #51025.

Expose all JSON Schema keywords in the index

When making an OPTIONS request to an endpoint, the REST API will return the args that the route accepts. Previously, only a limited subset of JSON Schema keywords were exposed. In WordPress 5.6, now the full list of JSON Schema keywords that the REST API supports will be exposed. See #51020.

More specific validation error codes

When the type of a value is incorrect, rest_validate_value_from_schema now returns rest_invalid_type instead of the generic rest_invalid_param. The validation error code is not currently exposed to REST API clients. This would only effect direct usages of the validation function.

Miscellaneous

The apiRequest library now supports using the PUT and DELETE 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. methods with servers that didn’t support those methods. This is done by making the request a POST request and passing the original HTTP method in the X-HTTP-Method-Override 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.. #43605.

The comments controller now uses the rest_get_route_for_post function introduced in WordPress 5.5 to generate the up response link. This function is filterable to allow for custom controllers to properly define their REST API route. #44152.

The REST API now supports a broader range of JSON media types. Previously, only application/json was supported which prevented using subtypes like application/activity+json. The REST API will now json_decode the body of requests using a JSON subtype Content-Type. Additionally, wp_die() now properly sends the error as JSON when a JSON subtype is specified in the Accept header. #49404.

Props @m_butcher for reviewing.

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

Core major versions auto-updates UI changes in WordPress 5.6 – Correction

WordPress 5.6 introduces a new UIUI User interface to allow website administrators to opt-in to major versions of automatic updates. As noted in a previous dev note, this feature follows the plugins and themes auto-updates user interface, which was shipped in WordPress 5.5. Both are part of the Nine WordPress Core projects for 2019-2020.

The scope of the feature changed during the 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. phase of WordPress 5.6. This dev notedev 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. cancels and replaces the preceding one.

As announced by Executive Director @chanthaboune (see the related post below), the initial scope of CoreCore Core is the set of software required to run WordPress. The Core Development Team builds WordPress. auto-updates has moved to:

  • Provide some updates to the design of the UI.
  • For existing installations, the behavior will remain the same as it is today: opted-in to minor updates by default, but a user must opt-in to major updates (constants and filters that are already in use by hosts or agencies will still take precedence).
  • For new installations, the default behavior will change: opted-in to minor updates by default and opted-in to major updates by default.

For more details about this decision and the roadmap for the next releases, please check the related post on Make/Core:

Major Core auto-updates UI changes in WordPress 5.6

How does it look?

The core auto-updates feature already exists for years in WordPress. WP 5.6 only introduces a new user interface to make it easier to opt-in to automatic updates for major versions.

By default, WordPress auto-updates itself, but only for minor releases. Developers can already opt-in to major releases auto-updates by setting up the existing WP_AUTO_UPDATE_CORE constant to true or by using the allow_major_auto_core_updates existing 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..

With WordPress 5.6, it’s possible for website administrators to opt-in/out to automatic updates for major versions, using a specific interface located on the Updates screen:

When the administrator clicks on the “Enable automatic updates for all new versions of WordPress” link, auto-updates for WordPress Core major versions are enabled:

It’s then possible to opt-out for major versions auto-updates by clicking the “Switch to automatic updates for maintenance and security releases only” link.

How to override the default settings using constants and filters?

This settings section adds some links to allow administrators to opt-in to major core auto-updates. But it also checks for any existing constant or filter and even to see whether the option should be available or not by default and whether it should be set up to enabled or disabled state, using the following order:

  1. By default, auto-updates for major versions are:
    • Disabled for existing WordPress installations.
    • Disabled if a version controlversion control A version control system keeps track of the source code and revisions to the source code. WordPress uses Subversion (SVN) for version control, with Git mirrors for most repositories. system is detected on the WordPress installation.
    • Enabled for fresh new installations.
  2. If get_site_option( ‘auto_update_core_major’ ) returns true or enabled, auto-updates are enabled. Otherwise, they are disabled. This option is the one stored in the database when the UI is triggered. If this option is set, it overrides the above use cases.
  3. If WP_AUTO_UPDATE_CORE constant returns truebeta, or rc, auto-updates are enabled. If the constant returns falseminor or is not defined, auto-updates are disabled. If this constant is set, it overrides the above parameters.
  4. If allow_major_auto_core_updates filter returns true or enabled, auto-updates are enabled. If the filter returns false or is not used, auto-updates are disabled. If this filter is used, it overrides the above parameters.

To disable auto-updates for major versions by default, developers can set the WP_AUTO_UPDATE_CORE to false (to disable all auto-updates) or minor (to enable only minor core auto-updates, which is the default behavior). It has to be done using the wp-config.php file.

Developers can alternatively use the allow_major_auto_core_updates filter to set up core major versions auto-updates to true or false by default. Example:

add_filter( 'allow_major_auto_core_updates', '__return_false' );

In the following screenshot, auto-updates for major versions have been enabled programmatically using a filter or a constant:

In the following screenshot, auto-updates for major versions have been disabled programmatically using a filter or a constant:

How to extend the core auto-updates UI?

There is an action hook running right at the end of this settings section to add some options if needed. Using the after_core_auto_updates_settings action hook, developers can add other settings or texts.

For example, the following snippet adds a link to WordPress documentation about auto-updates.

function my_plugin_after_core_auto_updates_settings( $auto_update_settings ) {
	?>
	<p class="auto-update-status">
		<?php _e( 'For more details about Core auto-updates, see <a href="https://wordpress.org/support/article/configuring-automatic-background-updates/">WordPress documentation</a>', 'my-plugin' ); ?>
	</p>
    <?php
}
add_action( 'after_core_auto_updates_settings', 'my_plugin_after_core_auto_updates_settings', 10, 1 );

Props @cbringmann, @planningwrite and @poena for proof-reading.

#5-6, #auto-updates, #core-auto-updates, #dev-notes, #feature-autoupdates

WordPress and PHP 8.0


Update on November 24, 2020: Added a call out in the “Strict type/value validations for internal functions” section that there are still scenarios where WP CoreCore Core is the set of software required to run WordPress. The Core Development Team builds WordPress. could potentially pass 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. types to PHPPHP The web scripting language in which WordPress is primarily architected. WordPress requires PHP 7.4 or higher core functions, especially where values are passed through filters. Props @hellofromtonya.


PHP 8.0 is in the final stages of its release cycle. As of the publish date of this post, version 8.0 RC5 has been released, and the final release of PHP 8.0.0 is scheduled for November 26, 2020.

As the expected changes in PHP 8 were made known earlier this year, WordPress Core contributorsCore Contributors Core contributors are those who have worked on a release of WordPress, by creating the functions or finding and patching bugs. These contributions are done through Trac. https://core.trac.wordpress.org. worked to identify potential compatibility issues within the code base. This includes a call to test earlier in the release cycle.

WordPress Core aims to be compatible with PHP 8.0 in the 5.6 release (currently scheduled for December 8, 2020).

However, PHP 8.0 is a major version update with a large number of changes that break backwards compatibility, and many features that were deprecated within the PHP 7.x feature releases have been officially removed.

What does compatibility mean here?

Significant effort has been put towards making WordPress 5.6 compatible with PHP 8 on its own, but it is very likely that there are still undiscovered issues remaining.

Because of the nature of WordPress usage and the commitment to our user base, compatibility is to be considered in the eyes of those users. The goal is to elevate the broader ecosystem to a state that is compatible with PHP 8. That requires that the Core software not just be compatible on its own, but also provides defenses against common problems seen in the transition to PHP 8, while continuing to function on older versions of PHP.

It also should be acknowledged that WordPress is never used in isolation (without any theme or plugins), so WordPress itself being able to run on PHP 8 does not indicate “full” compatibility.

The state of PHP 8 support within the broader ecosystem (plugins, themes, etc.) is impossible to know. For that reason, WordPress 5.6 should be considered “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. compatible” with PHP 8.

“Beta compatibility”

Calling WordPress 5.6 “beta compatible” is a good first step. Doing so acknowledges the hard work that has been done to get WordPress running on PHP 8 without major issues and achieve passing PHPUnit tests. It also honors the project’s commitment to being compatible with the new versions of PHP when they are released.

At the same time Core cannot claim “full compatibility” because the process to achieve that state takes a larger amount of time within the greater ecosystem. That’s where WordPress Core needs help.

All 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 developers, as well as hosting communities, are called on to make their code compatible with PHP 8. This will allow WordPress to attain truly “full compatibility” sooner, and without end users having to carry the burden.

It’s also worth noting that all known compatibility issues that were identified through automated testing or static analysis have been addressed, except those detailed further down in this post. Automated test coverage of WordPress Core needs much improvement, and some problems will require manual testing of WordPress on PHP 8 under varying conditions to discover.

For the reasons above, it is highly recommended that you thoroughly test your site before upgrading to PHP 8.


Below is a breakdown of why the PHP 8 update is a bit different than other more recent PHP updates, and the changes that directly affect WordPress in PHP 8.0 that developers need to be aware of.

PHP release types

The release process that the PHP project currently follows was proposed and established back in 2010. This process outlines strict guidelines around when certain types of changes can be made. The process is structured around the idea of “major releases”, and follows semantic versioning.

The current major release of PHP is 7. Over the last 5 years, there have been 4 feature releases for the PHP 7 major releasemajor release A release, identified by the first two numbers (3.6), which is the focus of a full release cycle and feature development. WordPress uses decimaling count for major release versions, so 2.8, 2.9, 3.0, and 3.1 are sequential and comparable in scope. (7.1, 7.2, 7.3, and 7.4), and over 130 security/bug fix releases to these feature releases.

Feature releases

Though new features and bugbug A bug is an error or unexpected result. Performance improvements, code optimization, and are considered enhancements, not defects. After feature freeze, only bugs are dealt with, with regressions (adverse changes from the previous version) being the highest priority. fixes are allowed in feature releases, backwards compatibility and 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. compatibility must be maintained. These rules dictating what types of changes are allowed, lower the likelihood that sites will break when upgrading to new feature releases within the same major release of PHP.

When older features are deprecated within these releases, they remain functional. It’s common practice for deprecated features to trigger errors (usually E_WARNING, E_NOTICE, or E_DEPRECATED level), informing developers that the feature is deprecated. Deprecated features can only be removed in a future major release.

Major releases

Like feature releases, bug fixes and new features can be added in major releases. However, old features can be removed entirely, maintaining backwards compatibility and API compatibility is not required.

As of PHP 8 RC4, there are 48 changes to core PHP that break backwards compatibility, and 166 throughout PHP 8 overall (extensions, libraries, etc.).

What this means for developers

Sites that are consistently updating to the latest versions of PHP and addressing issues with each feature release are usually less likely to experience problems when updating to a new major version.

New features in PHP 8 are not compatible with PHP 7 or PHP 5 and usually cause fatal errors.

While making your plugin or theme PHP 8 compatible is strongly encouraged, using features added in PHP 8 is not recommended in distributed plugins and themes unless Requires PHP is set to 8.0 in the 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. section of the main file (plugins) or style.css file (themes).

Changes in PHP 8

Below is a non-exhaustive breakdown of select changes in PHP 8.0 that plugin and theme developers need to be aware of and should accommodate in their code.

Named parameters

PHP 8 introduces the ability to pass arguments to a function by the parameter name instead of the parameter position. This is advantageous in several ways, but to name a few:

  • The argument’s meaning becomes self documenting.
  • The arguments become order-independent.
  • Default values can be skipped arbitrarily.

As an example, let’s take a look at retrieving a term as an associative array using get_term().

<?php
// PHP < 8.0
$my_term = get_term( 1, '', ARRAY_A );

// PHP >= 8.0
$my_term = get_term( output: ARRAY_A, term: 1 );

Note that the arguments in the second example are defined out of order, and because the arguments are not processed in order, the optional parameters using the default value, are no longer required.

Named parameters also work with PHP’s internal functions.

<?php
// Using positional arguments:
array_fill( 0, 100, 50 );

// Using named arguments:
array_fill( start_index: 0, count: 100, value: 50 );

This is a very simplistic overview of the named parameters feature. Please read the full Request for Comments (RFC) on the PHP website for a complete breakdown, which details the impact on variadic functions, func_get_args() and related functions, as well as call_user_func_array() and related functions.

Named parameters and WordPress

The named parameter feature introduces a significant backwards compatibility consideration for all PHP code going forward. With the introduction of this feature, parameter names become a part of the API contract and any changes to their names in future WordPress releases will break backwards compatibility, causing a fatal error when code is invoking a function using an outdated parameter name.

An active review of the function signatures throughout WordPress Core has been proposed to ensure that all parameter names are descriptive, accurate, and do not use reserved keywords to avoid any potential for confusion, but it will not be a part of WordPress 5.6.

Using named parameters when calling WordPress functions and class methods is explicitly not supported and highly discouraged until this audit can be completed, as during the audit, parameter names are subject to change without notice. When this audit has been completed, it will be announced in a future developer note.

If you choose to take advantage of named parameters when using WordPress Core functions and classes before that time, you do so at your own risk.

Additionally, PHP Core has been reviewing their own parameter names in anticipation of the PHP 8 release. Because the PHP documentation has not yet been updated to reflect PHP 8 changes, some of the parameter names currently detailed in the documentation may also change.

To follow or contribute to this review, see #51553, and #50531 on TracTrac An open source project by Edgewall Software that serves as a bug tracker and project management tool for WordPress..

Strict type/value validations for internal functions

When support for scalar type declarations was added in PHP 7.0, a new (optional) per-file directive to enforce strict type checking was also added. Including declare( strict_types = 1 ); at the top of a file would ensure that strict type checking is performed on all arguments and return values where scalar types were declared.

When configured, strict type checking also extends to extensions and internal PHP functions invoked within the file. In strict mode, when the type of a value passed does not match the type expected, a Fatal error: Uncaught TypeError is triggered.

However, when strict type checking was not enabled, the behavior of internal functions when receiving an unexpected type was very inconsistent. Some threw a warning and returned NULL, some returned false and threw a TypeError with strict types on, and others generated a TypeError (even if strict_types was not declared).

Starting in PHP 8, a TypeError will be consistently thrown for all internal PHP functions when invalid parameter types are passed, even when strict type checking is not declared.

Additionally, some PHP core functions which did not have type declarations previously, now do. It’s likely that some TypeErrors will be thrown for functions which didn’t even give a warning in older PHP versions.

Type checking for user-defined functions will remain the same. Including declare( strict_types = 1 ); at the top of files is required to enforce strict type checking throughout the file. No WordPress Core code uses strict mode.

An effort to ensure defensive code practices are in place to avoid any potential for invalid types to be passed to WordPress Core function is underway in #51423. Until this is completed, it is possible that some code within WordPress could trigger a TypeError, especially if a value’s type is incorrectly changed through code hooked to a 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..

Please read the full RFC on the PHP wiki for a complete breakdown of these changes. For more information on this as it relates to WordPress Core, see #51525 on Trac.

Stricter type checks for arithmetic and bitwise operators

In past versions of PHP, applying arithmetic and bitwise operators to arrays, non-overloaded objects, and resources was allowed. However, the behavior was sometimes inconsistent in different scenarios.

Starting in PHP 8, all arithmetic and bitwise operators will throw a TypeError when one of the operands is an array, non-overloaded object, or resource. An exception to this is array + array, which will remain unchanged.

Please read the full RFC on the PHP wiki for a complete breakdown of these changes. For more information on this as it relates to WordPress Core, see #51525 on Trac.

Saner numeric strings

Numeric string handling has been altered to be more intuitive and less
error-prone. Trailing white space is now allowed in numeric strings for
consistency with how leading white space is treated. This mostly affects:

  • The is_numeric() function
  • String-to-string comparisons
  • Type declarations
  • Increment and decrement operations

The concept of a “leading-numeric string” has been mostly dropped; the cases where this remains exist in order to ease migrationMigration Moving the code, database and media files for a website site from one server to another. Most typically done when changing hosting companies.. Strings which emitted an E_NOTICE “A non well-formed numeric value encountered” will now emit an E_WARNING “A non-numeric value encountered” and all strings which emitted an E_WARNING “A non-numeric value encountered” will now throw a TypeError. This mostly affects:

  • Arithmetic operations
  • Bitwise operations

This E_WARNING to TypeError change also affects the E_WARNING “Illegal string offset ‘string'” for illegal string offsets. The behavior of explicit casts to int/float from strings has not been changed.

Please read the full RFC on the PHP wiki for a complete breakdown of these changes.

Non-strict comparisons between numbers and non-numeric strings

Non-strict comparisons between numbers and non-numeric strings now work by casting the number to string and comparing the strings. Comparisons between numbers and numeric strings continue to work as before. Notably, this means that 0 == "not-a-number" is considered false now.

A few other code patterns that may be common in plugins and themes that will be affected:

  • '' < 0 is now considered true (see [48960]).
  • 'not-a-number' > 0 is also now considered true (see [49043]).

Error, warning, and notice changes

A large handful of preexisting errors have been reclassified. Here’s are some that may be commonly encountered:

Warnings converted to error exceptions

  • Attempting to write to a property of a non-object. Previously this
    implicitly created a stdClass object for null, false and empty strings.
  • Attempting to append an element to an array for which the PHP_INT_MAX key is already used.
  • Attempting to use an invalid type (array or object) as an array key or
    string offset.
  • Attempting to write to an array index of a scalar value.
  • Attempting to unpack a non-array/Traversable.

Please read the full RFC on the PHP wiki for more information on these changes.

Notices converted to warnings

  • Attempting to read an undefined variable.
  • Attempting to read an undefined property.
  • Attempting to read an undefined array key.
  • Attempting to read a property of a non-object.
  • Attempting to access an array index of a non-array.
  • Attempting to convert an array to string.
  • Attempting to use a resource as an array key.
  • Attempting to use null, a boolean, or a float as a string offset.
  • Attempting to read an out-of-bounds string offset.
  • Attempting to assign an empty string to a string offset.

Read the full RFC on the PHP wiki for more information.

Build & Test Tool Related Changes

Because WordPress supports PHP 5.6.20 or higher, running the WordPress Core PHPUnit test suite on PHP 8 is not straightforward.

  • PHPUnit >= 9.3 is the only version of PHPUnit that currently supports PHP 8.
  • PHPunit 5.7.x is the last version to include support for PHP 5.6.
  • PHPUnit 8.x changed several methods that do not return values to specify a void return type declaration. However, this return type is not available in PHP < 7.1.

In order to maintain the ability to run the test suite on PHP 5.6 while also allowing the tests to run on PHP 8, the changes to PHPUnit required have been backported into the WordPress Core test suite and Composer is used to manipulate the autoload process for PHPUnit 7.x.

To run the WordPress Core PHPUnit test suite on PHP 8, it is required to use Composer for installation and running.

To help make this easier, a new NPM script has been added to run the test suite within the local Docker environment using the Composer installed version of PHPUnit.

// Run within the local Docker container using version of
// PHPUnit installed within the container.
npm run test:php

// Run within the local Docker container using version of
// PHPUnit installed via Composer.
npm run test:php-composer

For more information on this new command, see #51456. For more information on making the test suite compatible with PHP 8/PHPUnit >= 8, see #46149, #50902, and #50913.

External Libraries

Several external libraries bundled with WordPress Core have been updated to fix PHP 8 compatibility issues. Pull requests have been opened where appropriate to ensure these changes are included in future releases of these libraries.

  • SimplePie has been updated from version 1.5.5 to 1.5.6 (see #51521). Additionally, the WP_Feed_Cache class has been deprecated and will only be loaded for backwards compatibility if SimplePie < 3 is loaded within a plugin (see #51629 and #29204).
  • sodium_compat was updated to avoid an error when attempting to access the MB_OVERLOAD_STRING constant, which has been removed in PHP 8 (see #51399).
  • Text_Diff was updated to fix a “Non-static method cannot be called statically” fatal error (see #51559).

Additional notes

  • create_function() has been removed. The final instance of this function in WordPress has been removed (see #50899).
  • The @ operator will no longer silence fatal errors. Care should be taken that error messages are not displayed in production environments, which can result in information leaks.
  • Following the hash comment operator # immediately with an opening bracket is not supported as a comment anymore since this syntax is now used for attributes.
  • libxml_disable_entity_loader() has been deprecated (see #50898).
  • Resource to object return type changes, including the introduction of the is_gd_image() function.
  • Changes to sorting: if any code relied on a certain sort order based on previous behavior, this may now fail.
  • The parameter/return types for various PHP functions have changed and may have an impact. Subtle changes like that substr() will now always return a string. Previously, this returned string|false.

Summary

As always, reading through the complete upgrade document is highly recommended.

Even as WordPress Core continues to expand its support for new versions of PHP, support for old versions will remain as is for the time being, staying at PHP 5.6.20 and higher until usage numbers show that the impact on users will be minimal.

There is a separate initiative to decrease the usage numbers for older versions of PHP being guided by the Core PHP team through the servehappy initiative. If you wish to help with this effort, please join the #core-php room in the Making WordPress Core Slack instance.

WordPress continues to encourage all users to run the latest and greatest versions of PHP. This includes PHP 8.0 upon its official release.

A full list of tickets related to PHP 8.0 support can be found on Trac.

Props @helen, @jrf, @jeffpaul, @sergeybiryukov, @andraganescu, @omarreiss, @hellofromtonya, and @chanthaboune for peer reviewing.

#5-6, #dev-notes, #php-8-0

Miscellaneous developer focused changes in WordPress 5.6

WordPress 5.6 includes several small, developer-focused, changes. Here’s a summary of what you can expect.

General: Replace older-style PHPPHP The web scripting language in which WordPress is primarily architected. WordPress requires PHP 7.4 or higher type conversion functions with type casts

PHP’s intval(), strval(), floatval(), and boolval() typecasting functions are artifacts in the WordPress code base from the PHP 4 days. In PHP 5 and later direct type casting is available, which is often many times more performant than their function predecessors.

In WordPress CoreCore Core is the set of software required to run WordPress. The Core Development Team builds WordPress., over 250 remaining occurrences of typecasting functions were removed in favor of direct typecasting. This improves performance, readability, and consistency throughout Core.

  • intval()(int)
  • strval()(string)
  • floatval()(float)

For more information, check out 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.: #42918.

General: Introduce the ability to merge multiple WP_Error objects into one another, and to store more than one item of data for an error

The WP_Error class is used throughout WordPress to indicate an error has occurred with some more specific details (an error code, message, etc.). While this class supports storing multiple error messages and codes in a single instance, it’s not currently possible to merge two WP_Error instances into one without doing so manually.

In WordPress 5.6, three new methods have been added to the WP_Error class to help with these scenarios. 

<?php
$error_1 = new WP_Error(
    'code1',
    'This is my first error message.',
    'Error_Data'
);

$error_2 = new WP_Error(
    'code2',
    'This is my second error message.',
    'Error_Data2'
);

// Merge from another WP_Error.
$error_1->merge_from( $error_2 );

// Retrieve all error data, optionally for a specific error code.
$error_1->get_all_error_data( 'code2' );

// Export to another WP_Error
$error_1->export_to( $error_2 );

For more information, check out the related ticket on Trac: #38777.

Pings/Trackbacks: Split do_all_pings() into several functions

The do_all_pings() function is responsible for performing pingbacks, trackbacks, enclosures, and updates for a site. However, in its current state, it’s impossible to disable just one of those services.

In WordPress 5.6, each service has been split out into its own function.

  • do_all_pingbacks()
  • do_all_enclosures()
  • do_all_trackbacks()
  • generic_ping() has existed since WordPress 1.2

The do_all_pings() function will remain in order to prevent changing the behavior configured by any 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 currently unhooking do_all_pings() from the do_pings action. do_all_pings() will now fire a new action, do_all_pings, with the four functions above attached.

As an example, let’s say you wish to disable only trackbacks. The following snippet would unhook the trackbacks function, preventing trackbacks from being performed.

 <?php
 remove_action( ‘do_all_pings’, ‘do_all_trackbacks’ ); 

For more information, check out the related ticket on Trac: #36576.

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.: Allow for wp_count_terms( $args ) signature, making passing a taxonomy optional

In WordPress 4.3, the concept of shared taxonomy terms was eliminated. This paved the road for many taxonomy related features and improvements in the following years, including the WP_Term class (#14162) and term 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. (#10142) in WordPress 4.4, and making the $taxonomy parameter optional when calling get_terms() (see #35495).

In WordPress 5.6, the wp_count_terms() function signature has been updated for consistency and now matches that of get_terms(). This also makes it more apparent that wp_count_terms() can be used to count all terms, and not just ones from a certain taxonomy.

Similar to the change previously made to get_terms(), no deprecation warnings are triggered when using the legacy function signature.

For more information, check out the related ticket on Trac: #36399.

Build/Test Tools: Fix code coverage generation

The phpunit.xml.dist file that configures the PHPUnit test suite was incorrectly configuring the code coverage setup to generate a code coverage report from the src directory. Because the WP_RUN_CORE_TESTS constant is also defined as 1 in the ruleset, the codebase is run from the build directory. This was resulting in an empty and inaccurate coverage report.

This makes the coverage setup consistent with other parts of the test suite when the WP_RUN_CORE_TESTS constant is set to 1.

Note: If you have a local phpunit.xml file that changes the WP_RUN_CORE_TESTS constant to 0, you should also – in the same file – change the code coverage setup to use the src directory instead.

For more information, check out the related ticket on Trac: #50267.

Networks and Sites: New filters and actions

In WordPress 5.6, two new filters have been introduced to provide more control over the email sent out to administrators when a new site is created.

First, the new_site_email_filter has been added to allow developers to alter the following parts of this email: to, subject, message, and headers.

Second, the send_new_site_email has been added to allow developers to disable this email entirely. Returning false to this 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. will prevent the email from being sent at all.

For more information on these filters, check out the related ticket on Trac: #42134.

Additionally, the network_site_info_form action has been added in the site info form within the networknetwork (versus site, blog) adminadmin (and super admin). This action hook allows developers to add additional fields to the form.

For more information, check out the related ticket on Trac: #50704.

Database: Deprecated post_category column removed

In WordPress 2.8, the posts.post_category database column was dropped from the database schema and, it will no longer be added to new sites. However, the column was never removed from sites created with WordPress 2.7 or earlier.

Upon upgrading to WordPress 5.6, the posts.post-category column will be removed from the posts table if present in the database.

For more information, check out the related ticket on Trac: #51288.

General: Add $options parameter to JSONJSON JSON, or JavaScript Object Notation, is a minimal, readable format for structuring data. It is used primarily to transmit data between a server and web application, as an alternative to XML. response functions

WordPress has several utility functions for sending proper JSON responses to requests. Eventually, they all call wp_json_encode(), which accepts an $options parameter. This gets passed to the PHP internal json_encode() function as the $flags argument.

The following functions now accept an $options parameter:

  • wp_send_json()
  • wp_send_json_success()
  • wp_send_json_error()

For more information, check out the related ticket on Trac: #51293.

Additional developer changes

  • Administration: Restore alternative admin menu position for menu items with the same position value as an existing menu item (see #42918).
    Comments: Adds a comments_template_top_level_query_args filter for top level comments query arguments in comments_template() (see  #38074).
  • Media: sanitize_file_name() now removes accents, making it more consistent with sanitize_title() and sanitize_user() (see #22363).
  • Media: The image_sideload_extensions filter has been added to the list of allowed file extensions when sideloading an image from a URLURL A specific web address of a website or web page on the Internet, such as a website’s URL www.wordpress.org (see #50695).
  • Media: Stream wrappers are now supported by the WP_Image_Editor_Imagick image editing class (see #42663).
  • Media: The wp_get_attachment_image filter has been introduced within wp_get_attachment_image() to filter the HTMLHTML HyperText Markup Language. The semantic scripting language primarily used for outputting content in web browsers. output (see #50801).
  • Multisitemultisite Used to describe a WordPress installation with a network of multiple blogs, grouped by sites. This installation type has shared users tables, and creates separate database tables for each blog (wp_posts becomes wp_0_posts). See also network, blog, site: get_dirsize() now has a more contextual cache, storing sizes by directory resulting in a performance improvement (see #19879).
  • Quick/Bulk Edit: The quick_edit_dropdown_authors_args filter has been introduced to allow the authors dropdown within the Quick Edit interface to be modified (see #47685).
  • Site Health: The recovery_mode_email filter has been updated to support attachments. This adds the ability for developers to add attachments to pass to wp_mail() (see #51276).
  • Users: Introduce email_exists filter, to complement username_exists (see #51379).
  • Users: Introduce the invited_user_email filter for filtering the contents of the email sent when an existing user is invited to a site on Multisite (see #42132).
  • Upgrade/Install: Introduce the wp_installed_email filter for filtering the contents of the email sent when WordPress is installed, without needing to override the wp_new_blog_notification() pluggable function (see #42133).
  • Widgets: When support for the HTML5 navigation-widgets is declared, the 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.) cloud widgetWidget A WordPress Widget is a small block that performs a specific function. You can add these widgets in sidebars also known as widget-ready areas on your web page. WordPress widgets were originally created to provide a simple and easy-to-use way of giving design and structure control of the WordPress theme to the user. is now properly wrapped in a <nav> element to improve semantics and accessibilityAccessibility Accessibility (commonly shortened to a11y) refers to the design of products, devices, services, or environments for people with disabilities. The concept of accessible design ensures both “direct access” (i.e. unassisted) and “indirect access” meaning compatibility with a person’s assistive technology (for example, computer screen readers). (https://en.wikipedia.org/wiki/Accessibility) (see #51455).

Props @desrosj and @newyorkerlaura for helping to draft/review.

#5-6, #dev-notes

REST API Batch Framework in WordPress 5.6

WordPress 5.6 introduces a framework for making a series of 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/. calls in one request to the server. At its simplest, this is a helpful performance optimization when a large number of write operations need to be made. It also optionally offers basic concurrency controls.

Registration

In order to be used in a batch request, routes must first declare support for the feature during their registration. For example:

register_rest_route( 'my-ns/v1', 'my-route', array(
	'methods'             => WP_REST_Server::CREATABLE,
	'callback'            => 'my_callback',
	'permission_callback' => 'my_permission_callback',
	'allow_batch'         => array( 'v1' => true ),
) );

If the REST API route was implemented using best practices, declaring support should be sufficient for the route to be writable via the batch endpoint. Specifically, these are the things to look out for:

  1. Routes must use the WP_REST_Request object to get all request data. In other words, it shouldn’t access the $_GET, $_POST or $_SERVER variables to get parameters or headers.
  2. Routes must return data. This could be a WP_REST_Response object, a WP_Error object or any kind of JSONJSON JSON, or JavaScript Object Notation, is a minimal, readable format for structuring data. It is used primarily to transmit data between a server and web application, as an alternative to XML. serializable data. This means the route must not directly echo the response and die(). For example by using wp_send_json() or wp_die().
  3. Routes must be re-entrant. Be prepared for the same route to be called multiple times in a batch.

Making a Request

To send a batch, make a POST request to https://yoursite.test/wp-json/batch/v1 with an array of the desired requests. For example, the simplest batch request looks like this.

{
  "requests": [
    {
      "path": "/my-ns/v1/route"
    }
  ]
}

Request Format

Each request is an object that can accept the following properties.

{
  "method": "PUT",
  "path": "/my-ns/v1/route/1?query=param",
  "headers": {
    "My-Header": "my-value",
    "Multi": [ "v1", "v2" ]
  },
  "body": {
    "project": "Gutenberg"
  }
}
  • method is 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. method to use for the request. If omitted, the POST method is used.
  • path is the REST API route to call. Query parameters can be included. This property is required.
  • headers is an object of 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. names to a header values. If the header has multiple values, it can be passed as an array.
  • body is the parameters to pass to the route. It is filled in the POST parameter type.

Discovering Max Requests

By default, the REST API accepts up to 25 requests in a single batch. However, this value is filterable so it can be scaled up or down based on server resources.

function my_prefix_rest_get_max_batch_size() {
	return 50;
}

add_filter( 'rest_get_max_batch_size', 'my_prefix_rest_get_max_batch_size' );

As such, clients are strongly encouraged to make a preflight request to discover the limit. For example, making an OPTIONS request to batch/v1 will return the following response.

{
  "namespace": "",
  "methods": [ "POST" ],
  "endpoints": [
    {
      "methods": [ "POST" ],
      "args": {
        "validation": {
          "type": "string",
          "enum": [ "require-all-validate", "normal" ],
          "default": "normal",
          "required": false
        },
        "requests": {
          "type": "array",
          "maxItems": 25,
          "items": {
            "type": "object",
            "properties": {
              "method": {
                "type": "string",
                "enum": [ "POST", "PUT", "PATCH", "DELETE" ],
                "default": "POST"
              },
              "path": {
                "type": "string",
                "required": true
              },
              "body": {
                "type": "object",
                "properties": [],
                "additionalProperties": true
              },
              "headers": {
                "type": "object",
                "properties": [],
                "additionalProperties": {
                  "type": [ "string", "array" ],
                  "items": {
                    "type": "string"
                  }
                }
              }
            }
          },
          "required": true
        }
      }
    }
  ],
  "_links": {
    "self": [
      {
        "href": "http://trunk.test/wp-json/batch/v1"
      }
    ]
  }
}

The limit is specified in the endpoints[0].args.requests.maxItems property.

Response Format

The batch endpoint will return a 207 status code and the responses of each request in the same order as they were requested. For example:

{
  "responses": [
    {
      "body": {
        "id": 1,
        "_links": {
          "self": [
            {
              "href": "http://trunk.test/wp-json/my-ns/v1/route/1"
            }
          ]
        }
      },
      "status": 201,
      "headers": {
        "Location": "http://trunk.test/wp-json/my-n1/v1/route/1",
        "Allow": "GET, POST"
      }
    }
  ]
}

Internally, the REST API envelopes each response before including it in the responses array.

Validation Modes

By default, each request is processed in isolation. This means that a batch response can contain some requests that were successful, and some that failed. Sometimes it’s desired to only process a batch if all the requests are valid. For instance, in GutenbergGutenberg The Gutenberg project is the new Editor Interface for WordPress. The editor improves the process and experience of creating new content, making writing rich content much simpler. It uses ‘blocks’ to add richness rather than shortcodes, custom HTML etc. https://wordpress.org/gutenberg/ we don’t want to save some menu items, ideally all would be saved or none would.

To accomplish this, the REST API allows for passing a validation mode of require-all-validate. When this is set, the REST API will first check that each request is valid according to WP_REST_Request::has_valid_params() and WP_REST_Request::sanitize_params(). If any request fails validation, then the entire batch is rejected.

In this example, a batch of two requests is made and the second one has failed validation. Since the order of responses is still the same as the order of requests, null is used to indicate that the request didn’t fail validation.

{
  "failed": "validation",
  "responses": [
    null,
    {
      "body": {
        "code": "error_code",
        "message": "Invalid request data",
        "data": { "status": 400 }
      },
      "status": 400,
      "headers": {}
    }
  ]
}

Note: Using require-all-validate is not a guarantee that all requests will be successful. A route callback may still return an error.

Validate Callback

Those WP_REST_Request methods use the validate_callback and sanitize_callback specified for each parameter when the route is registered. In most cases, this will mean the schema based validation.

Any validation done inside the route, for instance in the prepare_item_for_database method, will not cause the batch to be rejected. If this is a concern, it is recommended to move as much validation as possible into the validate_callback for each individual parameter. This can be built on top of the existing schema based validation, for instance.

'post' => array(
	'type'        => 'integer',
	'minimum'     => 1,
	'required'    => true,
	'arg_options' => array(
		'validate_callback' => function ( $value, $request, $param ) {
			$valid = rest_validate_request_arg( $value, $request, $param );

			if ( is_wp_error( $valid ) ) {
				return $valid;
			}

			if ( ! get_post( $value ) || ! current_user_can( 'read_post', $value ) ) {
				return new WP_Error( 'invalid_post', __( 'That post does not exist.' ) );
			}

			return true;
		}
	)
)

Sometimes when performing validation, the full context of the request is needed. Typically, this validation would have been done in prepare_item_for_database, but WordPress 5.6 introduces an alternative. When registering a route, a top-level validate_callback can now be specified. It will receive the full WP_REST_Request object and can return a WP_Error instance or false. The callback won’t be executed if parameter-level validation did not succeed.

register_rest_route( 'my-ns/v1', 'route', array(
	'callback'            => '__return_empty_array',
	'permission_callback' => '__return_true',
	'validate_callback'   => function( $request ) {
		if ( $request['pass1'] !== $request['pass2'] ) {
			return new WP_Error(
				'passwords_must_match',
				__( 'Passwords must match.' ),
				array( 'status' => 400 )
			);
		}

		return true;
	}
) );

Note: Request validation happens before permission checks take place. Keep this in mind when considering whether to moving logic to a validate_callback.

Limitations

No built-in routes currently allow batching. This will be added in a future release, most likely starting immediately with WordPress 5.7.

GET requests are not supported. Developers are instead encouraged to use linking and embedding or utilize parallel requests for the time being.

Further Reading

See #50244, [49252], [48947], [48945].

Props @kadamwhite, @m_butcher, @jeffmatson for reviewing.

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

New action wp_after_insert_post in WordPress 5.6.

The new action wp_after_insert_post has been added to WordPress 5.6 to allow theme and 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 developers to run custom code after a post and its terms and 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. data have been updated.

The save_post and related actions have commonly been used for this purpose but these 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. can fire before terms and meta data are updated outside of the classic editor. (For example in 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/., via 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, within the CustomizerCustomizer Tool built into WordPress core that hooks into most modern themes. You can use it to preview and modify many of your site’s appearance settings. and when an auto-draft is created.)

The new action sends up to four parameters:

  • $post_id The post ID has been updated, an integer.
  • $post The full post object in its updated form, a WP_Post object.
  • $updated Whether the post has been updated or not, a boolean.
  • $post_before The full post object prior to the update, a WP_Post object. For new posts this is null.

By default WordPress fires this hook at the end of wp_insert_post(). A third parameter has been added to the function to allow developers to prevent the hook from firing automatically:

  • $fire_after_hooks Whether to fire the after insert hooks, a boolean. Optional, default true.

The same parameter has been added to wp_update_post() as the third parameter and wp_insert_attachment() as the fifth parameter.

In the event a developer calls any of these functions and prevents the hook from firing, it is expected they will manually call the new function wp_after_insert_post() to trigger the new action. This new function requires three parameters:

  • $post The post ID or object that has been saved, ether an integer or WP_Post object
  • $update Whether the post has been updated (true) or inserted (false).
  • $post_before null for new posts, the WP_Post object prior to the update for updated posts.

For the history of this change, see ticketticket Created for both bug reports and feature development on the bug tracker. #45114. The changes were committed in [49172] and [49731]. A discussion on the approach took place in Slack during a dev chat.

An example when inserting a post.

In the event you are calling wp_insert_post() or one of the related functions listed above, if you are then updating the post’s terms or meta data separately it is recommended you prevent the hook from running and call it manually. For example:

$post_id = wp_insert_post(
    array(
        'post_title'   => 'My post title',
        'post_content' => 'My post content',
        'post_type'    => 'my_cpt',
    ),
    false,
    false
);

add_post_meta( $post_id, 'my_meta_key', 'my meta value' );

wp_after_insert_post( $post_id, false, null );

When updating a post, you will need to store the WP_Post object’s state before running the update. Due to the way PHPPHP The web scripting language in which WordPress is primarily architected. WordPress requires PHP 7.4 or higher passes objects and the get_post() internals, it is recommended you get the post via its ID.

$before_post = get_post( $post_id );

wp_update_post(
    array(
        'ID'           => $post_id,
        'post_title'   => 'My updated post title',
        'post_content' => 'My updated post content',
    ),
    false,
    false
);

add_post_meta( $post_id, 'my_meta_key', 'my meta value' );

wp_after_insert_post( $post_id, true, $before_post );

Props to @planningwrite, @timothyblynjacobs and @chrisvanpatten for reviewing this dev notedev 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..

Edit: The $post_before parameters were committed after this dev note was first published. This has been updated to reflect those changes.

#5-6, #dev-notes

New createBlocksFromInnerBlocksTemplate Block API

There is a 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. 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. in WordPress 5.6: createBlocksFromInnerBlocksTemplate, with which you can create blocks from InnerBlocks template.

Given an array of InnerBlocks templates or Block Objects, it returns an array of created Blocks from them.
It handles the case of having InnerBlocks as Blocks by converting them to the proper format to continue recursively.

This is especially useful for handling block variations, transformations and creation/replacement of blocks which use InnerBlocks template.

An example that would create new blocks from a block variation using InnerBlocks’ template and replace the block’s content is:

import { InnerBlocks } from '@wordpress/block-editor';
import { useDispatch } from '@wordpress/data';
import { __ } from '@wordpress/i18n';
import { Button, ToolbarGroup, ToolbarButton } from '@wordpress/components';
import { BlockControls, useBlockProps } from '@wordpress/block-editor';
import { createBlocksFromInnerBlocksTemplate } from '@wordpress/blocks';

function MyEditBlock( { clientId } ) {
    const { replaceInnerBlocks } = useDispatch( 'core/block-editor' );
    const variation = {
        name: 'my-variation',
        title: __( 'My variation' ),
        innerBlocks: [
            [ 'core/paragraph', { content: 'Hello' } ],
            [ 'core/paragraph', { placeholder: __( 'Write title…' ) } ],
        ],
    };
    const onClick = () => {
        replaceInnerBlocks(
            clientId,
            createBlocksFromInnerBlocksTemplate( variation.innerBlocks )
        );
    };
    return (
        <div { ...useBlockProps() }>
            <BlockControls>
                <ToolbarGroup>
                    <ToolbarButton onClick={ onClick }>
                        <span>Change InnerBlocks</span>
                    </ToolbarButton>
                </ToolbarGroup>
            </BlockControls>
            <InnerBlocks />
        </div>
    );
}

See the pull request for implementation details and more.

Props to @ntsekouras for writing this dev notedev 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..

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

Changes to Toolbar components in WordPress 5.6

Toolbar shouldn’t be used within other toolbars

To better reflect its semantics, the Toolbar component shouldn’t be used to group a set of toolbar controls within another toolbar anymore and will show a deprecation warning if used like so. ToolbarGroup should be used instead.

Before

<BlockControls>
  <Toolbar>
    <ToolbarButton />
  </Toolbar>
</BlockControls>

After

<BlockControls>
  <ToolbarGroup>
    <ToolbarButton />
  </ToolbarGroup>
</BlockControls>

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. toolbars now require controls to be ToolbarButton or ToolbarItem elements

Rendering native <button> or other custom tabbable elements directly as toolbar items (for example, using BlockControls or BlockFormatControls) has been deprecated. In order to improve toolbar accessibilityAccessibility Accessibility (commonly shortened to a11y) refers to the design of products, devices, services, or environments for people with disabilities. The concept of accessible design ensures both “direct access” (i.e. unassisted) and “indirect access” meaning compatibility with a person’s assistive technology (for example, computer screen readers). (https://en.wikipedia.org/wiki/Accessibility), toolbar items now should use ToolbarButton for regular buttons, or ToolbarItem for any other kind of control (for example, dropdowns).

Before

<BlockControls>
  <button />
  <Button />
  <DropdownMenu />
</BlockControls>

After

<BlockControls>
  <ToolbarItem as="button" />
  <ToolbarButton />
  <ToolbarItem>
    { ( itemProps ) => ( <DropdownMenu toggleProps={ itemProps } /> ) }
  </ToolbarItem>
</BlockControls>

Props to @hazdiego for writing this dev notedev 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..

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

Editor styling changes in WordPress 5.6

These changes are important enhancements for both accessibilityAccessibility Accessibility (commonly shortened to a11y) refers to the design of products, devices, services, or environments for people with disabilities. The concept of accessible design ensures both “direct access” (i.e. unassisted) and “indirect access” meaning compatibility with a person’s assistive technology (for example, computer screen readers). (https://en.wikipedia.org/wiki/Accessibility) and user experience on small screens.

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. styles use relative instead of absolute values

Previously, blocks were using hardcoded pixel values for all their sizing properties (paddings, margins, font-sizes etc).

Starting with WordPress 5.6, default block-styles use font-size-relative units (em) making it easier for themes to change the default content font-size without having to rewrite/override all block styles.

Media & Text blocks show media on top in mobile view

Previously, if the stack on mobile behavior was not disabled, and media had the option to appear on the left (the default), on mobile, the media appeared on top and the text on the bottom. If media had the option to appear on the right on mobile when stacked media would appear at the bottom and text on top.

There was feedback that the left/right position of media should not map to top/bottom on mobile and that for a better UXUX User experience on mobile, media should always appear on top. Starting with WordPress, 5.6 media text blocks will have media on top on mobile unless the stack on mobile option is disabled, and in that case, media appears at the side of text like on desktop.

Props to @aristath and @jorgefilipecosta for writing these 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..

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

Reusable Blocks extracted into a separate package

Reusable blocks are a feature available in the post editor. They were previously part of the @wordpress/editor package. To make them available in other editors, they have been moved to a separate package called @wordpress/reusable-blocks.

How it works

To enable reusable blocks in your 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, simply change your <BlockEditorProvider /> as follows:

import { ReusableBlocksMenuItems } from '@wordpress/reusable-blocks';

const { __experimentalReusableBlocks } = useSelect(
    ( select ) => select( 'core' ).getEntityRecords(
        'postType',
        'wp_block',
    )
);

return (
    <BlockEditorProvider
        settings={ {
            ...settings,
            __experimentalReusableBlocks,
        } }
        { ...props } // value, onInput, onChange, etc.
    >
        <ReusableBlocksMenuItems />
        { children }
    </BlockEditorProvider>
);

Props to @zieladam for writing this dev notedev 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..

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