I may be missing something here, so apologies if this is an option I just haven't found.

Problem/Motivation

When a Feature module is reverted, no hooks are invoked on that module. hook_features_revert() is invoked on the components contained within that Feature module, but nothing on the Feature is called.

Let me explain my current use case to give you an example of how I would like to use this. I'm upgrading an existing D6 site to D7. Some of the stuff in the D6 site config was rolled into Features for D7, such as an events module that contains the Event node type, some views, menu items, etc. However, I need to move a menu item (User Group Meetups, lets say) underneath the Events menu item that's added by the View. Until the Feature module is enabled and reverted, that Events menu item doesn't exist in the DB, so I can't move the pre-existing (from D6) User Group Meetups menu item because there is no mlid from the Events menu item to use as the parent ID (plid) on the User Group Meetups menu item.

I sure hope that makes some kind of sense.

Proposed resolution

This problem and many others could be solved by invoking some hooks on the Feature module itself when actions are taken on it. _features_restore() runs revert, rebuild, enable, and disable, so it would make sense to invoke these hooks there.

foreach ($items as $module_name => $components) {
  // Invoke pre hook
  $pre_hook = 'pre_' . $restore_hook;
  module_invoke($module_name, $pre_hook);

  foreach ($components as $component) {
    // ...yadda yadda yadda
  }
  
  // Invoke post hook
  $post_hook = 'post_' . $restore_hook;
  module_invoke($module_name, $post_hook);
}

This would make the following hooks available on Features modules only:

  • hook_pre_features_revert()
  • hook_pre_features_rebuild()
  • hook_pre_features_disable_feature()
  • hook_pre_features_enable_feature()
  • hook_post_features_revert()
  • hook_post_features_rebuild()
  • hook_post_features_disable_feature()
  • hook_post_features_enable_feature()

Remaining tasks

  • Determine if this can already be done and I've managed to overlook it.
  • Determine if these hooks should take any arguments.
  • Implement the hook invokations that I sort of coded in the block above, and make sure they work. If so, roll them into a patch for community testing.

User interface changes

None

API changes

Eight new hooks available to module developers, listed above.

Comments

davidburns’s picture

I support this decision! +1

BrockBoland’s picture

StatusFileSize
new2.57 KB

First pass attached. This adds the hooks I mentioned above and API documentation for them.

BrockBoland’s picture

This might not work after all. Running drush fra results in calling _features_restore() once for each component, so the revert hooks would fire for every component, which is not what I had in mind.

But, this might be OK: move the module_invoke() inside of the foreach ($components as $component) loop, and pass the $component to these new hooks as an argument. Not quite what I was going for, but it could do the job.

BrockBoland’s picture

StatusFileSize
new3.59 KB

Updated to move the call inside the loop, and add the $component to the API documentation.

mpotter’s picture

Status: Active » Needs review
hefox’s picture

Looking at the patch quickly but not actually reading the issue, I've wanted something like this at some point

Related/semi-duplicate of reallylongissue #981248: Allow a feature to execute a secondary install function after features components are created ?

BrockBoland’s picture

Yeah, that is pretty similar (though to be honest I only looked at the patch and didn't read the discussion)

mpotter’s picture

Status: Needs review » Reviewed & tested by the community

The patch in #4 seems to be working for me.

mpotter’s picture

Status: Reviewed & tested by the community » Fixed

Committed to ce3863e!

MarcElbichon’s picture

StatusFileSize
new3.13 KB

I want to know where ALL components have been enabled.
Patch invoke pre and post hooks with no arguments before first and after last component.

BrockBoland’s picture

That's an idea. Haven't tested the patch, but it looks good. Should we track that here or open a new issue for it?

bleen’s picture

I love #10 ... but I think that you should open a new issue and re-close this

Cauliflower’s picture

Status: Fixed » Closed (fixed)

I created a seperate issue and patch for this, see http://drupal.org/node/1844566#comment-6749250

vinmassaro’s picture

Can I get an example of how to implement this? My feature creates a view with a block, and the block configuration is being exported using features_extra. Unless I manually revert the feature, the block configuration is not stood up and shows as overridden. I'm trying to revert the feature immediately after it is enabled.

Inside people_listing.module, I have:


function people_listing_post_features_enable_feature($component) {
    features_revert(array('people_listing' => array('fe_block_settings')));
}

The features_revert() bit works correctly from drush php-eval, but does not seem to work from this hook. Thanks.

BrockBoland’s picture

I'm not sure: I haven't tried calling features_revert() directly, so I'm not sure about the arguments. Have you confirmed that people_listing_post_features_enable_feature() is running, at least?

vinmassaro’s picture

@BrockBoland yes, it is running. I swapped out the features_revert() with a drupal_set_message() and it's outputting after I enable the people_listing feature. My features_revert() bit runs correctly from drush or a block.

vinmassaro’s picture

Issue summary: View changes

Updated Remaining Tasks

kholloway’s picture

This is great work. My only question is these hooks are more like listening hooks in that you are only passed read-only copies of what is about to happen.

It would be really nice if the hook (specifically alter hooks) could actually get more control of the process before it happens.

For example when a component is about to be reverted you can call the pre-hook to know exactly what component is about to be reverted (which gives you a nice way to figure out what is about to be changed) and there is a post-hook to know the change is complete but there is still absolutely no way I have figured out to stop or alter the change.

These hooks are great if you want to react to things you can't change in the flow of a feature but they don't seem like enough if you want to, for example stop a revert from happening at all depending on the component.

Of course if I have missed something please let me know :)

kholloway’s picture

StatusFileSize
new695 bytes

Regarding my comment (#17) I added a new hook that allows you to alter the $items (components) list before a revert/alter/enable/disable is performed. The hook is called:
hook_features_restore_alter

I am open to suggestions on making this better but it was the missing link for me to be able to actually alter the components before the above 4 actions are performed. Without this hook you can only watch before they happen ;)

My hook api example shows one way to use it though there are of course many others.

kholloway’s picture

StatusFileSize
new1.9 KB
kholloway’s picture

Apologies. I uploaded the wrong file. Please see the latest file I uploaded.

Thanks

Growiel’s picture

Hi,

Sorry to reopen this but I think it's the right place.

The hook_post_features_enable_feature() is called at the wrong time. Let me explain.

I have a Features module that creates some field_bases and field_instances and I need to change the permission on those (with the Field Permission module).

The problem is, when the hook_post_features_enable_feature() is called, the field are not yet created, and I get an error on my code to manage the permissions.

This hook needs to be called last, after everything has been imported and created, so the content is available to the module to alter it in anyways possible.

As a side note, if one day Features could auto export Field Permissions, it would be neat.

I hope I make sense.

kholloway’s picture

Moved my issue/solution (patch) to this new issue:
https://www.drupal.org/node/2341637

jastraat’s picture

I am wanting to add some default taxonomy terms to a vocabulary defined by a feature. Unfortunately, hook_post_features_enable_feature() does not work for this, and it seems like this would be a relatively clear use case for such a hook.

Suggestions?

jastraat’s picture

Status: Closed (fixed) » Active
duaelfr’s picture

Status: Active » Needs review
StatusFileSize
new2.72 KB

It has been a long time I wanted to add these hooks into Features.
It includes 2 new hooks and their related documentation.

This patch does not introduce any side effect as it does not alter existing code nor change existing variables values.

Bonus: even if this patch has been made for 7.x-1.x, it also applies on 7.x-2.2

  • mpotter committed ce3863e on 8.x-3.x
    Issue #1782492 by BrockBoland: Added Invoke a hook on the Features...
dinarcon’s picture

Version: 7.x-1.x-dev » 7.x-2.x-dev
Status: Needs review » Reviewed & tested by the community

The patch has not been applied to any of 7.x-1.x, 7.x-2.x, 8.x-3.x It cannot be found in the git log. After manually applying the patch, I could use it as described by @DuaelFr in #25

The last submitted patch, 2: 1782492-2.patch, failed testing.

The last submitted patch, 4: 1782492-4.patch, failed testing.

The last submitted patch, 10: features.patch, failed testing.

The last submitted patch, 19: features.module.patch, failed testing.

dgtlmoon’s picture

+1 works well here, thanks! (2.x and 2.5 tested)

mpotter’s picture

Status: Reviewed & tested by the community » Closed (fixed)

Not sure why this got re-opened.

The OP was committed to Features back in Nov 2012 here: https://www.drupal.org/commitlog/commit/9184/ce3863e445fe07c47e79d6a82e9...

The comment in #26 was auto-generated by the drupal.org commit bot when the 8.x branch of Features was added.

Any additional requests or work on this issue such as in #25 need to be submitted to NEW issues (see #13). You should never re-open an old issue especially with a patch that was previously committed. Otherwise both the d.o testbot and other users get confused.

duaelfr’s picture

Sorry Mike, I didn't read the entire issue but just seen that it was still active.
I'll open a new one asap.
Thank you for your awesome work on this module.

dgtlmoon’s picture

Ok so my confusion then - I wonder why the patch still applied cleanly?