There's a subtle bug that shows up in features_get_default() for those rare occasions when module_invoke($m, $default_hook) returns NULL.

The Features code is as follows:

        if ($default_hook && module_hook($m, $default_hook)) {
          $cache[$component][$m] = module_invoke($m, $default_hook);
          if ($alter) {
            drupal_alter($default_hook, $cache[$component][$m]);
          }
        }

As you can see, this takes a default hook named $default_hook, checks to see if the current module $m contains this hook, if it does it then executes that module hook implementation and stores the return as $cache[$component][$m]. Simple stuff.

As an example consider flag.module. It's implementation of hook_views_default_views() starts with the following:

function flag_views_default_views() {
  // Only setup views for the "bookmarks" flag.
  // If it's been deleted, don't create any views.
  $flag = flag_get_flag('bookmarks');
  if (!$flag) {
    return;
  }

In this case, if there is not a flag named 'bookmarks' available it just bails and exits the function with a NULL return. The problem with the Features
logic in features_get_default() is that it doesn't check to see if the return from the hook implementation is valid, it immediately stores it in the $cache array and tries to run drupal_alter() on it.

Then skip on down the line to your own implementation of hook_views_default_views() and the normal expectation that $views is an array no longer is true, so using e.g. if(array_key_exists('myview', $views)) starts to throw errors like this:

warning: array_key_exists() [function.array-key-exists]: The second argument should be either an array or an object in sites/all/modules/Custom/mymodule/mymodule.module on line 1726.

Views' own implementation of this code is in the _views_discover_default_views() function and verifies that the results from the hook implementation was valid before trying to process it, as follows:

        $results = call_user_func($module . "_views_default_views");
        if (!empty($results) && is_array($results)) {

What I suggest is:

  • Verifying that the results from the module_invoke() call is an array.
  • If it is an array add it to the cache array and proceed.
  • If it is not an array simply continue to the next iteration of the foreach() loop.

A patch will be forthcoming.

Comments

damienmckenna’s picture

FYI the code in the current DRUPAL-6--1 and DRUPAL-7--1 branches is as follows:

        if ($default_hook && function_exists("{$m}_{$default_hook}")) {
          $cache[$component][$m] = call_user_func("{$m}_{$default_hook}");
          if ($alter) {
            drupal_alter($default_hook, $cache[$component][$m]);
          }
        }
damienmckenna’s picture

Here are patches for the DRUPAL-6--1 and DRUPAL-7--1 branches, and the v6.x-1.0 release.

damienmckenna’s picture

Status: Active » Needs review
hefox’s picture

Noticed this before, putting on raider to test when awake

hefox’s picture

There's some other bugs in features_get_deault and patches for them, and the patches are overlapping. Should we fix features_get_default in one issue or multiple?

1) runs alter when alter isn't relavent for that hook (hook_node_info_alter)
2) $alter argument messes with the static caching (recalling it with different $alter returns original call cause it's not caching based on alter).
3) this one
1 and 2 are covered in another issue that has conflicting patch

mpotter’s picture

Version: 6.x-1.0 » 7.x-1.x-dev
StatusFileSize
new1.19 KB

This is an old issue, but seems like it still applies. Here is the latest patch for D7. Seems pretty straight-forward so might commit it soon.

mpotter’s picture

Status: Needs review » Fixed

Committed this to ed51a64 so we can finish fixing other issues in features_get_default.

damienmckenna’s picture

Version: 7.x-1.x-dev » 6.x-1.x-dev
Status: Fixed » Needs review
StatusFileSize
new917 bytes

Thanks for working through all these issues!

Rerolled for D6.

damienmckenna’s picture

Any chance of having this committed? #8 still applies cleanly to the latest 6.x-1.x.

hefox’s picture

Mark the issues you think are RTBC as such and I'll commit them soon.

damienmckenna’s picture

Status: Needs review » Reviewed & tested by the community

RTBC, forgot that testbot doesn't work on D6.

hefox’s picture

Status: Reviewed & tested by the community » Fixed

Status: Fixed » Closed (fixed)

Automatically closed -- issue fixed for 2 weeks with no activity.