Virtual.php 46 KB

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