From 38a08902736c56cf35e08f9200eb3c43e03a005e Mon Sep 17 00:00:00 2001 From: Blair Cooper Date: Fri, 2 Feb 2024 21:59:06 -0800 Subject: [PATCH 1/5] Fixes #459 Support arrays/JSON in pluck and patch Add support to for serialized arrays and JSON to both plick and patch. Add additional examples and a note about the stdin blocking issue with patch. --- src/Option_Command.php | 56 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 56 insertions(+) diff --git a/src/Option_Command.php b/src/Option_Command.php index c7fc585e..df774510 100644 --- a/src/Option_Command.php +++ b/src/Option_Command.php @@ -577,6 +577,28 @@ public function delete( $args ) { * - json * - yaml * --- + * + * ## EXAMPLES + * + * # Get the value of the 'field_key' in the option with name 'option_name' + * $ wp option pluck option_name field_key + * field_value + * + * # Get the value of the 'last_updated' field in a JSON value in the option with name 'app_updates' + * Option value: a:1:{s:4:"u558";a:1:{s:8:"required";b:0;}} + * $ wp option pluck fs_gdpr u558 + * array ( + * 'required' => false, + * ) + * + * # Get the value of the 'last_updated' field in a JSON value in the option with name 'app_updates' + * Option value: a:1:{s:4:"u558";a:1:{s:8:"required";b:1;}} + * $ wp option pluck fs_gdpr u558 required + * 1 + * + * # Get the value of the 'last_updated' field in a JSON value in the option with name 'app_updates' + * Option value: {"last_updated":1706931333,"next_update":2706931333} + * $ wp option pluck app_updates last_update */ public function pluck( $args, $assoc_args ) { list( $key ) = $args; @@ -597,6 +619,14 @@ function ( $key ) { array_slice( $args, 1 ) ); + if (function_exists('maybe_unserialize')) { + $value = maybe_unserialize($value); + } + + if (Utils\is_json($value)) { + $value = json_decode($value); + } + $traverser = new RecursiveDataStructureTraverser( $value ); try { @@ -662,9 +692,27 @@ function ( $key ) { * $ wp option patch update option_name foo * Error: Please provide value to update. * + * # Update the value of the key 'required' in the 'u558' element to 1 for the option with name 'fs_gdpr'. + * Option value before: a:1:{s:4:"u558";a:1:{s:8:"required";b:0;}} + * Option value after: a:1:{s:4:"u558";a:1:{s:8:"required";b:1;}} + * $ wp option patch update fs_gdpr u558 required 1 + * Success: Updated 'option_name' option. + * * # Delete the nested key 'bar' under 'foo' key on an option with name 'option_name'. * $ wp option patch delete option_name foo bar * Success: Updated 'option_name' option. + * + * ## NOTES + * # Blocking on STDIN + * This command attempts to read the value to use for patching from + * stdin before using a value from the command line. If no value is + * available then it will use the last value on the command line. On + * some consoles this will cause the command to block on stdin + * awaiting input. If this encountered, piping an empty string to the + * command can be used to work around the problem. + * E.g.; echo '' | wp option patch update an_option the_key the_value + * + * Ref: https://github.com/wp-cli/entity-command/issues/164 */ public function patch( $args, $assoc_args ) { list( $action, $key ) = $args; @@ -705,6 +753,14 @@ function ( $key ) { $old_value = clone $current_value; } + if (function_exists('maybe_unserialize')) { + $current_value = maybe_unserialize($current_value); + } + + if (Utils\is_json($current_value)) { + $current_value = json_decode($current_value); + } + $traverser = new RecursiveDataStructureTraverser( $current_value ); try { From a1a033965ad1b1595eef180678eda6e7e9a2a837 Mon Sep 17 00:00:00 2001 From: Blair Cooper Date: Sat, 3 Feb 2024 12:20:54 -0800 Subject: [PATCH 2/5] Fixes #459 Maybe serialize returned value in Pluck A serialized version of an array as a response is likely more useful than a var_dump quivilent. --- src/Option_Command.php | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/src/Option_Command.php b/src/Option_Command.php index df774510..302b3a17 100644 --- a/src/Option_Command.php +++ b/src/Option_Command.php @@ -619,12 +619,12 @@ function ( $key ) { array_slice( $args, 1 ) ); - if (function_exists('maybe_unserialize')) { - $value = maybe_unserialize($value); + if (function_exists( 'maybe_unserialize' )) { + $value = maybe_unserialize( $value ); } - if (Utils\is_json($value)) { - $value = json_decode($value); + if (Utils\is_json( $value )) { + $value = json_decode( $value ); } $traverser = new RecursiveDataStructureTraverser( $value ); @@ -635,6 +635,12 @@ function ( $key ) { die( 1 ); } + if (function_exists( 'is_serialized' ) && + function_exists( 'maybe_serialize' ) && + !is_serialized( $value ) ) { + $value = maybe_serialize( $value ); + } + WP_CLI::print_value( $value, $assoc_args ); } From 260dcc539356f4a00fd25b778be7643eb67fc270 Mon Sep 17 00:00:00 2001 From: Blair Cooper Date: Sat, 3 Feb 2024 16:11:02 -0800 Subject: [PATCH 3/5] Fix PHPCS issues --- src/Option_Command.php | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/src/Option_Command.php b/src/Option_Command.php index 302b3a17..dd9cf65e 100644 --- a/src/Option_Command.php +++ b/src/Option_Command.php @@ -619,12 +619,12 @@ function ( $key ) { array_slice( $args, 1 ) ); - if (function_exists( 'maybe_unserialize' )) { - $value = maybe_unserialize( $value ); + if ( function_exists( 'maybe_unserialize' ) ) { + $value = maybe_unserialize( $value ); } - if (Utils\is_json( $value )) { - $value = json_decode( $value ); + if ( Utils\is_json( $value ) ) { + $value = json_decode( $value ); } $traverser = new RecursiveDataStructureTraverser( $value ); @@ -635,10 +635,10 @@ function ( $key ) { die( 1 ); } - if (function_exists( 'is_serialized' ) && - function_exists( 'maybe_serialize' ) && - !is_serialized( $value ) ) { - $value = maybe_serialize( $value ); + if ( function_exists( 'is_serialized' ) && + function_exists( 'maybe_serialize' ) && + ! is_serialized( $value ) ) { + $value = maybe_serialize( $value ); } WP_CLI::print_value( $value, $assoc_args ); @@ -759,12 +759,12 @@ function ( $key ) { $old_value = clone $current_value; } - if (function_exists('maybe_unserialize')) { - $current_value = maybe_unserialize($current_value); + if ( function_exists( 'maybe_unserialize' ) ) { + $current_value = maybe_unserialize( $current_value ); } - if (Utils\is_json($current_value)) { - $current_value = json_decode($current_value); + if ( Utils\is_json( $current_value ) ) { + $current_value = json_decode( $current_value ); } $traverser = new RecursiveDataStructureTraverser( $current_value ); From 1474ab9d900dd58dade013c307da86f3d0ec41ec Mon Sep 17 00:00:00 2001 From: Blair Cooper Date: Sun, 4 Feb 2024 08:56:41 -0800 Subject: [PATCH 4/5] Add feature tests --- features/option-pluck-patch.feature | 199 ++++++++++++++++++++++++++++ src/Option_Command.php | 4 + 2 files changed, 203 insertions(+) diff --git a/features/option-pluck-patch.feature b/features/option-pluck-patch.feature index 0e796fd7..42c4d532 100644 --- a/features/option-pluck-patch.feature +++ b/features/option-pluck-patch.feature @@ -82,6 +82,83 @@ Feature: Option commands have pluck and patch. foo """ + @pluck @pluck-array + Scenario: A value can be retrieved from an array by key. + Given a WP install + And I run `wp option update option_name 'a:1:{s:3:"key";s:5:"value";}'` + + When I run `wp option pluck option_name key` + Then STDOUT should be: + """ + value + """ + + @pluck @pluck-array + Scenario: A value can be retrieved from an array by index. + Given a WP install + And I run `wp option update option_name 'a:1:{i:0;s:5:"value";}'` + + When I run `wp option pluck option_name 0` + Then STDOUT should be: + """ + value + """ + + @pluck @pluck-array + Scenario: A value can be retrieved from an array within an array. + Given a WP install + And I run `wp option update option_name 'a:1:{s:3:"key";a:1:{i:0;s:10:"innerValue";}}'` + + When I run `wp option pluck option_name key 0` + Then STDOUT should be: + """ + innerValue + """ + + @pluck @pluck-array + Scenario: An array retrieved from an array by key. + Given a WP install + And I run `wp option update option_name 'a:1:{s:3:"key";a:1:{i:0;s:10:"innerValue";}}'` + + When I run `wp option pluck option_name key` + Then STDOUT should be: + """ + a:1:{i:0;s:10:"innerValue";} + """ + + @pluck @pluck-json + Scenario: A value can be retrieved from a Json object. + Given a WP install + And I run `wp option update option_name 's:15:"{"key":"value"}";'` + + When I run `wp option pluck option_name key` + Then STDOUT should be: + """ + value + """ + + @pluck @pluck-json + Scenario: A value can be retrieved from a Json object within an object. + Given a WP install + And I run `wp option update option_name 's:38:"{"outerKey":{"innerKey":"innerValue"}}";'` + + When I run `wp option pluck option_name outerKey innerKey` + Then STDOUT should be: + """ + innerValue + """ + + @pluck @pluck-json + Scenario: A Json object can be retrieved from within a Json object. + Given a WP install + And I run `wp option update option_name 's:38:"{"outerKey":{"innerKey":"innerValue"}}";'` + + When I run `wp option pluck option_name outerKey` + Then STDOUT should be: + """ + {"innerKey":"innerValue"} + """ + @patch @patch-update @patch-arg Scenario: Nested values can be changed. Given a WP install @@ -300,6 +377,128 @@ Feature: Option commands have pluck and patch. 1 """ + @patch @pluck @patch-array + Scenario: An array value can be updated + Given a WP install + And a setup.php file: + """ + 'origValue']; + $ret = update_option( 'wp_cli_test', $option ); + """ + And I run `wp eval-file setup.php` + + When I run `wp option pluck wp_cli_test key` + Then STDOUT should be: + """ + origValue + """ + + When I run `wp option patch update wp_cli_test key newValue` + Then STDOUT should be: + """ + Success: Updated 'wp_cli_test' option. + """ + + When I run `wp option pluck wp_cli_test key` + Then STDOUT should be: + """ + newValue + """ + + @patch @pluck @patch-array + Scenario: An array value can be updated within an array + Given a WP install + And a setup.php file: + """ + ['innerKey' => 'origValue']]; + $ret = update_option( 'wp_cli_test', $option ); + """ + And I run `wp eval-file setup.php` + + When I run `wp option pluck wp_cli_test outerKey innerKey` + Then STDOUT should be: + """ + origValue + """ + + When I run `wp option patch update wp_cli_test outerKey innerKey newValue` + Then STDOUT should be: + """ + Success: Updated 'wp_cli_test' option. + """ + + When I run `wp option pluck wp_cli_test outerKey innerKey` + Then STDOUT should be: + """ + newValue + """ + + @patch @pluck @patch-json + Scenario: A Json object can be updated + Given a WP install + And a setup.php file: + """ + key = 'origValue'; + $json = json_encode( $obj ); + $ret = update_option( 'wp_cli_test', $json ); + """ + And I run `wp eval-file setup.php` + + When I run `wp option pluck wp_cli_test key` + Then STDOUT should be: + """ + origValue + """ + + When I run `wp option patch update wp_cli_test key newValue` + Then STDOUT should be: + """ + Success: Updated 'wp_cli_test' option. + """ + + When I run `wp option pluck wp_cli_test key` + Then STDOUT should be: + """ + newValue + """ + + @patch @pluck @patch-json + Scenario: A value in a Json object can be updated within a json object + Given a WP install + And a setup.php file: + """ + innerKey = 'origValue'; + $outer = new \stdClass(); + $outer->outerKey = $inner; + $json = json_encode( $outer ); + $ret = update_option( 'wp_cli_test', $json ); + """ + And I run `wp eval-file setup.php` + + When I run `wp option pluck wp_cli_test outerKey innerKey` + Then STDOUT should be: + """ + origValue + """ + + When I run `wp option patch update wp_cli_test outerKey innerKey newValue` + Then STDOUT should be: + """ + Success: Updated 'wp_cli_test' option. + """ + + When I run `wp option pluck wp_cli_test outerKey innerKey` + Then STDOUT should be: + """ + newValue + """ + @patch Scenario: When we don't pass all necessary argumants. Given a WP install diff --git a/src/Option_Command.php b/src/Option_Command.php index dd9cf65e..27c60767 100644 --- a/src/Option_Command.php +++ b/src/Option_Command.php @@ -635,6 +635,10 @@ function ( $key ) { die( 1 ); } + if ( $value instanceof \stdClass ) { + $value = json_encode( $value ); + } + if ( function_exists( 'is_serialized' ) && function_exists( 'maybe_serialize' ) && ! is_serialized( $value ) ) { From d7aeeab72d8fb216055122b6e0c360ead885691a Mon Sep 17 00:00:00 2001 From: Blair Cooper Date: Sun, 4 Feb 2024 08:59:13 -0800 Subject: [PATCH 5/5] Fix PHPCS issue --- src/Option_Command.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Option_Command.php b/src/Option_Command.php index 27c60767..a23f2690 100644 --- a/src/Option_Command.php +++ b/src/Option_Command.php @@ -636,7 +636,7 @@ function ( $key ) { } if ( $value instanceof \stdClass ) { - $value = json_encode( $value ); + $value = json_encode( $value ); } if ( function_exists( 'is_serialized' ) &&