Just found an issue with hook_features_export().

I have added Breakpoints as a dependency on a custom module:

dependencies[] = breakpoints

When I enable my custom module, it will enable Breakpoints, which will then trigger ctools_features_declare_functions(), then I get this error:

<b>Fatal error</b>:  Cannot redeclare breakpoint_group_features_export() (previously declared in /vagrant/drupal/sites/default/modules/contrib/features/includes/features.ctools.inc(31) : eval()'d code:1) in <b>/vagrant/drupal/sites/default/modules/contrib/breakpoints/breakpoints.module</b> on line <b>882</b><br />

Then I debugged the

function ctools_features_declare_functions($reset = FALSE) {
/**
 * This is called by Features to ensure ctools component functions are defined
 * Dynamically declare functions under a ctools component's namespace if they are not already declared.
 */
  if (function_exists('_ctools_features_get_info')) {
   foreach (_ctools_features_get_info(NULL, $reset) as $component => $info) {
      $code = '';
      if (!function_exists("{$info['module']}_features_api")) {
        $code .= 'function '. $info['module'] .'_features_api() { return ctools_component_features_api("'. $info['module'] .'"); }';
      }
      if (!function_exists("{$component}_features_export")) {
        $code .= 'function '. $component .'_features_export($data, &$export, $module_name = "") { return ctools_component_features_export("'. $component .'", $data, $export, $module_name); }';
      }
      if (!function_exists("{$component}_features_export_options")) {
        $code .= 'function '. $component .'_features_export_options() { return ctools_component_features_export_options("'. $component .'"); }';
      }
      if (!function_exists("{$component}_features_export_render")) {
        $code .= 'function '. $component .'_features_export_render($module, $data, $export = NULL) { return ctools_component_features_export_render("'. $component .'", $module, $data, $export); }';
      }
      if (!function_exists("{$component}_features_revert")) {
        $code .= 'function '. $component .'_features_revert($module) { return ctools_component_features_revert("'. $component .'", $module); }';
      }
      krumo($code);
      eval($code);
    }
  }
}

The variable $code being used by eval() is

function breakpoint_group_features_export($data, &$export, $module_name = "") {
  return ctools_component_features_export("breakpoint_group", $data, $export, $module_name);
}

function breakpoint_group_features_export_options() {
  return ctools_component_features_export_options("breakpoint_group");
}

function breakpoint_group_features_export_render($module, $data, $export = NULL) {
  return ctools_component_features_export_render("breakpoint_group", $module, $data, $export);
}

function breakpoint_group_features_revert($module) {
  return ctools_component_features_revert("breakpoint_group", $module);
}

And the function breakpoint_group_features_export() is being declared again, which causes the PHP error.

/**
 * Implements hook_features_export().
 */
function breakpoint_group_features_export($data, &$export, $module_name = '') {
  features_include();
  $pipe = ctools_component_features_export('breakpoint_group', $data, $export, $module_name);
  foreach ($data as $group_name) {
    $group = breakpoints_breakpoint_group_load($group_name);
    foreach ($group->breakpoints as $breakpoint_name) {
      $breakpoint = breakpoints_breakpoint_load_by_fullkey($breakpoint_name);
      if ($breakpoint->source_type != BREAKPOINTS_SOURCE_TYPE_THEME) {
        $pipe['breakpoints'][] = $breakpoint_name;
      }
    }
  }
  return $pipe;
}

see http://cgit.drupalcode.org/breakpoints/tree/breakpoints.module#866

I believe it is a typo on the hook_features_export(), it should be breakpoints_group_features_export().
The conflict is happening because Features should use a component name that doesn't conflict with the module name. i.e. in Views module, the component is views_view.
Also, in Drupal the format to use hooks is module_name_hook_name.
I am attaching a patch, please review.

CommentFileSizeAuthor
#1 fatal_error-2354119-1.patch600 bytesmarcelovani
Support from Acquia helps fund testing for Drupal Acquia logo

Comments

marcelovani’s picture

Status: Active » Needs review
FileSize
600 bytes
marcelovani’s picture

Status: Needs review » Closed (works as designed)

Just found this http://drupalcontrib.org/api/drupal/contributions!features!features.api....
Which means that we should actually use the Component name rather than the Module name.

Regarding the errors reported, it seems that Memcache had the hook cached.

So the final fix as to clear Memcache before running Drush updb.

I will close the ticket but leave it here, as it might help other people with similar problem.

marcelovani’s picture