Skip to content

Commit c5e06bd

Browse files
committed
various fixes
1 parent 05041ab commit c5e06bd

3 files changed

Lines changed: 69 additions & 4 deletions

File tree

features/search-replace-callback.feature

Lines changed: 59 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,11 @@ Feature: Test search-replace --callback option
66
And a callback-function.php file:
77
"""
88
<?php
9-
function test_callback( $data, $replacement ) {
9+
function test_callback( $data, $replacement, $search_regex ) {
10+
// Assert that search_regex is null when not using --regex
11+
if ( $search_regex !== null ) {
12+
throw new Exception( 'Expected $search_regex to be null without --regex, got: ' . var_export( $search_regex, true ) );
13+
}
1014
return str_replace( 'foo', strtoupper( $replacement ), $data );
1115
}
1216
"""
@@ -42,6 +46,17 @@ Feature: Test search-replace --callback option
4246
"""
4347
<?php
4448
function regex_callback( $data, $replacement, $search_regex ) {
49+
// Assert that search_regex is provided when using --regex
50+
if ( $search_regex === null ) {
51+
throw new Exception( 'Expected $search_regex to be set with --regex, got null' );
52+
}
53+
if ( !is_string( $search_regex ) ) {
54+
throw new Exception( 'Expected $search_regex to be a string, got: ' . gettype( $search_regex ) );
55+
}
56+
// Verify it's a valid regex pattern
57+
if ( @preg_match( $search_regex, '' ) === false ) {
58+
throw new Exception( '$search_regex is not a valid regex pattern: ' . $search_regex );
59+
}
4560
// Replace matched digits with their square
4661
return preg_replace_callback( $search_regex, function( $matches ) {
4762
$num = (int)$matches[1];
@@ -127,3 +142,46 @@ Feature: Test search-replace --callback option
127142
"""
128143
bar content
129144
"""
145+
146+
@require-mysql
147+
Scenario: Callback function receives opts parameter with table and column context
148+
Given a WP install
149+
And a callback-opts.php file:
150+
"""
151+
<?php
152+
function opts_callback( $data, $replacement, $search_regex, $opts ) {
153+
// Only verify opts when we have a match for content columns
154+
if ( strpos( $data, 'foo' ) !== false && isset( $opts['col'] ) && $opts['col'] === 'post_content' ) {
155+
// Verify opts parameter exists and has expected structure
156+
if ( !is_array( $opts ) ) {
157+
throw new Exception( 'Expected $opts to be an array, got: ' . gettype( $opts ) );
158+
}
159+
if ( !isset( $opts['table'] ) ) {
160+
throw new Exception( 'Expected $opts["table"] to be set' );
161+
}
162+
// Verify we're processing wp_posts table
163+
if ( strpos( $opts['table'], 'posts' ) === false ) {
164+
throw new Exception( 'Expected table to contain "posts", got: ' . $opts['table'] );
165+
}
166+
return str_replace( 'foo', $replacement, $data );
167+
} elseif ( strpos( $data, 'foo' ) !== false ) {
168+
// For other columns, just do the replacement without assertions
169+
return str_replace( 'foo', $replacement, $data );
170+
}
171+
return $data;
172+
}
173+
"""
174+
And I run `wp post create --post_title='foo title' --post_content='foo content here' --porcelain`
175+
And save STDOUT as {POST_ID}
176+
177+
When I run `wp search-replace 'foo' 'verified' wp_posts --include-columns=post_content --callback='opts_callback' --precise --require=callback-opts.php`
178+
Then STDOUT should contain:
179+
"""
180+
Success: Made 1 replacement.
181+
"""
182+
183+
When I run `wp post get {POST_ID} --field=content`
184+
Then STDOUT should be:
185+
"""
186+
verified content here
187+
"""

src/Search_Replace_Command.php

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -126,9 +126,9 @@ class Search_Replace_Command extends WP_CLI_Command {
126126
* table name maps to an array of column names, each of which maps to an array of
127127
* string values to match in the WHERE clause. If set to false, no filtering is applied.
128128
*
129-
* @var array<string, array<string, string[]>>|false
129+
* @var array<string, array<string, string[]>>
130130
*/
131-
private $where;
131+
private $where = [];
132132

133133
/**
134134
* @var bool
@@ -219,7 +219,12 @@ class Search_Replace_Command extends WP_CLI_Command {
219219
* : Prints rows to the console as they're updated.
220220
*
221221
* [--callback=<user-function>]
222-
* : Runs a user-specified function on each string that contains <old>. <new> is passed as the second argument and the regex string as the third if it exists: call_user_func( 'callback', $data, $new, $search_regex ).
222+
* : Runs a user-specified function on each string that contains <old>. The callback is called as follows:
223+
* call_user_func( 'callback', $data, $new, $search_regex, $opts )
224+
* * $data is the matched string
225+
* * $new is the replacement string
226+
* * $search_regex is the regex pattern (if applicable, null otherwise)
227+
* * $opts is an array of options.
223228
*
224229
* [--regex]
225230
* : Runs the search using a regular expression (without delimiters).

src/WP_CLI/SearchReplacer.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,8 @@ public function __construct( $from, $to, $recurse_objects = false, $regex = fals
9797
* Ignores any serialized objects unless $recurse_objects is set to true.
9898
*
9999
* @param array|string $data The data to operate on.
100+
* @param array $opts Additional options for the replacement passed through to the callback
101+
* An array like: ['table' => $table, 'col' => $col, 'key' => $primary_keys]
100102
* @param bool $serialised Does the value of $data need to be unserialized?
101103
* @param array $opts Options for the callback.
102104
*

0 commit comments

Comments
 (0)