lib.php 36 KB

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