/** * Migrate meta values to taxonomy terms. Delete meta after import * * ## OPTIONS * * <meta-key> * : Meta key to convert * * <taxonomy-slug> * : Taxonomy to move values into * * [--<field>=<value>] * : One or more args to pass to WP_Query. * * ## EXAMPLES * * wp mtt migrate meta_key taxonomy_slug * wp mtt migrate meta_key taxonomy_slug --posts_per_page=200 --paged=2 * */ function migrate($args, $assoc_args) { list($meta_key, $taxonomy) = $args; if (!($taxonomy_object = get_taxonomy($taxonomy))) { WP_CLI::error(sprintf("The taxonomy '%s' doesn't exist", $taxonomy)); } $defaults = array('post_type' => $taxonomy_object->object_type, 'posts_per_page' => -1, 'post_status' => 'any'); $query_args = array_merge($defaults, $assoc_args); $query = new WP_Query($query_args); // summary WP_CLI::log(sprintf("---\nPer page: %d \nPage: %d \nTotal pages: %d\n---", $query_args['posts_per_page'], isset($query_args['paged']) ? $query_args['paged'] : 1, $query->max_num_pages)); while ($query->have_posts()) { $query->the_post(); $id = get_the_id(); // get meta $metas = get_post_meta($id, $meta_key); // create term if (!$metas) { WP_CLI::log(WP_CLI::colorize("%c[{$id}]%n No meta, skipped")); } else { if (!is_wp_error(wp_set_object_terms($id, $metas, $taxonomy, true))) { WP_CLI::log(WP_CLI::colorize("%g[{$id}]%n Migrated: " . implode(', ', $metas))); // clean meta delete_post_meta($id, $meta_key); } else { WP_CLI::log(WP_CLI::colorize("%r[{$id}]%n Error: Could not set terms for post")); } } } }
/** * Grant super-admin privileges to one or more users. * * <user>... * : One or more user IDs, user emails, or user logins. */ public function add($args, $_) { $users = $this->fetcher->get_many($args); $user_logins = wp_list_pluck($users, 'user_login'); $super_admins = self::get_admins(); $num_super_admins = count($super_admins); foreach ($user_logins as $user_login) { $user = get_user_by('login', $user_login); if (!$user) { WP_CLI::warning("Couldn't find {$user_login} user."); continue; } if (in_array($user->user_login, $super_admins)) { WP_CLI::warning("User {$user_login} already has super-admin capabilities."); continue; } $super_admins[] = $user->user_login; } if ($num_super_admins === count($super_admins)) { WP_CLI::log('No changes.'); } else { if (update_site_option('site_admins', $super_admins)) { WP_CLI::success('Granted super-admin capabilities.'); } else { WP_CLI::error('Site options update failed!'); } } }
/** * Forces a full Varnish Purge of the entire site (provided * regex is supported). * * ## EXAMPLES * * wp varnish purge * * wp varnish purge http://example.com/wp-content/themes/twentyeleventy/style.css * * wp vanrish purge "/wp-content/themes/twentysixty/style.css" * * wp varnish purge http://example.com/wp-content/themes/ --wildcard * * wp varnish purge "/wp-content/themes/" --wildcard * */ function purge($args, $assoc_args) { $wp_version = get_bloginfo('version'); $cli_version = WP_CLI_VERSION; // Set the URL/path list($url) = $args; // If wildcard is set, or the URL argument is empty // then treat this as a full purge if (isset($assoc_args['wildcard']) || empty($url)) { $pregex = '/?vhp-regex'; $wild = ".*"; } else { $pregex = $wild = ''; } wp_create_nonce('vhp-flush-cli'); // Make sure the URL is a URL: if (!empty($url)) { // If the URL isn't a URL, make it a URL if (empty(esc_url($url))) { $url = $this->varnish_purge->the_home_url() . $url; } } else { $url = $this->varnish_purge->the_home_url(); } if (version_compare($wp_version, '4.6', '>=') && (version_compare($cli_version, '0.25.0', '<') || version_compare($cli_version, '0.25.0-alpha', 'eq'))) { WP_CLI::log(sprintf('This plugin does not work on WP 4.6 and up, unless WP-CLI is version 0.25.0 or greater. You\'re using WP-CLI %s and WordPress %s.', $cli_version, $wp_version)); WP_CLI::log('To flush your cache, please run the following command:'); WP_CLI::log(sprintf('$ curl -X PURGE "%s"', $url . $wild)); WP_CLI::error('Varnish Cache must be purged manually.'); } $this->varnish_purge->purgeUrl($url . $pregex); WP_CLI::success('The Varnish cache was purged.'); }
/** * Import content from a WXR file. * * ## OPTIONS * * <file>... * : Path to one or more valid WXR files for importing. * * --authors=<authors> * : How the author mapping should be handled. Options are 'create', 'mapping.csv', or 'skip'. The first will create any non-existent users from the WXR file. The second will read author mapping associations from a CSV, or create a CSV for editing if the file path doesn't exist. The CSV requires two columns, and a header row like "old_user_login,new_user_login". The last option will skip any author mapping. * * [--skip=<data-type>] * : Skip importing specific data. Supported options are: 'attachment' and 'image_resize' (skip time-consuming thumbnail generation). */ public function __invoke($args, $assoc_args) { $defaults = array('authors' => null, 'skip' => array()); $assoc_args = wp_parse_args($assoc_args, $defaults); if (!is_array($assoc_args['skip'])) { $assoc_args['skip'] = explode(',', $assoc_args['skip']); } $importer = $this->is_importer_available(); if (is_wp_error($importer)) { WP_CLI::error($importer); } $this->add_wxr_filters(); WP_CLI::log('Starting the import process...'); foreach ($args as $file) { if (!is_readable($file)) { WP_CLI::warning("Can't read {$file} file."); } $ret = $this->import_wxr($file, $assoc_args); if (is_wp_error($ret)) { WP_CLI::warning($ret); } else { WP_CLI::line(); // WXR import ends with HTML, so make sure message is on next line WP_CLI::success("Finished importing from {$file} file."); } } }
/** * Fixes issues with slow saving in wp-admin due to no audio/video media files * * Core Ticket: https://core.trac.wordpress.org/ticket/31071 * * eg.: `wp vip-go-one-time-fixers blank-media-fix --allow-root --url=beta.thesun.co.uk` * * @subcommand blank-media-fix */ public function blank_media_fix($args, $assoc_args) { if (!function_exists('wpcom_vip_download_image')) { WP_CLI::error('This script requires the wpcom_vip_download_image() function, https://vip.wordpress.com/functions/wpcom_vip_download_image/'); } $audio_file_url = 'https://cldup.com/xmre07YagX.mp3'; // 1sec.mp3 $video_file_url = 'https://cldup.com/KHsK5yZkvv.avi'; // 1sec.avi $args = array('post_type' => 'attachment', 'post_status' => 'inherit', 'meta_query' => array(array('key' => '_vip_blank_media_fix', 'value' => 'video'))); $video_query = new WP_Query($args); if (!$video_query->post_count) { WP_CLI::log('Video fix not found, applying...'); $video_file_id = $this->wpcom_vip_download_image($video_file_url, 0, 'VIP: Fix for slow post saving'); if (!is_wp_error($video_file_id)) { $args = array('ID' => $video_file_id, 'post_date' => '2000-01-01', 'post_date_gmt' => '2000-01-01', 'post_modified' => '2000-01-01', 'post_modified_gmt' => '2000-01-01'); $updated_video_file_id = wp_update_post($args, true); if (!is_wp_error($updated_video_file_id)) { WP_CLI::success('Video fix applied'); $video_meta = update_post_meta($updated_video_file_id, '_vip_blank_media_fix', 'video'); if (false === $video_meta) { WP_CLI::warning('Could not update video _vip_blank_media_fix meta'); } } else { // Video date was not updated WP_CLI::error($updated_video_file_id->get_error_message()); } } else { // Sideload failed WP_CLI::error($video_file_id->get_error_message()); } } else { WP_CLI::warning('Blank video fix already exists for this site'); } $args = array('post_type' => 'attachment', 'post_status' => 'inherit', 'meta_query' => array(array('key' => '_vip_blank_media_fix', 'value' => 'audio'))); $audio_query = new WP_Query($args); if (!$audio_query->post_count) { WP_CLI::log('Audio fix not found, applying...'); $audio_file_id = $this->wpcom_vip_download_image($audio_file_url, 0, 'VIP: Fix for slow post saving'); if (!is_wp_error($audio_file_id)) { $args = array('ID' => $audio_file_id, 'post_date' => '2000-01-01', 'post_date_gmt' => '2000-01-01', 'post_modified' => '2000-01-01', 'post_modified_gmt' => '2000-01-01'); $updated_audio_file_id = wp_update_post($args, true); if (!is_wp_error($updated_audio_file_id)) { WP_CLI::success('Audio fix applied'); $audio_meta = update_post_meta($updated_audio_file_id, '_vip_blank_media_fix', 'audio'); if (false === $audio_meta) { WP_CLI::warning('Could not update audio _vip_blank_media_fix meta'); } } else { // Audio date was not updated WP_CLI::error($updated_audio_file_id->get_error_message()); } } else { // Sideload failed WP_CLI::error($video_file_id->get_error_message()); } } else { WP_CLI::warning('Blank video fix already exists for this site'); } }
/** * * Assigns random terms to all posts in a taxonomy. * * By default all objects of the 'post' post type will be randomized, use the * --post_type flag to target pages or a custom post type. Use the --include * and --exclude flags to filter or ignore specific object IDs and the --before * and --after flags to specify a date range. Also, optionally pass --terms as * a list of terms you want to use for the randomization. If terms exist in the * target taxonomy, those terms will be used. If not, a string of 6 words * generated randomly will be used for the randomization. * * ## Options * * <taxonomy> * : The taxonomy that should get randomized * * ## Exmples * * wp randomize category * * @synopsis <taxonomy> [--include=<bar>] [--exclude=<foo>] [--post_type=<foo>] * [--before=<bar>] [--after=<date>] [--terms=<terms>] * **/ public function taxonomy($args, $assoc_args) { $taxonomy = $args[0]; $get_posts = $this->get_specified_posts($assoc_args); $message = $get_posts['message']; $posts = $get_posts['posts']; $args = $get_posts['args']; $preamble = "Will assign random {$taxonomy} terms"; print_r("{$preamble} {$message}.\n"); if (isset($assoc_args['terms'])) { $terms = explode(',', $assoc_args['terms']); \WP_CLI::log('Using terms ' . $assoc_args['terms']); } else { \WP_CLI::log('Gathering and processing random terms.'); $terms = $this->get_random_terms(); \WP_CLI::log('No term list given, using random terms.'); } foreach ($posts as $p) { $index = array_rand($terms); $term = $terms[$index]; \WP_CLI::log("Assigning {$term} to taxonomy {$taxonomy} for {$p->post_type} {$p->ID}"); if (!term_exists($term, $taxonomy)) { wp_insert_term($term, $taxonomy); } wp_set_object_terms($p->ID, $term, $taxonomy, $append = false); } }
/** * Setup Elasticsearch. * * ## OPTIONS * * [--host=<url>] * : The name of the person to greet. * * [--port=<number>] * : Accepted values: csv, json. Default: csv * * ## EXAMPLES * * wp elasticsearch setup --host=example.com --port=9200 * * @subcommand setup */ function setup($args, $assoc_args) { $param = array(); $param['endpoint'] = preg_replace('/(^https:\\/\\/|^http:\\/\\/)/is', '', $assoc_args['host']); $param['port'] = $assoc_args['port']; $tries = 5; $sleep = 3; do { $response = wp_remote_get(esc_url($assoc_args['host']) . ':' . $assoc_args['port']); if (200 == wp_remote_retrieve_response_code($response)) { // Looks good! break; } else { WP_CLI::log("\nInvalid response from ES, sleeping {$sleep} seconds and trying again...\n"); sleep($sleep); } } while (--$tries); if (200 != wp_remote_retrieve_response_code($response)) { WP_CLI::error('Could not connect to Elasticsearch server.'); exit; } update_option('wpels_settings', $param); try { if (!\MegumiTeam\WooCommerceElasticsearch\Loader::get_instance()->data_sync()) { WP_CLI::error('Elasticsearch built index failed.'); } } catch (Exception $e) { WP_CLI::error($e->getMessage()); exit; } WP_CLI::success("Elasticsearch built index completed."); }
function check_themes() { $themes = get_theme_updates(); if (!empty($themes)) { WP_CLI::success('Theme updates refreshed.'); } else { WP_CLI::log('Themes are up to date.'); } }
/** * List plugins a user has favorited in the WordPress.org plugins directory. * * ## OPTIONS * * <user> * : The username of the wordpress.org account whose favorite plugins you are listing. * * [--slug] * : Only return plugin slugs. Can be combined with `wp plugin install` (see examples). * * [--verbose] * : Display more information about the plugins. * * ## EXAMPLES * * wp plugin favorites matt * wp plugin favorites matt --verbose * wp plugin favorites matt --slug | xargs wp plugin install --activate * wp plugin favorites matt --slug | grep -vwE "(hello-dolly|bbpress)" | xargs wp plugin install --activate * * @synopsis <user> [--slug] [--verbose] */ public function __invoke($args, $assoc_args) { // prepare variables list($user) = $args; extract($assoc_args = wp_parse_args($assoc_args, array('slug' => false, 'verbose' => false))); // get access to plugins_api require_once ABSPATH . 'wp-admin/includes/plugin-install.php'; // query wordpress.org $api = plugins_api('query_plugins', array('user' => $user, 'fields' => array('last_updated' => true, 'active_installs' => true))); // only return slug? if ($slug) { foreach ($api->plugins as $plugin) { WP_CLI::log($plugin->slug); } return; } // get table columns $props = array('name', 'last_updated', 'rating', 'num_ratings', 'active_installs'); if ($verbose) { $props = array_merge($props, array('author', 'version', 'requires', 'tested', 'short_description')); } // pull object properties into an array $plugins = array(); foreach ($api->plugins as $plugin) { $args = array(); foreach ($props as $prop) { $args[$prop] = ''; if (isset($plugin->{$prop})) { $args[$prop] = $plugin->{$prop}; // clean up some fields for output switch ($prop) { case 'rating': $args[$prop] = (int) $args['rating'] / 100 * 5 . '/5'; break; case 'author': $args[$prop] = strip_tags($args['author']); break; case 'last_updated': $args[$prop] = date('Y-m-d', strtotime($args['last_updated'])); break; case 'active_installs': $args[$prop] = number_format($args['active_installs']); break; } } } $plugins[$plugin->slug] = $args; } if (!$plugins) { WP_CLI::log('No favorite plugins found.'); return; } // output as list table $formatter = new \WP_CLI\Formatter($assoc_args, $props, 'plugin'); $formatter->display_items($plugins); }
/** * List all cron events that are due now. * * ## EXAMPLES * * wp cron event wppaas list * * @subcommand list */ public function list_($args, $assoc_args) { $events = static::get_cron_events_due_now(); if (!is_wp_error($events) && $events) { $hooks = wp_list_pluck($events, 'hook'); WP_CLI::log(sprintf('There are %d cron event(s) due now: %s', count($hooks), implode(', ', $hooks))); return; } WP_CLI::warning('No cron events are due.'); }
/** * See Status of a working job * * @param $args * @param $assoc_args */ public function working($args, $assoc_args) { $job_object = BackWPup_Job::get_working_data(); if (!is_object($job_object)) { WP_CLI::error(__('No job running', 'backwpup')); } $formatter_args = array('format' => 'table', 'fields' => array('JobID', 'Name', 'Warnings', 'Errors', 'On Step', 'Done'), 'field' => NULL); $formatter = new WP_CLI\Formatter($formatter_args); $items = array(); $items[] = array('JobID' => $job_object->job['jobid'], 'Name' => $job_object->job['name'], 'Warnings' => $job_object->warnings, 'Errors' => $job_object->errors, 'On Step' => $job_object->steps_data[$job_object->step_working]['NAME'], 'Done' => $job_object->step_percent . ' / ' . $job_object->substep_percent, 'Last message' => str_replace('…', '...', strip_tags($job_object->lastmsg))); $formatter->display_items($items); WP_CLI::log('Last Message: ' . str_replace('…', '...', strip_tags($job_object->lastmsg))); }
/** * Export content to a WXR file. * * ## OPTIONS * * [--dir=<dirname>] * : Full path to directory where WXR export files should be stored. Defaults * to current working directory. * * [--skip_comments] * : Don't export comments. * * [--max_file_size=<MB>] * : A single export file should have this many megabytes. * * ## FILTERS * * [--start_date=<date>] * : Export only posts newer than this date, in format YYYY-MM-DD. * * [--end_date=<date>] * : Export only posts older than this date, in format YYYY-MM-DD. * * [--post_type=<post-type>] * : Export only posts with this post_type. * * [--post__in=<pid>] * : Export all posts specified as a comma-separated list of IDs. * * [--author=<author>] * : Export only posts by this author. Can be either user login or user ID. * * [--category=<name>] * : Export only posts in this category. * * [--post_status=<status>] * : Export only posts with this status. * * ## EXAMPLES * * wp export --dir=/tmp/ --user=admin --post_type=post --start_date=2011-01-01 --end_date=2011-12-31 * * wp export --dir=/tmp/ --post__in=123,124,125 */ public function __invoke($_, $assoc_args) { $defaults = array('dir' => NULL, 'start_date' => NULL, 'end_date' => NULL, 'post_type' => NULL, 'author' => NULL, 'category' => NULL, 'post_status' => NULL, 'post__in' => NULL, 'skip_comments' => NULL, 'max_file_size' => 15); $this->validate_args(wp_parse_args($assoc_args, $defaults)); if (!function_exists('wp_export')) { self::load_export_api(); } WP_CLI::log('Starting export process...'); add_action('wp_export_new_file', function ($file_path) { WP_CLI::log(sprintf("Writing to file %s", $file_path)); }); wp_export(array('filters' => $this->export_args, 'writer' => 'WP_Export_Split_Files_Writer', 'writer_args' => array('max_file_size' => $this->max_file_size * MB_IN_BYTES, 'destination_directory' => $this->wxr_path, 'filename_template' => self::get_filename_template()))); WP_CLI::success('All done with export.'); }
/** * @param string $level * @param string $message * @param array $context * * @return void */ public function log($level, $message, array $context = array()) { switch ($level) { case LogLevel::WARNING: \WP_CLI::warning($message); break; case LogLevel::ERROR: case LogLevel::ALERT: case LogLevel::EMERGENCY: case LogLevel::CRITICAL: \WP_CLI::error($message); break; default: \WP_CLI::log($message); } }
public function __invoke() { $sets = GP::$translation_set->all(); foreach ($sets as $set) { /* translators: %d: Set ID */ WP_CLI::log(sprintf(__('Processing set #%d..', 'glotpress'), $set->id)); $translations = GP::$translation->find(array('translation_set_id' => $set->id, 'status' => 'current'), 'original_id ASC'); $prev_original_id = null; foreach ($translations as $translation) { if ($translation->original_id == $prev_original_id) { WP_CLI::warning(sprintf(__('Duplicate with original_id #%1$d. Translation #%2$d', 'glotpress'), $prev_original_id, $translation->id)); $translation->delete(); } $prev_original_id = $translation->original_id; } } WP_CLI::success('Multiple currents are cleaned up.'); }
function feedback($string) { if (isset($this->upgrader->strings[$string])) { $string = $this->upgrader->strings[$string]; } if (strpos($string, '%') !== false) { $args = func_get_args(); $args = array_splice($args, 1); if (!empty($args)) { $string = vsprintf($string, $args); } } if (empty($string)) { return; } $string = str_replace('…', '...', strip_tags($string)); \WP_CLI::log($string); }
/** * Switch terms from one taxonomy to another. * * ## OPTIONS * * --from=<taxonomy> * : The Taxonomy to switch from. * * --to=<taxonomy> * : The Taxonomy to switch to. * * [--parent=<parent>] * : The term parent to limit by. * * [--terms=<terms>] * : Comma separated list of term ids to switch. * * ## EXAMPLES * * wp taxonomy-switcher convert --from=category --to=post_tag * wp taxonomy-switcher convert --from=category --to=post_tag --parent=123 * wp taxonomy-switcher convert --from=category --to=post_tag --terms=1,2,13 * * @synopsis --from=<taxonomy> --to=<taxonomy> [--parent=<parent>] [--terms=<terms>] */ public function convert($args, $assoc_args) { $args = $this->map_arg_names($assoc_args); $tax_switcher = new Taxonomy_Switcher($this->map_arg_names($assoc_args)); $count = $tax_switcher->count(); if (!$count) { WP_CLI::error($tax_switcher->notices('no_terms')); } WP_CLI::log($tax_switcher->notices('switching')); if (0 < $tax_switcher->parent) { WP_CLI::log($tax_switcher->notices('limit_by_parent')); } if (!empty($tax_switcher->terms)) { WP_CLI::log($tax_switcher->notices('limit_by_terms')); } set_time_limit(0); $tax_switcher->convert(); WP_CLI::success($tax_switcher->notices('switched')); }
/** * Get a list of product categories. * * ## OPTIONS * * [--format=<format>] * : Accepted values: table, csv, json, count. Default: table * * ## EXAMPLES * * wp wpsc-category list * * wp wpsc-category list --format=csv * * @subcommand list * @synopsis */ function list_($args, $assoc_args) { $formatter = $this->get_formatter($assoc_args); $args = array('number' => 0, 'orderby' => 'name', 'order' => 'ASC', 'fields' => 'all', 'hide_empty' => false); if ('ids' == $formatter->format) { $args['fields'] = 'ids'; } $terms = get_terms('wpsc_product_category', $args); if (is_wp_error($terms)) { WP_CLI::error(__("Couldn't retrieve categories.", 'wpsc')); } elseif (!count($terms)) { WP_CLI::log(__('No categories found.', 'wpsc')); } if ('ids' == $formatter->format) { echo implode(' ', $terms); } else { $formatter->display_items($terms); } }
/** * Migrate post content from <img> tags to image shortcodes. * * ## OPTIONS * * <id>... * : One or more IDs of posts to update. * * [--dry-run] * : Only show the content which is to be changed, don't update posts. * * ## EXAMPLES * * ## Migrate all Posts to the Image Shortcake syntax * wp image-shortcake-shortcode migrate `wp post list --post_type=post` --ids` * * ## Converts images to shortcodes on one post, preserving a log to rollback in case of errors. * wp image-shortcake migrate 123 > potential-oops.txt * * * @synopsis <id>... [--dry-run] */ public function migrate($args, $assoc_args) { foreach (array_filter($args) as $post_ID) { $post = $this->fetcher->get_check($post_ID); $_content = $post->post_content; $caption_replacements = Img_Shortcode_Data_Migration::find_caption_shortcodes_for_replacement($_content); $_content = str_replace(array_keys($caption_replacements), array_values($caption_replacements), $_content); $img_tag_replacements = Img_Shortcode_Data_Migration::find_img_tags_for_replacement($_content); $_content = str_replace(array_keys($img_tag_replacements), array_values($img_tag_replacements), $_content); $replacements = array_merge((array) $caption_replacements, (array) $img_tag_replacements); WP_CLI::log(''); if (0 === count($replacements)) { WP_CLI::log('Nothing to replace on post ' . $post->ID . '. Skipping.'); WP_CLI::log(''); continue; } $header = 'Image shortcode replacements for post ' . $post->ID; WP_CLI::log($header); WP_CLI::log(str_repeat('=', strlen($header))); WP_CLI::log(''); foreach ($replacements as $del => $ins) { \WP_CLI::log(\cli\Colors::colorize('%C-%n') . $del, true); \WP_CLI::log(\cli\Colors::colorize('%G+%n') . $ins, true); } WP_CLI::log(''); if (isset($assoc_args['dry-run'])) { WP_CLI::log('Post not updated: --dry-run specifed.'); WP_CLI::log(''); continue; } global $wpdb; // @codingStandardsIgnoreStart $updated = $wpdb->update($wpdb->posts, array('post_content' => $_content), array('ID' => $post_ID)); // @codingStandardsIgnoreEnd if (1 === $updated) { clean_post_cache($post); WP_CLI::success('Updated post ' . $post->ID . '.'); } else { WP_CLI::warning('There was an unexpected error updating post ' . $post->ID . '.'); } } }
/** * Runs all pending WooCommerce database updates. */ public static function update() { global $wpdb; $wpdb->hide_errors(); include_once WC_ABSPATH . 'includes/class-wc-install.php'; include_once WC_ABSPATH . 'includes/wc-update-functions.php'; $current_db_version = get_option('woocommerce_db_version'); $update_count = 0; foreach (WC_Install::get_db_update_callbacks() as $version => $update_callbacks) { if (version_compare($current_db_version, $version, '<')) { foreach ($update_callbacks as $update_callback) { WP_CLI::log(sprintf(__('Calling update function: %s', 'woocommerce'), $update_callback)); call_user_func($update_callback); $update_count++; } } } WC_Admin_Notices::remove_notice('update'); WP_CLI::success(sprintf(__('%1$d updates complete. Database version is %2$s', 'woocommerce'), absint($update_count), get_option('woocommerce_db_version'))); }
protected static function tgz($args, $assoc_args) { @(list($repo, $tag) = $args); // Get the tarball URL for the latest (or specified release) $url = sprintf("https://api.github.com/repos/%s/releases/%s", $repo, $tag ? "tags/{$tag}" : 'latest'); WP_CLI::debug("Querying for releases: {$url}"); $url = self::tarball_url($url, @$assoc_args['token']); // If no releases are available fail-back to a commitish if ($url) { WP_CLI::log("Found release: {$url}"); } else { $url = sprintf("https://api.github.com/repos/%s/tarball/%s", $repo, $tag ?: 'master'); } WP_CLI::debug("Fetching {$url}"); $tgz = self::fetch_tarball($url, @$assoc_args['token']); WP_CLI::debug("Fetched {$tgz}"); WP_CLI::debug("Converting {$tgz} to zip"); $zip = self::tgz_to_zip($repo, $tgz); WP_CLI::debug("Converted {$tgz} to {$zip}"); return array($url, $tgz, $zip); }
/** * List out all of the crons that can be run. * * ## EXAMPLES * * wp videopress list_crons */ public function list_crons() { $scheduler = VideoPress_Scheduler::init(); $crons = $scheduler->get_crons(); $schedules = wp_get_schedules(); if (count($crons) === 0) { WP_CLI::success(__('Found no available cron jobs.', 'jetpack')); } elseif (count($crons) === 1) { WP_CLI::success(__('Found 1 available cron job.', 'jetpack')); } else { WP_CLI::success(sprintf(__('Found %d available cron jobs.', 'jetpack'), count($crons))); } foreach ($crons as $cron_name => $cron) { $interval = isset($schedules[$cron['interval']]['display']) ? $schedules[$cron['interval']]['display'] : $cron['interval']; $runs_next = $scheduler->check_cron($cron_name); $status = $runs_next ? sprintf('Scheduled - Runs Next at %s GMT', gmdate('Y-m-d H:i:s', $runs_next)) : 'Not Scheduled'; WP_CLI::log('Name: ' . $cron_name); WP_CLI::log('Method: ' . $cron['method']); WP_CLI::log('Interval: ' . $interval); WP_CLI::log('Status: ' . $status); } }
/** * Find insecure images & update postmeta * * ## OPTIONS * * <site_id> : ID of the site * * ## EXAMPLES * * wp bu-ssl findimages --ssldebug * * @synopsis [--ssldebug] */ function findimages($args, $assoc_args) { global $wpdb; $postids = get_posts(array('post_type' => array('any'), 'nopaging' => true, 'cache_results' => false, 'update_post_meta_cache' => false, 'update_post_term_cache' => false, 'fields' => 'ids')); WP_CLI::log(sprintf("Scanning site #%d: Checking %d posts", get_current_blog_id(), count($postids))); $this->ssl->remove_all_postmeta(); if ($postids) { foreach ($postids as $id) { $post = get_post($id); $urls = $this->ssl->search_for_insecure_images_by_post($id); $debug = ''; if (isset($assoc_args['ssldebug'])) { $debug = "\n" . var_export($urls, true) . "\n"; } $this->ssl->do_update_postmeta($id, $urls); if (count($urls)) { WP_CLI::warning(sprintf("#%d '%s' - %d insecure image(s)", $id, $post->post_title, count($urls), get_permalink($post)) . $debug); } } WP_CLI::success(sprintf("%d posts scanned.", count($postids))); } }
/** * Theme activation * * ## OPTIONS * * [<theme>] * : The theme name to activate. Defaults to 'sage'. * * [--show-on-front=<page-type>] * : What to show on the front page. Options are: 'posts', 'page'. Default is 'page'. * * [--permalink-structure=<permalink-string>] * : Permalink structure. Default is '/%postname%/'. * * [--skip-navigation] * : Skip creating default Primary Navigation. * * ## EXAMPLES * * wp theme activation * wp theme activation --show-on-front=page --permalink-structure='/%year%/%postname%/' --skip-navigation * * @subcommand activation * @alias roots-activate */ public function activation($args = [], $options = []) { list($theme) = $args + ['sage']; $defaults = ['permalink-structure' => '/%postname%/', 'show-on-front' => 'page', 'skip-navigation' => false]; $options = wp_parse_args($options, $defaults); $options['skip-navigation'] = $options['skip-navigation'] || !!wp_get_nav_menu_object('Primary Navigation'); \WP_CLI::log('Activating theme and setting options'); $home_page_options = ['post_content' => 'Lorem Ipsum', 'post_status' => 'publish', 'post_title' => 'Home', 'post_type' => 'page']; parent::activate([$theme]); if ($home_page_id = wp_insert_post($home_page_options, false)) { \WP_CLI::run_command(['option', 'update', 'show_on_front', $options['show-on-front']]); \WP_CLI::run_command(['option', 'update', 'page_on_front', $home_page_id]); } if (!$options['skip-navigation'] && ($menu_id = wp_create_nav_menu('Primary Navigation'))) { $home_page_id && wp_update_nav_menu_item($menu_id, 0, ['menu-item-title' => $home_page_options['post_title'], 'menu-item-object' => $home_page_options['post_type'], 'menu-item-object-id' => $home_page_id, 'menu-item-type' => 'post_type', 'menu-item-status' => 'publish']); set_theme_mod('nav_menu_locations', ['primary_navigation' => $menu_id]); \WP_CLI::success('Primary Navigation created.'); } \WP_CLI::run_command(['rewrite', 'structure', $options['permalink-structure']]); \WP_CLI::run_command(['rewrite', 'flush']); \WP_CLI::success('Theme activated'); }
/** * Convert the NextGen Gallery Shortcodes in posts in this site into WordPress gallery shortcodes. * * ## OPTIONS * * ## EXAMPLES * * wp escape-ngg convert * */ public function convert() { $count = Escape_NextGen_Gallery::init()->count(); WP_CLI::log(sprintf('Processing %d posts with NextGen Gallery shortcodes', $count)); set_time_limit(0); $uploads = wp_upload_dir(); $baseurl = $uploads['baseurl']; $post_ids = Escape_NextGen_Gallery::init()->get_post_ids(); $progress = new \cli\progress\Bar('Progress', $count); foreach ($post_ids as $post_id) { $progress->tick(); Escape_NextGen_Gallery::init()->process_post($post_id); } $progress->finish(); foreach (Escape_NextGen_Gallery::init()->infos as $info) { WP_CLI::log($info); } foreach (Escape_NextGen_Gallery::init()->warnings as $warning) { WP_CLI::warning($warning); } $lines = array((object) array('Converted' => 'posts converted', 'Count' => Escape_NextGen_Gallery::init()->posts_count), (object) array('Converted' => 'images converted', 'Count' => Escape_NextGen_Gallery::init()->images_count)); $fields = array('Converted', 'Count'); \WP_CLI\Utils\format_items('table', $lines, $fields); }
/** * Recount the comment_count value for one or more posts. * * ## OPTIONS * * <id>... * : IDs for one or more posts to update. * * ## EXAMPLES * * $ wp comment recount 123 * Updated post 123 comment count to 67. */ public function recount($args) { foreach ($args as $id) { wp_update_comment_count($id); $post = get_post($id); if ($post) { WP_CLI::log(sprintf("Updated post %d comment count to %d.", $post->ID, $post->comment_count)); } else { WP_CLI::warning(sprintf("Post %d doesn't exist.", $post->ID)); } } }
/** * Import users from a CSV file. * * ## OPTIONS * * <file> * : The local or remote CSV file of users to import. * * [--send-email] * : Send an email to new users with their account details. * * [--skip-update] * : Don't update users that already exist. * * ## EXAMPLES * * # Import users from local CSV file * $ wp user import-csv /path/to/users.csv * Success: bobjones created * Success: newuser1 created * Success: existinguser created * * # Import users from remote CSV file * $ wp user import-csv http://example.com/users.csv * * Sample users.csv file: * * user_login,user_email,display_name,role * bobjones,bobjones@example.com,Bob Jones,contributor * newuser1,newuser1@example.com,New User,author * existinguser,existinguser@example.com,Existing User,administrator * * @subcommand import-csv */ public function import_csv($args, $assoc_args) { $blog_users = get_users(); $filename = $args[0]; if (0 === stripos($filename, 'http://') || 0 === stripos($filename, 'https://')) { $response = wp_remote_head($filename); $response_code = (string) wp_remote_retrieve_response_code($response); if (in_array($response_code[0], array(4, 5))) { WP_CLI::error("Couldn't access remote CSV file (HTTP {$response_code} response)."); } } else { if (!file_exists($filename)) { WP_CLI::error(sprintf("Missing file: %s", $filename)); } } foreach (new \WP_CLI\Iterators\CSV($filename) as $i => $new_user) { $defaults = array('role' => get_option('default_role'), 'user_pass' => wp_generate_password(), 'user_registered' => strftime("%F %T", time()), 'display_name' => false); $new_user = array_merge($defaults, $new_user); $secondary_roles = array(); if (!empty($new_user['roles'])) { $roles = array_map('trim', explode(',', $new_user['roles'])); $invalid_role = false; foreach ($roles as $role) { if (is_null(get_role($role))) { WP_CLI::warning("{$new_user['user_login']} has an invalid role."); $invalid_role = true; break; } } if ($invalid_role) { continue; } $new_user['role'] = array_shift($roles); $secondary_roles = $roles; } else { if ('none' === $new_user['role']) { $new_user['role'] = false; } elseif (is_null(get_role($new_user['role']))) { WP_CLI::warning("{$new_user['user_login']} has an invalid role."); continue; } } // User already exists and we just need to add them to the site if they aren't already there $existing_user = get_user_by('email', $new_user['user_email']); if (!$existing_user) { $existing_user = get_user_by('login', $new_user['user_login']); } if ($existing_user && \WP_CLI\Utils\get_flag_value($assoc_args, 'skip-update')) { WP_CLI::log("{$existing_user->user_login} exists and has been skipped."); continue; } else { if ($existing_user) { $new_user['ID'] = $existing_user->ID; $user_id = wp_update_user($new_user); if (!in_array($existing_user->user_login, wp_list_pluck($blog_users, 'user_login')) && is_multisite() && $new_user['role']) { add_user_to_blog(get_current_blog_id(), $existing_user->ID, $new_user['role']); WP_CLI::log("{$existing_user->user_login} added as {$new_user['role']}."); } // Create the user } else { unset($new_user['ID']); // Unset else it will just return the ID if (is_multisite()) { $ret = wpmu_validate_user_signup($new_user['user_login'], $new_user['user_email']); if (is_wp_error($ret['errors']) && !empty($ret['errors']->errors)) { WP_CLI::warning($ret['errors']); continue; } $user_id = wpmu_create_user($new_user['user_login'], $new_user['user_pass'], $new_user['user_email']); if (!$user_id) { WP_CLI::warning("Unknown error creating new user."); continue; } $new_user['ID'] = $user_id; $user_id = wp_update_user($new_user); if (is_wp_error($user_id)) { WP_CLI::warning($user_id); continue; } } else { $user_id = wp_insert_user($new_user); } if (\WP_CLI\Utils\get_flag_value($assoc_args, 'send-email')) { self::wp_new_user_notification($user_id, $new_user['user_pass']); } } } if (is_wp_error($user_id)) { WP_CLI::warning($user_id); continue; } else { if ($new_user['role'] === false) { delete_user_option($user_id, 'capabilities'); delete_user_option($user_id, 'user_level'); } } $user = get_user_by('id', $user_id); foreach ($secondary_roles as $secondary_role) { $user->add_role($secondary_role); } if (!empty($existing_user)) { WP_CLI::success($new_user['user_login'] . " updated."); } else { WP_CLI::success($new_user['user_login'] . " created."); } } }
protected function install_from_repo($slug, $assoc_args) { $api = themes_api('theme_information', array('slug' => $slug)); if (is_wp_error($api)) { return $api; } if (isset($assoc_args['version'])) { self::alter_api_response($api, $assoc_args['version']); } if (!isset($assoc_args['force']) && wp_get_theme($slug)->exists()) { // We know this will fail, so avoid a needless download of the package. return new WP_Error('already_installed', 'Theme already installed.'); } WP_CLI::log(sprintf('Installing %s (%s)', $api->name, $api->version)); if (!isset($assoc_args['version']) || 'dev' !== $assoc_args['version']) { WP_CLI::get_http_cache_manager()->whitelist_package($api->download_link, $this->item_type, $api->slug, $api->version); } $result = $this->get_upgrader($assoc_args)->install($api->download_link); return $result; }
protected function update_many($args, $assoc_args) { call_user_func($this->upgrade_refresh); if (!empty($assoc_args['format']) && in_array($assoc_args['format'], array('json', 'csv'))) { $logger = new \WP_CLI\Loggers\Quiet(); \WP_CLI::set_logger($logger); } if (!\WP_CLI\Utils\get_flag_value($assoc_args, 'all') && empty($args)) { \WP_CLI::error("Please specify one or more {$this->item_type}s, or use --all."); } $items = $this->get_item_list(); if (!\WP_CLI\Utils\get_flag_value($assoc_args, 'all')) { $items = $this->filter_item_list($items, $args); } $items_to_update = wp_list_filter($items, array('update' => true)); if (\WP_CLI\Utils\get_flag_value($assoc_args, 'dry-run')) { if (empty($items_to_update)) { \WP_CLI::line("No {$this->item_type} updates available."); return; } if (!empty($assoc_args['format']) && in_array($assoc_args['format'], array('json', 'csv'))) { \WP_CLI\Utils\format_items($assoc_args['format'], $items_to_update, array('name', 'status', 'version', 'update_version')); } else { if (!empty($assoc_args['format']) && 'summary' === $assoc_args['format']) { \WP_CLI::line("Available {$this->item_type} updates:"); foreach ($items_to_update as $item_to_update => $info) { \WP_CLI::log("{$info['title']} update from version {$info['version']} to version {$info['update_version']}"); } } else { \WP_CLI::line("Available {$this->item_type} updates:"); \WP_CLI\Utils\format_items('table', $items_to_update, array('name', 'status', 'version', 'update_version')); } } return; } $result = array(); // Only attempt to update if there is something to update if (!empty($items_to_update)) { $cache_manager = \WP_CLI::get_http_cache_manager(); foreach ($items_to_update as $item) { $cache_manager->whitelist_package($item['update_package'], $this->item_type, $item['name'], $item['update_version']); } $upgrader = $this->get_upgrader($assoc_args); $result = $upgrader->bulk_upgrade(wp_list_pluck($items_to_update, 'update_id')); } // Let the user know the results. $num_to_update = count($items_to_update); $num_updated = count(array_filter($result)); $line = "Updated {$num_updated}/{$num_to_update} {$this->item_type}s."; if ($num_to_update == $num_updated) { \WP_CLI::success($line); } else { if ($num_updated > 0) { \WP_CLI::warning($line); } else { \WP_CLI::error($line); } } if ($num_to_update > 0) { if (!empty($assoc_args['format']) && 'summary' === $assoc_args['format']) { foreach ($items_to_update as $item_to_update => $info) { $message = $result[$info['update_id']] !== null ? 'updated successfully' : 'did not update'; \WP_CLI::log("{$info['title']} {$message} from version {$info['version']} to version {$info['update_version']}"); } } else { $status = array(); foreach ($items_to_update as $item_to_update => $info) { $status[$item_to_update] = array('name' => $info['name'], 'old_version' => $info['version'], 'new_version' => $info['update_version'], 'status' => $result[$info['update_id']] !== null ? 'Updated' : 'Error'); } $format = 'table'; if (!empty($assoc_args['format']) && in_array($assoc_args['format'], array('json', 'csv'))) { $format = $assoc_args['format']; } \WP_CLI\Utils\format_items($format, $status, array('name', 'old_version', 'new_version', 'status')); } } }
/** * Update WordPress. * * ## OPTIONS * * [<zip>] * : Path to zip file to use, instead of downloading from wordpress.org. * * [--version=<version>] * : Update to this version, instead of to the latest version. * * [--force] * : Update even when installed WP version is greater than the requested version. * * [--locale=<locale>] * : Select which language you want to download. * * ## EXAMPLES * * wp core update * * wp core update --version=3.8 ../latest.zip * * wp core update --version=3.1 --force * * @alias upgrade */ function update($args, $assoc_args) { global $wp_version; $update = $from_api = null; $upgrader = 'WP_CLI\\CoreUpgrader'; if (!empty($args[0])) { $upgrader = 'WP_CLI\\NonDestructiveCoreUpgrader'; $version = !empty($assoc_args['version']) ? $assoc_args['version'] : null; $update = (object) array('response' => 'upgrade', 'current' => $version, 'download' => $args[0], 'packages' => (object) array('partial' => null, 'new_bundled' => null, 'no_content' => null, 'full' => $args[0]), 'version' => $version, 'locale' => null); } else { if (empty($assoc_args['version'])) { wp_version_check(); $from_api = get_site_transient('update_core'); if (empty($from_api->updates)) { $update = false; } else { list($update) = $from_api->updates; } } else { if (version_compare($wp_version, $assoc_args['version'], '<') || isset($assoc_args['force'])) { $version = $assoc_args['version']; $locale = isset($assoc_args['locale']) ? $assoc_args['locale'] : get_locale(); $new_package = $this->get_download_url($version, $locale); $update = (object) array('response' => 'upgrade', 'current' => $assoc_args['version'], 'download' => $new_package, 'packages' => (object) array('partial' => null, 'new_bundled' => null, 'no_content' => null, 'full' => $new_package), 'version' => $version, 'locale' => $locale); } else { WP_CLI::success('WordPress is up to date.'); return; } } } require_once ABSPATH . 'wp-admin/includes/upgrade.php'; if ($update->version) { WP_CLI::log("Updating to version {$update->version} ({$update->locale})..."); } else { WP_CLI::log("Starting update..."); } $GLOBALS['wp_cli_update_obj'] = $update; $result = Utils\get_upgrader($upgrader)->upgrade($update); unset($GLOBALS['wp_cli_update_obj']); if (is_wp_error($result)) { $msg = WP_CLI::error_to_string($result); if ('up_to_date' != $result->get_error_code()) { WP_CLI::error($msg); } else { WP_CLI::success($msg); } } else { WP_CLI::success('WordPress updated successfully.'); } }
/** * Uninstall a WP-CLI package. * * ## OPTIONS * * <name> * : Name of the package to uninstall. * * ## EXAMPLES * * $ wp package uninstall wp-cli/server-command * Removing require statement from /home/person/.wp-cli/packages/composer.json * Deleting package directory /home/person/.wp-cli/packages/vendor/wp-cli/server-command * Regenerating Composer autoload. * Success: Uninstalled package. */ public function uninstall($args) { list($package_name) = $args; try { $composer = $this->get_composer(); } catch (Exception $e) { WP_CLI::error($e->getMessage()); } if (false === ($package = $this->get_installed_package_by_name($package_name))) { WP_CLI::error("Package not installed."); } $composer_json_obj = $this->get_composer_json(); // Remove the 'require' from composer.json $json_path = $composer_json_obj->getPath(); WP_CLI::log(sprintf('Removing require statement from %s', $json_path)); $composer_backup = file_get_contents($composer_json_obj->getPath()); $manipulator = new JsonManipulator($composer_backup); $manipulator->removeSubNode('require', $package_name); file_put_contents($composer_json_obj->getPath(), $manipulator->getContents()); try { $composer = $this->get_composer(); } catch (Exception $e) { WP_CLI::error($e->getMessage()); } // Set up the installer $install = Installer::create(new NullIO(), $composer); $install->setUpdate(true); // Installer class will only override composer.lock with this flag $install->setPreferSource(true); // Use VCS when VCS for easier contributions. WP_CLI::log('Removing package directories and regenerating autoloader...'); $res = false; try { $res = $install->run(); } catch (Exception $e) { WP_CLI::warning($e->getMessage()); } if (0 === $res) { WP_CLI::success("Uninstalled package."); } else { file_put_contents($composer_json_obj->getPath(), $composer_backup); WP_CLI::error("Package removal failed (Composer return code {$res})."); } }