Is there any mechanism in place for controlling the order in which the include files for a feature are processed when enabling that feature?

Surely the only way this is controlled isn't just by doing an alphabetical sort on the array keys from the features array that's built up in the .info file...

The issue I'm running into is that I've got several conditional fields that depend on the fields already being imported, however the conditional fields include file is being processed first so it tries to run before the fields it depends on exist, and as such fails horribly. The only workaround I've been able to find thus far is to keep those conditional fields in a different feature and ensure it only is enabled after the feature that provides the fields it requires.

This feels messy to me, I'd really like to be able to package the whole thing up as a single feature since really the conditional field settings are part of the configuration for that content type.

Is there anything like a weight attribute that can be assigned to these exportables to prevent situations like this? Surely I can't be the only one who's ever run into this kind of problem.

Would this not be an issue if it used ctools exportables rather than the regular features api hooks?

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

DamienMcKenna’s picture

Please provide example code from a Conditional Fields export, it isn't a module I currently use.

willvincent’s picture

FileSize
5.54 KB

Sure.

This is a feature that consists only of the conditional fields config, if it's included with the content type that provides the fields required here the feature cannot be installed (unless those fields have been created without the feature).

As far as I can tell, this is because features is processing everything in the .info file features[] array in alphabetical order. So this item is processed before the fields item(s) process.

I'll see if I can get you an example with everything together so you can see what I mean about it not being able to install.

Note, this depends on the patch provided here: http://drupal.org/node/1191248#comment-4749566

willvincent’s picture

FileSize
5.65 KB

Ok, this should be the full feature that was giving me problems.

As you will see, it defines the content type, fields for that content type, etc.

Nikki Aiuto’s picture

Did you ever get a solution for this? I noticed also that conditional fields failed unless I put them in a separate feature.

Grayside’s picture

Posting archives gets a far minority of investigative clicks as just pasting the relevant code snippet or plaintext file.

willvincent’s picture

I've just accepted exporting conditional fields as their own feature as a workable solution for the time being.

febbraro’s picture

Status: Active » Postponed (maintainer needs more info)
squinternata’s picture

so there is no way to give an order to inc files ??
i think is important because otherwise we have to create so many features..
and it not good when you have to give features to users.
thansk
A

mpotter’s picture

Status: Postponed (maintainer needs more info) » Closed (won't fix)

Closing this for lack of activity. Please re-open this issue if you can reproduce it in the latest version.

Charlouze’s picture

Version: 7.x-1.x-dev » 7.x-2.0-beta1
Status: Closed (won't fix) » Active

I'm reopening this issue because I had some trouble with input formats and ckeditor.
I had to separate my input format definition in an other feature in order for my ckeditor config to find them.

Alice Heaton’s picture

Title: Controlling order of processing include files in a feature when enabling » Controlling order of processing components in a feature when enabling

Problem

To reproduce:

- Create a filter format ;
- Create a CKEditor profile for that filter format ;
- Export as a feature.

When that feature is enabled on another site, the filter format is not associated with the ckeditor profile.

Analysis

The reason is that the ckeditor component is enabled before the filter component.

Suggested solution

I do not think this is actually a Features issue (but I am posting this here for discussion/people to see suggested solution)

There is no way for Features to know how to order the components. In the ckeditor/filter example, filter isn't even a dependency of ckeditor. I also don't think implementing a way for creators of features to order the components is the right solution for this - it should be up to the modules to express these dependencies.

In Features 2.x, there is a hook called `hook_features_api_alter` which can allow modules to do just that - reorder the components. So I think this is not a Features issue - the issue should be reported on the CKEditor issue queue (or other relevant modules) for them to implement `hook_features_api_alter`.

In Features 1.x, the same can be achieved by implementing `hook_module_implements_alter`, which can re-order the modules for a particular hook.

Until this is addressed by the CKEditor, the easier workaround is to implement those hooks yourself within your feature.

Here is my (tested) implementation for Features 1.x. Put this in the features .module file, and replace 'mymodule' with the module's name.

function mymodule_module_implements_alter(&$implementations, $hook) {
  if ($hook == 'features_api' && isset($implementations['ckeditor'])) {
    $setting = $implementations['ckeditor'];
    unset($implementations['ckeditor']);
    $implementations['ckeditor'] = $setting;
  }
}

The solution above should also work with Features 2.x. but it would be best to implement `hook_features_api_alter`. It would look something like this (not tested):

function mymodule_features_api_alter(&$components) {
  if (isset($components['ckeditor'])) {
    $setting = $components['ckeditor'];
    unset($components['ckeditor'];
    $components['ckeditor'] = $setting;
  }
}

Similar solution should apply in other cases where ordering or components is needed.

willvincent’s picture

Is there any reason hook_features_api_alter() couldn't be used within a feature or install profile?

Alice Heaton’s picture

@willvincent: it shouldn't be in the install profile, because it needs to be called every time the cache is cleared.

But it can definitely be in the feature itself - this is what I did with the implementation of `hook_module_implements_alter`. Add it to the features's .module file and rename `mymodule` with the feature's module name (and in your case I guess replace `ckeditor` with `conditonal_fields`). Features won't overwrite your code when you re-create the feature, so you won't need to do it again.

In the long term I still think it should be up to the module that implements a feature component to do this - ckeditor in my case, conditional field in yours. Features itself can't do this, as it doesn't have knowledge of the dependencies. Arguably this information could be provided by the module when they declare their component, but as `hook_features_api_alter` already allows them to do this, I'm not sure there's a need.

acrollet’s picture

I can confirm that solution 2 in #11 works well with features 2.x. For reference, here's the code, fixed up a bit:


/**
 * Implements hook_features_api_alter().
 *
 * Alter features component order so that any custom text formats
 * will be available when the ckeditor profiles are installed.
 */
function mymodule_features_api_alter(&$components) {
  if (isset($components['ckeditor_profile'])) {
    $setting = $components['ckeditor_profile'];
    unset($components['ckeditor_profile']);
    $components['ckeditor_profile'] = $setting;
  }
}
willvincent’s picture

Title: Controlling order of processing components in a feature when enabling » Provide documentation about feature component processing order
Category: support » task
FileSize
1.23 KB

Ok.. since we have a workable solution for this. It seems to me this is a documentation issue at this point,

Can we do something like this?

Alice Heaton’s picture

@willvincent: I don't think it's up to people who create a feature to add this code. Adding this code yourself is a workaround - but in the long term it should be up to the relevant modules to do this - CKEditor knows filters need to be enabled first, Conditional Fields knows other fields need to be enabled first, so they should implement hook_features_api_alter themselves.

I agree this is now a documentation issue, but I think the main documentation to edit would be API.txt. We can still keep something in README.txt to let people know this problem might arise (and point them to a solution), but I don't think people should be expected to write this code.

I will have a go at this as soon as find some time :)

willvincent’s picture

I don't think it's unreasonable to expect people to write this code. People using features should have at least a basic understanding of module writing in the first place (IMHO).

Yes, perhaps the onus should be on the problematic modules, but rather than pointing fingers, and playing the blame game, why is it not ok to include documentation in the readme on how to do this -- even if it is just a workaround?

erik.erskine’s picture

@Alice Heaton, @willvincent:

I have exactly the same issue as described in #11. To me, #11 is a ckeditor issue and I've raised it with a suitable patch there: https://drupal.org/node/2043365

willvincent’s picture

*sigh*

All I am saying is including some documentation on how to work around this issue, in the event ANY module causes issues. I still don't understand why that's such a big deal.

Whatever. I give up.

shaisachs’s picture

The fix in #11 was indeed quite helpful for me - I had a similar node_export / node dependency problem. FWIW here is the code I used in that case:

function awesomeblog_features_api_alter(&$components) {
  if (isset($components['node_export_features'])) {
    $setting = $components['node_export_features'];
    unset($components['node_export_features']);
    $components['node_export_features'] = $setting;
  }
}

However from a coding standpoint I'm a little (excuse the pun) unsettled by the technique used, since it seems to rely on the fact that PHP will provide non-integer array keys in the order they were inserted into the array - that's why unsetting and then re-setting the key works.

It seems to me that we'd be much better off with an explicit weight key in the components array, which can then be fiddled in hook_features_api_alter - e.g. node_export module can look at the weight of the node component and set its own weight to 1+that. Then features should sort by the weight element, and everything will work in a nice, semantically meaningful way.

GuyPaddock’s picture

Issue summary: View changes

@shaisachs: The sample code in this thread is similar to the sample code Drupal core provides for module_implements_alter.

PHP's behavior of sorting the array keys by insertion order is consistent between versions. In addition, PHP documentation states:

Arrays are ordered. The order can be changed using various sorting functions.

I'm not saying I'm crazy about this being the best way to change the position of the element in the array, but since the key needs to be preserved, there isn't really a more efficient way to do it.