Skip to content

Docs: Use richer numeric-string type for DB-backed class properties - #12408

Closed
westonruter wants to merge 4 commits into
WordPress:trunkfrom
westonruter:add/numeric-string-types
Closed

Docs: Use richer numeric-string type for DB-backed class properties#12408
westonruter wants to merge 4 commits into
WordPress:trunkfrom
westonruter:add/numeric-string-types

Conversation

@westonruter

@westonruterwestonruter commented Jul 6, 2026

Copy link
Copy Markdown
Member

Follow-up to r62437 / be80802 (for Core-44723) which corrected the type of WP_User_Request::$user_id and added numeric-string as a richer PHPStan type to WP_Post::$post_author and WP_Post::$comment_count. This PR extends the same treatment to the remaining DB-backed class properties which are documented as string but always hold numeric strings, and corrects the documented types of a few magic properties along the way:

  • WP_Comment: Adds @phpstan-var numeric-string to $comment_ID, $comment_post_ID, $comment_karma, $comment_parent, and $user_id. ($comment_approved is intentionally excluded since it can also be spam, trash, or post-trashed.)
  • WP_Site: Adds @phpstan-var numeric-string to $blog_id, $site_id, $public, $archived, $mature, $spam, $deleted, and $lang_id.
  • WP_Network: Adds @phpstan-var numeric-string to the private $blog_id property, and documents the corresponding magic $blog_id property (exposed via __get(), which returns (string) $this->get_main_site_id()) with an @property tag and an @phpstan-property numeric-string refinement, as it was previously missing from the class-level tags.
  • WP_Site::$post_count (magic): Corrects the type from int to int|string|false (int|numeric-string|false for PHPStan). The value is lazy-loaded via get_option( 'post_count' ) in WP_Site::get_details(), so despite update_posts_count() storing an integer, it is a numeric string once read back from the database, and false when the option is not set (new sites with no published posts — see Tests_Multisite_Site_Details::test_site_details_cached_including_false_values()). The integer can also be returned within the same request via the options cache and can persist in the site-details object cache.
  • WP_User::$user_status (magic): Adds an @phpstan-property numeric-string refinement. The value comes raw off the wp_users row, where the column always exists.
  • WP_User::$user_level (magic): Corrects the type from int to int|string (int|numeric-string|'' for PHPStan). The value resolves through get_user_meta( ..., 'wp_user_level', true ), which returns a numeric string, or an empty string when the metadata is absent (e.g. a multisite user with no role on the site). It is an integer only after WP_User::update_user_level_from_caps() has assigned one to the instance in the same request, such as via WP_User::set_role() during wp_insert_user(). ($spam/$deleted are left as plain string since on single site they fall through to user meta and return ''.)

WP_Post and WP_Term integer-like fields are not touched because they are actually cast to int during hydration (WP_Post::get_instance()/sanitize_term()).

Existing core call sites are unaffected: nothing in core reads the magic WP_Site::$post_count, and the WP_User::$user_level readers either cast to (int) (wp_set_current_user()) or use loose comparisons in deprecated.php.

Trac tickets: https://core.trac.wordpress.org/ticket/64898, https://core.trac.wordpress.org/ticket/64896

Use of AI Tools

AI assistance: Yes
Tool(s): Claude Code
Model(s): Claude Fable 5
Used for: Auditing core for remaining DB-backed properties missing numeric-string types, tracing the runtime types of the magic properties, authoring the docblock changes and commit messages, and verifying with PHPCS/PHPStan. All changes were reviewed and directed 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


✅ Committed in 0ee8e28 (r62640).

@github-actions

github-actionsBot commented Jul 6, 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. You can also manually ask me to refresh this list by adding the props-bot label.

Core Committers: Use this line as a base for the props when committing in SVN:

Props westonruter.

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

westonruterand others added 4 commits July 5, 2026 20:29
…type
The private `$blog_id` property is exposed externally via `__get()`, which
returns `(string) $this->get_main_site_id()`, but it was missing from the
class-level `@property` tags. Document it as `string` with the richer
`numeric-string` type in a `@phpstan-property` tag.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The property is lazy-loaded via `get_option( 'post_count' )` in
`WP_Site::get_details()`, so despite `update_posts_count()` storing an
integer, the value is a numeric string once read back from the database,
and `false` when the option is not set (new sites with no published
posts). The integer originally passed to `update_option()` can also be
returned within the same request via the options cache, and can persist
in the 'site-details' object cache.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…vel` properties
The `user_status` value comes raw off the `wp_users` row, where the
column always exists, so it is always a numeric string.
The `user_level` value resolves through
`get_user_meta( ..., 'wp_user_level', true )`, which returns a numeric
string, or an empty string when the metadata is absent (e.g. a multisite
user with no role on the site). It is an integer only after
`WP_User::update_user_level_from_caps()` has assigned one to the
instance in the same request, such as via `WP_User::set_role()` during
`wp_insert_user()`.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@westonruter
westonruterforce-pushed the add/numeric-string-types branch from 38446fb to d84085dCompareJuly 6, 2026 03:30
@github-actions

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.

pento pushed a commit that referenced this pull request Jul 6, 2026
Add `@phpstan-var numeric-string` annotations to string properties which hold integer database values:
* `WP_Comment::$comment_ID`
* `WP_Comment::$comment_post_ID`
* `WP_Comment::$comment_karma`
* `WP_Comment::$comment_parent`
* `WP_Comment::$user_id`
* the eight `WP_Site` properties backed by integer columns of the `wp_blogs` table
* the private `WP_Network::$blog_id` property
Previously the `numeric-string` nature of such properties was only indicated in the property description:
> A numeric string, for compatibility reasons.
Additionally, document the magic `WP_Network::$blog_id` property, which is exposed via `__get()` as a numeric string but was missing from the class-level `@property` tags.
Finally, correct the documented types of three magic properties:
* `WP_Site::$post_count` is lazy-loaded via `get_option()`, so it is a numeric string once read back from the database and `false` when the option is not set (new sites with no published posts); it holds an integer only when served from the options cache in the same request that updated it.
* `WP_User::$user_status` always holds a numeric string coming raw off the users table row.
* `WP_User::$user_level` resolves through user metadata as a numeric string (or an empty string when the metadata is absent), holding an integer only after `WP_User::update_user_level_from_caps()` has assigned one to the instance in the same request.
Developed in #12408.
Follow-up to r37657, r37870, r38630, r48941, r62437.
See #44723, #64896, #64898.
git-svn-id: https://develop.svn.wordpress.org/trunk@62640 602fd350-edb4-49c9-b593-d223f7449a82
markjaquith pushed a commit to markjaquith/WordPress that referenced this pull request Jul 6, 2026
Add `@phpstan-var numeric-string` annotations to string properties which hold integer database values:
* `WP_Comment::$comment_ID`
* `WP_Comment::$comment_post_ID`
* `WP_Comment::$comment_karma`
* `WP_Comment::$comment_parent`
* `WP_Comment::$user_id`
* the eight `WP_Site` properties backed by integer columns of the `wp_blogs` table
* the private `WP_Network::$blog_id` property
Previously the `numeric-string` nature of such properties was only indicated in the property description:
> A numeric string, for compatibility reasons.
Additionally, document the magic `WP_Network::$blog_id` property, which is exposed via `__get()` as a numeric string but was missing from the class-level `@property` tags.
Finally, correct the documented types of three magic properties:
* `WP_Site::$post_count` is lazy-loaded via `get_option()`, so it is a numeric string once read back from the database and `false` when the option is not set (new sites with no published posts); it holds an integer only when served from the options cache in the same request that updated it.
* `WP_User::$user_status` always holds a numeric string coming raw off the users table row.
* `WP_User::$user_level` resolves through user metadata as a numeric string (or an empty string when the metadata is absent), holding an integer only after `WP_User::update_user_level_from_caps()` has assigned one to the instance in the same request.
Developed in WordPress/wordpress-develop#12408.
Follow-up to r37657, r37870, r38630, r48941, r62437.
See #44723, #64896, #64898.
Built from https://develop.svn.wordpress.org/trunk@62640
git-svn-id: http://core.svn.wordpress.org/trunk@61925 1a063a9b-81f0-0310-95a4-ce76da25c4cd
Sign up for freeto 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.

1 participant

@westonruter