I'd like a way to alter the options of a handler. For instance a Field might have an extra access option, or a Filter an extra condition.

The logic to use the option is doable in other views hooks, like hook_views_query_alter() or hook_views_pre_build(), for any module, but an outside module can't add options to the Field or Filter handler.

Views very cleverly uses option_definition() to clean up handler options before saving, and when exporting, but this means handlers aren't extensible.

My solution is very simple: add an option_definition alter to allow any module to add options, or change defaults.

Adding form, validate and submit alters aren't even necessary, because the outside module can do that with normal form alters.

Members fund testing for the Drupal project. Drupal Association Learn more

Comments

rudiedirkx created an issue. See original summary.

rudiedirkx’s picture

Status: Active » Needs review
FileSize
2.11 KB

Patch adds a method altered_option_definition() to wrap around option_definition() to alter the result. Since it's executed for handlers and plugins, it calls 2 different alters:

  • views_plugin_option_definition
  • views_handler_option_definition

Since it's to high up in the Views process, not much changes.

I ran a few performance tests and on big views, or pages with several views, the total time spent altering (with 0 implementations) is 1.5 ms.

flaviovs’s picture

Do you have any pointers about how this is a standard idiom to alter views handlers options? Any other module doing this?

IMHO, the right way to do this would be to use hook_views_data_alter() to plug in your our handler, which would be a subclass of the handler with the method(s) you want to override. In this specific case, you would override the option_definition().

This requires no patch. And it's plain simple, effective, and elegant, isn't?

rudiedirkx’s picture

I don't know of any other module needing this, but I've needed it a few times in different projects. Sometimes it could be solved with a Display Extender, sometimes with a new Field/Filter handler etc. It was always easier to add options. This time I went for it.

Your solution is very elegant, and correct, but there are SOOO many handlers, I can't override them all, and that's exactly what I want. In this case I want to add an access fieldset & options to all fields and filters, to hide/disable them for different users & context.

It's also a good way to change views defaults, see #1244576: Consider allowing configuration of the default options for field handlers.

rudiedirkx’s picture

Project: Views image » Views
Version: » 7.x-3.x-dev

Crap. I didn't mean Views image, I meant Views.

flaviovs’s picture

:-)

BTW, one thing that came to mind: what's the purpose of altering option_definition() only?

I mean, OK, you'll be able to add options here and there, and now what? How do you process them? How do you make them useful?

You'd need to alter other methods, don't you?

I still think that sub-classing a handler is the API-wise way to go.

rudiedirkx’s picture

The rest of the methods, you can form-alter and views-hook. I've used it in Views Arguments for adding access options to all Fields and Filters, using a normal form alter. Then in hook_views_pre_build I use those options. Because they're real options, they have defaults and are exported and imported. You can't add options without option_definition.

It'd be very very nice if there were such a thing as Display Extender for all handlers. Maybe Field Extender or Handler Extender.

Sub classing is impossible. I need ALL handlers, including all contrib etc.

rudiedirkx’s picture

It would be much nicer to have hooks for the form/validate/submit too though... What I do now is

  1. hook_form_views_ui_config_item_form_alter() extends form and adds #element_validate
  2. #element_validate validates and rewrites values and saves it back info $form_state

See http://cgit.drupalcode.org/views_arguments/tree/views_arguments.module?h...

The access plugin is much cleaner, using options_form(), options_validate() and options_submit()

See http://cgit.drupalcode.org/views_arguments/tree/views/views_arguments_pl...

MustangGB’s picture

Status: Needs review » Reviewed & tested by the community

I encountered the same issue, needing to extend every single field handler to add a new option to the base class seems like lunacy, especially considering that everything else, excluding option_definition(), can be hooked.

Patch does the job advertised perfectly.

DamienMcKenna’s picture

Status: Reviewed & tested by the community » Needs work

This needs an update to views.api.php.

MustangGB’s picture

Status: Needs work » Needs review
FileSize
4.3 KB

So I don't profess to being that great at writing docs, but I gave it a go.

rudiedirkx’s picture

Status: Needs review » Needs work

I like it. If you add some @param and @return it's perfect IMO. And maybe a more realistic example in the hook itself. Maybe something that illustrates the difference between a plugin and a handler.

MustangGB’s picture

If you add some @param and @return it's perfect IMO.

I've added @param, but as alter functions don't return anything I don't think @return is needed.

And maybe a more realistic example in the hook itself. Maybe something that illustrates the difference between a plugin and a handler.

Suggestions on a postcard please, the example is almost exactly what I'm using for my use-case.

rudiedirkx’s picture

Status: Needs work » Reviewed & tested by the community

I don't know a good example =) I like it. Maybe @DamienMcKenna will like it too.

DamienMcKenna’s picture

Status: Reviewed & tested by the community » Needs work

One very minor thing, altered_option_definition() needs an explanation of its @return.

MustangGB’s picture

Status: Needs work » Needs review
FileSize
4.9 KB

Updated block comment for altered_option_definition().

MustangGB’s picture

Waiting for DamienMcKenna's review, in the meantime adding to #2866162: Plan for Views 7.x-3.18 release so it doesn't get lost/forgotten.

MustangGB’s picture

DamienMcKenna’s picture

FileSize
5.21 KB
804 bytes

A minor change to more clearly indicate what hooks are being called.

DamienMcKenna’s picture

I looked around to see if this might inadvertently introduce API changes. I noticed that set_default_options() is also referenced in ViewsUiBaseViewsWizard, does that method need to made aware of the hooks too?

MustangGB’s picture

ViewsUiBaseViewsWizard::set_default_options() isn't calling option_definition(), so it shouldn't care about these changes I'd believe.

DamienMcKenna’s picture

Also ViewsUiBaseViewsWizard doesn't extend views_object so the former's instance of set_default_options() isn't overriding the latter's.

DamienMcKenna’s picture

One concern I have is that modules will need to update to support the new method because they override one of the methods being modified. Right now I only see better_exposed_filters with an overridden unpack_options(), but there could be custom code to content with. This might benefit from a changenotice.

DamienMcKenna’s picture

Removing this from the 3.18 release just so we can get it out the door, but we'll look to add it to the next release.

MustangGB’s picture

Well of course adding support for the new method for other modules is optional, hence why altered_option_definition() was done as an addition to option_definition().

I looked at "Better Exposed Filters" overridden unpack_options() and it also isn't calling option_definition(), so not sure why it would be effected by this issue.

Also what is the policy regarding change notices, as far as I know this shouldn't hold up inclusion of the feature in a release, at least this is how change notices for "Drupal core" have been treated, see: Outstanding D8 views change notices