diff --git a/composer.json b/composer.json index 956d608b..2a97564e 100644 --- a/composer.json +++ b/composer.json @@ -20,14 +20,15 @@ "wp-cli/db-command": "^1.3 || ^2", "wp-cli/entity-command": "^1.3 || ^2", "wp-cli/extension-command": "^1.2 || ^2", - "wp-cli/wp-cli-tests": "^4" + "wp-cli/wp-cli-tests": "dev-add/phpstan-enhancements" }, "config": { "process-timeout": 7200, "sort-packages": true, "allow-plugins": { "dealerdirect/phpcodesniffer-composer-installer": true, - "johnpbloch/wordpress-core-installer": true + "johnpbloch/wordpress-core-installer": true, + "phpstan/extension-installer": true }, "lock": false }, @@ -64,12 +65,14 @@ "behat-rerun": "rerun-behat-tests", "lint": "run-linter-tests", "phpcs": "run-phpcs-tests", + "phpstan": "run-phpstan-tests", "phpcbf": "run-phpcbf-cleanup", "phpunit": "run-php-unit-tests", "prepare-tests": "install-package-tests", "test": [ "@lint", "@phpcs", + "@phstan", "@phpunit", "@behat" ] diff --git a/features/core-update.feature b/features/core-update.feature index 8941bda4..fd8eb701 100644 --- a/features/core-update.feature +++ b/features/core-update.feature @@ -1,77 +1,42 @@ Feature: Update WordPress core - # This test downgrades to an older WordPress version, but the SQLite plugin requires 6.0+ + # This test downgrades to an older WordPress version, but the SQLite plugin requires 6.4+ @require-mysql Scenario: Update from a ZIP file Given a WP install And I try `wp theme install twentytwenty --activate` - When I run `wp core download --version=3.9 --force` + When I run `wp core download --version=6.2 --force` Then STDOUT should not be empty - When I run `wp eval 'echo $GLOBALS["wp_version"];'` + When I try `wp eval 'echo $GLOBALS["wp_version"];'` Then STDOUT should be: """ - 3.9 + 6.2 """ - When I run `wget http://wordpress.org/wordpress-4.0.zip --quiet` - And I run `wp core update wordpress-4.0.zip` + When I run `wget http://wordpress.org/wordpress-6.2.zip --quiet` + And I run `wp core update wordpress-6.2.zip` Then STDOUT should be: """ Starting update... Unpacking the update... - Cleaning up files... - No files found that need cleaning up. - Success: WordPress updated successfully. - """ - - When I run `wp eval 'echo $GLOBALS["wp_version"];'` - Then STDOUT should be: - """ - 4.0 - """ - - # PHP 7.1 needs WP 3.9 (due to wp_check_php_mysql_versions(), see trac changeset [27257]), - # and travis doesn't install mysql extension by default for PHP 7.0. - @less-than-php-7 - Scenario: Update to the latest minor release - Given a WP install - And I try `wp theme install twentytwenty --activate` - - When I run `wp core download --version=4.1 --force` - Then STDOUT should not be empty - - # WP core throws notice for PHP 8+. - When I try `wp core update --minor` - Then STDOUT should contain: - """ - Updating to version {WP_VERSION-4.1-latest} - """ - And STDOUT should contain: - """ Success: WordPress updated successfully. """ - When I run `wp core update --minor` - Then STDOUT should be: - """ - Success: WordPress is at the latest minor release. - """ - - When I run `wp core version` + When I try `wp eval 'echo $GLOBALS["wp_version"];'` Then STDOUT should be: """ - {WP_VERSION-4.1-latest} + 6.2 """ - # This test downgrades to an older WordPress version, but the SQLite plugin requires 6.0+ + # This test downgrades to an older WordPress version, but the SQLite plugin requires 6.4+ @require-mysql - Scenario: Update to the latest minor release (PHP 7.1 compatible with WP >= 3.9) + Scenario: Update to the latest minor release (PHP 7.2 compatible with WP >= 4.9) Given a WP install And I try `wp theme install twentytwenty --activate` - When I run `wp core download --version=4.1.30 --force` + When I run `wp core download --version=6.2.5 --force` Then STDOUT should contain: """ Success: WordPress downloaded. @@ -81,7 +46,7 @@ Feature: Update WordPress core When I try `wp core update --minor` Then STDOUT should contain: """ - Updating to version {WP_VERSION-4.1-latest} + Updating to version {WP_VERSION-6.2-latest} """ And STDOUT should contain: """ @@ -98,17 +63,17 @@ Feature: Update WordPress core When I run `wp core version` Then STDOUT should be: """ - {WP_VERSION-4.1-latest} + {WP_VERSION-6.2-latest} """ - # This test downgrades to an older WordPress version, but the SQLite plugin requires 6.0+ + # This test downgrades to an older WordPress version, but the SQLite plugin requires 6.4+ @require-mysql Scenario: Core update from cache Given a WP install And I try `wp theme install twentytwenty --activate` And an empty cache - When I run `wp core update --version=3.9.1 --force` + When I run `wp core update --version=6.2.5 --force` Then STDOUT should not contain: """ Using cached file @@ -118,13 +83,13 @@ Feature: Update WordPress core Downloading """ - When I run `wp core update --version=4.0 --force` + When I run `wp core update --version=6.0 --force` Then STDOUT should not be empty - When I run `wp core update --version=3.9.1 --force` + When I run `wp core update --version=6.2.5 --force` Then STDOUT should contain: """ - Using cached file '{SUITE_CACHE_DIR}/core/wordpress-3.9.1-en_US.zip'... + Using cached file '{SUITE_CACHE_DIR}/core/wordpress-6.2.5-en_US.zip'... """ And STDOUT should not contain: """ diff --git a/phpstan.neon.dist b/phpstan.neon.dist new file mode 100644 index 00000000..30337dab --- /dev/null +++ b/phpstan.neon.dist @@ -0,0 +1,19 @@ +parameters: + level: 9 + paths: + - src + - core-command.php + scanDirectories: + - vendor/wp-cli/wp-cli/php + - vendor/wp-cli/wp-cli-tests + scanFiles: + - vendor/php-stubs/wordpress-stubs/wordpress-stubs.php + treatPhpDocTypesAsCertain: false + dynamicConstantNames: + - WP_DEBUG + - WP_DEBUG_LOG + - WP_DEBUG_DISPLAY + ignoreErrors: + - identifier: missingType.iterableValue + - identifier: missingType.parameter + - identifier: missingType.return diff --git a/src/Core_Command.php b/src/Core_Command.php index 7539fefc..3dd85bf6 100644 --- a/src/Core_Command.php +++ b/src/Core_Command.php @@ -75,8 +75,11 @@ class Core_Command extends WP_CLI_Command { * +---------+-------------+-------------------------------------------------------------+ * * @subcommand check-update + * + * @param string[] $args Positional arguments. Unused. + * @param array{minor?: bool, major?: bool, 'force-check'?: bool, field?: string, format: string} $assoc_args Associative arguments. */ - public function check_update( $_, $assoc_args ) { + public function check_update( $args, $assoc_args ) { $format = Utils\get_flag_value( $assoc_args, 'format', 'table' ); $updates = $this->get_updates( $assoc_args ); @@ -136,8 +139,14 @@ public function check_update( $_, $assoc_args ) { * Success: WordPress downloaded. * * @when before_wp_load + * + * @param array{0?: string} $args Positional arguments. + * @param array{path?: string, locale?: string, version?: string, 'skip-content'?: bool, force?: bool, insecure?: bool, extract?: bool} $assoc_args Associative arguments. */ public function download( $args, $assoc_args ) { + /** + * @var string $download_dir + */ $download_dir = ! empty( $assoc_args['path'] ) ? ( rtrim( $assoc_args['path'], '/\\' ) . '/' ) : ABSPATH; @@ -160,7 +169,11 @@ public function download( $args, $assoc_args ) { WP_CLI::log( "Creating directory '{$download_dir}'." ); if ( ! @mkdir( $download_dir, 0777, true /*recursive*/ ) ) { $error = error_get_last(); - WP_CLI::error( "Failed to create directory '{$download_dir}': {$error['message']}." ); + if ( $error ) { + WP_CLI::error( "Failed to create directory '{$download_dir}': {$error['message']}." ); + } else { + WP_CLI::error( "Failed to create directory '{$download_dir}'." ); + } } } @@ -168,10 +181,10 @@ public function download( $args, $assoc_args ) { WP_CLI::error( "'{$download_dir}' is not writable by current user." ); } - $locale = (string) Utils\get_flag_value( $assoc_args, 'locale', 'en_US' ); - $skip_content = (bool) Utils\get_flag_value( $assoc_args, 'skip-content', false ); - $insecure = (bool) Utils\get_flag_value( $assoc_args, 'insecure', false ); - $extract = (bool) Utils\get_flag_value( $assoc_args, 'extract', true ); + $locale = Utils\get_flag_value( $assoc_args, 'locale', 'en_US' ); + $skip_content = Utils\get_flag_value( $assoc_args, 'skip-content', false ); + $insecure = Utils\get_flag_value( $assoc_args, 'insecure', false ); + $extract = Utils\get_flag_value( $assoc_args, 'extract', true ); if ( $skip_content && ! $extract ) { WP_CLI::error( 'Cannot use both --skip-content and --no-extract at the same time.' ); @@ -235,7 +248,7 @@ public function download( $args, $assoc_args ) { $path_parts = pathinfo( $download_url ); $extension = 'tar.gz'; - if ( 'zip' === $path_parts['extension'] ) { + if ( isset( $path_parts['extension'] ) && 'zip' === $path_parts['extension'] ) { $extension = 'zip'; if ( $extract && ! class_exists( 'ZipArchive' ) ) { WP_CLI::error( 'Extracting a zip file requires ZipArchive.' ); @@ -256,7 +269,7 @@ public function download( $args, $assoc_args ) { $bad_cache = false; - if ( $cache_file ) { + if ( is_string( $cache_file ) ) { WP_CLI::log( "Using cached file '{$cache_file}'..." ); $skip_content_cache_file = $skip_content ? self::strip_content_dir( $cache_file ) : null; if ( $extract ) { @@ -290,16 +303,18 @@ function () use ( $temp ) { 'insecure' => $insecure, ]; + /** @var \WpOrg\Requests\Response $response */ $response = Utils\http_request( 'GET', $download_url, null, $headers, $options ); if ( 404 === (int) $response->status_code ) { WP_CLI::error( 'Release not found. Double-check locale or version.' ); - } elseif ( 20 !== (int) substr( $response->status_code, 0, 2 ) ) { + } elseif ( 20 !== (int) substr( (string) $response->status_code, 0, 2 ) ) { WP_CLI::error( "Couldn't access download URL (HTTP code {$response->status_code})." ); } if ( 'nightly' !== $version ) { unset( $options['filename'] ); + /** @var \WpOrg\Requests\Response $md5_response */ $md5_response = Utils\http_request( 'GET', $download_url . '.md5', null, [], $options ); if ( $md5_response->status_code >= 200 && $md5_response->status_code < 300 ) { $md5_file = md5_file( $temp ); @@ -373,11 +388,12 @@ function () use ( $temp ) { * fi * * @subcommand is-installed + * + * @param string[] $args Positional arguments. Unused. + * @param array{network?: bool} $assoc_args Associative arguments. */ public function is_installed( $args, $assoc_args ) { - if ( is_blog_installed() - && ( ! Utils\get_flag_value( $assoc_args, 'network' ) - || is_multisite() ) ) { + if ( is_blog_installed() && ( ! Utils\get_flag_value( $assoc_args, 'network' ) || is_multisite() ) ) { WP_CLI::halt( 0 ); } @@ -432,6 +448,9 @@ public function is_installed( $args, $assoc_args ) { * * # Install WordPress without disclosing admin_password to bash history * $ wp core install --url=example.com --title=Example --admin_user=supervisor --admin_email=info@example.com --prompt=admin_password < admin_password.txt + * + * @param string[] $args Positional arguments. Unused. + * @param array{url: string, title: string, admin_user: string, admin_password?: string, admin_email: string, locale?: string, 'skip-email'?: bool} $assoc_args Associative arguments. */ public function install( $args, $assoc_args ) { if ( $this->do_install( $assoc_args ) ) { @@ -479,6 +498,9 @@ public function install( $args, $assoc_args ) { * * @subcommand multisite-convert * @alias install-network + * + * @param string[] $args Positional arguments. Unused. + * @param array{title?: string, base: string, subdomains?: bool, 'skip-config'?: bool} $assoc_args Associative arguments. */ public function multisite_convert( $args, $assoc_args ) { if ( is_multisite() ) { @@ -487,8 +509,13 @@ public function multisite_convert( $args, $assoc_args ) { $assoc_args = self::set_multisite_defaults( $assoc_args ); if ( ! isset( $assoc_args['title'] ) ) { + /** + * @var string $blogname + */ + $blogname = get_option( 'blogname' ); + // translators: placeholder is blog name - $assoc_args['title'] = sprintf( _x( '%s Sites', 'Default network name' ), get_option( 'blogname' ) ); + $assoc_args['title'] = sprintf( _x( '%s Sites', 'Default network name' ), $blogname ); } if ( $this->multisite_convert_( $assoc_args ) ) { @@ -552,6 +579,9 @@ public function multisite_convert( $args, $assoc_args ) { * Success: Network installed. Don't forget to set up rewrite rules. * * @subcommand multisite-install + * + * @param string[] $args Positional arguments. Unused. + * @param array{url?: string, base: string, subdomains?: bool, title: string, admin_user: string, admin_password?: string, admin_email: string, 'skip-email'?: bool, 'skip-config'?: bool} $assoc_args Associative arguments. */ public function multisite_install( $args, $assoc_args ) { if ( $this->do_install( $assoc_args ) ) { @@ -619,6 +649,7 @@ private function do_install( $assoc_args ) { if ( true === Utils\get_flag_value( $assoc_args, 'skip-email' ) ) { if ( ! function_exists( 'wp_new_blog_notification' ) ) { + // @phpstan-ignore function.inner function wp_new_blog_notification() { // Silence is golden } @@ -636,18 +667,7 @@ function wp_new_blog_notification() { 'admin_password' => '', ]; - if ( Utils\wp_version_compare( '4.0', '<' ) ) { - if ( array_key_exists( 'locale', $assoc_args ) ) { - WP_CLI::warning( - sprintf( - 'The flag --locale=%s is being ignored as it requires WordPress 4.0+.', - $assoc_args['locale'] - ) - ); - } - } else { - $defaults['locale'] = ''; - } + $defaults['locale'] = ''; $args = wp_parse_args( $assoc_args, $defaults ); @@ -664,31 +684,15 @@ function wp_new_blog_notification() { WP_CLI::error( "The '{$args['admin_email']}' email address is invalid." ); } - if ( Utils\wp_version_compare( '4.0', '>=' ) ) { - $result = wp_install( - $args['title'], - $args['admin_user'], - $args['admin_email'], - $public, - '', - $password, - $args['locale'] - ); - } else { - $result = wp_install( - $args['title'], - $args['admin_user'], - $args['admin_email'], - $public, - '', - $password - ); - } - - if ( is_wp_error( $result ) ) { - $reason = WP_CLI::error_to_string( $result ); - WP_CLI::error( "Installation failed ({$reason})." ); - } + $result = wp_install( + $args['title'], + $args['admin_user'], + $args['admin_email'], + $public, + '', + $password, + $args['locale'] + ); if ( ! empty( $GLOBALS['wpdb']->last_error ) ) { WP_CLI::error( 'Installation produced database errors, and may have partially or completely failed.' ); @@ -724,10 +728,15 @@ private function multisite_convert_( $assoc_args ) { install_network(); + /** + * @var string $admin_email + */ + $admin_email = get_option( 'admin_email' ); + $result = populate_network( $assoc_args['site_id'], $domain, - get_option( 'admin_email' ), + $admin_email, $assoc_args['title'], $assoc_args['base'], $assoc_args['subdomains'] @@ -738,7 +747,7 @@ private function multisite_convert_( $assoc_args ) { if ( true === $result ) { WP_CLI::log( 'Set up multisite database tables.' ); - } elseif ( is_wp_error( $result ) ) { + } else { switch ( $result->get_error_code() ) { case 'siteid_exists': @@ -855,7 +864,7 @@ private static function modify_wp_config( $content ) { $wp_config_path = Utils\locate_wp_config(); $token = "/* That's all, stop editing!"; - $config_contents = file_get_contents( $wp_config_path ); + $config_contents = (string) file_get_contents( $wp_config_path ); if ( false === strpos( $config_contents, $token ) ) { return false; } @@ -873,8 +882,12 @@ private static function modify_wp_config( $content ) { } private static function get_clean_basedomain() { - $domain = preg_replace( '|https?://|', '', get_option( 'siteurl' ) ); - $slash = strpos( $domain, '/' ); + /** + * @var string $siteurl + */ + $siteurl = get_option( 'siteurl' ); + $domain = (string) preg_replace( '|https?://|', '', $siteurl ); + $slash = strpos( $domain, '/' ); if ( false !== $slash ) { $domain = substr( $domain, 0, $slash ); } @@ -903,6 +916,9 @@ private static function get_clean_basedomain() { * Package language: en_US * * @when before_wp_load + * + * @param string[] $args Positional arguments. Unused. + * @param array{extra?: bool} $assoc_args Associative arguments. */ public function version( $args = [], $assoc_args = [] ) { $details = self::get_wp_details(); @@ -951,7 +967,7 @@ private static function get_wp_details( $abspath = ABSPATH ) { ); } - $version_content = file_get_contents( $versions_path, false, null, 6, 2048 ); + $version_content = (string) file_get_contents( $versions_path, false, null, 6, 2048 ); $vars = [ 'wp_version', 'wp_db_version', 'tinymce_version', 'wp_local_package' ]; $result = []; @@ -987,7 +1003,7 @@ private static function get_template_path( $template ) { * @param string $var_name Variable name to search for. * @param string $code PHP code to search in. * - * @return int|string|null + * @return string|null */ private static function find_var( $var_name, $code ) { $start = strpos( $code, '$' . $var_name . ' = ' ); @@ -1016,6 +1032,9 @@ private static function get_core_checksums( $version, $locale, $insecure ) { $wp_org_api = new WpOrgApi( [ 'insecure' => $insecure ] ); try { + /** + * @var array|false $checksums + */ $checksums = $wp_org_api->get_core_checksums( $version, $locale ); } catch ( Exception $exception ) { return $exception->getMessage(); @@ -1083,6 +1102,9 @@ private static function get_core_checksums( $version, $locale, $insecure ) { * Success: WordPress updated successfully. * * @alias upgrade + * + * @param array{0?: string} $args Positional arguments. + * @param array{minor?: bool, version?: string, force?: bool, locale?: string, insecure?: bool} $assoc_args Associative arguments. */ public function update( $args, $assoc_args ) { global $wp_version; @@ -1118,6 +1140,10 @@ public function update( $args, $assoc_args ) { // Update to next release wp_version_check(); + + /** + * @var object{updates: array} $from_api + */ $from_api = get_site_transient( 'update_core' ); if ( Utils\get_flag_value( $assoc_args, 'minor' ) ) { @@ -1142,7 +1168,11 @@ public function update( $args, $assoc_args ) { // Specific version is given $version = $assoc_args['version']; - $locale = Utils\get_flag_value( $assoc_args, 'locale', get_locale() ); + + /** + * @var string $locale + */ + $locale = Utils\get_flag_value( $assoc_args, 'locale', get_locale() ); $new_package = $this->get_download_url( $version, $locale ); @@ -1178,7 +1208,12 @@ public function update( $args, $assoc_args ) { $insecure = (bool) Utils\get_flag_value( $assoc_args, 'insecure', false ); $GLOBALS['wpcli_core_update_obj'] = $update; - $result = Utils\get_upgrader( $upgrader, $insecure )->upgrade( $update ); + + /** + * @var \WP_CLI\Core\CoreUpgrader $wp_upgrader + */ + $wp_upgrader = Utils\get_upgrader( $upgrader, $insecure ); + $result = $wp_upgrader->upgrade( $update ); unset( $GLOBALS['wpcli_core_update_obj'] ); if ( is_wp_error( $result ) ) { @@ -1196,7 +1231,10 @@ public function update( $args, $assoc_args ) { $to_version = $wp_details['wp_version']; } - $locale = (string) Utils\get_flag_value( $assoc_args, 'locale', get_locale() ); + /** + * @var string $locale + */ + $locale = Utils\get_flag_value( $assoc_args, 'locale', get_locale() ); $this->cleanup_extra_files( $from_version, $to_version, $locale, $insecure ); WP_CLI::success( 'WordPress updated successfully.' ); @@ -1229,6 +1267,9 @@ public function update( $args, $assoc_args ) { * Success: WordPress database upgraded on 123/123 sites. * * @subcommand update-db + * + * @param string[] $args Positional arguments. Unused. + * @param array{network?: bool, 'dry-run'?: bool} $assoc_args Associative arguments. */ public function update_db( $args, $assoc_args ) { global $wpdb, $wp_db_version, $wp_current_db_version; @@ -1256,6 +1297,10 @@ public function update_db( $args, $assoc_args ) { $success = 0; $total = 0; $site_ids = []; + + /** + * @var object{site_id: int, domain: string, path: string} $blog + */ foreach ( $it as $blog ) { ++$total; $site_ids[] = $blog->site_id; @@ -1264,6 +1309,10 @@ public function update_db( $args, $assoc_args ) { if ( $dry_run ) { $cmd .= ' --dry-run'; } + + /** + * @var object{stdout: string, stderr: string, return_code: int} $process + */ $process = WP_CLI::runcommand( $cmd, [ @@ -1293,8 +1342,15 @@ public function update_db( $args, $assoc_args ) { WP_CLI::success( "WordPress database upgraded on {$success}/{$total} sites." ); } else { require_once ABSPATH . 'wp-admin/includes/upgrade.php'; + + /** + * @var string $wp_current_db_version + */ + // phpcs:ignore WordPress.WP.GlobalVariablesOverride.Prohibited -- Replacing WP Core behavior is the goal here. + $wp_current_db_version = __get_option( 'db_version' ); // phpcs:ignore WordPress.WP.GlobalVariablesOverride.Prohibited -- Replacing WP Core behavior is the goal here. - $wp_current_db_version = (int) __get_option( 'db_version' ); + $wp_current_db_version = (int) $wp_current_db_version; + if ( $wp_db_version !== $wp_current_db_version ) { if ( $dry_run ) { WP_CLI::success( "WordPress database will be upgraded from db version {$wp_current_db_version} to {$wp_db_version}." ); @@ -1354,6 +1410,10 @@ private function get_download_url( $version, $locale = 'en_US', $file_type = 'zi private function get_updates( $assoc_args ) { $force_check = Utils\get_flag_value( $assoc_args, 'force-check' ); wp_version_check( [], $force_check ); + + /** + * @var object{updates: array}|false $from_api + */ $from_api = get_site_transient( 'update_core' ); if ( ! $from_api ) { return []; @@ -1466,7 +1526,7 @@ private function cleanup_extra_files( $version_from, $version_to, $locale, $inse $old_basename = basename( $old_realpath ); $new_filepath = $new_filepaths[ $lowercase_old_filepath_to_check ]; $expected_basename = basename( $new_filepath ); - $new_realpath = realpath( ABSPATH . $new_filepath ); + $new_realpath = (string) realpath( ABSPATH . $new_filepath ); $new_basename = basename( $new_realpath ); // On Windows or Unix with only the incorrectly cased file. @@ -1483,8 +1543,10 @@ private function cleanup_extra_files( $version_from, $version_to, $locale, $inse if ( basename( $old_filepath_to_check ) === $old_basename ) { // Check if case-insensitive file system, eg on OSX. if ( fileinode( $old_realpath ) === fileinode( $new_realpath ) ) { + $files = scandir( dirname( $new_realpath ) ) ?: []; + // Check deeper because even realpath or glob might not return the actual case. - if ( ! in_array( $expected_basename, scandir( dirname( $new_realpath ) ), true ) ) { + if ( ! in_array( $expected_basename, $files, true ) ) { WP_CLI::debug( "Renaming file '{$old_filepath_to_check}' => '{$new_filepath}'", 'core' ); rename( ABSPATH . $old_filepath_to_check, ABSPATH . $old_filepath_to_check . '.tmp' ); @@ -1542,6 +1604,10 @@ function () use ( $new_zip_file ) { // phpcs:ignore WordPress.NamingConventions.ValidVariableName.UsedPropertyNotSnakeCase for ( $i = 0; $i < $zip->numFiles; $i++ ) { $info = $zip->statIndex( $i ); + if ( ! $info ) { + continue; + } + // Strip all files in wp-content/themes and wp-content/plugins // but leave the directories and index.php files intact. if ( in_array( diff --git a/src/WP_CLI/Core/CoreUpgrader.php b/src/WP_CLI/Core/CoreUpgrader.php index 44827752..c07c4368 100644 --- a/src/WP_CLI/Core/CoreUpgrader.php +++ b/src/WP_CLI/Core/CoreUpgrader.php @@ -51,10 +51,12 @@ public function download_package( $package, $check_signatures = false, $hook_ext * Filter whether to return the package. * * @since 3.7.0 + * @since 5.5.0 Added the `$hook_extra` parameter. * - * @param bool $reply Whether to bail without returning the package. Default is false. - * @param string $package The package file name. - * @param object $this The WP_Upgrader instance. + * @param bool $reply Whether to bail without returning the package. Default is false. + * @param string $package The package file name. + * @param \WP_Upgrader $upgrader The WP_Upgrader instance. + * @param array $hook_extra Extra arguments passed to hooked filters. */ $reply = apply_filters( // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound -- Override existing hook from Core. @@ -64,6 +66,11 @@ public function download_package( $package, $check_signatures = false, $hook_ext $this, $hook_extra ); + + /** + * @var false|string|\WP_Error $reply + */ + if ( false !== $reply ) { return $reply; } @@ -89,9 +96,13 @@ function () use ( $temp ) { } ); - $cache = WP_CLI::get_cache(); - $update = $GLOBALS['wpcli_core_update_obj']; - $cache_key = "core/{$filename}-{$update->locale}.{$extension}"; + $cache = WP_CLI::get_cache(); + $update = $GLOBALS['wpcli_core_update_obj']; + $cache_key = "core/{$filename}-{$update->locale}.{$extension}"; + + /** + * @var false|string $cache_file + */ $cache_file = $cache->has( $cache_key ); if ( $cache_file && false === stripos( $package, 'https://wordpress.org/nightly-builds/' ) @@ -115,8 +126,8 @@ function () use ( $temp ) { $this->skin->feedback( 'downloading_package', $package ); - /** @var \Requests_Response|\WpOrg\Requests\Response null $req */ try { + /** @var \WpOrg\Requests\Response $response */ $response = Utils\http_request( 'GET', $package, null, $headers, $options ); } catch ( Exception $e ) { return new WP_Error( 'download_failed', $e->getMessage() ); @@ -152,7 +163,7 @@ function () use ( $temp ) { * @type bool $do_rollback Whether to perform this "upgrade" as a rollback. * Default false. * } - * @return null|false|WP_Error False or WP_Error on failure, null on success. + * @return string|false|WP_Error New WordPress version on success, false or WP_Error on failure. */ public function upgrade( $current, $args = [] ) { set_error_handler( [ __CLASS__, 'error_handler' ], E_USER_WARNING | E_USER_NOTICE );