WP CLI: --skip-plugins

A few notes on skipping plugins with wp-cli.

Suppose you want to skip all except one, DONTSKIP:

wp user list --skip-plugins=$(wp plugin list --field=name | grep -v ^DONTSKIP$ | tr  '\n' ',')

If this will be repeated, you’d benefit from saving the ‘skip-list’ to a text file instead of running the nested command each time. This also allows you to update the skip-list relatively easily, if you don’t mind tighly squeezed comma-separated lists.

wp plugin list --field=name | grep -v ^DONTSKIP$ | tr  '\n' ',' > skipplugins.txt
wp user list --skip-plugins=`cat skipplugins.txt`

If it’s a permanent skip-list, save the keystrokes and processes by putting it in a config file (different options depending on how global you want that change: http://wp-cli.org/config/)

 #~/.wp-cli/config.yml
skip-plugins:
 - skip-me
 - skip-me-too

isset() Assumptions

register_setting() can be really handy, but take note! The first time your option gets saved, it’ll pass through the santize callback twice. With most input, it won’t matter; and if you’re explicit, it won’t matter either. But under the right conditions, it will.

Suppose your register_setting() looks like this:

register_setting( $option_group, 'checkbox', 'sanitize' );

And you have a pair of checkboxes like this:

<input type="checkbox" name="checkbox[one]" value="1" />
<input type="checkbox" name="checkbox[two]" value="1" />

And finally, your sanitize callback looks like this

function sanitize( $input ) {
	$input['one'] = isset( $input[ 'one' ] ) ? true : false;
	$input['two'] = isset( $input[ 'two' ] ) ? true : false;
	return $input;
}

See the problem?

On the very first save, both $input['one'] and $input['two'] will be true, no matter what. Say checkbox one is unchecked, when it fist passes through, $input['one'] is set to false – as expected. But when the input is passed through sanitize the second time, $input['one'] is set (to false) and thus the $input['one'] is changed to true.

demo

So the moral of the story is: be more explicit, don’t make assumptions.

Fun with WP-CLI

A random collection of things you perhaps didn’t know you could do with WP-CLI.

Maybe you’ve imported an image before, but did you know you can import a whole directory just as easily? For example, if the directory is named ‘images’:

wp media import images/*

Sometimes you need to run a command based on a result set from another command. In many cases, you can do that by nesting the one in the other. For example, if you want to change the password for all users with the ‘author’ role.

wp user update $(wp user list --role=author --field=ID) --user_pass=password

Or go crazy and regenerate media for the featured image of all sticky posts.

wp media regenerate $(wp eval 'foreach( wp_parse_id_list( get_option("sticky_posts") ) as $id ) { echo get_post_thumbnail_id($id). " "; }')

Trying to run a command for each site in a multisite doesn’t have to be a chore. A little bash script can speed things along.

#!/bin/bash

for url in $(wp site list --field=url)
do
	wp theme activate twentyfourteen --url=$url
done

Save that to a file, and run with bash: bash filename

You can do that in a one-liner as well, but that can make it harder to see what you’re doing, especially with more comprehensive commands.

for url in $(wp site list --field=url); do wp theme activate twentyfourteen --url=$url; done

Function: wp_list_pluck()

Suppose you want to get some information about some posts in this format: an array of post titles, keyed by the post ID. How would you do it? Spoiler alert: Skip the first 2 options

Let’s assume you’re fetching some posts via get_posts(). For simplicity I won’t be passing an arguments to that function, but go ahead if you want to ๐Ÿ™‚

$posts = get_posts();

Option 1

$post_titles = array();

foreach( $posts as $p ) {
	$post_titles[ $p->ID] = $p->post_title;
}

Not bad, but surely there’s a WordPress-y way to do that.

Option 2

You might have come across the function wp_list_pluck() which is really neat for pulling a particular value by key from an array of arrays or objects.

$post_titles = wp_list_pluck( $posts, 'post_title' );

This works for getting the titles, but leaves us without the IDs as keys. You might extrapolate that to this

$post_titles = array_combine( wp_list_pluck( $posts, 'ID' ), wp_list_pluck( $posts, 'post_title' ) );

Now we have what we want, but that seems clunky.

Option 3 (the best!)

Since WordPress 4.0, wp_list_pluck() takes a third argument that makes it behave more like the native PHP function (since 5.5) array_column(). This third argument allows you to specify a key whose value should be used as the key of the returned array.

$post_titles = wp_list_pluck( $posts, 'post_title', 'ID' );

Dog Bite

I’d gone for a walk as I often do. And I passed a dog I often pass.

In the past, the dog has barked but has usually been chained up in the yard. Even when the dog was loose, it never seemed threatening, it would run up, smell me out, and leave. This time, the dog was on the chain, but either it was longer than usual or was loose at the other end. There is no sidewalk where I was, just a narrow shoulder, a little ditch, then the yard – but the dog was able to jump the ditch (even I could) and get my leg.

I didn’t really feel the bite, and the dog didn’t attack, just nipped and went back to its owners. Maybe a couple dozen steps later my leg felt wet. Eww.

From there, I called my mom to come pick me up, then did a casual “maybe I should go to the ER…?” She agreed. It was a peculiarly busy Thursday evening. Checked in around 9pm. A deputy met me in the waiting area, took a report. I was terrible at describing the dog (medium sized… yellow… not a lab or pit…), and couldn’t describe the house either – but the deputy is pretty sure he knows the dog. I guess there’s some history.

I got to triage at maybe 10:30. Around 11pm I got into a room, and waited.

https://twitter.com/trepmal/status/492570983086051328

At some point, a nurse came in to give me a tetanus shot. I waited at least another 2.5 hours (ish) before I finally saw a doctor. Apparently there was only one on shift. Then at 2:20

https://twitter.com/trepmal/status/492600306983632897

In the end, they gave me 2 stitches and prescribed some antibiotics. No painkillers, but it surprisingly doesn’t really hurt.

Pictures here, password is cujo: https://trepmal.com/2014/07/25/dog-bite-pictures/

How to Become A Better Developer

I was on a panel at WordCamp Seattleย this last weekend on becoming a better developer. One point I repeated a few times was “read core” and a related point of “don’t rely on tutorials.”

These ideas have been circling in my head since then, so I wanted to write them down.

Are Tutorials a Problem?

Tutorials can be great for providing context for code, but they often leave the reader without the tools to work out of that context. They may come away with working code, and even be able to reuse it over and over, but often without knowing what it is they’re doing. This happened to me.

It seems to me that a lot of tutorials fall into one of three categories:

  1. Installers: This is probably what irks me most. There will be a headline that looks like “How to foo bar” and the first step is “Download the Foo Bar plugin” and proceed to explain how to set up a plugin. These tutorials may be perfectly fine for helping a user solve a problem, but the title is very misleading.
  2. Copy-Pasta: These often just describe a problem and offer a snippet as a solution but with little-to-no explanation.
  3. Over-Simplified: These are tricky. The tutorial is often really trying to teach and does so understandably by simplifying the code to the bare-bones. But they are incomplete because they skip the ‘shoulds’ (like sanitization, and security) because they’re not ‘have tos’ so that users will end up with code that technically works but with no idea that there should be more.

I’m not sure there’s hope for the Installers. Those authors should just be more careful about picking titles. Or I should be better about detecting linkbait.

As for the other two, I won’t pretend I’ve never done those. I’m also not suggesting that they have no use, but I think there’s room for improvement.

Copy-Pasta is a great way to end up with conflicting function names, a bloated functions.php file, and/or unintended side-effects.

To me, the over-simplified ones are the most dangerous because the user doesn’t know what they’re missing. It’s like teaching someone to build a car, but never getting around to the seatbelts and windshield – they’ll get in and drive on the highway and be fine till they’re not.

Go To the Source (Code)

If you want to learn how a function really works, you’ll have to look at the source. Tutorials can provide examples of how to use a function or hook, but you’re often on your own to learn how/if you can repurpose or reuse it in a different context.

I’ve faced this personally more than once, and wrote about it.

WordPress core is neither magic nor mystery (though it can feel like it at times!). It’s full of awesome gems that you may never learn about unless you dig in.

Where do you start? Try the Code Reference and look up functions that you see in tutorials. Personally, I spend a lot of time in my xref or just straight up opening core files in my text editor.

Follow up: Personal Project Sprint

I got off to a strong start, but I can’t deny I lost steam. I may do this again in a few months, but I’ll make a few amendments.

  • Need to have a better record of what I want to have accomplished by the end of the month.
  • Need to stash new ideas out of sight so I don’t get distracted.
  • Need to have a more convenient method of tracking what gets accomplished.

Overall though, I got my taxes done with more than a week to spare, got a few blog posts published, spent some time learning some new things. So not a loss ๐Ÿ™‚
Continue reading Follow up: Personal Project Sprint