dolibarr 25.0.0-alpha
custom_prompt.php
Go to the documentation of this file.
1<?php
2/* Copyright (C) 2004-2017 Laurent Destailleur <eldy@users.sourceforge.net>
3 * Copyright (C) 2022 Alice Adminson <aadminson@example.com>
4 * Copyright (C) 2024-2026 Frédéric France <frederic.france@free.fr>
5 * Copyright (C) 2026 Jose Martinez <jose.martinez@pichinov.com>
6 * Copyright (C) 2024 Alexandre Spangaro <alexandre@inovea-conseil.com>
7 * Copyright (C) 2026 Nick Fragoulis
8 *
9 * This program is free software: you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation, either version 3 of the License, or
12 * (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program. If not, see <https://www.gnu.org/licenses/>.
21 */
22
29// Load Dolibarr environment
30require '../../main.inc.php';
38require_once DOL_DOCUMENT_ROOT."/core/lib/admin.lib.php";
39require_once DOL_DOCUMENT_ROOT."/ai/lib/ai.lib.php";
40require_once DOL_DOCUMENT_ROOT."/core/class/html.formai.class.php";
41
42$langs->loadLangs(array("admin", "website", "other"));
43
44$arrayofaifeatures = getListOfAIFeatures();
45$arrayofai = getListOfAIServices();
46
47// Parameters
48$action = GETPOST('action', 'aZ09');
49$backtopage = GETPOST('backtopage', 'alpha');
50$cancel = GETPOST('cancel', 'alpha');
51$modulepart = GETPOST('modulepart', 'aZ09'); // Used by actions_setmoduleoptions.inc.php
52
53$functioncode = GETPOST('functioncode', 'alpha');
54$pre_prompt = GETPOST('prePrompt');
55$post_prompt = GETPOST('postPrompt');
56$blacklists = GETPOST('blacklists');
57$test = GETPOST('test');
58$key = (string) GETPOST('key', 'alpha');
59
60if (empty($action)) {
61 $action = 'edit';
62}
63
64$error = 0;
65$setupnotempty = 0;
66
67// Access control
68if (!$user->admin) {
70}
71if (!isModEnabled('ai')) {
72 accessforbidden('Module AI not activated.');
73}
74
75// Set this to 1 to use the factory to manage constants. Warning, the generated module will be compatible with version v15+ only
76$useFormSetup = 1;
77
78if (!class_exists('FormSetup')) {
79 require_once DOL_DOCUMENT_ROOT.'/core/class/html.formsetup.class.php';
80}
81
82$form = new Form($db);
83$formSetup = new FormSetup($db);
84$aiservice = getDolGlobalString('AI_API_SERVICE', 'chatgpt');
85
86// Setup conf for AI model
87$formSetup->formHiddenInputs['action'] = "updatefeaturemodel";
88foreach ($arrayofaifeatures as $featurekey => $feature) {
89 $newfeaturekey = $featurekey;
90 if (preg_match('/^text/', $featurekey)) {
91 $newfeaturekey = 'textgeneration';
92 }
93 $item = $formSetup->newItem('AI_API_'.strtoupper($aiservice).'_MODEL_'.$feature["function"]); // Name of constant must end with _KEY so it is encrypted when saved into database.
94 if (!empty($arrayofai[$aiservice][$newfeaturekey]['default']) && $arrayofai[$aiservice][$newfeaturekey]['default'] != 'na') {
95 $item->nameText = '<span class="valignmiddle">'.$langs->trans("AI_API_MODEL_".$feature["function"]).' </span><span class="opacitymedium valignmiddle">('.$langs->trans("Default").' = '.$arrayofai[$aiservice][$newfeaturekey]['default'].')</span>';
96 if (!empty($arrayofai[$aiservice][$newfeaturekey]['examples'])) {
97 $htmltooltip = $langs->trans("Example").': '.$arrayofai[$aiservice][$newfeaturekey]['examples'];
98 $item->nameText .= $form->textwithpicto('', $htmltooltip);
99 }
100 } else {
101 $item->nameText = $langs->trans("AI_API_MODEL_".$feature["function"]).' <span class="opacitymedium">('.$langs->trans("None").')</span>';
102 }
103 $item->cssClass = 'minwidth500 input';
104}
105
106$setupnotempty += count($formSetup->items);
107
108$dirmodels = array_merge(array('/'), (array) $conf->modules_parts['models']);
109
110
111/*
112 * Actions
113 */
114
115// get all configs in const AI
116
117$currentConfigurationsJson = getDolGlobalString('AI_CONFIGURATIONS_PROMPT');
118$currentConfigurations = json_decode($currentConfigurationsJson, true);
119
120if ($action == 'updatefeaturemodel' && !empty($user->admin)) {
121 $formSetup->saveConfFromPost();
122 $action = 'edit';
123}
124
125if ($action == 'update' && $cancel) {
126 $action = 'edit';
127}
128
129if ($action == 'update' && !$cancel && !$test) {
130 $error = 0;
131 if (empty($functioncode)) {
132 $error++;
133 setEventMessages($langs->trans('ErrorInputRequired'), null, 'errors');
134 }
135 if (!is_array($currentConfigurations)) {
136 $currentConfigurations = [];
137 }
138
139 $blacklistArray = array_filter(array_map('trim', explode(',', $blacklists)));
140
141 if (empty($functioncode) || (empty($pre_prompt) && empty($post_prompt) && empty($blacklists))) {
142 if (isset($currentConfigurations[$functioncode])) {
143 unset($currentConfigurations[$functioncode]);
144 }
145 } else {
146 $currentConfigurations[$functioncode] = [
147 'prePrompt' => $pre_prompt,
148 'postPrompt' => $post_prompt,
149 'blacklists' => $blacklistArray,
150 ];
151 }
152
153 $newConfigurationsJson = json_encode($currentConfigurations, JSON_UNESCAPED_UNICODE);
154 $result = dolibarr_set_const($db, 'AI_CONFIGURATIONS_PROMPT', $newConfigurationsJson, 'chaine', 0, '', $conf->entity);
155 if (!$error) {
156 if ($result) {
157 header("Location: ".$_SERVER['PHP_SELF']);
158 setEventMessages($langs->trans("SetupSaved"), null, 'mesgs');
159 exit;
160 } else {
161 setEventMessages($langs->trans("ErrorUpdating"), null, 'errors');
162 }
163 }
164
165 $action = 'edit';
166}
167
168// Update entry
169if ($action == 'updatePrompts' && !$test) {
170 $blacklistArray = array_filter(array_map('trim', explode(',', $blacklists)));
171
172 $currentConfigurations[$key] = [
173 'prePrompt' => $pre_prompt,
174 'postPrompt' => $post_prompt,
175 'blacklists' => $blacklistArray,
176 ];
177
178 $newConfigurationsJson = json_encode($currentConfigurations, JSON_UNESCAPED_UNICODE);
179 $result = dolibarr_set_const($db, 'AI_CONFIGURATIONS_PROMPT', $newConfigurationsJson, 'chaine', 0, '', $conf->entity);
180 if (!$error) {
181 $action = 'edit';
182 if ($result) {
183 setEventMessages($langs->trans("SetupSaved"), null, 'mesgs');
184 } else {
185 setEventMessages($langs->trans("ErrorUpdating"), null, 'errors');
186 }
187 }
188}
189
190// Test entry
191if ($action == 'updatePrompts' && $test) {
192 $action = 'edit';
193}
194
195// Delete entry
196if ($action == 'confirm_deleteproperty' && GETPOST('confirm') == 'yes') {
197 if (isset($currentConfigurations[$key])) {
198 unset($currentConfigurations[$key]);
199
200 $newConfigurationsJson = json_encode($currentConfigurations, JSON_UNESCAPED_UNICODE);
201 $res = dolibarr_set_const($db, 'AI_CONFIGURATIONS_PROMPT', $newConfigurationsJson, 'chaine', 0, '', $conf->entity);
202 if ($res) {
203 header("Location: ".$_SERVER['PHP_SELF']);
204 setEventMessages($langs->trans("RecordDeleted"), null, 'mesgs');
205 exit;
206 } else {
207 setEventMessages($langs->trans("NoRecordDeleted"), null, 'errors');
208 }
209 }
210}
211
212
213/*
214 * View
215 */
216
217$formai = new FormAI($db);
218
219$help_url = '';
220$title = "AiSetup";
221
222llxHeader('', $langs->trans($title), $help_url, '', 0, 0, '', '', '', 'mod-ai page-admin_custom_prompt');
223
224$linkback = '<a href="'.($backtopage ? $backtopage : DOL_URL_ROOT.'/admin/modules.php?restore_lastsearch_values=1').'">'.img_picto($langs->trans("BackToModuleList"), 'back', 'class="pictofixedwidth"').'<span class="hideonsmartphone">'.$langs->trans("BackToModuleList").'</span></a>';
225
226print load_fiche_titre($langs->trans($title), $linkback, 'title_setup');
227
228// Configuration header
229$head = aiAdminPrepareHead();
230print dol_get_fiche_head($head, 'custom', $langs->trans($title), -1, "ai");
231
232$newcardbutton = dolGetButtonTitle($langs->trans('NewCustomPrompt'), '', 'fa fa-plus-circle', $_SERVER["PHP_SELF"].'?action=create', '', 1);
233/*
234$newbutton = '<a href="'.$_SERVER["PHP_SELF"].'?action=create" title="'.$langs->trans("NewCustomPrompt").'">';
235$newbutton .= img_picto('', 'add');
236$newbutton .= '</a>';
237*/
238
239print load_fiche_titre($langs->trans("AIPromptForFeatures", $arrayofai[$aiservice]['label']), $newcardbutton, '');
240
241
242if ($action == 'deleteproperty') {
243 $formconfirm = $form->formconfirm(
244 $_SERVER["PHP_SELF"].'?key='.urlencode(GETPOST('key', 'alpha')),
245 $langs->trans('Delete'),
246 $langs->trans('ConfirmDeleteSetup', GETPOST('key', 'alpha')),
247 'confirm_deleteproperty',
248 '',
249 0,
250 1
251 );
252 print $formconfirm;
253}
254
255if ($action == 'create') {
256 $out = '<div class="addcustomprompt">';
257
258 $out .= '<form action="'.$_SERVER["PHP_SELF"].'" method="POST">';
259 $out .= '<input type="hidden" name="token" value="'.newToken().'">';
260 $out .= '<input type="hidden" name="action" value="update">';
261
262
263 $out .= '<table class="noborder centpercent">';
264 $out .= '<thead>';
265 $out .= '<tr class="liste_titre">';
266 $out .= '<td>'.$langs->trans('NewCustomPrompt').'</td>';
267 $out .= '<td></td>';
268 $out .= '</tr>';
269 $out .= '</thead>';
270
271 $out .= '<tbody>';
272 $out .= '<tr class="oddeven">';
273 $out .= '<td class="col-setup-title titlefield">';
274 $out .= '<span id="module" class="spanforparamtooltip">'.$langs->trans("Feature").'</span>';
275 $out .= '</td>';
276 $out .= '<td>';
277 // Combo list of AI features
278 $out .= '<select name="functioncode" id="functioncode" class="flat minwidth500">';
279 $out .= '<option>&nbsp;</option>';
280 foreach ($arrayofaifeatures as $featurekey => $feature) {
281 $labelhtml = $langs->trans($arrayofaifeatures[$featurekey]['label']).($arrayofaifeatures[$featurekey]['status'] == 'notused' ? ' <span class="opacitymedium">('.$langs->trans("NotYetAvailable").')</span>' : "");
282 $labeltext = $langs->trans($arrayofaifeatures[$featurekey]['label']);
283 $out .= '<option value="'.dolPrintHTMLForAttribute($featurekey).'" data-html="'.dolPrintHTMLForAttribute($labelhtml).'">'.dolPrintHTML($labeltext).'</option>';
284 }
285 $out .= '</select>';
286 $out .= ajax_combobox("functioncode");
287 $out .= '<script type="text/javascript">
288 jQuery(document).ready(function() {
289 jQuery("#functioncode").on("change", function() {
290 console.log("We change value of ai function");
291 var changedValue = $(this).val();
292 console.log(changedValue);
293 var arrayplaceholder = {';
294 foreach ($arrayofaifeatures as $featurekey => $feature) {
295 $out .= dol_sanitizeKeyCode($featurekey).': \''.dol_escape_js(empty($feature['placeholder']) ? '' : $feature['placeholder']).'\',';
296 }
297 $out .= '}
298 jQuery("#prePromptInput'.dol_sanitizeKeyCode($key).'").val(arrayplaceholder[changedValue]);
299 });
300 });
301 </script>
302 ';
303
304 $out .= '</td>';
305 $out .= '</tr>';
306
307 $out .= '<tr class="oddeven">';
308 $out .= '<td class="col-setup-title">';
309 $out .= '<span id="prePrompt" class="spanforparamtooltip">';
310 $out .= $form->textwithpicto($langs->trans("Pre-Prompt"), $langs->trans("Pre-PromptHelp"));
311 $out .= '</span>';
312 $out .= '</td>';
313 $out .= '<td>';
314 $out .= '<textarea class="flat minwidth500 quatrevingtpercent" id="prePromptInput'.$key.'" name="prePrompt" rows="2"></textarea>';
315 $out .= '</td>';
316 $out .= '</tr>';
317 $out .= '<tr class="oddeven">';
318 $out .= '<td class="col-setup-title">';
319 $out .= '<span id="postPrompt" class="spanforparamtooltip">';
320 $out .= $form->textwithpicto($langs->trans("Post-Prompt"), $langs->trans("Post-PromptHelp"));
321 $out .= '</span>';
322 $out .= '</td>';
323 $out .= '<td>';
324 $out .= '<textarea class="flat minwidth500 quatrevingtpercent" id="postPromptInput" name="postPrompt" rows="2"></textarea>';
325 $out .= '</td>';
326 $out .= '</tr>';
327 $out .= '<tr class="oddeven">';
328 $out .= '<td class="col-setup-title">';
329 $out .= '<span id="blacklists" class="spanforparamtooltip">';
330 $out .= $form->textwithpicto($langs->trans("BlackListWords"), $langs->trans("BlackListWordsAIHelp").'.<br>'.$langs->trans("BlackListWordsHelp"));
331 $out .= '</span>';
332 $out .= '</td>';
333 $out .= '<td>';
334 $out .= '<input type="text" class="flat minwidth500 quatrevingtpercent" id="blacklistsInput" name="blacklists">';
335 $out .= '</td>';
336 $out .= '</tr>';
337 $out .= '</tbody>';
338 $out .= '</table>';
339
340 $out .= $form->buttonsSaveCancel("Add", "");
341 $out .= '</form>';
342
343 $out .= "<br>";
344 $out .= "<br>";
345
346 $out .= '</div>';
347
348 print $out;
349}
350
351if ($action == 'edit' || $action == 'create' || $action == 'deleteproperty') {
352 $out = '';
353
354 if (empty($currentConfigurations)) {
355 if ($action != 'create') {
356 print '<!-- no custom prompt-->'."\n";
357 print '<span class="opacitymedium">'.$langs->trans("None").'</span>';
358 print '<br>';
359 print '<br>';
360 }
361 print '<br>';
362 } else {
363 print '<br>';
364
365 foreach ($currentConfigurations as $confkey => $config) {
366 if (!empty($confkey) && !preg_match('/^[a-z]+$/i', $confkey)) { // Ignore empty saved setup
367 continue;
368 }
369
370 $out .= '<form action="'.$_SERVER["PHP_SELF"].'" method="POST">';
371 $out .= '<input type="hidden" name="token" value="'.newToken().'">';
372 $out .= '<input type="hidden" name="key" value="'.$confkey.'" />';
373 $out .= '<input type="hidden" name="action" value="updatePrompts">';
374 $out .= '<input type="hidden" name="page_y" value="">';
375
376 $out .= '<table class="noborder centpercent">';
377 $out .= '<thead>';
378 $out .= '<tr class="liste_titre">';
379 $out .= '<td class="titlefield">'.$arrayofaifeatures[$confkey]['picto'].' '.$langs->trans($arrayofaifeatures[$confkey]['label']);
380 $out .= '<a class="deletefielda reposition marginleftonly right" href="'.$_SERVER["PHP_SELF"].'?action=deleteproperty&token='.newToken().'&key='.urlencode($confkey).'">'.img_delete().'</a>';
381 $out .= '</td>';
382 $out .= '<td></td>';
383 $out .= '</tr>';
384 $out .= '</thead>';
385 $out .= '<tbody>';
386
387 $out .= '<tr class="oddeven">';
388 $out .= '<td class="col-setup-title">';
389 $out .= '<span id="prePrompt" class="spanforparamtooltip">'.$langs->trans("Pre-Prompt").'</span>';
390 $out .= '</td>';
391 $out .= '<td>';
392 $out .= '<textarea class="flat minwidth500 quatrevingtpercent" id="prePromptInput_'.$confkey.'" name="prePrompt" rows="2">'.$config['prePrompt'].'</textarea>';
393 $out .= '</td>';
394 $out .= '</tr>';
395
396 $out .= '<tr class="oddeven">';
397 $out .= '<td class="col-setup-title">';
398 $out .= '<span id="postPrompt" class="spanforparamtooltip">'.$langs->trans("Post-Prompt").'</span>';
399 $out .= '</td>';
400 $out .= '<td>';
401 $out .= '<textarea class="flat minwidth500 quatrevingtpercent" id="postPromptInput_'.$confkey.'" name="postPrompt" rows="2">'.$config['postPrompt'].'</textarea>';
402 $out .= '</td>';
403 $out .= '</tr>';
404
405 $out .= '<tr id="fichetwothirdright-'.$confkey.'" class="oddeven">';
406 $out .= '<td>'.$form->textwithpicto($langs->trans("BlackListWords"), $langs->trans("BlackListWordsHelp")).'</td>';
407 $out .= '<td>';
408 $out .= '<input type="text" class="flat minwidth500 quatrevingtpercent" id="blacklist_'.$confkey.'" name="blacklists" value="'.(isset($config['blacklists']) ? implode(', ', (array) $config['blacklists']) : '').'">';
409 $out .= '</td>';
410 $out .= '</tr>';
411
412 $out .= '<tr>';
413 $out .= '<td>'.$langs->trans("Test").'</td>';
414 $out .= '<td>';
415
416 include_once DOL_DOCUMENT_ROOT.'/core/class/html.formmail.class.php';
417 $formmail = new FormMail($db);
418 $formmail->withaiprompt = 'html'; // set format
419
420 $showlinktoai = $confkey; // 'textgenerationemail', 'textgenerationwebpage', 'imagegeneration', ...
421 $showlinktoailabel = $langs->trans("ToTest");
422 $htmlname = $confkey;
423 $onlyenhancements = $confkey;
424 $showlinktolayout = 0;
425
426 // Fill $out
427 include DOL_DOCUMENT_ROOT.'/core/tpl/formlayoutai.tpl.php';
428
429 $out .= '<div id="'.$htmlname.'"></div>';
430
431 $out .= '</td>';
432 $out .= '</tr>';
433
434 $out .= '</tbody>';
435 $out .= '</table>';
436
437 $out .= '<center><input type="submit" class="button small submitBtn reposition" name="modify" data-index="'.$confkey.'" value="'.dol_escape_htmltag($langs->trans("Save")).'"/></center>';
438
439 $out .= '</form>';
440
441 $out .= '<br><br>';
442 }
443 }
444
445 print $out;
446
447 print '<br>';
448}
449
450// Availability alert: when the adapter recorded a runtime "model not found /
451// retired" provider error, warn on screen on the page where the models are
452// actually fixed, suggesting the closest model currently offered. Warn only —
453// nothing is changed automatically.
454$runfail = json_decode(getDolGlobalString('AI_MODEL_RUNTIME_FAILURE'), true);
455// Only warn about the provider and model in use now: a record left by another
456// provider describes a setup the administrator has already moved away from.
457$runfailservice = is_array($runfail) ? (string) ($runfail['service'] ?? '') : '';
458if ($runfailservice !== '' && $runfailservice !== getDolGlobalString('AI_API_SERVICE')) {
459 $runfail = null;
460}
461if (is_array($runfail) && !empty($runfail['model'])) {
462 $msg = $langs->trans(
463 "AIModelRuntimeFailureBanner",
464 dol_escape_htmltag((string) $runfail['model']),
465 dol_print_date((int) ($runfail['ts'] ?? 0), 'dayhour'),
466 dol_escape_htmltag((string) ($runfail['message'] ?? ''))
467 );
468 $modellist = getAiProviderModelList($db);
469 if (!empty($modellist['models'])) {
470 $suggest = aiSuggestClosestModel((string) $runfail['model'], $modellist['models']);
471 if ($suggest !== '') {
472 $msg .= ' '.dol_escape_htmltag($langs->trans("AIModelClosestAvailable", $suggest));
473 }
474 }
475 print info_admin($msg, 0, 0, 'warning');
476}
477
478// Custom models
479if ($action == 'edit' || $action == 'create' || $action == 'deleteproperty') {
480 print load_fiche_titre($langs->trans("AIModelForFeature", $arrayofai[$aiservice]['label']), '', '');
481
482 print $formSetup->generateOutput(true);
483}
484
485
486if (empty($setupnotempty)) {
487 print '<br>'.$langs->trans("NothingToSetup");
488}
489
490
491// Datalist of the provider's available model ids (fed by ajax/list_models.php,
492// cached 1h server-side): every *_MODEL_* text input gets autocompletion, which
493// avoids typos in the seven free-text model fields. The fields stay plain free
494// text (a datalist only suggests, never constrains — required for local AI
495// providers with no model-listing API, where this whole block is a no-op).
496// Active check: a saved model absent from the provider's current list gets a
497// warning picto — warn only, never block, since a listing can be incomplete
498// (aliases, fine-tunes) while the value still works.
499print '<datalist id="ai-model-ids"></datalist>'."\n";
500print '<script nonce="'.getNonce().'">
501fetch("'.dol_buildpath('/ai/ajax/list_models.php', 1).'").then(function (r) { return r.json(); }).then(function (j) {
502 if (!j || !j.models || !j.models.length) return;
503 var dl = document.getElementById("ai-model-ids");
504 j.models.forEach(function (id) { var o = document.createElement("option"); o.value = id; dl.appendChild(o); });
505 document.querySelectorAll("input[name*=\'_MODEL_\']").forEach(function (i) {
506 i.setAttribute("list", "ai-model-ids");
507 if (i.value && j.models.indexOf(i.value) < 0) {
508 // Closest-match suggestion: longest shared prefix with an offered id
509 var v = i.value.toLowerCase(), best = "", bestlen = 0;
510 j.models.forEach(function (m) {
511 var b = m.toLowerCase(), n = 0;
512 while (n < v.length && n < b.length && v.charAt(n) === b.charAt(n)) n++;
513 if (n > bestlen) { bestlen = n; best = m; }
514 });
515 var w = document.createElement("span");
516 w.className = "fas fa-exclamation-triangle pictowarning paddingleft";
517 w.title = \''.dol_escape_js($langs->trans("AIModelNotInProviderList")).'\';
518 if (best && bestlen >= 4) {
519 w.title += \' \' + \''.dol_escape_js($langs->trans("AIModelClosestAvailable", '{m}')).'\'.replace("{m}", best);
520 }
521 i.insertAdjacentElement("afterend", w);
522 }
523 });
524}).catch(function () {});
525</script>'."\n";
526
527// Page end
528print dol_get_fiche_end();
529
530llxFooter();
531$db->close();
dolibarr_set_const($db, $name, $value, $type='chaine', $visible=0, $note='', $entity=1)
Insert a parameter (key,value) into database (delete old key then insert it again).
getListOfAIFeatures()
Prepare admin pages header.
Definition ai.lib.php:37
aiAdminPrepareHead()
Prepare admin pages header.
Definition ai.lib.php:531
getAiProviderModelList($db, $forcerefresh=false)
Return the list of model ids offered by the configured AI provider, with a 1-hour cache in the consta...
Definition ai.lib.php:624
getListOfAIServices()
Get list of available ai services.
Definition ai.lib.php:69
aiSuggestClosestModel($missing, array $models)
Suggest the closest available model id for a model that disappeared from the provider's list: same fa...
Definition ai.lib.php:711
ajax_combobox($htmlname, $events=array(), $minLengthToAutocomplete=0, $forcefocus=0, $widthTypeOfAutocomplete='resolve', $idforemptyvalue='-1', $morecss='', $placeholder='')
Convert a html select field into an ajax combobox.
Definition ajax.lib.php:477
if(!defined('NOREQUIRESOC')) if(!defined( 'NOREQUIRETRAN')) if(!defined('NOTOKENRENEWAL')) if(!defined( 'NOREQUIREMENU')) if(!defined('NOREQUIREHTML')) if(!defined( 'NOREQUIREAJAX')) llxHeader($head='', $title='', $help_url='', $target='', $disablejs=0, $disablehead=0, $arrayofjs='', $arrayofcss='', $morequerystring='', $morecssonbody='', $replacemainareaby='', $disablenofollow=0, $disablenoindex=0)
Empty header.
Definition wrapper.php:73
Class to generate HTML forms for single email Usage: $formai = new FormAI($db) $formai->proprietes=1 ...
Class to manage generation of HTML components Only common components must be here.
Class to manage a HTML form to send a unitary email Usage: $formail = new FormMail($db) $formmail->pr...
This class help you create setup render.
if(!isModEnabled('ai')||!getDolGlobalString('AI_ASSISTANT_ENABLED')) global $conf
The main.inc.php has been included so the following variable are now defined:
dol_escape_js($stringtoescape, $mode=0, $noescapebackslashn=0)
Returns text escaped for inclusion into JavaScript code.
newToken()
Return the value of token currently saved into session with name 'newtoken'.
GETPOST($paramname, $check='alphanohtml', $method=0, $filter=null, $options=null, $noreplace=0, $nodefault=0)
Return value of a param into GET or POST supervariable.
dol_buildpath($path, $type=0, $returnemptyifnotfound=0)
Return path of url or filesystem.
dol_print_date($time, $format='', $tzoutput='auto', $outputlangs=null, $encodetooutput=false, $decorate=0)
Output date in a string format according to outputlangs (or langs if not defined).
getDolGlobalString($key, $default='')
Return a Dolibarr global constant string value.
dol_sanitizeKeyCode($str)
Clean a string to use it as a key or code.
isModEnabled($module)
Is Dolibarr module enabled.
dol_get_fiche_head($links=array(), $active='', $title='', $notab=0, $picto='', $pictoisfullpath=0, $morehtmlright='', $morecss='', $limittoshow=0, $moretabssuffix='', $dragdropfile=0, $morecssdiv='')
Show tabs of a record.
Definition html.lib.php:540
dolGetButtonTitle($label, $helpText='', $iconClass='fa fa-file', $url='', $id='', $status=1, $params=array())
Function dolGetButtonTitle : this kind of buttons are used in title in list.
load_fiche_titre($title, $morehtmlright='', $picto='generic', $pictoisfullpath=0, $id='', $morecssontable='', $morehtmlcenter='', $morecssonpicto='widthpictotitle')
Load a title with picto.
info_admin($text, $infoonimgalt=0, $nodiv=0, $admin='1', $morecss='hideonsmartphone', $textfordropdown='', $picto='', $textonpictotooltip='', $cssfordropdown='info_admin')
Show information in HTML for admin users or standard users.
dol_escape_htmltag($stringtoescape, $keepb=0, $keepn=0, $noescapetags='', $escapeonlyhtmltags=0, $cleanalsojavascript=0)
Definition html.lib.php:181
accessforbidden($message='', $printheader=1, $printfooter=1, $showonlymessage=0, $params=null)
Show a message to say access is forbidden and stop program.