@@ -134,16 +134,24 @@ class Search_Replace_Command extends WP_CLI_Command {
134134 *
135135 * ## OPTIONS
136136 *
137- * <old>
137+ * [ <old>]
138138 * : A string to search for within the database.
139139 *
140- * <new>
140+ * [ <new>]
141141 * : Replace instances of the first string with this new string.
142142 *
143143 * [<table>...]
144144 * : List of database tables to restrict the replacement to. Wildcards are
145145 * supported, e.g. `'wp_*options'` or `'wp_post*'`.
146146 *
147+ * [--old=<value>]
148+ * : An alternative way to specify the search string. Use this when the
149+ * search string starts with '--' (e.g., --old='--some-text').
150+ *
151+ * [--new=<value>]
152+ * : An alternative way to specify the replacement string. Use this when the
153+ * replacement string starts with '--' (e.g., --new='--other-text').
154+ *
147155 * [--dry-run]
148156 * : Run the entire search/replace operation and show report, but don't save
149157 * changes to the database.
@@ -250,6 +258,9 @@ class Search_Replace_Command extends WP_CLI_Command {
250258 * # Search/replace to a SQL file without transforming the database
251259 * $ wp search-replace foo bar --export=database.sql
252260 *
261+ * # Search/replace string containing hyphens
262+ * $ wp search-replace --old='--old-string' --new='new-string'
263+ *
253264 * # Use precise mode for complex serialized data
254265 * $ wp search-replace 'oldurl.com' 'newurl.com' --precise
255266 *
@@ -262,12 +273,47 @@ class Search_Replace_Command extends WP_CLI_Command {
262273 * fi
263274 *
264275 * @param array<string> $args Positional arguments.
265- * @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.
276+ * @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.
266277 */
267278 public function __invoke ( $ args , $ assoc_args ) {
268279 global $ wpdb ;
269- $ old = array_shift ( $ args );
270- $ new = array_shift ( $ args );
280+
281+ // Support --old and --new flags as an alternative to positional arguments.
282+ // This allows users to search/replace strings that start with '--'.
283+ $ old_flag = Utils \get_flag_value ( $ assoc_args , 'old ' );
284+ $ new_flag = Utils \get_flag_value ( $ assoc_args , 'new ' );
285+
286+ // Check if both flags and positional arguments are provided.
287+ $ both_flags_provided = null !== $ old_flag && null !== $ new_flag ;
288+ $ has_positional_args = ! empty ( $ args );
289+ if ( $ both_flags_provided && $ has_positional_args ) {
290+ WP_CLI ::error ( 'Cannot use both positional arguments and --old/--new flags. Please use one method or the other. ' );
291+ }
292+
293+ // Determine old and new values.
294+ $ old = null !== $ old_flag ? $ old_flag : array_shift ( $ args );
295+ $ new = null !== $ new_flag ? $ new_flag : array_shift ( $ args );
296+
297+ // Validate that both old and new values are provided and not empty.
298+ if ( null === $ old || null === $ new || '' === $ old ) {
299+ $ missing = array ();
300+ if ( null === $ old || '' === $ old ) {
301+ $ missing [] = '<old> ' ;
302+ }
303+ // new value is allowed to be empty.
304+ if ( null === $ new ) {
305+ $ missing [] = '<new> ' ;
306+ }
307+ $ error_msg = count ( $ missing ) === 2
308+ ? 'Please provide both <old> and <new> arguments. '
309+ : sprintf ( 'Please provide the %s argument. ' , $ missing [0 ] );
310+
311+ $ error_msg .= "\n\nNote: If your search or replacement string starts with '--', use the flag syntax instead: "
312+ . "\n wp search-replace --old='--text' --new='replacement' " ;
313+
314+ WP_CLI ::error ( $ error_msg );
315+ }
316+
271317 $ total = 0 ;
272318 $ report = array ();
273319 $ this ->dry_run = Utils \get_flag_value ( $ assoc_args , 'dry-run ' , false );
0 commit comments