Completed
Push — 1.10.x ( 22fbaf...dc201d )
by
unknown
105:12 queued 60:06
created

api.lib.php ➔ api_is_in_group()   C

Complexity

Conditions 7
Paths 8

Size

Total Lines 25
Code Lines 15

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 7
eloc 15
c 1
b 0
f 0
nc 8
nop 2
dl 0
loc 25
rs 6.7272
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 $type              The requested path type (a defined constant), see the examples.
0 ignored issues
show
Bug introduced by
There is no parameter named $type. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

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

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

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

Loading history...
596
 * @param string $path (optional)   A path which type is to be converted. Also, it may be a defined constant for a path.
597
 * This parameter has meaning when $type parameter has one of the following values: TO_WEB, TO_SYS, TO_REL. Otherwise it is ignored.
598
 * @return string                   The requested path or the converted path.
599
 *
600
 * A terminology note:
601
 * The defined constants used by this function contain the abbreviations WEB, REL, SYS with the following meaning for types:
602
 * WEB - an absolute URL (we often call it web-path),
603
 * example: http://www.mychamilo.org/chamilo/courses/COURSE01/document/lesson01.html;
604
 *
605
 * REL - represents a semi-absolute URL - a web-path, which is relative to the root web-path of the server, without server's base,
606
 * example: /chamilo/courses/COURSE01/document/lesson01.html;
607
 *
608
 * SYS - represents an absolute path inside the scope of server's file system,
609
 * /var/www/chamilo/courses/COURSE01/document/lesson01.html or
610
 * C:/Inetpub/wwwroot/chamilo/courses/COURSE01/document/lesson01.html.
611
 *
612
 * In some abstract sense we can consider these three path types as absolute.
613
 *
614
 * Notes about the current behaviour model:
615
 * 1. Windows back-slashes are converted to slashes in the result.
616
 * 2. A semi-absolute web-path is detected by its leading slash. On Linux systems, absolute system paths start with
617
 * a slash too, so an additional check about presence of leading system server base is implemented. For example, the function is
618
 * able to distinguish type difference between /var/www/chamilo/courses/ (SYS) and /chamilo/courses/ (REL).
619
 * 3. The function api_get_path() returns only these three types of paths, which in some sense are absolute. The function has
620
 * no a mechanism for processing relative web/system paths, such as: lesson01.html, ./lesson01.html, ../css/my_styles.css.
621
 * It has not been identified as needed yet.
622
 * 4. Also, resolving the meta-symbols "." and ".." within paths has not been implemented, it is to be identified as needed.
623
 *
624
 * Example:
625
 * Assume that your server root is /var/www/ ,
626
 * Chamilo is installed in a sub folder chamilo/ and the URL of your campus is http://www.mychamilo.org
627
 * The other configuration parameters have not been changed.
628
 *
629
 * This is how we can get most used paths, for common purpose:
630
631
 * api_get_path(REL_PATH)                       /chamilo/
632
 * api_get_path(REL_COURSE_PATH)                /chamilo/courses/
633
 * api_get_path(REL_CODE_PATH)                  /chamilo/main/
634
 * api_get_path(REL_UPLOAD_PATH)                /chamilo/app/upload/
635
 * 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'].
636
 * api_get_path(SYS_PATH)                       /var/www/chamilo/
637
 * api_get_path(SYS_APP_PATH)                   /var/www/chamilo/app/
638
 * api_get_path(SYS_UPLOAD_PATH)                /var/www/chamilo/app/upload/
639
 * api_get_path(SYS_ARCHIVE_PATH)               /var/www/chamilo/app/cache
640
 * api_get_path(SYS_COURSE_PATH)                /var/www/chamilo/app/courses/
641
 * api_get_path(SYS_CSS_PATH)                   /var/www/chamilo/app/Resources/public/css
642
 * api_get_path(SYS_CODE_PATH)                  /var/www/chamilo/main/
643
 * api_get_path(INCLUDE_PATH)                   /var/www/chamilo/main/inc/
644
 * api_get_path(LIBRARY_PATH)                   /var/www/chamilo/main/inc/lib/
645
 * api_get_path(CONFIGURATION_PATH)             /var/www/chamilo/main/inc/conf/
646
 * api_get_path(SYS_LANG_PATH)                  /var/www/chamilo/main/lang/
647
 * api_get_path(SYS_PLUGIN_PATH)                /var/www/chamilo/plugin/
648
 * api_get_path(SYS_TEST_PATH)                  /var/www/chamilo/tests/
649
 * api_get_path(SYS_TEMPLATE_PATH)              /var/www/chamilo/main/template/
650
 * api_get_path(SYS_PUBLIC_PATH)                /var/www/chamilo/web/
651
 *
652
 * api_get_path(WEB_SERVER_ROOT_PATH)           http://www.mychamilo.org/
653
 * api_get_path(WEB_PATH)                       http://www.mychamilo.org/chamilo/
654
 * api_get_path(WEB_COURSE_PATH)                http://www.mychamilo.org/chamilo/courses/
655
 * api_get_path(WEB_CODE_PATH)                  http://www.mychamilo.org/chamilo/main/
656
 * api_get_path(WEB_PLUGIN_PATH)                http://www.mychamilo.org/chamilo/plugin/
657
 * api_get_path(WEB_ARCHIVE_PATH)               http://www.mychamilo.org/chamilo/app/cache/
658
 * api_get_path(WEB_IMG_PATH)                   http://www.mychamilo.org/chamilo/main/img/
659
 * api_get_path(WEB_CSS_PATH)                   http://www.mychamilo.org/chamilo/web/css/
660
 * api_get_path(WEB_LIBRARY_PATH)               http://www.mychamilo.org/chamilo/main/inc/lib/
661
 * api_get_path(WEB_LIBRARY_JS_PATH)            http://www.mychamilo.org/chamilo/web/Chamilo/javascript
662
 * api_get_path(WEB_TEMPLATE_PATH)              http://www.mychamilo.org/chamilo/main/template/
663
 * api_get_path(WEB_UPLOAD_PATH)                http://www.mychamilo.org/chamilo/app/upload/
664
 * api_get_path(WEB_PUBLIC_PATH)                http://www.mychamilo.org/chamilo/web/
665
 *
666
 * This is how we retrieve paths of "registered" resource files (scripts, players, etc.):
667
 * api_get_path(TO_WEB, FLASH_PLAYER_AUDIO)     http://www.mychamilo.org/chamilo/main/inc/lib/mediaplayer/player.swf
668
 * api_get_path(TO_WEB, FLASH_PLAYER_VIDEO)     http://www.mychamilo.org/chamilo/main/inc/lib/mediaplayer/player.swf
669
 * api_get_path(TO_SYS, SCRIPT_SWFOBJECT)       /var/www/chamilo/main/inc/lib/swfobject/swfobject.js
670
 * api_get_path(TO_REL, SCRIPT_ASCIIMATHML)     /chamilo/main/inc/lib/asciimath/ASCIIMathML.js
671
 * ...
672
 *
673
 * We can convert arbitrary paths, that are not registered (no defined constant).
674
 * For guaranteed result, these paths should point inside the system Chamilo.
675
 * Some random examples:
676
 * api_get_path(TO_WEB, $_SERVER['REQUEST_URI'])
677
 * api_get_path(TO_SYS, $_SERVER['PHP_SELF'])
678
 * api_get_path(TO_REL, __FILE__)
679
 * ...
680
 */
681
function api_get_path($path_type, $path = null)
682
{
683
    static $paths = array(
684
        WEB_PATH                => '',
685
        SYS_PATH                => '',
686
        REL_PATH                => '',
687
        WEB_SERVER_ROOT_PATH    => '',
688
        SYS_SERVER_ROOT_PATH    => '',
689
        WEB_COURSE_PATH         => '',
690
        SYS_COURSE_PATH         => '',
691
        REL_COURSE_PATH         => '',
692
        REL_CODE_PATH           => '',
693
        WEB_CODE_PATH           => '',
694
        SYS_CODE_PATH           => '',
695
        SYS_LANG_PATH           => 'lang/',
696
        WEB_IMG_PATH            => 'img/',
697
        WEB_CSS_PATH            => 'web/css/',
698
        SYS_CSS_PATH            => 'app/Resources/public/css/',
699
        SYS_PLUGIN_PATH         => 'plugin/',
700
        WEB_PLUGIN_PATH         => 'plugin/',
701
        SYS_ARCHIVE_PATH        => 'app/cache/',
702
        WEB_ARCHIVE_PATH        => 'app/cache/',
703
        SYS_APP_PATH            => 'app/',
704
        WEB_APP_PATH            => 'app/',
705
        SYS_UPLOAD_PATH         => 'app/upload/',
706
        REL_UPLOAD_PATH         => 'app/upload/',
707
        INCLUDE_PATH            => 'inc/',
708
        LIBRARY_PATH            => 'inc/lib/',
709
        CONFIGURATION_PATH      => 'app/config/',
710
        WEB_LIBRARY_PATH        => 'inc/lib/',
711
        WEB_LIBRARY_JS_PATH     => 'inc/lib/javascript/',
712
        WEB_AJAX_PATH           => 'inc/ajax/',
713
        SYS_TEST_PATH           => 'tests/',
714
        WEB_TEMPLATE_PATH       => 'template/',
715
        WEB_UPLOAD_PATH         => 'app/upload/',
716
        WEB_PUBLIC_PATH         => 'web/',
717
        SYS_TEMPLATE_PATH       => 'template/',
718
        SYS_PUBLIC_PATH         => 'web/',
719
        WEB_FONTS_PATH          => 'fonts/',
720
        SYS_FONTS_PATH          => 'fonts/',
721
    );
722
723
    static $resource_paths = array(
724
        FLASH_PLAYER_AUDIO      => 'inc/lib/mediaplayer/player.swf',
725
        FLASH_PLAYER_VIDEO      => 'inc/lib/mediaplayer/player.swf',
726
        SCRIPT_SWFOBJECT        => 'inc/lib/swfobject/swfobject.js',
727
        SCRIPT_ASCIIMATHML      => 'inc/lib/javascript/asciimath/ASCIIMathML.js',
728
        DRAWING_ASCIISVG        => 'inc/lib/javascript/asciimath/d.svg'
729
    );
730
731
    static $is_this_function_initialized;
732
    static $server_base_web; // No trailing slash.
733
    static $server_base_sys; // No trailing slash.
734
    static $root_web;
735
    static $root_sys;
736
    static $root_rel;
737
738
    // Always load root_web modifications for multiple url features
739
    global $_configuration;
740
    //default $_configuration['root_web'] configuration
741
    $root_web = $_configuration['root_web'];
742
743
    $code_folder = 'main/';
744
    $course_folder = 'courses/';
745
746
    // Configuration data for already installed system.
747
    $root_sys = $_configuration['root_sys'];
748
    $load_new_config = false;
749
750
    // To avoid that the api_get_access_url() function fails since global.inc.php also calls the main_api.lib.php
751
    if ($path_type == WEB_PATH) {
752
        if (isset($_configuration['access_url']) &&  $_configuration['access_url'] != 1) {
753
            //we look into the DB the function api_get_access_url
754
            $url_info = api_get_access_url($_configuration['access_url']);
755
            $root_web = $url_info['active'] == 1 ? $url_info['url'] : $_configuration['root_web'];
756
            $load_new_config = true;
757
        }
758
    }
759
760
    if (!$is_this_function_initialized) {
761
        global $_configuration;
762
763
        $root_rel = $_configuration['url_append'];
764
765
        // Support for the installation process.
766
        // Developers might use the function api_get_path() directly or indirectly (this is difficult to be traced), at the moment when
767
        // configuration has not been created yet. This is why this function should be upgraded to return correct results in this case.
768
769
        if (defined('SYSTEM_INSTALLATION') && SYSTEM_INSTALLATION) {
770
            if (($pos = strpos(($requested_page_rel = api_get_self()), 'main/install')) !== false) {
771
                $root_rel = substr($requested_page_rel, 0, $pos);
772
                // See http://www.mediawiki.org/wiki/Manual:$wgServer
773
                $server_protocol = (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] == 'on') ? 'https' : 'http';
774
                $server_name =
775
                    isset($_SERVER['SERVER_NAME']) ? $_SERVER['SERVER_NAME']
776
                    : (isset($_SERVER['HOSTNAME']) ? $_SERVER['HOSTNAME']
777
                    : (isset($_SERVER['HTTP_HOST']) ? $_SERVER['HTTP_HOST']
778
                    : (isset($_SERVER['SERVER_ADDR']) ? $_SERVER['SERVER_ADDR']
779
                    : 'localhost')));
780
                if (isset($_SERVER['SERVER_PORT']) && !strpos($server_name, ':')
781
                    && (($server_protocol == 'http'
782
                    && $_SERVER['SERVER_PORT'] != 80 ) || ($server_protocol == 'https' && $_SERVER['SERVER_PORT'] != 443 ))) {
783
                    $server_name .= ":" . $_SERVER['SERVER_PORT'];
784
                }
785
                $root_web = $server_protocol.'://'.$server_name.$root_rel;
786
                $root_sys = str_replace('\\', '/', realpath(__DIR__.'/../../../')).'/';
787
                $code_folder = 'main/';
788
            }
789
            // Here we give up, so we don't touch anything.
790
        }
791
792
        // Dealing with trailing slashes.
793
        $root_web       = api_add_trailing_slash($root_web);
794
        $root_sys       = api_add_trailing_slash($root_sys);
795
        $root_rel       = api_add_trailing_slash($root_rel);
796
        $code_folder    = api_add_trailing_slash($code_folder);
797
        $course_folder  = api_add_trailing_slash($course_folder);
798
799
        // Web server base and system server base.
800
        $server_base_web = preg_replace('@'.$root_rel.'$@', '', $root_web); // No trailing slash.
801
        $server_base_sys = preg_replace('@'.$root_rel.'$@', '', $root_sys); // No trailing slash.
802
803
        // Initialization of a table that contains common-purpose paths.
804
        $paths[WEB_PATH]                = $root_web;
805
        $paths[SYS_PATH]                = $root_sys;
806
        $paths[REL_PATH]                = $root_rel;
807
        $paths[WEB_SERVER_ROOT_PATH]    = $server_base_web.'/';
808
        $paths[SYS_SERVER_ROOT_PATH]    = $server_base_sys.'/';
809
810
        $paths[WEB_COURSE_PATH]         = $root_web.$course_folder;
811
812
        $paths[REL_COURSE_PATH]         = $root_rel.$course_folder;
813
        $paths[REL_CODE_PATH]           = $root_rel.$code_folder;
814
        $paths[WEB_CODE_PATH]           = $root_web.$code_folder;
815
        $paths[SYS_CODE_PATH]           = $root_sys.$code_folder;
816
        $paths[REL_UPLOAD_PATH]         = $root_rel.$paths[SYS_UPLOAD_PATH];
817
818
        $paths[WEB_DEFAULT_COURSE_DOCUMENT_PATH] = $paths[WEB_CODE_PATH].'default_course_document/';
819
        $paths[REL_DEFAULT_COURSE_DOCUMENT_PATH] = $paths[REL_PATH].'main/default_course_document/';
820
821
        // Now we can switch into api_get_path() "terminology".
822
        $paths[SYS_LANG_PATH]           = $paths[SYS_CODE_PATH].$paths[SYS_LANG_PATH];
823
824
        $paths[SYS_APP_PATH]            = $paths[SYS_PATH].$paths[SYS_APP_PATH];
825
        $paths[WEB_APP_PATH]            = $paths[WEB_PATH].$paths[WEB_APP_PATH];
826
        $paths[SYS_UPLOAD_PATH]         = $paths[SYS_PATH].$paths[SYS_UPLOAD_PATH];
827
828
        $paths[SYS_PLUGIN_PATH]         = $paths[SYS_PATH].$paths[SYS_PLUGIN_PATH];
829
        $paths[SYS_ARCHIVE_PATH]        = $paths[SYS_PATH].$paths[SYS_ARCHIVE_PATH];
830
        $paths[SYS_TEST_PATH]           = $paths[SYS_PATH].$paths[SYS_TEST_PATH];
831
        $paths[SYS_TEMPLATE_PATH]       = $paths[SYS_CODE_PATH].$paths[SYS_TEMPLATE_PATH];
832
        $paths[SYS_PUBLIC_PATH]         = $paths[SYS_PATH].$paths[SYS_PUBLIC_PATH];
833
        $paths[SYS_CSS_PATH]            = $paths[SYS_PATH].$paths[SYS_CSS_PATH];
834
        $paths[SYS_FONTS_PATH]          = $paths[SYS_CODE_PATH].$paths[SYS_FONTS_PATH];
835
836
        $paths[WEB_CSS_PATH]            = $paths[WEB_PATH].$paths[WEB_CSS_PATH];
837
        $paths[WEB_IMG_PATH]            = $paths[WEB_CODE_PATH].$paths[WEB_IMG_PATH];
838
        $paths[WEB_LIBRARY_PATH]        = $paths[WEB_CODE_PATH].$paths[WEB_LIBRARY_PATH];
839
        $paths[WEB_LIBRARY_JS_PATH]     = $paths[WEB_CODE_PATH].$paths[WEB_LIBRARY_JS_PATH];
840
841
        $paths[WEB_AJAX_PATH]           = $paths[WEB_CODE_PATH].$paths[WEB_AJAX_PATH];
842
        $paths[WEB_FONTS_PATH]          = $paths[WEB_CODE_PATH].$paths[WEB_FONTS_PATH];
843
844
        $paths[WEB_PLUGIN_PATH]         = $paths[WEB_PATH].$paths[WEB_PLUGIN_PATH];
845
        $paths[WEB_ARCHIVE_PATH]        = $paths[WEB_PATH].$paths[WEB_ARCHIVE_PATH];
846
847
        $paths[WEB_TEMPLATE_PATH]       = $paths[WEB_CODE_PATH].$paths[WEB_TEMPLATE_PATH];
848
        $paths[WEB_UPLOAD_PATH]         = $paths[WEB_PATH].$paths[WEB_UPLOAD_PATH];
849
        $paths[WEB_PUBLIC_PATH]         = $paths[WEB_PATH].$paths[WEB_PUBLIC_PATH];
850
851
        $paths[INCLUDE_PATH]            = $paths[SYS_CODE_PATH].$paths[INCLUDE_PATH];
852
        $paths[LIBRARY_PATH]            = $paths[SYS_CODE_PATH].$paths[LIBRARY_PATH];
853
        $paths[CONFIGURATION_PATH]      = $paths[SYS_PATH].$paths[CONFIGURATION_PATH];
854
        $paths[SYS_COURSE_PATH]         = $paths[SYS_APP_PATH].$course_folder;
855
856
        $is_this_function_initialized = true;
857
    } else {
858
        if ($load_new_config) {
859
            //  Redefining variables to work well with the "multiple url" feature
860
861
            // All web paths need to be here
862
            $web_paths = array(
863
                WEB_PATH                => '',
864
                WEB_SERVER_ROOT_PATH    => '',
865
                WEB_COURSE_PATH         => '',
866
                WEB_CODE_PATH           => '',
867
                WEB_IMG_PATH            => 'img/',
868
                WEB_CSS_PATH            => 'web/css/',
869
                WEB_PLUGIN_PATH         => 'plugin/',
870
                WEB_ARCHIVE_PATH        => 'archive/',
871
                WEB_LIBRARY_PATH        => 'inc/lib/',
872
                WEB_AJAX_PATH           => 'inc/ajax/'
873
            );
874
875
            $root_web = api_add_trailing_slash($root_web);
876
            // Web server base and system server base.
877
            $server_base_web = preg_replace('@'.$root_rel.'$@', '', $root_web); // No trailing slash.
878
879
            // Redefine root webs
880
            $paths[WEB_PATH]                = $root_web;
881
            $paths[WEB_SERVER_ROOT_PATH]    = $server_base_web.'/';
882
            $paths[WEB_COURSE_PATH]         = $root_web.$course_folder;
883
            $paths[WEB_CODE_PATH]           = $root_web.$code_folder;
884
            $paths[WEB_IMG_PATH]            = $paths[WEB_CODE_PATH].$web_paths[WEB_IMG_PATH];
885
886
            $paths[WEB_CSS_PATH]            = $paths[WEB_PATH].$web_paths[WEB_CSS_PATH];
887
            $paths[WEB_PLUGIN_PATH]         = $paths[WEB_PATH].$web_paths[WEB_PLUGIN_PATH];
888
            $paths[WEB_ARCHIVE_PATH]        = $paths[WEB_PATH].$web_paths[WEB_ARCHIVE_PATH];
889
            $paths[WEB_LIBRARY_PATH]        = $paths[WEB_CODE_PATH].$web_paths[WEB_LIBRARY_PATH];
890
            $paths[WEB_AJAX_PATH]           = $paths[WEB_CODE_PATH].$web_paths[WEB_AJAX_PATH];
891
            $paths[WEB_FONTS_PATH]          = $paths[WEB_CODE_PATH].$paths[WEB_FONTS_PATH];
892
        }
893
    }
894
895
    // Shallow purification and validation of input parameters.
896
897
    $path_type = trim($path_type);
898
    $path = trim($path);
899
900
    if (empty($path_type)) {
901
        return null;
902
    }
903
904
    // Retrieving a common-purpose path.
905
    if (isset($paths[$path_type])) {
906
        return $paths[$path_type];
907
    }
908
909
    // Retrieving a specific resource path.
910
911
    if (isset($resource_paths[$path])) {
912
        switch ($path_type) {
913
            case TO_WEB:
914
                return $paths[WEB_CODE_PATH].$resource_paths[$path];
915
            case TO_SYS:
916
                return $paths[SYS_CODE_PATH].$resource_paths[$path];
917
            case TO_REL:
918
                return $paths[REL_CODE_PATH].$resource_paths[$path];
919
            default:
920
                return null;
921
        }
922
    }
923
924
    // Common-purpose paths as a second parameter - recognition.
925
926
    if (isset($paths[$path])) {
927
        $path = $paths[$path];
928
    }
929
930
    // Second purification.
931
932
    // Replacing Windows back slashes.
933
    $path = str_replace('\\', '/', $path);
934
    // Query strings sometimes mighth wrongly appear in non-URLs.
935
    // Let us check remove them from all types of paths.
936
    if (($pos = strpos($path, '?')) !== false) {
937
        $path = substr($path, 0, $pos);
938
    }
939
940
    // Detection of the input path type. Conversion to semi-absolute type ( /chamilo/main/inc/.... ).
941
942
    if (preg_match(VALID_WEB_PATH, $path)) {
943
944
        // A special case: When a URL points to the document download script directly, without
945
        // mod-rewrite translation, we have to translate it into an "ordinary" web path.
946
        // For example:
947
        // http://localhost/chamilo/main/document/download.php?doc_url=/image.png&cDir=/
948
        // becomes
949
        // http://localhost/chamilo/courses/TEST/document/image.png
950
        // TEST is a course directory name, so called "system course code".
951
        if (strpos($path, 'download.php') !== false) { // Fast detection first.
952
            $path = urldecode($path);
953
            if (preg_match('/(.*)main\/document\/download.php\?doc_url=\/(.*)&cDir=\/(.*)?/', $path, $matches)) {
954
                $sys_course_code =
955
                    isset($_SESSION['_course']['sysCode'])  // User is inside a course?
956
                        ? $_SESSION['_course']['sysCode']   // Yes, then use course's directory name.
957
                        : '{SYS_COURSE_CODE}';              // No, then use a fake code, it may be processed later.
958
                $path = $matches[1].'courses/'.$sys_course_code.'/document/'.str_replace('//', '/', $matches[3].'/'.$matches[2]);
959
            }
960
        }
961
        // Replacement of the present web server base with a slash '/'.
962
        $path = preg_replace(VALID_WEB_SERVER_BASE, '/', $path);
963
964
    } elseif (strpos($path, $server_base_sys) === 0) {
965
        $path = preg_replace('@^'.$server_base_sys.'@', '', $path);
966
    } 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...
967
        // Leading slash - we assume that this path is semi-absolute (REL),
968
        // then path is left without furthes modifications.
969
    } else {
970
        return null; // Probably implementation of this case won't be needed.
971
    }
972
973
    // Path now is semi-absolute. It is convenient at this moment repeated slashes to be removed.
974
    $path = preg_replace(REPEATED_SLASHES_PURIFIER, '/', $path);
975
976
    // Path conversion to the requested type.
977
978
    switch ($path_type) {
979
        case TO_WEB:
980
            return $server_base_web.$path;
981
        case TO_SYS:
982
            return $server_base_sys.$path;
983
        case TO_REL:
984
            return $path;
985
    }
986
987
    return null;
988
}
989
990
/**
991
 * Gets a modified version of the path for the CDN, if defined in
992
 * configuration.php
993
 * @param string $web_path The path of the resource without CDN
994
 * @return string The path of the resource converted to CDN
995
 * @author Yannick Warnier <[email protected]>
996
 */
997
function api_get_cdn_path($web_path)
998
{
999
    global $_configuration;
1000
    $web_root = api_get_path(WEB_PATH);
1001
    $ext = substr($web_path,strrpos($web_path,'.'));
1002
    if (isset($ext[2])) { // faster version of strlen to check if len>2
1003
        // Check for CDN definitions
1004
        if (!empty($_configuration['cdn_enable']) && !empty($ext)) {
1005
            foreach ($_configuration['cdn'] as $host => $exts) {
1006
                if (in_array($ext,$exts)) {
1007
                    //Use host as defined in $_configuration['cdn'], without
1008
                    // trailing slash
1009
                    return str_replace($web_root,$host.'/',$web_path);
1010
                }
1011
            }
1012
        }
1013
    }
1014
    return $web_path;
1015
}
1016
1017
/**
1018
 * @return bool Return true if CAS authentification is activated
1019
 *
1020
 */
1021
function api_is_cas_activated() {
1022
    return api_get_setting('cas_activate') == "true";
1023
}
1024
1025
/**
1026
 * @return bool     Return true if LDAP authentification is activated
1027
 *
1028
 */
1029
function api_is_ldap_activated() {
1030
    global $extAuthSource;
1031
    return is_array($extAuthSource[LDAP_AUTH_SOURCE]);
1032
}
1033
1034
/**
1035
 * @return bool     Return true if Facebook authentification is activated
1036
 *
1037
 */
1038
function api_is_facebook_auth_activated() {
1039
    global $_configuration;
1040
    return (isset($_configuration['facebook_auth']) && $_configuration['facebook_auth'] == 1);
1041
}
1042
1043
/**
1044
 * This function checks whether a given path points inside the system.
1045
 * @param string $path      The path to be tested.
1046
 * It should be full path, web-absolute (WEB), semi-absolute (REL) or system-absolyte (SYS).
1047
 * @return bool             Returns true when the given path is inside the system, false otherwise.
1048
 */
1049
function api_is_internal_path($path) {
1050
    $path = str_replace('\\', '/', trim($path));
1051
    if (empty($path)) {
1052
        return false;
1053
    }
1054
    if (strpos($path, api_remove_trailing_slash(api_get_path(WEB_PATH))) === 0) {
1055
        return true;
1056
    }
1057
    if (strpos($path, api_remove_trailing_slash(api_get_path(SYS_PATH))) === 0) {
1058
        return true;
1059
    }
1060
    $server_base_web = api_remove_trailing_slash(api_get_path(REL_PATH));
1061
    $server_base_web = empty($server_base_web) ? '/' : $server_base_web;
1062
    if (strpos($path, $server_base_web) === 0) {
1063
        return true;
1064
    }
1065
    return false;
1066
}
1067
1068
/**
1069
 * Adds to a given path a trailing slash if it is necessary (adds "/" character at the end of the string).
1070
 * @param string $path          The input path.
1071
 * @return string               Returns the modified path.
1072
 */
1073
function api_add_trailing_slash($path) {
1074
    return substr($path, -1) == '/' ? $path : $path.'/';
1075
}
1076
1077
/**
1078
 * Removes from a given path the trailing slash if it is necessary (removes "/" character from the end of the string).
1079
 * @param string $path          The input path.
1080
 * @return string               Returns the modified path.
1081
 */
1082
function api_remove_trailing_slash($path) {
1083
    return substr($path, -1) == '/' ? substr($path, 0, -1) : $path;
1084
}
1085
1086
/**
1087
 * Checks the RFC 3986 syntax of a given URL.
1088
 * @param string $url       The URL to be checked.
1089
 * @param bool $absolute    Whether the URL is absolute (beginning with a scheme such as "http:").
1090
 * @return bool             Returns the URL if it is valid, FALSE otherwise.
1091
 * This function is an adaptation from the function valid_url(), Drupal CMS.
1092
 * @link http://drupal.org
1093
 * Note: The built-in function filter_var($urs, FILTER_VALIDATE_URL) has a bug for some versions of PHP.
1094
 * @link http://bugs.php.net/51192
1095
 */
1096
function api_valid_url($url, $absolute = false) {
1097
    if ($absolute) {
1098
        if (preg_match("
1099
            /^                                                      # Start at the beginning of the text
1100
            (?:ftp|https?|feed):\/\/                                # Look for ftp, http, https or feed schemes
1101
            (?:                                                     # Userinfo (optional) which is typically
1102
                (?:(?:[\w\.\-\+!$&'\(\)*\+,;=]|%[0-9a-f]{2})+:)*    # a username or a username and password
1103
                (?:[\w\.\-\+%!$&'\(\)*\+,;=]|%[0-9a-f]{2})+@        # combination
1104
            )?
1105
            (?:
1106
                (?:[a-z0-9\-\.]|%[0-9a-f]{2})+                      # A domain name or a IPv4 address
1107
                |(?:\[(?:[0-9a-f]{0,4}:)*(?:[0-9a-f]{0,4})\])       # or a well formed IPv6 address
1108
            )
1109
            (?::[0-9]+)?                                            # Server port number (optional)
1110
            (?:[\/|\?]
1111
                (?:[\w#!:\.\?\+=&@$'~*,;\/\(\)\[\]\-]|%[0-9a-f]{2}) # The path and query (optional)
1112
            *)?
1113
            $/xi", $url)) {
1114
            return $url;
1115
        }
1116
        return false;
1117
    } else {
1118
        return preg_match("/^(?:[\w#!:\.\?\+=&@$'~*,;\/\(\)\[\]\-]|%[0-9a-f]{2})+$/i", $url) ? $url : false;
1119
    }
1120
}
1121
1122
/**
1123
 * Checks whether a given string looks roughly like an email address.
1124
 * Tries to use PHP built-in validator in the filter extension (from PHP 5.2), falls back to a reasonably competent regex validator.
1125
 * Conforms approximately to RFC2822
1126
 * @link http://www.hexillion.com/samples/#Regex Original pattern found here
1127
 * This function is an adaptation from the method PHPMailer::ValidateAddress(), PHPMailer module.
1128
 * @link http://phpmailer.worxware.com
1129
 * @param string $address   The e-mail address to be checked.
1130
 * @return mixed            Returns the e-mail if it is valid, FALSE otherwise.
1131
 */
1132
function api_valid_email($address)
1133
{
1134
    return filter_var($address, FILTER_VALIDATE_EMAIL);
1135
    /*
1136
    // disable for now because the results are incoherent - YW 20110926
1137
1138
    if (function_exists('filter_var')) { // Introduced in PHP 5.2.
1139
        return filter_var($address, FILTER_VALIDATE_EMAIL);
1140
    } else {
1141
        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;
1142
    }*/
1143
}
1144
1145
1146
/* PROTECTION FUNCTIONS
1147
   Use these functions to protect your scripts. */
1148
1149
/**
1150
 * Function used to protect a course script.
1151
 * The function blocks access when
1152
 * - there is no $_SESSION["_course"] defined; or
1153
 * - $is_allowed_in_course is set to false (this depends on the course
1154
 * visibility and user status).
1155
 *
1156
 * This is only the first proposal, test and improve!
1157
 * @param boolean       Option to print headers when displaying error message. Default: false
1158
 * @param boolean       Whether session admins should be allowed or not.
1159
 * @return boolean      True if the user has access to the current course or is out of a course context, false otherwise
1160
 * @todo replace global variable
1161
 * @author Roan Embrechts
1162
 */
1163
function api_protect_course_script($print_headers = false, $allow_session_admins = false, $allow_drh = false)
1164
{
1165
    $is_allowed_in_course = api_is_allowed_in_course();
1166
1167
    $is_visible = false;
1168
    $course_info = api_get_course_info();
1169
1170
    if (empty($course_info)) {
1171
        api_not_allowed($print_headers);
1172
        return false;
1173
    }
1174
1175
    if (api_is_drh()) {
1176
        return true;
1177
    }
1178
1179
    if (api_is_platform_admin($allow_session_admins)) {
1180
        return true;
1181
    }
1182
    if (isset($course_info) && isset($course_info['visibility'])) {
1183
        switch ($course_info['visibility']) {
1184
            default:
1185 View Code Duplication
            case COURSE_VISIBILITY_CLOSED:
1186
                // Completely closed: the course is only accessible to the teachers. - 0
1187
                if (api_get_user_id() && !api_is_anonymous() && $is_allowed_in_course) {
1188
                    $is_visible = true;
1189
                }
1190
                break;
1191 View Code Duplication
            case COURSE_VISIBILITY_REGISTERED:
1192
                // Private - access authorized to course members only - 1
1193
                if (api_get_user_id() && !api_is_anonymous() && $is_allowed_in_course) {
1194
                    $is_visible = true;
1195
                }
1196
                break;
1197 View Code Duplication
            case COURSE_VISIBILITY_OPEN_PLATFORM:
1198
                // Open - access allowed for users registered on the platform - 2
1199
                if (api_get_user_id() && !api_is_anonymous() && $is_allowed_in_course) {
1200
                    $is_visible = true;
1201
                }
1202
                break;
1203
            case COURSE_VISIBILITY_OPEN_WORLD:
1204
                //Open - access allowed for the whole world - 3
1205
                $is_visible = true;
1206
                break;
1207
            case COURSE_VISIBILITY_HIDDEN:
1208
                //Completely closed: the course is only accessible to the teachers. - 0
1209
                if (api_is_platform_admin()) {
1210
                    $is_visible = true;
1211
                }
1212
                break;
1213
        }
1214
1215
        //If password is set and user is not registered to the course then the course is not visible
1216
        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...
1217
            isset($course_info['registration_code']) &&
1218
            !empty($course_info['registration_code'])
1219
        ) {
1220
            $is_visible = false;
1221
        }
1222
    }
1223
1224
    //Check session visibility
1225
    $session_id = api_get_session_id();
1226
1227
    if (!empty($session_id)) {
1228
        //$is_allowed_in_course was set in local.inc.php
1229
        if (!$is_allowed_in_course) {
1230
            $is_visible = false;
1231
        }
1232
    }
1233
1234
    if (!$is_visible) {
1235
        api_not_allowed($print_headers);
1236
        return false;
1237
    }
1238
    return true;
1239
}
1240
1241
/**
1242
 * Function used to protect an admin script.
1243
 *
1244
 * The function blocks access when the user has no platform admin rights
1245
 * with an error message printed on default output
1246
 * @param bool Whether to allow session admins as well
1247
 * @param bool Whether to allow HR directors as well
1248
 * @param string An optional message (already passed through get_lang)
1249
 * @return bool True if user is allowed, false otherwise.
1250
 * The function also outputs an error message in case not allowed
1251
 * @author Roan Embrechts (original author)
1252
 */
1253
function api_protect_admin_script($allow_sessions_admins = false, $allow_drh = false, $message = null)
1254
{
1255
    if (!api_is_platform_admin($allow_sessions_admins, $allow_drh)) {
1256
        api_not_allowed(true, $message);
1257
        return false;
1258
    }
1259
    return true;
1260
}
1261
1262
/**
1263
 * Function used to protect a teacher script.
1264
 * The function blocks access when the user has no teacher rights.
1265
 *
1266
 * @author Yoselyn Castillo
1267
 */
1268
function api_protect_teacher_script($allow_sessions_admins = false)
1269
{
1270
    if (!api_is_allowed_to_edit()) {
1271
        api_not_allowed(true);
1272
        return false;
1273
    }
1274
    return true;
1275
}
1276
1277
/**
1278
 * Function used to prevent anonymous users from accessing a script.
1279
 * @param bool|true $printHeaders
1280
 * @author Roan Embrechts
1281
 *
1282
 * @return bool
1283
 */
1284
function api_block_anonymous_users($printHeaders = true)
1285
{
1286
    $user = api_get_user_info();
1287 View Code Duplication
    if (!(isset($user['user_id']) && $user['user_id']) || api_is_anonymous($user['user_id'], true)) {
1288
        api_not_allowed($printHeaders);
1289
        return false;
1290
    }
1291
1292
    return true;
1293
}
1294
1295
/**
1296
 * @return array with the navigator name and version
1297
 */
1298
function api_get_navigator() {
1299
    $navigator = 'Unknown';
1300
    $version = 0;
1301
1302
    if (!isset($_SERVER['HTTP_USER_AGENT'])) {
1303
        return array('name' => 'Unknown', 'version' => '0.0.0');
1304
    }
1305
1306
    if (strpos($_SERVER['HTTP_USER_AGENT'], 'Opera') !== false) {
1307
        $navigator = 'Opera';
1308
        list (, $version) = explode('Opera', $_SERVER['HTTP_USER_AGENT']);
1309 View Code Duplication
    } elseif (strpos($_SERVER['HTTP_USER_AGENT'], 'MSIE') !== false) {
1310
        $navigator = 'Internet Explorer';
1311
        list (, $version) = explode('MSIE', $_SERVER['HTTP_USER_AGENT']);
1312
    } elseif (strpos($_SERVER['HTTP_USER_AGENT'], 'Chrome') !== false) {
1313
        $navigator = 'Chrome';
1314
        list (, $version) = explode('Chrome', $_SERVER['HTTP_USER_AGENT']);
1315
    } elseif (stripos($_SERVER['HTTP_USER_AGENT'], 'safari') !== false) {
1316
        $navigator = 'Safari';
1317
        list (, $version) = explode('Version/', $_SERVER['HTTP_USER_AGENT']);
1318
    } elseif (strpos($_SERVER['HTTP_USER_AGENT'], 'Gecko') !== false) {
1319
        $navigator = 'Mozilla';
1320
        list (, $version) = explode('; rv:', $_SERVER['HTTP_USER_AGENT']);
1321 View Code Duplication
    } elseif (strpos($_SERVER['HTTP_USER_AGENT'], 'Netscape') !== false) {
1322
        $navigator = 'Netscape';
1323
        list (, $version) = explode('Netscape', $_SERVER['HTTP_USER_AGENT']);
1324
    } elseif (strpos($_SERVER['HTTP_USER_AGENT'], 'Konqueror') !== false) {
1325
        $navigator = 'Konqueror';
1326
        list (, $version) = explode('Konqueror', $_SERVER['HTTP_USER_AGENT']);
1327 View Code Duplication
    } elseif (stripos($_SERVER['HTTP_USER_AGENT'], 'applewebkit') !== false) {
1328
        $navigator = 'AppleWebKit';
1329
        list (, $version) = explode('Version/', $_SERVER['HTTP_USER_AGENT']);
1330
    }
1331
    $version = str_replace('/', '', $version);
1332
    if (strpos($version, '.') === false) {
1333
        $version = number_format(doubleval($version), 1);
1334
    }
1335
    $return = array('name' => $navigator, 'version' => $version);
1336
    return $return;
1337
}
1338
1339
/**
1340
 * @return True if user self registration is allowed, false otherwise.
1341
 */
1342
function api_is_self_registration_allowed()
1343
{
1344
    return isset($GLOBALS['allowSelfReg']) ? $GLOBALS['allowSelfReg'] : false;
1345
}
1346
1347
/**
1348
 * This function returns the id of the user which is stored in the $_user array.
1349
 *
1350
 * example: The function can be used to check if a user is logged in
1351
 *          if (api_get_user_id())
1352
 * @return integer the id of the current user, 0 if is empty
1353
 */
1354
function api_get_user_id()
1355
{
1356
    return empty($GLOBALS['_user']['user_id']) ? 0 : intval($GLOBALS['_user']['user_id']);
1357
}
1358
1359
/**
1360
 * Gets the list of courses a specific user is subscribed to
1361
 * @param int       User ID
1362
 * @param boolean   $fetch_session Whether to get session courses or not - NOT YET IMPLEMENTED
1363
 * @return array    Array of courses in the form [0]=>('code'=>xxx,'db'=>xxx,'dir'=>xxx,'status'=>d)
1364
 */
1365
function api_get_user_courses($userid, $fetch_session = true)
1366
{
1367
    // Get out if not integer
1368
    if ($userid != strval(intval($userid))) {
1369
        return array();
1370
    }
1371
1372
    $t_course = Database::get_main_table(TABLE_MAIN_COURSE);
1373
    $t_course_user = Database::get_main_table(TABLE_MAIN_COURSE_USER);
1374
1375
    $sql = "SELECT cc.id as real_id, cc.code code, cc.directory dir, cu.status status
1376
            FROM    $t_course       cc,
1377
                    $t_course_user   cu
1378
            WHERE
1379
                cc.id = cu.c_id AND
1380
                cu.user_id = '".$userid."' AND
1381
                cu.relation_type<>".COURSE_RELATION_TYPE_RRHH." ";
1382
    $result = Database::query($sql);
1383
    if ($result === false) {
1384
        return array();
1385
    }
1386
1387
    $courses = array();
1388
    while ($row = Database::fetch_array($result)) {
1389
        // we only need the database name of the course
1390
        $courses[] = $row;
1391
    }
1392
1393
    return $courses;
1394
}
1395
1396
/**
1397
 * Formats user information into a standard array
1398
 * This function should be only used inside api_get_user_info()
1399
 *
1400
 * @param array Non-standard user array
1401
 * @param bool $add_password
1402
 *
1403
 * @return array Standard user array
1404
 */
1405
function _api_format_user($user, $add_password = false)
1406
{
1407
    $result = array();
1408
1409
    $firstname = null;
1410
    $lastname = null;
1411
1412
    if (isset($user['firstname']) && isset($user['lastname'])) {
1413
        $firstname = $user['firstname'];
1414
        $lastname = $user['lastname'];
1415
    } elseif (isset($user['firstName']) && isset($user['lastName'])) {
1416
        $firstname = isset($user['firstName']) ? $user['firstName'] : null;
1417
        $lastname = isset($user['lastName']) ? $user['lastName'] : null;
1418
    }
1419
1420
    $result['complete_name'] = api_get_person_name($firstname, $lastname);
1421
1422
    $result['complete_name_with_username'] = $result['complete_name'];
1423
1424
    if (!empty($user['username'])) {
1425
        $result['complete_name_with_username'] = $result['complete_name'].' ('.$user['username'].')';
1426
    }
1427
1428
    $result['firstname'] = $firstname;
1429
    $result['lastname'] = $lastname;
1430
1431
    // Kept for historical reasons
1432
    $result['firstName'] = $firstname;
1433
    $result['lastName'] = $lastname;
1434
1435
    $attributes = array(
1436
        'phone',
1437
        'picture_uri',
1438
        'official_code',
1439
        'status',
1440
        'active',
1441
        'auth_source',
1442
        'username',
1443
        'theme',
1444
        'language',
1445
        'creator_id',
1446
        'registration_date',
1447
        'hr_dept_id',
1448
        'expiration_date',
1449
        'last_login'
1450
    );
1451
1452
    foreach ($attributes as $attribute) {
1453
        $result[$attribute] = isset($user[$attribute]) ? $user[$attribute] : null;
1454
    }
1455
1456
    if (isset($user['email'])) {
1457
        $result['mail'] = isset($user['email']) ? $user['email'] : null;
1458
        $result['email'] = isset($user['email'])? $user['email'] : null;
1459
    } else {
1460
        $result['mail'] = isset($user['mail']) ? $user['mail'] : null;
1461
        $result['email'] = isset($user['mail'])? $user['mail'] : null;
1462
    }
1463
    $user_id = intval($user['user_id']);
1464
    // Maintain the user_id index for backwards compatibility
1465
    $result['user_id'] = $result['id'] = $user_id;
1466
1467
    // Getting user avatar.
1468
    $originalFile = UserManager::getUserPicture($user_id, USER_IMAGE_SIZE_ORIGINAL, $result);
1469
    $smallFile = UserManager::getUserPicture($user_id, USER_IMAGE_SIZE_SMALL, $result);
1470
1471
    $result['avatar'] = $originalFile;
1472
    $avatarString = explode('?', $originalFile);
1473
    $result['avatar_no_query'] = reset($avatarString);
1474
    $result['avatar_small'] = $smallFile;
1475
1476
    if (isset($user['user_is_online'])) {
1477
        $result['user_is_online'] = $user['user_is_online'] == true ? 1 : 0;
1478
    }
1479
    if (isset($user['user_is_online_in_chat'])) {
1480
        $result['user_is_online_in_chat'] = intval($user['user_is_online_in_chat']);
1481
    }
1482
1483
    if ($add_password) {
1484
        $result['password'] = $user['password'];
1485
    }
1486
1487
    $result['profile_url'] = api_get_path(WEB_CODE_PATH).'social/profile.php?u='.$user_id;
1488
1489
    if (isset($user['extra'])) {
1490
        $result['extra'] = $user['extra'];
1491
    }
1492
1493
    return $result;
1494
}
1495
1496
/**
1497
 * Finds all the information about a user.
1498
 * If no parameter is passed you find all the information about the current user.
1499
 * @param int  $user_id
1500
 * @param bool $checkIfUserOnline
1501
 * @param bool $showPassword
1502
 * @param bool $loadExtraData
1503
 * @param bool $loadOnlyVisibleExtraData Get the user extra fields that are visible
1504
 * @return array $user_info user_id, lastname, firstname, username, email, etc
1505
 * @author Patrick Cool <[email protected]>
1506
 * @author Julio Montoya
1507
 * @version 21 September 2004
1508
 */
1509
function api_get_user_info(
1510
    $user_id = 0,
1511
    $checkIfUserOnline = false,
1512
    $showPassword = false,
1513
    $loadExtraData = false,
1514
    $loadOnlyVisibleExtraData = false
1515
) {
1516
    if (empty($user_id)) {
1517
        $userFromSession = Session::read('_user');
1518
        if (isset($userFromSession)) {
1519
            return _api_format_user($userFromSession);
1520
        }
1521
        // @todo trigger an exception here
1522
        return false;
1523
    }
1524
1525
    $sql = "SELECT * FROM ".Database :: get_main_table(TABLE_MAIN_USER)."
1526
            WHERE id='".intval($user_id)."'";
1527
    $result = Database::query($sql);
1528
    if (Database::num_rows($result) > 0) {
1529
        $result_array = Database::fetch_array($result);
1530
        if ($checkIfUserOnline) {
1531
            $use_status_in_platform = user_is_online($user_id);
1532
1533
            $result_array['user_is_online'] = $use_status_in_platform;
1534
            $user_online_in_chat = 0;
1535
1536
            if ($use_status_in_platform) {
1537
                $user_status = UserManager::get_extra_user_data_by_field(
1538
                    $user_id,
1539
                    'user_chat_status',
1540
                    false,
1541
                    true
1542
                );
1543
                if (intval($user_status['user_chat_status']) == 1) {
1544
                    $user_online_in_chat = 1;
1545
                }
1546
            }
1547
            $result_array['user_is_online_in_chat'] = $user_online_in_chat;
1548
        }
1549
1550
        if ($loadExtraData) {
1551
            $fieldValue = new ExtraFieldValue('user');
1552
1553
            $result_array['extra'] = $fieldValue->getAllValuesForAnItem(
1554
                $user_id,
1555
                $loadOnlyVisibleExtraData
1556
            );
1557
        }
1558
        $user = _api_format_user($result_array, $showPassword);
1559
1560
        return $user;
1561
    }
1562
    return false;
1563
}
1564
1565
/**
1566
 * Finds all the information about a user from username instead of user id
1567
 * @param string $username
1568
 * @return array $user_info array user_id, lastname, firstname, username, email
1569
 * @author Yannick Warnier <[email protected]>
1570
 */
1571 View Code Duplication
function api_get_user_info_from_username($username = '')
1572
{
1573
    if (empty($username)) {
1574
        return false;
1575
    }
1576
    $username = trim($username);
1577
1578
    $sql = "SELECT * FROM ".Database :: get_main_table(TABLE_MAIN_USER)."
1579
            WHERE username='".Database::escape_string($username)."'";
1580
    $result = Database::query($sql);
1581
    if (Database::num_rows($result) > 0) {
1582
        $result_array = Database::fetch_array($result);
1583
        return _api_format_user($result_array);
1584
    }
1585
    return false;
1586
}
1587
1588
/**
1589
 * Get first user with an email
1590
 * @param string $email
1591
 * @return array|bool
1592
 */
1593 View Code Duplication
function api_get_user_info_from_email($email = '')
1594
{
1595
    if (empty($email)) {
1596
        return false;
1597
    }
1598
    $sql = "SELECT * FROM ".Database :: get_main_table(TABLE_MAIN_USER)."
1599
            WHERE email ='".Database::escape_string($email)."' LIMIT 1";
1600
    $result = Database::query($sql);
1601
    if (Database::num_rows($result) > 0) {
1602
        $result_array = Database::fetch_array($result);
1603
        return _api_format_user($result_array);
1604
    }
1605
1606
    return false;
1607
}
1608
1609
/**
1610
 * @return string
1611
 */
1612
function api_get_course_id()
1613
{
1614
    return isset($GLOBALS['_cid']) ? $GLOBALS['_cid'] : null;
1615
}
1616
1617
/**
1618
 * Returns the current course id
1619
 * @return int
1620
 */
1621
function api_get_real_course_id()
1622
{
1623
    return api_get_course_int_id();
1624
}
1625
1626
/**
1627
 * Returns the current course id (integer)
1628
 * @param   string  $code   Optional course code
1629
 * @return int
1630
 */
1631
function api_get_course_int_id($code = null)
1632
{
1633 View Code Duplication
    if (!empty($code)) {
1634
        $code = Database::escape_string($code);
1635
        $row = Database::select(
1636
            'id',
1637
            Database::get_main_table(TABLE_MAIN_COURSE),
1638
            array('where'=> array('code = ?' => array($code))),
1639
            'first'
1640
        );
1641
1642
        if (is_array($row) && isset($row['id'])) {
1643
            return $row['id'];
1644
        } else {
1645
            return false;
1646
        }
1647
    }
1648
    return Session::read('_real_cid', 0);
1649
}
1650
1651
/**
1652
 * Returns the current course directory
1653
 *
1654
 * This function relies on api_get_course_info()
1655
 * @param string    The course code - optional (takes it from session if not given)
1656
 * @return string   The directory where the course is located inside the Chamilo "courses" directory
1657
 * @author Yannick Warnier <[email protected]>
1658
 */
1659
function api_get_course_path($course_code = null)
1660
{
1661
    $info = !empty($course_code) ? api_get_course_info($course_code) : api_get_course_info();
1662
    return $info['path'];
1663
}
1664
1665
/**
1666
 * Gets a course setting from the current course_setting table. Try always using integer values.
1667
 * @param string    The name of the setting we want from the table
1668
 * @param string    Optional: course code
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
    $url = empty($GLOBALS['_cid']) ? '' : 'cidReq='.htmlspecialchars($GLOBALS['_cid']);
1723
    $origin = api_get_origin();
1724
1725
    if ($addSessionId) {
1726
        if (!empty($url)) {
1727
            $url .= api_get_session_id() == 0 ? '&id_session=0' : '&id_session='.api_get_session_id();
1728
        }
1729
    }
1730
1731
    if ($addGroupId) {
1732
        if (!empty($url)) {
1733
            $url .= api_get_group_id() == 0 ? '&gidReq=0' : '&gidReq='.api_get_group_id();
1734
        }
1735
    }
1736
1737
    $url .= '&gradebook='.intval(api_is_in_gradebook());
1738
    $url .= '&origin='.$origin;
1739
1740
    return $url;
1741
}
1742
1743
function api_is_in_gradebook()
1744
{
1745
    return Session::read('in_gradebook', false);
1746
}
1747
1748
function api_set_in_gradebook()
1749
{
1750
    Session::write('in_gradebook', true);
1751
}
1752
1753
function api_remove_in_gradebook()
1754
{
1755
    Session::erase('in_gradebook');
1756
}
1757
1758
/**
1759
 * Returns the current course info array see api_format_course_array()
1760
 * If the course_code is given, the returned array gives info about that
1761
 * particular course, if none given it gets the course info from the session.
1762
 *
1763
 * @param string $course_code
1764
 * @param bool $strict
1765
 *
1766
 * @return array
1767
 */
1768
function api_get_course_info($course_code = null, $strict = false)
1769
{
1770
    if (!empty($course_code)) {
1771
        $course_code = Database::escape_string($course_code);
1772
        $courseId = api_get_course_int_id($course_code);
1773
1774
        if (empty($courseId)) {
1775
            return array();
1776
        }
1777
1778
        $course_table = Database::get_main_table(TABLE_MAIN_COURSE);
1779
        $course_cat_table = Database::get_main_table(TABLE_MAIN_CATEGORY);
1780
        $sql = "SELECT
1781
                    course.*,
1782
                    course_category.code faCode,
1783
                    course_category.name faName
1784
                FROM $course_table
1785
                LEFT JOIN $course_cat_table
1786
                ON course.category_code = course_category.code
1787
                WHERE course.id = $courseId";
1788
        $result = Database::query($sql);
1789
        $courseInfo = array();
1790
        if (Database::num_rows($result) > 0) {
1791
            $data = Database::fetch_array($result);
1792
            $courseInfo = api_format_course_array($data);
1793
        }
1794
1795
        return $courseInfo;
1796
    }
1797
1798
    global $_course;
1799
    if ($_course == '-1') {
1800
        $_course = array();
1801
    }
1802
1803
    return $_course;
1804
}
1805
1806
/**
1807
 * Returns the current course info array.
1808
1809
 * Now if the course_code is given, the returned array gives info about that
1810
 * particular course, not specially the current one.
1811
 * @param int $id Numeric ID of the course
1812
 * @return array The course info as an array formatted by api_format_course_array, including category.name
1813
 */
1814 View Code Duplication
function api_get_course_info_by_id($id = null)
1815
{
1816
    if (!empty($id)) {
1817
        $id = intval($id);
1818
        $course_table = Database::get_main_table(TABLE_MAIN_COURSE);
1819
        $course_cat_table = Database::get_main_table(TABLE_MAIN_CATEGORY);
1820
        $sql = "SELECT
1821
                    course.*,
1822
                    course_category.code faCode,
1823
                    course_category.name faName
1824
                FROM $course_table
1825
                LEFT JOIN $course_cat_table
1826
                ON course.category_code =  course_category.code
1827
                WHERE course.id = $id";
1828
        $result = Database::query($sql);
1829
        $_course = array();
1830
        if (Database::num_rows($result) > 0) {
1831
            $course_data = Database::fetch_array($result);
1832
            $_course = api_format_course_array($course_data);
1833
        }
1834
        return $_course;
1835
    }
1836
1837
    global $_course;
1838
    if ($_course == '-1') $_course = array();
1839
    return $_course;
1840
}
1841
1842
/**
1843
 * Reformat the course array (output by api_get_course_info()) in order, mostly,
1844
 * to switch from 'code' to 'id' in the array. This is a legacy feature and is
1845
 * now possibly causing massive confusion as a new "id" field has been added to
1846
 * the course table in 1.9.0.
1847
 * @param $course_data
1848
 * @return array
1849
 * @todo eradicate the false "id"=code field of the $_course array and use the int id
1850
 */
1851
function api_format_course_array($course_data)
1852
{
1853
    if (empty($course_data)) {
1854
        return array();
1855
    }
1856
1857
    $_course = array();
1858
    $_course['id'] = $course_data['code'];
1859
    $_course['real_id'] = $course_data['id'];
1860
1861
    // Added
1862
    $_course['code'] = $course_data['code'];
1863
    $_course['name'] = $course_data['title'];
1864
    $_course['title'] = $course_data['title'];
1865
    $_course['official_code'] = $course_data['visual_code'];
1866
    $_course['visual_code'] = $course_data['visual_code'];
1867
    $_course['sysCode'] = $course_data['code'];
1868
    $_course['path'] = $course_data['directory']; // Use as key in path.
1869
    $_course['directory'] = $course_data['directory'];
1870
    $_course['creation_date'] = $course_data['creation_date'];
1871
    $_course['titular'] = $course_data['tutor_name'];
1872
    $_course['language'] = $course_data['course_language'];
1873
    $_course['extLink']['url'] = $course_data['department_url'];
1874
    $_course['extLink']['name'] = $course_data['department_name'];
1875
    $_course['categoryCode'] = $course_data['faCode'];
1876
    $_course['categoryName'] = $course_data['faName'];
1877
    $_course['visibility'] = $course_data['visibility'];
1878
    $_course['subscribe_allowed'] = $course_data['subscribe'];
1879
    $_course['subscribe'] = $course_data['subscribe'];
1880
    $_course['unsubscribe'] = $course_data['unsubscribe'];
1881
    $_course['course_language'] = $course_data['course_language'];
1882
    $_course['activate_legal'] = isset($course_data['activate_legal']) ? $course_data['activate_legal'] : false;
1883
    $_course['legal'] = $course_data['legal'];
1884
    $_course['show_score'] = $course_data['show_score']; //used in the work tool
1885
    $_course['department_name'] = $course_data['department_name'];
1886
    $_course['department_url'] = $course_data['department_url'];
1887
1888
    // Course password
1889
    $_course['registration_code'] = !empty($course_data['registration_code']) ? sha1($course_data['registration_code']) : null;
1890
    $_course['disk_quota'] = $course_data['disk_quota'];
1891
    $_course['course_public_url'] = api_get_path(WEB_COURSE_PATH).$course_data['directory'].'/index.php';
1892
1893
    if (array_key_exists('add_teachers_to_sessions_courses', $course_data)) {
1894
        $_course['add_teachers_to_sessions_courses'] = $course_data['add_teachers_to_sessions_courses'];
1895
    }
1896
1897
    if (file_exists(api_get_path(SYS_COURSE_PATH).$course_data['directory'].'/course-pic85x85.png')) {
1898
        $url_image = api_get_path(WEB_COURSE_PATH).$course_data['directory'].'/course-pic85x85.png';
1899
    } else {
1900
        $url_image = Display::return_icon('course.png', null, null, ICON_SIZE_BIG, null, true, false);
1901
    }
1902
    $_course['course_image'] = $url_image;
1903
1904
    if (file_exists(api_get_path(SYS_COURSE_PATH).$course_data['directory'].'/course-pic.png')) {
1905
        $url_image = api_get_path(WEB_COURSE_PATH).$course_data['directory'].'/course-pic.png';
1906
    } else {
1907
        $url_image = Display::returnIconPath('session_default.png');
1908
    }
1909
    $_course['course_image_large'] = $url_image;
1910
1911
    return $_course;
1912
}
1913
1914
/**
1915
 * Add a parameter to the existing URL. If this parameter already exists,
1916
 * just replace it with the new value
1917
 * @param   string  The URL
1918
 * @param   string  param=value string
1919
 * @param   boolean Whether to filter XSS or not
1920
 * @return  string  The URL with the added parameter
1921
 */
1922
function api_add_url_param($url, $param, $filter_xss = true) {
1923
    if (empty($param)) {
1924
        return $url;
1925
    }
1926
    if (strpos($url, '?') !== false) {
1927
        if ($param[0] != '&') {
1928
            $param = '&'.$param;
1929
        }
1930
        list (, $query_string) = explode('?', $url);
1931
        $param_list1 = explode('&', $param);
1932
        $param_list2 = explode('&', $query_string);
1933
        $param_list1_keys = $param_list1_vals = array();
1934
        foreach ($param_list1 as $key => $enreg) {
1935
            list ($param_list1_keys[$key], $param_list1_vals[$key]) = explode('=', $enreg);
1936
        }
1937
        $param_list1 = array ('keys' => $param_list1_keys, 'vals' => $param_list1_vals);
1938
        foreach ($param_list2 as $enreg) {
1939
            $enreg = explode('=', $enreg);
1940
            $key = array_search($enreg[0], $param_list1['keys']);
1941
            if (!is_null($key) && !is_bool($key)) {
1942
                $url = str_replace($enreg[0].'='.$enreg[1], $enreg[0].'='.$param_list1['vals'][$key], $url);
1943
                $param = str_replace('&'.$enreg[0].'='.$param_list1['vals'][$key], '', $param);
1944
            }
1945
        }
1946
        $url .= $param;
1947
    } else {
1948
        $url = $url.'?'.$param;
1949
    }
1950
    if ($filter_xss === true) {
1951
        $url = Security::remove_XSS(urldecode($url));
1952
    }
1953
    return $url;
1954
}
1955
1956
/**
1957
 * Returns a difficult to guess password.
1958
 * @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...
1959
 * @return string the generated password
1960
 */
1961
function api_generate_password($length = 8) {
1962
    $characters = 'abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ23456789';
1963
    if ($length < 2) {
1964
        $length = 2;
1965
    }
1966
    $password = '';
1967
    for ($i = 0; $i < $length; $i ++) {
1968
        $password .= $characters[rand() % strlen($characters)];
1969
    }
1970
    return $password;
1971
}
1972
1973
/**
1974
 * Checks a password to see wether it is OK to use.
1975
 * @param string $password
1976
 * @return true if the password is acceptable, false otherwise
1977
 * Notes about what a password "OK to use" is:
1978
 * 1. The password should be at least 5 characters long.
1979
 * 2. Only English letters (uppercase or lowercase, it doesn't matter) and digits are allowed.
1980
 * 3. The password should contain at least 3 letters.
1981
 * 4. It should contain at least 2 digits.
1982
 * 5. It should not contain 3 or more consequent (according to ASCII table) characters.
1983
 */
1984
function api_check_password($password) {
1985
    $password_length = api_strlen($password);
1986
    if ($password_length < 5) {
1987
        return false;
1988
    }
1989
    $password = api_strtolower($password);
1990
    $letters = 0;
1991
    $digits = 0;
1992
    $consequent_characters = 0;
1993
    $previous_character_code = 0;
1994
    for ($i = 0; $i < $password_length; $i ++) {
1995
        $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...
1996
        if ($i && abs($current_character_code - $previous_character_code) <= 1) {
1997
            $consequent_characters ++;
1998
            if ($consequent_characters == 3) {
1999
                return false;
2000
            }
2001
        } else {
2002
            $consequent_characters = 1;
2003
        }
2004
        if ($current_character_code >= 97 && $current_character_code <= 122) {
2005
            $letters ++;
2006
        } elseif ($current_character_code >= 48 && $current_character_code <= 57) {
2007
            $digits ++;
2008
        } else {
2009
            return false;
2010
        }
2011
        $previous_character_code = $current_character_code;
2012
    }
2013
    return ($letters >= 3 && $digits >= 2);
2014
}
2015
2016
/**
2017
 * Clears the user ID from the session if it was the anonymous user. Generally
2018
 * used on out-of-tools pages to remove a user ID that could otherwise be used
2019
 * in the wrong context.
2020
 * This function is to be used in conjunction with the api_set_anonymous()
2021
 * function to simulate the user existence in case of an anonymous visit.
2022
 * @param bool      database check switch - passed to api_is_anonymous()
2023
 * @return bool     true if succesfully unregistered, false if not anonymous.
2024
 */
2025
function api_clear_anonymous($db_check = false) {
2026
    global $_user;
2027
    if (api_is_anonymous($_user['user_id'], $db_check)) {
2028
        unset($_user['user_id']);
2029
        Session::erase('_uid');
2030
        return true;
2031
    }
2032
    return false;
2033
}
2034
2035
/**
2036
 * Returns the status string corresponding to the status code
2037
 * @author Noel Dieschburg
2038
 * @param the int status code
2039
 */
2040
function get_status_from_code($status_code) {
2041
    switch ($status_code) {
2042
        case STUDENT:
2043
            return get_lang('Student', '');
2044
        case TEACHER:
2045
            return get_lang('Teacher', '');
2046
        case COURSEMANAGER:
2047
            return get_lang('Manager', '');
2048
        case SESSIONADMIN:
2049
            return get_lang('SessionsAdmin', '');
2050
        case DRH:
2051
            return get_lang('Drh', '');
2052
    }
2053
}
2054
2055
/* FAILURE MANAGEMENT */
2056
2057
/**
2058
 * The Failure Management module is here to compensate
2059
 * the absence of an 'exception' device in PHP 4.
2060
 */
2061
2062
/**
2063
 * $api_failureList - array containing all the failure recorded in order of arrival.
2064
 */
2065
$api_failureList = array();
2066
2067
/**
2068
 * Fills a global array called $api_failureList
2069
 * This array collects all the failure occuring during the script runs
2070
 * The main purpose is allowing to manage the display messages externaly
2071
 * from the functions or objects. This strengthens encupsalation principle
2072
 *
2073
 * @author Hugues Peeters <[email protected]>
2074
 * @param  string $failure_type - the type of failure
2075
 * global: array $api_failureList
2076
 * @return boolean false to stay consistent with the main script
2077
 */
2078
function api_set_failure($failure_type) {
2079
    global $api_failureList;
2080
    $api_failureList[] = $failure_type;
2081
    return false;
2082
}
2083
2084
/**
2085
 * Sets the current user as anonymous if it hasn't been identified yet. This
2086
 * function should be used inside a tool only. The function api_clear_anonymous()
2087
 * acts in the opposite direction by clearing the anonymous user's data every
2088
 * time we get on a course homepage or on a neutral page (index, admin, my space)
2089
 * @return bool     true if set user as anonymous, false if user was already logged in or anonymous id could not be found
2090
 */
2091
function api_set_anonymous() {
2092
    global $_user;
2093
2094
    if (!empty($_user['user_id'])) {
2095
        return false;
2096
    }
2097
2098
    $user_id = api_get_anonymous_id();
2099
    if ($user_id == 0) {
2100
        return false;
2101
    }
2102
    Session::erase('_user');
2103
    $_user['user_id'] = $user_id;
2104
    $_user['is_anonymous'] = true;
2105
    $GLOBALS['_user'] = $_user;
2106
    Session::write('_user', $_user);
2107
    return true;
2108
}
2109
2110
/**
2111
 * Gets the last failure stored in $api_failureList;
2112
 *
2113
 * @author Hugues Peeters <[email protected]>
2114
 * @param void
2115
 * @return string - the last failure stored
2116
 */
2117
function api_get_last_failure() {
2118
    global $api_failureList;
2119
    return $api_failureList[count($api_failureList) - 1];
2120
}
2121
2122
/**
2123
 * Collects and manages failures occurring during script execution
2124
 * The main purpose is allowing to manage the display messages externally
2125
 * from functions or objects. This strengthens encapsulation principle
2126
 *
2127
 * @author Hugues Peeters <[email protected]>
2128
 * @package chamilo.library
2129
 */
2130
class api_failure {
2131
2132
    // TODO: $api_failureList to be hidden from global scope and to be renamed according to our coding conventions.
2133
    /**
2134
     * IMPLEMENTATION NOTE : For now the $api_failureList list is set to the
2135
     * global scope, as PHP 4 is unable to manage static variable in class. But
2136
     * this feature is awaited in PHP 5. The class is already written to minize
2137
     * the change when static class variable will be possible. And the API won't
2138
     * change.
2139
     */
2140
    public $api_failureList = array();
2141
2142
    /**
2143
     * Piles the last failure in the failure list
2144
     *
2145
     * @author Hugues Peeters <[email protected]>
2146
     * @param  string $failure_type - the type of failure
2147
     * @global array  $api_failureList
2148
     * @return bolean false to stay consistent with the main script
2149
     */
2150
    static function set_failure($failure_type) {
2151
        global $api_failureList;
2152
        $api_failureList[] = $failure_type;
2153
        return false;
2154
    }
2155
2156
    /**
2157
     * Gets the last failure stored
2158
     *
2159
     * @author Hugues Peeters <[email protected]>
2160
     * @param void
2161
     * @return string - the last failure stored
2162
     */
2163
    static function get_last_failure() {
2164
        global $api_failureList;
2165
        if (count($api_failureList) == 0) { return ''; }
2166
        return $api_failureList[count($api_failureList) - 1];
2167
    }
2168
}
2169
2170
2171
/* CONFIGURATION SETTINGS */
2172
2173
/**
2174
 * Gets the current Chamilo (not PHP/cookie) session ID
2175
 * @return  int     O if no active session, the session ID otherwise
2176
 */
2177
function api_get_session_id()
2178
{
2179
    return Session::read('id_session', 0);
2180
}
2181
2182
/**
2183
 * Gets the current Chamilo (not social network) group ID
2184
 * @return  int     O if no active session, the session ID otherwise
2185
 */
2186
function api_get_group_id()
2187
{
2188
    return Session::read('_gid', 0);
2189
}
2190
2191
2192
/**
2193
 * Gets the current or given session name
2194
 * @param   int     Session ID (optional)
2195
 * @return  string  The session name, or null if unfound
2196
 */
2197
function api_get_session_name($session_id) {
2198
    if (empty($session_id)) {
2199
        $session_id = api_get_session_id();
2200
        if (empty($session_id)) { return null; }
2201
    }
2202
    $t = Database::get_main_table(TABLE_MAIN_SESSION);
2203
    $s = "SELECT name FROM $t WHERE id = ".(int)$session_id;
2204
    $r = Database::query($s);
2205
    $c = Database::num_rows($r);
2206
    if ($c > 0) {
2207
        //technically, there can be only one, but anyway we take the first
2208
        $rec = Database::fetch_array($r);
2209
        return $rec['name'];
2210
    }
2211
    return null;
2212
}
2213
2214
/**
2215
 * Gets the session info by id
2216
 * @param int       Session ID
2217
 * @return array    information of the session
2218
 */
2219
function api_get_session_info($session_id)
2220
{
2221
    $data = array();
2222
    if (!empty($session_id)) {
2223
        $session_id = intval($session_id);
2224
        $tbl_session = Database::get_main_table(TABLE_MAIN_SESSION);
2225
        $sql = "SELECT * FROM $tbl_session WHERE id = $session_id";
2226
        $result = Database::query($sql);
2227
2228
        if (Database::num_rows($result)>0) {
2229
            $data = Database::fetch_array($result, 'ASSOC');
2230
        }
2231
    }
2232
2233
    return $data;
2234
}
2235
2236
/**
2237
 * Gets the session visibility by session id
2238
 * @param int $session_id
2239
 * @param int $courseId
2240
 * @param bool $ignore_visibility_for_admins
2241
 * @return int
2242
 *  0 = session still available,
2243
 *  SESSION_VISIBLE_READ_ONLY = 1,
2244
 *  SESSION_VISIBLE = 2,
2245
 *  SESSION_INVISIBLE = 3
2246
 */
2247
function api_get_session_visibility(
2248
    $session_id,
2249
    $courseId = null,
2250
    $ignore_visibility_for_admins = true
2251
) {
2252
    // Means that the session is still available.
2253
    $visibility = 0;
2254
2255
    if (api_is_platform_admin()) {
2256
        if ($ignore_visibility_for_admins) {
2257
            return SESSION_AVAILABLE;
2258
        }
2259
    }
2260
2261
    $now = time();
2262
    if (!empty($session_id)) {
2263
        $session_id = intval($session_id);
2264
        $tbl_session = Database::get_main_table(TABLE_MAIN_SESSION);
2265
2266
        $sql = "SELECT * FROM $tbl_session
2267
                WHERE id = $session_id ";
2268
2269
        $result = Database::query($sql);
2270
2271
        if (Database::num_rows($result) > 0) {
2272
            $row = Database::fetch_array($result, 'ASSOC');
2273
            $visibility = $original_visibility = $row['visibility'];
2274
2275
            // I don't care the session visibility.
2276
            if (empty($row['access_start_date']) && empty($row['access_end_date'])) {
2277
2278
                // Session duration per student.
2279
                if (isset($row['duration']) && !empty($row['duration'])) {
2280
                    $duration = $row['duration'] * 24 * 60 * 60;
2281
2282
                    $courseAccess = CourseManager::getFirstCourseAccessPerSessionAndUser(
2283
                        $session_id,
2284
                        api_get_user_id()
2285
                    );
2286
2287
                    // If there is a session duration but there is no previous
2288
                    // access by the user, then the session is still available
2289
                    if (count($courseAccess) == 0) {
2290
                        return SESSION_AVAILABLE;
2291
                    }
2292
2293
                    $currentTime = time();
2294
                    $firstAccess = 0;
2295
                    if (isset($courseAccess['login_course_date'])) {
2296
                        $firstAccess = api_strtotime(
2297
                            $courseAccess['login_course_date'],
2298
                            'UTC'
2299
                        );
2300
                    }
2301
                    $userDurationData = SessionManager::getUserSession(
2302
                        api_get_user_id(),
2303
                        $session_id
2304
                    );
2305
                    $userDuration = 0;
2306
                    if (isset($userDurationData['duration'])) {
2307
                        $userDuration = intval($userDurationData['duration']) * 24 * 60 * 60;
2308
                    }
2309
2310
                    $totalDuration = $firstAccess + $duration + $userDuration;
2311
                    if ($totalDuration > $currentTime) {
2312
                        return SESSION_AVAILABLE;
2313
                    } else {
2314
                        return SESSION_INVISIBLE;
2315
                    }
2316
                }
2317
2318
                return SESSION_AVAILABLE;
2319
            } else {
2320
2321
                // If start date was set.
2322
                if (!empty($row['access_start_date'])) {
2323
                    if ($now > api_strtotime($row['access_start_date'], 'UTC')) {
2324
                        $visibility = SESSION_AVAILABLE;
2325
                    } else {
2326
                        $visibility = SESSION_INVISIBLE;
2327
                    }
2328
                }
2329
2330
                // If the end date was set.
2331 View Code Duplication
                if (!empty($row['access_end_date'])) {
2332
                    // Only if date_start said that it was ok
2333
                    if ($visibility == SESSION_AVAILABLE) {
2334
                        if ($now < api_strtotime($row['access_end_date'], 'UTC')) {
2335
                            // Date still available
2336
                            $visibility = SESSION_AVAILABLE;
2337
                        } else {
2338
                            // Session ends
2339
                            $visibility = $row['visibility'];
2340
                        }
2341
                    }
2342
                }
2343
            }
2344
2345
            /* If I'm a coach the visibility can change in my favor depending in
2346
             the coach dates */
2347
            $is_coach = api_is_coach($session_id, $courseId);
2348
2349
            if ($is_coach) {
2350
                // Test end date.
2351 View Code Duplication
                if (!empty($row['coach_access_end_date'])) {
2352
                    $endDateCoach = api_strtotime($row['coach_access_end_date'], 'UTC');
2353
2354
                    if ($endDateCoach >= $now) {
2355
                        $visibility = SESSION_AVAILABLE;
2356
                    } else {
2357
                        $visibility = SESSION_INVISIBLE;
2358
                    }
2359
                }
2360
2361
                // Test start date.
2362 View Code Duplication
                if (!empty($row['coach_access_start_date'])) {
2363
                    $start = api_strtotime($row['coach_access_start_date'], 'UTC');
2364
                    if ($start < $now) {
2365
                        $visibility = SESSION_AVAILABLE;
2366
                    } else {
2367
                        $visibility = SESSION_INVISIBLE;
2368
                    }
2369
                }
2370
            }
2371
        } else {
2372
            $visibility = SESSION_INVISIBLE;
2373
        }
2374
    }
2375
2376
    return $visibility;
2377
}
2378
2379
/**
2380
 * This function returns a (star) session icon if the session is not null and
2381
 * the user is not a student
2382
 * @param int   $session_id
2383
 * @param int   $status_id User status id - if 5 (student), will return empty
2384
 * @return string   Session icon
2385
 */
2386
function api_get_session_image($session_id, $status_id)
2387
{
2388
    $session_id = (int)$session_id;
2389
    $session_img = '';
2390
    if ((int)$status_id != 5) { //check whether is not a student
2391
        if ($session_id > 0) {
2392
            $session_img = "&nbsp;&nbsp;".Display::return_icon(
2393
                'star.png',
2394
                get_lang('SessionSpecificResource'),
2395
                array('align' => 'absmiddle'),
2396
                ICON_SIZE_SMALL
2397
            );
2398
        }
2399
    }
2400
    return $session_img;
2401
}
2402
2403
/**
2404
 * This function add an additional condition according to the session of the course
2405
 * @param int       $session_id session id
2406
 * @param bool      $and optional, true if more than one condition false if the only condition in the query
2407
 * @param bool      $with_base_content optional, true to accept content with session=0 as well, false for strict session condition
2408
 * @return string   condition of the session
2409
 */
2410
function api_get_session_condition(
2411
    $session_id,
2412
    $and = true,
2413
    $with_base_content = false,
2414
    $session_field = "session_id"
2415
) {
2416
    $session_id = intval($session_id);
2417
2418
    if (empty($session_field)) {
2419
        $session_field = "session_id";
2420
    }
2421
    // Condition to show resources by session
2422
    $condition_add = $and ? " AND " : " WHERE ";
2423
2424
    if ($with_base_content) {
2425
        $condition_session = $condition_add." ( $session_field = $session_id OR $session_field = 0 OR $session_field IS NULL) ";
2426
    } else {
2427
        if (empty($session_id)) {
2428
            $condition_session = $condition_add." ($session_field = $session_id OR $session_field IS NULL)";
2429
        } else {
2430
            $condition_session = $condition_add." $session_field = $session_id ";
2431
        }
2432
    }
2433
    return $condition_session;
2434
}
2435
2436
/**
2437
 * This function returns information about coaches from a course in session
2438
 * @param int       optional, session id
2439
 * @param int $courseId
2440
 * @return array     array containing user_id, lastname, firstname, username
2441
 * @deprecated use CourseManager::get_coaches_from_course
2442
 */
2443
function api_get_coachs_from_course($session_id = 0, $courseId = '')
2444
{
2445
    if (!empty($session_id)) {
2446
        $session_id = intval($session_id);
2447
    } else {
2448
        $session_id = api_get_session_id();
2449
    }
2450
2451
    if (!empty($courseId)) {
2452
        $courseId = intval($courseId);
2453
    } else {
2454
        $courseId = api_get_course_int_id();
2455
    }
2456
2457
    $tbl_user = Database:: get_main_table(TABLE_MAIN_USER);
2458
    $tbl_session_course_user = Database:: get_main_table(TABLE_MAIN_SESSION_COURSE_USER);
2459
    $coaches = array();
2460
2461
    $sql = "SELECT
2462
                u.user_id,
2463
                u.lastname,
2464
                u.firstname,
2465
                u.username
2466
            FROM $tbl_user u, $tbl_session_course_user scu
2467
            WHERE
2468
              u.user_id = scu.user_id AND
2469
              scu.session_id = '$session_id' AND
2470
              scu.c_id = '$courseId' AND
2471
              scu.status = 2";
2472
    $rs = Database::query($sql);
2473
2474
    if (Database::num_rows($rs) > 0) {
2475
        while ($row = Database::fetch_array($rs)) {
2476
            $coaches[] = $row;
2477
        }
2478
2479
        return $coaches;
2480
    } else {
2481
2482
        return false;
2483
    }
2484
}
2485
2486
/**
2487
 * Returns the value of a setting from the web-adjustable admin config settings.
2488
 *
2489
 * WARNING true/false are stored as string, so when comparing you need to check e.g.
2490
 * if (api_get_setting('show_navigation_menu') == 'true') //CORRECT
2491
 * instead of
2492
 * if (api_get_setting('show_navigation_menu') == true) //INCORRECT
2493
 * @param string    $variable The variable name
2494
 * @param string    $key The subkey (sub-variable) if any. Defaults to NULL
2495
 * @author René Haentjens
2496
 * @author Bart Mollet
2497
 */
2498
function api_get_setting($variable, $key = null)
2499
{
2500
    global $_setting;
2501 View Code Duplication
    if ($variable == 'header_extra_content') {
2502
        $filename = api_get_path(SYS_PATH).api_get_home_path().'header_extra_content.txt';
2503
        if (file_exists($filename)) {
2504
            $value = file_get_contents($filename);
2505
            return $value ;
2506
        } else {
2507
            return '';
2508
        }
2509
    }
2510 View Code Duplication
    if ($variable == 'footer_extra_content') {
2511
        $filename = api_get_path(SYS_PATH).api_get_home_path().'footer_extra_content.txt';
2512
        if (file_exists($filename)) {
2513
            $value = file_get_contents($filename);
2514
            return $value ;
2515
        } else {
2516
            return '';
2517
        }
2518
    }
2519
    $value = null;
2520
    if (is_null($key)) {
2521
        $value = ((isset($_setting[$variable]) && $_setting[$variable] != '') ? $_setting[$variable] : null);
2522
    } else {
2523
        if (isset($_setting[$variable][$key])) {
2524
            $value = $_setting[$variable][$key];
2525
        }
2526
    }
2527
2528
    return $value;
2529
}
2530
2531
/**
2532
 * @param string $plugin
2533
 * @param string $variable
2534
 * @return string
2535
 */
2536
function api_get_plugin_setting($plugin, $variable)
2537
{
2538
    $variableName = $plugin.'_'.$variable;
2539
    $result = api_get_setting($variableName);
2540
    if (isset($result[$plugin])) {
2541
        return $result[$plugin];
2542
    }
2543
2544
    return null;
2545
}
2546
2547
/**
2548
 * Returns the value of a setting from the web-adjustable admin config settings.
2549
 **/
2550
function api_get_settings_params($params) {
2551
    $table = Database::get_main_table(TABLE_MAIN_SETTINGS_CURRENT);
2552
    $result = Database::select('*', $table, array('where' => $params));
2553
    return $result;
2554
}
2555
2556
function api_get_settings_params_simple($params) {
2557
    $table = Database::get_main_table(TABLE_MAIN_SETTINGS_CURRENT);
2558
    $result = Database::select('*', $table, array('where' => $params), 'one');
2559
    return $result;
2560
}
2561
2562
/**
2563
 * Returns the value of a setting from the web-adjustable admin config settings.
2564
 **/
2565
function api_delete_settings_params($params) {
2566
    $table = Database::get_main_table(TABLE_MAIN_SETTINGS_CURRENT);
2567
    $result = Database::delete($table, $params);
2568
    return $result;
2569
}
2570
2571
/**
2572
 * Returns an escaped version of $_SERVER['PHP_SELF'] to avoid XSS injection
2573
 * @return string   Escaped version of $_SERVER['PHP_SELF']
2574
 */
2575
function api_get_self() {
2576
    return htmlentities($_SERVER['PHP_SELF']);
2577
}
2578
2579
/* USER PERMISSIONS */
2580
2581
/**
2582
 * Checks whether current user is a platform administrator
2583
 * @param boolean Whether session admins should be considered admins or not
2584
 * @param boolean Whether HR directors should be considered admins or not
2585
 * @return boolean True if the user has platform admin rights,
2586
 * false otherwise.
2587
 * @see usermanager::is_admin(user_id) for a user-id specific function
2588
 */
2589
function api_is_platform_admin($allow_sessions_admins = false, $allow_drh = false)
2590
{
2591
    if (isset($_SESSION['is_platformAdmin']) && $_SESSION['is_platformAdmin']) {
2592
        return true;
2593
    }
2594
    $_user = api_get_user_info();
2595
    return
2596
        isset($_user['status']) &&
2597
        (
2598
            ($allow_sessions_admins && $_user['status'] == SESSIONADMIN) ||
2599
            ($allow_drh && $_user['status'] == DRH)
2600
        );
2601
}
2602
2603
/**
2604
 * Checks whether the user given as user id is in the admin table.
2605
 * @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...
2606
 * @param int $url URL ID. If provided, also check if the user is active on given URL
2607
 * @result bool True if the user is admin, false otherwise
2608
 */
2609
function api_is_platform_admin_by_id($user_id = null, $url = null)
2610
{
2611
    $user_id = intval($user_id);
2612
    if (empty($user_id)) {
2613
        $user_id = api_get_user_id();
2614
    }
2615
    $admin_table = Database::get_main_table(TABLE_MAIN_ADMIN);
2616
    $sql = "SELECT * FROM $admin_table WHERE user_id = $user_id";
2617
    $res = Database::query($sql);
2618
    $is_admin = Database::num_rows($res) === 1;
2619
    if (!$is_admin or !isset($url)) {
2620
        return $is_admin;
2621
    }
2622
    // We get here only if $url is set
2623
    $url = intval($url);
2624
    $url_user_table = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_USER);
2625
    $sql = "SELECT * FROM $url_user_table
2626
            WHERE access_url_id = $url AND user_id = $user_id";
2627
    $res = Database::query($sql);
2628
    $is_on_url = Database::num_rows($res) === 1;
2629
2630
    return $is_on_url;
2631
}
2632
2633
/**
2634
 * Returns the user's numeric status ID from the users table
2635
 * @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...
2636
 * @result int User's status (1 for teacher, 5 for student, etc)
2637
 */
2638
function api_get_user_status($user_id = null)
2639
{
2640
    $user_id = intval($user_id);
2641
    if (empty($user_id)) {
2642
        $user_id = api_get_user_id();
2643
    }
2644
    $table = Database::get_main_table(TABLE_MAIN_USER);
2645
    $sql = "SELECT status FROM $table WHERE user_id = $user_id ";
2646
    $result = Database::query($sql);
2647
    $status = null;
2648
    if (Database::num_rows($result)) {
2649
        $row = Database::fetch_array($result);
2650
        $status = $row['status'];
2651
    }
2652
    return $status;
2653
}
2654
2655
/**
2656
 * Checks whether current user is allowed to create courses
2657
 * @return boolean True if the user has course creation rights,
2658
 * false otherwise.
2659
 */
2660
function api_is_allowed_to_create_course() {
2661
    return Session::read('is_allowedCreateCourse');
2662
}
2663
2664
/**
2665
 * Checks whether the current user is a course administrator
2666
 * @return boolean True if current user is a course administrator
2667
 */
2668
function api_is_course_admin() {
2669
    if (api_is_platform_admin()) {
2670
        return true;
2671
    }
2672
    return Session::read('is_courseAdmin');
2673
}
2674
2675
/**
2676
 * Checks whether the current user is a course coach
2677
 * @return bool     True if current user is a course coach
2678
 */
2679
function api_is_course_coach() {
2680
    return Session::read('is_courseCoach');
2681
}
2682
2683
/**
2684
 * Checks whether the current user is a course tutor
2685
 * @return bool     True if current user is a course tutor
2686
 */
2687
function api_is_course_tutor() {
2688
    return Session::read('is_courseTutor');
2689
}
2690
2691
/**
2692
 * @param int $user_id
2693
 *
2694
 * @return array
2695
 */
2696
function api_get_user_platform_status($user_id = null) {
2697
    $status     = array();
2698
    $user_id    = intval($user_id);
2699
    if (empty($user_id)) {
2700
        $user_id = api_get_user_id();
2701
    }
2702
2703
    if (empty($user_id)) {
2704
        return false;
2705
    }
2706
    $group_id   = api_get_group_id();
2707
    $course_id  = api_get_course_int_id();
2708
    $course_code= api_get_course_id();
2709
    $session_id = api_get_session_id();
2710
2711
    //Group (in course)
2712
    if ($group_id && $course_id) {
2713
        $group_status = array();
2714
        $is_subscribed = GroupManager::is_subscribed($user_id, $group_id);
2715
        if ($is_subscribed) {
2716
            $group_status = array('id'=> $group_id , 'status' => 'student');
2717
            $is_tutor = GroupManager::is_tutor_of_group($user_id, $group_id);
2718
            if ($is_tutor) {
2719
                $group_status['status'] = 'tutor';
2720
            } else {
2721
                $group_status['status'] = 'student';
2722
            }
2723
        }
2724
        $status['group'] = $group_status;
2725
    }
2726
2727
    //Session
2728
    if ($session_id && $course_id) {
2729
        $session_status = array('id' => $session_id, 'course_id' => $course_id);
2730
        $session_user_status = SessionManager::get_user_status_in_course_session(
2731
            $user_id,
2732
            $course_id,
2733
            $session_id
2734
        );
2735
2736
        switch ($session_user_status) {
2737
            case 0:
2738
                $session_status['status'] = 'student';
2739
               break;
2740
            case 2:
2741
                $session_status['status'] = 'coach';
2742
            break;
2743
        }
2744
        $is_general_coach = SessionManager::user_is_general_coach($user_id, $session_id);
2745
        if ($is_general_coach) {
2746
            $session_status['status'] = 'general_coach';
2747
        }
2748
        $status['session'] = $session_status;
2749
2750
    } elseif($course_id) {
2751
        //Course
2752
        $course_status = array();
2753
        if ($course_id) {
2754
            $user_course_status = CourseManager::get_user_in_course_status($user_id, $course_code);
2755
2756
            if ($user_course_status) {
2757
                $course_status = array('id'=> $course_id);
2758
                switch($user_course_status) {
2759
                    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...
2760
                        $course_status['status'] = 'teacher';
2761
                    break;
2762
                    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...
2763
                        $course_status['status'] = 'student';
2764
                        //check if tutor
2765
                        $tutor_course_status = CourseManager::get_tutor_in_course_status($user_id, $course_code);
2766
                        if ($tutor_course_status) {
2767
                            $course_status['status'] = 'tutor';
2768
                        }
2769
                    break;
2770
                }
2771
            }
2772
        }
2773
        $status['course'] = $course_status;
2774
    }
2775
2776
    return $status;
2777
}
2778
2779
/**
2780
 * @param int $user_id
2781
 * @param int $courseId
2782
 * @param int $session_id
2783
 * @return bool
2784
 */
2785
function api_is_course_session_coach($user_id, $courseId, $session_id)
2786
{
2787
    $session_table = Database::get_main_table(TABLE_MAIN_SESSION);
2788
    $session_rel_course_rel_user_table  = Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER);
2789
2790
    $user_id = intval($user_id);
2791
    $session_id = intval($session_id);
2792
    $courseId = intval($courseId);
2793
2794
    $sql = "SELECT DISTINCT session.id
2795
            FROM $session_table
2796
            INNER JOIN $session_rel_course_rel_user_table session_rc_ru
2797
            ON session.id = session_rc_ru.session_id
2798
            WHERE
2799
                session_rc_ru.user_id = '".$user_id."'  AND
2800
                session_rc_ru.c_id = '$courseId' AND
2801
                session_rc_ru.status = 2 AND
2802
                session_rc_ru.session_id = '$session_id'";
2803
    $result = Database::query($sql);
2804
2805
    return Database::num_rows($result) > 0;
2806
}
2807
2808
/**
2809
 * Checks whether the current user is a course or session coach
2810
 * @param int $session_id
2811
 * @param int $courseId
2812
 * @param bool  Check whether we are in student view and, if we are, return false
2813
 * @return boolean True if current user is a course or session coach
2814
 */
2815
function api_is_coach($session_id = 0, $courseId = null, $check_student_view = true)
2816
{
2817
    $userId = api_get_user_id();
2818
2819
    if (!empty($session_id)) {
2820
        $session_id = intval($session_id);
2821
    } else {
2822
        $session_id = api_get_session_id();
2823
    }
2824
2825
    // The student preview was on
2826 View Code Duplication
    if ($check_student_view &&
2827
        isset($_SESSION['studentview']) && $_SESSION['studentview'] == "studentview"
2828
    ) {
2829
        return false;
2830
    }
2831
2832
    if (!empty($courseId)) {
2833
        $courseId = intval($courseId);
2834
    } else {
2835
        $courseId = api_get_course_int_id();
2836
    }
2837
2838
    $session_table = Database::get_main_table(TABLE_MAIN_SESSION);
2839
    $session_rel_course_rel_user_table = Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER);
2840
    $sessionIsCoach = null;
2841
2842
    if (!empty($courseId)) {
2843
        $sql = "SELECT DISTINCT s.id, name, access_start_date, access_end_date
2844
                FROM $session_table s
2845
                INNER JOIN $session_rel_course_rel_user_table session_rc_ru
2846
                ON session_rc_ru.session_id = s.id AND session_rc_ru.user_id = '".$userId."'
2847
                WHERE
2848
                    session_rc_ru.c_id = '$courseId' AND
2849
                    session_rc_ru.status = 2 AND
2850
                    session_rc_ru.session_id = '$session_id'";
2851
        $result = Database::query($sql);
2852
        $sessionIsCoach = Database::store_result($result);
2853
    }
2854
2855 View Code Duplication
    if (!empty($session_id)) {
2856
        $sql = "SELECT DISTINCT id, name, access_start_date, access_end_date
2857
                FROM $session_table
2858
                WHERE session.id_coach =  '".$userId."' AND id = '$session_id'
2859
                ORDER BY access_start_date, access_end_date, name";
2860
        $result = Database::query($sql);
2861
        if (!empty($sessionIsCoach)) {
2862
            $sessionIsCoach = array_merge($sessionIsCoach , Database::store_result($result));
2863
        } else {
2864
            $sessionIsCoach = Database::store_result($result);
2865
        }
2866
    }
2867
2868
    return (count($sessionIsCoach) > 0);
2869
}
2870
2871
/**
2872
 * Checks whether the current user is a session administrator
2873
 * @return boolean True if current user is a course administrator
2874
 */
2875
function api_is_session_admin()
2876
{
2877
    $user = api_get_user_info();
2878
    return isset($user['status']) && $user['status'] == SESSIONADMIN;
2879
}
2880
2881
/**
2882
 * Checks whether the current user is a human resources manager
2883
 * @return boolean True if current user is a human resources manager
2884
 */
2885
function api_is_drh()
2886
{
2887
    $user = api_get_user_info();
2888
    return isset($user['status']) && $user['status'] == DRH;
2889
}
2890
2891
/**
2892
 * Checks whether the current user is a student
2893
 * @return boolean True if current user is a human resources manager
2894
 */
2895
function api_is_student()
2896
{
2897
    $user = api_get_user_info();
2898
    return isset($user['status']) && $user['status'] == STUDENT;
2899
2900
}
2901
/**
2902
 * Checks whether the current user has the status 'teacher'
2903
 * @return boolean True if current user is a human resources manager
2904
 */
2905
function api_is_teacher()
2906
{
2907
    $user = api_get_user_info();
2908
    return isset($user['status']) && $user['status'] == COURSEMANAGER;
2909
}
2910
2911
/**
2912
 * Checks whether the current user is a invited user
2913
 * @return boolean
2914
 */
2915
function api_is_invitee()
2916
{
2917
    $user = api_get_user_info();
2918
2919
    return isset($user['status']) && $user['status'] == INVITEE;
2920
}
2921
2922
/**
2923
 * This function checks whether a session is assigned into a category
2924
 * @param int       - session id
2925
 * @param string    - category name
2926
 * @return bool     - true if is found, otherwise false
2927
 */
2928
function api_is_session_in_category($session_id, $category_name)
2929
{
2930
    $session_id = intval($session_id);
2931
    $category_name = Database::escape_string($category_name);
2932
2933
    $tbl_session = Database::get_main_table(TABLE_MAIN_SESSION);
2934
    $tbl_session_category = Database::get_main_table(TABLE_MAIN_SESSION_CATEGORY);
2935
2936
    $sql = "SELECT 1
2937
            FROM $tbl_session
2938
            WHERE $session_id IN (
2939
                SELECT s.id FROM $tbl_session s, $tbl_session_category sc
2940
                WHERE
2941
                  s.session_category_id = sc.id AND
2942
                  sc.name LIKE '%$category_name'
2943
            )";
2944
    $rs = Database::query($sql);
2945
2946
    if (Database::num_rows($rs) > 0) {
2947
        return true;
2948
    } else {
2949
        return false;
2950
    }
2951
}
2952
2953
/* DISPLAY OPTIONS
2954
   student view, title, message boxes,... */
2955
2956
/**
2957
 * Displays the title of a tool.
2958
 * Normal use: parameter is a string:
2959
 * api_display_tool_title("My Tool")
2960
 *
2961
 * Optionally, there can be a subtitle below
2962
 * the normal title, and / or a supra title above the normal title.
2963
 *
2964
 * e.g. supra title:
2965
 * group
2966
 * GROUP PROPERTIES
2967
 *
2968
 * e.g. subtitle:
2969
 * AGENDA
2970
 * calender & events tool
2971
 *
2972
 * @author Hugues Peeters <[email protected]>
2973
 * @param  mixed $title_element - it could either be a string or an array
2974
 *                               containing 'supraTitle', 'mainTitle',
2975
 *                               'subTitle'
2976
 * @return void
2977
 */
2978
function api_display_tool_title($title_element) {
2979
    if (is_string($title_element)) {
2980
        $tit = $title_element;
2981
        unset ($title_element);
2982
        $title_element['mainTitle'] = $tit;
2983
    }
2984
    echo '<h3>';
2985
    if (!empty($title_element['supraTitle'])) {
2986
        echo '<small>'.$title_element['supraTitle'].'</small><br />';
2987
    }
2988
    if (!empty($title_element['mainTitle'])) {
2989
        echo $title_element['mainTitle'];
2990
    }
2991
    if (!empty($title_element['subTitle'])) {
2992
        echo '<br /><small>'.$title_element['subTitle'].'</small>';
2993
    }
2994
    echo '</h3>';
2995
}
2996
2997
/**
2998
 * Displays options for switching between student view and course manager view
2999
 *
3000
 * Changes in version 1.2 (Patrick Cool)
3001
 * Student view switch now behaves as a real switch. It maintains its current state until the state
3002
 * is changed explicitly
3003
 *
3004
 * Changes in version 1.1 (Patrick Cool)
3005
 * student view now works correctly in subfolders of the document tool
3006
 * student view works correctly in the new links tool
3007
 *
3008
 * Example code for using this in your tools:
3009
 * //if ($is_courseAdmin && api_get_setting('student_view_enabled') == 'true') {
3010
 * //   display_tool_view_option($isStudentView);
3011
 * //}
3012
 * //and in later sections, use api_is_allowed_to_edit()
3013
 *
3014
 * @author Roan Embrechts
3015
 * @author Patrick Cool
3016
 * @author Julio Montoya, changes added in Chamilo
3017
 * @version 1.2
3018
 * @todo rewrite code so it is easier to understand
3019
 */
3020
function api_display_tool_view_option() {
3021
    if (api_get_setting('student_view_enabled') != 'true') {
3022
        return '';
3023
    }
3024
3025
    $sourceurl = '';
3026
    $is_framed = false;
3027
    // Exceptions apply for all multi-frames pages
3028
    if (strpos($_SERVER['REQUEST_URI'], 'chat/chat_banner.php') !== false) {
3029
        // The chat is a multiframe bit that doesn't work too well with the student_view, so do not show the link
3030
        return '';
3031
    }
3032
3033
    // Uncomment to remove student view link from document view page
3034
    if (strpos($_SERVER['REQUEST_URI'], 'newscorm/lp_header.php') !== false) {
3035
        if (empty($_GET['lp_id'])) {
3036
            return '';
3037
        }
3038
        $sourceurl = substr($_SERVER['REQUEST_URI'], 0, strpos($_SERVER['REQUEST_URI'], '?'));
3039
        $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);
3040
        //showinframes doesn't handle student view anyway...
3041
        //return '';
3042
        $is_framed = true;
3043
    }
3044
3045
    // Check whether the $_SERVER['REQUEST_URI'] contains already url parameters (thus a questionmark)
3046
    if (!$is_framed) {
3047
        if (strpos($_SERVER['REQUEST_URI'], '?') === false) {
3048
            $sourceurl = api_get_self().'?'.api_get_cidreq();
3049
        } else {
3050
            $sourceurl = $_SERVER['REQUEST_URI'];
3051
            //$sourceurl = str_replace('&', '&amp;', $sourceurl);
3052
        }
3053
    }
3054
3055
    $output_string = '';
3056
    if (!empty($_SESSION['studentview'])) {
3057
        if ($_SESSION['studentview'] == 'studentview') {
3058
            // We have to remove the isStudentView=true from the $sourceurl
3059
            $sourceurl = str_replace('&isStudentView=true', '', $sourceurl);
3060
            $sourceurl = str_replace('&isStudentView=false', '', $sourceurl);
3061
            $output_string .= '<a class="btn btn-success btn-xs" href="'.$sourceurl.'&isStudentView=false" target="_self">'.get_lang('SwitchToTeacherView').'</a>';
3062
        } elseif ($_SESSION['studentview'] == 'teacherview') {
3063
            // Switching to teacherview
3064
            $sourceurl = str_replace('&isStudentView=true', '', $sourceurl);
3065
            $sourceurl = str_replace('&isStudentView=false', '', $sourceurl);
3066
            $output_string .= '<a class="btn btn-primary btn-xs" href="'.$sourceurl.'&isStudentView=true" target="_self">'.get_lang('SwitchToStudentView').'</a>';
3067
        }
3068
    } else {
3069
        $output_string .= '<a class="btn btn-primary btn-xs" href="'.$sourceurl.'&isStudentView=true" target="_self">'.get_lang('SwitchToStudentView').'</a>';
3070
    }
3071
    return $output_string;
3072
}
3073
3074
// TODO: This is for the permission section.
3075
/**
3076
 * Function that removes the need to directly use is_courseAdmin global in
3077
 * tool scripts. It returns true or false depending on the user's rights in
3078
 * this particular course.
3079
 * Optionally checking for tutor and coach roles here allows us to use the
3080
 * student_view feature altogether with these roles as well.
3081
 * @param bool  Whether to check if the user has the tutor role
3082
 * @param bool  Whether to check if the user has the coach role
3083
 * @param bool  Whether to check if the user has the session coach role
3084
 * @param bool  check the student view or not
3085
 *
3086
 * @author Roan Embrechts
3087
 * @author Patrick Cool
3088
 * @author Julio Montoya
3089
 * @version 1.1, February 2004
3090
 * @return boolean, true: the user has the rights to edit, false: he does not
3091
 */
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...
3092
3093
function api_is_allowed_to_edit($tutor = false, $coach = false, $session_coach = false, $check_student_view = true)
3094
{
3095
    $my_session_id = api_get_session_id();
3096
    $is_allowed_coach_to_edit = api_is_coach(null, null, $check_student_view);
3097
    $session_visibility = api_get_session_visibility($my_session_id);
3098
3099
    // Admins can edit anything.
3100
    if (api_is_platform_admin(false)) {
3101
        //The student preview was on
3102 View Code Duplication
        if ($check_student_view &&
3103
            isset($_SESSION['studentview']) &&
3104
            $_SESSION['studentview'] == "studentview"
3105
        ) {
3106
            return false;
3107
        } else {
3108
            return true;
3109
        }
3110
    }
3111
3112
    $is_courseAdmin = api_is_course_admin();
3113
3114
    if (!$is_courseAdmin && $tutor) {
3115
        // If we also want to check if the user is a tutor...
3116
        $is_courseAdmin = $is_courseAdmin || api_is_course_tutor();
3117
    }
3118
3119
    if (!$is_courseAdmin && $coach) {
3120
        // If we also want to check if the user is a coach...';
3121
        // Check if session visibility is read only for coaches.
3122
        if ($session_visibility == SESSION_VISIBLE_READ_ONLY) {
3123
            $is_allowed_coach_to_edit = false;
3124
        }
3125
3126
        if (api_get_setting('allow_coach_to_edit_course_session') == 'true') {
3127
            // Check if coach is allowed to edit a course.
3128
            $is_courseAdmin = $is_courseAdmin || $is_allowed_coach_to_edit;
3129
        } else {
3130
            $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...
3131
        }
3132
    }
3133
3134
    if (!$is_courseAdmin && $session_coach) {
3135
        $is_courseAdmin = $is_courseAdmin || $is_allowed_coach_to_edit;
3136
    }
3137
3138
    // Check if the student_view is enabled, and if so, if it is activated.
3139
    if (api_get_setting('student_view_enabled') == 'true') {
3140
        if (!empty($my_session_id)) {
3141
            // Check if session visibility is read only for coaches.
3142
            if ($session_visibility == SESSION_VISIBLE_READ_ONLY) {
3143
                $is_allowed_coach_to_edit = false;
3144
            }
3145
3146
            if (api_get_setting('allow_coach_to_edit_course_session') == 'true') {
3147
                // Check if coach is allowed to edit a course.
3148
                $is_allowed = $is_allowed_coach_to_edit;
3149
            } else {
3150
                $is_allowed = false;
3151
            }
3152
            if ($check_student_view) {
3153
                $is_allowed = $is_allowed && $_SESSION['studentview'] != 'studentview';
3154
            }
3155
        } else {
3156
            if ($check_student_view) {
3157
                $is_allowed = $is_courseAdmin && $_SESSION['studentview'] != 'studentview';
3158
            } else {
3159
                $is_allowed = $is_courseAdmin;
3160
            }
3161
        }
3162
3163
        return $is_allowed;
3164
    } else {
3165
3166
        return $is_courseAdmin;
3167
    }
3168
}
3169
3170
/**
3171
* Checks if a student can edit contents in a session depending
3172
* on the session visibility
3173
* @param bool $tutor  Whether to check if the user has the tutor role
3174
* @param bool  $coach Whether to check if the user has the coach role
3175
* @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...
3176
*/
3177
function api_is_allowed_to_session_edit($tutor = false, $coach = false)
3178
{
3179
    if (api_is_allowed_to_edit($tutor, $coach)) {
3180
        // If I'm a teacher, I will return true in order to not affect the normal behaviour of Chamilo tools.
3181
        return true;
3182
    } else {
3183
        if (api_get_session_id() == 0) {
3184
            // I'm not in a session so i will return true to not affect the normal behaviour of Chamilo tools.
3185
            return true;
3186
        } else {
3187
            // I'm in a session and I'm a student
3188
            $session_id = api_get_session_id();
3189
3190
            // Get the session visibility
3191
            $session_visibility = api_get_session_visibility($session_id);
3192
            // if 5 the session is still available
3193
3194
            //@todo We could load the session_rel_course_rel_user permission to increase the level of detail.
3195
            //echo api_get_user_id();
3196
            //echo api_get_course_id();
3197
3198
            switch ($session_visibility) {
3199
                case SESSION_VISIBLE_READ_ONLY: // 1
3200
                    return false;
3201
                case SESSION_VISIBLE:           // 2
3202
                    return true;
3203
                case SESSION_INVISIBLE:         // 3
3204
                    return false;
3205
                case SESSION_AVAILABLE:         //5
3206
                    return true;
3207
            }
3208
3209
        }
3210
    }
3211
}
3212
3213
/**
3214
* Checks whether the user is allowed in a specific tool for a specific action
3215
* @param $tool the tool we are checking if the user has a certain permission
3216
* @param $action the action we are checking (add, edit, delete, move, visibility)
3217
* @author Patrick Cool <[email protected]>, Ghent University
3218
* @author Julio Montoya
3219
* @version 1.0
3220
*/
3221
function api_is_allowed($tool, $action, $task_id = 0)
3222
{
3223
    $_user = api_get_user_info();
3224
    $_course = api_get_course_info();
3225
3226
    if (api_is_course_admin()) {
3227
        return true;
3228
    }
3229
    //if (!$_SESSION['total_permissions'][$_course['code']] and $_course)
3230
    if (is_array($_course) and count($_course) > 0) {
3231
        require_once api_get_path(SYS_CODE_PATH).'permissions/permissions_functions.inc.php';
3232
3233
        // Getting the permissions of this user.
3234
        if ($task_id == 0) {
3235
            $user_permissions = get_permissions('user', $_user['user_id']);
3236
            $_SESSION['total_permissions'][$_course['code']] = $user_permissions;
3237
        }
3238
3239
        // Getting the permissions of the task.
3240
        if ($task_id != 0) {
3241
            $task_permissions = get_permissions('task', $task_id);
3242
            /* !!! */$_SESSION['total_permissions'][$_course['code']] = $task_permissions;
3243
        }
3244
        //print_r($_SESSION['total_permissions']);
3245
3246
        // Getting the permissions of the groups of the user
3247
        //$groups_of_user = GroupManager::get_group_ids($_course['db_name'], $_user['user_id']);
3248
3249
        //foreach($groups_of_user as $group)
3250
        //   $this_group_permissions = get_permissions('group', $group);
3251
3252
        // Getting the permissions of the courseroles of the user
3253
        $user_courserole_permissions = get_roles_permissions('user', $_user['user_id']);
3254
3255
        // Getting the permissions of the platformroles of the user
3256
        //$user_platformrole_permissions = get_roles_permissions('user', $_user['user_id'], ', platform');
3257
3258
        // Getting the permissions of the roles of the groups of the user
3259
        //foreach($groups_of_user as $group)
3260
        //    $this_group_courserole_permissions = get_roles_permissions('group', $group);
3261
3262
        // Getting the permissions of the platformroles of the groups of the user
3263
        //foreach($groups_of_user as $group)
3264
        //    $this_group_platformrole_permissions = get_roles_permissions('group', $group, 'platform');
3265
    }
3266
3267
    // If the permissions are limited, we have to map the extended ones to the limited ones.
3268
    if (api_get_setting('permissions') == 'limited') {
3269
        if ($action == 'Visibility') {
3270
            $action = 'Edit';
3271
        }
3272
        if ($action == 'Move') {
3273
            $action = 'Edit';
3274
        }
3275
    }
3276
3277
    // The session that contains all the permissions already exists for this course
3278
    // so there is no need to requery everything.
3279
    //my_print_r($_SESSION['total_permissions'][$_course['code']][$tool]);
3280
    if (is_array($_SESSION['total_permissions'][$_course['code']][$tool])) {
3281
        if (in_array($action, $_SESSION['total_permissions'][$_course['code']][$tool])) {
3282
            return true;
3283
        } else {
3284
            return false;
3285
        }
3286
    }
3287
}
3288
3289
/**
3290
 * Tells whether this user is an anonymous user
3291
 * @param int  $user_id      User ID (optional, will take session ID if not provided)
3292
 * @param bool $db_check     Whether to check in the database (true) or simply in
3293
 * the session (false) to see if the current user is the anonymous user
3294
 * @return bool     true if this user is anonymous, false otherwise
3295
 */
3296
function api_is_anonymous($user_id = null, $db_check = false) {
3297
    if (!isset($user_id)) {
3298
        $user_id = api_get_user_id();
3299
    }
3300
    if ($db_check) {
3301
        $info = api_get_user_info($user_id);
3302
        if ($info['status'] == ANONYMOUS) {
3303
            return true;
3304
        }
3305
    }
3306
3307
    $_user = api_get_user_info();
3308
    if (isset($_user['status']) && $_user['status'] == ANONYMOUS) {
3309
        //if ($_user['user_id'] == 0) {
3310
        // In some cases, api_set_anonymous doesn't seem to be triggered in local.inc.php. Make sure it is.
3311
        // Occurs in agenda for admin links - YW
3312
        global $use_anonymous;
3313
        if (isset($use_anonymous) && $use_anonymous) {
3314
            api_set_anonymous();
3315
        }
3316
3317
        return true;
3318
    }
3319
3320
    return ((isset($_user['is_anonymous']) && $_user['is_anonymous'] === true) || $_user === false);
3321
}
3322
3323
/**
3324
 * Displays message "You are not allowed here..." and exits the entire script.
3325
 * @param bool   $print_headers    Whether or not to print headers (default = false -> does not print them)
3326
 * @param string $message
3327
 */
3328
function api_not_allowed($print_headers = false, $message = null)
3329
{
3330
    if (api_get_setting('sso_authentication') === 'true') {
3331
        global $osso;
3332
        if ($osso) {
3333
            $osso->logout();
3334
        }
3335
    }
3336
    $home_url = api_get_path(WEB_PATH);
3337
    $user_id = api_get_user_id();
3338
    $course = api_get_course_id();
3339
3340
    global $this_section;
3341
3342
    if (CustomPages::enabled() && !isset($user_id)) {
3343
3344
        if (empty($user_id)) {
3345
            // Why the CustomPages::enabled() need to be to set the request_uri
3346
            $_SESSION['request_uri'] = $_SERVER['REQUEST_URI'];
3347
        }
3348
3349
        CustomPages::display(CustomPages::INDEX_UNLOGGED);
3350
    }
3351
3352
    $origin = isset($_GET['origin']) ? $_GET['origin'] : '';
3353
3354
    $msg = null;
3355
    if (isset($message)) {
3356
        $msg = $message;
3357 View Code Duplication
    } else {
3358
        $msg = Display::return_message(
3359
            get_lang('NotAllowedClickBack').'<br/><br/><a href="'.$home_url.'">'.get_lang('ReturnToCourseHomepage').'</a>',
3360
            'error',
3361
            false
3362
        );
3363
    }
3364
3365
    $msg = Display::div($msg, array('align'=>'center'));
3366
3367
    $show_headers = 0;
3368
3369
    if ($print_headers && $origin != 'learnpath') {
3370
        $show_headers = 1;
3371
    }
3372
3373
    $tpl = new Template(null, $show_headers, $show_headers);
3374
    $tpl->assign('hide_login_link', 1);
3375
    $tpl->assign('content', $msg);
3376
3377
    if (($user_id != 0 && !api_is_anonymous()) &&
3378
        (!isset($course) || $course == -1) &&
3379
        empty($_GET['cidReq'])
3380
    ) {
3381
        // if the access is not authorized and there is some login information
3382
        // but the cidReq is not found, assume we are missing course data and send the user
3383
        // to the user_portal
3384
        $tpl->display_one_col_template();
3385
        exit;
3386
    }
3387
3388
    if (!empty($_SERVER['REQUEST_URI']) &&
3389
        (!empty($_GET['cidReq']) ||
3390
            $this_section == SECTION_MYPROFILE ||
3391
            $this_section == SECTION_PLATFORM_ADMIN
3392
        )
3393
    ) {
3394
        $courseCode = api_get_course_id();
3395
        // Only display form and return to the previous URL if there was a course ID included
3396
        if ($user_id != 0 && !api_is_anonymous()) {
3397
            //if there is a user ID, then the user is not allowed but the session is still there. Say so and exit
3398
            $tpl->assign('content', $msg);
3399
            $tpl->display_one_col_template();
3400
            exit;
3401
        }
3402
3403
        if (!is_null($courseCode)) {
3404
            api_set_firstpage_parameter($courseCode);
3405
        }
3406
3407
        // If the user has no user ID, then his session has expired
3408
        $action = api_get_self().'?'.Security::remove_XSS($_SERVER['QUERY_STRING']);
3409
        $action = str_replace('&amp;', '&', $action);
3410
        $form = new FormValidator(
3411
            'formLogin',
3412
            'post',
3413
            $action,
3414
            null,
3415
            array(),
3416
            FormValidator::LAYOUT_BOX_NO_LABEL
3417
        );
3418
        $form->addElement('text', 'login', null, array('placeholder' => get_lang('UserName'), 'class' => 'autocapitalize_off'));
3419
        $form->addElement('password', 'password', null, array('placeholder' => get_lang('Password')));
3420
        $form->addButton('submitAuth', get_lang('LoginEnter'), '', 'primary');
3421
3422
        // see same text in auth/gotocourse.php and main_api.lib.php function api_not_allowed (above)
3423
        $content = Display::return_message(get_lang('NotAllowed'), 'error', false);
3424
3425
        if (!empty($courseCode)) {
3426
            $content .= '<h4>'.get_lang('LoginToGoToThisCourse').'</h4>';
3427
        }
3428
3429
        if (api_is_cas_activated()) {
3430
            $content .= Display::return_message(sprintf(get_lang('YouHaveAnInstitutionalAccount'), api_get_setting("Institution")), '', false);
3431
            $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'));
3432
            $content .= Display::return_message(get_lang('YouDontHaveAnInstitutionAccount'));
3433
            $content .= "<p style='text-align:center'><a href='#' onclick='$(this).parent().next().toggle()'>".get_lang('LoginWithExternalAccount')."</a></p>";
3434
            $content .= "<div style='display:none;'>";
3435
        }
3436
        $content .= '<div class="well_login">';
3437
        $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...
3438
        $content .='</div>';
3439
        if (api_is_cas_activated()) {
3440
            $content .= "</div>";
3441
        }
3442
3443
        if (!empty($courseCode)) {
3444
            $content .= '<hr/><p style="text-align:center"><a href="'.$home_url.'">'.
3445
                get_lang('ReturnToCourseHomepage').'</a></p>';
3446
        } else {
3447
            $content .= '<hr/><p style="text-align:center"><a href="'.$home_url.'">'.
3448
                get_lang('CampusHomepage').'</a></p>';
3449
        }
3450
3451
        $tpl->setLoginBodyClass();
3452
        $tpl->assign('content', $content);
3453
        $tpl->display_one_col_template();
3454
        exit;
3455
    }
3456
3457
    if ($user_id !=0 && !api_is_anonymous()) {
3458
        $tpl->display_one_col_template();
3459
        exit;
3460
    }
3461
3462
    $msg = null;
3463
3464
    // The session is over and we were not in a course,
3465
    // or we try to get directly to a private course without being logged
3466
    if (!is_null(api_get_course_int_id())) {
3467
        api_set_firstpage_parameter(api_get_course_id());
3468
        $tpl->setLoginBodyClass();
3469
        $action = api_get_self().'?'.Security::remove_XSS($_SERVER['QUERY_STRING']);
3470
        $action = str_replace('&amp;', '&', $action);
3471
        $form = new FormValidator('formLogin', 'post', $action, null, array('class'=>'form-stacked'));
3472
        $form->addElement('text', 'login', null, array('placeholder' => get_lang('UserName'), 'class' => 'col-md-3 autocapitalize_off')); //new
3473
        $form->addElement('password', 'password', null, array('placeholder' => get_lang('Password'), 'class' => 'col-md-3')); //new
3474
        $form->addButtonNext(get_lang('LoginEnter'), 'submitAuth');
3475
3476
        // see same text in auth/gotocourse.php and main_api.lib.php function api_not_allowed (bellow)
3477
        $msg = Display::return_message(get_lang('NotAllowed'), 'error', false);
3478
        $msg .= '<h4>'.get_lang('LoginToGoToThisCourse').'</h4>';
3479 View Code Duplication
        if (api_is_cas_activated()) {
3480
            $msg .= Display::return_message(sprintf(get_lang('YouHaveAnInstitutionalAccount'), api_get_setting("Institution")), '', false);
3481
            $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'));
3482
            $msg .= Display::return_message(get_lang('YouDontHaveAnInstitutionAccount'));
3483
            $msg .= "<p style='text-align:center'><a href='#' onclick='$(this).parent().next().toggle()'>".get_lang('LoginWithExternalAccount')."</a></p>";
3484
            $msg .= "<div style='display:none;'>";
3485
        }
3486
        $msg .= '<div class="well">';
3487
        $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...
3488
        $msg .='</div>';
3489
        if (api_is_cas_activated()) {
3490
            $msg .= "</div>";
3491
        }
3492
        $msg .= '<hr/><p style="text-align:center"><a href="'.$home_url.'">'.get_lang('ReturnToCourseHomepage').'</a></p>';
3493 View Code Duplication
    } else {
3494
        // we were not in a course, return to home page
3495
        $msg = Display::return_message(
3496
            get_lang('NotAllowed').'<br/><br/><a href="'.$home_url.'">'.get_lang('ReturnToCourseHomepage').'</a><br />',
3497
            'error',
3498
            false
3499
        );
3500
    }
3501
3502
    $tpl->assign('content', $msg);
3503
    $tpl->display_one_col_template();
3504
    exit;
3505
}
3506
3507
3508
/* WHAT'S NEW
3509
   functions for the what's new icons
3510
   in the user course list */
3511
3512
/**
3513
 * Gets a UNIX timestamp from a database (MySQL) datetime format string
3514
 * @param $last_post_datetime standard output date in a sql query
3515
 * @return unix timestamp
3516
 * @author Toon Van Hoecke <[email protected]>
3517
 * @version October 2003
3518
 * @desc convert sql date to unix timestamp
3519
 */
3520
function convert_sql_date($last_post_datetime) {
3521
    list ($last_post_date, $last_post_time) = explode(' ', $last_post_datetime);
3522
    list ($year, $month, $day) = explode('-', $last_post_date);
3523
    list ($hour, $min, $sec) = explode(':', $last_post_time);
3524
    return mktime((int)$hour, (int)$min, (int)$sec, (int)$month, (int)$day, (int)$year);
3525
}
3526
3527
/**
3528
 * Gets a database (MySQL) datetime format string from a UNIX timestamp
3529
 * @param   int     UNIX timestamp, as generated by the time() function. Will be generated if parameter not provided
3530
 * @return  string  MySQL datetime format, like '2009-01-30 12:23:34'
3531
 */
3532
function api_get_datetime($time = null) {
3533
    if (!isset($time)) { $time = time(); }
3534
    return date('Y-m-d H:i:s', $time);
3535
}
3536
3537
/**
3538
 * Gets item visibility from the item_property table
3539
 *
3540
 * Getting the visibility is done by getting the last updated visibility entry,
3541
 * using the largest session ID found if session 0 and another was found (meaning
3542
 * the only one that is actually from the session, in case there are results from
3543
 * session 0 *AND* session n).
3544
 * @param array     Course properties array (result of api_get_course_info())
3545
 * @param string    Tool (learnpath, document, etc)
3546
 * @param int       The item ID in the given tool
3547
 * @param int       The session ID (optional)
3548
 * @return int      -1 on error, 0 if invisible, 1 if visible
3549
 */
3550
function api_get_item_visibility(
3551
    $_course,
3552
    $tool,
3553
    $id,
3554
    $session = 0,
3555
    $user_id = null,
3556
    $type = null,
3557
    $group_id = null
3558
) {
3559
    if (!is_array($_course) || count($_course) == 0 || empty($tool) || empty($id)) {
3560
        return -1;
3561
    }
3562
3563
    $tool = Database::escape_string($tool);
3564
    $id = intval($id);
3565
    $session = (int) $session;
3566
    $TABLE_ITEMPROPERTY = Database::get_course_table(TABLE_ITEM_PROPERTY);
3567
    $course_id = intval($_course['real_id']);
3568
3569
    $userCondition = '';
3570
    if (!empty($user_id)) {
3571
        $user_id = intval($user_id);
3572
        $userCondition = " AND to_user_id = $user_id ";
3573
    }
3574
3575
    $typeCondition = '';
3576
    if (!empty($type)) {
3577
        $type = Database::escape_string($type);
3578
        $typeCondition = " AND lastedit_type = '$type' ";
3579
    }
3580
3581
    $groupCondition = '';
3582
    if (!empty($group_id)) {
3583
        $group_id = intval($group_id);
3584
        $groupCondition = " AND to_group_id = '$group_id' ";
3585
    }
3586
3587
    $sql = "SELECT visibility
3588
            FROM $TABLE_ITEMPROPERTY
3589
            WHERE
3590
                c_id = $course_id AND
3591
                tool = '$tool' AND
3592
                ref = $id AND
3593
                (session_id = $session OR session_id = 0 OR session_id IS NULL)
3594
                $userCondition $typeCondition $groupCondition
3595
            ORDER BY session_id DESC, lastedit_date DESC
3596
            LIMIT 1";
3597
3598
    $res = Database::query($sql);
3599
    if ($res === false || Database::num_rows($res) == 0) {
3600
        return -1;
3601
    }
3602
    $row = Database::fetch_array($res);
3603
3604
    return $row['visibility'];
3605
}
3606
3607
/**
3608
 * Delete a row in the c_item_property table
3609
 *
3610
 * @param array $courseInfo
3611
 * @param string $tool
3612
 * @param int $itemId
3613
 * @param int $userId
3614
 * @param int $groupId
3615
 * @param int $sessionId
3616
 * @return void
3617
 */
3618
function api_item_property_delete(
3619
    $courseInfo,
3620
    $tool,
3621
    $itemId,
3622
    $userId,
3623
    $groupId = 0,
3624
    $sessionId = 0
3625
) {
3626
    if (empty($courseInfo)) {
3627
        return false;
3628
    }
3629
3630
    $courseId = intval($courseInfo['real_id']);
3631
3632
    if (empty($courseId) || empty($tool) || empty($itemId)) {
3633
        return false;
3634
    }
3635
3636
    $table = Database::get_course_table(TABLE_ITEM_PROPERTY);
3637
    $tool = Database::escape_string($tool);
3638
    $itemId = intval($itemId);
3639
    $userId = intval($userId);
3640
    $groupId = intval($groupId);
3641
    $sessionId = intval($sessionId);
3642
3643
    $groupCondition = " AND to_group_id = $groupId ";
3644
    if (empty($groupId)) {
3645
        $groupCondition = " AND (to_group_id is NULL OR to_group_id = 0) ";
3646
    }
3647
3648
    $userCondition = " AND to_user_id = $userId ";
3649
    if (empty($userId)) {
3650
        $userCondition = " AND (to_user_id is NULL OR to_user_id = 0) ";
3651
    }
3652
    $sql = "DELETE FROM $table
3653
            WHERE
3654
                c_id = $courseId AND
3655
                tool  = '$tool' AND
3656
                ref = $itemId AND
3657
                session_id = $sessionId
3658
                $userCondition
3659
                $groupCondition
3660
            ";
3661
    Database::query($sql);
3662
}
3663
3664
/**
3665
 * Updates or adds item properties to the Item_propetry table
3666
 * Tool and lastedit_type are language independant strings (langvars->get_lang!)
3667
 *
3668
 * @param array $_course array with course properties
3669
 * @param string $tool tool id, linked to 'rubrique' of the course tool_list (Warning: language sensitive !!)
3670
 * @param int $item_id id of the item itself, linked to key of every tool ('id', ...), "*" = all items of the tool
3671
 * @param string $lastedit_type add or update action
0 ignored issues
show
Documentation introduced by
There is no parameter named $lastedit_type. Did you maybe mean $last_edit_type?

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

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

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

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

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

Loading history...
5736
 * @param bool $file_name
0 ignored issues
show
Documentation introduced by
There is no parameter named $file_name. Did you maybe mean $filename?

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...
5737
 *
5738
 * @return string
5739
 */
5740
function api_replace_dangerous_char($filename)
5741
{
5742
    return URLify::filter($filename, 250, '', true);
5743
5744
    /*
5745
    // Safe replacements for some non-letter characters.
5746
    static $search  = array(',', "\0", ' ', "\t", "\n", "\r", "\x0B", '/', "\\", '"', "'", '?', '*', '>', '<', '|', ':', '$', '(', ')', '^', '[', ']', '#', '+', '&', '%');
5747
    static $replace = array('_', '', '_', '_', '_', '_', '_', '-', '-', '-', '_', '-', '-', '-', '-', '-', '-', '-', '-', '-', '-', '-', '-', '-', '-', '-', '-');
5748
5749
    // Encoding detection.
5750
    $encoding = api_detect_encoding($filename);
5751
    // Converting html-entities into encoded characters.
5752
    $filename = api_html_entity_decode($filename, ENT_QUOTES, $encoding);
5753
    // Transliteration to ASCII letters, they are not dangerous for filesystems.
5754
    $filename = api_transliterate($filename, 'x', $encoding);
5755
5756
    // Trimming leading/trailing whitespace.
5757
    $filename = trim($filename);
5758
    // Trimming any leading/trailing dots.
5759
    $filename = trim($filename, '.');
5760
    $filename = trim($filename);
5761
5762
    // Replacing remaining dangerous non-letter characters.
5763
    $filename = str_replace($search, $replace, $filename);
5764
    if ($strict == 'strict') {
5765
        //$filename = str_replace('-', '_', $filename); // See task #1848.
5766
        //$filename = preg_replace('/[^0-9A-Za-z_.\-]/', '', $filename);
5767
        //Removing "_" character see BT#3628
5768
        $filename = preg_replace('/[^0-9A-Za-z.\-_]/', '', $filename);
5769
    }
5770
5771
    // Length is to be limited, so the file name to be acceptable by some operating systems.
5772
    $extension = (string)strrchr($filename, '.');
5773
    $extension_len = strlen($extension);
5774
    if ($extension_len > 0 && $extension_len < 250) {
5775
        $filename = substr($filename, 0, -$extension_len);
5776
        return substr($filename, 0, 250 - $extension_len).$extension;
5777
    }
5778
    return substr($filename, 0, 250);*/
5779
}
5780
5781
/**
5782
 * Fixes the $_SERVER['REQUEST_URI'] that is empty in IIS6.
5783
 * @author Ivan Tcholakov, 28-JUN-2006.
5784
 */
5785
function api_request_uri() {
5786
    if (!empty($_SERVER['REQUEST_URI'])) {
5787
        return $_SERVER['REQUEST_URI'];
5788
    }
5789
    $uri = $_SERVER['SCRIPT_NAME'];
5790
    if (!empty($_SERVER['QUERY_STRING'])) {
5791
        $uri .= '?'.$_SERVER['QUERY_STRING'];
5792
    }
5793
    $_SERVER['REQUEST_URI'] = $uri;
5794
    return $uri;
5795
}
5796
5797
5798
/** Gets the current access_url id of the Chamilo Platform
5799
 * @author Julio Montoya <[email protected]>
5800
 * @return int access_url_id of the current Chamilo Installation
5801
 */
5802
function api_get_current_access_url_id() {
5803
    $access_url_table = Database :: get_main_table(TABLE_MAIN_ACCESS_URL);
5804
    $path = Database::escape_string(api_get_path(WEB_PATH));
5805
    $sql = "SELECT id FROM $access_url_table WHERE url = '".$path."'";
5806
    $result = Database::query($sql);
5807
    if (Database::num_rows($result) > 0) {
5808
        $access_url_id = Database::result($result, 0, 0);
5809
        return $access_url_id;
5810
    }
5811
    //if the url in WEB_PATH was not found, it can only mean that there is
5812
    // either a configuration problem or the first URL has not been defined yet
5813
    // (by default it is http://localhost/). Thus the more sensible thing we can
5814
    // do is return 1 (the main URL) as the user cannot hack this value anyway
5815
    return 1;
5816
}
5817
5818
/**
5819
 * Gets the registered urls from a given user id
5820
 * @author Julio Montoya <[email protected]>
5821
 * @return int user id
5822
 */
5823
function api_get_access_url_from_user($user_id) {
5824
    $user_id = intval($user_id);
5825
    $table_url_rel_user = Database :: get_main_table(TABLE_MAIN_ACCESS_URL_REL_USER);
5826
    $table_url          = Database :: get_main_table(TABLE_MAIN_ACCESS_URL);
5827
    $sql = "SELECT access_url_id
5828
            FROM $table_url_rel_user url_rel_user
5829
            INNER JOIN $table_url u
5830
            ON (url_rel_user.access_url_id = u.id)
5831
            WHERE user_id = ".intval($user_id);
5832
    $result = Database::query($sql);
5833
    $url_list = array();
5834
    while ($row = Database::fetch_array($result, 'ASSOC')) {
5835
        $url_list[] = $row['access_url_id'];
5836
    }
5837
    return $url_list;
5838
}
5839
5840
/**
5841
 * Gets the status of a user in a course
5842
 * @param int       $user_id
5843
 * @param int    $courseId
5844
 * @return int      user status
5845
 */
5846
function api_get_status_of_user_in_course($user_id, $courseId)
5847
{
5848
    $tbl_rel_course_user = Database :: get_main_table(TABLE_MAIN_COURSE_USER);
5849
    if (!empty($user_id) && !empty($courseId)) {
5850
        $user_id        = intval($user_id);
5851
        $courseId    = intval($courseId);
5852
        $sql = 'SELECT status
5853
                FROM '.$tbl_rel_course_user.'
5854
                WHERE user_id='.$user_id.' AND c_id = '.$courseId;
5855
        $result = Database::query($sql);
5856
        $row_status = Database::fetch_array($result, 'ASSOC');
5857
        return $row_status['status'];
5858
    } else {
5859
        return 0;
5860
    }
5861
}
5862
5863
/**
5864
 * Checks whether the curent user is in a course or not.
5865
 *
5866
 * @param string        The course code - optional (takes it from session if not given)
5867
 * @return boolean
5868
 * @author Yannick Warnier <[email protected]>
5869
 */
5870
function api_is_in_course($course_code = null) {
5871
    if (isset($_SESSION['_course']['sysCode'])) {
5872
        if (!empty($course_code)) {
5873
            return $course_code == $_SESSION['_course']['sysCode'];
5874
        }
5875
        return true;
5876
    }
5877
    return false;
5878
}
5879
5880
/**
5881
 * Checks whether the curent user is in a group or not.
5882
 *
5883
 * @param string        The group id - optional (takes it from session if not given)
5884
 * @param string        The course code - optional (no additional check by course if course code is not given)
5885
 * @return boolean
5886
 * @author Ivan Tcholakov
5887
 */
5888
function api_is_in_group($groupIdParam = null, $courseCodeParam = null)
5889
{
5890
    if (!empty($courseCodeParam)) {
5891
        $courseCode = api_get_course_id();
5892
        if (!empty($courseCode)) {
5893
            if ($courseCodeParam != $courseCode) {
5894
                return false;
5895
            }
5896
        } else {
5897
            return false;
5898
        }
5899
    }
5900
5901
    $groupId = api_get_group_id();
5902
5903
    if (isset($groupId) && $groupId != '') {
5904
        if (!empty($groupIdParam)) {
5905
            return $groupIdParam == $groupId;
5906
        } else {
5907
            return true;
5908
        }
5909
    }
5910
5911
    return false;
5912
}
5913
5914
5915
/**
5916
 * Checks whether a secret key is valid
5917
 * @param string $original_key_secret  - secret key from (webservice) client
5918
 * @param string $security_key - security key from Chamilo
5919
 * @return boolean - true if secret key is valid, false otherwise
5920
 */
5921
function api_is_valid_secret_key($original_key_secret, $security_key) {
5922
    return $original_key_secret == sha1($security_key);
5923
}
5924
5925
/**
5926
 * Checks whether a user is into course
5927
 * @param int $course_id - the course id
5928
 * @param int $user_id - the user id
5929
 */
5930
function api_is_user_of_course($course_id, $user_id) {
5931
    $tbl_course_rel_user = Database::get_main_table(TABLE_MAIN_COURSE_USER);
5932
    $sql = 'SELECT user_id FROM '.$tbl_course_rel_user.'
5933
            WHERE
5934
                c_id ="'.intval($course_id).'" AND
5935
                user_id = "'.intval($user_id).'" AND
5936
                relation_type <> '.COURSE_RELATION_TYPE_RRHH.' ';
5937
    $result = Database::query($sql);
5938
    return Database::num_rows($result) == 1;
5939
}
5940
5941
/**
5942
 * Checks whether the server's operating system is Windows (TM).
5943
 * @return boolean - true if the operating system is Windows, false otherwise
5944
 */
5945
function api_is_windows_os() {
5946
    if (function_exists('php_uname')) {
5947
        // php_uname() exists as of PHP 4.0.2, according to the documentation.
5948
        // We expect that this function will always work for Chamilo 1.8.x.
5949
        $os = php_uname();
5950
    }
5951
    // The following methods are not needed, but let them stay, just in case.
5952
    elseif (isset($_ENV['OS'])) {
5953
        // Sometimes $_ENV['OS'] may not be present (bugs?)
5954
        $os = $_ENV['OS'];
5955
    }
5956
    elseif (defined('PHP_OS')) {
5957
        // PHP_OS means on which OS PHP was compiled, this is why
5958
        // using PHP_OS is the last choice for detection.
5959
        $os = PHP_OS;
5960
    } else {
5961
        return false;
5962
    }
5963
    return strtolower(substr((string)$os, 0, 3 )) == 'win';
5964
}
5965
5966
/**
5967
 * This function informs whether the sent request is XMLHttpRequest
5968
 */
5969
function api_is_xml_http_request() {
5970
    return isset($_SERVER['HTTP_X_REQUESTED_WITH']) && strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest';
5971
}
5972
5973
/**
5974
 * This wrapper function has been implemented for avoiding some known problems about the function getimagesize().
5975
 * @link http://php.net/manual/en/function.getimagesize.php
5976
 * @link http://www.dokeos.com/forum/viewtopic.php?t=12345
5977
 * @link http://www.dokeos.com/forum/viewtopic.php?t=16355
5978
 */
5979
function api_getimagesize($path) {
5980
    $image = new Image($path);
5981
    return $image->get_image_size();
5982
}
5983
5984
/**
5985
 * This function resizes an image, with preserving its proportions (or aspect ratio).
5986
 * @author Ivan Tcholakov, MAY-2009.
5987
 * @param int $image            System path or URL of the image
5988
 * @param int $target_width     Targeted width
5989
 * @param int $target_height    Targeted height
5990
 * @return array                Calculated new width and height
5991
 */
5992
function api_resize_image($image, $target_width, $target_height) {
5993
    $image_properties = api_getimagesize($image);
5994
    return api_calculate_image_size($image_properties['width'], $image_properties['height'], $target_width, $target_height);
5995
}
5996
5997
/**
5998
 * This function calculates new image size, with preserving image's proportions (or aspect ratio).
5999
 * @author Ivan Tcholakov, MAY-2009.
6000
 * @author The initial idea has been taken from code by Patrick Cool, MAY-2004.
6001
 * @param int $image_width      Initial width
6002
 * @param int $image_height     Initial height
6003
 * @param int $target_width     Targeted width
6004
 * @param int $target_height    Targeted height
6005
 * @return array                Calculated new width and height
6006
 */
6007
function api_calculate_image_size($image_width, $image_height, $target_width, $target_height) {
6008
    // Only maths is here.
6009
    $result = array('width' => $image_width, 'height' => $image_height);
6010
    if ($image_width <= 0 || $image_height <= 0) {
6011
        return $result;
6012
    }
6013
    $resize_factor_width = $target_width / $image_width;
6014
    $resize_factor_height = $target_height / $image_height;
6015
    $delta_width = $target_width - $image_width * $resize_factor_height;
6016
    $delta_height = $target_height - $image_height * $resize_factor_width;
6017
    if ($delta_width > $delta_height) {
6018
        $result['width'] = ceil($image_width * $resize_factor_height);
6019
        $result['height'] = ceil($image_height * $resize_factor_height);
6020
    }
6021
    elseif ($delta_width < $delta_height) {
6022
        $result['width'] = ceil($image_width * $resize_factor_width);
6023
        $result['height'] = ceil($image_height * $resize_factor_width);
6024
    }
6025
    else {
6026
        $result['width'] = ceil($target_width);
6027
        $result['height'] = ceil($target_height);
6028
    }
6029
    return $result;
6030
}
6031
6032
/**
6033
 * Returns a list of Chamilo's tools or
6034
 * checks whether a given identificator is a valid Chamilo's tool.
6035
 * @author Isaac flores paz
6036
 * @param string The tool name to filter
6037
 * @return mixed Filtered string or array
6038
 */
6039
function api_get_tools_lists($my_tool = null) {
6040
    $tools_list = array(
6041
        TOOL_DOCUMENT, TOOL_THUMBNAIL, TOOL_HOTPOTATOES,
6042
        TOOL_CALENDAR_EVENT, TOOL_LINK, TOOL_COURSE_DESCRIPTION, TOOL_SEARCH,
6043
        TOOL_LEARNPATH, TOOL_ANNOUNCEMENT, TOOL_FORUM, TOOL_THREAD, TOOL_POST,
6044
        TOOL_DROPBOX, TOOL_QUIZ, TOOL_USER, TOOL_GROUP, TOOL_BLOGS, TOOL_CHAT,
6045
        TOOL_CONFERENCE, TOOL_STUDENTPUBLICATION, TOOL_TRACKING, TOOL_HOMEPAGE_LINK,
6046
        TOOL_COURSE_SETTING, TOOL_BACKUP, TOOL_COPY_COURSE_CONTENT, TOOL_RECYCLE_COURSE,
6047
        TOOL_COURSE_HOMEPAGE, TOOL_COURSE_RIGHTS_OVERVIEW, TOOL_UPLOAD, TOOL_COURSE_MAINTENANCE,
6048
        TOOL_VISIO, TOOL_VISIO_CONFERENCE, TOOL_VISIO_CLASSROOM, TOOL_SURVEY, TOOL_WIKI,
6049
        TOOL_GLOSSARY, TOOL_GRADEBOOK, TOOL_NOTEBOOK, TOOL_ATTENDANCE, TOOL_COURSE_PROGRESS
6050
    );
6051
    if (empty($my_tool)) {
6052
        return $tools_list;
6053
    }
6054
    return in_array($my_tool, $tools_list) ? $my_tool : '';
6055
}
6056
6057
/**
6058
 * Checks whether we already approved the last version term and condition
6059
 * @param int user id
6060
 * @return bool true if we pass false otherwise
6061
 */
6062
function api_check_term_condition($user_id)
6063
{
6064
    if (api_get_setting('allow_terms_conditions') == 'true') {
6065
        //check if exists terms and conditions
6066
        if (LegalManager::count() == 0) {
6067
            return true;
6068
        }
6069
6070
        $extraFieldValue = new ExtraFieldValue('user');
6071
        $data = $extraFieldValue->get_values_by_handler_and_field_variable(
6072
            $user_id,
6073
            'legal_accept'
6074
        );
6075
6076
        if (!empty($data) && isset($data['value'])) {
6077
            $rowv = $data['value'];
6078
            $user_conditions = explode(':', $rowv);
6079
            $version = $user_conditions[0];
6080
            $lang_id = $user_conditions[1];
6081
            $real_version = LegalManager::get_last_version($lang_id);
6082
6083
            return $version >= $real_version;
6084
        }
6085
        return false;
6086
    }
6087
    return false;
6088
}
6089
6090
/**
6091
 * Gets all information of a tool into course
6092
 * @param int The tool id
6093
 * @return array
6094
 */
6095
function api_get_tool_information($tool_id) {
6096
    $t_tool = Database::get_course_table(TABLE_TOOL_LIST);
6097
    $course_id = api_get_course_int_id();
6098
    $sql = "SELECT * FROM $t_tool WHERE c_id = $course_id AND id = ".intval($tool_id);
6099
    $rs  = Database::query($sql);
6100
    return Database::fetch_array($rs);
6101
}
6102
6103
/**
6104
 * Gets all information of a tool into course
6105
 * @param int The tool id
6106
 * @return array
6107
 */
6108
function api_get_tool_information_by_name($name) {
6109
    $t_tool = Database::get_course_table(TABLE_TOOL_LIST);
6110
    $course_id = api_get_course_int_id();
6111
    $sql = "SELECT * FROM $t_tool
6112
            WHERE c_id = $course_id  AND name = '".Database::escape_string($name)."' ";
6113
    $rs  = Database::query($sql);
6114
    return Database::fetch_array($rs, 'ASSOC');
6115
}
6116
6117
/**
6118
 * @deprecated use api_trunc_str() instead.
6119
 */
6120
function shorten($input, $length = 15, $encoding = null) {
6121
    $length = intval($length);
6122
    if (!$length) {
6123
        $length = 15;
6124
    }
6125
    return api_trunc_str($input, $length, '...', false, $encoding);
6126
}
6127
6128
6129
/**
6130
 * Function used to protect a "global" admin script.
6131
 * The function blocks access when the user has no global platform admin rights.
6132
 * Global admins are the admins that are registered in the main.admin table
6133
 * AND the users who have access to the "principal" portal.
6134
 * That means that there is a record in the main.access_url_rel_user table
6135
 * with his user id and the access_url_id=1
6136
 *
6137
 * @author Julio Montoya
6138
 */
6139
function api_is_global_platform_admin($user_id = null)
6140
{
6141
    $user_id = intval($user_id);
6142
    if (empty($user_id)) {
6143
        $user_id = api_get_user_id();
6144
    }
6145
    if (api_is_platform_admin_by_id($user_id)) {
6146
        $urlList = api_get_access_url_from_user($user_id);
6147
        // The admin is registered in the first "main" site with access_url_id = 1
6148
        if (in_array(1, $urlList)) {
6149
            return true;
6150
        } else {
6151
            return false;
6152
        }
6153
    }
6154
    return false;
6155
}
6156
6157
/**
6158
 * @param int $admin_id_to_check
6159
 * @param int  $my_user_id
6160
 * @param bool $allow_session_admin
6161
 * @return bool
6162
 */
6163
function api_global_admin_can_edit_admin($admin_id_to_check, $my_user_id = null, $allow_session_admin = false)
6164
{
6165
    if (empty($my_user_id)) {
6166
        $my_user_id = api_get_user_id();
6167
    }
6168
6169
    $iam_a_global_admin = api_is_global_platform_admin($my_user_id);
6170
    $user_is_global_admin = api_is_global_platform_admin($admin_id_to_check);
6171
6172
    if ($iam_a_global_admin) {
6173
        // Global admin can edit everything
6174
        return true;
6175
    } else {
6176
        // If i'm a simple admin
6177
        $is_platform_admin = api_is_platform_admin_by_id($my_user_id);
6178
6179
        if ($allow_session_admin) {
6180
            $is_platform_admin = api_is_platform_admin_by_id($my_user_id) || (api_get_user_status($my_user_id) == SESSIONADMIN);
6181
        }
6182
6183
        if ($is_platform_admin) {
6184
            if ($user_is_global_admin) {
6185
                return false;
6186
            } else {
6187
                return true;
6188
            }
6189
        } else {
6190
            return false;
6191
        }
6192
    }
6193
}
6194
6195
/**
6196
 * @param int $admin_id_to_check
6197
 * @param int  $my_user_id
6198
 * @param bool $allow_session_admin
6199
 * @return bool
6200
 */
6201
function api_protect_super_admin($admin_id_to_check, $my_user_id = null, $allow_session_admin = false)
6202
{
6203
    if (api_global_admin_can_edit_admin($admin_id_to_check, $my_user_id, $allow_session_admin)) {
6204
        return true;
6205
    } else {
6206
        api_not_allowed();
6207
    }
6208
}
6209
6210
/**
6211
 * Function used to protect a global admin script.
6212
 * The function blocks access when the user has no global platform admin rights.
6213
 * See also the api_is_global_platform_admin() function wich defines who's a "global" admin
6214
 *
6215
 * @author Julio Montoya
6216
 */
6217
function api_protect_global_admin_script() {
6218
    if (!api_is_global_platform_admin()) {
6219
        api_not_allowed();
6220
        return false;
6221
    }
6222
    return true;
6223
}
6224
6225
/**
6226
 * Get active template
6227
 * @param string    theme type (optional: default)
6228
 * @param string    path absolute(abs) or relative(rel) (optional:rel)
6229
 * @return string   actived template path
6230
 */
6231
function api_get_template($path_type = 'rel') {
6232
    $path_types = array('rel', 'abs');
6233
    $template_path = '';
6234
    if (in_array($path_type, $path_types)) {
6235
        if ($path_type == 'rel') {
6236
            $template_path = api_get_path(SYS_TEMPLATE_PATH);
6237
        } else {
6238
            $template_path = api_get_path(WEB_TEMPLATE_PATH);
6239
        }
6240
    }
6241
    $actived_theme = 'default';
6242
    if (api_get_setting('active_template')) {
6243
        $actived_theme = api_get_setting('active_template');
6244
    }
6245
    $actived_theme_path = $template_path.$actived_theme.DIRECTORY_SEPARATOR;
6246
    return $actived_theme_path;
6247
}
6248
6249
/**
6250
 * Check browser support for type files
6251
 * This function check if the users browser support a file format or
6252
 * return the current browser and major ver when $format=check_browser
6253
 * @param string $format
6254
 *
6255
 * @return bool, or return text array if $format=check_browser
6256
 * @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...
6257
 */
6258
6259
function api_browser_support($format = "")
6260
{
6261
    $browser = new Browser();
6262
    $current_browser = $browser->getBrowser();
6263
    $a_versiontemp = explode('.', $browser->getVersion());
6264
    $current_majorver = $a_versiontemp[0];
6265
6266
    // Native svg support
6267
    if ($format == 'svg') {
6268
        if (($current_browser == 'Internet Explorer' && $current_majorver >= 9) ||
6269
            ($current_browser == 'Firefox' && $current_majorver > 1) ||
6270
            ($current_browser == 'Safari' && $current_majorver >= 4) ||
6271
            ($current_browser == 'Chrome' && $current_majorver >= 1) ||
6272
            ($current_browser == 'Opera' && $current_majorver >= 9)
6273
        ) {
6274
            return true;
6275
        } else {
6276
            return false;
6277
        }
6278
    } elseif ($format == 'pdf') {
6279
        //native pdf support
6280
        if ($current_browser == 'Chrome' && $current_majorver >= 6) {
6281
            return true;
6282
        } else {
6283
            return false;
6284
        }
6285
    } elseif ($format == 'tif' || $format == 'tiff') {
6286
        //native tif support
6287
        if ($current_browser == 'Safari' && $current_majorver >= 5) {
6288
            return true;
6289
        } else {
6290
            return false;
6291
        }
6292 View Code Duplication
    } elseif ($format == 'ogg' || $format == 'ogx' || $format == 'ogv' || $format == 'oga') {
6293
        //native ogg, ogv,oga support
6294
        if (($current_browser == 'Firefox' && $current_majorver >= 3) ||
6295
            ($current_browser == 'Chrome' && $current_majorver >= 3) ||
6296
            ($current_browser == 'Opera' && $current_majorver >= 9)) {
6297
            return true;
6298
        } else {
6299
            return false;
6300
        }
6301
    } elseif ($format == 'mpg' || $format == 'mpeg') {
6302
        //native mpg support
6303
        if (($current_browser == 'Safari' && $current_majorver >= 5)) {
6304
            return true;
6305
        } else {
6306
            return false;
6307
        }
6308
    } elseif ($format == 'mp4') {
6309
        //native mp4 support (TODO: Android, iPhone)
6310
        if ($current_browser == 'Android' || $current_browser == 'iPhone') {
6311
            return true;
6312
        } else {
6313
            return false;
6314
        }
6315
    } elseif ($format == 'mov') {
6316
        //native mov support( TODO:check iPhone)
6317
        if ($current_browser == 'Safari' && $current_majorver >= 5 || $current_browser == 'iPhone') {
6318
            return true;
6319
        } else {
6320
            return false;
6321
        }
6322
    } elseif ($format == 'avi') {
6323
        //native avi support
6324
        if ($current_browser == 'Safari' && $current_majorver >= 5) {
6325
            return true;
6326
        } else {
6327
            return false;
6328
        }
6329
    } elseif ($format == 'wmv') {
6330
        //native wmv support
6331
        if ($current_browser == 'Firefox' && $current_majorver >= 4) {
6332
            return true;
6333
        } else {
6334
            return false;
6335
        }
6336 View Code Duplication
    } elseif ($format == 'webm') {
6337
        //native webm support (TODO:check IE9, Chrome9, Android)
6338
        if (($current_browser == 'Firefox' && $current_majorver >= 4) ||
6339
            ($current_browser == 'Opera' && $current_majorver >= 9) ||
6340
            ($current_browser == 'Internet Explorer' && $current_majorver >= 9) ||
6341
            ($current_browser == 'Chrome' && $current_majorver >= 9) ||
6342
            $current_browser == 'Android'
6343
        ) {
6344
            return true;
6345
        } else {
6346
            return false;
6347
        }
6348
    } elseif ($format == 'wav') {
6349
        //native wav support (only some codecs !)
6350
        if (($current_browser == 'Firefox' && $current_majorver >= 4) ||
6351
            ($current_browser == 'Safari' && $current_majorver >= 5) ||
6352
            ($current_browser == 'Opera' && $current_majorver >= 9) ||
6353
            ($current_browser == 'Internet Explorer' && $current_majorver >= 9) ||
6354
            ($current_browser == 'Chrome' && $current_majorver > 9) ||
6355
            $current_browser == 'Android' ||
6356
            $current_browser == 'iPhone'
6357
        ) {
6358
            return true;
6359
        } else {
6360
            return false;
6361
        }
6362
    } elseif ($format == 'mid' || $format == 'kar') {
6363
        //native midi support (TODO:check Android)
6364
        if ($current_browser == 'Opera' && $current_majorver >= 9 || $current_browser == 'Android') {
6365
            return true;
6366
        } else {
6367
            return false;
6368
        }
6369
    } elseif ($format == 'wma') {
6370
        //native wma support
6371
        if ($current_browser == 'Firefox' && $current_majorver >= 4) {
6372
            return true;
6373
        } else {
6374
            return false;
6375
        }
6376
    } elseif ($format == 'au') {
6377
        //native au support
6378
        if ($current_browser == 'Safari' && $current_majorver >= 5) {
6379
            return true;
6380
        } else {
6381
            return false;
6382
        }
6383 View Code Duplication
    } elseif ($format == 'mp3') {
6384
        //native mp3 support (TODO:check Android, iPhone)
6385
        if (($current_browser == 'Safari' && $current_majorver >= 5) ||
6386
            ($current_browser == 'Chrome' && $current_majorver >= 6) ||
6387
            ($current_browser == 'Internet Explorer' && $current_majorver >= 9) ||
6388
            $current_browser == 'Android' ||
6389
            $current_browser == 'iPhone' ||
6390
            $current_browser == 'Firefox'
6391
        ) {
6392
            return true;
6393
        } else {
6394
            return false;
6395
        }
6396
    } elseif ($format == "check_browser") {
6397
        $array_check_browser = array($current_browser, $current_majorver);
6398
        return $array_check_browser;
6399
    } else {
6400
        return false;
6401
    }
6402
}
6403
6404
/**
6405
 * This function checks if exist path and file browscap.ini
6406
 * In order for this to work, your browscap configuration setting in php.ini
6407
 * must point to the correct location of the browscap.ini file on your system
6408
 * http://php.net/manual/en/function.get-browser.php
6409
 *
6410
 * @return bool
6411
 *
6412
 * @author Juan Carlos Raña Trabado
6413
 */
6414
function api_check_browscap() {
6415
    $setting = ini_get('browscap');
6416
    if ($setting) {
6417
        $browser = get_browser($_SERVER['HTTP_USER_AGENT'], true);
6418
        if (strpos($setting, 'browscap.ini') && !empty($browser)) {
6419
            return true;
6420
        }
6421
    }
6422
    return false;
6423
}
6424
6425
/**
6426
 * Returns the <script> HTML tag
6427
 */
6428
function api_get_js($file) {
6429
    return '<script type="text/javascript" src="'.api_get_path(WEB_LIBRARY_PATH).'javascript/'.$file.'"></script>'."\n";
6430
}
6431
6432
/**
6433
 * Returns the <script> HTML tag
6434
 */
6435
function api_get_asset($file) {
6436
    return '<script type="text/javascript" src="'.api_get_path(WEB_PATH).'web/assets/'.$file.'"></script>'."\n";
6437
}
6438
6439
/**
6440
 * Returns the <link> HTML tag
6441
 */
6442
function api_get_css($file, $media = 'screen') {
6443
    return '<link href="'.$file.'" rel="stylesheet" media="'.$media.'" type="text/css" />'."\n";
6444
}
6445
6446
/**
6447
 * Returns the js header to include the jquery library
6448
 */
6449
function api_get_jquery_js()
6450
{
6451
    return api_get_asset('jquery/dist/jquery.min.js');
6452
}
6453
6454
/**
6455
 * Returns the jquery path
6456
 * @return string
6457
 */
6458
function api_get_jquery_web_path()
6459
{
6460
    return api_get_path(WEB_PATH).'web/assets/jquery/dist/jquery.min.js';
6461
}
6462
6463
/**
6464
 * @return string
6465
 */
6466
function api_get_jquery_ui_js_web_path()
6467
{
6468
    return api_get_path(WEB_PATH).'web/assets/jquery-ui/jquery-ui.min.js';
6469
}
6470
6471
/**
6472
 * @return string
6473
 */
6474
function api_get_jquery_ui_css_web_path()
6475
{
6476
    return api_get_path(WEB_PATH).'web/assets/jquery-ui/themes/smoothness/jquery-ui.min.css';
6477
}
6478
6479
/**
6480
 * Returns the jquery-ui library js headers
6481
 * @param   bool    add the jqgrid library
6482
 * @return  string  html tags
6483
 *
6484
 */
6485
function api_get_jquery_ui_js($include_jqgrid = false) {
6486
    $libraries = array();
6487
    if ($include_jqgrid) {
6488
       $libraries[]='jqgrid';
6489
    }
6490
    return api_get_jquery_libraries_js($libraries);
6491
}
6492
6493
function api_get_jqgrid_js() {
6494
    return api_get_jquery_libraries_js(array('jqgrid'));
6495
}
6496
6497
6498
/**
6499
 * Returns the jquery library js and css headers
6500
 *
6501
 * @param   array   list of jquery libraries supported jquery-ui, jqgrid
6502
 * @param   bool    add the jquery library
6503
 * @return  string  html tags
6504
 *
6505
 */
6506
function api_get_jquery_libraries_js($libraries) {
6507
    $js = '';
6508
    $js_path = api_get_path(WEB_LIBRARY_PATH).'javascript/';
6509
6510
    //jqgrid js and css
6511
    if (in_array('jqgrid', $libraries)) {
6512
        $languaje   = 'en';
6513
        $platform_isocode = strtolower(api_get_language_isocode());
6514
6515
        //languages supported by jqgrid see files in main/inc/lib/javascript/jqgrid/js/i18n
6516
        $jqgrid_langs = array(
6517
            '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'
6518
        );
6519
6520
        if (in_array($platform_isocode, $jqgrid_langs)) {
6521
            $languaje = $platform_isocode;
6522
        }
6523
        //$js .= '<link rel="stylesheet" href="'.$js_path.'jqgrid/css/ui.jqgrid.css" type="text/css">';
6524
        $js .= api_get_css($js_path.'jqgrid/css/ui.jqgrid.css');
6525
        $js .= api_get_js('jqgrid/js/i18n/grid.locale-'.$languaje.'.js');
6526
        $js .= api_get_js('jqgrid/js/jquery.jqGrid.min.js');
6527
    }
6528
6529
    //Document multiple upload funcionality
6530
    if (in_array('jquery-upload', $libraries)) {
6531
6532
        $js .= api_get_asset('blueimp-load-image/js/load-image.all.min.js');
6533
        $js .= api_get_asset('blueimp-canvas-to-blob/js/canvas-to-blob.min.js');
6534
        $js .= api_get_asset('jquery-file-upload/js/jquery.iframe-transport.js');
6535
        $js .= api_get_asset('jquery-file-upload/js/jquery.fileupload.js');
6536
        $js .= api_get_asset('jquery-file-upload/js/jquery.fileupload-process.js');
6537
        $js .= api_get_asset('jquery-file-upload/js/jquery.fileupload-image.js');
6538
        $js .= api_get_asset('jquery-file-upload/js/jquery.fileupload-audio.js');
6539
        $js .= api_get_asset('jquery-file-upload/js/jquery.fileupload-video.js');
6540
        $js .= api_get_asset('jquery-file-upload/js/jquery.fileupload-validate.js');
6541
6542
        $js .= api_get_css(api_get_path(WEB_PATH).'web/assets/jquery-file-upload/css/jquery.fileupload.css');
6543
        $js .= api_get_css(api_get_path(WEB_PATH).'web/assets/jquery-file-upload/css/jquery.fileupload-ui.css');
6544
    }
6545
6546
    // jquery datepicker
6547
    if (in_array('datepicker', $libraries)) {
6548
        $languaje   = 'en-GB';
6549
        $platform_isocode = strtolower(api_get_language_isocode());
6550
6551
        // languages supported by jqgrid see files in main/inc/lib/javascript/jqgrid/js/i18n
6552
        $datapicker_langs = array(
6553
            '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'
6554
        );
6555
        if (in_array($platform_isocode, $datapicker_langs)) {
6556
            $languaje = $platform_isocode;
6557
        }
6558
6559
        $js .= api_get_js('jquery-ui/jquery-ui-i18n.min.js');
6560
        $script = '<script>
6561
        $(function(){
6562
            $.datepicker.setDefaults($.datepicker.regional["'.$languaje.'"]);
6563
            $.datepicker.regional["local"] = $.datepicker.regional["'.$languaje.'"];
6564
        });
6565
        </script>
6566
        ';
6567
        $js .= $script;
6568
    }
6569
    return $js;
6570
}
6571
6572
/**
6573
 * Returns the course's URL
6574
 *
6575
 * This function relies on api_get_course_info()
6576
 * @param   string  The course code - optional (takes it from session if not given)
6577
 * @param   int     The session id  - optional (takes it from session if not given)
6578
 * @return  mixed   The URL of the course or null if something does not work
6579
 * @author  Julio Montoya <[email protected]>
6580
 */
6581
function api_get_course_url($course_code = null, $session_id = null)
6582
{
6583
    if (empty($course_code)) {
6584
        $course_info = api_get_course_info();
6585
    } else {
6586
        $course_info = api_get_course_info($course_code);
6587
    }
6588
    if (empty($session_id)) {
6589
        $session_url = '?id_session='.api_get_session_id();
6590
    } else {
6591
        $session_url = '?id_session='.intval($session_id);
6592
    }
6593
    /*
6594
    if (empty($group_id)) {
6595
        $group_url = '&gidReq='.api_get_group_id();
6596
    } else {
6597
        $group_url = '&gidReq='.intval($group_id);
6598
    }*/
6599
    if (!empty($course_info['path'])) {
6600
        return api_get_path(WEB_COURSE_PATH).$course_info['path'].'/index.php'.$session_url;
6601
    }
6602
    return null;
6603
}
6604
6605
/**
6606
 *
6607
 * Check if the current portal has the $_configuration['multiple_access_urls'] parameter on
6608
 * @return bool true if multi site is enabled
6609
 *
6610
 * */
6611
function api_get_multiple_access_url() {
6612
    global $_configuration;
6613
    if (isset($_configuration['multiple_access_urls']) && $_configuration['multiple_access_urls']) {
6614
        return true;
6615
    }
6616
    return false;
6617
}
6618
6619
/**
6620
 * @return bool
6621
 */
6622
function api_is_multiple_url_enabled() {
6623
    return api_get_multiple_access_url();
6624
}
6625
6626
/**
6627
 * Returns a md5 unique id
6628
 * @todo add more parameters
6629
 */
6630
function api_get_unique_id() {
6631
    $id = md5(time().uniqid().api_get_user_id().api_get_course_id().api_get_session_id());
6632
    return $id;
6633
}
6634
6635
/**
6636
 * Get home path
6637
 * @return string
6638
 */
6639
function api_get_home_path()
6640
{
6641
    $home = 'app/home/';
6642
    if (api_get_multiple_access_url()) {
6643
        $access_url_id = api_get_current_access_url_id();
6644
        $url_info = api_get_access_url($access_url_id);
6645
        $url = api_remove_trailing_slash(preg_replace('/https?:\/\//i', '', $url_info['url']));
6646
        $clean_url = api_replace_dangerous_char($url);
6647
        $clean_url = str_replace('/', '-', $clean_url);
6648
        $clean_url .= '/';
6649
6650
        $home = 'app/home/' . $clean_url;
6651
    }
6652
6653
    return $home;
6654
}
6655
6656
/**
6657
 *
6658
 * @param int Course id
6659
 * @param int tool id: TOOL_QUIZ, TOOL_FORUM, TOOL_STUDENTPUBLICATION, TOOL_LEARNPATH
6660
 * @param int the item id (tool id, exercise id, lp id)
6661
 *
6662
 */
6663
function api_resource_is_locked_by_gradebook($item_id, $link_type, $course_code = null) {
6664
    if (api_is_platform_admin()) {
6665
        return false;
6666
    }
6667
    if (api_get_setting('gradebook_locking_enabled') == 'true') {
6668
        if (empty($course_code)) {
6669
            $course_code = api_get_course_id();
6670
        }
6671
        $table = Database::get_main_table(TABLE_MAIN_GRADEBOOK_LINK);
6672
        $item_id = intval($item_id);
6673
        $link_type = intval($link_type);
6674
        $course_code = Database::escape_string($course_code);
6675
        $sql = "SELECT locked FROM $table
6676
                WHERE locked = 1 AND ref_id = $item_id AND type = $link_type AND course_code = '$course_code' ";
6677
        $result = Database::query($sql);
6678
        if (Database::num_rows($result)) {
6679
            return true;
6680
        }
6681
    }
6682
    return false;
6683
}
6684
6685
/**
6686
 * Blocks a page if the item was added in a gradebook
6687
 *
6688
 * @param int       exercise id, work id, thread id,
6689
 * @param int       LINK_EXERCISE, LINK_STUDENTPUBLICATION, LINK_LEARNPATH LINK_FORUM_THREAD, LINK_ATTENDANCE
6690
 * see gradebook/lib/be/linkfactory
6691
 * @param string    course code
6692
 * @return boolean
6693
 */
6694
function api_block_course_item_locked_by_gradebook($item_id, $link_type, $course_code = null) {
6695
    if (api_is_platform_admin()) {
6696
        return false;
6697
    }
6698
6699
    if (api_resource_is_locked_by_gradebook($item_id, $link_type, $course_code)) {
6700
        $message = Display::return_message(get_lang('ResourceLockedByGradebook'), 'warning');
6701
        api_not_allowed(true, $message);
6702
    }
6703
}
6704
/**
6705
 * Checks the PHP version installed is enough to run Chamilo
6706
 * @param string Include path (used to load the error page)
6707
 * @return void
6708
 */
6709
function api_check_php_version($my_inc_path = null) {
6710
    if (!function_exists('version_compare') || version_compare( phpversion(), REQUIRED_PHP_VERSION, '<')) {
6711
        $global_error_code = 1;
6712
        // Incorrect PHP version
6713
        $global_page = $my_inc_path.'global_error_message.inc.php';
6714
        if (file_exists($global_page)) {
6715
            require $global_page;
6716
        }
6717
        exit;
6718
    }
6719
}
6720
/**
6721
 * Checks whether the Archive directory is present and writeable. If not,
6722
 * prints a warning message.
6723
 */
6724
function api_check_archive_dir() {
6725 View Code Duplication
    if (is_dir(api_get_path(SYS_ARCHIVE_PATH)) && !is_writable(api_get_path(SYS_ARCHIVE_PATH))) {
6726
        $message = Display::return_message(get_lang('ArchivesDirectoryNotWriteableContactAdmin'),'warning');
6727
        api_not_allowed(true, $message);
6728
    }
6729
}
6730
/**
6731
 * Returns an array of global configuration settings which should be ignored
6732
 * when printing the configuration settings screens
6733
 * @return array Array of strings, each identifying one of the excluded settings
6734
 */
6735
function api_get_locked_settings() {
6736
    return array(
6737
        'server_type',
6738
        'permanently_remove_deleted_files',
6739
        'account_valid_duration',
6740
        'service_visio',
6741
        'service_ppt2lp',
6742
        'wcag_anysurfer_public_pages',
6743
        'upload_extensions_list_type',
6744
        'upload_extensions_blacklist',
6745
        'upload_extensions_whitelist',
6746
        'upload_extensions_skip',
6747
        'upload_extensions_replace_by',
6748
        'hide_dltt_markup',
6749
        'split_users_upload_directory',
6750
        'permissions_for_new_directories',
6751
        'permissions_for_new_files',
6752
        'platform_charset',
6753
        'service_visio',
6754
        'ldap_description',
6755
        'cas_activate',
6756
        'cas_server',
6757
        'cas_server_uri',
6758
        'cas_port',
6759
        'cas_protocol',
6760
        'cas_add_user_activate',
6761
        'update_user_info_cas_with_ldap',
6762
        'languagePriority1',
6763
        'languagePriority2',
6764
        'languagePriority3',
6765
        'languagePriority4',
6766
        'login_is_email',
6767
        'chamilo_database_version'
6768
    );
6769
}
6770
6771
/**
6772
 * Checks if the user is corrently logged in. Returns the user ID if he is, or
6773
 * false if he isn't. If the user ID is given and is an integer, then the same
6774
 * ID is simply returned
6775
 * @param  integer User ID
6776
 * @return mixed Integer User ID is logged in, or false otherwise
6777
 */
6778
function api_user_is_login($user_id = null) {
6779
    $user_id = empty($user_id) ? api_get_user_id() : intval($user_id);
6780
    return $user_id && !api_is_anonymous();
6781
}
6782
6783
/**
6784
 * Guess the real ip for register in the database, even in reverse proxy cases.
6785
 * To be recognized, the IP has to be found in either $_SERVER['REMOTE_ADDR'] or
6786
 * in $_SERVER['HTTP_X_FORWARDED_FOR'], which is in common use with rproxies.
6787
 * @return string the user's real ip (unsafe - escape it before inserting to db)
6788
 * @author Jorge Frisancho Jibaja <[email protected]>, USIL - Some changes to allow the use of real IP using reverse proxy
6789
 * @version CEV CHANGE 24APR2012
6790
 */
6791
function api_get_real_ip(){
6792
    // Guess the IP if behind a reverse proxy
6793
    global $debug;
6794
    $ip = trim($_SERVER['REMOTE_ADDR']);
6795
    if (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) {
6796
        if (preg_match('/,/', $_SERVER['HTTP_X_FORWARDED_FOR'])) {
6797
            @list($ip1, $ip2) = @explode(',', $_SERVER['HTTP_X_FORWARDED_FOR']);
6798
        } else {
6799
            $ip1 = $_SERVER['HTTP_X_FORWARDED_FOR'];
6800
        }
6801
        $ip = trim($ip1);
6802
    }
6803
    if (!empty($debug)) error_log('Real IP: '.$ip);
6804
    return $ip;
6805
}
6806
6807
/**
6808
 * Checks whether an IP is included inside an IP range
6809
 * @param string IP address
6810
 * @param string IP range
6811
 * @return bool True if IP is in the range, false otherwise
6812
 * @author claudiu at cnixs dot com  on http://www.php.net/manual/fr/ref.network.php#55230
6813
 * @author Yannick Warnier for improvements and managment of multiple ranges
6814
 * @todo check for IPv6 support
6815
 */
6816
function api_check_ip_in_range($ip,$range)
6817
{
6818
    if (empty($ip) or empty($range)) {
6819
        return false;
6820
    }
6821
    $ip_ip = ip2long ($ip);
6822
    // divide range param into array of elements
6823
    if (strpos($range,',')!==false) {
6824
        $ranges = explode(',',$range);
6825
    } else {
6826
        $ranges = array($range);
6827
    }
6828
    foreach ($ranges as $range) {
6829
        $range = trim($range);
6830
        if (empty($range)) { continue; }
6831
        if (strpos($range,'/')===false) {
6832
            if (strcmp($ip,$range)===0) {
6833
                return true; // there is a direct IP match, return OK
6834
            }
6835
            continue; //otherwise, get to the next range
6836
        }
6837
        // the range contains a "/", so analyse completely
6838
        list ($net, $mask) = explode("/", $range);
6839
6840
        $ip_net = ip2long ($net);
6841
        // mask binary magic
6842
        $ip_mask = ~((1 << (32 - $mask)) - 1);
6843
6844
        $ip_ip_net = $ip_ip & $ip_mask;
6845
        if ($ip_ip_net == $ip_net) {
6846
            return true;
6847
        }
6848
    }
6849
6850
    return false;
6851
}
6852
6853
function api_check_user_access_to_legal($course_visibility) {
6854
    $course_visibility_list = array(COURSE_VISIBILITY_OPEN_WORLD, COURSE_VISIBILITY_OPEN_PLATFORM);
6855
    return in_array($course_visibility, $course_visibility_list) || api_is_drh();
6856
}
6857
6858
/**
6859
 * Checks if the global chat is enabled or not
6860
 *
6861
 * @return bool
6862
 */
6863
function api_is_global_chat_enabled()
6864
{
6865
    return
6866
        !api_is_anonymous() &&
6867
        api_get_setting('allow_global_chat') == 'true' &&
6868
        api_get_setting('allow_social_tool') == 'true';
6869
}
6870
6871
/**
6872
 * @todo Fix tool_visible_by_default_at_creation labels
6873
 * @todo Add sessionId parameter to avoid using context
6874
 *
6875
 * @param int $item_id
6876
 * @param int $tool_id
6877
 * @param int $group_id
6878
 * @param array $courseInfo
6879
 */
6880
function api_set_default_visibility($item_id, $tool_id, $group_id = 0, $courseInfo = array(), $sessionId = 0, $userId = 0)
6881
{
6882
    $courseInfo = empty($courseInfo) ? api_get_course_info() : $courseInfo;
6883
    $courseId = $courseInfo['real_id'];
6884
    $courseCode = $courseInfo['code'];
6885
    $sessionId = empty($sessionId) ? api_get_session_id() : $sessionId;
6886
    $userId = empty($userId) ? api_get_user_id() : $userId;
6887
6888
    $original_tool_id = $tool_id;
6889
6890
    switch ($tool_id) {
6891
        case TOOL_LINK:
6892
        case TOOL_LINK_CATEGORY:
6893
            $tool_id = 'links';
6894
            break;
6895
        case TOOL_DOCUMENT:
6896
            $tool_id = 'documents';
6897
            break;
6898
        case TOOL_LEARNPATH:
6899
            $tool_id = 'learning';
6900
            break;
6901
        case TOOL_ANNOUNCEMENT:
6902
            $tool_id = 'announcements';
6903
            break;
6904
        case TOOL_FORUM:
6905
        case TOOL_FORUM_CATEGORY:
6906
        case TOOL_FORUM_THREAD:
6907
            $tool_id = 'forums';
6908
            break;
6909
        case TOOL_QUIZ:
6910
            $tool_id = 'quiz';
6911
            break;
6912
    }
6913
    $setting = api_get_setting('tool_visible_by_default_at_creation');
6914
6915
    if (isset($setting[$tool_id])) {
6916
        $visibility = 'invisible';
6917
        if ($setting[$tool_id] == 'true') {
6918
            $visibility = 'visible';
6919
        }
6920
6921
        if (empty($group_id)) {
6922
            $group_id = api_get_group_id();
6923
        }
6924
6925
        // Read the portal and course default visibility
6926
        if ($tool_id == 'documents') {
6927
            $visibility = DocumentManager::getDocumentDefaultVisibility($courseCode);
6928
        }
6929
6930
        api_item_property_update(
6931
            $courseInfo,
6932
            $original_tool_id,
6933
            $item_id,
6934
            $visibility,
6935
            $userId,
6936
            $group_id,
6937
            null,
6938
            null,
6939
            null,
6940
            api_get_session_id()
6941
        );
6942
6943
        // Fixes default visibility for tests
6944
6945
        switch ($original_tool_id) {
6946
            case TOOL_QUIZ:
6947
                if (empty($sessionId)) {
6948
                    $objExerciseTmp = new Exercise($courseId);
6949
                    $objExerciseTmp->read($item_id);
6950
                    if ($visibility == 'visible') {
6951
                        $objExerciseTmp->enable();
6952
                        $objExerciseTmp->save();
6953
                    } else {
6954
                        $objExerciseTmp->disable();
6955
                        $objExerciseTmp->save();
6956
                    }
6957
                }
6958
                break;
6959
        }
6960
    }
6961
}
6962
6963
/**
6964
 * @return string
6965
 */
6966
function api_get_security_key() {
6967
    return api_get_configuration_value('security_key');
6968
}
6969
6970
/**
6971
 * @param int $user_id
6972
 * @param int $courseId
6973
 * @param int $session_id
6974
 * @return array
6975
 */
6976
function api_detect_user_roles($user_id, $courseId, $session_id = 0)
6977
{
6978
    $user_roles = array();
6979
    /*$user_info = api_get_user_info($user_id);
6980
    $user_roles[] = $user_info['status'];*/
6981
    $courseInfo = api_get_course_info_by_id($courseId);
6982
    $course_code = $courseInfo['code'];
6983
6984
    $url_id = api_get_current_access_url_id();
6985
    if (api_is_platform_admin_by_id($user_id, $url_id)) {
6986
        $user_roles[] = PLATFORM_ADMIN;
6987
    }
6988
6989
    /*if (api_is_drh()) {
6990
        $user_roles[] = DRH;
6991
    }*/
6992
6993
    if (!empty($session_id)) {
6994
        if (SessionManager::user_is_general_coach($user_id, $session_id)) {
6995
            $user_roles[] = SESSION_GENERAL_COACH;
6996
        }
6997
    }
6998
6999
    if (!empty($course_code)) {
7000
        if (empty($session_id)) {
7001
            if (CourseManager::is_course_teacher($user_id, $course_code)) {
7002
                $user_roles[] = COURSEMANAGER;
7003
            }
7004
            if (CourseManager::get_tutor_in_course_status($user_id, $course_code)) {
7005
                $user_roles[] = COURSE_TUTOR;
7006
            }
7007
7008
            if (CourseManager::is_user_subscribed_in_course($user_id, $course_code)) {
7009
                $user_roles[] = COURSE_STUDENT;
7010
            }
7011
        } else {
7012
            $user_status_in_session = SessionManager::get_user_status_in_course_session(
7013
                $user_id,
7014
                $courseId,
7015
                $session_id
7016
            );
7017
7018
            if (!empty($user_status_in_session)) {
7019
                if ($user_status_in_session == 0) {
7020
                    $user_roles[] = SESSION_STUDENT;
7021
                }
7022
                if ($user_status_in_session == 2) {
7023
                    $user_roles[] = SESSION_COURSE_COACH;
7024
                }
7025
            }
7026
7027
            /*if (api_is_course_session_coach($user_id, $course_code, $session_id)) {
7028
               $user_roles[] = SESSION_COURSE_COACH;
7029
            }*/
7030
        }
7031
    }
7032
    return $user_roles;
7033
}
7034
7035
function api_get_roles_to_string($roles) {
7036
    $role_names = array();
7037
    if (!empty($roles)) {
7038
        foreach ($roles as $role) {
7039
            $role_names[] = get_status_from_code($role);
7040
        }
7041
    }
7042
    if (!empty($role_names)) {
7043
        return implode(', ', $role_names);
7044
    }
7045
    return null;
7046
}
7047
7048
function role_actions() {
7049
    return array(
7050
        'course' => array(
7051
            'create',
7052
            'read',
7053
            'edit',
7054
            'delete'
7055
        ),
7056
        'admin' => array(
7057
            'create',
7058
            'read',
7059
            'edit',
7060
            'delete'
7061
        )
7062
    );
7063
}
7064
7065
/**
7066
 * @param int $courseId
7067
 * @param int $session_id
7068
 * @return bool
7069
 */
7070
function api_coach_can_edit_view_results($courseId = null, $session_id = null)
7071
{
7072
    $user_id = api_get_user_id();
7073
7074
    if (empty($courseId)) {
7075
        $courseId = api_get_course_int_id();
7076
    }
7077
7078
    if (empty($session_id)) {
7079
        $session_id = api_get_session_id();
7080
    }
7081
7082
    if (api_is_platform_admin()) {
7083
        return true;
7084
    }
7085
7086
    $roles = api_detect_user_roles($user_id, $courseId, $session_id);
7087
7088
    if (in_array(SESSION_COURSE_COACH, $roles)) {
7089
        //return api_get_setting('session_tutor_reports_visibility') == 'true';
7090
        return true;
7091
    } else {
7092
        if (in_array(COURSEMANAGER, $roles)) {
7093
            return true;
7094
        }
7095
        return false;
7096
    }
7097
}
7098
7099
function api_get_js_simple($file) {
7100
    return '<script type="text/javascript" src="'.$file.'"></script>'."\n";
7101
}
7102
7103
function api_set_settings_and_plugins() {
7104
    global $_configuration;
7105
    $_setting = array();
7106
    $_plugins = array();
7107
7108
    // access_url == 1 is the default chamilo location
7109
    $settings_by_access_list = array();
7110
    $access_url_id = api_get_current_access_url_id();
7111 View Code Duplication
    if ($access_url_id != 1) {
7112
        $url_info = api_get_access_url($_configuration['access_url']);
7113
        if ($url_info['active'] == 1) {
7114
            $settings_by_access = & api_get_settings(null, 'list', $_configuration['access_url'], 1);
7115
            foreach ($settings_by_access as & $row) {
7116
                if (empty($row['variable'])) {
7117
                    $row['variable'] = 0;
7118
                }
7119
                if (empty($row['subkey'])) {
7120
                    $row['subkey'] = 0;
7121
                }
7122
                if (empty($row['category'])) {
7123
                    $row['category'] = 0;
7124
                }
7125
                $settings_by_access_list[$row['variable']][$row['subkey']][$row['category']] = $row;
7126
            }
7127
        }
7128
    }
7129
7130
    $result = api_get_settings(null, 'list', 1);
7131
7132 View Code Duplication
    foreach ($result as & $row) {
7133
        if ($access_url_id != 1) {
7134
            if ($url_info['active'] == 1) {
7135
                $var = empty($row['variable']) ? 0 : $row['variable'];
7136
                $subkey = empty($row['subkey']) ? 0 : $row['subkey'];
7137
                $category = empty($row['category']) ? 0 : $row['category'];
7138
            }
7139
7140
            if ($row['access_url_changeable'] == 1 && $url_info['active'] == 1) {
7141
                if (isset($settings_by_access_list[$var]) &&
7142
                    $settings_by_access_list[$var][$subkey][$category]['selected_value'] != '') {
7143
                    if ($row['subkey'] == null) {
7144
                        $_setting[$row['variable']] = $settings_by_access_list[$var][$subkey][$category]['selected_value'];
7145
                    } else {
7146
                        $_setting[$row['variable']][$row['subkey']] = $settings_by_access_list[$var][$subkey][$category]['selected_value'];
7147
                    }
7148
                } else {
7149
                    if ($row['subkey'] == null) {
7150
                        $_setting[$row['variable']] = $row['selected_value'];
7151
                    } else {
7152
                        $_setting[$row['variable']][$row['subkey']] = $row['selected_value'];
7153
                    }
7154
                }
7155
            } else {
7156
                if ($row['subkey'] == null) {
7157
                    $_setting[$row['variable']] = $row['selected_value'];
7158
                } else {
7159
                    $_setting[$row['variable']][$row['subkey']] = $row['selected_value'];
7160
                }
7161
            }
7162
        } else {
7163
            if ($row['subkey'] == null) {
7164
                $_setting[$row['variable']] = $row['selected_value'];
7165
            } else {
7166
                $_setting[$row['variable']][$row['subkey']] = $row['selected_value'];
7167
            }
7168
        }
7169
    }
7170
7171
    $result = api_get_settings('Plugins', 'list', $access_url_id);
7172
    $_plugins = array();
7173 View Code Duplication
    foreach ($result as & $row) {
7174
        $key = & $row['variable'];
7175
        if (is_string($_setting[$key])) {
7176
            $_setting[$key] = array();
7177
        }
7178
        $_setting[$key][] = $row['selected_value'];
7179
        $_plugins[$key][] = $row['selected_value'];
7180
    }
7181
7182
    $_SESSION['_setting'] = $_setting;
7183
    $_SESSION['_plugins'] = $_plugins;
7184
}
7185
7186
function api_set_setting_last_update()
7187
{
7188
    // Saving latest refresh.
7189
    api_set_setting('settings_latest_update', api_get_utc_datetime());
7190
}
7191
7192
/**
7193
 * Tries to set memory limit, if authorized and new limit is higher than current
7194
 * @param string New memory limit
7195
 * @return bool True on success, false on failure or current is higher than suggested
7196
 * @assert (null) === false
7197
 * @assert (-1) === false
7198
 * @assert (0) === true
7199
 * @assert ('1G') === true
7200
 */
7201
function api_set_memory_limit($mem){
7202
    //if ini_set() not available, this function is useless
7203
    if (!function_exists('ini_set') || is_null($mem) || $mem == -1) {
7204
        return false;
7205
    }
7206
7207
    $memory_limit = ini_get('memory_limit');
7208
    if (api_get_bytes_memory_limit($mem) > api_get_bytes_memory_limit($memory_limit)){
7209
        ini_set('memory_limit', $mem);
7210
        return true;
7211
    }
7212
    return false;
7213
}
7214
7215
/**
7216
 * Gets memory limit in bytes
7217
 * @param string The memory size (128M, 1G, 1000K, etc)
7218
 * @return int
7219
 * @assert (null) === false
7220
 * @assert ('1t')  === 1099511627776
7221
 * @assert ('1g')  === 1073741824
7222
 * @assert ('1m')  === 1048576
7223
 * @assert ('100k') === 102400
7224
 */
7225
function api_get_bytes_memory_limit($mem){
7226
    $size = strtolower(substr($mem,-1));
7227
7228
    switch ($size) {
7229
        case 't':
7230
            $mem = intval(substr($mem,-1))*1024*1024*1024*1024;
7231
            break;
7232
        case 'g':
7233
            $mem = intval(substr($mem,0,-1))*1024*1024*1024;
7234
            break;
7235
        case 'm':
7236
            $mem = intval(substr($mem,0,-1))*1024*1024;
7237
            break;
7238
        case 'k':
7239
            $mem = intval(substr($mem,0,-1))*1024;
7240
            break;
7241
        default:
7242
            // we assume it's integer only
7243
            $mem = intval($mem);
7244
            break;
7245
    }
7246
    return $mem;
7247
}
7248
7249
/**
7250
 * Finds all the information about a user from username instead of user id
7251
 * @param string $username
0 ignored issues
show
Bug introduced by
There is no parameter named $username. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

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

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

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

Loading history...
7252
 *
7253
 * @return array $user_info user_id, lastname, firstname, username, email, ...
7254
 * @author Yannick Warnier <[email protected]>
7255
 */
7256 View Code Duplication
function api_get_user_info_from_official_code($official_code = '')
7257
{
7258
    if (empty($official_code)) {
7259
        return false;
7260
    }
7261
    $sql = "SELECT * FROM ".Database :: get_main_table(TABLE_MAIN_USER)."
7262
            WHERE official_code ='".Database::escape_string($official_code)."'";
7263
    $result = Database::query($sql);
7264
    if (Database::num_rows($result) > 0) {
7265
        $result_array = Database::fetch_array($result);
7266
        return _api_format_user($result_array);
7267
    }
7268
    return false;
7269
}
7270
7271
/**
7272
 *
7273
 * @param string $inputId the jquery id example: #password
0 ignored issues
show
Documentation introduced by
There is no parameter named $inputId. Did you maybe mean $usernameInputId?

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...
7274
 *
7275
 * @return string
7276
 */
7277
function api_get_password_checker_js($usernameInputId, $passwordInputid)
7278
{
7279
    $checkPass = api_get_setting('allow_strength_pass_checker');
7280
    $useStrengthPassChecker = $checkPass == 'true';
7281
7282
    if ($useStrengthPassChecker == false) {
7283
        return null;
7284
    }
7285
7286
    $verdicts = array(
7287
        get_lang('PasswordWeak'),
7288
        get_lang('PasswordNormal'),
7289
        get_lang('PasswordMedium'),
7290
        get_lang('PasswordStrong'),
7291
        get_lang('PasswordVeryStrong'),
7292
    );
7293
    $js = api_get_js('strength/strength.js');
7294
    $js .=  "<script>
7295
7296
    var verdicts = ['".implode("','", $verdicts)."'];
7297
    var errorMessages = {
7298
        password_to_short : \"" . get_lang('PasswordIsTooShort')."\",
7299
        same_as_username : \"".get_lang('YourPasswordCannotBeTheSameAsYourUsername')."\"
7300
    };
7301
7302
    $(document).ready(function() {
7303
        var options = {
7304
            verdicts: verdicts,
7305
            onLoad : function () {
7306
                //$('#messages').text('Start typing password');
7307
            },
7308
            onKeyUp: function (evt) {
7309
                $(evt.target).pwstrength('outputErrorList');
7310
            },
7311
            errorMessages : errorMessages,
7312
            viewports: {
7313
                progress: '#password_progress',
7314
                verdict: '#password-verdict',
7315
                errors: '#password-errors'
7316
            },
7317
            usernameField: '$usernameInputId'
7318
        };
7319
        $('".$passwordInputid."').pwstrength(options);
7320
    });
7321
    </script>";
7322
    return $js;
7323
}
7324
7325
/**
7326
 * Gets an array with "easy" passwords
7327
 * @return array
7328
 */
7329
function api_get_easy_password_list()
7330
{
7331
    $passwordList = array('123', '1234', '123456', 'admin', 'user', 'student', 'teacher');
7332
    $file = api_get_path(CONFIGURATION_PATH).'easy_password_list.php';
7333
    if (file_exists($file)) {
7334
        $passwordList = require_once $file;
7335
    }
7336
    return $passwordList;
7337
}
7338
7339
/**
7340
 * @param string $username
7341
 * create an user extra field called 'captcha_blocked_until_date'
7342
 */
7343
function api_block_account_captcha($username)
7344
{
7345
    $userInfo = api_get_user_info_from_username($username);
7346
    if (empty($userInfo)) {
7347
        return false;
7348
    }
7349
    $minutesToBlock = api_get_setting('captcha_time_to_block');
7350
    $time = time() + $minutesToBlock*60;
7351
    UserManager::update_extra_field_value(
7352
        $userInfo['user_id'],
7353
        'captcha_blocked_until_date',
7354
        api_get_utc_datetime($time)
7355
    );
7356
}
7357
7358
/**
7359
 * @param string $username
7360
 */
7361
function api_clean_account_captcha($username)
7362
{
7363
    $userInfo = api_get_user_info_from_username($username);
7364
    if (empty($userInfo)) {
7365
        return false;
7366
    }
7367
    Session::erase('loginFailedCount');
7368
    UserManager::update_extra_field_value(
7369
        $userInfo['user_id'],
7370
        'captcha_blocked_until_date',
7371
        null
7372
    );
7373
}
7374
7375
/**
7376
 * @param string $username
7377
 * @return bool
7378
 */
7379
function api_get_user_blocked_by_captcha($username)
7380
{
7381
    $userInfo = api_get_user_info_from_username($username);
7382
    if (empty($userInfo)) {
7383
        return false;
7384
    }
7385
    $data = UserManager::get_extra_user_data_by_field(
7386
        $userInfo['user_id'],
7387
        'captcha_blocked_until_date'
7388
    );
7389
    if (isset($data) && isset($data['captcha_blocked_until_date'])) {
7390
        return $data['captcha_blocked_until_date'];
7391
    }
7392
    return false;
7393
}
7394
7395
/**
7396
 * Remove tags from HTML anf return the $in_number_char first non-HTML char
7397
 * Postfix the text with "..." if it has been truncated.
7398
 * @return string
7399
 * @author hubert borderiou
7400
 */
7401
function api_get_short_text_from_html($in_html, $in_number_char)
7402
{
7403
    $out_res = api_remove_tags_with_space($in_html, false);
7404
    $postfix = "...";
7405
    if (strlen($out_res) > $in_number_char) {
7406
        $out_res = substr($out_res, 0, $in_number_char).$postfix;
7407
    }
7408
    return $out_res;
7409
}
7410
7411
/**
7412
 * Replace tags with a space in a text.
7413
 * If $in_double_quote_replace, replace " with '' (for HTML attribute purpose, for exemple)
7414
 * @return string
7415
 * @author hubert borderiou
7416
 */
7417
function api_remove_tags_with_space($in_html, $in_double_quote_replace = true) {
7418
    $out_res = $in_html;
7419
    if ($in_double_quote_replace) {
7420
        $out_res = str_replace('"', "''", $out_res);
7421
    }
7422
    // avoid text stuck together when tags are removed, adding a space after >
7423
    $out_res = str_replace (">", "> ", $out_res);
7424
    $out_res = strip_tags($out_res);
7425
7426
    return $out_res;
7427
}
7428
7429
/**
7430
 * If true, the drh can access all content (courses, users) inside a session
7431
 * @return bool
7432
 */
7433
function api_drh_can_access_all_session_content()
7434
{
7435
    $a = api_get_setting('drh_can_access_all_session_content');
7436
    return $a == 'true';
7437
}
7438
7439
/**
7440
 * @param string $tool
7441
 * @param string $setting
7442
 * @param mixed $defaultValue
7443
 * @return string
7444
 */
7445
function api_get_default_tool_setting($tool, $setting, $defaultValue)
7446
{
7447
    global $_configuration;
7448
    if (isset($_configuration[$tool]) &&
7449
        isset($_configuration[$tool]['default_settings']) &&
7450
        isset($_configuration[$tool]['default_settings'][$setting])
7451
    ) {
7452
        return $_configuration[$tool]['default_settings'][$setting];
7453
    }
7454
    return $defaultValue;
7455
7456
}
7457
7458
/**
7459
 * Checks if user can login as another user
7460
 *
7461
 * @param int $loginAsUserId the user id to log in
7462
 * @param int $userId my user id
7463
 * @return bool
7464
 */
7465
function api_can_login_as($loginAsUserId, $userId = null)
7466
{
7467
    if (empty($userId)) {
7468
        $userId = api_get_user_id();
7469
    }
7470
    if ($loginAsUserId == $userId) {
7471
        return false;
7472
    }
7473
7474
    if (empty($loginAsUserId)) {
7475
        return false;
7476
    }
7477
7478
    if ($loginAsUserId != strval(intval($loginAsUserId))) {
7479
        return false;
7480
    }
7481
    // Check if the user to login is an admin
7482
7483
    if (api_is_platform_admin_by_id($loginAsUserId)) {
7484
        // Only super admins can login to admin accounts
7485
        if (!api_global_admin_can_edit_admin($loginAsUserId)) {
7486
            return false;
7487
        }
7488
    }
7489
7490
    $userInfo = api_get_user_info($userId);
7491
7492
    $isDrh = function() use($loginAsUserId) {
7493
        if (api_is_drh()) {
7494
            if (api_drh_can_access_all_session_content()) {
7495
                $users = SessionManager::getAllUsersFromCoursesFromAllSessionFromStatus('drh_all', api_get_user_id());
7496
                $userList = array();
7497
                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...
7498
                    $userList[] = $user['user_id'];
7499
                }
7500
                if (in_array($loginAsUserId, $userList)) {
7501
                    return true;
7502
                }
7503
            } else {
7504
                if (api_is_drh() && UserManager::is_user_followed_by_drh($loginAsUserId, api_get_user_id())) {
7505
                    return true;
7506
                }
7507
            }
7508
        }
7509
        return false;
7510
    };
7511
7512
    return api_is_platform_admin() || (api_is_session_admin() && $userInfo['status'] == 5) || $isDrh();
7513
}
7514
7515
/**
7516
 * @return bool
7517
 */
7518
function api_is_allowed_in_course()
7519
{
7520
    return Session::read('is_allowed_in_course');
7521
}
7522
7523
/**
7524
 * Show a string in
7525
 * @param string $string Some string to dump, removing tabs, spaces,
7526
 * newlines, etc (usually most useful for SQL queries)
7527
 * @param int $dump Set to 1 to use print_r()
7528
 */
7529
function api_error_log($string, $dump = 0)
7530
{
7531
    // Clean query
7532
    $bt = debug_backtrace();
7533
    $caller = array_shift($bt);;
7534
    if ($dump == 1) {
7535
        $string = print_r($string, 1);
7536
    } else {
7537
        $string = str_replace(array("\r", "\n", "\t", "\10"), '', $string);
7538
        $string = str_replace('    ',' ', $string);
7539
    }
7540
7541
    error_log("-------------------------------------");
7542
    error_log($string);
7543
    error_log("File: ".$caller['file']." +".$caller['line']);
7544
    error_log("-------------------------------------");
7545
}
7546
7547
/**
7548
 * Set the cookie to go directly to the course code $in_firstpage
7549
 * after login
7550
 * @param string $in_firstpage is the course code of the course to go
7551
 */
7552
function api_set_firstpage_parameter($in_firstpage)
7553
{
7554
    setcookie("GotoCourse", $in_firstpage);
7555
}
7556
7557
/**
7558
 * Delete the cookie to go directly to the course code $in_firstpage
7559
 * after login
7560
 */
7561
function api_delete_firstpage_parameter()
7562
{
7563
    setcookie("GotoCourse", "", time() - 3600);
7564
}
7565
7566
/**
7567
 * @return true if course_code for direct course access after login is set
7568
 */
7569
function exist_firstpage_parameter()
7570
{
7571
    return (isset($_COOKIE['GotoCourse']) && $_COOKIE['GotoCourse'] != "");
7572
}
7573
7574
/**
7575
 * @return return the course_code of the course where user login
7576
 */
7577
function api_get_firstpage_parameter()
7578
{
7579
    return $_COOKIE['GotoCourse'];
7580
}
7581
7582
/**
7583
 * Return true on https install
7584
 * @return boolean
7585
 */
7586
function api_is_https()
7587
{
7588
    return (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] != 'off');
7589
}
7590
7591
/**
7592
 * Return protocol (http or https)
7593
 * @return string
7594
 */
7595
function api_get_protocol()
7596
{
7597
    return api_is_https() ? 'https' : 'http';
7598
}
7599
7600
/**
7601
 * Return a string where " are replaced with 2 '
7602
 * It is useful when you pass a PHP variable in a Javascript browser dialog
7603
 * e.g. : alert("<?php get_lang('Message') ?>");
7604
 * and message contains character "
7605
 *
7606
 * @param string $in_text
7607
 * @return string
7608
 */
7609
function convert_double_quote_to_single($in_text) {
7610
    return api_preg_replace('/"/', "''", $in_text);
7611
}
7612
7613
/**
7614
 * Get origin
7615
 *
7616
 * @param string
7617
 * @return string
7618
 **/
7619
function api_get_origin()
7620
{
7621
    if (isset($_REQUEST['origin'])) {
7622
        return $_REQUEST['origin'] == 'learnpath' ? 'learnpath' : null;
7623
    }
7624
7625
    return null;
7626
}
7627
7628
/**
7629
 * Warns an user that the portal reach certain limit.
7630
 * @param string $limitName
7631
 */
7632
function api_warn_hosting_contact($limitName)
7633
{
7634
    $hostingParams = api_get_configuration_value(1);
7635
    $email = null;
7636
7637
    if (!empty($hostingParams)) {
7638
        if (isset($hostingParams['hosting_contact_mail'])) {
7639
            $email = $hostingParams['hosting_contact_mail'];
7640
        }
7641
    }
7642
7643
    if (!empty($email)) {
7644
        $subject = get_lang('HostingWarningReached');
7645
        $body = get_lang('PortalName').': '.api_get_path(WEB_PATH)." \n ";
7646
        $body .= get_lang('PortalLimitType').': '.$limitName." \n ";
7647
        if (isset($hostingParams[$limitName])) {
7648
            $body .= get_lang('Value') . ': ' . $hostingParams[$limitName];
7649
        }
7650
        api_mail_html(null, $email, $subject, $body);
7651
    }
7652
}
7653
7654
/**
7655
 * @param string $variable
7656
 * @return bool|mixed
7657
 */
7658
function api_get_configuration_value($variable)
7659
{
7660
    global $_configuration;
7661
    if (isset($_configuration[$variable])) {
7662
        return $_configuration[$variable];
7663
    }
7664
    return false;
7665
}
7666
7667
/**
7668
 * Returns supported image extensions in the portal
7669
 * @return  array   Supported image extensions in the portal
7670
 */
7671
function api_get_supported_image_extensions()
7672
{
7673
    // jpg can also be called jpeg, jpe, jfif and jif. See https://en.wikipedia.org/wiki/JPEG#JPEG_filename_extensions
7674
    $supportedImageExtensions = array('jpg', 'jpeg', 'png', 'gif', 'svg', 'jpe', 'jfif', 'jif');
7675
    if (version_compare(PHP_VERSION, '5.5.0', '>=')) {
7676
        array_push($supportedImageExtensions, 'webp');
7677
    }
7678
    return $supportedImageExtensions;
7679
}
7680
7681
/**
7682
 * This setting changes the registration status for the campus
7683
 *
7684
 * @author Patrick Cool <[email protected]>, Ghent University
7685
 * @version August 2006
7686
 * @param   bool    $listCampus Whether we authorize
7687
 * @todo the $_settings should be reloaded here. => write api function for this and use this in global.inc.php also.
7688
 */
7689 View Code Duplication
function api_register_campus($listCampus = true) {
7690
    $tbl_settings = Database :: get_main_table(TABLE_MAIN_SETTINGS_CURRENT);
7691
7692
    $sql = "UPDATE $tbl_settings SET selected_value='true' WHERE variable='registered'";
7693
    Database::query($sql);
7694
7695
    if (!$listCampus) {
7696
        $sql = "UPDATE $tbl_settings SET selected_value='true' WHERE variable='donotlistcampus'";
7697
        Database::query($sql);
7698
    }
7699
}
7700
7701
/**
7702
 * Checks whether current user is a student boss
7703
 * @global array $_user
7704
 * @return boolean
7705
 */
7706
function api_is_student_boss()
7707
{
7708
    $_user = api_get_user_info();
7709
7710
    return isset($_user['status']) && $_user['status'] == STUDENT_BOSS;
7711
}
7712
7713
/**
7714
 * Check whether the user type should be exclude.
7715
 * Such as invited or anonymous users
7716
 * @param boolean $checkDB Optional. Whether check the user status
7717
 * @param int $userId Options. The user id
7718
 *
7719
 * @return boolean
7720
 */
7721
function api_is_excluded_user_type($checkDB = false, $userId = 0)
7722
{
7723
    if ($checkDB) {
7724
        $userId = empty($userId) ? api_get_user_id() : intval($userId);
7725
7726
        if ($userId == 0) {
7727
            return true;
7728
        }
7729
7730
        $userInfo = api_get_user_info($userId);
7731
7732
        switch ($userInfo['status']) {
7733
            case INVITEE:
7734
                //no break;
7735
            case ANONYMOUS:
7736
                return true;
7737
            default:
7738
                return false;
7739
        }
7740
    }
7741
7742
    $isInvited = api_is_invitee();
7743
    $isAnonymous = api_is_anonymous();
7744
7745
    if ($isInvited || $isAnonymous) {
7746
        return true;
7747
    }
7748
7749
    return false;
7750
}
7751
7752
/**
7753
 * Get the user status to ignore in reports
7754
 * @param string $format Optional. The result type (array or string)
7755
 * @return array|string
7756
 */
7757
function api_get_users_status_ignored_in_reports($format = 'array')
7758
{
7759
    $excludedTypes = array(
7760
        INVITEE,
7761
        ANONYMOUS
7762
    );
7763
7764
    if ($format == 'string') {
7765
        return implode(', ', $excludedTypes);
7766
    }
7767
7768
    return $excludedTypes;
7769
}
7770
7771
/**
7772
 * Set the Site Use Cookie Warning for 1 year
7773
 */
7774
function api_set_site_use_cookie_warning_cookie()
7775
{
7776
    setcookie("ChamiloUsesCookies", "ok", time()+31556926);
7777
}
7778
7779
/**
7780
 * Return true if the Site Use Cookie Warning Cookie warning exists
7781
 * @return bool
7782
 */
7783
function api_site_use_cookie_warning_cookie_exist()
7784
{
7785
    return isset($_COOKIE['ChamiloUsesCookies']);
7786
}
7787
7788
/**
7789
 * Given a number of seconds, format the time to show hours, minutes and seconds
7790
 * @param int $time The time in seconds
7791
 * @param string $originFormat Optional. PHP o JS
7792
 * @return string (00h00'00")
7793
 */
7794
function api_format_time($time, $originFormat = 'php')
7795
{
7796
    $h = get_lang('h');
7797
    $hours = $time / 3600;
7798
    $mins = ($time % 3600) / 60;
7799
    $secs = ($time % 60);
7800
7801
    if ($originFormat == 'js') {
7802
        $formattedTime = trim(sprintf("%02d : %02d : %02d", $hours, $mins, $secs));
7803
    } else {
7804
        $formattedTime = trim(sprintf("%02d$h%02d'%02d\"", $hours, $mins, $secs));
7805
    }
7806
7807
    return $formattedTime;
7808
}
7809
7810
/**
7811
 * Create a new empty directory with index.html file
7812
 * @param string $name The new directory name
7813
 * @param string $parentDirectory Directory parent directory name
7814
 * @return boolean Return true if the directory was create. Otherwise return false
7815
 */
7816
function api_create_protected_dir($name, $parentDirectory)
7817
{
7818
    $isCreated = false;
7819
7820
    if (!is_writable($parentDirectory)) {
7821
        return false;
7822
    }
7823
7824
    $fullPath = $parentDirectory . api_replace_dangerous_char($name);
7825
7826
    if (mkdir($fullPath, api_get_permissions_for_new_directories(), true)) {
7827
        $fp = fopen($fullPath . '/index.html', 'w');
7828
7829
        if ($fp) {
7830
            if (fwrite($fp, '<html><head></head><body></body></html>')) {
7831
                $isCreated = true;
7832
            }
7833
        }
7834
7835
        fclose($fp);
7836
    }
7837
7838
    return $isCreated;
7839
}
7840
7841
/**
7842
 * Sends an HTML email using the phpmailer class (and multipart/alternative to downgrade gracefully)
7843
 * Sender name and email can be specified, if not specified
7844
 * name and email of the platform admin are used
7845
 *
7846
 * @author Bert Vanderkimpen ICT&O UGent
7847
 * @author Yannick Warnier <[email protected]>
7848
 *
7849
 * @param string    name of recipient
7850
 * @param string    email of recipient
7851
 * @param string    email subject
7852
 * @param string    email body
7853
 * @param string    sender name
7854
 * @param string    sender e-mail
7855
 * @param array     extra headers in form $headers = array($name => $value) to allow parsing
7856
 * @param array     data file (path and filename)
7857
 * @param bool      True for attaching a embedded file inside content html (optional)
7858
 * @param array     Additional parameters
7859
 * @return          returns true if mail was sent
7860
 * @see             class.phpmailer.php
7861
 */
7862
function api_mail_html(
7863
    $recipient_name,
7864
    $recipient_email,
7865
    $subject,
7866
    $message,
7867
    $senderName = '',
7868
    $senderEmail = '',
7869
    $extra_headers = array(),
7870
    $data_file = array(),
7871
    $embedded_image = false,
7872
    $additionalParameters = array()
7873
) {
7874
    global $platform_email;
7875
7876
    $mail = new PHPMailer();
7877
    $mail->Mailer = $platform_email['SMTP_MAILER'];
7878
    $mail->Host = $platform_email['SMTP_HOST'];
7879
    $mail->Port = $platform_email['SMTP_PORT'];
7880
    $mail->CharSet = $platform_email['SMTP_CHARSET'];
7881
    // Stay far below SMTP protocol 980 chars limit.
7882
    $mail->WordWrap = 200;
7883
7884
    if ($platform_email['SMTP_AUTH']) {
7885
        $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...
7886
        $mail->Username = $platform_email['SMTP_USER'];
7887
        $mail->Password = $platform_email['SMTP_PASS'];
7888
        if (isset($platform_email['SMTP_SECURE'])) {
7889
            $mail->SMTPSecure = $platform_email['SMTP_SECURE'];
7890
        }
7891
    }
7892
    $mail->SMTPDebug = isset($platform_email['SMTP_DEBUG'])?$platform_email['SMTP_DEBUG']:0;
7893
7894
    // 5 = low, 1 = high
7895
    $mail->Priority = 3;
7896
    $mail->SMTPKeepAlive = true;
7897
7898
    // Default values
7899
    $notification = new Notification();
7900
    $defaultEmail = $notification->getDefaultPlatformSenderEmail();
7901
    $defaultName = $notification->getDefaultPlatformSenderName();
7902
7903
    // Error to admin.
7904
    $mail->AddCustomHeader('Errors-To: '.$defaultEmail);
7905
7906
    // If the parameter is set don't use the admin.
7907
    $senderName = !empty($senderName) ? $senderName : $defaultName;
7908
    $senderEmail = !empty($senderEmail) ? $senderEmail : $defaultEmail;
7909
7910
    // Reply to first
7911
    if (isset($extra_headers['reply_to'])) {
7912
        $mail->AddReplyTo(
7913
            $extra_headers['reply_to']['mail'],
7914
            $extra_headers['reply_to']['name']
7915
        );
7916
        $mail->Sender = $extra_headers['reply_to']['mail'];
7917
        unset($extra_headers['reply_to']);
7918
    }
7919
    //If the SMTP configuration only accept one sender
7920
    if ($platform_email['SMTP_UNIQUE_SENDER']) {
7921
        $senderName = $platform_email['SMTP_FROM_NAME'];
7922
        $senderEmail = $platform_email['SMTP_FROM_EMAIL'];
7923
    }
7924
    $mail->SetFrom($senderEmail, $senderName);
7925
7926
    $mail->Subject = $subject;
7927
    $mail->AltBody = strip_tags(
7928
        str_replace('<br />', "\n", api_html_entity_decode($message))
7929
    );
7930
7931
    // Send embedded image.
7932
    if ($embedded_image) {
7933
        // Get all images html inside content.
7934
        preg_match_all("/<img\s+.*?src=[\"\']?([^\"\' >]*)[\"\']?[^>]*>/i", $message, $m);
7935
        // Prepare new tag images.
7936
        $new_images_html = array();
7937
        $i = 1;
7938
        if (!empty($m[1])) {
7939
            foreach ($m[1] as $image_path) {
7940
                $real_path = realpath($image_path);
7941
                $filename  = basename($image_path);
7942
                $image_cid = $filename.'_'.$i;
7943
                $encoding = 'base64';
7944
                $image_type = mime_content_type($real_path);
7945
                $mail->AddEmbeddedImage(
7946
                    $real_path,
7947
                    $image_cid,
7948
                    $filename,
7949
                    $encoding,
7950
                    $image_type
0 ignored issues
show
Bug introduced by
It seems like $image_type defined by mime_content_type($real_path) on line 7944 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...
7951
                );
7952
                $new_images_html[] = '<img src="cid:'.$image_cid.'" />';
7953
                $i++;
7954
            }
7955
        }
7956
7957
        // Replace origin image for new embedded image html.
7958
        $x = 0;
7959
        if (!empty($m[0])) {
7960
            foreach ($m[0] as $orig_img) {
7961
                $message = str_replace($orig_img, $new_images_html[$x], $message);
7962
                $x++;
7963
            }
7964
        }
7965
    }
7966
7967
    $mailView = new Template(null, false, false, false, false, false, false);
7968
    $mailView->assign('content', $message);
7969
7970
    if (isset($additionalParameters['link'])) {
7971
        $mailView->assign('link', $additionalParameters['link']);
7972
    }
7973
7974
    $layout = $mailView->get_template('mail/mail.tpl');
7975
    $mail->Body = $mailView->fetch($layout);
7976
7977
    // Attachment ...
7978
    if (!empty($data_file)) {
7979
        $o = 0;
7980 View Code Duplication
        foreach ($data_file as $file_attach) {
7981
            if (!empty($file_attach['path']) && !empty($file_attach['filename'])) {
7982
                $mail->AddAttachment($file_attach['path'], $file_attach['filename']);
7983
            }
7984
            $o++;
7985
        }
7986
    } elseif (is_array($_FILES)) {
7987
        $data_file = $_FILES;
7988
        $o = 0;
7989 View Code Duplication
        foreach ($data_file as $file_attach) {
7990
            if (!empty($file_attach['tmp_name']) && !empty($file_attach['name'])) {
7991
                $mail->AddAttachment($file_attach['tmp_name'], $file_attach['name']);
7992
            }
7993
            $o++;
7994
        }
7995
    }
7996
7997
    // Only valid addresses are accepted.
7998
    if (is_array($recipient_email)) {
7999
        foreach ($recipient_email as $dest) {
8000
            if (api_valid_email($dest)) {
8001
                $mail->AddAddress($dest, $recipient_name);
8002
            }
8003
        }
8004
    } else {
8005
        if (api_valid_email($recipient_email)) {
8006
            $mail->AddAddress($recipient_email, $recipient_name);
8007
        } else {
8008
            return 0;
8009
        }
8010
    }
8011
8012
    if (is_array($extra_headers) && count($extra_headers) > 0) {
8013
        foreach ($extra_headers as $key => $value) {
8014
            switch (strtolower($key)) {
8015
                case 'encoding':
8016
                case 'content-transfer-encoding':
8017
                    $mail->Encoding = $value;
8018
                    break;
8019
                case 'charset':
8020
                    $mail->Charset = $value;
8021
                    break;
8022
                case 'contenttype':
8023
                case 'content-type':
8024
                    $mail->ContentType = $value;
8025
                    break;
8026
                default:
8027
                    $mail->AddCustomHeader($key.':'.$value);
8028
                    break;
8029
            }
8030
        }
8031
    } else {
8032
        if (!empty($extra_headers)) {
8033
            $mail->AddCustomHeader($extra_headers);
8034
        }
8035
    }
8036
8037
    // WordWrap the html body (phpMailer only fixes AltBody) FS#2988
8038
    $mail->Body = $mail->WrapText($mail->Body, $mail->WordWrap);
8039
    // Send the mail message.
8040
    if (!$mail->Send()) {
8041
        error_log('ERROR: mail not sent to '.$recipient_name.' ('.$recipient_email.') because of '.$mail->ErrorInfo.'<br />');
8042
        if ($mail->SMTPDebug) {
8043
            error_log(
8044
                "Connection details :: " .
8045
                "Protocol: " . $mail->Mailer . ' :: ' .
8046
                "Host/Port: " . $mail->Host . ':' . $mail->Port . ' :: ' .
8047
                "Authent/Open: " . ($mail->SMTPAuth?'Authent':'Open') . ' :: ' .
8048
                ($mail->SMTPAuth?"  User/Pass: " . $mail->Username . ':' . $mail->Password:'')
8049
            );
8050
        }
8051
        return 0;
8052
    }
8053
8054
    if (!empty($additionalParameters)) {
8055
        $plugin = new AppPlugin();
8056
        $smsPlugin = $plugin->getSMSPluginLibrary();
8057
        if ($smsPlugin) {
8058
            $smsPlugin->send($additionalParameters);
8059
        }
8060
    }
8061
8062
    // Clear all the addresses.
8063
    $mail->ClearAddresses();
8064
    return 1;
8065
}
8066
8067
/**
8068
 * @param string $tool Possible values:
8069
 * GroupManager::GROUP_TOOL_*
8070
 *
8071
 */
8072
function api_protect_course_group($tool, $showHeader = true)
8073
{
8074
    $userId = api_get_user_id();
8075
    $groupId = api_get_group_id();
8076
8077
    if (!empty($groupId)) {
8078
        $allow = GroupManager::user_has_access(
8079
            $userId,
8080
            $groupId,
8081
            $tool
8082
        );
8083
8084
        if (!$allow) {
8085
            api_not_allowed($showHeader);
8086
        }
8087
    }
8088
}
8089
8090
/**
8091
 * Eliminate the duplicates of a multidimensional array by sending the key
8092
 * @param array $array multidimensional array
8093
 * @param int $key key to find to compare
8094
 *
8095
 */
8096
function api_unique_multidim_array($array, $key){
8097
    $temp_array = array();
8098
    $i = 0;
8099
    $key_array = array();
8100
8101
    foreach($array as $val){
8102
        if(!in_array($val[$key],$key_array)){
8103
            $key_array[$i] = $val[$key];
8104
            $temp_array[$i] = $val;
8105
        }
8106
        $i++;
8107
    }
8108
    return $temp_array;
8109
}
8110
8111
/**
8112
 * Limit the access to Session Admins wheen the limit_session_admin_role
8113
 * configuration variable is set to true
8114
 */
8115
function api_protect_limit_for_session_admin()
8116
{
8117
    $limitAdmin = api_get_setting('limit_session_admin_role');
8118
    if (api_is_session_admin() && $limitAdmin === 'true') {
8119
        api_not_allowed(true);
8120
    }
8121
}
8122
8123
function api_is_student_view_active() {
8124
    return (isset($_SESSION['studentview']) && $_SESSION['studentview'] == "studentview");
8125
}
8126