Passed
Push — master ( 7cc9b1...dddfd9 )
by Julito
09:51
created

Template::isToolBarDisplayedForUser()   B

Complexity

Conditions 8
Paths 7

Size

Total Lines 25
Code Lines 17

Duplication

Lines 0
Ratio 0 %

Importance

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

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