Miscellaneous developer focused changes in WordPress 5.7

In WordPress 5.7, a large handful of developer-focused changes were made that deserve to be called out. Let’s take a look!

Post statuses when counting term posts

The _update_post_term_count() function is responsible for querying the database for the number of objects belonging to a given term and updating the count property for that term in the database. However, the publish post status has been hard coded in the database query ever since it was introduced in [5556] (except for when counting attachments, which always use the inherit status).

If a site wants to include posts with a different status in a term’s count, the current solution is to use the edited_term_taxonomy action hook that immediately follows the code updating the term’s count in the database. This can be used to run an additional query to calculate the desired count, and a second query to update the term’s count in the database to reflect this. This works, but results in unnecessary database queries.

Starting in WordPress 5.7, the update_post_term_count_statuses 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 adjust the list of post statuses used when counting posts for a term.


The following example uses the update_post_term_count_statuses filter to include posts with the future status when counting posts for a category 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. term.

 * Include posts with the future status in term counts.
 * @param string[]    $post_statuses List of post statuses to include in the count. Default is 'publish'.
 * @param WP_Taxonomy $taxonomy      Current taxonomy object.
 * @return List of post statuses to include in the count.
function myplugin_custom_statuses_in_term_counts( $post_statuses, $taxonomy ) {
	if ( 'category' !== $taxonomy->name ) {
		return $post_statuses;

	if ( ! in_array( 'future', $post_statuses, true ) ) {
		$post_statuses[] = 'future';

	return $post_statuses;
add_filter( 'update_post_term_count_statuses', 'myplugin_custom_statuses_in_term_counts', 10, 2 );

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

Overriding the behavior of wp_mail()

The wp_mail() function is one of roughly 40 functions in WordPress CoreCore Core is the set of software required to run WordPress. The Core Development Team builds WordPress. that are “pluggable”. Pluggable functions are ones that can be completely replaced simply by being defined elsewhere. WordPress wraps its own version of these functions in an if ( ! function_exists( 'function_name' ) ) check, allowing other versions of the function to take precedent without causing a PHPPHP The web scripting language in which WordPress is primarily architected. WordPress requires PHP 5.6.20 or higher fatal error.

While this approach is sometimes handy, it’s often using a sledgehammer to crack a nut, as most of the desired adjustments are very minor. There are also a lot of problems with defining custom versions of pluggable functions:

  • Unless you are monitoring changes to these functions in each new version of WordPress and merging in changes, the custom versions of a function will not receive 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, improvements, or compatibility enhancements.
  • Pluggable functions can only be overridden once, and there’s no reliable way to control which custom version of the function is used (whichever is loaded first wins).
  • No assumptions can be made about the code found within a custom versions of pluggable functions. If an action or filter hook is added to WordPress, there’s no guarantee the custom version will ever be updated to include that filter.

In WordPress 5.7, a new filter has been introduced to allow the wp_mail() function to be short-circuited without having to define a custom version of the entire function. When a non-null value is returned to the new pre_wp_mail filter, wp_mail() will assume the email is being processed elsewhere and will return early.

This makes it easier for emails to be handled differently in various environment types (staging, local, etc.), placed in some type of queue system, etc., and prevents unnecessary processing.

For more information on this change, see #35069 on Trac.

Better error handling in the Cron 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.

Since WordPress 5.1, the various WP-Cron related functions (wp_schedule_event(), etc.) now return meaningful return values, but the underlying reason for failure is still not surfaced.

To solve this, a new $wp_error parameter has been added to all functions writing to the cron array. This allows more descriptive and meaningful errors can be returned instead of just false. The functions affected are:

  • wp_schedule_single_event()
  • wp_schedule_event()
  • wp_reschedule_event()
  • wp_unschedule_event()
  • _set_cron_array() (meant for internal use only)

The related filters have also been updated to pass and receive a WP_Error object. The filters affected are:

  • pre_schedule_event
  • pre_reschedule_event
  • pre_unschedule_event

For more information on this change, see #49961 on Trac.

Additional developer treats

  • Two new functions have been introduced to determine whether a post status or post should be viewable more easily: is_post_status_viewable() and is_post_publicly_viewable() (see #49380).
  • Embeds will now work for all posts with public post statuses, even custom ones. Previously, only posts with the publish status could be embedded (see #47574).
  • When WP_DEBUG is set to true, PHP error suppression flags will no longer be applied when calling getimagesize(). This will help identify scenarios where errors occur with the goal of removing all error suppression in the future. In PHP 8.0, the @ operator was updated and no longer suppresses fatal errors. These calls have also been wrapped in the new wp_getimagesize() function to minimize code repetition (see #49889.
  • The redirect_canonical() function has been updated to ensure that users are only redirected to private posts if they are authenticated. All other users will be shown a 404 page at the originally requested URLURL A specific web address of a website or web page on the Internet, such as a website’s URL www.wordpress.org. This removes the ability to use ID enumeration to discover the slugs of private posts (see #5272).
  • The new wp_image_src_get_dimensions filter has been added to the wp_image_src_get_dimensions() function to allow the dimensions for a file to be corrected whenever WordPress is not able to correctly retrieve them from attachment metadata (see #51865).
  • get_post_status() has been improved to prevent false from being returned for the attachment post type when the parent post has been deleted (see #52326).
  • The bulk edit checkboxes in post list tables are currently tied to the edit_post capability. However, it is sometimes desirable to show or hide these checkboxes in certain scenarios. The new wp_list_table_show_post_checkbox filter added in 5.7 will allow more control over when these checkboxes are visible (see #51291).
  • The Quick/Bulk Edit dropdown fields at the top and bottom of post list tables will no longer produce unexpected behavior. Previously, some list tables ignored the bottom dropdown value entirely, always applying the value selected in the field at the top, and selecting a new value in one dropdown did not synchronize to the other (see #46872).
  • The WP_MEMORY_LIMIT constant has been added to the debug info in Site Health (see #51680).
  • In WordPress 5.7, A new string, filter_by_date, is accepted in the labels array passed to register_post_type(). This label is output for the date filter in list tables and defaults to Filter by date (see #42421).
  • Also in 5.7, a new string, filter_by_item, is accepted in the labels array passed to register_taxonomy(). This label is used for the related filter displayed at the top of list tables, but only for hierarchical taxonomies. The default value is Filter by category (see #42421).
  • sort and args are now officially declared as properties within the WP_Taxonomy class. These have been in use since WordPress 2.5 and 2.6 but were never declared as class properties (see #52142).
  • The PHPMailer library has been updated to the latest version, 6.3.0 (see #52577).

Props for @audrasjb for contributing and @cbringmann, @metalandcoffee for reviewing.

#5-7, #dev-notes