Managing WordPress from the command line

Introduction to WP-CLI & examples in daily use

WordPress

Comand Line Interface

Have you heard of WP-CLI before?

Are you using WP-CLI?

WordPress Admin

VS

Which was quicker?

Installing WP-CLI

http://wp-cli.org/#installing

Command Structure

$ wp plugin install wordpress-seo --activate

command

subcommand

parameter

flag

Getting Help

q key to quit

Start small

Migration

Database Migration

$ wp db export
Success: Exported to 'local-2018-03-17-9d26a34.sql'.

$ wp db import local-2018-03-17-9d26a34.sql
Success: Imported from 'local-2018-03-17-9d26a34.sql'.

HTTP to HTTPS

+------------+--------------+--------------+------+
| Table      | Column       | Replacements | Type |
+------------+--------------+--------------+------+
| wp_options | option_value | 2            | PHP  |
| wp_posts   | post_content | 1            | SQL  |
| wp_posts   | guid         | 3            | SQL  |
+------------+--------------+--------------+------+
Success: 6 replacements to be made.

Test Run

$ wp search-replace http://example.com https://example.com
$ wp search-replace http://example.com https://example.com
  --skip-columns=guid --dry-run
$ wp search-replace http://example.com https://example.com
  --skip-columns=guid
+------------+--------------+--------------+------+
| Table      | Column       | Replacements | Type |
+------------+--------------+--------------+------+
| wp_options | option_value | 2            | PHP  |
| wp_posts   | post_content | 1            | SQL  |
| wp_posts   | guid         | 3            | SQL  |
+------------+--------------+--------------+------+
Success: Made 6 replacements

Live Run

$ wp rewrite flush
Success: Rewrite rules flushed.
$ wp cache flush
Success: The cache was flushed.
$ wp transient delete --all
Success: 8 transients deleted from the database.

Clear

$ wp media regenerate
Found 3 images to regenerate.
1/3 Regenerated thumbnails for "Vertical Image" (ID 123).
2/3 Regenerated thumbnails for "Horizontal Image" (ID 124).
3/3 Regenerated thumbnails for "Beautiful Picture" (ID 125).
Success: Regenerated 3 of 3 images.

Generate Image Sizes

Development

$ wp user update admin --user_pass=password

Success: Updated user 1.
$ wp db search WordPress wp_posts
wp_posts:post_content
17:Welcome to WordPress. This is your

wp_posts:post_content
36:wpmeetups "[your-subject]"
[your-name] <wordpress@>
From: [your-name] <[your-email]>

wpmeetups "[your-subject]"
wpmeetups <wordpress@>
Message Body:

Plugins

$ wp jetpack status full
Checking status for https://example.com
Success: Jetpack is currently connected
to WordPress.com
The Jetpack Version is 5.8
The WordPress.com blog_id is 328491835
The WordPress.com account for the primary
connection is info@example.com

Additional data:
version......... 5.8
wp-version...... 4.9.4
$ wp migratedb profile 8
Initiating migration...
Exporting tables   100% [==============] 0:09 / 0:09
Cleaning up...
Success: Export saved to:
/uploads/wp-migrate-db/example-migrate.sql.gz

Migrate DB Pro

$ wp migratedb import /uploads/wp-migrate-db/export.sql.gz
Initiating migration...
Importing file  100% [==============] 1:29 / 1:29
Cleaning up...
Flushing caches and rewrite rules...
Success: Migration successful.

Migrate DB Pro

Running code from the command line

$ wp eval "var_dump(wp_get_translation_updates());"
array(9) {
  [0]=>
  object(stdClass)#8262 (7) {
    ["type"]=> string(4) "core"
    ["slug"]=> string(7) "default"
    ["language"]=> string(5) "de_CH"
    ["version"]=> string(5) "4.9.4"
    ["updated"]=> string(19) "2018-02-12 10:10:36"
    ["package"]=> string(64) "https://downloads.wordpress.org/translation/core/4.9.4/de_CH.zip"
    ["autoupdate"]=> bool(true)
  }
[...]
$query = new WP_Query( [
	'post_type'              => 'any',
	'post_status'            => 'any',
	'posts_per_page'         => -1,
	'no_found_rows'          => true,
	'meta_key'               => 'ph_related_dossier',
	'lang'                   => '',
	'fields'                 => 'ids',
	'update_post_meta_cache' => true,
	'update_post_term_cache' => false,
] );
if ( ! $query->have_posts() ) {
	WP_CLI::error( 'No posts.' );
}
foreach ( $query->posts as $post_id ) {
	$dossier_id = get_post_meta( $post_id, 'ph_related_dossier', true );
	if ( ! $dossier_id || is_array( $dossier_id ) ) { // No dossier linked or already in new format.
		continue;
	}
	if ( 'ph_artist' === get_post_type( $post_id ) ) {
		$success = delete_post_meta( $post_id, 'ph_related_dossier', $dossier_id );
		if ( $success ) {
			WP_CLI::log( "Deleted Artist $post_id meta..." );
		}
		continue;
	}
	// Convert to array...
	update_post_meta( $post_id, 'ph_related_dossier', [ $dossier_id ] );
	// ...and add new meta.
	add_post_meta( $post_id, 'ph_related_dossier_' . $dossier_id, true );

	WP_CLI::log( "Processed $post_id..." );
}
wp_reset_postdata();
WP_CLI::success( 'Done.' );
$ wp eval-file ./scripts/migration-related-dossier.php
Processed 123 ...
Processed 124 ...
[...]

Multisite

$ wp plugin list

+-----------------------------------+----------------+-----------+---------+
| name                              | status         | update    | version |
+-----------------------------------+----------------+-----------+---------+
| google-analytics-for-wordpress    | active-network | available | 7.0.4   |
| gutenberg                         | active         | none      | 2.7.0   |
+-----------------------------------+----------------+-----------+---------+
$ wp plugin list --url=stage.example.com

+-----------------------------------+----------------+-----------+---------+
| name                              | status         | update    | version |
+-----------------------------------+----------------+-----------+---------+
| google-analytics-for-wordpress    | active-network | available | 7.0.4   |
| gutenberg                         | inactive       | none      | 2.7.0   |
+-----------------------------------+----------------+-----------+---------+
$ wp plugin activate gutenberg --network

Plugin 'gutenberg' network activated.
Success: Network activated 1 of 1 plugins.
$ wp plugin activate gutenberg --url=stage.example.com

Plugin 'gutenberg' activated.
Success: Activated 1 of 1 plugins.
$ wp core multisite-install
> --title="Welcome to the WordPress" \
> --admin_user="admin" --admin_password="password" \
> --admin_email="user@example.com"

Single site database tables already present.
Set up multisite database tables.
Added multisite constants to wp-config.php.
Success: Network installed. Don't forget to set
up rewrite rules.
$ wp core multisite-convert

Set up multisite database tables.
Added multisite constants to wp-config.php.
Success: Network installed. Don't forget to
set up rewrite rules

wp-cli.yml

path: web/wp
wp-cli.yml

Running command remotely

path: web/wp

@prod:
  ssh: deploy@example.com/var/www/example.com
@prod2:
  ssh: deploy@1.example.com/var/www/example.com
@prod-all:
  @prod
  @prod2

@stage:
  ssh: deploy@example.com/var/www/stage.example.com

@dev:
  ssh: vagrant/var/www/example.com
wp-cli.yml
$ wp @prod cli version
WP-CLI 1.5.0

$ wp @prod-all cli version
@prod
WP-CLI 1.5.0
@prod2
WP-CLI 1.5.0

Multisite

path: web/wp

_envs:
  - &test_data
    ssh: deploy@example.com/var/www/stage.example.com
    path: web/wp

@stage:
  url: https://stage.example.com/
  <<: *test_data
wp-cli.yml

Doing multiple tasks

https://make.wordpress.org/cli/handbook/shell-friends/

Scenario:

Reorganising the categories. Delete term A and add the posts to term B.

$ wp post list --category_name=a --format=ids |
  xargs -0 -d ' ' -I % wp post term add % category b
Success: Added term.
Success: Added term.
Success: Added term.
[...]
$ wp post delete $(wp post list
  --post_type='page' --format=ids)
Success: Trashed post 32.
Success: Trashed post 28.
Success: Trashed post 4.
Success: Trashed post 2.
$ wp post list --format=ids --post_type=
  $(wp post-type list --capability_type=post
   --field=name | tr "\n" ",")

6486 6484 6482 6480 6478 6476 6474 6472 6470 6468 6466 

Packages

$ wp package install git@github.com:trepmal/wp-revisions-cli.git
Installing package trepmal/wp-revisions-cli (dev-master)
Updating ~/.wp-cli/packages/composer.json to require the package...
Registering git@github.com:trepmal/wp-revisions-cli.git as
a VCS repository...
Using Composer to install the package...
---
Loading composer repositories with package information
Updating dependencies
Resolving dependencies through SAT
Dependency resolution completed in 0.185 seconds
Analyzed 5540 packages to resolve dependencies
Analyzed 333592 rules to resolve dependencies
Package operations: 1 install, 2 updates, 0 removals
Installs: trepmal/wp-revisions-cli:dev-master fa49116
Updates: gettext/gettext:dev-master 9ba1532, wp-cli/i18n-command:dev-master 90f3f8e
 - Installing trepmal/wp-revisions-cli (dev-master fa49116)
Writing lock file
Generating autoload files
---
Success: Package installed.

https://make.wordpress.org/cli/handbook/common-issues/

Gutenberg

$ wp scaffold block movie --title="Movie block" --plugin=movies
Success: Created block 'Movie block'.
0 8 * * 7 ~/bin/wp cli update --yes --quiet  > /dev/null

Updating WP-CLI

Resources