Passed
Push — master ( 442ea1...bdf7a9 )
by Julito
09:38
created

Template::set_system_parameters()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 25
Code Lines 14

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 14
nc 2
nop 0
dl 0
loc 25
rs 9.7998
c 0
b 0
f 0
1
<?php
2
3
/* For licensing terms, see /license.txt */
4
5
use Chamilo\CoreBundle\Entity\SessionRelCourseRelUser;
6
use Chamilo\CoreBundle\Framework\Container;
7
use Chamilo\UserBundle\Entity\User;
8
use Symfony\Component\HttpFoundation\Response;
9
10
/**
11
 * Class Template.
12
 *
13
 * @author Julio Montoya <[email protected]>
14
 *
15
 * @todo better organization of the class, methods and variables
16
 */
17
class Template
18
{
19
    /**
20
     * The Template folder name see main/template.
21
     *
22
     * @var string
23
     */
24
    public $templateFolder = 'default';
25
26
    /**
27
     * The theme that will be used: chamilo, public_admin, chamilo_red, etc
28
     * This variable is set from the database.
29
     *
30
     * @var string
31
     */
32
    public $theme = '';
33
34
    /**
35
     * @var string
36
     */
37
    public $preview_theme = '';
38
    public $title = null;
39
    public $show_header;
40
    public $show_footer;
41
    public $help;
42
    public $menu_navigation = []; //Used in the userportal.lib.php function: return_navigation_course_links()
43
    public $show_learnpath = false; // This is a learnpath section or not?
44
    public $plugin = null;
45
    public $course_id = null;
46
    public $user_is_logged_in = false;
47
    public $twig = null;
48
49
    /* Loads chamilo plugins */
50
    public $load_plugins = false;
51
    public $params = [];
52
    public $force_plugin_load = false;
53
    public $responseCode = 0;
54
    private $themeDir;
55
56
    /**
57
     * @param string $title
58
     * @param bool   $show_header
59
     * @param bool   $show_footer
60
     * @param bool   $show_learnpath
61
     * @param bool   $hide_global_chat
62
     * @param bool   $load_plugins
63
     * @param int    $responseCode
64
     * @param bool   $sendHeaders      send http headers or not
65
     */
66
    public function __construct(
67
        $title = '',
68
        $show_header = true,
0 ignored issues
show
Unused Code introduced by
The parameter $show_header is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

68
        /** @scrutinizer ignore-unused */ $show_header = true,

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
69
        $show_footer = true,
0 ignored issues
show
Unused Code introduced by
The parameter $show_footer is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

69
        /** @scrutinizer ignore-unused */ $show_footer = true,

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
70
        $show_learnpath = false,
71
        $hide_global_chat = false,
72
        $load_plugins = true,
73
        $sendHeaders = true,
0 ignored issues
show
Unused Code introduced by
The parameter $sendHeaders is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

73
        /** @scrutinizer ignore-unused */ $sendHeaders = true,

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
74
        $responseCode = 0
0 ignored issues
show
Unused Code introduced by
The parameter $responseCode is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

74
        /** @scrutinizer ignore-unused */ $responseCode = 0

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
75
    ) {
76
        // Page title
77
        $this->title = $title;
78
        global $interbreadcrumb;
79
        $interbreadcrumb[] = ['url' => '#', 'name' => $title];
80
        $this->show_learnpath = $show_learnpath;
81
        //$this->setResponseCode($responseCode);
82
83
        if (empty($this->show_learnpath)) {
84
            $origin = api_get_origin();
85
            if ('learnpath' === $origin) {
86
                $this->show_learnpath = true;
87
                $show_footer = false;
88
                $show_header = false;
89
            }
90
        }
91
        $this->hide_global_chat = $hide_global_chat;
0 ignored issues
show
Bug Best Practice introduced by
The property hide_global_chat does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
92
        $this->load_plugins = $load_plugins;
93
94
        /*$template_paths = [
95
            api_get_path(SYS_CODE_PATH).'template/overrides', // user defined templates
96
            api_get_path(SYS_CODE_PATH).'template', //template folder
97
            api_get_path(SYS_PLUGIN_PATH), // plugin folder
98
            api_get_path(SYS_PATH).'src/ThemeBundle/Resources/views',
99
        ];*/
100
101
        $this->twig = Container::getTwig();
102
103
        // Setting system variables
104
        //$this->set_system_parameters();
105
106
        // Setting user variables
107
        //$this->set_user_parameters();
108
109
        // Setting course variables
110
        //$this->set_course_parameters();
111
112
        // Setting administrator variables
113
        //$this->setAdministratorParams();
114
        //$this->setCSSEditor();
115
116
        // Header and footer are showed by default
117
        //$this->set_footer($show_footer);
118
        //$this->set_header($show_header);
119
120
        //$this->set_header_parameters($sendHeaders);
121
        //$this->set_footer_parameters();
122
123
        $defaultStyle = api_get_setting('display.default_template');
124
        if (!empty($defaultStyle)) {
125
            $this->templateFolder = $defaultStyle;
126
        }
127
    }
128
129
    /**
130
     * @param string $helpInput
131
     */
132
    public function setHelp($helpInput = null)
133
    {
134
        if (!empty($helpInput)) {
135
            $help = $helpInput;
136
        } else {
137
            $help = $this->help;
138
        }
139
140
        $content = '';
141
        if ('true' == api_get_setting('enable_help_link')) {
142
            if (!empty($help)) {
143
                $help = Security::remove_XSS($help);
144
                $content = '<div class="help">';
145
                $content .= Display::url(
146
                    Display::return_icon('help.png', get_lang('Help'), null, ICON_SIZE_LARGE),
147
                    api_get_path(WEB_CODE_PATH).'help/help.php?open='.$help,
148
                    [
149
                        'class' => 'ajax',
150
                        'data-title' => get_lang('Help'),
151
                    ]
152
                );
153
                $content .= '</div>';
154
            }
155
        }
156
        $this->assign('help_content', $content);
157
    }
158
159
    /**
160
     * Use template system to parse the actions menu.
161
     *
162
     * @todo finish it!
163
     */
164
    public function set_actions($actions)
165
    {
166
        $action_string = '';
167
        if (!empty($actions)) {
168
            foreach ($actions as $action) {
169
                $action_string .= $action;
170
            }
171
        }
172
        $this->assign('actions', $actions);
173
    }
174
175
    /**
176
     * Render the template.
177
     *
178
     * @param string $template           The template path
179
     * @param bool   $clearFlashMessages Clear the $_SESSION variables for flash messages
180
     */
181
    public function display($template)
182
    {
183
        $template = str_replace('tpl', 'html.twig', $template);
184
        $templateFile = api_get_path(SYS_CODE_PATH).'template/'.$template;
185
186
        $this->loadLegacyParams();
187
188
        if (!file_exists($templateFile)) {
189
            $e = new \Gaufrette\Exception\FileNotFound($templateFile);
190
            echo $e->getMessage();
191
            exit;
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
192
        }
193
194
        $this->returnResponse($this->params, $template);
195
    }
196
197
    /**
198
     * @param string $template
199
     *
200
     * @throws \Twig\Error\Error
201
     */
202
    public function displayTemplate($template)
203
    {
204
        $this->loadLegacyParams();
205
        $this->returnResponse($this->params, $template);
206
    }
207
208
    /**
209
     * Shortcut to display a 1 col layout (index.php).
210
     * */
211
    public function display_one_col_template()
212
    {
213
        $this->loadLegacyParams();
214
        $template = '@ChamiloTheme/Layout/layout_one_col.html.twig';
215
        $origin = api_get_origin();
216
        if ('learnpath' === $origin) {
217
            $template = '@ChamiloTheme/Layout/no_layout.html.twig';
218
        }
219
        $this->returnResponse($this->params, $template);
220
    }
221
222
    /**
223
     * Displays an empty template.
224
     */
225
    public function display_blank_template()
226
    {
227
        $this->loadLegacyParams();
228
        $template = '@ChamiloTheme/Layout/blank.html.twig';
229
        $this->returnResponse($this->params, $template);
230
    }
231
232
    /**
233
     * Displays an empty template.
234
     */
235
    public function displayBlankTemplateNoHeader()
236
    {
237
        $this->loadLegacyParams();
238
        $template = '@ChamiloTheme/Layout/blank_no_header.html.twig';
239
        $this->returnResponse($this->params, $template);
240
    }
241
242
    /**
243
     * Displays an empty template.
244
     */
245
    public function display_no_layout_template()
246
    {
247
        $this->loadLegacyParams();
248
        $template = '@ChamiloTheme/Layout/no_layout.html.twig';
249
        $this->returnResponse($this->params, $template);
250
    }
251
252
    /**
253
     * Displays an empty template.
254
     */
255
    public function displaySkillLayout()
256
    {
257
        $this->loadLegacyParams();
258
        $template = '@ChamiloTheme/Layout/skill_layout.html.twig';
259
        $this->returnResponse($this->params, $template);
260
    }
261
262
    /**
263
     * return true if toolbar has to be displayed for user.
264
     *
265
     * @return bool
266
     */
267
    public static function isToolBarDisplayedForUser()
268
    {
269
        //Toolbar
270
        $show_admin_toolbar = api_get_setting('show_admin_toolbar');
271
        $show_toolbar = false;
272
273
        switch ($show_admin_toolbar) {
274
            case 'do_not_show':
275
                break;
276
            case 'show_to_admin':
277
                if (api_is_platform_admin()) {
278
                    $show_toolbar = true;
279
                }
280
                break;
281
            case 'show_to_admin_and_teachers':
282
                if (api_is_platform_admin() || api_is_allowed_to_edit()) {
283
                    $show_toolbar = true;
284
                }
285
                break;
286
            case 'show_to_all':
287
                $show_toolbar = true;
288
                break;
289
        }
290
291
        return $show_toolbar;
292
    }
293
294
    /**
295
     * Sets the header visibility.
296
     *
297
     * @param bool true if we show the header
298
     */
299
    public function set_header($status)
300
    {
301
        $this->show_header = $status;
302
        $this->assign('show_header', $status);
303
304
        $show_toolbar = 0;
305
306
        if (self::isToolBarDisplayedForUser()) {
307
            $show_toolbar = 1;
308
        }
309
310
        $this->assign('show_toolbar', $show_toolbar);
311
312
        // Only if course is available
313
        $courseToolBar = '';
314
        $show_course_navigation_menu = '';
315
        if (!empty($this->course_id) && $this->user_is_logged_in) {
316
            if ('false' !== api_get_setting('show_toolshortcuts')) {
317
                // Course toolbar
318
                $courseToolBar = CourseHome::show_navigation_tool_shortcuts();
319
            }
320
            if ('false' !== api_get_setting('show_navigation_menu')) {
321
                //Course toolbar
322
                $show_course_navigation_menu = CourseHome::show_navigation_menu();
323
            }
324
        }
325
        $this->assign('show_course_shortcut', $courseToolBar);
326
        $this->assign('show_course_navigation_menu', $show_course_navigation_menu);
327
    }
328
329
    /**
330
     * Returns the sub-folder and filename for the given tpl file.
331
     *
332
     * If template not found in overrides/ or custom template folder, the default template will be used.
333
     *
334
     * @param string $name
335
     *
336
     * @return string
337
     */
338
    public static function findTemplateFilePath($name)
339
    {
340
        $sysTemplatePath = api_get_path(SYS_TEMPLATE_PATH);
341
342
        // Check if the tpl file is present in the main/template/overrides/ dir
343
        // Overrides is a special directory meant for temporary template
344
        // customization. It must be taken into account before anything else
345
        if (is_readable($sysTemplatePath."overrides/$name")) {
346
            return "overrides/$name";
347
        }
348
349
        $defaultFolder = api_get_configuration_value('default_template');
350
351
        // If a template folder has been manually defined, search for the right
352
        // file, and if not found, go for the same file in the default template
353
        if ($defaultFolder && 'default' != $defaultFolder) {
354
            // Avoid missing template error, use the default file.
355
            if (file_exists($sysTemplatePath."$defaultFolder/$name")) {
356
                return "$defaultFolder/$name";
357
            }
358
        }
359
360
        $name = str_replace('tpl', 'html.twig', $name);
361
362
        return "default/$name";
363
    }
364
365
    /**
366
     * Call non-static for Template::findTemplateFilePath.
367
     *
368
     * @see Template::findTemplateFilePath()
369
     *
370
     * @param string $name
371
     *
372
     * @return string
373
     */
374
    public function get_template($name)
375
    {
376
        return api_find_template($name);
377
    }
378
379
    /**
380
     * Get CSS themes sub-directory.
381
     *
382
     * @param string $theme
383
     *
384
     * @return string with a trailing slash, e.g. 'themes/chamilo_red/'
385
     */
386
    public static function getThemeDir($theme)
387
    {
388
        $themeDir = 'themes/'.$theme.'/';
389
        $virtualTheme = api_get_configuration_value('virtual_css_theme_folder');
390
        if (!empty($virtualTheme)) {
391
            $virtualThemeList = api_get_themes(true);
392
            $isVirtualTheme = in_array($theme, array_keys($virtualThemeList));
393
            if ($isVirtualTheme) {
394
                $themeDir = 'themes/'.$virtualTheme.'/'.$theme.'/';
395
            }
396
        }
397
398
        return $themeDir;
399
    }
400
401
    /**
402
     * Set legacy twig globals in order to be hook in the LegacyListener.php.
403
     *
404
     * @return array
405
     */
406
    public static function getGlobals()
407
    {
408
        return [
409
            '_s' => [
410
                'software_name' => api_get_configuration_value('software_name'),
411
                'system_version' => api_get_configuration_value('system_version'),
412
                'site_name' => api_get_setting('siteName'),
413
                'institution' => api_get_setting('Institution'),
414
                'gamification_mode' => api_get_setting('gamification_mode'),
415
            ],
416
            'template' => 'default', // @todo setup template folder in config.yml;
417
        ];
418
    }
419
420
    /**
421
     * Set theme, include mainstream CSS files.
422
     *
423
     * @deprecated
424
     * @see setCssCustomFiles() for additional CSS sheets
425
     */
426
    public function setCssFiles()
427
    {
428
        global $disable_js_and_css_files;
429
        $css = [];
430
431
        // Default CSS Bootstrap
432
        $bowerCSSFiles = [
433
            'fontawesome/css/font-awesome.min.css',
434
            'jquery-ui/themes/smoothness/theme.css',
435
            'jquery-ui/themes/smoothness/jquery-ui.min.css',
436
            'mediaelement/build/mediaelementplayer.min.css',
437
            'jqueryui-timepicker-addon/dist/jquery-ui-timepicker-addon.min.css',
438
            'bootstrap/dist/css/bootstrap.min.css',
439
            'jquery.scrollbar/jquery.scrollbar.css',
440
            //'bootstrap-daterangepicker/daterangepicker.css',
441
            'bootstrap-select/dist/css/bootstrap-select.min.css',
442
            'select2/dist/css/select2.min.css',
443
            'flag-icon-css/css/flag-icon.min.css',
444
            'mediaelement/plugins/vrview/vrview.css',
445
        ];
446
447
        $features = api_get_configuration_value('video_features');
448
        $defaultFeatures = ['playpause', 'current', 'progress', 'duration', 'tracks', 'volume', 'fullscreen', 'vrview'];
449
450
        if (!empty($features) && isset($features['features'])) {
451
            foreach ($features['features'] as $feature) {
452
                if ('vrview' === $feature) {
453
                    continue;
454
                }
455
                $bowerCSSFiles[] = "mediaelement/plugins/$feature/$feature.css";
456
                $defaultFeatures[] = $feature;
457
            }
458
        }
459
460
        foreach ($bowerCSSFiles as $file) {
461
            //$css[] = api_get_path(WEB_PUBLIC_PATH).'assets/'.$file;
462
        }
463
464
        //$css[] = api_get_path(WEB_LIBRARY_PATH).'javascript/chosen/chosen.css';
465
466
        if (api_is_global_chat_enabled()) {
467
            $css[] = api_get_path(WEB_LIBRARY_PATH).'javascript/chat/css/chat.css';
468
        }
469
        $css_file_to_string = '';
470
        foreach ($css as $file) {
471
            $css_file_to_string .= api_get_css($file);
472
        }
473
474
        if (!$disable_js_and_css_files) {
475
            $this->assign('css_static_file_to_string', $css_file_to_string);
476
        }
477
478
        $defaultFeatures = implode("','", $defaultFeatures);
479
        $this->assign('video_features', $defaultFeatures);
480
    }
481
482
    /**
483
     * Prepare custom CSS to be added at the very end of the <head> section.
484
     *
485
     * @see setCssFiles() for the mainstream CSS files
486
     */
487
    public function setCssCustomFiles()
488
    {
489
        global $disable_js_and_css_files;
490
        $css = [];
491
        if ($this->show_learnpath) {
492
            if (is_file(api_get_path(SYS_CSS_PATH).$this->themeDir.'learnpath.css')) {
493
                $css[] = api_get_path(WEB_CSS_PATH).$this->themeDir.'learnpath.css';
494
            }
495
        }
496
497
        $css_file_to_string = '';
498
        foreach ($css as $file) {
499
            $css_file_to_string .= api_get_css($file);
500
        }
501
502
        // @todo move this somewhere else. Special fix when using tablets in order to see the text near icons
503
        if (SHOW_TEXT_NEAR_ICONS == true) {
0 ignored issues
show
Coding Style Best Practice introduced by
It seems like you are loosely comparing two booleans. Considering using the strict comparison === instead.

When comparing two booleans, it is generally considered safer to use the strict comparison operator.

Loading history...
504
            //hack in order to fix the actions buttons
505
            $css_file_to_string .= '<style>
506
                .td_actions a {
507
                    float:left;
508
                    width:100%;
509
                }
510
                .forum_message_left a {
511
                    float:left;
512
                    width:100%;
513
                }
514
                </style>';
515
        }
516
517
        $navigator_info = api_get_navigator();
518
        if ('Internet Explorer' == $navigator_info['name'] && '6' == $navigator_info['version']) {
519
            $css_file_to_string .= 'img, div { behavior: url('.api_get_path(WEB_LIBRARY_PATH).'javascript/iepngfix/iepngfix.htc) } '."\n";
520
        }
521
522
        if (!$disable_js_and_css_files) {
523
            $this->assign('css_custom_file_to_string', $css_file_to_string);
524
525
            $style_print = '';
526
            if (is_readable(api_get_path(SYS_CSS_PATH).$this->theme.'/print.css')) {
527
                $style_print = api_get_css(
528
                    api_get_path(WEB_CSS_PATH).$this->theme.'/print.css',
529
                    'print'
530
                );
531
            }
532
            $this->assign('css_style_print', $style_print);
533
        }
534
535
        // Logo
536
        $logo = return_logo($this->theme);
537
        $logoPdf = return_logo($this->theme, false);
538
        $this->assign('logo', $logo);
539
        $this->assign('logo_pdf', $logoPdf);
540
        $this->assign('show_media_element', 1);
541
    }
542
543
    /**
544
     * Declare and define the template variable that will be used to load
545
     * javascript libraries in the header.
546
     */
547
    public function set_js_files()
548
    {
549
        global $disable_js_and_css_files, $htmlHeadXtra;
550
        $isoCode = api_get_language_isocode();
551
        $selectLink = 'bootstrap-select/dist/js/i18n/defaults-'.$isoCode.'_'.strtoupper($isoCode).'.min.js';
552
553
        if ('en' == $isoCode) {
554
            $selectLink = 'bootstrap-select/dist/js/i18n/defaults-'.$isoCode.'_US.min.js';
555
        }
556
        // JS files
557
        $js_files = [
558
            'chosen/chosen.jquery.min.js',
559
        ];
560
561
        $viewBySession = 'true' === api_get_setting('my_courses_view_by_session');
562
563
        if (api_is_global_chat_enabled() || $viewBySession) {
564
            // Do not include the global chat in LP
565
            if (false == $this->show_learnpath &&
566
                true == $this->show_footer &&
567
                false == $this->hide_global_chat
0 ignored issues
show
Coding Style Best Practice introduced by
It seems like you are loosely comparing two booleans. Considering using the strict comparison === instead.

When comparing two booleans, it is generally considered safer to use the strict comparison operator.

Loading history...
568
            ) {
569
                $js_files[] = 'chat/js/chat.js';
570
            }
571
        }
572
573
        if ('true' === api_get_setting('accessibility_font_resize')) {
574
            $js_files[] = 'fontresize.js';
575
        }
576
577
        $js_file_to_string = '';
578
        $bowerJsFiles = [
579
            'modernizr/modernizr.js',
580
            'jquery/query.min.js',
581
            'bootstrap/dist/js/bootstrap.min.js',
582
            'jquery-ui/jquery-ui.min.js',
583
            'jqueryui-touch-punch/jquery.ui.touch-punch.min.js',
584
            'moment/min/moment-with-locales.js',
585
            //'bootstrap-daterangepicker/daterangepicker.js',
586
            'jquery-timeago/jquery.timeago.js',
587
            'mediaelement/mediaelement-and-player.min.js',
588
            'jqueryui-timepicker-addon/dist/jquery-ui-timepicker-addon.min.js',
589
            'image-map-resizer/js/imageMapResizer.min.js',
590
            'jquery.scrollbar/jquery.scrollbar.min.js',
591
            //'readmore-js/readmore.min.js',
592
            'bootstrap-select/dist/js/bootstrap-select.min.js',
593
            $selectLink,
594
            'select2/dist/js/select2.min.js',
595
            "select2/dist/js/i18n/$isoCode.js",
596
            'mediaelement/plugins/vrview/vrview.js',
597
        ];
598
599
        $features = api_get_configuration_value('video_features');
600
        if (!empty($features) && isset($features['features'])) {
601
            foreach ($features['features'] as $feature) {
602
                if ('vrview' === $feature) {
603
                    continue;
604
                }
605
                $bowerJsFiles[] = "mediaelement/plugins/$feature/$feature.js";
606
            }
607
        }
608
609
        if (CHAMILO_LOAD_WYSIWYG === true) {
610
            $bowerJsFiles[] = 'ckeditor/ckeditor.js';
611
        }
612
613
        if ('true' === api_get_setting('include_asciimathml_script')) {
614
            $bowerJsFiles[] = 'MathJax/MathJax.js?config=TeX-MML-AM_HTMLorMML';
615
        }
616
617
        if ('en' != $isoCode) {
618
            $bowerJsFiles[] = 'jqueryui-timepicker-addon/dist/i18n/jquery-ui-timepicker-'.$isoCode.'.js';
619
            $bowerJsFiles[] = 'jquery-ui/ui/minified/i18n/datepicker-'.$isoCode.'.min.js';
620
        }
621
622
        foreach ($bowerJsFiles as $file) {
623
            //$js_file_to_string .= '<script type="text/javascript" src="'.api_get_path(WEB_PUBLIC_PATH).'assets/'.$file.'"></script>'."\n";
624
        }
625
626
        foreach ($js_files as $file) {
627
            //$js_file_to_string .= api_get_js($file);
628
        }
629
630
        // Loading email_editor js
631
        if (!api_is_anonymous() && 'true' == api_get_setting('allow_email_editor')) {
632
            $template = $this->get_template('mail_editor/email_link.js.tpl');
633
            $js_file_to_string .= $this->fetch($template);
634
        }
635
636
        if (!$disable_js_and_css_files) {
637
            $this->assign('js_file_to_string', $js_file_to_string);
638
            $extraHeaders = '';
639
            //$extraHeaders = '<script>var _p = '.json_encode($this->getWebPaths(), JSON_PRETTY_PRINT).'</script>';
640
            //Adding jquery ui by default
641
            $extraHeaders .= api_get_jquery_ui_js();
642
            if (isset($htmlHeadXtra) && $htmlHeadXtra) {
643
                foreach ($htmlHeadXtra as &$this_html_head) {
644
                    $extraHeaders .= $this_html_head."\n";
645
                }
646
            }
647
648
            $ajax = api_get_path(WEB_AJAX_PATH);
649
            $courseId = api_get_course_id();
650
            if (empty($courseId)) {
651
                $courseLogoutCode = '
652
                <script>
653
                function courseLogout() {
654
                }
655
                </script>';
656
            } else {
657
                $courseLogoutCode = "
658
                <script>
659
                var logOutUrl = '".$ajax."course.ajax.php?a=course_logout&".api_get_cidreq()."';
660
                function courseLogout() {
661
                    $.ajax({
662
                        async : false,
663
                        url: logOutUrl,
664
                        success: function (data) {
665
                            return 1;
666
                        }
667
                    });
668
                }
669
                </script>";
670
            }
671
672
            $extraHeaders .= $courseLogoutCode;
673
            $this->assign('extra_headers', $extraHeaders);
674
        }
675
    }
676
677
    /**
678
     * @param array  $params
679
     * @param string $template
680
     *
681
     * @throws \Twig\Error\Error
682
     */
683
    public function returnResponse($params, $template)
684
    {
685
        $flash = Display::getFlashToString();
686
        Display::cleanFlashMessages();
687
        $response = new Response();
688
        $params['flash_messages'] = $flash;
689
        $content = Container::getTemplating()->render($template, $params);
690
        $response->setContent($content);
691
        $response->send();
692
    }
693
694
    /**
695
     * Special function to declare last-minute JS libraries which depend on
696
     * other things to be declared first. In particular, it might be useful
697
     * under IE9 with compatibility mode, which for some reason is getting
698
     * upset when a variable is used in a function (even if not used yet)
699
     * when this variable hasn't been defined yet.
700
     */
701
    public function set_js_files_post()
702
    {
703
        global $disable_js_and_css_files;
704
        $js_files = [];
705
        if (api_is_global_chat_enabled()) {
706
            //Do not include the global chat in LP
707
            if (false == $this->show_learnpath && true == $this->show_footer && false == $this->hide_global_chat) {
0 ignored issues
show
Coding Style Best Practice introduced by
It seems like you are loosely comparing two booleans. Considering using the strict comparison === instead.

When comparing two booleans, it is generally considered safer to use the strict comparison operator.

Loading history...
708
                $js_files[] = 'chat/js/chat.js';
709
            }
710
        }
711
        $js_file_to_string = '';
712
        foreach ($js_files as $js_file) {
713
            $js_file_to_string .= api_get_js($js_file);
714
        }
715
        if (!$disable_js_and_css_files) {
716
            $this->assign('js_file_to_string_post', $js_file_to_string);
717
        }
718
    }
719
720
    /**
721
     * @param string $theme
722
     *
723
     * @return string
724
     */
725
    public static function getPortalIcon($theme)
726
    {
727
        // Default root chamilo favicon
728
        $icon = 'favicon.ico';
729
730
        // Added to verify if in the current Chamilo Theme exist a favicon
731
        $themeUrl = api_get_path(SYS_CSS_PATH).'themes/'.$theme.'/images/';
732
733
        // If exist pick the current chamilo theme favicon.
734
        if (is_file($themeUrl.'favicon.ico')) {
735
            $icon = 'build/css/themes/'.$theme.'/images/favicon.ico';
736
        }
737
738
        return $icon;
739
    }
740
741
    /**
742
     * Show footer js template.
743
     */
744
    public function show_footer_js_template()
745
    {
746
        $tpl = $this->get_template('layout/footer.js.tpl');
747
        $this->display($tpl);
748
    }
749
750
    /**
751
     * @param string $template
752
     *
753
     * @return string
754
     */
755
    public function fetch($template = null)
756
    {
757
        return $this->twig->render($template, $this->params);
758
    }
759
760
    /**
761
     * @param string $variable
762
     * @param mixed  $value
763
     */
764
    public function assign($variable, $value = '')
765
    {
766
        $this->params[$variable] = $value;
767
    }
768
769
    /**
770
     * Adds a body class for login pages.
771
     */
772
    public function setLoginBodyClass()
773
    {
774
        $this->assign('login_class', 'section-login');
775
    }
776
777
    /**
778
     * The theme that will be used if the database is not working.
779
     *
780
     * @return string
781
     */
782
    public static function getThemeFallback()
783
    {
784
        $theme = api_get_configuration_value('theme_fallback');
785
        if (empty($theme)) {
786
            $theme = 'chamilo';
787
        }
788
789
        return $theme;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $theme also could return the type boolean which is incompatible with the documented return type string.
Loading history...
790
    }
791
792
    /**
793
     * @return string
794
     */
795
    public function handleLoginFailed()
796
    {
797
        $message = get_lang('Login failed - incorrect login or password.');
798
799
        if (!isset($_GET['error'])) {
800
            if (api_is_self_registration_allowed()) {
801
                $message = get_lang('Login failed - if you are not registered, you can do so using the <a href=claroline/auth/inscription.php>registration form</a>');
802
            }
803
        } else {
804
            switch ($_GET['error']) {
805
                case '':
806
                    if (api_is_self_registration_allowed()) {
807
                        $message = get_lang('Login failed - if you are not registered, you can do so using the <a href=claroline/auth/inscription.php>registration form</a>');
808
                    }
809
                    break;
810
                case 'account_expired':
811
                    $message = get_lang('Account expired');
812
                    break;
813
                case 'account_inactive':
814
                    $message = get_lang('Account inactive');
815
816
                    if ('confirmation' === api_get_setting('allow_registration')) {
817
                        $message = get_lang('Your account is inactive because you have not confirmed it yet. Check your email and follow the instructions or click the following link to resend the email').PHP_EOL;
818
                        $message .= Display::url(
819
                            get_lang('Send confirmation mail again'),
820
                            api_get_path(WEB_PATH).'main/auth/resend_confirmation_mail.php',
821
                            ['class' => 'alert-link']
822
                        );
823
                    }
824
                    break;
825
                case 'user_password_incorrect':
826
                    $message = get_lang('Login failed - incorrect login or password.');
827
                    break;
828
                case 'access_url_inactive':
829
                    $message = get_lang('Account inactive for this URL');
830
                    break;
831
                case 'wrong_captcha':
832
                    $message = get_lang('The text you entered doesn\'t match the picture.');
833
                    break;
834
                case 'blocked_by_captcha':
835
                    $message = get_lang('Account blocked by captcha.');
836
                    break;
837
                case 'multiple_connection_not_allowed':
838
                    $message = get_lang('This user is already logged in');
839
                    break;
840
            }
841
        }
842
843
        return Display::return_message($message, 'error', false);
844
    }
845
846
    /**
847
     * @return string
848
     */
849
    public function displayLoginForm()
850
    {
851
        $form = new FormValidator(
852
            'form-login',
853
            'POST',
854
            api_get_path(WEB_PUBLIC_PATH).'login_check',
855
            null,
856
            null,
857
            FormValidator::LAYOUT_BOX_NO_LABEL
858
        );
859
        $params = [
860
            'id' => '_username',
861
            'autofocus' => 'autofocus',
862
            'icon' => 'user fa-fw',
863
            'placeholder' => get_lang('Username'),
864
        ];
865
        $browserAutoCapitalize = false;
866
        // Avoid showing the autocapitalize option if the browser doesn't
867
        // support it: this attribute is against the HTML5 standard
868
        if (api_browser_support('autocapitalize')) {
0 ignored issues
show
Deprecated Code introduced by
The function api_browser_support() has been deprecated. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

868
        if (/** @scrutinizer ignore-deprecated */ api_browser_support('autocapitalize')) {
Loading history...
869
            $browserAutoCapitalize = false;
870
            $params['autocapitalize'] = 'none';
871
        }
872
        $form->addText(
873
            '_username',
874
            get_lang('Username'),
875
            true,
876
            $params
877
        );
878
        $params = [
879
            'id' => '_password',
880
            'icon' => 'lock fa-fw',
881
            'placeholder' => get_lang('Pass'),
882
        ];
883
        if ($browserAutoCapitalize) {
884
            $params['autocapitalize'] = 'none';
885
        }
886
        $form->addElement(
887
            'password',
888
            '_password',
889
            get_lang('Pass'),
890
            $params
891
        );
892
893
        $token = Chamilo\CoreBundle\Framework\Container::$container->get('security.csrf.token_manager')->getToken('authenticate');
894
        $form->addHidden('_csrf_token', $token->getValue());
895
896
        // Captcha
897
        $captcha = api_get_setting('allow_captcha');
898
        $allowCaptcha = 'true' === $captcha;
899
900
        if ($allowCaptcha) {
901
            $useCaptcha = isset($_SESSION['loginFailed']) ? $_SESSION['loginFailed'] : null;
902
            if ($useCaptcha) {
903
                $ajax = api_get_path(WEB_AJAX_PATH).'form.ajax.php?a=get_captcha';
904
                $options = [
905
                    'width' => 250,
906
                    'height' => 90,
907
                    'callback' => $ajax.'&var='.basename(__FILE__, '.php'),
908
                    'sessionVar' => basename(__FILE__, '.php'),
909
                    'imageOptions' => [
910
                        'font_size' => 20,
911
                        'font_path' => api_get_path(SYS_FONTS_PATH).'opensans/',
912
                        'font_file' => 'OpenSans-Regular.ttf',
913
                        //'output' => 'gif'
914
                    ],
915
                ];
916
917
                // Minimum options using all defaults (including defaults for Image_Text):
918
                //$options = array('callback' => 'qfcaptcha_image.php');
919
                $captcha_question = $form->addElement('CAPTCHA_Image', 'captcha_question', '', $options);
920
                $form->addHtml(get_lang('Click on the image to load a new one.'));
921
922
                $form->addElement(
923
                    'text',
924
                    'captcha',
925
                    get_lang('Enter the letters you see.')
926
                );
927
                $form->addRule(
928
                    'captcha',
929
                    get_lang('Enter the characters you see on the image'),
930
                    'required',
931
                    null,
932
                    'client'
933
                );
934
                $form->addRule(
935
                    'captcha',
936
                    get_lang('The text you entered doesn\'t match the picture.'),
937
                    'CAPTCHA',
938
                    $captcha_question
939
                );
940
            }
941
        }
942
943
        $form->addButton(
944
            'submitAuth',
945
            get_lang('Login'),
946
            null,
947
            'primary',
948
            null,
949
            'btn-block'
950
        );
951
952
        $html = $form->returnForm();
953
954
        return $html;
955
    }
956
957
    /**
958
     * Returns the tutors names for the current course in session
959
     * Function to use in Twig templates.
960
     *
961
     * @return string
962
     */
963
    public static function returnTutorsNames()
964
    {
965
        $em = Database::getManager();
966
        $tutors = $em
967
            ->createQuery('
968
                SELECT u FROM ChamiloUserBundle:User u
969
                INNER JOIN ChamiloCoreBundle:SessionRelCourseRelUser scu WITH u.id = scu.user
970
                WHERE scu.status = :teacher_status AND scu.session = :session AND scu.course = :course
971
            ')
972
            ->setParameters([
973
                'teacher_status' => SessionRelCourseRelUser::STATUS_COURSE_COACH,
974
                'session' => api_get_session_id(),
975
                'course' => api_get_course_int_id(),
976
            ])
977
            ->getResult();
978
979
        $names = [];
980
981
        /** @var User $tutor */
982
        foreach ($tutors as $tutor) {
983
            $names[] = UserManager::formatUserFullName($tutor);
984
        }
985
986
        return implode(CourseManager::USER_SEPARATOR, $names);
987
    }
988
989
    /*s
990
     * Returns the teachers name for the current course
991
     * Function to use in Twig templates
992
     * @return string
993
     */
994
    public static function returnTeachersNames()
995
    {
996
        $em = Database::getManager();
997
        $teachers = $em
998
            ->createQuery('
999
                SELECT u FROM ChamiloUserBundle:User u
1000
                INNER JOIN ChamiloCoreBundle:CourseRelUser cu WITH u.id = cu.user
1001
                WHERE cu.status = :teacher_status AND cu.course = :course
1002
            ')
1003
            ->setParameters([
1004
                'teacher_status' => User::COURSE_MANAGER,
1005
                'course' => api_get_course_int_id(),
1006
            ])
1007
            ->getResult();
1008
1009
        $names = [];
1010
1011
        /** @var User $teacher */
1012
        foreach ($teachers as $teacher) {
1013
            $names[] = UserManager::formatUserFullName($teacher);
1014
        }
1015
1016
        return implode(CourseManager::USER_SEPARATOR, $names);
1017
    }
1018
1019
    /**
1020
     * @param int $code
1021
     */
1022
    public function setResponseCode($code)
1023
    {
1024
        $this->responseCode = $code;
1025
    }
1026
1027
    /**
1028
     * @param string $code
1029
     */
1030
    public function getResponseCode()
1031
    {
1032
        return $this->responseCode;
1033
    }
1034
1035
    /**
1036
     * Assign HTML code to the 'bug_notification' template variable for the side tabs to report issues.
1037
     *
1038
     * @return bool Always return true because there is always a string, even if empty
1039
     */
1040
    public function assignBugNotification()
1041
    {
1042
        //@todo move this in the template
1043
        $rightFloatMenu = '';
1044
        $iconBug = Display::return_icon(
1045
            'bug.png',
1046
            get_lang('Report a bug'),
1047
            [],
1048
            ICON_SIZE_LARGE
1049
        );
1050
        if ('true' === api_get_setting('show_link_bug_notification') && $this->user_is_logged_in) {
1051
            $rightFloatMenu = '<div class="report">
1052
		        <a href="https://github.com/chamilo/chamilo-lms/wiki/How-to-report-issues" target="_blank">
1053
                    '.$iconBug.'
1054
                </a>
1055
		        </div>';
1056
        }
1057
1058
        if ('true' === api_get_setting('show_link_ticket_notification') &&
1059
            $this->user_is_logged_in
1060
        ) {
1061
            // by default is project_id = 1
1062
            $defaultProjectId = 1;
1063
            $iconTicket = Display::return_icon(
1064
                'help.png',
1065
                get_lang('Ticket'),
1066
                [],
1067
                ICON_SIZE_LARGE
1068
            );
1069
            $courseInfo = api_get_course_info();
1070
            $courseParams = '';
1071
            if (!empty($courseInfo)) {
1072
                $courseParams = api_get_cidreq();
1073
            }
1074
            $url = api_get_path(WEB_CODE_PATH).'ticket/tickets.php?project_id='.$defaultProjectId.'&'.$courseParams;
1075
1076
            $allow = TicketManager::userIsAllowInProject(api_get_user_info(), $defaultProjectId);
0 ignored issues
show
Bug introduced by
It seems like api_get_user_info() can also be of type false; however, parameter $userInfo of TicketManager::userIsAllowInProject() does only seem to accept array, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

1076
            $allow = TicketManager::userIsAllowInProject(/** @scrutinizer ignore-type */ api_get_user_info(), $defaultProjectId);
Loading history...
1077
1078
            if ($allow) {
1079
                $rightFloatMenu .= '<div class="help">
1080
                    <a href="'.$url.'" target="_blank">
1081
                        '.$iconTicket.'
1082
                    </a>
1083
                </div>';
1084
            }
1085
        }
1086
1087
        $this->assign('bug_notification', $rightFloatMenu);
1088
1089
        return true;
1090
    }
1091
1092
    /**
1093
     * Load legacy params.
1094
     */
1095
    private function loadLegacyParams()
1096
    {
1097
        // Set legacy breadcrumb
1098
        global $interbreadcrumb;
1099
        $this->params['legacy_breadcrumb'] = $interbreadcrumb;
1100
1101
        global $htmlHeadXtra;
1102
        $this->params['legacy_javascript'] = $htmlHeadXtra;
1103
    }
1104
1105
    /**
1106
     * Prepare the _c array for template files. The _c array contains
1107
     * information about the current course.
1108
     */
1109
    private function set_course_parameters()
0 ignored issues
show
Unused Code introduced by
The method set_course_parameters() is not used, and could be removed.

This check looks for private methods that have been defined, but are not used inside the class.

Loading history...
1110
    {
1111
        //Setting course id
1112
        $course = api_get_course_info();
1113
        if (empty($course)) {
1114
            $this->assign('course_is_set', false);
1115
1116
            return;
1117
        }
1118
        $this->assign('course_is_set', true);
1119
        $this->course_id = $course['id'];
1120
        $_c = [
1121
            'id' => $course['real_id'],
1122
            'code' => $course['code'],
1123
            'title' => $course['name'],
1124
            'visibility' => $course['visibility'],
1125
            'language' => $course['language'],
1126
            'directory' => $course['directory'],
1127
            'session_id' => api_get_session_id(),
1128
            'user_is_teacher' => api_is_course_admin(),
1129
            'student_view' => (!empty($_GET['isStudentView']) && 'true' == $_GET['isStudentView']),
1130
        ];
1131
        $this->assign('course_code', $course['code']);
1132
        $this->assign('_c', $_c);
1133
    }
1134
1135
    /**
1136
     * Prepare the _u array for template files. The _u array contains
1137
     * information about the current user, as returned by
1138
     * api_get_user_info().
1139
     */
1140
    private function set_user_parameters()
0 ignored issues
show
Unused Code introduced by
The method set_user_parameters() is not used, and could be removed.

This check looks for private methods that have been defined, but are not used inside the class.

Loading history...
1141
    {
1142
        $user_info = [];
1143
        $user_info['logged'] = 0;
1144
        $this->user_is_logged_in = false;
1145
        if (api_user_is_login()) {
1146
            $user_info = api_get_user_info(api_get_user_id(), true);
1147
            $user_info['logged'] = 1;
1148
1149
            $user_info['is_admin'] = 0;
1150
            if (api_is_platform_admin()) {
1151
                $user_info['is_admin'] = 1;
1152
            }
1153
1154
            $user_info['messages_count'] = MessageManager::getCountNewMessages();
1155
            $this->user_is_logged_in = true;
1156
        }
1157
        // Setting the $_u array that could be use in any template
1158
        $this->assign('_u', $user_info);
1159
    }
1160
1161
    /**
1162
     * Set header parameters.
1163
     *
1164
     * @deprecated
1165
     *
1166
     * @param bool $sendHeaders send headers
1167
     */
1168
    private function set_header_parameters($sendHeaders)
0 ignored issues
show
Unused Code introduced by
The method set_header_parameters() is not used, and could be removed.

This check looks for private methods that have been defined, but are not used inside the class.

Loading history...
1169
    {
1170
        global $httpHeadXtra, $interbreadcrumb, $language_file, $_configuration, $this_section;
1171
        $_course = api_get_course_info();
1172
        $nameTools = $this->title;
1173
        $navigation = return_navigation_array();
1174
        $this->menu_navigation = $navigation['menu_navigation'];
1175
1176
        $this->assign('system_charset', api_get_system_encoding());
1177
1178
        if (isset($httpHeadXtra) && $httpHeadXtra) {
1179
            foreach ($httpHeadXtra as &$thisHttpHead) {
1180
                //header($thisHttpHead);
1181
            }
1182
        }
1183
1184
        $this->assign(
1185
            'online_button',
1186
            Display::return_icon('statusonline.png', null, [], ICON_SIZE_ATOM)
1187
        );
1188
        $this->assign(
1189
            'offline_button',
1190
            Display::return_icon('statusoffline.png', null, [], ICON_SIZE_ATOM)
1191
        );
1192
1193
        // Get language iso-code for this page - ignore errors
1194
        $this->assign('document_language', api_get_language_isocode());
1195
1196
        $course_title = isset($_course['name']) ? $_course['name'] : null;
1197
1198
        $title_list = [];
1199
1200
        $title_list[] = api_get_setting('Institution');
1201
        $title_list[] = api_get_setting('siteName');
1202
1203
        if (!empty($course_title)) {
1204
            $title_list[] = $course_title;
1205
        }
1206
        if ('' != $nameTools) {
1207
            $title_list[] = $nameTools;
1208
        }
1209
1210
        $title_string = '';
1211
        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...
1212
            $title_string .= $title_list[$i];
1213
            if (isset($title_list[$i + 1])) {
1214
                $item = trim($title_list[$i + 1]);
1215
                if (!empty($item)) {
1216
                    $title_string .= ' - ';
1217
                }
1218
            }
1219
        }
1220
1221
        $this->assign('title_string', $title_string);
1222
1223
        // Setting the theme and CSS files
1224
        $this->setCssFiles();
0 ignored issues
show
Deprecated Code introduced by
The function Template::setCssFiles() has been deprecated. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

1224
        /** @scrutinizer ignore-deprecated */ $this->setCssFiles();
Loading history...
1225
        $this->set_js_files();
1226
        $this->setCssCustomFiles();
1227
1228
        $browser = api_browser_support('check_browser');
0 ignored issues
show
Deprecated Code introduced by
The function api_browser_support() has been deprecated. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

1228
        $browser = /** @scrutinizer ignore-deprecated */ api_browser_support('check_browser');
Loading history...
1229
        if ('Internet Explorer' == $browser[0] && $browser[1] >= '11') {
1230
            $browser_head = '<meta http-equiv="X-UA-Compatible" content="IE=EmulateIE9" />';
1231
            $this->assign('browser_specific_head', $browser_head);
1232
        }
1233
1234
        // Implementation of prefetch.
1235
        // See http://cdn.chamilo.org/main/img/online.png for details
1236
        $prefetch = '';
1237
        if (!empty($_configuration['cdn_enable'])) {
1238
            $prefetch .= '<meta http-equiv="x-dns-prefetch-control" content="on">';
1239
            foreach ($_configuration['cdn'] as $host => $exts) {
1240
                $prefetch .= '<link rel="dns-prefetch" href="'.$host.'">';
1241
            }
1242
        }
1243
1244
        $this->assign('prefetch', $prefetch);
1245
        $this->assign('text_direction', api_get_text_direction());
1246
        $this->assign('section_name', 'section-'.$this_section);
1247
        $this->assignFavIcon();
1248
        $this->setHelp();
1249
1250
        $this->assignBugNotification(); //Prepare the 'bug_notification' var for the template
1251
1252
        $this->assignAccessibilityBlock(); //Prepare the 'accessibility' var for the template
1253
1254
        // Preparing values for the menu
1255
1256
        // Logout link
1257
        $hideLogout = api_get_setting('hide_logout_button');
1258
        if ('true' === $hideLogout) {
1259
            $this->assign('logout_link', null);
1260
        } else {
1261
            $this->assign('logout_link', api_get_path(WEB_PATH).'index.php?logout=logout&uid='.api_get_user_id());
1262
        }
1263
1264
        // Profile link
1265
        if ('true' == api_get_setting('allow_social_tool')) {
1266
            $profile_url = api_get_path(WEB_CODE_PATH).'social/home.php';
1267
        } else {
1268
            $profile_url = api_get_path(WEB_CODE_PATH).'auth/profile.php';
1269
        }
1270
1271
        $this->assign('profile_url', $profile_url);
1272
1273
        //Message link
1274
        $message_link = null;
1275
        $message_url = null;
1276
        if ('true' == api_get_setting('allow_message_tool')) {
1277
            $message_url = api_get_path(WEB_CODE_PATH).'messages/inbox.php';
1278
            $message_link = '<a href="'.api_get_path(WEB_CODE_PATH).'messages/inbox.php">'.get_lang('Inbox').'</a>';
1279
        }
1280
        $this->assign('message_link', $message_link);
1281
        $this->assign('message_url', $message_url);
1282
1283
        $pendingSurveyLink = '';
1284
        $show = api_get_configuration_value('show_pending_survey_in_menu');
1285
        if ($show) {
1286
            $pendingSurveyLink = api_get_path(WEB_CODE_PATH).'survey/pending.php';
1287
        }
1288
        $this->assign('pending_survey_url', $pendingSurveyLink);
1289
1290
        // Certificate Link
1291
        $allow = api_get_configuration_value('certificate.hide_my_certificate_link');
1292
        if (false === $allow) {
1293
            $certificateUrl = api_get_path(WEB_CODE_PATH).'gradebook/my_certificates.php';
1294
            $certificateLink = Display::url(
1295
                get_lang('My certificates'),
1296
                $certificateUrl
1297
            );
1298
            $this->assign('certificate_link', $certificateLink);
1299
            $this->assign('certificate_url', $certificateUrl);
1300
        }
1301
1302
        $institution = api_get_setting('Institution');
1303
        $portal_name = empty($institution) ? api_get_setting('siteName') : $institution;
1304
1305
        $this->assign('portal_name', $portal_name);
1306
1307
        //Menu
1308
        //$menu = menuArray();
1309
        //$this->assign('menu', $menu);
1310
1311
        $breadcrumb = '';
1312
        // Hide breadcrumb in LP
1313
        if (false == $this->show_learnpath) {
1314
            $breadcrumb = return_breadcrumb(
1315
                $interbreadcrumb,
1316
                $language_file,
1317
                $nameTools
1318
            );
1319
        }
1320
        $this->assign('breadcrumb', $breadcrumb);
1321
1322
        //Extra content
1323
        $extra_header = null;
1324
        if (!api_is_platform_admin()) {
1325
            $extra_header = trim(api_get_setting('header_extra_content'));
1326
        }
1327
        $this->assign('header_extra_content', $extra_header);
1328
1329
        if ($sendHeaders) {
1330
            /*header('Content-Type: text/html; charset='.api_get_system_encoding());
1331
            header(
1332
                'X-Powered-By: '.$_configuration['software_name'].' '.substr($_configuration['system_version'], 0, 1)
1333
            );
1334
            self::addHTTPSecurityHeaders();*/
1335
1336
            $responseCode = $this->getResponseCode();
1337
            if (!empty($responseCode)) {
1338
                switch ($responseCode) {
1339
                    case '404':
1340
                        header("HTTP/1.0 404 Not Found");
1341
                        break;
1342
                }
1343
            }
1344
        }
1345
1346
        $socialMeta = '';
1347
        $metaTitle = api_get_setting('meta_title');
1348
        if (!empty($metaTitle)) {
1349
            $socialMeta .= '<meta name="twitter:card" content="summary" />'."\n";
1350
            $metaSite = api_get_setting('meta_twitter_site');
1351
            if (!empty($metaSite)) {
1352
                $socialMeta .= '<meta name="twitter:site" content="'.$metaSite.'" />'."\n";
1353
                $metaCreator = api_get_setting('meta_twitter_creator');
1354
                if (!empty($metaCreator)) {
1355
                    $socialMeta .= '<meta name="twitter:creator" content="'.$metaCreator.'" />'."\n";
1356
                }
1357
            }
1358
1359
            // The user badge page emits its own meta tags, so if this is
1360
            // enabled, ignore the global ones
1361
            $userId = isset($_GET['user']) ? intval($_GET['user']) : 0;
1362
            $skillId = isset($_GET['skill']) ? intval($_GET['skill']) : 0;
1363
1364
            if (!$userId && !$skillId) {
1365
                // no combination of user and skill ID has been defined,
1366
                // so print the normal OpenGraph meta tags
1367
                $socialMeta .= '<meta property="og:title" content="'.$metaTitle.'" />'."\n";
1368
                $socialMeta .= '<meta property="og:url" content="'.api_get_path(WEB_PATH).'" />'."\n";
1369
1370
                $metaDescription = api_get_setting('meta_description');
1371
                if (!empty($metaDescription)) {
1372
                    $socialMeta .= '<meta property="og:description" content="'.$metaDescription.'" />'."\n";
1373
                }
1374
1375
                $metaImage = api_get_setting('meta_image_path');
1376
                if (!empty($metaImage)) {
1377
                    if (is_file(api_get_path(SYS_PATH).$metaImage)) {
1378
                        $path = api_get_path(WEB_PATH).$metaImage;
1379
                        $socialMeta .= '<meta property="og:image" content="'.$path.'" />'."\n";
1380
                    }
1381
                }
1382
            }
1383
        }
1384
1385
        $this->assign('social_meta', $socialMeta);
1386
    }
1387
1388
    /**
1389
     * Set footer parameters.
1390
     */
1391
    private function set_footer_parameters()
0 ignored issues
show
Unused Code introduced by
The method set_footer_parameters() is not used, and could be removed.

This check looks for private methods that have been defined, but are not used inside the class.

Loading history...
1392
    {
1393
        // Loading footer extra content
1394
        if (!api_is_platform_admin()) {
1395
            $extra_footer = trim(api_get_setting('footer_extra_content'));
1396
            if (!empty($extra_footer)) {
1397
                $this->assign('footer_extra_content', $extra_footer);
1398
            }
1399
        }
1400
    }
1401
1402
    /**
1403
     * Manage specific HTTP headers security.
1404
     */
1405
    private function addHTTPSecurityHeaders()
0 ignored issues
show
Unused Code introduced by
The method addHTTPSecurityHeaders() is not used, and could be removed.

This check looks for private methods that have been defined, but are not used inside the class.

Loading history...
1406
    {
1407
        // Implementation of HTTP headers security, as suggested and checked
1408
        // by https://securityheaders.io/
1409
        // Enable these settings in configuration.php to use them on your site
1410
        // Strict-Transport-Security
1411
        $setting = api_get_configuration_value('security_strict_transport');
1412
        if (!empty($setting)) {
1413
            header('Strict-Transport-Security: '.$setting);
1414
        }
1415
        // Content-Security-Policy
1416
        $setting = api_get_configuration_value('security_content_policy');
1417
        if (!empty($setting)) {
1418
            header('Content-Security-Policy: '.$setting);
1419
        }
1420
        $setting = api_get_configuration_value('security_content_policy_report_only');
1421
        if (!empty($setting)) {
1422
            header('Content-Security-Policy-Report-Only: '.$setting);
1423
        }
1424
        // Public-Key-Pins
1425
        $setting = api_get_configuration_value('security_public_key_pins');
1426
        if (!empty($setting)) {
1427
            header('Public-Key-Pins: '.$setting);
1428
        }
1429
        $setting = api_get_configuration_value('security_public_key_pins_report_only');
1430
        if (!empty($setting)) {
1431
            header('Public-Key-Pins-Report-Only: '.$setting);
1432
        }
1433
        // X-Frame-Options
1434
        $setting = api_get_configuration_value('security_x_frame_options');
1435
        if (!empty($setting)) {
1436
            header('X-Frame-Options: '.$setting);
1437
        }
1438
        // X-XSS-Protection
1439
        $setting = api_get_configuration_value('security_xss_protection');
1440
        if (!empty($setting)) {
1441
            header('X-XSS-Protection: '.$setting);
1442
        }
1443
        // X-Content-Type-Options
1444
        $setting = api_get_configuration_value('security_x_content_type_options');
1445
        if (!empty($setting)) {
1446
            header('X-Content-Type-Options: '.$setting);
1447
        }
1448
        // Referrer-Policy
1449
        $setting = api_get_configuration_value('security_referrer_policy');
1450
        if (!empty($setting)) {
1451
            header('Referrer-Policy: '.$setting);
1452
        }
1453
        // end of HTTP headers security block
1454
    }
1455
1456
    /**
1457
     * Assign favicon to the 'favico' template variable.
1458
     *
1459
     * @return bool Always return true because there is always at least one correct favicon.ico
1460
     */
1461
    private function assignFavIcon()
1462
    {
1463
        // Default root chamilo favicon
1464
        $favico = '<link rel="shortcut icon" href="'.api_get_path(WEB_PATH).'favicon.ico" type="image/x-icon" />';
1465
1466
        //Added to verify if in the current Chamilo Theme exist a favicon
1467
        $favicoThemeUrl = api_get_path(SYS_CSS_PATH).$this->themeDir.'images/';
1468
1469
        //If exist pick the current chamilo theme favicon
1470
        if (is_file($favicoThemeUrl.'favicon.ico')) {
1471
            $favico = '<link rel="shortcut icon" href="'.api_get_path(WEB_CSS_PATH).$this->themeDir.'images/favicon.ico" type="image/x-icon" />';
1472
        }
1473
1474
        if (api_is_multiple_url_enabled()) {
1475
            /*$access_url_id = api_get_current_access_url_id();
1476
            if ($access_url_id != -1) {
1477
                $url_info = api_get_access_url($access_url_id);
1478
                $url = api_remove_trailing_slash(
1479
                    preg_replace('/https?:\/\//i', '', $url_info['url'])
1480
                );
1481
                $clean_url = api_replace_dangerous_char($url);
1482
                $clean_url = str_replace('/', '-', $clean_url);
1483
                $clean_url .= '/';
1484
                $homep = api_get_path(REL_PATH).'home/'.$clean_url; //homep for Home Path
1485
                $icon_real_homep = api_get_path(SYS_APP_PATH).'home/'.$clean_url;
1486
                //we create the new dir for the new sites
1487
                if (is_file($icon_real_homep.'favicon.ico')) {
1488
                    $favico = '<link rel="shortcut icon" href="'.$homep.'favicon.ico" type="image/x-icon" />';
1489
                }
1490
            }*/
1491
        }
1492
1493
        $this->assign('favico', $favico);
1494
1495
        return true;
1496
    }
1497
1498
    /**
1499
     * Assign HTML code to the 'accessibility' template variable (usually shown above top menu).
1500
     *
1501
     * @return bool Always return true (even if empty string)
1502
     */
1503
    private function assignAccessibilityBlock()
1504
    {
1505
        $resize = '';
1506
        if ('true' == api_get_setting('accessibility_font_resize')) {
1507
            $resize .= '<div class="resize_font">';
1508
            $resize .= '<div class="btn-group">';
1509
            $resize .= '<a title="'.get_lang('Decrease the font size').'" href="#" class="decrease_font btn btn-default"><em class="fa fa-font"></em></a>';
1510
            $resize .= '<a title="'.get_lang('Reset the font size').'" href="#" class="reset_font btn btn-default"><em class="fa fa-font"></em></a>';
1511
            $resize .= '<a title="'.get_lang('Increase the font size').'" href="#" class="increase_font btn btn-default"><em class="fa fa-font"></em></a>';
1512
            $resize .= '</div>';
1513
            $resize .= '</div>';
1514
        }
1515
        $this->assign('accessibility', $resize);
1516
1517
        return true;
1518
    }
1519
1520
    /**
1521
     * Assign HTML code to the 'social_meta' template variable (usually shown above top menu).
1522
     *
1523
     * @return bool Always return true (even if empty string)
1524
     */
1525
    private function assignSocialMeta()
0 ignored issues
show
Unused Code introduced by
The method assignSocialMeta() is not used, and could be removed.

This check looks for private methods that have been defined, but are not used inside the class.

Loading history...
1526
    {
1527
        $socialMeta = '';
1528
        $metaTitle = api_get_setting('meta_title');
1529
        if (!empty($metaTitle)) {
1530
            $socialMeta .= '<meta name="twitter:card" content="summary" />'."\n";
1531
            $metaSite = api_get_setting('meta_twitter_site');
1532
            if (!empty($metaSite)) {
1533
                $socialMeta .= '<meta name="twitter:site" content="'.$metaSite.'" />'."\n";
1534
                $metaCreator = api_get_setting('meta_twitter_creator');
1535
                if (!empty($metaCreator)) {
1536
                    $socialMeta .= '<meta name="twitter:creator" content="'.$metaCreator.'" />'."\n";
1537
                }
1538
            }
1539
1540
            // The user badge page emits its own meta tags, so if this is
1541
            // enabled, ignore the global ones
1542
            $userId = isset($_GET['user']) ? intval($_GET['user']) : 0;
1543
            $skillId = isset($_GET['skill']) ? intval($_GET['skill']) : 0;
1544
1545
            if (!$userId && !$skillId) {
1546
                // no combination of user and skill ID has been defined,
1547
                // so print the normal or course-specific OpenGraph meta tags
1548
                // Check for a course ID
1549
                $courseId = api_get_course_int_id();
1550
                // Check session ID from session/id/about (see .htaccess)
1551
                $sessionId = isset($_GET['session_id']) ? intval($_GET['session_id']) : 0;
1552
1553
                if (false != $courseId) {
0 ignored issues
show
Bug Best Practice introduced by
It seems like you are loosely comparing $courseId of type integer to the boolean false. If you are specifically checking for non-zero, consider using something more explicit like > 0 or !== 0 instead.
Loading history...
1554
                    // If we are inside a course (even if within a session), publish info about the course
1555
                    $course = api_get_course_entity($courseId);
1556
                    // @TODO: support right-to-left in title
1557
                    $socialMeta .= '<meta property="og:title" content="'.$course->getTitle().' - '.$metaTitle.'" />'."\n";
1558
                    $socialMeta .= '<meta property="twitter:title" content="'.$course->getTitle().' - '.$metaTitle.'" />'."\n";
1559
                    $socialMeta .= '<meta property="og:url" content="'.api_get_course_url($course->getCode()).'" />'."\n";
1560
1561
                    $metaDescription = api_get_setting('meta_description');
1562
                    if (!empty($course->getDescription())) {
1563
                        $socialMeta .= '<meta property="og:description" content="'.strip_tags($course->getDescription()).'" />'."\n";
1564
                        $socialMeta .= '<meta property="twitter:description" content="'.strip_tags($course->getDescription()).'" />'."\n";
1565
                    } elseif (!empty($metaDescription)) {
1566
                        $socialMeta .= '<meta property="og:description" content="'.$metaDescription.'" />'."\n";
1567
                        $socialMeta .= '<meta property="twitter:description" content="'.$metaDescription.'" />'."\n";
1568
                    }
1569
1570
                    $picture = Container::getIllustrationRepository()->getIllustrationUrl($course);
1571
                    if (!empty($picture)) {
1572
                        $socialMeta .= '<meta property="og:image" content="'.$picture.'" />'."\n";
1573
                        $socialMeta .= '<meta property="twitter:image" content="'.$picture.'" />'."\n";
1574
                        $socialMeta .= '<meta property="twitter:image:alt" content="'.$course->getTitle().' - '.$metaTitle.'" />'."\n";
1575
                    } else {
1576
                        $socialMeta .= $this->getMetaPortalImagePath($metaTitle);
1577
                    }
1578
                } elseif (0 !== $sessionId) {
1579
                    // If we are on a session "about" screen, publish info about the session
1580
                    $em = Database::getManager();
1581
                    $session = $em->find('ChamiloCoreBundle:Session', $sessionId);
1582
1583
                    $socialMeta .= '<meta property="og:title" content="'.$session->getName().' - '.$metaTitle.'" />'."\n";
1584
                    $socialMeta .= '<meta property="twitter:title" content="'.$session->getName().' - '.$metaTitle.'" />'."\n";
1585
                    $socialMeta .= '<meta property="og:url" content="'.api_get_path(WEB_PATH)."sessions/{$session->getId()}/about/".'" />'."\n";
1586
1587
                    $sessionValues = new ExtraFieldValue('session');
1588
                    $sessionImage = $sessionValues->get_values_by_handler_and_field_variable($session->getId(), 'image')['value'];
1589
                    $sessionImageSysPath = api_get_path(SYS_UPLOAD_PATH).$sessionImage;
1590
1591
                    if (!empty($sessionImage) && is_file($sessionImageSysPath)) {
1592
                        $sessionImagePath = api_get_path(WEB_UPLOAD_PATH).$sessionImage;
1593
                        $socialMeta .= '<meta property="og:image" content="'.$sessionImagePath.'" />'."\n";
1594
                        $socialMeta .= '<meta property="twitter:image" content="'.$sessionImagePath.'" />'."\n";
1595
                        $socialMeta .= '<meta property="twitter:image:alt" content="'.$session->getName().' - '.$metaTitle.'" />'."\n";
1596
                    } else {
1597
                        $socialMeta .= $this->getMetaPortalImagePath($metaTitle);
1598
                    }
1599
                } else {
1600
                    // Otherwise (not a course nor a session, nor a user, nor a badge), publish portal info
1601
                    $socialMeta .= '<meta property="og:title" content="'.$metaTitle.'" />'."\n";
1602
                    $socialMeta .= '<meta property="twitter:title" content="'.$metaTitle.'" />'."\n";
1603
                    $socialMeta .= '<meta property="og:url" content="'.api_get_path(WEB_PATH).'" />'."\n";
1604
1605
                    $metaDescription = api_get_setting('meta_description');
1606
                    if (!empty($metaDescription)) {
1607
                        $socialMeta .= '<meta property="og:description" content="'.$metaDescription.'" />'."\n";
1608
                        $socialMeta .= '<meta property="twitter:description" content="'.$metaDescription.'" />'."\n";
1609
                    }
1610
                    $socialMeta .= $this->getMetaPortalImagePath($metaTitle);
1611
                }
1612
            }
1613
        }
1614
1615
        $this->assign('social_meta', $socialMeta);
1616
1617
        return true;
1618
    }
1619
1620
    /**
1621
     * Get platform meta image tag (check meta_image_path setting, then use the logo).
1622
     *
1623
     * @param string $imageAlt The alt attribute for the image
1624
     *
1625
     * @return string The meta image HTML tag, or empty
1626
     */
1627
    private function getMetaPortalImagePath($imageAlt = '')
1628
    {
1629
        // Load portal meta image if defined
1630
        $metaImage = api_get_setting('meta_image_path');
1631
        $metaImageSysPath = api_get_path(SYS_PATH).$metaImage;
1632
        $metaImageWebPath = api_get_path(WEB_PATH).$metaImage;
1633
        $portalImageMeta = '';
1634
        if (!empty($metaImage)) {
1635
            if (is_file($metaImageSysPath)) {
1636
                $portalImageMeta = '<meta property="og:image" content="'.$metaImageWebPath.'" />'."\n";
1637
                $portalImageMeta .= '<meta property="twitter:image" content="'.$metaImageWebPath.'" />'."\n";
1638
                $portalImageMeta .= '<meta property="twitter:image:alt" content="'.$imageAlt.'" />'."\n";
1639
            }
1640
        } else {
1641
            $logo = ChamiloApi::getPlatformLogoPath($this->theme);
1642
            if (!empty($logo)) {
1643
                $portalImageMeta = '<meta property="og:image" content="'.$logo.'" />'."\n";
1644
                $portalImageMeta .= '<meta property="twitter:image" content="'.$logo.'" />'."\n";
1645
                $portalImageMeta .= '<meta property="twitter:image:alt" content="'.$imageAlt.'" />'."\n";
1646
            }
1647
        }
1648
1649
        return $portalImageMeta;
1650
    }
1651
}
1652