Code Quality: Add PHPStan types for wp_insert_term(), wp_update_term(), and wp_delete_term()#12465
Conversation
A query-string $args takes the string branch of the union, so numeric-string in the array shape only admitted unguarded values such as $_POST['parent']. sanitize_term_field() silently clamps a negative parent to 0, and a default of 0 is discarded by the term_exists() check in wp_delete_term(). 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. |
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. |
Add PHPStan array shapes for the `$args` parameter of `wp_insert_term()`, `wp_update_term()`, and `wp_delete_term()`, along with narrowed return types. The types describe the contract these functions are intended to be called with, rather than what unguarded callers happen to pass today. Developed in #12465. Follow-up to r62680. See #64898. git-svn-id: https://develop.svn.wordpress.org/trunk@62682 602fd350-edb4-49c9-b593-d223f7449a82
Add PHPStan array shapes for the `$args` parameter of `wp_insert_term()`, `wp_update_term()`, and `wp_delete_term()`, along with narrowed return types. The types describe the contract these functions are intended to be called with, rather than what unguarded callers happen to pass today. Developed in WordPress/wordpress-develop#12465. Follow-up to r62680. See #64898. Built from https://develop.svn.wordpress.org/trunk@62682 git-svn-id: http://core.svn.wordpress.org/trunk@61966 1a063a9b-81f0-0310-95a4-ce76da25c4cd
✅ Committed in r62682 (0527680)
Adds PHPStan array shapes and narrowed parameter/return types to
wp_insert_term(),wp_update_term(), andwp_delete_term()insrc/wp-includes/taxonomy.php. This removes themissingType.iterableValueerrors reported for each function's$argsparameter and return type at PHPStan level 10.The types describe the contract these functions are intended to be called with, rather than what unguarded callers happen to pass today. Notably:
parentis typednon-negative-int.sanitize_term_field()putsparentin$int_fieldsand silently clamps a negative value to0, reparenting the term to the root. Anumeric-stringalternative would be redundant: forwp_insert_term()a query string matches thestringbranch of the union, so the array shape only ever constrains callers passing an actual array, where anintis what should be supplied; andwp_update_term()has nostringbranch at all.wp_delete_term()'sdefaultis typedpositive-int, since0is discarded by the subsequentterm_exists()check.$argsshapes forwp_insert_term()andwp_update_term()are unsealed (...), because$argsis forwarded to thepre_insert_term,wp_insert_term_data,wp_insert_term_duplicate_term_check,create_term,wp_update_term_data, andedit_termhooks, where plugins legitimately read arbitrary keys.wp_delete_term()'s shape is sealed, as its$argsis consumed locally and never passed to a hook.descriptionisstring|nullforwp_insert_term()butstringforwp_update_term(). This asymmetry is deliberate:wp_insert_term()explicitly coerces a null description (// Coerce null description to strings, to avoid database errors.), whilewp_update_term()has no such coercion.wp_delete_term()'s return is narrowed tobool|WP_Error|0, verified against all six return paths. This relies on theterm_exists()conditional return type added in r62680.These annotations surface new
argument.typeerrors at several core call sites that pass$_POSTor otherwise unvalidated data directly into these functions (wp-admin/edit-tags.php,wp-admin/includes/ajax-actions.php,wp-includes/nav-menu.php,class-wp-rest-terms-controller.php,class-wp-xmlrpc-server.php). These are pre-existing latent issues that the types now make visible, and are left to be addressed separately.The two
term_id: mixedreturn errors that remain insidewp_insert_term()andwp_update_term()stem fromapply_filters()being typed as returningmixed, and are addressed in a separate pull request. See #12022.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 annotations against the function bodies and every core call site by diffing PHPStan level 10 output before and after; identifying that
wp_update_term()cannot accept a query string, the nulldescription/slugvalues, the unsealed-shape requirement, and the redundantnumeric-stringalternatives; and authoring the finalnon-negative-int/positive-intnarrowings. All changes were reviewed, tested, and are owned 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