How we use WP-CLI to build better sites faster

January 3, 2018

At Cornershop, we’re always looking for ways we can provide better value to our clients. One reason we make such extensive use of WordPress is that we found it was a great tool for developing quality websites that took less effort than other systems out there.

But using WordPress is just the start. Like an automotive manufacturer cranking out hybrids, we’re always looking for ways to boost efficiency. This means crafting affordable, custom WordPress sites while still being able to accommodate the huge variety of needs and requirements our clients’ projects have: custom post types, faceted search, form integrations, and so on. There’s often a lot of custom work, which can be costly to implement.

Here’s what we did

To solve this problem of “How do we build good stuff fast,” we’ve developed our own custom workflow for piecing together custom code with more reusable components. It’s basically a dynamic scaffolding system that allows us to customize and “inject” pre-written code into a custom theme, leveraging WordPress’s awesome Command Line Interface (known as WP-CLI).

We decided to base our tool on WP-CLI because it already has widespread adoption in the WordPress developer community, makes documentation easy, and it supports a lot of the sort of stuff we needed, such as mustache templates. If you didn’t know, WP-CLI actually already offers scaffolding for a few common WordPress needs, such as defining a post type or a taxonomy: see documentation on the scaffold command for details.

We’ve taken that basic idea of scaffolding within WP-CLI to the next level.

We built a plugin for internal use, which we call Produce, that extends WP-CLI with a new command and subcommands that generate code and put it where we need it, specifically, into our custom starter theme, Crate.

Basically, it works like this:

  1. Make sure the starter theme, Crate, is present
  2. Install and activate the Produce plugin
  3. Run WP-CLI commands to copy files from the plugin to theme
  4. When done, uninstall the Produce plugin

As of now, our Produce plugin supports about a half-dozen commands, with more constantly in the works.

Here’s one example

wp loginscreen images/logo.png --bg=#333333

This command would customize the WordPress login screen, replacing the WordPress logo with the file themes/crate/images/logo.png and settting the page background color to a dark grey. Before running this command, the login screen typically looks something like this:

Running the command via WP-CLI could go something like this:

At the end, you’d wind up with a screen like so:

We can use Produce commands for a variety of things.

Here are some other sample commands

wp produce site-options

This command generates a bunch of commonly-used ACF Pro fields for a site, such as a default featured image for posts, URLs for social media networks, and so forth.

wp produce term-fields --taxonomies=category,issue

This command generates a set of ACF Pro fields that are available to terms in whatever taxonomies are specified. The fields include featured image, WYSIWYG introduction, and term icon.

wp produce articles --slug=news

This command takes the idea of `wp scaffold post-type` and turbocharges it, creating a new post type called “articles” along with a related taxonomy, Article Type, as well as including some custom fields for external URL, original author, and the like — something a lot of our clients need.

Check it out

While we developed Produce specifically for in-house use, as it really only works with our own custom starter theme, I have published an older copy of the codebase so you can check out how it’s built.

Thankfully, WP-CLI makes creating new commands really easy. The basic structure of a command in our plugin is like this:

class Articles_Command extends CShop_Produce {

  public function __invoke( $args, $assoc_args ) {
    // do things…
  }

}

WP_CLI::add_command(
  'produce articles',
  'Articles_Command'
);

The key part of that code is the magic `__invoke` function, which is what actually gets called when an end user runs your command. So for Produce, the internals of `__invoke` might look something like this (note that we extend a base class of CShop_Produce which defines many of the method called below):

$do_thing = self::prompt(
  'Make site awesome?',
  array( 'Yes', 'No', 'Maybe' ),
  'Yes'
);

if ( 'Yes' === $do_thing ) $this->enqueue( 'demo.sass' );

$data = array( 'bg' => $user_defined color, 'img_src' => $path_to_file );

$this->enqueue(
  'demo.mustache',
  '/templates/demo.php',
  $data
);

self::next_steps( "@include 'demo'", 'core.sass' );
WP_CLI::success( 'Demo files successfully loaded.' );

Where a lot of the magic really happens is with the use of mustache templates. They allow us to write code that can accept parameters, so that as our code is being copied from Produce into Crate, we can modify it to include certain values specified by the user at the time the command was run. This is the heart of the “dynamic” part of the scaffolding: Without having to write any code, we can tailor what’s going into our starter theme. Mustache templates can be used to generate any type of tile: we use them for producing JS files, PHP templates, and even ACF Pro JSON files that define fields. They’re incredibly flexible!

I don’t expect our exact approach to extending WP-CLI in this way to be right for every agency or every context, but I think the general idea of extending WP-CLI to facilitate building out custom stuff is applicable to a wide variety of development tasks. How would (or do) you extend WP-CLI to help you get your job done? Hit us up on Twitter @cornershop and let us know!

By Ben Byrne

Ben is our very own designer/developer unicorn. He’s been designing on the web professionally for over 17 years, but he’s also been a developer for almost as long, building up extensive experience with languages such as HTML, CSS, JavaScript, and PHP, and putting them to good use implementing his designs on several CMS platforms, including WordPress and Drupal. In addition to his own work, Ben oversees the design and development the rest of our team does, ensuring it’s up to our high standards. He enjoys sharing his knowledge, and has presented to groups of varying sizes on topics like the difference between print and web design, web typography, WordPress widgets, and front-end performance.