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

67
        /** @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...
68
        $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

68
        /** @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...
69
        $show_learnpath = false,
70
        $hide_global_chat = false,
71
        $load_plugins = true,
72
        $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

72
        /** @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...
73
        $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

73
        /** @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...
74
    ) {
75
        // Page title
76
        $this->title = $title;
77
        $this->show_learnpath = $show_learnpath;
78
        //$this->setResponseCode($responseCode);
79
80
        if (empty($this->show_learnpath)) {
81
            $origin = api_get_origin();
82
            if ($origin === 'learnpath') {
83
                $this->show_learnpath = true;
84
                $show_footer = false;
85
                $show_header = false;
86
            }
87
        }
88
        $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...
89
        $this->load_plugins = $load_plugins;
90
91
        /*$template_paths = [
92
            api_get_path(SYS_CODE_PATH).'template/overrides', // user defined templates
93
            api_get_path(SYS_CODE_PATH).'template', //template folder
94
            api_get_path(SYS_PLUGIN_PATH), // plugin folder
95
            api_get_path(SYS_PATH).'src/ThemeBundle/Resources/views',
96
        ];*/
97
98
        $this->twig = Container::getTwig();
99
100
        // Setting system variables
101
        //$this->set_system_parameters();
102
103
        // Setting user variables
104
        //$this->set_user_parameters();
105
106
        // Setting course variables
107
        //$this->set_course_parameters();
108
109
        // Setting administrator variables
110
        //$this->setAdministratorParams();
111
        //$this->setCSSEditor();
112
113
        // Header and footer are showed by default
114
        //$this->set_footer($show_footer);
115
        //$this->set_header($show_header);
116
117
        //$this->set_header_parameters($sendHeaders);
118
        //$this->set_footer_parameters();
119
120
        $defaultStyle = api_get_setting('display.default_template');
121
        if (!empty($defaultStyle)) {
122
            $this->templateFolder = $defaultStyle;
123
        }
124
    }
125
126
    /**
127
     * Return the item's url key:.
128
     *
129
     *      c_id=xx&id=xx
130
     *
131
     * @param object $item
132
     *
133
     * @return string
134
     */
135
    public static function key($item)
136
    {
137
        $id = isset($item->id) ? $item->id : null;
138
        $c_id = isset($item->c_id) ? $item->c_id : null;
139
        $result = '';
140
        if ($c_id) {
141
            $result = "c_id=$c_id";
142
        }
143
        if ($id) {
144
            if ($result) {
145
                $result .= "&amp;id=$id";
146
            } else {
147
                $result .= "&amp;id=$id";
148
            }
149
        }
150
151
        return $result;
152
    }
153
154
    /**
155
     * @param string $helpInput
156
     */
157
    public function setHelp($helpInput = null)
158
    {
159
        if (!empty($helpInput)) {
160
            $help = $helpInput;
161
        } else {
162
            $help = $this->help;
163
        }
164
165
        $content = '';
166
        if (api_get_setting('enable_help_link') == 'true') {
167
            if (!empty($help)) {
168
                $help = Security::remove_XSS($help);
169
                $content = '<div class="help">';
170
                $content .= Display::url(
171
                    Display::return_icon('help.png', get_lang('Help'), null, ICON_SIZE_LARGE),
172
                    api_get_path(WEB_CODE_PATH).'help/help.php?open='.$help,
173
                    [
174
                        'class' => 'ajax',
175
                        'data-title' => get_lang('Help'),
176
                    ]
177
                );
178
                $content .= '</div>';
179
            }
180
        }
181
        $this->assign('help_content', $content);
182
    }
183
184
    /**
185
     * Use template system to parse the actions menu.
186
     *
187
     * @todo finish it!
188
     */
189
    public function set_actions($actions)
190
    {
191
        $action_string = '';
192
        if (!empty($actions)) {
193
            foreach ($actions as $action) {
194
                $action_string .= $action;
195
            }
196
        }
197
        $this->assign('actions', $actions);
198
    }
199
200
    /**
201
     * Render the template.
202
     *
203
     * @param string $template           The template path
204
     * @param bool   $clearFlashMessages Clear the $_SESSION variables for flash messages
205
     */
206
    public function display($template)
207
    {
208
        $template = str_replace('tpl', 'html.twig', $template);
209
        $templateFile = api_get_path(SYS_PATH).'main/template/'.$template;
210
211
        $this->loadLegacyParams();
212
213
        if (!file_exists($templateFile)) {
214
            $e = new \Gaufrette\Exception\FileNotFound($templateFile);
215
            echo $e->getMessage();
216
            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...
217
        }
218
219
        $this->returnResponse($this->params, $template);
220
    }
221
222
    /**
223
     * @param string $template
224
     *
225
     * @throws \Twig\Error\Error
226
     */
227
    public function displayTemplate($template)
228
    {
229
        $this->loadLegacyParams();
230
        $this->returnResponse($this->params, $template);
231
    }
232
233
    /**
234
     * Shortcut to display a 1 col layout (index.php).
235
     * */
236
    public function display_one_col_template()
237
    {
238
        $this->loadLegacyParams();
239
        $template = '@ChamiloTheme/Layout/layout_one_col.html.twig';
240
        $this->returnResponse($this->params, $template);
241
    }
242
243
    /**
244
     * Displays an empty template.
245
     */
246
    public function display_blank_template()
247
    {
248
        $this->loadLegacyParams();
249
        $template = '@ChamiloTheme/Layout/blank.html.twig';
250
        $this->returnResponse($this->params, $template);
251
    }
252
253
    /**
254
     * Displays an empty template.
255
     */
256
    public function displayBlankTemplateNoHeader()
257
    {
258
        $this->loadLegacyParams();
259
        $template = '@ChamiloTheme/Layout/blank_no_header.html.twig';
260
        $this->returnResponse($this->params, $template);
261
    }
262
263
    /**
264
     * Displays an empty template.
265
     */
266
    public function display_no_layout_template()
267
    {
268
        $this->loadLegacyParams();
269
        $template = '@ChamiloTheme/Layout/no_layout.html.twig';
270
        $this->returnResponse($this->params, $template);
271
    }
272
273
    /**
274
     * Displays an empty template.
275
     */
276
    public function displaySkillLayout()
277
    {
278
        $this->loadLegacyParams();
279
        $template = '@ChamiloTheme/Layout/skill_layout.html.twig';
280
        $this->returnResponse($this->params, $template);
281
    }
282
283
    /**
284
     * return true if toolbar has to be displayed for user.
285
     *
286
     * @return bool
287
     */
288
    public static function isToolBarDisplayedForUser()
289
    {
290
        //Toolbar
291
        $show_admin_toolbar = api_get_setting('show_admin_toolbar');
292
        $show_toolbar = false;
293
294
        switch ($show_admin_toolbar) {
295
            case 'do_not_show':
296
                break;
297
            case 'show_to_admin':
298
                if (api_is_platform_admin()) {
299
                    $show_toolbar = true;
300
                }
301
                break;
302
            case 'show_to_admin_and_teachers':
303
                if (api_is_platform_admin() || api_is_allowed_to_edit()) {
304
                    $show_toolbar = true;
305
                }
306
                break;
307
            case 'show_to_all':
308
                $show_toolbar = true;
309
                break;
310
        }
311
312
        return $show_toolbar;
313
    }
314
315
    /**
316
     * Sets the header visibility.
317
     *
318
     * @param bool true if we show the header
319
     */
320
    public function set_header($status)
321
    {
322
        $this->show_header = $status;
323
        $this->assign('show_header', $status);
324
325
        $show_toolbar = 0;
326
327
        if (self::isToolBarDisplayedForUser()) {
328
            $show_toolbar = 1;
329
        }
330
331
        $this->assign('show_toolbar', $show_toolbar);
332
333
        // Only if course is available
334
        $courseToolBar = '';
335
        $show_course_navigation_menu = '';
336
        if (!empty($this->course_id) && $this->user_is_logged_in) {
337
            if (api_get_setting('show_toolshortcuts') !== 'false') {
338
                // Course toolbar
339
                $courseToolBar = CourseHome::show_navigation_tool_shortcuts();
340
            }
341
            if (api_get_setting('show_navigation_menu') !== 'false') {
342
                //Course toolbar
343
                $show_course_navigation_menu = CourseHome::show_navigation_menu();
344
            }
345
        }
346
        $this->assign('show_course_shortcut', $courseToolBar);
347
        $this->assign('show_course_navigation_menu', $show_course_navigation_menu);
348
    }
349
350
    /**
351
     * Returns the sub-folder and filename for the given tpl file.
352
     *
353
     * If template not found in overrides/ or custom template folder, the default template will be used.
354
     *
355
     * @param string $name
356
     *
357
     * @return string
358
     */
359
    public static function findTemplateFilePath($name)
360
    {
361
        $sysTemplatePath = api_get_path(SYS_TEMPLATE_PATH);
362
363
        // Check if the tpl file is present in the main/template/overrides/ dir
364
        // Overrides is a special directory meant for temporary template
365
        // customization. It must be taken into account before anything else
366
        if (is_readable($sysTemplatePath."overrides/$name")) {
367
            return "overrides/$name";
368
        }
369
370
        $defaultFolder = api_get_configuration_value('default_template');
371
372
        // If a template folder has been manually defined, search for the right
373
        // file, and if not found, go for the same file in the default template
374
        if ($defaultFolder && $defaultFolder != 'default') {
375
            // Avoid missing template error, use the default file.
376
            if (file_exists($sysTemplatePath."$defaultFolder/$name")) {
377
                return "$defaultFolder/$name";
378
            }
379
        }
380
381
        $name = str_replace('tpl', 'html.twig', $name);
382
383
        return "default/$name";
384
    }
385
386
    /**
387
     * Call non-static for Template::findTemplateFilePath.
388
     *
389
     * @see Template::findTemplateFilePath()
390
     *
391
     * @param string $name
392
     *
393
     * @return string
394
     */
395
    public function get_template($name)
396
    {
397
        return api_find_template($name);
398
    }
399
400
    /**
401
     * Get CSS themes sub-directory.
402
     *
403
     * @param string $theme
404
     *
405
     * @return string with a trailing slash, e.g. 'themes/chamilo_red/'
406
     */
407
    public static function getThemeDir($theme)
408
    {
409
        $themeDir = 'themes/'.$theme.'/';
410
        $virtualTheme = api_get_configuration_value('virtual_css_theme_folder');
411
        if (!empty($virtualTheme)) {
412
            $virtualThemeList = api_get_themes(true);
413
            $isVirtualTheme = in_array($theme, array_keys($virtualThemeList));
414
            if ($isVirtualTheme) {
415
                $themeDir = 'themes/'.$virtualTheme.'/'.$theme.'/';
416
            }
417
        }
418
419
        return $themeDir;
420
    }
421
422
    /**
423
     * Set system parameters from api_get_configuration into _s array for use in TPLs
424
     * Also fills the _p array from getWebPaths().
425
     *
426
     * @uses \self::getWebPaths()
427
     */
428
    public function set_system_parameters()
429
    {
430
        $this->theme = api_get_visual_theme();
431
        if (!empty($this->preview_theme)) {
432
            $this->theme = $this->preview_theme;
433
        }
434
435
        $this->assign('theme', $this->theme);
436
437
        $this->themeDir = self::getThemeDir($this->theme);
438
439
        // Setting app paths/URLs
440
        //$this->assign('_p', $this->getWebPaths());
441
442
        // Here we can add system parameters that can be use in any template
443
        $_s = [
444
            'software_name' => api_get_configuration_value('software_name'),
445
            'system_version' => api_get_configuration_value('system_version'),
446
            'site_name' => api_get_setting('siteName'),
447
            'institu_tion' => api_get_setting('Institution'),
448
            'date' => api_format_date('now', DATE_FORMAT_LONG),
449
            'timezone' => api_get_timezone(),
450
            'gamification_mode' => api_get_setting('gamification_mode'),
451
        ];
452
        $this->assign('_s', $_s);
453
    }
454
455
    /**
456
     * Set legacy twig globals in order to be hook in the LegacyListener.php.
457
     *
458
     * @return array
459
     */
460
    public static function getGlobals()
461
    {
462
        $queryString = empty($_SERVER['QUERY_STRING']) ? '' : $_SERVER['QUERY_STRING'];
463
        $requestURI = empty($_SERVER['REQUEST_URI']) ? '' : $_SERVER['REQUEST_URI'];
464
465
        $_p = [
466
            'web' => api_get_path(WEB_PATH),
467
            'web_public' => api_get_path(WEB_PUBLIC_PATH),
468
            'web_url' => api_get_web_url(),
469
            'web_relative' => api_get_path(REL_PATH),
470
            'web_course' => api_get_path(WEB_COURSE_PATH),
471
            'web_main' => api_get_path(WEB_CODE_PATH),
472
            'web_css' => api_get_path(WEB_CSS_PATH),
473
            //'web_css_theme' => api_get_path(WEB_CSS_PATH).$this->themeDir,
474
            'web_ajax' => api_get_path(WEB_AJAX_PATH),
475
            'web_img' => api_get_path(WEB_IMG_PATH),
476
            'web_plugin' => api_get_path(WEB_PLUGIN_PATH),
477
            'web_lib' => api_get_path(WEB_LIBRARY_PATH),
478
            'web_upload' => api_get_path(WEB_UPLOAD_PATH),
479
            'web_self' => api_get_self(),
480
            'web_query_vars' => api_htmlentities($queryString),
481
            'web_self_query_vars' => api_htmlentities($requestURI),
482
            'web_cid_query' => api_get_cidreq(),
483
            'web_rel_code' => api_get_path(REL_CODE_PATH),
484
        ];
485
486
        $_s = [
487
            'software_name' => api_get_configuration_value('software_name'),
488
            'system_version' => api_get_configuration_value('system_version'),
489
            'site_name' => api_get_setting('siteName'),
490
            'institution' => api_get_setting('Institution'),
491
            //'date' => api_format_date('now', DATE_FORMAT_LONG),
492
            'date' => '',
493
            'timezone' => '',
494
            //'timezone' => api_get_timezone(),
495
            'gamification_mode' => api_get_setting('gamification_mode'),
496
        ];
497
498
        //$user_info = api_get_user_info();
499
500
        return [
501
            '_p' => $_p,
502
            '_s' => $_s,
503
            //       '_u' => $user_info,
504
            'template' => 'default', // @todo setup template folder in config.yml;
505
        ];
506
    }
507
508
    /**
509
     * Set theme, include mainstream CSS files.
510
     *
511
     * @deprecated
512
     * @see setCssCustomFiles() for additional CSS sheets
513
     */
514
    public function setCssFiles()
515
    {
516
        global $disable_js_and_css_files;
517
        $css = [];
518
519
        // Default CSS Bootstrap
520
        $bowerCSSFiles = [
521
            'fontawesome/css/font-awesome.min.css',
522
            'jquery-ui/themes/smoothness/theme.css',
523
            'jquery-ui/themes/smoothness/jquery-ui.min.css',
524
            'mediaelement/build/mediaelementplayer.min.css',
525
            'jqueryui-timepicker-addon/dist/jquery-ui-timepicker-addon.min.css',
526
            'bootstrap/dist/css/bootstrap.min.css',
527
            'jquery.scrollbar/jquery.scrollbar.css',
528
            //'bootstrap-daterangepicker/daterangepicker.css',
529
            'bootstrap-select/dist/css/bootstrap-select.min.css',
530
            'select2/dist/css/select2.min.css',
531
            'flag-icon-css/css/flag-icon.min.css',
532
            'mediaelement/plugins/vrview/vrview.css',
533
        ];
534
535
        $features = api_get_configuration_value('video_features');
536
        $defaultFeatures = ['playpause', 'current', 'progress', 'duration', 'tracks', 'volume', 'fullscreen', 'vrview'];
537
538
        if (!empty($features) && isset($features['features'])) {
539
            foreach ($features['features'] as $feature) {
540
                if ($feature === 'vrview') {
541
                    continue;
542
                }
543
                $bowerCSSFiles[] = "mediaelement/plugins/$feature/$feature.css";
544
                $defaultFeatures[] = $feature;
545
            }
546
        }
547
548
        foreach ($bowerCSSFiles as $file) {
549
            //$css[] = api_get_path(WEB_PUBLIC_PATH).'assets/'.$file;
550
        }
551
552
        //$css[] = api_get_path(WEB_LIBRARY_PATH).'javascript/chosen/chosen.css';
553
554
        if (api_is_global_chat_enabled()) {
555
            $css[] = api_get_path(WEB_LIBRARY_PATH).'javascript/chat/css/chat.css';
556
        }
557
        $css_file_to_string = '';
558
        foreach ($css as $file) {
559
            $css_file_to_string .= api_get_css($file);
560
        }
561
562
        if (!$disable_js_and_css_files) {
563
            $this->assign('css_static_file_to_string', $css_file_to_string);
564
        }
565
566
        $defaultFeatures = implode("','", $defaultFeatures);
567
        $this->assign('video_features', $defaultFeatures);
568
    }
569
570
    /**
571
     * Prepare custom CSS to be added at the very end of the <head> section.
572
     *
573
     * @see setCssFiles() for the mainstream CSS files
574
     */
575
    public function setCssCustomFiles()
576
    {
577
        global $disable_js_and_css_files;
578
        $css = [];
579
        if ($this->show_learnpath) {
580
            if (is_file(api_get_path(SYS_CSS_PATH).$this->themeDir.'learnpath.css')) {
581
                $css[] = api_get_path(WEB_CSS_PATH).$this->themeDir.'learnpath.css';
582
            }
583
        }
584
585
        $css_file_to_string = '';
586
        foreach ($css as $file) {
587
            $css_file_to_string .= api_get_css($file);
588
        }
589
590
        // @todo move this somewhere else. Special fix when using tablets in order to see the text near icons
591
        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...
592
            //hack in order to fix the actions buttons
593
            $css_file_to_string .= '<style>
594
                .td_actions a {
595
                    float:left;
596
                    width:100%;
597
                }
598
                .forum_message_left a {
599
                    float:left;
600
                    width:100%;
601
                }
602
                </style>';
603
        }
604
605
        $navigator_info = api_get_navigator();
606
        if ($navigator_info['name'] == 'Internet Explorer' && $navigator_info['version'] == '6') {
607
            $css_file_to_string .= 'img, div { behavior: url('.api_get_path(WEB_LIBRARY_PATH).'javascript/iepngfix/iepngfix.htc) } '."\n";
608
        }
609
610
        if (!$disable_js_and_css_files) {
611
            $this->assign('css_custom_file_to_string', $css_file_to_string);
612
613
            $style_print = '';
614
            if (is_readable(api_get_path(SYS_CSS_PATH).$this->theme.'/print.css')) {
615
                $style_print = api_get_css(
616
                    api_get_path(WEB_CSS_PATH).$this->theme.'/print.css',
617
                    'print'
618
                );
619
            }
620
            $this->assign('css_style_print', $style_print);
621
        }
622
623
        // Logo
624
        $logo = return_logo($this->theme);
625
        $logoPdf = return_logo($this->theme, false);
626
        $this->assign('logo', $logo);
627
        $this->assign('logo_pdf', $logoPdf);
628
        $this->assign('show_media_element', 1);
629
    }
630
631
    /**
632
     * Declare and define the template variable that will be used to load
633
     * javascript libraries in the header.
634
     */
635
    public function set_js_files()
636
    {
637
        global $disable_js_and_css_files, $htmlHeadXtra;
638
        $isoCode = api_get_language_isocode();
639
        $selectLink = 'bootstrap-select/dist/js/i18n/defaults-'.$isoCode.'_'.strtoupper($isoCode).'.min.js';
640
641
        if ($isoCode == 'en') {
642
            $selectLink = 'bootstrap-select/dist/js/i18n/defaults-'.$isoCode.'_US.min.js';
643
        }
644
        // JS files
645
        $js_files = [
646
            'chosen/chosen.jquery.min.js',
647
        ];
648
649
        $viewBySession = api_get_setting('my_courses_view_by_session') === 'true';
650
651
        if (api_is_global_chat_enabled() || $viewBySession) {
652
            // Do not include the global chat in LP
653
            if ($this->show_learnpath == false &&
654
                $this->show_footer == true &&
655
                $this->hide_global_chat == false
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...
656
            ) {
657
                $js_files[] = 'chat/js/chat.js';
658
            }
659
        }
660
661
        if (api_get_setting('accessibility_font_resize') === 'true') {
662
            $js_files[] = 'fontresize.js';
663
        }
664
665
        $js_file_to_string = '';
666
        $bowerJsFiles = [
667
            'modernizr/modernizr.js',
668
            'jquery/query.min.js',
669
            'bootstrap/dist/js/bootstrap.min.js',
670
            'jquery-ui/jquery-ui.min.js',
671
            'jqueryui-touch-punch/jquery.ui.touch-punch.min.js',
672
            'moment/min/moment-with-locales.js',
673
            //'bootstrap-daterangepicker/daterangepicker.js',
674
            'jquery-timeago/jquery.timeago.js',
675
            'mediaelement/mediaelement-and-player.min.js',
676
            'jqueryui-timepicker-addon/dist/jquery-ui-timepicker-addon.min.js',
677
            'image-map-resizer/js/imageMapResizer.min.js',
678
            'jquery.scrollbar/jquery.scrollbar.min.js',
679
            //'readmore-js/readmore.min.js',
680
            'bootstrap-select/dist/js/bootstrap-select.min.js',
681
            $selectLink,
682
            'select2/dist/js/select2.min.js',
683
            "select2/dist/js/i18n/$isoCode.js",
684
            'mediaelement/plugins/vrview/vrview.js',
685
        ];
686
687
        $features = api_get_configuration_value('video_features');
688
        if (!empty($features) && isset($features['features'])) {
689
            foreach ($features['features'] as $feature) {
690
                if ($feature === 'vrview') {
691
                    continue;
692
                }
693
                $bowerJsFiles[] = "mediaelement/plugins/$feature/$feature.js";
694
            }
695
        }
696
697
        if (CHAMILO_LOAD_WYSIWYG === true) {
698
            $bowerJsFiles[] = 'ckeditor/ckeditor.js';
699
        }
700
701
        if (api_get_setting('include_asciimathml_script') === 'true') {
702
            $bowerJsFiles[] = 'MathJax/MathJax.js?config=TeX-MML-AM_HTMLorMML';
703
        }
704
705
        if ($isoCode != 'en') {
706
            $bowerJsFiles[] = 'jqueryui-timepicker-addon/dist/i18n/jquery-ui-timepicker-'.$isoCode.'.js';
707
            $bowerJsFiles[] = 'jquery-ui/ui/minified/i18n/datepicker-'.$isoCode.'.min.js';
708
        }
709
710
        foreach ($bowerJsFiles as $file) {
711
            //$js_file_to_string .= '<script type="text/javascript" src="'.api_get_path(WEB_PUBLIC_PATH).'assets/'.$file.'"></script>'."\n";
712
        }
713
714
        foreach ($js_files as $file) {
715
            //$js_file_to_string .= api_get_js($file);
716
        }
717
718
        // Loading email_editor js
719
        if (!api_is_anonymous() && api_get_setting('allow_email_editor') == 'true') {
720
            $template = $this->get_template('mail_editor/email_link.js.tpl');
721
            $js_file_to_string .= $this->fetch($template);
722
        }
723
724
        if (!$disable_js_and_css_files) {
725
            $this->assign('js_file_to_string', $js_file_to_string);
726
            $extraHeaders = '';
727
            //$extraHeaders = '<script>var _p = '.json_encode($this->getWebPaths(), JSON_PRETTY_PRINT).'</script>';
728
            //Adding jquery ui by default
729
            $extraHeaders .= api_get_jquery_ui_js();
730
            if (isset($htmlHeadXtra) && $htmlHeadXtra) {
731
                foreach ($htmlHeadXtra as &$this_html_head) {
732
                    $extraHeaders .= $this_html_head."\n";
733
                }
734
            }
735
736
            $ajax = api_get_path(WEB_AJAX_PATH);
737
            $courseId = api_get_course_id();
738
            if (empty($courseId)) {
739
                $courseLogoutCode = '
740
                <script>
741
                function courseLogout() {
742
                }
743
                </script>';
744
            } else {
745
                $courseLogoutCode = "
746
                <script>
747
                var logOutUrl = '".$ajax."course.ajax.php?a=course_logout&".api_get_cidreq()."';
748
                function courseLogout() {                
749
                    $.ajax({
750
                        async : false,
751
                        url: logOutUrl,
752
                        success: function (data) {
753
                            return 1;
754
                        }
755
                    });
756
                }
757
                </script>";
758
            }
759
760
            $extraHeaders .= $courseLogoutCode;
761
            $this->assign('extra_headers', $extraHeaders);
762
        }
763
    }
764
765
    /**
766
     * @param array  $params
767
     * @param string $template
768
     *
769
     * @throws \Twig\Error\Error
770
     */
771
    public function returnResponse($params, $template)
772
    {
773
        $flash = Display::getFlashToString();
774
        Display::cleanFlashMessages();
775
        $response = new Response();
776
        $params['flash_messages'] = $flash;
777
        $content = Container::getTemplating()->render($template, $params);
778
        $response->setContent($content);
779
        $response->send();
780
    }
781
782
    /**
783
     * Special function to declare last-minute JS libraries which depend on
784
     * other things to be declared first. In particular, it might be useful
785
     * under IE9 with compatibility mode, which for some reason is getting
786
     * upset when a variable is used in a function (even if not used yet)
787
     * when this variable hasn't been defined yet.
788
     */
789
    public function set_js_files_post()
790
    {
791
        global $disable_js_and_css_files;
792
        $js_files = [];
793
        if (api_is_global_chat_enabled()) {
794
            //Do not include the global chat in LP
795
            if ($this->show_learnpath == false && $this->show_footer == true && $this->hide_global_chat == false) {
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...
796
                $js_files[] = 'chat/js/chat.js';
797
            }
798
        }
799
        $js_file_to_string = '';
800
        foreach ($js_files as $js_file) {
801
            $js_file_to_string .= api_get_js($js_file);
802
        }
803
        if (!$disable_js_and_css_files) {
804
            $this->assign('js_file_to_string_post', $js_file_to_string);
805
        }
806
    }
807
808
    /**
809
     * @param string $theme
810
     *
811
     * @return string
812
     */
813
    public static function getPortalIcon($theme)
814
    {
815
        // Default root chamilo favicon
816
        $icon = '<link rel="shortcut icon" href="'.api_get_path(WEB_PUBLIC_PATH).'favicon.ico" type="image/x-icon" />';
817
818
        // Added to verify if in the current Chamilo Theme exist a favicon
819
        $themeUrl = api_get_path(SYS_CSS_PATH).'themes/'.$theme.'/images/';
820
821
        //If exist pick the current chamilo theme favicon
822
        if (is_file($themeUrl.'favicon.ico')) {
823
            $icon = '<link rel="shortcut icon" href="'.api_get_path(WEB_PUBLIC_PATH).'build/css/themes/'.$theme.'/images/favicon.ico" type="image/x-icon" />';
824
        }
825
826
        return $icon;
827
    }
828
829
    /**
830
     * Show footer js template.
831
     */
832
    public function show_footer_js_template()
833
    {
834
        $tpl = $this->get_template('layout/footer.js.tpl');
835
        $this->display($tpl);
836
    }
837
838
    /**
839
     * @param string $template
840
     *
841
     * @return string
842
     */
843
    public function fetch($template = null)
844
    {
845
        $template = $this->twig->loadTemplate($template);
846
847
        return $template->render($this->params);
848
    }
849
850
    /**
851
     * @param string $variable
852
     * @param mixed  $value
853
     */
854
    public function assign($variable, $value = '')
855
    {
856
        $this->params[$variable] = $value;
857
    }
858
859
    /**
860
     * Adds a body class for login pages.
861
     */
862
    public function setLoginBodyClass()
863
    {
864
        $this->assign('login_class', 'section-login');
865
    }
866
867
    /**
868
     * The theme that will be used if the database is not working.
869
     *
870
     * @return string
871
     */
872
    public static function getThemeFallback()
873
    {
874
        $theme = api_get_configuration_value('theme_fallback');
875
        if (empty($theme)) {
876
            $theme = 'chamilo';
877
        }
878
879
        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...
880
    }
881
882
    /**
883
     * @return string
884
     */
885
    public function handleLoginFailed()
886
    {
887
        $message = get_lang('InvalidId');
888
889
        if (!isset($_GET['error'])) {
890
            if (api_is_self_registration_allowed()) {
891
                $message = get_lang('InvalidForSelfRegistration');
892
            }
893
        } else {
894
            switch ($_GET['error']) {
895
                case '':
896
                    if (api_is_self_registration_allowed()) {
897
                        $message = get_lang('InvalidForSelfRegistration');
898
                    }
899
                    break;
900
                case 'account_expired':
901
                    $message = get_lang('AccountExpired');
902
                    break;
903
                case 'account_inactive':
904
                    $message = get_lang('AccountInactive');
905
906
                    if (api_get_setting('allow_registration') === 'confirmation') {
907
                        $message = get_lang('AccountNotConfirmed').PHP_EOL;
908
                        $message .= Display::url(
909
                            get_lang('ReSendConfirmationMail'),
910
                            api_get_path(WEB_PATH).'main/auth/resend_confirmation_mail.php',
911
                            ['class' => 'alert-link']
912
                        );
913
                    }
914
                    break;
915
                case 'user_password_incorrect':
916
                    $message = get_lang('InvalidId');
917
                    break;
918
                case 'access_url_inactive':
919
                    $message = get_lang('AccountURLInactive');
920
                    break;
921
                case 'wrong_captcha':
922
                    $message = get_lang('TheTextYouEnteredDoesNotMatchThePicture');
923
                    break;
924
                case 'blocked_by_captcha':
925
                    $message = get_lang('AccountBlockedByCaptcha');
926
                    break;
927
                case 'multiple_connection_not_allowed':
928
                    $message = get_lang('MultipleConnectionsAreNotAllow');
929
                    break;
930
            }
931
        }
932
933
        return Display::return_message($message, 'error', false);
934
    }
935
936
    /**
937
     * @return string
938
     */
939
    public function displayLoginForm()
940
    {
941
        $form = new FormValidator(
942
            'form-login',
943
            'POST',
944
            api_get_path(WEB_PUBLIC_PATH).'login_check',
945
            null,
946
            null,
947
            FormValidator::LAYOUT_BOX_NO_LABEL
948
        );
949
        $params = [
950
            'id' => '_username',
951
            'autofocus' => 'autofocus',
952
            'icon' => 'user fa-fw',
953
            'placeholder' => get_lang('UserName'),
954
        ];
955
        $browserAutoCapitalize = false;
956
        // Avoid showing the autocapitalize option if the browser doesn't
957
        // support it: this attribute is against the HTML5 standard
958
        if (api_browser_support('autocapitalize')) {
959
            $browserAutoCapitalize = false;
960
            $params['autocapitalize'] = 'none';
961
        }
962
        $form->addText(
963
            '_username',
964
            get_lang('UserName'),
965
            true,
966
            $params
967
        );
968
        $params = [
969
            'id' => '_password',
970
            'icon' => 'lock fa-fw',
971
            'placeholder' => get_lang('Pass'),
972
        ];
973
        if ($browserAutoCapitalize) {
974
            $params['autocapitalize'] = 'none';
975
        }
976
        $form->addElement(
977
            'password',
978
            '_password',
979
            get_lang('Pass'),
980
            $params
981
        );
982
983
        $token = Chamilo\CoreBundle\Framework\Container::$container->get('security.csrf.token_manager')->getToken('authenticate');
984
        $form->addHidden('_csrf_token', $token->getValue());
985
986
        // Captcha
987
        $captcha = api_get_setting('allow_captcha');
988
        $allowCaptcha = $captcha === 'true';
989
990
        if ($allowCaptcha) {
991
            $useCaptcha = isset($_SESSION['loginFailed']) ? $_SESSION['loginFailed'] : null;
992
            if ($useCaptcha) {
993
                $ajax = api_get_path(WEB_AJAX_PATH).'form.ajax.php?a=get_captcha';
994
                $options = [
995
                    'width' => 250,
996
                    'height' => 90,
997
                    'callback' => $ajax.'&var='.basename(__FILE__, '.php'),
998
                    'sessionVar' => basename(__FILE__, '.php'),
999
                    'imageOptions' => [
1000
                        'font_size' => 20,
1001
                        'font_path' => api_get_path(SYS_FONTS_PATH).'opensans/',
1002
                        'font_file' => 'OpenSans-Regular.ttf',
1003
                        //'output' => 'gif'
1004
                    ],
1005
                ];
1006
1007
                // Minimum options using all defaults (including defaults for Image_Text):
1008
                //$options = array('callback' => 'qfcaptcha_image.php');
1009
                $captcha_question = $form->addElement('CAPTCHA_Image', 'captcha_question', '', $options);
1010
                $form->addHtml(get_lang('ClickOnTheImageForANewOne'));
1011
1012
                $form->addElement(
1013
                    'text',
1014
                    'captcha',
1015
                    get_lang('EnterTheLettersYouSee')
1016
                );
1017
                $form->addRule(
1018
                    'captcha',
1019
                    get_lang('EnterTheCharactersYouReadInTheImage'),
1020
                    'required',
1021
                    null,
1022
                    'client'
1023
                );
1024
                $form->addRule(
1025
                    'captcha',
1026
                    get_lang('TheTextYouEnteredDoesNotMatchThePicture'),
1027
                    'CAPTCHA',
1028
                    $captcha_question
1029
                );
1030
            }
1031
        }
1032
1033
        $form->addButton(
1034
            'submitAuth',
1035
            get_lang('LoginEnter'),
1036
            null,
1037
            'primary',
1038
            null,
1039
            'btn-block'
1040
        );
1041
1042
        $html = $form->returnForm();
1043
1044
        return $html;
1045
    }
1046
1047
    /**
1048
     * Returns the tutors names for the current course in session
1049
     * Function to use in Twig templates.
1050
     *
1051
     * @return string
1052
     */
1053
    public static function returnTutorsNames()
1054
    {
1055
        $em = Database::getManager();
1056
        $tutors = $em
1057
            ->createQuery('
1058
                SELECT u FROM ChamiloUserBundle:User u
1059
                INNER JOIN ChamiloCoreBundle:SessionRelCourseRelUser scu WITH u.id = scu.user
1060
                WHERE scu.status = :teacher_status AND scu.session = :session AND scu.course = :course
1061
            ')
1062
            ->setParameters([
1063
                'teacher_status' => SessionRelCourseRelUser::STATUS_COURSE_COACH,
1064
                'session' => api_get_session_id(),
1065
                'course' => api_get_course_int_id(),
1066
            ])
1067
            ->getResult();
1068
1069
        $names = [];
1070
1071
        /** @var User $tutor */
1072
        foreach ($tutors as $tutor) {
1073
            $names[] = UserManager::formatUserFullName($tutor);
1074
        }
1075
1076
        return implode(CourseManager::USER_SEPARATOR, $names);
1077
    }
1078
1079
    /*s
1080
     * Returns the teachers name for the current course
1081
     * Function to use in Twig templates
1082
     * @return string
1083
     */
1084
    public static function returnTeachersNames()
1085
    {
1086
        $em = Database::getManager();
1087
        $teachers = $em
1088
            ->createQuery('
1089
                SELECT u FROM ChamiloUserBundle:User u
1090
                INNER JOIN ChamiloCoreBundle:CourseRelUser cu WITH u.id = cu.user
1091
                WHERE cu.status = :teacher_status AND cu.course = :course
1092
            ')
1093
            ->setParameters([
1094
                'teacher_status' => User::COURSE_MANAGER,
1095
                'course' => api_get_course_int_id(),
1096
            ])
1097
            ->getResult();
1098
1099
        $names = [];
1100
1101
        /** @var User $teacher */
1102
        foreach ($teachers as $teacher) {
1103
            $names[] = UserManager::formatUserFullName($teacher);
1104
        }
1105
1106
        return implode(CourseManager::USER_SEPARATOR, $names);
1107
    }
1108
1109
    /**
1110
     * @param int $code
1111
     */
1112
    public function setResponseCode($code)
1113
    {
1114
        $this->responseCode = $code;
1115
    }
1116
1117
    /**
1118
     * @param string $code
1119
     */
1120
    public function getResponseCode()
1121
    {
1122
        return $this->responseCode;
1123
    }
1124
1125
    /**
1126
     * Assign HTML code to the 'bug_notification' template variable for the side tabs to report issues.
1127
     *
1128
     * @return bool Always return true because there is always a string, even if empty
1129
     */
1130
    public function assignBugNotification()
1131
    {
1132
        //@todo move this in the template
1133
        $rightFloatMenu = '';
1134
        $iconBug = Display::return_icon(
1135
            'bug.png',
1136
            get_lang('ReportABug'),
1137
            [],
1138
            ICON_SIZE_LARGE
1139
        );
1140
        if (api_get_setting('show_link_bug_notification') === 'true' && $this->user_is_logged_in) {
1141
            $rightFloatMenu = '<div class="report">
1142
		        <a href="https://github.com/chamilo/chamilo-lms/wiki/How-to-report-issues" target="_blank">
1143
                    '.$iconBug.'
1144
                </a>
1145
		        </div>';
1146
        }
1147
1148
        if (api_get_setting('show_link_ticket_notification') === 'true' &&
1149
            $this->user_is_logged_in
1150
        ) {
1151
            // by default is project_id = 1
1152
            $defaultProjectId = 1;
1153
            $iconTicket = Display::return_icon(
1154
                'help.png',
1155
                get_lang('Ticket'),
1156
                [],
1157
                ICON_SIZE_LARGE
1158
            );
1159
            $courseInfo = api_get_course_info();
1160
            $courseParams = '';
1161
            if (!empty($courseInfo)) {
1162
                $courseParams = api_get_cidreq();
1163
            }
1164
            $url = api_get_path(WEB_CODE_PATH).'ticket/tickets.php?project_id='.$defaultProjectId.'&'.$courseParams;
1165
1166
            $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

1166
            $allow = TicketManager::userIsAllowInProject(/** @scrutinizer ignore-type */ api_get_user_info(), $defaultProjectId);
Loading history...
1167
1168
            if ($allow) {
1169
                $rightFloatMenu .= '<div class="help">
1170
                    <a href="'.$url.'" target="_blank">
1171
                        '.$iconTicket.'
1172
                    </a>
1173
                </div>';
1174
            }
1175
        }
1176
1177
        $this->assign('bug_notification', $rightFloatMenu);
1178
1179
        return true;
1180
    }
1181
1182
    /**
1183
     * Load legacy params.
1184
     */
1185
    private function loadLegacyParams()
1186
    {
1187
        // Set legacy breadcrumb
1188
        global $interbreadcrumb;
1189
        $this->params['legacy_breadcrumb'] = $interbreadcrumb;
1190
1191
        global $htmlHeadXtra;
1192
        $this->params['legacy_javascript'] = $htmlHeadXtra;
1193
    }
1194
1195
    /**
1196
     * Prepare the _c array for template files. The _c array contains
1197
     * information about the current course.
1198
     */
1199
    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...
1200
    {
1201
        //Setting course id
1202
        $course = api_get_course_info();
1203
        if (empty($course)) {
1204
            $this->assign('course_is_set', false);
1205
1206
            return;
1207
        }
1208
        $this->assign('course_is_set', true);
1209
        $this->course_id = $course['id'];
1210
        $_c = [
1211
            'id' => $course['real_id'],
1212
            'code' => $course['code'],
1213
            'title' => $course['name'],
1214
            'visibility' => $course['visibility'],
1215
            'language' => $course['language'],
1216
            'directory' => $course['directory'],
1217
            'session_id' => api_get_session_id(),
1218
            'user_is_teacher' => api_is_course_admin(),
1219
            'student_view' => (!empty($_GET['isStudentView']) && $_GET['isStudentView'] == 'true'),
1220
        ];
1221
        $this->assign('course_code', $course['code']);
1222
        $this->assign('_c', $_c);
1223
    }
1224
1225
    /**
1226
     * Prepare the _u array for template files. The _u array contains
1227
     * information about the current user, as returned by
1228
     * api_get_user_info().
1229
     */
1230
    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...
1231
    {
1232
        $user_info = [];
1233
        $user_info['logged'] = 0;
1234
        $this->user_is_logged_in = false;
1235
        if (api_user_is_login()) {
1236
            $user_info = api_get_user_info(api_get_user_id(), true);
1237
            $user_info['logged'] = 1;
1238
1239
            $user_info['is_admin'] = 0;
1240
            if (api_is_platform_admin()) {
1241
                $user_info['is_admin'] = 1;
1242
            }
1243
1244
            $user_info['messages_count'] = MessageManager::getCountNewMessages();
1245
            $this->user_is_logged_in = true;
1246
        }
1247
        // Setting the $_u array that could be use in any template
1248
        $this->assign('_u', $user_info);
1249
    }
1250
1251
    /**
1252
     * Set header parameters.
1253
     *
1254
     * @deprecated
1255
     *
1256
     * @param bool $sendHeaders send headers
1257
     */
1258
    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...
1259
    {
1260
        global $httpHeadXtra, $interbreadcrumb, $language_file, $_configuration, $this_section;
1261
        $_course = api_get_course_info();
1262
        $nameTools = $this->title;
1263
        $navigation = return_navigation_array();
1264
        $this->menu_navigation = $navigation['menu_navigation'];
1265
1266
        $this->assign('system_charset', api_get_system_encoding());
1267
1268
        if (isset($httpHeadXtra) && $httpHeadXtra) {
1269
            foreach ($httpHeadXtra as &$thisHttpHead) {
1270
                //header($thisHttpHead);
1271
            }
1272
        }
1273
1274
        $this->assign(
1275
            'online_button',
1276
            Display::return_icon('statusonline.png', null, [], ICON_SIZE_ATOM)
1277
        );
1278
        $this->assign(
1279
            'offline_button',
1280
            Display::return_icon('statusoffline.png', null, [], ICON_SIZE_ATOM)
1281
        );
1282
1283
        // Get language iso-code for this page - ignore errors
1284
        $this->assign('document_language', api_get_language_isocode());
1285
1286
        $course_title = isset($_course['name']) ? $_course['name'] : null;
1287
1288
        $title_list = [];
1289
1290
        $title_list[] = api_get_setting('Institution');
1291
        $title_list[] = api_get_setting('siteName');
1292
1293
        if (!empty($course_title)) {
1294
            $title_list[] = $course_title;
1295
        }
1296
        if ($nameTools != '') {
1297
            $title_list[] = $nameTools;
1298
        }
1299
1300
        $title_string = '';
1301
        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...
1302
            $title_string .= $title_list[$i];
1303
            if (isset($title_list[$i + 1])) {
1304
                $item = trim($title_list[$i + 1]);
1305
                if (!empty($item)) {
1306
                    $title_string .= ' - ';
1307
                }
1308
            }
1309
        }
1310
1311
        $this->assign('title_string', $title_string);
1312
1313
        // Setting the theme and CSS files
1314
        $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

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