30include_once
'inc.php';
31if (file_exists($conffile)) {
32 include_once $conffile;
46require_once $dolibarr_main_document_root.
'/core/lib/admin.lib.php';
47include_once $dolibarr_main_document_root.
'/core/lib/images.lib.php';
48require_once $dolibarr_main_document_root.
'/core/class/extrafields.class.php';
49require_once
'lib/repair.lib.php';
57$err = error_reporting();
62$setuplang =
GETPOST(
"selectlang",
'aZ09', 3) ?
GETPOST(
"selectlang",
'aZ09', 3) :
'auto';
63$langs->setDefaultLang($setuplang);
65$langs->loadLangs(array(
"admin",
"install",
"other"));
67if ($dolibarr_main_db_type ==
"mysqli") {
70if ($dolibarr_main_db_type ==
"pgsql") {
73if ($dolibarr_main_db_type ==
"mssql") {
79if (!is_object(
$conf)) {
88pHeader($langs->trans(
"Repair"),
"upgrade2",
GETPOST(
'action',
'aZ09'));
93print
'<div class="warning" style="padding-top: 10px">';
94print $langs->trans(
"SetAtLeastOneOptionAsUrlParameter");
101print
'Option standard is '.(GETPOST(
'standard',
'alpha') ?
GETPOST(
'standard',
'alpha') :
'undefined').
'<br>'.
"\n";
103print
'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";
105print
'Option restore_thirdparties_logos is '.(GETPOST(
'restore_thirdparties_logos',
'alpha') ?
GETPOST(
'restore_thirdparties_logos',
'alpha') :
'undefined').
'<br>'.
"\n";
106print
'Option restore_user_pictures is '.(GETPOST(
'restore_user_pictures',
'alpha') ?
GETPOST(
'restore_user_pictures',
'alpha') :
'undefined').
'<br>'.
"\n";
107print
'Option rebuild_product_thumbs is '.(GETPOST(
'rebuild_product_thumbs',
'alpha') ?
GETPOST(
'rebuild_product_thumbs',
'alpha') :
'undefined').
'<br>'.
"\n";
109print
'Option clean_linked_elements is '.(GETPOST(
'clean_linked_elements',
'alpha') ?
GETPOST(
'clean_linked_elements',
'alpha') :
'undefined').
'<br>'.
"\n";
110print
'Option clean_menus is '.(GETPOST(
'clean_menus',
'alpha') ?
GETPOST(
'clean_menus',
'alpha') :
'undefined').
'<br>'.
"\n";
111print
'Option clean_orphelin_dir is '.(GETPOST(
'clean_orphelin_dir',
'alpha') ?
GETPOST(
'clean_orphelin_dir',
'alpha') :
'undefined').
'<br>'.
"\n";
112print
'Option clean_product_stock_batch is '.(GETPOST(
'clean_product_stock_batch',
'alpha') ?
GETPOST(
'clean_product_stock_batch',
'alpha') :
'undefined').
'<br>'.
"\n";
113print
'Option clean_perm_table is '.(GETPOST(
'clean_perm_table',
'alpha') ?
GETPOST(
'clean_perm_table',
'alpha') :
'undefined').
'<br>'.
"\n";
114print
'Option clean_ecm_files_table is '.(GETPOST(
'clean_ecm_files_table',
'alpha') ?
GETPOST(
'clean_ecm_files_table',
'alpha') :
'undefined').
'<br>'.
"\n";
115print
'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";
117print
'Option set_empty_time_spent_amount is '.(GETPOST(
'set_empty_time_spent_amount',
'alpha') ?
GETPOST(
'set_empty_time_spent_amount',
'alpha') :
'undefined').
'<br>'.
"\n";
119print
'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";
120print
'<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');
122if ($dolibarr_main_db_character_set !=
'utf8mb4') {
123 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.">';
126print
"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";
129print
'Option rebuild_sequences, for postgresql only, is '.(GETPOST(
'rebuild_sequences',
'alpha') ?
GETPOST(
'rebuild_sequences',
'alpha') :
'undefined').
'<br>'.
"\n";
134print
'<table cellspacing="0" cellpadding="1" class="centpercent">';
138if (preg_match(
'/crypted:/i', $dolibarr_main_db_pass) || !empty($dolibarr_main_db_encrypted_pass)) {
139 require_once $dolibarr_main_document_root.
'/core/lib/security.lib.php';
140 if (preg_match(
'/crypted:/i', $dolibarr_main_db_pass)) {
141 $dolibarr_main_db_pass = preg_replace(
'/crypted:/i',
'', $dolibarr_main_db_pass);
142 $dolibarr_main_db_pass =
dol_decode($dolibarr_main_db_pass);
143 $dolibarr_main_db_encrypted_pass = $dolibarr_main_db_pass;
145 $dolibarr_main_db_pass =
dol_decode($dolibarr_main_db_encrypted_pass);
150$conf->db->type = $dolibarr_main_db_type;
151$conf->db->host = $dolibarr_main_db_host;
152$conf->db->port = $dolibarr_main_db_port;
153$conf->db->name = $dolibarr_main_db_name;
154$conf->db->user = $dolibarr_main_db_user;
155$conf->db->pass = $dolibarr_main_db_pass;
158$conf->db->dolibarr_main_db_encryption = isset($dolibarr_main_db_encryption) ? $dolibarr_main_db_encryption : 0;
159$conf->db->dolibarr_main_db_cryptkey = isset($dolibarr_main_db_cryptkey) ? $dolibarr_main_db_cryptkey :
'';
164 print
'<tr><td class="nowrap">';
165 print $langs->trans(
"ServerConnection").
" : $dolibarr_main_db_host</td><td class=\"right\">".$langs->trans(
"OK").
"</td></tr>";
166 dolibarr_install_syslog(
"repair: ".$langs->transnoentities(
"ServerConnection").
": ".$dolibarr_main_db_host.$langs->transnoentities(
"OK"));
169 print
"<tr><td>".$langs->trans(
"ErrorFailedToConnectToDatabase", $dolibarr_main_db_name).
"</td><td class=\"right\">".$langs->transnoentities(
"Error").
"</td></tr>";
170 dolibarr_install_syslog(
"repair: ".$langs->transnoentities(
"ErrorFailedToConnectToDatabase", $dolibarr_main_db_name));
175 if ($db->database_selected) {
176 print
'<tr><td class="nowrap">';
177 print $langs->trans(
"DatabaseConnection").
" : ".$dolibarr_main_db_name.
"</td><td class=\"right\">".$langs->trans(
"OK").
"</td></tr>";
181 print
"<tr><td>".$langs->trans(
"ErrorFailedToConnectToDatabase", $dolibarr_main_db_name).
"</td><td class=\"right\">".$langs->trans(
"Error").
"</td></tr>";
182 dolibarr_install_syslog(
"repair: ".$langs->transnoentities(
"ErrorFailedToConnectToDatabase", $dolibarr_main_db_name));
189 $version = $db->getVersion();
190 $versionarray = $db->getVersionArray();
191 print
'<tr><td>'.$langs->trans(
"ServerVersion").
'</td>';
192 print
'<td class="right">'.$version.
'</td></tr>';
197$conf->setValues($db);
199if (defined(
'SYSLOG_FILE')) {
200 $conf->global->SYSLOG_FILE = constant(
'SYSLOG_FILE');
202$conf->global->MAIN_ENABLE_LOG_TO_HTML = 1;
207$oneoptionset = (
GETPOST(
'standard',
'alpha') ||
GETPOST(
'restore_thirdparties_logos',
'alpha') ||
GETPOST(
'clean_linked_elements',
'alpha') ||
GETPOST(
'clean_menus',
'alpha')
208 ||
GETPOST(
'clean_orphelin_dir',
'alpha') ||
GETPOST(
'clean_product_stock_batch',
'alpha') ||
GETPOST(
'set_empty_time_spent_amount',
'alpha') ||
GETPOST(
'rebuild_product_thumbs',
'alpha')
209 ||
GETPOST(
'clean_perm_table',
'alpha') ||
GETPOST(
'clean_ecm_files_table',
'alpha')
210 ||
GETPOST(
'force_disable_of_modules_not_found',
'alpha')
211 ||
GETPOST(
'force_utf8_on_tables',
'alpha') ||
GETPOST(
'force_utf8mb4_on_tables',
'alpha') ||
GETPOST(
'force_collation_from_conf_on_tables',
'alpha')
212 ||
GETPOST(
'rebuild_sequences',
'alpha') ||
GETPOST(
'recalculateinvoicetotal',
'alpha'));
214if ($ok && $oneoptionset) {
216 print
'<tr><td colspan="2">'.$langs->trans(
"PleaseBePatient").
'<br><br></td></tr>';
222if ($ok &&
GETPOST(
'standard',
'alpha')) {
223 $dir =
"mysql/migration/";
230 $filesindir = array();
231 $handle = opendir($dir);
232 if (is_resource($handle)) {
233 while (($file = readdir($handle)) !==
false) {
234 if (preg_match(
'/\.sql$/i', $file)) {
235 $filesindir[] = $file;
241 foreach ($filesindir as $file) {
242 if (preg_match(
'/repair/i', $file)) {
248 foreach ($filelist as $file) {
249 print
'<tr><td class="nowrap">*** ';
250 print $langs->trans(
"Script").
'</td><td class="right">'.$file.
'</td></tr>';
252 $name = substr($file, 0,
dol_strlen($file) - 4);
255 $ok =
run_sql($dir.$file, 0, 0, 1);
262if ($ok &&
GETPOST(
'standard',
'alpha')) {
266 $listofmodulesextra = array(
'societe' =>
'societe',
'adherent' =>
'adherent',
'product' =>
'product',
267 'socpeople' =>
'socpeople',
'propal' =>
'propal',
'commande' =>
'commande',
268 'facture' =>
'facture',
'facturedet' =>
'facturedet',
'facture_rec' =>
'facture_rec',
'facturedet_rec' =>
'facturedet_rec',
269 'supplier_proposal' =>
'supplier_proposal',
'commande_fournisseur' =>
'commande_fournisseur',
270 'facture_fourn' =>
'facture_fourn',
'facture_fourn_rec' =>
'facture_fourn_rec',
'facture_fourn_det' =>
'facture_fourn_det',
'facture_fourn_det_rec' =>
'facture_fourn_det_rec',
271 'fichinter' =>
'fichinter',
'fichinterdet' =>
'fichinterdet',
272 'inventory' =>
'inventory',
273 'actioncomm' =>
'actioncomm',
'bom_bom' =>
'bom_bom',
'mrp_mo' =>
'mrp_mo',
274 'adherent_type' =>
'adherent_type',
'user' =>
'user',
'partnership' =>
'partnership',
'projet' =>
'projet',
'projet_task' =>
'projet_task',
'ticket' =>
'ticket');
277 print
'<tr><td colspan="2"><br>*** Check fields into extra table structure match table of definition. If not add column into table</td></tr>';
278 foreach ($listofmodulesextra as $tablename => $elementtype) {
280 $tableextra = MAIN_DB_PREFIX.$tablename.
'_extrafields';
283 $arrayoffieldsdesc = $extrafields->fetch_name_optionals_label($elementtype);
286 $arrayoffieldsfound = array();
287 $resql = $db->DDLDescTable($tableextra);
289 print
'<tr><td>Check availability of extra field for '.$tableextra;
291 while ($obj = $db->fetch_object($resql)) {
292 $fieldname = $fieldtype =
'';
293 if (preg_match(
'/mysql/', $db->type)) {
294 $fieldname = $obj->Field;
295 $fieldtype = $obj->Type;
297 $fieldname = isset($obj->Key) ? $obj->Key : $obj->attname;
298 $fieldtype = isset($obj->Type) ? $obj->Type :
'varchar';
301 if (empty($fieldname)) {
304 if (in_array($fieldname, array(
'rowid',
'tms',
'fk_object',
'import_key'))) {
307 $arrayoffieldsfound[$fieldname] = array(
'type' => $fieldtype);
309 print
' - Found '.count($arrayoffieldsfound).
' fields into table';
310 if (count($arrayoffieldsfound) > 0) {
311 print
' <span class="opacitymedium">('.implode(
', ', array_keys($arrayoffieldsfound)).
')</span>';
316 foreach ($arrayoffieldsdesc as $code => $label) {
317 if (!in_array($code, array_keys($arrayoffieldsfound))) {
318 print
'Found field '.$code.
' declared into '.MAIN_DB_PREFIX.
'extrafields table but not found into desc of table '.$tableextra.
" -> ";
319 $type = $extrafields->attributes[$elementtype][
'type'][$code];
320 $length = $extrafields->attributes[$elementtype][
'size'][$code];
326 if ($type ==
'boolean') {
329 } elseif ($type ==
'price') {
332 } elseif ($type ==
'phone') {
335 } elseif ($type ==
'mail') {
338 } elseif (($type ==
'select') || ($type ==
'sellist') || ($type ==
'radio') || ($type ==
'checkbox') || ($type ==
'chkbxlst')) {
341 } elseif ($type ==
'link') {
351 'value' => $lengthdb,
352 'attribute' => $attribute,
353 'default' => $default,
360 if (
GETPOST(
'standard',
'alpha') ==
'confirmed') {
361 $result = $db->DDLAddField($tableextra, $code, $field_desc,
"");
364 print
"KO ".$db->lasterror.
"<br>\n";
369 print
' - Mode test, no column added.';
374 print
"</td><td> </td></tr>\n";
376 print
'<tr><td>Table '.$tableextra.
' is not found</td><td></td></tr>'.
"\n";
383if ($ok &&
GETPOST(
'standard',
'alpha')) {
389if ($ok &&
GETPOST(
'standard',
'alpha')) {
390 print
'<tr><td colspan="2"><br>*** Clean constant record of modules not enabled</td></tr>';
392 $sql =
"SELECT name, entity, value";
393 $sql .=
" FROM ".MAIN_DB_PREFIX.
"const as c";
394 $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'";
395 $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'";
396 $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_%'";
397 $sql .=
" OR name LIKE 'MAIN_MODULE_%_MODULEFOREXTERNAL'";
398 $sql .=
" ORDER BY name, entity";
400 $resql = $db->query($sql);
402 $num = $db->num_rows($resql);
409 $obj = $db->fetch_object($resql);
412 if (preg_match(
'/MAIN_MODULE_([^_]+)_(.+)/i', $obj->name, $reg)) {
416 $sql2 =
"SELECT COUNT(*) as nb";
417 $sql2 .=
" FROM ".MAIN_DB_PREFIX.
"const as c";
418 $sql2 .=
" WHERE name = 'MAIN_MODULE_".$name.
"'";
419 $sql2 .=
" AND entity = ".((int) $obj->entity);
420 $resql2 = $db->query($sql2);
422 $obj2 = $db->fetch_object($resql2);
423 if ($obj2 && $obj2->nb == 0) {
425 $sqldelete =
"DELETE FROM ".MAIN_DB_PREFIX.
"const WHERE name = '".$db->escape($obj->name).
"' AND entity = ".((int) $obj->entity);
427 if (
GETPOST(
'standard',
'alpha') ==
'confirmed') {
428 $db->query($sqldelete);
430 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>';
432 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>';
452if ($ok &&
GETPOST(
'standard',
'alpha')) {
453 print
'<tr><td colspan="2"><br>*** Clean definition of boxes of modules not enabled</td></tr>';
455 $sql =
"SELECT file, entity FROM ".MAIN_DB_PREFIX.
"boxes_def";
456 $sql .=
" WHERE file like '%@%'";
458 $resql = $db->query($sql);
460 $num = $db->num_rows($resql);
467 $obj = $db->fetch_object($resql);
470 if (preg_match(
'/^(.+)@(.+)$/i', $obj->file, $reg)) {
474 $sql2 =
"SELECT COUNT(*) as nb";
475 $sql2 .=
" FROM ".MAIN_DB_PREFIX.
"const as c";
476 $sql2 .=
" WHERE name = 'MAIN_MODULE_".strtoupper($module).
"'";
477 $sql2 .=
" AND entity = ".((int) $obj->entity);
478 $sql2 .=
" AND value <> 0";
479 $resql2 = $db->query($sql2);
481 $obj2 = $db->fetch_object($resql2);
482 if ($obj2 && $obj2->nb == 0) {
484 $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).
")";
485 $sqldeleteb =
"DELETE FROM ".MAIN_DB_PREFIX.
"boxes_def WHERE file = '".$db->escape($obj->file).
"' AND entity = ".((int) $obj->entity);
487 if (
GETPOST(
'standard',
'alpha') ==
'confirmed') {
488 $db->query($sqldeletea);
489 $db->query($sqldeleteb);
491 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>';
493 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>';
511if ($ok &&
GETPOST(
'restore_thirdparties_logos')) {
516 print
'<tr><td colspan="2"><br>*** Restore thirdparties logo<br>';
518 $sql =
"SELECT s.rowid, s.nom as name, s.logo FROM ".MAIN_DB_PREFIX.
"societe as s ORDER BY s.nom";
519 $resql = $db->query($sql);
521 $num = $db->num_rows($resql);
525 $obj = $db->fetch_object($resql);
533 $tmp = explode(
'.', (
string) $obj->logo);
535 if (isset($tmp[1])) {
540 $filetotest = $dolibarr_main_data_root.
'/societe/logos/'.$name.$ext;
541 $filetotestsmall = $dolibarr_main_data_root.
'/societe/logos/thumbs/'.$name.
'_small'.$ext;
543 print
'Check thirdparty '.$obj->rowid.
' name='.$obj->name.
' logo='.$obj->logo.
' file '.$filetotest.
" exists=".$exists.
"<br>\n";
545 $filetarget = $dolibarr_main_data_root.
'/societe/'.$obj->rowid.
'/logos/'.$name.$ext;
546 $filetargetsmall = $dolibarr_main_data_root.
'/societe/'.$obj->rowid.
'/logos/thumbs/'.$name.
'_small'.$ext;
549 if (
GETPOST(
'restore_thirdparties_logos',
'alpha') ==
'confirmed') {
550 dol_mkdir($dolibarr_main_data_root.
'/societe/'.$obj->rowid.
'/logos');
553 print
" -> Copy file ".$filetotest.
" -> ".$filetarget.
"<br>\n";
554 if (
GETPOST(
'restore_thirdparties_logos',
'alpha') ==
'confirmed') {
555 dol_copy($filetotest, $filetarget,
'', 0);
561 if (
GETPOST(
'restore_thirdparties_logos',
'alpha') ==
'confirmed') {
562 dol_mkdir($dolibarr_main_data_root.
'/societe/'.$obj->rowid.
'/logos/thumbs');
564 print
" -> Copy file ".$filetotestsmall.
" -> ".$filetargetsmall.
"<br>\n";
565 if (
GETPOST(
'restore_thirdparties_logos',
'alpha') ==
'confirmed') {
566 dol_copy($filetotestsmall, $filetargetsmall,
'', 0);
585if ($ok &&
GETPOST(
'restore_user_pictures',
'alpha')) {
590 print
'<tr><td colspan="2"><br>*** Restore user pictures<br>';
592 $sql =
"SELECT s.rowid, s.firstname, s.lastname, s.login, s.photo FROM ".MAIN_DB_PREFIX.
"user as s ORDER BY s.rowid";
593 $resql = $db->query($sql);
595 $num = $db->num_rows($resql);
599 $obj = $db->fetch_object($resql);
607 $tmp = explode(
'.', (
string) $obj->photo);
609 if (isset($tmp[1])) {
614 $filetotest = $dolibarr_main_data_root.
'/users/'.substr(sprintf(
'%08d', $obj->rowid), -1, 1).
'/'.substr(sprintf(
'%08d', $obj->rowid), -2, 1).
'/'.$name.$ext;
615 $filetotestsmall = $dolibarr_main_data_root.
'/users/'.substr(sprintf(
'%08d', $obj->rowid), -1, 1).
'/'.substr(sprintf(
'%08d', $obj->rowid), -2, 1).
'/thumbs/'.$name.
'_small'.$ext;
616 $filetotestmini = $dolibarr_main_data_root.
'/users/'.substr(sprintf(
'%08d', $obj->rowid), -1, 1).
'/'.substr(sprintf(
'%08d', $obj->rowid), -2, 1).
'/thumbs/'.$name.
'_mini'.$ext;
618 print
'Check user '.$obj->rowid.
' lastname='.$obj->lastname.
' firstname='.$obj->firstname.
' photo='.$obj->photo.
' file '.$filetotest.
" exists=".$exists.
"<br>\n";
620 $filetarget = $dolibarr_main_data_root.
'/users/'.$obj->rowid.
'/'.$name.$ext;
621 $filetargetsmall = $dolibarr_main_data_root.
'/users/'.$obj->rowid.
'/thumbs/'.$name.
'_small'.$ext;
622 $filetargetmini = $dolibarr_main_data_root.
'/users/'.$obj->rowid.
'/thumbs/'.$name.
'_mini'.$ext;
626 if (
GETPOST(
'restore_user_pictures',
'alpha') ==
'confirmed') {
627 dol_mkdir($dolibarr_main_data_root.
'/users/'.$obj->rowid);
630 print
" -> Copy file ".$filetotest.
" -> ".$filetarget.
"<br>\n";
631 if (
GETPOST(
'restore_user_pictures',
'alpha') ==
'confirmed') {
632 dol_copy($filetotest, $filetarget,
'', 0);
638 if (
GETPOST(
'restore_user_pictures',
'alpha') ==
'confirmed') {
639 dol_mkdir($dolibarr_main_data_root.
'/users/'.$obj->rowid.
'/thumbs');
642 print
" -> Copy file ".$filetotestsmall.
" -> ".$filetargetsmall.
"<br>\n";
643 if (
GETPOST(
'restore_user_pictures',
'alpha') ==
'confirmed') {
644 dol_copy($filetotestsmall, $filetargetsmall,
'', 0);
650 if (
GETPOST(
'restore_user_pictures',
'alpha') ==
'confirmed') {
651 dol_mkdir($dolibarr_main_data_root.
'/users/'.$obj->rowid.
'/thumbs');
654 print
" -> Copy file ".$filetotestmini.
" -> ".$filetargetmini.
"<br>\n";
655 if (
GETPOST(
'restore_user_pictures',
'alpha') ==
'confirmed') {
656 dol_copy($filetotestmini, $filetargetmini,
'', 0);
674if ($ok &&
GETPOST(
'rebuild_product_thumbs',
'alpha')) {
676 global $maxwidthsmall, $maxheightsmall, $maxwidthmini, $maxheightmini;
678 print
'<tr><td colspan="2"><br>*** Rebuild product thumbs<br>';
680 $sql =
"SELECT s.rowid, s.ref FROM ".MAIN_DB_PREFIX.
"product as s ORDER BY s.ref";
681 $resql = $db->query($sql);
683 $num = $db->num_rows($resql);
687 $obj = $db->fetch_object($resql);
689 if (!empty($obj->ref)) {
690 $files =
dol_dir_list($dolibarr_main_data_root.
'/produit/'.$obj->ref,
'files', 0);
691 foreach ($files as $file) {
694 $imgThumbSmall =
'notbuild';
695 if (
GETPOST(
'rebuild_product_thumbs',
'alpha') ==
'confirmed') {
697 $imgThumbSmall =
vignette($file[
'fullname'], $maxwidthsmall, $maxheightsmall,
'_small', 50,
"thumbs");
699 print
'Check product '.$obj->rowid.
", file ".$file[
'fullname'].
" -> ".$imgThumbSmall.
" maxwidthsmall=".$maxwidthsmall.
" maxheightsmall=".$maxheightsmall.
"<br>\n";
700 $imgThumbMini =
'notbuild';
701 if (
GETPOST(
'rebuild_product_thumbs',
'alpha') ==
'confirmed') {
704 $imgThumbMini =
vignette($file[
'fullname'], $maxwidthmini, $maxheightmini,
'_mini', 50,
"thumbs");
706 print
'Check product '.$obj->rowid.
", file ".$file[
'fullname'].
" -> ".$imgThumbMini.
" maxwidthmini=".$maxwidthmini.
" maxheightmini=".$maxheightmini.
"<br>\n";
722if ($ok &&
GETPOST(
'clean_linked_elements',
'alpha')) {
723 print
'<tr><td colspan="2"><br>*** Check table of linked elements and delete orphelins links</td></tr>';
725 print
'<tr><td colspan="2">'.checkLinkedElements(
'propal',
'commande').
"</td></tr>\n";
728 print
'<tr><td colspan="2">'.checkLinkedElements(
'propal',
'facture').
"</td></tr>\n";
731 print
'<tr><td colspan="2">'.checkLinkedElements(
'commande',
'facture').
"</td></tr>\n";
734 print
'<tr><td colspan="2">'.checkLinkedElements(
'commande',
'shipping').
"</td></tr>\n";
737 print
'<tr><td colspan="2">'.checkLinkedElements(
'shipping',
'delivery').
"</td></tr>\n";
740 print
'<tr><td colspan="2">'.checkLinkedElements(
'order_supplier',
'invoice_supplier').
"</td></tr>\n";
745if ($ok &&
GETPOST(
'clean_menus',
'alpha')) {
746 print
'<tr><td colspan="2"><br>*** Clean menu entries coming from disabled modules</td></tr>';
748 $sql =
"SELECT rowid, module";
749 $sql .=
" FROM ".MAIN_DB_PREFIX.
"menu as c";
750 $sql .=
" WHERE module IS NOT NULL AND module <> ''";
751 $sql .=
" ORDER BY module";
753 $resql = $db->query($sql);
755 $num = $db->num_rows($resql);
759 $obj = $db->fetch_object($resql);
761 $modulecond = $obj->module;
762 $modulecondarray = explode(
'|', $obj->module);
771 foreach ($modulecondarray as $tmpname) {
772 if ($tmpname ==
'margins') {
777 if (!empty(
$conf->$tmpname)) {
778 $result =
$conf->$tmpname->enabled;
785 if (!$moduleok && $modulecond) {
786 print
' - Module condition '.$modulecond.
' seems ko, we delete menu entry.';
787 if (
GETPOST(
'clean_menus') ==
'confirmed') {
788 $sql2 =
"DELETE FROM ".MAIN_DB_PREFIX.
"menu WHERE module = '".$db->escape($modulecond).
"'";
789 $resql2 = $db->query($sql2);
794 print
' - <span class="warning">Cleaned</span>';
797 print
' - <span class="warning">Canceled (test mode)</span>';
800 print
' - Module condition '.$modulecond.
' is ok, we do nothing.';
819 print
'<tr><td>No menu entries of disabled menus found</td></tr>';
829if ($ok &&
GETPOST(
'clean_orphelin_dir',
'alpha')) {
830 $listmodulepart = array(
'company',
'invoice',
'invoice_supplier',
'propal',
'order',
'order_supplier',
'contract',
'tax');
831 foreach ($listmodulepart as $modulepart) {
832 $filearray = array();
833 $upload_dir = isset(
$conf->$modulepart->dir_output) ?
$conf->$modulepart->dir_output :
'';
834 if ($modulepart ==
'company') {
835 $upload_dir =
$conf->societe->dir_output;
837 if ($modulepart ==
'invoice') {
838 $upload_dir =
$conf->facture->dir_output;
840 if ($modulepart ==
'invoice_supplier') {
841 $upload_dir =
$conf->fournisseur->facture->dir_output;
843 if ($modulepart ==
'order') {
844 $upload_dir =
$conf->commande->dir_output;
846 if ($modulepart ==
'order_supplier') {
847 $upload_dir =
$conf->fournisseur->commande->dir_output;
849 if ($modulepart ==
'contract') {
850 $upload_dir =
$conf->contrat->dir_output;
853 if (empty($upload_dir)) {
857 print
'<tr><td colspan="2"><br>*** Clean orphelins files into files '.$upload_dir.
'</td></tr>';
859 $filearray =
dol_dir_list($upload_dir,
"files", 1,
'', array(
'^SPECIMEN\.pdf$',
'^\.',
'(\.meta|_preview.*\.png)$',
'^temp$',
'^payments$',
'^CVS$',
'^thumbs$'),
'', SORT_DESC, 1, 1);
862 if ($modulepart ==
'company') {
863 include_once DOL_DOCUMENT_ROOT.
'/societe/class/societe.class.php';
864 $object_instance =
new Societe($db);
866 if ($modulepart ==
'invoice') {
867 include_once DOL_DOCUMENT_ROOT.
'/compta/facture/class/facture.class.php';
868 $object_instance =
new Facture($db);
869 } elseif ($modulepart ==
'invoice_supplier') {
870 include_once DOL_DOCUMENT_ROOT.
'/fourn/class/fournisseur.facture.class.php';
872 } elseif ($modulepart ==
'propal') {
873 include_once DOL_DOCUMENT_ROOT.
'/comm/propal/class/propal.class.php';
874 $object_instance =
new Propal($db);
875 } elseif ($modulepart ==
'order') {
876 include_once DOL_DOCUMENT_ROOT.
'/commande/class/commande.class.php';
877 $object_instance =
new Commande($db);
878 } elseif ($modulepart ==
'order_supplier') {
879 include_once DOL_DOCUMENT_ROOT.
'/fourn/class/fournisseur.commande.class.php';
881 } elseif ($modulepart ==
'contract') {
882 include_once DOL_DOCUMENT_ROOT.
'/contrat/class/contrat.class.php';
883 $object_instance =
new Contrat($db);
884 } elseif ($modulepart ==
'tax') {
885 include_once DOL_DOCUMENT_ROOT.
'/compta/sociales/class/chargesociales.class.php';
889 foreach ($filearray as $key => $file) {
890 if (!is_dir($file[
'name'])
891 && $file[
'name'] !=
'.'
892 && $file[
'name'] !=
'..'
893 && $file[
'name'] !=
'CVS'
896 $relativefile = preg_replace(
'/'.preg_quote($upload_dir.
'/',
'/').
'/',
'', $file[
'fullname']);
901 $object_instance->id = 0;
902 $object_instance->ref =
'';
906 if ($modulepart ==
'invoice') {
907 preg_match(
'/(.*)\/[^\/]+$/', $relativefile, $reg);
910 if ($modulepart ==
'invoice_supplier') {
911 preg_match(
'/(\d+)\/[^\/]+$/', $relativefile, $reg);
912 $id = empty($reg[1]) ?
'' : $reg[1];
914 if ($modulepart ==
'propal') {
915 preg_match(
'/(.*)\/[^\/]+$/', $relativefile, $reg);
918 if ($modulepart ==
'order') {
919 preg_match(
'/(.*)\/[^\/]+$/', $relativefile, $reg);
922 if ($modulepart ==
'order_supplier') {
923 preg_match(
'/(.*)\/[^\/]+$/', $relativefile, $reg);
926 if ($modulepart ==
'contract') {
927 preg_match(
'/(.*)\/[^\/]+$/', $relativefile, $reg);
930 if ($modulepart ==
'tax') {
931 preg_match(
'/(\d+)\/[^\/]+$/', $relativefile, $reg);
935 if ((
$id || $ref) && $object_instance !==
null) {
937 $result = $object_instance->fetch(
$id, $ref);
941 print
'<tr><td colspan="2">';
942 print
'Delete orphelins file '.$file[
'fullname'].
'<br>';
943 if (
GETPOST(
'clean_orphelin_dir',
'alpha') ==
'confirmed') {
948 } elseif ($result < 0) {
949 print
'Error in '.get_class($object_instance).
'.fetch of id'.
$id.
' ref='.$ref.
', result='.$result.
'<br>';
958if ($ok &&
GETPOST(
'clean_product_stock_batch',
'alpha')) {
959 $methodtofix =
GETPOST(
'methodtofix',
'alpha') ?
GETPOST(
'methodtofix',
'alpha') :
'updatestock';
961 print
'<tr><td colspan="2"><br>*** Clean table product_batch, methodtofix='.$methodtofix.
' (possible values: updatestock or updatebatch)</td></tr>';
963 $sql =
"SELECT p.rowid, p.ref, p.tobatch, ps.rowid as psrowid, ps.fk_entrepot, ps.reel, SUM(pb.qty) as reelbatch";
964 $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";
965 $sql .=
" WHERE p.rowid = ps.fk_product";
966 $sql .=
" GROUP BY p.rowid, p.ref, p.tobatch, ps.rowid, ps.fk_entrepot, ps.reel";
967 $sql .=
" HAVING (SUM(pb.qty) IS NOT NULL AND reel != SUM(pb.qty)) OR (SUM(pb.qty) IS NULL AND p.tobatch > 0)";
969 $resql = $db->query($sql);
971 $num = $db->num_rows($resql);
976 $obj = $db->fetch_object($resql);
977 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)';
980 if ($obj->reel != $obj->reelbatch) {
981 if (empty($obj->tobatch)) {
983 print
' -> Delete qty '.$obj->reelbatch.
' for any lot linked to fk_product_stock='.$obj->psrowid;
984 $sql2 =
"DELETE FROM ".MAIN_DB_PREFIX.
"product_batch";
985 $sql2 .=
" WHERE fk_product_stock = ".((int) $obj->psrowid);
988 if (
GETPOST(
'clean_product_stock_batch') ==
'confirmed') {
989 $resql2 = $db->query($sql2);
996 if ($methodtofix ==
'updatebatch') {
998 print
' -> Insert qty '.($obj->reel - $obj->reelbatch).
' with lot 000000 linked to fk_product_stock='.$obj->psrowid;
999 $sql2 =
"INSERT INTO ".MAIN_DB_PREFIX.
"product_batch(fk_product_stock, batch, qty)";
1000 $sql2 .=
"VALUES(".((int) $obj->psrowid).
", '000000', ".((float) ($obj->reel - $obj->reelbatch)).
")";
1003 if (
GETPOST(
'clean_product_stock_batch') ==
'confirmed') {
1004 $resql2 = $db->query($sql2);
1013 if ($methodtofix ==
'updatestock') {
1015 print
' -> Update qty of product_stock with qty = '.($obj->reelbatch ? ((float) $obj->reelbatch) :
'0').
' for ps.rowid = '.((
int) $obj->psrowid);
1016 $sql2 =
"UPDATE ".MAIN_DB_PREFIX.
"product_stock";
1017 $sql2 .=
" SET reel = ".($obj->reelbatch ? ((float) $obj->reelbatch) :
'0').
" WHERE rowid = ".((
int) $obj->psrowid);
1020 if (
GETPOST(
'clean_product_stock_batch') ==
'confirmed') {
1025 $resql2 = $db->query($sql2);
1028 $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)';
1029 $resql3 = $db->query($sql3);
1054 print
'<tr><td colspan="2">Nothing to do</td></tr>';
1063if ($ok &&
GETPOST(
'clean_product_stock_negative_if_batch',
'alpha')) {
1064 print
'<tr><td colspan="2"><br>Clean table product_batch, methodtofix='.$methodtofix.
' (possible values: updatestock or updatebatch)</td></tr>';
1066 $sql =
"SELECT p.rowid, p.ref, p.tobatch, ps.rowid as psrowid, ps.fk_entrepot, ps.reel, SUM(pb.qty) as reelbatch";
1067 $sql .=
" FROM ".MAIN_DB_PREFIX.
"product as p, ".MAIN_DB_PREFIX.
"product_stock as ps, ".MAIN_DB_PREFIX.
"product_batch as pb";
1068 $sql .=
" WHERE p.rowid = ps.fk_product AND ps.rowid = pb.fk_product_stock";
1069 $sql .=
" AND p.tobatch > 0";
1070 $sql .=
" GROUP BY p.rowid, p.ref, p.tobatch, ps.rowid, ps.fk_entrepot, ps.reel";
1071 $sql .=
" HAVING reel != SUM(pb.qty)";
1072 $resql = $db->query($sql);
1074 $num = $db->num_rows($resql);
1079 $obj = $db->fetch_object($resql);
1080 print
'<tr><td>'.$obj->rowid.
'-'.$obj->ref.
'-'.$obj->fk_entrepot.
' -> '.$obj->psrowid.
': '.$obj->reel.
' != '.$obj->reelbatch;
1089if ($ok &&
GETPOST(
'set_empty_time_spent_amount',
'alpha')) {
1090 print
'<tr><td colspan="2"><br>*** Set value of time spent without amount</td></tr>';
1092 $sql =
"SELECT COUNT(ptt.rowid) as nb, u.rowid as user_id, u.login, u.thm as user_thm";
1093 $sql .=
" FROM ".MAIN_DB_PREFIX.
"element_time as ptt, ".MAIN_DB_PREFIX.
"user as u";
1094 $sql .=
" WHERE ptt.fk_user = u.rowid";
1095 $sql .=
" AND ptt.thm IS NULL and u.thm > 0";
1096 $sql .=
" GROUP BY u.rowid, u.login, u.thm";
1098 $resql = $db->query($sql);
1100 $num = $db->num_rows($resql);
1105 $obj = $db->fetch_object($resql);
1106 print
'<tr><td>'.$obj->login.
'-'.$obj->user_id.
' ('.$obj->nb.
' lines to fix) -> '.$obj->user_thm;
1110 if (
GETPOST(
'set_empty_time_spent_amount') ==
'confirmed') {
1111 $sql2 =
"UPDATE ".MAIN_DB_PREFIX.
"element_time";
1112 $sql2 .=
" SET thm = ".$obj->user_thm.
" WHERE thm IS NULL AND fk_user = ".((int) $obj->user_id);
1113 $resql2 = $db->query($sql2);
1135 print
'<tr><td>No time spent with empty line on users with a hourly rate defined</td></tr>';
1144if ($ok &&
GETPOST(
'force_disable_of_modules_not_found',
'alpha')) {
1145 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>';
1147 $arraylistofkey = array(
'hooks',
'js',
'css');
1149 foreach ($arraylistofkey as $key) {
1150 $sql =
"SELECT DISTINCT name, value";
1151 $sql .=
" FROM ".MAIN_DB_PREFIX.
"const as c";
1152 $sql .=
" WHERE name LIKE 'MAIN_MODULE_%_".strtoupper($key).
"'";
1153 $sql .=
" ORDER BY name";
1155 $resql = $db->query($sql);
1157 $num = $db->num_rows($resql);
1161 $obj = $db->fetch_object($resql);
1162 $constantname = $obj->name;
1170 if (preg_match(
'/MAIN_MODULE_(.*)_'.strtoupper($key).
'/i', $constantname, $reg)) {
1171 $name = strtolower($reg[1]);
1177 if ($key ==
'hooks') {
1178 $reloffile = $name.
'/class/actions_'.$name.
'.class.php';
1181 $value = $obj->value;
1182 $valuearray = (array) json_decode($value);
1183 $reloffile = $valuearray[0];
1184 $reloffile = preg_replace(
'/^\//',
'', $valuearray[0]);
1186 if ($key ==
'css') {
1187 $value = $obj->value;
1188 $valuearray = (array) json_decode($value);
1189 if ($value && (!is_array($valuearray) || count($valuearray) == 0)) {
1190 $valuearray = array();
1191 $valuearray[0] = $value;
1193 $reloffile = preg_replace(
'/^\//',
'', $valuearray[0]);
1208 print
' - File of '.$key.
' ('.$reloffile.
') NOT found, we disable the module.';
1209 if (
GETPOST(
'force_disable_of_modules_not_found') ==
'confirmed') {
1210 $sql2 =
"DELETE FROM ".MAIN_DB_PREFIX.
"const WHERE name = 'MAIN_MODULE_".strtoupper($name).
"_".strtoupper($key).
"'";
1211 $resql2 = $db->query($sql2);
1216 $sql3 =
"DELETE FROM ".MAIN_DB_PREFIX.
"const WHERE name = 'MAIN_MODULE_".strtoupper($name).
"'";
1217 $resql3 = $db->query($sql3);
1222 print
' - <span class="warning">Cleaned</span>';
1225 print
' - <span class="warning">Canceled (test mode)</span>';
1228 print
' - File of '.$key.
' ('.$reloffile.
') found, we do nothing.';
1248 print
'<tr><td>No active module with missing files found by searching on MAIN_MODULE_(.*)_'.strtoupper($key).
'</td></tr>';
1258if ($ok &&
GETPOST(
'clean_perm_table',
'alpha')) {
1259 print
'<tr><td colspan="2"><br>*** Clean table user_rights from lines of external modules no more enabled</td></tr>';
1262 foreach (
$conf->modules as $key => $val) {
1263 $listofmods .= ($listofmods ?
',' :
'').
"'".$db->escape($val).
"'";
1266 $sql =
"SELECT id, libelle as label, module from ".MAIN_DB_PREFIX.
"rights_def WHERE module NOT IN (".$db->sanitize($listofmods, 1).
") AND id > 100000";
1268 $resql = $db->query($sql);
1270 $num = $db->num_rows($resql);
1274 $obj = $db->fetch_object($resql);
1276 print
'<tr><td>Found line with id '.$obj->id.
', label "'.$obj->label.
'" of module "'.$obj->module.
'" to delete';
1277 if (
GETPOST(
'clean_perm_table',
'alpha') ==
'confirmed') {
1278 $sqldelete =
"DELETE FROM ".MAIN_DB_PREFIX.
"rights_def WHERE id = ".((int) $obj->id);
1279 $resqldelete = $db->query($sqldelete);
1280 if (!$resqldelete) {
1290 print
'<tr><td>No lines of a disabled external module (with id > 100000) found into table rights_def</td></tr>';
1299if ($ok &&
GETPOST(
'clean_ecm_files_table',
'alpha')) {
1300 print
'<tr><td colspan="2"><br>*** Clean table ecm_files from lines of entries whose physical files does not exists anymore (emplemented for entity 1 only)</td></tr>';
1304 $sql =
"SELECT rowid, filename, filepath, entity from ".MAIN_DB_PREFIX.
"ecm_files";
1305 $sql .=
" WHERE entity = 1";
1306 $sql .=
" ORDER BY rowid ASC";
1309 $nbfiletodelete = 0;
1311 $resql = $db->query($sql);
1313 $num = $db->num_rows($resql);
1317 $obj = $db->fetch_object($resql);
1318 if ($obj->rowid > 0) {
1319 $filetocheck = DOL_DATA_ROOT.
'/'.$obj->filepath.
'/'.$obj->filename;
1323 if ($nbfiletodelete <= $MAXTODELETE) {
1324 print
'<tr><td>Found line with id '.$obj->rowid.
', entity '.$obj->entity.
', file "'.$filetocheck.
'" to delete';
1325 if (
GETPOST(
'clean_ecm_files_table',
'alpha') ==
'confirmed') {
1326 $sqldelete =
"DELETE FROM ".MAIN_DB_PREFIX.
"ecm_files WHERE rowid = ".((int) $obj->rowid);
1327 $resqldelete = $db->query($sqldelete);
1328 if (!$resqldelete) {
1342 if ($nbfiletodelete > $MAXTODELETE) {
1343 print
'<tr><td>There is more than '.$MAXTODELETE.
' invalid entries into ecm_files index table (among '.$nbfile.
' analyzed) with no valid physical files. Run the page several time to process all of them.</td></tr>';
1345 print
'<tr><td>Nb of entries processed into ecm_files index table: '.$nbfile.
', number of invalid record: '.$nbfiletodelete.
'</td></tr>';
1353if ($ok &&
GETPOST(
'force_utf8_on_tables',
'alpha')) {
1354 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>';
1356 if ($db->type ==
"mysql" || $db->type ==
"mysqli") {
1357 $force_utf8_on_tables =
GETPOST(
'force_utf8_on_tables',
'alpha');
1359 $listoftables = $db->DDLListTablesFull($db->database_name);
1362 if ($force_utf8_on_tables ==
'confirmed') {
1363 $sql =
'SET FOREIGN_KEY_CHECKS=0';
1364 print
'<!-- '.$sql.
' -->';
1365 print
'<tr><td colspan="2">'.$sql.
'</td></tr>';
1366 $resql = $db->query($sql);
1369 $foreignkeystorestore = array();
1372 foreach ($listoftables as $table) {
1374 if (
$conf->db->dolibarr_main_db_encryption != 0 && preg_match(
'/\_const$/', $table[0])) {
1377 if ($table[1] ==
'VIEW') {
1378 print
'<tr><td colspan="2">'.$table[0].
' is a '.$table[1].
' <span class="opacitymedium">(Skipped)</span></td></tr>';
1383 $arrayofforeignkey = array(
1384 'llx_accounting_account' =>
'fk_accounting_account_fk_pcg_version',
1385 'llx_accounting_system' =>
'fk_accounting_account_fk_pcg_version',
1386 'llx_c_type_contact' =>
'fk_societe_commerciaux_fk_c_type_contact_code',
1387 'llx_societe_commerciaux' =>
'fk_societe_commerciaux_fk_c_type_contact_code'
1390 foreach ($arrayofforeignkey as $tmptable => $foreignkeyname) {
1391 if ($table[0] == $tmptable) {
1392 print
'<tr><td colspan="2">';
1393 $sqltmp =
"ALTER TABLE ".$db->sanitize($table[0]).
" DROP FOREIGN KEY ".$db->sanitize($foreignkeyname);
1395 if ($force_utf8_on_tables ==
'confirmed') {
1396 $resqltmp = $db->query($sqltmp);
1398 print
' - <span class="opacitymedium">Disabled</span>';
1401 $foreignkeystorestore[$tmptable] = $foreignkeyname;
1406 foreach ($listoftables as $table) {
1408 if (
$conf->db->dolibarr_main_db_encryption != 0 && preg_match(
'/\_const$/', $table[0])) {
1411 if ($table[1] ==
'VIEW') {
1412 print
'<tr><td colspan="2">'.$table[0].
' is a '.$table[1].
' <span class="opacitymedium">(Skipped)</span></td></tr>';
1416 $collation =
'utf8_unicode_ci';
1417 $defaultcollation = $db->getDefaultCollationDatabase();
1418 if (preg_match(
'/general/', $defaultcollation)) {
1419 $collation =
'utf8_general_ci';
1422 print
'<tr><td colspan="2">';
1424 $sql1 =
"ALTER TABLE ".$db->sanitize($table[0]).
" ROW_FORMAT=dynamic";
1425 $sql2 =
"ALTER TABLE ".$db->sanitize($table[0]).
" CONVERT TO CHARACTER SET utf8 COLLATE ".$db->sanitize($collation);
1426 print
'<!-- '.$sql1.
' -->';
1427 print
'<!-- '.$sql2.
' -->';
1428 if ($force_utf8_on_tables ==
'confirmed') {
1429 $resql1 = $db->query($sql1);
1431 $resql2 = $db->query($sql2);
1435 print
' - Done '.(($resql1 && $resql2) ?
'<span class="opacitymedium">(OK)</span>' :
'<span class="error" title="'.
dol_escape_htmltag($db->lasterror).
'">(KO)</span>');
1437 print
' - <span class="opacitymedium">Disabled</span>';
1445 foreach ($foreignkeystorestore as $tmptable => $foreignkeyname) {
1446 $stringtofindinline =
"ALTER TABLE .* ADD CONSTRAINT ".$db->sanitize($foreignkeyname);
1447 $fileforkeys = DOL_DOCUMENT_ROOT.
'/install/mysql/tables/'.$tmptable.
'.key.sql';
1450 $handle = fopen($fileforkeys,
'r');
1452 while (($line = fgets($handle)) !==
false) {
1454 if (preg_match(
'/^'.$stringtofindinline.
'/i', $line)) {
1455 $resqltmp = $db->query($line);
1456 print
'<tr><td colspan="2">';
1458 print
' - Done '.($resqltmp ?
'<span class="opacitymedium">(OK)</span>' :
'<span class="error" title="'.dol_escape_htmltag($db->lasterror).
'">(KO)</span>');
1470 if ($force_utf8_on_tables ==
'confirmed') {
1471 $sql =
'SET FOREIGN_KEY_CHECKS=1';
1472 print
'<!-- '.$sql.
' -->';
1473 print
'<tr><td colspan="2">'.$sql.
'</td></tr>';
1474 $resql = $db->query($sql);
1477 print
'<tr><td colspan="2">Not available with database type '.$db->type.
'</td></tr>';
1482if ($ok &&
GETPOST(
'force_utf8mb4_on_tables',
'alpha')) {
1483 print
'<tr><td colspan="2"><br>*** Force page code and collation of tables into utf8mb4/utf8mb4_unicode_ci (for mysql/mariadb only)</td></tr>';
1485 if ($db->type ==
"mysql" || $db->type ==
"mysqli") {
1486 $force_utf8mb4_on_tables =
GETPOST(
'force_utf8mb4_on_tables',
'alpha');
1489 $listoftables = $db->DDLListTablesFull($db->database_name);
1492 if ($force_utf8mb4_on_tables ==
'confirmed') {
1493 $sql =
'SET FOREIGN_KEY_CHECKS=0';
1494 print
'<!-- '.$sql.
' -->';
1495 print
'<tr><td colspan="2">'.$sql.
'</td></tr>';
1496 $resql = $db->query($sql);
1499 $foreignkeystorestore = array();
1502 foreach ($listoftables as $table) {
1504 if (
$conf->db->dolibarr_main_db_encryption != 0 && preg_match(
'/\_const$/', $table[0])) {
1507 if ($table[1] ==
'VIEW') {
1508 print
'<tr><td colspan="2">'.$table[0].
' is a '.$table[1].
' <span class="opacitymedium">(Skipped)</span></td></tr>';
1513 $arrayofforeignkey = array(
1514 'llx_accounting_account' =>
'fk_accounting_account_fk_pcg_version',
1515 'llx_accounting_system' =>
'fk_accounting_account_fk_pcg_version',
1516 'llx_c_type_contact' =>
'fk_societe_commerciaux_fk_c_type_contact_code',
1517 'llx_societe_commerciaux' =>
'fk_societe_commerciaux_fk_c_type_contact_code'
1520 foreach ($arrayofforeignkey as $tmptable => $foreignkeyname) {
1521 if ($table[0] == $tmptable) {
1522 print
'<tr><td colspan="2">';
1523 $sqltmp =
"ALTER TABLE ".$db->sanitize($table[0]).
" DROP FOREIGN KEY ".$db->sanitize($foreignkeyname);
1525 if ($force_utf8mb4_on_tables ==
'confirmed') {
1526 $resqltmp = $db->query($sqltmp);
1528 print
' - <span class="opacitymedium">Disabled</span>';
1531 $foreignkeystorestore[$tmptable] = $foreignkeyname;
1536 foreach ($listoftables as $table) {
1538 if (
$conf->db->dolibarr_main_db_encryption != 0 && preg_match(
'/\_const$/', $table[0])) {
1541 if ($table[1] ==
'VIEW') {
1542 print
'<tr><td colspan="2">'.$table[0].
' is a '.$table[1].
' <span class="opacitymedium">(Skipped)</span></td></tr>';
1546 $collation =
'utf8mb4_unicode_ci';
1547 $defaultcollation = $db->getDefaultCollationDatabase();
1548 if (preg_match(
'/general/', $defaultcollation)) {
1549 $collation =
'utf8mb4_general_ci';
1552 print
'<tr><td colspan="2">';
1554 $sql1 =
"ALTER TABLE ".$db->sanitize($table[0]).
" ROW_FORMAT=dynamic";
1555 $sql2 =
"ALTER TABLE ".$db->sanitize($table[0]).
" CONVERT TO CHARACTER SET utf8mb4 COLLATE ".$db->sanitize($collation);
1556 print
'<!-- '.$sql1.
' -->';
1557 print
'<!-- '.$sql2.
' -->';
1558 if ($force_utf8mb4_on_tables ==
'confirmed') {
1559 $resql1 = $db->query($sql1);
1561 $resql2 = $db->query($sql2);
1565 print
' - Done '.(($resql1 && $resql2) ?
'<span class="opacitymedium">(OK)</span>' :
'<span class="error" title="'.
dol_escape_htmltag($db->lasterror).
'">(KO)</span>');
1567 print
' - <span class="opacitymedium">Disabled</span>';
1575 foreach ($foreignkeystorestore as $tmptable => $foreignkeyname) {
1576 $stringtofindinline =
"ALTER TABLE .* ADD CONSTRAINT ".$db->sanitize($foreignkeyname);
1577 $fileforkeys = DOL_DOCUMENT_ROOT.
'/install/mysql/tables/'.$tmptable.
'.key.sql';
1580 $handle = fopen($fileforkeys,
'r');
1582 while (($line = fgets($handle)) !==
false) {
1584 if (preg_match(
'/^'.$stringtofindinline.
'/i', $line)) {
1585 $resqltmp = $db->query($line);
1586 print
'<tr><td colspan="2">';
1588 print
' - Done '.($resqltmp ?
'<span class="opacitymedium">(OK)</span>' :
'<span class="error" title="'.dol_escape_htmltag($db->lasterror).
'">(KO)</span>');
1600 if ($force_utf8mb4_on_tables ==
'confirmed') {
1601 $sql =
'SET FOREIGN_KEY_CHECKS=1';
1602 print
'<!-- '.$sql.
' -->';
1603 print
'<tr><td colspan="2">'.$sql.
'</td></tr>';
1604 $resql = $db->query($sql);
1607 print
'<tr><td colspan="2">Not available with database type '.$db->type.
'</td></tr>';
1611if ($ok &&
GETPOST(
'force_collation_from_conf_on_tables',
'alpha')) {
1612 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>';
1614 if ($db->type ==
"mysql" || $db->type ==
"mysqli") {
1615 $force_collation_from_conf_on_tables =
GETPOST(
'force_collation_from_conf_on_tables',
'alpha');
1617 $listoftables = $db->DDLListTablesFull($db->database_name);
1620 if ($force_collation_from_conf_on_tables ==
'confirmed') {
1621 $sql =
'SET FOREIGN_KEY_CHECKS=0';
1622 print
'<!-- '.$sql.
' -->';
1623 $resql = $db->query($sql);
1626 foreach ($listoftables as $table) {
1628 if (
$conf->db->dolibarr_main_db_encryption != 0 && preg_match(
'/\_const$/', $table[0])) {
1631 if ($table[1] ==
'VIEW') {
1632 print
'<tr><td colspan="2">'.$table[0].
' is a '.$table[1].
' (Skipped)</td></tr>';
1636 print
'<tr><td colspan="2">';
1638 $sql1 =
"ALTER TABLE ".$table[0].
" ROW_FORMAT=dynamic";
1639 $sql2 =
"ALTER TABLE ".$table[0].
" CONVERT TO CHARACTER SET ".
$conf->db->character_set.
" COLLATE ".
$conf->db->dolibarr_main_db_collation;
1640 print
'<!-- '.$sql1.
' -->';
1641 print
'<!-- '.$sql2.
' -->';
1642 if ($force_collation_from_conf_on_tables ==
'confirmed') {
1643 $resql1 = $db->query($sql1);
1645 $resql2 = $db->query($sql2);
1649 print
' - Done '.(($resql1 && $resql2) ?
'<span class="opacitymedium">(OK)</span>' :
'<span class="error" title="'.
dol_escape_htmltag($db->lasterror).
'">(KO)</span>');
1651 print
' - <span class="opacitymedium">Disabled</span>';
1657 if ($force_collation_from_conf_on_tables ==
'confirmed') {
1658 $sql =
'SET FOREIGN_KEY_CHECKS=1';
1659 print
'<!-- '.$sql.
' -->';
1660 $resql = $db->query($sql);
1663 print
'<tr><td colspan="2">Not available with database type '.$db->type.
'</td></tr>';
1668if ($ok &&
GETPOST(
'rebuild_sequences',
'alpha')) {
1669 print
'<tr><td colspan="2"><br>*** Force to rebuild sequences (for postgresql only)</td></tr>';
1671 if ($db->type ==
"pgsql") {
1672 $rebuild_sequence =
GETPOST(
'rebuild_sequences',
'alpha');
1674 if ($rebuild_sequence ==
'confirmed') {
1675 $sql =
"SELECT dol_util_rebuild_sequences();";
1676 print
'<!-- '.$sql.
' -->';
1677 $resql = $db->query($sql);
1680 print
'<tr><td colspan="2">Not available with database type '.$db->type.
'</td></tr>';
1685if ($ok &&
GETPOST(
'repair_link_dispatch_lines_supplier_order_lines')) {
1709 $repair_link_dispatch_lines_supplier_order_lines =
GETPOST(
'repair_link_dispatch_lines_supplier_order_lines',
'alpha');
1712 echo
'<tr><th>Repair llx_receptiondet_batch.fk_commandefourndet</th></tr>';
1713 echo
'<tr><td>Repair in progress. This may take a while.</td></tr>';
1715 $sql_dispatch =
'SELECT * FROM '.MAIN_DB_PREFIX.
'receptiondet_batch WHERE COALESCE(fk_elementdet, 0) = 0';
1717 $resql_dispatch = $db->query($sql_dispatch);
1718 $n_processed_rows = 0;
1720 if ($resql_dispatch) {
1721 if ($db->num_rows($resql_dispatch) == 0) {
1722 echo
'<tr><td>Nothing to do.</td></tr>';
1725 while ($obj_dispatch = $db->fetch_object($resql_dispatch)) {
1726 $sql_line =
'SELECT line.rowid, line.qty FROM '.MAIN_DB_PREFIX.
'commande_fournisseurdet AS line';
1727 $sql_line .=
' WHERE line.fk_commande = '.((int) $obj_dispatch->fk_commande);
1728 $sql_line .=
' AND line.fk_product = '.((int) $obj_dispatch->fk_product);
1729 $resql_line = $db->query($sql_line);
1735 $remaining_qty = $obj_dispatch->qty;
1736 $first_iteration =
true;
1738 echo
'<tr><td>Unable to find a matching supplier order line for dispatch #'.$obj_dispatch->rowid.
'</td></tr>';
1739 $errors[] = $sql_line;
1740 $n_processed_rows++;
1743 if ($db->num_rows($resql_line) == 0) {
1746 while ($obj_line = $db->fetch_object($resql_line)) {
1747 if (!$remaining_qty) {
1750 if (!$obj_line->rowid) {
1753 $qty_for_line = min($remaining_qty, $obj_line->qty);
1754 if ($first_iteration) {
1755 $sql_attach =
'UPDATE '.MAIN_DB_PREFIX.
'receptiondet_batch';
1756 $sql_attach .=
' SET fk_elementdet = '.((int) $obj_line->rowid).
', qty = '.((float) $qty_for_line);
1757 $sql_attach .=
' WHERE rowid = '.((int) $obj_dispatch->rowid);
1758 $first_iteration =
false;
1760 $sql_attach_values = array(
1761 (
string) ((
int) $obj_dispatch->fk_element),
1762 (
string) ((
int) $obj_dispatch->fk_product),
1763 (
string) ((
int) $obj_line->rowid),
1764 (
string) ((
float) $qty_for_line),
1765 (
string) ((
int) $obj_dispatch->fk_entrepot),
1766 (
string) ((
int) $obj_dispatch->fk_user),
1767 $obj_dispatch->datec ?
"'".$db->idate($db->jdate($obj_dispatch->datec)).
"'" :
'NULL',
1768 $obj_dispatch->comment ?
"'".$db->escape($obj_dispatch->comment).
"'" :
'NULL',
1769 $obj_dispatch->
status ? (string) ((int) $obj_dispatch->
status) :
'NULL',
1770 $obj_dispatch->tms ?
"'".$db->idate($db->jdate($obj_dispatch->tms)).
"'" :
'NULL',
1771 $obj_dispatch->batch ?
"'".$db->escape($obj_dispatch->batch).
"'" :
'NULL',
1772 $obj_dispatch->eatby ?
"'".$db->escape($obj_dispatch->eatby).
"'" :
'NULL',
1773 $obj_dispatch->sellby ?
"'".$db->escape($obj_dispatch->sellby).
"'" :
'NULL'
1775 $sql_attach_values = implode(
', ', $sql_attach_values);
1777 $sql_attach =
'INSERT INTO '.MAIN_DB_PREFIX.
'receptiondet_batch';
1778 $sql_attach .=
' (fk_element, fk_product, fk_elementdet, qty, fk_entrepot, fk_user, datec, comment, status, tms, batch, eatby, sellby)';
1779 $sql_attach .=
" VALUES (".$sql_attach_values.
")";
1782 if ($repair_link_dispatch_lines_supplier_order_lines ==
'confirmed') {
1783 $resql_attach = $db->query($sql_attach);
1785 $resql_attach =
true;
1788 if ($resql_attach) {
1789 $remaining_qty -= $qty_for_line;
1791 $errors[] = $sql_attach;
1794 $first_iteration =
false;
1796 $n_processed_rows++;
1799 if (!($n_processed_rows & 0xff)) {
1800 echo
'<tr><td>Processed '.$n_processed_rows.
' rows with '.count($errors).
' errors…'.
"</td></tr>\n";
1806 echo
'<tr><td>Unable to find any dispatch without an fk_commandefourndet.'.
"</td></tr>\n";
1807 echo $sql_dispatch.
"\n";
1809 echo
'<tr><td>Fixed '.$n_processed_rows.
' rows with '.count($errors).
' errors…'.
"</td></tr>\n";
1810 echo
'<tr><td>DONE.'.
"</td></tr>\n";
1812 if (count($errors)) {
1814 echo
'<tr><td>The transaction was rolled back due to errors: nothing was changed by the script.</td></tr>';
1820 echo
'<tr><td><h3>SQL queries with errors:</h3></tr></td>';
1821 echo
'<tr><td>'.implode(
'</td></tr><tr><td>', $errors).
'</td></tr>';
1825if ($ok &&
GETPOST(
'repair_supplier_order_duplicate_ref')) {
1826 require_once DOL_DOCUMENT_ROOT .
'/fourn/class/fournisseur.commande.class.php';
1827 include_once DOL_DOCUMENT_ROOT .
'/societe/class/societe.class.php';
1834 $sql =
"SELECT * FROM " . MAIN_DB_PREFIX .
"commande_fournisseur";
1835 $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)";
1838 $duplicateSupplierOrders = [];
1839 $resql = $db->query($sql);
1841 while ($rawSupplierOrder = $db->fetch_object($resql)) {
1843 $supplierOrder->setVarsFromFetchObj($rawSupplierOrder);
1845 $duplicateSupplierOrders[$rawSupplierOrder->ref] [] = $supplierOrder;
1852 foreach ($duplicateSupplierOrders as $ref => $supplierOrders) {
1854 foreach (array_slice($supplierOrders, 1) as $supplierOrder) {
1857 $soc->fetch($supplierOrder->fourn_id);
1859 $newRef = $supplierOrder->getNextNumRef($soc);
1861 $sql =
"UPDATE " . MAIN_DB_PREFIX .
"commande_fournisseur cf SET cf.ref = '" . $db->escape($newRef) .
"' WHERE cf.rowid = " . (int) $supplierOrder->id;
1862 if (!$db->query($sql)) {
1878if ($ok &&
GETPOST(
'recalculateinvoicetotal') ==
'confirmed') {
1881 $sql =
"SELECT f.rowid, SUM(fd.total_ht) as total_ht";
1882 $sql .=
" FROM ".MAIN_DB_PREFIX.
"facture f";
1883 $sql .=
" LEFT JOIN ".MAIN_DB_PREFIX.
"facturedet fd ON fd.fk_facture = f.rowid";
1884 $sql .=
" WHERE f.total_ht = 0";
1885 $sql .=
" GROUP BY fd.fk_facture HAVING SUM(fd.total_ht) <> 0";
1887 $resql = $db->query($sql);
1889 $num = $db->num_rows($resql);
1890 print
"We found ".$num.
" factures qualified that will have their total recalculated because they are at zero and line items not at zero\n";
1891 dol_syslog(
"We found ".$num.
" factures qualified that will have their total recalculated because they are at zero and line items not at zero");
1896 $obj = $db->fetch_object($resql);
1899 SUM(fd.total_ht) as 'total_ht',
1900 SUM(fd.total_tva) as 'total_tva',
1901 SUM(fd.total_localtax1) as 'localtax1',
1902 SUM(fd.total_localtax2) as 'localtax2',
1903 SUM(fd.total_ttc) as 'total_ttc'
1905 ".MAIN_DB_PREFIX.
"facturedet fd
1907 fd.fk_facture = $obj->rowid";
1908 $ressql_calculs = $db->query($sql_calculs);
1909 while ($obj_calcul = $db->fetch_object($ressql_calculs)) {
1911 UPDATE ".MAIN_DB_PREFIX.
"facture
1913 total_ht = ".($obj_calcul->total_ht ?
price2num($obj_calcul->total_ht,
'MT') : 0).
",
1914 total_tva = ".($obj_calcul->total_tva ?
price2num($obj_calcul->total_tva,
'MT') : 0).
",
1915 localtax1 = ".($obj_calcul->localtax1 ?
price2num($obj_calcul->localtax1,
'MT') : 0).
",
1916 localtax2 = ".($obj_calcul->localtax2 ?
price2num($obj_calcul->localtax2,
'MT') : 0).
",
1917 total_ttc = ".($obj_calcul->total_ttc ?
price2num($obj_calcul->total_ttc,
'MT') : 0).
"
1919 rowid = $obj->rowid";
1920 $db->query($sql_maj);
1925 print
"Pas de factures à traiter\n";
1929 dol_syslog(
"calculate_total_and_taxes.php: Error");
1942if (empty($actiondone)) {
1943 print
'<div class="error">'.$langs->trans(
"ErrorWrongParameters").
'</div>';
1947 print
'<div class="center" style="padding-top: 10px"><a href="../index.php?mainmenu=home&leftmenu=home'.(GETPOSTISSET(
"login") ?
'&username='.urlencode(
GETPOST(
"login")) :
'').
'">';
1948 print $langs->trans(
"GoToDolibarr");
1955if ($db->connected) {
1960if (!$ok && isset($argv[1])) {
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 suppliers invoices.
Class to manage invoices.
Class to manage proposals.
Class to manage third parties objects (customers, suppliers, prospects...)
print $langs trans("Ref").' m titre as m m statut as status
Or an array listing all the potential status of the object: array: int of the status => translated la...
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.
global $conf
The following vars must be defined: $type2label $form $conf, $lang, The following vars may also be de...
clean_data_ecm_directories()
Clean data into ecm_directories table.
dol_decode($chain, $key='1')
Decode a base 64 encoded + specific delta change.