Passed
Push — master ( 53af2f...2f4516 )
by Julito
11:40
created

api_get_setting_in_list()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 2
nc 1
nop 2
dl 0
loc 5
rs 9.4285
c 0
b 0
f 0
1
<?php
2
/* For licensing terms, see /license.txt */
3
4
use ChamiloSession as Session;
5
use Chamilo\CoreBundle\Entity\SettingsCurrent;
6
use Chamilo\CoreBundle\Framework\Container;
7
use Chamilo\CourseBundle\Entity\CItemProperty;
8
use Chamilo\UserBundle\Entity\User;
9
use Symfony\Component\Finder\Finder;
10
11
/**
12
 * This is a code library for Chamilo.
13
 * It is included by default in every Chamilo file (through including the global.inc.php)
14
 * This library is in process of being transferred to src/Chamilo/CoreBundle/Component/Utils/ChamiloApi.
15
 * Whenever a function is transferred to the ChamiloApi class, the places where it is used should include
16
 * the "use Chamilo\CoreBundle\Component\Utils\ChamiloApi;" statement.
17
 * @package chamilo.library
18
 */
19
20
/**
21
 * Constants declaration
22
 */
23
24
// PHP version requirement.
25
define('REQUIRED_PHP_VERSION', '7.1.3');
26
define('REQUIRED_MIN_MEMORY_LIMIT', '128');
27
define('REQUIRED_MIN_UPLOAD_MAX_FILESIZE', '10');
28
define('REQUIRED_MIN_POST_MAX_SIZE', '10');
29
30
// USER STATUS CONSTANTS
31
/** global status of a user: student */
32
define('STUDENT', 5);
33
/** global status of a user: course manager */
34
define('COURSEMANAGER', 1);
35
/** global status of a user: session admin */
36
define('SESSIONADMIN', 3);
37
/** global status of a user: human ressource manager */
38
define('DRH', 4);
39
/** global status of a user: human ressource manager */
40
define('ANONYMOUS', 6);
41
/** global status of a user: low security, necessary for inserting data from
42
 * the teacher through HTMLPurifier */
43
define('COURSEMANAGERLOWSECURITY', 10);
44
// Soft user status
45
define('PLATFORM_ADMIN', 11);
46
define('SESSION_COURSE_COACH', 12);
47
define('SESSION_GENERAL_COACH', 13);
48
define('COURSE_STUDENT', 14); //student subscribed in a course
49
define('SESSION_STUDENT', 15); //student subscribed in a session course
50
define('COURSE_TUTOR', 16); // student is tutor of a course (NOT in session)
51
define('STUDENT_BOSS', 17); // student is boss
52
define('INVITEE', 20);
53
define('HRM_REQUEST', 21); //HRM has request for vinculation with user
54
55
// Table of status
56
$_status_list[COURSEMANAGER] = 'teacher'; // 1
57
$_status_list[SESSIONADMIN] = 'session_admin'; // 3
58
$_status_list[DRH] = 'drh'; // 4
59
$_status_list[STUDENT] = 'user'; // 5
60
$_status_list[ANONYMOUS] = 'anonymous'; // 6
61
$_status_list[INVITEE] = 'invited'; // 20
62
63
// COURSE VISIBILITY CONSTANTS
64
/** only visible for course admin */
65
define('COURSE_VISIBILITY_CLOSED', 0);
66
/** only visible for users registered in the course */
67
define('COURSE_VISIBILITY_REGISTERED', 1);
68
/** Open for all registered users on the platform */
69
define('COURSE_VISIBILITY_OPEN_PLATFORM', 2);
70
/** Open for the whole world */
71
define('COURSE_VISIBILITY_OPEN_WORLD', 3);
72
/** Invisible to all except admin */
73
define('COURSE_VISIBILITY_HIDDEN', 4);
74
75
define('COURSE_REQUEST_PENDING', 0);
76
define('COURSE_REQUEST_ACCEPTED', 1);
77
define('COURSE_REQUEST_REJECTED', 2);
78
define('DELETE_ACTION_ENABLED', false);
79
80
// EMAIL SENDING RECIPIENT CONSTANTS
81
define('SEND_EMAIL_EVERYONE', 1);
82
define('SEND_EMAIL_STUDENTS', 2);
83
define('SEND_EMAIL_TEACHERS', 3);
84
85
// SESSION VISIBILITY CONSTANTS
86
define('SESSION_VISIBLE_READ_ONLY', 1);
87
define('SESSION_VISIBLE', 2);
88
define('SESSION_INVISIBLE', 3); // not available
89
define('SESSION_AVAILABLE', 4);
90
91
define('SESSION_LINK_TARGET', '_self');
92
93
define('SUBSCRIBE_ALLOWED', 1);
94
define('SUBSCRIBE_NOT_ALLOWED', 0);
95
define('UNSUBSCRIBE_ALLOWED', 1);
96
define('UNSUBSCRIBE_NOT_ALLOWED', 0);
97
98
// SURVEY VISIBILITY CONSTANTS
99
define('SURVEY_VISIBLE_TUTOR', 0);
100
define('SURVEY_VISIBLE_TUTOR_STUDENT', 1);
101
define('SURVEY_VISIBLE_PUBLIC', 2);
102
103
// CONSTANTS defining all tools, using the english version
104
/* When you add a new tool you must add it into function api_get_tools_lists() too */
105
define('TOOL_DOCUMENT', 'document');
106
define('TOOL_LP_FINAL_ITEM', 'final_item');
107
define('TOOL_THUMBNAIL', 'thumbnail');
108
define('TOOL_HOTPOTATOES', 'hotpotatoes');
109
define('TOOL_CALENDAR_EVENT', 'calendar_event');
110
define('TOOL_LINK', 'link');
111
define('TOOL_LINK_CATEGORY', 'link_category');
112
define('TOOL_COURSE_DESCRIPTION', 'course_description');
113
define('TOOL_SEARCH', 'search');
114
define('TOOL_LEARNPATH', 'learnpath');
115
define('TOOL_LEARNPATH_CATEGORY', 'learnpath_category');
116
define('TOOL_AGENDA', 'agenda');
117
define('TOOL_ANNOUNCEMENT', 'announcement');
118
define('TOOL_FORUM', 'forum');
119
define('TOOL_FORUM_CATEGORY', 'forum_category');
120
define('TOOL_FORUM_THREAD', 'forum_thread');
121
define('TOOL_FORUM_POST', 'forum_post');
122
define('TOOL_FORUM_ATTACH', 'forum_attachment');
123
define('TOOL_FORUM_THREAD_QUALIFY', 'forum_thread_qualify');
124
define('TOOL_THREAD', 'thread');
125
define('TOOL_POST', 'post');
126
define('TOOL_DROPBOX', 'dropbox');
127
define('TOOL_QUIZ', 'quiz');
128
define('TOOL_TEST_CATEGORY', 'test_category');
129
define('TOOL_USER', 'user');
130
define('TOOL_GROUP', 'group');
131
define('TOOL_BLOGS', 'blog_management');
132
define('TOOL_CHAT', 'chat');
133
define('TOOL_STUDENTPUBLICATION', 'student_publication');
134
define('TOOL_TRACKING', 'tracking');
135
define('TOOL_HOMEPAGE_LINK', 'homepage_link');
136
define('TOOL_COURSE_SETTING', 'course_setting');
137
define('TOOL_BACKUP', 'backup');
138
define('TOOL_COPY_COURSE_CONTENT', 'copy_course_content');
139
define('TOOL_RECYCLE_COURSE', 'recycle_course');
140
define('TOOL_COURSE_HOMEPAGE', 'course_homepage');
141
define('TOOL_COURSE_RIGHTS_OVERVIEW', 'course_rights');
142
define('TOOL_UPLOAD', 'file_upload');
143
define('TOOL_COURSE_MAINTENANCE', 'course_maintenance');
144
define('TOOL_SURVEY', 'survey');
145
define('TOOL_WIKI', 'wiki');
146
define('TOOL_GLOSSARY', 'glossary');
147
define('TOOL_GRADEBOOK', 'gradebook');
148
define('TOOL_NOTEBOOK', 'notebook');
149
define('TOOL_ATTENDANCE', 'attendance');
150
define('TOOL_COURSE_PROGRESS', 'course_progress');
151
152
// CONSTANTS defining Chamilo interface sections
153
define('SECTION_CAMPUS', 'mycampus');
154
define('SECTION_COURSES', 'mycourses');
155
define('SECTION_CATALOG', 'catalog');
156
define('SECTION_MYPROFILE', 'myprofile');
157
define('SECTION_MYAGENDA', 'myagenda');
158
define('SECTION_COURSE_ADMIN', 'course_admin');
159
define('SECTION_PLATFORM_ADMIN', 'platform_admin');
160
define('SECTION_MYGRADEBOOK', 'mygradebook');
161
define('SECTION_TRACKING', 'session_my_space');
162
define('SECTION_SOCIAL', 'social-network');
163
define('SECTION_DASHBOARD', 'dashboard');
164
define('SECTION_REPORTS', 'reports');
165
define('SECTION_GLOBAL', 'global');
166
167
// CONSTANT name for local authentication source
168
define('PLATFORM_AUTH_SOURCE', 'platform');
169
define('CAS_AUTH_SOURCE', 'cas');
170
define('LDAP_AUTH_SOURCE', 'extldap');
171
172
// CONSTANT defining the default HotPotatoes files directory
173
define('DIR_HOTPOTATOES', '/HotPotatoes_files');
174
175
// event logs types
176
define('LOG_COURSE_DELETE', 'course_deleted');
177
define('LOG_COURSE_CREATE', 'course_created');
178
179
// @todo replace 'soc_gr' with social_group
180
define('LOG_GROUP_PORTAL_CREATED', 'soc_gr_created');
181
define('LOG_GROUP_PORTAL_UPDATED', 'soc_gr_updated');
182
define('LOG_GROUP_PORTAL_DELETED', 'soc_gr_deleted');
183
define('LOG_GROUP_PORTAL_USER_DELETE_ALL', 'soc_gr_delete_users');
184
185
define('LOG_GROUP_PORTAL_ID', 'soc_gr_portal_id');
186
define('LOG_GROUP_PORTAL_REL_USER_ARRAY', 'soc_gr_user_array');
187
188
define('LOG_GROUP_PORTAL_USER_SUBSCRIBED', 'soc_gr_u_subs');
189
define('LOG_GROUP_PORTAL_USER_UNSUBSCRIBED', 'soc_gr_u_unsubs');
190
define('LOG_GROUP_PORTAL_USER_UPDATE_ROLE', 'soc_gr_update_role');
191
192
define('LOG_USER_DELETE', 'user_deleted');
193
define('LOG_USER_CREATE', 'user_created');
194
define('LOG_USER_ENABLE', 'user_enable');
195
define('LOG_USER_DISABLE', 'user_disable');
196
define('LOG_USER_FIELD_CREATE', 'user_field_created');
197
define('LOG_USER_FIELD_DELETE', 'user_field_deleted');
198
define('LOG_SESSION_CREATE', 'session_created');
199
define('LOG_SESSION_DELETE', 'session_deleted');
200
define('LOG_SESSION_ADD_USER_COURSE', 'session_add_user_course');
201
define('LOG_SESSION_DELETE_USER_COURSE', 'session_delete_user_course');
202
define('LOG_SESSION_DELETE_USER', 'session_delete_user');
203
define('LOG_SESSION_ADD_COURSE', 'session_add_course');
204
define('LOG_SESSION_DELETE_COURSE', 'session_delete_course');
205
206
define('LOG_SESSION_CATEGORY_CREATE', 'session_cat_created'); //changed in 1.9.8
207
define('LOG_SESSION_CATEGORY_DELETE', 'session_cat_deleted'); //changed in 1.9.8
208
define('LOG_CONFIGURATION_SETTINGS_CHANGE', 'settings_changed');
209
define('LOG_PLATFORM_LANGUAGE_CHANGE', 'platform_lng_changed'); //changed in 1.9.8
210
define('LOG_SUBSCRIBE_USER_TO_COURSE', 'user_subscribed');
211
define('LOG_UNSUBSCRIBE_USER_FROM_COURSE', 'user_unsubscribed');
212
define('LOG_ATTEMPTED_FORCED_LOGIN', 'attempted_forced_login');
213
214
define('LOG_HOMEPAGE_CHANGED', 'homepage_changed');
215
216
define('LOG_PROMOTION_CREATE', 'promotion_created');
217
define('LOG_PROMOTION_DELETE', 'promotion_deleted');
218
define('LOG_CAREER_CREATE', 'career_created');
219
define('LOG_CAREER_DELETE', 'career_deleted');
220
221
define('LOG_USER_PERSONAL_DOC_DELETED', 'user_doc_deleted');
222
define('LOG_WIKI_ACCESS', 'wiki_page_view');
223
224
// All results from an exercise
225
define('LOG_EXERCISE_RESULT_DELETE', 'exe_result_deleted');
226
227
// Logs only the one attempt
228
define('LOG_EXERCISE_ATTEMPT_DELETE', 'exe_attempt_deleted');
229
define('LOG_LP_ATTEMPT_DELETE', 'lp_attempt_deleted');
230
define('LOG_QUESTION_RESULT_DELETE', 'qst_attempt_deleted');
231
232
define('LOG_MY_FOLDER_CREATE', 'my_folder_created');
233
define('LOG_MY_FOLDER_CHANGE', 'my_folder_changed');
234
define('LOG_MY_FOLDER_DELETE', 'my_folder_deleted');
235
define('LOG_MY_FOLDER_COPY', 'my_folder_copied');
236
define('LOG_MY_FOLDER_CUT', 'my_folder_cut');
237
define('LOG_MY_FOLDER_PASTE', 'my_folder_pasted');
238
define('LOG_MY_FOLDER_UPLOAD', 'my_folder_uploaded');
239
240
// Event logs data types (max 20 chars)
241
define('LOG_COURSE_CODE', 'course_code');
242
define('LOG_COURSE_ID', 'course_id');
243
define('LOG_USER_ID', 'user_id');
244
define('LOG_USER_OBJECT', 'user_object');
245
define('LOG_USER_FIELD_VARIABLE', 'user_field_variable');
246
define('LOG_SESSION_ID', 'session_id');
247
define('LOG_SESSION_CATEGORY_ID', 'session_category_id');
248
define('LOG_CONFIGURATION_SETTINGS_CATEGORY', 'settings_category');
249
define('LOG_CONFIGURATION_SETTINGS_VARIABLE', 'settings_variable');
250
define('LOG_PLATFORM_LANGUAGE', 'default_platform_language');
251
define('LOG_CAREER_ID', 'career_id');
252
define('LOG_PROMOTION_ID', 'promotion_id');
253
define('LOG_GRADEBOOK_LOCKED', 'gradebook_locked');
254
define('LOG_GRADEBOOK_UNLOCKED', 'gradebook_unlocked');
255
define('LOG_GRADEBOOK_ID', 'gradebook_id');
256
define('LOG_WIKI_PAGE_ID', 'wiki_page_id');
257
define('LOG_EXERCISE_ID', 'exercise_id');
258
define('LOG_EXERCISE_AND_USER_ID', 'exercise_and_user_id');
259
define('LOG_LP_ID', 'lp_id');
260
define('LOG_EXERCISE_ATTEMPT_QUESTION_ID', 'exercise_a_q_id');
261
define('LOG_EXERCISE_ATTEMPT', 'exe_id');
262
263
define('LOG_WORK_DIR_DELETE', 'work_dir_delete');
264
define('LOG_WORK_FILE_DELETE', 'work_file_delete');
265
define('LOG_WORK_DATA', 'work_data_array');
266
267
define('LOG_MY_FOLDER_PATH', 'path');
268
define('LOG_MY_FOLDER_NEW_PATH', 'new_path');
269
270
define('USERNAME_PURIFIER', '/[^0-9A-Za-z_\.]/');
271
272
//used when login_is_email setting is true
273
define('USERNAME_PURIFIER_MAIL', '/[^0-9A-Za-z_\.@]/');
274
define('USERNAME_PURIFIER_SHALLOW', '/\s/');
275
276
// This constant is a result of Windows OS detection, it has a boolean value:
277
// true whether the server runs on Windows OS, false otherwise.
278
define('IS_WINDOWS_OS', api_is_windows_os());
279
280
// Checks for installed optional php-extensions.
281
define('INTL_INSTALLED', function_exists('intl_get_error_code')); // intl extension (from PECL), it is installed by default as of PHP 5.3.0
282
define('ICONV_INSTALLED', function_exists('iconv')); // iconv extension, for PHP5 on Windows it is installed by default.
283
define('MBSTRING_INSTALLED', function_exists('mb_strlen')); // mbstring extension.
284
285
// Patterns for processing paths.                                   // Examples:
286
define('REPEATED_SLASHES_PURIFIER', '/\/{2,}/'); // $path = preg_replace(REPEATED_SLASHES_PURIFIER, '/', $path);
287
define('VALID_WEB_PATH', '/https?:\/\/[^\/]*(\/.*)?/i'); // $is_valid_path = preg_match(VALID_WEB_PATH, $path);
288
define('VALID_WEB_SERVER_BASE', '/https?:\/\/[^\/]*/i'); // $new_path = preg_replace(VALID_WEB_SERVER_BASE, $new_base, $path);
289
290
// Constants for api_get_path() and api_get_path_type(), etc. - registered path types.
291
// basic (leaf elements)
292
define('REL_CODE_PATH', 'REL_CODE_PATH');
293
define('REL_COURSE_PATH', 'REL_COURSE_PATH');
294
define('REL_HOME_PATH', 'REL_HOME_PATH');
295
296
// Constants for api_get_path() and api_get_path_type(), etc. - registered path types.
297
define('WEB_PATH', 'WEB_PATH');
298
define('WEB_APP_PATH', 'WEB_APP_PATH');
299
define('SYS_PATH', 'SYS_PATH');
300
define('SYS_APP_PATH', 'SYS_APP_PATH');
301
define('SYS_UPLOAD_PATH', 'SYS_UPLOAD_PATH');
302
define('WEB_UPLOAD_PATH', 'WEB_UPLOAD_PATH');
303
304
define('REL_PATH', 'REL_PATH');
305
define('WEB_COURSE_PATH', 'WEB_COURSE_PATH');
306
define('SYS_COURSE_PATH', 'SYS_COURSE_PATH');
307
define('WEB_CODE_PATH', 'WEB_CODE_PATH');
308
define('SYS_CODE_PATH', 'SYS_CODE_PATH');
309
define('SYS_LANG_PATH', 'SYS_LANG_PATH');
310
define('WEB_IMG_PATH', 'WEB_IMG_PATH');
311
define('WEB_CSS_PATH', 'WEB_CSS_PATH');
312
define('WEB_PUBLIC_PATH', 'WEB_PUBLIC_PATH');
313
define('SYS_CSS_PATH', 'SYS_CSS_PATH');
314
define('SYS_PLUGIN_PATH', 'SYS_PLUGIN_PATH');
315
define('WEB_PLUGIN_PATH', 'WEB_PLUGIN_PATH');
316
define('WEB_PLUGIN_ASSET_PATH', 'WEB_PLUGIN_ASSET_PATH');
317
define('SYS_ARCHIVE_PATH', 'SYS_ARCHIVE_PATH');
318
define('WEB_ARCHIVE_PATH', 'WEB_ARCHIVE_PATH');
319
define('SYS_INC_PATH', 'SYS_INC_PATH');
320
define('LIBRARY_PATH', 'LIBRARY_PATH');
321
define('CONFIGURATION_PATH', 'CONFIGURATION_PATH');
322
define('WEB_LIBRARY_PATH', 'WEB_LIBRARY_PATH');
323
define('WEB_LIBRARY_JS_PATH', 'WEB_LIBRARY_JS_PATH');
324
define('WEB_AJAX_PATH', 'WEB_AJAX_PATH');
325
define('SYS_TEST_PATH', 'SYS_TEST_PATH');
326
define('WEB_TEMPLATE_PATH', 'WEB_TEMPLATE_PATH');
327
define('SYS_TEMPLATE_PATH', 'SYS_TEMPLATE_PATH');
328
define('SYS_PUBLIC_PATH', 'SYS_PUBLIC_PATH');
329
define('SYS_HOME_PATH', 'SYS_HOME_PATH');
330
define('WEB_HOME_PATH', 'WEB_HOME_PATH');
331
define('WEB_FONTS_PATH', 'WEB_FONTS_PATH');
332
define('SYS_FONTS_PATH', 'SYS_FONTS_PATH');
333
334
define('SYS_DEFAULT_COURSE_DOCUMENT_PATH', 'SYS_DEFAULT_COURSE_DOCUMENT_PATH');
335
define('REL_DEFAULT_COURSE_DOCUMENT_PATH', 'REL_DEFAULT_COURSE_DOCUMENT_PATH');
336
define('WEB_DEFAULT_COURSE_DOCUMENT_PATH', 'WEB_DEFAULT_COURSE_DOCUMENT_PATH');
337
338
// Relations type with Course manager
339
define('COURSE_RELATION_TYPE_COURSE_MANAGER', 1);
340
define('SESSION_RELATION_TYPE_COURSE_MANAGER', 1);
341
342
// Relations type with Human resources manager
343
define('COURSE_RELATION_TYPE_RRHH', 1);
344
define('SESSION_RELATION_TYPE_RRHH', 1);
345
346
//User image sizes
347
define('USER_IMAGE_SIZE_ORIGINAL', 1);
348
define('USER_IMAGE_SIZE_BIG', 2);
349
define('USER_IMAGE_SIZE_MEDIUM', 3);
350
define('USER_IMAGE_SIZE_SMALL', 4);
351
352
// Relation type between users
353
define('USER_UNKNOWN', 0);
354
define('USER_RELATION_TYPE_UNKNOWN', 1);
355
define('USER_RELATION_TYPE_PARENT', 2); // should be deprecated is useless
356
define('USER_RELATION_TYPE_FRIEND', 3);
357
define('USER_RELATION_TYPE_GOODFRIEND', 4); // should be deprecated is useless
358
define('USER_RELATION_TYPE_ENEMY', 5); // should be deprecated is useless
359
define('USER_RELATION_TYPE_DELETED', 6);
360
define('USER_RELATION_TYPE_RRHH', 7);
361
define('USER_RELATION_TYPE_BOSS', 8);
362
define('USER_RELATION_TYPE_HRM_REQUEST', 9);
363
364
// Gradebook link constants
365
// Please do not change existing values, they are used in the database !
366
define('GRADEBOOK_ITEM_LIMIT', 1000);
367
368
define('LINK_EXERCISE', 1);
369
define('LINK_DROPBOX', 2);
370
define('LINK_STUDENTPUBLICATION', 3);
371
define('LINK_LEARNPATH', 4);
372
define('LINK_FORUM_THREAD', 5);
373
//define('LINK_WORK',6);
374
define('LINK_ATTENDANCE', 7);
375
define('LINK_SURVEY', 8);
376
define('LINK_HOTPOTATOES', 9);
377
378
// Score display types constants
379
define('SCORE_DIV', 1); // X / Y
380
define('SCORE_PERCENT', 2); // XX %
381
define('SCORE_DIV_PERCENT', 3); // X / Y (XX %)
382
define('SCORE_AVERAGE', 4); // XX %
383
define('SCORE_DECIMAL', 5); // 0.50  (X/Y)
384
define('SCORE_BAR', 6); // Uses the Display::bar_progress function
385
define('SCORE_SIMPLE', 7); // X
386
define('SCORE_IGNORE_SPLIT', 8); //  ??
387
define('SCORE_DIV_PERCENT_WITH_CUSTOM', 9); // X / Y (XX %) - Good!
388
define('SCORE_CUSTOM', 10); // Good!
389
define('SCORE_DIV_SIMPLE_WITH_CUSTOM', 11); // X - Good!
390
define('SCORE_DIV_SIMPLE_WITH_CUSTOM_LETTERS', 12); // X - Good!
391
define('SCORE_ONLY_SCORE', 13); // X - Good!
392
393
define('SCORE_BOTH', 1);
394
define('SCORE_ONLY_DEFAULT', 2);
395
define('SCORE_ONLY_CUSTOM', 3);
396
397
// From display.lib.php
398
399
define('MAX_LENGTH_BREADCRUMB', 100);
400
define('ICON_SIZE_ATOM', 8);
401
define('ICON_SIZE_TINY', 16);
402
define('ICON_SIZE_SMALL', 22);
403
define('ICON_SIZE_MEDIUM', 32);
404
define('ICON_SIZE_LARGE', 48);
405
define('ICON_SIZE_BIG', 64);
406
define('ICON_SIZE_HUGE', 128);
407
define('SHOW_TEXT_NEAR_ICONS', false);
408
409
// Session catalog
410
define('CATALOG_COURSES', 0);
411
define('CATALOG_SESSIONS', 1);
412
define('CATALOG_COURSES_SESSIONS', 2);
413
414
// Hook type events, pre-process and post-process.
415
// All means to be executed for both hook event types
416
define('HOOK_EVENT_TYPE_PRE', 0);
417
define('HOOK_EVENT_TYPE_POST', 1);
418
define('HOOK_EVENT_TYPE_ALL', 10);
419
420
define('CAREER_STATUS_ACTIVE', 1);
421
define('CAREER_STATUS_INACTIVE', 0);
422
423
define('PROMOTION_STATUS_ACTIVE', 1);
424
define('PROMOTION_STATUS_INACTIVE', 0);
425
426
// Group permissions
427
define('GROUP_PERMISSION_OPEN', '1');
428
define('GROUP_PERMISSION_CLOSED', '2');
429
430
// Group user permissions
431
define('GROUP_USER_PERMISSION_ADMIN', '1'); // the admin of a group
432
define('GROUP_USER_PERMISSION_READER', '2'); // a normal user
433
define('GROUP_USER_PERMISSION_PENDING_INVITATION', '3'); // When an admin/moderator invites a user
434
define('GROUP_USER_PERMISSION_PENDING_INVITATION_SENT_BY_USER', '4'); // an user joins a group
435
define('GROUP_USER_PERMISSION_MODERATOR', '5'); // a moderator
436
define('GROUP_USER_PERMISSION_ANONYMOUS', '6'); // an anonymous user
437
define('GROUP_USER_PERMISSION_HRM', '7'); // a human resources manager
438
439
define('GROUP_IMAGE_SIZE_ORIGINAL', 1);
440
define('GROUP_IMAGE_SIZE_BIG', 2);
441
define('GROUP_IMAGE_SIZE_MEDIUM', 3);
442
define('GROUP_IMAGE_SIZE_SMALL', 4);
443
define('GROUP_TITLE_LENGTH', 50);
444
445
// Exercise
446
// @todo move into a class
447
define('ALL_ON_ONE_PAGE', 1);
448
define('ONE_PER_PAGE', 2);
449
450
define('EXERCISE_FEEDBACK_TYPE_END', 0); //Feedback 		 - show score and expected answers
451
define('EXERCISE_FEEDBACK_TYPE_DIRECT', 1); //DirectFeedback - Do not show score nor answers
452
define('EXERCISE_FEEDBACK_TYPE_EXAM', 2); //NoFeedback 	 - Show score only
453
454
define('RESULT_DISABLE_SHOW_SCORE_AND_EXPECTED_ANSWERS', 0); //show score and expected answers
455
define('RESULT_DISABLE_NO_SCORE_AND_EXPECTED_ANSWERS', 1); //Do not show score nor answers
456
define('RESULT_DISABLE_SHOW_SCORE_ONLY', 2); //Show score only
457
define('RESULT_DISABLE_SHOW_FINAL_SCORE_ONLY_WITH_CATEGORIES', 3); //Show final score only with categories
458
define('RESULT_DISABLE_SHOW_SCORE_ATTEMPT_SHOW_ANSWERS_LAST_ATTEMPT', 4); //Show final score only with categories
459
460
define('EXERCISE_MAX_NAME_SIZE', 80);
461
462
// Question types (edit next array as well when adding values)
463
// @todo move into a class
464
define('UNIQUE_ANSWER', 1);
465
define('MULTIPLE_ANSWER', 2);
466
define('FILL_IN_BLANKS', 3);
467
define('MATCHING', 4);
468
define('FREE_ANSWER', 5);
469
define('HOT_SPOT', 6);
470
define('HOT_SPOT_ORDER', 7);
471
define('HOT_SPOT_DELINEATION', 8);
472
define('MULTIPLE_ANSWER_COMBINATION', 9);
473
define('UNIQUE_ANSWER_NO_OPTION', 10);
474
define('MULTIPLE_ANSWER_TRUE_FALSE', 11);
475
define('MULTIPLE_ANSWER_COMBINATION_TRUE_FALSE', 12);
476
define('ORAL_EXPRESSION', 13);
477
define('GLOBAL_MULTIPLE_ANSWER', 14);
478
define('MEDIA_QUESTION', 15);
479
define('CALCULATED_ANSWER', 16);
480
define('UNIQUE_ANSWER_IMAGE', 17);
481
define('DRAGGABLE', 18);
482
define('MATCHING_DRAGGABLE', 19);
483
define('ANNOTATION', 20);
484
define('READING_COMPREHENSION', 21);
485
486
define('EXERCISE_CATEGORY_RANDOM_SHUFFLED', 1);
487
define('EXERCISE_CATEGORY_RANDOM_ORDERED', 2);
488
define('EXERCISE_CATEGORY_RANDOM_DISABLED', 0);
489
490
// Question selection type
491
define('EX_Q_SELECTION_ORDERED', 1);
492
define('EX_Q_SELECTION_RANDOM', 2);
493
define('EX_Q_SELECTION_CATEGORIES_ORDERED_QUESTIONS_ORDERED', 3);
494
define('EX_Q_SELECTION_CATEGORIES_RANDOM_QUESTIONS_ORDERED', 4);
495
define('EX_Q_SELECTION_CATEGORIES_ORDERED_QUESTIONS_RANDOM', 5);
496
define('EX_Q_SELECTION_CATEGORIES_RANDOM_QUESTIONS_RANDOM', 6);
497
define('EX_Q_SELECTION_CATEGORIES_RANDOM_QUESTIONS_ORDERED_NO_GROUPED', 7);
498
define('EX_Q_SELECTION_CATEGORIES_RANDOM_QUESTIONS_RANDOM_NO_GROUPED', 8);
499
define('EX_Q_SELECTION_CATEGORIES_ORDERED_BY_PARENT_QUESTIONS_ORDERED', 9);
500
define('EX_Q_SELECTION_CATEGORIES_ORDERED_BY_PARENT_QUESTIONS_RANDOM', 10);
501
502
// one big string with all question types, for the validator in pear/HTML/QuickForm/Rule/QuestionType
503
define(
504
    'QUESTION_TYPES',
505
    UNIQUE_ANSWER.':'.
506
    MULTIPLE_ANSWER.':'.
507
    FILL_IN_BLANKS.':'.
508
    MATCHING.':'.
509
    FREE_ANSWER.':'.
510
    HOT_SPOT.':'.
511
    HOT_SPOT_ORDER.':'.
512
    HOT_SPOT_DELINEATION.':'.
513
    MULTIPLE_ANSWER_COMBINATION.':'.
514
    UNIQUE_ANSWER_NO_OPTION.':'.
515
    MULTIPLE_ANSWER_TRUE_FALSE.':'.
516
    MULTIPLE_ANSWER_COMBINATION_TRUE_FALSE.':'.
517
    ORAL_EXPRESSION.':'.
518
    GLOBAL_MULTIPLE_ANSWER.':'.
519
    MEDIA_QUESTION.':'.
520
    CALCULATED_ANSWER.':'.
521
    UNIQUE_ANSWER_IMAGE.':'.
522
    DRAGGABLE.':'.
523
    MATCHING_DRAGGABLE.':'.
524
    ANNOTATION
525
);
526
527
//Some alias used in the QTI exports
528
define('MCUA', 1);
529
define('TF', 1);
530
define('MCMA', 2);
531
define('FIB', 3);
532
533
// Skills
534
define('SKILL_TYPE_REQUIREMENT', 'required');
535
define('SKILL_TYPE_ACQUIRED', 'acquired');
536
define('SKILL_TYPE_BOTH', 'both');
537
538
// Message
539
define('MESSAGE_STATUS_NEW', '0');
540
define('MESSAGE_STATUS_UNREAD', '1');
541
//2 ??
542
define('MESSAGE_STATUS_DELETED', '3');
543
define('MESSAGE_STATUS_OUTBOX', '4');
544
define('MESSAGE_STATUS_INVITATION_PENDING', '5');
545
define('MESSAGE_STATUS_INVITATION_ACCEPTED', '6');
546
define('MESSAGE_STATUS_INVITATION_DENIED', '7');
547
define('MESSAGE_STATUS_WALL', '8');
548
define('MESSAGE_STATUS_WALL_DELETE', '9');
549
define('MESSAGE_STATUS_WALL_POST', '10');
550
define('MESSAGE_STATUS_CONVERSATION', '11');
551
552
// Images
553
define('IMAGE_WALL_SMALL_SIZE', 200);
554
define('IMAGE_WALL_MEDIUM_SIZE', 500);
555
define('IMAGE_WALL_BIG_SIZE', 2000);
556
define('IMAGE_WALL_SMALL', 'small');
557
define('IMAGE_WALL_MEDIUM', 'medium');
558
define('IMAGE_WALL_BIG', 'big');
559
560
// Social PLUGIN PLACES
561
define('SOCIAL_LEFT_PLUGIN', 1);
562
define('SOCIAL_CENTER_PLUGIN', 2);
563
define('SOCIAL_RIGHT_PLUGIN', 3);
564
define('CUT_GROUP_NAME', 50);
565
566
/**
567
 * FormValidator Filter
568
 */
569
define('NO_HTML', 1);
570
define('STUDENT_HTML', 2);
571
define('TEACHER_HTML', 3);
572
define('STUDENT_HTML_FULLPAGE', 4);
573
define('TEACHER_HTML_FULLPAGE', 5);
574
575
// Timeline
576
define('TIMELINE_STATUS_ACTIVE', '1');
577
define('TIMELINE_STATUS_INACTIVE', '2');
578
579
// Event email template class
580
define('EVENT_EMAIL_TEMPLATE_ACTIVE', 1);
581
define('EVENT_EMAIL_TEMPLATE_INACTIVE', 0);
582
583
// Course home
584
define('SHORTCUTS_HORIZONTAL', 0);
585
define('SHORTCUTS_VERTICAL', 1);
586
587
// Image class
588
define('IMAGE_PROCESSOR', 'gd'); // 'imagick' or 'gd' strings
589
590
// Course copy
591
define('FILE_SKIP', 1);
592
define('FILE_RENAME', 2);
593
define('FILE_OVERWRITE', 3);
594
define('UTF8_CONVERT', false); //false by default
595
596
define('DOCUMENT', 'file');
597
define('FOLDER', 'folder');
598
599
define('RESOURCE_ASSET', 'asset');
600
define('RESOURCE_DOCUMENT', 'document');
601
define('RESOURCE_GLOSSARY', 'glossary');
602
define('RESOURCE_EVENT', 'calendar_event');
603
define('RESOURCE_LINK', 'link');
604
define('RESOURCE_COURSEDESCRIPTION', 'course_description');
605
define('RESOURCE_LEARNPATH', 'learnpath');
606
define('RESOURCE_ANNOUNCEMENT', 'announcement');
607
define('RESOURCE_FORUM', 'forum');
608
define('RESOURCE_FORUMTOPIC', 'thread');
609
define('RESOURCE_FORUMPOST', 'post');
610
define('RESOURCE_QUIZ', 'quiz');
611
define('RESOURCE_TEST_CATEGORY', 'test_category');
612
define('RESOURCE_QUIZQUESTION', 'Exercise_Question');
613
define('RESOURCE_TOOL_INTRO', 'Tool introduction');
614
define('RESOURCE_LINKCATEGORY', 'Link_Category');
615
define('RESOURCE_FORUMCATEGORY', 'Forum_Category');
616
define('RESOURCE_SCORM', 'Scorm');
617
define('RESOURCE_SURVEY', 'survey');
618
define('RESOURCE_SURVEYQUESTION', 'survey_question');
619
define('RESOURCE_SURVEYINVITATION', 'survey_invitation');
620
define('RESOURCE_WIKI', 'wiki');
621
define('RESOURCE_THEMATIC', 'thematic');
622
define('RESOURCE_ATTENDANCE', 'attendance');
623
define('RESOURCE_WORK', 'work');
624
define('RESOURCE_SESSION_COURSE', 'session_course');
625
define('RESOURCE_GRADEBOOK', 'gradebook');
626
define('ADD_THEMATIC_PLAN', 6);
627
628
// Max online users to show per page (whoisonline)
629
define('MAX_ONLINE_USERS', 12);
630
631
// Number of characters maximum to show in preview of course blog posts
632
define('BLOG_MAX_PREVIEW_CHARS', 800);
633
// HTML string to replace with a 'Read more...' link
634
define('BLOG_PAGE_BREAK', '<div style="page-break-after: always"><span style="display: none;">&nbsp;</span></div>');
635
636
// Make sure the CHAMILO_LOAD_WYSIWYG constant is defined
637
// To remove CKeditor libs from HTML, set this constant to true before loading
638
if (!defined('CHAMILO_LOAD_WYSIWYG')) {
639
    define('CHAMILO_LOAD_WYSIWYG', true);
640
}
641
642
/* Constants for course home */
643
define('TOOL_PUBLIC', 'Public');
644
define('TOOL_PUBLIC_BUT_HIDDEN', 'PublicButHide');
645
define('TOOL_COURSE_ADMIN', 'courseAdmin');
646
define('TOOL_PLATFORM_ADMIN', 'platformAdmin');
647
define('TOOL_AUTHORING', 'toolauthoring');
648
define('TOOL_INTERACTION', 'toolinteraction');
649
define('TOOL_COURSE_PLUGIN', 'toolcourseplugin'); //all plugins that can be enabled in courses
650
define('TOOL_ADMIN', 'tooladmin');
651
define('TOOL_ADMIN_PLATFORM', 'tooladminplatform');
652
define('TOOL_DRH', 'tool_drh');
653
define('TOOL_STUDENT_VIEW', 'toolstudentview');
654
define('TOOL_ADMIN_VISIBLE', 'tooladminvisible');
655
656
/**
657
 * Inclusion of internationalization libraries
658
 */
659
require_once __DIR__.'/internationalization.lib.php';
660
661
/**
662
 * Returns a path to a certain resource within the Chamilo area, specifyed through a parameter.
663
 * Also, this function provides conversion between path types, in this case the input path points inside the Chamilo area too.
664
 *
665
 * See $_configuration['course_folder'] in the configuration.php to alter the WEB_COURSE_PATH and SYS_COURSE_PATH parameters.
666
667
 * @param string $path (optional)   A path which type is to be converted. Also, it may be a defined constant for a path.
668
 * This parameter has meaning when $type parameter has one of the following values: TO_WEB, TO_SYS, TO_REL. Otherwise it is ignored.
669
 * @return string                   The requested path or the converted path.
670
 *
671
 *
672
 * Notes about the current behaviour model:
673
 * 1. Windows back-slashes are converted to slashes in the result.
674
 * 2. A semi-absolute web-path is detected by its leading slash. On Linux systems, absolute system paths start with
675
 * a slash too, so an additional check about presence of leading system server base is implemented. For example, the function is
676
 * able to distinguish type difference between /var/www/chamilo/courses/ (SYS) and /chamilo/courses/ (REL).
677
 * 3. The function api_get_path() returns only these three types of paths, which in some sense are absolute. The function has
678
 * no a mechanism for processing relative web/system paths, such as: lesson01.html, ./lesson01.html, ../css/my_styles.css.
679
 * It has not been identified as needed yet.
680
 * 4. Also, resolving the meta-symbols "." and ".." within paths has not been implemented, it is to be identified as needed.
681
 *
682
 * For examples go to: *
683
 * See main/admin/system_status.php?section=paths
684
 *
685
 * Vchamilo changes : allow using an alternate configuration
686
 * to get vchamilo  instance paths
687
 */
688
function api_get_path($path = '', $configuration = [])
689
{
690
    global $paths;
691
692
    // get proper configuration data if exists
693
    global $_configuration;
694
695
    $emptyConfigurationParam = false;
696
    if (empty($configuration)) {
697
        $configuration = (array) $_configuration;
698
        $emptyConfigurationParam = true;
699
    }
700
701
    $course_folder = 'courses/';
702
    static $root_web = '';
703
704
    //var_dump(Container::getRouter()->generate('legacy_index'));exit;
705
706
    $root_sys = Container::getRootDir();
707
708
    // If no $root_web has been set so far *and* no custom config has been passed to the function
709
    // then re-use the previously-calculated (run-specific) $root_web and skip this complex calculation
710
    if (empty($root_web) || $emptyConfigurationParam === false || empty($configuration)) {
711
        // Resolve master hostname.
712
        if (!empty($configuration) && array_key_exists('root_web', $configuration)) {
713
            $root_web = $configuration['root_web'];
714
        } else {
715
            $root_web = '';
716
            // Try guess it from server.
717
            if (defined('SYSTEM_INSTALLATION') && SYSTEM_INSTALLATION) {
718
                if (($pos = strpos(($requested_page_rel = api_get_self()), 'main/install')) !== false) {
719
                    $root_rel = substr($requested_page_rel, 0, $pos);
720
                    // See http://www.mediawiki.org/wiki/Manual:$wgServer
721
                    $server_protocol = (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] == 'on') ? 'https' : 'http';
722
                    $server_name =
723
                        isset($_SERVER['SERVER_NAME']) ? $_SERVER['SERVER_NAME']
724
                            : (isset($_SERVER['HOSTNAME']) ? $_SERVER['HOSTNAME']
725
                            : (isset($_SERVER['HTTP_HOST']) ? $_SERVER['HTTP_HOST']
726
                                : (isset($_SERVER['SERVER_ADDR']) ? $_SERVER['SERVER_ADDR']
727
                                    : 'localhost')));
728
                    if (isset($_SERVER['SERVER_PORT']) && !strpos($server_name, ':')
729
                        && (($server_protocol == 'http'
730
                                && $_SERVER['SERVER_PORT'] != 80) || ($server_protocol == 'https' && $_SERVER['SERVER_PORT'] != 443))
731
                    ) {
732
                        $server_name .= ":".$_SERVER['SERVER_PORT'];
733
                    }
734
                    $root_web = $server_protocol.'://'.$server_name.$root_rel;
735
                    $root_sys = str_replace('\\', '/', realpath(__DIR__.'/../../../')).'/';
736
                }
737
                // Here we give up, so we don't touch anything.
738
            }
739
        }
740
    }
741
742
    if (isset($configuration['multiple_access_urls']) &&
743
        $configuration['multiple_access_urls']
744
    ) {
745
        // To avoid that the api_get_access_url() function fails since global.inc.php also calls the main_api.lib.php
746
        if (isset($configuration['access_url']) && !empty($configuration['access_url'])) {
747
            // We look into the DB the function api_get_access_url
748
            $urlInfo = api_get_access_url($configuration['access_url']);
749
            // Avoid default value
750
            $defaultValues = ['http://localhost/', 'https://localhost/'];
751
            if (!empty($urlInfo['url']) && !in_array($urlInfo['url'], $defaultValues)) {
752
                $root_web = $urlInfo['active'] == 1 ? $urlInfo['url'] : $configuration['root_web'];
753
            }
754
        }
755
    }
756
757
    $paths = [];
758
    // Initialise cache with default values.
759
    if (!array_key_exists($root_web, $paths)) {
760
        $paths[$root_web] = [
761
            WEB_PATH => '',
762
            SYS_PATH => '',
763
            REL_PATH => '',
764
            WEB_COURSE_PATH => '',
765
            SYS_COURSE_PATH => '',
766
            REL_COURSE_PATH => '',
767
            WEB_CODE_PATH => 'main/',
768
            SYS_CODE_PATH => 'main/',
769
            REL_CODE_PATH => '/main/',
770
            SYS_LANG_PATH => 'lang/',
771
            WEB_IMG_PATH => 'img/',
772
            WEB_CSS_PATH => 'public/build/css/',
773
            SYS_CSS_PATH => 'public/build/css/',
774
            SYS_PLUGIN_PATH => 'plugin/',
775
            WEB_PLUGIN_PATH => 'plugin/',
776
            WEB_PLUGIN_ASSET_PATH => 'public/plugins/',
777
            SYS_ARCHIVE_PATH => 'var/cache/',
778
            WEB_ARCHIVE_PATH => 'var/cache/',
779
            SYS_HOME_PATH => 'app/home/',
780
            WEB_HOME_PATH => 'app/home/',
781
            REL_HOME_PATH => 'app/home/',
782
            SYS_APP_PATH => 'var/',
783
            WEB_APP_PATH => 'app/',
784
            SYS_UPLOAD_PATH => 'app/upload/',
785
            SYS_INC_PATH => 'inc/',
786
            CONFIGURATION_PATH => 'app/config/',
787
            LIBRARY_PATH => 'inc/lib/',
788
            WEB_LIBRARY_PATH => 'inc/lib/',
789
            WEB_LIBRARY_JS_PATH => 'inc/lib/javascript/',
790
            WEB_AJAX_PATH => 'inc/ajax/',
791
            SYS_TEST_PATH => 'tests/',
792
            WEB_TEMPLATE_PATH => 'template/',
793
            SYS_TEMPLATE_PATH => 'template/',
794
            WEB_UPLOAD_PATH => 'app/upload/',
795
            WEB_PUBLIC_PATH => 'public/',
796
            SYS_PUBLIC_PATH => 'public/',
797
            WEB_FONTS_PATH => 'fonts/',
798
            SYS_FONTS_PATH => 'fonts/',
799
        ];
800
    }
801
802
    $isInitialized = [];
803
    $course_folder = isset($configuration['course_folder']) ? $configuration['course_folder'] : $course_folder;
804
    $root_rel = isset($configuration['url_append']) ? $configuration['url_append'] : '';
805
806
    // Web server base and system server base.
807
    if (!array_key_exists($root_web, $isInitialized)) {
808
        // process absolute global roots
809
        if (!empty($configuration)) {
810
            $code_folder = 'main';
811
        } else {
812
            $code_folder = $paths[$root_web][REL_CODE_PATH];
813
        }
814
815
        // Support for the installation process.
816
        // Developers might use the function api_get_path() directly or indirectly (this is difficult to be traced), at the moment when
817
        // configuration has not been created yet. This is why this function should be upgraded to return correct results in this case.
818
819
        // Dealing with trailing slashes.
820
        $slashed_root_web = api_add_trailing_slash($root_web);
821
        $root_sys = api_add_trailing_slash($root_sys);
822
        $root_rel = api_add_trailing_slash($root_rel);
823
        $code_folder = api_add_trailing_slash($code_folder);
824
        $course_folder = api_add_trailing_slash($course_folder);
825
826
        // Initialization of a table that contains common-purpose paths.
827
        $paths[$root_web][REL_PATH] = $root_rel;
828
        $paths[$root_web][REL_COURSE_PATH] = $root_rel.$course_folder;
829
        $paths[$root_web][REL_CODE_PATH] = $root_rel.$code_folder;
830
        $paths[$root_web][REL_DEFAULT_COURSE_DOCUMENT_PATH] = $paths[$root_web][REL_PATH].'main/default_course_document/';
831
832
        $paths[$root_web][WEB_PATH] = $slashed_root_web;
833
        $paths[$root_web][WEB_CODE_PATH] = $paths[$root_web][WEB_PATH].$code_folder;
834
        $paths[$root_web][WEB_COURSE_PATH] = $paths[$root_web][WEB_PATH].$course_folder;
835
        $paths[$root_web][WEB_DEFAULT_COURSE_DOCUMENT_PATH] = $paths[$root_web][WEB_CODE_PATH].'default_course_document/';
836
        $paths[$root_web][WEB_APP_PATH] = $paths[$root_web][WEB_PATH].$paths[$root_web][WEB_APP_PATH];
837
        $paths[$root_web][WEB_PLUGIN_PATH] = $paths[$root_web][WEB_PATH].$paths[$root_web][WEB_PLUGIN_PATH];
838
        $paths[$root_web][WEB_PLUGIN_ASSET_PATH] = $paths[$root_web][WEB_PATH].$paths[$root_web][WEB_PLUGIN_ASSET_PATH];
839
        $paths[$root_web][WEB_ARCHIVE_PATH] = $paths[$root_web][WEB_PATH].$paths[$root_web][WEB_ARCHIVE_PATH];
840
841
        $paths[$root_web][WEB_CSS_PATH] = $paths[$root_web][WEB_PATH].$paths[$root_web][WEB_CSS_PATH];
842
        $paths[$root_web][WEB_IMG_PATH] = $paths[$root_web][WEB_CODE_PATH].$paths[$root_web][WEB_IMG_PATH];
843
        $paths[$root_web][WEB_LIBRARY_PATH] = $paths[$root_web][WEB_CODE_PATH].$paths[$root_web][WEB_LIBRARY_PATH];
844
        $paths[$root_web][WEB_LIBRARY_JS_PATH] = $paths[$root_web][WEB_CODE_PATH].$paths[$root_web][WEB_LIBRARY_JS_PATH];
845
        $paths[$root_web][WEB_AJAX_PATH] = $paths[$root_web][WEB_CODE_PATH].$paths[$root_web][WEB_AJAX_PATH];
846
        $paths[$root_web][WEB_FONTS_PATH] = $paths[$root_web][WEB_CODE_PATH].$paths[$root_web][WEB_FONTS_PATH];
847
        $paths[$root_web][WEB_TEMPLATE_PATH] = $paths[$root_web][WEB_CODE_PATH].$paths[$root_web][WEB_TEMPLATE_PATH];
848
        $paths[$root_web][WEB_UPLOAD_PATH] = $paths[$root_web][WEB_PATH].$paths[$root_web][WEB_UPLOAD_PATH];
849
        $paths[$root_web][WEB_PUBLIC_PATH] = $paths[$root_web][WEB_PATH].$paths[$root_web][WEB_PUBLIC_PATH];
850
        $paths[$root_web][WEB_HOME_PATH] = $paths[$root_web][WEB_PATH].$paths[$root_web][REL_HOME_PATH];
851
852
        $paths[$root_web][SYS_PATH] = $root_sys;
853
        $paths[$root_web][SYS_CODE_PATH] = $root_sys.$code_folder;
854
        $paths[$root_web][SYS_TEST_PATH] = $paths[$root_web][SYS_PATH].$paths[$root_web][SYS_TEST_PATH];
855
        $paths[$root_web][SYS_TEMPLATE_PATH] = $paths[$root_web][SYS_CODE_PATH].$paths[$root_web][SYS_TEMPLATE_PATH];
856
        $paths[$root_web][SYS_PUBLIC_PATH] = $paths[$root_web][SYS_PATH].$paths[$root_web][SYS_PUBLIC_PATH];
857
        $paths[$root_web][SYS_CSS_PATH] = $paths[$root_web][SYS_PATH].$paths[$root_web][SYS_CSS_PATH];
858
        $paths[$root_web][SYS_FONTS_PATH] = $paths[$root_web][SYS_CODE_PATH].$paths[$root_web][SYS_FONTS_PATH];
859
        $paths[$root_web][SYS_ARCHIVE_PATH] = $paths[$root_web][SYS_PATH].$paths[$root_web][SYS_ARCHIVE_PATH];
860
        $paths[$root_web][SYS_APP_PATH] = $paths[$root_web][SYS_PATH].$paths[$root_web][SYS_APP_PATH];
861
        $paths[$root_web][SYS_COURSE_PATH] = $paths[$root_web][SYS_APP_PATH].$course_folder;
862
        $paths[$root_web][SYS_UPLOAD_PATH] = $paths[$root_web][SYS_PATH].$paths[$root_web][SYS_UPLOAD_PATH];
863
        $paths[$root_web][SYS_LANG_PATH] = $paths[$root_web][SYS_CODE_PATH].$paths[$root_web][SYS_LANG_PATH];
864
        $paths[$root_web][SYS_HOME_PATH] = $paths[$root_web][SYS_PATH].$paths[$root_web][SYS_HOME_PATH];
865
        $paths[$root_web][SYS_PLUGIN_PATH] = $paths[$root_web][SYS_PATH].$paths[$root_web][SYS_PLUGIN_PATH];
866
        $paths[$root_web][SYS_INC_PATH] = $paths[$root_web][SYS_CODE_PATH].$paths[$root_web][SYS_INC_PATH];
867
868
        $paths[$root_web][LIBRARY_PATH] = $paths[$root_web][SYS_CODE_PATH].$paths[$root_web][LIBRARY_PATH];
869
        $paths[$root_web][CONFIGURATION_PATH] = $paths[$root_web][SYS_PATH].$paths[$root_web][CONFIGURATION_PATH];
870
871
        global $virtualChamilo;
872
        if (!empty($virtualChamilo)) {
873
            $paths[$root_web][SYS_ARCHIVE_PATH] = api_add_trailing_slash($virtualChamilo[SYS_ARCHIVE_PATH]);
874
            $paths[$root_web][SYS_HOME_PATH] = api_add_trailing_slash($virtualChamilo[SYS_HOME_PATH]);
875
            $paths[$root_web][SYS_COURSE_PATH] = api_add_trailing_slash($virtualChamilo[SYS_COURSE_PATH]);
876
            $paths[$root_web][SYS_UPLOAD_PATH] = api_add_trailing_slash($virtualChamilo[SYS_UPLOAD_PATH]);
877
878
            $paths[$root_web][WEB_HOME_PATH] = api_add_trailing_slash($virtualChamilo[WEB_HOME_PATH]);
879
            $paths[$root_web][WEB_UPLOAD_PATH] = api_add_trailing_slash($virtualChamilo[WEB_UPLOAD_PATH]);
880
            $paths[$root_web][WEB_ARCHIVE_PATH] = api_add_trailing_slash($virtualChamilo[WEB_ARCHIVE_PATH]);
881
            //$paths[$root_web][WEB_COURSE_PATH] = api_add_trailing_slash($virtualChamilo[WEB_COURSE_PATH]);
882
883
            // WEB_UPLOAD_PATH should be handle by apache htaccess in the vhost
884
885
            // RewriteEngine On
886
            // RewriteRule /app/upload/(.*)$ http://localhost/other/upload/my-chamilo111-net/$1 [QSA,L]
887
888
            //$paths[$root_web][WEB_UPLOAD_PATH] = api_add_trailing_slash($virtualChamilo[WEB_UPLOAD_PATH]);
889
            //$paths[$root_web][REL_PATH] = $virtualChamilo[REL_PATH];
890
            //$paths[$root_web][REL_COURSE_PATH] = $virtualChamilo[REL_COURSE_PATH];
891
        }
892
893
        $isInitialized[$root_web] = true;
894
    }
895
896
    $path = trim($path);
897
898
    // Retrieving a common-purpose path.
899
    if (isset($paths[$root_web][$path])) {
900
        return $paths[$root_web][$path];
901
    }
902
903
    // Second purification.
904
905
    // Replacing Windows back slashes.
906
    $path = str_replace('\\', '/', $path);
907
    // Query strings sometimes mighth wrongly appear in non-URLs.
908
    // Let us check remove them from all types of paths.
909
    if (($pos = strpos($path, '?')) !== false) {
910
        $path = substr($path, 0, $pos);
911
    }
912
913
    // Detection of the input path type. Conversion to semi-absolute type ( /chamilo/main/inc/.... ).
914
915
    if (preg_match(VALID_WEB_PATH, $path)) {
916
        // A special case: When a URL points to the document download script directly, without
917
        // mod-rewrite translation, we have to translate it into an "ordinary" web path.
918
        // For example:
919
        // http://localhost/chamilo/main/document/download.php?doc_url=/image.png&cDir=/
920
        // becomes
921
        // http://localhost/chamilo/courses/TEST/document/image.png
922
        // TEST is a course directory name, so called "system course code".
923
        if (strpos($path, 'download.php') !== false) { // Fast detection first.
924
            $path = urldecode($path);
925
            if (preg_match('/(.*)main\/document\/download.php\?doc_url=\/(.*)&cDir=\/(.*)?/', $path, $matches)) {
926
                $sys_course_code =
927
                    isset($_SESSION['_course']['sysCode'])  // User is inside a course?
928
                        ? $_SESSION['_course']['sysCode']   // Yes, then use course's directory name.
929
                        : '{SYS_COURSE_CODE}'; // No, then use a fake code, it may be processed later.
930
                $path = $matches[1].'courses/'.$sys_course_code.'/document/'.str_replace('//', '/', $matches[3].'/'.$matches[2]);
931
            }
932
        }
933
        // Replacement of the present web server base with a slash '/'.
934
        $path = preg_replace(VALID_WEB_SERVER_BASE, '/', $path);
935
    }
936
937
    // Path now is semi-absolute. It is convenient at this moment repeated slashes to be removed.
938
    $path = preg_replace(REPEATED_SLASHES_PURIFIER, '/', $path);
939
940
    return $path;
941
}
942
943
/**
944
 * Gets a modified version of the path for the CDN, if defined in
945
 * configuration.php
946
 * @param string $web_path The path of the resource without CDN
947
 * @return string The path of the resource converted to CDN
948
 * @author Yannick Warnier <[email protected]>
949
 */
950
function api_get_cdn_path($web_path)
951
{
952
    global $_configuration;
953
    $web_root = api_get_path(WEB_PATH);
954
    $ext = substr($web_path, strrpos($web_path, '.'));
955
    if (isset($ext[2])) { // faster version of strlen to check if len>2
956
        // Check for CDN definitions
957
        if (!empty($_configuration['cdn_enable']) && !empty($ext)) {
958
            foreach ($_configuration['cdn'] as $host => $exts) {
959
                if (in_array($ext, $exts)) {
960
                    //Use host as defined in $_configuration['cdn'], without
961
                    // trailing slash
962
                    return str_replace($web_root, $host.'/', $web_path);
963
                }
964
            }
965
        }
966
    }
967
    return $web_path;
968
}
969
970
/**
971
 * @return bool Return true if CAS authentification is activated
972
 *
973
 */
974
function api_is_cas_activated()
975
{
976
    return api_get_setting('cas_activate') == "true";
977
}
978
979
/**
980
 * @return bool     Return true if LDAP authentification is activated
981
 *
982
 */
983
function api_is_ldap_activated()
984
{
985
    global $extAuthSource;
986
    return is_array($extAuthSource[LDAP_AUTH_SOURCE]);
987
}
988
989
/**
990
 * @return bool     Return true if Facebook authentification is activated
991
 *
992
 */
993
function api_is_facebook_auth_activated()
994
{
995
    global $_configuration;
996
    return (isset($_configuration['facebook_auth']) && $_configuration['facebook_auth'] == 1);
997
}
998
999
/**
1000
 * Adds to a given path a trailing slash if it is necessary (adds "/" character at the end of the string).
1001
 * @param string $path          The input path.
1002
 * @return string               Returns the modified path.
1003
 */
1004
function api_add_trailing_slash($path)
1005
{
1006
    return substr($path, -1) == '/' ? $path : $path.'/';
1007
}
1008
1009
/**
1010
 * Removes from a given path the trailing slash if it is necessary (removes "/" character from the end of the string).
1011
 * @param string $path          The input path.
1012
 * @return string               Returns the modified path.
1013
 */
1014
function api_remove_trailing_slash($path)
1015
{
1016
    return substr($path, -1) == '/' ? substr($path, 0, -1) : $path;
1017
}
1018
1019
/**
1020
 * Checks the RFC 3986 syntax of a given URL.
1021
 * @param string $url       The URL to be checked.
1022
 * @param bool $absolute    Whether the URL is absolute (beginning with a scheme such as "http:").
1023
 * @return string|false             Returns the URL if it is valid, FALSE otherwise.
1024
 * This function is an adaptation from the function valid_url(), Drupal CMS.
1025
 * @link http://drupal.org
1026
 * Note: The built-in function filter_var($urs, FILTER_VALIDATE_URL) has a bug for some versions of PHP.
1027
 * @link http://bugs.php.net/51192
1028
 */
1029
function api_valid_url($url, $absolute = false)
1030
{
1031
    if ($absolute) {
1032
        if (preg_match("
1033
            /^                                                      # Start at the beginning of the text
1034
            (?:ftp|https?|feed):\/\/                                # Look for ftp, http, https or feed schemes
1035
            (?:                                                     # Userinfo (optional) which is typically
1036
                (?:(?:[\w\.\-\+!$&'\(\)*\+,;=]|%[0-9a-f]{2})+:)*    # a username or a username and password
1037
                (?:[\w\.\-\+%!$&'\(\)*\+,;=]|%[0-9a-f]{2})+@        # combination
1038
            )?
1039
            (?:
1040
                (?:[a-z0-9\-\.]|%[0-9a-f]{2})+                      # A domain name or a IPv4 address
1041
                |(?:\[(?:[0-9a-f]{0,4}:)*(?:[0-9a-f]{0,4})\])       # or a well formed IPv6 address
1042
            )
1043
            (?::[0-9]+)?                                            # Server port number (optional)
1044
            (?:[\/|\?]
1045
                (?:[\w#!:\.\?\+=&@$'~*,;\/\(\)\[\]\-]|%[0-9a-f]{2}) # The path and query (optional)
1046
            *)?
1047
            $/xi", $url)) {
1048
            return $url;
1049
        }
1050
        return false;
1051
    } else {
1052
        return preg_match("/^(?:[\w#!:\.\?\+=&@$'~*,;\/\(\)\[\]\-]|%[0-9a-f]{2})+$/i", $url) ? $url : false;
1053
    }
1054
}
1055
1056
/**
1057
 * Checks whether a given string looks roughly like an email address.
1058
 *
1059
 * @param string $address   The e-mail address to be checked.
1060
 * @return mixed            Returns the e-mail if it is valid, FALSE otherwise.
1061
 */
1062
function api_valid_email($address)
1063
{
1064
    return filter_var($address, FILTER_VALIDATE_EMAIL);
1065
}
1066
1067
/* PROTECTION FUNCTIONS
1068
   Use these functions to protect your scripts. */
1069
1070
/**
1071
 * Function used to protect a course script.
1072
 * The function blocks access when
1073
 * - there is no $_SESSION["_course"] defined; or
1074
 * - $is_allowed_in_course is set to false (this depends on the course
1075
 * visibility and user status).
1076
 *
1077
 * This is only the first proposal, test and improve!
1078
 * @param boolean Option to print headers when displaying error message. Default: false
1079
 * @param boolean Whether session admins should be allowed or not.
1080
 * @return boolean True if the user has access to the current course or is out of a course context, false otherwise
1081
 * @todo replace global variable
1082
 * @author Roan Embrechts
1083
 */
1084
function api_protect_course_script($print_headers = false, $allow_session_admins = false, $allow_drh = false)
1085
{
1086
    $is_allowed_in_course = api_is_allowed_in_course();
1087
1088
    $is_visible = false;
1089
    $course_info = api_get_course_info();
1090
1091
    if (empty($course_info)) {
1092
        api_not_allowed($print_headers);
1093
        return false;
1094
    }
1095
1096
    if (api_is_drh()) {
1097
        return true;
1098
    }
1099
1100
    // Session admin has access to course
1101
    $sessionAccess = api_get_configuration_value('session_admins_access_all_content');
1102
    if ($sessionAccess) {
1103
        $allow_session_admins = true;
1104
    }
1105
1106
    if (api_is_platform_admin($allow_session_admins)) {
1107
        return true;
1108
    }
1109
1110
    if (isset($course_info) && isset($course_info['visibility'])) {
1111
        switch ($course_info['visibility']) {
1112
            default:
1113
            case COURSE_VISIBILITY_CLOSED:
1114
                // Completely closed: the course is only accessible to the teachers. - 0
1115
                if (api_get_user_id() && !api_is_anonymous() && $is_allowed_in_course) {
1116
                    $is_visible = true;
1117
                }
1118
                break;
1119
            case COURSE_VISIBILITY_REGISTERED:
1120
                // Private - access authorized to course members only - 1
1121
                if (api_get_user_id() && !api_is_anonymous() && $is_allowed_in_course) {
1122
                    $is_visible = true;
1123
                }
1124
                break;
1125
            case COURSE_VISIBILITY_OPEN_PLATFORM:
1126
                // Open - access allowed for users registered on the platform - 2
1127
                if (api_get_user_id() && !api_is_anonymous() && $is_allowed_in_course) {
1128
                    $is_visible = true;
1129
                }
1130
                break;
1131
            case COURSE_VISIBILITY_OPEN_WORLD:
1132
                //Open - access allowed for the whole world - 3
1133
                $is_visible = true;
1134
                break;
1135
            case COURSE_VISIBILITY_HIDDEN:
1136
                //Completely closed: the course is only accessible to the teachers. - 0
1137
                if (api_is_platform_admin()) {
1138
                    $is_visible = true;
1139
                }
1140
                break;
1141
        }
1142
1143
        //If password is set and user is not registered to the course then the course is not visible
1144
        if ($is_allowed_in_course == false &&
1145
            isset($course_info['registration_code']) &&
1146
            !empty($course_info['registration_code'])
1147
        ) {
1148
            $is_visible = false;
1149
        }
1150
    }
1151
1152
    // Check session visibility
1153
    $session_id = api_get_session_id();
1154
1155
    if (!empty($session_id)) {
1156
        //$is_allowed_in_course was set in local.inc.php
1157
        if (!$is_allowed_in_course) {
1158
            $is_visible = false;
1159
        }
1160
    }
1161
1162
    if (!$is_visible) {
1163
        api_not_allowed($print_headers);
1164
        return false;
1165
    }
1166
    return true;
1167
}
1168
1169
/**
1170
 * Function used to protect an admin script.
1171
 *
1172
 * The function blocks access when the user has no platform admin rights
1173
 * with an error message printed on default output
1174
 * @param bool Whether to allow session admins as well
1175
 * @param bool Whether to allow HR directors as well
1176
 * @param string An optional message (already passed through get_lang)
1177
 * @return bool True if user is allowed, false otherwise.
1178
 * The function also outputs an error message in case not allowed
1179
 * @author Roan Embrechts (original author)
1180
 */
1181
function api_protect_admin_script($allow_sessions_admins = false, $allow_drh = false, $message = null)
1182
{
1183
    if (!api_is_platform_admin($allow_sessions_admins, $allow_drh)) {
1184
        api_not_allowed(true, $message);
1185
        return false;
1186
    }
1187
    return true;
1188
}
1189
1190
/**
1191
 * Function used to protect a teacher script.
1192
 * The function blocks access when the user has no teacher rights.
1193
 *
1194
 * @author Yoselyn Castillo
1195
 */
1196
function api_protect_teacher_script($allow_sessions_admins = false)
1197
{
1198
    if (!api_is_allowed_to_edit()) {
1199
        api_not_allowed(true);
1200
        return false;
1201
    }
1202
    return true;
1203
}
1204
1205
/**
1206
 * Function used to prevent anonymous users from accessing a script.
1207
 * @param bool|true $printHeaders
1208
 * @author Roan Embrechts
1209
 *
1210
 * @return bool
1211
 */
1212
function api_block_anonymous_users($printHeaders = true)
1213
{
1214
    $user = api_get_user_info();
1215
    if (!(isset($user['user_id']) && $user['user_id']) || api_is_anonymous($user['user_id'], true)) {
1216
        api_not_allowed($printHeaders);
1217
        return false;
1218
    }
1219
1220
    return true;
1221
}
1222
1223
/**
1224
 * @return array with the navigator name and version
1225
 */
1226
function api_get_navigator()
1227
{
1228
    $navigator = 'Unknown';
1229
    $version = 0;
1230
1231
    if (!isset($_SERVER['HTTP_USER_AGENT'])) {
1232
        return ['name' => 'Unknown', 'version' => '0.0.0'];
1233
    }
1234
1235
    if (strpos($_SERVER['HTTP_USER_AGENT'], 'Opera') !== false) {
1236
        $navigator = 'Opera';
1237
        list(, $version) = explode('Opera', $_SERVER['HTTP_USER_AGENT']);
1238
    } elseif (strpos($_SERVER['HTTP_USER_AGENT'], 'MSIE') !== false) {
1239
        $navigator = 'Internet Explorer';
1240
        list(, $version) = explode('MSIE', $_SERVER['HTTP_USER_AGENT']);
1241
    } elseif (strpos($_SERVER['HTTP_USER_AGENT'], 'Chrome') !== false) {
1242
        $navigator = 'Chrome';
1243
        list(, $version) = explode('Chrome', $_SERVER['HTTP_USER_AGENT']);
1244
    } elseif (stripos($_SERVER['HTTP_USER_AGENT'], 'safari') !== false) {
1245
        $navigator = 'Safari';
1246
        list(, $version) = explode('Version/', $_SERVER['HTTP_USER_AGENT']);
1247
    } elseif (strpos($_SERVER['HTTP_USER_AGENT'], 'Gecko') !== false) {
1248
        $navigator = 'Mozilla';
1249
        list(, $version) = explode('; rv:', $_SERVER['HTTP_USER_AGENT']);
1250
    } elseif (strpos($_SERVER['HTTP_USER_AGENT'], 'Netscape') !== false) {
1251
        $navigator = 'Netscape';
1252
        list(, $version) = explode('Netscape', $_SERVER['HTTP_USER_AGENT']);
1253
    } elseif (strpos($_SERVER['HTTP_USER_AGENT'], 'Konqueror') !== false) {
1254
        $navigator = 'Konqueror';
1255
        list(, $version) = explode('Konqueror', $_SERVER['HTTP_USER_AGENT']);
1256
    } elseif (stripos($_SERVER['HTTP_USER_AGENT'], 'applewebkit') !== false) {
1257
        $navigator = 'AppleWebKit';
1258
        list(, $version) = explode('Version/', $_SERVER['HTTP_USER_AGENT']);
1259
    }
1260
    $version = str_replace('/', '', $version);
1261
    if (strpos($version, '.') === false) {
1262
        $version = number_format(doubleval($version), 1);
1263
    }
1264
    $return = ['name' => $navigator, 'version' => $version];
1265
    return $return;
1266
}
1267
1268
/**
1269
 * @return True if user self registration is allowed, false otherwise.
1270
 */
1271
function api_is_self_registration_allowed()
1272
{
1273
    return isset($GLOBALS['allowSelfReg']) ? $GLOBALS['allowSelfReg'] : false;
1274
}
1275
1276
/**
1277
 * This function returns the id of the user which is stored in the $_user array.
1278
 *
1279
 * example: The function can be used to check if a user is logged in
1280
 *          if (api_get_user_id())
1281
 * @return int the id of the current user, 0 if is empty
1282
 */
1283
function api_get_user_id()
1284
{
1285
    $userInfo = Session::read('_user');
1286
    if ($userInfo && isset($userInfo['user_id'])) {
1287
        return (int) $userInfo['user_id'];
1288
    }
1289
    return 0;
1290
}
1291
1292
/**
1293
 * Gets the list of courses a specific user is subscribed to
1294
 * @param int       User ID
1295
 * @param boolean   $fetch_session Whether to get session courses or not - NOT YET IMPLEMENTED
1296
 * @return array    Array of courses in the form [0]=>('code'=>xxx,'db'=>xxx,'dir'=>xxx,'status'=>d)
1297
 * @deprecated use CourseManager::get_courses_list_by_user_id()
1298
 */
1299
function api_get_user_courses($userid, $fetch_session = true)
1300
{
1301
    // Get out if not integer
1302
    if ($userid != strval(intval($userid))) {
1303
        return [];
1304
    }
1305
1306
    $t_course = Database::get_main_table(TABLE_MAIN_COURSE);
1307
    $t_course_user = Database::get_main_table(TABLE_MAIN_COURSE_USER);
1308
1309
    $sql = "SELECT cc.id as real_id, cc.code code, cc.directory dir, cu.status status
1310
            FROM    $t_course       cc,
1311
                    $t_course_user   cu
1312
            WHERE
1313
                cc.id = cu.c_id AND
1314
                cu.user_id = '".$userid."' AND
1315
                cu.relation_type<>".COURSE_RELATION_TYPE_RRHH." ";
1316
    $result = Database::query($sql);
1317
    if ($result === false) {
1318
        return [];
1319
    }
1320
1321
    $courses = [];
1322
    while ($row = Database::fetch_array($result)) {
1323
        // we only need the database name of the course
1324
        $courses[] = $row;
1325
    }
1326
1327
    return $courses;
1328
}
1329
1330
/**
1331
 * Formats user information into a standard array
1332
 * This function should be only used inside api_get_user_info()
1333
 *
1334
 * @param array Non-standard user array
1335
 * @param bool $add_password
1336
 * @param bool $loadAvatars turn off to improve performance
1337
 *
1338
 * @return array Standard user array
1339
 */
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...
1340
function _api_format_user($user, $add_password = false, $loadAvatars = true)
1341
{
1342
    $result = [];
1343
1344
    $result['firstname'] = null;
1345
    $result['lastname'] = null;
1346
1347
    if (isset($user['firstname']) && isset($user['lastname'])) { // with only lowercase
1348
        $result['firstname'] = $user['firstname'];
1349
        $result['lastname'] = $user['lastname'];
1350
    } elseif (isset($user['firstName']) && isset($user['lastName'])) { // with uppercase letters
1351
        $result['firstname'] = isset($user['firstName']) ? $user['firstName'] : null;
1352
        $result['lastname'] = isset($user['lastName']) ? $user['lastName'] : null;
1353
    }
1354
1355
    if (isset($user['email'])) {
1356
        $result['mail'] = isset($user['email']) ? $user['email'] : null;
1357
        $result['email'] = isset($user['email']) ? $user['email'] : null;
1358
    } else {
1359
        $result['mail'] = isset($user['mail']) ? $user['mail'] : null;
1360
        $result['email'] = isset($user['mail']) ? $user['mail'] : null;
1361
    }
1362
1363
    $result['complete_name'] = api_get_person_name($result['firstname'], $result['lastname']);
1364
    $result['complete_name_with_username'] = $result['complete_name'];
1365
1366
    if (!empty($user['username'])) {
1367
        $result['complete_name_with_username'] = $result['complete_name'].' ('.$user['username'].')';
1368
    }
1369
1370
    $showEmail = api_get_setting('show_email_addresses') === 'true';
1371
    if (!empty($user['email'])) {
1372
        $result['complete_name_with_email_forced'] = $result['complete_name'].' ('.$user['email'].')';
1373
        if ($showEmail) {
1374
            $result['complete_name_with_email'] = $result['complete_name'].' ('.$user['email'].')';
1375
        }
1376
    } else {
1377
        $result['complete_name_with_email'] = $result['complete_name'];
1378
        $result['complete_name_with_email_forced'] = $result['complete_name'];
1379
    }
1380
1381
    // Kept for historical reasons
1382
    $result['firstName'] = $result['firstname'];
1383
    $result['lastName'] = $result['lastname'];
1384
1385
    $attributes = [
1386
        'phone',
1387
        'address',
1388
        'picture_uri',
1389
        'official_code',
1390
        'status',
1391
        'active',
1392
        'auth_source',
1393
        'username',
1394
        'theme',
1395
        'language',
1396
        'creator_id',
1397
        'registration_date',
1398
        'hr_dept_id',
1399
        'expiration_date',
1400
        'last_login',
1401
        'user_is_online'
1402
    ];
1403
1404
    if (api_get_setting('extended_profile') === 'true') {
1405
        $attributes[] = 'competences';
1406
        $attributes[] = 'diplomas';
1407
        $attributes[] = 'teach';
1408
        $attributes[] = 'openarea';
1409
    }
1410
1411
    foreach ($attributes as $attribute) {
1412
        $result[$attribute] = isset($user[$attribute]) ? $user[$attribute] : null;
1413
    }
1414
1415
    $user_id = intval($user['user_id']);
1416
    // Maintain the user_id index for backwards compatibility
1417
    $result['user_id'] = $result['id'] = $user_id;
1418
1419
    // Getting user avatar.
1420
    if ($loadAvatars) {
1421
        $result['avatar'] = '';
1422
        $result['avatar_no_query'] = '';
1423
        $result['avatar_small'] = '';
1424
        $result['avatar_medium'] = '';
1425
1426
        if (!isset($user['avatar'])) {
1427
            $originalFile = UserManager::getUserPicture(
1428
                $user_id,
1429
                USER_IMAGE_SIZE_ORIGINAL,
1430
                null,
1431
                $result
1432
            );
1433
            $result['avatar'] = $originalFile;
1434
            $avatarString = explode('?', $result['avatar']);
1435
            $result['avatar_no_query'] = reset($avatarString);
1436
        } else {
1437
            $result['avatar'] = $user['avatar'];
1438
            $avatarString = explode('?', $user['avatar']);
1439
            $result['avatar_no_query'] = reset($avatarString);
1440
        }
1441
1442
        if (!isset($user['avatar_small'])) {
1443
            $smallFile = UserManager::getUserPicture(
1444
                $user_id,
1445
                USER_IMAGE_SIZE_SMALL,
1446
                null,
1447
                $result
1448
            );
1449
            $result['avatar_small'] = $smallFile;
1450
        } else {
1451
            $result['avatar_small'] = $user['avatar_small'];
1452
        }
1453
1454
        if (!isset($user['avatar_medium'])) {
1455
            $mediumFile = UserManager::getUserPicture(
1456
                $user_id,
1457
                USER_IMAGE_SIZE_MEDIUM,
1458
                null,
1459
                $result
1460
            );
1461
            $result['avatar_medium'] = $mediumFile;
1462
        } else {
1463
            $result['avatar_medium'] = $user['avatar_medium'];
1464
        }
1465
    }
1466
1467
    if (isset($user['user_is_online'])) {
1468
        $result['user_is_online'] = $user['user_is_online'] == true ? 1 : 0;
1469
    }
1470
    if (isset($user['user_is_online_in_chat'])) {
1471
        $result['user_is_online_in_chat'] = intval($user['user_is_online_in_chat']);
1472
    }
1473
1474
    if ($add_password) {
1475
        $result['password'] = $user['password'];
1476
    }
1477
1478
    if (isset($result['profile_completed'])) {
1479
        $result['profile_completed'] = $user['profile_completed'];
1480
    }
1481
1482
    $result['profile_url'] = api_get_path(WEB_CODE_PATH).'social/profile.php?u='.$user_id;
1483
1484
    // Send message link
1485
    $sendMessage = api_get_path(WEB_AJAX_PATH).'user_manager.ajax.php?a=get_user_popup&user_id='.$user_id;
1486
    $result['complete_name_with_message_link'] = Display::url(
1487
        $result['complete_name_with_username'],
1488
        $sendMessage,
1489
        ['class' => 'ajax']
1490
    );
1491
1492
    if (isset($user['extra'])) {
1493
        $result['extra'] = $user['extra'];
1494
    }
1495
1496
    return $result;
1497
}
1498
1499
/**
1500
 * Finds all the information about a user.
1501
 * If no parameter is passed you find all the information about the current user.
1502
 * @param int  $user_id
1503
 * @param bool $checkIfUserOnline
1504
 * @param bool $showPassword
1505
 * @param bool $loadExtraData
1506
 * @param bool $loadOnlyVisibleExtraData Get the user extra fields that are visible
1507
 * @param bool $loadAvatars turn off to improve performance and if avatars are not needed.
1508
 * @param bool $updateCache update apc cache if exists
1509
 *
1510
 * @return array $user_info user_id, lastname, firstname, username, email, etc
1511
 * @author Patrick Cool <[email protected]>
1512
 * @author Julio Montoya
1513
 * @version 21 September 2004
1514
 */
1515
function api_get_user_info(
1516
    $user_id = 0,
1517
    $checkIfUserOnline = false,
1518
    $showPassword = false,
1519
    $loadExtraData = false,
1520
    $loadOnlyVisibleExtraData = false,
1521
    $loadAvatars = true,
1522
    $updateCache = false
1523
) {
1524
    $apcVar = null;
1525
    $user = false;
1526
    $cacheAvailable = api_get_configuration_value('apc');
1527
1528
    if (empty($user_id)) {
1529
        $userFromSession = Session::read('_user');
1530
1531
        if (isset($userFromSession)) {
1532
            if ($cacheAvailable === true) {
1533
                $apcVar = api_get_configuration_value('apc_prefix').'userinfo_'.$userFromSession['user_id'];
1534
                if (apcu_exists($apcVar)) {
1535
                    if ($updateCache) {
1536
                        apcu_store($apcVar, $userFromSession, 60);
1537
                    }
1538
                    $user = apcu_fetch($apcVar);
1539
                } else {
1540
                    $user = _api_format_user(
1541
                        $userFromSession,
1542
                        $showPassword,
1543
                        $loadAvatars
1544
                    );
1545
                    apcu_store($apcVar, $user, 60);
1546
                }
1547
            } else {
1548
                $user = _api_format_user(
1549
                    $userFromSession,
1550
                    $showPassword,
1551
                    $loadAvatars
1552
                );
1553
            }
1554
1555
            return $user;
1556
        }
1557
1558
        return false;
1559
    }
1560
1561
    // Make sure user_id is safe
1562
    $user_id = intval($user_id);
1563
1564
    // Re-use user information if not stale and already stored in APCu
1565
    if ($cacheAvailable === true) {
1566
        $apcVar = api_get_configuration_value('apc_prefix').'userinfo_'.$user_id;
1567
        if (apcu_exists($apcVar) && $updateCache == false && $checkIfUserOnline == false) {
1568
            $user = apcu_fetch($apcVar);
1569
1570
            return $user;
1571
        }
1572
    }
1573
1574
    $sql = "SELECT * FROM ".Database::get_main_table(TABLE_MAIN_USER)."
1575
            WHERE id = $user_id";
1576
    $result = Database::query($sql);
1577
    if (Database::num_rows($result) > 0) {
1578
        $result_array = Database::fetch_array($result);
1579
        if ($checkIfUserOnline) {
1580
            $use_status_in_platform = user_is_online($user_id);
1581
            $result_array['user_is_online'] = $use_status_in_platform;
1582
            $user_online_in_chat = 0;
1583
1584
            if ($use_status_in_platform) {
1585
                $user_status = UserManager::get_extra_user_data_by_field(
1586
                    $user_id,
1587
                    'user_chat_status',
1588
                    false,
1589
                    true
1590
                );
1591
                if (@intval($user_status['user_chat_status']) == 1) {
1592
                    $user_online_in_chat = 1;
1593
                }
1594
            }
1595
            $result_array['user_is_online_in_chat'] = $user_online_in_chat;
1596
        }
1597
1598
        if ($loadExtraData) {
1599
            $fieldValue = new ExtraFieldValue('user');
1600
            $result_array['extra'] = $fieldValue->getAllValuesForAnItem(
1601
                $user_id,
1602
                $loadOnlyVisibleExtraData
1603
            );
1604
        }
1605
        $user = _api_format_user($result_array, $showPassword, $loadAvatars);
1606
    }
1607
1608
    if ($cacheAvailable === true) {
1609
        apcu_store($apcVar, $user, 60);
1610
    }
1611
1612
    return $user;
1613
}
1614
1615
/**
1616
 * @param int $userId
1617
 * @return User
1618
 */
1619
function api_get_user_entity($userId)
1620
{
1621
    $userId = (int) $userId;
1622
    /** @var \Chamilo\UserBundle\Repository\UserRepository $repo */
1623
    $repo = Database::getManager()->getRepository('ChamiloUserBundle:User');
1624
1625
    return $repo->find($userId);
1626
}
1627
1628
/**
1629
 * Finds all the information about a user from username instead of user id
1630
 * @param string $username
1631
 * @return array $user_info array user_id, lastname, firstname, username, email
1632
 * @author Yannick Warnier <[email protected]>
1633
 */
1634
function api_get_user_info_from_username($username = '')
1635
{
1636
    if (empty($username)) {
1637
        return false;
1638
    }
1639
    $username = trim($username);
1640
1641
    $sql = "SELECT * FROM ".Database::get_main_table(TABLE_MAIN_USER)."
1642
            WHERE username='".Database::escape_string($username)."'";
1643
    $result = Database::query($sql);
1644
    if (Database::num_rows($result) > 0) {
1645
        $result_array = Database::fetch_array($result);
1646
        return _api_format_user($result_array);
1647
    }
1648
    return false;
1649
}
1650
1651
/**
1652
 * Get first user with an email
1653
 * @param string $email
1654
 * @return array|bool
1655
 */
1656
function api_get_user_info_from_email($email = '')
1657
{
1658
    if (empty($email)) {
1659
        return false;
1660
    }
1661
    $sql = "SELECT * FROM ".Database::get_main_table(TABLE_MAIN_USER)."
1662
            WHERE email ='".Database::escape_string($email)."' LIMIT 1";
1663
    $result = Database::query($sql);
1664
    if (Database::num_rows($result) > 0) {
1665
        $result_array = Database::fetch_array($result);
1666
        return _api_format_user($result_array);
1667
    }
1668
1669
    return false;
1670
}
1671
1672
/**
1673
 * @return string
1674
 */
1675
function api_get_course_id()
1676
{
1677
    return Session::read('_cid', null);
1678
}
1679
1680
/**
1681
 * Returns the current course id (integer)
1682
 * @param   string  $code   Optional course code
1683
 * @return int
1684
 */
1685
function api_get_course_int_id($code = null)
1686
{
1687
    if (!empty($code)) {
1688
        $code = Database::escape_string($code);
1689
        $row = Database::select(
1690
            'id',
1691
            Database::get_main_table(TABLE_MAIN_COURSE),
1692
            ['where'=> ['code = ?' => [$code]]],
1693
            'first'
1694
        );
1695
1696
        if (is_array($row) && isset($row['id'])) {
1697
            return $row['id'];
1698
        } else {
1699
            return false;
1700
        }
1701
    }
1702
    return Session::read('_real_cid', 0);
1703
}
1704
1705
/**
1706
 * Returns the current course directory
1707
 *
1708
 * This function relies on api_get_course_info()
1709
 * @param string    The course code - optional (takes it from session if not given)
1710
 * @return string   The directory where the course is located inside the Chamilo "courses" directory
1711
 * @author Yannick Warnier <[email protected]>
1712
 */
1713
function api_get_course_path($course_code = null)
1714
{
1715
    $info = !empty($course_code) ? api_get_course_info($course_code) : api_get_course_info();
1716
    return $info['path'];
1717
}
1718
1719
/**
1720
 * Gets a course setting from the current course_setting table. Try always using integer values.
1721
 * @param string    The name of the setting we want from the table
1722
 * @param string    Optional: course code
1723
 * @param string $setting_name
1724
 * @return mixed    The value of that setting in that table. Return -1 if not found.
1725
 */
1726
function api_get_course_setting($setting_name, $course_code = null)
1727
{
1728
    $course_info = api_get_course_info($course_code);
1729
    $table = Database::get_course_table(TABLE_COURSE_SETTING);
1730
    $setting_name = Database::escape_string($setting_name);
1731
    if (!empty($course_info['real_id']) && !empty($setting_name)) {
1732
        $sql = "SELECT value FROM $table
1733
                WHERE c_id = {$course_info['real_id']} AND variable = '$setting_name'";
1734
        $res = Database::query($sql);
1735
        if (Database::num_rows($res) > 0) {
1736
            $row = Database::fetch_array($res);
1737
            if ($setting_name === 'email_alert_manager_on_new_quiz') {
1738
                if (!is_null($row['value'])) {
1739
                    $result = explode(',', $row['value']);
1740
                    $row['value'] = $result;
1741
                }
1742
            }
1743
            return $row['value'];
1744
        }
1745
    }
1746
    return -1;
1747
}
1748
1749
/**
1750
 * Gets an anonymous user ID
1751
 *
1752
 * For some tools that need tracking, like the learnpath tool, it is necessary
1753
 * to have a usable user-id to enable some kind of tracking, even if not
1754
 * perfect. An anonymous ID is taken from the users table by looking for a
1755
 * status of "6" (anonymous).
1756
 * @return int  User ID of the anonymous user, or O if no anonymous user found
1757
 */
1758
function api_get_anonymous_id()
1759
{
1760
    // Find if another anon is connected now
1761
    $table = Database::get_main_table(TABLE_STATISTIC_TRACK_E_LOGIN);
1762
    $tableU = Database::get_main_table(TABLE_MAIN_USER);
1763
    $ip = api_get_real_ip();
1764
    $max = api_get_configuration_value('max_anonymous_users');
1765
    if ($max >= 2) {
1766
        $sql = "SELECT * FROM $table as TEL 
1767
                JOIN $tableU as U
1768
                ON U.user_id = TEL.login_user_id
1769
                WHERE TEL.user_ip = '$ip'
1770
                    AND U.status = ".ANONYMOUS."
1771
                    AND U.user_id != 2 ";
1772
1773
        $result = Database::query($sql);
1774
        if (empty(Database::num_rows($result))) {
1775
            $login = uniqid('anon_');
1776
            $anonList = UserManager::get_user_list(['status' => ANONYMOUS], ['registration_date ASC']);
1777
            if (count($anonList) == $max) {
1778
                foreach ($anonList as $userToDelete) {
1779
                    UserManager::delete_user($userToDelete['user_id']);
1780
                    break;
1781
                }
1782
            }
1783
            $userId = UserManager::create_user(
1784
                $login,
1785
                'anon',
1786
                ANONYMOUS,
1787
                ' anonymous@localhost',
1788
                $login,
1789
                $login
1790
            );
1791
            return $userId;
1792
        } else {
1793
            $row = Database::fetch_array($result, 'ASSOC');
1794
            return $row['user_id'];
1795
        }
1796
    }
1797
1798
    $table = Database::get_main_table(TABLE_MAIN_USER);
1799
    $sql = "SELECT user_id 
1800
            FROM $table 
1801
            WHERE status = ".ANONYMOUS." ";
1802
    $res = Database::query($sql);
1803
    if (Database::num_rows($res) > 0) {
1804
        $row = Database::fetch_array($res, 'ASSOC');
1805
        return $row['user_id'];
1806
    }
1807
1808
    // No anonymous user was found.
1809
    return 0;
1810
}
1811
1812
/**
1813
 * @param string $courseCode
1814
 * @param int $sessionId
1815
 * @param int $groupId
1816
 * @return string
1817
 */
1818
function api_get_cidreq_params($courseCode, $sessionId = 0, $groupId = 0)
1819
{
1820
    $courseCode = !empty($courseCode) ? htmlspecialchars($courseCode) : '';
1821
    $sessionId = !empty($sessionId) ? (int) $sessionId : 0;
1822
    $groupId = !empty($groupId) ? (int) $groupId : 0;
1823
1824
    $url = 'cidReq='.$courseCode;
1825
    $url .= '&id_session='.$sessionId;
1826
    $url .= '&gidReq='.$groupId;
1827
1828
    return $url;
1829
}
1830
1831
/**
1832
 * Returns the current course url part including session, group, and gradebook params
1833
 *
1834
 * @param bool $addSessionId
1835
 * @param bool $addGroupId
1836
 * @param string $origin
1837
 *
1838
 * @return  string  Course & session references to add to a URL
1839
 *
1840
 */
1841
function api_get_cidreq($addSessionId = true, $addGroupId = true, $origin = '')
1842
{
1843
    $courseCode = api_get_course_id();
1844
    $url = empty($courseCode) ? '' : 'cidReq='.htmlspecialchars($courseCode);
1845
    $origin = empty($origin) ? api_get_origin() : Security::remove_XSS($origin);
1846
1847
    if ($addSessionId) {
1848
        if (!empty($url)) {
1849
            $url .= api_get_session_id() == 0 ? '&id_session=0' : '&id_session='.api_get_session_id();
1850
        }
1851
    }
1852
1853
    if ($addGroupId) {
1854
        if (!empty($url)) {
1855
            $url .= api_get_group_id() == 0 ? '&gidReq=0' : '&gidReq='.api_get_group_id();
1856
        }
1857
    }
1858
1859
    if (!empty($url)) {
1860
        $url .= '&gradebook='.intval(api_is_in_gradebook());
1861
        $url .= '&origin='.$origin;
1862
    }
1863
1864
    return $url;
1865
}
1866
1867
/**
1868
 * Get if we visited a gradebook page
1869
 * @return bool
1870
 */
1871
function api_is_in_gradebook()
1872
{
1873
    return Session::read('in_gradebook', false);
1874
}
1875
1876
/**
1877
 * Set that we are in a page inside a gradebook
1878
 * @return bool
1879
 */
1880
function api_set_in_gradebook()
1881
{
1882
    Session::write('in_gradebook', true);
1883
}
1884
1885
/**
1886
 * Remove gradebook session
1887
 */
1888
function api_remove_in_gradebook()
1889
{
1890
    Session::erase('in_gradebook');
1891
}
1892
1893
/**
1894
 * Returns the current course info array see api_format_course_array()
1895
 * If the course_code is given, the returned array gives info about that
1896
 * particular course, if none given it gets the course info from the session.
1897
 *
1898
 * @param string $course_code
1899
 * @param bool $strict
1900
 *
1901
 * @return array
1902
 */
1903
function api_get_course_info($course_code = null, $strict = false)
1904
{
1905
    if (!empty($course_code)) {
1906
        $course_code = Database::escape_string($course_code);
1907
        $courseId = api_get_course_int_id($course_code);
1908
1909
        if (empty($courseId)) {
1910
            return [];
1911
        }
1912
1913
        $course_table = Database::get_main_table(TABLE_MAIN_COURSE);
1914
        $course_cat_table = Database::get_main_table(TABLE_MAIN_CATEGORY);
1915
        $sql = "SELECT
1916
                    course.*,
1917
                    course_category.code faCode,
1918
                    course_category.name faName
1919
                FROM $course_table
1920
                LEFT JOIN $course_cat_table
1921
                ON course.category_code = course_category.code
1922
                WHERE course.id = $courseId";
1923
        $result = Database::query($sql);
1924
        $courseInfo = [];
1925
        if (Database::num_rows($result) > 0) {
1926
            $data = Database::fetch_array($result);
1927
            $courseInfo = api_format_course_array($data);
1928
        }
1929
1930
        return $courseInfo;
1931
    }
1932
1933
    global $_course;
1934
    if ($_course == '-1') {
1935
        $_course = [];
1936
    }
1937
1938
    return $_course;
1939
}
1940
1941
/**
1942
 * @param int $courseId
1943
 * @return \Chamilo\CoreBundle\Entity\Course
1944
 */
1945
function api_get_course_entity($courseId)
1946
{
1947
    if (empty($courseId)) {
1948
        $courseId = api_get_course_int_id();
1949
    }
1950
    return CourseManager::getManager()->find($courseId);
1951
}
1952
1953
/**
1954
 * Returns the current course info array.
1955
1956
 * Now if the course_code is given, the returned array gives info about that
1957
 * particular course, not specially the current one.
1958
 * @param int $id Numeric ID of the course
1959
 * @return array The course info as an array formatted by api_format_course_array, including category.name
1960
 */
1961
function api_get_course_info_by_id($id = null)
1962
{
1963
    if (!empty($id)) {
1964
        $id = intval($id);
1965
        $course_table = Database::get_main_table(TABLE_MAIN_COURSE);
1966
        $course_cat_table = Database::get_main_table(TABLE_MAIN_CATEGORY);
1967
        $sql = "SELECT
1968
                    course.*,
1969
                    course_category.code faCode,
1970
                    course_category.name faName
1971
                FROM $course_table
1972
                LEFT JOIN $course_cat_table
1973
                ON course.category_code = course_category.code
1974
                WHERE course.id = $id";
1975
        $result = Database::query($sql);
1976
        $_course = [];
1977
        if (Database::num_rows($result) > 0) {
1978
            $row = Database::fetch_array($result);
1979
            $_course = api_format_course_array($row);
1980
        }
1981
        return $_course;
1982
    }
1983
1984
    global $_course;
1985
    if ($_course == '-1') {
1986
        $_course = [];
1987
    }
1988
    return $_course;
1989
}
1990
1991
/**
1992
 * Reformat the course array (output by api_get_course_info()) in order, mostly,
1993
 * to switch from 'code' to 'id' in the array. This is a legacy feature and is
1994
 * now possibly causing massive confusion as a new "id" field has been added to
1995
 * the course table in 1.9.0.
1996
 * @param $course_data
1997
 * @return array
1998
 * @todo eradicate the false "id"=code field of the $_course array and use the int id
1999
 */
2000
function api_format_course_array($course_data)
2001
{
2002
    if (empty($course_data)) {
2003
        return [];
2004
    }
2005
2006
    $_course = [];
2007
    $_course['id'] = $course_data['code'];
2008
    $_course['real_id'] = $course_data['id'];
2009
2010
    // Added
2011
    $_course['code'] = $course_data['code'];
2012
    $_course['name'] = $course_data['title'];
2013
    $_course['title'] = $course_data['title'];
2014
    $_course['official_code'] = $course_data['visual_code'];
2015
    $_course['visual_code'] = $course_data['visual_code'];
2016
    $_course['sysCode'] = $course_data['code'];
2017
    $_course['path'] = $course_data['directory']; // Use as key in path.
2018
    $_course['directory'] = $course_data['directory'];
2019
    $_course['creation_date'] = $course_data['creation_date'];
2020
    $_course['titular'] = $course_data['tutor_name'];
2021
    $_course['language'] = $course_data['course_language'];
2022
    $_course['extLink']['url'] = $course_data['department_url'];
2023
    $_course['extLink']['name'] = $course_data['department_name'];
2024
    $_course['categoryCode'] = $course_data['faCode'];
2025
    $_course['categoryName'] = $course_data['faName'];
2026
    $_course['visibility'] = $course_data['visibility'];
2027
    $_course['subscribe_allowed'] = $course_data['subscribe'];
2028
    $_course['subscribe'] = $course_data['subscribe'];
2029
    $_course['unsubscribe'] = $course_data['unsubscribe'];
2030
    $_course['course_language'] = $course_data['course_language'];
2031
    $_course['activate_legal'] = isset($course_data['activate_legal']) ? $course_data['activate_legal'] : false;
2032
    $_course['legal'] = $course_data['legal'];
2033
    $_course['show_score'] = $course_data['show_score']; //used in the work tool
2034
    $_course['department_name'] = $course_data['department_name'];
2035
    $_course['department_url'] = $course_data['department_url'];
2036
2037
    $courseSys = api_get_path(SYS_COURSE_PATH).$course_data['directory'];
2038
    $webCourseHome = api_get_path(WEB_COURSE_PATH).$course_data['directory'];
2039
2040
    // Course password
2041
    $_course['registration_code'] = !empty($course_data['registration_code']) ? sha1($course_data['registration_code']) : null;
2042
    $_course['disk_quota'] = $course_data['disk_quota'];
2043
    $_course['course_public_url'] = $webCourseHome.'/index.php';
2044
2045
    if (array_key_exists('add_teachers_to_sessions_courses', $course_data)) {
2046
        $_course['add_teachers_to_sessions_courses'] = $course_data['add_teachers_to_sessions_courses'];
2047
    }
2048
2049
    // Course image
2050
    $_course['course_image_source'] = '';
2051
    if (file_exists($courseSys.'/course-pic85x85.png')) {
2052
        $url_image = $webCourseHome.'/course-pic85x85.png';
2053
        $_course['course_image_source'] = $courseSys.'/course-pic85x85.png';
2054
    } else {
2055
        $url_image = Display::return_icon(
2056
            'course.png',
2057
            null,
2058
            null,
2059
            ICON_SIZE_BIG,
2060
            null,
2061
            true,
2062
            false
2063
        );
2064
    }
2065
    $_course['course_image'] = $url_image;
2066
2067
    // Course large image
2068
    $_course['course_image_large_source'] = '';
2069
    if (file_exists($courseSys.'/course-pic.png')) {
2070
        $url_image = $webCourseHome.'/course-pic.png';
2071
        $_course['course_image_large_source'] = $courseSys.'/course-pic.png';
2072
    } else {
2073
        $url_image = Display::return_icon(
2074
            'session_default.png',
2075
            null,
2076
            null,
2077
            null,
2078
            null,
2079
            true
2080
        );
2081
    }
2082
    $_course['course_image_large'] = $url_image;
2083
2084
    return $_course;
2085
}
2086
2087
/**
2088
 * Returns a difficult to guess password.
2089
 * @param int $length the length of the password
2090
 * @return string the generated password
2091
 */
2092
function api_generate_password($length = 8)
2093
{
2094
    if ($length < 2) {
2095
        $length = 2;
2096
    }
2097
2098
    $charactersLowerCase = 'abcdefghijkmnopqrstuvwxyz';
2099
    $charactersUpperCase = 'ABCDEFGHJKLMNPQRSTUVWXYZ';
2100
    $minNumbers = 2;
2101
    $length = $length - $minNumbers;
2102
    $minLowerCase = round($length / 2);
2103
    $minUpperCase = $length - $minLowerCase;
2104
2105
    $password = '';
2106
    $passwordRequirements = api_get_configuration_value('password_requirements');
2107
2108
    $factory = new RandomLib\Factory();
2109
    $generator = $factory->getGenerator(new SecurityLib\Strength(SecurityLib\Strength::MEDIUM));
2110
2111
    if (!empty($passwordRequirements)) {
2112
        $length = $passwordRequirements['min']['length'];
2113
        $minNumbers = $passwordRequirements['min']['numeric'];
2114
        $minLowerCase = $passwordRequirements['min']['lowercase'];
2115
        $minUpperCase = $passwordRequirements['min']['uppercase'];
2116
2117
        $rest = $length - $minNumbers - $minLowerCase - $minUpperCase;
2118
        // Add the rest to fill the length requirement
2119
        if ($rest > 0) {
2120
            $password .= $generator->generateString($rest, $charactersLowerCase.$charactersUpperCase);
2121
        }
2122
    }
2123
2124
    // Min digits default 2
2125
    for ($i = 0; $i < $minNumbers; $i++) {
2126
        $password .= $generator->generateInt(2, 9);
2127
    }
2128
2129
    // Min lowercase
2130
    $password .= $generator->generateString($minLowerCase, $charactersLowerCase);
2131
2132
    // Min uppercase
2133
    $password .= $generator->generateString($minUpperCase, $charactersUpperCase);
2134
    $password = str_shuffle($password);
2135
2136
    return $password;
2137
}
2138
2139
/**
2140
 * Checks a password to see wether it is OK to use.
2141
 * @param string $password
2142
 * @return boolean if the password is acceptable, false otherwise
2143
 * Notes about what a password "OK to use" is:
2144
 * 1. The password should be at least 5 characters long.
2145
 * 2. Only English letters (uppercase or lowercase, it doesn't matter) and digits are allowed.
2146
 * 3. The password should contain at least 3 letters.
2147
 * 4. It should contain at least 2 digits.
2148
 * Settings will change if the configuration value is set: password_requirements
2149
 */
2150
function api_check_password($password)
2151
{
2152
    $passwordRequirements = Security::getPasswordRequirements();
2153
2154
    $minLength = $passwordRequirements['min']['length'];
2155
    $minNumbers = $passwordRequirements['min']['numeric'];
2156
    // Optional
2157
    $minLowerCase = $passwordRequirements['min']['lowercase'];
2158
    $minUpperCase = $passwordRequirements['min']['uppercase'];
2159
2160
    $minLetters = $minLowerCase + $minUpperCase;
2161
    $passwordLength = api_strlen($password);
2162
2163
    $conditions = [
2164
        'min_length' => $passwordLength >= $minLength
2165
    ];
2166
2167
    $digits = 0;
2168
    $lowerCase = 0;
2169
    $upperCase = 0;
2170
2171
    for ($i = 0; $i < $passwordLength; $i++) {
2172
        $currentCharacterCode = api_ord(api_substr($password, $i, 1));
2173
        if ($currentCharacterCode >= 65 && $currentCharacterCode <= 90) {
2174
            $upperCase++;
2175
        }
2176
2177
        if ($currentCharacterCode >= 97 && $currentCharacterCode <= 122) {
2178
            $lowerCase++;
2179
        }
2180
        if ($currentCharacterCode >= 48 && $currentCharacterCode <= 57) {
2181
            $digits++;
2182
        }
2183
    }
2184
2185
    // Min number of digits
2186
    $conditions['min_numeric'] = $digits >= $minNumbers;
2187
2188
    if (!empty($minUpperCase)) {
2189
        // Uppercase
2190
        $conditions['min_uppercase'] = $upperCase >= $minUpperCase;
2191
    }
2192
2193
    if (!empty($minLowerCase)) {
2194
        // Lowercase
2195
        $conditions['min_lowercase'] = $upperCase >= $minLowerCase;
2196
    }
2197
2198
    // Min letters
2199
    $letters = $upperCase + $lowerCase;
2200
    $conditions['min_letters'] = $letters >= $minLetters;
2201
2202
    $isPasswordOk = true;
2203
    foreach ($conditions as $condition) {
2204
        if ($condition === false) {
2205
            $isPasswordOk = false;
2206
            break;
2207
        }
2208
    }
2209
2210
    if ($isPasswordOk === false) {
2211
        $output = get_lang('NewPasswordRequirementsNotMatched').'<br />';
2212
        $output .= Security::getPasswordRequirementsToString($conditions);
2213
2214
        Display::addFlash(Display::return_message($output, 'warning', false));
2215
    }
2216
2217
    return $isPasswordOk;
2218
}
2219
2220
/**
2221
 * Clears the user ID from the session if it was the anonymous user. Generally
2222
 * used on out-of-tools pages to remove a user ID that could otherwise be used
2223
 * in the wrong context.
2224
 * This function is to be used in conjunction with the api_set_anonymous()
2225
 * function to simulate the user existence in case of an anonymous visit.
2226
 * @param bool      database check switch - passed to api_is_anonymous()
2227
 * @return bool     true if succesfully unregistered, false if not anonymous.
2228
 */
2229
function api_clear_anonymous($db_check = false)
2230
{
2231
    global $_user;
2232
    if (api_is_anonymous($_user['user_id'], $db_check)) {
2233
        unset($_user['user_id']);
2234
        Session::erase('_uid');
2235
        return true;
2236
    }
2237
    return false;
2238
}
2239
2240
/**
2241
 * Returns the status string corresponding to the status code
2242
 * @author Noel Dieschburg
2243
 * @param the int status code
2244
 * @return string
2245
 */
2246
function get_status_from_code($status_code)
2247
{
2248
    switch ($status_code) {
2249
        case STUDENT:
2250
            return get_lang('Student', '');
2251
        case TEACHER:
2252
            return get_lang('Teacher', '');
2253
        case COURSEMANAGER:
2254
            return get_lang('Manager', '');
2255
        case SESSIONADMIN:
2256
            return get_lang('SessionsAdmin', '');
2257
        case DRH:
2258
            return get_lang('Drh', '');
2259
    }
2260
}
2261
2262
/**
2263
 * Sets the current user as anonymous if it hasn't been identified yet. This
2264
 * function should be used inside a tool only. The function api_clear_anonymous()
2265
 * acts in the opposite direction by clearing the anonymous user's data every
2266
 * time we get on a course homepage or on a neutral page (index, admin, my space)
2267
 * @return bool     true if set user as anonymous, false if user was already logged in or anonymous id could not be found
2268
 */
2269
function api_set_anonymous()
2270
{
2271
    global $_user;
2272
2273
    if (!empty($_user['user_id'])) {
2274
        return false;
2275
    }
2276
2277
    $user_id = api_get_anonymous_id();
2278
    if ($user_id == 0) {
2279
        return false;
2280
    }
2281
2282
    if (isset($_user['is_anonymous'])) {
2283
        return false;
2284
    }
2285
2286
    Session::erase('_user');
2287
    $_user['user_id'] = $user_id;
2288
    $_user['is_anonymous'] = true;
2289
    $GLOBALS['_user'] = $_user;
2290
    Session::write('_user', $_user);
2291
    return true;
2292
}
2293
2294
/**
2295
 * Gets the current Chamilo (not PHP/cookie) session ID
2296
 * @return  int     O if no active session, the session ID otherwise
2297
 */
2298
function api_get_session_id()
2299
{
2300
    return (int) Session::read('id_session', 0);
2301
}
2302
2303
/**
2304
 * Gets the current Chamilo (not social network) group ID
2305
 * @return  int     O if no active session, the session ID otherwise
2306
 */
2307
function api_get_group_id()
2308
{
2309
    return Session::read('_gid', 0);
2310
}
2311
2312
/**
2313
 * Gets the current or given session name
2314
 * @param   int     Session ID (optional)
2315
 * @return  string  The session name, or null if not found
2316
 */
2317
function api_get_session_name($session_id = 0)
2318
{
2319
    if (empty($session_id)) {
2320
        $session_id = api_get_session_id();
2321
        if (empty($session_id)) {
2322
            return null;
2323
        }
2324
    }
2325
    $t = Database::get_main_table(TABLE_MAIN_SESSION);
2326
    $s = "SELECT name FROM $t WHERE id = ".(int) $session_id;
2327
    $r = Database::query($s);
2328
    $c = Database::num_rows($r);
2329
    if ($c > 0) {
2330
        //technically, there can be only one, but anyway we take the first
2331
        $rec = Database::fetch_array($r);
2332
        return $rec['name'];
2333
    }
2334
    return null;
2335
}
2336
2337
/**
2338
 * Gets the session info by id
2339
 * @param int $id       Session ID
2340
 * @return array    information of the session
2341
 */
2342
function api_get_session_info($id)
2343
{
2344
    return SessionManager::fetch($id);
2345
}
2346
2347
/**
2348
 * Gets the session visibility by session id
2349
 * @param int $session_id
2350
 * @param int $courseId
2351
 * @param bool $ignore_visibility_for_admins
2352
 * @return int
2353
 *  0 = session still available,
2354
 *  SESSION_VISIBLE_READ_ONLY = 1,
2355
 *  SESSION_VISIBLE = 2,
2356
 *  SESSION_INVISIBLE = 3
2357
 */
2358
function api_get_session_visibility(
2359
    $session_id,
2360
    $courseId = null,
2361
    $ignore_visibility_for_admins = true
2362
) {
2363
    if (api_is_platform_admin()) {
2364
        if ($ignore_visibility_for_admins) {
2365
            return SESSION_AVAILABLE;
2366
        }
2367
    }
2368
2369
    $now = time();
2370
2371
    if (empty($session_id)) {
2372
        return 0; // Means that the session is still available.
2373
    }
2374
2375
    $session_id = intval($session_id);
2376
    $tbl_session = Database::get_main_table(TABLE_MAIN_SESSION);
2377
2378
    $result = Database::query("SELECT * FROM $tbl_session WHERE id = $session_id");
2379
2380
    if (Database::num_rows($result) <= 0) {
2381
        return SESSION_INVISIBLE;
2382
    }
2383
2384
    $row = Database::fetch_array($result, 'ASSOC');
2385
    $visibility = $original_visibility = $row['visibility'];
2386
2387
    // I don't care the session visibility.
2388
    if (empty($row['access_start_date']) && empty($row['access_end_date'])) {
2389
        // Session duration per student.
2390
        if (isset($row['duration']) && !empty($row['duration'])) {
2391
            $duration = $row['duration'] * 24 * 60 * 60;
2392
            $courseAccess = CourseManager::getFirstCourseAccessPerSessionAndUser($session_id, api_get_user_id());
2393
2394
            // If there is a session duration but there is no previous
2395
            // access by the user, then the session is still available
2396
            if (count($courseAccess) == 0) {
2397
                return SESSION_AVAILABLE;
2398
            }
2399
2400
            $currentTime = time();
2401
            $firstAccess = isset($courseAccess['login_course_date'])
2402
                ? api_strtotime($courseAccess['login_course_date'], 'UTC')
2403
                : 0;
2404
            $userDurationData = SessionManager::getUserSession(
2405
                api_get_user_id(),
2406
                $session_id
2407
            );
2408
            $userDuration = isset($userDurationData['duration'])
2409
                ? (intval($userDurationData['duration']) * 24 * 60 * 60)
2410
                : 0;
2411
2412
            $totalDuration = $firstAccess + $duration + $userDuration;
2413
2414
            return $totalDuration > $currentTime ? SESSION_AVAILABLE : SESSION_VISIBLE_READ_ONLY;
2415
        }
2416
2417
        return SESSION_AVAILABLE;
2418
    }
2419
    // If start date was set.
2420
    if (!empty($row['access_start_date'])) {
2421
        $visibility = $now > api_strtotime($row['access_start_date'], 'UTC') ? SESSION_AVAILABLE : SESSION_INVISIBLE;
2422
    }
2423
2424
    // If the end date was set.
2425
    if (!empty($row['access_end_date'])) {
2426
        // Only if date_start said that it was ok
2427
        if ($visibility === SESSION_AVAILABLE) {
2428
            $visibility = $now < api_strtotime($row['access_end_date'], 'UTC')
2429
                ? SESSION_AVAILABLE // Date still available
2430
                : $row['visibility']; // Session ends
2431
        }
2432
    }
2433
2434
    /* If I'm a coach the visibility can change in my favor depending in
2435
     the coach dates */
2436
    $isCoach = api_is_coach($session_id, $courseId);
2437
2438
    if ($isCoach) {
2439
        // Test start date.
2440
        if (!empty($row['coach_access_start_date'])) {
2441
            $start = api_strtotime($row['coach_access_start_date'], 'UTC');
2442
            $visibility = $start < $now ? SESSION_AVAILABLE : SESSION_INVISIBLE;
2443
        }
2444
2445
        // Test end date.
2446
        if (!empty($row['coach_access_end_date'])) {
2447
            if ($visibility === SESSION_AVAILABLE) {
2448
                $endDateCoach = api_strtotime($row['coach_access_end_date'], 'UTC');
2449
                $visibility = $endDateCoach >= $now ? SESSION_AVAILABLE : $row['visibility'];
2450
            }
2451
        }
2452
    }
2453
2454
    return $visibility;
2455
}
2456
2457
/**
2458
 * This function returns a (star) session icon if the session is not null and
2459
 * the user is not a student
2460
 * @param int   $session_id
2461
 * @param int   $status_id User status id - if 5 (student), will return empty
2462
 * @return string   Session icon
2463
 */
2464
function api_get_session_image($session_id, $status_id)
2465
{
2466
    $session_id = (int) $session_id;
2467
    $session_img = '';
2468
    if ((int) $status_id != 5) { //check whether is not a student
2469
        if ($session_id > 0) {
2470
            $session_img = "&nbsp;&nbsp;".Display::return_icon(
2471
                    'star.png',
2472
                    get_lang('SessionSpecificResource'),
2473
                    ['align' => 'absmiddle'],
2474
                    ICON_SIZE_SMALL
2475
                );
2476
        }
2477
    }
2478
    return $session_img;
2479
}
2480
2481
/**
2482
 * This function add an additional condition according to the session of the course
2483
 * @param int       $session_id session id
2484
 * @param bool      $and optional, true if more than one condition false if the only condition in the query
2485
 * @param bool      $with_base_content optional, true to accept content with session=0 as well,
2486
 * false for strict session condition
2487
 * @param string $session_field
2488
 * @return string   condition of the session
2489
 */
2490
function api_get_session_condition(
2491
    $session_id,
2492
    $and = true,
2493
    $with_base_content = false,
2494
    $session_field = 'session_id'
2495
) {
2496
    $session_id = intval($session_id);
2497
2498
    if (empty($session_field)) {
2499
        $session_field = "session_id";
2500
    }
2501
    // Condition to show resources by session
2502
    $condition_add = $and ? " AND " : " WHERE ";
2503
2504
    if ($with_base_content) {
2505
        $condition_session = $condition_add." ( $session_field = $session_id OR $session_field = 0 OR $session_field IS NULL) ";
2506
    } else {
2507
        if (empty($session_id)) {
2508
            $condition_session = $condition_add." ($session_field = $session_id OR $session_field IS NULL)";
2509
        } else {
2510
            $condition_session = $condition_add." $session_field = $session_id ";
2511
        }
2512
    }
2513
    return $condition_session;
2514
}
2515
2516
/**
2517
 * Returns the value of a setting from the web-adjustable admin config settings.
2518
 *
2519
 * WARNING true/false are stored as string, so when comparing you need to check e.g.
2520
 * if (api_get_setting('show_navigation_menu') == 'true') //CORRECT
2521
 * instead of
2522
 * if (api_get_setting('show_navigation_menu') == true) //INCORRECT
2523
 * @param string    $variable The variable name
2524
 * @param string    $key The subkey (sub-variable) if any. Defaults to NULL
2525
 * @return string
2526
 * @author René Haentjens
2527
 * @author Bart Mollet
2528
 */
2529
function api_get_setting($variable)
2530
{
2531
    $variable = trim($variable);
2532
    switch ($variable) {
2533
        case 'header_extra_content':
2534
            $filename = api_get_path(SYS_PATH).api_get_home_path().'header_extra_content.txt';
2535
            if (file_exists($filename)) {
2536
                $value = file_get_contents($filename);
2537
                return $value ;
2538
            } else {
2539
                return '';
2540
            }
2541
            break;
2542
        case 'footer_extra_content':
2543
            $filename = api_get_path(SYS_PATH).api_get_home_path().'footer_extra_content.txt';
2544
            if (file_exists($filename)) {
2545
                $value = file_get_contents($filename);
2546
                return $value ;
2547
            } else {
2548
                return '';
2549
            }
2550
            break;
2551
        case 'server_type':
2552
            $test = ['dev', 'test'];
2553
            $environment = Container::getEnvironment();
2554
            if (in_array($environment, $test)) {
2555
                return 'test';
2556
            }
2557
            return 'prod';
2558
        case 'stylesheets':
2559
            $variable = 'platform.theme';
2560
        // deprecated settings
2561
        // no break
2562
        case 'openid_authentication':
2563
        case 'sso_authentication':
2564
        case 'service_ppt2lp':
2565
        case 'add_cas_login_button_cas_button_label':
2566
        case 'add_cas_login_button_cas_button_comment':
2567
        case 'add_cas_login_button_cas_image_url':
2568
        case 'add_cas_logout_button_cas_logout_label':
2569
        case 'add_cas_logout_button_cas_logout_comment':
2570
        case 'add_cas_logout_button_cas_logout_image_url':
2571
        case 'add_facebook_login_button_facebook_button_url':
2572
        case 'add_shibboleth_login_button_shibboleth_button_label':
2573
        case 'add_shibboleth_login_button_shibboleth_button_comment':
2574
        case 'add_shibboleth_login_button_shibboleth_image_url':
2575
        case 'formLogin_hide_unhide_label':
2576
            return false;
2577
            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...
2578
        case 'tool_visible_by_default_at_creation':
2579
            $values = Container::getSettingsManager()->getSetting($variable);
2580
            $newResult = [];
2581
            foreach ($values as $parameter) {
2582
                $newResult[$parameter] = 'true';
2583
            }
2584
            return $newResult;
2585
            break;
2586
        default:
2587
            /** @var \Doctrine\ORM\EntityManager $em */
2588
            return Container::getSettingsManager()->getSetting($variable);
2589
    }
2590
2591
    // Old code
2592
    var_dump($variable);
0 ignored issues
show
Security Debugging Code introduced by
var_dump($variable) looks like debug code. Are you sure you do not want to remove it?
Loading history...
Unused Code introduced by
var_dump($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...
2593
2594
    global $_setting;
2595
    if ($variable == 'header_extra_content') {
2596
        $filename = api_get_home_path().'header_extra_content.txt';
2597
        if (file_exists($filename)) {
2598
            $value = file_get_contents($filename);
2599
            return $value;
2600
        } else {
2601
            return '';
2602
        }
2603
    }
2604
    if ($variable == 'footer_extra_content') {
2605
        $filename = api_get_home_path().'footer_extra_content.txt';
2606
        if (file_exists($filename)) {
2607
            $value = file_get_contents($filename);
2608
            return $value;
2609
        } else {
2610
            return '';
2611
        }
2612
    }
2613
    $value = null;
2614
    if (is_null($key)) {
2615
        $value = ((isset($_setting[$variable]) && $_setting[$variable] != '') ? $_setting[$variable] : null);
2616
    } else {
2617
        if (isset($_setting[$variable][$key])) {
2618
            $value = $_setting[$variable][$key];
2619
        }
2620
    }
2621
2622
    return $value;
2623
}
2624
2625
/**
2626
 * @param string $variable
2627
 * @param string $option
2628
 * @return bool
2629
 */
2630
function api_get_setting_in_list($variable, $option)
2631
{
2632
    $value = api_get_setting($variable);
2633
2634
    return in_array($option, $value);
2635
}
2636
2637
/**
2638
 * @param string $plugin
2639
 * @param string $variable
2640
 * @return string
2641
 */
2642
function api_get_plugin_setting($plugin, $variable)
2643
{
2644
    $variableName = $plugin.'_'.$variable;
2645
    $params = [
2646
        'category = ? AND subkey = ? AND variable = ?' => [
2647
            'Plugins',
2648
            $plugin,
2649
            $variableName,
2650
        ],
2651
    ];
2652
    $table = Database::get_main_table(TABLE_MAIN_SETTINGS_CURRENT);
2653
    $result = Database::select(
2654
        'selected_value',
2655
        $table,
2656
        ['where' => $params],
2657
        'one'
2658
    );
2659
    if ($result) {
2660
        $result = $result['selected_value'];
2661
        return $result;
2662
    }
2663
2664
    return null;
2665
    /// Old code
2666
2667
    $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...
2668
    $result = api_get_setting($variableName);
2669
2670
    if (isset($result[$plugin])) {
2671
        $value = $result[$plugin];
2672
        if (@unserialize($value) !== false) {
2673
            $value = unserialize($value);
2674
        }
2675
        return $value;
2676
    }
2677
2678
    return null;
2679
}
2680
2681
/**
2682
 * Returns the value of a setting from the web-adjustable admin config settings.
2683
 **/
2684
function api_get_settings_params($params)
2685
{
2686
    $table = Database::get_main_table(TABLE_MAIN_SETTINGS_CURRENT);
2687
    $result = Database::select('*', $table, ['where' => $params]);
2688
    return $result;
2689
}
2690
2691
function api_get_settings_params_simple($params)
2692
{
2693
    $table = Database::get_main_table(TABLE_MAIN_SETTINGS_CURRENT);
2694
    $result = Database::select('*', $table, ['where' => $params], 'one');
2695
    return $result;
2696
}
2697
2698
/**
2699
 * Returns the value of a setting from the web-adjustable admin config settings.
2700
 **/
2701
function api_delete_settings_params($params)
2702
{
2703
    $table = Database::get_main_table(TABLE_MAIN_SETTINGS_CURRENT);
2704
    $result = Database::delete($table, $params);
2705
    return $result;
2706
}
2707
2708
/**
2709
 * Returns an escaped version of $_SERVER['PHP_SELF'] to avoid XSS injection
2710
 * @return string   Escaped version of $_SERVER['PHP_SELF']
2711
 */
2712
function api_get_self()
2713
{
2714
    return htmlentities($_SERVER['PHP_SELF']);
2715
}
2716
2717
/* USER PERMISSIONS */
2718
2719
/**
2720
 * Checks whether current user is a platform administrator
2721
 * @param boolean $allowSessionAdmins Whether session admins should be considered admins or not
2722
 * @param boolean $allowDrh Whether HR directors should be considered admins or not
2723
 * @return boolean True if the user has platform admin rights,
2724
 * false otherwise.
2725
 * @see usermanager::is_admin(user_id) for a user-id specific function
2726
 */
2727
function api_is_platform_admin($allowSessionAdmins = false, $allowDrh = false)
2728
{
2729
    $isAdmin = Session::read('is_platformAdmin');
2730
    if ($isAdmin) {
2731
        return true;
2732
    }
2733
    $user = api_get_user_info();
2734
    return
2735
        isset($user['status']) &&
2736
        (
2737
            ($allowSessionAdmins && $user['status'] == SESSIONADMIN) ||
2738
            ($allowDrh && $user['status'] == DRH)
2739
        );
2740
}
2741
2742
/**
2743
 * Checks whether the user given as user id is in the admin table.
2744
 * @param int $user_id If none provided, will use current user
2745
 * @param int $url URL ID. If provided, also check if the user is active on given URL
2746
 * @return bool True if the user is admin, false otherwise
2747
 */
2748
function api_is_platform_admin_by_id($user_id = null, $url = null)
2749
{
2750
    $user_id = intval($user_id);
2751
    if (empty($user_id)) {
2752
        $user_id = api_get_user_id();
2753
    }
2754
    $admin_table = Database::get_main_table(TABLE_MAIN_ADMIN);
2755
    $sql = "SELECT * FROM $admin_table WHERE user_id = $user_id";
2756
    $res = Database::query($sql);
2757
    $is_admin = Database::num_rows($res) === 1;
2758
    if (!$is_admin || !isset($url)) {
2759
        return $is_admin;
2760
    }
2761
    // We get here only if $url is set
2762
    $url = intval($url);
2763
    $url_user_table = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_USER);
2764
    $sql = "SELECT * FROM $url_user_table
2765
            WHERE access_url_id = $url AND user_id = $user_id";
2766
    $res = Database::query($sql);
2767
    $result = Database::num_rows($res) === 1;
2768
2769
    return $result;
2770
}
2771
2772
/**
2773
 * Returns the user's numeric status ID from the users table
2774
 * @param int $user_id If none provided, will use current user
2775
 * @return int User's status (1 for teacher, 5 for student, etc)
2776
 */
2777
function api_get_user_status($user_id = null)
2778
{
2779
    $user_id = intval($user_id);
2780
    if (empty($user_id)) {
2781
        $user_id = api_get_user_id();
2782
    }
2783
    $table = Database::get_main_table(TABLE_MAIN_USER);
2784
    $sql = "SELECT status FROM $table WHERE user_id = $user_id ";
2785
    $result = Database::query($sql);
2786
    $status = null;
2787
    if (Database::num_rows($result)) {
2788
        $row = Database::fetch_array($result);
2789
        $status = $row['status'];
2790
    }
2791
    return $status;
2792
}
2793
2794
/**
2795
 * Checks whether current user is allowed to create courses
2796
 * @return boolean True if the user has course creation rights,
2797
 * false otherwise.
2798
 */
2799
function api_is_allowed_to_create_course()
2800
{
2801
    if (api_is_platform_admin()) {
2802
        return true;
2803
    }
2804
2805
    // Teachers can only create courses
2806
    if (api_is_teacher()) {
2807
        if (api_get_setting('allow_users_to_create_courses') === 'true') {
2808
            return true;
2809
        } else {
2810
            return false;
2811
        }
2812
    }
2813
2814
    return Session::read('is_allowedCreateCourse');
2815
}
2816
2817
/**
2818
 * Checks whether the current user is a course administrator
2819
 * @return boolean True if current user is a course administrator
2820
 */
2821
function api_is_course_admin()
2822
{
2823
    if (api_is_platform_admin()) {
2824
        return true;
2825
    }
2826
    return Session::read('is_courseAdmin');
2827
}
2828
2829
/**
2830
 * Checks whether the current user is a course coach
2831
 * Based on the presence of user in session.id_coach (session general coach)
2832
 * @return bool True if current user is a course coach
2833
 */
2834
function api_is_session_general_coach()
2835
{
2836
    return Session::read('is_session_general_coach');
2837
}
2838
2839
/**
2840
 * Checks whether the current user is a course tutor
2841
 * Based on the presence of user in session_rel_course_rel_user.user_id with status = 2
2842
 * @return bool     True if current user is a course tutor
2843
 */
2844
function api_is_course_tutor()
2845
{
2846
    return Session::read('is_courseTutor');
2847
}
2848
2849
/**
2850
 * @param int $user_id
2851
 * @param int $courseId
2852
 * @param int $session_id
2853
 * @return bool
2854
 */
2855
function api_is_course_session_coach($user_id, $courseId, $session_id)
2856
{
2857
    $session_table = Database::get_main_table(TABLE_MAIN_SESSION);
2858
    $session_rel_course_rel_user_table = Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER);
2859
2860
    $user_id = intval($user_id);
2861
    $session_id = intval($session_id);
2862
    $courseId = intval($courseId);
2863
2864
    $sql = "SELECT DISTINCT session.id
2865
            FROM $session_table
2866
            INNER JOIN $session_rel_course_rel_user_table session_rc_ru
2867
            ON session.id = session_rc_ru.session_id
2868
            WHERE
2869
                session_rc_ru.user_id = '".$user_id."'  AND
2870
                session_rc_ru.c_id = '$courseId' AND
2871
                session_rc_ru.status = 2 AND
2872
                session_rc_ru.session_id = '$session_id'";
2873
    $result = Database::query($sql);
2874
2875
    return Database::num_rows($result) > 0;
2876
}
2877
2878
/**
2879
 * Checks whether the current user is a course or session coach
2880
 * @param int $session_id
2881
 * @param int $courseId
2882
 * @param bool  Check whether we are in student view and, if we are, return false
2883
 * @return boolean True if current user is a course or session coach
2884
 */
2885
function api_is_coach($session_id = 0, $courseId = null, $check_student_view = true)
2886
{
2887
    $userId = api_get_user_id();
2888
2889
    if (!empty($session_id)) {
2890
        $session_id = intval($session_id);
2891
    } else {
2892
        $session_id = api_get_session_id();
2893
    }
2894
2895
    // The student preview was on
2896
    if ($check_student_view && api_is_student_view_active()) {
2897
        return false;
2898
    }
2899
2900
    if (!empty($courseId)) {
2901
        $courseId = intval($courseId);
2902
    } else {
2903
        $courseId = api_get_course_int_id();
2904
    }
2905
2906
    $session_table = Database::get_main_table(TABLE_MAIN_SESSION);
2907
    $session_rel_course_rel_user_table = Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER);
2908
    $sessionIsCoach = null;
2909
2910
    if (!empty($courseId)) {
2911
        $sql = "SELECT DISTINCT s.id, name, access_start_date, access_end_date
2912
                FROM $session_table s
2913
                INNER JOIN $session_rel_course_rel_user_table session_rc_ru
2914
                ON session_rc_ru.session_id = s.id AND session_rc_ru.user_id = '".$userId."'
2915
                WHERE
2916
                    session_rc_ru.c_id = '$courseId' AND
2917
                    session_rc_ru.status = 2 AND
2918
                    session_rc_ru.session_id = '$session_id'";
2919
        $result = Database::query($sql);
2920
        $sessionIsCoach = Database::store_result($result);
2921
    }
2922
2923
    if (!empty($session_id)) {
2924
        $sql = "SELECT DISTINCT id, name, access_start_date, access_end_date
2925
                FROM $session_table
2926
                WHERE session.id_coach = $userId AND id = $session_id
2927
                ORDER BY access_start_date, access_end_date, name";
2928
        $result = Database::query($sql);
2929
        if (!empty($sessionIsCoach)) {
2930
            $sessionIsCoach = array_merge(
2931
                $sessionIsCoach,
2932
                Database::store_result($result)
2933
            );
2934
        } else {
2935
            $sessionIsCoach = Database::store_result($result);
2936
        }
2937
    }
2938
2939
    return count($sessionIsCoach) > 0;
2940
}
2941
2942
/**
2943
 * Checks whether the current user is a session administrator
2944
 * @return boolean True if current user is a course administrator
2945
 */
2946
function api_is_session_admin()
2947
{
2948
    $user = api_get_user_info();
2949
    return isset($user['status']) && $user['status'] == SESSIONADMIN;
2950
}
2951
2952
/**
2953
 * Checks whether the current user is a human resources manager
2954
 * @return boolean True if current user is a human resources manager
2955
 */
2956
function api_is_drh()
2957
{
2958
    $user = api_get_user_info();
2959
    return isset($user['status']) && $user['status'] == DRH;
2960
}
2961
2962
/**
2963
 * Checks whether the current user is a student
2964
 * @return boolean True if current user is a human resources manager
2965
 */
2966
function api_is_student()
2967
{
2968
    $user = api_get_user_info();
2969
    return isset($user['status']) && $user['status'] == STUDENT;
2970
}
2971
2972
/**
2973
 * Checks whether the current user has the status 'teacher'
2974
 * @return boolean True if current user is a human resources manager
2975
 */
2976
function api_is_teacher()
2977
{
2978
    $user = api_get_user_info();
2979
    return isset($user['status']) && $user['status'] == COURSEMANAGER;
2980
}
2981
2982
/**
2983
 * Checks whether the current user is a invited user
2984
 * @return boolean
2985
 */
2986
function api_is_invitee()
2987
{
2988
    $user = api_get_user_info();
2989
2990
    return isset($user['status']) && $user['status'] == INVITEE;
2991
}
2992
2993
/**
2994
 * This function checks whether a session is assigned into a category
2995
 * @param int       - session id
2996
 * @param string    - category name
2997
 * @return bool     - true if is found, otherwise false
2998
 */
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...
2999
function api_is_session_in_category($session_id, $category_name)
3000
{
3001
    $session_id = intval($session_id);
3002
    $category_name = Database::escape_string($category_name);
3003
    $tbl_session = Database::get_main_table(TABLE_MAIN_SESSION);
3004
    $tbl_session_category = Database::get_main_table(TABLE_MAIN_SESSION_CATEGORY);
3005
3006
    $sql = "SELECT 1
3007
            FROM $tbl_session
3008
            WHERE $session_id IN (
3009
                SELECT s.id FROM $tbl_session s, $tbl_session_category sc
3010
                WHERE
3011
                  s.session_category_id = sc.id AND
3012
                  sc.name LIKE '%$category_name'
3013
            )";
3014
    $rs = Database::query($sql);
3015
3016
    if (Database::num_rows($rs) > 0) {
3017
        return true;
3018
    } else {
3019
        return false;
3020
    }
3021
}
3022
3023
/**
3024
 * Displays the title of a tool.
3025
 * Normal use: parameter is a string:
3026
 * api_display_tool_title("My Tool")
3027
 *
3028
 * Optionally, there can be a subtitle below
3029
 * the normal title, and / or a supra title above the normal title.
3030
 *
3031
 * e.g. supra title:
3032
 * group
3033
 * GROUP PROPERTIES
3034
 *
3035
 * e.g. subtitle:
3036
 * AGENDA
3037
 * calender & events tool
3038
 *
3039
 * @author Hugues Peeters <[email protected]>
3040
 * @param  mixed $title_element - it could either be a string or an array
3041
 *                               containing 'supraTitle', 'mainTitle',
3042
 *                               'subTitle'
3043
 * @return void
3044
 */
3045
function api_display_tool_title($title_element)
3046
{
3047
    if (is_string($title_element)) {
3048
        $tit = $title_element;
3049
        unset($title_element);
3050
        $title_element['mainTitle'] = $tit;
3051
    }
3052
    echo '<h3>';
3053
    if (!empty($title_element['supraTitle'])) {
3054
        echo '<small>'.$title_element['supraTitle'].'</small><br />';
3055
    }
3056
    if (!empty($title_element['mainTitle'])) {
3057
        echo $title_element['mainTitle'];
3058
    }
3059
    if (!empty($title_element['subTitle'])) {
3060
        echo '<br /><small>'.$title_element['subTitle'].'</small>';
3061
    }
3062
    echo '</h3>';
3063
}
3064
3065
/**
3066
 * Displays options for switching between student view and course manager view
3067
 *
3068
 * Changes in version 1.2 (Patrick Cool)
3069
 * Student view switch now behaves as a real switch. It maintains its current state until the state
3070
 * is changed explicitly
3071
 *
3072
 * Changes in version 1.1 (Patrick Cool)
3073
 * student view now works correctly in subfolders of the document tool
3074
 * student view works correctly in the new links tool
3075
 *
3076
 * Example code for using this in your tools:
3077
 * //if ($is_courseAdmin && api_get_setting('student_view_enabled') == 'true') {
3078
 * //   display_tool_view_option($isStudentView);
3079
 * //}
3080
 * //and in later sections, use api_is_allowed_to_edit()
3081
 *
3082
 * @author Roan Embrechts
3083
 * @author Patrick Cool
3084
 * @author Julio Montoya, changes added in Chamilo
3085
 * @version 1.2
3086
 * @todo rewrite code so it is easier to understand
3087
 */
3088
function api_display_tool_view_option()
3089
{
3090
    if (api_get_setting('student_view_enabled') != 'true') {
3091
        return '';
3092
    }
3093
3094
    $sourceurl = '';
3095
    $is_framed = false;
3096
    // Exceptions apply for all multi-frames pages
3097
    if (strpos($_SERVER['REQUEST_URI'], 'chat/chat_banner.php') !== false) {
3098
        // The chat is a multiframe bit that doesn't work too well with the student_view, so do not show the link
3099
        return '';
3100
    }
3101
3102
    // Uncomment to remove student view link from document view page
3103
    if (strpos($_SERVER['REQUEST_URI'], 'lp/lp_header.php') !== false) {
3104
        if (empty($_GET['lp_id'])) {
3105
            return '';
3106
        }
3107
        $sourceurl = substr($_SERVER['REQUEST_URI'], 0, strpos($_SERVER['REQUEST_URI'], '?'));
3108
        $sourceurl = str_replace(
3109
            'lp/lp_header.php',
3110
            'lp/lp_controller.php?'.api_get_cidreq().'&action=view&lp_id='.intval($_GET['lp_id']).'&isStudentView='.($_SESSION['studentview'] == 'studentview' ? 'false' : 'true'),
3111
            $sourceurl
3112
        );
3113
        //showinframes doesn't handle student view anyway...
3114
        //return '';
3115
        $is_framed = true;
3116
    }
3117
3118
    // Check whether the $_SERVER['REQUEST_URI'] contains already url parameters (thus a questionmark)
3119
    if (!$is_framed) {
3120
        if (strpos($_SERVER['REQUEST_URI'], '?') === false) {
3121
            $sourceurl = api_get_self().'?'.api_get_cidreq();
3122
        } else {
3123
            $sourceurl = $_SERVER['REQUEST_URI'];
3124
        }
3125
    }
3126
3127
    $output_string = '';
3128
    if (!empty($_SESSION['studentview'])) {
3129
        if ($_SESSION['studentview'] == 'studentview') {
3130
            // We have to remove the isStudentView=true from the $sourceurl
3131
            $sourceurl = str_replace('&isStudentView=true', '', $sourceurl);
3132
            $sourceurl = str_replace('&isStudentView=false', '', $sourceurl);
3133
            $output_string .= '<a class="btn btn-primary btn-sm" href="'.$sourceurl.'&isStudentView=false" target="_self">'.
3134
                Display::returnFontAwesomeIcon('eye').' '.get_lang('SwitchToTeacherView').'</a>';
3135
        } elseif ($_SESSION['studentview'] == 'teacherview') {
3136
            // Switching to teacherview
3137
            $sourceurl = str_replace('&isStudentView=true', '', $sourceurl);
3138
            $sourceurl = str_replace('&isStudentView=false', '', $sourceurl);
3139
            $output_string .= '<a class="btn btn-default btn-sm" href="'.$sourceurl.'&isStudentView=true" target="_self">'.
3140
                Display::returnFontAwesomeIcon('eye').' '.get_lang('SwitchToStudentView').'</a>';
3141
        }
3142
    } else {
3143
        $output_string .= '<a class="btn btn-default btn-sm" href="'.$sourceurl.'&isStudentView=true" target="_self">'.
3144
            Display::returnFontAwesomeIcon('eye').' '.get_lang('SwitchToStudentView').'</a>';
3145
    }
3146
    $html = Display::tag('div', $output_string, ['class'=>'view-options']);
3147
    return $html;
3148
}
3149
3150
// TODO: This is for the permission section.
3151
/**
3152
 * Function that removes the need to directly use is_courseAdmin global in
3153
 * tool scripts. It returns true or false depending on the user's rights in
3154
 * this particular course.
3155
 * Optionally checking for tutor and coach roles here allows us to use the
3156
 * student_view feature altogether with these roles as well.
3157
 * @param bool  Whether to check if the user has the tutor role
3158
 * @param bool  Whether to check if the user has the coach role
3159
 * @param bool  Whether to check if the user has the session coach role
3160
 * @param bool  check the student view or not
3161
 *
3162
 * @author Roan Embrechts
3163
 * @author Patrick Cool
3164
 * @author Julio Montoya
3165
 * @version 1.1, February 2004
3166
 * @return boolean true: the user has the rights to edit, false: he does not
3167
 */
3168
3169
function api_is_allowed_to_edit(
3170
    $tutor = false,
3171
    $coach = false,
3172
    $session_coach = false,
3173
    $check_student_view = true
3174
) {
3175
    $sessionId = api_get_session_id();
3176
    $is_allowed_coach_to_edit = api_is_coach(null, null, $check_student_view);
3177
    $session_visibility = api_get_session_visibility($sessionId);
3178
3179
    // Admins can edit anything.
3180
    if (api_is_platform_admin(false)) {
3181
        //The student preview was on
3182
        if ($check_student_view && api_is_student_view_active()) {
3183
            return false;
3184
        } else {
3185
            return true;
3186
        }
3187
    }
3188
3189
    $is_courseAdmin = api_is_course_admin();
3190
3191
    if (!$is_courseAdmin && $tutor) {
3192
        // If we also want to check if the user is a tutor...
3193
        $is_courseAdmin = $is_courseAdmin || api_is_course_tutor();
3194
    }
3195
3196
    if (!$is_courseAdmin && $coach) {
3197
        // If we also want to check if the user is a coach...';
3198
        // Check if session visibility is read only for coaches.
3199
        if ($session_visibility == SESSION_VISIBLE_READ_ONLY) {
3200
            $is_allowed_coach_to_edit = false;
3201
        }
3202
3203
        if (api_get_setting('allow_coach_to_edit_course_session') == 'true') {
3204
            // Check if coach is allowed to edit a course.
3205
            $is_courseAdmin = $is_courseAdmin || $is_allowed_coach_to_edit;
3206
        }
3207
    }
3208
3209
    if (!$is_courseAdmin && $session_coach) {
3210
        $is_courseAdmin = $is_courseAdmin || $is_allowed_coach_to_edit;
3211
    }
3212
3213
    // Check if the student_view is enabled, and if so, if it is activated.
3214
    if (api_get_setting('student_view_enabled') == 'true') {
3215
        if (!empty($sessionId)) {
3216
            // Check if session visibility is read only for coaches.
3217
            if ($session_visibility == SESSION_VISIBLE_READ_ONLY) {
3218
                $is_allowed_coach_to_edit = false;
3219
            }
3220
3221
            if (api_get_setting('allow_coach_to_edit_course_session') == 'true') {
3222
                // Check if coach is allowed to edit a course.
3223
                $is_allowed = $is_allowed_coach_to_edit;
3224
            } else {
3225
                $is_allowed = false;
3226
            }
3227
            if ($check_student_view) {
3228
                $is_allowed = $is_allowed && $_SESSION['studentview'] != 'studentview';
3229
            }
3230
        } else {
3231
            if ($check_student_view) {
3232
                $is_allowed = $is_courseAdmin && $_SESSION['studentview'] != 'studentview';
3233
            } else {
3234
                $is_allowed = $is_courseAdmin;
3235
            }
3236
        }
3237
3238
        return $is_allowed;
3239
    } else {
3240
        return $is_courseAdmin;
3241
    }
3242
}
3243
3244
/**
3245
 * Returns true if user is a course coach of at least one course in session
3246
 * @param int $sessionId
3247
 * @return bool
3248
 */
3249
function api_is_coach_of_course_in_session($sessionId)
3250
{
3251
    if (api_is_platform_admin()) {
3252
        return true;
3253
    }
3254
3255
    $userId = api_get_user_id();
3256
    $courseList = UserManager::get_courses_list_by_session(
3257
        $userId,
3258
        $sessionId
3259
    );
3260
3261
    // Session visibility.
3262
    $visibility = api_get_session_visibility(
3263
        $sessionId,
3264
        null,
3265
        false
3266
    );
3267
3268
    if ($visibility != SESSION_VISIBLE && !empty($courseList)) {
3269
        // Course Coach session visibility.
3270
        $blockedCourseCount = 0;
3271
        $closedVisibilityList = [
3272
            COURSE_VISIBILITY_CLOSED,
3273
            COURSE_VISIBILITY_HIDDEN
3274
        ];
3275
3276
        foreach ($courseList as $course) {
3277
            // Checking session visibility
3278
            $sessionCourseVisibility = api_get_session_visibility(
3279
                $sessionId,
3280
                $course['real_id']
3281
            );
3282
3283
            $courseIsVisible = !in_array(
3284
                $course['visibility'],
3285
                $closedVisibilityList
3286
            );
3287
            if ($courseIsVisible === false || $sessionCourseVisibility == SESSION_INVISIBLE) {
3288
                $blockedCourseCount++;
3289
            }
3290
        }
3291
3292
        // If all courses are blocked then no show in the list.
3293
        if ($blockedCourseCount === count($courseList)) {
3294
            $visibility = SESSION_INVISIBLE;
3295
        } else {
3296
            $visibility = SESSION_VISIBLE;
3297
        }
3298
    }
3299
3300
    switch ($visibility) {
3301
        case SESSION_VISIBLE_READ_ONLY:
3302
        case SESSION_VISIBLE:
3303
        case SESSION_AVAILABLE:
3304
            return true;
3305
            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...
3306
        case SESSION_INVISIBLE:
3307
            return false;
3308
    }
3309
3310
    return false;
3311
}
3312
3313
/**
3314
 * Checks if a student can edit contents in a session depending
3315
 * on the session visibility
3316
 * @param bool $tutor  Whether to check if the user has the tutor role
3317
 * @param bool  $coach Whether to check if the user has the coach role
3318
 * @return boolean true: the user has the rights to edit, false: he does not
3319
 */
3320
function api_is_allowed_to_session_edit($tutor = false, $coach = false)
3321
{
3322
    if (api_is_allowed_to_edit($tutor, $coach)) {
3323
        // If I'm a teacher, I will return true in order to not affect the normal behaviour of Chamilo tools.
3324
        return true;
3325
    } else {
3326
        $sessionId = api_get_session_id();
3327
3328
        if ($sessionId == 0) {
3329
            // I'm not in a session so i will return true to not affect the normal behaviour of Chamilo tools.
3330
            return true;
3331
        } else {
3332
            // I'm in a session and I'm a student
3333
            // Get the session visibility
3334
            $session_visibility = api_get_session_visibility($sessionId);
3335
            // if 5 the session is still available
3336
            //@todo We could load the session_rel_course_rel_user permission to increase the level of detail.
3337
            //echo api_get_user_id();
3338
            //echo api_get_course_id();
3339
3340
            switch ($session_visibility) {
3341
                case SESSION_VISIBLE_READ_ONLY: // 1
3342
                    return false;
3343
                case SESSION_VISIBLE:           // 2
3344
                    return true;
3345
                case SESSION_INVISIBLE:         // 3
3346
                    return false;
3347
                case SESSION_AVAILABLE:         //5
3348
                    return true;
3349
            }
3350
        }
3351
    }
3352
}
3353
3354
/**
3355
 * Checks whether the user is allowed in a specific tool for a specific action
3356
 * @param string $tool the tool we are checking if the user has a certain permission
3357
 * @param string $action the action we are checking (add, edit, delete, move, visibility)
3358
 * @return bool
3359
 * @author Patrick Cool <[email protected]>, Ghent University
3360
 * @author Julio Montoya
3361
 * @version 1.0
3362
 */
3363
function api_is_allowed($tool, $action, $task_id = 0)
3364
{
3365
    $_user = api_get_user_info();
3366
    $_course = api_get_course_info();
3367
3368
    if (api_is_course_admin()) {
3369
        return true;
3370
    }
3371
3372
    if (is_array($_course) and count($_course) > 0) {
3373
        require_once api_get_path(SYS_CODE_PATH).'permissions/permissions_functions.inc.php';
3374
3375
        // Getting the permissions of this user.
3376
        if ($task_id == 0) {
3377
            $user_permissions = get_permissions('user', $_user['user_id']);
3378
            $_SESSION['total_permissions'][$_course['code']] = $user_permissions;
3379
        }
3380
3381
        // Getting the permissions of the task.
3382
        if ($task_id != 0) {
3383
            $task_permissions = get_permissions('task', $task_id);
3384
            /* !!! */$_SESSION['total_permissions'][$_course['code']] = $task_permissions;
3385
        }
3386
        //print_r($_SESSION['total_permissions']);
3387
3388
        // Getting the permissions of the groups of the user
3389
        //$groups_of_user = GroupManager::get_group_ids($_course['db_name'], $_user['user_id']);
3390
3391
        //foreach($groups_of_user as $group)
3392
        //   $this_group_permissions = get_permissions('group', $group);
3393
3394
        // Getting the permissions of the courseroles of the user
3395
        $user_courserole_permissions = get_roles_permissions('user', $_user['user_id']);
3396
3397
        // Getting the permissions of the platformroles of the user
3398
        //$user_platformrole_permissions = get_roles_permissions('user', $_user['user_id'], ', platform');
3399
3400
        // Getting the permissions of the roles of the groups of the user
3401
        //foreach($groups_of_user as $group)
3402
        //    $this_group_courserole_permissions = get_roles_permissions('group', $group);
3403
3404
        // Getting the permissions of the platformroles of the groups of the user
3405
        //foreach($groups_of_user as $group)
3406
        //    $this_group_platformrole_permissions = get_roles_permissions('group', $group, 'platform');
3407
    }
3408
3409
    // If the permissions are limited, we have to map the extended ones to the limited ones.
3410
    if (api_get_setting('permissions') == 'limited') {
3411
        if ($action == 'Visibility') {
3412
            $action = 'Edit';
3413
        }
3414
        if ($action == 'Move') {
3415
            $action = 'Edit';
3416
        }
3417
    }
3418
3419
    // The session that contains all the permissions already exists for this course
3420
    // so there is no need to requery everything.
3421
    //my_print_r($_SESSION['total_permissions'][$_course['code']][$tool]);
3422
    if (is_array($_SESSION['total_permissions'][$_course['code']][$tool])) {
3423
        if (in_array($action, $_SESSION['total_permissions'][$_course['code']][$tool])) {
3424
            return true;
3425
        } else {
3426
            return false;
3427
        }
3428
    }
3429
}
3430
3431
/**
3432
 * Tells whether this user is an anonymous user
3433
 * @param int  $user_id      User ID (optional, will take session ID if not provided)
3434
 * @param bool $db_check     Whether to check in the database (true) or simply in
3435
 * the session (false) to see if the current user is the anonymous user
3436
 * @return bool     true if this user is anonymous, false otherwise
3437
 */
3438
function api_is_anonymous($user_id = null, $db_check = false)
3439
{
3440
    if ($db_check) {
3441
        if (!isset($user_id)) {
3442
            $user_id = api_get_user_id();
3443
        }
3444
        $info = api_get_user_info($user_id);
3445
3446
        if ($info['status'] == 6 || $user_id == 0 || empty($info)) {
3447
            return true;
3448
        }
3449
    }
3450
3451
    return Session::read('IS_AUTHENTICATED_FULLY', false);
3452
}
3453
3454
/**
3455
 * Displays message "You are not allowed here..." and exits the entire script.
3456
 * @param bool   $print_headers    Whether or not to print headers (default = false -> does not print them)
3457
 * @param string $message
3458
 * @param int $responseCode
3459
 */
3460
function api_not_allowed(
3461
    $print_headers = false,
3462
    $message = null,
3463
    $responseCode = 0
3464
) {
3465
    if (api_get_setting('sso_authentication') === 'true') {
3466
        global $osso;
3467
        if ($osso) {
3468
            $osso->logout();
3469
        }
3470
    }
3471
    $home_url = api_get_path(WEB_PATH);
3472
    $user_id = api_get_user_id();
3473
    $course = api_get_course_id();
3474
3475
    global $this_section;
3476
3477
    if (CustomPages::enabled() && !isset($user_id)) {
3478
        if (empty($user_id)) {
3479
            // Why the CustomPages::enabled() need to be to set the request_uri
3480
            $_SESSION['request_uri'] = $_SERVER['REQUEST_URI'];
3481
        }
3482
        CustomPages::display(CustomPages::INDEX_UNLOGGED);
3483
    }
3484
3485
    $origin = api_get_origin();
3486
3487
    $msg = null;
3488
    if (isset($message)) {
3489
        $msg = $message;
3490
    } else {
3491
        $msg = Display::return_message(
3492
            get_lang('NotAllowedClickBack').'
3493
            <script>function goBack(){window.history.back();}</script>',
3494
            'error',
3495
            false
3496
        );
3497
        $msg .= '<p class="text-center">
3498
             <a onclick="goBack();" class="btn btn-default" href="'.$home_url.'">'.get_lang('GoBack').'</a>
3499
             </p>';
3500
    }
3501
3502
    $msg = Display::div($msg, ['align'=>'center']);
3503
3504
    $show_headers = 0;
3505
    if ($print_headers && $origin != 'learnpath') {
3506
        $show_headers = 1;
3507
    }
3508
3509
    $tpl = new Template(null, $show_headers, $show_headers, false, true, false, true, $responseCode);
3510
    $tpl->assign('hide_login_link', 1);
3511
    $tpl->assign('content', $msg);
3512
3513
    if (($user_id != 0 && !api_is_anonymous()) &&
3514
        (!isset($course) || $course == -1) &&
3515
        empty($_GET['cidReq'])
3516
    ) {
3517
        // if the access is not authorized and there is some login information
3518
        // but the cidReq is not found, assume we are missing course data and send the user
3519
        // to the user_portal
3520
        $tpl->display_one_col_template();
3521
        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...
3522
    }
3523
3524
    if (!empty($_SERVER['REQUEST_URI']) &&
3525
        (
3526
            !empty($_GET['cidReq']) ||
3527
            $this_section == SECTION_MYPROFILE ||
3528
            $this_section == SECTION_PLATFORM_ADMIN
3529
        )
3530
    ) {
3531
        $courseCode = api_get_course_id();
3532
        // Only display form and return to the previous URL if there was a course ID included
3533
        if ($user_id != 0 && !api_is_anonymous()) {
3534
            //if there is a user ID, then the user is not allowed but the session is still there. Say so and exit
3535
            $tpl->assign('content', $msg);
3536
            $tpl->display_one_col_template();
3537
            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...
3538
        }
3539
3540
        if (!is_null($courseCode)) {
3541
            api_set_firstpage_parameter($courseCode);
3542
        }
3543
3544
        // If the user has no user ID, then his session has expired
3545
        $form = api_get_not_allowed_login_form();
3546
3547
        // see same text in auth/gotocourse.php and main_api.lib.php function api_not_allowed (above)
3548
        $content = Display::return_message(get_lang('NotAllowed'), 'error', false);
3549
3550
        if (!empty($courseCode)) {
3551
            $content .= '<h4>'.get_lang('LoginToGoToThisCourse').'</h4>';
3552
        }
3553
3554
        if (api_is_cas_activated()) {
3555
            $content .= Display::return_message(sprintf(get_lang('YouHaveAnInstitutionalAccount'), api_get_setting("Institution")), '', false);
3556
            $content .= Display::div(
3557
                "<br/><a href='".get_cas_direct_URL(api_get_course_id())."'>".sprintf(get_lang('LoginWithYourAccount'), api_get_setting("Institution"))."</a><br/><br/>",
3558
                ['align' => 'center']
3559
            );
3560
            $content .= Display::return_message(get_lang('YouDontHaveAnInstitutionAccount'));
3561
            $content .= "<p style='text-align:center'><a href='#' onclick='$(this).parent().next().toggle()'>".get_lang('LoginWithExternalAccount')."</a></p>";
3562
            $content .= "<div style='display:none;'>";
3563
        }
3564
        $content .= '<div class="well">';
3565
        $content .= $form->returnForm();
3566
        $content .= '</div>';
3567
        if (api_is_cas_activated()) {
3568
            $content .= "</div>";
3569
        }
3570
3571
        if (!empty($courseCode)) {
3572
            $content .= '<hr/><p style="text-align:center"><a href="'.$home_url.'">'.
3573
                get_lang('ReturnToCourseHomepage').'</a></p>';
3574
        } else {
3575
            $content .= '<hr/><p style="text-align:center"><a href="'.$home_url.'">'.
3576
                get_lang('BackHome').'</a></p>';
3577
        }
3578
3579
        $tpl->setLoginBodyClass();
3580
        $tpl->assign('content', $content);
3581
        $tpl->display_one_col_template();
3582
        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...
3583
    }
3584
3585
    if ($user_id != 0 && !api_is_anonymous()) {
3586
        $tpl->display_one_col_template();
3587
        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...
3588
    }
3589
3590
    $msg = null;
3591
    // The session is over and we were not in a course,
3592
    // or we try to get directly to a private course without being logged
3593
    $courseId = api_get_course_int_id();
3594
    if (!empty($courseId)) {
3595
        api_set_firstpage_parameter(api_get_course_id());
3596
        $tpl->setLoginBodyClass();
3597
3598
        // see same text in auth/gotocourse.php and main_api.lib.php function api_not_allowed (bellow)
3599
        $msg = Display::return_message(get_lang('NotAllowed'), 'error', false);
3600
        $msg .= '<h4>'.get_lang('LoginToGoToThisCourse').'</h4>';
3601
        $casEnabled = api_is_cas_activated();
3602
        if ($casEnabled) {
3603
            $msg .= Display::return_message(
3604
                sprintf(get_lang('YouHaveAnInstitutionalAccount'), api_get_setting("Institution")),
3605
                '',
3606
                false
3607
            );
3608
            $msg .= Display::div("<br/><a href='".get_cas_direct_URL(api_get_course_int_id())."'>".getCASLogoHTML()." ".sprintf(get_lang('LoginWithYourAccount'), api_get_setting("Institution"))."</a><br/><br/>", ['align'=>'center']);
3609
            $msg .= Display::return_message(get_lang('YouDontHaveAnInstitutionAccount'));
3610
            $msg .= "<p style='text-align:center'><a href='#' onclick='$(this).parent().next().toggle()'>".get_lang('LoginWithExternalAccount')."</a></p>";
3611
            $msg .= "<div style='display:none;'>";
3612
        }
3613
        $form = api_get_not_allowed_login_form();
3614
        $msg .= '<div class="well">';
3615
        $msg .= $form->returnForm();
3616
        $msg .= '</div>';
3617
        if ($casEnabled) {
3618
            $msg .= "</div>";
3619
        }
3620
    } else {
3621
        // we were not in a course, return to home page
3622
        $msg = Display::return_message(
3623
            get_lang('NotAllowed'),
3624
            'error',
3625
            false
3626
        );
3627
3628
        $msg .= '<p class="text-center">
3629
                 <a class="btn btn-default" href="'.$home_url.'">'.get_lang('BackHome').'</a>
3630
                 </p>';
3631
3632
        if (!empty($message)) {
3633
            $msg = $message;
3634
        }
3635
3636
        if (api_is_anonymous()) {
3637
            $form = api_get_not_allowed_login_form();
3638
            $msg .= '<div class="well">';
3639
            $msg .= $form->returnForm();
3640
            $msg .= '</div>';
3641
        }
3642
    }
3643
3644
    $tpl->assign('content', $msg);
3645
    $tpl->display_one_col_template();
3646
    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...
3647
}
3648
3649
/**
3650
 * @return FormValidator
3651
 */
3652
function api_get_not_allowed_login_form()
3653
{
3654
    $action = api_get_self().'?'.Security::remove_XSS($_SERVER['QUERY_STRING']);
3655
    $action = str_replace('&amp;', '&', $action);
3656
    Session::write('redirect_after_not_allow_page', $action);
3657
    $action .= '&redirect_after_not_allow_page=1';
3658
3659
    $form = new FormValidator(
3660
        'formLogin',
3661
        'post',
3662
        $action,
3663
        null,
3664
        ['class' => 'form-stacked']
3665
    );
3666
    $params = [
3667
        'placeholder' => get_lang('UserName'),
3668
        'class' => 'col-md-3'
3669
    ];
3670
    if (api_browser_support('autocapitalize')) {
3671
        $params['autocapitalize'] = 'none';
3672
    }
3673
3674
    $form->addElement(
3675
        'text',
3676
        'login',
3677
        null,
3678
        $params
3679
    );
3680
    $form->addElement(
3681
        'password',
3682
        'password',
3683
        null,
3684
        ['placeholder' => get_lang('Password'), 'class' => 'col-md-3']
3685
    ); //new
3686
    $form->addButtonNext(get_lang('LoginEnter'), 'submitAuth');
3687
3688
    return $form;
3689
}
3690
3691
/**
3692
 * Gets a UNIX timestamp from a database (MySQL) datetime format string
3693
 * @param $last_post_datetime standard output date in a sql query
3694
 * @return integer timestamp
3695
 * @author Toon Van Hoecke <[email protected]>
3696
 * @version October 2003
3697
 * @desc convert sql date to unix timestamp
3698
 */
3699
function convert_sql_date($last_post_datetime)
3700
{
3701
    list($last_post_date, $last_post_time) = explode(' ', $last_post_datetime);
3702
    list($year, $month, $day) = explode('-', $last_post_date);
3703
    list($hour, $min, $sec) = explode(':', $last_post_time);
3704
    return mktime((int) $hour, (int) $min, (int) $sec, (int) $month, (int) $day, (int) $year);
3705
}
3706
3707
/**
3708
 * Gets item visibility from the item_property table
3709
 *
3710
 * Getting the visibility is done by getting the last updated visibility entry,
3711
 * using the largest session ID found if session 0 and another was found (meaning
3712
 * the only one that is actually from the session, in case there are results from
3713
 * session 0 *AND* session n).
3714
 * @param array     Course properties array (result of api_get_course_info())
3715
 * @param string    Tool (learnpath, document, etc)
3716
 * @param int       The item ID in the given tool
3717
 * @param int       The session ID (optional)
3718
 * @param string $tool
3719
 * @param integer $user_id
3720
 * @param string $type
3721
 * @return int      -1 on error, 0 if invisible, 1 if visible
3722
 */
3723
function api_get_item_visibility(
3724
    $_course,
3725
    $tool,
3726
    $id,
3727
    $session = 0,
3728
    $user_id = null,
3729
    $type = null,
3730
    $group_id = null
3731
) {
3732
    if (!is_array($_course) || count($_course) == 0 || empty($tool) || empty($id)) {
3733
        return -1;
3734
    }
3735
3736
    $tool = Database::escape_string($tool);
3737
    $id = intval($id);
3738
    $session = (int) $session;
3739
    $TABLE_ITEMPROPERTY = Database::get_course_table(TABLE_ITEM_PROPERTY);
3740
    $course_id = intval($_course['real_id']);
3741
3742
    $userCondition = '';
3743
    if (!empty($user_id)) {
3744
        $user_id = intval($user_id);
3745
        $userCondition = " AND to_user_id = $user_id ";
3746
    }
3747
3748
    $typeCondition = '';
3749
    if (!empty($type)) {
3750
        $type = Database::escape_string($type);
3751
        $typeCondition = " AND lastedit_type = '$type' ";
3752
    }
3753
3754
    $groupCondition = '';
3755
    if (!empty($group_id)) {
3756
        $group_id = intval($group_id);
3757
        $groupCondition = " AND to_group_id = '$group_id' ";
3758
    }
3759
3760
    $sql = "SELECT visibility
3761
            FROM $TABLE_ITEMPROPERTY
3762
            WHERE
3763
                c_id = $course_id AND
3764
                tool = '$tool' AND
3765
                ref = $id AND
3766
                (session_id = $session OR session_id = 0 OR session_id IS NULL)
3767
                $userCondition $typeCondition $groupCondition
3768
            ORDER BY session_id DESC, lastedit_date DESC
3769
            LIMIT 1";
3770
3771
    $res = Database::query($sql);
3772
    if ($res === false || Database::num_rows($res) == 0) {
3773
        return -1;
3774
    }
3775
    $row = Database::fetch_array($res);
3776
3777
    return $row['visibility'];
3778
}
3779
3780
/**
3781
 * Delete a row in the c_item_property table
3782
 *
3783
 * @param array $courseInfo
3784
 * @param string $tool
3785
 * @param int $itemId
3786
 * @param int $userId
3787
 * @param int $groupId group.iid
3788
 * @param int $sessionId
3789
 * @return false|null
3790
 */
3791
function api_item_property_delete(
3792
    $courseInfo,
3793
    $tool,
3794
    $itemId,
3795
    $userId,
3796
    $groupId = 0,
3797
    $sessionId = 0
3798
) {
3799
    if (empty($courseInfo)) {
3800
        return false;
3801
    }
3802
3803
    $courseId = intval($courseInfo['real_id']);
3804
3805
    if (empty($courseId) || empty($tool) || empty($itemId)) {
3806
        return false;
3807
    }
3808
3809
    $table = Database::get_course_table(TABLE_ITEM_PROPERTY);
3810
    $tool = Database::escape_string($tool);
3811
    $itemId = intval($itemId);
3812
    $userId = intval($userId);
3813
    $groupId = intval($groupId);
3814
    $sessionId = intval($sessionId);
3815
3816
    $groupCondition = " AND to_group_id = $groupId ";
3817
    if (empty($groupId)) {
3818
        $groupCondition = " AND (to_group_id is NULL OR to_group_id = 0) ";
3819
    }
3820
3821
    $userCondition = " AND to_user_id = $userId ";
3822
    if (empty($userId)) {
3823
        $userCondition = " AND (to_user_id is NULL OR to_user_id = 0) ";
3824
    }
3825
    $sessionCondition = api_get_session_condition($sessionId, true, false, 'session_id');
3826
    $sql = "DELETE FROM $table
3827
            WHERE
3828
                c_id = $courseId AND
3829
                tool  = '$tool' AND
3830
                ref = $itemId
3831
                $sessionCondition
3832
                $userCondition
3833
                $groupCondition
3834
            ";
3835
3836
    Database::query($sql);
3837
}
3838
3839
/**
3840
 * Updates or adds item properties to the Item_propetry table
3841
 * Tool and lastedit_type are language independant strings (langvars->get_lang!)
3842
 *
3843
 * @param array $_course array with course properties
3844
 * @param string $tool tool id, linked to 'rubrique' of the course tool_list (Warning: language sensitive !!)
3845
 * @param int $item_id id of the item itself, linked to key of every tool ('id', ...)
3846
 * @param string $last_edit_type add or update action
3847
 * (1) message to be translated (in trad4all) : e.g. DocumentAdded, DocumentUpdated;
3848
 * (2) "delete"
3849
 * (3) "visible"
3850
 * (4) "invisible"
3851
 * @param int $user_id id of the editing/adding user
3852
 * @param array $groupInfo must include group.iid/group.od
3853
 * @param int $to_user_id id of the intended user (always has priority over $to_group_id !), only relevant for $type (1)
3854
 * @param string $start_visible 0000-00-00 00:00:00 format
3855
 * @param string $end_visible 0000-00-00 00:00:00 format
3856
 * @param int $session_id The session ID, if any, otherwise will default to 0
3857
 * @return boolean False if update fails.
3858
 * @author Toon Van Hoecke <[email protected]>, Ghent University
3859
 * @version January 2005
3860
 * @desc update the item_properties table (if entry not exists, insert) of the course
3861
 */
3862
function api_item_property_update(
3863
    $_course,
3864
    $tool,
3865
    $item_id,
3866
    $last_edit_type,
3867
    $user_id,
3868
    $groupInfo = [],
3869
    $to_user_id = null,
3870
    $start_visible = '',
3871
    $end_visible = '',
3872
    $session_id = 0
3873
) {
3874
    if (empty($_course)) {
3875
        return false;
3876
    }
3877
3878
    $course_id = $_course['real_id'];
3879
3880
    if (empty($course_id)) {
3881
        return false;
3882
    }
3883
3884
    $to_group_id = 0;
3885
    if (!empty($groupInfo) && isset($groupInfo['iid'])) {
3886
        $to_group_id = $groupInfo['iid'];
3887
    }
3888
3889
    $em = Database::getManager();
3890
3891
    // Definition of variables.
3892
    $tool = Database::escape_string($tool);
3893
    $item_id = intval($item_id);
3894
    $lastEditTypeNoFilter = $last_edit_type;
3895
    $last_edit_type = Database::escape_string($last_edit_type);
3896
    $user_id = intval($user_id);
3897
3898
    $startVisible = "NULL";
3899
    if (!empty($start_visible)) {
3900
        $start_visible = Database::escape_string($start_visible);
3901
        $startVisible = "'$start_visible'";
3902
    }
3903
3904
    $endVisible = "NULL";
3905
    if (!empty($end_visible)) {
3906
        $end_visible = Database::escape_string($end_visible);
3907
        $endVisible = "'$end_visible'";
3908
    }
3909
3910
    $to_filter = '';
3911
    $time = api_get_utc_datetime();
3912
3913
    if (!empty($session_id)) {
3914
        $session_id = intval($session_id);
3915
    } else {
3916
        $session_id = api_get_session_id();
3917
    }
3918
3919
    // Definition of tables.
3920
    $tableItemProperty = Database::get_course_table(TABLE_ITEM_PROPERTY);
3921
3922
    if ($to_user_id <= 0) {
3923
        $to_user_id = null; // No to_user_id set
3924
    }
3925
3926
    if (!is_null($to_user_id)) {
3927
        // $to_user_id has more priority than $to_group_id
3928
        $to_user_id = intval($to_user_id);
3929
        $to_field = 'to_user_id';
3930
        $to_value = $to_user_id;
3931
    } else {
3932
        // $to_user_id is not set.
3933
        $to_field = 'to_group_id';
3934
        $to_value = $to_group_id;
3935
    }
3936
3937
    $toValueCondition = empty($to_value) ? "NULL" : "'$to_value'";
3938
    // Set filters for $to_user_id and $to_group_id, with priority for $to_user_id
3939
    $condition_session = " AND session_id = $session_id ";
3940
    if (empty($session_id)) {
3941
        $condition_session = " AND (session_id = 0 OR session_id IS NULL) ";
3942
    }
3943
3944
    $filter = " c_id = $course_id AND tool = '$tool' AND ref = $item_id $condition_session ";
3945
3946
    // Check whether $to_user_id and $to_group_id are passed in the function call.
3947
    // If both are not passed (both are null) then it is a message for everybody and $to_group_id should be 0 !
3948
    if (is_null($to_user_id) && is_null($to_group_id)) {
3949
        $to_group_id = 0;
3950
    }
3951
3952
    if (!is_null($to_user_id)) {
3953
        // Set filter to intended user.
3954
        $to_filter = " AND to_user_id = $to_user_id $condition_session";
3955
    } else {
3956
        // Set filter to intended group.
3957
        if (($to_group_id != 0) && $to_group_id == strval(intval($to_group_id))) {
3958
            $to_filter = " AND to_group_id = $to_group_id $condition_session";
3959
        }
3960
    }
3961
3962
    // Adding filter if set.
3963
    $filter .= $to_filter;
3964
3965
    // Update if possible
3966
    $set_type = '';
3967
3968
    switch ($lastEditTypeNoFilter) {
3969
        case 'delete':
3970
            // delete = make item only visible for the platform admin.
3971
            $visibility = '2';
3972
            if (!empty($session_id)) {
3973
                // Check whether session id already exist into item_properties for updating visibility or add it.
3974
                $sql = "SELECT session_id FROM $tableItemProperty
3975
                        WHERE
3976
                            c_id = $course_id AND
3977
                            tool = '$tool' AND
3978
                            ref = $item_id AND
3979
                            session_id = $session_id";
3980
                $rs = Database::query($sql);
3981
                if (Database::num_rows($rs) > 0) {
3982
                    $sql = "UPDATE $tableItemProperty
3983
                            SET lastedit_type       = '".str_replace('_', '', ucwords($tool))."Deleted',
3984
                                lastedit_date       = '$time',
3985
                                lastedit_user_id    = $user_id,
3986
                                visibility          = $visibility,
3987
                                session_id          = $session_id $set_type
3988
                            WHERE $filter";
3989
                    $result = Database::query($sql);
3990
                } else {
3991
                    $sql = "INSERT INTO $tableItemProperty (c_id, tool, ref, insert_date, insert_user_id, lastedit_date, lastedit_type, lastedit_user_id, $to_field, visibility, start_visible, end_visible, session_id)
3992
                            VALUES ($course_id, '$tool',$item_id, '$time', $user_id, '$time', '$last_edit_type',$user_id, $toValueCondition, $visibility, $startVisible, $endVisible, $session_id)";
3993
                    $result = Database::query($sql);
3994
                    $id = Database::insert_id();
3995
                    if ($id) {
3996
                        $sql = "UPDATE $tableItemProperty SET id = iid WHERE iid = $id";
3997
                        Database::query($sql);
3998
                    }
3999
                }
4000
            } else {
4001
                $sql = "UPDATE $tableItemProperty
4002
                        SET
4003
                            lastedit_type='".str_replace('_', '', ucwords($tool))."Deleted',
4004
                            lastedit_date='$time',
4005
                            lastedit_user_id = $user_id,
4006
                            visibility = $visibility $set_type
4007
                        WHERE $filter";
4008
                $result = Database::query($sql);
4009
            }
4010
            break;
4011
        case 'visible': // Change item to visible.
4012
            $visibility = '1';
4013
            if (!empty($session_id)) {
4014
                // Check whether session id already exist into item_properties for updating visibility or add it.
4015
                $sql = "SELECT session_id FROM $tableItemProperty
4016
                        WHERE
4017
                            c_id = $course_id AND
4018
                            tool = '$tool' AND
4019
                            ref = $item_id AND
4020
                            session_id = $session_id";
4021
                $rs = Database::query($sql);
4022
                if (Database::num_rows($rs) > 0) {
4023
                    $sql = "UPDATE $tableItemProperty
4024
                            SET
4025
                                lastedit_type='".str_replace('_', '', ucwords($tool))."Visible',
4026
                                lastedit_date='$time',
4027
                                lastedit_user_id = $user_id,
4028
                                visibility = $visibility,
4029
                                session_id = $session_id $set_type
4030
                            WHERE $filter";
4031
                    $result = Database::query($sql);
4032
                } else {
4033
                    $sql = "INSERT INTO $tableItemProperty (c_id, tool, ref, insert_date, insert_user_id, lastedit_date, lastedit_type, lastedit_user_id, $to_field, visibility, start_visible, end_visible, session_id)
4034
                            VALUES ($course_id, '$tool', $item_id, '$time', $user_id, '$time', '$last_edit_type', $user_id, $toValueCondition, $visibility, $startVisible, $endVisible, $session_id)";
4035
                    $result = Database::query($sql);
4036
                    $id = Database::insert_id();
4037
                    if ($id) {
4038
                        $sql = "UPDATE $tableItemProperty SET id = iid WHERE iid = $id";
4039
                        Database::query($sql);
4040
                    }
4041
                }
4042
            } else {
4043
                $sql = "UPDATE $tableItemProperty
4044
                        SET
4045
                            lastedit_type='".str_replace('_', '', ucwords($tool))."Visible',
4046
                            lastedit_date='$time',
4047
                            lastedit_user_id = $user_id,
4048
                            visibility = $visibility $set_type
4049
                        WHERE $filter";
4050
                $result = Database::query($sql);
4051
            }
4052
            break;
4053
        case 'invisible': // Change item to invisible.
4054
            $visibility = '0';
4055
            if (!empty($session_id)) {
4056
                // Check whether session id already exist into item_properties for updating visibility or add it
4057
                $sql = "SELECT session_id FROM $tableItemProperty
4058
                        WHERE
4059
                            c_id = $course_id AND
4060
                            tool = '$tool' AND
4061
                            ref = $item_id AND
4062
                            session_id = $session_id";
4063
                $rs = Database::query($sql);
4064
                if (Database::num_rows($rs) > 0) {
4065
                    $sql = "UPDATE $tableItemProperty
4066
                            SET
4067
                                lastedit_type = '".str_replace('_', '', ucwords($tool))."Invisible',
4068
                                lastedit_date = '$time',
4069
                                lastedit_user_id = $user_id,
4070
                                visibility = $visibility,
4071
                                session_id = $session_id $set_type
4072
                            WHERE $filter";
4073
                    $result = Database::query($sql);
4074
                } else {
4075
                    $sql = "INSERT INTO $tableItemProperty (c_id, tool, ref, insert_date, insert_user_id, lastedit_date, lastedit_type, lastedit_user_id,$to_field, visibility, start_visible, end_visible, session_id)
4076
                            VALUES ($course_id, '$tool', $item_id, '$time', $user_id, '$time', '$last_edit_type', $user_id, $toValueCondition, $visibility, $startVisible, $endVisible, $session_id)";
4077
                    $result = Database::query($sql);
4078
                    $id = Database::insert_id();
4079
                    if ($id) {
4080
                        $sql = "UPDATE $tableItemProperty SET id = iid WHERE iid = $id";
4081
                        Database::query($sql);
4082
                    }
4083
                }
4084
            } else {
4085
                $sql = "UPDATE $tableItemProperty
4086
                        SET
4087
                            lastedit_type = '".str_replace('_', '', ucwords($tool))."Invisible',
4088
                            lastedit_date = '$time',
4089
                            lastedit_user_id = $user_id,
4090
                            visibility = $visibility $set_type
4091
                        WHERE $filter";
4092
                $result = Database::query($sql);
4093
            }
4094
            break;
4095
        default: // The item will be added or updated.
4096
            $set_type = ", lastedit_type = '$last_edit_type' ";
4097
            $visibility = '1';
4098
            //$filter .= $to_filter; already added
4099
            $sql = "UPDATE $tableItemProperty
4100
                    SET
4101
                      lastedit_date = '$time',
4102
                      lastedit_user_id = $user_id $set_type
4103
                    WHERE $filter";
4104
            $result = Database::query($sql);
4105
    }
4106
4107
    // Insert if no entries are found (can only happen in case of $last_edit_type switch is 'default').
4108
    if ($result == false || Database::affected_rows($result) == 0) {
4109
        $objCourse = $em->find('ChamiloCoreBundle:Course', intval($course_id));
4110
        $objTime = new DateTime('now', new DateTimeZone('UTC'));
4111
        $objUser = api_get_user_entity($user_id);
4112
        if (empty($objUser)) {
4113
            // Use anonymous
4114
            $user_id = api_get_anonymous_id();
4115
            $objUser = api_get_user_entity($user_id);
4116
        }
4117
        $objGroup = $em->find('ChamiloCourseBundle:CGroupInfo', intval($to_group_id));
4118
        $objToUser = api_get_user_entity($to_user_id);
4119
        $objSession = $em->find('ChamiloCoreBundle:Session', intval($session_id));
4120
4121
        $startVisibleDate = !empty($start_visible) ? new DateTime($start_visible, new DateTimeZone('UTC')) : null;
4122
        $endVisibleDate = !empty($endVisibleDate) ? new DateTime($endVisibleDate, new DateTimeZone('UTC')) : null;
4123
4124
        $cItemProperty = new CItemProperty($objCourse);
4125
        $cItemProperty
4126
            ->setTool($tool)
4127
            ->setRef($item_id)
4128
            ->setInsertDate($objTime)
4129
            ->setInsertUser($objUser)
4130
            ->setLasteditDate($objTime)
4131
            ->setLasteditType($last_edit_type)
4132
            ->setGroup($objGroup)
4133
            ->setToUser($objToUser)
4134
            ->setVisibility($visibility)
4135
            ->setStartVisible($startVisibleDate)
4136
            ->setEndVisible($endVisibleDate)
4137
            ->setSession($objSession);
4138
4139
        $em->persist($cItemProperty);
4140
        $em->flush();
4141
4142
        $id = $cItemProperty->getIid();
4143
4144
        if ($id) {
4145
            $cItemProperty->setId($id);
4146
            $em->merge($cItemProperty);
4147
            $em->flush();
4148
4149
            return false;
4150
        }
4151
    }
4152
4153
    return true;
4154
}
4155
4156
/**
4157
 * Gets item property by tool
4158
 * @param string    course code
4159
 * @param string    tool name, linked to 'rubrique' of the course tool_list (Warning: language sensitive !!)
4160
 * @param int       id of the item itself, linked to key of every tool ('id', ...), "*" = all items of the tool
4161
 * @param int $session_id
4162
 * @param string $tool
4163
 * @param string $course_code
4164
 * @return array All fields from c_item_property (all rows found) or empty array
4165
 */
4166
function api_get_item_property_by_tool($tool, $course_code, $session_id = null)
4167
{
4168
    $course_info = api_get_course_info($course_code);
4169
    $tool = Database::escape_string($tool);
4170
4171
    // Definition of tables.
4172
    $item_property_table = Database::get_course_table(TABLE_ITEM_PROPERTY);
4173
    $session_id = intval($session_id);
4174
    $session_condition = ' AND session_id = '.$session_id;
4175
    if (empty($session_id)) {
4176
        $session_condition = " AND (session_id = 0 OR session_id IS NULL) ";
4177
    }
4178
    $course_id = $course_info['real_id'];
4179
4180
    $sql = "SELECT * FROM $item_property_table
4181
            WHERE
4182
                c_id = $course_id AND
4183
                tool = '$tool'
4184
                $session_condition ";
4185
    $rs = Database::query($sql);
4186
    $list = [];
4187
    if (Database::num_rows($rs) > 0) {
4188
        while ($row = Database::fetch_array($rs, 'ASSOC')) {
4189
            $list[] = $row;
4190
        }
4191
    }
4192
    return $list;
4193
}
4194
4195
/**
4196
 * Gets item property by tool and user
4197
 * @param int $userId
4198
 * @param int $tool
4199
 * @param int $courseId
4200
 * @param int $session_id
4201
 * @return array
4202
 */
4203
function api_get_item_property_list_by_tool_by_user(
4204
    $userId,
4205
    $tool,
4206
    $courseId,
4207
    $session_id = 0
4208
) {
4209
    $userId = intval($userId);
4210
    $tool = Database::escape_string($tool);
4211
    $session_id = intval($session_id);
4212
    $courseId = intval($courseId);
4213
4214
    // Definition of tables.
4215
    $item_property_table = Database::get_course_table(TABLE_ITEM_PROPERTY);
4216
    $session_condition = ' AND session_id = '.$session_id;
4217
    if (empty($session_id)) {
4218
        $session_condition = " AND (session_id = 0 OR session_id IS NULL) ";
4219
    }
4220
    $sql = "SELECT * FROM $item_property_table
4221
            WHERE
4222
                insert_user_id = $userId AND
4223
                c_id = $courseId AND
4224
                tool = '$tool'
4225
                $session_condition ";
4226
4227
    $rs = Database::query($sql);
4228
    $list = [];
4229
    if (Database::num_rows($rs) > 0) {
4230
        while ($row = Database::fetch_array($rs, 'ASSOC')) {
4231
            $list[] = $row;
4232
        }
4233
    }
4234
4235
    return $list;
4236
}
4237
4238
/**
4239
 * Gets item property id from tool of a course
4240
 * @param string $course_code course code
4241
 * @param string $tool tool name, linked to 'rubrique' of the course tool_list (Warning: language sensitive !!)
4242
 * @param int $ref id of the item itself, linked to key of every tool ('id', ...), "*" = all items of the tool
4243
 * @param int $sessionId Session ID (optional)
4244
 * @return int
4245
 */
4246
function api_get_item_property_id($course_code, $tool, $ref, $sessionId = 0)
4247
{
4248
    $course_info = api_get_course_info($course_code);
4249
    $tool = Database::escape_string($tool);
4250
    $ref = intval($ref);
4251
4252
    // Definition of tables.
4253
    $tableItemProperty = Database::get_course_table(TABLE_ITEM_PROPERTY);
4254
    $course_id = $course_info['real_id'];
4255
    $sessionId = (int) $sessionId;
4256
    $sessionCondition = " AND session_id = $sessionId ";
4257
    if (empty($sessionId)) {
4258
        $sessionCondition = " AND (session_id = 0 OR session_id IS NULL) ";
4259
    }
4260
    $sql = "SELECT id FROM $tableItemProperty
4261
            WHERE
4262
                c_id = $course_id AND
4263
                tool = '$tool' AND
4264
                ref = $ref
4265
                $sessionCondition";
4266
    $rs = Database::query($sql);
4267
    $item_property_id = '';
4268
    if (Database::num_rows($rs) > 0) {
4269
        $row = Database::fetch_array($rs);
4270
        $item_property_id = $row['id'];
4271
    }
4272
    return $item_property_id;
4273
}
4274
4275
/**
4276
 * Inserts a record in the track_e_item_property table (No update)
4277
 * @param string $tool
4278
 * @param int $ref
4279
 * @param string $title
4280
 * @param string $content
4281
 * @param int $progress
4282
 * @return bool|int
4283
 */
4284
function api_track_item_property_update($tool, $ref, $title, $content, $progress)
4285
{
4286
    $tbl_stats_item_property = Database::get_main_table(TABLE_STATISTIC_TRACK_E_ITEM_PROPERTY);
4287
    $course_id = api_get_course_int_id(); //numeric
4288
    $course_code = api_get_course_id(); //alphanumeric
4289
    $item_property_id = api_get_item_property_id($course_code, $tool, $ref);
4290
    if (!empty($item_property_id)) {
4291
        $sql = "INSERT IGNORE INTO $tbl_stats_item_property SET
4292
                course_id           = '$course_id',
4293
                item_property_id    = '$item_property_id',
4294
                title               = '".Database::escape_string($title)."',
4295
                content             = '".Database::escape_string($content)."',
4296
                progress            = '".intval($progress)."',
4297
                lastedit_date       = '".api_get_utc_datetime()."',
4298
                lastedit_user_id    = '".api_get_user_id()."',
4299
                session_id          = '".api_get_session_id()."'";
4300
        $result = Database::query($sql);
4301
        $affected_rows = Database::affected_rows($result);
4302
4303
        return $affected_rows;
4304
    }
4305
4306
    return false;
4307
}
4308
4309
/**
4310
 * @param string $tool
4311
 * @param int $ref
4312
 * @return array|resource
4313
 */
4314
function api_get_track_item_property_history($tool, $ref)
4315
{
4316
    $tbl_stats_item_property = Database::get_main_table(TABLE_STATISTIC_TRACK_E_ITEM_PROPERTY);
4317
    $course_id = api_get_course_int_id(); //numeric
4318
    $course_code = api_get_course_id(); //alphanumeric
4319
    $item_property_id = api_get_item_property_id($course_code, $tool, $ref);
4320
    $sql = "SELECT * FROM $tbl_stats_item_property
4321
            WHERE item_property_id = $item_property_id AND course_id = $course_id
4322
            ORDER BY lastedit_date DESC";
4323
    $result = Database::query($sql);
4324
    if ($result === false or $result === null) {
4325
        $result = [];
4326
    } else {
4327
        $result = Database::store_result($result, 'ASSOC');
4328
    }
4329
4330
    return $result;
4331
}
4332
4333
/**
4334
 * Gets item property data from tool of a course id
4335
 * @param int $course_id
4336
 * @param string $tool   tool name, linked to 'rubrique' of the course tool_list (Warning: language sensitive !!)
4337
 * @param int $ref id of the item itself, linked to key of every tool ('id', ...), "*" = all items of the tool
4338
 * @param int $session_id
4339
 * @param int $groupId
4340
 *
4341
 * @return array with all fields from c_item_property, empty array if not found or false if course could not be found
4342
 */
4343
function api_get_item_property_info($course_id, $tool, $ref, $session_id = 0, $groupId = 0)
4344
{
4345
    $courseInfo = api_get_course_info_by_id($course_id);
4346
4347
    if (empty($courseInfo)) {
4348
        return false;
4349
    }
4350
4351
    $tool = Database::escape_string($tool);
4352
    $ref = intval($ref);
4353
    $course_id = $courseInfo['real_id'];
4354
    $session_id = intval($session_id);
4355
4356
    $sessionCondition = " session_id = $session_id";
4357
    if (empty($session_id)) {
4358
        $sessionCondition = " (session_id = 0 OR session_id IS NULL) ";
4359
    }
4360
4361
    // Definition of tables.
4362
    $table = Database::get_course_table(TABLE_ITEM_PROPERTY);
4363
4364
    $sql = "SELECT * FROM $table
4365
            WHERE
4366
                c_id = $course_id AND
4367
                tool = '$tool' AND
4368
                ref = $ref AND
4369
                $sessionCondition ";
4370
4371
    if (!empty($groupId)) {
4372
        $groupId = intval($groupId);
4373
        $sql .= " AND to_group_id = $groupId ";
4374
    }
4375
4376
    $rs  = Database::query($sql);
4377
    $row = [];
4378
    if (Database::num_rows($rs) > 0) {
4379
        $row = Database::fetch_array($rs, 'ASSOC');
4380
    }
4381
4382
    return $row;
4383
}
4384
4385
/**
4386
 * Displays a combo box so the user can select his/her preferred language.
4387
 * @param string The desired name= value for the select
4388
 * @param bool Whether we use the JQuery Chozen library or not
4389
 * (in some cases, like the indexing language picker, it can alter the presentation)
4390
 * @return string
4391
 */
4392
function api_get_languages_combo($name = 'language')
4393
{
4394
    $ret = '';
4395
    $platformLanguage = api_get_setting('platformLanguage');
4396
4397
    // Retrieve a complete list of all the languages.
4398
    $language_list = api_get_languages();
4399
4400
    if (count($language_list) < 2) {
4401
        return $ret;
4402
    }
4403
4404
    // The the current language of the user so that his/her language occurs as selected in the dropdown menu.
4405
    if (isset($_SESSION['user_language_choice'])) {
4406
        $default = $_SESSION['user_language_choice'];
4407
    } else {
4408
        $default = $platformLanguage;
4409
    }
4410
4411
    $ret .= '<select name="'.$name.'" id="language_chosen" class="selectpicker show-tick form-control">';
4412
    foreach ($language_list as $key => $value) {
4413
        if ($key == $default) {
4414
            $selected = ' selected="selected"';
4415
        } else {
4416
            $selected = '';
4417
        }
4418
        $ret .= sprintf('<option value=%s" %s>%s</option>', $key, $selected, $value);
4419
    }
4420
    $ret .= '</select>';
4421
4422
    return $ret;
4423
}
4424
4425
/**
4426
 * Displays a form (drop down menu) so the user can select his/her preferred language.
4427
 * The form works with or without javascript
4428
 * @param  boolean Hide form if only one language available (defaults to false = show the box anyway)
4429
 * @param bool $showAsButton
4430
 * @return string Display the box directly
4431
 */
4432
function api_display_language_form($hide_if_no_choice = false, $showAsButton = false)
4433
{
4434
    // Retrieve a complete list of all the languages.
4435
    $language_list = api_get_languages();
4436
4437
    if (count($language_list) <= 1 && $hide_if_no_choice) {
4438
        // don't show any form
4439
        return '';
4440
    }
4441
4442
    // The the current language of the user so that his/her language occurs as selected in the dropdown menu.
4443
    if (isset($_SESSION['user_language_choice'])) {
4444
        $user_selected_language = $_SESSION['user_language_choice'];
4445
    }
4446
    if (empty($user_selected_language)) {
4447
        $user_selected_language = api_get_setting('platformLanguage');
4448
    }
4449
4450
    $user_selected_language = 'en';
4451
    $countryCode = languageToCountryIsoCode($user_selected_language);
4452
    $language = api_get_language_from_iso($user_selected_language);
4453
4454
    $url = api_get_self();
4455
    if ($showAsButton) {
4456
        $html = '<div class="btn-group">
4457
              <button type="button" class="btn btn-default dropdown-toggle" data-toggle="dropdown">
4458
                <span class="flag-icon flag-icon-'.$countryCode.'"></span>
4459
                '.$language->getOriginalName().'
4460
                <span class="caret">
4461
                </span>
4462
              </button>';
4463
    } else {
4464
        $html = '
4465
            <a href="'.$url.'" class="dropdown-toggle" data-toggle="dropdown" role="button">
4466
                <span class="flag-icon flag-icon-'.$countryCode.'"></span> 
4467
                '.$language->getOriginalName().'
4468
                <span class="caret"></span>
4469
            </a>
4470
            ';
4471
    }
4472
4473
    $html .= '<ul class="dropdown-menu" role="menu">';
4474
    foreach ($language_list as $iso => $data) {
4475
        $urlLink = $url.'?language='.$data;
4476
        $html .= '<li><a href="'.$urlLink.'">';
4477
        $html .= '<span class="flag-icon flag-icon-'.languageToCountryIsoCode($iso).'"></span> '.$data.'</a></li>';
4478
    }
4479
    $html .= '</ul>';
4480
4481
    if ($showAsButton) {
4482
        $html .= '</div>';
4483
    }
4484
4485
    return $html;
4486
}
4487
4488
/**
4489
 * @param string $languageIsoCode
4490
 * @return string
4491
 */
4492
function languageToCountryIsoCode($languageIsoCode)
4493
{
4494
    // @todo save in DB
4495
    switch ($languageIsoCode) {
4496
        case 'ko':
4497
            $country = 'kr';
4498
            break;
4499
        case 'ja':
4500
            $country = 'jp';
4501
            break;
4502
        case 'ca':
4503
            $country = 'es';
4504
            break;
4505
        case 'gl':
4506
            $country = 'es';
4507
            break;
4508
        case 'ka':
4509
            $country = 'ge';
4510
            break;
4511
        case 'sl':
4512
            $country = 'si';
4513
            break;
4514
        case 'eu':
4515
            $country = 'es';
4516
            break;
4517
        case 'cs':
4518
            $country = 'cz';
4519
            break;
4520
        case 'el':
4521
            $country = 'ae';
4522
            break;
4523
        case 'ar':
4524
            $country = 'ae';
4525
            break;
4526
        case 'en':
4527
            $country = 'gb';
4528
            break;
4529
        case 'he':
4530
            $country = 'il';
4531
            break;
4532
        case 'uk':
4533
            $country = 'ua'; //Ukraine
4534
            break;
4535
        case 'da':
4536
            $country = 'dk';
4537
            break;
4538
        case 'pt-BR':
4539
            $country = 'br';
4540
            break;
4541
        case 'qu':
4542
            $country = 'pe';
4543
            break;
4544
        case 'sv':
4545
            $country = 'se';
4546
            break;
4547
        case 'zh-TW':
4548
        case 'zh':
4549
            $country = 'cn';
4550
            break;
4551
        default:
4552
            $country = $languageIsoCode;
4553
            break;
4554
    }
4555
    $country = strtolower($country);
4556
    return $country;
4557
}
4558
4559
4560
/**
4561
 * Returns a list of all the languages that are made available by the admin.
4562
 * @return array An array with all languages. Structure of the array is
4563
 *  array['name'] = An array with the name of every language
4564
 *  array['folder'] = An array with the corresponding names of the language-folders in the filesystem
4565
 */
4566
function api_get_languages()
4567
{
4568
    $tbl_language = Database::get_main_table(TABLE_MAIN_LANGUAGE);
4569
    $sql = "SELECT * FROM $tbl_language WHERE available='1' 
4570
            ORDER BY original_name ASC";
4571
    $result = Database::query($sql);
4572
    $languages = [];
4573
    while ($row = Database::fetch_array($result, 'ASSOC')) {
4574
        $languages[$row['isocode']] = $row['original_name'];
4575
    }
4576
    return $languages;
4577
}
4578
4579
/**
4580
 * Returns a list of all the languages that are made available by the admin.
4581
 * @return array
4582
 */
4583
function api_get_languages_to_array()
4584
{
4585
    $tbl_language = Database::get_main_table(TABLE_MAIN_LANGUAGE);
4586
    $sql = "SELECT * FROM $tbl_language WHERE available='1' ORDER BY original_name ASC";
4587
    $result = Database::query($sql);
4588
    $languages = [];
4589
    while ($row = Database::fetch_array($result)) {
4590
        $languages[$row['dokeos_folder']] = $row['original_name'];
4591
    }
4592
    return $languages;
4593
}
4594
4595
/**
4596
 * Returns the id (the database id) of a language
4597
 * @param   string  language name (the corresponding name of the language-folder in the filesystem)
4598
 * @return  int     id of the language
4599
 */
4600
function api_get_language_id($language)
4601
{
4602
    $tbl_language = Database::get_main_table(TABLE_MAIN_LANGUAGE);
4603
    if (empty($language)) {
4604
        return null;
4605
    }
4606
    $language = Database::escape_string($language);
4607
    $sql = "SELECT id FROM $tbl_language
4608
            WHERE dokeos_folder = '$language' LIMIT 1";
4609
    $result = Database::query($sql);
4610
    $row = Database::fetch_array($result);
4611
    return $row['id'];
4612
}
4613
4614
/**
4615
 * Gets language of the requested type for the current user. Types are :
4616
 * user_profil_lang : profile language of current user
4617
 * user_select_lang : language selected by user at login
4618
 * course_lang : language of the current course
4619
 * platform_lang : default platform language
4620
 * @param string $lang_type
4621
 * @return string
4622
 **/
4623
function api_get_language_from_type($lang_type)
4624
{
4625
    $return = false;
4626
    switch ($lang_type) {
4627
        case 'platform_lang':
4628
            $temp_lang = api_get_setting('platformLanguage');
4629
            if (!empty($temp_lang)) {
4630
                $return = $temp_lang;
4631
            }
4632
            break;
4633
        case 'user_profil_lang':
4634
            $_user = api_get_user_info();
4635
            if (isset($_user['language']) && !empty($_user['language'])) {
4636
                $return = $_user['language'];
4637
            }
4638
            break;
4639
        case 'user_selected_lang':
4640
            if (isset($_SESSION['user_language_choice']) && !empty($_SESSION['user_language_choice'])) {
4641
                $return = $_SESSION['user_language_choice'];
4642
            }
4643
            break;
4644
        case 'course_lang':
4645
            global $_course;
4646
            $cidReq = null;
4647
            if (empty($_course)) {
4648
                // Code modified because the local.inc.php file it's declarated after this work
4649
                // causing the function api_get_course_info() returns a null value
4650
                $cidReq = isset($_GET["cidReq"]) ? Database::escape_string($_GET["cidReq"]) : null;
4651
                $cDir = (!empty($_GET['cDir']) ? $_GET['cDir'] : null);
4652
                if (empty($cidReq) && !empty($cDir)) {
4653
                    $c = CourseManager::getCourseCodeFromDirectory($cDir);
4654
                    if ($c) {
4655
                        $cidReq = $c;
4656
                    }
4657
                }
4658
            }
4659
            $_course = api_get_course_info($cidReq);
4660
            if (isset($_course['language']) && !empty($_course['language'])) {
4661
                $return = $_course['language'];
4662
                $showCourseInUserLanguage = api_get_course_setting('show_course_in_user_language');
4663
                if ($showCourseInUserLanguage == 1) {
4664
                    $userInfo = api_get_user_info();
4665
                    if (isset($userInfo['language'])) {
4666
                        $return = $userInfo['language'];
4667
                    }
4668
                }
4669
            }
4670
            break;
4671
        default:
4672
            $return = false;
4673
            break;
4674
    }
4675
4676
    return $return;
4677
}
4678
4679
/**
4680
 * Get the language information by its id
4681
 * @param int $languageId
4682
 * @return array
4683
 */
4684
function api_get_language_info($languageId)
4685
{
4686
    $language = Database::getManager()
4687
        ->find('ChamiloCoreBundle:Language', intval($languageId));
4688
4689
    if (!$language) {
4690
        return [];
4691
    }
4692
4693
    return [
4694
        'id' => $language->getId(),
4695
        'original_name' => $language->getOriginalName(),
4696
        'english_name' => $language->getEnglishName(),
4697
        'isocode' => $language->getIsocode(),
4698
        'dokeos_folder' => $language->getDokeosFolder(),
4699
        'available' => $language->getAvailable(),
4700
        'parent_id' => $language->getParent() ? $language->getParent()->getId() : null
4701
    ];
4702
}
4703
4704
/**
4705
 * @param string $code
4706
 * @return \Chamilo\CoreBundle\Entity\Language
4707
 */
4708
function api_get_language_from_iso($code)
4709
{
4710
    $em = Database::getManager();
4711
    $language = $em->getRepository('ChamiloCoreBundle:Language')->findOneBy(['isocode' => $code]);
4712
    return $language;
4713
}
4714
4715
/**
4716
 * Returns the name of the visual (CSS) theme to be applied on the current page.
4717
 * The returned name depends on the platform, course or user -wide settings.
4718
 * @return string The visual theme's name, it is the name of a folder inside web/css/themes
4719
 */
4720
function api_get_visual_theme()
4721
{
4722
    static $visual_theme;
4723
    if (!isset($visual_theme)) {
4724
        // Get style directly from DB
4725
        $styleFromDatabase = api_get_settings_params_simple(
4726
            [
4727
                'variable = ? AND access_url = ?' => [
4728
                    'stylesheets',
4729
                    api_get_current_access_url_id(),
4730
                ],
4731
            ]
4732
        );
4733
        if ($styleFromDatabase) {
4734
            $platform_theme = $styleFromDatabase['selected_value'];
4735
        } else {
4736
            $platform_theme = api_get_setting('stylesheets');
4737
        }
4738
4739
        // Platform's theme.
4740
        $visual_theme = $platform_theme;
4741
        if (api_get_setting('user_selected_theme') == 'true') {
4742
            $user_info = api_get_user_info();
4743
            if (isset($user_info['theme'])) {
4744
                $user_theme = $user_info['theme'];
4745
4746
                if (!empty($user_theme)) {
4747
                    $visual_theme = $user_theme;
4748
                    // User's theme.
4749
                }
4750
            }
4751
        }
4752
4753
        $course_id = api_get_course_id();
4754
        if (!empty($course_id) && $course_id != -1) {
4755
            if (api_get_setting('allow_course_theme') == 'true') {
4756
                $course_theme = api_get_course_setting('course_theme');
4757
4758
                if (!empty($course_theme) && $course_theme != -1) {
4759
                    if (!empty($course_theme)) {
4760
                        // Course's theme.
4761
                        $visual_theme = $course_theme;
4762
                    }
4763
                }
4764
4765
                $allow_lp_theme = api_get_course_setting('allow_learning_path_theme');
4766
                if ($allow_lp_theme == 1) {
4767
                    global $lp_theme_css, $lp_theme_config;
4768
                    // These variables come from the file lp_controller.php.
4769
                    if (!$lp_theme_config) {
4770
                        if (!empty($lp_theme_css)) {
4771
                            // LP's theme.
4772
                            $visual_theme = $lp_theme_css;
4773
                        }
4774
                    }
4775
                }
4776
            }
4777
        }
4778
4779
        if (empty($visual_theme)) {
4780
            $visual_theme = 'chamilo';
4781
        }
4782
4783
        global $lp_theme_log;
4784
        if ($lp_theme_log) {
4785
            $visual_theme = $platform_theme;
4786
        }
4787
    }
4788
4789
    return $visual_theme;
4790
}
4791
4792
/**
4793
 * Returns a list of CSS themes currently available in the CSS folder
4794
 * The folder must have a default.css file
4795
 * @param bool $getOnlyThemeFromVirtualInstance Used by the vchamilo plugin
4796
 * @return array        List of themes directories from the css folder
4797
 * Note: Directory names (names of themes) in the file system should contain ASCII-characters only.
4798
 */
4799
function api_get_themes($getOnlyThemeFromVirtualInstance = false)
4800
{
4801
    // This configuration value is set by the vchamilo plugin
4802
    $virtualTheme = api_get_configuration_value('virtual_css_theme_folder');
4803
4804
    $readCssFolder = function ($dir) use ($virtualTheme) {
4805
        $finder = new Finder();
4806
        $themes = $finder->directories()->in($dir)->depth(0)->sortByName();
4807
        $list = [];
4808
        /** @var Symfony\Component\Finder\SplFileInfo $theme */
4809
        foreach ($themes as $theme) {
4810
            $folder = $theme->getFilename();
4811
            // A theme folder is consider if there's a default.css file
4812
            if (!file_exists($theme->getPathname().'/default.css')) {
4813
                continue;
4814
            }
4815
            $name = ucwords(str_replace('_', ' ', $folder));
4816
            if ($folder == $virtualTheme) {
4817
                continue;
4818
            }
4819
            $list[$folder] = $name;
4820
        }
4821
        return $list;
4822
    };
4823
4824
    $dir = api_get_path(SYS_CSS_PATH).'themes/';
4825
    $list = $readCssFolder($dir);
4826
4827
    if (!empty($virtualTheme)) {
4828
        $newList = $readCssFolder($dir.'/'.$virtualTheme);
4829
        if ($getOnlyThemeFromVirtualInstance) {
4830
            return $newList;
4831
        }
4832
        $list = $list + $newList;
4833
        asort($list);
4834
    }
4835
4836
    return $list;
4837
}
4838
4839
/**
4840
 * Find the largest sort value in a given user_course_category
4841
 * This function is used when we are moving a course to a different category
4842
 * and also when a user subscribes to courses (the new course is added at the end of the main category
4843
 * @author Patrick Cool <[email protected]>, Ghent University
4844
 * @param int $user_course_category the id of the user_course_category
4845
 * @param integer $user_id
4846
 * @return int the value of the highest sort of the user_course_category
4847
 */
4848
function api_max_sort_value($user_course_category, $user_id)
4849
{
4850
    $tbl_course_user = Database::get_main_table(TABLE_MAIN_COURSE_USER);
4851
    $sql = "SELECT max(sort) as max_sort FROM $tbl_course_user
4852
            WHERE
4853
                user_id='".intval($user_id)."' AND
4854
                relation_type<>".COURSE_RELATION_TYPE_RRHH." AND
4855
                user_course_cat='".intval($user_course_category)."'";
4856
    $result_max = Database::query($sql);
4857
    if (Database::num_rows($result_max) == 1) {
4858
        $row_max = Database::fetch_array($result_max);
4859
        return $row_max['max_sort'];
4860
    }
4861
    return 0;
4862
}
4863
4864
/**
4865
 * Transforms a number of seconds in hh:mm:ss format
4866
 * @author Julian Prud'homme
4867
 * @param integer the number of seconds
4868
 * @return string the formated time
4869
 */
4870
function api_time_to_hms($seconds)
4871
{
4872
    // $seconds = -1 means that we have wrong data in the db.
4873
    if ($seconds == -1) {
4874
        return
4875
            get_lang('Unknown').
4876
            Display::return_icon(
4877
                'info2.gif',
4878
                get_lang('WrongDatasForTimeSpentOnThePlatform'),
4879
                ['align' => 'absmiddle', 'hspace' => '3px']
4880
            );
4881
    }
4882
4883
    // How many hours ?
4884
    $hours = floor($seconds / 3600);
4885
4886
    // How many minutes ?
4887
    $min = floor(($seconds - ($hours * 3600)) / 60);
4888
4889
    // How many seconds
4890
    $sec = floor($seconds - ($hours * 3600) - ($min * 60));
4891
4892
    if ($sec < 10) {
4893
        $sec = "0$sec";
4894
    }
4895
4896
    if ($min < 10) {
4897
        $min = "0$min";
4898
    }
4899
4900
    return "$hours:$min:$sec";
4901
}
4902
4903
/* FILE SYSTEM RELATED FUNCTIONS */
4904
4905
/**
4906
 * Returns the permissions to be assigned to every newly created directory by the web-server.
4907
 * The return value is based on the platform administrator's setting
4908
 * "Administration > Configuration settings > Security > Permissions for new directories".
4909
 * @return int  Returns the permissions in the format "Owner-Group-Others, Read-Write-Execute", as an integer value.
4910
 */
4911
function api_get_permissions_for_new_directories()
4912
{
4913
    static $permissions;
4914
    if (!isset($permissions)) {
4915
        $permissions = trim(api_get_setting('permissions_for_new_directories'));
4916
        // The default value 0777 is according to that in the platform administration panel after fresh system installation.
4917
        $permissions = octdec(!empty($permissions) ? $permissions : '0777');
4918
    }
4919
    return $permissions;
4920
}
4921
4922
/**
4923
 * Returns the permissions to be assigned to every newly created directory by the web-server.
4924
 * The return value is based on the platform administrator's setting
4925
 * "Administration > Configuration settings > Security > Permissions for new files".
4926
 * @return int Returns the permissions in the format
4927
 * "Owner-Group-Others, Read-Write-Execute", as an integer value.
4928
 */
4929
function api_get_permissions_for_new_files()
4930
{
4931
    static $permissions;
4932
    if (!isset($permissions)) {
4933
        $permissions = trim(api_get_setting('permissions_for_new_files'));
4934
        // The default value 0666 is according to that in the platform
4935
        // administration panel after fresh system installation.
4936
        $permissions = octdec(!empty($permissions) ? $permissions : '0666');
4937
    }
4938
    return $permissions;
4939
}
4940
4941
/**
4942
 * Deletes a file, or a folder and its contents
4943
 *
4944
 * @author      Aidan Lister <[email protected]>
4945
 * @version     1.0.3
4946
 * @param       string   $dirname    Directory to delete
4947
 * @param       bool     Deletes only the content or not
4948
 * @param       bool     $strict if one folder/file fails stop the loop
4949
 * @return      bool     Returns TRUE on success, FALSE on failure
4950
 * @link http://aidanlister.com/2004/04/recursively-deleting-a-folder-in-php/
4951
 * @author      Yannick Warnier, adaptation for the Chamilo LMS, April, 2008
4952
 * @author      Ivan Tcholakov, a sanity check about Directory class creation has been added, September, 2009
4953
 */
4954
function rmdirr($dirname, $delete_only_content_in_folder = false, $strict = false)
4955
{
4956
    $res = true;
4957
    // A sanity check.
4958
    if (!file_exists($dirname)) {
4959
        return false;
4960
    }
4961
    $php_errormsg = '';
4962
    // Simple delete for a file.
4963
    if (is_file($dirname) || is_link($dirname)) {
4964
        $res = unlink($dirname);
4965
        if ($res === false) {
4966
            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);
4967
        }
4968
        return $res;
4969
    }
4970
4971
    // Loop through the folder.
4972
    $dir = dir($dirname);
4973
    // A sanity check.
4974
    $is_object_dir = is_object($dir);
4975
    if ($is_object_dir) {
4976
        while (false !== $entry = $dir->read()) {
4977
            // Skip pointers.
4978
            if ($entry == '.' || $entry == '..') {
4979
                continue;
4980
            }
4981
4982
            // Recurse.
4983
            if ($strict) {
4984
                $result = rmdirr("$dirname/$entry");
4985
                if ($result == false) {
4986
                    $res = false;
4987
                    break;
4988
                }
4989
            } else {
4990
                rmdirr("$dirname/$entry");
4991
            }
4992
        }
4993
    }
4994
4995
    // Clean up.
4996
    if ($is_object_dir) {
4997
        $dir->close();
4998
    }
4999
5000
    if ($delete_only_content_in_folder == false) {
5001
        $res = rmdir($dirname);
5002
        if ($res === false) {
5003
            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);
5004
        }
5005
    }
5006
    return $res;
5007
}
5008
5009
// TODO: This function is to be simplified. File access modes to be implemented.
5010
/**
5011
 * function adapted from a php.net comment
5012
 * copy recursively a folder
5013
 * @param the source folder
5014
 * @param the dest folder
5015
 * @param an array of excluded file_name (without extension)
5016
 * @param copied_files the returned array of copied files
5017
 * @param string $source
5018
 * @param string $dest
5019
 */
5020
function copyr($source, $dest, $exclude = [], $copied_files = [])
5021
{
5022
    if (empty($dest)) {
5023
        return false;
5024
    }
5025
    // Simple copy for a file
5026
    if (is_file($source)) {
5027
        $path_info = pathinfo($source);
5028
        if (!in_array($path_info['filename'], $exclude)) {
5029
            copy($source, $dest);
5030
        }
5031
        return true;
5032
    } elseif (!is_dir($source)) {
5033
        //then source is not a dir nor a file, return
5034
        return false;
5035
    }
5036
5037
    // Make destination directory.
5038
    if (!is_dir($dest)) {
5039
        mkdir($dest, api_get_permissions_for_new_directories());
5040
    }
5041
5042
    // Loop through the folder.
5043
    $dir = dir($source);
5044
    while (false !== $entry = $dir->read()) {
5045
        // Skip pointers
5046
        if ($entry == '.' || $entry == '..') {
5047
            continue;
5048
        }
5049
5050
        // Deep copy directories.
5051
        if ($dest !== "$source/$entry") {
5052
            $files = copyr("$source/$entry", "$dest/$entry", $exclude, $copied_files);
5053
        }
5054
    }
5055
    // Clean up.
5056
    $dir->close();
5057
    return true;
5058
}
5059
5060
// TODO: Using DIRECTORY_SEPARATOR is not recommended, this is an obsolete approach. Documentation header to be added here.
5061
/**
5062
 * @param string $pathname
5063
 * @param string $base_path_document
5064
 * @param integer $session_id
5065
 */
5066
function copy_folder_course_session(
5067
    $pathname,
5068
    $base_path_document,
5069
    $session_id,
5070
    $course_info,
5071
    $document,
5072
    $source_course_id
5073
) {
5074
    $table = Database::get_course_table(TABLE_DOCUMENT);
5075
    $session_id = intval($session_id);
5076
    $source_course_id = intval($source_course_id);
5077
5078
    // Check whether directory already exists.
5079
    if (is_dir($pathname) || empty($pathname)) {
5080
        return true;
5081
    }
5082
5083
    // Ensure that a file with the same name does not already exist.
5084
    if (is_file($pathname)) {
5085
        trigger_error('copy_folder_course_session(): File exists', E_USER_WARNING);
5086
        return false;
5087
    }
5088
5089
    $course_id = $course_info['real_id'];
5090
    $folders = explode(DIRECTORY_SEPARATOR, str_replace($base_path_document.DIRECTORY_SEPARATOR, '', $pathname));
5091
    $new_pathname = $base_path_document;
5092
    $path = '';
5093
5094
    foreach ($folders as $folder) {
5095
        $new_pathname .= DIRECTORY_SEPARATOR.$folder;
5096
        $path .= DIRECTORY_SEPARATOR.$folder;
5097
5098
        if (!file_exists($new_pathname)) {
5099
            $path = Database::escape_string($path);
5100
5101
            $sql = "SELECT * FROM $table
5102
                    WHERE
5103
                        c_id = $source_course_id AND
5104
                        path = '$path' AND
5105
                        filetype = 'folder' AND
5106
                        session_id = '$session_id'";
5107
            $rs1 = Database::query($sql);
5108
            $num_rows = Database::num_rows($rs1);
5109
5110
            if ($num_rows == 0) {
5111
                mkdir($new_pathname, api_get_permissions_for_new_directories());
5112
5113
                // Insert new folder with destination session_id.
5114
                $params = [
5115
                    'c_id' => $course_id,
5116
                    'path' => $path,
5117
                    'comment' => $document->comment,
5118
                    'title' => basename($new_pathname),
5119
                    'filetype' => 'folder',
5120
                    'size' => '0',
5121
                    'session_id' => $session_id
5122
                ];
5123
                $document_id = Database::insert($table, $params);
5124
                if ($document_id) {
5125
                    $sql = "UPDATE $table SET id = iid WHERE iid = $document_id";
5126
                    Database::query($sql);
5127
5128
                    api_item_property_update(
5129
                        $course_info,
5130
                        TOOL_DOCUMENT,
5131
                        $document_id,
5132
                        'FolderCreated',
5133
                        api_get_user_id(),
5134
                        0,
5135
                        0,
5136
                        null,
5137
                        null,
5138
                        $session_id
5139
                    );
5140
                }
5141
            }
5142
        }
5143
    } // en foreach
5144
}
5145
5146
// TODO: chmodr() is a better name. Some corrections are needed. Documentation header to be added here.
5147
/**
5148
 * @param string $path
5149
 */
5150
function api_chmod_R($path, $filemode)
5151
{
5152
    if (!is_dir($path)) {
5153
        return chmod($path, $filemode);
5154
    }
5155
5156
    $handler = opendir($path);
5157
    while ($file = readdir($handler)) {
5158
        if ($file != '.' && $file != '..') {
5159
            $fullpath = "$path/$file";
5160
            if (!is_dir($fullpath)) {
5161
                if (!chmod($fullpath, $filemode)) {
5162
                    return false;
5163
                }
5164
            } else {
5165
                if (!api_chmod_R($fullpath, $filemode)) {
5166
                    return false;
5167
                }
5168
            }
5169
        }
5170
    }
5171
5172
    closedir($handler);
5173
    return chmod($path, $filemode);
5174
}
5175
5176
5177
// TODO: Where the following function has been copy/pased from? There is no information about author and license. Style, coding conventions...
5178
/**
5179
 * Parse info file format. (e.g: file.info)
5180
 *
5181
 * Files should use an ini-like format to specify values.
5182
 * White-space generally doesn't matter, except inside values.
5183
 * e.g.
5184
 *
5185
 * @verbatim
5186
 *   key = value
5187
 *   key = "value"
5188
 *   key = 'value'
5189
 *   key = "multi-line
5190
 *
5191
 *   value"
5192
 *   key = 'multi-line
5193
 *
5194
 *   value'
5195
 *   key
5196
 *   =
5197
 *   'value'
5198
 * @endverbatim
5199
 *
5200
 * Arrays are created using a GET-like syntax:
5201
 *
5202
 * @verbatim
5203
 *   key[] = "numeric array"
5204
 *   key[index] = "associative array"
5205
 *   key[index][] = "nested numeric array"
5206
 *   key[index][index] = "nested associative array"
5207
 * @endverbatim
5208
 *
5209
 * PHP constants are substituted in, but only when used as the entire value:
5210
 *
5211
 * Comments should start with a semi-colon at the beginning of a line.
5212
 *
5213
 * This function is NOT for placing arbitrary module-specific settings. Use
5214
 * variable_get() and variable_set() for that.
5215
 *
5216
 * Information stored in the module.info file:
5217
 * - name: The real name of the module for display purposes.
5218
 * - description: A brief description of the module.
5219
 * - dependencies: An array of shortnames of other modules this module depends on.
5220
 * - package: The name of the package of modules this module belongs to.
5221
 *
5222
 * Example of .info file:
5223
 * <code>
5224
 * @verbatim
5225
 *   name = Forum
5226
 *   description = Enables threaded discussions about general topics.
5227
 *   dependencies[] = taxonomy
5228
 *   dependencies[] = comment
5229
 *   package = Core - optional
5230
 *   version = VERSION
5231
 * @endverbatim
5232
 * </code>
5233
 * @param string $filename
5234
 *   The file we are parsing. Accepts file with relative or absolute path.
5235
 * @return
5236
 *   The info array.
5237
 */
5238
function api_parse_info_file($filename)
5239
{
5240
    $info = [];
5241
5242
    if (!file_exists($filename)) {
5243
        return $info;
5244
    }
5245
5246
    $data = file_get_contents($filename);
5247
    if (preg_match_all('
5248
        @^\s*                           # Start at the beginning of a line, ignoring leading whitespace
5249
        ((?:
5250
          [^=;\[\]]|                    # Key names cannot contain equal signs, semi-colons or square brackets,
5251
          \[[^\[\]]*\]                  # unless they are balanced and not nested
5252
        )+?)
5253
        \s*=\s*                         # Key/value pairs are separated by equal signs (ignoring white-space)
5254
        (?:
5255
          ("(?:[^"]|(?<=\\\\)")*")|     # Double-quoted string, which may contain slash-escaped quotes/slashes
5256
          (\'(?:[^\']|(?<=\\\\)\')*\')| # Single-quoted string, which may contain slash-escaped quotes/slashes
5257
          ([^\r\n]*?)                   # Non-quoted string
5258
        )\s*$                           # Stop at the next end of a line, ignoring trailing whitespace
5259
        @msx', $data, $matches, PREG_SET_ORDER)) {
5260
        $key = $value1 = $value2 = $value3 = '';
5261
        foreach ($matches as $match) {
5262
            // Fetch the key and value string.
5263
            $i = 0;
5264
            foreach (['key', 'value1', 'value2', 'value3'] as $var) {
5265
                $$var = isset($match[++$i]) ? $match[$i] : '';
5266
            }
5267
            $value = stripslashes(substr($value1, 1, -1)).stripslashes(substr($value2, 1, -1)).$value3;
5268
5269
            // Parse array syntax.
5270
            $keys = preg_split('/\]?\[/', rtrim($key, ']'));
5271
            $last = array_pop($keys);
5272
            $parent = &$info;
5273
5274
            // Create nested arrays.
5275
            foreach ($keys as $key) {
5276
                if ($key == '') {
5277
                    $key = count($parent);
5278
                }
5279
                if (!isset($parent[$key]) || !is_array($parent[$key])) {
5280
                    $parent[$key] = [];
5281
                }
5282
                $parent = &$parent[$key];
5283
            }
5284
5285
            // Handle PHP constants.
5286
            if (defined($value)) {
5287
                $value = constant($value);
5288
            }
5289
5290
            // Insert actual value.
5291
            if ($last == '') {
5292
                $last = count($parent);
5293
            }
5294
            $parent[$last] = $value;
5295
        }
5296
    }
5297
    return $info;
5298
}
5299
5300
/**
5301
 * Gets Chamilo version from the configuration files
5302
 * @return string   A string of type "1.8.4", or an empty string if the version could not be found
5303
 */
5304
function api_get_version()
5305
{
5306
    return (string) api_get_configuration_value('system_version');
5307
}
5308
5309
/**
5310
 * Gets the software name (the name/brand of the Chamilo-based customized system)
5311
 * @return string
5312
 */
5313
function api_get_software_name()
5314
{
5315
    $name = api_get_configuration_value('software_name');
5316
    if (!empty($name)) {
5317
        return $name;
5318
    } else {
5319
        return 'Chamilo';
5320
    }
5321
}
5322
5323
/**
5324
 * Checks whether status given in parameter exists in the platform
5325
 * @param mixed the status (can be either int either string)
5326
 * @return boolean if the status exists, else returns false
5327
 */
5328
function api_status_exists($status_asked)
5329
{
5330
    global $_status_list;
5331
    return in_array($status_asked, $_status_list) ? true : isset($_status_list[$status_asked]);
5332
}
5333
5334
/**
5335
 * Checks whether status given in parameter exists in the platform. The function
5336
 * returns the status ID or false if it does not exist, but given the fact there
5337
 * is no "0" status, the return value can be checked against
5338
 * if(api_status_key()) to know if it exists.
5339
 * @param   mixed   The status (can be either int or string)
5340
 * @return  mixed   Status ID if exists, false otherwise
5341
 */
5342
function api_status_key($status)
5343
{
5344
    global $_status_list;
5345
    return isset($_status_list[$status]) ? $status : array_search($status, $_status_list);
5346
}
5347
5348
/**
5349
 * Gets the status langvars list
5350
 * @return string[] the list of status with their translations
5351
 */
5352
function api_get_status_langvars()
5353
{
5354
    return [
5355
        COURSEMANAGER => get_lang('Teacher', ''),
5356
        SESSIONADMIN => get_lang('SessionsAdmin', ''),
5357
        DRH => get_lang('Drh', ''),
5358
        STUDENT => get_lang('Student', ''),
5359
        ANONYMOUS => get_lang('Anonymous', ''),
5360
        STUDENT_BOSS => get_lang('RoleStudentBoss', ''),
5361
        INVITEE => get_lang('Invited'),
5362
    ];
5363
}
5364
5365
/**
5366
 * The function that retrieves all the possible settings for a certain config setting
5367
 * @author Patrick Cool <[email protected]>, Ghent University
5368
 */
5369
function api_get_settings_options($var)
5370
{
5371
    $table_settings_options = Database::get_main_table(TABLE_MAIN_SETTINGS_OPTIONS);
5372
    $var = Database::escape_string($var);
5373
    $sql = "SELECT * FROM $table_settings_options
5374
            WHERE variable = '$var'
5375
            ORDER BY id";
5376
    $result = Database::query($sql);
5377
    $settings_options_array = [];
5378
    while ($row = Database::fetch_array($result, 'ASSOC')) {
5379
        $settings_options_array[] = $row;
5380
    }
5381
    return $settings_options_array;
5382
}
5383
5384
/**
5385
 * @param array $params
5386
 */
5387
function api_set_setting_option($params)
5388
{
5389
    $table = Database::get_main_table(TABLE_MAIN_SETTINGS_OPTIONS);
5390
    if (empty($params['id'])) {
5391
        Database::insert($table, $params);
5392
    } else {
5393
        Database::update($table, $params, ['id = ? '=> $params['id']]);
5394
    }
5395
}
5396
5397
/**
5398
 * @param array $params
5399
 */
5400
function api_set_setting_simple($params)
5401
{
5402
    $table = Database::get_main_table(TABLE_MAIN_SETTINGS_CURRENT);
5403
    $url_id = api_get_current_access_url_id();
5404
5405
    if (empty($params['id'])) {
5406
        $params['access_url'] = $url_id;
5407
        Database::insert($table, $params);
5408
    } else {
5409
        Database::update($table, $params, ['id = ? '=> [$params['id']]]);
5410
    }
5411
}
5412
5413
/**
5414
 * @param int $id
5415
 */
5416
function api_delete_setting_option($id)
5417
{
5418
    $table = Database::get_main_table(TABLE_MAIN_SETTINGS_OPTIONS);
5419
    if (!empty($id)) {
5420
        Database::delete($table, ['id = ? '=> $id]);
5421
    }
5422
}
5423
5424
/**
5425
 * Sets a platform configuration setting to a given value
5426
 * @param string    The variable we want to update
5427
 * @param string    The value we want to record
5428
 * @param string    The sub-variable if any (in most cases, this will remain null)
5429
 * @param string    The category if any (in most cases, this will remain null)
5430
 * @param int       The access_url for which this parameter is valid
5431
 * @param string $cat
5432
 * @return bool|null
5433
 */
5434
function api_set_setting($var, $value, $subvar = null, $cat = null, $access_url = 1)
5435
{
5436
    if (empty($var)) {
5437
        return false;
5438
    }
5439
    $t_settings = Database::get_main_table(TABLE_MAIN_SETTINGS_CURRENT);
5440
    $var = Database::escape_string($var);
5441
    $value = Database::escape_string($value);
5442
    $access_url = (int) $access_url;
5443
    if (empty($access_url)) {
5444
        $access_url = 1;
5445
    }
5446
    $select = "SELECT id FROM $t_settings WHERE variable = '$var' ";
5447
    if (!empty($subvar)) {
5448
        $subvar = Database::escape_string($subvar);
5449
        $select .= " AND subkey = '$subvar'";
5450
    }
5451
    if (!empty($cat)) {
5452
        $cat = Database::escape_string($cat);
5453
        $select .= " AND category = '$cat'";
5454
    }
5455
    if ($access_url > 1) {
5456
        $select .= " AND access_url = $access_url";
5457
    } else {
5458
        $select .= " AND access_url = 1 ";
5459
    }
5460
5461
    $res = Database::query($select);
5462
    if (Database::num_rows($res) > 0) {
5463
        // Found item for this access_url.
5464
        $row = Database::fetch_array($res);
5465
        $sql = "UPDATE $t_settings SET selected_value = '$value'
5466
                WHERE id = ".$row['id'];
5467
        Database::query($sql);
5468
    } else {
5469
        // Item not found for this access_url, we have to check if it exist with access_url = 1
5470
        $select = "SELECT * FROM $t_settings
5471
                   WHERE variable = '$var' AND access_url = 1 ";
5472
        // Just in case
5473
        if ($access_url == 1) {
5474
            if (!empty($subvar)) {
5475
                $select .= " AND subkey = '$subvar'";
5476
            }
5477
            if (!empty($cat)) {
5478
                $select .= " AND category = '$cat'";
5479
            }
5480
            $res = Database::query($select);
5481
            if (Database::num_rows($res) > 0) {
5482
                // We have a setting for access_url 1, but none for the current one, so create one.
5483
                $row = Database::fetch_array($res);
5484
                $insert = "INSERT INTO $t_settings (variable, subkey, type,category, selected_value, title, comment, scope, subkeytext, access_url)
5485
                        VALUES
5486
                        ('".$row['variable']."',".(!empty($row['subkey']) ? "'".$row['subkey']."'" : "NULL").",".
5487
                    "'".$row['type']."','".$row['category']."',".
5488
                    "'$value','".$row['title']."',".
5489
                    "".(!empty($row['comment']) ? "'".$row['comment']."'" : "NULL").",".(!empty($row['scope']) ? "'".$row['scope']."'" : "NULL").",".
5490
                    "".(!empty($row['subkeytext']) ? "'".$row['subkeytext']."'" : "NULL").",$access_url)";
5491
                Database::query($insert);
5492
            } else {
0 ignored issues
show
Unused Code introduced by
This else statement is empty and can be removed.

This check looks for the else branches of if statements that have no statements or where all statements have been commented out. This may be the result of changes for debugging or the code may simply be obsolete.

These else branches can be removed.

if (rand(1, 6) > 3) {
print "Check failed";
} else {
    //print "Check succeeded";
}

could be turned into

if (rand(1, 6) > 3) {
    print "Check failed";
}

This is much more concise to read.

Loading history...
5493
                // Such a setting does not exist.
5494
                //error_log(__FILE__.':'.__LINE__.': Attempting to update setting '.$var.' ('.$subvar.') which does not exist at all', 0);
5495
            }
5496
        } else {
5497
            // Other access url.
5498
            if (!empty($subvar)) {
5499
                $select .= " AND subkey = '$subvar'";
5500
            }
5501
            if (!empty($cat)) {
5502
                $select .= " AND category = '$cat'";
5503
            }
5504
            $res = Database::query($select);
5505
5506
            if (Database::num_rows($res) > 0) {
5507
                // We have a setting for access_url 1, but none for the current one, so create one.
5508
                $row = Database::fetch_array($res);
5509
                if ($row['access_url_changeable'] == 1) {
5510
                    $insert = "INSERT INTO $t_settings (variable,subkey, type,category, selected_value,title, comment,scope, subkeytext,access_url, access_url_changeable) VALUES
5511
                            ('".$row['variable']."',".
5512
                        (!empty($row['subkey']) ? "'".$row['subkey']."'" : "NULL").",".
5513
                        "'".$row['type']."','".$row['category']."',".
5514
                        "'$value','".$row['title']."',".
5515
                        "".(!empty($row['comment']) ? "'".$row['comment']."'" : "NULL").",".
5516
                        (!empty($row['scope']) ? "'".$row['scope']."'" : "NULL").",".
5517
                        "".(!empty($row['subkeytext']) ? "'".$row['subkeytext']."'" : "NULL").",$access_url,".$row['access_url_changeable'].")";
5518
                    Database::query($insert);
5519
                }
5520
            } else { // Such a setting does not exist.
0 ignored issues
show
Unused Code introduced by
This else statement is empty and can be removed.

This check looks for the else branches of if statements that have no statements or where all statements have been commented out. This may be the result of changes for debugging or the code may simply be obsolete.

These else branches can be removed.

if (rand(1, 6) > 3) {
print "Check failed";
} else {
    //print "Check succeeded";
}

could be turned into

if (rand(1, 6) > 3) {
    print "Check failed";
}

This is much more concise to read.

Loading history...
5521
                //error_log(__FILE__.':'.__LINE__.': Attempting to update setting '.$var.' ('.$subvar.') which does not exist at all. The access_url is: '.$access_url.' ',0);
5522
            }
5523
        }
5524
    }
5525
}
5526
5527
/**
5528
 * Sets a whole category of settings to one specific value
5529
 * @param string    Category
5530
 * @param string    Value
5531
 * @param int       Access URL. Optional. Defaults to 1
5532
 * @param array     Optional array of filters on field type
5533
 * @param string $category
5534
 * @param string $value
5535
 * @return bool
5536
 */
5537
function api_set_settings_category($category, $value = null, $access_url = 1, $fieldtype = [])
5538
{
5539
    if (empty($category)) {
5540
        return false;
5541
    }
5542
    $category = Database::escape_string($category);
5543
    $t_s = Database::get_main_table(TABLE_MAIN_SETTINGS_CURRENT);
5544
    $access_url = (int) $access_url;
5545
    if (empty($access_url)) {
5546
        $access_url = 1;
5547
    }
5548
    if (isset($value)) {
5549
        $value = Database::escape_string($value);
5550
        $sql = "UPDATE $t_s SET selected_value = '$value'
5551
                WHERE category = '$category' AND access_url = $access_url";
5552
        if (is_array($fieldtype) && count($fieldtype) > 0) {
5553
            $sql .= " AND ( ";
5554
            $i = 0;
5555
            foreach ($fieldtype as $type) {
5556
                if ($i > 0) {
5557
                    $sql .= ' OR ';
5558
                }
5559
                $type = Database::escape_string($type);
5560
                $sql .= " type='".$type."' ";
5561
                $i++;
5562
            }
5563
            $sql .= ")";
5564
        }
5565
        $res = Database::query($sql);
5566
        return $res !== false;
5567
    } else {
5568
        $sql = "UPDATE $t_s SET selected_value = NULL
5569
                WHERE category = '$category' AND access_url = $access_url";
5570
        if (is_array($fieldtype) && count($fieldtype) > 0) {
5571
            $sql .= " AND ( ";
5572
            $i = 0;
5573
            foreach ($fieldtype as $type) {
5574
                if ($i > 0) {
5575
                    $sql .= ' OR ';
5576
                }
5577
                $type = Database::escape_string($type);
5578
                $sql .= " type='".$type."' ";
5579
                $i++;
5580
            }
5581
            $sql .= ")";
5582
        }
5583
        $res = Database::query($sql);
5584
        return $res !== false;
5585
    }
5586
}
5587
5588
/**
5589
 * Gets all available access urls in an array (as in the database)
5590
 * @return array    An array of database records
5591
 */
5592
function api_get_access_urls($from = 0, $to = 1000000, $order = 'url', $direction = 'ASC')
5593
{
5594
    $table = Database::get_main_table(TABLE_MAIN_ACCESS_URL);
5595
    $from = (int) $from;
5596
    $to = (int) $to;
5597
    $order = Database::escape_string($order, null, false);
5598
    $direction = Database::escape_string($direction, null, false);
5599
    $sql = "SELECT id, url, description, active, created_by, tms
5600
            FROM $table
5601
            ORDER BY $order $direction
5602
            LIMIT $to OFFSET $from";
5603
    $res = Database::query($sql);
5604
    return Database::store_result($res);
5605
}
5606
5607
/**
5608
 * Gets the access url info in an array
5609
 * @param int $id Id of the access url
5610
 * @param bool $returnDefault Set to false if you want the real URL if URL 1 is still 'http://localhost/'
5611
 * @return array All the info (url, description, active, created_by, tms)
5612
 * from the access_url table
5613
 * @author Julio Montoya
5614
 */
5615
function api_get_access_url($id, $returnDefault = true)
5616
{
5617
    static $staticResult;
5618
    $id = intval($id);
5619
5620
    if (isset($staticResult[$id])) {
5621
        $result = $staticResult[$id];
5622
    } else {
5623
        // Calling the Database:: library dont work this is handmade.
5624
        $table_access_url = Database::get_main_table(TABLE_MAIN_ACCESS_URL);
5625
        $sql = "SELECT url, description, active, created_by, tms
5626
                FROM $table_access_url WHERE id = '$id' ";
5627
        $res = Database::query($sql);
5628
        $result = @Database::fetch_array($res);
5629
        $staticResult[$id] = $result;
5630
    }
5631
5632
    // If the result url is 'http://localhost/' (the default) and the root_web
5633
    // (=current url) is different, and the $id is = 1 (which might mean
5634
    // api_get_current_access_url_id() returned 1 by default), then return the
5635
    // root_web setting instead of the current URL
5636
    // This is provided as an option to avoid breaking the storage of URL-specific
5637
    // homepages in home/localhost/
5638
    if ($id === 1 && $returnDefault === false) {
5639
        $currentUrl = api_get_current_access_url_id();
5640
        // only do this if we are on the main URL (=1), otherwise we could get
5641
        // information on another URL instead of the one asked as parameter
5642
        if ($currentUrl === 1) {
5643
            $rootWeb = api_get_path(WEB_PATH);
5644
            $default = 'http://localhost/';
5645
            if ($result['url'] === $default && $rootWeb != $default) {
5646
                $result['url'] = $rootWeb;
5647
            }
5648
        }
5649
    }
5650
5651
    return $result;
5652
}
5653
5654
/**
5655
 * Gets all the current settings for a specific access url
5656
 * @param string    The category, if any, that we want to get
5657
 * @param string    Whether we want a simple list (display a category) or
5658
 * a grouped list (group by variable as in settings.php default). Values: 'list' or 'group'
5659
 * @param int       Access URL's ID. Optional. Uses 1 by default, which is the unique URL
5660
 * @return array    Array of database results for the current settings of the current access URL
5661
 */
5662
function &api_get_settings($cat = null, $ordering = 'list', $access_url = 1, $url_changeable = 0)
5663
{
5664
    $table = Database::get_main_table(TABLE_MAIN_SETTINGS_CURRENT);
5665
    $access_url = (int) $access_url;
5666
    $where_condition = '';
5667
    if ($url_changeable == 1) {
5668
        $where_condition = " AND access_url_changeable= '1' ";
5669
    }
5670
    if (empty($access_url) || $access_url == -1) {
5671
        $access_url = 1;
5672
    }
5673
    $sql = "SELECT * FROM $table
5674
            WHERE access_url = $access_url  $where_condition ";
5675
5676
    if (!empty($cat)) {
5677
        $cat = Database::escape_string($cat);
5678
        $sql .= " AND category='$cat' ";
5679
    }
5680
    if ($ordering == 'group') {
5681
        $sql .= " ORDER BY id ASC";
5682
    } else {
5683
        $sql .= " ORDER BY 1,2 ASC";
5684
    }
5685
    $result = Database::query($sql);
5686
    if ($result === null) {
5687
        return [];
5688
    }
5689
    $result = Database::store_result($result, 'ASSOC');
5690
5691
    return $result;
5692
}
5693
5694
/**
5695
 * @param string $value The value we want to record
5696
 * @param string $variable The variable name we want to insert
5697
 * @param string $subKey The subkey for the variable we want to insert
5698
 * @param string $type The type for the variable we want to insert
5699
 * @param string $category The category for the variable we want to insert
5700
 * @param string $title The title
5701
 * @param string $comment The comment
5702
 * @param string $scope The scope
5703
 * @param string $subKeyText The subkey text
5704
 * @param int $accessUrlId The access_url for which this parameter is valid
5705
 * @param int $visibility The changeability of this setting for non-master urls
5706
 * @return int The setting ID
5707
 */
5708
function api_add_setting(
5709
    $value,
5710
    $variable,
5711
    $subKey = '',
5712
    $type = 'textfield',
5713
    $category = '',
5714
    $title = '',
5715
    $comment = '',
5716
    $scope = '',
5717
    $subKeyText = '',
5718
    $accessUrlId = 1,
5719
    $visibility = 0
5720
) {
5721
    $em = Database::getManager();
5722
    $settingRepo = $em->getRepository('ChamiloCoreBundle:SettingsCurrent');
5723
    $accessUrlId = (int) $accessUrlId ?: 1;
5724
5725
    if (is_array($value)) {
5726
        $value = serialize($value);
5727
    } else {
5728
        $value = trim($value);
5729
    }
5730
5731
    $criteria = ['variable' => $variable, 'accessUrl' => $accessUrlId];
5732
5733
    if (!empty($subKey)) {
5734
        $criteria['subkey'] = $subKey;
5735
    }
5736
5737
    // Check if this variable doesn't exist already
5738
    /** @var SettingsCurrent $setting */
5739
    $setting = $settingRepo->findOneBy($criteria);
5740
5741
    if ($setting) {
5742
        $setting->setSelectedValue($value);
5743
5744
        $em->persist($setting);
5745
        $em->flush();
5746
5747
        return $setting->getId();
5748
    }
5749
5750
    // Item not found for this access_url, we have to check if the whole thing is missing
5751
    // (in which case we ignore the insert) or if there *is* a record but just for access_url = 1
5752
    $setting = new SettingsCurrent();
5753
    $setting
5754
        ->setVariable($variable)
5755
        ->setSelectedValue($value)
5756
        ->setType($type)
5757
        ->setCategory($category)
5758
        ->setSubkey($subKey)
5759
        ->setTitle($title)
5760
        ->setComment($comment)
5761
        ->setScope($scope)
5762
        ->setSubkeytext($subKeyText)
5763
        ->setAccessUrl($accessUrlId)
5764
        ->setAccessUrlChangeable($visibility);
5765
5766
    $em->persist($setting);
5767
    $em->flush();
5768
5769
    return $setting->getId();
5770
}
5771
5772
/**
5773
 * Checks wether a user can or can't view the contents of a course.
5774
 * @deprecated use CourseManager::is_user_subscribed_in_course
5775
 * @param   int $userid     User id or NULL to get it from $_SESSION
5776
 * @param   int $cid        Course id to check whether the user is allowed.
5777
 * @return  bool
5778
 */
5779
function api_is_course_visible_for_user($userid = null, $cid = null)
5780
{
5781
    if ($userid === null) {
5782
        $userid = api_get_user_id();
5783
    }
5784
    if (empty($userid) || strval(intval($userid)) != $userid) {
5785
        if (api_is_anonymous()) {
5786
            $userid = api_get_anonymous_id();
5787
        } else {
5788
            return false;
5789
        }
5790
    }
5791
    $cid = Database::escape_string($cid);
5792
5793
    $courseInfo = api_get_course_info($cid);
5794
    $courseId = $courseInfo['real_id'];
5795
    $is_platformAdmin = api_is_platform_admin();
5796
5797
    $course_table = Database::get_main_table(TABLE_MAIN_COURSE);
5798
    $course_cat_table = Database::get_main_table(TABLE_MAIN_CATEGORY);
5799
5800
    $sql = "SELECT
5801
                $course_table.category_code,
5802
                $course_table.visibility,
5803
                $course_table.code,
5804
                $course_cat_table.code
5805
            FROM $course_table
5806
            LEFT JOIN $course_cat_table
5807
                ON $course_table.category_code = $course_cat_table.code
5808
            WHERE
5809
                $course_table.code = '$cid'
5810
            LIMIT 1";
5811
5812
    $result = Database::query($sql);
5813
5814
    if (Database::num_rows($result) > 0) {
5815
        $visibility = Database::fetch_array($result);
5816
        $visibility = $visibility['visibility'];
5817
    } else {
5818
        $visibility = 0;
5819
    }
5820
    // Shortcut permissions in case the visibility is "open to the world".
5821
    if ($visibility === COURSE_VISIBILITY_OPEN_WORLD) {
5822
        return true;
5823
    }
5824
5825
    $tbl_course_user = Database::get_main_table(TABLE_MAIN_COURSE_USER);
5826
5827
    $sql = "SELECT
5828
                is_tutor, status
5829
            FROM $tbl_course_user
5830
            WHERE
5831
                user_id  = '$userid' AND
5832
                relation_type <> '".COURSE_RELATION_TYPE_RRHH."' AND
5833
                c_id = $courseId
5834
            LIMIT 1";
5835
5836
    $result = Database::query($sql);
5837
5838
    if (Database::num_rows($result) > 0) {
5839
        // This user has got a recorded state for this course.
5840
        $cuData = Database::fetch_array($result);
5841
        $is_courseMember = true;
5842
        $is_courseAdmin = ($cuData['status'] == 1);
5843
    }
5844
5845
    if (!$is_courseAdmin) {
5846
        // This user has no status related to this course.
5847
        // Is it the session coach or the session admin?
5848
        $tbl_session = Database::get_main_table(TABLE_MAIN_SESSION);
5849
        $tbl_session_course = Database::get_main_table(TABLE_MAIN_SESSION_COURSE);
5850
        $tbl_session_course_user = Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER);
5851
5852
        $sql = "SELECT
5853
                    session.id_coach, session_admin_id, session.id
5854
                FROM
5855
                    $tbl_session as session
5856
                INNER JOIN $tbl_session_course
5857
                    ON session_rel_course.session_id = session.id
5858
                    AND session_rel_course.c_id = '$courseId'
5859
                LIMIT 1";
5860
5861
        $result = Database::query($sql);
5862
        $row = Database::store_result($result);
5863
5864
        if ($row[0]['id_coach'] == $userid) {
5865
            $is_courseMember = true;
5866
            $is_courseAdmin = false;
5867
        } elseif ($row[0]['session_admin_id'] == $userid) {
5868
            $is_courseMember = false;
5869
            $is_courseAdmin = false;
5870
        } else {
5871
            // Check if the current user is the course coach.
5872
            $sql = "SELECT 1
5873
                    FROM $tbl_session_course
5874
                    WHERE session_rel_course.c_id = '$courseId'
5875
                    AND session_rel_course.id_coach = '$userid'
5876
                    LIMIT 1";
5877
5878
            $result = Database::query($sql);
5879
5880
            //if ($row = Database::fetch_array($result)) {
5881
            if (Database::num_rows($result) > 0) {
5882
                $is_courseMember = true;
5883
                $tbl_user = Database::get_main_table(TABLE_MAIN_USER);
5884
5885
                $sql = "SELECT status FROM $tbl_user
5886
                        WHERE user_id = $userid
5887
                        LIMIT 1";
5888
5889
                $result = Database::query($sql);
5890
5891
                if (Database::result($result, 0, 0) == 1) {
5892
                    $is_courseAdmin = true;
5893
                } else {
5894
                    $is_courseAdmin = false;
5895
                }
5896
            } else {
5897
                // Check if the user is a student is this session.
5898
                $sql = "SELECT  id
5899
                        FROM $tbl_session_course_user
5900
                        WHERE
5901
                            user_id  = '$userid' AND
5902
                            c_id = '$courseId'
5903
                        LIMIT 1";
5904
5905
                if (Database::num_rows($result) > 0) {
5906
                    // This user haa got a recorded state for this course.
5907
                    while ($row = Database::fetch_array($result)) {
5908
                        $is_courseMember = true;
5909
                        $is_courseAdmin = false;
5910
                    }
5911
                }
5912
            }
5913
        }
5914
    }
5915
5916
    switch ($visibility) {
5917
        case COURSE_VISIBILITY_OPEN_WORLD:
5918
            return true;
5919
        case COURSE_VISIBILITY_OPEN_PLATFORM:
5920
            return isset($userid);
5921
        case COURSE_VISIBILITY_REGISTERED:
5922
        case COURSE_VISIBILITY_CLOSED:
5923
            return $is_platformAdmin || $is_courseMember || $is_courseAdmin;
5924
        case COURSE_VISIBILITY_HIDDEN:
5925
            return $is_platformAdmin;
5926
    }
5927
5928
    return false;
5929
}
5930
5931
/**
5932
 * Returns whether an element (forum, message, survey ...) belongs to a session or not
5933
 * @param String the tool of the element
5934
 * @param int the element id in database
5935
 * @param int the session_id to compare with element session id
5936
 * @param string $tool
5937
 * @return boolean true if the element is in the session, false else
5938
 */
5939
function api_is_element_in_the_session($tool, $element_id, $session_id = null)
5940
{
5941
    if (is_null($session_id)) {
5942
        $session_id = api_get_session_id();
5943
    }
5944
5945
    // Get information to build query depending of the tool.
5946
    switch ($tool) {
5947
        case TOOL_SURVEY:
5948
            $table_tool = Database::get_course_table(TABLE_SURVEY);
5949
            $key_field = 'survey_id';
5950
            break;
5951
        case TOOL_ANNOUNCEMENT:
5952
            $table_tool = Database::get_course_table(TABLE_ANNOUNCEMENT);
5953
            $key_field = 'id';
5954
            break;
5955
        case TOOL_AGENDA:
5956
            $table_tool = Database::get_course_table(TABLE_AGENDA);
5957
            $key_field = 'id';
5958
            break;
5959
        case TOOL_GROUP:
5960
            $table_tool = Database::get_course_table(TABLE_GROUP);
5961
            $key_field = 'id';
5962
            break;
5963
        default:
5964
            return false;
5965
    }
5966
    $course_id = api_get_course_int_id();
5967
5968
    $sql = "SELECT session_id FROM $table_tool 
5969
            WHERE c_id = $course_id AND $key_field =  ".intval($element_id);
5970
    $rs = Database::query($sql);
5971
    if ($element_session_id = Database::result($rs, 0, 0)) {
5972
        if ($element_session_id == intval($session_id)) {
5973
            // The element belongs to the session.
5974
            return true;
5975
        }
5976
    }
5977
    return false;
5978
}
5979
5980
/**
5981
 * Replaces "forbidden" characters in a filename string.
5982
 *
5983
 * @param string $filename
5984
 * @param bool $treat_spaces_as_hyphens
5985
 *
5986
 * @return string
5987
 */
5988
function api_replace_dangerous_char($filename, $treat_spaces_as_hyphens = true)
5989
{
5990
    return URLify::filter(
5991
        $filename,
5992
        250,
5993
        '',
5994
        true,
5995
        true,
5996
        false,
5997
        false,
5998
        $treat_spaces_as_hyphens
5999
    );
6000
}
6001
6002
/**
6003
 * Fixes the $_SERVER['REQUEST_URI'] that is empty in IIS6.
6004
 * @author Ivan Tcholakov, 28-JUN-2006.
6005
 */
6006
function api_request_uri()
6007
{
6008
    if (!empty($_SERVER['REQUEST_URI'])) {
6009
        return $_SERVER['REQUEST_URI'];
6010
    }
6011
    $uri = $_SERVER['SCRIPT_NAME'];
6012
    if (!empty($_SERVER['QUERY_STRING'])) {
6013
        $uri .= '?'.$_SERVER['QUERY_STRING'];
6014
    }
6015
    $_SERVER['REQUEST_URI'] = $uri;
6016
    return $uri;
6017
}
6018
6019
6020
/** Gets the current access_url id of the Chamilo Platform
6021
 * @author Julio Montoya <[email protected]>
6022
 * @return int access_url_id of the current Chamilo Installation
6023
 */
6024
function api_get_current_access_url_id()
6025
{
6026
    $access_url_table = Database::get_main_table(TABLE_MAIN_ACCESS_URL);
6027
    $path = Database::escape_string(api_get_path(WEB_PATH));
6028
    $sql = "SELECT id FROM $access_url_table WHERE url = '".$path."'";
6029
    $result = Database::query($sql);
6030
    if (Database::num_rows($result) > 0) {
6031
        $access_url_id = Database::result($result, 0, 0);
6032
        return $access_url_id;
6033
    }
6034
    //if the url in WEB_PATH was not found, it can only mean that there is
6035
    // either a configuration problem or the first URL has not been defined yet
6036
    // (by default it is http://localhost/). Thus the more sensible thing we can
6037
    // do is return 1 (the main URL) as the user cannot hack this value anyway
6038
    return 1;
6039
}
6040
6041
/**
6042
 * Gets the registered urls from a given user id
6043
 * @author Julio Montoya <[email protected]>
6044
 * @return int user id
6045
 */
6046
function api_get_access_url_from_user($user_id)
6047
{
6048
    $user_id = intval($user_id);
6049
    $table_url_rel_user = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_USER);
6050
    $table_url          = Database::get_main_table(TABLE_MAIN_ACCESS_URL);
6051
    $sql = "SELECT access_url_id
6052
            FROM $table_url_rel_user url_rel_user
6053
            INNER JOIN $table_url u
6054
            ON (url_rel_user.access_url_id = u.id)
6055
            WHERE user_id = ".intval($user_id);
6056
    $result = Database::query($sql);
6057
    $list = [];
6058
    while ($row = Database::fetch_array($result, 'ASSOC')) {
6059
        $list[] = $row['access_url_id'];
6060
    }
6061
    return $list;
6062
}
6063
6064
/**
6065
 * Gets the status of a user in a course
6066
 * @param int       $user_id
6067
 * @param int    $courseId
6068
 * @return int      user status
6069
 */
6070
function api_get_status_of_user_in_course($user_id, $courseId)
6071
{
6072
    $tbl_rel_course_user = Database::get_main_table(TABLE_MAIN_COURSE_USER);
6073
    if (!empty($user_id) && !empty($courseId)) {
6074
        $user_id = intval($user_id);
6075
        $courseId = intval($courseId);
6076
        $sql = 'SELECT status
6077
                FROM '.$tbl_rel_course_user.'
6078
                WHERE user_id='.$user_id.' AND c_id = '.$courseId;
6079
        $result = Database::query($sql);
6080
        $row_status = Database::fetch_array($result, 'ASSOC');
6081
        return $row_status['status'];
6082
    } else {
6083
        return 0;
6084
    }
6085
}
6086
6087
/**
6088
 * Checks whether the curent user is in a group or not.
6089
 *
6090
 * @param string        The group id - optional (takes it from session if not given)
6091
 * @param string        The course code - optional (no additional check by course if course code is not given)
6092
 * @return boolean
6093
 * @author Ivan Tcholakov
6094
 */
6095
function api_is_in_group($groupIdParam = null, $courseCodeParam = null)
6096
{
6097
    if (!empty($courseCodeParam)) {
6098
        $courseCode = api_get_course_id();
6099
        if (!empty($courseCode)) {
6100
            if ($courseCodeParam != $courseCode) {
6101
                return false;
6102
            }
6103
        } else {
6104
            return false;
6105
        }
6106
    }
6107
6108
    $groupId = api_get_group_id();
6109
6110
    if (isset($groupId) && $groupId != '') {
6111
        if (!empty($groupIdParam)) {
6112
            return $groupIdParam == $groupId;
6113
        } else {
6114
            return true;
6115
        }
6116
    }
6117
6118
    return false;
6119
}
6120
6121
/**
6122
 * Checks whether a secret key is valid
6123
 * @param string $original_key_secret  - secret key from (webservice) client
6124
 * @param string $security_key - security key from Chamilo
6125
 * @return boolean - true if secret key is valid, false otherwise
6126
 */
6127
function api_is_valid_secret_key($original_key_secret, $security_key)
6128
{
6129
    return $original_key_secret == sha1($security_key);
6130
}
6131
6132
/**
6133
 * Checks whether a user is into course
6134
 * @param int $course_id - the course id
6135
 * @param int $user_id - the user id
6136
 * @return bool
6137
 */
6138
function api_is_user_of_course($course_id, $user_id)
6139
{
6140
    $tbl_course_rel_user = Database::get_main_table(TABLE_MAIN_COURSE_USER);
6141
    $sql = 'SELECT user_id FROM '.$tbl_course_rel_user.'
6142
            WHERE
6143
                c_id ="'.intval($course_id).'" AND
6144
                user_id = "'.intval($user_id).'" AND
6145
                relation_type <> '.COURSE_RELATION_TYPE_RRHH.' ';
6146
    $result = Database::query($sql);
6147
    return Database::num_rows($result) == 1;
6148
}
6149
6150
/**
6151
 * Checks whether the server's operating system is Windows (TM).
6152
 * @return boolean - true if the operating system is Windows, false otherwise
6153
 */
6154
function api_is_windows_os()
6155
{
6156
    if (function_exists('php_uname')) {
6157
        // php_uname() exists as of PHP 4.0.2, according to the documentation.
6158
        // We expect that this function will always work for Chamilo 1.8.x.
6159
        $os = php_uname();
6160
    }
6161
    // The following methods are not needed, but let them stay, just in case.
6162
    elseif (isset($_ENV['OS'])) {
6163
        // Sometimes $_ENV['OS'] may not be present (bugs?)
6164
        $os = $_ENV['OS'];
6165
    } elseif (defined('PHP_OS')) {
6166
        // PHP_OS means on which OS PHP was compiled, this is why
6167
        // using PHP_OS is the last choice for detection.
6168
        $os = PHP_OS;
6169
    } else {
6170
        return false;
6171
    }
6172
    return strtolower(substr((string) $os, 0, 3)) == 'win';
6173
}
6174
6175
/**
6176
 * This function informs whether the sent request is XMLHttpRequest
6177
 */
6178
function api_is_xml_http_request()
6179
{
6180
    return isset($_SERVER['HTTP_X_REQUESTED_WITH']) && strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest';
6181
}
6182
6183
/**
6184
 * This wrapper function has been implemented for avoiding some known problems about the function getimagesize().
6185
 * @link http://php.net/manual/en/function.getimagesize.php
6186
 * @link http://www.dokeos.com/forum/viewtopic.php?t=12345
6187
 * @link http://www.dokeos.com/forum/viewtopic.php?t=16355
6188
 * @return integer
6189
 */
6190
function api_getimagesize($path)
6191
{
6192
    $image = new Image($path);
6193
    return $image->get_image_size();
6194
}
6195
6196
/**
6197
 * This function resizes an image, with preserving its proportions (or aspect ratio).
6198
 * @author Ivan Tcholakov, MAY-2009.
6199
 * @param int $image            System path or URL of the image
6200
 * @param int $target_width     Targeted width
6201
 * @param int $target_height    Targeted height
6202
 * @return array                Calculated new width and height
6203
 */
6204
function api_resize_image($image, $target_width, $target_height)
6205
{
6206
    $image_properties = api_getimagesize($image);
6207
6208
    return api_calculate_image_size(
6209
        $image_properties['width'],
6210
        $image_properties['height'],
6211
        $target_width,
6212
        $target_height
6213
    );
6214
}
6215
6216
/**
6217
 * This function calculates new image size, with preserving image's proportions (or aspect ratio).
6218
 * @author Ivan Tcholakov, MAY-2009.
6219
 * @author The initial idea has been taken from code by Patrick Cool, MAY-2004.
6220
 * @param int $image_width      Initial width
6221
 * @param int $image_height     Initial height
6222
 * @param int $target_width     Targeted width
6223
 * @param int $target_height    Targeted height
6224
 * @return array                Calculated new width and height
6225
 */
6226
function api_calculate_image_size(
6227
    $image_width,
6228
    $image_height,
6229
    $target_width,
6230
    $target_height
6231
) {
6232
    // Only maths is here.
6233
    $result = ['width' => $image_width, 'height' => $image_height];
6234
    if ($image_width <= 0 || $image_height <= 0) {
6235
        return $result;
6236
    }
6237
    $resize_factor_width = $target_width / $image_width;
6238
    $resize_factor_height = $target_height / $image_height;
6239
    $delta_width = $target_width - $image_width * $resize_factor_height;
6240
    $delta_height = $target_height - $image_height * $resize_factor_width;
6241
    if ($delta_width > $delta_height) {
6242
        $result['width'] = ceil($image_width * $resize_factor_height);
6243
        $result['height'] = ceil($image_height * $resize_factor_height);
6244
    } elseif ($delta_width < $delta_height) {
6245
        $result['width'] = ceil($image_width * $resize_factor_width);
6246
        $result['height'] = ceil($image_height * $resize_factor_width);
6247
    } else {
6248
        $result['width'] = ceil($target_width);
6249
        $result['height'] = ceil($target_height);
6250
    }
6251
    return $result;
6252
}
6253
6254
/**
6255
 * Returns a list of Chamilo's tools or
6256
 * checks whether a given identificator is a valid Chamilo's tool.
6257
 * @author Isaac flores paz
6258
 * @param string The tool name to filter
6259
 * @return mixed Filtered string or array
6260
 */
6261
function api_get_tools_lists($my_tool = null)
6262
{
6263
    $tools_list = [
6264
        TOOL_DOCUMENT,
6265
        TOOL_THUMBNAIL,
6266
        TOOL_HOTPOTATOES,
6267
        TOOL_CALENDAR_EVENT,
6268
        TOOL_LINK,
6269
        TOOL_COURSE_DESCRIPTION,
6270
        TOOL_SEARCH,
6271
        TOOL_LEARNPATH,
6272
        TOOL_ANNOUNCEMENT,
6273
        TOOL_FORUM,
6274
        TOOL_THREAD,
6275
        TOOL_POST,
6276
        TOOL_DROPBOX,
6277
        TOOL_QUIZ,
6278
        TOOL_USER,
6279
        TOOL_GROUP,
6280
        TOOL_BLOGS,
6281
        TOOL_CHAT,
6282
        TOOL_STUDENTPUBLICATION,
6283
        TOOL_TRACKING,
6284
        TOOL_HOMEPAGE_LINK,
6285
        TOOL_COURSE_SETTING,
6286
        TOOL_BACKUP,
6287
        TOOL_COPY_COURSE_CONTENT,
6288
        TOOL_RECYCLE_COURSE,
6289
        TOOL_COURSE_HOMEPAGE,
6290
        TOOL_COURSE_RIGHTS_OVERVIEW,
6291
        TOOL_UPLOAD,
6292
        TOOL_COURSE_MAINTENANCE,
6293
        TOOL_SURVEY,
6294
        TOOL_WIKI,
6295
        TOOL_GLOSSARY,
6296
        TOOL_GRADEBOOK,
6297
        TOOL_NOTEBOOK,
6298
        TOOL_ATTENDANCE,
6299
        TOOL_COURSE_PROGRESS,
6300
    ];
6301
    if (empty($my_tool)) {
6302
        return $tools_list;
6303
    }
6304
    return in_array($my_tool, $tools_list) ? $my_tool : '';
6305
}
6306
6307
/**
6308
 * Checks whether we already approved the last version term and condition
6309
 * @param int user id
6310
 * @return bool true if we pass false otherwise
6311
 */
6312
function api_check_term_condition($userId)
6313
{
6314
    if (api_get_setting('allow_terms_conditions') == 'true') {
6315
        // Check if exists terms and conditions
6316
        if (LegalManager::count() == 0) {
6317
            return true;
6318
        }
6319
6320
        $extraFieldValue = new ExtraFieldValue('user');
6321
        $data = $extraFieldValue->get_values_by_handler_and_field_variable(
6322
            $userId,
6323
            'legal_accept'
6324
        );
6325
6326
        if (!empty($data) && isset($data['value']) && !empty($data['value'])) {
6327
            $result = $data['value'];
6328
            $user_conditions = explode(':', $result);
6329
            $version = $user_conditions[0];
6330
            $lang_id = $user_conditions[1];
6331
            $real_version = LegalManager::get_last_version($lang_id);
6332
6333
            return $version >= $real_version;
6334
        }
6335
        return false;
6336
    }
6337
    return false;
6338
}
6339
6340
/**
6341
 * Gets all information of a tool into course
6342
 * @param int The tool id
6343
 * @return array
6344
 */
6345
function api_get_tool_information_by_name($name)
6346
{
6347
    $t_tool = Database::get_course_table(TABLE_TOOL_LIST);
6348
    $course_id = api_get_course_int_id();
6349
    $sql = "SELECT * FROM $t_tool
6350
            WHERE c_id = $course_id  AND name = '".Database::escape_string($name)."' ";
6351
    $rs  = Database::query($sql);
6352
    return Database::fetch_array($rs, 'ASSOC');
6353
}
6354
6355
/**
6356
 * Function used to protect a "global" admin script.
6357
 * The function blocks access when the user has no global platform admin rights.
6358
 * Global admins are the admins that are registered in the main.admin table
6359
 * AND the users who have access to the "principal" portal.
6360
 * That means that there is a record in the main.access_url_rel_user table
6361
 * with his user id and the access_url_id=1
6362
 *
6363
 * @author Julio Montoya
6364
 * @param integer $user_id
6365
 * @return bool
6366
 */
6367
function api_is_global_platform_admin($user_id = null)
6368
{
6369
    $user_id = intval($user_id);
6370
    if (empty($user_id)) {
6371
        $user_id = api_get_user_id();
6372
    }
6373
    if (api_is_platform_admin_by_id($user_id)) {
6374
        $urlList = api_get_access_url_from_user($user_id);
6375
        // The admin is registered in the first "main" site with access_url_id = 1
6376
        if (in_array(1, $urlList)) {
6377
            return true;
6378
        } else {
6379
            return false;
6380
        }
6381
    }
6382
    return false;
6383
}
6384
6385
/**
6386
 * @param int $admin_id_to_check
6387
 * @param int  $my_user_id
6388
 * @param bool $allow_session_admin
6389
 * @return bool
6390
 */
6391
function api_global_admin_can_edit_admin(
6392
    $admin_id_to_check,
6393
    $my_user_id = null,
6394
    $allow_session_admin = false
6395
) {
6396
    if (empty($my_user_id)) {
6397
        $my_user_id = api_get_user_id();
6398
    }
6399
6400
    $iam_a_global_admin = api_is_global_platform_admin($my_user_id);
6401
    $user_is_global_admin = api_is_global_platform_admin($admin_id_to_check);
6402
6403
    if ($iam_a_global_admin) {
6404
        // Global admin can edit everything
6405
        return true;
6406
    } else {
6407
        // If i'm a simple admin
6408
        $is_platform_admin = api_is_platform_admin_by_id($my_user_id);
6409
6410
        if ($allow_session_admin) {
6411
            $is_platform_admin = api_is_platform_admin_by_id($my_user_id) || (api_get_user_status($my_user_id) == SESSIONADMIN);
6412
        }
6413
6414
        if ($is_platform_admin) {
6415
            if ($user_is_global_admin) {
6416
                return false;
6417
            } else {
6418
                return true;
6419
            }
6420
        } else {
6421
            return false;
6422
        }
6423
    }
6424
}
6425
6426
/**
6427
 * @param int $admin_id_to_check
6428
 * @param int  $my_user_id
6429
 * @param bool $allow_session_admin
6430
 * @return boolean|null
6431
 */
6432
function api_protect_super_admin($admin_id_to_check, $my_user_id = null, $allow_session_admin = false)
6433
{
6434
    if (api_global_admin_can_edit_admin($admin_id_to_check, $my_user_id, $allow_session_admin)) {
6435
        return true;
6436
    } else {
6437
        api_not_allowed();
6438
    }
6439
}
6440
6441
/**
6442
 * Function used to protect a global admin script.
6443
 * The function blocks access when the user has no global platform admin rights.
6444
 * See also the api_is_global_platform_admin() function wich defines who's a "global" admin
6445
 *
6446
 * @author Julio Montoya
6447
 */
6448
function api_protect_global_admin_script()
6449
{
6450
    if (!api_is_global_platform_admin()) {
6451
        api_not_allowed();
6452
        return false;
6453
    }
6454
    return true;
6455
}
6456
6457
/**
6458
 * Get active template
6459
 * @param string    theme type (optional: default)
6460
 * @param string    path absolute(abs) or relative(rel) (optional:rel)
6461
 * @return string   actived template path
6462
 */
6463
function api_get_template($path_type = 'rel')
6464
{
6465
    $path_types = ['rel', 'abs'];
6466
    $template_path = '';
6467
    if (in_array($path_type, $path_types)) {
6468
        if ($path_type == 'rel') {
6469
            $template_path = api_get_path(SYS_TEMPLATE_PATH);
6470
        } else {
6471
            $template_path = api_get_path(WEB_TEMPLATE_PATH);
6472
        }
6473
    }
6474
    $actived_theme = 'default';
6475
    if (api_get_setting('active_template')) {
6476
        $actived_theme = api_get_setting('active_template');
6477
    }
6478
    $actived_theme_path = $template_path.$actived_theme.DIRECTORY_SEPARATOR;
6479
    return $actived_theme_path;
6480
}
6481
6482
/**
6483
 * Check browser support for specific file types or features
6484
 * This function checks if the user's browser supports a file format or given
6485
 * feature, or returns the current browser and major version when
6486
 * $format=check_browser. Only a limited number of formats and features are
6487
 * checked by this method. Make sure you check its definition first.
6488
 * @param string $format Can be a file format (extension like svg, webm, ...) or a feature (like autocapitalize, ...)
6489
 *
6490
 * @return bool or return text array if $format=check_browser
6491
 * @author Juan Carlos Raña Trabado
6492
 */
6493
function api_browser_support($format = '')
6494
{
6495
    $browser = new Browser();
6496
    $current_browser = $browser->getBrowser();
6497
    $a_versiontemp = explode('.', $browser->getVersion());
6498
    $current_majorver = $a_versiontemp[0];
6499
6500
    static $result;
6501
6502
    if (isset($result[$format])) {
6503
        return $result[$format];
6504
    }
6505
6506
    // Native svg support
6507
    if ($format == 'svg') {
6508
        if (($current_browser == 'Internet Explorer' && $current_majorver >= 9) ||
6509
            ($current_browser == 'Firefox' && $current_majorver > 1) ||
6510
            ($current_browser == 'Safari' && $current_majorver >= 4) ||
6511
            ($current_browser == 'Chrome' && $current_majorver >= 1) ||
6512
            ($current_browser == 'Opera' && $current_majorver >= 9)
6513
        ) {
6514
            $result[$format] = true;
6515
            return true;
6516
        } else {
6517
            $result[$format] = false;
6518
            return false;
6519
        }
6520
    } elseif ($format == 'pdf') {
6521
        //native pdf support
6522
        if ($current_browser == 'Chrome' && $current_majorver >= 6) {
6523
            $result[$format] = true;
6524
            return true;
6525
        } else {
6526
            $result[$format] = false;
6527
            return false;
6528
        }
6529
    } elseif ($format == 'tif' || $format == 'tiff') {
6530
        //native tif support
6531
        if ($current_browser == 'Safari' && $current_majorver >= 5) {
6532
            $result[$format] = true;
6533
            return true;
6534
        } else {
6535
            $result[$format] = false;
6536
            return false;
6537
        }
6538
    } elseif ($format == 'ogg' || $format == 'ogx' || $format == 'ogv' || $format == 'oga') {
6539
        //native ogg, ogv,oga support
6540
        if (($current_browser == 'Firefox' && $current_majorver >= 3) ||
6541
            ($current_browser == 'Chrome' && $current_majorver >= 3) ||
6542
            ($current_browser == 'Opera' && $current_majorver >= 9)) {
6543
            $result[$format] = true;
6544
            return true;
6545
        } else {
6546
            $result[$format] = false;
6547
            return false;
6548
        }
6549
    } elseif ($format == 'mpg' || $format == 'mpeg') {
6550
        //native mpg support
6551
        if (($current_browser == 'Safari' && $current_majorver >= 5)) {
6552
            $result[$format] = true;
6553
            return true;
6554
        } else {
6555
            $result[$format] = false;
6556
            return false;
6557
        }
6558
    } elseif ($format == 'mp4') {
6559
        //native mp4 support (TODO: Android, iPhone)
6560
        if ($current_browser == 'Android' || $current_browser == 'iPhone') {
6561
            $result[$format] = true;
6562
            return true;
6563
        } else {
6564
            $result[$format] = false;
6565
            return false;
6566
        }
6567
    } elseif ($format == 'mov') {
6568
        //native mov support( TODO:check iPhone)
6569
        if ($current_browser == 'Safari' && $current_majorver >= 5 || $current_browser == 'iPhone') {
6570
            $result[$format] = true;
6571
            return true;
6572
        } else {
6573
            $result[$format] = false;
6574
            return false;
6575
        }
6576
    } elseif ($format == 'avi') {
6577
        //native avi support
6578
        if ($current_browser == 'Safari' && $current_majorver >= 5) {
6579
            $result[$format] = true;
6580
            return true;
6581
        } else {
6582
            $result[$format] = false;
6583
            return false;
6584
        }
6585
    } elseif ($format == 'wmv') {
6586
        //native wmv support
6587
        if ($current_browser == 'Firefox' && $current_majorver >= 4) {
6588
            $result[$format] = true;
6589
            return true;
6590
        } else {
6591
            $result[$format] = false;
6592
            return false;
6593
        }
6594
    } elseif ($format == 'webm') {
6595
        //native webm support (TODO:check IE9, Chrome9, Android)
6596
        if (($current_browser == 'Firefox' && $current_majorver >= 4) ||
6597
            ($current_browser == 'Opera' && $current_majorver >= 9) ||
6598
            ($current_browser == 'Internet Explorer' && $current_majorver >= 9) ||
6599
            ($current_browser == 'Chrome' && $current_majorver >= 9) ||
6600
            $current_browser == 'Android'
6601
        ) {
6602
            $result[$format] = true;
6603
            return true;
6604
        } else {
6605
            $result[$format] = false;
6606
            return false;
6607
        }
6608
    } elseif ($format == 'wav') {
6609
        //native wav support (only some codecs !)
6610
        if (($current_browser == 'Firefox' && $current_majorver >= 4) ||
6611
            ($current_browser == 'Safari' && $current_majorver >= 5) ||
6612
            ($current_browser == 'Opera' && $current_majorver >= 9) ||
6613
            ($current_browser == 'Internet Explorer' && $current_majorver >= 9) ||
6614
            ($current_browser == 'Chrome' && $current_majorver > 9) ||
6615
            $current_browser == 'Android' ||
6616
            $current_browser == 'iPhone'
6617
        ) {
6618
            $result[$format] = true;
6619
            return true;
6620
        } else {
6621
            $result[$format] = false;
6622
            return false;
6623
        }
6624
    } elseif ($format == 'mid' || $format == 'kar') {
6625
        //native midi support (TODO:check Android)
6626
        if ($current_browser == 'Opera' && $current_majorver >= 9 || $current_browser == 'Android') {
6627
            $result[$format] = true;
6628
            return true;
6629
        } else {
6630
            $result[$format] = false;
6631
            return false;
6632
        }
6633
    } elseif ($format == 'wma') {
6634
        //native wma support
6635
        if ($current_browser == 'Firefox' && $current_majorver >= 4) {
6636
            $result[$format] = true;
6637
            return true;
6638
        } else {
6639
            $result[$format] = false;
6640
            return false;
6641
        }
6642
    } elseif ($format == 'au') {
6643
        //native au support
6644
        if ($current_browser == 'Safari' && $current_majorver >= 5) {
6645
            $result[$format] = true;
6646
            return true;
6647
        } else {
6648
            $result[$format] = false;
6649
            return false;
6650
        }
6651
    } elseif ($format == 'mp3') {
6652
        //native mp3 support (TODO:check Android, iPhone)
6653
        if (($current_browser == 'Safari' && $current_majorver >= 5) ||
6654
            ($current_browser == 'Chrome' && $current_majorver >= 6) ||
6655
            ($current_browser == 'Internet Explorer' && $current_majorver >= 9) ||
6656
            $current_browser == 'Android' ||
6657
            $current_browser == 'iPhone' ||
6658
            $current_browser == 'Firefox'
6659
        ) {
6660
            $result[$format] = true;
6661
            return true;
6662
        } else {
6663
            $result[$format] = false;
6664
            return false;
6665
        }
6666
    } elseif ($format == 'autocapitalize') {
6667
        // Help avoiding showing the autocapitalize option if the browser doesn't
6668
        // support it: this attribute is against the HTML5 standard
6669
        if ($current_browser == 'Safari' || $current_browser == 'iPhone') {
6670
            return true;
6671
        } else {
6672
            return false;
6673
        }
6674
    } elseif ($format == "check_browser") {
6675
        $array_check_browser = [$current_browser, $current_majorver];
6676
        return $array_check_browser;
6677
    } else {
6678
        $result[$format] = false;
6679
        return false;
6680
    }
6681
}
6682
6683
/**
6684
 * This function checks if exist path and file browscap.ini
6685
 * In order for this to work, your browscap configuration setting in php.ini
6686
 * must point to the correct location of the browscap.ini file on your system
6687
 * http://php.net/manual/en/function.get-browser.php
6688
 *
6689
 * @return bool
6690
 *
6691
 * @author Juan Carlos Raña Trabado
6692
 */
6693
function api_check_browscap()
6694
{
6695
    $setting = ini_get('browscap');
6696
    if ($setting) {
6697
        $browser = get_browser($_SERVER['HTTP_USER_AGENT'], true);
6698
        if (strpos($setting, 'browscap.ini') && !empty($browser)) {
6699
            return true;
6700
        }
6701
    }
6702
    return false;
6703
}
6704
6705
/**
6706
 * Returns the <script> HTML tag
6707
 */
6708
function api_get_js($file)
6709
{
6710
    return '<script type="text/javascript" src="'.api_get_path(WEB_LIBRARY_PATH).'javascript/'.$file.'"></script>'."\n";
6711
}
6712
6713
/**
6714
 * Returns the <script> HTML tag
6715
 * @return string
6716
 */
6717
function api_get_asset($file)
6718
{
6719
    return '<script type="text/javascript" src="'.api_get_path(WEB_PUBLIC_PATH).'assets/'.$file.'"></script>'."\n";
6720
}
6721
6722
/**
6723
 * Returns the <script> HTML tag
6724
 * @return string
6725
 */
6726
function api_get_css_asset($file, $media = 'screen')
6727
{
6728
    return '<link href="'.api_get_path(WEB_PUBLIC_PATH).'assets/'.$file.'" rel="stylesheet" media="'.$media.'" type="text/css" />'."\n";
6729
}
6730
6731
/**
6732
 * Returns the <link> HTML tag
6733
 * @param string $file
6734
 */
6735
function api_get_css($file, $media = 'screen')
6736
{
6737
    return '<link href="'.$file.'" rel="stylesheet" media="'.$media.'" type="text/css" />'."\n";
6738
}
6739
6740
/**
6741
 * Returns the js header to include the jquery library
6742
 */
6743
function api_get_jquery_js()
6744
{
6745
    return api_get_asset('jquery/dist/jquery.min.js');
6746
}
6747
6748
/**
6749
 * Returns the jquery path
6750
 * @return string
6751
 */
6752
function api_get_jquery_web_path()
6753
{
6754
    return api_get_path(WEB_PUBLIC_PATH).'assets/jquery/dist/jquery.min.js';
6755
}
6756
6757
/**
6758
 * @return string
6759
 */
6760
function api_get_jquery_ui_js_web_path()
6761
{
6762
    return api_get_path(WEB_PUBLIC_PATH).'assets/jquery-ui/jquery-ui.min.js';
6763
}
6764
6765
/**
6766
 * @return string
6767
 */
6768
function api_get_jquery_ui_css_web_path()
6769
{
6770
    return api_get_path(WEB_PUBLIC_PATH).'assets/jquery-ui/themes/smoothness/jquery-ui.min.css';
6771
}
6772
6773
/**
6774
 * Returns the jquery-ui library js headers
6775
 * @param   bool    add the jqgrid library
6776
 * @return  string  html tags
6777
 *
6778
 */
6779
function api_get_jquery_ui_js($include_jqgrid = false)
6780
{
6781
    $libraries = [];
6782
    if ($include_jqgrid) {
6783
        $libraries[] = 'jqgrid';
6784
    }
6785
    return api_get_jquery_libraries_js($libraries);
6786
}
6787
6788
function api_get_jqgrid_js()
6789
{
6790
    return api_get_jquery_libraries_js(['jqgrid']);
6791
}
6792
6793
/**
6794
 * Returns the jquery library js and css headers
6795
 *
6796
 * @param   array   list of jquery libraries supported jquery-ui, jqgrid
6797
 * @param   bool    add the jquery library
6798
 * @return  string  html tags
6799
 *
6800
 */
6801
function api_get_jquery_libraries_js($libraries)
6802
{
6803
    $js = '';
6804
    $js_path = api_get_path(WEB_LIBRARY_PATH).'javascript/';
6805
6806
    //jqgrid js and css
6807
    if (in_array('jqgrid', $libraries)) {
6808
        $languaje = 'en';
6809
        $platform_isocode = strtolower(api_get_language_isocode());
6810
6811
        //languages supported by jqgrid see files in main/inc/lib/javascript/jqgrid/js/i18n
6812
        $jqgrid_langs = [
6813
            'bg', 'bg1251', 'cat', 'cn', 'cs', 'da', 'de', 'el', 'en', 'es', 'fa', 'fi', 'fr', 'gl', 'he', 'hu', 'is', 'it', 'ja', 'nl', 'no', 'pl', 'pt-br', 'pt', 'ro', 'ru', 'sk', 'sr', 'sv', 'tr', 'ua'
6814
        ];
6815
6816
        if (in_array($platform_isocode, $jqgrid_langs)) {
6817
            $languaje = $platform_isocode;
6818
        }
6819
        //$js .= '<link rel="stylesheet" href="'.$js_path.'jqgrid/css/ui.jqgrid.css" type="text/css">';
6820
        $js .= api_get_css($js_path.'jqgrid/css/ui.jqgrid.css');
6821
        $js .= api_get_js('jqgrid/js/i18n/grid.locale-'.$languaje.'.js');
6822
        $js .= api_get_js('jqgrid/js/jquery.jqGrid.min.js');
6823
    }
6824
6825
    //Document multiple upload funcionality
6826
    if (in_array('jquery-uploadzs', $libraries)) {
6827
        $js .= api_get_asset('blueimp-load-image/js/load-image.all.min.js');
6828
        $js .= api_get_asset('blueimp-canvas-to-blob/js/canvas-to-blob.min.js');
6829
        $js .= api_get_asset('jquery-file-upload/js/jquery.iframe-transport.js');
6830
        $js .= api_get_asset('jquery-file-upload/js/jquery.fileupload.js');
6831
        $js .= api_get_asset('jquery-file-upload/js/jquery.fileupload-process.js');
6832
        $js .= api_get_asset('jquery-file-upload/js/jquery.fileupload-image.js');
6833
        $js .= api_get_asset('jquery-file-upload/js/jquery.fileupload-audio.js');
6834
        $js .= api_get_asset('jquery-file-upload/js/jquery.fileupload-video.js');
6835
        $js .= api_get_asset('jquery-file-upload/js/jquery.fileupload-validate.js');
6836
6837
        $js .= api_get_css(api_get_path(WEB_PUBLIC_PATH).'assets/jquery-file-upload/css/jquery.fileupload.css');
6838
        $js .= api_get_css(api_get_path(WEB_PUBLIC_PATH).'assets/jquery-file-upload/css/jquery.fileupload-ui.css');
6839
    }
6840
6841
    // jquery datepicker
6842
    if (in_array('datepicker', $libraries)) {
6843
        $languaje = 'en-GB';
6844
        $platform_isocode = strtolower(api_get_language_isocode());
6845
6846
        // languages supported by jqgrid see files in main/inc/lib/javascript/jqgrid/js/i18n
6847
        $datapicker_langs = [
6848
            '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'
6849
        ];
6850
        if (in_array($platform_isocode, $datapicker_langs)) {
6851
            $languaje = $platform_isocode;
6852
        }
6853
6854
        $js .= api_get_js('jquery-ui/jquery-ui-i18n.min.js');
6855
        $script = '<script>
6856
        $(function(){
6857
            $.datepicker.setDefaults($.datepicker.regional["'.$languaje.'"]);
6858
            $.datepicker.regional["local"] = $.datepicker.regional["'.$languaje.'"];
6859
        });
6860
        </script>
6861
        ';
6862
        $js .= $script;
6863
    }
6864
    return $js;
6865
}
6866
6867
/**
6868
 * Returns the course's URL
6869
 *
6870
 * This function relies on api_get_course_info()
6871
 * @param   string  The course code - optional (takes it from session if not given)
6872
 * @param   int     The session id  - optional (takes it from session if not given)
6873
 * @param integer $session_id
6874
 * @return  string|null   The URL of the course or null if something does not work
6875
 * @author  Julio Montoya <[email protected]>
6876
 */
6877
function api_get_course_url($course_code = null, $session_id = null)
6878
{
6879
    if (empty($course_code)) {
6880
        $course_info = api_get_course_info();
6881
    } else {
6882
        $course_info = api_get_course_info($course_code);
6883
    }
6884
    if (empty($session_id)) {
6885
        $session_url = '?id_session='.api_get_session_id();
6886
    } else {
6887
        $session_url = '?id_session='.intval($session_id);
6888
    }
6889
    /*
6890
    if (empty($group_id)) {
6891
        $group_url = '&gidReq='.api_get_group_id();
6892
    } else {
6893
        $group_url = '&gidReq='.intval($group_id);
6894
    }*/
6895
    if (!empty($course_info['path'])) {
6896
        return api_get_path(WEB_COURSE_PATH).$course_info['path'].'/index.php'.$session_url;
6897
    }
6898
    return null;
6899
}
6900
6901
/**
6902
 *
6903
 * Check if the current portal has the $_configuration['multiple_access_urls'] parameter on
6904
 * @return bool true if multi site is enabled
6905
 *
6906
 **/
6907
function api_get_multiple_access_url()
6908
{
6909
    global $_configuration;
6910
    if (isset($_configuration['multiple_access_urls']) && $_configuration['multiple_access_urls']) {
6911
        return true;
6912
    }
6913
    return false;
6914
}
6915
6916
/**
6917
 * @return bool
6918
 */
6919
function api_is_multiple_url_enabled()
6920
{
6921
    return api_get_multiple_access_url();
6922
}
6923
6924
/**
6925
 * Returns a md5 unique id
6926
 * @todo add more parameters
6927
 */
6928
function api_get_unique_id()
6929
{
6930
    $id = md5(time().uniqid().api_get_user_id().api_get_course_id().api_get_session_id());
6931
    return $id;
6932
}
6933
6934
/**
6935
 * Get home path
6936
 * @return string
6937
 */
6938
function api_get_home_path()
6939
{
6940
    // FIX : Start the routing determination from central path definition
6941
    $home = api_get_path(SYS_HOME_PATH);
6942
    if (api_get_multiple_access_url()) {
6943
        $access_url_id = api_get_current_access_url_id();
6944
        $url_info = api_get_access_url($access_url_id);
6945
        $url = api_remove_trailing_slash(preg_replace('/https?:\/\//i', '', $url_info['url']));
6946
        $clean_url = api_replace_dangerous_char($url);
6947
        $clean_url = str_replace('/', '-', $clean_url);
6948
        $clean_url .= '/';
6949
        if ($clean_url != 'localhost/') {
6950
            // means that the multiple URL was not well configured we don't rename the $home variable
6951
            return "{$home}{$clean_url}";
6952
        }
6953
    }
6954
6955
    return $home;
6956
}
6957
6958
/**
6959
 *
6960
 * @param int Course id
6961
 * @param int tool id: TOOL_QUIZ, TOOL_FORUM, TOOL_STUDENTPUBLICATION, TOOL_LEARNPATH
6962
 * @param int the item id (tool id, exercise id, lp id)
6963
 * @return bool
6964
 */
6965
function api_resource_is_locked_by_gradebook($item_id, $link_type, $course_code = null)
6966
{
6967
    if (api_is_platform_admin()) {
6968
        return false;
6969
    }
6970
    if (api_get_setting('gradebook_locking_enabled') == 'true') {
6971
        if (empty($course_code)) {
6972
            $course_code = api_get_course_id();
6973
        }
6974
        $table = Database::get_main_table(TABLE_MAIN_GRADEBOOK_LINK);
6975
        $item_id = intval($item_id);
6976
        $link_type = intval($link_type);
6977
        $course_code = Database::escape_string($course_code);
6978
        $sql = "SELECT locked FROM $table
6979
                WHERE locked = 1 AND ref_id = $item_id AND type = $link_type AND course_code = '$course_code' ";
6980
        $result = Database::query($sql);
6981
        if (Database::num_rows($result)) {
6982
            return true;
6983
        }
6984
    }
6985
    return false;
6986
}
6987
6988
/**
6989
 * Blocks a page if the item was added in a gradebook
6990
 *
6991
 * @param int       exercise id, work id, thread id,
6992
 * @param int       LINK_EXERCISE, LINK_STUDENTPUBLICATION, LINK_LEARNPATH LINK_FORUM_THREAD, LINK_ATTENDANCE
6993
 * see gradebook/lib/be/linkfactory
6994
 * @param string    course code
6995
 * @return false|null
6996
 */
6997
function api_block_course_item_locked_by_gradebook($item_id, $link_type, $course_code = null)
6998
{
6999
    if (api_is_platform_admin()) {
7000
        return false;
7001
    }
7002
7003
    if (api_resource_is_locked_by_gradebook($item_id, $link_type, $course_code)) {
7004
        $message = Display::return_message(get_lang('ResourceLockedByGradebook'), 'warning');
7005
        api_not_allowed(true, $message);
7006
    }
7007
}
7008
7009
/**
7010
 * Checks the PHP version installed is enough to run Chamilo
7011
 * @param string Include path (used to load the error page)
7012
 * @return void
7013
 */
7014
function api_check_php_version($my_inc_path = null)
7015
{
7016
    if (!function_exists('version_compare') || version_compare(phpversion(), REQUIRED_PHP_VERSION, '<')) {
7017
        $global_error_code = 1;
7018
        // Incorrect PHP version
7019
        $global_page = $my_inc_path.'global_error_message.inc.php';
7020
        if (file_exists($global_page)) {
7021
            require $global_page;
7022
        }
7023
        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...
7024
    }
7025
}
7026
7027
/**
7028
 * Checks whether the Archive directory is present and writeable. If not,
7029
 * prints a warning message.
7030
 */
7031
function api_check_archive_dir()
7032
{
7033
    if (is_dir(api_get_path(SYS_ARCHIVE_PATH)) && !is_writable(api_get_path(SYS_ARCHIVE_PATH))) {
7034
        $message = Display::return_message(get_lang('ArchivesDirectoryNotWriteableContactAdmin'), 'warning');
7035
        api_not_allowed(true, $message);
7036
    }
7037
}
7038
7039
/**
7040
 * Returns an array of global configuration settings which should be ignored
7041
 * when printing the configuration settings screens
7042
 * @return array Array of strings, each identifying one of the excluded settings
7043
 */
7044
function api_get_locked_settings()
7045
{
7046
    return [
7047
        'permanently_remove_deleted_files',
7048
        'account_valid_duration',
7049
        'service_ppt2lp',
7050
        'wcag_anysurfer_public_pages',
7051
        'upload_extensions_list_type',
7052
        'upload_extensions_blacklist',
7053
        'upload_extensions_whitelist',
7054
        'upload_extensions_skip',
7055
        'upload_extensions_replace_by',
7056
        'hide_dltt_markup',
7057
        'split_users_upload_directory',
7058
        'permissions_for_new_directories',
7059
        'permissions_for_new_files',
7060
        'platform_charset',
7061
        'ldap_description',
7062
        'cas_activate',
7063
        'cas_server',
7064
        'cas_server_uri',
7065
        'cas_port',
7066
        'cas_protocol',
7067
        'cas_add_user_activate',
7068
        'update_user_info_cas_with_ldap',
7069
        'languagePriority1',
7070
        'languagePriority2',
7071
        'languagePriority3',
7072
        'languagePriority4',
7073
        'login_is_email',
7074
        'chamilo_database_version'
7075
    ];
7076
}
7077
7078
/**
7079
 * Checks if the user is corrently logged in. Returns the user ID if he is, or
7080
 * false if he isn't. If the user ID is given and is an integer, then the same
7081
 * ID is simply returned
7082
 * @param  integer User ID
7083
 * @return boolean Integer User ID is logged in, or false otherwise
7084
 */
7085
function api_user_is_login($user_id = null)
7086
{
7087
    $user_id = empty($user_id) ? api_get_user_id() : intval($user_id);
7088
    return $user_id && !api_is_anonymous();
7089
}
7090
7091
/**
7092
 * Guess the real ip for register in the database, even in reverse proxy cases.
7093
 * To be recognized, the IP has to be found in either $_SERVER['REMOTE_ADDR'] or
7094
 * in $_SERVER['HTTP_X_FORWARDED_FOR'], which is in common use with rproxies.
7095
 * @return string the user's real ip (unsafe - escape it before inserting to db)
7096
 * @author Jorge Frisancho Jibaja <[email protected]>, USIL - Some changes to allow the use of real IP using reverse proxy
7097
 * @version CEV CHANGE 24APR2012
7098
 */
7099
function api_get_real_ip()
7100
{
7101
    // Guess the IP if behind a reverse proxy
7102
    global $debug;
7103
    $ip = trim($_SERVER['REMOTE_ADDR']);
7104
    if (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) {
7105
        if (preg_match('/,/', $_SERVER['HTTP_X_FORWARDED_FOR'])) {
7106
            @list($ip1, $ip2) = @explode(',', $_SERVER['HTTP_X_FORWARDED_FOR']);
7107
        } else {
7108
            $ip1 = $_SERVER['HTTP_X_FORWARDED_FOR'];
7109
        }
7110
        $ip = trim($ip1);
7111
    }
7112
    if (!empty($debug)) {
7113
        error_log('Real IP: '.$ip);
7114
    }
7115
    return $ip;
7116
}
7117
7118
/**
7119
 * Checks whether an IP is included inside an IP range
7120
 * @param string IP address
7121
 * @param string IP range
7122
 * @param string $ip
7123
 * @return bool True if IP is in the range, false otherwise
7124
 * @author claudiu at cnixs dot com  on http://www.php.net/manual/fr/ref.network.php#55230
7125
 * @author Yannick Warnier for improvements and managment of multiple ranges
7126
 * @todo check for IPv6 support
7127
 */
7128
function api_check_ip_in_range($ip, $range)
7129
{
7130
    if (empty($ip) or empty($range)) {
7131
        return false;
7132
    }
7133
    $ip_ip = ip2long($ip);
7134
    // divide range param into array of elements
7135
    if (strpos($range, ',') !== false) {
7136
        $ranges = explode(',', $range);
7137
    } else {
7138
        $ranges = [$range];
7139
    }
7140
    foreach ($ranges as $range) {
7141
        $range = trim($range);
7142
        if (empty($range)) {
7143
            continue;
7144
        }
7145
        if (strpos($range, '/') === false) {
7146
            if (strcmp($ip, $range) === 0) {
7147
                return true; // there is a direct IP match, return OK
7148
            }
7149
            continue; //otherwise, get to the next range
7150
        }
7151
        // the range contains a "/", so analyse completely
7152
        list($net, $mask) = explode("/", $range);
7153
7154
        $ip_net = ip2long($net);
7155
        // mask binary magic
7156
        $ip_mask = ~((1 << (32 - $mask)) - 1);
7157
7158
        $ip_ip_net = $ip_ip & $ip_mask;
7159
        if ($ip_ip_net == $ip_net) {
7160
            return true;
7161
        }
7162
    }
7163
7164
    return false;
7165
}
7166
7167
function api_check_user_access_to_legal($course_visibility)
7168
{
7169
    $course_visibility_list = [COURSE_VISIBILITY_OPEN_WORLD, COURSE_VISIBILITY_OPEN_PLATFORM];
7170
    return in_array($course_visibility, $course_visibility_list) || api_is_drh();
7171
}
7172
7173
/**
7174
 * Checks if the global chat is enabled or not
7175
 *
7176
 * @return bool
7177
 */
7178
function api_is_global_chat_enabled()
7179
{
7180
    return
7181
        !api_is_anonymous() &&
7182
        api_get_setting('allow_global_chat') == 'true' &&
7183
        api_get_setting('allow_social_tool') == 'true';
7184
}
7185
7186
/**
7187
 * @todo Fix tool_visible_by_default_at_creation labels
7188
 * @todo Add sessionId parameter to avoid using context
7189
 *
7190
 * @param int $item_id
7191
 * @param int $tool_id
7192
 * @param int $group_id id
7193
 * @param array $courseInfo
7194
 * @param int $sessionId
7195
 * @param int $userId
7196
 */
7197
function api_set_default_visibility(
7198
    $item_id,
7199
    $tool_id,
7200
    $group_id = 0,
7201
    $courseInfo = [],
7202
    $sessionId = 0,
7203
    $userId = 0
7204
) {
7205
    $courseInfo = empty($courseInfo) ? api_get_course_info() : $courseInfo;
7206
    $courseId = $courseInfo['real_id'];
7207
    $courseCode = $courseInfo['code'];
7208
    $sessionId = empty($sessionId) ? api_get_session_id() : $sessionId;
7209
    $userId = empty($userId) ? api_get_user_id() : $userId;
7210
7211
    if (empty($group_id)) {
7212
        $group_id = api_get_group_id();
7213
    }
7214
7215
    $groupInfo = GroupManager::get_group_properties($group_id);
7216
    $original_tool_id = $tool_id;
7217
7218
    switch ($tool_id) {
7219
        case TOOL_LINK:
7220
        case TOOL_LINK_CATEGORY:
7221
            $tool_id = 'links';
7222
            break;
7223
        case TOOL_DOCUMENT:
7224
            $tool_id = 'documents';
7225
            break;
7226
        case TOOL_LEARNPATH:
7227
            $tool_id = 'learning';
7228
            break;
7229
        case TOOL_ANNOUNCEMENT:
7230
            $tool_id = 'announcements';
7231
            break;
7232
        case TOOL_FORUM:
7233
        case TOOL_FORUM_CATEGORY:
7234
        case TOOL_FORUM_THREAD:
7235
            $tool_id = 'forums';
7236
            break;
7237
        case TOOL_QUIZ:
7238
            $tool_id = 'quiz';
7239
            break;
7240
    }
7241
    $setting = api_get_setting('tool_visible_by_default_at_creation');
7242
7243
    if (isset($setting[$tool_id])) {
7244
        $visibility = 'invisible';
7245
        if ($setting[$tool_id] == 'true') {
7246
            $visibility = 'visible';
7247
        }
7248
7249
        // Read the portal and course default visibility
7250
        if ($tool_id == 'documents') {
7251
            $visibility = DocumentManager::getDocumentDefaultVisibility($courseCode);
7252
        }
7253
7254
        api_item_property_update(
7255
            $courseInfo,
7256
            $original_tool_id,
7257
            $item_id,
7258
            $visibility,
7259
            $userId,
7260
            $groupInfo,
7261
            null,
7262
            null,
7263
            null,
7264
            $sessionId
7265
        );
7266
7267
        // Fixes default visibility for tests
7268
        switch ($original_tool_id) {
7269
            case TOOL_QUIZ:
7270
                if (empty($sessionId)) {
7271
                    $objExerciseTmp = new Exercise($courseId);
7272
                    $objExerciseTmp->read($item_id);
7273
                    if ($visibility == 'visible') {
7274
                        $objExerciseTmp->enable();
7275
                        $objExerciseTmp->save();
7276
                    } else {
7277
                        $objExerciseTmp->disable();
7278
                        $objExerciseTmp->save();
7279
                    }
7280
                }
7281
                break;
7282
        }
7283
    }
7284
}
7285
7286
/**
7287
 * @return string
7288
 */
7289
function api_get_security_key()
7290
{
7291
    return api_get_configuration_value('security_key');
7292
}
7293
7294
/**
7295
 * @param int $user_id
7296
 * @param int $courseId
7297
 * @param int $session_id
7298
 * @return array
7299
 */
7300
function api_detect_user_roles($user_id, $courseId, $session_id = 0)
7301
{
7302
    $user_roles = [];
7303
    $courseInfo = api_get_course_info_by_id($courseId);
7304
    $course_code = $courseInfo['code'];
7305
7306
    $url_id = api_get_current_access_url_id();
7307
    if (api_is_platform_admin_by_id($user_id, $url_id)) {
7308
        $user_roles[] = PLATFORM_ADMIN;
7309
    }
7310
7311
    /*if (api_is_drh()) {
7312
        $user_roles[] = DRH;
7313
    }*/
7314
7315
    if (!empty($session_id)) {
7316
        if (SessionManager::user_is_general_coach($user_id, $session_id)) {
7317
            $user_roles[] = SESSION_GENERAL_COACH;
7318
        }
7319
    }
7320
7321
    if (!empty($course_code)) {
7322
        if (empty($session_id)) {
7323
            if (CourseManager::is_course_teacher($user_id, $course_code)) {
7324
                $user_roles[] = COURSEMANAGER;
7325
            }
7326
            if (CourseManager::get_tutor_in_course_status($user_id, $courseInfo['real_id'])) {
7327
                $user_roles[] = COURSE_TUTOR;
7328
            }
7329
7330
            if (CourseManager::is_user_subscribed_in_course($user_id, $course_code)) {
7331
                $user_roles[] = COURSE_STUDENT;
7332
            }
7333
        } else {
7334
            $user_status_in_session = SessionManager::get_user_status_in_course_session(
7335
                $user_id,
7336
                $courseId,
7337
                $session_id
7338
            );
7339
7340
            if (!empty($user_status_in_session)) {
7341
                if ($user_status_in_session == 0) {
7342
                    $user_roles[] = SESSION_STUDENT;
7343
                }
7344
                if ($user_status_in_session == 2) {
7345
                    $user_roles[] = SESSION_COURSE_COACH;
7346
                }
7347
            }
7348
7349
            /*if (api_is_course_session_coach($user_id, $course_code, $session_id)) {
7350
               $user_roles[] = SESSION_COURSE_COACH;
7351
            }*/
7352
        }
7353
    }
7354
    return $user_roles;
7355
}
7356
7357
/**
7358
 * @param int $courseId
7359
 * @param int $session_id
7360
 * @return bool
7361
 */
7362
function api_coach_can_edit_view_results($courseId = null, $session_id = null)
7363
{
7364
    if (api_is_platform_admin()) {
7365
        return true;
7366
    }
7367
7368
    $user_id = api_get_user_id();
7369
7370
    if (empty($courseId)) {
7371
        $courseId = api_get_course_int_id();
7372
    }
7373
7374
    if (empty($session_id)) {
7375
        $session_id = api_get_session_id();
7376
    }
7377
7378
    $roles = api_detect_user_roles($user_id, $courseId, $session_id);
7379
7380
    if (in_array(SESSION_COURSE_COACH, $roles)) {
7381
        //return api_get_setting('session_tutor_reports_visibility') == 'true';
7382
        return true;
7383
    } else {
7384
        if (in_array(COURSEMANAGER, $roles)) {
7385
            return true;
7386
        }
7387
        return false;
7388
    }
7389
}
7390
7391
/**
7392
 * @param string $file
7393
 * @return string
7394
 */
7395
function api_get_js_simple($file)
7396
{
7397
    return '<script type="text/javascript" src="'.$file.'"></script>'."\n";
7398
}
7399
7400
function api_set_settings_and_plugins()
7401
{
7402
    global $_configuration;
7403
    $_setting = [];
7404
    $_plugins = [];
7405
7406
    // access_url == 1 is the default chamilo location
7407
    $settings_by_access_list = [];
7408
    $access_url_id = api_get_current_access_url_id();
7409
    if ($access_url_id != 1) {
7410
        $url_info = api_get_access_url($_configuration['access_url']);
7411
        if ($url_info['active'] == 1) {
7412
            $settings_by_access = & api_get_settings(null, 'list', $_configuration['access_url'], 1);
7413
            foreach ($settings_by_access as & $row) {
7414
                if (empty($row['variable'])) {
7415
                    $row['variable'] = 0;
7416
                }
7417
                if (empty($row['subkey'])) {
7418
                    $row['subkey'] = 0;
7419
                }
7420
                if (empty($row['category'])) {
7421
                    $row['category'] = 0;
7422
                }
7423
                $settings_by_access_list[$row['variable']][$row['subkey']][$row['category']] = $row;
7424
            }
7425
        }
7426
    }
7427
7428
    $result = api_get_settings(null, 'list', 1);
7429
7430
    foreach ($result as & $row) {
7431
        if ($access_url_id != 1) {
7432
            if ($url_info['active'] == 1) {
7433
                $var = empty($row['variable']) ? 0 : $row['variable'];
7434
                $subkey = empty($row['subkey']) ? 0 : $row['subkey'];
7435
                $category = empty($row['category']) ? 0 : $row['category'];
7436
            }
7437
7438
            if ($row['access_url_changeable'] == 1 && $url_info['active'] == 1) {
7439
                if (isset($settings_by_access_list[$var]) &&
7440
                    $settings_by_access_list[$var][$subkey][$category]['selected_value'] != '') {
7441
                    if ($row['subkey'] == null) {
7442
                        $_setting[$row['variable']] = $settings_by_access_list[$var][$subkey][$category]['selected_value'];
7443
                    } else {
7444
                        $_setting[$row['variable']][$row['subkey']] = $settings_by_access_list[$var][$subkey][$category]['selected_value'];
7445
                    }
7446
                } else {
7447
                    if ($row['subkey'] == null) {
7448
                        $_setting[$row['variable']] = $row['selected_value'];
7449
                    } else {
7450
                        $_setting[$row['variable']][$row['subkey']] = $row['selected_value'];
7451
                    }
7452
                }
7453
            } else {
7454
                if ($row['subkey'] == null) {
7455
                    $_setting[$row['variable']] = $row['selected_value'];
7456
                } else {
7457
                    $_setting[$row['variable']][$row['subkey']] = $row['selected_value'];
7458
                }
7459
            }
7460
        } else {
7461
            if ($row['subkey'] == null) {
7462
                $_setting[$row['variable']] = $row['selected_value'];
7463
            } else {
7464
                $_setting[$row['variable']][$row['subkey']] = $row['selected_value'];
7465
            }
7466
        }
7467
    }
7468
7469
    $result = api_get_settings('Plugins', 'list', $access_url_id);
7470
    $_plugins = [];
7471
    foreach ($result as & $row) {
7472
        $key = & $row['variable'];
7473
        if (is_string($_setting[$key])) {
7474
            $_setting[$key] = [];
7475
        }
7476
        $_setting[$key][] = $row['selected_value'];
7477
        $_plugins[$key][] = $row['selected_value'];
7478
    }
7479
7480
    $_SESSION['_setting'] = $_setting;
7481
    $_SESSION['_plugins'] = $_plugins;
7482
}
7483
7484
/**
7485
 * Tries to set memory limit, if authorized and new limit is higher than current
7486
 * @param string $mem New memory limit
7487
 * @return bool True on success, false on failure or current is higher than suggested
7488
 * @assert (null) === false
7489
 * @assert (-1) === false
7490
 * @assert (0) === true
7491
 * @assert ('1G') === true
7492
 */
7493
function api_set_memory_limit($mem)
7494
{
7495
    //if ini_set() not available, this function is useless
7496
    if (!function_exists('ini_set') || is_null($mem) || $mem == -1) {
7497
        return false;
7498
    }
7499
7500
    $memory_limit = ini_get('memory_limit');
7501
    if (api_get_bytes_memory_limit($mem) > api_get_bytes_memory_limit($memory_limit)) {
7502
        ini_set('memory_limit', $mem);
7503
        return true;
7504
    }
7505
    return false;
7506
}
7507
7508
/**
7509
 * Gets memory limit in bytes
7510
 * @param string The memory size (128M, 1G, 1000K, etc)
7511
 * @return int
7512
 * @assert (null) === false
7513
 * @assert ('1t')  === 1099511627776
7514
 * @assert ('1g')  === 1073741824
7515
 * @assert ('1m')  === 1048576
7516
 * @assert ('100k') === 102400
7517
 */
7518
function api_get_bytes_memory_limit($mem)
7519
{
7520
    $size = strtolower(substr($mem, -1));
7521
7522
    switch ($size) {
7523
        case 't':
7524
            $mem = intval(substr($mem, -1)) * 1024 * 1024 * 1024 * 1024;
7525
            break;
7526
        case 'g':
7527
            $mem = intval(substr($mem, 0, -1)) * 1024 * 1024 * 1024;
7528
            break;
7529
        case 'm':
7530
            $mem = intval(substr($mem, 0, -1)) * 1024 * 1024;
7531
            break;
7532
        case 'k':
7533
            $mem = intval(substr($mem, 0, -1)) * 1024;
7534
            break;
7535
        default:
7536
            // we assume it's integer only
7537
            $mem = intval($mem);
7538
            break;
7539
    }
7540
    return $mem;
7541
}
7542
7543
/**
7544
 * Finds all the information about a user from username instead of user id
7545
 *
7546
 * @param string $officialCode
7547
 * @return array $user_info user_id, lastname, firstname, username, email, ...
7548
 * @author Yannick Warnier <[email protected]>
7549
 */
7550
function api_get_user_info_from_official_code($officialCode)
7551
{
7552
    if (empty($officialCode)) {
7553
        return false;
7554
    }
7555
    $sql = "SELECT * FROM ".Database::get_main_table(TABLE_MAIN_USER)."
7556
            WHERE official_code ='".Database::escape_string($officialCode)."'";
7557
    $result = Database::query($sql);
7558
    if (Database::num_rows($result) > 0) {
7559
        $result_array = Database::fetch_array($result);
7560
        return _api_format_user($result_array);
7561
    }
7562
    return false;
7563
}
7564
7565
/**
7566
 * @param string $usernameInputId
7567
 * @param string $passwordInputId
7568
 * @return null|string
7569
 */
7570
function api_get_password_checker_js($usernameInputId, $passwordInputId)
7571
{
7572
    $checkPass = api_get_setting('allow_strength_pass_checker');
7573
    $useStrengthPassChecker = $checkPass === 'true';
7574
7575
    if ($useStrengthPassChecker === false) {
7576
        return null;
7577
    }
7578
7579
    $translations = [
7580
        'wordLength' => get_lang('PasswordIsTooShort'),
7581
        'wordNotEmail' => get_lang('YourPasswordCannotBeTheSameAsYourEmail'),
7582
        'wordSimilarToUsername' => get_lang('YourPasswordCannotContainYourUsername'),
7583
        'wordTwoCharacterClasses' => get_lang('WordTwoCharacterClasses'),
7584
        'wordRepetitions' => get_lang('TooManyRepetitions'),
7585
        'wordSequences' => get_lang('YourPasswordContainsSequences'),
7586
        'errorList' => get_lang('ErrorsFound'),
7587
        'veryWeak' => get_lang('PasswordVeryWeak'),
7588
        'weak' => get_lang('PasswordWeak'),
7589
        'normal' => get_lang('PasswordNormal'),
7590
        'medium' => get_lang('PasswordMedium'),
7591
        'strong' => get_lang('PasswordStrong'),
7592
        'veryStrong' => get_lang('PasswordVeryStrong')
7593
    ];
7594
7595
    $js = api_get_asset('pwstrength-bootstrap/dist/pwstrength-bootstrap.min.js');
7596
    $js .= "<script>    
7597
    var errorMessages = {
7598
        password_to_short : \"" . get_lang('PasswordIsTooShort')."\",
7599
        same_as_username : \"".get_lang('YourPasswordCannotBeTheSameAsYourUsername')."\"
7600
    };
7601
7602
    $(document).ready(function() {
7603
        var lang = ".json_encode($translations).";     
7604
        var options = {        
7605
            onLoad : function () {
7606
                //$('#messages').text('Start typing password');
7607
            },
7608
            onKeyUp: function (evt) {
7609
                $(evt.target).pwstrength('outputErrorList');
7610
            },
7611
            errorMessages : errorMessages,
7612
            viewports: {
7613
                progress: '#password_progress',
7614
                verdict: '#password-verdict',
7615
                errors: '#password-errors'
7616
            },
7617
            usernameField: '$usernameInputId'
7618
        };
7619
        options.i18n = {
7620
            t: function (key) {
7621
                var result = lang[key];
7622
                return result === key ? '' : result; // This assumes you return the                
7623
            }
7624
        };
7625
        $('".$passwordInputId."').pwstrength(options);
7626
    });
7627
    </script>";
7628
7629
    return $js;
7630
}
7631
7632
/**
7633
 * create an user extra field called 'captcha_blocked_until_date'
7634
 * @param string $username
7635
 * @return bool
7636
 */
7637
function api_block_account_captcha($username)
7638
{
7639
    $userInfo = api_get_user_info_from_username($username);
7640
    if (empty($userInfo)) {
7641
        return false;
7642
    }
7643
    $minutesToBlock = api_get_setting('captcha_time_to_block');
7644
    $time = time() + $minutesToBlock * 60;
7645
    UserManager::update_extra_field_value(
7646
        $userInfo['user_id'],
7647
        'captcha_blocked_until_date',
7648
        api_get_utc_datetime($time)
7649
    );
7650
    return true;
7651
}
7652
7653
/**
7654
 * @param string $username
7655
 * @return bool
7656
 */
7657
function api_clean_account_captcha($username)
7658
{
7659
    $userInfo = api_get_user_info_from_username($username);
7660
    if (empty($userInfo)) {
7661
        return false;
7662
    }
7663
    Session::erase('loginFailedCount');
7664
    UserManager::update_extra_field_value(
7665
        $userInfo['user_id'],
7666
        'captcha_blocked_until_date',
7667
        null
7668
    );
7669
    return true;
7670
}
7671
7672
/**
7673
 * @param string $username
7674
 * @return bool
7675
 */
7676
function api_get_user_blocked_by_captcha($username)
7677
{
7678
    $userInfo = api_get_user_info_from_username($username);
7679
    if (empty($userInfo)) {
7680
        return false;
7681
    }
7682
    $data = UserManager::get_extra_user_data_by_field(
7683
        $userInfo['user_id'],
7684
        'captcha_blocked_until_date'
7685
    );
7686
    if (isset($data) && isset($data['captcha_blocked_until_date'])) {
7687
        return $data['captcha_blocked_until_date'];
7688
    }
7689
    return false;
7690
}
7691
7692
/**
7693
 * Remove tags from HTML anf return the $in_number_char first non-HTML char
7694
 * Postfix the text with "..." if it has been truncated.
7695
 * @param string $text
7696
 * @param integer $number
7697
 *
7698
 * @return string
7699
 * @author hubert borderiou
7700
 */
7701
function api_get_short_text_from_html($text, $number)
7702
{
7703
    // Delete script and style tags
7704
    $text =  preg_replace('/(<(script|style)\b[^>]*>).*?(<\/\2>)/is', "$1$3", $text);
7705
    $text = api_html_entity_decode($text);
7706
    $out_res = api_remove_tags_with_space($text, false);
7707
    $postfix = "...";
7708
    if (strlen($out_res) > $number) {
7709
        $out_res = substr($out_res, 0, $number).$postfix;
7710
    }
7711
    return $out_res;
7712
}
7713
7714
/**
7715
 * Replace tags with a space in a text.
7716
 * If $in_double_quote_replace, replace " with '' (for HTML attribute purpose, for exemple)
7717
 * @return string
7718
 * @author hubert borderiou
7719
 */
7720
function api_remove_tags_with_space($in_html, $in_double_quote_replace = true)
7721
{
7722
    $out_res = $in_html;
7723
    if ($in_double_quote_replace) {
7724
        $out_res = str_replace('"', "''", $out_res);
7725
    }
7726
    // avoid text stuck together when tags are removed, adding a space after >
7727
    $out_res = str_replace(">", "> ", $out_res);
7728
    $out_res = strip_tags($out_res);
7729
7730
    return $out_res;
7731
}
7732
7733
/**
7734
 * If true, the drh can access all content (courses, users) inside a session
7735
 * @return bool
7736
 */
7737
function api_drh_can_access_all_session_content()
7738
{
7739
    $value = api_get_setting('drh_can_access_all_session_content');
7740
7741
    return $value === 'true';
7742
}
7743
7744
/**
7745
 * @param string $tool
7746
 * @param string $setting
7747
 * @param integer $defaultValue
7748
 * @return string
7749
 */
7750
function api_get_default_tool_setting($tool, $setting, $defaultValue)
7751
{
7752
    global $_configuration;
7753
    if (isset($_configuration[$tool]) &&
7754
        isset($_configuration[$tool]['default_settings']) &&
7755
        isset($_configuration[$tool]['default_settings'][$setting])
7756
    ) {
7757
        return $_configuration[$tool]['default_settings'][$setting];
7758
    }
7759
7760
    return $defaultValue;
7761
}
7762
7763
/**
7764
 * Checks if user can login as another user
7765
 *
7766
 * @param int $loginAsUserId the user id to log in
7767
 * @param int $userId my user id
7768
 * @return bool
7769
 */
7770
function api_can_login_as($loginAsUserId, $userId = null)
7771
{
7772
    if (empty($userId)) {
7773
        $userId = api_get_user_id();
7774
    }
7775
    if ($loginAsUserId == $userId) {
7776
        return false;
7777
    }
7778
7779
    if (empty($loginAsUserId)) {
7780
        return false;
7781
    }
7782
7783
    if ($loginAsUserId != strval(intval($loginAsUserId))) {
7784
        return false;
7785
    }
7786
7787
    // Check if the user to login is an admin
7788
    if (api_is_platform_admin_by_id($loginAsUserId)) {
7789
        // Only super admins can login to admin accounts
7790
        if (!api_global_admin_can_edit_admin($loginAsUserId)) {
7791
            return false;
7792
        }
7793
    }
7794
7795
    $userInfo = api_get_user_info($userId);
7796
    $isDrh = function () use ($loginAsUserId) {
7797
        if (api_is_drh()) {
7798
            if (api_drh_can_access_all_session_content()) {
7799
                $users = SessionManager::getAllUsersFromCoursesFromAllSessionFromStatus(
7800
                    'drh_all',
7801
                    api_get_user_id()
7802
                );
7803
                $userList = [];
7804
                if (is_array($users)) {
7805
                    foreach ($users as $user) {
7806
                        $userList[] = $user['user_id'];
7807
                    }
7808
                }
7809
                if (in_array($loginAsUserId, $userList)) {
7810
                    return true;
7811
                }
7812
            } else {
7813
                if (api_is_drh() &&
7814
                    UserManager::is_user_followed_by_drh($loginAsUserId, api_get_user_id())
7815
                ) {
7816
                    return true;
7817
                }
7818
            }
7819
        }
7820
        return false;
7821
    };
7822
7823
    return api_is_platform_admin() || (api_is_session_admin() && $userInfo['status'] == 5) || $isDrh();
7824
}
7825
7826
/**
7827
 * @return bool
7828
 */
7829
function api_is_allowed_in_course()
7830
{
7831
    if (api_is_platform_admin()) {
7832
        return true;
7833
    }
7834
7835
    return Session::read('is_allowed_in_course');
7836
}
7837
7838
/**
7839
 * Set the cookie to go directly to the course code $in_firstpage
7840
 * after login
7841
 * @param string $in_firstpage is the course code of the course to go
7842
 */
7843
function api_set_firstpage_parameter($in_firstpage)
7844
{
7845
    setcookie('GotoCourse', $in_firstpage);
7846
}
7847
7848
/**
7849
 * Delete the cookie to go directly to the course code $in_firstpage
7850
 * after login
7851
 */
7852
function api_delete_firstpage_parameter()
7853
{
7854
    setcookie('GotoCourse', '', time() - 3600);
7855
}
7856
7857
/**
7858
 * @return boolean if course_code for direct course access after login is set
7859
 */
7860
function exist_firstpage_parameter()
7861
{
7862
    return isset($_COOKIE['GotoCourse']) && $_COOKIE['GotoCourse'] != '';
7863
}
7864
7865
/**
7866
 * @return return the course_code of the course where user login
7867
 */
7868
function api_get_firstpage_parameter()
7869
{
7870
    return $_COOKIE['GotoCourse'];
7871
}
7872
7873
/**
7874
 * Return true on https install
7875
 * @return boolean
7876
 */
7877
function api_is_https()
7878
{
7879
    if (!empty($_SERVER['HTTP_X_FORWARDED_PROTO']) &&
7880
        $_SERVER['HTTP_X_FORWARDED_PROTO'] == 'https' || !empty($_configuration['force_https_forwarded_proto'])
7881
    ) {
7882
        $isSecured = true;
7883
    } else {
7884
        if (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] != 'off') {
7885
            $isSecured = true;
7886
        } else {
7887
            $isSecured = false;
7888
            // last chance
7889
            if (!empty($_SERVER['SERVER_PORT']) && $_SERVER['SERVER_PORT'] == 443) {
7890
                $isSecured = true;
7891
            }
7892
        }
7893
    }
7894
7895
    return $isSecured;
7896
}
7897
7898
/**
7899
 * Return protocol (http or https)
7900
 * @return string
7901
 */
7902
function api_get_protocol()
7903
{
7904
    return api_is_https() ? 'https' : 'http';
7905
}
7906
7907
/**
7908
 * Return a string where " are replaced with 2 '
7909
 * It is useful when you pass a PHP variable in a Javascript browser dialog
7910
 * e.g. : alert("<?php get_lang('Message') ?>");
7911
 * and message contains character "
7912
 *
7913
 * @param string $in_text
7914
 * @return string
7915
 */
7916
function convert_double_quote_to_single($in_text)
7917
{
7918
    return api_preg_replace('/"/', "''", $in_text);
7919
}
7920
7921
/**
7922
 * Get origin
7923
 *
7924
 * @param string
7925
 * @return string
7926
 **/
7927
function api_get_origin()
7928
{
7929
    $origin = isset($_REQUEST['origin']) ? Security::remove_XSS($_REQUEST['origin']) : '';
7930
7931
    return $origin;
7932
}
7933
7934
/**
7935
 * Warns an user that the portal reach certain limit.
7936
 * @param string $limitName
7937
 */
7938
function api_warn_hosting_contact($limitName)
7939
{
7940
    $hostingParams = api_get_configuration_value(1);
7941
    $email = null;
7942
7943
    if (!empty($hostingParams)) {
7944
        if (isset($hostingParams['hosting_contact_mail'])) {
7945
            $email = $hostingParams['hosting_contact_mail'];
7946
        }
7947
    }
7948
7949
    if (!empty($email)) {
7950
        $subject = get_lang('HostingWarningReached');
7951
        $body = get_lang('PortalName').': '.api_get_path(WEB_PATH)." \n ";
7952
        $body .= get_lang('PortalLimitType').': '.$limitName." \n ";
7953
        if (isset($hostingParams[$limitName])) {
7954
            $body .= get_lang('Value').': '.$hostingParams[$limitName];
7955
        }
7956
        api_mail_html(null, $email, $subject, $body);
7957
    }
7958
}
7959
7960
/**
7961
 * Gets value of a variable from app/config/configuration.php
7962
 * Variables that are not set in the configuration.php file but set elsewhere:
7963
 * - virtual_css_theme_folder (vchamilo plugin)
7964
 * - access_url (global.inc.php)
7965
 * - apc/apc_prefix (global.inc.php)
7966
 *
7967
 * @param string $variable
7968
 *
7969
 * @return bool|mixed
7970
 */
7971
function api_get_configuration_value($variable)
7972
{
7973
    global $_configuration;
7974
    // Check the current url id, id = 1 by default
7975
    $urlId = isset($_configuration['access_url']) ? (int) $_configuration['access_url'] : 1;
7976
7977
    $variable = trim($variable);
7978
7979
    // Check if variable exists
7980
    if (isset($_configuration[$variable])) {
7981
        if (is_array($_configuration[$variable])) {
7982
            // Check if it exists for the sub portal
7983
            if (array_key_exists($urlId, $_configuration[$variable])) {
7984
                return $_configuration[$variable][$urlId];
7985
            } else {
7986
                // Try to found element with id = 1 (master portal)
7987
                if (array_key_exists(1, $_configuration[$variable])) {
7988
                    return $_configuration[$variable][1];
7989
                }
7990
            }
7991
        }
7992
7993
        return $_configuration[$variable];
7994
    }
7995
7996
    return false;
7997
}
7998
7999
/**
8000
 * Returns supported image extensions in the portal
8001
 * @param   bool    $supportVectors Whether vector images should also be accepted or not
8002
 * @return  array   Supported image extensions in the portal
8003
 */
8004
function api_get_supported_image_extensions($supportVectors = true)
8005
{
8006
    // jpg can also be called jpeg, jpe, jfif and jif. See https://en.wikipedia.org/wiki/JPEG#JPEG_filename_extensions
8007
    $supportedImageExtensions = ['jpg', 'jpeg', 'png', 'gif', 'jpe', 'jfif', 'jif'];
8008
    if ($supportVectors) {
8009
        array_push($supportedImageExtensions, 'svg');
8010
    }
8011
    if (version_compare(PHP_VERSION, '5.5.0', '>=')) {
8012
        array_push($supportedImageExtensions, 'webp');
8013
    }
8014
    return $supportedImageExtensions;
8015
}
8016
8017
/**
8018
 * This setting changes the registration status for the campus
8019
 *
8020
 * @author Patrick Cool <[email protected]>, Ghent University
8021
 * @version August 2006
8022
 * @param   bool    $listCampus Whether we authorize
8023
 * @todo the $_settings should be reloaded here. => write api function for this and use this in global.inc.php also.
8024
 */
8025
function api_register_campus($listCampus = true)
8026
{
8027
    $tbl_settings = Database::get_main_table(TABLE_MAIN_SETTINGS_CURRENT);
8028
8029
    $sql = "UPDATE $tbl_settings SET selected_value='true' WHERE variable='registered'";
8030
    Database::query($sql);
8031
8032
    if (!$listCampus) {
8033
        $sql = "UPDATE $tbl_settings SET selected_value='true' WHERE variable='donotlistcampus'";
8034
        Database::query($sql);
8035
    }
8036
}
8037
8038
/**
8039
 * Checks whether current user is a student boss
8040
 * @global array $_user
8041
 * @return boolean
8042
 */
8043
function api_is_student_boss()
8044
{
8045
    $_user = api_get_user_info();
8046
8047
    return isset($_user['status']) && $_user['status'] == STUDENT_BOSS;
8048
}
8049
8050
/**
8051
 * Check whether the user type should be exclude.
8052
 * Such as invited or anonymous users
8053
 * @param boolean $checkDB Optional. Whether check the user status
8054
 * @param int $userId Options. The user id
8055
 *
8056
 * @return boolean
8057
 */
8058
function api_is_excluded_user_type($checkDB = false, $userId = 0)
8059
{
8060
    if ($checkDB) {
8061
        $userId = empty($userId) ? api_get_user_id() : intval($userId);
8062
8063
        if ($userId == 0) {
8064
            return true;
8065
        }
8066
8067
        $userInfo = api_get_user_info($userId);
8068
8069
        switch ($userInfo['status']) {
8070
            case INVITEE:
8071
            case ANONYMOUS:
8072
                return true;
8073
            default:
8074
                return false;
8075
        }
8076
    }
8077
8078
    $isInvited = api_is_invitee();
8079
    $isAnonymous = api_is_anonymous();
8080
8081
    if ($isInvited || $isAnonymous) {
8082
        return true;
8083
    }
8084
8085
    return false;
8086
}
8087
8088
/**
8089
 * Get the user status to ignore in reports
8090
 * @param string $format Optional. The result type (array or string)
8091
 * @return array|string
8092
 */
8093
function api_get_users_status_ignored_in_reports($format = 'array')
8094
{
8095
    $excludedTypes = [
8096
        INVITEE,
8097
        ANONYMOUS
8098
    ];
8099
8100
    if ($format == 'string') {
8101
        return implode(', ', $excludedTypes);
8102
    }
8103
8104
    return $excludedTypes;
8105
}
8106
8107
/**
8108
 * Set the Site Use Cookie Warning for 1 year
8109
 */
8110
function api_set_site_use_cookie_warning_cookie()
8111
{
8112
    setcookie('ChamiloUsesCookies', 'ok', time() + 31556926);
8113
}
8114
8115
/**
8116
 * Return true if the Site Use Cookie Warning Cookie warning exists
8117
 * @return bool
8118
 */
8119
function api_site_use_cookie_warning_cookie_exist()
8120
{
8121
    return isset($_COOKIE['ChamiloUsesCookies']);
8122
}
8123
8124
/**
8125
 * Given a number of seconds, format the time to show hours, minutes and seconds
8126
 * @param int $time The time in seconds
8127
 * @param string $originFormat Optional. PHP o JS
8128
 * @return string (00h00'00")
8129
 */
8130
function api_format_time($time, $originFormat = 'php')
8131
{
8132
    $h = get_lang('h');
8133
    $hours = $time / 3600;
8134
    $mins = ($time % 3600) / 60;
8135
    $secs = ($time % 60);
8136
8137
    if ($time < 0) {
8138
        $hours = 0;
8139
        $mins = 0;
8140
        $secs = 0;
8141
    }
8142
8143
    if ($originFormat == 'js') {
8144
        $formattedTime = trim(sprintf("%02d : %02d : %02d", $hours, $mins, $secs));
8145
    } else {
8146
        $formattedTime = trim(sprintf("%02d$h%02d'%02d\"", $hours, $mins, $secs));
8147
    }
8148
8149
    return $formattedTime;
8150
}
8151
8152
/**
8153
 * Create a new empty directory with index.html file
8154
 * @param string $name The new directory name
8155
 * @param string $parentDirectory Directory parent directory name
8156
 * @return boolean Return true if the directory was create. Otherwise return false
8157
 */
8158
function api_create_protected_dir($name, $parentDirectory)
8159
{
8160
    $isCreated = false;
8161
8162
    if (!is_writable($parentDirectory)) {
8163
        return false;
8164
    }
8165
8166
    $fullPath = $parentDirectory.api_replace_dangerous_char($name);
8167
8168
    if (mkdir($fullPath, api_get_permissions_for_new_directories(), true)) {
8169
        $fp = fopen($fullPath.'/index.html', 'w');
8170
8171
        if ($fp) {
8172
            if (fwrite($fp, '<html><head></head><body></body></html>')) {
8173
                $isCreated = true;
8174
            }
8175
        }
8176
8177
        fclose($fp);
8178
    }
8179
8180
    return $isCreated;
8181
}
8182
8183
/**
8184
 * Sends an HTML email using the phpmailer class (and multipart/alternative to downgrade gracefully)
8185
 * Sender name and email can be specified, if not specified
8186
 * name and email of the platform admin are used
8187
 *
8188
 * @author Bert Vanderkimpen ICT&O UGent
8189
 * @author Yannick Warnier <[email protected]>
8190
 *
8191
 * @param string    name of recipient
8192
 * @param string    email of recipient
8193
 * @param string    email subject
8194
 * @param string    email body
8195
 * @param string    sender name
8196
 * @param string    sender e-mail
8197
 * @param array     extra headers in form $headers = array($name => $value) to allow parsing
8198
 * @param array     data file (path and filename)
8199
 * @param bool      True for attaching a embedded file inside content html (optional)
8200
 * @param array     Additional parameters
8201
 * @return          integer true if mail was sent
8202
 * @see             class.phpmailer.php
8203
 */
8204
function api_mail_html(
8205
    $recipient_name,
8206
    $recipient_email,
8207
    $subject,
8208
    $message,
8209
    $senderName = '',
8210
    $senderEmail = '',
8211
    $extra_headers = [],
8212
    $data_file = [],
8213
    $embedded_image = false,
8214
    $additionalParameters = []
8215
) {
8216
    global $platform_email;
8217
    return;
8218
8219
    $mail = new PHPMailer();
0 ignored issues
show
Unused Code introduced by
$mail = new PHPMailer() 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...
8220
    $mail->Mailer = $platform_email['SMTP_MAILER'];
8221
    $mail->Host = $platform_email['SMTP_HOST'];
8222
    $mail->Port = $platform_email['SMTP_PORT'];
8223
    $mail->CharSet = $platform_email['SMTP_CHARSET'];
8224
    // Stay far below SMTP protocol 980 chars limit.
8225
    $mail->WordWrap = 200;
8226
8227
    if ($platform_email['SMTP_AUTH']) {
8228
        $mail->SMTPAuth = 1;
8229
        $mail->Username = $platform_email['SMTP_USER'];
8230
        $mail->Password = $platform_email['SMTP_PASS'];
8231
        if (isset($platform_email['SMTP_SECURE'])) {
8232
            $mail->SMTPSecure = $platform_email['SMTP_SECURE'];
8233
        }
8234
    }
8235
    $mail->SMTPDebug = isset($platform_email['SMTP_DEBUG']) ? $platform_email['SMTP_DEBUG'] : 0;
8236
8237
    // 5 = low, 1 = high
8238
    $mail->Priority = 3;
8239
    $mail->SMTPKeepAlive = true;
8240
8241
    // Default values
8242
    $notification = new Notification();
8243
    $defaultEmail = $notification->getDefaultPlatformSenderEmail();
8244
    $defaultName = $notification->getDefaultPlatformSenderName();
8245
8246
    // If the parameter is set don't use the admin.
8247
    $senderName = !empty($senderName) ? $senderName : $defaultName;
8248
    $senderEmail = !empty($senderEmail) ? $senderEmail : $defaultEmail;
8249
8250
    // Reply to first
8251
    if (isset($extra_headers['reply_to']) && empty($platform_email['SMTP_UNIQUE_REPLY_TO'])) {
8252
        $mail->AddReplyTo(
8253
            $extra_headers['reply_to']['mail'],
8254
            $extra_headers['reply_to']['name']
8255
        );
8256
        // Errors to sender
8257
        $mail->AddCustomHeader('Errors-To: '.$extra_headers['reply_to']['mail']);
8258
        $mail->Sender = $extra_headers['reply_to']['mail'];
8259
        unset($extra_headers['reply_to']);
8260
    } else {
8261
        $mail->AddCustomHeader('Errors-To: '.$defaultEmail);
8262
    }
8263
8264
    //If the SMTP configuration only accept one sender
8265
    if (isset($platform_email['SMTP_UNIQUE_SENDER']) && $platform_email['SMTP_UNIQUE_SENDER']) {
8266
        $senderName = $platform_email['SMTP_FROM_NAME'];
8267
        $senderEmail = $platform_email['SMTP_FROM_EMAIL'];
8268
        $valid = PHPMailer::validateAddress($senderEmail);
8269
        if ($valid) {
8270
            //force-set Sender to $senderEmail, otherwise SetFrom only does it if it is currently empty
8271
            $mail->Sender = $senderEmail;
8272
        }
8273
    }
8274
8275
    $mail->SetFrom($senderEmail, $senderName);
8276
    $mail->Subject = $subject;
8277
    $mail->AltBody = strip_tags(
8278
        str_replace('<br />', "\n", api_html_entity_decode($message))
8279
    );
8280
8281
    $list = api_get_configuration_value('send_all_emails_to');
8282
    if (!empty($list) && isset($list['emails'])) {
8283
        foreach ($list['emails'] as $email) {
8284
            //$mail->AddBCC($email);
8285
            $mail->AddAddress($email);
8286
        }
8287
    }
8288
8289
    // Send embedded image.
8290
    if ($embedded_image) {
8291
        // Get all images html inside content.
8292
        preg_match_all("/<img\s+.*?src=[\"\']?([^\"\' >]*)[\"\']?[^>]*>/i", $message, $m);
8293
        // Prepare new tag images.
8294
        $new_images_html = [];
8295
        $i = 1;
8296
        if (!empty($m[1])) {
8297
            foreach ($m[1] as $image_path) {
8298
                $real_path = realpath($image_path);
8299
                $filename  = basename($image_path);
8300
                $image_cid = $filename.'_'.$i;
8301
                $encoding = 'base64';
8302
                $image_type = mime_content_type($real_path);
8303
                $mail->AddEmbeddedImage(
8304
                    $real_path,
8305
                    $image_cid,
8306
                    $filename,
8307
                    $encoding,
8308
                    $image_type
8309
                );
8310
                $new_images_html[] = '<img src="cid:'.$image_cid.'" />';
8311
                $i++;
8312
            }
8313
        }
8314
8315
        // Replace origin image for new embedded image html.
8316
        $x = 0;
8317
        if (!empty($m[0])) {
8318
            foreach ($m[0] as $orig_img) {
8319
                $message = str_replace($orig_img, $new_images_html[$x], $message);
8320
                $x++;
8321
            }
8322
        }
8323
    }
8324
8325
    $mailView = new Template(null, false, false, false, false, false, false);
8326
8327
    $noReply = api_get_setting('noreply_email_address');
8328
    if (!empty($noReply)) {
8329
        $message .= "<br />".get_lang('ThisIsAutomaticEmailNoReply');
8330
    }
8331
    $mailView->assign('content', $message);
8332
8333
    if (isset($additionalParameters['link'])) {
8334
        $mailView->assign('link', $additionalParameters['link']);
8335
    }
8336
    $mailView->assign('mail_header_style', api_get_configuration_value('mail_header_style'));
8337
    $mailView->assign('mail_content_style', api_get_configuration_value('mail_content_style'));
8338
    $layout = $mailView->get_template('mail/mail.tpl');
8339
    $mail->Body = $mailView->fetch($layout);
8340
8341
    // Attachment ...
8342
    if (!empty($data_file)) {
8343
        $o = 0;
8344
        foreach ($data_file as $file_attach) {
8345
            if (!empty($file_attach['path']) && !empty($file_attach['filename'])) {
8346
                $mail->AddAttachment($file_attach['path'], $file_attach['filename']);
8347
            }
8348
            $o++;
8349
        }
8350
    }
8351
8352
    // Only valid addresses are accepted.
8353
    if (is_array($recipient_email)) {
8354
        foreach ($recipient_email as $dest) {
8355
            if (api_valid_email($dest)) {
8356
                $mail->AddAddress($dest, $recipient_name);
8357
            }
8358
        }
8359
    } else {
8360
        if (api_valid_email($recipient_email)) {
8361
            $mail->AddAddress($recipient_email, $recipient_name);
8362
        } else {
8363
            return 0;
8364
        }
8365
    }
8366
8367
    if (is_array($extra_headers) && count($extra_headers) > 0) {
8368
        foreach ($extra_headers as $key => $value) {
8369
            switch (strtolower($key)) {
8370
                case 'encoding':
8371
                case 'content-transfer-encoding':
8372
                    $mail->Encoding = $value;
8373
                    break;
8374
                case 'charset':
8375
                    $mail->Charset = $value;
8376
                    break;
8377
                case 'contenttype':
8378
                case 'content-type':
8379
                    $mail->ContentType = $value;
8380
                    break;
8381
                default:
8382
                    $mail->AddCustomHeader($key.':'.$value);
8383
                    break;
8384
            }
8385
        }
8386
    } else {
8387
        if (!empty($extra_headers)) {
8388
            $mail->AddCustomHeader($extra_headers);
8389
        }
8390
    }
8391
8392
    // WordWrap the html body (phpMailer only fixes AltBody) FS#2988
8393
    $mail->Body = $mail->WrapText($mail->Body, $mail->WordWrap);
8394
8395
    // Send the mail message.
8396
    if (!$mail->Send()) {
8397
        error_log('ERROR: mail not sent to '.$recipient_name.' ('.$recipient_email.') because of '.$mail->ErrorInfo.'<br />');
8398
        if ($mail->SMTPDebug) {
8399
            error_log(
8400
                "Connection details :: ".
8401
                "Protocol: ".$mail->Mailer.' :: '.
8402
                "Host/Port: ".$mail->Host.':'.$mail->Port.' :: '.
8403
                "Authent/Open: ".($mail->SMTPAuth ? 'Authent' : 'Open').' :: '.
8404
                ($mail->SMTPAuth ? "  User/Pass: ".$mail->Username.':'.$mail->Password : '').' :: '.
8405
                "Sender: ".$mail->Sender
8406
            );
8407
        }
8408
        return 0;
8409
    }
8410
8411
    if (!empty($additionalParameters)) {
8412
        $plugin = new AppPlugin();
8413
        $smsPlugin = $plugin->getSMSPluginLibrary();
8414
        if ($smsPlugin) {
8415
            $smsPlugin->send($additionalParameters);
8416
        }
8417
    }
8418
8419
    // Clear all the addresses.
8420
    $mail->ClearAddresses();
8421
8422
    // Clear all attachments
8423
    $mail->ClearAttachments();
8424
8425
    return 1;
8426
}
8427
8428
/**
8429
 * @param string $tool Possible values: GroupManager::GROUP_TOOL_*
8430
 * @param bool $showHeader
8431
 */
8432
function api_protect_course_group($tool, $showHeader = true)
8433
{
8434
    $userId = api_get_user_id();
8435
    $groupId = api_get_group_id();
8436
    $groupInfo = GroupManager::get_group_properties($groupId);
8437
8438
    if (!empty($groupInfo)) {
8439
        $allow = GroupManager::user_has_access(
8440
            $userId,
8441
            $groupInfo['iid'],
8442
            $tool
8443
        );
8444
8445
        if (!$allow) {
8446
            api_not_allowed($showHeader);
8447
        }
8448
    }
8449
}
8450
8451
/**
8452
 * Check if a date is in a date range
8453
 *
8454
 * @param datetime $startDate
8455
 * @param datetime $endDate
8456
 * @param datetime $currentDate
8457
 * @return bool true if date is in rage, false otherwise
8458
 */
8459
function api_is_date_in_date_range($startDate, $endDate, $currentDate = null)
8460
{
8461
    $startDate = strtotime(api_get_local_time($startDate));
8462
    $endDate = strtotime(api_get_local_time($endDate));
8463
    $currentDate = strtotime(api_get_local_time($currentDate));
8464
8465
    if ($currentDate >= $startDate && $currentDate <= $endDate) {
8466
        return true;
8467
    }
8468
8469
    return false;
8470
}
8471
8472
/**
8473
 * Eliminate the duplicates of a multidimensional array by sending the key
8474
 *
8475
 * @param array $array multidimensional array
8476
 * @param int $key key to find to compare
8477
 * @return array
8478
 *
8479
 */
8480
function api_unique_multidim_array($array, $key)
8481
{
8482
    $temp_array = [];
8483
    $i = 0;
8484
    $key_array = [];
8485
8486
    foreach ($array as $val) {
8487
        if (!in_array($val[$key], $key_array)) {
8488
            $key_array[$i] = $val[$key];
8489
            $temp_array[$i] = $val;
8490
        }
8491
        $i++;
8492
    }
8493
    return $temp_array;
8494
}
8495
8496
/**
8497
 * Limit the access to Session Admins wheen the limit_session_admin_role
8498
 * configuration variable is set to true
8499
 */
8500
function api_protect_limit_for_session_admin()
8501
{
8502
    $limitAdmin = api_get_setting('limit_session_admin_role');
8503
    if (api_is_session_admin() && $limitAdmin === 'true') {
8504
        api_not_allowed(true);
8505
    }
8506
}
8507
8508
/**
8509
 * @return bool
8510
 */
8511
function api_is_student_view_active()
8512
{
8513
    $studentView = Session::read('studentview');
8514
    return $studentView == 'studentview';
8515
}
8516
8517
/**
8518
 * Adds a file inside the upload/$type/id
8519
 *
8520
 * @param string $type
8521
 * @param array $file
8522
 * @param int $itemId
8523
 * @param string $cropParameters
8524
 * @return array|bool
8525
 */
8526
function api_upload_file($type, $file, $itemId, $cropParameters = '')
8527
{
8528
    $upload = process_uploaded_file($file);
8529
    if ($upload) {
8530
        $name = api_replace_dangerous_char($file['name']);
8531
8532
        // No "dangerous" files
8533
        $name = disable_dangerous_file($name);
8534
8535
        $pathId = '/'.substr((string) $itemId, 0, 1).'/'.$itemId.'/';
8536
        $path = api_get_path(SYS_UPLOAD_PATH).$type.$pathId;
8537
8538
        if (!is_dir($path)) {
8539
            mkdir($path, api_get_permissions_for_new_directories(), true);
8540
        }
8541
8542
        $pathToSave = $path.$name;
8543
8544
        $result = move_uploaded_file($file['tmp_name'], $pathToSave);
8545
        if ($result) {
8546
            if (!empty($cropParameters)) {
8547
                $image = new Image($pathToSave);
8548
                $image->crop($cropParameters);
8549
            }
8550
8551
            return ['path_to_save' => $pathId.$name];
8552
        }
8553
        return false;
8554
    }
8555
}
8556
8557
/**
8558
 * @param string $type
8559
 * @param int $itemId
8560
 * @param string $file
8561
 *
8562
 * @return bool
8563
 */
8564
function api_get_uploaded_file($type, $itemId, $file)
8565
{
8566
    $itemId = (int) $itemId;
8567
    $pathId = '/'.substr((string) $itemId, 0, 1).'/'.$itemId.'/';
8568
    $path = api_get_path(SYS_UPLOAD_PATH).$type.$pathId;
8569
8570
    $file = basename($file);
8571
8572
    $file = $path.'/'.$file;
8573
    if (file_exists($file)) {
8574
        return $file;
8575
    }
8576
    return false;
8577
}
8578
8579
/**
8580
 * @param string $type
8581
 * @param int $itemId
8582
 * @param string $file
8583
 * @param string $title
8584
 */
8585
function api_download_uploaded_file($type, $itemId, $file, $title = '')
8586
{
8587
    $file = api_get_uploaded_file($type, $itemId, $file);
8588
    if ($file) {
8589
        if (Security::check_abs_path($file, api_get_path(SYS_UPLOAD_PATH).$type)) {
8590
            DocumentManager::file_send_for_download($file, true, $title);
8591
            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...
8592
        }
8593
    }
8594
    api_not_allowed(true);
8595
}
8596
8597
/**
8598
 * @param string $type
8599
 * @param string $file
8600
 */
8601
function api_remove_uploaded_file($type, $file)
8602
{
8603
    $path = api_get_path(SYS_UPLOAD_PATH).$type.'/'.$file;
8604
    if (file_exists($path)) {
8605
        unlink($path);
8606
    }
8607
}
8608
8609
/**
8610
 * Converts string value to float value
8611
 *
8612
 * 3.141516 => 3.141516
8613
 * 3,141516 => 3.141516
8614
 * @todo WIP
8615
 *
8616
 * @param string $number
8617
 * @return float
8618
 */
8619
function api_float_val($number)
8620
{
8621
    $number = (float) str_replace(',', '.', trim($number));
8622
    return $number;
8623
}
8624
8625
/**
8626
 * Converts float values
8627
 * Example if $decimals = 2
8628
 *
8629
 * 3.141516 => 3.14
8630
 * 3,141516 => 3,14
8631
 *
8632
 * @todo WIP
8633
 *
8634
 * @param string $number number in iso code
8635
 * @param int $decimals
8636
 * @return bool|string
8637
 */
8638
function api_number_format($number, $decimals = 0)
8639
{
8640
    $number = api_float_val($number);
8641
8642
    return number_format($number, $decimals);
8643
}
8644
8645
/**
8646
 * Set location url with a exit break by default
8647
 *
8648
 * @param $url
8649
 * @param bool $exit
8650
 * @return void
8651
 */
8652
function location($url, $exit = true)
8653
{
8654
    header('Location: '.$url);
8655
8656
    if ($exit) {
8657
        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...
8658
    }
8659
}
8660
8661
/**
8662
 * @return string
8663
 */
8664
function api_get_web_url()
8665
{
8666
    if (api_get_setting('server_type') == 'test') {
8667
        return api_get_path(WEB_PATH).'web/app_dev.php/';
8668
    } else {
8669
        return api_get_path(WEB_PATH).'web/';
8670
    }
8671
}
8672