New PHP Polyfills in 4.9.6

It is considered good practice to validate variables before using them. As using type declarations is still very rare in the WordPress world, parameters passed in to functions may not be of the variable type expected. Similarly, the type of variable returned by a filter may have changed due to incorrect usage of the filter by plugins or themes.

One particular situation which causes bugs often is counting something which isn’t countable. Proper variable validation can prevent those bugs.

In PHP 7.2, a warning was introduced when count() is used on an uncountable value. PHP 7.3 will introduce the  function is_countable(), which will help prevent this warning by checking that the passed variable is actually countable (the RFC has passed the vote and the function has already been implemented and merged into PHP Core).

Using count() to detect if a value is iterable (able to be passed to a foreach() loop, for example), is also a common practice. However, this will also result in warnings when upgrading to PHP 7.2. In PHP 7.1, the is_iterable() function was introduced to help prevent these warnings.

To help WordPress Core, plugins, and themes be forwards compatible, a polyfill for each of these functions has been added in 4.9.6. When a site is not running a version of PHP that includes these functions, WordPress will automatically load these polyfills.

Checking A Value Is Countable

is_countable() was introduced in #43583.

Old Way

if ( count( $var ) > 0 ) {
        // Do something.
}

New Way

if ( is_countable( $var ) && count( $var ) > 0 ) {
        // Do something.
}

Checking A Value Is Iterable

is_iterable() was introduced in #43619.

Old Way

if ( count( $var ) > 0 ) {
        foreach( $var as $key => $value) {
                // Do something.
        }
}

New Way

if ( is_iterable( $var ) ) {
        foreach( $var as $key => $value) {
                // Do something.
        }
}

Updating Core

New tickets should be opened on Trac for instances in Core that would benefit from these new functions on a case by case basis. Since all instances of count() and foreach() should be verified, a meta ticket has been opened to keep track of which files have been checked (#44123).

Want to learn how to write better conditions?

To better understand how variables behave in various PHP versions, how to write better conditions, and to improve variable validation, you may like the PHP Cheat Sheets website.

#4-9-6, #dev-notes

JSHint removed from CodeMirror in 4.9.3

CodeMirror was introduced to WordPress 4.9 for an improved code editing experience. For JavaScript linting, CodeMirror uses JSHint which unfortunately includes some code that isn't compatible with the GPL. Therefore, in WordPress 4.9.3, we are removing JSHint and replacing it with esprima and a custom wrapper to provide some basic linting for JavaScript. This allows the code editor to show compilation errors, but not errors in formatting. 

If your code relies upon JSHint from core, you should update that code to include a copy of JSHint.  Please note that as JSHint isn't currently GPL compatible, it can not be distributed in the WordPress Plugin Repository. 

For more info, please see #42850.

#4-9, #4-9-3, #codemirror, #dev-notes, #jshint

Auto-formatting of author bios reverted in 4.9.2

In WordPress 4.9.2 auto-formatting of author bios via get_the_author_description was removed after being introduced in WordPress 4.9.

Introducing auto-formatting broke a number of themes. Unfortunately, reverting it in 4.9.2 potentially breaks themes that had implemented a fix for this

For background, formatting was introduced in #40040 and reverted in #42578.

Maintaining auto-formatting

Theme authors wishing to maintain auto-formatting of author bios can add the following code to their theme's functions.php file.

add_filter( 'get_the_author_description', 'wptexturize' );
add_filter( 'get_the_author_description', 'convert_chars' );
add_filter( 'get_the_author_description', 'wpautop' );
add_filter( 'get_the_author_description', 'shortcode_unautop' );

#4-9, #4-9-2, #dev-notes

Nav Menu Improvements in the Customizer in 4.9

In our usability tests with prior releases, we identified two common problems users encountered when trying to create a menu.

  1. Clicking the Add a Menu button in an attempt to add a page to their new menu.
  2. Forgetting to assign the menu to a location.

In WordPress 4.9, we’ve updated the Customizer’s menu creation flow to address these issues.

An Updated Menus Panel

The Menus panel layout and copy have been updated for clarity. The panel now shows menus first and locations second. This puts menus front and center and allows the panel to adjust more easily to specific scenarios. For example, when there are no menus, the panel asks users to create a menu and explains the steps to be taken.

Before After

Menu Creation

When the user clicks Create New Menu, the Customizer opens a dedicated menu creation section. Using a dedicated section allows us to guide the user through each step of menu creation. We start by inviting the user to provide a clear name for the menu and to select its new location. Once the menu is created, we guide them to add menu items and highlight the Add Items button if the user doesn’t find it after a short time.

Create a Menu for a Location

The locations section now allows the user to create a menu for a location that has not been assigned a menu. When the user clicks a location’s Create New Menu link, the Customizer opens the Menu Creation section with the location preselected.

Deprecated UI Classes

With the addition of a dedicated menu creation section, a number of classes are no longer used and are being deprecated.

The following PHP classes have been deprecated along with their files:

  • WP_Customize_New_Menu_Control in
    wp-includes/customize/class-wp-customize-new-menu-control.php
  • WP_Customize_New_Menu_Section in
    wp-includes/customize/class-wp-customize-new-menu-section.php

The following JS class has been deprecated (but not its containing file):

  • api.Menus.NewMenuControl in
    wp-admin/js/customize-nav-menus.js

Related Tickets

  • #40104 Customizer: Improve menu creation flow
  • #36279 Add an “add new menu” button to the menu locations section in the customizer
  • #42114 Customize Menus: UX Improvements
  • #42116 Customize Menus: Add “It doesn’t look like your site has any menus yet” view
  • #42357 NewMenuControl class has been removed from trunk

#4-9, #customizer, #dev-notes

New Features and Enhancements with Customizer Changesets in 4.9

In WordPress 4.7 the concept of changesets was introduced in the Customizer (#30937). To understand the new Customizer improvements in 4.9, you must first go back and review what was proposed and implemented a year ago:

Customize Changesets Technical Design Decisions

Changesets are a way to persistently store changes made via the Customizer framework. Changesets contain the pending changes for any number of settings, and a setting can model any object in WordPress—whether options, theme mods, nav menu items, widgets, or even posts/pages and their postmeta. Changesets are identified by UUID (which is the post_name for the customize_changeset post type that stores the data as JSON in post_content). When a request is made to WordPress with the customize_changeset_uuid request param—whether to the frontend or to the REST API—the Customizer framework will bootstrap and all of the values from the changeset will be read and applied to the response via WordPress filters added by the settings’ respective WP_Customize_Setting::preview() methods.

Only an authorized user can write changes into a changeset for a given setting (according to its respective capability). But once it has been written then anyone can preview the site with the changes in the changeset applied: all that is needed is the UUID. Since previewing a changeset is now a readonly operation (whereas before 4.7 it was always a POST request), a changeset can be previewed on a site by authenticated and unauthenticated users alike. With the changeset UUID supplied when opening the Customizer, a user can keep iterating on a set of changes over several days or longer and only publish them once stakeholders are satisfied. Now, freelancers and agencies will be better able to communicate and collaborate on site changes with clients.

Once a customize_changeset post transitions to the publish status then all of the values in the changeset will be passed into their respective WP_Customize_Setting::update() methods to publish (“go live”) on the site: in version control terminology, the staged values from the changeset get committed and pushed. All of the changes go live together in a batch save operation (originally changesets were termed “transactions”).

As noted in the 4.7 merge proposal:

For the initial core merge, no UI changes are being proposed. The feature will only be exposed as the new query parameter on the URL. Adding a UI to this feature will happen in a future release.

The future [release] is now. Where the infrastructure of changesets was merged from the Customize Changesets feature plugin in 4.7, the key UI features from the plugin are now being merged in 4.9 after a significant number of design iterations.

This dev note contains sections on the following:

Continue reading

#4-9, #customize, #dev-notes

Press This in 4.9

In WordPress 4.9, Press This has found a new home as a “canonical” plugin.

Proposed in #41689 and committed in r41584, Press This and the supporting functions are no longer in Core at all. This is notably different than the Link Manager deprecation, which left all of the code in Core but deactivated behind a filter. If you are extending the WP_Press_This class, you will need to update your plugin or theme as it is no longer present in Core.

When someone visits wp-admin/press-this.php, they are given a prompt to install the new plugin or to notify their administrator to install it:

If installing it through the prompt above, the activation flow will return them to Press This:

If you are extending Press This or are depending on functionality from it, you can see how to check for plugin availability via 4.9’s wp-admin/press-this.php and please comment on #37938 discussing if some of the parsing functionality of Press This would be beneficial ported back into Core.

In the new plugin, older bookmarklets will no longer function and this feature is discontinued. Usage of bookmarklets across the web has decreased significantly and bad actors attempting to trick users to preform unsavory actions increased over the years. Coupled with advancing toward a new editing in experience in Core, we decided it was a suitable time to make these changes in one swift move.

Continued development of Press This will happen at https://github.com/WordPress/press-this/ and I hope those who like the streamline editing experience will continue to contribute. Short-term goals include switching to the REST API instead of admin-ajax and tweaking the current experience.

#4-9, #dev-notes

Improvements to the Customize JS API in 4.9

There are many user-facing Customizer improvements in 4.9, including: drafting/scheduling of changesets, autosave revisions, changeset post locking, frontend public previews, a new experience for browsing and installing themes, updated nav menu creation UX, and the code editing improvements for the Custom HTML widget and Additional CSS. But in addition to all of these, there are also many improvements for developers which will make extending the Customizer much more pleasant.

Something important to remember about the Customizer is that it is a single page application that is powered by JavaScript. Many developers may only interact with the PHP API for registering controls, settings, sections, panels, and partials. But controls, sections, and panels do not need to be registered in PHP at all. The PHP API for registration is essentially a wrapper for the underlying JS API. When you load the Customizer all of the params for the PHP-registered constructs are exported to the client for the JavaScript API to instantiate and initially add to the UI, but this JS API can dynamically instantiate additional constructs at any time thereafter in a Customizer session. This is how new widgets, nav menus, and nav menu items are added without requiring the entire Customizer to reload. You can also avoid statically registering settings and partials in PHP by instead adding filters to dynamically recognize settings and partials, allowing them to be registered on demand. All of this allows the Customizer application to scale out to be able to customize and preview an unlimited number of things on a site (e.g. any post or page with their postmeta in the Customize Posts feature plugin). The point here is that in order for the Customizer to scale, the JavaScript API must be used directly. So this is why the Customizer JS API improvements in 4.9 are important as they fix many longstanding annoyances and shortcomings with the JS API.

This dev note contains the following sections:

Continue reading

#4-9, #customize, #dev-notes

Changed behaviour of esc_sql() in WordPress 4.8.3

As part of the WordPress 4.8.3 release, there is a change in `esc_sql()` behaviour that may affect plugin developers who expect `esc_sql()` to return a string that’s usable outside of the context of building a query to send to WPDB.

While we strongly recommend you do not use `esc_sql()` for other purposes, we understand that it can be tricky to rewrite old code rapidly. To return to the old behaviour, you can use the `$wpdb->remove_placeholder_escape()` method, like so:

echo esc_sql( "100%" );
// "100{9fa52f39262a451892931117b9ab11b5a06d3a15faee833cc75edb18b4411d11}"

echo $wpdb->remove_placeholder_escape( esc_sql( "100%" ) );
// "100%"

#4-8, #4-8-3, #dev-notes, #wpdb

MediaElement upgrades in WordPress 4.9

MediaElement has been upgraded to 4.2.6 (see #39686), which includes many bug fixes as well as:

  • Removal of all dependencies to jQuery in code to make it more portable
  • Updated UI, using flexbox
  • Improved accessibility for player controls
  • Dropped support for older browsers (supports IE11+, Chrome, FF, Safari, Android 4+ and iOS 8+), keep in mind that ME.js applies to the front end and not just WP Admin
  • Upgraded YouTube and Vimeo renderers to use new APIs (for Vimeo, it uses now https://player.vimeo.com/api/player.js, since Froogaloop is deprecated)
  • Added support for iOS 10 and Mac OS on websites using HTTPS

With this upgrade, a couple of things must be considered:

  1. In order to create themes compatible with it, it is required to add the classPrefix: mejs- in the player configuration, since latest version of MEJS switched to BEM naming convention, so make sure it is set correctly.
  2. player.options.mode has been removed completely.
  3. Although jQuery was removed from the core package, a MediaElement migration file has been included to provide full backward compatibility between themes and development of new features.

A full list of changes in MediaElement.js is available in the project’s GitHub repository.

Props to @rafa8626 for helping write this Dev Note.

#4-9, #dev-notes, #jquery, #mediaelement

Improvements in REST API request parameter regular expressions

With WordPress 4.9, a bug has been fixed which would cause unexpected numeric results to be included in the parsed URL parameters for a REST API request. Prior to this change, calling WP_REST_Request::get_params() for a request like /wp/v2/users/(?P<id>[\d]+) with an ID of 10 would return array( 'id' => 10, 1 => '10' ), where the latter numeric key is unnecessary and a result of PCRE matching against a named subpattern (see preg_match() documentation). The fix ensures that the above request now only returns array( 'id' => 10 ) instead. This helps for example to verify that a request does not include more than a few specific parameters.

The WP REST API docs have always been using named URL parameters, using regular (numeric) matches was never recommended. With this bug fix in place, using named parameters is now effectively required, for example /my-namespace/my-endpoint/(?P<numeric_param>[\d]+) must be used instead of /my-namespace/my-endpoint/(\d+). For background discussion on these changes, see #40704.

#4-9, #dev-notes, #rest-api