diff --git a/bin/run-phpstan-tests b/bin/run-phpstan-tests
new file mode 100755
index 000000000..21f276900
--- /dev/null
+++ b/bin/run-phpstan-tests
@@ -0,0 +1,7 @@
+#!/bin/sh
+
+# Run the code style check only if a configuration file exists.
+if [ -f "phpstan.dist.neon" ] || [ -f "phpstan.neon.dist" ] || [ -f "phpstan.neon" ]
+then
+ vendor/bin/phpstan --memory-limit=2048M analyse "$@"
+fi
diff --git a/composer.json b/composer.json
index 4826e0136..8e678002b 100644
--- a/composer.json
+++ b/composer.json
@@ -15,6 +15,9 @@
"php-parallel-lint/php-console-highlighter": "^1.0",
"php-parallel-lint/php-parallel-lint": "^1.3.1",
"phpcompatibility/php-compatibility": "dev-develop",
+ "phpstan/extension-installer": "^1.4.3",
+ "phpstan/phpstan": "^1.12.26",
+ "szepeviktor/phpstan-wordpress": "^v1.3.5",
"wp-cli/config-command": "^1 || ^2",
"wp-cli/core-command": "^1 || ^2",
"wp-cli/eval-command": "^1 || ^2",
@@ -28,7 +31,8 @@
"config": {
"allow-plugins": {
"dealerdirect/phpcodesniffer-composer-installer": true,
- "johnpbloch/wordpress-core-installer": true
+ "johnpbloch/wordpress-core-installer": true,
+ "phpstan/extension-installer": true
},
"sort-packages": true,
"lock": false
@@ -63,7 +67,8 @@
"bin/run-linter-tests",
"bin/run-php-unit-tests",
"bin/run-phpcs-tests",
- "bin/run-phpcbf-cleanup"
+ "bin/run-phpcbf-cleanup",
+ "bin/run-phpstan-tests"
],
"scripts": {
"behat": "run-behat-tests",
@@ -71,11 +76,13 @@
"lint": "run-linter-tests",
"phpcs": "run-phpcs-tests",
"phpcbf": "run-phpcbf-cleanup",
+ "phpstan": "run-phpstan-tests",
"phpunit": "run-php-unit-tests",
"prepare-tests": "install-package-tests",
"test": [
"@lint",
"@phpcs",
+ "@phpstan",
"@phpunit",
"@behat"
]
diff --git a/phpcs.xml.dist b/phpcs.xml.dist
index 966056354..24888b4b8 100644
--- a/phpcs.xml.dist
+++ b/phpcs.xml.dist
@@ -59,6 +59,8 @@
#############################################################################
-->
+ tests/phpstan/scan-files.php
+
diff --git a/phpstan.neon.dist b/phpstan.neon.dist
new file mode 100644
index 000000000..01b2d732d
--- /dev/null
+++ b/phpstan.neon.dist
@@ -0,0 +1,19 @@
+parameters:
+ level: 6
+ paths:
+ - src
+ - tests
+ scanDirectories:
+ - vendor/wp-cli/wp-cli
+ - vendor/phpunit/php-code-coverage
+ - vendor/behat/behat
+ scanFiles:
+ - tests/phpstan/scan-files.php
+ treatPhpDocTypesAsCertain: false
+ dynamicConstantNames:
+ - WP_DEBUG
+ - WP_DEBUG_LOG
+ - WP_DEBUG_DISPLAY
+ ignoreErrors:
+ # Needs fixing in WP-CLI.
+ - message: '#Parameter \#1 \$cmd of function WP_CLI\\Utils\\esc_cmd expects array#'
diff --git a/src/Context/FeatureContext.php b/src/Context/FeatureContext.php
index df28bb3dd..150f0d30b 100644
--- a/src/Context/FeatureContext.php
+++ b/src/Context/FeatureContext.php
@@ -3,13 +3,17 @@
namespace WP_CLI\Tests\Context;
use Behat\Behat\Context\SnippetAcceptingContext;
+use Behat\Behat\EventDispatcher\Event\OutlineTested;
use Behat\Behat\Hook\Scope\AfterScenarioScope;
use Behat\Behat\Hook\Scope\BeforeScenarioScope;
+use Behat\Behat\Hook\Scope\FeatureScope;
+use Behat\Behat\Hook\Scope\ScenarioScope;
use Behat\Testwork\Hook\Scope\AfterSuiteScope;
use Behat\Testwork\Hook\Scope\BeforeSuiteScope;
use Behat\Behat\Hook\Scope\AfterFeatureScope;
use Behat\Behat\Hook\Scope\BeforeFeatureScope;
use Behat\Behat\Hook\Scope\BeforeStepScope;
+use Behat\Testwork\Hook\Scope\HookScope;
use SebastianBergmann\CodeCoverage\Report\Clover;
use SebastianBergmann\CodeCoverage\Driver\Selector;
use SebastianBergmann\CodeCoverage\Driver\Xdebug;
@@ -19,6 +23,7 @@
use RuntimeException;
use DirectoryIterator;
use WP_CLI\Process;
+use WP_CLI\ProcessRun;
use WP_CLI\Utils;
use WP_CLI\WpOrgApi;
@@ -33,53 +38,73 @@ class FeatureContext implements SnippetAcceptingContext {
/**
* The result of the last command run with `When I run` or `When I try`. Lives until the end of the scenario.
+ *
+ * @var ?ProcessRun
*/
protected $result;
/**
* The number of emails sent by the last command run with `When I run` or `When I try`. Lives until the end of the scenario.
+ *
+ * @var int
*/
protected $email_sends;
/**
* The current working directory for scenarios that have a "Given a WP installation" or "Given an empty directory" step. Variable RUN_DIR. Lives until the end of the scenario.
+ *
+ * @var ?string
*/
private static $run_dir;
/**
* The Directory that 'composer behat' is run from, assumed to always be the top level project folder
+ *
+ * @var string
*/
private static $behat_run_dir;
/**
* Where WordPress core is downloaded to for caching, and which is copied to RUN_DIR during a "Given a WP installation" step. Lives until manually deleted.
+ *
+ * @var string
*/
private static $cache_dir;
/**
* The directory that holds the install cache, and which is copied to RUN_DIR during a "Given a WP installation" step. Recreated on each suite run.
+ *
+ * @var string
*/
private static $install_cache_dir;
/**
* The directory that holds a copy of the sqlite-database-integration plugin, and which is copied to RUN_DIR during a "Given a WP installation" step. Lives until manually deleted.
+ *
+ * @var ?string
*/
private static $sqlite_cache_dir;
/**
* The directory that the WP-CLI cache (WP_CLI_CACHE_DIR, normally "$HOME/.wp-cli/cache") is set to on a "Given an empty cache" step.
* Variable SUITE_CACHE_DIR. Lives until the end of the scenario (or until another "Given an empty cache" step within the scenario).
+ *
+ * @var ?string
*/
private static $suite_cache_dir;
/**
* Where the current WP-CLI source repository is copied to for Composer-based tests with a "Given a dependency on current wp-cli" step.
* Variable COMPOSER_LOCAL_REPOSITORY. Lives until the end of the suite.
+ *
+ * @var ?string
*/
private static $composer_local_repository;
/**
* The test database settings. All but `dbname` can be set via environment variables. The database is dropped at the start of each scenario and created on a "Given a WP installation" step.
+ *
+ * @var array
*/
private static $db_settings = [
'dbname' => 'wp_cli_test',
@@ -90,16 +115,22 @@ class FeatureContext implements SnippetAcceptingContext {
/**
* What type of database should WordPress use for the test installations. Default to MySQL
+ *
+ * @var string
*/
private static $db_type = 'mysql';
/**
* Name of mysql binary to use (mysql or mariadb). Default to mysql
+ *
+ * @var string
*/
private static $mysql_binary = 'mysql';
/**
* Array of background process ids started by the current scenario. Used to terminate them at the end of the scenario.
+ *
+ * @var array
*/
private $running_procs = [];
@@ -107,27 +138,77 @@ class FeatureContext implements SnippetAcceptingContext {
* Array of variables available as {VARIABLE_NAME}. Some are always set: CORE_CONFIG_SETTINGS, DB_USER, DB_PASSWORD, DB_HOST, SRC_DIR, CACHE_DIR, WP_VERSION-version-latest.
* Some are step-dependent: RUN_DIR, SUITE_CACHE_DIR, COMPOSER_LOCAL_REPOSITORY, PHAR_PATH. One is set on use: INVOKE_WP_CLI_WITH_PHP_ARGS-args.
* Scenarios can define their own variables using "Given save" steps. Variables are reset for each scenario.
+ *
+ * @var array
*/
public $variables = [];
/**
* The current feature file and scenario line number as '.'. Used in RUN_DIR and SUITE_CACHE_DIR directory names. Set at the start of each scenario.
+ *
+ * @var ?string
*/
private static $temp_dir_infix;
/**
- * Settings and variables for WP_CLI_TEST_LOG_RUN_TIMES run time logging.
+ * Whether to log run times - WP_CLI_TEST_LOG_RUN_TIMES env var. Set on `@BeforeScenario'.
+ *
+ * @var false|string
*/
- private static $log_run_times; // Whether to log run times - WP_CLI_TEST_LOG_RUN_TIMES env var. Set on `@BeforeScenario'.
- private static $suite_start_time; // When the suite started, set on `@BeforeScenario'.
- private static $output_to; // Where to output log - stdout|error_log. Set on `@BeforeSuite`.
- private static $num_top_processes; // Number of processes/methods to output by longest run times. Set on `@BeforeSuite`.
- private static $num_top_scenarios; // Number of scenarios to output by longest run times. Set on `@BeforeSuite`.
+ private static $log_run_times;
- private static $scenario_run_times = []; // Scenario run times (top `self::$num_top_scenarios` only).
- private static $scenario_count = 0; // Scenario count, incremented on `@AfterScenario`.
- private static $proc_method_run_times = []; // Array of run time info for proc methods, keyed by method name and arg, each a 2-element array containing run time and run count.
+ /**
+ * When the suite started, set on `@BeforeScenario'.
+ *
+ * @var float
+ */
+ private static $suite_start_time;
+ /**
+ * Where to output log - stdout|error_log. Set on `@BeforeSuite`.
+ *
+ * @var string
+ */
+ private static $output_to;
+
+ /**
+ * Number of processes/methods to output by longest run times. Set on `@BeforeSuite`.
+ *
+ * @var int
+ */
+ private static $num_top_processes;
+
+ /**
+ * Number of scenarios to output by longest run times. Set on `@BeforeSuite`.
+ *
+ * @var int
+ */
+ private static $num_top_scenarios;
+
+ /**
+ * Scenario run times (top `self::$num_top_scenarios` only).
+ *
+ * @var array
+ */
+ private static $scenario_run_times = [];
+
+ /**
+ * Scenario count, incremented on `@AfterScenario`.
+ *
+ * @var int
+ */
+ private static $scenario_count = 0;
+
+ /**
+ * Array of run time info for proc methods, keyed by method name and arg, each a 2-element array containing run time and run count.
+ *
+ * @var array
+ */
+ private static $proc_method_run_times = [];
+
+ /**
+ * @var array
+ */
private $mocked_requests = [];
/**
@@ -154,28 +235,28 @@ class FeatureContext implements SnippetAcceptingContext {
/**
* @BeforeFeature
*/
- public static function store_feature( BeforeFeatureScope $scope ) {
+ public static function store_feature( BeforeFeatureScope $scope ): void {
self::$feature = $scope->getFeature();
}
/**
* @BeforeScenario
*/
- public function store_scenario( BeforeScenarioScope $scope ) {
+ public function store_scenario( BeforeScenarioScope $scope ): void {
$this->scenario = $scope->getScenario();
}
/**
* @BeforeStep
*/
- public function store_step( BeforeStepScope $scope ) {
+ public function store_step( BeforeStepScope $scope ): void {
$this->step_line = $scope->getStep()->getLine();
}
/**
* @AfterScenario
*/
- public function forget_scenario( AfterScenarioScope $scope ) {
+ public function forget_scenario( AfterScenarioScope $scope ): void {
$this->step_line = 0;
$this->scenario = null;
}
@@ -183,14 +264,14 @@ public function forget_scenario( AfterScenarioScope $scope ) {
/**
* @AfterFeature
*/
- public static function forget_feature( AfterFeatureScope $scope ) {
+ public static function forget_feature( AfterFeatureScope $scope ): void {
self::$feature = null;
}
/**
* @AfterSuite
*/
- public static function merge_coverage_reports() {
+ public static function merge_coverage_reports(): void {
$with_code_coverage = (string) getenv( 'WP_CLI_TEST_COVERAGE' );
if ( ! \in_array( $with_code_coverage, [ 'true', '1' ], true ) ) {
@@ -221,7 +302,7 @@ class_exists( Selector::class ) ? ( new Selector() )->forLineCoverage( $filter )
*
* @return string Absolute path to the Composer vendor folder.
*/
- public static function get_vendor_dir() {
+ public static function get_vendor_dir(): ?string {
static $vendor_folder = null;
if ( null !== $vendor_folder ) {
@@ -233,9 +314,9 @@ public static function get_vendor_dir() {
// wp-cli/wp-cli-tests is a dependency of the current working dir.
getcwd() . '/vendor',
// wp-cli/wp-cli-tests is the root project.
- dirname( dirname( __DIR__ ) ) . '/vendor',
+ dirname( __DIR__, 2 ) . '/vendor',
// wp-cli/wp-cli-tests is a dependency.
- dirname( dirname( dirname( dirname( __DIR__ ) ) ) ),
+ dirname( __DIR__, 4 ),
];
$vendor_folder = '';
@@ -258,7 +339,7 @@ public static function get_vendor_dir() {
*
* @return string Absolute path to the WP-CLI framework folder.
*/
- public static function get_framework_dir() {
+ public static function get_framework_dir(): ?string {
static $framework_folder = null;
if ( null !== $framework_folder ) {
@@ -290,13 +371,12 @@ public static function get_framework_dir() {
return $framework_folder;
}
-
/**
* Get the path to the WP-CLI binary.
*
* @return string Absolute path to the WP-CLI binary.
*/
- public static function get_bin_path() {
+ public static function get_bin_path(): ?string {
static $bin_path = null;
if ( null !== $bin_path ) {
@@ -325,9 +405,11 @@ public static function get_bin_path() {
}
/**
- * Get the environment variables required for launched `wp` processes
+ * Get the environment variables required for launched `wp` processes.
+ *
+ * @return array
*/
- private static function get_process_env_variables() {
+ private static function get_process_env_variables(): array {
static $env = null;
if ( null !== $env ) {
@@ -426,10 +508,10 @@ private static function get_process_env_variables() {
/**
* Get the internal variables to use within tests.
*
- * @return array Associative array of internal variables that will be mapped
- * into tests.
+ * @return array Associative array of internal variables that will be mapped
+ * into tests.
*/
- private static function get_behat_internal_variables() {
+ private static function get_behat_internal_variables(): array {
static $variables = null;
if ( null !== $variables ) {
@@ -437,12 +519,12 @@ private static function get_behat_internal_variables() {
}
$paths = [
- dirname( dirname( dirname( dirname( __DIR__ ) ) ) ) . '/wp-cli/wp-cli/VERSION',
- dirname( dirname( dirname( dirname( dirname( __DIR__ ) ) ) ) ) . '/VERSION',
- dirname( dirname( __DIR__ ) ) . '/vendor/wp-cli/wp-cli/VERSION',
+ dirname( __DIR__, 4 ) . '/wp-cli/wp-cli/VERSION',
+ dirname( __DIR__, 5 ) . '/VERSION',
+ dirname( __DIR__, 2 ) . '/vendor/wp-cli/wp-cli/VERSION',
];
- $framework_root = dirname( dirname( __DIR__ ) );
+ $framework_root = dirname( __DIR__, 2 );
foreach ( $paths as $path ) {
if ( file_exists( $path ) ) {
$framework_root = (string) realpath( dirname( $path ) );
@@ -452,8 +534,8 @@ private static function get_behat_internal_variables() {
$variables = [
'FRAMEWORK_ROOT' => realpath( $framework_root ),
- 'SRC_DIR' => realpath( dirname( dirname( __DIR__ ) ) ),
- 'PROJECT_DIR' => realpath( dirname( dirname( dirname( dirname( dirname( __DIR__ ) ) ) ) ) ),
+ 'SRC_DIR' => realpath( dirname( __DIR__, 2 ) ),
+ 'PROJECT_DIR' => realpath( dirname( __DIR__, 5 ) ),
];
return $variables;
@@ -462,8 +544,10 @@ private static function get_behat_internal_variables() {
/**
* Download and extract a single copy of the sqlite-database-integration plugin
* for use in subsequent WordPress copies
+ *
+ * @param string $dir
*/
- private static function download_sqlite_plugin( $dir ) {
+ private static function download_sqlite_plugin( $dir ): void {
$download_url = 'https://downloads.wordpress.org/plugin/sqlite-database-integration.zip';
$download_location = $dir . '/sqlite-database-integration.zip';
@@ -499,8 +583,10 @@ private static function download_sqlite_plugin( $dir ) {
/**
* Given a WordPress installation with the sqlite-database-integration plugin,
* configure it to use SQLite as the database by placing the db.php dropin file
+ *
+ * @param string $dir
*/
- private static function configure_sqlite( $dir ) {
+ private static function configure_sqlite( $dir ): void {
$db_copy = $dir . '/wp-content/mu-plugins/sqlite-database-integration/db.copy';
$db_dropin = $dir . '/wp-content/db.php';
@@ -526,7 +612,7 @@ private static function configure_sqlite( $dir ) {
* We cache the results of `wp core download` to improve test performance.
* Ideally, we'd cache at the HTTP layer for more reliable tests.
*/
- private static function cache_wp_files() {
+ private static function cache_wp_files(): void {
$wp_version = getenv( 'WP_VERSION' );
$wp_version_suffix = ( false !== $wp_version ) ? "-$wp_version" : '';
self::$cache_dir = sys_get_temp_dir() . '/wp-cli-test-core-download-cache' . $wp_version_suffix;
@@ -552,7 +638,7 @@ private static function cache_wp_files() {
/**
* @BeforeSuite
*/
- public static function prepare( BeforeSuiteScope $scope ) {
+ public static function prepare( BeforeSuiteScope $scope ): void {
// Test performance statistics - useful for detecting slow tests.
self::$log_run_times = getenv( 'WP_CLI_TEST_LOG_RUN_TIMES' );
if ( false !== self::$log_run_times ) {
@@ -588,7 +674,7 @@ public static function prepare( BeforeSuiteScope $scope ) {
/**
* @AfterSuite
*/
- public static function afterSuite( AfterSuiteScope $scope ) {
+ public static function afterSuite( AfterSuiteScope $scope ): void {
if ( self::$composer_local_repository ) {
self::remove_dir( self::$composer_local_repository );
self::$composer_local_repository = null;
@@ -602,7 +688,7 @@ public static function afterSuite( AfterSuiteScope $scope ) {
/**
* @BeforeScenario
*/
- public function beforeScenario( BeforeScenarioScope $scope ) {
+ public function beforeScenario( BeforeScenarioScope $scope ): void {
if ( self::$log_run_times ) {
self::log_run_times_before_scenario( $scope );
}
@@ -628,7 +714,7 @@ public function beforeScenario( BeforeScenarioScope $scope ) {
/**
* @AfterScenario
*/
- public function afterScenario( AfterScenarioScope $scope ) {
+ public function afterScenario( AfterScenarioScope $scope ): void {
if ( self::$run_dir ) {
// Remove altered WP install, unless there's an error.
@@ -668,8 +754,10 @@ public function afterScenario( AfterScenarioScope $scope ) {
/**
* Terminate a process and any of its children.
+ *
+ * @param int $master_pid
*/
- private static function terminate_proc( $master_pid ) {
+ private static function terminate_proc( $master_pid ): void {
$output = `ps -o ppid,pid,command | grep $master_pid`;
@@ -679,7 +767,7 @@ private static function terminate_proc( $master_pid ) {
$child = $matches[2];
if ( (int) $parent === (int) $master_pid ) {
- self::terminate_proc( $child );
+ self::terminate_proc( (int) $child );
}
}
}
@@ -696,7 +784,7 @@ private static function terminate_proc( $master_pid ) {
/**
* Create a temporary WP_CLI_CACHE_DIR. Exposed as SUITE_CACHE_DIR in "Given an empty cache" step.
*/
- public static function create_cache_dir() {
+ public static function create_cache_dir(): string {
if ( self::$suite_cache_dir ) {
self::remove_dir( self::$suite_cache_dir );
}
@@ -776,6 +864,9 @@ public function __construct() {
/**
* Replace standard {VARIABLE_NAME} variables and the special {INVOKE_WP_CLI_WITH_PHP_ARGS-args} and {WP_VERSION-version-latest} variables.
* Note that standard variable names can only contain uppercase letters, digits and underscores and cannot begin with a digit.
+ *
+ * @param string $str
+ * @return string
*/
public function replace_variables( $str ) {
if ( false !== strpos( $str, '{INVOKE_WP_CLI_WITH_PHP_ARGS-' ) ) {
@@ -790,6 +881,9 @@ public function replace_variables( $str ) {
/**
* Substitute {INVOKE_WP_CLI_WITH_PHP_ARGS-args} variables.
+ *
+ * @param string $str
+ * @return string
*/
private function replace_invoke_wp_cli_with_php_args( $str ) {
static $phar_path = null, $shell_path = null;
@@ -802,7 +896,7 @@ private function replace_invoke_wp_cli_with_php_args( $str ) {
if ( false !== $bin_dir && file_exists( $bin_dir . '/wp' ) && file_get_contents( $bin_dir . '/wp', false, null, 0, $phar_begin_len ) === $phar_begin ) {
$phar_path = $bin_dir . '/wp';
} else {
- $src_dir = dirname( dirname( __DIR__ ) );
+ $src_dir = dirname( __DIR__, 2 );
$bin_path = $src_dir . '/bin/wp';
$vendor_bin_path = $src_dir . '/vendor/bin/wp';
if ( file_exists( $bin_path ) && is_executable( $bin_path ) ) {
@@ -817,7 +911,7 @@ private function replace_invoke_wp_cli_with_php_args( $str ) {
$str = preg_replace_callback(
'/{INVOKE_WP_CLI_WITH_PHP_ARGS-([^}]*)}/',
- function ( $matches ) use ( $phar_path, $shell_path ) {
+ static function ( $matches ) use ( $phar_path, $shell_path ) {
return $phar_path ? "php {$matches[1]} {$phar_path}" : ( 'WP_CLI_PHP_ARGS=' . escapeshellarg( $matches[1] ) . ' ' . $shell_path );
},
$str
@@ -828,6 +922,9 @@ function ( $matches ) use ( $phar_path, $shell_path ) {
/**
* Replace variables callback.
+ *
+ * @param array $matches
+ * @return string
*/
private function replace_var( $matches ) {
$str = $matches[0];
@@ -845,8 +942,11 @@ private function replace_var( $matches ) {
/**
* Substitute {WP_VERSION-version-latest} variables.
+ *
+ * @param string $str
+ * @return string
*/
- private function replace_wp_versions( $str ) {
+ private function replace_wp_versions( $str ): string {
static $wp_versions = null;
if ( null === $wp_versions ) {
$wp_versions = [];
@@ -878,8 +978,13 @@ private function replace_wp_versions( $str ) {
/**
* Get the file and line number for the current behat scope.
+ *
+ * @param ScenarioScope|FeatureScope|OutlineTested $scope
+ * @param int $line
+ *
+ * @param-out int $line
*/
- private static function get_event_file( $scope, &$line ) {
+ private static function get_event_file( $scope, &$line ): ?string {
if ( method_exists( $scope, 'getScenario' ) ) {
$scenario_feature = $scope->getScenario();
} elseif ( method_exists( $scope, 'getFeature' ) ) {
@@ -902,7 +1007,7 @@ private static function get_event_file( $scope, &$line ) {
/**
* Create the RUN_DIR directory, unless already set for this scenario.
*/
- public function create_run_dir() {
+ public function create_run_dir(): void {
if ( ! isset( $this->variables['RUN_DIR'] ) ) {
self::$run_dir = sys_get_temp_dir() . '/' . uniqid( 'wp-cli-test-run-' . self::$temp_dir_infix . '-', true );
$this->variables['RUN_DIR'] = self::$run_dir;
@@ -910,7 +1015,10 @@ public function create_run_dir() {
}
}
- public function build_phar( $version = 'same' ) {
+ /**
+ * @param string $version
+ */
+ public function build_phar( $version = 'same' ): void {
$this->variables['PHAR_PATH'] = $this->variables['RUN_DIR'] . '/' . uniqid( 'wp-cli-build-', true ) . '.phar';
// Test running against a package installed as a WP-CLI dependency
@@ -931,7 +1039,10 @@ public function build_phar( $version = 'same' ) {
)->run_check();
}
- public function download_phar( $version = 'same' ) {
+ /**
+ * @param string $version
+ */
+ public function download_phar( $version = 'same' ): void {
if ( 'same' === $version ) {
$version = WP_CLI_VERSION;
}
@@ -957,7 +1068,7 @@ public function download_phar( $version = 'same' ) {
/**
* CACHE_DIR is a cache for downloaded test data such as images. Lives until manually deleted.
*/
- private function set_cache_dir() {
+ private function set_cache_dir(): void {
$path = sys_get_temp_dir() . '/wp-cli-test-cache';
if ( ! file_exists( $path ) ) {
mkdir( $path );
@@ -968,11 +1079,11 @@ private function set_cache_dir() {
/**
* Run a MySQL command with `$db_settings`.
*
- * @param string $sql_cmd Command to run.
- * @param array $assoc_args Optional. Associative array of options. Default empty.
- * @param bool $add_database Optional. Whether to add dbname to the $sql_cmd. Default false.
+ * @param string $sql_cmd Command to run.
+ * @param array $assoc_args Optional. Associative array of options. Default empty.
+ * @param bool $add_database Optional. Whether to add dbname to the $sql_cmd. Default false.
*/
- private static function run_sql( $sql_cmd, $assoc_args = [], $add_database = false ) {
+ private static function run_sql( $sql_cmd, $assoc_args = [], $add_database = false ): void {
$default_assoc_args = [
'host' => self::$db_settings['dbhost'],
'user' => self::$db_settings['dbuser'],
@@ -988,7 +1099,7 @@ private static function run_sql( $sql_cmd, $assoc_args = [], $add_database = fal
}
}
- public function create_db() {
+ public function create_db(): void {
if ( 'sqlite' === self::$db_type ) {
return;
}
@@ -997,7 +1108,7 @@ public function create_db() {
self::run_sql( self::$mysql_binary . ' --no-defaults', [ 'execute' => "CREATE DATABASE IF NOT EXISTS $dbname" ] );
}
- public function drop_db() {
+ public function drop_db(): void {
if ( 'sqlite' === self::$db_type ) {
return;
}
@@ -1005,7 +1116,13 @@ public function drop_db() {
self::run_sql( self::$mysql_binary . ' --no-defaults', [ 'execute' => "DROP DATABASE IF EXISTS $dbname" ] );
}
- public function proc( $command, $assoc_args = [], $path = '' ) {
+ /**
+ * @param string $command
+ * @param array $assoc_args
+ * @param string $path
+ * @return Process
+ */
+ public function proc( $command, $assoc_args = [], $path = '' ): Process {
if ( ! empty( $assoc_args ) ) {
$command .= Utils\assoc_args_to_str( $assoc_args );
}
@@ -1043,8 +1160,10 @@ public function proc( $command, $assoc_args = [], $path = '' ) {
/**
* Start a background process. Will automatically be closed when the tests finish.
+ *
+ * @param string $cmd
*/
- public function background_proc( $cmd ) {
+ public function background_proc( $cmd ): void {
$descriptors = [
0 => STDIN,
1 => [ 'pipe', 'w' ],
@@ -1060,39 +1179,55 @@ public function background_proc( $cmd ) {
if ( ! $status['running'] ) {
$stderr = is_resource( $pipes[2] ) ? ( ': ' . stream_get_contents( $pipes[2] ) ) : '';
throw new RuntimeException( sprintf( "Failed to start background process '%s'%s.", $cmd, $stderr ) );
- } else {
- $this->running_procs[] = $proc;
}
+
+ $this->running_procs[] = $proc;
}
- public function move_files( $src, $dest ) {
+ /**
+ * @param string $src
+ * @param string $dest
+ */
+ public function move_files( $src, $dest ): void {
rename( $this->variables['RUN_DIR'] . "/$src", $this->variables['RUN_DIR'] . "/$dest" );
}
/**
* Remove a directory (recursive).
+ *
+ * @param string $dir
*/
- public static function remove_dir( $dir ) {
+ public static function remove_dir( $dir ): void {
Process::create( Utils\esc_cmd( 'rm -rf %s', $dir ) )->run_check();
}
/**
* Copy a directory (recursive). Destination directory must exist.
+ *
+ * @param string $src_dir
+ * @param string $dest_dir
*/
- public static function copy_dir( $src_dir, $dest_dir ) {
+ public static function copy_dir( $src_dir, $dest_dir ): void {
$shell_command = ( 'Darwin' === PHP_OS )
? Utils\esc_cmd( 'cp -R %s/* %s', $src_dir, $dest_dir )
: Utils\esc_cmd( 'cp -r %s/* %s', $src_dir, $dest_dir );
Process::create( $shell_command )->run_check();
}
- public function add_line_to_wp_config( &$wp_config_code, $line ) {
+ /**
+ * @param string $wp_config_code
+ * @param string $line
+ */
+ public function add_line_to_wp_config( &$wp_config_code, $line ): void {
$token = "/* That's all, stop editing!";
$wp_config_code = str_replace( $token, "$line\n\n$token", $wp_config_code );
}
- public function download_wp( $subdir = '' ) {
+ /**
+ * @param string $subdir
+ */
+ public function download_wp( $subdir = '' ): void {
$dest_dir = $this->variables['RUN_DIR'] . "/$subdir";
if ( $subdir ) {
@@ -1106,10 +1241,10 @@ public function download_wp( $subdir = '' ) {
}
// Disable emailing.
- copy( dirname( dirname( __DIR__ ) ) . '/utils/no-mail.php', $dest_dir . '/wp-content/mu-plugins/no-mail.php' );
+ copy( dirname( __DIR__, 2 ) . '/utils/no-mail.php', $dest_dir . '/wp-content/mu-plugins/no-mail.php' );
// Add polyfills.
- copy( dirname( dirname( __DIR__ ) ) . '/utils/polyfills.php', $dest_dir . '/wp-content/mu-plugins/polyfills.php' );
+ copy( dirname( __DIR__, 2 ) . '/utils/polyfills.php', $dest_dir . '/wp-content/mu-plugins/polyfills.php' );
if ( 'sqlite' === self::$db_type ) {
self::copy_dir( self::$sqlite_cache_dir, $dest_dir . '/wp-content/mu-plugins' );
@@ -1117,7 +1252,13 @@ public function download_wp( $subdir = '' ) {
}
}
- public function create_config( $subdir = '', $extra_php = false ) {
+ /**
+ * Create a wp-config.php file.
+ *
+ * @param string $subdir
+ * @param string|false $extra_php
+ */
+ public function create_config( $subdir = '', $extra_php = false ): void {
$params = self::$db_settings;
// Replaces all characters that are not alphanumeric or an underscore into an underscore.
@@ -1150,7 +1291,10 @@ public function create_config( $subdir = '', $extra_php = false ) {
}
}
- public function install_wp( $subdir = '' ) {
+ /**
+ * @param string $subdir
+ */
+ public function install_wp( $subdir = '' ): void {
$wp_version = getenv( 'WP_VERSION' );
$wp_version_suffix = ( false !== $wp_version ) ? "-$wp_version" : '';
self::$install_cache_dir = sys_get_temp_dir() . '/wp-cli-test-core-install-cache' . $wp_version_suffix;
@@ -1179,14 +1323,11 @@ public function install_wp( $subdir = '' ) {
'skip-email' => true,
];
- $run_dir = '' !== $subdir ? ( $this->variables['RUN_DIR'] . "/$subdir" ) : $this->variables['RUN_DIR'];
- $install_cache_path = '';
+ $run_dir = '' !== $subdir ? ( $this->variables['RUN_DIR'] . "/$subdir" ) : $this->variables['RUN_DIR'];
- if ( self::$install_cache_dir ) {
- $install_cache_path = self::$install_cache_dir . '/install_' . md5( implode( ':', $install_args ) . ':subdir=' . $subdir );
- }
+ $install_cache_path = self::$install_cache_dir . '/install_' . md5( implode( ':', $install_args ) . ':subdir=' . $subdir );
- if ( $install_cache_path && file_exists( $install_cache_path ) ) {
+ if ( file_exists( $install_cache_path ) ) {
self::copy_dir( $install_cache_path, $run_dir );
// This is the sqlite equivalent of restoring a database dump in MySQL
@@ -1198,31 +1339,32 @@ public function install_wp( $subdir = '' ) {
} else {
$this->proc( 'wp core install', $install_args, $subdir )->run_check();
- if ( $install_cache_path ) {
- mkdir( $install_cache_path );
+ mkdir( $install_cache_path );
- self::dir_diff_copy( $run_dir, self::$cache_dir, $install_cache_path );
+ self::dir_diff_copy( $run_dir, self::$cache_dir, $install_cache_path );
- if ( 'sqlite' !== self::$db_type ) {
- $mysqldump_binary = Utils\get_sql_dump_command();
- $mysqldump_binary = Utils\force_env_on_nix_systems( $mysqldump_binary );
- $support_column_statistics = exec( "{$mysqldump_binary} --help | grep 'column-statistics'" );
- $command = "{$mysqldump_binary} --no-defaults --no-tablespaces";
- if ( $support_column_statistics ) {
- $command .= ' --skip-column-statistics';
- }
- self::run_sql( $command, [ 'result-file' => "{$install_cache_path}.sql" ], true /*add_database*/ );
+ if ( 'sqlite' !== self::$db_type ) {
+ $mysqldump_binary = Utils\get_sql_dump_command();
+ $mysqldump_binary = Utils\force_env_on_nix_systems( $mysqldump_binary );
+ $support_column_statistics = exec( "{$mysqldump_binary} --help | grep 'column-statistics'" );
+ $command = "{$mysqldump_binary} --no-defaults --no-tablespaces";
+ if ( $support_column_statistics ) {
+ $command .= ' --skip-column-statistics';
}
+ self::run_sql( $command, [ 'result-file' => "{$install_cache_path}.sql" ], true /*add_database*/ );
+ }
- if ( 'sqlite' === self::$db_type ) {
- // This is the sqlite equivalent of creating a database dump in MySQL
- copy( "$run_dir/wp-content/database/.ht.sqlite", "{$install_cache_path}.sqlite" );
- }
+ if ( 'sqlite' === self::$db_type ) {
+ // This is the sqlite equivalent of creating a database dump in MySQL
+ copy( "$run_dir/wp-content/database/.ht.sqlite", "{$install_cache_path}.sqlite" );
}
}
}
- public function install_wp_with_composer( $vendor_directory = 'vendor' ) {
+ /**
+ * @param string $vendor_directory
+ */
+ public function install_wp_with_composer( $vendor_directory = 'vendor' ): void {
$this->create_run_dir();
$this->create_db();
@@ -1266,15 +1408,13 @@ public function install_wp_with_composer( $vendor_directory = 'vendor' ) {
$this->proc( 'wp core install', $install_args )->run_check();
}
- public function composer_add_wp_cli_local_repository() {
+ public function composer_add_wp_cli_local_repository(): void {
if ( ! self::$composer_local_repository ) {
self::$composer_local_repository = sys_get_temp_dir() . '/' . uniqid( 'wp-cli-composer-local-', true );
mkdir( self::$composer_local_repository );
$env = self::get_process_env_variables();
- $src = isset( $env['TRAVIS_BUILD_DIR'] )
- ? $env['TRAVIS_BUILD_DIR']
- : realpath( self::get_vendor_dir() . '/../' );
+ $src = $env['TRAVIS_BUILD_DIR'] ?? realpath( self::get_vendor_dir() . '/../' );
self::copy_dir( $src, self::$composer_local_repository . '/' );
self::remove_dir( self::$composer_local_repository . '/.git' );
@@ -1285,13 +1425,16 @@ public function composer_add_wp_cli_local_repository() {
$this->variables['COMPOSER_LOCAL_REPOSITORY'] = self::$composer_local_repository;
}
- public function composer_require_current_wp_cli() {
+ public function composer_require_current_wp_cli(): void {
$this->composer_add_wp_cli_local_repository();
// TODO: Specific alias version should be deduced to keep up-to-date.
$this->composer_command( 'require "wp-cli/wp-cli:dev-main as 2.5.x-dev" --optimize-autoloader' );
}
- public function start_php_server( $subdir = '' ) {
+ /**
+ * @param string $subdir
+ */
+ public function start_php_server( $subdir = '' ): void {
$dir = $this->variables['RUN_DIR'] . '/';
if ( $subdir ) {
$dir .= trim( $subdir, '/' ) . '/';
@@ -1307,7 +1450,10 @@ public function start_php_server( $subdir = '' ) {
$this->background_proc( $cmd );
}
- private function composer_command( $cmd ) {
+ /**
+ * @param string $cmd
+ */
+ private function composer_command( $cmd ): void {
if ( ! isset( $this->variables['COMPOSER_PATH'] ) ) {
$this->variables['COMPOSER_PATH'] = exec( 'which composer' );
}
@@ -1316,8 +1462,10 @@ private function composer_command( $cmd ) {
/**
* Initialize run time logging.
+ *
+ * @param BeforeSuiteScope $scope
*/
- private static function log_run_times_before_suite( BeforeSuiteScope $scope ) {
+ private static function log_run_times_before_suite( BeforeSuiteScope $scope ): void {
self::$suite_start_time = microtime( true );
Process::$log_run_times = true;
@@ -1345,8 +1493,10 @@ private static function log_run_times_before_suite( BeforeSuiteScope $scope ) {
/**
* Record the start time of the scenario into the `$scenario_run_times` array.
+ *
+ * @param ScenarioScope|FeatureScope|OutlineTested $scope
*/
- private static function log_run_times_before_scenario( $scope ) {
+ private static function log_run_times_before_scenario( $scope ): void {
$scenario_key = self::get_scenario_key( $scope );
if ( $scenario_key ) {
self::$scenario_run_times[ $scenario_key ] = -microtime( true );
@@ -1355,8 +1505,10 @@ private static function log_run_times_before_scenario( $scope ) {
/**
* Save the run time of the scenario into the `$scenario_run_times` array. Only the top `self::$num_top_scenarios` are kept.
+ *
+ * @param ScenarioScope|FeatureScope|OutlineTested $scope
*/
- private static function log_run_times_after_scenario( $scope ) {
+ private static function log_run_times_after_scenario( $scope ): void {
$scenario_key = self::get_scenario_key( $scope );
if ( $scenario_key ) {
self::$scenario_run_times[ $scenario_key ] += microtime( true );
@@ -1376,7 +1528,7 @@ private static function log_run_times_after_scenario( $scope ) {
* @param string $src_dir The directory to be compared to `$upd_dir`.
* @param string $cop_dir Where to copy any files/directories in `$upd_dir` but not in `$src_dir` to.
*/
- private static function dir_diff_copy( $upd_dir, $src_dir, $cop_dir ) {
+ private static function dir_diff_copy( $upd_dir, $src_dir, $cop_dir ): void {
$files = scandir( $upd_dir );
if ( false === $files ) {
$error = error_get_last();
@@ -1406,12 +1558,14 @@ private static function dir_diff_copy( $upd_dir, $src_dir, $cop_dir ) {
/**
* Get the scenario key used for `$scenario_run_times` array.
* Format " :", eg "core-command core-update.feature:221".
+ *
+ * @param ScenarioScope|FeatureScope|OutlineTested $scope
*/
- private static function get_scenario_key( $scope ) {
+ private static function get_scenario_key( $scope ): string {
$scenario_key = '';
$file = self::get_event_file( $scope, $line );
if ( isset( $file ) ) {
- $scenario_grandparent = Utils\basename( dirname( dirname( $file ) ) );
+ $scenario_grandparent = Utils\basename( dirname( $file, 2 ) );
$scenario_key = $scenario_grandparent . ' ' . Utils\basename( $file ) . ':' . $line;
}
return $scenario_key;
@@ -1420,7 +1574,7 @@ private static function get_scenario_key( $scope ) {
/**
* Print out stats on the run times of processes and scenarios.
*/
- private static function log_run_times_after_suite( AfterSuiteScope $scope ) {
+ private static function log_run_times_after_suite( AfterSuiteScope $scope ): void {
$suite = '';
if ( self::$scenario_run_times ) {
@@ -1429,10 +1583,10 @@ private static function log_run_times_after_suite( AfterSuiteScope $scope ) {
$suite = substr( $keys[0], 0, strpos( $keys[0], ' ' ) );
}
- $run_from = Utils\basename( dirname( dirname( __DIR__ ) ) );
+ $run_from = Utils\basename( dirname( __DIR__, 2 ) );
// Format same as Behat, if have minutes.
- $fmt = function ( $time ) {
+ $fmt = static function ( $time ) {
$mins = floor( $time / 60 );
return round( $time, 3 ) . ( $mins ? ( ' (' . $mins . 'm' . round( $time - ( $mins * 60 ), 3 ) . 's)' ) : '' );
};
@@ -1443,7 +1597,7 @@ private static function log_run_times_after_suite( AfterSuiteScope $scope ) {
// Process and proc method run times.
$run_times = array_merge( Process::$run_times, self::$proc_method_run_times );
- $reduce_callback = function ( $carry, $item ) {
+ $reduce_callback = static function ( $carry, $item ) {
return [ $carry[0] + $item[0], $carry[1] + $item[1] ];
};
@@ -1465,14 +1619,14 @@ private static function log_run_times_after_suite( AfterSuiteScope $scope ) {
$run_from
);
- $sort_callback = function ( $a, $b ) {
+ $sort_callback = static function ( $a, $b ) {
return $a[0] === $b[0] ? 0 : ( $a[0] < $b[0] ? 1 : -1 ); // Reverse sort.
};
uasort( $run_times, $sort_callback );
$tops = array_slice( $run_times, 0, self::$num_top_processes, true );
- $runtime_callback = function ( $k, $v, $i ) {
+ $runtime_callback = static function ( $k, $v, $i ) {
return sprintf( ' %3d. %7.3f %3d %s', $i + 1, round( $v[0], 3 ), $v[1], $k );
};
@@ -1492,7 +1646,7 @@ private static function log_run_times_after_suite( AfterSuiteScope $scope ) {
$tops = array_slice( self::$scenario_run_times, 0, self::$num_top_scenarios, true );
- $scenario_runtime_callback = function ( $k, $v, $i ) {
+ $scenario_runtime_callback = static function ( $k, $v, $i ) {
return sprintf( ' %3d. %7.3f %s', $i + 1, round( $v, 3 ), substr( $k, strpos( $k, ' ' ) + 1 ) );
};
@@ -1519,8 +1673,11 @@ private static function log_run_times_after_suite( AfterSuiteScope $scope ) {
/**
* Log the run time of a proc method (one that doesn't use Process but does (use a function that does) a `proc_open()`).
+ *
+ * @param string $key
+ * @param int|float $start_time
*/
- private static function log_proc_method_run_time( $key, $start_time ) {
+ private static function log_proc_method_run_time( $key, $start_time ): void {
$run_time = microtime( true ) - $start_time;
if ( ! isset( self::$proc_method_run_times[ $key ] ) ) {
self::$proc_method_run_times[ $key ] = [ 0, 0 ];
@@ -1530,8 +1687,11 @@ private static function log_proc_method_run_time( $key, $start_time ) {
}
}
-// phpcs:ignore Universal.Files.SeparateFunctionsFromOO.Mixed
-function wp_cli_behat_env_debug( $message ) {
+
+/**
+ * @param string $message
+ */
+function wp_cli_behat_env_debug( $message ): void { // phpcs:ignore Universal.Files.SeparateFunctionsFromOO.Mixed
if ( ! getenv( 'WP_CLI_TEST_DEBUG_BEHAT_ENV' ) ) {
return;
}
@@ -1542,7 +1702,7 @@ function wp_cli_behat_env_debug( $message ) {
/**
* Load required support files as needed before heading into the Behat context.
*/
-function wpcli_bootstrap_behat_feature_context() {
+function wpcli_bootstrap_behat_feature_context(): void {
$vendor_folder = FeatureContext::get_vendor_dir();
wp_cli_behat_env_debug( "Vendor folder location: {$vendor_folder}" );
@@ -1557,11 +1717,6 @@ function wpcli_bootstrap_behat_feature_context() {
$framework_folder = FeatureContext::get_framework_dir();
wp_cli_behat_env_debug( "Framework folder location: {$framework_folder}" );
- // Didn't manage to detect a valid framework folder.
- if ( empty( $vendor_folder ) ) {
- return;
- }
-
// Load helper functionality that is needed for the tests.
require_once "{$framework_folder}/php/utils.php";
require_once "{$framework_folder}/php/WP_CLI/Process.php";
diff --git a/src/Context/GivenStepDefinitions.php b/src/Context/GivenStepDefinitions.php
index d4e8b5fb8..3df2d5324 100644
--- a/src/Context/GivenStepDefinitions.php
+++ b/src/Context/GivenStepDefinitions.php
@@ -23,7 +23,7 @@ trait GivenStepDefinitions {
*
* @Given an empty directory
*/
- public function given_an_empty_directory() {
+ public function given_an_empty_directory(): void {
$this->create_run_dir();
}
@@ -40,8 +40,11 @@ public function given_an_empty_directory() {
* @access public
*
* @Given /^an? (empty|non-existent) ([^\s]+) directory$/
+ *
+ * @param string $empty_or_nonexistent
+ * @param string $dir
*/
- public function given_a_specific_directory( $empty_or_nonexistent, $dir ) {
+ public function given_a_specific_directory( $empty_or_nonexistent, $dir ): void {
$dir = $this->replace_variables( $dir );
if ( ! Utils\is_path_absolute( $dir ) ) {
$dir = $this->variables['RUN_DIR'] . "/$dir";
@@ -82,7 +85,7 @@ public function given_a_specific_directory( $empty_or_nonexistent, $dir ) {
*
* @Given an empty cache
*/
- public function given_an_empty_cache() {
+ public function given_an_empty_cache(): void {
$this->variables['SUITE_CACHE_DIR'] = FeatureContext::create_cache_dir();
}
@@ -105,8 +108,12 @@ public function given_an_empty_cache() {
* @access public
*
* @Given /^an? ([^\s]+) (file|cache file):$/
+ *
+ * @param string $path
+ * @param string $type
+ * @param PyStringNode $content
*/
- public function given_a_specific_file( $path, $type, PyStringNode $content ) {
+ public function given_a_specific_file( $path, $type, PyStringNode $content ): void {
$path = $this->replace_variables( (string) $path );
$content = $this->replace_variables( (string) $content ) . "\n";
$full_path = 'cache file' === $type
@@ -131,8 +138,12 @@ public function given_a_specific_file( $path, $type, PyStringNode $content ) {
* @access public
*
* @Given /^"([^"]+)" replaced with "([^"]+)" in the ([^\s]+) file$/
+ *
+ * @param string $search
+ * @param string $replace
+ * @param string $path
*/
- public function given_string_replaced_with_string_in_a_specific_file( $search, $replace, $path ) {
+ public function given_string_replaced_with_string_in_a_specific_file( $search, $replace, $path ): void {
$full_path = $this->variables['RUN_DIR'] . "/$path";
$contents = file_get_contents( $full_path );
$contents = str_replace( $search, $replace, $contents );
@@ -156,8 +167,11 @@ public function given_string_replaced_with_string_in_a_specific_file( $search, $
* @access public
*
* @Given /^that HTTP requests to (.*?) will respond with:$/
+ *
+ * @param string $url_or_pattern
+ * @param PyStringNode $content
*/
- public function given_a_request_to_a_url_respond_with_file( $url_or_pattern, PyStringNode $content ) {
+ public function given_a_request_to_a_url_respond_with_file( $url_or_pattern, PyStringNode $content ): void {
if ( ! isset( $this->variables['RUN_DIR'] ) ) {
$this->create_run_dir();
}
@@ -325,7 +339,7 @@ static function( \$pre, \$parsed_args, \$url ) {
*
* @Given WP files
*/
- public function given_wp_files() {
+ public function given_wp_files(): void {
$this->download_wp();
}
@@ -343,7 +357,7 @@ public function given_wp_files() {
*
* @Given wp-config.php
*/
- public function given_wp_config_php() {
+ public function given_wp_config_php(): void {
$this->create_config();
}
@@ -362,7 +376,7 @@ public function given_wp_config_php() {
*
* @Given a database
*/
- public function given_a_database() {
+ public function given_a_database(): void {
$this->create_db();
}
@@ -383,7 +397,7 @@ public function given_a_database() {
*
* @Given a WP install(ation)
*/
- public function given_a_wp_installation() {
+ public function given_a_wp_installation(): void {
$this->install_wp();
}
@@ -403,8 +417,10 @@ public function given_a_wp_installation() {
* @access public
*
* @Given a WP install(ation) in :subdir
+ *
+ * @param string $subdir
*/
- public function given_a_wp_installation_in_a_specific_folder( $subdir ) {
+ public function given_a_wp_installation_in_a_specific_folder( $subdir ): void {
$this->install_wp( $subdir );
}
@@ -425,7 +441,7 @@ public function given_a_wp_installation_in_a_specific_folder( $subdir ) {
*
* @Given a WP install(ation) with Composer
*/
- public function given_a_wp_installation_with_composer() {
+ public function given_a_wp_installation_with_composer(): void {
$this->install_wp_with_composer();
}
@@ -445,8 +461,10 @@ public function given_a_wp_installation_with_composer() {
* @access public
*
* @Given a WP install(ation) with Composer and a custom vendor directory :vendor_directory
+ *
+ * @param string $vendor_directory
*/
- public function given_a_wp_installation_with_composer_and_a_custom_vendor_folder( $vendor_directory ) {
+ public function given_a_wp_installation_with_composer_and_a_custom_vendor_folder( $vendor_directory ): void {
$this->install_wp_with_composer( $vendor_directory );
}
@@ -468,8 +486,10 @@ public function given_a_wp_installation_with_composer_and_a_custom_vendor_folder
* @access public
*
* @Given /^a WP multisite (subdirectory|subdomain)?\s?(install|installation)$/
+ *
+ * @param string $type Multisite installation type.
*/
- public function given_a_wp_multisite_installation( $type = 'subdirectory' ) {
+ public function given_a_wp_multisite_installation( $type = 'subdirectory' ): void {
$this->install_wp();
$subdomains = ! empty( $type ) && 'subdomain' === $type ? 1 : 0;
$this->proc(
@@ -497,8 +517,10 @@ public function given_a_wp_multisite_installation( $type = 'subdirectory' ) {
* @access public
*
* @Given these installed and active plugins:
+ *
+ * @param string $stream
*/
- public function given_these_installed_and_active_plugins( $stream ) {
+ public function given_these_installed_and_active_plugins( $stream ): void {
$plugins = implode( ' ', array_map( 'trim', explode( PHP_EOL, (string) $stream ) ) );
$plugins = $this->replace_variables( $plugins );
@@ -520,7 +542,7 @@ public function given_these_installed_and_active_plugins( $stream ) {
*
* @Given a custom wp-content directory
*/
- public function given_a_custom_wp_directory() {
+ public function given_a_custom_wp_directory(): void {
$wp_config_path = $this->variables['RUN_DIR'] . '/wp-config.php';
$wp_config_code = file_get_contents( $wp_config_path );
@@ -574,7 +596,7 @@ public function given_a_custom_wp_directory() {
*
* @Given download:
*/
- public function given_a_download( TableNode $table ) {
+ public function given_a_download( TableNode $table ): void {
foreach ( $table->getHash() as $row ) {
$path = $this->replace_variables( $row['path'] );
if ( file_exists( $path ) ) {
@@ -602,8 +624,12 @@ public function given_a_download( TableNode $table ) {
* @access public
*
* @Given /^save (STDOUT|STDERR) ([\'].+[^\'])?\s?as \{(\w+)\}$/
+ *
+ * @param string $stream
+ * @param string $output_filter
+ * @param string $key
*/
- public function given_saved_stdout_stderr( $stream, $output_filter, $key ) {
+ public function given_saved_stdout_stderr( $stream, $output_filter, $key ): void {
$stream = strtolower( $stream );
if ( $output_filter ) {
@@ -631,8 +657,10 @@ public function given_saved_stdout_stderr( $stream, $output_filter, $key ) {
* @access public
*
* @Given /^a new Phar with (?:the same version|version "([^"]+)")$/
+ *
+ * @param string $version
*/
- public function given_a_new_phar_with_a_specific_version( $version = 'same' ) {
+ public function given_a_new_phar_with_a_specific_version( $version = 'same' ): void {
$this->build_phar( $version );
}
@@ -652,8 +680,10 @@ public function given_a_new_phar_with_a_specific_version( $version = 'same' ) {
* @access public
*
* @Given /^a downloaded Phar with (?:the same version|version "([^"]+)")$/
+ *
+ * @param string $version
*/
- public function given_a_downloaded_phar_with_a_specific_version( $version = 'same' ) {
+ public function given_a_downloaded_phar_with_a_specific_version( $version = 'same' ): void {
$this->download_phar( $version );
}
@@ -669,8 +699,12 @@ public function given_a_downloaded_phar_with_a_specific_version( $version = 'sam
* @access public
*
* @Given /^save the (.+) file ([\'].+[^\'])?as \{(\w+)\}$/
+ *
+ * @param string $filepath
+ * @param string $output_filter
+ * @param string $key
*/
- public function given_saved_a_specific_file( $filepath, $output_filter, $key ) {
+ public function given_saved_a_specific_file( $filepath, $output_filter, $key ): void {
$full_file = file_get_contents( $this->replace_variables( $filepath ) );
if ( $output_filter ) {
@@ -699,7 +733,7 @@ public function given_saved_a_specific_file( $filepath, $output_filter, $key ) {
*
* @Given a misconfigured WP_CONTENT_DIR constant directory
*/
- public function given_a_misconfigured_wp_content_dir_constant_directory() {
+ public function given_a_misconfigured_wp_content_dir_constant_directory(): void {
$wp_config_path = $this->variables['RUN_DIR'] . '/wp-config.php';
$wp_config_code = file_get_contents( $wp_config_path );
@@ -725,7 +759,7 @@ public function given_a_misconfigured_wp_content_dir_constant_directory() {
*
* @Given a dependency on current wp-cli
*/
- public function given_a_dependency_on_wp_cli() {
+ public function given_a_dependency_on_wp_cli(): void {
$this->composer_require_current_wp_cli();
}
@@ -742,7 +776,7 @@ public function given_a_dependency_on_wp_cli() {
*
* @Given a PHP built-in web server
*/
- public function given_a_php_built_in_web_server() {
+ public function given_a_php_built_in_web_server(): void {
$this->start_php_server();
}
@@ -758,8 +792,10 @@ public function given_a_php_built_in_web_server() {
* @access public
*
* @Given a PHP built-in web server to serve :subdir
+ *
+ * @param string $subdir
*/
- public function given_a_php_built_in_web_server_to_serve_a_specific_folder( $subdir ) {
+ public function given_a_php_built_in_web_server_to_serve_a_specific_folder( $subdir ): void {
$this->start_php_server( $subdir );
}
}
diff --git a/src/Context/Support.php b/src/Context/Support.php
index 67a16ab40..cd3f34ca6 100644
--- a/src/Context/Support.php
+++ b/src/Context/Support.php
@@ -11,46 +11,89 @@
trait Support {
-
- protected function assert_regex( $regex, $actual ) {
+ /**
+ * @param string $regex
+ * @param string $actual
+ * @throws Exception
+ */
+ protected function assert_regex( $regex, $actual ): void {
if ( ! preg_match( $regex, $actual ) ) {
throw new Exception( 'Actual value: ' . var_export( $actual, true ) );
}
}
- protected function assert_not_regex( $regex, $actual ) {
+ /**
+ * @param string $regex
+ * @param string $actual
+ * @throws Exception
+ */
+ protected function assert_not_regex( $regex, $actual ): void {
if ( preg_match( $regex, $actual ) ) {
throw new Exception( 'Actual value: ' . var_export( $actual, true ) );
}
}
- protected function assert_equals( $expected, $actual ) {
+ /**
+ * Loose comparison.
+ *
+ * @param mixed $expected
+ * @param mixed $actual
+ * @throws Exception
+ */
+ protected function assert_equals( $expected, $actual ): void {
// phpcs:ignore Universal.Operators.StrictComparisons.LooseNotEqual -- Deliberate loose comparison.
if ( $expected != $actual ) {
throw new Exception( 'Actual value: ' . var_export( $actual, true ) );
}
}
- protected function assert_not_equals( $expected, $actual ) {
+ /**
+ * Loose comparison.
+ *
+ * @param mixed $expected
+ * @param mixed $actual
+ * @throws Exception
+ */
+ protected function assert_not_equals( $expected, $actual ): void {
// phpcs:ignore Universal.Operators.StrictComparisons.LooseEqual -- Deliberate loose comparison.
if ( $expected == $actual ) {
throw new Exception( 'Actual value: ' . var_export( $actual, true ) );
}
}
- protected function assert_numeric( $actual ) {
+ /**
+ * @param mixed $actual
+ * @throws Exception
+ *
+ * @phpstan-assert numeric-string|number $actual
+ */
+ protected function assert_numeric( $actual ): void {
if ( ! is_numeric( $actual ) ) {
throw new Exception( 'Actual value: ' . var_export( $actual, true ) );
}
}
- protected function assert_not_numeric( $actual ) {
+ /**
+ * @param mixed $actual
+ * @throws Exception
+ *
+ * @phpstan-assert !(numeric-string|number) $actual
+ */
+ protected function assert_not_numeric( $actual ): void {
if ( is_numeric( $actual ) ) {
throw new Exception( 'Actual value: ' . var_export( $actual, true ) );
}
}
- protected function check_string( $output, $expected, $action, $message = false, $strictly = false ) {
+ /**
+ * @param string $output
+ * @param string $expected
+ * @param string $action
+ * @param string|false $message
+ * @param bool $strictly
+ * @throws Exception
+ */
+ protected function check_string( $output, $expected, $action, $message = false, $strictly = false ): void {
// Strip ANSI color codes before comparing strings.
if ( ! $strictly ) {
$output = preg_replace( '/\e[[][A-Za-z0-9];?[0-9]*m?/', '', $output );
@@ -70,7 +113,7 @@ protected function check_string( $output, $expected, $action, $message = false,
break;
default:
- throw new PendingException();
+ throw new \Behat\Behat\Tester\Exception\PendingException();
}
if ( ! $r ) {
@@ -81,7 +124,13 @@ protected function check_string( $output, $expected, $action, $message = false,
}
}
- protected function compare_tables( $expected_rows, $actual_rows, $output ) {
+ /**
+ * @param array $expected_rows
+ * @param array $actual_rows
+ * @param string $output
+ * @throws Exception
+ */
+ protected function compare_tables( $expected_rows, $actual_rows, $output ): void {
// The first row is the header and must be present.
if ( $expected_rows[0] !== $actual_rows[0] ) {
throw new Exception( $output );
@@ -96,6 +145,11 @@ protected function compare_tables( $expected_rows, $actual_rows, $output ) {
}
}
+ /**
+ * @param mixed $expected
+ * @param mixed $actual
+ * @return bool
+ */
protected function compare_contents( $expected, $actual ) {
if ( gettype( $expected ) !== gettype( $actual ) ) {
return false;
@@ -167,8 +221,8 @@ protected function check_that_json_string_contains_json_string( $actual_json, $e
* Both strings are expected to have headers for their CSVs.
* $actualCSV must match all data rows in $expectedCSV
*
- * @param string $actual_csv A CSV string
- * @param array $expected_csv A nested array of values
+ * @param string $actual_csv A CSV string
+ * @param array> $expected_csv A nested array of values
* @return bool Whether $actual_csv contains $expected_csv
*/
protected function check_that_csv_string_contains_values( $actual_csv, $expected_csv ) {
@@ -183,6 +237,10 @@ static function ( $str ) {
return false;
}
+ /**
+ * @var array> $actual_csv
+ */
+
// Each sample must have headers.
$actual_headers = array_values( array_shift( $actual_csv ) );
$expected_headers = array_values( array_shift( $expected_csv ) );
diff --git a/src/Context/ThenStepDefinitions.php b/src/Context/ThenStepDefinitions.php
index 6a2cca92b..9ab0477f9 100644
--- a/src/Context/ThenStepDefinitions.php
+++ b/src/Context/ThenStepDefinitions.php
@@ -25,8 +25,11 @@ trait ThenStepDefinitions {
* @access public
*
* @Then /^the return code should( not)? be (\d+)$/
+ *
+ * @param bool $not
+ * @param numeric-string $return_code
*/
- public function then_the_return_code_should_be( $not, $return_code ) {
+ public function then_the_return_code_should_be( $not, $return_code ): void {
if (
( ! $not && (int) $return_code !== $this->result->return_code )
|| ( $not && (int) $return_code === $this->result->return_code )
@@ -57,8 +60,13 @@ public function then_the_return_code_should_be( $not, $return_code ) {
* @access public
*
* @Then /^(STDOUT|STDERR) should( strictly)? (be|contain|not contain):$/
+ *
+ * @param string $stream
+ * @param bool $strictly
+ * @param string $action
+ * @param PyStringNode $expected
*/
- public function then_stdout_stderr_should_contain( $stream, $strictly, $action, PyStringNode $expected ) {
+ public function then_stdout_stderr_should_contain( $stream, $strictly, $action, PyStringNode $expected ): void {
$stream = strtolower( $stream );
@@ -80,8 +88,10 @@ public function then_stdout_stderr_should_contain( $stream, $strictly, $action,
* @access public
*
* @Then /^(STDOUT|STDERR) should be a number$/
+ *
+ * @param string $stream
*/
- public function then_stdout_stderr_should_be_a_number( $stream ) {
+ public function then_stdout_stderr_should_be_a_number( $stream ): void {
$stream = strtolower( $stream );
@@ -101,8 +111,10 @@ public function then_stdout_stderr_should_be_a_number( $stream ) {
* @access public
*
* @Then /^(STDOUT|STDERR) should not be a number$/
+ *
+ * @param string $stream
*/
- public function then_stdout_stderr_should_not_be_a_number( $stream ) {
+ public function then_stdout_stderr_should_not_be_a_number( $stream ): void {
$stream = strtolower( $stream );
@@ -126,7 +138,7 @@ public function then_stdout_stderr_should_not_be_a_number( $stream ) {
*
* @Then /^STDOUT should be a table containing rows:$/
*/
- public function then_stdout_should_be_a_table_containing_rows( TableNode $expected ) {
+ public function then_stdout_should_be_a_table_containing_rows( TableNode $expected ): void {
$output = $this->result->stdout;
$actual_rows = explode( "\n", rtrim( $output, "\n" ) );
@@ -162,7 +174,7 @@ public function then_stdout_should_be_a_table_containing_rows( TableNode $expect
*
* @Then /^STDOUT should end with a table containing rows:$/
*/
- public function then_stdout_should_end_with_a_table_containing_rows( TableNode $expected ) {
+ public function then_stdout_should_end_with_a_table_containing_rows( TableNode $expected ): void {
$output = $this->result->stdout;
$actual_rows = explode( "\n", rtrim( $output, "\n" ) );
@@ -198,7 +210,7 @@ public function then_stdout_should_end_with_a_table_containing_rows( TableNode $
*
* @Then /^STDOUT should be JSON containing:$/
*/
- public function then_stdout_should_be_json_containing( PyStringNode $expected ) {
+ public function then_stdout_should_be_json_containing( PyStringNode $expected ): void {
$output = $this->result->stdout;
$expected = $this->replace_variables( (string) $expected );
@@ -225,7 +237,7 @@ public function then_stdout_should_be_json_containing( PyStringNode $expected )
*
* @Then /^STDOUT should be a JSON array containing:$/
*/
- public function then_stdout_should_be_a_json_array_containing( PyStringNode $expected ) {
+ public function then_stdout_should_be_a_json_array_containing( PyStringNode $expected ): void {
$output = $this->result->stdout;
$expected = $this->replace_variables( (string) $expected );
@@ -253,7 +265,7 @@ public function then_stdout_should_be_a_json_array_containing( PyStringNode $exp
*
* @Then /^STDOUT should be CSV containing:$/
*/
- public function then_stdout_should_be_csv_containing( TableNode $expected ) {
+ public function then_stdout_should_be_csv_containing( TableNode $expected ): void {
$output = $this->result->stdout;
$expected_rows = $expected->getRows();
@@ -286,7 +298,7 @@ public function then_stdout_should_be_csv_containing( TableNode $expected ) {
*
* @Then /^STDOUT should be YAML containing:$/
*/
- public function then_stdout_should_be_yaml_containing( PyStringNode $expected ) {
+ public function then_stdout_should_be_yaml_containing( PyStringNode $expected ): void {
$output = $this->result->stdout;
$expected = $this->replace_variables( (string) $expected );
@@ -308,8 +320,10 @@ public function then_stdout_should_be_yaml_containing( PyStringNode $expected )
* @access public
*
* @Then /^(STDOUT|STDERR) should be empty$/
+ *
+ * @param string $stream
*/
- public function then_stdout_stderr_should_be_empty( $stream ) {
+ public function then_stdout_stderr_should_be_empty( $stream ): void {
$stream = strtolower( $stream );
@@ -330,8 +344,10 @@ public function then_stdout_stderr_should_be_empty( $stream ) {
* @access public
*
* @Then /^(STDOUT|STDERR) should not be empty$/
+ *
+ * @param string $stream
*/
- public function then_stdout_stderr_should_not_be_empty( $stream ) {
+ public function then_stdout_stderr_should_not_be_empty( $stream ): void {
$stream = strtolower( $stream );
@@ -353,8 +369,12 @@ public function then_stdout_stderr_should_not_be_empty( $stream ) {
* @access public
*
* @Then /^(STDOUT|STDERR) should be a version string (<|<=|>|>=|==|=|!=|<>) ([+\w.{}-]+)$/
+ *
+ * @param string $stream
+ * @param string $operator
+ * @param string $goal_ver
*/
- public function then_stdout_stderr_should_be_a_specific_version_string( $stream, $operator, $goal_ver ) {
+ public function then_stdout_stderr_should_be_a_specific_version_string( $stream, $operator, $goal_ver ): void {
$goal_ver = $this->replace_variables( $goal_ver );
$stream = strtolower( $stream );
if ( false === version_compare( trim( $this->result->$stream, "\n" ), $goal_ver, $operator ) ) {
@@ -384,8 +404,14 @@ public function then_stdout_stderr_should_be_a_specific_version_string( $stream,
* @access public
*
* @Then /^the (.+) (file|directory) should( strictly)? (exist|not exist|be:|contain:|not contain:)$/
+ *
+ * @param string $path File/directory path.
+ * @param string $type Type, either 'file' or 'directory'.
+ * @param string $strictly Whether it's a strict check.
+ * @param string $action Expected status.
+ * @param string $expected Expected content.
*/
- public function then_a_specific_file_folder_should_exist( $path, $type, $strictly, $action, $expected = null ) {
+ public function then_a_specific_file_folder_should_exist( $path, $type, $strictly, $action, $expected = null ): void {
$path = $this->replace_variables( $path );
// If it's a relative path, make it relative to the current test dir.
@@ -423,6 +449,7 @@ public function then_a_specific_file_folder_should_exist( $path, $type, $strictl
}
$action = substr( $action, 0, -1 );
$expected = $this->replace_variables( (string) $expected );
+ $contents = '';
if ( 'file' === $type ) {
$contents = file_get_contents( $path );
} elseif ( 'directory' === $type ) {
@@ -448,8 +475,12 @@ public function then_a_specific_file_folder_should_exist( $path, $type, $strictl
* @access public
*
* @Then /^the contents of the (.+) file should( not)? match (((\/.+\/)|(#.+#))([a-z]+)?)$/
+ *
+ * @param string $path
+ * @param bool $not
+ * @param string $expected
*/
- public function then_the_contents_of_a_specific_file_should_match( $path, $not, $expected ) {
+ public function then_the_contents_of_a_specific_file_should_match( $path, $not, $expected ): void {
$path = $this->replace_variables( $path );
$expected = $this->replace_variables( $expected );
@@ -477,8 +508,12 @@ public function then_the_contents_of_a_specific_file_should_match( $path, $not,
* @access public
*
* @Then /^(STDOUT|STDERR) should( not)? match (((\/.+\/)|(#.+#))([a-z]+)?)$/
+ *
+ * @param string $stream
+ * @param bool $not
+ * @param string $expected
*/
- public function then_stdout_stderr_should_match_a_string( $stream, $not, $expected ) {
+ public function then_stdout_stderr_should_match_a_string( $stream, $not, $expected ): void {
$expected = $this->replace_variables( $expected );
$stream = strtolower( $stream );
@@ -501,8 +536,10 @@ public function then_stdout_stderr_should_match_a_string( $stream, $not, $expect
* @access public
*
* @Then /^an email should (be sent|not be sent)$/
+ *
+ * @param string $expected Expected status, either 'be sent' or 'not be sent'.
*/
- public function then_an_email_should_be_sent( $expected ) {
+ public function then_an_email_should_be_sent( $expected ): void {
if ( 'be sent' === $expected ) {
$this->assert_not_equals( 0, $this->email_sends );
} elseif ( 'not be sent' === $expected ) {
@@ -525,8 +562,10 @@ public function then_an_email_should_be_sent( $expected ) {
* @access public
*
* @Then the HTTP status code should be :code
+ *
+ * @param int $return_code Expected HTTP status code.
*/
- public function then_the_http_status_code_should_be( $return_code ) {
+ public function then_the_http_status_code_should_be( $return_code ): void {
$response = Requests::request( 'http://localhost:8080' );
$this->assert_equals( $return_code, $response->status_code );
}
diff --git a/src/Context/WhenStepDefinitions.php b/src/Context/WhenStepDefinitions.php
index eaa14a141..2de8b3e2e 100644
--- a/src/Context/WhenStepDefinitions.php
+++ b/src/Context/WhenStepDefinitions.php
@@ -7,6 +7,11 @@
trait WhenStepDefinitions {
+ /**
+ * @param Process $proc Process instance.
+ * @param string $mode Mode, either 'run' or 'try'.
+ * @return mixed
+ */
public function wpcli_tests_invoke_proc( $proc, $mode ) {
$map = array(
'run' => 'run_check_stderr',
@@ -17,7 +22,13 @@ public function wpcli_tests_invoke_proc( $proc, $mode ) {
return $proc->$method();
}
- public function wpcli_tests_capture_email_sends( $stdout ) {
+ /**
+ * Capture the number of sent emails by parsing STDOUT.
+ *
+ * @param string $stdout
+ * @return array{string, int}
+ */
+ public function wpcli_tests_capture_email_sends( $stdout ): array {
$stdout = preg_replace( '#WP-CLI test suite: Sent email to.+\n?#', '', $stdout, -1, $email_sends );
return array( $stdout, $email_sends );
@@ -36,8 +47,10 @@ public function wpcli_tests_capture_email_sends( $stdout ) {
* @access public
*
* @When /^I launch in the background `([^`]+)`$/
+ *
+ * @param string $cmd Command to run.
*/
- public function when_i_launch_in_the_background( $cmd ) {
+ public function when_i_launch_in_the_background( $cmd ): void {
$this->background_proc( $cmd );
}
@@ -68,8 +81,11 @@ public function when_i_launch_in_the_background( $cmd ) {
* @access public
*
* @When /^I (run|try) `([^`]+)`$/
+ *
+ * @param string $mode Mode, either 'run' or 'try'.
+ * @param string $cmd Command to execute.
*/
- public function when_i_run( $mode, $cmd ) {
+ public function when_i_run( $mode, $cmd ): void {
$cmd = $this->replace_variables( $cmd );
$this->result = $this->wpcli_tests_invoke_proc( $this->proc( $cmd ), $mode );
list( $this->result->stdout, $this->email_sends ) = $this->wpcli_tests_capture_email_sends( $this->result->stdout );
@@ -92,8 +108,12 @@ public function when_i_run( $mode, $cmd ) {
* @access public
*
* @When /^I (run|try) `([^`]+)` from '([^\s]+)'$/
+ *
+ * @param string $mode Mode, either 'run' or 'try'.
+ * @param string $cmd Command to execute.
+ * @param string $subdir Directory.
*/
- public function when_i_run_from_a_subfolder( $mode, $cmd, $subdir ) {
+ public function when_i_run_from_a_subfolder( $mode, $cmd, $subdir ): void {
$cmd = $this->replace_variables( $cmd );
$this->result = $this->wpcli_tests_invoke_proc( $this->proc( $cmd, array(), $subdir ), $mode );
list( $this->result->stdout, $this->email_sends ) = $this->wpcli_tests_capture_email_sends( $this->result->stdout );
@@ -122,8 +142,10 @@ public function when_i_run_from_a_subfolder( $mode, $cmd, $subdir ) {
* @access public
*
* @When /^I (run|try) the previous command again$/
+ *
+ * @param string $mode Mode, either 'run' or 'try'
*/
- public function when_i_run_the_previous_command_again( $mode ) {
+ public function when_i_run_the_previous_command_again( $mode ): void {
if ( ! isset( $this->result ) ) {
throw new Exception( 'No previous command.' );
}
diff --git a/tests/bootstrap.php b/tests/bootstrap.php
index c66cd935e..80babbe09 100644
--- a/tests/bootstrap.php
+++ b/tests/bootstrap.php
@@ -31,7 +31,11 @@
require_once WP_CLI_ROOT . '/php/utils.php';
require_once __DIR__ . '/includes/TestCase.php';
-function wpcli_tests_include_config( array $config_filenames = [] ) {
+/**
+ * @param string[] $config_filenames List of config file names to look for.
+ * @return void
+ */
+function wpcli_tests_include_config( array $config_filenames = [] ): void {
$config_filename = false;
foreach ( $config_filenames as $filename ) {
if ( file_exists( PACKAGE_ROOT . '/' . $filename ) ) {
diff --git a/tests/phpstan/scan-files.php b/tests/phpstan/scan-files.php
new file mode 100644
index 000000000..ced169fe4
--- /dev/null
+++ b/tests/phpstan/scan-files.php
@@ -0,0 +1,6 @@
+temp_dir = Utils\get_temp_dir() . uniqid( 'wp-cli-test-behat-tags-', true );
@@ -15,7 +18,7 @@ protected function set_up() {
mkdir( $this->temp_dir . '/features' );
}
- protected function tear_down() {
+ protected function tear_down(): void {
if ( $this->temp_dir && file_exists( $this->temp_dir ) ) {
foreach ( glob( $this->temp_dir . '/features/*' ) as $feature_file ) {
@@ -30,8 +33,11 @@ protected function tear_down() {
/**
* @dataProvider data_behat_tags_wp_version_github_token
+ *
+ * @param string $env
+ * @param string $expected
*/
- public function test_behat_tags_wp_version_github_token( $env, $expected ) {
+ public function test_behat_tags_wp_version_github_token( $env, $expected ): void {
$env_wp_version = getenv( 'WP_VERSION' );
$env_github_token = getenv( 'GITHUB_TOKEN' );
$db_type = getenv( 'WP_CLI_TEST_DBTYPE' );
@@ -74,7 +80,10 @@ public function test_behat_tags_wp_version_github_token( $env, $expected ) {
putenv( false === $env_github_token ? 'GITHUB_TOKEN' : "GITHUB_TOKEN=$env_github_token" );
}
- public static function data_behat_tags_wp_version_github_token() {
+ /**
+ * @return array
+ */
+ public static function data_behat_tags_wp_version_github_token(): array {
return array(
array( 'WP_VERSION=4.5', '~@require-wp-4.6&&~@require-wp-4.8&&~@require-wp-4.9&&~@github-api' ),
array( 'WP_VERSION=4.6', '~@require-wp-4.8&&~@require-wp-4.9&&~@less-than-wp-4.6&&~@github-api' ),
@@ -90,7 +99,7 @@ public static function data_behat_tags_wp_version_github_token() {
);
}
- public function test_behat_tags_php_version() {
+ public function test_behat_tags_php_version(): void {
$env_github_token = getenv( 'GITHUB_TOKEN' );
putenv( 'GITHUB_TOKEN' );
@@ -146,7 +155,7 @@ public function test_behat_tags_php_version() {
putenv( false === $env_github_token ? 'GITHUB_TOKEN' : "GITHUB_TOKEN=$env_github_token" );
}
- public function test_behat_tags_extension() {
+ public function test_behat_tags_extension(): void {
$env_github_token = getenv( 'GITHUB_TOKEN' );
$db_type = getenv( 'WP_CLI_TEST_DBTYPE' );