Skip to content
Draft
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
28 changes: 27 additions & 1 deletion features/search-replace.feature
Original file line number Diff line number Diff line change
Expand Up @@ -1393,7 +1393,6 @@ Feature: Do global search/replace
Success: Made 0 replacements.
"""

@require-mysql
Scenario: Search/replace strings starting with hyphens using --old and --new flags
Given a WP install
And I run `wp post create --post_title="Test Post" --post_content="This is --old-content and more text" --porcelain`
Expand All @@ -1416,6 +1415,33 @@ Feature: Do global search/replace
--old-content
"""

@require-mysql
Scenario: Progress bar shows when not in verbose mode
Given a WP install
And I run `wp post generate --count=100`
And I run `wp option set test_url 'Visit http://example.com for more'`

When I run `wp search-replace http://example.com http://example.org --precise`
Then STDERR should contain:
"""
Processing
"""

@require-mysql
Scenario: Progress bar does not show in verbose mode
Given a WP install
And I run `wp post generate --count=10`

When I run `wp search-replace http://example.com http://example.org --verbose`
Then STDOUT should contain:
"""
Checking:
"""
And STDERR should not contain:
"""
Processing
"""

@require-mysql
Scenario: Error when neither positional args nor flags provided
Given a WP install
Expand Down
72 changes: 72 additions & 0 deletions src/Search_Replace_Command.php
Original file line number Diff line number Diff line change
Expand Up @@ -608,6 +608,18 @@ private function php_export_table( $table, $old, $new ) {
WP_CLI::log( sprintf( 'Checking: %s', $table ) );
}

// Set up progress bar if appropriate
$progress = null;
if ( $this->should_show_progress_bar() ) {
global $wpdb;
$table_sql = self::esc_sql_ident( $table );
// phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared -- escaped through self::esc_sql_ident
$total_rows = $wpdb->get_var( "SELECT COUNT(*) FROM {$table_sql}" );
if ( $total_rows > 0 ) {
$progress = \WP_CLI\Utils\make_progress_bar( sprintf( 'Processing %s', $table ), $total_rows );
}
}

$rows = array();
foreach ( new Iterators\Table( $args ) as $i => $row ) {
$row_fields = array();
Expand All @@ -623,9 +635,17 @@ private function php_export_table( $table, $old, $new ) {
$row_fields[ $col ] = $value;
}
$rows[] = $row_fields;

if ( $progress ) {
$progress->tick();
}
}
$this->write_sql_row_fields( $table, $rows );

if ( $progress ) {
$progress->finish();
}

$table_report = array();
$total_rows = 0;
$total_cols = 0;
Expand Down Expand Up @@ -700,12 +720,22 @@ static function ( $key ) {
);
$order_by_sql = 'ORDER BY ' . implode( ',', $order_by_keys );
$limit = 1000;
$progress = null;

// 2 errors:
// - WordPress.DB.PreparedSQL.InterpolatedNotPrepared -- escaped through self::esc_sql_ident
// - WordPress.CodeAnalysis.AssignmentInCondition -- no reason to do copy-paste for a single valid assignment in while
// phpcs:ignore
while ( $rows = $wpdb->get_results( "SELECT {$primary_keys_sql} FROM {$table_sql} {$where_key} {$order_by_sql} LIMIT {$limit}" ) ) {
// Set up progress bar on first iteration if we have rows to process
if ( null === $progress && $this->should_show_progress_bar() ) {
// Count total rows to process
// phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared -- escaped through self::esc_sql_ident
$total_rows = $wpdb->get_var( "SELECT COUNT(*) FROM {$table_sql} {$where_key}" );
if ( $total_rows > 0 ) {
$progress = \WP_CLI\Utils\make_progress_bar( sprintf( 'Processing %s.%s', $table, $col ), $total_rows );
}
}
foreach ( $rows as $keys ) {
$where_sql = '';
foreach ( (array) $keys as $k => $v ) {
Expand Down Expand Up @@ -750,6 +780,10 @@ static function ( $key ) {
}
}

if ( $progress ) {
$progress->tick( count( $rows ) );
}

// Because we are ordering by primary keys from least to greatest,
// we can exclude previous chunks from consideration by adding greater-than conditions
// to insist the next chunk's keys must be greater than the last of this chunk's keys.
Expand Down Expand Up @@ -786,6 +820,10 @@ static function ( $key ) {
$where_key = 'WHERE ' . implode( ' AND ', $where_key_conditions );
}

if ( $progress ) {
$progress->finish();
}

if ( $this->verbose && 'table' === $this->format ) {
$time = round( microtime( true ) - $this->start_time, 3 );
WP_CLI::log( sprintf( '%d rows affected using PHP (in %ss).', $count, $time ) );
Expand Down Expand Up @@ -901,6 +939,40 @@ private static function is_text_col( $type ) {
return false;
}

/**
* Determines whether a progress bar should be shown.
*
* @return bool True if progress bar should be shown.
*/
private function should_show_progress_bar() {
// Don't show progress bar if in quiet mode
if ( WP_CLI::get_config( 'quiet' ) ) {
return false;
}

// Don't show progress bar if exporting to STDOUT
if ( STDOUT === $this->export_handle ) {
return false;
}

// Don't show progress bar if logging is enabled (would interfere with log output)
if ( null !== $this->log_handle ) {
return false;
}

// Don't show progress bar if verbose mode is enabled (it shows row-by-row updates)
if ( $this->verbose ) {
return false;
}

// Don't show progress bar if format is 'count'
if ( 'count' === $this->format ) {
return false;
}

return true;
}

private static function esc_like( $old ) {
global $wpdb;

Expand Down
Loading