diff --git a/.distignore b/.distignore index ffb1e0e4..cd7978e7 100644 --- a/.distignore +++ b/.distignore @@ -14,5 +14,6 @@ /package-lock.json /phpcs* /phpunit* +/phpstan.* /readme.md -/SECURITY.md \ No newline at end of file +/SECURITY.md diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index c20d222e..c940d0db 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -59,6 +59,9 @@ jobs: - name: Lint PHP Compatibility run: composer lint-compat + - name: PHPStan + run: npm run lint:phpstan + test-php: name: Test PHP ${{ matrix.php }} ${{ matrix.wp != '' && format( ' (WP {0}) ', matrix.wp ) || '' }} runs-on: ubuntu-latest diff --git a/.gitignore b/.gitignore index 6430f0ee..d36ae742 100644 --- a/.gitignore +++ b/.gitignore @@ -5,3 +5,4 @@ /dist/ /tests/logs/ .phpunit.result.cache +phpstan.neon diff --git a/class-two-factor-compat.php b/class-two-factor-compat.php index 731a2dff..d7b4f46a 100644 --- a/class-two-factor-compat.php +++ b/class-two-factor-compat.php @@ -50,6 +50,6 @@ public function jetpack_rememberme( $rememberme ) { * @return boolean */ public function jetpack_is_sso_active() { - return ( method_exists( 'Jetpack', 'is_module_active' ) && Jetpack::is_module_active( 'sso' ) ); + return ( class_exists( 'Jetpack' ) && method_exists( 'Jetpack', 'is_module_active' ) && Jetpack::is_module_active( 'sso' ) ); } } diff --git a/class-two-factor-core.php b/class-two-factor-core.php index 51c3cee3..90b6ebaf 100644 --- a/class-two-factor-core.php +++ b/class-two-factor-core.php @@ -93,7 +93,7 @@ class Two_Factor_Core { * @since 0.1-dev */ public static function add_hooks( $compat ) { - add_action( 'init', array( __CLASS__, 'get_providers' ) ); + add_action( 'init', array( __CLASS__, 'get_providers' ) ); // @phpstan-ignore return.void add_action( 'wp_login', array( __CLASS__, 'wp_login' ), 10, 2 ); add_filter( 'wp_login_errors', array( __CLASS__, 'maybe_show_reset_password_notice' ) ); add_action( 'after_password_reset', array( __CLASS__, 'clear_password_reset_notice' ) ); diff --git a/composer.json b/composer.json index fe2389c7..2fe8e169 100644 --- a/composer.json +++ b/composer.json @@ -31,12 +31,14 @@ "phpcompatibility/phpcompatibility-wp": "^2.1", "phpunit/phpunit": "^8.5|^9.6", "spatie/phpunit-watcher": "^1.23", + "szepeviktor/phpstan-wordpress": "^1.3", "wp-coding-standards/wpcs": "^3.1", "yoast/phpunit-polyfills": "^2.0" }, "scripts": { "lint": "phpcs", "lint-compat": "phpcs -p --standard=PHPCompatibilityWP --runtime-set testVersion 7.2- --extensions=php --ignore='tests/,dist/,includes/Yubico/,vendor/,node_modules/' .", + "lint-phpstan": "phpstan analyse --verbose --memory-limit=1G", "test": "vendor/bin/phpunit", "test:watch": [ "Composer\\Config::disableProcessTimeout", diff --git a/composer.lock b/composer.lock index a4046e68..f1ecd991 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "a1a44a4d12c7db29c2010274f4d2f36f", + "content-hash": "13824921a7208b7752f2a13ecde2ab08", "packages": [], "packages-dev": [ { @@ -1121,6 +1121,54 @@ }, "time": "2023-11-22T10:21:01+00:00" }, + { + "name": "php-stubs/wordpress-stubs", + "version": "v6.6.0", + "source": { + "type": "git", + "url": "https://github.com/php-stubs/wordpress-stubs.git", + "reference": "86e8753e89d59849276dcdd91b9a7dd78bb4abe2" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-stubs/wordpress-stubs/zipball/86e8753e89d59849276dcdd91b9a7dd78bb4abe2", + "reference": "86e8753e89d59849276dcdd91b9a7dd78bb4abe2", + "shasum": "" + }, + "require-dev": { + "dealerdirect/phpcodesniffer-composer-installer": "^1.0", + "nikic/php-parser": "^4.13", + "php": "^7.4 || ^8.0", + "php-stubs/generator": "^0.8.3", + "phpdocumentor/reflection-docblock": "^5.4.1", + "phpstan/phpstan": "^1.10.49", + "phpunit/phpunit": "^9.5", + "szepeviktor/phpcs-psr-12-neutron-hybrid-ruleset": "^1.0", + "wp-coding-standards/wpcs": "3.1.0 as 2.3.0" + }, + "suggest": { + "paragonie/sodium_compat": "Pure PHP implementation of libsodium", + "symfony/polyfill-php80": "Symfony polyfill backporting some PHP 8.0+ features to lower PHP versions", + "szepeviktor/phpstan-wordpress": "WordPress extensions for PHPStan" + }, + "type": "library", + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "WordPress function and class declaration stubs for static analysis.", + "homepage": "https://github.com/php-stubs/wordpress-stubs", + "keywords": [ + "PHPStan", + "static analysis", + "wordpress" + ], + "support": { + "issues": "https://github.com/php-stubs/wordpress-stubs/issues", + "source": "https://github.com/php-stubs/wordpress-stubs/tree/v6.6.0" + }, + "time": "2024-07-17T08:50:38+00:00" + }, { "name": "phpcompatibility/php-compatibility", "version": "dev-develop", @@ -1519,6 +1567,64 @@ ], "time": "2024-05-20T13:34:27+00:00" }, + { + "name": "phpstan/phpstan", + "version": "1.12.3", + "source": { + "type": "git", + "url": "https://github.com/phpstan/phpstan.git", + "reference": "0fcbf194ab63d8159bb70d9aa3e1350051632009" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpstan/phpstan/zipball/0fcbf194ab63d8159bb70d9aa3e1350051632009", + "reference": "0fcbf194ab63d8159bb70d9aa3e1350051632009", + "shasum": "" + }, + "require": { + "php": "^7.2|^8.0" + }, + "conflict": { + "phpstan/phpstan-shim": "*" + }, + "bin": [ + "phpstan", + "phpstan.phar" + ], + "type": "library", + "autoload": { + "files": [ + "bootstrap.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "PHPStan - PHP Static Analysis Tool", + "keywords": [ + "dev", + "static analysis" + ], + "support": { + "docs": "https://phpstan.org/user-guide/getting-started", + "forum": "https://github.com/phpstan/phpstan/discussions", + "issues": "https://github.com/phpstan/phpstan/issues", + "security": "https://github.com/phpstan/phpstan/security/policy", + "source": "https://github.com/phpstan/phpstan-src" + }, + "funding": [ + { + "url": "https://github.com/ondrejmirtes", + "type": "github" + }, + { + "url": "https://github.com/phpstan", + "type": "github" + } + ], + "time": "2024-09-09T08:10:35+00:00" + }, { "name": "phpunit/php-code-coverage", "version": "7.0.17", @@ -4589,6 +4695,69 @@ ], "time": "2024-05-31T14:33:22+00:00" }, + { + "name": "szepeviktor/phpstan-wordpress", + "version": "v1.3.5", + "source": { + "type": "git", + "url": "https://github.com/szepeviktor/phpstan-wordpress.git", + "reference": "7f8cfe992faa96b6a33bbd75c7bace98864161e7" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/szepeviktor/phpstan-wordpress/zipball/7f8cfe992faa96b6a33bbd75c7bace98864161e7", + "reference": "7f8cfe992faa96b6a33bbd75c7bace98864161e7", + "shasum": "" + }, + "require": { + "php": "^7.2 || ^8.0", + "php-stubs/wordpress-stubs": "^4.7 || ^5.0 || ^6.0", + "phpstan/phpstan": "^1.10.31", + "symfony/polyfill-php73": "^1.12.0" + }, + "require-dev": { + "composer/composer": "^2.1.14", + "dealerdirect/phpcodesniffer-composer-installer": "^1.0", + "php-parallel-lint/php-parallel-lint": "^1.1", + "phpstan/phpstan-strict-rules": "^1.2", + "phpunit/phpunit": "^8.0 || ^9.0", + "szepeviktor/phpcs-psr-12-neutron-hybrid-ruleset": "^1.0", + "wp-coding-standards/wpcs": "3.1.0 as 2.3.0" + }, + "suggest": { + "swissspidy/phpstan-no-private": "Detect usage of internal core functions, classes and methods" + }, + "type": "phpstan-extension", + "extra": { + "phpstan": { + "includes": [ + "extension.neon" + ] + } + }, + "autoload": { + "psr-4": { + "SzepeViktor\\PHPStan\\WordPress\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "WordPress extensions for PHPStan", + "keywords": [ + "PHPStan", + "code analyse", + "code analysis", + "static analysis", + "wordpress" + ], + "support": { + "issues": "https://github.com/szepeviktor/phpstan-wordpress/issues", + "source": "https://github.com/szepeviktor/phpstan-wordpress/tree/v1.3.5" + }, + "time": "2024-06-28T22:27:19+00:00" + }, { "name": "theseer/tokenizer", "version": "1.2.3", diff --git a/package.json b/package.json index 7ee5b30a..894e834d 100644 --- a/package.json +++ b/package.json @@ -12,6 +12,7 @@ "build": "grunt build", "lint": "npm-run-all lint:*", "lint:php": "composer lint", + "lint:phpstan": "composer lint-phpstan", "lint:css": "wp-scripts lint-style ./user-edit.css ./providers/css/", "lint:js": "wp-scripts lint-js ./Gruntfile.js ./providers/js/", "format": "npm-run-all format:*", diff --git a/phpstan.dist.neon b/phpstan.dist.neon new file mode 100644 index 00000000..fc02e7c0 --- /dev/null +++ b/phpstan.dist.neon @@ -0,0 +1,10 @@ +includes: + - vendor/szepeviktor/phpstan-wordpress/extension.neon +parameters: + level: 0 + paths: + - includes + - providers + - class-two-factor-compat.php + - class-two-factor-core.php + - two-factor.php