Posts, Post Types: Improve static analysis types for post retrieval functions#12485
Posts, Post Types: Improve static analysis types for post retrieval functions#12485westonruter wants to merge 1 commit into
Conversation
…unctions. Narrow the conditional `@phpstan-return` types of `get_post()`, `get_page()`, `get_page_by_path()`, `get_children()`, `wp_get_recent_posts()`, and `wp_get_post_revision()` so that the `ARRAY_A` and `ARRAY_N` outputs are typed as `non-empty-array`, consistent with `WP_Post::to_array()`, which always returns at least the object's properties. Prior to this, `wp_get_post_revision()` had no conditional return type at all, so its return value was seen as `WP_Post|array|null` regardless of the requested `$output`. Describing it precisely resolves a number of pre-existing `Cannot access property $ID on array|WP_Post` errors in its callers, including `wp_restore_post_revision()`, `wp_delete_post_revision()`, `wp_xmlrpc_server::wp_restoreRevision()`, and `wp-admin/revision.php`. Additionally: * Guard against `get_post()` returning `null` in `trackback_url_list()`, which would otherwise emit "Trying to access array offset on value of type null" warnings when called with an invalid post ID. * Collect the array output of `wp_get_recent_posts()` in a separate `$posts` variable rather than overwriting the `WP_Post` objects in `$results` in place. Reassigning array values over the elements of `$results` left the variable holding a mix of `WP_Post` objects and arrays partway through the loop, so static analysis could only infer `array<WP_Post|array<string, mixed>>` for it. Building up a dedicated variable guarantees that everything it contains is an array, allowing the `ARRAY_A` branch of the return type to be expressed precisely. This does not change the returned value. Note that `non-empty-array` is a PHPStan-specific type which phpDocumentor does not understand, so the plain `@return` tag for `WP_Post::to_array()` continues to use `array<string, mixed>` and the narrower type is supplied via `@phpstan-return`. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
The following accounts have interacted with this PR and/or linked issues. I will continue to update these lists as activity occurs. You can also manually ask me to refresh this list by adding the 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. |
| return $results ? $results : array(); | ||
| return $posts; |
There was a problem hiding this comment.
No need for a ternary here, because if $results is falsy, then it was an empty string to begin with. So passing through an empty $posts is the same.
| if ( ! $postdata ) { | ||
| return; | ||
| } |
There was a problem hiding this comment.
This prevents a PHP error where the post_excerpt key could be attempted to be read from a null value on $postdata if the lookup failed.
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. |
Narrow the conditional `@phpstan-return` types of `get_post()`, `get_page()`, `get_page_by_path()`, `get_children()`, and `wp_get_recent_posts()` so that the `ARRAY_A` and `ARRAY_N` outputs are typed as `non-empty-array` instead of `array`. This is consistent with `WP_Post::to_array()`, which always returns at least the object's declared properties and so can never yield an empty array. Slight refactoring is done on `wp_get_recent_posts()` to support static analysis. Additionally, `wp_get_post_revision()` had no conditional return type at all, so its result was seen as `WP_Post|array|null` regardless of the requested `$output`. Describing it precisely resolves 30 pre-existing `Cannot access property $ID on array|WP_Post` errors in its callers. Furthermore, `trackback_url_list()` now bails when `get_post()` returns `null`. Previously it fell through to `$postdata['post_excerpt']`, emitting "Trying to access array offset on value of type null" warnings when called with an invalid post ID. Developed in #12485. Follow-up to r62648. See #64898. git-svn-id: https://develop.svn.wordpress.org/trunk@62694 602fd350-edb4-49c9-b593-d223f7449a82
Narrow the conditional `@phpstan-return` types of `get_post()`, `get_page()`, `get_page_by_path()`, `get_children()`, and `wp_get_recent_posts()` so that the `ARRAY_A` and `ARRAY_N` outputs are typed as `non-empty-array` instead of `array`. This is consistent with `WP_Post::to_array()`, which always returns at least the object's declared properties and so can never yield an empty array. Slight refactoring is done on `wp_get_recent_posts()` to support static analysis. Additionally, `wp_get_post_revision()` had no conditional return type at all, so its result was seen as `WP_Post|array|null` regardless of the requested `$output`. Describing it precisely resolves 30 pre-existing `Cannot access property $ID on array|WP_Post` errors in its callers. Furthermore, `trackback_url_list()` now bails when `get_post()` returns `null`. Previously it fell through to `$postdata['post_excerpt']`, emitting "Trying to access array offset on value of type null" warnings when called with an invalid post ID. Developed in WordPress/wordpress-develop#12485. Follow-up to r62648. See #64898. Built from https://develop.svn.wordpress.org/trunk@62694 git-svn-id: http://core.svn.wordpress.org/trunk@61978 1a063a9b-81f0-0310-95a4-ce76da25c4cd
✅ Committed in r62694 (99fc144)
This improves the static analysis types for the post retrieval functions, so that the type of the returned value can be determined from the requested
$output.Conditional return types
The
@phpstan-returntypes ofget_post(),get_page(),get_page_by_path(),get_children(), andwp_get_recent_posts()are narrowed so that theARRAY_AandARRAY_Noutputs are typed asnon-empty-array. This is consistent withWP_Post::to_array(), which always returns at least the object's declared properties and therefore can never return an empty array.wp_get_post_revision()previously had no conditional return type at all, so its return value was seen asWP_Post|array|nullregardless of the requested$output. Describing it precisely resolves 30 pre-existing PHPStan errors in its callers — mostlyCannot access property $ID on array|WP_Post— acrosswp_restore_post_revision(),wp_delete_post_revision(),wp_xmlrpc_server::wp_restoreRevision(), andwp-admin/revision.php.Note that
non-empty-arrayis a PHPStan-specific type which phpDocumentor does not understand, so the plain@returntag forWP_Post::to_array()continues to usearray<string, mixed>, with the narrower type supplied via@phpstan-return.Behavior changes
Two small runtime changes were needed to support the above:
trackback_url_list()now bails whenget_post()returnsnull. Previously, calling it with an invalid post ID would fall through to$postdata['post_excerpt'], emitting "Trying to access array offset on value of type null" warnings.wp_get_recent_posts()now collects itsARRAY_Aoutput in a separate$postsvariable rather than overwriting theWP_Postobjects in$resultsin place. Reassigning array values over the elements of$resultsleft the variable holding a mix ofWP_Postobjects and arrays partway through the loop, so static analysis could only ever inferarray<WP_Post|array<string, mixed>>for it. Building up a dedicated variable guarantees that everything it contains is an array. The returned value is unchanged.A note on
list<>It may be tempting to type these array returns as
list<…>rather thanarray<int, …>, but that would not be sound. Thethe_posts,posts_results, andposts_pre_queryfilters allow plugins to return arbitrary arrays — anarray_filter()in athe_postscallback is enough to produce a sparse numeric array — and core never re-indexes the result.array<int, …>is therefore the honest type. (get_children()is keyed by post ID in any case.)Testing instructions
No behavior change is expected beyond the removal of the PHP warnings noted above. The existing tests pass:
Static analysis was verified to introduce no new errors on the changed files (and to fix 30 existing ones).
Trac ticket: https://core.trac.wordpress.org/ticket/64898
Use of AI Tools
AI assistance: Yes
Tool(s): Claude Code
Model(s): Claude Opus 4.8
Used for: Reviewing the change for correctness and consistency, extending it to
wp_get_post_revision()andWP_Post::to_array(), verifying with PHPStan/PHPCS/PHPUnit, and drafting the commit message and this description. All changes were reviewed and edited by me.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.