(Maybe that's on the TODO already)

Currently field modules can only specify the 'operator' key of the 'filter' array for views integration.

There are numerous other useful keys for filters ('list', 'list-type', 'value-type', 'option', ...), probably too many to dedicate one op in hook_field_settings for each one of them, as it is currently done for 'operator'

My idea would be to have a single 'filter' op in hook_field_settings, that would return an array of all the required key / value pairs, which would then be merged with the 'name' key generated in content_views_tables.

Someting like (roughly) :

function content_views_tables() {
(...)
  $filter = module_invoke($module, 'field_settings', 'filter', $field);
  $name = array('name' => $field_types[$field['type']]['label'] .': '. $field['widget']['label'] .' ('. $field['field_name'] .')');
  $table['filters'][$main_column['column']] = array_merge($filter, $name):
(...)
}

I can probably provide the corresponding patch (and adapt existing field modules).
I'd like to get opinions about that approach beforehands, though...

Comments

yched’s picture

Status: Active » Needs review
StatusFileSize
new3.21 KB

Well, I needed it, so I went for it...

This patches content.module, and the fields modules that currently implement 'filter operators' (namely text and number)

Maybe this is not the approach JonBob had in mind for the yet-to-come full-fledged views integration.
At least this patch might be a temporary means for some people to have advanced filter features for cck fields, until the "official" implementation comes.

karens’s picture

I've been looking at this, too, but haven't had time to completely follow up on it. I'm trying to figure out if we have support for the standard views operators and handlers, which would be very handy. For instance I submitted a patch to views that created a re-usable operator and handler for LIKE queries (see the discussion at http://drupal.org/node/58245). The patch has been committed now and it allows you to say that the views operator is 'views_handler_operator_like' and the filter is 'views_handler_filter_like', then you get a whole gamut of 'contains', 'starts with', 'ends with', etc behavior for the view. There are a whole list of other pre-defined operators and filters for various equals, not equals, etc. operations. You can see them all at the end of the views.module code.

What I haven't been able to figure out yet is whether the current cck method of handling views will allow you to select those operators and filters. If not, it would probably be a desirable behavior.

yched’s picture

StatusFileSize
new1.25 KB

Re-rolled against current cvs

Sorry Karen, I missed your answer here.

I think this patch provides exactly what you're talking about : a field module can provide all the filter settings allowed by Views, thus including pre-defined operators and handlers.

You just have to include in hook_field_setting something like

case 'filter':
      return array(
        'operator' => 'views_handler_operator_gtlt',
        'value' => views_handler_filter_date_value_form(),
        'handler' => 'views_handler_filter_timestamp',
        'option' => 'string',
      );

It's been working on a pre-production site for about a month now, and everything looks fine.

karens’s picture

This is exactly what I was thinking about. Just one problem for my purposes, you are limited to one filter per field type and sometimes you want more than one. For instance, in the nodereference field I want to offer a way to filter by the nid, the title, and maybe by the node type, so I would need to define 3 filters.

Do you think you could adapt to that possibility? I know that screws up the filter name, so maybe each extra filter defines something to append to the name to clarify it -- Nodereference: My Field Name (by title)

karens’s picture

Now that I look at it, to filter by nodereference title I'm probably going to need add another table join, which can't be done without another patch. Well, it would still be useful to define multiple filters. We can worry about table joins another day...

yched’s picture

StatusFileSize
new3.63 KB

OK, I gave it a shot.

The included patch supports multiple filters for each field.
field modules can declare their filters in hook_field_setting ($op == 'filters"), by returning something like :

case 'filters':
  return array(
    'default' => array(
      'operator' => array(
        '=' => t('is equal to'),
        '!=' => t('is not equal to'),
        'LIKE' => t('matches the pattern'),
      'handler' => ... ,
      ),
    ),
    'other' => array(
      'operator' => array(
        '=' => t('is equal to'),
        '!=' => t('is not equal to'),
        'LIKE' => t('matches the pattern'),
      'handler' => ... ,
      'option' => ... ,
      'value' => ... ,
      ),
    ),
  );

The naming conventions are actually a little bit of an issue.
"Human readable" names (the ones you see when you select your filters in the views UI) are generated this way :
Field Type : Field Label - the filter key (Field Name)
(the bold part is the difference with cvs currently generated names)
except for the filter with the key 'default', for which the key string is not inserted
(this is an attempt to reduce cluttering, espacially for the field types that will only declare one filter)

Reviews are much welcome, as well as advice from views gurus
(@dopry : I don't know if you're one of those, but you did a neat job with views arguments in cck - do you have an opinion about this ?)

karens’s picture

I think this is working fine, at least for the things I have tried so far. Thanks for this, it will add a lot of flexibility to cck views.

Now I need to see how best to use it in the nodereference field...

karens’s picture

Just wanted to report that I have been using this patch and it is working fine. I think it's really important to get this applied because many fields will need more flexibility in the way they handle filtering (date fields and fields with multiple options, for instance.)

+1 on getting this committed.

moshe weitzman’s picture

Status: Needs review » Reviewed & tested by the community

just moving this along since it has seen proper positive review. feel free to move it back if it isn't ready for some reason.

magnestyuk’s picture

I don't get it. I followed the example in #6 and added to text.module after 'default':

    'other' => array(
          'operator' => 'views_handler_operator_like',
          'handler' => 'views_handler_filter_like',
      ),

I don't really understand what should go in place of 'other', but the exposed filter, when searched, throws sql errors:

1. for fields that have their separate table, unknown column in where clause:
'node_data_field_mycustomfield1.field_mycustomfield1_value_other'
the table exists, but the column does not. nor does any column with the name 'field_mycustomfield1_value_[anything]'

2. for fields whose values are stored in the content type table, unknown column in where clause:
'node_data_field_mycustomfield2.field_mycustomfield2_value_other'
the table does not exist, because mycustomfield2 does not have its own table.

am I doing something wrong?

thanks for any help.

karens’s picture

Hopefully this is a needless question, but you did make the change to the content module, too, right?

I think you may be missing a join. If you add a filter for a field that does not exist in the view, you will get messages like this. Try adding the field you are filtering on as a field in the view.

If that is not the problem, reply with a copy of the complete sql error message and a copy of the view you have created (you can get the copy of the view from an export).

karens’s picture

Also, don't worry about the fact that the table names look wrong. CCK has to use psuedo names because the table names can change.

magnestyuk’s picture

yes, I patched content.module as well, with the patch in #6. I've just done a clean test with only one custom field, made a view with node title and the cck field as fields, and also as expopsed filters. No change. The error message goes like this:

Warning: Unknown column 'node_data_field_mytextfield.field_mytextfield_value_mykey' in 'where clause' query: SELECT node.nid, node.title AS node_title, node.changed AS node_changed, node_data_field_mytextfield.field_mytextfield_value AS node_data_field_mytextfield_field_mytextfield_value, node_data_field_mytextfield.field_mytextfield_format AS node_data_field_mytextfield_field_mytextfield_format FROM node node LEFT JOIN node_content_mytype node_data_field_mytextfield ON node.vid = node_data_field_mytextfield.vid WHERE (UPPER(node.title) LIKE UPPER('%kis%')) AND (UPPER(node_data_field_mytextfield.field_mytextfield_value_mykey) LIKE UPPER('%meg%')) AND (node.type IN ('content-mytype')) LIMIT 0, 15 in /var/www/test/includes/database.mysql.inc on line 120

and my view is:

  $view = new stdClass();
  $view->name = 'myview';
  $view->description = 'myview1';
  $view->access = array (
  0 => '3',
);
  $view->view_args_php = '';
  $view->page = TRUE;
  $view->page_title = 'myview';
  $view->page_header = '';
  $view->page_header_format = '1';
  $view->page_footer = '';
  $view->page_footer_format = '1';
  $view->page_empty = '';
  $view->page_empty_format = '1';
  $view->page_type = 'table';
  $view->url = 'myview';
  $view->use_pager = FALSE;
  $view->nodes_per_page = '15';
  $view->sort = array (
  );
  $view->argument = array (
  );
  $view->field = array (
    array (
      'tablename' => 'node',
      'field' => 'title',
      'label' => 'title',
      'handler' => 'views_handler_field_nodelink',
    ),
    array (
      'tablename' => 'node_data_field_mytextfield',
      'field' => 'field_mytextfield_value',
      'label' => 'mytextfield',
    ),
  );
  $view->filter = array (
    array (
      'tablename' => 'node',
      'field' => 'title',
      'operator' => '=',
      'options' => '',
      'value' => '',
    ),
    array (
      'tablename' => 'node_data_field_mytextfield',
      'field' => 'field_mytextfield_value_mykey',
      'operator' => '=',
      'options' => '',
      'value' => '',
    ),
    array (
      'tablename' => 'node',
      'field' => 'type',
      'operator' => 'OR',
      'options' => '',
      'value' => array (
  0 => 'content-mytype',
),
    ),
  );
  $view->exposed_filter = array (
    array (
      'tablename' => 'node',
      'field' => 'title',
      'label' => 'title',
      'optional' => 1,
      'is_default' => 0,
      'operator' => 0,
      'single' => 0,
    ),
    array (
      'tablename' => 'node_data_field_mytextfield',
      'field' => 'field_mytextfield_value_mykey',
      'label' => 'mytextfield',
      'optional' => 1,
      'is_default' => 0,
      'operator' => 0,
      'single' => 0,
    ),
  );
  $view->requires = array(node, node_data_field_mytextfield);
  $views[$view->name] = $view;
magnestyuk’s picture

ok, I noticed that my node type filter was not in the view as a field so I added it now, but nothing's changed.
(by the way, using latest cvs views+cck)

yched’s picture

In fact I did encounter a similar problem using one of the views "built-in" filter handlers (in my case it was views_handler_filter_timestamp).

I _think_ this is a problem in the filter functions themselves, not properly taking into account cck's aliases for fields. I'm not sure though whether this is not rather my patch's fault...

I'm about to submit an issue to views about that - and maybe get merlin's opinion about this patch as well ?

magnestyuk’s picture

bad news, but thanks for saying it's not only me...
this search functionality is the one thing that's left to complete a job I'm doing, so I'm ready to do testing, reports and stuff, but I can't code :(

yched’s picture

OK, I submitted a patch for the views filter handlers - you can follow that here.

@suppasonic : maybe you could test it and see if it solves the issue for views_handler_filter_like ?
(and post a review over there ?)
NB : make sure you empty your cache after patching :-)

moshe weitzman’s picture

I have a need for this. Specifically, this paves the way for CCK text fields and number fields to show a dropdown in their exposed filters section. The options in the dropdown should match the options setup in the field instance definition. yched - perhaps you could exhance text,module as described as an example of this new feature. i was a bit confused about 'other' just like suppasonic is. an exampe would document usage well and prove the capability.

This has been RTBC for a bit now. Some feedback from a CCK or Views Maintainer would be nice.

yched’s picture

StatusFileSize
new2.78 KB

@suppasonic : I've updated the patch for views.module.
It should now allow this cck-filters patch to work well with views built-in filter handlers.

@moshe : Yes, I probably should do that. Maybe tomorrow ?

And yes, this patch desperatly needs review from JonBob and / or Merlin.
And yes, it seems this functionnality is needed by quite a few people now.
Please ? Are you there ? :-)

yched’s picture

StatusFileSize
new3.64 KB

OK, here's an updated version of the patch
It does exactly the same thing, except for the cosmetic part (human-readable designation of the filters in the filter selection drop-down)
See my next post for more info about that.

This patch also updates the field modules that currently implement views filters (simple update, no enhanced filter definition - that will need dedicated patches when this one gets committed)

As moshe suggested, the next post will contain an example of an enhanced text.module using the extended filter functionnalities the patch provides.

yched’s picture

StatusFileSize
new917 bytes

Here's an example of an enhanced text.module using the views filter patch.
(I stress "example" here, it does not try to be relevant, and is in no way a proposition for the text.module...)
Since it uses views.module predefined filter handlers, it requires this patch as well.

NB : after applying these patches, be sure to empty your cache AND re-save your views to have the changes taken into account.

Below is the important part (in function text_field_settings) :

    case 'filters':
      return array(
        'substring' => array(
          'operator' => 'views_handler_operator_like',
          'handler' => 'views_handler_filter_like',
        ),
        'alpha' => array(
          'name' => 'alphabetical order',
          'operator' => 'views_handler_operator_gtlt',
        ),
      );

This defines two filters for text fields : the first one allows 'LIKE'-style criterions, and the other allows 'alphabetically greater/lesser than'-style criterions (probably dumb (?), but I had to find a second one...).

Any filter parameter allowed by views API ('value', 'option', I'm not aware of all of them... see views API docs ;-) ) can be used, except 'field', that will anyway get overriden by content.module.

Since the patch allows for several filters for a given field, the "tricky" part is naming them, so that the user can choose...
It works this way :

  • if only one filter is defined, no need for cruft, we keep the naming convention CCK currently uses :
    [field_type] : [field_label] ([type_name])
    for instance "Text : color (colored node)"
  • if we have several filters (like in this example), the text given as the 'name' param is inserted (if none, the key value of the filter is used) :
    [field_type] : [field_label] - [filter_name] ([type_name])
    for instance "Text : color - substring (colored node)"
    or "Text : color - alphabetical order (colored node)"

Hope that makes sense :-) Longest post in my life, anyway - am I being wordy ?

merlinofchaos’s picture

Tagging so I can follow this.

magnestyuk’s picture

@yched: thanks for continuing to work on this. I applied your patches and now everything works with no errors.

@moshe: in #18, maybe you're referring to what I would also like to see:
in exposed filters for select/check box/radio button fields, the user should be able to choose from a dropdown that is populated by the values of those fields, something like what taxonomy's exposed filters can do. this cannot be currently done with cck fields, right? now a user must manually enter a search term but does not know which values are indeed available. compare that to how an exposed taxonomy filter or an exposed node type filter works.
this one would probably need a custom operator/handler, not available in views.module...

karens’s picture

If this patch gets committed, a patch to the optionwidgets module can create a handler to populate a drop-down list of available options. I don't think any changes to the views module will be needed. We just need this patch committed...

karens’s picture

I decided to take a look at what would be needed to get the drop-down list working and it is going to be a bit more complicated than I originally thought and will need a patch to text and number modules, since widgets don't have any views handling options. I just wanted to clear that up in case anyone wants to work on a patch for that, but it doesn't change the fact that it will still require that this patch get committed since a custom handler will be needed.

karens’s picture

I don't want to impede getting this patch committed by getting into discussions about how to get drop-down lists working, so I've bumped another issue on that topic (http://drupal.org/node/63690) and we can move the drop-down list patch discussion over there...

RayZ’s picture

Is there something more that needs to be done to get this patch committed? It's been marked RTBC for quite a while.

yched’s picture

I think all it needs is JonBob's review and / or commit - he seems to be around again these days (cvs commits).

JonBob, if you hear this :-)

jonbob’s picture

Status: Reviewed & tested by the community » Fixed

Committed.

yched’s picture

Status: Fixed » Needs review
StatusFileSize
new2.4 KB

Great ! Thanks !

Reopening just to provide the matching update for field.php.
Please feel free to correct the wording...

Side note : do you plan a 4.7 backport ?

yched’s picture

Oops, sorry, this was in fact backported ...

jonbob’s picture

Status: Needs review » Fixed

Committed (both branches).

Anonymous’s picture

Status: Fixed » Closed (fixed)