Cryptic title, but couldn't think of a better one, feel free to adjust to something better. Im using the latest dev versions of chaos tools and views.
What I want to create should be doable with views, yet I can't figure out why it doesn't. I want to create a view that, when no argument is given, lists a few roles, and when an argument is given (argument is role_id), should list the users of that role. For this example, I only wanted to list the role of administrator, and when an argument is given (=the role_id of administrator), list all the users in the administrator role.
So, I set up the following filter criteria: the user should be active, and should have the role administrator. WITHOUT an argument, this works as expected, and generates a list of allowed items as I specified. this is the query Views generates (administrator is role_id 3):
SELECT users_roles.rid AS users_roles_rid, role.name AS role_name, COUNT(users.uid) AS num_records
FROM
{users} users
INNER JOIN {users_roles} users_roles ON users.uid = users_roles.uid
LEFT JOIN {role} role ON users_roles.rid = role.rid
WHERE (( (users.status <> '0') AND (users_roles.rid = '3') ))
GROUP BY role_name, users_roles_rid
ORDER BY role_name ASC
Now comes the fun part: the contextual filter is using the User: Roles filter. It gives me a nice page with 0 results on it. WTF. The query is kinda weird too:
SELECT users.picture AS users_picture, users.uid AS uid, users.name AS users_name, users.mail AS users_mail
FROM
{users} users
INNER JOIN {users_roles} users_roles ON users.uid = users_roles.uid
LEFT JOIN {users_roles} users_roles2 ON users.uid = users_roles2.uid AND users_roles2.rid != 3
WHERE (( (users.status <> '0') AND (users_roles.rid = '3') AND (users_roles2.rid = '3') ))
ORDER BY users_name ASC
Especially the last part (AND users_roles2.rid != 3) of the 5th line does not make any sense to me: never did I specify NOT to select rid 3. I re-created the view at least 4 times, and checked all my settings.
I'm still hoping that I'm doing something wrong, but I think this is a bug.
Removing the role filter makes it all magically work, it now lists users when my view receives the argument (in this case, 3). But obviously, this is not what I set out to do; list only certain roles...
SELECT users.picture AS users_picture, users.uid AS uid, users.name AS users_name, users.mail AS users_mail
FROM
{users} users
INNER JOIN {users_roles} users_roles ON users.uid = users_roles.uid
WHERE (( (users.status <> '0') AND (users_roles.rid = '3') ))
ORDER BY users_name ASC
Comments
Comment #1
kiphaas7 commentedRe-assigning, because I'm still not sure if it's an error on my side or Views.
Comment #2
merlinofchaos commentedRemove your filter for administrator (that's going to work counter to your contextual filter). The reason the query looks weird is that since roles are many::one it's trying to have the filters work together so you get users that have both roles.
Set the action to take if the contextual filter is not present to summary. That should force the contextual filter to create a summary of roles without the argument.
Comment #3
kiphaas7 commentedYour solution is exactly what I have now. If I understand you correctly, you want me to remove the filter and let the contextual filter create a summary if no argument is given. BUT, I want to limit the roles shown in the summary/present in the contextual filter. That's why I created the filter in the first place.
Case: I have role a, b, c and d present in the system. Of these roles, I want to generate a summary of roles b and c if no value is given for the contextual filter. B and c should also be the only allowed values for my contextual filter.
That is why I combined a filter and contextual filter in the first place…
Comment #4
merlinofchaos commentedPerhaps i was confused since you were limiting it to one role. A list of one role is not really a list.
Because of the many to one aspect of this, I'm not completely sure what you're asking is possible. It seems easy on the surface, but it makes the query very, very complicated.
Comment #5
kwongkkt commentedSimilar problem here.
I am using "filter" + "contextual filter" with "use grouping" to remove duplicates.
I have many roles created, while only 6 are selected for "filter", their IDs are '5', '6', '7', '8', '9', '10'.
For the "contextual filter", i selected "Display a summary", the count in the summary is correct.
However, when I click on the summary of role ID 10, the expanded page shows nothing, which I expect one to show.
Then I wonder, "Why the last role selected cannot show correctly?". I take a look at the sql and here it is.
It does not make sense on this line.
I DO want user with role id 10, which is correct on the where clause.
Then I take a look at how it works for other roles, e.g. role id 8
Why it is still asking for role id != 10??? Does it imply some default value by the last role to filter??
And only the where clause is updating
It looks more likely is a bug to me.
Subscribe.
Comment #6
dawehnerThat's perhaps a bug but why critical?
Critical is a tag for the module not for your site.
Do you really need the first filter?
Comment #7
merlinofchaos commentedThis is not a bug. This is the intended behavior.
When you combine the two, the *intent* is that you get users that contain *all* selected roles. Using the contextual filter does not cause the filter to be magically ignored.
Making this critical? That is bad behavior.
I believe the way to accomplish this task is probably to use two displays. One has the base path without the argument, such as 'foo' and the other has the base path with the argument, such as 'foo/%'. The second one does not have the filter to limit the roles. That makes the summary automatically filter results the way you want, but doesn't then try to combine that filter.
Comment #8
kwongkkt commentedLet me make it clear this way.
> When you combine the two, the *intent* is that you get users that contain *all* selected roles.
> Using the contextual filter does not cause the filter to be magically ignored.
You mean I am using "is all of" operator, but I always use "is one of" operator.
One thing to add, when I use "is one of" combined with "select all", why it shows nothing?
> I believe the way to accomplish this task is probably to use two displays.
> One has the base path without the argument, such as 'foo' and
> the other has the base path with the argument, such as 'foo/%'.
I believe, the idea of "summary", means that if I have 6 roles, I do not have to create 6 sub-pages by hand? not to mention when it is always more than that
Comment #9
merlinofchaos commentedNo, they are *two separate filters* which means they are anded together. The contextual filter has no interest in the operator on your filter, and you're assuming magic happens.
Comment #10
merlinofchaos commentedComment #11
kwongkkt commentedHere is the guide to reproduce the BUG, please correct me if you cannot reproduce it
1. in a clean new drupal, i now have 4 roles
2. add one role "dummy", under "admin->people->role"
3. add a new user "dummy-user", assign the role "dummy"
4. go to views, create one view of users
5. add contextual filter "user: roles", select summary
6. add filter "user: roles", select "power user", "administrator"
7. NOTE : "administrator" is last in the list
8. save the view and look at each row in summary
9. "power user" is showing correctly, "admin" is the only user
10. "administrator" shows nothing, where is "root"????
11. now edit this view, in the filter of roles, also select the new role "dummy"
12. NOTE : "dummy" is last in the list
13. save it and see what happens
14. "root" appears now
15. look at the "dummy" role page, it shows nothing
16. to make the "dummy" role page to act normal, repeat through step 1, using new names
Comment #12
merlinofchaos commentedI can reproduce it. The problem is, that's the expected behavior. If you had just done what I had suggested earlier, you'd be done with this now. Instead, you're having a childish argument with me.
So you have a contextual filter and a filter. They are separate filters. They are also both many to one. This is the part that introduces the complication.
When using many to one, each filter has to add a separate JOIN. So the roles table is getting joined in twice. Now, I realize, you're expecting it to add just one join. But it doesn't. The system doesn't work that way.
So what you're doing is creating a filter that on the surface does this:
SELECT fields FROM users WHERE user role is ('administrator', 'dummy') AND role is ('dummy');The problem is, it doesn't do quite exactly that. The reason is, because there are two filters, and it's an AND, the system presumes that you want a user with *two* roles. Therefore, one filter is actually excluding the roles from the other filter. What you really end up with is:
SELECT fields FROM users WHERE user role is ('administrator') AND role is ('dummy');Now, there's a checkbox that says "Allow this to work with other filters." Sadly, that checkbox has had its wording changed in the UI update without checking with me, because it actually only works with other *arguments*. If that checkbox worked with non-contextual filters, checking it would work.
On the other hand, if you do what I suggested earlier, which is to have two page displays, one of them which responds to 'foo' and contains the user: roles filter, and one which responds to 'foo/%' and does NOT contain the contextual filter, you would've had a solution for this already.
Now. Please stop yelling at me that you're right. I respect that you didn't understand why it wasn't a bug because to really understand it you need to understand the whole system, but insisting that you're right and the maintainer is wrong EMPHATICALLY just pisses the maintainer off. Now, I'm done SUPPORT REQUEST.