Standardization of WP-Admin colors in WordPress 5.7

This is the first part of a larger project in cleaning up WordPress adminadmin (and super admin) CSSCSS Cascading Style Sheets.. In WordPress 5.7, all colors used in the CSS is collapsed to one of 12 blues, greens, reds, and yellows, 13 grays, pure black, and pure white.

This new streamlined color palette collapses all the colors that used to be in the WordPress source code down to seven coreCore Core is the set of software required to run WordPress. The Core Development Team builds WordPress. colors and a range of 56 shades that meet the WCAG 2.0 AA recommended contrast ratio against white or black.

The colors are perceptually uniform from light to dark in each range, which means they start at white and get darker by the same amount with each step. Half the range has a 4.5 or higher contrast ratio against black, and the other half maintains the same contrast against white.

Standardizing on this set of colors will help contributors make consistent, accessible design decisions. Themes 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 are encouraged to use this new color palette, for better consistency between their products and WordPress Core.

Plugin authors that use the existing CSS Core classes should be all set up with the new color palette, as every Core class was updated accordingly.

The full color palette is also available on this CodePen, courtesy of @ryelle.

A PostCSS tool to help plugin authors to switch to the new WP-Admin color palette

@ryelle also published a PostCSS tool which can be used on any CSS file to either replace or create a second CSS file with the 5.7 colors – this is essentially the same process that ran over core, so it should make the same matches in plugin CSS.

This tool uses PostCSS and postcss-palettize-colors to automatically convert any colors in your CSS to the new color palette in WordPress admin. It uses a basic color difference algorithm to convert any color to the closest color in the palette.

To use it, follow the usage guide from PostCSS for your setup. Follow the postcss.config.js in this gist to add the postcss-palettize-colors to your process. Make sure to define the palette colors using paletteOptions.

If you’re not using PostCSS or a build process yet, you can use this tool via the following steps:

  1. Install the dependencies:
    npm i postcss postcss-cli https://github.com/ryelle/postcss-palettize-colors.git
  2. Configure PostCSS – download the postcss.config.js in this gist. This includes the full color palette for wp-admin.
  3. Run PostCSS via command line:
    npx postcss style.css --replace
  4. Swap out style.css for the path to your CSS file. Note, this will overwrite your CSS file with the new color values.

Alternately, if you need to match colors in both 5.7 and older WordPress: you could use this command to create a separate 5.7-specific stylesheet, and check the version of WordPress to enqueue the correct CSS for each version:

npx postcss style.css -o style-57.css

See also postcss-cli for more configuration options.

Now that the color palette has been reduced, the next step will be to switch to CSS variables for a better maintainability of WordPress Admin CSS colors.


For reference, see ticketticket Created for both bug reports and feature development on the bug tracker. #49999 and the initial proposal published on Make/Core.

Props @ryelle for proofreading.

#5-7, #dev-notes

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 5.6.20 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

Send reset password links in WordPress 5.7

WordPress 5.7 introduces a new feature that allows website administrators to manually send a reset password link to existing users. This can be helpful when users loose their password and cannot use the lost password link for any reason.

In terms of workflow, the feature does not directly change the user’s password. It sends them a password reset link via email so they are able to reset their password by themselves. Sending a reset password link is more secure than directly changing the password for the user. Passwords should not be communicated directly.

The reset password email notification is sent using the existing retrieve_password() function, which can be filtered using the retrieve_password hook. Please note that retrieve_password was also moved from wp-login.php to wp-includes/user.php.

This feature can be found in several places in the WordPress Adminadmin (and super admin).

Using the user profile screen

The feature is available on the user profile screen, right above the “Set new password” setting.

Using the action link available on the users list screen

There is also a quick action link available in the users list. It is showed when you hover/focus the user’s row.

Using bulk actions

It is also possible to bulk send password reset links by using the bulk action available in the action dropdown located right above the users list table.

Password reset link email notification

Here is the content of the email notification:

Subject: [SITENAME] Password Reset
- - -

Someone has requested a password reset for the following account:

Site Name: [SITENAME]

Username: [USERNAME]

If this was a mistake, ignore this email and nothing will happen.

To reset your password, visit the following address:

[RESET_PASSWORD_URL]

This password reset request originated from the IP address [IPADDRESS].

The email subject and message can be filtered using the retrieve_password_title and the retrieve_password_message hooksHooks In WordPress theme and development, hooks are functions that can be applied to an action or a Filter in WordPress. Actions are functions performed when a certain event occurs in WordPress. Filters allow you to modify certain functions. Arguments used to hook both filters and actions look the same..


For reference, see ticketticket Created for both bug reports and feature development on the bug tracker. #34281

Props to @chaton666 and @jdy68 for proofreading

#5-7, #dev-notes

Dev Chat Agenda for February 24th 2021

Here is the agenda for this week’s meetings to occur at the following times: February 24th, 2021 at 5:00 UTC and February 24th, 2021 at 20:00 UTC.

Announcements

Blogblog (versus network, site) Post Highlights

Developer notes

Field GuideField guide The field guide is a type of blogpost published on Make/Core during the release candidate phase of the WordPress release cycle. The field guide generally lists all the dev notes published during the beta cycle. This guide is linked in the about page of the corresponding version of WordPress, in the release post and in the HelpHub version page.

The WordPress 5.7 Field Guide is out! Read through it for a full breakdown of everything you need to know about WordPress 5.7.

Components check-in and status updates

  • Check-in with each component for status updates.
  • Poll for components that need assistance.

Open Floor

Do you have something to propose for the agenda, or a specific item relevant to our standard list above?

Please leave a comment, and say whether or not you’ll be in the chat, so the group can either give you the floor or bring up your topic for you, accordingly.

This meeting happens in the #core channel. To join the meeting, you’ll need an account on the Making WordPress Slack.

Props @desrosj for proof reading.

#5-7, #agenda, #dev-chat

Introducing script attributes related functions in WordPress 5.7

WordPress 5.7 adds a handful of new functions that enables passing attributes, such as async or nonce, to both regular and inline script 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. This creates a path forward for enabling a Content-Security-Policy (or CSP) in CoreCore Core is the set of software required to run WordPress. The Core Development Team builds WordPress., plugins, and themes.

These new functions are:

  • wp_get_script_tag() – Formats <script> loader tags and automatically injects a type attribute (if needed).
  • wp_print_script_tag() – Prints a formatted <script> loader tag.
  • wp_print_inline_script_tag() – Prints inline JavaScriptJavaScript JavaScript or JS is an object-oriented computer programming language commonly used to create interactive effects within web browsers. WordPress makes extensive use of JS for a better user experience. While PHP is executed on the server, JS executes within a user’s browser. https://www.javascript.com/. wrapped in a <script> tag.
  • wp_get_inline_script_tag() – Wraps inline JavaScript in a <script> tag.

All of these functions automatically inject the type attribute if the theme has not declared support for HTML5 script tags. Reminder: to declare HTML5 support for script tags, theme authors should use the following declaration in their functions.php file:

add_theme_supports( 'html5', 'script' );

Examples

wp_get_inline_script_tag()

wp_get_inline_script_tag(
	'document.createElement("video");',
	array(
		'id'    => 'create-video-js',
		'async' => true,
	)
);

Returns:

<script id="create-video-js" async>document.createElement("video");</script>

wp_print_inline_script_tag()

Directly prints the value returned by wp_get_inline_script_tag().

wp_get_script_tag()

Setting the attributed value to true just add the attribute without any value. For example:

wp_get_script_tag(
	array(
		'src'      => 'RELATIVE_PATH/FILE.js',
		'nomodule' => true,
	)
);

Returns:

<script src="RELATIVE_PATH/FILE.js" nomodule></script>

Attributes values are automatically escaped using esc_attr but URLs have to be manually escaped using esc_url. For example:

wp_get_script_tag(
     array(
         'id'        => 'jquery-"js"-2.3.4',
         'integrity' => 'sha384-long_hash',
         'src'       => esc_url( 'https://domain.tld/jquery-2.3.4.min.js' ),
     )
 );

Returns:

<script id="jquery-"js"-2.3.4" integrity="sha384-long_hash" src="https://domain.tld/jquery-2.3.4.min.js"></script>

wp_print_script_tag()

Directly prints the value returned by wp_get_script_tag().

Plugins/Themes should not overwrite the nonce attribute of script tags if not specifically responsible for implementing CSP integration.

Filtering script tag attributes in WP 5.7

The wp_script_attributes hook can be used to filterFilter Filters are one of the two types of Hooks https://codex.wordpress.org/Plugin_API/Hooks. They provide a way for functions to modify data of other functions. They are the counterpart to Actions. Unlike Actions, filters are meant to work in an isolated manner, and should never have side effects such as affecting global variables and output. the attributes to be added in script tags. Attributes are provided in an array containing key-value pairs representing <script> tag attributes.

Please note that only the attribute name is added to the <script> tag for entries with a boolean value, if the value is true.

Attributes are sanitized by the new wp_sanitize_script_attributes function before being printed in the script tag.

Example of use

Adds a nonce attribute to every script tag generated by either wp_get_script_tag or wp_get_inline_script_tag:

function wporg_my_wp_script_attributes( $attr ) {
	if ( ! isset( $attr['nonce'] ) ) {
		$attr['nonce'] = get_my_custom_nonce(); // Random custom function
	}
	return $attr;
);
add_filter( 'wp_script_attributes', 'wporg_my_wp_script_attributes' );

What’s next?

This creates a path forward for enabling a Content-Security-Policy (or CSP) 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 Core, plugins, and themes.

The next steps to get wp-admin to Strict CSP mode are:

  • Add nonces to all <script> elements. With strict CSP, every <script> element must have a nonce attribute which matches the value specified in the policy. Work started in ticketticket Created for both bug reports and feature development on the bug tracker. #39941.
  • Refactor inline event handlers and javascript: URIs. Inline event handlers (onclick="...", onerror="...") and <a href="javascript:..."> links can be used to run scripts, so an attacker who finds an XSS 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. could inject such HTMLHTML HyperText Markup Language. The semantic scripting language primarily used for outputting content in web browsers. and execute malicious JavaScript. CSP requires refactoring those patterns into safer alternatives. Work started in ticket #51407.
  • Refactor calls to JSJS JavaScript, a web scripting language typically executed in the browser. Often used for advanced user interfaces and behaviors. APIs incompatible with CSP – includes things like document.write() used to load additional scripts and uses of eval().
  • Serve the Content-Security-Policy 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.. This final step will be the reward at the end of the process, turning on Strict CSP.

A complete post will be published by @adamsilverstein and @enricocarraro on Make/Core to explain these next steps in details.


For reference, see ticket #39941.

Props @johnbillion, @adamsilverstein, @enricocarraro, and @desrosj for proofreading.

#5-7, #dev-notes

WordPress 5.7: A new dynamic hook to filter the content of a single block

The render_block() function is responsible for rendering each individual 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. into an HTMLHTML HyperText Markup Language. The semantic scripting language primarily used for outputting content in web browsers. string. There are several filters available that allow plugins and themes to alter how the block is rendered.

  • pre_render_block: Allows render_block() to be short-circuited, by returning a non-null value.
  • render_block_data: Filters the block being rendered in render_block(), before it’s processed.
  • render_block_context: Filters the default context provided to a rendered block.
  • render_block: Filters the content of a single block.

While these filters grant a large amount of control over how an individual block is rendered, hooked functions need to perform some verification that the block being rendered is of the desired block type before making any modifications.

In WordPress 5.7, a new dynamic 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., render_block_{$this->name}, will be introduced, allowing a function to be hooked only to blocks of a specific type. In the new filter, {$this->name} represents the name or slug of the block as it was registered. For example, the paragraph block, registered with a name of core/paragraph can be filtered using render_block_core/paragraph.

This reduces the amount of code previously needed to target the rendering of specific block types.

Usage examples

The following example will filter all core/paragraph blocks, wrapping them in a <div> element.

/**
 * Wrap all core/paragragh blocks in a <div>.
 *
 * @param string $block_content The block content about to be appended.
 * @param array  $block         The full block, including name and attributes.
 * @return string Modified block content.
 */
function wporg_paragraph_block_wrapper( $block_content, $block ) {
	$content  = '<div class="my-custom-wrapper">' . $block_content . '</div>';
	return $content;
}
add_filter( 'render_block_core/paragraph', 'wporg_paragraph_block_wrapper', 10, 2 );

Result:

<div class="my-custom-wrapper">
	<!-- block content -->
</div>

Note: The names of all WordPress CoreCore Core is the set of software required to run WordPress. The Core Development Team builds WordPress. block types are prefixed with core/. For custom block types declared in a pluginPlugin A plugin is a piece of software containing a group of functions that can be added to a WordPress website. They can extend functionality or add new features to your WordPress websites. WordPress plugins are written in the PHP programming language and integrate seamlessly with WordPress. These can be free in the WordPress.org Plugin Directory https://wordpress.org/plugins/ or can be cost-based plugin from a third-party or theme, the name of the filter may be something like render_block_my-plugin/my-custom-block.


In this example, only paragraphs using the large font size keyword will be wrapped into a <div> element:

/**
 * Wrap all core/paragraph blocks with large font size in a <div>.
 *
 * @param string $block_content The block content about to be appended.
 * @param array  $block         The full block, including name and attributes.
 * @return string Modified block content.
 */
function wporg_large_sized_paragraph_block_wrapper( $block_content, $block ) {
	if ( isset( $block['attrs']['fontSize'] ) && 'large' === $block['attrs']['fontSize'] ) {
		$block_content = '<div class="my-large-paragraph">' . $block_content . '</div>';
	}
	return $block_content;
}
add_filter( 'render_block_core/paragraph', 'wporg_large_sized_paragraph_block_wrapper', 10, 2 );

Result:

<div class="my-large-paragraph">
	<p class="has-large-font-size">
		<!-- block content -->
	</p>
</div>

For more information on this change, see ticketticket Created for both bug reports and feature development on the bug tracker. #46187 on TracTrac An open source project by Edgewall Software that serves as a bug tracker and project management tool for WordPress..

Props @chaton666 and @desrosj for proofreading.

#5-7, #dev-notes

Feature Plugin: Rollback Update Failure

This feature pluginFeature Plugin A plugin that was created with the intention of eventually being proposed for inclusion in WordPress Core. See Features as Plugins. is an offshoot of Matt’s 9 Projects for 2019. Specifically it’s a follow-up to auto-updates for plugins and themes. Our goal is to provide a safety mechanism of sorts should an update, including auto-updates, fail potentially leaving the user’s site in an unstable state.

This is a feature plugin based on the PR for #51857. We are working towards inclusion in WordPress 5.8. The general overview is to provide a mechanism whereby a failed pluginPlugin A plugin is a piece of software containing a group of functions that can be added to a WordPress website. They can extend functionality or add new features to your WordPress websites. WordPress plugins are written in the PHP programming language and integrate seamlessly with WordPress. These can be free in the WordPress.org Plugin Directory https://wordpress.org/plugins/ or can be cost-based plugin from a third-party or theme update does not leave the site in an unstable state. This part of the project is not about ensuring that a successful update does not cause any issues.

Some of the issues of failed updates include:

  • Having a plugin folder content be deleted and the plugin no longer active.
  • Having a plugin not completely update and result in a PHPPHP The web scripting language in which WordPress is primarily architected. WordPress requires PHP 5.6.20 or higher fatal message or WSOD

While these are not the only results of failed updates, they seem to consistute the majority of reported issues.

The assumption is that most of the errors in large plugins/themes occur during the copy_dir() part of WP_Upgrader::install_package(). 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. #52342 brought more error reporting to copy_dir() and Trac ticket #52831 provides 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. hook in order to process the rollback in the event of a plugin/theme update failure. As of WordPress 5.7-beta1 both of these tickets are in coreCore Core is the set of software required to run WordPress. The Core Development Team builds WordPress..

It is during the WP_Upgrader::install_package() that the currently installed plugin/theme is deleted in anticipation of copying the new update into that location. Having an empty plugin/theme folder or an incompletely copied update seems to be the most common issue.

Rollback Update Failure Feature Plugin is available for feedback and testing. Contributions from the WordPress community are welcome on the plugin’s GitHub repository.

Testing

There was much discussion regarding the thought that adding additional IO processes for the zip and unzip process could result in server timeout issues on resource starved shared hosts. Activating the feature plugin will result in the creation of a ZIP file of the installed plugin/theme being updated every time an update is performed. The unzip only occurs during testing or if a WP_Error is returned from WP_Upgrader::install_package(). Any issues would only happen during a plugin or theme update.

For the sake of testing assume any server timeout occurring during the update process might be releated to the additional IO processes creating the zipfile. Please report these in GitHub Issues and report your server details. ( Host, RAM, OS, etc. )

There will be messaging in the event of an error and successful or unsuccessful rollback.

To simulate a failure, use the filter add_filter( 'rollback_update_testing', '__return_true' );

Alternatively you can install the Rollback Update Testing plugin, activating it as needed. If you have GitHub Updater installed, you can easily install this Gist from the Install Plugin tab. Select Gist as the Remote Repository Host.

Next Steps

The Rollback Update Failure feature plugin is an early step towards inclusion in WordPress Core. We need your help. Simply installing and activating the plugin will help test whether or not the additional server IO processes may cause issue with resource starved shared hosting.

Thanks @audrasjb for reviewing.

Making WordPress Releases Easier

Update: Let’s move forward with the March release, a July release (to give folks time to adjust their company plans), and a final release in December. I will create a plan to help us lessen the burden of releases, and in December I will see what we’ve accomplished and get some 2022/23 target release months published.

The past few weeks have been very busy in terms of WordPress’ release cadence. There has been the WP 5.6.1 release, WP 5.7 betaBeta A pre-release of software that is given out to a large group of users to trial under real conditions. Beta versions have gone through alpha testing in-house and are generally fairly close in look, feel and function to the final product; however, design changes often occur as part of the process. 1, and discussions to start organizing the next major and minor releases are already underway. The roadmap for the year promised four major releases, as well as any follow-up minor releases, and flags have been raised about how we can accomplish that.

tl;dr I’ve been exploring the problem of making the release process easier with WordPress contributors for 3+ years; high level notes are shared below. From my research, the work to automate what we can (and potentially get the project ready for more releases per year) would take 3-4 dedicated developers who are proficient in our backend tools/infrastructure, at least a project manager, 1-2 internal communications people, and probably a year or more of work (if we had all the resources, and they were working at full capacity). This means that 4 major releases is not a viable plan in 2021.

What are the challenges?

  • Balancing developer needs with user needs. A rapid release cycle (CI/CD) definitely appeals to some developers. In my observation, our users see no difference between our nuanced guidelines around minors vs majors, and currently experience each type of release (~9ish on average) as “yet another thing I have to update.”
  • Balancing the OSS philosophy of releasing early and often with the reality that we ship a CMS to ~39% of the web. In my observation, our commitment to backward compatibility and relative consistency is key to our users’ continued use of WordPress, and makes “ship, then iterate” more challenging.
  • WordPress takes a responsive approach to open sourceOpen Source Open Source denotes software for which the original source code is made freely available and may be redistributed and modified. Open Source **must be** delivered via a licensing model, see GPL. product and project management, despite our scale. Contributors expect WordPress maintainers to seek out and respond to feedback on both product and process, which is time-consuming.
  • Related, every release team — major or minor — makes hard calls and unpopular decisions. This results in fatigue and increased risk of burnout in contributor roles that have a limited pool of trained and experienced candidates. The more releases, the more fatigue and burnout risk we run.
  • Currently, only a small number of active contributors can do the administrative work required during a release, and they split that responsibility across releases for the year. The onboarding process for contributors with that skill set is lengthy, and the main mechanism we use to recruit and start training them (our in-person events) is not available.
  • Automating the basic tasks involved in a major or minor releaseMinor Release A set of releases or versions having the same minor version number may be collectively referred to as .x , for example version 5.2.x to refer to versions 5.2, 5.2.1, 5.2.3, and all other versions in the 5.2 (five dot two) branch of that software. Minor Releases often make improvements to existing features and functionality. requires time from skilled developers as well as product ownership and project management. In my observation, we do not have people with those skills and extra time available to help here, given our ongoing need for increased project coordination.

What changes are needed?

  • Better testing: That would include automated testing, security testing, smoke testing, E2E tests, beta testing, etc.
  • Seasoned CoreCore Core is the set of software required to run WordPress. The Core Development Team builds WordPress. developers: Many more of them, and also more of their time focused on Core.
  • Better handoff in design/dev iterations: The WordPress project has more developer contributors than design contributors, and few people who have the time, experience, and skill required to coordinate the work at scale.
  • Shifts in our collective philosophies: A shift to a culture of review, to an ideology of continuous development (as it relates to CMSs and software that is open to a vast networknetwork (versus site, blog) of extenders), and finally a shift in the nuanced application of OSS methodologies (aimless contributions vs agenda-free contributions, non-reciprocal vs no value, coordination vs dictation, etc).

What could we change right now?

  • Mentorship: The mentorship programs that are in place across teams in the project, could stand a fresh eye to account for active and passive learning that happens during in-person events. If we gave it a little more definition, and some better tools, then we could potentially remove that barrier to entry for all future contributors.
  • Triagetriage The act of evaluating and sorting bug reports, in order to decide priority, severity, and other factors.: There was a call for this at the end of 2018, and it suffered from a bit of a false start. Triage is not only a key part of maintaining WordPress, it’s also the common denominator in the paths of success for many of the long-term contributors I’ve spoken to.
  • Feature Proposals: The feature proposal process was suspended during the first phase of 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/, but I think it’s time to revive it. The benefits of this process are that discussions can happen on the Make network, which opens up feedback to a broader audience, so that when a proposal gets to any final decision makers, the questions have all been answered (or at least asked).
  • Product/Project Processes: This is hard in open source. We know that trying to design by committee is prone to failure, but making that work have a clear owner feels like we’re walling off the future of the project. I have no solutions, but I will start a few conversations in the near future so we can collectively come to a potential way forward.

Time for your feedback!

I believe that it is essential to reduce the effort required to have a successful WordPress release, but that we should start with some planning. I’d like to hear from folks in the comments if you’re interested and available to lead efforts around any of the things listed above, or if you have anything that needs clarification in what I shared!

Editor Chat Agenda: 24 February 2021

Facilitator and notetaker @annezazu

This is the agenda for the weekly editor chat scheduled for Wednesday, 24 February 2021, 14:00 UTC. This meeting is held in the #coreCore Core is the set of software required to run WordPress. The Core Development Team builds WordPress.-editor channel in the Making WordPress SlackSlack Slack is a Collaborative Group Chat Platform https://slack.com/. The WordPress community has its own Slack Channel at https://make.wordpress.org/chat/.. All are welcome to join!

  • WordPress 5.7 RC 1 & WordPress 5.6.2
  • 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/ 10.1 RC & a reminder of the celebration post for 100 releases.
  • Monthly Plan for February 2021 and key project updates:
    • Global Styles.
    • 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.-based 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. Editor.
    • Navigation block.
    • Full Site Editing.
  • Task Coordination.
  • Open Floor.

Even if you can’t make the meeting, you’re encouraged to share anything relevant for the meeting in the comments below:

  • If you have anything to share for the Task Coordination section, please leave it as a comment on this post.
  • If you have anything to propose for the agenda or other specific items related to those listed above, please leave a comment below.

#core-editor #core-editor-agenda

Lazy-loading iframes in 5.7

In WordPress 5.7, iframes will be lazy-loaded by default, using the browser-level loading attribute. This will bring to iframes the same performance benefits which WordPress 5.5 introduced by lazy-loading images.

Similar to how it affects images, WordPress will add loading="lazy" to only those iframe tags that have both width and height attributes present, to avoid any perceived negative impact on layout shifting. The attribute is added on page output using the wp_filter_content_tags() function which was introduced in WordPress 5.5 with specifically that extensibility in mind which now allows reusing it for this new performance feature. Since the considerations of lazy-loading iframes are similar to those of lazy-loading images, please refer to the original image lazy-loading announcement post as well as this article on browser-level lazy-loading for background information on the topic.

See also #50756 for the ticketticket Created for both bug reports and feature development on the bug tracker. where this feature was worked on.

Impact on oEmbed content

By default, WordPress will add a loading="lazy" attribute to the following iframes:

  • iframes within post content (the_content)
  • iframes within post excerpts (the_excerpt)
  • iframes within text widgets (widget_text_content)

The majority of iframes used on WordPress sites typically come from its oEmbed integration, which will automatically transform a URLURL A specific web address of a website or web page on the Internet, such as a website’s URL www.wordpress.org to certain web platform resources (such as tweets or YouTube videos) into the referenced embedded media when pasted into the editor.

The markup of those iframe tags is controlled by the respective web service, and only some of those web services follow the best practice of providing width and height attribute. Since WordPress cannot guess the dimensions of the embedded resource, the loading="lazy" attribute will only be added if the oEmbed iframe 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.) comes with both dimension attributes present.

Customizing lazy-loading iframes

Developers can customize whether and how iframes are lazy-loaded in a similar way to how they can for images, with the primary 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. being the existing wp_lazy_loading_enabled, which going forward will return true for iframe tags by default.

For example, if you would like to turn off lazy-loading by default for iframes within post content, you could use the following code snippet:

function disable_post_content_iframe_lazy_loading( $default, $tag_name, $context ) {
	if ( 'iframe' === $tag_name && 'the_content' === $context ) {
		return false;
	}
	return $default;
}
add_filter(
	'wp_lazy_loading_enabled',
	'disable_post_content_iframe_lazy_loading',
	10,
	3
);

In addition, there is a new wp_iframe_tag_add_loading_attr filter which allows customization of a specific iframe tag. For example, you could use this filter to skip addition of the loading attribute on 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. that will likely appear within the initially visible viewport, to avoid impacting the Largest Contentful Paint metric. The filter has the same signature as the related wp_img_tag_add_loading_attr filter for images.

Here is an example code snippet which would disable lazy-loading iframes that embed YouTube videos within post content:

function skip_loading_lazy_youtube_iframes( $value, $iframe, $context ) {
	if ( 'the_content' === $context && false !== strpos( $iframe, 'youtube.com' ) {
		return false;
	}
	return $value;
}
add_filter(
	'wp_iframe_tag_add_loading_attr',
	'skip_loading_lazy_youtube_iframes',
	10,
	3
);

Please refer to the “Customizing lazy-loading” section of the image lazy-loading announcement post for additional guidance.

Props @audrasjb for proofreading.

#5-7, #dev-notes, #feature-lazyloading