Completed
Push — master ( 4fc9f8...d0e06e )
by Julito
12:04
created

Template::setCssCustomFiles()   B

Complexity

Conditions 9
Paths 72

Size

Total Lines 54
Code Lines 26

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 9
eloc 26
nc 72
nop 0
dl 0
loc 54
rs 8.0555
c 0
b 0
f 0

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
/* For licensing terms, see /license.txt */
4
5
use Chamilo\CoreBundle\Entity\SessionRelCourseRelUser;
6
use Chamilo\CoreBundle\Entity\User;
7
use Chamilo\CoreBundle\Framework\Container;
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,
69
        $show_footer = true,
70
        $show_learnpath = false,
71
        $hide_global_chat = false,
72
        $load_plugins = true,
73
        $sendHeaders = true,
74
        $responseCode = 0
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;
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 = '@ChamiloCore/Layout/layout_one_col.html.twig';
215
        $origin = api_get_origin();
216
        if ('learnpath' === $origin) {
217
            $template = '@ChamiloCore/Layout/no_layout.html.twig';
218
        }
219
        $this->setVueParams($this->params);
220
        $this->returnResponse($this->params, $template);
221
    }
222
223
    /**
224
     * Displays an empty template.
225
     */
226
    public function display_blank_template()
227
    {
228
        $this->loadLegacyParams();
229
        $template = '@ChamiloCore/Layout/blank.html.twig';
230
        $this->returnResponse($this->params, $template);
231
    }
232
233
    /**
234
     * Displays an empty template.
235
     */
236
    public function displayBlankTemplateNoHeader()
237
    {
238
        $this->loadLegacyParams();
239
        $template = '@ChamiloCore/Layout/blank_no_header.html.twig';
240
        $this->returnResponse($this->params, $template);
241
    }
242
243
    /**
244
     * Displays an empty template.
245
     */
246
    public function display_no_layout_template()
247
    {
248
        $this->loadLegacyParams();
249
        $template = '@ChamiloCore/Layout/no_layout.html.twig';
250
        $this->returnResponse($this->params, $template);
251
    }
252
253
    /**
254
     * Displays an empty template.
255
     */
256
    public function displaySkillLayout()
257
    {
258
        $this->loadLegacyParams();
259
        $template = '@ChamiloCore/Layout/skill_layout.html.twig';
260
        $this->returnResponse($this->params, $template);
261
    }
262
263
    /**
264
     * return true if toolbar has to be displayed for user.
265
     *
266
     * @return bool
267
     */
268
    public static function isToolBarDisplayedForUser()
269
    {
270
        //Toolbar
271
        $show_admin_toolbar = api_get_setting('show_admin_toolbar');
272
        $show_toolbar = false;
273
274
        switch ($show_admin_toolbar) {
275
            case 'do_not_show':
276
                break;
277
            case 'show_to_admin':
278
                if (api_is_platform_admin()) {
279
                    $show_toolbar = true;
280
                }
281
                break;
282
            case 'show_to_admin_and_teachers':
283
                if (api_is_platform_admin() || api_is_allowed_to_edit()) {
284
                    $show_toolbar = true;
285
                }
286
                break;
287
            case 'show_to_all':
288
                $show_toolbar = true;
289
                break;
290
        }
291
292
        return $show_toolbar;
293
    }
294
295
    /**
296
     * Sets the header visibility.
297
     *
298
     * @param bool true if we show the header
299
     */
300
    public function set_header($status)
301
    {
302
        $this->show_header = $status;
303
        $this->assign('show_header', $status);
304
305
        $show_toolbar = 0;
306
307
        if (self::isToolBarDisplayedForUser()) {
308
            $show_toolbar = 1;
309
        }
310
311
        $this->assign('show_toolbar', $show_toolbar);
312
313
        // Only if course is available
314
        $courseToolBar = '';
315
        $show_course_navigation_menu = '';
316
        if (!empty($this->course_id) && $this->user_is_logged_in) {
317
            if ('false' !== api_get_setting('show_toolshortcuts')) {
318
                // Course toolbar
319
                $courseToolBar = CourseHome::show_navigation_tool_shortcuts();
320
            }
321
            if ('false' !== api_get_setting('show_navigation_menu')) {
322
                //Course toolbar
323
                $show_course_navigation_menu = CourseHome::show_navigation_menu();
324
            }
325
        }
326
        $this->assign('show_course_shortcut', $courseToolBar);
327
        $this->assign('show_course_navigation_menu', $show_course_navigation_menu);
328
    }
329
330
    /**
331
     * Returns the sub-folder and filename for the given tpl file.
332
     *
333
     * If template not found in overrides/ or custom template folder, the default template will be used.
334
     *
335
     * @param string $name
336
     *
337
     * @return string
338
     */
339
    public static function findTemplateFilePath($name)
340
    {
341
        $sysTemplatePath = api_get_path(SYS_TEMPLATE_PATH);
342
343
        // Check if the tpl file is present in the main/template/overrides/ dir
344
        // Overrides is a special directory meant for temporary template
345
        // customization. It must be taken into account before anything else
346
        if (is_readable($sysTemplatePath."overrides/$name")) {
347
            return "overrides/$name";
348
        }
349
350
        $defaultFolder = api_get_configuration_value('default_template');
351
352
        // If a template folder has been manually defined, search for the right
353
        // file, and if not found, go for the same file in the default template
354
        if ($defaultFolder && 'default' != $defaultFolder) {
355
            // Avoid missing template error, use the default file.
356
            if (file_exists($sysTemplatePath."$defaultFolder/$name")) {
357
                return "$defaultFolder/$name";
358
            }
359
        }
360
361
        $name = str_replace('tpl', 'html.twig', $name);
362
363
        return "default/$name";
364
    }
365
366
    /**
367
     * Call non-static for Template::findTemplateFilePath.
368
     *
369
     * @see Template::findTemplateFilePath()
370
     *
371
     * @param string $name
372
     *
373
     * @return string
374
     */
375
    public function get_template($name)
376
    {
377
        return api_find_template($name);
378
    }
379
380
    /**
381
     * Get CSS themes sub-directory.
382
     *
383
     * @param string $theme
384
     *
385
     * @return string with a trailing slash, e.g. 'themes/chamilo_red/'
386
     */
387
    public static function getThemeDir($theme)
388
    {
389
        $themeDir = 'themes/'.$theme.'/';
390
        $virtualTheme = api_get_configuration_value('virtual_css_theme_folder');
391
        if (!empty($virtualTheme)) {
392
            $virtualThemeList = api_get_themes(true);
393
            $isVirtualTheme = in_array($theme, array_keys($virtualThemeList));
394
            if ($isVirtualTheme) {
395
                $themeDir = 'themes/'.$virtualTheme.'/'.$theme.'/';
396
            }
397
        }
398
399
        return $themeDir;
400
    }
401
402
    /**
403
     * Set legacy twig globals in order to be hook in the LegacyListener.php.
404
     *
405
     * @return array
406
     */
407
    public static function getGlobals()
408
    {
409
        return [
410
            '_s' => [
411
                'software_name' => api_get_configuration_value('software_name'),
412
                'system_version' => api_get_configuration_value('system_version'),
413
                'site_name' => api_get_setting('siteName'),
414
                'institution' => api_get_setting('Institution'),
415
                'gamification_mode' => api_get_setting('gamification_mode'),
416
            ],
417
            'template' => 'default', // @todo setup template folder in config.yml;
418
        ];
419
    }
420
421
    /**
422
     * Set theme, include mainstream CSS files.
423
     *
424
     * @deprecated
425
     * @see setCssCustomFiles() for additional CSS sheets
426
     */
427
    public function setCssFiles()
428
    {
429
        global $disable_js_and_css_files;
430
        $css = [];
431
432
        // Default CSS Bootstrap
433
        $bowerCSSFiles = [
434
            'fontawesome/css/font-awesome.min.css',
435
            'jquery-ui/themes/smoothness/theme.css',
436
            'jquery-ui/themes/smoothness/jquery-ui.min.css',
437
            'mediaelement/build/mediaelementplayer.min.css',
438
            'jqueryui-timepicker-addon/dist/jquery-ui-timepicker-addon.min.css',
439
            'bootstrap/dist/css/bootstrap.min.css',
440
            'jquery.scrollbar/jquery.scrollbar.css',
441
            //'bootstrap-daterangepicker/daterangepicker.css',
442
            'bootstrap-select/dist/css/bootstrap-select.min.css',
443
            'select2/dist/css/select2.min.css',
444
            'flag-icon-css/css/flag-icon.min.css',
445
            'mediaelement/plugins/vrview/vrview.css',
446
        ];
447
448
        $features = api_get_configuration_value('video_features');
449
        $defaultFeatures = ['playpause', 'current', 'progress', 'duration', 'tracks', 'volume', 'fullscreen', 'vrview'];
450
451
        if (!empty($features) && isset($features['features'])) {
452
            foreach ($features['features'] as $feature) {
453
                if ('vrview' === $feature) {
454
                    continue;
455
                }
456
                $bowerCSSFiles[] = "mediaelement/plugins/$feature/$feature.css";
457
                $defaultFeatures[] = $feature;
458
            }
459
        }
460
461
        foreach ($bowerCSSFiles as $file) {
462
            //$css[] = api_get_path(WEB_PUBLIC_PATH).'assets/'.$file;
463
        }
464
465
        //$css[] = api_get_path(WEB_LIBRARY_PATH).'javascript/chosen/chosen.css';
466
467
        if (api_is_global_chat_enabled()) {
468
            $css[] = api_get_path(WEB_LIBRARY_PATH).'javascript/chat/css/chat.css';
469
        }
470
        $css_file_to_string = '';
471
        foreach ($css as $file) {
472
            $css_file_to_string .= api_get_css($file);
473
        }
474
475
        if (!$disable_js_and_css_files) {
476
            $this->assign('css_static_file_to_string', $css_file_to_string);
477
        }
478
479
        $defaultFeatures = implode("','", $defaultFeatures);
480
        $this->assign('video_features', $defaultFeatures);
481
    }
482
483
    /**
484
     * Prepare custom CSS to be added at the very end of the <head> section.
485
     *
486
     * @see setCssFiles() for the mainstream CSS files
487
     */
488
    public function setCssCustomFiles()
489
    {
490
        global $disable_js_and_css_files;
491
        $css = [];
492
        if ($this->show_learnpath) {
493
            if (is_file(api_get_path(SYS_CSS_PATH).$this->themeDir.'learnpath.css')) {
494
                $css[] = api_get_path(WEB_CSS_PATH).$this->themeDir.'learnpath.css';
495
            }
496
        }
497
498
        $css_file_to_string = '';
499
        foreach ($css as $file) {
500
            $css_file_to_string .= api_get_css($file);
501
        }
502
503
        // @todo move this somewhere else. Special fix when using tablets in order to see the text near icons
504
        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...
505
            //hack in order to fix the actions buttons
506
            $css_file_to_string .= '<style>
507
                .td_actions a {
508
                    float:left;
509
                    width:100%;
510
                }
511
                .forum_message_left a {
512
                    float:left;
513
                    width:100%;
514
                }
515
                </style>';
516
        }
517
518
        $navigator_info = api_get_navigator();
519
        if ('Internet Explorer' == $navigator_info['name'] && '6' == $navigator_info['version']) {
520
            $css_file_to_string .= 'img, div { behavior: url('.api_get_path(WEB_LIBRARY_PATH).'javascript/iepngfix/iepngfix.htc) } '."\n";
521
        }
522
523
        if (!$disable_js_and_css_files) {
524
            $this->assign('css_custom_file_to_string', $css_file_to_string);
525
526
            $style_print = '';
527
            if (is_readable(api_get_path(SYS_CSS_PATH).$this->theme.'/print.css')) {
528
                $style_print = api_get_css(
529
                    api_get_path(WEB_CSS_PATH).$this->theme.'/print.css',
530
                    'print'
531
                );
532
            }
533
            $this->assign('css_style_print', $style_print);
534
        }
535
536
        // Logo
537
        $logo = return_logo($this->theme);
538
        $logoPdf = return_logo($this->theme, false);
539
        $this->assign('logo', $logo);
540
        $this->assign('logo_pdf', $logoPdf);
541
        $this->assign('show_media_element', 1);
542
    }
543
544
    /**
545
     * Declare and define the template variable that will be used to load
546
     * javascript libraries in the header.
547
     */
548
    public function set_js_files()
549
    {
550
        global $disable_js_and_css_files, $htmlHeadXtra;
551
        $isoCode = api_get_language_isocode();
552
        $selectLink = 'bootstrap-select/dist/js/i18n/defaults-'.$isoCode.'_'.strtoupper($isoCode).'.min.js';
553
554
        if ('en' == $isoCode) {
555
            $selectLink = 'bootstrap-select/dist/js/i18n/defaults-'.$isoCode.'_US.min.js';
556
        }
557
        // JS files
558
        $js_files = [
559
            'chosen/chosen.jquery.min.js',
560
        ];
561
562
        $viewBySession = 'true' === api_get_setting('my_courses_view_by_session');
563
564
        if (api_is_global_chat_enabled() || $viewBySession) {
565
            // Do not include the global chat in LP
566
            if (false == $this->show_learnpath &&
567
                true == $this->show_footer &&
568
                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...
569
            ) {
570
                $js_files[] = 'chat/js/chat.js';
571
            }
572
        }
573
574
        if ('true' === api_get_setting('accessibility_font_resize')) {
575
            $js_files[] = 'fontresize.js';
576
        }
577
578
        $js_file_to_string = '';
579
        $bowerJsFiles = [
580
            'modernizr/modernizr.js',
581
            'jquery/query.min.js',
582
            'bootstrap/dist/js/bootstrap.min.js',
583
            'jquery-ui/jquery-ui.min.js',
584
            'jqueryui-touch-punch/jquery.ui.touch-punch.min.js',
585
            'moment/min/moment-with-locales.js',
586
            //'bootstrap-daterangepicker/daterangepicker.js',
587
            'jquery-timeago/jquery.timeago.js',
588
            'mediaelement/mediaelement-and-player.min.js',
589
            'jqueryui-timepicker-addon/dist/jquery-ui-timepicker-addon.min.js',
590
            'image-map-resizer/js/imageMapResizer.min.js',
591
            'jquery.scrollbar/jquery.scrollbar.min.js',
592
            //'readmore-js/readmore.min.js',
593
            'bootstrap-select/dist/js/bootstrap-select.min.js',
594
            $selectLink,
595
            'select2/dist/js/select2.min.js',
596
            "select2/dist/js/i18n/$isoCode.js",
597
            'mediaelement/plugins/vrview/vrview.js',
598
        ];
599
600
        $features = api_get_configuration_value('video_features');
601
        if (!empty($features) && isset($features['features'])) {
602
            foreach ($features['features'] as $feature) {
603
                if ('vrview' === $feature) {
604
                    continue;
605
                }
606
                $bowerJsFiles[] = "mediaelement/plugins/$feature/$feature.js";
607
            }
608
        }
609
610
        if (CHAMILO_LOAD_WYSIWYG === true) {
611
            $bowerJsFiles[] = 'ckeditor/ckeditor.js';
612
        }
613
614
        if ('true' === api_get_setting('include_asciimathml_script')) {
615
            $bowerJsFiles[] = 'MathJax/MathJax.js?config=TeX-MML-AM_HTMLorMML';
616
        }
617
618
        if ('en' != $isoCode) {
619
            $bowerJsFiles[] = 'jqueryui-timepicker-addon/dist/i18n/jquery-ui-timepicker-'.$isoCode.'.js';
620
            $bowerJsFiles[] = 'jquery-ui/ui/minified/i18n/datepicker-'.$isoCode.'.min.js';
621
        }
622
623
        foreach ($bowerJsFiles as $file) {
624
            //$js_file_to_string .= '<script type="text/javascript" src="'.api_get_path(WEB_PUBLIC_PATH).'assets/'.$file.'"></script>'."\n";
625
        }
626
627
        foreach ($js_files as $file) {
628
            //$js_file_to_string .= api_get_js($file);
629
        }
630
631
        // Loading email_editor js
632
        if (!api_is_anonymous() && 'true' == api_get_setting('allow_email_editor')) {
633
            $template = $this->get_template('mail_editor/email_link.js.tpl');
634
            $js_file_to_string .= $this->fetch($template);
635
        }
636
637
        if (!$disable_js_and_css_files) {
638
            $this->assign('js_file_to_string', $js_file_to_string);
639
            $extraHeaders = '';
640
            //$extraHeaders = '<script>var _p = '.json_encode($this->getWebPaths(), JSON_PRETTY_PRINT).'</script>';
641
            //Adding jquery ui by default
642
            $extraHeaders .= api_get_jquery_ui_js();
643
            if (isset($htmlHeadXtra) && $htmlHeadXtra) {
644
                foreach ($htmlHeadXtra as &$this_html_head) {
645
                    $extraHeaders .= $this_html_head."\n";
646
                }
647
            }
648
649
            $ajax = api_get_path(WEB_AJAX_PATH);
650
            $courseId = api_get_course_id();
651
            if (empty($courseId)) {
652
                $courseLogoutCode = '
653
                <script>
654
                function courseLogout() {
655
                }
656
                </script>';
657
            } else {
658
                $courseLogoutCode = "
659
                <script>
660
                var logOutUrl = '".$ajax."course.ajax.php?a=course_logout&".api_get_cidreq()."';
661
                function courseLogout() {
662
                    $.ajax({
663
                        async : false,
664
                        url: logOutUrl,
665
                        success: function (data) {
666
                            return 1;
667
                        }
668
                    });
669
                }
670
                </script>";
671
            }
672
673
            $extraHeaders .= $courseLogoutCode;
674
            $this->assign('extra_headers', $extraHeaders);
675
        }
676
    }
677
678
    public static function setVueParams(&$params)
679
    {
680
        $params['is_authenticated'] = !api_is_anonymous();
681
        /*$user = api_get_user_entity(api_get_user_id());
682
        $encoded = '';
683
        if ($user) {
684
            $encoded = json_encode($user);
685
        }
686
        $params['user'] = $encoded;*/
687
        $params['from_vue'] = isset($_REQUEST['from_vue']) ? 1 : 0;
688
    }
689
690
    /**
691
     * @param array  $params
692
     * @param string $template
693
     *
694
     * @throws \Twig\Error\Error
695
     */
696
    public function returnResponse($params, $template)
697
    {
698
        $flash = Display::getFlashToString();
699
        Display::cleanFlashMessages();
700
        $response = new Response();
701
        $params['flash_messages'] = $flash;
702
        $content = Container::getTemplating()->render($template, $params);
703
        $response->setContent($content);
704
        $response->send();
705
    }
706
707
    /**
708
     * Special function to declare last-minute JS libraries which depend on
709
     * other things to be declared first. In particular, it might be useful
710
     * under IE9 with compatibility mode, which for some reason is getting
711
     * upset when a variable is used in a function (even if not used yet)
712
     * when this variable hasn't been defined yet.
713
     */
714
    public function set_js_files_post()
715
    {
716
        global $disable_js_and_css_files;
717
        $js_files = [];
718
        if (api_is_global_chat_enabled()) {
719
            //Do not include the global chat in LP
720
            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...
721
                $js_files[] = 'chat/js/chat.js';
722
            }
723
        }
724
        $js_file_to_string = '';
725
        foreach ($js_files as $js_file) {
726
            $js_file_to_string .= api_get_js($js_file);
727
        }
728
        if (!$disable_js_and_css_files) {
729
            $this->assign('js_file_to_string_post', $js_file_to_string);
730
        }
731
    }
732
733
    /**
734
     * @param string $theme
735
     *
736
     * @return string
737
     */
738
    public static function getPortalIcon($theme)
739
    {
740
        // Default root chamilo favicon
741
        $icon = 'favicon.ico';
742
743
        // Added to verify if in the current Chamilo Theme exist a favicon
744
        $themeUrl = api_get_path(SYS_CSS_PATH).'themes/'.$theme.'/images/';
745
746
        // If exist pick the current chamilo theme favicon.
747
        if (is_file($themeUrl.'favicon.ico')) {
748
            $icon = 'build/css/themes/'.$theme.'/images/favicon.ico';
749
        }
750
751
        return $icon;
752
    }
753
754
    /**
755
     * Show footer js template.
756
     */
757
    public function show_footer_js_template()
758
    {
759
        $tpl = $this->get_template('layout/footer.js.tpl');
760
        $this->display($tpl);
761
    }
762
763
    /**
764
     * @param string $template
765
     *
766
     * @return string
767
     */
768
    public function fetch($template = null)
769
    {
770
        return $this->twig->render($template, $this->params);
771
    }
772
773
    /**
774
     * @param string $variable
775
     * @param mixed  $value
776
     */
777
    public function assign($variable, $value = '')
778
    {
779
        $this->params[$variable] = $value;
780
    }
781
782
    /**
783
     * Adds a body class for login pages.
784
     */
785
    public function setLoginBodyClass()
786
    {
787
        $this->assign('login_class', 'section-login');
788
    }
789
790
    /**
791
     * The theme that will be used if the database is not working.
792
     *
793
     * @return string
794
     */
795
    public static function getThemeFallback()
796
    {
797
        $theme = api_get_configuration_value('theme_fallback');
798
        if (empty($theme)) {
799
            $theme = 'chamilo';
800
        }
801
802
        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...
803
    }
804
805
    /**
806
     * @return string
807
     */
808
    public function handleLoginFailed()
809
    {
810
        $message = get_lang('Login failed - incorrect login or password.');
811
812
        if (!isset($_GET['error'])) {
813
            if (api_is_self_registration_allowed()) {
814
                $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>');
815
            }
816
        } else {
817
            switch ($_GET['error']) {
818
                case '':
819
                    if (api_is_self_registration_allowed()) {
820
                        $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>');
821
                    }
822
                    break;
823
                case 'account_expired':
824
                    $message = get_lang('Account expired');
825
                    break;
826
                case 'account_inactive':
827
                    $message = get_lang('Account inactive');
828
829
                    if ('confirmation' === api_get_setting('allow_registration')) {
830
                        $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;
831
                        $message .= Display::url(
832
                            get_lang('Send confirmation mail again'),
833
                            api_get_path(WEB_PATH).'main/auth/resend_confirmation_mail.php',
834
                            ['class' => 'alert-link']
835
                        );
836
                    }
837
                    break;
838
                case 'user_password_incorrect':
839
                    $message = get_lang('Login failed - incorrect login or password.');
840
                    break;
841
                case 'access_url_inactive':
842
                    $message = get_lang('Account inactive for this URL');
843
                    break;
844
                case 'wrong_captcha':
845
                    $message = get_lang('The text you entered doesn\'t match the picture.');
846
                    break;
847
                case 'blocked_by_captcha':
848
                    $message = get_lang('Account blocked by captcha.');
849
                    break;
850
                case 'multiple_connection_not_allowed':
851
                    $message = get_lang('This user is already logged in');
852
                    break;
853
            }
854
        }
855
856
        return Display::return_message($message, 'error', false);
857
    }
858
859
    /**
860
     * @return string
861
     */
862
    public function displayLoginForm()
863
    {
864
        $form = new FormValidator(
865
            'form-login',
866
            'POST',
867
            api_get_path(WEB_PUBLIC_PATH).'login_check',
868
            null,
869
            null,
870
            FormValidator::LAYOUT_BOX_NO_LABEL
871
        );
872
        $params = [
873
            'id' => '_username',
874
            'autofocus' => 'autofocus',
875
            'icon' => 'user fa-fw',
876
            'placeholder' => get_lang('Username'),
877
        ];
878
        $browserAutoCapitalize = false;
879
        // Avoid showing the autocapitalize option if the browser doesn't
880
        // support it: this attribute is against the HTML5 standard
881
        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

881
        if (/** @scrutinizer ignore-deprecated */ api_browser_support('autocapitalize')) {
Loading history...
882
            $browserAutoCapitalize = false;
883
            $params['autocapitalize'] = 'none';
884
        }
885
        $form->addText(
886
            '_username',
887
            get_lang('Username'),
888
            true,
889
            $params
890
        );
891
        $params = [
892
            'id' => '_password',
893
            'icon' => 'lock fa-fw',
894
            'placeholder' => get_lang('Pass'),
895
        ];
896
        if ($browserAutoCapitalize) {
897
            $params['autocapitalize'] = 'none';
898
        }
899
        $form->addElement(
900
            'password',
901
            '_password',
902
            get_lang('Pass'),
903
            $params
904
        );
905
906
        $token = Chamilo\CoreBundle\Framework\Container::$container->get('security.csrf.token_manager')->getToken('authenticate');
907
        $form->addHidden('_csrf_token', $token->getValue());
908
909
        // Captcha
910
        $captcha = api_get_setting('allow_captcha');
911
        $allowCaptcha = 'true' === $captcha;
912
913
        if ($allowCaptcha) {
914
            $useCaptcha = isset($_SESSION['loginFailed']) ? $_SESSION['loginFailed'] : null;
915
            if ($useCaptcha) {
916
                $ajax = api_get_path(WEB_AJAX_PATH).'form.ajax.php?a=get_captcha';
917
                $options = [
918
                    'width' => 250,
919
                    'height' => 90,
920
                    'callback' => $ajax.'&var='.basename(__FILE__, '.php'),
921
                    'sessionVar' => basename(__FILE__, '.php'),
922
                    'imageOptions' => [
923
                        'font_size' => 20,
924
                        'font_path' => api_get_path(SYS_FONTS_PATH).'opensans/',
925
                        'font_file' => 'OpenSans-Regular.ttf',
926
                        //'output' => 'gif'
927
                    ],
928
                ];
929
930
                // Minimum options using all defaults (including defaults for Image_Text):
931
                //$options = array('callback' => 'qfcaptcha_image.php');
932
                $captcha_question = $form->addElement('CAPTCHA_Image', 'captcha_question', '', $options);
933
                $form->addHtml(get_lang('Click on the image to load a new one.'));
934
935
                $form->addElement(
936
                    'text',
937
                    'captcha',
938
                    get_lang('Enter the letters you see.')
939
                );
940
                $form->addRule(
941
                    'captcha',
942
                    get_lang('Enter the characters you see on the image'),
943
                    'required',
944
                    null,
945
                    'client'
946
                );
947
                $form->addRule(
948
                    'captcha',
949
                    get_lang('The text you entered doesn\'t match the picture.'),
950
                    'CAPTCHA',
951
                    $captcha_question
952
                );
953
            }
954
        }
955
956
        $form->addButton(
957
            'submitAuth',
958
            get_lang('Login'),
959
            null,
960
            'primary',
961
            null,
962
            'btn-block'
963
        );
964
965
        $html = $form->returnForm();
966
967
        return $html;
968
    }
969
970
    /**
971
     * Returns the tutors names for the current course in session
972
     * Function to use in Twig templates.
973
     *
974
     * @return string
975
     */
976
    public static function returnTutorsNames()
977
    {
978
        $em = Database::getManager();
979
        $tutors = $em
980
            ->createQuery('
981
                SELECT u FROM ChamiloCoreBundle:User u
982
                INNER JOIN ChamiloCoreBundle:SessionRelCourseRelUser scu WITH u.id = scu.user
983
                WHERE scu.status = :teacher_status AND scu.session = :session AND scu.course = :course
984
            ')
985
            ->setParameters([
986
                'teacher_status' => SessionRelCourseRelUser::STATUS_COURSE_COACH,
987
                'session' => api_get_session_id(),
988
                'course' => api_get_course_int_id(),
989
            ])
990
            ->getResult();
991
992
        $names = [];
993
994
        /** @var User $tutor */
995
        foreach ($tutors as $tutor) {
996
            $names[] = UserManager::formatUserFullName($tutor);
997
        }
998
999
        return implode(CourseManager::USER_SEPARATOR, $names);
1000
    }
1001
1002
    /*s
1003
     * Returns the teachers name for the current course
1004
     * Function to use in Twig templates
1005
     * @return string
1006
     */
1007
    public static function returnTeachersNames()
1008
    {
1009
        $em = Database::getManager();
1010
        $teachers = $em
1011
            ->createQuery('
1012
                SELECT u FROM ChamiloCoreBundle:User u
1013
                INNER JOIN ChamiloCoreBundle:CourseRelUser cu WITH u.id = cu.user
1014
                WHERE cu.status = :teacher_status AND cu.course = :course
1015
            ')
1016
            ->setParameters([
1017
                'teacher_status' => User::COURSE_MANAGER,
1018
                'course' => api_get_course_int_id(),
1019
            ])
1020
            ->getResult();
1021
1022
        $names = [];
1023
1024
        /** @var User $teacher */
1025
        foreach ($teachers as $teacher) {
1026
            $names[] = UserManager::formatUserFullName($teacher);
1027
        }
1028
1029
        return implode(CourseManager::USER_SEPARATOR, $names);
1030
    }
1031
1032
    /**
1033
     * @param int $code
1034
     */
1035
    public function setResponseCode($code)
1036
    {
1037
        $this->responseCode = $code;
1038
    }
1039
1040
    /**
1041
     * @param string $code
1042
     */
1043
    public function getResponseCode()
1044
    {
1045
        return $this->responseCode;
1046
    }
1047
1048
    /**
1049
     * Assign HTML code to the 'bug_notification' template variable for the side tabs to report issues.
1050
     *
1051
     * @return bool Always return true because there is always a string, even if empty
1052
     */
1053
    public function assignBugNotification()
1054
    {
1055
        //@todo move this in the template
1056
        $rightFloatMenu = '';
1057
        $iconBug = Display::return_icon(
1058
            'bug.png',
1059
            get_lang('Report a bug'),
1060
            [],
1061
            ICON_SIZE_LARGE
1062
        );
1063
        if ('true' === api_get_setting('show_link_bug_notification') && $this->user_is_logged_in) {
1064
            $rightFloatMenu = '<div class="report">
1065
		        <a href="https://github.com/chamilo/chamilo-lms/wiki/How-to-report-issues" target="_blank">
1066
                    '.$iconBug.'
1067
                </a>
1068
		        </div>';
1069
        }
1070
1071
        if ('true' === api_get_setting('show_link_ticket_notification') &&
1072
            $this->user_is_logged_in
1073
        ) {
1074
            // by default is project_id = 1
1075
            $defaultProjectId = 1;
1076
            $iconTicket = Display::return_icon(
1077
                'help.png',
1078
                get_lang('Ticket'),
1079
                [],
1080
                ICON_SIZE_LARGE
1081
            );
1082
            $courseInfo = api_get_course_info();
1083
            $courseParams = '';
1084
            if (!empty($courseInfo)) {
1085
                $courseParams = api_get_cidreq();
1086
            }
1087
            $url = api_get_path(WEB_CODE_PATH).'ticket/tickets.php?project_id='.$defaultProjectId.'&'.$courseParams;
1088
1089
            $allow = TicketManager::userIsAllowInProject(api_get_user_info(), $defaultProjectId);
1090
1091
            if ($allow) {
1092
                $rightFloatMenu .= '<div class="help">
1093
                    <a href="'.$url.'" target="_blank">
1094
                        '.$iconTicket.'
1095
                    </a>
1096
                </div>';
1097
            }
1098
        }
1099
1100
        $this->assign('bug_notification', $rightFloatMenu);
1101
1102
        return true;
1103
    }
1104
1105
    /**
1106
     * Load legacy params.
1107
     */
1108
    private function loadLegacyParams()
1109
    {
1110
        // Set legacy breadcrumb
1111
        global $interbreadcrumb;
1112
        $this->params['legacy_breadcrumb'] = $interbreadcrumb;
1113
1114
        global $htmlHeadXtra;
1115
        $this->params['legacy_javascript'] = $htmlHeadXtra;
1116
    }
1117
1118
    /**
1119
     * Prepare the _c array for template files. The _c array contains
1120
     * information about the current course.
1121
     */
1122
    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...
1123
    {
1124
        //Setting course id
1125
        $course = api_get_course_info();
1126
        if (empty($course)) {
1127
            $this->assign('course_is_set', false);
1128
1129
            return;
1130
        }
1131
        $this->assign('course_is_set', true);
1132
        $this->course_id = $course['id'];
1133
        $_c = [
1134
            'id' => $course['real_id'],
1135
            'code' => $course['code'],
1136
            'title' => $course['name'],
1137
            'visibility' => $course['visibility'],
1138
            'language' => $course['language'],
1139
            'directory' => $course['directory'],
1140
            'session_id' => api_get_session_id(),
1141
            'user_is_teacher' => api_is_course_admin(),
1142
            'student_view' => (!empty($_GET['isStudentView']) && 'true' == $_GET['isStudentView']),
1143
        ];
1144
        $this->assign('course_code', $course['code']);
1145
        $this->assign('_c', $_c);
1146
    }
1147
1148
    /**
1149
     * Prepare the _u array for template files. The _u array contains
1150
     * information about the current user, as returned by
1151
     * api_get_user_info().
1152
     */
1153
    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...
1154
    {
1155
        $user_info = [];
1156
        $user_info['logged'] = 0;
1157
        $this->user_is_logged_in = false;
1158
        if (api_user_is_login()) {
1159
            $user_info = api_get_user_info(api_get_user_id(), true);
1160
            $user_info['logged'] = 1;
1161
1162
            $user_info['is_admin'] = 0;
1163
            if (api_is_platform_admin()) {
1164
                $user_info['is_admin'] = 1;
1165
            }
1166
1167
            $user_info['messages_count'] = MessageManager::getCountNewMessages();
1168
            $this->user_is_logged_in = true;
1169
        }
1170
        // Setting the $_u array that could be use in any template
1171
        $this->assign('_u', $user_info);
1172
    }
1173
1174
    /**
1175
     * Set header parameters.
1176
     *
1177
     * @deprecated
1178
     *
1179
     * @param bool $sendHeaders send headers
1180
     */
1181
    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...
1182
    {
1183
        global $httpHeadXtra, $interbreadcrumb, $language_file, $_configuration, $this_section;
1184
        $_course = api_get_course_info();
1185
        $nameTools = $this->title;
1186
        $navigation = return_navigation_array();
1187
        $this->menu_navigation = $navigation['menu_navigation'];
1188
1189
        $this->assign('system_charset', api_get_system_encoding());
1190
1191
        if (isset($httpHeadXtra) && $httpHeadXtra) {
1192
            foreach ($httpHeadXtra as &$thisHttpHead) {
1193
                //header($thisHttpHead);
1194
            }
1195
        }
1196
1197
        $this->assign(
1198
            'online_button',
1199
            Display::return_icon('statusonline.png', null, [], ICON_SIZE_ATOM)
1200
        );
1201
        $this->assign(
1202
            'offline_button',
1203
            Display::return_icon('statusoffline.png', null, [], ICON_SIZE_ATOM)
1204
        );
1205
1206
        // Get language iso-code for this page - ignore errors
1207
        $this->assign('document_language', api_get_language_isocode());
1208
1209
        $course_title = isset($_course['name']) ? $_course['name'] : null;
1210
1211
        $title_list = [];
1212
1213
        $title_list[] = api_get_setting('Institution');
1214
        $title_list[] = api_get_setting('siteName');
1215
1216
        if (!empty($course_title)) {
1217
            $title_list[] = $course_title;
1218
        }
1219
        if ('' != $nameTools) {
1220
            $title_list[] = $nameTools;
1221
        }
1222
1223
        $title_string = '';
1224
        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...
1225
            $title_string .= $title_list[$i];
1226
            if (isset($title_list[$i + 1])) {
1227
                $item = trim($title_list[$i + 1]);
1228
                if (!empty($item)) {
1229
                    $title_string .= ' - ';
1230
                }
1231
            }
1232
        }
1233
1234
        $this->assign('title_string', $title_string);
1235
1236
        // Setting the theme and CSS files
1237
        $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

1237
        /** @scrutinizer ignore-deprecated */ $this->setCssFiles();
Loading history...
1238
        $this->set_js_files();
1239
        $this->setCssCustomFiles();
1240
1241
        $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

1241
        $browser = /** @scrutinizer ignore-deprecated */ api_browser_support('check_browser');
Loading history...
1242
        if ('Internet Explorer' == $browser[0] && $browser[1] >= '11') {
1243
            $browser_head = '<meta http-equiv="X-UA-Compatible" content="IE=EmulateIE9" />';
1244
            $this->assign('browser_specific_head', $browser_head);
1245
        }
1246
1247
        // Implementation of prefetch.
1248
        // See http://cdn.chamilo.org/main/img/online.png for details
1249
        $prefetch = '';
1250
        if (!empty($_configuration['cdn_enable'])) {
1251
            $prefetch .= '<meta http-equiv="x-dns-prefetch-control" content="on">';
1252
            foreach ($_configuration['cdn'] as $host => $exts) {
1253
                $prefetch .= '<link rel="dns-prefetch" href="'.$host.'">';
1254
            }
1255
        }
1256
1257
        $this->assign('prefetch', $prefetch);
1258
        $this->assign('text_direction', api_get_text_direction());
1259
        $this->assign('section_name', 'section-'.$this_section);
1260
        $this->assignFavIcon();
1261
        $this->setHelp();
1262
1263
        $this->assignBugNotification(); //Prepare the 'bug_notification' var for the template
1264
1265
        $this->assignAccessibilityBlock(); //Prepare the 'accessibility' var for the template
1266
1267
        // Preparing values for the menu
1268
1269
        // Logout link
1270
        $hideLogout = api_get_setting('hide_logout_button');
1271
        if ('true' === $hideLogout) {
1272
            $this->assign('logout_link', null);
1273
        } else {
1274
            $this->assign('logout_link', api_get_path(WEB_PATH).'index.php?logout=logout&uid='.api_get_user_id());
1275
        }
1276
1277
        // Profile link
1278
        if ('true' == api_get_setting('allow_social_tool')) {
1279
            $profile_url = api_get_path(WEB_CODE_PATH).'social/home.php';
1280
        } else {
1281
            $profile_url = api_get_path(WEB_CODE_PATH).'auth/profile.php';
1282
        }
1283
1284
        $this->assign('profile_url', $profile_url);
1285
1286
        //Message link
1287
        $message_link = null;
1288
        $message_url = null;
1289
        if ('true' == api_get_setting('allow_message_tool')) {
1290
            $message_url = api_get_path(WEB_CODE_PATH).'messages/inbox.php';
1291
            $message_link = '<a href="'.api_get_path(WEB_CODE_PATH).'messages/inbox.php">'.get_lang('Inbox').'</a>';
1292
        }
1293
        $this->assign('message_link', $message_link);
1294
        $this->assign('message_url', $message_url);
1295
1296
        $pendingSurveyLink = '';
1297
        $show = api_get_configuration_value('show_pending_survey_in_menu');
1298
        if ($show) {
1299
            $pendingSurveyLink = api_get_path(WEB_CODE_PATH).'survey/pending.php';
1300
        }
1301
        $this->assign('pending_survey_url', $pendingSurveyLink);
1302
1303
        // Certificate Link
1304
        $allow = api_get_configuration_value('certificate.hide_my_certificate_link');
1305
        if (false === $allow) {
1306
            $certificateUrl = api_get_path(WEB_CODE_PATH).'gradebook/my_certificates.php';
1307
            $certificateLink = Display::url(
1308
                get_lang('My certificates'),
1309
                $certificateUrl
1310
            );
1311
            $this->assign('certificate_link', $certificateLink);
1312
            $this->assign('certificate_url', $certificateUrl);
1313
        }
1314
1315
        $institution = api_get_setting('Institution');
1316
        $portal_name = empty($institution) ? api_get_setting('siteName') : $institution;
1317
1318
        $this->assign('portal_name', $portal_name);
1319
1320
        //Menu
1321
        //$menu = menuArray();
1322
        //$this->assign('menu', $menu);
1323
1324
        $breadcrumb = '';
1325
        // Hide breadcrumb in LP
1326
        if (false == $this->show_learnpath) {
1327
            $breadcrumb = return_breadcrumb(
1328
                $interbreadcrumb,
1329
                $language_file,
1330
                $nameTools
1331
            );
1332
        }
1333
        $this->assign('breadcrumb', $breadcrumb);
1334
1335
        //Extra content
1336
        $extra_header = null;
1337
        if (!api_is_platform_admin()) {
1338
            $extra_header = trim(api_get_setting('header_extra_content'));
1339
        }
1340
        $this->assign('header_extra_content', $extra_header);
1341
1342
        if ($sendHeaders) {
1343
            /*header('Content-Type: text/html; charset='.api_get_system_encoding());
1344
            header(
1345
                'X-Powered-By: '.$_configuration['software_name'].' '.substr($_configuration['system_version'], 0, 1)
1346
            );
1347
            self::addHTTPSecurityHeaders();*/
1348
1349
            $responseCode = $this->getResponseCode();
1350
            if (!empty($responseCode)) {
1351
                switch ($responseCode) {
1352
                    case '404':
1353
                        header("HTTP/1.0 404 Not Found");
1354
                        break;
1355
                }
1356
            }
1357
        }
1358
1359
        $socialMeta = '';
1360
        $metaTitle = api_get_setting('meta_title');
1361
        if (!empty($metaTitle)) {
1362
            $socialMeta .= '<meta name="twitter:card" content="summary" />'."\n";
1363
            $metaSite = api_get_setting('meta_twitter_site');
1364
            if (!empty($metaSite)) {
1365
                $socialMeta .= '<meta name="twitter:site" content="'.$metaSite.'" />'."\n";
1366
                $metaCreator = api_get_setting('meta_twitter_creator');
1367
                if (!empty($metaCreator)) {
1368
                    $socialMeta .= '<meta name="twitter:creator" content="'.$metaCreator.'" />'."\n";
1369
                }
1370
            }
1371
1372
            // The user badge page emits its own meta tags, so if this is
1373
            // enabled, ignore the global ones
1374
            $userId = isset($_GET['user']) ? intval($_GET['user']) : 0;
1375
            $skillId = isset($_GET['skill']) ? intval($_GET['skill']) : 0;
1376
1377
            if (!$userId && !$skillId) {
1378
                // no combination of user and skill ID has been defined,
1379
                // so print the normal OpenGraph meta tags
1380
                $socialMeta .= '<meta property="og:title" content="'.$metaTitle.'" />'."\n";
1381
                $socialMeta .= '<meta property="og:url" content="'.api_get_path(WEB_PATH).'" />'."\n";
1382
1383
                $metaDescription = api_get_setting('meta_description');
1384
                if (!empty($metaDescription)) {
1385
                    $socialMeta .= '<meta property="og:description" content="'.$metaDescription.'" />'."\n";
1386
                }
1387
1388
                $metaImage = api_get_setting('meta_image_path');
1389
                if (!empty($metaImage)) {
1390
                    if (is_file(api_get_path(SYS_PATH).$metaImage)) {
1391
                        $path = api_get_path(WEB_PATH).$metaImage;
1392
                        $socialMeta .= '<meta property="og:image" content="'.$path.'" />'."\n";
1393
                    }
1394
                }
1395
            }
1396
        }
1397
1398
        $this->assign('social_meta', $socialMeta);
1399
    }
1400
1401
    /**
1402
     * Set footer parameters.
1403
     */
1404
    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...
1405
    {
1406
        // Loading footer extra content
1407
        if (!api_is_platform_admin()) {
1408
            $extra_footer = trim(api_get_setting('footer_extra_content'));
1409
            if (!empty($extra_footer)) {
1410
                $this->assign('footer_extra_content', $extra_footer);
1411
            }
1412
        }
1413
    }
1414
1415
    /**
1416
     * Manage specific HTTP headers security.
1417
     */
1418
    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...
1419
    {
1420
        // Implementation of HTTP headers security, as suggested and checked
1421
        // by https://securityheaders.io/
1422
        // Enable these settings in configuration.php to use them on your site
1423
        // Strict-Transport-Security
1424
        $setting = api_get_configuration_value('security_strict_transport');
1425
        if (!empty($setting)) {
1426
            header('Strict-Transport-Security: '.$setting);
1427
        }
1428
        // Content-Security-Policy
1429
        $setting = api_get_configuration_value('security_content_policy');
1430
        if (!empty($setting)) {
1431
            header('Content-Security-Policy: '.$setting);
1432
        }
1433
        $setting = api_get_configuration_value('security_content_policy_report_only');
1434
        if (!empty($setting)) {
1435
            header('Content-Security-Policy-Report-Only: '.$setting);
1436
        }
1437
        // Public-Key-Pins
1438
        $setting = api_get_configuration_value('security_public_key_pins');
1439
        if (!empty($setting)) {
1440
            header('Public-Key-Pins: '.$setting);
1441
        }
1442
        $setting = api_get_configuration_value('security_public_key_pins_report_only');
1443
        if (!empty($setting)) {
1444
            header('Public-Key-Pins-Report-Only: '.$setting);
1445
        }
1446
        // X-Frame-Options
1447
        $setting = api_get_configuration_value('security_x_frame_options');
1448
        if (!empty($setting)) {
1449
            header('X-Frame-Options: '.$setting);
1450
        }
1451
        // X-XSS-Protection
1452
        $setting = api_get_configuration_value('security_xss_protection');
1453
        if (!empty($setting)) {
1454
            header('X-XSS-Protection: '.$setting);
1455
        }
1456
        // X-Content-Type-Options
1457
        $setting = api_get_configuration_value('security_x_content_type_options');
1458
        if (!empty($setting)) {
1459
            header('X-Content-Type-Options: '.$setting);
1460
        }
1461
        // Referrer-Policy
1462
        $setting = api_get_configuration_value('security_referrer_policy');
1463
        if (!empty($setting)) {
1464
            header('Referrer-Policy: '.$setting);
1465
        }
1466
        // end of HTTP headers security block
1467
    }
1468
1469
    /**
1470
     * Assign favicon to the 'favico' template variable.
1471
     *
1472
     * @return bool Always return true because there is always at least one correct favicon.ico
1473
     */
1474
    private function assignFavIcon()
1475
    {
1476
        // Default root chamilo favicon
1477
        $favico = '<link rel="shortcut icon" href="'.api_get_path(WEB_PATH).'favicon.ico" type="image/x-icon" />';
1478
1479
        //Added to verify if in the current Chamilo Theme exist a favicon
1480
        $favicoThemeUrl = api_get_path(SYS_CSS_PATH).$this->themeDir.'images/';
1481
1482
        //If exist pick the current chamilo theme favicon
1483
        if (is_file($favicoThemeUrl.'favicon.ico')) {
1484
            $favico = '<link rel="shortcut icon" href="'.api_get_path(WEB_CSS_PATH).$this->themeDir.'images/favicon.ico" type="image/x-icon" />';
1485
        }
1486
1487
        if (api_is_multiple_url_enabled()) {
1488
            /*$access_url_id = api_get_current_access_url_id();
1489
            if ($access_url_id != -1) {
1490
                $url_info = api_get_access_url($access_url_id);
1491
                $url = api_remove_trailing_slash(
1492
                    preg_replace('/https?:\/\//i', '', $url_info['url'])
1493
                );
1494
                $clean_url = api_replace_dangerous_char($url);
1495
                $clean_url = str_replace('/', '-', $clean_url);
1496
                $clean_url .= '/';
1497
                $homep = api_get_path(REL_PATH).'home/'.$clean_url; //homep for Home Path
1498
                $icon_real_homep = api_get_path(SYS_APP_PATH).'home/'.$clean_url;
1499
                //we create the new dir for the new sites
1500
                if (is_file($icon_real_homep.'favicon.ico')) {
1501
                    $favico = '<link rel="shortcut icon" href="'.$homep.'favicon.ico" type="image/x-icon" />';
1502
                }
1503
            }*/
1504
        }
1505
1506
        $this->assign('favico', $favico);
1507
1508
        return true;
1509
    }
1510
1511
    /**
1512
     * Assign HTML code to the 'accessibility' template variable (usually shown above top menu).
1513
     *
1514
     * @return bool Always return true (even if empty string)
1515
     */
1516
    private function assignAccessibilityBlock()
1517
    {
1518
        $resize = '';
1519
        if ('true' == api_get_setting('accessibility_font_resize')) {
1520
            $resize .= '<div class="resize_font">';
1521
            $resize .= '<div class="btn-group">';
1522
            $resize .= '<a title="'.get_lang('Decrease the font size').'" href="#" class="decrease_font btn btn-default"><em class="fa fa-font"></em></a>';
1523
            $resize .= '<a title="'.get_lang('Reset the font size').'" href="#" class="reset_font btn btn-default"><em class="fa fa-font"></em></a>';
1524
            $resize .= '<a title="'.get_lang('Increase the font size').'" href="#" class="increase_font btn btn-default"><em class="fa fa-font"></em></a>';
1525
            $resize .= '</div>';
1526
            $resize .= '</div>';
1527
        }
1528
        $this->assign('accessibility', $resize);
1529
1530
        return true;
1531
    }
1532
1533
    /**
1534
     * Assign HTML code to the 'social_meta' template variable (usually shown above top menu).
1535
     *
1536
     * @return bool Always return true (even if empty string)
1537
     */
1538
    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...
1539
    {
1540
        $socialMeta = '';
1541
        $metaTitle = api_get_setting('meta_title');
1542
        if (!empty($metaTitle)) {
1543
            $socialMeta .= '<meta name="twitter:card" content="summary" />'."\n";
1544
            $metaSite = api_get_setting('meta_twitter_site');
1545
            if (!empty($metaSite)) {
1546
                $socialMeta .= '<meta name="twitter:site" content="'.$metaSite.'" />'."\n";
1547
                $metaCreator = api_get_setting('meta_twitter_creator');
1548
                if (!empty($metaCreator)) {
1549
                    $socialMeta .= '<meta name="twitter:creator" content="'.$metaCreator.'" />'."\n";
1550
                }
1551
            }
1552
1553
            // The user badge page emits its own meta tags, so if this is
1554
            // enabled, ignore the global ones
1555
            $userId = isset($_GET['user']) ? intval($_GET['user']) : 0;
1556
            $skillId = isset($_GET['skill']) ? intval($_GET['skill']) : 0;
1557
1558
            if (!$userId && !$skillId) {
1559
                // no combination of user and skill ID has been defined,
1560
                // so print the normal or course-specific OpenGraph meta tags
1561
                // Check for a course ID
1562
                $courseId = api_get_course_int_id();
1563
                // Check session ID from session/id/about (see .htaccess)
1564
                $sessionId = isset($_GET['session_id']) ? intval($_GET['session_id']) : 0;
1565
1566
                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...
1567
                    // If we are inside a course (even if within a session), publish info about the course
1568
                    $course = api_get_course_entity($courseId);
1569
                    // @TODO: support right-to-left in title
1570
                    $socialMeta .= '<meta property="og:title" content="'.$course->getTitle().' - '.$metaTitle.'" />'."\n";
1571
                    $socialMeta .= '<meta property="twitter:title" content="'.$course->getTitle().' - '.$metaTitle.'" />'."\n";
1572
                    $socialMeta .= '<meta property="og:url" content="'.api_get_course_url($course->getCode()).'" />'."\n";
1573
1574
                    $metaDescription = api_get_setting('meta_description');
1575
                    if (!empty($course->getDescription())) {
1576
                        $socialMeta .= '<meta property="og:description" content="'.strip_tags($course->getDescription()).'" />'."\n";
1577
                        $socialMeta .= '<meta property="twitter:description" content="'.strip_tags($course->getDescription()).'" />'."\n";
1578
                    } elseif (!empty($metaDescription)) {
1579
                        $socialMeta .= '<meta property="og:description" content="'.$metaDescription.'" />'."\n";
1580
                        $socialMeta .= '<meta property="twitter:description" content="'.$metaDescription.'" />'."\n";
1581
                    }
1582
1583
                    $picture = Container::getIllustrationRepository()->getIllustrationUrl($course);
1584
                    if (!empty($picture)) {
1585
                        $socialMeta .= '<meta property="og:image" content="'.$picture.'" />'."\n";
1586
                        $socialMeta .= '<meta property="twitter:image" content="'.$picture.'" />'."\n";
1587
                        $socialMeta .= '<meta property="twitter:image:alt" content="'.$course->getTitle().' - '.$metaTitle.'" />'."\n";
1588
                    } else {
1589
                        $socialMeta .= $this->getMetaPortalImagePath($metaTitle);
1590
                    }
1591
                } elseif (0 !== $sessionId) {
1592
                    // If we are on a session "about" screen, publish info about the session
1593
                    $em = Database::getManager();
1594
                    $session = $em->find('ChamiloCoreBundle:Session', $sessionId);
1595
1596
                    $socialMeta .= '<meta property="og:title" content="'.$session->getName().' - '.$metaTitle.'" />'."\n";
1597
                    $socialMeta .= '<meta property="twitter:title" content="'.$session->getName().' - '.$metaTitle.'" />'."\n";
1598
                    $socialMeta .= '<meta property="og:url" content="'.api_get_path(WEB_PATH)."sessions/{$session->getId()}/about/".'" />'."\n";
1599
1600
                    $sessionValues = new ExtraFieldValue('session');
1601
                    $sessionImage = $sessionValues->get_values_by_handler_and_field_variable($session->getId(), 'image')['value'];
1602
                    $sessionImageSysPath = api_get_path(SYS_UPLOAD_PATH).$sessionImage;
1603
1604
                    if (!empty($sessionImage) && is_file($sessionImageSysPath)) {
1605
                        $sessionImagePath = api_get_path(WEB_UPLOAD_PATH).$sessionImage;
1606
                        $socialMeta .= '<meta property="og:image" content="'.$sessionImagePath.'" />'."\n";
1607
                        $socialMeta .= '<meta property="twitter:image" content="'.$sessionImagePath.'" />'."\n";
1608
                        $socialMeta .= '<meta property="twitter:image:alt" content="'.$session->getName().' - '.$metaTitle.'" />'."\n";
1609
                    } else {
1610
                        $socialMeta .= $this->getMetaPortalImagePath($metaTitle);
1611
                    }
1612
                } else {
1613
                    // Otherwise (not a course nor a session, nor a user, nor a badge), publish portal info
1614
                    $socialMeta .= '<meta property="og:title" content="'.$metaTitle.'" />'."\n";
1615
                    $socialMeta .= '<meta property="twitter:title" content="'.$metaTitle.'" />'."\n";
1616
                    $socialMeta .= '<meta property="og:url" content="'.api_get_path(WEB_PATH).'" />'."\n";
1617
1618
                    $metaDescription = api_get_setting('meta_description');
1619
                    if (!empty($metaDescription)) {
1620
                        $socialMeta .= '<meta property="og:description" content="'.$metaDescription.'" />'."\n";
1621
                        $socialMeta .= '<meta property="twitter:description" content="'.$metaDescription.'" />'."\n";
1622
                    }
1623
                    $socialMeta .= $this->getMetaPortalImagePath($metaTitle);
1624
                }
1625
            }
1626
        }
1627
1628
        $this->assign('social_meta', $socialMeta);
1629
1630
        return true;
1631
    }
1632
1633
    /**
1634
     * Get platform meta image tag (check meta_image_path setting, then use the logo).
1635
     *
1636
     * @param string $imageAlt The alt attribute for the image
1637
     *
1638
     * @return string The meta image HTML tag, or empty
1639
     */
1640
    private function getMetaPortalImagePath($imageAlt = '')
1641
    {
1642
        // Load portal meta image if defined
1643
        $metaImage = api_get_setting('meta_image_path');
1644
        $metaImageSysPath = api_get_path(SYS_PATH).$metaImage;
1645
        $metaImageWebPath = api_get_path(WEB_PATH).$metaImage;
1646
        $portalImageMeta = '';
1647
        if (!empty($metaImage)) {
1648
            if (is_file($metaImageSysPath)) {
1649
                $portalImageMeta = '<meta property="og:image" content="'.$metaImageWebPath.'" />'."\n";
1650
                $portalImageMeta .= '<meta property="twitter:image" content="'.$metaImageWebPath.'" />'."\n";
1651
                $portalImageMeta .= '<meta property="twitter:image:alt" content="'.$imageAlt.'" />'."\n";
1652
            }
1653
        } else {
1654
            $logo = ChamiloApi::getPlatformLogoPath($this->theme);
1655
            if (!empty($logo)) {
1656
                $portalImageMeta = '<meta property="og:image" content="'.$logo.'" />'."\n";
1657
                $portalImageMeta .= '<meta property="twitter:image" content="'.$logo.'" />'."\n";
1658
                $portalImageMeta .= '<meta property="twitter:image:alt" content="'.$imageAlt.'" />'."\n";
1659
            }
1660
        }
1661
1662
        return $portalImageMeta;
1663
    }
1664
}
1665