Completed
Push — 1.10.x ( 981700...503274 )
by Julito
61:06
created

api.lib.php ➔ api_replace_dangerous_char()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 1 Features 0
Metric Value
cc 1
eloc 2
c 1
b 1
f 0
nc 1
nop 1
dl 0
loc 4
rs 10
1
<?php
2
/* For licensing terms, see /license.txt */
3
4
/**
5
 * This is a code library for Chamilo.
6
 * It is included by default in every Chamilo file (through including the global.inc.php)
7
 *
8
 * @package chamilo.library
9
 */
10
11
use ChamiloSession as Session;
12
13
/**
14
 * Constants declaration
15
 */
16
17
// PHP version requirement.
18
define('REQUIRED_PHP_VERSION', '5.4');
19
define('REQUIRED_MIN_MEMORY_LIMIT', '128');
20
define('REQUIRED_MIN_UPLOAD_MAX_FILESIZE', '10');
21
define('REQUIRED_MIN_POST_MAX_SIZE', '10');
22
23
// USER STATUS CONSTANTS
24
/** global status of a user: student */
25
define('STUDENT', 5);
26
/** global status of a user: course manager */
27
define('COURSEMANAGER', 1);
28
/** global status of a user: session admin */
29
define('SESSIONADMIN', 3);
30
/** global status of a user: human ressource manager */
31
define('DRH', 4);
32
/** global status of a user: human ressource manager */
33
define('ANONYMOUS', 6);
34
/** global status of a user: low security, necessary for inserting data from
35
 * the teacher through HTMLPurifier */
36
define('COURSEMANAGERLOWSECURITY', 10);
37
38
//Soft user status
39
define('PLATFORM_ADMIN', 11);
40
define('SESSION_COURSE_COACH', 12);
41
define('SESSION_GENERAL_COACH', 13);
42
define('COURSE_STUDENT', 14);   //student subscribed in a course
43
define('SESSION_STUDENT', 15);  //student subscribed in a session course
44
define('COURSE_TUTOR', 16); // student is tutor of a course (NOT in session)
45
define('STUDENT_BOSS', 17); // student is boss
46
define('INVITEE', 20);
47
48
// Table of status
49
$_status_list[COURSEMANAGER] = 'teacher';        // 1
50
$_status_list[SESSIONADMIN] = 'session_admin';  // 3
51
$_status_list[DRH] = 'drh';            // 4
52
$_status_list[STUDENT] = 'user';           // 5
53
$_status_list[ANONYMOUS] = 'anonymous';      // 6
54
$_status_list[INVITEE] = 'invited';        // 20
55
56
// COURSE VISIBILITY CONSTANTS
57
/** only visible for course admin */
58
define('COURSE_VISIBILITY_CLOSED', 0);
59
/** only visible for users registered in the course */
60
define('COURSE_VISIBILITY_REGISTERED', 1);
61
/** Open for all registered users on the platform */
62
define('COURSE_VISIBILITY_OPEN_PLATFORM', 2);
63
/** Open for the whole world */
64
define('COURSE_VISIBILITY_OPEN_WORLD', 3);
65
/** Invisible to all except admin */
66
define('COURSE_VISIBILITY_HIDDEN', 4);
67
68
define('COURSE_REQUEST_PENDING', 0);
69
define('COURSE_REQUEST_ACCEPTED', 1);
70
define('COURSE_REQUEST_REJECTED', 2);
71
define('DELETE_ACTION_ENABLED', false);
72
73
// EMAIL SENDING RECIPIENT CONSTANTS
74
define('SEND_EMAIL_EVERYONE', 1);
75
define('SEND_EMAIL_STUDENTS', 2);
76
define('SEND_EMAIL_TEACHERS', 3);
77
78
// SESSION VISIBILITY CONSTANTS
79
define('SESSION_VISIBLE_READ_ONLY', 1);
80
define('SESSION_VISIBLE', 2);
81
define('SESSION_INVISIBLE', 3); // not available
82
define('SESSION_AVAILABLE', 4);
83
84
define('SESSION_LINK_TARGET', '_self');
85
86
define('SUBSCRIBE_ALLOWED', 1);
87
define('SUBSCRIBE_NOT_ALLOWED', 0);
88
define('UNSUBSCRIBE_ALLOWED', 1);
89
define('UNSUBSCRIBE_NOT_ALLOWED', 0);
90
91
// SURVEY VISIBILITY CONSTANTS
92
define('SURVEY_VISIBLE_TUTOR', 0);
93
define('SURVEY_VISIBLE_TUTOR_STUDENT', 1);
94
define('SURVEY_VISIBLE_PUBLIC', 2);
95
96
// CONSTANTS defining all tools, using the english version
97
/* When you add a new tool you must add it into function api_get_tools_lists() too */
98
define('TOOL_DOCUMENT', 'document');
99
define('TOOL_LP_FINAL_ITEM', 'final_item');
100
define('TOOL_THUMBNAIL', 'thumbnail');
101
define('TOOL_HOTPOTATOES', 'hotpotatoes');
102
define('TOOL_CALENDAR_EVENT', 'calendar_event');
103
define('TOOL_LINK', 'link');
104
define('TOOL_LINK_CATEGORY', 'link_category');
105
define('TOOL_COURSE_DESCRIPTION', 'course_description');
106
define('TOOL_SEARCH', 'search');
107
define('TOOL_LEARNPATH', 'learnpath');
108
define('TOOL_AGENDA', 'agenda');
109
define('TOOL_ANNOUNCEMENT', 'announcement');
110
define('TOOL_FORUM', 'forum');
111
define('TOOL_FORUM_CATEGORY', 'forum_category');
112
define('TOOL_FORUM_THREAD', 'forum_thread');
113
define('TOOL_FORUM_POST', 'forum_post');
114
define('TOOL_FORUM_ATTACH', 'forum_attachment');
115
define('TOOL_FORUM_THREAD_QUALIFY', 'forum_thread_qualify');
116
define('TOOL_THREAD', 'thread');
117
define('TOOL_POST', 'post');
118
define('TOOL_DROPBOX', 'dropbox');
119
define('TOOL_QUIZ', 'quiz');
120
define('TOOL_TEST_CATEGORY', 'test_category');
121
define('TOOL_USER', 'user');
122
define('TOOL_GROUP', 'group');
123
define('TOOL_BLOGS', 'blog_management');
124
define('TOOL_CHAT', 'chat');
125
define('TOOL_CONFERENCE', 'conference');
126
define('TOOL_STUDENTPUBLICATION', 'student_publication');
127
define('TOOL_TRACKING', 'tracking');
128
define('TOOL_HOMEPAGE_LINK', 'homepage_link');
129
define('TOOL_COURSE_SETTING', 'course_setting');
130
define('TOOL_BACKUP', 'backup');
131
define('TOOL_COPY_COURSE_CONTENT', 'copy_course_content');
132
define('TOOL_RECYCLE_COURSE', 'recycle_course');
133
define('TOOL_COURSE_HOMEPAGE', 'course_homepage');
134
define('TOOL_COURSE_RIGHTS_OVERVIEW', 'course_rights');
135
define('TOOL_UPLOAD', 'file_upload');
136
define('TOOL_COURSE_MAINTENANCE', 'course_maintenance');
137
define('TOOL_VISIO', 'visio');
138
define('TOOL_VISIO_CONFERENCE', 'visio_conference');
139
define('TOOL_VISIO_CLASSROOM', 'visio_classroom');
140
define('TOOL_SURVEY', 'survey');
141
define('TOOL_WIKI', 'wiki');
142
define('TOOL_GLOSSARY', 'glossary');
143
define('TOOL_GRADEBOOK', 'gradebook');
144
define('TOOL_NOTEBOOK', 'notebook');
145
define('TOOL_ATTENDANCE', 'attendance');
146
define('TOOL_COURSE_PROGRESS', 'course_progress');
147
148
// CONSTANTS defining Chamilo interface sections
149
define('SECTION_CAMPUS', 'mycampus');
150
define('SECTION_COURSES', 'mycourses');
151
define('SECTION_MYPROFILE', 'myprofile');
152
define('SECTION_MYAGENDA', 'myagenda');
153
define('SECTION_COURSE_ADMIN', 'course_admin');
154
define('SECTION_PLATFORM_ADMIN', 'platform_admin');
155
define('SECTION_MYGRADEBOOK', 'mygradebook');
156
define('SECTION_TRACKING', 'session_my_space');
157
define('SECTION_SOCIAL', 'social-network');
158
define('SECTION_DASHBOARD', 'dashboard');
159
define('SECTION_REPORTS', 'reports');
160
define('SECTION_GLOBAL', 'global');
161
162
// CONSTANT name for local authentication source
163
define('PLATFORM_AUTH_SOURCE', 'platform');
164
define('CAS_AUTH_SOURCE', 'cas');
165
define('LDAP_AUTH_SOURCE', 'extldap');
166
167
// CONSTANT defining the default HotPotatoes files directory
168
define('DIR_HOTPOTATOES', '/HotPotatoes_files');
169
170
// event logs types
171
define('LOG_COURSE_DELETE', 'course_deleted');
172
define('LOG_COURSE_CREATE', 'course_created');
173
174
// @todo replace 'soc_gr' with social_group
175
define('LOG_GROUP_PORTAL_CREATED', 'soc_gr_created');
176
define('LOG_GROUP_PORTAL_UPDATED', 'soc_gr_updated');
177
define('LOG_GROUP_PORTAL_DELETED', 'soc_gr_deleted');
178
define('LOG_GROUP_PORTAL_USER_DELETE_ALL', 'soc_gr_delete_users');
179
180
define('LOG_GROUP_PORTAL_ID', 'soc_gr_portal_id');
181
define('LOG_GROUP_PORTAL_REL_USER_ARRAY', 'soc_gr_user_array');
182
183
define('LOG_GROUP_PORTAL_USER_SUBSCRIBED', 'soc_gr_u_subs');
184
define('LOG_GROUP_PORTAL_USER_UNSUBSCRIBED', 'soc_gr_u_unsubs');
185
define('LOG_GROUP_PORTAL_USER_UPDATE_ROLE', 'soc_gr_update_role');
186
187
define('LOG_USER_DELETE', 'user_deleted');
188
define('LOG_USER_CREATE', 'user_created');
189
define('LOG_USER_ENABLE', 'user_enable');
190
define('LOG_USER_DISABLE', 'user_disable');
191
define('LOG_USER_FIELD_CREATE', 'user_field_created');
192
define('LOG_USER_FIELD_DELETE', 'user_field_deleted');
193
define('LOG_SESSION_CREATE', 'session_created');
194
define('LOG_SESSION_DELETE', 'session_deleted');
195
define('LOG_SESSION_ADD_USER_COURSE', 'session_add_user_course');
196
define('LOG_SESSION_DELETE_USER_COURSE', 'session_delete_user_course');
197
define('LOG_SESSION_DELETE_USER', 'session_delete_user');
198
define('LOG_SESSION_ADD_COURSE', 'session_add_course');
199
define('LOG_SESSION_DELETE_COURSE', 'session_delete_course');
200
201
define('LOG_SESSION_CATEGORY_CREATE', 'session_cat_created'); //changed in 1.9.8
202
define('LOG_SESSION_CATEGORY_DELETE', 'session_cat_deleted'); //changed in 1.9.8
203
define('LOG_CONFIGURATION_SETTINGS_CHANGE', 'settings_changed');
204
define('LOG_PLATFORM_LANGUAGE_CHANGE', 'platform_lng_changed'); //changed in 1.9.8
205
define('LOG_SUBSCRIBE_USER_TO_COURSE', 'user_subscribed');
206
define('LOG_UNSUBSCRIBE_USER_FROM_COURSE', 'user_unsubscribed');
207
define('LOG_ATTEMPTED_FORCED_LOGIN', 'attempted_forced_login');
208
209
define('LOG_HOMEPAGE_CHANGED', 'homepage_changed');
210
211
define('LOG_PROMOTION_CREATE', 'promotion_created');
212
define('LOG_PROMOTION_DELETE', 'promotion_deleted');
213
define('LOG_CAREER_CREATE', 'career_created');
214
define('LOG_CAREER_DELETE', 'career_deleted');
215
216
define('LOG_USER_PERSONAL_DOC_DELETED', 'user_doc_deleted');
217
define('LOG_WIKI_ACCESS', 'wiki_page_view');
218
219
define('LOG_EXERCISE_RESULT_DELETE', 'exe_result_deleted');
220
define('LOG_LP_ATTEMPT_DELETE', 'lp_attempt_deleted');
221
define('LOG_QUESTION_RESULT_DELETE', 'qst_attempt_deleted');
222
223
define('LOG_MY_FOLDER_CREATE', 'my_folder_created');
224
define('LOG_MY_FOLDER_CHANGE', 'my_folder_changed');
225
define('LOG_MY_FOLDER_DELETE', 'my_folder_deleted');
226
define('LOG_MY_FOLDER_COPY', 'my_folder_copied');
227
define('LOG_MY_FOLDER_CUT', 'my_folder_cut');
228
define('LOG_MY_FOLDER_PASTE', 'my_folder_pasted');
229
define('LOG_MY_FOLDER_UPLOAD', 'my_folder_uploaded');
230
231
// Event logs data types (max 20 chars)
232
define('LOG_COURSE_CODE', 'course_code');
233
define('LOG_COURSE_ID', 'course_id');
234
define('LOG_USER_ID', 'user_id');
235
define('LOG_USER_OBJECT', 'user_object');
236
define('LOG_USER_FIELD_VARIABLE', 'user_field_variable');
237
define('LOG_SESSION_ID', 'session_id');
238
define('LOG_SESSION_CATEGORY_ID', 'session_category_id');
239
define('LOG_CONFIGURATION_SETTINGS_CATEGORY', 'settings_category');
240
define('LOG_CONFIGURATION_SETTINGS_VARIABLE', 'settings_variable');
241
define('LOG_PLATFORM_LANGUAGE', 'default_platform_language');
242
define('LOG_CAREER_ID', 'career_id');
243
define('LOG_PROMOTION_ID', 'promotion_id');
244
define('LOG_GRADEBOOK_LOCKED', 'gradebook_locked');
245
define('LOG_GRADEBOOK_UNLOCKED', 'gradebook_unlocked');
246
define('LOG_GRADEBOOK_ID', 'gradebook_id');
247
define('LOG_WIKI_PAGE_ID', 'wiki_page_id');
248
define('LOG_EXERCISE_ID', 'exercise_id');
249
define('LOG_EXERCISE_AND_USER_ID', 'exercise_and_user_id');
250
define('LOG_LP_ID', 'lp_id');
251
define('LOG_EXERCISE_ATTEMPT_QUESTION_ID', 'exercise_a_q_id');
252
253
define('LOG_MY_FOLDER_PATH', 'path');
254
define('LOG_MY_FOLDER_NEW_PATH', 'new_path');
255
256
define('USERNAME_PURIFIER', '/[^0-9A-Za-z_\.]/');
257
258
//used when login_is_email setting is true
259
define('USERNAME_PURIFIER_MAIL', '/[^0-9A-Za-z_\.@]/');
260
define('USERNAME_PURIFIER_SHALLOW', '/\s/');
261
262
// This constant is a result of Windows OS detection, it has a boolean value:
263
// true whether the server runs on Windows OS, false otherwise.
264
define('IS_WINDOWS_OS', api_is_windows_os());
265
266
// Checks for installed optional php-extensions.
267
define('INTL_INSTALLED', function_exists('intl_get_error_code'));   // intl extension (from PECL), it is installed by default as of PHP 5.3.0
268
define('ICONV_INSTALLED', function_exists('iconv'));                // iconv extension, for PHP5 on Windows it is installed by default.
269
define('MBSTRING_INSTALLED', function_exists('mb_strlen'));         // mbstring extension.
270
271
// Patterns for processing paths.                                   // Examples:
272
define('REPEATED_SLASHES_PURIFIER', '/\/{2,}/');                    // $path = preg_replace(REPEATED_SLASHES_PURIFIER, '/', $path);
273
define('VALID_WEB_PATH', '/https?:\/\/[^\/]*(\/.*)?/i');            // $is_valid_path = preg_match(VALID_WEB_PATH, $path);
274
define('VALID_WEB_SERVER_BASE', '/https?:\/\/[^\/]*/i');            // $new_path = preg_replace(VALID_WEB_SERVER_BASE, $new_base, $path);
275
276
// Constants for api_get_path() and api_get_path_type(), etc. - registered path types.
277
define('WEB_PATH', 'WEB_PATH');
278
define('WEB_APP_PATH', 'WEB_APP_PATH');
279
define('SYS_PATH', 'SYS_PATH');
280
define('SYS_APP_PATH', 'SYS_APP_PATH');
281
define('SYS_UPLOAD_PATH', 'SYS_UPLOAD_PATH');
282
define('WEB_UPLOAD_PATH', 'WEB_UPLOAD_PATH');
283
284
define('REL_PATH', 'REL_PATH');
285
define('WEB_SERVER_ROOT_PATH', 'WEB_SERVER_ROOT_PATH');
286
define('SYS_SERVER_ROOT_PATH', 'SYS_SERVER_ROOT_PATH');
287
define('WEB_COURSE_PATH', 'WEB_COURSE_PATH');
288
define('SYS_COURSE_PATH', 'SYS_COURSE_PATH');
289
define('REL_COURSE_PATH', 'REL_COURSE_PATH');
290
define('REL_CODE_PATH', 'REL_CODE_PATH');
291
define('REL_UPLOAD_PATH', 'REL_UPLOAD_PATH');
292
define('WEB_CODE_PATH', 'WEB_CODE_PATH');
293
define('SYS_CODE_PATH', 'SYS_CODE_PATH');
294
define('SYS_LANG_PATH', 'SYS_LANG_PATH');
295
define('WEB_IMG_PATH', 'WEB_IMG_PATH');
296
define('WEB_CSS_PATH', 'WEB_CSS_PATH');
297
define('WEB_PUBLIC_PATH', 'WEB_PUBLIC_PATH');
298
define('SYS_CSS_PATH', 'SYS_CSS_PATH');
299
define('SYS_PLUGIN_PATH', 'SYS_PLUGIN_PATH');
300
define('PLUGIN_PATH', 'SYS_PLUGIN_PATH'); // deprecated ?
301
define('WEB_PLUGIN_PATH', 'WEB_PLUGIN_PATH');
302
define('SYS_ARCHIVE_PATH', 'SYS_ARCHIVE_PATH');
303
define('WEB_ARCHIVE_PATH', 'WEB_ARCHIVE_PATH');
304
define('INCLUDE_PATH', 'INCLUDE_PATH');
305
define('LIBRARY_PATH', 'LIBRARY_PATH');
306
define('CONFIGURATION_PATH', 'CONFIGURATION_PATH');
307
define('WEB_LIBRARY_PATH', 'WEB_LIBRARY_PATH');
308
define('WEB_LIBRARY_JS_PATH', 'WEB_LIBRARY_JS_PATH');
309
define('WEB_AJAX_PATH', 'WEB_AJAX_PATH');
310
define('SYS_TEST_PATH', 'SYS_TEST_PATH');
311
define('WEB_TEMPLATE_PATH', 'WEB_TEMPLATE_PATH');
312
define('SYS_TEMPLATE_PATH', 'SYS_TEMPLATE_PATH');
313
define('SYS_PUBLIC_PATH', 'SYS_PUBLIC_PATH');
314
315
define('WEB_FONTS_PATH', 'WEB_FONTS_PATH');
316
define('SYS_FONTS_PATH', 'SYS_FONTS_PATH');
317
318
define('SYS_DEFAULT_COURSE_DOCUMENT_PATH', 'SYS_DEFAULT_COURSE_DOCUMENT_PATH');
319
define('REL_DEFAULT_COURSE_DOCUMENT_PATH', 'REL_DEFAULT_COURSE_DOCUMENT_PATH');
320
define('WEB_DEFAULT_COURSE_DOCUMENT_PATH', 'WEB_DEFAULT_COURSE_DOCUMENT_PATH');
321
322
// Constants for requesting path conversion.
323
define('TO_WEB', 'TO_WEB');
324
define('TO_SYS', 'TO_SYS');
325
define('TO_REL', 'TO_REL');
326
327
// Paths to registered specific resource files (scripts, players, etc.)
328
define('FLASH_PLAYER_AUDIO', '{FLASH_PLAYER_AUDIO}');
329
define('FLASH_PLAYER_VIDEO', '{FLASH_PLAYER_VIDEO}');
330
define('SCRIPT_SWFOBJECT', '{SCRIPT_SWFOBJECT}');
331
define('SCRIPT_ASCIIMATHML', '{SCRIPT_ASCIIMATHML}');
332
define('DRAWING_ASCIISVG', '{DRAWING_ASCIISVG}');
333
334
// Forcing PclZip library to use a custom temporary folder.
335
define('PCLZIP_TEMPORARY_DIR', api_get_path(SYS_ARCHIVE_PATH));
336
337
// Relations type with Course manager
338
define('COURSE_RELATION_TYPE_COURSE_MANAGER', 1);
339
define('SESSION_RELATION_TYPE_COURSE_MANAGER', 1);
340
341
// Relations type with Human resources manager
342
define('COURSE_RELATION_TYPE_RRHH', 1);
343
define('SESSION_RELATION_TYPE_RRHH', 1);
344
345
//User image sizes
346
define('USER_IMAGE_SIZE_ORIGINAL', 1);
347
define('USER_IMAGE_SIZE_BIG', 2);
348
define('USER_IMAGE_SIZE_MEDIUM', 3);
349
define('USER_IMAGE_SIZE_SMALL', 4);
350
351
// Relation type between users
352
define('USER_UNKNOW', 0);
353
define('USER_RELATION_TYPE_UNKNOW', 1);
354
define('USER_RELATION_TYPE_PARENT', 2); // should be deprecated is useless
355
define('USER_RELATION_TYPE_FRIEND', 3);
356
define('USER_RELATION_TYPE_GOODFRIEND', 4); // should be deprecated is useless
357
define('USER_RELATION_TYPE_ENEMY', 5); // should be deprecated is useless
358
define('USER_RELATION_TYPE_DELETED', 6);
359
define('USER_RELATION_TYPE_RRHH', 7);
360
define('USER_RELATION_TYPE_BOSS', 8);
361
362
// Gradebook link constants
363
// Please do not change existing values, they are used in the database !
364
365
define('GRADEBOOK_ITEM_LIMIT', 1000);
366
367
define('LINK_EXERCISE', 1);
368
define('LINK_DROPBOX', 2);
369
define('LINK_STUDENTPUBLICATION', 3);
370
define('LINK_LEARNPATH', 4);
371
define('LINK_FORUM_THREAD', 5);
372
//define('LINK_WORK',6);
373
define('LINK_ATTENDANCE', 7);
374
define('LINK_SURVEY', 8);
375
define('LINK_HOTPOTATOES', 9);
376
377
// Score display types constants
378
define('SCORE_DIV', 1);    // X / Y
379
define('SCORE_PERCENT', 2);    // XX %
380
define('SCORE_DIV_PERCENT', 3);    // X / Y (XX %)
381
define('SCORE_AVERAGE', 4);    // XX %
382
define('SCORE_DECIMAL', 5);    // 0.50  (X/Y)
383
define('SCORE_BAR', 6);    // Uses the Display::bar_progress function
384
define('SCORE_SIMPLE', 7);    // X
385
define('SCORE_IGNORE_SPLIT', 8);    //  ??
386
define('SCORE_DIV_PERCENT_WITH_CUSTOM', 9);    // X / Y (XX %) - Good!
387
define('SCORE_CUSTOM', 10);    // Good!
388
define('SCORE_DIV_SIMPLE_WITH_CUSTOM', 11);    // X - Good!
389
define('SCORE_DIV_SIMPLE_WITH_CUSTOM_LETTERS', 12);    // X - Good!
390
define('SCORE_ONLY_SCORE', 13);    // X - Good!
391
392
define('SCORE_BOTH', 1);
393
define('SCORE_ONLY_DEFAULT', 2);
394
define('SCORE_ONLY_CUSTOM', 3);
395
396
// From display.lib.php
397
398
define('MAX_LENGTH_BREADCRUMB', 100);
399
define('ICON_SIZE_ATOM', 8);
400
define('ICON_SIZE_TINY', 16);
401
define('ICON_SIZE_SMALL', 22);
402
define('ICON_SIZE_MEDIUM', 32);
403
define('ICON_SIZE_LARGE', 48);
404
define('ICON_SIZE_BIG', 64);
405
define('ICON_SIZE_HUGE', 128);
406
define('SHOW_TEXT_NEAR_ICONS', false);
407
408
// Session catalog
409
define('CATALOG_COURSES', 0);
410
define('CATALOG_SESSIONS', 1);
411
define('CATALOG_COURSES_SESSIONS', 2);
412
413
// Hook type events, pre-process and post-process.
414
// All means to be executed for both hook event types
415
define('HOOK_EVENT_TYPE_PRE', 0);
416
define('HOOK_EVENT_TYPE_POST', 1);
417
define('HOOK_EVENT_TYPE_ALL', 10);
418
419
define('CAREER_STATUS_ACTIVE', 1);
420
define('CAREER_STATUS_INACTIVE', 0);
421
422
define('PROMOTION_STATUS_ACTIVE', 1);
423
define('PROMOTION_STATUS_INACTIVE', 0);
424
425
// Group permissions
426
define('GROUP_PERMISSION_OPEN', '1');
427
define('GROUP_PERMISSION_CLOSED', '2');
428
429
// Group user permissions
430
define('GROUP_USER_PERMISSION_ADMIN', '1'); // the admin of a group
431
define('GROUP_USER_PERMISSION_READER', '2'); // a normal user
432
define('GROUP_USER_PERMISSION_PENDING_INVITATION', '3'); // When an admin/moderator invites a user
433
define('GROUP_USER_PERMISSION_PENDING_INVITATION_SENT_BY_USER', '4'); // an user joins a group
434
define('GROUP_USER_PERMISSION_MODERATOR', '5'); // a moderator
435
define('GROUP_USER_PERMISSION_ANONYMOUS', '6'); // an anonymous user
436
define('GROUP_USER_PERMISSION_HRM', '7'); // a human resources manager
437
438
define('GROUP_IMAGE_SIZE_ORIGINAL', 1);
439
define('GROUP_IMAGE_SIZE_BIG', 2);
440
define('GROUP_IMAGE_SIZE_MEDIUM', 3);
441
define('GROUP_IMAGE_SIZE_SMALL', 4);
442
443
define('GROUP_TITLE_LENGTH', 50);
444
445
// Exercise
446
// @todo move into a class
447
448
define('ALL_ON_ONE_PAGE', 1);
449
define('ONE_PER_PAGE', 2);
450
451
define('EXERCISE_FEEDBACK_TYPE_END', 0); //Feedback 		 - show score and expected answers
452
define('EXERCISE_FEEDBACK_TYPE_DIRECT', 1); //DirectFeedback - Do not show score nor answers
453
define('EXERCISE_FEEDBACK_TYPE_EXAM', 2); //NoFeedback 	 - Show score only
454
455
define('RESULT_DISABLE_SHOW_SCORE_AND_EXPECTED_ANSWERS', 0); //show score and expected answers
456
define('RESULT_DISABLE_NO_SCORE_AND_EXPECTED_ANSWERS', 1); //Do not show score nor answers
457
define('RESULT_DISABLE_SHOW_SCORE_ONLY', 2); //Show score only
458
define('RESULT_DISABLE_SHOW_FINAL_SCORE_ONLY_WITH_CATEGORIES', 3); //Show final score only with categories
459
define('RESULT_DISABLE_SHOW_SCORE_ATTEMPT_SHOW_ANSWERS_LAST_ATTEMPT', 4); //Show final score only with categories
460
461
define('EXERCISE_MAX_NAME_SIZE', 80);
462
463
// Question types (edit next array as well when adding values)
464
// @todo move into a class
465
define('UNIQUE_ANSWER', 1);
466
define('MULTIPLE_ANSWER', 2);
467
define('FILL_IN_BLANKS', 3);
468
define('MATCHING', 4);
469
define('FREE_ANSWER', 5);
470
define('HOT_SPOT', 6);
471
define('HOT_SPOT_ORDER', 7);
472
define('HOT_SPOT_DELINEATION', 8);
473
define('MULTIPLE_ANSWER_COMBINATION', 9);
474
define('UNIQUE_ANSWER_NO_OPTION', 10);
475
define('MULTIPLE_ANSWER_TRUE_FALSE', 11);
476
define('MULTIPLE_ANSWER_COMBINATION_TRUE_FALSE', 12);
477
define('ORAL_EXPRESSION', 13);
478
define('GLOBAL_MULTIPLE_ANSWER', 14);
479
define('MEDIA_QUESTION', 15);
480
define('CALCULATED_ANSWER', 16);
481
define('UNIQUE_ANSWER_IMAGE', 17);
482
define('DRAGGABLE', 18);
483
define('MATCHING_DRAGGABLE', 19);
484
485
define('EXERCISE_CATEGORY_RANDOM_SHUFFLED', 1);
486
define('EXERCISE_CATEGORY_RANDOM_ORDERED', 2);
487
define('EXERCISE_CATEGORY_RANDOM_DISABLED', 0);
488
489
// Question selection type
490
define('EX_Q_SELECTION_ORDERED', 1);
491
define('EX_Q_SELECTION_RANDOM', 2);
492
define('EX_Q_SELECTION_CATEGORIES_ORDERED_QUESTIONS_ORDERED', 3);
493
define('EX_Q_SELECTION_CATEGORIES_RANDOM_QUESTIONS_ORDERED', 4);
494
define('EX_Q_SELECTION_CATEGORIES_ORDERED_QUESTIONS_RANDOM', 5);
495
define('EX_Q_SELECTION_CATEGORIES_RANDOM_QUESTIONS_RANDOM', 6);
496
define('EX_Q_SELECTION_CATEGORIES_RANDOM_QUESTIONS_ORDERED_NO_GROUPED', 7);
497
define('EX_Q_SELECTION_CATEGORIES_RANDOM_QUESTIONS_RANDOM_NO_GROUPED', 8);
498
define('EX_Q_SELECTION_CATEGORIES_ORDERED_BY_PARENT_QUESTIONS_ORDERED', 9);
499
define('EX_Q_SELECTION_CATEGORIES_ORDERED_BY_PARENT_QUESTIONS_RANDOM', 10);
500
501
// one big string with all question types, for the validator in pear/HTML/QuickForm/Rule/QuestionType
502
define('QUESTION_TYPES',
503
    UNIQUE_ANSWER.':'.
504
    MULTIPLE_ANSWER.':'.
505
    FILL_IN_BLANKS.':'.
506
    MATCHING.':'.
507
    FREE_ANSWER.':'.
508
    HOT_SPOT.':'.
509
    HOT_SPOT_ORDER.':'.
510
    HOT_SPOT_DELINEATION.':'.
511
    MULTIPLE_ANSWER_COMBINATION.':'.
512
    UNIQUE_ANSWER_NO_OPTION.':'.
513
    MULTIPLE_ANSWER_TRUE_FALSE.':'.
514
    MULTIPLE_ANSWER_COMBINATION_TRUE_FALSE.':'.
515
    ORAL_EXPRESSION.':'.
516
    GLOBAL_MULTIPLE_ANSWER.':'.
517
    MEDIA_QUESTION.':'.
518
    CALCULATED_ANSWER.':'.
519
    UNIQUE_ANSWER_IMAGE.':'.
520
    DRAGGABLE.':'.
521
    MATCHING_DRAGGABLE
522
);
523
524
//Some alias used in the QTI exports
525
define('MCUA', 1);
526
define('TF', 1);
527
define('MCMA', 2);
528
define('FIB', 3);
529
530
// Skills
531
define('SKILL_TYPE_REQUIREMENT', 'required');
532
define('SKILL_TYPE_ACQUIRED', 'acquired');
533
define('SKILL_TYPE_BOTH', 'both');
534
535
// Message
536
define('MESSAGE_STATUS_NEW', '0');
537
define('MESSAGE_STATUS_UNREAD', '1');
538
//2 ??
539
define('MESSAGE_STATUS_DELETED', '3');
540
define('MESSAGE_STATUS_OUTBOX', '4');
541
define('MESSAGE_STATUS_INVITATION_PENDING', '5');
542
define('MESSAGE_STATUS_INVITATION_ACCEPTED', '6');
543
define('MESSAGE_STATUS_INVITATION_DENIED', '7');
544
define('MESSAGE_STATUS_WALL', '8');
545
define('MESSAGE_STATUS_WALL_DELETE', '9');
546
define('MESSAGE_STATUS_WALL_POST', '10');
547
// Images
548
define('IMAGE_WALL_SMALL_SIZE', 200);
549
define('IMAGE_WALL_MEDIUM_SIZE', 500);
550
define('IMAGE_WALL_BIG_SIZE', 2000);
551
define('IMAGE_WALL_SMALL', 'small');
552
define('IMAGE_WALL_MEDIUM', 'medium');
553
define('IMAGE_WALL_BIG', 'big');
554
555
// Social PLUGIN PLACES
556
define('SOCIAL_LEFT_PLUGIN', 1);
557
define('SOCIAL_CENTER_PLUGIN', 2);
558
define('SOCIAL_RIGHT_PLUGIN', 3);
559
define('CUT_GROUP_NAME', 50);
560
561
/**
562
 * FormValidator Filter
563
 */
564
define('NO_HTML', 1);
565
define('STUDENT_HTML', 2);
566
define('TEACHER_HTML', 3);
567
define('STUDENT_HTML_FULLPAGE', 4);
568
define('TEACHER_HTML_FULLPAGE', 5);
569
570
// Timeline
571
define('TIMELINE_STATUS_ACTIVE', '1');
572
define('TIMELINE_STATUS_INACTIVE', '2');
573
574
// Event email template class
575
define ('EVENT_EMAIL_TEMPLATE_ACTIVE',  1);
576
define ('EVENT_EMAIL_TEMPLATE_INACTIVE', 0);
577
578
// Course home
579
define('SHORTCUTS_HORIZONTAL', 0);
580
define('SHORTCUTS_VERTICAL', 1);
581
582
// Image class
583
define('IMAGE_PROCESSOR', 'gd'); // 'imagick' or 'gd' strings
584
585
/**
586
 * Inclusion of internationalization libraries
587
 */
588
require_once __DIR__.'/internationalization.lib.php';
589
590
/**
591
 * Returns a path to a certain resource within the Chamilo area, specifyed through a parameter.
592
 * Also, this function provides conversion between path types, in this case the input path points inside the Chamilo area too.
593
 *
594
 * See $_configuration['course_folder'] in the configuration.php to alter the WEB_COURSE_PATH and SYS_COURSE_PATH parameters.
595
 * @param string $path (optional)   A path which type is to be converted. Also, it may be a defined constant for a path.
596
 * This parameter has meaning when $type parameter has one of the following values: TO_WEB, TO_SYS, TO_REL. Otherwise it is ignored.
597
 * @return string                   The requested path or the converted path.
598
 *
599
 * A terminology note:
600
 * The defined constants used by this function contain the abbreviations WEB, REL, SYS with the following meaning for types:
601
 * WEB - an absolute URL (we often call it web-path),
602
 * example: http://www.mychamilo.org/chamilo/courses/COURSE01/document/lesson01.html;
603
 *
604
 * REL - represents a semi-absolute URL - a web-path, which is relative to the root web-path of the server, without server's base,
605
 * example: /chamilo/courses/COURSE01/document/lesson01.html;
606
 *
607
 * SYS - represents an absolute path inside the scope of server's file system,
608
 * /var/www/chamilo/courses/COURSE01/document/lesson01.html or
609
 * C:/Inetpub/wwwroot/chamilo/courses/COURSE01/document/lesson01.html.
610
 *
611
 * In some abstract sense we can consider these three path types as absolute.
612
 *
613
 * Notes about the current behaviour model:
614
 * 1. Windows back-slashes are converted to slashes in the result.
615
 * 2. A semi-absolute web-path is detected by its leading slash. On Linux systems, absolute system paths start with
616
 * a slash too, so an additional check about presence of leading system server base is implemented. For example, the function is
617
 * able to distinguish type difference between /var/www/chamilo/courses/ (SYS) and /chamilo/courses/ (REL).
618
 * 3. The function api_get_path() returns only these three types of paths, which in some sense are absolute. The function has
619
 * no a mechanism for processing relative web/system paths, such as: lesson01.html, ./lesson01.html, ../css/my_styles.css.
620
 * It has not been identified as needed yet.
621
 * 4. Also, resolving the meta-symbols "." and ".." within paths has not been implemented, it is to be identified as needed.
622
 *
623
 * Example:
624
 * Assume that your server root is /var/www/ ,
625
 * Chamilo is installed in a sub folder chamilo/ and the URL of your campus is http://www.mychamilo.org
626
 * The other configuration parameters have not been changed.
627
 *
628
 * This is how we can get most used paths, for common purpose:
629
630
 * api_get_path(REL_PATH)                       /chamilo/
631
 * api_get_path(REL_COURSE_PATH)                /chamilo/courses/
632
 * api_get_path(REL_CODE_PATH)                  /chamilo/main/
633
 * api_get_path(REL_UPLOAD_PATH)                /chamilo/app/upload/
634
 * api_get_path(SYS_SERVER_ROOT_PATH)           /var/www/ - This is the physical folder where the system Chamilo has been placed. It is not always equal to $_SERVER['DOCUMENT_ROOT'].
635
 * api_get_path(SYS_PATH)                       /var/www/chamilo/
636
 * api_get_path(SYS_APP_PATH)                   /var/www/chamilo/app/
637
 * api_get_path(SYS_UPLOAD_PATH)                /var/www/chamilo/app/upload/
638
 * api_get_path(SYS_ARCHIVE_PATH)               /var/www/chamilo/app/cache
639
 * api_get_path(SYS_COURSE_PATH)                /var/www/chamilo/app/courses/
640
 * api_get_path(SYS_CSS_PATH)                   /var/www/chamilo/app/Resources/public/css
641
 * api_get_path(SYS_CODE_PATH)                  /var/www/chamilo/main/
642
 * api_get_path(INCLUDE_PATH)                   /var/www/chamilo/main/inc/
643
 * api_get_path(LIBRARY_PATH)                   /var/www/chamilo/main/inc/lib/
644
 * api_get_path(CONFIGURATION_PATH)             /var/www/chamilo/main/inc/conf/
645
 * api_get_path(SYS_LANG_PATH)                  /var/www/chamilo/main/lang/
646
 * api_get_path(SYS_PLUGIN_PATH)                /var/www/chamilo/plugin/
647
 * api_get_path(SYS_TEST_PATH)                  /var/www/chamilo/tests/
648
 * api_get_path(SYS_TEMPLATE_PATH)              /var/www/chamilo/main/template/
649
 * api_get_path(SYS_PUBLIC_PATH)                /var/www/chamilo/web/
650
 *
651
 * api_get_path(WEB_SERVER_ROOT_PATH)           http://www.mychamilo.org/
652
 * api_get_path(WEB_PATH)                       http://www.mychamilo.org/chamilo/
653
 * api_get_path(WEB_COURSE_PATH)                http://www.mychamilo.org/chamilo/courses/
654
 * api_get_path(WEB_CODE_PATH)                  http://www.mychamilo.org/chamilo/main/
655
 * api_get_path(WEB_PLUGIN_PATH)                http://www.mychamilo.org/chamilo/plugin/
656
 * api_get_path(WEB_ARCHIVE_PATH)               http://www.mychamilo.org/chamilo/app/cache/
657
 * api_get_path(WEB_IMG_PATH)                   http://www.mychamilo.org/chamilo/main/img/
658
 * api_get_path(WEB_CSS_PATH)                   http://www.mychamilo.org/chamilo/web/css/
659
 * api_get_path(WEB_LIBRARY_PATH)               http://www.mychamilo.org/chamilo/main/inc/lib/
660
 * api_get_path(WEB_LIBRARY_JS_PATH)            http://www.mychamilo.org/chamilo/web/Chamilo/javascript
661
 * api_get_path(WEB_TEMPLATE_PATH)              http://www.mychamilo.org/chamilo/main/template/
662
 * api_get_path(WEB_UPLOAD_PATH)                http://www.mychamilo.org/chamilo/app/upload/
663
 * api_get_path(WEB_PUBLIC_PATH)                http://www.mychamilo.org/chamilo/web/
664
 *
665
 * This is how we retrieve paths of "registered" resource files (scripts, players, etc.):
666
 * api_get_path(TO_WEB, FLASH_PLAYER_AUDIO)     http://www.mychamilo.org/chamilo/main/inc/lib/mediaplayer/player.swf
667
 * api_get_path(TO_WEB, FLASH_PLAYER_VIDEO)     http://www.mychamilo.org/chamilo/main/inc/lib/mediaplayer/player.swf
668
 * api_get_path(TO_SYS, SCRIPT_SWFOBJECT)       /var/www/chamilo/main/inc/lib/swfobject/swfobject.js
669
 * api_get_path(TO_REL, SCRIPT_ASCIIMATHML)     /chamilo/main/inc/lib/asciimath/ASCIIMathML.js
670
 * ...
671
 *
672
 * We can convert arbitrary paths, that are not registered (no defined constant).
673
 * For guaranteed result, these paths should point inside the system Chamilo.
674
 * Some random examples:
675
 * api_get_path(TO_WEB, $_SERVER['REQUEST_URI'])
676
 * api_get_path(TO_SYS, $_SERVER['PHP_SELF'])
677
 * api_get_path(TO_REL, __FILE__)
678
 * ...
679
 */
680
function api_get_path($path_type, $path = null)
681
{
682
    static $paths = array(
683
        WEB_PATH                => '',
684
        SYS_PATH                => '',
685
        REL_PATH                => '',
686
        WEB_SERVER_ROOT_PATH    => '',
687
        SYS_SERVER_ROOT_PATH    => '',
688
        WEB_COURSE_PATH         => '',
689
        SYS_COURSE_PATH         => '',
690
        REL_COURSE_PATH         => '',
691
        REL_CODE_PATH           => '',
692
        WEB_CODE_PATH           => '',
693
        SYS_CODE_PATH           => '',
694
        SYS_LANG_PATH           => 'lang/',
695
        WEB_IMG_PATH            => 'img/',
696
        WEB_CSS_PATH            => 'web/css/',
697
        SYS_CSS_PATH            => 'app/Resources/public/css/',
698
        SYS_PLUGIN_PATH         => 'plugin/',
699
        WEB_PLUGIN_PATH         => 'plugin/',
700
        SYS_ARCHIVE_PATH        => 'app/cache/',
701
        WEB_ARCHIVE_PATH        => 'app/cache/',
702
        SYS_APP_PATH            => 'app/',
703
        WEB_APP_PATH            => 'app/',
704
        SYS_UPLOAD_PATH         => 'app/upload/',
705
        REL_UPLOAD_PATH         => 'app/upload/',
706
        INCLUDE_PATH            => 'inc/',
707
        LIBRARY_PATH            => 'inc/lib/',
708
        CONFIGURATION_PATH      => 'app/config/',
709
        WEB_LIBRARY_PATH        => 'inc/lib/',
710
        WEB_LIBRARY_JS_PATH     => 'inc/lib/javascript/',
711
        WEB_AJAX_PATH           => 'inc/ajax/',
712
        SYS_TEST_PATH           => 'tests/',
713
        WEB_TEMPLATE_PATH       => 'template/',
714
        WEB_UPLOAD_PATH         => 'app/upload/',
715
        WEB_PUBLIC_PATH         => 'web/',
716
        SYS_TEMPLATE_PATH       => 'template/',
717
        SYS_PUBLIC_PATH         => 'web/',
718
        WEB_FONTS_PATH          => 'fonts/',
719
        SYS_FONTS_PATH          => 'fonts/',
720
    );
721
722
    static $resource_paths = array(
723
        FLASH_PLAYER_AUDIO      => 'inc/lib/mediaplayer/player.swf',
724
        FLASH_PLAYER_VIDEO      => 'inc/lib/mediaplayer/player.swf',
725
        SCRIPT_SWFOBJECT        => 'inc/lib/swfobject/swfobject.js',
726
        SCRIPT_ASCIIMATHML      => 'inc/lib/javascript/asciimath/ASCIIMathML.js',
727
        DRAWING_ASCIISVG        => 'inc/lib/javascript/asciimath/d.svg'
728
    );
729
730
    static $is_this_function_initialized;
731
    static $server_base_web; // No trailing slash.
732
    static $server_base_sys; // No trailing slash.
733
    static $root_web;
734
    static $root_sys;
735
    static $root_rel;
736
737
    // Always load root_web modifications for multiple url features
738
    global $_configuration;
739
    //default $_configuration['root_web'] configuration
740
    $root_web = $_configuration['root_web'];
741
742
    $code_folder = 'main/';
743
    $course_folder = 'courses/';
744
745
    // Configuration data for already installed system.
746
    $root_sys = $_configuration['root_sys'];
747
    $load_new_config = false;
748
749
    // To avoid that the api_get_access_url() function fails since global.inc.php also calls the main_api.lib.php
750
    if ($path_type == WEB_PATH) {
751
        if (isset($_configuration['access_url']) &&  $_configuration['access_url'] != 1) {
752
            //we look into the DB the function api_get_access_url
753
            $url_info = api_get_access_url($_configuration['access_url']);
754
            $root_web = $url_info['active'] == 1 ? $url_info['url'] : $_configuration['root_web'];
755
            $load_new_config = true;
756
        }
757
    }
758
759
    if (!$is_this_function_initialized) {
760
        global $_configuration;
761
762
        $root_rel = $_configuration['url_append'];
763
764
        // Support for the installation process.
765
        // Developers might use the function api_get_path() directly or indirectly (this is difficult to be traced), at the moment when
766
        // configuration has not been created yet. This is why this function should be upgraded to return correct results in this case.
767
768
        if (defined('SYSTEM_INSTALLATION') && SYSTEM_INSTALLATION) {
769
            if (($pos = strpos(($requested_page_rel = api_get_self()), 'main/install')) !== false) {
770
                $root_rel = substr($requested_page_rel, 0, $pos);
771
                // See http://www.mediawiki.org/wiki/Manual:$wgServer
772
                $server_protocol = (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] == 'on') ? 'https' : 'http';
773
                $server_name =
774
                    isset($_SERVER['SERVER_NAME']) ? $_SERVER['SERVER_NAME']
775
                    : (isset($_SERVER['HOSTNAME']) ? $_SERVER['HOSTNAME']
776
                    : (isset($_SERVER['HTTP_HOST']) ? $_SERVER['HTTP_HOST']
777
                    : (isset($_SERVER['SERVER_ADDR']) ? $_SERVER['SERVER_ADDR']
778
                    : 'localhost')));
779
                if (isset($_SERVER['SERVER_PORT']) && !strpos($server_name, ':')
780
                    && (($server_protocol == 'http'
781
                    && $_SERVER['SERVER_PORT'] != 80 ) || ($server_protocol == 'https' && $_SERVER['SERVER_PORT'] != 443 ))) {
782
                    $server_name .= ":" . $_SERVER['SERVER_PORT'];
783
                }
784
                $root_web = $server_protocol.'://'.$server_name.$root_rel;
785
                $root_sys = str_replace('\\', '/', realpath(__DIR__.'/../../../')).'/';
786
                $code_folder = 'main/';
787
            }
788
            // Here we give up, so we don't touch anything.
789
        }
790
791
        // Dealing with trailing slashes.
792
        $root_web       = api_add_trailing_slash($root_web);
793
        $root_sys       = api_add_trailing_slash($root_sys);
794
        $root_rel       = api_add_trailing_slash($root_rel);
795
        $code_folder    = api_add_trailing_slash($code_folder);
796
        $course_folder  = api_add_trailing_slash($course_folder);
797
798
        // Web server base and system server base.
799
        $server_base_web = preg_replace('@'.$root_rel.'$@', '', $root_web); // No trailing slash.
800
        $server_base_sys = preg_replace('@'.$root_rel.'$@', '', $root_sys); // No trailing slash.
801
802
        // Initialization of a table that contains common-purpose paths.
803
        $paths[WEB_PATH]                = $root_web;
804
        $paths[SYS_PATH]                = $root_sys;
805
        $paths[REL_PATH]                = $root_rel;
806
        $paths[WEB_SERVER_ROOT_PATH]    = $server_base_web.'/';
807
        $paths[SYS_SERVER_ROOT_PATH]    = $server_base_sys.'/';
808
809
        $paths[WEB_COURSE_PATH]         = $root_web.$course_folder;
810
811
        $paths[REL_COURSE_PATH]         = $root_rel.$course_folder;
812
        $paths[REL_CODE_PATH]           = $root_rel.$code_folder;
813
        $paths[WEB_CODE_PATH]           = $root_web.$code_folder;
814
        $paths[SYS_CODE_PATH]           = $root_sys.$code_folder;
815
        $paths[REL_UPLOAD_PATH]         = $root_rel.$paths[SYS_UPLOAD_PATH];
816
817
        $paths[WEB_DEFAULT_COURSE_DOCUMENT_PATH] = $paths[WEB_CODE_PATH].'default_course_document/';
818
        $paths[REL_DEFAULT_COURSE_DOCUMENT_PATH] = $paths[REL_PATH].'main/default_course_document/';
819
820
        // Now we can switch into api_get_path() "terminology".
821
        $paths[SYS_LANG_PATH]           = $paths[SYS_CODE_PATH].$paths[SYS_LANG_PATH];
822
823
        $paths[SYS_APP_PATH]            = $paths[SYS_PATH].$paths[SYS_APP_PATH];
824
        $paths[WEB_APP_PATH]            = $paths[WEB_PATH].$paths[WEB_APP_PATH];
825
        $paths[SYS_UPLOAD_PATH]         = $paths[SYS_PATH].$paths[SYS_UPLOAD_PATH];
826
827
        $paths[SYS_PLUGIN_PATH]         = $paths[SYS_PATH].$paths[SYS_PLUGIN_PATH];
828
        $paths[SYS_ARCHIVE_PATH]        = $paths[SYS_PATH].$paths[SYS_ARCHIVE_PATH];
829
        $paths[SYS_TEST_PATH]           = $paths[SYS_PATH].$paths[SYS_TEST_PATH];
830
        $paths[SYS_TEMPLATE_PATH]       = $paths[SYS_CODE_PATH].$paths[SYS_TEMPLATE_PATH];
831
        $paths[SYS_PUBLIC_PATH]         = $paths[SYS_PATH].$paths[SYS_PUBLIC_PATH];
832
        $paths[SYS_CSS_PATH]            = $paths[SYS_PATH].$paths[SYS_CSS_PATH];
833
        $paths[SYS_FONTS_PATH]          = $paths[SYS_CODE_PATH].$paths[SYS_FONTS_PATH];
834
835
        $paths[WEB_CSS_PATH]            = $paths[WEB_PATH].$paths[WEB_CSS_PATH];
836
        $paths[WEB_IMG_PATH]            = $paths[WEB_CODE_PATH].$paths[WEB_IMG_PATH];
837
        $paths[WEB_LIBRARY_PATH]        = $paths[WEB_CODE_PATH].$paths[WEB_LIBRARY_PATH];
838
        $paths[WEB_LIBRARY_JS_PATH]     = $paths[WEB_CODE_PATH].$paths[WEB_LIBRARY_JS_PATH];
839
840
        $paths[WEB_AJAX_PATH]           = $paths[WEB_CODE_PATH].$paths[WEB_AJAX_PATH];
841
        $paths[WEB_FONTS_PATH]          = $paths[WEB_CODE_PATH].$paths[WEB_FONTS_PATH];
842
843
        $paths[WEB_PLUGIN_PATH]         = $paths[WEB_PATH].$paths[WEB_PLUGIN_PATH];
844
        $paths[WEB_ARCHIVE_PATH]        = $paths[WEB_PATH].$paths[WEB_ARCHIVE_PATH];
845
846
        $paths[WEB_TEMPLATE_PATH]       = $paths[WEB_CODE_PATH].$paths[WEB_TEMPLATE_PATH];
847
        $paths[WEB_UPLOAD_PATH]         = $paths[WEB_PATH].$paths[WEB_UPLOAD_PATH];
848
        $paths[WEB_PUBLIC_PATH]         = $paths[WEB_PATH].$paths[WEB_PUBLIC_PATH];
849
850
        $paths[INCLUDE_PATH]            = $paths[SYS_CODE_PATH].$paths[INCLUDE_PATH];
851
        $paths[LIBRARY_PATH]            = $paths[SYS_CODE_PATH].$paths[LIBRARY_PATH];
852
        $paths[CONFIGURATION_PATH]      = $paths[SYS_PATH].$paths[CONFIGURATION_PATH];
853
        $paths[SYS_COURSE_PATH]         = $paths[SYS_APP_PATH].$course_folder;
854
855
        $is_this_function_initialized = true;
856
    } else {
857
        if ($load_new_config) {
858
            //  Redefining variables to work well with the "multiple url" feature
859
860
            // All web paths need to be here
861
            $web_paths = array(
862
                WEB_PATH                => '',
863
                WEB_SERVER_ROOT_PATH    => '',
864
                WEB_COURSE_PATH         => '',
865
                WEB_CODE_PATH           => '',
866
                WEB_IMG_PATH            => 'img/',
867
                WEB_CSS_PATH            => 'web/css/',
868
                WEB_PLUGIN_PATH         => 'plugin/',
869
                WEB_ARCHIVE_PATH        => 'archive/',
870
                WEB_LIBRARY_PATH        => 'inc/lib/',
871
                WEB_AJAX_PATH           => 'inc/ajax/'
872
            );
873
874
            $root_web = api_add_trailing_slash($root_web);
875
            // Web server base and system server base.
876
            $server_base_web = preg_replace('@'.$root_rel.'$@', '', $root_web); // No trailing slash.
877
878
            // Redefine root webs
879
            $paths[WEB_PATH]                = $root_web;
880
            $paths[WEB_SERVER_ROOT_PATH]    = $server_base_web.'/';
881
            $paths[WEB_COURSE_PATH]         = $root_web.$course_folder;
882
            $paths[WEB_CODE_PATH]           = $root_web.$code_folder;
883
            $paths[WEB_IMG_PATH]            = $paths[WEB_CODE_PATH].$web_paths[WEB_IMG_PATH];
884
885
            $paths[WEB_CSS_PATH]            = $paths[WEB_PATH].$web_paths[WEB_CSS_PATH];
886
            $paths[WEB_PLUGIN_PATH]         = $paths[WEB_PATH].$web_paths[WEB_PLUGIN_PATH];
887
            $paths[WEB_ARCHIVE_PATH]        = $paths[WEB_PATH].$web_paths[WEB_ARCHIVE_PATH];
888
            $paths[WEB_LIBRARY_PATH]        = $paths[WEB_CODE_PATH].$web_paths[WEB_LIBRARY_PATH];
889
            $paths[WEB_AJAX_PATH]           = $paths[WEB_CODE_PATH].$web_paths[WEB_AJAX_PATH];
890
            $paths[WEB_FONTS_PATH]          = $paths[WEB_CODE_PATH].$paths[WEB_FONTS_PATH];
891
        }
892
    }
893
894
    // Shallow purification and validation of input parameters.
895
896
    $path_type = trim($path_type);
897
    $path = trim($path);
898
899
    if (empty($path_type)) {
900
        return null;
901
    }
902
903
    // Retrieving a common-purpose path.
904
    if (isset($paths[$path_type])) {
905
        return $paths[$path_type];
906
    }
907
908
    // Retrieving a specific resource path.
909
910
    if (isset($resource_paths[$path])) {
911
        switch ($path_type) {
912
            case TO_WEB:
913
                return $paths[WEB_CODE_PATH].$resource_paths[$path];
914
            case TO_SYS:
915
                return $paths[SYS_CODE_PATH].$resource_paths[$path];
916
            case TO_REL:
917
                return $paths[REL_CODE_PATH].$resource_paths[$path];
918
            default:
919
                return null;
920
        }
921
    }
922
923
    // Common-purpose paths as a second parameter - recognition.
924
925
    if (isset($paths[$path])) {
926
        $path = $paths[$path];
927
    }
928
929
    // Second purification.
930
931
    // Replacing Windows back slashes.
932
    $path = str_replace('\\', '/', $path);
933
    // Query strings sometimes mighth wrongly appear in non-URLs.
934
    // Let us check remove them from all types of paths.
935
    if (($pos = strpos($path, '?')) !== false) {
936
        $path = substr($path, 0, $pos);
937
    }
938
939
    // Detection of the input path type. Conversion to semi-absolute type ( /chamilo/main/inc/.... ).
940
941
    if (preg_match(VALID_WEB_PATH, $path)) {
942
943
        // A special case: When a URL points to the document download script directly, without
944
        // mod-rewrite translation, we have to translate it into an "ordinary" web path.
945
        // For example:
946
        // http://localhost/chamilo/main/document/download.php?doc_url=/image.png&cDir=/
947
        // becomes
948
        // http://localhost/chamilo/courses/TEST/document/image.png
949
        // TEST is a course directory name, so called "system course code".
950
        if (strpos($path, 'download.php') !== false) { // Fast detection first.
951
            $path = urldecode($path);
952
            if (preg_match('/(.*)main\/document\/download.php\?doc_url=\/(.*)&cDir=\/(.*)?/', $path, $matches)) {
953
                $sys_course_code =
954
                    isset($_SESSION['_course']['sysCode'])  // User is inside a course?
955
                        ? $_SESSION['_course']['sysCode']   // Yes, then use course's directory name.
956
                        : '{SYS_COURSE_CODE}';              // No, then use a fake code, it may be processed later.
957
                $path = $matches[1].'courses/'.$sys_course_code.'/document/'.str_replace('//', '/', $matches[3].'/'.$matches[2]);
958
            }
959
        }
960
        // Replacement of the present web server base with a slash '/'.
961
        $path = preg_replace(VALID_WEB_SERVER_BASE, '/', $path);
962
963
    } elseif (strpos($path, $server_base_sys) === 0) {
964
        $path = preg_replace('@^'.$server_base_sys.'@', '', $path);
965
    } elseif (strpos($path, '/') === 0) {
0 ignored issues
show
Unused Code introduced by
This elseif statement is empty, and could be removed.

This check looks for the bodies of elseif 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 elseif bodies can be removed. If you have an empty elseif but statements in the else branch, consider inverting the condition.

Loading history...
966
        // Leading slash - we assume that this path is semi-absolute (REL),
967
        // then path is left without furthes modifications.
968
    } else {
969
        return null; // Probably implementation of this case won't be needed.
970
    }
971
972
    // Path now is semi-absolute. It is convenient at this moment repeated slashes to be removed.
973
    $path = preg_replace(REPEATED_SLASHES_PURIFIER, '/', $path);
974
975
    // Path conversion to the requested type.
976
977
    switch ($path_type) {
978
        case TO_WEB:
979
            return $server_base_web.$path;
980
        case TO_SYS:
981
            return $server_base_sys.$path;
982
        case TO_REL:
983
            return $path;
984
    }
985
986
    return null;
987
}
988
989
/**
990
 * Gets a modified version of the path for the CDN, if defined in
991
 * configuration.php
992
 * @param string $web_path The path of the resource without CDN
993
 * @return string The path of the resource converted to CDN
994
 * @author Yannick Warnier <[email protected]>
995
 */
996
function api_get_cdn_path($web_path)
997
{
998
    global $_configuration;
999
    $web_root = api_get_path(WEB_PATH);
1000
    $ext = substr($web_path,strrpos($web_path,'.'));
1001
    if (isset($ext[2])) { // faster version of strlen to check if len>2
1002
        // Check for CDN definitions
1003
        if (!empty($_configuration['cdn_enable']) && !empty($ext)) {
1004
            foreach ($_configuration['cdn'] as $host => $exts) {
1005
                if (in_array($ext,$exts)) {
1006
                    //Use host as defined in $_configuration['cdn'], without
1007
                    // trailing slash
1008
                    return str_replace($web_root,$host.'/',$web_path);
1009
                }
1010
            }
1011
        }
1012
    }
1013
    return $web_path;
1014
}
1015
1016
/**
1017
 * @return bool Return true if CAS authentification is activated
1018
 *
1019
 */
1020
function api_is_cas_activated() {
1021
    return api_get_setting('cas_activate') == "true";
1022
}
1023
1024
/**
1025
 * @return bool     Return true if LDAP authentification is activated
1026
 *
1027
 */
1028
function api_is_ldap_activated() {
1029
    global $extAuthSource;
1030
    return is_array($extAuthSource[LDAP_AUTH_SOURCE]);
1031
}
1032
1033
/**
1034
 * @return bool     Return true if Facebook authentification is activated
1035
 *
1036
 */
1037
function api_is_facebook_auth_activated() {
1038
    global $_configuration;
1039
    return (isset($_configuration['facebook_auth']) && $_configuration['facebook_auth'] == 1);
1040
}
1041
1042
/**
1043
 * This function checks whether a given path points inside the system.
1044
 * @param string $path      The path to be tested.
1045
 * It should be full path, web-absolute (WEB), semi-absolute (REL) or system-absolyte (SYS).
1046
 * @return bool             Returns true when the given path is inside the system, false otherwise.
1047
 */
1048
function api_is_internal_path($path) {
1049
    $path = str_replace('\\', '/', trim($path));
1050
    if (empty($path)) {
1051
        return false;
1052
    }
1053
    if (strpos($path, api_remove_trailing_slash(api_get_path(WEB_PATH))) === 0) {
1054
        return true;
1055
    }
1056
    if (strpos($path, api_remove_trailing_slash(api_get_path(SYS_PATH))) === 0) {
1057
        return true;
1058
    }
1059
    $server_base_web = api_remove_trailing_slash(api_get_path(REL_PATH));
1060
    $server_base_web = empty($server_base_web) ? '/' : $server_base_web;
1061
    if (strpos($path, $server_base_web) === 0) {
1062
        return true;
1063
    }
1064
    return false;
1065
}
1066
1067
/**
1068
 * Adds to a given path a trailing slash if it is necessary (adds "/" character at the end of the string).
1069
 * @param string $path          The input path.
1070
 * @return string               Returns the modified path.
1071
 */
1072
function api_add_trailing_slash($path) {
1073
    return substr($path, -1) == '/' ? $path : $path.'/';
1074
}
1075
1076
/**
1077
 * Removes from a given path the trailing slash if it is necessary (removes "/" character from the end of the string).
1078
 * @param string $path          The input path.
1079
 * @return string               Returns the modified path.
1080
 */
1081
function api_remove_trailing_slash($path) {
1082
    return substr($path, -1) == '/' ? substr($path, 0, -1) : $path;
1083
}
1084
1085
/**
1086
 * Checks the RFC 3986 syntax of a given URL.
1087
 * @param string $url       The URL to be checked.
1088
 * @param bool $absolute    Whether the URL is absolute (beginning with a scheme such as "http:").
1089
 * @return string|false             Returns the URL if it is valid, FALSE otherwise.
1090
 * This function is an adaptation from the function valid_url(), Drupal CMS.
1091
 * @link http://drupal.org
1092
 * Note: The built-in function filter_var($urs, FILTER_VALIDATE_URL) has a bug for some versions of PHP.
1093
 * @link http://bugs.php.net/51192
1094
 */
1095
function api_valid_url($url, $absolute = false) {
1096
    if ($absolute) {
1097
        if (preg_match("
1098
            /^                                                      # Start at the beginning of the text
1099
            (?:ftp|https?|feed):\/\/                                # Look for ftp, http, https or feed schemes
1100
            (?:                                                     # Userinfo (optional) which is typically
1101
                (?:(?:[\w\.\-\+!$&'\(\)*\+,;=]|%[0-9a-f]{2})+:)*    # a username or a username and password
1102
                (?:[\w\.\-\+%!$&'\(\)*\+,;=]|%[0-9a-f]{2})+@        # combination
1103
            )?
1104
            (?:
1105
                (?:[a-z0-9\-\.]|%[0-9a-f]{2})+                      # A domain name or a IPv4 address
1106
                |(?:\[(?:[0-9a-f]{0,4}:)*(?:[0-9a-f]{0,4})\])       # or a well formed IPv6 address
1107
            )
1108
            (?::[0-9]+)?                                            # Server port number (optional)
1109
            (?:[\/|\?]
1110
                (?:[\w#!:\.\?\+=&@$'~*,;\/\(\)\[\]\-]|%[0-9a-f]{2}) # The path and query (optional)
1111
            *)?
1112
            $/xi", $url)) {
1113
            return $url;
1114
        }
1115
        return false;
1116
    } else {
1117
        return preg_match("/^(?:[\w#!:\.\?\+=&@$'~*,;\/\(\)\[\]\-]|%[0-9a-f]{2})+$/i", $url) ? $url : false;
1118
    }
1119
}
1120
1121
/**
1122
 * Checks whether a given string looks roughly like an email address.
1123
 * Tries to use PHP built-in validator in the filter extension (from PHP 5.2), falls back to a reasonably competent regex validator.
1124
 * Conforms approximately to RFC2822
1125
 * @link http://www.hexillion.com/samples/#Regex Original pattern found here
1126
 * This function is an adaptation from the method PHPMailer::ValidateAddress(), PHPMailer module.
1127
 * @link http://phpmailer.worxware.com
1128
 * @param string $address   The e-mail address to be checked.
1129
 * @return mixed            Returns the e-mail if it is valid, FALSE otherwise.
1130
 */
1131
function api_valid_email($address)
1132
{
1133
    return filter_var($address, FILTER_VALIDATE_EMAIL);
1134
    /*
1135
    // disable for now because the results are incoherent - YW 20110926
1136
1137
    if (function_exists('filter_var')) { // Introduced in PHP 5.2.
1138
        return filter_var($address, FILTER_VALIDATE_EMAIL);
1139
    } else {
1140
        return preg_match('/^(?:[\w\!\#\$\%\&\'\*\+\-\/\=\?\^\`\{\|\}\~]+\.)*[\w\!\#\$\%\&\'\*\+\-\/\=\?\^\`\{\|\}\~]+@(?:(?:(?:[a-zA-Z0-9_](?:[a-zA-Z0-9_\-](?!\.)){0,61}[a-zA-Z0-9_-]?\.)+[a-zA-Z0-9_](?:[a-zA-Z0-9_\-](?!$)){0,61}[a-zA-Z0-9_]?)|(?:\[(?:(?:[01]?\d{1,2}|2[0-4]\d|25[0-5])\.){3}(?:[01]?\d{1,2}|2[0-4]\d|25[0-5])\]))$/', $address) ? $address : false;
1141
    }*/
1142
}
1143
1144
1145
/* PROTECTION FUNCTIONS
1146
   Use these functions to protect your scripts. */
1147
1148
/**
1149
 * Function used to protect a course script.
1150
 * The function blocks access when
1151
 * - there is no $_SESSION["_course"] defined; or
1152
 * - $is_allowed_in_course is set to false (this depends on the course
1153
 * visibility and user status).
1154
 *
1155
 * This is only the first proposal, test and improve!
1156
 * @param boolean       Option to print headers when displaying error message. Default: false
1157
 * @param boolean       Whether session admins should be allowed or not.
1158
 * @return boolean      True if the user has access to the current course or is out of a course context, false otherwise
1159
 * @todo replace global variable
1160
 * @author Roan Embrechts
1161
 */
1162
function api_protect_course_script($print_headers = false, $allow_session_admins = false, $allow_drh = false)
1163
{
1164
    $is_allowed_in_course = api_is_allowed_in_course();
1165
1166
    $is_visible = false;
1167
    $course_info = api_get_course_info();
1168
1169
    if (empty($course_info)) {
1170
        api_not_allowed($print_headers);
1171
        return false;
1172
    }
1173
1174
    if (api_is_drh()) {
1175
        return true;
1176
    }
1177
1178
    if (api_is_platform_admin($allow_session_admins)) {
1179
        return true;
1180
    }
1181
    if (isset($course_info) && isset($course_info['visibility'])) {
1182
        switch ($course_info['visibility']) {
1183
            default:
1184 View Code Duplication
            case COURSE_VISIBILITY_CLOSED:
1185
                // Completely closed: the course is only accessible to the teachers. - 0
1186
                if (api_get_user_id() && !api_is_anonymous() && $is_allowed_in_course) {
1187
                    $is_visible = true;
1188
                }
1189
                break;
1190 View Code Duplication
            case COURSE_VISIBILITY_REGISTERED:
1191
                // Private - access authorized to course members only - 1
1192
                if (api_get_user_id() && !api_is_anonymous() && $is_allowed_in_course) {
1193
                    $is_visible = true;
1194
                }
1195
                break;
1196 View Code Duplication
            case COURSE_VISIBILITY_OPEN_PLATFORM:
1197
                // Open - access allowed for users registered on the platform - 2
1198
                if (api_get_user_id() && !api_is_anonymous() && $is_allowed_in_course) {
1199
                    $is_visible = true;
1200
                }
1201
                break;
1202
            case COURSE_VISIBILITY_OPEN_WORLD:
1203
                //Open - access allowed for the whole world - 3
1204
                $is_visible = true;
1205
                break;
1206
            case COURSE_VISIBILITY_HIDDEN:
1207
                //Completely closed: the course is only accessible to the teachers. - 0
1208
                if (api_is_platform_admin()) {
1209
                    $is_visible = true;
1210
                }
1211
                break;
1212
        }
1213
1214
        //If password is set and user is not registered to the course then the course is not visible
1215
        if ($is_allowed_in_course == false &
0 ignored issues
show
Comprehensibility introduced by
Consider adding parentheses for clarity. Current Interpretation: ($is_allowed_in_course =...o['registration_code']), Probably Intended Meaning: $is_allowed_in_course ==...['registration_code']))

When comparing the result of a bit operation, we suggest to add explicit parenthesis and not to rely on PHP’s built-in operator precedence to ensure the code behaves as intended and to make it more readable.

Let’s take a look at these examples:

// Returns always int(0).
return 0 === $foo & 4;
return (0 === $foo) & 4;

// More likely intended return: true/false
return 0 === ($foo & 4);
Loading history...
1216
            isset($course_info['registration_code']) &&
1217
            !empty($course_info['registration_code'])
1218
        ) {
1219
            $is_visible = false;
1220
        }
1221
    }
1222
1223
    //Check session visibility
1224
    $session_id = api_get_session_id();
1225
1226
    if (!empty($session_id)) {
1227
        //$is_allowed_in_course was set in local.inc.php
1228
        if (!$is_allowed_in_course) {
1229
            $is_visible = false;
1230
        }
1231
    }
1232
1233
    if (!$is_visible) {
1234
        api_not_allowed($print_headers);
1235
        return false;
1236
    }
1237
    return true;
1238
}
1239
1240
/**
1241
 * Function used to protect an admin script.
1242
 *
1243
 * The function blocks access when the user has no platform admin rights
1244
 * with an error message printed on default output
1245
 * @param bool Whether to allow session admins as well
1246
 * @param bool Whether to allow HR directors as well
1247
 * @param string An optional message (already passed through get_lang)
1248
 * @return bool True if user is allowed, false otherwise.
1249
 * The function also outputs an error message in case not allowed
1250
 * @author Roan Embrechts (original author)
1251
 */
1252
function api_protect_admin_script($allow_sessions_admins = false, $allow_drh = false, $message = null)
1253
{
1254
    if (!api_is_platform_admin($allow_sessions_admins, $allow_drh)) {
1255
        api_not_allowed(true, $message);
1256
        return false;
1257
    }
1258
    return true;
1259
}
1260
1261
/**
1262
 * Function used to protect a teacher script.
1263
 * The function blocks access when the user has no teacher rights.
1264
 *
1265
 * @author Yoselyn Castillo
1266
 */
1267
function api_protect_teacher_script($allow_sessions_admins = false)
1268
{
1269
    if (!api_is_allowed_to_edit()) {
1270
        api_not_allowed(true);
1271
        return false;
1272
    }
1273
    return true;
1274
}
1275
1276
/**
1277
 * Function used to prevent anonymous users from accessing a script.
1278
 * @param bool|true $printHeaders
1279
 * @author Roan Embrechts
1280
 *
1281
 * @return bool
1282
 */
1283
function api_block_anonymous_users($printHeaders = true)
1284
{
1285
    $user = api_get_user_info();
1286 View Code Duplication
    if (!(isset($user['user_id']) && $user['user_id']) || api_is_anonymous($user['user_id'], true)) {
1287
        api_not_allowed($printHeaders);
1288
        return false;
1289
    }
1290
1291
    return true;
1292
}
1293
1294
/**
1295
 * @return array with the navigator name and version
1296
 */
1297
function api_get_navigator() {
1298
    $navigator = 'Unknown';
1299
    $version = 0;
1300
1301
    if (!isset($_SERVER['HTTP_USER_AGENT'])) {
1302
        return array('name' => 'Unknown', 'version' => '0.0.0');
1303
    }
1304
1305
    if (strpos($_SERVER['HTTP_USER_AGENT'], 'Opera') !== false) {
1306
        $navigator = 'Opera';
1307
        list (, $version) = explode('Opera', $_SERVER['HTTP_USER_AGENT']);
1308 View Code Duplication
    } elseif (strpos($_SERVER['HTTP_USER_AGENT'], 'MSIE') !== false) {
1309
        $navigator = 'Internet Explorer';
1310
        list (, $version) = explode('MSIE', $_SERVER['HTTP_USER_AGENT']);
1311
    } elseif (strpos($_SERVER['HTTP_USER_AGENT'], 'Chrome') !== false) {
1312
        $navigator = 'Chrome';
1313
        list (, $version) = explode('Chrome', $_SERVER['HTTP_USER_AGENT']);
1314
    } elseif (stripos($_SERVER['HTTP_USER_AGENT'], 'safari') !== false) {
1315
        $navigator = 'Safari';
1316
        list (, $version) = explode('Version/', $_SERVER['HTTP_USER_AGENT']);
1317
    } elseif (strpos($_SERVER['HTTP_USER_AGENT'], 'Gecko') !== false) {
1318
        $navigator = 'Mozilla';
1319
        list (, $version) = explode('; rv:', $_SERVER['HTTP_USER_AGENT']);
1320 View Code Duplication
    } elseif (strpos($_SERVER['HTTP_USER_AGENT'], 'Netscape') !== false) {
1321
        $navigator = 'Netscape';
1322
        list (, $version) = explode('Netscape', $_SERVER['HTTP_USER_AGENT']);
1323
    } elseif (strpos($_SERVER['HTTP_USER_AGENT'], 'Konqueror') !== false) {
1324
        $navigator = 'Konqueror';
1325
        list (, $version) = explode('Konqueror', $_SERVER['HTTP_USER_AGENT']);
1326 View Code Duplication
    } elseif (stripos($_SERVER['HTTP_USER_AGENT'], 'applewebkit') !== false) {
1327
        $navigator = 'AppleWebKit';
1328
        list (, $version) = explode('Version/', $_SERVER['HTTP_USER_AGENT']);
1329
    }
1330
    $version = str_replace('/', '', $version);
1331
    if (strpos($version, '.') === false) {
1332
        $version = number_format(doubleval($version), 1);
1333
    }
1334
    $return = array('name' => $navigator, 'version' => $version);
1335
    return $return;
1336
}
1337
1338
/**
1339
 * @return True if user self registration is allowed, false otherwise.
1340
 */
1341
function api_is_self_registration_allowed()
1342
{
1343
    return isset($GLOBALS['allowSelfReg']) ? $GLOBALS['allowSelfReg'] : false;
1344
}
1345
1346
/**
1347
 * This function returns the id of the user which is stored in the $_user array.
1348
 *
1349
 * example: The function can be used to check if a user is logged in
1350
 *          if (api_get_user_id())
1351
 * @return integer the id of the current user, 0 if is empty
1352
 */
1353
function api_get_user_id()
1354
{
1355
    return empty($GLOBALS['_user']['user_id']) ? 0 : intval($GLOBALS['_user']['user_id']);
1356
}
1357
1358
/**
1359
 * Gets the list of courses a specific user is subscribed to
1360
 * @param int       User ID
1361
 * @param boolean   $fetch_session Whether to get session courses or not - NOT YET IMPLEMENTED
1362
 * @return array    Array of courses in the form [0]=>('code'=>xxx,'db'=>xxx,'dir'=>xxx,'status'=>d)
1363
 */
1364
function api_get_user_courses($userid, $fetch_session = true)
1365
{
1366
    // Get out if not integer
1367
    if ($userid != strval(intval($userid))) {
1368
        return array();
1369
    }
1370
1371
    $t_course = Database::get_main_table(TABLE_MAIN_COURSE);
1372
    $t_course_user = Database::get_main_table(TABLE_MAIN_COURSE_USER);
1373
1374
    $sql = "SELECT cc.id as real_id, cc.code code, cc.directory dir, cu.status status
1375
            FROM    $t_course       cc,
1376
                    $t_course_user   cu
1377
            WHERE
1378
                cc.id = cu.c_id AND
1379
                cu.user_id = '".$userid."' AND
1380
                cu.relation_type<>".COURSE_RELATION_TYPE_RRHH." ";
1381
    $result = Database::query($sql);
1382
    if ($result === false) {
1383
        return array();
1384
    }
1385
1386
    $courses = array();
1387
    while ($row = Database::fetch_array($result)) {
1388
        // we only need the database name of the course
1389
        $courses[] = $row;
1390
    }
1391
1392
    return $courses;
1393
}
1394
1395
/**
1396
 * Formats user information into a standard array
1397
 * This function should be only used inside api_get_user_info()
1398
 *
1399
 * @param array Non-standard user array
1400
 * @param bool $add_password
1401
 *
1402
 * @return array Standard user array
1403
 */
1404
function _api_format_user($user, $add_password = false)
1405
{
1406
    $result = array();
1407
1408
    $firstname = null;
1409
    $lastname = null;
1410
1411
    if (isset($user['firstname']) && isset($user['lastname'])) {
1412
        $firstname = $user['firstname'];
1413
        $lastname = $user['lastname'];
1414
    } elseif (isset($user['firstName']) && isset($user['lastName'])) {
1415
        $firstname = isset($user['firstName']) ? $user['firstName'] : null;
1416
        $lastname = isset($user['lastName']) ? $user['lastName'] : null;
1417
    }
1418
1419
    $result['complete_name'] = api_get_person_name($firstname, $lastname);
1420
1421
    $result['complete_name_with_username'] = $result['complete_name'];
1422
1423
    if (!empty($user['username'])) {
1424
        $result['complete_name_with_username'] = $result['complete_name'].' ('.$user['username'].')';
1425
    }
1426
1427
    $result['firstname'] = $firstname;
1428
    $result['lastname'] = $lastname;
1429
1430
    // Kept for historical reasons
1431
    $result['firstName'] = $firstname;
1432
    $result['lastName'] = $lastname;
1433
1434
    $attributes = array(
1435
        'phone',
1436
        'picture_uri',
1437
        'official_code',
1438
        'status',
1439
        'active',
1440
        'auth_source',
1441
        'username',
1442
        'theme',
1443
        'language',
1444
        'creator_id',
1445
        'registration_date',
1446
        'hr_dept_id',
1447
        'expiration_date',
1448
        'last_login'
1449
    );
1450
1451
    foreach ($attributes as $attribute) {
1452
        $result[$attribute] = isset($user[$attribute]) ? $user[$attribute] : null;
1453
    }
1454
1455
    if (isset($user['email'])) {
1456
        $result['mail'] = isset($user['email']) ? $user['email'] : null;
1457
        $result['email'] = isset($user['email'])? $user['email'] : null;
1458
    } else {
1459
        $result['mail'] = isset($user['mail']) ? $user['mail'] : null;
1460
        $result['email'] = isset($user['mail'])? $user['mail'] : null;
1461
    }
1462
    $user_id = intval($user['user_id']);
1463
    // Maintain the user_id index for backwards compatibility
1464
    $result['user_id'] = $result['id'] = $user_id;
1465
1466
    // Getting user avatar.
1467
    $originalFile = UserManager::getUserPicture($user_id, USER_IMAGE_SIZE_ORIGINAL, $result);
1468
    $smallFile = UserManager::getUserPicture($user_id, USER_IMAGE_SIZE_SMALL, $result);
1469
1470
    $result['avatar'] = $originalFile;
1471
    $avatarString = explode('?', $originalFile);
1472
    $result['avatar_no_query'] = reset($avatarString);
1473
    $result['avatar_small'] = $smallFile;
1474
1475
    if (isset($user['user_is_online'])) {
1476
        $result['user_is_online'] = $user['user_is_online'] == true ? 1 : 0;
1477
    }
1478
    if (isset($user['user_is_online_in_chat'])) {
1479
        $result['user_is_online_in_chat'] = intval($user['user_is_online_in_chat']);
1480
    }
1481
1482
    if ($add_password) {
1483
        $result['password'] = $user['password'];
1484
    }
1485
1486
    $result['profile_url'] = api_get_path(WEB_CODE_PATH).'social/profile.php?u='.$user_id;
1487
1488
    if (isset($user['extra'])) {
1489
        $result['extra'] = $user['extra'];
1490
    }
1491
1492
    return $result;
1493
}
1494
1495
/**
1496
 * Finds all the information about a user.
1497
 * If no parameter is passed you find all the information about the current user.
1498
 * @param int  $user_id
1499
 * @param bool $checkIfUserOnline
1500
 * @param bool $showPassword
1501
 * @param bool $loadExtraData
1502
 * @param bool $loadOnlyVisibleExtraData Get the user extra fields that are visible
1503
 * @return array $user_info user_id, lastname, firstname, username, email, etc
1504
 * @author Patrick Cool <[email protected]>
1505
 * @author Julio Montoya
1506
 * @version 21 September 2004
1507
 */
1508
function api_get_user_info(
1509
    $user_id = 0,
1510
    $checkIfUserOnline = false,
1511
    $showPassword = false,
1512
    $loadExtraData = false,
1513
    $loadOnlyVisibleExtraData = false
1514
) {
1515
    if (empty($user_id)) {
1516
        $userFromSession = Session::read('_user');
1517
        if (isset($userFromSession)) {
1518
            return _api_format_user($userFromSession);
1519
        }
1520
        // @todo trigger an exception here
1521
        return false;
1522
    }
1523
1524
    $sql = "SELECT * FROM ".Database :: get_main_table(TABLE_MAIN_USER)."
1525
            WHERE id='".intval($user_id)."'";
1526
    $result = Database::query($sql);
1527
    if (Database::num_rows($result) > 0) {
1528
        $result_array = Database::fetch_array($result);
1529
        if ($checkIfUserOnline) {
1530
            $use_status_in_platform = user_is_online($user_id);
1531
1532
            $result_array['user_is_online'] = $use_status_in_platform;
1533
            $user_online_in_chat = 0;
1534
1535
            if ($use_status_in_platform) {
1536
                $user_status = UserManager::get_extra_user_data_by_field(
1537
                    $user_id,
1538
                    'user_chat_status',
1539
                    false,
1540
                    true
1541
                );
1542
                if (intval($user_status['user_chat_status']) == 1) {
1543
                    $user_online_in_chat = 1;
1544
                }
1545
            }
1546
            $result_array['user_is_online_in_chat'] = $user_online_in_chat;
1547
        }
1548
1549
        if ($loadExtraData) {
1550
            $fieldValue = new ExtraFieldValue('user');
1551
1552
            $result_array['extra'] = $fieldValue->getAllValuesForAnItem(
1553
                $user_id,
1554
                $loadOnlyVisibleExtraData
1555
            );
1556
        }
1557
        $user = _api_format_user($result_array, $showPassword);
1558
1559
        return $user;
1560
    }
1561
    return false;
1562
}
1563
1564
/**
1565
 * Finds all the information about a user from username instead of user id
1566
 * @param string $username
1567
 * @return array $user_info array user_id, lastname, firstname, username, email
1568
 * @author Yannick Warnier <[email protected]>
1569
 */
1570 View Code Duplication
function api_get_user_info_from_username($username = '')
1571
{
1572
    if (empty($username)) {
1573
        return false;
1574
    }
1575
    $username = trim($username);
1576
1577
    $sql = "SELECT * FROM ".Database :: get_main_table(TABLE_MAIN_USER)."
1578
            WHERE username='".Database::escape_string($username)."'";
1579
    $result = Database::query($sql);
1580
    if (Database::num_rows($result) > 0) {
1581
        $result_array = Database::fetch_array($result);
1582
        return _api_format_user($result_array);
1583
    }
1584
    return false;
1585
}
1586
1587
/**
1588
 * Get first user with an email
1589
 * @param string $email
1590
 * @return array|bool
1591
 */
1592 View Code Duplication
function api_get_user_info_from_email($email = '')
1593
{
1594
    if (empty($email)) {
1595
        return false;
1596
    }
1597
    $sql = "SELECT * FROM ".Database :: get_main_table(TABLE_MAIN_USER)."
1598
            WHERE email ='".Database::escape_string($email)."' LIMIT 1";
1599
    $result = Database::query($sql);
1600
    if (Database::num_rows($result) > 0) {
1601
        $result_array = Database::fetch_array($result);
1602
        return _api_format_user($result_array);
1603
    }
1604
1605
    return false;
1606
}
1607
1608
/**
1609
 * @return string
1610
 */
1611
function api_get_course_id()
1612
{
1613
    return Session::read('_cid', null);
1614
}
1615
1616
/**
1617
 * Returns the current course id
1618
 * @return int
1619
 */
1620
function api_get_real_course_id()
1621
{
1622
    return api_get_course_int_id();
1623
}
1624
1625
/**
1626
 * Returns the current course id (integer)
1627
 * @param   string  $code   Optional course code
1628
 * @return int
1629
 */
1630
function api_get_course_int_id($code = null)
1631
{
1632 View Code Duplication
    if (!empty($code)) {
1633
        $code = Database::escape_string($code);
1634
        $row = Database::select(
1635
            'id',
1636
            Database::get_main_table(TABLE_MAIN_COURSE),
1637
            array('where'=> array('code = ?' => array($code))),
1638
            'first'
1639
        );
1640
1641
        if (is_array($row) && isset($row['id'])) {
1642
            return $row['id'];
1643
        } else {
1644
            return false;
1645
        }
1646
    }
1647
    return Session::read('_real_cid', 0);
1648
}
1649
1650
/**
1651
 * Returns the current course directory
1652
 *
1653
 * This function relies on api_get_course_info()
1654
 * @param string    The course code - optional (takes it from session if not given)
1655
 * @return string   The directory where the course is located inside the Chamilo "courses" directory
1656
 * @author Yannick Warnier <[email protected]>
1657
 */
1658
function api_get_course_path($course_code = null)
1659
{
1660
    $info = !empty($course_code) ? api_get_course_info($course_code) : api_get_course_info();
1661
    return $info['path'];
1662
}
1663
1664
/**
1665
 * Gets a course setting from the current course_setting table. Try always using integer values.
1666
 * @param string    The name of the setting we want from the table
1667
 * @param string    Optional: course code
1668
 * @param string $setting_name
1669
 * @return mixed    The value of that setting in that table. Return -1 if not found.
1670
 */
1671
function api_get_course_setting($setting_name, $course_code = null)
1672
{
1673
    $course_info = api_get_course_info($course_code);
1674
    $table = Database::get_course_table(TABLE_COURSE_SETTING);
1675
    $setting_name = Database::escape_string($setting_name);
1676 View Code Duplication
    if (!empty($course_info['real_id']) && !empty($setting_name)) {
1677
        $sql = "SELECT value FROM $table
1678
                WHERE c_id = {$course_info['real_id']} AND variable = '$setting_name'";
1679
        $res = Database::query($sql);
1680
        if (Database::num_rows($res) > 0) {
1681
            $row = Database::fetch_array($res);
1682
            return $row['value'];
1683
        }
1684
    }
1685
    return -1;
1686
}
1687
1688
/**
1689
 * Gets an anonymous user ID
1690
 *
1691
 * For some tools that need tracking, like the learnpath tool, it is necessary
1692
 * to have a usable user-id to enable some kind of tracking, even if not
1693
 * perfect. An anonymous ID is taken from the users table by looking for a
1694
 * status of "6" (anonymous).
1695
 * @return int  User ID of the anonymous user, or O if no anonymous user found
1696
 */
1697
function api_get_anonymous_id()
1698
{
1699
    $table = Database::get_main_table(TABLE_MAIN_USER);
1700
    $sql = "SELECT user_id FROM $table WHERE status = ".ANONYMOUS;
1701
    $res = Database::query($sql);
1702
    if (Database::num_rows($res) > 0) {
1703
        $row = Database::fetch_array($res);
1704
        return $row['user_id'];
1705
    }
1706
1707
    // No anonymous user was found.
1708
    return 0;
1709
}
1710
1711
/**
1712
 * Returns the cidreq parameter name + current course id taken from
1713
 * $GLOBALS['_cid'] and returns a string like 'cidReq=ABC&id_session=123
1714
 *
1715
 * @param bool $addSessionId
1716
 * @param bool $addGroupId
1717
 * @return  string  Course & session references to add to a URL
1718
 *
1719
 */
1720
function api_get_cidreq($addSessionId = true, $addGroupId = true)
1721
{
1722
    $courseCode = api_get_course_id();
1723
    $url = empty($courseCode) ? '' : 'cidReq='.htmlspecialchars($courseCode);
1724
    $origin = api_get_origin();
1725
1726
    if ($addSessionId) {
1727
        if (!empty($url)) {
1728
            $url .= api_get_session_id() == 0 ? '&id_session=0' : '&id_session='.api_get_session_id();
1729
        }
1730
    }
1731
1732
    if ($addGroupId) {
1733
        if (!empty($url)) {
1734
            $url .= api_get_group_id() == 0 ? '&gidReq=0' : '&gidReq='.api_get_group_id();
1735
        }
1736
    }
1737
1738
    if (!empty($url)) {
1739
        $url .= '&gradebook='.intval(api_is_in_gradebook());
1740
        $url .= '&origin='.$origin;
1741
    }
1742
1743
    return $url;
1744
}
1745
1746
function api_is_in_gradebook()
1747
{
1748
    return Session::read('in_gradebook', false);
1749
}
1750
1751
function api_set_in_gradebook()
1752
{
1753
    Session::write('in_gradebook', true);
1754
}
1755
1756
function api_remove_in_gradebook()
1757
{
1758
    Session::erase('in_gradebook');
1759
}
1760
1761
/**
1762
 * Returns the current course info array see api_format_course_array()
1763
 * If the course_code is given, the returned array gives info about that
1764
 * particular course, if none given it gets the course info from the session.
1765
 *
1766
 * @param string $course_code
1767
 * @param bool $strict
1768
 *
1769
 * @return array
1770
 */
1771
function api_get_course_info($course_code = null, $strict = false)
1772
{
1773
    if (!empty($course_code)) {
1774
        $course_code = Database::escape_string($course_code);
1775
        $courseId = api_get_course_int_id($course_code);
1776
1777
        if (empty($courseId)) {
1778
            return array();
1779
        }
1780
1781
        $course_table = Database::get_main_table(TABLE_MAIN_COURSE);
1782
        $course_cat_table = Database::get_main_table(TABLE_MAIN_CATEGORY);
1783
        $sql = "SELECT
1784
                    course.*,
1785
                    course_category.code faCode,
1786
                    course_category.name faName
1787
                FROM $course_table
1788
                LEFT JOIN $course_cat_table
1789
                ON course.category_code = course_category.code
1790
                WHERE course.id = $courseId";
1791
        $result = Database::query($sql);
1792
        $courseInfo = array();
1793
        if (Database::num_rows($result) > 0) {
1794
            $data = Database::fetch_array($result);
1795
            $courseInfo = api_format_course_array($data);
1796
        }
1797
1798
        return $courseInfo;
1799
    }
1800
1801
    global $_course;
1802
    if ($_course == '-1') {
1803
        $_course = array();
1804
    }
1805
1806
    return $_course;
1807
}
1808
1809
/**
1810
 * Returns the current course info array.
1811
1812
 * Now if the course_code is given, the returned array gives info about that
1813
 * particular course, not specially the current one.
1814
 * @param int $id Numeric ID of the course
1815
 * @return array The course info as an array formatted by api_format_course_array, including category.name
1816
 */
1817 View Code Duplication
function api_get_course_info_by_id($id = null)
1818
{
1819
    if (!empty($id)) {
1820
        $id = intval($id);
1821
        $course_table = Database::get_main_table(TABLE_MAIN_COURSE);
1822
        $course_cat_table = Database::get_main_table(TABLE_MAIN_CATEGORY);
1823
        $sql = "SELECT
1824
                    course.*,
1825
                    course_category.code faCode,
1826
                    course_category.name faName
1827
                FROM $course_table
1828
                LEFT JOIN $course_cat_table
1829
                ON course.category_code =  course_category.code
1830
                WHERE course.id = $id";
1831
        $result = Database::query($sql);
1832
        $_course = array();
1833
        if (Database::num_rows($result) > 0) {
1834
            $course_data = Database::fetch_array($result);
1835
            $_course = api_format_course_array($course_data);
1836
        }
1837
        return $_course;
1838
    }
1839
1840
    global $_course;
1841
    if ($_course == '-1') $_course = array();
1842
    return $_course;
1843
}
1844
1845
/**
1846
 * Reformat the course array (output by api_get_course_info()) in order, mostly,
1847
 * to switch from 'code' to 'id' in the array. This is a legacy feature and is
1848
 * now possibly causing massive confusion as a new "id" field has been added to
1849
 * the course table in 1.9.0.
1850
 * @param $course_data
1851
 * @return array
1852
 * @todo eradicate the false "id"=code field of the $_course array and use the int id
1853
 */
1854
function api_format_course_array($course_data)
1855
{
1856
    if (empty($course_data)) {
1857
        return array();
1858
    }
1859
1860
    $_course = array();
1861
    $_course['id'] = $course_data['code'];
1862
    $_course['real_id'] = $course_data['id'];
1863
1864
    // Added
1865
    $_course['code'] = $course_data['code'];
1866
    $_course['name'] = $course_data['title'];
1867
    $_course['title'] = $course_data['title'];
1868
    $_course['official_code'] = $course_data['visual_code'];
1869
    $_course['visual_code'] = $course_data['visual_code'];
1870
    $_course['sysCode'] = $course_data['code'];
1871
    $_course['path'] = $course_data['directory']; // Use as key in path.
1872
    $_course['directory'] = $course_data['directory'];
1873
    $_course['creation_date'] = $course_data['creation_date'];
1874
    $_course['titular'] = $course_data['tutor_name'];
1875
    $_course['language'] = $course_data['course_language'];
1876
    $_course['extLink']['url'] = $course_data['department_url'];
1877
    $_course['extLink']['name'] = $course_data['department_name'];
1878
    $_course['categoryCode'] = $course_data['faCode'];
1879
    $_course['categoryName'] = $course_data['faName'];
1880
    $_course['visibility'] = $course_data['visibility'];
1881
    $_course['subscribe_allowed'] = $course_data['subscribe'];
1882
    $_course['subscribe'] = $course_data['subscribe'];
1883
    $_course['unsubscribe'] = $course_data['unsubscribe'];
1884
    $_course['course_language'] = $course_data['course_language'];
1885
    $_course['activate_legal'] = isset($course_data['activate_legal']) ? $course_data['activate_legal'] : false;
1886
    $_course['legal'] = $course_data['legal'];
1887
    $_course['show_score'] = $course_data['show_score']; //used in the work tool
1888
    $_course['department_name'] = $course_data['department_name'];
1889
    $_course['department_url'] = $course_data['department_url'];
1890
1891
    // Course password
1892
    $_course['registration_code'] = !empty($course_data['registration_code']) ? sha1($course_data['registration_code']) : null;
1893
    $_course['disk_quota'] = $course_data['disk_quota'];
1894
    $_course['course_public_url'] = api_get_path(WEB_COURSE_PATH).$course_data['directory'].'/index.php';
1895
1896
    if (array_key_exists('add_teachers_to_sessions_courses', $course_data)) {
1897
        $_course['add_teachers_to_sessions_courses'] = $course_data['add_teachers_to_sessions_courses'];
1898
    }
1899
1900
    if (file_exists(api_get_path(SYS_COURSE_PATH).$course_data['directory'].'/course-pic85x85.png')) {
1901
        $url_image = api_get_path(WEB_COURSE_PATH).$course_data['directory'].'/course-pic85x85.png';
1902
    } else {
1903
        $url_image = Display::return_icon('course.png', null, null, ICON_SIZE_BIG, null, true, false);
1904
    }
1905
    $_course['course_image'] = $url_image;
1906
1907
    if (file_exists(api_get_path(SYS_COURSE_PATH).$course_data['directory'].'/course-pic.png')) {
1908
        $url_image = api_get_path(WEB_COURSE_PATH).$course_data['directory'].'/course-pic.png';
1909
    } else {
1910
        $url_image = Display::returnIconPath('session_default.png');
1911
    }
1912
    $_course['course_image_large'] = $url_image;
1913
1914
    return $_course;
1915
}
1916
1917
/**
1918
 * Add a parameter to the existing URL. If this parameter already exists,
1919
 * just replace it with the new value
1920
 * @param   string  The URL
1921
 * @param   string  param=value string
1922
 * @param   boolean Whether to filter XSS or not
1923
 * @return  string  The URL with the added parameter
1924
 */
1925
function api_add_url_param($url, $param, $filter_xss = true) {
1926
    if (empty($param)) {
1927
        return $url;
1928
    }
1929
    if (strpos($url, '?') !== false) {
1930
        if ($param[0] != '&') {
1931
            $param = '&'.$param;
1932
        }
1933
        list (, $query_string) = explode('?', $url);
1934
        $param_list1 = explode('&', $param);
1935
        $param_list2 = explode('&', $query_string);
1936
        $param_list1_keys = $param_list1_vals = array();
1937
        foreach ($param_list1 as $key => $enreg) {
1938
            list ($param_list1_keys[$key], $param_list1_vals[$key]) = explode('=', $enreg);
1939
        }
1940
        $param_list1 = array ('keys' => $param_list1_keys, 'vals' => $param_list1_vals);
1941
        foreach ($param_list2 as $enreg) {
1942
            $enreg = explode('=', $enreg);
1943
            $key = array_search($enreg[0], $param_list1['keys']);
1944
            if (!is_null($key) && !is_bool($key)) {
1945
                $url = str_replace($enreg[0].'='.$enreg[1], $enreg[0].'='.$param_list1['vals'][$key], $url);
1946
                $param = str_replace('&'.$enreg[0].'='.$param_list1['vals'][$key], '', $param);
1947
            }
1948
        }
1949
        $url .= $param;
1950
    } else {
1951
        $url = $url.'?'.$param;
1952
    }
1953
    if ($filter_xss === true) {
1954
        $url = Security::remove_XSS(urldecode($url));
1955
    }
1956
    return $url;
1957
}
1958
1959
/**
1960
 * Returns a difficult to guess password.
1961
 * @param int $length, the length of the password
0 ignored issues
show
Documentation introduced by
There is no parameter named $length,. Did you maybe mean $length?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function. It has, however, found a similar but not annotated parameter which might be a good fit.

Consider the following example. The parameter $ireland is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $ireland
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was changed, but the annotation was not.

Loading history...
1962
 * @return string the generated password
1963
 */
1964
function api_generate_password($length = 8) {
1965
    $characters = 'abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ23456789';
1966
    if ($length < 2) {
1967
        $length = 2;
1968
    }
1969
    $password = '';
1970
    for ($i = 0; $i < $length; $i ++) {
1971
        $password .= $characters[rand() % strlen($characters)];
1972
    }
1973
    return $password;
1974
}
1975
1976
/**
1977
 * Checks a password to see wether it is OK to use.
1978
 * @param string $password
1979
 * @return boolean if the password is acceptable, false otherwise
1980
 * Notes about what a password "OK to use" is:
1981
 * 1. The password should be at least 5 characters long.
1982
 * 2. Only English letters (uppercase or lowercase, it doesn't matter) and digits are allowed.
1983
 * 3. The password should contain at least 3 letters.
1984
 * 4. It should contain at least 2 digits.
1985
 * 5. It should not contain 3 or more consequent (according to ASCII table) characters.
1986
 */
1987
function api_check_password($password) {
1988
    $password_length = api_strlen($password);
1989
    if ($password_length < 5) {
1990
        return false;
1991
    }
1992
    $password = api_strtolower($password);
1993
    $letters = 0;
1994
    $digits = 0;
1995
    $consequent_characters = 0;
1996
    $previous_character_code = 0;
1997
    for ($i = 0; $i < $password_length; $i ++) {
1998
        $current_character_code = api_ord(api_substr($password, $i, 1));
0 ignored issues
show
Bug introduced by
The call to api_ord() misses a required argument $encoding.

This check looks for function calls that miss required arguments.

Loading history...
Security Bug introduced by
It seems like api_substr($password, $i, 1) targeting api_substr() can also be of type false; however, api_ord() does only seem to accept string, did you maybe forget to handle an error condition?
Loading history...
1999
        if ($i && abs($current_character_code - $previous_character_code) <= 1) {
2000
            $consequent_characters ++;
2001
            if ($consequent_characters == 3) {
2002
                return false;
2003
            }
2004
        } else {
2005
            $consequent_characters = 1;
2006
        }
2007
        if ($current_character_code >= 97 && $current_character_code <= 122) {
2008
            $letters ++;
2009
        } elseif ($current_character_code >= 48 && $current_character_code <= 57) {
2010
            $digits ++;
2011
        } else {
2012
            return false;
2013
        }
2014
        $previous_character_code = $current_character_code;
2015
    }
2016
    return ($letters >= 3 && $digits >= 2);
2017
}
2018
2019
/**
2020
 * Clears the user ID from the session if it was the anonymous user. Generally
2021
 * used on out-of-tools pages to remove a user ID that could otherwise be used
2022
 * in the wrong context.
2023
 * This function is to be used in conjunction with the api_set_anonymous()
2024
 * function to simulate the user existence in case of an anonymous visit.
2025
 * @param bool      database check switch - passed to api_is_anonymous()
2026
 * @return bool     true if succesfully unregistered, false if not anonymous.
2027
 */
2028
function api_clear_anonymous($db_check = false) {
2029
    global $_user;
2030
    if (api_is_anonymous($_user['user_id'], $db_check)) {
2031
        unset($_user['user_id']);
2032
        Session::erase('_uid');
2033
        return true;
2034
    }
2035
    return false;
2036
}
2037
2038
/**
2039
 * Returns the status string corresponding to the status code
2040
 * @author Noel Dieschburg
2041
 * @param the int status code
2042
 */
2043
function get_status_from_code($status_code) {
2044
    switch ($status_code) {
2045
        case STUDENT:
2046
            return get_lang('Student', '');
2047
        case TEACHER:
2048
            return get_lang('Teacher', '');
2049
        case COURSEMANAGER:
2050
            return get_lang('Manager', '');
2051
        case SESSIONADMIN:
2052
            return get_lang('SessionsAdmin', '');
2053
        case DRH:
2054
            return get_lang('Drh', '');
2055
    }
2056
}
2057
2058
/* FAILURE MANAGEMENT */
2059
2060
/**
2061
 * The Failure Management module is here to compensate
2062
 * the absence of an 'exception' device in PHP 4.
2063
 */
2064
2065
/**
2066
 * $api_failureList - array containing all the failure recorded in order of arrival.
2067
 */
2068
$api_failureList = array();
2069
2070
/**
2071
 * Fills a global array called $api_failureList
2072
 * This array collects all the failure occuring during the script runs
2073
 * The main purpose is allowing to manage the display messages externaly
2074
 * from the functions or objects. This strengthens encupsalation principle
2075
 *
2076
 * @author Hugues Peeters <[email protected]>
2077
 * @param  string $failure_type - the type of failure
2078
 * global: array $api_failureList
2079
 * @return boolean false to stay consistent with the main script
2080
 */
2081
function api_set_failure($failure_type) {
2082
    global $api_failureList;
2083
    $api_failureList[] = $failure_type;
2084
    return false;
2085
}
2086
2087
/**
2088
 * Sets the current user as anonymous if it hasn't been identified yet. This
2089
 * function should be used inside a tool only. The function api_clear_anonymous()
2090
 * acts in the opposite direction by clearing the anonymous user's data every
2091
 * time we get on a course homepage or on a neutral page (index, admin, my space)
2092
 * @return bool     true if set user as anonymous, false if user was already logged in or anonymous id could not be found
2093
 */
2094
function api_set_anonymous() {
2095
    global $_user;
2096
2097
    if (!empty($_user['user_id'])) {
2098
        return false;
2099
    }
2100
2101
    $user_id = api_get_anonymous_id();
2102
    if ($user_id == 0) {
2103
        return false;
2104
    }
2105
    Session::erase('_user');
2106
    $_user['user_id'] = $user_id;
2107
    $_user['is_anonymous'] = true;
2108
    $GLOBALS['_user'] = $_user;
2109
    Session::write('_user', $_user);
2110
    return true;
2111
}
2112
2113
/**
2114
 * Gets the last failure stored in $api_failureList;
2115
 *
2116
 * @author Hugues Peeters <[email protected]>
2117
 * @param void
2118
 * @return string - the last failure stored
2119
 */
2120
function api_get_last_failure() {
2121
    global $api_failureList;
2122
    return $api_failureList[count($api_failureList) - 1];
2123
}
2124
2125
/**
2126
 * Collects and manages failures occurring during script execution
2127
 * The main purpose is allowing to manage the display messages externally
2128
 * from functions or objects. This strengthens encapsulation principle
2129
 *
2130
 * @author Hugues Peeters <[email protected]>
2131
 * @package chamilo.library
2132
 */
2133
class api_failure {
2134
2135
    // TODO: $api_failureList to be hidden from global scope and to be renamed according to our coding conventions.
2136
    /**
2137
     * IMPLEMENTATION NOTE : For now the $api_failureList list is set to the
2138
     * global scope, as PHP 4 is unable to manage static variable in class. But
2139
     * this feature is awaited in PHP 5. The class is already written to minize
2140
     * the change when static class variable will be possible. And the API won't
2141
     * change.
2142
     */
2143
    public $api_failureList = array();
2144
2145
    /**
2146
     * Piles the last failure in the failure list
2147
     *
2148
     * @author Hugues Peeters <[email protected]>
2149
     * @param  string $failure_type - the type of failure
2150
     * @global array  $api_failureList
2151
     * @return boolean false to stay consistent with the main script
2152
     */
2153
    static function set_failure($failure_type) {
2154
        global $api_failureList;
2155
        $api_failureList[] = $failure_type;
2156
        return false;
2157
    }
2158
2159
    /**
2160
     * Gets the last failure stored
2161
     *
2162
     * @author Hugues Peeters <[email protected]>
2163
     * @param void
2164
     * @return string - the last failure stored
2165
     */
2166
    static function get_last_failure() {
2167
        global $api_failureList;
2168
        if (count($api_failureList) == 0) { return ''; }
2169
        return $api_failureList[count($api_failureList) - 1];
2170
    }
2171
}
2172
2173
2174
/* CONFIGURATION SETTINGS */
2175
2176
/**
2177
 * Gets the current Chamilo (not PHP/cookie) session ID
2178
 * @return  int     O if no active session, the session ID otherwise
2179
 */
2180
function api_get_session_id()
2181
{
2182
    return Session::read('id_session', 0);
2183
}
2184
2185
/**
2186
 * Gets the current Chamilo (not social network) group ID
2187
 * @return  int     O if no active session, the session ID otherwise
2188
 */
2189
function api_get_group_id()
2190
{
2191
    return Session::read('_gid', 0);
2192
}
2193
2194
2195
/**
2196
 * Gets the current or given session name
2197
 * @param   int     Session ID (optional)
2198
 * @return  string  The session name, or null if unfound
2199
 */
2200
function api_get_session_name($session_id) {
2201
    if (empty($session_id)) {
2202
        $session_id = api_get_session_id();
2203
        if (empty($session_id)) { return null; }
2204
    }
2205
    $t = Database::get_main_table(TABLE_MAIN_SESSION);
2206
    $s = "SELECT name FROM $t WHERE id = ".(int)$session_id;
2207
    $r = Database::query($s);
2208
    $c = Database::num_rows($r);
2209
    if ($c > 0) {
2210
        //technically, there can be only one, but anyway we take the first
2211
        $rec = Database::fetch_array($r);
2212
        return $rec['name'];
2213
    }
2214
    return null;
2215
}
2216
2217
/**
2218
 * Gets the session info by id
2219
 * @param int       Session ID
2220
 * @return array    information of the session
2221
 */
2222
function api_get_session_info($session_id)
2223
{
2224
    $data = array();
2225
    if (!empty($session_id)) {
2226
        $session_id = intval($session_id);
2227
        $tbl_session = Database::get_main_table(TABLE_MAIN_SESSION);
2228
        $sql = "SELECT * FROM $tbl_session WHERE id = $session_id";
2229
        $result = Database::query($sql);
2230
2231
        if (Database::num_rows($result)>0) {
2232
            $data = Database::fetch_array($result, 'ASSOC');
2233
        }
2234
    }
2235
2236
    return $data;
2237
}
2238
2239
/**
2240
 * Gets the session visibility by session id
2241
 * @param int $session_id
2242
 * @param int $courseId
2243
 * @param bool $ignore_visibility_for_admins
2244
 * @return int
2245
 *  0 = session still available,
2246
 *  SESSION_VISIBLE_READ_ONLY = 1,
2247
 *  SESSION_VISIBLE = 2,
2248
 *  SESSION_INVISIBLE = 3
2249
 */
2250
function api_get_session_visibility(
2251
    $session_id,
2252
    $courseId = null,
2253
    $ignore_visibility_for_admins = true
2254
) {
2255
    // Means that the session is still available.
2256
    $visibility = 0;
2257
2258
    if (api_is_platform_admin()) {
2259
        if ($ignore_visibility_for_admins) {
2260
            return SESSION_AVAILABLE;
2261
        }
2262
    }
2263
2264
    $now = time();
2265
    if (!empty($session_id)) {
2266
        $session_id = intval($session_id);
2267
        $tbl_session = Database::get_main_table(TABLE_MAIN_SESSION);
2268
2269
        $sql = "SELECT * FROM $tbl_session
2270
                WHERE id = $session_id ";
2271
2272
        $result = Database::query($sql);
2273
2274
        if (Database::num_rows($result) > 0) {
2275
            $row = Database::fetch_array($result, 'ASSOC');
2276
            $visibility = $original_visibility = $row['visibility'];
2277
2278
            // I don't care the session visibility.
2279
            if (empty($row['access_start_date']) && empty($row['access_end_date'])) {
2280
2281
                // Session duration per student.
2282
                if (isset($row['duration']) && !empty($row['duration'])) {
2283
                    $duration = $row['duration'] * 24 * 60 * 60;
2284
2285
                    $courseAccess = CourseManager::getFirstCourseAccessPerSessionAndUser(
2286
                        $session_id,
2287
                        api_get_user_id()
2288
                    );
2289
2290
                    // If there is a session duration but there is no previous
2291
                    // access by the user, then the session is still available
2292
                    if (count($courseAccess) == 0) {
2293
                        return SESSION_AVAILABLE;
2294
                    }
2295
2296
                    $currentTime = time();
2297
                    $firstAccess = 0;
2298
                    if (isset($courseAccess['login_course_date'])) {
2299
                        $firstAccess = api_strtotime(
2300
                            $courseAccess['login_course_date'],
2301
                            'UTC'
2302
                        );
2303
                    }
2304
                    $userDurationData = SessionManager::getUserSession(
2305
                        api_get_user_id(),
2306
                        $session_id
2307
                    );
2308
                    $userDuration = 0;
2309
                    if (isset($userDurationData['duration'])) {
2310
                        $userDuration = intval($userDurationData['duration']) * 24 * 60 * 60;
2311
                    }
2312
2313
                    $totalDuration = $firstAccess + $duration + $userDuration;
2314
                    if ($totalDuration > $currentTime) {
2315
                        return SESSION_AVAILABLE;
2316
                    } else {
2317
                        return SESSION_INVISIBLE;
2318
                    }
2319
                }
2320
2321
                return SESSION_AVAILABLE;
2322
            } else {
2323
2324
                // If start date was set.
2325
                if (!empty($row['access_start_date'])) {
2326
                    if ($now > api_strtotime($row['access_start_date'], 'UTC')) {
2327
                        $visibility = SESSION_AVAILABLE;
2328
                    } else {
2329
                        $visibility = SESSION_INVISIBLE;
2330
                    }
2331
                }
2332
2333
                // If the end date was set.
2334 View Code Duplication
                if (!empty($row['access_end_date'])) {
2335
                    // Only if date_start said that it was ok
2336
                    if ($visibility == SESSION_AVAILABLE) {
2337
                        if ($now < api_strtotime($row['access_end_date'], 'UTC')) {
2338
                            // Date still available
2339
                            $visibility = SESSION_AVAILABLE;
2340
                        } else {
2341
                            // Session ends
2342
                            $visibility = $row['visibility'];
2343
                        }
2344
                    }
2345
                }
2346
            }
2347
2348
            /* If I'm a coach the visibility can change in my favor depending in
2349
             the coach dates */
2350
            $is_coach = api_is_coach($session_id, $courseId);
2351
2352
            if ($is_coach) {
2353
                // Test end date.
2354 View Code Duplication
                if (!empty($row['coach_access_end_date'])) {
2355
                    $endDateCoach = api_strtotime($row['coach_access_end_date'], 'UTC');
2356
2357
                    if ($endDateCoach >= $now) {
2358
                        $visibility = SESSION_AVAILABLE;
2359
                    } else {
2360
                        $visibility = SESSION_INVISIBLE;
2361
                    }
2362
                }
2363
2364
                // Test start date.
2365 View Code Duplication
                if (!empty($row['coach_access_start_date'])) {
2366
                    $start = api_strtotime($row['coach_access_start_date'], 'UTC');
2367
                    if ($start < $now) {
2368
                        $visibility = SESSION_AVAILABLE;
2369
                    } else {
2370
                        $visibility = SESSION_INVISIBLE;
2371
                    }
2372
                }
2373
            }
2374
        } else {
2375
            $visibility = SESSION_INVISIBLE;
2376
        }
2377
    }
2378
2379
    return $visibility;
2380
}
2381
2382
/**
2383
 * This function returns a (star) session icon if the session is not null and
2384
 * the user is not a student
2385
 * @param int   $session_id
2386
 * @param int   $status_id User status id - if 5 (student), will return empty
2387
 * @return string   Session icon
2388
 */
2389
function api_get_session_image($session_id, $status_id)
2390
{
2391
    $session_id = (int)$session_id;
2392
    $session_img = '';
2393
    if ((int)$status_id != 5) { //check whether is not a student
2394
        if ($session_id > 0) {
2395
            $session_img = "&nbsp;&nbsp;".Display::return_icon(
2396
                'star.png',
2397
                get_lang('SessionSpecificResource'),
2398
                array('align' => 'absmiddle'),
2399
                ICON_SIZE_SMALL
2400
            );
2401
        }
2402
    }
2403
    return $session_img;
2404
}
2405
2406
/**
2407
 * This function add an additional condition according to the session of the course
2408
 * @param int       $session_id session id
2409
 * @param bool      $and optional, true if more than one condition false if the only condition in the query
2410
 * @param bool      $with_base_content optional, true to accept content with session=0 as well, false for strict session condition
2411
 * @return string   condition of the session
2412
 */
2413
function api_get_session_condition(
2414
    $session_id,
2415
    $and = true,
2416
    $with_base_content = false,
2417
    $session_field = "session_id"
2418
) {
2419
    $session_id = intval($session_id);
2420
2421
    if (empty($session_field)) {
2422
        $session_field = "session_id";
2423
    }
2424
    // Condition to show resources by session
2425
    $condition_add = $and ? " AND " : " WHERE ";
2426
2427
    if ($with_base_content) {
2428
        $condition_session = $condition_add." ( $session_field = $session_id OR $session_field = 0 OR $session_field IS NULL) ";
2429
    } else {
2430
        if (empty($session_id)) {
2431
            $condition_session = $condition_add." ($session_field = $session_id OR $session_field IS NULL)";
2432
        } else {
2433
            $condition_session = $condition_add." $session_field = $session_id ";
2434
        }
2435
    }
2436
    return $condition_session;
2437
}
2438
2439
/**
2440
 * This function returns information about coaches from a course in session
2441
 * @param int       optional, session id
2442
 * @param int $courseId
2443
 * @return array     array containing user_id, lastname, firstname, username
2444
 * @deprecated use CourseManager::get_coaches_from_course
2445
 */
2446
function api_get_coachs_from_course($session_id = 0, $courseId = '')
2447
{
2448
    if (!empty($session_id)) {
2449
        $session_id = intval($session_id);
2450
    } else {
2451
        $session_id = api_get_session_id();
2452
    }
2453
2454
    if (!empty($courseId)) {
2455
        $courseId = intval($courseId);
2456
    } else {
2457
        $courseId = api_get_course_int_id();
2458
    }
2459
2460
    $tbl_user = Database:: get_main_table(TABLE_MAIN_USER);
2461
    $tbl_session_course_user = Database:: get_main_table(TABLE_MAIN_SESSION_COURSE_USER);
2462
    $coaches = array();
2463
2464
    $sql = "SELECT
2465
                u.user_id,
2466
                u.lastname,
2467
                u.firstname,
2468
                u.username
2469
            FROM $tbl_user u, $tbl_session_course_user scu
2470
            WHERE
2471
              u.user_id = scu.user_id AND
2472
              scu.session_id = '$session_id' AND
2473
              scu.c_id = '$courseId' AND
2474
              scu.status = 2";
2475
    $rs = Database::query($sql);
2476
2477
    if (Database::num_rows($rs) > 0) {
2478
        while ($row = Database::fetch_array($rs)) {
2479
            $coaches[] = $row;
2480
        }
2481
2482
        return $coaches;
2483
    } else {
2484
2485
        return false;
2486
    }
2487
}
2488
2489
/**
2490
 * Returns the value of a setting from the web-adjustable admin config settings.
2491
 *
2492
 * WARNING true/false are stored as string, so when comparing you need to check e.g.
2493
 * if (api_get_setting('show_navigation_menu') == 'true') //CORRECT
2494
 * instead of
2495
 * if (api_get_setting('show_navigation_menu') == true) //INCORRECT
2496
 * @param string    $variable The variable name
2497
 * @param string    $key The subkey (sub-variable) if any. Defaults to NULL
2498
 * @author René Haentjens
2499
 * @author Bart Mollet
2500
 */
2501
function api_get_setting($variable, $key = null)
2502
{
2503
    global $_setting;
2504 View Code Duplication
    if ($variable == 'header_extra_content') {
2505
        $filename = api_get_path(SYS_PATH).api_get_home_path().'header_extra_content.txt';
2506
        if (file_exists($filename)) {
2507
            $value = file_get_contents($filename);
2508
            return $value ;
2509
        } else {
2510
            return '';
2511
        }
2512
    }
2513 View Code Duplication
    if ($variable == 'footer_extra_content') {
2514
        $filename = api_get_path(SYS_PATH).api_get_home_path().'footer_extra_content.txt';
2515
        if (file_exists($filename)) {
2516
            $value = file_get_contents($filename);
2517
            return $value ;
2518
        } else {
2519
            return '';
2520
        }
2521
    }
2522
    $value = null;
2523
    if (is_null($key)) {
2524
        $value = ((isset($_setting[$variable]) && $_setting[$variable] != '') ? $_setting[$variable] : null);
2525
    } else {
2526
        if (isset($_setting[$variable][$key])) {
2527
            $value = $_setting[$variable][$key];
2528
        }
2529
    }
2530
2531
    return $value;
2532
}
2533
2534
/**
2535
 * @param string $plugin
2536
 * @param string $variable
2537
 * @return string
2538
 */
2539
function api_get_plugin_setting($plugin, $variable)
2540
{
2541
    $variableName = $plugin.'_'.$variable;
2542
    $result = api_get_setting($variableName);
2543
    if (isset($result[$plugin])) {
2544
        return $result[$plugin];
2545
    }
2546
2547
    return null;
2548
}
2549
2550
/**
2551
 * Returns the value of a setting from the web-adjustable admin config settings.
2552
 **/
2553
function api_get_settings_params($params) {
2554
    $table = Database::get_main_table(TABLE_MAIN_SETTINGS_CURRENT);
2555
    $result = Database::select('*', $table, array('where' => $params));
2556
    return $result;
2557
}
2558
2559
function api_get_settings_params_simple($params) {
2560
    $table = Database::get_main_table(TABLE_MAIN_SETTINGS_CURRENT);
2561
    $result = Database::select('*', $table, array('where' => $params), 'one');
2562
    return $result;
2563
}
2564
2565
/**
2566
 * Returns the value of a setting from the web-adjustable admin config settings.
2567
 **/
2568
function api_delete_settings_params($params) {
2569
    $table = Database::get_main_table(TABLE_MAIN_SETTINGS_CURRENT);
2570
    $result = Database::delete($table, $params);
2571
    return $result;
2572
}
2573
2574
/**
2575
 * Returns an escaped version of $_SERVER['PHP_SELF'] to avoid XSS injection
2576
 * @return string   Escaped version of $_SERVER['PHP_SELF']
2577
 */
2578
function api_get_self() {
2579
    return htmlentities($_SERVER['PHP_SELF']);
2580
}
2581
2582
/* USER PERMISSIONS */
2583
2584
/**
2585
 * Checks whether current user is a platform administrator
2586
 * @param boolean Whether session admins should be considered admins or not
2587
 * @param boolean Whether HR directors should be considered admins or not
2588
 * @return boolean True if the user has platform admin rights,
2589
 * false otherwise.
2590
 * @see usermanager::is_admin(user_id) for a user-id specific function
2591
 */
2592
function api_is_platform_admin($allow_sessions_admins = false, $allow_drh = false)
2593
{
2594
    if (isset($_SESSION['is_platformAdmin']) && $_SESSION['is_platformAdmin']) {
2595
        return true;
2596
    }
2597
    $_user = api_get_user_info();
2598
    return
2599
        isset($_user['status']) &&
2600
        (
2601
            ($allow_sessions_admins && $_user['status'] == SESSIONADMIN) ||
2602
            ($allow_drh && $_user['status'] == DRH)
2603
        );
2604
}
2605
2606
/**
2607
 * Checks whether the user given as user id is in the admin table.
2608
 * @param int $user_id. If none provided, will use current user
0 ignored issues
show
Documentation introduced by
There is no parameter named $user_id.. Did you maybe mean $user_id?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function. It has, however, found a similar but not annotated parameter which might be a good fit.

Consider the following example. The parameter $ireland is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $ireland
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was changed, but the annotation was not.

Loading history...
2609
 * @param int $url URL ID. If provided, also check if the user is active on given URL
2610
 * @result bool True if the user is admin, false otherwise
2611
 */
2612
function api_is_platform_admin_by_id($user_id = null, $url = null)
2613
{
2614
    $user_id = intval($user_id);
2615
    if (empty($user_id)) {
2616
        $user_id = api_get_user_id();
2617
    }
2618
    $admin_table = Database::get_main_table(TABLE_MAIN_ADMIN);
2619
    $sql = "SELECT * FROM $admin_table WHERE user_id = $user_id";
2620
    $res = Database::query($sql);
2621
    $is_admin = Database::num_rows($res) === 1;
2622
    if (!$is_admin or !isset($url)) {
2623
        return $is_admin;
2624
    }
2625
    // We get here only if $url is set
2626
    $url = intval($url);
2627
    $url_user_table = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_USER);
2628
    $sql = "SELECT * FROM $url_user_table
2629
            WHERE access_url_id = $url AND user_id = $user_id";
2630
    $res = Database::query($sql);
2631
    $is_on_url = Database::num_rows($res) === 1;
2632
2633
    return $is_on_url;
2634
}
2635
2636
/**
2637
 * Returns the user's numeric status ID from the users table
2638
 * @param int $user_id. If none provided, will use current user
0 ignored issues
show
Documentation introduced by
There is no parameter named $user_id.. Did you maybe mean $user_id?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function. It has, however, found a similar but not annotated parameter which might be a good fit.

Consider the following example. The parameter $ireland is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $ireland
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was changed, but the annotation was not.

Loading history...
2639
 * @result int User's status (1 for teacher, 5 for student, etc)
2640
 */
2641
function api_get_user_status($user_id = null)
2642
{
2643
    $user_id = intval($user_id);
2644
    if (empty($user_id)) {
2645
        $user_id = api_get_user_id();
2646
    }
2647
    $table = Database::get_main_table(TABLE_MAIN_USER);
2648
    $sql = "SELECT status FROM $table WHERE user_id = $user_id ";
2649
    $result = Database::query($sql);
2650
    $status = null;
2651
    if (Database::num_rows($result)) {
2652
        $row = Database::fetch_array($result);
2653
        $status = $row['status'];
2654
    }
2655
    return $status;
2656
}
2657
2658
/**
2659
 * Checks whether current user is allowed to create courses
2660
 * @return boolean True if the user has course creation rights,
2661
 * false otherwise.
2662
 */
2663
function api_is_allowed_to_create_course() {
2664
    return Session::read('is_allowedCreateCourse');
2665
}
2666
2667
/**
2668
 * Checks whether the current user is a course administrator
2669
 * @return boolean True if current user is a course administrator
2670
 */
2671
function api_is_course_admin() {
2672
    if (api_is_platform_admin()) {
2673
        return true;
2674
    }
2675
    return Session::read('is_courseAdmin');
2676
}
2677
2678
/**
2679
 * Checks whether the current user is a course coach
2680
 * @return bool     True if current user is a course coach
2681
 */
2682
function api_is_course_coach() {
2683
    return Session::read('is_courseCoach');
2684
}
2685
2686
/**
2687
 * Checks whether the current user is a course tutor
2688
 * @return bool     True if current user is a course tutor
2689
 */
2690
function api_is_course_tutor() {
2691
    return Session::read('is_courseTutor');
2692
}
2693
2694
/**
2695
 * @param int $user_id
2696
 *
2697
 * @return array
2698
 */
2699
function api_get_user_platform_status($user_id = null) {
2700
    $status     = array();
2701
    $user_id    = intval($user_id);
2702
    if (empty($user_id)) {
2703
        $user_id = api_get_user_id();
2704
    }
2705
2706
    if (empty($user_id)) {
2707
        return false;
2708
    }
2709
    $group_id   = api_get_group_id();
2710
    $course_id  = api_get_course_int_id();
2711
    $course_code= api_get_course_id();
2712
    $session_id = api_get_session_id();
2713
2714
    //Group (in course)
2715
    if ($group_id && $course_id) {
2716
        $group_status = array();
2717
        $is_subscribed = GroupManager::is_subscribed($user_id, $group_id);
2718
        if ($is_subscribed) {
2719
            $group_status = array('id'=> $group_id , 'status' => 'student');
2720
            $is_tutor = GroupManager::is_tutor_of_group($user_id, $group_id);
2721
            if ($is_tutor) {
2722
                $group_status['status'] = 'tutor';
2723
            } else {
2724
                $group_status['status'] = 'student';
2725
            }
2726
        }
2727
        $status['group'] = $group_status;
2728
    }
2729
2730
    //Session
2731
    if ($session_id && $course_id) {
2732
        $session_status = array('id' => $session_id, 'course_id' => $course_id);
2733
        $session_user_status = SessionManager::get_user_status_in_course_session(
2734
            $user_id,
2735
            $course_id,
2736
            $session_id
2737
        );
2738
2739
        switch ($session_user_status) {
2740
            case 0:
2741
                $session_status['status'] = 'student';
2742
               break;
2743
            case 2:
2744
                $session_status['status'] = 'coach';
2745
            break;
2746
        }
2747
        $is_general_coach = SessionManager::user_is_general_coach($user_id, $session_id);
2748
        if ($is_general_coach) {
2749
            $session_status['status'] = 'general_coach';
2750
        }
2751
        $status['session'] = $session_status;
2752
2753
    } elseif($course_id) {
2754
        //Course
2755
        $course_status = array();
2756
        if ($course_id) {
2757
            $user_course_status = CourseManager::get_user_in_course_status($user_id, $course_code);
2758
2759
            if ($user_course_status) {
2760
                $course_status = array('id'=> $course_id);
2761
                switch($user_course_status) {
2762
                    case 1;
0 ignored issues
show
Coding Style introduced by
case statements should be defined using a colon.

As per the PSR-2 coding standard, case statements should not be wrapped in curly braces. There is no need for braces, since each case is terminated by the next break.

There is also the option to use a semicolon instead of a colon, this is discouraged because many programmers do not even know it works and the colon is universal between programming languages.

switch ($expr) {
    case "A": { //wrong
        doSomething();
        break;
    }
    case "B"; //wrong
        doSomething();
        break;
    case "C": //right
        doSomething();
        break;
}

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
2763
                        $course_status['status'] = 'teacher';
2764
                    break;
2765
                    case 5;
0 ignored issues
show
Coding Style introduced by
case statements should be defined using a colon.

As per the PSR-2 coding standard, case statements should not be wrapped in curly braces. There is no need for braces, since each case is terminated by the next break.

There is also the option to use a semicolon instead of a colon, this is discouraged because many programmers do not even know it works and the colon is universal between programming languages.

switch ($expr) {
    case "A": { //wrong
        doSomething();
        break;
    }
    case "B"; //wrong
        doSomething();
        break;
    case "C": //right
        doSomething();
        break;
}

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
2766
                        $course_status['status'] = 'student';
2767
                        //check if tutor
2768
                        $tutor_course_status = CourseManager::get_tutor_in_course_status($user_id, $course_code);
2769
                        if ($tutor_course_status) {
2770
                            $course_status['status'] = 'tutor';
2771
                        }
2772
                    break;
2773
                }
2774
            }
2775
        }
2776
        $status['course'] = $course_status;
2777
    }
2778
2779
    return $status;
2780
}
2781
2782
/**
2783
 * @param int $user_id
2784
 * @param int $courseId
2785
 * @param int $session_id
2786
 * @return bool
2787
 */
2788
function api_is_course_session_coach($user_id, $courseId, $session_id)
2789
{
2790
    $session_table = Database::get_main_table(TABLE_MAIN_SESSION);
2791
    $session_rel_course_rel_user_table  = Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER);
2792
2793
    $user_id = intval($user_id);
2794
    $session_id = intval($session_id);
2795
    $courseId = intval($courseId);
2796
2797
    $sql = "SELECT DISTINCT session.id
2798
            FROM $session_table
2799
            INNER JOIN $session_rel_course_rel_user_table session_rc_ru
2800
            ON session.id = session_rc_ru.session_id
2801
            WHERE
2802
                session_rc_ru.user_id = '".$user_id."'  AND
2803
                session_rc_ru.c_id = '$courseId' AND
2804
                session_rc_ru.status = 2 AND
2805
                session_rc_ru.session_id = '$session_id'";
2806
    $result = Database::query($sql);
2807
2808
    return Database::num_rows($result) > 0;
2809
}
2810
2811
/**
2812
 * Checks whether the current user is a course or session coach
2813
 * @param int $session_id
2814
 * @param int $courseId
2815
 * @param bool  Check whether we are in student view and, if we are, return false
2816
 * @return boolean True if current user is a course or session coach
2817
 */
2818
function api_is_coach($session_id = 0, $courseId = null, $check_student_view = true)
2819
{
2820
    $userId = api_get_user_id();
2821
2822
    if (!empty($session_id)) {
2823
        $session_id = intval($session_id);
2824
    } else {
2825
        $session_id = api_get_session_id();
2826
    }
2827
2828
    // The student preview was on
2829 View Code Duplication
    if ($check_student_view &&
2830
        isset($_SESSION['studentview']) && $_SESSION['studentview'] == "studentview"
2831
    ) {
2832
        return false;
2833
    }
2834
2835
    if (!empty($courseId)) {
2836
        $courseId = intval($courseId);
2837
    } else {
2838
        $courseId = api_get_course_int_id();
2839
    }
2840
2841
    $session_table = Database::get_main_table(TABLE_MAIN_SESSION);
2842
    $session_rel_course_rel_user_table = Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER);
2843
    $sessionIsCoach = null;
2844
2845
    if (!empty($courseId)) {
2846
        $sql = "SELECT DISTINCT s.id, name, access_start_date, access_end_date
2847
                FROM $session_table s
2848
                INNER JOIN $session_rel_course_rel_user_table session_rc_ru
2849
                ON session_rc_ru.session_id = s.id AND session_rc_ru.user_id = '".$userId."'
2850
                WHERE
2851
                    session_rc_ru.c_id = '$courseId' AND
2852
                    session_rc_ru.status = 2 AND
2853
                    session_rc_ru.session_id = '$session_id'";
2854
        $result = Database::query($sql);
2855
        $sessionIsCoach = Database::store_result($result);
2856
    }
2857
2858 View Code Duplication
    if (!empty($session_id)) {
2859
        $sql = "SELECT DISTINCT id, name, access_start_date, access_end_date
2860
                FROM $session_table
2861
                WHERE session.id_coach =  '".$userId."' AND id = '$session_id'
2862
                ORDER BY access_start_date, access_end_date, name";
2863
        $result = Database::query($sql);
2864
        if (!empty($sessionIsCoach)) {
2865
            $sessionIsCoach = array_merge($sessionIsCoach , Database::store_result($result));
2866
        } else {
2867
            $sessionIsCoach = Database::store_result($result);
2868
        }
2869
    }
2870
2871
    return (count($sessionIsCoach) > 0);
2872
}
2873
2874
/**
2875
 * Checks whether the current user is a session administrator
2876
 * @return boolean True if current user is a course administrator
2877
 */
2878
function api_is_session_admin()
2879
{
2880
    $user = api_get_user_info();
2881
    return isset($user['status']) && $user['status'] == SESSIONADMIN;
2882
}
2883
2884
/**
2885
 * Checks whether the current user is a human resources manager
2886
 * @return boolean True if current user is a human resources manager
2887
 */
2888
function api_is_drh()
2889
{
2890
    $user = api_get_user_info();
2891
    return isset($user['status']) && $user['status'] == DRH;
2892
}
2893
2894
/**
2895
 * Checks whether the current user is a student
2896
 * @return boolean True if current user is a human resources manager
2897
 */
2898
function api_is_student()
2899
{
2900
    $user = api_get_user_info();
2901
    return isset($user['status']) && $user['status'] == STUDENT;
2902
2903
}
2904
/**
2905
 * Checks whether the current user has the status 'teacher'
2906
 * @return boolean True if current user is a human resources manager
2907
 */
2908
function api_is_teacher()
2909
{
2910
    $user = api_get_user_info();
2911
    return isset($user['status']) && $user['status'] == COURSEMANAGER;
2912
}
2913
2914
/**
2915
 * Checks whether the current user is a invited user
2916
 * @return boolean
2917
 */
2918
function api_is_invitee()
2919
{
2920
    $user = api_get_user_info();
2921
2922
    return isset($user['status']) && $user['status'] == INVITEE;
2923
}
2924
2925
/**
2926
 * This function checks whether a session is assigned into a category
2927
 * @param int       - session id
2928
 * @param string    - category name
2929
 * @return bool     - true if is found, otherwise false
2930
 */
2931
function api_is_session_in_category($session_id, $category_name)
2932
{
2933
    $session_id = intval($session_id);
2934
    $category_name = Database::escape_string($category_name);
2935
2936
    $tbl_session = Database::get_main_table(TABLE_MAIN_SESSION);
2937
    $tbl_session_category = Database::get_main_table(TABLE_MAIN_SESSION_CATEGORY);
2938
2939
    $sql = "SELECT 1
2940
            FROM $tbl_session
2941
            WHERE $session_id IN (
2942
                SELECT s.id FROM $tbl_session s, $tbl_session_category sc
2943
                WHERE
2944
                  s.session_category_id = sc.id AND
2945
                  sc.name LIKE '%$category_name'
2946
            )";
2947
    $rs = Database::query($sql);
2948
2949
    if (Database::num_rows($rs) > 0) {
2950
        return true;
2951
    } else {
2952
        return false;
2953
    }
2954
}
2955
2956
/* DISPLAY OPTIONS
2957
   student view, title, message boxes,... */
2958
2959
/**
2960
 * Displays the title of a tool.
2961
 * Normal use: parameter is a string:
2962
 * api_display_tool_title("My Tool")
2963
 *
2964
 * Optionally, there can be a subtitle below
2965
 * the normal title, and / or a supra title above the normal title.
2966
 *
2967
 * e.g. supra title:
2968
 * group
2969
 * GROUP PROPERTIES
2970
 *
2971
 * e.g. subtitle:
2972
 * AGENDA
2973
 * calender & events tool
2974
 *
2975
 * @author Hugues Peeters <[email protected]>
2976
 * @param  mixed $title_element - it could either be a string or an array
2977
 *                               containing 'supraTitle', 'mainTitle',
2978
 *                               'subTitle'
2979
 * @return void
2980
 */
2981
function api_display_tool_title($title_element) {
2982
    if (is_string($title_element)) {
2983
        $tit = $title_element;
2984
        unset ($title_element);
2985
        $title_element['mainTitle'] = $tit;
2986
    }
2987
    echo '<h3>';
2988
    if (!empty($title_element['supraTitle'])) {
2989
        echo '<small>'.$title_element['supraTitle'].'</small><br />';
2990
    }
2991
    if (!empty($title_element['mainTitle'])) {
2992
        echo $title_element['mainTitle'];
2993
    }
2994
    if (!empty($title_element['subTitle'])) {
2995
        echo '<br /><small>'.$title_element['subTitle'].'</small>';
2996
    }
2997
    echo '</h3>';
2998
}
2999
3000
/**
3001
 * Displays options for switching between student view and course manager view
3002
 *
3003
 * Changes in version 1.2 (Patrick Cool)
3004
 * Student view switch now behaves as a real switch. It maintains its current state until the state
3005
 * is changed explicitly
3006
 *
3007
 * Changes in version 1.1 (Patrick Cool)
3008
 * student view now works correctly in subfolders of the document tool
3009
 * student view works correctly in the new links tool
3010
 *
3011
 * Example code for using this in your tools:
3012
 * //if ($is_courseAdmin && api_get_setting('student_view_enabled') == 'true') {
3013
 * //   display_tool_view_option($isStudentView);
3014
 * //}
3015
 * //and in later sections, use api_is_allowed_to_edit()
3016
 *
3017
 * @author Roan Embrechts
3018
 * @author Patrick Cool
3019
 * @author Julio Montoya, changes added in Chamilo
3020
 * @version 1.2
3021
 * @todo rewrite code so it is easier to understand
3022
 */
3023
function api_display_tool_view_option() {
3024
    if (api_get_setting('student_view_enabled') != 'true') {
3025
        return '';
3026
    }
3027
3028
    $sourceurl = '';
3029
    $is_framed = false;
3030
    // Exceptions apply for all multi-frames pages
3031
    if (strpos($_SERVER['REQUEST_URI'], 'chat/chat_banner.php') !== false) {
3032
        // The chat is a multiframe bit that doesn't work too well with the student_view, so do not show the link
3033
        return '';
3034
    }
3035
3036
    // Uncomment to remove student view link from document view page
3037
    if (strpos($_SERVER['REQUEST_URI'], 'newscorm/lp_header.php') !== false) {
3038
        if (empty($_GET['lp_id'])) {
3039
            return '';
3040
        }
3041
        $sourceurl = substr($_SERVER['REQUEST_URI'], 0, strpos($_SERVER['REQUEST_URI'], '?'));
3042
        $sourceurl = str_replace('newscorm/lp_header.php', 'newscorm/lp_controller.php?'.api_get_cidreq().'&action=view&lp_id='.intval($_GET['lp_id']).'&isStudentView='.($_SESSION['studentview']=='studentview' ? 'false' : 'true'), $sourceurl);
3043
        //showinframes doesn't handle student view anyway...
3044
        //return '';
3045
        $is_framed = true;
3046
    }
3047
3048
    // Check whether the $_SERVER['REQUEST_URI'] contains already url parameters (thus a questionmark)
3049
    if (!$is_framed) {
3050
        if (strpos($_SERVER['REQUEST_URI'], '?') === false) {
3051
            $sourceurl = api_get_self().'?'.api_get_cidreq();
3052
        } else {
3053
            $sourceurl = $_SERVER['REQUEST_URI'];
3054
            //$sourceurl = str_replace('&', '&amp;', $sourceurl);
3055
        }
3056
    }
3057
3058
    $output_string = '';
3059
    if (!empty($_SESSION['studentview'])) {
3060
        if ($_SESSION['studentview'] == 'studentview') {
3061
            // We have to remove the isStudentView=true from the $sourceurl
3062
            $sourceurl = str_replace('&isStudentView=true', '', $sourceurl);
3063
            $sourceurl = str_replace('&isStudentView=false', '', $sourceurl);
3064
            $output_string .= '<a class="btn btn-success btn-xs" href="'.$sourceurl.'&isStudentView=false" target="_self">'.get_lang('SwitchToTeacherView').'</a>';
3065
        } elseif ($_SESSION['studentview'] == 'teacherview') {
3066
            // Switching to teacherview
3067
            $sourceurl = str_replace('&isStudentView=true', '', $sourceurl);
3068
            $sourceurl = str_replace('&isStudentView=false', '', $sourceurl);
3069
            $output_string .= '<a class="btn btn-primary btn-xs" href="'.$sourceurl.'&isStudentView=true" target="_self">'.get_lang('SwitchToStudentView').'</a>';
3070
        }
3071
    } else {
3072
        $output_string .= '<a class="btn btn-primary btn-xs" href="'.$sourceurl.'&isStudentView=true" target="_self">'.get_lang('SwitchToStudentView').'</a>';
3073
    }
3074
    return $output_string;
3075
}
3076
3077
// TODO: This is for the permission section.
3078
/**
3079
 * Function that removes the need to directly use is_courseAdmin global in
3080
 * tool scripts. It returns true or false depending on the user's rights in
3081
 * this particular course.
3082
 * Optionally checking for tutor and coach roles here allows us to use the
3083
 * student_view feature altogether with these roles as well.
3084
 * @param bool  Whether to check if the user has the tutor role
3085
 * @param bool  Whether to check if the user has the coach role
3086
 * @param bool  Whether to check if the user has the session coach role
3087
 * @param bool  check the student view or not
3088
 *
3089
 * @author Roan Embrechts
3090
 * @author Patrick Cool
3091
 * @author Julio Montoya
3092
 * @version 1.1, February 2004
3093
 * @return boolean, true: the user has the rights to edit, false: he does not
3094
 */
0 ignored issues
show
Documentation introduced by
The doc-type boolean, could not be parsed: Expected "|" or "end of type", but got "," at position 7. (view supported doc-types)

This check marks PHPDoc comments that could not be parsed by our parser. To see which comment annotations we can parse, please refer to our documentation on supported doc-types.

Loading history...
3095
3096
function api_is_allowed_to_edit($tutor = false, $coach = false, $session_coach = false, $check_student_view = true)
3097
{
3098
    $my_session_id = api_get_session_id();
3099
    $is_allowed_coach_to_edit = api_is_coach(null, null, $check_student_view);
3100
    $session_visibility = api_get_session_visibility($my_session_id);
3101
3102
    // Admins can edit anything.
3103
    if (api_is_platform_admin(false)) {
3104
        //The student preview was on
3105 View Code Duplication
        if ($check_student_view &&
3106
            isset($_SESSION['studentview']) &&
3107
            $_SESSION['studentview'] == "studentview"
3108
        ) {
3109
            return false;
3110
        } else {
3111
            return true;
3112
        }
3113
    }
3114
3115
    $is_courseAdmin = api_is_course_admin();
3116
3117
    if (!$is_courseAdmin && $tutor) {
3118
        // If we also want to check if the user is a tutor...
3119
        $is_courseAdmin = $is_courseAdmin || api_is_course_tutor();
3120
    }
3121
3122
    if (!$is_courseAdmin && $coach) {
3123
        // If we also want to check if the user is a coach...';
3124
        // Check if session visibility is read only for coaches.
3125
        if ($session_visibility == SESSION_VISIBLE_READ_ONLY) {
3126
            $is_allowed_coach_to_edit = false;
3127
        }
3128
3129
        if (api_get_setting('allow_coach_to_edit_course_session') == 'true') {
3130
            // Check if coach is allowed to edit a course.
3131
            $is_courseAdmin = $is_courseAdmin || $is_allowed_coach_to_edit;
3132
        } else {
3133
            $is_courseAdmin = $is_courseAdmin;
0 ignored issues
show
Bug introduced by
Why assign $is_courseAdmin to itself?

This checks looks for cases where a variable has been assigned to itself.

This assignement can be removed without consequences.

Loading history...
3134
        }
3135
    }
3136
3137
    if (!$is_courseAdmin && $session_coach) {
3138
        $is_courseAdmin = $is_courseAdmin || $is_allowed_coach_to_edit;
3139
    }
3140
3141
    // Check if the student_view is enabled, and if so, if it is activated.
3142
    if (api_get_setting('student_view_enabled') == 'true') {
3143
        if (!empty($my_session_id)) {
3144
            // Check if session visibility is read only for coaches.
3145
            if ($session_visibility == SESSION_VISIBLE_READ_ONLY) {
3146
                $is_allowed_coach_to_edit = false;
3147
            }
3148
3149
            if (api_get_setting('allow_coach_to_edit_course_session') == 'true') {
3150
                // Check if coach is allowed to edit a course.
3151
                $is_allowed = $is_allowed_coach_to_edit;
3152
            } else {
3153
                $is_allowed = false;
3154
            }
3155
            if ($check_student_view) {
3156
                $is_allowed = $is_allowed && $_SESSION['studentview'] != 'studentview';
3157
            }
3158
        } else {
3159
            if ($check_student_view) {
3160
                $is_allowed = $is_courseAdmin && $_SESSION['studentview'] != 'studentview';
3161
            } else {
3162
                $is_allowed = $is_courseAdmin;
3163
            }
3164
        }
3165
3166
        return $is_allowed;
3167
    } else {
3168
3169
        return $is_courseAdmin;
3170
    }
3171
}
3172
3173
/**
3174
* Checks if a student can edit contents in a session depending
3175
* on the session visibility
3176
* @param bool $tutor  Whether to check if the user has the tutor role
3177
* @param bool  $coach Whether to check if the user has the coach role
3178
* @return boolean, true: the user has the rights to edit, false: he does not
0 ignored issues
show
Documentation introduced by
The doc-type boolean, could not be parsed: Expected "|" or "end of type", but got "," at position 7. (view supported doc-types)

This check marks PHPDoc comments that could not be parsed by our parser. To see which comment annotations we can parse, please refer to our documentation on supported doc-types.

Loading history...
3179
*/
3180
function api_is_allowed_to_session_edit($tutor = false, $coach = false)
3181
{
3182
    if (api_is_allowed_to_edit($tutor, $coach)) {
3183
        // If I'm a teacher, I will return true in order to not affect the normal behaviour of Chamilo tools.
3184
        return true;
3185
    } else {
3186
        if (api_get_session_id() == 0) {
3187
            // I'm not in a session so i will return true to not affect the normal behaviour of Chamilo tools.
3188
            return true;
3189
        } else {
3190
            // I'm in a session and I'm a student
3191
            $session_id = api_get_session_id();
3192
3193
            // Get the session visibility
3194
            $session_visibility = api_get_session_visibility($session_id);
3195
            // if 5 the session is still available
3196
3197
            //@todo We could load the session_rel_course_rel_user permission to increase the level of detail.
3198
            //echo api_get_user_id();
3199
            //echo api_get_course_id();
3200
3201
            switch ($session_visibility) {
3202
                case SESSION_VISIBLE_READ_ONLY: // 1
3203
                    return false;
3204
                case SESSION_VISIBLE:           // 2
3205
                    return true;
3206
                case SESSION_INVISIBLE:         // 3
3207
                    return false;
3208
                case SESSION_AVAILABLE:         //5
3209
                    return true;
3210
            }
3211
3212
        }
3213
    }
3214
}
3215
3216
/**
3217
* Checks whether the user is allowed in a specific tool for a specific action
3218
* @param string $tool the tool we are checking if the user has a certain permission
3219
* @param string $action the action we are checking (add, edit, delete, move, visibility)
3220
* @author Patrick Cool <[email protected]>, Ghent University
3221
* @author Julio Montoya
3222
* @version 1.0
3223
*/
3224
function api_is_allowed($tool, $action, $task_id = 0)
3225
{
3226
    $_user = api_get_user_info();
3227
    $_course = api_get_course_info();
3228
3229
    if (api_is_course_admin()) {
3230
        return true;
3231
    }
3232
    //if (!$_SESSION['total_permissions'][$_course['code']] and $_course)
3233
    if (is_array($_course) and count($_course) > 0) {
3234
        require_once api_get_path(SYS_CODE_PATH).'permissions/permissions_functions.inc.php';
3235
3236
        // Getting the permissions of this user.
3237
        if ($task_id == 0) {
3238
            $user_permissions = get_permissions('user', $_user['user_id']);
3239
            $_SESSION['total_permissions'][$_course['code']] = $user_permissions;
3240
        }
3241
3242
        // Getting the permissions of the task.
3243
        if ($task_id != 0) {
3244
            $task_permissions = get_permissions('task', $task_id);
3245
            /* !!! */$_SESSION['total_permissions'][$_course['code']] = $task_permissions;
3246
        }
3247
        //print_r($_SESSION['total_permissions']);
3248
3249
        // Getting the permissions of the groups of the user
3250
        //$groups_of_user = GroupManager::get_group_ids($_course['db_name'], $_user['user_id']);
3251
3252
        //foreach($groups_of_user as $group)
3253
        //   $this_group_permissions = get_permissions('group', $group);
3254
3255
        // Getting the permissions of the courseroles of the user
3256
        $user_courserole_permissions = get_roles_permissions('user', $_user['user_id']);
3257
3258
        // Getting the permissions of the platformroles of the user
3259
        //$user_platformrole_permissions = get_roles_permissions('user', $_user['user_id'], ', platform');
3260
3261
        // Getting the permissions of the roles of the groups of the user
3262
        //foreach($groups_of_user as $group)
3263
        //    $this_group_courserole_permissions = get_roles_permissions('group', $group);
3264
3265
        // Getting the permissions of the platformroles of the groups of the user
3266
        //foreach($groups_of_user as $group)
3267
        //    $this_group_platformrole_permissions = get_roles_permissions('group', $group, 'platform');
3268
    }
3269
3270
    // If the permissions are limited, we have to map the extended ones to the limited ones.
3271
    if (api_get_setting('permissions') == 'limited') {
3272
        if ($action == 'Visibility') {
3273
            $action = 'Edit';
3274
        }
3275
        if ($action == 'Move') {
3276
            $action = 'Edit';
3277
        }
3278
    }
3279
3280
    // The session that contains all the permissions already exists for this course
3281
    // so there is no need to requery everything.
3282
    //my_print_r($_SESSION['total_permissions'][$_course['code']][$tool]);
3283
    if (is_array($_SESSION['total_permissions'][$_course['code']][$tool])) {
3284
        if (in_array($action, $_SESSION['total_permissions'][$_course['code']][$tool])) {
3285
            return true;
3286
        } else {
3287
            return false;
3288
        }
3289
    }
3290
}
3291
3292
/**
3293
 * Tells whether this user is an anonymous user
3294
 * @param int  $user_id      User ID (optional, will take session ID if not provided)
3295
 * @param bool $db_check     Whether to check in the database (true) or simply in
3296
 * the session (false) to see if the current user is the anonymous user
3297
 * @return bool     true if this user is anonymous, false otherwise
3298
 */
3299
function api_is_anonymous($user_id = null, $db_check = false) {
3300
    if (!isset($user_id)) {
3301
        $user_id = api_get_user_id();
3302
    }
3303
    if ($db_check) {
3304
        $info = api_get_user_info($user_id);
3305
        if ($info['status'] == ANONYMOUS) {
3306
            return true;
3307
        }
3308
    }
3309
3310
    $_user = api_get_user_info();
3311
    if (isset($_user['status']) && $_user['status'] == ANONYMOUS) {
3312
        //if ($_user['user_id'] == 0) {
3313
        // In some cases, api_set_anonymous doesn't seem to be triggered in local.inc.php. Make sure it is.
3314
        // Occurs in agenda for admin links - YW
3315
        global $use_anonymous;
3316
        if (isset($use_anonymous) && $use_anonymous) {
3317
            api_set_anonymous();
3318
        }
3319
3320
        return true;
3321
    }
3322
3323
    return ((isset($_user['is_anonymous']) && $_user['is_anonymous'] === true) || $_user === false);
3324
}
3325
3326
/**
3327
 * Displays message "You are not allowed here..." and exits the entire script.
3328
 * @param bool   $print_headers    Whether or not to print headers (default = false -> does not print them)
3329
 * @param string $message
3330
 */
3331
function api_not_allowed($print_headers = false, $message = null)
3332
{
3333
    if (api_get_setting('sso_authentication') === 'true') {
3334
        global $osso;
3335
        if ($osso) {
3336
            $osso->logout();
3337
        }
3338
    }
3339
    $home_url = api_get_path(WEB_PATH);
3340
    $user_id = api_get_user_id();
3341
    $course = api_get_course_id();
3342
3343
    global $this_section;
3344
3345
    if (CustomPages::enabled() && !isset($user_id)) {
3346
3347
        if (empty($user_id)) {
3348
            // Why the CustomPages::enabled() need to be to set the request_uri
3349
            $_SESSION['request_uri'] = $_SERVER['REQUEST_URI'];
3350
        }
3351
3352
        CustomPages::display(CustomPages::INDEX_UNLOGGED);
3353
    }
3354
3355
    $origin = isset($_GET['origin']) ? $_GET['origin'] : '';
3356
3357
    $msg = null;
3358
    if (isset($message)) {
3359
        $msg = $message;
3360 View Code Duplication
    } else {
3361
        $msg = Display::return_message(
3362
            get_lang('NotAllowedClickBack').'<br/><br/><a href="'.$home_url.'">'.get_lang('ReturnToCourseHomepage').'</a>',
3363
            'error',
3364
            false
3365
        );
3366
    }
3367
3368
    $msg = Display::div($msg, array('align'=>'center'));
3369
3370
    $show_headers = 0;
3371
3372
    if ($print_headers && $origin != 'learnpath') {
3373
        $show_headers = 1;
3374
    }
3375
3376
    $tpl = new Template(null, $show_headers, $show_headers);
3377
    $tpl->assign('hide_login_link', 1);
3378
    $tpl->assign('content', $msg);
3379
3380
    if (($user_id != 0 && !api_is_anonymous()) &&
3381
        (!isset($course) || $course == -1) &&
3382
        empty($_GET['cidReq'])
3383
    ) {
3384
        // if the access is not authorized and there is some login information
3385
        // but the cidReq is not found, assume we are missing course data and send the user
3386
        // to the user_portal
3387
        $tpl->display_one_col_template();
3388
        exit;
3389
    }
3390
3391
    if (!empty($_SERVER['REQUEST_URI']) &&
3392
        (!empty($_GET['cidReq']) ||
3393
            $this_section == SECTION_MYPROFILE ||
3394
            $this_section == SECTION_PLATFORM_ADMIN
3395
        )
3396
    ) {
3397
        $courseCode = api_get_course_id();
3398
        // Only display form and return to the previous URL if there was a course ID included
3399
        if ($user_id != 0 && !api_is_anonymous()) {
3400
            //if there is a user ID, then the user is not allowed but the session is still there. Say so and exit
3401
            $tpl->assign('content', $msg);
3402
            $tpl->display_one_col_template();
3403
            exit;
3404
        }
3405
3406
        if (!is_null($courseCode)) {
3407
            api_set_firstpage_parameter($courseCode);
3408
        }
3409
3410
        // If the user has no user ID, then his session has expired
3411
        $action = api_get_self().'?'.Security::remove_XSS($_SERVER['QUERY_STRING']);
3412
        $action = str_replace('&amp;', '&', $action);
3413
        $form = new FormValidator(
3414
            'formLogin',
3415
            'post',
3416
            $action,
3417
            null,
3418
            array(),
3419
            FormValidator::LAYOUT_BOX_NO_LABEL
3420
        );
3421
        $form->addElement('text', 'login', null, array('placeholder' => get_lang('UserName'), 'class' => 'autocapitalize_off'));
3422
        $form->addElement('password', 'password', null, array('placeholder' => get_lang('Password')));
3423
        $form->addButton('submitAuth', get_lang('LoginEnter'), '', 'primary');
3424
3425
        // see same text in auth/gotocourse.php and main_api.lib.php function api_not_allowed (above)
3426
        $content = Display::return_message(get_lang('NotAllowed'), 'error', false);
3427
3428
        if (!empty($courseCode)) {
3429
            $content .= '<h4>'.get_lang('LoginToGoToThisCourse').'</h4>';
3430
        }
3431
3432
        if (api_is_cas_activated()) {
3433
            $content .= Display::return_message(sprintf(get_lang('YouHaveAnInstitutionalAccount'), api_get_setting("Institution")), '', false);
3434
            $content .= Display::div("<br/><a href='".get_cas_direct_URL(api_get_course_id())."'>".sprintf(get_lang('LoginWithYourAccount'), api_get_setting("Institution"))."</a><br/><br/>", array('align'=>'center'));
3435
            $content .= Display::return_message(get_lang('YouDontHaveAnInstitutionAccount'));
3436
            $content .= "<p style='text-align:center'><a href='#' onclick='$(this).parent().next().toggle()'>".get_lang('LoginWithExternalAccount')."</a></p>";
3437
            $content .= "<div style='display:none;'>";
3438
        }
3439
        $content .= '<div class="well_login">';
3440
        $content .= $form->return_form();
0 ignored issues
show
Deprecated Code introduced by
The method FormValidator::return_form() has been deprecated with message: use returnForm()

This method has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.

Loading history...
3441
        $content .='</div>';
3442
        if (api_is_cas_activated()) {
3443
            $content .= "</div>";
3444
        }
3445
3446
        if (!empty($courseCode)) {
3447
            $content .= '<hr/><p style="text-align:center"><a href="'.$home_url.'">'.
3448
                get_lang('ReturnToCourseHomepage').'</a></p>';
3449
        } else {
3450
            $content .= '<hr/><p style="text-align:center"><a href="'.$home_url.'">'.
3451
                get_lang('CampusHomepage').'</a></p>';
3452
        }
3453
3454
        $tpl->setLoginBodyClass();
3455
        $tpl->assign('content', $content);
3456
        $tpl->display_one_col_template();
3457
        exit;
3458
    }
3459
3460
    if ($user_id !=0 && !api_is_anonymous()) {
3461
        $tpl->display_one_col_template();
3462
        exit;
3463
    }
3464
3465
    $msg = null;
3466
3467
    // The session is over and we were not in a course,
3468
    // or we try to get directly to a private course without being logged
3469
    if (!is_null(api_get_course_int_id())) {
3470
        api_set_firstpage_parameter(api_get_course_id());
3471
        $tpl->setLoginBodyClass();
3472
        $action = api_get_self().'?'.Security::remove_XSS($_SERVER['QUERY_STRING']);
3473
        $action = str_replace('&amp;', '&', $action);
3474
        $form = new FormValidator('formLogin', 'post', $action, null, array('class'=>'form-stacked'));
3475
        $form->addElement('text', 'login', null, array('placeholder' => get_lang('UserName'), 'class' => 'col-md-3 autocapitalize_off')); //new
3476
        $form->addElement('password', 'password', null, array('placeholder' => get_lang('Password'), 'class' => 'col-md-3')); //new
3477
        $form->addButtonNext(get_lang('LoginEnter'), 'submitAuth');
3478
3479
        // see same text in auth/gotocourse.php and main_api.lib.php function api_not_allowed (bellow)
3480
        $msg = Display::return_message(get_lang('NotAllowed'), 'error', false);
3481
        $msg .= '<h4>'.get_lang('LoginToGoToThisCourse').'</h4>';
3482 View Code Duplication
        if (api_is_cas_activated()) {
3483
            $msg .= Display::return_message(sprintf(get_lang('YouHaveAnInstitutionalAccount'), api_get_setting("Institution")), '', false);
3484
            $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/>", array('align'=>'center'));
3485
            $msg .= Display::return_message(get_lang('YouDontHaveAnInstitutionAccount'));
3486
            $msg .= "<p style='text-align:center'><a href='#' onclick='$(this).parent().next().toggle()'>".get_lang('LoginWithExternalAccount')."</a></p>";
3487
            $msg .= "<div style='display:none;'>";
3488
        }
3489
        $msg .= '<div class="well">';
3490
        $msg .= $form->return_form();
0 ignored issues
show
Deprecated Code introduced by
The method FormValidator::return_form() has been deprecated with message: use returnForm()

This method has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.

Loading history...
3491
        $msg .='</div>';
3492
        if (api_is_cas_activated()) {
3493
            $msg .= "</div>";
3494
        }
3495
        $msg .= '<hr/><p style="text-align:center"><a href="'.$home_url.'">'.get_lang('ReturnToCourseHomepage').'</a></p>';
3496 View Code Duplication
    } else {
3497
        // we were not in a course, return to home page
3498
        $msg = Display::return_message(
3499
            get_lang('NotAllowed').'<br/><br/><a href="'.$home_url.'">'.get_lang('ReturnToCourseHomepage').'</a><br />',
3500
            'error',
3501
            false
3502
        );
3503
    }
3504
3505
    $tpl->assign('content', $msg);
3506
    $tpl->display_one_col_template();
3507
    exit;
3508
}
3509
3510
3511
/* WHAT'S NEW
3512
   functions for the what's new icons
3513
   in the user course list */
3514
3515
/**
3516
 * Gets a UNIX timestamp from a database (MySQL) datetime format string
3517
 * @param $last_post_datetime standard output date in a sql query
3518
 * @return integer timestamp
3519
 * @author Toon Van Hoecke <[email protected]>
3520
 * @version October 2003
3521
 * @desc convert sql date to unix timestamp
3522
 */
3523
function convert_sql_date($last_post_datetime) {
3524
    list ($last_post_date, $last_post_time) = explode(' ', $last_post_datetime);
3525
    list ($year, $month, $day) = explode('-', $last_post_date);
3526
    list ($hour, $min, $sec) = explode(':', $last_post_time);
3527
    return mktime((int)$hour, (int)$min, (int)$sec, (int)$month, (int)$day, (int)$year);
3528
}
3529
3530
/**
3531
 * Gets a database (MySQL) datetime format string from a UNIX timestamp
3532
 * @param   int     UNIX timestamp, as generated by the time() function. Will be generated if parameter not provided
3533
 * @return  string  MySQL datetime format, like '2009-01-30 12:23:34'
3534
 */
3535
function api_get_datetime($time = null) {
3536
    if (!isset($time)) { $time = time(); }
3537
    return date('Y-m-d H:i:s', $time);
3538
}
3539
3540
/**
3541
 * Gets item visibility from the item_property table
3542
 *
3543
 * Getting the visibility is done by getting the last updated visibility entry,
3544
 * using the largest session ID found if session 0 and another was found (meaning
3545
 * the only one that is actually from the session, in case there are results from
3546
 * session 0 *AND* session n).
3547
 * @param array     Course properties array (result of api_get_course_info())
3548
 * @param string    Tool (learnpath, document, etc)
3549
 * @param int       The item ID in the given tool
3550
 * @param int       The session ID (optional)
3551
 * @param string $tool
3552
 * @param integer $user_id
3553
 * @param string $type
3554
 * @return int      -1 on error, 0 if invisible, 1 if visible
3555
 */
3556
function api_get_item_visibility(
3557
    $_course,
3558
    $tool,
3559
    $id,
3560
    $session = 0,
3561
    $user_id = null,
3562
    $type = null,
3563
    $group_id = null
3564
) {
3565
    if (!is_array($_course) || count($_course) == 0 || empty($tool) || empty($id)) {
3566
        return -1;
3567
    }
3568
3569
    $tool = Database::escape_string($tool);
3570
    $id = intval($id);
3571
    $session = (int) $session;
3572
    $TABLE_ITEMPROPERTY = Database::get_course_table(TABLE_ITEM_PROPERTY);
3573
    $course_id = intval($_course['real_id']);
3574
3575
    $userCondition = '';
3576
    if (!empty($user_id)) {
3577
        $user_id = intval($user_id);
3578
        $userCondition = " AND to_user_id = $user_id ";
3579
    }
3580
3581
    $typeCondition = '';
3582
    if (!empty($type)) {
3583
        $type = Database::escape_string($type);
3584
        $typeCondition = " AND lastedit_type = '$type' ";
3585
    }
3586
3587
    $groupCondition = '';
3588
    if (!empty($group_id)) {
3589
        $group_id = intval($group_id);
3590
        $groupCondition = " AND to_group_id = '$group_id' ";
3591
    }
3592
3593
    $sql = "SELECT visibility
3594
            FROM $TABLE_ITEMPROPERTY
3595
            WHERE
3596
                c_id = $course_id AND
3597
                tool = '$tool' AND
3598
                ref = $id AND
3599
                (session_id = $session OR session_id = 0 OR session_id IS NULL)
3600
                $userCondition $typeCondition $groupCondition
3601
            ORDER BY session_id DESC, lastedit_date DESC
3602
            LIMIT 1";
3603
3604
    $res = Database::query($sql);
3605
    if ($res === false || Database::num_rows($res) == 0) {
3606
        return -1;
3607
    }
3608
    $row = Database::fetch_array($res);
3609
3610
    return $row['visibility'];
3611
}
3612
3613
/**
3614
 * Delete a row in the c_item_property table
3615
 *
3616
 * @param array $courseInfo
3617
 * @param string $tool
3618
 * @param int $itemId
3619
 * @param int $userId
3620
 * @param int $groupId
3621
 * @param int $sessionId
3622
 * @return false|null
3623
 */
3624
function api_item_property_delete(
3625
    $courseInfo,
3626
    $tool,
3627
    $itemId,
3628
    $userId,
3629
    $groupId = 0,
3630
    $sessionId = 0
3631
) {
3632
    if (empty($courseInfo)) {
3633
        return false;
3634
    }
3635
3636
    $courseId = intval($courseInfo['real_id']);
3637
3638
    if (empty($courseId) || empty($tool) || empty($itemId)) {
3639
        return false;
3640
    }
3641
3642
    $table = Database::get_course_table(TABLE_ITEM_PROPERTY);
3643
    $tool = Database::escape_string($tool);
3644
    $itemId = intval($itemId);
3645
    $userId = intval($userId);
3646
    $groupId = intval($groupId);
3647
    $sessionId = intval($sessionId);
3648
3649
    $groupCondition = " AND to_group_id = $groupId ";
3650
    if (empty($groupId)) {
3651
        $groupCondition = " AND (to_group_id is NULL OR to_group_id = 0) ";
3652
    }
3653
3654
    $userCondition = " AND to_user_id = $userId ";
3655
    if (empty($userId)) {
3656
        $userCondition = " AND (to_user_id is NULL OR to_user_id = 0) ";
3657
    }
3658
    $sql = "DELETE FROM $table
3659
            WHERE
3660
                c_id = $courseId AND
3661
                tool  = '$tool' AND
3662
                ref = $itemId AND
3663
                session_id = $sessionId
3664
                $userCondition
3665
                $groupCondition
3666
            ";
3667
    Database::query($sql);
3668
}
3669
3670
/**
3671
 * Updates or adds item properties to the Item_propetry table
3672
 * Tool and lastedit_type are language independant strings (langvars->get_lang!)
3673
 *
3674
 * @param array $_course array with course properties
3675
 * @param string $tool tool id, linked to 'rubrique' of the course tool_list (Warning: language sensitive !!)
3676
 * @param int $item_id id of the item itself, linked to key of every tool ('id', ...), "*" = all items of the tool
3677
 * @param string $last_edit_type add or update action
3678
 * (1) message to be translated (in trad4all) : e.g. DocumentAdded, DocumentUpdated;
3679
 * (2) "delete"
3680
 * (3) "visible"
3681
 * (4) "invisible"
3682
 * @param int $user_id : id of the editing/adding user
3683
 * @param int $to_group_id : id of the intended group (0 = for everybody), only relevant for $type (1)
3684
 * @param int $to_user_id : id of the intended user (always has priority over $to_group_id !), only relevant for $type (1)
3685
 * @param string $start_visible 0000-00-00 00:00:00 format
3686
 * @param string $end_visible 0000-00-00 00:00:00 format
3687
 * @param int $session_id The session ID, if any, otherwise will default to 0
3688
 * @return boolean False if update fails.
3689
 * @author Toon Van Hoecke <[email protected]>, Ghent University
3690
 * @version January 2005
3691
 * @desc update the item_properties table (if entry not exists, insert) of the course
3692
 */
3693
function api_item_property_update(
3694
    $_course,
3695
    $tool,
3696
    $item_id,
3697
    $last_edit_type,
3698
    $user_id,
3699
    $to_group_id = 0,
3700
    $to_user_id = null,
3701
    $start_visible = '',
3702
    $end_visible = '',
3703
    $session_id = 0
3704
) {
3705
    if (empty($_course)) {
3706
        return false;
3707
    }
3708
3709
    $course_id = $_course['real_id'];
3710
3711
    if (empty($course_id)) {
3712
        return false;
3713
    }
3714
3715
    // Definition of variables.
3716
    $tool = Database::escape_string($tool);
3717
    $item_id = intval($item_id);
3718
    $lastEditTypeNoFilter = $last_edit_type;
3719
    $last_edit_type = Database::escape_string($last_edit_type);
3720
    $user_id = intval($user_id);
3721
3722
    $startVisible = "NULL";
3723
    if (!empty($start_visible)) {
3724
        $start_visible = Database::escape_string($start_visible);
3725
        $startVisible = "'$start_visible'";
3726
    }
3727
3728
    $endVisible = "NULL";
3729
    if (!empty($end_visible)) {
3730
        $end_visible = Database::escape_string($end_visible);
3731
        $endVisible = "'$end_visible'";
3732
    }
3733
3734
    $to_filter = '';
3735
    $time = api_get_utc_datetime();
3736
3737
    if (!empty($session_id)) {
3738
        $session_id = intval($session_id);
3739
    } else {
3740
        $session_id = api_get_session_id();
3741
    }
3742
3743
    // Definition of tables.
3744
    $tableItemProperty = Database::get_course_table(TABLE_ITEM_PROPERTY);
3745
3746
    if ($to_user_id <= 0) {
3747
        $to_user_id = null; // No to_user_id set
3748
    }
3749
3750
    if (!is_null($to_user_id)) {
3751
        // $to_user_id has more priority than $to_group_id
3752
        $to_user_id = intval($to_user_id);
3753
        $to_field = 'to_user_id';
3754
        $to_value = $to_user_id;
3755
    } else {
3756
        // $to_user_id is not set.
3757
        $to_field = 'to_group_id';
3758
        $to_value = $to_group_id;
3759
    }
3760
3761
    $toValueCondition = empty($to_value) ? "NULL" : "'$to_value'";
3762
3763
    // Set filters for $to_user_id and $to_group_id, with priority for $to_user_id
3764
    $condition_session = " AND session_id = $session_id ";
3765
    if (empty($session_id)) {
3766
        $condition_session = " AND (session_id = 0 OR session_id IS NULL) ";
3767
    }
3768
3769
    $filter = " c_id = $course_id AND tool = '$tool' AND ref = $item_id $condition_session ";
3770
3771
    if ($item_id === '*') {
0 ignored issues
show
Unused Code Bug introduced by
The strict comparison === seems to always evaluate to false as the types of $item_id (integer) and '*' (string) can never be identical. Maybe you want to use a loose comparison == instead?
Loading history...
3772
        // For all (not deleted) items of the tool
3773
        $filter = " c_id = $course_id  AND tool = '$tool' AND visibility <> 2 $condition_session";
3774
    }
3775
3776
    // Check whether $to_user_id and $to_group_id are passed in the function call.
3777
    // If both are not passed (both are null) then it is a message for everybody and $to_group_id should be 0 !
3778
    if (is_null($to_user_id) && is_null($to_group_id)) {
3779
        $to_group_id = 0;
3780
    }
3781
3782
    if (!is_null($to_user_id)) {
3783
        // Set filter to intended user.
3784
        $to_filter = " AND to_user_id = $to_user_id $condition_session";
3785
    } else {
3786
        // Set filter to intended group.
3787
        if (($to_group_id != 0) && $to_group_id == strval(intval($to_group_id))) {
3788
            $to_filter = " AND to_group_id = $to_group_id $condition_session";
3789
        }
3790
    }
3791
3792
    // Adding filter if set.
3793
    $filter .= $to_filter;
3794
3795
    // Update if possible
3796
    $set_type = '';
3797
3798
    switch ($lastEditTypeNoFilter) {
3799 View Code Duplication
        case 'delete':
3800
            // delete = make item only visible for the platform admin.
3801
            $visibility = '2';
3802
            if (!empty($session_id)) {
3803
                // Check whether session id already exist into item_properties for updating visibility or add it.
3804
                $sql = "SELECT session_id FROM $tableItemProperty
3805
                        WHERE
3806
                            c_id = $course_id AND
3807
                            tool = '$tool' AND
3808
                            ref = $item_id AND
3809
                            session_id = $session_id";
3810
                $rs = Database::query($sql);
3811
                if (Database::num_rows($rs) > 0) {
3812
                    $sql = "UPDATE $tableItemProperty
3813
                            SET lastedit_type       = '".str_replace('_', '', ucwords($tool))."Deleted',
3814
                                lastedit_date       = '$time',
3815
                                lastedit_user_id    = $user_id,
3816
                                visibility          = $visibility,
3817
                                session_id          = $session_id $set_type
3818
                            WHERE $filter";
3819
                    $result = Database::query($sql);
3820
                } else {
3821
                    $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)
3822
                            VALUES ($course_id, '$tool',$item_id, '$time', $user_id, '$time', '$last_edit_type',$user_id, $toValueCondition, $visibility, $startVisible, $endVisible, $session_id)";
3823
                    $result = Database::query($sql);
3824
                    $id = Database::insert_id();
3825
                    if ($id) {
3826
                        $sql = "UPDATE $tableItemProperty SET id = iid WHERE iid = $id";
3827
                        Database::query($sql);
3828
                    }
3829
                }
3830
            } else {
3831
                $sql = "UPDATE $tableItemProperty
3832
                        SET
3833
                            lastedit_type='".str_replace('_', '', ucwords($tool))."Deleted',
3834
                            lastedit_date='$time',
3835
                            lastedit_user_id = $user_id,
3836
                            visibility = $visibility $set_type
3837
                        WHERE $filter";
3838
                $result = Database::query($sql);
3839
            }
3840
            break;
3841 View Code Duplication
        case 'visible' : // Change item to visible.
3842
            $visibility = '1';
3843
            if (!empty($session_id)) {
3844
                // Check whether session id already exist into item_properties for updating visibility or add it.
3845
                $sql = "SELECT session_id FROM $tableItemProperty
3846
                        WHERE
3847
                            c_id = $course_id AND
3848
                            tool = '$tool' AND
3849
                            ref = $item_id AND
3850
                            session_id = $session_id";
3851
                $rs = Database::query($sql);
3852
                if (Database::num_rows($rs) > 0) {
3853
                    $sql = "UPDATE $tableItemProperty
3854
                            SET
3855
                                lastedit_type='".str_replace('_', '', ucwords($tool))."Visible',
3856
                                lastedit_date='$time',
3857
                                lastedit_user_id = $user_id,
3858
                                visibility = $visibility,
3859
                                session_id = $session_id $set_type
3860
                            WHERE $filter";
3861
                    $result = Database::query($sql);
3862
                } else {
3863
                    $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)
3864
                            VALUES ($course_id, '$tool', $item_id, '$time', $user_id, '$time', '$last_edit_type', $user_id, $toValueCondition, $visibility, $startVisible, $endVisible, $session_id)";
3865
                    $result = Database::query($sql);
3866
                    $id = Database::insert_id();
3867
                    if ($id) {
3868
                        $sql = "UPDATE $tableItemProperty SET id = iid WHERE iid = $id";
3869
                        Database::query($sql);
3870
                    }
3871
                }
3872
            } else {
3873
                $sql = "UPDATE $tableItemProperty
3874
                        SET
3875
                            lastedit_type='".str_replace('_', '', ucwords($tool))."Visible',
3876
                            lastedit_date='$time',
3877
                            lastedit_user_id = $user_id,
3878
                            visibility = $visibility $set_type
3879
                        WHERE $filter";
3880
                $result = Database::query($sql);
3881
            }
3882
            break;
3883 View Code Duplication
        case 'invisible' : // Change item to invisible.
3884
            $visibility = '0';
3885
            if (!empty($session_id)) {
3886
                // Check whether session id already exist into item_properties for updating visibility or add it
3887
                $sql = "SELECT session_id FROM $tableItemProperty
3888
                        WHERE
3889
                            c_id = $course_id AND
3890
                            tool = '$tool' AND
3891
                            ref = $item_id AND
3892
                            session_id = $session_id";
3893
                $rs = Database::query($sql);
3894
                if (Database::num_rows($rs) > 0) {
3895
                    $sql = "UPDATE $tableItemProperty
3896
                            SET
3897
                                lastedit_type = '".str_replace('_', '', ucwords($tool))."Invisible',
3898
                                lastedit_date = '$time',
3899
                                lastedit_user_id = $user_id,
3900
                                visibility = $visibility,
3901
                                session_id = $session_id $set_type
3902
                            WHERE $filter";
3903
                    $result = Database::query($sql);
3904
                } else {
3905
                    $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)
3906
                            VALUES ($course_id, '$tool', $item_id, '$time', $user_id, '$time', '$last_edit_type', $user_id, $toValueCondition, $visibility, $startVisible, $endVisible, $session_id)";
3907
                    $result = Database::query($sql);
3908
                    $id = Database::insert_id();
3909
                    if ($id) {
3910
                        $sql = "UPDATE $tableItemProperty SET id = iid WHERE iid = $id";
3911
                        Database::query($sql);
3912
                    }
3913
                }
3914
            } else {
3915
                $sql = "UPDATE $tableItemProperty
3916
                        SET
3917
                            lastedit_type = '".str_replace('_', '', ucwords($tool))."Invisible',
3918
                            lastedit_date = '$time',
3919
                            lastedit_user_id = $user_id,
3920
                            visibility = $visibility $set_type
3921
                        WHERE $filter";
3922
                $result = Database::query($sql);
3923
            }
3924
            break;
3925
        default : // The item will be added or updated.
0 ignored issues
show
Coding Style introduced by
There must be no space before the colon in a DEFAULT statement

As per the PSR-2 coding standard, there must not be a space in front of the colon in the default statement.

switch ($expr) {
    default : //wrong
        doSomething();
        break;
}

switch ($expr) {
    default: //right
        doSomething();
        break;
}

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
3926
            $set_type = ", lastedit_type = '$last_edit_type' ";
3927
            $visibility = '1';
3928
            //$filter .= $to_filter; already added
3929
            $sql = "UPDATE $tableItemProperty
3930
                    SET
3931
                      lastedit_date = '$time',
3932
                      lastedit_user_id = $user_id $set_type
3933
                    WHERE $filter";
3934
            $result = Database::query($sql);
3935
    }
3936
3937
    // Insert if no entries are found (can only happen in case of $last_edit_type switch is 'default').
3938
    if (Database::affected_rows($result) == 0) {
0 ignored issues
show
Bug introduced by
It seems like $result can be null; however, affected_rows() does not accept null, maybe add an additional type check?

Unless you are absolutely sure that the expression can never be null because of other conditions, we strongly recommend to add an additional type check to your code:

/** @return stdClass|null */
function mayReturnNull() { }

function doesNotAcceptNull(stdClass $x) { }

// With potential error.
function withoutCheck() {
    $x = mayReturnNull();
    doesNotAcceptNull($x); // Potential error here.
}

// Safe - Alternative 1
function withCheck1() {
    $x = mayReturnNull();
    if ( ! $x instanceof stdClass) {
        throw new \LogicException('$x must be defined.');
    }
    doesNotAcceptNull($x);
}

// Safe - Alternative 2
function withCheck2() {
    $x = mayReturnNull();
    if ($x instanceof stdClass) {
        doesNotAcceptNull($x);
    }
}
Loading history...
3939
        $sessionCondition = empty($session_id) ? "NULL" : "'$session_id'";
3940
        $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)
3941
                VALUES ($course_id, '$tool', $item_id, '$time', $user_id, '$time', '$last_edit_type', $user_id, $toValueCondition, $visibility, $startVisible, $endVisible, $sessionCondition)";
3942
        Database::query($sql);
3943
        $id = Database::insert_id();
3944
        if ($id) {
3945
            $sql = "UPDATE $tableItemProperty SET id = iid WHERE iid = $id";
3946
            Database::query($sql);
3947
            return false;
3948
        }
3949
    }
3950
3951
    return true;
3952
}
3953
3954
/**
3955
 * Gets item property by tool
3956
 * @param string    course code
3957
 * @param string    tool name, linked to 'rubrique' of the course tool_list (Warning: language sensitive !!)
3958
 * @param int       id of the item itself, linked to key of every tool ('id', ...), "*" = all items of the tool
3959
 * @param int $session_id
3960
 * @param string $tool
3961
 * @param string $course_code
3962
 * @return array All fields from c_item_property (all rows found) or empty array
3963
 */
3964
function api_get_item_property_by_tool($tool, $course_code, $session_id = null)
3965
{
3966
    $course_info = api_get_course_info($course_code);
3967
    $tool = Database::escape_string($tool);
3968
3969
    // Definition of tables.
3970
    $item_property_table = Database::get_course_table(TABLE_ITEM_PROPERTY);
3971
    $session_id = intval($session_id);
3972
    $session_condition = ' AND session_id = '.$session_id;
3973
    if (empty($session_id)) {
3974
        $session_condition = " AND (session_id = 0 OR session_id IS NULL) ";
3975
    }
3976
    $course_id = $course_info['real_id'];
3977
3978
    $sql = "SELECT * FROM $item_property_table
3979
            WHERE
3980
                c_id = $course_id AND
3981
                tool = '$tool'
3982
                $session_condition ";
3983
    $rs  = Database::query($sql);
3984
    $list = array();
3985
    if (Database::num_rows($rs) > 0) {
3986
        while ($row = Database::fetch_array($rs, 'ASSOC')) {
3987
            $list[] = $row;
3988
        }
3989
    }
3990
    return $list;
3991
}
3992
3993
/**
3994
 * Gets item property by tool and user
3995
 * @param int $userId
3996
 * @param int $tool
3997
 * @param int $courseId
3998
 * @param int $session_id
3999
 * @return array
4000
 */
4001
function api_get_item_property_list_by_tool_by_user(
4002
    $userId,
4003
    $tool,
4004
    $courseId,
4005
    $session_id = 0
4006
) {
4007
    $userId = intval($userId);
4008
    $tool = Database::escape_string($tool);
4009
    $session_id = intval($session_id);
4010
    $courseId = intval($courseId);
4011
4012
    // Definition of tables.
4013
    $item_property_table = Database::get_course_table(TABLE_ITEM_PROPERTY);
4014
    $session_condition = ' AND session_id = '.$session_id;
4015
    if (empty($session_id)) {
4016
        $session_condition = " AND (session_id = 0 OR session_id IS NULL) ";
4017
    }
4018
    $sql = "SELECT * FROM $item_property_table
4019
            WHERE
4020
                insert_user_id = $userId AND
4021
                c_id = $courseId AND
4022
                tool = '$tool'
4023
                $session_condition ";
4024
4025
    $rs = Database::query($sql);
4026
    $list = array();
4027
    if (Database::num_rows($rs) > 0) {
4028
        while ($row = Database::fetch_array($rs, 'ASSOC')) {
4029
            $list[] = $row;
4030
        }
4031
    }
4032
4033
    return $list;
4034
}
4035
4036
/**
4037
 * Gets item property id from tool of a course
4038
 * @param string $course_code course code
4039
 * @param string $tool tool name, linked to 'rubrique' of the course tool_list (Warning: language sensitive !!)
4040
 * @param int $ref id of the item itself, linked to key of every tool ('id', ...), "*" = all items of the tool
4041
 * @param int $sessionId Session ID (optional)
4042
 * @return int
4043
 */
4044
function api_get_item_property_id($course_code, $tool, $ref, $sessionId = 0)
4045
{
4046
    $course_info = api_get_course_info($course_code);
4047
    $tool = Database::escape_string($tool);
4048
    $ref = intval($ref);
4049
4050
    // Definition of tables.
4051
    $tableItemProperty = Database::get_course_table(TABLE_ITEM_PROPERTY);
4052
    $course_id = $course_info['real_id'];
4053
    $sessionCondition = " AND session_id = $sessionId ";
4054
    if (empty($sessionId)) {
4055
        $sessionCondition = " AND (session_id = 0 OR session_id IS NULL) ";
4056
    }
4057
    $sql = "SELECT id FROM $tableItemProperty
4058
            WHERE
4059
                c_id = $course_id AND
4060
                tool = '$tool' AND
4061
                ref = $ref
4062
                $sessionCondition";
4063
    $rs  = Database::query($sql);
4064
    $item_property_id = '';
4065
    if (Database::num_rows($rs) > 0) {
4066
        $row = Database::fetch_array($rs);
4067
        $item_property_id = $row['id'];
4068
    }
4069
    return $item_property_id;
4070
}
4071
4072
/**
4073
 * Inserts a record in the track_e_item_property table (No update)
4074
 * @param string $tool
4075
 * @param int $ref
4076
 * @param string $title
4077
 * @param string $content
4078
 * @param int $progress
4079
 * @return bool|int
4080
 */
4081
function api_track_item_property_update($tool, $ref, $title, $content, $progress)
4082
{
4083
    $tbl_stats_item_property = Database::get_main_table(TABLE_STATISTIC_TRACK_E_ITEM_PROPERTY);
4084
    $course_id = api_get_real_course_id(); //numeric
4085
    $course_code = api_get_course_id(); //alphanumeric
4086
    $item_property_id = api_get_item_property_id($course_code, $tool, $ref);
4087
    if (!empty($item_property_id)) {
4088
        $sql = "INSERT IGNORE INTO $tbl_stats_item_property SET
4089
                course_id           = '$course_id',
4090
                item_property_id    = '$item_property_id',
4091
                title               = '".Database::escape_string($title)."',
4092
                content             = '".Database::escape_string($content)."',
4093
                progress            = '".intval($progress)."',
4094
                lastedit_date       = '".api_get_utc_datetime()."',
4095
                lastedit_user_id    = '".api_get_user_id()."',
4096
                session_id          = '".api_get_session_id()."'";
4097
        $result = Database::query($sql);
4098
        $affected_rows = Database::affected_rows($result);
4099
4100
        return $affected_rows;
4101
    }
4102
4103
    return false;
4104
}
4105
4106
/**
4107
 * @param string $tool
4108
 * @param int $ref
4109
 * @return array|resource
4110
 */
4111
function api_get_track_item_property_history($tool, $ref)
4112
{
4113
    $tbl_stats_item_property = Database::get_main_table(TABLE_STATISTIC_TRACK_E_ITEM_PROPERTY);
4114
    $course_id = api_get_real_course_id(); //numeric
4115
    $course_code = api_get_course_id(); //alphanumeric
4116
    $item_property_id = api_get_item_property_id($course_code, $tool, $ref);
4117
    $sql = "SELECT * FROM $tbl_stats_item_property
4118
            WHERE item_property_id = $item_property_id AND course_id = $course_id
4119
            ORDER BY lastedit_date DESC";
4120
    $result = Database::query($sql);
4121
    $result = Database::store_result($result,'ASSOC');
0 ignored issues
show
Bug introduced by
It seems like $result can be null; however, store_result() does not accept null, maybe add an additional type check?

Unless you are absolutely sure that the expression can never be null because of other conditions, we strongly recommend to add an additional type check to your code:

/** @return stdClass|null */
function mayReturnNull() { }

function doesNotAcceptNull(stdClass $x) { }

// With potential error.
function withoutCheck() {
    $x = mayReturnNull();
    doesNotAcceptNull($x); // Potential error here.
}

// Safe - Alternative 1
function withCheck1() {
    $x = mayReturnNull();
    if ( ! $x instanceof stdClass) {
        throw new \LogicException('$x must be defined.');
    }
    doesNotAcceptNull($x);
}

// Safe - Alternative 2
function withCheck2() {
    $x = mayReturnNull();
    if ($x instanceof stdClass) {
        doesNotAcceptNull($x);
    }
}
Loading history...
4122
    return $result;
4123
}
4124
4125
/**
4126
 * Gets item property data from tool of a course id
4127
 * @param int $course_id
4128
 * @param string $tool   tool name, linked to 'rubrique' of the course tool_list (Warning: language sensitive !!)
4129
 * @param int $ref id of the item itself, linked to key of every tool ('id', ...), "*" = all items of the tool
4130
 * @param int $session_id
4131
 * @param int $groupId
4132
 *
4133
 * @return array Array with all fields from c_item_property, empty array if not found or false if course could not be found
4134
 */
4135
function api_get_item_property_info($course_id, $tool, $ref, $session_id = 0, $groupId = 0)
4136
{
4137
    $courseInfo = api_get_course_info_by_id($course_id);
4138
4139
    if (empty($courseInfo)) {
4140
        return false;
4141
    }
4142
4143
    $tool = Database::escape_string($tool);
4144
    $ref = intval($ref);
4145
    $course_id = $courseInfo['real_id'];
4146
    $session_id = intval($session_id);
4147
4148
    $sessionCondition = " session_id = $session_id";
4149
    if (empty($session_id)) {
4150
        $sessionCondition = " (session_id = 0 OR session_id IS NULL) ";
4151
    }
4152
4153
    // Definition of tables.
4154
    $table = Database::get_course_table(TABLE_ITEM_PROPERTY);
4155
4156
    $sql = "SELECT * FROM $table
4157
            WHERE
4158
                c_id = $course_id AND
4159
                tool = '$tool' AND
4160
                ref = $ref AND
4161
                $sessionCondition ";
4162
4163
    if (!empty($groupId)) {
4164
        $groupId = intval($groupId);
4165
        $sql .= " AND to_group_id = $groupId ";
4166
    }
4167
4168
    $rs  = Database::query($sql);
4169
    $row = array();
4170
    if (Database::num_rows($rs) > 0) {
4171
        $row = Database::fetch_array($rs,'ASSOC');
4172
    }
4173
4174
    return $row;
4175
}
4176
4177
/**
4178
 * Displays a combo box so the user can select his/her preferred language.
4179
 * @param string The desired name= value for the select
4180
 * @param bool Whether we use the JQuery Chozen library or not
4181
 * (in some cases, like the indexing language picker, it can alter the presentation)
4182
 * @return string
4183
 */
4184
4185
function api_get_languages_combo($name = 'language')
4186
{
4187
    $ret = '';
4188
    $platformLanguage = api_get_setting('platformLanguage');
4189
4190
    // Retrieve a complete list of all the languages.
4191
    $language_list = api_get_languages();
4192
4193
    if (count($language_list['name']) < 2) {
4194
        return $ret;
4195
    }
4196
4197
    // The the current language of the user so that his/her language occurs as selected in the dropdown menu.
4198
    if (isset($_SESSION['user_language_choice'])) {
4199
        $default = $_SESSION['user_language_choice'];
4200
    } else {
4201
        $default = $platformLanguage;
4202
    }
4203
4204
    $languages  = $language_list['name'];
4205
    $folder     = $language_list['folder'];
4206
4207
    $ret .= '<select name="' . $name . '" id="language_chosen" class="selectpicker show-tick form-control">';
4208
    foreach ($languages as $key => $value) {
4209
        if ($folder[$key] == $default) {
4210
            $selected = ' selected="selected"';
4211
        } else {
4212
            $selected = '';
4213
        }
4214
        $ret .= sprintf('<option value=%s" %s>%s</option>', $folder[$key], $selected, $value);
4215
    }
4216
    $ret .= '</select>';
4217
    return $ret;
4218
}
4219
4220
/**
4221
 * Displays a form (drop down menu) so the user can select his/her preferred language.
4222
 * The form works with or without javascript
4223
 * @param  boolean Hide form if only one language available (defaults to false = show the box anyway)
4224
 * @return null|string Display the box directly
4225
 */
4226
function api_display_language_form($hide_if_no_choice = false)
4227
{
4228
    // Retrieve a complete list of all the languages.
4229
    $language_list = api_get_languages();
4230
    if (count($language_list['name']) <= 1 && $hide_if_no_choice) {
4231
        return; //don't show any form
4232
    }
4233
4234
    // The the current language of the user so that his/her language occurs as selected in the dropdown menu.
4235
    if (isset($_SESSION['user_language_choice'])) {
4236
        $user_selected_language = $_SESSION['user_language_choice'];
4237
    }
4238
    if (empty($user_selected_language)) {
4239
        $user_selected_language = api_get_setting('platformLanguage');
4240
    }
4241
4242
    $original_languages = $language_list['name'];
4243
    $folder = $language_list['folder']; // This line is probably no longer needed.
4244
    $html = '
4245
    <script type="text/javascript">
4246
    <!--
4247
    $(document).ready(function() {
4248
        $("#language_list").change(function() {
4249
            jumpMenu("parent",this,0);
4250
        });
4251
    });
4252
4253
    function jumpMenu(targ,selObj,restore){ // v3.0
4254
        eval(targ+".location=\'"+selObj.options[selObj.selectedIndex].value+"\'");
4255
        if (restore) selObj.selectedIndex=0;
4256
    }
4257
    //-->
4258
    </script>';
4259
    $html .= '<form id="lang_form" name="lang_form" method="post" action="'.api_get_self().'">';
4260
    $html .= '<label style="display: none;" for="language_list">' . get_lang('Language') . '</label>';
4261
    $html .=  '<select id="language_list" class="selectpicker show-tick form-control" name="language_list" >';
4262
4263
    foreach ($original_languages as $key => $value) {
4264
        if ($folder[$key] == $user_selected_language) {
4265
            $option_end = ' selected="selected" >';
4266
        } else {
4267
            $option_end = '>';
4268
        }
4269
        $html .=  '<option value="'.api_get_self().'?language='.$folder[$key].'"'.$option_end;
4270
        //echo substr($value, 0, 16); // Cut string to keep 800x600 aspect.
4271
        $html .=  $value.'</option>';
4272
    }
4273
    $html .=  '</select>';
4274
    $html .=  '<noscript><input type="submit" name="user_select_language" value="'.get_lang('Ok').'" /></noscript>';
4275
    $html .=  '</form>';
4276
    return $html;
4277
}
4278
4279
/**
4280
 * Returns a list of all the languages that are made available by the admin.
4281
 * @return array An array with all languages. Structure of the array is
4282
 *  array['name'] = An array with the name of every language
4283
 *  array['folder'] = An array with the corresponding names of the language-folders in the filesystem
4284
 */
4285
function api_get_languages() {
4286
    $tbl_language = Database::get_main_table(TABLE_MAIN_LANGUAGE);
4287
    $sql = "SELECT * FROM $tbl_language WHERE available='1' ORDER BY original_name ASC";
4288
    $result = Database::query($sql);
4289
    $language_list = array();
4290
    while ($row = Database::fetch_array($result)) {
4291
        $language_list['name'][] = $row['original_name'];
4292
        $language_list['folder'][] = $row['dokeos_folder'];
4293
    }
4294
    return $language_list;
4295
}
4296
4297
/**
4298
 * Returns a list of all the languages that are made available by the admin.
4299
 * @return array
4300
 */
4301
function api_get_languages_to_array() {
4302
    $tbl_language = Database::get_main_table(TABLE_MAIN_LANGUAGE);
4303
    $sql = "SELECT * FROM $tbl_language WHERE available='1' ORDER BY original_name ASC";
4304
    $result = Database::query($sql);
4305
    $languages = array();
4306
    while ($row = Database::fetch_array($result)) {
4307
        $languages[$row['dokeos_folder']] = $row['original_name'];
4308
    }
4309
    return $languages;
4310
}
4311
4312
/**
4313
 * Returns the id (the database id) of a language
4314
 * @param   string  language name (the corresponding name of the language-folder in the filesystem)
4315
 * @return  int     id of the language
4316
 */
4317
function api_get_language_id($language)
4318
{
4319
    $tbl_language = Database::get_main_table(TABLE_MAIN_LANGUAGE);
4320
    if (empty($language)) {
4321
        return null;
4322
    }
4323
    $language = Database::escape_string($language);
4324
    $sql = "SELECT id FROM $tbl_language
4325
            WHERE dokeos_folder = '$language' LIMIT 1";
4326
    $result = Database::query($sql);
4327
    $row = Database::fetch_array($result);
4328
    return $row['id'];
4329
}
4330
4331
/**
4332
 * Gets language of the requested type for the current user. Types are :
4333
 * user_profil_lang : profile language of current user
4334
 * user_select_lang : language selected by user at login
4335
 * course_lang : language of the current course
4336
 * platform_lang : default platform language
4337
 * @param string $lang_type
4338
 * @return string
4339
 **/
4340
function api_get_language_from_type($lang_type)
4341
{
4342
    $return = false;
4343
4344
    switch ($lang_type) {
4345
        case 'platform_lang':
4346
            $temp_lang = api_get_setting('platformLanguage');
4347
            if (!empty($temp_lang))
4348
                $return = $temp_lang;
4349
            break;
4350
        case 'user_profil_lang':
4351
            $_user = api_get_user_info();
4352 View Code Duplication
            if (isset($_user['language']) && !empty($_user['language']))
4353
                $return = $_user['language'];
4354
            break;
4355
        case 'user_selected_lang':
4356
            if (isset($_SESSION['user_language_choice']) && !empty($_SESSION['user_language_choice']))
4357
                $return = $_SESSION['user_language_choice'];
4358
            break;
4359
        case 'course_lang':
4360
            global $_course;
4361
            $cidReq = null;
4362
            if (empty($_course)) {
4363
                // Code modified because the local.inc.php file it's declarated after this work
4364
                // causing the function api_get_course_info() returns a null value
4365
                $cidReq = isset($_GET["cidReq"]) ? Database::escape_string($_GET["cidReq"]) : null;
4366
                $cDir = (!empty($_GET['cDir']) ? $_GET['cDir'] : null);
4367
                if (empty($cidReq) && !empty($cDir)) {
4368
                    $c = CourseManager::get_course_id_from_path($cDir);
4369
                    if ($c) {
4370
                        $cidReq = $c;
4371
                    }
4372
                }
4373
            }
4374
            $_course = api_get_course_info($cidReq);
4375 View Code Duplication
            if (isset($_course['language']) && !empty($_course['language']))
4376
                $return = $_course['language'];
4377
            break;
4378
        default:
4379
            $return = false;
4380
        break;
4381
    }
4382
4383
    return $return;
4384
}
4385
4386
function api_get_language_info($language_id) {
4387
    $tbl_admin_languages = Database :: get_main_table(TABLE_MAIN_LANGUAGE);
4388
    $sql = 'SELECT * FROM '.$tbl_admin_languages.' WHERE id = "'.intval($language_id).'"';
4389
    $rs = Database::query($sql);
4390
    $language_info = array();
4391
    if (Database::num_rows($rs)) {
4392
        $language_info = Database::fetch_array($rs,'ASSOC');
4393
    }
4394
    return $language_info;
4395
}
4396
4397
/**
4398
 * Returns the name of the visual (CSS) theme to be applied on the current page.
4399
 * The returned name depends on the platform, course or user -wide settings.
4400
 * @return string   The visual theme's name, it is the name of a folder inside .../chamilo/main/css/
4401
 */
4402
function api_get_visual_theme()
4403
{
4404
    static $visual_theme;
4405
    if (!isset($visual_theme)) {
4406
4407
        $platform_theme = api_get_setting('stylesheets');
4408
4409
        // Platform's theme.
4410
        $visual_theme = $platform_theme;
4411
4412
        if (api_get_setting('user_selected_theme') == 'true') {
4413
            $user_info = api_get_user_info();
4414
            if (isset($user_info['theme'])) {
4415
                $user_theme = $user_info['theme'];
4416
4417
                if (!empty($user_theme)) {
4418
                    $visual_theme = $user_theme;
4419
                    // User's theme.
4420
                }
4421
            }
4422
        }
4423
4424
        $course_id = api_get_course_id();
4425
4426
        if (!empty($course_id) && $course_id != -1) {
4427
            if (api_get_setting('allow_course_theme') == 'true') {
4428
                $course_theme = api_get_course_setting('course_theme');
4429
4430
                if (!empty($course_theme) && $course_theme != -1) {
4431
                    if (!empty($course_theme)) {
4432
                        // Course's theme.
4433
                        $visual_theme = $course_theme;
4434
                    }
4435
                }
4436
4437
                $allow_lp_theme = api_get_course_setting('allow_learning_path_theme');
4438
                if ($allow_lp_theme == 1) {
4439
                    global $lp_theme_css, $lp_theme_config;
4440
                    // These variables come from the file lp_controller.php.
4441
                    if (!$lp_theme_config) {
4442
                        if (!empty($lp_theme_css)) {
4443
                            // LP's theme.
4444
                            $visual_theme = $lp_theme_css;
4445
                        }
4446
                    }
4447
                }
4448
            }
4449
        }
4450
4451
        if (empty($visual_theme)) {
4452
            $visual_theme = 'chamilo';
4453
        }
4454
4455
        global $lp_theme_log;
4456
        if ($lp_theme_log) {
4457
            $visual_theme = $platform_theme;
4458
        }
4459
    }
4460
4461
    return $visual_theme;
4462
}
4463
4464
/**
4465
 * Returns a list of CSS themes currently available in the CSS folder
4466
 * @return array        List of themes directories from the css folder
4467
 * Note: Directory names (names of themes) in the file system should contain ASCII-characters only.
4468
 */
4469
function api_get_themes() {
4470
    $cssdir = api_get_path(SYS_CSS_PATH) . 'themes/';
4471
    $list_dir = array();
4472
    $list_name = array();
4473
4474
    if (is_dir($cssdir)) {
4475
        $themes = @scandir($cssdir);
4476
4477
        if (is_array($themes)) {
4478
            if ($themes !== false) {
4479
                sort($themes);
4480
4481
                foreach ($themes as & $theme) {
4482
                    if (substr($theme, 0, 1) == '.') {
4483
                        continue;
4484
                    } else {
4485
                        if (is_dir($cssdir.$theme)) {
4486
                            $list_dir[] = $theme;
4487
                            $list_name[] = ucwords(str_replace('_', ' ', $theme));
4488
                        }
4489
                    }
4490
                }
4491
            }
4492
        }
4493
    }
4494
4495
    return array($list_dir, $list_name);
4496
}
4497
4498
/**
4499
 * Find the largest sort value in a given user_course_category
4500
 * This function is used when we are moving a course to a different category
4501
 * and also when a user subscribes to courses (the new course is added at the end of the main category
4502
 * @author Patrick Cool <[email protected]>, Ghent University
4503
 * @param int $user_course_category: the id of the user_course_category
0 ignored issues
show
Documentation introduced by
There is no parameter named $user_course_category:. Did you maybe mean $user_course_category?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function. It has, however, found a similar but not annotated parameter which might be a good fit.

Consider the following example. The parameter $ireland is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $ireland
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was changed, but the annotation was not.

Loading history...
4504
 * @param integer $user_id
4505
 * @return int the value of the highest sort of the user_course_category
4506
 */
4507
function api_max_sort_value($user_course_category, $user_id)
4508
{
4509
    $tbl_course_user = Database::get_main_table(TABLE_MAIN_COURSE_USER);
4510
    $sql = "SELECT max(sort) as max_sort FROM $tbl_course_user
4511
            WHERE
4512
                user_id='".intval($user_id)."' AND
4513
                relation_type<>".COURSE_RELATION_TYPE_RRHH." AND
4514
                user_course_cat='".intval($user_course_category)."'";
4515
    $result_max = Database::query($sql);
4516
    if (Database::num_rows($result_max) == 1) {
4517
        $row_max = Database::fetch_array($result_max);
4518
        return $row_max['max_sort'];
4519
    }
4520
    return 0;
4521
}
4522
4523
/**
4524
 * This function converts the string "true" or "false" to a boolean true or false.
4525
 * This function is in the first place written for the Chamilo Config Settings (also named AWACS)
4526
 * @param string "true" or "false"
4527
 * @return boolean true or false
4528
 * @author Patrick Cool <[email protected]>, Ghent University
4529
 */
4530
function api_string_2_boolean($string) {
4531
    if ($string == 'true') {
4532
        return true;
4533
    }
4534
    if ($string == 'false') {
4535
        return false;
4536
    }
4537
    return false;
4538
}
4539
4540
/**
4541
 * Determines the number of plugins installed for a given location
4542
 */
4543
function api_number_of_plugins($location) {
4544
    global $_plugins;
4545
    return isset($_plugins[$location]) && is_array($_plugins[$location]) ? count($_plugins[$location]) : 0;
4546
}
4547
4548
/**
4549
 * Transforms a number of seconds in hh:mm:ss format
4550
 * @author Julian Prud'homme
4551
 * @param integer the number of seconds
4552
 * @return string the formated time
4553
 */
4554
function api_time_to_hms($seconds)
4555
{
4556
    // $seconds = -1 means that we have wrong data in the db.
4557
    if ($seconds == -1) {
4558
        return
4559
            get_lang('Unknown').
4560
            Display::return_icon(
4561
                'info2.gif',
4562
                get_lang('WrongDatasForTimeSpentOnThePlatform'),
4563
                array('align' => 'absmiddle', 'hspace' => '3px')
4564
            );
4565
    }
4566
4567
    // How many hours ?
4568
    $hours = floor($seconds / 3600);
4569
4570
    // How many minutes ?
4571
    $min = floor(($seconds - ($hours * 3600)) / 60);
4572
4573
    // How many seconds
4574
    $sec = floor($seconds - ($hours * 3600) - ($min * 60));
4575
4576
    if ($sec < 10) {
4577
        $sec = "0$sec";
4578
    }
4579
4580
    if ($min < 10) {
4581
        $min = "0$min";
4582
    }
4583
4584
    return "$hours:$min:$sec";
4585
}
4586
4587
/* FILE SYSTEM RELATED FUNCTIONS */
4588
4589
/**
4590
 * Returns the permissions to be assigned to every newly created directory by the web-server.
4591
 * The return value is based on the platform administrator's setting
4592
 * "Administration > Configuration settings > Security > Permissions for new directories".
4593
 * @return int  Returns the permissions in the format "Owner-Group-Others, Read-Write-Execute", as an integer value.
4594
 */
4595 View Code Duplication
function api_get_permissions_for_new_directories() {
4596
    static $permissions;
4597
    if (!isset($permissions)) {
4598
        $permissions = trim(api_get_setting('permissions_for_new_directories'));
4599
        // The default value 0777 is according to that in the platform administration panel after fresh system installation.
4600
        $permissions = octdec(!empty($permissions) ? $permissions : '0777');
4601
    }
4602
    return $permissions;
4603
}
4604
4605
/**
4606
 * Returns the permissions to be assigned to every newly created directory by the web-server.
4607
 * The return value is based on the platform administrator's setting
4608
 * "Administration > Configuration settings > Security > Permissions for new files".
4609
 * @return int Returns the permissions in the format
4610
 * "Owner-Group-Others, Read-Write-Execute", as an integer value.
4611
 */
4612 View Code Duplication
function api_get_permissions_for_new_files() {
4613
    static $permissions;
4614
    if (!isset($permissions)) {
4615
        $permissions = trim(api_get_setting('permissions_for_new_files'));
4616
        // The default value 0666 is according to that in the platform administration panel after fresh system installation.
4617
        $permissions = octdec(!empty($permissions) ? $permissions : '0666');
4618
    }
4619
    return $permissions;
4620
}
4621
4622
/**
4623
 * Deletes a file, or a folder and its contents
4624
 *
4625
 * @author      Aidan Lister <[email protected]>
4626
 * @version     1.0.3
4627
 * @param       string   $dirname    Directory to delete
4628
 * @param       bool     Deletes only the content or not
4629
 * @param       bool     $strict if one folder/file fails stop the loop
4630
 * @return      bool     Returns TRUE on success, FALSE on failure
4631
 * @link http://aidanlister.com/2004/04/recursively-deleting-a-folder-in-php/
4632
 * @author      Yannick Warnier, adaptation for the Chamilo LMS, April, 2008
4633
 * @author      Ivan Tcholakov, a sanity check about Directory class creation has been added, September, 2009
4634
 */
4635
function rmdirr($dirname, $delete_only_content_in_folder = false, $strict = false) {
4636
    $res = true;
4637
4638
    // A sanity check.
4639
    if (!file_exists($dirname)) {
4640
        return false;
4641
    }
4642
    $php_errormsg = '';
4643
    // Simple delete for a file.
4644
    if (is_file($dirname) || is_link($dirname)) {
4645
        $res = unlink($dirname);
4646 View Code Duplication
        if ($res === false) {
4647
            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);
4648
        }
4649
        return $res;
4650
    }
4651
4652
    // Loop through the folder.
4653
    $dir = dir($dirname);
4654
    // A sanity check.
4655
    $is_object_dir = is_object($dir);
4656 View Code Duplication
    if ($is_object_dir) {
4657
        while (false !== $entry = $dir->read()) {
4658
            // Skip pointers.
4659
            if ($entry == '.' || $entry == '..') {
4660
                continue;
4661
            }
4662
4663
            // Recurse.
4664
            if ($strict) {
4665
                $result = rmdirr("$dirname/$entry");
4666
                if ($result == false) {
4667
                    $res = false;
4668
                    break;
4669
                }
4670
            } else {
4671
                rmdirr("$dirname/$entry");
4672
            }
4673
        }
4674
    }
4675
4676
    // Clean up.
4677
    if ($is_object_dir) {
4678
        $dir->close();
4679
    }
4680
4681
    if ($delete_only_content_in_folder == false) {
4682
        $res = rmdir($dirname);
4683 View Code Duplication
        if ($res === false) {
4684
            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);
4685
        }
4686
    }
4687
    return $res;
4688
}
4689
4690
// TODO: This function is to be simplified. File access modes to be implemented.
4691
/**
4692
 * function adapted from a php.net comment
4693
 * copy recursively a folder
4694
 * @param the source folder
4695
 * @param the dest folder
4696
 * @param an array of excluded file_name (without extension)
4697
 * @param copied_files the returned array of copied files
4698
 * @param string $source
4699
 * @param string $dest
4700
 */
4701
function copyr($source, $dest, $exclude = array(), $copied_files = array()) {
4702
    if (empty($dest)) { return false; }
4703
    // Simple copy for a file
4704
    if (is_file($source)) {
4705
        $path_info = pathinfo($source);
4706
        if (!in_array($path_info['filename'], $exclude)) {
4707
            copy($source, $dest);
4708
        }
4709
        return true;
4710
    } elseif (!is_dir($source)) {
4711
        //then source is not a dir nor a file, return
4712
        return false;
4713
    }
4714
4715
    // Make destination directory.
4716
    if (!is_dir($dest)) {
4717
        mkdir($dest, api_get_permissions_for_new_directories());
4718
    }
4719
4720
    // Loop through the folder.
4721
    $dir = dir($source);
4722
    while (false !== $entry = $dir->read()) {
4723
        // Skip pointers
4724
        if ($entry == '.' || $entry == '..') {
4725
            continue;
4726
        }
4727
4728
        // Deep copy directories.
4729
        if ($dest !== "$source/$entry") {
4730
            $files = copyr("$source/$entry", "$dest/$entry", $exclude, $copied_files);
4731
        }
4732
    }
4733
    // Clean up.
4734
    $dir->close();
4735
    return true;
4736
}
4737
4738
// TODO: Using DIRECTORY_SEPARATOR is not recommended, this is an obsolete approach. Documentation header to be added here.
4739
/**
4740
 * @param string $pathname
4741
 * @param string $base_path_document
4742
 * @param integer $session_id
4743
 */
4744
function copy_folder_course_session(
4745
    $pathname,
4746
    $base_path_document,
4747
    $session_id,
4748
    $course_info,
4749
    $document,
4750
    $source_course_id
4751
) {
4752
    $table = Database :: get_course_table(TABLE_DOCUMENT);
4753
    $session_id = intval($session_id);
4754
    $source_course_id = intval($source_course_id);
4755
4756
    // Check whether directory already exists.
4757
    if (is_dir($pathname) || empty($pathname)) {
4758
        return true;
4759
    }
4760
4761
    // Ensure that a file with the same name does not already exist.
4762
    if (is_file($pathname)) {
4763
        trigger_error('copy_folder_course_session(): File exists', E_USER_WARNING);
4764
        return false;
4765
    }
4766
4767
    $course_id = $course_info['real_id'];
4768
4769
    $folders = explode(DIRECTORY_SEPARATOR,str_replace($base_path_document.DIRECTORY_SEPARATOR,'',$pathname));
4770
4771
    $new_pathname = $base_path_document;
4772
    $path = '';
4773
4774
    foreach ($folders as $folder) {
4775
        $new_pathname .= DIRECTORY_SEPARATOR.$folder;
4776
        $path .= DIRECTORY_SEPARATOR.$folder;
4777
4778
        if (!file_exists($new_pathname)) {
4779
            $path = Database::escape_string($path);
4780
4781
            $sql = "SELECT * FROM $table
4782
                    WHERE
4783
                        c_id = $source_course_id AND
4784
                        path = '$path' AND
4785
                        filetype = 'folder' AND
4786
                        session_id = '$session_id'";
4787
            $rs1  = Database::query($sql);
4788
            $num_rows = Database::num_rows($rs1);
4789
4790
            if ($num_rows == 0) {
4791
                mkdir($new_pathname, api_get_permissions_for_new_directories());
4792
4793
                // Insert new folder with destination session_id.
4794
                $params = [
4795
                    'c_id' => $course_id,
4796
                    'path' => $path,
4797
                    'comment' => $document->comment,
4798
                    'title' => basename($new_pathname),
4799
                    'filetype' => 'folder',
4800
                    'size' => '0',
4801
                    'session_id' => $session_id
4802
                ];
4803
                $document_id = Database::insert($table, $params);
4804
                if ($document_id) {
4805
4806
                    $sql = "UPDATE $table SET id = iid WHERE iid = $document_id";
4807
                    Database::query($sql);
4808
4809
                    api_item_property_update(
4810
                        $course_info,
4811
                        TOOL_DOCUMENT,
4812
                        $document_id,
4813
                        'FolderCreated',
4814
                        api_get_user_id(),
4815
                        0,
4816
                        0,
4817
                        null,
4818
                        null,
4819
                        $session_id
4820
                    );
4821
                }
4822
            }
4823
        }
4824
4825
    } // en foreach
4826
}
4827
4828
// TODO: chmodr() is a better name. Some corrections are needed. Documentation header to be added here.
4829
/**
4830
 * @param string $path
4831
 */
4832
function api_chmod_R($path, $filemode) {
4833
    if (!is_dir($path)) {
4834
        return chmod($path, $filemode);
4835
    }
4836
4837
    $handler = opendir($path);
4838
    while ($file = readdir($handler)) {
4839
        if ($file != '.' && $file != '..') {
4840
            $fullpath = "$path/$file";
4841
            if (!is_dir($fullpath)) {
4842
                if (!chmod($fullpath, $filemode)) {
4843
                    return false;
4844
                }
4845
            } else {
4846
                if (!api_chmod_R($fullpath, $filemode)) {
4847
                    return false;
4848
                }
4849
            }
4850
        }
4851
    }
4852
4853
    closedir($handler);
4854
    return chmod($path, $filemode);
4855
}
4856
4857
4858
// TODO: Where the following function has been copy/pased from? There is no information about author and license. Style, coding conventions...
4859
/**
4860
 * Parse info file format. (e.g: file.info)
4861
 *
4862
 * Files should use an ini-like format to specify values.
4863
 * White-space generally doesn't matter, except inside values.
4864
 * e.g.
4865
 *
4866
 * @verbatim
4867
 *   key = value
4868
 *   key = "value"
4869
 *   key = 'value'
4870
 *   key = "multi-line
4871
 *
4872
 *   value"
4873
 *   key = 'multi-line
4874
 *
4875
 *   value'
4876
 *   key
4877
 *   =
4878
 *   'value'
4879
 * @endverbatim
4880
 *
4881
 * Arrays are created using a GET-like syntax:
4882
 *
4883
 * @verbatim
4884
 *   key[] = "numeric array"
4885
 *   key[index] = "associative array"
4886
 *   key[index][] = "nested numeric array"
4887
 *   key[index][index] = "nested associative array"
4888
 * @endverbatim
4889
 *
4890
 * PHP constants are substituted in, but only when used as the entire value:
4891
 *
4892
 * Comments should start with a semi-colon at the beginning of a line.
4893
 *
4894
 * This function is NOT for placing arbitrary module-specific settings. Use
4895
 * variable_get() and variable_set() for that.
4896
 *
4897
 * Information stored in the module.info file:
4898
 * - name: The real name of the module for display purposes.
4899
 * - description: A brief description of the module.
4900
 * - dependencies: An array of shortnames of other modules this module depends on.
4901
 * - package: The name of the package of modules this module belongs to.
4902
 *
4903
 * Example of .info file:
4904
 * <code>
4905
 * @verbatim
4906
 *   name = Forum
4907
 *   description = Enables threaded discussions about general topics.
4908
 *   dependencies[] = taxonomy
4909
 *   dependencies[] = comment
4910
 *   package = Core - optional
4911
 *   version = VERSION
4912
 * @endverbatim
4913
 * </code>
4914
 * @param string $filename
4915
 *   The file we are parsing. Accepts file with relative or absolute path.
4916
 * @return
4917
 *   The info array.
4918
 */
4919
function parse_info_file($filename) {
4920
    $info = array();
4921
4922
    if (!file_exists($filename)) {
4923
        return $info;
4924
    }
4925
4926
    $data = file_get_contents($filename);
4927
    if (preg_match_all('
4928
        @^\s*                           # Start at the beginning of a line, ignoring leading whitespace
4929
        ((?:
4930
          [^=;\[\]]|                    # Key names cannot contain equal signs, semi-colons or square brackets,
4931
          \[[^\[\]]*\]                  # unless they are balanced and not nested
4932
        )+?)
4933
        \s*=\s*                         # Key/value pairs are separated by equal signs (ignoring white-space)
4934
        (?:
4935
          ("(?:[^"]|(?<=\\\\)")*")|     # Double-quoted string, which may contain slash-escaped quotes/slashes
4936
          (\'(?:[^\']|(?<=\\\\)\')*\')| # Single-quoted string, which may contain slash-escaped quotes/slashes
4937
          ([^\r\n]*?)                   # Non-quoted string
4938
        )\s*$                           # Stop at the next end of a line, ignoring trailing whitespace
4939
        @msx', $data, $matches, PREG_SET_ORDER)) {
4940
        $key = $value1 = $value2 = $value3 = '';
4941
        foreach ($matches as $match) {
4942
            // Fetch the key and value string.
4943
            $i = 0;
4944
            foreach (array('key', 'value1', 'value2', 'value3') as $var) {
4945
                $$var = isset($match[++$i]) ? $match[$i] : '';
4946
            }
4947
            $value = stripslashes(substr($value1, 1, -1)) . stripslashes(substr($value2, 1, -1)) . $value3;
4948
4949
            // Parse array syntax.
4950
            $keys = preg_split('/\]?\[/', rtrim($key, ']'));
4951
            $last = array_pop($keys);
4952
            $parent = &$info;
4953
4954
            // Create nested arrays.
4955
            foreach ($keys as $key) {
4956
                if ($key == '') {
4957
                    $key = count($parent);
4958
                }
4959
                if (!isset($parent[$key]) || !is_array($parent[$key])) {
4960
                    $parent[$key] = array();
4961
                }
4962
                $parent = &$parent[$key];
4963
            }
4964
4965
            // Handle PHP constants.
4966
            if (defined($value)) {
4967
                $value = constant($value);
4968
            }
4969
4970
            // Insert actual value.
4971
            if ($last == '') {
4972
                $last = count($parent);
4973
            }
4974
            $parent[$last] = $value;
4975
        }
4976
    }
4977
    return $info;
4978
}
4979
4980
4981
/**
4982
 * Gets Chamilo version from the configuration files
4983
 * @return string   A string of type "1.8.4", or an empty string if the version could not be found
4984
 */
4985
function api_get_version() {
4986
    global $_configuration;
4987
    return (string)$_configuration['system_version'];
4988
}
4989
4990
/**
4991
 * Gets the software name (the name/brand of the Chamilo-based customized system)
4992
 * @return string
4993
 */
4994
function api_get_software_name() {
4995
    $name = api_get_configuration_value('software_name');
4996
    if (!empty($name)) {
4997
        return $name;
4998
    } else {
4999
        return 'Chamilo';
5000
    }
5001
}
5002
5003
/**
5004
 * Checks whether status given in parameter exists in the platform
5005
 * @param mixed the status (can be either int either string)
5006
 * @return boolean if the status exists, else returns false
5007
 */
5008
function api_status_exists($status_asked) {
5009
    global $_status_list;
5010
    return in_array($status_asked, $_status_list) ? true : isset($_status_list[$status_asked]);
5011
}
5012
5013
/**
5014
 * Checks whether status given in parameter exists in the platform. The function
5015
 * returns the status ID or false if it does not exist, but given the fact there
5016
 * is no "0" status, the return value can be checked against
5017
 * if(api_status_key()) to know if it exists.
5018
 * @param   mixed   The status (can be either int or string)
5019
 * @return  mixed   Status ID if exists, false otherwise
5020
 */
5021
function api_status_key($status) {
5022
    global $_status_list;
5023
    return isset($_status_list[$status]) ? $status : array_search($status, $_status_list);
5024
}
5025
5026
/**
5027
 * Gets the status langvars list
5028
 * @return string[] the list of status with their translations
5029
 */
5030
function api_get_status_langvars() {
5031
    return array(
5032
        COURSEMANAGER   => get_lang('Teacher', ''),
5033
        SESSIONADMIN    => get_lang('SessionsAdmin', ''),
5034
        DRH             => get_lang('Drh', ''),
5035
        STUDENT         => get_lang('Student', ''),
5036
        ANONYMOUS       => get_lang('Anonymous', ''),
5037
        STUDENT_BOSS    => get_lang('RoleStudentBoss', ''),
5038
        INVITEE         => get_lang('Invited'),
5039
    );
5040
}
5041
5042
/**
5043
* The function that retrieves all the possible settings for a certain config setting
5044
* @author Patrick Cool <[email protected]>, Ghent University
5045
*/
5046
function api_get_settings_options($var) {
5047
    $table_settings_options = Database :: get_main_table(TABLE_MAIN_SETTINGS_OPTIONS);
5048
    $var = Database::escape_string($var);
5049
    $sql = "SELECT * FROM $table_settings_options
5050
            WHERE variable = '$var'
5051
            ORDER BY id";
5052
    $result = Database::query($sql);
5053
    $settings_options_array = array();
5054
    while ($row = Database::fetch_array($result, 'ASSOC')) {
5055
        $settings_options_array[] = $row;
5056
    }
5057
    return $settings_options_array;
5058
}
5059
5060
/**
5061
 * @param array $params
5062
 */
5063
function api_set_setting_option($params) {
5064
    $table = Database::get_main_table(TABLE_MAIN_SETTINGS_OPTIONS);
5065 View Code Duplication
    if (empty($params['id'])) {
5066
        Database::insert($table, $params);
5067
    } else {
5068
        Database::update($table, $params, array('id = ? '=> $params['id']));
5069
    }
5070
}
5071
5072
/**
5073
 * @param array $params
5074
 */
5075
function api_set_setting_simple($params) {
5076
    $table = Database::get_main_table(TABLE_MAIN_SETTINGS_CURRENT);
5077
    $url_id = api_get_current_access_url_id();
5078
5079 View Code Duplication
    if (empty($params['id'])) {
5080
        $params['access_url'] = $url_id;
5081
        Database::insert($table, $params);
5082
    } else {
5083
        Database::update($table, $params, array('id = ? '=> array($params['id'])));
5084
    }
5085
}
5086
5087
/**
5088
 * @param int $id
5089
 */
5090
function api_delete_setting_option($id) {
5091
    $table = Database::get_main_table(TABLE_MAIN_SETTINGS_OPTIONS);
5092
    if (!empty($id)) {
5093
        Database::delete($table, array('id = ? '=> $id));
5094
    }
5095
}
5096
5097
/**
5098
 * Sets a platform configuration setting to a given value
5099
 * @param string    The variable we want to update
5100
 * @param string    The value we want to record
5101
 * @param string    The sub-variable if any (in most cases, this will remain null)
5102
 * @param string    The category if any (in most cases, this will remain null)
5103
 * @param int       The access_url for which this parameter is valid
5104
 * @param string $cat
5105
 */
5106
function api_set_setting($var, $value, $subvar = null, $cat = null, $access_url = 1)
5107
{
5108
    if (empty($var)) {
5109
        return false;
5110
    }
5111
    $t_settings = Database::get_main_table(TABLE_MAIN_SETTINGS_CURRENT);
5112
    $var = Database::escape_string($var);
5113
    $value = Database::escape_string($value);
5114
    $access_url = (int)$access_url;
5115
    if (empty($access_url)) { $access_url = 1; }
5116
    $select = "SELECT id FROM $t_settings WHERE variable = '$var' ";
5117
    if (!empty($subvar)) {
5118
        $subvar = Database::escape_string($subvar);
5119
        $select .= " AND subkey = '$subvar'";
5120
    }
5121
    if (!empty($cat)) {
5122
        $cat = Database::escape_string($cat);
5123
        $select .= " AND category = '$cat'";
5124
    }
5125
    if ($access_url > 1) {
5126
        $select .= " AND access_url = $access_url";
5127
    } else {
5128
        $select .= " AND access_url = 1 ";
5129
    }
5130
5131
    $res = Database::query($select);
5132
    if (Database::num_rows($res) > 0) {
5133
        // Found item for this access_url.
5134
        $row = Database::fetch_array($res);
5135
        $sql = "UPDATE $t_settings SET selected_value = '$value'
5136
                WHERE id = ".$row['id'] ;
5137
        Database::query($sql);
5138
    } else {
5139
        // Item not found for this access_url, we have to check if it exist with access_url = 1
5140
        $select = "SELECT * FROM $t_settings
5141
                   WHERE variable = '$var' AND access_url = 1 ";
5142
        // Just in case
5143
        if ($access_url == 1) {
5144
            if (!empty($subvar)) {
5145
                $select .= " AND subkey = '$subvar'";
5146
            }
5147
            if (!empty($cat)) {
5148
                $select .= " AND category = '$cat'";
5149
            }
5150
            $res = Database::query($select);
5151
5152
            if (Database::num_rows($res) > 0) {
5153
                // We have a setting for access_url 1, but none for the current one, so create one.
5154
                $row = Database::fetch_array($res);
5155
                $insert = "INSERT INTO $t_settings (variable, subkey, type,category, selected_value, title, comment, scope, subkeytext, access_url)
5156
                        VALUES
5157
                        ('".$row['variable']."',".(!empty($row['subkey']) ? "'".$row['subkey']."'" : "NULL")."," .
5158
                        "'".$row['type']."','".$row['category']."'," .
5159
                        "'$value','".$row['title']."'," .
5160
                        "".(!empty($row['comment']) ? "'".$row['comment']."'" : "NULL").",".(!empty($row['scope']) ? "'".$row['scope']."'" : "NULL")."," .
5161
                        "".(!empty($row['subkeytext'])?"'".$row['subkeytext']."'":"NULL").",$access_url)";
5162
                Database::query($insert);
5163 View Code Duplication
            } else { // Such a setting does not exist.
5164
                error_log(__FILE__.':'.__LINE__.': Attempting to update setting '.$var.' ('.$subvar.') which does not exist at all', 0);
5165
            }
5166
        } else {
5167
            // Other access url.
5168
            if (!empty($subvar)) {
5169
                $select .= " AND subkey = '$subvar'";
5170
            }
5171
            if (!empty($cat)) {
5172
                $select .= " AND category = '$cat'";
5173
            }
5174
            $res = Database::query($select);
5175
5176
            if (Database::num_rows($res) > 0) { // We have a setting for access_url 1, but none for the current one, so create one.
5177
                $row = Database::fetch_array($res);
5178
                if ($row['access_url_changeable'] == 1) {
5179
                    $insert = "INSERT INTO $t_settings (variable,subkey, type,category, selected_value,title, comment,scope, subkeytext,access_url, access_url_changeable) VALUES
5180
                            ('".$row['variable']."',".
5181
                            (!empty($row['subkey']) ? "'".$row['subkey']."'" : "NULL")."," .
5182
                            "'".$row['type']."','".$row['category']."'," .
5183
                            "'$value','".$row['title']."'," .
5184
                            "".(!empty($row['comment']) ? "'".$row['comment']."'" : "NULL").",".
5185
                            (!empty($row['scope']) ? "'".$row['scope']."'" : "NULL")."," .
5186
                            "".(!empty($row['subkeytext']) ? "'".$row['subkeytext']."'" : "NULL").",$access_url,".$row['access_url_changeable'].")";
5187
                    Database::query($insert);
5188
                }
5189 View Code Duplication
            } else { // Such a setting does not exist.
5190
                error_log(__FILE__.':'.__LINE__.': Attempting to update setting '.$var.' ('.$subvar.') which does not exist at all. The access_url is: '.$access_url.' ',0);
5191
            }
5192
        }
5193
    }
5194
}
5195
5196
/**
5197
 * Sets a whole category of settings to one specific value
5198
 * @param string    Category
5199
 * @param string    Value
5200
 * @param int       Access URL. Optional. Defaults to 1
5201
 * @param array     Optional array of filters on field type
5202
 * @param string $category
5203
 * @param string $value
5204
 */
5205
function api_set_settings_category($category, $value = null, $access_url = 1, $fieldtype = array())
5206
{
5207
    if (empty($category)) {
5208
        return false;
5209
    }
5210
    $category = Database::escape_string($category);
5211
    $t_s = Database::get_main_table(TABLE_MAIN_SETTINGS_CURRENT);
5212
    $access_url = (int) $access_url;
5213
    if (empty($access_url)) { $access_url = 1; }
5214
    if (isset($value)) {
5215
        $value = Database::escape_string($value);
5216
        $sql = "UPDATE $t_s SET selected_value = '$value'
5217
                WHERE category = '$category' AND access_url = $access_url";
5218 View Code Duplication
        if (is_array($fieldtype) && count($fieldtype)>0) {
5219
            $sql .= " AND ( ";
5220
            $i = 0;
5221
            foreach ($fieldtype as $type){
5222
                if ($i > 0) {
5223
                    $sql .= ' OR ';
5224
                }
5225
                $type = Database::escape_string($type);
5226
                $sql .= " type='".$type."' ";
5227
                $i++;
5228
            }
5229
            $sql .= ")";
5230
        }
5231
        $res = Database::query($sql);
5232
        return $res !== false;
5233
    } else {
5234
        $sql = "UPDATE $t_s SET selected_value = NULL
5235
                WHERE category = '$category' AND access_url = $access_url";
5236 View Code Duplication
        if (is_array($fieldtype) && count($fieldtype)>0) {
5237
            $sql .= " AND ( ";
5238
            $i = 0;
5239
            foreach ($fieldtype as $type){
5240
                if ($i > 0) {
5241
                    $sql .= ' OR ';
5242
                }
5243
                $type = Database::escape_string($type);
5244
                $sql .= " type='".$type."' ";
5245
                $i++;
5246
            }
5247
            $sql .= ")";
5248
        }
5249
        $res = Database::query($sql);
5250
        return $res !== false;
5251
    }
5252
}
5253
5254
/**
5255
 * Gets all available access urls in an array (as in the database)
5256
 * @return array    An array of database records
5257
 */
5258
function api_get_access_urls($from = 0, $to = 1000000, $order = 'url', $direction = 'ASC')
5259
{
5260
    $table = Database::get_main_table(TABLE_MAIN_ACCESS_URL);
5261
    $from = (int) $from;
5262
    $to = (int) $to;
5263
    $order = Database::escape_string($order, null, false);
5264
    $direction = Database::escape_string($direction, null, false);
5265
    $sql = "SELECT id, url, description, active, created_by, tms
5266
            FROM $table
5267
            ORDER BY $order $direction
5268
            LIMIT $to OFFSET $from";
5269
    $res = Database::query($sql);
5270
    return Database::store_result($res);
5271
}
5272
5273
/**
5274
 * Gets the access url info in an array
5275
 * @param int $id Id of the access url
5276
 * @param bool $returnDefault Set to false if you want the real URL if URL 1 is still 'http://localhost/'
5277
 * @return array All the info (url, description, active, created_by, tms)
5278
 * from the access_url table
5279
 * @author Julio Montoya
5280
 */
5281
function api_get_access_url($id, $returnDefault = true)
5282
{
5283
    $id = intval($id);
5284
    // Calling the Database:: library dont work this is handmade.
5285
    $table_access_url = Database::get_main_table(TABLE_MAIN_ACCESS_URL);
5286
    $sql = "SELECT url, description, active, created_by, tms
5287
            FROM $table_access_url WHERE id = '$id' ";
5288
    $res = Database::query($sql);
5289
    $result = @Database::fetch_array($res);
5290
    // If the result url is 'http://localhost/' (the default) and the root_web
5291
    // (=current url) is different, and the $id is = 1 (which might mean
5292
    // api_get_current_access_url_id() returned 1 by default), then return the
5293
    // root_web setting instead of the current URL
5294
    // This is provided as an option to avoid breaking the storage of URL-specific
5295
    // homepages in home/localhost/
5296
    if ($id === 1 && $returnDefault === false) {
5297
        $currentUrl = api_get_current_access_url_id();
5298
        // only do this if we are on the main URL (=1), otherwise we could get
5299
        // information on another URL instead of the one asked as parameter
5300
        if ($currentUrl === 1) {
5301
            $rootWeb = api_get_path(WEB_PATH);
5302
            $default = 'http://localhost/';
5303
            if ($result['url'] === $default && $rootWeb != $default) {
5304
                $result['url'] = $rootWeb;
5305
            }
5306
        }
5307
    }
5308
5309
    return $result;
5310
}
5311
5312
/**
5313
 * Adds an access URL into the database
5314
 * @param string    URL
5315
 * @param string    Description
5316
 * @param int       Active (1= active, 0=disabled)
5317
 * @return int      The new database id, or the existing database id if this url already exists
5318
 */
5319
function api_add_access_url($u, $d = '', $a = 1) {
5320
    $t_au = Database::get_main_table(TABLE_MAIN_ACCESS_URL);
5321
    $u = Database::escape_string($u);
5322
    $d = Database::escape_string($d);
5323
    $a = (int) $a;
5324
    $sql = "SELECT id FROM $t_au WHERE url LIKE '$u'";
5325
    $res = Database::query($sql);
5326
    if ($res === false) {
5327
        // Problem querying the database - return false.
5328
        return false;
5329
    }
5330
    if (Database::num_rows($res) > 0) {
5331
        return Database::result($res, 0, 'id');
5332
    }
5333
    $ui = api_get_user_id();
5334
5335
    $sql = "INSERT INTO $t_au (url,description,active,created_by,tms) VALUES ('$u','$d',$a,$ui,'')";
5336
    $res = Database::query($sql);
5337
    return ($res === false) ? false : Database::insert_id();
5338
}
5339
5340
/**
5341
 * Gets all the current settings for a specific access url
5342
 * @param string    The category, if any, that we want to get
5343
 * @param string    Whether we want a simple list (display a category) or
5344
 * a grouped list (group by variable as in settings.php default). Values: 'list' or 'group'
5345
 * @param int       Access URL's ID. Optional. Uses 1 by default, which is the unique URL
5346
 * @return array    Array of database results for the current settings of the current access URL
5347
 */
5348
function & api_get_settings($cat = null, $ordering = 'list', $access_url = 1, $url_changeable = 0)
5349
{
5350
    $table = Database::get_main_table(TABLE_MAIN_SETTINGS_CURRENT);
5351
    $access_url = (int) $access_url;
5352
    $where_condition = '';
5353
    if ($url_changeable == 1) {
5354
        $where_condition = " AND access_url_changeable= '1' ";
5355
    }
5356
    if (empty($access_url) || $access_url == -1) {
5357
        $access_url = 1;
5358
    }
5359
    $sql = "SELECT * FROM $table
5360
            WHERE access_url = $access_url  $where_condition ";
5361
5362
    if (!empty($cat)) {
5363
        $cat = Database::escape_string($cat);
5364
        $sql .= " AND category='$cat' ";
5365
    }
5366
    if ($ordering == 'group') {
5367
        $sql .= " ORDER BY id ASC";
5368
    } else {
5369
        $sql .= " ORDER BY 1,2 ASC";
5370
    }
5371
    $result = Database::store_result(Database::query($sql));
0 ignored issues
show
Bug introduced by
It seems like \Database::query($sql) can be null; however, store_result() does not accept null, maybe add an additional type check?

Unless you are absolutely sure that the expression can never be null because of other conditions, we strongly recommend to add an additional type check to your code:

/** @return stdClass|null */
function mayReturnNull() { }

function doesNotAcceptNull(stdClass $x) { }

// With potential error.
function withoutCheck() {
    $x = mayReturnNull();
    doesNotAcceptNull($x); // Potential error here.
}

// Safe - Alternative 1
function withCheck1() {
    $x = mayReturnNull();
    if ( ! $x instanceof stdClass) {
        throw new \LogicException('$x must be defined.');
    }
    doesNotAcceptNull($x);
}

// Safe - Alternative 2
function withCheck2() {
    $x = mayReturnNull();
    if ($x instanceof stdClass) {
        doesNotAcceptNull($x);
    }
}
Loading history...
5372
    return $result;
5373
}
5374
5375
/**
5376
 * Gets the distinct settings categories
5377
 * @param array     Array of strings giving the categories we want to excluded
5378
 * @param int       Access URL. Optional. Defaults to 1
5379
 * @return array    A list of categories
5380
 */
5381
function & api_get_settings_categories($exceptions = array(), $access_url = 1) {
5382
    $access_url = (int) $access_url;
5383
    $t_cs = Database::get_main_table(TABLE_MAIN_SETTINGS_CURRENT);
5384
    $list = "'".implode("','",$exceptions)."'";
5385
    $sql = "SELECT DISTINCT category FROM $t_cs WHERE category is NOT NULL ";
5386
    if ($list != "'',''" && $list != "''" && !empty($list)) {
5387
        $sql .= " AND category NOT IN ($list) ";
5388
    }
5389
    $result = Database::store_result(Database::query($sql));
0 ignored issues
show
Bug introduced by
It seems like \Database::query($sql) can be null; however, store_result() does not accept null, maybe add an additional type check?

Unless you are absolutely sure that the expression can never be null because of other conditions, we strongly recommend to add an additional type check to your code:

/** @return stdClass|null */
function mayReturnNull() { }

function doesNotAcceptNull(stdClass $x) { }

// With potential error.
function withoutCheck() {
    $x = mayReturnNull();
    doesNotAcceptNull($x); // Potential error here.
}

// Safe - Alternative 1
function withCheck1() {
    $x = mayReturnNull();
    if ( ! $x instanceof stdClass) {
        throw new \LogicException('$x must be defined.');
    }
    doesNotAcceptNull($x);
}

// Safe - Alternative 2
function withCheck2() {
    $x = mayReturnNull();
    if ($x instanceof stdClass) {
        doesNotAcceptNull($x);
    }
}
Loading history...
5390
    return $result;
5391
}
5392
5393
/**
5394
 * Deletes a setting
5395
 * @param string    Variable
5396
 * @param string    Subkey
5397
 * @param int       Access URL
5398
 * @return boolean  False on failure, true on success
5399
 */
5400
5401
function api_delete_setting($v, $s = null, $a = 1) {
5402
    if (empty($v)) { return false; }
5403
    $t_cs = Database::get_main_table(TABLE_MAIN_SETTINGS_CURRENT);
5404
    $v = Database::escape_string($v);
5405
    $a = (int) $a;
5406
    if (empty($a)) { $a = 1; }
5407
    if (!empty($s)) {
5408
        $s = Database::escape_string($s);
5409
        $sql = "DELETE FROM $t_cs WHERE variable = '$v' AND subkey = '$s' AND access_url = $a";
5410
        $r = Database::query($sql);
5411
        return $r;
5412
    }
5413
    $sql = "DELETE FROM $t_cs WHERE variable = '$v' AND access_url = $a";
5414
    $r = Database::query($sql);
5415
    return $r;
5416
}
5417
5418
/**
5419
 * Deletes all the settings from one category
5420
 * @param string    Subkey
5421
 * @param int       Access URL
5422
 * @return boolean  False on failure, true on success
5423
 */
5424
function api_delete_category_settings_by_subkey($subkey, $access_url_id = 1) {
5425
    if (empty($subkey)) { return false; }
5426
    $t_cs = Database::get_main_table(TABLE_MAIN_SETTINGS_CURRENT);
5427
    $subkey = Database::escape_string($subkey);
5428
    $access_url_id = intval($access_url_id);
5429
    $sql = "DELETE FROM $t_cs WHERE subkey = '$subkey' AND access_url = $access_url_id";
5430
    $r = Database::query($sql);
5431
    return $r;
5432
}
5433
5434
/**
5435
 * Sets a platform configuration setting to a given value
5436
 * @param string    The value we want to record
5437
 * @param string    The variable name we want to insert
5438
 * @param string    The subkey for the variable we want to insert
5439
 * @param string    The type for the variable we want to insert
5440
 * @param string    The category for the variable we want to insert
5441
 * @param string    The title
5442
 * @param string    The comment
5443
 * @param string    The scope
5444
 * @param string    The subkey text
5445
 * @param int       The access_url for which this parameter is valid
5446
 * @param int       The changeability of this setting for non-master urls
5447
 * @param string $val
5448
 * @param string $var
5449
 * @param string $sk
5450
 * @param string $c
5451
 * @return boolean  true on success, false on failure
5452
 */
5453
function api_add_setting($val, $var, $sk = null, $type = 'textfield', $c = null, $title = '', $com = '', $sc = null, $skt = null, $a = 1, $v = 0) {
5454
    if (empty($var) || !isset($val)) { return false; }
5455
    $t_settings = Database::get_main_table(TABLE_MAIN_SETTINGS_CURRENT);
5456
    $var = Database::escape_string($var);
5457
    $val = Database::escape_string($val);
5458
    $a = (int) $a;
5459
    if (empty($a)) { $a = 1; }
5460
    // Check if this variable doesn't exist already
5461
    $select = "SELECT id FROM $t_settings WHERE variable = '$var' ";
5462
    if (!empty($sk)) {
5463
        $sk = Database::escape_string($sk);
5464
        $select .= " AND subkey = '$sk'";
5465
    }
5466
    if ($a > 1) {
5467
        $select .= " AND access_url = $a";
5468
    } else {
5469
        $select .= " AND access_url = 1 ";
5470
    }
5471
    $res = Database::query($select);
5472
    if (Database::num_rows($res) > 0) { // Found item for this access_url.
5473
        $row = Database::fetch_array($res);
5474
        Database::update(
5475
            $t_settings,
5476
            array('selected_value' => $val),
5477
            array('id = ?' => array($row['id']))
5478
        );
5479
        return $row['id'];
5480
    }
5481
5482
    // Item not found for this access_url, we have to check if the whole thing is missing
5483
    // (in which case we ignore the insert) or if there *is* a record but just for access_url = 1
5484
    $insert = "INSERT INTO $t_settings " .
5485
                "(variable,selected_value," .
5486
                "type,category," .
5487
                "subkey,title," .
5488
                "comment,scope," .
5489
                "subkeytext,access_url,access_url_changeable)" .
5490
                " VALUES ('$var','$val',";
5491 View Code Duplication
    if (isset($type)) {
5492
        $type = Database::escape_string($type);
5493
        $insert .= "'$type',";
5494
    } else {
5495
        $insert .= "NULL,";
5496
    }
5497 View Code Duplication
    if (isset($c)) { // Category
5498
        $c = Database::escape_string($c);
5499
        $insert .= "'$c',";
5500
    } else {
5501
        $insert .= "NULL,";
5502
    }
5503 View Code Duplication
    if (isset($sk)) { // Subkey
5504
        $sk = Database::escape_string($sk);
5505
        $insert .= "'$sk',";
5506
    } else {
5507
        $insert .= "NULL,";
5508
    }
5509 View Code Duplication
    if (isset($title)) { // Title
5510
        $title = Database::escape_string($title);
5511
        $insert .= "'$title',";
5512
    } else {
5513
        $insert .= "NULL,";
5514
    }
5515 View Code Duplication
    if (isset($com)) { // Comment
5516
        $com = Database::escape_string($com);
5517
        $insert .= "'$com',";
5518
    } else {
5519
        $insert .= "NULL,";
5520
    }
5521 View Code Duplication
    if (isset($sc)) { // Scope
5522
        $sc = Database::escape_string($sc);
5523
        $insert .= "'$sc',";
5524
    } else {
5525
        $insert .= "NULL,";
5526
    }
5527 View Code Duplication
    if (isset($skt)) { // Subkey text
5528
        $skt = Database::escape_string($skt);
5529
        $insert .= "'$skt',";
5530
    } else {
5531
        $insert .= "NULL,";
5532
    }
5533
    $insert .= "$a,$v)";
5534
    $res = Database::query($insert);
5535
    return $res;
5536
}
5537
5538
/**
5539
 * Checks wether a user can or can't view the contents of a course.
5540
 *
5541
 * @param   int $userid     User id or NULL to get it from $_SESSION
5542
 * @param   int $cid        Course id to check whether the user is allowed.
5543
 * @return  bool
5544
 */
5545
function api_is_course_visible_for_user($userid = null, $cid = null) {
5546
    if ($userid == null) {
0 ignored issues
show
Bug Best Practice introduced by
It seems like you are loosely comparing $userid of type integer|null against null; this is ambiguous if the integer can be zero. Consider using a strict comparison === instead.
Loading history...
5547
        $userid = api_get_user_id();
5548
    }
5549
    if (empty($userid) || strval(intval($userid)) != $userid) {
5550
        if (api_is_anonymous()) {
5551
            $userid = api_get_anonymous_id();
5552
        } else {
5553
            return false;
5554
        }
5555
    }
5556
    $cid = Database::escape_string($cid);
5557
5558
    $courseInfo = api_get_course_info($cid);
5559
    $courseId = $courseInfo['real_id'];
5560
5561
    global $is_platformAdmin;
5562
5563
    $course_table = Database::get_main_table(TABLE_MAIN_COURSE);
5564
    $course_cat_table = Database::get_main_table(TABLE_MAIN_CATEGORY);
5565
5566
    $sql = "SELECT
5567
                $course_table.category_code,
5568
                $course_table.visibility,
5569
                $course_table.code,
5570
                $course_cat_table.code
5571
            FROM $course_table
5572
            LEFT JOIN $course_cat_table
5573
                ON $course_table.category_code = $course_cat_table.code
5574
            WHERE
5575
                $course_table.code = '$cid'
5576
            LIMIT 1";
5577
5578
    $result = Database::query($sql);
5579
5580 View Code Duplication
    if (Database::num_rows($result) > 0) {
5581
        $visibility = Database::fetch_array($result);
5582
        $visibility = $visibility['visibility'];
5583
    } else {
5584
        $visibility = 0;
5585
    }
5586
    // Shortcut permissions in case the visibility is "open to the world".
5587
    if ($visibility === COURSE_VISIBILITY_OPEN_WORLD) {
5588
        return true;
5589
    }
5590
5591
    $tbl_course_user = Database :: get_main_table(TABLE_MAIN_COURSE_USER);
5592
5593
    $sql = "SELECT
5594
                is_tutor, status
5595
            FROM $tbl_course_user
5596
            WHERE
5597
                user_id  = '$userid' AND
5598
                relation_type <> '".COURSE_RELATION_TYPE_RRHH."' AND
5599
                c_id = $courseId
5600
            LIMIT 1";
5601
5602
    $result = Database::query($sql);
5603
5604
    if (Database::num_rows($result) > 0) {
5605
        // This user has got a recorded state for this course.
5606
        $cuData = Database::fetch_array($result);
5607
        $is_courseMember = true;
5608
        $is_courseTutor = ($cuData['is_tutor'] == 1);
5609
        $is_courseAdmin = ($cuData['status'] == 1);
5610
    }
5611
5612
    if (!$is_courseAdmin) {
5613
        // This user has no status related to this course.
5614
        // Is it the session coach or the session admin?
5615
        $tbl_session = Database::get_main_table(TABLE_MAIN_SESSION);
5616
        $tbl_session_course = Database::get_main_table(TABLE_MAIN_SESSION_COURSE);
5617
        $tbl_session_course_user = Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER);
5618
5619
        $sql = "SELECT
5620
                    session.id_coach, session_admin_id, session.id
5621
                FROM
5622
                    $tbl_session as session
5623
                INNER JOIN $tbl_session_course
5624
                    ON session_rel_course.session_id = session.id
5625
                    AND session_rel_course.c_id = '$courseId'
5626
                LIMIT 1";
5627
5628
        $result = Database::query($sql);
5629
        $row = Database::store_result($result);
5630
5631
        if ($row[0]['id_coach'] == $userid) {
5632
            $is_courseMember = true;
5633
            $is_courseTutor = true;
5634
            $is_courseAdmin = false;
5635
            $is_courseCoach = true;
5636
            $is_sessionAdmin = false;
5637
        }
5638
        elseif ($row[0]['session_admin_id'] == $userid) {
5639
            $is_courseMember = false;
5640
            $is_courseTutor = false;
5641
            $is_courseAdmin = false;
5642
            $is_courseCoach = false;
5643
            $is_sessionAdmin = true;
5644
        } else {
5645
            // Check if the current user is the course coach.
5646
            $sql = "SELECT 1
5647
                    FROM $tbl_session_course
5648
                    WHERE session_rel_course.c_id = '$courseId'
5649
                    AND session_rel_course.id_coach = '$userid'
5650
                    LIMIT 1";
5651
5652
            $result = Database::query($sql);
5653
5654
            //if ($row = Database::fetch_array($result)) {
5655
            if (Database::num_rows($result) > 0 ) {
5656
                $is_courseMember = true;
5657
                $is_courseTutor = true;
5658
                $is_courseCoach = true;
5659
                $is_sessionAdmin = false;
5660
5661
                $tbl_user = Database :: get_main_table(TABLE_MAIN_USER);
5662
5663
                $sql = "SELECT status FROM $tbl_user
5664
                        WHERE user_id = $userid
5665
                        LIMIT 1";
5666
5667
                $result = Database::query($sql);
5668
5669
                if (Database::result($result, 0, 0) == 1) {
5670
                    $is_courseAdmin = true;
5671
                } else {
5672
                    $is_courseAdmin = false;
5673
                }
5674
            } else {
5675
                // Check if the user is a student is this session.
5676
                $sql = "SELECT  id
5677
                        FROM $tbl_session_course_user
5678
                        WHERE
5679
                            user_id  = '$userid' AND
5680
                            c_id = '$courseId'
5681
                        LIMIT 1";
5682
5683
                if (Database::num_rows($result) > 0) {
5684
                    // This user haa got a recorded state for this course.
5685
                    while ($row = Database::fetch_array($result)) {
5686
                        $is_courseMember = true;
5687
                        $is_courseTutor = false;
5688
                        $is_courseAdmin = false;
5689
                        $is_sessionAdmin = false;
5690
                    }
5691
                }
5692
            }
5693
        }
5694
    }
5695
5696
    switch ($visibility) {
5697
        case COURSE_VISIBILITY_OPEN_WORLD:
5698
            return true;
5699
        case COURSE_VISIBILITY_OPEN_PLATFORM:
5700
            return isset($userid);
5701
        case COURSE_VISIBILITY_REGISTERED:
5702
        case COURSE_VISIBILITY_CLOSED:
5703
            return $is_platformAdmin || $is_courseMember || $is_courseAdmin;
5704
        case COURSE_VISIBILITY_HIDDEN:
5705
            return $is_platformAdmin;
5706
    }
5707
5708
    return false;
5709
}
5710
5711
/**
5712
 * Returns whether an element (forum, message, survey ...) belongs to a session or not
5713
 * @param String the tool of the element
5714
 * @param int the element id in database
5715
 * @param int the session_id to compare with element session id
5716
 * @param string $tool
5717
 * @return boolean true if the element is in the session, false else
5718
 */
5719
function api_is_element_in_the_session($tool, $element_id, $session_id = null) {
5720
    if (is_null($session_id)) {
5721
        $session_id = intval($_SESSION['id_session']);
5722
    }
5723
5724
    // Get information to build query depending of the tool.
5725
    switch ($tool) {
5726
        case TOOL_SURVEY :
5727
            $table_tool = Database::get_course_table(TABLE_SURVEY);
5728
            $key_field = 'survey_id';
5729
            break;
5730
        case TOOL_ANNOUNCEMENT :
5731
            $table_tool = Database::get_course_table(TABLE_ANNOUNCEMENT);
5732
            $key_field = 'id';
5733
            break;
5734
        case TOOL_AGENDA :
5735
            $table_tool = Database::get_course_table(TABLE_AGENDA);
5736
            $key_field = 'id';
5737
            break;
5738
        case TOOL_GROUP :
5739
            $table_tool = Database::get_course_table(TABLE_GROUP);
5740
            $key_field = 'id';
5741
            break;
5742
        default:
5743
            return false;
5744
    }
5745
    $course_id = api_get_course_int_id();
5746
5747
    $sql = "SELECT session_id FROM $table_tool WHERE c_id = $course_id AND $key_field =  ".intval($element_id);
5748
    $rs = Database::query($sql);
5749
    if ($element_session_id = Database::result($rs, 0, 0)) {
5750
        if ($element_session_id == intval($session_id)) {
5751
            // The element belongs to the session.
5752
            return true;
5753
        }
5754
    }
5755
    return false;
5756
}
5757
5758
/**
5759
 * Replaces "forbidden" characters in a filename string.
5760
 *
5761
 * @param string $filename
5762
 *
5763
 * @return string
5764
 */
5765
function api_replace_dangerous_char($filename)
5766
{
5767
    return URLify::filter($filename, 250, '', true, true, false, false);
5768
}
5769
5770
/**
5771
 * Fixes the $_SERVER['REQUEST_URI'] that is empty in IIS6.
5772
 * @author Ivan Tcholakov, 28-JUN-2006.
5773
 */
5774
function api_request_uri() {
5775
    if (!empty($_SERVER['REQUEST_URI'])) {
5776
        return $_SERVER['REQUEST_URI'];
5777
    }
5778
    $uri = $_SERVER['SCRIPT_NAME'];
5779
    if (!empty($_SERVER['QUERY_STRING'])) {
5780
        $uri .= '?'.$_SERVER['QUERY_STRING'];
5781
    }
5782
    $_SERVER['REQUEST_URI'] = $uri;
5783
    return $uri;
5784
}
5785
5786
5787
/** Gets the current access_url id of the Chamilo Platform
5788
 * @author Julio Montoya <[email protected]>
5789
 * @return int access_url_id of the current Chamilo Installation
5790
 */
5791
function api_get_current_access_url_id() {
5792
    $access_url_table = Database :: get_main_table(TABLE_MAIN_ACCESS_URL);
5793
    $path = Database::escape_string(api_get_path(WEB_PATH));
5794
    $sql = "SELECT id FROM $access_url_table WHERE url = '".$path."'";
5795
    $result = Database::query($sql);
5796
    if (Database::num_rows($result) > 0) {
5797
        $access_url_id = Database::result($result, 0, 0);
5798
        return $access_url_id;
5799
    }
5800
    //if the url in WEB_PATH was not found, it can only mean that there is
5801
    // either a configuration problem or the first URL has not been defined yet
5802
    // (by default it is http://localhost/). Thus the more sensible thing we can
5803
    // do is return 1 (the main URL) as the user cannot hack this value anyway
5804
    return 1;
5805
}
5806
5807
/**
5808
 * Gets the registered urls from a given user id
5809
 * @author Julio Montoya <[email protected]>
5810
 * @return int user id
5811
 */
5812
function api_get_access_url_from_user($user_id) {
5813
    $user_id = intval($user_id);
5814
    $table_url_rel_user = Database :: get_main_table(TABLE_MAIN_ACCESS_URL_REL_USER);
5815
    $table_url          = Database :: get_main_table(TABLE_MAIN_ACCESS_URL);
5816
    $sql = "SELECT access_url_id
5817
            FROM $table_url_rel_user url_rel_user
5818
            INNER JOIN $table_url u
5819
            ON (url_rel_user.access_url_id = u.id)
5820
            WHERE user_id = ".intval($user_id);
5821
    $result = Database::query($sql);
5822
    $url_list = array();
5823
    while ($row = Database::fetch_array($result, 'ASSOC')) {
5824
        $url_list[] = $row['access_url_id'];
5825
    }
5826
    return $url_list;
5827
}
5828
5829
/**
5830
 * Gets the status of a user in a course
5831
 * @param int       $user_id
5832
 * @param int    $courseId
5833
 * @return int      user status
5834
 */
5835
function api_get_status_of_user_in_course($user_id, $courseId)
5836
{
5837
    $tbl_rel_course_user = Database :: get_main_table(TABLE_MAIN_COURSE_USER);
5838
    if (!empty($user_id) && !empty($courseId)) {
5839
        $user_id        = intval($user_id);
5840
        $courseId    = intval($courseId);
5841
        $sql = 'SELECT status
5842
                FROM '.$tbl_rel_course_user.'
5843
                WHERE user_id='.$user_id.' AND c_id = '.$courseId;
5844
        $result = Database::query($sql);
5845
        $row_status = Database::fetch_array($result, 'ASSOC');
5846
        return $row_status['status'];
5847
    } else {
5848
        return 0;
5849
    }
5850
}
5851
5852
/**
5853
 * Checks whether the curent user is in a course or not.
5854
 *
5855
 * @param string        The course code - optional (takes it from session if not given)
5856
 * @return boolean
5857
 * @author Yannick Warnier <[email protected]>
5858
 */
5859
function api_is_in_course($course_code = null) {
5860
    if (isset($_SESSION['_course']['sysCode'])) {
5861
        if (!empty($course_code)) {
5862
            return $course_code == $_SESSION['_course']['sysCode'];
5863
        }
5864
        return true;
5865
    }
5866
    return false;
5867
}
5868
5869
/**
5870
 * Checks whether the curent user is in a group or not.
5871
 *
5872
 * @param string        The group id - optional (takes it from session if not given)
5873
 * @param string        The course code - optional (no additional check by course if course code is not given)
5874
 * @return boolean
5875
 * @author Ivan Tcholakov
5876
 */
5877
function api_is_in_group($groupIdParam = null, $courseCodeParam = null)
5878
{
5879
    if (!empty($courseCodeParam)) {
5880
        $courseCode = api_get_course_id();
5881
        if (!empty($courseCode)) {
5882
            if ($courseCodeParam != $courseCode) {
5883
                return false;
5884
            }
5885
        } else {
5886
            return false;
5887
        }
5888
    }
5889
5890
    $groupId = api_get_group_id();
5891
5892
    if (isset($groupId) && $groupId != '') {
5893
        if (!empty($groupIdParam)) {
5894
            return $groupIdParam == $groupId;
5895
        } else {
5896
            return true;
5897
        }
5898
    }
5899
5900
    return false;
5901
}
5902
5903
5904
/**
5905
 * Checks whether a secret key is valid
5906
 * @param string $original_key_secret  - secret key from (webservice) client
5907
 * @param string $security_key - security key from Chamilo
5908
 * @return boolean - true if secret key is valid, false otherwise
5909
 */
5910
function api_is_valid_secret_key($original_key_secret, $security_key) {
5911
    return $original_key_secret == sha1($security_key);
5912
}
5913
5914
/**
5915
 * Checks whether a user is into course
5916
 * @param int $course_id - the course id
5917
 * @param int $user_id - the user id
5918
 */
5919
function api_is_user_of_course($course_id, $user_id) {
5920
    $tbl_course_rel_user = Database::get_main_table(TABLE_MAIN_COURSE_USER);
5921
    $sql = 'SELECT user_id FROM '.$tbl_course_rel_user.'
5922
            WHERE
5923
                c_id ="'.intval($course_id).'" AND
5924
                user_id = "'.intval($user_id).'" AND
5925
                relation_type <> '.COURSE_RELATION_TYPE_RRHH.' ';
5926
    $result = Database::query($sql);
5927
    return Database::num_rows($result) == 1;
5928
}
5929
5930
/**
5931
 * Checks whether the server's operating system is Windows (TM).
5932
 * @return boolean - true if the operating system is Windows, false otherwise
5933
 */
5934
function api_is_windows_os() {
5935
    if (function_exists('php_uname')) {
5936
        // php_uname() exists as of PHP 4.0.2, according to the documentation.
5937
        // We expect that this function will always work for Chamilo 1.8.x.
5938
        $os = php_uname();
5939
    }
5940
    // The following methods are not needed, but let them stay, just in case.
5941
    elseif (isset($_ENV['OS'])) {
5942
        // Sometimes $_ENV['OS'] may not be present (bugs?)
5943
        $os = $_ENV['OS'];
5944
    }
5945
    elseif (defined('PHP_OS')) {
5946
        // PHP_OS means on which OS PHP was compiled, this is why
5947
        // using PHP_OS is the last choice for detection.
5948
        $os = PHP_OS;
5949
    } else {
5950
        return false;
5951
    }
5952
    return strtolower(substr((string)$os, 0, 3 )) == 'win';
5953
}
5954
5955
/**
5956
 * This function informs whether the sent request is XMLHttpRequest
5957
 */
5958
function api_is_xml_http_request() {
5959
    return isset($_SERVER['HTTP_X_REQUESTED_WITH']) && strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest';
5960
}
5961
5962
/**
5963
 * This wrapper function has been implemented for avoiding some known problems about the function getimagesize().
5964
 * @link http://php.net/manual/en/function.getimagesize.php
5965
 * @link http://www.dokeos.com/forum/viewtopic.php?t=12345
5966
 * @link http://www.dokeos.com/forum/viewtopic.php?t=16355
5967
 * @return integer
5968
 */
5969
function api_getimagesize($path) {
5970
    $image = new Image($path);
5971
    return $image->get_image_size();
5972
}
5973
5974
/**
5975
 * This function resizes an image, with preserving its proportions (or aspect ratio).
5976
 * @author Ivan Tcholakov, MAY-2009.
5977
 * @param int $image            System path or URL of the image
5978
 * @param int $target_width     Targeted width
5979
 * @param int $target_height    Targeted height
5980
 * @return array                Calculated new width and height
5981
 */
5982
function api_resize_image($image, $target_width, $target_height) {
5983
    $image_properties = api_getimagesize($image);
5984
    return api_calculate_image_size($image_properties['width'], $image_properties['height'], $target_width, $target_height);
5985
}
5986
5987
/**
5988
 * This function calculates new image size, with preserving image's proportions (or aspect ratio).
5989
 * @author Ivan Tcholakov, MAY-2009.
5990
 * @author The initial idea has been taken from code by Patrick Cool, MAY-2004.
5991
 * @param int $image_width      Initial width
5992
 * @param int $image_height     Initial height
5993
 * @param int $target_width     Targeted width
5994
 * @param int $target_height    Targeted height
5995
 * @return array                Calculated new width and height
5996
 */
5997
function api_calculate_image_size($image_width, $image_height, $target_width, $target_height) {
5998
    // Only maths is here.
5999
    $result = array('width' => $image_width, 'height' => $image_height);
6000
    if ($image_width <= 0 || $image_height <= 0) {
6001
        return $result;
6002
    }
6003
    $resize_factor_width = $target_width / $image_width;
6004
    $resize_factor_height = $target_height / $image_height;
6005
    $delta_width = $target_width - $image_width * $resize_factor_height;
6006
    $delta_height = $target_height - $image_height * $resize_factor_width;
6007
    if ($delta_width > $delta_height) {
6008
        $result['width'] = ceil($image_width * $resize_factor_height);
6009
        $result['height'] = ceil($image_height * $resize_factor_height);
6010
    }
6011
    elseif ($delta_width < $delta_height) {
6012
        $result['width'] = ceil($image_width * $resize_factor_width);
6013
        $result['height'] = ceil($image_height * $resize_factor_width);
6014
    }
6015
    else {
6016
        $result['width'] = ceil($target_width);
6017
        $result['height'] = ceil($target_height);
6018
    }
6019
    return $result;
6020
}
6021
6022
/**
6023
 * Returns a list of Chamilo's tools or
6024
 * checks whether a given identificator is a valid Chamilo's tool.
6025
 * @author Isaac flores paz
6026
 * @param string The tool name to filter
6027
 * @return mixed Filtered string or array
6028
 */
6029
function api_get_tools_lists($my_tool = null) {
6030
    $tools_list = array(
6031
        TOOL_DOCUMENT, TOOL_THUMBNAIL, TOOL_HOTPOTATOES,
6032
        TOOL_CALENDAR_EVENT, TOOL_LINK, TOOL_COURSE_DESCRIPTION, TOOL_SEARCH,
6033
        TOOL_LEARNPATH, TOOL_ANNOUNCEMENT, TOOL_FORUM, TOOL_THREAD, TOOL_POST,
6034
        TOOL_DROPBOX, TOOL_QUIZ, TOOL_USER, TOOL_GROUP, TOOL_BLOGS, TOOL_CHAT,
6035
        TOOL_CONFERENCE, TOOL_STUDENTPUBLICATION, TOOL_TRACKING, TOOL_HOMEPAGE_LINK,
6036
        TOOL_COURSE_SETTING, TOOL_BACKUP, TOOL_COPY_COURSE_CONTENT, TOOL_RECYCLE_COURSE,
6037
        TOOL_COURSE_HOMEPAGE, TOOL_COURSE_RIGHTS_OVERVIEW, TOOL_UPLOAD, TOOL_COURSE_MAINTENANCE,
6038
        TOOL_VISIO, TOOL_VISIO_CONFERENCE, TOOL_VISIO_CLASSROOM, TOOL_SURVEY, TOOL_WIKI,
6039
        TOOL_GLOSSARY, TOOL_GRADEBOOK, TOOL_NOTEBOOK, TOOL_ATTENDANCE, TOOL_COURSE_PROGRESS
6040
    );
6041
    if (empty($my_tool)) {
6042
        return $tools_list;
6043
    }
6044
    return in_array($my_tool, $tools_list) ? $my_tool : '';
6045
}
6046
6047
/**
6048
 * Checks whether we already approved the last version term and condition
6049
 * @param int user id
6050
 * @return bool true if we pass false otherwise
6051
 */
6052
function api_check_term_condition($user_id)
6053
{
6054
    if (api_get_setting('allow_terms_conditions') == 'true') {
6055
        //check if exists terms and conditions
6056
        if (LegalManager::count() == 0) {
6057
            return true;
6058
        }
6059
6060
        $extraFieldValue = new ExtraFieldValue('user');
6061
        $data = $extraFieldValue->get_values_by_handler_and_field_variable(
6062
            $user_id,
6063
            'legal_accept'
6064
        );
6065
6066
        if (!empty($data) && isset($data['value'])) {
6067
            $rowv = $data['value'];
6068
            $user_conditions = explode(':', $rowv);
6069
            $version = $user_conditions[0];
6070
            $lang_id = $user_conditions[1];
6071
            $real_version = LegalManager::get_last_version($lang_id);
6072
6073
            return $version >= $real_version;
6074
        }
6075
        return false;
6076
    }
6077
    return false;
6078
}
6079
6080
/**
6081
 * Gets all information of a tool into course
6082
 * @param int The tool id
6083
 * @return array
6084
 */
6085
function api_get_tool_information($tool_id) {
6086
    $t_tool = Database::get_course_table(TABLE_TOOL_LIST);
6087
    $course_id = api_get_course_int_id();
6088
    $sql = "SELECT * FROM $t_tool WHERE c_id = $course_id AND id = ".intval($tool_id);
6089
    $rs  = Database::query($sql);
6090
    return Database::fetch_array($rs);
6091
}
6092
6093
/**
6094
 * Gets all information of a tool into course
6095
 * @param int The tool id
6096
 * @return array
6097
 */
6098
function api_get_tool_information_by_name($name) {
6099
    $t_tool = Database::get_course_table(TABLE_TOOL_LIST);
6100
    $course_id = api_get_course_int_id();
6101
    $sql = "SELECT * FROM $t_tool
6102
            WHERE c_id = $course_id  AND name = '".Database::escape_string($name)."' ";
6103
    $rs  = Database::query($sql);
6104
    return Database::fetch_array($rs, 'ASSOC');
6105
}
6106
6107
/**
6108
 * @deprecated use api_trunc_str() instead.
6109
 */
6110
function shorten($input, $length = 15, $encoding = null) {
6111
    $length = intval($length);
6112
    if (!$length) {
6113
        $length = 15;
6114
    }
6115
    return api_trunc_str($input, $length, '...', false, $encoding);
6116
}
6117
6118
6119
/**
6120
 * Function used to protect a "global" admin script.
6121
 * The function blocks access when the user has no global platform admin rights.
6122
 * Global admins are the admins that are registered in the main.admin table
6123
 * AND the users who have access to the "principal" portal.
6124
 * That means that there is a record in the main.access_url_rel_user table
6125
 * with his user id and the access_url_id=1
6126
 *
6127
 * @author Julio Montoya
6128
 * @param integer $user_id
6129
 */
6130
function api_is_global_platform_admin($user_id = null)
6131
{
6132
    $user_id = intval($user_id);
6133
    if (empty($user_id)) {
6134
        $user_id = api_get_user_id();
6135
    }
6136
    if (api_is_platform_admin_by_id($user_id)) {
6137
        $urlList = api_get_access_url_from_user($user_id);
6138
        // The admin is registered in the first "main" site with access_url_id = 1
6139
        if (in_array(1, $urlList)) {
6140
            return true;
6141
        } else {
6142
            return false;
6143
        }
6144
    }
6145
    return false;
6146
}
6147
6148
/**
6149
 * @param int $admin_id_to_check
6150
 * @param int  $my_user_id
6151
 * @param bool $allow_session_admin
6152
 * @return bool
6153
 */
6154
function api_global_admin_can_edit_admin($admin_id_to_check, $my_user_id = null, $allow_session_admin = false)
6155
{
6156
    if (empty($my_user_id)) {
6157
        $my_user_id = api_get_user_id();
6158
    }
6159
6160
    $iam_a_global_admin = api_is_global_platform_admin($my_user_id);
6161
    $user_is_global_admin = api_is_global_platform_admin($admin_id_to_check);
6162
6163
    if ($iam_a_global_admin) {
6164
        // Global admin can edit everything
6165
        return true;
6166
    } else {
6167
        // If i'm a simple admin
6168
        $is_platform_admin = api_is_platform_admin_by_id($my_user_id);
6169
6170
        if ($allow_session_admin) {
6171
            $is_platform_admin = api_is_platform_admin_by_id($my_user_id) || (api_get_user_status($my_user_id) == SESSIONADMIN);
6172
        }
6173
6174
        if ($is_platform_admin) {
6175
            if ($user_is_global_admin) {
6176
                return false;
6177
            } else {
6178
                return true;
6179
            }
6180
        } else {
6181
            return false;
6182
        }
6183
    }
6184
}
6185
6186
/**
6187
 * @param int $admin_id_to_check
6188
 * @param int  $my_user_id
6189
 * @param bool $allow_session_admin
6190
 * @return boolean|null
6191
 */
6192
function api_protect_super_admin($admin_id_to_check, $my_user_id = null, $allow_session_admin = false)
6193
{
6194
    if (api_global_admin_can_edit_admin($admin_id_to_check, $my_user_id, $allow_session_admin)) {
6195
        return true;
6196
    } else {
6197
        api_not_allowed();
6198
    }
6199
}
6200
6201
/**
6202
 * Function used to protect a global admin script.
6203
 * The function blocks access when the user has no global platform admin rights.
6204
 * See also the api_is_global_platform_admin() function wich defines who's a "global" admin
6205
 *
6206
 * @author Julio Montoya
6207
 */
6208
function api_protect_global_admin_script() {
6209
    if (!api_is_global_platform_admin()) {
6210
        api_not_allowed();
6211
        return false;
6212
    }
6213
    return true;
6214
}
6215
6216
/**
6217
 * Get active template
6218
 * @param string    theme type (optional: default)
6219
 * @param string    path absolute(abs) or relative(rel) (optional:rel)
6220
 * @return string   actived template path
6221
 */
6222
function api_get_template($path_type = 'rel') {
6223
    $path_types = array('rel', 'abs');
6224
    $template_path = '';
6225
    if (in_array($path_type, $path_types)) {
6226
        if ($path_type == 'rel') {
6227
            $template_path = api_get_path(SYS_TEMPLATE_PATH);
6228
        } else {
6229
            $template_path = api_get_path(WEB_TEMPLATE_PATH);
6230
        }
6231
    }
6232
    $actived_theme = 'default';
6233
    if (api_get_setting('active_template')) {
6234
        $actived_theme = api_get_setting('active_template');
6235
    }
6236
    $actived_theme_path = $template_path.$actived_theme.DIRECTORY_SEPARATOR;
6237
    return $actived_theme_path;
6238
}
6239
6240
/**
6241
 * Check browser support for type files
6242
 * This function check if the users browser support a file format or
6243
 * return the current browser and major ver when $format=check_browser
6244
 * @param string $format
6245
 *
6246
 * @return bool, or return text array if $format=check_browser
6247
 * @author Juan Carlos Raña Trabado
0 ignored issues
show
Documentation introduced by
The doc-type bool, could not be parsed: Expected "|" or "end of type", but got "," at position 4. (view supported doc-types)

This check marks PHPDoc comments that could not be parsed by our parser. To see which comment annotations we can parse, please refer to our documentation on supported doc-types.

Loading history...
6248
 */
6249
6250
function api_browser_support($format = "")
6251
{
6252
    $browser = new Browser();
6253
    $current_browser = $browser->getBrowser();
6254
    $a_versiontemp = explode('.', $browser->getVersion());
6255
    $current_majorver = $a_versiontemp[0];
6256
6257
    // Native svg support
6258
    if ($format == 'svg') {
6259
        if (($current_browser == 'Internet Explorer' && $current_majorver >= 9) ||
6260
            ($current_browser == 'Firefox' && $current_majorver > 1) ||
6261
            ($current_browser == 'Safari' && $current_majorver >= 4) ||
6262
            ($current_browser == 'Chrome' && $current_majorver >= 1) ||
6263
            ($current_browser == 'Opera' && $current_majorver >= 9)
6264
        ) {
6265
            return true;
6266
        } else {
6267
            return false;
6268
        }
6269
    } elseif ($format == 'pdf') {
6270
        //native pdf support
6271
        if ($current_browser == 'Chrome' && $current_majorver >= 6) {
6272
            return true;
6273
        } else {
6274
            return false;
6275
        }
6276
    } elseif ($format == 'tif' || $format == 'tiff') {
6277
        //native tif support
6278
        if ($current_browser == 'Safari' && $current_majorver >= 5) {
6279
            return true;
6280
        } else {
6281
            return false;
6282
        }
6283 View Code Duplication
    } elseif ($format == 'ogg' || $format == 'ogx' || $format == 'ogv' || $format == 'oga') {
6284
        //native ogg, ogv,oga support
6285
        if (($current_browser == 'Firefox' && $current_majorver >= 3) ||
6286
            ($current_browser == 'Chrome' && $current_majorver >= 3) ||
6287
            ($current_browser == 'Opera' && $current_majorver >= 9)) {
6288
            return true;
6289
        } else {
6290
            return false;
6291
        }
6292
    } elseif ($format == 'mpg' || $format == 'mpeg') {
6293
        //native mpg support
6294
        if (($current_browser == 'Safari' && $current_majorver >= 5)) {
6295
            return true;
6296
        } else {
6297
            return false;
6298
        }
6299
    } elseif ($format == 'mp4') {
6300
        //native mp4 support (TODO: Android, iPhone)
6301
        if ($current_browser == 'Android' || $current_browser == 'iPhone') {
6302
            return true;
6303
        } else {
6304
            return false;
6305
        }
6306
    } elseif ($format == 'mov') {
6307
        //native mov support( TODO:check iPhone)
6308
        if ($current_browser == 'Safari' && $current_majorver >= 5 || $current_browser == 'iPhone') {
6309
            return true;
6310
        } else {
6311
            return false;
6312
        }
6313
    } elseif ($format == 'avi') {
6314
        //native avi support
6315
        if ($current_browser == 'Safari' && $current_majorver >= 5) {
6316
            return true;
6317
        } else {
6318
            return false;
6319
        }
6320
    } elseif ($format == 'wmv') {
6321
        //native wmv support
6322
        if ($current_browser == 'Firefox' && $current_majorver >= 4) {
6323
            return true;
6324
        } else {
6325
            return false;
6326
        }
6327 View Code Duplication
    } elseif ($format == 'webm') {
6328
        //native webm support (TODO:check IE9, Chrome9, Android)
6329
        if (($current_browser == 'Firefox' && $current_majorver >= 4) ||
6330
            ($current_browser == 'Opera' && $current_majorver >= 9) ||
6331
            ($current_browser == 'Internet Explorer' && $current_majorver >= 9) ||
6332
            ($current_browser == 'Chrome' && $current_majorver >= 9) ||
6333
            $current_browser == 'Android'
6334
        ) {
6335
            return true;
6336
        } else {
6337
            return false;
6338
        }
6339
    } elseif ($format == 'wav') {
6340
        //native wav support (only some codecs !)
6341
        if (($current_browser == 'Firefox' && $current_majorver >= 4) ||
6342
            ($current_browser == 'Safari' && $current_majorver >= 5) ||
6343
            ($current_browser == 'Opera' && $current_majorver >= 9) ||
6344
            ($current_browser == 'Internet Explorer' && $current_majorver >= 9) ||
6345
            ($current_browser == 'Chrome' && $current_majorver > 9) ||
6346
            $current_browser == 'Android' ||
6347
            $current_browser == 'iPhone'
6348
        ) {
6349
            return true;
6350
        } else {
6351
            return false;
6352
        }
6353
    } elseif ($format == 'mid' || $format == 'kar') {
6354
        //native midi support (TODO:check Android)
6355
        if ($current_browser == 'Opera' && $current_majorver >= 9 || $current_browser == 'Android') {
6356
            return true;
6357
        } else {
6358
            return false;
6359
        }
6360
    } elseif ($format == 'wma') {
6361
        //native wma support
6362
        if ($current_browser == 'Firefox' && $current_majorver >= 4) {
6363
            return true;
6364
        } else {
6365
            return false;
6366
        }
6367
    } elseif ($format == 'au') {
6368
        //native au support
6369
        if ($current_browser == 'Safari' && $current_majorver >= 5) {
6370
            return true;
6371
        } else {
6372
            return false;
6373
        }
6374 View Code Duplication
    } elseif ($format == 'mp3') {
6375
        //native mp3 support (TODO:check Android, iPhone)
6376
        if (($current_browser == 'Safari' && $current_majorver >= 5) ||
6377
            ($current_browser == 'Chrome' && $current_majorver >= 6) ||
6378
            ($current_browser == 'Internet Explorer' && $current_majorver >= 9) ||
6379
            $current_browser == 'Android' ||
6380
            $current_browser == 'iPhone' ||
6381
            $current_browser == 'Firefox'
6382
        ) {
6383
            return true;
6384
        } else {
6385
            return false;
6386
        }
6387
    } elseif ($format == "check_browser") {
6388
        $array_check_browser = array($current_browser, $current_majorver);
6389
        return $array_check_browser;
6390
    } else {
6391
        return false;
6392
    }
6393
}
6394
6395
/**
6396
 * This function checks if exist path and file browscap.ini
6397
 * In order for this to work, your browscap configuration setting in php.ini
6398
 * must point to the correct location of the browscap.ini file on your system
6399
 * http://php.net/manual/en/function.get-browser.php
6400
 *
6401
 * @return bool
6402
 *
6403
 * @author Juan Carlos Raña Trabado
6404
 */
6405
function api_check_browscap() {
6406
    $setting = ini_get('browscap');
6407
    if ($setting) {
6408
        $browser = get_browser($_SERVER['HTTP_USER_AGENT'], true);
6409
        if (strpos($setting, 'browscap.ini') && !empty($browser)) {
6410
            return true;
6411
        }
6412
    }
6413
    return false;
6414
}
6415
6416
/**
6417
 * Returns the <script> HTML tag
6418
 */
6419
function api_get_js($file) {
6420
    return '<script type="text/javascript" src="'.api_get_path(WEB_LIBRARY_PATH).'javascript/'.$file.'"></script>'."\n";
6421
}
6422
6423
/**
6424
 * Returns the <script> HTML tag
6425
 */
6426
function api_get_asset($file) {
6427
    return '<script type="text/javascript" src="'.api_get_path(WEB_PATH).'web/assets/'.$file.'"></script>'."\n";
6428
}
6429
6430
/**
6431
 * Returns the <link> HTML tag
6432
 * @param string $file
6433
 */
6434
function api_get_css($file, $media = 'screen') {
6435
    return '<link href="'.$file.'" rel="stylesheet" media="'.$media.'" type="text/css" />'."\n";
6436
}
6437
6438
/**
6439
 * Returns the js header to include the jquery library
6440
 */
6441
function api_get_jquery_js()
6442
{
6443
    return api_get_asset('jquery/dist/jquery.min.js');
6444
}
6445
6446
/**
6447
 * Returns the jquery path
6448
 * @return string
6449
 */
6450
function api_get_jquery_web_path()
6451
{
6452
    return api_get_path(WEB_PATH).'web/assets/jquery/dist/jquery.min.js';
6453
}
6454
6455
/**
6456
 * @return string
6457
 */
6458
function api_get_jquery_ui_js_web_path()
6459
{
6460
    return api_get_path(WEB_PATH).'web/assets/jquery-ui/jquery-ui.min.js';
6461
}
6462
6463
/**
6464
 * @return string
6465
 */
6466
function api_get_jquery_ui_css_web_path()
6467
{
6468
    return api_get_path(WEB_PATH).'web/assets/jquery-ui/themes/smoothness/jquery-ui.min.css';
6469
}
6470
6471
/**
6472
 * Returns the jquery-ui library js headers
6473
 * @param   bool    add the jqgrid library
6474
 * @return  string  html tags
6475
 *
6476
 */
6477
function api_get_jquery_ui_js($include_jqgrid = false) {
6478
    $libraries = array();
6479
    if ($include_jqgrid) {
6480
       $libraries[]='jqgrid';
6481
    }
6482
    return api_get_jquery_libraries_js($libraries);
6483
}
6484
6485
function api_get_jqgrid_js() {
6486
    return api_get_jquery_libraries_js(array('jqgrid'));
6487
}
6488
6489
6490
/**
6491
 * Returns the jquery library js and css headers
6492
 *
6493
 * @param   array   list of jquery libraries supported jquery-ui, jqgrid
6494
 * @param   bool    add the jquery library
6495
 * @return  string  html tags
6496
 *
6497
 */
6498
function api_get_jquery_libraries_js($libraries) {
6499
    $js = '';
6500
    $js_path = api_get_path(WEB_LIBRARY_PATH).'javascript/';
6501
6502
    //jqgrid js and css
6503
    if (in_array('jqgrid', $libraries)) {
6504
        $languaje   = 'en';
6505
        $platform_isocode = strtolower(api_get_language_isocode());
6506
6507
        //languages supported by jqgrid see files in main/inc/lib/javascript/jqgrid/js/i18n
6508
        $jqgrid_langs = array(
6509
            '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'
6510
        );
6511
6512
        if (in_array($platform_isocode, $jqgrid_langs)) {
6513
            $languaje = $platform_isocode;
6514
        }
6515
        //$js .= '<link rel="stylesheet" href="'.$js_path.'jqgrid/css/ui.jqgrid.css" type="text/css">';
6516
        $js .= api_get_css($js_path.'jqgrid/css/ui.jqgrid.css');
6517
        $js .= api_get_js('jqgrid/js/i18n/grid.locale-'.$languaje.'.js');
6518
        $js .= api_get_js('jqgrid/js/jquery.jqGrid.min.js');
6519
    }
6520
6521
    //Document multiple upload funcionality
6522
    if (in_array('jquery-upload', $libraries)) {
6523
6524
        $js .= api_get_asset('blueimp-load-image/js/load-image.all.min.js');
6525
        $js .= api_get_asset('blueimp-canvas-to-blob/js/canvas-to-blob.min.js');
6526
        $js .= api_get_asset('jquery-file-upload/js/jquery.iframe-transport.js');
6527
        $js .= api_get_asset('jquery-file-upload/js/jquery.fileupload.js');
6528
        $js .= api_get_asset('jquery-file-upload/js/jquery.fileupload-process.js');
6529
        $js .= api_get_asset('jquery-file-upload/js/jquery.fileupload-image.js');
6530
        $js .= api_get_asset('jquery-file-upload/js/jquery.fileupload-audio.js');
6531
        $js .= api_get_asset('jquery-file-upload/js/jquery.fileupload-video.js');
6532
        $js .= api_get_asset('jquery-file-upload/js/jquery.fileupload-validate.js');
6533
6534
        $js .= api_get_css(api_get_path(WEB_PATH).'web/assets/jquery-file-upload/css/jquery.fileupload.css');
6535
        $js .= api_get_css(api_get_path(WEB_PATH).'web/assets/jquery-file-upload/css/jquery.fileupload-ui.css');
6536
    }
6537
6538
    // jquery datepicker
6539
    if (in_array('datepicker', $libraries)) {
6540
        $languaje   = 'en-GB';
6541
        $platform_isocode = strtolower(api_get_language_isocode());
6542
6543
        // languages supported by jqgrid see files in main/inc/lib/javascript/jqgrid/js/i18n
6544
        $datapicker_langs = array(
6545
            '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'
6546
        );
6547
        if (in_array($platform_isocode, $datapicker_langs)) {
6548
            $languaje = $platform_isocode;
6549
        }
6550
6551
        $js .= api_get_js('jquery-ui/jquery-ui-i18n.min.js');
6552
        $script = '<script>
6553
        $(function(){
6554
            $.datepicker.setDefaults($.datepicker.regional["'.$languaje.'"]);
6555
            $.datepicker.regional["local"] = $.datepicker.regional["'.$languaje.'"];
6556
        });
6557
        </script>
6558
        ';
6559
        $js .= $script;
6560
    }
6561
    return $js;
6562
}
6563
6564
/**
6565
 * Returns the course's URL
6566
 *
6567
 * This function relies on api_get_course_info()
6568
 * @param   string  The course code - optional (takes it from session if not given)
6569
 * @param   int     The session id  - optional (takes it from session if not given)
6570
 * @param integer $session_id
6571
 * @return  string|null   The URL of the course or null if something does not work
6572
 * @author  Julio Montoya <[email protected]>
6573
 */
6574
function api_get_course_url($course_code = null, $session_id = null)
6575
{
6576
    if (empty($course_code)) {
6577
        $course_info = api_get_course_info();
6578
    } else {
6579
        $course_info = api_get_course_info($course_code);
6580
    }
6581
    if (empty($session_id)) {
6582
        $session_url = '?id_session='.api_get_session_id();
6583
    } else {
6584
        $session_url = '?id_session='.intval($session_id);
6585
    }
6586
    /*
6587
    if (empty($group_id)) {
6588
        $group_url = '&gidReq='.api_get_group_id();
6589
    } else {
6590
        $group_url = '&gidReq='.intval($group_id);
6591
    }*/
6592
    if (!empty($course_info['path'])) {
6593
        return api_get_path(WEB_COURSE_PATH).$course_info['path'].'/index.php'.$session_url;
6594
    }
6595
    return null;
6596
}
6597
6598
/**
6599
 *
6600
 * Check if the current portal has the $_configuration['multiple_access_urls'] parameter on
6601
 * @return bool true if multi site is enabled
6602
 *
6603
 * */
6604
function api_get_multiple_access_url() {
6605
    global $_configuration;
6606
    if (isset($_configuration['multiple_access_urls']) && $_configuration['multiple_access_urls']) {
6607
        return true;
6608
    }
6609
    return false;
6610
}
6611
6612
/**
6613
 * @return bool
6614
 */
6615
function api_is_multiple_url_enabled() {
6616
    return api_get_multiple_access_url();
6617
}
6618
6619
/**
6620
 * Returns a md5 unique id
6621
 * @todo add more parameters
6622
 */
6623
function api_get_unique_id() {
6624
    $id = md5(time().uniqid().api_get_user_id().api_get_course_id().api_get_session_id());
6625
    return $id;
6626
}
6627
6628
/**
6629
 * Get home path
6630
 * @return string
6631
 */
6632
function api_get_home_path()
6633
{
6634
    $home = 'app/home/';
6635
    if (api_get_multiple_access_url()) {
6636
        $access_url_id = api_get_current_access_url_id();
6637
        $url_info = api_get_access_url($access_url_id);
6638
        $url = api_remove_trailing_slash(preg_replace('/https?:\/\//i', '', $url_info['url']));
6639
        $clean_url = api_replace_dangerous_char($url);
6640
        $clean_url = str_replace('/', '-', $clean_url);
6641
        $clean_url .= '/';
6642
6643
        $home = 'app/home/' . $clean_url;
6644
    }
6645
6646
    return $home;
6647
}
6648
6649
/**
6650
 *
6651
 * @param int Course id
6652
 * @param int tool id: TOOL_QUIZ, TOOL_FORUM, TOOL_STUDENTPUBLICATION, TOOL_LEARNPATH
6653
 * @param int the item id (tool id, exercise id, lp id)
6654
 *
6655
 */
6656
function api_resource_is_locked_by_gradebook($item_id, $link_type, $course_code = null) {
6657
    if (api_is_platform_admin()) {
6658
        return false;
6659
    }
6660
    if (api_get_setting('gradebook_locking_enabled') == 'true') {
6661
        if (empty($course_code)) {
6662
            $course_code = api_get_course_id();
6663
        }
6664
        $table = Database::get_main_table(TABLE_MAIN_GRADEBOOK_LINK);
6665
        $item_id = intval($item_id);
6666
        $link_type = intval($link_type);
6667
        $course_code = Database::escape_string($course_code);
6668
        $sql = "SELECT locked FROM $table
6669
                WHERE locked = 1 AND ref_id = $item_id AND type = $link_type AND course_code = '$course_code' ";
6670
        $result = Database::query($sql);
6671
        if (Database::num_rows($result)) {
6672
            return true;
6673
        }
6674
    }
6675
    return false;
6676
}
6677
6678
/**
6679
 * Blocks a page if the item was added in a gradebook
6680
 *
6681
 * @param int       exercise id, work id, thread id,
6682
 * @param int       LINK_EXERCISE, LINK_STUDENTPUBLICATION, LINK_LEARNPATH LINK_FORUM_THREAD, LINK_ATTENDANCE
6683
 * see gradebook/lib/be/linkfactory
6684
 * @param string    course code
6685
 * @return false|null
6686
 */
6687
function api_block_course_item_locked_by_gradebook($item_id, $link_type, $course_code = null) {
6688
    if (api_is_platform_admin()) {
6689
        return false;
6690
    }
6691
6692
    if (api_resource_is_locked_by_gradebook($item_id, $link_type, $course_code)) {
6693
        $message = Display::return_message(get_lang('ResourceLockedByGradebook'), 'warning');
6694
        api_not_allowed(true, $message);
6695
    }
6696
}
6697
/**
6698
 * Checks the PHP version installed is enough to run Chamilo
6699
 * @param string Include path (used to load the error page)
6700
 * @return void
6701
 */
6702
function api_check_php_version($my_inc_path = null) {
6703
    if (!function_exists('version_compare') || version_compare( phpversion(), REQUIRED_PHP_VERSION, '<')) {
6704
        $global_error_code = 1;
6705
        // Incorrect PHP version
6706
        $global_page = $my_inc_path.'global_error_message.inc.php';
6707
        if (file_exists($global_page)) {
6708
            require $global_page;
6709
        }
6710
        exit;
6711
    }
6712
}
6713
/**
6714
 * Checks whether the Archive directory is present and writeable. If not,
6715
 * prints a warning message.
6716
 */
6717
function api_check_archive_dir() {
6718 View Code Duplication
    if (is_dir(api_get_path(SYS_ARCHIVE_PATH)) && !is_writable(api_get_path(SYS_ARCHIVE_PATH))) {
6719
        $message = Display::return_message(get_lang('ArchivesDirectoryNotWriteableContactAdmin'),'warning');
6720
        api_not_allowed(true, $message);
6721
    }
6722
}
6723
/**
6724
 * Returns an array of global configuration settings which should be ignored
6725
 * when printing the configuration settings screens
6726
 * @return array Array of strings, each identifying one of the excluded settings
6727
 */
6728
function api_get_locked_settings() {
6729
    return array(
6730
        'server_type',
6731
        'permanently_remove_deleted_files',
6732
        'account_valid_duration',
6733
        'service_visio',
6734
        'service_ppt2lp',
6735
        'wcag_anysurfer_public_pages',
6736
        'upload_extensions_list_type',
6737
        'upload_extensions_blacklist',
6738
        'upload_extensions_whitelist',
6739
        'upload_extensions_skip',
6740
        'upload_extensions_replace_by',
6741
        'hide_dltt_markup',
6742
        'split_users_upload_directory',
6743
        'permissions_for_new_directories',
6744
        'permissions_for_new_files',
6745
        'platform_charset',
6746
        'service_visio',
6747
        'ldap_description',
6748
        'cas_activate',
6749
        'cas_server',
6750
        'cas_server_uri',
6751
        'cas_port',
6752
        'cas_protocol',
6753
        'cas_add_user_activate',
6754
        'update_user_info_cas_with_ldap',
6755
        'languagePriority1',
6756
        'languagePriority2',
6757
        'languagePriority3',
6758
        'languagePriority4',
6759
        'login_is_email',
6760
        'chamilo_database_version'
6761
    );
6762
}
6763
6764
/**
6765
 * Checks if the user is corrently logged in. Returns the user ID if he is, or
6766
 * false if he isn't. If the user ID is given and is an integer, then the same
6767
 * ID is simply returned
6768
 * @param  integer User ID
6769
 * @return boolean Integer User ID is logged in, or false otherwise
6770
 */
6771
function api_user_is_login($user_id = null) {
6772
    $user_id = empty($user_id) ? api_get_user_id() : intval($user_id);
6773
    return $user_id && !api_is_anonymous();
6774
}
6775
6776
/**
6777
 * Guess the real ip for register in the database, even in reverse proxy cases.
6778
 * To be recognized, the IP has to be found in either $_SERVER['REMOTE_ADDR'] or
6779
 * in $_SERVER['HTTP_X_FORWARDED_FOR'], which is in common use with rproxies.
6780
 * @return string the user's real ip (unsafe - escape it before inserting to db)
6781
 * @author Jorge Frisancho Jibaja <[email protected]>, USIL - Some changes to allow the use of real IP using reverse proxy
6782
 * @version CEV CHANGE 24APR2012
6783
 */
6784
function api_get_real_ip(){
6785
    // Guess the IP if behind a reverse proxy
6786
    global $debug;
6787
    $ip = trim($_SERVER['REMOTE_ADDR']);
6788
    if (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) {
6789
        if (preg_match('/,/', $_SERVER['HTTP_X_FORWARDED_FOR'])) {
6790
            @list($ip1, $ip2) = @explode(',', $_SERVER['HTTP_X_FORWARDED_FOR']);
6791
        } else {
6792
            $ip1 = $_SERVER['HTTP_X_FORWARDED_FOR'];
6793
        }
6794
        $ip = trim($ip1);
6795
    }
6796
    if (!empty($debug)) error_log('Real IP: '.$ip);
6797
    return $ip;
6798
}
6799
6800
/**
6801
 * Checks whether an IP is included inside an IP range
6802
 * @param string IP address
6803
 * @param string IP range
6804
 * @param string $ip
6805
 * @return bool True if IP is in the range, false otherwise
6806
 * @author claudiu at cnixs dot com  on http://www.php.net/manual/fr/ref.network.php#55230
6807
 * @author Yannick Warnier for improvements and managment of multiple ranges
6808
 * @todo check for IPv6 support
6809
 */
6810
function api_check_ip_in_range($ip,$range)
6811
{
6812
    if (empty($ip) or empty($range)) {
6813
        return false;
6814
    }
6815
    $ip_ip = ip2long ($ip);
6816
    // divide range param into array of elements
6817
    if (strpos($range,',')!==false) {
6818
        $ranges = explode(',',$range);
6819
    } else {
6820
        $ranges = array($range);
6821
    }
6822
    foreach ($ranges as $range) {
6823
        $range = trim($range);
6824
        if (empty($range)) { continue; }
6825
        if (strpos($range,'/')===false) {
6826
            if (strcmp($ip,$range)===0) {
6827
                return true; // there is a direct IP match, return OK
6828
            }
6829
            continue; //otherwise, get to the next range
6830
        }
6831
        // the range contains a "/", so analyse completely
6832
        list ($net, $mask) = explode("/", $range);
6833
6834
        $ip_net = ip2long ($net);
6835
        // mask binary magic
6836
        $ip_mask = ~((1 << (32 - $mask)) - 1);
6837
6838
        $ip_ip_net = $ip_ip & $ip_mask;
6839
        if ($ip_ip_net == $ip_net) {
6840
            return true;
6841
        }
6842
    }
6843
6844
    return false;
6845
}
6846
6847
function api_check_user_access_to_legal($course_visibility) {
6848
    $course_visibility_list = array(COURSE_VISIBILITY_OPEN_WORLD, COURSE_VISIBILITY_OPEN_PLATFORM);
6849
    return in_array($course_visibility, $course_visibility_list) || api_is_drh();
6850
}
6851
6852
/**
6853
 * Checks if the global chat is enabled or not
6854
 *
6855
 * @return bool
6856
 */
6857
function api_is_global_chat_enabled()
6858
{
6859
    return
6860
        !api_is_anonymous() &&
6861
        api_get_setting('allow_global_chat') == 'true' &&
6862
        api_get_setting('allow_social_tool') == 'true';
6863
}
6864
6865
/**
6866
 * @todo Fix tool_visible_by_default_at_creation labels
6867
 * @todo Add sessionId parameter to avoid using context
6868
 *
6869
 * @param int $item_id
6870
 * @param int $tool_id
6871
 * @param int $group_id
6872
 * @param array $courseInfo
6873
 */
6874
function api_set_default_visibility($item_id, $tool_id, $group_id = 0, $courseInfo = array(), $sessionId = 0, $userId = 0)
6875
{
6876
    $courseInfo = empty($courseInfo) ? api_get_course_info() : $courseInfo;
6877
    $courseId = $courseInfo['real_id'];
6878
    $courseCode = $courseInfo['code'];
6879
    $sessionId = empty($sessionId) ? api_get_session_id() : $sessionId;
6880
    $userId = empty($userId) ? api_get_user_id() : $userId;
6881
6882
    $original_tool_id = $tool_id;
6883
6884
    switch ($tool_id) {
6885
        case TOOL_LINK:
6886
        case TOOL_LINK_CATEGORY:
6887
            $tool_id = 'links';
6888
            break;
6889
        case TOOL_DOCUMENT:
6890
            $tool_id = 'documents';
6891
            break;
6892
        case TOOL_LEARNPATH:
6893
            $tool_id = 'learning';
6894
            break;
6895
        case TOOL_ANNOUNCEMENT:
6896
            $tool_id = 'announcements';
6897
            break;
6898
        case TOOL_FORUM:
6899
        case TOOL_FORUM_CATEGORY:
6900
        case TOOL_FORUM_THREAD:
6901
            $tool_id = 'forums';
6902
            break;
6903
        case TOOL_QUIZ:
6904
            $tool_id = 'quiz';
6905
            break;
6906
    }
6907
    $setting = api_get_setting('tool_visible_by_default_at_creation');
6908
6909
    if (isset($setting[$tool_id])) {
6910
        $visibility = 'invisible';
6911
        if ($setting[$tool_id] == 'true') {
6912
            $visibility = 'visible';
6913
        }
6914
6915
        if (empty($group_id)) {
6916
            $group_id = api_get_group_id();
6917
        }
6918
6919
        // Read the portal and course default visibility
6920
        if ($tool_id == 'documents') {
6921
            $visibility = DocumentManager::getDocumentDefaultVisibility($courseCode);
6922
        }
6923
6924
        api_item_property_update(
6925
            $courseInfo,
6926
            $original_tool_id,
6927
            $item_id,
6928
            $visibility,
6929
            $userId,
6930
            $group_id,
6931
            null,
6932
            null,
6933
            null,
6934
            api_get_session_id()
6935
        );
6936
6937
        // Fixes default visibility for tests
6938
6939
        switch ($original_tool_id) {
6940
            case TOOL_QUIZ:
6941
                if (empty($sessionId)) {
6942
                    $objExerciseTmp = new Exercise($courseId);
6943
                    $objExerciseTmp->read($item_id);
6944
                    if ($visibility == 'visible') {
6945
                        $objExerciseTmp->enable();
6946
                        $objExerciseTmp->save();
6947
                    } else {
6948
                        $objExerciseTmp->disable();
6949
                        $objExerciseTmp->save();
6950
                    }
6951
                }
6952
                break;
6953
        }
6954
    }
6955
}
6956
6957
/**
6958
 * @return string
6959
 */
6960
function api_get_security_key() {
6961
    return api_get_configuration_value('security_key');
6962
}
6963
6964
/**
6965
 * @param int $user_id
6966
 * @param int $courseId
6967
 * @param int $session_id
6968
 * @return array
6969
 */
6970
function api_detect_user_roles($user_id, $courseId, $session_id = 0)
6971
{
6972
    $user_roles = array();
6973
    /*$user_info = api_get_user_info($user_id);
6974
    $user_roles[] = $user_info['status'];*/
6975
    $courseInfo = api_get_course_info_by_id($courseId);
6976
    $course_code = $courseInfo['code'];
6977
6978
    $url_id = api_get_current_access_url_id();
6979
    if (api_is_platform_admin_by_id($user_id, $url_id)) {
6980
        $user_roles[] = PLATFORM_ADMIN;
6981
    }
6982
6983
    /*if (api_is_drh()) {
6984
        $user_roles[] = DRH;
6985
    }*/
6986
6987
    if (!empty($session_id)) {
6988
        if (SessionManager::user_is_general_coach($user_id, $session_id)) {
6989
            $user_roles[] = SESSION_GENERAL_COACH;
6990
        }
6991
    }
6992
6993
    if (!empty($course_code)) {
6994
        if (empty($session_id)) {
6995
            if (CourseManager::is_course_teacher($user_id, $course_code)) {
6996
                $user_roles[] = COURSEMANAGER;
6997
            }
6998
            if (CourseManager::get_tutor_in_course_status($user_id, $course_code)) {
6999
                $user_roles[] = COURSE_TUTOR;
7000
            }
7001
7002
            if (CourseManager::is_user_subscribed_in_course($user_id, $course_code)) {
7003
                $user_roles[] = COURSE_STUDENT;
7004
            }
7005
        } else {
7006
            $user_status_in_session = SessionManager::get_user_status_in_course_session(
7007
                $user_id,
7008
                $courseId,
7009
                $session_id
7010
            );
7011
7012
            if (!empty($user_status_in_session)) {
7013
                if ($user_status_in_session == 0) {
7014
                    $user_roles[] = SESSION_STUDENT;
7015
                }
7016
                if ($user_status_in_session == 2) {
7017
                    $user_roles[] = SESSION_COURSE_COACH;
7018
                }
7019
            }
7020
7021
            /*if (api_is_course_session_coach($user_id, $course_code, $session_id)) {
7022
               $user_roles[] = SESSION_COURSE_COACH;
7023
            }*/
7024
        }
7025
    }
7026
    return $user_roles;
7027
}
7028
7029
function api_get_roles_to_string($roles) {
7030
    $role_names = array();
7031
    if (!empty($roles)) {
7032
        foreach ($roles as $role) {
7033
            $role_names[] = get_status_from_code($role);
7034
        }
7035
    }
7036
    if (!empty($role_names)) {
7037
        return implode(', ', $role_names);
7038
    }
7039
    return null;
7040
}
7041
7042
function role_actions() {
7043
    return array(
7044
        'course' => array(
7045
            'create',
7046
            'read',
7047
            'edit',
7048
            'delete'
7049
        ),
7050
        'admin' => array(
7051
            'create',
7052
            'read',
7053
            'edit',
7054
            'delete'
7055
        )
7056
    );
7057
}
7058
7059
/**
7060
 * @param int $courseId
7061
 * @param int $session_id
7062
 * @return bool
7063
 */
7064
function api_coach_can_edit_view_results($courseId = null, $session_id = null)
7065
{
7066
    $user_id = api_get_user_id();
7067
7068
    if (empty($courseId)) {
7069
        $courseId = api_get_course_int_id();
7070
    }
7071
7072
    if (empty($session_id)) {
7073
        $session_id = api_get_session_id();
7074
    }
7075
7076
    if (api_is_platform_admin()) {
7077
        return true;
7078
    }
7079
7080
    $roles = api_detect_user_roles($user_id, $courseId, $session_id);
7081
7082
    if (in_array(SESSION_COURSE_COACH, $roles)) {
7083
        //return api_get_setting('session_tutor_reports_visibility') == 'true';
7084
        return true;
7085
    } else {
7086
        if (in_array(COURSEMANAGER, $roles)) {
7087
            return true;
7088
        }
7089
        return false;
7090
    }
7091
}
7092
7093
function api_get_js_simple($file) {
7094
    return '<script type="text/javascript" src="'.$file.'"></script>'."\n";
7095
}
7096
7097
function api_set_settings_and_plugins() {
7098
    global $_configuration;
7099
    $_setting = array();
7100
    $_plugins = array();
7101
7102
    // access_url == 1 is the default chamilo location
7103
    $settings_by_access_list = array();
7104
    $access_url_id = api_get_current_access_url_id();
7105 View Code Duplication
    if ($access_url_id != 1) {
7106
        $url_info = api_get_access_url($_configuration['access_url']);
7107
        if ($url_info['active'] == 1) {
7108
            $settings_by_access = & api_get_settings(null, 'list', $_configuration['access_url'], 1);
7109
            foreach ($settings_by_access as & $row) {
7110
                if (empty($row['variable'])) {
7111
                    $row['variable'] = 0;
7112
                }
7113
                if (empty($row['subkey'])) {
7114
                    $row['subkey'] = 0;
7115
                }
7116
                if (empty($row['category'])) {
7117
                    $row['category'] = 0;
7118
                }
7119
                $settings_by_access_list[$row['variable']][$row['subkey']][$row['category']] = $row;
7120
            }
7121
        }
7122
    }
7123
7124
    $result = api_get_settings(null, 'list', 1);
7125
7126 View Code Duplication
    foreach ($result as & $row) {
7127
        if ($access_url_id != 1) {
7128
            if ($url_info['active'] == 1) {
7129
                $var = empty($row['variable']) ? 0 : $row['variable'];
7130
                $subkey = empty($row['subkey']) ? 0 : $row['subkey'];
7131
                $category = empty($row['category']) ? 0 : $row['category'];
7132
            }
7133
7134
            if ($row['access_url_changeable'] == 1 && $url_info['active'] == 1) {
7135
                if (isset($settings_by_access_list[$var]) &&
7136
                    $settings_by_access_list[$var][$subkey][$category]['selected_value'] != '') {
7137
                    if ($row['subkey'] == null) {
7138
                        $_setting[$row['variable']] = $settings_by_access_list[$var][$subkey][$category]['selected_value'];
7139
                    } else {
7140
                        $_setting[$row['variable']][$row['subkey']] = $settings_by_access_list[$var][$subkey][$category]['selected_value'];
7141
                    }
7142
                } else {
7143
                    if ($row['subkey'] == null) {
7144
                        $_setting[$row['variable']] = $row['selected_value'];
7145
                    } else {
7146
                        $_setting[$row['variable']][$row['subkey']] = $row['selected_value'];
7147
                    }
7148
                }
7149
            } else {
7150
                if ($row['subkey'] == null) {
7151
                    $_setting[$row['variable']] = $row['selected_value'];
7152
                } else {
7153
                    $_setting[$row['variable']][$row['subkey']] = $row['selected_value'];
7154
                }
7155
            }
7156
        } else {
7157
            if ($row['subkey'] == null) {
7158
                $_setting[$row['variable']] = $row['selected_value'];
7159
            } else {
7160
                $_setting[$row['variable']][$row['subkey']] = $row['selected_value'];
7161
            }
7162
        }
7163
    }
7164
7165
    $result = api_get_settings('Plugins', 'list', $access_url_id);
7166
    $_plugins = array();
7167 View Code Duplication
    foreach ($result as & $row) {
7168
        $key = & $row['variable'];
7169
        if (is_string($_setting[$key])) {
7170
            $_setting[$key] = array();
7171
        }
7172
        $_setting[$key][] = $row['selected_value'];
7173
        $_plugins[$key][] = $row['selected_value'];
7174
    }
7175
7176
    $_SESSION['_setting'] = $_setting;
7177
    $_SESSION['_plugins'] = $_plugins;
7178
}
7179
7180
function api_set_setting_last_update()
7181
{
7182
    // Saving latest refresh.
7183
    api_set_setting('settings_latest_update', api_get_utc_datetime());
7184
}
7185
7186
/**
7187
 * Tries to set memory limit, if authorized and new limit is higher than current
7188
 * @param string New memory limit
7189
 * @param string $mem
7190
 * @return bool True on success, false on failure or current is higher than suggested
7191
 * @assert (null) === false
7192
 * @assert (-1) === false
7193
 * @assert (0) === true
7194
 * @assert ('1G') === true
7195
 */
7196
function api_set_memory_limit($mem){
7197
    //if ini_set() not available, this function is useless
7198
    if (!function_exists('ini_set') || is_null($mem) || $mem == -1) {
7199
        return false;
7200
    }
7201
7202
    $memory_limit = ini_get('memory_limit');
7203
    if (api_get_bytes_memory_limit($mem) > api_get_bytes_memory_limit($memory_limit)){
7204
        ini_set('memory_limit', $mem);
7205
        return true;
7206
    }
7207
    return false;
7208
}
7209
7210
/**
7211
 * Gets memory limit in bytes
7212
 * @param string The memory size (128M, 1G, 1000K, etc)
7213
 * @return int
7214
 * @assert (null) === false
7215
 * @assert ('1t')  === 1099511627776
7216
 * @assert ('1g')  === 1073741824
7217
 * @assert ('1m')  === 1048576
7218
 * @assert ('100k') === 102400
7219
 */
7220
function api_get_bytes_memory_limit($mem){
7221
    $size = strtolower(substr($mem,-1));
7222
7223
    switch ($size) {
7224
        case 't':
7225
            $mem = intval(substr($mem,-1))*1024*1024*1024*1024;
7226
            break;
7227
        case 'g':
7228
            $mem = intval(substr($mem,0,-1))*1024*1024*1024;
7229
            break;
7230
        case 'm':
7231
            $mem = intval(substr($mem,0,-1))*1024*1024;
7232
            break;
7233
        case 'k':
7234
            $mem = intval(substr($mem,0,-1))*1024;
7235
            break;
7236
        default:
7237
            // we assume it's integer only
7238
            $mem = intval($mem);
7239
            break;
7240
    }
7241
    return $mem;
7242
}
7243
7244
/**
7245
 * Finds all the information about a user from username instead of user id
7246
 *
7247
 * @return array $user_info user_id, lastname, firstname, username, email, ...
7248
 * @author Yannick Warnier <[email protected]>
7249
 */
7250 View Code Duplication
function api_get_user_info_from_official_code($official_code = '')
7251
{
7252
    if (empty($official_code)) {
7253
        return false;
7254
    }
7255
    $sql = "SELECT * FROM ".Database :: get_main_table(TABLE_MAIN_USER)."
7256
            WHERE official_code ='".Database::escape_string($official_code)."'";
7257
    $result = Database::query($sql);
7258
    if (Database::num_rows($result) > 0) {
7259
        $result_array = Database::fetch_array($result);
7260
        return _api_format_user($result_array);
7261
    }
7262
    return false;
7263
}
7264
7265
/**
7266
 *
7267
 *
7268
 * @return string
7269
 */
7270
function api_get_password_checker_js($usernameInputId, $passwordInputid)
7271
{
7272
    $checkPass = api_get_setting('allow_strength_pass_checker');
7273
    $useStrengthPassChecker = $checkPass == 'true';
7274
7275
    if ($useStrengthPassChecker == false) {
7276
        return null;
7277
    }
7278
7279
    $verdicts = array(
7280
        get_lang('PasswordWeak'),
7281
        get_lang('PasswordNormal'),
7282
        get_lang('PasswordMedium'),
7283
        get_lang('PasswordStrong'),
7284
        get_lang('PasswordVeryStrong'),
7285
    );
7286
    $js = api_get_js('strength/strength.js');
7287
    $js .=  "<script>
7288
7289
    var verdicts = ['".implode("','", $verdicts)."'];
7290
    var errorMessages = {
7291
        password_to_short : \"" . get_lang('PasswordIsTooShort')."\",
7292
        same_as_username : \"".get_lang('YourPasswordCannotBeTheSameAsYourUsername')."\"
7293
    };
7294
7295
    $(document).ready(function() {
7296
        var options = {
7297
            verdicts: verdicts,
7298
            onLoad : function () {
7299
                //$('#messages').text('Start typing password');
7300
            },
7301
            onKeyUp: function (evt) {
7302
                $(evt.target).pwstrength('outputErrorList');
7303
            },
7304
            errorMessages : errorMessages,
7305
            viewports: {
7306
                progress: '#password_progress',
7307
                verdict: '#password-verdict',
7308
                errors: '#password-errors'
7309
            },
7310
            usernameField: '$usernameInputId'
7311
        };
7312
        $('".$passwordInputid."').pwstrength(options);
7313
    });
7314
    </script>";
7315
    return $js;
7316
}
7317
7318
/**
7319
 * Gets an array with "easy" passwords
7320
 * @return array
7321
 */
7322
function api_get_easy_password_list()
7323
{
7324
    $passwordList = array('123', '1234', '123456', 'admin', 'user', 'student', 'teacher');
7325
    $file = api_get_path(CONFIGURATION_PATH).'easy_password_list.php';
7326
    if (file_exists($file)) {
7327
        $passwordList = require_once $file;
7328
    }
7329
    return $passwordList;
7330
}
7331
7332
/**
7333
 * @param string $username
7334
 * create an user extra field called 'captcha_blocked_until_date'
7335
 */
7336
function api_block_account_captcha($username)
7337
{
7338
    $userInfo = api_get_user_info_from_username($username);
7339
    if (empty($userInfo)) {
7340
        return false;
7341
    }
7342
    $minutesToBlock = api_get_setting('captcha_time_to_block');
7343
    $time = time() + $minutesToBlock*60;
7344
    UserManager::update_extra_field_value(
7345
        $userInfo['user_id'],
7346
        'captcha_blocked_until_date',
7347
        api_get_utc_datetime($time)
7348
    );
7349
}
7350
7351
/**
7352
 * @param string $username
7353
 */
7354
function api_clean_account_captcha($username)
7355
{
7356
    $userInfo = api_get_user_info_from_username($username);
7357
    if (empty($userInfo)) {
7358
        return false;
7359
    }
7360
    Session::erase('loginFailedCount');
7361
    UserManager::update_extra_field_value(
7362
        $userInfo['user_id'],
7363
        'captcha_blocked_until_date',
7364
        null
7365
    );
7366
}
7367
7368
/**
7369
 * @param string $username
7370
 * @return bool
7371
 */
7372
function api_get_user_blocked_by_captcha($username)
7373
{
7374
    $userInfo = api_get_user_info_from_username($username);
7375
    if (empty($userInfo)) {
7376
        return false;
7377
    }
7378
    $data = UserManager::get_extra_user_data_by_field(
7379
        $userInfo['user_id'],
7380
        'captcha_blocked_until_date'
7381
    );
7382
    if (isset($data) && isset($data['captcha_blocked_until_date'])) {
7383
        return $data['captcha_blocked_until_date'];
7384
    }
7385
    return false;
7386
}
7387
7388
/**
7389
 * Remove tags from HTML anf return the $in_number_char first non-HTML char
7390
 * Postfix the text with "..." if it has been truncated.
7391
 * @param integer $in_number_char
7392
 * @return string
7393
 * @author hubert borderiou
7394
 */
7395
function api_get_short_text_from_html($in_html, $in_number_char)
7396
{
7397
    $out_res = api_remove_tags_with_space($in_html, false);
7398
    $postfix = "...";
7399
    if (strlen($out_res) > $in_number_char) {
7400
        $out_res = substr($out_res, 0, $in_number_char).$postfix;
7401
    }
7402
    return $out_res;
7403
}
7404
7405
/**
7406
 * Replace tags with a space in a text.
7407
 * If $in_double_quote_replace, replace " with '' (for HTML attribute purpose, for exemple)
7408
 * @return string
7409
 * @author hubert borderiou
7410
 */
7411
function api_remove_tags_with_space($in_html, $in_double_quote_replace = true) {
7412
    $out_res = $in_html;
7413
    if ($in_double_quote_replace) {
7414
        $out_res = str_replace('"', "''", $out_res);
7415
    }
7416
    // avoid text stuck together when tags are removed, adding a space after >
7417
    $out_res = str_replace (">", "> ", $out_res);
7418
    $out_res = strip_tags($out_res);
7419
7420
    return $out_res;
7421
}
7422
7423
/**
7424
 * If true, the drh can access all content (courses, users) inside a session
7425
 * @return bool
7426
 */
7427
function api_drh_can_access_all_session_content()
7428
{
7429
    $a = api_get_setting('drh_can_access_all_session_content');
7430
    return $a == 'true';
7431
}
7432
7433
/**
7434
 * @param string $tool
7435
 * @param string $setting
7436
 * @param integer $defaultValue
7437
 * @return string
7438
 */
7439
function api_get_default_tool_setting($tool, $setting, $defaultValue)
7440
{
7441
    global $_configuration;
7442
    if (isset($_configuration[$tool]) &&
7443
        isset($_configuration[$tool]['default_settings']) &&
7444
        isset($_configuration[$tool]['default_settings'][$setting])
7445
    ) {
7446
        return $_configuration[$tool]['default_settings'][$setting];
7447
    }
7448
    return $defaultValue;
7449
7450
}
7451
7452
/**
7453
 * Checks if user can login as another user
7454
 *
7455
 * @param int $loginAsUserId the user id to log in
7456
 * @param int $userId my user id
7457
 * @return bool
7458
 */
7459
function api_can_login_as($loginAsUserId, $userId = null)
7460
{
7461
    if (empty($userId)) {
7462
        $userId = api_get_user_id();
7463
    }
7464
    if ($loginAsUserId == $userId) {
7465
        return false;
7466
    }
7467
7468
    if (empty($loginAsUserId)) {
7469
        return false;
7470
    }
7471
7472
    if ($loginAsUserId != strval(intval($loginAsUserId))) {
7473
        return false;
7474
    }
7475
    // Check if the user to login is an admin
7476
7477
    if (api_is_platform_admin_by_id($loginAsUserId)) {
7478
        // Only super admins can login to admin accounts
7479
        if (!api_global_admin_can_edit_admin($loginAsUserId)) {
7480
            return false;
7481
        }
7482
    }
7483
7484
    $userInfo = api_get_user_info($userId);
7485
7486
    $isDrh = function() use($loginAsUserId) {
7487
        if (api_is_drh()) {
7488
            if (api_drh_can_access_all_session_content()) {
7489
                $users = SessionManager::getAllUsersFromCoursesFromAllSessionFromStatus('drh_all', api_get_user_id());
7490
                $userList = array();
7491
                foreach ($users as $user) {
0 ignored issues
show
Bug introduced by
The expression $users of type array|integer is not guaranteed to be traversable. How about adding an additional type check?

There are different options of fixing this problem.

  1. If you want to be on the safe side, you can add an additional type-check:

    $collection = json_decode($data, true);
    if ( ! is_array($collection)) {
        throw new \RuntimeException('$collection must be an array.');
    }
    
    foreach ($collection as $item) { /** ... */ }
    
  2. If you are sure that the expression is traversable, you might want to add a doc comment cast to improve IDE auto-completion and static analysis:

    /** @var array $collection */
    $collection = json_decode($data, true);
    
    foreach ($collection as $item) { /** .. */ }
    
  3. Mark the issue as a false-positive: Just hover the remove button, in the top-right corner of this issue for more options.

Loading history...
7492
                    $userList[] = $user['user_id'];
7493
                }
7494
                if (in_array($loginAsUserId, $userList)) {
7495
                    return true;
7496
                }
7497
            } else {
7498
                if (api_is_drh() && UserManager::is_user_followed_by_drh($loginAsUserId, api_get_user_id())) {
7499
                    return true;
7500
                }
7501
            }
7502
        }
7503
        return false;
7504
    };
7505
7506
    return api_is_platform_admin() || (api_is_session_admin() && $userInfo['status'] == 5) || $isDrh();
7507
}
7508
7509
/**
7510
 * @return bool
7511
 */
7512
function api_is_allowed_in_course()
7513
{
7514
    return Session::read('is_allowed_in_course');
7515
}
7516
7517
/**
7518
 * Show a string in
7519
 * @param string $string Some string to dump, removing tabs, spaces,
7520
 * newlines, etc (usually most useful for SQL queries)
7521
 * @param int $dump Set to 1 to use print_r()
7522
 */
7523
function api_error_log($string, $dump = 0)
7524
{
7525
    // Clean query
7526
    $bt = debug_backtrace();
7527
    $caller = array_shift($bt);;
7528
    if ($dump == 1) {
7529
        $string = print_r($string, 1);
7530
    } else {
7531
        $string = str_replace(array("\r", "\n", "\t", "\10"), '', $string);
7532
        $string = str_replace('    ',' ', $string);
7533
    }
7534
7535
    error_log("-------------------------------------");
7536
    error_log($string);
7537
    error_log("File: ".$caller['file']." +".$caller['line']);
7538
    error_log("-------------------------------------");
7539
}
7540
7541
/**
7542
 * Set the cookie to go directly to the course code $in_firstpage
7543
 * after login
7544
 * @param string $in_firstpage is the course code of the course to go
7545
 */
7546
function api_set_firstpage_parameter($in_firstpage)
7547
{
7548
    setcookie("GotoCourse", $in_firstpage);
7549
}
7550
7551
/**
7552
 * Delete the cookie to go directly to the course code $in_firstpage
7553
 * after login
7554
 */
7555
function api_delete_firstpage_parameter()
7556
{
7557
    setcookie("GotoCourse", "", time() - 3600);
7558
}
7559
7560
/**
7561
 * @return boolean if course_code for direct course access after login is set
7562
 */
7563
function exist_firstpage_parameter()
7564
{
7565
    return (isset($_COOKIE['GotoCourse']) && $_COOKIE['GotoCourse'] != "");
7566
}
7567
7568
/**
7569
 * @return return the course_code of the course where user login
7570
 */
7571
function api_get_firstpage_parameter()
7572
{
7573
    return $_COOKIE['GotoCourse'];
7574
}
7575
7576
/**
7577
 * Return true on https install
7578
 * @return boolean
7579
 */
7580
function api_is_https()
7581
{
7582
    return (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] != 'off');
7583
}
7584
7585
/**
7586
 * Return protocol (http or https)
7587
 * @return string
7588
 */
7589
function api_get_protocol()
7590
{
7591
    return api_is_https() ? 'https' : 'http';
7592
}
7593
7594
/**
7595
 * Return a string where " are replaced with 2 '
7596
 * It is useful when you pass a PHP variable in a Javascript browser dialog
7597
 * e.g. : alert("<?php get_lang('Message') ?>");
7598
 * and message contains character "
7599
 *
7600
 * @param string $in_text
7601
 * @return string
7602
 */
7603
function convert_double_quote_to_single($in_text) {
7604
    return api_preg_replace('/"/', "''", $in_text);
7605
}
7606
7607
/**
7608
 * Get origin
7609
 *
7610
 * @param string
7611
 * @return string
7612
 **/
7613
function api_get_origin()
7614
{
7615
    if (isset($_REQUEST['origin'])) {
7616
        return $_REQUEST['origin'] == 'learnpath' ? 'learnpath' : null;
7617
    }
7618
7619
    return null;
7620
}
7621
7622
/**
7623
 * Warns an user that the portal reach certain limit.
7624
 * @param string $limitName
7625
 */
7626
function api_warn_hosting_contact($limitName)
7627
{
7628
    $hostingParams = api_get_configuration_value(1);
7629
    $email = null;
7630
7631
    if (!empty($hostingParams)) {
7632
        if (isset($hostingParams['hosting_contact_mail'])) {
7633
            $email = $hostingParams['hosting_contact_mail'];
7634
        }
7635
    }
7636
7637
    if (!empty($email)) {
7638
        $subject = get_lang('HostingWarningReached');
7639
        $body = get_lang('PortalName').': '.api_get_path(WEB_PATH)." \n ";
7640
        $body .= get_lang('PortalLimitType').': '.$limitName." \n ";
7641
        if (isset($hostingParams[$limitName])) {
7642
            $body .= get_lang('Value') . ': ' . $hostingParams[$limitName];
7643
        }
7644
        api_mail_html(null, $email, $subject, $body);
7645
    }
7646
}
7647
7648
/**
7649
 * @param string $variable
7650
 * @return bool|mixed
7651
 */
7652
function api_get_configuration_value($variable)
7653
{
7654
    global $_configuration;
7655
    if (isset($_configuration[$variable])) {
7656
        return $_configuration[$variable];
7657
    }
7658
    return false;
7659
}
7660
7661
/**
7662
 * Returns supported image extensions in the portal
7663
 * @return  array   Supported image extensions in the portal
7664
 */
7665
function api_get_supported_image_extensions()
7666
{
7667
    // jpg can also be called jpeg, jpe, jfif and jif. See https://en.wikipedia.org/wiki/JPEG#JPEG_filename_extensions
7668
    $supportedImageExtensions = array('jpg', 'jpeg', 'png', 'gif', 'svg', 'jpe', 'jfif', 'jif');
7669
    if (version_compare(PHP_VERSION, '5.5.0', '>=')) {
7670
        array_push($supportedImageExtensions, 'webp');
7671
    }
7672
    return $supportedImageExtensions;
7673
}
7674
7675
/**
7676
 * This setting changes the registration status for the campus
7677
 *
7678
 * @author Patrick Cool <[email protected]>, Ghent University
7679
 * @version August 2006
7680
 * @param   bool    $listCampus Whether we authorize
7681
 * @todo the $_settings should be reloaded here. => write api function for this and use this in global.inc.php also.
7682
 */
7683 View Code Duplication
function api_register_campus($listCampus = true) {
7684
    $tbl_settings = Database :: get_main_table(TABLE_MAIN_SETTINGS_CURRENT);
7685
7686
    $sql = "UPDATE $tbl_settings SET selected_value='true' WHERE variable='registered'";
7687
    Database::query($sql);
7688
7689
    if (!$listCampus) {
7690
        $sql = "UPDATE $tbl_settings SET selected_value='true' WHERE variable='donotlistcampus'";
7691
        Database::query($sql);
7692
    }
7693
}
7694
7695
/**
7696
 * Checks whether current user is a student boss
7697
 * @global array $_user
7698
 * @return boolean
7699
 */
7700
function api_is_student_boss()
7701
{
7702
    $_user = api_get_user_info();
7703
7704
    return isset($_user['status']) && $_user['status'] == STUDENT_BOSS;
7705
}
7706
7707
/**
7708
 * Check whether the user type should be exclude.
7709
 * Such as invited or anonymous users
7710
 * @param boolean $checkDB Optional. Whether check the user status
7711
 * @param int $userId Options. The user id
7712
 *
7713
 * @return boolean
7714
 */
7715
function api_is_excluded_user_type($checkDB = false, $userId = 0)
7716
{
7717
    if ($checkDB) {
7718
        $userId = empty($userId) ? api_get_user_id() : intval($userId);
7719
7720
        if ($userId == 0) {
7721
            return true;
7722
        }
7723
7724
        $userInfo = api_get_user_info($userId);
7725
7726
        switch ($userInfo['status']) {
7727
            case INVITEE:
7728
                //no break;
7729
            case ANONYMOUS:
7730
                return true;
7731
            default:
7732
                return false;
7733
        }
7734
    }
7735
7736
    $isInvited = api_is_invitee();
7737
    $isAnonymous = api_is_anonymous();
7738
7739
    if ($isInvited || $isAnonymous) {
7740
        return true;
7741
    }
7742
7743
    return false;
7744
}
7745
7746
/**
7747
 * Get the user status to ignore in reports
7748
 * @param string $format Optional. The result type (array or string)
7749
 * @return array|string
7750
 */
7751
function api_get_users_status_ignored_in_reports($format = 'array')
7752
{
7753
    $excludedTypes = array(
7754
        INVITEE,
7755
        ANONYMOUS
7756
    );
7757
7758
    if ($format == 'string') {
7759
        return implode(', ', $excludedTypes);
7760
    }
7761
7762
    return $excludedTypes;
7763
}
7764
7765
/**
7766
 * Set the Site Use Cookie Warning for 1 year
7767
 */
7768
function api_set_site_use_cookie_warning_cookie()
7769
{
7770
    setcookie("ChamiloUsesCookies", "ok", time()+31556926);
7771
}
7772
7773
/**
7774
 * Return true if the Site Use Cookie Warning Cookie warning exists
7775
 * @return bool
7776
 */
7777
function api_site_use_cookie_warning_cookie_exist()
7778
{
7779
    return isset($_COOKIE['ChamiloUsesCookies']);
7780
}
7781
7782
/**
7783
 * Given a number of seconds, format the time to show hours, minutes and seconds
7784
 * @param int $time The time in seconds
7785
 * @param string $originFormat Optional. PHP o JS
7786
 * @return string (00h00'00")
7787
 */
7788
function api_format_time($time, $originFormat = 'php')
7789
{
7790
    $h = get_lang('h');
7791
    $hours = $time / 3600;
7792
    $mins = ($time % 3600) / 60;
7793
    $secs = ($time % 60);
7794
7795
    if ($originFormat == 'js') {
7796
        $formattedTime = trim(sprintf("%02d : %02d : %02d", $hours, $mins, $secs));
7797
    } else {
7798
        $formattedTime = trim(sprintf("%02d$h%02d'%02d\"", $hours, $mins, $secs));
7799
    }
7800
7801
    return $formattedTime;
7802
}
7803
7804
/**
7805
 * Create a new empty directory with index.html file
7806
 * @param string $name The new directory name
7807
 * @param string $parentDirectory Directory parent directory name
7808
 * @return boolean Return true if the directory was create. Otherwise return false
7809
 */
7810
function api_create_protected_dir($name, $parentDirectory)
7811
{
7812
    $isCreated = false;
7813
7814
    if (!is_writable($parentDirectory)) {
7815
        return false;
7816
    }
7817
7818
    $fullPath = $parentDirectory . api_replace_dangerous_char($name);
7819
7820
    if (mkdir($fullPath, api_get_permissions_for_new_directories(), true)) {
7821
        $fp = fopen($fullPath . '/index.html', 'w');
7822
7823
        if ($fp) {
7824
            if (fwrite($fp, '<html><head></head><body></body></html>')) {
7825
                $isCreated = true;
7826
            }
7827
        }
7828
7829
        fclose($fp);
7830
    }
7831
7832
    return $isCreated;
7833
}
7834
7835
/**
7836
 * Sends an HTML email using the phpmailer class (and multipart/alternative to downgrade gracefully)
7837
 * Sender name and email can be specified, if not specified
7838
 * name and email of the platform admin are used
7839
 *
7840
 * @author Bert Vanderkimpen ICT&O UGent
7841
 * @author Yannick Warnier <[email protected]>
7842
 *
7843
 * @param string    name of recipient
7844
 * @param string    email of recipient
7845
 * @param string    email subject
7846
 * @param string    email body
7847
 * @param string    sender name
7848
 * @param string    sender e-mail
7849
 * @param array     extra headers in form $headers = array($name => $value) to allow parsing
7850
 * @param array     data file (path and filename)
7851
 * @param bool      True for attaching a embedded file inside content html (optional)
7852
 * @param array     Additional parameters
7853
 * @return          integer true if mail was sent
7854
 * @see             class.phpmailer.php
7855
 */
7856
function api_mail_html(
7857
    $recipient_name,
7858
    $recipient_email,
7859
    $subject,
7860
    $message,
7861
    $senderName = '',
7862
    $senderEmail = '',
7863
    $extra_headers = array(),
7864
    $data_file = array(),
7865
    $embedded_image = false,
7866
    $additionalParameters = array()
7867
) {
7868
    global $platform_email;
7869
7870
    $mail = new PHPMailer();
7871
    $mail->Mailer = $platform_email['SMTP_MAILER'];
7872
    $mail->Host = $platform_email['SMTP_HOST'];
7873
    $mail->Port = $platform_email['SMTP_PORT'];
7874
    $mail->CharSet = $platform_email['SMTP_CHARSET'];
7875
    // Stay far below SMTP protocol 980 chars limit.
7876
    $mail->WordWrap = 200;
7877
7878
    if ($platform_email['SMTP_AUTH']) {
7879
        $mail->SMTPAuth = 1;
0 ignored issues
show
Documentation Bug introduced by
The property $SMTPAuth was declared of type boolean, but 1 is of type integer. Maybe add a type cast?

This check looks for assignments to scalar types that may be of the wrong type.

To ensure the code behaves as expected, it may be a good idea to add an explicit type cast.

$answer = 42;

$correct = false;

$correct = (bool) $answer;
Loading history...
7880
        $mail->Username = $platform_email['SMTP_USER'];
7881
        $mail->Password = $platform_email['SMTP_PASS'];
7882
        if (isset($platform_email['SMTP_SECURE'])) {
7883
            $mail->SMTPSecure = $platform_email['SMTP_SECURE'];
7884
        }
7885
    }
7886
    $mail->SMTPDebug = isset($platform_email['SMTP_DEBUG'])?$platform_email['SMTP_DEBUG']:0;
7887
7888
    // 5 = low, 1 = high
7889
    $mail->Priority = 3;
7890
    $mail->SMTPKeepAlive = true;
7891
7892
    // Default values
7893
    $notification = new Notification();
7894
    $defaultEmail = $notification->getDefaultPlatformSenderEmail();
7895
    $defaultName = $notification->getDefaultPlatformSenderName();
7896
7897
    // Error to admin.
7898
    $mail->AddCustomHeader('Errors-To: '.$defaultEmail);
7899
7900
    // If the parameter is set don't use the admin.
7901
    $senderName = !empty($senderName) ? $senderName : $defaultName;
7902
    $senderEmail = !empty($senderEmail) ? $senderEmail : $defaultEmail;
7903
7904
    // Reply to first
7905
    if (isset($extra_headers['reply_to'])) {
7906
        $mail->AddReplyTo(
7907
            $extra_headers['reply_to']['mail'],
7908
            $extra_headers['reply_to']['name']
7909
        );
7910
        $mail->Sender = $extra_headers['reply_to']['mail'];
7911
        unset($extra_headers['reply_to']);
7912
    }
7913
    //If the SMTP configuration only accept one sender
7914
    if ($platform_email['SMTP_UNIQUE_SENDER']) {
7915
        $senderName = $platform_email['SMTP_FROM_NAME'];
7916
        $senderEmail = $platform_email['SMTP_FROM_EMAIL'];
7917
    }
7918
    $mail->SetFrom($senderEmail, $senderName);
7919
7920
    $mail->Subject = $subject;
7921
    $mail->AltBody = strip_tags(
7922
        str_replace('<br />', "\n", api_html_entity_decode($message))
7923
    );
7924
7925
    // Send embedded image.
7926
    if ($embedded_image) {
7927
        // Get all images html inside content.
7928
        preg_match_all("/<img\s+.*?src=[\"\']?([^\"\' >]*)[\"\']?[^>]*>/i", $message, $m);
7929
        // Prepare new tag images.
7930
        $new_images_html = array();
7931
        $i = 1;
7932
        if (!empty($m[1])) {
7933
            foreach ($m[1] as $image_path) {
7934
                $real_path = realpath($image_path);
7935
                $filename  = basename($image_path);
7936
                $image_cid = $filename.'_'.$i;
7937
                $encoding = 'base64';
7938
                $image_type = mime_content_type($real_path);
7939
                $mail->AddEmbeddedImage(
7940
                    $real_path,
7941
                    $image_cid,
7942
                    $filename,
7943
                    $encoding,
7944
                    $image_type
0 ignored issues
show
Bug introduced by
It seems like $image_type defined by mime_content_type($real_path) on line 7938 can also be of type array<string,string,{"ai...tring","zip":"string"}>; however, PHPMailer::AddEmbeddedImage() does only seem to accept string, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
7945
                );
7946
                $new_images_html[] = '<img src="cid:'.$image_cid.'" />';
7947
                $i++;
7948
            }
7949
        }
7950
7951
        // Replace origin image for new embedded image html.
7952
        $x = 0;
7953
        if (!empty($m[0])) {
7954
            foreach ($m[0] as $orig_img) {
7955
                $message = str_replace($orig_img, $new_images_html[$x], $message);
7956
                $x++;
7957
            }
7958
        }
7959
    }
7960
7961
    $mailView = new Template(null, false, false, false, false, false, false);
7962
    $mailView->assign('content', $message);
7963
7964
    if (isset($additionalParameters['link'])) {
7965
        $mailView->assign('link', $additionalParameters['link']);
7966
    }
7967
7968
    $layout = $mailView->get_template('mail/mail.tpl');
7969
    $mail->Body = $mailView->fetch($layout);
7970
7971
    // Attachment ...
7972
    if (!empty($data_file)) {
7973
        $o = 0;
7974 View Code Duplication
        foreach ($data_file as $file_attach) {
7975
            if (!empty($file_attach['path']) && !empty($file_attach['filename'])) {
7976
                $mail->AddAttachment($file_attach['path'], $file_attach['filename']);
7977
            }
7978
            $o++;
7979
        }
7980
    } elseif (is_array($_FILES)) {
7981
        $data_file = $_FILES;
7982
        $o = 0;
7983 View Code Duplication
        foreach ($data_file as $file_attach) {
7984
            if (!empty($file_attach['tmp_name']) && !empty($file_attach['name'])) {
7985
                $mail->AddAttachment($file_attach['tmp_name'], $file_attach['name']);
7986
            }
7987
            $o++;
7988
        }
7989
    }
7990
7991
    // Only valid addresses are accepted.
7992
    if (is_array($recipient_email)) {
7993
        foreach ($recipient_email as $dest) {
7994
            if (api_valid_email($dest)) {
7995
                $mail->AddAddress($dest, $recipient_name);
7996
            }
7997
        }
7998
    } else {
7999
        if (api_valid_email($recipient_email)) {
8000
            $mail->AddAddress($recipient_email, $recipient_name);
8001
        } else {
8002
            return 0;
8003
        }
8004
    }
8005
8006
    if (is_array($extra_headers) && count($extra_headers) > 0) {
8007
        foreach ($extra_headers as $key => $value) {
8008
            switch (strtolower($key)) {
8009
                case 'encoding':
8010
                case 'content-transfer-encoding':
8011
                    $mail->Encoding = $value;
8012
                    break;
8013
                case 'charset':
8014
                    $mail->Charset = $value;
8015
                    break;
8016
                case 'contenttype':
8017
                case 'content-type':
8018
                    $mail->ContentType = $value;
8019
                    break;
8020
                default:
8021
                    $mail->AddCustomHeader($key.':'.$value);
8022
                    break;
8023
            }
8024
        }
8025
    } else {
8026
        if (!empty($extra_headers)) {
8027
            $mail->AddCustomHeader($extra_headers);
8028
        }
8029
    }
8030
8031
    // WordWrap the html body (phpMailer only fixes AltBody) FS#2988
8032
    $mail->Body = $mail->WrapText($mail->Body, $mail->WordWrap);
8033
    // Send the mail message.
8034
    if (!$mail->Send()) {
8035
        error_log('ERROR: mail not sent to '.$recipient_name.' ('.$recipient_email.') because of '.$mail->ErrorInfo.'<br />');
8036
        if ($mail->SMTPDebug) {
8037
            error_log(
8038
                "Connection details :: " .
8039
                "Protocol: " . $mail->Mailer . ' :: ' .
8040
                "Host/Port: " . $mail->Host . ':' . $mail->Port . ' :: ' .
8041
                "Authent/Open: " . ($mail->SMTPAuth?'Authent':'Open') . ' :: ' .
8042
                ($mail->SMTPAuth?"  User/Pass: " . $mail->Username . ':' . $mail->Password:'')
8043
            );
8044
        }
8045
        return 0;
8046
    }
8047
8048
    if (!empty($additionalParameters)) {
8049
        $plugin = new AppPlugin();
8050
        $smsPlugin = $plugin->getSMSPluginLibrary();
8051
        if ($smsPlugin) {
8052
            $smsPlugin->send($additionalParameters);
8053
        }
8054
    }
8055
8056
    // Clear all the addresses.
8057
    $mail->ClearAddresses();
8058
    return 1;
8059
}
8060
8061
/**
8062
 * @param string $tool Possible values:
8063
 * GroupManager::GROUP_TOOL_*
8064
 *
8065
 */
8066
function api_protect_course_group($tool, $showHeader = true)
8067
{
8068
    $userId = api_get_user_id();
8069
    $groupId = api_get_group_id();
8070
8071
    if (!empty($groupId)) {
8072
        $allow = GroupManager::user_has_access(
8073
            $userId,
8074
            $groupId,
8075
            $tool
8076
        );
8077
8078
        if (!$allow) {
8079
            api_not_allowed($showHeader);
8080
        }
8081
    }
8082
}
8083
8084
/**
8085
 * Eliminate the duplicates of a multidimensional array by sending the key
8086
 * @param array $array multidimensional array
8087
 * @param int $key key to find to compare
8088
 *
8089
 */
8090
function api_unique_multidim_array($array, $key){
8091
    $temp_array = array();
8092
    $i = 0;
8093
    $key_array = array();
8094
8095
    foreach($array as $val){
8096
        if(!in_array($val[$key],$key_array)){
8097
            $key_array[$i] = $val[$key];
8098
            $temp_array[$i] = $val;
8099
        }
8100
        $i++;
8101
    }
8102
    return $temp_array;
8103
}
8104
8105
/**
8106
 * Limit the access to Session Admins wheen the limit_session_admin_role
8107
 * configuration variable is set to true
8108
 */
8109
function api_protect_limit_for_session_admin()
8110
{
8111
    $limitAdmin = api_get_setting('limit_session_admin_role');
8112
    if (api_is_session_admin() && $limitAdmin === 'true') {
8113
        api_not_allowed(true);
8114
    }
8115
}
8116
8117
function api_is_student_view_active() {
8118
    return (isset($_SESSION['studentview']) && $_SESSION['studentview'] == "studentview");
8119
}
8120