Completed
Push — 1.10.x ( ba0bf0...97c0d2 )
by Angel Fernando Quiroz
44:06
created

api.lib.php ➔ api_not_allowed()   F

Complexity

Conditions 31
Paths 2880

Size

Total Lines 178
Code Lines 116

Duplication

Lines 22
Ratio 12.36 %
Metric Value
cc 31
eloc 116
nc 2880
nop 2
dl 22
loc 178
rs 2

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

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
460
define('EXERCISE_MAX_NAME_SIZE', 80);
461
462
// Question types (edit next array as well when adding values)
463
// @todo move into a class
464
define('UNIQUE_ANSWER', 1);
465
define('MULTIPLE_ANSWER', 2);
466
define('FILL_IN_BLANKS', 3);
467
define('MATCHING', 4);
468
define('FREE_ANSWER', 5);
469
define('HOT_SPOT', 6);
470
define('HOT_SPOT_ORDER', 7);
471
define('HOT_SPOT_DELINEATION', 8);
472
define('MULTIPLE_ANSWER_COMBINATION', 9);
473
define('UNIQUE_ANSWER_NO_OPTION', 10);
474
define('MULTIPLE_ANSWER_TRUE_FALSE', 11);
475
define('MULTIPLE_ANSWER_COMBINATION_TRUE_FALSE', 12);
476
define('ORAL_EXPRESSION', 13);
477
define('GLOBAL_MULTIPLE_ANSWER', 14);
478
define('MEDIA_QUESTION', 15);
479
define('CALCULATED_ANSWER', 16);
480
define('UNIQUE_ANSWER_IMAGE', 17);
481
define('DRAGGABLE', 18);
482
define('MATCHING_DRAGGABLE', 19);
483
484
define('EXERCISE_CATEGORY_RANDOM_SHUFFLED', 1);
485
define('EXERCISE_CATEGORY_RANDOM_ORDERED', 2);
486
define('EXERCISE_CATEGORY_RANDOM_DISABLED', 0);
487
488
// Question selection type
489
define('EX_Q_SELECTION_ORDERED', 1);
490
define('EX_Q_SELECTION_RANDOM', 2);
491
define('EX_Q_SELECTION_CATEGORIES_ORDERED_QUESTIONS_ORDERED', 3);
492
define('EX_Q_SELECTION_CATEGORIES_RANDOM_QUESTIONS_ORDERED', 4);
493
define('EX_Q_SELECTION_CATEGORIES_ORDERED_QUESTIONS_RANDOM', 5);
494
define('EX_Q_SELECTION_CATEGORIES_RANDOM_QUESTIONS_RANDOM', 6);
495
define('EX_Q_SELECTION_CATEGORIES_RANDOM_QUESTIONS_ORDERED_NO_GROUPED', 7);
496
define('EX_Q_SELECTION_CATEGORIES_RANDOM_QUESTIONS_RANDOM_NO_GROUPED', 8);
497
define('EX_Q_SELECTION_CATEGORIES_ORDERED_BY_PARENT_QUESTIONS_ORDERED', 9);
498
define('EX_Q_SELECTION_CATEGORIES_ORDERED_BY_PARENT_QUESTIONS_RANDOM', 10);
499
500
// one big string with all question types, for the validator in pear/HTML/QuickForm/Rule/QuestionType
501
define('QUESTION_TYPES',
502
    UNIQUE_ANSWER.':'.
503
    MULTIPLE_ANSWER.':'.
504
    FILL_IN_BLANKS.':'.
505
    MATCHING.':'.
506
    FREE_ANSWER.':'.
507
    HOT_SPOT.':'.
508
    HOT_SPOT_ORDER.':'.
509
    HOT_SPOT_DELINEATION.':'.
510
    MULTIPLE_ANSWER_COMBINATION.':'.
511
    UNIQUE_ANSWER_NO_OPTION.':'.
512
    MULTIPLE_ANSWER_TRUE_FALSE.':'.
513
    MULTIPLE_ANSWER_COMBINATION_TRUE_FALSE.':'.
514
    ORAL_EXPRESSION.':'.
515
    GLOBAL_MULTIPLE_ANSWER.':'.
516
    MEDIA_QUESTION.':'.
517
    CALCULATED_ANSWER.':'.
518
    UNIQUE_ANSWER_IMAGE.':'.
519
    DRAGGABLE.':'.
520
    MATCHING_DRAGGABLE
521
);
522
523
//Some alias used in the QTI exports
524
define('MCUA', 1);
525
define('TF', 1);
526
define('MCMA', 2);
527
define('FIB', 3);
528
529
// Skills
530
define('SKILL_TYPE_REQUIREMENT', 'required');
531
define('SKILL_TYPE_ACQUIRED', 'acquired');
532
define('SKILL_TYPE_BOTH', 'both');
533
534
// Message
535
define('MESSAGE_STATUS_NEW', '0');
536
define('MESSAGE_STATUS_UNREAD', '1');
537
//2 ??
538
define('MESSAGE_STATUS_DELETED', '3');
539
define('MESSAGE_STATUS_OUTBOX', '4');
540
define('MESSAGE_STATUS_INVITATION_PENDING', '5');
541
define('MESSAGE_STATUS_INVITATION_ACCEPTED', '6');
542
define('MESSAGE_STATUS_INVITATION_DENIED', '7');
543
define('MESSAGE_STATUS_WALL', '8');
544
define('MESSAGE_STATUS_WALL_DELETE', '9');
545
define('MESSAGE_STATUS_WALL_POST', '10');
546
// Images
547
define('IMAGE_WALL_SMALL_SIZE', 200);
548
define('IMAGE_WALL_MEDIUM_SIZE', 500);
549
define('IMAGE_WALL_BIG_SIZE', 2000);
550
define('IMAGE_WALL_SMALL', 'small');
551
define('IMAGE_WALL_MEDIUM', 'medium');
552
define('IMAGE_WALL_BIG', 'big');
553
554
// Social PLUGIN PLACES
555
define('SOCIAL_LEFT_PLUGIN', 1);
556
define('SOCIAL_CENTER_PLUGIN', 2);
557
define('SOCIAL_RIGHT_PLUGIN', 3);
558
define('CUT_GROUP_NAME', 50);
559
560
/**
561
 * FormValidator Filter
562
 */
563
define('NO_HTML', 1);
564
define('STUDENT_HTML', 2);
565
define('TEACHER_HTML', 3);
566
define('STUDENT_HTML_FULLPAGE', 4);
567
define('TEACHER_HTML_FULLPAGE', 5);
568
569
// Timeline
570
define('TIMELINE_STATUS_ACTIVE', '1');
571
define('TIMELINE_STATUS_INACTIVE', '2');
572
573
// Event email template class
574
define ('EVENT_EMAIL_TEMPLATE_ACTIVE',  1);
575
define ('EVENT_EMAIL_TEMPLATE_INACTIVE', 0);
576
577
// Course home
578
define('SHORTCUTS_HORIZONTAL', 0);
579
define('SHORTCUTS_VERTICAL', 1);
580
581
// Image class
582
define('IMAGE_PROCESSOR', 'gd'); // 'imagick' or 'gd' strings
583
584
/**
585
 * Inclusion of internationalization libraries
586
 */
587
require_once __DIR__.'/internationalization.lib.php';
588
589
/**
590
 * Returns a path to a certain resource within the Chamilo area, specifyed through a parameter.
591
 * Also, this function provides conversion between path types, in this case the input path points inside the Chamilo area too.
592
 *
593
 * See $_configuration['course_folder'] in the configuration.php to alter the WEB_COURSE_PATH and SYS_COURSE_PATH parameters.
594
 * @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...
595
 * @param string $path (optional)   A path which type is to be converted. Also, it may be a defined constant for a path.
596
 * This parameter has meaning when $type parameter has one of the following values: TO_WEB, TO_SYS, TO_REL. Otherwise it is ignored.
597
 * @return string                   The requested path or the converted path.
598
 *
599
 * A terminology note:
600
 * The defined constants used by this function contain the abbreviations WEB, REL, SYS with the following meaning for types:
601
 * WEB - an absolute URL (we often call it web-path),
602
 * example: http://www.mychamilo.org/chamilo/courses/COURSE01/document/lesson01.html;
603
 *
604
 * REL - represents a semi-absolute URL - a web-path, which is relative to the root web-path of the server, without server's base,
605
 * example: /chamilo/courses/COURSE01/document/lesson01.html;
606
 *
607
 * SYS - represents an absolute path inside the scope of server's file system,
608
 * /var/www/chamilo/courses/COURSE01/document/lesson01.html or
609
 * C:/Inetpub/wwwroot/chamilo/courses/COURSE01/document/lesson01.html.
610
 *
611
 * In some abstract sense we can consider these three path types as absolute.
612
 *
613
 * Notes about the current behaviour model:
614
 * 1. Windows back-slashes are converted to slashes in the result.
615
 * 2. A semi-absolute web-path is detected by its leading slash. On Linux systems, absolute system paths start with
616
 * a slash too, so an additional check about presence of leading system server base is implemented. For example, the function is
617
 * able to distinguish type difference between /var/www/chamilo/courses/ (SYS) and /chamilo/courses/ (REL).
618
 * 3. The function api_get_path() returns only these three types of paths, which in some sense are absolute. The function has
619
 * no a mechanism for processing relative web/system paths, such as: lesson01.html, ./lesson01.html, ../css/my_styles.css.
620
 * It has not been identified as needed yet.
621
 * 4. Also, resolving the meta-symbols "." and ".." within paths has not been implemented, it is to be identified as needed.
622
 *
623
 * Example:
624
 * Assume that your server root is /var/www/ ,
625
 * Chamilo is installed in a sub folder chamilo/ and the URL of your campus is http://www.mychamilo.org
626
 * The other configuration parameters have not been changed.
627
 *
628
 * This is how we can get most used paths, for common purpose:
629
630
 * api_get_path(REL_PATH)                       /chamilo/
631
 * api_get_path(REL_COURSE_PATH)                /chamilo/courses/
632
 * api_get_path(REL_CODE_PATH)                  /chamilo/main/
633
 * api_get_path(REL_UPLOAD_PATH)                /chamilo/app/upload/
634
 * api_get_path(SYS_SERVER_ROOT_PATH)           /var/www/ - This is the physical folder where the system Chamilo has been placed. It is not always equal to $_SERVER['DOCUMENT_ROOT'].
635
 * api_get_path(SYS_PATH)                       /var/www/chamilo/
636
 * api_get_path(SYS_APP_PATH)                   /var/www/chamilo/app/
637
 * api_get_path(SYS_UPLOAD_PATH)                /var/www/chamilo/app/upload/
638
 * api_get_path(SYS_ARCHIVE_PATH)               /var/www/chamilo/app/cache
639
 * api_get_path(SYS_COURSE_PATH)                /var/www/chamilo/app/courses/
640
 * api_get_path(SYS_CSS_PATH)                   /var/www/chamilo/app/Resources/public/css
641
 * api_get_path(SYS_CODE_PATH)                  /var/www/chamilo/main/
642
 * api_get_path(INCLUDE_PATH)                   /var/www/chamilo/main/inc/
643
 * api_get_path(LIBRARY_PATH)                   /var/www/chamilo/main/inc/lib/
644
 * api_get_path(CONFIGURATION_PATH)             /var/www/chamilo/main/inc/conf/
645
 * api_get_path(SYS_LANG_PATH)                  /var/www/chamilo/main/lang/
646
 * api_get_path(SYS_PLUGIN_PATH)                /var/www/chamilo/plugin/
647
 * api_get_path(SYS_TEST_PATH)                  /var/www/chamilo/tests/
648
 * api_get_path(SYS_TEMPLATE_PATH)              /var/www/chamilo/main/template/
649
 * api_get_path(SYS_PUBLIC_PATH)                /var/www/chamilo/web/
650
 *
651
 * api_get_path(WEB_SERVER_ROOT_PATH)           http://www.mychamilo.org/
652
 * api_get_path(WEB_PATH)                       http://www.mychamilo.org/chamilo/
653
 * api_get_path(WEB_COURSE_PATH)                http://www.mychamilo.org/chamilo/courses/
654
 * api_get_path(WEB_CODE_PATH)                  http://www.mychamilo.org/chamilo/main/
655
 * api_get_path(WEB_PLUGIN_PATH)                http://www.mychamilo.org/chamilo/plugin/
656
 * api_get_path(WEB_ARCHIVE_PATH)               http://www.mychamilo.org/chamilo/app/cache/
657
 * api_get_path(WEB_IMG_PATH)                   http://www.mychamilo.org/chamilo/main/img/
658
 * api_get_path(WEB_CSS_PATH)                   http://www.mychamilo.org/chamilo/web/css/
659
 * api_get_path(WEB_LIBRARY_PATH)               http://www.mychamilo.org/chamilo/main/inc/lib/
660
 * api_get_path(WEB_LIBRARY_JS_PATH)            http://www.mychamilo.org/chamilo/web/Chamilo/javascript
661
 * api_get_path(WEB_TEMPLATE_PATH)              http://www.mychamilo.org/chamilo/main/template/
662
 * api_get_path(WEB_UPLOAD_PATH)                http://www.mychamilo.org/chamilo/app/upload/
663
 * api_get_path(WEB_PUBLIC_PATH)                http://www.mychamilo.org/chamilo/web/
664
 *
665
 * This is how we retrieve paths of "registered" resource files (scripts, players, etc.):
666
 * api_get_path(TO_WEB, FLASH_PLAYER_AUDIO)     http://www.mychamilo.org/chamilo/main/inc/lib/mediaplayer/player.swf
667
 * api_get_path(TO_WEB, FLASH_PLAYER_VIDEO)     http://www.mychamilo.org/chamilo/main/inc/lib/mediaplayer/player.swf
668
 * api_get_path(TO_SYS, SCRIPT_SWFOBJECT)       /var/www/chamilo/main/inc/lib/swfobject/swfobject.js
669
 * api_get_path(TO_REL, SCRIPT_ASCIIMATHML)     /chamilo/main/inc/lib/asciimath/ASCIIMathML.js
670
 * ...
671
 *
672
 * We can convert arbitrary paths, that are not registered (no defined constant).
673
 * For guaranteed result, these paths should point inside the system Chamilo.
674
 * Some random examples:
675
 * api_get_path(TO_WEB, $_SERVER['REQUEST_URI'])
676
 * api_get_path(TO_SYS, $_SERVER['PHP_SELF'])
677
 * api_get_path(TO_REL, __FILE__)
678
 * ...
679
 */
680
function api_get_path($path_type, $path = null)
681
{
682
    static $paths = array(
683
        WEB_PATH                => '',
684
        SYS_PATH                => '',
685
        REL_PATH                => '',
686
        WEB_SERVER_ROOT_PATH    => '',
687
        SYS_SERVER_ROOT_PATH    => '',
688
        WEB_COURSE_PATH         => '',
689
        SYS_COURSE_PATH         => '',
690
        REL_COURSE_PATH         => '',
691
        REL_CODE_PATH           => '',
692
        WEB_CODE_PATH           => '',
693
        SYS_CODE_PATH           => '',
694
        SYS_LANG_PATH           => 'lang/',
695
        WEB_IMG_PATH            => 'img/',
696
        WEB_CSS_PATH            => 'web/css/',
697
        SYS_CSS_PATH            => 'app/Resources/public/css/',
698
        SYS_PLUGIN_PATH         => 'plugin/',
699
        WEB_PLUGIN_PATH         => 'plugin/',
700
        SYS_ARCHIVE_PATH        => 'app/cache/',
701
        WEB_ARCHIVE_PATH        => 'app/cache/',
702
        SYS_APP_PATH            => 'app/',
703
        WEB_APP_PATH            => 'app/',
704
        SYS_UPLOAD_PATH         => 'app/upload/',
705
        REL_UPLOAD_PATH         => 'app/upload/',
706
        INCLUDE_PATH            => 'inc/',
707
        LIBRARY_PATH            => 'inc/lib/',
708
        CONFIGURATION_PATH      => 'app/config/',
709
        WEB_LIBRARY_PATH        => 'inc/lib/',
710
        WEB_LIBRARY_JS_PATH     => 'inc/lib/javascript/',
711
        WEB_AJAX_PATH           => 'inc/ajax/',
712
        SYS_TEST_PATH           => 'tests/',
713
        WEB_TEMPLATE_PATH       => 'template/',
714
        WEB_UPLOAD_PATH         => 'app/upload/',
715
        WEB_PUBLIC_PATH         => 'web/',
716
        SYS_TEMPLATE_PATH       => 'template/',
717
        SYS_PUBLIC_PATH         => 'web/',
718
        WEB_FONTS_PATH          => 'fonts/',
719
        SYS_FONTS_PATH          => 'fonts/',
720
    );
721
722
    static $resource_paths = array(
723
        FLASH_PLAYER_AUDIO      => 'inc/lib/mediaplayer/player.swf',
724
        FLASH_PLAYER_VIDEO      => 'inc/lib/mediaplayer/player.swf',
725
        SCRIPT_SWFOBJECT        => 'inc/lib/swfobject/swfobject.js',
726
        SCRIPT_ASCIIMATHML      => 'inc/lib/javascript/asciimath/ASCIIMathML.js',
727
        DRAWING_ASCIISVG        => 'inc/lib/javascript/asciimath/d.svg'
728
    );
729
730
    static $is_this_function_initialized;
731
    static $server_base_web; // No trailing slash.
732
    static $server_base_sys; // No trailing slash.
733
    static $root_web;
734
    static $root_sys;
735
    static $root_rel;
736
737
    // Always load root_web modifications for multiple url features
738
    global $_configuration;
739
    //default $_configuration['root_web'] configuration
740
    $root_web = $_configuration['root_web'];
741
742
    $code_folder = 'main/';
743
    $course_folder = 'courses/';
744
745
    // Configuration data for already installed system.
746
    $root_sys = $_configuration['root_sys'];
747
    $load_new_config = false;
748
749
    // To avoid that the api_get_access_url() function fails since global.inc.php also calls the main_api.lib.php
750
    if ($path_type == WEB_PATH) {
751
        if (isset($_configuration['access_url']) &&  $_configuration['access_url'] != 1) {
752
            //we look into the DB the function api_get_access_url
753
            $url_info = api_get_access_url($_configuration['access_url']);
754
            $root_web = $url_info['active'] == 1 ? $url_info['url'] : $_configuration['root_web'];
755
            $load_new_config = true;
756
        }
757
    }
758
759
    if (!$is_this_function_initialized) {
760
        global $_configuration;
761
762
        $root_rel = $_configuration['url_append'];
763
764
        // Support for the installation process.
765
        // Developers might use the function api_get_path() directly or indirectly (this is difficult to be traced), at the moment when
766
        // configuration has not been created yet. This is why this function should be upgraded to return correct results in this case.
767
768
        if (defined('SYSTEM_INSTALLATION') && SYSTEM_INSTALLATION) {
769
            if (($pos = strpos(($requested_page_rel = api_get_self()), 'main/install')) !== false) {
770
                $root_rel = substr($requested_page_rel, 0, $pos);
771
                // See http://www.mediawiki.org/wiki/Manual:$wgServer
772
                $server_protocol = (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] == 'on') ? 'https' : 'http';
773
                $server_name =
774
                    isset($_SERVER['SERVER_NAME']) ? $_SERVER['SERVER_NAME']
775
                    : (isset($_SERVER['HOSTNAME']) ? $_SERVER['HOSTNAME']
776
                    : (isset($_SERVER['HTTP_HOST']) ? $_SERVER['HTTP_HOST']
777
                    : (isset($_SERVER['SERVER_ADDR']) ? $_SERVER['SERVER_ADDR']
778
                    : 'localhost')));
779
                if (isset($_SERVER['SERVER_PORT']) && !strpos($server_name, ':')
780
                    && (($server_protocol == 'http'
781
                    && $_SERVER['SERVER_PORT'] != 80 ) || ($server_protocol == 'https' && $_SERVER['SERVER_PORT'] != 443 ))) {
782
                    $server_name .= ":" . $_SERVER['SERVER_PORT'];
783
                }
784
                $root_web = $server_protocol.'://'.$server_name.$root_rel;
785
                $root_sys = str_replace('\\', '/', realpath(__DIR__.'/../../../')).'/';
786
                $code_folder = 'main/';
787
            }
788
            // Here we give up, so we don't touch anything.
789
        }
790
791
        // Dealing with trailing slashes.
792
        $root_web       = api_add_trailing_slash($root_web);
793
        $root_sys       = api_add_trailing_slash($root_sys);
794
        $root_rel       = api_add_trailing_slash($root_rel);
795
        $code_folder    = api_add_trailing_slash($code_folder);
796
        $course_folder  = api_add_trailing_slash($course_folder);
797
798
        // Web server base and system server base.
799
        $server_base_web = preg_replace('@'.$root_rel.'$@', '', $root_web); // No trailing slash.
800
        $server_base_sys = preg_replace('@'.$root_rel.'$@', '', $root_sys); // No trailing slash.
801
802
        // Initialization of a table that contains common-purpose paths.
803
        $paths[WEB_PATH]                = $root_web;
804
        $paths[SYS_PATH]                = $root_sys;
805
        $paths[REL_PATH]                = $root_rel;
806
        $paths[WEB_SERVER_ROOT_PATH]    = $server_base_web.'/';
807
        $paths[SYS_SERVER_ROOT_PATH]    = $server_base_sys.'/';
808
809
        $paths[WEB_COURSE_PATH]         = $root_web.$course_folder;
810
811
        $paths[REL_COURSE_PATH]         = $root_rel.$course_folder;
812
        $paths[REL_CODE_PATH]           = $root_rel.$code_folder;
813
        $paths[WEB_CODE_PATH]           = $root_web.$code_folder;
814
        $paths[SYS_CODE_PATH]           = $root_sys.$code_folder;
815
        $paths[REL_UPLOAD_PATH]         = $root_rel.$paths[SYS_UPLOAD_PATH];
816
817
        $paths[WEB_DEFAULT_COURSE_DOCUMENT_PATH] = $paths[WEB_CODE_PATH].'default_course_document/';
818
        $paths[REL_DEFAULT_COURSE_DOCUMENT_PATH] = $paths[REL_PATH].'main/default_course_document/';
819
820
        // Now we can switch into api_get_path() "terminology".
821
        $paths[SYS_LANG_PATH]           = $paths[SYS_CODE_PATH].$paths[SYS_LANG_PATH];
822
823
        $paths[SYS_APP_PATH]            = $paths[SYS_PATH].$paths[SYS_APP_PATH];
824
        $paths[WEB_APP_PATH]            = $paths[WEB_PATH].$paths[WEB_APP_PATH];
825
        $paths[SYS_UPLOAD_PATH]         = $paths[SYS_PATH].$paths[SYS_UPLOAD_PATH];
826
827
        $paths[SYS_PLUGIN_PATH]         = $paths[SYS_PATH].$paths[SYS_PLUGIN_PATH];
828
        $paths[SYS_ARCHIVE_PATH]        = $paths[SYS_PATH].$paths[SYS_ARCHIVE_PATH];
829
        $paths[SYS_TEST_PATH]           = $paths[SYS_PATH].$paths[SYS_TEST_PATH];
830
        $paths[SYS_TEMPLATE_PATH]       = $paths[SYS_CODE_PATH].$paths[SYS_TEMPLATE_PATH];
831
        $paths[SYS_PUBLIC_PATH]         = $paths[SYS_PATH].$paths[SYS_PUBLIC_PATH];
832
        $paths[SYS_CSS_PATH]            = $paths[SYS_PATH].$paths[SYS_CSS_PATH];
833
        $paths[SYS_FONTS_PATH]          = $paths[SYS_CODE_PATH].$paths[SYS_FONTS_PATH];
834
835
        $paths[WEB_CSS_PATH]            = $paths[WEB_PATH].$paths[WEB_CSS_PATH];
836
        $paths[WEB_IMG_PATH]            = $paths[WEB_CODE_PATH].$paths[WEB_IMG_PATH];
837
        $paths[WEB_LIBRARY_PATH]        = $paths[WEB_CODE_PATH].$paths[WEB_LIBRARY_PATH];
838
        $paths[WEB_LIBRARY_JS_PATH]     = $paths[WEB_CODE_PATH].$paths[WEB_LIBRARY_JS_PATH];
839
840
        $paths[WEB_AJAX_PATH]           = $paths[WEB_CODE_PATH].$paths[WEB_AJAX_PATH];
841
        $paths[WEB_FONTS_PATH]          = $paths[WEB_CODE_PATH].$paths[WEB_FONTS_PATH];
842
843
        $paths[WEB_PLUGIN_PATH]         = $paths[WEB_PATH].$paths[WEB_PLUGIN_PATH];
844
        $paths[WEB_ARCHIVE_PATH]        = $paths[WEB_PATH].$paths[WEB_ARCHIVE_PATH];
845
846
        $paths[WEB_TEMPLATE_PATH]       = $paths[WEB_CODE_PATH].$paths[WEB_TEMPLATE_PATH];
847
        $paths[WEB_UPLOAD_PATH]         = $paths[WEB_PATH].$paths[WEB_UPLOAD_PATH];
848
        $paths[WEB_PUBLIC_PATH]         = $paths[WEB_PATH].$paths[WEB_PUBLIC_PATH];
849
850
        $paths[INCLUDE_PATH]            = $paths[SYS_CODE_PATH].$paths[INCLUDE_PATH];
851
        $paths[LIBRARY_PATH]            = $paths[SYS_CODE_PATH].$paths[LIBRARY_PATH];
852
        $paths[CONFIGURATION_PATH]      = $paths[SYS_PATH].$paths[CONFIGURATION_PATH];
853
        $paths[SYS_COURSE_PATH]         = $paths[SYS_APP_PATH].$course_folder;
854
855
        $is_this_function_initialized = true;
856
    } else {
857
        if ($load_new_config) {
858
            //  Redefining variables to work well with the "multiple url" feature
859
860
            // All web paths need to be here
861
            $web_paths = array(
862
                WEB_PATH                => '',
863
                WEB_SERVER_ROOT_PATH    => '',
864
                WEB_COURSE_PATH         => '',
865
                WEB_CODE_PATH           => '',
866
                WEB_IMG_PATH            => 'img/',
867
                WEB_CSS_PATH            => 'web/css/',
868
                WEB_PLUGIN_PATH         => 'plugin/',
869
                WEB_ARCHIVE_PATH        => 'archive/',
870
                WEB_LIBRARY_PATH        => 'inc/lib/',
871
                WEB_AJAX_PATH           => 'inc/ajax/'
872
            );
873
874
            $root_web = api_add_trailing_slash($root_web);
875
            // Web server base and system server base.
876
            $server_base_web = preg_replace('@'.$root_rel.'$@', '', $root_web); // No trailing slash.
877
878
            // Redefine root webs
879
            $paths[WEB_PATH]                = $root_web;
880
            $paths[WEB_SERVER_ROOT_PATH]    = $server_base_web.'/';
881
            $paths[WEB_COURSE_PATH]         = $root_web.$course_folder;
882
            $paths[WEB_CODE_PATH]           = $root_web.$code_folder;
883
            $paths[WEB_IMG_PATH]            = $paths[WEB_CODE_PATH].$web_paths[WEB_IMG_PATH];
884
885
            $paths[WEB_CSS_PATH]            = $paths[WEB_PATH].$web_paths[WEB_CSS_PATH];
886
            $paths[WEB_PLUGIN_PATH]         = $paths[WEB_PATH].$web_paths[WEB_PLUGIN_PATH];
887
            $paths[WEB_ARCHIVE_PATH]        = $paths[WEB_PATH].$web_paths[WEB_ARCHIVE_PATH];
888
            $paths[WEB_LIBRARY_PATH]        = $paths[WEB_CODE_PATH].$web_paths[WEB_LIBRARY_PATH];
889
            $paths[WEB_AJAX_PATH]           = $paths[WEB_CODE_PATH].$web_paths[WEB_AJAX_PATH];
890
            $paths[WEB_FONTS_PATH]          = $paths[WEB_CODE_PATH].$paths[WEB_FONTS_PATH];
891
        }
892
    }
893
894
    // Shallow purification and validation of input parameters.
895
896
    $path_type = trim($path_type);
897
    $path = trim($path);
898
899
    if (empty($path_type)) {
900
        return null;
901
    }
902
903
    // Retrieving a common-purpose path.
904
    if (isset($paths[$path_type])) {
905
        return $paths[$path_type];
906
    }
907
908
    // Retrieving a specific resource path.
909
910
    if (isset($resource_paths[$path])) {
911
        switch ($path_type) {
912
            case TO_WEB:
913
                return $paths[WEB_CODE_PATH].$resource_paths[$path];
914
            case TO_SYS:
915
                return $paths[SYS_CODE_PATH].$resource_paths[$path];
916
            case TO_REL:
917
                return $paths[REL_CODE_PATH].$resource_paths[$path];
918
            default:
919
                return null;
920
        }
921
    }
922
923
    // Common-purpose paths as a second parameter - recognition.
924
925
    if (isset($paths[$path])) {
926
        $path = $paths[$path];
927
    }
928
929
    // Second purification.
930
931
    // Replacing Windows back slashes.
932
    $path = str_replace('\\', '/', $path);
933
    // Query strings sometimes mighth wrongly appear in non-URLs.
934
    // Let us check remove them from all types of paths.
935
    if (($pos = strpos($path, '?')) !== false) {
936
        $path = substr($path, 0, $pos);
937
    }
938
939
    // Detection of the input path type. Conversion to semi-absolute type ( /chamilo/main/inc/.... ).
940
941
    if (preg_match(VALID_WEB_PATH, $path)) {
942
943
        // A special case: When a URL points to the document download script directly, without
944
        // mod-rewrite translation, we have to translate it into an "ordinary" web path.
945
        // For example:
946
        // http://localhost/chamilo/main/document/download.php?doc_url=/image.png&cDir=/
947
        // becomes
948
        // http://localhost/chamilo/courses/TEST/document/image.png
949
        // TEST is a course directory name, so called "system course code".
950
        if (strpos($path, 'download.php') !== false) { // Fast detection first.
951
            $path = urldecode($path);
952
            if (preg_match('/(.*)main\/document\/download.php\?doc_url=\/(.*)&cDir=\/(.*)?/', $path, $matches)) {
953
                $sys_course_code =
954
                    isset($_SESSION['_course']['sysCode'])  // User is inside a course?
955
                        ? $_SESSION['_course']['sysCode']   // Yes, then use course's directory name.
956
                        : '{SYS_COURSE_CODE}';              // No, then use a fake code, it may be processed later.
957
                $path = $matches[1].'courses/'.$sys_course_code.'/document/'.str_replace('//', '/', $matches[3].'/'.$matches[2]);
958
            }
959
        }
960
        // Replacement of the present web server base with a slash '/'.
961
        $path = preg_replace(VALID_WEB_SERVER_BASE, '/', $path);
962
963
    } elseif (strpos($path, $server_base_sys) === 0) {
964
        $path = preg_replace('@^'.$server_base_sys.'@', '', $path);
965
    } elseif (strpos($path, '/') === 0) {
0 ignored issues
show
Unused Code introduced by
This elseif statement is empty, and could be removed.

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

These elseif bodies can be removed. If you have an empty elseif but statements in the else branch, consider inverting the condition.

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

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

Let’s take a look at these examples:

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

// More likely intended return: true/false
return 0 === ($foo & 4);
Loading history...
1216
            isset($course_info['registration_code']) &&
1217
            !empty($course_info['registration_code'])
1218
        ) {
1219
            $is_visible = false;
1220
        }
1221
    }
1222
1223
    //Check session visibility
1224
    $session_id = api_get_session_id();
1225
1226
    if (!empty($session_id)) {
1227
        //$is_allowed_in_course was set in local.inc.php
1228
        if (!$is_allowed_in_course) {
1229
            $is_visible = false;
1230
        }
1231
    }
1232
1233
    if (!$is_visible) {
1234
        api_not_allowed($print_headers);
1235
        return false;
1236
    }
1237
    return true;
1238
}
1239
1240
/**
1241
 * Function used to protect an admin script.
1242
 *
1243
 * The function blocks access when the user has no platform admin rights
1244
 * with an error message printed on default output
1245
 * @param bool Whether to allow session admins as well
1246
 * @param bool Whether to allow HR directors as well
1247
 * @param string An optional message (already passed through get_lang)
1248
 * @return bool True if user is allowed, false otherwise.
1249
 * The function also outputs an error message in case not allowed
1250
 * @author Roan Embrechts (original author)
1251
 */
1252
function api_protect_admin_script($allow_sessions_admins = false, $allow_drh = false, $message = null)
1253
{
1254
    if (!api_is_platform_admin($allow_sessions_admins, $allow_drh)) {
1255
        api_not_allowed(true, $message);
1256
        return false;
1257
    }
1258
    return true;
1259
}
1260
1261
/**
1262
 * Function used to protect a teacher script.
1263
 * The function blocks access when the user has no teacher rights.
1264
 *
1265
 * @author Yoselyn Castillo
1266
 */
1267
function api_protect_teacher_script($allow_sessions_admins = false)
1268
{
1269
    if (!api_is_allowed_to_edit()) {
1270
        api_not_allowed(true);
1271
        return false;
1272
    }
1273
    return true;
1274
}
1275
1276
/**
1277
 * Function used to prevent anonymous users from accessing a script.
1278
 * @param bool|true $printHeaders
1279
 * @author Roan Embrechts
1280
 *
1281
 * @return bool
1282
 */
1283
function api_block_anonymous_users($printHeaders = true)
1284
{
1285
    $user = api_get_user_info();
1286 View Code Duplication
    if (!(isset($user['user_id']) && $user['user_id']) || api_is_anonymous($user['user_id'], true)) {
1287
        api_not_allowed($printHeaders);
1288
        return false;
1289
    }
1290
1291
    return true;
1292
}
1293
1294
/**
1295
 * @return array with the navigator name and version
1296
 */
1297
function api_get_navigator() {
1298
    $navigator = 'Unknown';
1299
    $version = 0;
1300
1301
    if (!isset($_SERVER['HTTP_USER_AGENT'])) {
1302
        return array('name' => 'Unknown', 'version' => '0.0.0');
1303
    }
1304
1305
    if (strpos($_SERVER['HTTP_USER_AGENT'], 'Opera') !== false) {
1306
        $navigator = 'Opera';
1307
        list (, $version) = explode('Opera', $_SERVER['HTTP_USER_AGENT']);
1308 View Code Duplication
    } elseif (strpos($_SERVER['HTTP_USER_AGENT'], 'MSIE') !== false) {
1309
        $navigator = 'Internet Explorer';
1310
        list (, $version) = explode('MSIE', $_SERVER['HTTP_USER_AGENT']);
1311
    } elseif (strpos($_SERVER['HTTP_USER_AGENT'], 'Chrome') !== false) {
1312
        $navigator = 'Chrome';
1313
        list (, $version) = explode('Chrome', $_SERVER['HTTP_USER_AGENT']);
1314
    } elseif (stripos($_SERVER['HTTP_USER_AGENT'], 'safari') !== false) {
1315
        $navigator = 'Safari';
1316
        list (, $version) = explode('Version/', $_SERVER['HTTP_USER_AGENT']);
1317
    } elseif (strpos($_SERVER['HTTP_USER_AGENT'], 'Gecko') !== false) {
1318
        $navigator = 'Mozilla';
1319
        list (, $version) = explode('; rv:', $_SERVER['HTTP_USER_AGENT']);
1320 View Code Duplication
    } elseif (strpos($_SERVER['HTTP_USER_AGENT'], 'Netscape') !== false) {
1321
        $navigator = 'Netscape';
1322
        list (, $version) = explode('Netscape', $_SERVER['HTTP_USER_AGENT']);
1323
    } elseif (strpos($_SERVER['HTTP_USER_AGENT'], 'Konqueror') !== false) {
1324
        $navigator = 'Konqueror';
1325
        list (, $version) = explode('Konqueror', $_SERVER['HTTP_USER_AGENT']);
1326 View Code Duplication
    } elseif (stripos($_SERVER['HTTP_USER_AGENT'], 'applewebkit') !== false) {
1327
        $navigator = 'AppleWebKit';
1328
        list (, $version) = explode('Version/', $_SERVER['HTTP_USER_AGENT']);
1329
    }
1330
    $version = str_replace('/', '', $version);
1331
    if (strpos($version, '.') === false) {
1332
        $version = number_format(doubleval($version), 1);
1333
    }
1334
    $return = array('name' => $navigator, 'version' => $version);
1335
    return $return;
1336
}
1337
1338
/**
1339
 * @return True if user self registration is allowed, false otherwise.
1340
 */
1341
function api_is_self_registration_allowed()
1342
{
1343
    return isset($GLOBALS['allowSelfReg']) ? $GLOBALS['allowSelfReg'] : false;
1344
}
1345
1346
/**
1347
 * This function returns the id of the user which is stored in the $_user array.
1348
 *
1349
 * example: The function can be used to check if a user is logged in
1350
 *          if (api_get_user_id())
1351
 * @return integer the id of the current user, 0 if is empty
1352
 */
1353
function api_get_user_id()
1354
{
1355
    return empty($GLOBALS['_user']['user_id']) ? 0 : intval($GLOBALS['_user']['user_id']);
1356
}
1357
1358
/**
1359
 * Gets the list of courses a specific user is subscribed to
1360
 * @param int       User ID
1361
 * @param boolean   $fetch_session Whether to get session courses or not - NOT YET IMPLEMENTED
1362
 * @return array    Array of courses in the form [0]=>('code'=>xxx,'db'=>xxx,'dir'=>xxx,'status'=>d)
1363
 */
1364
function api_get_user_courses($userid, $fetch_session = true)
1365
{
1366
    // Get out if not integer
1367
    if ($userid != strval(intval($userid))) {
1368
        return array();
1369
    }
1370
1371
    $t_course = Database::get_main_table(TABLE_MAIN_COURSE);
1372
    $t_course_user = Database::get_main_table(TABLE_MAIN_COURSE_USER);
1373
1374
    $sql = "SELECT cc.id as real_id, cc.code code, cc.directory dir, cu.status status
1375
            FROM    $t_course       cc,
1376
                    $t_course_user   cu
1377
            WHERE
1378
                cc.id = cu.c_id AND
1379
                cu.user_id = '".$userid."' AND
1380
                cu.relation_type<>".COURSE_RELATION_TYPE_RRHH." ";
1381
    $result = Database::query($sql);
1382
    if ($result === false) {
1383
        return array();
1384
    }
1385
1386
    $courses = array();
1387
    while ($row = Database::fetch_array($result)) {
1388
        // we only need the database name of the course
1389
        $courses[] = $row;
1390
    }
1391
1392
    return $courses;
1393
}
1394
1395
/**
1396
 * Formats user information into a standard array
1397
 * This function should be only used inside api_get_user_info()
1398
 *
1399
 * @param array Non-standard user array
1400
 * @param bool $add_password
1401
 *
1402
 * @return array Standard user array
1403
 */
1404
function _api_format_user($user, $add_password = false)
1405
{
1406
    $result = array();
1407
1408
    $firstname = null;
1409
    $lastname = null;
1410
1411
    if (isset($user['firstname']) && isset($user['lastname'])) {
1412
        $firstname = $user['firstname'];
1413
        $lastname = $user['lastname'];
1414
    } elseif (isset($user['firstName']) && isset($user['lastName'])) {
1415
        $firstname = isset($user['firstName']) ? $user['firstName'] : null;
1416
        $lastname = isset($user['lastName']) ? $user['lastName'] : null;
1417
    }
1418
1419
    $result['complete_name'] = api_get_person_name($firstname, $lastname);
1420
1421
    $result['complete_name_with_username'] = $result['complete_name'];
1422
1423
    if (!empty($user['username'])) {
1424
        $result['complete_name_with_username'] = $result['complete_name'].' ('.$user['username'].')';
1425
    }
1426
1427
    $result['firstname'] = $firstname;
1428
    $result['lastname'] = $lastname;
1429
1430
    // Kept for historical reasons
1431
    $result['firstName'] = $firstname;
1432
    $result['lastName'] = $lastname;
1433
1434
    $attributes = array(
1435
        'phone',
1436
        'picture_uri',
1437
        'official_code',
1438
        'status',
1439
        'active',
1440
        'auth_source',
1441
        'username',
1442
        'theme',
1443
        'language',
1444
        'creator_id',
1445
        'registration_date',
1446
        'hr_dept_id',
1447
        'expiration_date',
1448
        'last_login'
1449
    );
1450
1451
    foreach ($attributes as $attribute) {
1452
        $result[$attribute] = isset($user[$attribute]) ? $user[$attribute] : null;
1453
    }
1454
1455
    if (isset($user['email'])) {
1456
        $result['mail'] = isset($user['email']) ? $user['email'] : null;
1457
        $result['email'] = isset($user['email'])? $user['email'] : null;
1458
    } else {
1459
        $result['mail'] = isset($user['mail']) ? $user['mail'] : null;
1460
        $result['email'] = isset($user['mail'])? $user['mail'] : null;
1461
    }
1462
    $user_id = intval($user['user_id']);
1463
    // Maintain the user_id index for backwards compatibility
1464
    $result['user_id'] = $result['id'] = $user_id;
1465
1466
    // Getting user avatar.
1467
    $originalFile = UserManager::getUserPicture($user_id, USER_IMAGE_SIZE_ORIGINAL, $result);
1468
    $smallFile = UserManager::getUserPicture($user_id, USER_IMAGE_SIZE_SMALL, $result);
1469
1470
    $result['avatar'] = $originalFile;
1471
    $avatarString = explode('?', $originalFile);
1472
    $result['avatar_no_query'] = reset($avatarString);
1473
    $result['avatar_small'] = $smallFile;
1474
1475
    if (isset($user['user_is_online'])) {
1476
        $result['user_is_online'] = $user['user_is_online'] == true ? 1 : 0;
1477
    }
1478
    if (isset($user['user_is_online_in_chat'])) {
1479
        $result['user_is_online_in_chat'] = intval($user['user_is_online_in_chat']);
1480
    }
1481
1482
    if ($add_password) {
1483
        $result['password'] = $user['password'];
1484
    }
1485
1486
    $result['profile_url'] = api_get_path(WEB_CODE_PATH).'social/profile.php?u='.$user_id;
1487
1488
    if (isset($user['extra'])) {
1489
        $result['extra'] = $user['extra'];
1490
    }
1491
1492
    return $result;
1493
}
1494
1495
/**
1496
 * Finds all the information about a user.
1497
 * If no parameter is passed you find all the information about the current user.
1498
 * @param int  $user_id
1499
 * @param bool $checkIfUserOnline
1500
 * @param bool $showPassword
1501
 * @param bool $loadExtraData
1502
 * @param bool $loadOnlyVisibleExtraData Get the user extra fields that are visible
1503
 * @return array $user_info user_id, lastname, firstname, username, email, etc
1504
 * @author Patrick Cool <[email protected]>
1505
 * @author Julio Montoya
1506
 * @version 21 September 2004
1507
 */
1508
function api_get_user_info(
1509
    $user_id = 0,
1510
    $checkIfUserOnline = false,
1511
    $showPassword = false,
1512
    $loadExtraData = false,
1513
    $loadOnlyVisibleExtraData = false
1514
) {
1515
    if (empty($user_id)) {
1516
        $userFromSession = Session::read('_user');
1517
        if (isset($userFromSession)) {
1518
            return _api_format_user($userFromSession);
1519
        }
1520
        // @todo trigger an exception here
1521
        return false;
1522
    }
1523
1524
    $sql = "SELECT * FROM ".Database :: get_main_table(TABLE_MAIN_USER)."
1525
            WHERE id='".intval($user_id)."'";
1526
    $result = Database::query($sql);
1527
    if (Database::num_rows($result) > 0) {
1528
        $result_array = Database::fetch_array($result);
1529
        if ($checkIfUserOnline) {
1530
            $use_status_in_platform = user_is_online($user_id);
1531
1532
            $result_array['user_is_online'] = $use_status_in_platform;
1533
            $user_online_in_chat = 0;
1534
1535
            if ($use_status_in_platform) {
1536
                $user_status = UserManager::get_extra_user_data_by_field(
1537
                    $user_id,
1538
                    'user_chat_status',
1539
                    false,
1540
                    true
1541
                );
1542
                if (intval($user_status['user_chat_status']) == 1) {
1543
                    $user_online_in_chat = 1;
1544
                }
1545
            }
1546
            $result_array['user_is_online_in_chat'] = $user_online_in_chat;
1547
        }
1548
1549
        if ($loadExtraData) {
1550
            $fieldValue = new ExtraFieldValue('user');
1551
1552
            $result_array['extra'] = $fieldValue->getAllValuesForAnItem(
1553
                $user_id,
1554
                $loadOnlyVisibleExtraData
1555
            );
1556
        }
1557
        $user = _api_format_user($result_array, $showPassword);
1558
1559
        return $user;
1560
    }
1561
    return false;
1562
}
1563
1564
/**
1565
 * Finds all the information about a user from username instead of user id
1566
 * @param string $username
1567
 * @return array $user_info array user_id, lastname, firstname, username, email
1568
 * @author Yannick Warnier <[email protected]>
1569
 */
1570 View Code Duplication
function api_get_user_info_from_username($username = '')
1571
{
1572
    if (empty($username)) {
1573
        return false;
1574
    }
1575
    $username = trim($username);
1576
1577
    $sql = "SELECT * FROM ".Database :: get_main_table(TABLE_MAIN_USER)."
1578
            WHERE username='".Database::escape_string($username)."'";
1579
    $result = Database::query($sql);
1580
    if (Database::num_rows($result) > 0) {
1581
        $result_array = Database::fetch_array($result);
1582
        return _api_format_user($result_array);
1583
    }
1584
    return false;
1585
}
1586
1587
/**
1588
 * Get first user with an email
1589
 * @param string $email
1590
 * @return array|bool
1591
 */
1592 View Code Duplication
function api_get_user_info_from_email($email = '')
1593
{
1594
    if (empty($email)) {
1595
        return false;
1596
    }
1597
    $sql = "SELECT * FROM ".Database :: get_main_table(TABLE_MAIN_USER)."
1598
            WHERE email ='".Database::escape_string($email)."' LIMIT 1";
1599
    $result = Database::query($sql);
1600
    if (Database::num_rows($result) > 0) {
1601
        $result_array = Database::fetch_array($result);
1602
        return _api_format_user($result_array);
1603
    }
1604
1605
    return false;
1606
}
1607
1608
/**
1609
 * @return string
1610
 */
1611
function api_get_course_id()
1612
{
1613
    return isset($GLOBALS['_cid']) ? $GLOBALS['_cid'] : null;
1614
}
1615
1616
/**
1617
 * Returns the current course id
1618
 * @return int
1619
 */
1620
function api_get_real_course_id()
1621
{
1622
    return api_get_course_int_id();
1623
}
1624
1625
/**
1626
 * Returns the current course id (integer)
1627
 * @param   string  $code   Optional course code
1628
 * @return int
1629
 */
1630
function api_get_course_int_id($code = null)
1631
{
1632 View Code Duplication
    if (!empty($code)) {
1633
        $code = Database::escape_string($code);
1634
        $row = Database::select(
1635
            'id',
1636
            Database::get_main_table(TABLE_MAIN_COURSE),
1637
            array('where'=> array('code = ?' => array($code))),
1638
            'first'
1639
        );
1640
1641
        if (is_array($row) && isset($row['id'])) {
1642
            return $row['id'];
1643
        } else {
1644
            return false;
1645
        }
1646
    }
1647
    return Session::read('_real_cid', 0);
1648
}
1649
1650
/**
1651
 * Returns the current course directory
1652
 *
1653
 * This function relies on api_get_course_info()
1654
 * @param string    The course code - optional (takes it from session if not given)
1655
 * @return string   The directory where the course is located inside the Chamilo "courses" directory
1656
 * @author Yannick Warnier <[email protected]>
1657
 */
1658
function api_get_course_path($course_code = null)
1659
{
1660
    $info = !empty($course_code) ? api_get_course_info($course_code) : api_get_course_info();
1661
    return $info['path'];
1662
}
1663
1664
/**
1665
 * Gets a course setting from the current course_setting table. Try always using integer values.
1666
 * @param string    The name of the setting we want from the table
1667
 * @param string    Optional: course code
1668
 * @return mixed    The value of that setting in that table. Return -1 if not found.
1669
 */
1670
function api_get_course_setting($setting_name, $course_code = null)
1671
{
1672
    $course_info = api_get_course_info($course_code);
1673
    $table = Database::get_course_table(TABLE_COURSE_SETTING);
1674
    $setting_name = Database::escape_string($setting_name);
1675 View Code Duplication
    if (!empty($course_info['real_id']) && !empty($setting_name)) {
1676
        $sql = "SELECT value FROM $table
1677
                WHERE c_id = {$course_info['real_id']} AND variable = '$setting_name'";
1678
        $res = Database::query($sql);
1679
        if (Database::num_rows($res) > 0) {
1680
            $row = Database::fetch_array($res);
1681
            return $row['value'];
1682
        }
1683
    }
1684
    return -1;
1685
}
1686
1687
/**
1688
 * Gets an anonymous user ID
1689
 *
1690
 * For some tools that need tracking, like the learnpath tool, it is necessary
1691
 * to have a usable user-id to enable some kind of tracking, even if not
1692
 * perfect. An anonymous ID is taken from the users table by looking for a
1693
 * status of "6" (anonymous).
1694
 * @return int  User ID of the anonymous user, or O if no anonymous user found
1695
 */
1696
function api_get_anonymous_id()
1697
{
1698
    $table = Database::get_main_table(TABLE_MAIN_USER);
1699
    $sql = "SELECT user_id FROM $table WHERE status = ".ANONYMOUS;
1700
    $res = Database::query($sql);
1701
    if (Database::num_rows($res) > 0) {
1702
        $row = Database::fetch_array($res);
1703
        return $row['user_id'];
1704
    }
1705
1706
    // No anonymous user was found.
1707
    return 0;
1708
}
1709
1710
/**
1711
 * Returns the cidreq parameter name + current course id taken from
1712
 * $GLOBALS['_cid'] and returns a string like 'cidReq=ABC&id_session=123
1713
 *
1714
 * @param bool $addSessionId
1715
 * @param bool $addGroupId
1716
 * @return  string  Course & session references to add to a URL
1717
 *
1718
 */
1719
function api_get_cidreq($addSessionId = true, $addGroupId = true)
1720
{
1721
    $url = empty($GLOBALS['_cid']) ? '' : 'cidReq='.htmlspecialchars($GLOBALS['_cid']);
1722
    $origin = api_get_origin();
1723
1724
    if ($addSessionId) {
1725
        if (!empty($url)) {
1726
            $url .= api_get_session_id() == 0 ? '&id_session=0' : '&id_session='.api_get_session_id();
1727
        }
1728
    }
1729
1730
    if ($addGroupId) {
1731
        if (!empty($url)) {
1732
            $url .= api_get_group_id() == 0 ? '&gidReq=0' : '&gidReq='.api_get_group_id();
1733
        }
1734
    }
1735
1736
    $url .= '&gradebook='.intval(api_is_in_gradebook());
1737
    $url .= '&origin='.$origin;
1738
1739
    return $url;
1740
}
1741
1742
function api_is_in_gradebook()
1743
{
1744
    return Session::read('in_gradebook', false);
1745
}
1746
1747
function api_set_in_gradebook()
1748
{
1749
    Session::write('in_gradebook', true);
1750
}
1751
1752
function api_remove_in_gradebook()
1753
{
1754
    Session::erase('in_gradebook');
1755
}
1756
1757
/**
1758
 * Returns the current course info array see api_format_course_array()
1759
 * If the course_code is given, the returned array gives info about that
1760
 * particular course, if none given it gets the course info from the session.
1761
 *
1762
 * @param string $course_code
1763
 * @param bool $strict
1764
 *
1765
 * @return array
1766
 */
1767
function api_get_course_info($course_code = null, $strict = false)
1768
{
1769
    if (!empty($course_code)) {
1770
        $course_code = Database::escape_string($course_code);
1771
        $courseId = api_get_course_int_id($course_code);
1772
1773
        if (empty($courseId)) {
1774
            return array();
1775
        }
1776
1777
        $course_table = Database::get_main_table(TABLE_MAIN_COURSE);
1778
        $course_cat_table = Database::get_main_table(TABLE_MAIN_CATEGORY);
1779
        $sql = "SELECT
1780
                    course.*,
1781
                    course_category.code faCode,
1782
                    course_category.name faName
1783
                FROM $course_table
1784
                LEFT JOIN $course_cat_table
1785
                ON course.category_code = course_category.code
1786
                WHERE course.id = $courseId";
1787
        $result = Database::query($sql);
1788
        $courseInfo = array();
1789
        if (Database::num_rows($result) > 0) {
1790
            $data = Database::fetch_array($result);
1791
            $courseInfo = api_format_course_array($data);
1792
        }
1793
1794
        return $courseInfo;
1795
    }
1796
1797
    global $_course;
1798
    if ($_course == '-1') {
1799
        $_course = array();
1800
    }
1801
1802
    return $_course;
1803
}
1804
1805
/**
1806
 * Returns the current course info array.
1807
1808
 * Now if the course_code is given, the returned array gives info about that
1809
 * particular course, not specially the current one.
1810
 * @param int $id Numeric ID of the course
1811
 * @return array The course info as an array formatted by api_format_course_array, including category.name
1812
 */
1813 View Code Duplication
function api_get_course_info_by_id($id = null)
1814
{
1815
    if (!empty($id)) {
1816
        $id = intval($id);
1817
        $course_table = Database::get_main_table(TABLE_MAIN_COURSE);
1818
        $course_cat_table = Database::get_main_table(TABLE_MAIN_CATEGORY);
1819
        $sql = "SELECT
1820
                    course.*,
1821
                    course_category.code faCode,
1822
                    course_category.name faName
1823
                FROM $course_table
1824
                LEFT JOIN $course_cat_table
1825
                ON course.category_code =  course_category.code
1826
                WHERE course.id = $id";
1827
        $result = Database::query($sql);
1828
        $_course = array();
1829
        if (Database::num_rows($result) > 0) {
1830
            $course_data = Database::fetch_array($result);
1831
            $_course = api_format_course_array($course_data);
1832
        }
1833
        return $_course;
1834
    }
1835
1836
    global $_course;
1837
    if ($_course == '-1') $_course = array();
1838
    return $_course;
1839
}
1840
1841
/**
1842
 * Reformat the course array (output by api_get_course_info()) in order, mostly,
1843
 * to switch from 'code' to 'id' in the array. This is a legacy feature and is
1844
 * now possibly causing massive confusion as a new "id" field has been added to
1845
 * the course table in 1.9.0.
1846
 * @param $course_data
1847
 * @return array
1848
 * @todo eradicate the false "id"=code field of the $_course array and use the int id
1849
 */
1850
function api_format_course_array($course_data)
1851
{
1852
    if (empty($course_data)) {
1853
        return array();
1854
    }
1855
1856
    $_course = array();
1857
    $_course['id'] = $course_data['code'];
1858
    $_course['real_id'] = $course_data['id'];
1859
1860
    // Added
1861
    $_course['code'] = $course_data['code'];
1862
    $_course['name'] = $course_data['title'];
1863
    $_course['title'] = $course_data['title'];
1864
    $_course['official_code'] = $course_data['visual_code'];
1865
    $_course['visual_code'] = $course_data['visual_code'];
1866
    $_course['sysCode'] = $course_data['code'];
1867
    $_course['path'] = $course_data['directory']; // Use as key in path.
1868
    $_course['directory'] = $course_data['directory'];
1869
    $_course['creation_date'] = $course_data['creation_date'];
1870
    $_course['titular'] = $course_data['tutor_name'];
1871
    $_course['language'] = $course_data['course_language'];
1872
    $_course['extLink']['url'] = $course_data['department_url'];
1873
    $_course['extLink']['name'] = $course_data['department_name'];
1874
    $_course['categoryCode'] = $course_data['faCode'];
1875
    $_course['categoryName'] = $course_data['faName'];
1876
    $_course['visibility'] = $course_data['visibility'];
1877
    $_course['subscribe_allowed'] = $course_data['subscribe'];
1878
    $_course['subscribe'] = $course_data['subscribe'];
1879
    $_course['unsubscribe'] = $course_data['unsubscribe'];
1880
    $_course['course_language'] = $course_data['course_language'];
1881
    $_course['activate_legal'] = isset($course_data['activate_legal']) ? $course_data['activate_legal'] : false;
1882
    $_course['legal'] = $course_data['legal'];
1883
    $_course['show_score'] = $course_data['show_score']; //used in the work tool
1884
    $_course['department_name'] = $course_data['department_name'];
1885
    $_course['department_url'] = $course_data['department_url'];
1886
1887
    // Course password
1888
    $_course['registration_code'] = !empty($course_data['registration_code']) ? sha1($course_data['registration_code']) : null;
1889
    $_course['disk_quota'] = $course_data['disk_quota'];
1890
    $_course['course_public_url'] = api_get_path(WEB_COURSE_PATH).$course_data['directory'].'/index.php';
1891
1892
    if (array_key_exists('add_teachers_to_sessions_courses', $course_data)) {
1893
        $_course['add_teachers_to_sessions_courses'] = $course_data['add_teachers_to_sessions_courses'];
1894
    }
1895
1896
    if (file_exists(api_get_path(SYS_COURSE_PATH).$course_data['directory'].'/course-pic85x85.png')) {
1897
        $url_image = api_get_path(WEB_COURSE_PATH).$course_data['directory'].'/course-pic85x85.png';
1898
    } else {
1899
        $url_image = Display::return_icon('course.png', null, null, ICON_SIZE_BIG, null, true, false);
1900
    }
1901
    $_course['course_image'] = $url_image;
1902
1903
    if (file_exists(api_get_path(SYS_COURSE_PATH).$course_data['directory'].'/course-pic.png')) {
1904
        $url_image = api_get_path(WEB_COURSE_PATH).$course_data['directory'].'/course-pic.png';
1905
    } else {
1906
        $url_image = Display::returnIconPath('session_default.png');
1907
    }
1908
    $_course['course_image_large'] = $url_image;
1909
1910
    return $_course;
1911
}
1912
1913
/**
1914
 * Add a parameter to the existing URL. If this parameter already exists,
1915
 * just replace it with the new value
1916
 * @param   string  The URL
1917
 * @param   string  param=value string
1918
 * @param   boolean Whether to filter XSS or not
1919
 * @return  string  The URL with the added parameter
1920
 */
1921
function api_add_url_param($url, $param, $filter_xss = true) {
1922
    if (empty($param)) {
1923
        return $url;
1924
    }
1925
    if (strpos($url, '?') !== false) {
1926
        if ($param[0] != '&') {
1927
            $param = '&'.$param;
1928
        }
1929
        list (, $query_string) = explode('?', $url);
1930
        $param_list1 = explode('&', $param);
1931
        $param_list2 = explode('&', $query_string);
1932
        $param_list1_keys = $param_list1_vals = array();
1933
        foreach ($param_list1 as $key => $enreg) {
1934
            list ($param_list1_keys[$key], $param_list1_vals[$key]) = explode('=', $enreg);
1935
        }
1936
        $param_list1 = array ('keys' => $param_list1_keys, 'vals' => $param_list1_vals);
1937
        foreach ($param_list2 as $enreg) {
1938
            $enreg = explode('=', $enreg);
1939
            $key = array_search($enreg[0], $param_list1['keys']);
1940
            if (!is_null($key) && !is_bool($key)) {
1941
                $url = str_replace($enreg[0].'='.$enreg[1], $enreg[0].'='.$param_list1['vals'][$key], $url);
1942
                $param = str_replace('&'.$enreg[0].'='.$param_list1['vals'][$key], '', $param);
1943
            }
1944
        }
1945
        $url .= $param;
1946
    } else {
1947
        $url = $url.'?'.$param;
1948
    }
1949
    if ($filter_xss === true) {
1950
        $url = Security::remove_XSS(urldecode($url));
1951
    }
1952
    return $url;
1953
}
1954
1955
/**
1956
 * Returns a difficult to guess password.
1957
 * @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...
1958
 * @return string the generated password
1959
 */
1960
function api_generate_password($length = 8) {
1961
    $characters = 'abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ23456789';
1962
    if ($length < 2) {
1963
        $length = 2;
1964
    }
1965
    $password = '';
1966
    for ($i = 0; $i < $length; $i ++) {
1967
        $password .= $characters[rand() % strlen($characters)];
1968
    }
1969
    return $password;
1970
}
1971
1972
/**
1973
 * Checks a password to see wether it is OK to use.
1974
 * @param string $password
1975
 * @return true if the password is acceptable, false otherwise
1976
 * Notes about what a password "OK to use" is:
1977
 * 1. The password should be at least 5 characters long.
1978
 * 2. Only English letters (uppercase or lowercase, it doesn't matter) and digits are allowed.
1979
 * 3. The password should contain at least 3 letters.
1980
 * 4. It should contain at least 2 digits.
1981
 * 5. It should not contain 3 or more consequent (according to ASCII table) characters.
1982
 */
1983
function api_check_password($password) {
1984
    $password_length = api_strlen($password);
1985
    if ($password_length < 5) {
1986
        return false;
1987
    }
1988
    $password = api_strtolower($password);
1989
    $letters = 0;
1990
    $digits = 0;
1991
    $consequent_characters = 0;
1992
    $previous_character_code = 0;
1993
    for ($i = 0; $i < $password_length; $i ++) {
1994
        $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...
1995
        if ($i && abs($current_character_code - $previous_character_code) <= 1) {
1996
            $consequent_characters ++;
1997
            if ($consequent_characters == 3) {
1998
                return false;
1999
            }
2000
        } else {
2001
            $consequent_characters = 1;
2002
        }
2003
        if ($current_character_code >= 97 && $current_character_code <= 122) {
2004
            $letters ++;
2005
        } elseif ($current_character_code >= 48 && $current_character_code <= 57) {
2006
            $digits ++;
2007
        } else {
2008
            return false;
2009
        }
2010
        $previous_character_code = $current_character_code;
2011
    }
2012
    return ($letters >= 3 && $digits >= 2);
2013
}
2014
2015
/**
2016
 * Clears the user ID from the session if it was the anonymous user. Generally
2017
 * used on out-of-tools pages to remove a user ID that could otherwise be used
2018
 * in the wrong context.
2019
 * This function is to be used in conjunction with the api_set_anonymous()
2020
 * function to simulate the user existence in case of an anonymous visit.
2021
 * @param bool      database check switch - passed to api_is_anonymous()
2022
 * @return bool     true if succesfully unregistered, false if not anonymous.
2023
 */
2024
function api_clear_anonymous($db_check = false) {
2025
    global $_user;
2026
    if (api_is_anonymous($_user['user_id'], $db_check)) {
2027
        unset($_user['user_id']);
2028
        Session::erase('_uid');
2029
        return true;
2030
    }
2031
    return false;
2032
}
2033
2034
/**
2035
 * Returns the status string corresponding to the status code
2036
 * @author Noel Dieschburg
2037
 * @param the int status code
2038
 */
2039
function get_status_from_code($status_code) {
2040
    switch ($status_code) {
2041
        case STUDENT:
2042
            return get_lang('Student', '');
2043
        case TEACHER:
2044
            return get_lang('Teacher', '');
2045
        case COURSEMANAGER:
2046
            return get_lang('Manager', '');
2047
        case SESSIONADMIN:
2048
            return get_lang('SessionsAdmin', '');
2049
        case DRH:
2050
            return get_lang('Drh', '');
2051
    }
2052
}
2053
2054
/* FAILURE MANAGEMENT */
2055
2056
/**
2057
 * The Failure Management module is here to compensate
2058
 * the absence of an 'exception' device in PHP 4.
2059
 */
2060
2061
/**
2062
 * $api_failureList - array containing all the failure recorded in order of arrival.
2063
 */
2064
$api_failureList = array();
2065
2066
/**
2067
 * Fills a global array called $api_failureList
2068
 * This array collects all the failure occuring during the script runs
2069
 * The main purpose is allowing to manage the display messages externaly
2070
 * from the functions or objects. This strengthens encupsalation principle
2071
 *
2072
 * @author Hugues Peeters <[email protected]>
2073
 * @param  string $failure_type - the type of failure
2074
 * global: array $api_failureList
2075
 * @return boolean false to stay consistent with the main script
2076
 */
2077
function api_set_failure($failure_type) {
2078
    global $api_failureList;
2079
    $api_failureList[] = $failure_type;
2080
    return false;
2081
}
2082
2083
/**
2084
 * Sets the current user as anonymous if it hasn't been identified yet. This
2085
 * function should be used inside a tool only. The function api_clear_anonymous()
2086
 * acts in the opposite direction by clearing the anonymous user's data every
2087
 * time we get on a course homepage or on a neutral page (index, admin, my space)
2088
 * @return bool     true if set user as anonymous, false if user was already logged in or anonymous id could not be found
2089
 */
2090
function api_set_anonymous() {
2091
    global $_user;
2092
2093
    if (!empty($_user['user_id'])) {
2094
        return false;
2095
    }
2096
2097
    $user_id = api_get_anonymous_id();
2098
    if ($user_id == 0) {
2099
        return false;
2100
    }
2101
    Session::erase('_user');
2102
    $_user['user_id'] = $user_id;
2103
    $_user['is_anonymous'] = true;
2104
    $GLOBALS['_user'] = $_user;
2105
    Session::write('_user', $_user);
2106
    return true;
2107
}
2108
2109
/**
2110
 * Gets the last failure stored in $api_failureList;
2111
 *
2112
 * @author Hugues Peeters <[email protected]>
2113
 * @param void
2114
 * @return string - the last failure stored
2115
 */
2116
function api_get_last_failure() {
2117
    global $api_failureList;
2118
    return $api_failureList[count($api_failureList) - 1];
2119
}
2120
2121
/**
2122
 * Collects and manages failures occurring during script execution
2123
 * The main purpose is allowing to manage the display messages externally
2124
 * from functions or objects. This strengthens encapsulation principle
2125
 *
2126
 * @author Hugues Peeters <[email protected]>
2127
 * @package chamilo.library
2128
 */
2129
class api_failure {
2130
2131
    // TODO: $api_failureList to be hidden from global scope and to be renamed according to our coding conventions.
2132
    /**
2133
     * IMPLEMENTATION NOTE : For now the $api_failureList list is set to the
2134
     * global scope, as PHP 4 is unable to manage static variable in class. But
2135
     * this feature is awaited in PHP 5. The class is already written to minize
2136
     * the change when static class variable will be possible. And the API won't
2137
     * change.
2138
     */
2139
    public $api_failureList = array();
2140
2141
    /**
2142
     * Piles the last failure in the failure list
2143
     *
2144
     * @author Hugues Peeters <[email protected]>
2145
     * @param  string $failure_type - the type of failure
2146
     * @global array  $api_failureList
2147
     * @return bolean false to stay consistent with the main script
2148
     */
2149
    static function set_failure($failure_type) {
2150
        global $api_failureList;
2151
        $api_failureList[] = $failure_type;
2152
        return false;
2153
    }
2154
2155
    /**
2156
     * Gets the last failure stored
2157
     *
2158
     * @author Hugues Peeters <[email protected]>
2159
     * @param void
2160
     * @return string - the last failure stored
2161
     */
2162
    static function get_last_failure() {
2163
        global $api_failureList;
2164
        if (count($api_failureList) == 0) { return ''; }
2165
        return $api_failureList[count($api_failureList) - 1];
2166
    }
2167
}
2168
2169
2170
/* CONFIGURATION SETTINGS */
2171
2172
/**
2173
 * Gets the current Chamilo (not PHP/cookie) session ID
2174
 * @return  int     O if no active session, the session ID otherwise
2175
 */
2176
function api_get_session_id()
2177
{
2178
    return Session::read('id_session', 0);
2179
}
2180
2181
/**
2182
 * Gets the current Chamilo (not social network) group ID
2183
 * @return  int     O if no active session, the session ID otherwise
2184
 */
2185
function api_get_group_id()
2186
{
2187
    return Session::read('_gid', 0);
2188
}
2189
2190
2191
/**
2192
 * Gets the current or given session name
2193
 * @param   int     Session ID (optional)
2194
 * @return  string  The session name, or null if unfound
2195
 */
2196
function api_get_session_name($session_id) {
2197
    if (empty($session_id)) {
2198
        $session_id = api_get_session_id();
2199
        if (empty($session_id)) { return null; }
2200
    }
2201
    $t = Database::get_main_table(TABLE_MAIN_SESSION);
2202
    $s = "SELECT name FROM $t WHERE id = ".(int)$session_id;
2203
    $r = Database::query($s);
2204
    $c = Database::num_rows($r);
2205
    if ($c > 0) {
2206
        //technically, there can be only one, but anyway we take the first
2207
        $rec = Database::fetch_array($r);
2208
        return $rec['name'];
2209
    }
2210
    return null;
2211
}
2212
2213
/**
2214
 * Gets the session info by id
2215
 * @param int       Session ID
2216
 * @return array    information of the session
2217
 */
2218
function api_get_session_info($session_id)
2219
{
2220
    $data = array();
2221
    if (!empty($session_id)) {
2222
        $session_id = intval($session_id);
2223
        $tbl_session = Database::get_main_table(TABLE_MAIN_SESSION);
2224
        $sql = "SELECT * FROM $tbl_session WHERE id = $session_id";
2225
        $result = Database::query($sql);
2226
2227
        if (Database::num_rows($result)>0) {
2228
            $data = Database::fetch_array($result, 'ASSOC');
2229
        }
2230
    }
2231
2232
    return $data;
2233
}
2234
2235
/**
2236
 * Gets the session visibility by session id
2237
 * @param int $session_id
2238
 * @param int $courseId
2239
 * @param bool $ignore_visibility_for_admins
2240
 * @return int
2241
 *  0 = session still available,
2242
 *  SESSION_VISIBLE_READ_ONLY = 1,
2243
 *  SESSION_VISIBLE = 2,
2244
 *  SESSION_INVISIBLE = 3
2245
 */
2246
function api_get_session_visibility(
2247
    $session_id,
2248
    $courseId = null,
2249
    $ignore_visibility_for_admins = true
2250
) {
2251
    // Means that the session is still available.
2252
    $visibility = 0;
2253
2254
    if (api_is_platform_admin()) {
2255
        if ($ignore_visibility_for_admins) {
2256
            return SESSION_AVAILABLE;
2257
        }
2258
    }
2259
2260
    $now = time();
2261
    if (!empty($session_id)) {
2262
        $session_id = intval($session_id);
2263
        $tbl_session = Database::get_main_table(TABLE_MAIN_SESSION);
2264
2265
        $sql = "SELECT * FROM $tbl_session
2266
                WHERE id = $session_id ";
2267
2268
        $result = Database::query($sql);
2269
2270
        if (Database::num_rows($result) > 0) {
2271
            $row = Database::fetch_array($result, 'ASSOC');
2272
            $visibility = $original_visibility = $row['visibility'];
2273
2274
            // I don't care the session visibility.
2275
            if (empty($row['access_start_date']) && empty($row['access_end_date'])) {
2276
2277
                // Session duration per student.
2278
                if (isset($row['duration']) && !empty($row['duration'])) {
2279
                    $duration = $row['duration'] * 24 * 60 * 60;
2280
2281
                    $courseAccess = CourseManager::getFirstCourseAccessPerSessionAndUser(
2282
                        $session_id,
2283
                        api_get_user_id()
2284
                    );
2285
2286
                    // If there is a session duration but there is no previous
2287
                    // access by the user, then the session is still available
2288
                    if (count($courseAccess) == 0) {
2289
                        return SESSION_AVAILABLE;
2290
                    }
2291
2292
                    $currentTime = time();
2293
                    $firstAccess = 0;
2294
                    if (isset($courseAccess['login_course_date'])) {
2295
                        $firstAccess = api_strtotime(
2296
                            $courseAccess['login_course_date'],
2297
                            'UTC'
2298
                        );
2299
                    }
2300
                    $userDurationData = SessionManager::getUserSession(
2301
                        api_get_user_id(),
2302
                        $session_id
2303
                    );
2304
                    $userDuration = 0;
2305
                    if (isset($userDurationData['duration'])) {
2306
                        $userDuration = intval($userDurationData['duration']) * 24 * 60 * 60;
2307
                    }
2308
2309
                    $totalDuration = $firstAccess + $duration + $userDuration;
2310
                    if ($totalDuration > $currentTime) {
2311
                        return SESSION_AVAILABLE;
2312
                    } else {
2313
                        return SESSION_INVISIBLE;
2314
                    }
2315
                }
2316
2317
                return SESSION_AVAILABLE;
2318
            } else {
2319
2320
                // If start date was set.
2321
                if (!empty($row['access_start_date'])) {
2322
                    if ($now > api_strtotime($row['access_start_date'], 'UTC')) {
2323
                        $visibility = SESSION_AVAILABLE;
2324
                    } else {
2325
                        $visibility = SESSION_INVISIBLE;
2326
                    }
2327
                }
2328
2329
                // If the end date was set.
2330 View Code Duplication
                if (!empty($row['access_end_date'])) {
2331
                    // Only if date_start said that it was ok
2332
                    if ($visibility == SESSION_AVAILABLE) {
2333
                        if ($now < api_strtotime($row['access_end_date'], 'UTC')) {
2334
                            // Date still available
2335
                            $visibility = SESSION_AVAILABLE;
2336
                        } else {
2337
                            // Session ends
2338
                            $visibility = $row['visibility'];
2339
                        }
2340
                    }
2341
                }
2342
            }
2343
2344
            /* If I'm a coach the visibility can change in my favor depending in
2345
             the coach dates */
2346
            $is_coach = api_is_coach($session_id, $courseId);
2347
2348
            if ($is_coach) {
2349
                // Test end date.
2350 View Code Duplication
                if (!empty($row['coach_access_end_date'])) {
2351
                    $endDateCoach = api_strtotime($row['coach_access_end_date'], 'UTC');
2352
2353
                    if ($endDateCoach >= $now) {
2354
                        $visibility = SESSION_AVAILABLE;
2355
                    } else {
2356
                        $visibility = SESSION_INVISIBLE;
2357
                    }
2358
                }
2359
2360
                // Test start date.
2361 View Code Duplication
                if (!empty($row['coach_access_start_date'])) {
2362
                    $start = api_strtotime($row['coach_access_start_date'], 'UTC');
2363
                    if ($start < $now) {
2364
                        $visibility = SESSION_AVAILABLE;
2365
                    } else {
2366
                        $visibility = SESSION_INVISIBLE;
2367
                    }
2368
                }
2369
            }
2370
        } else {
2371
            $visibility = SESSION_INVISIBLE;
2372
        }
2373
    }
2374
2375
    return $visibility;
2376
}
2377
2378
/**
2379
 * This function returns a (star) session icon if the session is not null and
2380
 * the user is not a student
2381
 * @param int   $session_id
2382
 * @param int   $status_id User status id - if 5 (student), will return empty
2383
 * @return string   Session icon
2384
 */
2385
function api_get_session_image($session_id, $status_id)
2386
{
2387
    $session_id = (int)$session_id;
2388
    $session_img = '';
2389
    if ((int)$status_id != 5) { //check whether is not a student
2390
        if ($session_id > 0) {
2391
            $session_img = "&nbsp;&nbsp;".Display::return_icon(
2392
                'star.png',
2393
                get_lang('SessionSpecificResource'),
2394
                array('align' => 'absmiddle'),
2395
                ICON_SIZE_SMALL
2396
            );
2397
        }
2398
    }
2399
    return $session_img;
2400
}
2401
2402
/**
2403
 * This function add an additional condition according to the session of the course
2404
 * @param int       $session_id session id
2405
 * @param bool      $and optional, true if more than one condition false if the only condition in the query
2406
 * @param bool      $with_base_content optional, true to accept content with session=0 as well, false for strict session condition
2407
 * @return string   condition of the session
2408
 */
2409
function api_get_session_condition(
2410
    $session_id,
2411
    $and = true,
2412
    $with_base_content = false,
2413
    $session_field = "session_id"
2414
) {
2415
    $session_id = intval($session_id);
2416
2417
    if (empty($session_field)) {
2418
        $session_field = "session_id";
2419
    }
2420
    // Condition to show resources by session
2421
    $condition_add = $and ? " AND " : " WHERE ";
2422
2423
    if ($with_base_content) {
2424
        $condition_session = $condition_add." ( $session_field = $session_id OR $session_field = 0 OR $session_field IS NULL) ";
2425
    } else {
2426
        if (empty($session_id)) {
2427
            $condition_session = $condition_add." ($session_field = $session_id OR $session_field IS NULL)";
2428
        } else {
2429
            $condition_session = $condition_add." $session_field = $session_id ";
2430
        }
2431
    }
2432
    return $condition_session;
2433
}
2434
2435
/**
2436
 * This function returns information about coaches from a course in session
2437
 * @param int       optional, session id
2438
 * @param int $courseId
2439
 * @return array     array containing user_id, lastname, firstname, username
2440
 * @deprecated use CourseManager::get_coaches_from_course
2441
 */
2442
function api_get_coachs_from_course($session_id = 0, $courseId = '')
2443
{
2444
    if (!empty($session_id)) {
2445
        $session_id = intval($session_id);
2446
    } else {
2447
        $session_id = api_get_session_id();
2448
    }
2449
2450
    if (!empty($courseId)) {
2451
        $courseId = intval($courseId);
2452
    } else {
2453
        $courseId = api_get_course_int_id();
2454
    }
2455
2456
    $tbl_user = Database:: get_main_table(TABLE_MAIN_USER);
2457
    $tbl_session_course_user = Database:: get_main_table(TABLE_MAIN_SESSION_COURSE_USER);
2458
    $coaches = array();
2459
2460
    $sql = "SELECT
2461
                u.user_id,
2462
                u.lastname,
2463
                u.firstname,
2464
                u.username
2465
            FROM $tbl_user u, $tbl_session_course_user scu
2466
            WHERE
2467
              u.user_id = scu.user_id AND
2468
              scu.session_id = '$session_id' AND
2469
              scu.c_id = '$courseId' AND
2470
              scu.status = 2";
2471
    $rs = Database::query($sql);
2472
2473
    if (Database::num_rows($rs) > 0) {
2474
        while ($row = Database::fetch_array($rs)) {
2475
            $coaches[] = $row;
2476
        }
2477
2478
        return $coaches;
2479
    } else {
2480
2481
        return false;
2482
    }
2483
}
2484
2485
/**
2486
 * Returns the value of a setting from the web-adjustable admin config settings.
2487
 *
2488
 * WARNING true/false are stored as string, so when comparing you need to check e.g.
2489
 * if (api_get_setting('show_navigation_menu') == 'true') //CORRECT
2490
 * instead of
2491
 * if (api_get_setting('show_navigation_menu') == true) //INCORRECT
2492
 * @param string    $variable The variable name
2493
 * @param string    $key The subkey (sub-variable) if any. Defaults to NULL
2494
 * @author René Haentjens
2495
 * @author Bart Mollet
2496
 */
2497
function api_get_setting($variable, $key = null)
2498
{
2499
    global $_setting;
2500 View Code Duplication
    if ($variable == 'header_extra_content') {
2501
        $filename = api_get_path(SYS_PATH).api_get_home_path().'header_extra_content.txt';
2502
        if (file_exists($filename)) {
2503
            $value = file_get_contents($filename);
2504
            return $value ;
2505
        } else {
2506
            return '';
2507
        }
2508
    }
2509 View Code Duplication
    if ($variable == 'footer_extra_content') {
2510
        $filename = api_get_path(SYS_PATH).api_get_home_path().'footer_extra_content.txt';
2511
        if (file_exists($filename)) {
2512
            $value = file_get_contents($filename);
2513
            return $value ;
2514
        } else {
2515
            return '';
2516
        }
2517
    }
2518
    $value = null;
2519
    if (is_null($key)) {
2520
        $value = ((isset($_setting[$variable]) && $_setting[$variable] != '') ? $_setting[$variable] : null);
2521
    } else {
2522
        if (isset($_setting[$variable][$key])) {
2523
            $value = $_setting[$variable][$key];
2524
        }
2525
    }
2526
2527
    return $value;
2528
}
2529
2530
/**
2531
 * @param string $plugin
2532
 * @param string $variable
2533
 * @return string
2534
 */
2535
function api_get_plugin_setting($plugin, $variable)
2536
{
2537
    $variableName = $plugin.'_'.$variable;
2538
    $result = api_get_setting($variableName);
2539
    if (isset($result[$plugin])) {
2540
        return $result[$plugin];
2541
    }
2542
2543
    return null;
2544
}
2545
2546
/**
2547
 * Returns the value of a setting from the web-adjustable admin config settings.
2548
 **/
2549
function api_get_settings_params($params) {
2550
    $table = Database::get_main_table(TABLE_MAIN_SETTINGS_CURRENT);
2551
    $result = Database::select('*', $table, array('where' => $params));
2552
    return $result;
2553
}
2554
2555
function api_get_settings_params_simple($params) {
2556
    $table = Database::get_main_table(TABLE_MAIN_SETTINGS_CURRENT);
2557
    $result = Database::select('*', $table, array('where' => $params), 'one');
2558
    return $result;
2559
}
2560
2561
/**
2562
 * Returns the value of a setting from the web-adjustable admin config settings.
2563
 **/
2564
function api_delete_settings_params($params) {
2565
    $table = Database::get_main_table(TABLE_MAIN_SETTINGS_CURRENT);
2566
    $result = Database::delete($table, $params);
2567
    return $result;
2568
}
2569
2570
/**
2571
 * Returns an escaped version of $_SERVER['PHP_SELF'] to avoid XSS injection
2572
 * @return string   Escaped version of $_SERVER['PHP_SELF']
2573
 */
2574
function api_get_self() {
2575
    return htmlentities($_SERVER['PHP_SELF']);
2576
}
2577
2578
/* USER PERMISSIONS */
2579
2580
/**
2581
 * Checks whether current user is a platform administrator
2582
 * @param boolean Whether session admins should be considered admins or not
2583
 * @param boolean Whether HR directors should be considered admins or not
2584
 * @return boolean True if the user has platform admin rights,
2585
 * false otherwise.
2586
 * @see usermanager::is_admin(user_id) for a user-id specific function
2587
 */
2588
function api_is_platform_admin($allow_sessions_admins = false, $allow_drh = false)
2589
{
2590
    if (isset($_SESSION['is_platformAdmin']) && $_SESSION['is_platformAdmin']) {
2591
        return true;
2592
    }
2593
    $_user = api_get_user_info();
2594
    return
2595
        isset($_user['status']) &&
2596
        (
2597
            ($allow_sessions_admins && $_user['status'] == SESSIONADMIN) ||
2598
            ($allow_drh && $_user['status'] == DRH)
2599
        );
2600
}
2601
2602
/**
2603
 * Checks whether the user given as user id is in the admin table.
2604
 * @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...
2605
 * @param int $url URL ID. If provided, also check if the user is active on given URL
2606
 * @result bool True if the user is admin, false otherwise
2607
 */
2608
function api_is_platform_admin_by_id($user_id = null, $url = null)
2609
{
2610
    $user_id = intval($user_id);
2611
    if (empty($user_id)) {
2612
        $user_id = api_get_user_id();
2613
    }
2614
    $admin_table = Database::get_main_table(TABLE_MAIN_ADMIN);
2615
    $sql = "SELECT * FROM $admin_table WHERE user_id = $user_id";
2616
    $res = Database::query($sql);
2617
    $is_admin = Database::num_rows($res) === 1;
2618
    if (!$is_admin or !isset($url)) {
2619
        return $is_admin;
2620
    }
2621
    // We get here only if $url is set
2622
    $url = intval($url);
2623
    $url_user_table = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_USER);
2624
    $sql = "SELECT * FROM $url_user_table
2625
            WHERE access_url_id = $url AND user_id = $user_id";
2626
    $res = Database::query($sql);
2627
    $is_on_url = Database::num_rows($res) === 1;
2628
2629
    return $is_on_url;
2630
}
2631
2632
/**
2633
 * Returns the user's numeric status ID from the users table
2634
 * @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...
2635
 * @result int User's status (1 for teacher, 5 for student, etc)
2636
 */
2637
function api_get_user_status($user_id = null)
2638
{
2639
    $user_id = intval($user_id);
2640
    if (empty($user_id)) {
2641
        $user_id = api_get_user_id();
2642
    }
2643
    $table = Database::get_main_table(TABLE_MAIN_USER);
2644
    $sql = "SELECT status FROM $table WHERE user_id = $user_id ";
2645
    $result = Database::query($sql);
2646
    $status = null;
2647
    if (Database::num_rows($result)) {
2648
        $row = Database::fetch_array($result);
2649
        $status = $row['status'];
2650
    }
2651
    return $status;
2652
}
2653
2654
/**
2655
 * Checks whether current user is allowed to create courses
2656
 * @return boolean True if the user has course creation rights,
2657
 * false otherwise.
2658
 */
2659
function api_is_allowed_to_create_course() {
2660
    return Session::read('is_allowedCreateCourse');
2661
}
2662
2663
/**
2664
 * Checks whether the current user is a course administrator
2665
 * @return boolean True if current user is a course administrator
2666
 */
2667
function api_is_course_admin() {
2668
    if (api_is_platform_admin()) {
2669
        return true;
2670
    }
2671
    return Session::read('is_courseAdmin');
2672
}
2673
2674
/**
2675
 * Checks whether the current user is a course coach
2676
 * @return bool     True if current user is a course coach
2677
 */
2678
function api_is_course_coach() {
2679
    return Session::read('is_courseCoach');
2680
}
2681
2682
/**
2683
 * Checks whether the current user is a course tutor
2684
 * @return bool     True if current user is a course tutor
2685
 */
2686
function api_is_course_tutor() {
2687
    return Session::read('is_courseTutor');
2688
}
2689
2690
/**
2691
 * @param int $user_id
2692
 *
2693
 * @return array
2694
 */
2695
function api_get_user_platform_status($user_id = null) {
2696
    $status     = array();
2697
    $user_id    = intval($user_id);
2698
    if (empty($user_id)) {
2699
        $user_id = api_get_user_id();
2700
    }
2701
2702
    if (empty($user_id)) {
2703
        return false;
2704
    }
2705
    $group_id   = api_get_group_id();
2706
    $course_id  = api_get_course_int_id();
2707
    $course_code= api_get_course_id();
2708
    $session_id = api_get_session_id();
2709
2710
    //Group (in course)
2711
    if ($group_id && $course_id) {
2712
        $group_status = array();
2713
        $is_subscribed = GroupManager::is_subscribed($user_id, $group_id);
2714
        if ($is_subscribed) {
2715
            $group_status = array('id'=> $group_id , 'status' => 'student');
2716
            $is_tutor = GroupManager::is_tutor_of_group($user_id, $group_id);
2717
            if ($is_tutor) {
2718
                $group_status['status'] = 'tutor';
2719
            } else {
2720
                $group_status['status'] = 'student';
2721
            }
2722
        }
2723
        $status['group'] = $group_status;
2724
    }
2725
2726
    //Session
2727
    if ($session_id && $course_id) {
2728
        $session_status = array('id' => $session_id, 'course_id' => $course_id);
2729
        $session_user_status = SessionManager::get_user_status_in_course_session(
2730
            $user_id,
2731
            $course_id,
2732
            $session_id
2733
        );
2734
2735
        switch ($session_user_status) {
2736
            case 0:
2737
                $session_status['status'] = 'student';
2738
               break;
2739
            case 2:
2740
                $session_status['status'] = 'coach';
2741
            break;
2742
        }
2743
        $is_general_coach = SessionManager::user_is_general_coach($user_id, $session_id);
2744
        if ($is_general_coach) {
2745
            $session_status['status'] = 'general_coach';
2746
        }
2747
        $status['session'] = $session_status;
2748
2749
    } elseif($course_id) {
2750
        //Course
2751
        $course_status = array();
2752
        if ($course_id) {
2753
            $user_course_status = CourseManager::get_user_in_course_status($user_id, $course_code);
2754
2755
            if ($user_course_status) {
2756
                $course_status = array('id'=> $course_id);
2757
                switch($user_course_status) {
2758
                    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...
2759
                        $course_status['status'] = 'teacher';
2760
                    break;
2761
                    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...
2762
                        $course_status['status'] = 'student';
2763
                        //check if tutor
2764
                        $tutor_course_status = CourseManager::get_tutor_in_course_status($user_id, $course_code);
2765
                        if ($tutor_course_status) {
2766
                            $course_status['status'] = 'tutor';
2767
                        }
2768
                    break;
2769
                }
2770
            }
2771
        }
2772
        $status['course'] = $course_status;
2773
    }
2774
2775
    return $status;
2776
}
2777
2778
/**
2779
 * @param int $user_id
2780
 * @param int $courseId
2781
 * @param int $session_id
2782
 * @return bool
2783
 */
2784
function api_is_course_session_coach($user_id, $courseId, $session_id)
2785
{
2786
    $session_table = Database::get_main_table(TABLE_MAIN_SESSION);
2787
    $session_rel_course_rel_user_table  = Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER);
2788
2789
    $user_id = intval($user_id);
2790
    $session_id = intval($session_id);
2791
    $courseId = intval($courseId);
2792
2793
    $sql = "SELECT DISTINCT session.id
2794
            FROM $session_table
2795
            INNER JOIN $session_rel_course_rel_user_table session_rc_ru
2796
            ON session.id = session_rc_ru.session_id
2797
            WHERE
2798
                session_rc_ru.user_id = '".$user_id."'  AND
2799
                session_rc_ru.c_id = '$courseId' AND
2800
                session_rc_ru.status = 2 AND
2801
                session_rc_ru.session_id = '$session_id'";
2802
    $result = Database::query($sql);
2803
2804
    return Database::num_rows($result) > 0;
2805
}
2806
2807
/**
2808
 * Checks whether the current user is a course or session coach
2809
 * @param int $session_id
2810
 * @param int $courseId
2811
 * @param bool  Check whether we are in student view and, if we are, return false
2812
 * @return boolean True if current user is a course or session coach
2813
 */
2814
function api_is_coach($session_id = 0, $courseId = null, $check_student_view = true)
2815
{
2816
    $userId = api_get_user_id();
2817
2818
    if (!empty($session_id)) {
2819
        $session_id = intval($session_id);
2820
    } else {
2821
        $session_id = api_get_session_id();
2822
    }
2823
2824
    // The student preview was on
2825 View Code Duplication
    if ($check_student_view &&
2826
        isset($_SESSION['studentview']) && $_SESSION['studentview'] == "studentview"
2827
    ) {
2828
        return false;
2829
    }
2830
2831
    if (!empty($courseId)) {
2832
        $courseId = intval($courseId);
2833
    } else {
2834
        $courseId = api_get_course_int_id();
2835
    }
2836
2837
    $session_table = Database::get_main_table(TABLE_MAIN_SESSION);
2838
    $session_rel_course_rel_user_table = Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER);
2839
    $sessionIsCoach = null;
2840
2841
    if (!empty($courseId)) {
2842
        $sql = "SELECT DISTINCT s.id, name, access_start_date, access_end_date
2843
                FROM $session_table s
2844
                INNER JOIN $session_rel_course_rel_user_table session_rc_ru
2845
                ON session_rc_ru.session_id = s.id AND session_rc_ru.user_id = '".$userId."'
2846
                WHERE
2847
                    session_rc_ru.c_id = '$courseId' AND
2848
                    session_rc_ru.status = 2 AND
2849
                    session_rc_ru.session_id = '$session_id'";
2850
        $result = Database::query($sql);
2851
        $sessionIsCoach = Database::store_result($result);
2852
    }
2853
2854 View Code Duplication
    if (!empty($session_id)) {
2855
        $sql = "SELECT DISTINCT id, name, access_start_date, access_end_date
2856
                FROM $session_table
2857
                WHERE session.id_coach =  '".$userId."' AND id = '$session_id'
2858
                ORDER BY access_start_date, access_end_date, name";
2859
        $result = Database::query($sql);
2860
        if (!empty($sessionIsCoach)) {
2861
            $sessionIsCoach = array_merge($sessionIsCoach , Database::store_result($result));
2862
        } else {
2863
            $sessionIsCoach = Database::store_result($result);
2864
        }
2865
    }
2866
2867
    return (count($sessionIsCoach) > 0);
2868
}
2869
2870
/**
2871
 * Checks whether the current user is a session administrator
2872
 * @return boolean True if current user is a course administrator
2873
 */
2874
function api_is_session_admin()
2875
{
2876
    $user = api_get_user_info();
2877
    return isset($user['status']) && $user['status'] == SESSIONADMIN;
2878
}
2879
2880
/**
2881
 * Checks whether the current user is a human resources manager
2882
 * @return boolean True if current user is a human resources manager
2883
 */
2884
function api_is_drh()
2885
{
2886
    $user = api_get_user_info();
2887
    return isset($user['status']) && $user['status'] == DRH;
2888
}
2889
2890
/**
2891
 * Checks whether the current user is a student
2892
 * @return boolean True if current user is a human resources manager
2893
 */
2894
function api_is_student()
2895
{
2896
    $user = api_get_user_info();
2897
    return isset($user['status']) && $user['status'] == STUDENT;
2898
2899
}
2900
/**
2901
 * Checks whether the current user has the status 'teacher'
2902
 * @return boolean True if current user is a human resources manager
2903
 */
2904
function api_is_teacher()
2905
{
2906
    $user = api_get_user_info();
2907
    return isset($user['status']) && $user['status'] == COURSEMANAGER;
2908
}
2909
2910
/**
2911
 * Checks whether the current user is a invited user
2912
 * @return boolean
2913
 */
2914
function api_is_invitee()
2915
{
2916
    $user = api_get_user_info();
2917
2918
    return isset($user['status']) && $user['status'] == INVITEE;
2919
}
2920
2921
/**
2922
 * This function checks whether a session is assigned into a category
2923
 * @param int       - session id
2924
 * @param string    - category name
2925
 * @return bool     - true if is found, otherwise false
2926
 */
2927
function api_is_session_in_category($session_id, $category_name)
2928
{
2929
    $session_id = intval($session_id);
2930
    $category_name = Database::escape_string($category_name);
2931
2932
    $tbl_session = Database::get_main_table(TABLE_MAIN_SESSION);
2933
    $tbl_session_category = Database::get_main_table(TABLE_MAIN_SESSION_CATEGORY);
2934
2935
    $sql = "SELECT 1
2936
            FROM $tbl_session
2937
            WHERE $session_id IN (
2938
                SELECT s.id FROM $tbl_session s, $tbl_session_category sc
2939
                WHERE
2940
                  s.session_category_id = sc.id AND
2941
                  sc.name LIKE '%$category_name'
2942
            )";
2943
    $rs = Database::query($sql);
2944
2945
    if (Database::num_rows($rs) > 0) {
2946
        return true;
2947
    } else {
2948
        return false;
2949
    }
2950
}
2951
2952
/* DISPLAY OPTIONS
2953
   student view, title, message boxes,... */
2954
2955
/**
2956
 * Displays the title of a tool.
2957
 * Normal use: parameter is a string:
2958
 * api_display_tool_title("My Tool")
2959
 *
2960
 * Optionally, there can be a subtitle below
2961
 * the normal title, and / or a supra title above the normal title.
2962
 *
2963
 * e.g. supra title:
2964
 * group
2965
 * GROUP PROPERTIES
2966
 *
2967
 * e.g. subtitle:
2968
 * AGENDA
2969
 * calender & events tool
2970
 *
2971
 * @author Hugues Peeters <[email protected]>
2972
 * @param  mixed $title_element - it could either be a string or an array
2973
 *                               containing 'supraTitle', 'mainTitle',
2974
 *                               'subTitle'
2975
 * @return void
2976
 */
2977
function api_display_tool_title($title_element) {
2978
    if (is_string($title_element)) {
2979
        $tit = $title_element;
2980
        unset ($title_element);
2981
        $title_element['mainTitle'] = $tit;
2982
    }
2983
    echo '<h3>';
2984
    if (!empty($title_element['supraTitle'])) {
2985
        echo '<small>'.$title_element['supraTitle'].'</small><br />';
2986
    }
2987
    if (!empty($title_element['mainTitle'])) {
2988
        echo $title_element['mainTitle'];
2989
    }
2990
    if (!empty($title_element['subTitle'])) {
2991
        echo '<br /><small>'.$title_element['subTitle'].'</small>';
2992
    }
2993
    echo '</h3>';
2994
}
2995
2996
/**
2997
 * Displays options for switching between student view and course manager view
2998
 *
2999
 * Changes in version 1.2 (Patrick Cool)
3000
 * Student view switch now behaves as a real switch. It maintains its current state until the state
3001
 * is changed explicitly
3002
 *
3003
 * Changes in version 1.1 (Patrick Cool)
3004
 * student view now works correctly in subfolders of the document tool
3005
 * student view works correctly in the new links tool
3006
 *
3007
 * Example code for using this in your tools:
3008
 * //if ($is_courseAdmin && api_get_setting('student_view_enabled') == 'true') {
3009
 * //   display_tool_view_option($isStudentView);
3010
 * //}
3011
 * //and in later sections, use api_is_allowed_to_edit()
3012
 *
3013
 * @author Roan Embrechts
3014
 * @author Patrick Cool
3015
 * @author Julio Montoya, changes added in Chamilo
3016
 * @version 1.2
3017
 * @todo rewrite code so it is easier to understand
3018
 */
3019
function api_display_tool_view_option() {
3020
    if (api_get_setting('student_view_enabled') != 'true') {
3021
        return '';
3022
    }
3023
3024
    $sourceurl = '';
3025
    $is_framed = false;
3026
    // Exceptions apply for all multi-frames pages
3027
    if (strpos($_SERVER['REQUEST_URI'], 'chat/chat_banner.php') !== false) {
3028
        // The chat is a multiframe bit that doesn't work too well with the student_view, so do not show the link
3029
        return '';
3030
    }
3031
3032
    // Uncomment to remove student view link from document view page
3033
    if (strpos($_SERVER['REQUEST_URI'], 'newscorm/lp_header.php') !== false) {
3034
        if (empty($_GET['lp_id'])) {
3035
            return '';
3036
        }
3037
        $sourceurl = substr($_SERVER['REQUEST_URI'], 0, strpos($_SERVER['REQUEST_URI'], '?'));
3038
        $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);
3039
        //showinframes doesn't handle student view anyway...
3040
        //return '';
3041
        $is_framed = true;
3042
    }
3043
3044
    // Check whether the $_SERVER['REQUEST_URI'] contains already url parameters (thus a questionmark)
3045
    if (!$is_framed) {
3046
        if (strpos($_SERVER['REQUEST_URI'], '?') === false) {
3047
            $sourceurl = api_get_self().'?'.api_get_cidreq();
3048
        } else {
3049
            $sourceurl = $_SERVER['REQUEST_URI'];
3050
            //$sourceurl = str_replace('&', '&amp;', $sourceurl);
3051
        }
3052
    }
3053
3054
    $output_string = '';
3055
    if (!empty($_SESSION['studentview'])) {
3056
        if ($_SESSION['studentview'] == 'studentview') {
3057
            // We have to remove the isStudentView=true from the $sourceurl
3058
            $sourceurl = str_replace('&isStudentView=true', '', $sourceurl);
3059
            $sourceurl = str_replace('&isStudentView=false', '', $sourceurl);
3060
            $output_string .= '<a class="btn btn-success btn-xs" href="'.$sourceurl.'&isStudentView=false" target="_self">'.get_lang('SwitchToTeacherView').'</a>';
3061
        } elseif ($_SESSION['studentview'] == 'teacherview') {
3062
            // Switching to teacherview
3063
            $sourceurl = str_replace('&isStudentView=true', '', $sourceurl);
3064
            $sourceurl = str_replace('&isStudentView=false', '', $sourceurl);
3065
            $output_string .= '<a class="btn btn-primary btn-xs" href="'.$sourceurl.'&isStudentView=true" target="_self">'.get_lang('SwitchToStudentView').'</a>';
3066
        }
3067
    } else {
3068
        $output_string .= '<a class="btn btn-primary btn-xs" href="'.$sourceurl.'&isStudentView=true" target="_self">'.get_lang('SwitchToStudentView').'</a>';
3069
    }
3070
    return $output_string;
3071
}
3072
3073
// TODO: This is for the permission section.
3074
/**
3075
 * Function that removes the need to directly use is_courseAdmin global in
3076
 * tool scripts. It returns true or false depending on the user's rights in
3077
 * this particular course.
3078
 * Optionally checking for tutor and coach roles here allows us to use the
3079
 * student_view feature altogether with these roles as well.
3080
 * @param bool  Whether to check if the user has the tutor role
3081
 * @param bool  Whether to check if the user has the coach role
3082
 * @param bool  Whether to check if the user has the session coach role
3083
 * @param bool  check the student view or not
3084
 *
3085
 * @author Roan Embrechts
3086
 * @author Patrick Cool
3087
 * @author Julio Montoya
3088
 * @version 1.1, February 2004
3089
 * @return boolean, true: the user has the rights to edit, false: he does not
3090
 */
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...
3091
3092
function api_is_allowed_to_edit($tutor = false, $coach = false, $session_coach = false, $check_student_view = true)
3093
{
3094
    $my_session_id = api_get_session_id();
3095
    $is_allowed_coach_to_edit = api_is_coach(null, null, $check_student_view);
3096
    $session_visibility = api_get_session_visibility($my_session_id);
3097
3098
    // Admins can edit anything.
3099
    if (api_is_platform_admin(false)) {
3100
        //The student preview was on
3101 View Code Duplication
        if ($check_student_view &&
3102
            isset($_SESSION['studentview']) &&
3103
            $_SESSION['studentview'] == "studentview"
3104
        ) {
3105
            return false;
3106
        } else {
3107
            return true;
3108
        }
3109
    }
3110
3111
    $is_courseAdmin = api_is_course_admin();
3112
3113
    if (!$is_courseAdmin && $tutor) {
3114
        // If we also want to check if the user is a tutor...
3115
        $is_courseAdmin = $is_courseAdmin || api_is_course_tutor();
3116
    }
3117
3118
    if (!$is_courseAdmin && $coach) {
3119
        // If we also want to check if the user is a coach...';
3120
        // Check if session visibility is read only for coaches.
3121
        if ($session_visibility == SESSION_VISIBLE_READ_ONLY) {
3122
            $is_allowed_coach_to_edit = false;
3123
        }
3124
3125
        if (api_get_setting('allow_coach_to_edit_course_session') == 'true') {
3126
            // Check if coach is allowed to edit a course.
3127
            $is_courseAdmin = $is_courseAdmin || $is_allowed_coach_to_edit;
3128
        } else {
3129
            $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...
3130
        }
3131
    }
3132
3133
    if (!$is_courseAdmin && $session_coach) {
3134
        $is_courseAdmin = $is_courseAdmin || $is_allowed_coach_to_edit;
3135
    }
3136
3137
    // Check if the student_view is enabled, and if so, if it is activated.
3138
    if (api_get_setting('student_view_enabled') == 'true') {
3139
        if (!empty($my_session_id)) {
3140
            // Check if session visibility is read only for coaches.
3141
            if ($session_visibility == SESSION_VISIBLE_READ_ONLY) {
3142
                $is_allowed_coach_to_edit = false;
3143
            }
3144
3145
            if (api_get_setting('allow_coach_to_edit_course_session') == 'true') {
3146
                // Check if coach is allowed to edit a course.
3147
                $is_allowed = $is_allowed_coach_to_edit;
3148
            } else {
3149
                $is_allowed = false;
3150
            }
3151
            if ($check_student_view) {
3152
                $is_allowed = $is_allowed && $_SESSION['studentview'] != 'studentview';
3153
            }
3154
        } else {
3155
            if ($check_student_view) {
3156
                $is_allowed = $is_courseAdmin && $_SESSION['studentview'] != 'studentview';
3157
            } else {
3158
                $is_allowed = $is_courseAdmin;
3159
            }
3160
        }
3161
3162
        return $is_allowed;
3163
    } else {
3164
3165
        return $is_courseAdmin;
3166
    }
3167
}
3168
3169
/**
3170
* Checks if a student can edit contents in a session depending
3171
* on the session visibility
3172
* @param bool $tutor  Whether to check if the user has the tutor role
3173
* @param bool  $coach Whether to check if the user has the coach role
3174
* @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...
3175
*/
3176
function api_is_allowed_to_session_edit($tutor = false, $coach = false)
3177
{
3178
    if (api_is_allowed_to_edit($tutor, $coach)) {
3179
        // If I'm a teacher, I will return true in order to not affect the normal behaviour of Chamilo tools.
3180
        return true;
3181
    } else {
3182
        if (api_get_session_id() == 0) {
3183
            // I'm not in a session so i will return true to not affect the normal behaviour of Chamilo tools.
3184
            return true;
3185
        } else {
3186
            // I'm in a session and I'm a student
3187
            $session_id = api_get_session_id();
3188
3189
            // Get the session visibility
3190
            $session_visibility = api_get_session_visibility($session_id);
3191
            // if 5 the session is still available
3192
3193
            //@todo We could load the session_rel_course_rel_user permission to increase the level of detail.
3194
            //echo api_get_user_id();
3195
            //echo api_get_course_id();
3196
3197
            switch ($session_visibility) {
3198
                case SESSION_VISIBLE_READ_ONLY: // 1
3199
                    return false;
3200
                case SESSION_VISIBLE:           // 2
3201
                    return true;
3202
                case SESSION_INVISIBLE:         // 3
3203
                    return false;
3204
                case SESSION_AVAILABLE:         //5
3205
                    return true;
3206
            }
3207
3208
        }
3209
    }
3210
}
3211
3212
/**
3213
* Checks whether the user is allowed in a specific tool for a specific action
3214
* @param $tool the tool we are checking if the user has a certain permission
3215
* @param $action the action we are checking (add, edit, delete, move, visibility)
3216
* @author Patrick Cool <[email protected]>, Ghent University
3217
* @author Julio Montoya
3218
* @version 1.0
3219
*/
3220
function api_is_allowed($tool, $action, $task_id = 0)
3221
{
3222
    $_user = api_get_user_info();
3223
    $_course = api_get_course_info();
3224
3225
    if (api_is_course_admin()) {
3226
        return true;
3227
    }
3228
    //if (!$_SESSION['total_permissions'][$_course['code']] and $_course)
3229
    if (is_array($_course) and count($_course) > 0) {
3230
        require_once api_get_path(SYS_CODE_PATH).'permissions/permissions_functions.inc.php';
3231
3232
        // Getting the permissions of this user.
3233
        if ($task_id == 0) {
3234
            $user_permissions = get_permissions('user', $_user['user_id']);
3235
            $_SESSION['total_permissions'][$_course['code']] = $user_permissions;
3236
        }
3237
3238
        // Getting the permissions of the task.
3239
        if ($task_id != 0) {
3240
            $task_permissions = get_permissions('task', $task_id);
3241
            /* !!! */$_SESSION['total_permissions'][$_course['code']] = $task_permissions;
3242
        }
3243
        //print_r($_SESSION['total_permissions']);
3244
3245
        // Getting the permissions of the groups of the user
3246
        //$groups_of_user = GroupManager::get_group_ids($_course['db_name'], $_user['user_id']);
3247
3248
        //foreach($groups_of_user as $group)
3249
        //   $this_group_permissions = get_permissions('group', $group);
3250
3251
        // Getting the permissions of the courseroles of the user
3252
        $user_courserole_permissions = get_roles_permissions('user', $_user['user_id']);
3253
3254
        // Getting the permissions of the platformroles of the user
3255
        //$user_platformrole_permissions = get_roles_permissions('user', $_user['user_id'], ', platform');
3256
3257
        // Getting the permissions of the roles of the groups of the user
3258
        //foreach($groups_of_user as $group)
3259
        //    $this_group_courserole_permissions = get_roles_permissions('group', $group);
3260
3261
        // Getting the permissions of the platformroles of the groups of the user
3262
        //foreach($groups_of_user as $group)
3263
        //    $this_group_platformrole_permissions = get_roles_permissions('group', $group, 'platform');
3264
    }
3265
3266
    // If the permissions are limited, we have to map the extended ones to the limited ones.
3267
    if (api_get_setting('permissions') == 'limited') {
3268
        if ($action == 'Visibility') {
3269
            $action = 'Edit';
3270
        }
3271
        if ($action == 'Move') {
3272
            $action = 'Edit';
3273
        }
3274
    }
3275
3276
    // The session that contains all the permissions already exists for this course
3277
    // so there is no need to requery everything.
3278
    //my_print_r($_SESSION['total_permissions'][$_course['code']][$tool]);
3279
    if (is_array($_SESSION['total_permissions'][$_course['code']][$tool])) {
3280
        if (in_array($action, $_SESSION['total_permissions'][$_course['code']][$tool])) {
3281
            return true;
3282
        } else {
3283
            return false;
3284
        }
3285
    }
3286
}
3287
3288
/**
3289
 * Tells whether this user is an anonymous user
3290
 * @param int  $user_id      User ID (optional, will take session ID if not provided)
3291
 * @param bool $db_check     Whether to check in the database (true) or simply in
3292
 * the session (false) to see if the current user is the anonymous user
3293
 * @return bool     true if this user is anonymous, false otherwise
3294
 */
3295
function api_is_anonymous($user_id = null, $db_check = false) {
3296
    if (!isset($user_id)) {
3297
        $user_id = api_get_user_id();
3298
    }
3299
    if ($db_check) {
3300
        $info = api_get_user_info($user_id);
3301
        if ($info['status'] == ANONYMOUS) {
3302
            return true;
3303
        }
3304
    }
3305
3306
    $_user = api_get_user_info();
3307
    if (isset($_user['status']) && $_user['status'] == ANONYMOUS) {
3308
        //if ($_user['user_id'] == 0) {
3309
        // In some cases, api_set_anonymous doesn't seem to be triggered in local.inc.php. Make sure it is.
3310
        // Occurs in agenda for admin links - YW
3311
        global $use_anonymous;
3312
        if (isset($use_anonymous) && $use_anonymous) {
3313
            api_set_anonymous();
3314
        }
3315
3316
        return true;
3317
    }
3318
3319
    return ((isset($_user['is_anonymous']) && $_user['is_anonymous'] === true) || $_user === false);
3320
}
3321
3322
/**
3323
 * Displays message "You are not allowed here..." and exits the entire script.
3324
 * @param bool   $print_headers    Whether or not to print headers (default = false -> does not print them)
3325
 * @param string $message
3326
 */
3327
function api_not_allowed($print_headers = false, $message = null)
3328
{
3329
    if (api_get_setting('sso_authentication') === 'true') {
3330
        global $osso;
3331
        if ($osso) {
3332
            $osso->logout();
3333
        }
3334
    }
3335
    $home_url = api_get_path(WEB_PATH);
3336
    $user_id = api_get_user_id();
3337
    $course = api_get_course_id();
3338
3339
    global $this_section;
3340
3341
    if (CustomPages::enabled() && !isset($user_id)) {
3342
3343
        if (empty($user_id)) {
3344
            // Why the CustomPages::enabled() need to be to set the request_uri
3345
            $_SESSION['request_uri'] = $_SERVER['REQUEST_URI'];
3346
        }
3347
3348
        CustomPages::display(CustomPages::INDEX_UNLOGGED);
3349
    }
3350
3351
    $origin = isset($_GET['origin']) ? $_GET['origin'] : '';
3352
3353
    $msg = null;
3354
    if (isset($message)) {
3355
        $msg = $message;
3356 View Code Duplication
    } else {
3357
        $msg = Display::return_message(
3358
            get_lang('NotAllowedClickBack').'<br/><br/><a href="'.$home_url.'">'.get_lang('ReturnToCourseHomepage').'</a>',
3359
            'error',
3360
            false
3361
        );
3362
    }
3363
3364
    $msg = Display::div($msg, array('align'=>'center'));
3365
3366
    $show_headers = 0;
3367
3368
    if ($print_headers && $origin != 'learnpath') {
3369
        $show_headers = 1;
3370
    }
3371
3372
    $tpl = new Template(null, $show_headers, $show_headers);
3373
    $tpl->assign('hide_login_link', 1);
3374
    $tpl->assign('content', $msg);
3375
3376
    if (($user_id != 0 && !api_is_anonymous()) &&
3377
        (!isset($course) || $course == -1) &&
3378
        empty($_GET['cidReq'])
3379
    ) {
3380
        // if the access is not authorized and there is some login information
3381
        // but the cidReq is not found, assume we are missing course data and send the user
3382
        // to the user_portal
3383
        $tpl->display_one_col_template();
3384
        exit;
3385
    }
3386
3387
    if (!empty($_SERVER['REQUEST_URI']) &&
3388
        (!empty($_GET['cidReq']) ||
3389
            $this_section == SECTION_MYPROFILE ||
3390
            $this_section == SECTION_PLATFORM_ADMIN
3391
        )
3392
    ) {
3393
        $courseCode = api_get_course_id();
3394
        // Only display form and return to the previous URL if there was a course ID included
3395
        if ($user_id != 0 && !api_is_anonymous()) {
3396
            //if there is a user ID, then the user is not allowed but the session is still there. Say so and exit
3397
            $tpl->assign('content', $msg);
3398
            $tpl->display_one_col_template();
3399
            exit;
3400
        }
3401
3402
        if (!is_null($courseCode)) {
3403
            api_set_firstpage_parameter($courseCode);
3404
        }
3405
3406
        // If the user has no user ID, then his session has expired
3407
        $action = api_get_self().'?'.Security::remove_XSS($_SERVER['QUERY_STRING']);
3408
        $action = str_replace('&amp;', '&', $action);
3409
        $form = new FormValidator(
3410
            'formLogin',
3411
            'post',
3412
            $action,
3413
            null,
3414
            array(),
3415
            FormValidator::LAYOUT_BOX_NO_LABEL
3416
        );
3417
        $form->addElement('text', 'login', null, array('placeholder' => get_lang('UserName'), 'class' => 'autocapitalize_off'));
3418
        $form->addElement('password', 'password', null, array('placeholder' => get_lang('Password')));
3419
        $form->addButton('submitAuth', get_lang('LoginEnter'), '', 'primary');
3420
3421
        // see same text in auth/gotocourse.php and main_api.lib.php function api_not_allowed (above)
3422
        $content = Display::return_message(get_lang('NotAllowed'), 'error', false);
3423
3424
        if (!empty($courseCode)) {
3425
            $content .= '<h4>'.get_lang('LoginToGoToThisCourse').'</h4>';
3426
        }
3427
3428
        if (api_is_cas_activated()) {
3429
            $content .= Display::return_message(sprintf(get_lang('YouHaveAnInstitutionalAccount'), api_get_setting("Institution")), '', false);
3430
            $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'));
3431
            $content .= Display::return_message(get_lang('YouDontHaveAnInstitutionAccount'));
3432
            $content .= "<p style='text-align:center'><a href='#' onclick='$(this).parent().next().toggle()'>".get_lang('LoginWithExternalAccount')."</a></p>";
3433
            $content .= "<div style='display:none;'>";
3434
        }
3435
        $content .= '<div class="well_login">';
3436
        $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...
3437
        $content .='</div>';
3438
        if (api_is_cas_activated()) {
3439
            $content .= "</div>";
3440
        }
3441
3442
        if (!empty($courseCode)) {
3443
            $content .= '<hr/><p style="text-align:center"><a href="'.$home_url.'">'.
3444
                get_lang('ReturnToCourseHomepage').'</a></p>';
3445
        } else {
3446
            $content .= '<hr/><p style="text-align:center"><a href="'.$home_url.'">'.
3447
                get_lang('CampusHomepage').'</a></p>';
3448
        }
3449
3450
        $tpl->setLoginBodyClass();
3451
        $tpl->assign('content', $content);
3452
        $tpl->display_one_col_template();
3453
        exit;
3454
    }
3455
3456
    if ($user_id !=0 && !api_is_anonymous()) {
3457
        $tpl->display_one_col_template();
3458
        exit;
3459
    }
3460
3461
    $msg = null;
3462
3463
    // The session is over and we were not in a course,
3464
    // or we try to get directly to a private course without being logged
3465
    if (!is_null(api_get_course_int_id())) {
3466
        api_set_firstpage_parameter(api_get_course_id());
3467
        $tpl->setLoginBodyClass();
3468
        $action = api_get_self().'?'.Security::remove_XSS($_SERVER['QUERY_STRING']);
3469
        $action = str_replace('&amp;', '&', $action);
3470
        $form = new FormValidator('formLogin', 'post', $action, null, array('class'=>'form-stacked'));
3471
        $form->addElement('text', 'login', null, array('placeholder' => get_lang('UserName'), 'class' => 'col-md-3 autocapitalize_off')); //new
3472
        $form->addElement('password', 'password', null, array('placeholder' => get_lang('Password'), 'class' => 'col-md-3')); //new
3473
        $form->addButtonNext(get_lang('LoginEnter'), 'submitAuth');
3474
3475
        // see same text in auth/gotocourse.php and main_api.lib.php function api_not_allowed (bellow)
3476
        $msg = Display::return_message(get_lang('NotAllowed'), 'error', false);
3477
        $msg .= '<h4>'.get_lang('LoginToGoToThisCourse').'</h4>';
3478 View Code Duplication
        if (api_is_cas_activated()) {
3479
            $msg .= Display::return_message(sprintf(get_lang('YouHaveAnInstitutionalAccount'), api_get_setting("Institution")), '', false);
3480
            $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'));
3481
            $msg .= Display::return_message(get_lang('YouDontHaveAnInstitutionAccount'));
3482
            $msg .= "<p style='text-align:center'><a href='#' onclick='$(this).parent().next().toggle()'>".get_lang('LoginWithExternalAccount')."</a></p>";
3483
            $msg .= "<div style='display:none;'>";
3484
        }
3485
        $msg .= '<div class="well">';
3486
        $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...
3487
        $msg .='</div>';
3488
        if (api_is_cas_activated()) {
3489
            $msg .= "</div>";
3490
        }
3491
        $msg .= '<hr/><p style="text-align:center"><a href="'.$home_url.'">'.get_lang('ReturnToCourseHomepage').'</a></p>';
3492 View Code Duplication
    } else {
3493
        // we were not in a course, return to home page
3494
        $msg = Display::return_message(
3495
            get_lang('NotAllowed').'<br/><br/><a href="'.$home_url.'">'.get_lang('ReturnToCourseHomepage').'</a><br />',
3496
            'error',
3497
            false
3498
        );
3499
    }
3500
3501
    $tpl->assign('content', $msg);
3502
    $tpl->display_one_col_template();
3503
    exit;
3504
}
3505
3506
3507
/* WHAT'S NEW
3508
   functions for the what's new icons
3509
   in the user course list */
3510
3511
/**
3512
 * Gets a UNIX timestamp from a database (MySQL) datetime format string
3513
 * @param $last_post_datetime standard output date in a sql query
3514
 * @return unix timestamp
3515
 * @author Toon Van Hoecke <[email protected]>
3516
 * @version October 2003
3517
 * @desc convert sql date to unix timestamp
3518
 */
3519
function convert_sql_date($last_post_datetime) {
3520
    list ($last_post_date, $last_post_time) = explode(' ', $last_post_datetime);
3521
    list ($year, $month, $day) = explode('-', $last_post_date);
3522
    list ($hour, $min, $sec) = explode(':', $last_post_time);
3523
    return mktime((int)$hour, (int)$min, (int)$sec, (int)$month, (int)$day, (int)$year);
3524
}
3525
3526
/**
3527
 * Gets a database (MySQL) datetime format string from a UNIX timestamp
3528
 * @param   int     UNIX timestamp, as generated by the time() function. Will be generated if parameter not provided
3529
 * @return  string  MySQL datetime format, like '2009-01-30 12:23:34'
3530
 */
3531
function api_get_datetime($time = null) {
3532
    if (!isset($time)) { $time = time(); }
3533
    return date('Y-m-d H:i:s', $time);
3534
}
3535
3536
/**
3537
 * Gets item visibility from the item_property table
3538
 *
3539
 * Getting the visibility is done by getting the last updated visibility entry,
3540
 * using the largest session ID found if session 0 and another was found (meaning
3541
 * the only one that is actually from the session, in case there are results from
3542
 * session 0 *AND* session n).
3543
 * @param array     Course properties array (result of api_get_course_info())
3544
 * @param string    Tool (learnpath, document, etc)
3545
 * @param int       The item ID in the given tool
3546
 * @param int       The session ID (optional)
3547
 * @return int      -1 on error, 0 if invisible, 1 if visible
3548
 */
3549
function api_get_item_visibility(
3550
    $_course,
3551
    $tool,
3552
    $id,
3553
    $session = 0,
3554
    $user_id = null,
3555
    $type = null,
3556
    $group_id = null
3557
) {
3558
    if (!is_array($_course) || count($_course) == 0 || empty($tool) || empty($id)) {
3559
        return -1;
3560
    }
3561
3562
    $tool = Database::escape_string($tool);
3563
    $id = intval($id);
3564
    $session = (int) $session;
3565
    $TABLE_ITEMPROPERTY = Database::get_course_table(TABLE_ITEM_PROPERTY);
3566
    $course_id = intval($_course['real_id']);
3567
3568
    $userCondition = '';
3569
    if (!empty($user_id)) {
3570
        $user_id = intval($user_id);
3571
        $userCondition = " AND to_user_id = $user_id ";
3572
    }
3573
3574
    $typeCondition = '';
3575
    if (!empty($type)) {
3576
        $type = Database::escape_string($type);
3577
        $typeCondition = " AND lastedit_type = '$type' ";
3578
    }
3579
3580
    $groupCondition = '';
3581
    if (!empty($group_id)) {
3582
        $group_id = intval($group_id);
3583
        $groupCondition = " AND to_group_id = '$group_id' ";
3584
    }
3585
3586
    $sql = "SELECT visibility
3587
            FROM $TABLE_ITEMPROPERTY
3588
            WHERE
3589
                c_id = $course_id AND
3590
                tool = '$tool' AND
3591
                ref = $id AND
3592
                (session_id = $session OR session_id = 0 OR session_id IS NULL)
3593
                $userCondition $typeCondition $groupCondition
3594
            ORDER BY session_id DESC, lastedit_date DESC
3595
            LIMIT 1";
3596
3597
    $res = Database::query($sql);
3598
    if ($res === false || Database::num_rows($res) == 0) {
3599
        return -1;
3600
    }
3601
    $row = Database::fetch_array($res);
3602
3603
    return $row['visibility'];
3604
}
3605
3606
/**
3607
 * Delete a row in the c_item_property table
3608
 *
3609
 * @param array $courseInfo
3610
 * @param string $tool
3611
 * @param int $itemId
3612
 * @param int $userId
3613
 * @param int $groupId
3614
 * @param int $sessionId
3615
 * @return void
3616
 */
3617
function api_item_property_delete(
3618
    $courseInfo,
3619
    $tool,
3620
    $itemId,
3621
    $userId,
3622
    $groupId = 0,
3623
    $sessionId = 0
3624
) {
3625
    if (empty($courseInfo)) {
3626
        return false;
3627
    }
3628
3629
    $courseId = intval($courseInfo['real_id']);
3630
3631
    if (empty($courseId) || empty($tool) || empty($itemId)) {
3632
        return false;
3633
    }
3634
3635
    $table = Database::get_course_table(TABLE_ITEM_PROPERTY);
3636
    $tool = Database::escape_string($tool);
3637
    $itemId = intval($itemId);
3638
    $userId = intval($userId);
3639
    $groupId = intval($groupId);
3640
    $sessionId = intval($sessionId);
3641
3642
    $groupCondition = " AND to_group_id = $groupId ";
3643
    if (empty($groupId)) {
3644
        $groupCondition = " AND (to_group_id is NULL OR to_group_id = 0) ";
3645
    }
3646
3647
    $userCondition = " AND to_user_id = $userId ";
3648
    if (empty($userId)) {
3649
        $userCondition = " AND (to_user_id is NULL OR to_user_id = 0) ";
3650
    }
3651
    $sql = "DELETE FROM $table
3652
            WHERE
3653
                c_id = $courseId AND
3654
                tool  = '$tool' AND
3655
                ref = $itemId AND
3656
                session_id = $sessionId
3657
                $userCondition
3658
                $groupCondition
3659
            ";
3660
    Database::query($sql);
3661
}
3662
3663
/**
3664
 * Updates or adds item properties to the Item_propetry table
3665
 * Tool and lastedit_type are language independant strings (langvars->get_lang!)
3666
 *
3667
 * @param array $_course array with course properties
3668
 * @param string $tool tool id, linked to 'rubrique' of the course tool_list (Warning: language sensitive !!)
3669
 * @param int $item_id id of the item itself, linked to key of every tool ('id', ...), "*" = all items of the tool
3670
 * @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...
3671
 * (1) message to be translated (in trad4all) : e.g. DocumentAdded, DocumentUpdated;
3672
 * (2) "delete"
3673
 * (3) "visible"
3674
 * (4) "invisible"
3675
 * @param int $user_id : id of the editing/adding user
3676
 * @param int $to_group_id : id of the intended group (0 = for everybody), only relevant for $type (1)
3677
 * @param int $to_user_id : id of the intended user (always has priority over $to_group_id !), only relevant for $type (1)
3678
 * @param string $start_visible 0000-00-00 00:00:00 format
3679
 * @param string $end_visible 0000-00-00 00:00:00 format
3680
 * @param int $session_id The session ID, if any, otherwise will default to 0
3681
 * @return boolean False if update fails.
3682
 * @author Toon Van Hoecke <[email protected]>, Ghent University
3683
 * @version January 2005
3684
 * @desc update the item_properties table (if entry not exists, insert) of the course
3685
 */
3686
function api_item_property_update(
3687
    $_course,
3688
    $tool,
3689
    $item_id,
3690
    $last_edit_type,
3691
    $user_id,
3692
    $to_group_id = 0,
3693
    $to_user_id = null,
3694
    $start_visible = '',
3695
    $end_visible = '',
3696
    $session_id = 0
3697
) {
3698
    if (empty($_course)) {
3699
        return false;
3700
    }
3701
3702
    $course_id = $_course['real_id'];
3703
3704
    if (empty($course_id)) {
3705
        return false;
3706
    }
3707
3708
    // Definition of variables.
3709
    $tool = Database::escape_string($tool);
3710
    $item_id = intval($item_id);
3711
    $lastEditTypeNoFilter = $last_edit_type;
3712
    $last_edit_type = Database::escape_string($last_edit_type);
3713
    $user_id = intval($user_id);
3714
3715
    $startVisible = "NULL";
3716
    if (!empty($start_visible)) {
3717
        $start_visible = Database::escape_string($start_visible);
3718
        $startVisible = "'$start_visible'";
3719
    }
3720
3721
    $endVisible = "NULL";
3722
    if (!empty($end_visible)) {
3723
        $end_visible = Database::escape_string($end_visible);
3724
        $endVisible = "'$end_visible'";
3725
    }
3726
3727
    $to_filter = '';
3728
    $time = api_get_utc_datetime();
3729
3730
    if (!empty($session_id)) {
3731
        $session_id = intval($session_id);
3732
    } else {
3733
        $session_id = api_get_session_id();
3734
    }
3735
3736
    // Definition of tables.
3737
    $tableItemProperty = Database::get_course_table(TABLE_ITEM_PROPERTY);
3738
3739
    if ($to_user_id <= 0) {
3740
        $to_user_id = null; // No to_user_id set
3741
    }
3742
3743
    if (!is_null($to_user_id)) {
3744
        // $to_user_id has more priority than $to_group_id
3745
        $to_user_id = intval($to_user_id);
3746
        $to_field = 'to_user_id';
3747
        $to_value = $to_user_id;
3748
    } else {
3749
        // $to_user_id is not set.
3750
        $to_field = 'to_group_id';
3751
        $to_value = $to_group_id;
3752
    }
3753
3754
    $toValueCondition = empty($to_value) ? "NULL" : "'$to_value'";
3755
3756
    // Set filters for $to_user_id and $to_group_id, with priority for $to_user_id
3757
    $condition_session = " AND session_id = $session_id ";
3758
    if (empty($session_id)) {
3759
        $condition_session = " AND (session_id = 0 OR session_id IS NULL) ";
3760
    }
3761
3762
    $filter = " c_id = $course_id AND tool = '$tool' AND ref = $item_id $condition_session ";
3763
3764
    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...
3765
        // For all (not deleted) items of the tool
3766
        $filter = " c_id = $course_id  AND tool = '$tool' AND visibility <> 2 $condition_session";
3767
    }
3768
3769
    // Check whether $to_user_id and $to_group_id are passed in the function call.
3770
    // If both are not passed (both are null) then it is a message for everybody and $to_group_id should be 0 !
3771
    if (is_null($to_user_id) && is_null($to_group_id)) {
3772
        $to_group_id = 0;
3773
    }
3774
3775
    if (!is_null($to_user_id)) {
3776
        // Set filter to intended user.
3777
        $to_filter = " AND to_user_id = $to_user_id $condition_session";
3778
    } else {
3779
        // Set filter to intended group.
3780
        if (($to_group_id != 0) && $to_group_id == strval(intval($to_group_id))) {
3781
            $to_filter = " AND to_group_id = $to_group_id $condition_session";
3782
        }
3783
    }
3784
3785
    // Adding filter if set.
3786
    $filter .= $to_filter;
3787
3788
    // Update if possible
3789
    $set_type = '';
3790
3791
    switch ($lastEditTypeNoFilter) {
3792 View Code Duplication
        case 'delete':
3793
            // delete = make item only visible for the platform admin.
3794
            $visibility = '2';
3795
            if (!empty($session_id)) {
3796
                // Check whether session id already exist into item_properties for updating visibility or add it.
3797
                $sql = "SELECT session_id FROM $tableItemProperty
3798
                        WHERE
3799
                            c_id = $course_id AND
3800
                            tool = '$tool' AND
3801
                            ref = $item_id AND
3802
                            session_id = $session_id";
3803
                $rs = Database::query($sql);
3804
                if (Database::num_rows($rs) > 0) {
3805
                    $sql = "UPDATE $tableItemProperty
3806
                            SET lastedit_type       = '".str_replace('_', '', ucwords($tool))."Deleted',
3807
                                lastedit_date       = '$time',
3808
                                lastedit_user_id    = $user_id,
3809
                                visibility          = $visibility,
3810
                                session_id          = $session_id $set_type
3811
                            WHERE $filter";
3812
                    $result = Database::query($sql);
3813
                } else {
3814
                    $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)
3815
                            VALUES ($course_id, '$tool',$item_id, '$time', $user_id, '$time', '$last_edit_type',$user_id, $toValueCondition, $visibility, $startVisible, $endVisible, $session_id)";
3816
                    $result = Database::query($sql);
3817
                    $id = Database::insert_id();
3818
                    if ($id) {
3819
                        $sql = "UPDATE $tableItemProperty SET id = iid WHERE iid = $id";
3820
                        Database::query($sql);
3821
                    }
3822
                }
3823
            } else {
3824
                $sql = "UPDATE $tableItemProperty
3825
                        SET
3826
                            lastedit_type='".str_replace('_', '', ucwords($tool))."Deleted',
3827
                            lastedit_date='$time',
3828
                            lastedit_user_id = $user_id,
3829
                            visibility = $visibility $set_type
3830
                        WHERE $filter";
3831
                $result = Database::query($sql);
3832
            }
3833
            break;
3834 View Code Duplication
        case 'visible' : // Change item to visible.
3835
            $visibility = '1';
3836
            if (!empty($session_id)) {
3837
                // Check whether session id already exist into item_properties for updating visibility or add it.
3838
                $sql = "SELECT session_id FROM $tableItemProperty
3839
                        WHERE
3840
                            c_id = $course_id AND
3841
                            tool = '$tool' AND
3842
                            ref = $item_id AND
3843
                            session_id = $session_id";
3844
                $rs = Database::query($sql);
3845
                if (Database::num_rows($rs) > 0) {
3846
                    $sql = "UPDATE $tableItemProperty
3847
                            SET
3848
                                lastedit_type='".str_replace('_', '', ucwords($tool))."Visible',
3849
                                lastedit_date='$time',
3850
                                lastedit_user_id = $user_id,
3851
                                visibility = $visibility,
3852
                                session_id = $session_id $set_type
3853
                            WHERE $filter";
3854
                    $result = Database::query($sql);
3855
                } else {
3856
                    $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)
3857
                            VALUES ($course_id, '$tool', $item_id, '$time', $user_id, '$time', '$last_edit_type', $user_id, $toValueCondition, $visibility, $startVisible, $endVisible, $session_id)";
3858
                    $result = Database::query($sql);
3859
                    $id = Database::insert_id();
3860
                    if ($id) {
3861
                        $sql = "UPDATE $tableItemProperty SET id = iid WHERE iid = $id";
3862
                        Database::query($sql);
3863
                    }
3864
                }
3865
            } else {
3866
                $sql = "UPDATE $tableItemProperty
3867
                        SET
3868
                            lastedit_type='".str_replace('_', '', ucwords($tool))."Visible',
3869
                            lastedit_date='$time',
3870
                            lastedit_user_id = $user_id,
3871
                            visibility = $visibility $set_type
3872
                        WHERE $filter";
3873
                $result = Database::query($sql);
3874
            }
3875
            break;
3876 View Code Duplication
        case 'invisible' : // Change item to invisible.
3877
            $visibility = '0';
3878
            if (!empty($session_id)) {
3879
                // Check whether session id already exist into item_properties for updating visibility or add it
3880
                $sql = "SELECT session_id FROM $tableItemProperty
3881
                        WHERE
3882
                            c_id = $course_id AND
3883
                            tool = '$tool' AND
3884
                            ref = $item_id AND
3885
                            session_id = $session_id";
3886
                $rs = Database::query($sql);
3887
                if (Database::num_rows($rs) > 0) {
3888
                    $sql = "UPDATE $tableItemProperty
3889
                            SET
3890
                                lastedit_type = '".str_replace('_', '', ucwords($tool))."Invisible',
3891
                                lastedit_date = '$time',
3892
                                lastedit_user_id = $user_id,
3893
                                visibility = $visibility,
3894
                                session_id = $session_id $set_type
3895
                            WHERE $filter";
3896
                    $result = Database::query($sql);
3897
                } else {
3898
                    $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)
3899
                            VALUES ($course_id, '$tool', $item_id, '$time', $user_id, '$time', '$last_edit_type', $user_id, $toValueCondition, $visibility, $startVisible, $endVisible, $session_id)";
3900
                    $result = Database::query($sql);
3901
                    $id = Database::insert_id();
3902
                    if ($id) {
3903
                        $sql = "UPDATE $tableItemProperty SET id = iid WHERE iid = $id";
3904
                        Database::query($sql);
3905
                    }
3906
                }
3907
            } else {
3908
                $sql = "UPDATE $tableItemProperty
3909
                        SET
3910
                            lastedit_type = '".str_replace('_', '', ucwords($tool))."Invisible',
3911
                            lastedit_date = '$time',
3912
                            lastedit_user_id = $user_id,
3913
                            visibility = $visibility $set_type
3914
                        WHERE $filter";
3915
                $result = Database::query($sql);
3916
            }
3917
            break;
3918
        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...
3919
            $set_type = ", lastedit_type = '$last_edit_type' ";
3920
            $visibility = '1';
3921
            //$filter .= $to_filter; already added
3922
            $sql = "UPDATE $tableItemProperty
3923
                    SET
3924
                      lastedit_date = '$time',
3925
                      lastedit_user_id = $user_id $set_type
3926
                    WHERE $filter";
3927
            $result = Database::query($sql);
3928
    }
3929
3930
    // Insert if no entries are found (can only happen in case of $last_edit_type switch is 'default').
3931
    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...
3932
        $sessionCondition = empty($session_id) ? "NULL" : "'$session_id'";
3933
        $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)
3934
                VALUES ($course_id, '$tool', $item_id, '$time', $user_id, '$time', '$last_edit_type', $user_id, $toValueCondition, $visibility, $startVisible, $endVisible, $sessionCondition)";
3935
        Database::query($sql);
3936
        $id = Database::insert_id();
3937
        if ($id) {
3938
            $sql = "UPDATE $tableItemProperty SET id = iid WHERE iid = $id";
3939
            Database::query($sql);
3940
            return false;
3941
        }
3942
    }
3943
3944
    return true;
3945
}
3946
3947
/**
3948
 * Gets item property by tool
3949
 * @param string    course code
3950
 * @param string    tool name, linked to 'rubrique' of the course tool_list (Warning: language sensitive !!)
3951
 * @param int       id of the item itself, linked to key of every tool ('id', ...), "*" = all items of the tool
3952
 * @param int $session_id
3953
 * @return array All fields from c_item_property (all rows found) or empty array
3954
 */
3955
function api_get_item_property_by_tool($tool, $course_code, $session_id = null)
3956
{
3957
    $course_info = api_get_course_info($course_code);
3958
    $tool = Database::escape_string($tool);
3959
3960
    // Definition of tables.
3961
    $item_property_table = Database::get_course_table(TABLE_ITEM_PROPERTY);
3962
    $session_id = intval($session_id);
3963
    $session_condition = ' AND session_id = '.$session_id;
3964
    if (empty($session_id)) {
3965
        $session_condition = " AND (session_id = 0 OR session_id IS NULL) ";
3966
    }
3967
    $course_id = $course_info['real_id'];
3968
3969
    $sql = "SELECT * FROM $item_property_table
3970
            WHERE
3971
                c_id = $course_id AND
3972
                tool = '$tool'
3973
                $session_condition ";
3974
    $rs  = Database::query($sql);
3975
    $list = array();
3976
    if (Database::num_rows($rs) > 0) {
3977
        while ($row = Database::fetch_array($rs, 'ASSOC')) {
3978
            $list[] = $row;
3979
        }
3980
    }
3981
    return $list;
3982
}
3983
3984
/**
3985
 * Gets item property by tool and user
3986
 * @param int $userId
3987
 * @param int $tool
3988
 * @param int $courseId
3989
 * @param int $session_id
3990
 * @return array
3991
 */
3992
function api_get_item_property_list_by_tool_by_user(
3993
    $userId,
3994
    $tool,
3995
    $courseId,
3996
    $session_id = 0
3997
) {
3998
    $userId = intval($userId);
3999
    $tool = Database::escape_string($tool);
4000
    $session_id = intval($session_id);
4001
    $courseId = intval($courseId);
4002
4003
    // Definition of tables.
4004
    $item_property_table = Database::get_course_table(TABLE_ITEM_PROPERTY);
4005
    $session_condition = ' AND session_id = '.$session_id;
4006
    if (empty($session_id)) {
4007
        $session_condition = " AND (session_id = 0 OR session_id IS NULL) ";
4008
    }
4009
    $sql = "SELECT * FROM $item_property_table
4010
            WHERE
4011
                insert_user_id = $userId AND
4012
                c_id = $courseId AND
4013
                tool = '$tool'
4014
                $session_condition ";
4015
4016
    $rs = Database::query($sql);
4017
    $list = array();
4018
    if (Database::num_rows($rs) > 0) {
4019
        while ($row = Database::fetch_array($rs, 'ASSOC')) {
4020
            $list[] = $row;
4021
        }
4022
    }
4023
4024
    return $list;
4025
}
4026
4027
/**
4028
 * Gets item property id from tool of a course
4029
 * @param string $course_code course code
4030
 * @param string $tool tool name, linked to 'rubrique' of the course tool_list (Warning: language sensitive !!)
4031
 * @param int $ref id of the item itself, linked to key of every tool ('id', ...), "*" = all items of the tool
4032
 * @param int $sessionId Session ID (optional)
4033
 * @return int
4034
 */
4035
function api_get_item_property_id($course_code, $tool, $ref, $sessionId = 0)
4036
{
4037
    $course_info = api_get_course_info($course_code);
4038
    $tool = Database::escape_string($tool);
4039
    $ref = intval($ref);
4040
4041
    // Definition of tables.
4042
    $tableItemProperty = Database::get_course_table(TABLE_ITEM_PROPERTY);
4043
    $course_id = $course_info['real_id'];
4044
    $sessionCondition = " AND session_id = $sessionId ";
4045
    if (empty($sessionId)) {
4046
        $sessionCondition = " AND (session_id = 0 OR session_id IS NULL) ";
4047
    }
4048
    $sql = "SELECT id FROM $tableItemProperty
4049
            WHERE
4050
                c_id = $course_id AND
4051
                tool = '$tool' AND
4052
                ref = $ref
4053
                $sessionCondition";
4054
    $rs  = Database::query($sql);
4055
    $item_property_id = '';
4056
    if (Database::num_rows($rs) > 0) {
4057
        $row = Database::fetch_array($rs);
4058
        $item_property_id = $row['id'];
4059
    }
4060
    return $item_property_id;
4061
}
4062
4063
/**
4064
 * Inserts a record in the track_e_item_property table (No update)
4065
 * @param string $tool
4066
 * @param int $ref
4067
 * @param string $title
4068
 * @param string $content
4069
 * @param int $progress
4070
 * @return bool|int
4071
 */
4072
function api_track_item_property_update($tool, $ref, $title, $content, $progress)
4073
{
4074
    $tbl_stats_item_property = Database::get_main_table(TABLE_STATISTIC_TRACK_E_ITEM_PROPERTY);
4075
    $course_id = api_get_real_course_id(); //numeric
4076
    $course_code = api_get_course_id(); //alphanumeric
4077
    $item_property_id = api_get_item_property_id($course_code, $tool, $ref);
4078
    if (!empty($item_property_id)) {
4079
        $sql = "INSERT IGNORE INTO $tbl_stats_item_property SET
4080
                course_id           = '$course_id',
4081
                item_property_id    = '$item_property_id',
4082
                title               = '".Database::escape_string($title)."',
4083
                content             = '".Database::escape_string($content)."',
4084
                progress            = '".intval($progress)."',
4085
                lastedit_date       = '".api_get_utc_datetime()."',
4086
                lastedit_user_id    = '".api_get_user_id()."',
4087
                session_id          = '".api_get_session_id()."'";
4088
        $result = Database::query($sql);
4089
        $affected_rows = Database::affected_rows($result);
4090
4091
        return $affected_rows;
4092
    }
4093
4094
    return false;
4095
}
4096
4097
/**
4098
 * @param string $tool
4099
 * @param int $ref
4100
 * @return array|resource
4101
 */
4102
function api_get_track_item_property_history($tool, $ref)
4103
{
4104
    $tbl_stats_item_property = Database::get_main_table(TABLE_STATISTIC_TRACK_E_ITEM_PROPERTY);
4105
    $course_id = api_get_real_course_id(); //numeric
4106
    $course_code = api_get_course_id(); //alphanumeric
4107
    $item_property_id = api_get_item_property_id($course_code, $tool, $ref);
4108
    $sql = "SELECT * FROM $tbl_stats_item_property
4109
            WHERE item_property_id = $item_property_id AND course_id = $course_id
4110
            ORDER BY lastedit_date DESC";
4111
    $result = Database::query($sql);
4112
    $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...
4113
    return $result;
4114
}
4115
4116
/**
4117
 * Gets item property data from tool of a course id
4118
 * @param int $course_id
4119
 * @param string $tool   tool name, linked to 'rubrique' of the course tool_list (Warning: language sensitive !!)
4120
 * @param int $ref id of the item itself, linked to key of every tool ('id', ...), "*" = all items of the tool
4121
 * @param int $session_id
4122
 * @param int $groupId
4123
 *
4124
 * @return array Array with all fields from c_item_property, empty array if not found or false if course could not be found
4125
 */
4126
function api_get_item_property_info($course_id, $tool, $ref, $session_id = 0, $groupId = 0)
4127
{
4128
    $courseInfo = api_get_course_info_by_id($course_id);
4129
4130
    if (empty($courseInfo)) {
4131
        return false;
4132
    }
4133
4134
    $tool = Database::escape_string($tool);
4135
    $ref = intval($ref);
4136
    $course_id = $courseInfo['real_id'];
4137
    $session_id = intval($session_id);
4138
4139
    $sessionCondition = " session_id = $session_id";
4140
    if (empty($session_id)) {
4141
        $sessionCondition = " (session_id = 0 OR session_id IS NULL) ";
4142
    }
4143
4144
    // Definition of tables.
4145
    $table = Database::get_course_table(TABLE_ITEM_PROPERTY);
4146
4147
    $sql = "SELECT * FROM $table
4148
            WHERE
4149
                c_id = $course_id AND
4150
                tool = '$tool' AND
4151
                ref = $ref AND
4152
                $sessionCondition ";
4153
4154
    if (!empty($groupId)) {
4155
        $groupId = intval($groupId);
4156
        $sql .= " AND to_group_id = $groupId ";
4157
    }
4158
4159
    $rs  = Database::query($sql);
4160
    $row = array();
4161
    if (Database::num_rows($rs) > 0) {
4162
        $row = Database::fetch_array($rs,'ASSOC');
4163
    }
4164
4165
    return $row;
4166
}
4167
4168
/**
4169
 * Displays a combo box so the user can select his/her preferred language.
4170
 * @param string The desired name= value for the select
4171
 * @param bool Whether we use the JQuery Chozen library or not
4172
 * (in some cases, like the indexing language picker, it can alter the presentation)
4173
 * @return string
4174
 */
4175
4176
function api_get_languages_combo($name = 'language')
4177
{
4178
    $ret = '';
4179
    $platformLanguage = api_get_setting('platformLanguage');
4180
4181
    // Retrieve a complete list of all the languages.
4182
    $language_list = api_get_languages();
4183
4184
    if (count($language_list['name']) < 2) {
4185
        return $ret;
4186
    }
4187
4188
    // The the current language of the user so that his/her language occurs as selected in the dropdown menu.
4189
    if (isset($_SESSION['user_language_choice'])) {
4190
        $default = $_SESSION['user_language_choice'];
4191
    } else {
4192
        $default = $platformLanguage;
4193
    }
4194
4195
    $languages  = $language_list['name'];
4196
    $folder     = $language_list['folder'];
4197
4198
    $ret .= '<select name="' . $name . '" id="language_chosen" class="selectpicker show-tick form-control">';
4199
    foreach ($languages as $key => $value) {
4200
        if ($folder[$key] == $default) {
4201
            $selected = ' selected="selected"';
4202
        } else {
4203
            $selected = '';
4204
        }
4205
        $ret .= sprintf('<option value=%s" %s>%s</option>', $folder[$key], $selected, $value);
4206
    }
4207
    $ret .= '</select>';
4208
    return $ret;
4209
}
4210
4211
/**
4212
 * Displays a form (drop down menu) so the user can select his/her preferred language.
4213
 * The form works with or without javascript
4214
 * @param  boolean Hide form if only one language available (defaults to false = show the box anyway)
4215
 * @return void Display the box directly
4216
 */
4217
function api_display_language_form($hide_if_no_choice = false)
4218
{
4219
    // Retrieve a complete list of all the languages.
4220
    $language_list = api_get_languages();
4221
    if (count($language_list['name']) <= 1 && $hide_if_no_choice) {
4222
        return; //don't show any form
4223
    }
4224
4225
    // The the current language of the user so that his/her language occurs as selected in the dropdown menu.
4226
    if (isset($_SESSION['user_language_choice'])) {
4227
        $user_selected_language = $_SESSION['user_language_choice'];
4228
    }
4229
    if (empty($user_selected_language)) {
4230
        $user_selected_language = api_get_setting('platformLanguage');
4231
    }
4232
4233
    $original_languages = $language_list['name'];
4234
    $folder = $language_list['folder']; // This line is probably no longer needed.
4235
    $html = '
4236
    <script type="text/javascript">
4237
    <!--
4238
    $(document).ready(function() {
4239
        $("#language_list").change(function() {
4240
            jumpMenu("parent",this,0);
4241
        });
4242
    });
4243
4244
    function jumpMenu(targ,selObj,restore){ // v3.0
4245
        eval(targ+".location=\'"+selObj.options[selObj.selectedIndex].value+"\'");
4246
        if (restore) selObj.selectedIndex=0;
4247
    }
4248
    //-->
4249
    </script>';
4250
    $html .= '<form id="lang_form" name="lang_form" method="post" action="'.api_get_self().'">';
4251
    $html .= '<label style="display: none;" for="language_list">' . get_lang('Language') . '</label>';
4252
    $html .=  '<select id="language_list" class="selectpicker show-tick form-control" name="language_list" >';
4253
4254
    foreach ($original_languages as $key => $value) {
4255
        if ($folder[$key] == $user_selected_language) {
4256
            $option_end = ' selected="selected" >';
4257
        } else {
4258
            $option_end = '>';
4259
        }
4260
        $html .=  '<option value="'.api_get_self().'?language='.$folder[$key].'"'.$option_end;
4261
        //echo substr($value, 0, 16); // Cut string to keep 800x600 aspect.
4262
        $html .=  $value.'</option>';
4263
    }
4264
    $html .=  '</select>';
4265
    $html .=  '<noscript><input type="submit" name="user_select_language" value="'.get_lang('Ok').'" /></noscript>';
4266
    $html .=  '</form>';
4267
    return $html;
4268
}
4269
4270
/**
4271
 * Returns a list of all the languages that are made available by the admin.
4272
 * @return array An array with all languages. Structure of the array is
4273
 *  array['name'] = An array with the name of every language
4274
 *  array['folder'] = An array with the corresponding names of the language-folders in the filesystem
4275
 */
4276
function api_get_languages() {
4277
    $tbl_language = Database::get_main_table(TABLE_MAIN_LANGUAGE);
4278
    $sql = "SELECT * FROM $tbl_language WHERE available='1' ORDER BY original_name ASC";
4279
    $result = Database::query($sql);
4280
    $language_list = array();
4281
    while ($row = Database::fetch_array($result)) {
4282
        $language_list['name'][] = $row['original_name'];
4283
        $language_list['folder'][] = $row['dokeos_folder'];
4284
    }
4285
    return $language_list;
4286
}
4287
4288
/**
4289
 * Returns a list of all the languages that are made available by the admin.
4290
 * @return array
4291
 */
4292
function api_get_languages_to_array() {
4293
    $tbl_language = Database::get_main_table(TABLE_MAIN_LANGUAGE);
4294
    $sql = "SELECT * FROM $tbl_language WHERE available='1' ORDER BY original_name ASC";
4295
    $result = Database::query($sql);
4296
    $languages = array();
4297
    while ($row = Database::fetch_array($result)) {
4298
        $languages[$row['dokeos_folder']] = $row['original_name'];
4299
    }
4300
    return $languages;
4301
}
4302
4303
/**
4304
 * Returns the id (the database id) of a language
4305
 * @param   string  language name (the corresponding name of the language-folder in the filesystem)
4306
 * @return  int     id of the language
4307
 */
4308
function api_get_language_id($language)
4309
{
4310
    $tbl_language = Database::get_main_table(TABLE_MAIN_LANGUAGE);
4311
    if (empty($language)) {
4312
        return null;
4313
    }
4314
    $language = Database::escape_string($language);
4315
    $sql = "SELECT id FROM $tbl_language
4316
            WHERE dokeos_folder = '$language' LIMIT 1";
4317
    $result = Database::query($sql);
4318
    $row = Database::fetch_array($result);
4319
    return $row['id'];
4320
}
4321
4322
/**
4323
 * Gets language of the requested type for the current user. Types are :
4324
 * user_profil_lang : profile language of current user
4325
 * user_select_lang : language selected by user at login
4326
 * course_lang : language of the current course
4327
 * platform_lang : default platform language
4328
 * @param string $lang_type
4329
 * @return string
4330
 **/
4331
function api_get_language_from_type($lang_type)
4332
{
4333
    $return = false;
4334
4335
    switch ($lang_type) {
4336
        case 'platform_lang':
4337
            $temp_lang = api_get_setting('platformLanguage');
4338
            if (!empty($temp_lang))
4339
                $return = $temp_lang;
4340
            break;
4341
        case 'user_profil_lang':
4342
            $_user = api_get_user_info();
4343 View Code Duplication
            if (isset($_user['language']) && !empty($_user['language']))
4344
                $return = $_user['language'];
4345
            break;
4346
        case 'user_selected_lang':
4347
            if (isset($_SESSION['user_language_choice']) && !empty($_SESSION['user_language_choice']))
4348
                $return = $_SESSION['user_language_choice'];
4349
            break;
4350
        case 'course_lang':
4351
            global $_course;
4352
            $cidReq = null;
4353
            if (empty($_course)) {
4354
                // Code modified because the local.inc.php file it's declarated after this work
4355
                // causing the function api_get_course_info() returns a null value
4356
                $cidReq = isset($_GET["cidReq"]) ? Database::escape_string($_GET["cidReq"]) : null;
4357
                $cDir = (!empty($_GET['cDir']) ? $_GET['cDir'] : null);
4358
                if (empty($cidReq) && !empty($cDir)) {
4359
                    $c = CourseManager::get_course_id_from_path($cDir);
4360
                    if ($c) {
4361
                        $cidReq = $c;
4362
                    }
4363
                }
4364
            }
4365
            $_course = api_get_course_info($cidReq);
4366 View Code Duplication
            if (isset($_course['language']) && !empty($_course['language']))
4367
                $return = $_course['language'];
4368
            break;
4369
        default:
4370
            $return = false;
4371
        break;
4372
    }
4373
4374
    return $return;
4375
}
4376
4377
function api_get_language_info($language_id) {
4378
    $tbl_admin_languages = Database :: get_main_table(TABLE_MAIN_LANGUAGE);
4379
    $sql = 'SELECT * FROM '.$tbl_admin_languages.' WHERE id = "'.intval($language_id).'"';
4380
    $rs = Database::query($sql);
4381
    $language_info = array();
4382
    if (Database::num_rows($rs)) {
4383
        $language_info = Database::fetch_array($rs,'ASSOC');
4384
    }
4385
    return $language_info;
4386
}
4387
4388
/**
4389
 * Returns the name of the visual (CSS) theme to be applied on the current page.
4390
 * The returned name depends on the platform, course or user -wide settings.
4391
 * @return string   The visual theme's name, it is the name of a folder inside .../chamilo/main/css/
4392
 */
4393
function api_get_visual_theme()
4394
{
4395
    static $visual_theme;
4396
    if (!isset($visual_theme)) {
4397
4398
        $platform_theme = api_get_setting('stylesheets');
4399
4400
        // Platform's theme.
4401
        $visual_theme = $platform_theme;
4402
4403
        if (api_get_setting('user_selected_theme') == 'true') {
4404
            $user_info = api_get_user_info();
4405
            if (isset($user_info['theme'])) {
4406
                $user_theme = $user_info['theme'];
4407
4408
                if (!empty($user_theme)) {
4409
                    $visual_theme = $user_theme;
4410
                    // User's theme.
4411
                }
4412
            }
4413
        }
4414
4415
        $course_id = api_get_course_id();
4416
4417
        if (!empty($course_id) && $course_id != -1) {
4418
            if (api_get_setting('allow_course_theme') == 'true') {
4419
                $course_theme = api_get_course_setting('course_theme');
4420
4421
                if (!empty($course_theme) && $course_theme != -1) {
4422
                    if (!empty($course_theme)) {
4423
                        // Course's theme.
4424
                        $visual_theme = $course_theme;
4425
                    }
4426
                }
4427
4428
                $allow_lp_theme = api_get_course_setting('allow_learning_path_theme');
4429
                if ($allow_lp_theme == 1) {
4430
                    global $lp_theme_css, $lp_theme_config;
4431
                    // These variables come from the file lp_controller.php.
4432
                    if (!$lp_theme_config) {
4433
                        if (!empty($lp_theme_css)) {
4434
                            // LP's theme.
4435
                            $visual_theme = $lp_theme_css;
4436
                        }
4437
                    }
4438
                }
4439
            }
4440
        }
4441
4442
        if (empty($visual_theme)) {
4443
            $visual_theme = 'chamilo';
4444
        }
4445
4446
        global $lp_theme_log;
4447
        if ($lp_theme_log) {
4448
            $visual_theme = $platform_theme;
4449
        }
4450
    }
4451
4452
    return $visual_theme;
4453
}
4454
4455
/**
4456
 * Returns a list of CSS themes currently available in the CSS folder
4457
 * @return array        List of themes directories from the css folder
4458
 * Note: Directory names (names of themes) in the file system should contain ASCII-characters only.
4459
 */
4460
function api_get_themes() {
4461
    $cssdir = api_get_path(SYS_CSS_PATH) . 'themes/';
4462
    $list_dir = array();
4463
    $list_name = array();
4464
4465
    if (is_dir($cssdir)) {
4466
        $themes = @scandir($cssdir);
4467
4468
        if (is_array($themes)) {
4469
            if ($themes !== false) {
4470
                sort($themes);
4471
4472
                foreach ($themes as & $theme) {
4473
                    if (substr($theme, 0, 1) == '.') {
4474
                        continue;
4475
                    } else {
4476
                        if (is_dir($cssdir.$theme)) {
4477
                            $list_dir[] = $theme;
4478
                            $list_name[] = ucwords(str_replace('_', ' ', $theme));
4479
                        }
4480
                    }
4481
                }
4482
            }
4483
        }
4484
    }
4485
4486
    return array($list_dir, $list_name);
4487
}
4488
4489
/**
4490
 * Find the largest sort value in a given user_course_category
4491
 * This function is used when we are moving a course to a different category
4492
 * and also when a user subscribes to courses (the new course is added at the end of the main category
4493
 * @author Patrick Cool <[email protected]>, Ghent University
4494
 * @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...
4495
 * @return int the value of the highest sort of the user_course_category
4496
 */
4497
function api_max_sort_value($user_course_category, $user_id)
4498
{
4499
    $tbl_course_user = Database::get_main_table(TABLE_MAIN_COURSE_USER);
4500
    $sql = "SELECT max(sort) as max_sort FROM $tbl_course_user
4501
            WHERE
4502
                user_id='".intval($user_id)."' AND
4503
                relation_type<>".COURSE_RELATION_TYPE_RRHH." AND
4504
                user_course_cat='".intval($user_course_category)."'";
4505
    $result_max = Database::query($sql);
4506
    if (Database::num_rows($result_max) == 1) {
4507
        $row_max = Database::fetch_array($result_max);
4508
        return $row_max['max_sort'];
4509
    }
4510
    return 0;
4511
}
4512
4513
/**
4514
 * This function converts the string "true" or "false" to a boolean true or false.
4515
 * This function is in the first place written for the Chamilo Config Settings (also named AWACS)
4516
 * @param string "true" or "false"
4517
 * @return boolean true or false
4518
 * @author Patrick Cool <[email protected]>, Ghent University
4519
 */
4520
function api_string_2_boolean($string) {
4521
    if ($string == 'true') {
4522
        return true;
4523
    }
4524
    if ($string == 'false') {
4525
        return false;
4526
    }
4527
    return false;
4528
}
4529
4530
/**
4531
 * Determines the number of plugins installed for a given location
4532
 */
4533
function api_number_of_plugins($location) {
4534
    global $_plugins;
4535
    return isset($_plugins[$location]) && is_array($_plugins[$location]) ? count($_plugins[$location]) : 0;
4536
}
4537
4538
/**
4539
 * Checks to see wether a certain plugin is installed.
4540
 * @return boolean true if the plugin is installed, false otherwise.
4541
 */
4542
function api_is_plugin_installed($plugin_list, $plugin_name) {
4543
    if (is_array($plugin_list)) {
4544
        foreach ($plugin_list as $plugin_location) {
4545
            if (array_search($plugin_name, $plugin_location) !== false) {
4546
                return true;
4547
            }
4548
        }
4549
    }
4550
    return false;
4551
}
4552
4553
/**
4554
 * Transforms a number of seconds in hh:mm:ss format
4555
 * @author Julian Prud'homme
4556
 * @param integer the number of seconds
4557
 * @return string the formated time
4558
 */
4559
function api_time_to_hms($seconds)
4560
{
4561
    // $seconds = -1 means that we have wrong data in the db.
4562
    if ($seconds == -1) {
4563
        return
4564
            get_lang('Unknown').
4565
            Display::return_icon(
4566
                'info2.gif',
4567
                get_lang('WrongDatasForTimeSpentOnThePlatform'),
4568
                array('align' => 'absmiddle', 'hspace' => '3px')
4569
            );
4570
    }
4571
4572
    // How many hours ?
4573
    $hours = floor($seconds / 3600);
4574
4575
    // How many minutes ?
4576
    $min = floor(($seconds - ($hours * 3600)) / 60);
4577
4578
    // How many seconds
4579
    $sec = floor($seconds - ($hours * 3600) - ($min * 60));
4580
4581
    if ($sec < 10) {
4582
        $sec = "0$sec";
4583
    }
4584
4585
    if ($min < 10) {
4586
        $min = "0$min";
4587
    }
4588
4589
    return "$hours:$min:$sec";
4590
}
4591
4592
/* FILE SYSTEM RELATED FUNCTIONS */
4593
4594
/**
4595
 * Returns the permissions to be assigned to every newly created directory by the web-server.
4596
 * The return value is based on the platform administrator's setting
4597
 * "Administration > Configuration settings > Security > Permissions for new directories".
4598
 * @return int  Returns the permissions in the format "Owner-Group-Others, Read-Write-Execute", as an integer value.
4599
 */
4600 View Code Duplication
function api_get_permissions_for_new_directories() {
4601
    static $permissions;
4602
    if (!isset($permissions)) {
4603
        $permissions = trim(api_get_setting('permissions_for_new_directories'));
4604
        // The default value 0777 is according to that in the platform administration panel after fresh system installation.
4605
        $permissions = octdec(!empty($permissions) ? $permissions : '0777');
4606
    }
4607
    return $permissions;
4608
}
4609
4610
/**
4611
 * Returns the permissions to be assigned to every newly created directory by the web-server.
4612
 * The return value is based on the platform administrator's setting
4613
 * "Administration > Configuration settings > Security > Permissions for new files".
4614
 * @return int Returns the permissions in the format
4615
 * "Owner-Group-Others, Read-Write-Execute", as an integer value.
4616
 */
4617 View Code Duplication
function api_get_permissions_for_new_files() {
4618
    static $permissions;
4619
    if (!isset($permissions)) {
4620
        $permissions = trim(api_get_setting('permissions_for_new_files'));
4621
        // The default value 0666 is according to that in the platform administration panel after fresh system installation.
4622
        $permissions = octdec(!empty($permissions) ? $permissions : '0666');
4623
    }
4624
    return $permissions;
4625
}
4626
4627
/**
4628
 * Deletes a file, or a folder and its contents
4629
 *
4630
 * @author      Aidan Lister <[email protected]>
4631
 * @version     1.0.3
4632
 * @param       string   $dirname    Directory to delete
4633
 * @param       bool     Deletes only the content or not
4634
 * @param       bool     $strict if one folder/file fails stop the loop
4635
 * @return      bool     Returns TRUE on success, FALSE on failure
4636
 * @link http://aidanlister.com/2004/04/recursively-deleting-a-folder-in-php/
4637
 * @author      Yannick Warnier, adaptation for the Chamilo LMS, April, 2008
4638
 * @author      Ivan Tcholakov, a sanity check about Directory class creation has been added, September, 2009
4639
 */
4640
function rmdirr($dirname, $delete_only_content_in_folder = false, $strict = false) {
4641
    $res = true;
4642
4643
    // A sanity check.
4644
    if (!file_exists($dirname)) {
4645
        return false;
4646
    }
4647
    $php_errormsg = '';
4648
    // Simple delete for a file.
4649
    if (is_file($dirname) || is_link($dirname)) {
4650
        $res = unlink($dirname);
4651 View Code Duplication
        if ($res === false) {
4652
            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);
4653
        }
4654
        return $res;
4655
    }
4656
4657
    // Loop through the folder.
4658
    $dir = dir($dirname);
4659
    // A sanity check.
4660
    $is_object_dir = is_object($dir);
4661 View Code Duplication
    if ($is_object_dir) {
4662
        while (false !== $entry = $dir->read()) {
4663
            // Skip pointers.
4664
            if ($entry == '.' || $entry == '..') {
4665
                continue;
4666
            }
4667
4668
            // Recurse.
4669
            if ($strict) {
4670
                $result = rmdirr("$dirname/$entry");
4671
                if ($result == false) {
4672
                    $res = false;
4673
                    break;
4674
                }
4675
            } else {
4676
                rmdirr("$dirname/$entry");
4677
            }
4678
        }
4679
    }
4680
4681
    // Clean up.
4682
    if ($is_object_dir) {
4683
        $dir->close();
4684
    }
4685
4686
    if ($delete_only_content_in_folder == false) {
4687
        $res = rmdir($dirname);
4688 View Code Duplication
        if ($res === false) {
4689
            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);
4690
        }
4691
    }
4692
    return $res;
4693
}
4694
4695
// TODO: This function is to be simplified. File access modes to be implemented.
4696
/**
4697
 * function adapted from a php.net comment
4698
 * copy recursively a folder
4699
 * @param the source folder
4700
 * @param the dest folder
4701
 * @param an array of excluded file_name (without extension)
4702
 * @param copied_files the returned array of copied files
4703
 */
4704
function copyr($source, $dest, $exclude = array(), $copied_files = array()) {
4705
    if (empty($dest)) { return false; }
4706
    // Simple copy for a file
4707
    if (is_file($source)) {
4708
        $path_info = pathinfo($source);
4709
        if (!in_array($path_info['filename'], $exclude)) {
4710
            copy($source, $dest);
4711
        }
4712
        return true;
4713
    } elseif (!is_dir($source)) {
4714
        //then source is not a dir nor a file, return
4715
        return false;
4716
    }
4717
4718
    // Make destination directory.
4719
    if (!is_dir($dest)) {
4720
        mkdir($dest, api_get_permissions_for_new_directories());
4721
    }
4722
4723
    // Loop through the folder.
4724
    $dir = dir($source);
4725
    while (false !== $entry = $dir->read()) {
4726
        // Skip pointers
4727
        if ($entry == '.' || $entry == '..') {
4728
            continue;
4729
        }
4730
4731
        // Deep copy directories.
4732
        if ($dest !== "$source/$entry") {
4733
            $files = copyr("$source/$entry", "$dest/$entry", $exclude, $copied_files);
4734
        }
4735
    }
4736
    // Clean up.
4737
    $dir->close();
4738
    return true;
4739
}
4740
4741
// TODO: Using DIRECTORY_SEPARATOR is not recommended, this is an obsolete approach. Documentation header to be added here.
4742
function copy_folder_course_session(
4743
    $pathname,
4744
    $base_path_document,
4745
    $session_id,
4746
    $course_info,
4747
    $document,
4748
    $source_course_id
4749
) {
4750
    $table = Database :: get_course_table(TABLE_DOCUMENT);
4751
    $session_id = intval($session_id);
4752
    $source_course_id = intval($source_course_id);
4753
4754
    // Check whether directory already exists.
4755
    if (is_dir($pathname) || empty($pathname)) {
4756
        return true;
4757
    }
4758
4759
    // Ensure that a file with the same name does not already exist.
4760
    if (is_file($pathname)) {
4761
        trigger_error('copy_folder_course_session(): File exists', E_USER_WARNING);
4762
        return false;
4763
    }
4764
4765
    $course_id = $course_info['real_id'];
4766
4767
    $folders = explode(DIRECTORY_SEPARATOR,str_replace($base_path_document.DIRECTORY_SEPARATOR,'',$pathname));
4768
4769
    $new_pathname = $base_path_document;
4770
    $path = '';
4771
4772
    foreach ($folders as $folder) {
4773
        $new_pathname .= DIRECTORY_SEPARATOR.$folder;
4774
        $path .= DIRECTORY_SEPARATOR.$folder;
4775
4776
        if (!file_exists($new_pathname)) {
4777
            $path = Database::escape_string($path);
4778
4779
            $sql = "SELECT * FROM $table
4780
                    WHERE
4781
                        c_id = $source_course_id AND
4782
                        path = '$path' AND
4783
                        filetype = 'folder' AND
4784
                        session_id = '$session_id'";
4785
            $rs1  = Database::query($sql);
4786
            $num_rows = Database::num_rows($rs1);
4787
4788
            if ($num_rows == 0) {
4789
                mkdir($new_pathname, api_get_permissions_for_new_directories());
4790
4791
                // Insert new folder with destination session_id.
4792
                $params = [
4793
                    'c_id' => $course_id,
4794
                    'path' => $path,
4795
                    'comment' => $document->comment,
4796
                    'title' => basename($new_pathname),
4797
                    'filetype' => 'folder',
4798
                    'size' => '0',
4799
                    'session_id' => $session_id
4800
                ];
4801
                $document_id = Database::insert($table, $params);
4802
                if ($document_id) {
4803
4804
                    $sql = "UPDATE $table SET id = iid WHERE iid = $document_id";
4805
                    Database::query($sql);
4806
4807
                    api_item_property_update(
4808
                        $course_info,
4809
                        TOOL_DOCUMENT,
4810
                        $document_id,
4811
                        'FolderCreated',
4812
                        api_get_user_id(),
4813
                        0,
4814
                        0,
4815
                        null,
4816
                        null,
4817
                        $session_id
4818
                    );
4819
                }
4820
            }
4821
        }
4822
4823
    } // en foreach
4824
}
4825
4826
// TODO: chmodr() is a better name. Some corrections are needed. Documentation header to be added here.
4827
function api_chmod_R($path, $filemode) {
4828
    if (!is_dir($path)) {
4829
        return chmod($path, $filemode);
4830
    }
4831
4832
    $handler = opendir($path);
4833
    while ($file = readdir($handler)) {
4834
        if ($file != '.' && $file != '..') {
4835
            $fullpath = "$path/$file";
4836
            if (!is_dir($fullpath)) {
4837
                if (!chmod($fullpath, $filemode)) {
4838
                    return false;
4839
                }
4840
            } else {
4841
                if (!api_chmod_R($fullpath, $filemode)) {
4842
                    return false;
4843
                }
4844
            }
4845
        }
4846
    }
4847
4848
    closedir($handler);
4849
    return chmod($path, $filemode);
4850
}
4851
4852
4853
// TODO: Where the following function has been copy/pased from? There is no information about author and license. Style, coding conventions...
4854
/**
4855
 * Parse info file format. (e.g: file.info)
4856
 *
4857
 * Files should use an ini-like format to specify values.
4858
 * White-space generally doesn't matter, except inside values.
4859
 * e.g.
4860
 *
4861
 * @verbatim
4862
 *   key = value
4863
 *   key = "value"
4864
 *   key = 'value'
4865
 *   key = "multi-line
4866
 *
4867
 *   value"
4868
 *   key = 'multi-line
4869
 *
4870
 *   value'
4871
 *   key
4872
 *   =
4873
 *   'value'
4874
 * @endverbatim
4875
 *
4876
 * Arrays are created using a GET-like syntax:
4877
 *
4878
 * @verbatim
4879
 *   key[] = "numeric array"
4880
 *   key[index] = "associative array"
4881
 *   key[index][] = "nested numeric array"
4882
 *   key[index][index] = "nested associative array"
4883
 * @endverbatim
4884
 *
4885
 * PHP constants are substituted in, but only when used as the entire value:
4886
 *
4887
 * Comments should start with a semi-colon at the beginning of a line.
4888
 *
4889
 * This function is NOT for placing arbitrary module-specific settings. Use
4890
 * variable_get() and variable_set() for that.
4891
 *
4892
 * Information stored in the module.info file:
4893
 * - name: The real name of the module for display purposes.
4894
 * - description: A brief description of the module.
4895
 * - dependencies: An array of shortnames of other modules this module depends on.
4896
 * - package: The name of the package of modules this module belongs to.
4897
 *
4898
 * Example of .info file:
4899
 * <code>
4900
 * @verbatim
4901
 *   name = Forum
4902
 *   description = Enables threaded discussions about general topics.
4903
 *   dependencies[] = taxonomy
4904
 *   dependencies[] = comment
4905
 *   package = Core - optional
4906
 *   version = VERSION
4907
 * @endverbatim
4908
 * </code>
4909
 * @param $filename
4910
 *   The file we are parsing. Accepts file with relative or absolute path.
4911
 * @return
4912
 *   The info array.
4913
 */
4914
function parse_info_file($filename) {
4915
    $info = array();
4916
4917
    if (!file_exists($filename)) {
4918
        return $info;
4919
    }
4920
4921
    $data = file_get_contents($filename);
4922
    if (preg_match_all('
4923
        @^\s*                           # Start at the beginning of a line, ignoring leading whitespace
4924
        ((?:
4925
          [^=;\[\]]|                    # Key names cannot contain equal signs, semi-colons or square brackets,
4926
          \[[^\[\]]*\]                  # unless they are balanced and not nested
4927
        )+?)
4928
        \s*=\s*                         # Key/value pairs are separated by equal signs (ignoring white-space)
4929
        (?:
4930
          ("(?:[^"]|(?<=\\\\)")*")|     # Double-quoted string, which may contain slash-escaped quotes/slashes
4931
          (\'(?:[^\']|(?<=\\\\)\')*\')| # Single-quoted string, which may contain slash-escaped quotes/slashes
4932
          ([^\r\n]*?)                   # Non-quoted string
4933
        )\s*$                           # Stop at the next end of a line, ignoring trailing whitespace
4934
        @msx', $data, $matches, PREG_SET_ORDER)) {
4935
        $key = $value1 = $value2 = $value3 = '';
4936
        foreach ($matches as $match) {
4937
            // Fetch the key and value string.
4938
            $i = 0;
4939
            foreach (array('key', 'value1', 'value2', 'value3') as $var) {
4940
                $$var = isset($match[++$i]) ? $match[$i] : '';
4941
            }
4942
            $value = stripslashes(substr($value1, 1, -1)) . stripslashes(substr($value2, 1, -1)) . $value3;
4943
4944
            // Parse array syntax.
4945
            $keys = preg_split('/\]?\[/', rtrim($key, ']'));
4946
            $last = array_pop($keys);
4947
            $parent = &$info;
4948
4949
            // Create nested arrays.
4950
            foreach ($keys as $key) {
4951
                if ($key == '') {
4952
                    $key = count($parent);
4953
                }
4954
                if (!isset($parent[$key]) || !is_array($parent[$key])) {
4955
                    $parent[$key] = array();
4956
                }
4957
                $parent = &$parent[$key];
4958
            }
4959
4960
            // Handle PHP constants.
4961
            if (defined($value)) {
4962
                $value = constant($value);
4963
            }
4964
4965
            // Insert actual value.
4966
            if ($last == '') {
4967
                $last = count($parent);
4968
            }
4969
            $parent[$last] = $value;
4970
        }
4971
    }
4972
    return $info;
4973
}
4974
4975
4976
/**
4977
 * Gets Chamilo version from the configuration files
4978
 * @return string   A string of type "1.8.4", or an empty string if the version could not be found
4979
 */
4980
function api_get_version() {
4981
    global $_configuration;
4982
    return (string)$_configuration['system_version'];
4983
}
4984
4985
/**
4986
 * Gets the software name (the name/brand of the Chamilo-based customized system)
4987
 * @return string
4988
 */
4989
function api_get_software_name() {
4990
    $name = api_get_configuration_value('software_name');
4991
    if (!empty($name)) {
4992
        return $name;
4993
    } else {
4994
        return 'Chamilo';
4995
    }
4996
}
4997
4998
/**
4999
 * Checks whether status given in parameter exists in the platform
5000
 * @param mixed the status (can be either int either string)
5001
 * @return true if the status exists, else returns false
5002
 */
5003
function api_status_exists($status_asked) {
5004
    global $_status_list;
5005
    return in_array($status_asked, $_status_list) ? true : isset($_status_list[$status_asked]);
5006
}
5007
5008
/**
5009
 * Checks whether status given in parameter exists in the platform. The function
5010
 * returns the status ID or false if it does not exist, but given the fact there
5011
 * is no "0" status, the return value can be checked against
5012
 * if(api_status_key()) to know if it exists.
5013
 * @param   mixed   The status (can be either int or string)
5014
 * @return  mixed   Status ID if exists, false otherwise
5015
 */
5016
function api_status_key($status) {
5017
    global $_status_list;
5018
    return isset($_status_list[$status]) ? $status : array_search($status, $_status_list);
5019
}
5020
5021
/**
5022
 * Gets the status langvars list
5023
 * @return array the list of status with their translations
5024
 */
5025
function api_get_status_langvars() {
5026
    return array(
5027
        COURSEMANAGER   => get_lang('Teacher', ''),
5028
        SESSIONADMIN    => get_lang('SessionsAdmin', ''),
5029
        DRH             => get_lang('Drh', ''),
5030
        STUDENT         => get_lang('Student', ''),
5031
        ANONYMOUS       => get_lang('Anonymous', ''),
5032
        STUDENT_BOSS    => get_lang('RoleStudentBoss', ''),
5033
        INVITEE         => get_lang('Invited'),
5034
    );
5035
}
5036
5037
/**
5038
* The function that retrieves all the possible settings for a certain config setting
5039
* @author Patrick Cool <[email protected]>, Ghent University
5040
*/
5041
function api_get_settings_options($var) {
5042
    $table_settings_options = Database :: get_main_table(TABLE_MAIN_SETTINGS_OPTIONS);
5043
    $var = Database::escape_string($var);
5044
    $sql = "SELECT * FROM $table_settings_options
5045
            WHERE variable = '$var'
5046
            ORDER BY id";
5047
    $result = Database::query($sql);
5048
    $settings_options_array = array();
5049
    while ($row = Database::fetch_array($result, 'ASSOC')) {
5050
        $settings_options_array[] = $row;
5051
    }
5052
    return $settings_options_array;
5053
}
5054
5055
/**
5056
 * @param array $params
5057
 */
5058
function api_set_setting_option($params) {
5059
    $table = Database::get_main_table(TABLE_MAIN_SETTINGS_OPTIONS);
5060 View Code Duplication
    if (empty($params['id'])) {
5061
        Database::insert($table, $params);
5062
    } else {
5063
        Database::update($table, $params, array('id = ? '=> $params['id']));
5064
    }
5065
}
5066
5067
/**
5068
 * @param array $params
5069
 */
5070
function api_set_setting_simple($params) {
5071
    $table = Database::get_main_table(TABLE_MAIN_SETTINGS_CURRENT);
5072
    $url_id = api_get_current_access_url_id();
5073
5074 View Code Duplication
    if (empty($params['id'])) {
5075
        $params['access_url'] = $url_id;
5076
        Database::insert($table, $params);
5077
    } else {
5078
        Database::update($table, $params, array('id = ? '=> array($params['id'])));
5079
    }
5080
}
5081
5082
/**
5083
 * @param int $id
5084
 */
5085
function api_delete_setting_option($id) {
5086
    $table = Database::get_main_table(TABLE_MAIN_SETTINGS_OPTIONS);
5087
    if (!empty($id)) {
5088
        Database::delete($table, array('id = ? '=> $id));
5089
    }
5090
}
5091
5092
/**
5093
 * Sets a platform configuration setting to a given value
5094
 * @param string    The variable we want to update
5095
 * @param string    The value we want to record
5096
 * @param string    The sub-variable if any (in most cases, this will remain null)
5097
 * @param string    The category if any (in most cases, this will remain null)
5098
 * @param int       The access_url for which this parameter is valid
5099
 */
5100
function api_set_setting($var, $value, $subvar = null, $cat = null, $access_url = 1)
5101
{
5102
    if (empty($var)) {
5103
        return false;
5104
    }
5105
    $t_settings = Database::get_main_table(TABLE_MAIN_SETTINGS_CURRENT);
5106
    $var = Database::escape_string($var);
5107
    $value = Database::escape_string($value);
5108
    $access_url = (int)$access_url;
5109
    if (empty($access_url)) { $access_url = 1; }
5110
    $select = "SELECT id FROM $t_settings WHERE variable = '$var' ";
5111
    if (!empty($subvar)) {
5112
        $subvar = Database::escape_string($subvar);
5113
        $select .= " AND subkey = '$subvar'";
5114
    }
5115
    if (!empty($cat)) {
5116
        $cat = Database::escape_string($cat);
5117
        $select .= " AND category = '$cat'";
5118
    }
5119
    if ($access_url > 1) {
5120
        $select .= " AND access_url = $access_url";
5121
    } else {
5122
        $select .= " AND access_url = 1 ";
5123
    }
5124
5125
    $res = Database::query($select);
5126
    if (Database::num_rows($res) > 0) {
5127
        // Found item for this access_url.
5128
        $row = Database::fetch_array($res);
5129
        $sql = "UPDATE $t_settings SET selected_value = '$value'
5130
                WHERE id = ".$row['id'] ;
5131
        Database::query($sql);
5132
    } else {
5133
        // Item not found for this access_url, we have to check if it exist with access_url = 1
5134
        $select = "SELECT * FROM $t_settings
5135
                   WHERE variable = '$var' AND access_url = 1 ";
5136
        // Just in case
5137
        if ($access_url == 1) {
5138
            if (!empty($subvar)) {
5139
                $select .= " AND subkey = '$subvar'";
5140
            }
5141
            if (!empty($cat)) {
5142
                $select .= " AND category = '$cat'";
5143
            }
5144
            $res = Database::query($select);
5145
5146
            if (Database::num_rows($res) > 0) {
5147
                // We have a setting for access_url 1, but none for the current one, so create one.
5148
                $row = Database::fetch_array($res);
5149
                $insert = "INSERT INTO $t_settings (variable, subkey, type,category, selected_value, title, comment, scope, subkeytext, access_url)
5150
                        VALUES
5151
                        ('".$row['variable']."',".(!empty($row['subkey']) ? "'".$row['subkey']."'" : "NULL")."," .
5152
                        "'".$row['type']."','".$row['category']."'," .
5153
                        "'$value','".$row['title']."'," .
5154
                        "".(!empty($row['comment']) ? "'".$row['comment']."'" : "NULL").",".(!empty($row['scope']) ? "'".$row['scope']."'" : "NULL")."," .
5155
                        "".(!empty($row['subkeytext'])?"'".$row['subkeytext']."'":"NULL").",$access_url)";
5156
                Database::query($insert);
5157 View Code Duplication
            } else { // Such a setting does not exist.
5158
                error_log(__FILE__.':'.__LINE__.': Attempting to update setting '.$var.' ('.$subvar.') which does not exist at all', 0);
5159
            }
5160
        } else {
5161
            // Other access url.
5162
            if (!empty($subvar)) {
5163
                $select .= " AND subkey = '$subvar'";
5164
            }
5165
            if (!empty($cat)) {
5166
                $select .= " AND category = '$cat'";
5167
            }
5168
            $res = Database::query($select);
5169
5170
            if (Database::num_rows($res) > 0) { // We have a setting for access_url 1, but none for the current one, so create one.
5171
                $row = Database::fetch_array($res);
5172
                if ($row['access_url_changeable'] == 1) {
5173
                    $insert = "INSERT INTO $t_settings (variable,subkey, type,category, selected_value,title, comment,scope, subkeytext,access_url, access_url_changeable) VALUES
5174
                            ('".$row['variable']."',".
5175
                            (!empty($row['subkey']) ? "'".$row['subkey']."'" : "NULL")."," .
5176
                            "'".$row['type']."','".$row['category']."'," .
5177
                            "'$value','".$row['title']."'," .
5178
                            "".(!empty($row['comment']) ? "'".$row['comment']."'" : "NULL").",".
5179
                            (!empty($row['scope']) ? "'".$row['scope']."'" : "NULL")."," .
5180
                            "".(!empty($row['subkeytext']) ? "'".$row['subkeytext']."'" : "NULL").",$access_url,".$row['access_url_changeable'].")";
5181
                    Database::query($insert);
5182
                }
5183 View Code Duplication
            } else { // Such a setting does not exist.
5184
                error_log(__FILE__.':'.__LINE__.': Attempting to update setting '.$var.' ('.$subvar.') which does not exist at all. The access_url is: '.$access_url.' ',0);
5185
            }
5186
        }
5187
    }
5188
}
5189
5190
/**
5191
 * Sets a whole category of settings to one specific value
5192
 * @param string    Category
5193
 * @param string    Value
5194
 * @param int       Access URL. Optional. Defaults to 1
5195
 * @param array     Optional array of filters on field type
5196
 */
5197
function api_set_settings_category($category, $value = null, $access_url = 1, $fieldtype = array())
5198
{
5199
    if (empty($category)) {
5200
        return false;
5201
    }
5202
    $category = Database::escape_string($category);
5203
    $t_s = Database::get_main_table(TABLE_MAIN_SETTINGS_CURRENT);
5204
    $access_url = (int) $access_url;
5205
    if (empty($access_url)) { $access_url = 1; }
5206
    if (isset($value)) {
5207
        $value = Database::escape_string($value);
5208
        $sql = "UPDATE $t_s SET selected_value = '$value'
5209
                WHERE category = '$category' AND access_url = $access_url";
5210 View Code Duplication
        if (is_array($fieldtype) && count($fieldtype)>0) {
5211
            $sql .= " AND ( ";
5212
            $i = 0;
5213
            foreach ($fieldtype as $type){
5214
                if ($i > 0) {
5215
                    $sql .= ' OR ';
5216
                }
5217
                $type = Database::escape_string($type);
5218
                $sql .= " type='".$type."' ";
5219
                $i++;
5220
            }
5221
            $sql .= ")";
5222
        }
5223
        $res = Database::query($sql);
5224
        return $res !== false;
5225
    } else {
5226
        $sql = "UPDATE $t_s SET selected_value = NULL
5227
                WHERE category = '$category' AND access_url = $access_url";
5228 View Code Duplication
        if (is_array($fieldtype) && count($fieldtype)>0) {
5229
            $sql .= " AND ( ";
5230
            $i = 0;
5231
            foreach ($fieldtype as $type){
5232
                if ($i > 0) {
5233
                    $sql .= ' OR ';
5234
                }
5235
                $type = Database::escape_string($type);
5236
                $sql .= " type='".$type."' ";
5237
                $i++;
5238
            }
5239
            $sql .= ")";
5240
        }
5241
        $res = Database::query($sql);
5242
        return $res !== false;
5243
    }
5244
}
5245
5246
/**
5247
 * Gets all available access urls in an array (as in the database)
5248
 * @return array    An array of database records
5249
 */
5250
function api_get_access_urls($from = 0, $to = 1000000, $order = 'url', $direction = 'ASC')
5251
{
5252
    $table = Database::get_main_table(TABLE_MAIN_ACCESS_URL);
5253
    $from = (int) $from;
5254
    $to = (int) $to;
5255
    $order = Database::escape_string($order, null, false);
5256
    $direction = Database::escape_string($direction, null, false);
5257
    $sql = "SELECT id, url, description, active, created_by, tms
5258
            FROM $table
5259
            ORDER BY $order $direction
5260
            LIMIT $to OFFSET $from";
5261
    $res = Database::query($sql);
5262
    return Database::store_result($res);
5263
}
5264
5265
/**
5266
 * Gets the access url info in an array
5267
 * @param int $id Id of the access url
5268
 * @param bool $returnDefault Set to false if you want the real URL if URL 1 is still 'http://localhost/'
5269
 * @return array All the info (url, description, active, created_by, tms)
5270
 * from the access_url table
5271
 * @author Julio Montoya
5272
 */
5273
function api_get_access_url($id, $returnDefault = true)
5274
{
5275
    $id = intval($id);
5276
    // Calling the Database:: library dont work this is handmade.
5277
    $table_access_url = Database::get_main_table(TABLE_MAIN_ACCESS_URL);
5278
    $sql = "SELECT url, description, active, created_by, tms
5279
            FROM $table_access_url WHERE id = '$id' ";
5280
    $res = Database::query($sql);
5281
    $result = @Database::fetch_array($res);
5282
    // If the result url is 'http://localhost/' (the default) and the root_web
5283
    // (=current url) is different, and the $id is = 1 (which might mean
5284
    // api_get_current_access_url_id() returned 1 by default), then return the
5285
    // root_web setting instead of the current URL
5286
    // This is provided as an option to avoid breaking the storage of URL-specific
5287
    // homepages in home/localhost/
5288
    if ($id === 1 && $returnDefault === false) {
5289
        $currentUrl = api_get_current_access_url_id();
5290
        // only do this if we are on the main URL (=1), otherwise we could get
5291
        // information on another URL instead of the one asked as parameter
5292
        if ($currentUrl === 1) {
5293
            $rootWeb = api_get_path(WEB_PATH);
5294
            $default = 'http://localhost/';
5295
            if ($result['url'] === $default && $rootWeb != $default) {
5296
                $result['url'] = $rootWeb;
5297
            }
5298
        }
5299
    }
5300
5301
    return $result;
5302
}
5303
5304
/**
5305
 * Adds an access URL into the database
5306
 * @param string    URL
5307
 * @param string    Description
5308
 * @param int       Active (1= active, 0=disabled)
5309
 * @return int      The new database id, or the existing database id if this url already exists
5310
 */
5311
function api_add_access_url($u, $d = '', $a = 1) {
5312
    $t_au = Database::get_main_table(TABLE_MAIN_ACCESS_URL);
5313
    $u = Database::escape_string($u);
5314
    $d = Database::escape_string($d);
5315
    $a = (int) $a;
5316
    $sql = "SELECT id FROM $t_au WHERE url LIKE '$u'";
5317
    $res = Database::query($sql);
5318
    if ($res === false) {
5319
        // Problem querying the database - return false.
5320
        return false;
5321
    }
5322
    if (Database::num_rows($res) > 0) {
5323
        return Database::result($res, 0, 'id');
5324
    }
5325
    $ui = api_get_user_id();
5326
5327
    $sql = "INSERT INTO $t_au (url,description,active,created_by,tms) VALUES ('$u','$d',$a,$ui,'')";
5328
    $res = Database::query($sql);
5329
    return ($res === false) ? false : Database::insert_id();
5330
}
5331
5332
/**
5333
 * Gets all the current settings for a specific access url
5334
 * @param string    The category, if any, that we want to get
5335
 * @param string    Whether we want a simple list (display a category) or
5336
 * a grouped list (group by variable as in settings.php default). Values: 'list' or 'group'
5337
 * @param int       Access URL's ID. Optional. Uses 1 by default, which is the unique URL
5338
 * @return array    Array of database results for the current settings of the current access URL
5339
 */
5340
function & api_get_settings($cat = null, $ordering = 'list', $access_url = 1, $url_changeable = 0)
5341
{
5342
    $table = Database::get_main_table(TABLE_MAIN_SETTINGS_CURRENT);
5343
    $access_url = (int) $access_url;
5344
    $where_condition = '';
5345
    if ($url_changeable == 1) {
5346
        $where_condition = " AND access_url_changeable= '1' ";
5347
    }
5348
    if (empty($access_url) || $access_url == -1) {
5349
        $access_url = 1;
5350
    }
5351
    $sql = "SELECT * FROM $table
5352
            WHERE access_url = $access_url  $where_condition ";
5353
5354
    if (!empty($cat)) {
5355
        $cat = Database::escape_string($cat);
5356
        $sql .= " AND category='$cat' ";
5357
    }
5358
    if ($ordering == 'group') {
5359
        $sql .= " ORDER BY id ASC";
5360
    } else {
5361
        $sql .= " ORDER BY 1,2 ASC";
5362
    }
5363
    $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...
5364
    return $result;
5365
}
5366
5367
/**
5368
 * Gets the distinct settings categories
5369
 * @param array     Array of strings giving the categories we want to excluded
5370
 * @param int       Access URL. Optional. Defaults to 1
5371
 * @return array    A list of categories
5372
 */
5373
function & api_get_settings_categories($exceptions = array(), $access_url = 1) {
5374
    $access_url = (int) $access_url;
5375
    $t_cs = Database::get_main_table(TABLE_MAIN_SETTINGS_CURRENT);
5376
    $list = "'".implode("','",$exceptions)."'";
5377
    $sql = "SELECT DISTINCT category FROM $t_cs WHERE category is NOT NULL ";
5378
    if ($list != "'',''" && $list != "''" && !empty($list)) {
5379
        $sql .= " AND category NOT IN ($list) ";
5380
    }
5381
    $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...
5382
    return $result;
5383
}
5384
5385
/**
5386
 * Deletes a setting
5387
 * @param string    Variable
5388
 * @param string    Subkey
5389
 * @param int       Access URL
5390
 * @return boolean  False on failure, true on success
5391
 */
5392
5393
function api_delete_setting($v, $s = null, $a = 1) {
5394
    if (empty($v)) { return false; }
5395
    $t_cs = Database::get_main_table(TABLE_MAIN_SETTINGS_CURRENT);
5396
    $v = Database::escape_string($v);
5397
    $a = (int) $a;
5398
    if (empty($a)) { $a = 1; }
5399
    if (!empty($s)) {
5400
        $s = Database::escape_string($s);
5401
        $sql = "DELETE FROM $t_cs WHERE variable = '$v' AND subkey = '$s' AND access_url = $a";
5402
        $r = Database::query($sql);
5403
        return $r;
5404
    }
5405
    $sql = "DELETE FROM $t_cs WHERE variable = '$v' AND access_url = $a";
5406
    $r = Database::query($sql);
5407
    return $r;
5408
}
5409
5410
/**
5411
 * Deletes all the settings from one category
5412
 * @param string    Subkey
5413
 * @param int       Access URL
5414
 * @return boolean  False on failure, true on success
5415
 */
5416
function api_delete_category_settings_by_subkey($subkey, $access_url_id = 1) {
5417
    if (empty($subkey)) { return false; }
5418
    $t_cs = Database::get_main_table(TABLE_MAIN_SETTINGS_CURRENT);
5419
    $subkey = Database::escape_string($subkey);
5420
    $access_url_id = intval($access_url_id);
5421
    $sql = "DELETE FROM $t_cs WHERE subkey = '$subkey' AND access_url = $access_url_id";
5422
    $r = Database::query($sql);
5423
    return $r;
5424
}
5425
5426
/**
5427
 * Sets a platform configuration setting to a given value
5428
 * @param string    The value we want to record
5429
 * @param string    The variable name we want to insert
5430
 * @param string    The subkey for the variable we want to insert
5431
 * @param string    The type for the variable we want to insert
5432
 * @param string    The category for the variable we want to insert
5433
 * @param string    The title
5434
 * @param string    The comment
5435
 * @param string    The scope
5436
 * @param string    The subkey text
5437
 * @param int       The access_url for which this parameter is valid
5438
 * @param int       The changeability of this setting for non-master urls
5439
 * @return boolean  true on success, false on failure
5440
 */
5441
function api_add_setting($val, $var, $sk = null, $type = 'textfield', $c = null, $title = '', $com = '', $sc = null, $skt = null, $a = 1, $v = 0) {
5442
    if (empty($var) || !isset($val)) { return false; }
5443
    $t_settings = Database::get_main_table(TABLE_MAIN_SETTINGS_CURRENT);
5444
    $var = Database::escape_string($var);
5445
    $val = Database::escape_string($val);
5446
    $a = (int) $a;
5447
    if (empty($a)) { $a = 1; }
5448
    // Check if this variable doesn't exist already
5449
    $select = "SELECT id FROM $t_settings WHERE variable = '$var' ";
5450
    if (!empty($sk)) {
5451
        $sk = Database::escape_string($sk);
5452
        $select .= " AND subkey = '$sk'";
5453
    }
5454
    if ($a > 1) {
5455
        $select .= " AND access_url = $a";
5456
    } else {
5457
        $select .= " AND access_url = 1 ";
5458
    }
5459
    $res = Database::query($select);
5460
    if (Database::num_rows($res) > 0) { // Found item for this access_url.
5461
        $row = Database::fetch_array($res);
5462
        Database::update(
5463
            $t_settings,
5464
            array('selected_value' => $val),
5465
            array('id = ?' => array($row['id']))
5466
        );
5467
        return $row['id'];
5468
    }
5469
5470
    // Item not found for this access_url, we have to check if the whole thing is missing
5471
    // (in which case we ignore the insert) or if there *is* a record but just for access_url = 1
5472
    $insert = "INSERT INTO $t_settings " .
5473
                "(variable,selected_value," .
5474
                "type,category," .
5475
                "subkey,title," .
5476
                "comment,scope," .
5477
                "subkeytext,access_url,access_url_changeable)" .
5478
                " VALUES ('$var','$val',";
5479 View Code Duplication
    if (isset($type)) {
5480
        $type = Database::escape_string($type);
5481
        $insert .= "'$type',";
5482
    } else {
5483
        $insert .= "NULL,";
5484
    }
5485 View Code Duplication
    if (isset($c)) { // Category
5486
        $c = Database::escape_string($c);
5487
        $insert .= "'$c',";
5488
    } else {
5489
        $insert .= "NULL,";
5490
    }
5491 View Code Duplication
    if (isset($sk)) { // Subkey
5492
        $sk = Database::escape_string($sk);
5493
        $insert .= "'$sk',";
5494
    } else {
5495
        $insert .= "NULL,";
5496
    }
5497 View Code Duplication
    if (isset($title)) { // Title
5498
        $title = Database::escape_string($title);
5499
        $insert .= "'$title',";
5500
    } else {
5501
        $insert .= "NULL,";
5502
    }
5503 View Code Duplication
    if (isset($com)) { // Comment
5504
        $com = Database::escape_string($com);
5505
        $insert .= "'$com',";
5506
    } else {
5507
        $insert .= "NULL,";
5508
    }
5509 View Code Duplication
    if (isset($sc)) { // Scope
5510
        $sc = Database::escape_string($sc);
5511
        $insert .= "'$sc',";
5512
    } else {
5513
        $insert .= "NULL,";
5514
    }
5515 View Code Duplication
    if (isset($skt)) { // Subkey text
5516
        $skt = Database::escape_string($skt);
5517
        $insert .= "'$skt',";
5518
    } else {
5519
        $insert .= "NULL,";
5520
    }
5521
    $insert .= "$a,$v)";
5522
    $res = Database::query($insert);
5523
    return $res;
5524
}
5525
5526
/**
5527
 * Checks wether a user can or can't view the contents of a course.
5528
 *
5529
 * @param   int $userid     User id or NULL to get it from $_SESSION
5530
 * @param   int $cid        Course id to check whether the user is allowed.
5531
 * @return  bool
5532
 */
5533
function api_is_course_visible_for_user($userid = null, $cid = null) {
5534
    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...
5535
        $userid = api_get_user_id();
5536
    }
5537
    if (empty($userid) || strval(intval($userid)) != $userid) {
5538
        if (api_is_anonymous()) {
5539
            $userid = api_get_anonymous_id();
5540
        } else {
5541
            return false;
5542
        }
5543
    }
5544
    $cid = Database::escape_string($cid);
5545
5546
    $courseInfo = api_get_course_info($cid);
5547
    $courseId = $courseInfo['real_id'];
5548
5549
    global $is_platformAdmin;
5550
5551
    $course_table = Database::get_main_table(TABLE_MAIN_COURSE);
5552
    $course_cat_table = Database::get_main_table(TABLE_MAIN_CATEGORY);
5553
5554
    $sql = "SELECT
5555
                $course_table.category_code,
5556
                $course_table.visibility,
5557
                $course_table.code,
5558
                $course_cat_table.code
5559
            FROM $course_table
5560
            LEFT JOIN $course_cat_table
5561
                ON $course_table.category_code = $course_cat_table.code
5562
            WHERE
5563
                $course_table.code = '$cid'
5564
            LIMIT 1";
5565
5566
    $result = Database::query($sql);
5567
5568 View Code Duplication
    if (Database::num_rows($result) > 0) {
5569
        $visibility = Database::fetch_array($result);
5570
        $visibility = $visibility['visibility'];
5571
    } else {
5572
        $visibility = 0;
5573
    }
5574
    // Shortcut permissions in case the visibility is "open to the world".
5575
    if ($visibility === COURSE_VISIBILITY_OPEN_WORLD) {
5576
        return true;
5577
    }
5578
5579
    $tbl_course_user = Database :: get_main_table(TABLE_MAIN_COURSE_USER);
5580
5581
    $sql = "SELECT
5582
                is_tutor, status
5583
            FROM $tbl_course_user
5584
            WHERE
5585
                user_id  = '$userid' AND
5586
                relation_type <> '".COURSE_RELATION_TYPE_RRHH."' AND
5587
                c_id = $courseId
5588
            LIMIT 1";
5589
5590
    $result = Database::query($sql);
5591
5592
    if (Database::num_rows($result) > 0) {
5593
        // This user has got a recorded state for this course.
5594
        $cuData = Database::fetch_array($result);
5595
        $is_courseMember = true;
5596
        $is_courseTutor = ($cuData['is_tutor'] == 1);
5597
        $is_courseAdmin = ($cuData['status'] == 1);
5598
    }
5599
5600
    if (!$is_courseAdmin) {
5601
        // This user has no status related to this course.
5602
        // Is it the session coach or the session admin?
5603
        $tbl_session = Database::get_main_table(TABLE_MAIN_SESSION);
5604
        $tbl_session_course = Database::get_main_table(TABLE_MAIN_SESSION_COURSE);
5605
        $tbl_session_course_user = Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER);
5606
5607
        $sql = "SELECT
5608
                    session.id_coach, session_admin_id, session.id
5609
                FROM
5610
                    $tbl_session as session
5611
                INNER JOIN $tbl_session_course
5612
                    ON session_rel_course.session_id = session.id
5613
                    AND session_rel_course.c_id = '$courseId'
5614
                LIMIT 1";
5615
5616
        $result = Database::query($sql);
5617
        $row = Database::store_result($result);
5618
5619
        if ($row[0]['id_coach'] == $userid) {
5620
            $is_courseMember = true;
5621
            $is_courseTutor = true;
5622
            $is_courseAdmin = false;
5623
            $is_courseCoach = true;
5624
            $is_sessionAdmin = false;
5625
        }
5626
        elseif ($row[0]['session_admin_id'] == $userid) {
5627
            $is_courseMember = false;
5628
            $is_courseTutor = false;
5629
            $is_courseAdmin = false;
5630
            $is_courseCoach = false;
5631
            $is_sessionAdmin = true;
5632
        } else {
5633
            // Check if the current user is the course coach.
5634
            $sql = "SELECT 1
5635
                    FROM $tbl_session_course
5636
                    WHERE session_rel_course.c_id = '$courseId'
5637
                    AND session_rel_course.id_coach = '$userid'
5638
                    LIMIT 1";
5639
5640
            $result = Database::query($sql);
5641
5642
            //if ($row = Database::fetch_array($result)) {
5643
            if (Database::num_rows($result) > 0 ) {
5644
                $is_courseMember = true;
5645
                $is_courseTutor = true;
5646
                $is_courseCoach = true;
5647
                $is_sessionAdmin = false;
5648
5649
                $tbl_user = Database :: get_main_table(TABLE_MAIN_USER);
5650
5651
                $sql = "SELECT status FROM $tbl_user
5652
                        WHERE user_id = $userid
5653
                        LIMIT 1";
5654
5655
                $result = Database::query($sql);
5656
5657
                if (Database::result($result, 0, 0) == 1) {
5658
                    $is_courseAdmin = true;
5659
                } else {
5660
                    $is_courseAdmin = false;
5661
                }
5662
            } else {
5663
                // Check if the user is a student is this session.
5664
                $sql = "SELECT  id
5665
                        FROM $tbl_session_course_user
5666
                        WHERE
5667
                            user_id  = '$userid' AND
5668
                            c_id = '$courseId'
5669
                        LIMIT 1";
5670
5671
                if (Database::num_rows($result) > 0) {
5672
                    // This user haa got a recorded state for this course.
5673
                    while ($row = Database::fetch_array($result)) {
5674
                        $is_courseMember = true;
5675
                        $is_courseTutor = false;
5676
                        $is_courseAdmin = false;
5677
                        $is_sessionAdmin = false;
5678
                    }
5679
                }
5680
            }
5681
        }
5682
    }
5683
5684
    switch ($visibility) {
5685
        case COURSE_VISIBILITY_OPEN_WORLD:
5686
            return true;
5687
        case COURSE_VISIBILITY_OPEN_PLATFORM:
5688
            return isset($userid);
5689
        case COURSE_VISIBILITY_REGISTERED:
5690
        case COURSE_VISIBILITY_CLOSED:
5691
            return $is_platformAdmin || $is_courseMember || $is_courseAdmin;
5692
        case COURSE_VISIBILITY_HIDDEN:
5693
            return $is_platformAdmin;
5694
    }
5695
5696
    return false;
5697
}
5698
5699
/**
5700
 * Returns whether an element (forum, message, survey ...) belongs to a session or not
5701
 * @param String the tool of the element
5702
 * @param int the element id in database
5703
 * @param int the session_id to compare with element session id
5704
 * @return boolean true if the element is in the session, false else
5705
 */
5706
function api_is_element_in_the_session($tool, $element_id, $session_id = null) {
5707
    if (is_null($session_id)) {
5708
        $session_id = intval($_SESSION['id_session']);
5709
    }
5710
5711
    // Get information to build query depending of the tool.
5712
    switch ($tool) {
5713
        case TOOL_SURVEY :
5714
            $table_tool = Database::get_course_table(TABLE_SURVEY);
5715
            $key_field = 'survey_id';
5716
            break;
5717
        case TOOL_ANNOUNCEMENT :
5718
            $table_tool = Database::get_course_table(TABLE_ANNOUNCEMENT);
5719
            $key_field = 'id';
5720
            break;
5721
        case TOOL_AGENDA :
5722
            $table_tool = Database::get_course_table(TABLE_AGENDA);
5723
            $key_field = 'id';
5724
            break;
5725
        case TOOL_GROUP :
5726
            $table_tool = Database::get_course_table(TABLE_GROUP);
5727
            $key_field = 'id';
5728
            break;
5729
        default:
5730
            return false;
5731
    }
5732
    $course_id = api_get_course_int_id();
5733
5734
    $sql = "SELECT session_id FROM $table_tool WHERE c_id = $course_id AND $key_field =  ".intval($element_id);
5735
    $rs = Database::query($sql);
5736
    if ($element_session_id = Database::result($rs, 0, 0)) {
5737
        if ($element_session_id == intval($session_id)) {
5738
            // The element belongs to the session.
5739
            return true;
5740
        }
5741
    }
5742
    return false;
5743
}
5744
5745
/**
5746
 * Replaces "forbidden" characters in a filename string.
5747
 *
5748
 * @param string $filename
5749
 * @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...
5750
 * @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...
5751
 *
5752
 * @return string
5753
 */
5754
function api_replace_dangerous_char($filename)
5755
{
5756
    return URLify::filter($filename, 250, '', true);
5757
5758
    /*
5759
    // Safe replacements for some non-letter characters.
5760
    static $search  = array(',', "\0", ' ', "\t", "\n", "\r", "\x0B", '/', "\\", '"', "'", '?', '*', '>', '<', '|', ':', '$', '(', ')', '^', '[', ']', '#', '+', '&', '%');
5761
    static $replace = array('_', '', '_', '_', '_', '_', '_', '-', '-', '-', '_', '-', '-', '-', '-', '-', '-', '-', '-', '-', '-', '-', '-', '-', '-', '-', '-');
5762
5763
    // Encoding detection.
5764
    $encoding = api_detect_encoding($filename);
5765
    // Converting html-entities into encoded characters.
5766
    $filename = api_html_entity_decode($filename, ENT_QUOTES, $encoding);
5767
    // Transliteration to ASCII letters, they are not dangerous for filesystems.
5768
    $filename = api_transliterate($filename, 'x', $encoding);
5769
5770
    // Trimming leading/trailing whitespace.
5771
    $filename = trim($filename);
5772
    // Trimming any leading/trailing dots.
5773
    $filename = trim($filename, '.');
5774
    $filename = trim($filename);
5775
5776
    // Replacing remaining dangerous non-letter characters.
5777
    $filename = str_replace($search, $replace, $filename);
5778
    if ($strict == 'strict') {
5779
        //$filename = str_replace('-', '_', $filename); // See task #1848.
5780
        //$filename = preg_replace('/[^0-9A-Za-z_.\-]/', '', $filename);
5781
        //Removing "_" character see BT#3628
5782
        $filename = preg_replace('/[^0-9A-Za-z.\-_]/', '', $filename);
5783
    }
5784
5785
    // Length is to be limited, so the file name to be acceptable by some operating systems.
5786
    $extension = (string)strrchr($filename, '.');
5787
    $extension_len = strlen($extension);
5788
    if ($extension_len > 0 && $extension_len < 250) {
5789
        $filename = substr($filename, 0, -$extension_len);
5790
        return substr($filename, 0, 250 - $extension_len).$extension;
5791
    }
5792
    return substr($filename, 0, 250);*/
5793
}
5794
5795
/**
5796
 * Fixes the $_SERVER['REQUEST_URI'] that is empty in IIS6.
5797
 * @author Ivan Tcholakov, 28-JUN-2006.
5798
 */
5799
function api_request_uri() {
5800
    if (!empty($_SERVER['REQUEST_URI'])) {
5801
        return $_SERVER['REQUEST_URI'];
5802
    }
5803
    $uri = $_SERVER['SCRIPT_NAME'];
5804
    if (!empty($_SERVER['QUERY_STRING'])) {
5805
        $uri .= '?'.$_SERVER['QUERY_STRING'];
5806
    }
5807
    $_SERVER['REQUEST_URI'] = $uri;
5808
    return $uri;
5809
}
5810
5811
5812
/** Gets the current access_url id of the Chamilo Platform
5813
 * @author Julio Montoya <[email protected]>
5814
 * @return int access_url_id of the current Chamilo Installation
5815
 */
5816
function api_get_current_access_url_id() {
5817
    $access_url_table = Database :: get_main_table(TABLE_MAIN_ACCESS_URL);
5818
    $path = Database::escape_string(api_get_path(WEB_PATH));
5819
    $sql = "SELECT id FROM $access_url_table WHERE url = '".$path."'";
5820
    $result = Database::query($sql);
5821
    if (Database::num_rows($result) > 0) {
5822
        $access_url_id = Database::result($result, 0, 0);
5823
        return $access_url_id;
5824
    }
5825
    //if the url in WEB_PATH was not found, it can only mean that there is
5826
    // either a configuration problem or the first URL has not been defined yet
5827
    // (by default it is http://localhost/). Thus the more sensible thing we can
5828
    // do is return 1 (the main URL) as the user cannot hack this value anyway
5829
    return 1;
5830
}
5831
5832
/**
5833
 * Gets the registered urls from a given user id
5834
 * @author Julio Montoya <[email protected]>
5835
 * @return int user id
5836
 */
5837
function api_get_access_url_from_user($user_id) {
5838
    $user_id = intval($user_id);
5839
    $table_url_rel_user = Database :: get_main_table(TABLE_MAIN_ACCESS_URL_REL_USER);
5840
    $table_url          = Database :: get_main_table(TABLE_MAIN_ACCESS_URL);
5841
    $sql = "SELECT access_url_id
5842
            FROM $table_url_rel_user url_rel_user
5843
            INNER JOIN $table_url u
5844
            ON (url_rel_user.access_url_id = u.id)
5845
            WHERE user_id = ".intval($user_id);
5846
    $result = Database::query($sql);
5847
    $url_list = array();
5848
    while ($row = Database::fetch_array($result, 'ASSOC')) {
5849
        $url_list[] = $row['access_url_id'];
5850
    }
5851
    return $url_list;
5852
}
5853
5854
/**
5855
 * Gets the status of a user in a course
5856
 * @param int       $user_id
5857
 * @param int    $courseId
5858
 * @return int      user status
5859
 */
5860
function api_get_status_of_user_in_course($user_id, $courseId)
5861
{
5862
    $tbl_rel_course_user = Database :: get_main_table(TABLE_MAIN_COURSE_USER);
5863
    if (!empty($user_id) && !empty($courseId)) {
5864
        $user_id        = intval($user_id);
5865
        $courseId    = intval($courseId);
5866
        $sql = 'SELECT status
5867
                FROM '.$tbl_rel_course_user.'
5868
                WHERE user_id='.$user_id.' AND c_id = '.$courseId;
5869
        $result = Database::query($sql);
5870
        $row_status = Database::fetch_array($result, 'ASSOC');
5871
        return $row_status['status'];
5872
    } else {
5873
        return 0;
5874
    }
5875
}
5876
5877
/**
5878
 * Checks whether the curent user is in a course or not.
5879
 *
5880
 * @param string        The course code - optional (takes it from session if not given)
5881
 * @return boolean
5882
 * @author Yannick Warnier <[email protected]>
5883
 */
5884
function api_is_in_course($course_code = null) {
5885 View Code Duplication
    if (isset($_SESSION['_course']['sysCode'])) {
5886
        if (!empty($course_code)) {
5887
            return $course_code == $_SESSION['_course']['sysCode'];
5888
        }
5889
        return true;
5890
    }
5891
    return false;
5892
}
5893
5894
/**
5895
 * Checks whether the curent user is in a group or not.
5896
 *
5897
 * @param string        The group id - optional (takes it from session if not given)
5898
 * @param string        The course code - optional (no additional check by course if course code is not given)
5899
 * @return boolean
5900
 * @author Ivan Tcholakov
5901
 */
5902
function api_is_in_group($group_id = null, $course_code = null) {
5903
5904 View Code Duplication
    if (!empty($course_code)) {
5905
        if (isset($_SESSION['_course']['sysCode'])) {
5906
            if ($course_code != $_SESSION['_course']['sysCode']) return false;
5907
        } else {
5908
            return false;
5909
        }
5910
    }
5911
5912 View Code Duplication
    if (isset($_SESSION['_gid']) && $_SESSION['_gid'] != '') {
5913
        if (!empty($group_id)) {
5914
            return $group_id == $_SESSION['_gid'];
5915
        } else {
5916
            return true;
5917
        }
5918
    }
5919
    return false;
5920
}
5921
5922
5923
/**
5924
 * Checks whether a secret key is valid
5925
 * @param string $original_key_secret  - secret key from (webservice) client
5926
 * @param string $security_key - security key from Chamilo
5927
 * @return boolean - true if secret key is valid, false otherwise
5928
 */
5929
function api_is_valid_secret_key($original_key_secret, $security_key) {
5930
    return $original_key_secret == sha1($security_key);
5931
}
5932
5933
/**
5934
 * Checks whether a user is into course
5935
 * @param int $course_id - the course id
5936
 * @param int $user_id - the user id
5937
 */
5938
function api_is_user_of_course($course_id, $user_id) {
5939
    $tbl_course_rel_user = Database::get_main_table(TABLE_MAIN_COURSE_USER);
5940
    $sql = 'SELECT user_id FROM '.$tbl_course_rel_user.'
5941
            WHERE
5942
                c_id ="'.intval($course_id).'" AND
5943
                user_id = "'.intval($user_id).'" AND
5944
                relation_type <> '.COURSE_RELATION_TYPE_RRHH.' ';
5945
    $result = Database::query($sql);
5946
    return Database::num_rows($result) == 1;
5947
}
5948
5949
/**
5950
 * Checks whether the server's operating system is Windows (TM).
5951
 * @return boolean - true if the operating system is Windows, false otherwise
5952
 */
5953
function api_is_windows_os() {
5954
    if (function_exists('php_uname')) {
5955
        // php_uname() exists as of PHP 4.0.2, according to the documentation.
5956
        // We expect that this function will always work for Chamilo 1.8.x.
5957
        $os = php_uname();
5958
    }
5959
    // The following methods are not needed, but let them stay, just in case.
5960
    elseif (isset($_ENV['OS'])) {
5961
        // Sometimes $_ENV['OS'] may not be present (bugs?)
5962
        $os = $_ENV['OS'];
5963
    }
5964
    elseif (defined('PHP_OS')) {
5965
        // PHP_OS means on which OS PHP was compiled, this is why
5966
        // using PHP_OS is the last choice for detection.
5967
        $os = PHP_OS;
5968
    } else {
5969
        return false;
5970
    }
5971
    return strtolower(substr((string)$os, 0, 3 )) == 'win';
5972
}
5973
5974
/**
5975
 * This function informs whether the sent request is XMLHttpRequest
5976
 */
5977
function api_is_xml_http_request() {
5978
    return isset($_SERVER['HTTP_X_REQUESTED_WITH']) && strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest';
5979
}
5980
5981
/**
5982
 * This wrapper function has been implemented for avoiding some known problems about the function getimagesize().
5983
 * @link http://php.net/manual/en/function.getimagesize.php
5984
 * @link http://www.dokeos.com/forum/viewtopic.php?t=12345
5985
 * @link http://www.dokeos.com/forum/viewtopic.php?t=16355
5986
 */
5987
function api_getimagesize($path) {
5988
    $image = new Image($path);
5989
    return $image->get_image_size();
5990
}
5991
5992
/**
5993
 * This function resizes an image, with preserving its proportions (or aspect ratio).
5994
 * @author Ivan Tcholakov, MAY-2009.
5995
 * @param int $image            System path or URL of the image
5996
 * @param int $target_width     Targeted width
5997
 * @param int $target_height    Targeted height
5998
 * @return array                Calculated new width and height
5999
 */
6000
function api_resize_image($image, $target_width, $target_height) {
6001
    $image_properties = api_getimagesize($image);
6002
    return api_calculate_image_size($image_properties['width'], $image_properties['height'], $target_width, $target_height);
6003
}
6004
6005
/**
6006
 * This function calculates new image size, with preserving image's proportions (or aspect ratio).
6007
 * @author Ivan Tcholakov, MAY-2009.
6008
 * @author The initial idea has been taken from code by Patrick Cool, MAY-2004.
6009
 * @param int $image_width      Initial width
6010
 * @param int $image_height     Initial height
6011
 * @param int $target_width     Targeted width
6012
 * @param int $target_height    Targeted height
6013
 * @return array                Calculated new width and height
6014
 */
6015
function api_calculate_image_size($image_width, $image_height, $target_width, $target_height) {
6016
    // Only maths is here.
6017
    $result = array('width' => $image_width, 'height' => $image_height);
6018
    if ($image_width <= 0 || $image_height <= 0) {
6019
        return $result;
6020
    }
6021
    $resize_factor_width = $target_width / $image_width;
6022
    $resize_factor_height = $target_height / $image_height;
6023
    $delta_width = $target_width - $image_width * $resize_factor_height;
6024
    $delta_height = $target_height - $image_height * $resize_factor_width;
6025
    if ($delta_width > $delta_height) {
6026
        $result['width'] = ceil($image_width * $resize_factor_height);
6027
        $result['height'] = ceil($image_height * $resize_factor_height);
6028
    }
6029
    elseif ($delta_width < $delta_height) {
6030
        $result['width'] = ceil($image_width * $resize_factor_width);
6031
        $result['height'] = ceil($image_height * $resize_factor_width);
6032
    }
6033
    else {
6034
        $result['width'] = ceil($target_width);
6035
        $result['height'] = ceil($target_height);
6036
    }
6037
    return $result;
6038
}
6039
6040
/**
6041
 * Returns a list of Chamilo's tools or
6042
 * checks whether a given identificator is a valid Chamilo's tool.
6043
 * @author Isaac flores paz
6044
 * @param string The tool name to filter
6045
 * @return mixed Filtered string or array
6046
 */
6047
function api_get_tools_lists($my_tool = null) {
6048
    $tools_list = array(
6049
        TOOL_DOCUMENT, TOOL_THUMBNAIL, TOOL_HOTPOTATOES,
6050
        TOOL_CALENDAR_EVENT, TOOL_LINK, TOOL_COURSE_DESCRIPTION, TOOL_SEARCH,
6051
        TOOL_LEARNPATH, TOOL_ANNOUNCEMENT, TOOL_FORUM, TOOL_THREAD, TOOL_POST,
6052
        TOOL_DROPBOX, TOOL_QUIZ, TOOL_USER, TOOL_GROUP, TOOL_BLOGS, TOOL_CHAT,
6053
        TOOL_CONFERENCE, TOOL_STUDENTPUBLICATION, TOOL_TRACKING, TOOL_HOMEPAGE_LINK,
6054
        TOOL_COURSE_SETTING, TOOL_BACKUP, TOOL_COPY_COURSE_CONTENT, TOOL_RECYCLE_COURSE,
6055
        TOOL_COURSE_HOMEPAGE, TOOL_COURSE_RIGHTS_OVERVIEW, TOOL_UPLOAD, TOOL_COURSE_MAINTENANCE,
6056
        TOOL_VISIO, TOOL_VISIO_CONFERENCE, TOOL_VISIO_CLASSROOM, TOOL_SURVEY, TOOL_WIKI,
6057
        TOOL_GLOSSARY, TOOL_GRADEBOOK, TOOL_NOTEBOOK, TOOL_ATTENDANCE, TOOL_COURSE_PROGRESS
6058
    );
6059
    if (empty($my_tool)) {
6060
        return $tools_list;
6061
    }
6062
    return in_array($my_tool, $tools_list) ? $my_tool : '';
6063
}
6064
6065
/**
6066
 * Checks whether we already approved the last version term and condition
6067
 * @param int user id
6068
 * @return bool true if we pass false otherwise
6069
 */
6070
function api_check_term_condition($user_id)
6071
{
6072
    if (api_get_setting('allow_terms_conditions') == 'true') {
6073
        //check if exists terms and conditions
6074
        if (LegalManager::count() == 0) {
6075
            return true;
6076
        }
6077
6078
        $extraFieldValue = new ExtraFieldValue('user');
6079
        $data = $extraFieldValue->get_values_by_handler_and_field_variable(
6080
            $user_id,
6081
            'legal_accept'
6082
        );
6083
6084
        if (!empty($data) && isset($data['value'])) {
6085
            $rowv = $data['value'];
6086
            $user_conditions = explode(':', $rowv);
6087
            $version = $user_conditions[0];
6088
            $lang_id = $user_conditions[1];
6089
            $real_version = LegalManager::get_last_version($lang_id);
6090
6091
            return $version >= $real_version;
6092
        }
6093
        return false;
6094
    }
6095
    return false;
6096
}
6097
6098
/**
6099
 * Gets all information of a tool into course
6100
 * @param int The tool id
6101
 * @return array
6102
 */
6103
function api_get_tool_information($tool_id) {
6104
    $t_tool = Database::get_course_table(TABLE_TOOL_LIST);
6105
    $course_id = api_get_course_int_id();
6106
    $sql = "SELECT * FROM $t_tool WHERE c_id = $course_id AND id = ".intval($tool_id);
6107
    $rs  = Database::query($sql);
6108
    return Database::fetch_array($rs);
6109
}
6110
6111
/**
6112
 * Gets all information of a tool into course
6113
 * @param int The tool id
6114
 * @return array
6115
 */
6116
function api_get_tool_information_by_name($name) {
6117
    $t_tool = Database::get_course_table(TABLE_TOOL_LIST);
6118
    $course_id = api_get_course_int_id();
6119
    $sql = "SELECT * FROM $t_tool
6120
            WHERE c_id = $course_id  AND name = '".Database::escape_string($name)."' ";
6121
    $rs  = Database::query($sql);
6122
    return Database::fetch_array($rs, 'ASSOC');
6123
}
6124
6125
/**
6126
 * @deprecated use api_trunc_str() instead.
6127
 */
6128
function shorten($input, $length = 15, $encoding = null) {
6129
    $length = intval($length);
6130
    if (!$length) {
6131
        $length = 15;
6132
    }
6133
    return api_trunc_str($input, $length, '...', false, $encoding);
6134
}
6135
6136
6137
/**
6138
 * Function used to protect a "global" admin script.
6139
 * The function blocks access when the user has no global platform admin rights.
6140
 * Global admins are the admins that are registered in the main.admin table
6141
 * AND the users who have access to the "principal" portal.
6142
 * That means that there is a record in the main.access_url_rel_user table
6143
 * with his user id and the access_url_id=1
6144
 *
6145
 * @author Julio Montoya
6146
 */
6147
function api_is_global_platform_admin($user_id = null)
6148
{
6149
    $user_id = intval($user_id);
6150
    if (empty($user_id)) {
6151
        $user_id = api_get_user_id();
6152
    }
6153
    if (api_is_platform_admin_by_id($user_id)) {
6154
        $urlList = api_get_access_url_from_user($user_id);
6155
        // The admin is registered in the first "main" site with access_url_id = 1
6156
        if (in_array(1, $urlList)) {
6157
            return true;
6158
        } else {
6159
            return false;
6160
        }
6161
    }
6162
    return false;
6163
}
6164
6165
/**
6166
 * @param int $admin_id_to_check
6167
 * @param int  $my_user_id
6168
 * @param bool $allow_session_admin
6169
 * @return bool
6170
 */
6171
function api_global_admin_can_edit_admin($admin_id_to_check, $my_user_id = null, $allow_session_admin = false)
6172
{
6173
    if (empty($my_user_id)) {
6174
        $my_user_id = api_get_user_id();
6175
    }
6176
6177
    $iam_a_global_admin = api_is_global_platform_admin($my_user_id);
6178
    $user_is_global_admin = api_is_global_platform_admin($admin_id_to_check);
6179
6180
    if ($iam_a_global_admin) {
6181
        // Global admin can edit everything
6182
        return true;
6183
    } else {
6184
        // If i'm a simple admin
6185
        $is_platform_admin = api_is_platform_admin_by_id($my_user_id);
6186
6187
        if ($allow_session_admin) {
6188
            $is_platform_admin = api_is_platform_admin_by_id($my_user_id) || (api_get_user_status($my_user_id) == SESSIONADMIN);
6189
        }
6190
6191
        if ($is_platform_admin) {
6192
            if ($user_is_global_admin) {
6193
                return false;
6194
            } else {
6195
                return true;
6196
            }
6197
        } else {
6198
            return false;
6199
        }
6200
    }
6201
}
6202
6203
/**
6204
 * @param int $admin_id_to_check
6205
 * @param int  $my_user_id
6206
 * @param bool $allow_session_admin
6207
 * @return bool
6208
 */
6209
function api_protect_super_admin($admin_id_to_check, $my_user_id = null, $allow_session_admin = false)
6210
{
6211
    if (api_global_admin_can_edit_admin($admin_id_to_check, $my_user_id, $allow_session_admin)) {
6212
        return true;
6213
    } else {
6214
        api_not_allowed();
6215
    }
6216
}
6217
6218
/**
6219
 * Function used to protect a global admin script.
6220
 * The function blocks access when the user has no global platform admin rights.
6221
 * See also the api_is_global_platform_admin() function wich defines who's a "global" admin
6222
 *
6223
 * @author Julio Montoya
6224
 */
6225
function api_protect_global_admin_script() {
6226
    if (!api_is_global_platform_admin()) {
6227
        api_not_allowed();
6228
        return false;
6229
    }
6230
    return true;
6231
}
6232
6233
/**
6234
 * Get active template
6235
 * @param string    theme type (optional: default)
6236
 * @param string    path absolute(abs) or relative(rel) (optional:rel)
6237
 * @return string   actived template path
6238
 */
6239
function api_get_template($path_type = 'rel') {
6240
    $path_types = array('rel', 'abs');
6241
    $template_path = '';
6242
    if (in_array($path_type, $path_types)) {
6243
        if ($path_type == 'rel') {
6244
            $template_path = api_get_path(SYS_TEMPLATE_PATH);
6245
        } else {
6246
            $template_path = api_get_path(WEB_TEMPLATE_PATH);
6247
        }
6248
    }
6249
    $actived_theme = 'default';
6250
    if (api_get_setting('active_template')) {
6251
        $actived_theme = api_get_setting('active_template');
6252
    }
6253
    $actived_theme_path = $template_path.$actived_theme.DIRECTORY_SEPARATOR;
6254
    return $actived_theme_path;
6255
}
6256
6257
/**
6258
 * Check browser support for type files
6259
 * This function check if the users browser support a file format or
6260
 * return the current browser and major ver when $format=check_browser
6261
 * @param string $format
6262
 *
6263
 * @return bool, or return text array if $format=check_browser
6264
 * @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...
6265
 */
6266
6267
function api_browser_support($format = "")
6268
{
6269
    $browser = new Browser();
6270
    $current_browser = $browser->getBrowser();
6271
    $a_versiontemp = explode('.', $browser->getVersion());
6272
    $current_majorver = $a_versiontemp[0];
6273
6274
    // Native svg support
6275
    if ($format == 'svg') {
6276
        if (($current_browser == 'Internet Explorer' && $current_majorver >= 9) ||
6277
            ($current_browser == 'Firefox' && $current_majorver > 1) ||
6278
            ($current_browser == 'Safari' && $current_majorver >= 4) ||
6279
            ($current_browser == 'Chrome' && $current_majorver >= 1) ||
6280
            ($current_browser == 'Opera' && $current_majorver >= 9)
6281
        ) {
6282
            return true;
6283
        } else {
6284
            return false;
6285
        }
6286
    } elseif ($format == 'pdf') {
6287
        //native pdf support
6288
        if ($current_browser == 'Chrome' && $current_majorver >= 6) {
6289
            return true;
6290
        } else {
6291
            return false;
6292
        }
6293
    } elseif ($format == 'tif' || $format == 'tiff') {
6294
        //native tif support
6295
        if ($current_browser == 'Safari' && $current_majorver >= 5) {
6296
            return true;
6297
        } else {
6298
            return false;
6299
        }
6300 View Code Duplication
    } elseif ($format == 'ogg' || $format == 'ogx' || $format == 'ogv' || $format == 'oga') {
6301
        //native ogg, ogv,oga support
6302
        if (($current_browser == 'Firefox' && $current_majorver >= 3) ||
6303
            ($current_browser == 'Chrome' && $current_majorver >= 3) ||
6304
            ($current_browser == 'Opera' && $current_majorver >= 9)) {
6305
            return true;
6306
        } else {
6307
            return false;
6308
        }
6309
    } elseif ($format == 'mpg' || $format == 'mpeg') {
6310
        //native mpg support
6311
        if (($current_browser == 'Safari' && $current_majorver >= 5)) {
6312
            return true;
6313
        } else {
6314
            return false;
6315
        }
6316
    } elseif ($format == 'mp4') {
6317
        //native mp4 support (TODO: Android, iPhone)
6318
        if ($current_browser == 'Android' || $current_browser == 'iPhone') {
6319
            return true;
6320
        } else {
6321
            return false;
6322
        }
6323
    } elseif ($format == 'mov') {
6324
        //native mov support( TODO:check iPhone)
6325
        if ($current_browser == 'Safari' && $current_majorver >= 5 || $current_browser == 'iPhone') {
6326
            return true;
6327
        } else {
6328
            return false;
6329
        }
6330
    } elseif ($format == 'avi') {
6331
        //native avi support
6332
        if ($current_browser == 'Safari' && $current_majorver >= 5) {
6333
            return true;
6334
        } else {
6335
            return false;
6336
        }
6337
    } elseif ($format == 'wmv') {
6338
        //native wmv support
6339
        if ($current_browser == 'Firefox' && $current_majorver >= 4) {
6340
            return true;
6341
        } else {
6342
            return false;
6343
        }
6344 View Code Duplication
    } elseif ($format == 'webm') {
6345
        //native webm support (TODO:check IE9, Chrome9, Android)
6346
        if (($current_browser == 'Firefox' && $current_majorver >= 4) ||
6347
            ($current_browser == 'Opera' && $current_majorver >= 9) ||
6348
            ($current_browser == 'Internet Explorer' && $current_majorver >= 9) ||
6349
            ($current_browser == 'Chrome' && $current_majorver >= 9) ||
6350
            $current_browser == 'Android'
6351
        ) {
6352
            return true;
6353
        } else {
6354
            return false;
6355
        }
6356
    } elseif ($format == 'wav') {
6357
        //native wav support (only some codecs !)
6358
        if (($current_browser == 'Firefox' && $current_majorver >= 4) ||
6359
            ($current_browser == 'Safari' && $current_majorver >= 5) ||
6360
            ($current_browser == 'Opera' && $current_majorver >= 9) ||
6361
            ($current_browser == 'Internet Explorer' && $current_majorver >= 9) ||
6362
            ($current_browser == 'Chrome' && $current_majorver > 9) ||
6363
            $current_browser == 'Android' ||
6364
            $current_browser == 'iPhone'
6365
        ) {
6366
            return true;
6367
        } else {
6368
            return false;
6369
        }
6370
    } elseif ($format == 'mid' || $format == 'kar') {
6371
        //native midi support (TODO:check Android)
6372
        if ($current_browser == 'Opera' && $current_majorver >= 9 || $current_browser == 'Android') {
6373
            return true;
6374
        } else {
6375
            return false;
6376
        }
6377
    } elseif ($format == 'wma') {
6378
        //native wma support
6379
        if ($current_browser == 'Firefox' && $current_majorver >= 4) {
6380
            return true;
6381
        } else {
6382
            return false;
6383
        }
6384
    } elseif ($format == 'au') {
6385
        //native au support
6386
        if ($current_browser == 'Safari' && $current_majorver >= 5) {
6387
            return true;
6388
        } else {
6389
            return false;
6390
        }
6391 View Code Duplication
    } elseif ($format == 'mp3') {
6392
        //native mp3 support (TODO:check Android, iPhone)
6393
        if (($current_browser == 'Safari' && $current_majorver >= 5) ||
6394
            ($current_browser == 'Chrome' && $current_majorver >= 6) ||
6395
            ($current_browser == 'Internet Explorer' && $current_majorver >= 9) ||
6396
            $current_browser == 'Android' ||
6397
            $current_browser == 'iPhone' ||
6398
            $current_browser == 'Firefox'
6399
        ) {
6400
            return true;
6401
        } else {
6402
            return false;
6403
        }
6404
    } elseif ($format == "check_browser") {
6405
        $array_check_browser = array($current_browser, $current_majorver);
6406
        return $array_check_browser;
6407
    } else {
6408
        return false;
6409
    }
6410
}
6411
6412
/**
6413
 * This function checks if exist path and file browscap.ini
6414
 * In order for this to work, your browscap configuration setting in php.ini
6415
 * must point to the correct location of the browscap.ini file on your system
6416
 * http://php.net/manual/en/function.get-browser.php
6417
 *
6418
 * @return bool
6419
 *
6420
 * @author Juan Carlos Raña Trabado
6421
 */
6422
function api_check_browscap() {
6423
    $setting = ini_get('browscap');
6424
    if ($setting) {
6425
        $browser = get_browser($_SERVER['HTTP_USER_AGENT'], true);
6426
        if (strpos($setting, 'browscap.ini') && !empty($browser)) {
6427
            return true;
6428
        }
6429
    }
6430
    return false;
6431
}
6432
6433
/**
6434
 * Returns the <script> HTML tag
6435
 */
6436
function api_get_js($file) {
6437
    return '<script type="text/javascript" src="'.api_get_path(WEB_LIBRARY_PATH).'javascript/'.$file.'"></script>'."\n";
6438
}
6439
6440
/**
6441
 * Returns the <script> HTML tag
6442
 */
6443
function api_get_asset($file) {
6444
    return '<script type="text/javascript" src="'.api_get_path(WEB_PATH).'web/assets/'.$file.'"></script>'."\n";
6445
}
6446
6447
/**
6448
 * Returns the <link> HTML tag
6449
 */
6450
function api_get_css($file, $media = 'screen') {
6451
    return '<link href="'.$file.'" rel="stylesheet" media="'.$media.'" type="text/css" />'."\n";
6452
}
6453
6454
/**
6455
 * Returns the js header to include the jquery library
6456
 */
6457
function api_get_jquery_js()
6458
{
6459
    return api_get_asset('jquery/dist/jquery.min.js');
6460
}
6461
6462
/**
6463
 * Returns the jquery path
6464
 * @return string
6465
 */
6466
function api_get_jquery_web_path()
6467
{
6468
    return api_get_path(WEB_PATH).'web/assets/jquery/dist/jquery.min.js';
6469
}
6470
6471
/**
6472
 * @return string
6473
 */
6474
function api_get_jquery_ui_js_web_path()
6475
{
6476
    return api_get_path(WEB_PATH).'web/assets/jquery-ui/jquery-ui.min.js';
6477
}
6478
6479
/**
6480
 * @return string
6481
 */
6482
function api_get_jquery_ui_css_web_path()
6483
{
6484
    return api_get_path(WEB_PATH).'web/assets/jquery-ui/themes/smoothness/jquery-ui.min.css';
6485
}
6486
6487
/**
6488
 * Returns the jquery-ui library js headers
6489
 * @param   bool    add the jqgrid library
6490
 * @return  string  html tags
6491
 *
6492
 */
6493
function api_get_jquery_ui_js($include_jqgrid = false) {
6494
    $libraries = array();
6495
    if ($include_jqgrid) {
6496
       $libraries[]='jqgrid';
6497
    }
6498
    return api_get_jquery_libraries_js($libraries);
6499
}
6500
6501
function api_get_jqgrid_js() {
6502
    return api_get_jquery_libraries_js(array('jqgrid'));
6503
}
6504
6505
6506
/**
6507
 * Returns the jquery library js and css headers
6508
 *
6509
 * @param   array   list of jquery libraries supported jquery-ui, jqgrid
6510
 * @param   bool    add the jquery library
6511
 * @return  string  html tags
6512
 *
6513
 */
6514
function api_get_jquery_libraries_js($libraries) {
6515
    $js = '';
6516
    $js_path = api_get_path(WEB_LIBRARY_PATH).'javascript/';
6517
6518
    //jqgrid js and css
6519
    if (in_array('jqgrid', $libraries)) {
6520
        $languaje   = 'en';
6521
        $platform_isocode = strtolower(api_get_language_isocode());
6522
6523
        //languages supported by jqgrid see files in main/inc/lib/javascript/jqgrid/js/i18n
6524
        $jqgrid_langs = array(
6525
            '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'
6526
        );
6527
6528
        if (in_array($platform_isocode, $jqgrid_langs)) {
6529
            $languaje = $platform_isocode;
6530
        }
6531
        //$js .= '<link rel="stylesheet" href="'.$js_path.'jqgrid/css/ui.jqgrid.css" type="text/css">';
6532
        $js .= api_get_css($js_path.'jqgrid/css/ui.jqgrid.css');
6533
        $js .= api_get_js('jqgrid/js/i18n/grid.locale-'.$languaje.'.js');
6534
        $js .= api_get_js('jqgrid/js/jquery.jqGrid.min.js');
6535
    }
6536
6537
    //Document multiple upload funcionality
6538
    if (in_array('jquery-upload', $libraries)) {
6539
6540
        $js .= api_get_asset('blueimp-load-image/js/load-image.all.min.js');
6541
        $js .= api_get_asset('blueimp-canvas-to-blob/js/canvas-to-blob.min.js');
6542
        $js .= api_get_asset('jquery-file-upload/js/jquery.iframe-transport.js');
6543
        $js .= api_get_asset('jquery-file-upload/js/jquery.fileupload.js');
6544
        $js .= api_get_asset('jquery-file-upload/js/jquery.fileupload-process.js');
6545
        $js .= api_get_asset('jquery-file-upload/js/jquery.fileupload-image.js');
6546
        $js .= api_get_asset('jquery-file-upload/js/jquery.fileupload-audio.js');
6547
        $js .= api_get_asset('jquery-file-upload/js/jquery.fileupload-video.js');
6548
        $js .= api_get_asset('jquery-file-upload/js/jquery.fileupload-validate.js');
6549
6550
        $js .= api_get_css(api_get_path(WEB_PATH).'web/assets/jquery-file-upload/css/jquery.fileupload.css');
6551
        $js .= api_get_css(api_get_path(WEB_PATH).'web/assets/jquery-file-upload/css/jquery.fileupload-ui.css');
6552
    }
6553
6554
    // jquery datepicker
6555
    if (in_array('datepicker', $libraries)) {
6556
        $languaje   = 'en-GB';
6557
        $platform_isocode = strtolower(api_get_language_isocode());
6558
6559
        // languages supported by jqgrid see files in main/inc/lib/javascript/jqgrid/js/i18n
6560
        $datapicker_langs = array(
6561
            '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'
6562
        );
6563
        if (in_array($platform_isocode, $datapicker_langs)) {
6564
            $languaje = $platform_isocode;
6565
        }
6566
6567
        $js .= api_get_js('jquery-ui/jquery-ui-i18n.min.js');
6568
        $script = '<script>
6569
        $(function(){
6570
            $.datepicker.setDefaults($.datepicker.regional["'.$languaje.'"]);
6571
            $.datepicker.regional["local"] = $.datepicker.regional["'.$languaje.'"];
6572
        });
6573
        </script>
6574
        ';
6575
        $js .= $script;
6576
    }
6577
    return $js;
6578
}
6579
6580
/**
6581
 * Returns the course's URL
6582
 *
6583
 * This function relies on api_get_course_info()
6584
 * @param   string  The course code - optional (takes it from session if not given)
6585
 * @param   int     The session id  - optional (takes it from session if not given)
6586
 * @return  mixed   The URL of the course or null if something does not work
6587
 * @author  Julio Montoya <[email protected]>
6588
 */
6589
function api_get_course_url($course_code = null, $session_id = null)
6590
{
6591
    if (empty($course_code)) {
6592
        $course_info = api_get_course_info();
6593
    } else {
6594
        $course_info = api_get_course_info($course_code);
6595
    }
6596
    if (empty($session_id)) {
6597
        $session_url = '?id_session='.api_get_session_id();
6598
    } else {
6599
        $session_url = '?id_session='.intval($session_id);
6600
    }
6601
    /*
6602
    if (empty($group_id)) {
6603
        $group_url = '&gidReq='.api_get_group_id();
6604
    } else {
6605
        $group_url = '&gidReq='.intval($group_id);
6606
    }*/
6607
    if (!empty($course_info['path'])) {
6608
        return api_get_path(WEB_COURSE_PATH).$course_info['path'].'/index.php'.$session_url;
6609
    }
6610
    return null;
6611
}
6612
6613
/**
6614
 *
6615
 * Check if the current portal has the $_configuration['multiple_access_urls'] parameter on
6616
 * @return bool true if multi site is enabled
6617
 *
6618
 * */
6619
function api_get_multiple_access_url() {
6620
    global $_configuration;
6621
    if (isset($_configuration['multiple_access_urls']) && $_configuration['multiple_access_urls']) {
6622
        return true;
6623
    }
6624
    return false;
6625
}
6626
6627
/**
6628
 * @return bool
6629
 */
6630
function api_is_multiple_url_enabled() {
6631
    return api_get_multiple_access_url();
6632
}
6633
6634
/**
6635
 * Returns a md5 unique id
6636
 * @todo add more parameters
6637
 */
6638
function api_get_unique_id() {
6639
    $id = md5(time().uniqid().api_get_user_id().api_get_course_id().api_get_session_id());
6640
    return $id;
6641
}
6642
6643
/**
6644
 * Get home path
6645
 * @return string
6646
 */
6647
function api_get_home_path()
6648
{
6649
    $home = 'app/home/';
6650
    if (api_get_multiple_access_url()) {
6651
        $access_url_id = api_get_current_access_url_id();
6652
        $url_info = api_get_access_url($access_url_id);
6653
        $url = api_remove_trailing_slash(preg_replace('/https?:\/\//i', '', $url_info['url']));
6654
        $clean_url = api_replace_dangerous_char($url);
6655
        $clean_url = str_replace('/', '-', $clean_url);
6656
        $clean_url .= '/';
6657
6658
        $home = 'app/home/' . $clean_url;
6659
    }
6660
6661
    return $home;
6662
}
6663
6664
/**
6665
 *
6666
 * @param int Course id
6667
 * @param int tool id: TOOL_QUIZ, TOOL_FORUM, TOOL_STUDENTPUBLICATION, TOOL_LEARNPATH
6668
 * @param int the item id (tool id, exercise id, lp id)
6669
 *
6670
 */
6671
function api_resource_is_locked_by_gradebook($item_id, $link_type, $course_code = null) {
6672
    if (api_is_platform_admin()) {
6673
        return false;
6674
    }
6675
    if (api_get_setting('gradebook_locking_enabled') == 'true') {
6676
        if (empty($course_code)) {
6677
            $course_code = api_get_course_id();
6678
        }
6679
        $table = Database::get_main_table(TABLE_MAIN_GRADEBOOK_LINK);
6680
        $item_id = intval($item_id);
6681
        $link_type = intval($link_type);
6682
        $course_code = Database::escape_string($course_code);
6683
        $sql = "SELECT locked FROM $table
6684
                WHERE locked = 1 AND ref_id = $item_id AND type = $link_type AND course_code = '$course_code' ";
6685
        $result = Database::query($sql);
6686
        if (Database::num_rows($result)) {
6687
            return true;
6688
        }
6689
    }
6690
    return false;
6691
}
6692
6693
/**
6694
 * Blocks a page if the item was added in a gradebook
6695
 *
6696
 * @param int       exercise id, work id, thread id,
6697
 * @param int       LINK_EXERCISE, LINK_STUDENTPUBLICATION, LINK_LEARNPATH LINK_FORUM_THREAD, LINK_ATTENDANCE
6698
 * see gradebook/lib/be/linkfactory
6699
 * @param string    course code
6700
 * @return boolean
6701
 */
6702
function api_block_course_item_locked_by_gradebook($item_id, $link_type, $course_code = null) {
6703
    if (api_is_platform_admin()) {
6704
        return false;
6705
    }
6706
6707
    if (api_resource_is_locked_by_gradebook($item_id, $link_type, $course_code)) {
6708
        $message = Display::return_message(get_lang('ResourceLockedByGradebook'), 'warning');
6709
        api_not_allowed(true, $message);
6710
    }
6711
}
6712
/**
6713
 * Checks the PHP version installed is enough to run Chamilo
6714
 * @param string Include path (used to load the error page)
6715
 * @return void
6716
 */
6717
function api_check_php_version($my_inc_path = null) {
6718
    if (!function_exists('version_compare') || version_compare( phpversion(), REQUIRED_PHP_VERSION, '<')) {
6719
        $global_error_code = 1;
6720
        // Incorrect PHP version
6721
        $global_page = $my_inc_path.'global_error_message.inc.php';
6722
        if (file_exists($global_page)) {
6723
            require $global_page;
6724
        }
6725
        exit;
6726
    }
6727
}
6728
/**
6729
 * Checks whether the Archive directory is present and writeable. If not,
6730
 * prints a warning message.
6731
 */
6732
function api_check_archive_dir() {
6733 View Code Duplication
    if (is_dir(api_get_path(SYS_ARCHIVE_PATH)) && !is_writable(api_get_path(SYS_ARCHIVE_PATH))) {
6734
        $message = Display::return_message(get_lang('ArchivesDirectoryNotWriteableContactAdmin'),'warning');
6735
        api_not_allowed(true, $message);
6736
    }
6737
}
6738
/**
6739
 * Returns an array of global configuration settings which should be ignored
6740
 * when printing the configuration settings screens
6741
 * @return array Array of strings, each identifying one of the excluded settings
6742
 */
6743
function api_get_locked_settings() {
6744
    return array(
6745
        'server_type',
6746
        'permanently_remove_deleted_files',
6747
        'account_valid_duration',
6748
        'service_visio',
6749
        'service_ppt2lp',
6750
        'wcag_anysurfer_public_pages',
6751
        'upload_extensions_list_type',
6752
        'upload_extensions_blacklist',
6753
        'upload_extensions_whitelist',
6754
        'upload_extensions_skip',
6755
        'upload_extensions_replace_by',
6756
        'hide_dltt_markup',
6757
        'split_users_upload_directory',
6758
        'permissions_for_new_directories',
6759
        'permissions_for_new_files',
6760
        'platform_charset',
6761
        'service_visio',
6762
        'ldap_description',
6763
        'cas_activate',
6764
        'cas_server',
6765
        'cas_server_uri',
6766
        'cas_port',
6767
        'cas_protocol',
6768
        'cas_add_user_activate',
6769
        'update_user_info_cas_with_ldap',
6770
        'languagePriority1',
6771
        'languagePriority2',
6772
        'languagePriority3',
6773
        'languagePriority4',
6774
        'login_is_email',
6775
        'chamilo_database_version'
6776
    );
6777
}
6778
6779
/**
6780
 * Checks if the user is corrently logged in. Returns the user ID if he is, or
6781
 * false if he isn't. If the user ID is given and is an integer, then the same
6782
 * ID is simply returned
6783
 * @param  integer User ID
6784
 * @return mixed Integer User ID is logged in, or false otherwise
6785
 */
6786
function api_user_is_login($user_id = null) {
6787
    $user_id = empty($user_id) ? api_get_user_id() : intval($user_id);
6788
    return $user_id && !api_is_anonymous();
6789
}
6790
6791
/**
6792
 * Guess the real ip for register in the database, even in reverse proxy cases.
6793
 * To be recognized, the IP has to be found in either $_SERVER['REMOTE_ADDR'] or
6794
 * in $_SERVER['HTTP_X_FORWARDED_FOR'], which is in common use with rproxies.
6795
 * @return string the user's real ip (unsafe - escape it before inserting to db)
6796
 * @author Jorge Frisancho Jibaja <[email protected]>, USIL - Some changes to allow the use of real IP using reverse proxy
6797
 * @version CEV CHANGE 24APR2012
6798
 */
6799
function api_get_real_ip(){
6800
    // Guess the IP if behind a reverse proxy
6801
    global $debug;
6802
    $ip = trim($_SERVER['REMOTE_ADDR']);
6803
    if (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) {
6804
        if (preg_match('/,/', $_SERVER['HTTP_X_FORWARDED_FOR'])) {
6805
            @list($ip1, $ip2) = @explode(',', $_SERVER['HTTP_X_FORWARDED_FOR']);
6806
        } else {
6807
            $ip1 = $_SERVER['HTTP_X_FORWARDED_FOR'];
6808
        }
6809
        $ip = trim($ip1);
6810
    }
6811
    if (!empty($debug)) error_log('Real IP: '.$ip);
6812
    return $ip;
6813
}
6814
6815
/**
6816
 * Checks whether an IP is included inside an IP range
6817
 * @param string IP address
6818
 * @param string IP range
6819
 * @return bool True if IP is in the range, false otherwise
6820
 * @author claudiu at cnixs dot com  on http://www.php.net/manual/fr/ref.network.php#55230
6821
 * @author Yannick Warnier for improvements and managment of multiple ranges
6822
 * @todo check for IPv6 support
6823
 */
6824
function api_check_ip_in_range($ip,$range)
6825
{
6826
    if (empty($ip) or empty($range)) {
6827
        return false;
6828
    }
6829
    $ip_ip = ip2long ($ip);
6830
    // divide range param into array of elements
6831
    if (strpos($range,',')!==false) {
6832
        $ranges = explode(',',$range);
6833
    } else {
6834
        $ranges = array($range);
6835
    }
6836
    foreach ($ranges as $range) {
6837
        $range = trim($range);
6838
        if (empty($range)) { continue; }
6839
        if (strpos($range,'/')===false) {
6840
            if (strcmp($ip,$range)===0) {
6841
                return true; // there is a direct IP match, return OK
6842
            }
6843
            continue; //otherwise, get to the next range
6844
        }
6845
        // the range contains a "/", so analyse completely
6846
        list ($net, $mask) = explode("/", $range);
6847
6848
        $ip_net = ip2long ($net);
6849
        // mask binary magic
6850
        $ip_mask = ~((1 << (32 - $mask)) - 1);
6851
6852
        $ip_ip_net = $ip_ip & $ip_mask;
6853
        if ($ip_ip_net == $ip_net) {
6854
            return true;
6855
        }
6856
    }
6857
6858
    return false;
6859
}
6860
6861
function api_check_user_access_to_legal($course_visibility) {
6862
    $course_visibility_list = array(COURSE_VISIBILITY_OPEN_WORLD, COURSE_VISIBILITY_OPEN_PLATFORM);
6863
    return in_array($course_visibility, $course_visibility_list) || api_is_drh();
6864
}
6865
6866
/**
6867
 * Checks if the global chat is enabled or not
6868
 *
6869
 * @return bool
6870
 */
6871
function api_is_global_chat_enabled()
6872
{
6873
    return
6874
        !api_is_anonymous() &&
6875
        api_get_setting('allow_global_chat') == 'true' &&
6876
        api_get_setting('allow_social_tool') == 'true';
6877
}
6878
6879
/**
6880
 * @todo Fix tool_visible_by_default_at_creation labels
6881
 * @todo Add sessionId parameter to avoid using context
6882
 *
6883
 * @param int $item_id
6884
 * @param int $tool_id
6885
 * @param int $group_id
6886
 * @param array $courseInfo
6887
 */
6888
function api_set_default_visibility($item_id, $tool_id, $group_id = 0, $courseInfo = array(), $sessionId = 0, $userId = 0)
6889
{
6890
    $courseInfo = empty($courseInfo) ? api_get_course_info() : $courseInfo;
6891
    $courseId = $courseInfo['real_id'];
6892
    $courseCode = $courseInfo['code'];
6893
    $sessionId = empty($sessionId) ? api_get_session_id() : $sessionId;
6894
    $userId = empty($userId) ? api_get_user_id() : $userId;
6895
6896
    $original_tool_id = $tool_id;
6897
6898
    switch ($tool_id) {
6899
        case TOOL_LINK:
6900
        case TOOL_LINK_CATEGORY:
6901
            $tool_id = 'links';
6902
            break;
6903
        case TOOL_DOCUMENT:
6904
            $tool_id = 'documents';
6905
            break;
6906
        case TOOL_LEARNPATH:
6907
            $tool_id = 'learning';
6908
            break;
6909
        case TOOL_ANNOUNCEMENT:
6910
            $tool_id = 'announcements';
6911
            break;
6912
        case TOOL_FORUM:
6913
        case TOOL_FORUM_CATEGORY:
6914
        case TOOL_FORUM_THREAD:
6915
            $tool_id = 'forums';
6916
            break;
6917
        case TOOL_QUIZ:
6918
            $tool_id = 'quiz';
6919
            break;
6920
    }
6921
    $setting = api_get_setting('tool_visible_by_default_at_creation');
6922
6923
    if (isset($setting[$tool_id])) {
6924
        $visibility = 'invisible';
6925
        if ($setting[$tool_id] == 'true') {
6926
            $visibility = 'visible';
6927
        }
6928
6929
        if (empty($group_id)) {
6930
            $group_id = api_get_group_id();
6931
        }
6932
6933
        // Read the portal and course default visibility
6934
        if ($tool_id == 'documents') {
6935
            $visibility = DocumentManager::getDocumentDefaultVisibility($courseCode);
6936
        }
6937
6938
        api_item_property_update(
6939
            $courseInfo,
6940
            $original_tool_id,
6941
            $item_id,
6942
            $visibility,
6943
            $userId,
6944
            $group_id,
6945
            null,
6946
            null,
6947
            null,
6948
            api_get_session_id()
6949
        );
6950
6951
        // Fixes default visibility for tests
6952
6953
        switch ($original_tool_id) {
6954
            case TOOL_QUIZ:
6955
                if (empty($sessionId)) {
6956
                    $objExerciseTmp = new Exercise($courseId);
6957
                    $objExerciseTmp->read($item_id);
6958
                    if ($visibility == 'visible') {
6959
                        $objExerciseTmp->enable();
6960
                        $objExerciseTmp->save();
6961
                    } else {
6962
                        $objExerciseTmp->disable();
6963
                        $objExerciseTmp->save();
6964
                    }
6965
                }
6966
                break;
6967
        }
6968
    }
6969
}
6970
6971
/**
6972
 * @return string
6973
 */
6974
function api_get_security_key() {
6975
    return api_get_configuration_value('security_key');
6976
}
6977
6978
/**
6979
 * @param int $user_id
6980
 * @param int $courseId
6981
 * @param int $session_id
6982
 * @return array
6983
 */
6984
function api_detect_user_roles($user_id, $courseId, $session_id = 0)
6985
{
6986
    $user_roles = array();
6987
    /*$user_info = api_get_user_info($user_id);
6988
    $user_roles[] = $user_info['status'];*/
6989
    $courseInfo = api_get_course_info_by_id($courseId);
6990
    $course_code = $courseInfo['code'];
6991
6992
    $url_id = api_get_current_access_url_id();
6993
    if (api_is_platform_admin_by_id($user_id, $url_id)) {
6994
        $user_roles[] = PLATFORM_ADMIN;
6995
    }
6996
6997
    /*if (api_is_drh()) {
6998
        $user_roles[] = DRH;
6999
    }*/
7000
7001
    if (!empty($session_id)) {
7002
        if (SessionManager::user_is_general_coach($user_id, $session_id)) {
7003
            $user_roles[] = SESSION_GENERAL_COACH;
7004
        }
7005
    }
7006
7007
    if (!empty($course_code)) {
7008
        if (empty($session_id)) {
7009
            if (CourseManager::is_course_teacher($user_id, $course_code)) {
7010
                $user_roles[] = COURSEMANAGER;
7011
            }
7012
            if (CourseManager::get_tutor_in_course_status($user_id, $course_code)) {
7013
                $user_roles[] = COURSE_TUTOR;
7014
            }
7015
7016
            if (CourseManager::is_user_subscribed_in_course($user_id, $course_code)) {
7017
                $user_roles[] = COURSE_STUDENT;
7018
            }
7019
        } else {
7020
            $user_status_in_session = SessionManager::get_user_status_in_course_session(
7021
                $user_id,
7022
                $courseId,
7023
                $session_id
7024
            );
7025
7026
            if (!empty($user_status_in_session)) {
7027
                if ($user_status_in_session == 0) {
7028
                    $user_roles[] = SESSION_STUDENT;
7029
                }
7030
                if ($user_status_in_session == 2) {
7031
                    $user_roles[] = SESSION_COURSE_COACH;
7032
                }
7033
            }
7034
7035
            /*if (api_is_course_session_coach($user_id, $course_code, $session_id)) {
7036
               $user_roles[] = SESSION_COURSE_COACH;
7037
            }*/
7038
        }
7039
    }
7040
    return $user_roles;
7041
}
7042
7043
function api_get_roles_to_string($roles) {
7044
    $role_names = array();
7045
    if (!empty($roles)) {
7046
        foreach ($roles as $role) {
7047
            $role_names[] = get_status_from_code($role);
7048
        }
7049
    }
7050
    if (!empty($role_names)) {
7051
        return implode(', ', $role_names);
7052
    }
7053
    return null;
7054
}
7055
7056
function role_actions() {
7057
    return array(
7058
        'course' => array(
7059
            'create',
7060
            'read',
7061
            'edit',
7062
            'delete'
7063
        ),
7064
        'admin' => array(
7065
            'create',
7066
            'read',
7067
            'edit',
7068
            'delete'
7069
        )
7070
    );
7071
}
7072
7073
/**
7074
 * @param int $courseId
7075
 * @param int $session_id
7076
 * @return bool
7077
 */
7078
function api_coach_can_edit_view_results($courseId = null, $session_id = null)
7079
{
7080
    $user_id = api_get_user_id();
7081
7082
    if (empty($courseId)) {
7083
        $courseId = api_get_course_int_id();
7084
    }
7085
7086
    if (empty($session_id)) {
7087
        $session_id = api_get_session_id();
7088
    }
7089
7090
    if (api_is_platform_admin()) {
7091
        return true;
7092
    }
7093
7094
    $roles = api_detect_user_roles($user_id, $courseId, $session_id);
7095
7096
    if (in_array(SESSION_COURSE_COACH, $roles)) {
7097
        //return api_get_setting('session_tutor_reports_visibility') == 'true';
7098
        return true;
7099
    } else {
7100
        if (in_array(COURSEMANAGER, $roles)) {
7101
            return true;
7102
        }
7103
        return false;
7104
    }
7105
}
7106
7107
function api_get_js_simple($file) {
7108
    return '<script type="text/javascript" src="'.$file.'"></script>'."\n";
7109
}
7110
7111
function api_set_settings_and_plugins() {
7112
    global $_configuration;
7113
    $_setting = array();
7114
    $_plugins = array();
7115
7116
    // access_url == 1 is the default chamilo location
7117
    $settings_by_access_list = array();
7118
    $access_url_id = api_get_current_access_url_id();
7119 View Code Duplication
    if ($access_url_id != 1) {
7120
        $url_info = api_get_access_url($_configuration['access_url']);
7121
        if ($url_info['active'] == 1) {
7122
            $settings_by_access = & api_get_settings(null, 'list', $_configuration['access_url'], 1);
7123
            foreach ($settings_by_access as & $row) {
7124
                if (empty($row['variable'])) {
7125
                    $row['variable'] = 0;
7126
                }
7127
                if (empty($row['subkey'])) {
7128
                    $row['subkey'] = 0;
7129
                }
7130
                if (empty($row['category'])) {
7131
                    $row['category'] = 0;
7132
                }
7133
                $settings_by_access_list[$row['variable']][$row['subkey']][$row['category']] = $row;
7134
            }
7135
        }
7136
    }
7137
7138
    $result = api_get_settings(null, 'list', 1);
7139
7140 View Code Duplication
    foreach ($result as & $row) {
7141
        if ($access_url_id != 1) {
7142
            if ($url_info['active'] == 1) {
7143
                $var = empty($row['variable']) ? 0 : $row['variable'];
7144
                $subkey = empty($row['subkey']) ? 0 : $row['subkey'];
7145
                $category = empty($row['category']) ? 0 : $row['category'];
7146
            }
7147
7148
            if ($row['access_url_changeable'] == 1 && $url_info['active'] == 1) {
7149
                if (isset($settings_by_access_list[$var]) &&
7150
                    $settings_by_access_list[$var][$subkey][$category]['selected_value'] != '') {
7151
                    if ($row['subkey'] == null) {
7152
                        $_setting[$row['variable']] = $settings_by_access_list[$var][$subkey][$category]['selected_value'];
7153
                    } else {
7154
                        $_setting[$row['variable']][$row['subkey']] = $settings_by_access_list[$var][$subkey][$category]['selected_value'];
7155
                    }
7156
                } else {
7157
                    if ($row['subkey'] == null) {
7158
                        $_setting[$row['variable']] = $row['selected_value'];
7159
                    } else {
7160
                        $_setting[$row['variable']][$row['subkey']] = $row['selected_value'];
7161
                    }
7162
                }
7163
            } else {
7164
                if ($row['subkey'] == null) {
7165
                    $_setting[$row['variable']] = $row['selected_value'];
7166
                } else {
7167
                    $_setting[$row['variable']][$row['subkey']] = $row['selected_value'];
7168
                }
7169
            }
7170
        } else {
7171
            if ($row['subkey'] == null) {
7172
                $_setting[$row['variable']] = $row['selected_value'];
7173
            } else {
7174
                $_setting[$row['variable']][$row['subkey']] = $row['selected_value'];
7175
            }
7176
        }
7177
    }
7178
7179
    $result = api_get_settings('Plugins', 'list', $access_url_id);
7180
    $_plugins = array();
7181 View Code Duplication
    foreach ($result as & $row) {
7182
        $key = & $row['variable'];
7183
        if (is_string($_setting[$key])) {
7184
            $_setting[$key] = array();
7185
        }
7186
        $_setting[$key][] = $row['selected_value'];
7187
        $_plugins[$key][] = $row['selected_value'];
7188
    }
7189
7190
    $_SESSION['_setting'] = $_setting;
7191
    $_SESSION['_plugins'] = $_plugins;
7192
}
7193
7194
function api_set_setting_last_update()
7195
{
7196
    // Saving latest refresh.
7197
    api_set_setting('settings_latest_update', api_get_utc_datetime());
7198
}
7199
7200
/**
7201
 * Tries to set memory limit, if authorized and new limit is higher than current
7202
 * @param string New memory limit
7203
 * @return bool True on success, false on failure or current is higher than suggested
7204
 * @assert (null) === false
7205
 * @assert (-1) === false
7206
 * @assert (0) === true
7207
 * @assert ('1G') === true
7208
 */
7209
function api_set_memory_limit($mem){
7210
    //if ini_set() not available, this function is useless
7211
    if (!function_exists('ini_set') || is_null($mem) || $mem == -1) {
7212
        return false;
7213
    }
7214
7215
    $memory_limit = ini_get('memory_limit');
7216
    if (api_get_bytes_memory_limit($mem) > api_get_bytes_memory_limit($memory_limit)){
7217
        ini_set('memory_limit', $mem);
7218
        return true;
7219
    }
7220
    return false;
7221
}
7222
7223
/**
7224
 * Gets memory limit in bytes
7225
 * @param string The memory size (128M, 1G, 1000K, etc)
7226
 * @return int
7227
 * @assert (null) === false
7228
 * @assert ('1t')  === 1099511627776
7229
 * @assert ('1g')  === 1073741824
7230
 * @assert ('1m')  === 1048576
7231
 * @assert ('100k') === 102400
7232
 */
7233
function api_get_bytes_memory_limit($mem){
7234
    $size = strtolower(substr($mem,-1));
7235
7236
    switch ($size) {
7237
        case 't':
7238
            $mem = intval(substr($mem,-1))*1024*1024*1024*1024;
7239
            break;
7240
        case 'g':
7241
            $mem = intval(substr($mem,0,-1))*1024*1024*1024;
7242
            break;
7243
        case 'm':
7244
            $mem = intval(substr($mem,0,-1))*1024*1024;
7245
            break;
7246
        case 'k':
7247
            $mem = intval(substr($mem,0,-1))*1024;
7248
            break;
7249
        default:
7250
            // we assume it's integer only
7251
            $mem = intval($mem);
7252
            break;
7253
    }
7254
    return $mem;
7255
}
7256
7257
/**
7258
 * Finds all the information about a user from username instead of user id
7259
 * @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...
7260
 *
7261
 * @return array $user_info user_id, lastname, firstname, username, email, ...
7262
 * @author Yannick Warnier <[email protected]>
7263
 */
7264 View Code Duplication
function api_get_user_info_from_official_code($official_code = '')
7265
{
7266
    if (empty($official_code)) {
7267
        return false;
7268
    }
7269
    $sql = "SELECT * FROM ".Database :: get_main_table(TABLE_MAIN_USER)."
7270
            WHERE official_code ='".Database::escape_string($official_code)."'";
7271
    $result = Database::query($sql);
7272
    if (Database::num_rows($result) > 0) {
7273
        $result_array = Database::fetch_array($result);
7274
        return _api_format_user($result_array);
7275
    }
7276
    return false;
7277
}
7278
7279
/**
7280
 *
7281
 * @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...
7282
 *
7283
 * @return string
7284
 */
7285
function api_get_password_checker_js($usernameInputId, $passwordInputid)
7286
{
7287
    $checkPass = api_get_setting('allow_strength_pass_checker');
7288
    $useStrengthPassChecker = $checkPass == 'true';
7289
7290
    if ($useStrengthPassChecker == false) {
7291
        return null;
7292
    }
7293
7294
    $verdicts = array(
7295
        get_lang('PasswordWeak'),
7296
        get_lang('PasswordNormal'),
7297
        get_lang('PasswordMedium'),
7298
        get_lang('PasswordStrong'),
7299
        get_lang('PasswordVeryStrong'),
7300
    );
7301
    $js = api_get_js('strength/strength.js');
7302
    $js .=  "<script>
7303
7304
    var verdicts = ['".implode("','", $verdicts)."'];
7305
    var errorMessages = {
7306
        password_to_short : \"" . get_lang('PasswordIsTooShort')."\",
7307
        same_as_username : \"".get_lang('YourPasswordCannotBeTheSameAsYourUsername')."\"
7308
    };
7309
7310
    $(document).ready(function() {
7311
        var options = {
7312
            verdicts: verdicts,
7313
            onLoad : function () {
7314
                //$('#messages').text('Start typing password');
7315
            },
7316
            onKeyUp: function (evt) {
7317
                $(evt.target).pwstrength('outputErrorList');
7318
            },
7319
            errorMessages : errorMessages,
7320
            viewports: {
7321
                progress: '#password_progress',
7322
                verdict: '#password-verdict',
7323
                errors: '#password-errors'
7324
            },
7325
            usernameField: '$usernameInputId'
7326
        };
7327
        $('".$passwordInputid."').pwstrength(options);
7328
    });
7329
    </script>";
7330
    return $js;
7331
}
7332
7333
/**
7334
 * Gets an array with "easy" passwords
7335
 * @return array
7336
 */
7337
function api_get_easy_password_list()
7338
{
7339
    $passwordList = array('123', '1234', '123456', 'admin', 'user', 'student', 'teacher');
7340
    $file = api_get_path(CONFIGURATION_PATH).'easy_password_list.php';
7341
    if (file_exists($file)) {
7342
        $passwordList = require_once $file;
7343
    }
7344
    return $passwordList;
7345
}
7346
7347
/**
7348
 * @param string $username
7349
 * create an user extra field called 'captcha_blocked_until_date'
7350
 */
7351
function api_block_account_captcha($username)
7352
{
7353
    $userInfo = api_get_user_info_from_username($username);
7354
    if (empty($userInfo)) {
7355
        return false;
7356
    }
7357
    $minutesToBlock = api_get_setting('captcha_time_to_block');
7358
    $time = time() + $minutesToBlock*60;
7359
    UserManager::update_extra_field_value(
7360
        $userInfo['user_id'],
7361
        'captcha_blocked_until_date',
7362
        api_get_utc_datetime($time)
7363
    );
7364
}
7365
7366
/**
7367
 * @param string $username
7368
 */
7369
function api_clean_account_captcha($username)
7370
{
7371
    $userInfo = api_get_user_info_from_username($username);
7372
    if (empty($userInfo)) {
7373
        return false;
7374
    }
7375
    Session::erase('loginFailedCount');
7376
    UserManager::update_extra_field_value(
7377
        $userInfo['user_id'],
7378
        'captcha_blocked_until_date',
7379
        null
7380
    );
7381
}
7382
7383
/**
7384
 * @param string $username
7385
 * @return bool
7386
 */
7387
function api_get_user_blocked_by_captcha($username)
7388
{
7389
    $userInfo = api_get_user_info_from_username($username);
7390
    if (empty($userInfo)) {
7391
        return false;
7392
    }
7393
    $data = UserManager::get_extra_user_data_by_field(
7394
        $userInfo['user_id'],
7395
        'captcha_blocked_until_date'
7396
    );
7397
    if (isset($data) && isset($data['captcha_blocked_until_date'])) {
7398
        return $data['captcha_blocked_until_date'];
7399
    }
7400
    return false;
7401
}
7402
7403
/**
7404
 * Remove tags from HTML anf return the $in_number_char first non-HTML char
7405
 * Postfix the text with "..." if it has been truncated.
7406
 * @return string
7407
 * @author hubert borderiou
7408
 */
7409
function api_get_short_text_from_html($in_html, $in_number_char)
7410
{
7411
    $out_res = api_remove_tags_with_space($in_html, false);
7412
    $postfix = "...";
7413
    if (strlen($out_res) > $in_number_char) {
7414
        $out_res = substr($out_res, 0, $in_number_char).$postfix;
7415
    }
7416
    return $out_res;
7417
}
7418
7419
/**
7420
 * Replace tags with a space in a text.
7421
 * If $in_double_quote_replace, replace " with '' (for HTML attribute purpose, for exemple)
7422
 * @return string
7423
 * @author hubert borderiou
7424
 */
7425
function api_remove_tags_with_space($in_html, $in_double_quote_replace = true) {
7426
    $out_res = $in_html;
7427
    if ($in_double_quote_replace) {
7428
        $out_res = str_replace('"', "''", $out_res);
7429
    }
7430
    // avoid text stuck together when tags are removed, adding a space after >
7431
    $out_res = str_replace (">", "> ", $out_res);
7432
    $out_res = strip_tags($out_res);
7433
7434
    return $out_res;
7435
}
7436
7437
/**
7438
 * If true, the drh can access all content (courses, users) inside a session
7439
 * @return bool
7440
 */
7441
function api_drh_can_access_all_session_content()
7442
{
7443
    $a = api_get_setting('drh_can_access_all_session_content');
7444
    return $a == 'true';
7445
}
7446
7447
/**
7448
 * @param string $tool
7449
 * @param string $setting
7450
 * @param mixed $defaultValue
7451
 * @return string
7452
 */
7453
function api_get_default_tool_setting($tool, $setting, $defaultValue)
7454
{
7455
    global $_configuration;
7456
    if (isset($_configuration[$tool]) &&
7457
        isset($_configuration[$tool]['default_settings']) &&
7458
        isset($_configuration[$tool]['default_settings'][$setting])
7459
    ) {
7460
        return $_configuration[$tool]['default_settings'][$setting];
7461
    }
7462
    return $defaultValue;
7463
7464
}
7465
7466
/**
7467
 * Checks if user can login as another user
7468
 *
7469
 * @param int $loginAsUserId the user id to log in
7470
 * @param int $userId my user id
7471
 * @return bool
7472
 */
7473
function api_can_login_as($loginAsUserId, $userId = null)
7474
{
7475
    if (empty($userId)) {
7476
        $userId = api_get_user_id();
7477
    }
7478
    if ($loginAsUserId == $userId) {
7479
        return false;
7480
    }
7481
7482
    if (empty($loginAsUserId)) {
7483
        return false;
7484
    }
7485
7486
    if ($loginAsUserId != strval(intval($loginAsUserId))) {
7487
        return false;
7488
    }
7489
    // Check if the user to login is an admin
7490
7491
    if (api_is_platform_admin_by_id($loginAsUserId)) {
7492
        // Only super admins can login to admin accounts
7493
        if (!api_global_admin_can_edit_admin($loginAsUserId)) {
7494
            return false;
7495
        }
7496
    }
7497
7498
    $userInfo = api_get_user_info($userId);
7499
7500
    $isDrh = function() use($loginAsUserId) {
7501
        if (api_is_drh()) {
7502
            if (api_drh_can_access_all_session_content()) {
7503
                $users = SessionManager::getAllUsersFromCoursesFromAllSessionFromStatus('drh_all', api_get_user_id());
7504
                $userList = array();
7505
                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...
7506
                    $userList[] = $user['user_id'];
7507
                }
7508
                if (in_array($loginAsUserId, $userList)) {
7509
                    return true;
7510
                }
7511
            } else {
7512
                if (api_is_drh() && UserManager::is_user_followed_by_drh($loginAsUserId, api_get_user_id())) {
7513
                    return true;
7514
                }
7515
            }
7516
        }
7517
        return false;
7518
    };
7519
7520
    return api_is_platform_admin() || (api_is_session_admin() && $userInfo['status'] == 5) || $isDrh();
7521
}
7522
7523
/**
7524
 * @return bool
7525
 */
7526
function api_is_allowed_in_course()
7527
{
7528
    return Session::read('is_allowed_in_course');
7529
}
7530
7531
/**
7532
 * Show a string in
7533
 * @param string $string Some string to dump, removing tabs, spaces,
7534
 * newlines, etc (usually most useful for SQL queries)
7535
 * @param int $dump Set to 1 to use print_r()
7536
 */
7537
function api_error_log($string, $dump = 0)
7538
{
7539
    // Clean query
7540
    $bt = debug_backtrace();
7541
    $caller = array_shift($bt);;
7542
    if ($dump == 1) {
7543
        $string = print_r($string, 1);
7544
    } else {
7545
        $string = str_replace(array("\r", "\n", "\t", "\10"), '', $string);
7546
        $string = str_replace('    ',' ', $string);
7547
    }
7548
7549
    error_log("-------------------------------------");
7550
    error_log($string);
7551
    error_log("File: ".$caller['file']." +".$caller['line']);
7552
    error_log("-------------------------------------");
7553
}
7554
7555
/**
7556
 * Set the cookie to go directly to the course code $in_firstpage
7557
 * after login
7558
 * @param string $in_firstpage is the course code of the course to go
7559
 */
7560
function api_set_firstpage_parameter($in_firstpage)
7561
{
7562
    setcookie("GotoCourse", $in_firstpage);
7563
}
7564
7565
/**
7566
 * Delete the cookie to go directly to the course code $in_firstpage
7567
 * after login
7568
 */
7569
function api_delete_firstpage_parameter()
7570
{
7571
    setcookie("GotoCourse", "", time() - 3600);
7572
}
7573
7574
/**
7575
 * @return true if course_code for direct course access after login is set
7576
 */
7577
function exist_firstpage_parameter()
7578
{
7579
    return (isset($_COOKIE['GotoCourse']) && $_COOKIE['GotoCourse'] != "");
7580
}
7581
7582
/**
7583
 * @return return the course_code of the course where user login
7584
 */
7585
function api_get_firstpage_parameter()
7586
{
7587
    return $_COOKIE['GotoCourse'];
7588
}
7589
7590
/**
7591
 * Return true on https install
7592
 * @return boolean
7593
 */
7594
function api_is_https()
7595
{
7596
    return (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] != 'off');
7597
}
7598
7599
/**
7600
 * Return protocol (http or https)
7601
 * @return string
7602
 */
7603
function api_get_protocol()
7604
{
7605
    return api_is_https() ? 'https' : 'http';
7606
}
7607
7608
/**
7609
 * Return a string where " are replaced with 2 '
7610
 * It is useful when you pass a PHP variable in a Javascript browser dialog
7611
 * e.g. : alert("<?php get_lang('Message') ?>");
7612
 * and message contains character "
7613
 *
7614
 * @param string $in_text
7615
 * @return string
7616
 */
7617
function convert_double_quote_to_single($in_text) {
7618
    return api_preg_replace('/"/', "''", $in_text);
7619
}
7620
7621
/**
7622
 * Get origin
7623
 *
7624
 * @param string
7625
 * @return string
7626
 **/
7627
function api_get_origin()
7628
{
7629
    if (isset($_REQUEST['origin'])) {
7630
        return $_REQUEST['origin'] == 'learnpath' ? 'learnpath' : null;
7631
    }
7632
7633
    return null;
7634
}
7635
7636
/**
7637
 * Warns an user that the portal reach certain limit.
7638
 * @param string $limitName
7639
 */
7640
function api_warn_hosting_contact($limitName)
7641
{
7642
    $hostingParams = api_get_configuration_value(1);
7643
    $email = null;
7644
7645
    if (!empty($hostingParams)) {
7646
        if (isset($hostingParams['hosting_contact_mail'])) {
7647
            $email = $hostingParams['hosting_contact_mail'];
7648
        }
7649
    }
7650
7651
    if (!empty($email)) {
7652
        $subject = get_lang('HostingWarningReached');
7653
        $body = get_lang('PortalName').': '.api_get_path(WEB_PATH)." \n ";
7654
        $body .= get_lang('PortalLimitType').': '.$limitName." \n ";
7655
        if (isset($hostingParams[$limitName])) {
7656
            $body .= get_lang('Value') . ': ' . $hostingParams[$limitName];
7657
        }
7658
        api_mail_html(null, $email, $subject, $body);
7659
    }
7660
}
7661
7662
/**
7663
 * @param string $variable
7664
 * @return bool|mixed
7665
 */
7666
function api_get_configuration_value($variable)
7667
{
7668
    global $_configuration;
7669
    if (isset($_configuration[$variable])) {
7670
        return $_configuration[$variable];
7671
    }
7672
    return false;
7673
}
7674
7675
/**
7676
 * Returns supported image extensions in the portal
7677
 * @return  array   Supported image extensions in the portal
7678
 */
7679
function api_get_supported_image_extensions()
7680
{
7681
    // jpg can also be called jpeg, jpe, jfif and jif. See https://en.wikipedia.org/wiki/JPEG#JPEG_filename_extensions
7682
    $supportedImageExtensions = array('jpg', 'jpeg', 'png', 'gif', 'svg', 'jpe', 'jfif', 'jif');
7683
    if (version_compare(PHP_VERSION, '5.5.0', '>=')) {
7684
        array_push($supportedImageExtensions, 'webp');
7685
    }
7686
    return $supportedImageExtensions;
7687
}
7688
7689
/**
7690
 * This setting changes the registration status for the campus
7691
 *
7692
 * @author Patrick Cool <[email protected]>, Ghent University
7693
 * @version August 2006
7694
 * @param   bool    $listCampus Whether we authorize
7695
 * @todo the $_settings should be reloaded here. => write api function for this and use this in global.inc.php also.
7696
 */
7697 View Code Duplication
function api_register_campus($listCampus = true) {
7698
    $tbl_settings = Database :: get_main_table(TABLE_MAIN_SETTINGS_CURRENT);
7699
7700
    $sql = "UPDATE $tbl_settings SET selected_value='true' WHERE variable='registered'";
7701
    Database::query($sql);
7702
7703
    if (!$listCampus) {
7704
        $sql = "UPDATE $tbl_settings SET selected_value='true' WHERE variable='donotlistcampus'";
7705
        Database::query($sql);
7706
    }
7707
}
7708
7709
/**
7710
 * Checks whether current user is a student boss
7711
 * @global array $_user
7712
 * @return boolean
7713
 */
7714
function api_is_student_boss()
7715
{
7716
    $_user = api_get_user_info();
7717
7718
    return isset($_user['status']) && $_user['status'] == STUDENT_BOSS;
7719
}
7720
7721
/**
7722
 * Check whether the user type should be exclude.
7723
 * Such as invited or anonymous users
7724
 * @param boolean $checkDB Optional. Whether check the user status
7725
 * @param int $userId Options. The user id
7726
 *
7727
 * @return boolean
7728
 */
7729
function api_is_excluded_user_type($checkDB = false, $userId = 0)
7730
{
7731
    if ($checkDB) {
7732
        $userId = empty($userId) ? api_get_user_id() : intval($userId);
7733
7734
        if ($userId == 0) {
7735
            return true;
7736
        }
7737
7738
        $userInfo = api_get_user_info($userId);
7739
7740
        switch ($userInfo['status']) {
7741
            case INVITEE:
7742
                //no break;
7743
            case ANONYMOUS:
7744
                return true;
7745
            default:
7746
                return false;
7747
        }
7748
    }
7749
7750
    $isInvited = api_is_invitee();
7751
    $isAnonymous = api_is_anonymous();
7752
7753
    if ($isInvited || $isAnonymous) {
7754
        return true;
7755
    }
7756
7757
    return false;
7758
}
7759
7760
/**
7761
 * Get the user status to ignore in reports
7762
 * @param string $format Optional. The result type (array or string)
7763
 * @return array|string
7764
 */
7765
function api_get_users_status_ignored_in_reports($format = 'array')
7766
{
7767
    $excludedTypes = array(
7768
        INVITEE,
7769
        ANONYMOUS
7770
    );
7771
7772
    if ($format == 'string') {
7773
        return implode(', ', $excludedTypes);
7774
    }
7775
7776
    return $excludedTypes;
7777
}
7778
7779
/**
7780
 * Set the Site Use Cookie Warning for 1 year
7781
 */
7782
function api_set_site_use_cookie_warning_cookie()
7783
{
7784
    setcookie("ChamiloUsesCookies", "ok", time()+31556926);
7785
}
7786
7787
/**
7788
 * Return true if the Site Use Cookie Warning Cookie warning exists
7789
 * @return bool
7790
 */
7791
function api_site_use_cookie_warning_cookie_exist()
7792
{
7793
    return isset($_COOKIE['ChamiloUsesCookies']);
7794
}
7795
7796
/**
7797
 * Given a number of seconds, format the time to show hours, minutes and seconds
7798
 * @param int $time The time in seconds
7799
 * @param string $originFormat Optional. PHP o JS
7800
 * @return string (00h00'00")
7801
 */
7802
function api_format_time($time, $originFormat = 'php')
7803
{
7804
    $h = get_lang('h');
7805
    $hours = $time / 3600;
7806
    $mins = ($time % 3600) / 60;
7807
    $secs = ($time % 60);
7808
7809
    if ($originFormat == 'js') {
7810
        $formattedTime = trim(sprintf("%02d : %02d : %02d", $hours, $mins, $secs));
7811
    } else {
7812
        $formattedTime = trim(sprintf("%02d$h%02d'%02d\"", $hours, $mins, $secs));
7813
    }
7814
7815
    return $formattedTime;
7816
}
7817
7818
/**
7819
 * Create a new empty directory with index.html file
7820
 * @param string $name The new directory name
7821
 * @param string $parentDirectory Directory parent directory name
7822
 * @return boolean Return true if the directory was create. Otherwise return false
7823
 */
7824
function api_create_protected_dir($name, $parentDirectory)
7825
{
7826
    $isCreated = false;
7827
7828
    if (!is_writable($parentDirectory)) {
7829
        return false;
7830
    }
7831
7832
    $fullPath = $parentDirectory . api_replace_dangerous_char($name);
7833
7834
    if (mkdir($fullPath, api_get_permissions_for_new_directories(), true)) {
7835
        $fp = fopen($fullPath . '/index.html', 'w');
7836
7837
        if ($fp) {
7838
            if (fwrite($fp, '<html><head></head><body></body></html>')) {
7839
                $isCreated = true;
7840
            }
7841
        }
7842
7843
        fclose($fp);
7844
    }
7845
7846
    return $isCreated;
7847
}
7848
7849
/**
7850
 * Sends an HTML email using the phpmailer class (and multipart/alternative to downgrade gracefully)
7851
 * Sender name and email can be specified, if not specified
7852
 * name and email of the platform admin are used
7853
 *
7854
 * @author Bert Vanderkimpen ICT&O UGent
7855
 * @author Yannick Warnier <[email protected]>
7856
 *
7857
 * @param string    name of recipient
7858
 * @param string    email of recipient
7859
 * @param string    email subject
7860
 * @param string    email body
7861
 * @param string    sender name
7862
 * @param string    sender e-mail
7863
 * @param array     extra headers in form $headers = array($name => $value) to allow parsing
7864
 * @param array     data file (path and filename)
7865
 * @param bool      True for attaching a embedded file inside content html (optional)
7866
 * @param array     Additional parameters
7867
 * @return          returns true if mail was sent
7868
 * @see             class.phpmailer.php
7869
 */
7870
function api_mail_html(
7871
    $recipient_name,
7872
    $recipient_email,
7873
    $subject,
7874
    $message,
7875
    $senderName = '',
7876
    $senderEmail = '',
7877
    $extra_headers = array(),
7878
    $data_file = array(),
7879
    $embedded_image = false,
7880
    $additionalParameters = array()
7881
) {
7882
    global $platform_email;
7883
7884
    $mail = new PHPMailer();
7885
    $mail->Mailer = $platform_email['SMTP_MAILER'];
7886
    $mail->Host = $platform_email['SMTP_HOST'];
7887
    $mail->Port = $platform_email['SMTP_PORT'];
7888
    $mail->CharSet = $platform_email['SMTP_CHARSET'];
7889
    // Stay far below SMTP protocol 980 chars limit.
7890
    $mail->WordWrap = 200;
7891
7892
    if ($platform_email['SMTP_AUTH']) {
7893
        $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...
7894
        $mail->Username = $platform_email['SMTP_USER'];
7895
        $mail->Password = $platform_email['SMTP_PASS'];
7896
        if (isset($platform_email['SMTP_SECURE'])) {
7897
            $mail->SMTPSecure = $platform_email['SMTP_SECURE'];
7898
        }
7899
    }
7900
    $mail->SMTPDebug = isset($platform_email['SMTP_DEBUG'])?$platform_email['SMTP_DEBUG']:0;
7901
7902
    // 5 = low, 1 = high
7903
    $mail->Priority = 3;
7904
    $mail->SMTPKeepAlive = true;
7905
7906
    // Default values
7907
    $notification = new Notification();
7908
    $defaultEmail = $notification->getDefaultPlatformSenderEmail();
7909
    $defaultName = $notification->getDefaultPlatformSenderName();
7910
7911
    // Error to admin.
7912
    $mail->AddCustomHeader('Errors-To: '.$defaultEmail);
7913
7914
    // If the parameter is set don't use the admin.
7915
    $senderName = !empty($senderName) ? $senderName : $defaultName;
7916
    $senderEmail = !empty($senderEmail) ? $senderEmail : $defaultEmail;
7917
7918
    // Reply to first
7919
    if (isset($extra_headers['reply_to'])) {
7920
        $mail->AddReplyTo(
7921
            $extra_headers['reply_to']['mail'],
7922
            $extra_headers['reply_to']['name']
7923
        );
7924
        $mail->Sender = $extra_headers['reply_to']['mail'];
7925
        unset($extra_headers['reply_to']);
7926
    }
7927
    //If the SMTP configuration only accept one sender
7928
    if ($platform_email['SMTP_UNIQUE_SENDER']) {
7929
        $senderName = $platform_email['SMTP_FROM_NAME'];
7930
        $senderEmail = $platform_email['SMTP_FROM_EMAIL'];
7931
    }
7932
    $mail->SetFrom($senderEmail, $senderName);
7933
7934
    $mail->Subject = $subject;
7935
    $mail->AltBody = strip_tags(
7936
        str_replace('<br />', "\n", api_html_entity_decode($message))
7937
    );
7938
7939
    // Send embedded image.
7940
    if ($embedded_image) {
7941
        // Get all images html inside content.
7942
        preg_match_all("/<img\s+.*?src=[\"\']?([^\"\' >]*)[\"\']?[^>]*>/i", $message, $m);
7943
        // Prepare new tag images.
7944
        $new_images_html = array();
7945
        $i = 1;
7946
        if (!empty($m[1])) {
7947
            foreach ($m[1] as $image_path) {
7948
                $real_path = realpath($image_path);
7949
                $filename  = basename($image_path);
7950
                $image_cid = $filename.'_'.$i;
7951
                $encoding = 'base64';
7952
                $image_type = mime_content_type($real_path);
7953
                $mail->AddEmbeddedImage(
7954
                    $real_path,
7955
                    $image_cid,
7956
                    $filename,
7957
                    $encoding,
7958
                    $image_type
0 ignored issues
show
Bug introduced by
It seems like $image_type defined by mime_content_type($real_path) on line 7952 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...
7959
                );
7960
                $new_images_html[] = '<img src="cid:'.$image_cid.'" />';
7961
                $i++;
7962
            }
7963
        }
7964
7965
        // Replace origin image for new embedded image html.
7966
        $x = 0;
7967
        if (!empty($m[0])) {
7968
            foreach ($m[0] as $orig_img) {
7969
                $message = str_replace($orig_img, $new_images_html[$x], $message);
7970
                $x++;
7971
            }
7972
        }
7973
    }
7974
7975
    $mailView = new Template(null, false, false, false, false, false, false);
7976
    $mailView->assign('content', $message);
7977
7978
    if (isset($additionalParameters['link'])) {
7979
        $mailView->assign('link', $additionalParameters['link']);
7980
    }
7981
7982
    $layout = $mailView->get_template('mail/mail.tpl');
7983
    $mail->Body = $mailView->fetch($layout);
7984
7985
    // Attachment ...
7986
    if (!empty($data_file)) {
7987
        $o = 0;
7988 View Code Duplication
        foreach ($data_file as $file_attach) {
7989
            if (!empty($file_attach['path']) && !empty($file_attach['filename'])) {
7990
                $mail->AddAttachment($file_attach['path'], $file_attach['filename']);
7991
            }
7992
            $o++;
7993
        }
7994
    } elseif (is_array($_FILES)) {
7995
        $data_file = $_FILES;
7996
        $o = 0;
7997 View Code Duplication
        foreach ($data_file as $file_attach) {
7998
            if (!empty($file_attach['tmp_name']) && !empty($file_attach['name'])) {
7999
                $mail->AddAttachment($file_attach['tmp_name'], $file_attach['name']);
8000
            }
8001
            $o++;
8002
        }
8003
    }
8004
8005
    // Only valid addresses are accepted.
8006
    if (is_array($recipient_email)) {
8007
        foreach ($recipient_email as $dest) {
8008
            if (api_valid_email($dest)) {
8009
                $mail->AddAddress($dest, $recipient_name);
8010
            }
8011
        }
8012
    } else {
8013
        if (api_valid_email($recipient_email)) {
8014
            $mail->AddAddress($recipient_email, $recipient_name);
8015
        } else {
8016
            return 0;
8017
        }
8018
    }
8019
8020
    if (is_array($extra_headers) && count($extra_headers) > 0) {
8021
        foreach ($extra_headers as $key => $value) {
8022
            switch (strtolower($key)) {
8023
                case 'encoding':
8024
                case 'content-transfer-encoding':
8025
                    $mail->Encoding = $value;
8026
                    break;
8027
                case 'charset':
8028
                    $mail->Charset = $value;
8029
                    break;
8030
                case 'contenttype':
8031
                case 'content-type':
8032
                    $mail->ContentType = $value;
8033
                    break;
8034
                default:
8035
                    $mail->AddCustomHeader($key.':'.$value);
8036
                    break;
8037
            }
8038
        }
8039
    } else {
8040
        if (!empty($extra_headers)) {
8041
            $mail->AddCustomHeader($extra_headers);
8042
        }
8043
    }
8044
8045
    // WordWrap the html body (phpMailer only fixes AltBody) FS#2988
8046
    $mail->Body = $mail->WrapText($mail->Body, $mail->WordWrap);
8047
    // Send the mail message.
8048
    if (!$mail->Send()) {
8049
        error_log('ERROR: mail not sent to '.$recipient_name.' ('.$recipient_email.') because of '.$mail->ErrorInfo.'<br />');
8050
        if ($mail->SMTPDebug) {
8051
            error_log(
8052
                "Connection details :: " .
8053
                "Protocol: " . $mail->Mailer . ' :: ' .
8054
                "Host/Port: " . $mail->Host . ':' . $mail->Port . ' :: ' .
8055
                "Authent/Open: " . ($mail->SMTPAuth?'Authent':'Open') . ' :: ' .
8056
                ($mail->SMTPAuth?"  User/Pass: " . $mail->Username . ':' . $mail->Password:'')
8057
            );
8058
        }
8059
        return 0;
8060
    }
8061
8062
    if (!empty($additionalParameters)) {
8063
        $plugin = new AppPlugin();
8064
        $smsPlugin = $plugin->getSMSPluginLibrary();
8065
        if ($smsPlugin) {
8066
            $smsPlugin->send($additionalParameters);
8067
        }
8068
    }
8069
8070
    // Clear all the addresses.
8071
    $mail->ClearAddresses();
8072
    return 1;
8073
}
8074
8075
/**
8076
 * @param string $tool Possible values:
8077
 * GroupManager::GROUP_TOOL_*
8078
 *
8079
 */
8080
function api_protect_course_group($tool, $showHeader = true)
8081
{
8082
    $userId = api_get_user_id();
8083
    $groupId = api_get_group_id();
8084
8085
    if (!empty($groupId)) {
8086
        $allow = GroupManager::user_has_access(
8087
            $userId,
8088
            $groupId,
8089
            $tool
8090
        );
8091
8092
        if (!$allow) {
8093
            api_not_allowed($showHeader);
8094
        }
8095
    }
8096
}
8097
8098
/**
8099
 * Eliminate the duplicates of a multidimensional array by sending the key
8100
 * @param array $array multidimensional array
8101
 * @param int $key key to find to compare
8102
 *
8103
 */
8104
function api_unique_multidim_array($array, $key){
8105
    $temp_array = array();
8106
    $i = 0;
8107
    $key_array = array();
8108
8109
    foreach($array as $val){
8110
        if(!in_array($val[$key],$key_array)){
8111
            $key_array[$i] = $val[$key];
8112
            $temp_array[$i] = $val;
8113
        }
8114
        $i++;
8115
    }
8116
    return $temp_array;
8117
}
8118
8119
/**
8120
 * Limit the access to Session Admins wheen the limit_session_admin_role
8121
 * configuration variable is set to true
8122
 */
8123
function api_protect_limit_for_session_admin()
8124
{
8125
    $limitAdmin = api_get_setting('limit_session_admin_role');
8126
    if (api_is_session_admin() && $limitAdmin === 'true') {
8127
        api_not_allowed(true);
8128
    }
8129
}
8130
8131
function api_is_student_view_active() {
8132
    return (isset($_SESSION['studentview']) && $_SESSION['studentview'] == "studentview");
8133
}
8134