diff --git a/composer.json b/composer.json index 17f53c2116f71..649a3d429324c 100644 --- a/composer.json +++ b/composer.json @@ -23,7 +23,7 @@ "squizlabs/php_codesniffer": "3.13.5", "wp-coding-standards/wpcs": "~3.3.0", "phpcompatibility/phpcompatibility-wp": "~2.1.3", - "phpstan/phpstan": "2.1.39", + "phpstan/phpstan": "2.1.40", "yoast/phpunit-polyfills": "^1.1.0" }, "config": { diff --git a/phpstan.neon.dist b/phpstan.neon.dist index e74e6ec1a441b..38dd9c63098d0 100644 --- a/phpstan.neon.dist +++ b/phpstan.neon.dist @@ -14,7 +14,7 @@ includes: parameters: # https://phpstan.org/user-guide/rule-levels - level: 0 + level: 1 reportUnmatchedIgnoredErrors: true ignoreErrors: @@ -34,3 +34,8 @@ parameters: identifier: function.inner path: src/wp-includes/canonical.php count: 1 + + # Level 1: + - # These are too noisy at the moment. + identifier: variable.undefined + message: '#Variable \$[a-zA-Z0-9_]+ might not be defined\.#' diff --git a/src/wp-admin/includes/class-custom-image-header.php b/src/wp-admin/includes/class-custom-image-header.php index eb65605728062..2c0eb26c0fc9a 100644 --- a/src/wp-admin/includes/class-custom-image-header.php +++ b/src/wp-admin/includes/class-custom-image-header.php @@ -841,7 +841,7 @@ public function step_2() { $file = get_attached_file( $attachment_id, true ); $url = wp_get_attachment_image_src( $attachment_id, 'full' ); $url = $url[0]; - } elseif ( isset( $_POST ) ) { + } else { $data = $this->step_2_manage_upload(); $attachment_id = $data['attachment_id']; $file = $data['file']; diff --git a/src/wp-admin/includes/class-wp-filesystem-direct.php b/src/wp-admin/includes/class-wp-filesystem-direct.php index a4b197c15229f..34862a661d321 100644 --- a/src/wp-admin/includes/class-wp-filesystem-direct.php +++ b/src/wp-admin/includes/class-wp-filesystem-direct.php @@ -19,10 +19,8 @@ class WP_Filesystem_Direct extends WP_Filesystem_Base { * Constructor. * * @since 2.5.0 - * - * @param mixed $arg Not used. */ - public function __construct( $arg ) { + public function __construct() { $this->method = 'direct'; $this->errors = new WP_Error(); } diff --git a/src/wp-includes/class-wpdb.php b/src/wp-includes/class-wpdb.php index 23c865b87d817..60026dbdc5c16 100644 --- a/src/wp-includes/class-wpdb.php +++ b/src/wp-includes/class-wpdb.php @@ -2117,7 +2117,9 @@ public function parse_db_host( $host ) { * @since 3.9.0 * * @param bool $allow_bail Optional. Allows the function to bail. Default true. - * @return bool|void True if the connection is up. + * @return bool Whether the connection is up. Exits when `$allow_bail` is true and the connection is down. + * + * @phpstan-return ( $allow_bail is true ? bool|never : bool ) */ public function check_connection( $allow_bail = true ) { // Check if the connection is alive. diff --git a/src/wp-includes/functions.php b/src/wp-includes/functions.php index 4b6330a697780..8bf46ef0b871f 100644 --- a/src/wp-includes/functions.php +++ b/src/wp-includes/functions.php @@ -3766,7 +3766,7 @@ function wp_nonce_ays( $action ) { * } * @return never|void Returns void if `$args['exit']` is false, otherwise exits. * - * @phpstan-return ( $args['exit'] is false ? void : never ) + * @phpstan-return ( $args is array{exit: false} ? void : never ) */ function wp_die( $message = '', $title = '', $args = array() ) { global $wp_query; @@ -5501,6 +5501,8 @@ function wp_ob_end_flush_all() { * @since 2.3.2 * * @global wpdb $wpdb WordPress database abstraction object. + * + * @return never */ function dead_db() { global $wpdb; diff --git a/tests/phpstan/base.neon b/tests/phpstan/base.neon index 347c2198ae953..7bfe9d6eff3df 100644 --- a/tests/phpstan/base.neon +++ b/tests/phpstan/base.neon @@ -25,6 +25,8 @@ parameters: - ALLOW_SUBDIRECTORY_INSTALL - AUTH_SALT - AUTOMATIC_UPDATER_DISABLED + - BACKGROUND_COLOR + - BACKGROUND_IMAGE - COOKIEPATH - CUSTOM_TAGS - DISALLOW_FILE_EDIT @@ -32,8 +34,13 @@ parameters: - EMPTY_TRASH_DAYS - ENFORCE_GZIP - FORCE_SSL_LOGIN + - HEADER_IMAGE + - HEADER_IMAGE_HEIGHT + - HEADER_IMAGE_WIDTH + - HEADER_TEXTCOLOR - MEDIA_TRASH - MULTISITE + - NO_HEADER_TEXT - NOBLOGREDIRECT - SAVEQUERIES - SCRIPT_DEBUG @@ -105,6 +112,8 @@ parameters: - ../../src/wp-includes/deprecated.php - ../../src/wp-includes/ms-deprecated.php - ../../src/wp-includes/pluggable-deprecated.php + # These files are currently pulled in from Gutenberg, but maybe not long-term. See . + - ../../src/wp-includes/build # These files are sourced by wordpress/gutenberg in `tools/release/sync-stable-blocks.js`. - ../../src/wp-includes/blocks # Third-party libraries. diff --git a/tests/phpstan/baseline.php b/tests/phpstan/baseline.php index 646cbdbef630c..810d719f57b6a 100644 --- a/tests/phpstan/baseline.php +++ b/tests/phpstan/baseline.php @@ -1,3 +1,107 @@ '#^Variable \\$class in empty\\(\\) always exists and is always falsy\\.$#', + 'identifier' => 'empty.variable', + 'count' => 1, + 'path' => __DIR__ . '/../../src/wp-admin/includes/class-wp-posts-list-table.php', +]; +$ignoreErrors[] = [ + 'message' => '#^Variable \\$_POST in isset\\(\\) always exists and is not nullable\\.$#', + 'identifier' => 'isset.variable', + 'count' => 1, + 'path' => __DIR__ . '/../../src/wp-admin/includes/media.php', +]; +$ignoreErrors[] = [ + 'message' => '#^Variable \\$parent_file in empty\\(\\) always exists and is not falsy\\.$#', + 'identifier' => 'empty.variable', + 'count' => 1, + 'path' => __DIR__ . '/../../src/wp-admin/themes.php', +]; +$ignoreErrors[] = [ + 'message' => '#^Function twentyseventeen_edit_link invoked with 1 parameter, 0 required\\.$#', + 'identifier' => 'arguments.count', + 'count' => 1, + 'path' => __DIR__ . '/../../src/wp-content/themes/twentyseventeen/template-parts/page/content-front-page-panels.php', +]; +$ignoreErrors[] = [ + 'message' => '#^Function twentyseventeen_edit_link invoked with 1 parameter, 0 required\\.$#', + 'identifier' => 'arguments.count', + 'count' => 1, + 'path' => __DIR__ . '/../../src/wp-content/themes/twentyseventeen/template-parts/page/content-front-page.php', +]; +$ignoreErrors[] = [ + 'message' => '#^Function twentyseventeen_edit_link invoked with 1 parameter, 0 required\\.$#', + 'identifier' => 'arguments.count', + 'count' => 1, + 'path' => __DIR__ . '/../../src/wp-content/themes/twentyseventeen/template-parts/page/content-page.php', +]; +$ignoreErrors[] = [ + 'message' => '#^Function wp_cache_switch_to_blog_fallback invoked with 1 parameter, 0 required\\.$#', + 'identifier' => 'arguments.count', + 'count' => 1, + 'path' => __DIR__ . '/../../src/wp-includes/cache-compat.php', +]; +$ignoreErrors[] = [ + 'message' => '#^Variable \\$addl_path in empty\\(\\) always exists and is always falsy\\.$#', + 'identifier' => 'empty.variable', + 'count' => 1, + 'path' => __DIR__ . '/../../src/wp-includes/canonical.php', +]; +$ignoreErrors[] = [ + 'message' => '#^Variable \\$namespace in isset\\(\\) always exists and is not nullable\\.$#', + 'identifier' => 'isset.variable', + 'count' => 1, + 'path' => __DIR__ . '/../../src/wp-includes/class-wp-block-parser.php', +]; +$ignoreErrors[] = [ + 'message' => '#^Variable \\$block_type in empty\\(\\) always exists and is not falsy\\.$#', + 'identifier' => 'empty.variable', + 'count' => 1, + 'path' => __DIR__ . '/../../src/wp-includes/class-wp-block-supports.php', +]; +$ignoreErrors[] = [ + 'message' => '#^Variable \\$loader in isset\\(\\) always exists and is not nullable\\.$#', + 'identifier' => 'isset.variable', + 'count' => 1, + 'path' => __DIR__ . '/../../src/wp-includes/class-wp-oembed.php', +]; +$ignoreErrors[] = [ + 'message' => '#^Variable \\$search in empty\\(\\) always exists and is not falsy\\.$#', + 'identifier' => 'empty.variable', + 'count' => 1, + 'path' => __DIR__ . '/../../src/wp-includes/class-wp-query.php', +]; +$ignoreErrors[] = [ + 'message' => '#^Variable \\$status_type_clauses in empty\\(\\) always exists and is not falsy\\.$#', + 'identifier' => 'empty.variable', + 'count' => 1, + 'path' => __DIR__ . '/../../src/wp-includes/class-wp-query.php', +]; +$ignoreErrors[] = [ + 'message' => '#^Variable \\$deprecated in empty\\(\\) always exists and is always falsy\\.$#', + 'identifier' => 'empty.variable', + 'count' => 1, + 'path' => __DIR__ . '/../../src/wp-includes/pluggable.php', +]; +$ignoreErrors[] = [ + 'message' => '#^Variable \\$schema in empty\\(\\) is never defined\\.$#', + 'identifier' => 'empty.variable', + 'count' => 1, + 'path' => __DIR__ . '/../../src/wp-includes/rest-api/endpoints/class-wp-rest-attachments-controller.php', +]; +$ignoreErrors[] = [ + 'message' => '#^Variable \\$the_parent in empty\\(\\) always exists and is not falsy\\.$#', + 'identifier' => 'empty.variable', + 'count' => 1, + 'path' => __DIR__ . '/../../src/wp-includes/taxonomy.php', +]; +$ignoreErrors[] = [ + 'message' => '#^Variable \\$s in isset\\(\\) is never defined\\.$#', + 'identifier' => 'isset.variable', + 'count' => 1, + 'path' => __DIR__ . '/../../src/wp-includes/template.php', +]; + +return ['parameters' => ['ignoreErrors' => $ignoreErrors]]; diff --git a/tests/phpstan/bootstrap.php b/tests/phpstan/bootstrap.php index c87a26babf83d..77a597609270e 100644 --- a/tests/phpstan/bootstrap.php +++ b/tests/phpstan/bootstrap.php @@ -93,3 +93,12 @@ define( 'FS_TIMEOUT', 1 ); define( 'FS_CHMOD_DIR', 1 ); define( 'FS_CHMOD_FILE', 1 ); + +// Theme constants referenced in add_theme_support(). +define( 'NO_HEADER_TEXT', false ); +define( 'HEADER_IMAGE_WIDTH', 0 ); +define( 'HEADER_IMAGE_HEIGHT', 0 ); +define( 'HEADER_TEXTCOLOR', '' ); +define( 'HEADER_IMAGE', '' ); +define( 'BACKGROUND_COLOR', '' ); +define( 'BACKGROUND_IMAGE', '' );