dolibarr  18.0.0
repair.php
Go to the documentation of this file.
1 <?php
2 /* Copyright (C) 2004 Rodolphe Quiedeville <rodolphe@quiedeville.org>
3  * Copyright (C) 2004-2012 Laurent Destailleur <eldy@users.sourceforge.net>
4  * Copyright (C) 2005-2012 Regis Houssin <regis.houssin@inodbox.com>
5  * Copyright (C) 2015 Raphaël Doursenaud <rdoursenaud@gpcsolutions.fr>
6  * Copyright (C) 2021 Frédéric France <frederic.france@free.fr>
7  * Copyright (C) 2023 Gauthier VERDOL <gauthier.verdol@atm-consulting.fr>
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 
28 include_once 'inc.php';
29 if (file_exists($conffile)) {
30  include_once $conffile;
31 }
32 require_once $dolibarr_main_document_root.'/core/lib/admin.lib.php';
33 include_once $dolibarr_main_document_root.'/core/lib/images.lib.php';
34 require_once $dolibarr_main_document_root.'/core/class/extrafields.class.php';
35 require_once 'lib/repair.lib.php';
36 
37 $step = 2;
38 $ok = 0;
39 
40 
41 // Cette page peut etre longue. On augmente le delai autorise.
42 // Ne fonctionne que si on est pas en safe_mode.
43 $err = error_reporting();
44 error_reporting(0);
45 @set_time_limit(120);
46 error_reporting($err);
47 
48 $setuplang = GETPOST("selectlang", 'aZ09', 3) ?GETPOST("selectlang", 'aZ09', 3) : 'auto';
49 $langs->setDefaultLang($setuplang);
50 
51 $langs->loadLangs(array("admin", "install", "other"));
52 
53 if ($dolibarr_main_db_type == "mysqli") {
54  $choix = 1;
55 }
56 if ($dolibarr_main_db_type == "pgsql") {
57  $choix = 2;
58 }
59 if ($dolibarr_main_db_type == "mssql") {
60  $choix = 3;
61 }
62 
63 
64 dolibarr_install_syslog("--- repair: entering upgrade.php page");
65 if (!is_object($conf)) {
66  dolibarr_install_syslog("repair: conf file not initialized", LOG_ERR);
67 }
68 
69 
70 /*
71  * View
72  */
73 
74 pHeader('', "upgrade2", GETPOST('action', 'aZ09'));
75 
76 // Action to launch the repair script
77 $actiondone = 1;
78 
79 print '<h3>'.$langs->trans("Repair").'</h3>';
80 
81 print 'Option standard (\'test\' or \'confirmed\') is '.(GETPOST('standard', 'alpha') ?GETPOST('standard', 'alpha') : 'undefined').'<br>'."\n";
82 // Disable modules
83 print 'Option force_disable_of_modules_not_found (\'test\' or \'confirmed\') is '.(GETPOST('force_disable_of_modules_not_found', 'alpha') ?GETPOST('force_disable_of_modules_not_found', 'alpha') : 'undefined').'<br>'."\n";
84 // Files
85 print 'Option restore_thirdparties_logos (\'test\' or \'confirmed\') is '.(GETPOST('restore_thirdparties_logos', 'alpha') ?GETPOST('restore_thirdparties_logos', 'alpha') : 'undefined').'<br>'."\n";
86 print 'Option restore_user_pictures (\'test\' or \'confirmed\') is '.(GETPOST('restore_user_pictures', 'alpha') ?GETPOST('restore_user_pictures', 'alpha') : 'undefined').'<br>'."\n";
87 print 'Option rebuild_product_thumbs (\'test\' or \'confirmed\') is '.(GETPOST('rebuild_product_thumbs', 'alpha') ?GETPOST('rebuild_product_thumbs', 'alpha') : 'undefined').'<br>'."\n";
88 // Clean tables and data
89 print 'Option clean_linked_elements (\'test\' or \'confirmed\') is '.(GETPOST('clean_linked_elements', 'alpha') ?GETPOST('clean_linked_elements', 'alpha') : 'undefined').'<br>'."\n";
90 print 'Option clean_menus (\'test\' or \'confirmed\') is '.(GETPOST('clean_menus', 'alpha') ?GETPOST('clean_menus', 'alpha') : 'undefined').'<br>'."\n";
91 print 'Option clean_orphelin_dir (\'test\' or \'confirmed\') is '.(GETPOST('clean_orphelin_dir', 'alpha') ?GETPOST('clean_orphelin_dir', 'alpha') : 'undefined').'<br>'."\n";
92 print 'Option clean_product_stock_batch (\'test\' or \'confirmed\') is '.(GETPOST('clean_product_stock_batch', 'alpha') ?GETPOST('clean_product_stock_batch', 'alpha') : 'undefined').'<br>'."\n";
93 print 'Option clean_perm_table (\'test\' or \'confirmed\') is '.(GETPOST('clean_perm_table', 'alpha') ?GETPOST('clean_perm_table', 'alpha') : 'undefined').'<br>'."\n";
94 print 'Option repair_link_dispatch_lines_supplier_order_lines, (\'test\' or \'confirmed\') is '.(GETPOST('repair_link_dispatch_lines_supplier_order_lines', 'alpha') ?GETPOST('repair_link_dispatch_lines_supplier_order_lines', 'alpha') : 'undefined').'<br>'."\n";
95 // Init data
96 print 'Option set_empty_time_spent_amount (\'test\' or \'confirmed\') is '.(GETPOST('set_empty_time_spent_amount', 'alpha') ?GETPOST('set_empty_time_spent_amount', 'alpha') : 'undefined').'<br>'."\n";
97 // Structure
98 print 'Option force_utf8_on_tables (force utf8 + row=dynamic), for mysql/mariadb only (\'test\' or \'confirmed\') is '.(GETPOST('force_utf8_on_tables', 'alpha') ?GETPOST('force_utf8_on_tables', 'alpha') : 'undefined').'<br>'."\n";
99 print "Option force_utf8mb4_on_tables (force utf8mb4 + row=dynamic, EXPERIMENTAL!), for mysql/mariadb only ('test' or 'confirmed') is ".(GETPOST('force_utf8mb4_on_tables', 'alpha') ? GETPOST('force_utf8mb4_on_tables', 'alpha') : 'undefined')."<br>\n";
100 // Rebuild sequence
101 print 'Option rebuild_sequences, for postgresql only (\'test\' or \'confirmed\') is '.(GETPOST('rebuild_sequences', 'alpha') ?GETPOST('rebuild_sequences', 'alpha') : 'undefined').'<br>'."\n";
102 print '<br>';
103 
104 print '<table cellspacing="0" cellpadding="1" border="0" width="100%">';
105 $error = 0;
106 
107 // If password is encoded, we decode it
108 if (preg_match('/crypted:/i', $dolibarr_main_db_pass) || !empty($dolibarr_main_db_encrypted_pass)) {
109  require_once $dolibarr_main_document_root.'/core/lib/security.lib.php';
110  if (preg_match('/crypted:/i', $dolibarr_main_db_pass)) {
111  $dolibarr_main_db_pass = preg_replace('/crypted:/i', '', $dolibarr_main_db_pass);
112  $dolibarr_main_db_pass = dol_decode($dolibarr_main_db_pass);
113  $dolibarr_main_db_encrypted_pass = $dolibarr_main_db_pass; // We need to set this as it is used to know the password was initially crypted
114  } else {
115  $dolibarr_main_db_pass = dol_decode($dolibarr_main_db_encrypted_pass);
116  }
117 }
118 
119 // $conf is already instancied inside inc.php
120 $conf->db->type = $dolibarr_main_db_type;
121 $conf->db->host = $dolibarr_main_db_host;
122 $conf->db->port = $dolibarr_main_db_port;
123 $conf->db->name = $dolibarr_main_db_name;
124 $conf->db->user = $dolibarr_main_db_user;
125 $conf->db->pass = $dolibarr_main_db_pass;
126 
127 // For encryption
128 $conf->db->dolibarr_main_db_encryption = isset($dolibarr_main_db_encryption) ? $dolibarr_main_db_encryption : '';
129 $conf->db->dolibarr_main_db_cryptkey = isset($dolibarr_main_db_cryptkey) ? $dolibarr_main_db_cryptkey : '';
130 
131 $db = getDoliDBInstance($conf->db->type, $conf->db->host, $conf->db->user, $conf->db->pass, $conf->db->name, (int) $conf->db->port);
132 
133 if ($db->connected) {
134  print '<tr><td class="nowrap">';
135  print $langs->trans("ServerConnection")." : $dolibarr_main_db_host</td><td class=\"right\">".$langs->trans("OK")."</td></tr>";
136  dolibarr_install_syslog("repair: ".$langs->transnoentities("ServerConnection").": ".$dolibarr_main_db_host.$langs->transnoentities("OK"));
137  $ok = 1;
138 } else {
139  print "<tr><td>".$langs->trans("ErrorFailedToConnectToDatabase", $dolibarr_main_db_name)."</td><td class=\"right\">".$langs->transnoentities("Error")."</td></tr>";
140  dolibarr_install_syslog("repair: ".$langs->transnoentities("ErrorFailedToConnectToDatabase", $dolibarr_main_db_name));
141  $ok = 0;
142 }
143 
144 if ($ok) {
145  if ($db->database_selected) {
146  print '<tr><td class="nowrap">';
147  print $langs->trans("DatabaseConnection")." : ".$dolibarr_main_db_name."</td><td class=\"right\">".$langs->trans("OK")."</td></tr>";
148  dolibarr_install_syslog("repair: database connection successful: ".$dolibarr_main_db_name);
149  $ok = 1;
150  } else {
151  print "<tr><td>".$langs->trans("ErrorFailedToConnectToDatabase", $dolibarr_main_db_name)."</td><td class=\"right\">".$langs->trans("Error")."</td></tr>";
152  dolibarr_install_syslog("repair: ".$langs->transnoentities("ErrorFailedToConnectToDatabase", $dolibarr_main_db_name));
153  $ok = 0;
154  }
155 }
156 
157 // Show database version
158 if ($ok) {
159  $version = $db->getVersion();
160  $versionarray = $db->getVersionArray();
161  print '<tr><td>'.$langs->trans("ServerVersion").'</td>';
162  print '<td class="right">'.$version.'</td></tr>';
163  dolibarr_install_syslog("repair: ".$langs->transnoentities("ServerVersion").": ".$version);
164  //print '<td class="right">'.join('.',$versionarray).'</td></tr>';
165 }
166 
167 $conf->setValues($db);
168 // Reset forced setup after the setValues
169 if (defined('SYSLOG_FILE')) {
170  $conf->global->SYSLOG_FILE = constant('SYSLOG_FILE');
171 }
172 $conf->global->MAIN_ENABLE_LOG_TO_HTML = 1;
173 
174 
175 /* Start action here */
176 $oneoptionset = 0;
177 $oneoptionset = (GETPOST('standard', 'alpha') || GETPOST('restore_thirdparties_logos', 'alpha') || GETPOST('clean_linked_elements', 'alpha') || GETPOST('clean_menus', 'alpha')
178  || GETPOST('clean_orphelin_dir', 'alpha') || GETPOST('clean_product_stock_batch', 'alpha') || GETPOST('set_empty_time_spent_amount', 'alpha') || GETPOST('rebuild_product_thumbs', 'alpha')
179  || GETPOST('clean_perm_table', 'alpha')
180  || GETPOST('force_disable_of_modules_not_found', 'alpha')
181  || GETPOST('force_utf8_on_tables', 'alpha') || GETPOST('force_utf8mb4_on_tables', 'alpha')
182  || GETPOST('rebuild_sequences', 'alpha'));
183 
184 if ($ok && $oneoptionset) {
185  // Show wait message
186  print '<tr><td colspan="2">'.$langs->trans("PleaseBePatient").'<br><br></td></tr>';
187  flush();
188 }
189 
190 
191 // run_sql: Run repair SQL file
192 if ($ok && GETPOST('standard', 'alpha')) {
193  $dir = "mysql/migration/";
194 
195  $filelist = array();
196  $i = 0;
197  $ok = 0;
198 
199  // Recupere list fichier
200  $filesindir = array();
201  $handle = opendir($dir);
202  if (is_resource($handle)) {
203  while (($file = readdir($handle)) !== false) {
204  if (preg_match('/\.sql$/i', $file)) {
205  $filesindir[] = $file;
206  }
207  }
208  }
209  sort($filesindir);
210 
211  foreach ($filesindir as $file) {
212  if (preg_match('/repair/i', $file)) {
213  $filelist[] = $file;
214  }
215  }
216 
217  // Loop on each file
218  foreach ($filelist as $file) {
219  print '<tr><td class="nowrap">*** ';
220  print $langs->trans("Script").'</td><td class="right">'.$file.'</td></tr>';
221 
222  $name = substr($file, 0, dol_strlen($file) - 4);
223 
224  // Run sql script
225  $ok = run_sql($dir.$file, 0, '', 1);
226  }
227 }
228 
229 
230 // sync_extrafields: Search list of fields declared and list of fields created into databases, then create fields missing
231 
232 if ($ok && GETPOST('standard', 'alpha')) {
233  $extrafields = new ExtraFields($db);
234  $listofmodulesextra = array('societe'=>'societe', 'adherent'=>'adherent', 'product'=>'product',
235  'socpeople'=>'socpeople', 'propal'=>'propal', 'commande'=>'commande', 'facture'=>'facture',
236  'supplier_proposal'=>'supplier_proposal', 'commande_fournisseur'=>'commande_fournisseur', 'facture_fourn'=>'facture_fourn',
237  'actioncomm'=>'actioncomm', 'bom_bom'=>'bom_bom', 'mrp_mo'=>'mrp_mo',
238  'adherent_type'=>'adherent_type', 'user'=>'user', 'projet'=>'projet', 'projet_task'=>'projet_task');
239  print '<tr><td colspan="2"><br>*** Check fields into extra table structure match table of definition. If not add column into table</td></tr>';
240  foreach ($listofmodulesextra as $tablename => $elementtype) {
241  // Get list of fields
242  $tableextra = MAIN_DB_PREFIX.$tablename.'_extrafields';
243 
244  // Define $arrayoffieldsdesc
245  $arrayoffieldsdesc = $extrafields->fetch_name_optionals_label($elementtype);
246 
247  // Define $arrayoffieldsfound
248  $arrayoffieldsfound = array();
249  $resql = $db->DDLDescTable($tableextra);
250  if ($resql) {
251  print '<tr><td>Check availability of extra field for '.$tableextra."<br>\n";
252  $i = 0;
253  while ($obj = $db->fetch_object($resql)) {
254  $fieldname = $fieldtype = '';
255  if (preg_match('/mysql/', $db->type)) {
256  $fieldname = $obj->Field;
257  $fieldtype = $obj->Type;
258  } else {
259  $fieldname = isset($obj->Key) ? $obj->Key : $obj->attname;
260  $fieldtype = isset($obj->Type) ? $obj->Type : 'varchar';
261  }
262 
263  if (empty($fieldname)) {
264  continue;
265  }
266  if (in_array($fieldname, array('rowid', 'tms', 'fk_object', 'import_key'))) {
267  continue;
268  }
269  $arrayoffieldsfound[$fieldname] = array('type'=>$fieldtype);
270  }
271 
272  // If it does not match, we create fields
273  foreach ($arrayoffieldsdesc as $code => $label) {
274  if (!in_array($code, array_keys($arrayoffieldsfound))) {
275  print 'Found field '.$code.' declared into '.MAIN_DB_PREFIX.'extrafields table but not found into desc of table '.$tableextra." -> ";
276  $type = $extrafields->attributes[$elementtype]['type'][$code]; $length = $extrafields->attributes[$elementtype]['size'][$code]; $attribute = ''; $default = ''; $extra = ''; $null = 'null';
277 
278  if ($type == 'boolean') {
279  $typedb = 'int';
280  $lengthdb = '1';
281  } elseif ($type == 'price') {
282  $typedb = 'double';
283  $lengthdb = '24,8';
284  } elseif ($type == 'phone') {
285  $typedb = 'varchar';
286  $lengthdb = '20';
287  } elseif ($type == 'mail') {
288  $typedb = 'varchar';
289  $lengthdb = '128';
290  } elseif (($type == 'select') || ($type == 'sellist') || ($type == 'radio') || ($type == 'checkbox') || ($type == 'chkbxlst')) {
291  $typedb = 'text';
292  $lengthdb = '';
293  } elseif ($type == 'link') {
294  $typedb = 'int';
295  $lengthdb = '11';
296  } else {
297  $typedb = $type;
298  $lengthdb = $length;
299  }
300 
301  $field_desc = array(
302  'type'=>$typedb,
303  'value'=>$lengthdb,
304  'attribute'=>$attribute,
305  'default'=>$default,
306  'extra'=>$extra,
307  'null'=>$null
308  );
309  //var_dump($field_desc);exit;
310 
311  $result = 0;
312  if (GETPOST('standard', 'alpha') == 'confirmed') {
313  $result = $db->DDLAddField($tableextra, $code, $field_desc, "");
314 
315  if ($result < 0) {
316  print "KO ".$db->lasterror."<br>\n";
317  } else {
318  print "OK<br>\n";
319  }
320  } else {
321  print ' - Mode test, no column added.';
322  }
323  }
324  }
325 
326  print "</td><td>&nbsp;</td></tr>\n";
327  } else {
328  dol_print_error($db);
329  }
330  }
331 }
332 
333 
334 // clean_data_ecm_dir: Clean data into ecm_directories table
335 if ($ok && GETPOST('standard', 'alpha')) {
337 }
338 
339 
340 // clean declaration constants
341 if ($ok && GETPOST('standard', 'alpha')) {
342  print '<tr><td colspan="2"><br>*** Clean constant record of modules not enabled</td></tr>';
343 
344  $sql = "SELECT name, entity, value";
345  $sql .= " FROM ".MAIN_DB_PREFIX."const as c";
346  $sql .= " WHERE name LIKE 'MAIN_MODULE_%_TPL' OR name LIKE 'MAIN_MODULE_%_CSS' OR name LIKE 'MAIN_MODULE_%_JS' OR name LIKE 'MAIN_MODULE_%_HOOKS'";
347  $sql .= " OR name LIKE 'MAIN_MODULE_%_TRIGGERS' OR name LIKE 'MAIN_MODULE_%_THEME' OR name LIKE 'MAIN_MODULE_%_SUBSTITUTIONS' OR name LIKE 'MAIN_MODULE_%_MODELS'";
348  $sql .= " OR name LIKE 'MAIN_MODULE_%_MENUS' OR name LIKE 'MAIN_MODULE_%_LOGIN' OR name LIKE 'MAIN_MODULE_%_BARCODE' OR name LIKE 'MAIN_MODULE_%_TABS_%'";
349  $sql .= " OR name LIKE 'MAIN_MODULE_%_MODULEFOREXTERNAL'";
350  $sql .= " ORDER BY name, entity";
351 
352  $resql = $db->query($sql);
353  if ($resql) {
354  $num = $db->num_rows($resql);
355 
356  if ($num) {
357  $db->begin();
358 
359  $i = 0;
360  while ($i < $num) {
361  $obj = $db->fetch_object($resql);
362 
363  $reg = array();
364  if (preg_match('/MAIN_MODULE_([^_]+)_(.+)/i', $obj->name, $reg)) {
365  $name = $reg[1];
366  $type = $reg[2];
367 
368  $sql2 = "SELECT COUNT(*) as nb";
369  $sql2 .= " FROM ".MAIN_DB_PREFIX."const as c";
370  $sql2 .= " WHERE name = 'MAIN_MODULE_".$name."'";
371  $sql2 .= " AND entity = ".((int) $obj->entity);
372  $resql2 = $db->query($sql2);
373  if ($resql2) {
374  $obj2 = $db->fetch_object($resql2);
375  if ($obj2 && $obj2->nb == 0) {
376  // Module not found, so we can remove entry
377  $sqldelete = "DELETE FROM ".MAIN_DB_PREFIX."const WHERE name = '".$db->escape($obj->name)."' AND entity = ".((int) $obj->entity);
378 
379  if (GETPOST('standard', 'alpha') == 'confirmed') {
380  $db->query($sqldelete);
381 
382  print '<tr><td>Widget '.$obj->name.' set in entity '.$obj->entity.' with value '.$obj->value.' -> Module '.$name.' not enabled in entity '.((int) $obj->entity).', we delete record</td></tr>';
383  } else {
384  print '<tr><td>Widget '.$obj->name.' set in entity '.$obj->entity.' with value '.$obj->value.' -> Module '.$name.' not enabled in entity '.((int) $obj->entity).', we should delete record (not done, mode test)</td></tr>';
385  }
386  } else {
387  //print '<tr><td>Constant '.$obj->name.' set in entity '.$obj->entity.' with value '.$obj->value.' -> Module found in entity '.$obj->entity.', we keep record</td></tr>';
388  }
389  }
390  }
391 
392  $i++;
393  }
394 
395  $db->commit();
396  }
397  } else {
398  dol_print_error($db);
399  }
400 }
401 
402 
403 // clean box of not enabled modules
404 if ($ok && GETPOST('standard', 'alpha')) {
405  print '<tr><td colspan="2"><br>*** Clean definition of boxes of modules not enabled</td></tr>';
406 
407  $sql = "SELECT file, entity FROM ".MAIN_DB_PREFIX."boxes_def";
408  $sql .= " WHERE file like '%@%'";
409 
410  $resql = $db->query($sql);
411  if ($resql) {
412  $num = $db->num_rows($resql);
413 
414  if ($num) {
415  $db->begin();
416 
417  $i = 0;
418  while ($i < $num) {
419  $obj = $db->fetch_object($resql);
420 
421  $reg = array();
422  if (preg_match('/^(.+)@(.+)$/i', $obj->file, $reg)) {
423  $name = $reg[1];
424  $module = $reg[2];
425 
426  $sql2 = "SELECT COUNT(*) as nb";
427  $sql2 .= " FROM ".MAIN_DB_PREFIX."const as c";
428  $sql2 .= " WHERE name = 'MAIN_MODULE_".strtoupper($module)."'";
429  $sql2 .= " AND entity = ".((int) $obj->entity);
430  $sql2 .= " AND value <> 0";
431  $resql2 = $db->query($sql2);
432  if ($resql2) {
433  $obj2 = $db->fetch_object($resql2);
434  if ($obj2 && $obj2->nb == 0) {
435  // Module not found, so we canremove entry
436  $sqldeletea = "DELETE FROM ".MAIN_DB_PREFIX."boxes WHERE entity = ".((int) $obj->entity)." AND box_id IN (SELECT rowid FROM ".MAIN_DB_PREFIX."boxes_def WHERE file = '".$db->escape($obj->file)."' AND entity = ".((int) $obj->entity).")";
437  $sqldeleteb = "DELETE FROM ".MAIN_DB_PREFIX."boxes_def WHERE file = '".$db->escape($obj->file)."' AND entity = ".((int) $obj->entity);
438 
439  if (GETPOST('standard', 'alpha') == 'confirmed') {
440  $db->query($sqldeletea);
441  $db->query($sqldeleteb);
442 
443  print '<tr><td>Constant '.$obj->file.' set in boxes_def for entity '.$obj->entity.' but MAIN_MODULE_'.strtoupper($module).' not defined in entity '.((int) $obj->entity).', we delete record</td></tr>';
444  } else {
445  print '<tr><td>Constant '.$obj->file.' set in boxes_def for entity '.$obj->entity.' but MAIN_MODULE_'.strtoupper($module).' not defined in entity '.((int) $obj->entity).', we should delete record (not done, mode test)</td></tr>';
446  }
447  } else {
448  //print '<tr><td>Constant '.$obj->name.' set in entity '.$obj->entity.' with value '.$obj->value.' -> Module found in entity '.$obj->entity.', we keep record</td></tr>';
449  }
450  }
451  }
452 
453  $i++;
454  }
455 
456  $db->commit();
457  }
458  }
459 }
460 
461 
462 // restore_thirdparties_logos: Move logos to correct new directory.
463 if ($ok && GETPOST('restore_thirdparties_logos')) {
464  //$exts=array('gif','png','jpg');
465 
466  $ext = '';
467 
468  print '<tr><td colspan="2"><br>*** Restore thirdparties logo<br>';
469 
470  $sql = "SELECT s.rowid, s.nom as name, s.logo FROM ".MAIN_DB_PREFIX."societe as s ORDER BY s.nom";
471  $resql = $db->query($sql);
472  if ($resql) {
473  $num = $db->num_rows($resql);
474  $i = 0;
475 
476  while ($i < $num) {
477  $obj = $db->fetch_object($resql);
478 
479  /*
480  $name=preg_replace('/é/','',$obj->name);
481  $name=preg_replace('/ /','_',$name);
482  $name=preg_replace('/\'/','',$name);
483  */
484 
485  $tmp = explode('.', $obj->logo);
486  $name = $tmp[0];
487  if (isset($tmp[1])) {
488  $ext = '.'.$tmp[1];
489  }
490 
491  if (!empty($name)) {
492  $filetotest = $dolibarr_main_data_root.'/societe/logos/'.$name.$ext;
493  $filetotestsmall = $dolibarr_main_data_root.'/societe/logos/thumbs/'.$name.'_small'.$ext;
494  $exists = dol_is_file($filetotest);
495  print 'Check thirdparty '.$obj->rowid.' name='.$obj->name.' logo='.$obj->logo.' file '.$filetotest." exists=".$exists."<br>\n";
496  if ($exists) {
497  $filetarget = $dolibarr_main_data_root.'/societe/'.$obj->rowid.'/logos/'.$name.$ext;
498  $filetargetsmall = $dolibarr_main_data_root.'/societe/'.$obj->rowid.'/logos/thumbs/'.$name.'_small'.$ext;
499  $existt = dol_is_file($filetarget);
500  if (!$existt) {
501  if (GETPOST('restore_thirdparties_logos', 'alpha') == 'confirmed') {
502  dol_mkdir($dolibarr_main_data_root.'/societe/'.$obj->rowid.'/logos');
503  }
504 
505  print " &nbsp; &nbsp; &nbsp; -> Copy file ".$filetotest." -> ".$filetarget."<br>\n";
506  if (GETPOST('restore_thirdparties_logos', 'alpha') == 'confirmed') {
507  dol_copy($filetotest, $filetarget, '', 0);
508  }
509  }
510 
511  $existtt = dol_is_file($filetargetsmall);
512  if (!$existtt) {
513  if (GETPOST('restore_thirdparties_logos', 'alpha') == 'confirmed') {
514  dol_mkdir($dolibarr_main_data_root.'/societe/'.$obj->rowid.'/logos/thumbs');
515  }
516  print " &nbsp; &nbsp; &nbsp; -> Copy file ".$filetotestsmall." -> ".$filetargetsmall."<br>\n";
517  if (GETPOST('restore_thirdparties_logos', 'alpha') == 'confirmed') {
518  dol_copy($filetotestsmall, $filetargetsmall, '', 0);
519  }
520  }
521  }
522  }
523 
524  $i++;
525  }
526  } else {
527  $ok = 0;
528  dol_print_error($db);
529  }
530 
531  print '</td></tr>';
532 }
533 
534 
535 
536 // restore_user_pictures: Move pictures to correct new directory.
537 if ($ok && GETPOST('restore_user_pictures', 'alpha')) {
538  //$exts=array('gif','png','jpg');
539 
540  $ext = '';
541 
542  print '<tr><td colspan="2"><br>*** Restore user pictures<br>';
543 
544  $sql = "SELECT s.rowid, s.firstname, s.lastname, s.login, s.photo FROM ".MAIN_DB_PREFIX."user as s ORDER BY s.rowid";
545  $resql = $db->query($sql);
546  if ($resql) {
547  $num = $db->num_rows($resql);
548  $i = 0;
549 
550  while ($i < $num) {
551  $obj = $db->fetch_object($resql);
552 
553  /*
554  $name=preg_replace('/é/','',$obj->name);
555  $name=preg_replace('/ /','_',$name);
556  $name=preg_replace('/\'/','',$name);
557  */
558 
559  $tmp = explode('.', $obj->photo);
560  $name = $tmp[0];
561  if (isset($tmp[1])) {
562  $ext = '.'.$tmp[1];
563  }
564 
565  if (!empty($name)) {
566  $filetotest = $dolibarr_main_data_root.'/users/'.substr(sprintf('%08d', $obj->rowid), -1, 1).'/'.substr(sprintf('%08d', $obj->rowid), -2, 1).'/'.$name.$ext;
567  $filetotestsmall = $dolibarr_main_data_root.'/users/'.substr(sprintf('%08d', $obj->rowid), -1, 1).'/'.substr(sprintf('%08d', $obj->rowid), -2, 1).'/thumbs/'.$name.'_small'.$ext;
568  $filetotestmini = $dolibarr_main_data_root.'/users/'.substr(sprintf('%08d', $obj->rowid), -1, 1).'/'.substr(sprintf('%08d', $obj->rowid), -2, 1).'/thumbs/'.$name.'_mini'.$ext;
569  $exists = dol_is_file($filetotest);
570  print 'Check user '.$obj->rowid.' lastname='.$obj->lastname.' firstname='.$obj->firstname.' photo='.$obj->photo.' file '.$filetotest." exists=".$exists."<br>\n";
571  if ($exists) {
572  $filetarget = $dolibarr_main_data_root.'/users/'.$obj->rowid.'/'.$name.$ext;
573  $filetargetsmall = $dolibarr_main_data_root.'/users/'.$obj->rowid.'/thumbs/'.$name.'_small'.$ext;
574  $filetargetmini = $dolibarr_main_data_root.'/users/'.$obj->rowid.'/thumbs/'.$name.'_mini'.$ext;
575 
576  $existt = dol_is_file($filetarget);
577  if (!$existt) {
578  if (GETPOST('restore_user_pictures', 'alpha') == 'confirmed') {
579  dol_mkdir($dolibarr_main_data_root.'/users/'.$obj->rowid);
580  }
581 
582  print " &nbsp; &nbsp; &nbsp; -> Copy file ".$filetotest." -> ".$filetarget."<br>\n";
583  if (GETPOST('restore_user_pictures', 'alpha') == 'confirmed') {
584  dol_copy($filetotest, $filetarget, '', 0);
585  }
586  }
587 
588  $existtt = dol_is_file($filetargetsmall);
589  if (!$existtt) {
590  if (GETPOST('restore_user_pictures', 'alpha') == 'confirmed') {
591  dol_mkdir($dolibarr_main_data_root.'/users/'.$obj->rowid.'/thumbs');
592  }
593 
594  print " &nbsp; &nbsp; &nbsp; -> Copy file ".$filetotestsmall." -> ".$filetargetsmall."<br>\n";
595  if (GETPOST('restore_user_pictures', 'alpha') == 'confirmed') {
596  dol_copy($filetotestsmall, $filetargetsmall, '', 0);
597  }
598  }
599 
600  $existtt = dol_is_file($filetargetmini);
601  if (!$existtt) {
602  if (GETPOST('restore_user_pictures', 'alpha') == 'confirmed') {
603  dol_mkdir($dolibarr_main_data_root.'/users/'.$obj->rowid.'/thumbs');
604  }
605 
606  print " &nbsp; &nbsp; &nbsp; -> Copy file ".$filetotestmini." -> ".$filetargetmini."<br>\n";
607  if (GETPOST('restore_user_pictures', 'alpha') == 'confirmed') {
608  dol_copy($filetotestmini, $filetargetmini, '', 0);
609  }
610  }
611  }
612  }
613 
614  $i++;
615  }
616  } else {
617  $ok = 0;
618  dol_print_error($db);
619  }
620 
621  print '</td></tr>';
622 }
623 
624 
625 // rebuild_product_thumbs: Rebuild thumbs for product files
626 if ($ok && GETPOST('rebuild_product_thumbs', 'alpha')) {
627  $ext = '';
628  global $maxwidthsmall, $maxheightsmall, $maxwidthmini, $maxheightmini;
629 
630  print '<tr><td colspan="2"><br>*** Rebuild product thumbs<br>';
631 
632  $sql = "SELECT s.rowid, s.ref FROM ".MAIN_DB_PREFIX."product as s ORDER BY s.ref";
633  $resql = $db->query($sql);
634  if ($resql) {
635  $num = $db->num_rows($resql);
636  $i = 0;
637 
638  while ($i < $num) {
639  $obj = $db->fetch_object($resql);
640 
641  if (!empty($obj->ref)) {
642  $files = dol_dir_list($dolibarr_main_data_root.'/produit/'.$obj->ref, 'files', 0);
643  foreach ($files as $file) {
644  // Generate thumbs.
645  if (image_format_supported($file['fullname']) == 1) {
646  $imgThumbSmall = 'notbuild';
647  if (GETPOST('rebuild_product_thumbs', 'alpha') == 'confirmed') {
648  // Used on logon for example
649  $imgThumbSmall = vignette($file['fullname'], $maxwidthsmall, $maxheightsmall, '_small', 50, "thumbs");
650  }
651  print 'Check product '.$obj->rowid.", file ".$file['fullname']." -> ".$imgThumbSmall." maxwidthsmall=".$maxwidthsmall." maxheightsmall=".$maxheightsmall."<br>\n";
652  $imgThumbMini = 'notbuild';
653  if (GETPOST('rebuild_product_thumbs', 'alpha') == 'confirmed') {
654  // Create mini thumbs for image (Ratio is near 16/9)
655  // Used on menu or for setup page for example
656  $imgThumbMini = vignette($file['fullname'], $maxwidthmini, $maxheightmini, '_mini', 50, "thumbs");
657  }
658  print 'Check product '.$obj->rowid.", file ".$file['fullname']." -> ".$imgThumbMini." maxwidthmini=".$maxwidthmini." maxheightmini=".$maxheightmini."<br>\n";
659  }
660  }
661  }
662 
663  $i++;
664  }
665  } else {
666  $ok = 0;
667  dol_print_error($db);
668  }
669 
670  print '</td></tr>';
671 }
672 
673 // clean_linked_elements: Check and clean linked elements
674 if ($ok && GETPOST('clean_linked_elements', 'alpha')) {
675  print '<tr><td colspan="2"><br>*** Check table of linked elements and delete orphelins links</td></tr>';
676  // propal => order
677  print '<tr><td colspan="2">'.checkLinkedElements('propal', 'commande')."</td></tr>\n";
678 
679  // propal => invoice
680  print '<tr><td colspan="2">'.checkLinkedElements('propal', 'facture')."</td></tr>\n";
681 
682  // order => invoice
683  print '<tr><td colspan="2">'.checkLinkedElements('commande', 'facture')."</td></tr>\n";
684 
685  // order => shipping
686  print '<tr><td colspan="2">'.checkLinkedElements('commande', 'shipping')."</td></tr>\n";
687 
688  // shipping => delivery
689  print '<tr><td colspan="2">'.checkLinkedElements('shipping', 'delivery')."</td></tr>\n";
690 
691  // order_supplier => invoice_supplier
692  print '<tr><td colspan="2">'.checkLinkedElements('order_supplier', 'invoice_supplier')."</td></tr>\n";
693 }
694 
695 
696 // clean_menus: Check orphelins menus
697 if ($ok && GETPOST('clean_menus', 'alpha')) {
698  print '<tr><td colspan="2"><br>*** Clean menu entries coming from disabled modules</td></tr>';
699 
700  $sql = "SELECT rowid, module";
701  $sql .= " FROM ".MAIN_DB_PREFIX."menu as c";
702  $sql .= " WHERE module IS NOT NULL AND module <> ''";
703  $sql .= " ORDER BY module";
704 
705  $resql = $db->query($sql);
706  if ($resql) {
707  $num = $db->num_rows($resql);
708  if ($num) {
709  $i = 0;
710  while ($i < $num) {
711  $obj = $db->fetch_object($resql);
712 
713  $modulecond = $obj->module;
714  $modulecondarray = explode('|', $obj->module); // Name of module
715 
716  print '<tr><td>';
717  print $modulecond;
718 
719  $db->begin();
720 
721  if ($modulecond) { // And menu entry for module $modulecond was found in database.
722  $moduleok = 0;
723  foreach ($modulecondarray as $tmpname) {
724  if ($tmpname == 'margins') {
725  $tmpname = 'margin'; // TODO Remove this when normalized
726  }
727 
728  $result = 0;
729  if (!empty($conf->$tmpname)) {
730  $result = $conf->$tmpname->enabled;
731  }
732  if ($result) {
733  $moduleok++;
734  }
735  }
736 
737  if (!$moduleok && $modulecond) {
738  print ' - Module condition '.$modulecond.' seems ko, we delete menu entry.';
739  if (GETPOST('clean_menus') == 'confirmed') {
740  $sql2 = "DELETE FROM ".MAIN_DB_PREFIX."menu WHERE module = '".$db->escape($modulecond)."'";
741  $resql2 = $db->query($sql2);
742  if (!$resql2) {
743  $error++;
744  dol_print_error($db);
745  } else {
746  print ' - <span class="warning">Cleaned</span>';
747  }
748  } else {
749  print ' - <span class="warning">Canceled (test mode)</span>';
750  }
751  } else {
752  print ' - Module condition '.$modulecond.' is ok, we do nothing.';
753  }
754  }
755 
756  if (!$error) {
757  $db->commit();
758  } else {
759  $db->rollback();
760  }
761 
762  print'</td></tr>';
763 
764  if ($error) {
765  break;
766  }
767 
768  $i++;
769  }
770  } else {
771  print '<tr><td>No menu entries of disabled menus found</td></tr>';
772  }
773  } else {
774  dol_print_error($db);
775  }
776 }
777 
778 
779 
780 // clean_orphelin_dir: Run purge of directory
781 if ($ok && GETPOST('clean_orphelin_dir', 'alpha')) {
782  $listmodulepart = array('company', 'invoice', 'invoice_supplier', 'propal', 'order', 'order_supplier', 'contract', 'tax');
783  foreach ($listmodulepart as $modulepart) {
784  $filearray = array();
785  $upload_dir = isset($conf->$modulepart->dir_output) ? $conf->$modulepart->dir_output : '';
786  if ($modulepart == 'company') {
787  $upload_dir = $conf->societe->dir_output; // TODO change for multicompany sharing
788  }
789  if ($modulepart == 'invoice') {
790  $upload_dir = $conf->facture->dir_output;
791  }
792  if ($modulepart == 'invoice_supplier') {
793  $upload_dir = $conf->fournisseur->facture->dir_output;
794  }
795  if ($modulepart == 'order') {
796  $upload_dir = $conf->commande->dir_output;
797  }
798  if ($modulepart == 'order_supplier') {
799  $upload_dir = $conf->fournisseur->commande->dir_output;
800  }
801  if ($modulepart == 'contract') {
802  $upload_dir = $conf->contrat->dir_output;
803  }
804 
805  if (empty($upload_dir)) {
806  continue;
807  }
808 
809  print '<tr><td colspan="2"><br>*** Clean orphelins files into files '.$upload_dir.'</td></tr>';
810 
811  $filearray = dol_dir_list($upload_dir, "files", 1, '', array('^SPECIMEN\.pdf$', '^\.', '(\.meta|_preview.*\.png)$', '^temp$', '^payments$', '^CVS$', '^thumbs$'), '', SORT_DESC, 1, true);
812 
813  // To show ref or specific information according to view to show (defined by $module)
814  if ($modulepart == 'company') {
815  include_once DOL_DOCUMENT_ROOT.'/societe/class/societe.class.php';
816  $object_instance = new Societe($db);
817  }
818  if ($modulepart == 'invoice') {
819  include_once DOL_DOCUMENT_ROOT.'/compta/facture/class/facture.class.php';
820  $object_instance = new Facture($db);
821  } elseif ($modulepart == 'invoice_supplier') {
822  include_once DOL_DOCUMENT_ROOT.'/fourn/class/fournisseur.facture.class.php';
823  $object_instance = new FactureFournisseur($db);
824  } elseif ($modulepart == 'propal') {
825  include_once DOL_DOCUMENT_ROOT.'/comm/propal/class/propal.class.php';
826  $object_instance = new Propal($db);
827  } elseif ($modulepart == 'order') {
828  include_once DOL_DOCUMENT_ROOT.'/commande/class/commande.class.php';
829  $object_instance = new Commande($db);
830  } elseif ($modulepart == 'order_supplier') {
831  include_once DOL_DOCUMENT_ROOT.'/fourn/class/fournisseur.commande.class.php';
832  $object_instance = new CommandeFournisseur($db);
833  } elseif ($modulepart == 'contract') {
834  include_once DOL_DOCUMENT_ROOT.'/contrat/class/contrat.class.php';
835  $object_instance = new Contrat($db);
836  } elseif ($modulepart == 'tax') {
837  include_once DOL_DOCUMENT_ROOT.'/compta/sociales/class/chargesociales.class.php';
838  $object_instance = new ChargeSociales($db);
839  }
840 
841  foreach ($filearray as $key => $file) {
842  if (!is_dir($file['name'])
843  && $file['name'] != '.'
844  && $file['name'] != '..'
845  && $file['name'] != 'CVS'
846  ) {
847  // Define relative path used to store the file
848  $relativefile = preg_replace('/'.preg_quote($upload_dir.'/', '/').'/', '', $file['fullname']);
849 
850  //var_dump($file);
851  $id = 0; $ref = ''; $object_instance->id = 0; $object_instance->ref = ''; $label = '';
852 
853  // To show ref or specific information according to view to show (defined by $module)
854  if ($modulepart == 'invoice') {
855  preg_match('/(.*)\/[^\/]+$/', $relativefile, $reg); $ref = $reg[1];
856  }
857  if ($modulepart == 'invoice_supplier') {
858  preg_match('/(\d+)\/[^\/]+$/', $relativefile, $reg); $id = empty($reg[1]) ? '' : $reg[1];
859  }
860  if ($modulepart == 'propal') {
861  preg_match('/(.*)\/[^\/]+$/', $relativefile, $reg); $ref = $reg[1];
862  }
863  if ($modulepart == 'order') {
864  preg_match('/(.*)\/[^\/]+$/', $relativefile, $reg); $ref = $reg[1];
865  }
866  if ($modulepart == 'order_supplier') {
867  preg_match('/(.*)\/[^\/]+$/', $relativefile, $reg); $ref = $reg[1];
868  }
869  if ($modulepart == 'contract') {
870  preg_match('/(.*)\/[^\/]+$/', $relativefile, $reg); $ref = $reg[1];
871  }
872  if ($modulepart == 'tax') {
873  preg_match('/(\d+)\/[^\/]+$/', $relativefile, $reg); $id = $reg[1];
874  }
875 
876  if ($id || $ref) {
877  //print 'Fetch '.$id.' or '.$ref.'<br>';
878  $result = $object_instance->fetch($id, $ref);
879  //print $result.'<br>';
880  if ($result == 0) { // Not found but no error
881  // Clean of orphelins directories are done into repair.php
882  print '<tr><td colspan="2">';
883  print 'Delete orphelins file '.$file['fullname'].'<br>';
884  if (GETPOST('clean_orphelin_dir', 'alpha') == 'confirmed') {
885  dol_delete_file($file['fullname'], 1, 1, 1);
886  dol_delete_dir(dirname($file['fullname']), 1);
887  }
888  print "</td></tr>";
889  } elseif ($result < 0) {
890  print 'Error in '.get_class($object_instance).'.fetch of id'.$id.' ref='.$ref.', result='.$result.'<br>';
891  }
892  }
893  }
894  }
895  }
896 }
897 
898 // clean_linked_elements: Check and clean linked elements
899 if ($ok && GETPOST('clean_product_stock_batch', 'alpha')) {
900  $methodtofix = GETPOST('methodtofix', 'alpha') ?GETPOST('methodtofix', 'alpha') : 'updatestock';
901 
902  print '<tr><td colspan="2"><br>*** Clean table product_batch, methodtofix='.$methodtofix.' (possible values: updatestock or updatebatch)</td></tr>';
903 
904  $sql = "SELECT p.rowid, p.ref, p.tobatch, ps.rowid as psrowid, ps.fk_entrepot, ps.reel, SUM(pb.qty) as reelbatch";
905  $sql .= " FROM ".MAIN_DB_PREFIX."product as p, ".MAIN_DB_PREFIX."product_stock as ps LEFT JOIN ".MAIN_DB_PREFIX."product_batch as pb ON ps.rowid = pb.fk_product_stock";
906  $sql .= " WHERE p.rowid = ps.fk_product";
907  $sql .= " GROUP BY p.rowid, p.ref, p.tobatch, ps.rowid, ps.fk_entrepot, ps.reel";
908  $sql .= " HAVING (SUM(pb.qty) IS NOT NULL AND reel != SUM(pb.qty)) OR (SUM(pb.qty) IS NULL AND p.tobatch > 0)";
909  print $sql;
910  $resql = $db->query($sql);
911  if ($resql) {
912  $num = $db->num_rows($resql);
913 
914  if ($num) {
915  $i = 0;
916  while ($i < $num) {
917  $obj = $db->fetch_object($resql);
918  print '<tr><td>Product '.$obj->rowid.'-'.$obj->ref.' in warehouse id='.$obj->fk_entrepot.' (product_stock.id='.$obj->psrowid.'): '.$obj->reel.' (Stock product_stock.reel) != '.($obj->reelbatch ? $obj->reelbatch : '0').' (Stock batch sum product_batch)';
919 
920  // Fix is required
921  if ($obj->reel != $obj->reelbatch) {
922  if (empty($obj->tobatch)) {
923  // If product is not a product that support batches, we can clean stock by deleting the product batch lines
924  print ' -> Delete qty '.$obj->reelbatch.' for any lot linked to fk_product_stock='.$obj->psrowid;
925  $sql2 = "DELETE FROM ".MAIN_DB_PREFIX."product_batch";
926  $sql2 .= " WHERE fk_product_stock = ".((int) $obj->psrowid);
927  print '<br>'.$sql2;
928 
929  if (GETPOST('clean_product_stock_batch') == 'confirmed') {
930  $resql2 = $db->query($sql2);
931  if (!$resql2) {
932  $error++;
933  dol_print_error($db);
934  }
935  }
936  } else {
937  if ($methodtofix == 'updatebatch') {
938  // Method 1
939  print ' -> Insert qty '.($obj->reel - $obj->reelbatch).' with lot 000000 linked to fk_product_stock='.$obj->psrowid;
940  $sql2 = "INSERT INTO ".MAIN_DB_PREFIX."product_batch(fk_product_stock, batch, qty)";
941  $sql2 .= "VALUES(".((int) $obj->psrowid).", '000000', ".((float) ($obj->reel - $obj->reelbatch)).")";
942  print '<br>'.$sql2;
943 
944  if (GETPOST('clean_product_stock_batch') == 'confirmed') {
945  $resql2 = $db->query($sql2);
946  if (!$resql2) {
947  // TODO If it fails, we must make update
948  //$sql2 ="UPDATE ".MAIN_DB_PREFIX."product_batch";
949  //$sql2.=" SET ".$obj->psrowid.", '000000', ".($obj->reel - $obj->reelbatch).")";
950  //$sql2.=" WHERE fk_product_stock = ".((int) $obj->psrowid)
951  }
952  }
953  }
954  if ($methodtofix == 'updatestock') {
955  // Method 2
956  print ' -> Update qty of product_stock with qty = '.($obj->reelbatch ? ((float) $obj->reelbatch) : '0').' for ps.rowid = '.((int) $obj->psrowid);
957  $sql2 = "UPDATE ".MAIN_DB_PREFIX."product_stock";
958  $sql2 .= " SET reel = ".($obj->reelbatch ? ((float) $obj->reelbatch) : '0')." WHERE rowid = ".((int) $obj->psrowid);
959  print '<br>'.$sql2;
960 
961  if (GETPOST('clean_product_stock_batch') == 'confirmed') {
962  $error = 0;
963 
964  $db->begin();
965 
966  $resql2 = $db->query($sql2);
967  if ($resql2) {
968  // We update product_stock, so we must fill p.stock into product too.
969  $sql3 = 'UPDATE '.MAIN_DB_PREFIX.'product p SET p.stock= (SELECT SUM(ps.reel) FROM '.MAIN_DB_PREFIX.'product_stock ps WHERE ps.fk_product = p.rowid)';
970  $resql3 = $db->query($sql3);
971  if (!$resql3) {
972  $error++;
973  dol_print_error($db);
974  }
975  } else {
976  $error++;
977  dol_print_error($db);
978  }
979 
980  if (!$error) {
981  $db->commit();
982  } else {
983  $db->rollback();
984  }
985  }
986  }
987  }
988  }
989 
990  print'</td></tr>';
991 
992  $i++;
993  }
994  } else {
995  print '<tr><td colspan="2">Nothing to do</td></tr>';
996  }
997  } else {
998  dol_print_error($db);
999  }
1000 }
1001 
1002 
1003 // clean_product_stock_negative_if_batch
1004 if ($ok && GETPOST('clean_product_stock_negative_if_batch', 'alpha')) {
1005  print '<tr><td colspan="2"><br>Clean table product_batch, methodtofix='.$methodtofix.' (possible values: updatestock or updatebatch)</td></tr>';
1006 
1007  $sql = "SELECT p.rowid, p.ref, p.tobatch, ps.rowid as psrowid, ps.fk_entrepot, ps.reel, SUM(pb.qty) as reelbatch";
1008  $sql .= " FROM ".MAIN_DB_PREFIX."product as p, ".MAIN_DB_PREFIX."product_stock as ps, ".MAIN_DB_PREFIX."product_batch as pb";
1009  $sql .= " WHERE p.rowid = ps.fk_product AND ps.rowid = pb.fk_product_stock";
1010  $sql .= " AND p.tobatch > 0";
1011  $sql .= " GROUP BY p.rowid, p.ref, p.tobatch, ps.rowid, ps.fk_entrepot, ps.reel";
1012  $sql .= " HAVING reel != SUM(pb.qty)";
1013  $resql = $db->query($sql);
1014  if ($resql) {
1015  $num = $db->num_rows($resql);
1016 
1017  if ($num) {
1018  $i = 0;
1019  while ($i < $num) {
1020  $obj = $db->fetch_object($resql);
1021  print '<tr><td>'.$obj->rowid.'-'.$obj->ref.'-'.$obj->fk_entrepot.' -> '.$obj->psrowid.': '.$obj->reel.' != '.$obj->reelbatch;
1022 
1023  // TODO
1024  }
1025  }
1026  }
1027 }
1028 
1029 // set_empty_time_spent_amount
1030 if ($ok && GETPOST('set_empty_time_spent_amount', 'alpha')) {
1031  print '<tr><td colspan="2"><br>*** Set value of time spent without amount</td></tr>';
1032 
1033  $sql = "SELECT COUNT(ptt.rowid) as nb, u.rowid as user_id, u.login, u.thm as user_thm";
1034  $sql .= " FROM ".MAIN_DB_PREFIX."element_time as ptt, ".MAIN_DB_PREFIX."user as u";
1035  $sql .= " WHERE ptt.fk_user = u.rowid";
1036  $sql .= " AND ptt.thm IS NULL and u.thm > 0";
1037  $sql .= " GROUP BY u.rowid, u.login, u.thm";
1038 
1039  $resql = $db->query($sql);
1040  if ($resql) {
1041  $num = $db->num_rows($resql);
1042 
1043  if ($num) {
1044  $i = 0;
1045  while ($i < $num) {
1046  $obj = $db->fetch_object($resql);
1047  print '<tr><td>'.$obj->login.'-'.$obj->user_id.' ('.$obj->nb.' lines to fix) -> '.$obj->user_thm;
1048 
1049  $db->begin();
1050 
1051  if (GETPOST('set_empty_time_spent_amount') == 'confirmed') {
1052  $sql2 = "UPDATE ".MAIN_DB_PREFIX."element_time";
1053  $sql2 .= " SET thm = ".$obj->user_thm." WHERE thm IS NULL AND fk_user = ".((int) $obj->user_id);
1054  $resql2 = $db->query($sql2);
1055  if (!$resql2) {
1056  $error++;
1057  dol_print_error($db);
1058  }
1059  }
1060 
1061  if (!$error) {
1062  $db->commit();
1063  } else {
1064  $db->rollback();
1065  }
1066 
1067  print'</td></tr>';
1068 
1069  if ($error) {
1070  break;
1071  }
1072 
1073  $i++;
1074  }
1075  } else {
1076  print '<tr><td>No time spent with empty line on users with a hourly rate defined</td></tr>';
1077  }
1078  } else {
1079  dol_print_error($db);
1080  }
1081 }
1082 
1083 
1084 // force_disable_of_modules_not_found
1085 if ($ok && GETPOST('force_disable_of_modules_not_found', 'alpha')) {
1086  print '<tr><td colspan="2"><br>*** Force modules not found physicaly to be disabled (only modules adding js, css or hooks can be detected as removed physicaly)</td></tr>';
1087 
1088  $arraylistofkey = array('hooks', 'js', 'css');
1089 
1090  foreach ($arraylistofkey as $key) {
1091  $sql = "SELECT DISTINCT name, value";
1092  $sql .= " FROM ".MAIN_DB_PREFIX."const as c";
1093  $sql .= " WHERE name LIKE 'MAIN_MODULE_%_".strtoupper($key)."'";
1094  $sql .= " ORDER BY name";
1095 
1096  $resql = $db->query($sql);
1097  if ($resql) {
1098  $num = $db->num_rows($resql);
1099  if ($num) {
1100  $i = 0;
1101  while ($i < $num) {
1102  $obj = $db->fetch_object($resql);
1103  $constantname = $obj->name; // Name of constant for hook or js or css declaration
1104 
1105  print '<tr><td>';
1106  print dol_escape_htmltag($constantname);
1107 
1108  $db->begin();
1109 
1110  $reg = array();
1111  if (preg_match('/MAIN_MODULE_(.*)_'.strtoupper($key).'/i', $constantname, $reg)) {
1112  $name = strtolower($reg[1]);
1113 
1114  if ($name) { // An entry for key $key and module $name was found in database.
1115  $reloffile = '';
1116  $result = 'found';
1117 
1118  if ($key == 'hooks') {
1119  $reloffile = $name.'/class/actions_'.$name.'.class.php';
1120  }
1121  if ($key == 'js') {
1122  $value = $obj->value;
1123  $valuearray = json_decode($value);
1124  $reloffile = $valuearray[0];
1125  $reloffile = preg_replace('/^\//', '', $valuearray[0]);
1126  }
1127  if ($key == 'css') {
1128  $value = $obj->value;
1129  $valuearray = json_decode($value);
1130  if ($value && (!is_array($valuearray) || count($valuearray) == 0)) {
1131  $valuearray = array();
1132  $valuearray[0] = $value; // If value was not a json array but a string
1133  }
1134  $reloffile = preg_replace('/^\//', '', $valuearray[0]);
1135  }
1136 
1137  if ($reloffile) {
1138  //var_dump($key.' - '.$value.' - '.$reloffile);
1139  try {
1140  $result = dol_buildpath($reloffile, 0, 2);
1141  } catch (Exception $e) {
1142  $result = 'found'; // If error, we force like if we found to avoid any deletion
1143  }
1144  } else {
1145  $result = 'found'; //
1146  }
1147 
1148  if (!$result) {
1149  print ' - File of '.$key.' ('.$reloffile.') NOT found, we disable the module.';
1150  if (GETPOST('force_disable_of_modules_not_found') == 'confirmed') {
1151  $sql2 = "DELETE FROM ".MAIN_DB_PREFIX."const WHERE name = 'MAIN_MODULE_".strtoupper($name)."_".strtoupper($key)."'";
1152  $resql2 = $db->query($sql2);
1153  if (!$resql2) {
1154  $error++;
1155  dol_print_error($db);
1156  }
1157  $sql3 = "DELETE FROM ".MAIN_DB_PREFIX."const WHERE name = 'MAIN_MODULE_".strtoupper($name)."'";
1158  $resql3 = $db->query($sql3);
1159  if (!$resql3) {
1160  $error++;
1161  dol_print_error($db);
1162  } else {
1163  print ' - <span class="warning">Cleaned</span>';
1164  }
1165  } else {
1166  print ' - <span class="warning">Canceled (test mode)</span>';
1167  }
1168  } else {
1169  print ' - File of '.$key.' ('.$reloffile.') found, we do nothing.';
1170  }
1171  }
1172 
1173  if (!$error) {
1174  $db->commit();
1175  } else {
1176  $db->rollback();
1177  }
1178  }
1179 
1180  print'</td></tr>';
1181 
1182  if ($error) {
1183  break;
1184  }
1185 
1186  $i++;
1187  }
1188  } else {
1189  print '<tr><td>No active module with missing files found by searching on MAIN_MODULE_(.*)_'.strtoupper($key).'</td></tr>';
1190  }
1191  } else {
1192  dol_print_error($db);
1193  }
1194  }
1195 }
1196 
1197 
1198 // clean_old_module_entries: Clean data into const when files of module were removed without being
1199 if ($ok && GETPOST('clean_perm_table', 'alpha')) {
1200  print '<tr><td colspan="2"><br>*** Clean table user_rights from lines of external modules no more enabled</td></tr>';
1201 
1202  $listofmods = '';
1203  foreach ($conf->modules as $key => $val) {
1204  $listofmods .= ($listofmods ? ',' : '')."'".$db->escape($val)."'";
1205  }
1206 
1207  $sql = "SELECT id, libelle as label, module from ".MAIN_DB_PREFIX."rights_def WHERE module NOT IN (".$db->sanitize($listofmods, 1).") AND id > 100000";
1208 
1209  $resql = $db->query($sql);
1210  if ($resql) {
1211  $num = $db->num_rows($resql);
1212  if ($num) {
1213  $i = 0;
1214  while ($i < $num) {
1215  $obj = $db->fetch_object($resql);
1216  if ($obj->id > 0) {
1217  print '<tr><td>Found line with id '.$obj->id.', label "'.$obj->label.'" of module "'.$obj->module.'" to delete';
1218  if (GETPOST('clean_perm_table', 'alpha') == 'confirmed') {
1219  $sqldelete = "DELETE FROM ".MAIN_DB_PREFIX."rights_def WHERE id = ".((int) $obj->id);
1220  $resqldelete = $db->query($sqldelete);
1221  if (!$resqldelete) {
1222  dol_print_error($db);
1223  }
1224  print ' - deleted';
1225  }
1226  print '</td></tr>';
1227  }
1228  $i++;
1229  }
1230  } else {
1231  print '<tr><td>No lines of a disabled external module (with id > 100000) found into table rights_def</td></tr>';
1232  }
1233  } else {
1234  dol_print_error($db);
1235  }
1236 }
1237 
1238 
1239 
1240 // force utf8 on tables
1241 if ($ok && GETPOST('force_utf8_on_tables', 'alpha')) {
1242  print '<tr><td colspan="2"><br>*** Force page code and collation of tables into utf8/utf8_unicode_ci and row_format=dynamic (for mysql/mariadb only)</td></tr>';
1243 
1244  if ($db->type == "mysql" || $db->type == "mysqli") {
1245  $force_utf8_on_tables = GETPOST('force_utf8_on_tables', 'alpha');
1246 
1247  $listoftables = $db->DDLListTablesFull($db->database_name);
1248 
1249  // Disable foreign key checking for avoid errors
1250  if ($force_utf8_on_tables == 'confirmed') {
1251  $sql = 'SET FOREIGN_KEY_CHECKS=0';
1252  print '<!-- '.$sql.' -->';
1253  $resql = $db->query($sql);
1254  }
1255 
1256  foreach ($listoftables as $table) {
1257  // do not convert llx_const if mysql encrypt/decrypt is used
1258  if ($conf->db->dolibarr_main_db_encryption != 0 && preg_match('/\_const$/', $table[0])) {
1259  continue;
1260  }
1261  if ($table[1] == 'VIEW') {
1262  print '<tr><td colspan="2">'.$table[0].' is a '.$table[1].' (Skipped)</td></tr>';
1263  continue;
1264  }
1265 
1266  print '<tr><td colspan="2">';
1267  print $table[0];
1268  $sql1 = "ALTER TABLE ".$table[0]." ROW_FORMAT=dynamic";
1269  $sql2 = "ALTER TABLE ".$table[0]." CONVERT TO CHARACTER SET utf8 COLLATE utf8_unicode_ci";
1270  print '<!-- '.$sql1.' -->';
1271  print '<!-- '.$sql2.' -->';
1272  if ($force_utf8_on_tables == 'confirmed') {
1273  $resql1 = $db->query($sql1);
1274  if ($resql1) {
1275  $resql2 = $db->query($sql2);
1276  } else {
1277  $resql2 = false;
1278  }
1279  print ' - Done ('.(($resql1 && $resql2) ? 'OK' : 'KO').')';
1280  } else {
1281  print ' - Disabled';
1282  }
1283  print '</td></tr>';
1284  }
1285 
1286  // Enable foreign key checking
1287  if ($force_utf8_on_tables == 'confirmed') {
1288  $sql = 'SET FOREIGN_KEY_CHECKS=1';
1289  print '<!-- '.$sql.' -->';
1290  $resql = $db->query($sql);
1291  }
1292  } else {
1293  print '<tr><td colspan="2">Not available with database type '.$db->type.'</td></tr>';
1294  }
1295 }
1296 
1297 // force utf8mb4 on tables EXPERIMENTAL !
1298 if ($ok && GETPOST('force_utf8mb4_on_tables', 'alpha')) {
1299  print '<tr><td colspan="2"><br>*** Force page code and collation of tables into utf8mb4/utf8mb4_unicode_ci (for mysql/mariadb only)</td></tr>';
1300 
1301  if ($db->type == "mysql" || $db->type == "mysqli") {
1302  $force_utf8mb4_on_tables = GETPOST('force_utf8mb4_on_tables', 'alpha');
1303 
1304  $listoftables = $db->DDLListTablesFull($db->database_name);
1305 
1306  // Disable foreign key checking for avoid errors
1307  if ($force_utf8mb4_on_tables == 'confirmed') {
1308  $sql = 'SET FOREIGN_KEY_CHECKS=0';
1309  print '<!-- '.$sql.' -->';
1310  $resql = $db->query($sql);
1311  }
1312 
1313  foreach ($listoftables as $table) {
1314  // do not convert llx_const if mysql encrypt/decrypt is used
1315  if ($conf->db->dolibarr_main_db_encryption != 0 && preg_match('/\_const$/', $table[0])) {
1316  continue;
1317  }
1318  if ($table[1] == 'VIEW') {
1319  print '<tr><td colspan="2">'.$table[0].' is a '.$table[1].' (Skipped)</td></tr>';
1320  continue;
1321  }
1322 
1323  print '<tr><td colspan="2">';
1324  print $table[0];
1325  $sql1 = "ALTER TABLE ".$table[0]." ROW_FORMAT=dynamic";
1326  $sql2 = "ALTER TABLE ".$table[0]." CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci";
1327  print '<!-- '.$sql1.' -->';
1328  print '<!-- '.$sql2.' -->';
1329  if ($force_utf8mb4_on_tables == 'confirmed') {
1330  $resql1 = $db->query($sql1);
1331  if ($resql1) {
1332  $resql2 = $db->query($sql2);
1333  } else {
1334  $resql2 = false;
1335  }
1336  print ' - Done ('.(($resql1 && $resql2) ? 'OK' : 'KO').')';
1337  } else {
1338  print ' - Disabled';
1339  }
1340  print '</td></tr>';
1341  flush();
1342  ob_flush();
1343  }
1344 
1345  // Enable foreign key checking
1346  if ($force_utf8mb4_on_tables == 'confirmed') {
1347  $sql = 'SET FOREIGN_KEY_CHECKS=1';
1348  print '<!-- '.$sql.' -->';
1349  $resql = $db->query($sql);
1350  }
1351  } else {
1352  print '<tr><td colspan="2">Not available with database type '.$db->type.'</td></tr>';
1353  }
1354 }
1355 
1356 // rebuild sequences for pgsql
1357 if ($ok && GETPOST('rebuild_sequences', 'alpha')) {
1358  print '<tr><td colspan="2"><br>*** Force to rebuild sequences (for postgresql only)</td></tr>';
1359 
1360  if ($db->type == "pgsql") {
1361  $rebuild_sequence = GETPOST('rebuild_sequences', 'alpha');
1362 
1363  if ($rebuild_sequence == 'confirmed') {
1364  $sql = "SELECT dol_util_rebuild_sequences();";
1365  print '<!-- '.$sql.' -->';
1366  $resql = $db->query($sql);
1367  }
1368  } else {
1369  print '<tr><td colspan="2">Not available with database type '.$db->type.'</td></tr>';
1370  }
1371 }
1372 
1373 //
1374 if ($ok && GETPOST('repair_link_dispatch_lines_supplier_order_lines')) {
1375  /*
1376  * This script is meant to be run when upgrading from a dolibarr version < 3.8
1377  * to a newer version.
1378  *
1379  * Version 3.8 introduces a new column in llx_commande_fournisseur_dispatch, which
1380  * matches the dispatch to a specific supplier order line (so that if there are
1381  * several with the same product, the user can specifically tell which products of
1382  * which line were dispatched where).
1383  *
1384  * However when migrating, the new column has a default value of 0, which means that
1385  * old supplier orders whose lines were dispatched using the old dolibarr version
1386  * have unspecific dispatch lines, which are not taken into account by the new version,
1387  * thus making the order look like it was never dispatched at all.
1388  *
1389  * This scripts sets this foreign key to the first matching supplier order line whose
1390  * product (and supplier order of course) are the same as the dispatch’s.
1391  *
1392  * If the dispatched quantity is more than indicated on the order line (this happens if
1393  * there are several order lines for the same product), it creates new dispatch lines
1394  * pointing to the other order lines accordingly, until all the dispatched quantity is
1395  * accounted for.
1396  */
1397 
1398  $repair_link_dispatch_lines_supplier_order_lines = GETPOST('repair_link_dispatch_lines_supplier_order_lines', 'alpha');
1399 
1400 
1401  echo '<tr><th>Repair llx_commande_fournisseur_dispatch.fk_commandefourndet</th></tr>';
1402  echo '<tr><td>Repair in progress. This may take a while.</td></tr>';
1403 
1404  $sql_dispatch = 'SELECT * FROM '.MAIN_DB_PREFIX.'commande_fournisseur_dispatch WHERE COALESCE(fk_commandefourndet, 0) = 0';
1405  $db->begin();
1406  $resql_dispatch = $db->query($sql_dispatch);
1407  $n_processed_rows = 0;
1408  $errors = array();
1409  if ($resql_dispatch) {
1410  if ($db->num_rows($resql_dispatch) == 0) {
1411  echo '<tr><td>Nothing to do.</td></tr>';
1412  exit;
1413  }
1414  while ($obj_dispatch = $db->fetch_object($resql_dispatch)) {
1415  $sql_line = 'SELECT line.rowid, line.qty FROM '.MAIN_DB_PREFIX.'commande_fournisseurdet AS line';
1416  $sql_line .= ' WHERE line.fk_commande = '.((int) $obj_dispatch->fk_commande);
1417  $sql_line .= ' AND line.fk_product = '.((int) $obj_dispatch->fk_product);
1418  $resql_line = $db->query($sql_line);
1419 
1420  // s’il y a plusieurs lignes avec le même produit sur cette commande fournisseur,
1421  // on divise la ligne de dispatch en autant de lignes qu’on en a sur la commande pour le produit
1422  // et on met la quantité de la ligne dans la limite du "budget" indiqué par dispatch.qty
1423 
1424  $remaining_qty = $obj_dispatch->qty;
1425  $first_iteration = true;
1426  if (!$resql_line) {
1427  echo '<tr><td>Unable to find a matching supplier order line for dispatch #'.$obj_dispatch->rowid.'</td></tr>';
1428  $errors[] = $sql_line;
1429  $n_processed_rows++;
1430  continue;
1431  }
1432  if ($db->num_rows($resql_line) == 0) {
1433  continue;
1434  }
1435  while ($obj_line = $db->fetch_object($resql_line)) {
1436  if (!$remaining_qty) {
1437  break;
1438  }
1439  if (!$obj_line->rowid) {
1440  continue;
1441  }
1442  $qty_for_line = min($remaining_qty, $obj_line->qty);
1443  if ($first_iteration) {
1444  $sql_attach = 'UPDATE '.MAIN_DB_PREFIX.'commande_fournisseur_dispatch';
1445  $sql_attach .= ' SET fk_commandefourndet = '.((int) $obj_line->rowid).', qty = '.((float) $qty_for_line);
1446  $sql_attach .= ' WHERE rowid = '.((int) $obj_dispatch->rowid);
1447  $first_iteration = false;
1448  } else {
1449  $sql_attach_values = array(
1450  ((int) $obj_dispatch->fk_commande),
1451  ((int) $obj_dispatch->fk_product),
1452  ((int) $obj_line->rowid),
1453  ((float) $qty_for_line),
1454  ((int) $obj_dispatch->fk_entrepot),
1455  ((int) $obj_dispatch->fk_user),
1456  $obj_dispatch->datec ? "'".$db->idate($db->jdate($obj_dispatch->datec))."'" : 'NULL',
1457  $obj_dispatch->comment ? "'".$db->escape($obj_dispatch->comment)."'" : 'NULL',
1458  $obj_dispatch->status ? ((int) $obj_dispatch->status) : 'NULL',
1459  $obj_dispatch->tms ? "'".$db->idate($db->jdate($obj_dispatch->tms))."'" : 'NULL',
1460  $obj_dispatch->batch ? "'".$db->escape($obj_dispatch->batch)."'" : 'NULL',
1461  $obj_dispatch->eatby ? "'".$db->escape($obj_dispatch->eatby)."'" : 'NULL',
1462  $obj_dispatch->sellby ? "'".$db->escape($obj_dispatch->sellby)."'" : 'NULL'
1463  );
1464  $sql_attach_values = join(', ', $sql_attach_values);
1465 
1466  $sql_attach = 'INSERT INTO '.MAIN_DB_PREFIX.'commande_fournisseur_dispatch';
1467  $sql_attach .= ' (fk_commande, fk_product, fk_commandefourndet, qty, fk_entrepot, fk_user, datec, comment, status, tms, batch, eatby, sellby)';
1468  $sql_attach .= " VALUES (".$sql_attach_values.")";
1469  }
1470 
1471  if ($repair_link_dispatch_lines_supplier_order_lines == 'confirmed') {
1472  $resql_attach = $db->query($sql_attach);
1473  } else {
1474  $resql_attach = true; // Force success in test mode
1475  }
1476 
1477  if ($resql_attach) {
1478  $remaining_qty -= $qty_for_line;
1479  } else {
1480  $errors[] = $sql_attach;
1481  }
1482 
1483  $first_iteration = false;
1484  }
1485  $n_processed_rows++;
1486 
1487  // report progress every 256th row
1488  if (!($n_processed_rows & 0xff)) {
1489  echo '<tr><td>Processed '.$n_processed_rows.' rows with '.count($errors).' errors…'."</td></tr>\n";
1490  flush();
1491  ob_flush();
1492  }
1493  }
1494  } else {
1495  echo '<tr><td>Unable to find any dispatch without an fk_commandefourndet.'."</td></tr>\n";
1496  echo $sql_dispatch."\n";
1497  }
1498  echo '<tr><td>Fixed '.$n_processed_rows.' rows with '.count($errors).' errors…'."</td></tr>\n";
1499  echo '<tr><td>DONE.'."</td></tr>\n";
1500 
1501  if (count($errors)) {
1502  $db->rollback();
1503  echo '<tr><td>The transaction was rolled back due to errors: nothing was changed by the script.</td></tr>';
1504  } else {
1505  $db->commit();
1506  }
1507  $db->close();
1508 
1509  echo '<tr><td><h3>SQL queries with errors:</h3></tr></td>';
1510  echo '<tr><td>'.join('</td></tr><tr><td>', $errors).'</td></tr>';
1511 }
1512 
1513 // Repair llx_commande_fournisseur to eleminate duplicate reference
1514 if ($ok && GETPOST('repair_supplier_order_duplicate_ref')) {
1515  require_once DOL_DOCUMENT_ROOT . '/fourn/class/fournisseur.commande.class.php';
1516  include_once DOL_DOCUMENT_ROOT . '/societe/class/societe.class.php';
1517 
1518  $db->begin();
1519 
1520  $err = 0;
1521 
1522  // Query to find all duplicate supplier orders
1523  $sql = "SELECT * FROM " . MAIN_DB_PREFIX . "commande_fournisseur";
1524  $sql .= " WHERE ref IN (SELECT cf.ref FROM " . MAIN_DB_PREFIX . "commande_fournisseur cf GROUP BY cf.ref, cf.entity HAVING COUNT(cf.rowid) > 1)";
1525 
1526  // Build a list of ref => []CommandeFournisseur
1527  $duplicateSupplierOrders = [];
1528  $resql = $db->query($sql);
1529  if ($resql) {
1530  while ($rawSupplierOrder = $db->fetch_object($resql)) {
1531  $supplierOrder = new CommandeFournisseur($db);
1532  $supplierOrder->setVarsFromFetchObj($rawSupplierOrder);
1533 
1534  $duplicateSupplierOrders[$rawSupplierOrder->ref] [] = $supplierOrder;
1535  }
1536  } else {
1537  $err++;
1538  }
1539 
1540  // Process all duplicate supplier order and regenerate the reference for all except the first one
1541  foreach ($duplicateSupplierOrders as $ref => $supplierOrders) {
1543  foreach (array_slice($supplierOrders, 1) as $supplierOrder) {
1544  // Definition of supplier order numbering model name
1545  $soc = new Societe($db);
1546  $soc->fetch($supplierOrder->fourn_id);
1547 
1548  $newRef = $supplierOrder->getNextNumRef($soc);
1549 
1550  $sql = "UPDATE " . MAIN_DB_PREFIX . "commande_fournisseur cf SET cf.ref = '" . $db->escape($newRef) . "' WHERE cf.rowid = " . (int) $supplierOrder->id;
1551  if (!$db->query($sql)) {
1552  $err++;
1553  }
1554  }
1555  }
1556 
1557  if ($err == 0) {
1558  $db->commit();
1559  } else {
1560  $db->rollback();
1561  }
1562 }
1563 
1564 print '</table>';
1565 
1566 
1567 
1568 if (empty($actiondone)) {
1569  print '<div class="error">'.$langs->trans("ErrorWrongParameters").'</div>';
1570 }
1571 
1572 if ($oneoptionset) {
1573  print '<div class="center" style="padding-top: 10px"><a href="../index.php?mainmenu=home&leftmenu=home'.(GETPOSTISSET("login") ? '&username='.urlencode(GETPOST("login")) : '').'">';
1574  print $langs->trans("GoToDolibarr");
1575  print '</a></div>';
1576 } else {
1577  print '<div class="center warning" style="padding-top: 10px">';
1578  print $langs->trans("SetAtLeastOneOptionAsUrlParameter");
1579  print '</div>';
1580 }
1581 
1582 dolibarr_install_syslog("--- repair: end");
1583 pFooter(1, $setuplang);
1584 
1585 if ($db->connected) {
1586  $db->close();
1587 }
1588 
1589 // Return code if ran from command line
1590 if (!$ok && isset($argv[1])) {
1591  exit(1);
1592 }
Societe
Class to manage third parties objects (customers, suppliers, prospects...)
Definition: societe.class.php:51
dol_escape_htmltag
dol_escape_htmltag($stringtoescape, $keepb=0, $keepn=0, $noescapetags='', $escapeonlyhtmltags=0, $cleanalsojavascript=0)
Returns text escaped for inclusion in HTML alt or title or value tags, or into values of HTML input f...
Definition: functions.lib.php:1600
ChargeSociales
Classe permettant la gestion des paiements des charges La tva collectee n'est calculee que sur les fa...
Definition: chargesociales.class.php:34
GETPOST
GETPOST($paramname, $check='alphanohtml', $method=0, $filter=null, $options=null, $noreplace=0)
Return value of a param into GET or POST supervariable.
Definition: functions.lib.php:609
FactureFournisseur
Class to manage suppliers invoices.
Definition: fournisseur.facture.class.php:51
dol_print_error
dol_print_error($db='', $error='', $errors=null)
Displays error message system with all the information to facilitate the diagnosis and the escalation...
Definition: functions.lib.php:5107
dol_buildpath
dol_buildpath($path, $type=0, $returnemptyifnotfound=0)
Return path of url or filesystem.
Definition: functions.lib.php:1158
dol_dir_list
dol_dir_list($path, $types="all", $recursive=0, $filter="", $excludefilter=null, $sortcriteria="name", $sortorder=SORT_ASC, $mode=0, $nohook=0, $relativename="", $donotfollowsymlinks=0, $nbsecondsold=0)
Scan a directory and return a list of files/directories.
Definition: files.lib.php:62
image_format_supported
image_format_supported($file, $acceptsvg=0)
Return if a filename is file name of a supported image format.
Definition: images.lib.php:80
Facture
Class to manage invoices.
Definition: facture.class.php:60
getDoliDBInstance
getDoliDBInstance($type, $host, $user, $pass, $name, $port)
Return a DoliDB instance (database handler).
Definition: functions.lib.php:240
dol_copy
dol_copy($srcfile, $destfile, $newmask=0, $overwriteifexists=1, $testvirus=0, $indexdatabase=0)
Copy a file to another file.
Definition: files.lib.php:717
dol_is_file
dol_is_file($pathoffile)
Return if path is a file.
Definition: files.lib.php:483
dol_delete_file
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.
Definition: files.lib.php:1334
clean_data_ecm_directories
clean_data_ecm_directories()
Clean data into ecm_directories table.
Definition: repair.lib.php:130
Exception
dolibarr_install_syslog
dolibarr_install_syslog($message, $level=LOG_DEBUG)
Log function for install pages.
Definition: inc.php:663
Commande
Class to manage customers orders.
Definition: commande.class.php:47
dol_delete_dir
dol_delete_dir($dir, $nophperrors=0)
Remove a directory (not recursive, so content must be empty).
Definition: files.lib.php:1460
pHeader
pHeader($subtitle, $next, $action='set', $param='', $forcejqueryurl='', $csstable='main-inside')
Show HTML header of install pages.
Definition: inc.php:513
pFooter
pFooter($nonext=0, $setuplang='', $jscheckfunction='', $withpleasewait=0, $morehtml='')
Print HTML footer of install pages.
Definition: inc.php:602
$sql
if(isModEnabled('facture') && $user->hasRight('facture', 'lire')) if((isModEnabled('fournisseur') &&empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD) && $user->hasRight("fournisseur", "facture", "lire"))||(isModEnabled('supplier_invoice') && $user->hasRight("supplier_invoice", "lire"))) if(isModEnabled('don') && $user->hasRight('don', 'lire')) if(isModEnabled('tax') &&!empty($user->rights->tax->charges->lire)) if(isModEnabled('facture') &&isModEnabled('commande') && $user->hasRight("commande", "lire") &&empty($conf->global->WORKFLOW_DISABLE_CREATE_INVOICE_FROM_ORDER)) $sql
Social contributions to pay.
Definition: index.php:746
dol_strlen
dol_strlen($string, $stringencoding='UTF-8')
Make a strlen call.
Definition: functions.lib.php:3997
run_sql
run_sql($sqlfile, $silent=1, $entity=0, $usesavepoint=1, $handler='', $okerror='default', $linelengthlimit=32768, $nocommentremoval=0, $offsetforchartofaccount=0, $colspan=0, $onlysqltoimportwebsite=0, $database='')
Launch a sql file.
Definition: admin.lib.php:169
Contrat
Class to manage contracts.
Definition: contrat.class.php:43
CommandeFournisseur
Class to manage predefined suppliers products.
Definition: fournisseur.commande.class.php:48
ExtraFields
Class to manage standard extra fields.
Definition: extrafields.class.php:39
Propal
Class to manage proposals.
Definition: propal.class.php:52
dol_mkdir
dol_mkdir($dir, $dataroot='', $newmask='')
Creation of a directory (this can create recursive subdir)
Definition: functions.lib.php:6936
vignette
vignette($file, $maxWidth=160, $maxHeight=120, $extName='_small', $quality=50, $outdir='thumbs', $targetformat=0)
Create a thumbnail from an image file (Supported extensions are gif, jpg, png and bmp).
Definition: images.lib.php:509
float
div float
Buy price without taxes.
Definition: style.css.php:921
if
if(!defined( 'CSRFCHECK_WITH_TOKEN'))
Definition: journals_list.php:25
dol_decode
dol_decode($chain, $key='1')
Decode a base 64 encoded + specific delta change.
Definition: security.lib.php:69