Small help/guidance on working with features

We encourage users to post events happening in the community to the community events group on https://www.drupal.org.
hanoii's picture

I am i the need/will to start using features on my general development practice. This was long due and I found a nice project to really start using it but although I think I already learnt most of it, I am having some issues understanding or knowing what's the best way of working with them.

Because panopoly uses features extensively, I thought this might be a nice group to look for some specific guidance on how to achieve certain things.

Basically I can see how features are very nice with a lot of really hard configurations, like content types, fields, etc.. but it falls a bit short (at least at first) when it comes to specific configurations that are likely to change in dev/stage/production.

I have a project that uses a lot of services/wsclient/rules to both expose an API and being a client of a web service. All of those modules can be exported by features, however, all of them has some details that are definitely going to change in the dev/staging/production site. (i.e. wsclient URL, rules actions that will held different values, etc.). Exporting all of this with features and changing them on the dev/staging/prod sites will make the features always overridden and prone to be reverted.

What's the best way of work with those kind of things? I thought of a number of ways, I could use some global token in rules and have a module expose those tokens and make that configurable, but this will only work for rules, not wsclient or services config. Features override could be another option but it's definitely not playing nice with rules overrides at all - https://www.drupal.org/node/1957886. Defaultconfig might be another option but it's not working that good with rules or the other modules.

Anyway, I am sure here you must have faced something similar in a lot of projects so I wonder if you have a nice solution for something like this.

Thanks,
Ariel.=

Comments

dsnopek's picture

There's a couple of options for safely overriding Features (so they aren't marked as overridden).

The first one (which you've identified) is using Features Override. The main advantage with Features Override, is that it doesn't involve writing any code (it does it for you!) so site builders can do it. It also doesn't require "baking in" any special support for making something easy to override, you can use Features Override on anything - even stuff the original Features author didn't intend you to.

Defaultconfig is also a possibility for really simple Features components, like variables (strongarm) and permissions. But, yeah, like you mentioned it has trouble with more complex components like Panels and apparently Rules (although, I've never personally tried it).

Anyway, in your situation, you're basically expecting users to ALWAYS override these particular aspects of these Features. And you probably don't necessarily want to force the user who is making this change to learn to use the Rules and other complex UIs to do it.

So, here's the approach I'd recommend (which we use in Panopoly in a couple places):

  1. Manually write the hook_*_default_*_alter() hook for the thing you're going to override (this is the same hook that'd be written by Features Override). For example, for Field Instances, this hook is hook_field_default_field_instances_alter(). Usually, you can just take the hook Features used, and add _alter() to it, but you might have to look it up if it has a non-standard name. Anyway, in this hook, replace the thing you want users to be able to change with the value a Drupal variable (ie. variable_get(...)).
  2. Create an admin page with a form which allows users to change the value of this variable. Your form submit handler will need to revert the Feature (or otherwise update the data directly) in order for it to take effect immediately. So, to continue with the Field Instance example, after doing the variable_set(...), you'll have to do features_revert(array('original_feature' => array('field_instance')).

We do a variation on this in at least two places in Panopoly that I can think of:

  • panopoly_widgets: For setting the File widgets allowed extensions without overridding the Feature or forcing the user to use the Field UI admin pages.
  • panopoly_search: Allowing the SOLR and Database indexes and servers to be enabled or disabled without the Feature becoming overridden.

So, you can check out the code we used in those modules as an example!

I hope that helps. :-)

I recently wrote a Blog on

mpotter's picture

I recently wrote a Blog on this exact topic: http://www.phase2technology.com/blog/how-to-override-features/ . It gives the Pros/Cons of various override methods.

If Features Override doesn't work well with a particular module it would be good to post in their issue queue to see if they can improve it. All Features Override does is generate those hook_default_alter() functions that dsnopek mentions. So if the module doesn't work with Features Override it's probably not going to work with those alter hooks either and should be improved to handle the alter hooks better.