dolibarr 23.0.3
import_csv.modules.php
Go to the documentation of this file.
1<?php
2/* Copyright (C) 2006-2012 Laurent Destailleur <eldy@users.sourceforge.net>
3 * Copyright (C) 2009-2012 Regis Houssin <regis.houssin@inodbox.com>
4 * Copyright (C) 2012 Christophe Battarel <christophe.battarel@altairis.fr>
5 * Copyright (C) 2012-2016 Juanjo Menent <jmenent@2byte.es>
6 * Copyright (C) 2024 Frédéric France <frederic.france@free.fr>
7 * Copyright (C) 2024 MDW <mdeweerd@users.noreply.github.com>
8 * Copyright (C) 2026 Alexandre Spangaro <alexandre@inovea-conseil.com>
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 3 of the License, or
13 * (at your option) any later version.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this program. If not, see <https://www.gnu.org/licenses/>.
22 * or see https://www.gnu.org/
23 */
24
31require_once DOL_DOCUMENT_ROOT.'/core/modules/import/modules_import.php';
32
33
38{
42 public $db;
43
47 public $id;
48
53 public $version = 'dolibarr';
54
58 public $label_lib;
59
63 public $version_lib;
64
68 public $separator;
69
73 public $file; // Path of file
74
78 public $handle; // File handle
79
80 public $cacheconvert = array(); // Array to cache list of value found after a conversion
81
82 public $cachefieldtable = array(); // Array to cache list of value found into fields@tables
83
84 public $nbinsert = 0; // # of insert done during the import
85
86 public $nbupdate = 0; // # of update done during the import
87
88 public $charset = '';
89
93 public $col;
94
95
102 public function __construct($db, $datatoimport)
103 {
104 global $langs;
105
106 parent::__construct();
107 $this->db = $db;
108
109 $this->separator = (GETPOST('separator') ? GETPOST('separator') : getDolGlobalString('IMPORT_CSV_SEPARATOR_TO_USE', ','));
110 $this->enclosure = '"';
111 $this->escape = '"';
112
113 $this->id = 'csv'; // Same value then xxx in file name export_xxx.modules.php
114 $this->label = 'Csv'; // Label of driver
115 $this->desc = $langs->trans("CSVFormatDesc", $this->separator, $this->enclosure, $this->escape);
116 $this->extension = 'csv'; // Extension for generated file by this driver
117 $this->picto = 'mime/other'; // Picto
118 $this->version = '1.34'; // Driver version
119 $this->phpmin = array(7, 0); // Minimum version of PHP required by module
120
121 require_once DOL_DOCUMENT_ROOT.'/core/lib/admin.lib.php';
122 if (versioncompare($this->phpmin, versionphparray()) > 0) {
123 dol_syslog("Module need a higher PHP version");
124 $this->error = "Module need a higher PHP version";
125 return;
126 }
127
128 // If driver use an external library, put its name here
129 $this->label_lib = 'Dolibarr';
130 $this->version_lib = DOL_VERSION;
131
132 $this->datatoimport = $datatoimport;
133 if (preg_match('/^societe_/', $datatoimport)) {
134 $this->thirdpartyobject = new Societe($this->db);
135 }
136 }
137
138
139 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
146 public function write_header_example($outputlangs)
147 {
148 // phpcs:enable
149 return '';
150 }
151
152 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
160 public function write_title_example($outputlangs, $headerlinefields)
161 {
162 // phpcs:enable
163 $s = implode($this->separator, array_map('cleansep', $headerlinefields));
164 return $s."\n";
165 }
166
167 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
175 public function write_record_example($outputlangs, $contentlinevalues)
176 {
177 // phpcs:enable
178 $s = implode($this->separator, array_map('cleansep', $contentlinevalues));
179 return $s."\n";
180 }
181
182 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
189 public function write_footer_example($outputlangs)
190 {
191 // phpcs:enable
192 return '';
193 }
194
195
196 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
203 public function import_open_file($file)
204 {
205 // phpcs:enable
206 global $langs;
207 $ret = 1;
208
209 dol_syslog(get_class($this)."::open_file file=".$file);
210
211 ini_set('auto_detect_line_endings', 1); // For MAC compatibility
212
213 $handle = fopen(dol_osencode($file), "r");
214 if (!$handle) {
215 $langs->load("errors");
216 $this->error = $langs->trans("ErrorFailToOpenFile", $file);
217 $ret = -1;
218 } else {
219 $this->handle = $handle;
220 $this->file = $file;
221 }
222
223 return $ret;
224 }
225
226
227 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
234 public function import_get_nb_of_lines($file)
235 {
236 // phpcs:enable
237 return dol_count_nb_of_line($file);
238 }
239
240
241 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
247 public function import_read_header()
248 {
249 // phpcs:enable
250 return 0;
251 }
252
253
254 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
260 public function import_read_record()
261 {
262 // phpcs:enable
263 global $conf;
264
265 $arrayres = fgetcsv($this->handle, 100000, $this->separator, $this->enclosure, $this->escape);
266
267 // End of file
268 if ($arrayres === false) {
269 return false;
270 }
271
272 //var_dump($this->handle);
273 //var_dump($arrayres);exit;
274 $newarrayres = array();
275 $key = 1; // Default value to ensure $key is declared
276
277 if ($arrayres && is_array($arrayres)) {
278 foreach ($arrayres as $key => $val) {
279 if (getDolGlobalString('IMPORT_CSV_FORCE_CHARSET')) { // Forced charset
280 if (strtolower($conf->global->IMPORT_CSV_FORCE_CHARSET) == 'utf8') {
281 $newarrayres[$key]['val'] = $val;
282 $newarrayres[$key]['type'] = (dol_strlen($val) ? 1 : -1); // If empty we consider it's null
283 } else {
284 $newarrayres[$key]['val'] = mb_convert_encoding($val, 'UTF-8', 'ISO-8859-1');
285 $newarrayres[$key]['type'] = (dol_strlen($val) ? 1 : -1); // If empty we consider it's null
286 }
287 } else { // Autodetect format (UTF8 or ISO)
288 if (utf8_check($val)) {
289 $newarrayres[$key]['val'] = $val;
290 $newarrayres[$key]['type'] = (dol_strlen($val) ? 1 : -1); // If empty we consider it's null
291 } else {
292 $newarrayres[$key]['val'] = mb_convert_encoding($val, 'UTF-8', 'ISO-8859-1');
293 $newarrayres[$key]['type'] = (dol_strlen($val) ? 1 : -1); // If empty we consider it's null
294 }
295 }
296 }
297
298 $this->col = count($newarrayres);
299 }
300
301 return $newarrayres;
302 }
303
304 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
310 public function import_close_file()
311 {
312 // phpcs:enable
313 fclose($this->handle);
314 return 0;
315 }
316
317
318 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
330 public function import_insert($arrayrecord, $array_match_file_to_database, $objimport, $maxfields, $importid, $updatekeys)
331 {
332 // phpcs:enable
333 global $langs, $conf, $user;
334 global $thirdparty_static; // Specific to thirdparty import
335 global $tablewithentity_cache; // Cache to avoid to call desc at each rows on tables
336
337 $error = 0;
338 $warning = 0;
339 $this->errors = array();
340 $this->warnings = array();
341
342 //dol_syslog("import_csv.modules maxfields=".$maxfields." importid=".$importid);
343
344 //var_dump($array_match_file_to_database);
345 //var_dump($arrayrecord); exit;
346
347 $array_match_database_to_file = array_flip($array_match_file_to_database);
348 $sort_array_match_file_to_database = $array_match_file_to_database;
349 ksort($sort_array_match_file_to_database);
350
351 //var_dump($sort_array_match_file_to_database);
352
353 if (count($arrayrecord) == 0 || (count($arrayrecord) == 1 && empty($arrayrecord[0]['val']))) {
354 //print 'W';
355 $this->warnings[$warning]['lib'] = $langs->trans('EmptyLine');
356 $this->warnings[$warning]['type'] = 'EMPTY';
357 $warning++;
358 } else {
359 $last_insert_id_array = array(); // store the last inserted auto_increment id for each table, so that dependent tables can be inserted with the appropriate id (eg: extrafields fk_object will be set with the last inserted object's id)
360 $updatedone = false;
361 $insertdone = false;
362 // For each table to insert, me make a separate insert
363 foreach ($objimport->array_import_tables[0] as $alias => $tablename) {
364 // Build sql request
365 $sql = '';
366 $listfields = array();
367 $listvalues = array();
368 $i = 0;
369 $errorforthistable = 0;
370
371 // Define $tablewithentity_cache[$tablename] if not already defined
372 if (!isset($tablewithentity_cache[$tablename])) { // keep this test with "isset"
373 dol_syslog("Check if table ".$tablename." has an entity field");
374 $resql = $this->db->DDLDescTable($tablename, 'entity');
375 if ($resql) {
376 $obj = $this->db->fetch_object($resql);
377 if ($obj) {
378 $tablewithentity_cache[$tablename] = 1; // table contains entity field
379 } else {
380 $tablewithentity_cache[$tablename] = 0; // table does not contain entity field
381 }
382 } else {
383 dol_print_error($this->db);
384 }
385 } else {
386 //dol_syslog("Table ".$tablename." check for entity into cache is ".$tablewithentity_cache[$tablename]);
387 }
388
389 // Define an array to convert fields ('c.ref', ...) into column index (1, ...)
390 $arrayfield = array();
391 foreach ($sort_array_match_file_to_database as $key => $val) {
392 $arrayfield[$val] = ($key - 1);
393 }
394
395 // $arrayrecord start at key 0
396 // $sort_array_match_file_to_database start at key 1
397
398 // Loop on each fields in the match array: $key = 1..n, $val=alias of field (s.nom)
399 foreach ($sort_array_match_file_to_database as $key => $val) {
400 $fieldalias = preg_replace('/\..*$/i', '', $val);
401 $fieldname = preg_replace('/^.*\./i', '', $val);
402
403 if ($alias != $fieldalias) {
404 continue; // Not a field of current table
405 }
406
407 if ($key <= $maxfields) {
408 // Set $newval with value to insert and set $listvalues with sql request part for insert
409 $newval = '';
410 if ($arrayrecord[($key - 1)]['type'] > 0) {
411 $newval = $arrayrecord[($key - 1)]['val']; // If type of field into input file is not empty string (so defined into input file), we get value
412 }
413
414 //var_dump($newval);var_dump($val);
415 //var_dump($objimport->array_import_convertvalue[0][$val]);
416
417 // Make some tests on $newval
418
419 // Is it a required field ?
420 if (preg_match('/\*/', $objimport->array_import_fields[0][$val]) && ((string) $newval == '')) {
421 // @phan-suppress-next-line PhanPluginSuspiciousParamPosition
422 $this->errors[$error]['lib'] = $langs->trans('ErrorMissingMandatoryValue', $key);
423 $this->errors[$error]['type'] = 'NOTNULL';
424 $errorforthistable++;
425 $error++;
426 } else {
427 // Test format only if field is not a missing mandatory field (field may be a value or empty but not mandatory)
428 // We convert field if required
429 if (!empty($objimport->array_import_convertvalue[0][$val])) {
430 //print 'Must convert '.$newval.' with rule '.join(',',$objimport->array_import_convertvalue[0][$val]).'. ';
431 if ($objimport->array_import_convertvalue[0][$val]['rule'] == 'fetchidfromcodeid'
432 || $objimport->array_import_convertvalue[0][$val]['rule'] == 'fetchidfromref'
433 || $objimport->array_import_convertvalue[0][$val]['rule'] == 'fetchidfromcodeorlabel'
434 ) {
435 // New val can be an id or ref. If it start with id: it is forced to id, if it start with ref: it is forced to ref. It not, we try to guess.
436 $isidorref = 'id';
437 if (!is_numeric($newval) && $newval != '' && !preg_match('/^id:/i', $newval)) {
438 $isidorref = 'ref';
439 }
440
441 $newval = preg_replace('/^(id|ref):/i', '', $newval); // Remove id: or ref: that was used to force if field is id or ref
442 //print 'Newval is now "'.$newval.'" and is type '.$isidorref."<br>\n";
443
444 if ($isidorref == 'ref') { // If value into input import file is a ref, we apply the function defined into descriptor
445 $file = (empty($objimport->array_import_convertvalue[0][$val]['classfile']) ? $objimport->array_import_convertvalue[0][$val]['file'] : $objimport->array_import_convertvalue[0][$val]['classfile']);
446 $class = $objimport->array_import_convertvalue[0][$val]['class'];
447 $method = $objimport->array_import_convertvalue[0][$val]['method'];
448 if (isset($this->cacheconvert[$file.'_'.$class.'_'.$method.'_'][$newval]) && $this->cacheconvert[$file.'_'.$class.'_'.$method.'_'][$newval] != $newval) {
449 $newval = $this->cacheconvert[$file.'_'.$class.'_'.$method.'_'][$newval];
450 } else {
451 $resultload = dol_include_once($file);
452 if (empty($resultload)) {
453 dol_print_error(null, 'Error trying to call file='.$file.', class='.$class.', method='.$method);
454 break;
455 }
456 $classinstance = new $class($this->db);
457 if ($class == 'CGenericDic') {
458 $classinstance->element = $objimport->array_import_convertvalue[0][$val]['element'];
459 $classinstance->table_element = $objimport->array_import_convertvalue[0][$val]['table_element'];
460 }
461
462 // Try the fetch from code or ref
463 $param_array = array('', $newval);
464 if ($class == 'AccountingAccount') {
465 //var_dump($arrayrecord[0]['val']);
466 /*include_once DOL_DOCUMENT_ROOT.'/accountancy/class/accountancysystem.class.php';
467 $tmpchartofaccount = new AccountancySystem($this->db);
468 $tmpchartofaccount->fetch(getDolGlobalInt('CHARTOFACCOUNTS'));
469 //var_dump($tmpchartofaccount->ref.' - '.$arrayrecord[0]['val']);
470 if ((! (getDolGlobalInt('CHARTOFACCOUNTS') > 0)) || $tmpchartofaccount->ref != $arrayrecord[0]['val'])
471 {
472 $this->errors[$error]['lib']=$langs->trans('ErrorImportOfChartLimitedToCurrentChart', $tmpchartofaccount->ref);
473 $this->errors[$error]['type']='RESTRICTONCURRENCTCHART';
474 $errorforthistable++;
475 $error++;
476 }*/
477 $param_array = array('', $newval, 0, $arrayrecord[0]['val']); // Param to fetch parent from account, in chart.
478 }
479 if ($class == 'CActionComm') {
480 $param_array = array($newval); // CActionComm fetch method have same parameter for id and code
481 }
482 $result = call_user_func_array(array($classinstance, $method), $param_array);
483
484 // If duplicate record found
485 if (!($classinstance->id != '') && $result == -2) {
486 $this->errors[$error]['lib'] = $langs->trans('ErrorMultipleRecordFoundFromRef', $newval);
487 $this->errors[$error]['type'] = 'FOREIGNKEY';
488 $errorforthistable++;
489 $error++;
490 }
491
492 // If not found, try the fetch from label
493 if (!($classinstance->id != '') && $objimport->array_import_convertvalue[0][$val]['rule'] == 'fetchidfromcodeorlabel') {
494 $param_array = array('', '', $newval);
495 call_user_func_array(array($classinstance, $method), $param_array);
496 }
497 $this->cacheconvert[$file.'_'.$class.'_'.$method.'_'][$newval] = $classinstance->id;
498
499 //print 'We have made a '.$class.'->'.$method.' to get id from code '.$newval.'. ';
500 if ($classinstance->id != '') { // id may be 0, it is a found value
501 $newval = $classinstance->id;
502 } elseif (! $error) {
503 if (!empty($objimport->array_import_convertvalue[0][$val]['dict'])) {
504 $this->errors[$error]['lib'] = $langs->trans('ErrorFieldValueNotIn', num2Alpha($key - 1), $newval, 'code', $langs->transnoentitiesnoconv($objimport->array_import_convertvalue[0][$val]['dict']));
505 } elseif (!empty($objimport->array_import_convertvalue[0][$val]['element'])) {
506 $this->errors[$error]['lib'] = $langs->trans('ErrorFieldRefNotIn', num2Alpha($key - 1), $newval, $langs->transnoentitiesnoconv($objimport->array_import_convertvalue[0][$val]['element']));
507 } else {
508 $this->errors[$error]['lib'] = 'ErrorBadDefinitionOfImportProfile';
509 }
510 $this->errors[$error]['type'] = 'FOREIGNKEY';
511 $errorforthistable++;
512 $error++;
513 }
514 }
515 }
516 } elseif ($objimport->array_import_convertvalue[0][$val]['rule'] == 'fetchidfromcodeandlabel') {
517 $isidorref = 'id';
518 if (!is_numeric($newval) && $newval != '' && !preg_match('/^id:/i', $newval)) {
519 $isidorref = 'ref';
520 }
521 $newval = preg_replace('/^(id|ref):/i', '', $newval);
522
523 if ($isidorref == 'ref') {
524 $file = (empty($objimport->array_import_convertvalue[0][$val]['classfile']) ? $objimport->array_import_convertvalue[0][$val]['file'] : $objimport->array_import_convertvalue[0][$val]['classfile']);
525 $class = $objimport->array_import_convertvalue[0][$val]['class'];
526 $method = $objimport->array_import_convertvalue[0][$val]['method'];
527 $codefromfield = $objimport->array_import_convertvalue[0][$val]['codefromfield'];
528 $code = $arrayrecord[$arrayfield[$codefromfield]]['val'];
529 if ($this->cacheconvert[$file.'_'.$class.'_'.$method.'_'.$code][$newval] != '') {
530 $newval = $this->cacheconvert[$file.'_'.$class.'_'.$method.'_'.$code][$newval];
531 } else {
532 $resultload = dol_include_once($file);
533 if (empty($resultload)) {
534 dol_print_error(null, 'Error trying to call file='.$file.', class='.$class.', method='.$method.', code='.$code);
535 break;
536 }
537 $classinstance = new $class($this->db);
538 // Try the fetch from code and ref
539 $param_array = array('', $newval, $code);
540 call_user_func_array(array($classinstance, $method), $param_array);
541 $this->cacheconvert[$file.'_'.$class.'_'.$method.'_'.$code][$newval] = $classinstance->id;
542 if ($classinstance->id > 0) { // we found record
543 $newval = $classinstance->id;
544 } else {
545 if (!empty($objimport->array_import_convertvalue[0][$val]['dict'])) {
546 $this->errors[$error]['lib'] = $langs->trans('ErrorFieldValueNotIn', num2Alpha($key - 1), $newval, 'scale', $langs->transnoentitiesnoconv($objimport->array_import_convertvalue[0][$val]['dict']));
547 } else {
548 $this->errors[$error]['lib'] = 'ErrorFieldValueNotIn';
549 }
550 $this->errors[$error]['type'] = 'FOREIGNKEY';
551 $errorforthistable++;
552 $error++;
553 }
554 }
555 }
556 } elseif ($objimport->array_import_convertvalue[0][$val]['rule'] == 'zeroifnull') {
557 if (empty($newval)) {
558 $newval = '0';
559 }
560 } elseif ($objimport->array_import_convertvalue[0][$val]['rule'] == 'fetchidfromcodeunits' || $objimport->array_import_convertvalue[0][$val]['rule'] == 'fetchscalefromcodeunits') {
561 $file = (empty($objimport->array_import_convertvalue[0][$val]['classfile']) ? $objimport->array_import_convertvalue[0][$val]['file'] : $objimport->array_import_convertvalue[0][$val]['classfile']);
562 $class = $objimport->array_import_convertvalue[0][$val]['class'];
563 $method = $objimport->array_import_convertvalue[0][$val]['method'];
564 $units = $objimport->array_import_convertvalue[0][$val]['units'];
565 if ($this->cacheconvert[$file.'_'.$class.'_'.$method.'_'.$units][$newval] != '') {
566 $newval = $this->cacheconvert[$file.'_'.$class.'_'.$method.'_'.$units][$newval];
567 } else {
568 $resultload = dol_include_once($file);
569 if (empty($resultload)) {
570 dol_print_error(null, 'Error trying to call file='.$file.', class='.$class.', method='.$method.', units='.$units);
571 break;
572 }
573 $classinstance = new $class($this->db);
574 // Try the fetch from code or ref
575 call_user_func_array(array($classinstance, $method), array('', '', $newval, $units));
576 $scaleorid = (($objimport->array_import_convertvalue[0][$val]['rule'] == 'fetchidfromcodeunits') ? $classinstance->id : $classinstance->scale);
577 $this->cacheconvert[$file.'_'.$class.'_'.$method.'_'.$units][$newval] = $scaleorid;
578 //print 'We have made a '.$class.'->'.$method." to get a value from key '".$newval."' and we got '".$scaleorid."'.";exit;
579 if ($classinstance->id > 0) { // we found record
580 $newval = $scaleorid ? $scaleorid : 0;
581 } else {
582 if (!empty($objimport->array_import_convertvalue[0][$val]['dict'])) {
583 $this->errors[$error]['lib'] = $langs->trans('ErrorFieldValueNotIn', num2Alpha($key - 1), $newval, 'scale', $langs->transnoentitiesnoconv($objimport->array_import_convertvalue[0][$val]['dict']));
584 } else {
585 $this->errors[$error]['lib'] = 'ErrorFieldValueNotIn';
586 }
587 $this->errors[$error]['type'] = 'FOREIGNKEY';
588 $errorforthistable++;
589 $error++;
590 }
591 }
592 } elseif ($objimport->array_import_convertvalue[0][$val]['rule'] == 'getcustomercodeifauto') {
593 if (strtolower($newval) == 'auto') {
594 $this->thirdpartyobject->get_codeclient(null, 0);
595 $newval = $this->thirdpartyobject->code_client;
596 //print 'code_client='.$newval;
597 }
598 if (empty($newval)) {
599 $arrayrecord[($key - 1)]['type'] = -1; // If we get empty value, we will use "null"
600 }
601 } elseif ($objimport->array_import_convertvalue[0][$val]['rule'] == 'getsuppliercodeifauto') {
602 if (strtolower($newval) == 'auto') {
603 $this->thirdpartyobject->get_codefournisseur(null, 1);
604 $newval = $this->thirdpartyobject->code_fournisseur;
605 //print 'code_fournisseur='.$newval;
606 }
607 if (empty($newval)) {
608 $arrayrecord[($key - 1)]['type'] = -1; // If we get empty value, we will use "null"
609 }
610 } elseif ($objimport->array_import_convertvalue[0][$val]['rule'] == 'getcustomeraccountancycodeifauto') {
611 if (strtolower($newval) == 'auto') {
612 $this->thirdpartyobject->get_codecompta('customer');
613 $newval = $this->thirdpartyobject->code_compta_client;
614 //print 'code_compta='.$newval;
615 }
616 if (empty($newval)) {
617 $arrayrecord[($key - 1)]['type'] = -1; // If we get empty value, we will use "null"
618 }
619 } elseif ($objimport->array_import_convertvalue[0][$val]['rule'] == 'getsupplieraccountancycodeifauto') {
620 if (strtolower($newval) == 'auto') {
621 $this->thirdpartyobject->get_codecompta('supplier');
622 $newval = $this->thirdpartyobject->code_compta_fournisseur;
623 if (empty($newval)) {
624 $arrayrecord[($key - 1)]['type'] = -1; // If we get empty value, we will use "null"
625 }
626 //print 'code_compta_fournisseur='.$newval;
627 }
628 if (empty($newval)) {
629 $arrayrecord[($key - 1)]['type'] = -1; // If we get empty value, we will use "null"
630 }
631 } elseif ($objimport->array_import_convertvalue[0][$val]['rule'] == 'getrefifauto') {
632 if (strtolower($newval) == 'auto') {
633 $defaultref = '';
634
635 $classModForNumber = $objimport->array_import_convertvalue[0][$val]['class'];
636 $pathModForNumber = $objimport->array_import_convertvalue[0][$val]['path'];
637
638 if (!empty($classModForNumber) && !empty($pathModForNumber) && is_readable(DOL_DOCUMENT_ROOT.$pathModForNumber)) {
639 require_once DOL_DOCUMENT_ROOT.$pathModForNumber;
640 $modForNumber = new $classModForNumber();
641 '@phan-var-force ModeleNumRefMembers|ModeleNumRefCommandes|ModeleNumRefSuppliersInvoices|ModeleNumRefSuppliersOrders|ModeleNumRefProjects|ModeleNumRefTask|ModeleNumRefPropales $modForNumber';
642
643 $tmpobject = null;
644 // Set the object with the date property when we can
645 if (!empty($objimport->array_import_convertvalue[0][$val]['classobject'])) {
646 $pathForObject = $objimport->array_import_convertvalue[0][$val]['pathobject'];
647 require_once DOL_DOCUMENT_ROOT.$pathForObject;
648 $tmpclassobject = $objimport->array_import_convertvalue[0][$val]['classobject'];
649 $tmpobject = new $tmpclassobject($this->db);
650 foreach ($arrayfield as $tmpkey => $tmpval) { // $arrayfield is array('c.ref'=>0, ...)
651 if (in_array($tmpkey, array('t.date', 'c.date_commande'))) {
652 $tmpobject->date = dol_stringtotime($arrayrecord[$arrayfield[$tmpkey]]['val'], 1);
653 }
654 }
655 }
656
657 $defaultref = $modForNumber->getNextValue(null, $tmpobject);
658 }
659 if (is_numeric($defaultref) && $defaultref <= 0) { // If error
660 $defaultref = '';
661 }
662 $newval = $defaultref;
663 }
664 } elseif ($objimport->array_import_convertvalue[0][$val]['rule'] == 'compute') {
665 $file = (empty($objimport->array_import_convertvalue[0][$val]['classfile']) ? $objimport->array_import_convertvalue[0][$val]['file'] : $objimport->array_import_convertvalue[0][$val]['classfile']);
666 $class = $objimport->array_import_convertvalue[0][$val]['class'];
667 $method = $objimport->array_import_convertvalue[0][$val]['method'];
668 $resultload = dol_include_once($file);
669 if (empty($resultload)) {
670 dol_print_error(null, 'Error trying to call file='.$file.', class='.$class.', method='.$method);
671 break;
672 }
673 $classinstance = new $class($this->db);
674 $res = call_user_func_array(array($classinstance, $method), array(&$arrayrecord, $arrayfield, ($key - 1)));
675 if (empty($classinstance->error) && empty($classinstance->errors)) {
676 $newval = $res; // We get new value computed.
677 } else {
678 $this->errors[$error]['type'] = 'CLASSERROR';
679 $this->errors[$error]['lib'] = implode(
680 "\n",
681 array_merge([$classinstance->error], $classinstance->errors)
682 );
683 $errorforthistable++;
684 $error++;
685 }
686 } elseif ($objimport->array_import_convertvalue[0][$val]['rule'] == 'numeric') {
687 $newval = price2num($newval);
688 } elseif ($objimport->array_import_convertvalue[0][$val]['rule'] == 'accountingaccount') {
689 if (!getDolGlobalString('ACCOUNTING_MANAGE_ZERO')) {
690 $newval = rtrim(trim($newval), "0");
691 } else {
692 $newval = trim($newval);
693 }
694 }
695
696 //print 'Val to use as insert is '.$newval.'<br>';
697 }
698
699 // Test regexp
700 if (!empty($objimport->array_import_regex[0][$val]) && ($newval != '')) {
701 // If test regex string is "field@table" or "field@table:..." (means must exists into table ...)
702 $reg = array();
703 if (preg_match('/^(.+)@([^:]+)(:.+)?$/', $objimport->array_import_regex[0][$val], $reg)) {
704 $field = $reg[1];
705 $table = $reg[2];
706 $filter = !empty($reg[3]) ? substr($reg[3], 1) : '';
707
708 $cachekey = $field.'@'.$table;
709 if (!empty($filter)) {
710 $cachekey .= ':'.$filter;
711 }
712
713 // Load content of field@table into cache array
714 if (!is_array($this->cachefieldtable[$cachekey])) { // If content of field@table not already loaded into cache
715 $sql = "SELECT ".$field." as aliasfield FROM ".$table;
716 if (!empty($filter)) {
717 $sql .= ' WHERE '.$filter;
718 }
719
720 $resql = $this->db->query($sql);
721 if ($resql) {
722 $num = $this->db->num_rows($resql);
723 $i = 0;
724 while ($i < $num) {
725 $obj = $this->db->fetch_object($resql);
726 if ($obj) {
727 $this->cachefieldtable[$cachekey][] = $obj->aliasfield;
728 }
729 $i++;
730 }
731 } else {
732 dol_print_error($this->db);
733 }
734 }
735
736 // Now we check cache is not empty (should not) and key is in cache
737 if (!is_array($this->cachefieldtable[$cachekey]) || !in_array($newval, $this->cachefieldtable[$cachekey])) {
738 $tableforerror = $table;
739 if (!empty($filter)) {
740 $tableforerror .= ':'.$filter;
741 }
742 $this->errors[$error]['lib'] = $langs->transnoentitiesnoconv('ErrorFieldValueNotIn', num2Alpha($key - 1), $newval, $field, $tableforerror);
743 $this->errors[$error]['type'] = 'FOREIGNKEY';
744 $errorforthistable++;
745 $error++;
746 }
747 } elseif (!preg_match('/'.$objimport->array_import_regex[0][$val].'/i', $newval)) {
748 // If test is just a static regex
749 //if ($key == 19) print "xxx".$newval."zzz".$objimport->array_import_regex[0][$val]."<br>";
750 $this->errors[$error]['lib'] = $langs->transnoentitiesnoconv('ErrorWrongValueForField', num2Alpha($key - 1), $newval, $objimport->array_import_regex[0][$val]);
751 $this->errors[$error]['type'] = 'REGEX';
752 $errorforthistable++;
753 $error++;
754 }
755 }
756
757 // Check HTML injection
758 $inj = testSqlAndScriptInject($newval, 0);
759 if ($inj) {
760 $this->errors[$error]['lib'] = $langs->transnoentitiesnoconv('ErrorHtmlInjectionForField', num2Alpha($key - 1), dol_trunc($newval, 100));
761 $this->errors[$error]['type'] = 'HTMLINJECTION';
762 $errorforthistable++;
763 $error++;
764 }
765
766 // Other tests
767 // ...
768 }
769
770 // Define $listfields and $listvalues to build the SQL request
771 if (isModEnabled("socialnetworks") && strpos($fieldname, "socialnetworks") !== false) {
772 if (!in_array("socialnetworks", $listfields)) {
773 $listfields[] = "socialnetworks";
774 $socialkey = array_search("socialnetworks", $listfields); // Return position of 'socialnetworks' key in array
775 $listvalues[$socialkey] = '';
776 }
777 //var_dump($newval); var_dump($arrayrecord[($key - 1)]['type']);
778 if (!empty($newval) && $arrayrecord[($key - 1)]['type'] > 0) {
779 $socialkey = array_search("socialnetworks", $listfields); // Return position of 'socialnetworks' key in array
780 //var_dump('sk='.$socialkey); // socialkey=19
781 $socialnetwork = explode("_", $fieldname)[1];
782 if (empty($listvalues[$socialkey]) || $listvalues[$socialkey] == "null") {
783 $json = new stdClass();
784 $json->$socialnetwork = $newval;
785 $listvalues[$socialkey] = json_encode($json);
786 } else {
787 $jsondata = $listvalues[$socialkey];
788 $json = json_decode($jsondata);
789 $json->$socialnetwork = $newval;
790 $listvalues[$socialkey] = json_encode($json);
791 }
792 }
793 } else {
794 $listfields[] = $fieldname;
795 // Note: arrayrecord (and 'type') is filled with ->import_read_record called by import.php page before calling import_insert
796 if (empty($newval) && $arrayrecord[($key - 1)]['type'] < 0) {
797 $listvalues[] = ($newval == '0' ? (int) $newval : "null");
798 } elseif (empty($newval) && $arrayrecord[($key - 1)]['type'] == 0) {
799 $listvalues[] = "''";
800 } else {
801 $listvalues[] = "'".$this->db->escape($newval)."'";
802 }
803 }
804 }
805 $i++;
806 }
807
808 // We add hidden fields (but only if there is at least one field to add into table)
809 // We process here all the fields that were declared into the array $this->import_fieldshidden_array of the descriptor file.
810 // Previously we processed the ->import_fields_array.
811 if (!empty($listfields) && is_array($objimport->array_import_fieldshidden[0])) {
812 // Loop on each hidden fields to add them into listfields/listvalues
813 foreach ($objimport->array_import_fieldshidden[0] as $tmpkey => $tmpval) {
814 if (!preg_match('/^' . preg_quote($alias, '/') . '\./', $tmpkey)) {
815 continue; // Not a field of current table
816 }
817 $keyfieldcache = preg_replace('/^' . preg_quote($alias, '/') . '\./', '', $tmpkey);
818
819 if (in_array($keyfieldcache, $listfields)) { // avoid duplicates in insert
820 continue;
821 } elseif ($tmpval == 'user->id') {
822 $listfields[] = $keyfieldcache;
823 $listvalues[] = ((int) $user->id);
824 } elseif (preg_match('/^lastrowid-/', $tmpval)) {
825 $tmp = explode('-', $tmpval);
826 $lastinsertid = (isset($last_insert_id_array[$tmp[1]])) ? $last_insert_id_array[$tmp[1]] : 0;
827 $listfields[] = $keyfieldcache;
828 $listvalues[] = (int) $lastinsertid;
829 $keyfield = $keyfieldcache;
830 //print $tmpkey."-".$tmpval."-".$listfields."-".$listvalues."<br>";exit;
831 } elseif (preg_match('/^const-/', $tmpval)) {
832 $tmp = explode('-', $tmpval, 2);
833 $listfields[] = $keyfieldcache;
834 $listvalues[] = "'".$this->db->escape($tmp[1])."'";
835 } elseif (preg_match('/^rule-/', $tmpval)) { // Example: rule-computeAmount, rule-computeDirection, ...
836 $fieldname = $tmpkey;
837 if (!empty($objimport->array_import_convertvalue[0][$fieldname])) {
838 if ($objimport->array_import_convertvalue[0][$fieldname]['rule'] == 'compute') {
839 $file = (empty($objimport->array_import_convertvalue[0][$fieldname]['classfile']) ? $objimport->array_import_convertvalue[0][$fieldname]['file'] : $objimport->array_import_convertvalue[0][$fieldname]['classfile']);
840 $class = $objimport->array_import_convertvalue[0][$fieldname]['class'];
841 $method = $objimport->array_import_convertvalue[0][$fieldname]['method'];
842 $type = $objimport->array_import_convertvalue[0][$fieldname]['type'];
843 $resultload = dol_include_once($file);
844 if (empty($resultload)) {
845 dol_print_error(null, 'Error trying to call file=' . $file . ', class=' . $class . ', method=' . $method);
846 break;
847 }
848 $classinstance = new $class($this->db);
849 $res = call_user_func_array(array($classinstance, $method), array(&$arrayrecord, $arrayfield, ($key - 1)));
850 if (empty($classinstance->error) && empty($classinstance->errors)) {
851 $fieldArr = explode('.', $fieldname);
852 if (count($fieldArr) > 0) {
853 $fieldname = $fieldArr[1];
854 }
855
856 // Set $listfields and $listvalues
857 $listfields[] = $fieldname;
858 if ($type == 'int') {
859 $listvalues[] = (int) $res;
860 } elseif ($type == 'double') {
861 $listvalues[] = (float) $res;
862 } else {
863 $listvalues[] = "'".$this->db->escape($res)."'";
864 }
865 } else {
866 $this->errors[$error]['type'] = 'CLASSERROR';
867 $this->errors[$error]['lib'] = implode(
868 "\n",
869 array_merge([$classinstance->error], $classinstance->errors)
870 );
871 $errorforthistable++;
872 $error++;
873 }
874 }
875 }
876 } else {
877 $this->errors[$error]['lib'] = 'Bad value of profile setup '.$tmpval.' for array_import_fieldshidden';
878 $this->errors[$error]['type'] = 'Import profile setup';
879 $error++;
880 }
881 }
882 }
883 //print 'listfields='.$listfields.'<br>listvalues='.$listvalues.'<br>';
884
885 // If no error for this $alias/$tablename, we have a complete $listfields and $listvalues that are defined
886 // so we can try to make the insert or update now.
887 if (!$errorforthistable) {
888 //print "$alias/$tablename/$listfields/$listvalues<br>";
889 if (!empty($listfields)) {
890 $updatedone = false;
891 $insertdone = false;
892
893 $is_table_category_link = false;
894 $fname = 'rowid';
895 if (strpos($tablename, '_categorie_') !== false) {
896 $is_table_category_link = true;
897 $fname = '*';
898 }
899
900 if (!empty($updatekeys)) {
901 // We do SELECT to get the rowid, if we already have the rowid, it's to be used below for related tables (extrafields)
902
903 if (empty($lastinsertid)) { // No insert done yet for a parent table
904 $sqlSelect = "SELECT ".$fname." FROM ".$tablename;
905 $data = array_combine($listfields, $listvalues);
906 $where = array(); // filters to forge SQL request
907 $filters = array(); // filters to forge output error message
908 foreach ($updatekeys as $key) {
909 $col = $objimport->array_import_updatekeys[0][$key];
910 $key = preg_replace('/^.*\./i', '', $key);
911 if (isModEnabled("socialnetworks") && strpos($key, "socialnetworks") !== false) {
912 $tmp = explode("_", $key);
913 $key = $tmp[0];
914 $socialnetwork = $tmp[1];
915 $jsondata = $data[$key];
916 $json = json_decode($jsondata);
917 $stringtosearch = json_encode($socialnetwork).':'.json_encode($json->$socialnetwork);
918 //var_dump($stringtosearch);
919 //var_dump($this->db->escape($stringtosearch)); // This provide a value for sql string (but not for a like)
920 $where[] = $key." LIKE '%".$this->db->escape($this->db->escapeforlike($stringtosearch))."%'";
921 $filters[] = $col." LIKE '%".$this->db->escape($this->db->escapeforlike($stringtosearch))."%'";
922 //var_dump($where[1]); // This provide a value for sql string inside a like
923 } else {
924 $where[] = $key.' = '.$data[$key];
925 $filters[] = $col.' = '.$data[$key];
926 }
927 }
928 if (!empty($tablewithentity_cache[$tablename])) {
929 $where[] = "entity IN (".getEntity($this->getElementFromTableWithPrefix($tablename)).")";
930 $filters[] = "entity IN (".getEntity($this->getElementFromTableWithPrefix($tablename)).")";
931 }
932 $sqlSelect .= " WHERE ".implode(' AND ', $where);
933
934 $resql = $this->db->query($sqlSelect);
935 if ($resql) {
936 $num_rows = $this->db->num_rows($resql);
937 if ($num_rows == 1) {
938 $res = $this->db->fetch_object($resql);
939 $lastinsertid = $res->rowid;
940 $keyfield = 'rowid';
941 if ($is_table_category_link) {
942 $lastinsertid = 'linktable';
943 } // used to apply update on tables like llx_categorie_product and avoid being blocked for all file content if at least one entry already exists
944 $last_insert_id_array[$tablename] = $lastinsertid;
945 } elseif ($num_rows > 1) {
946 $this->errors[$error]['lib'] = $langs->trans('MultipleRecordFoundWithTheseFilters', implode(', ', $filters));
947 $this->errors[$error]['type'] = 'SQL';
948 $error++;
949 } else {
950 // No record found with filters, insert will be tried below
951 }
952 } else {
953 //print 'E';
954 $this->errors[$error]['lib'] = $this->db->lasterror();
955 $this->errors[$error]['type'] = 'SQL';
956 $error++;
957 }
958 } else {
959 // We have a last INSERT ID (got by previous pass), so we check if we have a row referencing this foreign key.
960 // This is required when updating table with some extrafields. When inserting a record in parent table, we can make
961 // a direct insert into subtable extrafields, but when me wake an update, the insertid is defined and the child record
962 // may already exists. So we rescan the extrafield table to know if record exists or not for the rowid.
963 // Note: For extrafield tablename, we have in importfieldshidden_array an entry 'extra.fk_object'=>'lastrowid-tableparent' so $keyfield is 'fk_object'
964 $sqlSelect = "SELECT rowid FROM ".$tablename;
965 if (empty($keyfield)) {
966 $keyfield = 'rowid';
967 }
968
969 $sqlSelect .= " WHERE ".$keyfield." = ".((int) $lastinsertid);
970
971 if (!empty($tablewithentity_cache[$tablename])) {
972 $sqlSelect .= " AND entity IN (".getEntity($this->getElementFromTableWithPrefix($tablename)).")";
973 }
974
975 $resql = $this->db->query($sqlSelect);
976 if ($resql) {
977 $res = $this->db->fetch_object($resql);
978 if ($this->db->num_rows($resql) == 1) {
979 // We have a row referencing this last foreign key, continue with UPDATE.
980 } else {
981 // No record found referencing this last foreign key,
982 // force $lastinsertid to 0 so we INSERT below.
983 $lastinsertid = 0;
984 }
985 } else {
986 //print 'E';
987 $this->errors[$error]['lib'] = $this->db->lasterror();
988 $this->errors[$error]['type'] = 'SQL';
989 $error++;
990 }
991 }
992
993 if (!empty($lastinsertid)) {
994 // We db escape social network field because he isn't in field creation
995 if (in_array("socialnetworks", $listfields)) {
996 $socialkey = array_search("socialnetworks", $listfields);
997 $tmpsql = $listvalues[$socialkey];
998 $listvalues[$socialkey] = "'".$this->db->escape($tmpsql)."'";
999 }
1000
1001 // Build SQL UPDATE request
1002 $sqlstart = "UPDATE ".$tablename;
1003
1004 $data = array_combine($listfields, $listvalues);
1005 $set = array();
1006 foreach ($data as $key => $val) {
1007 $set[] = $key." = ".$val; // $val was escaped/sanitized previously
1008 }
1009 $sqlstart .= " SET ".implode(', ', $set).", import_key = '".$this->db->escape($importid)."'";
1010 if (empty($keyfield)) {
1011 $keyfield = 'rowid';
1012 }
1013
1014 $sqlend = " WHERE ".$keyfield." = ".((int) $lastinsertid);
1015
1016 if ($is_table_category_link) {
1017 '@phan-var-force string[] $where';
1018 $sqlend = " WHERE " . implode(' AND ', $where);
1019 }
1020
1021 if (!empty($tablewithentity_cache[$tablename])) {
1022 $sqlend .= " AND entity IN (".getEntity($this->getElementFromTableWithPrefix($tablename)).")";
1023 }
1024
1025 $sql = $sqlstart.$sqlend;
1026
1027 // Run update request
1028 $resql = $this->db->query($sql);
1029 if ($resql) {
1030 // No error, update has been done. $this->db->db->affected_rows can be 0 if data hasn't changed
1031 $updatedone = true;
1032 } else {
1033 //print 'E';
1034 $this->errors[$error]['lib'] = $this->db->lasterror();
1035 $this->errors[$error]['type'] = 'SQL';
1036 $error++;
1037 }
1038 }
1039 }
1040
1041 // Update not done, we do insert
1042 if (!$error && !$updatedone) {
1043 // We db escape social network field because he isn't in field creation
1044 if (in_array("socialnetworks", $listfields)) {
1045 $socialkey = array_search("socialnetworks", $listfields);
1046 $tmpsql = $listvalues[$socialkey];
1047 $listvalues[$socialkey] = "'".$this->db->escape($tmpsql)."'";
1048 }
1049
1050 // Build SQL INSERT request
1051 $sqlstart = "INSERT INTO ".$tablename."(".implode(", ", $listfields).", import_key";
1052 $sqlend = ") VALUES(".implode(', ', $listvalues).", '".$this->db->escape($importid)."'";
1053 if (!empty($tablewithentity_cache[$tablename])) {
1054 $sqlstart .= ", entity";
1055 $sqlend .= ", ".$conf->entity;
1056 }
1057 if (!empty($objimport->array_import_tables_creator[0][$alias])) {
1058 $sqlstart .= ", ".$objimport->array_import_tables_creator[0][$alias];
1059 $sqlend .= ", ".$user->id;
1060 }
1061 $sql = $sqlstart.$sqlend.")";
1062 //dol_syslog("import_csv.modules", LOG_DEBUG);
1063
1064 // Run insert request
1065 if ($sql) {
1066 $resql = $this->db->query($sql);
1067 if ($resql) {
1068 if (!$is_table_category_link) {
1069 $last_insert_id_array[$tablename] = $this->db->last_insert_id($tablename); // store the last inserted auto_increment id for each table, so that child tables can be inserted with the appropriate id. This must be done just after the INSERT request, else we risk losing the id (because another sql query will be issued somewhere in Dolibarr).
1070 }
1071 $insertdone = true;
1072 } else {
1073 //print 'E';
1074 $this->errors[$error]['lib'] = $this->db->lasterror();
1075 $this->errors[$error]['type'] = 'SQL';
1076 $error++;
1077 }
1078 }
1079 }
1080 }
1081 /*else
1082 {
1083 dol_print_error(null,'ErrorFieldListEmptyFor '.$alias."/".$tablename);
1084 }*/
1085 }
1086
1087 if ($error) {
1088 break;
1089 }
1090 }
1091
1092 if ($updatedone) {
1093 $this->nbupdate++;
1094 }
1095 if ($insertdone) {
1096 $this->nbinsert++;
1097 }
1098 }
1099
1100 return 1;
1101 }
1102}
1103
1110function cleansep($value)
1111{
1112 return str_replace(array(',', ';'), '/', $value);
1113}
versionphparray()
Return version PHP.
versioncompare($versionarray1, $versionarray2)
Compare 2 versions (stored into 2 arrays), to know if a version (a,b,c) is lower than (x,...
Definition admin.lib.php:71
Class to import CSV files.
write_header_example($outputlangs)
Output header of an example file for this format.
import_get_nb_of_lines($file)
Return nb of records.
import_insert($arrayrecord, $array_match_file_to_database, $objimport, $maxfields, $importid, $updatekeys)
Insert a record into database.
__construct($db, $datatoimport)
Constructor.
import_read_record()
Return array of next record in input file.
write_record_example($outputlangs, $contentlinevalues)
Output record of an example file for this format.
write_footer_example($outputlangs)
Output footer of an example file for this format.
import_close_file()
Close file handle.
import_read_header()
Input header line from file.
write_title_example($outputlangs, $headerlinefields)
Output title line of an example file for this format.
import_open_file($file)
Open input file.
Parent class for import file readers.
getElementFromTableWithPrefix($tableNameWithPrefix)
Get element from table name with prefix.
Class to manage third parties objects (customers, suppliers, prospects...)
dol_stringtotime($string, $gm=1)
Convert a string date into a GM Timestamps date Warning: YYYY-MM-DDTHH:MM:SS+02:00 (RFC3339) is not s...
Definition date.lib.php:434
dol_count_nb_of_line($file)
Count number of lines in a file.
dol_osencode($str)
Return a string encoded into OS filesystem encoding.
price2num($amount, $rounding='', $option=0)
Function that return a number with universal decimal format (decimal separator is '.
dol_strlen($string, $stringencoding='UTF-8')
Make a strlen call.
if(!function_exists( 'dol_getprefix')) dol_include_once($relpath, $classname='')
Make an include_once using default root and alternate root if it fails.
num2Alpha($n)
Return a numeric value into an Excel like column number.
GETPOST($paramname, $check='alphanohtml', $method=0, $filter=null, $options=null, $noreplace=0)
Return value of a param into GET or POST supervariable.
dol_print_error($db=null, $error='', $errors=null)
Displays error message system with all the information to facilitate the diagnosis and the escalation...
dol_trunc($string, $size=40, $trunc='right', $stringencoding='UTF-8', $nodot=0, $display=0)
Truncate a string to a particular length adding '…' if string larger than length.
getDolGlobalString($key, $default='')
Return a Dolibarr global constant string value.
isModEnabled($module)
Is Dolibarr module enabled.
utf8_check($str)
Check if a string is in UTF8.
dol_syslog($message, $level=LOG_INFO, $ident=0, $suffixinfilename='', $restricttologhandler='', $logcontext=null)
Write log message into outputs.
cleansep($value)
Clean a string from separator.
testSqlAndScriptInject($val, $type)
Security: WAF layer for SQL Injection and XSS Injection (scripts) protection (Filters on GET,...
Definition waf.inc.php:103