Miscellaneous Core changes in WordPress 5.9

WordPress 5.9 brings a lot of smaller changes that developers should know about. Here’s a breakdown.

Comment text field now marked as required

With WP 5.9, a required asterisk is added to the comment text field. Historically, the name and email fields were marked as required, but the comment text field was not, though it was actually a required field.

Please note this change also adds a container to the comment required text sentence, with the required-field-message class.

If the theme (or 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) creates a custom logged_in_as or comment_notes_before message, this could result in having the asterisk character indicate the required Comment field without a “Required fields are marked *” explanation. For example, Twenty Nineteen and Twenty Twenty-One had removed the logged_in_as text by setting it to null, so the default text has been restored to display the required fields message (with the links).

Also, if a theme styles the indicator character specifically for the Name and Email field labels—as Twenty Eleven had done—those styles should apply to the Comment field label as well.

For more information, see 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. #16206 and related commits: [52029], [52149], [52200].

Two new oEmbed providers: Wolfram Notebook and Pinterest

All of the Wolfram services are tied together by the Wolfram Language: Notebooks are their hosted version of Wolfram Language based documents. Their oEmbed 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. is based on the following URLURL A specific web address of a website or web page on the Internet, such as a website’s URL www.wordpress.org scheme: https://www.wolframcloud.com/oembed. There is also a secondary endpoint that returns the embed wrapped in an iframeiframe iFrame is an acronym for an inline frame. An iFrame is used inside a webpage to load another HTML document and render it. This HTML document may also contain JavaScript and/or CSS which is loaded at the time when iframe tag is parsed by the user’s browser.: https://www.wolframcloud.com/oembed/iframe/.

For more information, see Trac ticket #53326.

Pinterest provides a single oEmbed endpoint, which handles URLs of pins, boards, and profiles: https://www.pinterest.com/oembed.json.

For more information, see Trac ticket #53448.

KSES: Add options for restricting tags based upon their attributes

This change adds two now attribute-related config options to KSES:

  • An array of allowed values can be defined for attributes. If the attribute value doesn’t fall into the list, the attribute will be removed from 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.).
  • Attributes can be marked as required. If a required attribute is not present, KSES will remove all attributes from the tag. As KSES doesn’t match opening and closing tags, it’s not possible to safely remove the tag itself, the safest fallback is to strip all attributes from the tag, instead.

Allow PDFs to be embedded as objects

Included with this change is an implementation of these options, allowing the <object> tag to be stored in posts, but only when it has a type attribute set to application/pdf.

This implementation also introduces the _wp_kses_allow_pdf_objects callback function, which is used to check if a PDF URL is safe.

For more information, see ticket #54261.

Remove role="navigation" from <nav> elements

According to HTML5 documentation, adding role="navigation" to a <nav> element is unnecessary. It should only be added to elements like <div> instead, when using the semantically correct <nav> is not possible.

Historically, role="navigation" was required for assistive technologyAssistive technology Assistive technology is an umbrella term that includes assistive, adaptive, and rehabilitative devices for people with disabilities and also includes the process used in selecting, locating, and using them. Assistive technology promotes greater independence by enabling people to perform tasks that they were formerly unable to accomplish, or had great difficulty accomplishing, by providing enhancements to, or changing methods of interacting with, the technology needed to accomplish such tasks. https://en.wikipedia.org/wiki/Assistive_technology to recognize HTML5 element’s native ARIA roles while HTML5 and ARIA were being introduced. With the deprecation of IE11, the role attribute is only required when mapping elements that don’t have native role.

This change removes the navigation role from the following items:

  • All the legacy navigation widgets
  • All the bundled themes from Twenty Eleven to Twenty Twenty-One
  • Functions such as the_posts_pagination(), which go through the _navigation_markup() function in the /wp-includes/link-template.php file.

For more information, see ticket #54054.

New hook in wp_http_validate_url to control which ports are allowed for remote requests

By default, WordPress only allows ports 80, 443, and 8080 to be used for (safe) remote requests. WordPress 5.9 adds a way to remove these hardcoded ports so it is possible to better control which ports are allowed or not.

The http_allowed_safe_ports can be used to control the list of ports considered safe in 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. API, with the following parameters:

  • $allowed_ports: Array of integers for valid ports.
  • $host: Host name of the requested URL.
  • $url: The requested URL.

Usage example:

function wporg_customize_http_allowed_safe_ports( $allowed_ports, $host, $url ) {
	$allowed_ports = array( 80, 81, 443, 444, 8080, 8081 );
	return $allowed_ports;
apply_filters( 'http_allowed_safe_ports', 'wporg_customize_http_allowed_safe_ports', 10, 3 );

For more information, see ticket #54331.

New wp_mail_succeeded hook for the wp_mail() function

WordPress 5.9 adds a new wp_mail_succeeded action in wp_mail() after the mail is sent. Please note that the hook’s firing does not necessarily mean the recipient received the mail, only that the mail was processed without any errors.

Usage example:

 * Logs each successful mail operation related to a specific user. 
function wporg_wp_mail_succeeded( $mail_data ) {
	$successful_mail_logs = get_site_option( 'successful_mail_logs', array() );
	if ( 'user@example.org' === $mail_data['to'] ) {
		$successful_mail_logs[] = current_time( 'mysql' );
		update_site_option( 'successful_mail_logs', $successful_mail_logs );
add_action( 'wp_mail_succeeded', 'wporg_wp_mail_succeeded', 10, 1 );

For more information, see Trac ticket #53826.

Use global post as the default for wp_get_post_parent_id()

Starting with WordPress 5.9, the $post parameter of wp_get_post_parent_id() is now optional, defaulting to the current global post object when called within the 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..

For more information, see Trac ticket #48358.

Allow wp_register_script() to be called after wp_enqueue_script()

When a plugin registers styles/scripts on wp_enqueue_scripts (as plugin authors are encouraged to do), and conditionally enqueues their script/style on the_content 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., things “just work”. In 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. themes, the_content is run prior to 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. being processed, which results in the above scenario failing.

With WordPress 5.9, the following example will work:

wp_enqueue_script( 'example' );
wp_register_script( 'example' ); 

Before 5.9, the enqueue silently failed (no “doing it wrong” message) and the following register has no impact.

Now, scripts can therefore be enqueued and dequeued (by “handle”) before they are registered.

For more information, see Trac ticket #54529.

get_term() accepts a term ID, instance of WP_Term, or an object (i.e. stdClass as a result of a db query). Starting with WordPress 5.9, functions that use get_term() also now allow for the same data types. This adds consistency, and this change is also removing extra processing code in consuming functions, so it provides better performance.

The following functions were changed accordingly:

  • get_category_feed_link()
  • get_term_feed_link()
  • get_tag_feed_link()
  • get_edit_tag_link()
  • get_edit_term_link()
  • edit_term_link()

For each of consumer of these functions, it is now possible to pass the object instead of the term ID.

For more information, see Trac ticket #50225.

Thanks @sabernhardt for proofreading.

#5-9, #dev-notes