Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support arrays/JSON in pluck and patch #460

Closed
wants to merge 7 commits into from
Closed
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
199 changes: 199 additions & 0 deletions features/option-pluck-patch.feature
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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:
"""
<?php
$option = ['key' => '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:
"""
<?php
$option = ['outerKey' => ['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:
"""
<?php
$obj = new \stdClass();
$obj->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:
"""
<?php
$inner = new \stdClass();
$inner->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
Expand Down
66 changes: 66 additions & 0 deletions src/Option_Command.php
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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 {
Expand All @@ -605,6 +635,16 @@ function ( $key ) {
die( 1 );
}

if ( $value instanceof \stdClass ) {
$value = json_encode( $value );
}

if ( function_exists( 'is_serialized' ) &&
function_exists( 'maybe_serialize' ) &&
! is_serialized( $value ) ) {
$value = maybe_serialize( $value );
}

WP_CLI::print_value( $value, $assoc_args );
}

Expand Down Expand Up @@ -662,9 +702,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;
Expand Down Expand Up @@ -705,6 +763,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 {
Expand Down
Loading