lib.php 37 KB

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