Skip to content
Merged
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
17 changes: 14 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ Quick links: [Using](#using) | [Installing](#installing) | [Contributing](#contr
## Using

~~~
wp search-replace <old> <new> [<table>...] [--dry-run] [--network] [--all-tables-with-prefix] [--all-tables] [--export[=<file>]] [--export_insert_size=<rows>] [--skip-tables=<tables>] [--skip-columns=<columns>] [--include-columns=<columns>] [--precise] [--recurse-objects] [--verbose] [--regex] [--regex-flags=<regex-flags>] [--regex-delimiter=<regex-delimiter>] [--regex-limit=<regex-limit>] [--format=<format>] [--report] [--report-changed-only] [--log[=<file>]] [--before_context=<num>] [--after_context=<num>]
wp search-replace [<old>] [<new>] [<table>...] [--old=<value>] [--new=<value>] [--dry-run] [--network] [--all-tables-with-prefix] [--all-tables] [--export[=<file>]] [--export_insert_size=<rows>] [--skip-tables=<tables>] [--skip-columns=<columns>] [--include-columns=<columns>] [--precise] [--recurse-objects] [--verbose] [--regex] [--regex-flags=<regex-flags>] [--regex-delimiter=<regex-delimiter>] [--regex-limit=<regex-limit>] [--format=<format>] [--report] [--report-changed-only] [--log[=<file>]] [--before_context=<num>] [--after_context=<num>]
~~~

Searches through all rows in a selection of tables and replaces
Expand All @@ -25,16 +25,24 @@ change primary key values.

**OPTIONS**

<old>
[<old>]
A string to search for within the database.

<new>
[<new>]
Replace instances of the first string with this new string.

[<table>...]
List of database tables to restrict the replacement to. Wildcards are
supported, e.g. `'wp_*options'` or `'wp_post*'`.

[--old=<value>]
An alternative way to specify the search string. Use this when the
search string starts with '--' (e.g., --old='--some-text').

[--new=<value>]
An alternative way to specify the replacement string. Use this when the
replacement string starts with '--' (e.g., --new='--other-text').

[--dry-run]
Run the entire search/replace operation and show report, but don't save
changes to the database.
Expand Down Expand Up @@ -139,6 +147,9 @@ change primary key values.
# Search/replace to a SQL file without transforming the database
$ wp search-replace foo bar --export=database.sql

# Search/replace string containing hyphens
$ wp search-replace --old='--old-string' --new='new-string'

# Bash script: Search/replace production to development url (multisite compatible)
#!/bin/bash
if $(wp --url=http://example.com core is-installed --network); then
Expand Down
42 changes: 42 additions & 0 deletions features/search-replace.feature
Original file line number Diff line number Diff line change
Expand Up @@ -1392,3 +1392,45 @@ Feature: Do global search/replace
"""
Success: Made 0 replacements.
"""

@require-mysql
Scenario: Search/replace strings starting with hyphens using --old and --new flags
Given a WP install
And I run `wp post create --post_title="Test Post" --post_content="This is --old-content and more text" --porcelain`
Then save STDOUT as {POST_ID}

When I run `wp search-replace --old='--old-content' --new='--new-content'`
Then STDOUT should contain:
"""
wp_posts
"""
And the return code should be 0

When I run `wp post get {POST_ID} --field=post_content`
Then STDOUT should contain:
"""
--new-content
"""
And STDOUT should not contain:
"""
--old-content
"""

@require-mysql
Scenario: Error when neither positional args nor flags provided
Given a WP install

When I try `wp search-replace`
Then STDERR should contain:
"""
Please provide both <old> and <new> arguments
"""
And STDERR should contain:
"""
--old
"""
And STDERR should contain:
"""
--new
"""
And the return code should be 1
Comment thread
swissspidy marked this conversation as resolved.
52 changes: 47 additions & 5 deletions src/Search_Replace_Command.php
Original file line number Diff line number Diff line change
Expand Up @@ -134,16 +134,24 @@ class Search_Replace_Command extends WP_CLI_Command {
*
* ## OPTIONS
*
* <old>
* [<old>]
* : A string to search for within the database.
*
* <new>
* [<new>]
* : Replace instances of the first string with this new string.
*
* [<table>...]
* : List of database tables to restrict the replacement to. Wildcards are
* supported, e.g. `'wp_*options'` or `'wp_post*'`.
*
* [--old=<value>]
* : An alternative way to specify the search string. Use this when the
* search string starts with '--' (e.g., --old='--some-text').
*
* [--new=<value>]
* : An alternative way to specify the replacement string. Use this when the
* replacement string starts with '--' (e.g., --new='--other-text').
*
* [--dry-run]
* : Run the entire search/replace operation and show report, but don't save
* changes to the database.
Expand Down Expand Up @@ -248,6 +256,9 @@ class Search_Replace_Command extends WP_CLI_Command {
* # Search/replace to a SQL file without transforming the database
* $ wp search-replace foo bar --export=database.sql
*
* # Search/replace string containing hyphens
* $ wp search-replace --old='--old-string' --new='new-string'
*
* # Bash script: Search/replace production to development url (multisite compatible)
* #!/bin/bash
* if $(wp --url=http://example.com core is-installed --network); then
Expand All @@ -257,12 +268,43 @@ class Search_Replace_Command extends WP_CLI_Command {
* fi
*
* @param array<string> $args Positional arguments.
* @param array{'dry-run'?: bool, 'network'?: bool, 'all-tables-with-prefix'?: bool, 'all-tables'?: bool, 'export'?: string, 'export_insert_size'?: string, 'skip-tables'?: string, 'skip-columns'?: string, 'include-columns'?: string, 'precise'?: bool, 'recurse-objects'?: bool, 'verbose'?: bool, 'regex'?: bool, 'regex-flags'?: string, 'regex-delimiter'?: string, 'regex-limit'?: string, 'format': string, 'report'?: bool, 'report-changed-only'?: bool, 'log'?: string, 'before_context'?: string, 'after_context'?: string} $assoc_args Associative arguments.
* @param array{'old'?: string, 'new'?: string, 'dry-run'?: bool, 'network'?: bool, 'all-tables-with-prefix'?: bool, 'all-tables'?: bool, 'export'?: string, 'export_insert_size'?: string, 'skip-tables'?: string, 'skip-columns'?: string, 'include-columns'?: string, 'precise'?: bool, 'recurse-objects'?: bool, 'verbose'?: bool, 'regex'?: bool, 'regex-flags'?: string, 'regex-delimiter'?: string, 'regex-limit'?: string, 'format': string, 'report'?: bool, 'report-changed-only'?: bool, 'log'?: string, 'before_context'?: string, 'after_context'?: string} $assoc_args Associative arguments.
*/
public function __invoke( $args, $assoc_args ) {
global $wpdb;
$old = array_shift( $args );
$new = array_shift( $args );

// Support --old and --new flags as an alternative to positional arguments.
// This allows users to search/replace strings that start with '--'.
$old = Utils\get_flag_value( $assoc_args, 'old' );
$new = Utils\get_flag_value( $assoc_args, 'new' );

// Fall back to positional arguments if flags not provided.
if ( null === $old ) {
$old = array_shift( $args );
}
if ( null === $new ) {
$new = array_shift( $args );
}
Comment thread
swissspidy marked this conversation as resolved.

// Validate that both old and new values are provided.
if ( null === $old || null === $new ) {
$missing = array();
if ( null === $old ) {
$missing[] = '<old>';
}
if ( null === $new ) {
$missing[] = '<new>';
}
$error_msg = count( $missing ) === 2
? 'Please provide both <old> and <new> arguments.'
: sprintf( 'Please provide the %s argument.', $missing[0] );

$error_msg .= "\n\nNote: If your search or replacement string starts with '--', use the flag syntax instead:"
. "\n wp search-replace --old='--text' --new='replacement'";

WP_CLI::error( $error_msg );
}
Comment thread
swissspidy marked this conversation as resolved.
Outdated

$total = 0;
$report = array();
$this->dry_run = Utils\get_flag_value( $assoc_args, 'dry-run', false );
Expand Down