WP-CLI Only WordPress

When it comes to unique use cases for WordPress, headless WordPress is all the talk. However earlier this year I stumbled upon another unique use case for WordPress. One I haven’t seen talked about before. That is a WP-CLI only WordPress.

WordPress runs just fine without being web accessible.

Under this configuration all interactions with WordPress happen through WP-CLI rather then the typical web requests. Why would this be useful? Well beyond my use case I’m not too sure 😄. I currently use this configuration of WordPress within CaptainCore CLI, part of my WordPress management toolkit.

Bash script which leverages all of WordPress via WP-CLI.

CaptainCore CLI is a bash script I wrote to manage WordPress sites. In order for it to work properly there is a bunch of site specific information it needs to track. Information like site name, site home directory, site plugin/theme details, site credentials and a whole bunch of other information. All of this site information is on the backend of my WordPress site as custom post types and custom fields. This powers the GUI part of my toolkit.

Rather to recreate my CLI from scratch I decided to mirror the existing WordPress data structure.

CaptainCore CLI spins up it’s own WordPress site and stores a local copy of the same data. This data is accessible via WP-CLI for changing or viewing. WordPress is essentially the datastore for my bash application.

All of the benefits of WordPress are included.

Here are a few examples showing the inner workings of CaptainCore CLI interacting with the local WordPress datastore.

# Store updated info in WordPress datastore

cd ${root_path}data
wp --quiet post meta update $site_id core $core
wp --quiet post meta update $site_id home_url $home_url
wp --quiet post meta update $site_id plugins "$plugins"
wp --quiet post meta update $site_id themes "$themes"
wp --quiet post meta update $site_id users << heredoc
# Manually syncing a site

cd ${root_path}data
wp db query "delete from wp_posts where ID in ($@);"
wp db query "delete from wp_postmeta where post_id in ($@);"
ssh $captaincore_master -p $captaincore_master_port "bash -s" < ${root_path}lib/remote-scripts/master-db-query $@ > sync.sql
wp db import sync.sql
# Add a site

cd ${root_path}data
wp eval-file ${root_path}lib/local-scripts/site-add.php site=$1 ${flags[@]}
# Update a site

cd ${root_path}data
wp eval-file ${root_path}lib/local-scripts/site-update.php site=$1 ${flags[@]}
# Lists sites

cd ${root_path}data
wp eval-file ${root_path}lib/local-scripts/site-list.php ${flags[@]}

Most of the command line arguments are simply passed on as arguments to a PHP script for WordPress to deal with. An example would be running the following command to retrieve a list of site with a specific version of WooCommerce.

captaincore site list --filter=plugin --filter-name=woocommerce --filter-version=3.3.0

This will be passed to WordPress by running the following WP-CLI command.

wp eval-file site-list.php filter=plugin filter-name=woocommerce filter-version=3.3.0

The file site-list.php does all of the real work. Read through site-list.php for an idea of how that works. Basically it does some fancy $arguments['meta_query'] within a get_posts( $arguments ) query.

Thoughts and potential alternatives. 

As a WordPress developer this was a quick and easy way to build out a custom CLI using WordPress. It keeps the complexities of my CLI fairly low as it closely mirrors the GUI parts of CaptainCore. That said WordPress wasn’t intended to used to make CLIs. There are far more performant and documented ways to create command line interfaces using other frameworks/languages. While WordPress was a quick and easy way to get started I’m exploring recreating the CLI using something like Golang. Golang is next on my list of languages to learn 🔨🧠.