dolibarr  13.0.2
modulehelp.php
Go to the documentation of this file.
1 <?php
2 /* Copyright (C) 2017 Laurent Destailleur <eldy@users.sourceforge.net>
3  * Copyright (C) 2017 Regis Houssin <regis.houssin@inodbox.com>
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 3 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program. If not, see <https://www.gnu.org/licenses/>.
17  */
18 
24 if (!defined('NOREQUIREMENU')) define('NOREQUIREMENU', '1'); // If there is no need to load and show top and left menu
25 if (!defined('NOTOKENRENEWAL')) define('NOTOKENRENEWAL', '1'); // Disabled because this page is into a popup on module search page and we want to avoid to have an Anti CSRF token error (done if MAIN_SECURITY_CSRF_WITH_TOKEN is on) when we make a second search after closing popup.
26 
27 
28 require '../main.inc.php';
29 require_once DOL_DOCUMENT_ROOT.'/core/lib/admin.lib.php';
30 require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
31 require_once DOL_DOCUMENT_ROOT.'/core/lib/functions2.lib.php';
32 
33 // Load translation files required by the page
34 $langs->loadLangs(array('errors', 'admin', 'modulebuilder', 'exports'));
35 
36 $mode = GETPOST('mode', 'alpha');
37 $action = GETPOST('action', 'aZ09');
38 $id = GETPOST('id', 'int');
39 if (empty($mode)) $mode = 'desc';
40 
41 if (!$user->admin)
43 
44 
45 
46 /*
47  * Actions
48  */
49 
50 // Nothing
51 
52 
53 /*
54  * View
55  */
56 
57 $form = new Form($db);
58 
59 $help_url = 'EN:First_setup|FR:Premiers_paramétrages|ES:Primeras_configuraciones';
60 llxHeader('', $langs->trans("Setup"), $help_url);
61 
62 print '<!-- Force style container -->'."\n".'<style>
63 .id-container {
64  width: 100%;
65 }
66 </style>';
67 
68 $arrayofnatures = array('core'=>$langs->transnoentitiesnoconv("Core"), 'external'=>$langs->transnoentitiesnoconv("External").' - '.$langs->trans("AllPublishers"));
69 
70 // Search modules dirs
71 $modulesdir = dolGetModulesDirs();
72 
73 
74 $filename = array();
75 $modules = array();
76 $orders = array();
77 $categ = array();
78 $dirmod = array();
79 $i = 0; // is a sequencer of modules found
80 $j = 0; // j is module number. Automatically affected if module number not defined.
81 $modNameLoaded = array();
82 
83 foreach ($modulesdir as $dir)
84 {
85  // Load modules attributes in arrays (name, numero, orders) from dir directory
86  //print $dir."\n<br>";
87  dol_syslog("Scan directory ".$dir." for module descriptor files (modXXX.class.php)");
88  $handle = @opendir($dir);
89  if (is_resource($handle))
90  {
91  while (($file = readdir($handle)) !== false)
92  {
93  //print "$i ".$file."\n<br>";
94  if (is_readable($dir.$file) && substr($file, 0, 3) == 'mod' && substr($file, dol_strlen($file) - 10) == '.class.php')
95  {
96  $modName = substr($file, 0, dol_strlen($file) - 10);
97 
98  if ($modName)
99  {
100  if (!empty($modNameLoaded[$modName]))
101  {
102  $mesg = "Error: Module ".$modName." was found twice: Into ".$modNameLoaded[$modName]." and ".$dir.". You probably have an old file on your disk.<br>";
103  setEventMessages($mesg, null, 'warnings');
104  dol_syslog($mesg, LOG_ERR);
105  continue;
106  }
107 
108  try {
109  $res = include_once $dir.$file;
110  if (class_exists($modName))
111  {
112  try {
113  $objMod = new $modName($db);
114  $modNameLoaded[$modName] = $dir;
115 
116  if (!$objMod->numero > 0 && $modName != 'modUser')
117  {
118  dol_syslog('The module descriptor '.$modName.' must have a numero property', LOG_ERR);
119  }
120  $j = $objMod->numero;
121 
122  $modulequalified = 1;
123 
124  // We discard modules according to features level (PS: if module is activated we always show it)
125  $const_name = 'MAIN_MODULE_'.strtoupper(preg_replace('/^mod/i', '', get_class($objMod)));
126  if ($objMod->version == 'development' && (empty($conf->global->$const_name) && ($conf->global->MAIN_FEATURES_LEVEL < 2))) $modulequalified = 0;
127  if ($objMod->version == 'experimental' && (empty($conf->global->$const_name) && ($conf->global->MAIN_FEATURES_LEVEL < 1))) $modulequalified = 0;
128  if (preg_match('/deprecated/', $objMod->version) && (empty($conf->global->$const_name) && ($conf->global->MAIN_FEATURES_LEVEL >= 0))) $modulequalified = 0;
129 
130  // We discard modules according to property disabled
131  //if (! empty($objMod->hidden)) $modulequalified=0;
132 
133  if ($modulequalified > 0)
134  {
135  $publisher = dol_escape_htmltag($objMod->getPublisher());
136  $external = ($objMod->isCoreOrExternalModule() == 'external');
137  if ($external)
138  {
139  if ($publisher)
140  {
141  $arrayofnatures['external_'.$publisher] = $langs->trans("External").' - '.$publisher;
142  } else {
143  $arrayofnatures['external_'] = $langs->trans("External").' - '.$langs->trans("UnknownPublishers");
144  }
145  }
146  ksort($arrayofnatures);
147  }
148 
149  // Define array $categ with categ with at least one qualified module
150  if ($modulequalified > 0)
151  {
152  $modules[$i] = $objMod;
153  $filename[$i] = $modName;
154 
155  // Gives the possibility to the module, to provide his own family info and position of this family
156  if (is_array($objMod->familyinfo) && !empty($objMod->familyinfo)) {
157  if (!is_array($familyinfo)) $familyinfo = array();
158  $familyinfo = array_merge($familyinfo, $objMod->familyinfo);
159  $familykey = key($objMod->familyinfo);
160  } else {
161  $familykey = $objMod->family;
162  }
163 
164  $moduleposition = ($objMod->module_position ? $objMod->module_position : '50');
165  if ($moduleposition == '50' && ($objMod->isCoreOrExternalModule() == 'external'))
166  {
167  $moduleposition = '80'; // External modules at end by default
168  }
169 
170  $orders[$i] = $familyinfo[$familykey]['position']."_".$familykey."_".$moduleposition."_".$j; // Sort by family, then by module position then number
171  $dirmod[$i] = $dir;
172  //print $i.'-'.$dirmod[$i].'<br>';
173  // Set categ[$i]
174  $specialstring = 'unknown';
175  if ($objMod->version == 'development' || $objMod->version == 'experimental') $specialstring = 'expdev';
176  if (isset($categ[$specialstring])) $categ[$specialstring]++; // Array of all different modules categories
177  else $categ[$specialstring] = 1;
178  $j++;
179  $i++;
180  } else dol_syslog("Module ".get_class($objMod)." not qualified");
181  } catch (Exception $e)
182  {
183  dol_syslog("Failed to load ".$dir.$file." ".$e->getMessage(), LOG_ERR);
184  }
185  } else {
186  print "Warning bad descriptor file : ".$dir.$file." (Class ".$modName." not found into file)<br>";
187  }
188  } catch (Exception $e)
189  {
190  dol_syslog("Failed to load ".$dir.$file." ".$e->getMessage(), LOG_ERR);
191  }
192  }
193  }
194  }
195  closedir($handle);
196  } else {
197  dol_syslog("htdocs/admin/modulehelp.php: Failed to open directory ".$dir.". See permission and open_basedir option.", LOG_WARNING);
198  }
199 }
200 
201 asort($orders);
202 //var_dump($orders);
203 //var_dump($categ);
204 //var_dump($modules);
205 
206 
207 unset($objMod);
208 $i = 0;
209 foreach ($orders as $tmpkey => $tmpvalue)
210 {
211  $tmpMod = $modules[$tmpkey];
212  if ($tmpMod->numero == $id)
213  {
214  $key = $i;
215  $modName = $filename[$tmpkey];
216  $dirofmodule = $dirmod[$tmpkey];
217  $objMod = $tmpMod;
218  break;
219  }
220  $i++;
221 }
222 $value = $orders[$key];
223 $tab = explode('_', $value);
224 $familyposition = $tab[0]; $familykey = $tab[1]; $module_position = $tab[2]; $numero = $tab[3];
225 
226 
227 
228 $head = modulehelp_prepare_head($objMod);
229 
230 // Check filters
231 $modulename = $objMod->getName();
232 $moduledesc = $objMod->getDesc();
233 $moduleauthor = $objMod->getPublisher();
234 $moduledir = strtolower(preg_replace('/^mod/i', '', get_class($objMod)));
235 
236 $const_name = 'MAIN_MODULE_'.strtoupper(preg_replace('/^mod/i', '', get_class($objMod)));
237 
238 $text = '<span class="opacitymedium">'.$langs->trans("LastActivationDate").':</span> ';
239 if (!empty($conf->global->$const_name)) $text .= dol_print_date($objMod->getLastActivationDate(), 'dayhour');
240 else $text .= $langs->trans("Disabled");
241 $tmp = $objMod->getLastActivationInfo();
242 $authorid = $tmp['authorid'];
243 if ($authorid > 0)
244 {
245  $tmpuser = new User($db);
246  $tmpuser->fetch($authorid);
247  $text .= '<br><span class="opacitymedium">'.$langs->trans("LastActivationAuthor").':</span> ';
248  $text .= $tmpuser->getNomUrl(1);
249 }
250 $ip = $tmp['ip'];
251 if ($ip)
252 {
253  $text .= '<br><span class="opacitymedium">'.$langs->trans("LastActivationIP").':</span> ';
254  $text .= $ip;
255 }
256 
257 $moreinfo = $text;
258 
259 $title = ($modulename ? $modulename : $moduledesc);
260 
261 print '<div class="centpercent">';
262 
263 $picto = 'object_'.$objMod->picto;
264 
265 print load_fiche_titre(($modulename ? $modulename : $moduledesc), $moreinfo, $picto, 0, '', 'titlemodulehelp');
266 print '<br>';
267 
268 print dol_get_fiche_head($head, $mode, '', -1);
269 
270 if (!$modulename)
271 {
272  dol_syslog("Error for module ".$key." - Property name of module looks empty", LOG_WARNING);
273 }
274 
275 // Load all lang files of module
276 if (isset($objMod->langfiles) && is_array($objMod->langfiles))
277 {
278  foreach ($objMod->langfiles as $domain)
279  {
280  $langs->load($domain);
281  }
282 }
283 
284 
285 
286 
287 // Version (with picto warning or not)
288 $version = $objMod->getVersion(0);
289 $versiontrans = '';
290 if (preg_match('/development/i', $version)) $versiontrans .= img_warning($langs->trans("Development"), 'style="float: left"');
291 if (preg_match('/experimental/i', $version)) $versiontrans .= img_warning($langs->trans("Experimental"), 'style="float: left"');
292 if (preg_match('/deprecated/i', $version)) $versiontrans .= img_warning($langs->trans("Deprecated"), 'style="float: left"');
293 $versiontrans .= $objMod->getVersion(1);
294 
295 // Define imginfo
296 $imginfo = "info";
297 if ($objMod->isCoreOrExternalModule() == 'external')
298 {
299  $imginfo = "info_black";
300 }
301 
302 // Define text of description of module
303 $text = '';
304 
305 if ($mode == 'desc')
306 {
307  if ($moduledesc) $text .= '<br>'.$moduledesc.'<br><br><br>';
308 
309  $text .= '<span class="opacitymedium">'.$langs->trans("Version").':</span> '.$version;
310 
311  $moduledescriptorfile = get_class($objMod).'.class.php';
312  $text .= '<br><span class="opacitymedium">'.$langs->trans("DescriptorFile").':</span> '.$moduledescriptorfile;
313 
314  $textexternal = '';
315  if ($objMod->isCoreOrExternalModule() == 'external')
316  {
317  $textexternal .= '<br><span class="opacitymedium">'.$langs->trans("Origin").':</span> '.$langs->trans("ExternalModule").' - '.$langs->trans("InstalledInto", $dirofmodule);
318  if ($objMod->editor_name != 'dolibarr') $textexternal .= '<br><span class="opacitymedium">'.$langs->trans("Publisher").':</span> '.(empty($objMod->editor_name) ? $langs->trans("Unknown") : $objMod->editor_name);
319  $editor_url = $objMod->editor_url;
320  if (!preg_match('/^http/', $editor_url)) $editor_url = 'http://'.$editor_url;
321  if (!empty($objMod->editor_url) && !preg_match('/dolibarr\.org/i', $objMod->editor_url)) $textexternal .= ($objMod->editor_name != 'dolibarr' ? ' - ' : '').img_picto('', 'globe').' <a href="'.$editor_url.'" target="_blank">'.$objMod->editor_url.'</a>';
322  $text .= $textexternal;
323  $text .= '<br>';
324  } else {
325  $text .= '<br><span class="opacitymedium">'.$langs->trans("Origin").':</span> '.$langs->trans("Core").'<br>';
326  }
327 
328  $moduledesclong = $objMod->getDescLong();
329  if ($moduledesclong) $text .= '<br><hr><div class="moduledesclong">'.$moduledesclong.'<div>';
330 }
331 
332 if ($mode == 'feature')
333 {
334  $text .= '<br><strong>'.$langs->trans("DependsOn").':</strong> ';
335  if (count($objMod->depends)) $text .= join(',', $objMod->depends);
336  else $text .= $langs->trans("None");
337  $text .= '<br><strong>'.$langs->trans("RequiredBy").':</strong> ';
338  if (count($objMod->requiredby)) $text .= join(',', $objMod->requiredby);
339  else $text .= $langs->trans("None");
340 
341  $text .= '<br><br>';
342 
343  $text .= '<br><strong>'.$langs->trans("AddDataTables").':</strong> ';
344  $sqlfiles = dol_dir_list(dol_buildpath($moduledir.'/sql/'), 'files', 0, 'llx.*\.sql', array('\.key\.sql', '\.sql\.back'));
345  if (count($sqlfiles) > 0)
346  {
347  $text .= $langs->trans("Yes").' (';
348  $i = 0;
349  foreach ($sqlfiles as $val)
350  {
351  $text .= ($i ? ', ' : '').preg_replace('/\.sql$/', '', preg_replace('/llx_/', '', $val['name']));
352  $i++;
353  }
354  $text .= ')';
355  } else $text .= $langs->trans("No");
356 
357  $text .= '<br>';
358 
359  $text .= '<br><strong>'.$langs->trans("AddDictionaries").':</strong> ';
360  if (isset($objMod->dictionaries) && isset($objMod->dictionaries['tablib']) && is_array($objMod->dictionaries['tablib']) && count($objMod->dictionaries['tablib']))
361  {
362  $i = 0;
363  foreach ($objMod->dictionaries['tablib'] as $val)
364  {
365  $text .= ($i ? ', ' : '').$val;
366  $i++;
367  }
368  } else $text .= $langs->trans("No");
369 
370  $text .= '<br>';
371 
372  $text .= '<br><strong>'.$langs->trans("AddData").':</strong> ';
373  $filedata = dol_buildpath($moduledir.'/sql/data.sql');
374  if (dol_is_file($filedata))
375  {
376  $text .= $langs->trans("Yes").' ('.$moduledir.'/sql/data.sql)';
377  } else $text .= $langs->trans("No");
378 
379  $text .= '<br>';
380 
381  $text .= '<br><strong>'.$langs->trans("AddRemoveTabs").':</strong> ';
382  if (isset($objMod->tabs) && is_array($objMod->tabs) && count($objMod->tabs))
383  {
384  $i = 0;
385  foreach ($objMod->tabs as $val)
386  {
387  if (is_array($val)) $val = $val['data'];
388  if (is_string($val))
389  {
390  $tmp = explode(':', $val, 3);
391  $text .= ($i ? ', ' : '').$tmp[0].':'.$tmp[1];
392  $i++;
393  }
394  }
395  } else $text .= $langs->trans("No");
396 
397  $text .= '<br>';
398 
399  $text .= '<br><strong>'.$langs->trans("AddModels").':</strong> ';
400  if (isset($objMod->module_parts) && isset($objMod->module_parts['models']) && $objMod->module_parts['models'])
401  {
402  $text .= $langs->trans("Yes");
403  } else $text .= $langs->trans("No");
404 
405  $text .= '<br>';
406 
407  $text .= '<br><strong>'.$langs->trans("AddSubstitutions").':</strong> ';
408  if (isset($objMod->module_parts) && isset($objMod->module_parts['substitutions']) && $objMod->module_parts['substitutions'])
409  {
410  $text .= $langs->trans("Yes");
411  } else $text .= $langs->trans("No");
412 
413  $text .= '<br>';
414 
415  $text .= '<br><strong>'.$langs->trans("AddSheduledJobs").':</strong> ';
416  if (isset($objMod->cronjobs) && is_array($objMod->cronjobs) && count($objMod->cronjobs))
417  {
418  $i = 0;
419  foreach ($objMod->cronjobs as $val)
420  {
421  $text .= ($i ? ', ' : '').($val['label']);
422  $i++;
423  }
424  } else $text .= $langs->trans("No");
425 
426  $text .= '<br>';
427 
428  $text .= '<br><strong>'.$langs->trans("AddTriggers").':</strong> ';
429  $moreinfoontriggerfile = '';
430  if (isset($objMod->module_parts) && isset($objMod->module_parts['triggers']) && $objMod->module_parts['triggers'])
431  {
432  $yesno = 'Yes';
433  } else {
434  $yesno = 'No';
435  }
436  require_once DOL_DOCUMENT_ROOT.'/core/class/interfaces.class.php';
437  $interfaces = new Interfaces($db);
438  $triggers = $interfaces->getTriggersList(array((($objMod->isCoreOrExternalModule() == 'external') ? '/'.$moduledir : '').'/core/triggers'));
439  foreach ($triggers as $triggercursor)
440  {
441  if ($triggercursor['module'] == $moduledir)
442  {
443  $yesno = 'Yes';
444  $moreinfoontriggerfile = ' ('.$triggercursor['relpath'].')';
445  }
446  }
447 
448  $text .= $langs->trans($yesno).$moreinfoontriggerfile;
449 
450  $text .= '<br>';
451 
452  $text .= '<br><strong>'.$langs->trans("AddBoxes").':</strong> ';
453  if (isset($objMod->boxes) && is_array($objMod->boxes) && count($objMod->boxes))
454  {
455  $i = 0;
456  foreach ($objMod->boxes as $val)
457  {
458  $text .= ($i ? ', ' : '').($val['file'] ? $val['file'] : $val[0]);
459  $i++;
460  }
461  } else $text .= $langs->trans("No");
462 
463  $text .= '<br>';
464 
465  $text .= '<br><strong>'.$langs->trans("AddHooks").':</strong> ';
466  if (isset($objMod->module_parts) && is_array($objMod->module_parts['hooks']) && count($objMod->module_parts['hooks']))
467  {
468  $i = 0;
469  foreach ($objMod->module_parts['hooks'] as $key => $val)
470  {
471  if ($key === 'entity') continue;
472 
473  // For special values
474  if ($key === 'data')
475  {
476  if (is_array($val))
477  {
478  foreach ($val as $value)
479  {
480  $text .= ($i ? ', ' : '').($value);
481  $i++;
482  }
483 
484  continue;
485  }
486  }
487 
488  $text .= ($i ? ', ' : '').($val);
489  $i++;
490  }
491  } else $text .= $langs->trans("No");
492 
493  $text .= '<br>';
494 
495  $text .= '<br><strong>'.$langs->trans("AddPermissions").':</strong> ';
496  if (isset($objMod->rights) && is_array($objMod->rights) && count($objMod->rights))
497  {
498  $i = 0;
499  foreach ($objMod->rights as $val)
500  {
501  $text .= ($i ? ', ' : '').($val[1]);
502  $i++;
503  }
504  } else $text .= $langs->trans("No");
505 
506  $text .= '<br>';
507 
508  $text .= '<br><strong>'.$langs->trans("AddMenus").':</strong> ';
509  if (isset($objMod->menu) && !empty($objMod->menu)) // objMod can be an array or just an int 1
510  {
511  $text .= $langs->trans("Yes");
512  } else $text .= $langs->trans("No");
513 
514  $text .= '<br>';
515 
516  $text .= '<br><strong>'.$langs->trans("AddExportProfiles").':</strong> ';
517  if (isset($objMod->export_label) && is_array($objMod->export_label) && count($objMod->export_label))
518  {
519  $i = 0;
520  foreach ($objMod->export_label as $val)
521  {
522  $text .= ($i ? ', ' : '').($val);
523  $i++;
524  }
525  } else $text .= $langs->trans("No");
526 
527  $text .= '<br>';
528 
529  $text .= '<br><strong>'.$langs->trans("AddImportProfiles").':</strong> ';
530  if (isset($objMod->import_label) && is_array($objMod->import_label) && count($objMod->import_label))
531  {
532  $i = 0;
533  foreach ($objMod->import_label as $val)
534  {
535  $text .= ($i ? ', ' : '').($val);
536  $i++;
537  }
538  } else $text .= $langs->trans("No");
539 
540  $text .= '<br>';
541 
542  $text .= '<br><strong>'.$langs->trans("AddOtherPagesOrServices").':</strong> ';
543  $text .= $langs->trans("DetectionNotPossible");
544 }
545 
546 
547 if ($mode == 'changelog')
548 {
549  $changelog = $objMod->getChangeLog();
550  if ($changelog) $text .= '<div class="moduledesclong">'.$changelog.'<div>';
551  else $text .= '<div class="moduledesclong">'.$langs->trans("NotAvailable").'</div>';
552 }
553 
554 print $text;
555 
556 
558 
559 print '</div>';
560 
561 // End of page
562 llxFooter();
563 $db->close();
GETPOST($paramname, $check= 'alphanohtml', $method=0, $filter=null, $options=null, $noreplace=0)
Return value of a param into GET or POST supervariable.
dolGetModulesDirs($subdir= '')
Return list of modules directories.
modulehelp_prepare_head($object)
Prepare array with list of tabs.
Definition: admin.lib.php:743
Class to manage Dolibarr users.
Definition: user.class.php:44
dol_buildpath($path, $type=0, $returnemptyifnotfound=0)
Return path of url or filesystem.
img_warning($titlealt= 'default', $moreatt= '', $morecss= 'pictowarning')
Show warning logo.
llxHeader()
Empty header.
Definition: wrapper.php:45
setEventMessages($mesg, $mesgs, $style= 'mesgs', $messagekey= '')
Set event messages in dol_events session object.
Class to manage generation of HTML components Only common components must be here.
load_fiche_titre($titre, $morehtmlright= '', $picto= 'generic', $pictoisfullpath=0, $id= '', $morecssontable= '', $morehtmlcenter= '')
Load a title with picto.
dol_strlen($string, $stringencoding= 'UTF-8')
Make a strlen call.
dol_syslog($message, $level=LOG_INFO, $ident=0, $suffixinfilename= '', $restricttologhandler= '', $logcontext=null)
Write log message into outputs.
accessforbidden($message= '', $printheader=1, $printfooter=1, $showonlymessage=0, $params=null)
Show a message to say access is forbidden and stop program Calling this function terminate execution ...
dol_dir_list($path, $types="all", $recursive=0, $filter="", $excludefilter=null, $sortcriteria="name", $sortorder=SORT_ASC, $mode=0, $nohook=0, $relativename="", $donotfollowsymlinks=0)
Scan a directory and return a list of files/directories.
Definition: files.lib.php:60
dol_is_file($pathoffile)
Return if path is a file.
Definition: files.lib.php:457
dol_get_fiche_head($links=array(), $active= '', $title= '', $notab=0, $picto= '', $pictoisfullpath=0, $morehtmlright= '', $morecss= '', $limittoshow=0, $moretabssuffix= '')
Show tabs of a record.
print
Draft customers invoices.
Definition: index.php:89
dol_print_date($time, $format= '', $tzoutput= 'auto', $outputlangs= '', $encodetooutput=false)
Output date in a string format according to outputlangs (or langs if not defined).
dol_get_fiche_end($notab=0)
Return tab footer of a card.
llxFooter()
Empty footer.
Definition: wrapper.php:59
Class to manage triggers.
dol_escape_htmltag($stringtoescape, $keepb=0, $keepn=0, $keepmoretags= '', $escapeonlyhtmltags=0)
Returns text escaped for inclusion in HTML alt or title tags, or into values of HTML input fields...