diff --git a/phpstan.neon.dist b/phpstan.neon.dist index 655bb9bbc807c..29ed8929eba7e 100644 --- a/phpstan.neon.dist +++ b/phpstan.neon.dist @@ -53,7 +53,6 @@ includes: - tests/phpstan/baselines/property.notFound.neon - tests/phpstan/baselines/property.private.neon - tests/phpstan/baselines/return.type.neon - - tests/phpstan/baselines/return.unusedType.neon - tests/phpstan/baselines/varTag.noVariable.neon - tests/phpstan/baselines/variable.undefined.neon # phpstan:baselines end @@ -116,6 +115,18 @@ parameters: path: src/wp-includes/compat.php reportUnmatched: false + # Level 4: + # wp_imagecreatetruecolor() returns whatever imagecreatetruecolor() returns: a resource on PHP 7.4 and a + # GdImage instance on PHP 8.0+. Its docblock lists both, which is correct for WP's 7.4+ range. Because + # `phpVersion.min` is 70400, PHPStan reads the function from its pre-8.0 map, sees only a resource, and + # reports GdImage as unused. Removing GdImage would make the docblock wrong on every PHP 8 install. + # `reportUnmatched: false` so this entry lapses quietly if PHPStan stops reporting it. + - + message: '#^Function wp_imagecreatetruecolor\(\) never returns GdImage so it can be removed from the return type\.$#' + identifier: return.unusedType + path: src/wp-includes/media.php + reportUnmatched: false + # Level 5: # substr_compare()'s $length has always accepted null, meaning "compare the full length". PHP 7.4 spelled # that `int $length = null`, where the null default makes the parameter implicitly nullable, and PHP 8.0 diff --git a/src/wp-admin/includes/plugin-install.php b/src/wp-admin/includes/plugin-install.php index ffae71c5b81f6..496b7ffd36679 100644 --- a/src/wp-admin/includes/plugin-install.php +++ b/src/wp-admin/includes/plugin-install.php @@ -223,9 +223,9 @@ function plugins_api( $action, $args = array() ) { * * @since 2.7.0 * - * @param object|WP_Error $res Response object or WP_Error. - * @param string $action The type of information being requested from the Plugin Installation API. - * @param object $args Plugin API arguments. + * @param object|array|WP_Error $res Response object or array, or WP_Error on failure. + * @param string $action The type of information being requested from the Plugin Installation API. + * @param object $args Plugin API arguments. */ return apply_filters( 'plugins_api_result', $res, $action, $args ); } diff --git a/src/wp-admin/includes/post.php b/src/wp-admin/includes/post.php index a255673aad601..64b5793d2cffc 100644 --- a/src/wp-admin/includes/post.php +++ b/src/wp-admin/includes/post.php @@ -1163,7 +1163,7 @@ function update_meta( $meta_id, $meta_key, $meta_value ) { * @access private * * @param int|WP_Post $post Post ID or post object. - * @return void|int|WP_Error Void if nothing fixed. 0 or WP_Error on update failure. The post ID on update success. + * @return void|int Void if nothing fixed. 0 on update failure. The post ID on update success. */ function _fix_attachment_links( $post ) { $post = get_post( $post, ARRAY_A ); diff --git a/src/wp-admin/includes/update.php b/src/wp-admin/includes/update.php index 22f44a33dbb54..e7b02a2a62c8a 100644 --- a/src/wp-admin/includes/update.php +++ b/src/wp-admin/includes/update.php @@ -11,7 +11,7 @@ * * @since 2.7.0 * - * @return object|array|false The response from the API on success, false on failure. + * @return object|false The response from the API on success, false on failure. */ function get_preferred_from_update_core() { $updates = get_core_updates(); diff --git a/src/wp-includes/category-template.php b/src/wp-includes/category-template.php index f48ebe6adb3d7..130f55e3fe043 100644 --- a/src/wp-includes/category-template.php +++ b/src/wp-includes/category-template.php @@ -1224,11 +1224,12 @@ function get_the_tag_list( $before = '', $sep = '', $after = '', $post_id = 0 ) * * @since 2.3.0 * - * @param string $tag_list List of tags. - * @param string $before String to use before the tags. - * @param string $sep String to use between the tags. - * @param string $after String to use after the tags. - * @param int $post_id Post ID. + * @param string|false|WP_Error $tag_list A list of tags on success, false if there are no terms, + * WP_Error on failure. + * @param string $before String to use before the tags. + * @param string $sep String to use between the tags. + * @param string $after String to use after the tags. + * @param int $post_id Post ID. */ return apply_filters( 'the_tags', $tag_list, $before, $sep, $after, $post_id ); } diff --git a/src/wp-includes/category.php b/src/wp-includes/category.php index e6085418e255d..e93c6c122eb75 100644 --- a/src/wp-includes/category.php +++ b/src/wp-includes/category.php @@ -428,7 +428,7 @@ function clean_category_cache( $id ) { * @since 4.4.0 The `$category` parameter now also accepts a WP_Term object. * @access private * - * @param array|object|WP_Term $category Category row object or array. + * @param array|object|WP_Term|null $category Category row object or array. Null is left unchanged. */ function _make_cat_compat( &$category ) { if ( is_object( $category ) && ! is_wp_error( $category ) ) { diff --git a/src/wp-includes/class-wp-recovery-mode-cookie-service.php b/src/wp-includes/class-wp-recovery-mode-cookie-service.php index a2ee34a723aa8..feefc942b6d52 100644 --- a/src/wp-includes/class-wp-recovery-mode-cookie-service.php +++ b/src/wp-includes/class-wp-recovery-mode-cookie-service.php @@ -195,7 +195,7 @@ private function generate_cookie() { * @since 5.2.0 * * @param string $data Data to hash. - * @return string|false The hashed $data, or false on failure. + * @return string The hashed $data. */ private function recovery_mode_hash( $data ) { $default_keys = array_unique( diff --git a/src/wp-includes/general-template.php b/src/wp-includes/general-template.php index eb6e185f5b49d..271881cc00df8 100644 --- a/src/wp-includes/general-template.php +++ b/src/wp-includes/general-template.php @@ -4760,9 +4760,9 @@ function wp_get_code_editor_settings( $args ) { * * @since 4.9.0 * - * @param array $settings The array of settings passed to the code editor. - * A falsey value disables the editor. - * @param array $args { + * @param array|false $settings The array of settings passed to the code editor. + * A falsey value disables the editor. + * @param array $args { * Args passed when calling `get_code_editor_settings()`. * * @type string $type The MIME type of the file to be edited. diff --git a/src/wp-includes/media.php b/src/wp-includes/media.php index 4cd69ade6cbb7..f12b2616d97dc 100644 --- a/src/wp-includes/media.php +++ b/src/wp-includes/media.php @@ -5587,7 +5587,9 @@ function get_post_galleries( $post, $html = true ) { * * @param int|WP_Post $post Optional. Post ID or WP_Post object. Default is global $post. * @param bool $html Optional. Whether to return HTML or data. Default is true. - * @return string|array Gallery data and srcs parsed from the expanded shortcode. + * @return string|array|false Gallery HTML or an array of gallery data and srcs parsed from + * the expanded shortcode, depending on `$html`. False if the post has + * no gallery. */ function get_post_gallery( $post = 0, $html = true ) { $galleries = get_post_galleries( $post, $html ); @@ -5598,9 +5600,10 @@ function get_post_gallery( $post = 0, $html = true ) { * * @since 3.6.0 * - * @param array $gallery The first-found post gallery. - * @param int|WP_Post $post Post ID or object. - * @param array $galleries Associative array of all found post galleries. + * @param string|array|false $gallery The first-found post gallery, or false if the post has no gallery. + * An HTML string when `$html` is true, otherwise an array. + * @param int|WP_Post $post Post ID or object. + * @param array $galleries Associative array of all found post galleries. */ return apply_filters( 'get_post_gallery', $gallery, $post, $galleries ); } diff --git a/src/wp-includes/post.php b/src/wp-includes/post.php index 5806d879f1c5e..fee280a11a5d5 100644 --- a/src/wp-includes/post.php +++ b/src/wp-includes/post.php @@ -7773,10 +7773,10 @@ function wp_mime_type_icon( $mime = 0, $preferred_ext = '.png' ) { * * @since 2.1.0 * - * @param string $icon Path to the mime type icon. - * @param string $mime Mime type. - * @param int $post_id Attachment ID. Will equal 0 if the function passed - * the mime type. + * @param string|false $icon Path to the mime type icon, or false if no icon was found. + * @param string $mime Mime type. + * @param int $post_id Attachment ID. Will equal 0 if the function passed + * the mime type. */ return apply_filters( 'wp_mime_type_icon', $icon, $mime, $post_id ); } diff --git a/src/wp-includes/revision.php b/src/wp-includes/revision.php index 179a32c2832c5..29bf2b07dd417 100644 --- a/src/wp-includes/revision.php +++ b/src/wp-includes/revision.php @@ -868,7 +868,7 @@ function wp_revisions_to_keep( $post ) { * @access private * * @param WP_Post $post - * @return WP_Post|false + * @return WP_Post */ function _set_preview( $post ) { if ( ! is_object( $post ) ) { diff --git a/src/wp-includes/taxonomy.php b/src/wp-includes/taxonomy.php index 6656a2f8e364a..ea9d4b04d137d 100644 --- a/src/wp-includes/taxonomy.php +++ b/src/wp-includes/taxonomy.php @@ -1273,7 +1273,8 @@ function get_term_field( $field, $term, $taxonomy = '', $context = 'display' ) { * * @param int|object $id Term ID or object. * @param string $taxonomy Taxonomy name. - * @return string|int|null|WP_Error Will return empty string if $term is not an object. + * @return WP_Term|string|WP_Error The term sanitized for editing, WP_Error if the taxonomy does not exist, + * or an empty string if the term does not exist. */ function get_term_to_edit( $id, $taxonomy ) { $term = get_term( $id, $taxonomy ); diff --git a/src/wp-includes/user.php b/src/wp-includes/user.php index 02a412b291a8e..518278feb9ed5 100644 --- a/src/wp-includes/user.php +++ b/src/wp-includes/user.php @@ -5341,8 +5341,9 @@ function wp_is_password_reset_allowed_for_user( $user ) { * * @since 2.7.0 * - * @param bool $allow Whether to allow the password to be reset. Default true. - * @param int $user_id The ID of the user attempting to reset a password. + * @param bool|WP_Error $allow Whether to allow the password to be reset, or a WP_Error to explain + * why it is not allowed. Default true. + * @param int $user_id The ID of the user attempting to reset a password. */ return apply_filters( 'allow_password_reset', $allow, $user->ID ); } diff --git a/src/wp-signup.php b/src/wp-signup.php index 4eb8c60b21408..dd4e5d5365f74 100644 --- a/src/wp-signup.php +++ b/src/wp-signup.php @@ -443,8 +443,8 @@ function signup_another_blog( $blogname = '', $blog_title = '', $errors = '' ) { * @global string $domain The new site's domain. * @global string $path The new site's path. * - * @return null|bool True if site signup was validated, false on error. - * The function halts all execution if the user is not logged in. + * @return bool True if site signup was validated, false on error. + * The function halts all execution if the user is not logged in. */ function validate_another_blog_signup() { global $blogname, $blog_title, $errors, $domain, $path; diff --git a/tests/phpstan/baselines/property.nonObject.neon b/tests/phpstan/baselines/property.nonObject.neon index 895c9e3656d3d..d04aff6ba2e14 100644 --- a/tests/phpstan/baselines/property.nonObject.neon +++ b/tests/phpstan/baselines/property.nonObject.neon @@ -48,21 +48,6 @@ parameters: identifier: property.nonObject count: 1 path: ../../../src/wp-admin/includes/class-theme-upgrader.php - - - message: '#^Cannot access property \$current on array\|object\.$#' - identifier: property.nonObject - count: 3 - path: ../../../src/wp-admin/includes/class-wp-automatic-updater.php - - - message: '#^Cannot access property \$response on array\|object\.$#' - identifier: property.nonObject - count: 1 - path: ../../../src/wp-admin/includes/class-wp-automatic-updater.php - - - message: '#^Cannot access property \$version on array\|object\.$#' - identifier: property.nonObject - count: 1 - path: ../../../src/wp-admin/includes/class-wp-automatic-updater.php - message: '#^Cannot access property \$info on array\|object\.$#' identifier: property.nonObject diff --git a/tests/phpstan/baselines/return.unusedType.neon b/tests/phpstan/baselines/return.unusedType.neon deleted file mode 100644 index 2acebf529a781..0000000000000 --- a/tests/phpstan/baselines/return.unusedType.neon +++ /dev/null @@ -1,100 +0,0 @@ -# PHPStan baseline for the `return.unusedType` errors in WordPress core. -# -# https://phpstan.org/error-identifiers/return.unusedType -# -# Each entry is scoped to a single file and carries an exact occurrence count, -# so that a new instance is reported as a new error rather than being absorbed -# silently. Fixing an occurrence therefore means decrementing or removing its -# entry here as part of the same change. -# -# The goal is to empty this file and delete it, along with the `includes` entry -# for it in phpstan.neon.dist. -# -# Generated by `composer phpstan:baselines`. Do not edit by hand; regenerate with -# -# composer phpstan:baselines -- --identifier=return.unusedType -# -# which reruns the analysis with this file suppressed so the errors surface again. - -parameters: - ignoreErrors: - - - message: '#^Function plugins_api\(\) never returns array so it can be removed from the return type\.$#' - identifier: return.unusedType - count: 1 - path: ../../../src/wp-admin/includes/plugin-install.php - - - message: '#^Function _fix_attachment_links\(\) never returns WP_Error so it can be removed from the return type\.$#' - identifier: return.unusedType - count: 1 - path: ../../../src/wp-admin/includes/post.php - - - message: '#^Function get_preferred_from_update_core\(\) never returns array so it can be removed from the return type\.$#' - identifier: return.unusedType - count: 1 - path: ../../../src/wp-admin/includes/update.php - - - message: '#^Function get_the_tag_list\(\) never returns WP_Error so it can be removed from the return type\.$#' - identifier: return.unusedType - count: 1 - path: ../../../src/wp-includes/category-template.php - - - message: '#^Function get_the_tag_list\(\) never returns false so it can be removed from the return type\.$#' - identifier: return.unusedType - count: 1 - path: ../../../src/wp-includes/category-template.php - - - message: '#^Function get_category\(\) never returns null so it can be removed from the return type\.$#' - identifier: return.unusedType - count: 1 - path: ../../../src/wp-includes/category.php - - - message: '#^Method WP_Recovery_Mode_Cookie_Service\:\:recovery_mode_hash\(\) never returns false so it can be removed from the return type\.$#' - identifier: return.unusedType - count: 1 - path: ../../../src/wp-includes/class-wp-recovery-mode-cookie-service.php - - - message: '#^Function wp_get_code_editor_settings\(\) never returns false so it can be removed from the return type\.$#' - identifier: return.unusedType - count: 1 - path: ../../../src/wp-includes/general-template.php - - - message: '#^Function get_post_gallery\(\) never returns string so it can be removed from the return type\.$#' - identifier: return.unusedType - count: 1 - path: ../../../src/wp-includes/media.php - - - message: '#^Function wp_imagecreatetruecolor\(\) never returns GdImage so it can be removed from the return type\.$#' - identifier: return.unusedType - count: 1 - path: ../../../src/wp-includes/media.php - - - message: '#^Function wp_mime_type_icon\(\) never returns false so it can be removed from the return type\.$#' - identifier: return.unusedType - count: 1 - path: ../../../src/wp-includes/post.php - - - message: '#^Function _set_preview\(\) never returns false so it can be removed from the return type\.$#' - identifier: return.unusedType - count: 1 - path: ../../../src/wp-includes/revision.php - - - message: '#^Function get_term_to_edit\(\) never returns int so it can be removed from the return type\.$#' - identifier: return.unusedType - count: 1 - path: ../../../src/wp-includes/taxonomy.php - - - message: '#^Function get_term_to_edit\(\) never returns null so it can be removed from the return type\.$#' - identifier: return.unusedType - count: 1 - path: ../../../src/wp-includes/taxonomy.php - - - message: '#^Function wp_is_password_reset_allowed_for_user\(\) never returns WP_Error so it can be removed from the return type\.$#' - identifier: return.unusedType - count: 1 - path: ../../../src/wp-includes/user.php - - - message: '#^Function validate_another_blog_signup\(\) never returns null so it can be removed from the return type\.$#' - identifier: return.unusedType - count: 1 - path: ../../../src/wp-signup.php