Skip to content

Commit b659443

Browse files
authored
Merge pull request #45 from wp-cli/context_bug
db search: fix match in context in non-regex case.
2 parents aab939f + 4113c78 commit b659443

File tree

2 files changed

+48
-35
lines changed

2 files changed

+48
-35
lines changed

features/db-search.feature

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -944,3 +944,29 @@ Feature: Search through the database
944944
2:v"v`v'v\v_v2
945945
"""
946946
And STDERR should be empty
947+
948+
Scenario: Search with matches within context
949+
Given a WP install
950+
And I run `wp option update matches_in_context '1234_XYXYX_2345678_XYXYX_2345678901_XYXYX_2345'`
951+
952+
When I run `wp db search XYXYX --before_context=10 --after_context=10 --stats`
953+
Then STDOUT should contain:
954+
"""
955+
Success: Found 3 matches
956+
"""
957+
And STDOUT should contain:
958+
"""
959+
:1234_XYXYX_2345678_X [...] X_2345678_XYXYX_234567890 [...] 345678901_XYXYX_2345
960+
"""
961+
And STDERR should be empty
962+
963+
When I run `wp db search XYXYX --before_context=10 --after_context=10 --regex --stats`
964+
Then STDOUT should contain:
965+
"""
966+
Success: Found 3 matches
967+
"""
968+
And STDOUT should contain:
969+
"""
970+
:1234_XYXYX_2345678_X [...] X_2345678_XYXYX_234567890 [...] 345678901_XYXYX_2345
971+
"""
972+
And STDERR should be empty

src/DB_Command.php

Lines changed: 22 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -715,10 +715,10 @@ public function prefix() {
715715
* ---
716716
*
717717
* [--regex]
718-
* : Runs the search as a regular expression (without delimiters). The search becomes case-sensitive (i.e. no PCRE flags are added, except 'u' if the database charset is UTF-8). Delimiters must be escaped if they occur in the expression.
718+
* : Runs the search as a regular expression (without delimiters). The search becomes case-sensitive (i.e. no PCRE flags are added). Delimiters must be escaped if they occur in the expression.
719719
*
720720
* [--regex-flags=<regex-flags>]
721-
* : Pass PCRE modifiers to the regex search (e.g. 'i' for case-insensitivity). Note that 'u' (UTF-8 mode) will not be automatically added.
721+
* : Pass PCRE modifiers to the regex search (e.g. 'i' for case-insensitivity).
722722
*
723723
* [--regex-delimiter=<regex-delimiter>]
724724
* : The delimiter to use for the regex. It must be escaped if it appears in the search string. The default value is the result of `chr(1)`.
@@ -842,24 +842,16 @@ public function search( $args, $assoc_args ) {
842842
if ( false === @preg_match( $search_regex, '' ) ) {
843843
WP_CLI::error( "The regex '$search_regex' fails." );
844844
}
845-
$encoding = null;
846-
if ( 0 === strpos( $wpdb->charset, 'utf8' ) ) {
847-
$encoding = 'UTF-8';
848-
if ( ! $regex_flags ) {
849-
$search_regex .= 'u';
850-
}
851-
}
852845
} else {
853-
$safe_search = preg_quote( $search, '#' );
854-
if ( 0 === strpos( $wpdb->charset, 'utf8' ) ) {
855-
$context_re = \cli\can_use_pcre_x() ? '\X' : '.';
856-
$search_regex = '#(' . $context_re . '{0,' . $before_context . '})(' . $safe_search .')(' . $context_re . '{0,' . $after_context . '})#iu';
857-
} else {
858-
$search_regex = '#(.{0,' . $before_context . '})(' . $safe_search .')(.{0,' . $after_context . '})#i';
859-
}
846+
$search_regex = '#' . preg_quote( $search, '#' ) . '#i';
860847
$esc_like_search = '%' . self::esc_like( $search ) . '%';
861848
}
862849

850+
$encoding = null;
851+
if ( 0 === strpos( $wpdb->charset, 'utf8' ) ) {
852+
$encoding = 'UTF-8';
853+
}
854+
863855
$tables = WP_CLI\Utils\wp_get_table_names( $args, $assoc_args );
864856

865857
$start_search_time = microtime( true );
@@ -903,34 +895,29 @@ public function search( $args, $assoc_args ) {
903895
$outputted_table_column_once = false;
904896
foreach ( $results as $result ) {
905897
$col_val = $result->$column;
906-
if ( preg_match_all( $search_regex, $col_val, $matches, $regex ? PREG_OFFSET_CAPTURE : PREG_PATTERN_ORDER ) ) {
898+
if ( preg_match_all( $search_regex, $col_val, $matches, PREG_OFFSET_CAPTURE ) ) {
907899
if ( ! $matches_only && ( ! $table_column_once || ! $outputted_table_column_once ) && ! $one_line ) {
908900
WP_CLI::log( $table_column_val );
909901
$outputted_table_column_once = true;
910902
}
911903
$pk_val = $primary_key ? ( $colors['id'][0] . $result->$primary_key . $colors['id'][1] . ':' ) : '';
912904

913905
$bits = array();
914-
if ( $regex ) {
915-
if ( null === $encoding ) {
916-
$encoding = false;
917-
if ( ( $before_context || $after_context ) && function_exists( 'mb_detect_encoding' ) ) {
918-
$encoding = mb_detect_encoding( $col_val, null, true /*strict*/ );
919-
}
920-
}
921-
foreach ( $matches[0] as $match_arr ) {
922-
$match = $match_arr[0];
923-
$offset = $match_arr[1];
924-
// Offsets are in bytes, so need to use `strlen()` and `substr()` before using `safe_substr()`.
925-
$before = $before_context && $offset ? \cli\safe_substr( substr( $col_val, 0, $offset ), -$before_context, null /*length*/, false /*is_width*/, $encoding ) : '';
926-
$after = $after_context ? \cli\safe_substr( substr( $col_val, $offset + strlen( $match ) ), 0, $after_context, false /*is_width*/, $encoding ) : '';
927-
$bits[] = $before . $colors['match'][0] . $match . $colors['match'][1] . $after;
928-
}
929-
} else {
930-
foreach ( $matches[0] as $key => $value ) {
931-
$bits[] = $matches[1][ $key ] . $colors['match'][0] . $matches[2][ $key ] . $colors['match'][1] . $matches[3][ $key ];
906+
$col_encoding = $encoding;
907+
if ( null === $col_encoding ) {
908+
$col_encoding = false;
909+
if ( ( $before_context || $after_context ) && function_exists( 'mb_detect_encoding' ) ) {
910+
$col_encoding = mb_detect_encoding( $col_val, null, true /*strict*/ );
932911
}
933912
}
913+
foreach ( $matches[0] as $match_arr ) {
914+
$match = $match_arr[0];
915+
$offset = $match_arr[1];
916+
// Offsets are in bytes, so need to use `strlen()` and `substr()` before using `safe_substr()`.
917+
$before = $before_context && $offset ? \cli\safe_substr( substr( $col_val, 0, $offset ), -$before_context, null /*length*/, false /*is_width*/, $col_encoding ) : '';
918+
$after = $after_context ? \cli\safe_substr( substr( $col_val, $offset + strlen( $match ) ), 0, $after_context, false /*is_width*/, $col_encoding ) : '';
919+
$bits[] = $before . $colors['match'][0] . $match . $colors['match'][1] . $after;
920+
}
934921
$match_count += count( $bits );
935922
$col_val = implode( ' [...] ', $bits );
936923

0 commit comments

Comments
 (0)