lib.php 38 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207
  1. <?php
  2. require_once 'lib/bootlib.php';
  3. require_once 'lib/vchamilo_plugin.class.php';
  4. function vchamilo_hook_configuration(&$_configuration)
  5. {
  6. global $VCHAMILO;
  7. if (defined('CLI_SCRIPT') && !defined('CLI_VCHAMILO_OVERRIDE')) {
  8. return;
  9. }
  10. // provides an effective value for the virtual root_web based on domain analysis
  11. vchamilo_get_hostname($_configuration);
  12. //$plugin = VChamiloPlugin::create();
  13. // We are on physical chamilo. Let original config play
  14. $virtualChamiloWebRoot = $_configuration['vchamilo_web_root'].'/';
  15. if ($_configuration['root_web'] == $virtualChamiloWebRoot){
  16. $VCHAMILO = 'main';
  17. return;
  18. }
  19. // pre hook to chamilo main table and get alternate configuration.
  20. // sure Database object is not set up. Soo use bootstrap connection
  21. /** @var \Doctrine\DBAL\Connection $connection */
  22. $connection = vchamilo_boot_connection($_configuration);
  23. $table = 'vchamilo';
  24. $query = "SELECT * FROM $table WHERE root_web = '$virtualChamiloWebRoot'";
  25. $result = $connection->executeQuery($query);
  26. $excludes = array('id', 'name');
  27. if ($result->rowCount()) {
  28. $data = $result->fetch();
  29. foreach ($data as $key => $value){
  30. if (!in_array($key, $excludes)){
  31. $_configuration[$key] = $value;
  32. }
  33. $_configuration['virtual'] = $data['root_web'].'/';
  34. $VCHAMILO = $data['root_web'];
  35. }
  36. } else {
  37. //die ("VChamilo : No configuration for this host. May be faked.");
  38. die ("VChamilo : Could not fetch virtual chamilo configuration");
  39. }
  40. }
  41. /**
  42. * @param array $_configuration
  43. */
  44. function vchamilo_get_hostname(&$_configuration)
  45. {
  46. if (!empty($_SERVER['HTTP_X_FORWARDED_PROTO']) &&
  47. $_SERVER['HTTP_X_FORWARDED_PROTO'] == 'https' || !empty($_configuration['force_https_forwarded_proto'])
  48. ) {
  49. $protocol = 'https';
  50. } else {
  51. $protocol = 'http';
  52. }
  53. if (defined('CLI_VCHAMILO_OVERRIDE')) {
  54. $_configuration['vchamilo_web_root'] = CLI_VCHAMILO_OVERRIDE;
  55. $_configuration['vchamilo_name'] = preg_replace('#https?://#', '', CLI_VCHAMILO_OVERRIDE);
  56. // remove radical from override for name
  57. // fake the server signature
  58. global $_SERVER;
  59. $_SERVER['SERVER_NAME'] = $_configuration['vchamilo_name'];
  60. $_SERVER['HTTP_HOST'] = $_configuration['vchamilo_name'];
  61. $_SERVER['QUERY_STRING'] = '';
  62. $_SERVER['REQUEST_URI'] = CLI_VCHAMILO_OVERRIDE;
  63. return;
  64. }
  65. $_configuration['vchamilo_web_root'] = "{$protocol}://".@$_SERVER['HTTP_HOST'];
  66. $_configuration['vchamilo_name'] = @$_SERVER['HTTP_HOST'];
  67. if (empty($_configuration['vchamilo_name'])) { // try again with another source if has failed
  68. $_configuration['vchamilo_name'] = "{$protocol}://".$_SERVER['SERVER_NAME'];
  69. if ($_SERVER['SERVER_PORT'] != 80) {
  70. $_configuration['vchamilo_name'] .= ':'.$_SERVER['SERVER_PORT'];
  71. }
  72. $_configuration['vchamilo_name'] = $_SERVER['SERVER_NAME'];
  73. }
  74. }
  75. /**
  76. * provides a side connection to a vchamilo database
  77. * @param array $vchamilo
  78. * @return a connection
  79. */
  80. function vchamilo_boot_connection(&$_configuration)
  81. {
  82. $dbParams = array(
  83. 'driver' => 'pdo_mysql',
  84. 'host' => $_configuration['db_host'],
  85. 'user' => $_configuration['db_user'],
  86. 'password' => $_configuration['db_password'],
  87. 'dbname' => isset($_configuration['main_database']) ? $_configuration['main_database'] : '',
  88. // Only relevant for pdo_sqlite, specifies the path to the SQLite database.
  89. 'path' => isset($_configuration['db_path']) ? $_configuration['db_path'] : '',
  90. // Only relevant for pdo_mysql, pdo_pgsql, and pdo_oci/oci8,
  91. 'port' => isset($_configuration['db_port']) ? $_configuration['db_port'] : ''
  92. );
  93. try {
  94. $database = new \Database();
  95. $connection = $database->connect($dbParams, $_configuration['root_sys'], $_configuration['root_sys'], true);
  96. } catch (Exception $e) {
  97. echo('Side connection failure with '.$_configuration['db_host'].', '.$_configuration['db_user'].', ******** ');
  98. die();
  99. }
  100. return $connection;
  101. }
  102. function vchamilo_redirect($url) {
  103. if (preg_match('#https?://#', $url)) {
  104. header('location: '.$url);
  105. } else {
  106. header('location: ' . api_get_path(WEB_PATH).$url);
  107. }
  108. exit;
  109. }
  110. function vchamilo_get_htaccess_fragment($course_folder)
  111. {
  112. $str = "
  113. # Change this file to fit your configuration and save it as .htaccess in the courses folder #
  114. # Chamilo mod rewrite
  115. # Comment lines start with # and are not processed
  116. <IfModule mod_rewrite.c>
  117. RewriteEngine On
  118. # Rewrite base is the dir chamilo is installed in with trailing slash
  119. RewriteBase /{$course_folder}/
  120. # Do not rewrite on the main dir
  121. # Change this path to the path of your main folder
  122. RewriteCond %{REQUEST_URI} !^/main/
  123. #replace nasty ampersands by 3 slashes, we change these back in download.php
  124. RewriteRule ([^/]+)/document/(.*)&(.*)$ $1/document/$2///$3 [N]
  125. # Rewrite everything in the scorm folder of a course to the download script
  126. RewriteRule ([^/]+)/scorm/(.*)$ /main/document/download_scorm.php?doc_url=/$2&cDir=$1 [QSA,L]
  127. # Rewrite everything in the document folder of a course to the download script
  128. RewriteRule ([^/]+)/document/(.*)$ /main/document/download.php?doc_url=/$2&cDir=$1 [QSA,L]
  129. # Rewrite everything in the work folder
  130. RewriteRule ([^/]+)/work/(.*)$ /main/work/download.php?file=work/$2&cDir=$1 [QSA,L]
  131. </IfModule>
  132. ";
  133. }
  134. function vchamilo_get_default_course_index_fragment() {
  135. return "<html><head></head><body></body></html>";
  136. }
  137. function vchamilo_template_exists($template) {
  138. global $_configuration;
  139. // Find and checktemplate directory (files and SQL).
  140. $separator = DIRECTORY_SEPARATOR;
  141. $templatefoldername = 'plugin'.$separator.'vchamilo'.$separator.'templates';
  142. $absolute_templatesdir = $_configuration['root_sys'].$templatefoldername;
  143. $relative_datadir = $templatefoldername.$separator.$template.'_sql';
  144. $absolute_datadir = $_configuration['root_sys'].$relative_datadir;
  145. return is_dir($absolute_datadir);
  146. }
  147. /**
  148. * drop a vchamilo instance databases using the physical connection
  149. * @param object $vchamilo
  150. * @param handle $side_cnx
  151. * return an array of errors or false if ok
  152. */
  153. function vchamilo_drop_databases(&$vchamilo)
  154. {
  155. global $plugininstance;
  156. if (is_array($vchamilo)) $vchamilo = (object)$vchamilo;
  157. // Drop databases you need to drop
  158. $sqls = array(" DROP DATABASE `{$vchamilo->main_database}` ");
  159. if (!empty($vchamilo->statistics_database) && ($vchamilo->main_database != $vchamilo->statistics_database)) {
  160. $sqls[] = " DROP DATABASE `{$vchamilo->statistics_database}` ";
  161. };
  162. if (!empty($vchamilo->user_personal_database) && ($vchamilo->user_personal_database != $vchamilo->statistics_database) && ($vchamilo->main_database != $vchamilo->user_personal_database)) {
  163. $sqls[] = " DROP DATABASE `{$vchamilo->user_personal_database}` ";
  164. }
  165. foreach($sqls as $sql){
  166. $res = Database::query($sql);
  167. if (!$res){
  168. $erroritem = new StdClass();
  169. $erroritem->message = $plugininstance->get_lang('couldnotdropdb');
  170. $erroritem->on = 'db';
  171. $erroritems[] = $erroritem;
  172. }
  173. }
  174. if (!empty($erroritems)){
  175. return $erroritems;
  176. }
  177. return false;
  178. }
  179. /**
  180. * Create all needed databases.
  181. * @uses $CFG The global configuration.
  182. * @param $vmoodledata object All the Host_form data.
  183. * @param $outputfile array The variables to inject in setup template SQL.
  184. * @return bool If TRUE, loading database from template was sucessful, otherwise FALSE.
  185. */
  186. function vchamilo_create_databases($vchamilo, $cnx = null)
  187. {
  188. // availability of SQL commands
  189. $createstatement = 'CREATE DATABASE %DATABASE% DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci ';
  190. $dbs = array($vchamilo->main_database);
  191. if (!empty($vchamilo->statistics_database) && $vchamilo->main_database != $vchamilo->statistics_database){
  192. $dbs[] = $vchamilo->statistics_database;
  193. }
  194. if (!empty($vchamilo->user_personal_database) && ($vchamilo->main_database != $vchamilo->user_personal_database) && ($vchamilo->statistics_database != $vchamilo->user_personal_database)){
  195. $dbs[] = $vchamilo->user_personal_database;
  196. }
  197. foreach($dbs as $adb){
  198. Display::addFlash(Display::return_message("Creating DB $adb"));
  199. $sql = str_replace('%DATABASE%', $adb, $createstatement);
  200. Database::query($sql);
  201. /*if(!$DB->execute_sql($sql)){
  202. print_error('noexecutionfor','block_vmoodle', $sql);
  203. return false;
  204. }*/
  205. }
  206. return true;
  207. }
  208. /**
  209. * get a proper SQLdump command
  210. * @param object $vmoodledata the complete new host information
  211. * @return string the shell command
  212. */
  213. function vchamilo_get_database_dump_cmd($vchamilodata)
  214. {
  215. global $CFG;
  216. $pgm = vchamilo_get_config('mysql_cmd');
  217. // Checks the needed program.
  218. Display::addFlash(Display::return_message("load_database_from_dump : checking database command"));
  219. if (!$pgm){
  220. $pgm = '/usr/bin/mysql';
  221. Display::addFlash(Display::return_message("Using default database command $pgm "));
  222. }
  223. $phppgm = str_replace("\\", '/', $pgm);
  224. $phppgm = str_replace("\"", '', $phppgm);
  225. $pgm = str_replace("/", DIRECTORY_SEPARATOR, $pgm);
  226. Display::addFlash(Display::return_message('load_database_from_dump : checking command is available'));
  227. if (!is_executable($phppgm)){
  228. print_error('databasecommanddoesnotmatchanexecutablefile');
  229. return false;
  230. }
  231. // Retrieves the host configuration (more secure).
  232. $vchamilodata = vchamilo_make_this();
  233. if (strstr($vchamilodata->db_host, ':') !== false){
  234. list($vchamilodata->db_host, $vchamilodata->db_port) = split(':', $vchamilodata->db_host);
  235. }
  236. // Password.
  237. if (!empty($vchamilodata->db_password)){
  238. $vchamilodata->db_password = '-p'.escapeshellarg($vchamilodata->db_password).' ';
  239. }
  240. // Making the command line (see 'vconfig.php' file for defining the right paths).
  241. $sqlcmd = $pgm.' -h'.$vchamilodata->db_host.(isset($vchamilodata->db_port) ? ' -P'.$vchamilodata->db_port.' ' : ' ' );
  242. $sqlcmd .= '-u'.$vchamilodata->db_user.' '.$vchamilodata->db_password;
  243. $sqlcmd .= '%DATABASE% < ';
  244. return $sqlcmd;
  245. }
  246. function vchamilo_load_db_template($vchamilo, $dbtemplate, $template){
  247. global $_configuration;
  248. // Make template directory (files and SQL).
  249. $separator = DIRECTORY_SEPARATOR;
  250. $templatefoldername = 'plugin'.$separator.'vchamilo'.$separator.'templates';
  251. $absolute_templatesdir = $_configuration['root_sys'].$templatefoldername;
  252. $relative_datadir = $templatefoldername.$separator.$template.'_sql';
  253. $absolute_datadir = $_configuration['root_sys'].$relative_datadir;
  254. $filerad = preg_replace('/_database$/', '', $dbtemplate);
  255. $sqlfile = 'chamilo_master_'.$filerad.'.sql';
  256. if (!$sqlcmd = vchamilo_get_database_dump_cmd($vchamilo)){
  257. return false;
  258. }
  259. $sqlcmd = str_replace('%DATABASE%', $vchamilo->$dbtemplate, $sqlcmd);
  260. // Make final commands to execute, depending on the database type.
  261. $import = $sqlcmd.$absolute_datadir.'/'.$sqlfile;
  262. // Execute the command.
  263. Display::addFlash(Display::return_message("load_database_from_dump : executing feeding sql as \n $import "));
  264. if (!defined('CLI_SCRIPT')){
  265. putenv('LANG=en_US.utf-8');
  266. }
  267. // ensure utf8 is correctly handled by php exec()
  268. // @see http://stackoverflow.com/questions/10028925/call-a-program-via-shell-exec-with-utf-8-text-input
  269. exec($import, $output, $return);
  270. Display::addFlash(Display::return_message(implode("\n", $output)."\n"));
  271. return true;
  272. }
  273. /**
  274. * load a bulk sql in database that is given through a vchamilo configuration record.
  275. * @param object $vchamilo
  276. * @param string $bulfile a bulk file of queries to process on the database
  277. * @param handle $cnx
  278. * @param array $vars an array of vars to inject in the bulk file before processing
  279. */
  280. function vchamilo_execute_db_sql(&$vchamilo, $bulkfile, $cnx = null, $vars=null, $filter=null){
  281. global $_configuration;
  282. if (file_exists($bulkfile)){
  283. $erroritem = new StdClass();
  284. $erroritem->message = "vchamilo_load_db_template : Bulk file $bulkfile not found";
  285. $erroritems[] = $erroritem;
  286. return $erroritem;
  287. }
  288. $local_cnx = 0;
  289. if (is_null($cnx)){
  290. $cnx = vchamilo_make_connection($vchamilo, true);
  291. $local_cnx = 1;
  292. }
  293. /// get dump file
  294. $sql = file($bulkfile);
  295. // converts into an array of text lines
  296. $dumpfile = implode('', $sql);
  297. if ($filter){
  298. foreach($filter as $from => $to){
  299. $dumpfile = mb_ereg_replace(preg_quote($from), $to, $dumpfile);
  300. }
  301. }
  302. // insert any external vars
  303. if (!empty($vars)){
  304. foreach($vars as $key => $value){
  305. // for debug : echo "$key => $value";
  306. $dumpfile = str_replace("<%%$key%%>", $value, $dumpfile);
  307. }
  308. }
  309. $sql = explode ("\n", $dumpfile);
  310. // cleanup unuseful things
  311. $sql = preg_replace("/^--.*/", "", $sql);
  312. $sql = preg_replace("/^\/\*.*/", "", $sql);
  313. $dumpfile = implode("\n", $sql);
  314. /// split into single queries
  315. $dumpfile = str_replace("\r\n", "\n", $dumpfile); // translates to Unix LF
  316. $queries = preg_split("/;\n/", $dumpfile);
  317. /// feed queries in database
  318. $i = 0;
  319. $j = 0;
  320. $l = 0;
  321. if (!empty($queries)){
  322. foreach($queries as $query){
  323. $query = trim($query); // get rid of trailing spaces and returns
  324. if ($query == '') continue; // avoid empty queries
  325. $query = mb_convert_encoding($query, 'iso-8859-1', 'auto');
  326. if (!$res = vchamilo_execute_query($vchamilo, $query, $cnx)){
  327. $erroritem = new StdClass();
  328. $erroritem->message = "vchamilo_load_db_template : Load error on query $l";
  329. $erroritem->content = $query;
  330. $erroritems[] = $erroritem;
  331. $j++;
  332. } else {
  333. $i++;
  334. }
  335. $l++;
  336. }
  337. }
  338. echo "loaded : $i queries succeeded, $j queries failed<br/>";
  339. if ($local_cnx){
  340. vchamilo_close_connection($vchamilo, $cnx);
  341. }
  342. if (!empty($erroritems)){
  343. return $erroritems;
  344. }
  345. return false;
  346. }
  347. /**
  348. * Dumps a SQL database for having a snapshot.
  349. * @param $vchamilo object The Vchamilo object.
  350. * @param $outputfilerad string The output SQL file radical.
  351. * @return bool If TRUE, dumping database was a success, otherwise FALSE.
  352. */
  353. function vchamilo_dump_databases($vchamilo, $outputfilerad)
  354. {
  355. global $CFG;
  356. // Separating host and port, if sticked.
  357. if (strstr($vchamilo->db_host, ':') !== false){
  358. list($host, $port) = split(':', $vchamilo->db_host);
  359. } else {
  360. $host = $vchamilo->db_host;
  361. }
  362. // By default, empty password.
  363. $pass = '';
  364. $pgm = null;
  365. if (empty($port)) {
  366. $port = 3306;
  367. }
  368. // Password.
  369. if (!empty($vchamilo->db_password)){
  370. $pass = "-p".escapeshellarg($vchamilo->db_password);
  371. }
  372. // Making the commands for each database.
  373. $cmds = array();
  374. //if ($CFG->ostype == 'WINDOWS') {
  375. if (false) {
  376. $cmd_main = "-h{$host} -P{$port} -u{$vchamilo->db_user} {$pass} {$vchamilo->main_database}";
  377. $cmds[] = $cmd_main . ' > ' . $outputfilerad.'_main.sql';
  378. if ($vchamilo->statistics_database != $vchamilo->main_database){
  379. $cmd_stats = "-h{$host} -P{$port} -u{$vchamilo->db_user} {$pass} {$vchamilo->statistics_database}";
  380. $cmds[] = $cmd_stats . ' > ' . $outputfilerad.'_statistics.sql';
  381. }
  382. if (($vchamilo->user_personal_database != $vchamilo->main_database) && ($vchamilo->user_personal_database != $vchamilo->statistics_database)) {
  383. $cmd_user = "-h{$host} -P{$port} -u{$vchamilo->db_user} {$pass} {$vchamilo->user_personal_database}";
  384. $cmds[] = $cmd_user . ' > ' . $outputfilerad.'_user_personal.sql';
  385. }
  386. } else {
  387. $cmd_main = "-h{$host} -P{$port} -u{$vchamilo->db_user} {$pass} {$vchamilo->main_database}";
  388. $cmds[] = $cmd_main . ' > ' . escapeshellarg($outputfilerad.'_main.sql');
  389. }
  390. $mysqldumpcmd = vchamilo_get_config('vchamilo', 'cmd_mysqldump', true);
  391. $pgm = !empty($mysqldumpcmd) ? stripslashes($mysqldumpcmd) : false ;
  392. if (!$pgm) {
  393. $erroritem = new StdClass();
  394. $erroritem->message = "Database dump command not available check here: ";
  395. $url = api_get_path(WEB_CODE_PATH).'admin/configure_plugin.php?name=vchamilo';
  396. $erroritem->message .= Display::url($url, $url);
  397. return array($erroritem);
  398. } else {
  399. $phppgm = str_replace("\\", '/', $pgm);
  400. $phppgm = str_replace("\"", '', $phppgm);
  401. $pgm = str_replace('/', DIRECTORY_SEPARATOR, $pgm);
  402. if (!is_executable($phppgm)){
  403. $erroritem = new StdClass();
  404. $erroritem->message = "Database dump command $phppgm does not match any executable";
  405. return array($erroritem);
  406. }
  407. // executing all commands
  408. foreach($cmds as $cmd){
  409. // Final command.
  410. $cmd = $pgm.' '.$cmd;
  411. // Prints log messages in the page and in 'cmd.log'.
  412. if ($LOG = fopen(dirname($outputfilerad).'/cmd.log', 'a')){
  413. fwrite($LOG, $cmd."\n");
  414. }
  415. // Executes the SQL command.
  416. exec($cmd, $execoutput, $returnvalue);
  417. if ($LOG){
  418. foreach($execoutput as $execline) fwrite($LOG, $execline."\n");
  419. fwrite($LOG, $returnvalue."\n");
  420. fclose($LOG);
  421. }
  422. }
  423. }
  424. // End with success.
  425. return 0;
  426. }
  427. /**
  428. * read manifest values in vchamilo template.
  429. * @uses $CFG
  430. */
  431. function vchamilo_get_vmanifest($version)
  432. {
  433. include(api_get_path(SYS_PATH, SYS_PATH).'/plugin/vchamilo/templates/'.$version.'_sql/manifest.php');
  434. $manifest->templatewwwroot = $templatewwwroot;
  435. $manifest->templatevdbprefix = $templatevdbprefix;
  436. $manifest->coursefolder = $coursefolder;
  437. return $manifest;
  438. }
  439. /**
  440. * make a fake vchamilo that represents the current host
  441. */
  442. function vchamilo_make_this()
  443. {
  444. global $_configuration;
  445. $thisPortal = new stdClass();
  446. $thisPortal->root_web = $_configuration['root_web'];
  447. $thisPortal->db_host = $_configuration['db_host'];
  448. $thisPortal->db_user = $_configuration['db_user'];
  449. $thisPortal->db_password = $_configuration['db_password'];
  450. $thisPortal->main_database = $_configuration['main_database'];
  451. return $thisPortal;
  452. }
  453. /**
  454. * Get available templates for defining a new virtual host.
  455. * @return array The availables templates, or EMPTY array.
  456. */
  457. function vchamilo_get_available_templates()
  458. {
  459. global $_configuration;
  460. global $plugininstance;
  461. $separator = DIRECTORY_SEPARATOR;
  462. $templatefoldername = 'plugin'.$separator.'vchamilo'.$separator.'templates';
  463. $absolute_templatesdir = $_configuration['root_sys'].$templatefoldername;
  464. // Scans the templates.
  465. if (!is_dir($absolute_templatesdir)){
  466. mkdir($absolute_templatesdir, 0777, true);
  467. }
  468. $dirs = glob($absolute_templatesdir.'/*');
  469. $vtemplates = preg_grep("/[^\/](.*)_vchamilodata$/", $dirs);
  470. // Retrieves template(s) name(s). Should be hostnames.
  471. $templatesarray = array('' => $plugininstance->get_lang('emptysite'));
  472. if ($vtemplates){
  473. foreach($vtemplates as $vtemplatedir){
  474. preg_match("/([^\/]*)_vchamilodata/", $vtemplatedir, $matches);
  475. $templatesarray[$matches[1]] = $matches[1];
  476. if (!isset($first)) $first = $matches[1];
  477. }
  478. }
  479. return $templatesarray;
  480. }
  481. function vchamilo_print_error($errortrace, $return = false)
  482. {
  483. $str = '';
  484. if (!empty($errortrace)){
  485. $str .= '<div class="vchamilo-errors" style="border:1px solid #a0a0a0;background-color:#ffa0a0;padding:5px;font-size:10px">';
  486. $str .= '<pre>';
  487. foreach($errortrace as $error){
  488. $str .= $error->message.'<br/>';
  489. $str .= @$error->content;
  490. }
  491. $str .= '</pre>';
  492. $str .= '</div>';
  493. }
  494. if ($return) return $str;
  495. Display::addFlash(Display::return_message($str));
  496. }
  497. /**
  498. * this function set will map standard moodle API calls to chamilo
  499. * internal primitives. This avoids too many changes to do in imported
  500. * code
  501. *
  502. */
  503. function vchamilo_get_config($module, $key, $isplugin = true)
  504. {
  505. if ($isplugin) {
  506. $key = $module.'_'.$key;
  507. }
  508. $params = array('variable = ? AND subkey = ?' => [$key, $module]);
  509. $result = api_get_settings_params_simple($params);
  510. if ($result) {
  511. return $result['selected_value'];
  512. }
  513. return false;
  514. }
  515. function vchamilo_load_files_from_template($vchamilo, $template)
  516. {
  517. global $_configuration;
  518. // Make template directory (files and SQL).
  519. $separator = DIRECTORY_SEPARATOR;
  520. $templatefoldername = 'plugin'.$separator.'vchamilo'.$separator.'templates';
  521. $relative_template_datadir = $templatefoldername.$separator.$template.'_vchamilodata';
  522. $absolute_templatesdir = $_configuration['root_sys'].$templatefoldername;
  523. $absolute_template_datadir = $_configuration['root_sys'].$relative_template_datadir;
  524. $vchamilo->virtual = true;
  525. // Get Vchamilo known record.
  526. $vcoursepath = api_get_path(SYS_COURSE_PATH, (array)$vchamilo);
  527. $vhomepath = api_get_path(SYS_HOME_PATH, (array)$vchamilo);
  528. $varchivepath = api_get_path(SYS_ARCHIVE_PATH, (array)$vchamilo);
  529. echo "archiveapth : $varchivepath";
  530. // Rename some dirs top match instance requirements
  531. $manifest = vchamilo_get_vmanifest($template);
  532. // get the protocol free hostname
  533. $originarchivedir = preg_replace('/https?:\/\//', '', $manifest->templatewwwroot);
  534. $originhomedir = preg_replace('/https?:\/\//', '', $manifest->templatewwwroot);
  535. Display::addFlash(Display::return_message("Copying {$absolute_template_datadir}/{$manifest->coursefolder} => $vcoursepath"));
  536. Display::addFlash(Display::return_message("Copying {$absolute_template_datadir}/archive/{$originarchivedir} => $varchivepath"));
  537. Display::addFlash(Display::return_message("Copying {$absolute_template_datadir}/home/{$originhomedir} => $vhomepath"));
  538. copyDirContentTo(chop_last_slash($absolute_template_datadir.'/'.$manifest->coursefolder), chop_last_slash($vcoursepath), false);
  539. copyDirContentTo(chop_last_slash($absolute_template_datadir.'/archive/'.$originarchivedir), chop_last_slash($varchivepath), false);
  540. copyDirContentTo(chop_last_slash($absolute_template_datadir.'/home/'.$originhomedir), chop_last_slash($vhomepath), false);
  541. }
  542. function chop_last_slash($path)
  543. {
  544. return preg_replace('/\/$/', '', $path);
  545. }
  546. /**
  547. * Moves a directory and its content to an other area
  548. *
  549. * @author - Hugues Peeters <peeters@ipm.ucl.ac.be>
  550. * @param - $orig_dir_path (string) - the path of the directory to move
  551. * @param - $destination (string) - the path of the new area
  552. * @return - no return
  553. */
  554. function copyDirContentTo($source, $destination, $move = true) {
  555. // Extract directory name - create it at destination - update destination trail
  556. if (!is_dir($source)) {
  557. return;
  558. }
  559. if (!is_dir($destination)) {
  560. mkdir($destination, api_get_permissions_for_new_directories());
  561. }
  562. $DIR = opendir($source);
  563. while ($element = readdir($DIR)) {
  564. if ($element == '.' || $element == '..') {
  565. continue; // Skip the current and parent directories
  566. } elseif (is_file($source.'/'.$element)) {
  567. copy($source.'/'.$element, $destination.'/'.$element);
  568. if ($move) {
  569. unlink($source.'/'.$element) ;
  570. }
  571. } elseif (is_dir($source.'/'.$element)) {
  572. $dirs_to_copy[] = $element;
  573. }
  574. }
  575. closedir($DIR) ;
  576. if (sizeof($dirs_to_copy) > 0) {
  577. foreach ($dirs_to_copy as $dir) {
  578. copyDirContentTo($source.'/'.$dir, $destination.'/'.$dir, $move); // Recursivity
  579. }
  580. }
  581. if ($move) {
  582. rmdir($source) ;
  583. }
  584. }
  585. // from moot
  586. define('PARAM_BOOL', 1);
  587. define('PARAM_INT', 2);
  588. define('PARAM_TEXT', 3);
  589. define('PARAM_RAW', 4);
  590. /**
  591. * this function set will map standard moodle API calls to chamilo
  592. * internal primitives. This avoids too many changes to do in imported
  593. * code
  594. *
  595. */
  596. function get_config($module, $key = false, $isplugin = true) {
  597. global $_configuration, $DB;
  598. static $static_settings;
  599. if (!isset($static_settings)) {
  600. include_once $_configuration['root_sys'].'local/ent_installer/static_settings.php';
  601. }
  602. if ($isplugin){
  603. $configkey = $module.'_'.$key;
  604. } else {
  605. $configkey = $key;
  606. }
  607. if ($module == 'ent_installer') {
  608. $dyna_setting = $DB->get_field(TABLE_MAIN_SETTINGS_CURRENT, 'selected_value', array('subkey' => 'ent_installer', 'variable' => $configkey));
  609. if (!is_null($dyna_setting)) {
  610. return $dyna_setting;
  611. }
  612. if (empty($config)) {
  613. Display::addFlash(Display::return_message("Wrap to static setting $module,$configkey "));
  614. if (array_key_exists($key, $static_settings)){
  615. return $static_settings[$key];
  616. }
  617. }
  618. } else {
  619. if (!$module) {
  620. return $DB->get_field(TABLE_MAIN_SETTINGS_CURRENT, 'selected_value', array('variable' => $configkey));
  621. }
  622. if ($key) {
  623. return $DB->get_field(TABLE_MAIN_SETTINGS_CURRENT, 'selected_value', array('variable' => $configkey, 'subkey' => $module));
  624. } else {
  625. // Get all config from a subkey as an object
  626. $configs = $DB->get_records(TABLE_MAIN_SETTINGS_CURRENT, array('subkey' => $module));
  627. if (!empty($configs)) {
  628. $config = new StdClass;
  629. foreach ($configs as $cf) {
  630. $key = str_replace($module.'_', '', $cf->variable);
  631. $config->$key = $cf->selected_value;
  632. }
  633. return $config;
  634. }
  635. return null;
  636. }
  637. }
  638. }
  639. function set_config($key, $value, $module, $isplugin = false) {
  640. if ($isplugin) {
  641. $key = $module.'_'.$key;
  642. }
  643. if ($isplugin) {
  644. // ensure setting is actually in database
  645. api_update_setting($value, $key, $module);
  646. } else {
  647. api_update_setting($value, $module, $key);
  648. }
  649. }
  650. /**
  651. * gets a string from a component
  652. *
  653. */
  654. function get_string($key, $component = 'local_ent_installer', $a = ''){
  655. global $_configuration;
  656. static $strings;
  657. static $fallbackstrings;
  658. if ($component == 'local_ent_installer') {
  659. $fallbackpath = $_configuration['root_sys'].'local/ent_installer/lang/english/local_ent_installer.php';
  660. if (!isset($strings)) {
  661. $lang = api_get_language_from_type('platform_lang');
  662. if (empty($lang)) $lang = 'english';
  663. $path = $_configuration['root_sys'].'local/ent_installer/lang/'.$lang.'/local_ent_installer.php';
  664. if (!file_exists($path)) {
  665. if (!file_exists($path)) {
  666. print_error('missinglang', null);
  667. die;
  668. }
  669. if (!isset($fallbackstrings)) {
  670. include $fallbackpath;
  671. $fallbackstrings = $string;
  672. }
  673. }
  674. include $path;
  675. $strings = $string;
  676. }
  677. if (!array_key_exists($key, $strings)) {
  678. if (!isset($fallbackstrings)) {
  679. include $fallbackpath;
  680. $fallbackstrings = $string;
  681. }
  682. if (!array_key_exists($key, $fallbackstrings)) {
  683. return "[[$key]]";
  684. }
  685. if (is_scalar($a)) {
  686. return str_replace('{$a}', $a, $fallbackstrings[$key]);
  687. }
  688. if (is_array($a)) {
  689. $a = (object)$a;
  690. }
  691. if (is_object($a)) {
  692. return replace_string_vars($a, $fallbackstrings[$key]);
  693. }
  694. debugging('String insertion not supported', 1);
  695. die;
  696. }
  697. if (is_scalar($a)) {
  698. return str_replace('{$a}', $a, $strings[$key]);
  699. }
  700. if (is_array($a)){
  701. $a = (object)$a;
  702. }
  703. if (is_object($a)){
  704. return replace_string_vars($a, $strings[$key]);
  705. }
  706. debugging('String insertion not supported', 1);
  707. die;
  708. } else {
  709. return get_lang($key);
  710. }
  711. }
  712. function replace_string_vars($a, $str){
  713. preg_match_all('/{\$a-\>(.+?)}/', $str, $matches);
  714. if (!empty($matches[1])){
  715. foreach($matches[1] as $replacekey){
  716. $str = str_replace('{$a->'.$replacekey.'}', $a->$replacekey, $str);
  717. }
  718. }
  719. return $str;
  720. }
  721. function print_error($key, $component = '', $passthru = false, $extrainfo = ''){
  722. global $debuglevel;
  723. global $debugdisplay;
  724. if ($component === null){
  725. $str = $key;
  726. } else {
  727. $str = get_string($string, $component);
  728. }
  729. ctrace('ERROR: '. $str);
  730. if (!empty($extrainfo)){
  731. ctrace('Extra: '. $extrainfo);
  732. }
  733. if ($debugdisplay >= 3){
  734. debug_print_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS);
  735. }
  736. if (!$passthru) die;
  737. }
  738. function debugging($message, $level) {
  739. global $debuglevel;
  740. global $debugdisplay;
  741. if ($level <= $debuglevel) {
  742. ctrace('DEBUG: '.$message);
  743. if ($debugdisplay >= 3){
  744. debug_print_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS);
  745. }
  746. }
  747. }
  748. /**
  749. * Wrap moodle to chamilo side
  750. *
  751. */
  752. function mtrace($message){
  753. ctrace($message);
  754. }
  755. function ctrace($str) {
  756. if (!defined('CLI_SCRIPT')) echo "<pre>";
  757. Display::addFlash(Display::return_message($str));
  758. if (!defined('CLI_SCRIPT')) echo "</pre>";
  759. }
  760. /**
  761. * Sets a platform configuration setting to a given value, creating it if necessary
  762. * @param string The value we want to record
  763. * @param string The variable name we want to insert
  764. * @param string The subkey for the variable we want to insert
  765. * @param string The type for the variable we want to insert
  766. * @param string The category for the variable we want to insert
  767. * @param string The title
  768. * @param string The comment
  769. * @param string The scope
  770. * @param string The subkey text
  771. * @param int The access_url for which this parameter is valid
  772. * @param int The changeability of this setting for non-master urls
  773. * @return boolean true on success, false on failure
  774. */
  775. function api_update_setting($val, $var, $sk = null, $type = 'textfield', $c = null, $title = '', $com = '', $sc = null, $skt = null, $a = 1, $v = 0) {
  776. global $_setting;
  777. if (empty($var) || !isset($val)) {
  778. return false;
  779. }
  780. $t_settings = Database::get_main_table(TABLE_MAIN_SETTINGS_CURRENT);
  781. $var = Database::escape_string($var);
  782. $val = Database::escape_string($val);
  783. $a = (int) $a;
  784. if (empty($a)) { $a = 1; }
  785. // Check if this variable doesn't exist already
  786. $select = "SELECT id FROM $t_settings WHERE variable = '$var' ";
  787. if (!empty($sk)) {
  788. $sk = Database::escape_string($sk);
  789. $select .= " AND subkey = '$sk'";
  790. }
  791. if ($a > 1) {
  792. $select .= " AND access_url = $a";
  793. } else {
  794. $select .= " AND access_url = 1 ";
  795. }
  796. $res = Database::query($select);
  797. if (Database::num_rows($res) > 0) { // Found item for this access_url.
  798. $row = Database::fetch_array($res);
  799. // update value
  800. $update['selected_value'] = $val;
  801. Database::update($t_settings, $update, array('id = ?' => $row['id']));
  802. return $row['id'];
  803. // update in memory setting value
  804. $_setting[$var][$sk] = $val;
  805. }
  806. // Item not found for this access_url, we have to check if the whole thing is missing
  807. // (in which case we ignore the insert) or if there *is* a record but just for access_url = 1
  808. $insert = "INSERT INTO $t_settings " .
  809. "(variable,selected_value," .
  810. "type,category," .
  811. "subkey,title," .
  812. "comment,scope," .
  813. "subkeytext,access_url,access_url_changeable)" .
  814. " VALUES ('$var','$val',";
  815. if (isset($type)) {
  816. $type = Database::escape_string($type);
  817. $insert .= "'$type',";
  818. } else {
  819. $insert .= "NULL,";
  820. }
  821. if (isset($c)) { // Category
  822. $c = Database::escape_string($c);
  823. $insert .= "'$c',";
  824. } else {
  825. $insert .= "NULL,";
  826. }
  827. if (isset($sk)) { // Subkey
  828. $sk = Database::escape_string($sk);
  829. $insert .= "'$sk',";
  830. } else {
  831. $insert .= "NULL,";
  832. }
  833. if (isset($title)) { // Title
  834. $title = Database::escape_string($title);
  835. $insert .= "'$title',";
  836. } else {
  837. $insert .= "NULL,";
  838. }
  839. if (isset($com)) { // Comment
  840. $com = Database::escape_string($com);
  841. $insert .= "'$com',";
  842. } else {
  843. $insert .= "NULL,";
  844. }
  845. if (isset($sc)) { // Scope
  846. $sc = Database::escape_string($sc);
  847. $insert .= "'$sc',";
  848. } else {
  849. $insert .= "NULL,";
  850. }
  851. if (isset($skt)) { // Subkey text
  852. $skt = Database::escape_string($skt);
  853. $insert .= "'$skt',";
  854. } else {
  855. $insert .= "NULL,";
  856. }
  857. $insert .= "$a,$v)";
  858. $res = Database::query($insert);
  859. // update in memory setting value
  860. $_setting[$var][$sk] = $value;
  861. return $res;
  862. }
  863. /**
  864. * converts a timestamp to sql tms
  865. * @param lint $time a unix timestamp
  866. */
  867. function make_tms($time) {
  868. $tms = date('Y-m-d H:i:s', $time);
  869. return $tms;
  870. }
  871. /**
  872. * Makes sure the data is using valid utf8, invalid characters are discarded.
  873. *
  874. * Note: this function is not intended for full objects with methods and private properties.
  875. *
  876. * @param mixed $value
  877. * @return mixed with proper utf-8 encoding
  878. */
  879. function fix_utf8($value) {
  880. if (is_null($value) or $value === '') {
  881. return $value;
  882. } else if (is_string($value)) {
  883. if ((string)(int)$value === $value) {
  884. // shortcut
  885. return $value;
  886. }
  887. // Lower error reporting because glibc throws bogus notices.
  888. $olderror = error_reporting();
  889. if ($olderror & E_NOTICE) {
  890. error_reporting($olderror ^ E_NOTICE);
  891. }
  892. // Note: this duplicates min_fix_utf8() intentionally.
  893. static $buggyiconv = null;
  894. if ($buggyiconv === null) {
  895. $buggyiconv = (!function_exists('iconv') or iconv('UTF-8', 'UTF-8//IGNORE', '100'.chr(130).'\80') !== '100\80');
  896. }
  897. if ($buggyiconv) {
  898. if (function_exists('mb_convert_encoding')) {
  899. $subst = mb_substitute_character();
  900. mb_substitute_character('');
  901. $result = mb_convert_encoding($value, 'utf-8', 'utf-8');
  902. mb_substitute_character($subst);
  903. } else {
  904. // Warn admins on admin/index.php page.
  905. $result = $value;
  906. }
  907. } else {
  908. $result = iconv('UTF-8', 'UTF-8//IGNORE', $value);
  909. }
  910. if ($olderror & E_NOTICE) {
  911. error_reporting($olderror);
  912. }
  913. return $result;
  914. } else if (is_array($value)) {
  915. foreach ($value as $k=>$v) {
  916. $value[$k] = fix_utf8($v);
  917. }
  918. return $value;
  919. } else if (is_object($value)) {
  920. $value = clone($value); // do not modify original
  921. foreach ($value as $k=>$v) {
  922. $value->$k = fix_utf8($v);
  923. }
  924. return $value;
  925. } else {
  926. // this is some other type, no utf-8 here
  927. return $value;
  928. }
  929. }
  930. function print_object($obj) {
  931. echo '<pre>';
  932. print_r($obj);
  933. echo '</pre>';
  934. }
  935. function require_js($file, $component, $return = false)
  936. {
  937. global $_configuration, $htmlHeadXtra;
  938. if (preg_match('/^local_/', $component)) {
  939. $component = str_replace('local_', '', $component);
  940. $path = 'local/';
  941. } else {
  942. $path = 'plugin/';
  943. }
  944. // Secure the postslashing of the roots.
  945. $root_web = $_configuration['root_web'].'/';
  946. $root_web = preg_replace('#//$#', '/', $root_web);
  947. $str = '<script type="text/javascript" src="'.$root_web.$path.$component.'/js/'.$file.'"></script>'."\n";
  948. if ($return === 'head') {
  949. $htmlHeadXtra[] = $str;
  950. }
  951. if ($return) {
  952. return $str;
  953. }
  954. echo $str;
  955. }
  956. function require_css($file, $component, $return = false)
  957. {
  958. global $_configuration, $htmlHeadXtra;
  959. if (preg_match('/^local_/', $component)) {
  960. $component = str_replace('local_', '', $component);
  961. $path = 'local/';
  962. } else {
  963. $path = 'plugin/';
  964. }
  965. // Secure the postslashing of the roots.
  966. $root_web = $_configuration['root_web'].'/';
  967. $root_web = preg_replace('#//$#', '/', $root_web);
  968. $str = '<link rel="stylesheet" type="text/css" href="'.$root_web.$path.$component.'/'.$file.'.css" />'."\n";
  969. if ($return === 'head') {
  970. $htmlHeadXtra[] = $str;
  971. }
  972. if ($return) {
  973. return $str;
  974. }
  975. echo $str;
  976. }
  977. /**
  978. *
  979. */
  980. function required_param($key, $type = 0)
  981. {
  982. if (array_key_exists($key, $_REQUEST)) {
  983. $value = $_REQUEST[$key];
  984. $value = param_filter_type($value, $type);
  985. return $value;
  986. }
  987. die("Missing expected param $key in request input");
  988. }
  989. function optional_param($key, $default, $type = 0)
  990. {
  991. if (array_key_exists($key, $_REQUEST)) {
  992. $value = $_REQUEST[$key];
  993. $value = param_filter_type($value, $type);
  994. return $value;
  995. }
  996. return $default;
  997. }
  998. function param_filter_type($value, $type)
  999. {
  1000. switch($type) {
  1001. case 0:
  1002. return $value; // no filtering
  1003. case PARAM_BOOL:
  1004. return $value == 0; // forces outputing boolean
  1005. case PARAM_INT:
  1006. if (preg_match('/^([1-90]+)/', $value, $matches)) {
  1007. return $matches[1];
  1008. }
  1009. return 0;
  1010. case PARAM_TEXT:
  1011. // TODO more filtering here
  1012. return $value;
  1013. }
  1014. }
  1015. function redirect($url) {
  1016. header("Location: $url\n\n");
  1017. }