The following error occurs when the 'clone' link is enabled but clone module is not enabled: warning: call_user_func_array() [function.call-user-func-array]: First argument is expected to be a valid callback, 'clone_access' was given in [REDACTED]/admin_hover.module on line 587.

The error occurs because the second continue (inside the inner foreach loop) operates on the inner foreach loop, instead of the outer foreach loop, like the first continue does. From admin_hover_links();

foreach ($admin_hover as $link) {
  // check active
  if (isset($active_links[$link['href']]) && !$active_links[$link['href']]) {
    continue;
  }
  // check dependencies
  if ($link['dependencies']) {
    foreach ($link['dependencies'] as $dependency) {
      if (!module_exists($dependency)) {
        continue;
      }
    }
  }

The attached patch fixes the issue with the smallest amount of changes possible. However due to reasons made obvious by this error, a better solution would be to avoid using the continue command (ever!) and/or break admin_hover_links() into more smaller functions.

It would also be wise to only expose links for 3rd party functions if the dependent 3rd party module exists. E.g. in admin_hover_admin_hover()

if (module_exists('clone')) {
  $links[] = array(
    'title' => 'Clone "@title"',
    'title arguments' => array('@title' => '[title-raw]'),
    'description' => 'Clone',
    'href' => 'node/[nid]/clone',
    'attributes' => array(
      'class' => 'admin_hover-node_clone',
    ),
    'object' => 'node',
    'access callback' => 'clone_access',
    'access arguments' => array('%object'),
    'dependencies' => array('clone'),
  );
}

Or by including and implementation of clone_admin_hover() if !function_exists('clone_admin_hover). E.g. in admin_hover.module

/**
 * An implementation of hook_init().
 */
function admin_hover_init() {
  if (!function_exists('clone_admin_hover')) {
    include 'modules/clone.inc';
  }
}

and in modules/clone.inc

/**
 * Implementation of hook_admin_hover().
 *
 * @return array
 *   Array of admin_hover links
 */
function admin_hover_admin_hover() {
  $links = array();
  $links[] = array(
    'title' => 'Clone "@title"',
    'title arguments' => array('@title' => '[title-raw]'),
    'description' => 'Clone',
    'href' => 'node/[nid]/clone',
    'attributes' => array(
      'class' => 'admin_hover-node_clone',
    ),
    'object' => 'node',
    'access callback' => 'clone_access',
    'access arguments' => array('%object'),
    'dependencies' => array('clone'),
  );
  return $links;
}
CommentFileSizeAuthor
#1 355261.patch890 bytesBevan
adminhover-continue.patch878 bytesBevan

Comments

Bevan’s picture

StatusFileSize
new890 bytes

Woops. I forgot to set a value to the variable, so it didn't work in some environments.

conortm’s picture

Assigned: Unassigned » conortm
Status: Needs review » Fixed

Thanks, Bevan!

Just earlier today, I updated the module (both 6.x and 5.x versions) to avoid this error (essentially, applying the patch you provided). However, I do agree that this error begs a more elegant solution. The admin_hover_links() function needs some division of labor and better handling of its various "checks".

Thanks for your insight and suggestions. I will definitely apply them to the code, to reach a more robust implementation.

Since this error has been fixed in the code, I am going to set this Issue's Status to "fixed". However, in further development, I will work on the deeper issue at hand.

Thanks, again!!!

Status: Fixed » Closed (fixed)

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