Passed
Push — master ( 241b61...cc68cc )
by Julito
09:18
created

api_get_item_property_id()   A

Complexity

Conditions 3
Paths 4

Size

Total Lines 28
Code Lines 20

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 3
eloc 20
nc 4
nop 4
dl 0
loc 28
rs 9.6
c 0
b 0
f 0

1 Method

Rating   Name   Duplication   Size   Complexity  
A api_get_languages() 0 12 2
1
<?php
2
3
/* For licensing terms, see /license.txt */
4
5
use Chamilo\CoreBundle\Entity\AccessUrl;
6
use Chamilo\CoreBundle\Entity\Course;
0 ignored issues
show
Bug introduced by
This use statement conflicts with another class in this namespace, Course. Consider defining an alias.

Let?s assume that you have a directory layout like this:

.
|-- OtherDir
|   |-- Bar.php
|   `-- Foo.php
`-- SomeDir
    `-- Foo.php

and let?s assume the following content of Bar.php:

// Bar.php
namespace OtherDir;

use SomeDir\Foo; // This now conflicts the class OtherDir\Foo

If both files OtherDir/Foo.php and SomeDir/Foo.php are loaded in the same runtime, you will see a PHP error such as the following:

PHP Fatal error:  Cannot use SomeDir\Foo as Foo because the name is already in use in OtherDir/Foo.php

However, as OtherDir/Foo.php does not necessarily have to be loaded and the error is only triggered if it is loaded before OtherDir/Bar.php, this problem might go unnoticed for a while. In order to prevent this error from surfacing, you must import the namespace with a different alias:

// Bar.php
namespace OtherDir;

use SomeDir\Foo as SomeDirFoo; // There is no conflict anymore.
Loading history...
7
use Chamilo\CoreBundle\Entity\Language;
8
use Chamilo\CoreBundle\Entity\Session as SessionEntity;
9
use Chamilo\CoreBundle\Entity\SettingsCurrent;
10
use Chamilo\CoreBundle\Entity\User;
11
use Chamilo\CoreBundle\Entity\UserCourseCategory;
12
use Chamilo\CoreBundle\Framework\Container;
13
use Chamilo\CourseBundle\Entity\CGroup;
14
use Chamilo\CourseBundle\Entity\CLp;
15
use ChamiloSession as Session;
16
use Symfony\Bridge\Twig\Mime\TemplatedEmail;
17
use Symfony\Component\Finder\Finder;
18
use Symfony\Component\Mime\Address;
19
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
20
use Symfony\Component\Security\Core\User\UserInterface;
21
22
/**
23
 * This is a code library for Chamilo.
24
 * It is included by default in every Chamilo file (through including the global.inc.php)
25
 * This library is in process of being transferred to src/Chamilo/CoreBundle/Component/Utils/ChamiloApi.
26
 * Whenever a function is transferred to the ChamiloApi class, the places where it is used should include
27
 * the "use Chamilo\CoreBundle\Component\Utils\ChamiloApi;" statement.
28
 */
29
30
// PHP version requirement.
31
define('REQUIRED_PHP_VERSION', '7.2');
32
define('REQUIRED_MIN_MEMORY_LIMIT', '128');
33
define('REQUIRED_MIN_UPLOAD_MAX_FILESIZE', '10');
34
define('REQUIRED_MIN_POST_MAX_SIZE', '10');
35
36
// USER STATUS CONSTANTS
37
/** global status of a user: student */
38
define('STUDENT', 5);
39
/** global status of a user: course manager */
40
define('COURSEMANAGER', 1);
41
/** global status of a user: session admin */
42
define('SESSIONADMIN', 3);
43
/** global status of a user: human ressource manager */
44
define('DRH', 4);
45
/** global status of a user: human ressource manager */
46
define('ANONYMOUS', 6);
47
/** global status of a user: low security, necessary for inserting data from
48
 * the teacher through HTMLPurifier */
49
define('COURSEMANAGERLOWSECURITY', 10);
50
// Soft user status
51
define('PLATFORM_ADMIN', 11);
52
define('SESSION_COURSE_COACH', 12);
53
define('SESSION_GENERAL_COACH', 13);
54
define('COURSE_STUDENT', 14); //student subscribed in a course
55
define('SESSION_STUDENT', 15); //student subscribed in a session course
56
define('COURSE_TUTOR', 16); // student is tutor of a course (NOT in session)
57
define('STUDENT_BOSS', 17); // student is boss
58
define('INVITEE', 20);
59
define('HRM_REQUEST', 21); //HRM has request for vinculation with user
60
61
// COURSE VISIBILITY CONSTANTS
62
/** only visible for course admin */
63
define('COURSE_VISIBILITY_CLOSED', 0);
64
/** only visible for users registered in the course */
65
define('COURSE_VISIBILITY_REGISTERED', 1);
66
/** Open for all registered users on the platform */
67
define('COURSE_VISIBILITY_OPEN_PLATFORM', 2);
68
/** Open for the whole world */
69
define('COURSE_VISIBILITY_OPEN_WORLD', 3);
70
/** Invisible to all except admin */
71
define('COURSE_VISIBILITY_HIDDEN', 4);
72
73
define('COURSE_REQUEST_PENDING', 0);
74
define('COURSE_REQUEST_ACCEPTED', 1);
75
define('COURSE_REQUEST_REJECTED', 2);
76
define('DELETE_ACTION_ENABLED', false);
77
78
// EMAIL SENDING RECIPIENT CONSTANTS
79
define('SEND_EMAIL_EVERYONE', 1);
80
define('SEND_EMAIL_STUDENTS', 2);
81
define('SEND_EMAIL_TEACHERS', 3);
82
83
// SESSION VISIBILITY CONSTANTS
84
define('SESSION_VISIBLE_READ_ONLY', 1);
85
define('SESSION_VISIBLE', 2);
86
define('SESSION_INVISIBLE', 3); // not available
87
define('SESSION_AVAILABLE', 4);
88
89
define('SESSION_LINK_TARGET', '_self');
90
91
define('SUBSCRIBE_ALLOWED', 1);
92
define('SUBSCRIBE_NOT_ALLOWED', 0);
93
define('UNSUBSCRIBE_ALLOWED', 1);
94
define('UNSUBSCRIBE_NOT_ALLOWED', 0);
95
96
// SURVEY VISIBILITY CONSTANTS
97
define('SURVEY_VISIBLE_TUTOR', 0);
98
define('SURVEY_VISIBLE_TUTOR_STUDENT', 1);
99
define('SURVEY_VISIBLE_PUBLIC', 2);
100
101
// CONSTANTS defining all tools, using the english version
102
/* When you add a new tool you must add it into function api_get_tools_lists() too */
103
define('TOOL_DOCUMENT', 'document');
104
define('TOOL_LP_FINAL_ITEM', 'final_item');
105
define('TOOL_READOUT_TEXT', 'readout_text');
106
define('TOOL_THUMBNAIL', 'thumbnail');
107
define('TOOL_HOTPOTATOES', 'hotpotatoes');
108
define('TOOL_CALENDAR_EVENT', 'calendar_event');
109
define('TOOL_LINK', 'link');
110
define('TOOL_LINK_CATEGORY', 'link_category');
111
define('TOOL_COURSE_DESCRIPTION', 'course_description');
112
define('TOOL_SEARCH', 'search');
113
define('TOOL_LEARNPATH', 'learnpath');
114
define('TOOL_LEARNPATH_CATEGORY', 'learnpath_category');
115
define('TOOL_AGENDA', 'agenda');
116
define('TOOL_ANNOUNCEMENT', 'announcement');
117
define('TOOL_FORUM', 'forum');
118
define('TOOL_FORUM_CATEGORY', 'forum_category');
119
define('TOOL_FORUM_THREAD', 'forum_thread');
120
define('TOOL_FORUM_POST', 'forum_post');
121
define('TOOL_FORUM_ATTACH', 'forum_attachment');
122
define('TOOL_FORUM_THREAD_QUALIFY', 'forum_thread_qualify');
123
define('TOOL_THREAD', 'thread');
124
define('TOOL_POST', 'post');
125
define('TOOL_DROPBOX', 'dropbox');
126
define('TOOL_QUIZ', 'quiz');
127
define('TOOL_TEST_CATEGORY', 'test_category');
128
define('TOOL_USER', 'user');
129
define('TOOL_GROUP', 'group');
130
define('TOOL_BLOGS', 'blog_management');
131
define('TOOL_CHAT', 'chat');
132
define('TOOL_STUDENTPUBLICATION', 'student_publication');
133
define('TOOL_TRACKING', 'tracking');
134
define('TOOL_HOMEPAGE_LINK', 'homepage_link');
135
define('TOOL_COURSE_SETTING', 'course_setting');
136
define('TOOL_BACKUP', 'backup');
137
define('TOOL_COPY_COURSE_CONTENT', 'copy_course_content');
138
define('TOOL_RECYCLE_COURSE', 'recycle_course');
139
define('TOOL_COURSE_HOMEPAGE', 'course_homepage');
140
define('TOOL_COURSE_RIGHTS_OVERVIEW', 'course_rights');
141
define('TOOL_UPLOAD', 'file_upload');
142
define('TOOL_COURSE_MAINTENANCE', 'course_maintenance');
143
define('TOOL_SURVEY', 'survey');
144
define('TOOL_WIKI', 'wiki');
145
define('TOOL_GLOSSARY', 'glossary');
146
define('TOOL_GRADEBOOK', 'gradebook');
147
define('TOOL_NOTEBOOK', 'notebook');
148
define('TOOL_ATTENDANCE', 'attendance');
149
define('TOOL_COURSE_PROGRESS', 'course_progress');
150
define('TOOL_PORTFOLIO', 'portfolio');
151
define('TOOL_PLAGIARISM', 'compilatio');
152
153
// CONSTANTS defining Chamilo interface sections
154
define('SECTION_CAMPUS', 'mycampus');
155
define('SECTION_COURSES', 'mycourses');
156
define('SECTION_CATALOG', 'catalog');
157
define('SECTION_MYPROFILE', 'myprofile');
158
define('SECTION_MYAGENDA', 'myagenda');
159
define('SECTION_COURSE_ADMIN', 'course_admin');
160
define('SECTION_PLATFORM_ADMIN', 'platform_admin');
161
define('SECTION_MYGRADEBOOK', 'mygradebook');
162
define('SECTION_TRACKING', 'session_my_space');
163
define('SECTION_SOCIAL', 'social-network');
164
define('SECTION_DASHBOARD', 'dashboard');
165
define('SECTION_REPORTS', 'reports');
166
define('SECTION_GLOBAL', 'global');
167
define('SECTION_INCLUDE', 'include');
168
169
// CONSTANT name for local authentication source
170
define('PLATFORM_AUTH_SOURCE', 'platform');
171
define('CAS_AUTH_SOURCE', 'cas');
172
define('LDAP_AUTH_SOURCE', 'extldap');
173
174
// CONSTANT defining the default HotPotatoes files directory
175
define('DIR_HOTPOTATOES', '/HotPotatoes_files');
176
177
// event logs types
178
define('LOG_COURSE_DELETE', 'course_deleted');
179
define('LOG_COURSE_CREATE', 'course_created');
180
define('LOG_COURSE_SETTINGS_CHANGED', 'course_settings_changed');
181
182
// @todo replace 'soc_gr' with social_group
183
define('LOG_GROUP_PORTAL_CREATED', 'soc_gr_created');
184
define('LOG_GROUP_PORTAL_UPDATED', 'soc_gr_updated');
185
define('LOG_GROUP_PORTAL_DELETED', 'soc_gr_deleted');
186
define('LOG_GROUP_PORTAL_USER_DELETE_ALL', 'soc_gr_delete_users');
187
188
define('LOG_GROUP_PORTAL_ID', 'soc_gr_portal_id');
189
define('LOG_GROUP_PORTAL_REL_USER_ARRAY', 'soc_gr_user_array');
190
191
define('LOG_GROUP_PORTAL_USER_SUBSCRIBED', 'soc_gr_u_subs');
192
define('LOG_GROUP_PORTAL_USER_UNSUBSCRIBED', 'soc_gr_u_unsubs');
193
define('LOG_GROUP_PORTAL_USER_UPDATE_ROLE', 'soc_gr_update_role');
194
195
define('LOG_USER_DELETE', 'user_deleted');
196
define('LOG_USER_CREATE', 'user_created');
197
define('LOG_USER_UPDATE', 'user_updated');
198
define('LOG_USER_PASSWORD_UPDATE', 'user_password_updated');
199
define('LOG_USER_ENABLE', 'user_enable');
200
define('LOG_USER_DISABLE', 'user_disable');
201
define('LOG_USER_ANONYMIZE', 'user_anonymized');
202
define('LOG_USER_FIELD_CREATE', 'user_field_created');
203
define('LOG_USER_FIELD_DELETE', 'user_field_deleted');
204
define('LOG_SESSION_CREATE', 'session_created');
205
define('LOG_SESSION_DELETE', 'session_deleted');
206
define('LOG_SESSION_ADD_USER_COURSE', 'session_add_user_course');
207
define('LOG_SESSION_DELETE_USER_COURSE', 'session_delete_user_course');
208
define('LOG_SESSION_ADD_USER', 'session_add_user');
209
define('LOG_SESSION_DELETE_USER', 'session_delete_user');
210
define('LOG_SESSION_ADD_COURSE', 'session_add_course');
211
define('LOG_SESSION_DELETE_COURSE', 'session_delete_course');
212
define('LOG_SESSION_CATEGORY_CREATE', 'session_cat_created'); //changed in 1.9.8
213
define('LOG_SESSION_CATEGORY_DELETE', 'session_cat_deleted'); //changed in 1.9.8
214
define('LOG_CONFIGURATION_SETTINGS_CHANGE', 'settings_changed');
215
define('LOG_PLATFORM_LANGUAGE_CHANGE', 'platform_lng_changed'); //changed in 1.9.8
216
define('LOG_SUBSCRIBE_USER_TO_COURSE', 'user_subscribed');
217
define('LOG_UNSUBSCRIBE_USER_FROM_COURSE', 'user_unsubscribed');
218
define('LOG_ATTEMPTED_FORCED_LOGIN', 'attempted_forced_login');
219
define('LOG_PLUGIN_CHANGE', 'plugin_changed');
220
define('LOG_HOMEPAGE_CHANGED', 'homepage_changed');
221
define('LOG_PROMOTION_CREATE', 'promotion_created');
222
define('LOG_PROMOTION_DELETE', 'promotion_deleted');
223
define('LOG_CAREER_CREATE', 'career_created');
224
define('LOG_CAREER_DELETE', 'career_deleted');
225
define('LOG_USER_PERSONAL_DOC_DELETED', 'user_doc_deleted');
226
define('LOG_WIKI_ACCESS', 'wiki_page_view');
227
// All results from an exercise
228
define('LOG_EXERCISE_RESULT_DELETE', 'exe_result_deleted');
229
// Logs only the one attempt
230
define('LOG_EXERCISE_ATTEMPT_DELETE', 'exe_attempt_deleted');
231
define('LOG_LP_ATTEMPT_DELETE', 'lp_attempt_deleted');
232
define('LOG_QUESTION_RESULT_DELETE', 'qst_attempt_deleted');
233
234
define('LOG_MY_FOLDER_CREATE', 'my_folder_created');
235
define('LOG_MY_FOLDER_CHANGE', 'my_folder_changed');
236
define('LOG_MY_FOLDER_DELETE', 'my_folder_deleted');
237
define('LOG_MY_FOLDER_COPY', 'my_folder_copied');
238
define('LOG_MY_FOLDER_CUT', 'my_folder_cut');
239
define('LOG_MY_FOLDER_PASTE', 'my_folder_pasted');
240
define('LOG_MY_FOLDER_UPLOAD', 'my_folder_uploaded');
241
242
// Event logs data types (max 20 chars)
243
define('LOG_COURSE_CODE', 'course_code');
244
define('LOG_COURSE_ID', 'course_id');
245
define('LOG_USER_ID', 'user_id');
246
define('LOG_USER_OBJECT', 'user_object');
247
define('LOG_USER_FIELD_VARIABLE', 'user_field_variable');
248
define('LOG_SESSION_ID', 'session_id');
249
250
define('LOG_QUESTION_ID', 'question_id');
251
define('LOG_SESSION_CATEGORY_ID', 'session_category_id');
252
define('LOG_CONFIGURATION_SETTINGS_CATEGORY', 'settings_category');
253
define('LOG_CONFIGURATION_SETTINGS_VARIABLE', 'settings_variable');
254
define('LOG_PLATFORM_LANGUAGE', 'default_platform_language');
255
define('LOG_PLUGIN_UPLOAD', 'plugin_upload');
256
define('LOG_PLUGIN_ENABLE', 'plugin_enable');
257
define('LOG_PLUGIN_SETTINGS_CHANGE', 'plugin_settings_change');
258
define('LOG_CAREER_ID', 'career_id');
259
define('LOG_PROMOTION_ID', 'promotion_id');
260
define('LOG_GRADEBOOK_LOCKED', 'gradebook_locked');
261
define('LOG_GRADEBOOK_UNLOCKED', 'gradebook_unlocked');
262
define('LOG_GRADEBOOK_ID', 'gradebook_id');
263
define('LOG_WIKI_PAGE_ID', 'wiki_page_id');
264
define('LOG_EXERCISE_ID', 'exercise_id');
265
define('LOG_EXERCISE_AND_USER_ID', 'exercise_and_user_id');
266
define('LOG_LP_ID', 'lp_id');
267
define('LOG_EXERCISE_ATTEMPT_QUESTION_ID', 'exercise_a_q_id');
268
define('LOG_EXERCISE_ATTEMPT', 'exe_id');
269
270
define('LOG_WORK_DIR_DELETE', 'work_dir_delete');
271
define('LOG_WORK_FILE_DELETE', 'work_file_delete');
272
define('LOG_WORK_DATA', 'work_data_array');
273
274
define('LOG_MY_FOLDER_PATH', 'path');
275
define('LOG_MY_FOLDER_NEW_PATH', 'new_path');
276
277
define('LOG_TERM_CONDITION_ACCEPTED', 'term_condition_accepted');
278
define('LOG_USER_CONFIRMED_EMAIL', 'user_confirmed_email');
279
define('LOG_USER_REMOVED_LEGAL_ACCEPT', 'user_removed_legal_accept');
280
281
define('LOG_USER_DELETE_ACCOUNT_REQUEST', 'user_delete_account_request');
282
283
define('LOG_QUESTION_CREATED', 'question_created');
284
define('LOG_QUESTION_UPDATED', 'question_updated');
285
define('LOG_QUESTION_DELETED', 'question_deleted');
286
define('LOG_QUESTION_REMOVED_FROM_QUIZ', 'question_removed_from_quiz');
287
288
define('USERNAME_PURIFIER', '/[^0-9A-Za-z_\.-]/');
289
290
//used when login_is_email setting is true
291
define('USERNAME_PURIFIER_MAIL', '/[^0-9A-Za-z_\.@]/');
292
define('USERNAME_PURIFIER_SHALLOW', '/\s/');
293
294
// This constant is a result of Windows OS detection, it has a boolean value:
295
// true whether the server runs on Windows OS, false otherwise.
296
define('IS_WINDOWS_OS', api_is_windows_os());
297
298
// iconv extension, for PHP5 on Windows it is installed by default.
299
define('ICONV_INSTALLED', function_exists('iconv'));
300
define('MBSTRING_INSTALLED', function_exists('mb_strlen')); // mbstring extension.
301
302
// Patterns for processing paths. Examples.
303
define('REPEATED_SLASHES_PURIFIER', '/\/{2,}/'); // $path = preg_replace(REPEATED_SLASHES_PURIFIER, '/', $path);
304
define('VALID_WEB_PATH', '/https?:\/\/[^\/]*(\/.*)?/i'); // $is_valid_path = preg_match(VALID_WEB_PATH, $path);
305
// $new_path = preg_replace(VALID_WEB_SERVER_BASE, $new_base, $path);
306
define('VALID_WEB_SERVER_BASE', '/https?:\/\/[^\/]*/i');
307
// Constants for api_get_path() and api_get_path_type(), etc. - registered path types.
308
// basic (leaf elements)
309
define('REL_CODE_PATH', 'REL_CODE_PATH');
310
define('REL_COURSE_PATH', 'REL_COURSE_PATH');
311
define('REL_HOME_PATH', 'REL_HOME_PATH');
312
313
// Constants for api_get_path() and api_get_path_type(), etc. - registered path types.
314
define('WEB_PATH', 'WEB_PATH');
315
define('SYS_PATH', 'SYS_PATH');
316
define('SYMFONY_SYS_PATH', 'SYMFONY_SYS_PATH');
317
define('SYS_UPLOAD_PATH', 'SYS_UPLOAD_PATH');
318
define('WEB_UPLOAD_PATH', 'WEB_UPLOAD_PATH');
319
320
define('REL_PATH', 'REL_PATH');
321
define('WEB_COURSE_PATH', 'WEB_COURSE_PATH');
322
define('WEB_CODE_PATH', 'WEB_CODE_PATH');
323
define('SYS_CODE_PATH', 'SYS_CODE_PATH');
324
define('SYS_LANG_PATH', 'SYS_LANG_PATH');
325
define('WEB_IMG_PATH', 'WEB_IMG_PATH');
326
define('WEB_CSS_PATH', 'WEB_CSS_PATH');
327
define('WEB_PUBLIC_PATH', 'WEB_PUBLIC_PATH');
328
define('SYS_CSS_PATH', 'SYS_CSS_PATH');
329
define('SYS_PLUGIN_PATH', 'SYS_PLUGIN_PATH');
330
define('WEB_PLUGIN_PATH', 'WEB_PLUGIN_PATH');
331
define('WEB_PLUGIN_ASSET_PATH', 'WEB_PLUGIN_ASSET_PATH');
332
define('SYS_ARCHIVE_PATH', 'SYS_ARCHIVE_PATH');
333
define('WEB_ARCHIVE_PATH', 'WEB_ARCHIVE_PATH');
334
define('LIBRARY_PATH', 'LIBRARY_PATH');
335
define('CONFIGURATION_PATH', 'CONFIGURATION_PATH');
336
define('WEB_LIBRARY_PATH', 'WEB_LIBRARY_PATH');
337
define('WEB_LIBRARY_JS_PATH', 'WEB_LIBRARY_JS_PATH');
338
define('WEB_AJAX_PATH', 'WEB_AJAX_PATH');
339
define('SYS_TEST_PATH', 'SYS_TEST_PATH');
340
define('SYS_TEMPLATE_PATH', 'SYS_TEMPLATE_PATH');
341
define('SYS_PUBLIC_PATH', 'SYS_PUBLIC_PATH');
342
define('SYS_FONTS_PATH', 'SYS_FONTS_PATH');
343
344
// Relations type with Course manager
345
define('COURSE_RELATION_TYPE_COURSE_MANAGER', 1);
346
define('SESSION_RELATION_TYPE_COURSE_MANAGER', 1);
347
348
// Relations type with Human resources manager
349
define('COURSE_RELATION_TYPE_RRHH', 1);
350
define('SESSION_RELATION_TYPE_RRHH', 1);
351
352
//User image sizes
353
define('USER_IMAGE_SIZE_ORIGINAL', 1);
354
define('USER_IMAGE_SIZE_BIG', 2);
355
define('USER_IMAGE_SIZE_MEDIUM', 3);
356
define('USER_IMAGE_SIZE_SMALL', 4);
357
358
// Relation type between users
359
define('USER_UNKNOWN', 0);
360
define('USER_RELATION_TYPE_UNKNOWN', 1);
361
define('USER_RELATION_TYPE_PARENT', 2); // should be deprecated is useless
362
define('USER_RELATION_TYPE_FRIEND', 3);
363
define('USER_RELATION_TYPE_GOODFRIEND', 4); // should be deprecated is useless
364
define('USER_RELATION_TYPE_ENEMY', 5); // should be deprecated is useless
365
define('USER_RELATION_TYPE_DELETED', 6);
366
define('USER_RELATION_TYPE_RRHH', 7);
367
define('USER_RELATION_TYPE_BOSS', 8);
368
define('USER_RELATION_TYPE_HRM_REQUEST', 9);
369
370
// Gradebook link constants
371
// Please do not change existing values, they are used in the database !
372
define('GRADEBOOK_ITEM_LIMIT', 1000);
373
374
define('LINK_EXERCISE', 1);
375
define('LINK_DROPBOX', 2);
376
define('LINK_STUDENTPUBLICATION', 3);
377
define('LINK_LEARNPATH', 4);
378
define('LINK_FORUM_THREAD', 5);
379
//define('LINK_WORK',6);
380
define('LINK_ATTENDANCE', 7);
381
define('LINK_SURVEY', 8);
382
define('LINK_HOTPOTATOES', 9);
383
384
// Score display types constants
385
define('SCORE_DIV', 1); // X / Y
386
define('SCORE_PERCENT', 2); // XX %
387
define('SCORE_DIV_PERCENT', 3); // X / Y (XX %)
388
define('SCORE_AVERAGE', 4); // XX %
389
define('SCORE_DECIMAL', 5); // 0.50  (X/Y)
390
define('SCORE_BAR', 6); // Uses the Display::bar_progress function
391
define('SCORE_SIMPLE', 7); // X
392
define('SCORE_IGNORE_SPLIT', 8); //  ??
393
define('SCORE_DIV_PERCENT_WITH_CUSTOM', 9); // X / Y (XX %) - Good!
394
define('SCORE_CUSTOM', 10); // Good!
395
define('SCORE_DIV_SIMPLE_WITH_CUSTOM', 11); // X - Good!
396
define('SCORE_DIV_SIMPLE_WITH_CUSTOM_LETTERS', 12); // X - Good!
397
define('SCORE_ONLY_SCORE', 13); // X - Good!
398
define('SCORE_NUMERIC', 14);
399
400
define('SCORE_BOTH', 1);
401
define('SCORE_ONLY_DEFAULT', 2);
402
define('SCORE_ONLY_CUSTOM', 3);
403
404
// From display.lib.php
405
406
define('MAX_LENGTH_BREADCRUMB', 100);
407
define('ICON_SIZE_ATOM', 8);
408
define('ICON_SIZE_TINY', 16);
409
define('ICON_SIZE_SMALL', 22);
410
define('ICON_SIZE_MEDIUM', 32);
411
define('ICON_SIZE_LARGE', 48);
412
define('ICON_SIZE_BIG', 64);
413
define('ICON_SIZE_HUGE', 128);
414
define('SHOW_TEXT_NEAR_ICONS', false);
415
416
// Session catalog
417
define('CATALOG_COURSES', 0);
418
define('CATALOG_SESSIONS', 1);
419
define('CATALOG_COURSES_SESSIONS', 2);
420
421
// Hook type events, pre-process and post-process.
422
// All means to be executed for both hook event types
423
define('HOOK_EVENT_TYPE_PRE', 0);
424
define('HOOK_EVENT_TYPE_POST', 1);
425
define('HOOK_EVENT_TYPE_ALL', 10);
426
427
define('CAREER_STATUS_ACTIVE', 1);
428
define('CAREER_STATUS_INACTIVE', 0);
429
430
define('PROMOTION_STATUS_ACTIVE', 1);
431
define('PROMOTION_STATUS_INACTIVE', 0);
432
433
// Group permissions
434
define('GROUP_PERMISSION_OPEN', '1');
435
define('GROUP_PERMISSION_CLOSED', '2');
436
437
// Group user permissions
438
define('GROUP_USER_PERMISSION_ADMIN', 1); // the admin of a group
439
define('GROUP_USER_PERMISSION_READER', 2); // a normal user
440
define('GROUP_USER_PERMISSION_PENDING_INVITATION', 3); // When an admin/moderator invites a user
441
define('GROUP_USER_PERMISSION_PENDING_INVITATION_SENT_BY_USER', 4); // an user joins a group
442
define('GROUP_USER_PERMISSION_MODERATOR', 5); // a moderator
443
define('GROUP_USER_PERMISSION_ANONYMOUS', 6); // an anonymous user
444
define('GROUP_USER_PERMISSION_HRM', 7); // a human resources manager
445
446
define('GROUP_IMAGE_SIZE_ORIGINAL', 1);
447
define('GROUP_IMAGE_SIZE_BIG', 2);
448
define('GROUP_IMAGE_SIZE_MEDIUM', 3);
449
define('GROUP_IMAGE_SIZE_SMALL', 4);
450
define('GROUP_TITLE_LENGTH', 50);
451
452
// Exercise
453
// @todo move into a class
454
define('ALL_ON_ONE_PAGE', 1);
455
define('ONE_PER_PAGE', 2);
456
457
define('EXERCISE_FEEDBACK_TYPE_END', 0); //Feedback 		 - show score and expected answers
458
define('EXERCISE_FEEDBACK_TYPE_DIRECT', 1); //DirectFeedback - Do not show score nor answers
459
define('EXERCISE_FEEDBACK_TYPE_EXAM', 2); // NoFeedback 	 - Show score only
460
define('EXERCISE_FEEDBACK_TYPE_POPUP', 3); // Popup BT#15827
461
462
define('RESULT_DISABLE_SHOW_SCORE_AND_EXPECTED_ANSWERS', 0); //show score and expected answers
463
define('RESULT_DISABLE_NO_SCORE_AND_EXPECTED_ANSWERS', 1); //Do not show score nor answers
464
define('RESULT_DISABLE_SHOW_SCORE_ONLY', 2); //Show score only
465
define('RESULT_DISABLE_SHOW_FINAL_SCORE_ONLY_WITH_CATEGORIES', 3); //Show final score only with categories
466
define('RESULT_DISABLE_SHOW_SCORE_ATTEMPT_SHOW_ANSWERS_LAST_ATTEMPT', 4);
467
define('RESULT_DISABLE_DONT_SHOW_SCORE_ONLY_IF_USER_FINISHES_ATTEMPTS_SHOW_ALWAYS_FEEDBACK', 5);
468
define('RESULT_DISABLE_RANKING', 6);
469
define('RESULT_DISABLE_SHOW_ONLY_IN_CORRECT_ANSWER', 7);
470
define('RESULT_DISABLE_SHOW_SCORE_AND_EXPECTED_ANSWERS_AND_RANKING', 8);
471
472
define('EXERCISE_MAX_NAME_SIZE', 80);
473
474
// Question types (edit next array as well when adding values)
475
// @todo move into a class
476
define('UNIQUE_ANSWER', 1);
477
define('MULTIPLE_ANSWER', 2);
478
define('FILL_IN_BLANKS', 3);
479
define('MATCHING', 4);
480
define('FREE_ANSWER', 5);
481
define('HOT_SPOT', 6);
482
define('HOT_SPOT_ORDER', 7);
483
define('HOT_SPOT_DELINEATION', 8);
484
define('MULTIPLE_ANSWER_COMBINATION', 9);
485
define('UNIQUE_ANSWER_NO_OPTION', 10);
486
define('MULTIPLE_ANSWER_TRUE_FALSE', 11);
487
define('MULTIPLE_ANSWER_COMBINATION_TRUE_FALSE', 12);
488
define('ORAL_EXPRESSION', 13);
489
define('GLOBAL_MULTIPLE_ANSWER', 14);
490
define('MEDIA_QUESTION', 15);
491
define('CALCULATED_ANSWER', 16);
492
define('UNIQUE_ANSWER_IMAGE', 17);
493
define('DRAGGABLE', 18);
494
define('MATCHING_DRAGGABLE', 19);
495
define('ANNOTATION', 20);
496
define('READING_COMPREHENSION', 21);
497
define('MULTIPLE_ANSWER_TRUE_FALSE_DEGREE_CERTAINTY', 22);
498
499
define('EXERCISE_CATEGORY_RANDOM_SHUFFLED', 1);
500
define('EXERCISE_CATEGORY_RANDOM_ORDERED', 2);
501
define('EXERCISE_CATEGORY_RANDOM_DISABLED', 0);
502
503
// Question selection type
504
define('EX_Q_SELECTION_ORDERED', 1);
505
define('EX_Q_SELECTION_RANDOM', 2);
506
define('EX_Q_SELECTION_CATEGORIES_ORDERED_QUESTIONS_ORDERED', 3);
507
define('EX_Q_SELECTION_CATEGORIES_RANDOM_QUESTIONS_ORDERED', 4);
508
define('EX_Q_SELECTION_CATEGORIES_ORDERED_QUESTIONS_RANDOM', 5);
509
define('EX_Q_SELECTION_CATEGORIES_RANDOM_QUESTIONS_RANDOM', 6);
510
define('EX_Q_SELECTION_CATEGORIES_RANDOM_QUESTIONS_ORDERED_NO_GROUPED', 7);
511
define('EX_Q_SELECTION_CATEGORIES_RANDOM_QUESTIONS_RANDOM_NO_GROUPED', 8);
512
define('EX_Q_SELECTION_CATEGORIES_ORDERED_BY_PARENT_QUESTIONS_ORDERED', 9);
513
define('EX_Q_SELECTION_CATEGORIES_ORDERED_BY_PARENT_QUESTIONS_RANDOM', 10);
514
515
// Used to save the skill_rel_item table
516
define('ITEM_TYPE_EXERCISE', 1);
517
define('ITEM_TYPE_HOTPOTATOES', 2);
518
define('ITEM_TYPE_LINK', 3);
519
define('ITEM_TYPE_LEARNPATH', 4);
520
define('ITEM_TYPE_GRADEBOOK', 5);
521
define('ITEM_TYPE_STUDENT_PUBLICATION', 6);
522
//define('ITEM_TYPE_FORUM', 7);
523
define('ITEM_TYPE_ATTENDANCE', 8);
524
define('ITEM_TYPE_SURVEY', 9);
525
define('ITEM_TYPE_FORUM_THREAD', 10);
526
527
// one big string with all question types, for the validator in pear/HTML/QuickForm/Rule/QuestionType
528
define(
529
    'QUESTION_TYPES',
530
    UNIQUE_ANSWER.':'.
531
    MULTIPLE_ANSWER.':'.
532
    FILL_IN_BLANKS.':'.
533
    MATCHING.':'.
534
    FREE_ANSWER.':'.
535
    HOT_SPOT.':'.
536
    HOT_SPOT_ORDER.':'.
537
    HOT_SPOT_DELINEATION.':'.
538
    MULTIPLE_ANSWER_COMBINATION.':'.
539
    UNIQUE_ANSWER_NO_OPTION.':'.
540
    MULTIPLE_ANSWER_TRUE_FALSE.':'.
541
    MULTIPLE_ANSWER_COMBINATION_TRUE_FALSE.':'.
542
    ORAL_EXPRESSION.':'.
543
    GLOBAL_MULTIPLE_ANSWER.':'.
544
    MEDIA_QUESTION.':'.
545
    CALCULATED_ANSWER.':'.
546
    UNIQUE_ANSWER_IMAGE.':'.
547
    DRAGGABLE.':'.
548
    MATCHING_DRAGGABLE.':'.
549
    MULTIPLE_ANSWER_TRUE_FALSE_DEGREE_CERTAINTY.':'.
550
    ANNOTATION
551
);
552
553
//Some alias used in the QTI exports
554
define('MCUA', 1);
555
define('TF', 1);
556
define('MCMA', 2);
557
define('FIB', 3);
558
559
// Skills
560
define('SKILL_TYPE_REQUIREMENT', 'required');
561
define('SKILL_TYPE_ACQUIRED', 'acquired');
562
define('SKILL_TYPE_BOTH', 'both');
563
564
// Message
565
define('MESSAGE_STATUS_NEW', '0');
566
define('MESSAGE_STATUS_UNREAD', '1');
567
//2 ??
568
define('MESSAGE_STATUS_DELETED', '3');
569
define('MESSAGE_STATUS_OUTBOX', '4');
570
define('MESSAGE_STATUS_INVITATION_PENDING', '5');
571
define('MESSAGE_STATUS_INVITATION_ACCEPTED', '6');
572
define('MESSAGE_STATUS_INVITATION_DENIED', '7');
573
define('MESSAGE_STATUS_WALL', '8');
574
define('MESSAGE_STATUS_WALL_DELETE', '9');
575
define('MESSAGE_STATUS_WALL_POST', '10');
576
define('MESSAGE_STATUS_CONVERSATION', '11');
577
define('MESSAGE_STATUS_FORUM', '12');
578
define('MESSAGE_STATUS_PROMOTED', '13');
579
580
// Images
581
define('IMAGE_WALL_SMALL_SIZE', 200);
582
define('IMAGE_WALL_MEDIUM_SIZE', 500);
583
define('IMAGE_WALL_BIG_SIZE', 2000);
584
define('IMAGE_WALL_SMALL', 'small');
585
define('IMAGE_WALL_MEDIUM', 'medium');
586
define('IMAGE_WALL_BIG', 'big');
587
588
// Social PLUGIN PLACES
589
define('SOCIAL_LEFT_PLUGIN', 1);
590
define('SOCIAL_CENTER_PLUGIN', 2);
591
define('SOCIAL_RIGHT_PLUGIN', 3);
592
define('CUT_GROUP_NAME', 50);
593
594
/**
595
 * FormValidator Filter.
596
 */
597
define('NO_HTML', 1);
598
define('STUDENT_HTML', 2);
599
define('TEACHER_HTML', 3);
600
define('STUDENT_HTML_FULLPAGE', 4);
601
define('TEACHER_HTML_FULLPAGE', 5);
602
603
// Timeline
604
define('TIMELINE_STATUS_ACTIVE', '1');
605
define('TIMELINE_STATUS_INACTIVE', '2');
606
607
// Event email template class
608
define('EVENT_EMAIL_TEMPLATE_ACTIVE', 1);
609
define('EVENT_EMAIL_TEMPLATE_INACTIVE', 0);
610
611
// Course home
612
define('SHORTCUTS_HORIZONTAL', 0);
613
define('SHORTCUTS_VERTICAL', 1);
614
615
// Image class
616
define('IMAGE_PROCESSOR', 'gd'); // 'imagick' or 'gd' strings
617
618
// Course copy
619
define('FILE_SKIP', 1);
620
define('FILE_RENAME', 2);
621
define('FILE_OVERWRITE', 3);
622
define('UTF8_CONVERT', false); //false by default
623
624
define('DOCUMENT', 'file');
625
define('FOLDER', 'folder');
626
627
define('RESOURCE_ASSET', 'asset');
628
define('RESOURCE_DOCUMENT', 'document');
629
define('RESOURCE_GLOSSARY', 'glossary');
630
define('RESOURCE_EVENT', 'calendar_event');
631
define('RESOURCE_LINK', 'link');
632
define('RESOURCE_COURSEDESCRIPTION', 'course_description');
633
define('RESOURCE_LEARNPATH', 'learnpath');
634
define('RESOURCE_LEARNPATH_CATEGORY', 'learnpath_category');
635
define('RESOURCE_ANNOUNCEMENT', 'announcement');
636
define('RESOURCE_FORUM', 'forum');
637
define('RESOURCE_FORUMTOPIC', 'thread');
638
define('RESOURCE_FORUMPOST', 'post');
639
define('RESOURCE_QUIZ', 'quiz');
640
define('RESOURCE_TEST_CATEGORY', 'test_category');
641
define('RESOURCE_QUIZQUESTION', 'Exercise_Question');
642
define('RESOURCE_TOOL_INTRO', 'Tool introduction');
643
define('RESOURCE_LINKCATEGORY', 'Link_Category');
644
define('RESOURCE_FORUMCATEGORY', 'Forum_Category');
645
define('RESOURCE_SCORM', 'Scorm');
646
define('RESOURCE_SURVEY', 'survey');
647
define('RESOURCE_SURVEYQUESTION', 'survey_question');
648
define('RESOURCE_SURVEYINVITATION', 'survey_invitation');
649
define('RESOURCE_WIKI', 'wiki');
650
define('RESOURCE_THEMATIC', 'thematic');
651
define('RESOURCE_ATTENDANCE', 'attendance');
652
define('RESOURCE_WORK', 'work');
653
define('RESOURCE_SESSION_COURSE', 'session_course');
654
define('RESOURCE_GRADEBOOK', 'gradebook');
655
define('ADD_THEMATIC_PLAN', 6);
656
657
// Max online users to show per page (whoisonline)
658
define('MAX_ONLINE_USERS', 12);
659
660
// Number of characters maximum to show in preview of course blog posts
661
define('BLOG_MAX_PREVIEW_CHARS', 800);
662
// HTML string to replace with a 'Read more...' link
663
define('BLOG_PAGE_BREAK', '<div style="page-break-after: always"><span style="display: none;">&nbsp;</span></div>');
664
665
// Make sure the CHAMILO_LOAD_WYSIWYG constant is defined
666
// To remove CKeditor libs from HTML, set this constant to true before loading
667
if (!defined('CHAMILO_LOAD_WYSIWYG')) {
668
    define('CHAMILO_LOAD_WYSIWYG', true);
669
}
670
671
/* Constants for course home */
672
define('TOOL_PUBLIC', 'Public');
673
define('TOOL_PUBLIC_BUT_HIDDEN', 'PublicButHide');
674
define('TOOL_COURSE_ADMIN', 'courseAdmin');
675
define('TOOL_PLATFORM_ADMIN', 'platformAdmin');
676
define('TOOL_AUTHORING', 'toolauthoring');
677
define('TOOL_INTERACTION', 'toolinteraction');
678
define('TOOL_COURSE_PLUGIN', 'toolcourseplugin'); //all plugins that can be enabled in courses
679
define('TOOL_ADMIN', 'tooladmin');
680
define('TOOL_ADMIN_PLATFORM', 'tooladminplatform');
681
define('TOOL_DRH', 'tool_drh');
682
define('TOOL_STUDENT_VIEW', 'toolstudentview');
683
define('TOOL_ADMIN_VISIBLE', 'tooladminvisible');
684
685
// Search settings (from main/inc/lib/search/IndexableChunk.class.php )
686
// some constants to avoid serialize string keys on serialized data array
687
define('SE_COURSE_ID', 0);
688
define('SE_TOOL_ID', 1);
689
define('SE_DATA', 2);
690
define('SE_USER', 3);
691
692
// in some cases we need top differenciate xapian documents of the same tool
693
define('SE_DOCTYPE_EXERCISE_EXERCISE', 0);
694
define('SE_DOCTYPE_EXERCISE_QUESTION', 1);
695
696
// xapian prefixes
697
define('XAPIAN_PREFIX_COURSEID', 'C');
698
define('XAPIAN_PREFIX_TOOLID', 'O');
699
700
/**
701
 * Returns a path to a certain resource within the Chamilo area, specifyed through a parameter.
702
 * Also, this function provides conversion between path types, in this case the input path points inside the Chamilo area too.
703
 *
704
 * See $_configuration['course_folder'] in the configuration.php to alter the WEB_COURSE_PATH and SYS_COURSE_PATH parameters.
705
706
 *
707
 * @param string $path (optional)   A path which type is to be converted. Also, it may be a defined constant for a path.
708
 *                     This parameter has meaning when $type parameter has one of the following values: TO_WEB, TO_SYS, TO_REL. Otherwise it is ignored.
709
 *
710
 * @return string the requested path or the converted path
711
 *
712
 * Notes about the current behaviour model:
713
 * 1. Windows back-slashes are converted to slashes in the result.
714
 * 2. A semi-absolute web-path is detected by its leading slash. On Linux systems, absolute system paths start with
715
 * a slash too, so an additional check about presence of leading system server base is implemented. For example, the function is
716
 * able to distinguish type difference between /var/www/chamilo/courses/ (SYS) and /chamilo/courses/ (REL).
717
 * 3. The function api_get_path() returns only these three types of paths, which in some sense are absolute. The function has
718
 * no a mechanism for processing relative web/system paths, such as: lesson01.html, ./lesson01.html, ../css/my_styles.css.
719
 * It has not been identified as needed yet.
720
 * 4. Also, resolving the meta-symbols "." and ".." within paths has not been implemented, it is to be identified as needed.
721
 *
722
 * For examples go to: *
723
 * See main/admin/system_status.php?section=paths
724
 *
725
 * Vchamilo changes : allow using an alternate configuration
726
 * to get vchamilo  instance paths
727
 */
728
function api_get_path($path = '', $configuration = [])
729
{
730
    global $paths;
731
732
    // get proper configuration data if exists
733
    global $_configuration;
734
735
    $emptyConfigurationParam = false;
736
    if (empty($configuration)) {
737
        $configuration = (array) $_configuration;
738
        $emptyConfigurationParam = true;
739
    }
740
741
    $root_sys = Container::getProjectDir();
742
743
    $root_web = '';
744
    // If no $root_web has been set so far *and* no custom config has been passed to the function
745
    // then re-use the previously-calculated (run-specific) $root_web and skip this complex calculation
746
    /*
747
    if (empty($root_web) || $emptyConfigurationParam === false || empty($configuration)) {
748
        // Resolve master hostname.
749
        if (!empty($configuration) && array_key_exists('root_web', $configuration)) {
750
            $root_web = $configuration['root_web'];
751
        } else {
752
            $root_web = '';
753
            // Try guess it from server.
754
            if (defined('SYSTEM_INSTALLATION') && SYSTEM_INSTALLATION) {
755
                if (($pos = strpos(($requested_page_rel = api_get_self()), 'main/install')) !== false) {
756
                    $root_rel = substr($requested_page_rel, 0, $pos);
757
                    // See http://www.mediawiki.org/wiki/Manual:$wgServer
758
                    $server_protocol = (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] == 'on') ? 'https' : 'http';
759
                    $server_name =
760
                        isset($_SERVER['SERVER_NAME']) ? $_SERVER['SERVER_NAME']
761
                            : (isset($_SERVER['HOSTNAME']) ? $_SERVER['HOSTNAME']
762
                            : (isset($_SERVER['HTTP_HOST']) ? $_SERVER['HTTP_HOST']
763
                                : (isset($_SERVER['SERVER_ADDR']) ? $_SERVER['SERVER_ADDR']
764
                                    : 'localhost')));
765
                    if (isset($_SERVER['SERVER_PORT']) && !strpos($server_name, ':')
766
                        && (($server_protocol == 'http'
767
                                && $_SERVER['SERVER_PORT'] != 80) || ($server_protocol == 'https' && $_SERVER['SERVER_PORT'] != 443))
768
                    ) {
769
                        $server_name .= ":".$_SERVER['SERVER_PORT'];
770
                    }
771
                    $root_web = $server_protocol.'://'.$server_name.$root_rel;
772
                    $root_sys = str_replace('\\', '/', realpath(__DIR__.'/../../../')).'/';
773
                }
774
                // Here we give up, so we don't touch anything.
775
            }
776
        }
777
    }*/
778
    if (isset(Container::$container)) {
779
        $root_web = Container::$container->get('router')->generate(
780
            'home',
781
            [],
782
            UrlGeneratorInterface::ABSOLUTE_URL
783
        );
784
    }
785
786
    if (isset($configuration['multiple_access_urls']) &&
787
        $configuration['multiple_access_urls']
788
    ) {
789
        // To avoid that the api_get_access_url() function fails since global.inc.php also calls the main_api.lib.php
790
        if (isset($configuration['access_url']) && !empty($configuration['access_url'])) {
791
            // We look into the DB the function api_get_access_url
792
            $urlInfo = api_get_access_url($configuration['access_url']);
793
            // Avoid default value
794
            $defaultValues = ['http://localhost/', 'https://localhost/'];
795
            if (!empty($urlInfo['url']) && !in_array($urlInfo['url'], $defaultValues)) {
796
                $root_web = 1 == $urlInfo['active'] ? $urlInfo['url'] : $configuration['root_web'];
797
            }
798
        }
799
    }
800
801
    $paths = [
802
        WEB_PATH => $root_web,
803
        SYMFONY_SYS_PATH => $root_sys,
804
        SYS_PATH => $root_sys.'public/',
805
        REL_PATH => '',
806
        CONFIGURATION_PATH => 'app/config/',
807
        LIBRARY_PATH => $root_sys.'public/main/inc/lib/',
808
809
        REL_COURSE_PATH => '',
810
        REL_CODE_PATH => '/main/',
811
812
        SYS_CODE_PATH => $root_sys.'public/main/',
813
        SYS_CSS_PATH => $root_sys.'public/build/css/',
814
        SYS_PLUGIN_PATH => $root_sys.'public/plugin/',
815
        SYS_ARCHIVE_PATH => $root_sys.'var/cache/',
816
       // SYS_UPLOAD_PATH => 'var/upload/',
817
        SYS_TEST_PATH => $root_sys.'tests/',
818
        SYS_TEMPLATE_PATH => $root_sys.'public/main/template/',
819
        SYS_PUBLIC_PATH => $root_sys.'public/',
820
        SYS_FONTS_PATH => $root_sys.'public/fonts/',
821
822
        WEB_CODE_PATH => $root_web.'main/',
823
        WEB_PLUGIN_ASSET_PATH => $root_web.'plugins/',
824
        WEB_COURSE_PATH => $root_web.'course/',
825
        WEB_IMG_PATH => $root_web.'img/',
826
        WEB_CSS_PATH => $root_web.'build/css/',
827
        WEB_AJAX_PATH => $root_web.'main/inc/ajax/',
828
        WEB_LIBRARY_PATH => $root_web.'main/inc/lib/',
829
        WEB_LIBRARY_JS_PATH => $root_web.'main/inc/lib/javascript/',
830
        WEB_PLUGIN_PATH => $root_web.'plugin/',
831
       // WEB_ARCHIVE_PATH => 'var/cache/',
832
        //WEB_UPLOAD_PATH => 'var/upload/',
833
        WEB_PUBLIC_PATH => $root_web,
834
    ];
835
836
    $root_rel = '';
837
838
    // Dealing with trailing slashes.
839
    $rootWebWithSlash = api_add_trailing_slash($root_web);
840
    $root_sys = api_add_trailing_slash($root_sys);
841
    $root_rel = api_add_trailing_slash($root_rel);
842
843
    global $virtualChamilo;
844
    if (!empty($virtualChamilo)) {
845
        $paths[SYS_ARCHIVE_PATH] = api_add_trailing_slash($virtualChamilo[SYS_ARCHIVE_PATH]);
846
        $paths[SYS_UPLOAD_PATH] = api_add_trailing_slash($virtualChamilo[SYS_UPLOAD_PATH]);
847
        //$paths[$root_web][WEB_UPLOAD_PATH] = api_add_trailing_slash($virtualChamilo[WEB_UPLOAD_PATH]);
848
        $paths[WEB_ARCHIVE_PATH] = api_add_trailing_slash($virtualChamilo[WEB_ARCHIVE_PATH]);
849
        //$paths[$root_web][WEB_COURSE_PATH] = api_add_trailing_slash($virtualChamilo[WEB_COURSE_PATH]);
850
851
        // WEB_UPLOAD_PATH should be handle by apache htaccess in the vhost
852
853
        // RewriteEngine On
854
        // RewriteRule /app/upload/(.*)$ http://localhost/other/upload/my-chamilo111-net/$1 [QSA,L]
855
856
        //$paths[$root_web][WEB_UPLOAD_PATH] = api_add_trailing_slash($virtualChamilo[WEB_UPLOAD_PATH]);
857
        //$paths[$root_web][REL_PATH] = $virtualChamilo[REL_PATH];
858
        //$paths[$root_web][REL_COURSE_PATH] = $virtualChamilo[REL_COURSE_PATH];
859
    }
860
861
    $path = trim($path);
862
863
    // Retrieving a common-purpose path.
864
    if (isset($paths[$path])) {
865
        return $paths[$path];
866
    }
867
868
    return false;
869
}
870
871
/**
872
 * Adds to a given path a trailing slash if it is necessary (adds "/" character at the end of the string).
873
 *
874
 * @param string $path the input path
875
 *
876
 * @return string returns the modified path
877
 */
878
function api_add_trailing_slash($path)
879
{
880
    return '/' == substr($path, -1) ? $path : $path.'/';
881
}
882
883
/**
884
 * Removes from a given path the trailing slash if it is necessary (removes "/" character from the end of the string).
885
 *
886
 * @param string $path the input path
887
 *
888
 * @return string returns the modified path
889
 */
890
function api_remove_trailing_slash($path)
891
{
892
    return '/' == substr($path, -1) ? substr($path, 0, -1) : $path;
893
}
894
895
/**
896
 * Checks the RFC 3986 syntax of a given URL.
897
 *
898
 * @param string $url      the URL to be checked
899
 * @param bool   $absolute whether the URL is absolute (beginning with a scheme such as "http:")
900
 *
901
 * @return string|false Returns the URL if it is valid, FALSE otherwise.
902
 *                      This function is an adaptation from the function valid_url(), Drupal CMS.
903
 *
904
 * @see http://drupal.org
905
 * Note: The built-in function filter_var($urs, FILTER_VALIDATE_URL) has a bug for some versions of PHP.
906
 * @see http://bugs.php.net/51192
907
 */
908
function api_valid_url($url, $absolute = false)
909
{
910
    if ($absolute) {
911
        if (preg_match("
912
            /^                                                      # Start at the beginning of the text
913
            (?:ftp|https?|feed):\/\/                                # Look for ftp, http, https or feed schemes
914
            (?:                                                     # Userinfo (optional) which is typically
915
                (?:(?:[\w\.\-\+!$&'\(\)*\+,;=]|%[0-9a-f]{2})+:)*    # a username or a username and password
916
                (?:[\w\.\-\+%!$&'\(\)*\+,;=]|%[0-9a-f]{2})+@        # combination
917
            )?
918
            (?:
919
                (?:[a-z0-9\-\.]|%[0-9a-f]{2})+                      # A domain name or a IPv4 address
920
                |(?:\[(?:[0-9a-f]{0,4}:)*(?:[0-9a-f]{0,4})\])       # or a well formed IPv6 address
921
            )
922
            (?::[0-9]+)?                                            # Server port number (optional)
923
            (?:[\/|\?]
924
                (?:[\w#!:\.\?\+=&@$'~*,;\/\(\)\[\]\-]|%[0-9a-f]{2}) # The path and query (optional)
925
            *)?
926
            $/xi", $url)) {
927
            return $url;
928
        }
929
930
        return false;
931
    } else {
932
        return preg_match("/^(?:[\w#!:\.\?\+=&@$'~*,;\/\(\)\[\]\-]|%[0-9a-f]{2})+$/i", $url) ? $url : false;
933
    }
934
}
935
936
/**
937
 * Checks whether a given string looks roughly like an email address.
938
 *
939
 * @param string $address the e-mail address to be checked
940
 *
941
 * @return mixed returns the e-mail if it is valid, FALSE otherwise
942
 */
943
function api_valid_email($address)
944
{
945
    return filter_var($address, FILTER_VALIDATE_EMAIL);
946
}
947
948
/* PROTECTION FUNCTIONS
949
   Use these functions to protect your scripts. */
950
951
/**
952
 * Function used to protect a course script.
953
 * The function blocks access when
954
 * - there is no $_SESSION["_course"] defined; or
955
 * - $is_allowed_in_course is set to false (this depends on the course
956
 * visibility and user status).
957
 *
958
 * This is only the first proposal, test and improve!
959
 *
960
 * @param bool Option to print headers when displaying error message. Default: false
961
 * @param bool whether session admins should be allowed or not
962
 * @param string $checkTool check if tool is available for users (user, group)
963
 *
964
 * @return bool True if the user has access to the current course or is out of a course context, false otherwise
965
 *
966
 * @todo replace global variable
967
 *
968
 * @author Roan Embrechts
969
 */
970
function api_protect_course_script($print_headers = false, $allow_session_admins = false, $checkTool = '')
971
{
972
    $course_info = api_get_course_info();
973
    if (empty($course_info)) {
974
        api_not_allowed($print_headers);
975
976
        return false;
977
    }
978
979
    if (api_is_drh()) {
980
        return true;
981
    }
982
983
    // Session admin has access to course
984
    $sessionAccess = api_get_configuration_value('session_admins_access_all_content');
985
    if ($sessionAccess) {
986
        $allow_session_admins = true;
987
    }
988
989
    if (api_is_platform_admin($allow_session_admins)) {
990
        return true;
991
    }
992
993
    $isAllowedInCourse = api_is_allowed_in_course();
994
    $is_visible = false;
995
    if (isset($course_info) && isset($course_info['visibility'])) {
996
        switch ($course_info['visibility']) {
997
            default:
998
            case COURSE_VISIBILITY_CLOSED:
999
                // Completely closed: the course is only accessible to the teachers. - 0
1000
                if ($isAllowedInCourse && api_get_user_id() && !api_is_anonymous()) {
1001
                    $is_visible = true;
1002
                }
1003
                break;
1004
            case COURSE_VISIBILITY_REGISTERED:
1005
                // Private - access authorized to course members only - 1
1006
                if ($isAllowedInCourse && api_get_user_id() && !api_is_anonymous()) {
1007
                    $is_visible = true;
1008
                }
1009
                break;
1010
            case COURSE_VISIBILITY_OPEN_PLATFORM:
1011
                // Open - access allowed for users registered on the platform - 2
1012
                if ($isAllowedInCourse && api_get_user_id() && !api_is_anonymous()) {
1013
                    $is_visible = true;
1014
                }
1015
                break;
1016
            case COURSE_VISIBILITY_OPEN_WORLD:
1017
                //Open - access allowed for the whole world - 3
1018
                $is_visible = true;
1019
                break;
1020
            case COURSE_VISIBILITY_HIDDEN:
1021
                //Completely closed: the course is only accessible to the teachers. - 0
1022
                if (api_is_platform_admin()) {
1023
                    $is_visible = true;
1024
                }
1025
                break;
1026
        }
1027
1028
        //If password is set and user is not registered to the course then the course is not visible
1029
        if (false == $isAllowedInCourse &&
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...
1030
            isset($course_info['registration_code']) &&
1031
            !empty($course_info['registration_code'])
1032
        ) {
1033
            $is_visible = false;
1034
        }
1035
    }
1036
1037
    if (!empty($checkTool)) {
1038
        if (!api_is_allowed_to_edit(true, true, true)) {
1039
            $toolInfo = api_get_tool_information_by_name($checkTool);
1040
            if (!empty($toolInfo) && isset($toolInfo['visibility']) && 0 == $toolInfo['visibility']) {
1041
                api_not_allowed(true);
1042
1043
                return false;
1044
            }
1045
        }
1046
    }
1047
1048
    // Check session visibility
1049
    $session_id = api_get_session_id();
1050
1051
    if (!empty($session_id)) {
1052
        // $isAllowedInCourse was set in local.inc.php
1053
        if (!$isAllowedInCourse) {
1054
            $is_visible = false;
1055
        }
1056
    }
1057
1058
    if (!$is_visible) {
1059
        api_not_allowed($print_headers);
1060
1061
        return false;
1062
    }
1063
1064
    return true;
1065
}
1066
1067
/**
1068
 * Function used to protect an admin script.
1069
 *
1070
 * The function blocks access when the user has no platform admin rights
1071
 * with an error message printed on default output
1072
 *
1073
 * @param bool Whether to allow session admins as well
1074
 * @param bool Whether to allow HR directors as well
1075
 * @param string An optional message (already passed through get_lang)
1076
 *
1077
 * @return bool True if user is allowed, false otherwise.
1078
 *              The function also outputs an error message in case not allowed
1079
 *
1080
 * @author Roan Embrechts (original author)
1081
 */
1082
function api_protect_admin_script($allow_sessions_admins = false, $allow_drh = false, $message = null)
1083
{
1084
    if (!api_is_platform_admin($allow_sessions_admins, $allow_drh)) {
1085
        api_not_allowed(true, $message);
1086
1087
        return false;
1088
    }
1089
1090
    return true;
1091
}
1092
1093
/**
1094
 * Function used to protect a teacher script.
1095
 * The function blocks access when the user has no teacher rights.
1096
 *
1097
 * @return bool True if the current user can access the script, false otherwise
1098
 *
1099
 * @author Yoselyn Castillo
1100
 */
1101
function api_protect_teacher_script()
1102
{
1103
    if (!api_is_allowed_to_edit()) {
1104
        api_not_allowed(true);
1105
1106
        return false;
1107
    }
1108
1109
    return true;
1110
}
1111
1112
/**
1113
 * Function used to prevent anonymous users from accessing a script.
1114
 *
1115
 * @param bool|true $printHeaders
1116
 *
1117
 * @author Roan Embrechts
1118
 *
1119
 * @return bool
1120
 */
1121
function api_block_anonymous_users($printHeaders = true)
1122
{
1123
    $user = api_get_user_info();
1124
    if (!(isset($user['user_id']) && $user['user_id']) || api_is_anonymous($user['user_id'], true)) {
1125
        api_not_allowed($printHeaders);
1126
1127
        return false;
1128
    }
1129
1130
    return true;
1131
}
1132
1133
/**
1134
 * Returns a rough evaluation of the browser's name and version based on very
1135
 * simple regexp.
1136
 *
1137
 * @return array with the navigator name and version ['name' => '...', 'version' => '...']
1138
 */
1139
function api_get_navigator()
1140
{
1141
    $navigator = 'Unknown';
1142
    $version = 0;
1143
1144
    if (!isset($_SERVER['HTTP_USER_AGENT'])) {
1145
        return ['name' => 'Unknown', 'version' => '0.0.0'];
1146
    }
1147
1148
    if (false !== strpos($_SERVER['HTTP_USER_AGENT'], 'Opera')) {
1149
        $navigator = 'Opera';
1150
        [, $version] = explode('Opera', $_SERVER['HTTP_USER_AGENT']);
1151
    } elseif (false !== strpos($_SERVER['HTTP_USER_AGENT'], 'Edge')) {
1152
        $navigator = 'Edge';
1153
        [, $version] = explode('Edge', $_SERVER['HTTP_USER_AGENT']);
1154
    } elseif (false !== strpos($_SERVER['HTTP_USER_AGENT'], 'MSIE')) {
1155
        $navigator = 'Internet Explorer';
1156
        [, $version] = explode('MSIE ', $_SERVER['HTTP_USER_AGENT']);
1157
    } elseif (false !== strpos($_SERVER['HTTP_USER_AGENT'], 'Chrome')) {
1158
        $navigator = 'Chrome';
1159
        [, $version] = explode('Chrome', $_SERVER['HTTP_USER_AGENT']);
1160
    } elseif (false !== stripos($_SERVER['HTTP_USER_AGENT'], 'Safari')) {
1161
        $navigator = 'Safari';
1162
        if (false !== stripos($_SERVER['HTTP_USER_AGENT'], 'Version/')) {
1163
            // If this Safari does have the "Version/" string in its user agent
1164
            // then use that as a version indicator rather than what's after
1165
            // "Safari/" which is rather a "build number" or something
1166
            [, $version] = explode('Version/', $_SERVER['HTTP_USER_AGENT']);
1167
        } else {
1168
            [, $version] = explode('Safari/', $_SERVER['HTTP_USER_AGENT']);
1169
        }
1170
    } elseif (false !== strpos($_SERVER['HTTP_USER_AGENT'], 'Firefox')) {
1171
        $navigator = 'Firefox';
1172
        [, $version] = explode('Firefox', $_SERVER['HTTP_USER_AGENT']);
1173
    } elseif (false !== strpos($_SERVER['HTTP_USER_AGENT'], 'Netscape')) {
1174
        $navigator = 'Netscape';
1175
        if (false !== stripos($_SERVER['HTTP_USER_AGENT'], 'Netscape/')) {
1176
            [, $version] = explode('Netscape', $_SERVER['HTTP_USER_AGENT']);
1177
        } else {
1178
            [, $version] = explode('Navigator', $_SERVER['HTTP_USER_AGENT']);
1179
        }
1180
    } elseif (false !== strpos($_SERVER['HTTP_USER_AGENT'], 'Konqueror')) {
1181
        $navigator = 'Konqueror';
1182
        [, $version] = explode('Konqueror', $_SERVER['HTTP_USER_AGENT']);
1183
    } elseif (false !== stripos($_SERVER['HTTP_USER_AGENT'], 'applewebkit')) {
1184
        $navigator = 'AppleWebKit';
1185
        [, $version] = explode('Version/', $_SERVER['HTTP_USER_AGENT']);
1186
    } elseif (false !== strpos($_SERVER['HTTP_USER_AGENT'], 'Gecko')) {
1187
        $navigator = 'Mozilla';
1188
        [, $version] = explode('; rv:', $_SERVER['HTTP_USER_AGENT']);
1189
    }
1190
1191
    // Now cut extra stuff around (mostly *after*) the version number
1192
    $version = preg_replace('/^([\/\s])?([\d\.]+)?.*/', '\2', $version);
1193
1194
    if (false === strpos($version, '.')) {
1195
        $version = number_format(doubleval($version), 1);
1196
    }
1197
1198
    return ['name' => $navigator, 'version' => $version];
1199
}
1200
1201
/**
1202
 * @return true if user self registration is allowed, false otherwise
1203
 */
1204
function api_is_self_registration_allowed()
1205
{
1206
    return isset($GLOBALS['allowSelfReg']) ? $GLOBALS['allowSelfReg'] : false;
0 ignored issues
show
Bug Best Practice introduced by
The expression return IssetNode ? $GLOB...'allowSelfReg'] : false could also return false which is incompatible with the documented return type true. Did you maybe forget to handle an error condition?

If the returned type also contains false, it is an indicator that maybe an error condition leading to the specific return statement remains unhandled.

Loading history...
1207
}
1208
1209
/**
1210
 * This function returns the id of the user which is stored in the $_user array.
1211
 *
1212
 * example: The function can be used to check if a user is logged in
1213
 *          if (api_get_user_id())
1214
 *
1215
 * @return int the id of the current user, 0 if is empty
1216
 */
1217
function api_get_user_id()
1218
{
1219
    $userInfo = Session::read('_user');
1220
    if ($userInfo && isset($userInfo['user_id'])) {
1221
        return (int) $userInfo['user_id'];
1222
    }
1223
1224
    return 0;
1225
}
1226
1227
/**
1228
 * Gets the list of courses a specific user is subscribed to.
1229
 *
1230
 * @param int       User ID
1231
 * @param bool $fetch_session Whether to get session courses or not - NOT YET IMPLEMENTED
1232
 *
1233
 * @return array Array of courses in the form [0]=>('code'=>xxx,'db'=>xxx,'dir'=>xxx,'status'=>d)
1234
 *
1235
 * @deprecated use CourseManager::get_courses_list_by_user_id()
1236
 */
1237
function api_get_user_courses($userId, $fetch_session = true)
1238
{
1239
    // Get out if not integer
1240
    if ($userId != strval(intval($userId))) {
1241
        return [];
1242
    }
1243
1244
    $t_course = Database::get_main_table(TABLE_MAIN_COURSE);
1245
    $t_course_user = Database::get_main_table(TABLE_MAIN_COURSE_USER);
1246
1247
    $sql = "SELECT cc.id as real_id, cc.code code, cc.directory dir, cu.status status
1248
            FROM $t_course cc, $t_course_user cu
1249
            WHERE
1250
                cc.id = cu.c_id AND
1251
                cu.user_id = $userId AND
1252
                cu.relation_type <> ".COURSE_RELATION_TYPE_RRHH;
1253
    $result = Database::query($sql);
1254
    if (false === $result) {
1255
        return [];
1256
    }
1257
1258
    $courses = [];
1259
    while ($row = Database::fetch_array($result)) {
1260
        // we only need the database name of the course
1261
        $courses[] = $row;
1262
    }
1263
1264
    return $courses;
1265
}
1266
1267
/**
1268
 * Formats user information into a standard array
1269
 * This function should be only used inside api_get_user_info().
1270
 *
1271
 * @param array Non-standard user array
0 ignored issues
show
Documentation Bug introduced by
The doc comment Non-standard at position 0 could not be parsed: Unknown type name 'Non-standard' at position 0 in Non-standard.
Loading history...
1272
 * @param bool $add_password
1273
 * @param bool $loadAvatars  turn off to improve performance
1274
 *
1275
 * @return array Standard user array
1276
 */
1277
function _api_format_user($user, $add_password = false, $loadAvatars = true)
1278
{
1279
    $result = [];
1280
1281
    if (!isset($user['id'])) {
1282
        return [];
1283
    }
1284
1285
    $result['firstname'] = null;
1286
    $result['lastname'] = null;
1287
1288
    if (isset($user['firstname']) && isset($user['lastname'])) {
1289
        // with only lowercase
1290
        $result['firstname'] = $user['firstname'];
1291
        $result['lastname'] = $user['lastname'];
1292
    } elseif (isset($user['firstName']) && isset($user['lastName'])) {
1293
        // with uppercase letters
1294
        $result['firstname'] = isset($user['firstName']) ? $user['firstName'] : null;
1295
        $result['lastname'] = isset($user['lastName']) ? $user['lastName'] : null;
1296
    }
1297
1298
    if (isset($user['email'])) {
1299
        $result['mail'] = isset($user['email']) ? $user['email'] : null;
1300
        $result['email'] = isset($user['email']) ? $user['email'] : null;
1301
    } else {
1302
        $result['mail'] = isset($user['mail']) ? $user['mail'] : null;
1303
        $result['email'] = isset($user['mail']) ? $user['mail'] : null;
1304
    }
1305
1306
    $result['complete_name'] = api_get_person_name($result['firstname'], $result['lastname']);
1307
    $result['complete_name_with_username'] = $result['complete_name'];
1308
1309
    if (!empty($user['username']) && 'false' === api_get_setting('profile.hide_username_with_complete_name')) {
1310
        $result['complete_name_with_username'] = $result['complete_name'].' ('.$user['username'].')';
1311
    }
1312
1313
    $showEmail = 'true' === api_get_setting('show_email_addresses');
1314
    if (!empty($user['email'])) {
1315
        $result['complete_name_with_email_forced'] = $result['complete_name'].' ('.$user['email'].')';
1316
        if ($showEmail) {
1317
            $result['complete_name_with_email'] = $result['complete_name'].' ('.$user['email'].')';
1318
        }
1319
    } else {
1320
        $result['complete_name_with_email'] = $result['complete_name'];
1321
        $result['complete_name_with_email_forced'] = $result['complete_name'];
1322
    }
1323
1324
    // Kept for historical reasons
1325
    $result['firstName'] = $result['firstname'];
1326
    $result['lastName'] = $result['lastname'];
1327
1328
    $attributes = [
1329
        'phone',
1330
        'address',
1331
        'picture_uri',
1332
        'official_code',
1333
        'status',
1334
        'active',
1335
        'auth_source',
1336
        'username',
1337
        'theme',
1338
        'language',
1339
        'creator_id',
1340
        'registration_date',
1341
        'hr_dept_id',
1342
        'expiration_date',
1343
        'last_login',
1344
        'user_is_online',
1345
    ];
1346
1347
    if ('true' === api_get_setting('extended_profile')) {
1348
        $attributes[] = 'competences';
1349
        $attributes[] = 'diplomas';
1350
        $attributes[] = 'teach';
1351
        $attributes[] = 'openarea';
1352
    }
1353
1354
    foreach ($attributes as $attribute) {
1355
        $result[$attribute] = isset($user[$attribute]) ? $user[$attribute] : null;
1356
    }
1357
1358
    $user_id = (int) $user['id'];
1359
    // Maintain the user_id index for backwards compatibility
1360
    $result['user_id'] = $result['id'] = $user_id;
1361
1362
    $hasCertificates = Certificate::getCertificateByUser($user_id);
1363
    $result['has_certificates'] = 0;
1364
    if (!empty($hasCertificates)) {
1365
        $result['has_certificates'] = 1;
1366
    }
1367
1368
    $result['icon_status'] = '';
1369
    $result['icon_status_medium'] = '';
1370
    $result['is_admin'] = UserManager::is_admin($user_id);
1371
1372
    // Getting user avatar.
1373
    if ($loadAvatars) {
1374
        $result['avatar'] = '';
1375
        $result['avatar_no_query'] = '';
1376
        $result['avatar_small'] = '';
1377
        $result['avatar_medium'] = '';
1378
1379
        /*if (!isset($user['avatar'])) {
1380
            $originalFile = UserManager::getUserPicture(
1381
                $user_id,
1382
                USER_IMAGE_SIZE_ORIGINAL,
1383
                null,
1384
                $result
1385
            );
1386
            $result['avatar'] = $originalFile;
1387
            $avatarString = explode('?', $result['avatar']);
1388
            $result['avatar_no_query'] = reset($avatarString);
1389
        } else {
1390
            $result['avatar'] = $user['avatar'];
1391
            $avatarString = explode('?', $user['avatar']);
1392
            $result['avatar_no_query'] = reset($avatarString);
1393
        }
1394
1395
        if (!isset($user['avatar_small'])) {
1396
            $smallFile = UserManager::getUserPicture(
1397
                $user_id,
1398
                USER_IMAGE_SIZE_SMALL,
1399
                null,
1400
                $result
1401
            );
1402
            $result['avatar_small'] = $smallFile;
1403
        } else {
1404
            $result['avatar_small'] = $user['avatar_small'];
1405
        }
1406
1407
        if (!isset($user['avatar_medium'])) {
1408
            $mediumFile = UserManager::getUserPicture(
1409
                $user_id,
1410
                USER_IMAGE_SIZE_MEDIUM,
1411
                null,
1412
                $result
1413
            );
1414
            $result['avatar_medium'] = $mediumFile;
1415
        } else {
1416
            $result['avatar_medium'] = $user['avatar_medium'];
1417
        }*/
1418
1419
        $urlImg = api_get_path(WEB_IMG_PATH);
1420
        $iconStatus = '';
1421
        $iconStatusMedium = '';
1422
        $label = '';
1423
        switch ($result['status']) {
1424
            case STUDENT:
1425
                if ($result['has_certificates']) {
1426
                    $iconStatus = $urlImg.'icons/svg/identifier_graduated.svg';
1427
                    $label = get_lang('Graduated');
1428
                } else {
1429
                    $iconStatus = $urlImg.'icons/svg/identifier_student.svg';
1430
                    $label = get_lang('Student');
1431
                }
1432
                break;
1433
            case COURSEMANAGER:
1434
                if ($result['is_admin']) {
1435
                    $iconStatus = $urlImg.'icons/svg/identifier_admin.svg';
1436
                    $label = get_lang('Admin');
1437
                } else {
1438
                    $iconStatus = $urlImg.'icons/svg/identifier_teacher.svg';
1439
                    $label = get_lang('Teacher');
1440
                }
1441
                break;
1442
            case STUDENT_BOSS:
1443
                $iconStatus = $urlImg.'icons/svg/identifier_teacher.svg';
1444
                $label = get_lang('StudentBoss');
1445
                break;
1446
        }
1447
1448
        if (!empty($iconStatus)) {
1449
            $iconStatusMedium = '<img src="'.$iconStatus.'" width="32px" height="32px">';
1450
            $iconStatus = '<img src="'.$iconStatus.'" width="22px" height="22px">';
1451
        }
1452
1453
        $result['icon_status'] = $iconStatus;
1454
        $result['icon_status_label'] = $label;
1455
        $result['icon_status_medium'] = $iconStatusMedium;
1456
    }
1457
1458
    if (isset($user['user_is_online'])) {
1459
        $result['user_is_online'] = true == $user['user_is_online'] ? 1 : 0;
1460
    }
1461
    if (isset($user['user_is_online_in_chat'])) {
1462
        $result['user_is_online_in_chat'] = (int) $user['user_is_online_in_chat'];
1463
    }
1464
1465
    if ($add_password) {
1466
        $result['password'] = $user['password'];
1467
    }
1468
1469
    if (isset($result['profile_completed'])) {
1470
        $result['profile_completed'] = $user['profile_completed'];
1471
    }
1472
1473
    $result['profile_url'] = api_get_path(WEB_CODE_PATH).'social/profile.php?u='.$user_id;
1474
1475
    // Send message link
1476
    $sendMessage = api_get_path(WEB_AJAX_PATH).'user_manager.ajax.php?a=get_user_popup&user_id='.$user_id;
1477
    $result['complete_name_with_message_link'] = Display::url(
1478
        $result['complete_name_with_username'],
1479
        $sendMessage,
1480
        ['class' => 'ajax']
1481
    );
1482
1483
    if (isset($user['extra'])) {
1484
        $result['extra'] = $user['extra'];
1485
    }
1486
1487
    return $result;
1488
}
1489
1490
/**
1491
 * Finds all the information about a user.
1492
 * If no parameter is passed you find all the information about the current user.
1493
 *
1494
 * @param int  $user_id
1495
 * @param bool $checkIfUserOnline
1496
 * @param bool $showPassword
1497
 * @param bool $loadExtraData
1498
 * @param bool $loadOnlyVisibleExtraData Get the user extra fields that are visible
1499
 * @param bool $loadAvatars              turn off to improve performance and if avatars are not needed
1500
 * @param bool $updateCache              update apc cache if exists
1501
 *
1502
 * @return mixed $user_info user_id, lastname, firstname, username, email, etc or false on error
1503
 *
1504
 * @author Patrick Cool <[email protected]>
1505
 * @author Julio Montoya
1506
 *
1507
 * @version 21 September 2004
1508
 */
1509
function api_get_user_info(
1510
    $user_id = 0,
1511
    $checkIfUserOnline = false,
1512
    $showPassword = false,
1513
    $loadExtraData = false,
1514
    $loadOnlyVisibleExtraData = false,
1515
    $loadAvatars = true,
1516
    $updateCache = false
1517
) {
1518
    // Make sure user_id is safe
1519
    $user_id = (int) $user_id;
1520
    $user = false;
1521
    if (empty($user_id)) {
1522
        $userFromSession = Session::read('_user');
1523
        if (isset($userFromSession) && !empty($userFromSession)) {
1524
            return $userFromSession;
1525
            /*
1526
            return _api_format_user(
1527
                $userFromSession,
1528
                $showPassword,
1529
                $loadAvatars
1530
            );*/
1531
        }
1532
1533
        return false;
1534
    }
1535
1536
    $sql = "SELECT * FROM ".Database::get_main_table(TABLE_MAIN_USER)."
1537
            WHERE id = $user_id";
1538
    $result = Database::query($sql);
1539
    if (Database::num_rows($result) > 0) {
1540
        $result_array = Database::fetch_array($result);
1541
        $result_array['user_is_online_in_chat'] = 0;
1542
        if ($checkIfUserOnline) {
1543
            $use_status_in_platform = user_is_online($user_id);
1544
            $result_array['user_is_online'] = $use_status_in_platform;
1545
            $user_online_in_chat = 0;
1546
            if ($use_status_in_platform) {
1547
                $user_status = UserManager::get_extra_user_data_by_field(
1548
                    $user_id,
1549
                    'user_chat_status',
1550
                    false,
1551
                    true
1552
                );
1553
                if (1 == (int) $user_status['user_chat_status']) {
1554
                    $user_online_in_chat = 1;
1555
                }
1556
            }
1557
            $result_array['user_is_online_in_chat'] = $user_online_in_chat;
1558
        }
1559
1560
        if ($loadExtraData) {
1561
            $fieldValue = new ExtraFieldValue('user');
1562
            $result_array['extra'] = $fieldValue->getAllValuesForAnItem(
1563
                $user_id,
1564
                $loadOnlyVisibleExtraData
1565
            );
1566
        }
1567
        $user = _api_format_user($result_array, $showPassword, $loadAvatars);
1568
    }
1569
1570
    return $user;
1571
}
1572
1573
function api_get_user_info_from_entity(
1574
    User $user,
1575
    $checkIfUserOnline = false,
1576
    $showPassword = false,
1577
    $loadExtraData = false,
1578
    $loadOnlyVisibleExtraData = false,
1579
    $loadAvatars = true,
1580
    $loadCertificate = false
1581
) {
1582
    if (!$user instanceof UserInterface) {
1583
        return false;
1584
    }
1585
1586
    // Make sure user_id is safe
1587
    $user_id = (int) $user->getId();
1588
1589
    if (empty($user_id)) {
1590
        $userFromSession = Session::read('_user');
1591
1592
        if (isset($userFromSession) && !empty($userFromSession)) {
1593
            return $userFromSession;
1594
        }
1595
1596
        return false;
1597
    }
1598
1599
    $result = [];
1600
    $result['user_is_online_in_chat'] = 0;
1601
    if ($checkIfUserOnline) {
1602
        $use_status_in_platform = user_is_online($user_id);
1603
        $result['user_is_online'] = $use_status_in_platform;
1604
        $user_online_in_chat = 0;
1605
        if ($use_status_in_platform) {
1606
            $user_status = UserManager::get_extra_user_data_by_field(
1607
                $user_id,
1608
                'user_chat_status',
1609
                false,
1610
                true
1611
            );
1612
            if (1 == (int) $user_status['user_chat_status']) {
1613
                $user_online_in_chat = 1;
1614
            }
1615
        }
1616
        $result['user_is_online_in_chat'] = $user_online_in_chat;
1617
    }
1618
1619
    if ($loadExtraData) {
1620
        $fieldValue = new ExtraFieldValue('user');
1621
        $result['extra'] = $fieldValue->getAllValuesForAnItem(
1622
            $user_id,
1623
            $loadOnlyVisibleExtraData
1624
        );
1625
    }
1626
1627
    $result['username'] = $user->getUsername();
1628
    $result['status'] = $user->getStatus();
1629
    $result['firstname'] = $user->getFirstname();
1630
    $result['lastname'] = $user->getLastname();
1631
    $result['email'] = $result['mail'] = $user->getEmail();
1632
    $result['complete_name'] = api_get_person_name($result['firstname'], $result['lastname']);
1633
    $result['complete_name_with_username'] = $result['complete_name'];
1634
1635
    if (!empty($result['username']) && 'false' === api_get_setting('profile.hide_username_with_complete_name')) {
1636
        $result['complete_name_with_username'] = $result['complete_name'].' ('.$result['username'].')';
1637
    }
1638
1639
    $showEmail = 'true' === api_get_setting('show_email_addresses');
1640
    if (!empty($result['email'])) {
1641
        $result['complete_name_with_email_forced'] = $result['complete_name'].' ('.$result['email'].')';
1642
        if ($showEmail) {
1643
            $result['complete_name_with_email'] = $result['complete_name'].' ('.$result['email'].')';
1644
        }
1645
    } else {
1646
        $result['complete_name_with_email'] = $result['complete_name'];
1647
        $result['complete_name_with_email_forced'] = $result['complete_name'];
1648
    }
1649
1650
    // Kept for historical reasons
1651
    $result['firstName'] = $result['firstname'];
1652
    $result['lastName'] = $result['lastname'];
1653
1654
    $attributes = [
1655
        'picture_uri',
1656
        'last_login',
1657
        'user_is_online',
1658
    ];
1659
1660
    $result['phone'] = $user->getPhone();
1661
    $result['address'] = $user->getAddress();
1662
    $result['official_code'] = $user->getOfficialCode();
1663
    $result['active'] = $user->getActive();
1664
    $result['auth_source'] = $user->getAuthSource();
1665
    $result['language'] = $user->getLanguage();
1666
    $result['creator_id'] = $user->getCreatorId();
1667
    $result['registration_date'] = $user->getRegistrationDate()->format('Y-m-d H:i:s');
1668
    $result['hr_dept_id'] = $user->getHrDeptId();
1669
    $result['expiration_date'] = '';
1670
    if ($user->getExpirationDate()) {
1671
        $result['expiration_date'] = $user->getExpirationDate()->format('Y-m-d H:i:s');
1672
    }
1673
1674
    $result['last_login'] = null;
1675
    if ($user->getLastLogin()) {
1676
        $result['last_login'] = $user->getLastLogin()->format('Y-m-d H:i:s');
1677
    }
1678
1679
    $result['competences'] = $user->getCompetences();
1680
    $result['diplomas'] = $user->getDiplomas();
1681
    $result['teach'] = $user->getTeach();
1682
    $result['openarea'] = $user->getOpenarea();
1683
    $user_id = (int) $user->getId();
1684
1685
    // Maintain the user_id index for backwards compatibility
1686
    $result['user_id'] = $result['id'] = $user_id;
1687
1688
    if ($loadCertificate) {
1689
        $hasCertificates = Certificate::getCertificateByUser($user_id);
1690
        $result['has_certificates'] = 0;
1691
        if (!empty($hasCertificates)) {
1692
            $result['has_certificates'] = 1;
1693
        }
1694
    }
1695
1696
    $result['icon_status'] = '';
1697
    $result['icon_status_medium'] = '';
1698
    $result['is_admin'] = UserManager::is_admin($user_id);
1699
1700
    // Getting user avatar.
1701
    if ($loadAvatars) {
1702
        $result['avatar'] = '';
1703
        $result['avatar_no_query'] = '';
1704
        $result['avatar_small'] = '';
1705
        $result['avatar_medium'] = '';
1706
1707
        /*if (!isset($user['avatar'])) {
1708
            $originalFile = UserManager::getUserPicture(
1709
                $user_id,
1710
                USER_IMAGE_SIZE_ORIGINAL,
1711
                null,
1712
                $result
1713
            );
1714
            $result['avatar'] = $originalFile;
1715
            $avatarString = explode('?', $result['avatar']);
1716
            $result['avatar_no_query'] = reset($avatarString);
1717
        } else {
1718
            $result['avatar'] = $user['avatar'];
1719
            $avatarString = explode('?', $user['avatar']);
1720
            $result['avatar_no_query'] = reset($avatarString);
1721
        }
1722
1723
        if (!isset($user['avatar_small'])) {
1724
            $smallFile = UserManager::getUserPicture(
1725
                $user_id,
1726
                USER_IMAGE_SIZE_SMALL,
1727
                null,
1728
                $result
1729
            );
1730
            $result['avatar_small'] = $smallFile;
1731
        } else {
1732
            $result['avatar_small'] = $user['avatar_small'];
1733
        }
1734
1735
        if (!isset($user['avatar_medium'])) {
1736
            $mediumFile = UserManager::getUserPicture(
1737
                $user_id,
1738
                USER_IMAGE_SIZE_MEDIUM,
1739
                null,
1740
                $result
1741
            );
1742
            $result['avatar_medium'] = $mediumFile;
1743
        } else {
1744
            $result['avatar_medium'] = $user['avatar_medium'];
1745
        }*/
1746
1747
        //$urlImg = api_get_path(WEB_IMG_PATH);
1748
        $urlImg = '/';
1749
        $iconStatus = '';
1750
        $iconStatusMedium = '';
1751
1752
        switch ($user->getStatus()) {
1753
            case STUDENT:
1754
                if (isset($result['has_certificates']) && $result['has_certificates']) {
1755
                    $iconStatus = $urlImg.'icons/svg/identifier_graduated.svg';
1756
                } else {
1757
                    $iconStatus = $urlImg.'icons/svg/identifier_student.svg';
1758
                }
1759
                break;
1760
            case COURSEMANAGER:
1761
                if ($result['is_admin']) {
1762
                    $iconStatus = $urlImg.'icons/svg/identifier_admin.svg';
1763
                } else {
1764
                    $iconStatus = $urlImg.'icons/svg/identifier_teacher.svg';
1765
                }
1766
                break;
1767
            case STUDENT_BOSS:
1768
                $iconStatus = $urlImg.'icons/svg/identifier_teacher.svg';
1769
                break;
1770
        }
1771
1772
        if (!empty($iconStatus)) {
1773
            $iconStatusMedium = '<img src="'.$iconStatus.'" width="32px" height="32px">';
1774
            $iconStatus = '<img src="'.$iconStatus.'" width="22px" height="22px">';
1775
        }
1776
1777
        $result['icon_status'] = $iconStatus;
1778
        $result['icon_status_medium'] = $iconStatusMedium;
1779
    }
1780
1781
    if (isset($result['user_is_online'])) {
1782
        $result['user_is_online'] = true == $result['user_is_online'] ? 1 : 0;
1783
    }
1784
    if (isset($result['user_is_online_in_chat'])) {
1785
        $result['user_is_online_in_chat'] = (int) $result['user_is_online_in_chat'];
1786
    }
1787
1788
    $result['password'] = '';
1789
    if ($showPassword) {
1790
        $result['password'] = $user->getPassword();
1791
    }
1792
1793
    if (isset($result['profile_completed'])) {
1794
        $result['profile_completed'] = $result['profile_completed'];
1795
    }
1796
1797
    $result['profile_url'] = api_get_path(WEB_CODE_PATH).'social/profile.php?u='.$user_id;
1798
1799
    // Send message link
1800
    $sendMessage = api_get_path(WEB_AJAX_PATH).'user_manager.ajax.php?a=get_user_popup&user_id='.$user_id;
1801
    $result['complete_name_with_message_link'] = Display::url(
1802
        $result['complete_name_with_username'],
1803
        $sendMessage,
1804
        ['class' => 'ajax']
1805
    );
1806
1807
    if (isset($result['extra'])) {
1808
        $result['extra'] = $result['extra'];
1809
    }
1810
1811
    return $result;
1812
}
1813
1814
function api_get_lp_entity(int $id): ?CLp
1815
{
1816
    return Database::getManager()->getRepository(CLp::class)->find($id);
1817
}
1818
1819
function api_get_user_entity(int $userId = 0): ?User
1820
{
1821
    $userId = $userId ?: api_get_user_id();
1822
    $repo = UserManager::getRepository();
1823
1824
    /** @var User $user */
1825
    $user = $repo->find($userId);
1826
1827
    return $user;
1828
}
1829
1830
function api_get_current_user(): ?User
1831
{
1832
    $isLoggedIn = Container::$container->get('security.authorization_checker')->isGranted('IS_AUTHENTICATED_REMEMBERED');
1833
    if (false === $isLoggedIn) {
1834
        return null;
1835
    }
1836
1837
    $token = Container::$container->get('security.token_storage')->getToken();
1838
1839
    if (null !== $token) {
1840
        return $token->getUser();
1841
    }
1842
1843
    return null;
1844
}
1845
1846
/**
1847
 * Finds all the information about a user from username instead of user id.
1848
 *
1849
 * @param string $username
1850
 *
1851
 * @return mixed $user_info array user_id, lastname, firstname, username, email or false on error
1852
 *
1853
 * @author Yannick Warnier <[email protected]>
1854
 */
1855
function api_get_user_info_from_username($username)
1856
{
1857
    if (empty($username)) {
1858
        return false;
1859
    }
1860
    $username = trim($username);
1861
1862
    $sql = "SELECT * FROM ".Database::get_main_table(TABLE_MAIN_USER)."
1863
            WHERE username='".Database::escape_string($username)."'";
1864
    $result = Database::query($sql);
1865
    if (Database::num_rows($result) > 0) {
1866
        $resultArray = Database::fetch_array($result);
1867
1868
        return _api_format_user($resultArray);
1869
    }
1870
1871
    return false;
1872
}
1873
1874
/**
1875
 * Get first user with an email.
1876
 *
1877
 * @param string $email
1878
 *
1879
 * @return array|bool
1880
 */
1881
function api_get_user_info_from_email($email = '')
1882
{
1883
    if (empty($email)) {
1884
        return false;
1885
    }
1886
    $sql = "SELECT * FROM ".Database::get_main_table(TABLE_MAIN_USER)."
1887
            WHERE email ='".Database::escape_string($email)."' LIMIT 1";
1888
    $result = Database::query($sql);
1889
    if (Database::num_rows($result) > 0) {
1890
        $resultArray = Database::fetch_array($result);
1891
1892
        return _api_format_user($resultArray);
1893
    }
1894
1895
    return false;
1896
}
1897
1898
/**
1899
 * @return string
1900
 */
1901
function api_get_course_id()
1902
{
1903
    return Session::read('_cid', null);
1904
}
1905
1906
/**
1907
 * Returns the current course id (integer).
1908
 *
1909
 * @param string $code Optional course code
1910
 *
1911
 * @return int
1912
 */
1913
function api_get_course_int_id($code = null)
1914
{
1915
    if (!empty($code)) {
1916
        $code = Database::escape_string($code);
1917
        $row = Database::select(
1918
            'id',
1919
            Database::get_main_table(TABLE_MAIN_COURSE),
1920
            ['where' => ['code = ?' => [$code]]],
1921
            'first'
1922
        );
1923
1924
        if (is_array($row) && isset($row['id'])) {
1925
            return $row['id'];
1926
        } else {
1927
            return false;
1928
        }
1929
    }
1930
1931
    return Session::read('_real_cid', 0);
1932
}
1933
1934
/**
1935
 * Returns the current course directory.
1936
 *
1937
 * This function relies on api_get_course_info()
1938
 *
1939
 * @param string    The course code - optional (takes it from session if not given)
1940
 *
1941
 * @return string The directory where the course is located inside the Chamilo "courses" directory
1942
 *
1943
 * @author Yannick Warnier <[email protected]>
1944
 */
1945
function api_get_course_path($course_code = null)
1946
{
1947
    $info = !empty($course_code) ? api_get_course_info($course_code) : api_get_course_info();
1948
1949
    return $info['path'];
1950
}
1951
1952
/**
1953
 * Gets a course setting from the current course_setting table. Try always using integer values.
1954
 *
1955
 * @param string $settingName The name of the setting we want from the table
1956
 * @param array  $courseInfo
1957
 * @param bool   $force       force checking the value in the database
1958
 *
1959
 * @return mixed The value of that setting in that table. Return -1 if not found.
1960
 */
1961
function api_get_course_setting($settingName, $courseInfo = [], $force = false)
1962
{
1963
    if (empty($courseInfo)) {
1964
        $courseInfo = api_get_course_info();
1965
    }
1966
1967
    if (empty($courseInfo) || empty($settingName)) {
1968
        return -1;
1969
    }
1970
1971
    $courseId = isset($courseInfo['real_id']) && !empty($courseInfo['real_id']) ? $courseInfo['real_id'] : 0;
1972
1973
    if (empty($courseId)) {
1974
        return -1;
1975
    }
1976
1977
    static $courseSettingInfo = [];
1978
1979
    if ($force) {
1980
        $courseSettingInfo = [];
1981
    }
1982
1983
    if (!isset($courseSettingInfo[$courseId])) {
1984
        $table = Database::get_course_table(TABLE_COURSE_SETTING);
1985
        $settingName = Database::escape_string($settingName);
1986
1987
        $sql = "SELECT variable, value FROM $table
1988
                WHERE c_id = $courseId ";
1989
        $res = Database::query($sql);
1990
        if (Database::num_rows($res) > 0) {
1991
            $result = Database::store_result($res, 'ASSOC');
1992
            $courseSettingInfo[$courseId] = array_column($result, 'value', 'variable');
1993
1994
            if (isset($courseSettingInfo[$courseId]['email_alert_manager_on_new_quiz'])) {
1995
                $value = $courseSettingInfo[$courseId]['email_alert_manager_on_new_quiz'];
1996
                if (!is_null($value)) {
1997
                    $result = explode(',', $value);
1998
                    $courseSettingInfo[$courseId]['email_alert_manager_on_new_quiz'] = $result;
1999
                }
2000
            }
2001
        }
2002
    }
2003
2004
    if (isset($courseSettingInfo[$courseId]) && isset($courseSettingInfo[$courseId][$settingName])) {
2005
        return $courseSettingInfo[$courseId][$settingName];
2006
    }
2007
2008
    return -1;
2009
}
2010
2011
function api_get_course_plugin_setting($plugin, $settingName, $courseInfo = [])
2012
{
2013
    $value = api_get_course_setting($settingName, $courseInfo, true);
2014
2015
    if (-1 === $value) {
2016
        // Check global settings
2017
        $value = api_get_plugin_setting($plugin, $settingName);
2018
        if ('true' === $value) {
2019
            return 1;
2020
        }
2021
        if ('false' === $value) {
2022
            return 0;
2023
        }
2024
        if (null === $value) {
2025
            return -1;
2026
        }
2027
    }
2028
2029
    return $value;
2030
}
2031
2032
/**
2033
 * Gets an anonymous user ID.
2034
 *
2035
 * For some tools that need tracking, like the learnpath tool, it is necessary
2036
 * to have a usable user-id to enable some kind of tracking, even if not
2037
 * perfect. An anonymous ID is taken from the users table by looking for a
2038
 * status of "6" (anonymous).
2039
 *
2040
 * @return int User ID of the anonymous user, or O if no anonymous user found
2041
 */
2042
function api_get_anonymous_id()
2043
{
2044
    // Find if another anon is connected now
2045
    $table = Database::get_main_table(TABLE_STATISTIC_TRACK_E_LOGIN);
2046
    $tableU = Database::get_main_table(TABLE_MAIN_USER);
2047
    $ip = Database::escape_string(api_get_real_ip());
2048
    $max = (int) api_get_configuration_value('max_anonymous_users');
2049
    if ($max >= 2) {
2050
        $sql = "SELECT * FROM $table as TEL
2051
                JOIN $tableU as U
2052
                ON U.id = TEL.login_user_id
2053
                WHERE TEL.user_ip = '$ip'
2054
                    AND U.status = ".ANONYMOUS."
2055
                    AND U.id != 2 ";
2056
2057
        $result = Database::query($sql);
2058
        if (empty(Database::num_rows($result))) {
2059
            $login = uniqid('anon_');
2060
            $anonList = UserManager::get_user_list(['status' => ANONYMOUS], ['registration_date ASC']);
2061
            if (count($anonList) >= $max) {
2062
                foreach ($anonList as $userToDelete) {
2063
                    UserManager::delete_user($userToDelete['user_id']);
2064
                    break;
2065
                }
2066
            }
2067
2068
            return UserManager::create_user(
0 ignored issues
show
Bug Best Practice introduced by
The expression return UserManager::crea...lhost', $login, $login) could also return false which is incompatible with the documented return type integer. Did you maybe forget to handle an error condition?

If the returned type also contains false, it is an indicator that maybe an error condition leading to the specific return statement remains unhandled.

Loading history...
2069
                $login,
2070
                'anon',
2071
                ANONYMOUS,
2072
                ' anonymous@localhost',
2073
                $login,
2074
                $login
2075
            );
2076
        } else {
2077
            $row = Database::fetch_array($result, 'ASSOC');
2078
2079
            return $row['id'];
2080
        }
2081
    }
2082
2083
    $table = Database::get_main_table(TABLE_MAIN_USER);
2084
    $sql = "SELECT id
2085
            FROM $table
2086
            WHERE status = ".ANONYMOUS." ";
2087
    $res = Database::query($sql);
2088
    if (Database::num_rows($res) > 0) {
2089
        $row = Database::fetch_array($res, 'ASSOC');
2090
2091
        return $row['id'];
2092
    }
2093
2094
    // No anonymous user was found.
2095
    return 0;
2096
}
2097
2098
/**
2099
 * @param int $courseId
2100
 * @param int $sessionId
2101
 * @param int $groupId
2102
 *
2103
 * @return string
2104
 */
2105
function api_get_cidreq_params($courseId, $sessionId = 0, $groupId = 0)
2106
{
2107
    $courseId = !empty($courseId) ? (int) $courseId : 0;
2108
    $sessionId = !empty($sessionId) ? (int) $sessionId : 0;
2109
    $groupId = !empty($groupId) ? (int) $groupId : 0;
2110
2111
    $url = 'cid='.$courseId;
2112
    $url .= '&sid='.$sessionId;
2113
    $url .= '&gid='.$groupId;
2114
2115
    return $url;
2116
}
2117
2118
/**
2119
 * Returns the current course url part including session, group, and gradebook params.
2120
 *
2121
 * @param bool   $addSessionId
2122
 * @param bool   $addGroupId
2123
 * @param string $origin
2124
 *
2125
 * @return string Course & session references to add to a URL
2126
 */
2127
function api_get_cidreq($addSessionId = true, $addGroupId = true, $origin = '')
2128
{
2129
    $courseId = api_get_course_int_id();
2130
    $url = empty($courseId) ? '' : 'cid='.$courseId;
2131
    $origin = empty($origin) ? api_get_origin() : Security::remove_XSS($origin);
2132
2133
    if ($addSessionId) {
2134
        if (!empty($url)) {
2135
            $url .= 0 == api_get_session_id() ? '&sid=0' : '&sid='.api_get_session_id();
2136
        }
2137
    }
2138
2139
    if ($addGroupId) {
2140
        if (!empty($url)) {
2141
            $url .= 0 == api_get_group_id() ? '&gid=0' : '&gid='.api_get_group_id();
2142
        }
2143
    }
2144
2145
    if (!empty($url)) {
2146
        $url .= '&gradebook='.(int) api_is_in_gradebook();
2147
        $url .= '&origin='.$origin;
2148
    }
2149
2150
    return $url;
2151
}
2152
2153
/**
2154
 * Get if we visited a gradebook page.
2155
 *
2156
 * @return bool
2157
 */
2158
function api_is_in_gradebook()
2159
{
2160
    return Session::read('in_gradebook', false);
2161
}
2162
2163
/**
2164
 * Set that we are in a page inside a gradebook.
2165
 */
2166
function api_set_in_gradebook()
2167
{
2168
    Session::write('in_gradebook', true);
2169
}
2170
2171
/**
2172
 * Remove gradebook session.
2173
 */
2174
function api_remove_in_gradebook()
2175
{
2176
    Session::erase('in_gradebook');
2177
}
2178
2179
/**
2180
 * Returns the current course info array see api_format_course_array()
2181
 * If the course_code is given, the returned array gives info about that
2182
 * particular course, if none given it gets the course info from the session.
2183
 *
2184
 * @param string $courseCode
2185
 *
2186
 * @return array
2187
 */
2188
function api_get_course_info($courseCode = null)
2189
{
2190
    if (!empty($courseCode)) {
2191
        $course = Container::getCourseRepository()->findOneByCode($courseCode);
2192
2193
        return api_format_course_array($course);
2194
    }
2195
2196
    /*$course_code = Database::escape_string($course_code);
2197
    $courseId = api_get_course_int_id($course_code);
2198
    if (empty($courseId)) {
2199
        return [];
2200
    }
2201
2202
    $course_table = Database::get_main_table(TABLE_MAIN_COURSE);
2203
    $course_cat_table = Database::get_main_table(TABLE_MAIN_CATEGORY);
2204
    $sql = "SELECT
2205
                course.*,
2206
                course_category.code faCode,
2207
                course_category.name faName
2208
            FROM $course_table
2209
            LEFT JOIN $course_cat_table
2210
            ON course.category_code = course_category.code
2211
            WHERE course.id = $courseId";
2212
    $result = Database::query($sql);
2213
    $courseInfo = [];
2214
    if (Database::num_rows($result) > 0) {
2215
        $data = Database::fetch_array($result);
2216
        $courseInfo = api_format_course_array($data);
2217
    }
2218
2219
    return $courseInfo;*/
2220
2221
    $course = Session::read('_course');
2222
    if ('-1' == $course) {
2223
        $course = [];
2224
    }
2225
2226
    return $course;
2227
}
2228
2229
/**
2230
 * @param int $courseId
2231
 */
2232
function api_get_course_entity($courseId = 0): ?Course
2233
{
2234
    if (empty($courseId)) {
2235
        $courseId = api_get_course_int_id();
2236
    }
2237
2238
    return Container::getCourseRepository()->find($courseId);
0 ignored issues
show
Bug Best Practice introduced by
The expression return Chamilo\CoreBundl...tory()->find($courseId) returns the type Chamilo\CoreBundle\Entity\ResourceInterface which includes types incompatible with the type-hinted return Chamilo\CoreBundle\Entity\Course|null.
Loading history...
2239
}
2240
2241
/**
2242
 * @param int $id
2243
 */
2244
function api_get_session_entity($id = 0): ?SessionEntity
2245
{
2246
    if (empty($id)) {
2247
        $id = api_get_session_id();
2248
    }
2249
2250
    if (empty($id)) {
2251
        return null;
2252
    }
2253
2254
    return Container::getSessionRepository()->find($id);
2255
}
2256
2257
/**
2258
 * @param int $id
2259
 */
2260
function api_get_group_entity($id = 0): ?CGroup
2261
{
2262
    if (empty($id)) {
2263
        $id = api_get_group_id();
2264
    }
2265
2266
    return Container::getGroupRepository()->find($id);
0 ignored issues
show
Bug Best Practice introduced by
The expression return Chamilo\CoreBundl...Repository()->find($id) returns the type Chamilo\CoreBundle\Entity\ResourceInterface which includes types incompatible with the type-hinted return Chamilo\CourseBundle\Entity\CGroup|null.
Loading history...
2267
}
2268
2269
/**
2270
 * @param int $id
2271
 */
2272
function api_get_url_entity($id = 0): ?AccessUrl
2273
{
2274
    if (empty($id)) {
2275
        $id = api_get_current_access_url_id();
2276
    }
2277
2278
    return Container::getAccessUrlRepository()->find($id);
0 ignored issues
show
Bug Best Practice introduced by
The expression return Chamilo\CoreBundl...Repository()->find($id) returns the type Chamilo\CoreBundle\Entity\ResourceInterface which includes types incompatible with the type-hinted return Chamilo\CoreBundle\Entity\AccessUrl|null.
Loading history...
2279
}
2280
2281
/**
2282
 * Returns the current course info array.
2283
2284
 * Now if the course_code is given, the returned array gives info about that
2285
 * particular course, not specially the current one.
2286
 *
2287
 * @param int $id Numeric ID of the course
2288
 *
2289
 * @return array The course info as an array formatted by api_format_course_array, including category.name
2290
 */
2291
function api_get_course_info_by_id($id = 0)
2292
{
2293
    $id = (int) $id;
2294
    if (empty($id)) {
2295
        $course = Session::read('_course', []);
2296
2297
        return $course;
2298
    }
2299
2300
    $course = Container::getCourseRepository()->find($id);
2301
    if (empty($course)) {
2302
        return [];
2303
    }
2304
2305
    return api_format_course_array($course);
2306
}
2307
2308
/**
2309
 * Reformat the course array (output by api_get_course_info()) in order, mostly,
2310
 * to switch from 'code' to 'id' in the array.
2311
 *
2312
 * @return array
2313
 *
2314
 * @todo eradicate the false "id"=code field of the $_course array and use the int id
2315
 */
2316
function api_format_course_array(Course $course = null)
2317
{
2318
    if (empty($course)) {
2319
        return [];
2320
    }
2321
2322
    $courseData = [];
2323
    $courseData['id'] = $courseData['real_id'] = $course->getId();
2324
2325
    // Added
2326
    $courseData['code'] = $courseData['sysCode'] = $course->getCode();
2327
    $courseData['name'] = $courseData['title'] = $course->getTitle();
2328
    $courseData['official_code'] = $courseData['visual_code'] = $course->getVisualCode();
2329
    $courseData['path'] = $courseData['directory'] = $course->getDirectory(); // Use as key in path.
2330
    $courseData['creation_date'] = $course->getCreationDate()->format('Y-m-d H:i:s');
2331
    $courseData['titular'] = $course->getTutorName();
2332
    $courseData['language'] = $courseData['course_language'] = $course->getCourseLanguage();
2333
    $courseData['extLink']['url'] = $courseData['department_url'] = $course->getDepartmentUrl();
2334
    $courseData['extLink']['name'] = $courseData['department_name'] = $course->getDepartmentName();
2335
2336
    $courseData['visibility'] = $course->getVisibility();
2337
    $courseData['subscribe_allowed'] = $courseData['subscribe'] = $course->getSubscribe();
2338
    $courseData['unsubscribe'] = $course->getUnsubscribe();
2339
    $courseData['activate_legal'] = $course->getActivateLegal();
2340
    $courseData['legal'] = $course->getLegal();
2341
    $courseData['show_score'] = $course->getShowScore(); //used in the work tool
2342
2343
    //$coursePath = api_get_path(WEB_COURSE_PATH);
2344
    $coursePath = '/course/';
2345
    $webCourseHome = $coursePath.$courseData['real_id'].'/home';
2346
2347
    // Course password
2348
    $courseData['registration_code'] = $course->getRegistrationCode();
2349
    $courseData['disk_quota'] = $course->getDiskQuota();
2350
    $courseData['course_public_url'] = $webCourseHome;
2351
    $courseData['about_url'] = $coursePath.$courseData['real_id'].'/about';
2352
    $courseData['add_teachers_to_sessions_courses'] = $course->isAddTeachersToSessionsCourses();
2353
    $courseData['entity'] = $course;
2354
2355
    $image = Display::return_icon(
2356
        'course.png',
2357
        null,
2358
        null,
2359
        ICON_SIZE_BIG,
2360
        null,
2361
        true,
2362
        false
2363
    );
2364
2365
    $illustration = Container::getIllustrationRepository()->getIllustrationUrl($course);
2366
    if (!empty($illustration)) {
2367
        $image = $illustration;
2368
    }
2369
2370
    $courseData['course_image'] = $image.'?filter=course_picture_small';
2371
2372
    // Course large image
2373
    /*$courseData['course_image_large_source'] = '';
2374
    if (file_exists($courseSys.'/course-pic.png')) {
2375
        $url_image = $webCourseHome.'/course-pic.png';
2376
        $courseData['course_image_large_source'] = $courseSys.'/course-pic.png';
2377
    } else {
2378
        $url_image = Display::return_icon(
2379
            'session_default.png',
2380
            null,
2381
            null,
2382
            null,
2383
            null,
2384
            true,
2385
            true
2386
        );
2387
    }*/
2388
2389
    $courseData['course_image_large'] = $image.'?filter=course_picture_medium';
2390
2391
    return $courseData;
2392
}
2393
2394
/**
2395
 * Returns a difficult to guess password.
2396
 *
2397
 * @param int $length the length of the password
2398
 *
2399
 * @return string the generated password
2400
 */
2401
function api_generate_password($length = 8)
2402
{
2403
    if ($length < 2) {
2404
        $length = 2;
2405
    }
2406
2407
    $charactersLowerCase = 'abcdefghijkmnopqrstuvwxyz';
2408
    $charactersUpperCase = 'ABCDEFGHJKLMNPQRSTUVWXYZ';
2409
    $minNumbers = 2;
2410
    $length = $length - $minNumbers;
2411
    $minLowerCase = round($length / 2);
2412
    $minUpperCase = $length - $minLowerCase;
2413
2414
    $password = '';
2415
    $passwordRequirements = api_get_configuration_value('password_requirements');
2416
2417
    $factory = new RandomLib\Factory();
2418
    $generator = $factory->getGenerator(new SecurityLib\Strength(SecurityLib\Strength::MEDIUM));
2419
2420
    if (!empty($passwordRequirements)) {
2421
        $length = $passwordRequirements['min']['length'];
2422
        $minNumbers = $passwordRequirements['min']['numeric'];
2423
        $minLowerCase = $passwordRequirements['min']['lowercase'];
2424
        $minUpperCase = $passwordRequirements['min']['uppercase'];
2425
2426
        $rest = $length - $minNumbers - $minLowerCase - $minUpperCase;
2427
        // Add the rest to fill the length requirement
2428
        if ($rest > 0) {
2429
            $password .= $generator->generateString($rest, $charactersLowerCase.$charactersUpperCase);
2430
        }
2431
    }
2432
2433
    // Min digits default 2
2434
    for ($i = 0; $i < $minNumbers; $i++) {
2435
        $password .= $generator->generateInt(2, 9);
2436
    }
2437
2438
    // Min lowercase
2439
    $password .= $generator->generateString($minLowerCase, $charactersLowerCase);
2440
2441
    // Min uppercase
2442
    $password .= $generator->generateString($minUpperCase, $charactersUpperCase);
2443
    $password = str_shuffle($password);
2444
2445
    return $password;
2446
}
2447
2448
/**
2449
 * Checks a password to see wether it is OK to use.
2450
 *
2451
 * @param string $password
2452
 *
2453
 * @return bool if the password is acceptable, false otherwise
2454
 *              Notes about what a password "OK to use" is:
2455
 *              1. The password should be at least 5 characters long.
2456
 *              2. Only English letters (uppercase or lowercase, it doesn't matter) and digits are allowed.
2457
 *              3. The password should contain at least 3 letters.
2458
 *              4. It should contain at least 2 digits.
2459
 *              Settings will change if the configuration value is set: password_requirements
2460
 */
2461
function api_check_password($password)
2462
{
2463
    $passwordRequirements = Security::getPasswordRequirements();
2464
2465
    $minLength = $passwordRequirements['min']['length'];
2466
    $minNumbers = $passwordRequirements['min']['numeric'];
2467
    // Optional
2468
    $minLowerCase = $passwordRequirements['min']['lowercase'];
2469
    $minUpperCase = $passwordRequirements['min']['uppercase'];
2470
2471
    $minLetters = $minLowerCase + $minUpperCase;
2472
    $passwordLength = api_strlen($password);
2473
2474
    $conditions = [
2475
        'min_length' => $passwordLength >= $minLength,
2476
    ];
2477
2478
    $digits = 0;
2479
    $lowerCase = 0;
2480
    $upperCase = 0;
2481
2482
    for ($i = 0; $i < $passwordLength; $i++) {
2483
        $currentCharacterCode = api_ord(api_substr($password, $i, 1));
2484
        if ($currentCharacterCode >= 65 && $currentCharacterCode <= 90) {
2485
            $upperCase++;
2486
        }
2487
2488
        if ($currentCharacterCode >= 97 && $currentCharacterCode <= 122) {
2489
            $lowerCase++;
2490
        }
2491
        if ($currentCharacterCode >= 48 && $currentCharacterCode <= 57) {
2492
            $digits++;
2493
        }
2494
    }
2495
2496
    // Min number of digits
2497
    $conditions['min_numeric'] = $digits >= $minNumbers;
2498
2499
    if (!empty($minUpperCase)) {
2500
        // Uppercase
2501
        $conditions['min_uppercase'] = $upperCase >= $minUpperCase;
2502
    }
2503
2504
    if (!empty($minLowerCase)) {
2505
        // Lowercase
2506
        $conditions['min_lowercase'] = $upperCase >= $minLowerCase;
2507
    }
2508
2509
    // Min letters
2510
    $letters = $upperCase + $lowerCase;
2511
    $conditions['min_letters'] = $letters >= $minLetters;
2512
2513
    $isPasswordOk = true;
2514
    foreach ($conditions as $condition) {
2515
        if (false === $condition) {
2516
            $isPasswordOk = false;
2517
            break;
2518
        }
2519
    }
2520
2521
    if (false === $isPasswordOk) {
2522
        $output = get_lang('The new password does not match the minimum security requirements').'<br />';
2523
        $output .= Security::getPasswordRequirementsToString($conditions);
2524
2525
        Display::addFlash(Display::return_message($output, 'warning', false));
2526
    }
2527
2528
    return $isPasswordOk;
2529
}
2530
2531
/**
2532
 * Returns the status string corresponding to the status code.
2533
 *
2534
 * @author Noel Dieschburg
2535
 *
2536
 * @param the int status code
2537
 *
2538
 * @return string
2539
 */
2540
function get_status_from_code($status_code)
2541
{
2542
    switch ($status_code) {
2543
        case STUDENT:
2544
            return get_lang('Student', '');
2545
        case COURSEMANAGER:
2546
            return get_lang('Teacher', '');
2547
        case SESSIONADMIN:
2548
            return get_lang('SessionsAdmin', '');
2549
        case DRH:
2550
            return get_lang('Drh', '');
2551
    }
2552
}
2553
2554
/**
2555
 * Gets the current Chamilo (not PHP/cookie) session ID.
2556
 *
2557
 * @return int O if no active session, the session ID otherwise
2558
 */
2559
function api_get_session_id()
2560
{
2561
    return (int) Session::read('sid', 0);
2562
}
2563
2564
/**
2565
 * Gets the current Chamilo (not social network) group ID.
2566
 *
2567
 * @return int O if no active session, the session ID otherwise
2568
 */
2569
function api_get_group_id()
2570
{
2571
    return Session::read('gid', 0);
2572
}
2573
2574
/**
2575
 * Gets the current or given session name.
2576
 *
2577
 * @param   int     Session ID (optional)
2578
 *
2579
 * @return string The session name, or null if not found
2580
 */
2581
function api_get_session_name($session_id = 0)
2582
{
2583
    if (empty($session_id)) {
2584
        $session_id = api_get_session_id();
2585
        if (empty($session_id)) {
2586
            return null;
2587
        }
2588
    }
2589
    $t = Database::get_main_table(TABLE_MAIN_SESSION);
2590
    $s = "SELECT name FROM $t WHERE id = ".(int) $session_id;
2591
    $r = Database::query($s);
2592
    $c = Database::num_rows($r);
2593
    if ($c > 0) {
2594
        //technically, there can be only one, but anyway we take the first
2595
        $rec = Database::fetch_array($r);
2596
2597
        return $rec['name'];
2598
    }
2599
2600
    return null;
2601
}
2602
2603
/**
2604
 * Gets the session info by id.
2605
 *
2606
 * @param int $id Session ID
2607
 *
2608
 * @return array information of the session
2609
 */
2610
function api_get_session_info($id)
2611
{
2612
    return SessionManager::fetch($id);
2613
}
2614
2615
/**
2616
 * Gets the session visibility by session id.
2617
 *
2618
 * @param int  $session_id
2619
 * @param int  $courseId
2620
 * @param bool $ignore_visibility_for_admins
2621
 *
2622
 * @return int
2623
 *             0 = session still available,
2624
 *             SESSION_VISIBLE_READ_ONLY = 1,
2625
 *             SESSION_VISIBLE = 2,
2626
 *             SESSION_INVISIBLE = 3
2627
 */
2628
function api_get_session_visibility(
2629
    $session_id,
2630
    $courseId = null,
2631
    $ignore_visibility_for_admins = true
2632
) {
2633
    if (api_is_platform_admin()) {
2634
        if ($ignore_visibility_for_admins) {
2635
            return SESSION_AVAILABLE;
2636
        }
2637
    }
2638
2639
    $now = time();
2640
    if (empty($session_id)) {
2641
        return 0; // Means that the session is still available.
2642
    }
2643
2644
    $session_id = (int) $session_id;
2645
    $tbl_session = Database::get_main_table(TABLE_MAIN_SESSION);
2646
2647
    $result = Database::query("SELECT * FROM $tbl_session WHERE id = $session_id");
2648
2649
    if (Database::num_rows($result) <= 0) {
2650
        return SESSION_INVISIBLE;
2651
    }
2652
2653
    $row = Database::fetch_array($result, 'ASSOC');
2654
    $visibility = $row['visibility'];
2655
2656
    // I don't care the session visibility.
2657
    if (empty($row['access_start_date']) && empty($row['access_end_date'])) {
2658
        // Session duration per student.
2659
        if (isset($row['duration']) && !empty($row['duration'])) {
2660
            $duration = $row['duration'] * 24 * 60 * 60;
2661
            $courseAccess = CourseManager::getFirstCourseAccessPerSessionAndUser($session_id, api_get_user_id());
2662
2663
            // If there is a session duration but there is no previous
2664
            // access by the user, then the session is still available
2665
            if (0 == count($courseAccess)) {
2666
                return SESSION_AVAILABLE;
2667
            }
2668
2669
            $currentTime = time();
2670
            $firstAccess = isset($courseAccess['login_course_date'])
2671
                ? api_strtotime($courseAccess['login_course_date'], 'UTC')
2672
                : 0;
2673
            $userDurationData = SessionManager::getUserSession(
2674
                api_get_user_id(),
2675
                $session_id
2676
            );
2677
            $userDuration = isset($userDurationData['duration'])
2678
                ? (intval($userDurationData['duration']) * 24 * 60 * 60)
2679
                : 0;
2680
2681
            $totalDuration = $firstAccess + $duration + $userDuration;
2682
2683
            return $totalDuration > $currentTime ? SESSION_AVAILABLE : SESSION_VISIBLE_READ_ONLY;
2684
        }
2685
2686
        return SESSION_AVAILABLE;
2687
    }
2688
2689
    // If start date was set.
2690
    if (!empty($row['access_start_date'])) {
2691
        $visibility = $now > api_strtotime($row['access_start_date'], 'UTC') ? SESSION_AVAILABLE : SESSION_INVISIBLE;
2692
    }
2693
2694
    // If the end date was set.
2695
    if (!empty($row['access_end_date'])) {
2696
        // Only if date_start said that it was ok
2697
        if (SESSION_AVAILABLE === $visibility) {
2698
            $visibility = $now < api_strtotime($row['access_end_date'], 'UTC')
2699
                ? SESSION_AVAILABLE // Date still available
2700
                : $row['visibility']; // Session ends
2701
        }
2702
    }
2703
2704
    // If I'm a coach the visibility can change in my favor depending in the coach dates.
2705
    $isCoach = api_is_coach($session_id, $courseId);
2706
2707
    if ($isCoach) {
2708
        // Test start date.
2709
        if (!empty($row['coach_access_start_date'])) {
2710
            $start = api_strtotime($row['coach_access_start_date'], 'UTC');
2711
            $visibility = $start < $now ? SESSION_AVAILABLE : SESSION_INVISIBLE;
2712
        }
2713
2714
        // Test end date.
2715
        if (!empty($row['coach_access_end_date'])) {
2716
            if (SESSION_AVAILABLE === $visibility) {
2717
                $endDateCoach = api_strtotime($row['coach_access_end_date'], 'UTC');
2718
                $visibility = $endDateCoach >= $now ? SESSION_AVAILABLE : $row['visibility'];
2719
            }
2720
        }
2721
    }
2722
2723
    return $visibility;
2724
}
2725
2726
/**
2727
 * This function returns a (star) session icon if the session is not null and
2728
 * the user is not a student.
2729
 *
2730
 * @param int $sessionId
2731
 * @param int $statusId  User status id - if 5 (student), will return empty
2732
 *
2733
 * @return string Session icon
2734
 */
2735
function api_get_session_image($sessionId, $statusId)
2736
{
2737
    $sessionId = (int) $sessionId;
2738
    $image = '';
2739
    if (STUDENT != $statusId) {
2740
        // Check whether is not a student
2741
        if ($sessionId > 0) {
2742
            $image = '&nbsp;&nbsp;'.Display::return_icon(
2743
                'star.png',
2744
                get_lang('Session-specific resource'),
2745
                ['align' => 'absmiddle'],
2746
                ICON_SIZE_SMALL
2747
            );
2748
        }
2749
    }
2750
2751
    return $image;
2752
}
2753
2754
/**
2755
 * This function add an additional condition according to the session of the course.
2756
 *
2757
 * @param int    $session_id        session id
2758
 * @param bool   $and               optional, true if more than one condition false if the only condition in the query
2759
 * @param bool   $with_base_content optional, true to accept content with session=0 as well,
2760
 *                                  false for strict session condition
2761
 * @param string $session_field
2762
 *
2763
 * @return string condition of the session
2764
 */
2765
function api_get_session_condition(
2766
    $session_id,
2767
    $and = true,
2768
    $with_base_content = false,
2769
    $session_field = 'session_id'
2770
) {
2771
    $session_id = (int) $session_id;
2772
2773
    if (empty($session_field)) {
2774
        $session_field = 'session_id';
2775
    }
2776
    // Condition to show resources by session
2777
    $condition_add = $and ? ' AND ' : ' WHERE ';
2778
2779
    if ($with_base_content) {
2780
        $condition_session = $condition_add." ( $session_field = $session_id OR $session_field = 0 OR $session_field IS NULL) ";
2781
    } else {
2782
        if (empty($session_id)) {
2783
            $condition_session = $condition_add." ($session_field = $session_id OR $session_field IS NULL)";
2784
        } else {
2785
            $condition_session = $condition_add." $session_field = $session_id ";
2786
        }
2787
    }
2788
2789
    return $condition_session;
2790
}
2791
2792
/**
2793
 * Returns the value of a setting from the web-adjustable admin config settings.
2794
 *
2795
 * WARNING true/false are stored as string, so when comparing you need to check e.g.
2796
 * if (api_get_setting('show_navigation_menu') == 'true') //CORRECT
2797
 * instead of
2798
 * if (api_get_setting('show_navigation_menu') == true) //INCORRECT
2799
 *
2800
 * @param string $variable The variable name
2801
 *
2802
 * @return string
2803
 */
2804
function api_get_setting($variable)
2805
{
2806
    $settingsManager = Container::getSettingsManager();
2807
    if (empty($settingsManager)) {
2808
        return '';
2809
    }
2810
    $variable = trim($variable);
2811
2812
    switch ($variable) {
2813
        /*case 'header_extra_content':
2814
            $filename = api_get_path(SYS_PATH).api_get_home_path().'header_extra_content.txt';
2815
            if (file_exists($filename)) {
2816
                $value = file_get_contents($filename);
2817
2818
                return $value;
2819
            } else {
2820
                return '';
2821
            }
2822
            break;
2823
        case 'footer_extra_content':
2824
            $filename = api_get_path(SYS_PATH).api_get_home_path().'footer_extra_content.txt';
2825
            if (file_exists($filename)) {
2826
                $value = file_get_contents($filename);
2827
2828
                return $value;
2829
            } else {
2830
                return '';
2831
            }
2832
            break;*/
2833
        case 'server_type':
2834
            $test = ['dev', 'test'];
2835
            $environment = Container::getEnvironment();
2836
            if (in_array($environment, $test)) {
2837
                return 'test';
2838
            }
2839
2840
            return 'prod';
2841
        case 'stylesheets':
2842
            $variable = 'platform.theme';
2843
        // deprecated settings
2844
        // no break
2845
        case 'openid_authentication':
2846
        case 'service_ppt2lp':
2847
        case 'formLogin_hide_unhide_label':
2848
            return false;
2849
            break;
0 ignored issues
show
Unused Code introduced by
break is not strictly necessary here and could be removed.

The break statement is not necessary if it is preceded for example by a return statement:

switch ($x) {
    case 1:
        return 'foo';
        break; // This break is not necessary and can be left off.
}

If you would like to keep this construct to be consistent with other case statements, you can safely mark this issue as a false-positive.

Loading history...
2850
        case 'tool_visible_by_default_at_creation':
2851
            $values = $settingsManager->getSetting($variable);
2852
            $newResult = [];
2853
            foreach ($values as $parameter) {
2854
                $newResult[$parameter] = 'true';
2855
            }
2856
2857
            return $newResult;
2858
            break;
2859
        default:
2860
            return $settingsManager->getSetting($variable);
2861
            break;
2862
    }
2863
}
2864
2865
/**
2866
 * @param string $variable
2867
 * @param string $option
2868
 *
2869
 * @return bool
2870
 */
2871
function api_get_setting_in_list($variable, $option)
2872
{
2873
    $value = api_get_setting($variable);
2874
2875
    return in_array($option, $value);
2876
}
2877
2878
/**
2879
 * @param string $plugin
2880
 * @param string $variable
2881
 *
2882
 * @return string
2883
 */
2884
function api_get_plugin_setting($plugin, $variable)
2885
{
2886
    $variableName = $plugin.'_'.$variable;
2887
    //$result = api_get_setting($variableName);
2888
    $params = [
2889
        'category = ? AND subkey = ? AND variable = ?' => [
2890
            'Plugins',
2891
            $plugin,
2892
            $variableName,
2893
        ],
2894
    ];
2895
    $table = Database::get_main_table(TABLE_MAIN_SETTINGS_CURRENT);
2896
    $result = Database::select(
2897
        'selected_value',
2898
        $table,
2899
        ['where' => $params],
2900
        'one'
2901
    );
2902
    if ($result) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $result of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
2903
        $value = $result['selected_value'];
2904
        $serializedValue = @unserialize($result['selected_value'], []);
2905
        if (false !== $serializedValue) {
2906
            $value = $serializedValue;
2907
        }
2908
2909
        return $value;
2910
    }
2911
2912
    return null;
2913
    /// Old code
2914
2915
    $variableName = $plugin.'_'.$variable;
0 ignored issues
show
Unused Code introduced by
$variableName = $plugin . '_' . $variable is not reachable.

This check looks for unreachable code. It uses sophisticated control flow analysis techniques to find statements which will never be executed.

Unreachable code is most often the result of return, die or exit statements that have been added for debug purposes.

function fx() {
    try {
        doSomething();
        return true;
    }
    catch (\Exception $e) {
        return false;
    }

    return false;
}

In the above example, the last return false will never be executed, because a return statement has already been met in every possible execution path.

Loading history...
2916
    $result = api_get_setting($variableName);
2917
2918
    if (isset($result[$plugin])) {
2919
        $value = $result[$plugin];
2920
2921
        $unserialized = UnserializeApi::unserialize('not_allowed_classes', $value, true);
2922
2923
        if (false !== $unserialized) {
2924
            $value = $unserialized;
2925
        }
2926
2927
        return $value;
2928
    }
2929
2930
    return null;
2931
}
2932
2933
/**
2934
 * Returns the value of a setting from the web-adjustable admin config settings.
2935
 */
2936
function api_get_settings_params($params)
2937
{
2938
    $table = Database::get_main_table(TABLE_MAIN_SETTINGS_CURRENT);
2939
    $result = Database::select('*', $table, ['where' => $params]);
2940
2941
    return $result;
2942
}
2943
2944
/**
2945
 * @param array $params example: [id = ? => '1']
2946
 *
2947
 * @return array
2948
 */
2949
function api_get_settings_params_simple($params)
2950
{
2951
    $table = Database::get_main_table(TABLE_MAIN_SETTINGS_CURRENT);
2952
    $result = Database::select('*', $table, ['where' => $params], 'one');
2953
2954
    return $result;
2955
}
2956
2957
/**
2958
 * Returns the value of a setting from the web-adjustable admin config settings.
2959
 */
2960
function api_delete_settings_params($params)
2961
{
2962
    $table = Database::get_main_table(TABLE_MAIN_SETTINGS_CURRENT);
2963
    $result = Database::delete($table, $params);
2964
2965
    return $result;
2966
}
2967
2968
/**
2969
 * Returns an escaped version of $_SERVER['PHP_SELF'] to avoid XSS injection.
2970
 *
2971
 * @return string Escaped version of $_SERVER['PHP_SELF']
2972
 */
2973
function api_get_self()
2974
{
2975
    return htmlentities($_SERVER['PHP_SELF']);
2976
}
2977
2978
/* USER PERMISSIONS */
2979
2980
/**
2981
 * Checks whether current user is a platform administrator.
2982
 *
2983
 * @param bool $allowSessionAdmins Whether session admins should be considered admins or not
2984
 * @param bool $allowDrh           Whether HR directors should be considered admins or not
2985
 *
2986
 * @return bool true if the user has platform admin rights,
2987
 *              false otherwise
2988
 *
2989
 * @see usermanager::is_admin(user_id) for a user-id specific function
2990
 */
2991
function api_is_platform_admin($allowSessionAdmins = false, $allowDrh = false)
2992
{
2993
    $currentUser = api_get_current_user();
2994
2995
    if (null === $currentUser) {
2996
        return false;
2997
    }
2998
2999
    $isAdmin = Session::read('is_platformAdmin');
3000
    if ($isAdmin) {
3001
        return true;
3002
    }
3003
    $user = api_get_user_info();
3004
3005
    return
3006
        isset($user['status']) &&
3007
        (
3008
            ($allowSessionAdmins && SESSIONADMIN == $user['status']) ||
3009
            ($allowDrh && DRH == $user['status'])
3010
        );
3011
}
3012
3013
/**
3014
 * Checks whether the user given as user id is in the admin table.
3015
 *
3016
 * @param int $user_id If none provided, will use current user
3017
 * @param int $url     URL ID. If provided, also check if the user is active on given URL
3018
 *
3019
 * @return bool True if the user is admin, false otherwise
3020
 */
3021
function api_is_platform_admin_by_id($user_id = null, $url = null)
3022
{
3023
    $user_id = (int) $user_id;
3024
    if (empty($user_id)) {
3025
        $user_id = api_get_user_id();
3026
    }
3027
    $admin_table = Database::get_main_table(TABLE_MAIN_ADMIN);
3028
    $sql = "SELECT * FROM $admin_table WHERE user_id = $user_id";
3029
    $res = Database::query($sql);
3030
    $is_admin = 1 === Database::num_rows($res);
3031
    if (!$is_admin || !isset($url)) {
3032
        return $is_admin;
3033
    }
3034
    // We get here only if $url is set
3035
    $url = (int) $url;
3036
    $url_user_table = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_USER);
3037
    $sql = "SELECT * FROM $url_user_table
3038
            WHERE access_url_id = $url AND user_id = $user_id";
3039
    $res = Database::query($sql);
3040
    $result = 1 === Database::num_rows($res);
3041
3042
    return $result;
3043
}
3044
3045
/**
3046
 * Returns the user's numeric status ID from the users table.
3047
 *
3048
 * @param int $user_id If none provided, will use current user
3049
 *
3050
 * @return int User's status (1 for teacher, 5 for student, etc)
3051
 */
3052
function api_get_user_status($user_id = null)
3053
{
3054
    $user_id = (int) $user_id;
3055
    if (empty($user_id)) {
3056
        $user_id = api_get_user_id();
3057
    }
3058
    $table = Database::get_main_table(TABLE_MAIN_USER);
3059
    $sql = "SELECT status FROM $table WHERE id = $user_id ";
3060
    $result = Database::query($sql);
3061
    $status = null;
3062
    if (Database::num_rows($result)) {
3063
        $row = Database::fetch_array($result);
3064
        $status = $row['status'];
3065
    }
3066
3067
    return $status;
3068
}
3069
3070
/**
3071
 * Checks whether current user is allowed to create courses.
3072
 *
3073
 * @return bool true if the user has course creation rights,
3074
 *              false otherwise
3075
 */
3076
function api_is_allowed_to_create_course()
3077
{
3078
    if (api_is_platform_admin()) {
3079
        return true;
3080
    }
3081
3082
    // Teachers can only create courses
3083
    if (api_is_teacher()) {
3084
        if ('true' === api_get_setting('allow_users_to_create_courses')) {
3085
            return true;
3086
        } else {
3087
            return false;
3088
        }
3089
    }
3090
3091
    return Session::read('is_allowedCreateCourse');
3092
}
3093
3094
/**
3095
 * Checks whether the current user is a course administrator.
3096
 *
3097
 * @return bool True if current user is a course administrator
3098
 */
3099
function api_is_course_admin()
3100
{
3101
    if (api_is_platform_admin()) {
3102
        return true;
3103
    }
3104
3105
    $user = api_get_current_user();
3106
    if ($user) {
3107
        if (
3108
            $user->hasRole('ROLE_CURRENT_SESSION_COURSE_TEACHER') ||
3109
            $user->hasRole('ROLE_CURRENT_COURSE_TEACHER')
3110
        ) {
3111
            return true;
3112
        }
3113
    }
3114
3115
    return false;
3116
    //return Session::read('is_courseAdmin');
3117
}
3118
3119
/**
3120
 * Checks whether the current user is a course coach
3121
 * Based on the presence of user in session.id_coach (session general coach).
3122
 *
3123
 * @return bool True if current user is a course coach
3124
 */
3125
function api_is_session_general_coach()
3126
{
3127
    return Session::read('is_session_general_coach');
3128
}
3129
3130
/**
3131
 * Checks whether the current user is a course tutor
3132
 * Based on the presence of user in session_rel_course_rel_user.user_id with status = 2.
3133
 *
3134
 * @return bool True if current user is a course tutor
3135
 */
3136
function api_is_course_tutor()
3137
{
3138
    return Session::read('is_courseTutor');
3139
}
3140
3141
/**
3142
 * @param int $user_id
3143
 * @param int $courseId
3144
 * @param int $session_id
3145
 *
3146
 * @return bool
3147
 */
3148
function api_is_course_session_coach($user_id, $courseId, $session_id)
3149
{
3150
    $session_table = Database::get_main_table(TABLE_MAIN_SESSION);
3151
    $session_rel_course_rel_user_table = Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER);
3152
3153
    $user_id = (int) $user_id;
3154
    $session_id = (int) $session_id;
3155
    $courseId = (int) $courseId;
3156
3157
    $sql = "SELECT DISTINCT session.id
3158
            FROM $session_table
3159
            INNER JOIN $session_rel_course_rel_user_table session_rc_ru
3160
            ON session.id = session_rc_ru.session_id
3161
            WHERE
3162
                session_rc_ru.user_id = '".$user_id."'  AND
3163
                session_rc_ru.c_id = '$courseId' AND
3164
                session_rc_ru.status = 2 AND
3165
                session_rc_ru.session_id = '$session_id'";
3166
    $result = Database::query($sql);
3167
3168
    return Database::num_rows($result) > 0;
3169
}
3170
3171
/**
3172
 * Checks whether the current user is a course or session coach.
3173
 *
3174
 * @param int $session_id
3175
 * @param int $courseId
3176
 * @param bool  Check whether we are in student view and, if we are, return false
3177
 *
3178
 * @return bool True if current user is a course or session coach
3179
 */
3180
function api_is_coach($session_id = 0, $courseId = null, $check_student_view = true)
3181
{
3182
    $userId = api_get_user_id();
3183
3184
    if (!empty($session_id)) {
3185
        $session_id = (int) $session_id;
3186
    } else {
3187
        $session_id = api_get_session_id();
3188
    }
3189
3190
    // The student preview was on
3191
    if ($check_student_view && api_is_student_view_active()) {
3192
        return false;
3193
    }
3194
3195
    if (!empty($courseId)) {
3196
        $courseId = (int) $courseId;
3197
    } else {
3198
        $courseId = api_get_course_int_id();
3199
    }
3200
3201
    $session_table = Database::get_main_table(TABLE_MAIN_SESSION);
3202
    $session_rel_course_rel_user_table = Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER);
3203
    $sessionIsCoach = [];
3204
3205
    if (!empty($courseId)) {
3206
        $sql = "SELECT DISTINCT s.id, name, access_start_date, access_end_date
3207
                FROM $session_table s
3208
                INNER JOIN $session_rel_course_rel_user_table session_rc_ru
3209
                ON session_rc_ru.session_id = s.id AND session_rc_ru.user_id = '".$userId."'
3210
                WHERE
3211
                    session_rc_ru.c_id = '$courseId' AND
3212
                    session_rc_ru.status = 2 AND
3213
                    session_rc_ru.session_id = '$session_id'";
3214
        $result = Database::query($sql);
3215
        $sessionIsCoach = Database::store_result($result);
3216
    }
3217
3218
    if (!empty($session_id)) {
3219
        $sql = "SELECT DISTINCT id, name, access_start_date, access_end_date
3220
                FROM $session_table
3221
                WHERE session.id_coach = $userId AND id = $session_id
3222
                ORDER BY access_start_date, access_end_date, name";
3223
        $result = Database::query($sql);
3224
        if (!empty($sessionIsCoach)) {
3225
            $sessionIsCoach = array_merge(
3226
                $sessionIsCoach,
3227
                Database::store_result($result)
3228
            );
3229
        } else {
3230
            $sessionIsCoach = Database::store_result($result);
3231
        }
3232
    }
3233
3234
    return count($sessionIsCoach) > 0;
3235
}
3236
3237
/**
3238
 * Checks whether the current user is a session administrator.
3239
 *
3240
 * @return bool True if current user is a course administrator
3241
 */
3242
function api_is_session_admin()
3243
{
3244
    $user = api_get_user_info();
3245
3246
    return isset($user['status']) && SESSIONADMIN == $user['status'];
3247
}
3248
3249
/**
3250
 * Checks whether the current user is a human resources manager.
3251
 *
3252
 * @return bool True if current user is a human resources manager
3253
 */
3254
function api_is_drh()
3255
{
3256
    $user = api_get_user_info();
3257
3258
    return isset($user['status']) && DRH == $user['status'];
3259
}
3260
3261
/**
3262
 * Checks whether the current user is a student.
3263
 *
3264
 * @return bool True if current user is a human resources manager
3265
 */
3266
function api_is_student()
3267
{
3268
    $user = api_get_user_info();
3269
3270
    return isset($user['status']) && STUDENT == $user['status'];
3271
}
3272
3273
/**
3274
 * Checks whether the current user has the status 'teacher'.
3275
 *
3276
 * @return bool True if current user is a human resources manager
3277
 */
3278
function api_is_teacher()
3279
{
3280
    $user = api_get_user_info();
3281
3282
    return isset($user['status']) && COURSEMANAGER == $user['status'];
3283
}
3284
3285
/**
3286
 * Checks whether the current user is a invited user.
3287
 *
3288
 * @return bool
3289
 */
3290
function api_is_invitee()
3291
{
3292
    $user = api_get_user_info();
3293
3294
    return isset($user['status']) && INVITEE == $user['status'];
3295
}
3296
3297
/**
3298
 * This function checks whether a session is assigned into a category.
3299
 *
3300
 * @param int       - session id
0 ignored issues
show
Documentation Bug introduced by
The doc comment - at position 0 could not be parsed: Unknown type name '-' at position 0 in -.
Loading history...
3301
 * @param string    - category name
3302
 *
3303
 * @return bool - true if is found, otherwise false
3304
 */
3305
function api_is_session_in_category($session_id, $category_name)
3306
{
3307
    $session_id = (int) $session_id;
3308
    $category_name = Database::escape_string($category_name);
3309
    $tbl_session = Database::get_main_table(TABLE_MAIN_SESSION);
3310
    $tbl_session_category = Database::get_main_table(TABLE_MAIN_SESSION_CATEGORY);
3311
3312
    $sql = "SELECT 1
3313
            FROM $tbl_session
3314
            WHERE $session_id IN (
3315
                SELECT s.id FROM $tbl_session s, $tbl_session_category sc
3316
                WHERE
3317
                  s.session_category_id = sc.id AND
3318
                  sc.name LIKE '%$category_name'
3319
            )";
3320
    $rs = Database::query($sql);
3321
3322
    if (Database::num_rows($rs) > 0) {
3323
        return true;
3324
    } else {
3325
        return false;
3326
    }
3327
}
3328
3329
/**
3330
 * Displays the title of a tool.
3331
 * Normal use: parameter is a string:
3332
 * api_display_tool_title("My Tool").
3333
 *
3334
 * Optionally, there can be a subtitle below
3335
 * the normal title, and / or a supra title above the normal title.
3336
 *
3337
 * e.g. supra title:
3338
 * group
3339
 * GROUP PROPERTIES
3340
 *
3341
 * e.g. subtitle:
3342
 * AGENDA
3343
 * calender & events tool
3344
 *
3345
 * @author Hugues Peeters <[email protected]>
3346
 *
3347
 * @param mixed $title_element - it could either be a string or an array
3348
 *                             containing 'supraTitle', 'mainTitle',
3349
 *                             'subTitle'
3350
 */
3351
function api_display_tool_title($title_element)
3352
{
3353
    if (is_string($title_element)) {
3354
        $tit = $title_element;
3355
        unset($title_element);
3356
        $title_element = [];
3357
        $title_element['mainTitle'] = $tit;
3358
    }
3359
    echo '<h3>';
3360
    if (!empty($title_element['supraTitle'])) {
3361
        echo '<small>'.$title_element['supraTitle'].'</small><br />';
3362
    }
3363
    if (!empty($title_element['mainTitle'])) {
3364
        echo $title_element['mainTitle'];
3365
    }
3366
    if (!empty($title_element['subTitle'])) {
3367
        echo '<br /><small>'.$title_element['subTitle'].'</small>';
3368
    }
3369
    echo '</h3>';
3370
}
3371
3372
/**
3373
 * Displays options for switching between student view and course manager view.
3374
 *
3375
 * Changes in version 1.2 (Patrick Cool)
3376
 * Student view switch now behaves as a real switch. It maintains its current state until the state
3377
 * is changed explicitly
3378
 *
3379
 * Changes in version 1.1 (Patrick Cool)
3380
 * student view now works correctly in subfolders of the document tool
3381
 * student view works correctly in the new links tool
3382
 *
3383
 * Example code for using this in your tools:
3384
 * //if ($is_courseAdmin && api_get_setting('student_view_enabled') == 'true') {
3385
 * //   display_tool_view_option($isStudentView);
3386
 * //}
3387
 * //and in later sections, use api_is_allowed_to_edit()
3388
 *
3389
 * @author Roan Embrechts
3390
 * @author Patrick Cool
3391
 * @author Julio Montoya, changes added in Chamilo
3392
 *
3393
 * @version 1.2
3394
 *
3395
 * @todo rewrite code so it is easier to understand
3396
 */
3397
function api_display_tool_view_option()
3398
{
3399
    if ('true' != api_get_setting('student_view_enabled')) {
3400
        return '';
3401
    }
3402
3403
    $sourceurl = '';
3404
    $is_framed = false;
3405
    // Exceptions apply for all multi-frames pages
3406
    if (false !== strpos($_SERVER['REQUEST_URI'], 'chat/chat_banner.php')) {
3407
        // The chat is a multiframe bit that doesn't work too well with the student_view, so do not show the link
3408
        return '';
3409
    }
3410
3411
    // Uncomment to remove student view link from document view page
3412
    if (false !== strpos($_SERVER['REQUEST_URI'], 'lp/lp_header.php')) {
3413
        if (empty($_GET['lp_id'])) {
3414
            return '';
3415
        }
3416
        $sourceurl = substr($_SERVER['REQUEST_URI'], 0, strpos($_SERVER['REQUEST_URI'], '?'));
3417
        $sourceurl = str_replace(
3418
            'lp/lp_header.php',
3419
            'lp/lp_controller.php?'.api_get_cidreq().'&action=view&lp_id='.intval($_GET['lp_id']).'&isStudentView='.('studentview' == $_SESSION['studentview'] ? 'false' : 'true'),
3420
            $sourceurl
3421
        );
3422
        //showinframes doesn't handle student view anyway...
3423
        //return '';
3424
        $is_framed = true;
3425
    }
3426
3427
    // Check whether the $_SERVER['REQUEST_URI'] contains already url parameters (thus a questionmark)
3428
    if (!$is_framed) {
3429
        if (false === strpos($_SERVER['REQUEST_URI'], '?')) {
3430
            $sourceurl = api_get_self().'?'.api_get_cidreq();
3431
        } else {
3432
            $sourceurl = $_SERVER['REQUEST_URI'];
3433
        }
3434
    }
3435
3436
    $output_string = '';
3437
    if (!empty($_SESSION['studentview'])) {
3438
        if ('studentview' == $_SESSION['studentview']) {
3439
            // We have to remove the isStudentView=true from the $sourceurl
3440
            $sourceurl = str_replace('&isStudentView=true', '', $sourceurl);
3441
            $sourceurl = str_replace('&isStudentView=false', '', $sourceurl);
3442
            $output_string .= '<a class="btn btn-primary btn-sm" href="'.$sourceurl.'&isStudentView=false" target="_self">'.
3443
                Display::returnFontAwesomeIcon('eye').' '.get_lang('Switch to teacher view').'</a>';
3444
        } elseif ('teacherview' == $_SESSION['studentview']) {
3445
            // Switching to teacherview
3446
            $sourceurl = str_replace('&isStudentView=true', '', $sourceurl);
3447
            $sourceurl = str_replace('&isStudentView=false', '', $sourceurl);
3448
            $output_string .= '<a class="btn btn-default btn-sm" href="'.$sourceurl.'&isStudentView=true" target="_self">'.
3449
                Display::returnFontAwesomeIcon('eye').' '.get_lang('Switch to student view').'</a>';
3450
        }
3451
    } else {
3452
        $output_string .= '<a class="btn btn-default btn-sm" href="'.$sourceurl.'&isStudentView=true" target="_self">'.
3453
            Display::returnFontAwesomeIcon('eye').' '.get_lang('Switch to student view').'</a>';
3454
    }
3455
    $output_string = Security::remove_XSS($output_string);
3456
    $html = Display::tag('div', $output_string, ['class' => 'view-options']);
3457
3458
    return $html;
3459
}
3460
3461
// TODO: This is for the permission section.
3462
/**
3463
 * Function that removes the need to directly use is_courseAdmin global in
3464
 * tool scripts. It returns true or false depending on the user's rights in
3465
 * this particular course.
3466
 * Optionally checking for tutor and coach roles here allows us to use the
3467
 * student_view feature altogether with these roles as well.
3468
 *
3469
 * @param bool  Whether to check if the user has the tutor role
3470
 * @param bool  Whether to check if the user has the coach role
3471
 * @param bool  Whether to check if the user has the session coach role
3472
 * @param bool  check the student view or not
3473
 *
3474
 * @author Roan Embrechts
3475
 * @author Patrick Cool
3476
 * @author Julio Montoya
3477
 *
3478
 * @version 1.1, February 2004
3479
 *
3480
 * @return bool true: the user has the rights to edit, false: he does not
3481
 */
3482
function api_is_allowed_to_edit(
3483
    $tutor = false,
3484
    $coach = false,
3485
    $session_coach = false,
3486
    $check_student_view = true
3487
) {
3488
    $allowSessionAdminEdit = true === api_get_setting('session.session_admins_edit_courses_content');
3489
    // Admins can edit anything.
3490
    if (api_is_platform_admin($allowSessionAdminEdit)) {
3491
        //The student preview was on
3492
        if ($check_student_view && api_is_student_view_active()) {
3493
            return false;
3494
        }
3495
3496
        return true;
3497
    }
3498
3499
    $sessionId = api_get_session_id();
3500
3501
    if ($sessionId && api_get_configuration_value('session_courses_read_only_mode')) {
3502
        $efv = new ExtraFieldValue('course');
3503
        $lockExrafieldField = $efv->get_values_by_handler_and_field_variable(
3504
            api_get_course_int_id(),
3505
            'session_courses_read_only_mode'
3506
        );
3507
3508
        if (!empty($lockExrafieldField['value'])) {
3509
            return false;
3510
        }
3511
    }
3512
3513
    $is_allowed_coach_to_edit = api_is_coach(null, null, $check_student_view);
3514
    $session_visibility = api_get_session_visibility($sessionId);
3515
    $is_courseAdmin = api_is_course_admin();
3516
3517
    if (!$is_courseAdmin && $tutor) {
3518
        // If we also want to check if the user is a tutor...
3519
        $is_courseAdmin = $is_courseAdmin || api_is_course_tutor();
3520
    }
3521
3522
    if (!$is_courseAdmin && $coach) {
3523
        // If we also want to check if the user is a coach...';
3524
        // Check if session visibility is read only for coaches.
3525
        if (SESSION_VISIBLE_READ_ONLY == $session_visibility) {
3526
            $is_allowed_coach_to_edit = false;
3527
        }
3528
3529
        if ('true' === api_get_setting('allow_coach_to_edit_course_session')) {
3530
            // Check if coach is allowed to edit a course.
3531
            $is_courseAdmin = $is_courseAdmin || $is_allowed_coach_to_edit;
3532
        }
3533
    }
3534
3535
    if (!$is_courseAdmin && $session_coach) {
3536
        $is_courseAdmin = $is_courseAdmin || $is_allowed_coach_to_edit;
3537
    }
3538
3539
    // Check if the student_view is enabled, and if so, if it is activated.
3540
    if ('true' === api_get_setting('student_view_enabled')) {
3541
        $studentView = api_is_student_view_active();
3542
        if (!empty($sessionId)) {
3543
            // Check if session visibility is read only for coaches.
3544
            if (SESSION_VISIBLE_READ_ONLY == $session_visibility) {
3545
                $is_allowed_coach_to_edit = false;
3546
            }
3547
3548
            $is_allowed = false;
3549
            if ('true' === api_get_setting('allow_coach_to_edit_course_session')) {
3550
                // Check if coach is allowed to edit a course.
3551
                $is_allowed = $is_allowed_coach_to_edit;
3552
            }
3553
            if ($check_student_view) {
3554
                $is_allowed = $is_allowed && false === $studentView;
3555
            }
3556
        } else {
3557
            $is_allowed = $is_courseAdmin;
3558
            if ($check_student_view) {
3559
                $is_allowed = $is_courseAdmin && false === $studentView;
3560
            }
3561
        }
3562
3563
        return $is_allowed;
3564
    } else {
3565
        return $is_courseAdmin;
3566
    }
3567
}
3568
3569
/**
3570
 * Returns true if user is a course coach of at least one course in session.
3571
 *
3572
 * @param int $sessionId
3573
 *
3574
 * @return bool
3575
 */
3576
function api_is_coach_of_course_in_session($sessionId)
3577
{
3578
    if (api_is_platform_admin()) {
3579
        return true;
3580
    }
3581
3582
    $userId = api_get_user_id();
3583
    $courseList = UserManager::get_courses_list_by_session(
3584
        $userId,
3585
        $sessionId
3586
    );
3587
3588
    // Session visibility.
3589
    $visibility = api_get_session_visibility(
3590
        $sessionId,
3591
        null,
3592
        false
3593
    );
3594
3595
    if (SESSION_VISIBLE != $visibility && !empty($courseList)) {
3596
        // Course Coach session visibility.
3597
        $blockedCourseCount = 0;
3598
        $closedVisibilityList = [
3599
            COURSE_VISIBILITY_CLOSED,
3600
            COURSE_VISIBILITY_HIDDEN,
3601
        ];
3602
3603
        foreach ($courseList as $course) {
3604
            // Checking session visibility
3605
            $sessionCourseVisibility = api_get_session_visibility(
3606
                $sessionId,
3607
                $course['real_id']
3608
            );
3609
3610
            $courseIsVisible = !in_array(
3611
                $course['visibility'],
3612
                $closedVisibilityList
3613
            );
3614
            if (false === $courseIsVisible || SESSION_INVISIBLE == $sessionCourseVisibility) {
3615
                $blockedCourseCount++;
3616
            }
3617
        }
3618
3619
        // If all courses are blocked then no show in the list.
3620
        if ($blockedCourseCount === count($courseList)) {
3621
            $visibility = SESSION_INVISIBLE;
3622
        } else {
3623
            $visibility = SESSION_VISIBLE;
3624
        }
3625
    }
3626
3627
    switch ($visibility) {
3628
        case SESSION_VISIBLE_READ_ONLY:
3629
        case SESSION_VISIBLE:
3630
        case SESSION_AVAILABLE:
3631
            return true;
3632
            break;
0 ignored issues
show
Unused Code introduced by
break is not strictly necessary here and could be removed.

The break statement is not necessary if it is preceded for example by a return statement:

switch ($x) {
    case 1:
        return 'foo';
        break; // This break is not necessary and can be left off.
}

If you would like to keep this construct to be consistent with other case statements, you can safely mark this issue as a false-positive.

Loading history...
3633
        case SESSION_INVISIBLE:
3634
            return false;
3635
    }
3636
3637
    return false;
3638
}
3639
3640
/**
3641
 * Checks if a student can edit contents in a session depending
3642
 * on the session visibility.
3643
 *
3644
 * @param bool $tutor Whether to check if the user has the tutor role
3645
 * @param bool $coach Whether to check if the user has the coach role
3646
 *
3647
 * @return bool true: the user has the rights to edit, false: he does not
3648
 */
3649
function api_is_allowed_to_session_edit($tutor = false, $coach = false)
3650
{
3651
    if (api_is_allowed_to_edit($tutor, $coach)) {
3652
        // If I'm a teacher, I will return true in order to not affect the normal behaviour of Chamilo tools.
3653
        return true;
3654
    } else {
3655
        $sessionId = api_get_session_id();
3656
3657
        if (0 == $sessionId) {
3658
            // I'm not in a session so i will return true to not affect the normal behaviour of Chamilo tools.
3659
            return true;
3660
        } else {
3661
            // I'm in a session and I'm a student
3662
            // Get the session visibility
3663
            $session_visibility = api_get_session_visibility($sessionId);
3664
            // if 5 the session is still available
3665
            switch ($session_visibility) {
3666
                case SESSION_VISIBLE_READ_ONLY: // 1
3667
                    return false;
3668
                case SESSION_VISIBLE:           // 2
3669
                    return true;
3670
                case SESSION_INVISIBLE:         // 3
3671
                    return false;
3672
                case SESSION_AVAILABLE:         //5
3673
                    return true;
3674
            }
3675
        }
3676
    }
3677
3678
    return false;
3679
}
3680
3681
/**
3682
 * Checks whether the user is allowed in a specific tool for a specific action.
3683
 *
3684
 * @param string $tool   the tool we are checking if the user has a certain permission
3685
 * @param string $action the action we are checking (add, edit, delete, move, visibility)
3686
 *
3687
 * @return bool
3688
 *
3689
 * @author Patrick Cool <[email protected]>, Ghent University
3690
 * @author Julio Montoya
3691
 *
3692
 * @version 1.0
3693
 */
3694
function api_is_allowed($tool, $action, $task_id = 0)
3695
{
3696
    $_user = api_get_user_info();
3697
    $_course = api_get_course_info();
3698
3699
    if (api_is_course_admin()) {
3700
        return true;
3701
    }
3702
3703
    if (is_array($_course) and count($_course) > 0) {
3704
        require_once api_get_path(SYS_CODE_PATH).'permissions/permissions_functions.inc.php';
3705
3706
        // Getting the permissions of this user.
3707
        if (0 == $task_id) {
3708
            $user_permissions = get_permissions('user', $_user['user_id']);
3709
            $_SESSION['total_permissions'][$_course['code']] = $user_permissions;
3710
        }
3711
3712
        // Getting the permissions of the task.
3713
        if (0 != $task_id) {
3714
            $task_permissions = get_permissions('task', $task_id);
3715
            /* !!! */$_SESSION['total_permissions'][$_course['code']] = $task_permissions;
3716
        }
3717
    }
3718
3719
    // If the permissions are limited, we have to map the extended ones to the limited ones.
3720
    if ('limited' == api_get_setting('permissions')) {
3721
        if ('Visibility' == $action) {
3722
            $action = 'Edit';
3723
        }
3724
        if ('Move' == $action) {
3725
            $action = 'Edit';
3726
        }
3727
    }
3728
3729
    // The session that contains all the permissions already exists for this course
3730
    // so there is no need to requery everything.
3731
    //my_print_r($_SESSION['total_permissions'][$_course['code']][$tool]);
3732
    if (is_array($_SESSION['total_permissions'][$_course['code']][$tool])) {
3733
        if (in_array($action, $_SESSION['total_permissions'][$_course['code']][$tool])) {
3734
            return true;
3735
        } else {
3736
            return false;
3737
        }
3738
    }
3739
3740
    return false;
3741
}
3742
3743
/**
3744
 * Tells whether this user is an anonymous user.
3745
 *
3746
 * @param int  $user_id  User ID (optional, will take session ID if not provided)
3747
 * @param bool $db_check Whether to check in the database (true) or simply in
3748
 *                       the session (false) to see if the current user is the anonymous user
3749
 *
3750
 * @return bool true if this user is anonymous, false otherwise
3751
 */
3752
function api_is_anonymous($user_id = null, $db_check = false)
3753
{
3754
    /*if ($db_check) {
3755
        if (!isset($user_id)) {
3756
            $user_id = api_get_user_id();
3757
        }
3758
3759
        $info = api_get_user_info($user_id);
3760
3761
        if (6 == $info['status'] || 0 == $user_id || empty($info)) {
3762
            return true;
3763
        }
3764
    }*/
3765
3766
    return !Container::getAuthorizationChecker()->isGranted('IS_AUTHENTICATED_FULLY');
3767
}
3768
3769
/**
3770
 * Displays message "You are not allowed here..." and exits the entire script.
3771
 *
3772
 * @param bool   $print_headers Whether or not to print headers (default = false -> does not print them)
3773
 * @param string $message
3774
 * @param int    $responseCode
3775
 */
3776
function api_not_allowed(
3777
    $print_headers = false,
3778
    $message = null,
3779
    $responseCode = 0
3780
) {
3781
    throw new Exception('You are not allowed');
3782
}
3783
3784
/**
3785
 * Gets a UNIX timestamp from a database (MySQL) datetime format string.
3786
 *
3787
 * @param $last_post_datetime standard output date in a sql query
3788
 *
3789
 * @return int timestamp
3790
 *
3791
 * @author Toon Van Hoecke <[email protected]>
3792
 *
3793
 * @version October 2003
3794
 * @desc convert sql date to unix timestamp
3795
 */
3796
function convert_sql_date($last_post_datetime)
3797
{
3798
    [$last_post_date, $last_post_time] = explode(' ', $last_post_datetime);
3799
    [$year, $month, $day] = explode('-', $last_post_date);
3800
    [$hour, $min, $sec] = explode(':', $last_post_time);
3801
3802
    return mktime((int) $hour, (int) $min, (int) $sec, (int) $month, (int) $day, (int) $year);
3803
}
3804
3805
/**
3806
 * Displays a combo box so the user can select his/her preferred language.
3807
 *
3808
 * @param string The desired name= value for the select
3809
 * @param bool Whether we use the JQuery Chozen library or not
3810
 * (in some cases, like the indexing language picker, it can alter the presentation)
3811
 *
3812
 * @deprecated
3813
 *
3814
 * @return string
3815
 */
3816
function api_get_languages_combo($name = 'language')
3817
{
3818
    $ret = '';
3819
    $platformLanguage = api_get_setting('platformLanguage');
3820
3821
    // Retrieve a complete list of all the languages.
3822
    $language_list = api_get_languages();
3823
3824
    if (count($language_list) < 2) {
3825
        return $ret;
3826
    }
3827
3828
    // The the current language of the user so that his/her language occurs as selected in the dropdown menu.
3829
    if (isset($_SESSION['user_language_choice'])) {
3830
        $default = $_SESSION['user_language_choice'];
3831
    } else {
3832
        $default = $platformLanguage;
3833
    }
3834
3835
    $ret .= '<select name="'.$name.'" id="language_chosen" class="selectpicker show-tick form-control">';
3836
    foreach ($language_list as $key => $value) {
3837
        if ($key == $default) {
3838
            $selected = ' selected="selected"';
3839
        } else {
3840
            $selected = '';
3841
        }
3842
        $ret .= sprintf('<option value=%s" %s>%s</option>', $key, $selected, $value);
3843
    }
3844
    $ret .= '</select>';
3845
3846
    return $ret;
3847
}
3848
3849
/**
3850
 * Displays a form (drop down menu) so the user can select his/her preferred language.
3851
 * The form works with or without javascript.
3852
 *
3853
 * @param  bool Hide form if only one language available (defaults to false = show the box anyway)
3854
 * @param bool $showAsButton
3855
 *
3856
 * @return string|null Display the box directly
3857
 */
3858
function api_display_language_form($hide_if_no_choice = false, $showAsButton = false)
3859
{
3860
    // Retrieve a complete list of all the languages.
3861
    $language_list = api_get_languages();
3862
    if (count($language_list['name']) <= 1 && $hide_if_no_choice) {
3863
        return; //don't show any form
3864
    }
3865
3866
    // The the current language of the user so that his/her language occurs as selected in the dropdown menu.
3867
    if (isset($_SESSION['user_language_choice'])) {
3868
        $user_selected_language = $_SESSION['user_language_choice'];
3869
    }
3870
    if (empty($user_selected_language)) {
3871
        $user_selected_language = api_get_setting('platformLanguage');
3872
    }
3873
3874
    $currentLanguageId = api_get_language_id($user_selected_language);
3875
    $currentLanguageInfo = api_get_language_info($currentLanguageId);
3876
    $countryCode = languageToCountryIsoCode($currentLanguageInfo['isocode']);
3877
    $url = api_get_self();
3878
    if ($showAsButton) {
3879
        $html = '<div class="btn-group">
3880
              <button type="button" class="btn btn-default dropdown-toggle" data-toggle="dropdown">
3881
                <span class="flag-icon flag-icon-'.$countryCode.'"></span>
3882
                '.$currentLanguageInfo['original_name'].'
3883
                <span class="caret">
3884
                </span>
3885
              </button>';
3886
    } else {
3887
        $html = '
3888
            <a href="'.$url.'" class="dropdown-toggle" data-toggle="dropdown" role="button">
3889
                <span class="flag-icon flag-icon-'.$countryCode.'"></span>
3890
                '.$currentLanguageInfo['original_name'].'
3891
                <span class="caret"></span>
3892
            </a>
3893
            ';
3894
    }
3895
3896
    $html .= '<ul class="dropdown-menu" role="menu">';
3897
    foreach ($language_list['all'] as $key => $data) {
3898
        $urlLink = $url.'?language='.$data['english_name'];
3899
        $html .= '<li><a href="'.$urlLink.'"><span class="flag-icon flag-icon-'.languageToCountryIsoCode($data['isocode']).'"></span> '.$data['original_name'].'</a></li>';
3900
    }
3901
    $html .= '</ul>';
3902
3903
    if ($showAsButton) {
3904
        $html .= '</div>';
3905
    }
3906
3907
    return $html;
3908
}
3909
3910
/**
3911
 * @param string $languageIsoCode
3912
 *
3913
 * @return string
3914
 */
3915
function languageToCountryIsoCode($languageIsoCode)
3916
{
3917
    $allow = api_get_configuration_value('language_flags_by_country');
3918
3919
    // @todo save in DB
3920
    switch ($languageIsoCode) {
3921
        case 'ar':
3922
            $country = 'ae';
3923
            break;
3924
        case 'bs':
3925
            $country = 'ba';
3926
            break;
3927
        case 'ca':
3928
            $country = 'es';
3929
            if ($allow) {
3930
                $country = 'catalan';
3931
            }
3932
            break;
3933
        case 'cs':
3934
            $country = 'cz';
3935
            break;
3936
        case 'da':
3937
            $country = 'dk';
3938
            break;
3939
        case 'el':
3940
            $country = 'ae';
3941
            break;
3942
        case 'en':
3943
            $country = 'gb';
3944
            break;
3945
        case 'eu': // Euskera
3946
            $country = 'es';
3947
            if ($allow) {
3948
                $country = 'basque';
3949
            }
3950
            break;
3951
        case 'gl': // galego
3952
            $country = 'es';
3953
            if ($allow) {
3954
                $country = 'galician';
3955
            }
3956
            break;
3957
        case 'he':
3958
            $country = 'il';
3959
            break;
3960
        case 'ja':
3961
            $country = 'jp';
3962
            break;
3963
        case 'ka':
3964
            $country = 'ge';
3965
            break;
3966
        case 'ko':
3967
            $country = 'kr';
3968
            break;
3969
        case 'ms':
3970
            $country = 'my';
3971
            break;
3972
        case 'pt-BR':
3973
            $country = 'br';
3974
            break;
3975
        case 'qu':
3976
            $country = 'pe';
3977
            break;
3978
        case 'sl':
3979
            $country = 'si';
3980
            break;
3981
        case 'sv':
3982
            $country = 'se';
3983
            break;
3984
        case 'uk': // Ukraine
3985
            $country = 'ua';
3986
            break;
3987
        case 'zh-TW':
3988
        case 'zh':
3989
            $country = 'cn';
3990
            break;
3991
        default:
3992
            $country = $languageIsoCode;
3993
            break;
3994
    }
3995
    $country = strtolower($country);
3996
3997
    return $country;
3998
}
3999
4000
/**
4001
 * Returns a list of all the languages that are made available by the admin.
4002
 *
4003
 * @return array An array with all languages. Structure of the array is
4004
 *               array['name'] = An array with the name of every language
4005
 *               array['folder'] = An array with the corresponding names of the language-folders in the filesystem
4006
 */
4007
function api_get_languages()
4008
{
4009
    $table = Database::get_main_table(TABLE_MAIN_LANGUAGE);
4010
    $sql = "SELECT * FROM $table WHERE available='1'
4011
            ORDER BY original_name ASC";
4012
    $result = Database::query($sql);
4013
    $languages = [];
4014
    while ($row = Database::fetch_array($result, 'ASSOC')) {
4015
        $languages[$row['isocode']] = $row['original_name'];
4016
    }
4017
4018
    return $languages;
4019
}
4020
4021
/**
4022
 * Returns a list of all the languages that are made available by the admin.
4023
 *
4024
 * @return array
4025
 */
4026
function api_get_languages_to_array()
4027
{
4028
    $tbl_language = Database::get_main_table(TABLE_MAIN_LANGUAGE);
4029
    $sql = "SELECT * FROM $tbl_language WHERE available='1' ORDER BY original_name ASC";
4030
    $result = Database::query($sql);
4031
    $languages = [];
4032
    while ($row = Database::fetch_array($result)) {
4033
        $languages[$row['english_name']] = $row['original_name'];
4034
    }
4035
4036
    return $languages;
4037
}
4038
4039
/**
4040
 * Returns the id (the database id) of a language.
4041
 *
4042
 * @param   string  language name (the corresponding name of the language-folder in the filesystem)
4043
 *
4044
 * @return int id of the language
4045
 */
4046
function api_get_language_id($language)
4047
{
4048
    $tbl_language = Database::get_main_table(TABLE_MAIN_LANGUAGE);
4049
    if (empty($language)) {
4050
        return null;
4051
    }
4052
    $language = Database::escape_string($language);
4053
    $sql = "SELECT id FROM $tbl_language
4054
            WHERE english_name = '$language' LIMIT 1";
4055
    $result = Database::query($sql);
4056
    $row = Database::fetch_array($result);
4057
4058
    return $row['id'];
4059
}
4060
4061
/**
4062
 * Get the language information by its id.
4063
 *
4064
 * @param int $languageId
4065
 *
4066
 * @throws Exception
4067
 *
4068
 * @return array
4069
 */
4070
function api_get_language_info($languageId)
4071
{
4072
    if (empty($languageId)) {
4073
        return [];
4074
    }
4075
4076
    $language = Database::getManager()->find(Language::class, $languageId);
4077
4078
    if (!$language) {
4079
        return [];
4080
    }
4081
4082
    return [
4083
        'id' => $language->getId(),
4084
        'original_name' => $language->getOriginalName(),
4085
        'english_name' => $language->getEnglishName(),
4086
        'isocode' => $language->getIsocode(),
4087
        'available' => $language->getAvailable(),
4088
        'parent_id' => $language->getParent() ? $language->getParent()->getId() : null,
4089
    ];
4090
}
4091
4092
/**
4093
 * @param string $code
4094
 *
4095
 * @return Language
4096
 */
4097
function api_get_language_from_iso($code)
4098
{
4099
    $em = Database::getManager();
4100
4101
    return $em->getRepository(Language::class)->findOneBy(['isocode' => $code]);
4102
}
4103
4104
/**
4105
 * Returns the name of the visual (CSS) theme to be applied on the current page.
4106
 * The returned name depends on the platform, course or user -wide settings.
4107
 *
4108
 * @return string The visual theme's name, it is the name of a folder inside web/css/themes
4109
 */
4110
function api_get_visual_theme()
4111
{
4112
    static $visual_theme;
4113
    if (!isset($visual_theme)) {
4114
        // Get style directly from DB
4115
        /*$styleFromDatabase = api_get_settings_params_simple(
4116
            [
4117
                'variable = ? AND access_url = ?' => [
4118
                    'stylesheets',
4119
                    api_get_current_access_url_id(),
4120
                ],
4121
            ]
4122
        );
4123
4124
        if ($styleFromDatabase) {
4125
            $platform_theme = $styleFromDatabase['selected_value'];
4126
        } else {
4127
            $platform_theme = api_get_setting('stylesheets');
4128
        }*/
4129
        $platform_theme = api_get_setting('stylesheets');
4130
4131
        // Platform's theme.
4132
        $visual_theme = $platform_theme;
4133
        if ('true' == api_get_setting('user_selected_theme')) {
4134
            $user_info = api_get_user_info();
4135
            if (isset($user_info['theme'])) {
4136
                $user_theme = $user_info['theme'];
4137
4138
                if (!empty($user_theme)) {
4139
                    $visual_theme = $user_theme;
4140
                    // User's theme.
4141
                }
4142
            }
4143
        }
4144
4145
        $course_id = api_get_course_id();
4146
        if (!empty($course_id)) {
4147
            if ('true' == api_get_setting('allow_course_theme')) {
4148
                $course_theme = api_get_course_setting('course_theme', $course_id);
4149
4150
                if (!empty($course_theme) && -1 != $course_theme) {
4151
                    if (!empty($course_theme)) {
4152
                        // Course's theme.
4153
                        $visual_theme = $course_theme;
4154
                    }
4155
                }
4156
4157
                $allow_lp_theme = api_get_course_setting('allow_learning_path_theme');
4158
                if (1 == $allow_lp_theme) {
4159
                    /*global $lp_theme_css, $lp_theme_config;
4160
                    // These variables come from the file lp_controller.php.
4161
                    if (!$lp_theme_config) {
4162
                        if (!empty($lp_theme_css)) {
4163
                            // LP's theme.
4164
                            $visual_theme = $lp_theme_css;
4165
                        }
4166
                    }*/
4167
                }
4168
            }
4169
        }
4170
4171
        if (empty($visual_theme)) {
4172
            $visual_theme = 'chamilo';
4173
        }
4174
4175
        /*global $lp_theme_log;
4176
        if ($lp_theme_log) {
4177
            $visual_theme = $platform_theme;
4178
        }*/
4179
    }
4180
4181
    return $visual_theme;
4182
}
4183
4184
/**
4185
 * Returns a list of CSS themes currently available in the CSS folder
4186
 * The folder must have a default.css file.
4187
 *
4188
 * @param bool $getOnlyThemeFromVirtualInstance Used by the vchamilo plugin
4189
 *
4190
 * @return array list of themes directories from the css folder
4191
 *               Note: Directory names (names of themes) in the file system should contain ASCII-characters only
4192
 */
4193
function api_get_themes($getOnlyThemeFromVirtualInstance = false)
4194
{
4195
    // This configuration value is set by the vchamilo plugin
4196
    $virtualTheme = api_get_configuration_value('virtual_css_theme_folder');
4197
4198
    $readCssFolder = function ($dir) use ($virtualTheme) {
4199
        $finder = new Finder();
4200
        $themes = $finder->directories()->in($dir)->depth(0)->sortByName();
4201
        $list = [];
4202
        /** @var Symfony\Component\Finder\SplFileInfo $theme */
4203
        foreach ($themes as $theme) {
4204
            $folder = $theme->getFilename();
4205
            // A theme folder is consider if there's a default.css file
4206
            if (!file_exists($theme->getPathname().'/default.css')) {
4207
                continue;
4208
            }
4209
            $name = ucwords(str_replace('_', ' ', $folder));
4210
            if ($folder == $virtualTheme) {
4211
                continue;
4212
            }
4213
            $list[$folder] = $name;
4214
        }
4215
4216
        return $list;
4217
    };
4218
4219
    $dir = api_get_path(SYS_CSS_PATH).'themes/';
4220
    $list = $readCssFolder($dir);
4221
4222
    if (!empty($virtualTheme)) {
4223
        $newList = $readCssFolder($dir.'/'.$virtualTheme);
4224
        if ($getOnlyThemeFromVirtualInstance) {
4225
            return $newList;
4226
        }
4227
        $list = $list + $newList;
4228
        asort($list);
4229
    }
4230
4231
    return $list;
4232
}
4233
4234
/**
4235
 * Find the largest sort value in a given user_course_category
4236
 * This function is used when we are moving a course to a different category
4237
 * and also when a user subscribes to courses (the new course is added at the end of the main category.
4238
 *
4239
 * @param int $courseCategoryId the id of the user_course_category
4240
 * @param int $userId
4241
 *
4242
 * @return int the value of the highest sort of the user_course_category
4243
 */
4244
function api_max_sort_value($courseCategoryId, $userId)
4245
{
4246
    $user = api_get_user_entity($userId);
4247
    $userCourseCategory = Database::getManager()->getRepository(UserCourseCategory::class)->find($courseCategoryId);
4248
4249
    return null === $user ? 0 : $user->getMaxSortValue($userCourseCategory);
4250
}
4251
4252
/**
4253
 * Transforms a number of seconds in hh:mm:ss format.
4254
 *
4255
 * @author Julian Prud'homme
4256
 *
4257
 * @param int    $seconds      number of seconds
4258
 * @param string $space
4259
 * @param bool   $showSeconds
4260
 * @param bool   $roundMinutes
4261
 *
4262
 * @return string the formatted time
4263
 */
4264
function api_time_to_hms($seconds, $space = ':', $showSeconds = true, $roundMinutes = false)
4265
{
4266
    // $seconds = -1 means that we have wrong data in the db.
4267
    if (-1 == $seconds) {
4268
        return
4269
            get_lang('Unknown').
4270
            Display::return_icon(
4271
                'info2.gif',
4272
                get_lang('The datas about this user were registered when the calculation of time spent on the platform wasn\'t possible.'),
4273
                ['align' => 'absmiddle', 'hspace' => '3px']
4274
            );
4275
    }
4276
4277
    // How many hours ?
4278
    $hours = floor($seconds / 3600);
4279
4280
    // How many minutes ?
4281
    $min = floor(($seconds - ($hours * 3600)) / 60);
4282
4283
    if ($roundMinutes) {
4284
        if ($min >= 45) {
4285
            $min = 45;
4286
        }
4287
4288
        if ($min >= 30 && $min <= 44) {
4289
            $min = 30;
4290
        }
4291
4292
        if ($min >= 15 && $min <= 29) {
4293
            $min = 15;
4294
        }
4295
4296
        if ($min >= 0 && $min <= 14) {
4297
            $min = 0;
4298
        }
4299
    }
4300
4301
    // How many seconds
4302
    $sec = floor($seconds - ($hours * 3600) - ($min * 60));
4303
4304
    if ($hours < 10) {
4305
        $hours = "0$hours";
4306
    }
4307
4308
    if ($sec < 10) {
4309
        $sec = "0$sec";
4310
    }
4311
4312
    if ($min < 10) {
4313
        $min = "0$min";
4314
    }
4315
4316
    $seconds = '';
4317
    if ($showSeconds) {
4318
        $seconds = $space.$sec;
4319
    }
4320
4321
    return $hours.$space.$min.$seconds;
4322
}
4323
4324
/* FILE SYSTEM RELATED FUNCTIONS */
4325
4326
/**
4327
 * Returns the permissions to be assigned to every newly created directory by the web-server.
4328
 * The return value is based on the platform administrator's setting
4329
 * "Administration > Configuration settings > Security > Permissions for new directories".
4330
 *
4331
 * @return int returns the permissions in the format "Owner-Group-Others, Read-Write-Execute", as an integer value
4332
 */
4333
function api_get_permissions_for_new_directories()
4334
{
4335
    static $permissions;
4336
    if (!isset($permissions)) {
4337
        $permissions = trim(api_get_setting('permissions_for_new_directories'));
4338
        // The default value 0777 is according to that in the platform administration panel after fresh system installation.
4339
        $permissions = octdec(!empty($permissions) ? $permissions : '0777');
4340
    }
4341
4342
    return $permissions;
4343
}
4344
4345
/**
4346
 * Returns the permissions to be assigned to every newly created directory by the web-server.
4347
 * The return value is based on the platform administrator's setting
4348
 * "Administration > Configuration settings > Security > Permissions for new files".
4349
 *
4350
 * @return int returns the permissions in the format
4351
 *             "Owner-Group-Others, Read-Write-Execute", as an integer value
4352
 */
4353
function api_get_permissions_for_new_files()
4354
{
4355
    static $permissions;
4356
    if (!isset($permissions)) {
4357
        $permissions = trim(api_get_setting('permissions_for_new_files'));
4358
        // The default value 0666 is according to that in the platform
4359
        // administration panel after fresh system installation.
4360
        $permissions = octdec(!empty($permissions) ? $permissions : '0666');
4361
    }
4362
4363
    return $permissions;
4364
}
4365
4366
/**
4367
 * Deletes a file, or a folder and its contents.
4368
 *
4369
 * @author      Aidan Lister <[email protected]>
4370
 *
4371
 * @version     1.0.3
4372
 *
4373
 * @param string $dirname Directory to delete
4374
 * @param       bool     Deletes only the content or not
4375
 * @param bool $strict if one folder/file fails stop the loop
4376
 *
4377
 * @return bool Returns TRUE on success, FALSE on failure
4378
 *
4379
 * @see http://aidanlister.com/2004/04/recursively-deleting-a-folder-in-php/
4380
 *
4381
 * @author      Yannick Warnier, adaptation for the Chamilo LMS, April, 2008
4382
 * @author      Ivan Tcholakov, a sanity check about Directory class creation has been added, September, 2009
4383
 */
4384
function rmdirr($dirname, $delete_only_content_in_folder = false, $strict = false)
4385
{
4386
    $res = true;
4387
    // A sanity check.
4388
    if (!file_exists($dirname)) {
4389
        return false;
4390
    }
4391
    $php_errormsg = '';
4392
    // Simple delete for a file.
4393
    if (is_file($dirname) || is_link($dirname)) {
4394
        $res = unlink($dirname);
4395
        if (false === $res) {
4396
            error_log(__FILE__.' line '.__LINE__.': '.((bool) ini_get('track_errors') ? $php_errormsg : 'Error not recorded because track_errors is off in your php.ini'), 0);
4397
        }
4398
4399
        return $res;
4400
    }
4401
4402
    // Loop through the folder.
4403
    $dir = dir($dirname);
4404
    // A sanity check.
4405
    $is_object_dir = is_object($dir);
4406
    if ($is_object_dir) {
4407
        while (false !== $entry = $dir->read()) {
4408
            // Skip pointers.
4409
            if ('.' == $entry || '..' == $entry) {
4410
                continue;
4411
            }
4412
4413
            // Recurse.
4414
            if ($strict) {
4415
                $result = rmdirr("$dirname/$entry");
4416
                if (false == $result) {
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...
4417
                    $res = false;
4418
                    break;
4419
                }
4420
            } else {
4421
                rmdirr("$dirname/$entry");
4422
            }
4423
        }
4424
    }
4425
4426
    // Clean up.
4427
    if ($is_object_dir) {
4428
        $dir->close();
4429
    }
4430
4431
    if (false == $delete_only_content_in_folder) {
4432
        $res = rmdir($dirname);
4433
        if (false === $res) {
4434
            error_log(__FILE__.' line '.__LINE__.': '.((bool) ini_get('track_errors') ? $php_errormsg : 'error not recorded because track_errors is off in your php.ini'), 0);
4435
        }
4436
    }
4437
4438
    return $res;
4439
}
4440
4441
// TODO: This function is to be simplified. File access modes to be implemented.
4442
/**
4443
 * function adapted from a php.net comment
4444
 * copy recursively a folder.
4445
 *
4446
 * @param the source folder
4447
 * @param the dest folder
4448
 * @param an array of excluded file_name (without extension)
4449
 * @param copied_files the returned array of copied files
4450
 * @param string $source
4451
 * @param string $dest
4452
 */
4453
function copyr($source, $dest, $exclude = [], $copied_files = [])
4454
{
4455
    if (empty($dest)) {
4456
        return false;
4457
    }
4458
    // Simple copy for a file
4459
    if (is_file($source)) {
4460
        $path_info = pathinfo($source);
4461
        if (!in_array($path_info['filename'], $exclude)) {
4462
            copy($source, $dest);
4463
        }
4464
4465
        return true;
4466
    } elseif (!is_dir($source)) {
4467
        //then source is not a dir nor a file, return
4468
        return false;
4469
    }
4470
4471
    // Make destination directory.
4472
    if (!is_dir($dest)) {
4473
        mkdir($dest, api_get_permissions_for_new_directories());
4474
    }
4475
4476
    // Loop through the folder.
4477
    $dir = dir($source);
4478
    while (false !== $entry = $dir->read()) {
4479
        // Skip pointers
4480
        if ('.' == $entry || '..' == $entry) {
4481
            continue;
4482
        }
4483
4484
        // Deep copy directories.
4485
        if ($dest !== "$source/$entry") {
4486
            $files = copyr("$source/$entry", "$dest/$entry", $exclude, $copied_files);
4487
        }
4488
    }
4489
    // Clean up.
4490
    $dir->close();
4491
4492
    return true;
4493
}
4494
4495
/**
4496
 * @todo: Using DIRECTORY_SEPARATOR is not recommended, this is an obsolete approach.
4497
 * Documentation header to be added here.
4498
 *
4499
 * @param string $pathname
4500
 * @param string $base_path_document
4501
 * @param int    $session_id
4502
 *
4503
 * @return mixed True if directory already exists, false if a file already exists at
4504
 *               the destination and null if everything goes according to plan
4505
 */
4506
function copy_folder_course_session(
4507
    $pathname,
4508
    $base_path_document,
4509
    $session_id,
4510
    $course_info,
4511
    $document,
4512
    $source_course_id
4513
) {
4514
    $table = Database::get_course_table(TABLE_DOCUMENT);
4515
    $session_id = intval($session_id);
4516
    $source_course_id = intval($source_course_id);
4517
4518
    // Check whether directory already exists.
4519
    if (is_dir($pathname) || empty($pathname)) {
4520
        return true;
4521
    }
4522
4523
    // Ensure that a file with the same name does not already exist.
4524
    if (is_file($pathname)) {
4525
        trigger_error('copy_folder_course_session(): File exists', E_USER_WARNING);
4526
4527
        return false;
4528
    }
4529
4530
    $course_id = $course_info['real_id'];
4531
    $folders = explode(DIRECTORY_SEPARATOR, str_replace($base_path_document.DIRECTORY_SEPARATOR, '', $pathname));
4532
    $new_pathname = $base_path_document;
4533
    $path = '';
4534
4535
    foreach ($folders as $folder) {
4536
        $new_pathname .= DIRECTORY_SEPARATOR.$folder;
4537
        $path .= DIRECTORY_SEPARATOR.$folder;
4538
4539
        if (!file_exists($new_pathname)) {
4540
            $path = Database::escape_string($path);
4541
4542
            $sql = "SELECT * FROM $table
4543
                    WHERE
4544
                        c_id = $source_course_id AND
4545
                        path = '$path' AND
4546
                        filetype = 'folder' AND
4547
                        session_id = '$session_id'";
4548
            $rs1 = Database::query($sql);
4549
            $num_rows = Database::num_rows($rs1);
4550
4551
            if (0 == $num_rows) {
4552
                mkdir($new_pathname, api_get_permissions_for_new_directories());
4553
4554
                // Insert new folder with destination session_id.
4555
                $params = [
4556
                    'c_id' => $course_id,
4557
                    'path' => $path,
4558
                    'comment' => $document->comment,
4559
                    'title' => basename($new_pathname),
4560
                    'filetype' => 'folder',
4561
                    'size' => '0',
4562
                    'session_id' => $session_id,
4563
                ];
4564
                Database::insert($table, $params);
4565
            }
4566
        }
4567
    } // en foreach
4568
}
4569
4570
// TODO: chmodr() is a better name. Some corrections are needed. Documentation header to be added here.
4571
/**
4572
 * @param string $path
4573
 */
4574
function api_chmod_R($path, $filemode)
4575
{
4576
    if (!is_dir($path)) {
4577
        return chmod($path, $filemode);
4578
    }
4579
4580
    $handler = opendir($path);
4581
    while ($file = readdir($handler)) {
4582
        if ('.' != $file && '..' != $file) {
4583
            $fullpath = "$path/$file";
4584
            if (!is_dir($fullpath)) {
4585
                if (!chmod($fullpath, $filemode)) {
4586
                    return false;
4587
                }
4588
            } else {
4589
                if (!api_chmod_R($fullpath, $filemode)) {
4590
                    return false;
4591
                }
4592
            }
4593
        }
4594
    }
4595
4596
    closedir($handler);
4597
4598
    return chmod($path, $filemode);
4599
}
4600
4601
// TODO: Where the following function has been copy/pased from? There is no information about author and license. Style, coding conventions...
4602
/**
4603
 * Parse info file format. (e.g: file.info).
4604
 *
4605
 * Files should use an ini-like format to specify values.
4606
 * White-space generally doesn't matter, except inside values.
4607
 * e.g.
4608
 *
4609
 * @verbatim
4610
 *   key = value
4611
 *   key = "value"
4612
 *   key = 'value'
4613
 *   key = "multi-line
4614
 *
4615
 *   value"
4616
 *   key = 'multi-line
4617
 *
4618
 *   value'
4619
 *   key
4620
 *   =
4621
 *   'value'
4622
 * @endverbatim
4623
 *
4624
 * Arrays are created using a GET-like syntax:
4625
 *
4626
 * @verbatim
4627
 *   key[] = "numeric array"
4628
 *   key[index] = "associative array"
4629
 *   key[index][] = "nested numeric array"
4630
 *   key[index][index] = "nested associative array"
4631
 * @endverbatim
4632
 *
4633
 * PHP constants are substituted in, but only when used as the entire value:
4634
 *
4635
 * Comments should start with a semi-colon at the beginning of a line.
4636
 *
4637
 * This function is NOT for placing arbitrary module-specific settings. Use
4638
 * variable_get() and variable_set() for that.
4639
 *
4640
 * Information stored in the module.info file:
4641
 * - name: The real name of the module for display purposes.
4642
 * - description: A brief description of the module.
4643
 * - dependencies: An array of shortnames of other modules this module depends on.
4644
 * - package: The name of the package of modules this module belongs to.
4645
 *
4646
 * Example of .info file:
4647
 * <code>
4648
 * @verbatim
4649
 *   name = Forum
4650
 *   description = Enables threaded discussions about general topics.
4651
 *   dependencies[] = taxonomy
4652
 *   dependencies[] = comment
4653
 *   package = Core - optional
4654
 *   version = VERSION
4655
 * @endverbatim
4656
 * </code>
4657
 *
4658
 * @param string $filename
4659
 *                         The file we are parsing. Accepts file with relative or absolute path.
4660
 *
4661
 * @return
4662
 *   The info array
4663
 */
4664
function api_parse_info_file($filename)
4665
{
4666
    $info = [];
4667
4668
    if (!file_exists($filename)) {
4669
        return $info;
4670
    }
4671
4672
    $data = file_get_contents($filename);
4673
    if (preg_match_all('
4674
        @^\s*                           # Start at the beginning of a line, ignoring leading whitespace
4675
        ((?:
4676
          [^=;\[\]]|                    # Key names cannot contain equal signs, semi-colons or square brackets,
4677
          \[[^\[\]]*\]                  # unless they are balanced and not nested
4678
        )+?)
4679
        \s*=\s*                         # Key/value pairs are separated by equal signs (ignoring white-space)
4680
        (?:
4681
          ("(?:[^"]|(?<=\\\\)")*")|     # Double-quoted string, which may contain slash-escaped quotes/slashes
4682
          (\'(?:[^\']|(?<=\\\\)\')*\')| # Single-quoted string, which may contain slash-escaped quotes/slashes
4683
          ([^\r\n]*?)                   # Non-quoted string
4684
        )\s*$                           # Stop at the next end of a line, ignoring trailing whitespace
4685
        @msx', $data, $matches, PREG_SET_ORDER)) {
4686
        $key = $value1 = $value2 = $value3 = '';
4687
        foreach ($matches as $match) {
4688
            // Fetch the key and value string.
4689
            $i = 0;
4690
            foreach (['key', 'value1', 'value2', 'value3'] as $var) {
4691
                $$var = isset($match[++$i]) ? $match[$i] : '';
4692
            }
4693
            $value = stripslashes(substr($value1, 1, -1)).stripslashes(substr($value2, 1, -1)).$value3;
4694
4695
            // Parse array syntax.
4696
            $keys = preg_split('/\]?\[/', rtrim($key, ']'));
4697
            $last = array_pop($keys);
4698
            $parent = &$info;
4699
4700
            // Create nested arrays.
4701
            foreach ($keys as $key) {
4702
                if ('' == $key) {
4703
                    $key = count($parent);
4704
                }
4705
                if (!isset($parent[$key]) || !is_array($parent[$key])) {
4706
                    $parent[$key] = [];
4707
                }
4708
                $parent = &$parent[$key];
4709
            }
4710
4711
            // Handle PHP constants.
4712
            if (defined($value)) {
4713
                $value = constant($value);
4714
            }
4715
4716
            // Insert actual value.
4717
            if ('' == $last) {
4718
                $last = count($parent);
4719
            }
4720
            $parent[$last] = $value;
4721
        }
4722
    }
4723
4724
    return $info;
4725
}
4726
4727
/**
4728
 * Gets Chamilo version from the configuration files.
4729
 *
4730
 * @return string A string of type "1.8.4", or an empty string if the version could not be found
4731
 */
4732
function api_get_version()
4733
{
4734
    return (string) api_get_configuration_value('system_version');
4735
}
4736
4737
/**
4738
 * Gets the software name (the name/brand of the Chamilo-based customized system).
4739
 *
4740
 * @return string
4741
 */
4742
function api_get_software_name()
4743
{
4744
    $name = api_get_configuration_value('software_name');
4745
    if (!empty($name)) {
4746
        return $name;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $name also could return the type boolean which is incompatible with the documented return type string.
Loading history...
4747
    } else {
4748
        return 'Chamilo';
4749
    }
4750
}
4751
4752
function api_get_status_list()
4753
{
4754
    $list = [];
4755
    // Table of status
4756
    $list[COURSEMANAGER] = 'teacher'; // 1
4757
    $list[SESSIONADMIN] = 'session_admin'; // 3
4758
    $list[DRH] = 'drh'; // 4
4759
    $list[STUDENT] = 'user'; // 5
4760
    $list[ANONYMOUS] = 'anonymous'; // 6
4761
    $list[INVITEE] = 'invited'; // 20
4762
4763
    return $list;
4764
}
4765
4766
/**
4767
 * Checks whether status given in parameter exists in the platform.
4768
 *
4769
 * @param mixed the status (can be either int either string)
4770
 *
4771
 * @return bool if the status exists, else returns false
4772
 */
4773
function api_status_exists($status_asked)
4774
{
4775
    $list = api_get_status_list();
4776
4777
    return in_array($status_asked, $list) ? true : isset($list[$status_asked]);
4778
}
4779
4780
/**
4781
 * Checks whether status given in parameter exists in the platform. The function
4782
 * returns the status ID or false if it does not exist, but given the fact there
4783
 * is no "0" status, the return value can be checked against
4784
 * if(api_status_key()) to know if it exists.
4785
 *
4786
 * @param   mixed   The status (can be either int or string)
4787
 *
4788
 * @return mixed Status ID if exists, false otherwise
4789
 */
4790
function api_status_key($status)
4791
{
4792
    $list = api_get_status_list();
4793
4794
    return isset($list[$status]) ? $status : array_search($status, $list);
4795
}
4796
4797
/**
4798
 * Gets the status langvars list.
4799
 *
4800
 * @return string[] the list of status with their translations
4801
 */
4802
function api_get_status_langvars()
4803
{
4804
    return [
4805
        COURSEMANAGER => get_lang('Teacher'),
4806
        SESSIONADMIN => get_lang('SessionsAdmin'),
4807
        DRH => get_lang('Human Resources Manager'),
4808
        STUDENT => get_lang('Learner'),
4809
        ANONYMOUS => get_lang('Anonymous'),
4810
        STUDENT_BOSS => get_lang('RoleStudentBoss'),
4811
        INVITEE => get_lang('Invited'),
4812
    ];
4813
}
4814
4815
/**
4816
 * The function that retrieves all the possible settings for a certain config setting.
4817
 *
4818
 * @author Patrick Cool <[email protected]>, Ghent University
4819
 */
4820
function api_get_settings_options($var)
4821
{
4822
    $table_settings_options = Database::get_main_table(TABLE_MAIN_SETTINGS_OPTIONS);
4823
    $var = Database::escape_string($var);
4824
    $sql = "SELECT * FROM $table_settings_options
4825
            WHERE variable = '$var'
4826
            ORDER BY id";
4827
    $result = Database::query($sql);
4828
    $settings_options_array = [];
4829
    while ($row = Database::fetch_array($result, 'ASSOC')) {
4830
        $settings_options_array[] = $row;
4831
    }
4832
4833
    return $settings_options_array;
4834
}
4835
4836
/**
4837
 * @param array $params
4838
 */
4839
function api_set_setting_option($params)
4840
{
4841
    $table = Database::get_main_table(TABLE_MAIN_SETTINGS_OPTIONS);
4842
    if (empty($params['id'])) {
4843
        Database::insert($table, $params);
4844
    } else {
4845
        Database::update($table, $params, ['id = ? ' => $params['id']]);
4846
    }
4847
}
4848
4849
/**
4850
 * @param array $params
4851
 */
4852
function api_set_setting_simple($params)
4853
{
4854
    $table = Database::get_main_table(TABLE_MAIN_SETTINGS_CURRENT);
4855
    $url_id = api_get_current_access_url_id();
4856
4857
    if (empty($params['id'])) {
4858
        $params['access_url'] = $url_id;
4859
        Database::insert($table, $params);
4860
    } else {
4861
        Database::update($table, $params, ['id = ? ' => [$params['id']]]);
4862
    }
4863
}
4864
4865
/**
4866
 * @param int $id
4867
 */
4868
function api_delete_setting_option($id)
4869
{
4870
    $table = Database::get_main_table(TABLE_MAIN_SETTINGS_OPTIONS);
4871
    if (!empty($id)) {
4872
        Database::delete($table, ['id = ? ' => $id]);
4873
    }
4874
}
4875
4876
/**
4877
 * Sets a platform configuration setting to a given value.
4878
 *
4879
 * @param string    The variable we want to update
4880
 * @param string    The value we want to record
4881
 * @param string    The sub-variable if any (in most cases, this will remain null)
4882
 * @param string    The category if any (in most cases, this will remain null)
4883
 * @param int       The access_url for which this parameter is valid
4884
 * @param string $cat
4885
 *
4886
 * @return bool|null
4887
 */
4888
function api_set_setting($var, $value, $subvar = null, $cat = null, $access_url = 1)
4889
{
4890
    if (empty($var)) {
4891
        return false;
4892
    }
4893
    $t_settings = Database::get_main_table(TABLE_MAIN_SETTINGS_CURRENT);
4894
    $var = Database::escape_string($var);
4895
    $value = Database::escape_string($value);
4896
    $access_url = (int) $access_url;
4897
    if (empty($access_url)) {
4898
        $access_url = 1;
4899
    }
4900
    $select = "SELECT id FROM $t_settings WHERE variable = '$var' ";
4901
    if (!empty($subvar)) {
4902
        $subvar = Database::escape_string($subvar);
4903
        $select .= " AND subkey = '$subvar'";
4904
    }
4905
    if (!empty($cat)) {
4906
        $cat = Database::escape_string($cat);
4907
        $select .= " AND category = '$cat'";
4908
    }
4909
    if ($access_url > 1) {
4910
        $select .= " AND access_url = $access_url";
4911
    } else {
4912
        $select .= " AND access_url = 1 ";
4913
    }
4914
4915
    $res = Database::query($select);
4916
    if (Database::num_rows($res) > 0) {
4917
        // Found item for this access_url.
4918
        $row = Database::fetch_array($res);
4919
        $sql = "UPDATE $t_settings SET selected_value = '$value'
4920
                WHERE id = ".$row['id'];
4921
        Database::query($sql);
4922
    } else {
4923
        // Item not found for this access_url, we have to check if it exist with access_url = 1
4924
        $select = "SELECT * FROM $t_settings
4925
                   WHERE variable = '$var' AND access_url = 1 ";
4926
        // Just in case
4927
        if (1 == $access_url) {
4928
            if (!empty($subvar)) {
4929
                $select .= " AND subkey = '$subvar'";
4930
            }
4931
            if (!empty($cat)) {
4932
                $select .= " AND category = '$cat'";
4933
            }
4934
            $res = Database::query($select);
4935
            if (Database::num_rows($res) > 0) {
4936
                // We have a setting for access_url 1, but none for the current one, so create one.
4937
                $row = Database::fetch_array($res);
4938
                $insert = "INSERT INTO $t_settings (variable, subkey, type,category, selected_value, title, comment, scope, subkeytext, access_url)
4939
                        VALUES
4940
                        ('".$row['variable']."',".(!empty($row['subkey']) ? "'".$row['subkey']."'" : "NULL").",".
4941
                    "'".$row['type']."','".$row['category']."',".
4942
                    "'$value','".$row['title']."',".
4943
                    "".(!empty($row['comment']) ? "'".$row['comment']."'" : "NULL").",".(!empty($row['scope']) ? "'".$row['scope']."'" : "NULL").",".
4944
                    "".(!empty($row['subkeytext']) ? "'".$row['subkeytext']."'" : "NULL").",$access_url)";
4945
                Database::query($insert);
4946
            } else {
4947
                // Such a setting does not exist.
4948
                //error_log(__FILE__.':'.__LINE__.': Attempting to update setting '.$var.' ('.$subvar.') which does not exist at all', 0);
4949
            }
4950
        } else {
4951
            // Other access url.
4952
            if (!empty($subvar)) {
4953
                $select .= " AND subkey = '$subvar'";
4954
            }
4955
            if (!empty($cat)) {
4956
                $select .= " AND category = '$cat'";
4957
            }
4958
            $res = Database::query($select);
4959
4960
            if (Database::num_rows($res) > 0) {
4961
                // We have a setting for access_url 1, but none for the current one, so create one.
4962
                $row = Database::fetch_array($res);
4963
                if (1 == $row['access_url_changeable']) {
4964
                    $insert = "INSERT INTO $t_settings (variable,subkey, type,category, selected_value,title, comment,scope, subkeytext,access_url, access_url_changeable) VALUES
4965
                            ('".$row['variable']."',".
4966
                        (!empty($row['subkey']) ? "'".$row['subkey']."'" : "NULL").",".
4967
                        "'".$row['type']."','".$row['category']."',".
4968
                        "'$value','".$row['title']."',".
4969
                        "".(!empty($row['comment']) ? "'".$row['comment']."'" : "NULL").",".
4970
                        (!empty($row['scope']) ? "'".$row['scope']."'" : "NULL").",".
4971
                        "".(!empty($row['subkeytext']) ? "'".$row['subkeytext']."'" : "NULL").",$access_url,".$row['access_url_changeable'].")";
4972
                    Database::query($insert);
4973
                }
4974
            } else { // Such a setting does not exist.
4975
                //error_log(__FILE__.':'.__LINE__.': Attempting to update setting '.$var.' ('.$subvar.') which does not exist at all. The access_url is: '.$access_url.' ',0);
4976
            }
4977
        }
4978
    }
4979
}
4980
4981
/**
4982
 * Sets a whole category of settings to one specific value.
4983
 *
4984
 * @param string    Category
4985
 * @param string    Value
4986
 * @param int       Access URL. Optional. Defaults to 1
4987
 * @param array     Optional array of filters on field type
4988
 * @param string $category
4989
 * @param string $value
4990
 *
4991
 * @return bool
4992
 */
4993
function api_set_settings_category($category, $value = null, $access_url = 1, $fieldtype = [])
4994
{
4995
    if (empty($category)) {
4996
        return false;
4997
    }
4998
    $category = Database::escape_string($category);
4999
    $t_s = Database::get_main_table(TABLE_MAIN_SETTINGS_CURRENT);
5000
    $access_url = (int) $access_url;
5001
    if (empty($access_url)) {
5002
        $access_url = 1;
5003
    }
5004
    if (isset($value)) {
5005
        $value = Database::escape_string($value);
5006
        $sql = "UPDATE $t_s SET selected_value = '$value'
5007
                WHERE category = '$category' AND access_url = $access_url";
5008
        if (is_array($fieldtype) && count($fieldtype) > 0) {
5009
            $sql .= " AND ( ";
5010
            $i = 0;
5011
            foreach ($fieldtype as $type) {
5012
                if ($i > 0) {
5013
                    $sql .= ' OR ';
5014
                }
5015
                $type = Database::escape_string($type);
5016
                $sql .= " type='".$type."' ";
5017
                $i++;
5018
            }
5019
            $sql .= ")";
5020
        }
5021
        $res = Database::query($sql);
5022
5023
        return false !== $res;
5024
    } else {
5025
        $sql = "UPDATE $t_s SET selected_value = NULL
5026
                WHERE category = '$category' AND access_url = $access_url";
5027
        if (is_array($fieldtype) && count($fieldtype) > 0) {
5028
            $sql .= " AND ( ";
5029
            $i = 0;
5030
            foreach ($fieldtype as $type) {
5031
                if ($i > 0) {
5032
                    $sql .= ' OR ';
5033
                }
5034
                $type = Database::escape_string($type);
5035
                $sql .= " type='".$type."' ";
5036
                $i++;
5037
            }
5038
            $sql .= ")";
5039
        }
5040
        $res = Database::query($sql);
5041
5042
        return false !== $res;
5043
    }
5044
}
5045
5046
/**
5047
 * Gets all available access urls in an array (as in the database).
5048
 *
5049
 * @return array An array of database records
5050
 */
5051
function api_get_access_urls($from = 0, $to = 1000000, $order = 'url', $direction = 'ASC')
5052
{
5053
    $table = Database::get_main_table(TABLE_MAIN_ACCESS_URL);
5054
    $from = (int) $from;
5055
    $to = (int) $to;
5056
    $order = Database::escape_string($order, null, false);
5057
    $direction = Database::escape_string($direction, null, false);
5058
    $sql = "SELECT id, url, description, active, created_by, tms
5059
            FROM $table
5060
            ORDER BY $order $direction
5061
            LIMIT $to OFFSET $from";
5062
    $res = Database::query($sql);
5063
5064
    return Database::store_result($res);
5065
}
5066
5067
/**
5068
 * Gets the access url info in an array.
5069
 *
5070
 * @param int  $id            Id of the access url
5071
 * @param bool $returnDefault Set to false if you want the real URL if URL 1 is still 'http://localhost/'
5072
 *
5073
 * @return array All the info (url, description, active, created_by, tms)
5074
 *               from the access_url table
5075
 *
5076
 * @author Julio Montoya
5077
 */
5078
function api_get_access_url($id, $returnDefault = true)
5079
{
5080
    static $staticResult;
5081
    $id = (int) $id;
5082
5083
    if (isset($staticResult[$id])) {
5084
        $result = $staticResult[$id];
5085
    } else {
5086
        // Calling the Database:: library dont work this is handmade.
5087
        $table_access_url = Database::get_main_table(TABLE_MAIN_ACCESS_URL);
5088
        $sql = "SELECT url, description, active, created_by, tms
5089
                FROM $table_access_url WHERE id = '$id' ";
5090
        $res = Database::query($sql);
5091
        $result = @Database::fetch_array($res);
5092
        $staticResult[$id] = $result;
5093
    }
5094
5095
    // If the result url is 'http://localhost/' (the default) and the root_web
5096
    // (=current url) is different, and the $id is = 1 (which might mean
5097
    // api_get_current_access_url_id() returned 1 by default), then return the
5098
    // root_web setting instead of the current URL
5099
    // This is provided as an option to avoid breaking the storage of URL-specific
5100
    // homepages in home/localhost/
5101
    if (1 === $id && false === $returnDefault) {
5102
        $currentUrl = api_get_current_access_url_id();
5103
        // only do this if we are on the main URL (=1), otherwise we could get
5104
        // information on another URL instead of the one asked as parameter
5105
        if (1 === $currentUrl) {
5106
            $rootWeb = api_get_path(WEB_PATH);
5107
            $default = 'http://localhost/';
5108
            if ($result['url'] === $default && $rootWeb != $default) {
5109
                $result['url'] = $rootWeb;
5110
            }
5111
        }
5112
    }
5113
5114
    return $result;
5115
}
5116
5117
/**
5118
 * Gets all the current settings for a specific access url.
5119
 *
5120
 * @param string    The category, if any, that we want to get
5121
 * @param string    Whether we want a simple list (display a category) or
5122
 * a grouped list (group by variable as in settings.php default). Values: 'list' or 'group'
5123
 * @param int       Access URL's ID. Optional. Uses 1 by default, which is the unique URL
5124
 *
5125
 * @return array Array of database results for the current settings of the current access URL
5126
 */
5127
function &api_get_settings($cat = null, $ordering = 'list', $access_url = 1, $url_changeable = 0)
5128
{
5129
    $table = Database::get_main_table(TABLE_MAIN_SETTINGS_CURRENT);
5130
    $access_url = (int) $access_url;
5131
    $where_condition = '';
5132
    if (1 == $url_changeable) {
5133
        $where_condition = " AND access_url_changeable= '1' ";
5134
    }
5135
    if (empty($access_url) || -1 == $access_url) {
5136
        $access_url = 1;
5137
    }
5138
    $sql = "SELECT * FROM $table
5139
            WHERE access_url = $access_url  $where_condition ";
5140
5141
    if (!empty($cat)) {
5142
        $cat = Database::escape_string($cat);
5143
        $sql .= " AND category='$cat' ";
5144
    }
5145
    if ('group' == $ordering) {
5146
        $sql .= " ORDER BY id ASC";
5147
    } else {
5148
        $sql .= " ORDER BY 1,2 ASC";
5149
    }
5150
    $result = Database::query($sql);
5151
    if (null === $result) {
5152
        return [];
5153
    }
5154
    $result = Database::store_result($result, 'ASSOC');
5155
5156
    return $result;
5157
}
5158
5159
/**
5160
 * @param string $value       The value we want to record
5161
 * @param string $variable    The variable name we want to insert
5162
 * @param string $subKey      The subkey for the variable we want to insert
5163
 * @param string $type        The type for the variable we want to insert
5164
 * @param string $category    The category for the variable we want to insert
5165
 * @param string $title       The title
5166
 * @param string $comment     The comment
5167
 * @param string $scope       The scope
5168
 * @param string $subKeyText  The subkey text
5169
 * @param int    $accessUrlId The access_url for which this parameter is valid
5170
 * @param int    $visibility  The changeability of this setting for non-master urls
5171
 *
5172
 * @return int The setting ID
5173
 */
5174
function api_add_setting(
5175
    $value,
5176
    $variable,
5177
    $subKey = '',
5178
    $type = 'textfield',
5179
    $category = '',
5180
    $title = '',
5181
    $comment = '',
5182
    $scope = '',
5183
    $subKeyText = '',
5184
    $accessUrlId = 1,
5185
    $visibility = 0
5186
) {
5187
    $em = Database::getManager();
5188
5189
    $settingRepo = $em->getRepository(SettingsCurrent::class);
5190
    $accessUrlId = (int) $accessUrlId ?: 1;
5191
5192
    if (is_array($value)) {
5193
        $value = serialize($value);
5194
    } else {
5195
        $value = trim($value);
5196
    }
5197
5198
    $criteria = ['variable' => $variable, 'url' => $accessUrlId];
5199
5200
    if (!empty($subKey)) {
5201
        $criteria['subkey'] = $subKey;
5202
    }
5203
5204
    // Check if this variable doesn't exist already
5205
    /** @var SettingsCurrent $setting */
5206
    $setting = $settingRepo->findOneBy($criteria);
5207
5208
    if ($setting) {
0 ignored issues
show
introduced by
$setting is of type Chamilo\CoreBundle\Entity\SettingsCurrent, thus it always evaluated to true.
Loading history...
5209
        $setting->setSelectedValue($value);
5210
5211
        $em->persist($setting);
5212
        $em->flush();
5213
5214
        return $setting->getId();
5215
    }
5216
5217
    // Item not found for this access_url, we have to check if the whole thing is missing
5218
    // (in which case we ignore the insert) or if there *is* a record but just for access_url = 1
5219
    $setting = new SettingsCurrent();
5220
    $url = api_get_url_entity();
5221
5222
    $setting
5223
        ->setVariable($variable)
5224
        ->setSelectedValue($value)
5225
        ->setType($type)
5226
        ->setCategory($category)
5227
        ->setSubkey($subKey)
5228
        ->setTitle($title)
5229
        ->setComment($comment)
5230
        ->setScope($scope)
5231
        ->setSubkeytext($subKeyText)
5232
        ->setUrl(api_get_url_entity())
5233
        ->setAccessUrlChangeable($visibility);
5234
5235
    $em->persist($setting);
5236
    $em->flush();
5237
5238
    return $setting->getId();
5239
}
5240
5241
/**
5242
 * Checks wether a user can or can't view the contents of a course.
5243
 *
5244
 * @deprecated use CourseManager::is_user_subscribed_in_course
5245
 *
5246
 * @param int $userid User id or NULL to get it from $_SESSION
5247
 * @param int $cid    course id to check whether the user is allowed
5248
 *
5249
 * @return bool
5250
 */
5251
function api_is_course_visible_for_user($userid = null, $cid = null)
5252
{
5253
    if (null === $userid) {
5254
        $userid = api_get_user_id();
5255
    }
5256
    if (empty($userid) || strval(intval($userid)) != $userid) {
5257
        if (api_is_anonymous()) {
5258
            $userid = api_get_anonymous_id();
5259
        } else {
5260
            return false;
5261
        }
5262
    }
5263
    $cid = Database::escape_string($cid);
5264
5265
    $courseInfo = api_get_course_info($cid);
5266
    $courseId = $courseInfo['real_id'];
5267
    $is_platformAdmin = api_is_platform_admin();
5268
5269
    $course_table = Database::get_main_table(TABLE_MAIN_COURSE);
5270
    $course_cat_table = Database::get_main_table(TABLE_MAIN_CATEGORY);
5271
5272
    $sql = "SELECT
5273
                $course_cat_table.code AS category_code,
5274
                $course_table.visibility,
5275
                $course_table.code,
5276
                $course_cat_table.code
5277
            FROM $course_table
5278
            LEFT JOIN $course_cat_table
5279
                ON $course_table.category_id = $course_cat_table.id
5280
            WHERE
5281
                $course_table.code = '$cid'
5282
            LIMIT 1";
5283
5284
    $result = Database::query($sql);
5285
5286
    if (Database::num_rows($result) > 0) {
5287
        $visibility = Database::fetch_array($result);
5288
        $visibility = $visibility['visibility'];
5289
    } else {
5290
        $visibility = 0;
5291
    }
5292
    // Shortcut permissions in case the visibility is "open to the world".
5293
    if (COURSE_VISIBILITY_OPEN_WORLD === $visibility) {
5294
        return true;
5295
    }
5296
5297
    $tbl_course_user = Database::get_main_table(TABLE_MAIN_COURSE_USER);
5298
5299
    $sql = "SELECT
5300
                is_tutor, status
5301
            FROM $tbl_course_user
5302
            WHERE
5303
                user_id  = '$userid' AND
5304
                relation_type <> '".COURSE_RELATION_TYPE_RRHH."' AND
5305
                c_id = $courseId
5306
            LIMIT 1";
5307
5308
    $result = Database::query($sql);
5309
5310
    if (Database::num_rows($result) > 0) {
5311
        // This user has got a recorded state for this course.
5312
        $cuData = Database::fetch_array($result);
5313
        $is_courseMember = true;
5314
        $is_courseAdmin = (1 == $cuData['status']);
5315
    }
5316
5317
    if (!$is_courseAdmin) {
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $is_courseAdmin does not seem to be defined for all execution paths leading up to this point.
Loading history...
5318
        // This user has no status related to this course.
5319
        // Is it the session coach or the session admin?
5320
        $tbl_session = Database::get_main_table(TABLE_MAIN_SESSION);
5321
        $tbl_session_course = Database::get_main_table(TABLE_MAIN_SESSION_COURSE);
5322
        $tbl_session_course_user = Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER);
5323
5324
        $sql = "SELECT
5325
                    session.id_coach, session_admin_id, session.id
5326
                FROM
5327
                    $tbl_session as session
5328
                INNER JOIN $tbl_session_course
5329
                    ON session_rel_course.session_id = session.id
5330
                    AND session_rel_course.c_id = '$courseId'
5331
                LIMIT 1";
5332
5333
        $result = Database::query($sql);
5334
        $row = Database::store_result($result);
5335
5336
        if ($row[0]['id_coach'] == $userid) {
5337
            $is_courseMember = true;
5338
            $is_courseAdmin = false;
5339
        } elseif ($row[0]['session_admin_id'] == $userid) {
5340
            $is_courseMember = false;
5341
            $is_courseAdmin = false;
5342
        } else {
5343
            // Check if the current user is the course coach.
5344
            $sql = "SELECT 1
5345
                    FROM $tbl_session_course
5346
                    WHERE session_rel_course.c_id = '$courseId'
5347
                    AND session_rel_course.id_coach = '$userid'
5348
                    LIMIT 1";
5349
5350
            $result = Database::query($sql);
5351
5352
            //if ($row = Database::fetch_array($result)) {
5353
            if (Database::num_rows($result) > 0) {
5354
                $is_courseMember = true;
5355
                $tbl_user = Database::get_main_table(TABLE_MAIN_USER);
5356
5357
                $sql = "SELECT status FROM $tbl_user
5358
                        WHERE id = $userid
5359
                        LIMIT 1";
5360
5361
                $result = Database::query($sql);
5362
5363
                if (1 == Database::result($result, 0, 0)) {
5364
                    $is_courseAdmin = true;
5365
                } else {
5366
                    $is_courseAdmin = false;
5367
                }
5368
            } else {
5369
                // Check if the user is a student is this session.
5370
                $sql = "SELECT  id
5371
                        FROM $tbl_session_course_user
5372
                        WHERE
5373
                            user_id  = '$userid' AND
5374
                            c_id = '$courseId'
5375
                        LIMIT 1";
5376
5377
                if (Database::num_rows($result) > 0) {
5378
                    // This user haa got a recorded state for this course.
5379
                    while ($row = Database::fetch_array($result)) {
5380
                        $is_courseMember = true;
5381
                        $is_courseAdmin = false;
5382
                    }
5383
                }
5384
            }
5385
        }
5386
    }
5387
5388
    switch ($visibility) {
5389
        case COURSE_VISIBILITY_OPEN_WORLD:
5390
            return true;
5391
        case COURSE_VISIBILITY_OPEN_PLATFORM:
5392
            return isset($userid);
5393
        case COURSE_VISIBILITY_REGISTERED:
5394
        case COURSE_VISIBILITY_CLOSED:
5395
            return $is_platformAdmin || $is_courseMember || $is_courseAdmin;
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $is_courseMember does not seem to be defined for all execution paths leading up to this point.
Loading history...
5396
        case COURSE_VISIBILITY_HIDDEN:
5397
            return $is_platformAdmin;
5398
    }
5399
5400
    return false;
5401
}
5402
5403
/**
5404
 * Returns whether an element (forum, message, survey ...) belongs to a session or not.
5405
 *
5406
 * @param string the tool of the element
5407
 * @param int the element id in database
5408
 * @param int the session_id to compare with element session id
5409
 *
5410
 * @return bool true if the element is in the session, false else
5411
 */
5412
function api_is_element_in_the_session($tool, $element_id, $session_id = null)
5413
{
5414
    if (is_null($session_id)) {
5415
        $session_id = api_get_session_id();
5416
    }
5417
5418
    $element_id = (int) $element_id;
5419
5420
    if (empty($element_id)) {
5421
        return false;
5422
    }
5423
5424
    // Get information to build query depending of the tool.
5425
    switch ($tool) {
5426
        case TOOL_SURVEY:
5427
            $table_tool = Database::get_course_table(TABLE_SURVEY);
5428
            $key_field = 'survey_id';
5429
            break;
5430
        case TOOL_ANNOUNCEMENT:
5431
            $table_tool = Database::get_course_table(TABLE_ANNOUNCEMENT);
5432
            $key_field = 'id';
5433
            break;
5434
        case TOOL_AGENDA:
5435
            $table_tool = Database::get_course_table(TABLE_AGENDA);
5436
            $key_field = 'id';
5437
            break;
5438
        case TOOL_GROUP:
5439
            $table_tool = Database::get_course_table(TABLE_GROUP);
5440
            $key_field = 'id';
5441
            break;
5442
        default:
5443
            return false;
5444
    }
5445
    $course_id = api_get_course_int_id();
5446
5447
    $sql = "SELECT session_id FROM $table_tool
5448
            WHERE c_id = $course_id AND $key_field =  ".$element_id;
5449
    $rs = Database::query($sql);
5450
    if ($element_session_id = Database::result($rs, 0, 0)) {
5451
        if ($element_session_id == intval($session_id)) {
5452
            // The element belongs to the session.
5453
            return true;
5454
        }
5455
    }
5456
5457
    return false;
5458
}
5459
5460
/**
5461
 * Replaces "forbidden" characters in a filename string.
5462
 *
5463
 * @param string $filename
5464
 * @param bool   $treat_spaces_as_hyphens
5465
 *
5466
 * @return string
5467
 */
5468
function api_replace_dangerous_char($filename, $treat_spaces_as_hyphens = true)
5469
{
5470
    // Some non-properly encoded file names can cause the whole file to be
5471
    // skipped when uploaded. Avoid this by detecting the encoding and
5472
    // converting to UTF-8, setting the source as ASCII (a reasonably
5473
    // limited characters set) if nothing could be found (BT#
5474
    $encoding = api_detect_encoding($filename);
5475
    if (empty($encoding)) {
5476
        $encoding = 'ASCII';
5477
        if (!api_is_valid_ascii($filename)) {
5478
            // try iconv and try non standard ASCII a.k.a CP437
5479
            // see BT#15022
5480
            if (function_exists('iconv')) {
5481
                $result = iconv('CP437', 'UTF-8', $filename);
5482
                if (api_is_valid_utf8($result)) {
5483
                    $filename = $result;
5484
                    $encoding = 'UTF-8';
5485
                }
5486
            }
5487
        }
5488
    }
5489
5490
    $filename = api_to_system_encoding($filename, $encoding);
5491
5492
    $url = URLify::filter(
5493
        $filename,
5494
        250,
5495
        '',
5496
        true,
5497
        false,
5498
        false,
5499
        false
5500
    );
5501
5502
    return $url;
5503
}
5504
5505
/**
5506
 * Fixes the $_SERVER['REQUEST_URI'] that is empty in IIS6.
5507
 *
5508
 * @author Ivan Tcholakov, 28-JUN-2006.
5509
 */
5510
function api_request_uri()
5511
{
5512
    if (!empty($_SERVER['REQUEST_URI'])) {
5513
        return $_SERVER['REQUEST_URI'];
5514
    }
5515
    $uri = $_SERVER['SCRIPT_NAME'];
5516
    if (!empty($_SERVER['QUERY_STRING'])) {
5517
        $uri .= '?'.$_SERVER['QUERY_STRING'];
5518
    }
5519
    $_SERVER['REQUEST_URI'] = $uri;
5520
5521
    return $uri;
5522
}
5523
5524
/** Gets the current access_url id of the Chamilo Platform.
5525
 * @author Julio Montoya <[email protected]>
5526
 *
5527
 * @return int access_url_id of the current Chamilo Installation
5528
 */
5529
function api_get_current_access_url_id()
5530
{
5531
    if (false === api_get_multiple_access_url()) {
5532
        return 1;
5533
    }
5534
5535
    static $id;
5536
    if (!empty($id)) {
5537
        return $id;
5538
    }
5539
5540
    $table = Database::get_main_table(TABLE_MAIN_ACCESS_URL);
5541
    $path = Database::escape_string(api_get_path(WEB_PATH));
5542
    $sql = "SELECT id FROM $table WHERE url = '".$path."'";
5543
    $result = Database::query($sql);
5544
    if (Database::num_rows($result) > 0) {
5545
        $id = Database::result($result, 0, 0);
5546
        if (false === $id) {
5547
            return -1;
5548
        }
5549
5550
        return (int) $id;
5551
    }
5552
5553
    $id = 1;
5554
5555
    //if the url in WEB_PATH was not found, it can only mean that there is
5556
    // either a configuration problem or the first URL has not been defined yet
5557
    // (by default it is http://localhost/). Thus the more sensible thing we can
5558
    // do is return 1 (the main URL) as the user cannot hack this value anyway
5559
    return 1;
5560
}
5561
5562
/**
5563
 * Gets the registered urls from a given user id.
5564
 *
5565
 * @author Julio Montoya <[email protected]>
5566
 *
5567
 * @param int $user_id
5568
 *
5569
 * @return array
5570
 */
5571
function api_get_access_url_from_user($user_id)
5572
{
5573
    $user_id = (int) $user_id;
5574
    $table_url_rel_user = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_USER);
5575
    $table_url = Database::get_main_table(TABLE_MAIN_ACCESS_URL);
5576
    $sql = "SELECT access_url_id
5577
            FROM $table_url_rel_user url_rel_user
5578
            INNER JOIN $table_url u
5579
            ON (url_rel_user.access_url_id = u.id)
5580
            WHERE user_id = ".$user_id;
5581
    $result = Database::query($sql);
5582
    $list = [];
5583
    while ($row = Database::fetch_array($result, 'ASSOC')) {
5584
        $list[] = $row['access_url_id'];
5585
    }
5586
5587
    return $list;
5588
}
5589
5590
/**
5591
 * Checks whether the curent user is in a group or not.
5592
 *
5593
 * @param string        The group id - optional (takes it from session if not given)
5594
 * @param string        The course code - optional (no additional check by course if course code is not given)
5595
 *
5596
 * @return bool
5597
 *
5598
 * @author Ivan Tcholakov
5599
 */
5600
function api_is_in_group($groupIdParam = null, $courseCodeParam = null)
5601
{
5602
    if (!empty($courseCodeParam)) {
5603
        $courseCode = api_get_course_id();
5604
        if (!empty($courseCode)) {
5605
            if ($courseCodeParam != $courseCode) {
5606
                return false;
5607
            }
5608
        } else {
5609
            return false;
5610
        }
5611
    }
5612
5613
    $groupId = api_get_group_id();
5614
5615
    if (isset($groupId) && '' != $groupId) {
5616
        if (!empty($groupIdParam)) {
5617
            return $groupIdParam == $groupId;
5618
        } else {
5619
            return true;
5620
        }
5621
    }
5622
5623
    return false;
5624
}
5625
5626
/**
5627
 * Checks whether a secret key is valid.
5628
 *
5629
 * @param string $original_key_secret - secret key from (webservice) client
5630
 * @param string $security_key        - security key from Chamilo
5631
 *
5632
 * @return bool - true if secret key is valid, false otherwise
5633
 */
5634
function api_is_valid_secret_key($original_key_secret, $security_key)
5635
{
5636
    return $original_key_secret == sha1($security_key);
5637
}
5638
5639
/**
5640
 * Checks whether a user is into course.
5641
 *
5642
 * @param int $course_id - the course id
5643
 * @param int $user_id   - the user id
5644
 *
5645
 * @return bool
5646
 */
5647
function api_is_user_of_course($course_id, $user_id)
5648
{
5649
    $tbl_course_rel_user = Database::get_main_table(TABLE_MAIN_COURSE_USER);
5650
    $sql = 'SELECT user_id FROM '.$tbl_course_rel_user.'
5651
            WHERE
5652
                c_id ="'.intval($course_id).'" AND
5653
                user_id = "'.intval($user_id).'" AND
5654
                relation_type <> '.COURSE_RELATION_TYPE_RRHH.' ';
5655
    $result = Database::query($sql);
5656
5657
    return 1 == Database::num_rows($result);
5658
}
5659
5660
/**
5661
 * Checks whether the server's operating system is Windows (TM).
5662
 *
5663
 * @return bool - true if the operating system is Windows, false otherwise
5664
 */
5665
function api_is_windows_os()
5666
{
5667
    if (function_exists('php_uname')) {
5668
        // php_uname() exists as of PHP 4.0.2, according to the documentation.
5669
        // We expect that this function will always work for Chamilo 1.8.x.
5670
        $os = php_uname();
5671
    }
5672
    // The following methods are not needed, but let them stay, just in case.
5673
    elseif (isset($_ENV['OS'])) {
5674
        // Sometimes $_ENV['OS'] may not be present (bugs?)
5675
        $os = $_ENV['OS'];
5676
    } elseif (defined('PHP_OS')) {
5677
        // PHP_OS means on which OS PHP was compiled, this is why
5678
        // using PHP_OS is the last choice for detection.
5679
        $os = PHP_OS;
5680
    } else {
5681
        return false;
5682
    }
5683
5684
    return 'win' == strtolower(substr((string) $os, 0, 3));
5685
}
5686
5687
/**
5688
 * This function informs whether the sent request is XMLHttpRequest.
5689
 */
5690
function api_is_xml_http_request()
5691
{
5692
    return isset($_SERVER['HTTP_X_REQUESTED_WITH']) && 'xmlhttprequest' == strtolower($_SERVER['HTTP_X_REQUESTED_WITH']);
5693
}
5694
5695
/**
5696
 * This wrapper function has been implemented for avoiding some known problems about the function getimagesize().
5697
 *
5698
 * @see http://php.net/manual/en/function.getimagesize.php
5699
 * @see http://www.dokeos.com/forum/viewtopic.php?t=12345
5700
 * @see http://www.dokeos.com/forum/viewtopic.php?t=16355
5701
 *
5702
 * @return int
5703
 */
5704
function api_getimagesize($path)
5705
{
5706
    $image = new Image($path);
0 ignored issues
show
Deprecated Code introduced by
The class Image has been deprecated. ( Ignorable by Annotation )

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

5706
    $image = /** @scrutinizer ignore-deprecated */ new Image($path);
Loading history...
5707
5708
    return $image->get_image_size();
5709
}
5710
5711
/**
5712
 * This function resizes an image, with preserving its proportions (or aspect ratio).
5713
 *
5714
 * @author Ivan Tcholakov, MAY-2009.
5715
 *
5716
 * @param int $image         System path or URL of the image
5717
 * @param int $target_width  Targeted width
5718
 * @param int $target_height Targeted height
5719
 *
5720
 * @return array Calculated new width and height
5721
 */
5722
function api_resize_image($image, $target_width, $target_height)
5723
{
5724
    $image_properties = api_getimagesize($image);
5725
5726
    return api_calculate_image_size(
5727
        $image_properties['width'],
5728
        $image_properties['height'],
5729
        $target_width,
5730
        $target_height
5731
    );
5732
}
5733
5734
/**
5735
 * This function calculates new image size, with preserving image's proportions (or aspect ratio).
5736
 *
5737
 * @author Ivan Tcholakov, MAY-2009.
5738
 * @author The initial idea has been taken from code by Patrick Cool, MAY-2004.
5739
 *
5740
 * @param int $image_width   Initial width
5741
 * @param int $image_height  Initial height
5742
 * @param int $target_width  Targeted width
5743
 * @param int $target_height Targeted height
5744
 *
5745
 * @return array Calculated new width and height
5746
 */
5747
function api_calculate_image_size(
5748
    $image_width,
5749
    $image_height,
5750
    $target_width,
5751
    $target_height
5752
) {
5753
    // Only maths is here.
5754
    $result = ['width' => $image_width, 'height' => $image_height];
5755
    if ($image_width <= 0 || $image_height <= 0) {
5756
        return $result;
5757
    }
5758
    $resize_factor_width = $target_width / $image_width;
5759
    $resize_factor_height = $target_height / $image_height;
5760
    $delta_width = $target_width - $image_width * $resize_factor_height;
5761
    $delta_height = $target_height - $image_height * $resize_factor_width;
5762
    if ($delta_width > $delta_height) {
5763
        $result['width'] = ceil($image_width * $resize_factor_height);
5764
        $result['height'] = ceil($image_height * $resize_factor_height);
5765
    } elseif ($delta_width < $delta_height) {
5766
        $result['width'] = ceil($image_width * $resize_factor_width);
5767
        $result['height'] = ceil($image_height * $resize_factor_width);
5768
    } else {
5769
        $result['width'] = ceil($target_width);
5770
        $result['height'] = ceil($target_height);
5771
    }
5772
5773
    return $result;
5774
}
5775
5776
/**
5777
 * Returns a list of Chamilo's tools or
5778
 * checks whether a given identificator is a valid Chamilo's tool.
5779
 *
5780
 * @author Isaac flores paz
5781
 *
5782
 * @param string The tool name to filter
5783
 *
5784
 * @return mixed Filtered string or array
5785
 */
5786
function api_get_tools_lists($my_tool = null)
5787
{
5788
    $tools_list = [
5789
        TOOL_DOCUMENT,
5790
        TOOL_THUMBNAIL,
5791
        TOOL_HOTPOTATOES,
5792
        TOOL_CALENDAR_EVENT,
5793
        TOOL_LINK,
5794
        TOOL_COURSE_DESCRIPTION,
5795
        TOOL_SEARCH,
5796
        TOOL_LEARNPATH,
5797
        TOOL_ANNOUNCEMENT,
5798
        TOOL_FORUM,
5799
        TOOL_THREAD,
5800
        TOOL_POST,
5801
        TOOL_DROPBOX,
5802
        TOOL_QUIZ,
5803
        TOOL_USER,
5804
        TOOL_GROUP,
5805
        TOOL_BLOGS,
5806
        TOOL_CHAT,
5807
        TOOL_STUDENTPUBLICATION,
5808
        TOOL_TRACKING,
5809
        TOOL_HOMEPAGE_LINK,
5810
        TOOL_COURSE_SETTING,
5811
        TOOL_BACKUP,
5812
        TOOL_COPY_COURSE_CONTENT,
5813
        TOOL_RECYCLE_COURSE,
5814
        TOOL_COURSE_HOMEPAGE,
5815
        TOOL_COURSE_RIGHTS_OVERVIEW,
5816
        TOOL_UPLOAD,
5817
        TOOL_COURSE_MAINTENANCE,
5818
        TOOL_SURVEY,
5819
        TOOL_WIKI,
5820
        TOOL_GLOSSARY,
5821
        TOOL_GRADEBOOK,
5822
        TOOL_NOTEBOOK,
5823
        TOOL_ATTENDANCE,
5824
        TOOL_COURSE_PROGRESS,
5825
    ];
5826
    if (empty($my_tool)) {
5827
        return $tools_list;
5828
    }
5829
5830
    return in_array($my_tool, $tools_list) ? $my_tool : '';
5831
}
5832
5833
/**
5834
 * Checks whether we already approved the last version term and condition.
5835
 *
5836
 * @param int user id
5837
 *
5838
 * @return bool true if we pass false otherwise
5839
 */
5840
function api_check_term_condition($userId)
5841
{
5842
    if ('true' === api_get_setting('allow_terms_conditions')) {
5843
        // Check if exists terms and conditions
5844
        if (0 == LegalManager::count()) {
5845
            return true;
5846
        }
5847
5848
        $extraFieldValue = new ExtraFieldValue('user');
5849
        $data = $extraFieldValue->get_values_by_handler_and_field_variable(
5850
            $userId,
5851
            'legal_accept'
5852
        );
5853
5854
        if (!empty($data) && isset($data['value']) && !empty($data['value'])) {
5855
            $result = $data['value'];
5856
            $user_conditions = explode(':', $result);
5857
            $version = $user_conditions[0];
5858
            $langId = $user_conditions[1];
5859
            $realVersion = LegalManager::get_last_version($langId);
5860
5861
            return $version >= $realVersion;
5862
        }
5863
5864
        return false;
5865
    }
5866
5867
    return false;
5868
}
5869
5870
/**
5871
 * Gets all information of a tool into course.
5872
 *
5873
 * @param int The tool id
5874
 *
5875
 * @return array
5876
 */
5877
function api_get_tool_information_by_name($name)
5878
{
5879
    $t_tool = Database::get_course_table(TABLE_TOOL_LIST);
5880
    $course_id = api_get_course_int_id();
5881
5882
    $sql = "SELECT id FROM tool
5883
            WHERE name = '".Database::escape_string($name)."' ";
5884
    $rs = Database::query($sql);
5885
    $data = Database::fetch_array($rs);
5886
    $tool = $data['id'];
5887
5888
    $sql = "SELECT * FROM $t_tool
5889
            WHERE c_id = $course_id  AND tool_id = '".$tool."' ";
5890
    $rs = Database::query($sql);
5891
5892
    return Database::fetch_array($rs, 'ASSOC');
5893
}
5894
5895
/**
5896
 * Function used to protect a "global" admin script.
5897
 * The function blocks access when the user has no global platform admin rights.
5898
 * Global admins are the admins that are registered in the main.admin table
5899
 * AND the users who have access to the "principal" portal.
5900
 * That means that there is a record in the main.access_url_rel_user table
5901
 * with his user id and the access_url_id=1.
5902
 *
5903
 * @author Julio Montoya
5904
 *
5905
 * @param int $user_id
5906
 *
5907
 * @return bool
5908
 */
5909
function api_is_global_platform_admin($user_id = null)
5910
{
5911
    $user_id = (int) $user_id;
5912
    if (empty($user_id)) {
5913
        $user_id = api_get_user_id();
5914
    }
5915
    if (api_is_platform_admin_by_id($user_id)) {
5916
        $urlList = api_get_access_url_from_user($user_id);
5917
        // The admin is registered in the first "main" site with access_url_id = 1
5918
        if (in_array(1, $urlList)) {
5919
            return true;
5920
        } else {
5921
            return false;
5922
        }
5923
    }
5924
5925
    return false;
5926
}
5927
5928
/**
5929
 * @param int  $admin_id_to_check
5930
 * @param int  $my_user_id
5931
 * @param bool $allow_session_admin
5932
 *
5933
 * @return bool
5934
 */
5935
function api_global_admin_can_edit_admin(
5936
    $admin_id_to_check,
5937
    $my_user_id = null,
5938
    $allow_session_admin = false
5939
) {
5940
    if (empty($my_user_id)) {
5941
        $my_user_id = api_get_user_id();
5942
    }
5943
5944
    $iam_a_global_admin = api_is_global_platform_admin($my_user_id);
5945
    $user_is_global_admin = api_is_global_platform_admin($admin_id_to_check);
5946
5947
    if ($iam_a_global_admin) {
5948
        // Global admin can edit everything
5949
        return true;
5950
    } else {
5951
        // If i'm a simple admin
5952
        $is_platform_admin = api_is_platform_admin_by_id($my_user_id);
5953
5954
        if ($allow_session_admin) {
5955
            $is_platform_admin = api_is_platform_admin_by_id($my_user_id) || (SESSIONADMIN == api_get_user_status($my_user_id));
5956
        }
5957
5958
        if ($is_platform_admin) {
5959
            if ($user_is_global_admin) {
5960
                return false;
5961
            } else {
5962
                return true;
5963
            }
5964
        } else {
5965
            return false;
5966
        }
5967
    }
5968
}
5969
5970
/**
5971
 * @param int  $admin_id_to_check
5972
 * @param int  $my_user_id
5973
 * @param bool $allow_session_admin
5974
 *
5975
 * @return bool|null
5976
 */
5977
function api_protect_super_admin($admin_id_to_check, $my_user_id = null, $allow_session_admin = false)
5978
{
5979
    if (api_global_admin_can_edit_admin($admin_id_to_check, $my_user_id, $allow_session_admin)) {
5980
        return true;
5981
    } else {
5982
        api_not_allowed();
5983
    }
5984
}
5985
5986
/**
5987
 * Function used to protect a global admin script.
5988
 * The function blocks access when the user has no global platform admin rights.
5989
 * See also the api_is_global_platform_admin() function wich defines who's a "global" admin.
5990
 *
5991
 * @author Julio Montoya
5992
 */
5993
function api_protect_global_admin_script()
5994
{
5995
    if (!api_is_global_platform_admin()) {
5996
        api_not_allowed();
5997
5998
        return false;
5999
    }
6000
6001
    return true;
6002
}
6003
6004
/**
6005
 * Check browser support for specific file types or features
6006
 * This function checks if the user's browser supports a file format or given
6007
 * feature, or returns the current browser and major version when
6008
 * $format=check_browser. Only a limited number of formats and features are
6009
 * checked by this method. Make sure you check its definition first.
6010
 *
6011
 * @param string $format Can be a file format (extension like svg, webm, ...) or a feature (like autocapitalize, ...)
6012
 *
6013
 * @deprecated
6014
 *
6015
 * @return bool or return text array if $format=check_browser
6016
 *
6017
 * @author Juan Carlos Raña Trabado
6018
 */
6019
function api_browser_support($format = '')
6020
{
6021
    return true;
6022
6023
    $browser = new Browser();
0 ignored issues
show
Unused Code introduced by
$browser = new Browser() is not reachable.

This check looks for unreachable code. It uses sophisticated control flow analysis techniques to find statements which will never be executed.

Unreachable code is most often the result of return, die or exit statements that have been added for debug purposes.

function fx() {
    try {
        doSomething();
        return true;
    }
    catch (\Exception $e) {
        return false;
    }

    return false;
}

In the above example, the last return false will never be executed, because a return statement has already been met in every possible execution path.

Loading history...
6024
    $current_browser = $browser->getBrowser();
6025
    $a_versiontemp = explode('.', $browser->getVersion());
6026
    $current_majorver = $a_versiontemp[0];
6027
6028
    static $result;
6029
6030
    if (isset($result[$format])) {
6031
        return $result[$format];
6032
    }
6033
6034
    // Native svg support
6035
    if ('svg' == $format) {
6036
        if (('Internet Explorer' == $current_browser && $current_majorver >= 9) ||
6037
            ('Firefox' == $current_browser && $current_majorver > 1) ||
6038
            ('Safari' == $current_browser && $current_majorver >= 4) ||
6039
            ('Chrome' == $current_browser && $current_majorver >= 1) ||
6040
            ('Opera' == $current_browser && $current_majorver >= 9)
6041
        ) {
6042
            $result[$format] = true;
6043
6044
            return true;
6045
        } else {
6046
            $result[$format] = false;
6047
6048
            return false;
6049
        }
6050
    } elseif ('pdf' == $format) {
6051
        // native pdf support
6052
        if ('Chrome' == $current_browser && $current_majorver >= 6) {
6053
            $result[$format] = true;
6054
6055
            return true;
6056
        } else {
6057
            $result[$format] = false;
6058
6059
            return false;
6060
        }
6061
    } elseif ('tif' == $format || 'tiff' == $format) {
6062
        //native tif support
6063
        if ('Safari' == $current_browser && $current_majorver >= 5) {
6064
            $result[$format] = true;
6065
6066
            return true;
6067
        } else {
6068
            $result[$format] = false;
6069
6070
            return false;
6071
        }
6072
    } elseif ('ogg' == $format || 'ogx' == $format || 'ogv' == $format || 'oga' == $format) {
6073
        //native ogg, ogv,oga support
6074
        if (('Firefox' == $current_browser && $current_majorver >= 3) ||
6075
            ('Chrome' == $current_browser && $current_majorver >= 3) ||
6076
            ('Opera' == $current_browser && $current_majorver >= 9)) {
6077
            $result[$format] = true;
6078
6079
            return true;
6080
        } else {
6081
            $result[$format] = false;
6082
6083
            return false;
6084
        }
6085
    } elseif ('mpg' == $format || 'mpeg' == $format) {
6086
        //native mpg support
6087
        if (('Safari' == $current_browser && $current_majorver >= 5)) {
6088
            $result[$format] = true;
6089
6090
            return true;
6091
        } else {
6092
            $result[$format] = false;
6093
6094
            return false;
6095
        }
6096
    } elseif ('mp4' == $format) {
6097
        //native mp4 support (TODO: Android, iPhone)
6098
        if ('Android' == $current_browser || 'iPhone' == $current_browser) {
6099
            $result[$format] = true;
6100
6101
            return true;
6102
        } else {
6103
            $result[$format] = false;
6104
6105
            return false;
6106
        }
6107
    } elseif ('mov' == $format) {
6108
        //native mov support( TODO:check iPhone)
6109
        if ('Safari' == $current_browser && $current_majorver >= 5 || 'iPhone' == $current_browser) {
0 ignored issues
show
introduced by
Consider adding parentheses for clarity. Current Interpretation: ('Safari' == $current_br...ne' == $current_browser, Probably Intended Meaning: 'Safari' == $current_bro...e' == $current_browser)
Loading history...
6110
            $result[$format] = true;
6111
6112
            return true;
6113
        } else {
6114
            $result[$format] = false;
6115
6116
            return false;
6117
        }
6118
    } elseif ('avi' == $format) {
6119
        //native avi support
6120
        if ('Safari' == $current_browser && $current_majorver >= 5) {
6121
            $result[$format] = true;
6122
6123
            return true;
6124
        } else {
6125
            $result[$format] = false;
6126
6127
            return false;
6128
        }
6129
    } elseif ('wmv' == $format) {
6130
        //native wmv support
6131
        if ('Firefox' == $current_browser && $current_majorver >= 4) {
6132
            $result[$format] = true;
6133
6134
            return true;
6135
        } else {
6136
            $result[$format] = false;
6137
6138
            return false;
6139
        }
6140
    } elseif ('webm' == $format) {
6141
        //native webm support (TODO:check IE9, Chrome9, Android)
6142
        if (('Firefox' == $current_browser && $current_majorver >= 4) ||
6143
            ('Opera' == $current_browser && $current_majorver >= 9) ||
6144
            ('Internet Explorer' == $current_browser && $current_majorver >= 9) ||
6145
            ('Chrome' == $current_browser && $current_majorver >= 9) ||
6146
            'Android' == $current_browser
6147
        ) {
6148
            $result[$format] = true;
6149
6150
            return true;
6151
        } else {
6152
            $result[$format] = false;
6153
6154
            return false;
6155
        }
6156
    } elseif ('wav' == $format) {
6157
        //native wav support (only some codecs !)
6158
        if (('Firefox' == $current_browser && $current_majorver >= 4) ||
6159
            ('Safari' == $current_browser && $current_majorver >= 5) ||
6160
            ('Opera' == $current_browser && $current_majorver >= 9) ||
6161
            ('Internet Explorer' == $current_browser && $current_majorver >= 9) ||
6162
            ('Chrome' == $current_browser && $current_majorver > 9) ||
6163
            'Android' == $current_browser ||
6164
            'iPhone' == $current_browser
6165
        ) {
6166
            $result[$format] = true;
6167
6168
            return true;
6169
        } else {
6170
            $result[$format] = false;
6171
6172
            return false;
6173
        }
6174
    } elseif ('mid' == $format || 'kar' == $format) {
6175
        //native midi support (TODO:check Android)
6176
        if ('Opera' == $current_browser && $current_majorver >= 9 || 'Android' == $current_browser) {
0 ignored issues
show
introduced by
Consider adding parentheses for clarity. Current Interpretation: ('Opera' == $current_bro...id' == $current_browser, Probably Intended Meaning: 'Opera' == $current_brow...d' == $current_browser)
Loading history...
6177
            $result[$format] = true;
6178
6179
            return true;
6180
        } else {
6181
            $result[$format] = false;
6182
6183
            return false;
6184
        }
6185
    } elseif ('wma' == $format) {
6186
        //native wma support
6187
        if ('Firefox' == $current_browser && $current_majorver >= 4) {
6188
            $result[$format] = true;
6189
6190
            return true;
6191
        } else {
6192
            $result[$format] = false;
6193
6194
            return false;
6195
        }
6196
    } elseif ('au' == $format) {
6197
        //native au support
6198
        if ('Safari' == $current_browser && $current_majorver >= 5) {
6199
            $result[$format] = true;
6200
6201
            return true;
6202
        } else {
6203
            $result[$format] = false;
6204
6205
            return false;
6206
        }
6207
    } elseif ('mp3' == $format) {
6208
        //native mp3 support (TODO:check Android, iPhone)
6209
        if (('Safari' == $current_browser && $current_majorver >= 5) ||
6210
            ('Chrome' == $current_browser && $current_majorver >= 6) ||
6211
            ('Internet Explorer' == $current_browser && $current_majorver >= 9) ||
6212
            'Android' == $current_browser ||
6213
            'iPhone' == $current_browser ||
6214
            'Firefox' == $current_browser
6215
        ) {
6216
            $result[$format] = true;
6217
6218
            return true;
6219
        } else {
6220
            $result[$format] = false;
6221
6222
            return false;
6223
        }
6224
    } elseif ('autocapitalize' == $format) {
6225
        // Help avoiding showing the autocapitalize option if the browser doesn't
6226
        // support it: this attribute is against the HTML5 standard
6227
        if ('Safari' == $current_browser || 'iPhone' == $current_browser) {
6228
            return true;
6229
        } else {
6230
            return false;
6231
        }
6232
    } elseif ("check_browser" == $format) {
6233
        $array_check_browser = [$current_browser, $current_majorver];
6234
6235
        return $array_check_browser;
6236
    } else {
6237
        $result[$format] = false;
6238
6239
        return false;
6240
    }
6241
}
6242
6243
/**
6244
 * This function checks if exist path and file browscap.ini
6245
 * In order for this to work, your browscap configuration setting in php.ini
6246
 * must point to the correct location of the browscap.ini file on your system
6247
 * http://php.net/manual/en/function.get-browser.php.
6248
 *
6249
 * @return bool
6250
 *
6251
 * @author Juan Carlos Raña Trabado
6252
 */
6253
function api_check_browscap()
6254
{
6255
    $setting = ini_get('browscap');
6256
    if ($setting) {
6257
        $browser = get_browser($_SERVER['HTTP_USER_AGENT'], true);
6258
        if (strpos($setting, 'browscap.ini') && !empty($browser)) {
6259
            return true;
6260
        }
6261
    }
6262
6263
    return false;
6264
}
6265
6266
/**
6267
 * Returns the <script> HTML tag.
6268
 */
6269
function api_get_js($file)
6270
{
6271
    return '<script type="text/javascript" src="'.api_get_path(WEB_LIBRARY_PATH).'javascript/'.$file.'"></script>'."\n";
6272
}
6273
6274
function api_get_build_js($file)
6275
{
6276
    return '<script type="text/javascript" src="'.api_get_path(WEB_PUBLIC_PATH).'build/'.$file.'"></script>'."\n";
6277
}
6278
6279
function api_get_build_css($file, $media = 'screen')
6280
{
6281
    return '<link
6282
        href="'.api_get_path(WEB_PUBLIC_PATH).'build/'.$file.'" rel="stylesheet" media="'.$media.'" type="text/css" />'."\n";
6283
}
6284
6285
/**
6286
 * Returns the <script> HTML tag.
6287
 *
6288
 * @return string
6289
 */
6290
function api_get_asset($file)
6291
{
6292
    return '<script type="text/javascript" src="'.api_get_path(WEB_PUBLIC_PATH).'build/libs/'.$file.'"></script>'."\n";
6293
}
6294
6295
/**
6296
 * Returns the <script> HTML tag.
6297
 *
6298
 * @param string $file
6299
 * @param string $media
6300
 *
6301
 * @return string
6302
 */
6303
function api_get_css_asset($file, $media = 'screen')
6304
{
6305
    return '<link href="'.api_get_path(WEB_PUBLIC_PATH).'build/libs/'.$file.'" rel="stylesheet" media="'.$media.'" type="text/css" />'."\n";
6306
}
6307
6308
/**
6309
 * Returns the <link> HTML tag.
6310
 *
6311
 * @param string $file
6312
 * @param string $media
6313
 */
6314
function api_get_css($file, $media = 'screen')
6315
{
6316
    return '<link href="'.$file.'" rel="stylesheet" media="'.$media.'" type="text/css" />'."\n";
6317
}
6318
6319
function api_get_bootstrap_and_font_awesome($returnOnlyPath = false)
6320
{
6321
    $url = api_get_path(WEB_PUBLIC_PATH).'build/css/bootstrap.css';
6322
    if ($returnOnlyPath) {
6323
        return $url;
6324
    }
6325
6326
    return '<link href="'.$url.'" rel="stylesheet" type="text/css" />'."\n";
6327
}
6328
6329
/**
6330
 * Returns the js header to include the jquery library.
6331
 */
6332
function api_get_jquery_js()
6333
{
6334
    return api_get_asset('jquery/jquery.min.js');
6335
}
6336
6337
/**
6338
 * Returns the jquery path.
6339
 *
6340
 * @return string
6341
 */
6342
function api_get_jquery_web_path()
6343
{
6344
    return api_get_path(WEB_PUBLIC_PATH).'assets/jquery/jquery.min.js';
6345
}
6346
6347
/**
6348
 * @return string
6349
 */
6350
function api_get_jquery_ui_js_web_path()
6351
{
6352
    return api_get_path(WEB_PUBLIC_PATH).'assets/jquery-ui/jquery-ui.min.js';
6353
}
6354
6355
/**
6356
 * @return string
6357
 */
6358
function api_get_jquery_ui_css_web_path()
6359
{
6360
    return api_get_path(WEB_PUBLIC_PATH).'assets/jquery-ui/themes/smoothness/jquery-ui.min.css';
6361
}
6362
6363
/**
6364
 * Returns the jquery-ui library js headers.
6365
 *
6366
 * @return string html tags
6367
 */
6368
function api_get_jquery_ui_js()
6369
{
6370
    $libraries = [];
6371
6372
    return api_get_jquery_libraries_js($libraries);
6373
}
6374
6375
function api_get_jqgrid_js()
6376
{
6377
    $routePublic = Container::getRouter()->generate('home');
6378
6379
    return api_get_css($routePublic.'build/free-jqgrid.css').PHP_EOL
6380
        .api_get_js_simple($routePublic.'build/free-jqgrid.js');
6381
}
6382
6383
/**
6384
 * Returns the jquery library js and css headers.
6385
 *
6386
 * @param   array   list of jquery libraries supported jquery-ui
6387
 * @param   bool    add the jquery library
6388
 *
6389
 * @return string html tags
6390
 */
6391
function api_get_jquery_libraries_js($libraries)
6392
{
6393
    $js = '';
6394
6395
    //Document multiple upload funcionality
6396
    if (in_array('jquery-uploadzs', $libraries)) {
6397
        $js .= api_get_asset('blueimp-load-image/js/load-image.all.min.js');
6398
        $js .= api_get_asset('blueimp-canvas-to-blob/js/canvas-to-blob.min.js');
6399
        $js .= api_get_asset('jquery-file-upload/js/jquery.iframe-transport.js');
6400
        $js .= api_get_asset('jquery-file-upload/js/jquery.fileupload.js');
6401
        $js .= api_get_asset('jquery-file-upload/js/jquery.fileupload-process.js');
6402
        $js .= api_get_asset('jquery-file-upload/js/jquery.fileupload-image.js');
6403
        $js .= api_get_asset('jquery-file-upload/js/jquery.fileupload-audio.js');
6404
        $js .= api_get_asset('jquery-file-upload/js/jquery.fileupload-video.js');
6405
        $js .= api_get_asset('jquery-file-upload/js/jquery.fileupload-validate.js');
6406
6407
        $js .= api_get_css(api_get_path(WEB_PUBLIC_PATH).'assets/jquery-file-upload/css/jquery.fileupload.css');
6408
        $js .= api_get_css(api_get_path(WEB_PUBLIC_PATH).'assets/jquery-file-upload/css/jquery.fileupload-ui.css');
6409
    }
6410
6411
    // jquery datepicker
6412
    if (in_array('datepicker', $libraries)) {
6413
        $languaje = 'en-GB';
6414
        $platform_isocode = strtolower(api_get_language_isocode());
6415
6416
        $datapicker_langs = [
6417
            'af', 'ar', 'ar-DZ', 'az', 'bg', 'bs', 'ca', 'cs', 'cy-GB', 'da', 'de', 'el', 'en-AU', 'en-GB', 'en-NZ', 'eo', 'es', 'et', 'eu', 'fa', 'fi', 'fo', 'fr', 'fr-CH', 'gl', 'he', 'hi', 'hr', 'hu', 'hy', 'id', 'is', 'it', 'ja', 'ka', 'kk', 'km', 'ko', 'lb', 'lt', 'lv', 'mk', 'ml', 'ms', 'nl', 'nl-BE', 'no', 'pl', 'pt', 'pt-BR', 'rm', 'ro', 'ru', 'sk', 'sl', 'sq', 'sr', 'sr-SR', 'sv', 'ta', 'th', 'tj', 'tr', 'uk', 'vi', 'zh-CN', 'zh-HK', 'zh-TW',
6418
        ];
6419
        if (in_array($platform_isocode, $datapicker_langs)) {
6420
            $languaje = $platform_isocode;
6421
        }
6422
6423
        $js .= api_get_js('jquery-ui/jquery-ui-i18n.min.js');
6424
        $script = '<script>
6425
        $(function(){
6426
            $.datepicker.setDefaults($.datepicker.regional["'.$languaje.'"]);
6427
            $.datepicker.regional["local"] = $.datepicker.regional["'.$languaje.'"];
6428
        });
6429
        </script>
6430
        ';
6431
        $js .= $script;
6432
    }
6433
6434
    return $js;
6435
}
6436
6437
/**
6438
 * Returns the URL to the course or session, removing the complexity of the URL
6439
 * building piece by piece.
6440
 *
6441
 * This function relies on api_get_course_info()
6442
 *
6443
 * @param string $courseCode The course code - optional (takes it from context if not given)
6444
 * @param int    $sessionId  The session ID  - optional (takes it from context if not given)
6445
 * @param int    $groupId    The group ID - optional (takes it from context if not given)
6446
 *
6447
 * @return string The URL to a course, a session, or empty string if nothing works
6448
 *                e.g. https://localhost/courses/ABC/index.php?session_id=3&gidReq=1
6449
 *
6450
 * @author  Julio Montoya <[email protected]>
6451
 */
6452
function api_get_course_url($courseCode = null, $sessionId = null, $groupId = null)
6453
{
6454
    $url = '';
6455
    // If courseCode not set, get context or []
6456
    if (empty($courseCode)) {
6457
        $courseInfo = api_get_course_info();
6458
    } else {
6459
        $courseInfo = api_get_course_info($courseCode);
6460
    }
6461
6462
    // If sessionId not set, get context or 0
6463
    if (empty($sessionId)) {
6464
        $sessionId = api_get_session_id();
6465
    }
6466
6467
    // If groupId not set, get context or 0
6468
    if (empty($groupId)) {
6469
        $groupId = api_get_group_id();
6470
    }
6471
6472
    // Build the URL
6473
    if (!empty($courseInfo)) {
6474
        // directory not empty, so we do have a course
6475
        $url = $courseInfo['course_public_url'].'?sid='.$sessionId.'&gid='.$groupId;
6476
    } else {
6477
        if (!empty($sessionId) && 'true' !== api_get_setting('session.remove_session_url')) {
6478
            // if the course was unset and the session was set, send directly to the session
6479
            $url = api_get_path(WEB_CODE_PATH).'session/index.php?session_id='.$sessionId;
6480
        }
6481
    }
6482
6483
    // if not valid combination was found, return an empty string
6484
    return $url;
6485
}
6486
6487
/**
6488
 * Check if the current portal has the $_configuration['multiple_access_urls'] parameter on.
6489
 *
6490
 * @return bool true if multi site is enabled
6491
 */
6492
function api_get_multiple_access_url()
6493
{
6494
    global $_configuration;
6495
    if (isset($_configuration['multiple_access_urls']) && $_configuration['multiple_access_urls']) {
6496
        return true;
6497
    }
6498
6499
    return false;
6500
}
6501
6502
/**
6503
 * @return bool
6504
 */
6505
function api_is_multiple_url_enabled()
6506
{
6507
    return api_get_multiple_access_url();
6508
}
6509
6510
/**
6511
 * Returns a md5 unique id.
6512
 *
6513
 * @todo add more parameters
6514
 */
6515
function api_get_unique_id()
6516
{
6517
    $id = md5(time().uniqid().api_get_user_id().api_get_course_id().api_get_session_id());
6518
6519
    return $id;
6520
}
6521
6522
/**
6523
 * @param int Course id
6524
 * @param int tool id: TOOL_QUIZ, TOOL_FORUM, TOOL_STUDENTPUBLICATION, TOOL_LEARNPATH
6525
 * @param int the item id (tool id, exercise id, lp id)
6526
 *
6527
 * @return bool
6528
 */
6529
function api_resource_is_locked_by_gradebook($item_id, $link_type, $course_code = null)
6530
{
6531
    if (api_is_platform_admin()) {
6532
        return false;
6533
    }
6534
    if ('true' == api_get_setting('gradebook_locking_enabled')) {
6535
        if (empty($course_code)) {
6536
            $course_code = api_get_course_id();
6537
        }
6538
        $table = Database::get_main_table(TABLE_MAIN_GRADEBOOK_LINK);
6539
        $item_id = (int) $item_id;
6540
        $link_type = (int) $link_type;
6541
        $course_code = Database::escape_string($course_code);
6542
        $sql = "SELECT locked FROM $table
6543
                WHERE locked = 1 AND ref_id = $item_id AND type = $link_type AND course_code = '$course_code' ";
6544
        $result = Database::query($sql);
6545
        if (Database::num_rows($result)) {
6546
            return true;
6547
        }
6548
    }
6549
6550
    return false;
6551
}
6552
6553
/**
6554
 * Blocks a page if the item was added in a gradebook.
6555
 *
6556
 * @param int       exercise id, work id, thread id,
6557
 * @param int       LINK_EXERCISE, LINK_STUDENTPUBLICATION, LINK_LEARNPATH LINK_FORUM_THREAD, LINK_ATTENDANCE
6558
 * see gradebook/lib/be/linkfactory
6559
 * @param string    course code
6560
 *
6561
 * @return false|null
6562
 */
6563
function api_block_course_item_locked_by_gradebook($item_id, $link_type, $course_code = null)
6564
{
6565
    if (api_is_platform_admin()) {
6566
        return false;
6567
    }
6568
6569
    if (api_resource_is_locked_by_gradebook($item_id, $link_type, $course_code)) {
6570
        $message = Display::return_message(get_lang('This option is not available because this activity is contained by an assessment, which is currently locked. To unlock the assessment, ask your platform administrator.'), 'warning');
6571
        api_not_allowed(true, $message);
6572
    }
6573
}
6574
6575
/**
6576
 * Checks the PHP version installed is enough to run Chamilo.
6577
 *
6578
 * @param string Include path (used to load the error page)
6579
 */
6580
function api_check_php_version()
6581
{
6582
    if (!function_exists('version_compare') ||
6583
        version_compare(phpversion(), REQUIRED_PHP_VERSION, '<')
6584
    ) {
6585
        throw new Exception('Wrong PHP version');
6586
    }
6587
}
6588
6589
/**
6590
 * Checks whether the Archive directory is present and writeable. If not,
6591
 * prints a warning message.
6592
 */
6593
function api_check_archive_dir()
6594
{
6595
    if (is_dir(api_get_path(SYS_ARCHIVE_PATH)) && !is_writable(api_get_path(SYS_ARCHIVE_PATH))) {
6596
        $message = Display::return_message(get_lang('The app/cache/ directory, used by this tool, is not writeable. Please contact your platform administrator.'), 'warning');
6597
        api_not_allowed(true, $message);
6598
    }
6599
}
6600
6601
/**
6602
 * Returns an array of global configuration settings which should be ignored
6603
 * when printing the configuration settings screens.
6604
 *
6605
 * @return array Array of strings, each identifying one of the excluded settings
6606
 */
6607
function api_get_locked_settings()
6608
{
6609
    return [
6610
        'permanently_remove_deleted_files',
6611
        'account_valid_duration',
6612
        'service_ppt2lp',
6613
        'wcag_anysurfer_public_pages',
6614
        'upload_extensions_list_type',
6615
        'upload_extensions_blacklist',
6616
        'upload_extensions_whitelist',
6617
        'upload_extensions_skip',
6618
        'upload_extensions_replace_by',
6619
        'hide_dltt_markup',
6620
        'split_users_upload_directory',
6621
        'permissions_for_new_directories',
6622
        'permissions_for_new_files',
6623
        'platform_charset',
6624
        'ldap_description',
6625
        'cas_activate',
6626
        'cas_server',
6627
        'cas_server_uri',
6628
        'cas_port',
6629
        'cas_protocol',
6630
        'cas_add_user_activate',
6631
        'update_user_info_cas_with_ldap',
6632
        'languagePriority1',
6633
        'languagePriority2',
6634
        'languagePriority3',
6635
        'languagePriority4',
6636
        'login_is_email',
6637
        'chamilo_database_version',
6638
    ];
6639
}
6640
6641
/**
6642
 * Guess the real ip for register in the database, even in reverse proxy cases.
6643
 * To be recognized, the IP has to be found in either $_SERVER['REMOTE_ADDR'] or
6644
 * in $_SERVER['HTTP_X_FORWARDED_FOR'], which is in common use with rproxies.
6645
 * Note: the result of this function is not SQL-safe. Please escape it before
6646
 * inserting in a database.
6647
 *
6648
 * @return string the user's real ip (unsafe - escape it before inserting to db)
6649
 *
6650
 * @author Jorge Frisancho Jibaja <[email protected]>, USIL - Some changes to allow the use of real IP using reverse proxy
6651
 *
6652
 * @version CEV CHANGE 24APR2012
6653
 */
6654
function api_get_real_ip()
6655
{
6656
    $ip = trim($_SERVER['REMOTE_ADDR']);
6657
    if (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) {
6658
        if (preg_match('/,/', $_SERVER['HTTP_X_FORWARDED_FOR'])) {
6659
            @list($ip1, $ip2) = @explode(',', $_SERVER['HTTP_X_FORWARDED_FOR']);
6660
        } else {
6661
            $ip1 = $_SERVER['HTTP_X_FORWARDED_FOR'];
6662
        }
6663
        $ip = trim($ip1);
6664
    }
6665
6666
    return $ip;
6667
}
6668
6669
/**
6670
 * Checks whether an IP is included inside an IP range.
6671
 *
6672
 * @param string IP address
6673
 * @param string IP range
6674
 * @param string $ip
6675
 *
6676
 * @return bool True if IP is in the range, false otherwise
6677
 *
6678
 * @author claudiu at cnixs dot com  on http://www.php.net/manual/fr/ref.network.php#55230
6679
 * @author Yannick Warnier for improvements and managment of multiple ranges
6680
 *
6681
 * @todo check for IPv6 support
6682
 */
6683
function api_check_ip_in_range($ip, $range)
6684
{
6685
    if (empty($ip) or empty($range)) {
6686
        return false;
6687
    }
6688
    $ip_ip = ip2long($ip);
6689
    // divide range param into array of elements
6690
    if (false !== strpos($range, ',')) {
6691
        $ranges = explode(',', $range);
6692
    } else {
6693
        $ranges = [$range];
6694
    }
6695
    foreach ($ranges as $range) {
0 ignored issues
show
introduced by
$range is overwriting one of the parameters of this function.
Loading history...
6696
        $range = trim($range);
6697
        if (empty($range)) {
6698
            continue;
6699
        }
6700
        if (false === strpos($range, '/')) {
6701
            if (0 === strcmp($ip, $range)) {
6702
                return true; // there is a direct IP match, return OK
6703
            }
6704
            continue; //otherwise, get to the next range
6705
        }
6706
        // the range contains a "/", so analyse completely
6707
        [$net, $mask] = explode("/", $range);
6708
6709
        $ip_net = ip2long($net);
6710
        // mask binary magic
6711
        $ip_mask = ~((1 << (32 - $mask)) - 1);
6712
6713
        $ip_ip_net = $ip_ip & $ip_mask;
6714
        if ($ip_ip_net == $ip_net) {
6715
            return true;
6716
        }
6717
    }
6718
6719
    return false;
6720
}
6721
6722
function api_check_user_access_to_legal($course_visibility)
6723
{
6724
    $course_visibility_list = [COURSE_VISIBILITY_OPEN_WORLD, COURSE_VISIBILITY_OPEN_PLATFORM];
6725
6726
    return in_array($course_visibility, $course_visibility_list) || api_is_drh();
6727
}
6728
6729
/**
6730
 * Checks if the global chat is enabled or not.
6731
 *
6732
 * @return bool
6733
 */
6734
function api_is_global_chat_enabled()
6735
{
6736
    return
6737
        !api_is_anonymous() &&
6738
        'true' === api_get_setting('allow_global_chat') &&
6739
        'true' === api_get_setting('allow_social_tool');
6740
}
6741
6742
/**
6743
 * @param int   $item_id
6744
 * @param int   $tool_id
6745
 * @param int   $group_id   id
6746
 * @param array $courseInfo
6747
 * @param int   $sessionId
6748
 * @param int   $userId
6749
 *
6750
 * @deprecated
6751
 */
6752
function api_set_default_visibility(
6753
    $item_id,
6754
    $tool_id,
6755
    $group_id = 0,
6756
    $courseInfo = [],
6757
    $sessionId = 0,
6758
    $userId = 0
6759
) {
6760
    $courseInfo = empty($courseInfo) ? api_get_course_info() : $courseInfo;
6761
    $courseId = $courseInfo['real_id'];
6762
    $courseCode = $courseInfo['code'];
6763
    $sessionId = empty($sessionId) ? api_get_session_id() : $sessionId;
6764
    $userId = empty($userId) ? api_get_user_id() : $userId;
6765
6766
    // if group is null force group_id = 0, this force is needed to create a LP folder with group = 0
6767
    if (is_null($group_id)) {
6768
        $group_id = 0;
6769
    } else {
6770
        $group_id = empty($group_id) ? api_get_group_id() : $group_id;
6771
    }
6772
6773
    $groupInfo = [];
6774
    if (!empty($group_id)) {
6775
        $groupInfo = GroupManager::get_group_properties($group_id);
6776
    }
6777
    $original_tool_id = $tool_id;
6778
6779
    switch ($tool_id) {
6780
        case TOOL_LINK:
6781
        case TOOL_LINK_CATEGORY:
6782
            $tool_id = 'links';
6783
            break;
6784
        case TOOL_DOCUMENT:
6785
            $tool_id = 'documents';
6786
            break;
6787
        case TOOL_LEARNPATH:
6788
            $tool_id = 'learning';
6789
            break;
6790
        case TOOL_ANNOUNCEMENT:
6791
            $tool_id = 'announcements';
6792
            break;
6793
        case TOOL_FORUM:
6794
        case TOOL_FORUM_CATEGORY:
6795
        case TOOL_FORUM_THREAD:
6796
            $tool_id = 'forums';
6797
            break;
6798
        case TOOL_QUIZ:
6799
            $tool_id = 'quiz';
6800
            break;
6801
    }
6802
    $setting = api_get_setting('tool_visible_by_default_at_creation');
6803
6804
    if (isset($setting[$tool_id])) {
6805
        $visibility = 'invisible';
6806
        if ('true' == $setting[$tool_id]) {
6807
            $visibility = 'visible';
6808
        }
6809
6810
        // Read the portal and course default visibility
6811
        if ('documents' === $tool_id) {
6812
            $visibility = DocumentManager::getDocumentDefaultVisibility($courseInfo);
6813
        }
6814
6815
        // Fixes default visibility for tests
6816
        switch ($original_tool_id) {
6817
            case TOOL_QUIZ:
6818
                if (empty($sessionId)) {
6819
                    $objExerciseTmp = new Exercise($courseId);
6820
                    $objExerciseTmp->read($item_id);
6821
                    if ('visible' == $visibility) {
6822
                        $objExerciseTmp->enable();
6823
                        $objExerciseTmp->save();
6824
                    } else {
6825
                        $objExerciseTmp->disable();
6826
                        $objExerciseTmp->save();
6827
                    }
6828
                }
6829
                break;
6830
        }
6831
    }
6832
}
6833
6834
/**
6835
 * @return string
6836
 */
6837
function api_get_security_key()
6838
{
6839
    return api_get_configuration_value('security_key');
0 ignored issues
show
Bug Best Practice introduced by
The expression return api_get_configura...n_value('security_key') also could return the type boolean which is incompatible with the documented return type string.
Loading history...
6840
}
6841
6842
/**
6843
 * @param int $user_id
6844
 * @param int $courseId
6845
 * @param int $session_id
6846
 *
6847
 * @return array
6848
 */
6849
function api_detect_user_roles($user_id, $courseId, $session_id = 0)
6850
{
6851
    $user_roles = [];
6852
    $courseInfo = api_get_course_info_by_id($courseId);
6853
    $course_code = $courseInfo['code'];
6854
6855
    $url_id = api_get_current_access_url_id();
6856
    if (api_is_platform_admin_by_id($user_id, $url_id)) {
6857
        $user_roles[] = PLATFORM_ADMIN;
6858
    }
6859
6860
    /*if (api_is_drh()) {
6861
        $user_roles[] = DRH;
6862
    }*/
6863
6864
    if (!empty($session_id)) {
6865
        if (SessionManager::user_is_general_coach($user_id, $session_id)) {
6866
            $user_roles[] = SESSION_GENERAL_COACH;
6867
        }
6868
    }
6869
6870
    if (!empty($course_code)) {
6871
        if (empty($session_id)) {
6872
            if (CourseManager::isCourseTeacher($user_id, $courseInfo['real_id'])) {
6873
                $user_roles[] = COURSEMANAGER;
6874
            }
6875
            if (CourseManager::get_tutor_in_course_status($user_id, $courseInfo['real_id'])) {
6876
                $user_roles[] = COURSE_TUTOR;
6877
            }
6878
6879
            if (CourseManager::is_user_subscribed_in_course($user_id, $course_code)) {
6880
                $user_roles[] = COURSE_STUDENT;
6881
            }
6882
        } else {
6883
            $user_status_in_session = SessionManager::get_user_status_in_course_session(
6884
                $user_id,
6885
                $courseId,
6886
                $session_id
6887
            );
6888
6889
            if (!empty($user_status_in_session)) {
6890
                if (0 == $user_status_in_session) {
6891
                    $user_roles[] = SESSION_STUDENT;
6892
                }
6893
                if (2 == $user_status_in_session) {
6894
                    $user_roles[] = SESSION_COURSE_COACH;
6895
                }
6896
            }
6897
6898
            /*if (api_is_course_session_coach($user_id, $course_code, $session_id)) {
6899
               $user_roles[] = SESSION_COURSE_COACH;
6900
            }*/
6901
        }
6902
    }
6903
6904
    return $user_roles;
6905
}
6906
6907
/**
6908
 * @param int $courseId
6909
 * @param int $session_id
6910
 *
6911
 * @return bool
6912
 */
6913
function api_coach_can_edit_view_results($courseId = null, $session_id = null)
6914
{
6915
    if (api_is_platform_admin()) {
6916
        return true;
6917
    }
6918
6919
    $user_id = api_get_user_id();
6920
6921
    if (empty($courseId)) {
6922
        $courseId = api_get_course_int_id();
6923
    }
6924
6925
    if (empty($session_id)) {
6926
        $session_id = api_get_session_id();
6927
    }
6928
6929
    $roles = api_detect_user_roles($user_id, $courseId, $session_id);
6930
6931
    if (in_array(SESSION_COURSE_COACH, $roles)) {
6932
        //return api_get_setting('session_tutor_reports_visibility') == 'true';
6933
        return true;
6934
    } else {
6935
        if (in_array(COURSEMANAGER, $roles)) {
6936
            return true;
6937
        }
6938
6939
        return false;
6940
    }
6941
}
6942
6943
/**
6944
 * @param string $file
6945
 *
6946
 * @return string
6947
 */
6948
function api_get_js_simple($file)
6949
{
6950
    return '<script type="text/javascript" src="'.$file.'"></script>'."\n";
6951
}
6952
6953
/**
6954
 * Modify default memory_limit and max_execution_time limits
6955
 * Needed when processing long tasks.
6956
 */
6957
function api_set_more_memory_and_time_limits()
6958
{
6959
    if (function_exists('ini_set')) {
6960
        api_set_memory_limit('256M');
6961
        ini_set('max_execution_time', 1800);
6962
    }
6963
}
6964
6965
/**
6966
 * Tries to set memory limit, if authorized and new limit is higher than current.
6967
 *
6968
 * @param string $mem New memory limit
6969
 *
6970
 * @return bool True on success, false on failure or current is higher than suggested
6971
 * @assert (null) === false
6972
 * @assert (-1) === false
6973
 * @assert (0) === true
6974
 * @assert ('1G') === true
6975
 */
6976
function api_set_memory_limit($mem)
6977
{
6978
    //if ini_set() not available, this function is useless
6979
    if (!function_exists('ini_set') || is_null($mem) || -1 == $mem) {
6980
        return false;
6981
    }
6982
6983
    $memory_limit = ini_get('memory_limit');
6984
    if (api_get_bytes_memory_limit($mem) > api_get_bytes_memory_limit($memory_limit)) {
6985
        ini_set('memory_limit', $mem);
6986
6987
        return true;
6988
    }
6989
6990
    return false;
6991
}
6992
6993
/**
6994
 * Gets memory limit in bytes.
6995
 *
6996
 * @param string The memory size (128M, 1G, 1000K, etc)
6997
 *
6998
 * @return int
6999
 * @assert (null) === false
7000
 * @assert ('1t')  === 1099511627776
7001
 * @assert ('1g')  === 1073741824
7002
 * @assert ('1m')  === 1048576
7003
 * @assert ('100k') === 102400
7004
 */
7005
function api_get_bytes_memory_limit($mem)
7006
{
7007
    $size = strtolower(substr($mem, -1));
7008
7009
    switch ($size) {
7010
        case 't':
7011
            $mem = intval(substr($mem, -1)) * 1024 * 1024 * 1024 * 1024;
7012
            break;
7013
        case 'g':
7014
            $mem = intval(substr($mem, 0, -1)) * 1024 * 1024 * 1024;
7015
            break;
7016
        case 'm':
7017
            $mem = intval(substr($mem, 0, -1)) * 1024 * 1024;
7018
            break;
7019
        case 'k':
7020
            $mem = intval(substr($mem, 0, -1)) * 1024;
7021
            break;
7022
        default:
7023
            // we assume it's integer only
7024
            $mem = intval($mem);
7025
            break;
7026
    }
7027
7028
    return $mem;
7029
}
7030
7031
/**
7032
 * Finds all the information about a user from username instead of user id.
7033
 *
7034
 * @param string $officialCode
7035
 *
7036
 * @return array $user_info user_id, lastname, firstname, username, email, ...
7037
 *
7038
 * @author Yannick Warnier <[email protected]>
7039
 */
7040
function api_get_user_info_from_official_code($officialCode)
7041
{
7042
    if (empty($officialCode)) {
7043
        return false;
7044
    }
7045
    $sql = "SELECT * FROM ".Database::get_main_table(TABLE_MAIN_USER)."
7046
            WHERE official_code ='".Database::escape_string($officialCode)."'";
7047
    $result = Database::query($sql);
7048
    if (Database::num_rows($result) > 0) {
7049
        $result_array = Database::fetch_array($result);
7050
7051
        return _api_format_user($result_array);
7052
    }
7053
7054
    return false;
7055
}
7056
7057
/**
7058
 * @param string $usernameInputId
7059
 * @param string $passwordInputId
7060
 *
7061
 * @return string|null
7062
 */
7063
function api_get_password_checker_js($usernameInputId, $passwordInputId)
7064
{
7065
    $checkPass = api_get_setting('allow_strength_pass_checker');
7066
    $useStrengthPassChecker = 'true' === $checkPass;
7067
7068
    if (false === $useStrengthPassChecker) {
7069
        return null;
7070
    }
7071
7072
    $translations = [
7073
        'wordLength' => get_lang('The password is too short'),
7074
        'wordNotEmail' => get_lang('Your password cannot be the same as your email'),
7075
        'wordSimilarToUsername' => get_lang('Your password cannot contain your username'),
7076
        'wordTwoCharacterClasses' => get_lang('Use different character classes'),
7077
        'wordRepetitions' => get_lang('Too many repetitions'),
7078
        'wordSequences' => get_lang('Your password contains sequences'),
7079
        'errorList' => get_lang('errors found'),
7080
        'veryWeak' => get_lang('Very weak'),
7081
        'weak' => get_lang('Weak'),
7082
        'normal' => get_lang('Normal'),
7083
        'medium' => get_lang('Medium'),
7084
        'strong' => get_lang('Strong'),
7085
        'veryStrong' => get_lang('Very strong'),
7086
    ];
7087
7088
    $js = api_get_asset('pwstrength-bootstrap/dist/pwstrength-bootstrap.js');
7089
    $js .= "<script>
7090
    var errorMessages = {
7091
        password_to_short : \"".get_lang('The password is too short')."\",
7092
        same_as_username : \"".get_lang('Your password cannot be the same as your username')."\"
7093
    };
7094
7095
    $(function() {
7096
        var lang = ".json_encode($translations).";
7097
        var options = {
7098
            onLoad : function () {
7099
                //$('#messages').text('Start typing password');
7100
            },
7101
            onKeyUp: function (evt) {
7102
                $(evt.target).pwstrength('outputErrorList');
7103
            },
7104
            errorMessages : errorMessages,
7105
            viewports: {
7106
                progress: '#password_progress',
7107
                verdict: '#password-verdict',
7108
                errors: '#password-errors'
7109
            },
7110
            usernameField: '$usernameInputId'
7111
        };
7112
        options.i18n = {
7113
            t: function (key) {
7114
                var result = lang[key];
7115
                return result === key ? '' : result; // This assumes you return the
7116
            }
7117
        };
7118
        $('".$passwordInputId."').pwstrength(options);
7119
    });
7120
    </script>";
7121
7122
    return $js;
7123
}
7124
7125
/**
7126
 * create an user extra field called 'captcha_blocked_until_date'.
7127
 *
7128
 * @param string $username
7129
 *
7130
 * @return bool
7131
 */
7132
function api_block_account_captcha($username)
7133
{
7134
    $userInfo = api_get_user_info_from_username($username);
7135
    if (empty($userInfo)) {
7136
        return false;
7137
    }
7138
    $minutesToBlock = api_get_setting('captcha_time_to_block');
7139
    $time = time() + $minutesToBlock * 60;
7140
    UserManager::update_extra_field_value(
7141
        $userInfo['user_id'],
7142
        'captcha_blocked_until_date',
7143
        api_get_utc_datetime($time)
7144
    );
7145
7146
    return true;
7147
}
7148
7149
/**
7150
 * @param string $username
7151
 *
7152
 * @return bool
7153
 */
7154
function api_clean_account_captcha($username)
7155
{
7156
    $userInfo = api_get_user_info_from_username($username);
7157
    if (empty($userInfo)) {
7158
        return false;
7159
    }
7160
    Session::erase('loginFailedCount');
7161
    UserManager::update_extra_field_value(
7162
        $userInfo['user_id'],
7163
        'captcha_blocked_until_date',
7164
        null
7165
    );
7166
7167
    return true;
7168
}
7169
7170
/**
7171
 * @param string $username
7172
 *
7173
 * @return bool
7174
 */
7175
function api_get_user_blocked_by_captcha($username)
7176
{
7177
    $userInfo = api_get_user_info_from_username($username);
7178
    if (empty($userInfo)) {
7179
        return false;
7180
    }
7181
    $data = UserManager::get_extra_user_data_by_field(
7182
        $userInfo['user_id'],
7183
        'captcha_blocked_until_date'
7184
    );
7185
    if (isset($data) && isset($data['captcha_blocked_until_date'])) {
7186
        return $data['captcha_blocked_until_date'];
7187
    }
7188
7189
    return false;
7190
}
7191
7192
/**
7193
 * Remove tags from HTML anf return the $in_number_char first non-HTML char
7194
 * Postfix the text with "..." if it has been truncated.
7195
 *
7196
 * @param string $text
7197
 * @param int    $number
7198
 *
7199
 * @return string
7200
 *
7201
 * @author hubert borderiou
7202
 */
7203
function api_get_short_text_from_html($text, $number)
7204
{
7205
    // Delete script and style tags
7206
    $text = preg_replace('/(<(script|style)\b[^>]*>).*?(<\/\2>)/is', "$1$3", $text);
7207
    $text = api_html_entity_decode($text);
7208
    $out_res = api_remove_tags_with_space($text, false);
7209
    $postfix = "...";
7210
    if (strlen($out_res) > $number) {
7211
        $out_res = substr($out_res, 0, $number).$postfix;
7212
    }
7213
7214
    return $out_res;
7215
}
7216
7217
/**
7218
 * Replace tags with a space in a text.
7219
 * If $in_double_quote_replace, replace " with '' (for HTML attribute purpose, for exemple).
7220
 *
7221
 * @return string
7222
 *
7223
 * @author hubert borderiou
7224
 */
7225
function api_remove_tags_with_space($in_html, $in_double_quote_replace = true)
7226
{
7227
    $out_res = $in_html;
7228
    if ($in_double_quote_replace) {
7229
        $out_res = str_replace('"', "''", $out_res);
7230
    }
7231
    // avoid text stuck together when tags are removed, adding a space after >
7232
    $out_res = str_replace(">", "> ", $out_res);
7233
    $out_res = strip_tags($out_res);
7234
7235
    return $out_res;
7236
}
7237
7238
/**
7239
 * If true, the drh can access all content (courses, users) inside a session.
7240
 *
7241
 * @return bool
7242
 */
7243
function api_drh_can_access_all_session_content()
7244
{
7245
    return 'true' === api_get_setting('drh_can_access_all_session_content');
7246
}
7247
7248
/**
7249
 * @param string $tool
7250
 * @param string $setting
7251
 * @param int    $defaultValue
7252
 *
7253
 * @return string
7254
 */
7255
function api_get_default_tool_setting($tool, $setting, $defaultValue)
7256
{
7257
    global $_configuration;
7258
    if (isset($_configuration[$tool]) &&
7259
        isset($_configuration[$tool]['default_settings']) &&
7260
        isset($_configuration[$tool]['default_settings'][$setting])
7261
    ) {
7262
        return $_configuration[$tool]['default_settings'][$setting];
7263
    }
7264
7265
    return $defaultValue;
7266
}
7267
7268
/**
7269
 * Checks if user can login as another user.
7270
 *
7271
 * @param int $loginAsUserId the user id to log in
7272
 * @param int $userId        my user id
7273
 *
7274
 * @return bool
7275
 */
7276
function api_can_login_as($loginAsUserId, $userId = null)
7277
{
7278
    $loginAsUserId = (int) $loginAsUserId;
7279
7280
    if (empty($loginAsUserId)) {
7281
        return false;
7282
    }
7283
7284
    if (empty($userId)) {
7285
        $userId = api_get_user_id();
7286
    }
7287
7288
    if ($loginAsUserId == $userId) {
7289
        return false;
7290
    }
7291
7292
    // Check if the user to login is an admin
7293
    if (api_is_platform_admin_by_id($loginAsUserId)) {
7294
        // Only super admins can login to admin accounts
7295
        if (!api_global_admin_can_edit_admin($loginAsUserId)) {
7296
            return false;
7297
        }
7298
    }
7299
7300
    $userInfo = api_get_user_info($loginAsUserId);
7301
    $isDrh = function () use ($loginAsUserId) {
7302
        if (api_is_drh()) {
7303
            if (api_drh_can_access_all_session_content()) {
7304
                $users = SessionManager::getAllUsersFromCoursesFromAllSessionFromStatus(
7305
                    'drh_all',
7306
                    api_get_user_id()
7307
                );
7308
                $userList = [];
7309
                if (is_array($users)) {
7310
                    foreach ($users as $user) {
7311
                        $userList[] = $user['id'];
7312
                    }
7313
                }
7314
                if (in_array($loginAsUserId, $userList)) {
7315
                    return true;
7316
                }
7317
            } else {
7318
                if (api_is_drh() &&
7319
                    UserManager::is_user_followed_by_drh($loginAsUserId, api_get_user_id())
7320
                ) {
7321
                    return true;
7322
                }
7323
            }
7324
        }
7325
7326
        return false;
7327
    };
7328
7329
    $loginAsStatusForSessionAdmins = [STUDENT];
7330
7331
    if (api_get_setting('session.allow_session_admin_login_as_teacher')) {
7332
        $loginAsStatusForSessionAdmins[] = COURSEMANAGER;
7333
    }
7334
7335
    return api_is_platform_admin() ||
7336
        (api_is_session_admin() && in_array($userInfo['status'], $loginAsStatusForSessionAdmins)) ||
7337
        $isDrh();
7338
}
7339
7340
/**
7341
 * @return bool
7342
 */
7343
function api_is_allowed_in_course()
7344
{
7345
    if (api_is_platform_admin()) {
7346
        return true;
7347
    }
7348
7349
    $user = api_get_current_user();
7350
    if ($user instanceof User) {
7351
        if ($user->hasRole('ROLE_CURRENT_SESSION_COURSE_STUDENT') ||
7352
            $user->hasRole('ROLE_CURRENT_SESSION_COURSE_TEACHER') ||
7353
            $user->hasRole('ROLE_CURRENT_COURSE_STUDENT') ||
7354
            $user->hasRole('ROLE_CURRENT_COURSE_TEACHER')
7355
        ) {
7356
            return true;
7357
        }
7358
    }
7359
7360
    return false;
7361
}
7362
7363
/**
7364
 * Return true on https install.
7365
 *
7366
 * @return bool
7367
 */
7368
function api_is_https()
7369
{
7370
    if (!empty($_SERVER['HTTP_X_FORWARDED_PROTO']) &&
0 ignored issues
show
introduced by
Consider adding parentheses for clarity. Current Interpretation: (! empty($_SERVER['HTTP_...ttps_forwarded_proto')), Probably Intended Meaning: ! empty($_SERVER['HTTP_X...tps_forwarded_proto')))
Loading history...
7371
        'https' == $_SERVER['HTTP_X_FORWARDED_PROTO'] || !empty(api_get_configuration_value('force_https_forwarded_proto'))
7372
    ) {
7373
        $isSecured = true;
7374
    } else {
7375
        if (!empty($_SERVER['HTTPS']) && 'off' != $_SERVER['HTTPS']) {
7376
            $isSecured = true;
7377
        } else {
7378
            $isSecured = false;
7379
            // last chance
7380
            if (!empty($_SERVER['SERVER_PORT']) && 443 == $_SERVER['SERVER_PORT']) {
7381
                $isSecured = true;
7382
            }
7383
        }
7384
    }
7385
7386
    return $isSecured;
7387
}
7388
7389
/**
7390
 * Return protocol (http or https).
7391
 *
7392
 * @return string
7393
 */
7394
function api_get_protocol()
7395
{
7396
    return api_is_https() ? 'https' : 'http';
7397
}
7398
7399
/**
7400
 * Return a string where " are replaced with 2 '
7401
 * It is useful when you pass a PHP variable in a Javascript browser dialog
7402
 * e.g. : alert("<?php get_lang('Message') ?>");
7403
 * and message contains character ".
7404
 *
7405
 * @param string $in_text
7406
 *
7407
 * @return string
7408
 */
7409
function convert_double_quote_to_single($in_text)
7410
{
7411
    return api_preg_replace('/"/', "''", $in_text);
7412
}
7413
7414
/**
7415
 * Get origin.
7416
 *
7417
 * @param string
7418
 *
7419
 * @return string
7420
 */
7421
function api_get_origin()
7422
{
7423
    return isset($_REQUEST['origin']) ? Security::remove_XSS($_REQUEST['origin']) : '';
7424
}
7425
7426
/**
7427
 * Warns an user that the portal reach certain limit.
7428
 *
7429
 * @param string $limitName
7430
 */
7431
function api_warn_hosting_contact($limitName)
7432
{
7433
    $hostingParams = api_get_configuration_value(1);
7434
    $email = null;
7435
7436
    if (!empty($hostingParams)) {
7437
        if (isset($hostingParams['hosting_contact_mail'])) {
7438
            $email = $hostingParams['hosting_contact_mail'];
7439
        }
7440
    }
7441
7442
    if (!empty($email)) {
7443
        $subject = get_lang('Hosting warning reached');
7444
        $body = get_lang('Portal name').': '.api_get_path(WEB_PATH)." \n ";
7445
        $body .= get_lang('Portal\'s limit type').': '.$limitName." \n ";
7446
        if (isset($hostingParams[$limitName])) {
7447
            $body .= get_lang('Value').': '.$hostingParams[$limitName];
7448
        }
7449
        api_mail_html(null, $email, $subject, $body);
7450
    }
7451
}
7452
7453
/**
7454
 * Gets value of a variable from config/configuration.php
7455
 * Variables that are not set in the configuration.php file but set elsewhere:
7456
 * - virtual_css_theme_folder (vchamilo plugin)
7457
 * - access_url (global.inc.php)
7458
 * - apc/apc_prefix (global.inc.php).
7459
 *
7460
 * @param string $variable
7461
 *
7462
 * @return bool|mixed
7463
 */
7464
function api_get_configuration_value($variable)
7465
{
7466
    global $_configuration;
7467
    // Check the current url id, id = 1 by default
7468
    $urlId = isset($_configuration['access_url']) ? (int) $_configuration['access_url'] : 1;
7469
7470
    $variable = trim($variable);
7471
7472
    // Check if variable exists
7473
    if (isset($_configuration[$variable])) {
7474
        if (is_array($_configuration[$variable])) {
7475
            // Check if it exists for the sub portal
7476
            if (array_key_exists($urlId, $_configuration[$variable])) {
7477
                return $_configuration[$variable][$urlId];
7478
            } else {
7479
                // Try to found element with id = 1 (master portal)
7480
                if (array_key_exists(1, $_configuration[$variable])) {
7481
                    return $_configuration[$variable][1];
7482
                }
7483
            }
7484
        }
7485
7486
        return $_configuration[$variable];
7487
    }
7488
7489
    return false;
7490
}
7491
7492
/**
7493
 * Retreives and returns a value in a hierarchical configuration array
7494
 * api_get_configuration_sub_value('a/b/c') returns api_get_configuration_value('a')['b']['c'].
7495
 *
7496
 * @param string $path      the successive array keys, separated by the separator
7497
 * @param mixed  $default   value to be returned if not found, null by default
7498
 * @param string $separator '/' by default
7499
 * @param array  $array     the active configuration array by default
7500
 *
7501
 * @return mixed the found value or $default
7502
 */
7503
function api_get_configuration_sub_value($path, $default = null, $separator = '/', $array = null)
7504
{
7505
    $pos = strpos($path, $separator);
7506
    if (false === $pos) {
7507
        if (is_null($array)) {
7508
            return api_get_configuration_value($path);
7509
        }
7510
        if (is_array($array) && array_key_exists($path, $array)) {
7511
            return $array[$path];
7512
        }
7513
7514
        return $default;
7515
    }
7516
    $key = substr($path, 0, $pos);
7517
    if (is_null($array)) {
7518
        $newArray = api_get_configuration_value($key);
7519
    } elseif (is_array($array) && array_key_exists($key, $array)) {
7520
        $newArray = $array[$key];
7521
    } else {
7522
        return $default;
7523
    }
7524
    if (is_array($newArray)) {
7525
        $newPath = substr($path, $pos + 1);
7526
7527
        return api_get_configuration_sub_value($newPath, $default, $separator, $newArray);
7528
    }
7529
7530
    return $default;
7531
}
7532
7533
/**
7534
 * Retrieves and returns a value in a hierarchical configuration array
7535
 * api_array_sub_value($array, 'a/b/c') returns $array['a']['b']['c'].
7536
 *
7537
 * @param array  $array     the recursive array that contains the value to be returned (or not)
7538
 * @param string $path      the successive array keys, separated by the separator
7539
 * @param mixed  $default   the value to be returned if not found
7540
 * @param string $separator the separator substring
7541
 *
7542
 * @return mixed the found value or $default
7543
 */
7544
function api_array_sub_value($array, $path, $default = null, $separator = '/')
7545
{
7546
    $pos = strpos($path, $separator);
7547
    if (false === $pos) {
7548
        if (is_array($array) && array_key_exists($path, $array)) {
7549
            return $array[$path];
7550
        }
7551
7552
        return $default;
7553
    }
7554
    $key = substr($path, 0, $pos);
7555
    if (is_array($array) && array_key_exists($key, $array)) {
7556
        $newArray = $array[$key];
7557
    } else {
7558
        return $default;
7559
    }
7560
    if (is_array($newArray)) {
7561
        $newPath = substr($path, $pos + 1);
7562
7563
        return api_array_sub_value($newArray, $newPath, $default);
7564
    }
7565
7566
    return $default;
7567
}
7568
7569
/**
7570
 * Returns supported image extensions in the portal.
7571
 *
7572
 * @param bool $supportVectors Whether vector images should also be accepted or not
7573
 *
7574
 * @return array Supported image extensions in the portal
7575
 */
7576
function api_get_supported_image_extensions($supportVectors = true)
7577
{
7578
    // jpg can also be called jpeg, jpe, jfif and jif. See https://en.wikipedia.org/wiki/JPEG#JPEG_filename_extensions
7579
    $supportedImageExtensions = ['jpg', 'jpeg', 'png', 'gif', 'jpe', 'jfif', 'jif'];
7580
    if ($supportVectors) {
7581
        array_push($supportedImageExtensions, 'svg');
7582
    }
7583
    if (version_compare(PHP_VERSION, '5.5.0', '>=')) {
7584
        array_push($supportedImageExtensions, 'webp');
7585
    }
7586
7587
    return $supportedImageExtensions;
7588
}
7589
7590
/**
7591
 * This setting changes the registration status for the campus.
7592
 *
7593
 * @author Patrick Cool <[email protected]>, Ghent University
7594
 *
7595
 * @version August 2006
7596
 *
7597
 * @param bool $listCampus Whether we authorize
7598
 *
7599
 * @todo the $_settings should be reloaded here. => write api function for this and use this in global.inc.php also.
7600
 */
7601
function api_register_campus($listCampus = true)
7602
{
7603
    $tbl_settings = Database::get_main_table(TABLE_MAIN_SETTINGS_CURRENT);
7604
7605
    $sql = "UPDATE $tbl_settings SET selected_value='true' WHERE variable='registered'";
7606
    Database::query($sql);
7607
7608
    if (!$listCampus) {
7609
        $sql = "UPDATE $tbl_settings SET selected_value='true' WHERE variable='donotlistcampus'";
7610
        Database::query($sql);
7611
    }
7612
}
7613
7614
/**
7615
 * Checks whether current user is a student boss.
7616
 *
7617
 * @global array $_user
7618
 *
7619
 * @return bool
7620
 */
7621
function api_is_student_boss()
7622
{
7623
    $_user = api_get_user_info();
7624
7625
    return isset($_user['status']) && STUDENT_BOSS == $_user['status'];
7626
}
7627
7628
/**
7629
 * Check whether the user type should be exclude.
7630
 * Such as invited or anonymous users.
7631
 *
7632
 * @param bool $checkDB Optional. Whether check the user status
7633
 * @param int  $userId  Options. The user id
7634
 *
7635
 * @return bool
7636
 */
7637
function api_is_excluded_user_type($checkDB = false, $userId = 0)
7638
{
7639
    if ($checkDB) {
7640
        $userId = empty($userId) ? api_get_user_id() : (int) $userId;
7641
7642
        if (0 == $userId) {
7643
            return true;
7644
        }
7645
7646
        $userInfo = api_get_user_info($userId);
7647
7648
        switch ($userInfo['status']) {
7649
            case INVITEE:
7650
            case ANONYMOUS:
7651
                return true;
7652
            default:
7653
                return false;
7654
        }
7655
    }
7656
7657
    $isInvited = api_is_invitee();
7658
    $isAnonymous = api_is_anonymous();
7659
7660
    if ($isInvited || $isAnonymous) {
7661
        return true;
7662
    }
7663
7664
    return false;
7665
}
7666
7667
/**
7668
 * Get the user status to ignore in reports.
7669
 *
7670
 * @param string $format Optional. The result type (array or string)
7671
 *
7672
 * @return array|string
7673
 */
7674
function api_get_users_status_ignored_in_reports($format = 'array')
7675
{
7676
    $excludedTypes = [
7677
        INVITEE,
7678
        ANONYMOUS,
7679
    ];
7680
7681
    if ('string' == $format) {
7682
        return implode(', ', $excludedTypes);
7683
    }
7684
7685
    return $excludedTypes;
7686
}
7687
7688
/**
7689
 * Set the Site Use Cookie Warning for 1 year.
7690
 */
7691
function api_set_site_use_cookie_warning_cookie()
7692
{
7693
    setcookie('ChamiloUsesCookies', 'ok', time() + 31556926);
7694
}
7695
7696
/**
7697
 * Return true if the Site Use Cookie Warning Cookie warning exists.
7698
 *
7699
 * @return bool
7700
 */
7701
function api_site_use_cookie_warning_cookie_exist()
7702
{
7703
    return isset($_COOKIE['ChamiloUsesCookies']);
7704
}
7705
7706
/**
7707
 * Given a number of seconds, format the time to show hours, minutes and seconds.
7708
 *
7709
 * @param int    $time         The time in seconds
7710
 * @param string $originFormat Optional. PHP o JS
7711
 *
7712
 * @return string (00h00'00")
7713
 */
7714
function api_format_time($time, $originFormat = 'php')
7715
{
7716
    $h = get_lang('h');
7717
    $hours = $time / 3600;
7718
    $mins = ($time % 3600) / 60;
7719
    $secs = ($time % 60);
7720
7721
    if ($time < 0) {
7722
        $hours = 0;
7723
        $mins = 0;
7724
        $secs = 0;
7725
    }
7726
7727
    if ('js' == $originFormat) {
7728
        $formattedTime = trim(sprintf("%02d : %02d : %02d", $hours, $mins, $secs));
7729
    } else {
7730
        $formattedTime = trim(sprintf("%02d$h%02d'%02d\"", $hours, $mins, $secs));
7731
    }
7732
7733
    return $formattedTime;
7734
}
7735
7736
/**
7737
 * Create a new empty directory with index.html file.
7738
 *
7739
 * @param string $name            The new directory name
7740
 * @param string $parentDirectory Directory parent directory name
7741
 *
7742
 * @deprecated use Resources
7743
 *
7744
 * @return bool Return true if the directory was create. Otherwise return false
7745
 */
7746
function api_create_protected_dir($name, $parentDirectory)
7747
{
7748
    $isCreated = false;
7749
7750
    if (!is_writable($parentDirectory)) {
7751
        return false;
7752
    }
7753
7754
    $fullPath = $parentDirectory.api_replace_dangerous_char($name);
7755
7756
    if (mkdir($fullPath, api_get_permissions_for_new_directories(), true)) {
7757
        $fp = fopen($fullPath.'/index.html', 'w');
7758
7759
        if ($fp) {
0 ignored issues
show
introduced by
$fp is of type false|resource, thus it always evaluated to false.
Loading history...
7760
            if (fwrite($fp, '<html><head></head><body></body></html>')) {
7761
                $isCreated = true;
7762
            }
7763
        }
7764
7765
        fclose($fp);
7766
    }
7767
7768
    return $isCreated;
7769
}
7770
7771
/**
7772
 * Sends an email
7773
 * Sender name and email can be specified, if not specified
7774
 * name and email of the platform admin are used.
7775
 *
7776
 * @param string    name of recipient
7777
 * @param string    email of recipient
7778
 * @param string    email subject
7779
 * @param string    email body
7780
 * @param string    sender name
7781
 * @param string    sender e-mail
7782
 * @param array     extra headers in form $headers = array($name => $value) to allow parsing
7783
 * @param array     data file (path and filename)
7784
 * @param bool      True for attaching a embedded file inside content html (optional)
7785
 * @param array     Additional parameters
7786
 *
7787
 * @return bool true if mail was sent
7788
 */
7789
function api_mail_html(
7790
    $recipientName,
7791
    $recipientEmail,
7792
    $subject,
7793
    $body,
7794
    $senderName = '',
7795
    $senderEmail = '',
7796
    $extra_headers = [],
7797
    $data_file = [],
7798
    $embeddedImage = false,
7799
    $additionalParameters = []
7800
) {
7801
    if (!api_valid_email($recipientEmail)) {
7802
        return false;
7803
    }
7804
7805
    // Default values
7806
    $notification = new Notification();
7807
    $defaultEmail = $notification->getDefaultPlatformSenderEmail();
7808
    $defaultName = $notification->getDefaultPlatformSenderName();
7809
7810
    // If the parameter is set don't use the admin.
7811
    $senderName = !empty($senderName) ? $senderName : $defaultName;
7812
    $senderEmail = !empty($senderEmail) ? $senderEmail : $defaultEmail;
7813
7814
    // Reply to first
7815
    $replyToName = '';
7816
    $replyToEmail = '';
7817
    if (isset($extra_headers['reply_to'])) {
7818
        $replyToEmail = $extra_headers['reply_to']['mail'];
7819
        $replyToName = $extra_headers['reply_to']['name'];
7820
    }
7821
7822
    try {
7823
        $message = new TemplatedEmail();
7824
        $message->subject($subject);
7825
7826
        $list = api_get_configuration_value('send_all_emails_to');
7827
        if (!empty($list) && isset($list['emails'])) {
7828
            foreach ($list['emails'] as $email) {
7829
                $message->cc($email);
7830
            }
7831
        }
7832
7833
        // Attachment
7834
        if (!empty($data_file)) {
7835
            foreach ($data_file as $file_attach) {
7836
                if (!empty($file_attach['path']) && !empty($file_attach['filename'])) {
7837
                    $message->attachFromPath($file_attach['path'], $file_attach['filename']);
7838
                }
7839
            }
7840
        }
7841
7842
        $noReply = api_get_setting('noreply_email_address');
7843
        $automaticEmailText = '';
7844
        if (!empty($noReply)) {
7845
            $automaticEmailText = '<br />'.get_lang('This is an automatic email message. Please do not reply to it.');
7846
        }
7847
7848
        $params = [
7849
            'mail_header_style' => api_get_configuration_value('mail_header_style'),
7850
            'mail_content_style' => api_get_configuration_value('mail_content_style'),
7851
            'link' => $additionalParameters['link'] ?? '',
7852
            'automatic_email_text' => $automaticEmailText,
7853
            'content' => $body,
7854
            'theme' => api_get_visual_theme(),
7855
        ];
7856
7857
        if (!empty($senderEmail)) {
7858
            $message->from(new Address($senderEmail, $senderName));
7859
        }
7860
7861
        if (!empty($recipientEmail)) {
7862
            $message->to(new Address($recipientEmail, $recipientName));
7863
        }
7864
7865
        if (!empty($replyToEmail)) {
7866
            $message->replyTo(new Address($replyToEmail, $replyToName));
7867
        }
7868
7869
        $message
7870
            ->htmlTemplate('ChamiloCoreBundle:Mailer:Default/default.html.twig')
7871
            ->textTemplate('ChamiloCoreBundle:Mailer:Default/default.text.twig')
7872
        ;
7873
        $message->context($params);
7874
        Container::getMailer()->send($message);
7875
7876
        return true;
7877
    } catch (Exception $e) {
7878
        error_log($e->getMessage());
7879
    }
7880
7881
    if (!empty($additionalParameters)) {
7882
        $plugin = new AppPlugin();
7883
        $smsPlugin = $plugin->getSMSPluginLibrary();
7884
        if ($smsPlugin) {
0 ignored issues
show
introduced by
$smsPlugin is of type SmsPluginLibraryInterface, thus it always evaluated to true.
Loading history...
7885
            $smsPlugin->send($additionalParameters);
7886
        }
7887
    }
7888
7889
    return 1;
7890
}
7891
7892
/**
7893
 * @param string $tool       Possible values: GroupManager::GROUP_TOOL_*
7894
 * @param bool   $showHeader
7895
 */
7896
function api_protect_course_group($tool, $showHeader = true)
7897
{
7898
    $groupId = api_get_group_id();
7899
    if (!empty($groupId)) {
7900
        if (api_is_platform_admin()) {
7901
            return true;
7902
        }
7903
7904
        if (api_is_allowed_to_edit(false, true, true)) {
7905
            return true;
7906
        }
7907
7908
        $userId = api_get_user_id();
7909
        $sessionId = api_get_session_id();
7910
        if (!empty($sessionId)) {
7911
            if (api_is_coach($sessionId, api_get_course_int_id())) {
7912
                return true;
7913
            }
7914
7915
            if (api_is_drh()) {
7916
                if (SessionManager::isUserSubscribedAsHRM($sessionId, $userId)) {
7917
                    return true;
7918
                }
7919
            }
7920
        }
7921
7922
        $groupInfo = GroupManager::get_group_properties($groupId);
7923
7924
        // Group doesn't exists
7925
        if (empty($groupInfo)) {
7926
            api_not_allowed($showHeader);
7927
        }
7928
7929
        // Check group access
7930
        $allow = GroupManager::user_has_access(
7931
            $userId,
7932
            $groupInfo['iid'],
7933
            $tool
7934
        );
7935
7936
        if (!$allow) {
7937
            api_not_allowed($showHeader);
7938
        }
7939
    }
7940
7941
    return false;
7942
}
7943
7944
/**
7945
 * Check if a date is in a date range.
7946
 *
7947
 * @param datetime $startDate
7948
 * @param datetime $endDate
7949
 * @param datetime $currentDate
7950
 *
7951
 * @return bool true if date is in rage, false otherwise
7952
 */
7953
function api_is_date_in_date_range($startDate, $endDate, $currentDate = null)
7954
{
7955
    $startDate = strtotime(api_get_local_time($startDate));
7956
    $endDate = strtotime(api_get_local_time($endDate));
7957
    $currentDate = strtotime(api_get_local_time($currentDate));
7958
7959
    if ($currentDate >= $startDate && $currentDate <= $endDate) {
7960
        return true;
7961
    }
7962
7963
    return false;
7964
}
7965
7966
/**
7967
 * Eliminate the duplicates of a multidimensional array by sending the key.
7968
 *
7969
 * @param array $array multidimensional array
7970
 * @param int   $key   key to find to compare
7971
 *
7972
 * @return array
7973
 */
7974
function api_unique_multidim_array($array, $key)
7975
{
7976
    $temp_array = [];
7977
    $i = 0;
7978
    $key_array = [];
7979
7980
    foreach ($array as $val) {
7981
        if (!in_array($val[$key], $key_array)) {
7982
            $key_array[$i] = $val[$key];
7983
            $temp_array[$i] = $val;
7984
        }
7985
        $i++;
7986
    }
7987
7988
    return $temp_array;
7989
}
7990
7991
/**
7992
 * Limit the access to Session Admins when the limit_session_admin_role
7993
 * configuration variable is set to true.
7994
 */
7995
function api_protect_limit_for_session_admin()
7996
{
7997
    $limitAdmin = api_get_setting('limit_session_admin_role');
7998
    if (api_is_session_admin() && 'true' === $limitAdmin) {
7999
        api_not_allowed(true);
8000
    }
8001
}
8002
8003
/**
8004
 * Limits that a session admin has access to list users.
8005
 * When limit_session_admin_list_users configuration variable is set to true.
8006
 */
8007
function api_protect_session_admin_list_users()
8008
{
8009
    $limitAdmin = api_get_configuration_value('limit_session_admin_list_users');
8010
8011
    if (api_is_session_admin() && true === $limitAdmin) {
8012
        api_not_allowed(true);
8013
    }
8014
}
8015
8016
/**
8017
 * @return bool
8018
 */
8019
function api_is_student_view_active()
8020
{
8021
    $studentView = Session::read('studentview');
8022
8023
    return 'studentview' === $studentView;
8024
}
8025
8026
/**
8027
 * Adds a file inside the upload/$type/id.
8028
 *
8029
 * @param string $type
8030
 * @param array  $file
8031
 * @param int    $itemId
8032
 * @param string $cropParameters
8033
 *
8034
 * @return array|bool
8035
 */
8036
function api_upload_file($type, $file, $itemId, $cropParameters = '')
8037
{
8038
    throw new Exception('api_upload_file not implemented');
8039
    $upload = process_uploaded_file($file);
0 ignored issues
show
Unused Code introduced by
$upload = process_uploaded_file($file) is not reachable.

This check looks for unreachable code. It uses sophisticated control flow analysis techniques to find statements which will never be executed.

Unreachable code is most often the result of return, die or exit statements that have been added for debug purposes.

function fx() {
    try {
        doSomething();
        return true;
    }
    catch (\Exception $e) {
        return false;
    }

    return false;
}

In the above example, the last return false will never be executed, because a return statement has already been met in every possible execution path.

Loading history...
8040
    if ($upload) {
8041
        $name = api_replace_dangerous_char($file['name']);
8042
8043
        // No "dangerous" files
8044
        $name = disable_dangerous_file($name);
8045
8046
        $pathId = '/'.substr((string) $itemId, 0, 1).'/'.$itemId.'/';
8047
        $path = api_get_path(SYS_UPLOAD_PATH).$type.$pathId;
8048
8049
        if (!is_dir($path)) {
8050
            mkdir($path, api_get_permissions_for_new_directories(), true);
8051
        }
8052
8053
        $pathToSave = $path.$name;
8054
        $result = moveUploadedFile($file, $pathToSave);
8055
8056
        if ($result) {
8057
            if (!empty($cropParameters)) {
8058
                $image = new Image($pathToSave);
0 ignored issues
show
Deprecated Code introduced by
The class Image has been deprecated. ( Ignorable by Annotation )

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

8058
                $image = /** @scrutinizer ignore-deprecated */ new Image($pathToSave);
Loading history...
8059
                $image->crop($cropParameters);
8060
            }
8061
8062
            return ['path_to_save' => $pathId.$name];
8063
        }
8064
    }
8065
8066
    return false;
8067
}
8068
8069
/**
8070
 * @param string $type
8071
 * @param int    $itemId
8072
 * @param string $file
8073
 *
8074
 * @return bool
8075
 */
8076
function api_get_uploaded_web_url($type, $itemId, $file)
8077
{
8078
    return api_get_uploaded_file($type, $itemId, $file, true);
8079
}
8080
8081
/**
8082
 * @param string $type
8083
 * @param int    $itemId
8084
 * @param string $file
8085
 * @param bool   $getUrl
8086
 *
8087
 * @return bool
8088
 */
8089
function api_get_uploaded_file($type, $itemId, $file, $getUrl = false)
8090
{
8091
    $itemId = (int) $itemId;
8092
    $pathId = '/'.substr((string) $itemId, 0, 1).'/'.$itemId.'/';
8093
    $path = api_get_path(SYS_UPLOAD_PATH).$type.$pathId;
8094
    $file = basename($file);
8095
    $file = $path.'/'.$file;
8096
    if (Security::check_abs_path($file, $path) && is_file($file) && file_exists($file)) {
8097
        if ($getUrl) {
8098
            return str_replace(api_get_path(SYS_UPLOAD_PATH), api_get_path(WEB_UPLOAD_PATH), $file);
8099
        }
8100
8101
        return $file;
8102
    }
8103
8104
    return false;
8105
}
8106
8107
/**
8108
 * @param string $type
8109
 * @param int    $itemId
8110
 * @param string $file
8111
 * @param string $title
8112
 */
8113
function api_download_uploaded_file($type, $itemId, $file, $title = '')
8114
{
8115
    $file = api_get_uploaded_file($type, $itemId, $file);
8116
    if ($file) {
8117
        if (Security::check_abs_path($file, api_get_path(SYS_UPLOAD_PATH).$type)) {
8118
            DocumentManager::file_send_for_download($file, true, $title);
8119
            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...
8120
        }
8121
    }
8122
    api_not_allowed(true);
8123
}
8124
8125
/**
8126
 * @param string $type
8127
 * @param string $file
8128
 */
8129
function api_remove_uploaded_file($type, $file)
8130
{
8131
    $typePath = api_get_path(SYS_UPLOAD_PATH).$type;
8132
    $path = $typePath.'/'.$file;
8133
    if (Security::check_abs_path($path, $typePath) && file_exists($path) && is_file($path)) {
8134
        unlink($path);
8135
    }
8136
}
8137
8138
/**
8139
 * @param string $type
8140
 * @param int    $itemId
8141
 * @param string $file
8142
 *
8143
 * @return bool
8144
 */
8145
function api_remove_uploaded_file_by_id($type, $itemId, $file)
8146
{
8147
    $file = api_get_uploaded_file($type, $itemId, $file, false);
8148
    $typePath = api_get_path(SYS_UPLOAD_PATH).$type;
8149
    if (Security::check_abs_path($file, $typePath) && file_exists($file) && is_file($file)) {
8150
        unlink($file);
8151
8152
        return true;
8153
    }
8154
8155
    return false;
8156
}
8157
8158
/**
8159
 * Converts string value to float value.
8160
 *
8161
 * 3.141516 => 3.141516
8162
 * 3,141516 => 3.141516
8163
 *
8164
 * @todo WIP
8165
 *
8166
 * @param string $number
8167
 *
8168
 * @return float
8169
 */
8170
function api_float_val($number)
8171
{
8172
    $number = (float) str_replace(',', '.', trim($number));
8173
8174
    return $number;
8175
}
8176
8177
/**
8178
 * Converts float values
8179
 * Example if $decimals = 2.
8180
 *
8181
 * 3.141516 => 3.14
8182
 * 3,141516 => 3,14
8183
 *
8184
 * @param string $number            number in iso code
8185
 * @param int    $decimals
8186
 * @param string $decimalSeparator
8187
 * @param string $thousandSeparator
8188
 *
8189
 * @return bool|string
8190
 */
8191
function api_number_format($number, $decimals = 0, $decimalSeparator = '.', $thousandSeparator = ',')
8192
{
8193
    $number = api_float_val($number);
8194
8195
    return number_format($number, $decimals, $decimalSeparator, $thousandSeparator);
8196
}
8197
8198
/**
8199
 * Set location url with a exit break by default.
8200
 *
8201
 * @param string $url
8202
 * @param bool   $exit
8203
 */
8204
function api_location($url, $exit = true)
8205
{
8206
    header('Location: '.$url);
8207
8208
    if ($exit) {
8209
        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...
8210
    }
8211
}
8212
8213
/**
8214
 * @return string
8215
 */
8216
function api_get_web_url()
8217
{
8218
    if ('test' === api_get_setting('server_type')) {
8219
        return api_get_path(WEB_PATH).'web/app_dev.php/';
8220
    } else {
8221
        return api_get_path(WEB_PATH).'web/';
8222
    }
8223
}
8224
8225
/**
8226
 * @param string $from
8227
 * @param string $to
8228
 *
8229
 * @return string
8230
 */
8231
function api_get_relative_path($from, $to)
8232
{
8233
    // some compatibility fixes for Windows paths
8234
    $from = is_dir($from) ? rtrim($from, '\/').'/' : $from;
8235
    $to = is_dir($to) ? rtrim($to, '\/').'/' : $to;
8236
    $from = str_replace('\\', '/', $from);
8237
    $to = str_replace('\\', '/', $to);
8238
8239
    $from = explode('/', $from);
8240
    $to = explode('/', $to);
8241
    $relPath = $to;
8242
8243
    foreach ($from as $depth => $dir) {
8244
        // find first non-matching dir
8245
        if ($dir === $to[$depth]) {
8246
            // ignore this directory
8247
            array_shift($relPath);
8248
        } else {
8249
            // get number of remaining dirs to $from
8250
            $remaining = count($from) - $depth;
8251
            if ($remaining > 1) {
8252
                // add traversals up to first matching dir
8253
                $padLength = (count($relPath) + $remaining - 1) * -1;
8254
                $relPath = array_pad($relPath, $padLength, '..');
8255
                break;
8256
            } else {
8257
                $relPath[0] = './'.$relPath[0];
8258
            }
8259
        }
8260
    }
8261
8262
    return implode('/', $relPath);
8263
}
8264
8265
/**
8266
 * Unserialize content using Brummann\Polyfill\Unserialize.
8267
 *
8268
 * @param string $type
8269
 * @param string $serialized
8270
 *
8271
 * @return mixed
8272
 */
8273
function api_unserialize_content($type, $serialized, $ignoreErrors = false)
8274
{
8275
    switch ($type) {
8276
        case 'career':
8277
        case 'sequence_graph':
8278
            $allowedClasses = [
8279
                \Fhaculty\Graph\Graph::class,
8280
                \Fhaculty\Graph\Set\VerticesMap::class,
8281
                \Fhaculty\Graph\Set\Vertices::class,
8282
                \Fhaculty\Graph\Set\Edges::class,
8283
            ];
8284
            break;
8285
        case 'lp':
8286
            $allowedClasses = [
8287
                learnpath::class,
8288
                learnpathItem::class,
8289
                aicc::class,
8290
                aiccBlock::class,
8291
                aiccItem::class,
8292
                aiccObjective::class,
8293
                aiccResource::class,
8294
                scorm::class,
8295
                scormItem::class,
8296
                scormMetadata::class,
8297
                scormOrganization::class,
8298
                scormResource::class,
8299
                Link::class,
8300
                LpItem::class,
8301
            ];
8302
            break;
8303
        case 'course':
8304
            $allowedClasses = [
8305
                \Chamilo\CourseBundle\Component\CourseCopy\Course::class,
8306
                \Chamilo\CourseBundle\Component\CourseCopy\Resources\Announcement::class,
8307
                \Chamilo\CourseBundle\Component\CourseCopy\Resources\Attendance::class,
8308
                \Chamilo\CourseBundle\Component\CourseCopy\Resources\CalendarEvent::class,
8309
                \Chamilo\CourseBundle\Component\CourseCopy\Resources\CourseCopyLearnpath::class,
8310
                \Chamilo\CourseBundle\Component\CourseCopy\Resources\CourseCopyTestCategory::class,
8311
                \Chamilo\CourseBundle\Component\CourseCopy\Resources\CourseDescription::class,
8312
                \Chamilo\CourseBundle\Component\CourseCopy\Resources\CourseSession::class,
8313
                \Chamilo\CourseBundle\Component\CourseCopy\Resources\Document::class,
8314
                \Chamilo\CourseBundle\Component\CourseCopy\Resources\Forum::class,
8315
                \Chamilo\CourseBundle\Component\CourseCopy\Resources\ForumCategory::class,
8316
                \Chamilo\CourseBundle\Component\CourseCopy\Resources\ForumPost::class,
8317
                \Chamilo\CourseBundle\Component\CourseCopy\Resources\ForumTopic::class,
8318
                \Chamilo\CourseBundle\Component\CourseCopy\Resources\Glossary::class,
8319
                \Chamilo\CourseBundle\Component\CourseCopy\Resources\GradeBookBackup::class,
8320
                \Chamilo\CourseBundle\Component\CourseCopy\Resources\Link::class,
8321
                \Chamilo\CourseBundle\Component\CourseCopy\Resources\LinkCategory::class,
8322
                \Chamilo\CourseBundle\Component\CourseCopy\Resources\Quiz::class,
8323
                \Chamilo\CourseBundle\Component\CourseCopy\Resources\QuizQuestion::class,
8324
                \Chamilo\CourseBundle\Component\CourseCopy\Resources\QuizQuestionOption::class,
8325
                \Chamilo\CourseBundle\Component\CourseCopy\Resources\ScormDocument::class,
8326
                \Chamilo\CourseBundle\Component\CourseCopy\Resources\Survey::class,
8327
                \Chamilo\CourseBundle\Component\CourseCopy\Resources\SurveyInvitation::class,
8328
                \Chamilo\CourseBundle\Component\CourseCopy\Resources\SurveyQuestion::class,
8329
                \Chamilo\CourseBundle\Component\CourseCopy\Resources\Thematic::class,
8330
                \Chamilo\CourseBundle\Component\CourseCopy\Resources\ToolIntro::class,
8331
                \Chamilo\CourseBundle\Component\CourseCopy\Resources\Wiki::class,
8332
                \Chamilo\CourseBundle\Component\CourseCopy\Resources\Work::class,
8333
                stdClass::class,
8334
            ];
8335
            break;
8336
        case 'not_allowed_classes':
8337
        default:
8338
            $allowedClasses = false;
8339
    }
8340
8341
    if ($ignoreErrors) {
8342
        return @UnserializeApi::unserialize(
8343
            $serialized,
8344
            ['allowed_classes' => $allowedClasses]
8345
        );
8346
    }
8347
8348
    return UnserializeApi::unserialize(
8349
        $serialized,
8350
        ['allowed_classes' => $allowedClasses]
8351
    );
8352
}
8353
8354
/**
8355
 * @param string $template
8356
 *
8357
 * @return string
8358
 */
8359
function api_find_template($template)
8360
{
8361
    return Template::findTemplateFilePath($template);
8362
}
8363
8364
/**
8365
 * @return array
8366
 */
8367
function api_get_language_list_for_flag()
8368
{
8369
    $table = Database::get_main_table(TABLE_MAIN_LANGUAGE);
8370
    $sql = "SELECT english_name, isocode FROM $table
8371
            ORDER BY original_name ASC";
8372
    static $languages = [];
8373
    if (empty($languages)) {
8374
        $result = Database::query($sql);
8375
        while ($row = Database::fetch_array($result)) {
8376
            $languages[$row['english_name']] = $row['isocode'];
8377
        }
8378
        $languages['english'] = 'gb';
8379
    }
8380
8381
    return $languages;
8382
}
8383
8384
/**
8385
 * @param string $name
8386
 *
8387
 * @return \ZipStream\ZipStream
8388
 */
8389
function api_create_zip($name)
8390
{
8391
    $zipStreamOptions = new \ZipStream\Option\Archive();
8392
    $zipStreamOptions->setSendHttpHeaders(true);
8393
    $zipStreamOptions->setContentDisposition('attachment');
8394
    $zipStreamOptions->setContentType('application/x-zip');
8395
8396
    $zip = new \ZipStream\ZipStream($name, $zipStreamOptions);
8397
8398
    return $zip;
8399
}
8400
8401
/**
8402
 * @return string
8403
 */
8404
function api_get_language_translate_html()
8405
{
8406
    $translate = api_get_configuration_value('translate_html');
8407
8408
    if (!$translate) {
8409
        return '';
8410
    }
8411
8412
    $languageList = api_get_languages();
8413
    $hideAll = '';
8414
    foreach ($languageList['all'] as $language) {
8415
        $hideAll .= '
8416
        $("span:lang('.$language['isocode'].')").filter(
8417
            function(e, val) {
8418
                // Only find the spans if they have set the lang
8419
                if ($(this).attr("lang") == null) {
8420
                    return false;
8421
                }
8422
8423
                // Ignore ckeditor classes
8424
                return !this.className.match(/cke(.*)/);
8425
        }).hide();'."\n";
8426
    }
8427
8428
    $userInfo = api_get_user_info();
8429
    $languageId = api_get_language_id($userInfo['language']);
8430
    $languageInfo = api_get_language_info($languageId);
8431
    $isoCode = 'en';
8432
8433
    if (!empty($languageInfo)) {
8434
        $isoCode = $languageInfo['isocode'];
8435
    }
8436
8437
    return '
8438
            $(function() {
8439
                '.$hideAll.'
8440
                var defaultLanguageFromUser = "'.$isoCode.'";
8441
8442
                $("span:lang('.$isoCode.')").filter(
8443
                    function() {
8444
                        // Ignore ckeditor classes
8445
                        return !this.className.match(/cke(.*)/);
8446
                }).show();
8447
8448
                var defaultLanguage = "";
8449
                var langFromUserFound = false;
8450
8451
                $(this).find("span").filter(
8452
                    function() {
8453
                        // Ignore ckeditor classes
8454
                        return !this.className.match(/cke(.*)/);
8455
                }).each(function() {
8456
                    defaultLanguage = $(this).attr("lang");
8457
                    if (defaultLanguage) {
8458
                        $(this).before().next("br").remove();
8459
                        if (defaultLanguageFromUser == defaultLanguage) {
8460
                            langFromUserFound = true;
8461
                        }
8462
                    }
8463
                });
8464
8465
                // Show default language
8466
                if (langFromUserFound == false && defaultLanguage) {
8467
                    $("span:lang("+defaultLanguage+")").filter(
8468
                    function() {
8469
                            // Ignore ckeditor classes
8470
                            return !this.className.match(/cke(.*)/);
8471
                    }).show();
8472
                }
8473
            });
8474
    ';
8475
}
8476