Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
23 changes: 22 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -527,7 +527,7 @@ defined in the SQL.
Finds a string in the database.

~~~
wp db search <search> [<tables>...] [--network] [--all-tables-with-prefix] [--all-tables] [--before_context=<num>] [--after_context=<num>] [--regex] [--regex-flags=<regex-flags>] [--regex-delimiter=<regex-delimiter>] [--table_column_once] [--one_line] [--matches_only] [--stats] [--table_column_color=<color_code>] [--id_color=<color_code>] [--match_color=<color_code>]
wp db search <search> [<tables>...] [--network] [--all-tables-with-prefix] [--all-tables] [--before_context=<num>] [--after_context=<num>] [--regex] [--regex-flags=<regex-flags>] [--regex-delimiter=<regex-delimiter>] [--table_column_once] [--one_line] [--matches_only] [--stats] [--table_column_color=<color_code>] [--id_color=<color_code>] [--match_color=<color_code>] [--fields=<fields>] [--format=<format>]
~~~

Searches through all of the text columns in a selection of database tables for a given string, Outputs colorized references to the string.
Expand Down Expand Up @@ -593,6 +593,12 @@ Defaults to searching through all tables registered to $wpdb. On multisite, this
[--match_color=<color_code>]
Percent color code to use for the match (unless both before and after context are 0, when no color code is used). For a list of available percent color codes, see below. Default '%3%k' (black on a mustard background).

[--fields=<fields>]
Get a specific subset of the fields.

[--format=<format>]
Render output in a particular format.

The percent color codes available are:

| Code | Color
Expand Down Expand Up @@ -661,6 +667,21 @@ They can be concatenated. For instance, the default match color of black on a mu
# SQL search and delete records from database table 'wp_options' where 'option_name' match 'foo'
wp db query "DELETE from wp_options where option_id in ($(wp db query "SELECT GROUP_CONCAT(option_id SEPARATOR ',') from wp_options where option_name like '%foo%';" --silent --skip-column-names))"

# Search for a string and print the result as a table
$ wp db search https://localhost:8889 --format=table --fields=table,column,match
+------------+--------------+-----------------------------+
| table | column | match |
+------------+--------------+-----------------------------+
| wp_options | option_value | https://localhost:8889 |
| wp_options | option_value | https://localhost:8889 |
| wp_posts | guid | https://localhost:8889/?p=1 |
| wp_users | user_url | https://localhost:8889 |
+------------+--------------+-----------------------------+

# Search for a string and get only the IDs (only works for a single table)
$ wp db search https://localhost:8889 wp_options --format=ids
1 2



### wp db tables
Expand Down
20 changes: 20 additions & 0 deletions features/db-search.feature
Original file line number Diff line number Diff line change
Expand Up @@ -1066,3 +1066,23 @@ Feature: Search through the database
:aöXYXYX
"""
And STDERR should be empty

Scenario: Search for a string and output the format as a table
Given a WP install

When I run `wp db search mail.example.com --format=csv`
Then STDOUT should contain:
"""
wp_options,option_value,mail.example.com,option_id
"""

When I try `wp db search example.com --format=ids`
Then STDERR should be:
"""
Error: The "ids" format can only be used for a single table.
"""
And STDOUT should be empty
And the return code should be 1

When I run `wp db search mail.example.com wp_options --format=ids`
Then STDOUT should not be empty
66 changes: 64 additions & 2 deletions src/DB_Command.php
Original file line number Diff line number Diff line change
Expand Up @@ -1225,6 +1225,12 @@ public function prefix() {
* [--match_color=<color_code>]
* : Percent color code to use for the match (unless both before and after context are 0, when no color code is used). For a list of available percent color codes, see below. Default '%3%k' (black on a mustard background).
*
* [--fields=<fields>]
* : Get a specific subset of the fields.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What fields are supported here?

*
* [--format=<format>]
* : Render output in a particular format.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should document supported --format=<format> options with YAML:

[--format=<format>]
---
options:
  - TK
---

*
* The percent color codes available are:
*
* | Code | Color
Expand Down Expand Up @@ -1293,6 +1299,21 @@ public function prefix() {
* # SQL search and delete records from database table 'wp_options' where 'option_name' match 'foo'
* wp db query "DELETE from wp_options where option_id in ($(wp db query "SELECT GROUP_CONCAT(option_id SEPARATOR ',') from wp_options where option_name like '%foo%';" --silent --skip-column-names))"
*
* # Search for a string and print the result as a table
* $ wp db search https://localhost:8889 --format=table --fields=table,column,match
* +------------+--------------+-----------------------------+
* | table | column | match |
* +------------+--------------+-----------------------------+
* | wp_options | option_value | https://localhost:8889 |
* | wp_options | option_value | https://localhost:8889 |
* | wp_posts | guid | https://localhost:8889/?p=1 |
* | wp_users | user_url | https://localhost:8889 |
* +------------+--------------+-----------------------------+
*
* # Search for a string and get only the IDs (only works for a single table)
* $ wp db search https://localhost:8889 wp_options --format=ids
* 1 2
*
* @when after_wp_load
*/
public function search( $args, $assoc_args ) {
Expand Down Expand Up @@ -1332,6 +1353,8 @@ public function search( $args, $assoc_args ) {
$one_line = Utils\get_flag_value( $assoc_args, 'one_line', false );
$matches_only = Utils\get_flag_value( $assoc_args, 'matches_only', false );
$stats = Utils\get_flag_value( $assoc_args, 'stats', false );
$fields = Utils\get_flag_value( $assoc_args, 'fields' );
$format = Utils\get_flag_value( $assoc_args, 'format' );

$column_count = 0;
$row_count = 0;
Expand Down Expand Up @@ -1366,6 +1389,8 @@ public function search( $args, $assoc_args ) {

$tables = Utils\wp_get_table_names( $args, $assoc_args );

$search_results = [];

$start_search_time = microtime( true );

foreach ( $tables as $table ) {
Expand Down Expand Up @@ -1409,7 +1434,7 @@ public function search( $args, $assoc_args ) {
foreach ( $results as $result ) {
$col_val = $result->$column;
if ( preg_match_all( $search_regex, $col_val, $matches, PREG_OFFSET_CAPTURE ) ) {
if ( ! $matches_only && ( ! $table_column_once || ! $outputted_table_column_once ) && ! $one_line ) {
if ( ! $format && ! $matches_only && ( ! $table_column_once || ! $outputted_table_column_once ) && ! $one_line ) {
WP_CLI::log( $table_column_val );
$outputted_table_column_once = true;
}
Expand Down Expand Up @@ -1457,13 +1482,50 @@ public function search( $args, $assoc_args ) {
$match_count += $match_cnt;
$col_val = implode( ' [...] ', $bits );

WP_CLI::log( $matches_only ? $col_val : ( $one_line ? "{$table_column_val}:{$pk_val}{$col_val}" : "{$pk_val}{$col_val}" ) );
if ( $format ) {
$search_results[] = [
'table' => $table,
'column' => $column,
// Remove the colors for the format output.
'match' => str_replace(
[ $colors['match'][0], $colors['match'][1] ],
[ '','' ],
$col_val
),
'primary_key_name' => $primary_key,
'primary_key_value' => $result->$primary_key,
];
} else {
WP_CLI::log( $matches_only ? $col_val : ( $one_line ? "{$table_column_val}:{$pk_val}{$col_val}" : "{$pk_val}{$col_val}" ) );
}
}
}
}
}
}

if ( $format ) {
$formatter_args = [
'format' => $format,
];
$formatter_fields = [ 'table', 'column', 'match', 'primary_key_name', 'primary_key_value' ];

if ( $fields ) {
$fields = explode( ',', $assoc_args['fields'] );
$formatter_fields = array_values( array_intersect( $formatter_fields, $fields ) );
}

if ( in_array( $format, [ 'ids', 'count' ], true ) ) {
if ( count( $tables ) > 1 ) {
WP_CLI::error( 'The "ids" format can only be used for a single table.' );
}
$search_results = array_column( $search_results, 'primary_key_value' );
}

$formatter = new Formatter( $formatter_args, $formatter_fields );
$formatter->display_items( $search_results );
}

if ( $stats ) {
$table_count = count( $tables );
$skipped_count = count( $skipped );
Expand Down