I’m trying to write a bash script to automate the syncing of a live site to a dev site. I have the basics figured out, like exporting the production db and importing / updating urls in the dev site, but I need help updating an option whose data is saved as an array.

Specifically, I want to change Woocommerce’s Stripe setting using wp-cli.

I can see the option using wp-cli:

$ wp option get woocommerce_stripe_settings
array (
  'enabled' => 'yes',
  'title' => 'Credit Card (Stripe)',
  'description' => 'Pay with your credit card via Stripe.',
  'testmode' => 'no',
  'test_secret_key' => 'sk_test_xxxxxxxxxxxxxxxxxx',
  'test_publishable_key' => 'pk_test_xxxxxxxxxxxxxxxxxx',
  'secret_key' => 'sk_live_xxxxxxxxxxxxxxxxxx',
  'publishable_key' => 'pk_live_xxxxxxxxxxxxxxxxxx',
  'capture' => 'yes',
  'stripe_checkout' => 'no',
  'allow_remember_me' => 'yes',
  'stripe_checkout_locale' => 'en',
  'stripe_bitcoin' => 'no',
  'stripe_checkout_image' => '',
  'saved_cards' => 'yes',
  'logging' => 'no',
  'apple_pay_domain_set' => 'yes',
  'statement_descriptor' => 'Statement From',
  'request_payment_api' => 'no',
  'apple_pay' => 'yes',
  'apple_pay_button' => 'black',
  'apple_pay_button_lang' => 'en',
)

I tried to use the serialized value that got from querying the DB directly, updating the s:2:"no" to s:3:"yes" but that didn’t seem to save the value correctly:

wp option update woocommerce_stripe_settings 'a:22:{s:7:"enabled";s:3:"yes";s:5:"title";s:20:"Credit Card (Stripe)";s:11:"description";s:37:"Pay with your credit card via Stripe.";s:8:"testmode";s:3:"yes";s:15:"test_secret_key";s:32:"sk_test_xxxxxxxxxxxxxxxxxxxxxxxx";s:20:"test_publishable_key";s:32:"pk_test_xxxxxxxxxxxxxxxxxxxxxxxx";s:10:"secret_key";s:32:"sk_live_xxxxxxxxxxxxxxxxxxxxxxxx";s:15:"publishable_key";s:32:"pk_live_xxxxxxxxxxxxxxxxxxxxxxxx";s:7:"capture";s:3:"yes";s:15:"stripe_checkout";s:2:"no";s:17:"allow_remember_me";s:3:"yes";s:22:"stripe_checkout_locale";s:2:"en";s:14:"stripe_bitcoin";s:2:"no";s:21:"stripe_checkout_image";s:0:"";s:11:"saved_cards";s:3:"yes";s:7:"logging";s:2:"no";s:20:"apple_pay_domain_set";s:3:"yes";s:20:"statement_descriptor";s:50:"                                                  ";s:19:"request_payment_api";s:2:"no";s:9:"apple_pay";s:3:"yes";s:16:"apple_pay_button";s:5:"black";s:21:"apple_pay_button_lang";s:2:"en";}'

Additionally, the only piece of information that I want to change is 'testmode' => 'no' to 'testmode' => 'yes' — so a solution of doing something like hardcoding the whole serialized array won’t work in my situation, and anyway feels really fragile to me anyway.

Is there a way to update just one value of an array using wpcli? In my mind it would look something like:

$ wp option update woocommerce_stripe_settings['testmode'] yes

1
1

Thanks to a tip from milo in the comments above, I looked at this similar question.

There is an answer provided by Laurent which basically gets the option using wp-cli, pipes it to an inline php program, makes the adjustments and then pipes it back to wp-cli. I took that idea and generalized it somewhat by creating a file sibling to my cloning script: update-array-option.sh.

#!/bin/bash

option_name=$1
option_key=$2
option_value=$3

wp option get ${option_name} --format=json | php -r "
\$option = json_decode( fgets(STDIN) );
\$option->${option_key} = \"${option_value}\";
print json_encode(\$option);
" | wp option set ${option_name} --format=json

Usage then becomes:

./update-array-option.sh <option-name> <option-key> <value>

Specifically for this question:

./update-array-option.sh woocommerce_stripe_settings testmode yes

Obviously this is quick and dirty and won’t handle all of the edge cases. It looks and feels gross to be mixing bash / php like this, and as with all things relating to strings in bash, YMMV.

Leave a Reply

Your email address will not be published. Required fields are marked *