danielebarchiesi@0:

APIs are a form of plugins that are tightly associated with a module. Instead of a module providing any number of plugins, each module provides only one file for an API and this file can contain hooks that the module should invoke.

danielebarchiesi@0: danielebarchiesi@0:

Modules support this API by implementing hook_ctools_plugin_api($module, $api). If they support the API, they return a packet of data:

danielebarchiesi@0: danielebarchiesi@0:
danielebarchiesi@0: function mymodule_ctools_plugin_api($module, $api) {
danielebarchiesi@0:   if ($module == 'some module' && $api = 'some api') {
danielebarchiesi@0:     return array(
danielebarchiesi@0:       'version' => The minimum API version this system supports. If this API version is incompatible then the .inc file will not be loaded.
danielebarchiesi@0:       'path' => Where to find the file. Optional; if not specified it will be the module's directory.
danielebarchiesi@0:       'file' => an alternative version of the filename. If not specified it will be $module.$api.inc
danielebarchiesi@0:     );
danielebarchiesi@0:   }
danielebarchiesi@0: }
danielebarchiesi@0: 
danielebarchiesi@0: danielebarchiesi@0:

This implementation must be in the .module file.

danielebarchiesi@0: danielebarchiesi@0:

Modules utilizing this can invole ctools_plugin_api_include() in order to ensure all modules that support the API will have their files loaded as necessary. It's usually easiest to create a small helper function like this:

danielebarchiesi@0: danielebarchiesi@0:
danielebarchiesi@0: define('MYMODULE_MINIMUM_VERSION', 1);
danielebarchiesi@0: define('MYMODULE_VERSION', 1);
danielebarchiesi@0: 
danielebarchiesi@0: function mymodule_include_api() {
danielebarchiesi@0:   ctools_include('plugins');
danielebarchiesi@0:   return ctools_plugin_api_include('mymodule', 'myapi', MYMODULE_MINIMUM_VERSION, MYMODULE_VERSION);
danielebarchiesi@0: }
danielebarchiesi@0: 
danielebarchiesi@0: danielebarchiesi@0:

Using a define will ensure your use of version numbers is consistent and easy to update when you make API changes. You can then use the usual module_invoke type commands:

danielebarchiesi@0: danielebarchiesi@0:
danielebarchiesi@0: mymodule_include_api();
danielebarchiesi@0: module_invoke('myhook', $data);
danielebarchiesi@0: 
danielebarchiesi@0: danielebarchiesi@0:

If you need to pass references, this construct is standard:

danielebarchiesi@0: danielebarchiesi@0:
danielebarchiesi@0: foreach (mymodule_include_api() as $module => $info) {
danielebarchiesi@0:   $function = $module . '_hookname';
danielebarchiesi@0:   // Just because they implement the API and include a file does not guarantee they implemented
danielebarchiesi@0:   // a hook function!
danielebarchiesi@0:   if (!function_exists($function)) {
danielebarchiesi@0:     continue;
danielebarchiesi@0:   }
danielebarchiesi@0: 
danielebarchiesi@0:   // Typically array_merge() is used below if data is returned.
danielebarchiesi@0:   $result = $function($data1, $data2, $data3);
danielebarchiesi@0: }
danielebarchiesi@0: 
danielebarchiesi@0: danielebarchiesi@0:

TODO: There needs to be a way to check API version without including anything, as a module may simply danielebarchiesi@0: provide normal plugins and versioning could still matter.