/** * Show table * * @param array $header * @param array $body */ protected static function table($header, $body) { $table = new \cli\Table(); $table->setHeaders($header); $table->setRows($body); $table->display(); }
/** * Lists one-time logins * * ## EXAMPLES * * wp one-time-login list * * @subcommand list */ function _list($args, $assoc_args) { // Get all one-time logins $otl_posts = get_posts(array('posts_per_page' => -1, 'post_type' => 'onetimelogin', 'order' => ASC)); // Error if no logins found if (empty($otl_posts)) { WP_CLI::error(__('No one time logins found.', 'one-time-login')); } // Set table headers $headers = array(__('ID', 'one-time-login'), __('Password', 'one-time-login'), __('User ID', 'one-time-login'), __('Date Generated', 'one-time-login'), __('Status', 'one-time-login'), __('Date Used', 'one-time-login')); $data = array(); // loop through logins and format foreach ($otl_posts as $otl) { $id = $otl->ID; $password = $otl->post_title; $user_id = get_post_meta($otl->ID, 'otl_user', true); $generated = $otl->post_date; $status = '0' === get_post_meta($otl->ID, 'otl_times_used', true) ? __('Available', 'one-time-login') : __('Expired', 'one-time-login'); $used = get_post_meta($otl->ID, 'otl_datetime_used', true); $data[] = array($id, $password, $user_id, $generated, $status, $used); } // Output table $table = new \cli\Table(); $table->setHeaders($headers); $table->setRows($data); $table->display(); }
/** * Search/replace strings in the database. * * ## DESCRIPTION * * This command will go through all rows in all tables and will replace all * appearances of the old string with the new one. * * It will correctly handle serialized values, and will not change primary key values. * * ## OPTIONS * * <old> * : The old string. * * <new> * : The new string. * * [<table>...] * : List of database tables to restrict the replacement to. * * [--network] * : Search/replace through all the tables in a multisite install. * * [--skip-columns=<columns>] * : Do not perform the replacement in the comma-separated columns. * * [--dry-run] * : Show report, but don't perform the changes. * * [--recurse-objects] * : Enable recursing into objects to replace strings * * ## EXAMPLES * * wp search-replace 'http://example.dev' 'http://example.com' --skip-columns=guid * * wp search-replace 'foo' 'bar' wp_posts wp_postmeta wp_terms --dry-run */ public function __invoke($args, $assoc_args) { $old = array_shift($args); $new = array_shift($args); $total = 0; $report = array(); $dry_run = isset($assoc_args['dry-run']); $recurse_objects = isset($assoc_args['recurse-objects']); if (isset($assoc_args['skip-columns'])) { $skip_columns = explode(',', $assoc_args['skip-columns']); } else { $skip_columns = array(); } // never mess with hashed passwords $skip_columns[] = 'user_pass'; $tables = self::get_table_list($args, isset($assoc_args['network'])); foreach ($tables as $table) { list($primary_key, $columns) = self::get_columns($table); // since we'll be updating one row at a time, // we need a primary key to identify the row if (null === $primary_key) { $report[] = array($table, '', 'skipped'); continue; } foreach ($columns as $col) { if (in_array($col, $skip_columns)) { continue; } $count = self::handle_col($col, $primary_key, $table, $old, $new, $dry_run, $recurse_objects); $report[] = array($table, $col, $count); $total += $count; } } $table = new \cli\Table(); $table->setHeaders(array('Table', 'Column', 'Replacements')); $table->setRows($report); $table->display(); if (!$dry_run) { WP_CLI::success("Made {$total} replacements."); } }
<?php require 'vendor/autoload.php'; echo "Hello World!\n\n"; echo "Payload: "; print_r(IronWorker\Runtime::getPayload(true)); echo "\nConfig: "; print_r(IronWorker\Runtime::getConfig(true)); // Add iron.json and uncomment this block to actually use it /* $ironmq = new \IronMQ\IronMQ(); $ironmq->postMessage('Some Queue', "Hello world"); $msg = $ironmq->getMessage('Some Queue'); var_dump($msg) */ echo "\n\nCLI Table:\n"; $headers = array('Id', 'Name', 'City'); $data = array(array(1, 'Elliott', 'San Francisco'), array(2, 'Washington', 'Bessemer'), array(3, 'Hopkins', 'Altoona')); $table = new \cli\Table(); $table->setHeaders($headers); $table->setRows($data); $table->display();
public function execute(array $args, array $options = array()) { # setUserMigration Path $this->migrationPath = isset($options['migration_path']) ? $options['migration_path'] : null; $list = $this->getDirectoryTree($this->getMigrationPath(), "php"); # get filename $file = isset($options['f']) ? true : false; $filter_apply = isset($options['a']) ? $options['a'] : false; $filter_new = isset($options['n']) ? $options['n'] : false; $filter_from = isset($options['from']) ? $options['from'] : false; $filter_to = isset($options['to']) ? $options['to'] : false; $filter_from = $filter_from ? strtotime($filter_from) : false; $filter_to = $filter_to ? strtotime($filter_to) : false; #check tag list $filer_tag = isset($options['tag']) ? $options['tag'] : false; if (!empty($list)) { $headers = array('№', 'id', 'Author', 'Date'); if ($file) { $headers[] = 'File'; } $headers[] = 'Description'; $headers[] = 'Status'; $table = new \cli\Table(); $table->setHeaders($headers); $count = 0; $applied = 0; $new = 0; $i = 1; $return_array_new = array(); $return_array_apply = array(); #filter $is_filter = false; $this->prepareFilter($list, $filter_from, $filter_to, $filer_tag, $options, $is_filter); foreach ($list as $id => $data) { $count++; $row = $data['file']; $name = $data['name']; # check in db $is_new = !$this->checkInDb($id); $class_name = "Migration" . $id; include_once "" . $this->getMigrationPath() . $row . ""; $color = ConsoleKit\Colors::GREEN; $status = ConsoleKit\Colors::colorize('apply', Colors::GREEN); # check in db if ($is_new) { $new++; $color = ConsoleKit\Colors::RED; $status = ConsoleKit\Colors::colorize('new', Colors::RED); } else { $applied++; } $rowArray = array(ConsoleKit\Colors::colorize($i, $color), ConsoleKit\Colors::colorize($id, $color), $data['author'], date("d.m.y G:h", $data['date'])); if ($file) { $rowArray[] = $row; } $rowArray[] = $data['description']; $rowArray[] = $status; if ($is_new) { $return_array_new[] = $rowArray; } else { $return_array_apply[] = $rowArray; } $i++; } if ($filter_new) { $table->setRows($return_array_new); } else { if ($filter_apply) { $table->setRows($return_array_apply); } else { $table->setRows(array_merge($return_array_apply, $return_array_new)); } } $displayArray = $table->getDisplayLines(); if (!empty($displayArray)) { $table->display(); } if (!$is_filter) { # count info $return[] = Colors::colorize('New:', Colors::RED) . " " . $new; $return[] = Colors::colorize('Applied:', Colors::GREEN) . " " . $applied; $return[] = "Count: " . $count; } # display $this->padding(implode(PHP_EOL, $return)); } else { $this->info('Empty migration'); } }
/** * Search/replace strings in the database. * * ## DESCRIPTION * * This command will go through all rows in a selection of tables * and will replace all appearances of the old string with the new one. The * default tables are those registered on the $wpdb object (usually * just WordPress core tables). * * It will correctly handle serialized values, and will not change primary key values. * * ## OPTIONS * * <old> * : The old string. * * <new> * : The new string. * * [<table>...] * : List of database tables to restrict the replacement to. Wildcards are supported, e.g. wp_\*_options or wp_post\?. * * [--network] * : Search/replace through all the tables in a multisite install. * * [--skip-columns=<columns>] * : Do not perform the replacement in the comma-separated columns. * * [--dry-run] * : Show report, but don't perform the changes. * * [--precise] * : Force the use of PHP (instead of SQL) which is more thorough, but slower. Use if you see issues with serialized data. * * [--recurse-objects] * : Enable recursing into objects to replace strings. Defaults to true; pass --no-recurse-objects to disable. * * [--all-tables-with-prefix] * : Enable replacement on any tables that match the table prefix even if not registered on wpdb * * [--all-tables] * : Enable replacement on ALL tables in the database, regardless of the prefix, and even if not registered on $wpdb. Overrides --network and --all-tables-with-prefix. * * [--verbose] * : Prints rows to the console as they're updated. * * [--regex] * : Runs the search using a regular expression. Warning: search-replace will take about 15-20x longer when using --regex. * * [--export[=<file>]] * : Write transformed data as SQL file instead of performing in-place replacements. If <file> is not supplied, will output to STDOUT. * * ## EXAMPLES * * wp search-replace 'http://example.dev' 'http://example.com' --skip-columns=guid * * wp search-replace 'foo' 'bar' wp_posts wp_postmeta wp_terms --dry-run * * # Turn your production database into a local database * wp search-replace --url=example.com example.com example.dev wp_\*_options * * # Search/replace to a SQL file without transforming the database * wp search-replace foo bar --export=database.sql */ public function __invoke($args, $assoc_args) { global $wpdb; $old = array_shift($args); $new = array_shift($args); $total = 0; $report = array(); $this->dry_run = \WP_CLI\Utils\get_flag_value($assoc_args, 'dry-run'); $php_only = \WP_CLI\Utils\get_flag_value($assoc_args, 'precise'); $this->recurse_objects = \WP_CLI\Utils\get_flag_value($assoc_args, 'recurse-objects', true); $this->verbose = \WP_CLI\Utils\get_flag_value($assoc_args, 'verbose'); $this->regex = \WP_CLI\Utils\get_flag_value($assoc_args, 'regex'); $this->skip_columns = explode(',', \WP_CLI\Utils\get_flag_value($assoc_args, 'skip-columns')); if ($old === $new && !$this->regex) { WP_CLI::warning("Replacement value '{$old}' is identical to search value '{$new}'. Skipping operation."); exit; } if (null !== ($export = \WP_CLI\Utils\get_flag_value($assoc_args, 'export'))) { if ($this->dry_run) { WP_CLI::error('You cannot supply --dry-run and --export at the same time.'); } if (true === $export) { $this->export_handle = STDOUT; $this->verbose = false; } else { $this->export_handle = fopen($assoc_args['export'], 'w'); if (false === $this->export_handle) { WP_CLI::error(sprintf('Unable to open "%s" for writing.', $assoc_args['export'])); } } $php_only = true; } // never mess with hashed passwords $this->skip_columns[] = 'user_pass'; // Get table names based on leftover $args or supplied $assoc_args $tables = \WP_CLI\Utils\wp_get_table_names($args, $assoc_args); foreach ($tables as $table) { if ($this->export_handle) { fwrite($this->export_handle, "\nDROP TABLE IF EXISTS `{$table}`;\n"); $row = $wpdb->get_row("SHOW CREATE TABLE `{$table}`", ARRAY_N); fwrite($this->export_handle, $row[1] . ";\n"); list($table_report, $total_rows) = $this->php_export_table($table, $old, $new); $report = array_merge($report, $table_report); $total += $total_rows; // Don't perform replacements on the actual database continue; } list($primary_keys, $columns, $all_columns) = self::get_columns($table); // since we'll be updating one row at a time, // we need a primary key to identify the row if (empty($primary_keys)) { $report[] = array($table, '', 'skipped'); continue; } foreach ($columns as $col) { if (in_array($col, $this->skip_columns)) { continue; } if ($this->verbose) { $this->start_time = microtime(true); WP_CLI::log(sprintf('Checking: %s.%s', $table, $col)); } if (!$php_only && !$this->regex) { $serialRow = $wpdb->get_row("SELECT * FROM `{$table}` WHERE `{$col}` REGEXP '^[aiO]:[1-9]' LIMIT 1"); } if ($php_only || $this->regex || NULL !== $serialRow) { $type = 'PHP'; $count = $this->php_handle_col($col, $primary_keys, $table, $old, $new); } else { $type = 'SQL'; $count = $this->sql_handle_col($col, $table, $old, $new); } $report[] = array($table, $col, $count, $type); $total += $count; } } if ($this->export_handle && STDOUT !== $this->export_handle) { fclose($this->export_handle); } // Only informational output after this point if (WP_CLI::get_config('quiet') || STDOUT === $this->export_handle) { return; } $table = new \cli\Table(); $table->setHeaders(array('Table', 'Column', 'Replacements', 'Type')); $table->setRows($report); $table->display(); if (!$this->dry_run) { if (!empty($assoc_args['export'])) { $success_message = "Made {$total} replacements and exported to {$assoc_args['export']}."; } else { $success_message = "Made {$total} replacements."; if ($total && 'Default' !== WP_CLI\Utils\wp_get_cache_type()) { $success_message .= ' Please remember to flush your persistent object cache with `wp cache flush`.'; } } WP_CLI::success($success_message); } }
/** * Search/replace strings in the database. * * ## DESCRIPTION * * This command will go through all rows in all tables and will replace all * appearances of the old string with the new one. * * It will correctly handle serialized values, and will not change primary key values. * * ## OPTIONS * * <old> * : The old string. * * <new> * : The new string. * * [<table>...] * : List of database tables to restrict the replacement to. * * [--network] * : Search/replace through all the tables in a multisite install. * * [--skip-columns=<columns>] * : Do not perform the replacement in the comma-separated columns. * * [--dry-run] * : Show report, but don't perform the changes. * * [--precise] * : Force the use of PHP (instead of SQL) which is more thorough, but slower. Use if you see issues with serialized data. * * [--recurse-objects] * : Enable recursing into objects to replace strings * * [--all-tables-with-prefix] * : Enable replacement on any tables that match the table prefix even if not registered on wpdb * * [--all-tables] * : Enable replacement on ALL tables in the database, regardless of the prefix. Overrides --network and --all-tables-with-prefix. * * [--verbose] * : Prints rows to the console as they're updated. * * [--regex] * : Runs the search using a regular expression. Warning: search-replace will take about 15-20x longer when using --regex. * * ## EXAMPLES * * wp search-replace 'http://example.dev' 'http://example.com' --skip-columns=guid * * wp search-replace 'foo' 'bar' wp_posts wp_postmeta wp_terms --dry-run * * # Turn your production database into a local database * wp search-replace --url=example.com example.com example.dev */ public function __invoke($args, $assoc_args) { global $wpdb; $old = array_shift($args); $new = array_shift($args); $total = 0; $report = array(); $dry_run = \WP_CLI\Utils\get_flag_value($assoc_args, 'dry-run'); $php_only = \WP_CLI\Utils\get_flag_value($assoc_args, 'precise'); $recurse_objects = \WP_CLI\Utils\get_flag_value($assoc_args, 'recurse-objects'); $verbose = \WP_CLI\Utils\get_flag_value($assoc_args, 'verbose'); $regex = \WP_CLI\Utils\get_flag_value($assoc_args, 'regex'); $skip_columns = explode(',', \WP_CLI\Utils\get_flag_value($assoc_args, 'skip-columns')); // never mess with hashed passwords $skip_columns[] = 'user_pass'; // Determine how to limit the list of tables. Defaults to 'wordpress' $table_type = 'wordpress'; if (\WP_CLI\Utils\get_flag_value($assoc_args, 'network')) { $table_type = 'network'; } if (\WP_CLI\Utils\get_flag_value($assoc_args, 'all-tables-with-prefix')) { $table_type = 'all-tables-with-prefix'; } if (\WP_CLI\Utils\get_flag_value($assoc_args, 'all-tables')) { $table_type = 'all-tables'; } // Get the array of tables to work with. If there is anything left in $args, assume those are table names to use $tables = empty($args) ? self::get_table_list($table_type) : $args; foreach ($tables as $table) { list($primary_keys, $columns) = self::get_columns($table); // since we'll be updating one row at a time, // we need a primary key to identify the row if (empty($primary_keys)) { $report[] = array($table, '', 'skipped'); continue; } foreach ($columns as $col) { if (in_array($col, $skip_columns)) { continue; } if (!$php_only) { $serialRow = $wpdb->get_row("SELECT * FROM `{$table}` WHERE `{$col}` REGEXP '^[aiO]:[1-9]' LIMIT 1"); } if ($php_only || $regex || NULL !== $serialRow) { $type = 'PHP'; $count = self::php_handle_col($col, $primary_keys, $table, $old, $new, $dry_run, $recurse_objects, $verbose, $regex); } else { $type = 'SQL'; $count = self::sql_handle_col($col, $table, $old, $new, $dry_run, $verbose); } $report[] = array($table, $col, $count, $type); $total += $count; } } if (!WP_CLI::get_config('quiet')) { $table = new \cli\Table(); $table->setHeaders(array('Table', 'Column', 'Replacements', 'Type')); $table->setRows($report); $table->display(); if (!$dry_run) { WP_CLI::success("Made {$total} replacements."); } } }
function print_cli_table($table_rows, $table_header = array(), $descr = NULL) { if (!is_array($table_rows)) { print_error("print_cli_table() argument {$table_rows} should be an array. Please report this error to developers."); return; } if (OBS_QUIET) { return; } if (!cli_is_piped() || OBS_DEBUG) { $count_rows = count($table_rows); if ($count_rows == 0) { return; } if (strlen($descr)) { print_cli_data($descr, '', 3); } $table = new \cli\Table(); $count_header = count($table_header); if ($count_header) { $table->setHeaders($table_header); } $table->setRows($table_rows); $table->display(); echo PHP_EOL; } else { print_cli_data("Notice", "Table output suppressed due to piped output." . PHP_EOL); } }
public function testTables() { $this->resetStreams(); $suffix = \cli\Shell::isPiped() ? "_piped" : ""; $this->assertTrue(is_numeric($columns = \cli\Shell::columns())); $headers = array('First Name', 'Last Name', 'City', 'State'); $data = array(array('Maryam', 'Elliott', 'Elizabeth City', 'SD'), array('Jerry', 'Washington', 'Bessemer', 'ME'), array('Allegra', 'Hopkins', 'Altoona', 'ME'), array('Audrey', 'Oneil', 'Dalton', 'SK')); $table = new \cli\Table(); $table->setRenderer(new \cli\table\Ascii()); $table->setHeaders($headers); $table->setRows($data); $table->display(); $output = $this->getStreams(); $this->assertEquals("", $output['errors']); $this->assertEquals(file_get_contents("test/output/table_1"), $output['contents']); $this->resetStreams(); $table->sort(1); $table->display(); $output = $this->getStreams(); $this->assertEquals("", $output['errors']); $this->assertEquals(file_get_contents("test/output/table_2"), $output['contents']); $this->resetStreams(); foreach ($data as $k => $v) { $data[$k] = array_combine(array("name", "surname", "city", "state"), $v); } $renderer = new \cli\table\Ascii(); $renderer->setCharacters(array("corner" => "x", "line" => "=", "border" => "!")); $table = new \cli\Table($data); $table->setRenderer($renderer); $table->sort("surname"); $table->display(); $output = $this->getStreams(); $this->assertEquals("", $output['errors']); $this->assertEquals(file_get_contents("test/output/table_3"), $output['contents']); $this->assertEquals("[0m", \cli\Colors::color("reset")); $this->assertEquals("foo\tbar", \cli\table\Tabular::row(array("foo", "bar"))); $this->assertNull(\cli\table\Tabular::border()); // test output $this->resetStreams(); \cli\out(" \\cli\\out sends output to STDOUT\n"); \cli\out(" It does not automatically append a new line\n"); \cli\out(" It does accept any number of %s which are then %s to %s for formatting\n", 'arguments', 'passed', 'sprintf'); \cli\out(" Alternatively, {:a} can use an {:b} as the second argument.\n\n", array('a' => 'you', 'b' => 'array')); \cli\err(' \\cli\\err sends output to STDERR'); \cli\err(' It does automatically append a new line'); \cli\err(' It does accept any number of %s which are then %s to %s for formatting', 'arguments', 'passed', 'sprintf'); \cli\err(" Alternatively, {:a} can use an {:b} as the second argument.\n", array('a' => 'you', 'b' => 'array')); \cli\line(' \\cli\\line forwards to \\cli\\out for output'); \cli\line(' It does automatically append a new line'); \cli\line(' It does accept any number of %s which are then %s to %s for formatting', 'arguments', 'passed', 'sprintf'); \cli\line(" Alternatively, {:a} can use an {:b} as the second argument.\n", array('a' => 'you', 'b' => 'array')); $output = $this->getStreams(); $this->assertEquals(file_get_contents("test/output/out_errors"), $output['errors']); $this->assertEquals(file_get_contents("test/output/out_contents"), $output['contents']); $string = ""; $string .= \cli\render(' \\cli\\err sends output to STDERR' . "\n"); $string .= \cli\render(' It does automatically append a new line' . "\n"); $string .= \cli\render(' It does accept any number of %s which are then %s to %s for formatting' . "\n", 'arguments', 'passed', 'sprintf'); $string .= \cli\render(" Alternatively, {:a} can use an {:b} as the second argument.\n\n", array('a' => 'you', 'b' => 'array')); $this->assertEquals(file_get_contents("test/output/out_errors"), $string); $this->resetStreams(); $in = tmpfile(); fputs($in, "quit\n"); fseek($in, 0); \cli\Streams::setStream("in", $in); $line = \cli\prompt("prompt", false, "# "); $output = $this->getStreams(); $this->assertEquals("quit", $line); $this->assertEquals("", $output['errors']); $this->assertEquals("prompt# ", $output['contents']); fseek($in, 0); $this->assertEquals("quit", \cli\input()); fclose($in); }
/** * Search/replace strings in the database. * * ## DESCRIPTION * * This command will go through all rows in all tables and will replace all * appearances of the old string with the new one. * * It will correctly handle serialized values, and will not change primary key values. * * ## OPTIONS * * <old> * : The old string. * * <new> * : The new string. * * [<table>...] * : List of database tables to restrict the replacement to. * * [--network] * : Search/replace through all the tables in a multisite install. * * [--skip-columns=<columns>] * : Do not perform the replacement in the comma-separated columns. * * [--dry-run] * : Show report, but don't perform the changes. * * [--precise] * : Force the use of PHP (instead of SQL) which is more thorough, but slower. Use if you see issues with serialized data. * * [--recurse-objects] * : Enable recursing into objects to replace strings * * ## EXAMPLES * * wp search-replace 'http://example.dev' 'http://example.com' --skip-columns=guid * * wp search-replace 'foo' 'bar' wp_posts wp_postmeta wp_terms --dry-run */ public function __invoke($args, $assoc_args) { global $wpdb; $old = array_shift($args); $new = array_shift($args); $total = 0; $report = array(); $dry_run = isset($assoc_args['dry-run']); $php_only = isset($assoc_args['precise']); $recurse_objects = isset($assoc_args['recurse-objects']); if (isset($assoc_args['skip-columns'])) { $skip_columns = explode(',', $assoc_args['skip-columns']); } else { $skip_columns = array(); } // never mess with hashed passwords $skip_columns[] = 'user_pass'; $tables = self::get_table_list($args, isset($assoc_args['network'])); foreach ($tables as $table) { list($primary_keys, $columns) = self::get_columns($table); // since we'll be updating one row at a time, // we need a primary key to identify the row if (empty($primary_keys)) { $report[] = array($table, '', 'skipped'); continue; } foreach ($columns as $col) { if (in_array($col, $skip_columns)) { continue; } if (!$php_only) { $serialRow = $wpdb->get_row("SELECT * FROM `{$table}` WHERE `{$col}` REGEXP '^[aiO]:[1-9]' LIMIT 1"); } if ($php_only || NULL !== $serialRow) { $type = 'PHP'; $count = self::php_handle_col($col, $primary_keys, $table, $old, $new, $dry_run, $recurse_objects); } else { $type = 'SQL'; $count = self::sql_handle_col($col, $table, $old, $new, $dry_run); } $report[] = array($table, $col, $count, $type); $total += $count; } } if (!WP_CLI::get_config('quiet')) { $table = new \cli\Table(); $table->setHeaders(array('Table', 'Column', 'Replacements', 'Type')); $table->setRows($report); $table->display(); if (!$dry_run) { WP_CLI::success("Made {$total} replacements."); } } }
/** * Search/replace strings in the database. * * ## DESCRIPTION * * This command will go through all rows in a selection of tables * and will replace all appearances of the old string with the new one. The * default tables are those registered on the $wpdb object (usually * just WordPress core tables). * * It will correctly handle serialized values, and will not change primary key values. * * ## OPTIONS * * <old> * : The old string. * * <new> * : The new string. * * [<table>...] * : List of database tables to restrict the replacement to. Wildcards are supported, e.g. wp_\*_options or wp_post\?. * * [--network] * : Search/replace through all the tables in a multisite install. * * [--skip-columns=<columns>] * : Do not perform the replacement in the comma-separated columns. * * [--dry-run] * : Show report, but don't perform the changes. * * [--precise] * : Force the use of PHP (instead of SQL) which is more thorough, but slower. Use if you see issues with serialized data. * * [--recurse-objects] * : Enable recursing into objects to replace strings. Defaults to true; pass --no-recurse-objects to disable. * * [--all-tables-with-prefix] * : Enable replacement on any tables that match the table prefix even if not registered on wpdb * * [--all-tables] * : Enable replacement on ALL tables in the database, regardless of the prefix, and even if not registered on $wpdb. Overrides --network and --all-tables-with-prefix. * * [--verbose] * : Prints rows to the console as they're updated. * * [--regex] * : Runs the search using a regular expression. Warning: search-replace will take about 15-20x longer when using --regex. * * ## EXAMPLES * * wp search-replace 'http://example.dev' 'http://example.com' --skip-columns=guid * * wp search-replace 'foo' 'bar' wp_posts wp_postmeta wp_terms --dry-run * * # Turn your production database into a local database * wp search-replace --url=example.com example.com example.dev wp_\*_options */ public function __invoke($args, $assoc_args) { global $wpdb; $old = array_shift($args); $new = array_shift($args); $total = 0; $report = array(); $dry_run = \WP_CLI\Utils\get_flag_value($assoc_args, 'dry-run'); $php_only = \WP_CLI\Utils\get_flag_value($assoc_args, 'precise'); $recurse_objects = \WP_CLI\Utils\get_flag_value($assoc_args, 'recurse-objects', true); $verbose = \WP_CLI\Utils\get_flag_value($assoc_args, 'verbose'); $regex = \WP_CLI\Utils\get_flag_value($assoc_args, 'regex'); $skip_columns = explode(',', \WP_CLI\Utils\get_flag_value($assoc_args, 'skip-columns')); if ($old === $new && !$regex) { WP_CLI::warning("Replacement value '{$old}' is identical to search value '{$new}'. Skipping operation."); exit; } // never mess with hashed passwords $skip_columns[] = 'user_pass'; // Determine how to limit the list of tables. Defaults to 'wordpress' $table_type = 'wordpress'; if (\WP_CLI\Utils\get_flag_value($assoc_args, 'network')) { $table_type = 'network'; } if (\WP_CLI\Utils\get_flag_value($assoc_args, 'all-tables-with-prefix')) { $table_type = 'all-tables-with-prefix'; } if (\WP_CLI\Utils\get_flag_value($assoc_args, 'all-tables')) { $table_type = 'all-tables'; } if (!empty($args)) { $new_tables = array(); foreach ($args as $key => $table) { if (false !== strpos($table, '*') || false !== strpos($table, '?')) { $expanded_tables = self::get_tables_for_glob($table); if (empty($expanded_tables)) { WP_CLI::error("Couldn't find any tables matching: {$table}"); } $new_tables = array_merge($new_tables, $expanded_tables); } else { $new_tables[] = $table; } } $args = $new_tables; } // Get the array of tables to work with. If there is anything left in $args, assume those are table names to use $tables = empty($args) ? self::get_table_list($table_type) : $args; foreach ($tables as $table) { list($primary_keys, $columns) = self::get_columns($table); // since we'll be updating one row at a time, // we need a primary key to identify the row if (empty($primary_keys)) { $report[] = array($table, '', 'skipped'); continue; } foreach ($columns as $col) { if (in_array($col, $skip_columns)) { continue; } if (!$php_only) { $serialRow = $wpdb->get_row("SELECT * FROM `{$table}` WHERE `{$col}` REGEXP '^[aiO]:[1-9]' LIMIT 1"); } if ($php_only || $regex || NULL !== $serialRow) { $type = 'PHP'; $count = self::php_handle_col($col, $primary_keys, $table, $old, $new, $dry_run, $recurse_objects, $verbose, $regex); } else { $type = 'SQL'; $count = self::sql_handle_col($col, $table, $old, $new, $dry_run, $verbose); } $report[] = array($table, $col, $count, $type); $total += $count; } } if (!WP_CLI::get_config('quiet')) { $table = new \cli\Table(); $table->setHeaders(array('Table', 'Column', 'Replacements', 'Type')); $table->setRows($report); $table->display(); if (!$dry_run) { $success_message = "Made {$total} replacements."; if ($total && 'Default' !== WP_CLI\Utils\wp_get_cache_type()) { $success_message .= ' Please remember to flush your persistent object cache with `wp cache flush`.'; } WP_CLI::success($success_message); } } }
/** * Search/replace strings in the database. * * ## DESCRIPTION * * This command will go through all rows in a selection of tables * and will replace all appearances of the old string with the new one. The * default tables are those registered on the $wpdb object (usually * just WordPress core tables). * * It will correctly handle serialized values, and will not change primary key values. * * ## OPTIONS * * <old> * : The old string. * * <new> * : The new string. * * [<table>...] * : List of database tables to restrict the replacement to. Wildcards are supported, e.g. wp_\*_options or wp_post\?. * * [--network] * : Search/replace through all the tables in a multisite install. * * [--skip-columns=<columns>] * : Do not perform the replacement in the comma-separated columns. * * [--dry-run] * : Show report, but don't perform the changes. * * [--precise] * : Force the use of PHP (instead of SQL) which is more thorough, but slower. Use if you see issues with serialized data. * * [--recurse-objects] * : Enable recursing into objects to replace strings. Defaults to true; pass --no-recurse-objects to disable. * * [--all-tables-with-prefix] * : Enable replacement on any tables that match the table prefix even if not registered on wpdb * * [--all-tables] * : Enable replacement on ALL tables in the database, regardless of the prefix, and even if not registered on $wpdb. Overrides --network and --all-tables-with-prefix. * * [--verbose] * : Prints rows to the console as they're updated. * * [--regex] * : Runs the search using a regular expression. Warning: search-replace will take about 15-20x longer when using --regex. * * ## EXAMPLES * * wp search-replace 'http://example.dev' 'http://example.com' --skip-columns=guid * * wp search-replace 'foo' 'bar' wp_posts wp_postmeta wp_terms --dry-run * * # Turn your production database into a local database * wp search-replace --url=example.com example.com example.dev wp_\*_options */ public function __invoke($args, $assoc_args) { global $wpdb; $old = array_shift($args); $new = array_shift($args); $total = 0; $report = array(); $dry_run = \WP_CLI\Utils\get_flag_value($assoc_args, 'dry-run'); $php_only = \WP_CLI\Utils\get_flag_value($assoc_args, 'precise'); $recurse_objects = \WP_CLI\Utils\get_flag_value($assoc_args, 'recurse-objects', true); $verbose = \WP_CLI\Utils\get_flag_value($assoc_args, 'verbose'); $regex = \WP_CLI\Utils\get_flag_value($assoc_args, 'regex'); $skip_columns = explode(',', \WP_CLI\Utils\get_flag_value($assoc_args, 'skip-columns')); if ($old === $new && !$regex) { WP_CLI::warning("Replacement value '{$old}' is identical to search value '{$new}'. Skipping operation."); exit; } // never mess with hashed passwords $skip_columns[] = 'user_pass'; // Get table names based on leftover $args or supplied $assoc_args $tables = \WP_CLI\Utils\wp_get_table_names($args, $assoc_args); foreach ($tables as $table) { list($primary_keys, $columns) = self::get_columns($table); // since we'll be updating one row at a time, // we need a primary key to identify the row if (empty($primary_keys)) { $report[] = array($table, '', 'skipped'); continue; } foreach ($columns as $col) { if (in_array($col, $skip_columns)) { continue; } if ($verbose) { $this->start_time = microtime(true); WP_CLI::log(sprintf('Checking: %s.%s', $table, $col)); } if (!$php_only) { $serialRow = $wpdb->get_row("SELECT * FROM `{$table}` WHERE `{$col}` REGEXP '^[aiO]:[1-9]' LIMIT 1"); } if ($php_only || $regex || NULL !== $serialRow) { $type = 'PHP'; $count = $this->php_handle_col($col, $primary_keys, $table, $old, $new, $dry_run, $recurse_objects, $verbose, $regex); } else { $type = 'SQL'; $count = $this->sql_handle_col($col, $table, $old, $new, $dry_run, $verbose); } $report[] = array($table, $col, $count, $type); $total += $count; } } if (!WP_CLI::get_config('quiet')) { $table = new \cli\Table(); $table->setHeaders(array('Table', 'Column', 'Replacements', 'Type')); $table->setRows($report); $table->display(); if (!$dry_run) { $success_message = "Made {$total} replacements."; if ($total && 'Default' !== WP_CLI\Utils\wp_get_cache_type()) { $success_message .= ' Please remember to flush your persistent object cache with `wp cache flush`.'; } WP_CLI::success($success_message); } } }
/** * Output user info in console * @param \stdClass $user */ public static function displayUser($user) { \cli\line('%_' . $user->nick . '%n ' . $user->email . ' (#' . $user->id . ')'); if (!empty($user->meta)) { $metaData = array(); foreach ($user->meta as $name => $val) { if (is_bool($val)) { $val = '%Wbool(' . ($val ? 'true' : 'false') . ')%n'; } elseif (is_array($val)) { $val = 'ARRAY: ' . json_encode($val) . ')'; } elseif ($val instanceof \stdClass) { $val = 'OBJECT: ' . json_encode((array) $val) . ')'; } if (strlen($val) > 70) { $val = substr($val, 0, 70) . '...'; } $metaData[] = array($name, $val); } $table = new \cli\Table(); $table->setHeaders(array('Meta name', 'Meta value')); $table->setRows($metaData); $table->display(); } }