I'm one of those guys who needs to see it to understand it, and I need to understand it fully to use it to the fullest.

So can someone point to me in my installation where the HOOK definitions are located?

For example, I know that when developing a module I can use _install hook in my install file, but besides having to logon to the website to see the API docs, where can I look on my local machine to see the parameters and functionality of the hooks (not always connected to the Internet).

Thanks
Bill

Comments

marcvangend’s picture

You can find a list of Drupal core hooks at http://api.drupal.org/api/group/hooks.

Drupal doesn't have a registry of hooks, so you cannot retrieve a list from one location. Every module is able to define it's own hooks, so depending on the modules you have installed, your Drupal site may have more hooks than just the core ones.

Modules are invoked by calling module_invoke() (in some cases) or module_invoke_all() (usually). For a simple example, see how _drupal_bootstrap_full() (http://api.drupal.org/api/function/_drupal_bootstrap_full/6) invokes hook_init in all modules that implement the init hook:

function _drupal_bootstrap_full() {
  static $called;

  if ($called) {
    return;
  }
  $called = 1;
  require_once './includes/theme.inc';
  require_once './includes/pager.inc';
  require_once './includes/menu.inc';
  require_once './includes/tablesort.inc';
  require_once './includes/file.inc';
  require_once './includes/unicode.inc';
  require_once './includes/image.inc';
  require_once './includes/form.inc';
  require_once './includes/mail.inc';
  require_once './includes/actions.inc';
  // Set the Drupal custom error handler.
  set_error_handler('drupal_error_handler');
  // Emit the correct charset HTTP header.
  drupal_set_header('Content-Type: text/html; charset=utf-8');
  // Detect string handling method
  unicode_check();
  // Undo magic quotes
  fix_gpc_magic();
  // Load all enabled modules
  module_load_all();
  // Let all modules take action before menu system handles the request
  // We do not want this while running update.php.
  if (!defined('MAINTENANCE_MODE') || MAINTENANCE_MODE != 'update') {
    module_invoke_all('init');
  }
}

Maybe there are nifty ways to generate a list of hooks in your site, but as far as I know, the line where module_invoke(_all)() is called is the only place where you can see it's parameters.

JYW Enterprise’s picture

Thanks for the reply.

I found this link while browsing the API documentation (http://api.drupal.org/api/drupal/developer--hooks--install.php/6/source) and I was under the impression this must exist somewhere, but could not find it in my installation.

But, what you said makes sense as far as how hooks are invoked. I guess I was thinking it was validating the requirements of each hook based on the link above. But what you are saying is that it seeks out the module(s) where the hook is implemented. It appears that it rips through the INC files of the core modules for each hook the system would look for.

But if I wrote a custom module and provided my own hook to be used by other modules, how would it know my hook is available so it would invoke it where it is being implemented by other modules. Is this stored in the database?

Thanks for the insight.

justageek’s picture

You can "define" a hook for your own module without ever creating a function for that hook, I know that sounds odd, but here is a practical example from Ubercart. Ubercart as its own function uc_cart_add_item which basically adds an item to the shoppers cart. In this function, you will see this code, which basically lets other modules "hook into" the add process and do something with the node being added.

$result = module_invoke_all('add_to_cart', $nid, $qty, $data);
  if (is_array($result) && !empty($result)) {
    foreach ($result as $row) {
      if ($row['success'] === FALSE) {
        if (isset($row['message']) && !empty($row['message'])) {
          $message = $row['message'];
        }
        else {
          $message = t('Sorry, that item is not available for purchase at this time.');
        }
        if ($row['silent'] === TRUE) {
          if ($check_redirect) {
            if (isset($_GET['destination'])) {
              drupal_goto();
            }
            $redirect = variable_get('uc_add_item_redirect', 'cart');
            if ($redirect != '<none>') {
              $_SESSION['uc_cart_last_url'] = uc_referer_uri();
              return $redirect;
            }
            else {
              return uc_referer_uri();
            }
          }
        }
        else {
          drupal_set_message($message, 'error');
        }
        return;
      }
    }
  }

So, there is no "add_to_cart" function, but if you as a third party developer want to hook into this process, you would build a function like this:

function mymodule_add_to_cart($nid, $qty, $data) {
  // do something with the variables passed in
 // return a value of true or false
}

The ubercart guys do a great job of documentation their hooks

/**
 * Do extra processing when an item is added to the shopping cart.
 *
 * Some modules need to be able to hook into the process of adding items to a
 * cart. For example, an inventory system may need to check stock levels and
 * prevent an out of stock item from being added to a customer's cart. This hook
 * lets developers squeeze right in at the end of the process after the product
 * information is all loaded and the product is about to be added to the cart.
 * In the event that a product should not be added to the cart, you simply have
 * to return a failure message described below. This hook may also be used simply
 * to perform some routine action when products are added to the cart.
 *
 * @param $nid
 *   The node ID of the product
 * @param $qty
 *   The quantity being added
 * @param $data
 *   The data array, including attributes and model number adjustments
 * @return
 *   The function can use this data to whatever purpose to see if the item can
 *   be added to the cart or not. The function should return an array containing
 *   the result array. (This is due to the nature of Drupal's module_invoke_all()
 *   function. You must return an array within an array or other module data will
 *   end up getting ignored.) At this moment, there are only three keys:
 *   - "success": TRUE or FALSE for whether the specified quantity of the item
 *       may be added to the cart or not; defaults to TRUE.
 *   - "message": the fail message to display in the event of a failure; if
 *       omitted, Ubercart will display a default fail message.
 *   - "silent": return TRUE to suppress the display of any messages; useful
 *       when a module simply needs to do some other processing during an add to
 *       cart or fail silently.
 */
function hook_add_to_cart($nid, $qty, $data) {
  if ($qty > 1) {
    $result[] = array(
      'success' => FALSE,
      'message' => t('Sorry, you can only add one of those at a time.'),
    );
  }
  return $result;
}

I hope this helps. The hook system is really cool but can be a little daunting at first, you got stuff firing all over the place!

marcvangend’s picture

I'm sot sure how the documentation pages are built; maybe some clever regex finds all core hooks, but I can also imagine that the list is 'editorial'.

Available hooks and hook implementations are not stored in the database. The naming convention of hook implementations is essential: when a module implements a hook, that function is called [modulename]_[hookname]. When Drupal initializes, all .module files of the enabled modules are included, defining all functions inside including the hook implementations. When a hook is invoked, Drupal looks up which modules have defined a function with the appropriate name (the essence of that process is in the module_hook function: http://api.drupal.org/api/function/module_hook/6). For instance, when hook_init is invoked, Drupal will check if node.module defined node_init(), if comment.module defined comment_init(), and so on. If the function is defined, it is executed.

[edit]
By the way, an interesting detail is that a hook registry was added to the development version of Drupal 7 in an attempt to improve performance. When it turned out that this didn't work as expected, a large part was taken out again.

Cybergarou’s picture

If you want a local copy of the API docs, you should check out Create your own API Site in Drupal 6.

This will also create pages for contributed modules if they are formatted correctly. (Like the Ubercart example given here.)

jaypan’s picture

The reason that you aren't finding them is because the hook definitions don't actually exist. They are entered into the documentation for reference purposes, basically so humans can understand what is going on. But the way hooks themselves work is actually quite different than how you see it in the documentation. As an example, here is what hook_menu() could look like:

$menu = module_invoke_all('menu');

That's all. What this does is goes through all modules, looks for their implementations of hook_menu(), and gathers the data that each module provides, and returns it to the value of $menu. As you can see, there is no hook_definition here. All there is is an implementation of the function that calls the hooks in each of the modules.

It's kind of confusing at the start when you don't understand it. But basically, when you look at the hook definitions, all they are doing is showing an example of how the data returned by the hook function should look.


Contact me to contract me for D7 -> D10/11 migrations.
Or anything really. I'm friendly, and open to work or conversation.
JYW Enterprise’s picture

Everyone,

Thanks for helping this Drupal-newbie grasp the mechanics of what is happening under the hood. You've all done a great job of explaining it. I think I get it now. I'm going to do a little experimenting to prove to myself I do.

All your efforts are greatly appreciated!

Thanks
Bill