Completed
Push — master ( 036366...035555 )
by Julito
12:18
created

Template::setVueParams()   A

Complexity

Conditions 3
Paths 4

Size

Total Lines 11
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 3
eloc 7
nc 4
nop 1
dl 0
loc 11
rs 10
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\CoreBundle\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 = '@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) {
0 ignored issues
show
introduced by
$user is of type Chamilo\CoreBundle\Entity\User, thus it always evaluated to true.
Loading history...
684
            $encoded = json_encode($user);
685
        }
686
        $params['user'] = $encoded;
687
688
        $params['from_vue'] = isset($_REQUEST['fromVue']) ? 1 : 0;
689
    }
690
691
    /**
692
     * @param array  $params
693
     * @param string $template
694
     *
695
     * @throws \Twig\Error\Error
696
     */
697
    public function returnResponse($params, $template)
698
    {
699
        $flash = Display::getFlashToString();
700
        Display::cleanFlashMessages();
701
        $response = new Response();
702
        $params['flash_messages'] = $flash;
703
        $content = Container::getTemplating()->render($template, $params);
704
        $response->setContent($content);
705
        $response->send();
706
    }
707
708
    /**
709
     * Special function to declare last-minute JS libraries which depend on
710
     * other things to be declared first. In particular, it might be useful
711
     * under IE9 with compatibility mode, which for some reason is getting
712
     * upset when a variable is used in a function (even if not used yet)
713
     * when this variable hasn't been defined yet.
714
     */
715
    public function set_js_files_post()
716
    {
717
        global $disable_js_and_css_files;
718
        $js_files = [];
719
        if (api_is_global_chat_enabled()) {
720
            //Do not include the global chat in LP
721
            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...
722
                $js_files[] = 'chat/js/chat.js';
723
            }
724
        }
725
        $js_file_to_string = '';
726
        foreach ($js_files as $js_file) {
727
            $js_file_to_string .= api_get_js($js_file);
728
        }
729
        if (!$disable_js_and_css_files) {
730
            $this->assign('js_file_to_string_post', $js_file_to_string);
731
        }
732
    }
733
734
    /**
735
     * @param string $theme
736
     *
737
     * @return string
738
     */
739
    public static function getPortalIcon($theme)
740
    {
741
        // Default root chamilo favicon
742
        $icon = 'favicon.ico';
743
744
        // Added to verify if in the current Chamilo Theme exist a favicon
745
        $themeUrl = api_get_path(SYS_CSS_PATH).'themes/'.$theme.'/images/';
746
747
        // If exist pick the current chamilo theme favicon.
748
        if (is_file($themeUrl.'favicon.ico')) {
749
            $icon = 'build/css/themes/'.$theme.'/images/favicon.ico';
750
        }
751
752
        return $icon;
753
    }
754
755
    /**
756
     * Show footer js template.
757
     */
758
    public function show_footer_js_template()
759
    {
760
        $tpl = $this->get_template('layout/footer.js.tpl');
761
        $this->display($tpl);
762
    }
763
764
    /**
765
     * @param string $template
766
     *
767
     * @return string
768
     */
769
    public function fetch($template = null)
770
    {
771
        return $this->twig->render($template, $this->params);
772
    }
773
774
    /**
775
     * @param string $variable
776
     * @param mixed  $value
777
     */
778
    public function assign($variable, $value = '')
779
    {
780
        $this->params[$variable] = $value;
781
    }
782
783
    /**
784
     * Adds a body class for login pages.
785
     */
786
    public function setLoginBodyClass()
787
    {
788
        $this->assign('login_class', 'section-login');
789
    }
790
791
    /**
792
     * The theme that will be used if the database is not working.
793
     *
794
     * @return string
795
     */
796
    public static function getThemeFallback()
797
    {
798
        $theme = api_get_configuration_value('theme_fallback');
799
        if (empty($theme)) {
800
            $theme = 'chamilo';
801
        }
802
803
        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...
804
    }
805
806
    /**
807
     * @return string
808
     */
809
    public function handleLoginFailed()
810
    {
811
        $message = get_lang('Login failed - incorrect login or password.');
812
813
        if (!isset($_GET['error'])) {
814
            if (api_is_self_registration_allowed()) {
815
                $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>');
816
            }
817
        } else {
818
            switch ($_GET['error']) {
819
                case '':
820
                    if (api_is_self_registration_allowed()) {
821
                        $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>');
822
                    }
823
                    break;
824
                case 'account_expired':
825
                    $message = get_lang('Account expired');
826
                    break;
827
                case 'account_inactive':
828
                    $message = get_lang('Account inactive');
829
830
                    if ('confirmation' === api_get_setting('allow_registration')) {
831
                        $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;
832
                        $message .= Display::url(
833
                            get_lang('Send confirmation mail again'),
834
                            api_get_path(WEB_PATH).'main/auth/resend_confirmation_mail.php',
835
                            ['class' => 'alert-link']
836
                        );
837
                    }
838
                    break;
839
                case 'user_password_incorrect':
840
                    $message = get_lang('Login failed - incorrect login or password.');
841
                    break;
842
                case 'access_url_inactive':
843
                    $message = get_lang('Account inactive for this URL');
844
                    break;
845
                case 'wrong_captcha':
846
                    $message = get_lang('The text you entered doesn\'t match the picture.');
847
                    break;
848
                case 'blocked_by_captcha':
849
                    $message = get_lang('Account blocked by captcha.');
850
                    break;
851
                case 'multiple_connection_not_allowed':
852
                    $message = get_lang('This user is already logged in');
853
                    break;
854
            }
855
        }
856
857
        return Display::return_message($message, 'error', false);
858
    }
859
860
    /**
861
     * @return string
862
     */
863
    public function displayLoginForm()
864
    {
865
        $form = new FormValidator(
866
            'form-login',
867
            'POST',
868
            api_get_path(WEB_PUBLIC_PATH).'login_check',
869
            null,
870
            null,
871
            FormValidator::LAYOUT_BOX_NO_LABEL
872
        );
873
        $params = [
874
            'id' => '_username',
875
            'autofocus' => 'autofocus',
876
            'icon' => 'user fa-fw',
877
            'placeholder' => get_lang('Username'),
878
        ];
879
        $browserAutoCapitalize = false;
880
        // Avoid showing the autocapitalize option if the browser doesn't
881
        // support it: this attribute is against the HTML5 standard
882
        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

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

1090
            $allow = TicketManager::userIsAllowInProject(/** @scrutinizer ignore-type */ api_get_user_info(), $defaultProjectId);
Loading history...
1091
1092
            if ($allow) {
1093
                $rightFloatMenu .= '<div class="help">
1094
                    <a href="'.$url.'" target="_blank">
1095
                        '.$iconTicket.'
1096
                    </a>
1097
                </div>';
1098
            }
1099
        }
1100
1101
        $this->assign('bug_notification', $rightFloatMenu);
1102
1103
        return true;
1104
    }
1105
1106
    /**
1107
     * Load legacy params.
1108
     */
1109
    private function loadLegacyParams()
1110
    {
1111
        // Set legacy breadcrumb
1112
        global $interbreadcrumb;
1113
        $this->params['legacy_breadcrumb'] = $interbreadcrumb;
1114
1115
        global $htmlHeadXtra;
1116
        $this->params['legacy_javascript'] = $htmlHeadXtra;
1117
    }
1118
1119
    /**
1120
     * Prepare the _c array for template files. The _c array contains
1121
     * information about the current course.
1122
     */
1123
    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...
1124
    {
1125
        //Setting course id
1126
        $course = api_get_course_info();
1127
        if (empty($course)) {
1128
            $this->assign('course_is_set', false);
1129
1130
            return;
1131
        }
1132
        $this->assign('course_is_set', true);
1133
        $this->course_id = $course['id'];
1134
        $_c = [
1135
            'id' => $course['real_id'],
1136
            'code' => $course['code'],
1137
            'title' => $course['name'],
1138
            'visibility' => $course['visibility'],
1139
            'language' => $course['language'],
1140
            'directory' => $course['directory'],
1141
            'session_id' => api_get_session_id(),
1142
            'user_is_teacher' => api_is_course_admin(),
1143
            'student_view' => (!empty($_GET['isStudentView']) && 'true' == $_GET['isStudentView']),
1144
        ];
1145
        $this->assign('course_code', $course['code']);
1146
        $this->assign('_c', $_c);
1147
    }
1148
1149
    /**
1150
     * Prepare the _u array for template files. The _u array contains
1151
     * information about the current user, as returned by
1152
     * api_get_user_info().
1153
     */
1154
    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...
1155
    {
1156
        $user_info = [];
1157
        $user_info['logged'] = 0;
1158
        $this->user_is_logged_in = false;
1159
        if (api_user_is_login()) {
1160
            $user_info = api_get_user_info(api_get_user_id(), true);
1161
            $user_info['logged'] = 1;
1162
1163
            $user_info['is_admin'] = 0;
1164
            if (api_is_platform_admin()) {
1165
                $user_info['is_admin'] = 1;
1166
            }
1167
1168
            $user_info['messages_count'] = MessageManager::getCountNewMessages();
1169
            $this->user_is_logged_in = true;
1170
        }
1171
        // Setting the $_u array that could be use in any template
1172
        $this->assign('_u', $user_info);
1173
    }
1174
1175
    /**
1176
     * Set header parameters.
1177
     *
1178
     * @deprecated
1179
     *
1180
     * @param bool $sendHeaders send headers
1181
     */
1182
    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...
1183
    {
1184
        global $httpHeadXtra, $interbreadcrumb, $language_file, $_configuration, $this_section;
1185
        $_course = api_get_course_info();
1186
        $nameTools = $this->title;
1187
        $navigation = return_navigation_array();
1188
        $this->menu_navigation = $navigation['menu_navigation'];
1189
1190
        $this->assign('system_charset', api_get_system_encoding());
1191
1192
        if (isset($httpHeadXtra) && $httpHeadXtra) {
1193
            foreach ($httpHeadXtra as &$thisHttpHead) {
1194
                //header($thisHttpHead);
1195
            }
1196
        }
1197
1198
        $this->assign(
1199
            'online_button',
1200
            Display::return_icon('statusonline.png', null, [], ICON_SIZE_ATOM)
1201
        );
1202
        $this->assign(
1203
            'offline_button',
1204
            Display::return_icon('statusoffline.png', null, [], ICON_SIZE_ATOM)
1205
        );
1206
1207
        // Get language iso-code for this page - ignore errors
1208
        $this->assign('document_language', api_get_language_isocode());
1209
1210
        $course_title = isset($_course['name']) ? $_course['name'] : null;
1211
1212
        $title_list = [];
1213
1214
        $title_list[] = api_get_setting('Institution');
1215
        $title_list[] = api_get_setting('siteName');
1216
1217
        if (!empty($course_title)) {
1218
            $title_list[] = $course_title;
1219
        }
1220
        if ('' != $nameTools) {
1221
            $title_list[] = $nameTools;
1222
        }
1223
1224
        $title_string = '';
1225
        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...
1226
            $title_string .= $title_list[$i];
1227
            if (isset($title_list[$i + 1])) {
1228
                $item = trim($title_list[$i + 1]);
1229
                if (!empty($item)) {
1230
                    $title_string .= ' - ';
1231
                }
1232
            }
1233
        }
1234
1235
        $this->assign('title_string', $title_string);
1236
1237
        // Setting the theme and CSS files
1238
        $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

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

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