Repository navigation
Docs: Add PHPStan array shapes - #13894
swissspidy wants to merge 4 commits into
Conversation
Adds array shapes and refined array types to functions that return or accept arrays with a known set of keys. The HTTP response is defined once, as the `HTTP_Response` type on `WP_Http`, and repeated on the `wp_remote_*()` and `wp_safe_remote_*()` functions. It includes the response of a non-blocking request, which has no `filename` and `false` for the code and message. Compared to the function map in php-stubs/wordpress-stubs, `WP_Widget::widget()` requires only the four keys `the_widget()` passes, `wp_widget_rss_form()` accepts the `'__i__'` placeholder as the widget number, the script tag attributes accept `false`, and `get_shortcode_tags_in_content()` returns `list<string>`. The map's `list<mixed>` for cron arguments, its shapes for `WP_List_Table::set_pagination_args()` and `Custom_Image_Header::set_header_image()`, and its conditional return for `get_block_wrapper_attributes()` are left out, since core does not match them. See #65817. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VieGtSQtUoVfHiGwTmkvtc
|
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 Unlinked AccountsThe following contributors have not linked their GitHub and WordPress.org accounts: @claude. Contributors, please read how to link your accounts to ensure your work is properly credited in WordPress releases. 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. |
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. |
There was a problem hiding this comment.
Copilot review overview
🟡 Changes recommended
Several new shapes exclude valid RSS widget inputs and short-circuited HTTP responses.
Review effort: Balanced
Findings: 3
Open (3)
What changed in this PR
Adds refined PHPStan array types and shapes across WordPress APIs without changing runtime behavior.
Changes:
- Defines reusable and public HTTP response shapes.
- Refines widget, robots, navigation, media, and block attribute arrays.
- Narrows several utility return and parameter types.
| File | Description |
|---|---|
src/wp-includes/widgets.php |
Types RSS widget data. |
src/wp-includes/shortcodes.php |
Types shortcode lists. |
src/wp-includes/script-loader.php |
Types script attributes. |
src/wp-includes/robots-template.php |
Types robots directives. |
src/wp-includes/nav-menu.php |
Types menu registrations. |
src/wp-includes/http.php |
Types remote responses. |
src/wp-includes/functions.php |
Refines unique-ID input. |
src/wp-includes/formatting.php |
Types HTML split results. |
src/wp-includes/feed.php |
Types Atom text tuples. |
src/wp-includes/class-wp-widget.php |
Shapes widget display arguments. |
src/wp-includes/class-wp-http.php |
Defines the HTTP response alias. |
src/wp-includes/class-wp-dependencies.php |
Refines dependency groups. |
src/wp-includes/class-wp-block-supports.php |
Types wrapper attributes. |
src/wp-admin/includes/post.php |
Types status lists. |
src/wp-admin/includes/nav-menu.php |
Shapes menu columns. |
src/wp-admin/includes/ms.php |
Shapes help-tab arguments. |
src/wp-admin/includes/media.php |
Shapes media helper results. |
src/wp-admin/includes/list-table.php |
Shapes list-table arguments. |
src/wp-admin/includes/bookmark.php |
Refines bookmark results. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
|
🤖 Comment by Claude Opus 5.5 Props for this subset, gathered from the full history of
Props for this PR (swissspidy for the split, westonruter for the review that shaped it): Generated by Claude Code |
Make http_response optional in the HTTP response shapes, since a pre_http_request filter can return a response without it. In wp_widget_rss_form(), make error optional and allow 'hidden' for the inputs, matching what the function handles. Add the documented plural, singular and ajax keys to the _get_list_table() shape, and drop two @phpstan-param tags that repeated the canonical ones. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015BuoHZQvJMvPEYp4Sfjgvd

Split out of #13530, as proposed in this comment (subset 7).
This adds array shapes and refined array types to functions that return or accept arrays with a known set of keys:
WP_Widget::widget()'s$args_get_list_table()'s$argswp_html_split()register_nav_menus()get_block_wrapper_attributes()'s$extra_attributesChanges from #13530
These follow the review analysis:
HTTP_Responsetype alias onWP_Http, and used byrequest(),get(),post()andhead(). The 8wp_remote_*()andwp_safe_remote_*()functions repeat it, because function docblocks cannot import a class type alias. The shape now covers non-blocking requests, which return empty headers,falsefor the code and message, nofilename, and anullhttp_response. It also matches the hash notationrequest()already has.WP_Widget::widget()$args. Only the four keys thatthe_widget()passes are required:before_widget,after_widget,before_titleandafter_title.wp_widget_rss_form().numberisint|string, since the widget template passes'__i__'.get_shortcode_tags_in_content()returnslist<string>, since it yields''when no shortcodes are registered.get_block_wrapper_attributes().$extra_attributesalso accepts numbers, which the body casts. The conditional return type is dropped, because the function can still return''when$extra_attributesis non-empty.list<mixed> $argson the cron functions. The stored cron arrays are stillarray<mixed>, sowp-cron.phpwould report errors.WP_List_Table::set_pagination_args(), which rejected numeric-string totals, the documentedinfinite_scrollkey and query strings, and forCustom_Image_Header::set_header_image(), whose body accepts objects and missing keys.@phpstan-return voidtags onwp_widget_rss_form()andregister_widget().Changes after review
http_responseis optional in all 9 shapes, becauserequest()returns apre_http_requestfilter value as is, and that value doesn't have to include it.wp_widget_rss_form().erroris optional, since the dashboard widget's first render passes onlynumber. The$inputsvalues arebool|'hidden', since'hidden'outputs a hidden field._get_list_table(). The shape includes the documentedplural,singularandajaxkeys, not justscreen.@phpstan-paramtags onwp_get_script_tag()andwp_get_inline_script_tag(), which repeated the canonicalarray<string, string|bool>already on trunk.Effect on the analysis
composer run phpstanpasses with no baseline changes. At level 10, compared against trunk, 57 errors are fixed and 19 are introduced. 2 of the 19 are inWP_Http::request(), where thepre_http_requestandhttp_responsefilters returnmixed. The rest are mostly callers that pass a plainarraywhere a shape is now expected, or existing errors reworded. (These counts were measured before the changes after review.)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: Splitting #13530 by tag kind, applying the corrections from the review analysis on #13530 and from review on this PR, checking each subset with
composer run phpstan(also at level 10, compared against trunk) andphpcs, and drafting the commit messages and this description. Reviewed 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.
🤖 Generated with Claude Code
https://claude.ai/code/session_015BuoHZQvJMvPEYp4Sfjgvd