admin.lib.php 64 KB

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