Completed
Push — master ( 43398a...5bd0ab )
by Julito
09:23
created

Template::show_footer_template()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

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

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