Repository navigation
Code Quality: Fix the return.unusedType PHPStan errors and remove the baseline - #15387
mukeshpanchal27 wants to merge 37 commits into
Conversation
…urn type. The function returns `true` or `false`. When the user is not logged in, it calls `die()` and does not return. Removing `null` from the `@return` tag removes the `return.unusedType` entry from the PHPStan baseline. There is no runtime change. See #65817. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Test using WordPress PlaygroundThe changes in this pull request can previewed and tested using a WordPress Playground instance. WordPress Playground is an experimental project that creates a full WordPress instance entirely within the browser. Some things to be aware of
For more details about these limitations and more, check out the Limitations page in the WordPress Playground documentation. |
|
The following accounts have interacted with this PR and/or linked issues. I will continue to update these lists as activity occurs. Core Committers: Use this line as a base for the props when committing in SVN: To understand the WordPress project's expectations around crediting contributors, please review the Contributor Attribution page in the Core Handbook. Props Bot commandsYou can trigger Props Bot actions by commenting on this PR:
|
There was a problem hiding this comment.
🟢 Approval recommended
The documentation and PHPStan baseline now consistently describe the function’s boolean-only return behavior, with no runtime changes or active review issues indicated.
No open issues 🎉
What changed in this PR
Updates validate_another_blog_signup() documentation and its PHPStan baseline to reflect that the function returns only a boolean when it returns. There is no runtime behavior change.
Changes:
- Removes
nullfrom the function’s documented return type. - Removes the obsolete PHPStan
return.unusedTypebaseline entry.
| File | Description |
|---|---|
tests/phpstan/baselines/return.unusedType.neon |
Removes the obsolete PHPStan baseline entry. |
src/wp-signup.php |
Updates the return documentation to bool. |
Review effort: Lite
westonruter
left a comment
There was a problem hiding this comment.
Can you fix the other return.unusedType errors as well so the baseline file can be removed?
`plugins_api()` documents that it returns an array for the `hot_tags` action, and the docblock says the `plugins_api_result` filter can change the response object or array. The filter's `@param` tag listed only `object|WP_Error`, so PHPStan concluded that the function never returns an array. This change adds `array` to the filter's `@param` tag and removes the matching `return.unusedType` baseline entry. There is no runtime change. See #65817. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… type. The function calls `wp_update_post()` without the `$wp_error` argument, so an update failure returns `0` and never a `WP_Error`. This change removes `WP_Error` from the `@return` tag and removes the matching `return.unusedType` baseline entry. There is no runtime change. See #65817. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…return type. The function returns the first update object from `get_core_updates()`, a placeholder object when there are no updates, or `false`. It never returns an array. This change removes `array` from the `@return` tag and removes the matching `return.unusedType` baseline entry. `WP_Automatic_Updater` reads properties from the result of this function. Before this change, PHPStan reported three `property.nonObject` errors there because the result could be an array. This change also removes those three baseline entries. There is no runtime change. See #65817. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
`get_the_tag_list()` passes the result of `get_the_term_list()` to the `the_tags` filter. That result is a string, `false` when there are no terms, or a `WP_Error` on failure. The filter's `@param` tag listed only `string`, so PHPStan concluded that the function never returns `false` or `WP_Error`. This change documents all three types on the filter and removes the two matching `return.unusedType` baseline entries. There is no runtime change. See #65817. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
`get_category()` passes the result of `get_term()` to `_make_cat_compat()` by reference. That result is `null` when the category does not exist, and `_make_cat_compat()` leaves `null` unchanged. The parameter type did not include `null`, so PHPStan assumed that the variable could not be `null` after the call. It then reported that `get_category()` never returns `null`. This change adds `null` to the parameter type and removes the matching `return.unusedType` baseline entry. There is no runtime change. See #65817. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
`WP_Recovery_Mode_Cookie_Service::recovery_mode_hash()` returns the result of `hash_hmac()` with the `sha1` algorithm. `hash_hmac()` returns `false` only for an unknown algorithm, and `sha1` is always available. This change removes `false` from the `@return` tag and removes the matching `return.unusedType` baseline entry. There is no runtime change. See #65817. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The `wp_code_editor_settings` filter description says that a falsey value disables the code editor, and `wp_enqueue_code_editor()` checks for it. The filter's `@param` tag listed only `array`, so PHPStan concluded that `wp_get_code_editor_settings()` never returns `false`. This change adds `false` to the filter's `@param` tag and removes the matching `return.unusedType` baseline entry. There is no runtime change. See #65817. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
`get_post_gallery()` returns the first item of `get_post_galleries()`. That item is an HTML string when `$html` is true, and an array otherwise. When the post has no gallery, `reset()` returns `false`. The `get_post_gallery` filter's `@param` tag listed only `array`, so PHPStan concluded that the function never returns a string. This change documents `string|array|false` on the filter and on the function, and removes the matching `return.unusedType` baseline entry. There is no runtime change. See #65817. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
`wp_mime_type_icon()` first reads the icon from the object cache, and `wp_cache_get()` returns `false` on a miss. If no icon file matches the MIME type, `$icon` stays `false` and the function passes it to the `wp_mime_type_icon` filter. The filter's `@param` tag listed only `string`, so PHPStan concluded that the function never returns `false`. This change adds `false` to the filter's `@param` tag and removes the matching `return.unusedType` baseline entry. There is no runtime change. See #65817. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
`_set_preview()` returns the post object that it receives, with the autosave content applied when one exists. It has no path that returns `false`. This change removes `false` from the `@return` tag and removes the matching `return.unusedType` baseline entry. There is no runtime change. See #65817. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
`get_term_to_edit()` returns the `WP_Error` from `get_term()`, an empty string when the term does not exist, or the term object from `sanitize_term()`. It never returns an integer or `null`, and the `@return` tag did not list the term object. This change documents `WP_Term|string|WP_Error` and removes the two matching `return.unusedType` baseline entries. There is no runtime change. See #65817. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
`retrieve_password()` checks whether `wp_is_password_reset_allowed_for_user()` returns a `WP_Error` and passes it on, so a filter callback can return a `WP_Error` to explain why a reset is not allowed. The filter's `@param` tag listed only `bool`, so PHPStan concluded that the function never returns a `WP_Error`. This change adds `WP_Error` to the filter's `@param` tag and removes the matching `return.unusedType` baseline entry. There is no runtime change. See #65817. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The earlier commits fixed every other entry in this baseline. The last entry reports that `wp_imagecreatetruecolor()` never returns `GdImage`. That report is a false positive. `imagecreatetruecolor()` returns a resource on PHP 7.4 and a `GdImage` instance on PHP 8.0+. PHPStan uses its pre-8.0 function map because `phpVersion.min` is 70400, so it sees only the resource. This change moves that entry to the permanent ignore list in `phpstan.neon.dist` with an explanation, deletes the baseline file, and removes its `includes` line. See #65817. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…//github.com/mukeshpanchal27/wordpress-develop into fix/validate-another-blog-signup-return-type
null from validate_another_blog_signup() return typereturn.unusedType PHPStan errors and remove the baseline
The continuation lines in the `get_term_to_edit()` `@return` tag and the `allow_password_reset` filter `@param` tag started one column too early. This change aligns them with the description text above. See #65817. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
@westonruter Done. This PR now fixes every Many of the errors came from filter docs, not from the functions. The PHPStan extension takes the return type of The One entry needs your opinion. PHPStan reports that The PR description lists every change. |
Mirror sanitize_post() so that sanitize_term() returns the same type it was given: a WP_Term stays a WP_Term, an array stays an array, and any other object stays an object. Previously the return was array|object regardless of input, so get_term_to_edit() was reported as returning array|object instead of its documented WP_Term|string|WP_Error. Also narrow get_term_to_edit() with `@phpstan-return WP_Term|''|WP_Error`, since an empty string is the only string it returns, and note that a WP_Error is also returned when the term ID is empty. This removes 16 PHPStan errors across taxonomy.php, class-wp-term.php, and class-wp-terms-list-table.php without adding any. Co-Authored-By: Claude Opus 5.5 (medium effort) <noreply@anthropic.com> Claude-Code-Session-Id: 9a95e289-8165-4c03-a202-98d54206ca8c
Add `@phpstan-param object|array<string, mixed> $term` and return `array<string, mixed>` for the array case, since the function reads and writes term fields by name. This documents what sanitize_term() actually requires. Callers that pass loosely typed arrays (sanitize_category(), wp_insert_term(), and wp_update_term()) are now flagged with argument.type errors; their own array types should be narrowed to match in a follow-up. Co-Authored-By: Claude Opus 5.5 (medium effort) <noreply@anthropic.com> Claude-Code-Session-Id: 9a95e289-8165-4c03-a202-98d54206ca8c
The function casts the integer fields (term_id, parent, count, term_group, term_taxonomy_id, and object_id) to int before anything else, and WP_Term holds those fields as ints, so `$value` is `string|int` rather than just `string`. Widen the `@param` and the `T` template bound to match. Co-Authored-By: Claude Opus 5.5 (medium effort) <noreply@anthropic.com> Claude-Code-Session-Id: 9a95e289-8165-4c03-a202-98d54206ca8c
| * @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. |
There was a problem hiding this comment.
Good. This matches the return value for wp_get_code_editor_settings():
@return array|false Settings for the code editor.
When wp_mime_type_icon() was given an attachment ID (or 0) and no icon matched, `$icon` was never assigned, so the filter received null along with an "Undefined variable $icon" warning. For a MIME type string, the value came straight from wp_cache_get(), which is untyped. Initialize `$icon` to false, and only use the cached value when it is a string, so the filter and the return value are always string|false. Also correct the hook docs: `$icon` is a URL, not a path, and `$mime` is 0 when the attachment does not exist. Add a test covering both the attachment ID and MIME type paths when no icon matches. Co-Authored-By: Claude Opus 5.5 (medium effort) <noreply@anthropic.com> Claude-Code-Session-Id: 9a95e289-8165-4c03-a202-98d54206ca8c
The function returns an array keyed by wildcard MIME type, each holding the list of real MIME types it matched. Declaring it as plain `array` left callers iterating over `mixed`, so wp_mime_type_icon() and media_upload_library_form() reported foreach and array key type errors. Co-Authored-By: Claude Opus 5.5 (medium effort) <noreply@anthropic.com> Claude-Code-Session-Id: 9a95e289-8165-4c03-a202-98d54206ca8c
The `icon_files` list can come from wp_cache_get(), so its values are untyped, and `$icon` reached the wp_mime_type_icon filter as `mixed`. Skip any matched entry that is not a string, so the filter and the return value are string|false on every path. Read the entry once through a local variable rather than checking and then reading `$types[ $wild ]` again. Co-Authored-By: Claude Opus 5.5 (medium effort) <noreply@anthropic.com> Claude-Code-Session-Id: 9a95e289-8165-4c03-a202-98d54206ca8c
_set_preview() is the core callback for the the_preview filter, which WP_Query applies to `$this->posts[0]` after the posts have already been converted with get_post(), so it always receives a WP_Post. With `@param WP_Post`, the guard's body was unreachable (PHPStan typed `$post` there as never) and contradicted the narrowed `@return WP_Post`. A survey of plugins in the WordPress.org directory found no the_preview callback that returns a non-object, and the plugins that call _set_preview() directly only pass it post objects. Co-Authored-By: Claude Opus 5.5 (medium effort) <noreply@anthropic.com> Claude-Code-Session-Id: 9a95e289-8165-4c03-a202-98d54206ca8c
get_post( 0 ) falls back to the global `$post`, so if an earlier test left it set, the "nonexistent attachment ID" case would resolve a real post and never reach the branch where `$mime` becomes 0. Pass PHP_INT_MAX instead, which can never match an attachment. Co-Authored-By: Claude Opus 5.5 (medium effort) <noreply@anthropic.com> Claude-Code-Session-Id: 9a95e289-8165-4c03-a202-98d54206ca8c
The returned array is keyed by the wildcard MIME types, and PHP casts all-digit string keys to integers, so a wildcard such as an icon named `404.png` produces an int key. Use `array-key` rather than `string` for the key type. The values remain lists of matched MIME type strings. Co-Authored-By: Claude Opus 5.5 (medium effort) <noreply@anthropic.com> Claude-Code-Session-Id: 9a95e289-8165-4c03-a202-98d54206ca8c
This comment has been minimized.
This comment has been minimized.
The wp_mime_type_icon filter docs already say `$mime` is 0 when an attachment ID is passed for a nonexistent attachment. `$post_id` is also 0 in that case, not only when a MIME type is passed, so say so. Co-Authored-By: Claude Opus 5.5 (medium effort) <noreply@anthropic.com> Claude-Code-Session-Id: 9a95e289-8165-4c03-a202-98d54206ca8c
`array<string, mixed>|object` is a plain generic rather than an array shape, so it belongs in the published `@param` tag instead of a separate `@phpstan-param` that duplicated it. PHPStan results are unchanged. Co-Authored-By: Claude Opus 5.5 (medium effort) <noreply@anthropic.com> Claude-Code-Session-Id: 9a95e289-8165-4c03-a202-98d54206ca8c
get_post_gallery() returns gallery HTML when `$html` is true and an array of gallery data when it is false, but its return type was the union of both. Add a conditional `@phpstan-return` so callers that pass `$html = false` (such as get_post_gallery_images()) get an array, and callers using the default get a string, which clears the echo type errors in the Twenty Thirteen and Twenty Seventeen gallery templates. Type the get_post_gallery filter's array as `array<string, mixed>` to match. Co-Authored-By: Claude Opus 5.5 (medium effort) <noreply@anthropic.com> Claude-Code-Session-Id: 9a95e289-8165-4c03-a202-98d54206ca8c
In data mode, each gallery is built from shortcode_parse_atts(), which puts positional shortcode attributes under integer keys, so `[gallery foo ids="1,2"]` yields `0 => 'foo'` alongside the named attributes. Type the gallery array as `array<mixed>` instead of `array<string, mixed>`, in both the conditional return type and the get_post_gallery filter. Co-Authored-By: Claude Opus 5.5 (medium effort) <noreply@anthropic.com> Claude-Code-Session-Id: 9a95e289-8165-4c03-a202-98d54206ca8c
Cover the `is_string()` check on the `mime_type_icon_{$mime}` cache
read: when the cache holds true, an array, or an int, the icon must be
looked up again rather than returned as-is. Reverting to the unchecked
cache read makes all three cases fail.
Also add the `@ticket` annotation to the existing no-matching-icon test.
Co-Authored-By: Claude Opus 5.5 (medium effort) <noreply@anthropic.com>
Claude-Code-Session-Id: 9a95e289-8165-4c03-a202-98d54206ca8c
The `$taxonomy` and `$context` lines, and the continuation lines below them, were one column short of the `$term` line after its type was widened to `array<string, mixed>|object`. Co-Authored-By: Claude Opus 5.5 (medium effort) <noreply@anthropic.com> Claude-Code-Session-Id: 9a95e289-8165-4c03-a202-98d54206ca8c
wp_mime_type_icon() resolves a numeric `$mime` with get_post(), so 0 (the default) falls back to the global post. `$mime` and `$post_id` are therefore 0 when no post is found for the passed ID, not specifically when an attachment ID is nonexistent. Co-Authored-By: Claude Opus 5.5 (medium effort) <noreply@anthropic.com> Claude-Code-Session-Id: 9a95e289-8165-4c03-a202-98d54206ca8c
A single-parameter array generic already has `array-key` keys, so `array<array-key, string[]>` is the same type written longer. This matches `array<mixed>` used for get_post_gallery(). Co-Authored-By: Claude Opus 5.5 (medium effort) <noreply@anthropic.com> Claude-Code-Session-Id: 9a95e289-8165-4c03-a202-98d54206ca8c
Every `return.unusedType` error is fixed and its baseline removed. Most came from a `@return` tag that listed a type the function never returns. Others came from a filter `@param` tag that listed too few types: PHPStan derives the result of `apply_filters()` from the hook's first `@param`, so where the function's documented return was already right, the hook docs were corrected instead of loosening the function's type. Correcting these types uncovered a real bug in `wp_mime_type_icon()`: when an attachment ID matched no icon, the `wp_mime_type_icon` filter received an undefined `$icon`, so `null` along with a warning. It now always receives `string|false`, and values read from the object cache are only used when they are strings. The `is_object()` guard in `_set_preview()` is removed, since `WP_Query` only applies the `the_preview` filter to a post already passed through `get_post()`, and no plugin in the directory was found to return anything else from it. Conditional return types are also added to `get_post_gallery()` and `sanitize_term()`, so callers get the type matching the arguments they pass. The `wp_imagecreatetruecolor()` error moves to the permanent ignore list, because PHPStan analyzes against PHP 7.4, where `imagecreatetruecolor()` returns a resource rather than a `GdImage`. Developed in #15387. Follow-up to r63023, r63941. Props mukesh27, westonruter. See #65817. git-svn-id: https://develop.svn.wordpress.org/trunk@65410 602fd350-edb4-49c9-b593-d223f7449a82
Every `return.unusedType` error is fixed and its baseline removed. Most came from a `@return` tag that listed a type the function never returns. Others came from a filter `@param` tag that listed too few types: PHPStan derives the result of `apply_filters()` from the hook's first `@param`, so where the function's documented return was already right, the hook docs were corrected instead of loosening the function's type. Correcting these types uncovered a real bug in `wp_mime_type_icon()`: when an attachment ID matched no icon, the `wp_mime_type_icon` filter received an undefined `$icon`, so `null` along with a warning. It now always receives `string|false`, and values read from the object cache are only used when they are strings. The `is_object()` guard in `_set_preview()` is removed, since `WP_Query` only applies the `the_preview` filter to a post already passed through `get_post()`, and no plugin in the directory was found to return anything else from it. Conditional return types are also added to `get_post_gallery()` and `sanitize_term()`, so callers get the type matching the arguments they pass. The `wp_imagecreatetruecolor()` error moves to the permanent ignore list, because PHPStan analyzes against PHP 7.4, where `imagecreatetruecolor()` returns a resource rather than a `GdImage`. Developed in WordPress/wordpress-develop#15387. Follow-up to r63023, r63941. Props mukesh27, westonruter. See #65817. Built from https://develop.svn.wordpress.org/trunk@65410 git-svn-id: http://core.svn.wordpress.org/trunk@64549 1a063a9b-81f0-0310-95a4-ce76da25c4cd
✅ Committed in r65410 (dd5ce8e).
This PR fixes every
return.unusedTypeerror that PHPStan reports, and deletestests/phpstan/baselines/return.unusedType.neon. While fixing those errors, it also tightens related types that were wrong or too loose, and fixes a bug inwp_mime_type_icon()that the fixes uncovered.PHPStan reads the return type of
apply_filters()from the@paramtag of the filter. Several errors came from a filter@paramtag that listed too few types. In those cases the function's@returntag was correct, so this PR fixes the filter docs instead.Runtime changes
wp_mime_type_icon(): when an attachment ID (or0) was passed and no icon matched,$iconwas never assigned, so thewp_mime_type_iconfilter receivednullalong with an "Undefined variable $icon" warning.$iconnow starts asfalse, so the filter and the return value arestring|falseon every path. Cached values (both themime_type_icon_{$mime}entry and theicon_fileslist) are only used when they are strings._set_preview(): theis_object()guard is removed. This function is core'sthe_previewcallback, andWP_Queryonly applies that filter to a post already converted withget_post(), so the guard was unreachable. A survey of the plugin directory found nothe_previewcallback that returns a non-object, and no direct caller that passes one.Wrong type removed from
@returnvalidate_another_blog_signup()nulltrueorfalse, or callsdie()._fix_attachment_links()WP_Errorwp_update_post()without$wp_error, so a failure returns0.get_preferred_from_update_core()arrayfalse.WP_Recovery_Mode_Cookie_Service::recovery_mode_hash()falsehash_hmac()withsha1cannot fail._set_preview()falseget_term_to_edit()WP_Term|string|WP_Error, with@phpstan-return WP_Term|''|WP_Errorintornull, the old tag did not list the term object, and the empty string is the only string it returns.The
get_preferred_from_update_core()change also clears threeproperty.nonObjecterrors inWP_Automatic_Updater. This PR removes those entries from theproperty.nonObjectbaseline.Filter
@paramtag correctedplugins_api_resultarrayplugins_api()documents an array forhot_tags.the_tagsstring|false|WP_Errorget_the_term_list().wp_code_editor_settingsfalseget_post_gallerystring|array<mixed>|falsereset()returnsfalsewhen the post has no gallery.wp_mime_type_icon$iconisstring|false,$mimeisstring|int$iconisfalsewhen no icon matches, and is a URL rather than a path.$mimeand$post_idare0when no post is found for the passed ID.allow_password_resetWP_Errorretrieve_password()already handles aWP_Errorresult.Types tightened
get_post_gallery(): conditional@phpstan-returnso that$html = falsegives the gallery data array and the default gives an HTML string. This clearsechotype errors in the Twenty Thirteen and Twenty Seventeen gallery templates.sanitize_term():$termisarray<string, mixed>|object, and a conditional@phpstan-returnreturns the same kind of value it was given (WP_Term, array, or object). This clears theget_term_to_edit()return type error and several offset-access errors on its result.sanitize_term_field():$valueisstring|int, since the integer fields are cast toint.wp_match_mime_types(): returnsarray<array-key, string[]>rather than a barearray, which removesmixedforeach and offset errors inwp_mime_type_icon()andmedia_upload_library_form().Other changes
_make_cat_compat()now acceptsnull.get_category()passes it the result ofget_term()by reference, and PHPStan assumed that result could not benullafter the call.wp_imagecreatetruecolor()keepsGdImagein its return type. PHPStan analyses against PHP 7.4, whereimagecreatetruecolor()returns a resource. On PHP 8 it returnsGdImage. This PR moves the entry to the permanent ignore list inphpstan.neon.distand explains why there, the same way thesubstr_compare()entry does.Testing
composer phpstanreports no errors.Tests_Post_Attachmentscoverwp_mime_type_icon()when no icon matches (for an attachment ID and for a MIME type) and when the icon cache holds a non-string value. Both fail on the previous code. Run them withnpm run test:php -- --filter test_wp_mime_type_icon.Trac ticket: https://core.trac.wordpress.org/ticket/65817
Use of AI Tools
AI assistance: Yes
Tool(s): Claude Code
Model(s): Claude Opus 5.5
Used for: Finding the fixes, editing the docblocks and baselines, writing the tests, surveying plugin usage of
the_preview, and drafting the PR. I reviewed the changes.This Pull Request is for code review only. Please keep all other discussion in the Trac ticket. Do not merge this Pull Request. See GitHub Pull Requests for Code Review in the Core Handbook for more details.