Passed
Push — master ( b3a000...eae2c0 )
by Julito
08:12
created

Template::setResponseCode()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 1
nc 1
nop 1
dl 0
loc 3
rs 10
c 0
b 0
f 0
1
<?php
2
3
/* For licensing terms, see /license.txt */
4
5
use Chamilo\CoreBundle\Component\Utils\ChamiloApi;
6
use Chamilo\CoreBundle\Entity\SessionRelCourseRelUser;
7
use Chamilo\CoreBundle\Entity\User;
8
use Chamilo\CoreBundle\Framework\Container;
9
use Symfony\Component\Filesystem\Exception\FileNotFoundException;
10
use Symfony\Component\HttpFoundation\Response;
11
12
/**
13
 * Class Template.
14
 *
15
 * @author Julio Montoya <[email protected]>
16
 *
17
 * @todo better organization of the class, methods and variables
18
 */
19
class Template
20
{
21
    /**
22
     * The Template folder name see main/template.
23
     *
24
     * @var string
25
     */
26
    public $templateFolder = 'default';
27
28
    /**
29
     * The theme that will be used: chamilo, public_admin, chamilo_red, etc
30
     * This variable is set from the database.
31
     *
32
     * @var string
33
     */
34
    public $theme = '';
35
36
    /**
37
     * @var string
38
     */
39
    public $preview_theme = '';
40
    public $title = null;
41
    public $show_header;
42
    public $show_footer;
43
    public $help;
44
    public $menu_navigation = []; //Used in the userportal.lib.php function: return_navigation_course_links()
45
    public $show_learnpath = false; // This is a learnpath section or not?
46
    public $plugin = null;
47
    public $course_id = null;
48
    public $user_is_logged_in = false;
49
    public $twig = null;
50
51
    /* Loads chamilo plugins */
52
    public $load_plugins = false;
53
    public $params = [];
54
    public $force_plugin_load = false;
55
    public $responseCode = 0;
56
    private $themeDir;
57
58
    /**
59
     * @param string $title
60
     * @param bool   $show_header
61
     * @param bool   $show_footer
62
     * @param bool   $show_learnpath
63
     * @param bool   $hide_global_chat
64
     * @param bool   $load_plugins
65
     * @param int    $responseCode
66
     * @param bool   $sendHeaders      send http headers or not
67
     */
68
    public function __construct(
69
        $title = '',
70
        $show_header = true,
71
        $show_footer = true,
72
        $show_learnpath = false,
73
        $hide_global_chat = false,
74
        $load_plugins = true,
75
        $sendHeaders = true,
76
        $responseCode = 0
77
    ) {
78
        // Page title
79
        $this->title = $title;
80
        global $interbreadcrumb;
81
        $interbreadcrumb[] = ['url' => '#', 'name' => $title];
82
        $this->show_learnpath = $show_learnpath;
83
        //$this->setResponseCode($responseCode);
84
85
        if (empty($this->show_learnpath)) {
86
            $origin = api_get_origin();
87
            if ('learnpath' === $origin) {
88
                $this->show_learnpath = true;
89
                $show_footer = false;
90
                $show_header = false;
91
            }
92
        }
93
        $this->hide_global_chat = $hide_global_chat;
94
        $this->load_plugins = $load_plugins;
95
96
        /*$template_paths = [
97
            api_get_path(SYS_CODE_PATH).'template/overrides', // user defined templates
98
            api_get_path(SYS_CODE_PATH).'template', //template folder
99
            api_get_path(SYS_PLUGIN_PATH), // plugin folder
100
            api_get_path(SYS_PATH).'src/ThemeBundle/Resources/views',
101
        ];*/
102
103
        $this->twig = Container::getTwig();
104
105
        // Setting system variables
106
        //$this->set_system_parameters();
107
108
        // Setting user variables
109
        //$this->set_user_parameters();
110
111
        // Setting course variables
112
        //$this->set_course_parameters();
113
114
        // Setting administrator variables
115
        //$this->setAdministratorParams();
116
        //$this->setCSSEditor();
117
118
        // Header and footer are showed by default
119
        //$this->set_footer($show_footer);
120
        //$this->set_header($show_header);
121
122
        $defaultStyle = api_get_setting('display.default_template');
123
        if (!empty($defaultStyle)) {
124
            $this->templateFolder = $defaultStyle;
0 ignored issues
show
Documentation Bug introduced by
It seems like $defaultStyle can also be of type array. However, the property $templateFolder is declared as type string. Maybe add an additional type check?

Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.

For example, imagine you have a variable $accountId that can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to the id property of an instance of the Account class. This class holds a proper account, so the id value must no longer be false.

Either this assignment is in error or a type check should be added for that assignment.

class Id
{
    public $id;

    public function __construct($id)
    {
        $this->id = $id;
    }

}

class Account
{
    /** @var  Id $id */
    public $id;
}

$account_id = false;

if (starsAreRight()) {
    $account_id = new Id(42);
}

$account = new Account();
if ($account instanceof Id)
{
    $account->id = $account_id;
}
Loading history...
125
        }
126
    }
127
128
    /**
129
     * @param string $helpInput
130
     */
131
    public function setHelp($helpInput = null)
132
    {
133
        if (!empty($helpInput)) {
134
            $help = $helpInput;
135
        } else {
136
            $help = $this->help;
137
        }
138
139
        $content = '';
140
        if ('true' == api_get_setting('enable_help_link')) {
141
            if (!empty($help)) {
142
                $help = Security::remove_XSS($help);
143
                $content = '<div class="help">';
144
                $content .= Display::url(
145
                    Display::return_icon('help.png', get_lang('Help'), null, ICON_SIZE_LARGE),
146
                    api_get_path(WEB_CODE_PATH).'help/help.php?open='.$help,
0 ignored issues
show
Bug introduced by
Are you sure $help of type array|string can be used in concatenation? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

146
                    api_get_path(WEB_CODE_PATH).'help/help.php?open='./** @scrutinizer ignore-type */ $help,
Loading history...
147
                    [
148
                        'class' => 'ajax',
149
                        'data-title' => get_lang('Help'),
150
                    ]
151
                );
152
                $content .= '</div>';
153
            }
154
        }
155
        $this->assign('help_content', $content);
156
    }
157
158
    /**
159
     * Use template system to parse the actions menu.
160
     *
161
     * @todo finish it!
162
     */
163
    public function set_actions($actions)
164
    {
165
        $action_string = '';
166
        if (!empty($actions)) {
167
            foreach ($actions as $action) {
168
                $action_string .= $action;
169
            }
170
        }
171
        $this->assign('actions', $actions);
172
    }
173
174
    /**
175
     * Render the template.
176
     *
177
     * @param string $template The template path
178
     */
179
    public function display($template)
180
    {
181
        $template = str_replace('tpl', 'html.twig', $template);
182
        $templateFile = api_get_path(SYS_CODE_PATH).'template/'.$template;
183
184
        $this->loadLegacyParams();
185
186
        if (!file_exists($templateFile)) {
187
            $e = new FileNotFoundException($templateFile);
188
            echo $e->getMessage();
189
            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...
190
        }
191
192
        $this->setVueParams($this->params);
193
        $this->returnResponse($this->params, $template);
194
    }
195
196
    /**
197
     * @param string $template
198
     *
199
     * @throws \Twig\Error\Error
200
     */
201
    public function displayTemplate($template)
202
    {
203
        $this->loadLegacyParams();
204
        $this->returnResponse($this->params, $template);
205
    }
206
207
    /**
208
     * Shortcut to display a 1 col layout (index.php).
209
     * */
210
    public function display_one_col_template()
211
    {
212
        $this->loadLegacyParams();
213
        $template = '@ChamiloCore/Layout/layout_one_col.html.twig';
214
        $origin = api_get_origin();
215
        if ('learnpath' === $origin) {
216
            $template = '@ChamiloCore/Layout/no_layout.html.twig';
217
        }
218
        $this->setVueParams($this->params);
219
        $this->returnResponse($this->params, $template);
220
    }
221
222
    public function displayTwoColTemplate()
223
    {
224
        $this->loadLegacyParams();
225
        $template = '@ChamiloCore/Layout/layout_two_col.html.twig';
226
        $this->setVueParams($this->params);
227
        $this->returnResponse($this->params, $template);
228
    }
229
230
    /**
231
     * Displays an empty template.
232
     */
233
    public function display_blank_template()
234
    {
235
        $this->loadLegacyParams();
236
        $template = '@ChamiloCore/Layout/blank.html.twig';
237
        $this->returnResponse($this->params, $template);
238
    }
239
240
    /**
241
     * Displays an empty template.
242
     */
243
    public function displayBlankTemplateNoHeader()
244
    {
245
        $this->loadLegacyParams();
246
        $template = '@ChamiloCore/Layout/blank_no_header.html.twig';
247
        $this->returnResponse($this->params, $template);
248
    }
249
250
    /**
251
     * Displays an empty template.
252
     */
253
    public function display_no_layout_template()
254
    {
255
        $this->loadLegacyParams();
256
        $template = '@ChamiloCore/Layout/no_layout.html.twig';
257
        $this->returnResponse($this->params, $template);
258
    }
259
260
    /**
261
     * Displays an empty template.
262
     */
263
    public function displaySkillLayout()
264
    {
265
        $this->loadLegacyParams();
266
        $template = '@ChamiloCore/Layout/skill_layout.html.twig';
267
        $this->returnResponse($this->params, $template);
268
    }
269
270
    /**
271
     * return true if toolbar has to be displayed for user.
272
     *
273
     * @return bool
274
     */
275
    public static function isToolBarDisplayedForUser()
276
    {
277
        //Toolbar
278
        $show_admin_toolbar = api_get_setting('show_admin_toolbar');
279
        $show_toolbar = false;
280
281
        switch ($show_admin_toolbar) {
282
            case 'do_not_show':
283
                break;
284
            case 'show_to_admin':
285
                if (api_is_platform_admin()) {
286
                    $show_toolbar = true;
287
                }
288
                break;
289
            case 'show_to_admin_and_teachers':
290
                if (api_is_platform_admin() || api_is_allowed_to_edit()) {
291
                    $show_toolbar = true;
292
                }
293
                break;
294
            case 'show_to_all':
295
                $show_toolbar = true;
296
                break;
297
        }
298
299
        return $show_toolbar;
300
    }
301
302
    /**
303
     * Sets the header visibility.
304
     *
305
     * @param bool true if we show the header
306
     */
307
    public function set_header($status)
308
    {
309
        $this->show_header = $status;
310
        $this->assign('show_header', $status);
311
312
        $show_toolbar = 0;
313
314
        if (self::isToolBarDisplayedForUser()) {
315
            $show_toolbar = 1;
316
        }
317
318
        $this->assign('show_toolbar', $show_toolbar);
319
320
        // Only if course is available
321
        $courseToolBar = '';
322
        $show_course_navigation_menu = '';
323
        if (!empty($this->course_id) && $this->user_is_logged_in) {
324
            if ('false' !== api_get_setting('show_toolshortcuts')) {
325
                // Course toolbar
326
                $courseToolBar = CourseHome::show_navigation_tool_shortcuts();
327
            }
328
            if ('false' !== api_get_setting('show_navigation_menu')) {
329
                //Course toolbar
330
                $show_course_navigation_menu = CourseHome::show_navigation_menu();
331
            }
332
        }
333
        $this->assign('show_course_shortcut', $courseToolBar);
334
        $this->assign('show_course_navigation_menu', $show_course_navigation_menu);
335
    }
336
337
    /**
338
     * Returns the sub-folder and filename for the given tpl file.
339
     *
340
     * If template not found in overrides/ or custom template folder, the default template will be used.
341
     *
342
     * @param string $name
343
     *
344
     * @return string
345
     */
346
    public static function findTemplateFilePath($name)
347
    {
348
        $sysTemplatePath = api_get_path(SYS_TEMPLATE_PATH);
349
350
        // Check if the tpl file is present in the main/template/overrides/ dir
351
        // Overrides is a special directory meant for temporary template
352
        // customization. It must be taken into account before anything else
353
        if (is_readable($sysTemplatePath."overrides/$name")) {
354
            return "overrides/$name";
355
        }
356
357
        $defaultFolder = api_get_configuration_value('default_template');
358
359
        // If a template folder has been manually defined, search for the right
360
        // file, and if not found, go for the same file in the default template
361
        if ($defaultFolder && 'default' != $defaultFolder) {
362
            // Avoid missing template error, use the default file.
363
            if (file_exists($sysTemplatePath."$defaultFolder/$name")) {
364
                return "$defaultFolder/$name";
365
            }
366
        }
367
368
        $name = str_replace('tpl', 'html.twig', $name);
369
370
        return "default/$name";
371
    }
372
373
    /**
374
     * Call non-static for Template::findTemplateFilePath.
375
     *
376
     * @see Template::findTemplateFilePath()
377
     *
378
     * @param string $name
379
     *
380
     * @return string
381
     */
382
    public function get_template($name)
383
    {
384
        return api_find_template($name);
385
    }
386
387
    /**
388
     * Get CSS themes sub-directory.
389
     *
390
     * @param string $theme
391
     *
392
     * @return string with a trailing slash, e.g. 'themes/chamilo_red/'
393
     */
394
    public static function getThemeDir($theme)
395
    {
396
        $themeDir = 'themes/'.$theme.'/';
397
        $virtualTheme = api_get_configuration_value('virtual_css_theme_folder');
398
        if (!empty($virtualTheme)) {
399
            $virtualThemeList = api_get_themes(true);
400
            $isVirtualTheme = in_array($theme, array_keys($virtualThemeList));
401
            if ($isVirtualTheme) {
402
                $themeDir = 'themes/'.$virtualTheme.'/'.$theme.'/';
403
            }
404
        }
405
406
        return $themeDir;
407
    }
408
409
    /**
410
     * Set legacy twig globals in order to be hook in the LegacyListener.php.
411
     *
412
     * @return array
413
     */
414
    public static function getGlobals()
415
    {
416
        return [
417
            '_s' => [
418
                'software_name' => api_get_configuration_value('software_name'),
419
                'system_version' => api_get_configuration_value('system_version'),
420
                'site_name' => api_get_setting('siteName'),
421
                'institution' => api_get_setting('Institution'),
422
                'gamification_mode' => api_get_setting('gamification_mode'),
423
            ],
424
            'template' => 'default', // @todo setup template folder in config.yml;
425
        ];
426
    }
427
428
    /**
429
     * Set theme, include mainstream CSS files.
430
     *
431
     * @deprecated
432
     * @see setCssCustomFiles() for additional CSS sheets
433
     */
434
    public function setCssFiles()
435
    {
436
        global $disable_js_and_css_files;
437
        $css = [];
438
439
        // Default CSS Bootstrap
440
        $bowerCSSFiles = [
441
            'fontawesome/css/font-awesome.min.css',
442
            'jquery-ui/themes/smoothness/theme.css',
443
            'jquery-ui/themes/smoothness/jquery-ui.min.css',
444
            'mediaelement/build/mediaelementplayer.min.css',
445
            'jqueryui-timepicker-addon/dist/jquery-ui-timepicker-addon.min.css',
446
            'bootstrap/dist/css/bootstrap.min.css',
447
            'jquery.scrollbar/jquery.scrollbar.css',
448
            //'bootstrap-daterangepicker/daterangepicker.css',
449
            'bootstrap-select/dist/css/bootstrap-select.min.css',
450
            'select2/dist/css/select2.min.css',
451
            'flag-icon-css/css/flag-icon.min.css',
452
            'mediaelement/plugins/vrview/vrview.css',
453
        ];
454
455
        $features = api_get_configuration_value('video_features');
456
        $defaultFeatures = ['playpause', 'current', 'progress', 'duration', 'tracks', 'volume', 'fullscreen', 'vrview'];
457
458
        if (!empty($features) && isset($features['features'])) {
459
            foreach ($features['features'] as $feature) {
460
                if ('vrview' === $feature) {
461
                    continue;
462
                }
463
                $bowerCSSFiles[] = "mediaelement/plugins/$feature/$feature.css";
464
                $defaultFeatures[] = $feature;
465
            }
466
        }
467
468
        foreach ($bowerCSSFiles as $file) {
469
            //$css[] = api_get_path(WEB_PUBLIC_PATH).'assets/'.$file;
470
        }
471
472
        //$css[] = api_get_path(WEB_LIBRARY_PATH).'javascript/chosen/chosen.css';
473
474
        if (api_is_global_chat_enabled()) {
475
            $css[] = api_get_path(WEB_LIBRARY_PATH).'javascript/chat/css/chat.css';
476
        }
477
        $css_file_to_string = '';
478
        foreach ($css as $file) {
479
            $css_file_to_string .= api_get_css($file);
480
        }
481
482
        if (!$disable_js_and_css_files) {
483
            $this->assign('css_static_file_to_string', $css_file_to_string);
484
        }
485
486
        $defaultFeatures = implode("','", $defaultFeatures);
487
        $this->assign('video_features', $defaultFeatures);
488
    }
489
490
    /**
491
     * Prepare custom CSS to be added at the very end of the <head> section.
492
     *
493
     * @see setCssFiles() for the mainstream CSS files
494
     */
495
    public function setCssCustomFiles()
496
    {
497
        global $disable_js_and_css_files;
498
        $css = [];
499
        if ($this->show_learnpath) {
500
            if (is_file(api_get_path(SYS_CSS_PATH).$this->themeDir.'learnpath.css')) {
501
                $css[] = api_get_path(WEB_CSS_PATH).$this->themeDir.'learnpath.css';
502
            }
503
        }
504
505
        $css_file_to_string = '';
506
        foreach ($css as $file) {
507
            $css_file_to_string .= api_get_css($file);
508
        }
509
510
        // @todo move this somewhere else. Special fix when using tablets in order to see the text near icons
511
        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...
512
            //hack in order to fix the actions buttons
513
            $css_file_to_string .= '<style>
514
                .td_actions a {
515
                    float:left;
516
                    width:100%;
517
                }
518
                .forum_message_left a {
519
                    float:left;
520
                    width:100%;
521
                }
522
                </style>';
523
        }
524
525
        $navigator_info = api_get_navigator();
526
        if ('Internet Explorer' == $navigator_info['name'] && '6' == $navigator_info['version']) {
527
            $css_file_to_string .= 'img, div { behavior: url('.api_get_path(WEB_LIBRARY_PATH).'javascript/iepngfix/iepngfix.htc) } '."\n";
528
        }
529
530
        if (!$disable_js_and_css_files) {
531
            $this->assign('css_custom_file_to_string', $css_file_to_string);
532
533
            $style_print = '';
534
            if (is_readable(api_get_path(SYS_CSS_PATH).$this->theme.'/print.css')) {
535
                $style_print = api_get_css(
536
                    api_get_path(WEB_CSS_PATH).$this->theme.'/print.css',
537
                    'print'
538
                );
539
            }
540
            $this->assign('css_style_print', $style_print);
541
        }
542
543
        // Logo
544
        $logo = return_logo($this->theme);
545
        $logoPdf = return_logo($this->theme, false);
546
        $this->assign('logo', $logo);
547
        $this->assign('logo_pdf', $logoPdf);
548
        $this->assign('show_media_element', 1);
549
    }
550
551
    /**
552
     * Declare and define the template variable that will be used to load
553
     * javascript libraries in the header.
554
     */
555
    public function set_js_files()
556
    {
557
        global $disable_js_and_css_files, $htmlHeadXtra;
558
        $isoCode = api_get_language_isocode();
559
        $selectLink = 'bootstrap-select/dist/js/i18n/defaults-'.$isoCode.'_'.strtoupper($isoCode).'.min.js';
560
561
        if ('en' == $isoCode) {
562
            $selectLink = 'bootstrap-select/dist/js/i18n/defaults-'.$isoCode.'_US.min.js';
563
        }
564
        // JS files
565
        $js_files = [
566
            'chosen/chosen.jquery.min.js',
567
        ];
568
569
        $viewBySession = 'true' === api_get_setting('my_courses_view_by_session');
570
571
        if (api_is_global_chat_enabled() || $viewBySession) {
572
            // Do not include the global chat in LP
573
            if (false == $this->show_learnpath &&
574
                true == $this->show_footer &&
575
                false == $this->hide_global_chat
0 ignored issues
show
Coding Style Best Practice introduced by
It seems like you are loosely comparing two booleans. Considering using the strict comparison === instead.

When comparing two booleans, it is generally considered safer to use the strict comparison operator.

Loading history...
576
            ) {
577
                $js_files[] = 'chat/js/chat.js';
578
            }
579
        }
580
581
        if ('true' === api_get_setting('accessibility_font_resize')) {
582
            $js_files[] = 'fontresize.js';
583
        }
584
585
        $js_file_to_string = '';
586
        $bowerJsFiles = [
587
            'modernizr/modernizr.js',
588
            'jquery/query.min.js',
589
            'bootstrap/dist/js/bootstrap.min.js',
590
            'jquery-ui/jquery-ui.min.js',
591
            'jqueryui-touch-punch/jquery.ui.touch-punch.min.js',
592
            'moment/min/moment-with-locales.js',
593
            //'bootstrap-daterangepicker/daterangepicker.js',
594
            'jquery-timeago/jquery.timeago.js',
595
            'mediaelement/mediaelement-and-player.min.js',
596
            'jqueryui-timepicker-addon/dist/jquery-ui-timepicker-addon.min.js',
597
            'image-map-resizer/js/imageMapResizer.min.js',
598
            'jquery.scrollbar/jquery.scrollbar.min.js',
599
            //'readmore-js/readmore.min.js',
600
            'bootstrap-select/dist/js/bootstrap-select.min.js',
601
            $selectLink,
602
            'select2/dist/js/select2.min.js',
603
            "select2/dist/js/i18n/$isoCode.js",
604
            'mediaelement/plugins/vrview/vrview.js',
605
        ];
606
607
        $features = api_get_configuration_value('video_features');
608
        if (!empty($features) && isset($features['features'])) {
609
            foreach ($features['features'] as $feature) {
610
                if ('vrview' === $feature) {
611
                    continue;
612
                }
613
                $bowerJsFiles[] = "mediaelement/plugins/$feature/$feature.js";
614
            }
615
        }
616
617
        if ('true' === api_get_setting('include_asciimathml_script')) {
618
            $bowerJsFiles[] = 'MathJax/MathJax.js?config=TeX-MML-AM_HTMLorMML';
619
        }
620
621
        if ('en' != $isoCode) {
622
            $bowerJsFiles[] = 'jqueryui-timepicker-addon/dist/i18n/jquery-ui-timepicker-'.$isoCode.'.js';
623
            $bowerJsFiles[] = 'jquery-ui/ui/minified/i18n/datepicker-'.$isoCode.'.min.js';
624
        }
625
626
        foreach ($bowerJsFiles as $file) {
627
            //$js_file_to_string .= '<script type="text/javascript" src="'.api_get_path(WEB_PUBLIC_PATH).'assets/'.$file.'"></script>'."\n";
628
        }
629
630
        foreach ($js_files as $file) {
631
            //$js_file_to_string .= api_get_js($file);
632
        }
633
634
        // Loading email_editor js
635
        if (!api_is_anonymous() && 'true' == api_get_setting('allow_email_editor')) {
636
            $template = $this->get_template('mail_editor/email_link.js.tpl');
637
            $js_file_to_string .= $this->fetch($template);
638
        }
639
640
        if (!$disable_js_and_css_files) {
641
            $this->assign('js_file_to_string', $js_file_to_string);
642
            $extraHeaders = '';
643
            //$extraHeaders = '<script>var _p = '.json_encode($this->getWebPaths(), JSON_PRETTY_PRINT).'</script>';
644
            //Adding jquery ui by default
645
            $extraHeaders .= api_get_jquery_ui_js();
646
            if (isset($htmlHeadXtra) && $htmlHeadXtra) {
647
                foreach ($htmlHeadXtra as &$this_html_head) {
648
                    $extraHeaders .= $this_html_head."\n";
649
                }
650
            }
651
652
            $ajax = api_get_path(WEB_AJAX_PATH);
653
            $courseId = api_get_course_id();
654
            if (empty($courseId)) {
655
                $courseLogoutCode = '
656
                <script>
657
                function courseLogout() {
658
                }
659
                </script>';
660
            } else {
661
                $courseLogoutCode = "
662
                <script>
663
                var logOutUrl = '".$ajax."course.ajax.php?a=course_logout&".api_get_cidreq()."';
664
                function courseLogout() {
665
                    $.ajax({
666
                        async : false,
667
                        url: logOutUrl,
668
                        success: function (data) {
669
                            return 1;
670
                        }
671
                    });
672
                }
673
                </script>";
674
            }
675
676
            $extraHeaders .= $courseLogoutCode;
677
            $this->assign('extra_headers', $extraHeaders);
678
        }
679
    }
680
681
    public static function setVueParams(&$params)
682
    {
683
        $params['is_authenticated'] = !api_is_anonymous();
684
        /*$user = api_get_user_entity(api_get_user_id());
685
        $encoded = '';
686
        if ($user) {
687
            $encoded = json_encode($user);
688
        }
689
        $params['user'] = $encoded;*/
690
        $params['from_vue'] = isset($_REQUEST['from_vue']) ? 1 : 0;
691
    }
692
693
    /**
694
     * @param array  $params
695
     * @param string $template
696
     *
697
     * @throws \Twig\Error\Error
698
     */
699
    public function returnResponse($params, $template)
700
    {
701
        $response = new Response();
702
        $content = Container::getTwig()->render($template, $params);
703
        $response->setContent($content);
704
        $response->send();
705
    }
706
707
    /**
708
     * Special function to declare last-minute JS libraries which depend on
709
     * other things to be declared first. In particular, it might be useful
710
     * under IE9 with compatibility mode, which for some reason is getting
711
     * upset when a variable is used in a function (even if not used yet)
712
     * when this variable hasn't been defined yet.
713
     */
714
    public function set_js_files_post()
715
    {
716
        global $disable_js_and_css_files;
717
        $js_files = [];
718
        if (api_is_global_chat_enabled()) {
719
            //Do not include the global chat in LP
720
            if (false == $this->show_learnpath && true == $this->show_footer && false == $this->hide_global_chat) {
0 ignored issues
show
Coding Style Best Practice introduced by
It seems like you are loosely comparing two booleans. Considering using the strict comparison === instead.

When comparing two booleans, it is generally considered safer to use the strict comparison operator.

Loading history...
721
                $js_files[] = 'chat/js/chat.js';
722
            }
723
        }
724
        $js_file_to_string = '';
725
        foreach ($js_files as $js_file) {
726
            $js_file_to_string .= api_get_js($js_file);
727
        }
728
        if (!$disable_js_and_css_files) {
729
            $this->assign('js_file_to_string_post', $js_file_to_string);
730
        }
731
    }
732
733
    /**
734
     * @param string $theme
735
     *
736
     * @return string
737
     */
738
    public static function getPortalIcon($theme)
739
    {
740
        // Default root chamilo favicon
741
        $icon = 'favicon.ico';
742
743
        // Added to verify if in the current Chamilo Theme exist a favicon
744
        $themeUrl = api_get_path(SYS_CSS_PATH).'themes/'.$theme.'/images/';
745
746
        // If exist pick the current chamilo theme favicon.
747
        if (is_file($themeUrl.'favicon.ico')) {
748
            $icon = 'build/css/themes/'.$theme.'/images/favicon.ico';
749
        }
750
751
        return $icon;
752
    }
753
754
    /**
755
     * Show footer js template.
756
     */
757
    public function show_footer_js_template()
758
    {
759
        $tpl = $this->get_template('layout/footer.js.tpl');
760
        $this->display($tpl);
761
    }
762
763
    /**
764
     * @param string $template
765
     *
766
     * @return string
767
     */
768
    public function fetch($template = null)
769
    {
770
        return $this->twig->render($template, $this->params);
771
    }
772
773
    /**
774
     * @param string $variable
775
     * @param mixed  $value
776
     */
777
    public function assign($variable, $value = '')
778
    {
779
        $this->params[$variable] = $value;
780
    }
781
782
    /**
783
     * Adds a body class for login pages.
784
     */
785
    public function setLoginBodyClass()
786
    {
787
        $this->assign('login_class', 'section-login');
788
    }
789
790
    /**
791
     * The theme that will be used if the database is not working.
792
     *
793
     * @return string
794
     */
795
    public static function getThemeFallback()
796
    {
797
        $theme = api_get_configuration_value('theme_fallback');
798
        if (empty($theme)) {
799
            $theme = 'chamilo';
800
        }
801
802
        return $theme;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $theme also could return the type boolean which is incompatible with the documented return type string.
Loading history...
803
    }
804
805
    /**
806
     * @return string
807
     */
808
    public function displayLoginForm()
809
    {
810
        $form = new FormValidator(
811
            'form-login',
812
            'POST',
813
            api_get_path(WEB_PUBLIC_PATH).'login_check',
814
            null,
815
            null,
816
            FormValidator::LAYOUT_BOX_NO_LABEL
817
        );
818
        $params = [
819
            'id' => '_username',
820
            'autofocus' => 'autofocus',
821
            'icon' => 'user fa-fw',
822
            'placeholder' => get_lang('Username'),
823
        ];
824
825
        // Avoid showing the autocapitalize option if the browser doesn't
826
        // support it: this attribute is against the HTML5 standard
827
        /*$browserAutoCapitalize = false;
828
        if (api_browser_support('autocapitalize')) {
829
            $browserAutoCapitalize = false;
830
            $params['autocapitalize'] = 'none';
831
        }*/
832
        $form->addText(
833
            '_username',
834
            get_lang('Username'),
835
            true,
836
            $params
837
        );
838
        $params = [
839
            'id' => '_password',
840
            'icon' => 'lock fa-fw',
841
            'placeholder' => get_lang('Pass'),
842
        ];
843
        /*if ($browserAutoCapitalize) {
844
            $params['autocapitalize'] = 'none';
845
        }*/
846
        $form->addElement(
847
            'password',
848
            '_password',
849
            get_lang('Pass'),
850
            $params
851
        );
852
853
        $token = Chamilo\CoreBundle\Framework\Container::$container->get('security.csrf.token_manager')->getToken('authenticate');
0 ignored issues
show
Bug introduced by
The method get() does not exist on null. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

853
        $token = Chamilo\CoreBundle\Framework\Container::$container->/** @scrutinizer ignore-call */ get('security.csrf.token_manager')->getToken('authenticate');

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
854
        $form->addHidden('_csrf_token', $token->getValue());
855
856
        // Captcha
857
        $captcha = api_get_setting('allow_captcha');
858
        $allowCaptcha = 'true' === $captcha;
859
860
        if ($allowCaptcha) {
861
            $useCaptcha = isset($_SESSION['loginFailed']) ? $_SESSION['loginFailed'] : null;
862
            if ($useCaptcha) {
863
                $ajax = api_get_path(WEB_AJAX_PATH).'form.ajax.php?a=get_captcha';
864
                $options = [
865
                    'width' => 250,
866
                    'height' => 90,
867
                    'callback' => $ajax.'&var='.basename(__FILE__, '.php'),
868
                    'sessionVar' => basename(__FILE__, '.php'),
869
                    'imageOptions' => [
870
                        'font_size' => 20,
871
                        'font_path' => api_get_path(SYS_FONTS_PATH).'opensans/',
872
                        'font_file' => 'OpenSans-Regular.ttf',
873
                        //'output' => 'gif'
874
                    ],
875
                ];
876
877
                // Minimum options using all defaults (including defaults for Image_Text):
878
                //$options = array('callback' => 'qfcaptcha_image.php');
879
                $captcha_question = $form->addElement('CAPTCHA_Image', 'captcha_question', '', $options);
880
                $form->addHtml(get_lang('Click on the image to load a new one.'));
881
882
                $form->addElement(
883
                    'text',
884
                    'captcha',
885
                    get_lang('Enter the letters you see.')
886
                );
887
                $form->addRule(
888
                    'captcha',
889
                    get_lang('Enter the characters you see on the image'),
890
                    'required',
891
                    null,
892
                    'client'
893
                );
894
                $form->addRule(
895
                    'captcha',
896
                    get_lang('The text you entered doesn\'t match the picture.'),
897
                    'CAPTCHA',
898
                    $captcha_question
899
                );
900
            }
901
        }
902
903
        $form->addButton(
904
            'submitAuth',
905
            get_lang('Login'),
906
            null,
907
            'primary',
908
            null,
909
            'btn-block'
910
        );
911
912
        $html = $form->returnForm();
913
914
        return $html;
915
    }
916
917
    /**
918
     * Returns the tutors names for the current course in session
919
     * Function to use in Twig templates.
920
     *
921
     * @return string
922
     */
923
    public static function returnTutorsNames()
924
    {
925
        $em = Database::getManager();
926
        $tutors = $em
927
            ->createQuery('
928
                SELECT u FROM ChamiloCoreBundle:User u
929
                INNER JOIN ChamiloCoreBundle:SessionRelCourseRelUser scu WITH u.id = scu.user
930
                WHERE scu.status = :teacher_status AND scu.session = :session AND scu.course = :course
931
            ')
932
            ->setParameters([
933
                'teacher_status' => SessionRelCourseRelUser::STATUS_COURSE_COACH,
934
                'session' => api_get_session_id(),
935
                'course' => api_get_course_int_id(),
936
            ])
937
            ->getResult();
938
939
        $names = [];
940
941
        /** @var User $tutor */
942
        foreach ($tutors as $tutor) {
943
            $names[] = UserManager::formatUserFullName($tutor);
944
        }
945
946
        return implode(CourseManager::USER_SEPARATOR, $names);
947
    }
948
949
    /**
950
     * @param int $code
951
     */
952
    public function setResponseCode($code)
953
    {
954
        $this->responseCode = $code;
955
    }
956
957
    public function getResponseCode()
958
    {
959
        return $this->responseCode;
960
    }
961
962
    /**
963
     * Assign HTML code to the 'bug_notification' template variable for the side tabs to report issues.
964
     *
965
     * @return bool Always return true because there is always a string, even if empty
966
     */
967
    public function assignBugNotification()
968
    {
969
        //@todo move this in the template
970
        $rightFloatMenu = '';
971
        $iconBug = Display::return_icon(
972
            'bug.png',
973
            get_lang('Report a bug'),
974
            [],
975
            ICON_SIZE_LARGE
976
        );
977
        if ('true' === api_get_setting('show_link_bug_notification') && $this->user_is_logged_in) {
978
            $rightFloatMenu = '<div class="report">
979
		        <a href="https://github.com/chamilo/chamilo-lms/wiki/How-to-report-issues" target="_blank">
980
                    '.$iconBug.'
981
                </a>
982
		        </div>';
983
        }
984
985
        if ('true' === api_get_setting('show_link_ticket_notification') &&
986
            $this->user_is_logged_in
987
        ) {
988
            // by default is project_id = 1
989
            $defaultProjectId = 1;
990
            $iconTicket = Display::return_icon(
991
                'help.png',
992
                get_lang('Ticket'),
993
                [],
994
                ICON_SIZE_LARGE
995
            );
996
            $courseInfo = api_get_course_info();
997
            $courseParams = '';
998
            if (!empty($courseInfo)) {
999
                $courseParams = api_get_cidreq();
1000
            }
1001
            $url = api_get_path(WEB_CODE_PATH).'ticket/tickets.php?project_id='.$defaultProjectId.'&'.$courseParams;
1002
1003
            $allow = TicketManager::userIsAllowInProject(api_get_user_info(), $defaultProjectId);
1004
1005
            if ($allow) {
1006
                $rightFloatMenu .= '<div class="help">
1007
                    <a href="'.$url.'" target="_blank">
1008
                        '.$iconTicket.'
1009
                    </a>
1010
                </div>';
1011
            }
1012
        }
1013
1014
        $this->assign('bug_notification', $rightFloatMenu);
1015
1016
        return true;
1017
    }
1018
1019
    /**
1020
     * Load legacy params.
1021
     */
1022
    private function loadLegacyParams()
1023
    {
1024
        // Set legacy breadcrumb
1025
        global $interbreadcrumb;
1026
1027
        $courseInfo = api_get_course_info();
1028
        if (!empty($courseInfo)) {
1029
            $url = $courseInfo['course_public_url'];
1030
            $sessionId = api_get_session_id();
1031
            if (!empty($sessionId)) {
1032
                $url .= '?sid='.$sessionId;
1033
            }
1034
            array_unshift(
1035
                $interbreadcrumb,
1036
                ['name' => $courseInfo['title'], 'url' => $url]
1037
            );
1038
        }
1039
1040
        $this->params['legacy_breadcrumb'] = json_encode($interbreadcrumb);
1041
1042
        global $htmlHeadXtra;
1043
        $this->params['legacy_javascript'] = $htmlHeadXtra;
1044
    }
1045
1046
    /**
1047
     * Prepare the _c array for template files. The _c array contains
1048
     * information about the current course.
1049
     */
1050
    private function set_course_parameters()
1051
    {
1052
        //Setting course id
1053
        $course = api_get_course_info();
1054
        if (empty($course)) {
1055
            $this->assign('course_is_set', false);
1056
1057
            return;
1058
        }
1059
        $this->assign('course_is_set', true);
1060
        $this->course_id = $course['id'];
1061
        $_c = [
1062
            'id' => $course['real_id'],
1063
            'code' => $course['code'],
1064
            'title' => $course['name'],
1065
            'visibility' => $course['visibility'],
1066
            'language' => $course['language'],
1067
            'directory' => $course['directory'],
1068
            'session_id' => api_get_session_id(),
1069
            'user_is_teacher' => api_is_course_admin(),
1070
            'student_view' => (!empty($_GET['isStudentView']) && 'true' == $_GET['isStudentView']),
1071
        ];
1072
        $this->assign('course_code', $course['code']);
1073
        $this->assign('_c', $_c);
1074
    }
1075
1076
    /**
1077
     * Manage specific HTTP headers security.
1078
     */
1079
    private function addHTTPSecurityHeaders()
1080
    {
1081
        // Implementation of HTTP headers security, as suggested and checked
1082
        // by https://securityheaders.io/
1083
        // Enable these settings in configuration.php to use them on your site
1084
        // Strict-Transport-Security
1085
        $setting = api_get_configuration_value('security_strict_transport');
1086
        if (!empty($setting)) {
1087
            header('Strict-Transport-Security: '.$setting);
1088
        }
1089
        // Content-Security-Policy
1090
        $setting = api_get_configuration_value('security_content_policy');
1091
        if (!empty($setting)) {
1092
            header('Content-Security-Policy: '.$setting);
1093
        }
1094
        $setting = api_get_configuration_value('security_content_policy_report_only');
1095
        if (!empty($setting)) {
1096
            header('Content-Security-Policy-Report-Only: '.$setting);
1097
        }
1098
        // Public-Key-Pins
1099
        $setting = api_get_configuration_value('security_public_key_pins');
1100
        if (!empty($setting)) {
1101
            header('Public-Key-Pins: '.$setting);
1102
        }
1103
        $setting = api_get_configuration_value('security_public_key_pins_report_only');
1104
        if (!empty($setting)) {
1105
            header('Public-Key-Pins-Report-Only: '.$setting);
1106
        }
1107
        // X-Frame-Options
1108
        $setting = api_get_configuration_value('security_x_frame_options');
1109
        if (!empty($setting)) {
1110
            header('X-Frame-Options: '.$setting);
1111
        }
1112
        // X-XSS-Protection
1113
        $setting = api_get_configuration_value('security_xss_protection');
1114
        if (!empty($setting)) {
1115
            header('X-XSS-Protection: '.$setting);
1116
        }
1117
        // X-Content-Type-Options
1118
        $setting = api_get_configuration_value('security_x_content_type_options');
1119
        if (!empty($setting)) {
1120
            header('X-Content-Type-Options: '.$setting);
1121
        }
1122
        // Referrer-Policy
1123
        $setting = api_get_configuration_value('security_referrer_policy');
1124
        if (!empty($setting)) {
1125
            header('Referrer-Policy: '.$setting);
1126
        }
1127
        // end of HTTP headers security block
1128
    }
1129
1130
    /**
1131
     * Assign favicon to the 'favico' template variable.
1132
     *
1133
     * @return bool Always return true because there is always at least one correct favicon.ico
1134
     */
1135
    private function assignFavIcon()
1136
    {
1137
        // Default root chamilo favicon
1138
        $favico = '<link rel="shortcut icon" href="'.api_get_path(WEB_PATH).'favicon.ico" type="image/x-icon" />';
1139
1140
        //Added to verify if in the current Chamilo Theme exist a favicon
1141
        $favicoThemeUrl = api_get_path(SYS_CSS_PATH).$this->themeDir.'images/';
1142
1143
        //If exist pick the current chamilo theme favicon
1144
        if (is_file($favicoThemeUrl.'favicon.ico')) {
1145
            $favico = '<link rel="shortcut icon" href="'.api_get_path(WEB_CSS_PATH).$this->themeDir.'images/favicon.ico" type="image/x-icon" />';
1146
        }
1147
1148
        if (api_is_multiple_url_enabled()) {
1149
            /*$access_url_id = api_get_current_access_url_id();
1150
            if ($access_url_id != -1) {
1151
                $url_info = api_get_access_url($access_url_id);
1152
                $url = api_remove_trailing_slash(
1153
                    preg_replace('/https?:\/\//i', '', $url_info['url'])
1154
                );
1155
                $clean_url = api_replace_dangerous_char($url);
1156
                $clean_url = str_replace('/', '-', $clean_url);
1157
                $clean_url .= '/';
1158
                $homep = api_get_path(REL_PATH).'home/'.$clean_url; //homep for Home Path
1159
                $icon_real_homep = api_get_path(SYS_APP_PATH).'home/'.$clean_url;
1160
                //we create the new dir for the new sites
1161
                if (is_file($icon_real_homep.'favicon.ico')) {
1162
                    $favico = '<link rel="shortcut icon" href="'.$homep.'favicon.ico" type="image/x-icon" />';
1163
                }
1164
            }*/
1165
        }
1166
1167
        $this->assign('favico', $favico);
1168
1169
        return true;
1170
    }
1171
1172
    /**
1173
     * Assign HTML code to the 'accessibility' template variable (usually shown above top menu).
1174
     *
1175
     * @return bool Always return true (even if empty string)
1176
     */
1177
    private function assignAccessibilityBlock()
1178
    {
1179
        $resize = '';
1180
        if ('true' == api_get_setting('accessibility_font_resize')) {
1181
            $resize .= '<div class="resize_font">';
1182
            $resize .= '<div class="btn-group">';
1183
            $resize .= '<a title="'.get_lang('Decrease the font size').'" href="#" class="decrease_font btn btn-default"><em class="fa fa-font"></em></a>';
1184
            $resize .= '<a title="'.get_lang('Reset the font size').'" href="#" class="reset_font btn btn-default"><em class="fa fa-font"></em></a>';
1185
            $resize .= '<a title="'.get_lang('Increase the font size').'" href="#" class="increase_font btn btn-default"><em class="fa fa-font"></em></a>';
1186
            $resize .= '</div>';
1187
            $resize .= '</div>';
1188
        }
1189
        $this->assign('accessibility', $resize);
1190
1191
        return true;
1192
    }
1193
1194
    /**
1195
     * Assign HTML code to the 'social_meta' template variable (usually shown above top menu).
1196
     *
1197
     * @return bool Always return true (even if empty string)
1198
     */
1199
    private function assignSocialMeta()
1200
    {
1201
        $socialMeta = '';
1202
        $metaTitle = api_get_setting('meta_title');
1203
        if (!empty($metaTitle)) {
1204
            $socialMeta .= '<meta name="twitter:card" content="summary" />'."\n";
1205
            $metaSite = api_get_setting('meta_twitter_site');
1206
            if (!empty($metaSite)) {
1207
                $socialMeta .= '<meta name="twitter:site" content="'.$metaSite.'" />'."\n";
0 ignored issues
show
Bug introduced by
Are you sure $metaSite of type array|string can be used in concatenation? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

1207
                $socialMeta .= '<meta name="twitter:site" content="'./** @scrutinizer ignore-type */ $metaSite.'" />'."\n";
Loading history...
1208
                $metaCreator = api_get_setting('meta_twitter_creator');
1209
                if (!empty($metaCreator)) {
1210
                    $socialMeta .= '<meta name="twitter:creator" content="'.$metaCreator.'" />'."\n";
0 ignored issues
show
Bug introduced by
Are you sure $metaCreator of type array|string can be used in concatenation? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

1210
                    $socialMeta .= '<meta name="twitter:creator" content="'./** @scrutinizer ignore-type */ $metaCreator.'" />'."\n";
Loading history...
1211
                }
1212
            }
1213
1214
            // The user badge page emits its own meta tags, so if this is
1215
            // enabled, ignore the global ones
1216
            $userId = isset($_GET['user']) ? intval($_GET['user']) : 0;
1217
            $skillId = isset($_GET['skill']) ? intval($_GET['skill']) : 0;
1218
1219
            if (!$userId && !$skillId) {
1220
                // no combination of user and skill ID has been defined,
1221
                // so print the normal or course-specific OpenGraph meta tags
1222
                // Check for a course ID
1223
                $courseId = api_get_course_int_id();
1224
                // Check session ID from session/id/about (see .htaccess)
1225
                $sessionId = isset($_GET['session_id']) ? intval($_GET['session_id']) : 0;
1226
1227
                if (false != $courseId) {
0 ignored issues
show
Bug Best Practice introduced by
It seems like you are loosely comparing $courseId of type integer to the boolean false. If you are specifically checking for non-zero, consider using something more explicit like > 0 or !== 0 instead.
Loading history...
1228
                    // If we are inside a course (even if within a session), publish info about the course
1229
                    $course = api_get_course_entity($courseId);
1230
                    // @TODO: support right-to-left in title
1231
                    $socialMeta .= '<meta property="og:title" content="'.$course->getTitle().' - '.$metaTitle.'" />'."\n";
0 ignored issues
show
Bug introduced by
Are you sure $metaTitle of type array|string can be used in concatenation? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

1231
                    $socialMeta .= '<meta property="og:title" content="'.$course->getTitle().' - './** @scrutinizer ignore-type */ $metaTitle.'" />'."\n";
Loading history...
1232
                    $socialMeta .= '<meta property="twitter:title" content="'.$course->getTitle().' - '.$metaTitle.'" />'."\n";
1233
                    $socialMeta .= '<meta property="og:url" content="'.api_get_course_url($course->getCode()).'" />'."\n";
1234
1235
                    $metaDescription = api_get_setting('meta_description');
1236
                    if (!empty($course->getDescription())) {
1237
                        $socialMeta .= '<meta property="og:description" content="'.strip_tags($course->getDescription()).'" />'."\n";
1238
                        $socialMeta .= '<meta property="twitter:description" content="'.strip_tags($course->getDescription()).'" />'."\n";
1239
                    } elseif (!empty($metaDescription)) {
1240
                        $socialMeta .= '<meta property="og:description" content="'.$metaDescription.'" />'."\n";
0 ignored issues
show
Bug introduced by
Are you sure $metaDescription of type array|string can be used in concatenation? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

1240
                        $socialMeta .= '<meta property="og:description" content="'./** @scrutinizer ignore-type */ $metaDescription.'" />'."\n";
Loading history...
1241
                        $socialMeta .= '<meta property="twitter:description" content="'.$metaDescription.'" />'."\n";
1242
                    }
1243
1244
                    $picture = Container::getIllustrationRepository()->getIllustrationUrl($course);
1245
                    if (!empty($picture)) {
1246
                        $socialMeta .= '<meta property="og:image" content="'.$picture.'" />'."\n";
1247
                        $socialMeta .= '<meta property="twitter:image" content="'.$picture.'" />'."\n";
1248
                        $socialMeta .= '<meta property="twitter:image:alt" content="'.$course->getTitle().' - '.$metaTitle.'" />'."\n";
1249
                    } else {
1250
                        $socialMeta .= $this->getMetaPortalImagePath($metaTitle);
1251
                    }
1252
                } elseif (0 !== $sessionId) {
1253
                    // If we are on a session "about" screen, publish info about the session
1254
                    $session = api_get_session_entity($sessionId);
1255
1256
                    $socialMeta .= '<meta property="og:title" content="'.$session->getName().' - '.$metaTitle.'" />'."\n";
1257
                    $socialMeta .= '<meta property="twitter:title" content="'.$session->getName().' - '.$metaTitle.'" />'."\n";
1258
                    $socialMeta .= '<meta property="og:url" content="'.api_get_path(WEB_PATH)."sessions/{$session->getId()}/about/".'" />'."\n";
1259
1260
                    $sessionValues = new ExtraFieldValue('session');
1261
                    $sessionImage = $sessionValues->get_values_by_handler_and_field_variable($session->getId(), 'image')['value'];
1262
                    //$sessionImageSysPath = api_get_path(SYS_UPLOAD_PATH).$sessionImage;
1263
                    if (!empty($sessionImage)) {
1264
                        $asset = Container::getAssetRepository()->find($sessionImage);
1265
                        $sessionImagePath = Container::getAssetRepository()->getAssetUrl($asset);
1266
                        if (!empty($sessionImagePath)) {
1267
                            $socialMeta .= '<meta property="og:image" content="'.$sessionImagePath.'" />'."\n";
1268
                            $socialMeta .= '<meta property="twitter:image" content="'.$sessionImagePath.'" />'."\n";
1269
                            $socialMeta .= '<meta property="twitter:image:alt" content="'.$session->getName().' - '.$metaTitle.'" />'."\n";
1270
                        }
1271
                    } else {
1272
                        $socialMeta .= $this->getMetaPortalImagePath($metaTitle);
1273
                    }
1274
                } else {
1275
                    // Otherwise (not a course nor a session, nor a user, nor a badge), publish portal info
1276
                    $socialMeta .= '<meta property="og:title" content="'.$metaTitle.'" />'."\n";
1277
                    $socialMeta .= '<meta property="twitter:title" content="'.$metaTitle.'" />'."\n";
1278
                    $socialMeta .= '<meta property="og:url" content="'.api_get_path(WEB_PATH).'" />'."\n";
1279
1280
                    $metaDescription = api_get_setting('meta_description');
1281
                    if (!empty($metaDescription)) {
1282
                        $socialMeta .= '<meta property="og:description" content="'.$metaDescription.'" />'."\n";
1283
                        $socialMeta .= '<meta property="twitter:description" content="'.$metaDescription.'" />'."\n";
1284
                    }
1285
                    $socialMeta .= $this->getMetaPortalImagePath($metaTitle);
1286
                }
1287
            }
1288
        }
1289
1290
        $this->assign('social_meta', $socialMeta);
1291
1292
        return true;
1293
    }
1294
1295
    /**
1296
     * Get platform meta image tag (check meta_image_path setting, then use the logo).
1297
     *
1298
     * @param string $imageAlt The alt attribute for the image
1299
     *
1300
     * @return string The meta image HTML tag, or empty
1301
     */
1302
    private function getMetaPortalImagePath($imageAlt = '')
1303
    {
1304
        // Load portal meta image if defined
1305
        $metaImage = api_get_setting('meta_image_path');
1306
        $metaImageSysPath = api_get_path(SYS_PATH).$metaImage;
0 ignored issues
show
Bug introduced by
Are you sure $metaImage of type array|string can be used in concatenation? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

1306
        $metaImageSysPath = api_get_path(SYS_PATH)./** @scrutinizer ignore-type */ $metaImage;
Loading history...
1307
        $metaImageWebPath = api_get_path(WEB_PATH).$metaImage;
1308
        $portalImageMeta = '';
1309
        if (!empty($metaImage)) {
1310
            if (is_file($metaImageSysPath)) {
1311
                $portalImageMeta = '<meta property="og:image" content="'.$metaImageWebPath.'" />'."\n";
1312
                $portalImageMeta .= '<meta property="twitter:image" content="'.$metaImageWebPath.'" />'."\n";
1313
                $portalImageMeta .= '<meta property="twitter:image:alt" content="'.$imageAlt.'" />'."\n";
1314
            }
1315
        } else {
1316
            $logo = ChamiloApi::getPlatformLogoPath($this->theme);
1317
            if (!empty($logo)) {
1318
                $portalImageMeta = '<meta property="og:image" content="'.$logo.'" />'."\n";
1319
                $portalImageMeta .= '<meta property="twitter:image" content="'.$logo.'" />'."\n";
1320
                $portalImageMeta .= '<meta property="twitter:image:alt" content="'.$imageAlt.'" />'."\n";
1321
            }
1322
        }
1323
1324
        return $portalImageMeta;
1325
    }
1326
}
1327