Exemplo n.º 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");
     }
 }
Exemplo n.º 2
0
 /**
  * Security copy of the core function with Requests - Gets the checksums for the given version of WordPress.
  *
  * @param string $version Version string to query.
  * @param string $locale  Locale to query.
  * @return bool|array False on failure. An array of checksums on success.
  */
 private static function get_core_checksums($version, $locale)
 {
     $url = $http_url = 'http://api.wordpress.org/core/checksums/1.0/?' . http_build_query(compact('version', 'locale'), null, '&');
     if ($ssl = wp_http_supports(array('ssl'))) {
         $url = 'https' . substr($url, 4);
     }
     $options = array('timeout' => 30);
     $headers = array('Accept' => 'application/json');
     $response = Utils\http_request('GET', $url, null, $headers, $options);
     if ($ssl && !$response->success) {
         WP_CLI::warning('wp-cli could not establish a secure connection to WordPress.org. Please contact your server administrator.');
         $response = Utils\http_request('GET', $http_url, null, $headers, $options);
     }
     if (!$response->success || 200 != $response->status_code) {
         return false;
     }
     $body = trim($response->body);
     $body = json_decode($body, true);
     if (!is_array($body) || !isset($body['checksums']) || !is_array($body['checksums'])) {
         return false;
     }
     return $body['checksums'];
 }
Exemplo n.º 3
0
 /**
  * Returns update information.
  */
 private function get_updates($assoc_args)
 {
     $url = 'https://api.github.com/repos/wp-cli/wp-cli/releases';
     $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(sprintf("Failed to get latest version (HTTP code %d).", $response->status_code));
     }
     $release_data = json_decode($response->body);
     $updates = array('major' => false, 'minor' => false, 'patch' => false);
     foreach ($release_data as $release) {
         // Get rid of leading "v" if there is one set.
         $release_version = $release->tag_name;
         if ('v' === substr($release_version, 0, 1)) {
             $release_version = ltrim($release_version, 'v');
         }
         $update_type = Utils\get_named_sem_ver($release_version, WP_CLI_VERSION);
         if (!$update_type) {
             continue;
         }
         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' => $release->assets[0]->browser_download_url);
     }
     foreach ($updates as $type => $value) {
         if (empty($value)) {
             unset($updates[$type]);
         }
     }
     foreach (array('major', 'minor', 'patch') as $type) {
         if (true === \WP_CLI\Utils\get_flag_value($assoc_args, $type)) {
             return !empty($updates[$type]) ? array($updates[$type]) : false;
         }
     }
     if (empty($updates) && preg_match('#-alpha-(.+)$#', WP_CLI_VERSION, $matches)) {
         $version_url = 'https://raw.githubusercontent.com/wp-cli/builds/gh-pages/phar/NIGHTLY_VERSION';
         $response = Utils\http_request('GET', $version_url);
         if (!$response->success || 200 !== $response->status_code) {
             WP_CLI::error(sprintf("Failed to get current nightly version (HTTP code %d)", $response->status_code));
         }
         $nightly_version = trim($response->body);
         if (WP_CLI_VERSION != $nightly_version) {
             $updates['nightly'] = array('version' => $nightly_version, 'update_type' => 'nightly', 'package_url' => 'https://raw.githubusercontent.com/wp-cli/builds/gh-pages/phar/wp-cli-nightly.phar');
         }
     }
     return array_values($updates);
 }
Exemplo n.º 4
0
 /**
  * Returns update information
  */
 private function get_updates($assoc_args)
 {
     $url = 'https://api.github.com/repos/wp-cli/wp-cli/releases';
     $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(sprintf("Failed to get latest version (HTTP code %d)", $response->status_code));
     }
     $release_data = json_decode($response->body);
     $current_parts = explode('.', WP_CLI_VERSION);
     $updates = array();
     foreach ($release_data as $release) {
         $release_version = $release->tag_name;
         // get rid of leading "v"
         if ('v' === substr($release_version, 0, 1)) {
             $release_version = ltrim($release_version, 'v');
         }
         // don't list earlier releases
         if (version_compare($release_version, WP_CLI_VERSION, '<=')) {
             continue;
         }
         $release_parts = explode('.', $release_version);
         $update_type = 'minor';
         if ($release_parts[0] === $current_parts[0] && $release_parts[1] === $current_parts[1]) {
             $update_type = 'patch';
         }
         if (!(\WP_CLI\Utils\get_flag_value($assoc_args, 'patch') && 'patch' !== $update_type) && !(\WP_CLI\Utils\get_flag_value($assoc_args, 'patch') === false && 'patch' === $update_type) && !(\WP_CLI\Utils\get_flag_value($assoc_args, 'minor') && 'minor' !== $update_type) && !(\WP_CLI\Utils\get_flag_value($assoc_args, 'minor') === false && 'minor' === $update_type) && !$this->same_minor_release($release_parts, $updates)) {
             $updates[] = array('version' => $release_version, 'update_type' => $update_type, 'package_url' => $release->assets[0]->browser_download_url);
         }
     }
     return $updates;
 }
Exemplo n.º 5
0
 /**
  * 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);
 }
Exemplo n.º 6
0
 /**
  * Security copy of the core function with Requests - Gets the checksums for the given version of WordPress.
  *
  * @param string $version Version string to query.
  * @param string $locale  Locale to query.
  * @return bool|array False on failure. An array of checksums on success.
  */
 private static function get_core_checksums($version, $locale)
 {
     $url = 'https://api.wordpress.org/core/checksums/1.0/?' . http_build_query(compact('version', 'locale'), null, '&');
     $options = array('timeout' => 30);
     $headers = array('Accept' => 'application/json');
     $response = Utils\http_request('GET', $url, null, $headers, $options);
     if (!$response->success || 200 != $response->status_code) {
         return false;
     }
     $body = trim($response->body);
     $body = json_decode($body, true);
     if (!is_array($body) || !isset($body['checksums']) || !is_array($body['checksums'])) {
         return false;
     }
     return $body['checksums'];
 }
Exemplo n.º 7
0
 /**
  * Get the index data from an API url
  *
  * @param string $api_url
  * @return array|false
  */
 private static function get_api_index($api_url)
 {
     $query_char = false !== strpos($api_url, '?') ? '&' : '?';
     $api_url .= $query_char . 'context=help';
     $response = Utils\http_request('GET', $api_url);
     if (empty($response->body)) {
         return false;
     }
     return json_decode($response->body, true);
 }
Exemplo n.º 8
0
 /**
  * Do a REST Request
  *
  * @param string $method
  * 
  */
 private function do_request($method, $route, $assoc_args)
 {
     if ('internal' === $this->scope) {
         $request = new \WP_REST_Request($method, $route);
         if (in_array($method, array('POST', 'PUT'))) {
             $request->set_body_params($assoc_args);
         } else {
             foreach ($assoc_args as $key => $value) {
                 $request->set_param($key, $value);
             }
         }
         $response = rest_do_request($request);
         if ($error = $response->as_error()) {
             WP_CLI::error($error);
         }
         return array($response->get_status(), $response->get_data(), $response->get_headers());
     } else {
         if ('http' === $this->scope) {
             $response = Utils\http_request($method, rtrim($this->api_url, '/') . $route, $assoc_args);
             $body = json_decode($response->body, true);
             if ($response->status_code >= 400) {
                 if (!empty($body['message'])) {
                     WP_CLI::error($body['message'] . ' ' . json_encode(array('status' => $response->status_code)));
                 } else {
                     switch ($response->status_code) {
                         case 404:
                             WP_CLI::error("No {$this->name} found.");
                             break;
                         default:
                             WP_CLI::error('Could not complete request.');
                             break;
                     }
                 }
             }
             return array($response->status_code, json_decode($response->body, true), $response->headers);
         }
     }
     WP_CLI::error('Invalid scope for REST command.');
 }
 /**
  * Check for update via Github API. Returns the available versions if there are updates, or empty if no update available.
  *
  * ## OPTIONS
  *
  * [--patch]
  * : Compare only the first two parts of the version number.
  *
  * [--minor]
  * : Compare only the first part of the version number.
  *
  * [--field=<field>]
  * : Prints the value of a single field for each update.
  *
  * [--fields=<fields>]
  * : Limit the output to specific object fields. Defaults to version,update_type,package_url.
  *
  * [--format=<format>]
  * : Accepted values: table, csv, json, count. Default: table
  *
  * @subcommand check-update
  */
 function check_update($_, $assoc_args)
 {
     $url = 'https://api.github.com/repos/wp-cli/wp-cli/releases';
     $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.");
     }
     $release_data = json_decode($response->body);
     $current_parts = explode('.', WP_CLI_VERSION);
     $updates = array();
     foreach ($release_data as $release) {
         $release_version = $release->tag_name;
         // get rid of leading "v"
         if ('v' === substr($release_version, 0, 1)) {
             $release_version = ltrim($release_version, 'v');
         }
         // don't list earlier releases
         if (version_compare($release_version, WP_CLI_VERSION, '<=')) {
             continue;
         }
         $release_parts = explode('.', $release_version);
         $update_type = 'minor';
         if ($release_parts[0] === $current_parts[0] && $release_parts[1] === $current_parts[1]) {
             $update_type = 'patch';
         }
         if (!(isset($assoc_args['patch']) && 'patch' !== $update_type) && !(isset($assoc_args['minor']) && 'minor' !== $update_type) && !$this->same_minor_release($release_parts, $updates)) {
             $updates[] = array('version' => $release_version, 'update_type' => $update_type, 'package_url' => $release->assets[0]->browser_download_url);
         }
     }
     if ($updates) {
         $formatter = new \WP_CLI\Formatter($assoc_args, array('version', 'update_type', 'package_url'));
         $formatter->display_items($updates);
     } else {
         if (empty($assoc_args['format']) || 'table' == $assoc_args['format']) {
             WP_CLI::success("WP-CLI is at the latest version.");
         }
     }
 }