dolibarr  19.0.0-dev
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 }
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
Classe permettant la gestion des paiements des charges La tva collectee n'est calculee que sur les fa...
Class to manage predefined suppliers products.
Class to manage customers orders.
Class to manage contracts.
Class to manage standard extra fields.
Class to manage suppliers invoices.
Class to manage invoices.
Class to manage proposals.
Class to manage third parties objects (customers, suppliers, prospects...)
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_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
dol_delete_dir($dir, $nophperrors=0)
Remove a directory (not recursive, so content must be empty).
Definition: files.lib.php:1460
dol_is_file($pathoffile)
Return if path is a file.
Definition: files.lib.php:483
dol_copy($srcfile, $destfile, $newmask=0, $overwriteifexists=1, $testvirus=0, $indexdatabase=0)
Copy a file to another file.
Definition: files.lib.php:717
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
dol_print_error($db='', $error='', $errors=null)
Displays error message system with all the information to facilitate the diagnosis and the escalation...
dol_strlen($string, $stringencoding='UTF-8')
Make a strlen call.
GETPOST($paramname, $check='alphanohtml', $method=0, $filter=null, $options=null, $noreplace=0)
Return value of a param into GET or POST supervariable.
dol_buildpath($path, $type=0, $returnemptyifnotfound=0)
Return path of url or filesystem.
dol_mkdir($dir, $dataroot='', $newmask='')
Creation of a directory (this can create recursive subdir)
getDoliDBInstance($type, $host, $user, $pass, $name, $port)
Return a DoliDB instance (database handler).
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...
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
image_format_supported($file, $acceptsvg=0)
Return if a filename is file name of a supported image format.
Definition: images.lib.php:80
pHeader($subtitle, $next, $action='set', $param='', $forcejqueryurl='', $csstable='main-inside')
Show HTML header of install pages.
Definition: inc.php:513
pFooter($nonext=0, $setuplang='', $jscheckfunction='', $withpleasewait=0, $morehtml='')
Print HTML footer of install pages.
Definition: inc.php:602
dolibarr_install_syslog($message, $level=LOG_DEBUG)
Log function for install pages.
Definition: inc.php:663
if(!defined( 'CSRFCHECK_WITH_TOKEN'))
div float
Buy price without taxes.
Definition: style.css.php:921
clean_data_ecm_directories()
Clean data into ecm_directories table.
Definition: repair.lib.php:130
dol_decode($chain, $key='1')
Decode a base 64 encoded + specific delta change.