7

Module1 has a function named 'function1'. 'function1' is not a type of hook, but it is a menu callback, or called inside a hook.

Module2 wants to override 'function1' using all variables which are available to function1 inside Module1.

I can call function1 using module_load_include(), but I need to override the called function.

How can I achieve this?

  • you should choose the right answer – vishal Sep 12 '13 at 15:46
7

If you want to use a different menu callback, you can implement hook_menu_alter() to change the menu callback. Suppose you want to override the menu callback Drupal defines for search, you could use the following code.

function mymodule_menu_alter(&$items) {
  if (isset($items['search'])) {
    $items['search']['page callback'] = 'mymodule_search_view';
  }
}

From mymodule_search_view() you can call search_view() without first including the file containing it, as that is done from Drupal before calling the menu callback.

Similar code could be done if the menu callback is returning a form, with the exception that, instead of changing the page callback (which probably is drupal_get_form()), you would change the page arguments to use as first argument the callback name of the function returning the form array. Rather than doing this, you should implement hook_form_alter(), and to hide the not necessary form elements with $form['element']['#access'] = FALSE', and not withunset($form['element'])`.

As for replacing a function that is called from a hook, what can be done is removing the hook implementation that calls that function, and replacing it with a different implementation. It is possible only with Drupal 7, and it must be done carefully. (I will explain why right.)
Suppose you want to change the function called in menu_node_update() (the implementation of hook_node_update()) from menu_node_save() to mymodule_node_save(). You could use the following code.

function mymodule_module_implements_alter(&$implementations, $hook) {
  if ($hook == 'node_update') {
    $group = $implementations['mymodule'];
    unset($implementations['mymodule']);
    unset($implementations['menu']);

    $implementations = array('mymodule' => group) + $implementations;
  }
}

function mymodule_node_update($node) {
  mymodule_node_save();
}

In this way, menu_node_update() would not be invoked anymore, but mymodule_node_update() would.

Normally, modules that depend from a hook implemented by another module don't check if that hook is executed; they check the module is enabled (and assume the hook is invoked), or they add that module as their dependency. Avoiding a hook is executed could cause problems to other modules which could be difficult to track. If it is really necessary to avoid a hook implemented by another module is executed, you should first check on a test site that all is working as expecting. Bear in mind that future Drupal version could break your code, and the code you are writing should be tested on future Drupal version too (when they are available).

2

You should try a module_invoke_all

Supposing your module A callback return the variable $output like this :

function module_a_callback($args){
$output =... your calculs ...
return $output;
}

Add this : module_invoke_all('module_a_alter');

function module_a_callback($args){
$output = ... your calculs ...

// call all module implementing your 'module_a_alter' hook
$alter =  module_invoke_all('module_a_alter', $args);

//if there is an answer, 
$final_output = isset($alter[0]) ? $alter[0] : $output;
return $output;
}

You just created the hook_module_a_alter($args) hook. In your module B, create the corresponding hook implementation

function module_b_module_a_alter($args){
 $output =... your calculs from module B ...
return $output;
}

Here a second methode, faster, using variables passed by reference :

 function module_a_callback($args){
 $output = ... your calculs ...

// call all module implementing your 'module_a_alter' hook
module_invoke_all('module_a_alter', $output,  $args);

return $output;
}

In your module B, create the corresponding hook implementation

function module_b_module_a_alter(&$output, $args){
 $output =... your calculs from module B ...
}

Have a look at this for a mini tuto. You can also use a module_invoke which allow you to specify the module listening your hook call.

  • 1
    Drupal alter hooks are called with drupal_alter(). I assume the question is asked for the generic case, when the OP didn't develop Module1. If the OP developed Module1, then it is better to support an alter hook from that module. – kiamlaluno Nov 3 '12 at 16:35
0

This is more of a php language issue than about Drupal per se....

You can't redefine a function in php by default. You could try using the runkit extension which will allow you to do it, but as far as I know use of runkit on production servers isn't recommended as it can get quite heavy.

In the cases where you absolutely need to change the functionality of another module, a well maintained patch is probably more appropriate.

In Drupal 8 this sort I'd thing should be far less of a problem as the focus is shifting much more towards an OO core (which of course is absolutely awesome) but for now we're stuck with workarounds for these types of situations.

  • The OP is asking how to replace a menu callback, or a function that is called from a hook. Both the cases are not PHP language issues. – kiamlaluno Nov 2 '12 at 12:59
  • @kiam I thought that at first too, but the OP says is not a type of hook, but it is a menu callback, or called inside a hook. hook_menu_alter() would be fine for the menu callback, but for a random function called inside a hook you would have to override the hook implementation to change the called function (sounds familiar ;))...or replace the existing function with another, which would come down to more of a language issue IMO. I might have misunderstood though, it's kind of hard without a code example to work from – Clive Nov 2 '12 at 13:11
  • 1
    It was better if the question asked for a specific case; in that way, we would not make an abstract reasoning. – kiamlaluno Nov 2 '12 at 14:24
-2

Try overriding this function's output by another function where they both meet in any other hook(as you have mentioned the function is being called inside a hook).

  • 1
    I didn't down-vote, but this answer is not helpful. What do you mean by, "overriding this function's output by another function"? If the hook is calling function1(), how do you make it call function2() instead? – kiamlaluno Nov 2 '12 at 14:27
  • by applying additional hook inside your function which execute after first one. – Ashish Nov 2 '12 at 14:53
  • The OP is talking of a function that is called from a hook implemented from another module. He wants to replace the function called from that hook with another one. – kiamlaluno Nov 2 '12 at 17:15

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.