admin.lib.php 67 KB

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