1<?php 2/* Copyright (C) 2008-2011 Laurent Destailleur <eldy@users.sourceforge.net> 3 * Copyright (C) 2005-2016 Regis Houssin <regis.houssin@inodbox.com> 4 * Copyright (C) 2012 J. Fernando Lagrange <fernando@demo-tic.org> 5 * Copyright (C) 2015 Raphaël Doursenaud <rdoursenaud@gpcsolutions.fr> 6 * 7 * This program is free software; you can redistribute it and/or modify 8 * it under the terms of the GNU General Public License as published by 9 * the Free Software Foundation; either version 3 of the License, or 10 * (at your option) any later version. 11 * 12 * This program is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 * GNU General Public License for more details. 16 * 17 * You should have received a copy of the GNU General Public License 18 * along with this program. If not, see <https://www.gnu.org/licenses/>. 19 * or see https://www.gnu.org/ 20 */ 21 22/** 23 * \file htdocs/core/lib/admin.lib.php 24 * \brief Library of admin functions 25 */ 26 27require_once DOL_DOCUMENT_ROOT.'/core/lib/functions2.lib.php'; 28 29/** 30 * Renvoi une version en chaine depuis une version en tableau 31 * 32 * @param array $versionarray Tableau de version (vermajeur,vermineur,autre) 33 * @return string Chaine version 34 * @see versioncompare() 35 */ 36function versiontostring($versionarray) 37{ 38 $string = '?'; 39 if (isset($versionarray[0])) { 40 $string = $versionarray[0]; 41 } 42 if (isset($versionarray[1])) { 43 $string .= '.'.$versionarray[1]; 44 } 45 if (isset($versionarray[2])) { 46 $string .= '.'.$versionarray[2]; 47 } 48 return $string; 49} 50 51/** 52 * Compare 2 versions (stored into 2 arrays). 53 * To check if Dolibarr version is lower than (x,y,z), do "if versioncompare(versiondolibarrarray(), array(x.y.z)) <= 0" 54 * For example: if (versioncompare(versiondolibarrarray(),array(4,0,-5)) >= 0) is true if version is 4.0 alpha or higher. 55 * For example: if (versioncompare(versiondolibarrarray(),array(4,0,0)) >= 0) is true if version is 4.0 final or higher. 56 * For example: if (versioncompare(versiondolibarrarray(),array(4,0,1)) >= 0) is true if version is 4.0.1 or higher. 57 * Alternative way to compare: if ((float) DOL_VERSION >= 4.0) is true if version is 4.0 alpha or higher (works only to compare first and second level) 58 * 59 * @param array $versionarray1 Array of version (vermajor,verminor,patch) 60 * @param array $versionarray2 Array of version (vermajor,verminor,patch) 61 * @return int -4,-3,-2,-1 if versionarray1<versionarray2 (value depends on level of difference) 62 * 0 if same 63 * 1,2,3,4 if versionarray1>versionarray2 (value depends on level of difference) 64 * @see versiontostring() 65 */ 66function versioncompare($versionarray1, $versionarray2) 67{ 68 $ret = 0; 69 $level = 0; 70 $count1 = count($versionarray1); 71 $count2 = count($versionarray2); 72 $maxcount = max($count1, $count2); 73 while ($level < $maxcount) { 74 $operande1 = isset($versionarray1[$level]) ? $versionarray1[$level] : 0; 75 $operande2 = isset($versionarray2[$level]) ? $versionarray2[$level] : 0; 76 if (preg_match('/alpha|dev/i', $operande1)) { 77 $operande1 = -5; 78 } 79 if (preg_match('/alpha|dev/i', $operande2)) { 80 $operande2 = -5; 81 } 82 if (preg_match('/beta$/i', $operande1)) { 83 $operande1 = -4; 84 } 85 if (preg_match('/beta$/i', $operande2)) { 86 $operande2 = -4; 87 } 88 if (preg_match('/beta([0-9])+/i', $operande1)) { 89 $operande1 = -3; 90 } 91 if (preg_match('/beta([0-9])+/i', $operande2)) { 92 $operande2 = -3; 93 } 94 if (preg_match('/rc$/i', $operande1)) { 95 $operande1 = -2; 96 } 97 if (preg_match('/rc$/i', $operande2)) { 98 $operande2 = -2; 99 } 100 if (preg_match('/rc([0-9])+/i', $operande1)) { 101 $operande1 = -1; 102 } 103 if (preg_match('/rc([0-9])+/i', $operande2)) { 104 $operande2 = -1; 105 } 106 $level++; 107 //print 'level '.$level.' '.$operande1.'-'.$operande2.'<br>'; 108 if ($operande1 < $operande2) { 109 $ret = -$level; break; 110 } 111 if ($operande1 > $operande2) { 112 $ret = $level; break; 113 } 114 } 115 //print join('.',$versionarray1).'('.count($versionarray1).') / '.join('.',$versionarray2).'('.count($versionarray2).') => '.$ret.'<br>'."\n"; 116 return $ret; 117} 118 119 120/** 121 * Return version PHP 122 * 123 * @return array Tableau de version (vermajeur,vermineur,autre) 124 */ 125function versionphparray() 126{ 127 return explode('.', PHP_VERSION); 128} 129 130/** 131 * Return version Dolibarr 132 * 133 * @return array Tableau de version (vermajeur,vermineur,autre) 134 */ 135function versiondolibarrarray() 136{ 137 return explode('.', DOL_VERSION); 138} 139 140 141/** 142 * Launch a sql file. Function is used by: 143 * - Migrate process (dolibarr-xyz-abc.sql) 144 * - Loading sql menus (auguria) 145 * - Running specific Sql by a module init 146 * - Loading sql file of website import package 147 * Install process however does not use it. 148 * Note that Sql files must have all comments at start of line. Also this function take ';' as the char to detect end of sql request 149 * 150 * @param string $sqlfile Full path to sql file 151 * @param int $silent 1=Do not output anything, 0=Output line for update page 152 * @param int $entity Entity targeted for multicompany module 153 * @param int $usesavepoint 1=Run a savepoint before each request and a rollback to savepoint if error (this allow to have some request with errors inside global transactions). 154 * @param string $handler Handler targeted for menu (replace __HANDLER__ with this value) 155 * @param string $okerror Family of errors we accept ('default', 'none') 156 * @param int $linelengthlimit Limit for length of each line (Use 0 if unknown, may be faster if defined) 157 * @param int $nocommentremoval Do no try to remove comments (in such a case, we consider that each line is a request, so use also $linelengthlimit=0) 158 * @param int $offsetforchartofaccount Offset to use to load chart of account table to update sql on the fly to add offset to rowid and account_parent value 159 * @return int <=0 if KO, >0 if OK 160 */ 161function run_sql($sqlfile, $silent = 1, $entity = '', $usesavepoint = 1, $handler = '', $okerror = 'default', $linelengthlimit = 32768, $nocommentremoval = 0, $offsetforchartofaccount = 0) 162{ 163 global $db, $conf, $langs, $user; 164 165 dol_syslog("Admin.lib::run_sql run sql file ".$sqlfile." silent=".$silent." entity=".$entity." usesavepoint=".$usesavepoint." handler=".$handler." okerror=".$okerror, LOG_DEBUG); 166 167 if (!is_numeric($linelengthlimit)) { 168 dol_syslog("Admin.lib::run_sql param linelengthlimit is not a numeric", LOG_ERR); 169 return -1; 170 } 171 172 $ok = 0; 173 $error = 0; 174 $i = 0; 175 $buffer = ''; 176 $arraysql = array(); 177 178 // Get version of database 179 $versionarray = $db->getVersionArray(); 180 181 $fp = fopen($sqlfile, "r"); 182 if ($fp) { 183 while (!feof($fp)) { 184 // Warning fgets with second parameter that is null or 0 hang. 185 if ($linelengthlimit > 0) { 186 $buf = fgets($fp, $linelengthlimit); 187 } else { 188 $buf = fgets($fp); 189 } 190 191 // Test if request must be ran only for particular database or version (if yes, we must remove the -- comment) 192 $reg = array(); 193 if (preg_match('/^--\sV(MYSQL|PGSQL)([^\s]*)/i', $buf, $reg)) { 194 $qualified = 1; 195 196 // restrict on database type 197 if (!empty($reg[1])) { 198 if (!preg_match('/'.preg_quote($reg[1]).'/i', $db->type)) { 199 $qualified = 0; 200 } 201 } 202 203 // restrict on version 204 if ($qualified) { 205 if (!empty($reg[2])) { 206 if (is_numeric($reg[2])) { // This is a version 207 $versionrequest = explode('.', $reg[2]); 208 //print var_dump($versionrequest); 209 //print var_dump($versionarray); 210 if (!count($versionrequest) || !count($versionarray) || versioncompare($versionrequest, $versionarray) > 0) { 211 $qualified = 0; 212 } 213 } else // This is a test on a constant. For example when we have -- VMYSQLUTF8UNICODE, we test constant $conf->global->UTF8UNICODE 214 { 215 $dbcollation = strtoupper(preg_replace('/_/', '', $conf->db->dolibarr_main_db_collation)); 216 //var_dump($reg[2]); 217 //var_dump($dbcollation); 218 if (empty($conf->db->dolibarr_main_db_collation) || ($reg[2] != $dbcollation)) { 219 $qualified = 0; 220 } 221 //var_dump($qualified); 222 } 223 } 224 } 225 226 if ($qualified) { 227 // Version qualified, delete SQL comments 228 $buf = preg_replace('/^--\sV(MYSQL|PGSQL)([^\s]*)/i', '', $buf); 229 //print "Ligne $i qualifi?e par version: ".$buf.'<br>'; 230 } 231 } 232 233 // Add line buf to buffer if not a comment 234 if ($nocommentremoval || !preg_match('/^\s*--/', $buf)) { 235 if (empty($nocommentremoval)) { 236 $buf = preg_replace('/([,;ERLT\)])\s*--.*$/i', '\1', $buf); //remove comment from a line that not start with -- before add it to the buffer 237 } 238 $buffer .= trim($buf); 239 } 240 241 //print $buf.'<br>';exit; 242 243 if (preg_match('/;/', $buffer)) { // If string contains ';', it's end of a request string, we save it in arraysql. 244 // Found new request 245 if ($buffer) { 246 $arraysql[$i] = $buffer; 247 } 248 $i++; 249 $buffer = ''; 250 } 251 } 252 253 if ($buffer) { 254 $arraysql[$i] = $buffer; 255 } 256 fclose($fp); 257 } else { 258 dol_syslog("Admin.lib::run_sql failed to open file ".$sqlfile, LOG_ERR); 259 } 260 261 // Loop on each request to see if there is a __+MAX_table__ key 262 $listofmaxrowid = array(); // This is a cache table 263 foreach ($arraysql as $i => $sql) { 264 $newsql = $sql; 265 266 // Replace __+MAX_table__ with max of table 267 while (preg_match('/__\+MAX_([A-Za-z0-9_]+)__/i', $newsql, $reg)) { 268 $table = $reg[1]; 269 if (!isset($listofmaxrowid[$table])) { 270 //var_dump($db); 271 $sqlgetrowid = 'SELECT MAX(rowid) as max from '.preg_replace('/^llx_/', MAIN_DB_PREFIX, $table); 272 $resql = $db->query($sqlgetrowid); 273 if ($resql) { 274 $obj = $db->fetch_object($resql); 275 $listofmaxrowid[$table] = $obj->max; 276 if (empty($listofmaxrowid[$table])) { 277 $listofmaxrowid[$table] = 0; 278 } 279 } else { 280 if (!$silent) { 281 print '<tr><td class="tdtop" colspan="2">'; 282 } 283 if (!$silent) { 284 print '<div class="error">'.$langs->trans("Failed to get max rowid for ".$table)."</div></td>"; 285 } 286 if (!$silent) { 287 print '</tr>'; 288 } 289 $error++; 290 break; 291 } 292 } 293 // Replace __+MAX_llx_table__ with +999 294 $from = '__+MAX_'.$table.'__'; 295 $to = '+'.$listofmaxrowid[$table]; 296 $newsql = str_replace($from, $to, $newsql); 297 dol_syslog('Admin.lib::run_sql New Request '.($i + 1).' (replacing '.$from.' to '.$to.')', LOG_DEBUG); 298 299 $arraysql[$i] = $newsql; 300 } 301 302 if ($offsetforchartofaccount > 0) { 303 // Replace lines 304 // 'INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 1401, 'PCG99-ABREGE', 'CAPIT', '1234', 1400, '...', 1);' 305 // with 306 // 'INSERT INTO llx_accounting_account (entity, rowid, fk_pcg_version, pcg_type, account_number, account_parent, label, active) VALUES (__ENTITY__, 1401 + 200100000, 'PCG99-ABREGE','CAPIT', '1234', 1400 + 200100000, '...', 1);' 307 // Note: string with 1234 instead of '1234' is also supported 308 $newsql = preg_replace('/VALUES\s*\(__ENTITY__, \s*(\d+)\s*,(\s*\'[^\',]*\'\s*,\s*\'[^\',]*\'\s*,\s*\'?[^\',]*\'?\s*),\s*\'?([^\',]*)\'?/ims', 'VALUES (__ENTITY__, \1 + '.$offsetforchartofaccount.', \2, \3 + '.$offsetforchartofaccount, $newsql); 309 $newsql = preg_replace('/([,\s])0 \+ '.$offsetforchartofaccount.'/ims', '\1 0', $newsql); 310 //var_dump($newsql); 311 $arraysql[$i] = $newsql; 312 } 313 } 314 315 // Loop on each request to execute request 316 $cursorinsert = 0; 317 $listofinsertedrowid = array(); 318 foreach ($arraysql as $i => $sql) { 319 if ($sql) { 320 // Replace the prefix tables 321 if (MAIN_DB_PREFIX != 'llx_') { 322 $sql = preg_replace('/llx_/i', MAIN_DB_PREFIX, $sql); 323 } 324 325 if (!empty($handler)) { 326 $sql = preg_replace('/__HANDLER__/i', "'".$db->escape($handler)."'", $sql); 327 } 328 329 $newsql = preg_replace('/__ENTITY__/i', (!empty($entity) ? $entity : $conf->entity), $sql); 330 331 // Add log of request 332 if (!$silent) { 333 print '<tr class="trforrunsql"><td class="tdtop opacitymedium">'.$langs->trans("Request").' '.($i + 1)." sql='".dol_htmlentities($newsql, ENT_NOQUOTES)."'</td></tr>\n"; 334 } 335 dol_syslog('Admin.lib::run_sql Request '.($i + 1), LOG_DEBUG); 336 $sqlmodified = 0; 337 338 // Replace for encrypt data 339 if (preg_match_all('/__ENCRYPT\(\'([^\']+)\'\)__/i', $newsql, $reg)) { 340 $num = count($reg[0]); 341 342 for ($j = 0; $j < $num; $j++) { 343 $from = $reg[0][$j]; 344 $to = $db->encrypt($reg[1][$j], 1); 345 $newsql = str_replace($from, $to, $newsql); 346 } 347 $sqlmodified++; 348 } 349 350 // Replace for decrypt data 351 if (preg_match_all('/__DECRYPT\(\'([A-Za-z0-9_]+)\'\)__/i', $newsql, $reg)) { 352 $num = count($reg[0]); 353 354 for ($j = 0; $j < $num; $j++) { 355 $from = $reg[0][$j]; 356 $to = $db->decrypt($reg[1][$j]); 357 $newsql = str_replace($from, $to, $newsql); 358 } 359 $sqlmodified++; 360 } 361 362 // Replace __x__ with rowid of insert nb x 363 while (preg_match('/__([0-9]+)__/', $newsql, $reg)) { 364 $cursor = $reg[1]; 365 if (empty($listofinsertedrowid[$cursor])) { 366 if (!$silent) { 367 print '<tr><td class="tdtop" colspan="2">'; 368 } 369 if (!$silent) { 370 print '<div class="error">'.$langs->trans("FileIsNotCorrect")."</div></td>"; 371 } 372 if (!$silent) { 373 print '</tr>'; 374 } 375 $error++; 376 break; 377 } 378 $from = '__'.$cursor.'__'; 379 $to = $listofinsertedrowid[$cursor]; 380 $newsql = str_replace($from, $to, $newsql); 381 $sqlmodified++; 382 } 383 384 if ($sqlmodified) { 385 dol_syslog('Admin.lib::run_sql New Request '.($i + 1), LOG_DEBUG); 386 } 387 388 $result = $db->query($newsql, $usesavepoint); 389 if ($result) { 390 if (!$silent) { 391 print '<!-- Result = OK -->'."\n"; 392 } 393 394 if (preg_replace('/insert into ([^\s]+)/i', $newsql, $reg)) { 395 $cursorinsert++; 396 397 // It's an insert 398 $table = preg_replace('/([^a-zA-Z_]+)/i', '', $reg[1]); 399 $insertedrowid = $db->last_insert_id($table); 400 $listofinsertedrowid[$cursorinsert] = $insertedrowid; 401 dol_syslog('Admin.lib::run_sql Insert nb '.$cursorinsert.', done in table '.$table.', rowid is '.$listofinsertedrowid[$cursorinsert], LOG_DEBUG); 402 } 403 // print '<td class="right">OK</td>'; 404 } else { 405 $errno = $db->errno(); 406 if (!$silent) { 407 print '<!-- Result = '.$errno.' -->'."\n"; 408 } 409 410 // Define list of errors we accept (array $okerrors) 411 $okerrors = array( // By default 412 'DB_ERROR_TABLE_ALREADY_EXISTS', 413 'DB_ERROR_COLUMN_ALREADY_EXISTS', 414 'DB_ERROR_KEY_NAME_ALREADY_EXISTS', 415 'DB_ERROR_TABLE_OR_KEY_ALREADY_EXISTS', // PgSql use same code for table and key already exist 416 'DB_ERROR_RECORD_ALREADY_EXISTS', 417 'DB_ERROR_NOSUCHTABLE', 418 'DB_ERROR_NOSUCHFIELD', 419 'DB_ERROR_NO_FOREIGN_KEY_TO_DROP', 420 'DB_ERROR_NO_INDEX_TO_DROP', 421 'DB_ERROR_CANNOT_CREATE', // Qd contrainte deja existante 422 'DB_ERROR_CANT_DROP_PRIMARY_KEY', 423 'DB_ERROR_PRIMARY_KEY_ALREADY_EXISTS', 424 'DB_ERROR_22P02' 425 ); 426 if ($okerror == 'none') { 427 $okerrors = array(); 428 } 429 430 // Is it an error we accept 431 if (!in_array($errno, $okerrors)) { 432 if (!$silent) { 433 print '<tr><td class="tdtop" colspan="2">'; 434 } 435 if (!$silent) { 436 print '<div class="error">'.$langs->trans("Error")." ".$db->errno().": ".$newsql."<br>".$db->error()."</div></td>"; 437 } 438 if (!$silent) { 439 print '</tr>'."\n"; 440 } 441 dol_syslog('Admin.lib::run_sql Request '.($i + 1)." Error ".$db->errno()." ".$newsql."<br>".$db->error(), LOG_ERR); 442 $error++; 443 } 444 } 445 446 if (!$silent) { 447 print '</tr>'."\n"; 448 } 449 } 450 } 451 452 if (!$silent) { 453 print '<tr><td>'.$langs->trans("ProcessMigrateScript").'</td>'; 454 print '<td class="right">'; 455 if ($error == 0) { 456 print '<span class="ok">'.$langs->trans("OK").'</span>'; 457 } else { 458 print '<span class="error">'.$langs->trans("Error").'</span>'; 459 } 460 //if (! empty($conf->use_javascript_ajax)) { 461 print '<script type="text/javascript" language="javascript"> 462 jQuery(document).ready(function() { 463 function init_trrunsql() 464 { 465 console.log("toggle .trforrunsql"); 466 jQuery(".trforrunsql").toggle(); 467 } 468 init_trrunsql(); 469 jQuery(".trforrunsqlshowhide").click(function() { 470 init_trrunsql(); 471 }); 472 }); 473 </script>'; 474 print ' - <a class="trforrunsqlshowhide" href="#">'.$langs->trans("ShowHideDetails").'</a>'; 475 //} 476 print '</td></tr>'."\n"; 477 } 478 479 if ($error == 0) { 480 $ok = 1; 481 } else { 482 $ok = 0; 483 } 484 485 return $ok; 486} 487 488 489/** 490 * Effacement d'une constante dans la base de donnees 491 * 492 * @param DoliDB $db Database handler 493 * @param string $name Name of constant or rowid of line 494 * @param int $entity Multi company id, -1 for all entities 495 * @return int <0 if KO, >0 if OK 496 * 497 * @see dolibarr_get_const(), dolibarr_set_const(), dol_set_user_param() 498 */ 499function dolibarr_del_const($db, $name, $entity = 1) 500{ 501 global $conf; 502 503 if (empty($name)) { 504 dol_print_error('', 'Error call dolibar_del_const with parameter name empty'); 505 return -1; 506 } 507 508 $sql = "DELETE FROM ".MAIN_DB_PREFIX."const"; 509 $sql .= " WHERE (".$db->decrypt('name')." = '".$db->escape($name)."'"; 510 if (is_numeric($name)) { 511 $sql .= " OR rowid = '".$db->escape($name)."'"; 512 } 513 $sql .= ")"; 514 if ($entity >= 0) { 515 $sql .= " AND entity = ".$entity; 516 } 517 518 dol_syslog("admin.lib::dolibarr_del_const", LOG_DEBUG); 519 $resql = $db->query($sql); 520 if ($resql) { 521 $conf->global->$name = ''; 522 return 1; 523 } else { 524 dol_print_error($db); 525 return -1; 526 } 527} 528 529/** 530 * Recupere une constante depuis la base de donnees. 531 * 532 * @param DoliDB $db Database handler 533 * @param string $name Nom de la constante 534 * @param int $entity Multi company id 535 * @return string Valeur de la constante 536 * 537 * @see dolibarr_del_const(), dolibarr_set_const(), dol_set_user_param() 538 */ 539function dolibarr_get_const($db, $name, $entity = 1) 540{ 541 global $conf; 542 $value = ''; 543 544 $sql = "SELECT ".$db->decrypt('value')." as value"; 545 $sql .= " FROM ".MAIN_DB_PREFIX."const"; 546 $sql .= " WHERE name = ".$db->encrypt($name, 1); 547 $sql .= " AND entity = ".$entity; 548 549 dol_syslog("admin.lib::dolibarr_get_const", LOG_DEBUG); 550 $resql = $db->query($sql); 551 if ($resql) { 552 $obj = $db->fetch_object($resql); 553 if ($obj) { 554 $value = $obj->value; 555 } 556 } 557 return $value; 558} 559 560 561/** 562 * Insert a parameter (key,value) into database (delete old key then insert it again). 563 * 564 * @param DoliDB $db Database handler 565 * @param string $name Name of constant 566 * @param string $value Value of constant 567 * @param string $type Type of constante (chaine par defaut) 568 * @param int $visible Is constant visible in Setup->Other page (0 by default) 569 * @param string $note Note on parameter 570 * @param int $entity Multi company id (0 means all entities) 571 * @return int -1 if KO, 1 if OK 572 * 573 * @see dolibarr_del_const(), dolibarr_get_const(), dol_set_user_param() 574 */ 575function dolibarr_set_const($db, $name, $value, $type = 'chaine', $visible = 0, $note = '', $entity = 1) 576{ 577 global $conf; 578 579 // Clean parameters 580 $name = trim($name); 581 582 // Check parameters 583 if (empty($name)) { 584 dol_print_error($db, "Error: Call to function dolibarr_set_const with wrong parameters", LOG_ERR); 585 exit; 586 } 587 588 //dol_syslog("dolibarr_set_const name=$name, value=$value type=$type, visible=$visible, note=$note entity=$entity"); 589 590 $db->begin(); 591 592 $sql = "DELETE FROM ".MAIN_DB_PREFIX."const"; 593 $sql .= " WHERE name = ".$db->encrypt($name, 1); 594 if ($entity >= 0) { 595 $sql .= " AND entity = ".$entity; 596 } 597 598 dol_syslog("admin.lib::dolibarr_set_const", LOG_DEBUG); 599 $resql = $db->query($sql); 600 601 if (strcmp($value, '')) { // true if different. Must work for $value='0' or $value=0 602 $sql = "INSERT INTO ".MAIN_DB_PREFIX."const(name,value,type,visible,note,entity)"; 603 $sql .= " VALUES ("; 604 $sql .= $db->encrypt($name, 1); 605 $sql .= ", ".$db->encrypt($value, 1); 606 $sql .= ",'".$db->escape($type)."',".$visible.",'".$db->escape($note)."',".$entity.")"; 607 608 //print "sql".$value."-".pg_escape_string($value)."-".$sql;exit; 609 //print "xx".$db->escape($value); 610 dol_syslog("admin.lib::dolibarr_set_const", LOG_DEBUG); 611 $resql = $db->query($sql); 612 } 613 614 if ($resql) { 615 $db->commit(); 616 $conf->global->$name = $value; 617 return 1; 618 } else { 619 $error = $db->lasterror(); 620 $db->rollback(); 621 return -1; 622 } 623} 624 625 626 627 628/** 629 * Prepare array with list of tabs 630 * 631 * @return array Array of tabs to show 632 */ 633function modules_prepare_head() 634{ 635 global $langs, $conf, $user; 636 $h = 0; 637 $head = array(); 638 $mode = empty($conf->global->MAIN_MODULE_SETUP_ON_LIST_BY_DEFAULT) ? 'commonkanban' : 'common'; 639 $head[$h][0] = DOL_URL_ROOT."/admin/modules.php?mode=".$mode; 640 $head[$h][1] = $langs->trans("AvailableModules"); 641 $head[$h][2] = 'modules'; 642 $h++; 643 644 $head[$h][0] = DOL_URL_ROOT."/admin/modules.php?mode=marketplace"; 645 $head[$h][1] = $langs->trans("ModulesMarketPlaces"); 646 $head[$h][2] = 'marketplace'; 647 $h++; 648 649 $head[$h][0] = DOL_URL_ROOT."/admin/modules.php?mode=deploy"; 650 $head[$h][1] = $langs->trans("AddExtensionThemeModuleOrOther"); 651 $head[$h][2] = 'deploy'; 652 $h++; 653 654 $head[$h][0] = DOL_URL_ROOT."/admin/modules.php?mode=develop"; 655 $head[$h][1] = $langs->trans("ModulesDevelopYourModule"); 656 $head[$h][2] = 'develop'; 657 $h++; 658 659 return $head; 660} 661 662 663/** 664 * Prepare array with list of tabs 665 * 666 * @return array Array of tabs to show 667 */ 668function security_prepare_head() 669{ 670 global $db, $langs, $conf, $user; 671 $h = 0; 672 $head = array(); 673 674 $head[$h][0] = DOL_URL_ROOT."/admin/security_other.php"; 675 $head[$h][1] = $langs->trans("Miscellaneous"); 676 $head[$h][2] = 'misc'; 677 $h++; 678 679 $head[$h][0] = DOL_URL_ROOT."/admin/security.php"; 680 $head[$h][1] = $langs->trans("Passwords"); 681 $head[$h][2] = 'passwords'; 682 $h++; 683 684 $head[$h][0] = DOL_URL_ROOT."/admin/security_file.php"; 685 $head[$h][1] = $langs->trans("Files").' ('.$langs->trans("Upload").')'; 686 $head[$h][2] = 'file'; 687 $h++; 688 689 /* 690 $head[$h][0] = DOL_URL_ROOT."/admin/security_file_download.php"; 691 $head[$h][1] = $langs->trans("Files").' ('.$langs->trans("Download").')'; 692 $head[$h][2] = 'filedownload'; 693 $h++; 694 */ 695 696 $head[$h][0] = DOL_URL_ROOT."/admin/proxy.php"; 697 $head[$h][1] = $langs->trans("ExternalAccess"); 698 $head[$h][2] = 'proxy'; 699 $h++; 700 701 $head[$h][0] = DOL_URL_ROOT."/admin/events.php"; 702 $head[$h][1] = $langs->trans("Audit"); 703 $head[$h][2] = 'audit'; 704 $h++; 705 706 707 // Show permissions lines 708 $nbPerms = 0; 709 $sql = "SELECT COUNT(r.id) as nb"; 710 $sql .= " FROM ".MAIN_DB_PREFIX."rights_def as r"; 711 $sql .= " WHERE r.libelle NOT LIKE 'tou%'"; // On ignore droits "tous" 712 $sql .= " AND entity = ".$conf->entity; 713 $sql .= " AND bydefault = 1"; 714 if (empty($conf->global->MAIN_USE_ADVANCED_PERMS)) { 715 $sql .= " AND r.perms NOT LIKE '%_advance'"; // Hide advanced perms if option is not enabled 716 } 717 $resql = $db->query($sql); 718 if ($resql) { 719 $obj = $db->fetch_object($resql); 720 if ($obj) { 721 $nbPerms = $obj->nb; 722 } 723 } else { 724 dol_print_error($db); 725 } 726 727 $head[$h][0] = DOL_URL_ROOT."/admin/perms.php"; 728 $head[$h][1] = $langs->trans("DefaultRights"); 729 if ($nbPerms > 0) { 730 $head[$h][1] .= (empty($conf->global->MAIN_OPTIMIZEFORTEXTBROWSER) ? '<span class="badge marginleftonlyshort">'.$nbPerms.'</span>' : ''); 731 } 732 $head[$h][2] = 'default'; 733 $h++; 734 735 return $head; 736} 737 738/** 739 * Prepare array with list of tabs 740 * @param object $object descriptor class 741 * @return array Array of tabs to show 742 */ 743function modulehelp_prepare_head($object) 744{ 745 global $langs, $conf, $user; 746 $h = 0; 747 $head = array(); 748 749 // FIX for compatibity habitual tabs 750 $object->id = $object->numero; 751 752 $head[$h][0] = DOL_URL_ROOT."/admin/modulehelp.php?id=".$object->id.'&mode=desc'; 753 $head[$h][1] = $langs->trans("Description"); 754 $head[$h][2] = 'desc'; 755 $h++; 756 757 $head[$h][0] = DOL_URL_ROOT."/admin/modulehelp.php?id=".$object->id.'&mode=feature'; 758 $head[$h][1] = $langs->trans("TechnicalServicesProvided"); 759 $head[$h][2] = 'feature'; 760 $h++; 761 762 if ($object->isCoreOrExternalModule() == 'external') { 763 $head[$h][0] = DOL_URL_ROOT."/admin/modulehelp.php?id=".$object->id.'&mode=changelog'; 764 $head[$h][1] = $langs->trans("ChangeLog"); 765 $head[$h][2] = 'changelog'; 766 $h++; 767 } 768 769 complete_head_from_modules($conf, $langs, $object, $head, $h, 'modulehelp_admin'); 770 771 complete_head_from_modules($conf, $langs, $object, $head, $h, 'modulehelp_admin', 'remove'); 772 773 774 return $head; 775} 776/** 777 * Prepare array with list of tabs 778 * 779 * @return array Array of tabs to show 780 */ 781function translation_prepare_head() 782{ 783 global $langs, $conf, $user; 784 $h = 0; 785 $head = array(); 786 787 $head[$h][0] = DOL_URL_ROOT."/admin/translation.php?mode=searchkey"; 788 $head[$h][1] = $langs->trans("TranslationKeySearch"); 789 $head[$h][2] = 'searchkey'; 790 $h++; 791 792 $head[$h][0] = DOL_URL_ROOT."/admin/translation.php?mode=overwrite"; 793 $head[$h][1] = $langs->trans("TranslationOverwriteKey").'<span class="fa fa-plus-circle valignmiddle paddingleft"></span>'; 794 $head[$h][2] = 'overwrite'; 795 $h++; 796 797 complete_head_from_modules($conf, $langs, null, $head, $h, 'translation_admin'); 798 799 complete_head_from_modules($conf, $langs, null, $head, $h, 'translation_admin', 'remove'); 800 801 802 return $head; 803} 804 805 806/** 807 * Prepare array with list of tabs 808 * 809 * @return array Array of tabs to show 810 */ 811function defaultvalues_prepare_head() 812{ 813 global $langs, $conf, $user; 814 $h = 0; 815 $head = array(); 816 817 $head[$h][0] = DOL_URL_ROOT."/admin/defaultvalues.php?mode=createform"; 818 $head[$h][1] = $langs->trans("DefaultCreateForm"); 819 $head[$h][2] = 'createform'; 820 $h++; 821 822 $head[$h][0] = DOL_URL_ROOT."/admin/defaultvalues.php?mode=filters"; 823 $head[$h][1] = $langs->trans("DefaultSearchFilters"); 824 $head[$h][2] = 'filters'; 825 $h++; 826 827 $head[$h][0] = DOL_URL_ROOT."/admin/defaultvalues.php?mode=sortorder"; 828 $head[$h][1] = $langs->trans("DefaultSortOrder"); 829 $head[$h][2] = 'sortorder'; 830 $h++; 831 832 if (!empty($conf->use_javascript_ajax)) { 833 $head[$h][0] = DOL_URL_ROOT."/admin/defaultvalues.php?mode=focus"; 834 $head[$h][1] = $langs->trans("DefaultFocus"); 835 $head[$h][2] = 'focus'; 836 $h++; 837 838 $head[$h][0] = DOL_URL_ROOT."/admin/defaultvalues.php?mode=mandatory"; 839 $head[$h][1] = $langs->trans("DefaultMandatory"); 840 $head[$h][2] = 'mandatory'; 841 $h++; 842 } 843 844 /*$head[$h][0] = DOL_URL_ROOT."/admin/translation.php?mode=searchkey"; 845 $head[$h][1] = $langs->trans("TranslationKeySearch"); 846 $head[$h][2] = 'searchkey'; 847 $h++;*/ 848 849 complete_head_from_modules($conf, $langs, null, $head, $h, 'defaultvalues_admin'); 850 851 complete_head_from_modules($conf, $langs, null, $head, $h, 'defaultvalues_admin', 'remove'); 852 853 854 return $head; 855} 856 857 858/** 859 * Return list of session 860 * 861 * @return array Array list of sessions 862 */ 863function listOfSessions() 864{ 865 global $conf; 866 867 $arrayofSessions = array(); 868 // session.save_path can be returned empty so we set a default location and work from there 869 $sessPath = '/tmp'; 870 $iniPath = ini_get("session.save_path"); 871 if ($iniPath) { 872 $sessPath = $iniPath; 873 } 874 $sessPath .= '/'; // We need the trailing slash 875 dol_syslog('admin.lib:listOfSessions sessPath='.$sessPath); 876 877 $dh = @opendir(dol_osencode($sessPath)); 878 if ($dh) { 879 while (($file = @readdir($dh)) !== false) { 880 if (preg_match('/^sess_/i', $file) && $file != "." && $file != "..") { 881 $fullpath = $sessPath.$file; 882 if (!@is_dir($fullpath) && is_readable($fullpath)) { 883 $sessValues = file_get_contents($fullpath); // get raw session data 884 // Example of possible value 885 //$sessValues = 'newtoken|s:32:"1239f7a0c4b899200fe9ca5ea394f307";dol_loginmesg|s:0:"";newtoken|s:32:"1236457104f7ae0f328c2928973f3cb5";dol_loginmesg|s:0:"";token|s:32:"123615ad8d650c5cc4199b9a1a76783f"; 886 // dol_login|s:5:"admin";dol_authmode|s:8:"dolibarr";dol_tz|s:1:"1";dol_tz_string|s:13:"Europe/Berlin";dol_dst|i:0;dol_dst_observed|s:1:"1";dol_dst_first|s:0:"";dol_dst_second|s:0:"";dol_screenwidth|s:4:"1920"; 887 // dol_screenheight|s:3:"971";dol_company|s:12:"MyBigCompany";dol_entity|i:1;mainmenu|s:4:"home";leftmenuopened|s:10:"admintools";idmenu|s:0:"";leftmenu|s:10:"admintools";'; 888 889 if (preg_match('/dol_login/i', $sessValues) && // limit to dolibarr session 890 (preg_match('/dol_entity\|i:'.$conf->entity.';/i', $sessValues) || preg_match('/dol_entity\|s:([0-9]+):"'.$conf->entity.'"/i', $sessValues)) && // limit to current entity 891 preg_match('/dol_company\|s:([0-9]+):"('.$conf->global->MAIN_INFO_SOCIETE_NOM.')"/i', $sessValues)) { // limit to company name 892 $tmp = explode('_', $file); 893 $idsess = $tmp[1]; 894 $regs = array(); 895 $loginfound = preg_match('/dol_login\|s:[0-9]+:"([A-Za-z0-9]+)"/i', $sessValues, $regs); 896 if ($loginfound) { 897 $arrayofSessions[$idsess]["login"] = $regs[1]; 898 } 899 $arrayofSessions[$idsess]["age"] = time() - filectime($fullpath); 900 $arrayofSessions[$idsess]["creation"] = filectime($fullpath); 901 $arrayofSessions[$idsess]["modification"] = filemtime($fullpath); 902 $arrayofSessions[$idsess]["raw"] = $sessValues; 903 } 904 } 905 } 906 } 907 @closedir($dh); 908 } 909 910 return $arrayofSessions; 911} 912 913/** 914 * Purge existing sessions 915 * 916 * @param int $mysessionid To avoid to try to delete my own session 917 * @return int >0 if OK, <0 if KO 918 */ 919function purgeSessions($mysessionid) 920{ 921 global $conf; 922 923 $sessPath = ini_get("session.save_path")."/"; 924 dol_syslog('admin.lib:purgeSessions mysessionid='.$mysessionid.' sessPath='.$sessPath); 925 926 $error = 0; 927 928 $dh = @opendir(dol_osencode($sessPath)); 929 if ($dh) { 930 while (($file = @readdir($dh)) !== false) { 931 if ($file != "." && $file != "..") { 932 $fullpath = $sessPath.$file; 933 if (!@is_dir($fullpath)) { 934 $sessValues = file_get_contents($fullpath); // get raw session data 935 936 if (preg_match('/dol_login/i', $sessValues) && // limit to dolibarr session 937 preg_match('/dol_entity\|s:([0-9]+):"('.$conf->entity.')"/i', $sessValues) && // limit to current entity 938 preg_match('/dol_company\|s:([0-9]+):"('.$conf->global->MAIN_INFO_SOCIETE_NOM.')"/i', $sessValues)) { // limit to company name 939 $tmp = explode('_', $file); 940 $idsess = $tmp[1]; 941 // We remove session if it's not ourself 942 if ($idsess != $mysessionid) { 943 $res = @unlink($fullpath); 944 if (!$res) { 945 $error++; 946 } 947 } 948 } 949 } 950 } 951 } 952 @closedir($dh); 953 } 954 955 if (!$error) { 956 return 1; 957 } else { 958 return -$error; 959 } 960} 961 962 963 964/** 965 * Enable a module 966 * 967 * @param string $value Name of module to activate 968 * @param int $withdeps Activate/Disable also all dependencies 969 * @return array array('nbmodules'=>nb modules activated with success, 'errors=>array of error messages, 'nbperms'=>Nb permission added); 970 */ 971function activateModule($value, $withdeps = 1) 972{ 973 global $db, $langs, $conf, $mysoc; 974 975 $ret = array(); 976 977 // Check parameters 978 if (empty($value)) { 979 $ret['errors'][] = 'ErrorBadParameter'; 980 return $ret; 981 } 982 983 $ret = array('nbmodules'=>0, 'errors'=>array(), 'nbperms'=>0); 984 $modName = $value; 985 $modFile = $modName.".class.php"; 986 987 // Loop on each directory to fill $modulesdir 988 $modulesdir = dolGetModulesDirs(); 989 990 // Loop on each modulesdir directories 991 $found = false; 992 foreach ($modulesdir as $dir) { 993 if (file_exists($dir.$modFile)) { 994 $found = @include_once $dir.$modFile; 995 if ($found) { 996 break; 997 } 998 } 999 } 1000 1001 $objMod = new $modName($db); 1002 1003 // Test if PHP version ok 1004 $verphp = versionphparray(); 1005 $vermin = isset($objMod->phpmin) ? $objMod->phpmin : 0; 1006 if (is_array($vermin) && versioncompare($verphp, $vermin) < 0) { 1007 $ret['errors'][] = $langs->trans("ErrorModuleRequirePHPVersion", versiontostring($vermin)); 1008 return $ret; 1009 } 1010 1011 // Test if Dolibarr version ok 1012 $verdol = versiondolibarrarray(); 1013 $vermin = isset($objMod->need_dolibarr_version) ? $objMod->need_dolibarr_version : 0; 1014 //print 'version: '.versioncompare($verdol,$vermin).' - '.join(',',$verdol).' - '.join(',',$vermin);exit; 1015 if (is_array($vermin) && versioncompare($verdol, $vermin) < 0) { 1016 $ret['errors'][] = $langs->trans("ErrorModuleRequireDolibarrVersion", versiontostring($vermin)); 1017 return $ret; 1018 } 1019 1020 // Test if javascript requirement ok 1021 if (!empty($objMod->need_javascript_ajax) && empty($conf->use_javascript_ajax)) { 1022 $ret['errors'][] = $langs->trans("ErrorModuleRequireJavascript"); 1023 return $ret; 1024 } 1025 1026 $const_name = $objMod->const_name; 1027 if (!empty($conf->global->$const_name)) { 1028 return $ret; 1029 } 1030 1031 $result = $objMod->init(); // Enable module 1032 1033 if ($result <= 0) { 1034 $ret['errors'][] = $objMod->error; 1035 } else { 1036 if ($withdeps) { 1037 if (isset($objMod->depends) && is_array($objMod->depends) && !empty($objMod->depends)) { 1038 // Activation of modules this module depends on 1039 // this->depends may be array('modModule1', 'mmodModule2') or array('always1'=>"modModule1", 'FR'=>'modModule2') 1040 foreach ($objMod->depends as $key => $modulestring) { 1041 //var_dump((! is_numeric($key)) && ! preg_match('/^always/', $key) && $mysoc->country_code && ! preg_match('/^'.$mysoc->country_code.'/', $key));exit; 1042 if ((!is_numeric($key)) && !preg_match('/^always/', $key) && $mysoc->country_code && !preg_match('/^'.$mysoc->country_code.'/', $key)) { 1043 dol_syslog("We are not concerned by dependency with key=".$key." because our country is ".$mysoc->country_code); 1044 continue; 1045 } 1046 $activate = false; 1047 foreach ($modulesdir as $dir) { 1048 if (file_exists($dir.$modulestring.".class.php")) { 1049 $resarray = activateModule($modulestring); 1050 if (empty($resarray['errors'])) { 1051 $activate = true; 1052 } else { 1053 foreach ($resarray['errors'] as $errorMessage) { 1054 dol_syslog($errorMessage, LOG_ERR); 1055 } 1056 } 1057 break; 1058 } 1059 } 1060 1061 if ($activate) { 1062 $ret['nbmodules'] += $resarray['nbmodules']; 1063 $ret['nbperms'] += $resarray['nbperms']; 1064 } else { 1065 $ret['errors'][] = $langs->trans('activateModuleDependNotSatisfied', $objMod->name, $modulestring); 1066 } 1067 } 1068 } 1069 1070 if (isset($objMod->conflictwith) && is_array($objMod->conflictwith) && !empty($objMod->conflictwith)) { 1071 // Desactivation des modules qui entrent en conflit 1072 $num = count($objMod->conflictwith); 1073 for ($i = 0; $i < $num; $i++) { 1074 foreach ($modulesdir as $dir) { 1075 if (file_exists($dir.$objMod->conflictwith[$i].".class.php")) { 1076 unActivateModule($objMod->conflictwith[$i], 0); 1077 } 1078 } 1079 } 1080 } 1081 } 1082 } 1083 1084 if (!count($ret['errors'])) { 1085 $ret['nbmodules']++; 1086 $ret['nbperms'] += count($objMod->rights); 1087 } 1088 1089 return $ret; 1090} 1091 1092 1093/** 1094 * Disable a module 1095 * 1096 * @param string $value Nom du module a desactiver 1097 * @param int $requiredby 1=Desactive aussi modules dependants 1098 * @return string Error message or ''; 1099 */ 1100function unActivateModule($value, $requiredby = 1) 1101{ 1102 global $db, $modules, $conf; 1103 1104 // Check parameters 1105 if (empty($value)) { 1106 return 'ErrorBadParameter'; 1107 } 1108 1109 $ret = ''; 1110 $modName = $value; 1111 $modFile = $modName.".class.php"; 1112 1113 // Loop on each directory to fill $modulesdir 1114 $modulesdir = dolGetModulesDirs(); 1115 1116 // Loop on each modulesdir directories 1117 $found = false; 1118 foreach ($modulesdir as $dir) { 1119 if (file_exists($dir.$modFile)) { 1120 $found = @include_once $dir.$modFile; 1121 if ($found) { 1122 break; 1123 } 1124 } 1125 } 1126 1127 if ($found) { 1128 $objMod = new $modName($db); 1129 $result = $objMod->remove(); 1130 if ($result <= 0) { 1131 $ret = $objMod->error; 1132 } 1133 } else // We come here when we try to unactivate a module when module does not exists anymore in sources 1134 { 1135 //print $dir.$modFile;exit; 1136 // TODO Replace this after DolibarrModules is moved as abstract class with a try catch to show module we try to disable has not been found or could not be loaded 1137 include_once DOL_DOCUMENT_ROOT.'/core/modules/DolibarrModules.class.php'; 1138 $genericMod = new DolibarrModules($db); 1139 $genericMod->name = preg_replace('/^mod/i', '', $modName); 1140 $genericMod->rights_class = strtolower(preg_replace('/^mod/i', '', $modName)); 1141 $genericMod->const_name = 'MAIN_MODULE_'.strtoupper(preg_replace('/^mod/i', '', $modName)); 1142 dol_syslog("modules::unActivateModule Failed to find module file, we use generic function with name ".$modName); 1143 $genericMod->remove(''); 1144 } 1145 1146 // Disable modules that depends on module we disable 1147 if (!$ret && $requiredby && is_object($objMod) && is_array($objMod->requiredby)) { 1148 $countrb = count($objMod->requiredby); 1149 for ($i = 0; $i < $countrb; $i++) { 1150 //var_dump($objMod->requiredby[$i]); 1151 unActivateModule($objMod->requiredby[$i]); 1152 } 1153 } 1154 1155 return $ret; 1156} 1157 1158 1159/** 1160 * Add external modules to list of dictionaries. 1161 * Addition is done into var $taborder, $tabname, etc... that are passed with pointers. 1162 * 1163 * @param array $taborder Taborder 1164 * @param array $tabname Tabname 1165 * @param array $tablib Tablib 1166 * @param array $tabsql Tabsql 1167 * @param array $tabsqlsort Tabsqlsort 1168 * @param array $tabfield Tabfield 1169 * @param array $tabfieldvalue Tabfieldvalue 1170 * @param array $tabfieldinsert Tabfieldinsert 1171 * @param array $tabrowid Tabrowid 1172 * @param array $tabcond Tabcond 1173 * @param array $tabhelp Tabhelp 1174 * @param array $tabfieldcheck Tabfieldcheck 1175 * @return int 1 1176 */ 1177function complete_dictionary_with_modules(&$taborder, &$tabname, &$tablib, &$tabsql, &$tabsqlsort, &$tabfield, &$tabfieldvalue, &$tabfieldinsert, &$tabrowid, &$tabcond, &$tabhelp, &$tabfieldcheck) 1178{ 1179 global $db, $modules, $conf, $langs; 1180 1181 dol_syslog("complete_dictionary_with_modules Search external modules to complete the list of dictionnary tables", LOG_DEBUG, 1); 1182 1183 // Search modules 1184 $modulesdir = dolGetModulesDirs(); 1185 $i = 0; // is a sequencer of modules found 1186 $j = 0; // j is module number. Automatically affected if module number not defined. 1187 1188 foreach ($modulesdir as $dir) { 1189 // Load modules attributes in arrays (name, numero, orders) from dir directory 1190 //print $dir."\n<br>"; 1191 dol_syslog("Scan directory ".$dir." for modules"); 1192 $handle = @opendir(dol_osencode($dir)); 1193 if (is_resource($handle)) { 1194 while (($file = readdir($handle)) !== false) { 1195 //print "$i ".$file."\n<br>"; 1196 if (is_readable($dir.$file) && substr($file, 0, 3) == 'mod' && substr($file, dol_strlen($file) - 10) == '.class.php') { 1197 $modName = substr($file, 0, dol_strlen($file) - 10); 1198 1199 if ($modName) { 1200 include_once $dir.$file; 1201 $objMod = new $modName($db); 1202 1203 if ($objMod->numero > 0) { 1204 $j = $objMod->numero; 1205 } else { 1206 $j = 1000 + $i; 1207 } 1208 1209 $modulequalified = 1; 1210 1211 // We discard modules according to features level (PS: if module is activated we always show it) 1212 $const_name = 'MAIN_MODULE_'.strtoupper(preg_replace('/^mod/i', '', get_class($objMod))); 1213 if ($objMod->version == 'development' && $conf->global->MAIN_FEATURES_LEVEL < 2 && !$conf->global->$const_name) { 1214 $modulequalified = 0; 1215 } 1216 if ($objMod->version == 'experimental' && $conf->global->MAIN_FEATURES_LEVEL < 1 && !$conf->global->$const_name) { 1217 $modulequalified = 0; 1218 } 1219 //If module is not activated disqualified 1220 if (empty($conf->global->$const_name)) { 1221 $modulequalified = 0; 1222 } 1223 1224 if ($modulequalified) { 1225 // Load languages files of module 1226 if (isset($objMod->langfiles) && is_array($objMod->langfiles)) { 1227 foreach ($objMod->langfiles as $langfile) { 1228 $langs->load($langfile); 1229 } 1230 } 1231 1232 // Complete the arrays &$tabname,&$tablib,&$tabsql,&$tabsqlsort,&$tabfield,&$tabfieldvalue,&$tabfieldinsert,&$tabrowid,&$tabcond 1233 if (empty($objMod->dictionaries) && !empty($objMod->dictionnaries)) { 1234 $objMod->dictionaries = $objMod->dictionnaries; // For backward compatibility 1235 } 1236 1237 if (!empty($objMod->dictionaries)) { 1238 //var_dump($objMod->dictionaries['tabname']); 1239 $nbtabname = $nbtablib = $nbtabsql = $nbtabsqlsort = $nbtabfield = $nbtabfieldvalue = $nbtabfieldinsert = $nbtabrowid = $nbtabcond = $nbtabfieldcheck = $nbtabhelp = 0; 1240 foreach ($objMod->dictionaries['tabname'] as $val) { 1241 $nbtabname++; $taborder[] = max($taborder) + 1; $tabname[] = $val; 1242 } // Position 1243 foreach ($objMod->dictionaries['tablib'] as $val) { 1244 $nbtablib++; $tablib[] = $val; 1245 } 1246 foreach ($objMod->dictionaries['tabsql'] as $val) { 1247 $nbtabsql++; $tabsql[] = $val; 1248 } 1249 foreach ($objMod->dictionaries['tabsqlsort'] as $val) { 1250 $nbtabsqlsort++; $tabsqlsort[] = $val; 1251 } 1252 foreach ($objMod->dictionaries['tabfield'] as $val) { 1253 $nbtabfield++; $tabfield[] = $val; 1254 } 1255 foreach ($objMod->dictionaries['tabfieldvalue'] as $val) { 1256 $nbtabfieldvalue++; $tabfieldvalue[] = $val; 1257 } 1258 foreach ($objMod->dictionaries['tabfieldinsert'] as $val) { 1259 $nbtabfieldinsert++; $tabfieldinsert[] = $val; 1260 } 1261 foreach ($objMod->dictionaries['tabrowid'] as $val) { 1262 $nbtabrowid++; $tabrowid[] = $val; 1263 } 1264 foreach ($objMod->dictionaries['tabcond'] as $val) { 1265 $nbtabcond++; $tabcond[] = $val; 1266 } 1267 if (!empty($objMod->dictionaries['tabhelp'])) { 1268 foreach ($objMod->dictionaries['tabhelp'] as $val) { 1269 $nbtabhelp++; $tabhelp[] = $val; 1270 } 1271 } 1272 if (!empty($objMod->dictionaries['tabfieldcheck'])) { 1273 foreach ($objMod->dictionaries['tabfieldcheck'] as $val) { 1274 $nbtabfieldcheck++; $tabfieldcheck[] = $val; 1275 } 1276 } 1277 1278 if ($nbtabname != $nbtablib || $nbtablib != $nbtabsql || $nbtabsql != $nbtabsqlsort) { 1279 print 'Error in descriptor of module '.$const_name.'. Array ->dictionaries has not same number of record for key "tabname", "tablib", "tabsql" and "tabsqlsort"'; 1280 //print "$const_name: $nbtabname=$nbtablib=$nbtabsql=$nbtabsqlsort=$nbtabfield=$nbtabfieldvalue=$nbtabfieldinsert=$nbtabrowid=$nbtabcond=$nbtabfieldcheck=$nbtabhelp\n"; 1281 } else { 1282 $taborder[] = 0; // Add an empty line 1283 } 1284 } 1285 1286 $j++; 1287 $i++; 1288 } else { 1289 dol_syslog("Module ".get_class($objMod)." not qualified"); 1290 } 1291 } 1292 } 1293 } 1294 closedir($handle); 1295 } else { 1296 dol_syslog("htdocs/admin/modules.php: Failed to open directory ".$dir.". See permission and open_basedir option.", LOG_WARNING); 1297 } 1298 } 1299 1300 dol_syslog("", LOG_DEBUG, -1); 1301 1302 return 1; 1303} 1304 1305/** 1306 * Activate external modules mandatory when country is country_code 1307 * 1308 * @param string $country_code CountryCode 1309 * @return int 1 1310 */ 1311function activateModulesRequiredByCountry($country_code) 1312{ 1313 global $db, $conf, $langs; 1314 1315 $modulesdir = dolGetModulesDirs(); 1316 1317 foreach ($modulesdir as $dir) { 1318 // Load modules attributes in arrays (name, numero, orders) from dir directory 1319 dol_syslog("Scan directory ".$dir." for modules"); 1320 $handle = @opendir(dol_osencode($dir)); 1321 if (is_resource($handle)) { 1322 while (($file = readdir($handle)) !== false) { 1323 if (is_readable($dir.$file) && substr($file, 0, 3) == 'mod' && substr($file, dol_strlen($file) - 10) == '.class.php') { 1324 $modName = substr($file, 0, dol_strlen($file) - 10); 1325 1326 if ($modName) { 1327 include_once $dir.$file; 1328 $objMod = new $modName($db); 1329 1330 $modulequalified = 1; 1331 1332 // We discard modules according to features level (PS: if module is activated we always show it) 1333 $const_name = 'MAIN_MODULE_'.strtoupper(preg_replace('/^mod/i', '', get_class($objMod))); 1334 1335 if ($objMod->version == 'development' && $conf->global->MAIN_FEATURES_LEVEL < 2) { 1336 $modulequalified = 0; 1337 } 1338 if ($objMod->version == 'experimental' && $conf->global->MAIN_FEATURES_LEVEL < 1) { 1339 $modulequalified = 0; 1340 } 1341 if (!empty($conf->global->$const_name)) { 1342 $modulequalified = 0; // already activated 1343 } 1344 1345 if ($modulequalified) { 1346 // Load languages files of module 1347 if (isset($objMod->automatic_activation) && is_array($objMod->automatic_activation) && isset($objMod->automatic_activation[$country_code])) { 1348 activateModule($modName); 1349 1350 setEventMessages($objMod->automatic_activation[$country_code], null, 'warnings'); 1351 } 1352 } else { 1353 dol_syslog("Module ".get_class($objMod)." not qualified"); 1354 } 1355 } 1356 } 1357 } 1358 closedir($handle); 1359 } else { 1360 dol_syslog("htdocs/admin/modules.php: Failed to open directory ".$dir.". See permission and open_basedir option.", LOG_WARNING); 1361 } 1362 } 1363 1364 return 1; 1365} 1366 1367/** 1368 * Search external modules to complete the list of contact element 1369 * 1370 * @param array $elementList elementList 1371 * @return int 1 1372 */ 1373function complete_elementList_with_modules(&$elementList) 1374{ 1375 global $db, $modules, $conf, $langs; 1376 1377 // Search modules 1378 $filename = array(); 1379 $modules = array(); 1380 $orders = array(); 1381 $categ = array(); 1382 $dirmod = array(); 1383 1384 $i = 0; // is a sequencer of modules found 1385 $j = 0; // j is module number. Automatically affected if module number not defined. 1386 1387 dol_syslog("complete_elementList_with_modules Search external modules to complete the list of contact element", LOG_DEBUG, 1); 1388 1389 $modulesdir = dolGetModulesDirs(); 1390 1391 foreach ($modulesdir as $dir) { 1392 // Load modules attributes in arrays (name, numero, orders) from dir directory 1393 //print $dir."\n<br>"; 1394 dol_syslog("Scan directory ".$dir." for modules"); 1395 $handle = @opendir(dol_osencode($dir)); 1396 if (is_resource($handle)) { 1397 while (($file = readdir($handle)) !== false) { 1398 //print "$i ".$file."\n<br>"; 1399 if (is_readable($dir.$file) && substr($file, 0, 3) == 'mod' && substr($file, dol_strlen($file) - 10) == '.class.php') { 1400 $modName = substr($file, 0, dol_strlen($file) - 10); 1401 1402 if ($modName) { 1403 include_once $dir.$file; 1404 $objMod = new $modName($db); 1405 1406 if ($objMod->numero > 0) { 1407 $j = $objMod->numero; 1408 } else { 1409 $j = 1000 + $i; 1410 } 1411 1412 $modulequalified = 1; 1413 1414 // We discard modules according to features level (PS: if module is activated we always show it) 1415 $const_name = 'MAIN_MODULE_'.strtoupper(preg_replace('/^mod/i', '', get_class($objMod))); 1416 if ($objMod->version == 'development' && $conf->global->MAIN_FEATURES_LEVEL < 2 && !$conf->global->$const_name) { 1417 $modulequalified = 0; 1418 } 1419 if ($objMod->version == 'experimental' && $conf->global->MAIN_FEATURES_LEVEL < 1 && !$conf->global->$const_name) { 1420 $modulequalified = 0; 1421 } 1422 //If module is not activated disqualified 1423 if (empty($conf->global->$const_name)) { 1424 $modulequalified = 0; 1425 } 1426 1427 if ($modulequalified) { 1428 // Load languages files of module 1429 if (isset($objMod->langfiles) && is_array($objMod->langfiles)) { 1430 foreach ($objMod->langfiles as $langfile) { 1431 $langs->load($langfile); 1432 } 1433 } 1434 1435 $modules[$i] = $objMod; 1436 $filename[$i] = $modName; 1437 $orders[$i] = $objMod->family."_".$j; // Sort on family then module number 1438 $dirmod[$i] = $dir; 1439 //print "x".$modName." ".$orders[$i]."\n<br>"; 1440 1441 if (!empty($objMod->module_parts['contactelement'])) { 1442 if (is_array($objMod->module_parts['contactelement'])) { 1443 foreach ($objMod->module_parts['contactelement'] as $elem => $title) { 1444 $elementList[$elem] = $langs->trans($title); 1445 } 1446 } else { 1447 $elementList[$objMod->name] = $langs->trans($objMod->name); 1448 } 1449 } 1450 1451 $j++; 1452 $i++; 1453 } else { 1454 dol_syslog("Module ".get_class($objMod)." not qualified"); 1455 } 1456 } 1457 } 1458 } 1459 closedir($handle); 1460 } else { 1461 dol_syslog("htdocs/admin/modules.php: Failed to open directory ".$dir.". See permission and open_basedir option.", LOG_WARNING); 1462 } 1463 } 1464 1465 dol_syslog("", LOG_DEBUG, -1); 1466 1467 return 1; 1468} 1469 1470/** 1471 * Show array with constants to edit 1472 * 1473 * @param array $tableau Array of constants array('key'=>array('type'=>type, 'label'=>label) 1474 * where type can be 'string', 'text', 'textarea', 'html', 'yesno', 'emailtemplate:xxx', ... 1475 * @param int $strictw3c 0=Include form into table (deprecated), 1=Form is outside table to respect W3C (deprecated), 2=No form nor button at all (form is output by caller, recommended) 1476 * @param string $helptext Help 1477 * @return void 1478 */ 1479function form_constantes($tableau, $strictw3c = 0, $helptext = '') 1480{ 1481 global $db, $langs, $conf, $user; 1482 global $_Avery_Labels; 1483 1484 $form = new Form($db); 1485 1486 if (empty($strictw3c)) { 1487 dol_syslog("Warning: Function form_constantes is calle with parameter strictw3c = 0, this is deprecated. Value must be 2 now.", LOG_DEBUG); 1488 } 1489 if (!empty($strictw3c) && $strictw3c == 1) { 1490 print "\n".'<form action="'.$_SERVER["PHP_SELF"].'" method="POST">'; 1491 print '<input type="hidden" name="token" value="'.newToken().'">'; 1492 print '<input type="hidden" name="action" value="updateall">'; 1493 } 1494 1495 print '<table class="noborder centpercent">'; 1496 print '<tr class="liste_titre">'; 1497 print '<td class="titlefield">'.$langs->trans("Description").'</td>'; 1498 print '<td>'; 1499 $text = $langs->trans("Value"); 1500 print $form->textwithpicto($text, $helptext, 1, 'help', '', 0, 2, 'idhelptext'); 1501 print '</td>'; 1502 if (empty($strictw3c)) { 1503 print '<td class="center" width="80">'.$langs->trans("Action").'</td>'; 1504 } 1505 print "</tr>\n"; 1506 1507 $label = ''; 1508 foreach ($tableau as $key => $const) { // Loop on each param 1509 $label = ''; 1510 // $const is a const key like 'MYMODULE_ABC' 1511 if (is_numeric($key)) { // Very old behaviour 1512 $type = 'string'; 1513 } else { 1514 if (is_array($const)) { 1515 $type = $const['type']; 1516 $label = $const['label']; 1517 $const = $key; 1518 } else { 1519 $type = $const; 1520 $const = $key; 1521 } 1522 } 1523 1524 $sql = "SELECT "; 1525 $sql .= "rowid"; 1526 $sql .= ", ".$db->decrypt('name')." as name"; 1527 $sql .= ", ".$db->decrypt('value')." as value"; 1528 $sql .= ", type"; 1529 $sql .= ", note"; 1530 $sql .= " FROM ".MAIN_DB_PREFIX."const"; 1531 $sql .= " WHERE ".$db->decrypt('name')." = '".$db->escape($const)."'"; 1532 $sql .= " AND entity IN (0, ".$conf->entity.")"; 1533 $sql .= " ORDER BY name ASC, entity DESC"; 1534 $result = $db->query($sql); 1535 1536 dol_syslog("List params", LOG_DEBUG); 1537 if ($result) { 1538 $obj = $db->fetch_object($result); // Take first result of select 1539 1540 if (empty($obj)) { // If not yet into table 1541 $obj = (object) array('rowid'=>'', 'name'=>$const, 'value'=>'', 'type'=>$type, 'note'=>''); 1542 } 1543 1544 if (empty($strictw3c)) { 1545 print "\n".'<form action="'.$_SERVER["PHP_SELF"].'" method="POST">'; 1546 print '<input type="hidden" name="token" value="'.newToken().'">'; 1547 } 1548 1549 print '<tr class="oddeven">'; 1550 1551 // Show constant 1552 print '<td>'; 1553 if (empty($strictw3c)) { 1554 print '<input type="hidden" name="action" value="update">'; 1555 } 1556 print '<input type="hidden" name="rowid'.(empty($strictw3c) ? '' : '[]').'" value="'.$obj->rowid.'">'; 1557 print '<input type="hidden" name="constname'.(empty($strictw3c) ? '' : '[]').'" value="'.$const.'">'; 1558 print '<input type="hidden" name="constnote_'.$obj->name.'" value="'.nl2br(dol_escape_htmltag($obj->note)).'">'; 1559 print '<input type="hidden" name="consttype_'.$obj->name.'" value="'.($obj->type ? $obj->type : 'string').'">'; 1560 1561 print ($label ? $label : $langs->trans('Desc'.$const)); 1562 1563 if ($const == 'ADHERENT_MAILMAN_URL') { 1564 print '. '.$langs->trans("Example").': <a href="#" id="exampleclick1">'.img_down().'</a><br>'; 1565 //print 'http://lists.exampe.com/cgi-bin/mailman/admin/%LISTE%/members?adminpw=%MAILMAN_ADMINPW%&subscribees=%EMAIL%&send_welcome_msg_to_this_batch=1'; 1566 print '<div id="example1" class="hidden">'; 1567 print 'http://lists.example.com/cgi-bin/mailman/admin/%LISTE%/members/add?subscribees_upload=%EMAIL%&adminpw=%MAILMAN_ADMINPW%&subscribe_or_invite=0&send_welcome_msg_to_this_batch=0&notification_to_list_owner=0'; 1568 print '</div>'; 1569 } 1570 if ($const == 'ADHERENT_MAILMAN_UNSUB_URL') { 1571 print '. '.$langs->trans("Example").': <a href="#" id="exampleclick2">'.img_down().'</a><br>'; 1572 print '<div id="example2" class="hidden">'; 1573 print 'http://lists.example.com/cgi-bin/mailman/admin/%LISTE%/members/remove?unsubscribees_upload=%EMAIL%&adminpw=%MAILMAN_ADMINPW%&send_unsub_ack_to_this_batch=0&send_unsub_notifications_to_list_owner=0'; 1574 print '</div>'; 1575 //print 'http://lists.example.com/cgi-bin/mailman/admin/%LISTE%/members/remove?adminpw=%MAILMAN_ADMINPW%&unsubscribees=%EMAIL%'; 1576 } 1577 if ($const == 'ADHERENT_MAILMAN_LISTS') { 1578 print '. '.$langs->trans("Example").': <a href="#" id="exampleclick3">'.img_down().'</a><br>'; 1579 print '<div id="example3" class="hidden">'; 1580 print 'mymailmanlist<br>'; 1581 print 'mymailmanlist1,mymailmanlist2<br>'; 1582 print 'TYPE:Type1:mymailmanlist1,TYPE:Type2:mymailmanlist2<br>'; 1583 if ($conf->categorie->enabled) { 1584 print 'CATEG:Categ1:mymailmanlist1,CATEG:Categ2:mymailmanlist2<br>'; 1585 } 1586 print '</div>'; 1587 //print 'http://lists.example.com/cgi-bin/mailman/admin/%LISTE%/members/remove?adminpw=%MAILMAN_ADMINPW%&unsubscribees=%EMAIL%'; 1588 } 1589 1590 print "</td>\n"; 1591 1592 // Value 1593 if ($const == 'ADHERENT_CARD_TYPE' || $const == 'ADHERENT_ETIQUETTE_TYPE') { 1594 print '<td>'; 1595 // List of possible labels (defined into $_Avery_Labels variable set into format_cards.lib.php) 1596 require_once DOL_DOCUMENT_ROOT.'/core/lib/format_cards.lib.php'; 1597 $arrayoflabels = array(); 1598 foreach (array_keys($_Avery_Labels) as $codecards) { 1599 $arrayoflabels[$codecards] = $_Avery_Labels[$codecards]['name']; 1600 } 1601 print $form->selectarray('constvalue'.(empty($strictw3c) ? '' : '[]'), $arrayoflabels, ($obj->value ? $obj->value : 'CARD'), 1, 0, 0); 1602 print '<input type="hidden" name="consttype" value="yesno">'; 1603 print '<input type="hidden" name="constnote'.(empty($strictw3c) ? '' : '[]').'" value="'.nl2br(dol_escape_htmltag($obj->note)).'">'; 1604 print '</td>'; 1605 } else { 1606 print '<td>'; 1607 print '<input type="hidden" name="consttype'.(empty($strictw3c) ? '' : '[]').'" value="'.($obj->type ? $obj->type : 'string').'">'; 1608 print '<input type="hidden" name="constnote'.(empty($strictw3c) ? '' : '[]').'" value="'.nl2br(dol_escape_htmltag($obj->note)).'">'; 1609 if ($obj->type == 'textarea' || in_array($const, array('ADHERENT_CARD_TEXT', 'ADHERENT_CARD_TEXT_RIGHT', 'ADHERENT_ETIQUETTE_TEXT'))) { 1610 print '<textarea class="flat" name="constvalue'.(empty($strictw3c) ? '' : '[]').'" cols="50" rows="5" wrap="soft">'."\n"; 1611 print $obj->value; 1612 print "</textarea>\n"; 1613 } elseif ($obj->type == 'html') { 1614 require_once DOL_DOCUMENT_ROOT.'/core/class/doleditor.class.php'; 1615 $doleditor = new DolEditor('constvalue_'.$const.(empty($strictw3c) ? '' : '[]'), $obj->value, '', 160, 'dolibarr_notes', '', false, false, $conf->fckeditor->enabled, ROWS_5, '90%'); 1616 $doleditor->Create(); 1617 } elseif ($obj->type == 'yesno') { 1618 print $form->selectyesno('constvalue'.(empty($strictw3c) ? '' : '[]'), $obj->value, 1); 1619 } elseif (preg_match('/emailtemplate/', $obj->type)) { 1620 include_once DOL_DOCUMENT_ROOT.'/core/class/html.formmail.class.php'; 1621 $formmail = new FormMail($db); 1622 1623 $tmp = explode(':', $obj->type); 1624 1625 $nboftemplates = $formmail->fetchAllEMailTemplate($tmp[1], $user, null, -1); // We set lang=null to get in priority record with no lang 1626 //$arraydefaultmessage = $formmail->getEMailTemplate($db, $tmp[1], $user, null, 0, 1, ''); 1627 $arrayofmessagename = array(); 1628 if (is_array($formmail->lines_model)) { 1629 foreach ($formmail->lines_model as $modelmail) { 1630 //var_dump($modelmail); 1631 $moreonlabel = ''; 1632 if (!empty($arrayofmessagename[$modelmail->label])) { 1633 $moreonlabel = ' <span class="opacitymedium">('.$langs->trans("SeveralLangugeVariatFound").')</span>'; 1634 } 1635 // The 'label' is the key that is unique if we exclude the language 1636 $arrayofmessagename[$modelmail->label.':'.$tmp[1]] = $langs->trans(preg_replace('/\(|\)/', '', $modelmail->label)).$moreonlabel; 1637 } 1638 } 1639 //var_dump($arraydefaultmessage); 1640 //var_dump($arrayofmessagename); 1641 print $form->selectarray('constvalue_'.$obj->name, $arrayofmessagename, $obj->value.':'.$tmp[1], 'None', 0, 0, '', 0, 0, 0, '', '', 1); 1642 } else // type = 'string' ou 'chaine' 1643 { 1644 print '<input type="text" class="flat" size="48" name="constvalue'.(empty($strictw3c) ? '' : '[]').'" value="'.dol_escape_htmltag($obj->value).'">'; 1645 } 1646 print '</td>'; 1647 } 1648 // Submit 1649 if (empty($strictw3c)) { 1650 print '<td class="center">'; 1651 print '<input type="submit" class="button" value="'.$langs->trans("Update").'" name="Button">'; 1652 print "</td>"; 1653 } 1654 print "</tr>\n"; 1655 1656 if (empty($strictw3c)) { 1657 print "</form>\n"; 1658 } 1659 } 1660 } 1661 print '</table>'; 1662 1663 if (!empty($strictw3c) && $strictw3c == 1) { 1664 print '<div align="center"><input type="submit" class="button" value="'.$langs->trans("Update").'" name="update"></div>'; 1665 print "</form>\n"; 1666 } 1667} 1668 1669 1670/** 1671 * Show array with constants to edit 1672 * 1673 * @param array $modules Array of all modules 1674 * @return string HTML string with warning 1675 */ 1676function showModulesExludedForExternal($modules) 1677{ 1678 global $conf, $langs; 1679 1680 $text = $langs->trans("OnlyFollowingModulesAreOpenedToExternalUsers"); 1681 $listofmodules = explode(',', $conf->global->MAIN_MODULES_FOR_EXTERNAL); 1682 $i = 0; 1683 if (!empty($modules)) { 1684 foreach ($modules as $module) { 1685 $moduleconst = $module->const_name; 1686 $modulename = strtolower($module->name); 1687 //print 'modulename='.$modulename; 1688 1689 //if (empty($conf->global->$moduleconst)) continue; 1690 if (!in_array($modulename, $listofmodules)) { 1691 continue; 1692 } 1693 //var_dump($modulename.' - '.$langs->trans('Module'.$module->numero.'Name')); 1694 1695 if ($i > 0) { 1696 $text .= ', '; 1697 } else { 1698 $text .= ' '; 1699 } 1700 $i++; 1701 $text .= $langs->trans('Module'.$module->numero.'Name'); 1702 } 1703 } 1704 return $text; 1705} 1706 1707 1708/** 1709 * Add document model used by doc generator 1710 * 1711 * @param string $name Model name 1712 * @param string $type Model type 1713 * @param string $label Model label 1714 * @param string $description Model description 1715 * @return int <0 if KO, >0 if OK 1716 */ 1717function addDocumentModel($name, $type, $label = '', $description = '') 1718{ 1719 global $db, $conf; 1720 1721 $db->begin(); 1722 1723 $sql = "INSERT INTO ".MAIN_DB_PREFIX."document_model (nom, type, entity, libelle, description)"; 1724 $sql .= " VALUES ('".$db->escape($name)."','".$db->escape($type)."',".$conf->entity.", "; 1725 $sql .= ($label ? "'".$db->escape($label)."'" : 'null').", "; 1726 $sql .= (!empty($description) ? "'".$db->escape($description)."'" : "null"); 1727 $sql .= ")"; 1728 1729 dol_syslog("admin.lib::addDocumentModel", LOG_DEBUG); 1730 $resql = $db->query($sql); 1731 if ($resql) { 1732 $db->commit(); 1733 return 1; 1734 } else { 1735 dol_print_error($db); 1736 $db->rollback(); 1737 return -1; 1738 } 1739} 1740 1741/** 1742 * Delete document model used by doc generator 1743 * 1744 * @param string $name Model name 1745 * @param string $type Model type 1746 * @return int <0 if KO, >0 if OK 1747 */ 1748function delDocumentModel($name, $type) 1749{ 1750 global $db, $conf; 1751 1752 $db->begin(); 1753 1754 $sql = "DELETE FROM ".MAIN_DB_PREFIX."document_model"; 1755 $sql .= " WHERE nom = '".$db->escape($name)."'"; 1756 $sql .= " AND type = '".$db->escape($type)."'"; 1757 $sql .= " AND entity = ".$conf->entity; 1758 1759 dol_syslog("admin.lib::delDocumentModel", LOG_DEBUG); 1760 $resql = $db->query($sql); 1761 if ($resql) { 1762 $db->commit(); 1763 return 1; 1764 } else { 1765 dol_print_error($db); 1766 $db->rollback(); 1767 return -1; 1768 } 1769} 1770 1771 1772/** 1773 * Return the php_info into an array 1774 * 1775 * @return array Array with PHP infos 1776 */ 1777function phpinfo_array() 1778{ 1779 ob_start(); 1780 phpinfo(); 1781 $phpinfostring = ob_get_contents(); 1782 ob_end_clean(); 1783 1784 $info_arr = array(); 1785 $info_lines = explode("\n", strip_tags($phpinfostring, "<tr><td><h2>")); 1786 $cat = "General"; 1787 foreach ($info_lines as $line) { 1788 // new cat? 1789 $title = array(); 1790 preg_match("~<h2>(.*)</h2>~", $line, $title) ? $cat = $title[1] : null; 1791 $val = array(); 1792 if (preg_match("~<tr><td[^>]+>([^<]*)</td><td[^>]+>([^<]*)</td></tr>~", $line, $val)) { 1793 $info_arr[trim($cat)][trim($val[1])] = $val[2]; 1794 } elseif (preg_match("~<tr><td[^>]+>([^<]*)</td><td[^>]+>([^<]*)</td><td[^>]+>([^<]*)</td></tr>~", $line, $val)) { 1795 $info_arr[trim($cat)][trim($val[1])] = array("local" => $val[2], "master" => $val[3]); 1796 } 1797 } 1798 return $info_arr; 1799} 1800 1801/** 1802 * Return array head with list of tabs to view object informations. 1803 * 1804 * @return array head array with tabs 1805 */ 1806function company_admin_prepare_head() 1807{ 1808 global $langs, $conf; 1809 1810 $h = 0; 1811 $head = array(); 1812 1813 $head[$h][0] = DOL_URL_ROOT."/admin/company.php"; 1814 $head[$h][1] = $langs->trans("Company"); 1815 $head[$h][2] = 'company'; 1816 $h++; 1817 1818 $head[$h][0] = DOL_URL_ROOT."/admin/openinghours.php"; 1819 $head[$h][1] = $langs->trans("OpeningHours"); 1820 $head[$h][2] = 'openinghours'; 1821 $h++; 1822 1823 $head[$h][0] = DOL_URL_ROOT."/admin/accountant.php"; 1824 $head[$h][1] = $langs->trans("Accountant"); 1825 $head[$h][2] = 'accountant'; 1826 $h++; 1827 1828 $head[$h][0] = DOL_URL_ROOT."/admin/company_socialnetworks.php"; 1829 $head[$h][1] = $langs->trans("SocialNetworksInformation"); 1830 $head[$h][2] = 'socialnetworks'; 1831 $h++; 1832 1833 complete_head_from_modules($conf, $langs, null, $head, $h, 'mycompany_admin', 'add'); 1834 1835 complete_head_from_modules($conf, $langs, null, $head, $h, 'mycompany_admin', 'remove'); 1836 1837 return $head; 1838} 1839 1840/** 1841 * Return array head with list of tabs to view object informations. 1842 * 1843 * @return array head array with tabs 1844 */ 1845function email_admin_prepare_head() 1846{ 1847 global $langs, $conf, $user; 1848 1849 $h = 0; 1850 $head = array(); 1851 1852 if (!empty($user->admin) && (empty($_SESSION['leftmenu']) || $_SESSION['leftmenu'] != 'email_templates')) { 1853 $head[$h][0] = DOL_URL_ROOT."/admin/mails.php"; 1854 $head[$h][1] = $langs->trans("OutGoingEmailSetup"); 1855 $head[$h][2] = 'common'; 1856 $h++; 1857 1858 if ($conf->mailing->enabled) { 1859 $head[$h][0] = DOL_URL_ROOT."/admin/mails_emailing.php"; 1860 $head[$h][1] = $langs->trans("OutGoingEmailSetupForEmailing", $langs->transnoentitiesnoconv("EMailing")); 1861 $head[$h][2] = 'common_emailing'; 1862 $h++; 1863 } 1864 1865 if ($conf->ticket->enabled) { 1866 $head[$h][0] = DOL_URL_ROOT."/admin/mails_ticket.php"; 1867 $head[$h][1] = $langs->trans("OutGoingEmailSetupForEmailing", $langs->transnoentitiesnoconv("Ticket")); 1868 $head[$h][2] = 'common_ticket'; 1869 $h++; 1870 } 1871 } 1872 1873 if (!empty($user->admin) && (empty($_SESSION['leftmenu']) || $_SESSION['leftmenu'] != 'email_templates')) { 1874 $head[$h][0] = DOL_URL_ROOT."/admin/mails_senderprofile_list.php"; 1875 $head[$h][1] = $langs->trans("EmailSenderProfiles"); 1876 $head[$h][2] = 'senderprofiles'; 1877 $h++; 1878 } 1879 1880 $head[$h][0] = DOL_URL_ROOT."/admin/mails_templates.php"; 1881 $head[$h][1] = $langs->trans("EMailTemplates"); 1882 $head[$h][2] = 'templates'; 1883 $h++; 1884 1885 complete_head_from_modules($conf, $langs, null, $head, $h, 'email_admin', 'remove'); 1886 1887 return $head; 1888} 1889