Virtual.php 45 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361
  1. <?php
  2. /* For licensing terms, see /license.txt */
  3. use Cocur\Slugify\Slugify;
  4. use Symfony\Component\Finder\Finder;
  5. use Symfony\Component\Console\Input\ArrayInput;
  6. use Symfony\Component\Console\Output\StreamOutput;
  7. use Symfony\Component\Console\Application;
  8. use Doctrine\ORM\EntityManager;
  9. /**
  10. * Class Virtual
  11. */
  12. class Virtual
  13. {
  14. /**
  15. * @param array $_configuration
  16. */
  17. public static function hookConfiguration(& $_configuration)
  18. {
  19. global $virtualChamilo;
  20. if (defined('CLI_SCRIPT') && !defined('CLI_VCHAMILO_OVERRIDE')) {
  21. return;
  22. }
  23. // provides an effective value for the virtual root_web based on domain analysis
  24. self::getHostName($_configuration);
  25. // We are on physical chamilo. Let original config play
  26. $virtualChamiloWebRoot = rtrim($_configuration['vchamilo_web_root'], '/') . '/';
  27. $virtualChamilo = [];
  28. if ($_configuration['root_web'] == $virtualChamiloWebRoot) {
  29. return;
  30. }
  31. // pre hook to chamilo main table and get alternate configuration.
  32. // sure Database object is not set up. Soo use bootstrap connection
  33. /** @var \Doctrine\DBAL\Connection $connection */
  34. $connection = Virtual::bootConnection($_configuration);
  35. $query = "SELECT * FROM vchamilo WHERE root_web = '$virtualChamiloWebRoot'";
  36. $result = $connection->executeQuery($query);
  37. if ($result->rowCount()) {
  38. $data = $result->fetch();
  39. $excludes = array('id', 'name');
  40. $query = "SELECT * FROM settings_current WHERE subkey = 'vchamilo'";
  41. $virtualSettings = $connection->executeQuery($query);
  42. $virtualSettings = $virtualSettings->fetchAll();
  43. $homePath = '';
  44. $coursePath = '';
  45. $archivePath = '';
  46. $uploadPath = '';
  47. $passwordEncryption = '';
  48. foreach ($virtualSettings as $setting) {
  49. switch ($setting['variable']) {
  50. case 'vchamilo_upload_real_root':
  51. $uploadPath = $setting['selected_value'];
  52. break;
  53. case 'vchamilo_home_real_root':
  54. $homePath = $setting['selected_value'];
  55. break;
  56. case 'vchamilo_course_real_root':
  57. $coursePath = $setting['selected_value'];
  58. break;
  59. case 'vchamilo_archive_real_root':
  60. $archivePath = $setting['selected_value'];
  61. break;
  62. case 'vchamilo_password_encryption':
  63. $passwordEncryption = $setting['selected_value'];
  64. break;
  65. }
  66. }
  67. if (empty($homePath) || empty($coursePath) || empty($archivePath) || empty($uploadPath)) {
  68. echo 'Configure correctly the vchamilo plugin';
  69. exit;
  70. }
  71. // Only load if is visible
  72. if ($data && $data['visible'] === '1') {
  73. foreach ($data as $key => $value) {
  74. if (!in_array($key, $excludes)) {
  75. // Avoid empty password_encryption
  76. if ($key == 'password_encryption' && empty($value)) {
  77. continue;
  78. }
  79. $_configuration[$key] = $value;
  80. }
  81. $_configuration['virtual'] = $data['root_web'].'/';
  82. }
  83. $data['SYS_ARCHIVE_PATH'] = self::addTrailingSlash($archivePath).$data['slug'];
  84. $data['SYS_HOME_PATH'] = self::addTrailingSlash($homePath).$data['slug'];
  85. $data['WEB_HOME_PATH'] = $_configuration['vchamilo_web_root'] . 'var/home/' . $data['slug'];
  86. $data['SYS_COURSE_PATH'] = self::addTrailingSlash($coursePath).$data['slug'];
  87. $data['WEB_HOME_PATH'] = $_configuration['vchamilo_web_root'] . 'var/courses/' . $data['slug'];
  88. $data['SYS_UPLOAD_PATH'] = self::addTrailingSlash($uploadPath).$data['slug'];
  89. $data['WEB_UPLOAD_PATH'] = $_configuration['vchamilo_web_root'] . 'var/upload/' . $data['slug'];
  90. if (!empty($passwordEncryption)) {
  91. $_configuration['password_encryption'] = $passwordEncryption;
  92. }
  93. $virtualChamilo = $data;
  94. } else {
  95. exit("This portal is disabled. Please contact your administrator");
  96. }
  97. } else {
  98. // Platform was not configured yet
  99. //die("VChamilo : Could not fetch virtual chamilo configuration");
  100. }
  101. }
  102. /**
  103. * @param array $_configuration
  104. */
  105. public static function getHostName(&$_configuration)
  106. {
  107. if (!empty($_SERVER['HTTP_X_FORWARDED_PROTO']) &&
  108. $_SERVER['HTTP_X_FORWARDED_PROTO'] == 'https' || !empty($_configuration['force_https_forwarded_proto'])
  109. ) {
  110. $protocol = 'https';
  111. } else {
  112. if (!empty($_SERVER['HTTPS'])) {
  113. $protocol = 'https';
  114. } else {
  115. $protocol = 'http';
  116. }
  117. }
  118. if (defined('CLI_VCHAMILO_OVERRIDE')) {
  119. $_configuration['vchamilo_web_root'] = CLI_VCHAMILO_OVERRIDE;
  120. $_configuration['vchamilo_name'] = preg_replace('#https?://#', '', CLI_VCHAMILO_OVERRIDE);
  121. // remove radical from override for name
  122. // fake the server signature
  123. global $_SERVER;
  124. $_SERVER['SERVER_NAME'] = $_configuration['vchamilo_name'];
  125. $_SERVER['HTTP_HOST'] = $_configuration['vchamilo_name'];
  126. $_SERVER['QUERY_STRING'] = '';
  127. $_SERVER['REQUEST_URI'] = CLI_VCHAMILO_OVERRIDE;
  128. return;
  129. }
  130. $contentPrefix = '/';
  131. if (isset($_SERVER['CONTEXT_PREFIX']) && !empty($_SERVER['CONTEXT_PREFIX'])) {
  132. $contentPrefix = $_SERVER['CONTEXT_PREFIX'];
  133. } else {
  134. // Getting url_append from URL
  135. if (isset($_SERVER['REQUEST_URI'])) {
  136. $requestUri = $_SERVER['REQUEST_URI'];
  137. if (strpos($requestUri, '/courses/') !== false) {
  138. $result = substr($requestUri, 0, strpos($requestUri, '/courses/'));
  139. if (!empty($result) && $result != '/') {
  140. $contentPrefix = $result;
  141. }
  142. }
  143. }
  144. }
  145. $_configuration['vchamilo_web_root'] = "{$protocol}://".@$_SERVER['HTTP_HOST'].$contentPrefix;
  146. $_configuration['vchamilo_name'] = @$_SERVER['HTTP_HOST'];
  147. if (empty($_configuration['vchamilo_name'])) { // try again with another source if has failed
  148. $_configuration['vchamilo_name'] = "{$protocol}://".$_SERVER['SERVER_NAME'];
  149. if ($_SERVER['SERVER_PORT'] != 80) {
  150. $_configuration['vchamilo_name'] .= ':'.$_SERVER['SERVER_PORT'];
  151. }
  152. $_configuration['vchamilo_name'] = $_SERVER['SERVER_NAME'];
  153. }
  154. }
  155. /**
  156. * @param string $path
  157. * @return string
  158. */
  159. public static function addTrailingSlash($path)
  160. {
  161. return substr($path, -1) == '/' ? $path : $path.'/';
  162. }
  163. /**
  164. * provides a side connection to a vchamilo database
  165. * @param array $_configuration
  166. *
  167. * @return \Doctrine\DBAL\Driver\Connection
  168. */
  169. public static function bootConnection(&$_configuration)
  170. {
  171. $dbParams = array(
  172. 'driver' => 'pdo_mysql',
  173. 'host' => $_configuration['db_host'],
  174. 'user' => $_configuration['db_user'],
  175. 'password' => $_configuration['db_password'],
  176. 'dbname' => isset($_configuration['main_database']) ? $_configuration['main_database'] : '',
  177. // Only relevant for pdo_sqlite, specifies the path to the SQLite database.
  178. 'path' => isset($_configuration['db_path']) ? $_configuration['db_path'] : '',
  179. // Only relevant for pdo_mysql, pdo_pgsql, and pdo_oci/oci8,
  180. 'port' => isset($_configuration['db_port']) ? $_configuration['db_port'] : '',
  181. );
  182. try {
  183. $database = new \Database();
  184. $connection = $database->connect(
  185. $dbParams,
  186. $_configuration['root_sys'],
  187. $_configuration['root_sys'],
  188. true
  189. );
  190. } catch (Exception $e) {
  191. echo('Side connection failure with '.$_configuration['db_host'].', '.$_configuration['db_user'].', ******** ');
  192. die();
  193. }
  194. return $connection;
  195. }
  196. /**
  197. * @param string $url
  198. */
  199. public static function redirect($url)
  200. {
  201. if (preg_match('#https?://#', $url)) {
  202. header('location: '.$url);
  203. } else {
  204. header('location: ' . api_get_path(WEB_PATH).$url);
  205. }
  206. exit;
  207. }
  208. /**
  209. * @param string $course_folder
  210. * @return string
  211. */
  212. public static function getHtaccessFragment($course_folder)
  213. {
  214. $str = "
  215. # Change this file to fit your configuration and save it as .htaccess in the courses folder #
  216. # Chamilo mod rewrite
  217. # Comment lines start with # and are not processed
  218. <IfModule mod_rewrite.c>
  219. RewriteEngine On
  220. # Rewrite base is the dir chamilo is installed in with trailing slash
  221. RewriteBase /{$course_folder}/
  222. # Do not rewrite on the main dir
  223. # Change this path to the path of your main folder
  224. RewriteCond %{REQUEST_URI} !^/main/
  225. #replace nasty ampersands by 3 slashes, we change these back in download.php
  226. RewriteRule ([^/]+)/document/(.*)&(.*)$ $1/document/$2///$3 [N]
  227. # Rewrite everything in the scorm folder of a course to the download script
  228. RewriteRule ([^/]+)/scorm/(.*)$ /main/document/download_scorm.php?doc_url=/$2&cDir=$1 [QSA,L]
  229. # Rewrite everything in the document folder of a course to the download script
  230. RewriteRule ([^/]+)/document/(.*)$ /main/document/download.php?doc_url=/$2&cDir=$1 [QSA,L]
  231. # Rewrite everything in the work folder
  232. RewriteRule ([^/]+)/work/(.*)$ /main/work/download.php?file=work/$2&cDir=$1 [QSA,L]
  233. </IfModule>
  234. ";
  235. return $str;
  236. }
  237. /**
  238. * @return string
  239. */
  240. public static function getDefaultCourseIndexFragment()
  241. {
  242. return "<html><head></head><body></body></html>";
  243. }
  244. /**
  245. * @param string $template
  246. * @return bool
  247. */
  248. public static function templateExists($template)
  249. {
  250. global $_configuration;
  251. // Find and checktemplate directory (files and SQL).
  252. $separator = DIRECTORY_SEPARATOR;
  253. $templatefoldername = 'plugin'.$separator.'vchamilo'.$separator.'templates';
  254. $relative_datadir = $templatefoldername.$separator.$template.'_sql';
  255. $absolute_datadir = $_configuration['root_sys'].$relative_datadir;
  256. return is_dir($absolute_datadir);
  257. }
  258. /**
  259. * drop a vchamilo instance databases using the physical connection
  260. * @param stdClass $params
  261. * return an array of errors or false if ok
  262. */
  263. public static function dropDatabase($params)
  264. {
  265. $params = clone $params;
  266. if (empty($params->main_database)) {
  267. Display::addFlash(Display::return_message('No database found'));
  268. return;
  269. }
  270. $databaseToDelete = $params->main_database;
  271. unset($params->main_database);
  272. $connection = self::getConnectionFromInstance($params);
  273. if ($connection) {
  274. $databases = $connection->getSchemaManager()->listDatabases();
  275. if (in_array($databaseToDelete, $databases)) {
  276. $connection->getSchemaManager()->dropDatabase(
  277. $databaseToDelete
  278. );
  279. Display::addFlash(
  280. Display::return_message(
  281. 'Database deleted: '.$databaseToDelete
  282. )
  283. );
  284. } else {
  285. Display::addFlash(
  286. Display::return_message(
  287. 'Database does not exist: '.$databaseToDelete
  288. )
  289. );
  290. }
  291. } else {
  292. Display::addFlash(
  293. Display::return_message(
  294. "Cannot connect DB: $databaseToDelete"
  295. )
  296. );
  297. }
  298. return false;
  299. }
  300. /**
  301. * @param stdClass $params
  302. * @return bool
  303. */
  304. public static function createDatabase($params)
  305. {
  306. $params = clone $params;
  307. $databaseName = $params->main_database;
  308. unset($params->main_database);
  309. $connection = Virtual::getConnectionFromInstance($params);
  310. if ($connection) {
  311. $databaseList = $connection->getSchemaManager()->listDatabases();
  312. if (!in_array($databaseName, $databaseList)) {
  313. $connection->getSchemaManager()->createDatabase($databaseName);
  314. Display::addFlash(
  315. Display::return_message("Creating DB ".$databaseName)
  316. );
  317. } else {
  318. Display::addFlash(
  319. Display::return_message("DB already exists: ".$databaseName)
  320. );
  321. }
  322. return true;
  323. }
  324. return false;
  325. }
  326. /**
  327. * get a proper SQLdump command
  328. * @param object $vchamilodata the complete new host information
  329. * @return string the shell command
  330. */
  331. public static function getDatabaseDumpCmd($vchamilodata)
  332. {
  333. $pgm = self::getConfig('vchamilo', 'mysql_cmd');
  334. if (!$pgm) {
  335. $pgm = '/usr/bin/mysql';
  336. }
  337. $phppgm = str_replace("\\", '/', $pgm);
  338. $phppgm = str_replace("\"", '', $phppgm);
  339. $pgm = str_replace("/", DIRECTORY_SEPARATOR, $pgm);
  340. if (!is_executable($phppgm)) {
  341. throw new Exception('databasecommanddoesnotmatchanexecutablefile');
  342. }
  343. // Retrieves the host configuration (more secure).
  344. $vchamilodata = empty($vchamilodata) ? Virtual::makeThis() : $vchamilodata;
  345. if (strstr($vchamilodata->db_host, ':') !== false) {
  346. list($vchamilodata->db_host, $vchamilodata->db_port) = explode(
  347. ':',
  348. $vchamilodata->db_host
  349. );
  350. }
  351. // Password.
  352. $databasePassword = '';
  353. if (!empty($vchamilodata->db_password)) {
  354. $databasePassword = '-p'.escapeshellarg($vchamilodata->db_password).' ';
  355. }
  356. // Making the command line (see 'vconfig.php' file for defining the right paths).
  357. $sqlcmd = $pgm.' -h'.$vchamilodata->db_host.(isset($vchamilodata->db_port) ? ' -P'.$vchamilodata->db_port.' ' : ' ' );
  358. $sqlcmd .= '-u'.$vchamilodata->db_user.' '.$databasePassword;
  359. $sqlcmd .= '%DATABASE% < ';
  360. return $sqlcmd;
  361. }
  362. /**
  363. * @param stdClass $vchamilo
  364. * @param string $template
  365. * @return bool
  366. */
  367. public static function loadDbTemplate($vchamilo, $template)
  368. {
  369. global $_configuration;
  370. // Make template directory (files and SQL).
  371. $separator = DIRECTORY_SEPARATOR;
  372. $templatefoldername = 'plugin'.$separator.'vchamilo'.$separator.'templates';
  373. $absolute_datadir = $_configuration['root_sys'].$templatefoldername.$separator.$template.$separator.'dump.sql';
  374. if (!$sqlcmd = Virtual::getDatabaseDumpCmd($vchamilo)) {
  375. return false;
  376. }
  377. $sqlcmd = str_replace('%DATABASE%', $vchamilo->main_database, $sqlcmd);
  378. // Make final commands to execute, depending on the database type.
  379. $import = $sqlcmd.$absolute_datadir;
  380. // Execute the command.
  381. Display::addFlash(Display::return_message("Load database from template dump: \n $import "));
  382. if (!defined('CLI_SCRIPT')) {
  383. putenv('LANG=en_US.utf-8');
  384. }
  385. // ensure utf8 is correctly handled by php exec()
  386. // @see http://stackoverflow.com/questions/10028925/call-a-program-via-shell-exec-with-utf-8-text-input
  387. exec($import, $output, $return);
  388. if (!empty($output)) {
  389. Display::addFlash(Display::return_message(implode("\n", $output)."\n"));
  390. }
  391. return true;
  392. }
  393. /**
  394. * Backups a database for having a snapshot.
  395. * @param $vchamilo object The Vchamilo object.
  396. * @param $outputfilerad string The output SQL file radical.
  397. * @return bool If TRUE, dumping database was a success, otherwise FALSE.
  398. */
  399. public static function backupDatabase($vchamilo, $outputfilerad)
  400. {
  401. // Separating host and port, if sticked.
  402. if (strstr($vchamilo->db_host, ':') !== false) {
  403. list($host, $port) = explode(':', $vchamilo->db_host);
  404. } else {
  405. $host = $vchamilo->db_host;
  406. }
  407. // By default, empty password.
  408. $pass = '';
  409. $pgm = null;
  410. if (empty($port)) {
  411. $port = 3306;
  412. }
  413. // Password.
  414. if (!empty($vchamilo->db_password)) {
  415. $pass = "-p".escapeshellarg($vchamilo->db_password);
  416. }
  417. // Making the commands for each database.
  418. $cmds = array();
  419. //if ($CFG->ostype == 'WINDOWS') {
  420. if (false) {
  421. $cmd_main = "-h{$host} -P{$port} -u{$vchamilo->db_user} {$pass} {$vchamilo->main_database}";
  422. $cmds[] = $cmd_main . ' > ' . $outputfilerad;
  423. } else {
  424. $cmd_main = "-h{$host} -P{$port} -u{$vchamilo->db_user} {$pass} {$vchamilo->main_database}";
  425. $cmds[] = $cmd_main . ' > ' . escapeshellarg($outputfilerad);
  426. }
  427. $mysqldumpcmd = self::getConfig('vchamilo', 'cmd_mysqldump', true);
  428. $pgm = !empty($mysqldumpcmd) ? stripslashes($mysqldumpcmd) : false;
  429. if (!$pgm) {
  430. $message = "Database dump command not available check here: ";
  431. $url = api_get_path(WEB_CODE_PATH).'admin/configure_plugin.php?name=vchamilo';
  432. $message .= Display::url($url, $url);
  433. Display::addFlash(Display::return_message($message));
  434. return false;
  435. } else {
  436. $phppgm = str_replace("\\", '/', $pgm);
  437. $phppgm = str_replace("\"", '', $phppgm);
  438. $pgm = str_replace('/', DIRECTORY_SEPARATOR, $pgm);
  439. if (!is_executable($phppgm)) {
  440. $message = "Database dump command $phppgm does not match any executable";
  441. Display::addFlash(Display::return_message($message));
  442. return false;
  443. }
  444. // executing all commands
  445. foreach ($cmds as $cmd) {
  446. // Final command.
  447. $cmd = $pgm.' '.$cmd;
  448. // Executes the SQL command.
  449. exec($cmd, $execoutput, $returnvalue);
  450. }
  451. }
  452. // End with success.
  453. return 1;
  454. }
  455. /**
  456. * read manifest values in vchamilo template.
  457. */
  458. public static function getVmanifest($version)
  459. {
  460. $templatewwwroot = '';
  461. // Define the $templatewwwroot content, found in manifest.php for this template
  462. $file = api_get_path(SYS_PATH).'/plugin/vchamilo/templates/'.$version.'/manifest.php';
  463. if (file_exists($file)) {
  464. include $file;
  465. $manifest = new stdClass();
  466. $manifest->templatewwwroot = $templatewwwroot;
  467. // $manifest->templatevdbprefix = $templatevdbprefix;
  468. // $manifest->coursefolder = $coursefolder;
  469. return $manifest;
  470. }
  471. return false;
  472. }
  473. /**
  474. * make a fake vchamilo that represents the current host
  475. */
  476. public static function makeThis()
  477. {
  478. global $_configuration;
  479. $thisPortal = new stdClass();
  480. $thisPortal->root_web = $_configuration['root_web'];
  481. $thisPortal->db_host = $_configuration['db_host'];
  482. $thisPortal->db_user = $_configuration['db_user'];
  483. $thisPortal->db_password = $_configuration['db_password'];
  484. $thisPortal->main_database = $_configuration['main_database'];
  485. return $thisPortal;
  486. }
  487. /**
  488. * Get available templates for defining a new virtual host.
  489. * @return array The available templates, or EMPTY array.
  490. */
  491. public static function getAvailableTemplates()
  492. {
  493. global $_configuration;
  494. $separator = DIRECTORY_SEPARATOR;
  495. $templatefoldername = 'plugin'.$separator.'vchamilo'.$separator.'templates';
  496. $tempDir = $_configuration['root_sys'].$templatefoldername;
  497. // Scans the templates.
  498. if (!is_dir($tempDir)) {
  499. mkdir($tempDir, 0777, true);
  500. }
  501. $finder = new \Symfony\Component\Finder\Finder();
  502. $dirs = $finder->in($tempDir)->depth('== 0');
  503. // Retrieves template(s) name(s). Should be hostnames.
  504. $templates = [];
  505. /*if ($addEmptyTemplate) {
  506. $templates = array('' => $plugin->get_lang('emptysite'));
  507. }*/
  508. $template = self::getConfig('vchamilo', 'default_template');
  509. if ($dirs) {
  510. /** @var Symfony\Component\Finder\SplFileInfo $dir */
  511. foreach ($dirs as $dir) {
  512. if (is_dir($dir->getPathname())) {
  513. // A template is considered when a dump.sql exists.
  514. if (file_exists($dir->getPathname().'/dump.sql')) {
  515. $templateName = $dir->getRelativePathname();
  516. if ($templateName == $template) {
  517. $templateName .= ' (default)';
  518. }
  519. $templates[$dir->getRelativePathname()] = $templateName;
  520. }
  521. }
  522. }
  523. }
  524. return $templates;
  525. }
  526. /**
  527. * this function set will map standard moodle API calls to chamilo
  528. * internal primitives. This avoids too many changes to do in imported
  529. * code
  530. */
  531. public static function getConfig($module, $key, $isplugin = true)
  532. {
  533. if ($isplugin) {
  534. $key = $module.'_'.$key;
  535. }
  536. $params = array('variable = ? AND subkey = ?' => [$key, $module]);
  537. $result = api_get_settings_params_simple($params);
  538. if ($result) {
  539. return $result['selected_value'];
  540. }
  541. return false;
  542. }
  543. /**
  544. * @param stdClass $vchamilo
  545. * @param string $template
  546. */
  547. public static function loadFilesFromTemplate($vchamilo, $template)
  548. {
  549. global $_configuration;
  550. // Make template directory (files and SQL).
  551. $separator = DIRECTORY_SEPARATOR;
  552. $templateDir = $_configuration['root_sys'].'plugin'.$separator.'vchamilo'.$separator.'templates'.$separator.$template;
  553. $vchamilo->virtual = true;
  554. $coursePath = self::getConfig('vchamilo', 'course_real_root').$separator.$vchamilo->slug;
  555. $homePath = self::getConfig('vchamilo', 'home_real_root').$separator.$vchamilo->slug;
  556. $archivePath = self::getConfig('vchamilo', 'archive_real_root').$separator.$vchamilo->slug;
  557. $uploadPath = self::getConfig('vchamilo', 'upload_real_root').$separator.$vchamilo->slug;
  558. // get the protocol free hostname
  559. Display::addFlash(
  560. Display::return_message("Copying {$templateDir}/data/courses => $coursePath")
  561. );
  562. copyDirTo(
  563. self::chopLastSlash($templateDir.'/data/courses'),
  564. self::chopLastSlash($coursePath),
  565. false
  566. );
  567. Display::addFlash(
  568. Display::return_message("Copying {$templateDir}/data/archive => $archivePath")
  569. );
  570. copyDirTo(
  571. self::chopLastSlash($templateDir.'/data/archive'),
  572. self::chopLastSlash($archivePath),
  573. false
  574. );
  575. Display::addFlash(
  576. Display::return_message("Copying {$templateDir}/data/home => $homePath")
  577. );
  578. copyDirTo(
  579. self::chopLastSlash($templateDir.'/data/home'),
  580. self::chopLastSlash($homePath),
  581. false
  582. );
  583. // Upload
  584. Display::addFlash(
  585. Display::return_message("Copying {$templateDir}/data/upload => $uploadPath")
  586. );
  587. copyDirTo(
  588. self::chopLastSlash($templateDir.'/data/upload/'),
  589. self::chopLastSlash($uploadPath),
  590. false
  591. );
  592. }
  593. /**
  594. * @param string $path
  595. *
  596. * @return mixed
  597. */
  598. public static function chopLastSlash($path)
  599. {
  600. return preg_replace('/\/$/', '', $path);
  601. }
  602. /**
  603. * @param string $str
  604. */
  605. public static function ctrace($str)
  606. {
  607. error_log($str);
  608. Display::addFlash(Display::return_message($str, 'normal', false));
  609. }
  610. /**
  611. * @param $file
  612. * @param $component
  613. * @param bool $return
  614. * @return string
  615. */
  616. public static function requireJs($file, $component, $return = false)
  617. {
  618. global $_configuration, $htmlHeadXtra;
  619. if (preg_match('/^local_/', $component)) {
  620. $component = str_replace('local_', '', $component);
  621. $path = 'local/';
  622. } else {
  623. $path = 'plugin/';
  624. }
  625. // Secure the postslashing of the roots.
  626. $root_web = $_configuration['root_web'].'/';
  627. $root_web = preg_replace('#//$#', '/', $root_web);
  628. $str = '<script type="text/javascript" src="'.$root_web.$path.$component.'/js/'.$file.'"></script>'."\n";
  629. if ($return === 'head') {
  630. $htmlHeadXtra[] = $str;
  631. }
  632. if ($return) {
  633. return $str;
  634. }
  635. echo $str;
  636. }
  637. /**
  638. * @param $file
  639. * @param $component
  640. * @param bool $return
  641. * @return string
  642. */
  643. public static function requireCss($file, $component, $return = false)
  644. {
  645. global $_configuration, $htmlHeadXtra;
  646. if (preg_match('/^local_/', $component)) {
  647. $component = str_replace('local_', '', $component);
  648. $path = 'local/';
  649. } else {
  650. $path = 'plugin/';
  651. }
  652. // Secure the postslashing of the roots.
  653. $root_web = $_configuration['root_web'].'/';
  654. $root_web = preg_replace('#//$#', '/', $root_web);
  655. $str = '<link rel="stylesheet" type="text/css" href="'.$root_web.$path.$component.'/'.$file.'.css" />'."\n";
  656. if ($return === 'head') {
  657. $htmlHeadXtra[] = $str;
  658. }
  659. if ($return) {
  660. return $str;
  661. }
  662. echo $str;
  663. }
  664. /**
  665. * @param string $url
  666. * @return string
  667. */
  668. public static function getSlugFromUrl($url)
  669. {
  670. $slugify = new Slugify();
  671. $urlInfo = parse_url($url);
  672. if (isset($urlInfo['host'])) {
  673. $path = $urlInfo['path'] != '/' ? '_'.$urlInfo['path'] : '';
  674. return $slugify->slugify($urlInfo['host'].$path);
  675. }
  676. return false;
  677. }
  678. /**
  679. * Check if all settings are complete
  680. */
  681. public static function checkSettings()
  682. {
  683. $enabled = self::getConfig('vchamilo', 'enable_virtualisation');
  684. if (empty($enabled)) {
  685. api_not_allowed(true, 'Plugin is not enabled');
  686. }
  687. global $virtualChamilo;
  688. if (!isset($virtualChamilo)) {
  689. api_not_allowed(
  690. true,
  691. 'You have to edit the configuration.php. Please check the readme file.'
  692. );
  693. }
  694. $coursePath = self::getConfig('vchamilo', 'course_real_root');
  695. $homePath = self::getConfig('vchamilo', 'home_real_root');
  696. $archivePath = self::getConfig('vchamilo', 'archive_real_root');
  697. $uploadPath = self::getConfig('vchamilo', 'upload_real_root');
  698. $cmdSql = self::getConfig('vchamilo', 'cmd_mysql');
  699. $cmdMySql = self::getConfig('vchamilo', 'cmd_mysqldump');
  700. if (empty($coursePath) || empty($homePath) || empty($uploadPath) || empty($archivePath) || empty($cmdSql) || empty($cmdMySql)) {
  701. api_not_allowed(true, 'You have to complete all plugin settings.');
  702. }
  703. $separator = DIRECTORY_SEPARATOR;
  704. $templatePath = api_get_path(SYS_PATH).'plugin'.$separator.'vchamilo'.$separator.'templates';
  705. $paths = [
  706. $coursePath,
  707. $homePath,
  708. $archivePath,
  709. $uploadPath,
  710. $templatePath
  711. ];
  712. foreach ($paths as $path) {
  713. $path = trim($path);
  714. if (is_dir($path)) {
  715. if (!is_writable($path)) {
  716. Display::addFlash(
  717. Display::return_message("Directory must have writable permissions: '$path'", 'warning')
  718. );
  719. };
  720. } else {
  721. Display::addFlash(
  722. Display::return_message("Directory doesn't exist: '$path'", 'warning')
  723. );
  724. }
  725. }
  726. }
  727. /**
  728. * @param object $instance
  729. * @return bool|\Doctrine\DBAL\Connection
  730. */
  731. public static function getConnectionFromInstance($instance, $getManager = false)
  732. {
  733. $dbParams = array(
  734. 'driver' => 'pdo_mysql',
  735. 'host' => $instance->db_host,
  736. 'user' => $instance->db_user,
  737. 'password' => $instance->db_password,
  738. //'dbname' => $instance->main_database,
  739. // Only relevant for pdo_sqlite, specifies the path to the SQLite database.
  740. //'path' => isset($_configuration['db_path']) ? $_configuration['db_path'] : '',
  741. // Only relevant for pdo_mysql, pdo_pgsql, and pdo_oci/oci8,
  742. //'port' => isset($_configuration['db_port']) ? $_configuration['db_port'] : '',
  743. );
  744. if (!empty($instance->main_database)) {
  745. $dbParams['dbname'] = $instance->main_database;
  746. }
  747. try {
  748. $database = new \Database();
  749. $manager = $database->connect(
  750. $dbParams,
  751. api_get_configuration_value('root_sys'),
  752. api_get_configuration_value('root_sys'),
  753. false,
  754. true
  755. );
  756. if ($getManager) {
  757. return $manager;
  758. }
  759. return $manager->getConnection();
  760. } catch (Exception $e) {
  761. error_log($e->getMessage());
  762. }
  763. return false;
  764. }
  765. /**
  766. * @param $data
  767. */
  768. public static function addInstance($data)
  769. {
  770. if (isset($data->what)) {
  771. unset($data->what);
  772. }
  773. if (isset($data->submitbutton)) {
  774. unset($data->submitbutton);
  775. }
  776. if (isset($data->id)) {
  777. unset($data->id);
  778. }
  779. if (isset($data->vid)) {
  780. unset($data->vid);
  781. }
  782. if (isset($data->testconnection)) {
  783. unset($data->testconnection);
  784. }
  785. if (isset($data->testdatapath)) {
  786. unset($data->testdatapath);
  787. }
  788. $registeronly = $data->registeronly;
  789. unset($data->registeronly);
  790. $data->lastcron = 0;
  791. $data->lastcrongap = 0;
  792. $data->croncount = 0;
  793. if (isset($data->template) && !empty($data->template)) {
  794. $template = $data->template;
  795. } else {
  796. $template = '';
  797. }
  798. $mainDatabase = api_get_configuration_value('main_database');
  799. if ($mainDatabase == $data->main_database) {
  800. Display::addFlash(
  801. Display::return_message('You cannot use the same database as the chamilo master', 'error')
  802. );
  803. return ;
  804. }
  805. $databaseName = $data->main_database;
  806. $data->main_database = '';
  807. $connection = Virtual::getConnectionFromInstance($data);
  808. $data->main_database = $databaseName;
  809. if (!$connection) {
  810. Display::addFlash(
  811. Display::return_message(
  812. 'Cannot connect to database with params: '.print_r($data, 1),
  813. 'error'
  814. )
  815. );
  816. return ;
  817. }
  818. $data->root_web = api_add_trailing_slash($data->root_web);
  819. if (substr($data->root_web, 0, 4) != 'http') {
  820. $data->root_web = api_get_protocol().'://'.$data->root_web;
  821. }
  822. self::ctrace('Registering: '.$data->root_web);
  823. $tablename = Database::get_main_table('vchamilo');
  824. $sql = "SELECT * FROM $tablename
  825. WHERE root_web = '".Database::escape_string($data->root_web)."'";
  826. $result = Database::query($sql);
  827. if (Database::num_rows($result)) {
  828. Database::update($tablename, $data, ['root_web = ?' => $data->root_web]);
  829. $virtualInfo = Database::fetch_array($result);
  830. $slug = $virtualInfo['slug'];
  831. } else {
  832. $slug = $data->slug = Virtual::getSlugFromUrl($data->root_web);
  833. if (empty($slug)) {
  834. Display::addFlash(
  835. Display::return_message('Cannot create slug from url: '.$data->root_web, 'error')
  836. );
  837. return ;
  838. }
  839. Database::insert($tablename, (array) $data);
  840. }
  841. if ($registeronly) {
  842. // Stop it now.
  843. self::ctrace('Registering only. out.');
  844. Virtual::redirect(api_get_path(WEB_PLUGIN_PATH).'vchamilo/views/manage.php');
  845. }
  846. // or we continue with physical creation
  847. self::createDirsFromSlug($slug);
  848. if (!$template) {
  849. // Create empty database for install
  850. self::ctrace("Creating database");
  851. Virtual::createDatabase($data);
  852. } else {
  853. // Deploy template database
  854. self::ctrace("Creating databases from template '$template'");
  855. Virtual::createDatabase($data);
  856. self::ctrace("Loading data template '$template'");
  857. Virtual::loadDbTemplate($data, $template);
  858. self::ctrace("Coying files from template '$template'");
  859. Virtual::loadFilesFromTemplate($data, $template);
  860. }
  861. // pluging in site name institution
  862. $settingstable = $data->main_database.'.settings_current';
  863. $accessurltable = $data->main_database.'.access_url';
  864. $sitename = Database::escape_string($data->sitename);
  865. $institution = Database::escape_string($data->institution);
  866. $sqls[] = "UPDATE {$settingstable} SET selected_value = '{$sitename}'
  867. WHERE variable = 'siteName' AND category = 'Platform' ";
  868. $sqls[] = "UPDATE {$settingstable} SET selected_value = '{$institution}'
  869. WHERE variable = 'institution' AND category = 'Platform' ";
  870. $sqls[] = "UPDATE {$accessurltable} SET url = '{$data->root_web}' WHERE id = '1' ";
  871. foreach ($sqls as $sql) {
  872. Database::query($sql);
  873. }
  874. self::ctrace("Finished");
  875. }
  876. /**
  877. * @param stdClass $data
  878. * @param string $fromVersion
  879. */
  880. public static function importInstance($data, $fromVersion)
  881. {
  882. if (isset($data->what)) {
  883. unset($data->what);
  884. }
  885. if (isset($data->submitbutton)) {
  886. unset($data->submitbutton);
  887. }
  888. if (isset($data->id)) {
  889. unset($data->id);
  890. }
  891. if (isset($data->vid)) {
  892. unset($data->vid);
  893. }
  894. if (isset($data->testconnection)) {
  895. unset($data->testconnection);
  896. }
  897. if (isset($data->testdatapath)) {
  898. unset($data->testdatapath);
  899. }
  900. $fromCoursePath = $data->course_path;
  901. $fromHomePath = $data->home_path;
  902. $fromUploadPath = $data->upload_path;
  903. unset($data->course_path);
  904. unset($data->home_path);
  905. unset($data->upload_path);
  906. $newDatabase = clone $data;
  907. $newDatabase->main_database = $newDatabase->import_to_main_database;
  908. $newDatabase->db_user = $newDatabase->import_to_db_user;
  909. $newDatabase->db_password = $newDatabase->import_to_db_password;
  910. $newDatabase->db_host = $newDatabase->import_to_db_host;
  911. unset($newDatabase->import_to_main_database);
  912. unset($newDatabase->import_to_db_user);
  913. unset($newDatabase->import_to_db_password);
  914. unset($newDatabase->import_to_db_host);
  915. unset($data->import_to_main_database);
  916. unset($data->import_to_db_user);
  917. unset($data->import_to_db_password);
  918. unset($data->import_to_db_host);
  919. $data->lastcron = 0;
  920. $data->lastcrongap = 0;
  921. $data->croncount = 0;
  922. $mainDatabase = api_get_configuration_value('main_database');
  923. if ($mainDatabase == $data->main_database) {
  924. Display::addFlash(
  925. Display::return_message('You cannot use the same database as the chamilo master', 'error')
  926. );
  927. return false;
  928. }
  929. self::ctrace('Registering: '.$data->root_web);
  930. $table = Database::get_main_table('vchamilo');
  931. $sql = "SELECT * FROM $table
  932. WHERE root_web = '".Database::escape_string($data->root_web)."'";
  933. $result = Database::query($sql);
  934. $id = null;
  935. if (Database::num_rows($result)) {
  936. Display::addFlash(
  937. Display::return_message('Instance was already added: '.$data->root_web, 'error')
  938. );
  939. return false;
  940. } else {
  941. /** @var EntityManager $em */
  942. $em = Virtual::getConnectionFromInstance($data, true);
  943. if ($em) {
  944. $connection = $em->getConnection();
  945. $statement = $connection->query('SELECT * FROM settings_current');
  946. $settings = $statement->fetchAll();
  947. $settings = array_column(
  948. $settings,
  949. 'selected_value',
  950. 'variable'
  951. );
  952. $institution = $settings['Institution'];
  953. $siteName = $settings['siteName'];
  954. $newDatabase->sitename = $siteName;
  955. $newDatabase->institution = $institution;
  956. $slug = $newDatabase->slug = $data->slug = Virtual::getSlugFromUrl($data->root_web);
  957. $id = Database::insert($table, (array)$newDatabase);
  958. }
  959. }
  960. if (!$id) {
  961. var_dump($data);
  962. throw new Exception('Was not registered');
  963. }
  964. if (empty($slug)) {
  965. throw new Exception('Slug is empty');
  966. }
  967. self::createDirsFromSlug($slug);
  968. $databaseCreated = Virtual::createDatabase($newDatabase);
  969. if (!$databaseCreated) {
  970. Display::addFlash(
  971. Display::return_message('Error while creating a DB', 'error')
  972. );
  973. return false;
  974. }
  975. $coursePath = self::getConfig('vchamilo', 'course_real_root').'/'.$slug;
  976. $homePath = self::getConfig('vchamilo', 'home_real_root').'/'.$slug;
  977. $uploadPath = self::getConfig('vchamilo', 'upload_real_root').'/'.$slug;
  978. $dumpFile = api_get_path(SYS_ARCHIVE_PATH).uniqid($data->main_database.'_dump_', true).'.sql';
  979. self::ctrace('Create backup from "'.$data->main_database.'" here: '.$dumpFile.' ');
  980. Virtual::backupDatabase($data, $dumpFile);
  981. $sqlcmd = Virtual::getDatabaseDumpCmd($newDatabase);
  982. $sqlcmd = str_replace('%DATABASE%', $newDatabase->main_database, $sqlcmd);
  983. $import = $sqlcmd.$dumpFile;
  984. // Execute the command.
  985. if (!defined('CLI_SCRIPT')) {
  986. putenv('LANG=en_US.utf-8');
  987. }
  988. // ensure utf8 is correctly handled by php exec()
  989. // @see http://stackoverflow.com/questions/10028925/call-a-program-via-shell-exec-with-utf-8-text-input
  990. $result = exec($import, $output, $return);
  991. self::ctrace('Restore backup here "'.$newDatabase->main_database.'" : <br />'.$import.' ');
  992. self::ctrace($result);
  993. $command = new \Chash\Command\Installation\UpgradeDatabaseCommand();
  994. // Creates the helper set
  995. $helperSet = \Doctrine\ORM\Tools\Console\ConsoleRunner::createHelperSet($em);
  996. $helpers = array(
  997. 'configuration' => new Chash\Helpers\ConfigurationHelper(),
  998. 'dialog' => new \Symfony\Component\Console\Helper\QuestionHelper(),
  999. );
  1000. foreach ($helpers as $name => $helper) {
  1001. $helperSet->set($helper, $name);
  1002. }
  1003. $command->setHelperSet($helperSet);
  1004. $tmpFile = tmpfile();
  1005. $outputStream = new \Symfony\Component\Console\Output\BufferedOutput($tmpFile);
  1006. $arguments = array(
  1007. 'from-version' => $fromVersion, // @todo change value
  1008. 'to-version' => '1.11.x',
  1009. 'host' => $newDatabase->db_host,
  1010. 'username' => $newDatabase->db_user,
  1011. 'password' => $newDatabase->db_password,
  1012. 'db_name' => $newDatabase->main_database,
  1013. 'root_sys' => api_get_configuration_value('root_sys')
  1014. );
  1015. $input = new ArrayInput($arguments);
  1016. $command->run($input, $outputStream);
  1017. error_log($outputStream->fetch());
  1018. if (file_exists($dumpFile)) {
  1019. unlink($dumpFile);
  1020. }
  1021. // Course
  1022. self::ctrace("Copy from '$fromCoursePath' to backup '$coursePath' ");
  1023. copyDirTo(
  1024. self::chopLastSlash($fromCoursePath),
  1025. self::chopLastSlash($coursePath),
  1026. false
  1027. );
  1028. // Home
  1029. self::ctrace("Copy from '$fromHomePath' to backup '$homePath' ");
  1030. copyDirTo(
  1031. self::chopLastSlash($fromHomePath),
  1032. self::chopLastSlash($homePath),
  1033. false
  1034. );
  1035. // Upload
  1036. self::ctrace("Copy from '$fromUploadPath' to backup '$uploadPath' ");
  1037. copyDirTo(
  1038. self::chopLastSlash($fromUploadPath),
  1039. self::chopLastSlash($uploadPath),
  1040. false
  1041. );
  1042. self::ctrace("Finished");
  1043. }
  1044. /**
  1045. * @param string $slug
  1046. *
  1047. * @return string
  1048. */
  1049. public static function createDirsFromSlug($slug)
  1050. {
  1051. // We continue with physical creation
  1052. // Create course directory for operations.
  1053. // this is very important here (DO NOT USE api_get_path() !!) because storage may be remotely located
  1054. $absAlternateCourse = Virtual::getConfig('vchamilo', 'course_real_root');
  1055. $courseDir = $absAlternateCourse.'/'.$slug;
  1056. if (!is_dir($courseDir)) {
  1057. self::ctrace("Creating physical course dir in $courseDir");
  1058. mkdir($courseDir, 0777, true);
  1059. // initiate default index
  1060. $indexFile = $courseDir.'/index.html';
  1061. if ($indexFile) {
  1062. file_put_contents($indexFile, self::getDefaultCourseIndexFragment());
  1063. }
  1064. $htaccessFile = $courseDir.'/.htaccess';
  1065. if ($htaccessFile) {
  1066. file_put_contents($htaccessFile, self::getHtaccessFragment($slug));
  1067. }
  1068. }
  1069. $absAlternateHome = Virtual::getConfig('vchamilo', 'home_real_root');
  1070. $absAlternateArchive = Virtual::getConfig('vchamilo', 'archive_real_root');
  1071. $absAlternateUpload = Virtual::getConfig('vchamilo', 'upload_real_root');
  1072. // absalternatehome is a vchamilo config setting that tells where the
  1073. // real physical storage for home pages are.
  1074. $homeDir = $absAlternateHome.'/'.$slug;
  1075. $archiveDir = $absAlternateArchive.'/'.$slug;
  1076. $uploadDir = $absAlternateUpload.'/'.$slug;
  1077. $dirs = [
  1078. $homeDir,
  1079. $archiveDir,
  1080. $uploadDir
  1081. ];
  1082. foreach ($dirs as $dir) {
  1083. self::ctrace("Making dir as $dir");
  1084. if (!is_dir($dir)) {
  1085. if (!mkdir($dir, 0777, true)) {
  1086. self::ctrace("Error creating dir $dir \n");
  1087. }
  1088. }
  1089. }
  1090. }
  1091. /**
  1092. * @param $id
  1093. * @return array|mixed
  1094. */
  1095. public static function getInstance($id)
  1096. {
  1097. $vhost = new stdClass();
  1098. if ($id) {
  1099. $id = (int) $id;
  1100. $sql = "SELECT * FROM vchamilo WHERE id = $id";
  1101. $result = Database::query($sql);
  1102. $vhost = (object) Database::fetch_array($result, 'ASSOC');
  1103. }
  1104. return $vhost;
  1105. }
  1106. /**
  1107. * @param stdClass $instance
  1108. *
  1109. * @return bool|string returns the original version of the app
  1110. */
  1111. public static function canBeUpgraded($instance)
  1112. {
  1113. $connection = Virtual::getConnectionFromInstance($instance);
  1114. if ($connection) {
  1115. $sql = 'SELECT * FROM settings_current WHERE variable = "chamilo_database_version"';
  1116. $statement = $connection->query($sql);
  1117. $settings = $statement->fetchAll();
  1118. $settings = array_column($settings, 'selected_value', 'variable');
  1119. $version = $settings['chamilo_database_version'];
  1120. $versionParts = explode('.', $version);
  1121. $version = implode('.', [$versionParts[0], $versionParts[1], '0']);
  1122. $currentVersion = api_get_setting('chamilo_database_version');
  1123. $versionParts = explode('.', $currentVersion);
  1124. $currentVersion = implode(
  1125. '.',
  1126. [$versionParts[0], $versionParts[1], '0']
  1127. );
  1128. if (version_compare($version, $currentVersion, '<')) {
  1129. return $version;
  1130. }
  1131. }
  1132. return false;
  1133. }
  1134. /**
  1135. * @return array
  1136. */
  1137. public static function getEncryptList()
  1138. {
  1139. $encryptList = [
  1140. 'bcrypt',
  1141. 'sha1',
  1142. 'md5',
  1143. 'none'
  1144. ];
  1145. return array_combine($encryptList, $encryptList);
  1146. }
  1147. }