Skip to content

Allow numeric strings in wp_checkdate() and the *_metadata_by_mid() functions - #15472

Closed
pwtyler wants to merge 10 commits into
WordPress:trunkfrom
pwtyler:phpstan/ms-site
Closed

pwtyler wants to merge 10 commits into
WordPress:trunkfrom
pwtyler:phpstan/ms-site

Conversation

@pwtyler

@pwtyler pwtyler commented Nov 4, 2026 •

Copy link
Copy Markdown

✅ Committed in r65269 (4e77779).


This fixes 17 PHPStan argument.type errors across 8 files. They come from function docblocks that document int while the functions accept numeric strings, and every core caller passes numeric strings.

Background

  • wp_checkdate() (9 errors): callers pass date parts cut from a date string, so they arrive as strings. r61172 (Core-26798) added is_numeric() checks and (int) casts for exactly that case, but left the @param int docblocks unchanged. A call-site (int) cast would be wrong here, because it would turn a malformed part like '1a' into a valid 1.
  • delete_metadata_by_mid() (8 errors): callers loop over meta IDs from $wpdb->get_col(), which are strings, as they have since r20435. Since r38699 (Core-37746), the function validates with is_numeric() and floor() and casts to an integer. get_metadata_by_mid() and update_metadata_by_mid() share that validation.

Changes

  • wp_checkdate(): $month, $day and $year are int|string, plus @phpstan-param int|numeric-string. The ranges that checkdate() requires are deliberately not applied, because the function's purpose is to validate input that may be out of range.
  • get_metadata_by_mid(), update_metadata_by_mid() and delete_metadata_by_mid(): $meta_id is int|string, plus @phpstan-param int|numeric-string.
  • Removes the 16 baseline entries from tests/phpstan/baselines/argument.type.neon.

Testing Instructions

  • npm run typecheck:php reports no errors.
  • npm run test:php -- --group meta,date,datequery passes, single-site and with -c tests/phpunit/multisite.xml.

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, Claude Sonnet 5.5
Used for: Surveying open PRs to avoid overlap, code archeology (tracing changesets), testing type variants against PHPStan, and drafting the change and this description. I reviewed and verified all output.


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.

…by_mid()`.

Both functions validate their numeric arguments with `is_numeric()` and cast them to integers, and every core caller passes strings: date parts cut from a date string with `substr()` or a regular expression, and meta IDs read with `$wpdb->get_col()`. Their docblocks still documented `int` only.

This widens `$month`, `$day`, and `$year` in `wp_checkdate()`, and `$meta_id` in `delete_metadata_by_mid()`, to `int|string`. That resolves 17 PHPStan `argument.type` errors across 8 files.

Follow-up to r18494, r20435, r38699, r61172.

See #65817.
… and `update_metadata_by_mid()`.

Both functions share the `is_numeric()` and `floor()` validation and integer cast used by `delete_metadata_by_mid()`, so they accept numeric strings in the same way.

See #65817.
# Conflicts:
#	tests/phpstan/baselines/argument.type.neon
Comment thread src/wp-includes/functions.php Resolved
@pwtyler
pwtyler marked this pull request as ready for review November 4, 2026 20:21
@github-actions

github-actions Bot commented Nov 4, 2026

Copy link
Copy Markdown

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:

Props pwtyler, westonruter.

To understand the WordPress project's expectations around crediting contributors, please review the Contributor Attribution page in the Core Handbook.


Props Bot commands

You can trigger Props Bot actions by commenting on this PR:

  • @propsbot add <username> to give props to a GitHub user. Requires write access.
  • @propsbot remove <username> to leave a user out of the props. Requires write access.
  • @propsbot refresh to refresh this list. Adding the props-bot label works too.

Comment thread src/wp-includes/meta.php Resolved
Comment thread src/wp-includes/meta.php Resolved
@github-actions

github-actions Bot commented Nov 4, 2026

Copy link
Copy Markdown

Test using WordPress Playground

The 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

  • All changes will be lost when closing a tab with a Playground instance.
  • All changes will be lost when refreshing the page.
  • A fresh instance is created each time the link below is clicked.
  • Every time this pull request is updated, a new ZIP file containing all changes is created. If changes are not reflected in the Playground instance,
    it's possible that the most recent build failed, or has not completed. Check the list of workflow runs to be sure.

For more details about these limitations and more, check out the Limitations page in the WordPress Playground documentation.

Test this pull request with WordPress Playground.

…id()` meta IDs.

Narrows the date parts in `wp_checkdate()` to the ranges accepted by PHP's `checkdate()`, and the meta IDs in `update_metadata_by_mid()` and `delete_metadata_by_mid()` to numeric values, using `@phpstan-param` so that the documented `int|string` types stay readable.

See #65817.
Matches `update_metadata_by_mid()` and `delete_metadata_by_mid()`, which share its validation.

See #65817.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Active critical and moderate findings show the proposed PHPStan contracts reject actual caller inputs, including string|false, out-of-range integers, and get_col() values that may be null or nonnumeric.

3 open issues
What changed in this PR

This pull request updates PHPDoc and PHPStan annotations for wp_checkdate() and metadata-by-ID functions, and removes related PHPStan baseline suppressions.

Changes:

  • Widens documented date-component and metadata-ID parameter types.
  • Adds PHPStan-specific annotations for string inputs.
  • Removes 17 corresponding argument.type baseline entries.
File Review
tests/​phpstan/​baselines/​argument.type.neon Removes the affected baseline entries, but the underlying type errors remain unresolved with the proposed contracts.
src/​wp-includes/​meta.php The proposed metadata-ID type does not account for get_col() values that may be null or unproven numeric strings.
src/​wp-includes/​functions.php The proposed wp_checkdate() types do not account for `string

This pull request requires changes.

Review effort: Lite

Comment thread src/wp-includes/functions.php Outdated
Comment on lines +7639 to +7641
* @phpstan-param int<1, 12>|numeric-string $month
* @phpstan-param int<1, 31>|numeric-string $day
* @phpstan-param int<1, 32767>|numeric-string $year

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤖 Comment by Claude Opus 5.5 (medium effort)

This does not apply at the project's rule level: at level 5, PHPStan does not report an argument whose union type is only partly accepted, so the string|false and string date parts pass and the removed baseline entries are genuinely resolved. Widening the type to int|string|false would discard the contract that level 7 is meant to enforce.

Details

vendor/bin/phpstan analyse -c phpstan.neon.dist (level 5, with the baselines) was run on ms-site.php, class-wp-customize-manager.php, post.php, and the other five caller files, and it reported no errors, including no unmatched baseline entries. The partially wrong union types are only reported from level 7, where flagging a date part that may be false or non-numeric is the intended result.

Comment thread src/wp-includes/meta.php
* @param int|string $meta_id ID for a specific meta row.
* @return bool True on successful delete, false on failure.
*
* @phpstan-param int|numeric-string $meta_id

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤖 Comment by Claude Opus 5.5 (medium effort)

This does not apply at the project's rule level: at level 5, PHPStan does not report an argument whose union type is only partly accepted, so the non-empty-string|null values from $wpdb->get_col() pass and the removed baseline entries are genuinely resolved. From level 7 the callers will be flagged, which is intended, since a meta ID should be provably numeric.

Details

vendor/bin/phpstan analyse -c phpstan.neon.dist (level 5, with the baselines) was run on comment.php, functions.php, ms-site.php, post.php, taxonomy.php, wp-admin/includes/ms.php, wp-admin/includes/user.php, and class-wp-customize-manager.php, and it reported no errors, including no unmatched baseline entries.

Comment thread src/wp-includes/functions.php Resolved
As a validator, `wp_checkdate()` must accept out-of-range and unvalidated input and return `false` for it, as its tests do with month `99` and year `0`. The ranges also rejected the `substr()` results its callers pass from level 7.

See #65817.
@pwtyler

pwtyler commented Nov 4, 2026 •

Copy link
Copy Markdown
Author
  • wp_checkdate(): I dropped the @phpstan-param ranges and kept int|string. As a validator it has to accept unvalidated and out-of-range input, and its tests pass month 99 and year 0 deliberately (tests/phpunit/tests/date/wpCheckdate.php:41-42). The ranges also rejected its callers' substr() results from level 7.
  • *_metadata_by_mid(): I kept @phpstan-param int|numeric-string $meta_id. It passes at level 5. From level 7 it flags the 7 callers that loop over $wpdb->get_col() results (non-empty-string|null), which seems like the right nudge, since a meta ID should be provably numeric.

pwtyler and others added 4 commits November 4, 2026 15:03
…n types.

Reverts 9b69b56. The PHPStan contract follows what `checkdate()` requires. Tests that deliberately pass out-of-range values can use `@phpstan-ignore` if they are ever analyzed.

See #65817.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Active critical type errors remain at the updated call sites, and the proposed contracts are not bounded to the documented valid ranges.

5 open issues
1 resolved since last review

Review effort: Lite

Comment on lines +7640 to +7642
* @phpstan-param int|numeric-string $month
* @phpstan-param int|numeric-string $day
* @phpstan-param int|numeric-string $year

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤖 Comment by Claude Opus 5.5 (medium effort)

This does not apply at the project's rule level: at level 5, PHPStan does not report an argument whose union type is only partly accepted, so the string|false and string date parts pass and the removed baseline entries are genuinely resolved. Widening the type to int|string|false would discard the contract that level 7 is meant to enforce.

Details

vendor/bin/phpstan analyse -c phpstan.neon.dist (level 5, with the baselines) was run on ms-site.php, class-wp-customize-manager.php, post.php, and the other five caller files, and it reported no errors, including no unmatched baseline entries. The partially wrong union types are only reported from level 7, where flagging a date part that may be false or non-numeric is the intended result.

Comment thread src/wp-includes/meta.php
* @type string $user_id Optional. The object ID when the meta type is 'user'.
* }
*
* @phpstan-param int|numeric-string $meta_id

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤖 Comment by Claude Opus 5.5 (medium effort)

This does not apply at the project's rule level: at level 5, PHPStan does not report an argument whose union type is only partly accepted, so the non-empty-string|null values from $wpdb->get_col() pass and the removed baseline entries are genuinely resolved. From level 7 the callers will be flagged, which is intended, since a meta ID should be provably numeric.

Details

vendor/bin/phpstan analyse -c phpstan.neon.dist (level 5, with the baselines) was run on comment.php, functions.php, ms-site.php, post.php, taxonomy.php, wp-admin/includes/ms.php, wp-admin/includes/user.php, and class-wp-customize-manager.php, and it reported no errors, including no unmatched baseline entries.

Comment thread src/wp-includes/functions.php Resolved
@pwtyler pwtyler changed the title Docs: Allow numeric strings in wp_checkdate() and the *_metadata_by_mid() functions Allow numeric strings in wp_checkdate() and the *_metadata_by_mid() functions Nov 4, 2026
wporg-sync pushed a commit that referenced this pull request Nov 4, 2026
The `wp_checkdate()` and `*_metadata_by_mid()` functions already validate their numeric arguments with `is_numeric()` and cast them to integers, and core callers pass strings: date parts cut from a date string, and meta IDs read with `$wpdb->get_col()`. Their docblocks still documented `int` only, which caused 17 PHPStan `argument.type` errors. The arguments are now documented as `int|string`, with PHPStan narrowing them to `int|numeric-string`. The `checkdate()` ranges are deliberately not applied to `wp_checkdate()`, since the function's purpose is to validate input that may be out of range.

Developed in #15472.
Follow-up to r18494, r20435, r38699, r61172.

Props pwtyler, westonruter.
See #65817.


git-svn-id: https://develop.svn.wordpress.org/trunk@65269 602fd350-edb4-49c9-b593-d223f7449a82
@westonruter westonruter closed this Nov 4, 2026
wporg-sync pushed a commit to WordPress/WordPress that referenced this pull request Nov 4, 2026
The `wp_checkdate()` and `*_metadata_by_mid()` functions already validate their numeric arguments with `is_numeric()` and cast them to integers, and core callers pass strings: date parts cut from a date string, and meta IDs read with `$wpdb->get_col()`. Their docblocks still documented `int` only, which caused 17 PHPStan `argument.type` errors. The arguments are now documented as `int|string`, with PHPStan narrowing them to `int|numeric-string`. The `checkdate()` ranges are deliberately not applied to `wp_checkdate()`, since the function's purpose is to validate input that may be out of range.

Developed in WordPress/wordpress-develop#15472.
Follow-up to r18494, r20435, r38699, r61172.

Props pwtyler, westonruter.
See #65817.

Built from https://develop.svn.wordpress.org/trunk@65269


git-svn-id: http://core.svn.wordpress.org/trunk@64418 1a063a9b-81f0-0310-95a4-ce76da25c4cd
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants