| 开发者 | davefx |
|---|---|
| 更新时间 | 2026年10月8日 01:38 |
| PHP版本: | 7.4 及以上 |
| WordPress版本: | 7.1 |
| 版权: | GPLv3 or later |
| 版权网址: | 版权信息 |
LENGTH() in the database rather than re-serializing it in PHP, times a real unserialize() of it on your machine after a warm-up pass, measures the resident footprint with the result kept alive, and works out what that costs in concurrent workers. It identifies roles that grant no effective permission, roles nobody holds, roles with identical capability sets, and capabilities it cannot account for — while being explicit that "unrecognised" is not "orphaned", because custom code checks capabilities no scanner can see.
It offers the missing primitive. There is no way in WordPress to say "this user is a wholesale customer" without granting them permissions. There are only roles. That is why membership plugins keep inventing them: they have no alternative. A LeanRoles tag is that alternative. It appears in $user->roles, answers current_user_can(), and can be filtered on in WP_User_Query — and it is never written to the autoloaded option. Third-party code cannot tell the difference.
What it does
wp leanroles audit --format=jsonlibraries/user-tags/, that any plugin can bundle so tags cost them nothing to adoptwp-content/plugins/leanroles and activate it.Yes, and that is the point of it. It reads. The only things it writes are a twelve-hour cache of count_users() and, on activation, a restore point of your role option.
They stop being injected. Because they grant no capabilities, nothing about what your users can do changes. The assignments stay in the database and come back when you reactivate.
Yes, and that is the point. The tag engine is a self-contained library that ships inside this plugin and can be copied into yours: one require_once and you have user_tags_add(), user_tags_get() and the rest. If several plugins bundle it, the newest copy wins and they all share one set of tags. Removing LeanRoles does not remove them. See libraries/user-tags/readme.md.
current_user_can('my_tag') work?Yes. So will in_array( 'my_tag', $user->roles ), get_users( array( 'role' => 'my_tag' ) ) and WP_Roles::is_role().
The auditor understands it: role options are per site and it reads the right one. Tags are per site too, since term relationships live in each site's own tables. Network-wide operations are not in this version.
It helps with query time and nothing else. Memory, unserialization and — with Redis — bandwidth all get worse, not better, because alloptions lives under a single key and crosses the wire whole on every request. The audit detects your drop-in and tones its findings down if that drop-in already compresses or splits the blob.
wp leanroles bulk could not stop. It ran passes until one reported itself finished, and if a pass ever stopped making progress there was nothing to end the loop — a command that never returns, or a cron worker pinned until the host kills it. It now abandons the run when a pass moves nobody, says which user it stopped at, and leaves the run resumable rather than undoing what it had done.
This affects the paid plans only. Nothing in this build changes.
0.5.0
wp leanroles tag export and wp leanroles role export no longer take --file. Both print to standard output, so redirect them where you want them: wp leanroles role export > roles.json. The plugin now writes to the filesystem nowhere at all.
Every string the plugin ships, including those in the bundled User Tags library, now uses one text domain, so all of them can be translated through translate.wordpress.org. Compiled translations are no longer bundled — the directory serves those, and community translations reach you the moment they are approved rather than the next time this plugin is released.
0.4.0
Two primitives the free tier was missing.
wp leanroles role update changes a role's display name and what it grants. Command line only, and that is the product decision rather than an omission: a screen of capability checkboxes would put this in the category of role editors, and this is an auditor. It keeps three things apart that are easy to conflate — granting a capability, denying one, and dropping it altogether — because a denied capability still occupies a row in the option, which is the thing being measured.
wp leanroles role export and import move a configuration between sites. Not the same as a restore point: a backup comes back to the site it came from, an export leaves, so it records where it came from and when. Protected roles are never touched in either direction, so a file that simply omits administrator cannot be a way to delete it.
Spanish is complete again. The catalogue had fallen behind the code by about a third.
0.3.0
Licensing, through Freemius. The SDK ships in libraries/freemius/ and handles the paid plan, licence activation and automatic updates.
It is the only part of the plugin that contacts anything outside your site, and it asks first. The opt-in on activation is skippable, and skipping costs you nothing: the auditor and user tags neither know nor care. What is shared if you do opt in, and what stays optional, is set out under Licensing, and the one external service above.
The SDK is required explicitly rather than autoloaded, for the same reason as the User Tags library: Freemius also arbitrates between every copy installed on a site and boots the newest, and an autoloader binding a class to a copy other than the one that won is the failure that pattern exists to avoid.
The plugin's test suite now loads it the way WordPress does, from inside wp-content/plugins. Loaded from anywhere else the SDK cannot find the plugin's main file, resolves it to the plugins directory, and warns on every read of the plugin headers.
0.2.2
Housekeeping in what ships, with no functional change.
The bundled library's readme.txt no longer travels in the archive. It is written for the wordpress.org directory, and a second directory readme inside one plugin is something a reviewer has to stop and work out. Its readme.md, which documents bundling the library, stays — whoever goes looking in libraries/user-tags/ wants that one.
The library is 1.3.4, which is called User Tags again. The name had been changed to claim a wordpress.org permalink for it; it is not being listed there separately, so the name was buying nothing.
0.2.1
The Users → Tags link works. The archive published as 0.2.0 carried an earlier build of the bundled library, in which renaming the text domain had swallowed the admin page slug — the two were the same string. The menu item pointed at a page that did not exist, and clicking it said you were not allowed to access it. Nothing was wrong with your permissions.
The library is now 1.3.3, which also means: activated on its own it registers its own screens, so a site can install User Tags without LeanRoles; and the whole plugin clears the wordpress.org Plugin Check. That last one found a handful of things worth fixing here too — a stale Tested up to, a hidden file inside the archive, three unescaped integers in the audit's worker-model inputs, and is_writable() where core's wp_is_writable() belongs.
0.2.0
The tag screens moved to the bundled library. They now sit under Users → Tags, which is where an administrator looks for something that belongs to users, rather than under the LeanRoles menu. Behaviour is the same; the code is now shared.
The library is User Tags, bundled in libraries/user-tags/ and free for any plugin to adopt. LeanRoles asks it for the screens the same way any other consumer would:
add_filter( 'user_tags_enable_admin', '__return_true' );
Spanish translation. languages/ carries the .pot and es_ES, and the plugin loads its own text domain rather than waiting for one to be loaded for it, so the strings arrive whichever way the plugin was installed.
The LeanRoles menu now holds the audit and nothing else.
0.1.0
First release.
The auditor. Strictly read-only, so it can be left on a client site without asking anyone first. It measures rather than estimates:
LENGTH() in the database, not by re-serializing in PHP — the two produce different strings, and the difference is exactly the sort of small dishonesty that gets a performance plugin disbelieved.unserialize() of your own option, timed on your own machine after a warm-up pass.level_N entries, and a conservative lower bound on what inheritance could remove.object-cache.php drop-in, with the findings toned down when the drop-in already compresses or shards the blob.$user->roles, answers current_user_can(), and WP_User_Query finds it — while granting no capability and never being written to the autoloaded role option. Create and edit tags, assign them individually or in bulk from the users list, filter by them, CSV import and export.
The tag engine ships as a standalone library, libraries/user-tags/, that any plugin can bundle. See https://github.com/davefx/user-tags
WP-CLI.
wp leanroles audit — including --format=json for aggregating across siteswp leanroles tag create|delete|list|assign|remove|users|export|importwp leanroles role delete --reassign=<slug> with a --dry-runwp leanroles backup create|list|restore