Repository navigation
Users: Lazy load capability data for author display lookups - #14143
spacedmonkey wants to merge 3 commits into
Conversation
Introduce `get_authordata()`, a lighter-weight alternative to `get_userdata()` for contexts that mainly need display data, such as the `$authordata` global set up in the Loop, author archives, and the author template tags. The returned `WP_User` defers loading the `caps`, `roles`, and `allcaps` properties until they are first accessed. `WP_User::init()` gains a `$short_init` parameter that unsets these properties, so that the first access is routed through the magic methods, which load the data on demand. `WP_User::__get()` now returns by reference, so the properties can still be modified in place. `WP_User` implements `JsonSerializable` and `__serialize()`, so that `wp_json_encode()` and `serialize()` include the capability data. By default, `WP_User` still loads the capability data immediately, so `get_object_vars()` and similar functions are unchanged for all other users. Follow-up to [60915], [61037]. Props spacedmonkey. See #58001. Co-Authored-By: Claude Opus 5.5 <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. |
…data(). The `get_userdata()` calls in `WP_Query::generate_postdata()` and `get_permalink()` were replaced with `get_authordata()`, which is passed an integer, so the ignored `argument.type` errors no longer occur. See #58001. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The capability data is always loaded before serializing, so the pending flag is always false and can be serialized as is, instead of being removed from the data. See #58001. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
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. |
Trac ticket: https://core.trac.wordpress.org/ticket/58001
Summary
Second attempt at lazy loading user capabilities, after [60915] was reverted in [61037]. This version keeps
caps,rolesandallcapspublic. It also makes lazy loading opt-in, soWP_Userbehaves as before unless code asks for the lazy version.get_authordata( $user_id ). It returns aWP_Userwhose capability data loads on first access. Display-only call sites use it:$authordataingenerate_postdata()andWP::register_globals()get_the_author_meta(),get_the_modified_author(),get_author_posts_url(),wp_list_authors()get_permalink()for%author%structuresWP_User::init( $data, $site_id, $short_init = false ). With$short_init,for_site()unsets the three properties, and the existing magic methods load them on first access.__get()now returns by reference, so$user->roles[] = 'x'and$user->allcaps['foo'] = truekeep working, even as the first access.WP_UserimplementsJsonSerializableand__serialize(), sowp_json_encode()andserialize()load the data first. Native unserialization restores the result, and payloads serialized before this change still unserialize correctly.WP_Userloads eagerly by default.new WP_User,get_userdata(),get_user_by()and the current user behave exactly as before, soget_object_vars(), array casts andprint_r()still includecaps,rolesandallcaps. This addresses the concerns behind the revert in comments 39, 42, 43 and 46, and Peter's test from comment 53 is included.Supersedes #13825. Unlike that PR, reading
$authordata->rolesdirectly loads the data instead of returning an empty array.Behaviour changes (for the dev note)
These apply only to users returned by
get_authordata():get_object_vars(),(array)casts,var_export()andprint_r()leave outcaps,rolesandallcapsuntil one of them is first accessed. On PHP 7.4 there is no way to hook into these.has_cap()for a super admin returns before readingallcaps, so it doesn't trigger the load.get_authordata()builds the user directly, so it bypasses the pluggableget_userdata().For all users:
WP_User::__get()now returns by reference. An in-place write to a meta key, such as$user->some_meta['k'] = 1, used to raise an "Indirect modification" notice and is now silently ignored. It never had any effect either way.Note
This defers loading the capability data but not the full user meta, because
cache_users()still primes all user meta. The full front-end saving depends on lazy user meta (#63021).Test plan
tests/phpunit/tests/user/wpUserLazyCapabilities.php(lazy and eager behaviour, magic methods, JSON, serialize,for_site()on single site and multisite, the super admin case)tests/phpunit/tests/user/getAuthordata.phpgetTheModifiedAuthor.php,getTheAuthorMeta.php,getTheAuthorPostsLink.php,wpListAuthors.phpandlink.php.generatePostdata.phpandsetupPostdata.phpupdated forget_authordata().capabilities.php:get_object_vars()includesallcapsfor aWP_Userthat hasn't been touched yet.58001group and theuser,capabilities,query,author,post,rest-api,template,linkgroups pass on single site and multisite (PHP 7.4).$authordataglobal.🤖 Generated with Claude Code