lib.php 35 KB

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