diff --git a/features/behat-steps.feature b/features/behat-steps.feature index 1620e011..a13293d9 100644 --- a/features/behat-steps.feature +++ b/features/behat-steps.feature @@ -468,6 +468,47 @@ Feature: Test that WP-CLI Behat steps work as expected When I launch in the background `wp eval 'sleep(2); echo "done";'` # Background process should not block, continuing immediately + @require-wp + Scenario: Set several options at once + Given a WP installation + And these options: + | name | value | autoload | format | + | uploads_use_yearmonth_folders | 0 | | | + | blogdescription | Run in {RUN_DIR} | | | + | wp_cli_test_array | {"a":1,"b":["c"]} | no | json | + + When I run `wp eval 'echo get_option( "uploads_use_yearmonth_folders" ) . "|" . get_option( "blogdescription" );'` + Then STDOUT should be: + """ + 0|Run in {RUN_DIR} + """ + + When I run `wp eval 'echo json_encode( get_option( "wp_cli_test_array" ) );'` + Then STDOUT should be: + """ + {"a":1,"b":["c"]} + """ + + When I run `wp eval 'echo array_key_exists( "wp_cli_test_array", wp_load_alloptions() ) ? "autoloaded" : "not autoloaded";'` + Then STDOUT should be: + """ + not autoloaded + """ + + @require-wp + Scenario: Set several network options at once + Given a WP multisite installation + And these site options: + | name | value | + | wp_cli_test_option | first | + | registration | user | + + When I run `wp eval 'echo get_site_option( "wp_cli_test_option" ) . "|" . get_site_option( "registration" );'` + Then STDOUT should be: + """ + first|user + """ + @require-wp Scenario: Test custom wp-content directory Given a WP installation diff --git a/src/Context/GivenStepDefinitions.php b/src/Context/GivenStepDefinitions.php index 03a87493..383e518b 100644 --- a/src/Context/GivenStepDefinitions.php +++ b/src/Context/GivenStepDefinitions.php @@ -430,6 +430,67 @@ public function given_these_installed_and_active_plugins( $stream ): void { $this->proc( "wp plugin install $plugins --activate" )->run_check(); } + /** + * Sets one or more options, or network options, in a single process. + * + * Columns are `name` and `value`, plus optionally `autoload` (`yes` or `no`) and `format` (`json` to decode the value). + * + * ``` + * Scenario: My example scenario + * Given a WP installation + * And these options: + * | name | value | + * | uploads_use_yearmonth_folders | 0 | + * | blog_public | 1 | + * + * Scenario: My multisite scenario + * Given a WP multisite installation + * And these site options: + * | name | value | format | + * | illegal_names | ["www","admin","files"] | json | + * ``` + * + * @access public + * + * @Given /^these (options|site options):$/ + * + * @param string $type Either 'options' or 'site options'. + * @param TableNode $table + */ + public function given_these_options( $type, TableNode $table ): void { + $options = []; + foreach ( $table->getHash() as $row ) { + if ( ! isset( $row['name'], $row['value'] ) ) { + throw new RuntimeException( 'The options table needs "name" and "value" columns.' ); + } + + $value = $this->replace_variables( $row['value'] ); + if ( 'json' === ( $row['format'] ?? '' ) ) { + $value = json_decode( $value, true ); + if ( JSON_ERROR_NONE !== json_last_error() ) { + throw new RuntimeException( "Invalid JSON value for option '{$row['name']}'." ); + } + } + + $autoload = null; + if ( isset( $row['autoload'] ) && '' !== $row['autoload'] ) { + $autoload = in_array( strtolower( $row['autoload'] ), [ 'yes', 'on', 'true', '1' ], true ); + } + + $options[] = [ $this->replace_variables( $row['name'] ), $value, $autoload ]; + } + + $function = 'site options' === $type ? 'update_site_option( $option[0], $option[1] )' : 'update_option( $option[0], $option[1], $option[2] )'; + $file = $this->variables['RUN_DIR'] . '/' . uniqid( 'wp-cli-test-options-', true ) . '.php'; + file_put_contents( $file, 'proc( Utils\esc_cmd( 'wp eval-file %s', $file ) )->run_check(); + } finally { + unlink( $file ); + } + } + /** * Configure a custom `wp-content` directory. *