I haven’t been able to find any info on the new hook system. I’ve already looked in the wiki but i couldn’t find it. could anyone point me to the doc?
Thank you
I am referring to this -> MAIN_MODULE_MYMODULE_HOOKS
The hook system is not yet documented, but you can find a very useful comment at the beginning in /htdocs/core/class/hookmanager.class.php :
/**
* Init array this->hooks with instantiated action controlers.
*
* First, a hook is declared by a module by adding a constant MAIN_MODULE_MYMODULENAME_HOOKS
* with value 'nameofcontext1:nameofcontext2:...' or 'all' into $this->const of module descriptor file.
* This make conf->hooks_modules loaded with an entry ('modulename'=>array(nameofcontext1,nameofcontext2,...))
* When this function is called by callHooks(list_of_contexts), an array this->hooks is defined with instance of controler
* class found into file /mymodule/class/actions_mymodule.class.php (if module has declared the context as a managed context).
* Then when a hook is executeHook('aMethod'...) is called, the method aMethod found into class will be executed.
*
* @param array $arraytype Array list of searched hooks tab/features. For example: 'thirdpartycard' (for hook methods into page card thirdparty), 'thirdpartydao' (for hook methods into Societe), ...
* @return int Always 1
*/
And the list of contexts and actions :
// Context hookmanager was created for ('thirdpartycard', 'thirdpartydao', ...)
/**
* Execute hooks (if the were initialized) for the given method
*
* @param string $method Name of method hooked ('doActions', 'printSearchForm', 'showInputField', ...)
* @param array $parameters Array of parameters
* @param Object &$object Object to use hooks on
* @param string &$action Action code on calling page ('create', 'edit', 'view', 'add', 'update', 'delete'...)
* @return mixed For doActions,showInputField,showOutputField: Return 0 if we want to keep standard actions, >0 if if want to stop standard actions, <0 means KO.
* For printSearchForm,printLeftBlock: Return HTML string.
* $this->error or this->errors are also defined by class called by this function if error.
*/
Thanks, I had seen this already but i had a hard time getting my head around it the first time.
I guess the hard thing for me to understand is: What’s the difference betweek a hook and a trigger.
The main differences seems to be that:
- with hooks you can pass parameters.
- with hooks you have to specify which method you want to call (“doActions”,…)
could you help me grasp the concept ?
Thanks
ps:
I saw that you were trying to port your CF module to use hooks. I’ll get the code from git to see how you’ve been using hooks.
I wasn’t able to port it at this time, but thank’s to eldy’s explanation I think I may be able now. If it works out as intended, I will give here more explanations.
Great, I look forward to it.
I have now done a little work with hooks myself. I think I’ve got it now.
Ok it’s ported now, you can look up directly at the code I produced (you can even make a diff between the master branch and the develop branch, at least on the customfields files, to see the difference).
I won’t go too much in the details as I feel the technical implementations may change a bit in the future, but here are an outline of the steps and concepts to use the hooks:
== Concepts
- On the contrary to the triggers which are by definition linked to an action, hooks can happen anywhere at anytime, they are an entry point into the program.
- Hooks work by context (ie the module, eg: “productcard” for products, “invoicecard” for invoices, etc…). It’s easy to find them, just search for “callHooks(”
- Hooks are functions that can be overloaded by your own. Eg: a hook called “doActions” can be used by yourself by making a function like this:
function doActions($parameters,$object,$action) {
...
}
where
* $parameters is an array of meta-data about the datas contained by the hook (eg: the context, always accessible by $parameters->context).
* $object is the object that you may work on. Eg: the product if you are in the productcard context.
* $action is the action if one is conveyed (generally “create” or “edit”).
== Implementation
To use a hook (overload a function), you first need to already have defined a module (see the wiki for that), and then you need to do 2 things:
1- to add your module to the hooks of the context you want to hook on.
This means that when this context (module) will happen, your module will be called.
To do that, just edit your /htdocs/includes/modYourModuleName.class.php and edit the $this->const variable with something like this:
$this->const = array(
0=>array('MAIN_MODULE_YOURMODULENAME_HOOKS', 'chaine', 'productcard:invoicecard:propalcard', 'Hooks list for managing printing functions of the CustomFields module', 0),
);
Of course change YourModuleName with your own module’s name.
Don’t touch ‘chaine’ which defines the type of the constant.
Then you get the value at the third index, which is a string with contexts separated by a comma.
IMPORTANT: Be careful: do not forget to DISABLE then RENABLE the module in the admin panel to accept the now const values, because these constants are only added to the database when enabling the module.
And please note that the const are updated because there is the remove() function (in the same file) that tells Dolibarr to remove the constants when disabling the module, else Dolibarr would not update the constants if they were not removed first (even if the values changed). Your remove() function should be something similar to this:
/**
* Function called when module is disabled.
* Remove from database constants, boxes and permissions from Dolibarr database.
* Data directories are not deleted.
* @return int 1 if OK, 0 if KO
*/
function remove()
{
$sql = array("DELETE FROM ".MAIN_DB_PREFIX."const WHERE name like '%_mymodulename' OR name like '%_mymodulename_%';");
return $this->_remove($sql);
}
2- You will overload a hook (a function) with your own.
Create the file /htdocs/yourmodulename/class/actions_yourmodulename.class.php and then put something like this:
/**
* \class actions_yourmodulename
* \brief Example hook file
*/
class ActionsYourModuleName // extends CommonObject
{
/** Overloading the doActions function : replacing the parent's function with the one below
* @param parameters meta datas of the hook (context, etc...)
* @param object the object you want to process (an invoice if you are in invoice module, a propale in propale's module, etc...)
* @param action current action (if set). Generally create or edit or null
* @return void
*/
function doActions($parameters, $object, $action) {
print_r($parameters);
echo "action: ".$action;
print_r($object);
if ($parameters->context == 'somecontext') {
// do something only for the context 'somecontext'
}
}
}
Your function should now be called when you access the module/context and you will see the parameters and object and action.
How to find the available hooks ? Just search for “executeHooks(” and you should easily find all the hooks.
Ok that’s all, good luck.
Thanks for this text.
I took it to init the documentation page onto wiki:
http://wiki.dolibarr.org/index.php/Hooks_system
Feel free to create a wiki account to edit yourself documentation directly from this official place.
eldy wrote:
Ah I didn’t know, I thought that the wiki was write-blocked for external people to the project.
Ok I will update it now as Ive just edited my post to add an info at the very same time you posted.
No, only home page is write-locked.
I will add a note on wiki to let know this…
Great to add this info in the Wiki.
I have some issues with the comment you make regarding constants
[code]
/**
* Function called when module is disabled.
* Remove from database constants, boxes and permissions from Dolibarr database.
* Data directories are not deleted.
* @return int 1 if OK, 0 if KO
*/
function remove()
{
$sql = array("DELETE FROM ".MAIN_DB_PREFIX.“const WHERE name like ‘%_mymodulename’ OR name like ‘%mymodulename%’;”);
return $this->_remove($sql);
}[/code]
Isn’t this unnecessary? Aren’t constants removed by DolibarrModules->delete_const() ?
Constant are automatically deleted only if whe you declare it, you set parameter 6 into declaration to 1, like this
$this->const = array( 0=>array(‘MAIN_MODULE_YOURMODULENAME_HOOKS’, ‘chaine’, ‘productcard:invoicecard:propalcard’, ‘Hooks list for managing printing functions of the CustomFields module’, 0, ‘current’, 1);
Last param is 1, by default it is 0 to avoid loosing setup when disabling/enabling a module
Right, so using this would basically delete all constants regardless of the $deleteonunactive (6th param) flag (which effectivelly makes it usesless):
[code]
function remove()
{
$sql = array("DELETE FROM ".MAIN_DB_PREFIX.“const WHERE name like ‘%_mymodulename’ OR name like ‘%mymodulename%’;”);
return $this->_remove($sql);
}[/code]
Wouldn’t it make more sense to use the $deleteonunactive param when declaring consts instead of force-deleting all consts on module uninstall?
I guess, I just don’t understand the use of an additional SQL statement in the descriptor if this is already being taken care of.
I am not trying to be picky//annoying , I just want to understand the advantage of this solution as opposed to the way it’s currently being done.
Indeed, I wrote this because I did it this way, I didn’t look for an alternative, but this way is I think better and simpler. I update the wiki. Thank’s for the input.
I have added informations on the wiki on how to implement hooks in one’s own module (so that it becomes “hookable” by others).