Good first Gutenberg issues

Want to submit your first pull request to Gutenberg? Here are a few good first issues to get your feet wet:

Read through the contributing guide for details on how to get started. Feel free to ask questions on the specific issue, or join us in the #core-editor channel with any questions you might have.

Analysis of distributed host testing failures

Since August, several WordPress hosts have been running the WordPress PHPUnit test suite on their infrastructure. Read this post for more background.

In total, six failures have been observed:

  1. r42421 – REST API: Return the proper status code for failed permission callbacks in WP_REST_Server->dispatch()
  2. r42037 – Customize: Support instantiation of partials with flat/unwrapped params for parity with controls, sections, and panels in [41726]
  3. r41764 – Widgets: Fix jshint error in media widget
  4. r41717 – Multisite: Replace calls to refresh_blog_details() with clean_blog_cache()
    • 1 of 1 hosts reported failures.
    • Travis CI reported a success. Root cause of host failure is unknown.
  5. r41614 – Users: There is not, in fact, 12345 users on every WordPress installation
  6. r41574 – I18N: Merge two similar “Cannot set parent term” error strings

Interesting! But also not very interesting because there's not much to see.

Landing Gutenberg in WordPress 5.0

Some incomplete ideas I've been noodling on that I want to make public.

Ultimately, the goal is: the vast majority of WordPress users are excited and should be able to use Gutenberg on day one. Fundamentally, this breaks down into two objectives:

  1. Make the end-user experience is so good that WordPress users actively want to switch to it. We need to continue user testing as we have been, and iterate based on real user feedback. We also need to market Gutenberg — communicate what users should expect and get them appropriately excited.
  2. Mitigate WordPress plugin and theme incompatibilities, to minimize conflicts that would cause WordPress to fall back to the classic editor. Success is defined by the majority of WordPress users being able to use Gutenberg on day one. If too many can't use Gutenberg because of conflicts, then we've failed at launch.

I've been brainstorming some strategies for the latter, which really is two parts: identification and mitigation.

First, we need to identify the true extent of the problem: what plugins and themes are incompatible with Gutenberg, and in what ways are each incompatible? Some automated ways we can produce this data includes:

  • Manual/automated analysis of action and filters usage, etc.
  • Activate each in an isolated environment and take before/after screenshots of the editor screen.

But, I'm thinking good ol' fashioned crowd-sourcing might be most effective. What if WordPress users had an easy way to report whether a given plugin or theme was compatible with Gutenberg? We could collect this data in aggregate to get a good sense of what types of incompatibilities we should expect, and where we should focus our efforts.

Once we've identified the plugin and theme conflicts, we'll need to mitigate them. Doing so will require excellent documentation, so authors more easily understand the changes they'll need to make, and deputizing other developers to help with the outreach process.

Seeking hard problems

It's that time of year again (where my schedule empties out), so I find myself in search of a really hard problem to work on. Some problems that have piqued my interest:

  • Affordable housing. Did you know that affordable housing is defined as paying 30% of income or less on housing? And did you know that Washington County, where Tualatin is located, has a gap of ~14,500 houses and growing? I didn't either until about five months ago. Even if you can still afford your housing, this is a problem the entire socio-economic spectrum should be working on.
  • Government technology. The USDS is really cool and having an amazing impact. You should listen to Jennifer Pahlka's SALT talk, "Fixing Government: Bottom Up and Outside In". I wish there was a similar initiative in Oregon. Is there one?
  • Landing Gutenberg in WordPress 5.0. Gutenberg is a revolutionary editing interface. So revolutionary, in fact, that it's one of the worst-rated plugins in the directory. Getting from where we are now to happily shipped in core is going to be a challenging, multi-faceted initiative.

Let me know if you have any input on these problems, or whether there are others I should be considering!

WordPress needs automated browser/integration/end-to-end testing

One thing I love most about WP-CLI is its Behat-based test suite. In fact, if you consider WP-CLI successful at all, I'd attribute said success to the test suite.

Having a great test suite ensures exceptional build quality because:

  • It’s easy to write new tests, which means they actually get written.
  • The tests interface with a command in the same manner as users interface with a command, and they describe how the command is expected to work in human-readable terms.

WordPress should have amazing integration tests too.

Historically, PhantomJS has been the de-facto standard for headless browser testing. PhantomJS is also Yet Another Abandoned Open Source project, and generally a pain to deal with. But we're in luck! Headless Chrome shipped in Chrome 59. It's pretty amazing. For your next side project, try out the Puppeteer library.

Now that we're over the headless browser hurdle, implementing automated browser testing is simply a matter of:

  1. Picking a framework. Behat is one option (see WordHat for an example), and Codeception is another. I like Behat, but Codeception is based on PHPUnit which might be a perk.
  2. Setting up a Docker container to provide a WordPress install in an isolated environment. For ease of use, Chrome headless could be provided in another container.
  3. Writing some tests. Prior to writing tests though, it would be helpful to plan out all major UX flows we want to cover with tests.

In fact, I'd argue that integration tests will be key for managing breakage when Gutenberg lands in WordPress core.

What would be really neat is if the test suite supported importing some base "state", such that it'd be possible to easily run the same test against dozens of scenarios. This would let us perform an experiment where run the test suite against every plugin in the plugin directory.

Next-generation managed WordPress hosting

What if there was a managed WordPress company that got rid of its servers altogether, and focused on helping you achieve the best possible results from any infrastructure on the market?

Here’s how it might work:

  1. When you sign up for an account, you connect your Google Analytics account, so the service has intelligence about your current traffic patterns.
  2. Based on expected resource utilization, the service suggests a server configuration on AWS, Digital Ocean, or Google Cloud Platform. Once you select your preference, the service provisions a WordPress-optimized hosting stack on the provider.
  3. As a part of the offering, the service provides a best-in-class object-cache drop-in, CDN-based full-page cache, Elasticsearch integration, etc.
  4. Over time, as the service passively monitors the performance of your WordPress instance, it offers suggestions for additional application-level optimizations (think New Relic but with a higher-level understanding of WordPress).
  5. Over time, the service also passively monitors your resource spend. If it detects there’s a more price-performant option on the market, the service makes it possible to migrate your site to new infrastructure seamlessly. As an example, a client of mine was spending $1k+ per month on Amazon’s CloudFront CDN. Now they’re spending $20/month on CloudFlare.

The target market is every customer subject to “Contact us for a quote” pricing (typically $2k/month and up). The service would enable a non-technical company to run their website in the price-performant public cloud without needing to internalize the DevOps cost.

Some existing options include ServerPilot and Laravel Forge, but neither focus deeply on WordPress.


One simple trick to clean up your WordPress database

Most WordPress sites likely run Akismet, which comes bundled with every new copy. What they probably don’t know is that, over time, Akismet will cause your wp_commentmeta table to balloon in size.

Use wp db size --tables to see the size of all tables:

$ wp db size --tables
| Name                  | Size   |
| wp_users              | 9 KB   |
| wp_usermeta           | 66 KB  |
| wp_posts              | 274 MB |
| wp_comments           | 48 MB  |
| wp_links              | 3 KB   |
| wp_options            | 41 MB  |
| wp_postmeta           | 25 MB  |
| wp_terms              | 796 KB |
| wp_term_taxonomy      | 621 KB |
| wp_term_relationships | 905 KB |
| wp_termmeta           | 48 KB  |
| wp_commentmeta        | 687 MB |

Whoa! wp_commentmeta is way larger than I’d expect it to be. What’s going on there?

Let’s take a look at what keys are used:

$ wp db query "SELECT DISTINCT meta_key FROM wp_commentmeta"
| meta_key              |
| akismet_result        |
| akismet_history       |
| ERRating              |
| akismet_user_result   |
| akismet_user          |
| akismet_rechecking    |
| akismet_as_submitted  |
| akismet_pro_tip       |
| _wp_trash_meta_status |
| is_customer_note      |
| rating                |

Hm. Can’t quite tell what might be a large one from that set. Let’s look at a random comment:

$ wp comment meta list 659968
| comment_id | meta_key             | meta_value                                                                              |
| 659968     | akismet_result       | true                                                                                    |
| 659968     | akismet_history      | {"time":1503414726.1497,"event":"check-spam"}                                           |
| 659968     | akismet_as_submitted | {"comment_author":"coach handbag tassels embroidery","comment_author_email":"[email protected] |
|            |                      |","comment_author_url":"http:\/\/\/accordion-zip-wallet-in- |
|            |                      | signature-embossed-leather-p-37.html","comment_content":"Hi, i think that i saw you vis |
|            |                      | ited my site thus i came to return the favor?I'm attempting to find things to enhance m |
|            |                      | y website!I suppose its ok to use some of your ideas!!","comment_type":"","user_ip":"58 |
|            |                      | .19.83.5","user_agent":"Mozilla\/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; Mozill |
|            |                      | a\/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1) ; .NET CLR 1.0.3705)","blog":"http:\ |
|            |                      | /\/","blog_lang":"en_US","blog_charset":"UTF-8","permalink":"http:\/\/exa |
|            |                      |\/one-two-three"}                                           |

What on Lord’s earth? Why is Akismet storing a copy of every comment in comment meta? I wonder how large that is in total:

$ wp db query "SELECT sum(char_length(meta_value)) FROM wp_commentmeta WHERE meta_key='akismet_as_submitted'"
| sum(char_length(meta_value)) |
|                    567045828 |

Ah, I see. Akismet’s akismet_as_submitted entry is 567 MB of the 1 GB total database size. That makes sense.

PS I tried to list the total comments but then I ran into a WP-CLI bug. Que será, será.

10 advanced WP-CLI tricks

These examples are adapted from my “WP-CLI: Advanced Usage” VIP Workshop presentation last week. I will now only ever use GIFs in slides.

wp-cli update --nightly

Live life on the bleeding edge by running latest and greatest version of WP-CLI.

The master branch is typically stable enough to use in local and staging environments. Or production too, yolo.

wp scaffold theme-tests

You probably knew you could scaffold plugin tests, but you probably didn’t know that you could also scaffold theme tests.

wp scaffold theme-tests gives you everything you need to write PHPUnit tests that leverage the WordPress test suite. Specifically:

  • bin/ is a setup script to download the WordPress test suite and create the test database.
  • .travis.yml is a configuration file to automatically run your tests every time you push to GitHub (Travis account required).
  • tests/ contains the PHPUnit-specific files. You can modify test-sample.php to your liking.

Functionally, theme tests are pretty much the same as plugin tests. Check out the generated tests/bootstrap.php file for the secret of how your theme gets loaded into the test suite.

wp role reset

If you’ve been monkeying about with core’s default roles, wp role reset will set them back to the basics.

Reset a single role, or reset them all with --all.

wp rewrite list --match=<uri>

Rewrite rules are WordPress’ API for routing URI patterns to WP_Query instances.

For historical reasons, rewrite rules are stored in an option, which means you need to “flush” (regenerate) rewrite rules any time you register a new one.

The --match=<uri> argument makes it possible to see which rewrite rules match the URI you’ve provided, making it simple to debug why your rewrite rule doesn’t seem to be working. Because rewrite rules never work the first time.

wp shell

Ever wish you could literally write and run PHP code against WordPress?

Well, now you can. Actually, you’ve been able to for years.

wp site empty

If you want to delete all content in your WordPress install, but keep users, options, etc., wp site empty is your new best friend.

wp cron event run

After the Rewrite API, WP Cron is the WordPress developer’s second most bane of their existence. It’s opaque, buggy, and unreliable.

But, we have to use it, so we may as well make it easier to work with.


There are some commands I still can never remember the arguments for.

--prompt works with any WP-CLI command, even those you write yourself, and interactively walks you through all of the arguments you need to complete.


WP-CLI supports global- and project-based configuration files to accelerate your workflow.

For instance, if you use the same command with the same arguments over and over again, you can define those arguments as the default arguments for the command.

“Ugh, I always have to enter the same username and password when installing WordPress”… no you don’t!


You must be a WP-CLI master.

Here are four challenges for you to complete (with WP-CLI) in two minutes or less. For the solution, click on the link to see the GIF: