1
|
|
|
<?php |
2
|
|
|
/* For licensing terms, see /license.txt */ |
3
|
|
|
|
4
|
|
|
use Chamilo\CoreBundle\Component\Utils\ChamiloApi; |
5
|
|
|
use Chamilo\CoreBundle\Entity\SessionRelCourseRelUser; |
6
|
|
|
use Chamilo\UserBundle\Entity\User; |
7
|
|
|
|
8
|
|
|
/** |
9
|
|
|
* Class Template. |
10
|
|
|
* |
11
|
|
|
* @author Julio Montoya <[email protected]> |
12
|
|
|
* |
13
|
|
|
* @todo better organization of the class, methods and variables |
14
|
|
|
*/ |
15
|
|
|
class Template |
16
|
|
|
{ |
17
|
|
|
/** |
18
|
|
|
* The Template folder name see main/template. |
19
|
|
|
* |
20
|
|
|
* @var string |
21
|
|
|
*/ |
22
|
|
|
public $templateFolder = 'default'; |
23
|
|
|
|
24
|
|
|
/** |
25
|
|
|
* The theme that will be used: chamilo, public_admin, chamilo_red, etc |
26
|
|
|
* This variable is set from the database. |
27
|
|
|
* |
28
|
|
|
* @var string |
29
|
|
|
*/ |
30
|
|
|
public $theme = ''; |
31
|
|
|
|
32
|
|
|
/** |
33
|
|
|
* @var string |
34
|
|
|
*/ |
35
|
|
|
public $preview_theme = ''; |
36
|
|
|
public $title = null; |
37
|
|
|
public $show_header; |
38
|
|
|
public $show_footer; |
39
|
|
|
public $help; |
40
|
|
|
public $menu_navigation = []; //Used in the userportal.lib.php function: return_navigation_course_links() |
41
|
|
|
public $show_learnpath = false; // This is a learnpath section or not? |
42
|
|
|
public $plugin = null; |
43
|
|
|
public $course_id = null; |
44
|
|
|
public $user_is_logged_in = false; |
45
|
|
|
public $twig = null; |
46
|
|
|
|
47
|
|
|
/* Loads chamilo plugins */ |
48
|
|
|
public $load_plugins = false; |
49
|
|
|
public $params = []; |
50
|
|
|
public $force_plugin_load = false; |
51
|
|
|
public $responseCode = 0; |
52
|
|
|
private $themeDir; |
53
|
|
|
|
54
|
|
|
/** |
55
|
|
|
* @param string $title |
56
|
|
|
* @param bool $show_header |
57
|
|
|
* @param bool $show_footer |
58
|
|
|
* @param bool $show_learnpath |
59
|
|
|
* @param bool $hide_global_chat |
60
|
|
|
* @param bool $load_plugins |
61
|
|
|
* @param int $responseCode |
62
|
|
|
* @param bool $sendHeaders send http headers or not |
63
|
|
|
*/ |
64
|
|
|
public function __construct( |
65
|
|
|
$title = '', |
66
|
|
|
$show_header = true, |
67
|
|
|
$show_footer = true, |
68
|
|
|
$show_learnpath = false, |
69
|
|
|
$hide_global_chat = false, |
70
|
|
|
$load_plugins = true, |
71
|
|
|
$sendHeaders = true, |
72
|
|
|
$responseCode = 0 |
73
|
|
|
) { |
74
|
|
|
// Page title |
75
|
|
|
$this->title = $title; |
76
|
|
|
$this->show_learnpath = $show_learnpath; |
77
|
|
|
$this->setResponseCode($responseCode); |
78
|
|
|
|
79
|
|
|
if (empty($this->show_learnpath)) { |
80
|
|
|
$origin = api_get_origin(); |
81
|
|
|
if ($origin === 'learnpath') { |
82
|
|
|
$this->show_learnpath = true; |
83
|
|
|
$show_footer = false; |
84
|
|
|
$show_header = false; |
85
|
|
|
} |
86
|
|
|
} |
87
|
|
|
$this->hide_global_chat = $hide_global_chat; |
88
|
|
|
$this->load_plugins = $load_plugins; |
89
|
|
|
|
90
|
|
|
$template_paths = [ |
91
|
|
|
api_get_path(SYS_CODE_PATH).'template/overrides', // user defined templates |
92
|
|
|
api_get_path(SYS_CODE_PATH).'template', //template folder |
93
|
|
|
api_get_path(SYS_PLUGIN_PATH), // plugin folder |
94
|
|
|
]; |
95
|
|
|
|
96
|
|
|
$urlId = api_get_current_access_url_id(); |
97
|
|
|
$cache_folder = api_get_path(SYS_ARCHIVE_PATH).'twig/'.$urlId.'/'; |
98
|
|
|
|
99
|
|
|
if (!is_dir($cache_folder)) { |
100
|
|
|
mkdir($cache_folder, api_get_permissions_for_new_directories(), true); |
101
|
|
|
} |
102
|
|
|
|
103
|
|
|
$loader = new Twig_Loader_Filesystem($template_paths); |
104
|
|
|
|
105
|
|
|
$isTestMode = api_get_setting('server_type') === 'test'; |
106
|
|
|
|
107
|
|
|
//Setting Twig options depending on the server see http://twig.sensiolabs.org/doc/api.html#environment-options |
108
|
|
|
if ($isTestMode) { |
109
|
|
|
$options = [ |
110
|
|
|
//'cache' => api_get_path(SYS_ARCHIVE_PATH), //path to the cache folder |
111
|
|
|
'autoescape' => false, |
112
|
|
|
'debug' => true, |
113
|
|
|
'auto_reload' => true, |
114
|
|
|
'optimizations' => 0, |
115
|
|
|
// turn on optimizations with -1 |
116
|
|
|
'strict_variables' => false, |
117
|
|
|
//If set to false, Twig will silently ignore invalid variables |
118
|
|
|
]; |
119
|
|
|
} else { |
120
|
|
|
$options = [ |
121
|
|
|
'cache' => $cache_folder, |
122
|
|
|
//path to the cache folder |
123
|
|
|
'autoescape' => false, |
124
|
|
|
'debug' => false, |
125
|
|
|
'auto_reload' => false, |
126
|
|
|
'optimizations' => -1, |
127
|
|
|
// turn on optimizations with -1 |
128
|
|
|
'strict_variables' => false, |
129
|
|
|
//If set to false, Twig will silently ignore invalid variables |
130
|
|
|
]; |
131
|
|
|
} |
132
|
|
|
|
133
|
|
|
$this->twig = new Twig_Environment($loader, $options); |
134
|
|
|
|
135
|
|
|
if ($isTestMode) { |
136
|
|
|
$this->twig->addExtension(new Twig_Extension_Debug()); |
137
|
|
|
} |
138
|
|
|
|
139
|
|
|
// Twig filters setup |
140
|
|
|
$filters = [ |
141
|
|
|
'var_dump', |
142
|
|
|
'get_plugin_lang', |
143
|
|
|
'get_lang', |
144
|
|
|
'api_get_path', |
145
|
|
|
'api_get_local_time', |
146
|
|
|
'api_convert_and_format_date', |
147
|
|
|
'api_is_allowed_to_edit', |
148
|
|
|
'api_get_user_info', |
149
|
|
|
'api_get_configuration_value', |
150
|
|
|
'api_get_setting', |
151
|
|
|
'api_get_plugin_setting', |
152
|
|
|
[ |
153
|
|
|
'name' => 'return_message', |
154
|
|
|
'callable' => 'Display::return_message_and_translate', |
155
|
|
|
], |
156
|
|
|
[ |
157
|
|
|
'name' => 'display_page_header', |
158
|
|
|
'callable' => 'Display::page_header_and_translate', |
159
|
|
|
], |
160
|
|
|
[ |
161
|
|
|
'name' => 'display_page_subheader', |
162
|
|
|
'callable' => 'Display::page_subheader_and_translate', |
163
|
|
|
], |
164
|
|
|
[ |
165
|
|
|
'name' => 'icon', |
166
|
|
|
'callable' => 'Display::get_icon_path', |
167
|
|
|
], |
168
|
|
|
[ |
169
|
|
|
'name' => 'img', |
170
|
|
|
'callable' => 'Display::get_image', |
171
|
|
|
], |
172
|
|
|
[ |
173
|
|
|
'name' => 'format_date', |
174
|
|
|
'callable' => 'api_format_date', |
175
|
|
|
], |
176
|
|
|
[ |
177
|
|
|
'name' => 'get_template', |
178
|
|
|
'callable' => 'api_find_template', |
179
|
|
|
], |
180
|
|
|
[ |
181
|
|
|
'name' => 'date_to_time_ago', |
182
|
|
|
'callable' => 'Display::dateToStringAgoAndLongDate', |
183
|
|
|
], |
184
|
|
|
[ |
185
|
|
|
'name' => 'remove_xss', |
186
|
|
|
'callable' => 'Security::remove_XSS', |
187
|
|
|
], |
188
|
|
|
]; |
189
|
|
|
|
190
|
|
|
foreach ($filters as $filter) { |
191
|
|
|
if (is_array($filter)) { |
192
|
|
|
$this->twig->addFilter(new Twig_SimpleFilter($filter['name'], $filter['callable'])); |
193
|
|
|
} else { |
194
|
|
|
$this->twig->addFilter(new Twig_SimpleFilter($filter, $filter)); |
195
|
|
|
} |
196
|
|
|
} |
197
|
|
|
|
198
|
|
|
$functions = [ |
199
|
|
|
['name' => 'get_tutors_names', 'callable' => 'Template::returnTutorsNames'], |
200
|
|
|
['name' => 'get_teachers_names', 'callable' => 'Template::returnTeachersNames'], |
201
|
|
|
]; |
202
|
|
|
|
203
|
|
|
foreach ($functions as $function) { |
204
|
|
|
$this->twig->addFunction(new Twig_SimpleFunction($function['name'], $function['callable'])); |
205
|
|
|
} |
206
|
|
|
|
207
|
|
|
// Setting system variables |
208
|
|
|
$this->set_system_parameters(); |
209
|
|
|
|
210
|
|
|
// Setting user variables |
211
|
|
|
$this->set_user_parameters(); |
212
|
|
|
|
213
|
|
|
// Setting course variables |
214
|
|
|
$this->set_course_parameters(); |
215
|
|
|
|
216
|
|
|
// Setting administrator variables |
217
|
|
|
$this->setAdministratorParams(); |
218
|
|
|
//$this->setCSSEditor(); |
219
|
|
|
|
220
|
|
|
// Header and footer are showed by default |
221
|
|
|
$this->set_footer($show_footer); |
222
|
|
|
$this->set_header($show_header); |
223
|
|
|
|
224
|
|
|
$this->set_header_parameters($sendHeaders); |
225
|
|
|
$this->set_footer_parameters(); |
226
|
|
|
|
227
|
|
|
$defaultStyle = api_get_configuration_value('default_template'); |
228
|
|
|
if (!empty($defaultStyle)) { |
229
|
|
|
$this->templateFolder = $defaultStyle; |
|
|
|
|
230
|
|
|
} |
231
|
|
|
|
232
|
|
|
$this->assign('template', $this->templateFolder); |
233
|
|
|
$this->assign('locale', api_get_language_isocode()); |
234
|
|
|
$this->assign('login_class', null); |
235
|
|
|
|
236
|
|
|
$allow = api_get_configuration_value('show_language_selector_in_menu'); |
237
|
|
|
if ($allow) { |
238
|
|
|
$this->assign('language_form', api_display_language_form()); |
239
|
|
|
} |
240
|
|
|
|
241
|
|
|
if (api_get_configuration_value('notification_event')) { |
242
|
|
|
$this->assign('notification_event', '1'); |
243
|
|
|
} |
244
|
|
|
|
245
|
|
|
// Chamilo plugins |
246
|
|
|
if ($this->show_header) { |
247
|
|
|
if ($this->load_plugins) { |
248
|
|
|
$this->plugin = new AppPlugin(); |
249
|
|
|
|
250
|
|
|
//1. Showing installed plugins in regions |
251
|
|
|
$pluginRegions = $this->plugin->get_plugin_regions(); |
252
|
|
|
foreach ($pluginRegions as $region) { |
253
|
|
|
$this->set_plugin_region($region); |
254
|
|
|
} |
255
|
|
|
|
256
|
|
|
//2. Loading the course plugin info |
257
|
|
|
global $course_plugin; |
258
|
|
|
if (isset($course_plugin) && !empty($course_plugin) && !empty($this->course_id)) { |
259
|
|
|
//Load plugin get_langs |
260
|
|
|
$this->plugin->load_plugin_lang_variables($course_plugin); |
261
|
|
|
} |
262
|
|
|
} |
263
|
|
|
} |
264
|
|
|
} |
265
|
|
|
|
266
|
|
|
/** |
267
|
|
|
* Return the item's url key:. |
268
|
|
|
* |
269
|
|
|
* c_id=xx&id=xx |
270
|
|
|
* |
271
|
|
|
* @param object $item |
272
|
|
|
* |
273
|
|
|
* @return string |
274
|
|
|
*/ |
275
|
|
|
public static function key($item) |
276
|
|
|
{ |
277
|
|
|
$id = isset($item->id) ? $item->id : null; |
278
|
|
|
$c_id = isset($item->c_id) ? $item->c_id : null; |
279
|
|
|
$result = ''; |
280
|
|
|
if ($c_id) { |
281
|
|
|
$result = "c_id=$c_id"; |
282
|
|
|
} |
283
|
|
|
if ($id) { |
284
|
|
|
if ($result) { |
285
|
|
|
$result .= "&id=$id"; |
286
|
|
|
} else { |
287
|
|
|
$result .= "&id=$id"; |
288
|
|
|
} |
289
|
|
|
} |
290
|
|
|
|
291
|
|
|
return $result; |
292
|
|
|
} |
293
|
|
|
|
294
|
|
|
/** |
295
|
|
|
* @param string $helpInput |
296
|
|
|
*/ |
297
|
|
|
public function setHelp($helpInput = null) |
298
|
|
|
{ |
299
|
|
|
if (!empty($helpInput)) { |
300
|
|
|
$help = $helpInput; |
301
|
|
|
} else { |
302
|
|
|
$help = $this->help; |
303
|
|
|
} |
304
|
|
|
|
305
|
|
|
$content = ''; |
306
|
|
|
if (api_get_setting('enable_help_link') == 'true') { |
307
|
|
|
if (!empty($help)) { |
308
|
|
|
$help = Security::remove_XSS($help); |
309
|
|
|
$content = '<div class="help">'; |
310
|
|
|
$content .= Display::url( |
311
|
|
|
Display::return_icon('help.large.png', get_lang('Help')), |
312
|
|
|
api_get_path(WEB_CODE_PATH).'help/help.php?open='.$help, |
313
|
|
|
[ |
314
|
|
|
'class' => 'ajax', |
315
|
|
|
'data-title' => get_lang('Help'), |
316
|
|
|
] |
317
|
|
|
); |
318
|
|
|
$content .= '</div>'; |
319
|
|
|
} |
320
|
|
|
} |
321
|
|
|
$this->assign('help_content', $content); |
322
|
|
|
} |
323
|
|
|
|
324
|
|
|
/** |
325
|
|
|
* Use template system to parse the actions menu. |
326
|
|
|
* |
327
|
|
|
* @todo finish it! |
328
|
|
|
*/ |
329
|
|
|
public function set_actions($actions) |
330
|
|
|
{ |
331
|
|
|
$action_string = ''; |
332
|
|
|
if (!empty($actions)) { |
333
|
|
|
foreach ($actions as $action) { |
334
|
|
|
$action_string .= $action; |
335
|
|
|
} |
336
|
|
|
} |
337
|
|
|
$this->assign('actions', $actions); |
338
|
|
|
} |
339
|
|
|
|
340
|
|
|
/** |
341
|
|
|
* Shortcut to display a 1 col layout (index.php). |
342
|
|
|
* */ |
343
|
|
|
public function display_one_col_template() |
344
|
|
|
{ |
345
|
|
|
$tpl = $this->get_template('layout/layout_1_col.tpl'); |
346
|
|
|
$this->display($tpl); |
347
|
|
|
} |
348
|
|
|
|
349
|
|
|
/** |
350
|
|
|
* Shortcut to display a 2 col layout (userportal.php). |
351
|
|
|
*/ |
352
|
|
|
public function display_two_col_template() |
353
|
|
|
{ |
354
|
|
|
$tpl = $this->get_template('layout/layout_2_col.tpl'); |
355
|
|
|
$this->display($tpl); |
356
|
|
|
} |
357
|
|
|
|
358
|
|
|
/** |
359
|
|
|
* Displays an empty template. |
360
|
|
|
*/ |
361
|
|
|
public function display_blank_template() |
362
|
|
|
{ |
363
|
|
|
$tpl = $this->get_template('layout/blank.tpl'); |
364
|
|
|
$this->display($tpl); |
365
|
|
|
} |
366
|
|
|
|
367
|
|
|
/** |
368
|
|
|
* Displays an empty template. |
369
|
|
|
*/ |
370
|
|
|
public function displayBlankTemplateNoHeader() |
371
|
|
|
{ |
372
|
|
|
$tpl = $this->get_template('layout/blank_no_header.tpl'); |
373
|
|
|
$this->display($tpl); |
374
|
|
|
} |
375
|
|
|
|
376
|
|
|
/** |
377
|
|
|
* Displays an empty template. |
378
|
|
|
*/ |
379
|
|
|
public function display_no_layout_template() |
380
|
|
|
{ |
381
|
|
|
$tpl = $this->get_template('layout/no_layout.tpl'); |
382
|
|
|
$this->display($tpl); |
383
|
|
|
} |
384
|
|
|
|
385
|
|
|
/** |
386
|
|
|
* Sets the footer visibility. |
387
|
|
|
* |
388
|
|
|
* @param bool true if we show the footer |
389
|
|
|
*/ |
390
|
|
|
public function set_footer($status) |
391
|
|
|
{ |
392
|
|
|
$this->show_footer = $status; |
393
|
|
|
$this->assign('show_footer', $status); |
394
|
|
|
} |
395
|
|
|
|
396
|
|
|
/** |
397
|
|
|
* return true if toolbar has to be displayed for user. |
398
|
|
|
* |
399
|
|
|
* @return bool |
400
|
|
|
*/ |
401
|
|
|
public static function isToolBarDisplayedForUser() |
402
|
|
|
{ |
403
|
|
|
//Toolbar |
404
|
|
|
$show_admin_toolbar = api_get_setting('show_admin_toolbar'); |
405
|
|
|
$show_toolbar = false; |
406
|
|
|
|
407
|
|
|
switch ($show_admin_toolbar) { |
408
|
|
|
case 'do_not_show': |
409
|
|
|
break; |
410
|
|
|
case 'show_to_admin': |
411
|
|
|
if (api_is_platform_admin()) { |
412
|
|
|
$show_toolbar = true; |
413
|
|
|
} |
414
|
|
|
break; |
415
|
|
|
case 'show_to_admin_and_teachers': |
416
|
|
|
if (api_is_platform_admin() || api_is_allowed_to_edit()) { |
417
|
|
|
$show_toolbar = true; |
418
|
|
|
} |
419
|
|
|
break; |
420
|
|
|
case 'show_to_all': |
421
|
|
|
$show_toolbar = true; |
422
|
|
|
break; |
423
|
|
|
} |
424
|
|
|
|
425
|
|
|
return $show_toolbar; |
426
|
|
|
} |
427
|
|
|
|
428
|
|
|
/** |
429
|
|
|
* Sets the header visibility. |
430
|
|
|
* |
431
|
|
|
* @param bool true if we show the header |
432
|
|
|
*/ |
433
|
|
|
public function set_header($status) |
434
|
|
|
{ |
435
|
|
|
$this->show_header = $status; |
436
|
|
|
$this->assign('show_header', $status); |
437
|
|
|
|
438
|
|
|
$show_toolbar = 0; |
439
|
|
|
|
440
|
|
|
if (self::isToolBarDisplayedForUser()) { |
441
|
|
|
$show_toolbar = 1; |
442
|
|
|
} |
443
|
|
|
|
444
|
|
|
$this->assign('show_toolbar', $show_toolbar); |
445
|
|
|
|
446
|
|
|
// Only if course is available |
447
|
|
|
$courseToolBar = ''; |
448
|
|
|
$show_course_navigation_menu = ''; |
449
|
|
|
if (!empty($this->course_id) && $this->user_is_logged_in) { |
450
|
|
|
if (api_get_setting('show_toolshortcuts') != 'false') { |
451
|
|
|
// Course toolbar |
452
|
|
|
$courseToolBar = CourseHome::show_navigation_tool_shortcuts(); |
453
|
|
|
} |
454
|
|
|
if (api_get_setting('show_navigation_menu') != 'false') { |
455
|
|
|
// Course toolbar |
456
|
|
|
$show_course_navigation_menu = CourseHome::show_navigation_menu(); |
457
|
|
|
} |
458
|
|
|
} |
459
|
|
|
$this->assign('show_course_shortcut', $courseToolBar); |
460
|
|
|
$this->assign('show_course_navigation_menu', $show_course_navigation_menu); |
461
|
|
|
} |
462
|
|
|
|
463
|
|
|
/** |
464
|
|
|
* Returns the sub-folder and filename for the given tpl file. |
465
|
|
|
* |
466
|
|
|
* If template not found in overrides/ or custom template folder, the default template will be used. |
467
|
|
|
* |
468
|
|
|
* @param string $name |
469
|
|
|
* |
470
|
|
|
* @return string |
471
|
|
|
*/ |
472
|
|
|
public static function findTemplateFilePath($name) |
473
|
|
|
{ |
474
|
|
|
$sysTemplatePath = api_get_path(SYS_TEMPLATE_PATH); |
475
|
|
|
|
476
|
|
|
// Check if the tpl file is present in the main/template/overrides/ dir |
477
|
|
|
// Overrides is a special directory meant for temporary template |
478
|
|
|
// customization. It must be taken into account before anything else |
479
|
|
|
if (is_readable($sysTemplatePath."overrides/$name")) { |
480
|
|
|
return "overrides/$name"; |
481
|
|
|
} |
482
|
|
|
|
483
|
|
|
$defaultFolder = api_get_configuration_value('default_template'); |
484
|
|
|
|
485
|
|
|
// If a template folder has been manually defined, search for the right |
486
|
|
|
// file, and if not found, go for the same file in the default template |
487
|
|
|
if ($defaultFolder && $defaultFolder != 'default') { |
488
|
|
|
// Avoid missing template error, use the default file. |
489
|
|
|
if (file_exists($sysTemplatePath."$defaultFolder/$name")) { |
490
|
|
|
return "$defaultFolder/$name"; |
491
|
|
|
} |
492
|
|
|
} |
493
|
|
|
|
494
|
|
|
return "default/$name"; |
495
|
|
|
} |
496
|
|
|
|
497
|
|
|
/** |
498
|
|
|
* Call non-static for Template::findTemplateFilePath. |
499
|
|
|
* |
500
|
|
|
* @see Template::findTemplateFilePath() |
501
|
|
|
* |
502
|
|
|
* @param string $name |
503
|
|
|
* |
504
|
|
|
* @return string |
505
|
|
|
*/ |
506
|
|
|
public function get_template($name) |
507
|
|
|
{ |
508
|
|
|
return api_find_template($name); |
509
|
|
|
} |
510
|
|
|
|
511
|
|
|
/** |
512
|
|
|
* Get CSS themes sub-directory. |
513
|
|
|
* |
514
|
|
|
* @param string $theme |
515
|
|
|
* |
516
|
|
|
* @return string with a trailing slash, e.g. 'themes/chamilo_red/' |
517
|
|
|
*/ |
518
|
|
|
public static function getThemeDir($theme) |
519
|
|
|
{ |
520
|
|
|
$themeDir = 'themes/'.$theme.'/'; |
521
|
|
|
$virtualTheme = api_get_configuration_value('virtual_css_theme_folder'); |
522
|
|
|
if (!empty($virtualTheme)) { |
523
|
|
|
$virtualThemeList = api_get_themes(true); |
524
|
|
|
$isVirtualTheme = in_array($theme, array_keys($virtualThemeList)); |
525
|
|
|
if ($isVirtualTheme) { |
526
|
|
|
$themeDir = 'themes/'.$virtualTheme.'/'.$theme.'/'; |
527
|
|
|
} |
528
|
|
|
} |
529
|
|
|
|
530
|
|
|
return $themeDir; |
531
|
|
|
} |
532
|
|
|
|
533
|
|
|
/** |
534
|
|
|
* Set system parameters from api_get_configuration into _s array for use in TPLs |
535
|
|
|
* Also fills the _p array from getWebPaths(). |
536
|
|
|
* |
537
|
|
|
* @uses \self::getWebPaths() |
538
|
|
|
*/ |
539
|
|
|
public function set_system_parameters() |
540
|
|
|
{ |
541
|
|
|
// Get the interface language from global.inc.php |
542
|
|
|
global $language_interface; |
543
|
|
|
$this->theme = api_get_visual_theme(); |
544
|
|
|
if (!empty($this->preview_theme)) { |
545
|
|
|
$this->theme = $this->preview_theme; |
546
|
|
|
} |
547
|
|
|
|
548
|
|
|
$this->themeDir = self::getThemeDir($this->theme); |
549
|
|
|
|
550
|
|
|
// Setting app paths/URLs |
551
|
|
|
$this->assign('_p', $this->getWebPaths()); |
552
|
|
|
|
553
|
|
|
// Here we can add system parameters that can be use in any template |
554
|
|
|
$_s = [ |
555
|
|
|
'software_name' => api_get_configuration_value('software_name'), |
556
|
|
|
'system_version' => api_get_configuration_value('system_version'), |
557
|
|
|
'site_name' => api_get_setting('siteName'), |
558
|
|
|
'institution' => api_get_setting('Institution'), |
559
|
|
|
'institution_url' => api_get_setting('InstitutionUrl'), |
560
|
|
|
'date' => api_format_date('now', DATE_FORMAT_LONG), |
561
|
|
|
'timezone' => api_get_timezone(), |
562
|
|
|
'gamification_mode' => api_get_setting('gamification_mode'), |
563
|
|
|
'language_interface' => $language_interface, |
564
|
|
|
]; |
565
|
|
|
$this->assign('_s', $_s); |
566
|
|
|
} |
567
|
|
|
|
568
|
|
|
/** |
569
|
|
|
* Set theme, include mainstream CSS files. |
570
|
|
|
* |
571
|
|
|
* @see setCssCustomFiles() for additional CSS sheets |
572
|
|
|
*/ |
573
|
|
|
public function setCssFiles() |
574
|
|
|
{ |
575
|
|
|
global $disable_js_and_css_files; |
576
|
|
|
$css = []; |
577
|
|
|
|
578
|
|
|
$webPublicPath = api_get_path(WEB_PUBLIC_PATH); |
579
|
|
|
$webJsPath = api_get_path(WEB_LIBRARY_JS_PATH); |
580
|
|
|
|
581
|
|
|
// Default CSS Bootstrap |
582
|
|
|
$bowerCSSFiles = [ |
583
|
|
|
'fontawesome/css/font-awesome.min.css', |
584
|
|
|
'jquery-ui/themes/smoothness/theme.css', |
585
|
|
|
'jquery-ui/themes/smoothness/jquery-ui.min.css', |
586
|
|
|
'mediaelement/build/mediaelementplayer.min.css', |
587
|
|
|
'jqueryui-timepicker-addon/dist/jquery-ui-timepicker-addon.min.css', |
588
|
|
|
'bootstrap/dist/css/bootstrap.min.css', |
589
|
|
|
'jquery.scrollbar/jquery.scrollbar.css', |
590
|
|
|
'bootstrap-daterangepicker/daterangepicker.css', |
591
|
|
|
'bootstrap-select/dist/css/bootstrap-select.min.css', |
592
|
|
|
'select2/dist/css/select2.min.css', |
593
|
|
|
]; |
594
|
|
|
|
595
|
|
|
$hide = api_get_configuration_value('hide_flag_language_switcher'); |
596
|
|
|
|
597
|
|
|
if ($hide === false) { |
598
|
|
|
$bowerCSSFiles[] = 'flag-icon-css/css/flag-icon.min.css'; |
599
|
|
|
} |
600
|
|
|
|
601
|
|
|
foreach ($bowerCSSFiles as $file) { |
602
|
|
|
$css[] = api_get_cdn_path($webPublicPath.'assets/'.$file); |
603
|
|
|
} |
604
|
|
|
|
605
|
|
|
$css[] = $webJsPath.'mediaelement/plugins/vrview/vrview.css'; |
606
|
|
|
|
607
|
|
|
$features = api_get_configuration_value('video_features'); |
608
|
|
|
$defaultFeatures = [ |
609
|
|
|
'playpause', |
610
|
|
|
'current', |
611
|
|
|
'progress', |
612
|
|
|
'duration', |
613
|
|
|
'tracks', |
614
|
|
|
'volume', |
615
|
|
|
'fullscreen', |
616
|
|
|
'vrview', |
617
|
|
|
'markersrolls', |
618
|
|
|
]; |
619
|
|
|
|
620
|
|
|
if (!empty($features) && isset($features['features'])) { |
621
|
|
|
foreach ($features['features'] as $feature) { |
622
|
|
|
if ($feature === 'vrview') { |
623
|
|
|
continue; |
624
|
|
|
} |
625
|
|
|
$css[] = $webJsPath."mediaelement/plugins/$feature/$feature.min.css"; |
626
|
|
|
$defaultFeatures[] = $feature; |
627
|
|
|
} |
628
|
|
|
} |
629
|
|
|
|
630
|
|
|
$css[] = $webJsPath.'chosen/chosen.css'; |
631
|
|
|
|
632
|
|
|
if (api_is_global_chat_enabled()) { |
633
|
|
|
$css[] = $webJsPath.'chat/css/chat.css'; |
634
|
|
|
} |
635
|
|
|
$css_file_to_string = ''; |
636
|
|
|
foreach ($css as $file) { |
637
|
|
|
$css_file_to_string .= api_get_css($file); |
638
|
|
|
} |
639
|
|
|
|
640
|
|
|
if (!$disable_js_and_css_files) { |
641
|
|
|
$this->assign('css_static_file_to_string', $css_file_to_string); |
642
|
|
|
} |
643
|
|
|
|
644
|
|
|
$defaultFeatures = implode("','", $defaultFeatures); |
645
|
|
|
$this->assign('video_features', $defaultFeatures); |
646
|
|
|
} |
647
|
|
|
|
648
|
|
|
/** |
649
|
|
|
* Prepare custom CSS to be added at the very end of the <head> section. |
650
|
|
|
* |
651
|
|
|
* @see setCssFiles() for the mainstream CSS files |
652
|
|
|
*/ |
653
|
|
|
public function setCssCustomFiles() |
654
|
|
|
{ |
655
|
|
|
global $disable_js_and_css_files; |
656
|
|
|
// Base CSS |
657
|
|
|
$css[] = api_get_cdn_path(api_get_path(WEB_CSS_PATH).'base.css'); |
|
|
|
|
658
|
|
|
|
659
|
|
|
if ($this->show_learnpath) { |
660
|
|
|
$css[] = api_get_cdn_path(api_get_path(WEB_CSS_PATH).'scorm.css'); |
661
|
|
|
if (is_file(api_get_path(SYS_CSS_PATH).$this->themeDir.'learnpath.css')) { |
662
|
|
|
$css[] = api_get_path(WEB_CSS_PATH).$this->themeDir.'learnpath.css'; |
663
|
|
|
} |
664
|
|
|
} |
665
|
|
|
|
666
|
|
|
$css[] = api_get_cdn_path(api_get_path(WEB_CSS_PATH).$this->themeDir.'default.css'); |
667
|
|
|
$css[] = api_get_cdn_path(ChamiloApi::getEditorBlockStylePath()); |
668
|
|
|
|
669
|
|
|
$css_file_to_string = null; |
670
|
|
|
foreach ($css as $file) { |
671
|
|
|
$css_file_to_string .= api_get_css($file); |
672
|
|
|
} |
673
|
|
|
// @todo move this somewhere else. Special fix when using tablets in order to see the text near icons |
674
|
|
|
if (SHOW_TEXT_NEAR_ICONS == true) { |
|
|
|
|
675
|
|
|
//hack in order to fix the actions buttons |
676
|
|
|
$css_file_to_string .= '<style> |
677
|
|
|
.td_actions a { |
678
|
|
|
float:left; |
679
|
|
|
width:100%; |
680
|
|
|
} |
681
|
|
|
.forum_message_left a { |
682
|
|
|
float:left; |
683
|
|
|
width:100%; |
684
|
|
|
} |
685
|
|
|
</style>'; |
686
|
|
|
} |
687
|
|
|
|
688
|
|
|
$navigator_info = api_get_navigator(); |
689
|
|
|
if ($navigator_info['name'] == 'Internet Explorer' && $navigator_info['version'] == '6') { |
690
|
|
|
$css_file_to_string .= 'img, div { behavior: url('.api_get_path(WEB_LIBRARY_PATH).'javascript/iepngfix/iepngfix.htc) } '."\n"; |
691
|
|
|
} |
692
|
|
|
|
693
|
|
|
if (!$disable_js_and_css_files) { |
694
|
|
|
$this->assign('css_custom_file_to_string', $css_file_to_string); |
695
|
|
|
|
696
|
|
|
$style_print = ''; |
697
|
|
|
if (is_readable(api_get_path(SYS_CSS_PATH).$this->theme.'/print.css')) { |
698
|
|
|
$style_print = api_get_css( |
699
|
|
|
api_get_cdn_path(api_get_path(WEB_CSS_PATH).$this->theme.'/print.css'), |
700
|
|
|
'print' |
701
|
|
|
); |
702
|
|
|
} |
703
|
|
|
$this->assign('css_style_print', $style_print); |
704
|
|
|
} |
705
|
|
|
|
706
|
|
|
// Logo |
707
|
|
|
$logo = return_logo($this->theme); |
708
|
|
|
$logoPdf = return_logo($this->theme, false); |
709
|
|
|
$this->assign('logo', $logo); |
710
|
|
|
$this->assign('logo_pdf', $logoPdf); |
711
|
|
|
$this->assign('show_media_element', 1); |
712
|
|
|
} |
713
|
|
|
|
714
|
|
|
/** |
715
|
|
|
* Declare and define the template variable that will be used to load |
716
|
|
|
* javascript libraries in the header. |
717
|
|
|
*/ |
718
|
|
|
public function set_js_files() |
719
|
|
|
{ |
720
|
|
|
global $disable_js_and_css_files, $htmlHeadXtra; |
721
|
|
|
$isoCode = api_get_language_isocode(); |
722
|
|
|
$selectLink = 'bootstrap-select/dist/js/i18n/defaults-'.$isoCode.'_'.strtoupper($isoCode).'.min.js'; |
723
|
|
|
|
724
|
|
|
if ($isoCode == 'en') { |
725
|
|
|
$selectLink = 'bootstrap-select/dist/js/i18n/defaults-'.$isoCode.'_US.min.js'; |
726
|
|
|
} |
727
|
|
|
// JS files |
728
|
|
|
$js_files = [ |
729
|
|
|
'chosen/chosen.jquery.min.js', |
730
|
|
|
'mediaelement/plugins/vrview/vrview.js', |
731
|
|
|
'mediaelement/plugins/markersrolls/markersrolls.min.js', |
732
|
|
|
]; |
733
|
|
|
|
734
|
|
|
if (api_get_setting('accessibility_font_resize') === 'true') { |
735
|
|
|
$js_files[] = 'fontresize.js'; |
736
|
|
|
} |
737
|
|
|
|
738
|
|
|
$js_file_to_string = ''; |
739
|
|
|
$bowerJsFiles = [ |
740
|
|
|
'modernizr/modernizr.js', |
741
|
|
|
'jquery/dist/jquery.min.js', |
742
|
|
|
'bootstrap/dist/js/bootstrap.min.js', |
743
|
|
|
'jquery-ui/jquery-ui.min.js', |
744
|
|
|
'jqueryui-touch-punch/jquery.ui.touch-punch.min.js', |
745
|
|
|
'moment/min/moment-with-locales.js', |
746
|
|
|
'bootstrap-daterangepicker/daterangepicker.js', |
747
|
|
|
'jquery-timeago/jquery.timeago.js', |
748
|
|
|
'mediaelement/build/mediaelement-and-player.min.js', |
749
|
|
|
'jqueryui-timepicker-addon/dist/jquery-ui-timepicker-addon.min.js', |
750
|
|
|
'image-map-resizer/js/imageMapResizer.min.js', |
751
|
|
|
'jquery.scrollbar/jquery.scrollbar.min.js', |
752
|
|
|
'readmore-js/readmore.min.js', |
753
|
|
|
'bootstrap-select/dist/js/bootstrap-select.min.js', |
754
|
|
|
$selectLink, |
755
|
|
|
'select2/dist/js/select2.min.js', |
756
|
|
|
"select2/dist/js/i18n/$isoCode.js", |
757
|
|
|
'js-cookie/src/js.cookie.js', |
758
|
|
|
]; |
759
|
|
|
|
760
|
|
|
$viewBySession = api_get_setting('my_courses_view_by_session') === 'true'; |
761
|
|
|
|
762
|
|
|
if ($viewBySession || api_is_global_chat_enabled()) { |
763
|
|
|
// Do not include the global chat in LP |
764
|
|
|
if ($this->show_learnpath == false && |
765
|
|
|
$this->show_footer == true && |
|
|
|
|
766
|
|
|
$this->hide_global_chat == false |
|
|
|
|
767
|
|
|
) { |
768
|
|
|
$js_files[] = 'chat/js/chat.js'; |
769
|
|
|
$bowerJsFiles[] = 'linkifyjs/linkify.js'; |
770
|
|
|
$bowerJsFiles[] = 'linkifyjs/linkify-jquery.js'; |
771
|
|
|
} |
772
|
|
|
} |
773
|
|
|
|
774
|
|
|
$features = api_get_configuration_value('video_features'); |
775
|
|
|
if (!empty($features) && isset($features['features'])) { |
776
|
|
|
foreach ($features['features'] as $feature) { |
777
|
|
|
if ($feature === 'vrview') { |
778
|
|
|
continue; |
779
|
|
|
} |
780
|
|
|
$js_files[] = "mediaelement/plugins/$feature/$feature.min.js"; |
781
|
|
|
} |
782
|
|
|
} |
783
|
|
|
|
784
|
|
|
if (CHAMILO_LOAD_WYSIWYG === true) { |
785
|
|
|
$bowerJsFiles[] = 'ckeditor/ckeditor.js'; |
786
|
|
|
} |
787
|
|
|
|
788
|
|
|
if (api_get_setting('include_asciimathml_script') === 'true') { |
789
|
|
|
$bowerJsFiles[] = 'MathJax/MathJax.js?config=TeX-MML-AM_HTMLorMML'; |
790
|
|
|
} |
791
|
|
|
|
792
|
|
|
// If not English and the language is supported by timepicker, localize |
793
|
|
|
$assetsPath = api_get_path(SYS_PUBLIC_PATH).'assets/'; |
794
|
|
|
if ($isoCode != 'en') { |
795
|
|
|
if (is_file($assetsPath.'jqueryui-timepicker-addon/dist/i18n/jquery-ui-timepicker-'.$isoCode.'.js') && is_file($assetsPath.'jquery-ui/ui/minified/i18n/datepicker-'.$isoCode.'.min.js')) { |
796
|
|
|
$bowerJsFiles[] = 'jqueryui-timepicker-addon/dist/i18n/jquery-ui-timepicker-'.$isoCode.'.js'; |
797
|
|
|
$bowerJsFiles[] = 'jquery-ui/ui/minified/i18n/datepicker-'.$isoCode.'.min.js'; |
798
|
|
|
} |
799
|
|
|
} |
800
|
|
|
|
801
|
|
|
foreach ($bowerJsFiles as $file) { |
802
|
|
|
$js_file_to_string .= '<script type="text/javascript" src="'.api_get_cdn_path(api_get_path(WEB_PUBLIC_PATH).'assets/'.$file).'"></script>'."\n"; |
803
|
|
|
} |
804
|
|
|
|
805
|
|
|
foreach ($js_files as $file) { |
806
|
|
|
$js_file_to_string .= api_get_js($file); |
807
|
|
|
} |
808
|
|
|
|
809
|
|
|
// Loading email_editor js |
810
|
|
|
if (!api_is_anonymous() && api_get_setting('allow_email_editor') === 'true') { |
811
|
|
|
$template = $this->get_template('mail_editor/email_link.js.tpl'); |
812
|
|
|
$js_file_to_string .= $this->fetch($template); |
813
|
|
|
} |
814
|
|
|
|
815
|
|
|
if (!$disable_js_and_css_files) { |
816
|
|
|
$this->assign('js_file_to_string', $js_file_to_string); |
817
|
|
|
|
818
|
|
|
$extraHeaders = '<script>var _p = '.json_encode($this->getWebPaths(), JSON_PRETTY_PRINT).'</script>'; |
819
|
|
|
// Adding jquery ui by default |
820
|
|
|
$extraHeaders .= api_get_jquery_ui_js(); |
821
|
|
|
if (isset($htmlHeadXtra) && $htmlHeadXtra) { |
822
|
|
|
foreach ($htmlHeadXtra as &$this_html_head) { |
823
|
|
|
$extraHeaders .= $this_html_head."\n"; |
824
|
|
|
} |
825
|
|
|
} |
826
|
|
|
|
827
|
|
|
$ajax = api_get_path(WEB_AJAX_PATH); |
828
|
|
|
$courseId = api_get_course_id(); |
829
|
|
|
if (empty($courseId)) { |
830
|
|
|
$courseLogoutCode = ' |
831
|
|
|
<script> |
832
|
|
|
function courseLogout() { |
833
|
|
|
} |
834
|
|
|
</script>'; |
835
|
|
|
} else { |
836
|
|
|
$courseLogoutCode = " |
837
|
|
|
<script> |
838
|
|
|
var logOutUrl = '".$ajax."course.ajax.php?a=course_logout&".api_get_cidreq()."'; |
839
|
|
|
function courseLogout() { |
840
|
|
|
$.ajax({ |
841
|
|
|
async : false, |
842
|
|
|
url: logOutUrl, |
843
|
|
|
success: function (data) { |
844
|
|
|
return 1; |
845
|
|
|
} |
846
|
|
|
}); |
847
|
|
|
} |
848
|
|
|
</script>"; |
849
|
|
|
} |
850
|
|
|
|
851
|
|
|
$extraHeaders .= $courseLogoutCode; |
852
|
|
|
$this->assign('extra_headers', $extraHeaders); |
853
|
|
|
} |
854
|
|
|
} |
855
|
|
|
|
856
|
|
|
/** |
857
|
|
|
* Special function to declare last-minute JS libraries which depend on |
858
|
|
|
* other things to be declared first. In particular, it might be useful |
859
|
|
|
* under IE9 with compatibility mode, which for some reason is getting |
860
|
|
|
* upset when a variable is used in a function (even if not used yet) |
861
|
|
|
* when this variable hasn't been defined yet. |
862
|
|
|
*/ |
863
|
|
|
public function set_js_files_post() |
864
|
|
|
{ |
865
|
|
|
global $disable_js_and_css_files; |
866
|
|
|
$js_files = []; |
867
|
|
|
$bower = ''; |
868
|
|
|
if (api_is_global_chat_enabled()) { |
869
|
|
|
//Do not include the global chat in LP |
870
|
|
|
if ($this->show_learnpath == false && $this->show_footer == true && $this->hide_global_chat == false) { |
|
|
|
|
871
|
|
|
$js_files[] = 'chat/js/chat.js'; |
872
|
|
|
$bower .= '<script type="text/javascript" src="'.api_get_path(WEB_PUBLIC_PATH).'assets/linkifyjs/linkify.js"></script>'; |
873
|
|
|
$bower .= '<script type="text/javascript" src="'.api_get_path(WEB_PUBLIC_PATH).'assets/linkifyjs/linkify-jquery.js"></script>'; |
874
|
|
|
} |
875
|
|
|
} |
876
|
|
|
$js_file_to_string = ''; |
877
|
|
|
foreach ($js_files as $js_file) { |
878
|
|
|
$js_file_to_string .= api_get_js($js_file); |
879
|
|
|
} |
880
|
|
|
if (!$disable_js_and_css_files) { |
881
|
|
|
$this->assign('js_file_to_string_post', $js_file_to_string.$bower); |
882
|
|
|
} |
883
|
|
|
} |
884
|
|
|
|
885
|
|
|
/** |
886
|
|
|
* Show header template. |
887
|
|
|
*/ |
888
|
|
|
public function show_header_template() |
889
|
|
|
{ |
890
|
|
|
$tpl = $this->get_template('layout/show_header.tpl'); |
891
|
|
|
$this->display($tpl); |
892
|
|
|
} |
893
|
|
|
|
894
|
|
|
/** |
895
|
|
|
* Show footer template. |
896
|
|
|
*/ |
897
|
|
|
public function show_footer_template() |
898
|
|
|
{ |
899
|
|
|
$tpl = $this->get_template('layout/show_footer.tpl'); |
900
|
|
|
$this->display($tpl); |
901
|
|
|
} |
902
|
|
|
|
903
|
|
|
/** |
904
|
|
|
* Sets the plugin content in a template variable. |
905
|
|
|
* |
906
|
|
|
* @param string $pluginRegion |
907
|
|
|
*/ |
908
|
|
|
public function set_plugin_region($pluginRegion) |
909
|
|
|
{ |
910
|
|
|
if (!empty($pluginRegion)) { |
911
|
|
|
$regionContent = $this->plugin->load_region( |
912
|
|
|
$pluginRegion, |
913
|
|
|
$this, |
914
|
|
|
$this->force_plugin_load |
915
|
|
|
); |
916
|
|
|
|
917
|
|
|
$pluginList = $this->plugin->getInstalledPlugins(false); |
918
|
|
|
foreach ($pluginList as $plugin_name) { |
919
|
|
|
// The plugin_info variable is available inside the plugin index |
920
|
|
|
$pluginInfo = $this->plugin->getPluginInfo($plugin_name); |
921
|
|
|
|
922
|
|
|
if (isset($pluginInfo['is_course_plugin']) && $pluginInfo['is_course_plugin']) { |
923
|
|
|
$courseInfo = api_get_course_info(); |
924
|
|
|
if (!empty($courseInfo)) { |
925
|
|
|
if (isset($pluginInfo['obj']) && $pluginInfo['obj'] instanceof Plugin) { |
926
|
|
|
/** @var Plugin $plugin */ |
927
|
|
|
$plugin = $pluginInfo['obj']; |
928
|
|
|
$regionContent .= $plugin->renderRegion($pluginRegion); |
929
|
|
|
} |
930
|
|
|
} |
931
|
|
|
} else { |
932
|
|
|
continue; |
933
|
|
|
} |
934
|
|
|
} |
935
|
|
|
|
936
|
|
|
if (!empty($regionContent)) { |
937
|
|
|
$this->assign('plugin_'.$pluginRegion, $regionContent); |
938
|
|
|
} else { |
939
|
|
|
$this->assign('plugin_'.$pluginRegion, null); |
940
|
|
|
} |
941
|
|
|
} |
942
|
|
|
|
943
|
|
|
return null; |
944
|
|
|
} |
945
|
|
|
|
946
|
|
|
/** |
947
|
|
|
* @param string $template |
948
|
|
|
* |
949
|
|
|
* @return string |
950
|
|
|
*/ |
951
|
|
|
public function fetch($template = null) |
952
|
|
|
{ |
953
|
|
|
$template = $this->twig->loadTemplate($template); |
954
|
|
|
|
955
|
|
|
return $template->render($this->params); |
956
|
|
|
} |
957
|
|
|
|
958
|
|
|
/** |
959
|
|
|
* @param string $variable |
960
|
|
|
* @param mixed $value |
961
|
|
|
*/ |
962
|
|
|
public function assign($variable, $value = '') |
963
|
|
|
{ |
964
|
|
|
$this->params[$variable] = $value; |
965
|
|
|
} |
966
|
|
|
|
967
|
|
|
/** |
968
|
|
|
* Render the template. |
969
|
|
|
* |
970
|
|
|
* @param string $template The template path |
971
|
|
|
* @param bool $clearFlashMessages Clear the $_SESSION variables for flash messages |
972
|
|
|
*/ |
973
|
|
|
public function display($template, $clearFlashMessages = true) |
974
|
|
|
{ |
975
|
|
|
$this->assign('page_origin', api_get_origin()); |
976
|
|
|
$this->assign('flash_messages', Display::getFlashToString()); |
977
|
|
|
|
978
|
|
|
if ($clearFlashMessages) { |
979
|
|
|
Display::cleanFlashMessages(); |
980
|
|
|
} |
981
|
|
|
|
982
|
|
|
echo $this->twig->render($template, $this->params); |
983
|
|
|
} |
984
|
|
|
|
985
|
|
|
/** |
986
|
|
|
* Adds a body class for login pages. |
987
|
|
|
*/ |
988
|
|
|
public function setLoginBodyClass() |
989
|
|
|
{ |
990
|
|
|
$this->assign('login_class', 'section-login'); |
991
|
|
|
} |
992
|
|
|
|
993
|
|
|
/** |
994
|
|
|
* The theme that will be used if the database is not working. |
995
|
|
|
* |
996
|
|
|
* @return string |
997
|
|
|
*/ |
998
|
|
|
public static function getThemeFallback() |
999
|
|
|
{ |
1000
|
|
|
$theme = api_get_configuration_value('theme_fallback'); |
1001
|
|
|
if (empty($theme)) { |
1002
|
|
|
$theme = 'chamilo'; |
1003
|
|
|
} |
1004
|
|
|
|
1005
|
|
|
return $theme; |
|
|
|
|
1006
|
|
|
} |
1007
|
|
|
|
1008
|
|
|
/** |
1009
|
|
|
* @param bool|true $setLoginForm |
1010
|
|
|
*/ |
1011
|
|
|
public function setLoginForm($setLoginForm = true) |
1012
|
|
|
{ |
1013
|
|
|
global $loginFailed; |
1014
|
|
|
$userId = api_get_user_id(); |
1015
|
|
|
if (!($userId) || api_is_anonymous($userId)) { |
1016
|
|
|
// Only display if the user isn't logged in. |
1017
|
|
|
$this->assign( |
1018
|
|
|
'login_language_form', |
1019
|
|
|
api_display_language_form(true, true) |
1020
|
|
|
); |
1021
|
|
|
if ($setLoginForm) { |
1022
|
|
|
$this->assign('login_form', $this->displayLoginForm()); |
1023
|
|
|
|
1024
|
|
|
if ($loginFailed) { |
1025
|
|
|
$this->assign('login_failed', $this::handleLoginFailed()); |
|
|
|
|
1026
|
|
|
} |
1027
|
|
|
} |
1028
|
|
|
} |
1029
|
|
|
} |
1030
|
|
|
|
1031
|
|
|
/** |
1032
|
|
|
* @return string |
1033
|
|
|
*/ |
1034
|
|
|
public function handleLoginFailed() |
1035
|
|
|
{ |
1036
|
|
|
$message = get_lang('InvalidId'); |
1037
|
|
|
|
1038
|
|
|
if (!isset($_GET['error'])) { |
1039
|
|
|
if (api_is_self_registration_allowed()) { |
1040
|
|
|
$message = get_lang('InvalidForSelfRegistration'); |
1041
|
|
|
} |
1042
|
|
|
} else { |
1043
|
|
|
switch ($_GET['error']) { |
1044
|
|
|
case '': |
1045
|
|
|
if (api_is_self_registration_allowed()) { |
1046
|
|
|
$message = get_lang('InvalidForSelfRegistration'); |
1047
|
|
|
} |
1048
|
|
|
break; |
1049
|
|
|
case 'account_expired': |
1050
|
|
|
$message = get_lang('AccountExpired'); |
1051
|
|
|
break; |
1052
|
|
|
case 'account_inactive': |
1053
|
|
|
$message = get_lang('AccountInactive'); |
1054
|
|
|
|
1055
|
|
|
if (api_get_setting('allow_registration') === 'confirmation') { |
1056
|
|
|
$message = get_lang('AccountNotConfirmed').PHP_EOL; |
1057
|
|
|
$message .= Display::url( |
1058
|
|
|
get_lang('ReSendConfirmationMail'), |
1059
|
|
|
api_get_path(WEB_PATH).'main/auth/resend_confirmation_mail.php', |
1060
|
|
|
['class' => 'alert-link'] |
1061
|
|
|
); |
1062
|
|
|
} |
1063
|
|
|
break; |
1064
|
|
|
case 'user_password_incorrect': |
1065
|
|
|
$message = get_lang('InvalidId'); |
1066
|
|
|
break; |
1067
|
|
|
case 'access_url_inactive': |
1068
|
|
|
$message = get_lang('AccountURLInactive'); |
1069
|
|
|
break; |
1070
|
|
|
case 'wrong_captcha': |
1071
|
|
|
$message = get_lang('TheTextYouEnteredDoesNotMatchThePicture'); |
1072
|
|
|
break; |
1073
|
|
|
case 'blocked_by_captcha': |
1074
|
|
|
$message = get_lang('AccountBlockedByCaptcha'); |
1075
|
|
|
break; |
1076
|
|
|
case 'multiple_connection_not_allowed': |
1077
|
|
|
$message = get_lang('MultipleConnectionsAreNotAllow'); |
1078
|
|
|
break; |
1079
|
|
|
case 'unrecognize_sso_origin': |
1080
|
|
|
//$message = get_lang('SSOError'); |
1081
|
|
|
break; |
1082
|
|
|
} |
1083
|
|
|
} |
1084
|
|
|
|
1085
|
|
|
return Display::return_message($message, 'error', false); |
1086
|
|
|
} |
1087
|
|
|
|
1088
|
|
|
public static function displayCASLoginButton($label = null) |
1089
|
|
|
{ |
1090
|
|
|
$course = api_get_course_id(); |
1091
|
|
|
$form = new FormValidator( |
1092
|
|
|
'form-cas-login', |
1093
|
|
|
'POST', |
1094
|
|
|
$_SERVER['REQUEST_URI'], |
1095
|
|
|
null, |
1096
|
|
|
null, |
1097
|
|
|
FormValidator::LAYOUT_BOX_NO_LABEL |
1098
|
|
|
); |
1099
|
|
|
$form->addHidden('forceCASAuthentication', 1); |
1100
|
|
|
$form->addButton( |
1101
|
|
|
'casLoginButton', |
1102
|
|
|
is_null($label) ? sprintf(get_lang('LoginWithYourAccount'), api_get_setting("Institution")) : $label, |
1103
|
|
|
api_get_setting("casLogoURL"), |
1104
|
|
|
'primary', |
1105
|
|
|
null, |
1106
|
|
|
'btn-block' |
1107
|
|
|
); |
1108
|
|
|
|
1109
|
|
|
return $form->returnForm(); |
1110
|
|
|
} |
1111
|
|
|
|
1112
|
|
|
public static function displayCASLogoutButton($label = null) |
1113
|
|
|
{ |
1114
|
|
|
$form = new FormValidator( |
1115
|
|
|
'form-cas-logout', |
1116
|
|
|
'GET', |
1117
|
|
|
api_get_path(WEB_PATH), |
1118
|
|
|
null, |
1119
|
|
|
null, |
1120
|
|
|
FormValidator::LAYOUT_BOX_NO_LABEL |
1121
|
|
|
); |
1122
|
|
|
$form->addHidden('logout', 1); |
1123
|
|
|
$form->addButton( |
1124
|
|
|
'casLogoutButton', |
1125
|
|
|
is_null($label) ? sprintf(get_lang('LogoutWithYourAccount'), api_get_setting("Institution")) : $label, |
1126
|
|
|
api_get_setting("casLogoURL"), |
1127
|
|
|
'primary', |
1128
|
|
|
null, |
1129
|
|
|
'btn-block' |
1130
|
|
|
); |
1131
|
|
|
|
1132
|
|
|
return $form->returnForm(); |
1133
|
|
|
} |
1134
|
|
|
|
1135
|
|
|
/** |
1136
|
|
|
* @throws Exception |
1137
|
|
|
* |
1138
|
|
|
* @return string |
1139
|
|
|
*/ |
1140
|
|
|
public static function displayLoginForm() |
1141
|
|
|
{ |
1142
|
|
|
// Get the $cas array from app/config/auth.conf.php |
1143
|
|
|
global $cas; |
1144
|
|
|
|
1145
|
|
|
if (is_array($cas) && array_key_exists('replace_login_form', $cas) && $cas['replace_login_form']) { |
1146
|
|
|
return self::displayCASLoginButton(); |
1147
|
|
|
} |
1148
|
|
|
|
1149
|
|
|
$form = new FormValidator( |
1150
|
|
|
'formLogin', |
1151
|
|
|
'POST', |
1152
|
|
|
null, |
1153
|
|
|
null, |
1154
|
|
|
null, |
1155
|
|
|
FormValidator::LAYOUT_BOX_NO_LABEL |
1156
|
|
|
); |
1157
|
|
|
$params = [ |
1158
|
|
|
'id' => 'login', |
1159
|
|
|
'autofocus' => 'autofocus', |
1160
|
|
|
'icon' => 'user fa-fw', |
1161
|
|
|
'placeholder' => get_lang('UserName'), |
1162
|
|
|
]; |
1163
|
|
|
$browserAutoCapitalize = false; |
1164
|
|
|
// Avoid showing the autocapitalize option if the browser doesn't |
1165
|
|
|
// support it: this attribute is against the HTML5 standard |
1166
|
|
|
if (api_browser_support('autocapitalize')) { |
1167
|
|
|
$browserAutoCapitalize = false; |
1168
|
|
|
$params['autocapitalize'] = 'none'; |
1169
|
|
|
} |
1170
|
|
|
$form->addText( |
1171
|
|
|
'login', |
1172
|
|
|
get_lang('UserName'), |
1173
|
|
|
true, |
1174
|
|
|
$params |
1175
|
|
|
); |
1176
|
|
|
$params = [ |
1177
|
|
|
'id' => 'password', |
1178
|
|
|
'icon' => 'lock fa-fw', |
1179
|
|
|
'placeholder' => get_lang('Pass'), |
1180
|
|
|
]; |
1181
|
|
|
if ($browserAutoCapitalize) { |
1182
|
|
|
$params['autocapitalize'] = 'none'; |
1183
|
|
|
} |
1184
|
|
|
$form->addElement( |
1185
|
|
|
'password', |
1186
|
|
|
'password', |
1187
|
|
|
get_lang('Pass'), |
1188
|
|
|
$params |
1189
|
|
|
); |
1190
|
|
|
// Captcha |
1191
|
|
|
$captcha = api_get_setting('allow_captcha'); |
1192
|
|
|
$allowCaptcha = $captcha === 'true'; |
1193
|
|
|
|
1194
|
|
|
if ($allowCaptcha) { |
1195
|
|
|
$useCaptcha = isset($_SESSION['loginFailed']) ? $_SESSION['loginFailed'] : null; |
1196
|
|
|
if ($useCaptcha) { |
1197
|
|
|
$ajax = api_get_path(WEB_AJAX_PATH).'form.ajax.php?a=get_captcha'; |
1198
|
|
|
$options = [ |
1199
|
|
|
'width' => 250, |
1200
|
|
|
'height' => 90, |
1201
|
|
|
'callback' => $ajax.'&var='.basename(__FILE__, '.php'), |
1202
|
|
|
'sessionVar' => basename(__FILE__, '.php'), |
1203
|
|
|
'imageOptions' => [ |
1204
|
|
|
'font_size' => 20, |
1205
|
|
|
'font_path' => api_get_path(SYS_FONTS_PATH).'opensans/', |
1206
|
|
|
'font_file' => 'OpenSans-Regular.ttf', |
1207
|
|
|
//'output' => 'gif' |
1208
|
|
|
], |
1209
|
|
|
]; |
1210
|
|
|
|
1211
|
|
|
// Minimum options using all defaults (including defaults for Image_Text): |
1212
|
|
|
//$options = array('callback' => 'qfcaptcha_image.php'); |
1213
|
|
|
$captchaQuestion = $form->addElement('CAPTCHA_Image', 'captcha_question', '', $options); |
1214
|
|
|
$form->addHtml(get_lang('ClickOnTheImageForANewOne')); |
1215
|
|
|
|
1216
|
|
|
$form->addElement( |
1217
|
|
|
'text', |
1218
|
|
|
'captcha', |
1219
|
|
|
get_lang('EnterTheLettersYouSee') |
1220
|
|
|
); |
1221
|
|
|
$form->addRule( |
1222
|
|
|
'captcha', |
1223
|
|
|
get_lang('EnterTheCharactersYouReadInTheImage'), |
1224
|
|
|
'required', |
1225
|
|
|
null, |
1226
|
|
|
'client' |
1227
|
|
|
); |
1228
|
|
|
$form->addRule( |
1229
|
|
|
'captcha', |
1230
|
|
|
get_lang('TheTextYouEnteredDoesNotMatchThePicture'), |
1231
|
|
|
'CAPTCHA', |
1232
|
|
|
$captchaQuestion |
1233
|
|
|
); |
1234
|
|
|
} |
1235
|
|
|
} |
1236
|
|
|
|
1237
|
|
|
$form->addButton( |
1238
|
|
|
'submitAuth', |
1239
|
|
|
get_lang('LoginEnter'), |
1240
|
|
|
null, |
1241
|
|
|
'primary', |
1242
|
|
|
null, |
1243
|
|
|
'btn-block' |
1244
|
|
|
); |
1245
|
|
|
|
1246
|
|
|
$html = $form->returnForm(); |
1247
|
|
|
if (api_get_setting('openid_authentication') == 'true') { |
1248
|
|
|
include_once api_get_path(SYS_CODE_PATH).'auth/openid/login.php'; |
1249
|
|
|
$html .= '<div>'.openid_form().'</div>'; |
|
|
|
|
1250
|
|
|
} |
1251
|
|
|
|
1252
|
|
|
$pluginKeycloak = api_get_plugin_setting('keycloak', 'tool_enable') === 'true'; |
1253
|
|
|
$plugin = null; |
1254
|
|
|
if ($pluginKeycloak) { |
1255
|
|
|
$pluginUrl = api_get_path(WEB_PLUGIN_PATH).'keycloak/start.php?sso'; |
1256
|
|
|
$pluginUrl = Display::url('Keycloak', $pluginUrl, ['class' => 'btn btn-primary']); |
1257
|
|
|
$html .= '<div>'.$pluginUrl.'</div>'; |
1258
|
|
|
} |
1259
|
|
|
|
1260
|
|
|
$html .= '<div></div>'; |
1261
|
|
|
|
1262
|
|
|
return $html; |
1263
|
|
|
} |
1264
|
|
|
|
1265
|
|
|
/** |
1266
|
|
|
* Returns the tutors names for the current course in session |
1267
|
|
|
* Function to use in Twig templates. |
1268
|
|
|
* |
1269
|
|
|
* @return string |
1270
|
|
|
*/ |
1271
|
|
|
public static function returnTutorsNames() |
1272
|
|
|
{ |
1273
|
|
|
$em = Database::getManager(); |
1274
|
|
|
$tutors = $em |
1275
|
|
|
->createQuery(' |
1276
|
|
|
SELECT u FROM ChamiloUserBundle:User u |
1277
|
|
|
INNER JOIN ChamiloCoreBundle:SessionRelCourseRelUser scu WITH u.id = scu.user |
1278
|
|
|
WHERE scu.status = :teacher_status AND scu.session = :session AND scu.course = :course |
1279
|
|
|
') |
1280
|
|
|
->setParameters([ |
1281
|
|
|
'teacher_status' => SessionRelCourseRelUser::STATUS_COURSE_COACH, |
1282
|
|
|
'session' => api_get_session_id(), |
1283
|
|
|
'course' => api_get_course_int_id(), |
1284
|
|
|
]) |
1285
|
|
|
->getResult(); |
1286
|
|
|
|
1287
|
|
|
$names = []; |
1288
|
|
|
|
1289
|
|
|
/** @var User $tutor */ |
1290
|
|
|
foreach ($tutors as $tutor) { |
1291
|
|
|
$names[] = UserManager::formatUserFullName($tutor); |
1292
|
|
|
} |
1293
|
|
|
|
1294
|
|
|
return implode(CourseManager::USER_SEPARATOR, $names); |
1295
|
|
|
} |
1296
|
|
|
|
1297
|
|
|
/** |
1298
|
|
|
* Returns the teachers name for the current course |
1299
|
|
|
* Function to use in Twig templates. |
1300
|
|
|
* |
1301
|
|
|
* @return string |
1302
|
|
|
*/ |
1303
|
|
|
public static function returnTeachersNames() |
1304
|
|
|
{ |
1305
|
|
|
$em = Database::getManager(); |
1306
|
|
|
$teachers = $em |
1307
|
|
|
->createQuery(' |
1308
|
|
|
SELECT u FROM ChamiloUserBundle:User u |
1309
|
|
|
INNER JOIN ChamiloCoreBundle:CourseRelUser cu WITH u.id = cu.user |
1310
|
|
|
WHERE cu.status = :teacher_status AND cu.course = :course |
1311
|
|
|
') |
1312
|
|
|
->setParameters([ |
1313
|
|
|
'teacher_status' => User::COURSE_MANAGER, |
1314
|
|
|
'course' => api_get_course_int_id(), |
1315
|
|
|
]) |
1316
|
|
|
->getResult(); |
1317
|
|
|
|
1318
|
|
|
$names = []; |
1319
|
|
|
|
1320
|
|
|
/** @var User $teacher */ |
1321
|
|
|
foreach ($teachers as $teacher) { |
1322
|
|
|
$names[] = UserManager::formatUserFullName($teacher); |
1323
|
|
|
} |
1324
|
|
|
|
1325
|
|
|
return implode(CourseManager::USER_SEPARATOR, $names); |
1326
|
|
|
} |
1327
|
|
|
|
1328
|
|
|
/** |
1329
|
|
|
* @param int $code |
1330
|
|
|
*/ |
1331
|
|
|
public function setResponseCode($code) |
1332
|
|
|
{ |
1333
|
|
|
$this->responseCode = $code; |
1334
|
|
|
} |
1335
|
|
|
|
1336
|
|
|
/** |
1337
|
|
|
* @param string $code |
1338
|
|
|
*/ |
1339
|
|
|
public function getResponseCode() |
1340
|
|
|
{ |
1341
|
|
|
return $this->responseCode; |
1342
|
|
|
} |
1343
|
|
|
|
1344
|
|
|
/** |
1345
|
|
|
* Assign HTML code to the 'bug_notification' template variable for the side tabs to report issues. |
1346
|
|
|
* |
1347
|
|
|
* @return bool Always return true because there is always a string, even if empty |
1348
|
|
|
*/ |
1349
|
|
|
public function assignBugNotification() |
1350
|
|
|
{ |
1351
|
|
|
//@todo move this in the template |
1352
|
|
|
$rightFloatMenu = ''; |
1353
|
|
|
$iconBug = Display::return_icon( |
1354
|
|
|
'bug.png', |
1355
|
|
|
get_lang('ReportABug'), |
1356
|
|
|
[], |
1357
|
|
|
ICON_SIZE_LARGE |
1358
|
|
|
); |
1359
|
|
|
if (api_get_setting('show_link_bug_notification') === 'true' && $this->user_is_logged_in) { |
1360
|
|
|
$rightFloatMenu = '<div class="report"> |
1361
|
|
|
<a href="https://github.com/chamilo/chamilo-lms/wiki/How-to-report-issues" target="_blank"> |
1362
|
|
|
'.$iconBug.' |
1363
|
|
|
</a> |
1364
|
|
|
</div>'; |
1365
|
|
|
} |
1366
|
|
|
|
1367
|
|
|
if (api_get_setting('show_link_ticket_notification') === 'true' && |
1368
|
|
|
$this->user_is_logged_in |
1369
|
|
|
) { |
1370
|
|
|
// by default is project_id = 1 |
1371
|
|
|
$defaultProjectId = 1; |
1372
|
|
|
$iconTicket = Display::return_icon( |
1373
|
|
|
'help.png', |
1374
|
|
|
get_lang('Ticket'), |
1375
|
|
|
[], |
1376
|
|
|
ICON_SIZE_LARGE |
1377
|
|
|
); |
1378
|
|
|
$courseInfo = api_get_course_info(); |
1379
|
|
|
$courseParams = ''; |
1380
|
|
|
if (!empty($courseInfo)) { |
1381
|
|
|
$courseParams = api_get_cidreq(); |
1382
|
|
|
} |
1383
|
|
|
$url = api_get_path(WEB_CODE_PATH).'ticket/tickets.php?project_id='.$defaultProjectId.'&'.$courseParams; |
1384
|
|
|
|
1385
|
|
|
$allow = TicketManager::userIsAllowInProject(api_get_user_info(), $defaultProjectId); |
1386
|
|
|
|
1387
|
|
|
if ($allow) { |
1388
|
|
|
$rightFloatMenu .= '<div class="help"> |
1389
|
|
|
<a href="'.$url.'" target="_blank"> |
1390
|
|
|
'.$iconTicket.' |
1391
|
|
|
</a> |
1392
|
|
|
</div>'; |
1393
|
|
|
} |
1394
|
|
|
} |
1395
|
|
|
|
1396
|
|
|
$this->assign('bug_notification', $rightFloatMenu); |
1397
|
|
|
|
1398
|
|
|
return true; |
1399
|
|
|
} |
1400
|
|
|
|
1401
|
|
|
/** |
1402
|
|
|
* Prepare the _c array for template files. The _c array contains |
1403
|
|
|
* information about the current course. |
1404
|
|
|
*/ |
1405
|
|
|
private function set_course_parameters() |
1406
|
|
|
{ |
1407
|
|
|
//Setting course id |
1408
|
|
|
$course = api_get_course_info(); |
1409
|
|
|
if (empty($course)) { |
1410
|
|
|
$this->assign('course_is_set', false); |
1411
|
|
|
|
1412
|
|
|
return; |
1413
|
|
|
} |
1414
|
|
|
$this->assign('course_is_set', true); |
1415
|
|
|
$this->course_id = $course['id']; |
1416
|
|
|
$_c = [ |
1417
|
|
|
'id' => $course['real_id'], |
1418
|
|
|
'code' => $course['code'], |
1419
|
|
|
'title' => $course['name'], |
1420
|
|
|
'visibility' => $course['visibility'], |
1421
|
|
|
'language' => $course['language'], |
1422
|
|
|
'directory' => $course['directory'], |
1423
|
|
|
'session_id' => api_get_session_id(), |
1424
|
|
|
'user_is_teacher' => api_is_course_admin(), |
1425
|
|
|
'student_view' => (!empty($_GET['isStudentView']) && $_GET['isStudentView'] == 'true'), |
1426
|
|
|
]; |
1427
|
|
|
$this->assign('course_code', $course['code']); |
1428
|
|
|
$this->assign('_c', $_c); |
1429
|
|
|
} |
1430
|
|
|
|
1431
|
|
|
/** |
1432
|
|
|
* Prepare the _u array for template files. The _u array contains |
1433
|
|
|
* information about the current user, as returned by |
1434
|
|
|
* api_get_user_info(). |
1435
|
|
|
*/ |
1436
|
|
|
private function set_user_parameters() |
1437
|
|
|
{ |
1438
|
|
|
$user_info = []; |
1439
|
|
|
$user_info['logged'] = 0; |
1440
|
|
|
$this->user_is_logged_in = false; |
1441
|
|
|
if (api_user_is_login()) { |
1442
|
|
|
$user_info = api_get_user_info(api_get_user_id(), true); |
1443
|
|
|
$user_info['logged'] = 1; |
1444
|
|
|
|
1445
|
|
|
$user_info['is_admin'] = 0; |
1446
|
|
|
if (api_is_platform_admin()) { |
1447
|
|
|
$user_info['is_admin'] = 1; |
1448
|
|
|
} |
1449
|
|
|
|
1450
|
|
|
$user_info['messages_count'] = MessageManager::getCountNewMessages(); |
1451
|
|
|
$this->user_is_logged_in = true; |
1452
|
|
|
} |
1453
|
|
|
// Setting the $_u array that could be use in any template |
1454
|
|
|
$this->assign('_u', $user_info); |
1455
|
|
|
} |
1456
|
|
|
|
1457
|
|
|
/** |
1458
|
|
|
* Get an array of all the web paths available (e.g. 'web' => 'https://my.chamilo.site/'). |
1459
|
|
|
* |
1460
|
|
|
* @return array |
1461
|
|
|
*/ |
1462
|
|
|
private function getWebPaths() |
1463
|
|
|
{ |
1464
|
|
|
$queryString = empty($_SERVER['QUERY_STRING']) ? '' : $_SERVER['QUERY_STRING']; |
1465
|
|
|
$requestURI = empty($_SERVER['REQUEST_URI']) ? '' : $_SERVER['REQUEST_URI']; |
1466
|
|
|
|
1467
|
|
|
return [ |
1468
|
|
|
'web' => api_get_path(WEB_PATH), |
1469
|
|
|
'web_url' => api_get_web_url(), |
1470
|
|
|
'web_relative' => api_get_path(REL_PATH), |
1471
|
|
|
'web_course' => api_get_path(WEB_COURSE_PATH), |
1472
|
|
|
'web_main' => api_get_path(WEB_CODE_PATH), |
1473
|
|
|
'web_css' => api_get_path(WEB_CSS_PATH), |
1474
|
|
|
'web_css_theme' => api_get_path(WEB_CSS_PATH).$this->themeDir, |
1475
|
|
|
'web_ajax' => api_get_path(WEB_AJAX_PATH), |
1476
|
|
|
'web_img' => api_get_path(WEB_IMG_PATH), |
1477
|
|
|
'web_plugin' => api_get_path(WEB_PLUGIN_PATH), |
1478
|
|
|
'web_lib' => api_get_path(WEB_LIBRARY_PATH), |
1479
|
|
|
'web_upload' => api_get_path(WEB_UPLOAD_PATH), |
1480
|
|
|
'web_self' => api_get_self(), |
1481
|
|
|
'self_basename' => basename(api_get_self()), |
1482
|
|
|
'web_query_vars' => api_htmlentities($queryString), |
1483
|
|
|
'web_self_query_vars' => api_htmlentities($requestURI), |
1484
|
|
|
'web_cid_query' => api_get_cidreq(), |
1485
|
|
|
'web_rel_code' => api_get_path(REL_CODE_PATH), |
1486
|
|
|
]; |
1487
|
|
|
} |
1488
|
|
|
|
1489
|
|
|
/** |
1490
|
|
|
* Set header parameters. |
1491
|
|
|
* |
1492
|
|
|
* @param bool $sendHeaders send headers |
1493
|
|
|
*/ |
1494
|
|
|
private function set_header_parameters($sendHeaders) |
1495
|
|
|
{ |
1496
|
|
|
global $httpHeadXtra, $interbreadcrumb, $language_file, $_configuration, $this_section; |
1497
|
|
|
$_course = api_get_course_info(); |
1498
|
|
|
$nameTools = $this->title; |
1499
|
|
|
$navigation = return_navigation_array(); |
1500
|
|
|
$this->menu_navigation = $navigation['menu_navigation']; |
1501
|
|
|
|
1502
|
|
|
$this->assign('system_charset', api_get_system_encoding()); |
1503
|
|
|
|
1504
|
|
|
if (isset($httpHeadXtra) && $httpHeadXtra) { |
1505
|
|
|
foreach ($httpHeadXtra as &$thisHttpHead) { |
1506
|
|
|
header($thisHttpHead); |
1507
|
|
|
} |
1508
|
|
|
} |
1509
|
|
|
|
1510
|
|
|
// Get language iso-code for this page - ignore errors |
1511
|
|
|
$this->assign('document_language', api_get_language_isocode()); |
1512
|
|
|
|
1513
|
|
|
$course_title = isset($_course['name']) ? $_course['name'] : null; |
1514
|
|
|
|
1515
|
|
|
$title_list = []; |
1516
|
|
|
|
1517
|
|
|
$title_list[] = api_get_setting('Institution'); |
1518
|
|
|
$title_list[] = api_get_setting('siteName'); |
1519
|
|
|
|
1520
|
|
|
if (!empty($course_title)) { |
1521
|
|
|
$title_list[] = $course_title; |
1522
|
|
|
} |
1523
|
|
|
if ($nameTools != '') { |
1524
|
|
|
$title_list[] = $nameTools; |
1525
|
|
|
} |
1526
|
|
|
|
1527
|
|
|
$title_string = ''; |
1528
|
|
|
for ($i = 0; $i < count($title_list); $i++) { |
|
|
|
|
1529
|
|
|
$title_string .= $title_list[$i]; |
1530
|
|
|
if (isset($title_list[$i + 1])) { |
1531
|
|
|
$item = trim($title_list[$i + 1]); |
1532
|
|
|
if (!empty($item)) { |
1533
|
|
|
$title_string .= ' - '; |
1534
|
|
|
} |
1535
|
|
|
} |
1536
|
|
|
} |
1537
|
|
|
|
1538
|
|
|
$this->assign('title_string', $title_string); |
1539
|
|
|
|
1540
|
|
|
// Setting the theme and CSS files |
1541
|
|
|
$this->setCssFiles(); |
1542
|
|
|
$this->set_js_files(); |
1543
|
|
|
$this->setCssCustomFiles(); |
1544
|
|
|
|
1545
|
|
|
$browser = api_browser_support('check_browser'); |
1546
|
|
|
if ($browser[0] == 'Internet Explorer' && $browser[1] >= '11') { |
1547
|
|
|
$browser_head = '<meta http-equiv="X-UA-Compatible" content="IE=EmulateIE9" />'; |
1548
|
|
|
$this->assign('browser_specific_head', $browser_head); |
1549
|
|
|
} |
1550
|
|
|
|
1551
|
|
|
// Implementation of prefetch. |
1552
|
|
|
// See http://cdn.chamilo.org/main/img/online.png for details |
1553
|
|
|
$prefetch = ''; |
1554
|
|
|
if (!empty($_configuration['cdn_enable'])) { |
1555
|
|
|
$prefetch .= '<meta http-equiv="x-dns-prefetch-control" content="on">'; |
1556
|
|
|
foreach ($_configuration['cdn'] as $host => $exts) { |
1557
|
|
|
$prefetch .= '<link rel="dns-prefetch" href="'.$host.'">'; |
1558
|
|
|
} |
1559
|
|
|
} |
1560
|
|
|
|
1561
|
|
|
$this->assign('prefetch', $prefetch); |
1562
|
|
|
$this->assign('text_direction', api_get_text_direction()); |
1563
|
|
|
$this->assign('section_name', 'section-'.$this_section); |
1564
|
|
|
$this->assignFavIcon(); |
1565
|
|
|
$this->setHelp(); |
1566
|
|
|
|
1567
|
|
|
$this->assignBugNotification(); //Prepare the 'bug_notification' var for the template |
1568
|
|
|
|
1569
|
|
|
$this->assignAccessibilityBlock(); //Prepare the 'accessibility' var for the template |
1570
|
|
|
|
1571
|
|
|
// Preparing values for the menu |
1572
|
|
|
|
1573
|
|
|
// Logout link |
1574
|
|
|
$hideLogout = api_get_setting('hide_logout_button'); |
1575
|
|
|
if ($hideLogout === 'true') { |
1576
|
|
|
$this->assign('logout_link', null); |
1577
|
|
|
} else { |
1578
|
|
|
$this->assign('logout_link', api_get_path(WEB_PATH).'index.php?logout=logout&uid='.api_get_user_id()); |
1579
|
|
|
} |
1580
|
|
|
|
1581
|
|
|
// Profile link |
1582
|
|
|
if (api_get_setting('allow_social_tool') == 'true') { |
1583
|
|
|
$profile_url = api_get_path(WEB_CODE_PATH).'social/home.php'; |
1584
|
|
|
} else { |
1585
|
|
|
$profile_url = api_get_path(WEB_CODE_PATH).'auth/profile.php'; |
1586
|
|
|
} |
1587
|
|
|
|
1588
|
|
|
$this->assign('profile_url', $profile_url); |
1589
|
|
|
|
1590
|
|
|
//Message link |
1591
|
|
|
$message_link = null; |
1592
|
|
|
$message_url = null; |
1593
|
|
|
if (api_get_setting('allow_message_tool') == 'true') { |
1594
|
|
|
$message_url = api_get_path(WEB_CODE_PATH).'messages/inbox.php'; |
1595
|
|
|
$message_link = '<a href="'.api_get_path(WEB_CODE_PATH).'messages/inbox.php">'.get_lang('Inbox').'</a>'; |
1596
|
|
|
} |
1597
|
|
|
$this->assign('message_link', $message_link); |
1598
|
|
|
$this->assign('message_url', $message_url); |
1599
|
|
|
|
1600
|
|
|
$pendingSurveyLink = ''; |
1601
|
|
|
$show = api_get_configuration_value('show_pending_survey_in_menu'); |
1602
|
|
|
if ($show) { |
1603
|
|
|
$pendingSurveyLink = api_get_path(WEB_CODE_PATH).'survey/pending.php'; |
1604
|
|
|
} |
1605
|
|
|
$this->assign('pending_survey_url', $pendingSurveyLink); |
1606
|
|
|
|
1607
|
|
|
// Certificate Link |
1608
|
|
|
$allow = api_get_configuration_value('hide_my_certificate_link'); |
1609
|
|
|
if ($allow === false) { |
1610
|
|
|
$certificateUrl = api_get_path(WEB_CODE_PATH).'gradebook/my_certificates.php'; |
1611
|
|
|
$certificateLink = Display::url( |
1612
|
|
|
get_lang('MyCertificates'), |
1613
|
|
|
$certificateUrl |
1614
|
|
|
); |
1615
|
|
|
$this->assign('certificate_link', $certificateLink); |
1616
|
|
|
$this->assign('certificate_url', $certificateUrl); |
1617
|
|
|
} |
1618
|
|
|
|
1619
|
|
|
$institution = api_get_setting('Institution'); |
1620
|
|
|
$portal_name = empty($institution) ? api_get_setting('siteName') : $institution; |
1621
|
|
|
|
1622
|
|
|
$this->assign('portal_name', $portal_name); |
1623
|
|
|
|
1624
|
|
|
//Menu |
1625
|
|
|
$menu = menuArray(); |
1626
|
|
|
$this->assign('menu', $menu); |
1627
|
|
|
|
1628
|
|
|
$breadcrumb = ''; |
1629
|
|
|
// Hide breadcrumb in LP |
1630
|
|
|
if ($this->show_learnpath == false) { |
1631
|
|
|
$breadcrumb = return_breadcrumb( |
1632
|
|
|
$interbreadcrumb, |
1633
|
|
|
$language_file, |
1634
|
|
|
$nameTools |
1635
|
|
|
); |
1636
|
|
|
} |
1637
|
|
|
$this->assign('breadcrumb', $breadcrumb); |
1638
|
|
|
|
1639
|
|
|
//Extra content |
1640
|
|
|
$extra_header = null; |
1641
|
|
|
if (!api_is_platform_admin()) { |
1642
|
|
|
$extra_header = trim(api_get_setting('header_extra_content')); |
1643
|
|
|
} |
1644
|
|
|
$this->assign('header_extra_content', $extra_header); |
1645
|
|
|
|
1646
|
|
|
if ($sendHeaders) { |
1647
|
|
|
header('Content-Type: text/html; charset='.api_get_system_encoding()); |
1648
|
|
|
header( |
1649
|
|
|
'X-Powered-By: '.$_configuration['software_name'].' '.substr($_configuration['system_version'], 0, 1) |
1650
|
|
|
); |
1651
|
|
|
self::addHTTPSecurityHeaders(); |
|
|
|
|
1652
|
|
|
|
1653
|
|
|
$responseCode = $this->getResponseCode(); |
1654
|
|
|
if (!empty($responseCode)) { |
1655
|
|
|
switch ($responseCode) { |
1656
|
|
|
case '404': |
1657
|
|
|
header("HTTP/1.0 404 Not Found"); |
1658
|
|
|
break; |
1659
|
|
|
} |
1660
|
|
|
} |
1661
|
|
|
} |
1662
|
|
|
|
1663
|
|
|
$this->assignSocialMeta(); |
1664
|
|
|
} |
1665
|
|
|
|
1666
|
|
|
/** |
1667
|
|
|
* Set footer parameters. |
1668
|
|
|
*/ |
1669
|
|
|
private function set_footer_parameters() |
1670
|
|
|
{ |
1671
|
|
|
if (api_get_setting('show_administrator_data') === 'true') { |
1672
|
|
|
$firstName = api_get_setting('administratorName'); |
1673
|
|
|
$lastName = api_get_setting('administratorSurname'); |
1674
|
|
|
|
1675
|
|
|
if (!empty($firstName) && !empty($lastName)) { |
1676
|
|
|
$name = api_get_person_name($firstName, $lastName); |
1677
|
|
|
} else { |
1678
|
|
|
$name = $lastName; |
1679
|
|
|
if (empty($lastName)) { |
1680
|
|
|
$name = $firstName; |
1681
|
|
|
} |
1682
|
|
|
} |
1683
|
|
|
|
1684
|
|
|
$adminName = ''; |
1685
|
|
|
// Administrator name |
1686
|
|
|
if (!empty($name)) { |
1687
|
|
|
$adminName = get_lang('Manager').' : '; |
1688
|
|
|
$adminName .= Display::encrypted_mailto_link( |
1689
|
|
|
api_get_setting('emailAdministrator'), |
1690
|
|
|
$name, |
1691
|
|
|
'', |
1692
|
|
|
true |
1693
|
|
|
); |
1694
|
|
|
} |
1695
|
|
|
$this->assign('administrator_name', $adminName); |
1696
|
|
|
} |
1697
|
|
|
|
1698
|
|
|
// Loading footer extra content |
1699
|
|
|
if (!api_is_platform_admin()) { |
1700
|
|
|
$extra_footer = trim(api_get_setting('footer_extra_content')); |
1701
|
|
|
if (!empty($extra_footer)) { |
1702
|
|
|
$this->assign('footer_extra_content', $extra_footer); |
1703
|
|
|
} |
1704
|
|
|
} |
1705
|
|
|
|
1706
|
|
|
// Tutor name |
1707
|
|
|
if (api_get_setting('show_tutor_data') == 'true') { |
1708
|
|
|
// Course manager |
1709
|
|
|
$courseId = api_get_course_int_id(); |
1710
|
|
|
$id_session = api_get_session_id(); |
1711
|
|
|
if (!empty($courseId)) { |
1712
|
|
|
$tutor_data = ''; |
1713
|
|
|
if ($id_session != 0) { |
1714
|
|
|
$users = SessionManager::getCoachesByCourseSession($id_session, $courseId); |
1715
|
|
|
$links = []; |
1716
|
|
|
if (!empty($users)) { |
1717
|
|
|
$coaches = []; |
1718
|
|
|
foreach ($users as $userId) { |
1719
|
|
|
$coaches[] = api_get_user_info($userId); |
1720
|
|
|
} |
1721
|
|
|
$links = array_column($coaches, 'complete_name_with_message_link'); |
1722
|
|
|
} |
1723
|
|
|
$count = count($links); |
1724
|
|
|
if ($count > 1) { |
1725
|
|
|
$tutor_data .= get_lang('Coachs').' : '; |
1726
|
|
|
$tutor_data .= array_to_string($links, CourseManager::USER_SEPARATOR); |
1727
|
|
|
} elseif ($count === 1) { |
1728
|
|
|
$tutor_data .= get_lang('Coach').' : '; |
1729
|
|
|
$tutor_data .= array_to_string($links, CourseManager::USER_SEPARATOR); |
1730
|
|
|
} elseif ($count === 0) { |
1731
|
|
|
$tutor_data .= ''; |
1732
|
|
|
} |
1733
|
|
|
} |
1734
|
|
|
$this->assign('session_teachers', $tutor_data); |
1735
|
|
|
} |
1736
|
|
|
} |
1737
|
|
|
|
1738
|
|
|
if (api_get_setting('show_teacher_data') == 'true') { |
1739
|
|
|
// course manager |
1740
|
|
|
$courseId = api_get_course_int_id(); |
1741
|
|
|
if (!empty($courseId)) { |
1742
|
|
|
$teacher_data = ''; |
1743
|
|
|
$teachers = CourseManager::getTeachersFromCourse($courseId); |
1744
|
|
|
if (!empty($teachers)) { |
1745
|
|
|
$teachersParsed = []; |
1746
|
|
|
foreach ($teachers as $teacher) { |
1747
|
|
|
$userId = $teacher['id']; |
1748
|
|
|
$teachersParsed[] = api_get_user_info($userId); |
1749
|
|
|
} |
1750
|
|
|
$links = array_column($teachersParsed, 'complete_name_with_message_link'); |
1751
|
|
|
$label = get_lang('Teacher'); |
1752
|
|
|
if (count($links) > 1) { |
1753
|
|
|
$label = get_lang('Teachers'); |
1754
|
|
|
} |
1755
|
|
|
$teacher_data .= $label.' : '.array_to_string($links, CourseManager::USER_SEPARATOR); |
1756
|
|
|
} |
1757
|
|
|
$this->assign('teachers', $teacher_data); |
1758
|
|
|
} |
1759
|
|
|
} |
1760
|
|
|
} |
1761
|
|
|
|
1762
|
|
|
/** |
1763
|
|
|
* Set administrator variables. |
1764
|
|
|
*/ |
1765
|
|
|
private function setAdministratorParams() |
1766
|
|
|
{ |
1767
|
|
|
$_admin = [ |
1768
|
|
|
'email' => api_get_setting('emailAdministrator'), |
1769
|
|
|
'surname' => api_get_setting('administratorSurname'), |
1770
|
|
|
'name' => api_get_setting('administratorName'), |
1771
|
|
|
'telephone' => api_get_setting('administratorTelephone'), |
1772
|
|
|
]; |
1773
|
|
|
|
1774
|
|
|
$this->assign('_admin', $_admin); |
1775
|
|
|
} |
1776
|
|
|
|
1777
|
|
|
/** |
1778
|
|
|
* Manage specific HTTP headers security. |
1779
|
|
|
*/ |
1780
|
|
|
private function addHTTPSecurityHeaders() |
1781
|
|
|
{ |
1782
|
|
|
// Implementation of HTTP headers security, as suggested and checked |
1783
|
|
|
// by https://securityheaders.io/ |
1784
|
|
|
// Enable these settings in configuration.php to use them on your site |
1785
|
|
|
// Strict-Transport-Security |
1786
|
|
|
$setting = api_get_configuration_value('security_strict_transport'); |
1787
|
|
|
if (!empty($setting)) { |
1788
|
|
|
header('Strict-Transport-Security: '.$setting); |
1789
|
|
|
} |
1790
|
|
|
// Content-Security-Policy |
1791
|
|
|
$setting = api_get_configuration_value('security_content_policy'); |
1792
|
|
|
if (!empty($setting)) { |
1793
|
|
|
header('Content-Security-Policy: '.$setting); |
1794
|
|
|
} |
1795
|
|
|
$setting = api_get_configuration_value('security_content_policy_report_only'); |
1796
|
|
|
if (!empty($setting)) { |
1797
|
|
|
header('Content-Security-Policy-Report-Only: '.$setting); |
1798
|
|
|
} |
1799
|
|
|
// Public-Key-Pins |
1800
|
|
|
$setting = api_get_configuration_value('security_public_key_pins'); |
1801
|
|
|
if (!empty($setting)) { |
1802
|
|
|
header('Public-Key-Pins: '.$setting); |
1803
|
|
|
} |
1804
|
|
|
$setting = api_get_configuration_value('security_public_key_pins_report_only'); |
1805
|
|
|
if (!empty($setting)) { |
1806
|
|
|
header('Public-Key-Pins-Report-Only: '.$setting); |
1807
|
|
|
} |
1808
|
|
|
// X-Frame-Options |
1809
|
|
|
$setting = api_get_configuration_value('security_x_frame_options'); |
1810
|
|
|
if (!empty($setting)) { |
1811
|
|
|
header('X-Frame-Options: '.$setting); |
1812
|
|
|
} |
1813
|
|
|
// X-XSS-Protection |
1814
|
|
|
$setting = api_get_configuration_value('security_xss_protection'); |
1815
|
|
|
if (!empty($setting)) { |
1816
|
|
|
header('X-XSS-Protection: '.$setting); |
1817
|
|
|
} |
1818
|
|
|
// X-Content-Type-Options |
1819
|
|
|
$setting = api_get_configuration_value('security_x_content_type_options'); |
1820
|
|
|
if (!empty($setting)) { |
1821
|
|
|
header('X-Content-Type-Options: '.$setting); |
1822
|
|
|
} |
1823
|
|
|
// Referrer-Policy |
1824
|
|
|
$setting = api_get_configuration_value('security_referrer_policy'); |
1825
|
|
|
if (!empty($setting)) { |
1826
|
|
|
header('Referrer-Policy: '.$setting); |
1827
|
|
|
} |
1828
|
|
|
// end of HTTP headers security block |
1829
|
|
|
} |
1830
|
|
|
|
1831
|
|
|
/** |
1832
|
|
|
* Assign favicon to the 'favico' template variable. |
1833
|
|
|
* |
1834
|
|
|
* @return bool Always return true because there is always at least one correct favicon.ico |
1835
|
|
|
*/ |
1836
|
|
|
private function assignFavIcon() |
1837
|
|
|
{ |
1838
|
|
|
// Default root chamilo favicon |
1839
|
|
|
$favico = '<link rel="shortcut icon" href="'.api_get_path(WEB_PATH).'favicon.ico" type="image/x-icon" />'; |
1840
|
|
|
|
1841
|
|
|
//Added to verify if in the current Chamilo Theme exist a favicon |
1842
|
|
|
$favicoThemeUrl = api_get_path(SYS_CSS_PATH).$this->themeDir.'images/'; |
1843
|
|
|
|
1844
|
|
|
//If exist pick the current chamilo theme favicon |
1845
|
|
|
if (is_file($favicoThemeUrl.'favicon.ico')) { |
1846
|
|
|
$favico = '<link rel="shortcut icon" href="'.api_get_path(WEB_CSS_PATH).$this->themeDir.'images/favicon.ico" type="image/x-icon" />'; |
1847
|
|
|
} |
1848
|
|
|
|
1849
|
|
|
if (api_is_multiple_url_enabled()) { |
1850
|
|
|
$access_url_id = api_get_current_access_url_id(); |
1851
|
|
|
if ($access_url_id != -1) { |
1852
|
|
|
$url_info = api_get_access_url($access_url_id); |
1853
|
|
|
$url = api_remove_trailing_slash( |
1854
|
|
|
preg_replace('/https?:\/\//i', '', $url_info['url']) |
1855
|
|
|
); |
1856
|
|
|
$clean_url = api_replace_dangerous_char($url); |
1857
|
|
|
$clean_url = str_replace('/', '-', $clean_url); |
1858
|
|
|
$clean_url .= '/'; |
1859
|
|
|
$homep = api_get_path(WEB_HOME_PATH).$clean_url; //homep for Home Path |
1860
|
|
|
$icon_real_homep = api_get_path(SYS_APP_PATH).'home/'.$clean_url; |
1861
|
|
|
//we create the new dir for the new sites |
1862
|
|
|
if (is_file($icon_real_homep.'favicon.ico')) { |
1863
|
|
|
$favico = '<link rel="shortcut icon" href="'.$homep.'favicon.ico" type="image/x-icon" />'; |
1864
|
|
|
} |
1865
|
|
|
} |
1866
|
|
|
} |
1867
|
|
|
|
1868
|
|
|
$this->assign('favico', $favico); |
1869
|
|
|
|
1870
|
|
|
return true; |
1871
|
|
|
} |
1872
|
|
|
|
1873
|
|
|
/** |
1874
|
|
|
* Assign HTML code to the 'accessibility' template variable (usually shown above top menu). |
1875
|
|
|
* |
1876
|
|
|
* @return bool Always return true (even if empty string) |
1877
|
|
|
*/ |
1878
|
|
|
private function assignAccessibilityBlock() |
1879
|
|
|
{ |
1880
|
|
|
$resize = ''; |
1881
|
|
|
if (api_get_setting('accessibility_font_resize') == 'true') { |
1882
|
|
|
$resize .= '<div class="resize_font">'; |
1883
|
|
|
$resize .= '<div class="btn-group">'; |
1884
|
|
|
$resize .= '<a title="'.get_lang('DecreaseFontSize').'" href="#" class="decrease_font btn btn-default"><em class="fa fa-font"></em></a>'; |
1885
|
|
|
$resize .= '<a title="'.get_lang('ResetFontSize').'" href="#" class="reset_font btn btn-default"><em class="fa fa-font"></em></a>'; |
1886
|
|
|
$resize .= '<a title="'.get_lang('IncreaseFontSize').'" href="#" class="increase_font btn btn-default"><em class="fa fa-font"></em></a>'; |
1887
|
|
|
$resize .= '</div>'; |
1888
|
|
|
$resize .= '</div>'; |
1889
|
|
|
} |
1890
|
|
|
$this->assign('accessibility', $resize); |
1891
|
|
|
|
1892
|
|
|
return true; |
1893
|
|
|
} |
1894
|
|
|
|
1895
|
|
|
/** |
1896
|
|
|
* Assign HTML code to the 'social_meta' template variable (usually shown above top menu). |
1897
|
|
|
* |
1898
|
|
|
* @return bool Always return true (even if empty string) |
1899
|
|
|
*/ |
1900
|
|
|
private function assignSocialMeta() |
1901
|
|
|
{ |
1902
|
|
|
$socialMeta = ''; |
1903
|
|
|
$metaTitle = api_get_setting('meta_title'); |
1904
|
|
|
if (!empty($metaTitle)) { |
1905
|
|
|
$socialMeta .= '<meta name="twitter:card" content="summary" />'."\n"; |
1906
|
|
|
$metaSite = api_get_setting('meta_twitter_site'); |
1907
|
|
|
if (!empty($metaSite)) { |
1908
|
|
|
$socialMeta .= '<meta name="twitter:site" content="'.$metaSite.'" />'."\n"; |
1909
|
|
|
$metaCreator = api_get_setting('meta_twitter_creator'); |
1910
|
|
|
if (!empty($metaCreator)) { |
1911
|
|
|
$socialMeta .= '<meta name="twitter:creator" content="'.$metaCreator.'" />'."\n"; |
1912
|
|
|
} |
1913
|
|
|
} |
1914
|
|
|
|
1915
|
|
|
// The user badge page emits its own meta tags, so if this is |
1916
|
|
|
// enabled, ignore the global ones |
1917
|
|
|
$userId = isset($_GET['user']) ? intval($_GET['user']) : 0; |
1918
|
|
|
$skillId = isset($_GET['skill']) ? intval($_GET['skill']) : 0; |
1919
|
|
|
|
1920
|
|
|
if (!$userId && !$skillId) { |
1921
|
|
|
// no combination of user and skill ID has been defined, |
1922
|
|
|
// so print the normal or course-specific OpenGraph meta tags |
1923
|
|
|
// Check for a course ID |
1924
|
|
|
$courseId = api_get_course_int_id(); |
1925
|
|
|
// Check session ID from session/id/about (see .htaccess) |
1926
|
|
|
$sessionId = isset($_GET['session_id']) ? intval($_GET['session_id']) : 0; |
1927
|
|
|
|
1928
|
|
|
if ($courseId != false) { |
|
|
|
|
1929
|
|
|
// If we are inside a course (even if within a session), publish info about the course |
1930
|
|
|
$course = api_get_course_entity($courseId); |
1931
|
|
|
// @TODO: support right-to-left in title |
1932
|
|
|
$socialMeta .= '<meta property="og:title" content="'.$course->getTitle().' - '.$metaTitle.'" />'."\n"; |
1933
|
|
|
$socialMeta .= '<meta property="twitter:title" content="'.$course->getTitle().' - '.$metaTitle.'" />'."\n"; |
1934
|
|
|
$socialMeta .= '<meta property="og:url" content="'.api_get_course_url($course->getCode()).'" />'."\n"; |
1935
|
|
|
|
1936
|
|
|
$metaDescription = api_get_setting('meta_description'); |
1937
|
|
|
if (!empty($course->getDescription())) { |
1938
|
|
|
$socialMeta .= '<meta property="og:description" content="'.strip_tags($course->getDescription()).'" />'."\n"; |
1939
|
|
|
$socialMeta .= '<meta property="twitter:description" content="'.strip_tags($course->getDescription()).'" />'."\n"; |
1940
|
|
|
} elseif (!empty($metaDescription)) { |
1941
|
|
|
$socialMeta .= '<meta property="og:description" content="'.$metaDescription.'" />'."\n"; |
1942
|
|
|
$socialMeta .= '<meta property="twitter:description" content="'.$metaDescription.'" />'."\n"; |
1943
|
|
|
} |
1944
|
|
|
|
1945
|
|
|
$picture = CourseManager::getPicturePath($course, true); |
1946
|
|
|
if (!empty($picture)) { |
1947
|
|
|
$socialMeta .= '<meta property="og:image" content="'.$picture.'" />'."\n"; |
1948
|
|
|
$socialMeta .= '<meta property="twitter:image" content="'.$picture.'" />'."\n"; |
1949
|
|
|
$socialMeta .= '<meta property="twitter:image:alt" content="'.$course->getTitle().' - '.$metaTitle.'" />'."\n"; |
1950
|
|
|
} else { |
1951
|
|
|
$socialMeta .= $this->getMetaPortalImagePath($metaTitle); |
1952
|
|
|
} |
1953
|
|
|
} elseif ($sessionId !== 0) { |
1954
|
|
|
// If we are on a session "about" screen, publish info about the session |
1955
|
|
|
$em = Database::getManager(); |
1956
|
|
|
$session = $em->find('ChamiloCoreBundle:Session', $sessionId); |
1957
|
|
|
|
1958
|
|
|
$socialMeta .= '<meta property="og:title" content="'.$session->getName().' - '.$metaTitle.'" />'."\n"; |
1959
|
|
|
$socialMeta .= '<meta property="twitter:title" content="'.$session->getName().' - '.$metaTitle.'" />'."\n"; |
1960
|
|
|
$socialMeta .= '<meta property="og:url" content="'.api_get_path(WEB_PATH)."session/{$session->getId()}/about/".'" />'."\n"; |
1961
|
|
|
|
1962
|
|
|
$sessionValues = new ExtraFieldValue('session'); |
1963
|
|
|
$sessionImage = $sessionValues->get_values_by_handler_and_field_variable($session->getId(), 'image')['value']; |
1964
|
|
|
$sessionImageSysPath = api_get_path(SYS_UPLOAD_PATH).$sessionImage; |
1965
|
|
|
|
1966
|
|
|
if (!empty($sessionImage) && is_file($sessionImageSysPath)) { |
1967
|
|
|
$sessionImagePath = api_get_path(WEB_UPLOAD_PATH).$sessionImage; |
1968
|
|
|
$socialMeta .= '<meta property="og:image" content="'.$sessionImagePath.'" />'."\n"; |
1969
|
|
|
$socialMeta .= '<meta property="twitter:image" content="'.$sessionImagePath.'" />'."\n"; |
1970
|
|
|
$socialMeta .= '<meta property="twitter:image:alt" content="'.$session->getName().' - '.$metaTitle.'" />'."\n"; |
1971
|
|
|
} else { |
1972
|
|
|
$socialMeta .= $this->getMetaPortalImagePath($metaTitle); |
1973
|
|
|
} |
1974
|
|
|
} else { |
1975
|
|
|
// Otherwise (not a course nor a session, nor a user, nor a badge), publish portal info |
1976
|
|
|
$socialMeta .= '<meta property="og:title" content="'.$metaTitle.'" />'."\n"; |
1977
|
|
|
$socialMeta .= '<meta property="twitter:title" content="'.$metaTitle.'" />'."\n"; |
1978
|
|
|
$socialMeta .= '<meta property="og:url" content="'.api_get_path(WEB_PATH).'" />'."\n"; |
1979
|
|
|
|
1980
|
|
|
$metaDescription = api_get_setting('meta_description'); |
1981
|
|
|
if (!empty($metaDescription)) { |
1982
|
|
|
$socialMeta .= '<meta property="og:description" content="'.$metaDescription.'" />'."\n"; |
1983
|
|
|
$socialMeta .= '<meta property="twitter:description" content="'.$metaDescription.'" />'."\n"; |
1984
|
|
|
} |
1985
|
|
|
$socialMeta .= $this->getMetaPortalImagePath($metaTitle); |
1986
|
|
|
} |
1987
|
|
|
} |
1988
|
|
|
} |
1989
|
|
|
|
1990
|
|
|
$this->assign('social_meta', $socialMeta); |
1991
|
|
|
|
1992
|
|
|
return true; |
1993
|
|
|
} |
1994
|
|
|
|
1995
|
|
|
/** |
1996
|
|
|
* Get platform meta image tag (check meta_image_path setting, then use the logo). |
1997
|
|
|
* |
1998
|
|
|
* @param string $imageAlt The alt attribute for the image |
1999
|
|
|
* |
2000
|
|
|
* @return string The meta image HTML tag, or empty |
2001
|
|
|
*/ |
2002
|
|
|
private function getMetaPortalImagePath($imageAlt = '') |
2003
|
|
|
{ |
2004
|
|
|
// Load portal meta image if defined |
2005
|
|
|
$metaImage = api_get_setting('meta_image_path'); |
2006
|
|
|
$metaImageSysPath = api_get_path(SYS_PATH).$metaImage; |
2007
|
|
|
$metaImageWebPath = api_get_path(WEB_PATH).$metaImage; |
2008
|
|
|
$portalImageMeta = ''; |
2009
|
|
|
if (!empty($metaImage)) { |
2010
|
|
|
if (is_file($metaImageSysPath)) { |
2011
|
|
|
$portalImageMeta = '<meta property="og:image" content="'.$metaImageWebPath.'" />'."\n"; |
2012
|
|
|
$portalImageMeta .= '<meta property="twitter:image" content="'.$metaImageWebPath.'" />'."\n"; |
2013
|
|
|
$portalImageMeta .= '<meta property="twitter:image:alt" content="'.$imageAlt.'" />'."\n"; |
2014
|
|
|
} |
2015
|
|
|
} else { |
2016
|
|
|
$logo = ChamiloApi::getPlatformLogoPath($this->theme); |
2017
|
|
|
if (!empty($logo)) { |
2018
|
|
|
$portalImageMeta = '<meta property="og:image" content="'.$logo.'" />'."\n"; |
2019
|
|
|
$portalImageMeta .= '<meta property="twitter:image" content="'.$logo.'" />'."\n"; |
2020
|
|
|
$portalImageMeta .= '<meta property="twitter:image:alt" content="'.$imageAlt.'" />'."\n"; |
2021
|
|
|
} |
2022
|
|
|
} |
2023
|
|
|
|
2024
|
|
|
return $portalImageMeta; |
2025
|
|
|
} |
2026
|
|
|
} |
2027
|
|
|
|
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 theid
property of an instance of theAccount
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.