| Project: | Views |
| Version: | 7.x-3.x-dev |
| Component: | Miscellaneous |
| Category: | feature request |
| Priority: | normal |
| Assigned: | Unassigned |
| Status: | reviewed & tested by the community |
| Issue tags: | views 3.x roadmap |
Issue Summary
A common feature/support request runs along the lines of "How do I filter this fields equivalence to this other field". For example, the most common variant of this is that a user may want all nodes with a CCK field equal to a user's profile field.
We could accomplish this by allowing the 'value' field to have an additional selector. Instead of just the typical value field, we could add all fields that are in the query (we would probably have to except pre_render and non-querying fields since they're pulling data differently) and simply put that fields field_alias into the query.
Obviously, this could not possibly work on exposed filters, but that actually makes it easier. If a filter is not exposed, we could put in a radio button that allows the user to select from fixed value or field. The field shows a select list. It might require some retooling of the existing handlers to allow this but perhaps an alternate query() method would be the easiest way to minimalize the impact on future development.
Comments
#1
tagging
#2
It might require some retooling of the existing handlers to allow this but perhaps an alternate query() method would be the easiest way to minimalize the impact on future development.We could add a if in the query method which calls another function. But this would need a lot of code changes for existing handlers.
So we have to execute it from the view::_build i guess.
To the design of the patch:
The field handlers gets a new method:
field_filter_alias:
return the field alias of the field, to be able to filter later.
returns FALSE if A the definition of the field data has a bit OR if the handler don't want it, for example views_handler_field_prerender_list
not sure yet about this returns TRUE for the admin settings, there might be no field alias at this point.
The filter handler gets new methods and settings:
query_field()
Attaches the query to filter by a field.
new settings: select the field to filter from, this will go over the existing fields of this display and checkwhether it returns a field_filter_alias
Thats it :)
#3
Hmm. What if we add:
<?php/**
* Determine if this field handler can be used to provide a value to filters.
*
* If this returns true, then $this->ensure_my_table() should set $this->field_alias
* which can then be used as a value for comparisons in the WHERE clause.
*/
function is_filter_value() { return TRUE; }
?>
Have this as TRUE by default. Have prerender_list set it to FALSE so that quickly eliminates most of the many to ones. Do a quick scan of other filter objects to see if any of them need to change their value.
#4
Here is a initial hackish version
TODO:
Find out how to call another query method. Currently its a quite hacky bit of code:
function query() {if ($this->options['field_filter']) {
return $this->query_field();
}
Any kind of suggestions are welcomed!
I had to move the build for filters under the build of fields.
#5
thanks
#6
I'll have a look
#7
subscribing
#8
Updating the patch to the latest dev. No other work done on it.
EDIT: There's an extra
dsm()call in there. Sorry!#9
Updated my patch at #8 to handle cases where
views_handler_field::get_field_alias()is called on an uninitialized handler. This happened when using a summary argument action.#10
subscribing
#11
Subscribe
#12
I do not have enough knowledge of the views module to make a relevant review of this patch, so I just tried to write a small module providing such a filter.
If you want to give it a try here it is : http://drupal.org/sandbox/david.fzs/1467698.
#13
subscribing
#14
Just tried david.fzs module in #12 and it work great. You should really just publish it as a full module.
#15
Doing some ticket cleanup - I will echo the sentiment in #14 - this functionality is really helpful in certain use cases and the david.fzs's sandbox module does the trick.
@merlinofchaos - do you think the sandbox code is a candidate for a merge? Seems to be a generalized enough function that it rightly belongs in views as opposed to an add-on module.
Marking needs review since there is working code for this use case that might be a candidate to merge in. Also marking 7.x.
#16
The last submitted patch, 699252-9-field_filter.patch, failed testing.
#17
The sandbox module from david.fzs is perfect! Only the fields that already have been added to the fields are candidates. Perfect! I'm totally using this forever.
@merlinofchaos @dawehner You should just merge this in.
@david.fzs If they don't merge it in, promote it to a full module, like @haydeniv suggests.
#18
@rudierdirkx
You totally get how opensource development works. In general we should first provide a patch against views, not an additional module,
and probably do some automatic testing for this feature, as you never want to break existing working views.
#19
Yeah I get that =) Just saying: his solution is excellent, so let's use that one. No need to create it yourself.
I'll create a patch against 3.x-dev.
#20
Cleaned up code and created a patch against 3.x-dev (f776088). All credits to @david.fzs.
It won't break existing Views, unless another module has defined data/filter
[views][fields_compare]in which case the fields data collection fromhook_views_dataimplementations will be corrupt. An acceptable risk IMO.#21
If you would just not maintain all existing code ... it's really common in drupal to just commit code which is actually working fine.
+++ b/handlers/views_handler_filter_fields_compare.incundefined@@ -0,0 +1,134 @@
+ function can_expose() {
Please use spaces instead of tabs.
+++ b/handlers/views_handler_filter_fields_compare.incundefined@@ -0,0 +1,134 @@
+ * Implements views_object#option_definition().
should be better views_handler_filter::option_definition() or maybe overrides
+++ b/handlers/views_handler_filter_fields_compare.incundefined@@ -0,0 +1,134 @@
+ '!=' => t('Is not equal to'),
Not equal should be probably <> instead.
+++ b/handlers/views_handler_filter_fields_compare.incundefined@@ -0,0 +1,134 @@
+ if ($handler->table != 'views') {
In general we should find a better way to find out whether a field actually maps to a field in the database. This seems to be a dirty hack
+++ b/handlers/views_handler_filter_fields_compare.incundefined@@ -0,0 +1,134 @@
+ $handlers = $this->view->display_handler->get_handlers('field');
+ if (!isset($handlers[$left], $handlers[$right])) {
+ return;
We should probably document what this code is doing.
+++ b/handlers/views_handler_filter_fields_compare.incundefined@@ -0,0 +1,134 @@
+ $left_handler->set_relationship();
+ $left_table_alias = $this->query->ensure_table($left_handler->table, $left_handler->relationship);
...
+ $right_handler = $handlers[$right];
+ $right_handler->set_relationship();
+ $right_table_alias = $this->query->ensure_table($right_handler->table, $right_handler->relationship);
Can't we use $left_handler->table_alias directly?
#22
I don't know what this means:
I've updated the patch:
views_handler_filterin this case). Most Views classes and methods don't do this though...!=to<>.field,real_field,tableetc don't mean anything untilhandler->query()is executed. I'm all for a better way (like adding ais_db_field()method to all handlers), but since there isn't any now... Something to think about for D8.$left_handler->table_aliasis empty at that point... Don't know why. After$this->query->ensure_table(...)it's still empty btw. Not connaisseur enough.#23
#24
Am I safe to apply this patch to my current views? Or has it been committed yet?
Thanks
#25
Just applied patch...works excellent...LOVE!
#26
Did this patch make into latest dev dated Oct 6?
#27
Patch doesn't seem to work with date fields - unless I have something set wrong. Here's the query - (field_data_field_date_criteria.field_date_criteria_value > users_flagging.created)
I'm trying to compare a date type node field to the date a user was created. If I choose less than, all user's are showed. If I choose greater than, none are showed.
#28
That's probably because
field_data_field_date_criteria.field_date_criteria_valueandusers_flagging.createdhave different formats.field_date_criteria_valueis probably a full datetime.createdis a timestamp (int).#29
Sounds correct. Is there a way to compare with formats? I ran into this again yesterday - tried to compare a custom user field (tried decimal, integer, text) to a geocoded field. The geocode filed outputs miles or km in distance....but I assume this is just a format and your patch compares raw values? Is this correct?
I also tried to create a math field in views, multiply the miles by *1 and the compare math field to my custom field, but math filed wasn't an option for comparisons. It sounds like I'm wanting to compare formatted values not raw, and your code is for raw?
Thank you
#30
FIXED
I apologize for my dumbness, but once the patch is applied, in the UI where do I find the options to make the comparison?
EDIT: I found the "global field comparison", now I have to understand why it says the handler is missing
EDIT 2: run update.php and way fine : )
#31
@IWasBornToWin Yes, this patch compares raw values. Directly from the database. (Inside the database even.) There's also no way to reformat pre-comparison on the fly. That would require a query alter.
In case of date fields: if you always want to compare timestamps (int), you can create your date fields with that format. Date fields have 3 available formats I think.
About the patch: can someone test, review, verify & change status to rtbc?
#32
patch works good.
#33
There is an issue with pulling the fields through a separate sql query. This renders fields that are calculated in the view field after the initial query to throw an error. It would be better if the addition pulled the data value from the $row->data directly..
For example lets say you allow a user to view a gambit x number of times. Well the gambit only stores a value of the max number of views allowed. The field times viewed would effectively query the user and calculate how many times a user has viewed gambit. In this case, pulling the value from the row output would render the intended result. Under the current approach, you would get the following:
<?phpSQLSTATE[42S22]: Column not found: 1054 Unknown column 'gambit.times_viewed' in 'where clause'
?>
#34
@JMOmandown What you want is even more advanced and could be seen as an edge case. I think the last patch handles most of the cases, which would be a great improvement. You could create another comparison field for more advanced comparisons. Agree? Disagree?
#35
While I do agree that it would require a great deal of structure change that arguably may not be worth the use case coverage, I don't think it is as far an edge case as you think. Comparing a value against a calculated value is pretty common among modules and would be as well among views if available.
The last patch does provide significant improvement! I may later, when I get sufficient time, delve into creating another comparison field for comparisons that steal the value from the view output and then filter (via ajax maybe) or at least a custom module as a place to start for others. However, I figured I'd bring up the procedural issue to you, who is much more familiar to the module, in case I was missing something.
#36
@JMOmandown You mean the path from #22? Still all credits to @david.fzs, who created the module.
So, does is still need work?
#37
Hi guys,
I'm trying to achieve the same thing, only that the left field is not being pulled from the database but rather is calculated based on some user input in an exposed views filter. Could someone tell me, theoretically, what I would have to do to achieve this.....
Thanks!
EDIT: Or i guess my question should be...how can I ignore the query process and do arbitrary calculations with the results of the left and right fields?
#38
@el_toro You'll need
hook_query_alter()orhook_views_query_alter()to add custom conditions. Do aget_class($query)to look up what methods it has in the api.#39
Hi rudiedirkx, thanks for the quick response.
Now being naive to the ways of views, this is how I'm expecting this to work.
1. I have the filter exposed with grouped filters.
2. When I set $this->value['value'] = $x; I'm expecting that the numerical field will be evaluated against $x and if the condition (e.g. > 5) is not satisfied then the row will be removed from the results.
Am I totally in the wrong domain here, in trying to achieve what I want?
EDIT: support request and code moved here http://drupal.org/node/1972146
#40
@el_toro This isn't the issue/thread/place for a support request like that. This issue is about a db field comparison filter. You should create a new issue (and remove the code in your last comment). You can send me the link so we can talk about it there.
#41
I assume this patch has never been committed to views? If I want to use latest version of views I need to reinstall patch after updating to latest views?
#42
This patch is currently marked 'needs work' meaning that the community has deemed it not ready to be committed. This it not only hasn't been committed, but it won't be committed until someone is able to fix the patch (or remove the blocker that had it called needs work). The last move to needs work was in #33, so you should read that and the following comments to see what still needs to be done.
#43
Thanks, I have zero knowledge on "fixing patches". Can I update to latest views and then reinstall the current patch that is working for me?
#44
What @JMOmandown requested was too edge case and since @IWasBornToWin rtbc'ed it before, it's now rtbc again. Patch in #22 should work fine.