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.
Comment | File | Size | Author |
---|---|---|---|
#27 | views-n2610418-27.patch | 5.16 KB | DamienMcKenna |
|
Comments
Comment #2
rudiedirkx CreditAttribution: rudiedirkx commentedPatch adds a method
altered_option_definition()
to wrap aroundoption_definition()
to alter the result. Since it's executed for handlers and plugins, it calls 2 different alters: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.
Comment #3
flaviovs CreditAttribution: flaviovs commentedDo 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 theoption_definition()
.This requires no patch. And it's plain simple, effective, and elegant, isn't?
Comment #4
rudiedirkx CreditAttribution: rudiedirkx commentedI 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.
Comment #5
rudiedirkx CreditAttribution: rudiedirkx commentedCrap. I didn't mean Views image, I meant Views.
Comment #6
flaviovs CreditAttribution: flaviovs commented:-)
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.
Comment #7
rudiedirkx CreditAttribution: rudiedirkx commentedThe 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.
Comment #8
rudiedirkx CreditAttribution: rudiedirkx commentedIt would be much nicer to have hooks for the form/validate/submit too though... What I do now is
hook_form_views_ui_config_item_form_alter()
extends form and adds#element_validate
#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()
andoptions_submit()
See http://cgit.drupalcode.org/views_arguments/tree/views/views_arguments_pl...
Comment #9
MustangGB CreditAttribution: MustangGB commentedI 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.
Comment #10
DamienMcKennaThis needs an update to views.api.php.
Comment #11
MustangGB CreditAttribution: MustangGB commentedSo I don't profess to being that great at writing docs, but I gave it a go.
Comment #12
rudiedirkx CreditAttribution: rudiedirkx commentedI 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.Comment #13
MustangGB CreditAttribution: MustangGB commentedI've added
@param
, but as alter functions don't return anything I don't think@return
is needed.Suggestions on a postcard please, the example is almost exactly what I'm using for my use-case.
Comment #14
rudiedirkx CreditAttribution: rudiedirkx commentedI don't know a good example =) I like it. Maybe @DamienMcKenna will like it too.
Comment #15
DamienMcKennaOne very minor thing, altered_option_definition() needs an explanation of its @return.
Comment #16
MustangGB CreditAttribution: MustangGB commentedUpdated block comment for altered_option_definition().
Comment #17
MustangGB CreditAttribution: MustangGB commentedWaiting 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.
Comment #18
MustangGB CreditAttribution: MustangGB commentedComment #19
DamienMcKennaA minor change to more clearly indicate what hooks are being called.
Comment #20
DamienMcKennaI 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?
Comment #21
MustangGB CreditAttribution: MustangGB commentedViewsUiBaseViewsWizard::set_default_options()
isn't callingoption_definition()
, so it shouldn't care about these changes I'd believe.Comment #22
DamienMcKennaAlso ViewsUiBaseViewsWizard doesn't extend views_object so the former's instance of set_default_options() isn't overriding the latter's.
Comment #23
DamienMcKennaOne 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.
Comment #24
DamienMcKennaRemoving 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.
Comment #25
MustangGB CreditAttribution: MustangGB commentedWell of course adding support for the new method for other modules is optional, hence why
altered_option_definition()
was done as an addition tooption_definition()
.I looked at "Better Exposed Filters" overridden
unpack_options()
and it also isn't callingoption_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
Comment #26
DamienMcKennaI've started a changenotice, please take a look and help improve it: https://www.drupal.org/node/2928637
This needs to be rerolled.
Comment #27
DamienMcKennaRerolled.
Comment #29
DamienMcKennaCommitted, thanks everyone!
Comment #30
MustangGB CreditAttribution: MustangGB commentedThanks.