2011-08-10 02:50:16 +02:00
< ? php
2012-02-24 08:52:30 +01:00
/* Copyright ( C ) 2010 - 2012 Laurent Destailleur < eldy @ users . sourceforge . net >
2012-12-30 15:13:49 +01:00
* Copyright ( C ) 2010 - 2012 Regis Houssin < regis . houssin @ capnetworks . com >
2011-08-10 02:50:16 +02:00
* Copyright ( C ) 2010 - 2011 Juanjo Menent < jmenent @ 2 byte . es >
*
* This program is free software ; you can redistribute it and / or modify
* it under the terms of the GNU General Public License as published by
2013-01-16 15:36:08 +01:00
* the Free Software Foundation ; either version 3 of the License , or
2011-08-10 02:50:16 +02:00
* ( at your option ) any later version .
*
* This program is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU General Public License for more details .
*
* You should have received a copy of the GNU General Public License
* along with this program . If not , see < http :// www . gnu . org / licenses />.
*/
/**
* \file htdocs / core / class / hookmanager . class . php
* \ingroup core
* \brief File of class to manage hooks
*/
/**
2012-05-06 00:45:15 +02:00
* Class to manage hooks
2011-08-10 02:50:16 +02:00
*/
class HookManager
{
var $db ;
2012-06-03 20:34:09 +02:00
var $error ;
var $errors = array ();
2011-08-10 02:50:16 +02:00
2011-10-14 18:51:20 +02:00
// Context hookmanager was created for ('thirdpartycard', 'thirdpartydao', ...)
var $contextarray = array ();
2011-08-10 02:50:16 +02:00
// Array with instantiated classes
var $hooks = array ();
2012-03-15 22:37:42 +01:00
2012-03-02 10:29:11 +01:00
// Array result
var $resArray = array ();
2013-01-22 17:43:41 +01:00
// Printable result
var $resPrint = '' ;
2011-08-10 02:50:16 +02:00
/**
2011-10-14 18:51:20 +02:00
* Constructor
*
2012-03-19 17:18:11 +01:00
* @ param DoliDB $db Handler acces base de donnees
2011-08-10 02:50:16 +02:00
*/
2012-02-24 08:52:30 +01:00
function __construct ( $db )
2011-08-10 02:50:16 +02:00
{
2012-02-24 08:52:30 +01:00
$this -> db = $db ;
2011-08-10 02:50:16 +02:00
}
/**
2011-10-14 18:51:20 +02:00
* Init array this -> hooks with instantiated action controlers .
2011-10-05 14:29:16 +02:00
* First , a hook is declared by a module by adding a constant MAIN_MODULE_MYMODULENAME_HOOKS
2011-10-16 01:38:40 +02:00
* with value 'nameofcontext1:nameofcontext2:...' into $this -> const of module descriptor file .
2011-10-14 18:51:20 +02:00
* This make conf -> hooks_modules loaded with an entry ( 'modulename' => array ( nameofcontext1 , nameofcontext2 , ... ))
2012-03-02 14:51:16 +01:00
* When initHooks function is called , with initHooks ( list_of_contexts ), an array this -> hooks is defined with instance of controler
2011-10-14 18:51:20 +02:00
* 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 .
2011-10-05 14:29:16 +02:00
*
2012-02-24 11:06:05 +01:00
* @ param array $arraycontext 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
2011-08-10 02:50:16 +02:00
*/
2012-03-02 14:51:16 +01:00
function initHooks ( $arraycontext )
2011-08-10 02:50:16 +02:00
{
global $conf ;
2011-10-14 18:51:20 +02:00
// Test if there is hooks to manage
2012-06-13 09:17:55 +02:00
if ( ! is_array ( $conf -> modules_parts [ 'hooks' ]) || empty ( $conf -> modules_parts [ 'hooks' ])) return ;
2011-08-10 02:50:16 +02:00
// For backward compatibility
2012-02-24 11:06:05 +01:00
if ( ! is_array ( $arraycontext )) $arraycontext = array ( $arraycontext );
2011-08-10 02:50:16 +02:00
2012-03-15 22:37:42 +01:00
$this -> contextarray = array_unique ( array_merge ( $arraycontext , $this -> contextarray )); // All contexts are concatenated
2011-10-14 18:51:20 +02:00
2012-06-13 09:17:55 +02:00
foreach ( $conf -> modules_parts [ 'hooks' ] as $module => $hooks )
2011-08-10 02:50:16 +02:00
{
if ( $conf -> $module -> enabled )
{
2012-02-24 11:06:05 +01:00
foreach ( $arraycontext as $context )
2011-08-10 02:50:16 +02:00
{
2012-02-24 11:06:05 +01:00
if ( is_array ( $hooks )) $arrayhooks = $hooks ; // New system
else $arrayhooks = explode ( ':' , $hooks ); // Old system (for backward compatibility)
if ( in_array ( $context , $arrayhooks )) // We instantiate action class only if hook is required
2011-08-10 02:50:16 +02:00
{
2011-08-21 20:34:49 +02:00
$path = '/' . $module . '/class/' ;
2011-08-10 02:50:16 +02:00
$actionfile = 'actions_' . $module . '.class.php' ;
$pathroot = '' ;
// Include actions class overwriting hooks
$resaction = dol_include_once ( $path . $actionfile );
if ( $resaction )
{
$controlclassname = 'Actions' . ucfirst ( $module );
2011-08-11 00:47:33 +02:00
$actionInstance = new $controlclassname ( $this -> db );
2012-03-09 14:48:56 +01:00
$this -> hooks [ $context ][ $module ] = $actionInstance ;
2011-08-10 02:50:16 +02:00
}
}
}
}
}
return 1 ;
}
/**
2012-03-15 22:37:42 +01:00
* Execute hooks ( if they were initialized ) for the given method
2011-10-14 18:51:20 +02:00
*
* @ 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' ... )
2012-02-06 17:18:19 +01:00
* @ return mixed For doActions , formObjectOptions : Return 0 if we want to keep standard actions , > 0 if if want to stop standard actions , < 0 means KO .
2013-01-23 00:24:20 +01:00
* For printSearchForm , printLeftBlock , printTopRightMenu , formAddObjectLine , ...: Return HTML string . TODO Must always return an int and things to print into -> resprints .
2012-11-26 13:26:50 +01:00
* Can also return some values into an array -> results .
2011-10-14 18:51:20 +02:00
* $this -> error or this -> errors are also defined by class called by this function if error .
2011-08-10 02:50:16 +02:00
*/
2011-08-11 09:51:50 +02:00
function executeHooks ( $method , $parameters = false , & $object = '' , & $action = '' )
2011-08-10 02:50:16 +02:00
{
if ( ! is_array ( $this -> hooks ) || empty ( $this -> hooks )) return '' ;
2011-10-14 18:51:20 +02:00
$parameters [ 'context' ] = join ( ':' , $this -> contextarray );
dol_syslog ( get_class ( $this ) . '::executeHooks method=' . $method . " action= " . $action . " context= " . $parameters [ 'context' ]);
2011-08-20 19:00:34 +02:00
2012-03-15 22:37:42 +01:00
// Loop on each hook to qualify modules that declared context
$modulealreadyexecuted = array ();
2012-11-26 13:26:50 +01:00
$resaction = 0 ; $error = 0 ;
$this -> resPrint = '' ; $this -> resArray = array ();
2012-03-15 22:37:42 +01:00
foreach ( $this -> hooks as $modules ) // this->hooks is an array with context as key and value is an array of modules that handle this context
2011-08-10 02:50:16 +02:00
{
2012-03-09 14:48:56 +01:00
if ( ! empty ( $modules ))
2011-08-10 02:50:16 +02:00
{
2012-03-15 22:37:42 +01:00
foreach ( $modules as $module => $actionclassinstance )
2011-08-10 02:50:16 +02:00
{
2012-11-26 13:26:50 +01:00
// jump to next class if method does not exists
if ( ! method_exists ( $actionclassinstance , $method )) continue ;
// test to avoid to run twice a hook, when a module implements several active contexts
2012-03-15 22:37:42 +01:00
if ( in_array ( $module , $modulealreadyexecuted )) continue ;
$modulealreadyexecuted [ $module ] = $module ;
2011-08-10 02:50:16 +02:00
// Hooks that return int
2012-11-26 13:26:50 +01:00
if (( $method == 'doActions' || $method == 'formObjectOptions' ))
2011-08-10 02:50:16 +02:00
{
2012-11-26 13:26:50 +01:00
$resaction += $actionclassinstance -> $method ( $parameters , $object , $action , $this ); // $object and $action can be changed by method ($object->id during creation for example or $action to go back to other action for example)
if ( $resaction < 0 || ! empty ( $actionclassinstance -> error ) || ( ! empty ( $actionclassinstance -> errors ) && count ( $actionclassinstance -> errors ) > 0 ))
{
$error ++ ;
$this -> error = $actionclassinstance -> error ; $this -> errors = array_merge ( $this -> errors , ( array ) $actionclassinstance -> errors );
// TODO remove this. Change must be inside the method if required
if ( $method == 'doActions' )
{
if ( $action == 'add' ) $action = 'create' ;
if ( $action == 'update' ) $action = 'edit' ;
}
}
2011-08-10 02:50:16 +02:00
}
2012-11-26 13:26:50 +01:00
// Generic hooks that return a string (printSearchForm, printLeftBlock, printTopRightMenu, formAddObjectLine, formBuilddocOptions, ...)
else
2013-04-19 19:45:06 +02:00
{
2012-11-26 13:26:50 +01:00
// TODO. this should be done into the method by returning nothing
if ( is_array ( $parameters ) && ! empty ( $parameters [ 'special_code' ]) && $parameters [ 'special_code' ] > 3 && $parameters [ 'special_code' ] != $actionclassinstance -> module_number ) continue ;
2012-03-15 22:37:42 +01:00
$result = $actionclassinstance -> $method ( $parameters , $object , $action , $this );
2012-11-26 13:26:50 +01:00
2013-04-19 19:45:06 +02:00
if ( ! empty ( $actionclassinstance -> results ) && is_array ( $actionclassinstance -> results )) $this -> resArray = array_merge ( $this -> resArray , $actionclassinstance -> results );
2012-11-26 13:26:50 +01:00
if ( ! empty ( $actionclassinstance -> resprints )) $this -> resPrint .= $actionclassinstance -> resprints ;
// TODO. remove this. array result must be set into $actionclassinstance->results
2012-12-01 15:45:05 +01:00
if ( is_array ( $result )) $this -> resArray = array_merge ( $this -> resArray , $result );
2012-11-26 13:26:50 +01:00
// TODO. remove this. result must not be a string. we must use $actionclassinstance->resprint to return a string
if ( ! is_array ( $result ) && ! is_numeric ( $result )) $this -> resPrint .= $result ;
2011-08-10 12:55:34 +02:00
}
2013-01-23 00:24:20 +01:00
2013-04-19 19:45:06 +02:00
//print "method=".$method." results=".count($actionclassinstance->results)." resprints=".count($actionclassinstance->resprints)." result=".$result." resaction=".$resaction;
2011-08-10 02:50:16 +02:00
}
}
}
2013-01-23 00:24:20 +01:00
if ( $method != 'doActions' && $method != 'formObjectOptions' ) return $this -> resPrint ; // TODO remove this. When there is something to print, ->resPrint is filled.
2012-11-26 13:26:50 +01:00
return ( $error ? - 1 : $resaction );
2011-08-10 02:50:16 +02:00
}
}
?>