From a94e53ebabd13455bcadbeac55e9b8eeb1886e56 Mon Sep 17 00:00:00 2001 From: rajkp Date: Mon, 27 May 2024 12:01:59 +0530 Subject: [PATCH 1/6] implement exclude revision flag to remove revision results from the db search --- src/DB_Command.php | 25 ++++++++++++++++++++----- 1 file changed, 20 insertions(+), 5 deletions(-) diff --git a/src/DB_Command.php b/src/DB_Command.php index 17d1c00e..592cd848 100644 --- a/src/DB_Command.php +++ b/src/DB_Command.php @@ -1264,6 +1264,9 @@ public function prefix() { * [--format=] * : Render output in a particular format. * + * [--exclude_revisions] + * : Exclude revisions from the search. + * * The percent color codes available are: * * | Code | Color @@ -1388,6 +1391,7 @@ public function search( $args, $assoc_args ) { $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' ); + $exclude_revisions = Utils\get_flag_value( $assoc_args, 'exclude_revisions', false ); $column_count = 0; $row_count = 0; @@ -1452,13 +1456,24 @@ public function search( $args, $assoc_args ) { } foreach ( $text_columns as $column ) { - $column_sql = self::esc_sql_ident( $column ); + $column_sql = self::esc_sql_ident( $column ); + $post_type_sql = self::esc_sql_ident( 'post_type' ); if ( $regex ) { - // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared -- Escaped through esc_sql_ident/esc_like. - $results = $wpdb->get_results( "SELECT {$primary_key_sql}{$column_sql} FROM {$table_sql}" ); + if ( $exclude_revisions && 'wp_posts' === $table ) { + // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared -- Escaped through esc_sql_ident/esc_like. + $results = $wpdb->get_results( "SELECT {$primary_key_sql}{$column_sql} FROM {$table_sql} WHERE {$post_type_sql} NOT IN ( 'revision' )" ); + } else { + // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared -- Escaped through esc_sql_ident/esc_like. + $results = $wpdb->get_results( "SELECT {$primary_key_sql}{$column_sql} FROM {$table_sql}" ); + } } else { - // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared -- Escaped through esc_sql_ident/esc_like. - $results = $wpdb->get_results( $wpdb->prepare( "SELECT {$primary_key_sql}{$column_sql} FROM {$table_sql} WHERE {$column_sql} LIKE %s;", $esc_like_search ) ); + if ( $exclude_revisions && 'wp_posts' === $table ) { + // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared -- Escaped through esc_sql_ident/esc_like. + $results = $wpdb->get_results( $wpdb->prepare( "SELECT {$primary_key_sql}{$column_sql} FROM {$table_sql} WHERE {$column_sql} LIKE %s AND {$post_type_sql} NOT IN ( 'revision' )", $esc_like_search ) ); + } else { + // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared -- Escaped through esc_sql_ident/esc_like. + $results = $wpdb->get_results( $wpdb->prepare( "SELECT {$primary_key_sql}{$column_sql} FROM {$table_sql} WHERE {$column_sql} LIKE %s;", $esc_like_search ) ); + } } if ( $results ) { $row_count += count( $results ); From aaaada6e223919c7623d114dc2d7cc272404b74b Mon Sep 17 00:00:00 2001 From: rajkp Date: Mon, 27 May 2024 18:31:47 +0530 Subject: [PATCH 2/6] Fix indentation issues and refactor the conditions in `wp db search` command --- src/DB_Command.php | 128 ++++++++++++++++++++++----------------------- 1 file changed, 64 insertions(+), 64 deletions(-) diff --git a/src/DB_Command.php b/src/DB_Command.php index 592cd848..a56f171c 100644 --- a/src/DB_Command.php +++ b/src/DB_Command.php @@ -45,18 +45,19 @@ class DB_Command extends WP_CLI_Command { * A list of incompatible SQL modes. * * Copied over from WordPress Core code. + * * @see https://github.com/WordPress/wordpress-develop/blob/5.4.0/src/wp-includes/wp-db.php#L559-L572 * * @var string[] Array of SQL mode names that are incompatible with WordPress. */ - protected $sql_incompatible_modes = [ + protected $sql_incompatible_modes = array( 'NO_ZERO_DATE', 'ONLY_FULL_GROUP_BY', 'STRICT_TRANS_TABLES', 'STRICT_ALL_TABLES', 'TRADITIONAL', 'ANSI', - ]; + ); /** * Creates a new database. @@ -198,8 +199,8 @@ public function clean( $_, $assoc_args ) { ); $tables = Utils\wp_get_table_names( - [], - [ 'all-tables-with-prefix' => true ] + array(), + array( 'all-tables-with-prefix' => true ) ); foreach ( $tables as $table ) { @@ -632,7 +633,7 @@ public function export( $args, $assoc_args ) { $initial_command = sprintf( "{$mysqldump_binary}%s ", $this->get_defaults_flag_string( $assoc_args ) ); WP_CLI::debug( "Running initial shell command: {$initial_command}", 'db' ); - $default_arguments = [ '%s' ]; + $default_arguments = array( '%s' ); if ( $support_column_statistics ) { $default_arguments[] = '--skip-column-statistics'; @@ -644,7 +645,7 @@ public function export( $args, $assoc_args ) { $command = $initial_command . implode( ' ', $default_arguments ); - $command_esc_args = [ DB_NAME ]; + $command_esc_args = array( DB_NAME ); if ( isset( $assoc_args['tables'] ) ) { $tables = explode( ',', trim( $assoc_args['tables'], ',' ) ); @@ -667,7 +668,7 @@ public function export( $args, $assoc_args ) { } } - $escaped_command = call_user_func_array( '\WP_CLI\Utils\esc_cmd', array_merge( [ $command ], $command_esc_args ) ); + $escaped_command = call_user_func_array( '\WP_CLI\Utils\esc_cmd', array_merge( array( $command ), $command_esc_args ) ); // Remove parameters not needed for SQL run. unset( $assoc_args['porcelain'] ); @@ -701,7 +702,7 @@ private function get_posts_table_charset( $assoc_args ) { '/usr/bin/env mysql%s --no-auto-rehash --batch --skip-column-names', $this->get_defaults_flag_string( $assoc_args ) ), - [ 'execute' => $query ], + array( 'execute' => $query ), false ); @@ -764,7 +765,7 @@ public function import( $args, $assoc_args ) { // Process options to MySQL. $mysql_args = array_merge( - [ 'database' => DB_NAME ], + array( 'database' => DB_NAME ), self::get_dbuser_dbpass_args( $assoc_args ), self::get_mysql_args( $assoc_args ) ); @@ -1023,8 +1024,8 @@ public function size( $args, $assoc_args ) { } // Build rows for the formatter. - $rows = []; - $fields = [ 'Name', 'Size' ]; + $rows = array(); + $fields = array( 'Name', 'Size' ); $default_unit = ( empty( $size_format ) && ! $human_readable ) ? ' B' : ''; @@ -1043,11 +1044,11 @@ public function size( $args, $assoc_args ) { ); // Add the table size to the list. - $rows[] = [ + $rows[] = array( 'Name' => $table_name, 'Size' => strtoupper( $table_bytes ) . $default_unit, 'Bytes' => strtoupper( $table_bytes ), - ]; + ); } } else { @@ -1060,11 +1061,11 @@ public function size( $args, $assoc_args ) { ); // Add the database size to the list. - $rows[] = [ + $rows[] = array( 'Name' => DB_NAME, 'Size' => strtoupper( $db_bytes ) . $default_unit, 'Bytes' => strtoupper( $db_bytes ), - ]; + ); } if ( ! empty( $size_format ) || $human_readable ) { @@ -1086,7 +1087,7 @@ public function size( $args, $assoc_args ) { if ( $human_readable ) { $size_key = floor( log( $row['Size'] ) / log( 1000 ) ); - $sizes = [ 'B', 'KB', 'MB', 'GB', 'TB' ]; + $sizes = array( 'B', 'KB', 'MB', 'GB', 'TB' ); $size_format = isset( $sizes[ $size_key ] ) ? $sizes[ $size_key ] : $sizes[0]; } @@ -1165,9 +1166,9 @@ function ( $a, $b ) use ( $order, $orderby ) { } // Display the rows. - $args = [ + $args = array( 'format' => $format, - ]; + ); $formatter = new Formatter( $args, $fields ); $formatter->display_items( $rows ); @@ -1266,7 +1267,7 @@ public function prefix() { * * [--exclude_revisions] * : Exclude revisions from the search. - * + * * The percent color codes available are: * * | Code | Color @@ -1378,11 +1379,11 @@ public function search( $args, $assoc_args ) { $colors = self::get_colors( $assoc_args, - [ + array( 'table_column' => '%G', 'id' => '%Y', 'match' => $before_context || $after_context ? '%3%k' : '', - ] + ) ); $table_column_once = Utils\get_flag_value( $assoc_args, 'table_column_once', false ); @@ -1396,7 +1397,7 @@ public function search( $args, $assoc_args ) { $column_count = 0; $row_count = 0; $match_count = 0; - $skipped = []; + $skipped = array(); if ( $regex ) { // Note the user must escape the delimiter in the search. @@ -1426,7 +1427,7 @@ public function search( $args, $assoc_args ) { $tables = Utils\wp_get_table_names( $args, $assoc_args ); - $search_results = []; + $search_results = array(); $start_search_time = microtime( true ); @@ -1466,15 +1467,14 @@ public function search( $args, $assoc_args ) { // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared -- Escaped through esc_sql_ident/esc_like. $results = $wpdb->get_results( "SELECT {$primary_key_sql}{$column_sql} FROM {$table_sql}" ); } + } elseif ( $exclude_revisions && 'wp_posts' === $table ) { + // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared -- Escaped through esc_sql_ident/esc_like. + $results = $wpdb->get_results( $wpdb->prepare( "SELECT {$primary_key_sql}{$column_sql} FROM {$table_sql} WHERE {$column_sql} LIKE %s AND {$post_type_sql} NOT IN ( 'revision' )", $esc_like_search ) ); } else { - if ( $exclude_revisions && 'wp_posts' === $table ) { - // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared -- Escaped through esc_sql_ident/esc_like. - $results = $wpdb->get_results( $wpdb->prepare( "SELECT {$primary_key_sql}{$column_sql} FROM {$table_sql} WHERE {$column_sql} LIKE %s AND {$post_type_sql} NOT IN ( 'revision' )", $esc_like_search ) ); - } else { - // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared -- Escaped through esc_sql_ident/esc_like. - $results = $wpdb->get_results( $wpdb->prepare( "SELECT {$primary_key_sql}{$column_sql} FROM {$table_sql} WHERE {$column_sql} LIKE %s;", $esc_like_search ) ); - } + // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared -- Escaped through esc_sql_ident/esc_like. + $results = $wpdb->get_results( $wpdb->prepare( "SELECT {$primary_key_sql}{$column_sql} FROM {$table_sql} WHERE {$column_sql} LIKE %s;", $esc_like_search ) ); } + if ( $results ) { $row_count += count( $results ); $table_column_val = $colors['table_column'][0] . "{$table}:{$column}" . $colors['table_column'][1]; @@ -1488,7 +1488,7 @@ public function search( $args, $assoc_args ) { } $pk_val = $primary_key ? ( $colors['id'][0] . $result->$primary_key . $colors['id'][1] . ':' ) : ''; - $bits = []; + $bits = array(); $col_encoding = $encoding; if ( ! $col_encoding && ( $before_context || $after_context ) && function_exists( 'mb_detect_encoding' ) ) { $col_encoding = mb_detect_encoding( $col_val, null, true /*strict*/ ); @@ -1531,18 +1531,18 @@ public function search( $args, $assoc_args ) { $col_val = implode( ' [...] ', $bits ); if ( $format ) { - $search_results[] = [ + $search_results[] = array( 'table' => $table, 'column' => $column, // Remove the colors for the format output. 'match' => str_replace( - [ $colors['match'][0], $colors['match'][1] ], - [ '','' ], + array( $colors['match'][0], $colors['match'][1] ), + array( '', '' ), $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}" ) ); } @@ -1553,17 +1553,17 @@ public function search( $args, $assoc_args ) { } if ( $format ) { - $formatter_args = [ + $formatter_args = array( 'format' => $format, - ]; - $formatter_fields = [ 'table', 'column', 'match', 'primary_key_name', 'primary_key_value' ]; + ); + $formatter_fields = array( '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 ( in_array( $format, array( 'ids', 'count' ), true ) ) { if ( count( $tables ) > 1 ) { WP_CLI::error( 'The "ids" format can only be used for a single table.' ); } @@ -1664,17 +1664,17 @@ public function columns( $args, $assoc_args ) { $format = Utils\get_flag_value( $assoc_args, 'format' ); - Utils\wp_get_table_names( [ $args[0] ], [ 'all-tables' => true ] ); + Utils\wp_get_table_names( array( $args[0] ), array( 'all-tables' => true ) ); $columns = $wpdb->get_results( // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared -- Asserted to be a valid table name through wp_get_table_names. 'SHOW COLUMNS FROM ' . $args[0] ); - $formatter_fields = [ 'Field', 'Type', 'Null', 'Key', 'Default', 'Extra' ]; - $formatter_args = [ + $formatter_fields = array( 'Field', 'Type', 'Null', 'Key', 'Default', 'Extra' ); + $formatter_args = array( 'format' => $format, - ]; + ); $formatter = new Formatter( $formatter_args, $formatter_fields ); $formatter->display_items( $columns ); @@ -1701,7 +1701,7 @@ private static function get_create_query() { * @param string $query Query to execute. * @param array $assoc_args Optional. Associative array of arguments. */ - protected function run_query( $query, $assoc_args = [] ) { + protected function run_query( $query, $assoc_args = array() ) { // Ensure that the SQL mode is compatible with WPDB. $query = $this->get_sql_mode_query( $assoc_args ) . $query; @@ -1717,7 +1717,7 @@ protected function run_query( $query, $assoc_args = [] ) { '/usr/bin/env mysql%s --no-auto-rehash', $this->get_defaults_flag_string( $assoc_args ) ), - array_merge( [ 'execute' => $query ], $mysql_args ) + array_merge( array( 'execute' => $query ), $mysql_args ) ); } @@ -1741,12 +1741,12 @@ protected function run_query( $query, $assoc_args = [] ) { * @type int $exit_code Exit code of the process. * } */ - private static function run( $cmd, $assoc_args = [], $send_to_shell = true, $interactive = false ) { - $required = [ + private static function run( $cmd, $assoc_args = array(), $send_to_shell = true, $interactive = false ) { + $required = array( 'host' => DB_HOST, 'user' => DB_USER, 'pass' => DB_PASSWORD, - ]; + ); if ( ! isset( $assoc_args['default-character-set'] ) && defined( 'DB_CHARSET' ) && constant( 'DB_CHARSET' ) ) { @@ -1789,7 +1789,7 @@ static function ( $a, $b ) { * @return array Array with `dbuser' and 'dbpass' set if in passed-in associative args array. */ private static function get_dbuser_dbpass_args( $assoc_args ) { - $mysql_args = []; + $mysql_args = array(); $dbuser = Utils\get_flag_value( $assoc_args, 'dbuser' ); if ( null !== $dbuser ) { $mysql_args['dbuser'] = $dbuser; @@ -1811,9 +1811,9 @@ private static function get_columns( $table ) { global $wpdb; $table_sql = self::esc_sql_ident( $table ); - $primary_keys = []; - $text_columns = []; - $all_columns = []; + $primary_keys = array(); + $text_columns = array(); + $all_columns = array(); $suppress_errors = $wpdb->suppress_errors(); // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared -- Escaped through esc_sql_ident/esc_like. @@ -1832,7 +1832,7 @@ private static function get_columns( $table ) { } } $wpdb->suppress_errors( $suppress_errors ); - return [ $primary_keys, $text_columns, $all_columns ]; + return array( $primary_keys, $text_columns, $all_columns ); } /** @@ -1842,7 +1842,7 @@ private static function get_columns( $table ) { * @return bool True if text column, false otherwise. */ private static function is_text_col( $type ) { - foreach ( [ 'text', 'varchar' ] as $token ) { + foreach ( array( 'text', 'varchar' ) as $token ) { if ( false !== strpos( $type, $token ) ) { return true; } @@ -1900,7 +1900,7 @@ function ( $v ) { $colors[ $color_col ] = $matches[0]; } } - $colors[ $color_col ] = $colors[ $color_col ] ? [ WP_CLI::colorize( $colors[ $color_col ] ), $color_reset ] : [ '', '' ]; + $colors[ $color_col ] = $colors[ $color_col ] ? array( WP_CLI::colorize( $colors[ $color_col ] ), $color_reset ) : array( '', '' ); } return $colors; @@ -1914,7 +1914,7 @@ function ( $v ) { */ private static function get_mysql_args( $assoc_args ) { - $allowed_mysql_options = [ + $allowed_mysql_options = array( 'auto-rehash', 'auto-vertical-output', 'batch', @@ -2001,9 +2001,9 @@ private static function get_mysql_args( $assoc_args ) { 'vertical', 'wait', 'xml', - ]; + ); - $mysql_args = []; + $mysql_args = array(); foreach ( $assoc_args as $mysql_option_key => $mysql_option_value ) { // Check flags to make sure they only contain valid options. @@ -2053,7 +2053,7 @@ protected function get_defaults_flag_string( &$assoc_args ) { * @return string Query string to use for setting the SQL modes to a * compatible state. */ - protected function get_sql_mode_query( $assoc_args, $modes = [] ) { + protected function get_sql_mode_query( $assoc_args, $modes = array() ) { if ( empty( $modes ) ) { $modes = $this->get_current_sql_modes( $assoc_args ); } @@ -2102,22 +2102,22 @@ protected function get_current_sql_modes( $assoc_args ) { // Make sure the provided arguments don't interfere with the expected // output here. - $args = []; - foreach ( [] as $arg ) { + $args = array(); + foreach ( array() as $arg ) { if ( isset( $assoc_args[ $arg ] ) ) { $args[ $arg ] = $assoc_args[ $arg ]; } } if ( null === $modes ) { - $modes = []; + $modes = array(); list( $stdout, $stderr, $exit_code ) = self::run( sprintf( '/usr/bin/env mysql%s --no-auto-rehash --batch --skip-column-names', $this->get_defaults_flag_string( $assoc_args ) ), - array_merge( $args, [ 'execute' => 'SELECT @@SESSION.sql_mode' ] ), + array_merge( $args, array( 'execute' => 'SELECT @@SESSION.sql_mode' ) ), false ); @@ -2139,7 +2139,7 @@ protected function get_current_sql_modes( $assoc_args ) { } if ( false === $modes ) { - $modes = []; + $modes = array(); } } From 2a9a529c1d265206a0ae811056ddb21dd1bff7cb Mon Sep 17 00:00:00 2001 From: rajkp Date: Thu, 20 Jun 2024 13:06:56 +0530 Subject: [PATCH 3/6] Fix the PHPCS formatting issue --- src/DB_Command.php | 116 ++++++++++++++++++++++----------------------- 1 file changed, 57 insertions(+), 59 deletions(-) diff --git a/src/DB_Command.php b/src/DB_Command.php index a56f171c..e3a117b9 100644 --- a/src/DB_Command.php +++ b/src/DB_Command.php @@ -45,19 +45,18 @@ class DB_Command extends WP_CLI_Command { * A list of incompatible SQL modes. * * Copied over from WordPress Core code. - * * @see https://github.com/WordPress/wordpress-develop/blob/5.4.0/src/wp-includes/wp-db.php#L559-L572 * * @var string[] Array of SQL mode names that are incompatible with WordPress. */ - protected $sql_incompatible_modes = array( + protected $sql_incompatible_modes = [ 'NO_ZERO_DATE', 'ONLY_FULL_GROUP_BY', 'STRICT_TRANS_TABLES', 'STRICT_ALL_TABLES', 'TRADITIONAL', 'ANSI', - ); + ]; /** * Creates a new database. @@ -199,8 +198,8 @@ public function clean( $_, $assoc_args ) { ); $tables = Utils\wp_get_table_names( - array(), - array( 'all-tables-with-prefix' => true ) + [], + [ 'all-tables-with-prefix' => true ] ); foreach ( $tables as $table ) { @@ -633,7 +632,7 @@ public function export( $args, $assoc_args ) { $initial_command = sprintf( "{$mysqldump_binary}%s ", $this->get_defaults_flag_string( $assoc_args ) ); WP_CLI::debug( "Running initial shell command: {$initial_command}", 'db' ); - $default_arguments = array( '%s' ); + $default_arguments = [ '%s' ]; if ( $support_column_statistics ) { $default_arguments[] = '--skip-column-statistics'; @@ -645,7 +644,7 @@ public function export( $args, $assoc_args ) { $command = $initial_command . implode( ' ', $default_arguments ); - $command_esc_args = array( DB_NAME ); + $command_esc_args = [ DB_NAME ]; if ( isset( $assoc_args['tables'] ) ) { $tables = explode( ',', trim( $assoc_args['tables'], ',' ) ); @@ -668,7 +667,7 @@ public function export( $args, $assoc_args ) { } } - $escaped_command = call_user_func_array( '\WP_CLI\Utils\esc_cmd', array_merge( array( $command ), $command_esc_args ) ); + $escaped_command = call_user_func_array( '\WP_CLI\Utils\esc_cmd', array_merge( [ $command ], $command_esc_args ) ); // Remove parameters not needed for SQL run. unset( $assoc_args['porcelain'] ); @@ -702,7 +701,7 @@ private function get_posts_table_charset( $assoc_args ) { '/usr/bin/env mysql%s --no-auto-rehash --batch --skip-column-names', $this->get_defaults_flag_string( $assoc_args ) ), - array( 'execute' => $query ), + [ 'execute' => $query ], false ); @@ -765,7 +764,7 @@ public function import( $args, $assoc_args ) { // Process options to MySQL. $mysql_args = array_merge( - array( 'database' => DB_NAME ), + [ 'database' => DB_NAME ], self::get_dbuser_dbpass_args( $assoc_args ), self::get_mysql_args( $assoc_args ) ); @@ -1024,8 +1023,8 @@ public function size( $args, $assoc_args ) { } // Build rows for the formatter. - $rows = array(); - $fields = array( 'Name', 'Size' ); + $rows = []; + $fields = [ 'Name', 'Size' ]; $default_unit = ( empty( $size_format ) && ! $human_readable ) ? ' B' : ''; @@ -1044,11 +1043,11 @@ public function size( $args, $assoc_args ) { ); // Add the table size to the list. - $rows[] = array( + $rows[] = [ 'Name' => $table_name, 'Size' => strtoupper( $table_bytes ) . $default_unit, 'Bytes' => strtoupper( $table_bytes ), - ); + ]; } } else { @@ -1061,11 +1060,11 @@ public function size( $args, $assoc_args ) { ); // Add the database size to the list. - $rows[] = array( + $rows[] = [ 'Name' => DB_NAME, 'Size' => strtoupper( $db_bytes ) . $default_unit, 'Bytes' => strtoupper( $db_bytes ), - ); + ]; } if ( ! empty( $size_format ) || $human_readable ) { @@ -1087,7 +1086,7 @@ public function size( $args, $assoc_args ) { if ( $human_readable ) { $size_key = floor( log( $row['Size'] ) / log( 1000 ) ); - $sizes = array( 'B', 'KB', 'MB', 'GB', 'TB' ); + $sizes = [ 'B', 'KB', 'MB', 'GB', 'TB' ]; $size_format = isset( $sizes[ $size_key ] ) ? $sizes[ $size_key ] : $sizes[0]; } @@ -1166,9 +1165,9 @@ function ( $a, $b ) use ( $order, $orderby ) { } // Display the rows. - $args = array( + $args = [ 'format' => $format, - ); + ]; $formatter = new Formatter( $args, $fields ); $formatter->display_items( $rows ); @@ -1379,11 +1378,11 @@ public function search( $args, $assoc_args ) { $colors = self::get_colors( $assoc_args, - array( + [ 'table_column' => '%G', 'id' => '%Y', 'match' => $before_context || $after_context ? '%3%k' : '', - ) + ] ); $table_column_once = Utils\get_flag_value( $assoc_args, 'table_column_once', false ); @@ -1397,7 +1396,7 @@ public function search( $args, $assoc_args ) { $column_count = 0; $row_count = 0; $match_count = 0; - $skipped = array(); + $skipped = []; if ( $regex ) { // Note the user must escape the delimiter in the search. @@ -1427,7 +1426,7 @@ public function search( $args, $assoc_args ) { $tables = Utils\wp_get_table_names( $args, $assoc_args ); - $search_results = array(); + $search_results = []; $start_search_time = microtime( true ); @@ -1474,7 +1473,6 @@ public function search( $args, $assoc_args ) { // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared -- Escaped through esc_sql_ident/esc_like. $results = $wpdb->get_results( $wpdb->prepare( "SELECT {$primary_key_sql}{$column_sql} FROM {$table_sql} WHERE {$column_sql} LIKE %s;", $esc_like_search ) ); } - if ( $results ) { $row_count += count( $results ); $table_column_val = $colors['table_column'][0] . "{$table}:{$column}" . $colors['table_column'][1]; @@ -1488,7 +1486,7 @@ public function search( $args, $assoc_args ) { } $pk_val = $primary_key ? ( $colors['id'][0] . $result->$primary_key . $colors['id'][1] . ':' ) : ''; - $bits = array(); + $bits = []; $col_encoding = $encoding; if ( ! $col_encoding && ( $before_context || $after_context ) && function_exists( 'mb_detect_encoding' ) ) { $col_encoding = mb_detect_encoding( $col_val, null, true /*strict*/ ); @@ -1531,18 +1529,18 @@ public function search( $args, $assoc_args ) { $col_val = implode( ' [...] ', $bits ); if ( $format ) { - $search_results[] = array( + $search_results[] = [ 'table' => $table, 'column' => $column, // Remove the colors for the format output. 'match' => str_replace( - array( $colors['match'][0], $colors['match'][1] ), - array( '', '' ), + [ $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}" ) ); } @@ -1553,17 +1551,17 @@ public function search( $args, $assoc_args ) { } if ( $format ) { - $formatter_args = array( + $formatter_args = [ 'format' => $format, - ); - $formatter_fields = array( 'table', 'column', 'match', 'primary_key_name', 'primary_key_value' ); + ]; + $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, array( 'ids', 'count' ), true ) ) { + 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.' ); } @@ -1664,17 +1662,17 @@ public function columns( $args, $assoc_args ) { $format = Utils\get_flag_value( $assoc_args, 'format' ); - Utils\wp_get_table_names( array( $args[0] ), array( 'all-tables' => true ) ); + Utils\wp_get_table_names( [ $args[0] ], [ 'all-tables' => true ] ); $columns = $wpdb->get_results( // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared -- Asserted to be a valid table name through wp_get_table_names. 'SHOW COLUMNS FROM ' . $args[0] ); - $formatter_fields = array( 'Field', 'Type', 'Null', 'Key', 'Default', 'Extra' ); - $formatter_args = array( + $formatter_fields = [ 'Field', 'Type', 'Null', 'Key', 'Default', 'Extra' ]; + $formatter_args = [ 'format' => $format, - ); + ]; $formatter = new Formatter( $formatter_args, $formatter_fields ); $formatter->display_items( $columns ); @@ -1701,7 +1699,7 @@ private static function get_create_query() { * @param string $query Query to execute. * @param array $assoc_args Optional. Associative array of arguments. */ - protected function run_query( $query, $assoc_args = array() ) { + protected function run_query( $query, $assoc_args = [] ) { // Ensure that the SQL mode is compatible with WPDB. $query = $this->get_sql_mode_query( $assoc_args ) . $query; @@ -1717,7 +1715,7 @@ protected function run_query( $query, $assoc_args = array() ) { '/usr/bin/env mysql%s --no-auto-rehash', $this->get_defaults_flag_string( $assoc_args ) ), - array_merge( array( 'execute' => $query ), $mysql_args ) + array_merge( [ 'execute' => $query ], $mysql_args ) ); } @@ -1741,12 +1739,12 @@ protected function run_query( $query, $assoc_args = array() ) { * @type int $exit_code Exit code of the process. * } */ - private static function run( $cmd, $assoc_args = array(), $send_to_shell = true, $interactive = false ) { - $required = array( + private static function run( $cmd, $assoc_args = [], $send_to_shell = true, $interactive = false ) { + $required = [ 'host' => DB_HOST, 'user' => DB_USER, 'pass' => DB_PASSWORD, - ); + ]; if ( ! isset( $assoc_args['default-character-set'] ) && defined( 'DB_CHARSET' ) && constant( 'DB_CHARSET' ) ) { @@ -1789,7 +1787,7 @@ static function ( $a, $b ) { * @return array Array with `dbuser' and 'dbpass' set if in passed-in associative args array. */ private static function get_dbuser_dbpass_args( $assoc_args ) { - $mysql_args = array(); + $mysql_args = []; $dbuser = Utils\get_flag_value( $assoc_args, 'dbuser' ); if ( null !== $dbuser ) { $mysql_args['dbuser'] = $dbuser; @@ -1811,9 +1809,9 @@ private static function get_columns( $table ) { global $wpdb; $table_sql = self::esc_sql_ident( $table ); - $primary_keys = array(); - $text_columns = array(); - $all_columns = array(); + $primary_keys = []; + $text_columns = []; + $all_columns = []; $suppress_errors = $wpdb->suppress_errors(); // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared -- Escaped through esc_sql_ident/esc_like. @@ -1832,7 +1830,7 @@ private static function get_columns( $table ) { } } $wpdb->suppress_errors( $suppress_errors ); - return array( $primary_keys, $text_columns, $all_columns ); + return [ $primary_keys, $text_columns, $all_columns ]; } /** @@ -1842,7 +1840,7 @@ private static function get_columns( $table ) { * @return bool True if text column, false otherwise. */ private static function is_text_col( $type ) { - foreach ( array( 'text', 'varchar' ) as $token ) { + foreach ( [ 'text', 'varchar' ] as $token ) { if ( false !== strpos( $type, $token ) ) { return true; } @@ -1900,7 +1898,7 @@ function ( $v ) { $colors[ $color_col ] = $matches[0]; } } - $colors[ $color_col ] = $colors[ $color_col ] ? array( WP_CLI::colorize( $colors[ $color_col ] ), $color_reset ) : array( '', '' ); + $colors[ $color_col ] = $colors[ $color_col ] ? [ WP_CLI::colorize( $colors[ $color_col ] ), $color_reset ] : [ '', '' ]; } return $colors; @@ -1914,7 +1912,7 @@ function ( $v ) { */ private static function get_mysql_args( $assoc_args ) { - $allowed_mysql_options = array( + $allowed_mysql_options = [ 'auto-rehash', 'auto-vertical-output', 'batch', @@ -2001,9 +1999,9 @@ private static function get_mysql_args( $assoc_args ) { 'vertical', 'wait', 'xml', - ); + ]; - $mysql_args = array(); + $mysql_args = []; foreach ( $assoc_args as $mysql_option_key => $mysql_option_value ) { // Check flags to make sure they only contain valid options. @@ -2053,7 +2051,7 @@ protected function get_defaults_flag_string( &$assoc_args ) { * @return string Query string to use for setting the SQL modes to a * compatible state. */ - protected function get_sql_mode_query( $assoc_args, $modes = array() ) { + protected function get_sql_mode_query( $assoc_args, $modes = [] ) { if ( empty( $modes ) ) { $modes = $this->get_current_sql_modes( $assoc_args ); } @@ -2102,22 +2100,22 @@ protected function get_current_sql_modes( $assoc_args ) { // Make sure the provided arguments don't interfere with the expected // output here. - $args = array(); - foreach ( array() as $arg ) { + $args = []; + foreach ( [] as $arg ) { if ( isset( $assoc_args[ $arg ] ) ) { $args[ $arg ] = $assoc_args[ $arg ]; } } if ( null === $modes ) { - $modes = array(); + $modes = []; list( $stdout, $stderr, $exit_code ) = self::run( sprintf( '/usr/bin/env mysql%s --no-auto-rehash --batch --skip-column-names', $this->get_defaults_flag_string( $assoc_args ) ), - array_merge( $args, array( 'execute' => 'SELECT @@SESSION.sql_mode' ) ), + array_merge( $args, [ 'execute' => 'SELECT @@SESSION.sql_mode' ] ), false ); @@ -2139,10 +2137,10 @@ protected function get_current_sql_modes( $assoc_args ) { } if ( false === $modes ) { - $modes = array(); + $modes = []; } } return $modes; } -} +} \ No newline at end of file From c5e760dc7b816190c59e586b69e8c9e2848ea1d9 Mon Sep 17 00:00:00 2001 From: rajkp Date: Thu, 20 Jun 2024 13:50:30 +0530 Subject: [PATCH 4/6] Refactor the search query for exclude revision flag --- src/DB_Command.php | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/DB_Command.php b/src/DB_Command.php index e3a117b9..36000f3e 100644 --- a/src/DB_Command.php +++ b/src/DB_Command.php @@ -1459,19 +1459,19 @@ public function search( $args, $assoc_args ) { $column_sql = self::esc_sql_ident( $column ); $post_type_sql = self::esc_sql_ident( 'post_type' ); if ( $regex ) { + $sql = "SELECT {$primary_key_sql}{$column_sql} FROM {$table_sql}"; if ( $exclude_revisions && 'wp_posts' === $table ) { - // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared -- Escaped through esc_sql_ident/esc_like. - $results = $wpdb->get_results( "SELECT {$primary_key_sql}{$column_sql} FROM {$table_sql} WHERE {$post_type_sql} NOT IN ( 'revision' )" ); - } else { - // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared -- Escaped through esc_sql_ident/esc_like. - $results = $wpdb->get_results( "SELECT {$primary_key_sql}{$column_sql} FROM {$table_sql}" ); + $sql .= " WHERE {$post_type_sql} NOT IN ( 'revision' )"; } - } elseif ( $exclude_revisions && 'wp_posts' === $table ) { // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared -- Escaped through esc_sql_ident/esc_like. - $results = $wpdb->get_results( $wpdb->prepare( "SELECT {$primary_key_sql}{$column_sql} FROM {$table_sql} WHERE {$column_sql} LIKE %s AND {$post_type_sql} NOT IN ( 'revision' )", $esc_like_search ) ); + $results = $wpdb->get_results( $sql ); } else { + $sql = "SELECT {$primary_key_sql}{$column_sql} FROM {$table_sql} WHERE {$column_sql} LIKE %s"; + if ( $exclude_revisions && 'wp_posts' === $table ) { + $sql .= " AND {$post_type_sql} NOT IN ( 'revision' )"; + } // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared -- Escaped through esc_sql_ident/esc_like. - $results = $wpdb->get_results( $wpdb->prepare( "SELECT {$primary_key_sql}{$column_sql} FROM {$table_sql} WHERE {$column_sql} LIKE %s;", $esc_like_search ) ); + $results = $wpdb->get_results( $wpdb->prepare( $sql, $esc_like_search ) ); } if ( $results ) { $row_count += count( $results ); @@ -2143,4 +2143,4 @@ protected function get_current_sql_modes( $assoc_args ) { return $modes; } -} \ No newline at end of file +} From 38ee18a8984beb0f9fba9ff483245574eb5ade85 Mon Sep 17 00:00:00 2001 From: rajkp Date: Thu, 20 Jun 2024 14:31:39 +0530 Subject: [PATCH 5/6] FIx the PHPCS error for prepare statements --- src/DB_Command.php | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/DB_Command.php b/src/DB_Command.php index 36000f3e..ef65cfc1 100644 --- a/src/DB_Command.php +++ b/src/DB_Command.php @@ -1459,19 +1459,19 @@ public function search( $args, $assoc_args ) { $column_sql = self::esc_sql_ident( $column ); $post_type_sql = self::esc_sql_ident( 'post_type' ); if ( $regex ) { - $sql = "SELECT {$primary_key_sql}{$column_sql} FROM {$table_sql}"; if ( $exclude_revisions && 'wp_posts' === $table ) { - $sql .= " WHERE {$post_type_sql} NOT IN ( 'revision' )"; + // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared -- Escaped through esc_sql_ident/esc_like. + $results = $wpdb->get_results( "SELECT {$primary_key_sql}{$column_sql} FROM {$table_sql} WHERE {$post_type_sql} NOT IN ( 'revision' )" ); + } else { + // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared -- Escaped through esc_sql_ident/esc_like. + $results = $wpdb->get_results( "SELECT {$primary_key_sql}{$column_sql} FROM {$table_sql}" ); } + } elseif ( $exclude_revisions && 'wp_posts' === $table ) { // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared -- Escaped through esc_sql_ident/esc_like. - $results = $wpdb->get_results( $sql ); + $results = $wpdb->get_results( $wpdb->prepare( "SELECT {$primary_key_sql}{$column_sql} FROM {$table_sql} WHERE {$column_sql} LIKE %s AND {$post_type_sql} NOT IN ( 'revision' )", $esc_like_search ) ); } else { - $sql = "SELECT {$primary_key_sql}{$column_sql} FROM {$table_sql} WHERE {$column_sql} LIKE %s"; - if ( $exclude_revisions && 'wp_posts' === $table ) { - $sql .= " AND {$post_type_sql} NOT IN ( 'revision' )"; - } // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared -- Escaped through esc_sql_ident/esc_like. - $results = $wpdb->get_results( $wpdb->prepare( $sql, $esc_like_search ) ); + $results = $wpdb->get_results( $wpdb->prepare( "SELECT {$primary_key_sql}{$column_sql} FROM {$table_sql} WHERE {$column_sql} LIKE %s;", $esc_like_search ) ); } if ( $results ) { $row_count += count( $results ); From 95cfad104f2a456ec0d9c14bceb96f4ae9e98cd4 Mon Sep 17 00:00:00 2001 From: rajkp Date: Tue, 25 Jun 2024 12:11:12 +0530 Subject: [PATCH 6/6] Add behat test for `exclude_revisions` flag --- features/db-search.feature | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/features/db-search.feature b/features/db-search.feature index 1f5e8f5b..bdd705b7 100644 --- a/features/db-search.feature +++ b/features/db-search.feature @@ -914,6 +914,29 @@ Feature: Search through the database """ And STDERR should be empty + Scenario: Search with exclude revisions option + Given a WP install + And I run `wp post create --post_content="This is the original post content." --post_title="Original Post"` + # Create a revision + And I run `wp post update 1 --post_content="This is the updated post content."` + + When I run `wp db search "updated post content"` + Then STDOUT should contain: + """ + wp_posts:post_content + 1:This is the updated post content. + wp_posts:post_content + 5:This is the updated post content. + """ + + When I run `wp db search "updated post content" --exclude_revisions` + Then STDOUT should contain: + """ + wp_posts:post_content + 1:This is the updated post content. + """ + And STDERR should be empty + Scenario: Search with custom colors Given a WP install