While I was working on the new Taxonomy Rockstar module, and building in the backend features, It was clear I needed to provide some sort of API for other developers who find it short a feature or two (layout generation in this situation) should be able to interact with some built in API functions in order to extend the module. This IS supposed to be a be all/end all module for Taxonomy by my own expectations.
During my inital "what do I need to do here" planning phase, I ran across doing something that I haven't done before in a module, contributed or otherwise. So I had to do a little research on how to do this the "drupal way". It was apparent that I needed to use one of a handful of functions that appeared to deal with hooks, and invoking the functionality of other modules.
The documentation on api.drupal.org gave the meanings for these functions, and the basic description, but didn't give me the best idea of how to really use them in my situation. After 2 hours of digging around, sorting through posts with no replies, and getting quite frustrated, I found out what I wanted could be done in just a few lines of code very easily.
The Implementation need
What I needed to accomplish with the first API function was the ability for a developer to define a new type of layout for Taxonomy Rockstar. The module plans to ship with a good handful of default layouts and browse/search types, but for it to be flexible, this seems like a no-brainer.
So I wanted my core function in taxonomy_rockstar.module to be able to reach out to any uses of a hook which would return an array of layout types provided by those modules.
taxonomy_rockstar_generate_layouts($vid = 0)
/**
* Get all layouts provided by hook_define_layouts()
*/
$all_layouts = 6">module_invoke_all('define_layouts');
/**
* If we are on a specific vocab page implementing this, we will disable the options that
* haven't been turned on with the Global settings page.
*/
if ($vid && array_filter(6">variable_get('tr-used-layouts', array()))) {
$available_layouts = array_filter(6">variable_get('tr-used-layouts', array()));
$print_layouts = array_intersect_key($all_layouts, $available_layouts);
return $print_layouts;
}
else {
return $all_layouts;
}
}
This function is in my main module, and for now does 2 functions. First, $all_layouts is defined by using the module_invoke_all() function on ANY module using a hook that I've basically just made up, define_layouts
Shortly after that, I have a little bit of logic here that is determining if a vocabulary id ($vid) was sent to the function. If it is, the form options can be filtered based on a global enable/disable switch. (this is here to keep the interface clutter free with disabled layouts, and to only display those on the global layout setting page.) This primary function then will return an array of the layouts, either the filtered one, or the full list, depending on the current need.
taxonomy_rockstar_list_define_layouts()
* Implementation of hook_define_layouts
* providing custom functionality for taxonomy rockstar
*
* @return array of layout options key => text
*/
function taxonomy_rockstar_list_define_layouts() {
return array(
'list-alpha' => 'List Alphabetically',
'list-grouped' => 'Grouped Alphabetically',
'list-date' => 'List by Recently Update',
);
}
Here is a simple example of how the hook_define_layouts that I've defined will work. In this example, and my simple testing, the array is manually created for simplicity. So this function is included in my taxonomy_rockstar_list.module file, and you can see the same structure as normal hooks, any module could integrate into this hook using YOURMODULE_define_layouts
Conclusion
Essentially there are 2 things needed to create your own hook(s).
- Create your own function that implements module_invoke_all('WHAT_YOU_WANT_YOU_HOOK_TO_BE_CALLED');
- Create your new module & function using YOURMODULE_WHAT_YOU_WANT_YOU_HOOK_TO_BE_CALLED
That is ALL it actually takes to implement your own hooks in a Drupal module. The great thing here is the flexibility that it provides for you to do anything, AND allow other developers to easily extend your work. The major consideration I can see here is naming your hook. You should obviously try to choose something unique to your module, that a core or another contributed module wont be using. I think in my example here, and in Taxonomy Rockstar, I will prefix all the hooks with tr_, so this would be tr_define_layouts, which would be MUCH more unlikely to run into a naming issue.
Good Luck!!


Thanks so much for the
Thanks so much for the tutorial. I was searching around as well for a simple explanation and example of the basics of module_invoke_all and you did an excellent job.
Glad it helped!!
Glad to hear this was useful for you. It was something that while obviously not complicated from this example, I had never needed to implement something like that, and the documentation was sparse at best, so it took me quite a bit of digging to find that it was really this simple to do.
Jake Strawn
Drupal Rockstar
Thank you for this info - I
Thank you for this info - I had been looking around for it and your site laid it out the best (especially the Conclusion)!
Perfect
This is exactly to the point. Perfect.
Thanks
You just saved me the 2 hrs that you went through!
Post new comment