Completed
Push — master ( 83b625...222536 )
by Julito
11:04
created

Template::set_system_parameters()   B

Complexity

Conditions 2
Paths 2

Size

Total Lines 25
Code Lines 15

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 15
nc 2
nop 0
dl 0
loc 25
rs 8.8571
c 0
b 0
f 0
1
<?php
2
/* For licensing terms, see /license.txt */
3
4
use Chamilo\CoreBundle\Entity\SessionRelCourseRelUser;
5
use Chamilo\UserBundle\Entity\User;
6
7
/**
8
 * Class Template
9
 *
10
 * @author Julio Montoya <[email protected]>
11
 * @todo better organization of the class, methods and variables
12
 *
13
 */
14
class Template
15
{
16
    /**
17
     * The Template folder name see main/template
18
     * @var string
19
     */
20
    public $templateFolder = 'default';
21
22
    /**
23
     * The theme that will be used: chamilo, public_admin, chamilo_red, etc
24
     * This variable is set from the database
25
     * @var string
26
     */
27
    public $theme = '';
28
    private $themeDir;
29
30
    /**
31
     * @var string
32
     */
33
    public $preview_theme = '';
34
    public $title = null;
35
    public $show_header;
36
    public $show_footer;
37
    public $help;
38
    public $menu_navigation = []; //Used in the userportal.lib.php function: return_navigation_course_links()
39
    public $show_learnpath = false; // This is a learnpath section or not?
40
    public $plugin = null;
41
    public $course_id = null;
42
    public $user_is_logged_in = false;
43
    public $twig = null;
44
45
    /* Loads chamilo plugins */
46
    public $load_plugins = false;
47
    public $params = [];
48
    public $force_plugin_load = false;
49
    public $responseCode = 0;
50
51
    /**
52
     * @param string $title
53
     * @param bool $show_header
54
     * @param bool $show_footer
55
     * @param bool $show_learnpath
56
     * @param bool $hide_global_chat
57
     * @param bool $load_plugins
58
     * @param int $responseCode
59
     * @param bool $sendHeaders send http headers or not
60
     */
61
    public function __construct(
62
        $title = '',
63
        $show_header = true,
64
        $show_footer = true,
65
        $show_learnpath = false,
66
        $hide_global_chat = false,
67
        $load_plugins = true,
68
        $sendHeaders = true,
69
        $responseCode = 0
70
    ) {
71
        // Page title
72
        $this->title = $title;
73
        $this->show_learnpath = $show_learnpath;
74
        $this->setResponseCode($responseCode);
75
76
        if (empty($this->show_learnpath)) {
77
            $origin = api_get_origin();
78
            if ($origin === 'learnpath') {
79
                $this->show_learnpath = true;
80
                $show_footer = false;
81
                $show_header = false;
82
            }
83
        }
84
        $this->hide_global_chat = $hide_global_chat;
85
        $this->load_plugins = $load_plugins;
86
87
        $template_paths = [
88
            api_get_path(SYS_CODE_PATH).'template/overrides', // user defined templates
89
            api_get_path(SYS_CODE_PATH).'template', //template folder
90
            api_get_path(SYS_PLUGIN_PATH) // plugin folder
91
        ];
92
93
        $urlId = api_get_current_access_url_id();
94
95
        $cache_folder = api_get_path(SYS_ARCHIVE_PATH).'twig/'.$urlId.'/';
96
97
        if (!is_dir($cache_folder)) {
98
            mkdir($cache_folder, api_get_permissions_for_new_directories(), true);
99
        }
100
101
        $loader = new Twig_Loader_Filesystem($template_paths);
102
103
        $isTestMode = api_get_setting('server_type') === 'test';
104
105
        //Setting Twig options depending on the server see http://twig.sensiolabs.org/doc/api.html#environment-options
106
        if ($isTestMode) {
107
            $options = [
108
                //'cache' => api_get_path(SYS_ARCHIVE_PATH), //path to the cache folder
109
                'autoescape' => false,
110
                'debug' => true,
111
                'auto_reload' => true,
112
                'optimizations' => 0,
113
                // turn on optimizations with -1
114
                'strict_variables' => false,
115
                //If set to false, Twig will silently ignore invalid variables
116
            ];
117
        } else {
118
            $options = [
119
                'cache' => $cache_folder,
120
                //path to the cache folder
121
                'autoescape' => false,
122
                'debug' => false,
123
                'auto_reload' => false,
124
                'optimizations' => -1,
125
                // turn on optimizations with -1
126
                'strict_variables' => false
127
                //If set to false, Twig will silently ignore invalid variables
128
            ];
129
        }
130
131
        $this->twig = new Twig_Environment($loader, $options);
132
        //$this->twig = \Chamilo\CoreBundle\Framework\Container::getTemplating();
133
134
        if ($isTestMode) {
135
            $this->twig->addExtension(new Twig_Extension_Debug());
136
        }
137
138
        // Twig filters setup
139
        $filters = [
140
            'get_plugin_lang',
141
            'get_lang',
142
            'api_get_path',
143
            'api_get_local_time',
144
            'api_convert_and_format_date',
145
            'api_is_allowed_to_edit',
146
            'api_get_user_info',
147
            'api_get_configuration_value',
148
            'api_get_setting',
149
            [
150
                'name' => 'return_message',
151
                'callable' => 'Display::return_message_and_translate'
152
            ],
153
            [
154
                'name' => 'display_page_header',
155
                'callable' => 'Display::page_header_and_translate'
156
            ],
157
            [
158
                'name' => 'display_page_subheader',
159
                'callable' => 'Display::page_subheader_and_translate'
160
            ],
161
            [
162
                'name' => 'icon',
163
                'callable' => 'Template::get_icon_path'
164
            ],
165
            [
166
                'name' => 'img',
167
                'callable' => 'Template::get_image'
168
            ],
169
            [
170
                'name' => 'format_date',
171
                'callable' => 'Template::format_date'
172
            ]
173
        ];
174
175
        foreach ($filters as $filter) {
176
            if (is_array($filter)) {
177
                $this->twig->addFilter(new Twig_SimpleFilter($filter['name'], $filter['callable']));
178
            } else {
179
                $this->twig->addFilter(new Twig_SimpleFilter($filter, $filter));
180
            }
181
        }
182
183
        $functions = [
184
            ['name' => 'get_tutors_names', 'callable' => 'Template::returnTutorsNames'],
185
            ['name' => 'get_teachers_names', 'callable' => 'Template::returnTeachersNames']
186
        ];
187
188
        foreach ($functions as $function) {
189
            $this->twig->addFunction(new Twig_SimpleFunction($function['name'], $function['callable']));
190
        }
191
192
        // Setting system variables
193
        $this->set_system_parameters();
194
195
        // Setting user variables
196
        $this->set_user_parameters();
197
198
        // Setting course variables
199
        $this->set_course_parameters();
200
201
        // Setting administrator variables
202
        $this->setAdministratorParams();
203
        //$this->setCSSEditor();
204
205
        // Header and footer are showed by default
206
        $this->set_footer($show_footer);
207
        $this->set_header($show_header);
208
209
        $this->set_header_parameters($sendHeaders);
210
        $this->set_footer_parameters();
211
212
        $defaultStyle = api_get_configuration_value('default_template');
213
        if (!empty($defaultStyle)) {
214
            $this->templateFolder = $defaultStyle;
215
        }
216
217
        $this->assign('template', $this->templateFolder);
218
        $this->assign('locale', api_get_language_isocode());
219
        $this->assign('login_class', null);
220
221
        $allow = api_get_configuration_value('show_language_selector_in_menu');
222
        if ($allow) {
223
            $this->assign('language_form', api_display_language_form());
224
        }
225
226
        // Chamilo plugins
227
        if ($this->show_header) {
228
            if ($this->load_plugins) {
229
                $this->plugin = new AppPlugin();
230
231
                //1. Showing installed plugins in regions
232
                $pluginRegions = $this->plugin->get_plugin_regions();
233
                foreach ($pluginRegions as $region) {
234
                    $this->set_plugin_region($region);
235
                }
236
237
                //2. Loading the course plugin info
238
                global $course_plugin;
239
                if (isset($course_plugin) && !empty($course_plugin) && !empty($this->course_id)) {
240
                    //Load plugin get_langs
241
                    $this->plugin->load_plugin_lang_variables($course_plugin);
242
                }
243
            }
244
        }
245
    }
246
247
    /**
248
     * @param string $image
249
     * @param int $size
250
     *
251
     * @return string
252
     */
253
    public static function get_icon_path($image, $size = ICON_SIZE_SMALL)
254
    {
255
        return Display::return_icon($image, '', [], $size, false, true);
256
    }
257
258
    /**
259
     * @param string $image
260
     * @param int $size
261
     * @param string $name
262
     * @return string
263
     */
264
    public static function get_image($image, $size = ICON_SIZE_SMALL, $name = '')
265
    {
266
        return Display::return_icon($image, $name, [], $size);
267
    }
268
269
    /**
270
     * @param string $timestamp
271
     * @param string $format
272
     *
273
     * @return string
274
     */
275
    public static function format_date($timestamp, $format = null)
276
    {
277
        return api_format_date($timestamp, $format);
278
    }
279
280
    /**
281
     * Return the item's url key:
282
     *
283
     *      c_id=xx&id=xx
284
     *
285
     * @param object $item
286
     * @return string
287
     */
288
    public static function key($item)
289
    {
290
        $id     = isset($item->id) ? $item->id : null;
291
        $c_id   = isset($item->c_id) ? $item->c_id : null;
292
        $result = '';
293
        if ($c_id) {
294
            $result = "c_id=$c_id";
295
        }
296
        if ($id) {
297
            if ($result) {
298
                $result .= "&amp;id=$id";
299
            } else {
300
                $result .= "&amp;id=$id";
301
            }
302
        }
303
        return $result;
304
    }
305
306
    /**
307
     * @param string $helpInput
308
     */
309
    public function setHelp($helpInput = null)
310
    {
311
        if (!empty($helpInput)) {
312
            $help = $helpInput;
313
        } else {
314
            $help = $this->help;
315
        }
316
317
        $content = '';
318
        if (api_get_setting('enable_help_link') == 'true') {
319
            if (!empty($help)) {
320
                $help = Security::remove_XSS($help);
321
                $content = '<div class="help">';
322
                $content .= Display::url(
323
                    Display::return_icon('help.large.png', get_lang('Help')),
324
                    api_get_path(WEB_CODE_PATH).'help/help.php?open='.$help,
325
                    [
326
                        'class' => 'ajax',
327
                        'data-title' => get_lang('Help')
328
                    ]
329
                );
330
                $content .= '</div>';
331
            }
332
        }
333
        $this->assign('help_content', $content);
334
    }
335
336
    /**
337
     * Use template system to parse the actions menu
338
     * @todo finish it!
339
     **/
340
    public function set_actions($actions)
341
    {
342
        $action_string = '';
343
        if (!empty($actions)) {
344
            foreach ($actions as $action) {
345
                $action_string .= $action;
346
            }
347
        }
348
        $this->assign('actions', $actions);
349
    }
350
351
    /**
352
     * Shortcut to display a 1 col layout (index.php)
353
     * */
354
    public function display_one_col_template()
355
    {
356
        $tpl = $this->get_template('layout/layout_1_col.html.twig');
357
        echo \Chamilo\CoreBundle\Framework\Container::getTemplating()->render($tpl, $this->params);
358
    }
359
360
    /**
361
     * Shortcut to display a 2 col layout (userportal.php)
362
     **/
363
    public function display_two_col_template()
364
    {
365
        $tpl = $this->get_template('layout/layout_2_col.html.twig');
366
        echo \Chamilo\CoreBundle\Framework\Container::getTemplating()->render($tpl, $this->params);
367
    }
368
369
    /**
370
     * Displays an empty template
371
     */
372
    public function display_blank_template()
373
    {
374
        $tpl = $this->get_template('layout/blank.tpl');
375
        $this->display($tpl);
376
    }
377
378
    /**
379
     * Displays an empty template
380
     */
381
    public function displayBlankTemplateNoHeader()
382
    {
383
        $tpl = $this->get_template('layout/blank_no_header.tpl');
384
        $this->display($tpl);
385
    }
386
387
    /**
388
     * Displays an empty template
389
     */
390
    public function display_no_layout_template()
391
    {
392
        $tpl = $this->get_template('layout/no_layout.tpl');
393
        $this->display($tpl);
394
    }
395
396
    /**
397
     * Sets the footer visibility
398
     * @param bool true if we show the footer
399
     */
400
    public function set_footer($status)
401
    {
402
        $this->show_footer = $status;
403
        $this->assign('show_footer', $status);
404
    }
405
406
    /**
407
     * return true if toolbar has to be displayed for user
408
     * @return bool
409
     */
410
    public static function isToolBarDisplayedForUser()
411
    {
412
        //Toolbar
413
        $show_admin_toolbar = api_get_setting('show_admin_toolbar');
414
        $show_toolbar = false;
415
416
        switch ($show_admin_toolbar) {
417
            case 'do_not_show':
418
                break;
419
            case 'show_to_admin':
420
                if (api_is_platform_admin()) {
421
                    $show_toolbar = true;
422
                }
423
                break;
424
            case 'show_to_admin_and_teachers':
425
                if (api_is_platform_admin() || api_is_allowed_to_edit()) {
426
                    $show_toolbar = true;
427
                }
428
                break;
429
            case 'show_to_all':
430
                $show_toolbar = true;
431
                break;
432
        }
433
        return $show_toolbar;
434
    }
435
436
    /**
437
     * Sets the header visibility
438
     * @param bool true if we show the header
439
     */
440
    public function set_header($status)
441
    {
442
        $this->show_header = $status;
443
        $this->assign('show_header', $status);
444
445
        $show_toolbar = 0;
446
447
        if (self::isToolBarDisplayedForUser()) {
448
            $show_toolbar = 1;
449
        }
450
451
        $this->assign('show_toolbar', $show_toolbar);
452
453
        //Only if course is available
454
        $show_course_shortcut = null;
455
        $show_course_navigation_menu = null;
456
457
        if (!empty($this->course_id) && $this->user_is_logged_in) {
458
            if (api_get_setting('show_toolshortcuts') != 'false') {
459
                //Course toolbar
460
                $show_course_shortcut = CourseHome::show_navigation_tool_shortcuts();
461
            }
462
            if (api_get_setting('show_navigation_menu') != 'false') {
463
                //Course toolbar
464
                $show_course_navigation_menu = CourseHome::show_navigation_menu();
465
            }
466
        }
467
        $this->assign('show_course_shortcut', $show_course_shortcut);
468
        $this->assign('show_course_navigation_menu', $show_course_navigation_menu);
469
    }
470
471
    /**
472
     * Returns the sub-folder and filename for the given tpl file.
473
     * If template not found in overrides/ or custom template folder, the
474
     * default template will be used.
475
     * @param string $name
476
     *
477
     * @return string
478
     */
479
    public function get_template($name)
480
    {
481
        // Check if the tpl file is present in the main/template/overrides/ dir
482
        // Overrides is a special directory meant for temporary template
483
        // customization. It must be taken into account before anything else
484
        $file = api_get_path(SYS_CODE_PATH).'template/overrides/'.$name;
485
        if (is_readable($file)) {
486
            return 'overrides/'.$name;
487
        }
488
        // If a template folder has been manually defined, search for the right
489
        // file, and if not found, go for the same file in the default template
490
        if ($this->templateFolder != 'default') {
491
            // Avoid missing template error, use the default file.
492
            $file = api_get_path(SYS_CODE_PATH).'template/'.$this->templateFolder.'/'.$name;
493
            if (!file_exists($file)) {
494
                return 'default/'.$name;
495
            }
496
        }
497
498
        return $this->templateFolder.'/'.$name;
499
    }
500
501
    /**
502
     * Prepare the _c array for template files. The _c array contains
503
     * information about the current course
504
     * @return void
505
     */
506
    private function set_course_parameters()
507
    {
508
        //Setting course id
509
        $course = api_get_course_info();
510
        if (empty($course)) {
511
            $this->assign('course_is_set', false);
512
            return;
513
        }
514
        $this->assign('course_is_set', true);
515
        $this->course_id = $course['id'];
516
        $_c = [
517
            'id' => $course['real_id'],
518
            'code' => $course['code'],
519
            'title' => $course['name'],
520
            'visibility' => $course['visibility'],
521
            'language' => $course['language'],
522
            'directory' => $course['directory'],
523
            'session_id' => api_get_session_id(),
524
            'user_is_teacher' => api_is_course_admin(),
525
            'student_view' => (!empty($_GET['isStudentView']) && $_GET['isStudentView'] == 'true'),
526
        ];
527
        $this->assign('course_code', $course['code']);
528
        $this->assign('_c', $_c);
529
    }
530
531
    /**
532
     * Prepare the _u array for template files. The _u array contains
533
     * information about the current user, as returned by
534
     * api_get_user_info()
535
     * @return void
536
     */
537
    private function set_user_parameters()
538
    {
539
        $user_info = [];
540
        $user_info['logged'] = 0;
541
        $this->user_is_logged_in = false;
542
        if (api_user_is_login()) {
543
            $user_info = api_get_user_info(api_get_user_id(), true);
544
            $user_info['logged'] = 1;
545
546
            $user_info['is_admin'] = 0;
547
            if (api_is_platform_admin()) {
548
                $user_info['is_admin'] = 1;
549
            }
550
551
            $user_info['messages_count'] = MessageManager::getCountNewMessages();
552
            $this->user_is_logged_in = true;
553
        }
554
        // Setting the $_u array that could be use in any template
555
        $this->assign('_u', $user_info);
556
    }
557
558
    /**
559
     * Get CSS themes sub-directory
560
     * @param string $theme
561
     * @return string with a trailing slash, e.g. 'themes/chamilo_red/'
562
     */
563
    public static function getThemeDir($theme)
564
    {
565
        $themeDir = 'themes/'.$theme.'/';
566
        $virtualTheme = api_get_configuration_value('virtual_css_theme_folder');
567
        if (!empty($virtualTheme)) {
568
            $virtualThemeList = api_get_themes(true);
569
            $isVirtualTheme = in_array($theme, array_keys($virtualThemeList));
570
            if ($isVirtualTheme) {
571
                $themeDir = 'themes/'.$virtualTheme.'/'.$theme.'/';
572
            }
573
        }
574
575
        return $themeDir;
576
    }
577
578
    /**
579
     * Get an array of all the web paths available (e.g. 'web' => 'https://my.chamilo.site/')
580
     * @return array
581
     */
582
    private function getWebPaths()
583
    {
584
        return [
585
            'web' => api_get_path(WEB_PATH),
586
            'web_url' => api_get_web_url(),
587
            'web_relative' => api_get_path(REL_PATH),
588
            'web_course' => api_get_path(WEB_COURSE_PATH),
589
            'web_main' => api_get_path(WEB_CODE_PATH),
590
            'web_css' => api_get_path(WEB_CSS_PATH),
591
            'web_css_theme' => api_get_path(WEB_CSS_PATH).$this->themeDir,
592
            'web_ajax' => api_get_path(WEB_AJAX_PATH),
593
            'web_img' => api_get_path(WEB_IMG_PATH),
594
            'web_plugin' => api_get_path(WEB_PLUGIN_PATH),
595
            'web_lib' => api_get_path(WEB_LIBRARY_PATH),
596
            'web_upload' => api_get_path(WEB_UPLOAD_PATH),
597
            'web_self' => api_get_self(),
598
            'web_query_vars' => api_htmlentities($_SERVER['QUERY_STRING']),
599
            'web_self_query_vars' => api_htmlentities($_SERVER['REQUEST_URI']),
600
            'web_cid_query' => api_get_cidreq(),
601
        ];
602
    }
603
604
    /**
605
     * Set system parameters from api_get_configuration into _s array for use in TPLs
606
     * Also fills the _p array from getWebPaths()
607
     * @uses self::getWebPaths()
608
     */
609
    public function set_system_parameters()
610
    {
611
        $this->theme = api_get_visual_theme();
612
        if (!empty($this->preview_theme)) {
613
            $this->theme = $this->preview_theme;
614
        }
615
616
        $this->assign('theme', $this->theme);
617
618
        $this->themeDir = self::getThemeDir($this->theme);
619
620
        // Setting app paths/URLs
621
        $this->assign('_p', $this->getWebPaths());
622
623
        // Here we can add system parameters that can be use in any template
624
        $_s = [
625
            'software_name' => api_get_configuration_value('software_name'),
626
            'system_version' => api_get_configuration_value('system_version'),
627
            'site_name' => api_get_setting('siteName'),
628
            'institution' => api_get_setting('Institution'),
629
            'date' => api_format_date('now', DATE_FORMAT_LONG),
630
            'timezone' => api_get_timezone(),
631
            'gamification_mode' => api_get_setting('gamification_mode')
632
        ];
633
        $this->assign('_s', $_s);
634
    }
635
636
    /**
637
     * Set legacy twig globals in order to be hook in the LegacyListener.php
638
     * @return array
639
     */
640
    public static function getGlobals()
641
    {
642
        $_p = [
643
            'web' => api_get_path(WEB_PATH),
644
            'web_relative' => api_get_path(REL_PATH),
645
            'web_course' => api_get_path(WEB_COURSE_PATH),
646
            'web_main' => api_get_path(WEB_CODE_PATH),
647
            'web_css' => api_get_path(WEB_CSS_PATH),
648
            //'web_css_theme' => api_get_path(WEB_CSS_PATH) . 'themes/' . $this->theme . '/',
649
            'web_ajax' => api_get_path(WEB_AJAX_PATH),
650
            'web_img' => api_get_path(WEB_IMG_PATH),
651
            'web_plugin' => api_get_path(WEB_PLUGIN_PATH),
652
            'web_plugin_asset' => api_get_path(WEB_PLUGIN_ASSET_PATH),
653
            'web_lib' => api_get_path(WEB_LIBRARY_PATH),
654
            'web_upload' => api_get_path(WEB_UPLOAD_PATH),
655
            'web_self' => api_get_self(),
656
            'web_query_vars' => api_htmlentities($_SERVER['QUERY_STRING']),
657
            'web_self_query_vars' => api_htmlentities($_SERVER['REQUEST_URI']),
658
            'web_cid_query' => api_get_cidreq(),
659
        ];
660
661
        $_s = [
662
            'software_name' => api_get_configuration_value('software_name'),
663
            'system_version' => api_get_configuration_value('system_version'),
664
            'site_name' => api_get_setting('siteName'),
665
            'institution' => api_get_setting('Institution'),
666
            'date' => api_format_date('now', DATE_FORMAT_LONG),
667
            'timezone' => api_get_timezone(),
668
            'gamification_mode' => api_get_setting('gamification_mode')
669
        ];
670
671
        //$user_info = api_get_user_info();
672
673
        return [
674
            '_p' => $_p,
675
            '_s' => $_s,
676
            //       '_u' => $user_info,
677
            'template' => 'default' // @todo setup template folder in config.yml;
678
        ];
679
    }
680
681
    /**
682
     * Set theme, include mainstream CSS files
683
     * @return void
684
     * @see setCssCustomFiles() for additional CSS sheets
685
     */
686
    public function setCssFiles()
687
    {
688
        global $disable_js_and_css_files;
689
        $css = [];
690
691
        // Default CSS Bootstrap
692
        $bowerCSSFiles = [
693
            'fontawesome/css/font-awesome.min.css',
694
            'jquery-ui/themes/smoothness/theme.css',
695
            'jquery-ui/themes/smoothness/jquery-ui.min.css',
696
            'mediaelement/build/mediaelementplayer.min.css',
697
            'jqueryui-timepicker-addon/dist/jquery-ui-timepicker-addon.min.css',
698
            'bootstrap/dist/css/bootstrap.min.css',
699
            'jquery.scrollbar/jquery.scrollbar.css',
700
            'bootstrap-daterangepicker/daterangepicker.css',
701
            'bootstrap-select/dist/css/bootstrap-select.min.css',
702
            'select2/dist/css/select2.min.css',
703
            'flag-icon-css/css/flag-icon.min.css'
704
        ];
705
706
        foreach ($bowerCSSFiles as $file) {
0 ignored issues
show
Unused Code introduced by
This foreach statement is empty and can be removed.

This check looks for foreach loops that have no statements or where all statements have been commented out. This may be the result of changes for debugging or the code may simply be obsolete.

Consider removing the loop.

Loading history...
707
            //$css[] = api_get_path(WEB_PUBLIC_PATH).'assets/'.$file;
708
        }
709
710
        //$css[] = api_get_path(WEB_LIBRARY_PATH).'javascript/chosen/chosen.css';
711
712
        if (api_is_global_chat_enabled()) {
713
            $css[] = api_get_path(WEB_LIBRARY_PATH).'javascript/chat/css/chat.css';
714
        }
715
        $css_file_to_string = '';
716
        foreach ($css as $file) {
717
            $css_file_to_string .= api_get_css($file);
718
        }
719
720
        if (!$disable_js_and_css_files) {
721
            $this->assign('css_static_file_to_string', $css_file_to_string);
722
        }
723
    }
724
725
    /**
726
     *
727
     */
728
    public function setCSSEditor()
729
    {
730
        $cssEditor = api_get_cdn_path(api_get_path(WEB_CSS_PATH).'editor.css');
731
        if (is_file(api_get_path(SYS_CSS_PATH).$this->themeDir.'editor.css')) {
732
            $cssEditor = api_get_path(WEB_CSS_PATH).$this->themeDir.'editor.css';
733
        }
734
735
        $this->assign('cssEditor', $cssEditor);
736
    }
737
738
    /**
739
     * Prepare custom CSS to be added at the very end of the <head> section
740
     * @return void
741
     * @see setCssFiles() for the mainstream CSS files
742
     */
743
    public function setCssCustomFiles()
744
    {
745
        global $disable_js_and_css_files;
746
        // chamilo CSS
747
        $css[] = api_get_cdn_path(api_get_path(WEB_CSS_PATH).'../chamilo.css');
748
749
        // Base CSS
750
        $css[] = api_get_cdn_path(api_get_path(WEB_CSS_PATH).'base.css');
751
752
        if ($this->show_learnpath) {
753
            $css[] = api_get_cdn_path(api_get_path(WEB_CSS_PATH).'scorm.css');
754
            if (is_file(api_get_path(SYS_CSS_PATH).$this->themeDir.'learnpath.css')) {
755
                $css[] = api_get_path(WEB_CSS_PATH).$this->themeDir.'learnpath.css';
756
            }
757
        }
758
759
        $css[] = api_get_cdn_path(api_get_path(WEB_CSS_PATH).$this->themeDir.'default.css');
760
761
        $css_file_to_string = null;
762
        foreach ($css as $file) {
0 ignored issues
show
Unused Code introduced by
This foreach statement is empty and can be removed.

This check looks for foreach loops that have no statements or where all statements have been commented out. This may be the result of changes for debugging or the code may simply be obsolete.

Consider removing the loop.

Loading history...
763
           // $css_file_to_string .= api_get_css($file);
764
        }
765
766
        // @todo move this somewhere else. Special fix when using tablets in order to see the text near icons
767
        if (SHOW_TEXT_NEAR_ICONS == true) {
768
            //hack in order to fix the actions buttons
769
            $css_file_to_string .= '<style>
770
                .td_actions a {
771
                    float:left;
772
                    width:100%;
773
                }
774
                .forum_message_left a {
775
                    float:left;
776
                    width:100%;
777
                }
778
                </style>';
779
        }
780
781
        $navigator_info = api_get_navigator();
782
        if ($navigator_info['name'] == 'Internet Explorer' && $navigator_info['version'] == '6') {
783
            $css_file_to_string .= 'img, div { behavior: url('.api_get_path(WEB_LIBRARY_PATH).'javascript/iepngfix/iepngfix.htc) } '."\n";
784
        }
785
786
        if (!$disable_js_and_css_files) {
787
            $this->assign('css_custom_file_to_string', $css_file_to_string);
788
789
            $style_print = '';
790
            if (is_readable(api_get_path(SYS_CSS_PATH).$this->theme.'/print.css')) {
791
                $style_print = api_get_css(
792
                    api_get_cdn_path(api_get_path(WEB_CSS_PATH).$this->theme.'/print.css'),
793
                    'print'
794
                );
795
            }
796
            $this->assign('css_style_print', $style_print);
797
        }
798
799
        // Logo
800
        $logo = return_logo($this->theme);
801
        $this->assign('logo', $logo);
802
        $this->assign('show_media_element', 1);
803
    }
804
805
    /**
806
     * Declare and define the template variable that will be used to load
807
     * javascript libraries in the header.
808
     */
809
    public function set_js_files()
810
    {
811
        global $disable_js_and_css_files, $htmlHeadXtra;
812
        $isoCode = api_get_language_isocode();
813
        $selectLink = 'bootstrap-select/dist/js/i18n/defaults-'.$isoCode.'_'.strtoupper($isoCode).'.min.js';
814
815
        if ($isoCode == 'en') {
816
            $selectLink = 'bootstrap-select/dist/js/i18n/defaults-'.$isoCode.'_US.min.js';
817
        }
818
        // JS files
819
        $js_files = [
820
            'chosen/chosen.jquery.min.js'
821
        ];
822
823
        $viewBySession = api_get_setting('my_courses_view_by_session') === 'true';
824
825
        if (api_is_global_chat_enabled() || $viewBySession) {
826
            // Do not include the global chat in LP
827
            if ($this->show_learnpath == false &&
828
                $this->show_footer == true &&
829
                $this->hide_global_chat == false
830
            ) {
831
                $js_files[] = 'chat/js/chat.js';
832
            }
833
        }
834
835
        if (api_get_setting('accessibility_font_resize') == 'true') {
836
            $js_files[] = 'fontresize.js';
837
        }
838
839
        $js_file_to_string = '';
840
        $bowerJsFiles = [
841
            'modernizr/modernizr.js',
842
            'jquery/dist/jquery.min.js',
843
            'bootstrap/dist/js/bootstrap.min.js',
844
            'jquery-ui/jquery-ui.min.js',
845
            'moment/min/moment-with-locales.js',
846
            'bootstrap-daterangepicker/daterangepicker.js',
847
            'jquery-timeago/jquery.timeago.js',
848
            'mediaelement/build/mediaelement-and-player.min.js',
849
            'jqueryui-timepicker-addon/dist/jquery-ui-timepicker-addon.min.js',
850
            'image-map-resizer/js/imageMapResizer.min.js',
851
            'jquery.scrollbar/jquery.scrollbar.min.js',
852
            'readmore-js/readmore.min.js',
853
            'bootstrap-select/dist/js/bootstrap-select.min.js',
854
            $selectLink,
855
            'select2/dist/js/select2.min.js',
856
            "select2/dist/js/i18n/$isoCode.js"
857
        ];
858
        if (CHAMILO_LOAD_WYSIWYG == true) {
859
            $bowerJsFiles[] = 'ckeditor/ckeditor.js';
860
        }
861
862
        if (api_get_setting('include_asciimathml_script') == 'true') {
863
            $bowerJsFiles[] = 'MathJax/MathJax.js?config=TeX-MML-AM_HTMLorMML';
864
        }
865
866
        if ($isoCode != 'en') {
867
            $bowerJsFiles[] = 'jqueryui-timepicker-addon/dist/i18n/jquery-ui-timepicker-'.$isoCode.'.js';
868
            $bowerJsFiles[] = 'jquery-ui/ui/minified/i18n/datepicker-'.$isoCode.'.min.js';
869
        }
870
871
        foreach ($bowerJsFiles as $file) {
0 ignored issues
show
Unused Code introduced by
This foreach statement is empty and can be removed.

This check looks for foreach loops that have no statements or where all statements have been commented out. This may be the result of changes for debugging or the code may simply be obsolete.

Consider removing the loop.

Loading history...
872
            //$js_file_to_string .= '<script type="text/javascript" src="'.api_get_path(WEB_PUBLIC_PATH).'assets/'.$file.'"></script>'."\n";
873
        }
874
875
        /*$js_file_to_string .= '<script type="text/javascript" src="'.api_get_path(WEB_PUBLIC_PATH).'build/chamilo.js"></script>'."\n";
876
        $js_file_to_string .= '<script type="text/javascript" src="'.api_get_path(WEB_PUBLIC_PATH).'libs/ckeditor/ckeditor.js"></script>'."\n";
877
        $js_file_to_string .= '<script type="text/javascript" src="'.api_get_path(WEB_PUBLIC_PATH).'libs/readmore-js/readmore.js"></script>'."\n";
878
        */
879
880
        foreach ($js_files as $file) {
0 ignored issues
show
Unused Code introduced by
This foreach statement is empty and can be removed.

This check looks for foreach loops that have no statements or where all statements have been commented out. This may be the result of changes for debugging or the code may simply be obsolete.

Consider removing the loop.

Loading history...
881
            //$js_file_to_string .= api_get_js($file);
882
        }
883
884
        // Loading email_editor js
885
        if (!api_is_anonymous() && api_get_setting('allow_email_editor') == 'true') {
886
            $template = $this->get_template('mail_editor/email_link.js.tpl');
887
            $js_file_to_string .= $this->fetch($template);
888
        }
889
890
        if (!$disable_js_and_css_files) {
891
            $this->assign('js_file_to_string', $js_file_to_string);
892
893
            $extra_headers = '<script>var _p = '.json_encode($this->getWebPaths(), JSON_PRETTY_PRINT).'</script>';
894
            //Adding jquery ui by default
895
            $extra_headers .= api_get_jquery_ui_js();
896
897
            //$extra_headers = '';
898
            if (isset($htmlHeadXtra) && $htmlHeadXtra) {
899
                foreach ($htmlHeadXtra as & $this_html_head) {
900
                    $extra_headers .= $this_html_head."\n";
901
                }
902
            }
903
            $this->assign('extra_headers', $extra_headers);
904
        }
905
    }
906
907
    /**
908
     * Special function to declare last-minute JS libraries which depend on
909
     * other things to be declared first. In particular, it might be useful
910
     * under IE9 with compatibility mode, which for some reason is getting
911
     * upset when a variable is used in a function (even if not used yet)
912
     * when this variable hasn't been defined yet.
913
     */
914
    public function set_js_files_post()
915
    {
916
        global $disable_js_and_css_files;
917
        $js_files = [];
918
        if (api_is_global_chat_enabled()) {
919
            //Do not include the global chat in LP
920
            if ($this->show_learnpath == false && $this->show_footer == true && $this->hide_global_chat == false) {
921
                $js_files[] = 'chat/js/chat.js';
922
            }
923
        }
924
        $js_file_to_string = null;
925
926
        foreach ($js_files as $js_file) {
927
            $js_file_to_string .= api_get_js($js_file);
928
        }
929
        if (!$disable_js_and_css_files) {
930
            $this->assign('js_file_to_string_post', $js_file_to_string);
931
        }
932
    }
933
934
    /**
935
     * Set header parameters
936
     * @param bool $sendHeaders send headers
937
     */
938
    private function set_header_parameters($sendHeaders)
939
    {
940
        global $httpHeadXtra, $interbreadcrumb, $language_file, $_configuration, $this_section;
941
        $_course = api_get_course_info();
942
        $nameTools = $this->title;
943
        $navigation = return_navigation_array();
944
        $this->menu_navigation = $navigation['menu_navigation'];
945
946
        $this->assign('system_charset', api_get_system_encoding());
947
948
        if (isset($httpHeadXtra) && $httpHeadXtra) {
949
            foreach ($httpHeadXtra as & $thisHttpHead) {
950
                header($thisHttpHead);
951
            }
952
        }
953
954
        $this->assign(
955
            'online_button',
956
            Display::return_icon('statusonline.png', null, [], ICON_SIZE_ATOM)
957
        );
958
        $this->assign(
959
            'offline_button',
960
            Display::return_icon('statusoffline.png', null, [], ICON_SIZE_ATOM)
961
        );
962
963
        // Get language iso-code for this page - ignore errors
964
        $this->assign('document_language', api_get_language_isocode());
965
966
        $course_title = isset($_course['name']) ? $_course['name'] : null;
967
968
        $title_list = [];
969
970
        $title_list[] = api_get_setting('Institution');
971
        $title_list[] = api_get_setting('siteName');
972
973
        if (!empty($course_title)) {
974
            $title_list[] = $course_title;
975
        }
976
        if ($nameTools != '') {
977
            $title_list[] = $nameTools;
978
        }
979
980
        $title_string = '';
981
        for ($i = 0; $i < count($title_list); $i++) {
0 ignored issues
show
Performance Best Practice introduced by
It seems like you are calling the size function count() as part of the test condition. You might want to compute the size beforehand, and not on each iteration.

If the size of the collection does not change during the iteration, it is generally a good practice to compute it beforehand, and not on each iteration:

for ($i=0; $i<count($array); $i++) { // calls count() on each iteration
}

// Better
for ($i=0, $c=count($array); $i<$c; $i++) { // calls count() just once
}
Loading history...
982
            $title_string .= $title_list[$i];
983
            if (isset($title_list[$i + 1])) {
984
                $item = trim($title_list[$i + 1]);
985
                if (!empty($item)) {
986
                    $title_string .= ' - ';
987
                }
988
            }
989
        }
990
991
        $this->assign('title_string', $title_string);
992
993
        // Setting the theme and CSS files
994
        $this->setCssFiles();
995
        $this->set_js_files();
996
        $this->setCssCustomFiles();
997
998
        $browser = api_browser_support('check_browser');
999
        if ($browser[0] == 'Internet Explorer' && $browser[1] >= '11') {
1000
            $browser_head = '<meta http-equiv="X-UA-Compatible" content="IE=EmulateIE9" />';
1001
            $this->assign('browser_specific_head', $browser_head);
1002
        }
1003
1004
        // Implementation of prefetch.
1005
        // See http://cdn.chamilo.org/main/img/online.png for details
1006
        $prefetch = '';
1007
        if (!empty($_configuration['cdn_enable'])) {
1008
            $prefetch .= '<meta http-equiv="x-dns-prefetch-control" content="on">';
1009
            foreach ($_configuration['cdn'] as $host => $exts) {
1010
                $prefetch .= '<link rel="dns-prefetch" href="'.$host.'">';
1011
            }
1012
        }
1013
1014
        $this->assign('prefetch', $prefetch);
1015
        $this->assign('text_direction', api_get_text_direction());
1016
        $this->assign('section_name', 'section-'.$this_section);
1017
1018
        // Default root chamilo favicon
1019
        $favico = '<link rel="shortcut icon" href="'.api_get_path(WEB_PATH).'favicon.ico" type="image/x-icon" />';
1020
1021
        //Added to verify if in the current Chamilo Theme exist a favicon
1022
        $favicoThemeUrl = api_get_path(SYS_CSS_PATH).$this->themeDir.'images/';
1023
1024
        //If exist pick the current chamilo theme favicon
1025
        if (is_file($favicoThemeUrl.'favicon.ico')) {
1026
            $favico = '<link rel="shortcut icon" href="'.api_get_path(WEB_CSS_PATH).$this->themeDir.'images/favicon.ico" type="image/x-icon" />';
1027
        }
1028
1029
        if (api_is_multiple_url_enabled()) {
1030
            $access_url_id = api_get_current_access_url_id();
1031
            if ($access_url_id != -1) {
1032
                $url_info = api_get_access_url($access_url_id);
1033
                $url = api_remove_trailing_slash(
1034
                    preg_replace('/https?:\/\//i', '', $url_info['url'])
1035
                );
1036
                $clean_url = api_replace_dangerous_char($url);
1037
                $clean_url = str_replace('/', '-', $clean_url);
1038
                $clean_url .= '/';
1039
                $homep = api_get_path(REL_PATH).'home/'.$clean_url; //homep for Home Path
1040
                $icon_real_homep = api_get_path(SYS_APP_PATH).'home/'.$clean_url;
1041
                //we create the new dir for the new sites
1042
                if (is_file($icon_real_homep.'favicon.ico')) {
1043
                    $favico = '<link rel="shortcut icon" href="'.$homep.'favicon.ico" type="image/x-icon" />';
1044
                }
1045
            }
1046
        }
1047
1048
        $this->assign('favico', $favico);
1049
        $this->setHelp();
1050
1051
        //@todo move this in the template
1052
        $rightFloatMenu = '';
1053
        $iconBug = Display::return_icon(
1054
            'bug.png',
1055
            get_lang('ReportABug'),
1056
            [],
1057
            ICON_SIZE_LARGE
1058
        );
1059
        if (api_get_setting('show_link_bug_notification') == 'true' && $this->user_is_logged_in) {
1060
            $rightFloatMenu = '<div class="report">
1061
		        <a href="https://github.com/chamilo/chamilo-lms/wiki/How-to-report-issues" target="_blank">
1062
                    '.$iconBug.'
1063
                </a>
1064
		        </div>';
1065
        }
1066
1067
        if (api_get_setting('show_link_ticket_notification') == 'true' && $this->user_is_logged_in) {
1068
            // by default is project_id = 1
1069
            $iconTicket = Display::return_icon(
1070
                'help.png',
1071
                get_lang('Ticket'),
1072
                [],
1073
                ICON_SIZE_LARGE
1074
            );
1075
            $courseInfo = api_get_course_info();
1076
            $courseParams = '';
1077
            if (!empty($courseInfo)) {
1078
                $courseParams = api_get_cidreq();
1079
            }
1080
            $url = api_get_path(WEB_CODE_PATH).'ticket/tickets.php?project_id=1&'.$courseParams;
1081
            $rightFloatMenu .= '<div class="help">
1082
		        <a href="'.$url.'" target="_blank">
1083
                    '.$iconTicket.'
1084
                </a>
1085
		    </div>';
1086
        }
1087
1088
        $this->assign('bug_notification', $rightFloatMenu);
1089
1090
        $resize = '';
1091
        if (api_get_setting('accessibility_font_resize') == 'true') {
1092
            $resize .= '<div class="resize_font">';
1093
            $resize .= '<div class="btn-group">';
1094
            $resize .= '<a title="'.get_lang('DecreaseFontSize').'" href="#" class="decrease_font btn btn-default"><em class="fa fa-font"></em></a>';
1095
            $resize .= '<a title="'.get_lang('ResetFontSize').'" href="#" class="reset_font btn btn-default"><em class="fa fa-font"></em></a>';
1096
            $resize .= '<a title="'.get_lang('IncreaseFontSize').'" href="#" class="increase_font btn btn-default"><em class="fa fa-font"></em></a>';
1097
            $resize .= '</div>';
1098
            $resize .= '</div>';
1099
        }
1100
        $this->assign('accessibility', $resize);
1101
1102
        // Preparing values for the menu
1103
1104
        // Logout link
1105
        $hideLogout = api_get_setting('hide_logout_button');
1106
        if ($hideLogout === 'true') {
1107
            $this->assign('logout_link', null);
1108
        } else {
1109
            $this->assign('logout_link', api_get_path(WEB_PATH).'index.php?logout=logout&uid='.api_get_user_id());
1110
        }
1111
1112
        // Profile link
1113
        if (api_get_setting('allow_social_tool') == 'true') {
1114
            $profile_url = api_get_path(WEB_CODE_PATH).'social/home.php';
1115
        } else {
1116
            $profile_url = api_get_path(WEB_CODE_PATH).'auth/profile.php';
1117
        }
1118
1119
        $this->assign('profile_url', $profile_url);
1120
1121
        //Message link
1122
        $message_link = null;
1123
        $message_url = null;
1124
        if (api_get_setting('allow_message_tool') == 'true') {
1125
            $message_url = api_get_path(WEB_CODE_PATH).'messages/inbox.php';
1126
            $message_link = '<a href="'.api_get_path(WEB_CODE_PATH).'messages/inbox.php">'.get_lang('Inbox').'</a>';
1127
        }
1128
        $this->assign('message_link', $message_link);
1129
        $this->assign('message_url', $message_url);
1130
1131
        // Certificate Link
1132
1133
        $allow = api_get_configuration_value('hide_my_certificate_link');
1134
        if ($allow === false) {
1135
            $certificateUrl = api_get_path(WEB_CODE_PATH).'gradebook/my_certificates.php';
1136
            $certificateLink = Display::url(
1137
                get_lang('MyCertificates'),
1138
                $certificateUrl
1139
            );
1140
            $this->assign('certificate_link', $certificateLink);
1141
            $this->assign('certificate_url', $certificateUrl);
1142
        }
1143
1144
        $institution = api_get_setting('Institution');
1145
        $portal_name = empty($institution) ? api_get_setting('siteName') : $institution;
1146
1147
        $this->assign('portal_name', $portal_name);
1148
1149
        //Menu
1150
        $menu = menuArray();
1151
        $this->assign('menu', $menu);
1152
1153
        $breadcrumb = '';
1154
        // Hide breadcrumb in LP
1155
        if ($this->show_learnpath == false) {
1156
            $breadcrumb = return_breadcrumb(
1157
                $interbreadcrumb,
1158
                $language_file,
1159
                $nameTools
1160
            );
1161
        }
1162
        $this->assign('breadcrumb', $breadcrumb);
1163
1164
        //Extra content
1165
        $extra_header = null;
1166
        if (!api_is_platform_admin()) {
1167
            $extra_header = trim(api_get_setting('header_extra_content'));
1168
        }
1169
        $this->assign('header_extra_content', $extra_header);
1170
1171
        if ($sendHeaders) {
1172
            header('Content-Type: text/html; charset='.api_get_system_encoding());
1173
            header(
1174
                'X-Powered-By: '.$_configuration['software_name'].' '.substr($_configuration['system_version'], 0, 1)
1175
            );
1176
            self::addHTTPSecurityHeaders();
1177
1178
            $responseCode = $this->getResponseCode();
1179
            if (!empty($responseCode)) {
1180
                switch ($responseCode) {
1181
                    case '404':
1182
                        header("HTTP/1.0 404 Not Found");
1183
                        break;
1184
                }
1185
            }
1186
        }
1187
1188
        $socialMeta = '';
1189
        $metaTitle = api_get_setting('meta_title');
1190
        if (!empty($metaTitle)) {
1191
            $socialMeta .= '<meta name="twitter:card" content="summary" />'."\n";
1192
            $metaSite = api_get_setting('meta_twitter_site');
1193
            if (!empty($metaSite)) {
1194
                $socialMeta .= '<meta name="twitter:site" content="'.$metaSite.'" />'."\n";
1195
                $metaCreator = api_get_setting('meta_twitter_creator');
1196
                if (!empty($metaCreator)) {
1197
                    $socialMeta .= '<meta name="twitter:creator" content="'.$metaCreator.'" />'."\n";
1198
                }
1199
            }
1200
1201
            // The user badge page emits its own meta tags, so if this is
1202
            // enabled, ignore the global ones
1203
            $userId = isset($_GET['user']) ? intval($_GET['user']) : 0;
1204
            $skillId = isset($_GET['skill']) ? intval($_GET['skill']) : 0;
1205
1206
            if (!$userId && !$skillId) {
1207
                // no combination of user and skill ID has been defined,
1208
                // so print the normal OpenGraph meta tags
1209
                $socialMeta .= '<meta property="og:title" content="'.$metaTitle.'" />'."\n";
1210
                $socialMeta .= '<meta property="og:url" content="'.api_get_path(WEB_PATH).'" />'."\n";
1211
1212
                $metaDescription = api_get_setting('meta_description');
1213
                if (!empty($metaDescription)) {
1214
                    $socialMeta .= '<meta property="og:description" content="'.$metaDescription.'" />'."\n";
1215
                }
1216
1217
                $metaImage = api_get_setting('meta_image_path');
1218
                if (!empty($metaImage)) {
1219
                    if (is_file(api_get_path(SYS_PATH).$metaImage)) {
1220
                        $path = api_get_path(WEB_PATH).$metaImage;
1221
                        $socialMeta .= '<meta property="og:image" content="'.$path.'" />'."\n";
1222
                    }
1223
                }
1224
            }
1225
        }
1226
1227
        $this->assign('social_meta', $socialMeta);
1228
    }
1229
1230
    /**
1231
     * Set footer parameters
1232
     */
1233
    private function set_footer_parameters()
1234
    {
1235
        if (api_get_setting('show_administrator_data') === 'true') {
1236
            $firstName = api_get_setting('administratorName');
1237
            $lastName = api_get_setting('administratorSurname');
1238
1239
            if (!empty($firstName) && !empty($lastName)) {
1240
                $name = api_get_person_name($firstName, $lastName);
1241
            } else {
1242
                $name = $lastName;
1243
                if (empty($lastName)) {
1244
                    $name = $firstName;
1245
                }
1246
            }
1247
1248
            $adminName = '';
1249
            // Administrator name
1250
            if (!empty($name)) {
1251
                $adminName = get_lang('Manager').' : '.
1252
                    Display::encrypted_mailto_link(
1253
                        api_get_setting('emailAdministrator'),
1254
                        $name
1255
                    );
1256
            }
1257
            $this->assign('administrator_name', $adminName);
1258
        }
1259
1260
        // Loading footer extra content
1261
        if (!api_is_platform_admin()) {
1262
            $extra_footer = trim(api_get_setting('footer_extra_content'));
1263
            if (!empty($extra_footer)) {
1264
                $this->assign('footer_extra_content', $extra_footer);
1265
            }
1266
        }
1267
1268
        // Tutor name
1269
        if (api_get_setting('show_tutor_data') == 'true') {
1270
            // Course manager
1271
            $courseId = api_get_course_int_id();
1272
            $id_session = api_get_session_id();
1273
            if (!empty($courseId)) {
1274
                $tutor_data = '';
1275
                if ($id_session != 0) {
1276
                    $coachs_email = CourseManager::get_email_of_tutor_to_session(
1277
                        $id_session,
1278
                        $courseId
1279
                    );
1280
                    $email_link = [];
1281
                    foreach ($coachs_email as $coach) {
1282
                        $email_link[] = Display::encrypted_mailto_link($coach['email'], $coach['complete_name']);
1283
                    }
1284
                    if (count($coachs_email) > 1) {
1285
                        $tutor_data .= get_lang('Coachs').' : ';
1286
                        $tutor_data .= array_to_string($email_link, CourseManager::USER_SEPARATOR);
1287
                    } elseif (count($coachs_email) == 1) {
1288
                        $tutor_data .= get_lang('Coach').' : ';
1289
                        $tutor_data .= array_to_string($email_link, CourseManager::USER_SEPARATOR);
1290
                    } elseif (count($coachs_email) == 0) {
1291
                        $tutor_data .= '';
1292
                    }
1293
                }
1294
                $this->assign('session_teachers', $tutor_data);
1295
            }
1296
        }
1297
1298
        if (api_get_setting('show_teacher_data') == 'true') {
1299
            // course manager
1300
            $courseId = api_get_course_int_id();
1301
            if (!empty($courseId)) {
1302
                $teacher_data = '';
1303
                $mail = CourseManager::get_emails_of_tutors_to_course($courseId);
1304
                if (!empty($mail)) {
1305
                    $teachers_parsed = [];
1306
                    foreach ($mail as $value) {
1307
                        foreach ($value as $email => $name) {
1308
                            $teachers_parsed[] = Display::encrypted_mailto_link($email, $name);
1309
                        }
1310
                    }
1311
                    $label = get_lang('Teacher');
1312
                    if (count($mail) > 1) {
1313
                        $label = get_lang('Teachers');
1314
                    }
1315
                    $teacher_data .= $label.' : '.array_to_string($teachers_parsed, CourseManager::USER_SEPARATOR);
1316
                }
1317
                $this->assign('teachers', $teacher_data);
1318
            }
1319
        }
1320
    }
1321
1322
    /**
1323
     * Show header template.
1324
     */
1325
    public function show_header_template()
1326
    {
1327
        $tpl = $this->get_template('layout/show_header.tpl');
1328
        $this->display($tpl);
1329
    }
1330
1331
    /**
1332
     * Show footer template.
1333
     */
1334
    public function show_footer_template()
1335
    {
1336
        $tpl = $this->get_template('layout/show_footer.tpl');
1337
        $this->display($tpl);
1338
    }
1339
1340
    /**
1341
     * Show footer js template.
1342
     */
1343
    public function show_footer_js_template()
1344
    {
1345
        $tpl = $this->get_template('layout/footer.js.tpl');
1346
        $this->display($tpl);
1347
    }
1348
1349
    /**
1350
     * Sets the plugin content in a template variable
1351
     * @param string $pluginRegion
1352
     * @return null
1353
     */
1354
    public function set_plugin_region($pluginRegion)
1355
    {
1356
        if (!empty($pluginRegion)) {
1357
            $regionContent = $this->plugin->load_region(
1358
                $pluginRegion,
1359
                $this,
1360
                $this->force_plugin_load
1361
            );
1362
1363
            $pluginList = $this->plugin->get_installed_plugins();
1364
            foreach ($pluginList as $plugin_name) {
1365
                // The plugin_info variable is available inside the plugin index
1366
                $pluginInfo = $this->plugin->getPluginInfo($plugin_name);
1367
1368
                if (isset($pluginInfo['is_course_plugin']) && $pluginInfo['is_course_plugin']) {
1369
                    $courseInfo = api_get_course_info();
1370
                    if (!empty($courseInfo)) {
1371
                        if (isset($pluginInfo['obj']) && $pluginInfo['obj'] instanceof Plugin) {
1372
                            /** @var Plugin $plugin */
1373
                            $plugin = $pluginInfo['obj'];
1374
                            $regionContent .= $plugin->renderRegion($pluginRegion);
1375
                        }
1376
                    }
1377
                } else {
1378
                    continue;
1379
                }
1380
            }
1381
1382
            if (!empty($regionContent)) {
1383
                $this->assign('plugin_'.$pluginRegion, $regionContent);
1384
            } else {
1385
                $this->assign('plugin_'.$pluginRegion, null);
1386
            }
1387
        }
1388
        return null;
1389
    }
1390
1391
    /**
1392
     * @param string $template
1393
     * @return string
1394
     */
1395
    public function fetch($template = null)
1396
    {
1397
        $template = $this->twig->loadTemplate($template);
1398
        return $template->render($this->params);
1399
    }
1400
1401
    /**
1402
     * @param string $variable
1403
     * @param mixed $value
1404
     */
1405
    public function assign($variable, $value = '')
1406
    {
1407
        $this->params[$variable] = $value;
1408
    }
1409
1410
    /**
1411
     * Render the template
1412
     * @param string $template The template path
1413
     * @param boolean $clearFlashMessages Clear the $_SESSION variables for flash messages
1414
     */
1415
    public function display($template, $clearFlashMessages = true)
1416
    {
1417
        $this->assign('flash_messages', Display::getFlashToString());
1418
1419
        if ($clearFlashMessages) {
1420
            Display::cleanFlashMessages();
1421
        }
1422
1423
        echo $this->twig->render($template, $this->params);
1424
    }
1425
1426
    /**
1427
     * Adds a body class for login pages
1428
     */
1429
    public function setLoginBodyClass()
1430
    {
1431
        $this->assign('login_class', 'section-login');
1432
    }
1433
1434
    /**
1435
     * The theme that will be used if the database is not working.
1436
     * @return string
1437
     */
1438
    public static function getThemeFallback()
1439
    {
1440
        $theme = api_get_configuration_value('theme_fallback');
1441
        if (empty($theme)) {
1442
            $theme = 'chamilo';
1443
        }
1444
        return $theme;
1445
    }
1446
1447
    /**
1448
     * @param bool|true $setLoginForm
1449
     */
1450
    public function setLoginForm($setLoginForm = true)
1451
    {
1452
        global $loginFailed;
1453
        $userId = api_get_user_id();
1454
        if (!($userId) || api_is_anonymous($userId)) {
1455
            // Only display if the user isn't logged in.
1456
            $this->assign(
1457
                'login_language_form',
1458
                api_display_language_form(true, true)
1459
            );
1460
            if ($setLoginForm) {
1461
                $this->assign('login_form', $this->displayLoginForm());
1462
1463
                if ($loginFailed) {
1464
                    $this->assign('login_failed', $this::handleLoginFailed());
1465
                }
1466
            }
1467
        }
1468
    }
1469
1470
    /**
1471
     * @return string
1472
     */
1473
    public function handleLoginFailed()
1474
    {
1475
        $message = get_lang('InvalidId');
1476
1477
        if (!isset($_GET['error'])) {
1478
            if (api_is_self_registration_allowed()) {
1479
                $message = get_lang('InvalidForSelfRegistration');
1480
            }
1481
        } else {
1482
            switch ($_GET['error']) {
1483
                case '':
1484
                    if (api_is_self_registration_allowed()) {
1485
                        $message = get_lang('InvalidForSelfRegistration');
1486
                    }
1487
                    break;
1488
                case 'account_expired':
1489
                    $message = get_lang('AccountExpired');
1490
                    break;
1491
                case 'account_inactive':
1492
                    $message = get_lang('AccountInactive');
1493
1494
                    if (api_get_setting('allow_registration') === 'confirmation') {
1495
                        $message = get_lang('AccountNotConfirmed').PHP_EOL;
1496
                        $message .= Display::url(
1497
                            get_lang('ReSendConfirmationMail'),
1498
                            api_get_path(WEB_PATH).'main/auth/resend_confirmation_mail.php',
1499
                            ['class' => 'alert-link']
1500
                        );
1501
                    }
1502
                    break;
1503
                case 'user_password_incorrect':
1504
                    $message = get_lang('InvalidId');
1505
                    break;
1506
                case 'access_url_inactive':
1507
                    $message = get_lang('AccountURLInactive');
1508
                    break;
1509
                case 'wrong_captcha':
1510
                    $message = get_lang('TheTextYouEnteredDoesNotMatchThePicture');
1511
                    break;
1512
                case 'blocked_by_captcha':
1513
                    $message = get_lang('AccountBlockedByCaptcha');
1514
                    break;
1515
                case 'multiple_connection_not_allowed':
1516
                    $message = get_lang('MultipleConnectionsAreNotAllow');
1517
                    break;
1518
                case 'unrecognize_sso_origin':
1519
                    //$message = get_lang('SSOError');
1520
                    break;
1521
            }
1522
        }
1523
        return Display::return_message($message, 'error', false);
1524
    }
1525
1526
    /**
1527
     * @return string
1528
     */
1529
    public function displayLoginForm()
1530
    {
1531
        $form = new FormValidator(
1532
            'formLogin',
1533
            'POST',
1534
            api_get_path(WEB_PUBLIC_PATH).'login_check',
1535
            null,
1536
            null,
1537
            FormValidator::LAYOUT_BOX_NO_LABEL
1538
        );
1539
        $params = [
1540
            'id' => '_username',
1541
            'autofocus' => 'autofocus',
1542
            'icon' => 'user fa-fw',
1543
            'placeholder' => get_lang('UserName'),
1544
        ];
1545
        $browserAutoCapitalize= false;
1546
        // Avoid showing the autocapitalize option if the browser doesn't
1547
        // support it: this attribute is against the HTML5 standard
1548
        if (api_browser_support('autocapitalize')) {
1549
            $browserAutoCapitalize = false;
1550
            $params['autocapitalize'] = 'none';
1551
        }
1552
        $form->addText(
1553
            '_username',
1554
            get_lang('UserName'),
1555
            true,
1556
            $params
1557
        );
1558
        $params = [
1559
            'id' => '_password',
1560
            'icon' => 'lock fa-fw',
1561
            'placeholder' => get_lang('Pass'),
1562
        ];
1563
        if ($browserAutoCapitalize) {
1564
            $params['autocapitalize'] = 'none';
1565
        }
1566
        $form->addElement(
1567
            'password',
1568
            '_password',
1569
            get_lang('Pass'),
1570
            $params
1571
        );
1572
1573
        $token = Chamilo\CoreBundle\Framework\Container::$container->get('security.csrf.token_manager')->getToken('authenticate');
1574
        $form->addHidden('_csrf_token', $token->getValue());
1575
1576
        // Captcha
1577
        $captcha = api_get_setting('allow_captcha');
1578
        $allowCaptcha = $captcha === 'true';
1579
1580
        if ($allowCaptcha) {
1581
            $useCaptcha = isset($_SESSION['loginFailed']) ? $_SESSION['loginFailed'] : null;
1582
            if ($useCaptcha) {
1583
                $ajax = api_get_path(WEB_AJAX_PATH).'form.ajax.php?a=get_captcha';
1584
                $options = [
1585
                    'width' => 250,
1586
                    'height' => 90,
1587
                    'callback'     => $ajax.'&var='.basename(__FILE__, '.php'),
1588
                    'sessionVar'   => basename(__FILE__, '.php'),
1589
                    'imageOptions' => [
1590
                        'font_size' => 20,
1591
                        'font_path' => api_get_path(SYS_FONTS_PATH).'opensans/',
1592
                        'font_file' => 'OpenSans-Regular.ttf',
1593
                        //'output' => 'gif'
1594
                    ]
1595
                ];
1596
1597
                // Minimum options using all defaults (including defaults for Image_Text):
1598
                //$options = array('callback' => 'qfcaptcha_image.php');
1599
                $captcha_question = $form->addElement('CAPTCHA_Image', 'captcha_question', '', $options);
1600
                $form->addHtml(get_lang('ClickOnTheImageForANewOne'));
1601
1602
                $form->addElement(
1603
                    'text',
1604
                    'captcha',
1605
                    get_lang('EnterTheLettersYouSee')
1606
                );
1607
                $form->addRule(
1608
                    'captcha',
1609
                    get_lang('EnterTheCharactersYouReadInTheImage'),
1610
                    'required',
1611
                    null,
1612
                    'client'
1613
                );
1614
                $form->addRule(
1615
                    'captcha',
1616
                    get_lang('TheTextYouEnteredDoesNotMatchThePicture'),
1617
                    'CAPTCHA',
1618
                    $captcha_question
1619
                );
1620
            }
1621
        }
1622
1623
        $form->addButton(
1624
            'submitAuth',
1625
            get_lang('LoginEnter'),
1626
            null,
1627
            'primary',
1628
            null,
1629
            'btn-block'
1630
        );
1631
1632
        $html = $form->returnForm();
1633
        if (api_get_setting('openid_authentication') == 'true') {
1634
            include_once api_get_path(SYS_CODE_PATH).'auth/openid/login.php';
1635
            $html .= '<div>'.openid_form().'</div>';
1636
        }
1637
1638
        return $html;
1639
    }
1640
1641
    /**
1642
     * Set administrator variables
1643
     */
1644
    private function setAdministratorParams()
1645
    {
1646
        $_admin = [
1647
            'email' => api_get_setting('emailAdministrator'),
1648
            'surname' => api_get_setting('administratorSurname'),
1649
            'name' => api_get_setting('administratorName'),
1650
            'telephone' => api_get_setting('administratorTelephone')
1651
        ];
1652
1653
        $this->assign('_admin', $_admin);
1654
    }
1655
1656
    /**
1657
     * Manage specific HTTP headers security
1658
     * @return void (prints headers directly)
1659
     */
1660
    private function addHTTPSecurityHeaders()
1661
    {
1662
        // Implementation of HTTP headers security, as suggested and checked
1663
        // by https://securityheaders.io/
1664
        // Enable these settings in configuration.php to use them on your site
1665
        // Strict-Transport-Security
1666
        $setting = api_get_configuration_value('security_strict_transport');
1667
        if (!empty($setting)) {
1668
            header('Strict-Transport-Security: '.$setting);
1669
        }
1670
        // Content-Security-Policy
1671
        $setting = api_get_configuration_value('security_content_policy');
1672
        if (!empty($setting)) {
1673
            header('Content-Security-Policy: '.$setting);
1674
        }
1675
        $setting = api_get_configuration_value('security_content_policy_report_only');
1676
        if (!empty($setting)) {
1677
            header('Content-Security-Policy-Report-Only: '.$setting);
1678
        }
1679
        // Public-Key-Pins
1680
        $setting = api_get_configuration_value('security_public_key_pins');
1681
        if (!empty($setting)) {
1682
            header('Public-Key-Pins: '.$setting);
1683
        }
1684
        $setting = api_get_configuration_value('security_public_key_pins_report_only');
1685
        if (!empty($setting)) {
1686
            header('Public-Key-Pins-Report-Only: '.$setting);
1687
        }
1688
        // X-Frame-Options
1689
        $setting = api_get_configuration_value('security_x_frame_options');
1690
        if (!empty($setting)) {
1691
            header('X-Frame-Options: '.$setting);
1692
        }
1693
        // X-XSS-Protection
1694
        $setting = api_get_configuration_value('security_xss_protection');
1695
        if (!empty($setting)) {
1696
            header('X-XSS-Protection: '.$setting);
1697
        }
1698
        // X-Content-Type-Options
1699
        $setting = api_get_configuration_value('security_x_content_type_options');
1700
        if (!empty($setting)) {
1701
            header('X-Content-Type-Options: '.$setting);
1702
        }
1703
        // Referrer-Policy
1704
        $setting = api_get_configuration_value('security_referrer_policy');
1705
        if (!empty($setting)) {
1706
            header('Referrer-Policy: '.$setting);
1707
        }
1708
        // end of HTTP headers security block
1709
    }
1710
1711
    /**
1712
     * Returns the tutors names for the current course in session
1713
     * Function to use in Twig templates
1714
     * @return string
1715
     */
1716
    public static function returnTutorsNames()
1717
    {
1718
        $em = Database::getManager();
1719
        $tutors = $em
1720
            ->createQuery('
1721
                SELECT u FROM ChamiloUserBundle:User u
1722
                INNER JOIN ChamiloCoreBundle:SessionRelCourseRelUser scu WITH u.id = scu.user
1723
                WHERE scu.status = :teacher_status AND scu.session = :session AND scu.course = :course
1724
            ')
1725
            ->setParameters([
1726
                'teacher_status' => SessionRelCourseRelUser::STATUS_COURSE_COACH,
1727
                'session' => api_get_session_id(),
1728
                'course' => api_get_course_int_id()
1729
            ])
1730
            ->getResult();
1731
1732
        $names = [];
1733
1734
        /** @var User $tutor */
1735
        foreach ($tutors as $tutor) {
1736
            $names[] = $tutor->getCompleteName();
1737
        }
1738
1739
        return implode(CourseManager::USER_SEPARATOR, $names);
1740
    }
1741
1742
    /**s
1743
     * Returns the teachers name for the current course
1744
     * Function to use in Twig templates
1745
     * @return string
1746
     */
1747
    public static function returnTeachersNames()
1748
    {
1749
        $em = Database::getManager();
1750
        $teachers = $em
1751
            ->createQuery('
1752
                SELECT u FROM ChamiloUserBundle:User u
1753
                INNER JOIN ChamiloCoreBundle:CourseRelUser cu WITH u.id = cu.user
1754
                WHERE cu.status = :teacher_status AND cu.course = :course
1755
            ')
1756
            ->setParameters([
1757
                'teacher_status' => User::COURSE_MANAGER,
1758
                'course' => api_get_course_int_id()
1759
            ])
1760
            ->getResult();
1761
1762
        $names = [];
1763
1764
        /** @var User $teacher */
1765
        foreach ($teachers as $teacher) {
1766
            $names[] = $teacher->getCompleteName();
1767
        }
1768
1769
        return implode(CourseManager::USER_SEPARATOR, $names);
1770
    }
1771
1772
    /**
1773
     * @param int $code
1774
     */
1775
    public function setResponseCode($code)
1776
    {
1777
        $this->responseCode = $code;
1778
    }
1779
1780
    /**
1781
     * @param string $code
1782
     */
1783
    public function getResponseCode()
1784
    {
1785
        return $this->responseCode;
1786
    }
1787
}
1788