/** * Execute arbitrary PHP code. * * ## OPTIONS * * <php-code> * : The code to execute, as a string. * * [--skip-wordpress] * : Execute code without loading WordPress. * * @when before_wp_load * * ## EXAMPLES * * $ wp eval 'echo WP_CONTENT_DIR;' * /var/www/wordpress/wp-content * * $ wp eval 'echo rand();' --skip-wordpress * 479620423 */ public function __invoke($args, $assoc_args) { if (null === \WP_CLI\Utils\get_flag_value($assoc_args, 'skip-wordpress')) { WP_CLI::get_runner()->load_wordpress(); } eval($args[0]); }
/** * Destroy a session for the given user. * * ## OPTIONS * * <user> * : User ID, user email, or user login. * * [<token>] * : The token of the session to destroy. Defaults to the most recently created session. * * [--all] * : Destroy all of the user's sessions. * * ## EXAMPLES * * # Destroy the most recent session of the given user. * $ wp user session destroy admin * Success: Destroyed session. 3 sessions remaining. * * # Destroy a specific session of the given user. * $ wp user session destroy admin e073ad8540a9c2... * Success: Destroyed session. 2 sessions remaining. * * # Destroy all the sessions of the given user. * $ wp user session destroy admin --all * Success: Destroyed all sessions. * * # Destroy all sessions for all users. * $ wp user list --field=ID | xargs wp user session destroy --all * Success: Destroyed all sessions. * Success: Destroyed all sessions. */ public function destroy($args, $assoc_args) { $user = $this->fetcher->get_check($args[0]); $token = \WP_CLI\Utils\get_flag_value($args, 1, null); $all = \WP_CLI\Utils\get_flag_value($assoc_args, 'all', false); $manager = WP_Session_Tokens::get_instance($user->ID); if ($token && $all) { WP_CLI::error('The --all flag cannot be specified along with a session token.'); } if ($all) { $manager->destroy_all(); WP_CLI::success('Destroyed all sessions.'); return; } $sessions = $this->get_all_sessions($manager); if (!$token) { if (empty($sessions)) { WP_CLI::success('No sessions to destroy.'); } $last = end($sessions); $token = $last['token']; } if (!isset($sessions[$token])) { WP_CLI::error('Session not found.'); } $this->destroy_session($manager, $token); $remaining = count($manager->get_all()); WP_CLI::success(sprintf('Destroyed session. %s remaining.', $remaining)); }
/** * Set a transient value. <expiration> is the time until expiration, in seconds. * * <key> * : Key for the transient. * * <value> * : Value to be set for the transient. * * [<expiration>] * : Time until expiration, in seconds. */ public function set($args) { list($key, $value) = $args; $expiration = \WP_CLI\Utils\get_flag_value($args, 2, 0); if (set_transient($key, $value, $expiration)) { WP_CLI::success('Transient added.'); } else { WP_CLI::error('Transient could not be set.'); } }
/** * Load and execute a PHP file. * * ## OPTIONS * * <file> * : The path to the PHP file to execute. * * [<arg>...] * : One or more arguments to pass to the file. They are placed in the $args variable. * * [--skip-wordpress] * : Load and execute file without loading WordPress. * * @when before_wp_load * * ## EXAMPLES * * wp eval-file my-code.php value1 value2 */ public function __invoke($args, $assoc_args) { $file = array_shift($args); if (!file_exists($file)) { WP_CLI::error("'{$file}' does not exist."); } if (null === \WP_CLI\Utils\get_flag_value($assoc_args, 'skip-wordpress')) { WP_CLI::get_runner()->load_wordpress(); } self::_eval($file, $args); }
/** * Create a new menu. * * ## OPTIONS * * <menu-name> * : A descriptive name for the menu. * * [--porcelain] * : Output just the new menu id. * * ## EXAMPLES * * $ wp menu create "My Menu" * Success: Created menu 200. */ public function create($args, $assoc_args) { $menu_id = wp_create_nav_menu($args[0]); if (is_wp_error($menu_id)) { WP_CLI::error($menu_id->get_error_message()); } else { if (\WP_CLI\Utils\get_flag_value($assoc_args, 'porcelain')) { WP_CLI::line($menu_id); } else { WP_CLI::success("Created menu {$menu_id}."); } } }
/** * Create a given database object. * Exits with status. * * @param array $args Arguments passed to command. Generally unused. * @param array $assoc_args Parameters passed to command to be passed to callback. * @param string $callback Function used to create object. */ protected function _create($args, $assoc_args, $callback) { unset($assoc_args[$this->obj_id_key]); $obj_id = $callback($assoc_args); if (is_wp_error($obj_id)) { \WP_CLI::error($obj_id); } if (\WP_CLI\Utils\get_flag_value($assoc_args, 'porcelain')) { \WP_CLI::line($obj_id); } else { \WP_CLI::success("Created {$this->obj_type} {$obj_id}."); } }
/** * Get a list of updates. * * ## Options * * [--<field>=<value>] * : Add additional arguments to Updates query. * * [--fields=<fields>] * : Limit fields returned. * * [--raw] * : Return raw values. IDs instead of human readable names. * * @param $args * @param $assoc_args * * @subcommand list */ public function list_($args, $assoc_args) { $query_args = wp_parse_args($assoc_args, array('items_per_page' => 20, 'page' => 1)); $query_args['order'] = array('update_date' => 'DESC'); $results = itelic_get_updates($query_args); $items = array(); foreach ($results as $item) { $items[] = $this->get_fields_for_object($item, \WP_CLI\Utils\get_flag_value($assoc_args, 'raw', false)); } if (empty($assoc_args['fields'])) { $assoc_args['fields'] = array('ID', 'activation', 'location', 'release', 'update_date', 'previous_version'); } $formatter = $this->get_formatter($assoc_args); $formatter->display_items($items); }
/** * Delete a transient value. * * <key> * : Key for the transient. * * [--network] * : Delete the value of a network transient, instead of that on a single site. */ public function delete($args, $assoc_args) { list($key) = $args; $func = \WP_CLI\Utils\get_flag_value($assoc_args, 'network') ? 'delete_site_transient' : 'delete_transient'; if ($func($key)) { WP_CLI::success('Transient deleted.'); } else { $func = \WP_CLI\Utils\get_flag_value($assoc_args, 'network') ? 'get_site_transient' : 'get_transient'; if ($func($key)) { WP_CLI::error('Transient was not deleted even though the transient appears to exist.'); } else { WP_CLI::warning('Transient was not deleted; however, the transient does not appear to exist.'); } } }
/** * Interactive PHP console. * * ## DESCRIPTION * * `wp shell` allows you to evaluate PHP statements and expressions interactively, from within a WordPress environment. This means that you have access to all the functions, classes and globals that you would have access to from inside a WordPress plugin, for example. * * ## OPTIONS * * [--basic] * : Start in fail-safe mode, even if Boris is available. */ public function __invoke($_, $assoc_args) { $implementations = array('\\Psy\\Shell', '\\Boris\\Boris', '\\WP_CLI\\REPL'); if (\WP_CLI\Utils\get_flag_value($assoc_args, 'basic')) { $class = '\\WP_CLI\\REPL'; } else { foreach ($implementations as $candidate) { if (class_exists($candidate)) { $class = $candidate; break; } } } if ('\\Psy\\Shell' == $class) { \Psy\Shell::debug(); } else { $repl = new $class("\nwp> "); $repl->start(); } }
/** * Purge the cache for one or more URL paths * * [<path>...] * : Specify one or more URL paths to purge cache for. * * [--all] * : Purge cache for all URL paths. */ public function clear($args, $assoc_args) { $instance = Pantheon_Cache::instance(); $instance->paths = array(); if (!function_exists('pantheon_clear_edge')) { WP_CLI::warning("pantheon_clear_edge() function doesn't exist in this environment so cache won't be purged."); } if (true === WP_CLI\Utils\get_flag_value($assoc_args, 'all')) { $instance->paths[] = '/.*'; $instance->cache_clean_urls(); WP_CLI::success("Cache purged for all URL paths."); } else { $instance->enqueue_urls($args); if (empty($instance->paths)) { WP_CLI::error('Please provide one or more URL paths to purge, or use the --all flag.'); } $path_count = count($instance->paths); $instance->cache_clean_urls(); WP_CLI::success("Cache purged for {$path_count} URL paths."); } }
/** * Create a site in a multisite install. * * ## OPTIONS * * --slug=<slug> * : Path for the new site. Subdomain on subdomain installs, directory on subdirectory installs. * * [--title=<title>] * : Title of the new site. Default: prettified slug. * * [--email=<email>] * : Email for Admin user. User will be created if none exists. Assignement to Super Admin if not included. * * [--network_id=<network-id>] * : Network to associate new site with. Defaults to current network (typically 1). * * [--private] * : If set, the new site will be non-public (not indexed) * * [--porcelain] * : If set, only the site id will be output on success. */ public function create($_, $assoc_args) { if (!is_multisite()) { WP_CLI::error('This is not a multisite install.'); } global $wpdb, $current_site; $base = $assoc_args['slug']; $title = \WP_CLI\Utils\get_flag_value($assoc_args, 'title', ucfirst($base)); $email = empty($assoc_args['email']) ? '' : $assoc_args['email']; // Network if (!empty($assoc_args['network_id'])) { $network = $this->_get_network($assoc_args['network_id']); if ($network === false) { WP_CLI::error(sprintf('Network with id %d does not exist.', $assoc_args['network_id'])); } } else { $network = $current_site; } $public = !\WP_CLI\Utils\get_flag_value($assoc_args, 'private'); // Sanitize if (preg_match('|^([a-zA-Z0-9-])+$|', $base)) { $base = strtolower($base); } // If not a subdomain install, make sure the domain isn't a reserved word if (!is_subdomain_install()) { $subdirectory_reserved_names = apply_filters('subdirectory_reserved_names', array('page', 'comments', 'blog', 'files', 'feed')); if (in_array($base, $subdirectory_reserved_names)) { WP_CLI::error('The following words are reserved and cannot be used as blog names: ' . implode(', ', $subdirectory_reserved_names)); } } // Check for valid email, if not, use the first Super Admin found // Probably a more efficient way to do this so we dont query for the // User twice if super admin $email = sanitize_email($email); if (empty($email) || !is_email($email)) { $super_admins = get_super_admins(); $email = ''; if (!empty($super_admins) && is_array($super_admins)) { // Just get the first one $super_login = $super_admins[0]; $super_user = get_user_by('login', $super_login); if ($super_user) { $email = $super_user->user_email; } } } if (is_subdomain_install()) { $path = '/'; $url = $newdomain = $base . '.' . preg_replace('|^www\\.|', '', $network->domain); } else { $newdomain = $network->domain; $path = '/' . trim($base, '/') . '/'; $url = $network->domain . $path; } $user_id = email_exists($email); if (!$user_id) { // Create a new user with a random password $password = wp_generate_password(12, false); $user_id = wpmu_create_user($base, $password, $email); if (false == $user_id) { WP_CLI::error("Can't create user."); } else { wp_new_user_notification($user_id, $password); } } $wpdb->hide_errors(); $id = wpmu_create_blog($newdomain, $path, $title, $user_id, array('public' => $public), $network->id); $wpdb->show_errors(); if (!is_wp_error($id)) { if (!is_super_admin($user_id) && !get_user_option('primary_blog', $user_id)) { update_user_option($user_id, 'primary_blog', $id, true); } // Prevent mailing admins of new sites // @TODO argument to pass in? // $content_mail = sprintf(__( "New site created by WP Command Line Interface\n\nAddress: %2s\nName: %3s"), get_site_url($id), stripslashes($title)); // wp_mail(get_site_option('admin_email'), sprintf(__('[%s] New Site Created'), $current_site->site_name), $content_mail, 'From: "Site Admin" <'.get_site_option( 'admin_email').'>'); } else { WP_CLI::error($id->get_error_message()); } if (\WP_CLI\Utils\get_flag_value($assoc_args, 'porcelain')) { WP_CLI::line($id); } else { WP_CLI::success("Site {$id} created: {$url}"); } }
/** * Fetch an array of scheduled cron events. * * @return array|WP_Error An array of event objects, or a WP_Error object if there are no events scheduled. */ protected static function get_cron_events() { $crons = _get_cron_array(); $events = array(); if (empty($crons)) { return new WP_Error('no_events', 'You currently have no scheduled cron events.'); } foreach ($crons as $time => $hooks) { foreach ($hooks as $hook => $hook_events) { foreach ($hook_events as $sig => $data) { $events["{$hook}-{$sig}"] = (object) array('hook' => $hook, 'time' => $time, 'sig' => $sig, 'args' => $data['args'], 'schedule' => $data['schedule'], 'interval' => \WP_CLI\Utils\get_flag_value($data, 'interval')); } } } $events = array_map('Cron_Event_Command::format_event', $events); return $events; }
/** * Update the permalink structure. * * ## DESCRIPTION * * Updates the post permalink structure. * * To regenerate a .htaccess file with WP-CLI, you'll need to add the mod_rewrite module * to your wp-cli.yml or config.yml. For example: * * `apache_modules: * - mod_rewrite` * * ## OPTIONS * * <permastruct> * : The new permalink structure to apply. * * [--category-base=<base>] * : Set the base for category permalinks, i.e. '/category/'. * * [--tag-base=<base>] * : Set the base for tag permalinks, i.e. '/tag/'. * * [--hard] * : Perform a hard flush - update `.htaccess` rules as well as rewrite rules in database. * * ## EXAMPLES * * wp rewrite structure '/%year%/%monthnum%/%postname%' */ public function structure($args, $assoc_args) { global $wp_rewrite; // copypasta from /wp-admin/options-permalink.php $prefix = $blog_prefix = ''; if (is_multisite() && !is_subdomain_install() && is_main_site()) { $blog_prefix = '/blog'; } $permalink_structure = $args[0] == 'default' ? '' : $args[0]; if (!empty($permalink_structure)) { $permalink_structure = preg_replace('#/+#', '/', '/' . str_replace('#', '', $permalink_structure)); if ($prefix && $blog_prefix) { $permalink_structure = $prefix . preg_replace('#^/?index\\.php#', '', $permalink_structure); } else { $permalink_structure = $blog_prefix . $permalink_structure; } } $wp_rewrite->set_permalink_structure($permalink_structure); // Update category or tag bases if (isset($assoc_args['category-base'])) { $category_base = $assoc_args['category-base']; if (!empty($category_base)) { $category_base = $blog_prefix . preg_replace('#/+#', '/', '/' . str_replace('#', '', $category_base)); } $wp_rewrite->set_category_base($category_base); } if (isset($assoc_args['tag-base'])) { $tag_base = $assoc_args['tag-base']; if (!empty($tag_base)) { $tag_base = $blog_prefix . preg_replace('#/+#', '/', '/' . str_replace('#', '', $tag_base)); } $wp_rewrite->set_tag_base($tag_base); } // make sure we detect mod_rewrite if configured in apache_modules in config self::apache_modules(); // Launch a new process to flush rewrites because core expects flush // to happen after rewrites are set $new_assoc_args = array(); if (\WP_CLI\Utils\get_flag_value($assoc_args, 'hard')) { $new_assoc_args['hard'] = true; if (!in_array('mod_rewrite', (array) WP_CLI::get_config('apache_modules'))) { WP_CLI::warning("Regenerating a .htaccess file requires special configuration. See usage docs."); } } $process_run = WP_CLI::launch_self('rewrite flush', array(), $new_assoc_args, true, true, array('apache_modules', WP_CLI::get_config('apache_modules'))); if (!empty($process_run->stderr)) { // Strip "Warning: " WP_CLI::warning(substr($process_run->stderr, 9)); } WP_CLI::success("Rewrite structure set."); }
/** * Uninstall a plugin. * * ## OPTIONS * * <plugin>... * : One or more plugins to uninstall. * * [--deactivate] * : Deactivate the plugin before uninstalling. Default behavior is to warn and skip if the plugin is active. * * [--skip-delete] * : If set, the plugin files will not be deleted. Only the uninstall procedure * will be run. * * ## EXAMPLES * * wp plugin uninstall hello */ function uninstall($args, $assoc_args = array()) { foreach ($this->fetcher->get_many($args) as $plugin) { if (is_plugin_active($plugin->file) && !WP_CLI\Utils\get_flag_value($assoc_args, 'deactivate')) { WP_CLI::warning("The '{$plugin->name}' plugin is active."); continue; } if (\WP_CLI\Utils\get_flag_value($assoc_args, 'deactivate')) { WP_CLI::log("Deactivating '{$plugin->name}'..."); $this->deactivate(array($plugin->name)); } uninstall_plugin($plugin->file); if (!\WP_CLI\Utils\get_flag_value($assoc_args, 'skip-delete') && $this->_delete($plugin)) { WP_CLI::success("Uninstalled and deleted '{$plugin->name}' plugin."); } else { WP_CLI::success("Ran uninstall procedure for '{$plugin->name}' plugin without deleting."); } } }
/** * Create a term. * * ## OPTIONS * * <taxonomy> * : Taxonomy for the new term. * * <term> * : A name for the new term. * * [--slug=<slug>] * : A unique slug for the new term. Defaults to sanitized version of name. * * [--description=<description>] * : A description for the new term. * * [--parent=<term-id>] * : A parent for the new term. * * [--porcelain] * : Output just the new term id. * * ## EXAMPLES * * wp term create category Apple --description="A type of fruit" */ public function create($args, $assoc_args) { list($taxonomy, $term) = $args; $defaults = array('slug' => sanitize_title($term), 'description' => '', 'parent' => 0); $assoc_args = wp_parse_args($assoc_args, $defaults); $porcelain = \WP_CLI\Utils\get_flag_value($assoc_args, 'porcelain'); unset($assoc_args['porcelain']); // Compatibility for < WP 4.0 if ($assoc_args['parent'] > 0 && !term_exists((int) $assoc_args['parent'])) { WP_CLI::error('Parent term does not exist.'); } $ret = wp_insert_term($term, $taxonomy, $assoc_args); if (is_wp_error($ret)) { WP_CLI::error($ret->get_error_message()); } else { if ($porcelain) { WP_CLI::line($ret['term_id']); } else { WP_CLI::success(sprintf("Created %s %d.", $taxonomy, $ret['term_id'])); } } }
/** * Dump the list of global parameters, as JSON or in var_export format. * * ## OPTIONS * * [--with-values] * : Display current values also. * * [--format=<format>] * : Accepted values: var_export, json. Default: json. * * @subcommand param-dump */ function param_dump($_, $assoc_args) { $spec = \WP_CLI::get_configurator()->get_spec(); if (\WP_CLI\Utils\get_flag_value($assoc_args, 'with-values')) { $config = \WP_CLI::get_configurator()->to_array(); // Copy current config values to $spec foreach ($spec as $key => $value) { if (isset($config[0][$key])) { $current = $config[0][$key]; } else { $current = NULL; } $spec[$key]['current'] = $current; } } if ('var_export' === \WP_CLI\Utils\get_flag_value($assoc_args, 'format')) { var_export($spec); } else { echo json_encode($spec); } }
/** * Set a value to the object cache, regardless of whether it already exists. * * Errors if the value can't be set. * * ## OPTIONS * * <key> * : Cache key. * * <value> * : Value to set on the key. * * [<group>] * : Method for grouping data within the cache which allows the same key to be used across groups. * * [<expiration>] * : Define how long to keep the value, in seconds. `0` means as long as possible. * --- * default: 0 * --- * * ## EXAMPLES * * # Set cache. * $ wp cache set my_key my_value my_group 300 * Success: Set object 'my_key' in group 'my_group'. */ public function set($args, $assoc_args) { list($key, $value) = $args; $group = \WP_CLI\Utils\get_flag_value($args, 2, ''); $expiration = \WP_CLI\Utils\get_flag_value($args, 3, 0); $result = wp_cache_set($key, $value, $group, $expiration); if (false === $result) { WP_CLI::error("Could not add object '{$key}' in group '{$group}'."); } WP_CLI::success("Set object '{$key}' in group '{$group}'."); }
/** * Get a string representing the type of update being checked for. */ private function get_update_type_str($assoc_args) { $update_type = ' '; foreach (array('major', 'minor', 'patch') as $type) { if (true === \WP_CLI\Utils\get_flag_value($assoc_args, $type)) { $update_type = ' ' . $type . ' '; break; } } return $update_type; }
/** * 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."); } } }
/** * 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 = \WP_CLI\Utils\get_flag_value($assoc_args, 'version'); $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)) { list($update) = $from_api->updates; } } else { if (version_compare($wp_version, $assoc_args['version'], '<') || \WP_CLI\Utils\get_flag_value($assoc_args, 'force')) { $version = $assoc_args['version']; $locale = \WP_CLI\Utils\get_flag_value($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); } } } if (!empty($update) && ($update->version != $wp_version || \WP_CLI\Utils\get_flag_value($assoc_args, 'force'))) { 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.'); } } else { WP_CLI::success('WordPress is up to date.'); } }
protected function extract_args($assoc_args, $defaults) { $out = array(); foreach ($defaults as $key => $value) { $out[$key] = \WP_CLI\Utils\get_flag_value($assoc_args, $key, $value); } return $out; }
/** * Remove theme mod(s). * * ## OPTIONS * * [<mod>...] * : One or more mods to remove. * * [--all] * : Remove all theme mods * * ## EXAMPLES * * wp theme mod remove --all * wp theme mod remove background_color * wp theme mod remove background_color header_textcolor */ public function remove($args = array(), $assoc_args = array()) { if (!\WP_CLI\Utils\get_flag_value($assoc_args, 'all') && empty($args)) { WP_CLI::error("You must specify at least one mod or use --all."); } if (\WP_CLI\Utils\get_flag_value($assoc_args, 'all')) { remove_theme_mods(); WP_CLI::success('Theme mods removed.'); return; } foreach ($args as $mod) { remove_theme_mod($mod); } WP_CLI::success(sprintf('%d mods removed.', count($args))); }
/** * Returns update information */ private function get_updates($assoc_args) { global $wp_version; $versions_path = ABSPATH . 'wp-includes/version.php'; include $versions_path; $url = 'https://api.wordpress.org/core/stable-check/1.0/'; $options = array('timeout' => 30); $headers = array('Accept' => 'application/json'); $response = Utils\http_request('GET', $url, $headers, $options); if (!$response->success || 200 !== $response->status_code) { WP_CLI::error("Failed to get latest version list."); } $release_data = json_decode($response->body); $release_versions = array_keys((array) $release_data); usort($release_versions, function ($a, $b) { return 1 === version_compare($a, $b); }); $locale = get_locale(); $compare_version = str_replace('-src', '', $GLOBALS['wp_version']); $updates = array('major' => false, 'minor' => false); foreach ($release_versions as $release_version) { $update_type = Utils\get_named_sem_ver($release_version, $compare_version); if (!$update_type) { continue; } // WordPress follow its own versioning which is roughly equivalent to semver if ('minor' === $update_type) { $update_type = 'major'; } else { if ('patch' === $update_type) { $update_type = 'minor'; } } if (!empty($updates[$update_type]) && !Comparator::greaterThan($release_version, $updates[$update_type]['version'])) { continue; } $updates[$update_type] = array('version' => $release_version, 'update_type' => $update_type, 'package_url' => $this->get_download_url($release_version, $locale)); } foreach ($updates as $type => $value) { if (empty($value)) { unset($updates[$type]); } } foreach (array('major', 'minor') as $type) { if (true === \WP_CLI\Utils\get_flag_value($assoc_args, $type)) { return !empty($updates[$type]) ? array($updates[$type]) : false; } } return array_values($updates); }
/** * Reset sidebar. * * Removes all widgets from the sidebar and places them in Inactive Widgets. * * ## OPTIONS * * [<sidebar-id>...] * : One or more sidebars to reset. * * [--all] * : If set, all sidebars will be reset. * * ## EXAMPLES * * # Reset a sidebar * $ wp widget reset sidebar-1 * Success: Sidebar 'sidebar-1' reset. * * # Reset multiple sidebars * $ wp widget reset sidebar-1 sidebar-2 * Success: Sidebar 'sidebar-1' reset. * Success: Sidebar 'sidebar-2' reset. * * # Reset all sidebars * $ wp widget reset --all * Success: Sidebar 'sidebar-1' reset. * Success: Sidebar 'sidebar-2' reset. * Success: Sidebar 'sidebar-3' reset. */ public function reset($args, $assoc_args) { global $wp_registered_sidebars; $all = \WP_CLI\Utils\get_flag_value($assoc_args, 'all', false); // Bail if no arguments and no all flag. if (!$all && empty($args)) { WP_CLI::error('Please specify one or more sidebars, or use --all.'); } // Fetch all sidebars if all flag is set. if ($all) { $args = array_keys($wp_registered_sidebars); } // Sidebar ID wp_inactive_widgets is reserved by WP core for inactive widgets. if (isset($args['wp_inactive_widgets'])) { unset($args['wp_inactive_widgets']); } // Check if no registered sidebar. if (empty($args)) { WP_CLI::error('No sidebar registered.'); } $count = $errors = 0; foreach ($args as $sidebar_id) { if (!array_key_exists($sidebar_id, $wp_registered_sidebars)) { WP_CLI::warning(sprintf('Invalid sidebar: %s', $sidebar_id)); $errors++; continue; } $widgets = $this->get_sidebar_widgets($sidebar_id); if (empty($widgets)) { WP_CLI::warning(sprintf("Sidebar '%s' is already empty.", $sidebar_id)); } else { foreach ($widgets as $widget) { $widget_id = $widget->id; list($name, $option_index, $new_sidebar_id, $sidebar_index) = $this->get_widget_data($widget_id); $this->move_sidebar_widget($widget_id, $new_sidebar_id, 'wp_inactive_widgets', $sidebar_index, 0); } WP_CLI::log(sprintf("Sidebar '%s' reset.", $sidebar_id)); $count++; } } Utils\report_batch_operation_results('sidebar', 'reset', count($args), $count, $errors); }
/** * List the database tables. * * Defaults to all tables registered to the $wpdb database handler. * * ## OPTIONS * * [<table>...] * : List tables based on wildcard search, e.g. 'wp_*_options' or 'wp_post?'. * * [--scope=<scope>] * : Can be all, global, ms_global, blog, or old tables. Defaults to all. * * [--network] * : List all the tables in a multisite install. Overrides --scope=<scope>. * * [--all-tables-with-prefix] * : List all tables that match the table prefix even if not registered on $wpdb. Overrides --network. * * [--all-tables] * : List all tables in the database, regardless of the prefix, and even if not registered on $wpdb. Overrides --all-tables-with-prefix. * * [--format=<format>] * : Render output in a particular format. * --- * default: list * options: * - list * - csv * --- * * ## EXAMPLES * * # Export only tables for a single site * $ wp db export --tables=$(wp db tables --url=sub.example.com --format=csv) * Success: Exported to wordpress_dbase.sql */ function tables($args, $assoc_args) { $format = WP_CLI\Utils\get_flag_value($assoc_args, 'format'); unset($assoc_args['format']); if (empty($args) && empty($assoc_args)) { $assoc_args['scope'] = 'all'; } $tables = WP_CLI\Utils\wp_get_table_names($args, $assoc_args); if ('csv' === $format) { WP_CLI::line(implode(',', $tables)); } else { foreach ($tables as $table) { WP_CLI::line($table); } } }
/** * Create attachments from local files or URLs. * * ## OPTIONS * * <file>... * : Path to file or files to be imported. Supports the glob(3) capabilities of the current shell. * If file is recognized as a URL (for example, with a scheme of http or ftp), the file will be * downloaded to a temp file before being sideloaded. * * [--post_id=<post_id>] * : ID of the post to attach the imported files to. * * [--title=<title>] * : Attachment title (post title field). * * [--caption=<caption>] * : Caption for attachent (post excerpt field). * * [--alt=<alt_text>] * : Alt text for image (saved as post meta). * * [--desc=<description>] * : "Description" field (post content) of attachment post. * * [--featured_image] * : If set, set the imported image as the Featured Image of the post its attached to. * * [--porcelain] * : Output just the new attachment ID. * * ## EXAMPLES * * # Import all jpgs in the current user's "Pictures" directory, not attached to any post. * $ wp media import ~/Pictures/**\/*.jpg * Imported file '/home/person/Pictures/beautiful-youg-girl-in-ivy.jpg' as attachment ID 1751. * Imported file '/home/person/Pictures/fashion-girl.jpg' as attachment ID 1752. * Success: Imported 2 of 2 images. * * # Import a local image and set it to be the post thumbnail for a post. * $ wp media import ~/Downloads/image.png --post_id=123 --title="A downloaded picture" --featured_image * Imported file '/home/person/Downloads/image.png' as attachment ID 1753 and attached to post 123 as featured image. * Success: Imported 1 of 1 images. * * # Import a local image, but set it as the featured image for all posts. * # 1. Import the image and get its attachment ID. * # 2. Assign the attachment ID as the featured image for all posts. * $ ATTACHMENT_ID="$(wp media import ~/Downloads/image.png --porcelain)" * $ wp post list --post_type=post --format=ids | xargs -d ' ' -I % wp post meta add % _thumbnail_id $ATTACHMENT_ID * Success: Added custom field. * Success: Added custom field. * * # Import an image from the web. * $ wp media import http://s.wordpress.org/style/images/wp-header-logo.png --title='The WordPress logo' --alt="Semantic personal publishing" * Imported file 'http://s.wordpress.org/style/images/wp-header-logo.png' as attachment ID 1755. * Success: Imported 1 of 1 images. */ function import($args, $assoc_args = array()) { $assoc_args = wp_parse_args($assoc_args, array('title' => '', 'caption' => '', 'alt' => '', 'desc' => '')); if (isset($assoc_args['post_id'])) { if (!get_post($assoc_args['post_id'])) { WP_CLI::warning("Invalid --post_id"); $assoc_args['post_id'] = false; } } else { $assoc_args['post_id'] = false; } $successes = $errors = 0; foreach ($args as $file) { $is_file_remote = parse_url($file, PHP_URL_HOST); $orig_filename = $file; if (empty($is_file_remote)) { if (!file_exists($file)) { WP_CLI::warning("Unable to import file '{$file}'. Reason: File doesn't exist."); $errors++; break; } $tempfile = $this->make_copy($file); } else { $tempfile = download_url($file); } $file_array = array('tmp_name' => $tempfile, 'name' => basename($file)); $post_array = array('post_title' => $assoc_args['title'], 'post_excerpt' => $assoc_args['caption'], 'post_content' => $assoc_args['desc']); $post_array = wp_slash($post_array); // use image exif/iptc data for title and caption defaults if possible if (empty($post_array['post_title']) || empty($post_array['post_excerpt'])) { // @codingStandardsIgnoreStart $image_meta = @wp_read_image_metadata($tempfile); // @codingStandardsIgnoreEnd if (!empty($image_meta)) { if (empty($post_array['post_title']) && trim($image_meta['title']) && !is_numeric(sanitize_title($image_meta['title']))) { $post_array['post_title'] = $image_meta['title']; } if (empty($post_array['post_excerpt']) && trim($image_meta['caption'])) { $post_array['post_excerpt'] = $image_meta['caption']; } } } if (empty($post_array['post_title'])) { $post_array['post_title'] = preg_replace('/\\.[^.]+$/', '', basename($file)); } // Deletes the temporary file. $success = media_handle_sideload($file_array, $assoc_args['post_id'], $assoc_args['title'], $post_array); if (is_wp_error($success)) { WP_CLI::warning(sprintf("Unable to import file '%s'. Reason: %s", $orig_filename, implode(', ', $success->get_error_messages()))); $errors++; continue; } // Set alt text if ($assoc_args['alt']) { update_post_meta($success, '_wp_attachment_image_alt', wp_slash($assoc_args['alt'])); } // Set as featured image, if --post_id and --featured_image are set if ($assoc_args['post_id'] && \WP_CLI\Utils\get_flag_value($assoc_args, 'featured_image')) { update_post_meta($assoc_args['post_id'], '_thumbnail_id', $success); } $attachment_success_text = ''; if ($assoc_args['post_id']) { $attachment_success_text = " and attached to post {$assoc_args['post_id']}"; if (\WP_CLI\Utils\get_flag_value($assoc_args, 'featured_image')) { $attachment_success_text .= ' as featured image'; } } if (\WP_CLI\Utils\get_flag_value($assoc_args, 'porcelain')) { WP_CLI::line($success); } else { WP_CLI::log(sprintf("Imported file '%s' as attachment ID %d%s.", $orig_filename, $success, $attachment_success_text)); } $successes++; } if (!Utils\get_flag_value($assoc_args, 'porcelain')) { Utils\report_batch_operation_results('image', 'import', count($args), $successes, $errors); } }
/** * Search wordpress.org repo. * * @param array $args A arguments array containing the search term in the first element. * @param array $assoc_args Data passed in from command. */ protected function _search($args, $assoc_args) { $term = $args[0]; $defaults = array('per-page' => 10, 'page' => 1, 'fields' => implode(',', array('name', 'slug', 'rating'))); $assoc_args = array_merge($defaults, $assoc_args); $fields = array(); foreach (explode(',', $assoc_args['fields']) as $field) { $fields[$field] = true; } $formatter = $this->get_formatter($assoc_args); $api_args = array('per_page' => (int) $assoc_args['per-page'], 'page' => (int) $assoc_args['page'], 'search' => $term, 'fields' => $fields); if ('plugin' == $this->item_type) { $api = plugins_api('query_plugins', $api_args); } else { $api = themes_api('query_themes', $api_args); } if (is_wp_error($api)) { \WP_CLI::error($api->get_error_message() . __(' Try again')); } $plural = $this->item_type . 's'; if (!isset($api->{$plural})) { \WP_CLI::error(__('API error. Try Again.')); } $items = $api->{$plural}; $count = \WP_CLI\Utils\get_flag_value($api->info, 'results', 'unknown'); \WP_CLI::success(sprintf('Showing %s of %s %s.', count($items), $count, $plural)); $formatter->display_items($items); }
/** * Delete a transient value. * * ## OPTIONS * * [<key>] * : Key for the transient. * * [--network] * : Delete the value of a network transient, instead of that on a single site. * * [--all] * : Delete all transients. * * [--expired] * : Delete all expired transients. * * ## EXAMPLES * * # Delete transient. * $ wp transient delete sample_key * Success: Transient deleted. * * # Delete expired transients. * $ wp transient delete --expired * Success: 12 expired transients deleted from the database. * * # Delete all transients. * $ wp transient delete --all * Success: 14 transients deleted from the database. */ public function delete($args, $assoc_args) { $key = !empty($args) ? $args[0] : NULL; $all = \WP_CLI\Utils\get_flag_value($assoc_args, 'all'); $expired = \WP_CLI\Utils\get_flag_value($assoc_args, 'expired'); if (true === $all) { $this->delete_all(); return; } else { if (true === $expired) { $this->delete_expired(); return; } } if (!$key) { WP_CLI::error('Please specify transient key, or use --all or --expired.'); } $func = \WP_CLI\Utils\get_flag_value($assoc_args, 'network') ? 'delete_site_transient' : 'delete_transient'; if ($func($key)) { WP_CLI::success('Transient deleted.'); } else { $func = \WP_CLI\Utils\get_flag_value($assoc_args, 'network') ? 'get_site_transient' : 'get_transient'; if ($func($key)) { WP_CLI::error('Transient was not deleted even though the transient appears to exist.'); } else { WP_CLI::warning('Transient was not deleted; however, the transient does not appear to exist.'); } } }
/** * Count comments, on whole blog or on a given post. * * ## OPTIONS * * [<post-id>] * : The ID of the post to count comments in. * * ## EXAMPLES * * # Count comments on whole blog * $ wp comment count * approved: 33 * spam: 3 * trash: 1 * post-trashed: 0 * all: 34 * moderated: 1 * total_comments: 37 * * # Count comments in a post * $ wp comment count 42 * approved: 19 * spam: 0 * trash: 0 * post-trashed: 0 * all: 19 * moderated: 0 * total_comments: 19 */ public function count($args, $assoc_args) { $post_id = \WP_CLI\Utils\get_flag_value($args, 0, 0); $count = wp_count_comments($post_id); // Move total_comments to the end of the object $total = $count->total_comments; unset($count->total_comments); $count->total_comments = $total; foreach ($count as $status => $count) { WP_CLI::line(str_pad("{$status}:", 17) . $count); } }
/** * Create attachments from local files or from URLs. * * ## OPTIONS * * <file>... * : Path to file or files to be imported. Supports the glob(3) capabilities of the current shell. * If file is recognized as a URL (for example, with a scheme of http or ftp), the file will be * downloaded to a temp file before being sideloaded. * * [--post_id=<post_id>] * : ID of the post to attach the imported files to * * [--title=<title>] * : Attachment title (post title field) * * [--caption=<caption>] * : Caption for attachent (post excerpt field) * * [--alt=<alt_text>] * : Alt text for image (saved as post meta) * * [--desc=<description>] * : "Description" field (post content) of attachment post * * [--featured_image] * : If set, set the imported image as the Featured Image of the post its attached to. * * [--porcelain] * : Output just the new attachment id. * * ## EXAMPLES * * # Import all jpgs in the current user's "Pictures" directory, not attached to any post * wp media import ~/Pictures/**\/*.jpg * * # Import a local image and set it to be the post thumbnail for a post * wp media import ~/Downloads/image.png --post_id=123 --title="A downloaded picture" --featured_image * * # Import an image from the web * wp media import http://s.wordpress.org/style/images/wp-header-logo.png --title='The WordPress logo' --alt="Semantic personal publishing" */ function import($args, $assoc_args = array()) { $assoc_args = wp_parse_args($assoc_args, array('title' => '', 'caption' => '', 'alt' => '', 'desc' => '')); if (isset($assoc_args['post_id'])) { if (!get_post($assoc_args['post_id'])) { WP_CLI::warning("Invalid --post_id"); $assoc_args['post_id'] = false; } } else { $assoc_args['post_id'] = false; } foreach ($args as $file) { $is_file_remote = parse_url($file, PHP_URL_SCHEME); $orig_filename = $file; if (empty($is_file_remote)) { if (!file_exists($file)) { WP_CLI::warning("Unable to import file {$file}. Reason: File doesn't exist."); break; } $tempfile = $this->_make_copy($file); } else { $tempfile = download_url($file); } $file_array = array('tmp_name' => $tempfile, 'name' => basename($file)); $post_array = array('post_title' => $assoc_args['title'], 'post_excerpt' => $assoc_args['caption'], 'post_content' => $assoc_args['desc']); // Deletes the temporary file. $success = media_handle_sideload($file_array, $assoc_args['post_id'], $assoc_args['title'], $post_array); if (is_wp_error($success)) { WP_CLI::warning(sprintf('Unable to import file %s. Reason: %s', $orig_filename, implode(', ', $success->get_error_messages()))); continue; } // Set alt text if ($assoc_args['alt']) { update_post_meta($success, '_wp_attachment_image_alt', $assoc_args['alt']); } // Set as featured image, if --post_id and --featured_image are set if ($assoc_args['post_id'] && \WP_CLI\Utils\get_flag_value($assoc_args, 'featured_image')) { update_post_meta($assoc_args['post_id'], '_thumbnail_id', $success); } $attachment_success_text = ''; if ($assoc_args['post_id']) { $attachment_success_text = " and attached to post {$assoc_args['post_id']}"; if (\WP_CLI\Utils\get_flag_value($assoc_args, 'featured_image')) { $attachment_success_text .= ' as featured image'; } } if (\WP_CLI\Utils\get_flag_value($assoc_args, 'porcelain')) { WP_CLI::line($success); } else { WP_CLI::success(sprintf('Imported file %s as attachment ID %d%s.', $orig_filename, $success, $attachment_success_text)); } } }