PageRenderTime 43ms CodeModel.GetById 16ms RepoModel.GetById 0ms app.codeStats 0ms

/htdocs/core/class/hookmanager.class.php

https://bitbucket.org/speedealing/speedealing
PHP | 177 lines | 92 code | 22 blank | 63 comment | 42 complexity | a8a2d2f03c6e434b67ca51d9f088ce66 MD5 | raw file
Possible License(s): LGPL-3.0, LGPL-2.1, GPL-3.0, MIT
  1. <?php
  2. /* Copyright (C) 2010-2012 Laurent Destailleur <eldy@users.sourceforge.net>
  3. * Copyright (C) 2010-2012 Regis Houssin <regis.houssin@capnetworks.com>
  4. * Copyright (C) 2010-2011 Juanjo Menent <jmenent@2byte.es>
  5. *
  6. * This program is free software; you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by
  8. * the Free Software Foundation; either version 3 of the License, or
  9. * (at your option) any later version.
  10. *
  11. * This program is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License
  17. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  18. */
  19. /**
  20. * \file htdocs/core/class/hookmanager.class.php
  21. * \ingroup core
  22. * \brief File of class to manage hooks
  23. */
  24. /**
  25. * Class to manage hooks
  26. */
  27. class HookManager
  28. {
  29. var $db;
  30. var $error;
  31. var $errors=array();
  32. // Context hookmanager was created for ('thirdpartycard', 'thirdpartydao', ...)
  33. var $contextarray=array();
  34. // Array with instantiated classes
  35. var $hooks=array();
  36. // Array result
  37. var $resArray=array();
  38. /**
  39. * Constructor
  40. *
  41. * @param DoliDB $db Handler acces base de donnees
  42. */
  43. function __construct($db = '')
  44. {
  45. $this->db = $db;
  46. }
  47. /**
  48. * Init array this->hooks with instantiated action controlers.
  49. * First, a hook is declared by a module by adding a constant MAIN_MODULE_MYMODULENAME_HOOKS
  50. * with value 'nameofcontext1:nameofcontext2:...' into $this->const of module descriptor file.
  51. * This make conf->hooks_modules loaded with an entry ('modulename'=>array(nameofcontext1,nameofcontext2,...))
  52. * When initHooks function is called, with initHooks(list_of_contexts), an array this->hooks is defined with instance of controler
  53. * class found into file /mymodule/class/actions_mymodule.class.php (if module has declared the context as a managed context).
  54. * Then when a hook is executeHook('aMethod'...) is called, the method aMethod found into class will be executed.
  55. *
  56. * @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), ...
  57. * @return int Always 1
  58. */
  59. function initHooks($arraycontext)
  60. {
  61. global $conf;
  62. // Test if there is hooks to manage
  63. if (! is_array($conf->modules_parts['hooks']) || empty($conf->modules_parts['hooks'])) return;
  64. // For backward compatibility
  65. if (! is_array($arraycontext)) $arraycontext=array($arraycontext);
  66. $this->contextarray=array_unique(array_merge($arraycontext,$this->contextarray)); // All contexts are concatenated
  67. foreach($conf->modules_parts['hooks'] as $module => $hooks)
  68. {
  69. if ($conf->$module->enabled)
  70. {
  71. foreach($arraycontext as $context)
  72. {
  73. if (is_array($hooks)) $arrayhooks=$hooks; // New system
  74. else $arrayhooks=explode(':',$hooks); // Old system (for backward compatibility)
  75. if (in_array($context,$arrayhooks)) // We instantiate action class only if hook is required
  76. {
  77. $path = '/'.$module.'/class/';
  78. $actionfile = 'actions_'.$module.'.class.php';
  79. $pathroot = '';
  80. // Include actions class overwriting hooks
  81. $resaction=dol_include_once($path.$actionfile);
  82. if ($resaction)
  83. {
  84. $controlclassname = 'Actions'.ucfirst($module);
  85. $actionInstance = new $controlclassname($this->db);
  86. $this->hooks[$context][$module] = $actionInstance;
  87. }
  88. }
  89. }
  90. }
  91. }
  92. return 1;
  93. }
  94. /**
  95. * Execute hooks (if they were initialized) for the given method
  96. *
  97. * @param string $method Name of method hooked ('doActions', 'printSearchForm', 'showInputField', ...)
  98. * @param array $parameters Array of parameters
  99. * @param Object &$object Object to use hooks on
  100. * @param string &$action Action code on calling page ('create', 'edit', 'view', 'add', 'update', 'delete'...)
  101. * @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.
  102. * For printSearchForm,printLeftBlock,printTopRightMenu,...: Return HTML string.
  103. * $this->error or this->errors are also defined by class called by this function if error.
  104. */
  105. function executeHooks($method, $parameters=false, &$object='', &$action='')
  106. {
  107. if (! is_array($this->hooks) || empty($this->hooks)) return '';
  108. $parameters['context']=join(':',$this->contextarray);
  109. dol_syslog(get_class($this).'::executeHooks method='.$method." action=".$action." context=".$parameters['context']);
  110. // Loop on each hook to qualify modules that declared context
  111. $modulealreadyexecuted=array();
  112. $resaction=0; $resprint='';
  113. 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
  114. {
  115. if (! empty($modules))
  116. {
  117. foreach($modules as $module => $actionclassinstance)
  118. {
  119. // test to avoid to run twice a hook, when a module implements several active contexts
  120. if (in_array($module,$modulealreadyexecuted)) continue;
  121. $modulealreadyexecuted[$module]=$module;
  122. // Hooks that return int
  123. if (($method == 'doActions' || $method == 'formObjectOptions') && method_exists($actionclassinstance,$method))
  124. {
  125. $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)
  126. if ($resaction < 0 || ! empty($actionclassinstance->error) || (! empty($actionclassinstance->errors) && count($actionclassinstance->errors) > 0))
  127. {
  128. $this->error=$actionclassinstance->error; $this->errors=array_merge($this->errors, (array) $actionclassinstance->errors);
  129. if ($method == 'doActions')
  130. {
  131. if ($action=='add') $action='create'; // TODO this change must be inside the doActions
  132. if ($action=='update') $action='edit'; // TODO this change must be inside the doActions
  133. }
  134. }
  135. }
  136. else if ($method == 'getFields' && method_exists($actioninstance,$method))
  137. {
  138. return $actioninstance->getFields($parameters, $object, $action); // action can be changed by method (to go back to other action for example), socid can be changed/set by method (during creation for example)
  139. }
  140. // Generic hooks that return a string (printSearchForm, printLeftBlock, formBuilddocOptions, ...)
  141. else if (method_exists($actionclassinstance,$method))
  142. {
  143. if (is_array($parameters) && ! empty($parameters['special_code']) && $parameters['special_code'] > 3 && $parameters['special_code'] != $actionclassinstance->module_number) continue;
  144. $result = $actionclassinstance->$method($parameters, $object, $action, $this);
  145. if (is_array($result)) $this->resArray = array_merge($this->resArray, $result);
  146. else $resprint.=$result;
  147. }
  148. }
  149. }
  150. }
  151. if ($method == 'doActions' || $method == 'formObjectOptions') return $resaction;
  152. return $resprint;
  153. }
  154. }
  155. ?>