Merge pull request #258 from wp-cli/add/phpstan

This commit is contained in:
Pascal Birchler 2025-07-05 08:34:21 +02:00 committed by GitHub
commit f57a4b077c
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 43 additions and 33 deletions

View file

@ -28,7 +28,7 @@
"php": ">=7.2.24", "php": ">=7.2.24",
"wp-cli/package-command": "^2", "wp-cli/package-command": "^2",
"wp-cli/scaffold-command": "^2", "wp-cli/scaffold-command": "^2",
"wp-cli/wp-cli": "^2.12" "wp-cli/wp-cli": "^2.13"
}, },
"require-dev": { "require-dev": {
"wp-cli/wp-cli-tests": "^5" "wp-cli/wp-cli-tests": "^5"

View file

@ -40,7 +40,7 @@ Feature: Scaffold a README.md file for an existing package
And the {PACKAGE_PATH}/local/wp-cli/default-readme/README.md file should exist And the {PACKAGE_PATH}/local/wp-cli/default-readme/README.md file should exist
And the {PACKAGE_PATH}/local/wp-cli/default-readme/README.md file should contain: And the {PACKAGE_PATH}/local/wp-cli/default-readme/README.md file should contain:
""" """
Installing this package requires WP-CLI v2.11 or greater. Update to the latest stable release with `wp cli update`. Installing this package requires WP-CLI v2.12 or greater. Update to the latest stable release with `wp cli update`.
""" """
And the {PACKAGE_PATH}/local/wp-cli/default-readme/README.md file should contain: And the {PACKAGE_PATH}/local/wp-cli/default-readme/README.md file should contain:
""" """
@ -76,7 +76,7 @@ Feature: Scaffold a README.md file for an existing package
And the {PACKAGE_PATH}/local/wp-cli/custom-branch/README.md file should exist And the {PACKAGE_PATH}/local/wp-cli/custom-branch/README.md file should exist
And the {PACKAGE_PATH}/local/wp-cli/custom-branch/README.md file should contain: And the {PACKAGE_PATH}/local/wp-cli/custom-branch/README.md file should contain:
""" """
Installing this package requires WP-CLI v2.11 or greater. Update to the latest stable release with `wp cli update`. Installing this package requires WP-CLI v2.12 or greater. Update to the latest stable release with `wp cli update`.
""" """
And the {PACKAGE_PATH}/local/wp-cli/custom-branch/README.md file should contain: And the {PACKAGE_PATH}/local/wp-cli/custom-branch/README.md file should contain:
""" """
@ -152,10 +152,10 @@ Feature: Scaffold a README.md file for an existing package
"files": [ "command.php" ] "files": [ "command.php" ]
}, },
"require": { "require": {
"wp-cli/wp-cli": "^2.11" "wp-cli/wp-cli": "^2.12"
}, },
"require-dev": { "require-dev": {
"wp-cli/wp-cli-tests": "^4.3.9" "wp-cli/wp-cli-tests": "^5.0.0"
}, },
"extra": { "extra": {
"readme": { "readme": {
@ -333,7 +333,7 @@ Feature: Scaffold a README.md file for an existing package
}, },
"require-dev": { "require-dev": {
"wp-cli/wp-cli": "*", "wp-cli/wp-cli": "*",
"wp-cli/wp-cli-tests": "^4.3.9" "wp-cli/wp-cli-tests": "^5.0.0"
}, },
"extra": { "extra": {
"bundled": true "bundled": true

View file

@ -34,7 +34,7 @@ Feature: Scaffold WP-CLI commands
And the {PACKAGE_PATH}/local/wp-cli/foo/composer.json file should contain: And the {PACKAGE_PATH}/local/wp-cli/foo/composer.json file should contain:
""" """
"require": { "require": {
"wp-cli/wp-cli": "^2.11" "wp-cli/wp-cli": "^2.12"
}, },
""" """
And the {PACKAGE_PATH}/local/wp-cli/foo/hello-world-command.php file should exist And the {PACKAGE_PATH}/local/wp-cli/foo/hello-world-command.php file should exist

13
phpstan.neon.dist Normal file
View file

@ -0,0 +1,13 @@
parameters:
level: 9
paths:
- src
- scaffold-package-command.php
scanDirectories:
- vendor/wp-cli/wp-cli/php
scanFiles:
- vendor/php-stubs/wordpress-stubs/wordpress-stubs.php
treatPhpDocTypesAsCertain: false
ignoreErrors:
- identifier: missingType.parameter
- identifier: missingType.return

View file

@ -5,6 +5,9 @@ namespace WP_CLI;
use WP_CLI; use WP_CLI;
use WP_CLI\Utils; use WP_CLI\Utils;


/**
* @phpstan-type ComposerConfig array{name: string, description: string, extra: array{readme: array{shields: array<string>}, commands: array<string>}, require: array<string, string>, 'require-dev': array<string, string>}
*/
class ScaffoldPackageCommand { class ScaffoldPackageCommand {


/** /**
@ -43,13 +46,13 @@ class ScaffoldPackageCommand {
* [--require_wp_cli=<version>] * [--require_wp_cli=<version>]
* : Required WP-CLI version for the package. * : Required WP-CLI version for the package.
* --- * ---
* default: ^2.11 * default: ^2.12
* --- * ---
* *
* [--require_wp_cli_tests=<version>] * [--require_wp_cli_tests=<version>]
* : Required WP-CLI testing framework version for the package. * : Required WP-CLI testing framework version for the package.
* --- * ---
* default: ^4.3.9 * default: ^5.0.0
* --- * ---


* [--skip-tests] * [--skip-tests]
@ -242,7 +245,10 @@ EOT;


self::check_if_valid_package_dir( $package_dir ); self::check_if_valid_package_dir( $package_dir );


$composer_obj = json_decode( file_get_contents( $package_dir . '/composer.json' ), true ); /**
* @var null|ComposerConfig $composer_obj
*/
$composer_obj = json_decode( (string) file_get_contents( $package_dir . '/composer.json' ), true );
if ( ! $composer_obj ) { if ( ! $composer_obj ) {
WP_CLI::error( 'Invalid composer.json in package directory.' ); WP_CLI::error( 'Invalid composer.json in package directory.' );
} }
@ -334,8 +340,8 @@ EOT;
*/ */


$longdesc = isset( $parent_command['longdesc'] ) ? $parent_command['longdesc'] : ''; $longdesc = isset( $parent_command['longdesc'] ) ? $parent_command['longdesc'] : '';
$longdesc = preg_replace( '/## GLOBAL PARAMETERS(.+)/s', '', $longdesc ); $longdesc = (string) preg_replace( '/## GLOBAL PARAMETERS(.+)/s', '', $longdesc );
$longdesc = preg_replace( '/##\s(.+)/', '**$1**', $longdesc ); $longdesc = (string) preg_replace( '/##\s(.+)/', '**$1**', $longdesc );


// definition lists // definition lists
$longdesc = preg_replace_callback( '/([^\n]+)\n: (.+?)(\n\n|$)/s', [ __CLASS__, 'rewrap_param_desc' ], $longdesc ); $longdesc = preg_replace_callback( '/([^\n]+)\n: (.+?)(\n\n|$)/s', [ __CLASS__, 'rewrap_param_desc' ], $longdesc );
@ -405,7 +411,9 @@ EOT;
$v = $composer_obj['extra']['readme'][ $section ][ $k ]; $v = $composer_obj['extra']['readme'][ $section ][ $k ];
if ( filter_var( $v, FILTER_VALIDATE_URL ) === $v ) { if ( filter_var( $v, FILTER_VALIDATE_URL ) === $v ) {
$response = Utils\http_request( 'GET', $v ); $response = Utils\http_request( 'GET', $v );
$v = $response->body;
// @phpstan-ignore class.notFound
$v = $response->body;
} elseif ( preg_match( $ext_regex, $v ) ) { } elseif ( preg_match( $ext_regex, $v ) ) {
$v = $package_dir . '/' . $v; $v = $package_dir . '/' . $v;
} }
@ -479,7 +487,10 @@ EOT;
$force = Utils\get_flag_value( $assoc_args, 'force' ); $force = Utils\get_flag_value( $assoc_args, 'force' );
$template_path = dirname( __DIR__ ) . '/templates'; $template_path = dirname( __DIR__ ) . '/templates';


$composer_obj = json_decode( file_get_contents( $package_dir . '/composer.json' ), true ); /**
* @var ComposerConfig $composer_obj
*/
$composer_obj = json_decode( (string) file_get_contents( $package_dir . '/composer.json' ), true );
$settings_vars = [ $settings_vars = [
'has_description' => false, 'has_description' => false,
'description' => '', 'description' => '',
@ -709,27 +720,10 @@ EOT;
$files_written = []; $files_written = [];
foreach ( $copy_source as $source => $to_copy ) { foreach ( $copy_source as $source => $to_copy ) {
foreach ( $to_copy as $file => $dir ) { foreach ( $to_copy as $file => $dir ) {
if ( 'php/WP_CLI/ProcessRun.php' === $file && ! file_exists( $source . "/{$file}" ) ) {
continue;
}
// file_get_contents() works with Phar-archived files // file_get_contents() works with Phar-archived files
$contents = file_get_contents( $source . "/{$file}" ); $contents = (string) file_get_contents( $source . "/{$file}" );
$file_path = $dir . basename( $file ); $file_path = $dir . basename( $file );


if ( '.travis.yml' === $file ) {
foreach ( $travis_tags as $travis_tag ) {
if ( isset( $travis_tag_overwrites[ $travis_tag ] ) ) {
// Note the contents fully overwrite, so should include the tag, eg `env:` etc (or nothing if want to remove totally).
$contents = preg_replace( '/^' . $travis_tag . ':.*?(?:^$|\z)/ms', $travis_tag_overwrites[ $travis_tag ], $contents );
} elseif ( isset( $travis_tag_appends[ $travis_tag ] ) ) {
$contents = preg_replace( '/^' . $travis_tag . ':.*?(?:^$|\z)/ms', '\0' . $travis_tag_appends[ $travis_tag ], $contents );
}
}
if ( $travis_append ) {
$contents .= $travis_append;
}
}

$force = Utils\get_flag_value( $assoc_args, 'force' ); $force = Utils\get_flag_value( $assoc_args, 'force' );
$should_write_file = $this->prompt_if_files_will_be_overwritten( $file_path, $force ); $should_write_file = $this->prompt_if_files_will_be_overwritten( $file_path, $force );
if ( ! $should_write_file ) { if ( ! $should_write_file ) {

View file

@ -15,7 +15,8 @@
"process-timeout": 7200, "process-timeout": 7200,
"sort-packages": true, "sort-packages": true,
"allow-plugins": { "allow-plugins": {
"dealerdirect/phpcodesniffer-composer-installer": true "dealerdirect/phpcodesniffer-composer-installer": true,
"phpstan/extension-installer": true
} }
}, },
"extra": { "extra": {
@ -42,12 +43,14 @@
"behat-rerun": "rerun-behat-tests", "behat-rerun": "rerun-behat-tests",
"lint": "run-linter-tests", "lint": "run-linter-tests",
"phpcs": "run-phpcs-tests", "phpcs": "run-phpcs-tests",
"phpstan": "run-phpstan-tests",
"phpcbf": "run-phpcbf-cleanup", "phpcbf": "run-phpcbf-cleanup",
"phpunit": "run-php-unit-tests", "phpunit": "run-php-unit-tests",
"prepare-tests": "install-package-tests", "prepare-tests": "install-package-tests",
"test": [ "test": [
"@lint", "@lint",
"@phpcs", "@phpcs",
"@phpstan",
"@phpunit", "@phpunit",
"@behat" "@behat"
] ]