WordPress PHP now (mostly) conforms to WordPress Coding Standards

For 12 long years, the WordPress Coding Standards have stood as a beacon of hope, a promise that code written for WordPress will be easily readable, recognisable, and portable. Sadly, WordPress’ own PHP hasn’t lived up to that promise.

Until now.

Weighing in at a respectable 105,650 lines added, 77,558 lines removed, with an 11MB diff, [42343] fixes 94.8% of the coding standards issues in WordPress’ PHP.

The 5.2%

The remaining 5% of coding standards issues require manual intervention, which means that we’re going to start accepting coding standards patches in the near future. Please hold off on creating tickets and submitting patches for now, while we figure out the best way to manage it.

Existing Patches

Unfortunately, this change means that most patches currently on Trac will no longer apply cleanly – they’re going to need updating. It’s going to take a bit of experimenting to figure out the most efficient way to handle this, if you’re interested in this problem, please go ahead and experiment!

The Wider Ecosystem

In the process of preparing for this, there were a lot of bugs fixed and features implemented in WPCS, as well as upstream in the PHPCS project – this not only benefits the WordPress ecosystem, but the wider PHP ecosystem. Special props to @jrf for driving the bulk of these changes, both in WPCS and PHPCS!

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

New Committers!

Usually, new committers are announced in line with release cycles, but we were all just too excited to wait until the 4.8 cycle started, so here they are!

First up, James Nylen (@jnylen0). James has been a driving force on the REST API, both when it was a feature plugin, and more recently in Core since the endpoints were merged. The tickets and comments he leaves on Trac are always thorough and thoughtful, his patches are consistently excellent, and his attitude is exemplary.

Next, Adam Silverstein (@adamsilverstein). Adam has been a regular contributor for years, bringing significant improvements to the Media Grid, as well as handling large parts of the JavaScript work around the REST API endpoints – both in wp-api.js, and tenaciously working on porting Dashboard features across to using the endpoints.

Rounding out our guest committer list, Felix Arntz (@flixos90). Felix has been a contributor to Multisite for some time now, writing excellent patches, as well as running Office Hours and Bug Scrubs. Not only that, he’s always been willing to jump in and help in any area of Core, showing the same level of enthusiasm and consideration across the board.

Finally, we have a bumper class of guest committers to make make permanent! Pascal Birchler (@swissspidy) and Joe McGill (@joemcgill), Rachel Baker (@rachelbaker), and Mike Schroder (@mikeschroder) are now permanent committers.

Please join me in congratulating James, Adam, Felix, Pascal, Joe, Rachel, and Mike! 🎉🔥⭐️👻💯

#4-7, #commit

WP_Hook: Next Generation Actions and Filters

WordPress 4.7 introduces a significant reworking of action and filter iteration to address bugs that arose from recursive callbacks and from callbacks that changed the hooked callbacks on currently running actions/filters.

What does this mean for you, the plugin or theme developer? In almost all cases, nothing. Everything should continue to run as expected, and this should fix a number of hard-to-trace bugs when different plugins are stepping on each others callbacks.

Who is affected?

If your plugin directly accesses the $wp_filter global rather than using the public hooks API, you might run into compatibility issues.

Case 1: Directly setting callbacks in the $wp_filter array

$wp_filter['save_post'][10]['my_special_key'] = array( 'function' => 'my_callback_function', 'accepted_args' => 2 );

This will no longer work, and will cause a fatal error. $wp_filter['save_post'] is no longer a simple array. Rather, it is an object that implements the ArrayAccess interface.

You have two options to work around. The first (and preferred) method is to use the add_filter() or add_action() functions.

add_action( 'save_post', 'my_callback_function', 10, 2 );

If, for some reason, you absolutely cannot, you can still work around this.

if ( ! isset( $wp_filter['save_post'] ) ) {
    $wp_filter['save_post'] = new WP_Hook();
}
$wp_filter[ 'save_post' ]->callbacks[10]['my_special_key'] = array( 'function' => 'my_callback_function', 'accepted_args' => 2 );

Case 2: Directly unsetting callbacks in the $wp_filter array

unset( $wp_filter['save_post'][10][ $my_callback_id ] );

This will fail for the same reason as case one. To work around, you can use the standard remove_filter() / remove_action() functions.

remove_action( 'save_post', 'my_callback_function', 10, 2 );

Or, if you absolutely must access the array directly:

if ( isset( $wp_filter[ 'save_post' ] ) ) {
    unset( $wp_filter['save_post']->callbacks[10][ $my_callback_id ] );
}

Case 3: Checking if a hook is an array

if ( isset( $wp_filter['save_post'] ) && is_array( $wp_filter['save_post'] ) ) {
    // do something
}

This will always return false. $wp_filter['save_post'] is a WP_Hook object. To check if a hook has callbacks, use has_action() or has_filter().

if ( has_action( 'save_post' ) ) {
    // do something
}

Case 4: Moving the $wp_filter array pointer manually

If you’re calling next() or prev() on the $wp_filter array pointer to manually manage the order that callbacks are called in (or if you’re doing it to work around #17817), you will likely be unsuccessful. Use callback priorities, add_action() / add_filter(), and remove_action() / remove_filter() appropriately and let WordPress manage execution order.

Other Cases

Almost all other cases where you might manipulate the $wp_filter global directly should continue to function as expected. The WP_Hook object implements the ArrayAccess and IteratorAggregate interfaces so that, while it’s not recommended, you may continue to iterate over callbacks in $wp_filter or directly retrieve priorities from the callback array.

Props

While there were many contributors of the course of this ticket, all of whom are listed in the changeset, I’d like to especially thank @jbrinley, for his work in architecting this solution, researching and testing potential compatibility issues, and for authoring the bulk of this post.

What’s Next

We’re confident in how solid the code is for the majority of sites, and for the major edge cases, so now it’s time to add the code to the nightly build, so all y’all can test it against your sites and plugins.

This is being treated as an early commit of a feature project, so the final decision for whether this code will be kept in WordPress 4.7 will be made no later than beta 1, which gives us a month and a half to see how it effects usage in the wider world.

The current nightly build contains this update, for your testing enjoyment.

If you have any feedback on the code, please leave a comment on this post. Please post any bugs you find to Core Trac.

#4-7, #dev-notes, #feature-projects, #hooks, #plugins

Reactions

What are Reactions?

If you’ve used Slack or Thefacebook recently, you’ll have noticed a new way of interacting and providing feedback – emoji reactions. It works much the same way as a Like button, but provides a wider range of reactions, so readers can give more nuanced feedback, without needing to go to the effort of leaving a comment. This also allows for readers to provide the same level of interaction in situations where a “Like” is an inappropriate message to send, as Eric Meyer describes in his post about Inadvertent Algorithmic Cruelty.

What does it do?

The reactions plugin currently has the following features:

  • Allows for reactions to posts
  • REST API endpoints for storing and retrieving reactions
  • An exceedingly ugly emoji selector

What is still being worked on?

Pretty much everything!

In its current state, the plugin is mostly a proof of concept, in need of significant work improving edge cases, design and User Experience.

Your first step is to install the plugin, as well as the WP-API plugin (the WP-API plugin is currently a requirement to avoid code duplication, that will likely be re-evaluated based on when each plugin might be merged into Core).

Please report any issues on the Github repository, or drop in the #feature-reactions channel in Slack to ask questions or give feedback. It’s also where we have our weekly chats, on Wednesday 23:00 UTC. Thank you!

#feature-plugins, #reactions

🎉 One more committer for 4.4!

Please join me in welcoming a new guest committer for WordPress 4.4 — Ryan McCue (@rmccue)!

Ryan has been contributing to the WordPress world for many years, through various patches, as well as being one of the maintainers of the SimplePie RSS library that WordPress uses.

More recently, he started the WordPress REST API feature plugin, and has been leading the development of it for the past two years, nine months and five days (not that anyone is counting!). As the REST API comes closer to being ready for merge, Ryan having commit access is a natural progression: he can bring his expertise in the REST API directly across to WordPress Core.

Congratulations, Ryan! 🎆💯⭐️⭐️⭐️⭐️⭐️

#4-4, #commit

Committer Reviews of the REST API

With the proposed merge of the REST API base code into Core, I’d like to try something a little bit different. The REST API is potentially going to cause one of the biggest shifts in workflow that WordPress has seen, so it’s important that all committers know how it works, and how it affects the parts of Core that they focus on.

And so, here’s the plan. Before the REST API is merged into Core, it needs a code review from all active committers. The code being proposed for merge has been separated out into its own repo, for your viewing convenience.

There are five areas I’d like to see covered:

  • Docs: Are the inline docs up to standard? What needs to be done before they’re ready? Official tutorials will be helpful, can they be fit into Devhub?
  • Security: Is it secure?
  • Performance: Are there any obvious performance issues in the base code? Are we encouraging plugin developers to write performant custom end points?
  • Ease of Use: Is it easy to write custom endpoints? Do we encourage quality code?
  • Forwards Compatibility: This is a little more nebulous, but can you envisage scenarios where we might need to break backwards compatibility in the future?

Choose one or more of these focusses for your review, and tackle it from that perspective.

You can also have a look at the proposed endpoints in the main repo, (scheduled for a later WordPress version), for inspiration on how it may interact with the areas of WordPress Core that you work on.

Post your review as a comment here, and link to any relevant bug reports or pull requests you submit to the plugin repo.

And finally, please have a think about how this process worked for you. I’d like this to be a model for future feature plugin merges, particularly those that touch many different areas of WordPress Core.

PS: I’m not kidding about all active committers. I won’t hesitate to publicly shame you for holding up the REST API merge. 🙂

#feature-plugins, #json-api, #rest-api

OMG EMOJI 😎

One of the fun bits of the utf8mb4 upgrade is that we can now store emoji! Once your site is upgraded to utf8mb4, it can natively store any emoji character. There were a couple of problems with that, though:

  • Some browsers don’t know how to render emoji 👎, or they have bugs in their implementation 😢. Notably, Chrome either doesn’t work or has bugs, older versions of IE don’t work, and Firefox has bugs.
  • Not all sites will be able to upgrade to utf8mb4, which means they’ll be unable to save emoji characters that they enter.

Not being able to use emoji makes everyone a sad panda (😭🐼), so we need to fix this. There are a few moving parts of our emoji support, so lets go through them.

utf8 backwards compatibility

If a site can’t be upgraded to utf8mb4, we convert emoji to their HTML-encoded equivalent, and store that, instead. From a UI perspective, post editing works as expected 🎉. Because fields need to be white listed to support this, we don’t allow it everywhere – just post_title, post_content and post_excerpt. We also allow it in the site title and the site description.

Browser support

There’s a small compatibility check included on every page, both on the front end, and in the Dashboard. For those interested, this adds 1-4ms (⚡️-fast!) to the page render time – the aim was to keep this as low as possible, to avoid affecting your UX. If you notice a little chunk of compressed JS at the top your HTML, that’s probably it. If you’d like to check out how it works in a more readable format, have a look through wp-emoji-loader.js.

Email ✉️ and RSS 📯 (There’s no RSS emoji, give me a break.)

Of course, the JS shim won’t work in email and RSS. So, we replace all emoji with a static PNG version in those cases.

TinyMCE 📝

In addition to the browser support JS, there’s a TinyMCE plugin that handles keeping emoji looking good, while you type. It’s pretty magical.

Taxonomies and URL slugs

You can totally make taxonomies and URL slugs with emoji in them. Because we love you, and want you to be happy. 😀

So, that’s about it. If you have any questions about the implementation, drop them in the comments below.

💩

#4-2, #dev-notes, #%f0%9f%91%bb, #emoji

The utf8mb4 Upgrade

In WordPress 4.2, we’re upgrading tables to utf8mb4, when we can. Your site will only upgrade when the following conditions are met:

  • You’re currently using the utf8 character set.
  • Your MySQL server is version 5.5.3 or higher (including all 10.x versions of MariaDB).
  • Your MySQL client libraries are version 5.5.3 or higher. If you’re using mysqlnd, 5.0.9 or higher.

The difference between utf8 and utf8mb4 is that the former can only store 3 byte characters, while the latter can store 4 byte characters. In Unicode terms, utf8 can only store characters in the Basic Multilingual Plane, while utf8mb4 can store any Unicode character. This greatly expands the language usability of WordPress, especially in countries that use Han character sets. Unicode isn’t without its problems, but it’s the best option available.

utf8mb4 is 100% backwards compatible with utf8.

Due to index size restrictions in MySQL, this does mean we need to re-create a handful of indexes to fit within MySQL’s rules. Using a standard configuration, MySQL allows 767 bytes per index, which for utf8 means 767 bytes / 3 bytes = 255 characters. For utf8mb4, that means 767 bytes / 4 bytes = 191 characters. The indexes that will be resized are:


wp_usermeta.meta_key
wp_terms.slug
wp_terms.name
wp_commentmeta.meta_key
wp.postmeta.meta_key
wp_posts.post_name

And from Multisite:


wp_site.domain
wp_sitemeta.meta_key
wp_signups.domain

Of course, the Multisite (and wp_usermeta) keys obey the DO_NOT_UPGRADE_GLOBAL_TABLES setting. The upgrade will only be attempted once, though we’ll probably add a check in a future WordPress version to see if we can upgrade now (say, if you’ve upgraded your MySQL server since upgrading to WordPress 4.2).

If you’re a plugin developer and your plugin includes custom tables, please test that your indexes fit within MySQL’s limits. MySQL won’t always produce an error when the index is too big, so you’ll need to manually check the size of each index, instead of relying on automated testing.

EDIT: One more thing…

If you’d like to upgrade your custom tables to utf8mb4 (and your indexes are all in order), you can do it really easily with the shiny new maybe_convert_table_to_utf8mb4( $tablename ) function. It’s available in `wp-admin/includes/upgrade.php`, and will sanity check that your tables are entirely utf8 before upgrading.

#4-2, #dev-notes, #utf8mb4, #wpdb

Emoji Chat Agenda, February 25, 2015

Here’s the agenda for Wednesday’s Emoji Chat in the #core channel on Slack.

Time/Date: Immediately after the Dev Chat.

  1. Emoji Helper – On platforms that don’t have an emoji keyboard, should we provide one?
  2. Performance – When we’re falling back to Twemoji on large pages, we have to consider how it will perform. Are there faster ways of replacing the emoji characters with images?
  3. Open Floor – There’s still time to rant about the evils of emoji! Let us know how you really feel.

#agenda, #emoji, #x1f4a9