template.lib.php 44 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281
  1. <?php
  2. /* For licensing terms, see /license.txt */
  3. /**
  4. * Class Template
  5. *
  6. * @author Julio Montoya <gugli100@gmail.com>
  7. * @todo better organization of the class, methods and variables
  8. *
  9. */
  10. class Template
  11. {
  12. /**
  13. * The Template folder name see main/template
  14. * @var string
  15. */
  16. public $templateFolder = 'default';
  17. /**
  18. * The theme that will be used: chamilo, public_admin, chamilo_red, etc
  19. * This variable is set from the database
  20. * @var string
  21. */
  22. public $theme = '';
  23. /**
  24. * @var string
  25. */
  26. public $preview_theme = '';
  27. public $title = null;
  28. public $show_header;
  29. public $show_footer;
  30. public $help;
  31. public $menu_navigation = array(); //Used in the userportal.lib.php function: return_navigation_course_links()
  32. public $show_learnpath = false; // This is a learnpath section or not?
  33. public $plugin = null;
  34. public $course_id = null;
  35. public $user_is_logged_in = false;
  36. public $twig = null;
  37. /* Loads chamilo plugins */
  38. public $load_plugins = false;
  39. public $params = array();
  40. public $force_plugin_load = false;
  41. /**
  42. * @param string $title
  43. * @param bool $show_header
  44. * @param bool $show_footer
  45. * @param bool $show_learnpath
  46. * @param bool $hide_global_chat
  47. * @param bool $load_plugins
  48. */
  49. public function __construct(
  50. $title = '',
  51. $show_header = true,
  52. $show_footer = true,
  53. $show_learnpath = false,
  54. $hide_global_chat = false,
  55. $load_plugins = true
  56. ) {
  57. // Page title
  58. $this->title = $title;
  59. $this->show_learnpath = $show_learnpath;
  60. $this->hide_global_chat = $hide_global_chat;
  61. $this->load_plugins = $load_plugins;
  62. $template_paths = array(
  63. api_get_path(SYS_CODE_PATH).'template/overrides', // user defined templates
  64. api_get_path(SYS_CODE_PATH).'template', //template folder
  65. api_get_path(SYS_PLUGIN_PATH) // plugin folder
  66. );
  67. $cache_folder = api_get_path(SYS_ARCHIVE_PATH).'twig';
  68. if (!is_dir($cache_folder)) {
  69. mkdir($cache_folder, api_get_permissions_for_new_directories());
  70. }
  71. $loader = new Twig_Loader_Filesystem($template_paths);
  72. //Setting Twig options depending on the server see http://twig.sensiolabs.org/doc/api.html#environment-options
  73. if (api_get_setting('server_type') == 'test') {
  74. $options = array(
  75. //'cache' => api_get_path(SYS_ARCHIVE_PATH), //path to the cache folder
  76. 'autoescape' => false,
  77. 'debug' => true,
  78. 'auto_reload' => true,
  79. 'optimizations' => 0,
  80. // turn on optimizations with -1
  81. 'strict_variables' => false,
  82. //If set to false, Twig will silently ignore invalid variables
  83. );
  84. } else {
  85. $options = array(
  86. 'cache' => $cache_folder,
  87. //path to the cache folder
  88. 'autoescape' => false,
  89. 'debug' => false,
  90. 'auto_reload' => false,
  91. 'optimizations' => -1,
  92. // turn on optimizations with -1
  93. 'strict_variables' => false
  94. //If set to false, Twig will silently ignore invalid variables
  95. );
  96. }
  97. $this->twig = new Twig_Environment($loader, $options);
  98. $this->twig->addFilter('get_plugin_lang', new Twig_Filter_Function('get_plugin_lang'));
  99. $this->twig->addFilter('get_lang', new Twig_Filter_Function('get_lang'));
  100. $this->twig->addFilter('get_path', new Twig_Filter_Function('api_get_path'));
  101. $this->twig->addFilter('get_setting', new Twig_Filter_Function('api_get_setting'));
  102. $this->twig->addFilter('var_dump', new Twig_Filter_Function('var_dump'));
  103. $this->twig->addFilter('return_message', new Twig_Filter_Function('Display::return_message_and_translate'));
  104. $this->twig->addFilter('display_page_header', new Twig_Filter_Function('Display::page_header_and_translate'));
  105. $this->twig->addFilter(
  106. 'display_page_subheader',
  107. new Twig_Filter_Function('Display::page_subheader_and_translate')
  108. );
  109. $this->twig->addFilter('icon', new Twig_Filter_Function('Template::get_icon_path'));
  110. $this->twig->addFilter('format_date', new Twig_Filter_Function('Template::format_date'));
  111. $this->twig->addFilter('api_get_local_time', new Twig_Filter_Function('api_get_local_time'));
  112. /*
  113. $lexer = new Twig_Lexer($this->twig, array(
  114. //'tag_comment' => array('{*', '*}'),
  115. //'tag_comment' => array('{#', '#}'),
  116. //'tag_block' => array('{', '}'),
  117. //'tag_variable' => array('{$', '}'),
  118. ));
  119. $this->twig->setLexer($lexer); */
  120. //Setting system variables
  121. $this->set_system_parameters();
  122. //Setting user variables
  123. $this->set_user_parameters();
  124. //Setting course variables
  125. $this->set_course_parameters();
  126. //Setting administrator variables
  127. $this->setAdministratorParams();
  128. //header and footer are showed by default
  129. $this->set_footer($show_footer);
  130. $this->set_header($show_header);
  131. $this->set_header_parameters();
  132. $this->set_footer_parameters();
  133. $defaultStyle = api_get_configuration_value('default_template');
  134. if (!empty($defaultStyle)) {
  135. $this->templateFolder = $defaultStyle;
  136. }
  137. $this->assign('template', $this->templateFolder);
  138. $this->assign('locale', api_get_language_isocode());
  139. $this->assign('css_styles', $this->theme);
  140. $this->assign('login_class', null);
  141. $this->setLoginForm();
  142. // Chamilo plugins
  143. if ($this->show_header) {
  144. if ($this->load_plugins) {
  145. $this->plugin = new AppPlugin();
  146. //1. Showing installed plugins in regions
  147. $plugin_regions = $this->plugin->get_plugin_regions();
  148. foreach ($plugin_regions as $region) {
  149. $this->set_plugin_region($region);
  150. }
  151. //2. Loading the course plugin info
  152. global $course_plugin;
  153. if (isset($course_plugin) && !empty($course_plugin) && !empty($this->course_id)) {
  154. //Load plugin get_langs
  155. $this->plugin->load_plugin_lang_variables($course_plugin);
  156. }
  157. }
  158. }
  159. }
  160. /**
  161. * @param string $image
  162. * @param int $size
  163. *
  164. * @return string
  165. */
  166. public static function get_icon_path($image, $size = ICON_SIZE_SMALL)
  167. {
  168. return Display::return_icon($image, '', array(), $size, false, true);
  169. }
  170. /**
  171. * @param string $timestamp
  172. * @param string $format
  173. *
  174. * @return string
  175. */
  176. public static function format_date($timestamp, $format = null)
  177. {
  178. return api_format_date($timestamp, $format);
  179. }
  180. /**
  181. * Return the item's url key:
  182. *
  183. * c_id=xx&id=xx
  184. *
  185. * @param object $item
  186. * @return string
  187. */
  188. public static function key($item)
  189. {
  190. $id = isset($item->id) ? $item->id : null;
  191. $c_id = isset($item->c_id) ? $item->c_id : null;
  192. $result = '';
  193. if ($c_id) {
  194. $result = "c_id=$c_id";
  195. }
  196. if ($id) {
  197. if ($result) {
  198. $result .= "&amp;id=$id";
  199. } else {
  200. $result .= "&amp;id=$id";
  201. }
  202. }
  203. return $result;
  204. }
  205. /**
  206. * @deprecated
  207. * @param null $helpInput
  208. */
  209. public function set_help($helpInput = null)
  210. {
  211. $this->setHelp($helpInput);
  212. }
  213. /**
  214. * @param string $helpInput
  215. */
  216. public function setHelp($helpInput = null)
  217. {
  218. if (!empty($helpInput)) {
  219. $help = $helpInput;
  220. } else {
  221. $help = $this->help;
  222. }
  223. $content = '';
  224. if (api_get_setting('enable_help_link') == 'true') {
  225. if (!empty($help)) {
  226. $help = Security::remove_XSS($help);
  227. $content = '<li class="help">';
  228. $content .= Display::url(
  229. Display::return_icon('help.large.png', get_lang('Help')),
  230. api_get_path(WEB_CODE_PATH) . 'help/help.php?open=' . $help,
  231. [
  232. 'class' => 'ajax',
  233. 'data-title' => get_lang('Help')
  234. ]
  235. );
  236. $content .= '</li>';
  237. }
  238. }
  239. $this->assign('help_content', $content);
  240. }
  241. /**
  242. * Use template system to parse the actions menu
  243. * @todo finish it!
  244. **/
  245. public function set_actions($actions)
  246. {
  247. $action_string = '';
  248. if (!empty($actions)) {
  249. foreach ($actions as $action) {
  250. $action_string .= $action;
  251. }
  252. }
  253. $this->assign('actions', $actions);
  254. }
  255. /**
  256. * Shortcut to display a 1 col layout (index.php)
  257. * */
  258. public function display_one_col_template()
  259. {
  260. $tpl = $this->get_template('layout/layout_1_col.tpl');
  261. $this->display($tpl);
  262. }
  263. /**
  264. * Shortcut to display a 2 col layout (userportal.php)
  265. **/
  266. public function display_two_col_template()
  267. {
  268. $tpl = $this->get_template('layout/layout_2_col.tpl');
  269. $this->display($tpl);
  270. }
  271. /**
  272. * Displays an empty template
  273. */
  274. public function display_blank_template()
  275. {
  276. $tpl = $this->get_template('layout/blank.tpl');
  277. $this->display($tpl);
  278. }
  279. /**
  280. * Displays an empty template
  281. */
  282. public function display_no_layout_template()
  283. {
  284. $tpl = $this->get_template('layout/no_layout.tpl');
  285. $this->display($tpl);
  286. }
  287. /**
  288. * Sets the footer visibility
  289. * @param bool true if we show the footer
  290. */
  291. public function set_footer($status)
  292. {
  293. $this->show_footer = $status;
  294. $this->assign('show_footer', $status);
  295. }
  296. /**
  297. * return true if toolbar has to be displayed for user
  298. * @return bool
  299. */
  300. public static function isToolBarDisplayedForUser()
  301. {
  302. //Toolbar
  303. $show_admin_toolbar = api_get_setting('show_admin_toolbar');
  304. $show_toolbar = false;
  305. switch ($show_admin_toolbar) {
  306. case 'do_not_show':
  307. break;
  308. case 'show_to_admin':
  309. if (api_is_platform_admin()) {
  310. $show_toolbar = true;
  311. }
  312. break;
  313. case 'show_to_admin_and_teachers':
  314. if (api_is_platform_admin() || api_is_allowed_to_edit()) {
  315. $show_toolbar = true;
  316. }
  317. break;
  318. case 'show_to_all':
  319. $show_toolbar = true;
  320. break;
  321. }
  322. return $show_toolbar;
  323. }
  324. /**
  325. * Sets the header visibility
  326. * @param bool true if we show the header
  327. */
  328. public function set_header($status)
  329. {
  330. $this->show_header = $status;
  331. $this->assign('show_header', $status);
  332. $show_toolbar = 0;
  333. if (self::isToolBarDisplayedForUser()) {
  334. $show_toolbar = 1;
  335. }
  336. $this->assign('show_toolbar', $show_toolbar);
  337. //Only if course is available
  338. $show_course_shortcut = null;
  339. $show_course_navigation_menu = null;
  340. if (!empty($this->course_id) && $this->user_is_logged_in) {
  341. if (api_get_setting('show_toolshortcuts') != 'false') {
  342. //Course toolbar
  343. $show_course_shortcut = CourseHome::show_navigation_tool_shortcuts();
  344. }
  345. if (api_get_setting('show_navigation_menu') != 'false') {
  346. //Course toolbar
  347. $show_course_navigation_menu = CourseHome::show_navigation_menu();
  348. }
  349. }
  350. $this->assign('show_course_shortcut', $show_course_shortcut);
  351. $this->assign('show_course_navigation_menu', $show_course_navigation_menu);
  352. }
  353. /**
  354. * @param string $name
  355. *
  356. * @return string
  357. */
  358. public function get_template($name)
  359. {
  360. return $this->templateFolder.'/'.$name;
  361. }
  362. /**
  363. * Set course parameters
  364. */
  365. private function set_course_parameters()
  366. {
  367. //Setting course id
  368. $course = api_get_course_info();
  369. if (empty($course)) {
  370. $this->assign('course_is_set', false);
  371. return;
  372. }
  373. $this->assign('course_is_set', true);
  374. $this->course_id = $course['id'];
  375. $_c = array(
  376. 'id' => $course['id'],
  377. 'code' => $course['code'],
  378. 'title' => $course['name'],
  379. 'visibility' => $course['visibility'],
  380. 'language' => $course['language'],
  381. 'directory' => $course['directory'],
  382. 'session_id' => api_get_session_id(),
  383. 'user_is_teacher' => api_is_course_admin(),
  384. 'student_view' => (!empty($_GET['isStudentView']) && $_GET['isStudentView'] == 'true'),
  385. );
  386. $this->assign('course_code', $course['code']);
  387. $this->assign('_c', $_c);
  388. }
  389. /**
  390. * Set user parameters
  391. */
  392. private function set_user_parameters()
  393. {
  394. $user_info = array();
  395. $user_info['logged'] = 0;
  396. $this->user_is_logged_in = false;
  397. if (api_user_is_login()) {
  398. $user_info = api_get_user_info(api_get_user_id(), true);
  399. $user_info['logged'] = 1;
  400. $user_info['is_admin'] = 0;
  401. if (api_is_platform_admin()) {
  402. $user_info['is_admin'] = 1;
  403. }
  404. $user_info['messages_count'] = MessageManager::get_new_messages();
  405. $this->user_is_logged_in = true;
  406. }
  407. // Setting the $_u array that could be use in any template
  408. $this->assign('_u', $user_info);
  409. }
  410. /**
  411. * Set system parameters
  412. */
  413. private function set_system_parameters()
  414. {
  415. global $_configuration;
  416. $this->theme = api_get_visual_theme();
  417. //Setting app paths/URLs
  418. $_p = array(
  419. 'web' => api_get_path(WEB_PATH),
  420. 'web_relative' => api_get_path(REL_PATH),
  421. 'web_course' => api_get_path(WEB_COURSE_PATH),
  422. 'web_main' => api_get_path(WEB_CODE_PATH),
  423. 'web_css' => api_get_path(WEB_CSS_PATH),
  424. 'web_css_theme' => api_get_path(WEB_CSS_PATH) . 'themes/' . $this->theme . '/',
  425. 'web_ajax' => api_get_path(WEB_AJAX_PATH),
  426. 'web_img' => api_get_path(WEB_IMG_PATH),
  427. 'web_plugin' => api_get_path(WEB_PLUGIN_PATH),
  428. 'web_lib' => api_get_path(WEB_LIBRARY_PATH),
  429. 'web_upload' => api_get_path(WEB_UPLOAD_PATH),
  430. 'web_self' => api_get_self(),
  431. 'web_query_vars' => api_htmlentities($_SERVER['QUERY_STRING']),
  432. 'web_self_query_vars' => api_htmlentities($_SERVER['REQUEST_URI']),
  433. 'web_cid_query' => api_get_cidreq(),
  434. );
  435. $this->assign('_p', $_p);
  436. //Here we can add system parameters that can be use in any template
  437. $_s = array(
  438. 'software_name' => $_configuration['software_name'],
  439. 'system_version' => $_configuration['system_version'],
  440. 'site_name' => api_get_setting('siteName'),
  441. 'institution' => api_get_setting('Institution'),
  442. 'date' => api_format_date('now', DATE_FORMAT_LONG),
  443. 'timezone' => _api_get_timezone(),
  444. 'gamification_mode' => api_get_setting('gamification_mode')
  445. );
  446. $this->assign('_s', $_s);
  447. }
  448. /**
  449. * Set theme, include mainstream CSS files
  450. * @return void
  451. * @see setCssCustomFiles() for additional CSS sheets
  452. */
  453. public function setCssFiles()
  454. {
  455. global $disable_js_and_css_files;
  456. $css = array();
  457. $this->theme = api_get_visual_theme();
  458. if (!empty($this->preview_theme)) {
  459. $this->theme = $this->preview_theme;
  460. }
  461. // Default CSS Bootstrap
  462. $bowerCSSFiles = [
  463. 'bootstrap-daterangepicker/daterangepicker-bs3.css',
  464. 'fontawesome/css/font-awesome.min.css',
  465. 'jquery-ui/themes/smoothness/theme.css',
  466. 'jquery-ui/themes/smoothness/jquery-ui.min.css',
  467. 'mediaelement/build/mediaelementplayer.min.css',
  468. 'jqueryui-timepicker-addon/dist/jquery-ui-timepicker-addon.min.css',
  469. 'bootstrap/dist/css/bootstrap.min.css',
  470. ];
  471. foreach ($bowerCSSFiles as $file) {
  472. $css[] = api_get_path(WEB_PATH).'web/assets/'.$file;
  473. }
  474. $css[] = api_get_path(WEB_CSS_PATH) . 'bootstrap-select.css';
  475. $css[] = api_get_path(WEB_LIBRARY_PATH) . 'javascript/chosen/chosen.css';
  476. $css[] = api_get_path(WEB_LIBRARY_PATH) . 'javascript/tag/style.css';
  477. if (api_is_global_chat_enabled()) {
  478. $css[] = api_get_path(WEB_LIBRARY_PATH) . 'javascript/chat/css/chat.css';
  479. }
  480. //THEME CSS STYLE
  481. // $css[] = api_get_cdn_path(api_get_path(WEB_CSS_PATH).'responsive.css');
  482. $css_file_to_string = null;
  483. foreach ($css as $file) {
  484. $css_file_to_string .= api_get_css($file);
  485. }
  486. if (!$disable_js_and_css_files) {
  487. $this->assign('css_static_file_to_string', $css_file_to_string);
  488. }
  489. }
  490. /**
  491. * Prepare custom CSS to be added at the very end of the <head> section
  492. * @return void
  493. * @see setCssFiles() for the mainstream CSS files
  494. */
  495. public function setCssCustomFiles()
  496. {
  497. global $disable_js_and_css_files;
  498. // Base CSS
  499. $css[] = api_get_cdn_path(api_get_path(WEB_CSS_PATH).'base.css');
  500. if ($this->show_learnpath) {
  501. $css[] = api_get_cdn_path(api_get_path(WEB_CSS_PATH).'scorm.css');
  502. if (is_file(api_get_path(SYS_CSS_PATH).'themes/'.$this->theme.'/learnpath.css')) {
  503. $css[] = api_get_path(WEB_CSS_PATH).'themes/'.$this->theme.'/learnpath.css';
  504. }
  505. }
  506. $css[] = api_get_cdn_path(api_get_path(WEB_CSS_PATH).'themes/'.$this->theme.'/default.css');
  507. $css_file_to_string = null;
  508. foreach ($css as $file) {
  509. $css_file_to_string .= api_get_css($file);
  510. }
  511. // @todo move this somewhere else. Special fix when using tablets in order to see the text near icons
  512. if (SHOW_TEXT_NEAR_ICONS == true) {
  513. //hack in order to fix the actions buttons
  514. $css_file_to_string .= '<style>
  515. .td_actions a {
  516. float:left;
  517. width:100%;
  518. }
  519. .forum_message_left a {
  520. float:left;
  521. width:100%;
  522. }
  523. </style>';
  524. }
  525. $navigator_info = api_get_navigator();
  526. if ($navigator_info['name'] == 'Internet Explorer' && $navigator_info['version'] == '6') {
  527. $css_file_to_string .= 'img, div { behavior: url('.api_get_path(WEB_LIBRARY_PATH).'javascript/iepngfix/iepngfix.htc) } '."\n";
  528. }
  529. if (!$disable_js_and_css_files) {
  530. $this->assign('css_custom_file_to_string', $css_file_to_string);
  531. $style_print = '';
  532. if (is_readable(api_get_path(SYS_CSS_PATH).$this->theme.'/print.css')) {
  533. $style_print = api_get_css(api_get_cdn_path(api_get_path(WEB_CSS_PATH) . $this->theme . '/print.css'),
  534. 'print');
  535. }
  536. $this->assign('css_style_print', $style_print);
  537. }
  538. // Logo
  539. $logo = return_logo($this->theme);
  540. $this->assign('logo', $logo);
  541. }
  542. /**
  543. * Declare and define the template variable that will be used to load
  544. * javascript libraries in the header.
  545. */
  546. public function set_js_files()
  547. {
  548. global $disable_js_and_css_files, $htmlHeadXtra;
  549. //JS files
  550. $js_files = array(
  551. 'chosen/chosen.jquery.min.js',
  552. );
  553. $viewBySession = api_get_setting('my_courses_view_by_session') === 'true';
  554. if (api_is_global_chat_enabled() || $viewBySession) {
  555. // Do not include the global chat in LP
  556. if ($this->show_learnpath == false &&
  557. $this->show_footer == true &&
  558. $this->hide_global_chat == false
  559. ) {
  560. $js_files[] = 'chat/js/chat.js';
  561. }
  562. }
  563. if (api_get_setting('accessibility_font_resize') == 'true') {
  564. $js_files[] = 'fontresize.js';
  565. }
  566. // Do not use minified version - generates errors (at least in the skills wheel)
  567. $js_files[] = 'tag/jquery.fcbkcomplete.js';
  568. $js_file_to_string = null;
  569. $isoCode = api_get_language_isocode();
  570. $bowerJsFiles = [
  571. 'modernizr/modernizr.js',
  572. 'jquery/dist/jquery.min.js',
  573. 'bootstrap/dist/js/bootstrap.min.js',
  574. 'jquery-ui/jquery-ui.min.js',
  575. 'moment/min/moment-with-locales.min.js',
  576. 'ckeditor/ckeditor.js',
  577. 'bootstrap-daterangepicker/daterangepicker.js',
  578. 'jquery-timeago/jquery.timeago.js',
  579. 'mediaelement/build/mediaelement-and-player.min.js',
  580. 'jqueryui-timepicker-addon/dist/jquery-ui-timepicker-addon.min.js',
  581. 'imagemap-resizer/js/imageMapResizer.min.js'
  582. ];
  583. if (api_get_setting('include_asciimathml_script') == 'true') {
  584. $bowerJsFiles[] = 'MathJax/MathJax.js?config=AM_HTMLorMML';
  585. }
  586. if ($isoCode != 'en') {
  587. $bowerJsFiles[] = 'jqueryui-timepicker-addon/dist/i18n/jquery-ui-timepicker-' . $isoCode . '.js';
  588. $bowerJsFiles[] = 'jquery-ui/ui/minified/i18n/datepicker-' . $isoCode . '.min.js';
  589. }
  590. foreach ($bowerJsFiles as $file) {
  591. $js_file_to_string .= '<script type="text/javascript" src="'.api_get_path(WEB_PATH).'web/assets/'.$file.'"></script>'."\n";
  592. }
  593. $js_file_to_string .= '<script type="text/javascript" src="'. api_get_path(WEB_LIBRARY_PATH) . 'javascript/bootstrap-select.min.js"></script>'."\n";
  594. foreach ($js_files as $file) {
  595. $js_file_to_string .= api_get_js($file);
  596. }
  597. // Loading email_editor js
  598. if (!api_is_anonymous() && api_get_setting('allow_email_editor') == 'true') {
  599. $js_file_to_string .= $this->fetch('default/mail_editor/email_link.js.tpl');
  600. }
  601. if (!$disable_js_and_css_files) {
  602. $this->assign('js_file_to_string', $js_file_to_string);
  603. //Adding jquery ui by default
  604. $extra_headers = api_get_jquery_ui_js();
  605. //$extra_headers = '';
  606. if (isset($htmlHeadXtra) && $htmlHeadXtra) {
  607. foreach ($htmlHeadXtra as & $this_html_head) {
  608. $extra_headers .= $this_html_head."\n";
  609. }
  610. }
  611. $this->assign('extra_headers', $extra_headers);
  612. }
  613. }
  614. /**
  615. * Special function to declare last-minute JS libraries which depend on
  616. * other things to be declared first. In particular, it might be useful
  617. * under IE9 with compatibility mode, which for some reason is getting
  618. * upset when a variable is used in a function (even if not used yet)
  619. * when this variable hasn't been defined yet.
  620. */
  621. public function set_js_files_post()
  622. {
  623. global $disable_js_and_css_files, $htmlHeadXtra;
  624. $js_files = array();
  625. if (api_is_global_chat_enabled()) {
  626. //Do not include the global chat in LP
  627. if ($this->show_learnpath == false && $this->show_footer == true && $this->hide_global_chat == false) {
  628. $js_files[] = 'chat/js/chat.js';
  629. }
  630. }
  631. $js_file_to_string = null;
  632. foreach ($js_files as $js_file) {
  633. $js_file_to_string .= api_get_js($js_file);
  634. }
  635. if (!$disable_js_and_css_files) {
  636. $this->assign('js_file_to_string_post', $js_file_to_string);
  637. }
  638. }
  639. /**
  640. * Set header parameters
  641. */
  642. private function set_header_parameters()
  643. {
  644. global $httpHeadXtra, $_course, $interbreadcrumb, $language_file, $_configuration, $this_section;
  645. $help = $this->help;
  646. $nameTools = $this->title;
  647. $navigation = return_navigation_array();
  648. $this->menu_navigation = $navigation['menu_navigation'];
  649. $this->assign('system_charset', api_get_system_encoding());
  650. if (isset($httpHeadXtra) && $httpHeadXtra) {
  651. foreach ($httpHeadXtra as & $thisHttpHead) {
  652. header($thisHttpHead);
  653. }
  654. }
  655. $this->assign('online_button', Display::return_icon('statusonline.png'));
  656. $this->assign('offline_button',Display::return_icon('statusoffline.png'));
  657. // Get language iso-code for this page - ignore errors
  658. $this->assign('document_language', api_get_language_isocode());
  659. $course_title = isset($_course['name']) ? $_course['name'] : null;
  660. $title_list = array();
  661. $title_list[] = api_get_setting('Institution');
  662. $title_list[] = api_get_setting('siteName');
  663. if (!empty($course_title)) {
  664. $title_list[] = $course_title;
  665. }
  666. if ($nameTools != '') {
  667. $title_list[] = $nameTools;
  668. }
  669. $title_string = '';
  670. for ($i = 0; $i < count($title_list); $i++) {
  671. $title_string .= $title_list[$i];
  672. if (isset($title_list[$i + 1])) {
  673. $item = trim($title_list[$i + 1]);
  674. if (!empty($item)) {
  675. $title_string .= ' - ';
  676. }
  677. }
  678. }
  679. $this->assign('title_string', $title_string);
  680. //Setting the theme and CSS files
  681. $css = $this->setCssFiles();
  682. $this->set_js_files();
  683. $this->setCssCustomFiles($css);
  684. //$this->set_js_files_post();
  685. $browser = api_browser_support('check_browser');
  686. if ($browser[0] == 'Internet Explorer' && $browser[1] >= '11') {
  687. $browser_head = '<meta http-equiv="X-UA-Compatible" content="IE=EmulateIE9" />';
  688. $this->assign('browser_specific_head', $browser_head);
  689. }
  690. // Implementation of prefetch.
  691. // See http://cdn.chamilo.org/main/img/online.png for details
  692. $prefetch = '';
  693. if (!empty($_configuration['cdn_enable'])) {
  694. $prefetch .= '<meta http-equiv="x-dns-prefetch-control" content="on">';
  695. foreach ($_configuration['cdn'] as $host => $exts) {
  696. $prefetch .= '<link rel="dns-prefetch" href="'.$host.'">';
  697. }
  698. }
  699. $this->assign('prefetch', $prefetch);
  700. $this->assign('text_direction', api_get_text_direction());
  701. $this->assign('section_name', 'section-'.$this_section);
  702. $favico = '<link rel="shortcut icon" href="'.api_get_path(WEB_PATH).'favicon.ico" type="image/x-icon" />';
  703. if (api_is_multiple_url_enabled()) {
  704. $access_url_id = api_get_current_access_url_id();
  705. if ($access_url_id != -1) {
  706. $url_info = api_get_access_url($access_url_id);
  707. $url = api_remove_trailing_slash(preg_replace('/https?:\/\//i', '', $url_info['url']));
  708. $clean_url = api_replace_dangerous_char($url);
  709. $clean_url = str_replace('/', '-', $clean_url);
  710. $clean_url .= '/';
  711. $homep = api_get_path(REL_PATH).'home/'.$clean_url; //homep for Home Path
  712. $icon_real_homep = api_get_path(SYS_APP_PATH).'home/'.$clean_url;
  713. //we create the new dir for the new sites
  714. if (is_file($icon_real_homep.'favicon.ico')) {
  715. $favico = '<link rel="shortcut icon" href="'.$homep.'favicon.ico" type="image/x-icon" />';
  716. }
  717. }
  718. }
  719. $this->assign('favico', $favico);
  720. $this->setHelp();
  721. //@todo move this in the template
  722. $bug_notification_link = '';
  723. if (api_get_setting('show_link_bug_notification') == 'true' && $this->user_is_logged_in) {
  724. $bug_notification_link = '<li class="report">
  725. <a href="http://support.chamilo.org/projects/chamilo-18/wiki/How_to_report_bugs" target="_blank">
  726. <img src="'.api_get_path(WEB_IMG_PATH).'bug.large.png" style="vertical-align: middle;" alt="'.get_lang('ReportABug').'" title="'.get_lang('ReportABug').'"/></a>
  727. </li>';
  728. }
  729. $this->assign('bug_notification_link', $bug_notification_link);
  730. $notification = return_notification_menu();
  731. $this->assign('notification_menu', $notification);
  732. // Preparing values for the menu
  733. // Logout link
  734. $hideLogout = api_get_setting('hide_logout_button');
  735. if ($hideLogout === 'true') {
  736. $this->assign('logout_link', null);
  737. } else {
  738. $this->assign('logout_link', api_get_path(WEB_PATH).'index.php?logout=logout&uid='.api_get_user_id());
  739. }
  740. //Profile link
  741. if (api_get_setting('allow_social_tool') == 'true') {
  742. $profile_url = api_get_path(WEB_CODE_PATH).'social/home.php';
  743. $profile_link = Display::url(get_lang('Profile'), $profile_url);
  744. } else {
  745. $profile_url = api_get_path(WEB_CODE_PATH).'auth/profile.php';
  746. $profile_link = Display::url(get_lang('Profile'), $profile_url);
  747. }
  748. $this->assign('profile_link', $profile_link);
  749. $this->assign('profile_url', $profile_url);
  750. //Message link
  751. $message_link = null;
  752. $message_url = null;
  753. if (api_get_setting('allow_message_tool') == 'true') {
  754. $message_url = api_get_path(WEB_CODE_PATH).'messages/inbox.php';
  755. $message_link = '<a href="'.api_get_path(WEB_CODE_PATH).'messages/inbox.php">'.get_lang('Inbox').'</a>';
  756. }
  757. $this->assign('message_link', $message_link);
  758. $this->assign('message_url', $message_url);
  759. $institution = api_get_setting('Institution');
  760. $portal_name = empty($institution) ? api_get_setting('siteName') : $institution;
  761. $this->assign('portal_name', $portal_name);
  762. //Menu
  763. $menu = return_menu();
  764. $this->assign('menu', $menu);
  765. // Setting notifications
  766. $count_unread_message = 0;
  767. if (api_get_setting('allow_message_tool') == 'true') {
  768. // get count unread message and total invitations
  769. $count_unread_message = MessageManager::get_number_of_messages(true);
  770. }
  771. $total_invitations = 0;
  772. if (api_get_setting('allow_social_tool') == 'true') {
  773. $number_of_new_messages_of_friend = SocialManager::get_message_number_invitation_by_user_id(
  774. api_get_user_id()
  775. );
  776. $usergroup = new UserGroup();
  777. $group_pending_invitations = $usergroup->get_groups_by_user(
  778. api_get_user_id(),
  779. GROUP_USER_PERMISSION_PENDING_INVITATION,
  780. false
  781. );
  782. if (!empty($group_pending_invitations)) {
  783. $group_pending_invitations = count($group_pending_invitations);
  784. } else {
  785. $group_pending_invitations = 0;
  786. }
  787. $total_invitations = intval($number_of_new_messages_of_friend) + $group_pending_invitations + intval($count_unread_message);
  788. }
  789. $total_invitations = (!empty($total_invitations) ? Display::badge($total_invitations) : null);
  790. $this->assign('user_notifications', $total_invitations);
  791. // Block Breadcrumb
  792. $breadcrumb = return_breadcrumb($interbreadcrumb, $language_file, $nameTools);
  793. $this->assign('breadcrumb', $breadcrumb);
  794. //Extra content
  795. $extra_header = null;
  796. if (!api_is_platform_admin()) {
  797. $extra_header = trim(api_get_setting('header_extra_content'));
  798. }
  799. $this->assign('header_extra_content', $extra_header);
  800. //if ($this->show_header == 1) {
  801. header('Content-Type: text/html; charset='.api_get_system_encoding());
  802. header(
  803. 'X-Powered-By: '.$_configuration['software_name'].' '.substr($_configuration['system_version'], 0, 1)
  804. );
  805. //}
  806. $socialMeta = '';
  807. $metaTitle = api_get_setting('meta_title');
  808. if (!empty($metaTitle)) {
  809. $socialMeta .= '<meta name="twitter:card" content="summary" />' . "\n";
  810. $socialMeta .= '<meta property="og:title" content="' . $metaTitle . '" />' . "\n";
  811. $socialMeta .= '<meta property="og:url" content="' . api_get_path(WEB_PATH) . '" />' . "\n";
  812. $metaDescription = api_get_setting('meta_description');
  813. if (!empty($metaDescription)) {
  814. $socialMeta .= '<meta property="og:description" content="' . $metaDescription . '" />' . "\n";
  815. }
  816. $metaSite = api_get_setting('meta_twitter_site');
  817. if (!empty($metaSite)) {
  818. $socialMeta .= '<meta name="twitter:site" content="' . $metaSite . '" />' . "\n";
  819. $metaCreator = api_get_setting('meta_twitter_creator');
  820. if (!empty($metaCreator)) {
  821. $socialMeta .= '<meta name="twitter:creator" content="' . $metaCreator . '" />' . "\n";
  822. }
  823. }
  824. $metaImage = api_get_setting('meta_image_path');
  825. if (!empty($metaImage)) {
  826. if (is_file(api_get_path(SYS_PATH) . $metaImage)) {
  827. $path = api_get_path(WEB_PATH) . $metaImage;
  828. $socialMeta .= '<meta property="og:image" content="' . $path . '" />' . "\n";
  829. }
  830. }
  831. }
  832. $this->assign('social_meta', $socialMeta);
  833. }
  834. /**
  835. * Set footer parameters
  836. */
  837. private function set_footer_parameters()
  838. {
  839. if (api_get_setting('show_administrator_data') == 'true') {
  840. //Administrator name
  841. $administrator_data = get_lang('Manager').' : '.Display::encrypted_mailto_link(
  842. api_get_setting('emailAdministrator'),
  843. api_get_person_name(api_get_setting('administratorName'), api_get_setting('administratorSurname'))
  844. );
  845. $this->assign('administrator_name', $administrator_data);
  846. }
  847. //Loading footer extra content
  848. if (!api_is_platform_admin()) {
  849. $extra_footer = trim(api_get_setting('footer_extra_content'));
  850. if (!empty($extra_footer)) {
  851. $this->assign('footer_extra_content', $extra_footer);
  852. }
  853. }
  854. //Tutor name
  855. if (api_get_setting('show_tutor_data') == 'true') {
  856. // Course manager
  857. $courseId = api_get_course_int_id();
  858. $id_session = api_get_session_id();
  859. if (!empty($courseId)) {
  860. $tutor_data = '';
  861. if ($id_session != 0) {
  862. $coachs_email = CourseManager::get_email_of_tutor_to_session($id_session, $courseId);
  863. $email_link = array();
  864. foreach ($coachs_email as $coach) {
  865. $email_link[] = Display::encrypted_mailto_link($coach['email'], $coach['complete_name']);
  866. }
  867. if (count($coachs_email) > 1) {
  868. $tutor_data .= get_lang('Coachs').' : ';
  869. $tutor_data .= array_to_string($email_link, CourseManager::USER_SEPARATOR);
  870. } elseif (count($coachs_email) == 1) {
  871. $tutor_data .= get_lang('Coach').' : ';
  872. $tutor_data .= array_to_string($email_link, CourseManager::USER_SEPARATOR);
  873. } elseif (count($coachs_email) == 0) {
  874. $tutor_data .= '';
  875. }
  876. }
  877. $this->assign('session_teachers', $tutor_data);
  878. }
  879. }
  880. if (api_get_setting('show_teacher_data') == 'true') {
  881. // course manager
  882. $courseId = api_get_course_int_id();
  883. if (!empty($courseId)) {
  884. $teacher_data = '';
  885. $mail= CourseManager::get_emails_of_tutors_to_course($courseId);
  886. if (!empty($mail)) {
  887. $teachers_parsed = array();
  888. foreach ($mail as $value) {
  889. foreach ($value as $email => $name) {
  890. $teachers_parsed[] = Display::encrypted_mailto_link($email, $name);
  891. }
  892. }
  893. $label = get_lang('Teacher');
  894. if (count($mail) > 1) {
  895. $label = get_lang('Teachers');
  896. }
  897. $teacher_data .= $label.' : '.array_to_string($teachers_parsed, CourseManager::USER_SEPARATOR);
  898. }
  899. $this->assign('teachers', $teacher_data);
  900. }
  901. }
  902. }
  903. /**
  904. * Show header template.
  905. */
  906. public function show_header_template()
  907. {
  908. $tpl = $this->get_template('layout/show_header.tpl');
  909. $this->display($tpl);
  910. }
  911. /**
  912. * Show footer template.
  913. */
  914. public function show_footer_template()
  915. {
  916. $tpl = $this->get_template('layout/show_footer.tpl');
  917. $this->display($tpl);
  918. }
  919. /**
  920. * Sets the plugin content in a template variable
  921. * @param string $plugin_region
  922. * @return null
  923. */
  924. public function set_plugin_region($plugin_region)
  925. {
  926. if (!empty($plugin_region)) {
  927. $region_content = $this->plugin->load_region($plugin_region, $this, $this->force_plugin_load);
  928. if (!empty($region_content)) {
  929. $this->assign('plugin_'.$plugin_region, $region_content);
  930. } else {
  931. $this->assign('plugin_'.$plugin_region, null);
  932. }
  933. }
  934. return null;
  935. }
  936. /**
  937. * @param string $template
  938. * @return string
  939. */
  940. public function fetch($template = null)
  941. {
  942. $template = $this->twig->loadTemplate($template);
  943. return $template->render($this->params);
  944. }
  945. /**
  946. * @param $tpl_var
  947. * @param null $value
  948. */
  949. public function assign($tpl_var, $value = null)
  950. {
  951. $this->params[$tpl_var] = $value;
  952. }
  953. /**
  954. * @param string $template
  955. */
  956. public function display($template)
  957. {
  958. $this->assign('flash_messages', Display::getFlashToString());
  959. Display::cleanFlashMessages();
  960. echo $this->twig->render($template, $this->params);
  961. }
  962. /**
  963. * Adds a body class for login pages
  964. */
  965. public function setLoginBodyClass()
  966. {
  967. $this->assign('login_class', 'section-login');
  968. }
  969. /**
  970. * The theme that will be used if the database is not working.
  971. * @return string
  972. */
  973. public static function getThemeFallback()
  974. {
  975. $theme = api_get_configuration_value('theme_fallback');
  976. if (empty($theme)) {
  977. $theme = 'chamilo';
  978. }
  979. return $theme;
  980. }
  981. /**
  982. * @param bool|true $setLoginForm
  983. */
  984. public function setLoginForm($setLoginForm = true)
  985. {
  986. global $loginFailed;
  987. $userId = api_get_user_id();
  988. if (!($userId) || api_is_anonymous($userId)) {
  989. // Only display if the user isn't logged in.
  990. $this->assign(
  991. 'login_language_form',
  992. api_display_language_form(true)
  993. );
  994. if ($setLoginForm) {
  995. $this->assign('login_form', $this->displayLoginForm());
  996. if ($loginFailed) {
  997. $this->assign('login_failed', $this::handleLoginFailed());
  998. }
  999. }
  1000. }
  1001. }
  1002. /**
  1003. * @return string
  1004. */
  1005. public function handleLoginFailed()
  1006. {
  1007. $message = get_lang('InvalidId');
  1008. if (!isset($_GET['error'])) {
  1009. if (api_is_self_registration_allowed()) {
  1010. $message = get_lang('InvalidForSelfRegistration');
  1011. }
  1012. } else {
  1013. switch ($_GET['error']) {
  1014. case '':
  1015. if (api_is_self_registration_allowed()) {
  1016. $message = get_lang('InvalidForSelfRegistration');
  1017. }
  1018. break;
  1019. case 'account_expired':
  1020. $message = get_lang('AccountExpired');
  1021. break;
  1022. case 'account_inactive':
  1023. $message = get_lang('AccountInactive');
  1024. break;
  1025. case 'user_password_incorrect':
  1026. $message = get_lang('InvalidId');
  1027. break;
  1028. case 'access_url_inactive':
  1029. $message = get_lang('AccountURLInactive');
  1030. break;
  1031. case 'wrong_captcha':
  1032. $message = get_lang('TheTextYouEnteredDoesNotMatchThePicture');
  1033. break;
  1034. case 'blocked_by_captcha':
  1035. $message = get_lang('AccountBlockedByCaptcha');
  1036. break;
  1037. case 'multiple_connection_not_allowed':
  1038. $message = get_lang('MultipleConnectionsAreNotAllow');
  1039. break;
  1040. case 'unrecognize_sso_origin':
  1041. //$message = get_lang('SSOError');
  1042. break;
  1043. }
  1044. }
  1045. return Display::return_message($message, 'error');
  1046. }
  1047. /**
  1048. * @return string
  1049. */
  1050. public function displayLoginForm()
  1051. {
  1052. $form = new FormValidator(
  1053. 'formLogin',
  1054. 'POST',
  1055. null,
  1056. null,
  1057. null,
  1058. FormValidator::LAYOUT_BOX_NO_LABEL
  1059. );
  1060. $form->addText(
  1061. 'login',
  1062. get_lang('UserName'),
  1063. true,
  1064. array('id' => 'login', 'autofocus' => 'autofocus', 'icon' => 'user')
  1065. );
  1066. $form->addElement(
  1067. 'password',
  1068. 'password',
  1069. get_lang('Pass'),
  1070. array('id' => 'password', 'icon' => 'lock')
  1071. );
  1072. // Captcha
  1073. $captcha = api_get_setting('allow_captcha');
  1074. $allowCaptcha = $captcha == 'true';
  1075. if ($allowCaptcha) {
  1076. $useCaptcha = isset($_SESSION['loginFailed']) ? $_SESSION['loginFailed'] : null;
  1077. if ($useCaptcha) {
  1078. $ajax = api_get_path(WEB_AJAX_PATH).'form.ajax.php?a=get_captcha';
  1079. $options = array(
  1080. 'width' => 250,
  1081. 'height' => 90,
  1082. 'callback' => $ajax.'&var='.basename(__FILE__, '.php'),
  1083. 'sessionVar' => basename(__FILE__, '.php'),
  1084. 'imageOptions' => array(
  1085. 'font_size' => 20,
  1086. 'font_path' => api_get_path(SYS_FONTS_PATH) . 'opensans/',
  1087. 'font_file' => 'OpenSans-Regular.ttf',
  1088. //'output' => 'gif'
  1089. )
  1090. );
  1091. // Minimum options using all defaults (including defaults for Image_Text):
  1092. //$options = array('callback' => 'qfcaptcha_image.php');
  1093. $captcha_question = $form->addElement('CAPTCHA_Image', 'captcha_question', '', $options);
  1094. $form->addHtml(get_lang('ClickOnTheImageForANewOne'));
  1095. $form->addElement('text', 'captcha', get_lang('EnterTheLettersYouSee'));
  1096. $form->addRule('captcha', get_lang('EnterTheCharactersYouReadInTheImage'), 'required', null, 'client');
  1097. $form->addRule('captcha', get_lang('TheTextYouEnteredDoesNotMatchThePicture'), 'CAPTCHA', $captcha_question);
  1098. }
  1099. }
  1100. $form->addButton('submitAuth', get_lang('LoginEnter'), null, 'primary', null, 'btn-block');
  1101. $html = $form->returnForm();
  1102. if (api_get_setting('openid_authentication') == 'true') {
  1103. include_once 'main/auth/openid/login.php';
  1104. $html .= '<div>'.openid_form().'</div>';
  1105. }
  1106. return $html;
  1107. }
  1108. /**
  1109. * Set administrator variables
  1110. */
  1111. private function setAdministratorParams()
  1112. {
  1113. $_admin = [
  1114. 'email' => api_get_setting('emailAdministrator'),
  1115. 'surname' => api_get_setting('administratorSurname'),
  1116. 'name' => api_get_setting('administratorName'),
  1117. 'telephone' => api_get_setting('administratorTelephone')
  1118. ];
  1119. $this->assign('_admin', $_admin);
  1120. }
  1121. }