private static function _extract($tarball, $dest) { if (!class_exists('PharData')) { $cmd = "tar xz --strip-components=1 --directory=%s -f {$tarball}"; WP_CLI::launch(Utils\esc_cmd($cmd, $dest)); return; } $phar = new PharData($tarball); $tempdir = implode(DIRECTORY_SEPARATOR, array(dirname($tarball), basename($tarball, '.tar.gz'), $phar->getFileName())); $phar->extractTo(dirname($tempdir), null, true); self::_copy_overwrite_files($tempdir, $dest); self::_rmdir(dirname($tempdir)); }
/** * Repair the database. * * Runs `mysqlcheck` utility with `--repair=true` using `DB_HOST`, * `DB_NAME`, `DB_USER` and `DB_PASSWORD` database credentials * specified in wp-config.php. * * [See docs](http://dev.mysql.com/doc/refman/5.7/en/repair-table.html) for * more details on the `REPAIR TABLE` statement. * * ## EXAMPLES * * $ wp db repair * Success: Database repaired. */ public function repair() { self::run(Utils\esc_cmd('mysqlcheck --no-defaults %s', DB_NAME), array('repair' => true)); WP_CLI::success("Database repaired."); }
/** * Generate files needed for writing Behat tests for your command. * * ## DESCRIPTION * * These are the files that are generated: * * * `.travis.yml` is the configuration file for Travis CI * * `bin/install-package-tests.sh` will configure environment to run tests. Script expects WP_CLI_BIN_DIR and WP_CLI_CONFIG_PATH environment variables. * * `features/load-wp-cli.feature` is a basic test to confirm WP-CLI can load. * * `features/bootstrap`, `features/steps`, `features/extra` are Behat configuration files. * * `utils/generate-package-require-from-composer.php` generates a test config.yml file from your package's composer.json * * ## ENVIRONMENT * * The `features/bootstrap/FeatureContext.php` file expects the WP_CLI_BIN_DIR and WP_CLI_CONFIG_PATH environment variables. * * WP-CLI Behat framework uses Behat ~2.5. * * ## OPTIONS * * <dir> * : The package directory to generate tests for. * * ## EXAMPLE * * wp scaffold package-tests /path/to/command/dir/ * * @when before_wp_load * @subcommand package-tests */ public function package_tests($args, $assoc_args) { list($package_dir) = $args; if (is_file($package_dir)) { $package_dir = dirname($package_dir); } else { if (is_dir($package_dir)) { $package_dir = rtrim($package_dir, '/'); } } if (!is_dir($package_dir) || !file_exists($package_dir . '/composer.json')) { WP_CLI::error("Invalid package directory. composer.json file must be present."); } $package_dir .= '/'; $bin_dir = $package_dir . 'bin/'; $utils_dir = $package_dir . 'utils/'; $features_dir = $package_dir . 'features/'; $bootstrap_dir = $features_dir . 'bootstrap/'; $steps_dir = $features_dir . 'steps/'; $extra_dir = $features_dir . 'extra/'; foreach (array($features_dir, $bootstrap_dir, $steps_dir, $extra_dir, $utils_dir, $bin_dir) as $dir) { if (!is_dir($dir)) { Process::create(Utils\esc_cmd('mkdir %s', $dir))->run(); } } $to_copy = array('templates/.travis.package.yml' => $package_dir, 'templates/load-wp-cli.feature' => $features_dir, 'templates/install-package-tests.sh' => $bin_dir, 'features/bootstrap/FeatureContext.php' => $bootstrap_dir, 'features/bootstrap/support.php' => $bootstrap_dir, 'php/WP_CLI/Process.php' => $bootstrap_dir, 'php/utils.php' => $bootstrap_dir, 'utils/get-package-require-from-composer.php' => $utils_dir, 'features/steps/given.php' => $steps_dir, 'features/steps/when.php' => $steps_dir, 'features/steps/then.php' => $steps_dir, 'features/extra/no-mail.php' => $extra_dir); foreach ($to_copy as $file => $dir) { // file_get_contents() works with Phar-archived files $contents = file_get_contents(WP_CLI_ROOT . "/{$file}"); $file_path = $dir . basename($file); $file_path = str_replace(array('.travis.package.yml'), array('.travis.yml'), $file_path); $result = Process::create(Utils\esc_cmd('touch %s', $file_path))->run(); file_put_contents($file_path, $contents); if ('templates/install-package-tests.sh' === $file) { Process::create(Utils\esc_cmd('chmod +x %s', $file_path))->run(); } } WP_CLI::success("Created test files."); }
public function download_wp($subdir = '') { $dest_dir = $this->variables['RUN_DIR'] . "/{$subdir}"; if ($subdir) { mkdir($dest_dir); } Process::create(Utils\esc_cmd("cp -r %s/* %s", self::$cache_dir, $dest_dir), null, self::get_process_env_variables())->run_check(); // disable emailing mkdir($dest_dir . '/wp-content/mu-plugins'); copy(__DIR__ . '/../extra/no-mail.php', $dest_dir . '/wp-content/mu-plugins/no-mail.php'); }
/** * Exports the database to a file or to STDOUT. * * ## OPTIONS * * [<file>] * : The name of the SQL file to export. If '-', then outputs to STDOUT. If omitted, it will be '{dbname}.sql'. * * [--<field>=<value>] * : Extra arguments to pass to mysqldump * * ## EXAMPLES * * wp db dump --add-drop-table * * @alias dump */ function export($args, $assoc_args) { $result_file = $this->get_file_name($args); $stdout = '-' === $result_file; if (!$stdout) { $assoc_args['result-file'] = $result_file; } self::run(Utils\esc_cmd('mysqldump %s', DB_NAME), $assoc_args); if (!$stdout) { WP_CLI::success(sprintf('Exported to %s', $result_file)); } }
/** * Generate files needed for writing Behat tests for your command. * * ## DESCRIPTION * * These are the files that are generated: * * * `.travis.yml` is the configuration file for Travis CI * * `bin/install-package-tests.sh` will configure environment to run tests. Script expects WP_CLI_BIN_DIR and WP_CLI_CONFIG_PATH environment variables. * * `features/load-wp-cli.feature` is a basic test to confirm WP-CLI can load. * * `features/bootstrap`, `features/steps`, `features/extra` are Behat configuration files. * * `utils/generate-package-require-from-composer.php` generates a test config.yml file from your package's composer.json * * ## ENVIRONMENT * * The `features/bootstrap/FeatureContext.php` file expects the WP_CLI_BIN_DIR and WP_CLI_CONFIG_PATH environment variables. * * WP-CLI Behat framework uses Behat ~2.5. * * ## OPTIONS * * <dir> * : The package directory to generate tests for. * * [--force] * : Overwrite files that already exist. * * ## EXAMPLE * * wp scaffold package-tests /path/to/command/dir/ * * @when before_wp_load * @subcommand package-tests */ public function package_tests($args, $assoc_args) { list($package_dir) = $args; if (is_file($package_dir)) { $package_dir = dirname($package_dir); } else { if (is_dir($package_dir)) { $package_dir = rtrim($package_dir, '/'); } } if (!is_dir($package_dir) || !file_exists($package_dir . '/composer.json')) { WP_CLI::error("Invalid package directory. composer.json file must be present."); } $package_dir .= '/'; $bin_dir = $package_dir . 'bin/'; $utils_dir = $package_dir . 'utils/'; $features_dir = $package_dir . 'features/'; $bootstrap_dir = $features_dir . 'bootstrap/'; $steps_dir = $features_dir . 'steps/'; $extra_dir = $features_dir . 'extra/'; foreach (array($features_dir, $bootstrap_dir, $steps_dir, $extra_dir, $utils_dir, $bin_dir) as $dir) { if (!is_dir($dir)) { Process::create(Utils\esc_cmd('mkdir %s', $dir))->run(); } } $to_copy = array('templates/.travis.package.yml' => $package_dir, 'templates/load-wp-cli.feature' => $features_dir, 'templates/install-package-tests.sh' => $bin_dir, 'features/bootstrap/FeatureContext.php' => $bootstrap_dir, 'features/bootstrap/support.php' => $bootstrap_dir, 'php/WP_CLI/Process.php' => $bootstrap_dir, 'php/utils.php' => $bootstrap_dir, 'ci/behat-tags.php' => $utils_dir, 'utils/get-package-require-from-composer.php' => $utils_dir, 'features/steps/given.php' => $steps_dir, 'features/steps/when.php' => $steps_dir, 'features/steps/then.php' => $steps_dir, 'features/extra/no-mail.php' => $extra_dir); $files_written = array(); foreach ($to_copy as $file => $dir) { // file_get_contents() works with Phar-archived files $contents = file_get_contents(WP_CLI_ROOT . "/{$file}"); $file_path = $dir . basename($file); $file_path = str_replace(array('.travis.package.yml'), array('.travis.yml'), $file_path); $force = \WP_CLI\Utils\get_flag_value($assoc_args, 'force'); $should_write_file = $this->prompt_if_files_will_be_overwritten($file_path, $force); if (!$should_write_file) { continue; } $files_written[] = $file_path; $result = Process::create(Utils\esc_cmd('touch %s', $file_path))->run(); file_put_contents($file_path, $contents); if ('templates/install-package-tests.sh' === $file) { Process::create(Utils\esc_cmd('chmod +x %s', $file_path))->run(); } } $this->log_whether_files_written($files_written, $skip_message = 'All package tests were skipped.', $success_message = 'Created test files.'); }
/** * Take a walk through the history of a function. * * ## OPTIONS * * [--filename=<filename>] * : Absolute or ABSPATH-relative path to the file which contains this * function. Only necessary when the function you're blaming isn't loaded * in the current call. * * [--no-docblock] * : Exclude the docblock from the blame. * * ## EXAMPLES * * wp svn blame get_post_meta * * wp svn blame WP_Rewrite::generate_rewrite_rules * * @subcommand blame * @synopsis <function> [--filename=<filename>] [--no-docblock] */ public function blame($args, $assoc_args) { $assoc_args = array_merge(array('filename' => false, 'docblock' => true), $assoc_args); $func = explode('::', $args[0], 2); $revision = false; $prompt = 'b'; $do_docblock = false; if (2 === count($func)) { $function_name = $func[1]; } else { $function_name = $func[0]; } while ('q' != $prompt) { switch ($prompt) { case 'v': $url = sprintf('https://core.trac.wordpress.org/changeset/%d', $latest); $cmd = Utils\esc_cmd('open %s', $url); WP_CLI::line('Opening changeset in your browser'); $text = self::launch_command($cmd); if (is_wp_error($text)) { WP_CLI::error($text); } break; case 'g': $go = intval($this->prompt('Enter revision number', '')); if (!$go) { break; } else { $revision = $go; // fall through } case 'b': // ---------------------------------- if (!$revision && !$assoc_args['filename']) { try { if (2 === count($func)) { $ref = new ReflectionMethod($func[0], $func[1]); } else { $ref = new ReflectionFunction($func[0]); } $filename = $ref->getFileName(); } catch (ReflectionException $e) { // @TODO message about using the --filename arg WP_CLI::error($e->getMessage()); } } else { if ($assoc_args['filename']) { if (file_exists($assoc_args['filename'])) { $filename = $assoc_args['filename']; } elseif (file_exists(ABSPATH . $assoc_args['filename'])) { $filename = ABSPATH . $assoc_args['filename']; } else { WP_CLI::error(sprintf("File '%s' does not exist", $assoc_args['filename'])); } } } if ($revision) { $cmd = Utils\esc_cmd('svn blame %s@%s', $filename, $revision); WP_CLI::line(sprintf('Fetching r%d...', $revision)); WP_CLI::line('This can be *very* slow for large files'); } else { $cmd = Utils\esc_cmd('svn blame %s', $filename); } $text = self::launch_command($cmd); if (is_wp_error($text)) { WP_CLI::error($text); } $text = str_replace(array("\r\n", "\r"), "\n", $text); $data = explode("\n", "\n" . $text); $lazy_explode = explode(sprintf('function %s', $function_name), $text, 2); $start_line = substr_count($lazy_explode[0], "\n") + 1; $func_onwards = explode("\n", $lazy_explode[1]); $func_length = 0; foreach ($func_onwards as $k => $v) { if (18 === strpos($v, '}')) { $func_length = $k; break; } } if (empty($func_length)) { WP_CLI::error('¯\\_(ツ)_/¯'); } $do_docblock = $assoc_args['docblock'] && ' */' === substr($data[$start_line - 1], 18, 3); if ($do_docblock) { while ('/**' !== substr($data[$start_line], 18, 3)) { $start_line--; $func_length++; } } $data = $raw_data = array_slice($data, $start_line, $func_length + 1, true); $revisions = array(); $data = array_map(function ($line, $value) use(&$revisions) { if (preg_match('|^[ ]*([0-9]+)|', $value, $matches)) { $revisions[$line] = intval($matches[1]); } return $value; }, array_keys($data), $data); $revision_list = array_unique($revisions); rsort($revision_list); $latest = $revision_list[0]; $out = array_map(function ($line, $value) use($revision_list) { $n = str_pad($line, 4, ' ', STR_PAD_LEFT); $return = "{$n} | {$value}"; if (preg_match('|^[ ]*([0-9]+)|', $value, $matches)) { if ($matches[1] == $revision_list[0]) { $return = WP_CLI::colorize('%K' . $return . '%n'); } } return $return; }, array_keys($raw_data), $data); WP_CLI::line(str_repeat('-', 100)); if ($revision) { WP_CLI::line(sprintf('%s() at r%s', $function_name, $revision)); } else { WP_CLI::line(sprintf('%s() in your working copy', $function_name)); } WP_CLI::line(str_repeat('-', 100)); WP_CLI::line(''); WP_CLI::line(implode("\n", $out)); WP_CLI::line(''); WP_CLI::line(str_repeat('-', 100)); $revision = $revision_list[1]; break; } WP_CLI::line(''); WP_CLI::line(sprintf('[v] View changeset in your browser (r%d)', $latest)); WP_CLI::line(sprintf('[b] Back in history (r%d)', $revision)); WP_CLI::line('[g] Go directly to a specified revision'); WP_CLI::line('[q] Quit'); WP_CLI::line(''); $prompt = strtolower($this->prompt('What next?', '?')); } WP_CLI::success('DONE'); }
/** * Download core WordPress files. * * Downloads and extracts WordPress core files to the specified path. Uses * an archive file stored in cache if WordPress has been previously * downloaded. * * ## OPTIONS * * [--path=<path>] * : Specify the path in which to install WordPress. * * [--locale=<locale>] * : Select which language you want to download. * * [--version=<version>] * : Select which version you want to download. Accepts a version number, 'latest' or 'nightly' * * [--force] * : Overwrites existing files, if present. * * ## EXAMPLES * * $ wp core download --locale=nl_NL * Downloading WordPress 4.5.2 (nl_NL)... * md5 hash verified: c5366d05b521831dd0b29dfc386e56a5 * Success: WordPress downloaded. * * @when before_wp_load */ public function download($args, $assoc_args) { $download_dir = !empty($assoc_args['path']) ? $assoc_args['path'] : ABSPATH; $wordpress_present = is_readable($download_dir . 'wp-load.php'); if (!\WP_CLI\Utils\get_flag_value($assoc_args, 'force') && $wordpress_present) { WP_CLI::error('WordPress files seem to already be present here.'); } if (!is_dir($download_dir)) { if (!is_writable(dirname($download_dir))) { WP_CLI::error(sprintf("Insufficient permission to create directory '%s'.", $download_dir)); } WP_CLI::log(sprintf("Creating directory '%s'.", $download_dir)); $mkdir = \WP_CLI\Utils\is_windows() ? 'mkdir %s' : 'mkdir -p %s'; WP_CLI::launch(Utils\esc_cmd($mkdir, $download_dir)); } if (!is_writable($download_dir)) { WP_CLI::error(sprintf("'%s' is not writable by current user.", $download_dir)); } $locale = \WP_CLI\Utils\get_flag_value($assoc_args, 'locale', 'en_US'); if (isset($assoc_args['version']) && 'latest' !== $assoc_args['version']) { $version = $assoc_args['version']; $version = in_array(strtolower($version), array('trunk', 'nightly')) ? 'nightly' : $version; //nightly builds are only available in .zip format $ext = 'nightly' === $version ? 'zip' : 'tar.gz'; $download_url = $this->get_download_url($version, $locale, $ext); } else { $offer = $this->get_download_offer($locale); if (!$offer) { WP_CLI::error("The requested locale ({$locale}) was not found."); } $version = $offer['current']; $download_url = str_replace('.zip', '.tar.gz', $offer['download']); } if ('nightly' === $version && 'en_US' !== $locale) { WP_CLI::error('Nightly builds are only available for the en_US locale.'); } $from_version = ''; if (file_exists($download_dir . 'wp-includes/version.php')) { global $wp_version; require_once $download_dir . 'wp-includes/version.php'; $from_version = $wp_version; } WP_CLI::log(sprintf('Downloading WordPress %s (%s)...', $version, $locale)); $path_parts = pathinfo($download_url); $extension = 'tar.gz'; if ('zip' === $path_parts['extension']) { $extension = 'zip'; if (!class_exists('ZipArchive')) { WP_CLI::error('Extracting a zip file requires ZipArchive.'); } } $cache = WP_CLI::get_cache(); $cache_key = "core/wordpress-{$version}-{$locale}.{$extension}"; $cache_file = $cache->has($cache_key); $bad_cache = false; if ($cache_file) { WP_CLI::log("Using cached file '{$cache_file}'..."); try { Extractor::extract($cache_file, $download_dir); } catch (Exception $e) { WP_CLI::warning("Extraction failed, downloading a new copy..."); $bad_cache = true; } } if (!$cache_file || $bad_cache) { // We need to use a temporary file because piping from cURL to tar is flaky // on MinGW (and probably in other environments too). $temp = \WP_CLI\Utils\get_temp_dir() . uniqid('wp_') . ".{$extension}"; $headers = array('Accept' => 'application/json'); $options = array('timeout' => 600, 'filename' => $temp); $response = Utils\http_request('GET', $download_url, null, $headers, $options); if (404 == $response->status_code) { WP_CLI::error("Release not found. Double-check locale or version."); } else { if (20 != substr($response->status_code, 0, 2)) { WP_CLI::error("Couldn't access download URL (HTTP code {$response->status_code})."); } } if ('nightly' !== $version) { $md5_response = Utils\http_request('GET', $download_url . '.md5'); if (20 != substr($md5_response->status_code, 0, 2)) { WP_CLI::error("Couldn't access md5 hash for release (HTTP code {$response->status_code})."); } $md5_file = md5_file($temp); if ($md5_file === $md5_response->body) { WP_CLI::log('md5 hash verified: ' . $md5_file); } else { WP_CLI::error("md5 hash for download ({$md5_file}) is different than the release hash ({$md5_response->body})."); } } else { WP_CLI::warning('md5 hash checks are not available for nightly downloads.'); } try { Extractor::extract($temp, $download_dir); } catch (Exception $e) { WP_CLI::error("Couldn't extract WordPress archive. " . $e->getMessage()); } if ('nightly' !== $version) { $cache->import($cache_key, $temp); } unlink($temp); } if ($wordpress_present) { $this->cleanup_extra_files($from_version, $version, $locale); } WP_CLI::success('WordPress downloaded.'); }
public function download_wp($subdir = '') { $dest_dir = $this->variables['RUN_DIR'] . "/{$subdir}"; if ($subdir) { mkdir($dest_dir); } $this->proc(Utils\esc_cmd("cp -r %s/* %s", self::$cache_dir, $dest_dir))->run_check(); // disable emailing mkdir($dest_dir . '/wp-content/mu-plugins'); copy(__DIR__ . '/../extra/no-mail.php', $dest_dir . '/wp-content/mu-plugins/no-mail.php'); symlink(dirname(dirname(dirname(dirname(dirname(__FILE__))))), $dest_dir . '/wp-content/plugins/woocommerce'); }