Make WordPress Core

Opened 13 years ago

Closed 12 years ago

Last modified 12 years ago

#17860 closed defect (bug) (fixed)

Multisite: Incorrect User Counts on Sites

Reported by: cgrymala's profile cgrymala Owned by: nacin's profile nacin
Milestone: 3.5 Priority: normal
Severity: normal Version: 3.1.3
Component: Multisite Keywords:
Focuses: Cc:

Description

On a Multisite installation, the count of users does not always match the number of users displayed in the table on wp-admin/users.php or wp-admin/network/site-users.php.

The issue appears to be related to some users being stored in the database with specific capabilities, but without one of those capabilities being a "role".

For instance, let's say you're working on a site with an ID of 12 and a table prefix of wp_. If you query the wp_usermeta table you will retrieve a result similar to the following:

umeta_id: 72
user_id: 3
meta_key: wp_12_capabilities
meta_value: a:1:{s:17:"gform_full_access";s:1:"1";}

That particular capability is added by Gravity Forms, but there are other plugins that perform similar actions.

When you view the table of Users under Network Admin -> Sites -> Edit -> Users or under Site Admin -> Users, the user count does not match what's shown in the table.

This bug is present in the current stable version (3.1.3) and in the current nightly version as of June 21, 2011.

I have attached 2 screen shots showing the Network Admin -> Sites -> Edit -> Users screen and the Site Admin -> Users screen. As you can see, the number next to "All" says there are 2 users, and the number of "items" at the top and bottom of the table is 2; but there is only 1 user displayed in the table.

This bug makes it very difficult to manage the users on each site and, in some cases, will trigger a "user already exists" error when you try to use "Add New" to add a user that's not shown in the table (though I haven't been able to reproduce that particular problem since I started testing to create this ticket).

Attachments (3)

user-table.png (10.2 KB) - added by cgrymala 13 years ago.
Users Table as shown from Network Admin -> Sites -> Edit -> Users
site-user-table.png (12.0 KB) - added by cgrymala 13 years ago.
Users Table as shown from Site Admin -> Users
17860.diff (575 bytes) - added by nacin 12 years ago.

Download all attachments as: .zip

Change History (21)

@cgrymala
13 years ago

Users Table as shown from Network Admin -> Sites -> Edit -> Users

@cgrymala
13 years ago

Users Table as shown from Site Admin -> Users

#1 follow-up: @hebbet
13 years ago

  • Version set to 3.1.3

#2 in reply to: ↑ 1 ; follow-up: @cgrymala
13 years ago

Replying to hebbet:
As mentioned above, this bug is also present in the current nightly version (which is showing as 3.2-RC1 right now). Thank you.

#3 in reply to: ↑ 2 @hebbet
13 years ago

Version should be the lowest affected Version, in your case it is 3.1.3 as you mentioned.

Replying to cgrymala:

Replying to hebbet:
As mentioned above, this bug is also present in the current nightly version (which is showing as 3.2-RC1 right now). Thank you.

#4 follow-up: @kawauso
13 years ago

The issue can be traced to line 198 of class-wp-users-list-table.php:

if ( is_multisite() && empty( $role ) )
	continue;

which skips any users without a role for the current blog.

#5 in reply to: ↑ 4 @cgrymala
13 years ago

Thanks for tracking that down, kawauso. I suspect the next step in this process is to discuss what the solution should be. Do we remove users without a valid role from the array before any processing is done so they're not counted at all, or do we assign them a fake/default role so that they'll still be listed in the user table.

Either way, the way it's set up right now is confusing, at best; and some sort of solution should probably be worked out.

What's the proper keyword to assign to a ticket to indicate it needs further discussion? Is that what the dev-feedback keyword is for? Thanks.

Replying to kawauso:

The issue can be traced to line 198 of class-wp-users-list-table.php:

if ( is_multisite() && empty( $role ) )
	continue;

which skips any users without a role for the current blog.

#6 follow-up: @jane
13 years ago

  • Cc petemall added
  • Keywords ux-feedback removed

You don't need a keyword to indicate further discussion is needed. If the core team hasn't tagged it as blessed, further discussion will be needed. :) dev-feedback is generally used when a patch needs review from the core team.

From a ux perspective, if someone is part of a multisite network, but has no role on an individual site, I would not expect them to show in the user table for that site.

#8 in reply to: ↑ 6 ; follow-up: @cgrymala
13 years ago

Replying to jane:

You don't need a keyword to indicate further discussion is needed. If the core team hasn't tagged it as blessed, further discussion will be needed. :) dev-feedback is generally used when a patch needs review from the core team.

From a ux perspective, if someone is part of a multisite network, but has no role on an individual site, I would not expect them to show in the user table for that site.

Thanks, Jane. You're right that the person shouldn't show up in the user table if they have no role or capabilities on the site in a multisite network. The problem is, they are being added to the user count if they have any capabilities for the site, even if they don't have a role for that site.

To make things more complicated, if they have capabilities and no role; WordPress won't even let you assign a role to them. Since you can't access the user through the user table, you can't give them a role; and if you try to "Add New" and type in their username, WordPress tells you that the user is already a member of the site.

In order to be able to give the user a role on the site, you have to find their usermeta information for that site in the database, delete the capabilities that they've been assigned, and then go back into the admin area and add them to the site.

#9 in reply to: ↑ 8 @scribu
12 years ago

Replying to cgrymala:

To make things more complicated, if they have capabilities and no role; WordPress won't even let you assign a role to them.

This plugin should help with that: http://wordpress.org/extend/plugins/user-management-tools/screenshots/

#10 @nacin
12 years ago

To make things more complicated, if they have capabilities and no role; WordPress won't even let you assign a role to them.

That seems like a separate bug.

Reading through this ticket, I am reminded of two others: the recent #22361, and the older and infamous #10201.

There are a number of deficiencies when it comes to roles and capabilities, and there are two ways to address them. They are not mutually exclusive. One is to start plotting a complete overhaul (akin to #10201). The other is to start chipping away at particular issues. For example, make multiple roles a little less painful, and/or fix what I quoted above.

Reading the original report here, it seems like this particular issue is that the way we decide to show users in the list table is more restrictive than what we use to count them. Obviously, those should be the same. And I would say that if they have a meta_key of any value (other than a:0:{}), they should be counted, and they should be displayed in some form. And obviously, displaying their roles/capabilities, and editing their roles, should not be so painful.

So, we agree there's a problem here. Now, we can start to look at the solution. It appears quite obvious that the bug is in the list table, as kawauso pointed out.

This was added for #12711, see [13883] and [13894]. Essentially, it was added to avoid showing users with an empty meta key (the fix was to stop creating empty meta keys, and remove them instead), but instead it avoids users with no role (which ensnares users with a single cap). Two ways out of this mess —

  • An upgrade routine to remove empty cap keys, as they should not exist. As cap key names are based on the blog_id, this is not fun, as it would need to be run on individual sites, despite being a global table. With an upgrade, may just remove the check.
  • Changing empty( $role ) to empty( $user->caps ).

Now, with that change, I guess the user would show as having "None" for a role. It's tough to consider a user being a member of the blog without having a role, but it *is* possible, and get_blogs_of_user() does consider the user to be part of this site, as does is_user_member_of_blog().

And so I ask you, is the bug really "incorrect user counts", or is it that users are improperly hidden? I would think that it is the latter, in which case, I've attached a patch that should do the trick.

@nacin
12 years ago

#11 @roytanck
12 years ago

Checking $user->caps sounds like an excellent solution imho. If I understand correctly it will list users who do not have a role, and allow admins to give them a role and/or remove them? I'm currently doing that by editing another user and then changing the id in the url, so this would be a huge improvement :). Thanks.

#12 follow-up: @nacin
12 years ago

Checking $user->caps sounds like an excellent solution imho. If I understand correctly it will list users who do not have a role, and allow admins to give them a role and/or remove them?

Doesn't seem like it would allow admins to give them a role, based on the report "if they have capabilities and no role; WordPress won't even let you assign a role to them," above. I did not yet investigate.

#13 in reply to: ↑ 12 @roytanck
12 years ago

Replying to nacin:

Doesn't seem like it would allow admins to give them a role, based on the report "if they have capabilities and no role; WordPress won't even let you assign a role to them," above. I did not yet investigate.

I did some quick tests, and your patch adds users without a role (capabilities: a:1:{s:17:"gform_full_access";s:1:"1";}) to wp-admin/network/site-users.php and wp-admin/users.php (as expected) with their role listed as "None".

Without the patch applied, these users would not be listed there, making it impossible for admins to click through to their profiles, and change "No role for this blog" to something more useful. These users could also not be added ("That user is already a member of this site"), or removed from the blog.

I agree that the problem here is the difference between how users are counted and listed. The other approach would imho be to not list these users, but also make it possible for admins to add them to the blog. Basically, either we treat users without a role as "strangers" (not counted, not listed, able to add) or as "family" (counted, listed).

#14 follow-up: @ipstenu
12 years ago

Not all users of the network show up like this on sites... What is it that makes them partially show up in the user list? If you add a user, they show up as they should, and from what I can tell, just visiting a site you're not a member of, as a logged in user, does not add you in any way to the user count.

How are these people getting half-added? I can't figure out how that gets started.

#15 in reply to: ↑ 14 @roytanck
12 years ago

Replying to ipstenu:

Not all users of the network show up like this on sites... What is it that makes them partially show up in the user list? If you add a user, they show up as they should, and from what I can tell, just visiting a site you're not a member of, as a logged in user, does not add you in any way to the user count.

How are these people getting half-added? I can't figure out how that gets started.

In my case, there's a Gravity Forms capability that somehow remains after a user has been removed. The result is a usermeta record with none of WP's default (or added) roles, just the gform_full_access capability.

Since count_users simply checks for whether a usermeta record (prefix_capabilities) exists, this capability (or even a record with an empty array) is enough for the user to be counted.

The site I'm working on has been online for a while, so I don't know exactly how this started, but I did notice that Gravity Forms only adds the capability, and never actively removes it. Not when a user is demoted (even though only admins should have this cap), nor in any other case.

#16 @nacin
12 years ago

  • Owner set to nacin
  • Resolution set to fixed
  • Status changed from new to closed

In 22686:

Less insane multiple role handling in the users list table.

If the user has more than one role, opt to show the first role that is
'editable', if present. Otherwise, fall back to the remaining roles.

In the future, we should show a comma-separated list of all roles,
editable or otherwise, and this list should be filterable, either by user,
or by the roles which can appear. Probably both.

In multisite, only hide users that have no capabilities (in case they
possess a leftover, empty wp_xx_capabilities key from the MU days),
not users that have no role, as they may have a cap but no role.

see #22361. fixes #17860.

#17 @helenyhou
12 years ago

  • Milestone changed from Awaiting Review to 3.5

#18 @nacin
12 years ago

In 22689:

Use correct variable. see #17860.

Note: See TracTickets for help on using tickets.