dolibarr 25.0.0-alpha
upload_page.php
Go to the documentation of this file.
1<?php
2/* Copyright (C) 2005-2017 Laurent Destailleur <eldy@users.sourceforge.net>
3 * Copyright (C) 2024-2025 Frédéric France <frederic.france@free.fr>
4 * Copyright (C) 2024-2026 MDW <mdeweerd@users.noreply.github.com>
5 *
6 * This file is a modified version of datepicker.php from phpBSM to fix some
7 * bugs, to add new features and to dramatically increase speed.
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
28require_once '../main.inc.php';
36require_once DOL_DOCUMENT_ROOT.'/core/class/html.form.class.php';
37require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
38require_once DOL_DOCUMENT_ROOT.'/ai/class/ai.class.php';
39require_once DOL_DOCUMENT_ROOT.'/societe/class/societe.class.php';
40require_once DOL_DOCUMENT_ROOT.'/product/class/product.class.php';
41require_once DOL_DOCUMENT_ROOT.'/fourn/class/fournisseur.facture.class.php';
42
43$langs->loadLangs(array("main", "exports", "other"));
44
45$action = GETPOST('action', 'aZ09');
46$modulepart = GETPOST('modulepart', 'aZ09');
47$socid = GETPOSTINT('socid');
48$prodid = GETPOSTINT('prodid');
49
50
51// users/temp/import
52$upload_dir = $conf->user->dir_temp.'/import';
53dol_mkdir($upload_dir);
54
55$file = GETPOST('file');
56
57$originalfilename = $file;
58$uid = $thiid = $pid = $erid = $salid = 0;
59$reg = array();
60if (preg_match('/-uid([\d+])/', $file, $reg)) {
61 $uid = $reg[1];
62 $originalfilename = preg_replace('/-uid\d+/', '', $originalfilename);
63}
64if (preg_match('/-thiid([\d+])/', $file, $reg)) {
65 $thiid = $reg[1];
66 $originalfilename = preg_replace('/-thiid\d+/', '', $originalfilename);
67}
68if (preg_match('/-pid([\d+])/', $file, $reg)) {
69 $pid = $reg[1];
70 $originalfilename = preg_replace('/-pid\d+/', '', $originalfilename);
71}
72if (preg_match('/-erid([\d+])/', $file, $reg)) {
73 $erid = $reg[1];
74 $originalfilename = preg_replace('/-erid\d+/', '', $originalfilename);
75}
76if (preg_match('/-salid([\d+])/', $file, $reg)) {
77 $salid = $reg[1];
78 $originalfilename = preg_replace('/-salid\d+/', '', $originalfilename);
79}
80$originalfilename = preg_replace('/^upload_page-[a-z_]+-/', '', $originalfilename);
81
82$error = 0;
83
84$ai = new Ai($db);
85$ajaxFileUrl = '';
86$fullnewname = '';
87
88
89/*
90 * Actions
91 */
92
93if (getDolGlobalString('MAIN_USE_TOP_MENU_IMPORT_FILE') && !is_numeric(getDolGlobalString('MAIN_USE_TOP_MENU_IMPORT_FILE'))) {
94 $urlforuploadpage = getDolGlobalString('MAIN_USE_TOP_MENU_IMPORT_FILE');
95
96 header("Location: ".$urlforuploadpage);
97 exit(1);
98}
99
100if ($action == 'uploadfile') { // Test on permission not required here. Done later
101 if (!$modulepart) { // Should not happen
102 print 'Error, modulepart param is empty';
103 exit(1);
104 }
105
106 // $modulepart can be 'invoice_supplier', ...
107 $arrayobject = getElementProperties($modulepart);
108
109 $module = $arrayobject['module'];
110 $element = $arrayobject['element'];
111 $dir_output = $arrayobject['dir_output'];
112 $dir_temp = $arrayobject['dir_temp'];
113
114 $permlevel1 = 'read';
115 $permlevel2 = '';
116 $fileprefix = 'unknown';
117 if (in_array($modulepart, array('fournisseur', 'invoice_supplier'))) {
118 $permlevel1 = 'facture';
119 $permlevel2 = 'read';
120 $fileprefix = 'upload_page-'.$modulepart.'-uid'.$user->id.'-thiid'.(GETPOSTINT('socid') > 0 ? GETPOSTINT('socid') : 0).'-pid'.(GETPOSTINT('search_prodid') > 0 ? GETPOSTINT('search_prodid') : 0);
121 } elseif ($modulepart == 'expensereport') {
122 $fileprefix = 'upload_page-'.$modulepart.'-uid'.$user->id.'-erid'.(GETPOSTINT('userexpensereportid') > 0 ? GETPOSTINT('userexpensereportid') : 0).'-pid'.(GETPOSTINT('search_prodid') > 0 ? GETPOSTINT('search_prodid') : 0);
123 } elseif ($modulepart == 'salaries') {
124 $fileprefix = 'upload_page-'.$modulepart.'-uid'.$user->id.'-salid'.(GETPOSTINT('usersalaryid') > 0 ? GETPOSTINT('usersalaryid') : 0);
125 }
126
127 if ($permlevel2) {
128 $permissiontoadd = $user->hasRight($module, $permlevel1, $permlevel2); // Used by actions_linkedfiles
129 } else {
130 $permissiontoadd = $user->hasRight($module, $permlevel1); // Used by actions_linkedfiles
131 }
132 $forceFullTextIndexation = '0'; // Used by actions_linkedfiles
133
134
135 if (!empty($_FILES['userfile']['name'])) {
136 $fullnewname = $fileprefix.'-'.$_FILES['userfile']['name'];
137 $_FILES['userfile']['name'] = $fullnewname;
138
139 // $dir_output = output dir of object
140 // $dir_temp = temp dir of object
141 // $upload_dir is "users/temp/import"
142 include DOL_DOCUMENT_ROOT.'/core/actions_linkedfiles.inc.php'; // Save uploaded file into $upload_dir (with overwrite if file already exists)
143
144 // Call AI to decrypt the file
145 // Use AJAX call instead of redirect
146 // @phpstan-ignore-next-line $error may have been modified by actions_linkedfiles.inc.php
147 if (!$error) {
148 // We will make the AJAX call from the bottom of the page
149 $ajaxFileUrl = DOL_URL_ROOT.'/core/ajax/ajaxuploadpage.php?file='.urlencode($fullnewname);
150 }
151 }
152} else {
153 // Delete the temporary files that are used when uploading files
154 dol_delete_file($upload_dir.'/upload_page-by'.$user->id.'-*');
155}
156
157
158/*
159 * View
160 */
161
162$form = new Form($db);
163
164// Important: Following code is to avoid page request by browser and PHP CPU at each Dolibarr page access.
165/*
166if (GETPOSTINT('cache')) {
167 header('Cache-Control: max-age='.GETPOSTINT('cache').', public');
168 // For a .php, we must set an Expires to avoid to have it forced to an expired value by the web server
169 header('Expires: '.gmdate('D, d M Y H:i:s', dol_now('gmt') + GETPOSTINT('cache')).' GMT');
170 // HTTP/1.0
171 header('Pragma: token=public');
172} else {
173 // HTTP/1.0
174 header('Cache-Control: no-cache');
175}
176*/
177
178$title = $langs->trans("UploadFile");
179$help_url = '';
180
181$arrayofjs = array();
182$arrayofcss = array();
183
184llxHeader('', $title, $help_url, '', 0, 0, $arrayofjs, $arrayofcss, '', 'mod-upload page-card');
185
186print load_fiche_titre('', '', '', 0, '', '', '<h2>'.img_picto('', 'upload').' '.$title.'</h2>');
187
188
189// Instantiate hooks of thirdparty module
190$hookmanager->initHooks(array('uploadform'));
191
192// Define $uploadform
193$uploadform = '';
194
195
196// Form to upload a supplier invoice
197if (empty($action)) {
198 $uploadform = '<div class="display-flex">';
199
200 if (isModEnabled('supplier_invoice')) {
201 $prodtext = $langs->trans("RefOrLabel");
202
203 $langs->load("bills");
204 $uploadform .= '
205 <div id="supplierinvoice" class="flex-item flex-item-uploadfile">'.img_picto('', 'bill', 'class="fa-2x"').'<br>
206 <div>'.$langs->trans("SupplierInvoice").'<br><br>';
207
208 //$uploadform .= '<div class="disableautoopen paddingbottom">';
209 //$uploadform .= '<input type="checkbox" name="newsupplierinvoice" id="newsupplierinvoice" value="1" checked="checked" class="disableautoopen"><label for="newsupplierinvoice" class="disableautoopen">'.$langs->trans("NewInvoice").'</label><br>';
210 //$uploadform .= '</div>';
211
212 $uploadform .= img_picto('', 'company', 'class="pictofixedwidth"');
213 $uploadform .= $form->select_company($socid, 'socid', '(statut:=:0)', $langs->transnoentitiesnoconv("Supplier"), 0, 0, array(), 0, 'maxwidth200 disableautoopen');
214
215 $uploadform .= '<br>';
216
217 //$uploadform .= $form->select_produits_fournisseurs(0, $prodid, 'prodid', '', '', 0, 1, 2, $prodtext, 0, array(), GETPOSTINT('socid'), '1', 0, 'maxwidth200 disableautoopen', 0, '', null, 1);
218 $uploadform .= img_picto('', 'product', 'class="pictofixedwidth"');
219 $uploadform .= $form->select_produits_fournisseurs(0, $prodid, 'prodid', '', '', array(), 1, 1, 'maxwidth200 disableautoopen', $prodtext, 1);
220
221 $uploadform .= '<br>';
222
223 $uploadform .= '<br>
224 <small class="opacitymedium">'.$langs->trans("OrClickToSelectAFile").'...</small>
225 </div>
226 </div>';
227 }
228
229 // Form to upload an expense report
230 if (isModEnabled('expensereport')) {
231 $langs->load("expensereport");
232 $uploadform .= '
233 <div id="userexpensereport" class="flex-item flex-item-uploadfile">'.img_picto('', 'expensereport', 'class="fa-2x"').'<br>
234 <div>'.$langs->trans("ExpenseReport").'<br><br>';
235
236 $uploadform .= img_picto('', 'user', 'class="pictofixedwidth"');
237 //$uploadform .= '<span class="disableautoopen">';
238 $uploadform .= $form->select_dolusers(GETPOSTINT('userexpensereportid') > 0 ? GETPOSTINT('userexpensereportid') : $user->id, 'userexpensereportid', $langs->transnoentitiesnoconv("User"), null, 0, 'hierarchyme', '', '', 0, 0, '', 0, '', 'maxwidth200 disableautoopen', 1);
239 //$uploadform .= '</span>';
240
241 $uploadform .= '<br>';
242
243 $uploadform .= '<br>
244 <small class="opacitymedium">'.$langs->trans("OrClickToSelectAFile").'...</small>
245 </div>
246 </div>';
247 }
248
249
250 // Form to upload a salary document
251 if (isModEnabled('salaries')) {
252 $langs->load("salaries");
253 $uploadform .= '
254 <div id="userpayroll" class="flex-item flex-item-uploadfile">'.img_picto('', 'salary', 'class="fa-2x"').'<br>
255 <div>'.$langs->trans("UserPaySlip").'<br><br>';
256
257
258 $uploadform .= img_picto('', 'user', 'class="pictofixedwidth"');
259 //$uploadform .= '<span class="disableautoopen">';
260 $uploadform .= $form->select_dolusers(GETPOSTINT('usersalaryid') > 0 ? GETPOSTINT('usersalaryid') : $user->id, 'usersalaryid', $langs->transnoentitiesnoconv("Employee"), null, 0, 'hierarchyme', '', '', 0, 0, '', 0, '', 'maxwidth200 disableautoopen', 1);
261 //$uploadform .= '</span>';
262
263 $uploadform .= '<br>';
264
265 $uploadform .= '<br>
266 <small class="opacitymedium">'.$langs->trans("OrClickToSelectAFile").'...</small>
267 </div>
268 </div>';
269 }
270
271 $uploadform .= '</div>';
272}
273
274
275
276// Execute hook printSearchForm
277$parameters = array('uploadform' => $uploadform);
278$reshook = $hookmanager->executeHooks('printUploadForm', $parameters); // Note that $action and $object may have been modified by some hooks
279if (empty($reshook)) {
280 $uploadform .= $hookmanager->resPrint;
281} else {
282 $uploadform = $hookmanager->resPrint;
283}
284
285$uploadform .= '<br>';
286
287
288if ($action == 'uploadfile' || $action == 'showsummary') {
289 print '<b>'.$langs->trans("ImportingFile", $originalfilename).'</b><br>';
290 print '<br>';
291
292 print '<div class="'.($action == 'showsummary' ? 'green' : 'neutral').'" style="padding-left: 20px; padding-right: 20px;">';
293
294 print '<div class="marginbottom">';
295 if ($action == 'showsummary') {
296 print $langs->trans("AIProcessingDone", $ai->getApiService());
297 } else {
298 print $langs->trans("AIProcessingPleaseWait", $ai->getApiService()).'...';
299 }
300 print '</div>';
301 print '<br>';
302
303 print '<div class="progress" title="80%">
304 <div class="progress-bar" role="progressbar" style="width: '.($action == 'showsummary' ? '100' : '0').'%" aria-valuenow="0" aria-valuemin="0" aria-valuemax="100"></div>
305 </div>';
306
307 print '</div>';
308
309 // Add AJAX call script
310 if (!empty($ajaxFileUrl)) {
311 print '<script>
312 $(document).ready(function() {
313 console.log("Call ajaxFileUrl: '.dol_escape_js($ajaxFileUrl).'");
314 $.ajax({
315 url: \''.dol_escape_js($ajaxFileUrl).'\',
316 type: "GET",
317 dataType: "json",
318 beforeSend: function() {
319 $(".progress-bar").css("width", "25%");
320 },
321 success: function(data, textStatus, jqXHR) {
322 if (jqXHR.status === 200) {
323 // Display the JSON content
324 console.log("Fill the #ajax-result with json result");
325 console.log(data);
326 $("#ajax-result").val(JSON.stringify(data, null, 2));
327 $(".progress-bar").css("width", "100%");
328 // Submit the form
329 //$("#form-result").submit();
330 $("#form-result-submit").show();
331 } else {
332 // Display error if status is not 200
333 $("#ajax-result").html("<div class=\"error\">Error: HTTP status " + jqXHR.status + "</div>");
334 }
335 },
336 error: function(jqXHR, textStatus, errorThrown) {
337 // Display error
338 $("#ajax-result").html("<div class=\"error\">Error: " + (jqXHR.responseText || errorThrown || "Unknown error") + "</div>");
339 $(".progress-bar").css("width", "100%");
340 }
341 });
342 });
343 </script>';
344 }
345
346 // Example of JSON result when importing a supplier PDF invoice
347 /* {
348 "document_info": {
349 "type": "Facture",
350 "invoice_number": "MSTRL-API-1234-001",
351 "invoice_reference": "Pro - Annual",
352 "issue_date": "2026-08-21",
353 "due_date": "2026-08-21",
354 "payment_terms": {
355 "days": 0,
356 "description": "0 jours"
357 },
358 "organization": "MyBigCompany"
359 },
360 "vendor": {
361 "name": "Mistral AI SAS",
362 "address": {
363 "street": "15, rue des Halles",
364 "postal_code": "75001",
365 "city": "Paris",
366 "country": "France"
367 },
368 "vat_number": "FR95952418325",
369 "professional_id": {
370 "siren": "952 418 325",
371 "capital": "19,189.04 €",
372 "rcs": "Paris"
373 },
374 "email": "no-reply@mistral.ai",
375 "contact_url": "https://help.mistral.ai/en"
376 },
377 "recipient": {
378 "name": "MyBigCompany",
379 "address": {
380 "street": "1 rue de la paix",
381 "postal_code": "75000",
382 "city": "Paris",
383 "country": "France"
384 },
385 "vat_number": "FR012345678901",
386 "email": "contact@mybigcompany.com"
387 },
388 "items": [
389 {
390 "description": "Fee for use- August",
391 "service": "Pro - Annual",
392 "quantity": 1,
393 "unit_price": 143.9,
394 "vat_rate": 20,
395 "total_excluding_tax": 143.9,
396 "total_including_tax": 172.68,
397 "period_start": "2026-08-21",
398 "period_end": "2027-08-20"
399 }
400 ],
401 "summary": {
402 "subtotal_excluding_tax": 143.9,
403 "tax": {
404 "rate": 20,
405 "amount": 28.78,
406 "description": "EU FR Standard (20.0% sur 143,90 €)"
407 },
408 "total_including_tax": 172.68
409 },
410 "payment_info": {
411 "due_date": "2026-08-21",
412 "amount_due": 172.68,
413 "currency": "EUR"
414 },
415 "other": {
416 "notes": [
417 {
418 "type": "legal",
419 "content": "Mistral AI - SAS au capital de 19,189.04€ - 952 418 325 R.C.S. Paris"
420 },
421 {
422 "type": "contact",
423 "content": "For any inquiry, please refer to https://help.mistral.ai/en"
424 }
425 ]
426 }
427 }
428 */
429
430 print '<form class="" id="form-result" method="POST">';
431 print '<input type="hidden" name="token" value="'.newToken().'">';
432 print '<input type="hidden" name="modulepart" value="'.$modulepart.'">';
433 print '<input type="hidden" name="action" value="showsummary">';
434 print '<input type="hidden" name="socid" value="'.$socid.'">';
435 print '<input type="hidden" name="prodid" value="'.$prodid.'">';
436 print '<input type="hidden" name="originalfilename" value="'.$fullnewname.'">';
437 print '<input type="hidden" name="jsonstring" id="ajax-result" value="jsonstringtoreplace">';
438 if ($action == 'uploadfile') {
439 print '<input type="submit" name="form-result-submit" class="" value="'.$langs->trans("Next").'">'; // TODO Hide.
440 }
441 print '</form>'."\n";
442 print "\n";
443}
444
445if ($action == 'showsummary') {
446 print '<form class="" id="summary-result">';
447 print '<br>';
448 print '<div class="neutral">';
449
450 print '<input type="hidden" name="token" value="'.newToken().'">';
451
452 $json = json_decode(GETPOST('jsonstring', 'restricthtml'), true);
453
454 if ($modulepart == 'invoice_supplier') {
455 print '
456 <div id="supplierinvoice" class="">';
457
458 //print '<div class="inline-block">'.img_picto('', 'bill', '').' '.$langs->trans("SupplierInvoice").'</div>';
459 //print '<br><br>';
460
461 $nameindoc = $json['vendor']['name'];
462 $addressindoc = $json['vendor']['address'];
463 $idprof1indoc = $json['professional_id']['siren'];
464 $idprof2indoc = $json['supplier']['siret'];
465 $emailindoc = $json['email'];
466 $vatnumberindoc = $json['vat_number'];
467
468 // Thirdparty
469 $tmpthirdparty = new Societe($db);
470 print img_picto('', 'company', 'class="pictofixedwidth"').$langs->trans("ThirdParty").'<br>';
471 if (GETPOSTINT('socid')) {
472 $tmpthirdparty->fetch(GETPOSTINT('socid'));
473 // TODO We can show a warning if we find a diff with autodetected value $nameindoc
474 } else {
475 // Try to find thirdparty
476 $result = $tmpthirdparty->findNearest(0, $nameindoc, '', '', $idprof1indoc, $idprof2indoc, '', '', '', '', $emailindoc, $vatnumberindoc, 0, 0, '1');
477
478 if ($result > 0) {
479 $tmpthirdparty->id = $result;
480 }
481 }
482
483 print '<span class="opacitymedium">'.$langs->trans("FoundInDocument").' :</span> ';
484 print $nameindoc.', &nbsp;'.implode(', ', $addressindoc);
485 print '<br>';
486 if (empty($tmpthirdparty->id)) {
487 print '<span class="opacitymedium">'.$langs->trans("NotFoundInDatabase").'</span><br>';
488 print $langs->trans("ChooseTheThirdPartyTouse").' ';
489 print $form->select_company($socid, 'socid', '(statut:=:0)', $langs->trans("Name"), 0, 0, array(), 0, 'maxwidth200 disableautoopen');
490 //print ' &nbsp; '.$langs->trans("or").' &nbsp; <input type="checkbox" name="createthirdparty" id="createthirdparty" value="1" checked><label for="createthirdparty"> '.$langs->trans("CreateIt").'</label>';
491 } else {
492 print $langs->trans("WillUse").' ';
493 print $tmpthirdparty->getNomUrl(1);
494 print '<input type="hidden" name="socid" value="'.$tmpthirdparty->id.'">';
495 }
496
497
498 print '<br><br>';
499
500
501 $nameprodindoc = $json['items'][0]['description'];
502
503
504 // Product
505 $prodid = GETPOSTINT('prodid');
506 $prodtext = $langs->trans("RefOrLabel");
507
508 $tmpproduct = new Product($db);
509 print img_picto('', 'product', 'class="pictofixedwidth"').$langs->trans("Product").'<br>';
510
511 if ($prodid) {
512 $tmpproduct->fetch($prodid);
513 // TODO We can show a warning if we find a diff with autodetected value $json['items']['service']
514 } else {
515 //$tmpproduct->ref = $json['ref'];
516 }
517
518 print '<span class="opacitymedium">'.$langs->trans("FoundInDocument").' :</span> ';
519 print $nameprodindoc;
520 print '<br>';
521 if (empty($tmpproduct->id)) {
522 print $langs->trans("ChooseTheProductTouse").' ';
523 print $form->select_produits_fournisseurs(0, $prodid, 'prodid', '', '', array(), 1, 1, 'maxwidth200 disableautoopen', $prodtext, 1);
524 } else {
525 print $langs->trans("WillUse").' ';
526 print $tmpproduct->getNomUrl(1);
527 print '<input type="hidden" name="prodid" value="'.$tmpproduct->id.'">';
528 }
529
530
531 print '<br><br>';
532
533 $tmpinvoice = new FactureFournisseur($db);
534
535 $invoiceindoc = $ai->decodeJsonIntoArray($json, 'supplier_invoice');
536
537 print img_picto('', 'supplier_invoice', 'class="pictofixedwidth"').$langs->trans("SupplierInvoice").'<br>';
538
539 print '<span class="opacitymedium">'.$langs->trans("FoundInDocument").' :</span> ';
540 print $invoiceindoc['supplierref'].' - '.$invoiceindoc['due_date'].' - '.$invoiceindoc['issue_date'];
541 print ' - '.$invoiceindoc['currency_code'];
542 print '<br>';
543
544 // Supplier invoice
545 if (!empty($invoiceindoc['supplierref'])) {
546 // Try to find supplier invoice
547 // TODO Search using ref (see code of einvoicing module)
548 //$tmpinvoice->find...
549 }
550
551 if (empty($tmpinvoice->id)) {
552 print $langs->trans("InvoiceWillBeCreated");
553 } else {
554 print $tmpinvoice->getNomUrl(1);
555 print '<input type="hidden name="invoiceid" value="'.$tmpinvoice->id.'">';
556 }
557
558 print '<br>
559
560 </div>
561 </div>';
562
563 print '<center><input type="submit" name="submit" class="button" value="'.$langs->trans("Create").'"></center>';
564 }
565
566 print '<input type="hidden" name="jsonstring" value="'.$json.'">';
567
568 print '</div>';
569 print '</form>';
570} else {
571 // Show all forms
572 print "\n";
573 print "<!-- Begin UploadForm -->\n";
574 print '<form id="uploadform" enctype="multipart/form-data" method="POST" action="'.dolBuildUrl($_SERVER["PHP_SELF"]).'">';
575 print '<input type="hidden" name="token" value="'.newToken().'">';
576 print '<input type="hidden" name="action" value="uploadfile">';
577 print '<input type="hidden" name="sendit" value="1">';
578 print '<input type="hidden" name="modulepart" id="modulepart" value="">';
579 print '<input type="hidden" name="overwritefile" value="1">';
580
581 print '<div class="center"><div class="center" style="padding: 10px;">';
582 print '<style>.menu_titre { padding-top: 7px; }</style>';
583 print '<div id="blockupload" class="center">'."\n";
584 //print '<input name="filenamePDF" id="filenamePDF" type="hideobject">';
585 print $uploadform;
586
587
588 $accept = '.pdf,image/*';
589 $disablemulti = 1;
590 $perm = 1;
591 $capture = 1;
592
593 $maxfilesizearray = getMaxFileSizeArray();
594 $max = $maxfilesizearray['max'];
595 $maxmin = $maxfilesizearray['maxmin'];
596 $maxphptoshow = $maxfilesizearray['maxphptoshow'];
597 $maxphptoshowparam = $maxfilesizearray['maxphptoshowparam'];
598 $out = '';
599 if ($maxmin > 0) {
600 $out .= '<input type="hidden" name="MAX_FILE_SIZE" value="'.($maxmin * 1024).'">'; // MAX_FILE_SIZE must precede the field type=file
601 }
602 $out .= '<input class="hideobject" type="file" id="fileInput" value=""';
603 // @phpstan-ignore-next-line
604 $out .= ((getDolGlobalString('MAIN_DISABLE_MULTIPLE_FILEUPLOAD') || $disablemulti) ? ' name="userfile"' : ' name="userfile[]" multiple');
605 // @phpstan-ignore-next-line
606 $out .= (!getDolGlobalString('MAIN_UPLOAD_DOC') || empty($perm) ? ' disabled' : '');
607 // @phpstan-ignore-next-line
608 $out .= (!empty($accept) ? ' accept="'.$accept.'"' : ' accept=""');
609 // @phpstan-ignore-next-line
610 $out .= (!empty($capture) ? ' capture="capture"' : '');
611 $out .= '>';
612
613 print $out;
614
615
616 print "<script>
617 $(document).ready(function() {
618 jQuery('#supplierinvoice:not(.disableautoopen)').on('click', function(event) {
619 console.log('Click on link supplierinvoice to open input file');
620 console.log(event);
621 if (!event.target.closest('.disableautoopen')) {
622 $('#modulepart').val('invoice_supplier');
623 $('#fileInput').click();
624 }
625 });
626
627 jQuery('#userexpensereport:not(.disableautoopen)').on('click', function(event) {
628 console.log('Click on link userexpensereport to open input file');
629 console.log(event);
630 if (!event.target.closest('.disableautoopen')) {
631 $('#modulepart').val('expensereport');
632 $('#fileInput').click();
633 }
634 });
635
636 jQuery('#userpayroll:not(.disableautoopen)').on('click', function(event) {
637 console.log('Click on link userpayroll to open input file');
638 console.log(event);
639 if (!event.target.closest('.disableautoopen')) {
640 $('#modulepart').val('salaries');
641 $('#fileInput').click();
642 }
643 });
644
645 jQuery('#fileInput').on('change', function(event) {
646 console.log(event);
647 console.log('A file was selected, we submit the form');
648 $('#uploadform').submit();
649 });
650 });
651 </script>";
652
653 print '</div>'."\n";
654 print '</div></div>';
655
656 print '</form>';
657 print "\n<!-- End UploadForm -->\n";
658}
659
660
661// End of page
662llxFooter();
663$db->close();
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
$object ref
Definition info.php:90
Class for AI feature.
Definition ai.class.php:36
Class to manage generation of HTML components Only common components must be here.
print $script_file $mode $langs defaultlang(is_numeric($duration_value) ? " delay=". $duration_value :"").(is_numeric($duration_value2) ? " after cd cd cd description as p label as s rowid as s nom as s email
Sender: Who sends the email ("Sender" has sent emails on behalf of "From").
print $script_file $mode $langs defaultlang(is_numeric($duration_value) ? " delay=". $duration_value :"").(is_numeric($duration_value2) ? " after cd cd cd description as description
Only used if Module[ID]Desc translation string is not found.
if(!isModEnabled('ai')||!getDolGlobalString('AI_ASSISTANT_ENABLED')) global $conf
The main.inc.php has been included so the following variable are now defined:
if(!isModEnabled('ai')||!getDolGlobalString('AI_ASSISTANT_ENABLED')) global $db
API class for accounts.
dol_delete_file($file, $disableglob=0, $nophperrors=0, $nohook=0, $object=null, $allowdotdot=false, $indexdatabase=1, $nolog=0)
Remove a file or several files with a mask.
getElementProperties($elementType)
Get an array with properties of an element.
dol_escape_js($stringtoescape, $mode=0, $noescapebackslashn=0)
Returns text escaped for inclusion into JavaScript code.
GETPOST($paramname, $check='alphanohtml', $method=0, $filter=null, $options=null, $noreplace=0, $nodefault=0)
Return value of a param into GET or POST supervariable.
GETPOSTINT($paramname, $method=0, $nodefault=0)
Return the value of a $_GET or $_POST supervariable, converted into integer.
getDolGlobalString($key, $default='')
Return a Dolibarr global constant string value.
isModEnabled($module)
Is Dolibarr module enabled.
dol_mkdir($dir, $dataroot='', $newmask='')
Creation of a directory (this can create recursive subdir)
multi select button
0 = Do not include form tag and submit button -1 = Do not include form tag but include submit button
div refaddress div address
img_picto($titlealt, $picto, $moreatt='', $pictoisfullpath=0, $srconly=0, $notitle=0, $alt='', $morecss='', $marginleftonlyshort=2, $allowothertags=array())
Show picto whatever it's its name (generic function)
load_fiche_titre($title, $morehtmlright='', $picto='generic', $pictoisfullpath=0, $id='', $morecssontable='', $morehtmlcenter='', $morecssonpicto='widthpictotitle')
Load a title with picto.
if(preg_match('/(crypted|dolcrypt):/i', $dolibarr_main_db_pass)||!empty($dolibarr_main_db_encrypted_pass)) $conf db type
'integer', 'integer:ObjectClass:PathToClass[:AddCreateButtonOrNot[:Filter[:Sortfield]]]',...
Definition repair.php:130
$conf db name
Only used if Module[ID]Name translation string is not found.
Definition repair.php:133