30include_once
'inc.php';
31if (file_exists($conffile)) {
32 include_once $conffile;
34require_once $dolibarr_main_document_root.
'/core/lib/admin.lib.php';
35include_once $dolibarr_main_document_root.
'/core/lib/images.lib.php';
36require_once $dolibarr_main_document_root.
'/core/class/extrafields.class.php';
37require_once
'lib/repair.lib.php';
45$err = error_reporting();
50$setuplang =
GETPOST(
"selectlang",
'aZ09', 3) ?
GETPOST(
"selectlang",
'aZ09', 3) :
'auto';
51$langs->setDefaultLang($setuplang);
53$langs->loadLangs(array(
"admin",
"install",
"other"));
55if ($dolibarr_main_db_type ==
"mysqli") {
58if ($dolibarr_main_db_type ==
"pgsql") {
61if ($dolibarr_main_db_type ==
"mssql") {
67if (!is_object($conf)) {
76pHeader($langs->trans(
"Repair"),
"upgrade2",
GETPOST(
'action',
'aZ09'));
81print
'<div class="warning" style="padding-top: 10px">';
82print $langs->trans(
"SetAtLeastOneOptionAsUrlParameter");
89print
'Option standard is '.(GETPOST(
'standard',
'alpha') ?
GETPOST(
'standard',
'alpha') :
'undefined').
'<br>'.
"\n";
91print
'Option force_disable_of_modules_not_found is '.(GETPOST(
'force_disable_of_modules_not_found',
'alpha') ?
GETPOST(
'force_disable_of_modules_not_found',
'alpha') :
'undefined').
'<br>'.
"\n";
93print
'Option restore_thirdparties_logos is '.(GETPOST(
'restore_thirdparties_logos',
'alpha') ?
GETPOST(
'restore_thirdparties_logos',
'alpha') :
'undefined').
'<br>'.
"\n";
94print
'Option restore_user_pictures is '.(GETPOST(
'restore_user_pictures',
'alpha') ?
GETPOST(
'restore_user_pictures',
'alpha') :
'undefined').
'<br>'.
"\n";
95print
'Option rebuild_product_thumbs is '.(GETPOST(
'rebuild_product_thumbs',
'alpha') ?
GETPOST(
'rebuild_product_thumbs',
'alpha') :
'undefined').
'<br>'.
"\n";
97print
'Option clean_linked_elements is '.(GETPOST(
'clean_linked_elements',
'alpha') ?
GETPOST(
'clean_linked_elements',
'alpha') :
'undefined').
'<br>'.
"\n";
98print
'Option clean_menus is '.(GETPOST(
'clean_menus',
'alpha') ?
GETPOST(
'clean_menus',
'alpha') :
'undefined').
'<br>'.
"\n";
99print
'Option clean_orphelin_dir is '.(GETPOST(
'clean_orphelin_dir',
'alpha') ?
GETPOST(
'clean_orphelin_dir',
'alpha') :
'undefined').
'<br>'.
"\n";
100print
'Option clean_product_stock_batch is '.(GETPOST(
'clean_product_stock_batch',
'alpha') ?
GETPOST(
'clean_product_stock_batch',
'alpha') :
'undefined').
'<br>'.
"\n";
101print
'Option clean_perm_table is '.(GETPOST(
'clean_perm_table',
'alpha') ?
GETPOST(
'clean_perm_table',
'alpha') :
'undefined').
'<br>'.
"\n";
102print
'Option repair_link_dispatch_lines_supplier_order_lines, is '.(GETPOST(
'repair_link_dispatch_lines_supplier_order_lines',
'alpha') ?
GETPOST(
'repair_link_dispatch_lines_supplier_order_lines',
'alpha') :
'undefined').
'<br>'.
"\n";
104print
'Option set_empty_time_spent_amount is '.(GETPOST(
'set_empty_time_spent_amount',
'alpha') ?
GETPOST(
'set_empty_time_spent_amount',
'alpha') :
'undefined').
'<br>'.
"\n";
106print
'Option force_utf8_on_tables (force utf8 + row=dynamic), for mysql/mariadb only, is '.(GETPOST(
'force_utf8_on_tables',
'alpha') ?
GETPOST(
'force_utf8_on_tables',
'alpha') :
'undefined').
'<br>'.
"\n";
107print
'<span class="valignmiddle">'.
"Option force_utf8mb4_on_tables (force utf8mb4 + row=dynamic, EXPERIMENTAL!), for mysql/mariadb only, is ".(
GETPOST(
'force_utf8mb4_on_tables',
'alpha') ?
GETPOST(
'force_utf8mb4_on_tables',
'alpha') :
'undefined');
109if ($dolibarr_main_db_character_set !=
'utf8mb4') {
110 print
'<img src="../theme/eldy/img/warning.png" class="pictofortooltip valignmiddle" title="If you switch to utf8mb4, you must also check the value for $dolibarr_main_db_character_set and $dolibarr_main_db_collation into conf/conf.php file.">';
113print
"Option force_collation_from_conf_on_tables (force ".$conf->db->character_set.
"/".$conf->db->dolibarr_main_db_collation.
" + row=dynamic), for mysql/mariadb only is ".(
GETPOST(
'force_collation_from_conf_on_tables',
'alpha') ?
GETPOST(
'force_collation_from_conf_on_tables',
'alpha') :
'undefined').
"<br>\n";
116print
'Option rebuild_sequences, for postgresql only, is '.(GETPOST(
'rebuild_sequences',
'alpha') ?
GETPOST(
'rebuild_sequences',
'alpha') :
'undefined').
'<br>'.
"\n";
121print
'<table cellspacing="0" cellpadding="1" class="centpercent">';
125if (preg_match(
'/crypted:/i', $dolibarr_main_db_pass) || !empty($dolibarr_main_db_encrypted_pass)) {
126 require_once $dolibarr_main_document_root.
'/core/lib/security.lib.php';
127 if (preg_match(
'/crypted:/i', $dolibarr_main_db_pass)) {
128 $dolibarr_main_db_pass = preg_replace(
'/crypted:/i',
'', $dolibarr_main_db_pass);
129 $dolibarr_main_db_pass =
dol_decode($dolibarr_main_db_pass);
130 $dolibarr_main_db_encrypted_pass = $dolibarr_main_db_pass;
132 $dolibarr_main_db_pass =
dol_decode($dolibarr_main_db_encrypted_pass);
137$conf->db->type = $dolibarr_main_db_type;
138$conf->db->host = $dolibarr_main_db_host;
139$conf->db->port = $dolibarr_main_db_port;
140$conf->db->name = $dolibarr_main_db_name;
141$conf->db->user = $dolibarr_main_db_user;
142$conf->db->pass = $dolibarr_main_db_pass;
145$conf->db->dolibarr_main_db_encryption = isset($dolibarr_main_db_encryption) ? $dolibarr_main_db_encryption : 0;
146$conf->db->dolibarr_main_db_cryptkey = isset($dolibarr_main_db_cryptkey) ? $dolibarr_main_db_cryptkey :
'';
148$db =
getDoliDBInstance($conf->db->type, $conf->db->host, $conf->db->user, $conf->db->pass, $conf->db->name, (
int) $conf->db->port);
151 print
'<tr><td class="nowrap">';
152 print $langs->trans(
"ServerConnection").
" : $dolibarr_main_db_host</td><td class=\"right\">".$langs->trans(
"OK").
"</td></tr>";
153 dolibarr_install_syslog(
"repair: ".$langs->transnoentities(
"ServerConnection").
": ".$dolibarr_main_db_host.$langs->transnoentities(
"OK"));
156 print
"<tr><td>".$langs->trans(
"ErrorFailedToConnectToDatabase", $dolibarr_main_db_name).
"</td><td class=\"right\">".$langs->transnoentities(
"Error").
"</td></tr>";
157 dolibarr_install_syslog(
"repair: ".$langs->transnoentities(
"ErrorFailedToConnectToDatabase", $dolibarr_main_db_name));
162 if ($db->database_selected) {
163 print
'<tr><td class="nowrap">';
164 print $langs->trans(
"DatabaseConnection").
" : ".$dolibarr_main_db_name.
"</td><td class=\"right\">".$langs->trans(
"OK").
"</td></tr>";
168 print
"<tr><td>".$langs->trans(
"ErrorFailedToConnectToDatabase", $dolibarr_main_db_name).
"</td><td class=\"right\">".$langs->trans(
"Error").
"</td></tr>";
169 dolibarr_install_syslog(
"repair: ".$langs->transnoentities(
"ErrorFailedToConnectToDatabase", $dolibarr_main_db_name));
176 $version = $db->getVersion();
177 $versionarray = $db->getVersionArray();
178 print
'<tr><td>'.$langs->trans(
"ServerVersion").
'</td>';
179 print
'<td class="right">'.$version.
'</td></tr>';
184$conf->setValues($db);
186if (defined(
'SYSLOG_FILE')) {
187 $conf->global->SYSLOG_FILE = constant(
'SYSLOG_FILE');
189$conf->global->MAIN_ENABLE_LOG_TO_HTML = 1;
194$oneoptionset = (
GETPOST(
'standard',
'alpha') ||
GETPOST(
'restore_thirdparties_logos',
'alpha') ||
GETPOST(
'clean_linked_elements',
'alpha') ||
GETPOST(
'clean_menus',
'alpha')
195 ||
GETPOST(
'clean_orphelin_dir',
'alpha') ||
GETPOST(
'clean_product_stock_batch',
'alpha') ||
GETPOST(
'set_empty_time_spent_amount',
'alpha') ||
GETPOST(
'rebuild_product_thumbs',
'alpha')
196 ||
GETPOST(
'clean_perm_table',
'alpha')
197 ||
GETPOST(
'force_disable_of_modules_not_found',
'alpha')
198 ||
GETPOST(
'force_utf8_on_tables',
'alpha') ||
GETPOST(
'force_utf8mb4_on_tables',
'alpha') ||
GETPOST(
'force_collation_from_conf_on_tables',
'alpha')
199 ||
GETPOST(
'rebuild_sequences',
'alpha') ||
GETPOST(
'recalculateinvoicetotal',
'alpha'));
201if ($ok && $oneoptionset) {
203 print
'<tr><td colspan="2">'.$langs->trans(
"PleaseBePatient").
'<br><br></td></tr>';
209if ($ok &&
GETPOST(
'standard',
'alpha')) {
210 $dir =
"mysql/migration/";
217 $filesindir = array();
218 $handle = opendir($dir);
219 if (is_resource($handle)) {
220 while (($file = readdir($handle)) !==
false) {
221 if (preg_match(
'/\.sql$/i', $file)) {
222 $filesindir[] = $file;
228 foreach ($filesindir as $file) {
229 if (preg_match(
'/repair/i', $file)) {
235 foreach ($filelist as $file) {
236 print
'<tr><td class="nowrap">*** ';
237 print $langs->trans(
"Script").
'</td><td class="right">'.$file.
'</td></tr>';
239 $name = substr($file, 0,
dol_strlen($file) - 4);
242 $ok =
run_sql($dir.$file, 0,
'', 1);
249if ($ok &&
GETPOST(
'standard',
'alpha')) {
253 $listofmodulesextra = array(
'societe' =>
'societe',
'adherent' =>
'adherent',
'product' =>
'product',
254 'socpeople' =>
'socpeople',
'propal' =>
'propal',
'commande' =>
'commande',
255 'facture' =>
'facture',
'facturedet' =>
'facturedet',
'facture_rec' =>
'facture_rec',
'facturedet_rec' =>
'facturedet_rec',
256 'supplier_proposal' =>
'supplier_proposal',
'commande_fournisseur' =>
'commande_fournisseur',
257 'facture_fourn' =>
'facture_fourn',
'facture_fourn_rec' =>
'facture_fourn_rec',
'facture_fourn_det' =>
'facture_fourn_det',
'facture_fourn_det_rec' =>
'facture_fourn_det_rec',
258 'fichinter' =>
'fichinter',
'fichinterdet' =>
'fichinterdet',
259 'inventory' =>
'inventory',
260 'actioncomm' =>
'actioncomm',
'bom_bom' =>
'bom_bom',
'mrp_mo' =>
'mrp_mo',
261 'adherent_type' =>
'adherent_type',
'user' =>
'user',
'partnership' =>
'partnership',
'projet' =>
'projet',
'projet_task' =>
'projet_task',
'ticket' =>
'ticket');
264 print
'<tr><td colspan="2"><br>*** Check fields into extra table structure match table of definition. If not add column into table</td></tr>';
265 foreach ($listofmodulesextra as $tablename => $elementtype) {
267 $tableextra = MAIN_DB_PREFIX.$tablename.
'_extrafields';
270 $arrayoffieldsdesc = $extrafields->fetch_name_optionals_label($elementtype);
273 $arrayoffieldsfound = array();
274 $resql = $db->DDLDescTable($tableextra);
276 print
'<tr><td>Check availability of extra field for '.$tableextra;
278 while ($obj = $db->fetch_object($resql)) {
279 $fieldname = $fieldtype =
'';
280 if (preg_match(
'/mysql/', $db->type)) {
281 $fieldname = $obj->Field;
282 $fieldtype = $obj->Type;
284 $fieldname = isset($obj->Key) ? $obj->Key : $obj->attname;
285 $fieldtype = isset($obj->Type) ? $obj->Type :
'varchar';
288 if (empty($fieldname)) {
291 if (in_array($fieldname, array(
'rowid',
'tms',
'fk_object',
'import_key'))) {
294 $arrayoffieldsfound[$fieldname] = array(
'type' => $fieldtype);
296 print
' - Found '.count($arrayoffieldsfound).
' fields into table';
297 if (count($arrayoffieldsfound) > 0) {
298 print
' <span class="opacitymedium">('.implode(
', ', array_keys($arrayoffieldsfound)).
')</span>';
303 foreach ($arrayoffieldsdesc as $code => $label) {
304 if (!in_array($code, array_keys($arrayoffieldsfound))) {
305 print
'Found field '.$code.
' declared into '.MAIN_DB_PREFIX.
'extrafields table but not found into desc of table '.$tableextra.
" -> ";
306 $type = $extrafields->attributes[$elementtype][
'type'][$code];
307 $length = $extrafields->attributes[$elementtype][
'size'][$code];
313 if ($type ==
'boolean') {
316 } elseif ($type ==
'price') {
319 } elseif ($type ==
'phone') {
322 } elseif ($type ==
'mail') {
325 } elseif (($type ==
'select') || ($type ==
'sellist') || ($type ==
'radio') || ($type ==
'checkbox') || ($type ==
'chkbxlst')) {
328 } elseif ($type ==
'link') {
338 'value' => $lengthdb,
339 'attribute' => $attribute,
340 'default' => $default,
347 if (
GETPOST(
'standard',
'alpha') ==
'confirmed') {
348 $result = $db->DDLAddField($tableextra, $code, $field_desc,
"");
351 print
"KO ".$db->lasterror.
"<br>\n";
356 print
' - Mode test, no column added.';
361 print
"</td><td> </td></tr>\n";
363 print
'<tr><td>Table '.$tableextra.
' is not found</td><td></td></tr>'.
"\n";
370if ($ok &&
GETPOST(
'standard',
'alpha')) {
376if ($ok &&
GETPOST(
'standard',
'alpha')) {
377 print
'<tr><td colspan="2"><br>*** Clean constant record of modules not enabled</td></tr>';
379 $sql =
"SELECT name, entity, value";
380 $sql .=
" FROM ".MAIN_DB_PREFIX.
"const as c";
381 $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'";
382 $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'";
383 $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_%'";
384 $sql .=
" OR name LIKE 'MAIN_MODULE_%_MODULEFOREXTERNAL'";
385 $sql .=
" ORDER BY name, entity";
387 $resql = $db->query($sql);
389 $num = $db->num_rows($resql);
396 $obj = $db->fetch_object($resql);
399 if (preg_match(
'/MAIN_MODULE_([^_]+)_(.+)/i', $obj->name, $reg)) {
403 $sql2 =
"SELECT COUNT(*) as nb";
404 $sql2 .=
" FROM ".MAIN_DB_PREFIX.
"const as c";
405 $sql2 .=
" WHERE name = 'MAIN_MODULE_".$name.
"'";
406 $sql2 .=
" AND entity = ".((int) $obj->entity);
407 $resql2 = $db->query($sql2);
409 $obj2 = $db->fetch_object($resql2);
410 if ($obj2 && $obj2->nb == 0) {
412 $sqldelete =
"DELETE FROM ".MAIN_DB_PREFIX.
"const WHERE name = '".$db->escape($obj->name).
"' AND entity = ".((int) $obj->entity);
414 if (
GETPOST(
'standard',
'alpha') ==
'confirmed') {
415 $db->query($sqldelete);
417 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>';
419 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>';
439if ($ok &&
GETPOST(
'standard',
'alpha')) {
440 print
'<tr><td colspan="2"><br>*** Clean definition of boxes of modules not enabled</td></tr>';
442 $sql =
"SELECT file, entity FROM ".MAIN_DB_PREFIX.
"boxes_def";
443 $sql .=
" WHERE file like '%@%'";
445 $resql = $db->query($sql);
447 $num = $db->num_rows($resql);
454 $obj = $db->fetch_object($resql);
457 if (preg_match(
'/^(.+)@(.+)$/i', $obj->file, $reg)) {
461 $sql2 =
"SELECT COUNT(*) as nb";
462 $sql2 .=
" FROM ".MAIN_DB_PREFIX.
"const as c";
463 $sql2 .=
" WHERE name = 'MAIN_MODULE_".strtoupper($module).
"'";
464 $sql2 .=
" AND entity = ".((int) $obj->entity);
465 $sql2 .=
" AND value <> 0";
466 $resql2 = $db->query($sql2);
468 $obj2 = $db->fetch_object($resql2);
469 if ($obj2 && $obj2->nb == 0) {
471 $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).
")";
472 $sqldeleteb =
"DELETE FROM ".MAIN_DB_PREFIX.
"boxes_def WHERE file = '".$db->escape($obj->file).
"' AND entity = ".((int) $obj->entity);
474 if (
GETPOST(
'standard',
'alpha') ==
'confirmed') {
475 $db->query($sqldeletea);
476 $db->query($sqldeleteb);
478 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>';
480 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>';
498if ($ok &&
GETPOST(
'restore_thirdparties_logos')) {
503 print
'<tr><td colspan="2"><br>*** Restore thirdparties logo<br>';
505 $sql =
"SELECT s.rowid, s.nom as name, s.logo FROM ".MAIN_DB_PREFIX.
"societe as s ORDER BY s.nom";
506 $resql = $db->query($sql);
508 $num = $db->num_rows($resql);
512 $obj = $db->fetch_object($resql);
520 $tmp = explode(
'.', $obj->logo);
522 if (isset($tmp[1])) {
527 $filetotest = $dolibarr_main_data_root.
'/societe/logos/'.$name.$ext;
528 $filetotestsmall = $dolibarr_main_data_root.
'/societe/logos/thumbs/'.$name.
'_small'.$ext;
530 print
'Check thirdparty '.$obj->rowid.
' name='.$obj->name.
' logo='.$obj->logo.
' file '.$filetotest.
" exists=".$exists.
"<br>\n";
532 $filetarget = $dolibarr_main_data_root.
'/societe/'.$obj->rowid.
'/logos/'.$name.$ext;
533 $filetargetsmall = $dolibarr_main_data_root.
'/societe/'.$obj->rowid.
'/logos/thumbs/'.$name.
'_small'.$ext;
536 if (
GETPOST(
'restore_thirdparties_logos',
'alpha') ==
'confirmed') {
537 dol_mkdir($dolibarr_main_data_root.
'/societe/'.$obj->rowid.
'/logos');
540 print
" -> Copy file ".$filetotest.
" -> ".$filetarget.
"<br>\n";
541 if (
GETPOST(
'restore_thirdparties_logos',
'alpha') ==
'confirmed') {
542 dol_copy($filetotest, $filetarget,
'', 0);
548 if (
GETPOST(
'restore_thirdparties_logos',
'alpha') ==
'confirmed') {
549 dol_mkdir($dolibarr_main_data_root.
'/societe/'.$obj->rowid.
'/logos/thumbs');
551 print
" -> Copy file ".$filetotestsmall.
" -> ".$filetargetsmall.
"<br>\n";
552 if (
GETPOST(
'restore_thirdparties_logos',
'alpha') ==
'confirmed') {
553 dol_copy($filetotestsmall, $filetargetsmall,
'', 0);
572if ($ok &&
GETPOST(
'restore_user_pictures',
'alpha')) {
577 print
'<tr><td colspan="2"><br>*** Restore user pictures<br>';
579 $sql =
"SELECT s.rowid, s.firstname, s.lastname, s.login, s.photo FROM ".MAIN_DB_PREFIX.
"user as s ORDER BY s.rowid";
580 $resql = $db->query($sql);
582 $num = $db->num_rows($resql);
586 $obj = $db->fetch_object($resql);
594 $tmp = explode(
'.', $obj->photo);
596 if (isset($tmp[1])) {
601 $filetotest = $dolibarr_main_data_root.
'/users/'.substr(sprintf(
'%08d', $obj->rowid), -1, 1).
'/'.substr(sprintf(
'%08d', $obj->rowid), -2, 1).
'/'.$name.$ext;
602 $filetotestsmall = $dolibarr_main_data_root.
'/users/'.substr(sprintf(
'%08d', $obj->rowid), -1, 1).
'/'.substr(sprintf(
'%08d', $obj->rowid), -2, 1).
'/thumbs/'.$name.
'_small'.$ext;
603 $filetotestmini = $dolibarr_main_data_root.
'/users/'.substr(sprintf(
'%08d', $obj->rowid), -1, 1).
'/'.substr(sprintf(
'%08d', $obj->rowid), -2, 1).
'/thumbs/'.$name.
'_mini'.$ext;
605 print
'Check user '.$obj->rowid.
' lastname='.$obj->lastname.
' firstname='.$obj->firstname.
' photo='.$obj->photo.
' file '.$filetotest.
" exists=".$exists.
"<br>\n";
607 $filetarget = $dolibarr_main_data_root.
'/users/'.$obj->rowid.
'/'.$name.$ext;
608 $filetargetsmall = $dolibarr_main_data_root.
'/users/'.$obj->rowid.
'/thumbs/'.$name.
'_small'.$ext;
609 $filetargetmini = $dolibarr_main_data_root.
'/users/'.$obj->rowid.
'/thumbs/'.$name.
'_mini'.$ext;
613 if (
GETPOST(
'restore_user_pictures',
'alpha') ==
'confirmed') {
614 dol_mkdir($dolibarr_main_data_root.
'/users/'.$obj->rowid);
617 print
" -> Copy file ".$filetotest.
" -> ".$filetarget.
"<br>\n";
618 if (
GETPOST(
'restore_user_pictures',
'alpha') ==
'confirmed') {
619 dol_copy($filetotest, $filetarget,
'', 0);
625 if (
GETPOST(
'restore_user_pictures',
'alpha') ==
'confirmed') {
626 dol_mkdir($dolibarr_main_data_root.
'/users/'.$obj->rowid.
'/thumbs');
629 print
" -> Copy file ".$filetotestsmall.
" -> ".$filetargetsmall.
"<br>\n";
630 if (
GETPOST(
'restore_user_pictures',
'alpha') ==
'confirmed') {
631 dol_copy($filetotestsmall, $filetargetsmall,
'', 0);
637 if (
GETPOST(
'restore_user_pictures',
'alpha') ==
'confirmed') {
638 dol_mkdir($dolibarr_main_data_root.
'/users/'.$obj->rowid.
'/thumbs');
641 print
" -> Copy file ".$filetotestmini.
" -> ".$filetargetmini.
"<br>\n";
642 if (
GETPOST(
'restore_user_pictures',
'alpha') ==
'confirmed') {
643 dol_copy($filetotestmini, $filetargetmini,
'', 0);
661if ($ok &&
GETPOST(
'rebuild_product_thumbs',
'alpha')) {
663 global $maxwidthsmall, $maxheightsmall, $maxwidthmini, $maxheightmini;
665 print
'<tr><td colspan="2"><br>*** Rebuild product thumbs<br>';
667 $sql =
"SELECT s.rowid, s.ref FROM ".MAIN_DB_PREFIX.
"product as s ORDER BY s.ref";
668 $resql = $db->query($sql);
670 $num = $db->num_rows($resql);
674 $obj = $db->fetch_object($resql);
676 if (!empty($obj->ref)) {
677 $files =
dol_dir_list($dolibarr_main_data_root.
'/produit/'.$obj->ref,
'files', 0);
678 foreach ($files as $file) {
681 $imgThumbSmall =
'notbuild';
682 if (
GETPOST(
'rebuild_product_thumbs',
'alpha') ==
'confirmed') {
684 $imgThumbSmall =
vignette($file[
'fullname'], $maxwidthsmall, $maxheightsmall,
'_small', 50,
"thumbs");
686 print
'Check product '.$obj->rowid.
", file ".$file[
'fullname'].
" -> ".$imgThumbSmall.
" maxwidthsmall=".$maxwidthsmall.
" maxheightsmall=".$maxheightsmall.
"<br>\n";
687 $imgThumbMini =
'notbuild';
688 if (
GETPOST(
'rebuild_product_thumbs',
'alpha') ==
'confirmed') {
691 $imgThumbMini =
vignette($file[
'fullname'], $maxwidthmini, $maxheightmini,
'_mini', 50,
"thumbs");
693 print
'Check product '.$obj->rowid.
", file ".$file[
'fullname'].
" -> ".$imgThumbMini.
" maxwidthmini=".$maxwidthmini.
" maxheightmini=".$maxheightmini.
"<br>\n";
709if ($ok &&
GETPOST(
'clean_linked_elements',
'alpha')) {
710 print
'<tr><td colspan="2"><br>*** Check table of linked elements and delete orphelins links</td></tr>';
712 print
'<tr><td colspan="2">'.checkLinkedElements(
'propal',
'commande').
"</td></tr>\n";
715 print
'<tr><td colspan="2">'.checkLinkedElements(
'propal',
'facture').
"</td></tr>\n";
718 print
'<tr><td colspan="2">'.checkLinkedElements(
'commande',
'facture').
"</td></tr>\n";
721 print
'<tr><td colspan="2">'.checkLinkedElements(
'commande',
'shipping').
"</td></tr>\n";
724 print
'<tr><td colspan="2">'.checkLinkedElements(
'shipping',
'delivery').
"</td></tr>\n";
727 print
'<tr><td colspan="2">'.checkLinkedElements(
'order_supplier',
'invoice_supplier').
"</td></tr>\n";
732if ($ok &&
GETPOST(
'clean_menus',
'alpha')) {
733 print
'<tr><td colspan="2"><br>*** Clean menu entries coming from disabled modules</td></tr>';
735 $sql =
"SELECT rowid, module";
736 $sql .=
" FROM ".MAIN_DB_PREFIX.
"menu as c";
737 $sql .=
" WHERE module IS NOT NULL AND module <> ''";
738 $sql .=
" ORDER BY module";
740 $resql = $db->query($sql);
742 $num = $db->num_rows($resql);
746 $obj = $db->fetch_object($resql);
748 $modulecond = $obj->module;
749 $modulecondarray = explode(
'|', $obj->module);
758 foreach ($modulecondarray as $tmpname) {
759 if ($tmpname ==
'margins') {
764 if (!empty($conf->$tmpname)) {
765 $result = $conf->$tmpname->enabled;
772 if (!$moduleok && $modulecond) {
773 print
' - Module condition '.$modulecond.
' seems ko, we delete menu entry.';
774 if (
GETPOST(
'clean_menus') ==
'confirmed') {
775 $sql2 =
"DELETE FROM ".MAIN_DB_PREFIX.
"menu WHERE module = '".$db->escape($modulecond).
"'";
776 $resql2 = $db->query($sql2);
781 print
' - <span class="warning">Cleaned</span>';
784 print
' - <span class="warning">Canceled (test mode)</span>';
787 print
' - Module condition '.$modulecond.
' is ok, we do nothing.';
806 print
'<tr><td>No menu entries of disabled menus found</td></tr>';
816if ($ok &&
GETPOST(
'clean_orphelin_dir',
'alpha')) {
817 $listmodulepart = array(
'company',
'invoice',
'invoice_supplier',
'propal',
'order',
'order_supplier',
'contract',
'tax');
818 foreach ($listmodulepart as $modulepart) {
819 $filearray = array();
820 $upload_dir = isset($conf->$modulepart->dir_output) ? $conf->$modulepart->dir_output :
'';
821 if ($modulepart ==
'company') {
822 $upload_dir = $conf->societe->dir_output;
824 if ($modulepart ==
'invoice') {
825 $upload_dir = $conf->facture->dir_output;
827 if ($modulepart ==
'invoice_supplier') {
828 $upload_dir = $conf->fournisseur->facture->dir_output;
830 if ($modulepart ==
'order') {
831 $upload_dir = $conf->commande->dir_output;
833 if ($modulepart ==
'order_supplier') {
834 $upload_dir = $conf->fournisseur->commande->dir_output;
836 if ($modulepart ==
'contract') {
837 $upload_dir = $conf->contrat->dir_output;
840 if (empty($upload_dir)) {
844 print
'<tr><td colspan="2"><br>*** Clean orphelins files into files '.$upload_dir.
'</td></tr>';
846 $filearray =
dol_dir_list($upload_dir,
"files", 1,
'', array(
'^SPECIMEN\.pdf$',
'^\.',
'(\.meta|_preview.*\.png)$',
'^temp$',
'^payments$',
'^CVS$',
'^thumbs$'),
'', SORT_DESC, 1,
true);
849 if ($modulepart ==
'company') {
850 include_once DOL_DOCUMENT_ROOT.
'/societe/class/societe.class.php';
851 $object_instance =
new Societe($db);
853 if ($modulepart ==
'invoice') {
854 include_once DOL_DOCUMENT_ROOT.
'/compta/facture/class/facture.class.php';
855 $object_instance =
new Facture($db);
856 } elseif ($modulepart ==
'invoice_supplier') {
857 include_once DOL_DOCUMENT_ROOT.
'/fourn/class/fournisseur.facture.class.php';
859 } elseif ($modulepart ==
'propal') {
860 include_once DOL_DOCUMENT_ROOT.
'/comm/propal/class/propal.class.php';
861 $object_instance =
new Propal($db);
862 } elseif ($modulepart ==
'order') {
863 include_once DOL_DOCUMENT_ROOT.
'/commande/class/commande.class.php';
864 $object_instance =
new Commande($db);
865 } elseif ($modulepart ==
'order_supplier') {
866 include_once DOL_DOCUMENT_ROOT.
'/fourn/class/fournisseur.commande.class.php';
868 } elseif ($modulepart ==
'contract') {
869 include_once DOL_DOCUMENT_ROOT.
'/contrat/class/contrat.class.php';
870 $object_instance =
new Contrat($db);
871 } elseif ($modulepart ==
'tax') {
872 include_once DOL_DOCUMENT_ROOT.
'/compta/sociales/class/chargesociales.class.php';
876 foreach ($filearray as $key => $file) {
877 if (!is_dir($file[
'name'])
878 && $file[
'name'] !=
'.'
879 && $file[
'name'] !=
'..'
880 && $file[
'name'] !=
'CVS'
883 $relativefile = preg_replace(
'/'.preg_quote($upload_dir.
'/',
'/').
'/',
'', $file[
'fullname']);
888 $object_instance->id = 0;
889 $object_instance->ref =
'';
893 if ($modulepart ==
'invoice') {
894 preg_match(
'/(.*)\/[^\/]+$/', $relativefile, $reg);
897 if ($modulepart ==
'invoice_supplier') {
898 preg_match(
'/(\d+)\/[^\/]+$/', $relativefile, $reg);
899 $id = empty($reg[1]) ?
'' : $reg[1];
901 if ($modulepart ==
'propal') {
902 preg_match(
'/(.*)\/[^\/]+$/', $relativefile, $reg);
905 if ($modulepart ==
'order') {
906 preg_match(
'/(.*)\/[^\/]+$/', $relativefile, $reg);
909 if ($modulepart ==
'order_supplier') {
910 preg_match(
'/(.*)\/[^\/]+$/', $relativefile, $reg);
913 if ($modulepart ==
'contract') {
914 preg_match(
'/(.*)\/[^\/]+$/', $relativefile, $reg);
917 if ($modulepart ==
'tax') {
918 preg_match(
'/(\d+)\/[^\/]+$/', $relativefile, $reg);
924 $result = $object_instance->fetch($id, $ref);
928 print
'<tr><td colspan="2">';
929 print
'Delete orphelins file '.$file[
'fullname'].
'<br>';
930 if (
GETPOST(
'clean_orphelin_dir',
'alpha') ==
'confirmed') {
935 } elseif ($result < 0) {
936 print
'Error in '.get_class($object_instance).
'.fetch of id'.$id.
' ref='.$ref.
', result='.$result.
'<br>';
945if ($ok &&
GETPOST(
'clean_product_stock_batch',
'alpha')) {
946 $methodtofix =
GETPOST(
'methodtofix',
'alpha') ?
GETPOST(
'methodtofix',
'alpha') :
'updatestock';
948 print
'<tr><td colspan="2"><br>*** Clean table product_batch, methodtofix='.$methodtofix.
' (possible values: updatestock or updatebatch)</td></tr>';
950 $sql =
"SELECT p.rowid, p.ref, p.tobatch, ps.rowid as psrowid, ps.fk_entrepot, ps.reel, SUM(pb.qty) as reelbatch";
951 $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";
952 $sql .=
" WHERE p.rowid = ps.fk_product";
953 $sql .=
" GROUP BY p.rowid, p.ref, p.tobatch, ps.rowid, ps.fk_entrepot, ps.reel";
954 $sql .=
" HAVING (SUM(pb.qty) IS NOT NULL AND reel != SUM(pb.qty)) OR (SUM(pb.qty) IS NULL AND p.tobatch > 0)";
956 $resql = $db->query($sql);
958 $num = $db->num_rows($resql);
963 $obj = $db->fetch_object($resql);
964 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)';
967 if ($obj->reel != $obj->reelbatch) {
968 if (empty($obj->tobatch)) {
970 print
' -> Delete qty '.$obj->reelbatch.
' for any lot linked to fk_product_stock='.$obj->psrowid;
971 $sql2 =
"DELETE FROM ".MAIN_DB_PREFIX.
"product_batch";
972 $sql2 .=
" WHERE fk_product_stock = ".((int) $obj->psrowid);
975 if (
GETPOST(
'clean_product_stock_batch') ==
'confirmed') {
976 $resql2 = $db->query($sql2);
983 if ($methodtofix ==
'updatebatch') {
985 print
' -> Insert qty '.($obj->reel - $obj->reelbatch).
' with lot 000000 linked to fk_product_stock='.$obj->psrowid;
986 $sql2 =
"INSERT INTO ".MAIN_DB_PREFIX.
"product_batch(fk_product_stock, batch, qty)";
987 $sql2 .=
"VALUES(".((int) $obj->psrowid).
", '000000', ".((float) ($obj->reel - $obj->reelbatch)).
")";
990 if (
GETPOST(
'clean_product_stock_batch') ==
'confirmed') {
991 $resql2 = $db->query($sql2);
1000 if ($methodtofix ==
'updatestock') {
1002 print
' -> Update qty of product_stock with qty = '.($obj->reelbatch ? ((float) $obj->reelbatch) :
'0').
' for ps.rowid = '.((
int) $obj->psrowid);
1003 $sql2 =
"UPDATE ".MAIN_DB_PREFIX.
"product_stock";
1004 $sql2 .=
" SET reel = ".($obj->reelbatch ? ((float) $obj->reelbatch) :
'0').
" WHERE rowid = ".((
int) $obj->psrowid);
1007 if (
GETPOST(
'clean_product_stock_batch') ==
'confirmed') {
1012 $resql2 = $db->query($sql2);
1015 $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)';
1016 $resql3 = $db->query($sql3);
1041 print
'<tr><td colspan="2">Nothing to do</td></tr>';
1050if ($ok &&
GETPOST(
'clean_product_stock_negative_if_batch',
'alpha')) {
1051 print
'<tr><td colspan="2"><br>Clean table product_batch, methodtofix='.$methodtofix.
' (possible values: updatestock or updatebatch)</td></tr>';
1053 $sql =
"SELECT p.rowid, p.ref, p.tobatch, ps.rowid as psrowid, ps.fk_entrepot, ps.reel, SUM(pb.qty) as reelbatch";
1054 $sql .=
" FROM ".MAIN_DB_PREFIX.
"product as p, ".MAIN_DB_PREFIX.
"product_stock as ps, ".MAIN_DB_PREFIX.
"product_batch as pb";
1055 $sql .=
" WHERE p.rowid = ps.fk_product AND ps.rowid = pb.fk_product_stock";
1056 $sql .=
" AND p.tobatch > 0";
1057 $sql .=
" GROUP BY p.rowid, p.ref, p.tobatch, ps.rowid, ps.fk_entrepot, ps.reel";
1058 $sql .=
" HAVING reel != SUM(pb.qty)";
1059 $resql = $db->query($sql);
1061 $num = $db->num_rows($resql);
1066 $obj = $db->fetch_object($resql);
1067 print
'<tr><td>'.$obj->rowid.
'-'.$obj->ref.
'-'.$obj->fk_entrepot.
' -> '.$obj->psrowid.
': '.$obj->reel.
' != '.$obj->reelbatch;
1076if ($ok &&
GETPOST(
'set_empty_time_spent_amount',
'alpha')) {
1077 print
'<tr><td colspan="2"><br>*** Set value of time spent without amount</td></tr>';
1079 $sql =
"SELECT COUNT(ptt.rowid) as nb, u.rowid as user_id, u.login, u.thm as user_thm";
1080 $sql .=
" FROM ".MAIN_DB_PREFIX.
"element_time as ptt, ".MAIN_DB_PREFIX.
"user as u";
1081 $sql .=
" WHERE ptt.fk_user = u.rowid";
1082 $sql .=
" AND ptt.thm IS NULL and u.thm > 0";
1083 $sql .=
" GROUP BY u.rowid, u.login, u.thm";
1085 $resql = $db->query($sql);
1087 $num = $db->num_rows($resql);
1092 $obj = $db->fetch_object($resql);
1093 print
'<tr><td>'.$obj->login.
'-'.$obj->user_id.
' ('.$obj->nb.
' lines to fix) -> '.$obj->user_thm;
1097 if (
GETPOST(
'set_empty_time_spent_amount') ==
'confirmed') {
1098 $sql2 =
"UPDATE ".MAIN_DB_PREFIX.
"element_time";
1099 $sql2 .=
" SET thm = ".$obj->user_thm.
" WHERE thm IS NULL AND fk_user = ".((int) $obj->user_id);
1100 $resql2 = $db->query($sql2);
1122 print
'<tr><td>No time spent with empty line on users with a hourly rate defined</td></tr>';
1131if ($ok &&
GETPOST(
'force_disable_of_modules_not_found',
'alpha')) {
1132 print
'<tr><td colspan="2"><br>*** Force modules not found physically to be disabled (only modules adding js, css or hooks can be detected as removed physically)</td></tr>';
1134 $arraylistofkey = array(
'hooks',
'js',
'css');
1136 foreach ($arraylistofkey as $key) {
1137 $sql =
"SELECT DISTINCT name, value";
1138 $sql .=
" FROM ".MAIN_DB_PREFIX.
"const as c";
1139 $sql .=
" WHERE name LIKE 'MAIN_MODULE_%_".strtoupper($key).
"'";
1140 $sql .=
" ORDER BY name";
1142 $resql = $db->query($sql);
1144 $num = $db->num_rows($resql);
1148 $obj = $db->fetch_object($resql);
1149 $constantname = $obj->name;
1157 if (preg_match(
'/MAIN_MODULE_(.*)_'.strtoupper($key).
'/i', $constantname, $reg)) {
1158 $name = strtolower($reg[1]);
1164 if ($key ==
'hooks') {
1165 $reloffile = $name.
'/class/actions_'.$name.
'.class.php';
1168 $value = $obj->value;
1169 $valuearray = (array) json_decode($value);
1170 $reloffile = $valuearray[0];
1171 $reloffile = preg_replace(
'/^\//',
'', $valuearray[0]);
1173 if ($key ==
'css') {
1174 $value = $obj->value;
1175 $valuearray = (array) json_decode($value);
1176 if ($value && (!is_array($valuearray) || count($valuearray) == 0)) {
1177 $valuearray = array();
1178 $valuearray[0] = $value;
1180 $reloffile = preg_replace(
'/^\//',
'', $valuearray[0]);
1195 print
' - File of '.$key.
' ('.$reloffile.
') NOT found, we disable the module.';
1196 if (
GETPOST(
'force_disable_of_modules_not_found') ==
'confirmed') {
1197 $sql2 =
"DELETE FROM ".MAIN_DB_PREFIX.
"const WHERE name = 'MAIN_MODULE_".strtoupper($name).
"_".strtoupper($key).
"'";
1198 $resql2 = $db->query($sql2);
1203 $sql3 =
"DELETE FROM ".MAIN_DB_PREFIX.
"const WHERE name = 'MAIN_MODULE_".strtoupper($name).
"'";
1204 $resql3 = $db->query($sql3);
1209 print
' - <span class="warning">Cleaned</span>';
1212 print
' - <span class="warning">Canceled (test mode)</span>';
1215 print
' - File of '.$key.
' ('.$reloffile.
') found, we do nothing.';
1235 print
'<tr><td>No active module with missing files found by searching on MAIN_MODULE_(.*)_'.strtoupper($key).
'</td></tr>';
1245if ($ok &&
GETPOST(
'clean_perm_table',
'alpha')) {
1246 print
'<tr><td colspan="2"><br>*** Clean table user_rights from lines of external modules no more enabled</td></tr>';
1249 foreach ($conf->modules as $key => $val) {
1250 $listofmods .= ($listofmods ?
',' :
'').
"'".$db->escape($val).
"'";
1253 $sql =
"SELECT id, libelle as label, module from ".MAIN_DB_PREFIX.
"rights_def WHERE module NOT IN (".$db->sanitize($listofmods, 1).
") AND id > 100000";
1255 $resql = $db->query($sql);
1257 $num = $db->num_rows($resql);
1261 $obj = $db->fetch_object($resql);
1263 print
'<tr><td>Found line with id '.$obj->id.
', label "'.$obj->label.
'" of module "'.$obj->module.
'" to delete';
1264 if (
GETPOST(
'clean_perm_table',
'alpha') ==
'confirmed') {
1265 $sqldelete =
"DELETE FROM ".MAIN_DB_PREFIX.
"rights_def WHERE id = ".((int) $obj->id);
1266 $resqldelete = $db->query($sqldelete);
1267 if (!$resqldelete) {
1277 print
'<tr><td>No lines of a disabled external module (with id > 100000) found into table rights_def</td></tr>';
1287if ($ok &&
GETPOST(
'force_utf8_on_tables',
'alpha')) {
1288 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>';
1290 if ($db->type ==
"mysql" || $db->type ==
"mysqli") {
1291 $force_utf8_on_tables =
GETPOST(
'force_utf8_on_tables',
'alpha');
1293 $listoftables = $db->DDLListTablesFull($db->database_name);
1296 if ($force_utf8_on_tables ==
'confirmed') {
1297 $sql =
'SET FOREIGN_KEY_CHECKS=0';
1298 print
'<!-- '.$sql.
' -->';
1299 print
'<tr><td colspan="2">'.$sql.
'</td></tr>';
1300 $resql = $db->query($sql);
1303 $foreignkeystorestore = array();
1306 foreach ($listoftables as $table) {
1308 if ($conf->db->dolibarr_main_db_encryption != 0 && preg_match(
'/\_const$/', $table[0])) {
1311 if ($table[1] ==
'VIEW') {
1312 print
'<tr><td colspan="2">'.$table[0].
' is a '.$table[1].
' <span class="opacitymedium">(Skipped)</span></td></tr>';
1317 $arrayofforeignkey = array(
1318 'llx_accounting_account' =>
'fk_accounting_account_fk_pcg_version',
1319 'llx_accounting_system' =>
'fk_accounting_account_fk_pcg_version',
1320 'llx_c_type_contact' =>
'fk_societe_commerciaux_fk_c_type_contact_code',
1321 'llx_societe_commerciaux' =>
'fk_societe_commerciaux_fk_c_type_contact_code'
1324 foreach ($arrayofforeignkey as $tmptable => $foreignkeyname) {
1325 if ($table[0] == $tmptable) {
1326 print
'<tr><td colspan="2">';
1327 $sqltmp =
"ALTER TABLE ".$db->sanitize($table[0]).
" DROP FOREIGN KEY ".$db->sanitize($foreignkeyname);
1329 if ($force_utf8_on_tables ==
'confirmed') {
1330 $resqltmp = $db->query($sqltmp);
1332 print
' - <span class="opacitymedium">Disabled</span>';
1335 $foreignkeystorestore[$tmptable] = $foreignkeyname;
1340 foreach ($listoftables as $table) {
1342 if ($conf->db->dolibarr_main_db_encryption != 0 && preg_match(
'/\_const$/', $table[0])) {
1345 if ($table[1] ==
'VIEW') {
1346 print
'<tr><td colspan="2">'.$table[0].
' is a '.$table[1].
' <span class="opacitymedium">(Skipped)</span></td></tr>';
1350 $collation =
'utf8_unicode_ci';
1351 $defaultcollation = $db->getDefaultCollationDatabase();
1352 if (preg_match(
'/general/', $defaultcollation)) {
1353 $collation =
'utf8_general_ci';
1356 print
'<tr><td colspan="2">';
1358 $sql1 =
"ALTER TABLE ".$db->sanitize($table[0]).
" ROW_FORMAT=dynamic";
1359 $sql2 =
"ALTER TABLE ".$db->sanitize($table[0]).
" CONVERT TO CHARACTER SET utf8 COLLATE ".$db->sanitize($collation);
1360 print
'<!-- '.$sql1.
' -->';
1361 print
'<!-- '.$sql2.
' -->';
1362 if ($force_utf8_on_tables ==
'confirmed') {
1363 $resql1 = $db->query($sql1);
1365 $resql2 = $db->query($sql2);
1369 print
' - Done '.(($resql1 && $resql2) ?
'<span class="opacitymedium">(OK)</span>' :
'<span class="error" title="'.
dol_escape_htmltag($db->lasterror).
'">(KO)</span>');
1371 print
' - <span class="opacitymedium">Disabled</span>';
1379 foreach ($foreignkeystorestore as $tmptable => $foreignkeyname) {
1380 $stringtofindinline =
"ALTER TABLE .* ADD CONSTRAINT ".$db->sanitize($foreignkeyname);
1381 $fileforkeys = DOL_DOCUMENT_ROOT.
'/install/mysql/tables/'.$tmptable.
'.key.sql';
1384 $handle = fopen($fileforkeys,
'r');
1386 while (($line = fgets($handle)) !==
false) {
1388 if (preg_match(
'/^'.$stringtofindinline.
'/i', $line)) {
1389 $resqltmp = $db->query($line);
1390 print
'<tr><td colspan="2">';
1392 print
' - Done '.($resqltmp ?
'<span class="opacitymedium">(OK)</span>' :
'<span class="error" title="'.dol_escape_htmltag($db->lasterror).
'">(KO)</span>');
1404 if ($force_utf8_on_tables ==
'confirmed') {
1405 $sql =
'SET FOREIGN_KEY_CHECKS=1';
1406 print
'<!-- '.$sql.
' -->';
1407 print
'<tr><td colspan="2">'.$sql.
'</td></tr>';
1408 $resql = $db->query($sql);
1411 print
'<tr><td colspan="2">Not available with database type '.$db->type.
'</td></tr>';
1416if ($ok &&
GETPOST(
'force_utf8mb4_on_tables',
'alpha')) {
1417 print
'<tr><td colspan="2"><br>*** Force page code and collation of tables into utf8mb4/utf8mb4_unicode_ci (for mysql/mariadb only)</td></tr>';
1419 if ($db->type ==
"mysql" || $db->type ==
"mysqli") {
1420 $force_utf8mb4_on_tables =
GETPOST(
'force_utf8mb4_on_tables',
'alpha');
1423 $listoftables = $db->DDLListTablesFull($db->database_name);
1426 if ($force_utf8mb4_on_tables ==
'confirmed') {
1427 $sql =
'SET FOREIGN_KEY_CHECKS=0';
1428 print
'<!-- '.$sql.
' -->';
1429 print
'<tr><td colspan="2">'.$sql.
'</td></tr>';
1430 $resql = $db->query($sql);
1433 $foreignkeystorestore = array();
1436 foreach ($listoftables as $table) {
1438 if ($conf->db->dolibarr_main_db_encryption != 0 && preg_match(
'/\_const$/', $table[0])) {
1441 if ($table[1] ==
'VIEW') {
1442 print
'<tr><td colspan="2">'.$table[0].
' is a '.$table[1].
' <span class="opacitymedium">(Skipped)</span></td></tr>';
1447 $arrayofforeignkey = array(
1448 'llx_accounting_account' =>
'fk_accounting_account_fk_pcg_version',
1449 'llx_accounting_system' =>
'fk_accounting_account_fk_pcg_version',
1450 'llx_c_type_contact' =>
'fk_societe_commerciaux_fk_c_type_contact_code',
1451 'llx_societe_commerciaux' =>
'fk_societe_commerciaux_fk_c_type_contact_code'
1454 foreach ($arrayofforeignkey as $tmptable => $foreignkeyname) {
1455 if ($table[0] == $tmptable) {
1456 print
'<tr><td colspan="2">';
1457 $sqltmp =
"ALTER TABLE ".$db->sanitize($table[0]).
" DROP FOREIGN KEY ".$db->sanitize($foreignkeyname);
1459 if ($force_utf8mb4_on_tables ==
'confirmed') {
1460 $resqltmp = $db->query($sqltmp);
1462 print
' - <span class="opacitymedium">Disabled</span>';
1465 $foreignkeystorestore[$tmptable] = $foreignkeyname;
1470 foreach ($listoftables as $table) {
1472 if ($conf->db->dolibarr_main_db_encryption != 0 && preg_match(
'/\_const$/', $table[0])) {
1475 if ($table[1] ==
'VIEW') {
1476 print
'<tr><td colspan="2">'.$table[0].
' is a '.$table[1].
' <span class="opacitymedium">(Skipped)</span></td></tr>';
1480 $collation =
'utf8mb4_unicode_ci';
1481 $defaultcollation = $db->getDefaultCollationDatabase();
1482 if (preg_match(
'/general/', $defaultcollation)) {
1483 $collation =
'utf8mb4_general_ci';
1486 print
'<tr><td colspan="2">';
1488 $sql1 =
"ALTER TABLE ".$db->sanitize($table[0]).
" ROW_FORMAT=dynamic";
1489 $sql2 =
"ALTER TABLE ".$db->sanitize($table[0]).
" CONVERT TO CHARACTER SET utf8mb4 COLLATE ".$db->sanitize($collation);
1490 print
'<!-- '.$sql1.
' -->';
1491 print
'<!-- '.$sql2.
' -->';
1492 if ($force_utf8mb4_on_tables ==
'confirmed') {
1493 $resql1 = $db->query($sql1);
1495 $resql2 = $db->query($sql2);
1499 print
' - Done '.(($resql1 && $resql2) ?
'<span class="opacitymedium">(OK)</span>' :
'<span class="error" title="'.
dol_escape_htmltag($db->lasterror).
'">(KO)</span>');
1501 print
' - <span class="opacitymedium">Disabled</span>';
1509 foreach ($foreignkeystorestore as $tmptable => $foreignkeyname) {
1510 $stringtofindinline =
"ALTER TABLE .* ADD CONSTRAINT ".$db->sanitize($foreignkeyname);
1511 $fileforkeys = DOL_DOCUMENT_ROOT.
'/install/mysql/tables/'.$tmptable.
'.key.sql';
1514 $handle = fopen($fileforkeys,
'r');
1516 while (($line = fgets($handle)) !==
false) {
1518 if (preg_match(
'/^'.$stringtofindinline.
'/i', $line)) {
1519 $resqltmp = $db->query($line);
1520 print
'<tr><td colspan="2">';
1522 print
' - Done '.($resqltmp ?
'<span class="opacitymedium">(OK)</span>' :
'<span class="error" title="'.dol_escape_htmltag($db->lasterror).
'">(KO)</span>');
1534 if ($force_utf8mb4_on_tables ==
'confirmed') {
1535 $sql =
'SET FOREIGN_KEY_CHECKS=1';
1536 print
'<!-- '.$sql.
' -->';
1537 print
'<tr><td colspan="2">'.$sql.
'</td></tr>';
1538 $resql = $db->query($sql);
1541 print
'<tr><td colspan="2">Not available with database type '.$db->type.
'</td></tr>';
1545if ($ok &&
GETPOST(
'force_collation_from_conf_on_tables',
'alpha')) {
1546 print
'<tr><td colspan="2"><br>*** Force page code and collation of tables into '.$conf->db->character_set.
'/'.$conf->db->dolibarr_main_db_collation.
' and row_format=dynamic (for mysql/mariadb only)</td></tr>';
1548 if ($db->type ==
"mysql" || $db->type ==
"mysqli") {
1549 $force_collation_from_conf_on_tables =
GETPOST(
'force_collation_from_conf_on_tables',
'alpha');
1551 $listoftables = $db->DDLListTablesFull($db->database_name);
1554 if ($force_collation_from_conf_on_tables ==
'confirmed') {
1555 $sql =
'SET FOREIGN_KEY_CHECKS=0';
1556 print
'<!-- '.$sql.
' -->';
1557 $resql = $db->query($sql);
1560 foreach ($listoftables as $table) {
1562 if ($conf->db->dolibarr_main_db_encryption != 0 && preg_match(
'/\_const$/', $table[0])) {
1565 if ($table[1] ==
'VIEW') {
1566 print
'<tr><td colspan="2">'.$table[0].
' is a '.$table[1].
' (Skipped)</td></tr>';
1570 print
'<tr><td colspan="2">';
1572 $sql1 =
"ALTER TABLE ".$table[0].
" ROW_FORMAT=dynamic";
1573 $sql2 =
"ALTER TABLE ".$table[0].
" CONVERT TO CHARACTER SET ".$conf->db->character_set.
" COLLATE ".$conf->db->dolibarr_main_db_collation;
1574 print
'<!-- '.$sql1.
' -->';
1575 print
'<!-- '.$sql2.
' -->';
1576 if ($force_collation_from_conf_on_tables ==
'confirmed') {
1577 $resql1 = $db->query($sql1);
1579 $resql2 = $db->query($sql2);
1583 print
' - Done '.(($resql1 && $resql2) ?
'<span class="opacitymedium">(OK)</span>' :
'<span class="error" title="'.
dol_escape_htmltag($db->lasterror).
'">(KO)</span>');
1585 print
' - <span class="opacitymedium">Disabled</span>';
1591 if ($force_collation_from_conf_on_tables ==
'confirmed') {
1592 $sql =
'SET FOREIGN_KEY_CHECKS=1';
1593 print
'<!-- '.$sql.
' -->';
1594 $resql = $db->query($sql);
1597 print
'<tr><td colspan="2">Not available with database type '.$db->type.
'</td></tr>';
1602if ($ok &&
GETPOST(
'rebuild_sequences',
'alpha')) {
1603 print
'<tr><td colspan="2"><br>*** Force to rebuild sequences (for postgresql only)</td></tr>';
1605 if ($db->type ==
"pgsql") {
1606 $rebuild_sequence =
GETPOST(
'rebuild_sequences',
'alpha');
1608 if ($rebuild_sequence ==
'confirmed') {
1609 $sql =
"SELECT dol_util_rebuild_sequences();";
1610 print
'<!-- '.$sql.
' -->';
1611 $resql = $db->query($sql);
1614 print
'<tr><td colspan="2">Not available with database type '.$db->type.
'</td></tr>';
1619if ($ok &&
GETPOST(
'repair_link_dispatch_lines_supplier_order_lines')) {
1643 $repair_link_dispatch_lines_supplier_order_lines =
GETPOST(
'repair_link_dispatch_lines_supplier_order_lines',
'alpha');
1646 echo
'<tr><th>Repair llx_receptiondet_batch.fk_commandefourndet</th></tr>';
1647 echo
'<tr><td>Repair in progress. This may take a while.</td></tr>';
1649 $sql_dispatch =
'SELECT * FROM '.MAIN_DB_PREFIX.
'receptiondet_batch WHERE COALESCE(fk_elementdet, 0) = 0';
1651 $resql_dispatch = $db->query($sql_dispatch);
1652 $n_processed_rows = 0;
1654 if ($resql_dispatch) {
1655 if ($db->num_rows($resql_dispatch) == 0) {
1656 echo
'<tr><td>Nothing to do.</td></tr>';
1659 while ($obj_dispatch = $db->fetch_object($resql_dispatch)) {
1660 $sql_line =
'SELECT line.rowid, line.qty FROM '.MAIN_DB_PREFIX.
'commande_fournisseurdet AS line';
1661 $sql_line .=
' WHERE line.fk_commande = '.((int) $obj_dispatch->fk_commande);
1662 $sql_line .=
' AND line.fk_product = '.((int) $obj_dispatch->fk_product);
1663 $resql_line = $db->query($sql_line);
1669 $remaining_qty = $obj_dispatch->qty;
1670 $first_iteration =
true;
1672 echo
'<tr><td>Unable to find a matching supplier order line for dispatch #'.$obj_dispatch->rowid.
'</td></tr>';
1673 $errors[] = $sql_line;
1674 $n_processed_rows++;
1677 if ($db->num_rows($resql_line) == 0) {
1680 while ($obj_line = $db->fetch_object($resql_line)) {
1681 if (!$remaining_qty) {
1684 if (!$obj_line->rowid) {
1687 $qty_for_line = min($remaining_qty, $obj_line->qty);
1688 if ($first_iteration) {
1689 $sql_attach =
'UPDATE '.MAIN_DB_PREFIX.
'receptiondet_batch';
1690 $sql_attach .=
' SET fk_elementdet = '.((int) $obj_line->rowid).
', qty = '.((float) $qty_for_line);
1691 $sql_attach .=
' WHERE rowid = '.((int) $obj_dispatch->rowid);
1692 $first_iteration =
false;
1694 $sql_attach_values = array(
1695 (
string) ((
int) $obj_dispatch->fk_element),
1696 (
string) ((
int) $obj_dispatch->fk_product),
1697 (
string) ((
int) $obj_line->rowid),
1698 (
string) ((
float) $qty_for_line),
1699 (
string) ((
int) $obj_dispatch->fk_entrepot),
1700 (
string) ((
int) $obj_dispatch->fk_user),
1701 $obj_dispatch->datec ?
"'".$db->idate($db->jdate($obj_dispatch->datec)).
"'" :
'NULL',
1702 $obj_dispatch->comment ?
"'".$db->escape($obj_dispatch->comment).
"'" :
'NULL',
1703 $obj_dispatch->
status ? (string) ((int) $obj_dispatch->
status) :
'NULL',
1704 $obj_dispatch->tms ?
"'".$db->idate($db->jdate($obj_dispatch->tms)).
"'" :
'NULL',
1705 $obj_dispatch->batch ?
"'".$db->escape($obj_dispatch->batch).
"'" :
'NULL',
1706 $obj_dispatch->eatby ?
"'".$db->escape($obj_dispatch->eatby).
"'" :
'NULL',
1707 $obj_dispatch->sellby ?
"'".$db->escape($obj_dispatch->sellby).
"'" :
'NULL'
1709 $sql_attach_values = implode(
', ', $sql_attach_values);
1711 $sql_attach =
'INSERT INTO '.MAIN_DB_PREFIX.
'receptiondet_batch';
1712 $sql_attach .=
' (fk_element, fk_product, fk_elementdet, qty, fk_entrepot, fk_user, datec, comment, status, tms, batch, eatby, sellby)';
1713 $sql_attach .=
" VALUES (".$sql_attach_values.
")";
1716 if ($repair_link_dispatch_lines_supplier_order_lines ==
'confirmed') {
1717 $resql_attach = $db->query($sql_attach);
1719 $resql_attach =
true;
1722 if ($resql_attach) {
1723 $remaining_qty -= $qty_for_line;
1725 $errors[] = $sql_attach;
1728 $first_iteration =
false;
1730 $n_processed_rows++;
1733 if (!($n_processed_rows & 0xff)) {
1734 echo
'<tr><td>Processed '.$n_processed_rows.
' rows with '.count($errors).
' errors…'.
"</td></tr>\n";
1740 echo
'<tr><td>Unable to find any dispatch without an fk_commandefourndet.'.
"</td></tr>\n";
1741 echo $sql_dispatch.
"\n";
1743 echo
'<tr><td>Fixed '.$n_processed_rows.
' rows with '.count($errors).
' errors…'.
"</td></tr>\n";
1744 echo
'<tr><td>DONE.'.
"</td></tr>\n";
1746 if (count($errors)) {
1748 echo
'<tr><td>The transaction was rolled back due to errors: nothing was changed by the script.</td></tr>';
1754 echo
'<tr><td><h3>SQL queries with errors:</h3></tr></td>';
1755 echo
'<tr><td>'.implode(
'</td></tr><tr><td>', $errors).
'</td></tr>';
1759if ($ok &&
GETPOST(
'repair_supplier_order_duplicate_ref')) {
1760 require_once DOL_DOCUMENT_ROOT .
'/fourn/class/fournisseur.commande.class.php';
1761 include_once DOL_DOCUMENT_ROOT .
'/societe/class/societe.class.php';
1768 $sql =
"SELECT * FROM " . MAIN_DB_PREFIX .
"commande_fournisseur";
1769 $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)";
1772 $duplicateSupplierOrders = [];
1773 $resql = $db->query($sql);
1775 while ($rawSupplierOrder = $db->fetch_object($resql)) {
1777 $supplierOrder->setVarsFromFetchObj($rawSupplierOrder);
1779 $duplicateSupplierOrders[$rawSupplierOrder->ref] [] = $supplierOrder;
1786 foreach ($duplicateSupplierOrders as $ref => $supplierOrders) {
1788 foreach (array_slice($supplierOrders, 1) as $supplierOrder) {
1791 $soc->fetch($supplierOrder->fourn_id);
1793 $newRef = $supplierOrder->getNextNumRef($soc);
1795 $sql =
"UPDATE " . MAIN_DB_PREFIX .
"commande_fournisseur cf SET cf.ref = '" . $db->escape($newRef) .
"' WHERE cf.rowid = " . (int) $supplierOrder->id;
1796 if (!$db->query($sql)) {
1812if ($ok &&
GETPOST(
'recalculateinvoicetotal') ==
'confirmed') {
1815 $sql =
"SELECT f.rowid, SUM(fd.total_ht) as total_ht";
1816 $sql .=
" FROM ".MAIN_DB_PREFIX.
"facture f";
1817 $sql .=
" LEFT JOIN ".MAIN_DB_PREFIX.
"facturedet fd ON fd.fk_facture = f.rowid";
1818 $sql .=
" WHERE f.total_ht = 0";
1819 $sql .=
" GROUP BY fd.fk_facture HAVING SUM(fd.total_ht) <> 0";
1821 $resql = $db->query($sql);
1823 $num = $db->num_rows($resql);
1824 print
"We found ".$num.
" factures qualified that will have their total recalculated because they are at zero and line items not at zero\n";
1825 dol_syslog(
"We found ".$num.
" factures qualified that will have their total recalculated because they are at zero and line items not at zero");
1830 $obj = $db->fetch_object($resql);
1833 SUM(fd.total_ht) as 'total_ht',
1834 SUM(fd.total_tva) as 'total_tva',
1835 SUM(fd.total_localtax1) as 'localtax1',
1836 SUM(fd.total_localtax2) as 'localtax2',
1837 SUM(fd.total_ttc) as 'total_ttc'
1839 ".MAIN_DB_PREFIX.
"facturedet fd
1841 fd.fk_facture = $obj->rowid";
1842 $ressql_calculs = $db->query($sql_calculs);
1843 while ($obj_calcul = $db->fetch_object($ressql_calculs)) {
1845 UPDATE ".MAIN_DB_PREFIX.
"facture
1847 total_ht = ".($obj_calcul->total_ht ?
price2num($obj_calcul->total_ht,
'MT') : 0).
",
1848 total_tva = ".($obj_calcul->total_tva ?
price2num($obj_calcul->total_tva,
'MT') : 0).
",
1849 localtax1 = ".($obj_calcul->localtax1 ?
price2num($obj_calcul->localtax1,
'MT') : 0).
",
1850 localtax2 = ".($obj_calcul->localtax2 ?
price2num($obj_calcul->localtax2,
'MT') : 0).
",
1851 total_ttc = ".($obj_calcul->total_ttc ?
price2num($obj_calcul->total_ttc,
'MT') : 0).
"
1853 rowid = $obj->rowid";
1854 $db->query($sql_maj);
1859 print
"Pas de factures à traiter\n";
1863 dol_syslog(
"calculate_total_and_taxes.php: Error");
1876if (empty($actiondone)) {
1877 print
'<div class="error">'.$langs->trans(
"ErrorWrongParameters").
'</div>';
1881 print
'<div class="center" style="padding-top: 10px"><a href="../index.php?mainmenu=home&leftmenu=home'.(GETPOSTISSET(
"login") ?
'&username='.urlencode(
GETPOST(
"login")) :
'').
'">';
1882 print $langs->trans(
"GoToDolibarr");
1889if ($db->connected) {
1894if (!$ok && isset($argv[1])) {
print $langs trans("AuditedSecurityEvents").'</strong >< span class="opacitymedium"></span >< br > status
Or an array listing all the potential status of the object: array: int of the status => translated la...
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.
Class for managing the social charges.
Class to manage predefined suppliers products.
Class to manage customers orders.
Class to manage contracts.
Class to manage suppliers invoices.
Class to manage invoices.
Class to manage proposals.
Class to manage third parties objects (customers, suppliers, prospects...)
dol_copy($srcfile, $destfile, $newmask='0', $overwriteifexists=1, $testvirus=0, $indexdatabase=0)
Copy a file to another 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.
dol_delete_dir($dir, $nophperrors=0)
Remove a directory (not recursive, so content must be empty).
dol_is_file($pathoffile)
Return if path is a file.
dol_dir_list($utf8_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.
price2num($amount, $rounding='', $option=0)
Function that return a number with universal decimal format (decimal separator is '.
dol_strlen($string, $stringencoding='UTF-8')
Make a strlen call.
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_print_error($db=null, $error='', $errors=null)
Displays error message system with all the information to facilitate the diagnosis and the escalation...
dol_syslog($message, $level=LOG_INFO, $ident=0, $suffixinfilename='', $restricttologhandler='', $logcontext=null)
Write log message into outputs.
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).
image_format_supported($file, $acceptsvg=0)
Return if a filename is file name of a supported image format.
pHeader($subtitle, $next, $action='set', $param='', $forcejqueryurl='', $csstable='main-inside')
Show HTML header of install pages.
pFooter($nonext=0, $setuplang='', $jscheckfunction='', $withpleasewait=0, $morehtml='')
Print HTML footer of install pages.
dolibarr_install_syslog($message, $level=LOG_DEBUG)
Log function for install pages.
clean_data_ecm_directories()
Clean data into ecm_directories table.
dol_decode($chain, $key='1')
Decode a base 64 encoded + specific delta change.