Exemple #1
0
 /**
  * Install a WP-CLI package.
  *
  * Packages are required to be a valid Composer package, and can be
  * specified as:
  *
  * * Package name from WP-CLI's package index.
  * * Git URL accessible by the current shell user.
  * * Path to a directory on the local machine.
  * * Local or remote .zip file.
  *
  * When installing a local directory, WP-CLI simply registers a
  * reference to the directory. If you move or delete the directory, WP-CLI's
  * reference breaks.
  *
  * When installing a .zip file, WP-CLI extracts the package to
  * `~/.wp-cli/packages/local/<package-name>`.
  *
  * ## OPTIONS
  *
  * <name|git|path|zip>
  * : Name, git URL, directory path, or .zip file for the package to install.
  * Names can optionally include a version constraint
  * (e.g. wp-cli/server-command:@stable).
  *
  * ## EXAMPLES
  *
  *     # Install the latest development version from the package index.
  *     $ wp package install wp-cli/server-command
  *     Installing package wp-cli/server-command (dev-master)
  *     Updating /home/person/.wp-cli/packages/composer.json to require the package...
  *     Using Composer to install the package...
  *     ---
  *     Loading composer repositories with package information
  *     Updating dependencies
  *     Resolving dependencies through SAT
  *     Dependency resolution completed in 0.005 seconds
  *     Analyzed 732 packages to resolve dependencies
  *     Analyzed 1034 rules to resolve dependencies
  *      - Installing package
  *     Writing lock file
  *     Generating autoload files
  *     ---
  *     Success: Package installed.
  *
  *     # Install the latest stable version.
  *     $ wp package install wp-cli/server-command:@stable
  *
  *     # Install a package hosted at a git URL.
  *     $ wp package install git@github.com:runcommand/hook.git
  *
  *     # Install a package in a .zip file.
  *     $ wp package install google-sitemap-generator-cli.zip
  */
 public function install($args, $assoc_args)
 {
     list($package_name) = $args;
     $git_package = $dir_package = false;
     $version = 'dev-master';
     if ('.git' === strtolower(substr($package_name, -4, 4))) {
         $git_package = $package_name;
         preg_match('#([^:\\/]+\\/[^\\/]+)\\.git#', $package_name, $matches);
         if (!empty($matches[1])) {
             $package_name = $matches[1];
         } else {
             WP_CLI::error("Couldn't parse package name from expected path '<name>/<package>'.");
         }
     } else {
         if (false !== strpos($package_name, '://') && false !== stripos($package_name, '.zip') || pathinfo($package_name, PATHINFO_EXTENSION) === 'zip' && is_file($package_name)) {
             // Download the remote ZIP file to a temp directory
             if (false !== strpos($package_name, '://')) {
                 $temp = Utils\get_temp_dir() . uniqid('package_') . ".zip";
                 $options = array('timeout' => 600, 'filename' => $temp);
                 $response = Utils\http_request('GET', $package_name, null, array(), $options);
                 if (20 != substr($response->status_code, 0, 2)) {
                     WP_CLI::error("Couldn't download package.");
                 }
                 $package_name = $temp;
             }
             $dir_package = Utils\get_temp_dir() . uniqid('package_');
             try {
                 // Extract the package to get the package name
                 Extractor::extract($package_name, $dir_package);
                 list($package_name, $version) = self::get_package_name_and_version_from_dir_package($dir_package);
                 // Move to a location based on the package name
                 $local_dir = rtrim(WP_CLI::get_runner()->get_packages_dir_path(), '/') . '/local/';
                 $actual_dir_package = $local_dir . str_replace('/', '-', $package_name);
                 Extractor::copy_overwrite_files($dir_package, $actual_dir_package);
                 Extractor::rmdir($dir_package);
                 // Behold, the extracted package
                 $dir_package = $actual_dir_package;
             } catch (Exception $e) {
                 WP_CLI::error($e->getMessage());
             }
         } else {
             if (is_dir($package_name) && file_exists($package_name . '/composer.json')) {
                 $dir_package = $package_name;
                 if (!Utils\is_path_absolute($dir_package)) {
                     $dir_package = getcwd() . DIRECTORY_SEPARATOR . $dir_package;
                 }
                 list($package_name, $version) = self::get_package_name_and_version_from_dir_package($dir_package);
             } else {
                 if (false !== strpos($package_name, ':')) {
                     list($package_name, $version) = explode(':', $package_name);
                 }
                 $package = $this->get_community_package_by_name($package_name);
                 if (!$package) {
                     WP_CLI::error("Invalid package.");
                 }
             }
         }
     }
     WP_CLI::log(sprintf("Installing package %s (%s)", $package_name, $version));
     $composer_json_obj = $this->get_composer_json();
     // Add the 'require' to composer.json
     WP_CLI::log(sprintf("Updating %s to require the package...", $composer_json_obj->getPath()));
     $composer_backup = file_get_contents($composer_json_obj->getPath());
     $json_manipulator = new JsonManipulator($composer_backup);
     $json_manipulator->addMainKey('name', 'wp-cli/wp-cli');
     $json_manipulator->addMainKey('version', self::get_wp_cli_version_composer());
     $json_manipulator->addLink('require', $package_name, $version);
     $json_manipulator->addConfigSetting('secure-http', true);
     if ($git_package) {
         WP_CLI::log(sprintf('Registering %s as a VCS repository...', $git_package));
         $json_manipulator->addRepository($package_name, array('type' => 'vcs', 'url' => $git_package));
     } else {
         if ($dir_package) {
             WP_CLI::log(sprintf('Registering %s as a path repository...', $dir_package));
             $json_manipulator->addRepository($package_name, array('type' => 'path', 'url' => $dir_package));
         }
     }
     $composer_backup_decoded = json_decode($composer_backup, true);
     // If the composer file does not contain the current package index repository, refresh the repository definition.
     if (empty($composer_backup_decoded['repositories']['wp-cli']['url']) || self::PACKAGE_INDEX_URL != $composer_backup_decoded['repositories']['wp-cli']['url']) {
         WP_CLI::log('Updating package index repository url...');
         $json_manipulator->addRepository('wp-cli', array('type' => 'composer', 'url' => self::PACKAGE_INDEX_URL));
     }
     file_put_contents($composer_json_obj->getPath(), $json_manipulator->getContents());
     try {
         $composer = $this->get_composer();
     } catch (Exception $e) {
         WP_CLI::error($e->getMessage());
     }
     // Set up the EventSubscriber
     $event_subscriber = new \WP_CLI\PackageManagerEventSubscriber();
     $composer->getEventDispatcher()->addSubscriber($event_subscriber);
     // Set up the installer
     $install = Installer::create(new ComposerIO(), $composer);
     $install->setUpdate(true);
     // Installer class will only override composer.lock with this flag
     $install->setPreferSource(true);
     // Use VCS when VCS for easier contributions.
     // Try running the installer, but revert composer.json if failed
     WP_CLI::log('Using Composer to install the package...');
     WP_CLI::log('---');
     $res = false;
     try {
         $res = $install->run();
     } catch (Exception $e) {
         WP_CLI::warning($e->getMessage());
     }
     WP_CLI::log('---');
     if (0 === $res) {
         WP_CLI::success("Package installed.");
     } else {
         file_put_contents($composer_json_obj->getPath(), $composer_backup);
         WP_CLI::error("Package installation failed (Composer return code {$res}). Reverted composer.json");
     }
 }
Exemple #2
0
 /**
  * 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.');
 }