template.lib.php 56 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658
  1. <?php
  2. /* For licensing terms, see /license.txt */
  3. /**
  4. * Class Template.
  5. *
  6. * @author Julio Montoya <gugli100@gmail.com>
  7. *
  8. * @todo better organization of the class, methods and variables
  9. */
  10. class Template
  11. {
  12. /**
  13. * The Template folder name see main/template.
  14. *
  15. * @var string
  16. */
  17. public $templateFolder = 'default';
  18. /**
  19. * The theme that will be used: chamilo, public_admin, chamilo_red, etc
  20. * This variable is set from the database.
  21. *
  22. * @var string
  23. */
  24. public $theme = '';
  25. /**
  26. * @var string
  27. */
  28. public $preview_theme = '';
  29. public $title = null;
  30. public $show_header;
  31. public $show_footer;
  32. public $help;
  33. public $menu_navigation = []; //Used in the userportal.lib.php function: return_navigation_course_links()
  34. public $show_learnpath = false; // This is a learnpath section or not?
  35. public $plugin = null;
  36. public $course_id = null;
  37. public $user_is_logged_in = false;
  38. public $twig = null;
  39. /* Loads chamilo plugins */
  40. public $load_plugins = false;
  41. public $params = [];
  42. public $force_plugin_load = false;
  43. private $themeDir;
  44. /**
  45. * @param string $title
  46. * @param bool $show_header
  47. * @param bool $show_footer
  48. * @param bool $show_learnpath
  49. * @param bool $hide_global_chat
  50. * @param bool $load_plugins
  51. * @param bool $sendHeaders send http headers or not
  52. */
  53. public function __construct(
  54. $title = '',
  55. $show_header = true,
  56. $show_footer = true,
  57. $show_learnpath = false,
  58. $hide_global_chat = false,
  59. $load_plugins = true,
  60. $sendHeaders = true
  61. ) {
  62. // Page title
  63. $this->title = $title;
  64. $this->show_learnpath = $show_learnpath;
  65. if (empty($this->show_learnpath)) {
  66. $origin = api_get_origin();
  67. if ($origin === 'learnpath') {
  68. $this->show_learnpath = true;
  69. $show_footer = false;
  70. $show_header = false;
  71. }
  72. }
  73. $this->hide_global_chat = $hide_global_chat;
  74. $this->load_plugins = $load_plugins;
  75. $template_paths = [
  76. api_get_path(SYS_CODE_PATH).'template/overrides', // user defined templates
  77. api_get_path(SYS_CODE_PATH).'template', //template folder
  78. api_get_path(SYS_PLUGIN_PATH), // plugin folder
  79. ];
  80. $urlId = api_get_current_access_url_id();
  81. $cache_folder = api_get_path(SYS_ARCHIVE_PATH).'twig/'.$urlId.'/';
  82. if (!is_dir($cache_folder)) {
  83. mkdir($cache_folder, api_get_permissions_for_new_directories(), true);
  84. }
  85. $loader = new Twig_Loader_Filesystem($template_paths);
  86. $isTestMode = api_get_setting('server_type') === 'test';
  87. //Setting Twig options depending on the server see http://twig.sensiolabs.org/doc/api.html#environment-options
  88. if ($isTestMode) {
  89. $options = [
  90. //'cache' => api_get_path(SYS_ARCHIVE_PATH), //path to the cache folder
  91. 'autoescape' => false,
  92. 'debug' => true,
  93. 'auto_reload' => true,
  94. 'optimizations' => 0,
  95. // turn on optimizations with -1
  96. 'strict_variables' => false,
  97. //If set to false, Twig will silently ignore invalid variables
  98. ];
  99. } else {
  100. $options = [
  101. 'cache' => $cache_folder,
  102. //path to the cache folder
  103. 'autoescape' => false,
  104. 'debug' => false,
  105. 'auto_reload' => false,
  106. 'optimizations' => -1,
  107. // turn on optimizations with -1
  108. 'strict_variables' => false,
  109. //If set to false, Twig will silently ignore invalid variables
  110. ];
  111. }
  112. $this->twig = new Twig_Environment($loader, $options);
  113. if ($isTestMode) {
  114. $this->twig->addExtension(new Twig_Extension_Debug());
  115. }
  116. // Twig filters setup
  117. $filters = [
  118. 'get_plugin_lang',
  119. 'get_lang',
  120. 'api_get_path',
  121. 'api_get_local_time',
  122. 'api_convert_and_format_date',
  123. 'api_is_allowed_to_edit',
  124. 'api_get_user_info',
  125. 'api_get_configuration_value',
  126. 'api_get_setting',
  127. [
  128. 'name' => 'return_message',
  129. 'callable' => 'Display::return_message_and_translate',
  130. ],
  131. [
  132. 'name' => 'display_page_header',
  133. 'callable' => 'Display::page_header_and_translate',
  134. ],
  135. [
  136. 'name' => 'display_page_subheader',
  137. 'callable' => 'Display::page_subheader_and_translate',
  138. ],
  139. [
  140. 'name' => 'icon',
  141. 'callable' => 'Template::get_icon_path',
  142. ],
  143. [
  144. 'name' => 'img',
  145. 'callable' => 'Template::get_image',
  146. ],
  147. [
  148. 'name' => 'format_date',
  149. 'callable' => 'Template::format_date',
  150. ],
  151. ];
  152. foreach ($filters as $filter) {
  153. if (is_array($filter)) {
  154. $this->twig->addFilter(new Twig_SimpleFilter($filter['name'], $filter['callable']));
  155. } else {
  156. $this->twig->addFilter(new Twig_SimpleFilter($filter, $filter));
  157. }
  158. }
  159. // Setting system variables
  160. $this->set_system_parameters();
  161. // Setting user variables
  162. $this->set_user_parameters();
  163. // Setting course variables
  164. $this->set_course_parameters();
  165. // Setting administrator variables
  166. $this->setAdministratorParams();
  167. //$this->setCSSEditor();
  168. // Header and footer are showed by default
  169. $this->set_footer($show_footer);
  170. $this->set_header($show_header);
  171. $this->set_header_parameters($sendHeaders);
  172. $this->set_footer_parameters();
  173. $defaultStyle = api_get_configuration_value('default_template');
  174. if (!empty($defaultStyle)) {
  175. $this->templateFolder = $defaultStyle;
  176. }
  177. $this->assign('template', $this->templateFolder);
  178. $this->assign('locale', api_get_language_isocode());
  179. $this->assign('login_class', null);
  180. $allow = api_get_configuration_value('show_language_selector_in_menu');
  181. if ($allow) {
  182. $this->assign('language_form', api_display_language_form());
  183. }
  184. // Chamilo plugins
  185. if ($this->show_header) {
  186. if ($this->load_plugins) {
  187. $this->plugin = new AppPlugin();
  188. //1. Showing installed plugins in regions
  189. $pluginRegions = $this->plugin->get_plugin_regions();
  190. foreach ($pluginRegions as $region) {
  191. $this->set_plugin_region($region);
  192. }
  193. //2. Loading the course plugin info
  194. global $course_plugin;
  195. if (isset($course_plugin) && !empty($course_plugin) && !empty($this->course_id)) {
  196. //Load plugin get_langs
  197. $this->plugin->load_plugin_lang_variables($course_plugin);
  198. }
  199. }
  200. }
  201. }
  202. /**
  203. * @param string $image
  204. * @param int $size
  205. *
  206. * @return string
  207. */
  208. public static function get_icon_path($image, $size = ICON_SIZE_SMALL)
  209. {
  210. return Display::return_icon($image, '', [], $size, false, true);
  211. }
  212. /**
  213. * @param string $image
  214. * @param int $size
  215. * @param string $name
  216. *
  217. * @return string
  218. */
  219. public static function get_image($image, $size = ICON_SIZE_SMALL, $name = '')
  220. {
  221. return Display::return_icon($image, $name, [], $size);
  222. }
  223. /**
  224. * @param string $timestamp
  225. * @param string $format
  226. *
  227. * @return string
  228. */
  229. public static function format_date($timestamp, $format = null)
  230. {
  231. return api_format_date($timestamp, $format);
  232. }
  233. /**
  234. * Return the item's url key:.
  235. *
  236. * c_id=xx&id=xx
  237. *
  238. * @param object $item
  239. *
  240. * @return string
  241. */
  242. public static function key($item)
  243. {
  244. $id = isset($item->id) ? $item->id : null;
  245. $c_id = isset($item->c_id) ? $item->c_id : null;
  246. $result = '';
  247. if ($c_id) {
  248. $result = "c_id=$c_id";
  249. }
  250. if ($id) {
  251. if ($result) {
  252. $result .= "&amp;id=$id";
  253. } else {
  254. $result .= "&amp;id=$id";
  255. }
  256. }
  257. return $result;
  258. }
  259. /**
  260. * @param string $helpInput
  261. */
  262. public function setHelp($helpInput = null)
  263. {
  264. if (!empty($helpInput)) {
  265. $help = $helpInput;
  266. } else {
  267. $help = $this->help;
  268. }
  269. $content = '';
  270. if (api_get_setting('enable_help_link') == 'true') {
  271. if (!empty($help)) {
  272. $help = Security::remove_XSS($help);
  273. $content = '<div class="help">';
  274. $content .= Display::url(
  275. Display::return_icon('help.large.png', get_lang('Help')),
  276. api_get_path(WEB_CODE_PATH).'help/help.php?open='.$help,
  277. [
  278. 'class' => 'ajax',
  279. 'data-title' => get_lang('Help'),
  280. ]
  281. );
  282. $content .= '</div>';
  283. }
  284. }
  285. $this->assign('help_content', $content);
  286. }
  287. /**
  288. * Use template system to parse the actions menu.
  289. *
  290. * @todo finish it!
  291. */
  292. public function set_actions($actions)
  293. {
  294. $action_string = '';
  295. if (!empty($actions)) {
  296. foreach ($actions as $action) {
  297. $action_string .= $action;
  298. }
  299. }
  300. $this->assign('actions', $actions);
  301. }
  302. /**
  303. * Shortcut to display a 1 col layout (index.php).
  304. * */
  305. public function display_one_col_template()
  306. {
  307. $tpl = $this->get_template('layout/layout_1_col.tpl');
  308. $this->display($tpl);
  309. }
  310. /**
  311. * Shortcut to display a 2 col layout (userportal.php).
  312. */
  313. public function display_two_col_template()
  314. {
  315. $tpl = $this->get_template('layout/layout_2_col.tpl');
  316. $this->display($tpl);
  317. }
  318. /**
  319. * Displays an empty template.
  320. */
  321. public function display_blank_template()
  322. {
  323. $tpl = $this->get_template('layout/blank.tpl');
  324. $this->display($tpl);
  325. }
  326. /**
  327. * Displays an empty template.
  328. */
  329. public function display_no_layout_template()
  330. {
  331. $tpl = $this->get_template('layout/no_layout.tpl');
  332. $this->display($tpl);
  333. }
  334. /**
  335. * Sets the footer visibility.
  336. *
  337. * @param bool true if we show the footer
  338. */
  339. public function set_footer($status)
  340. {
  341. $this->show_footer = $status;
  342. $this->assign('show_footer', $status);
  343. }
  344. /**
  345. * return true if toolbar has to be displayed for user.
  346. *
  347. * @return bool
  348. */
  349. public static function isToolBarDisplayedForUser()
  350. {
  351. //Toolbar
  352. $show_admin_toolbar = api_get_setting('show_admin_toolbar');
  353. $show_toolbar = false;
  354. switch ($show_admin_toolbar) {
  355. case 'do_not_show':
  356. break;
  357. case 'show_to_admin':
  358. if (api_is_platform_admin()) {
  359. $show_toolbar = true;
  360. }
  361. break;
  362. case 'show_to_admin_and_teachers':
  363. if (api_is_platform_admin() || api_is_allowed_to_edit()) {
  364. $show_toolbar = true;
  365. }
  366. break;
  367. case 'show_to_all':
  368. $show_toolbar = true;
  369. break;
  370. }
  371. return $show_toolbar;
  372. }
  373. /**
  374. * Sets the header visibility.
  375. *
  376. * @param bool true if we show the header
  377. */
  378. public function set_header($status)
  379. {
  380. $this->show_header = $status;
  381. $this->assign('show_header', $status);
  382. $show_toolbar = 0;
  383. if (self::isToolBarDisplayedForUser()) {
  384. $show_toolbar = 1;
  385. }
  386. $this->assign('show_toolbar', $show_toolbar);
  387. //Only if course is available
  388. $show_course_shortcut = null;
  389. $show_course_navigation_menu = null;
  390. if (!empty($this->course_id) && $this->user_is_logged_in) {
  391. if (api_get_setting('show_toolshortcuts') != 'false') {
  392. //Course toolbar
  393. $show_course_shortcut = CourseHome::show_navigation_tool_shortcuts();
  394. }
  395. if (api_get_setting('show_navigation_menu') != 'false') {
  396. //Course toolbar
  397. $show_course_navigation_menu = CourseHome::show_navigation_menu();
  398. }
  399. }
  400. $this->assign('show_course_shortcut', $show_course_shortcut);
  401. $this->assign('show_course_navigation_menu', $show_course_navigation_menu);
  402. }
  403. /**
  404. * Returns the sub-folder and filename for the given tpl file.
  405. * If template not found in overrides/ or custom template folder, the
  406. * default template will be used.
  407. *
  408. * @param string $name
  409. *
  410. * @return string
  411. */
  412. public function get_template($name)
  413. {
  414. // Check if the tpl file is present in the main/template/overrides/ dir
  415. // Overrides is a special directory meant for temporary template
  416. // customization. It must be taken into account before anything else
  417. $file = api_get_path(SYS_CODE_PATH).'template/overrides/'.$name;
  418. if (is_readable($file)) {
  419. return 'overrides/'.$name;
  420. }
  421. // If a template folder has been manually defined, search for the right
  422. // file, and if not found, go for the same file in the default template
  423. if ($this->templateFolder != 'default') {
  424. // Avoid missing template error, use the default file.
  425. $file = api_get_path(SYS_CODE_PATH).'template/'.$this->templateFolder.'/'.$name;
  426. if (!file_exists($file)) {
  427. return 'default/'.$name;
  428. }
  429. }
  430. return $this->templateFolder.'/'.$name;
  431. }
  432. /**
  433. * Get CSS themes sub-directory.
  434. *
  435. * @param string $theme
  436. *
  437. * @return string with a trailing slash, e.g. 'themes/chamilo_red/'
  438. */
  439. public static function getThemeDir($theme)
  440. {
  441. $themeDir = 'themes/'.$theme.'/';
  442. $virtualTheme = api_get_configuration_value('virtual_css_theme_folder');
  443. if (!empty($virtualTheme)) {
  444. $virtualThemeList = api_get_themes(true);
  445. $isVirtualTheme = in_array($theme, array_keys($virtualThemeList));
  446. if ($isVirtualTheme) {
  447. $themeDir = 'themes/'.$virtualTheme.'/'.$theme.'/';
  448. }
  449. }
  450. return $themeDir;
  451. }
  452. /**
  453. * Set system parameters from api_get_configuration into _s array for use in TPLs
  454. * Also fills the _p array from getWebPaths().
  455. *
  456. * @uses \self::getWebPaths()
  457. */
  458. public function set_system_parameters()
  459. {
  460. $this->theme = api_get_visual_theme();
  461. if (!empty($this->preview_theme)) {
  462. $this->theme = $this->preview_theme;
  463. }
  464. $this->themeDir = self::getThemeDir($this->theme);
  465. // Setting app paths/URLs
  466. $this->assign('_p', $this->getWebPaths());
  467. // Here we can add system parameters that can be use in any template
  468. $_s = [
  469. 'software_name' => api_get_configuration_value('software_name'),
  470. 'system_version' => api_get_configuration_value('system_version'),
  471. 'site_name' => api_get_setting('siteName'),
  472. 'institution' => api_get_setting('Institution'),
  473. 'date' => api_format_date('now', DATE_FORMAT_LONG),
  474. 'timezone' => api_get_timezone(),
  475. 'gamification_mode' => api_get_setting('gamification_mode'),
  476. ];
  477. $this->assign('_s', $_s);
  478. }
  479. /**
  480. * Set theme, include mainstream CSS files.
  481. *
  482. * @see setCssCustomFiles() for additional CSS sheets
  483. */
  484. public function setCssFiles()
  485. {
  486. global $disable_js_and_css_files;
  487. $css = [];
  488. // Default CSS Bootstrap
  489. $bowerCSSFiles = [
  490. 'fontawesome/css/font-awesome.min.css',
  491. 'jquery-ui/themes/smoothness/theme.css',
  492. 'jquery-ui/themes/smoothness/jquery-ui.min.css',
  493. 'mediaelement/build/mediaelementplayer.min.css',
  494. 'jqueryui-timepicker-addon/dist/jquery-ui-timepicker-addon.min.css',
  495. 'bootstrap/dist/css/bootstrap.min.css',
  496. 'jquery.scrollbar/jquery.scrollbar.css',
  497. 'bootstrap-daterangepicker/daterangepicker.css',
  498. 'bootstrap-select/dist/css/bootstrap-select.min.css',
  499. 'select2/dist/css/select2.min.css',
  500. 'flag-icon-css/css/flag-icon.min.css',
  501. ];
  502. foreach ($bowerCSSFiles as $file) {
  503. $css[] = api_get_path(WEB_PUBLIC_PATH).'assets/'.$file;
  504. }
  505. $css[] = api_get_path(WEB_LIBRARY_PATH).'javascript/chosen/chosen.css';
  506. if (api_is_global_chat_enabled()) {
  507. $css[] = api_get_path(WEB_LIBRARY_PATH).'javascript/chat/css/chat.css';
  508. }
  509. $css_file_to_string = '';
  510. foreach ($css as $file) {
  511. $css_file_to_string .= api_get_css($file);
  512. }
  513. if (!$disable_js_and_css_files) {
  514. $this->assign('css_static_file_to_string', $css_file_to_string);
  515. }
  516. }
  517. public function setCSSEditor()
  518. {
  519. $cssEditor = api_get_cdn_path(api_get_path(WEB_CSS_PATH).'editor.css');
  520. if (is_file(api_get_path(SYS_CSS_PATH).$this->themeDir.'editor.css')) {
  521. $cssEditor = api_get_path(WEB_CSS_PATH).$this->themeDir.'editor.css';
  522. }
  523. $this->assign('cssEditor', $cssEditor);
  524. }
  525. /**
  526. * Prepare custom CSS to be added at the very end of the <head> section.
  527. *
  528. * @see setCssFiles() for the mainstream CSS files
  529. */
  530. public function setCssCustomFiles()
  531. {
  532. global $disable_js_and_css_files;
  533. // Base CSS
  534. $css[] = api_get_cdn_path(api_get_path(WEB_CSS_PATH).'base.css');
  535. if ($this->show_learnpath) {
  536. $css[] = api_get_cdn_path(api_get_path(WEB_CSS_PATH).'scorm.css');
  537. if (is_file(api_get_path(SYS_CSS_PATH).$this->themeDir.'learnpath.css')) {
  538. $css[] = api_get_path(WEB_CSS_PATH).$this->themeDir.'learnpath.css';
  539. }
  540. }
  541. $css[] = api_get_cdn_path(api_get_path(WEB_CSS_PATH).$this->themeDir.'default.css');
  542. $css_file_to_string = null;
  543. foreach ($css as $file) {
  544. $css_file_to_string .= api_get_css($file);
  545. }
  546. // @todo move this somewhere else. Special fix when using tablets in order to see the text near icons
  547. if (SHOW_TEXT_NEAR_ICONS == true) {
  548. //hack in order to fix the actions buttons
  549. $css_file_to_string .= '<style>
  550. .td_actions a {
  551. float:left;
  552. width:100%;
  553. }
  554. .forum_message_left a {
  555. float:left;
  556. width:100%;
  557. }
  558. </style>';
  559. }
  560. $navigator_info = api_get_navigator();
  561. if ($navigator_info['name'] == 'Internet Explorer' && $navigator_info['version'] == '6') {
  562. $css_file_to_string .= 'img, div { behavior: url('.api_get_path(WEB_LIBRARY_PATH).'javascript/iepngfix/iepngfix.htc) } '."\n";
  563. }
  564. if (!$disable_js_and_css_files) {
  565. $this->assign('css_custom_file_to_string', $css_file_to_string);
  566. $style_print = '';
  567. if (is_readable(api_get_path(SYS_CSS_PATH).$this->theme.'/print.css')) {
  568. $style_print = api_get_css(
  569. api_get_cdn_path(api_get_path(WEB_CSS_PATH).$this->theme.'/print.css'),
  570. 'print'
  571. );
  572. }
  573. $this->assign('css_style_print', $style_print);
  574. }
  575. // Logo
  576. $logo = return_logo($this->theme);
  577. $this->assign('logo', $logo);
  578. $this->assign('show_media_element', 1);
  579. }
  580. /**
  581. * Declare and define the template variable that will be used to load
  582. * javascript libraries in the header.
  583. */
  584. public function set_js_files()
  585. {
  586. global $disable_js_and_css_files, $htmlHeadXtra;
  587. $isoCode = api_get_language_isocode();
  588. $selectLink = 'bootstrap-select/dist/js/i18n/defaults-'.$isoCode.'_'.strtoupper($isoCode).'.min.js';
  589. if ($isoCode == 'en') {
  590. $selectLink = 'bootstrap-select/dist/js/i18n/defaults-'.$isoCode.'_US.min.js';
  591. }
  592. // JS files
  593. $js_files = [
  594. 'chosen/chosen.jquery.min.js',
  595. ];
  596. $viewBySession = api_get_setting('my_courses_view_by_session') === 'true';
  597. if (api_is_global_chat_enabled() || $viewBySession) {
  598. // Do not include the global chat in LP
  599. if ($this->show_learnpath == false &&
  600. $this->show_footer == true &&
  601. $this->hide_global_chat == false
  602. ) {
  603. $js_files[] = 'chat/js/chat.js';
  604. }
  605. }
  606. if (api_get_setting('accessibility_font_resize') == 'true') {
  607. $js_files[] = 'fontresize.js';
  608. }
  609. $js_file_to_string = '';
  610. $bowerJsFiles = [
  611. 'modernizr/modernizr.js',
  612. 'jquery/dist/jquery.min.js',
  613. 'bootstrap/dist/js/bootstrap.min.js',
  614. 'jquery-ui/jquery-ui.min.js',
  615. 'jqueryui-touch-punch/jquery.ui.touch-punch.min.js',
  616. 'moment/min/moment-with-locales.js',
  617. 'bootstrap-daterangepicker/daterangepicker.js',
  618. 'jquery-timeago/jquery.timeago.js',
  619. 'mediaelement/build/mediaelement-and-player.min.js',
  620. 'jqueryui-timepicker-addon/dist/jquery-ui-timepicker-addon.min.js',
  621. 'image-map-resizer/js/imageMapResizer.min.js',
  622. 'jquery.scrollbar/jquery.scrollbar.min.js',
  623. 'readmore-js/readmore.min.js',
  624. 'bootstrap-select/dist/js/bootstrap-select.min.js',
  625. $selectLink,
  626. 'select2/dist/js/select2.min.js',
  627. "select2/dist/js/i18n/$isoCode.js",
  628. ];
  629. if (CHAMILO_LOAD_WYSIWYG == true) {
  630. $bowerJsFiles[] = 'ckeditor/ckeditor.js';
  631. }
  632. if (api_get_setting('include_asciimathml_script') == 'true') {
  633. $bowerJsFiles[] = 'MathJax/MathJax.js?config=TeX-MML-AM_HTMLorMML';
  634. }
  635. if ($isoCode != 'en') {
  636. $bowerJsFiles[] = 'jqueryui-timepicker-addon/dist/i18n/jquery-ui-timepicker-'.$isoCode.'.js';
  637. $bowerJsFiles[] = 'jquery-ui/ui/minified/i18n/datepicker-'.$isoCode.'.min.js';
  638. }
  639. foreach ($bowerJsFiles as $file) {
  640. $js_file_to_string .= '<script type="text/javascript" src="'.api_get_path(WEB_PUBLIC_PATH).'assets/'.$file.'"></script>'."\n";
  641. }
  642. foreach ($js_files as $file) {
  643. $js_file_to_string .= api_get_js($file);
  644. }
  645. // Loading email_editor js
  646. if (!api_is_anonymous() && api_get_setting('allow_email_editor') == 'true') {
  647. $template = $this->get_template('mail_editor/email_link.js.tpl');
  648. $js_file_to_string .= $this->fetch($template);
  649. }
  650. if (!$disable_js_and_css_files) {
  651. $this->assign('js_file_to_string', $js_file_to_string);
  652. $extra_headers = '<script>var _p = '.json_encode($this->getWebPaths(), JSON_PRETTY_PRINT).'</script>';
  653. //Adding jquery ui by default
  654. $extra_headers .= api_get_jquery_ui_js();
  655. //$extra_headers = '';
  656. if (isset($htmlHeadXtra) && $htmlHeadXtra) {
  657. foreach ($htmlHeadXtra as &$this_html_head) {
  658. $extra_headers .= $this_html_head."\n";
  659. }
  660. }
  661. $this->assign('extra_headers', $extra_headers);
  662. }
  663. }
  664. /**
  665. * Special function to declare last-minute JS libraries which depend on
  666. * other things to be declared first. In particular, it might be useful
  667. * under IE9 with compatibility mode, which for some reason is getting
  668. * upset when a variable is used in a function (even if not used yet)
  669. * when this variable hasn't been defined yet.
  670. */
  671. public function set_js_files_post()
  672. {
  673. global $disable_js_and_css_files;
  674. $js_files = [];
  675. if (api_is_global_chat_enabled()) {
  676. //Do not include the global chat in LP
  677. if ($this->show_learnpath == false && $this->show_footer == true && $this->hide_global_chat == false) {
  678. $js_files[] = 'chat/js/chat.js';
  679. }
  680. }
  681. $js_file_to_string = null;
  682. foreach ($js_files as $js_file) {
  683. $js_file_to_string .= api_get_js($js_file);
  684. }
  685. if (!$disable_js_and_css_files) {
  686. $this->assign('js_file_to_string_post', $js_file_to_string);
  687. }
  688. }
  689. /**
  690. * Show header template.
  691. */
  692. public function show_header_template()
  693. {
  694. $tpl = $this->get_template('layout/show_header.tpl');
  695. $this->display($tpl);
  696. }
  697. /**
  698. * Show footer template.
  699. */
  700. public function show_footer_template()
  701. {
  702. $tpl = $this->get_template('layout/show_footer.tpl');
  703. $this->display($tpl);
  704. }
  705. /**
  706. * Show footer js template.
  707. */
  708. public function show_footer_js_template()
  709. {
  710. $tpl = $this->get_template('layout/footer.js.tpl');
  711. $this->display($tpl);
  712. }
  713. /**
  714. * Sets the plugin content in a template variable.
  715. *
  716. * @param string $pluginRegion
  717. */
  718. public function set_plugin_region($pluginRegion)
  719. {
  720. if (!empty($pluginRegion)) {
  721. $regionContent = $this->plugin->load_region(
  722. $pluginRegion,
  723. $this,
  724. $this->force_plugin_load
  725. );
  726. $pluginList = $this->plugin->get_installed_plugins();
  727. foreach ($pluginList as $plugin_name) {
  728. // The plugin_info variable is available inside the plugin index
  729. $pluginInfo = $this->plugin->getPluginInfo($plugin_name);
  730. if (isset($pluginInfo['is_course_plugin']) && $pluginInfo['is_course_plugin']) {
  731. $courseInfo = api_get_course_info();
  732. if (!empty($courseInfo)) {
  733. if (isset($pluginInfo['obj']) && $pluginInfo['obj'] instanceof Plugin) {
  734. /** @var Plugin $plugin */
  735. $plugin = $pluginInfo['obj'];
  736. $regionContent .= $plugin->renderRegion($pluginRegion);
  737. }
  738. }
  739. } else {
  740. continue;
  741. }
  742. }
  743. if (!empty($regionContent)) {
  744. $this->assign('plugin_'.$pluginRegion, $regionContent);
  745. } else {
  746. $this->assign('plugin_'.$pluginRegion, null);
  747. }
  748. }
  749. return null;
  750. }
  751. /**
  752. * @param string $template
  753. *
  754. * @return string
  755. */
  756. public function fetch($template = null)
  757. {
  758. $template = $this->twig->loadTemplate($template);
  759. return $template->render($this->params);
  760. }
  761. /**
  762. * @param string $variable
  763. * @param mixed $value
  764. */
  765. public function assign($variable, $value = '')
  766. {
  767. $this->params[$variable] = $value;
  768. }
  769. /**
  770. * Render the template.
  771. *
  772. * @param string $template The template path
  773. * @param bool $clearFlashMessages Clear the $_SESSION variables for flash messages
  774. */
  775. public function display($template, $clearFlashMessages = true)
  776. {
  777. $this->assign('flash_messages', Display::getFlashToString());
  778. if ($clearFlashMessages) {
  779. Display::cleanFlashMessages();
  780. }
  781. echo $this->twig->render($template, $this->params);
  782. }
  783. /**
  784. * Adds a body class for login pages.
  785. */
  786. public function setLoginBodyClass()
  787. {
  788. $this->assign('login_class', 'section-login');
  789. }
  790. /**
  791. * The theme that will be used if the database is not working.
  792. *
  793. * @return string
  794. */
  795. public static function getThemeFallback()
  796. {
  797. $theme = api_get_configuration_value('theme_fallback');
  798. if (empty($theme)) {
  799. $theme = 'chamilo';
  800. }
  801. return $theme;
  802. }
  803. /**
  804. * @param bool|true $setLoginForm
  805. */
  806. public function setLoginForm($setLoginForm = true)
  807. {
  808. global $loginFailed;
  809. $userId = api_get_user_id();
  810. if (!($userId) || api_is_anonymous($userId)) {
  811. // Only display if the user isn't logged in.
  812. $this->assign(
  813. 'login_language_form',
  814. api_display_language_form(true, true)
  815. );
  816. if ($setLoginForm) {
  817. $this->assign('login_form', $this->displayLoginForm());
  818. if ($loginFailed) {
  819. $this->assign('login_failed', $this::handleLoginFailed());
  820. }
  821. }
  822. }
  823. }
  824. /**
  825. * @return string
  826. */
  827. public function handleLoginFailed()
  828. {
  829. $message = get_lang('InvalidId');
  830. if (!isset($_GET['error'])) {
  831. if (api_is_self_registration_allowed()) {
  832. $message = get_lang('InvalidForSelfRegistration');
  833. }
  834. } else {
  835. switch ($_GET['error']) {
  836. case '':
  837. if (api_is_self_registration_allowed()) {
  838. $message = get_lang('InvalidForSelfRegistration');
  839. }
  840. break;
  841. case 'account_expired':
  842. $message = get_lang('AccountExpired');
  843. break;
  844. case 'account_inactive':
  845. $message = get_lang('AccountInactive');
  846. if (api_get_setting('allow_registration') === 'confirmation') {
  847. $message = sprintf(
  848. get_lang('YourAccountIsInactiveBecauseYouDoesntConfirmItCheckYourEmailAndFollowTheInstructionsOrClickTheFollowingLinkXToReSendTheEmail'),
  849. Display::url(get_lang('ReSendConfirmationMail'), api_get_path(WEB_PATH).'main/auth/resend_confirmation_mail.php'));
  850. }
  851. break;
  852. case 'user_password_incorrect':
  853. $message = get_lang('InvalidId');
  854. break;
  855. case 'access_url_inactive':
  856. $message = get_lang('AccountURLInactive');
  857. break;
  858. case 'wrong_captcha':
  859. $message = get_lang('TheTextYouEnteredDoesNotMatchThePicture');
  860. break;
  861. case 'blocked_by_captcha':
  862. $message = get_lang('AccountBlockedByCaptcha');
  863. break;
  864. case 'multiple_connection_not_allowed':
  865. $message = get_lang('MultipleConnectionsAreNotAllow');
  866. break;
  867. case 'unrecognize_sso_origin':
  868. //$message = get_lang('SSOError');
  869. break;
  870. }
  871. }
  872. return Display::return_message($message, 'error');
  873. }
  874. /**
  875. * @return string
  876. */
  877. public function displayLoginForm()
  878. {
  879. $form = new FormValidator(
  880. 'formLogin',
  881. 'POST',
  882. null,
  883. null,
  884. null,
  885. FormValidator::LAYOUT_BOX_NO_LABEL
  886. );
  887. $params = [
  888. 'id' => 'login',
  889. 'autofocus' => 'autofocus',
  890. 'icon' => 'user fa-fw',
  891. 'placeholder' => get_lang('UserName'),
  892. ];
  893. $browserAutoCapitalize = false;
  894. // Avoid showing the autocapitalize option if the browser doesn't
  895. // support it: this attribute is against the HTML5 standard
  896. if (api_browser_support('autocapitalize')) {
  897. $browserAutoCapitalize = false;
  898. $params['autocapitalize'] = 'none';
  899. }
  900. $form->addText(
  901. 'login',
  902. get_lang('UserName'),
  903. true,
  904. $params
  905. );
  906. $params = [
  907. 'id' => 'password',
  908. 'icon' => 'lock fa-fw',
  909. 'placeholder' => get_lang('Pass'),
  910. ];
  911. if ($browserAutoCapitalize) {
  912. $params['autocapitalize'] = 'none';
  913. }
  914. $form->addElement(
  915. 'password',
  916. 'password',
  917. get_lang('Pass'),
  918. $params
  919. );
  920. // Captcha
  921. $captcha = api_get_setting('allow_captcha');
  922. $allowCaptcha = $captcha === 'true';
  923. if ($allowCaptcha) {
  924. $useCaptcha = isset($_SESSION['loginFailed']) ? $_SESSION['loginFailed'] : null;
  925. if ($useCaptcha) {
  926. $ajax = api_get_path(WEB_AJAX_PATH).'form.ajax.php?a=get_captcha';
  927. $options = [
  928. 'width' => 250,
  929. 'height' => 90,
  930. 'callback' => $ajax.'&var='.basename(__FILE__, '.php'),
  931. 'sessionVar' => basename(__FILE__, '.php'),
  932. 'imageOptions' => [
  933. 'font_size' => 20,
  934. 'font_path' => api_get_path(SYS_FONTS_PATH).'opensans/',
  935. 'font_file' => 'OpenSans-Regular.ttf',
  936. //'output' => 'gif'
  937. ],
  938. ];
  939. // Minimum options using all defaults (including defaults for Image_Text):
  940. //$options = array('callback' => 'qfcaptcha_image.php');
  941. $captcha_question = $form->addElement('CAPTCHA_Image', 'captcha_question', '', $options);
  942. $form->addHtml(get_lang('ClickOnTheImageForANewOne'));
  943. $form->addElement(
  944. 'text',
  945. 'captcha',
  946. get_lang('EnterTheLettersYouSee')
  947. );
  948. $form->addRule(
  949. 'captcha',
  950. get_lang('EnterTheCharactersYouReadInTheImage'),
  951. 'required',
  952. null,
  953. 'client'
  954. );
  955. $form->addRule(
  956. 'captcha',
  957. get_lang('TheTextYouEnteredDoesNotMatchThePicture'),
  958. 'CAPTCHA',
  959. $captcha_question
  960. );
  961. }
  962. }
  963. $form->addButton(
  964. 'submitAuth',
  965. get_lang('LoginEnter'),
  966. null,
  967. 'primary',
  968. null,
  969. 'btn-block'
  970. );
  971. $html = $form->returnForm();
  972. if (api_get_setting('openid_authentication') == 'true') {
  973. include_once api_get_path(SYS_CODE_PATH).'auth/openid/login.php';
  974. $html .= '<div>'.openid_form().'</div>';
  975. }
  976. return $html;
  977. }
  978. /**
  979. * Prepare the _c array for template files. The _c array contains
  980. * information about the current course.
  981. */
  982. private function set_course_parameters()
  983. {
  984. //Setting course id
  985. $course = api_get_course_info();
  986. if (empty($course)) {
  987. $this->assign('course_is_set', false);
  988. return;
  989. }
  990. $this->assign('course_is_set', true);
  991. $this->course_id = $course['id'];
  992. $_c = [
  993. 'id' => $course['id'],
  994. 'code' => $course['code'],
  995. 'title' => $course['name'],
  996. 'visibility' => $course['visibility'],
  997. 'language' => $course['language'],
  998. 'directory' => $course['directory'],
  999. 'session_id' => api_get_session_id(),
  1000. 'user_is_teacher' => api_is_course_admin(),
  1001. 'student_view' => (!empty($_GET['isStudentView']) && $_GET['isStudentView'] == 'true'),
  1002. ];
  1003. $this->assign('course_code', $course['code']);
  1004. $this->assign('_c', $_c);
  1005. }
  1006. /**
  1007. * Prepare the _u array for template files. The _u array contains
  1008. * information about the current user, as returned by
  1009. * api_get_user_info().
  1010. */
  1011. private function set_user_parameters()
  1012. {
  1013. $user_info = [];
  1014. $user_info['logged'] = 0;
  1015. $this->user_is_logged_in = false;
  1016. if (api_user_is_login()) {
  1017. $user_info = api_get_user_info(api_get_user_id(), true);
  1018. $user_info['logged'] = 1;
  1019. $user_info['is_admin'] = 0;
  1020. if (api_is_platform_admin()) {
  1021. $user_info['is_admin'] = 1;
  1022. }
  1023. $user_info['messages_count'] = MessageManager::getCountNewMessages();
  1024. $this->user_is_logged_in = true;
  1025. }
  1026. // Setting the $_u array that could be use in any template
  1027. $this->assign('_u', $user_info);
  1028. }
  1029. /**
  1030. * Get an array of all the web paths available (e.g. 'web' => 'https://my.chamilo.site/').
  1031. *
  1032. * @return array
  1033. */
  1034. private function getWebPaths()
  1035. {
  1036. return [
  1037. 'web' => api_get_path(WEB_PATH),
  1038. 'web_url' => api_get_web_url(),
  1039. 'web_relative' => api_get_path(REL_PATH),
  1040. 'web_course' => api_get_path(WEB_COURSE_PATH),
  1041. 'web_main' => api_get_path(WEB_CODE_PATH),
  1042. 'web_css' => api_get_path(WEB_CSS_PATH),
  1043. 'web_css_theme' => api_get_path(WEB_CSS_PATH).$this->themeDir,
  1044. 'web_ajax' => api_get_path(WEB_AJAX_PATH),
  1045. 'web_img' => api_get_path(WEB_IMG_PATH),
  1046. 'web_plugin' => api_get_path(WEB_PLUGIN_PATH),
  1047. 'web_lib' => api_get_path(WEB_LIBRARY_PATH),
  1048. 'web_upload' => api_get_path(WEB_UPLOAD_PATH),
  1049. 'web_self' => api_get_self(),
  1050. 'web_query_vars' => api_htmlentities($_SERVER['QUERY_STRING']),
  1051. 'web_self_query_vars' => api_htmlentities($_SERVER['REQUEST_URI']),
  1052. 'web_cid_query' => api_get_cidreq(),
  1053. 'basename' => basename(api_get_self()),
  1054. ];
  1055. }
  1056. /**
  1057. * Set header parameters.
  1058. *
  1059. * @param bool $sendHeaders send headers
  1060. */
  1061. private function set_header_parameters($sendHeaders)
  1062. {
  1063. global $httpHeadXtra, $interbreadcrumb, $language_file, $_configuration, $this_section;
  1064. $_course = api_get_course_info();
  1065. $nameTools = $this->title;
  1066. $navigation = return_navigation_array();
  1067. $this->menu_navigation = $navigation['menu_navigation'];
  1068. // ofaj
  1069. $locale = api_get_language_isocode();
  1070. $categories = Database::getManager()->getRepository('ChamiloFaqBundle:Category')->retrieveActive();
  1071. $faqCategories = [];
  1072. if ($categories) {
  1073. /** @var \Chamilo\FaqBundle\Entity\Category $cat */
  1074. foreach ($categories as $cat) {
  1075. $sql = "SELECT * FROM faq_category_translation
  1076. WHERE locale = '$locale' AND translatable_id = ".$cat->getId();
  1077. $result = Database::query($sql);
  1078. $category = Database::fetch_array($result, 'ASSOC');
  1079. $faqCategories[] = $category;
  1080. }
  1081. }
  1082. $this->assign('faq_categories', $faqCategories);
  1083. $this->assign('system_charset', api_get_system_encoding());
  1084. if (isset($httpHeadXtra) && $httpHeadXtra) {
  1085. foreach ($httpHeadXtra as &$thisHttpHead) {
  1086. header($thisHttpHead);
  1087. }
  1088. }
  1089. $this->assign(
  1090. 'online_button',
  1091. Display::return_icon('statusonline.png', null, [], ICON_SIZE_ATOM)
  1092. );
  1093. $this->assign(
  1094. 'offline_button',
  1095. Display::return_icon('statusoffline.png', null, [], ICON_SIZE_ATOM)
  1096. );
  1097. // Get language iso-code for this page - ignore errors
  1098. $this->assign('document_language', api_get_language_isocode());
  1099. $this->assign('current_language', api_get_interface_language());
  1100. $course_title = isset($_course['name']) ? $_course['name'] : null;
  1101. $title_list = [];
  1102. $title_list[] = api_get_setting('Institution');
  1103. $title_list[] = api_get_setting('siteName');
  1104. if (!empty($course_title)) {
  1105. $title_list[] = $course_title;
  1106. }
  1107. if ($nameTools != '') {
  1108. $title_list[] = $nameTools;
  1109. }
  1110. $title_string = '';
  1111. for ($i = 0; $i < count($title_list); $i++) {
  1112. $title_string .= $title_list[$i];
  1113. if (isset($title_list[$i + 1])) {
  1114. $item = trim($title_list[$i + 1]);
  1115. if (!empty($item)) {
  1116. $title_string .= ' - ';
  1117. }
  1118. }
  1119. }
  1120. $this->assign('title_string', $title_string);
  1121. // Setting the theme and CSS files
  1122. $this->setCssFiles();
  1123. $this->set_js_files();
  1124. $this->setCssCustomFiles();
  1125. $browser = api_browser_support('check_browser');
  1126. if ($browser[0] == 'Internet Explorer' && $browser[1] >= '11') {
  1127. $browser_head = '<meta http-equiv="X-UA-Compatible" content="IE=EmulateIE9" />';
  1128. $this->assign('browser_specific_head', $browser_head);
  1129. }
  1130. // Implementation of prefetch.
  1131. // See http://cdn.chamilo.org/main/img/online.png for details
  1132. $prefetch = '';
  1133. if (!empty($_configuration['cdn_enable'])) {
  1134. $prefetch .= '<meta http-equiv="x-dns-prefetch-control" content="on">';
  1135. foreach ($_configuration['cdn'] as $host => $exts) {
  1136. $prefetch .= '<link rel="dns-prefetch" href="'.$host.'">';
  1137. }
  1138. }
  1139. $this->assign('prefetch', $prefetch);
  1140. $this->assign('text_direction', api_get_text_direction());
  1141. $this->assign('section_name', 'section-'.$this_section);
  1142. // Default root chamilo favicon
  1143. $favico = '<link rel="shortcut icon" href="'.api_get_path(WEB_PATH).'favicon.ico" type="image/x-icon" />';
  1144. //Added to verify if in the current Chamilo Theme exist a favicon
  1145. $favicoThemeUrl = api_get_path(SYS_CSS_PATH).$this->themeDir.'images/';
  1146. //If exist pick the current chamilo theme favicon
  1147. if (is_file($favicoThemeUrl.'favicon.ico')) {
  1148. $favico = '<link rel="shortcut icon" href="'.api_get_path(WEB_CSS_PATH).$this->themeDir.'images/favicon.ico" type="image/x-icon" />';
  1149. }
  1150. if (api_is_multiple_url_enabled()) {
  1151. $access_url_id = api_get_current_access_url_id();
  1152. if ($access_url_id != -1) {
  1153. $url_info = api_get_access_url($access_url_id);
  1154. $url = api_remove_trailing_slash(
  1155. preg_replace('/https?:\/\//i', '', $url_info['url'])
  1156. );
  1157. $clean_url = api_replace_dangerous_char($url);
  1158. $clean_url = str_replace('/', '-', $clean_url);
  1159. $clean_url .= '/';
  1160. $homep = api_get_path(REL_PATH).'home/'.$clean_url; //homep for Home Path
  1161. $icon_real_homep = api_get_path(SYS_APP_PATH).'home/'.$clean_url;
  1162. //we create the new dir for the new sites
  1163. if (is_file($icon_real_homep.'favicon.ico')) {
  1164. $favico = '<link rel="shortcut icon" href="'.$homep.'favicon.ico" type="image/x-icon" />';
  1165. }
  1166. }
  1167. }
  1168. $this->assign('favico', $favico);
  1169. $this->setHelp();
  1170. //@todo move this in the template
  1171. $rightFloatMenu = '';
  1172. $iconBug = Display::return_icon(
  1173. 'bug.png',
  1174. get_lang('ReportABug'),
  1175. [],
  1176. ICON_SIZE_LARGE
  1177. );
  1178. if (api_get_setting('show_link_bug_notification') == 'true' && $this->user_is_logged_in) {
  1179. $rightFloatMenu = '<div class="report">
  1180. <a href="https://github.com/chamilo/chamilo-lms/wiki/How-to-report-issues" target="_blank">
  1181. '.$iconBug.'
  1182. </a>
  1183. </div>';
  1184. }
  1185. if (api_get_setting('show_link_ticket_notification') == 'true' &&
  1186. $this->user_is_logged_in
  1187. ) {
  1188. // by default is project_id = 1
  1189. $defaultProjectId = 1;
  1190. $allow = TicketManager::userIsAllowInProject(api_get_user_info(), $defaultProjectId);
  1191. if ($allow) {
  1192. $iconTicket = Display::return_icon(
  1193. 'help.png',
  1194. get_lang('Ticket'),
  1195. [],
  1196. ICON_SIZE_LARGE
  1197. );
  1198. $courseInfo = api_get_course_info();
  1199. $courseParams = '';
  1200. if (!empty($courseInfo)) {
  1201. $courseParams = api_get_cidreq();
  1202. }
  1203. $url = api_get_path(WEB_CODE_PATH).
  1204. 'ticket/tickets.php?project_id='.$defaultProjectId.'&'.$courseParams;
  1205. $rightFloatMenu .= '<div class="help">
  1206. <a href="'.$url.'" target="_blank">
  1207. '.$iconTicket.'
  1208. </a>
  1209. </div>';
  1210. }
  1211. }
  1212. $this->assign('bug_notification', $rightFloatMenu);
  1213. $resize = '';
  1214. if (api_get_setting('accessibility_font_resize') == 'true') {
  1215. $resize .= '<div class="resize_font">';
  1216. $resize .= '<div class="btn-group">';
  1217. $resize .= '<a title="'.get_lang('DecreaseFontSize').'" href="#" class="decrease_font btn btn-default"><em class="fa fa-font"></em></a>';
  1218. $resize .= '<a title="'.get_lang('ResetFontSize').'" href="#" class="reset_font btn btn-default"><em class="fa fa-font"></em></a>';
  1219. $resize .= '<a title="'.get_lang('IncreaseFontSize').'" href="#" class="increase_font btn btn-default"><em class="fa fa-font"></em></a>';
  1220. $resize .= '</div>';
  1221. $resize .= '</div>';
  1222. }
  1223. $this->assign('accessibility', $resize);
  1224. // Preparing values for the menu
  1225. // Logout link
  1226. $hideLogout = api_get_setting('hide_logout_button');
  1227. if ($hideLogout === 'true') {
  1228. $this->assign('logout_link', null);
  1229. } else {
  1230. $this->assign('logout_link', api_get_path(WEB_PATH).'index.php?logout=logout&uid='.api_get_user_id());
  1231. }
  1232. // Profile link
  1233. if (api_get_setting('allow_social_tool') == 'true') {
  1234. $profile_url = api_get_path(WEB_CODE_PATH).'social/home.php';
  1235. } else {
  1236. $profile_url = api_get_path(WEB_CODE_PATH).'auth/profile.php';
  1237. }
  1238. $this->assign('profile_url', $profile_url);
  1239. //Message link
  1240. $message_link = null;
  1241. $message_url = null;
  1242. if (api_get_setting('allow_message_tool') == 'true') {
  1243. $message_url = api_get_path(WEB_CODE_PATH).'messages/inbox.php';
  1244. $message_link = '<a href="'.api_get_path(WEB_CODE_PATH).'messages/inbox.php">'.get_lang('Inbox').'</a>';
  1245. }
  1246. $this->assign('message_link', $message_link);
  1247. $this->assign('message_url', $message_url);
  1248. // Certificate Link
  1249. $allow = api_get_configuration_value('hide_my_certificate_link');
  1250. if ($allow === false) {
  1251. $certificateUrl = api_get_path(WEB_CODE_PATH).'gradebook/my_certificates.php';
  1252. $certificateLink = Display::url(
  1253. get_lang('MyCertificates'),
  1254. $certificateUrl
  1255. );
  1256. $this->assign('certificate_link', $certificateLink);
  1257. $this->assign('certificate_url', $certificateUrl);
  1258. }
  1259. $institution = api_get_setting('Institution');
  1260. $portal_name = empty($institution) ? api_get_setting('siteName') : $institution;
  1261. $this->assign('portal_name', $portal_name);
  1262. //Menu
  1263. $menu = menuArray();
  1264. $this->assign('menu', $menu);
  1265. $breadcrumb = '';
  1266. // Hide breadcrumb in LP
  1267. if ($this->show_learnpath == false) {
  1268. $breadcrumb = return_breadcrumb(
  1269. $interbreadcrumb,
  1270. $language_file,
  1271. $nameTools
  1272. );
  1273. }
  1274. $this->assign('breadcrumb', $breadcrumb);
  1275. //Extra content
  1276. $extra_header = null;
  1277. if (!api_is_platform_admin()) {
  1278. $extra_header = trim(api_get_setting('header_extra_content'));
  1279. }
  1280. $this->assign('header_extra_content', $extra_header);
  1281. if ($sendHeaders) {
  1282. header('Content-Type: text/html; charset='.api_get_system_encoding());
  1283. header(
  1284. 'X-Powered-By: '.$_configuration['software_name'].' '.substr($_configuration['system_version'], 0, 1)
  1285. );
  1286. }
  1287. self::addHTTPSecurityHeaders();
  1288. $socialMeta = '';
  1289. $metaTitle = api_get_setting('meta_title');
  1290. if (!empty($metaTitle)) {
  1291. $socialMeta .= '<meta name="twitter:card" content="summary" />'."\n";
  1292. $metaSite = api_get_setting('meta_twitter_site');
  1293. if (!empty($metaSite)) {
  1294. $socialMeta .= '<meta name="twitter:site" content="'.$metaSite.'" />'."\n";
  1295. $metaCreator = api_get_setting('meta_twitter_creator');
  1296. if (!empty($metaCreator)) {
  1297. $socialMeta .= '<meta name="twitter:creator" content="'.$metaCreator.'" />'."\n";
  1298. }
  1299. }
  1300. // The user badge page emits its own meta tags, so if this is
  1301. // enabled, ignore the global ones
  1302. $userId = isset($_GET['user']) ? intval($_GET['user']) : 0;
  1303. $skillId = isset($_GET['skill']) ? intval($_GET['skill']) : 0;
  1304. if (!$userId && !$skillId) {
  1305. // no combination of user and skill ID has been defined,
  1306. // so print the normal OpenGraph meta tags
  1307. $socialMeta .= '<meta property="og:title" content="'.$metaTitle.'" />'."\n";
  1308. $socialMeta .= '<meta property="og:url" content="'.api_get_path(WEB_PATH).'" />'."\n";
  1309. $metaDescription = api_get_setting('meta_description');
  1310. if (!empty($metaDescription)) {
  1311. $socialMeta .= '<meta property="og:description" content="'.$metaDescription.'" />'."\n";
  1312. }
  1313. $metaImage = api_get_setting('meta_image_path');
  1314. if (!empty($metaImage)) {
  1315. if (is_file(api_get_path(SYS_PATH).$metaImage)) {
  1316. $path = api_get_path(WEB_PATH).$metaImage;
  1317. $socialMeta .= '<meta property="og:image" content="'.$path.'" />'."\n";
  1318. }
  1319. }
  1320. }
  1321. }
  1322. $this->assign('social_meta', $socialMeta);
  1323. }
  1324. /**
  1325. * Set footer parameters.
  1326. */
  1327. private function set_footer_parameters()
  1328. {
  1329. if (api_get_setting('show_administrator_data') === 'true') {
  1330. $firstName = api_get_setting('administratorName');
  1331. $lastName = api_get_setting('administratorSurname');
  1332. if (!empty($firstName) && !empty($lastName)) {
  1333. $name = api_get_person_name($firstName, $lastName);
  1334. } else {
  1335. $name = $lastName;
  1336. if (empty($lastName)) {
  1337. $name = $firstName;
  1338. }
  1339. }
  1340. $adminName = '';
  1341. // Administrator name
  1342. if (!empty($name)) {
  1343. $adminName = get_lang('Manager').' : '.
  1344. Display::encrypted_mailto_link(
  1345. api_get_setting('emailAdministrator'),
  1346. $name
  1347. );
  1348. }
  1349. $this->assign('administrator_name', $adminName);
  1350. }
  1351. // Loading footer extra content
  1352. if (!api_is_platform_admin()) {
  1353. $extra_footer = trim(api_get_setting('footer_extra_content'));
  1354. if (!empty($extra_footer)) {
  1355. $this->assign('footer_extra_content', $extra_footer);
  1356. }
  1357. }
  1358. // Tutor name
  1359. if (api_get_setting('show_tutor_data') == 'true') {
  1360. // Course manager
  1361. $courseId = api_get_course_int_id();
  1362. $id_session = api_get_session_id();
  1363. if (!empty($courseId)) {
  1364. $tutor_data = '';
  1365. if ($id_session != 0) {
  1366. $coachs_email = CourseManager::get_email_of_tutor_to_session(
  1367. $id_session,
  1368. $courseId
  1369. );
  1370. $email_link = [];
  1371. foreach ($coachs_email as $coach) {
  1372. $email_link[] = Display::encrypted_mailto_link($coach['email'], $coach['complete_name']);
  1373. }
  1374. if (count($coachs_email) > 1) {
  1375. $tutor_data .= get_lang('Coachs').' : ';
  1376. $tutor_data .= array_to_string($email_link, CourseManager::USER_SEPARATOR);
  1377. } elseif (count($coachs_email) == 1) {
  1378. $tutor_data .= get_lang('Coach').' : ';
  1379. $tutor_data .= array_to_string($email_link, CourseManager::USER_SEPARATOR);
  1380. } elseif (count($coachs_email) == 0) {
  1381. $tutor_data .= '';
  1382. }
  1383. }
  1384. $this->assign('session_teachers', $tutor_data);
  1385. }
  1386. }
  1387. if (api_get_setting('show_teacher_data') == 'true') {
  1388. // course manager
  1389. $courseId = api_get_course_int_id();
  1390. if (!empty($courseId)) {
  1391. $teacher_data = '';
  1392. $mail = CourseManager::get_emails_of_tutors_to_course($courseId);
  1393. if (!empty($mail)) {
  1394. $teachers_parsed = [];
  1395. foreach ($mail as $value) {
  1396. foreach ($value as $email => $name) {
  1397. $teachers_parsed[] = Display::encrypted_mailto_link($email, $name);
  1398. }
  1399. }
  1400. $label = get_lang('Teacher');
  1401. if (count($mail) > 1) {
  1402. $label = get_lang('Teachers');
  1403. }
  1404. $teacher_data .= $label.' : '.array_to_string($teachers_parsed, CourseManager::USER_SEPARATOR);
  1405. }
  1406. $this->assign('teachers', $teacher_data);
  1407. }
  1408. }
  1409. }
  1410. /**
  1411. * Set administrator variables.
  1412. */
  1413. private function setAdministratorParams()
  1414. {
  1415. $_admin = [
  1416. 'email' => api_get_setting('emailAdministrator'),
  1417. 'surname' => api_get_setting('administratorSurname'),
  1418. 'name' => api_get_setting('administratorName'),
  1419. 'telephone' => api_get_setting('administratorTelephone'),
  1420. ];
  1421. $this->assign('_admin', $_admin);
  1422. }
  1423. /**
  1424. * Manage specific HTTP headers security.
  1425. */
  1426. private function addHTTPSecurityHeaders()
  1427. {
  1428. // Implementation of HTTP headers security, as suggested and checked
  1429. // by https://securityheaders.io/
  1430. // Enable these settings in configuration.php to use them on your site
  1431. // Strict-Transport-Security
  1432. $setting = api_get_configuration_value('security_strict_transport');
  1433. if (!empty($setting)) {
  1434. header('Strict-Transport-Security: '.$setting);
  1435. }
  1436. // Content-Security-Policy
  1437. $setting = api_get_configuration_value('security_content_policy');
  1438. if (!empty($setting)) {
  1439. header('Content-Security-Policy: '.$setting);
  1440. }
  1441. $setting = api_get_configuration_value('security_content_policy_report_only');
  1442. if (!empty($setting)) {
  1443. header('Content-Security-Policy-Report-Only: '.$setting);
  1444. }
  1445. // Public-Key-Pins
  1446. $setting = api_get_configuration_value('security_public_key_pins');
  1447. if (!empty($setting)) {
  1448. header('Public-Key-Pins: '.$setting);
  1449. }
  1450. $setting = api_get_configuration_value('security_public_key_pins_report_only');
  1451. if (!empty($setting)) {
  1452. header('Public-Key-Pins-Report-Only: '.$setting);
  1453. }
  1454. // X-Frame-Options
  1455. $setting = api_get_configuration_value('security_x_frame_options');
  1456. if (!empty($setting)) {
  1457. header('X-Frame-Options: '.$setting);
  1458. }
  1459. // X-XSS-Protection
  1460. $setting = api_get_configuration_value('security_xss_protection');
  1461. if (!empty($setting)) {
  1462. header('X-XSS-Protection: '.$setting);
  1463. }
  1464. // X-Content-Type-Options
  1465. $setting = api_get_configuration_value('security_x_content_type_options');
  1466. if (!empty($setting)) {
  1467. header('X-Content-Type-Options: '.$setting);
  1468. }
  1469. // Referrer-Policy
  1470. $setting = api_get_configuration_value('security_referrer_policy');
  1471. if (!empty($setting)) {
  1472. header('Referrer-Policy: '.$setting);
  1473. }
  1474. // end of HTTP headers security block
  1475. }
  1476. }