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