Completed
Push — 1.10.x ( d27a7f...1f2dc0 )
by Julito
83:07 queued 34:57
created

api.lib.php ➔ api_is_coach_of_course_in_session()   C

Complexity

Conditions 12
Paths 16

Size

Total Lines 64
Code Lines 39

Duplication

Lines 32
Ratio 50 %

Importance

Changes 0
Metric Value
cc 12
eloc 39
nc 16
nop 1
dl 32
loc 64
rs 6.0561
c 0
b 0
f 0

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

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

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

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

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

Let’s take a look at these examples:

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

// More likely intended return: true/false
return 0 === ($foo & 4);
Loading history...
1216
            isset($course_info['registration_code']) &&
1217
            !empty($course_info['registration_code'])
1218
        ) {
1219
            $is_visible = false;
1220
        }
1221
    }
1222
1223
    //Check session visibility
1224
    $session_id = api_get_session_id();
1225
1226
    if (!empty($session_id)) {
1227
        //$is_allowed_in_course was set in local.inc.php
1228
        if (!$is_allowed_in_course) {
1229
            $is_visible = false;
1230
        }
1231
    }
1232
1233
    if (!$is_visible) {
1234
        api_not_allowed($print_headers);
1235
        return false;
1236
    }
1237
    return true;
1238
}
1239
1240
/**
1241
 * Function used to protect an admin script.
1242
 *
1243
 * The function blocks access when the user has no platform admin rights
1244
 * with an error message printed on default output
1245
 * @param bool Whether to allow session admins as well
1246
 * @param bool Whether to allow HR directors as well
1247
 * @param string An optional message (already passed through get_lang)
1248
 * @return bool True if user is allowed, false otherwise.
1249
 * The function also outputs an error message in case not allowed
1250
 * @author Roan Embrechts (original author)
1251
 */
1252
function api_protect_admin_script($allow_sessions_admins = false, $allow_drh = false, $message = null)
1253
{
1254
    if (!api_is_platform_admin($allow_sessions_admins, $allow_drh)) {
1255
        api_not_allowed(true, $message);
1256
        return false;
1257
    }
1258
    return true;
1259
}
1260
1261
/**
1262
 * Function used to protect a teacher script.
1263
 * The function blocks access when the user has no teacher rights.
1264
 *
1265
 * @author Yoselyn Castillo
1266
 */
1267
function api_protect_teacher_script($allow_sessions_admins = false)
1268
{
1269
    if (!api_is_allowed_to_edit()) {
1270
        api_not_allowed(true);
1271
        return false;
1272
    }
1273
    return true;
1274
}
1275
1276
/**
1277
 * Function used to prevent anonymous users from accessing a script.
1278
 * @param bool|true $printHeaders
1279
 * @author Roan Embrechts
1280
 *
1281
 * @return bool
1282
 */
1283
function api_block_anonymous_users($printHeaders = true)
1284
{
1285
    $user = api_get_user_info();
1286 View Code Duplication
    if (!(isset($user['user_id']) && $user['user_id']) || api_is_anonymous($user['user_id'], true)) {
1287
        api_not_allowed($printHeaders);
1288
        return false;
1289
    }
1290
1291
    return true;
1292
}
1293
1294
/**
1295
 * @return array with the navigator name and version
1296
 */
1297
function api_get_navigator() {
1298
    $navigator = 'Unknown';
1299
    $version = 0;
1300
1301
    if (!isset($_SERVER['HTTP_USER_AGENT'])) {
1302
        return array('name' => 'Unknown', 'version' => '0.0.0');
1303
    }
1304
1305
    if (strpos($_SERVER['HTTP_USER_AGENT'], 'Opera') !== false) {
1306
        $navigator = 'Opera';
1307
        list (, $version) = explode('Opera', $_SERVER['HTTP_USER_AGENT']);
1308 View Code Duplication
    } elseif (strpos($_SERVER['HTTP_USER_AGENT'], 'MSIE') !== false) {
1309
        $navigator = 'Internet Explorer';
1310
        list (, $version) = explode('MSIE', $_SERVER['HTTP_USER_AGENT']);
1311
    } elseif (strpos($_SERVER['HTTP_USER_AGENT'], 'Chrome') !== false) {
1312
        $navigator = 'Chrome';
1313
        list (, $version) = explode('Chrome', $_SERVER['HTTP_USER_AGENT']);
1314
    } elseif (stripos($_SERVER['HTTP_USER_AGENT'], 'safari') !== false) {
1315
        $navigator = 'Safari';
1316
        list (, $version) = explode('Version/', $_SERVER['HTTP_USER_AGENT']);
1317
    } elseif (strpos($_SERVER['HTTP_USER_AGENT'], 'Gecko') !== false) {
1318
        $navigator = 'Mozilla';
1319
        list (, $version) = explode('; rv:', $_SERVER['HTTP_USER_AGENT']);
1320 View Code Duplication
    } elseif (strpos($_SERVER['HTTP_USER_AGENT'], 'Netscape') !== false) {
1321
        $navigator = 'Netscape';
1322
        list (, $version) = explode('Netscape', $_SERVER['HTTP_USER_AGENT']);
1323
    } elseif (strpos($_SERVER['HTTP_USER_AGENT'], 'Konqueror') !== false) {
1324
        $navigator = 'Konqueror';
1325
        list (, $version) = explode('Konqueror', $_SERVER['HTTP_USER_AGENT']);
1326 View Code Duplication
    } elseif (stripos($_SERVER['HTTP_USER_AGENT'], 'applewebkit') !== false) {
1327
        $navigator = 'AppleWebKit';
1328
        list (, $version) = explode('Version/', $_SERVER['HTTP_USER_AGENT']);
1329
    }
1330
    $version = str_replace('/', '', $version);
1331
    if (strpos($version, '.') === false) {
1332
        $version = number_format(doubleval($version), 1);
1333
    }
1334
    $return = array('name' => $navigator, 'version' => $version);
1335
    return $return;
1336
}
1337
1338
/**
1339
 * @return True if user self registration is allowed, false otherwise.
1340
 */
1341
function api_is_self_registration_allowed()
1342
{
1343
    return isset($GLOBALS['allowSelfReg']) ? $GLOBALS['allowSelfReg'] : false;
1344
}
1345
1346
/**
1347
 * This function returns the id of the user which is stored in the $_user array.
1348
 *
1349
 * example: The function can be used to check if a user is logged in
1350
 *          if (api_get_user_id())
1351
 * @return integer the id of the current user, 0 if is empty
1352
 */
1353
function api_get_user_id()
1354
{
1355
    return empty($GLOBALS['_user']['user_id']) ? 0 : intval($GLOBALS['_user']['user_id']);
1356
}
1357
1358
/**
1359
 * Gets the list of courses a specific user is subscribed to
1360
 * @param int       User ID
1361
 * @param boolean   $fetch_session Whether to get session courses or not - NOT YET IMPLEMENTED
1362
 * @return array    Array of courses in the form [0]=>('code'=>xxx,'db'=>xxx,'dir'=>xxx,'status'=>d)
1363
 */
1364
function api_get_user_courses($userid, $fetch_session = true)
1365
{
1366
    // Get out if not integer
1367
    if ($userid != strval(intval($userid))) {
1368
        return array();
1369
    }
1370
1371
    $t_course = Database::get_main_table(TABLE_MAIN_COURSE);
1372
    $t_course_user = Database::get_main_table(TABLE_MAIN_COURSE_USER);
1373
1374
    $sql = "SELECT cc.id as real_id, cc.code code, cc.directory dir, cu.status status
1375
            FROM    $t_course       cc,
1376
                    $t_course_user   cu
1377
            WHERE
1378
                cc.id = cu.c_id AND
1379
                cu.user_id = '".$userid."' AND
1380
                cu.relation_type<>".COURSE_RELATION_TYPE_RRHH." ";
1381
    $result = Database::query($sql);
1382
    if ($result === false) {
1383
        return array();
1384
    }
1385
1386
    $courses = array();
1387
    while ($row = Database::fetch_array($result)) {
1388
        // we only need the database name of the course
1389
        $courses[] = $row;
1390
    }
1391
1392
    return $courses;
1393
}
1394
1395
/**
1396
 * Formats user information into a standard array
1397
 * This function should be only used inside api_get_user_info()
1398
 *
1399
 * @param array Non-standard user array
1400
 * @param bool $add_password
1401
 *
1402
 * @return array Standard user array
1403
 */
1404
function _api_format_user($user, $add_password = false)
1405
{
1406
    $result = array();
1407
1408
    $firstname = null;
1409
    $lastname = null;
1410
1411
    if (isset($user['firstname']) && isset($user['lastname'])) {
1412
        $firstname = $user['firstname'];
1413
        $lastname = $user['lastname'];
1414
    } elseif (isset($user['firstName']) && isset($user['lastName'])) {
1415
        $firstname = isset($user['firstName']) ? $user['firstName'] : null;
1416
        $lastname = isset($user['lastName']) ? $user['lastName'] : null;
1417
    }
1418
1419
    $result['complete_name'] = api_get_person_name($firstname, $lastname);
1420
1421
    $result['complete_name_with_username'] = $result['complete_name'];
1422
1423
    if (!empty($user['username'])) {
1424
        $result['complete_name_with_username'] = $result['complete_name'].' ('.$user['username'].')';
1425
    }
1426
1427
    $result['firstname'] = $firstname;
1428
    $result['lastname'] = $lastname;
1429
1430
    // Kept for historical reasons
1431
    $result['firstName'] = $firstname;
1432
    $result['lastName'] = $lastname;
1433
1434
    $attributes = array(
1435
        'phone',
1436
        'picture_uri',
1437
        'official_code',
1438
        'status',
1439
        'active',
1440
        'auth_source',
1441
        'username',
1442
        'theme',
1443
        'language',
1444
        'creator_id',
1445
        'registration_date',
1446
        'hr_dept_id',
1447
        'expiration_date',
1448
        'last_login'
1449
    );
1450
    if (api_get_setting('extended_profile') === 'true') {
1451
        $attributes[] = 'competences';
1452
        $attributes[] = 'diplomas';
1453
        $attributes[] = 'teach';
1454
        $attributes[] = 'openarea';
1455
    }
1456
1457
    foreach ($attributes as $attribute) {
1458
        $result[$attribute] = isset($user[$attribute]) ? $user[$attribute] : null;
1459
    }
1460
1461
    if (isset($user['email'])) {
1462
        $result['mail'] = isset($user['email']) ? $user['email'] : null;
1463
        $result['email'] = isset($user['email'])? $user['email'] : null;
1464
    } else {
1465
        $result['mail'] = isset($user['mail']) ? $user['mail'] : null;
1466
        $result['email'] = isset($user['mail'])? $user['mail'] : null;
1467
    }
1468
    $user_id = intval($user['user_id']);
1469
    // Maintain the user_id index for backwards compatibility
1470
    $result['user_id'] = $result['id'] = $user_id;
1471
1472
    // Getting user avatar.
1473
    $originalFile = UserManager::getUserPicture($user_id, USER_IMAGE_SIZE_ORIGINAL, $result);
1474
    $smallFile = UserManager::getUserPicture($user_id, USER_IMAGE_SIZE_SMALL, $result);
1475
1476
    $result['avatar'] = $originalFile;
1477
    $avatarString = explode('?', $originalFile);
1478
    $result['avatar_no_query'] = reset($avatarString);
1479
    $result['avatar_small'] = $smallFile;
1480
1481
    if (isset($user['user_is_online'])) {
1482
        $result['user_is_online'] = $user['user_is_online'] == true ? 1 : 0;
1483
    }
1484
    if (isset($user['user_is_online_in_chat'])) {
1485
        $result['user_is_online_in_chat'] = intval($user['user_is_online_in_chat']);
1486
    }
1487
1488
    if ($add_password) {
1489
        $result['password'] = $user['password'];
1490
    }
1491
1492
    $result['profile_url'] = api_get_path(WEB_CODE_PATH).'social/profile.php?u='.$user_id;
1493
1494
    if (isset($user['extra'])) {
1495
        $result['extra'] = $user['extra'];
1496
    }
1497
1498
    return $result;
1499
}
1500
1501
/**
1502
 * Finds all the information about a user.
1503
 * If no parameter is passed you find all the information about the current user.
1504
 * @param int  $user_id
1505
 * @param bool $checkIfUserOnline
1506
 * @param bool $showPassword
1507
 * @param bool $loadExtraData
1508
 * @param bool $loadOnlyVisibleExtraData Get the user extra fields that are visible
1509
 * @return array $user_info user_id, lastname, firstname, username, email, etc
1510
 * @author Patrick Cool <[email protected]>
1511
 * @author Julio Montoya
1512
 * @version 21 September 2004
1513
 */
1514
function api_get_user_info(
1515
    $user_id = 0,
1516
    $checkIfUserOnline = false,
1517
    $showPassword = false,
1518
    $loadExtraData = false,
1519
    $loadOnlyVisibleExtraData = false
1520
) {
1521
    if (empty($user_id)) {
1522
        $userFromSession = Session::read('_user');
1523
        if (isset($userFromSession)) {
1524
            return _api_format_user($userFromSession);
1525
        }
1526
        // @todo trigger an exception here
1527
        return false;
1528
    }
1529
1530
    $sql = "SELECT * FROM ".Database :: get_main_table(TABLE_MAIN_USER)."
1531
            WHERE id='".intval($user_id)."'";
1532
    $result = Database::query($sql);
1533
    if (Database::num_rows($result) > 0) {
1534
        $result_array = Database::fetch_array($result);
1535
        if ($checkIfUserOnline) {
1536
            $use_status_in_platform = user_is_online($user_id);
1537
1538
            $result_array['user_is_online'] = $use_status_in_platform;
1539
            $user_online_in_chat = 0;
1540
1541
            if ($use_status_in_platform) {
1542
                $user_status = UserManager::get_extra_user_data_by_field(
1543
                    $user_id,
1544
                    'user_chat_status',
1545
                    false,
1546
                    true
1547
                );
1548
                if (intval($user_status['user_chat_status']) == 1) {
1549
                    $user_online_in_chat = 1;
1550
                }
1551
            }
1552
            $result_array['user_is_online_in_chat'] = $user_online_in_chat;
1553
        }
1554
1555
        if ($loadExtraData) {
1556
            $fieldValue = new ExtraFieldValue('user');
1557
1558
            $result_array['extra'] = $fieldValue->getAllValuesForAnItem(
1559
                $user_id,
1560
                $loadOnlyVisibleExtraData
1561
            );
1562
        }
1563
        $user = _api_format_user($result_array, $showPassword);
1564
1565
        return $user;
1566
    }
1567
    return false;
1568
}
1569
1570
/**
1571
 * Finds all the information about a user from username instead of user id
1572
 * @param string $username
1573
 * @return array $user_info array user_id, lastname, firstname, username, email
1574
 * @author Yannick Warnier <[email protected]>
1575
 */
1576 View Code Duplication
function api_get_user_info_from_username($username = '')
1577
{
1578
    if (empty($username)) {
1579
        return false;
1580
    }
1581
    $username = trim($username);
1582
1583
    $sql = "SELECT * FROM ".Database :: get_main_table(TABLE_MAIN_USER)."
1584
            WHERE username='".Database::escape_string($username)."'";
1585
    $result = Database::query($sql);
1586
    if (Database::num_rows($result) > 0) {
1587
        $result_array = Database::fetch_array($result);
1588
        return _api_format_user($result_array);
1589
    }
1590
    return false;
1591
}
1592
1593
/**
1594
 * Get first user with an email
1595
 * @param string $email
1596
 * @return array|bool
1597
 */
1598 View Code Duplication
function api_get_user_info_from_email($email = '')
1599
{
1600
    if (empty($email)) {
1601
        return false;
1602
    }
1603
    $sql = "SELECT * FROM ".Database :: get_main_table(TABLE_MAIN_USER)."
1604
            WHERE email ='".Database::escape_string($email)."' LIMIT 1";
1605
    $result = Database::query($sql);
1606
    if (Database::num_rows($result) > 0) {
1607
        $result_array = Database::fetch_array($result);
1608
        return _api_format_user($result_array);
1609
    }
1610
1611
    return false;
1612
}
1613
1614
/**
1615
 * @return string
1616
 */
1617
function api_get_course_id()
1618
{
1619
    return Session::read('_cid', null);
1620
}
1621
1622
/**
1623
 * Returns the current course id
1624
 * @return int
1625
 */
1626
function api_get_real_course_id()
1627
{
1628
    return api_get_course_int_id();
1629
}
1630
1631
/**
1632
 * Returns the current course id (integer)
1633
 * @param   string  $code   Optional course code
1634
 * @return int
1635
 */
1636
function api_get_course_int_id($code = null)
1637
{
1638 View Code Duplication
    if (!empty($code)) {
1639
        $code = Database::escape_string($code);
1640
        $row = Database::select(
1641
            'id',
1642
            Database::get_main_table(TABLE_MAIN_COURSE),
1643
            array('where'=> array('code = ?' => array($code))),
1644
            'first'
1645
        );
1646
1647
        if (is_array($row) && isset($row['id'])) {
1648
            return $row['id'];
1649
        } else {
1650
            return false;
1651
        }
1652
    }
1653
    return Session::read('_real_cid', 0);
1654
}
1655
1656
/**
1657
 * Returns the current course directory
1658
 *
1659
 * This function relies on api_get_course_info()
1660
 * @param string    The course code - optional (takes it from session if not given)
1661
 * @return string   The directory where the course is located inside the Chamilo "courses" directory
1662
 * @author Yannick Warnier <[email protected]>
1663
 */
1664
function api_get_course_path($course_code = null)
1665
{
1666
    $info = !empty($course_code) ? api_get_course_info($course_code) : api_get_course_info();
1667
    return $info['path'];
1668
}
1669
1670
/**
1671
 * Gets a course setting from the current course_setting table. Try always using integer values.
1672
 * @param string    The name of the setting we want from the table
1673
 * @param string    Optional: course code
1674
 * @param string $setting_name
1675
 * @return mixed    The value of that setting in that table. Return -1 if not found.
1676
 */
1677
function api_get_course_setting($setting_name, $course_code = null)
1678
{
1679
    $course_info = api_get_course_info($course_code);
1680
    $table = Database::get_course_table(TABLE_COURSE_SETTING);
1681
    $setting_name = Database::escape_string($setting_name);
1682 View Code Duplication
    if (!empty($course_info['real_id']) && !empty($setting_name)) {
1683
        $sql = "SELECT value FROM $table
1684
                WHERE c_id = {$course_info['real_id']} AND variable = '$setting_name'";
1685
        $res = Database::query($sql);
1686
        if (Database::num_rows($res) > 0) {
1687
            $row = Database::fetch_array($res);
1688
            return $row['value'];
1689
        }
1690
    }
1691
    return -1;
1692
}
1693
1694
/**
1695
 * Gets an anonymous user ID
1696
 *
1697
 * For some tools that need tracking, like the learnpath tool, it is necessary
1698
 * to have a usable user-id to enable some kind of tracking, even if not
1699
 * perfect. An anonymous ID is taken from the users table by looking for a
1700
 * status of "6" (anonymous).
1701
 * @return int  User ID of the anonymous user, or O if no anonymous user found
1702
 */
1703
function api_get_anonymous_id()
1704
{
1705
    $table = Database::get_main_table(TABLE_MAIN_USER);
1706
    $sql = "SELECT user_id FROM $table WHERE status = ".ANONYMOUS;
1707
    $res = Database::query($sql);
1708
    if (Database::num_rows($res) > 0) {
1709
        $row = Database::fetch_array($res);
1710
        return $row['user_id'];
1711
    }
1712
1713
    // No anonymous user was found.
1714
    return 0;
1715
}
1716
1717
/**
1718
 * Returns the cidreq parameter name + current course id taken from
1719
 * $GLOBALS['_cid'] and returns a string like 'cidReq=ABC&id_session=123
1720
 *
1721
 * @param bool $addSessionId
1722
 * @param bool $addGroupId
1723
 * @return  string  Course & session references to add to a URL
1724
 *
1725
 */
1726
function api_get_cidreq($addSessionId = true, $addGroupId = true)
1727
{
1728
    $courseCode = api_get_course_id();
1729
    $url = empty($courseCode) ? '' : 'cidReq='.htmlspecialchars($courseCode);
1730
    $origin = api_get_origin();
1731
1732
    if ($addSessionId) {
1733
        if (!empty($url)) {
1734
            $url .= api_get_session_id() == 0 ? '&id_session=0' : '&id_session='.api_get_session_id();
1735
        }
1736
    }
1737
1738
    if ($addGroupId) {
1739
        if (!empty($url)) {
1740
            $url .= api_get_group_id() == 0 ? '&gidReq=0' : '&gidReq='.api_get_group_id();
1741
        }
1742
    }
1743
1744
    if (!empty($url)) {
1745
        $url .= '&gradebook='.intval(api_is_in_gradebook());
1746
        $url .= '&origin='.$origin;
1747
    }
1748
1749
    return $url;
1750
}
1751
1752
function api_is_in_gradebook()
1753
{
1754
    return Session::read('in_gradebook', false);
1755
}
1756
1757
function api_set_in_gradebook()
1758
{
1759
    Session::write('in_gradebook', true);
1760
}
1761
1762
function api_remove_in_gradebook()
1763
{
1764
    Session::erase('in_gradebook');
1765
}
1766
1767
/**
1768
 * Returns the current course info array see api_format_course_array()
1769
 * If the course_code is given, the returned array gives info about that
1770
 * particular course, if none given it gets the course info from the session.
1771
 *
1772
 * @param string $course_code
1773
 * @param bool $strict
1774
 *
1775
 * @return array
1776
 */
1777
function api_get_course_info($course_code = null, $strict = false)
1778
{
1779
    if (!empty($course_code)) {
1780
        $course_code = Database::escape_string($course_code);
1781
        $courseId = api_get_course_int_id($course_code);
1782
1783
        if (empty($courseId)) {
1784
            return array();
1785
        }
1786
1787
        $course_table = Database::get_main_table(TABLE_MAIN_COURSE);
1788
        $course_cat_table = Database::get_main_table(TABLE_MAIN_CATEGORY);
1789
        $sql = "SELECT
1790
                    course.*,
1791
                    course_category.code faCode,
1792
                    course_category.name faName
1793
                FROM $course_table
1794
                LEFT JOIN $course_cat_table
1795
                ON course.category_code = course_category.code
1796
                WHERE course.id = $courseId";
1797
        $result = Database::query($sql);
1798
        $courseInfo = array();
1799
        if (Database::num_rows($result) > 0) {
1800
            $data = Database::fetch_array($result);
1801
            $courseInfo = api_format_course_array($data);
1802
        }
1803
1804
        return $courseInfo;
1805
    }
1806
1807
    global $_course;
1808
    if ($_course == '-1') {
1809
        $_course = array();
1810
    }
1811
1812
    return $_course;
1813
}
1814
1815
/**
1816
 * Returns the current course info array.
1817
1818
 * Now if the course_code is given, the returned array gives info about that
1819
 * particular course, not specially the current one.
1820
 * @param int $id Numeric ID of the course
1821
 * @return array The course info as an array formatted by api_format_course_array, including category.name
1822
 */
1823 View Code Duplication
function api_get_course_info_by_id($id = null)
1824
{
1825
    if (!empty($id)) {
1826
        $id = intval($id);
1827
        $course_table = Database::get_main_table(TABLE_MAIN_COURSE);
1828
        $course_cat_table = Database::get_main_table(TABLE_MAIN_CATEGORY);
1829
        $sql = "SELECT
1830
                    course.*,
1831
                    course_category.code faCode,
1832
                    course_category.name faName
1833
                FROM $course_table
1834
                LEFT JOIN $course_cat_table
1835
                ON course.category_code =  course_category.code
1836
                WHERE course.id = $id";
1837
        $result = Database::query($sql);
1838
        $_course = array();
1839
        if (Database::num_rows($result) > 0) {
1840
            $course_data = Database::fetch_array($result);
1841
            $_course = api_format_course_array($course_data);
1842
        }
1843
        return $_course;
1844
    }
1845
1846
    global $_course;
1847
    if ($_course == '-1') $_course = array();
1848
    return $_course;
1849
}
1850
1851
/**
1852
 * Reformat the course array (output by api_get_course_info()) in order, mostly,
1853
 * to switch from 'code' to 'id' in the array. This is a legacy feature and is
1854
 * now possibly causing massive confusion as a new "id" field has been added to
1855
 * the course table in 1.9.0.
1856
 * @param $course_data
1857
 * @return array
1858
 * @todo eradicate the false "id"=code field of the $_course array and use the int id
1859
 */
1860
function api_format_course_array($course_data)
1861
{
1862
    if (empty($course_data)) {
1863
        return array();
1864
    }
1865
1866
    $_course = array();
1867
    $_course['id'] = $course_data['code'];
1868
    $_course['real_id'] = $course_data['id'];
1869
1870
    // Added
1871
    $_course['code'] = $course_data['code'];
1872
    $_course['name'] = $course_data['title'];
1873
    $_course['title'] = $course_data['title'];
1874
    $_course['official_code'] = $course_data['visual_code'];
1875
    $_course['visual_code'] = $course_data['visual_code'];
1876
    $_course['sysCode'] = $course_data['code'];
1877
    $_course['path'] = $course_data['directory']; // Use as key in path.
1878
    $_course['directory'] = $course_data['directory'];
1879
    $_course['creation_date'] = $course_data['creation_date'];
1880
    $_course['titular'] = $course_data['tutor_name'];
1881
    $_course['language'] = $course_data['course_language'];
1882
    $_course['extLink']['url'] = $course_data['department_url'];
1883
    $_course['extLink']['name'] = $course_data['department_name'];
1884
    $_course['categoryCode'] = $course_data['faCode'];
1885
    $_course['categoryName'] = $course_data['faName'];
1886
    $_course['visibility'] = $course_data['visibility'];
1887
    $_course['subscribe_allowed'] = $course_data['subscribe'];
1888
    $_course['subscribe'] = $course_data['subscribe'];
1889
    $_course['unsubscribe'] = $course_data['unsubscribe'];
1890
    $_course['course_language'] = $course_data['course_language'];
1891
    $_course['activate_legal'] = isset($course_data['activate_legal']) ? $course_data['activate_legal'] : false;
1892
    $_course['legal'] = $course_data['legal'];
1893
    $_course['show_score'] = $course_data['show_score']; //used in the work tool
1894
    $_course['department_name'] = $course_data['department_name'];
1895
    $_course['department_url'] = $course_data['department_url'];
1896
1897
    // Course password
1898
    $_course['registration_code'] = !empty($course_data['registration_code']) ? sha1($course_data['registration_code']) : null;
1899
    $_course['disk_quota'] = $course_data['disk_quota'];
1900
    $_course['course_public_url'] = api_get_path(WEB_COURSE_PATH).$course_data['directory'].'/index.php';
1901
1902
    if (array_key_exists('add_teachers_to_sessions_courses', $course_data)) {
1903
        $_course['add_teachers_to_sessions_courses'] = $course_data['add_teachers_to_sessions_courses'];
1904
    }
1905
1906
    if (file_exists(api_get_path(SYS_COURSE_PATH).$course_data['directory'].'/course-pic85x85.png')) {
1907
        $url_image = api_get_path(WEB_COURSE_PATH).$course_data['directory'].'/course-pic85x85.png';
1908
    } else {
1909
        $url_image = Display::return_icon('course.png', null, null, ICON_SIZE_BIG, null, true, false);
1910
    }
1911
    $_course['course_image'] = $url_image;
1912
1913
    if (file_exists(api_get_path(SYS_COURSE_PATH).$course_data['directory'].'/course-pic.png')) {
1914
        $url_image = api_get_path(WEB_COURSE_PATH).$course_data['directory'].'/course-pic.png';
1915
    } else {
1916
        $url_image = Display::returnIconPath('session_default.png');
1917
    }
1918
    $_course['course_image_large'] = $url_image;
1919
1920
    return $_course;
1921
}
1922
1923
/**
1924
 * Add a parameter to the existing URL. If this parameter already exists,
1925
 * just replace it with the new value
1926
 * @param   string  The URL
1927
 * @param   string  param=value string
1928
 * @param   boolean Whether to filter XSS or not
1929
 * @return  string  The URL with the added parameter
1930
 */
1931
function api_add_url_param($url, $param, $filter_xss = true) {
1932
    if (empty($param)) {
1933
        return $url;
1934
    }
1935
    if (strpos($url, '?') !== false) {
1936
        if ($param[0] != '&') {
1937
            $param = '&'.$param;
1938
        }
1939
        list (, $query_string) = explode('?', $url);
1940
        $param_list1 = explode('&', $param);
1941
        $param_list2 = explode('&', $query_string);
1942
        $param_list1_keys = $param_list1_vals = array();
1943
        foreach ($param_list1 as $key => $enreg) {
1944
            list ($param_list1_keys[$key], $param_list1_vals[$key]) = explode('=', $enreg);
1945
        }
1946
        $param_list1 = array ('keys' => $param_list1_keys, 'vals' => $param_list1_vals);
1947
        foreach ($param_list2 as $enreg) {
1948
            $enreg = explode('=', $enreg);
1949
            $key = array_search($enreg[0], $param_list1['keys']);
1950
            if (!is_null($key) && !is_bool($key)) {
1951
                $url = str_replace($enreg[0].'='.$enreg[1], $enreg[0].'='.$param_list1['vals'][$key], $url);
1952
                $param = str_replace('&'.$enreg[0].'='.$param_list1['vals'][$key], '', $param);
1953
            }
1954
        }
1955
        $url .= $param;
1956
    } else {
1957
        $url = $url.'?'.$param;
1958
    }
1959
    if ($filter_xss === true) {
1960
        $url = Security::remove_XSS(urldecode($url));
1961
    }
1962
    return $url;
1963
}
1964
1965
/**
1966
 * Returns a difficult to guess password.
1967
 * @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...
1968
 * @return string the generated password
1969
 */
1970
function api_generate_password($length = 8) {
1971
    $characters = 'abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ23456789';
1972
    if ($length < 2) {
1973
        $length = 2;
1974
    }
1975
    $password = '';
1976
    for ($i = 0; $i < $length; $i ++) {
1977
        $password .= $characters[rand() % strlen($characters)];
1978
    }
1979
    return $password;
1980
}
1981
1982
/**
1983
 * Checks a password to see wether it is OK to use.
1984
 * @param string $password
1985
 * @return boolean if the password is acceptable, false otherwise
1986
 * Notes about what a password "OK to use" is:
1987
 * 1. The password should be at least 5 characters long.
1988
 * 2. Only English letters (uppercase or lowercase, it doesn't matter) and digits are allowed.
1989
 * 3. The password should contain at least 3 letters.
1990
 * 4. It should contain at least 2 digits.
1991
 * 5. It should not contain 3 or more consequent (according to ASCII table) characters.
1992
 */
1993
function api_check_password($password) {
1994
    $password_length = api_strlen($password);
1995
    if ($password_length < 5) {
1996
        return false;
1997
    }
1998
    $password = api_strtolower($password);
1999
    $letters = 0;
2000
    $digits = 0;
2001
    $consequent_characters = 0;
2002
    $previous_character_code = 0;
2003
    for ($i = 0; $i < $password_length; $i ++) {
2004
        $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...
2005
        if ($i && abs($current_character_code - $previous_character_code) <= 1) {
2006
            $consequent_characters ++;
2007
            if ($consequent_characters == 3) {
2008
                return false;
2009
            }
2010
        } else {
2011
            $consequent_characters = 1;
2012
        }
2013
        if ($current_character_code >= 97 && $current_character_code <= 122) {
2014
            $letters ++;
2015
        } elseif ($current_character_code >= 48 && $current_character_code <= 57) {
2016
            $digits ++;
2017
        } else {
2018
            return false;
2019
        }
2020
        $previous_character_code = $current_character_code;
2021
    }
2022
    return ($letters >= 3 && $digits >= 2);
2023
}
2024
2025
/**
2026
 * Clears the user ID from the session if it was the anonymous user. Generally
2027
 * used on out-of-tools pages to remove a user ID that could otherwise be used
2028
 * in the wrong context.
2029
 * This function is to be used in conjunction with the api_set_anonymous()
2030
 * function to simulate the user existence in case of an anonymous visit.
2031
 * @param bool      database check switch - passed to api_is_anonymous()
2032
 * @return bool     true if succesfully unregistered, false if not anonymous.
2033
 */
2034
function api_clear_anonymous($db_check = false) {
2035
    global $_user;
2036
    if (api_is_anonymous($_user['user_id'], $db_check)) {
2037
        unset($_user['user_id']);
2038
        Session::erase('_uid');
2039
        return true;
2040
    }
2041
    return false;
2042
}
2043
2044
/**
2045
 * Returns the status string corresponding to the status code
2046
 * @author Noel Dieschburg
2047
 * @param the int status code
2048
 */
2049
function get_status_from_code($status_code) {
2050
    switch ($status_code) {
2051
        case STUDENT:
2052
            return get_lang('Student', '');
2053
        case TEACHER:
2054
            return get_lang('Teacher', '');
2055
        case COURSEMANAGER:
2056
            return get_lang('Manager', '');
2057
        case SESSIONADMIN:
2058
            return get_lang('SessionsAdmin', '');
2059
        case DRH:
2060
            return get_lang('Drh', '');
2061
    }
2062
}
2063
2064
/* FAILURE MANAGEMENT */
2065
2066
/**
2067
 * The Failure Management module is here to compensate
2068
 * the absence of an 'exception' device in PHP 4.
2069
 */
2070
2071
/**
2072
 * $api_failureList - array containing all the failure recorded in order of arrival.
2073
 */
2074
$api_failureList = array();
2075
2076
/**
2077
 * Fills a global array called $api_failureList
2078
 * This array collects all the failure occuring during the script runs
2079
 * The main purpose is allowing to manage the display messages externaly
2080
 * from the functions or objects. This strengthens encupsalation principle
2081
 *
2082
 * @author Hugues Peeters <[email protected]>
2083
 * @param  string $failure_type - the type of failure
2084
 * global: array $api_failureList
2085
 * @return boolean false to stay consistent with the main script
2086
 */
2087
function api_set_failure($failure_type) {
2088
    global $api_failureList;
2089
    $api_failureList[] = $failure_type;
2090
    return false;
2091
}
2092
2093
/**
2094
 * Sets the current user as anonymous if it hasn't been identified yet. This
2095
 * function should be used inside a tool only. The function api_clear_anonymous()
2096
 * acts in the opposite direction by clearing the anonymous user's data every
2097
 * time we get on a course homepage or on a neutral page (index, admin, my space)
2098
 * @return bool     true if set user as anonymous, false if user was already logged in or anonymous id could not be found
2099
 */
2100
function api_set_anonymous() {
2101
    global $_user;
2102
2103
    if (!empty($_user['user_id'])) {
2104
        return false;
2105
    }
2106
2107
    $user_id = api_get_anonymous_id();
2108
    if ($user_id == 0) {
2109
        return false;
2110
    }
2111
    Session::erase('_user');
2112
    $_user['user_id'] = $user_id;
2113
    $_user['is_anonymous'] = true;
2114
    $GLOBALS['_user'] = $_user;
2115
    Session::write('_user', $_user);
2116
    return true;
2117
}
2118
2119
/**
2120
 * Gets the last failure stored in $api_failureList;
2121
 *
2122
 * @author Hugues Peeters <[email protected]>
2123
 * @param void
2124
 * @return string - the last failure stored
2125
 */
2126
function api_get_last_failure() {
2127
    global $api_failureList;
2128
    return $api_failureList[count($api_failureList) - 1];
2129
}
2130
2131
/**
2132
 * Collects and manages failures occurring during script execution
2133
 * The main purpose is allowing to manage the display messages externally
2134
 * from functions or objects. This strengthens encapsulation principle
2135
 *
2136
 * @author Hugues Peeters <[email protected]>
2137
 * @package chamilo.library
2138
 */
2139
class api_failure {
2140
2141
    // TODO: $api_failureList to be hidden from global scope and to be renamed according to our coding conventions.
2142
    /**
2143
     * IMPLEMENTATION NOTE : For now the $api_failureList list is set to the
2144
     * global scope, as PHP 4 is unable to manage static variable in class. But
2145
     * this feature is awaited in PHP 5. The class is already written to minize
2146
     * the change when static class variable will be possible. And the API won't
2147
     * change.
2148
     */
2149
    public $api_failureList = array();
2150
2151
    /**
2152
     * Piles the last failure in the failure list
2153
     *
2154
     * @author Hugues Peeters <[email protected]>
2155
     * @param  string $failure_type - the type of failure
2156
     * @global array  $api_failureList
2157
     * @return boolean false to stay consistent with the main script
2158
     */
2159
    static function set_failure($failure_type) {
2160
        global $api_failureList;
2161
        $api_failureList[] = $failure_type;
2162
        return false;
2163
    }
2164
2165
    /**
2166
     * Gets the last failure stored
2167
     *
2168
     * @author Hugues Peeters <[email protected]>
2169
     * @param void
2170
     * @return string - the last failure stored
2171
     */
2172
    static function get_last_failure() {
2173
        global $api_failureList;
2174
        if (count($api_failureList) == 0) { return ''; }
2175
        return $api_failureList[count($api_failureList) - 1];
2176
    }
2177
}
2178
2179
2180
/* CONFIGURATION SETTINGS */
2181
2182
/**
2183
 * Gets the current Chamilo (not PHP/cookie) session ID
2184
 * @return  int     O if no active session, the session ID otherwise
2185
 */
2186
function api_get_session_id()
2187
{
2188
    return Session::read('id_session', 0);
2189
}
2190
2191
/**
2192
 * Gets the current Chamilo (not social network) group ID
2193
 * @return  int     O if no active session, the session ID otherwise
2194
 */
2195
function api_get_group_id()
2196
{
2197
    return Session::read('_gid', 0);
2198
}
2199
2200
2201
/**
2202
 * Gets the current or given session name
2203
 * @param   int     Session ID (optional)
2204
 * @return  string  The session name, or null if unfound
2205
 */
2206
function api_get_session_name($session_id) {
2207
    if (empty($session_id)) {
2208
        $session_id = api_get_session_id();
2209
        if (empty($session_id)) { return null; }
2210
    }
2211
    $t = Database::get_main_table(TABLE_MAIN_SESSION);
2212
    $s = "SELECT name FROM $t WHERE id = ".(int)$session_id;
2213
    $r = Database::query($s);
2214
    $c = Database::num_rows($r);
2215
    if ($c > 0) {
2216
        //technically, there can be only one, but anyway we take the first
2217
        $rec = Database::fetch_array($r);
2218
        return $rec['name'];
2219
    }
2220
    return null;
2221
}
2222
2223
/**
2224
 * Gets the session info by id
2225
 * @param int       Session ID
2226
 * @return array    information of the session
2227
 */
2228
function api_get_session_info($session_id)
2229
{
2230
    $data = array();
2231
    if (!empty($session_id)) {
2232
        $session_id = intval($session_id);
2233
        $tbl_session = Database::get_main_table(TABLE_MAIN_SESSION);
2234
        $sql = "SELECT * FROM $tbl_session WHERE id = $session_id";
2235
        $result = Database::query($sql);
2236
2237
        if (Database::num_rows($result)>0) {
2238
            $data = Database::fetch_array($result, 'ASSOC');
2239
        }
2240
    }
2241
2242
    return $data;
2243
}
2244
2245
/**
2246
 * Gets the session visibility by session id
2247
 * @param int $session_id
2248
 * @param int $courseId
2249
 * @param bool $ignore_visibility_for_admins
2250
 * @return int
2251
 *  0 = session still available,
2252
 *  SESSION_VISIBLE_READ_ONLY = 1,
2253
 *  SESSION_VISIBLE = 2,
2254
 *  SESSION_INVISIBLE = 3
2255
 */
2256
function api_get_session_visibility(
2257
    $session_id,
2258
    $courseId = null,
2259
    $ignore_visibility_for_admins = true
2260
) {
2261
    // Means that the session is still available.
2262
    $visibility = 0;
2263
2264
    if (api_is_platform_admin()) {
2265
        if ($ignore_visibility_for_admins) {
2266
            return SESSION_AVAILABLE;
2267
        }
2268
    }
2269
2270
    $now = time();
2271
    if (!empty($session_id)) {
2272
        $session_id = intval($session_id);
2273
        $tbl_session = Database::get_main_table(TABLE_MAIN_SESSION);
2274
2275
        $sql = "SELECT * FROM $tbl_session
2276
                WHERE id = $session_id ";
2277
2278
        $result = Database::query($sql);
2279
2280
        if (Database::num_rows($result) > 0) {
2281
            $row = Database::fetch_array($result, 'ASSOC');
2282
            $visibility = $original_visibility = $row['visibility'];
2283
2284
            // I don't care the session visibility.
2285
            if (empty($row['access_start_date']) && empty($row['access_end_date'])) {
2286
2287
                // Session duration per student.
2288
                if (isset($row['duration']) && !empty($row['duration'])) {
2289
                    $duration = $row['duration'] * 24 * 60 * 60;
2290
2291
                    $courseAccess = CourseManager::getFirstCourseAccessPerSessionAndUser(
2292
                        $session_id,
2293
                        api_get_user_id()
2294
                    );
2295
2296
                    // If there is a session duration but there is no previous
2297
                    // access by the user, then the session is still available
2298
                    if (count($courseAccess) == 0) {
2299
                        return SESSION_AVAILABLE;
2300
                    }
2301
2302
                    $currentTime = time();
2303
                    $firstAccess = 0;
2304
                    if (isset($courseAccess['login_course_date'])) {
2305
                        $firstAccess = api_strtotime(
2306
                            $courseAccess['login_course_date'],
2307
                            'UTC'
2308
                        );
2309
                    }
2310
                    $userDurationData = SessionManager::getUserSession(
2311
                        api_get_user_id(),
2312
                        $session_id
2313
                    );
2314
                    $userDuration = 0;
2315
                    if (isset($userDurationData['duration'])) {
2316
                        $userDuration = intval($userDurationData['duration']) * 24 * 60 * 60;
2317
                    }
2318
2319
                    $totalDuration = $firstAccess + $duration + $userDuration;
2320
                    if ($totalDuration > $currentTime) {
2321
                        return SESSION_AVAILABLE;
2322
                    } else {
2323
                        return SESSION_INVISIBLE;
2324
                    }
2325
                }
2326
2327
                return SESSION_AVAILABLE;
2328
            } else {
2329
2330
                // If start date was set.
2331
                if (!empty($row['access_start_date'])) {
2332
                    if ($now > api_strtotime($row['access_start_date'], 'UTC')) {
2333
                        $visibility = SESSION_AVAILABLE;
2334
                    } else {
2335
                        $visibility = SESSION_INVISIBLE;
2336
                    }
2337
                }
2338
2339
                // If the end date was set.
2340 View Code Duplication
                if (!empty($row['access_end_date'])) {
2341
                    // Only if date_start said that it was ok
2342
                    if ($visibility == SESSION_AVAILABLE) {
2343
                        if ($now < api_strtotime($row['access_end_date'], 'UTC')) {
2344
                            // Date still available
2345
                            $visibility = SESSION_AVAILABLE;
2346
                        } else {
2347
                            // Session ends
2348
                            $visibility = $row['visibility'];
2349
                        }
2350
                    }
2351
                }
2352
            }
2353
2354
            /* If I'm a coach the visibility can change in my favor depending in
2355
             the coach dates */
2356
            $is_coach = api_is_coach($session_id, $courseId);
2357
2358
            if ($is_coach) {
2359
                // Test end date.
2360 View Code Duplication
                if (!empty($row['coach_access_end_date'])) {
2361
                    $endDateCoach = api_strtotime($row['coach_access_end_date'], 'UTC');
2362
2363
                    if ($endDateCoach >= $now) {
2364
                        $visibility = SESSION_AVAILABLE;
2365
                    } else {
2366
                        $visibility = SESSION_INVISIBLE;
2367
                    }
2368
                }
2369
2370
                // Test start date.
2371 View Code Duplication
                if (!empty($row['coach_access_start_date'])) {
2372
                    $start = api_strtotime($row['coach_access_start_date'], 'UTC');
2373
                    if ($start < $now) {
2374
                        $visibility = SESSION_AVAILABLE;
2375
                    } else {
2376
                        $visibility = SESSION_INVISIBLE;
2377
                    }
2378
                }
2379
            }
2380
        } else {
2381
            $visibility = SESSION_INVISIBLE;
2382
        }
2383
    }
2384
2385
    return $visibility;
2386
}
2387
2388
/**
2389
 * This function returns a (star) session icon if the session is not null and
2390
 * the user is not a student
2391
 * @param int   $session_id
2392
 * @param int   $status_id User status id - if 5 (student), will return empty
2393
 * @return string   Session icon
2394
 */
2395
function api_get_session_image($session_id, $status_id)
2396
{
2397
    $session_id = (int)$session_id;
2398
    $session_img = '';
2399
    if ((int)$status_id != 5) { //check whether is not a student
2400
        if ($session_id > 0) {
2401
            $session_img = "&nbsp;&nbsp;".Display::return_icon(
2402
                'star.png',
2403
                get_lang('SessionSpecificResource'),
2404
                array('align' => 'absmiddle'),
2405
                ICON_SIZE_SMALL
2406
            );
2407
        }
2408
    }
2409
    return $session_img;
2410
}
2411
2412
/**
2413
 * This function add an additional condition according to the session of the course
2414
 * @param int       $session_id session id
2415
 * @param bool      $and optional, true if more than one condition false if the only condition in the query
2416
 * @param bool      $with_base_content optional, true to accept content with session=0 as well, false for strict session condition
2417
 * @return string   condition of the session
2418
 */
2419
function api_get_session_condition(
2420
    $session_id,
2421
    $and = true,
2422
    $with_base_content = false,
2423
    $session_field = "session_id"
2424
) {
2425
    $session_id = intval($session_id);
2426
2427
    if (empty($session_field)) {
2428
        $session_field = "session_id";
2429
    }
2430
    // Condition to show resources by session
2431
    $condition_add = $and ? " AND " : " WHERE ";
2432
2433
    if ($with_base_content) {
2434
        $condition_session = $condition_add." ( $session_field = $session_id OR $session_field = 0 OR $session_field IS NULL) ";
2435
    } else {
2436
        if (empty($session_id)) {
2437
            $condition_session = $condition_add." ($session_field = $session_id OR $session_field IS NULL)";
2438
        } else {
2439
            $condition_session = $condition_add." $session_field = $session_id ";
2440
        }
2441
    }
2442
    return $condition_session;
2443
}
2444
2445
/**
2446
 * This function returns information about coaches from a course in session
2447
 * @param int       optional, session id
2448
 * @param int $courseId
2449
 * @return array     array containing user_id, lastname, firstname, username
2450
 * @deprecated use CourseManager::get_coaches_from_course
2451
 */
2452
function api_get_coachs_from_course($session_id = 0, $courseId = '')
2453
{
2454
    if (!empty($session_id)) {
2455
        $session_id = intval($session_id);
2456
    } else {
2457
        $session_id = api_get_session_id();
2458
    }
2459
2460
    if (!empty($courseId)) {
2461
        $courseId = intval($courseId);
2462
    } else {
2463
        $courseId = api_get_course_int_id();
2464
    }
2465
2466
    $tbl_user = Database:: get_main_table(TABLE_MAIN_USER);
2467
    $tbl_session_course_user = Database:: get_main_table(TABLE_MAIN_SESSION_COURSE_USER);
2468
    $coaches = array();
2469
2470
    $sql = "SELECT
2471
                u.user_id,
2472
                u.lastname,
2473
                u.firstname,
2474
                u.username
2475
            FROM $tbl_user u, $tbl_session_course_user scu
2476
            WHERE
2477
              u.user_id = scu.user_id AND
2478
              scu.session_id = '$session_id' AND
2479
              scu.c_id = '$courseId' AND
2480
              scu.status = 2";
2481
    $rs = Database::query($sql);
2482
2483
    if (Database::num_rows($rs) > 0) {
2484
        while ($row = Database::fetch_array($rs)) {
2485
            $coaches[] = $row;
2486
        }
2487
2488
        return $coaches;
2489
    } else {
2490
2491
        return false;
2492
    }
2493
}
2494
2495
/**
2496
 * Returns the value of a setting from the web-adjustable admin config settings.
2497
 *
2498
 * WARNING true/false are stored as string, so when comparing you need to check e.g.
2499
 * if (api_get_setting('show_navigation_menu') == 'true') //CORRECT
2500
 * instead of
2501
 * if (api_get_setting('show_navigation_menu') == true) //INCORRECT
2502
 * @param string    $variable The variable name
2503
 * @param string    $key The subkey (sub-variable) if any. Defaults to NULL
2504
 * @author René Haentjens
2505
 * @author Bart Mollet
2506
 */
2507
function api_get_setting($variable, $key = null)
2508
{
2509
    global $_setting;
2510 View Code Duplication
    if ($variable == 'header_extra_content') {
2511
        $filename = api_get_path(SYS_PATH).api_get_home_path().'header_extra_content.txt';
2512
        if (file_exists($filename)) {
2513
            $value = file_get_contents($filename);
2514
            return $value ;
2515
        } else {
2516
            return '';
2517
        }
2518
    }
2519 View Code Duplication
    if ($variable == 'footer_extra_content') {
2520
        $filename = api_get_path(SYS_PATH).api_get_home_path().'footer_extra_content.txt';
2521
        if (file_exists($filename)) {
2522
            $value = file_get_contents($filename);
2523
            return $value ;
2524
        } else {
2525
            return '';
2526
        }
2527
    }
2528
    $value = null;
2529
    if (is_null($key)) {
2530
        $value = ((isset($_setting[$variable]) && $_setting[$variable] != '') ? $_setting[$variable] : null);
2531
    } else {
2532
        if (isset($_setting[$variable][$key])) {
2533
            $value = $_setting[$variable][$key];
2534
        }
2535
    }
2536
2537
    return $value;
2538
}
2539
2540
/**
2541
 * @param string $plugin
2542
 * @param string $variable
2543
 * @return string
2544
 */
2545
function api_get_plugin_setting($plugin, $variable)
2546
{
2547
    $variableName = $plugin.'_'.$variable;
2548
    $result = api_get_setting($variableName);
2549
    if (isset($result[$plugin])) {
2550
        return $result[$plugin];
2551
    }
2552
2553
    return null;
2554
}
2555
2556
/**
2557
 * Returns the value of a setting from the web-adjustable admin config settings.
2558
 **/
2559
function api_get_settings_params($params) {
2560
    $table = Database::get_main_table(TABLE_MAIN_SETTINGS_CURRENT);
2561
    $result = Database::select('*', $table, array('where' => $params));
2562
    return $result;
2563
}
2564
2565
function api_get_settings_params_simple($params) {
2566
    $table = Database::get_main_table(TABLE_MAIN_SETTINGS_CURRENT);
2567
    $result = Database::select('*', $table, array('where' => $params), 'one');
2568
    return $result;
2569
}
2570
2571
/**
2572
 * Returns the value of a setting from the web-adjustable admin config settings.
2573
 **/
2574
function api_delete_settings_params($params) {
2575
    $table = Database::get_main_table(TABLE_MAIN_SETTINGS_CURRENT);
2576
    $result = Database::delete($table, $params);
2577
    return $result;
2578
}
2579
2580
/**
2581
 * Returns an escaped version of $_SERVER['PHP_SELF'] to avoid XSS injection
2582
 * @return string   Escaped version of $_SERVER['PHP_SELF']
2583
 */
2584
function api_get_self() {
2585
    return htmlentities($_SERVER['PHP_SELF']);
2586
}
2587
2588
/* USER PERMISSIONS */
2589
2590
/**
2591
 * Checks whether current user is a platform administrator
2592
 * @param boolean Whether session admins should be considered admins or not
2593
 * @param boolean Whether HR directors should be considered admins or not
2594
 * @return boolean True if the user has platform admin rights,
2595
 * false otherwise.
2596
 * @see usermanager::is_admin(user_id) for a user-id specific function
2597
 */
2598
function api_is_platform_admin($allow_sessions_admins = false, $allow_drh = false)
2599
{
2600
    if (isset($_SESSION['is_platformAdmin']) && $_SESSION['is_platformAdmin']) {
2601
        return true;
2602
    }
2603
    $_user = api_get_user_info();
2604
    return
2605
        isset($_user['status']) &&
2606
        (
2607
            ($allow_sessions_admins && $_user['status'] == SESSIONADMIN) ||
2608
            ($allow_drh && $_user['status'] == DRH)
2609
        );
2610
}
2611
2612
/**
2613
 * Checks whether the user given as user id is in the admin table.
2614
 * @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...
2615
 * @param int $url URL ID. If provided, also check if the user is active on given URL
2616
 * @result bool True if the user is admin, false otherwise
2617
 */
2618
function api_is_platform_admin_by_id($user_id = null, $url = null)
2619
{
2620
    $user_id = intval($user_id);
2621
    if (empty($user_id)) {
2622
        $user_id = api_get_user_id();
2623
    }
2624
    $admin_table = Database::get_main_table(TABLE_MAIN_ADMIN);
2625
    $sql = "SELECT * FROM $admin_table WHERE user_id = $user_id";
2626
    $res = Database::query($sql);
2627
    $is_admin = Database::num_rows($res) === 1;
2628
    if (!$is_admin or !isset($url)) {
2629
        return $is_admin;
2630
    }
2631
    // We get here only if $url is set
2632
    $url = intval($url);
2633
    $url_user_table = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_USER);
2634
    $sql = "SELECT * FROM $url_user_table
2635
            WHERE access_url_id = $url AND user_id = $user_id";
2636
    $res = Database::query($sql);
2637
    $is_on_url = Database::num_rows($res) === 1;
2638
2639
    return $is_on_url;
2640
}
2641
2642
/**
2643
 * Returns the user's numeric status ID from the users table
2644
 * @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...
2645
 * @result int User's status (1 for teacher, 5 for student, etc)
2646
 */
2647
function api_get_user_status($user_id = null)
2648
{
2649
    $user_id = intval($user_id);
2650
    if (empty($user_id)) {
2651
        $user_id = api_get_user_id();
2652
    }
2653
    $table = Database::get_main_table(TABLE_MAIN_USER);
2654
    $sql = "SELECT status FROM $table WHERE user_id = $user_id ";
2655
    $result = Database::query($sql);
2656
    $status = null;
2657
    if (Database::num_rows($result)) {
2658
        $row = Database::fetch_array($result);
2659
        $status = $row['status'];
2660
    }
2661
    return $status;
2662
}
2663
2664
/**
2665
 * Checks whether current user is allowed to create courses
2666
 * @return boolean True if the user has course creation rights,
2667
 * false otherwise.
2668
 */
2669
function api_is_allowed_to_create_course() {
2670
    return Session::read('is_allowedCreateCourse');
2671
}
2672
2673
/**
2674
 * Checks whether the current user is a course administrator
2675
 * @return boolean True if current user is a course administrator
2676
 */
2677
function api_is_course_admin() {
2678
    if (api_is_platform_admin()) {
2679
        return true;
2680
    }
2681
    return Session::read('is_courseAdmin');
2682
}
2683
2684
/**
2685
 * Checks whether the current user is a course coach
2686
 * @return bool     True if current user is a course coach
2687
 */
2688
function api_is_course_coach() {
2689
    return Session::read('is_courseCoach');
2690
}
2691
2692
/**
2693
 * Checks whether the current user is a course tutor
2694
 * @return bool     True if current user is a course tutor
2695
 */
2696
function api_is_course_tutor() {
2697
    return Session::read('is_courseTutor');
2698
}
2699
2700
/**
2701
 * @param int $user_id
2702
 *
2703
 * @return array
2704
 */
2705
function api_get_user_platform_status($user_id = null) {
2706
    $status     = array();
2707
    $user_id    = intval($user_id);
2708
    if (empty($user_id)) {
2709
        $user_id = api_get_user_id();
2710
    }
2711
2712
    if (empty($user_id)) {
2713
        return false;
2714
    }
2715
    $group_id   = api_get_group_id();
2716
    $course_id  = api_get_course_int_id();
2717
    $course_code= api_get_course_id();
2718
    $session_id = api_get_session_id();
2719
2720
    //Group (in course)
2721
    if ($group_id && $course_id) {
2722
        $group_status = array();
2723
        $is_subscribed = GroupManager::is_subscribed($user_id, $group_id);
2724
        if ($is_subscribed) {
2725
            $group_status = array('id'=> $group_id , 'status' => 'student');
2726
            $is_tutor = GroupManager::is_tutor_of_group($user_id, $group_id);
2727
            if ($is_tutor) {
2728
                $group_status['status'] = 'tutor';
2729
            } else {
2730
                $group_status['status'] = 'student';
2731
            }
2732
        }
2733
        $status['group'] = $group_status;
2734
    }
2735
2736
    //Session
2737
    if ($session_id && $course_id) {
2738
        $session_status = array('id' => $session_id, 'course_id' => $course_id);
2739
        $session_user_status = SessionManager::get_user_status_in_course_session(
2740
            $user_id,
2741
            $course_id,
2742
            $session_id
2743
        );
2744
2745
        switch ($session_user_status) {
2746
            case 0:
2747
                $session_status['status'] = 'student';
2748
               break;
2749
            case 2:
2750
                $session_status['status'] = 'coach';
2751
            break;
2752
        }
2753
        $is_general_coach = SessionManager::user_is_general_coach($user_id, $session_id);
2754
        if ($is_general_coach) {
2755
            $session_status['status'] = 'general_coach';
2756
        }
2757
        $status['session'] = $session_status;
2758
2759
    } elseif($course_id) {
2760
        //Course
2761
        $course_status = array();
2762
        if ($course_id) {
2763
            $user_course_status = CourseManager::get_user_in_course_status($user_id, $course_code);
2764
2765
            if ($user_course_status) {
2766
                $course_status = array('id'=> $course_id);
2767
                switch($user_course_status) {
2768
                    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...
2769
                        $course_status['status'] = 'teacher';
2770
                    break;
2771
                    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...
2772
                        $course_status['status'] = 'student';
2773
                        //check if tutor
2774
                        $tutor_course_status = CourseManager::get_tutor_in_course_status($user_id, $course_code);
2775
                        if ($tutor_course_status) {
2776
                            $course_status['status'] = 'tutor';
2777
                        }
2778
                    break;
2779
                }
2780
            }
2781
        }
2782
        $status['course'] = $course_status;
2783
    }
2784
2785
    return $status;
2786
}
2787
2788
/**
2789
 * @param int $user_id
2790
 * @param int $courseId
2791
 * @param int $session_id
2792
 * @return bool
2793
 */
2794
function api_is_course_session_coach($user_id, $courseId, $session_id)
2795
{
2796
    $session_table = Database::get_main_table(TABLE_MAIN_SESSION);
2797
    $session_rel_course_rel_user_table  = Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER);
2798
2799
    $user_id = intval($user_id);
2800
    $session_id = intval($session_id);
2801
    $courseId = intval($courseId);
2802
2803
    $sql = "SELECT DISTINCT session.id
2804
            FROM $session_table
2805
            INNER JOIN $session_rel_course_rel_user_table session_rc_ru
2806
            ON session.id = session_rc_ru.session_id
2807
            WHERE
2808
                session_rc_ru.user_id = '".$user_id."'  AND
2809
                session_rc_ru.c_id = '$courseId' AND
2810
                session_rc_ru.status = 2 AND
2811
                session_rc_ru.session_id = '$session_id'";
2812
    $result = Database::query($sql);
2813
2814
    return Database::num_rows($result) > 0;
2815
}
2816
2817
/**
2818
 * Checks whether the current user is a course or session coach
2819
 * @param int $session_id
2820
 * @param int $courseId
2821
 * @param bool  Check whether we are in student view and, if we are, return false
2822
 * @return boolean True if current user is a course or session coach
2823
 */
2824
function api_is_coach($session_id = 0, $courseId = null, $check_student_view = true)
2825
{
2826
    $userId = api_get_user_id();
2827
2828
    if (!empty($session_id)) {
2829
        $session_id = intval($session_id);
2830
    } else {
2831
        $session_id = api_get_session_id();
2832
    }
2833
2834
    // The student preview was on
2835 View Code Duplication
    if ($check_student_view &&
2836
        isset($_SESSION['studentview']) && $_SESSION['studentview'] == "studentview"
2837
    ) {
2838
        return false;
2839
    }
2840
2841
    if (!empty($courseId)) {
2842
        $courseId = intval($courseId);
2843
    } else {
2844
        $courseId = api_get_course_int_id();
2845
    }
2846
2847
    $session_table = Database::get_main_table(TABLE_MAIN_SESSION);
2848
    $session_rel_course_rel_user_table = Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER);
2849
    $sessionIsCoach = null;
2850
2851
    if (!empty($courseId)) {
2852
        $sql = "SELECT DISTINCT s.id, name, access_start_date, access_end_date
2853
                FROM $session_table s
2854
                INNER JOIN $session_rel_course_rel_user_table session_rc_ru
2855
                ON session_rc_ru.session_id = s.id AND session_rc_ru.user_id = '".$userId."'
2856
                WHERE
2857
                    session_rc_ru.c_id = '$courseId' AND
2858
                    session_rc_ru.status = 2 AND
2859
                    session_rc_ru.session_id = '$session_id'";
2860
        $result = Database::query($sql);
2861
        $sessionIsCoach = Database::store_result($result);
2862
    }
2863
2864 View Code Duplication
    if (!empty($session_id)) {
2865
        $sql = "SELECT DISTINCT id, name, access_start_date, access_end_date
2866
                FROM $session_table
2867
                WHERE session.id_coach =  '".$userId."' AND id = '$session_id'
2868
                ORDER BY access_start_date, access_end_date, name";
2869
        $result = Database::query($sql);
2870
        if (!empty($sessionIsCoach)) {
2871
            $sessionIsCoach = array_merge($sessionIsCoach , Database::store_result($result));
2872
        } else {
2873
            $sessionIsCoach = Database::store_result($result);
2874
        }
2875
    }
2876
2877
    return (count($sessionIsCoach) > 0);
2878
}
2879
2880
/**
2881
 * Checks whether the current user is a session administrator
2882
 * @return boolean True if current user is a course administrator
2883
 */
2884
function api_is_session_admin()
2885
{
2886
    $user = api_get_user_info();
2887
    return isset($user['status']) && $user['status'] == SESSIONADMIN;
2888
}
2889
2890
/**
2891
 * Checks whether the current user is a human resources manager
2892
 * @return boolean True if current user is a human resources manager
2893
 */
2894
function api_is_drh()
2895
{
2896
    $user = api_get_user_info();
2897
    return isset($user['status']) && $user['status'] == DRH;
2898
}
2899
2900
/**
2901
 * Checks whether the current user is a student
2902
 * @return boolean True if current user is a human resources manager
2903
 */
2904
function api_is_student()
2905
{
2906
    $user = api_get_user_info();
2907
    return isset($user['status']) && $user['status'] == STUDENT;
2908
2909
}
2910
/**
2911
 * Checks whether the current user has the status 'teacher'
2912
 * @return boolean True if current user is a human resources manager
2913
 */
2914
function api_is_teacher()
2915
{
2916
    $user = api_get_user_info();
2917
    return isset($user['status']) && $user['status'] == COURSEMANAGER;
2918
}
2919
2920
/**
2921
 * Checks whether the current user is a invited user
2922
 * @return boolean
2923
 */
2924
function api_is_invitee()
2925
{
2926
    $user = api_get_user_info();
2927
2928
    return isset($user['status']) && $user['status'] == INVITEE;
2929
}
2930
2931
/**
2932
 * This function checks whether a session is assigned into a category
2933
 * @param int       - session id
2934
 * @param string    - category name
2935
 * @return bool     - true if is found, otherwise false
2936
 */
2937
function api_is_session_in_category($session_id, $category_name)
2938
{
2939
    $session_id = intval($session_id);
2940
    $category_name = Database::escape_string($category_name);
2941
2942
    $tbl_session = Database::get_main_table(TABLE_MAIN_SESSION);
2943
    $tbl_session_category = Database::get_main_table(TABLE_MAIN_SESSION_CATEGORY);
2944
2945
    $sql = "SELECT 1
2946
            FROM $tbl_session
2947
            WHERE $session_id IN (
2948
                SELECT s.id FROM $tbl_session s, $tbl_session_category sc
2949
                WHERE
2950
                  s.session_category_id = sc.id AND
2951
                  sc.name LIKE '%$category_name'
2952
            )";
2953
    $rs = Database::query($sql);
2954
2955
    if (Database::num_rows($rs) > 0) {
2956
        return true;
2957
    } else {
2958
        return false;
2959
    }
2960
}
2961
2962
/* DISPLAY OPTIONS
2963
   student view, title, message boxes,... */
2964
2965
/**
2966
 * Displays the title of a tool.
2967
 * Normal use: parameter is a string:
2968
 * api_display_tool_title("My Tool")
2969
 *
2970
 * Optionally, there can be a subtitle below
2971
 * the normal title, and / or a supra title above the normal title.
2972
 *
2973
 * e.g. supra title:
2974
 * group
2975
 * GROUP PROPERTIES
2976
 *
2977
 * e.g. subtitle:
2978
 * AGENDA
2979
 * calender & events tool
2980
 *
2981
 * @author Hugues Peeters <[email protected]>
2982
 * @param  mixed $title_element - it could either be a string or an array
2983
 *                               containing 'supraTitle', 'mainTitle',
2984
 *                               'subTitle'
2985
 * @return void
2986
 */
2987
function api_display_tool_title($title_element) {
2988
    if (is_string($title_element)) {
2989
        $tit = $title_element;
2990
        unset ($title_element);
2991
        $title_element['mainTitle'] = $tit;
2992
    }
2993
    echo '<h3>';
2994
    if (!empty($title_element['supraTitle'])) {
2995
        echo '<small>'.$title_element['supraTitle'].'</small><br />';
2996
    }
2997
    if (!empty($title_element['mainTitle'])) {
2998
        echo $title_element['mainTitle'];
2999
    }
3000
    if (!empty($title_element['subTitle'])) {
3001
        echo '<br /><small>'.$title_element['subTitle'].'</small>';
3002
    }
3003
    echo '</h3>';
3004
}
3005
3006
/**
3007
 * Displays options for switching between student view and course manager view
3008
 *
3009
 * Changes in version 1.2 (Patrick Cool)
3010
 * Student view switch now behaves as a real switch. It maintains its current state until the state
3011
 * is changed explicitly
3012
 *
3013
 * Changes in version 1.1 (Patrick Cool)
3014
 * student view now works correctly in subfolders of the document tool
3015
 * student view works correctly in the new links tool
3016
 *
3017
 * Example code for using this in your tools:
3018
 * //if ($is_courseAdmin && api_get_setting('student_view_enabled') == 'true') {
3019
 * //   display_tool_view_option($isStudentView);
3020
 * //}
3021
 * //and in later sections, use api_is_allowed_to_edit()
3022
 *
3023
 * @author Roan Embrechts
3024
 * @author Patrick Cool
3025
 * @author Julio Montoya, changes added in Chamilo
3026
 * @version 1.2
3027
 * @todo rewrite code so it is easier to understand
3028
 */
3029
function api_display_tool_view_option() {
3030
    if (api_get_setting('student_view_enabled') != 'true') {
3031
        return '';
3032
    }
3033
3034
    $sourceurl = '';
3035
    $is_framed = false;
3036
    // Exceptions apply for all multi-frames pages
3037
    if (strpos($_SERVER['REQUEST_URI'], 'chat/chat_banner.php') !== false) {
3038
        // The chat is a multiframe bit that doesn't work too well with the student_view, so do not show the link
3039
        return '';
3040
    }
3041
3042
    // Uncomment to remove student view link from document view page
3043
    if (strpos($_SERVER['REQUEST_URI'], 'newscorm/lp_header.php') !== false) {
3044
        if (empty($_GET['lp_id'])) {
3045
            return '';
3046
        }
3047
        $sourceurl = substr($_SERVER['REQUEST_URI'], 0, strpos($_SERVER['REQUEST_URI'], '?'));
3048
        $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);
3049
        //showinframes doesn't handle student view anyway...
3050
        //return '';
3051
        $is_framed = true;
3052
    }
3053
3054
    // Check whether the $_SERVER['REQUEST_URI'] contains already url parameters (thus a questionmark)
3055
    if (!$is_framed) {
3056
        if (strpos($_SERVER['REQUEST_URI'], '?') === false) {
3057
            $sourceurl = api_get_self().'?'.api_get_cidreq();
3058
        } else {
3059
            $sourceurl = $_SERVER['REQUEST_URI'];
3060
            //$sourceurl = str_replace('&', '&amp;', $sourceurl);
3061
        }
3062
    }
3063
3064
    $output_string = '';
3065
    if (!empty($_SESSION['studentview'])) {
3066
        if ($_SESSION['studentview'] == 'studentview') {
3067
            // We have to remove the isStudentView=true from the $sourceurl
3068
            $sourceurl = str_replace('&isStudentView=true', '', $sourceurl);
3069
            $sourceurl = str_replace('&isStudentView=false', '', $sourceurl);
3070
            $output_string .= '<a class="btn btn-success btn-xs" href="'.$sourceurl.'&isStudentView=false" target="_self">'.get_lang('SwitchToTeacherView').'</a>';
3071
        } elseif ($_SESSION['studentview'] == 'teacherview') {
3072
            // Switching to teacherview
3073
            $sourceurl = str_replace('&isStudentView=true', '', $sourceurl);
3074
            $sourceurl = str_replace('&isStudentView=false', '', $sourceurl);
3075
            $output_string .= '<a class="btn btn-primary btn-xs" href="'.$sourceurl.'&isStudentView=true" target="_self">'.get_lang('SwitchToStudentView').'</a>';
3076
        }
3077
    } else {
3078
        $output_string .= '<a class="btn btn-primary btn-xs" href="'.$sourceurl.'&isStudentView=true" target="_self">'.get_lang('SwitchToStudentView').'</a>';
3079
    }
3080
    return $output_string;
3081
}
3082
3083
// TODO: This is for the permission section.
3084
/**
3085
 * Function that removes the need to directly use is_courseAdmin global in
3086
 * tool scripts. It returns true or false depending on the user's rights in
3087
 * this particular course.
3088
 * Optionally checking for tutor and coach roles here allows us to use the
3089
 * student_view feature altogether with these roles as well.
3090
 * @param bool  Whether to check if the user has the tutor role
3091
 * @param bool  Whether to check if the user has the coach role
3092
 * @param bool  Whether to check if the user has the session coach role
3093
 * @param bool  check the student view or not
3094
 *
3095
 * @author Roan Embrechts
3096
 * @author Patrick Cool
3097
 * @author Julio Montoya
3098
 * @version 1.1, February 2004
3099
 * @return boolean, true: the user has the rights to edit, false: he does not
3100
 */
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...
3101
3102
function api_is_allowed_to_edit($tutor = false, $coach = false, $session_coach = false, $check_student_view = true)
3103
{
3104
    $my_session_id = api_get_session_id();
3105
    $is_allowed_coach_to_edit = api_is_coach(null, null, $check_student_view);
3106
    $session_visibility = api_get_session_visibility($my_session_id);
3107
3108
    // Admins can edit anything.
3109
    if (api_is_platform_admin(false)) {
3110
        //The student preview was on
3111 View Code Duplication
        if ($check_student_view &&
3112
            isset($_SESSION['studentview']) &&
3113
            $_SESSION['studentview'] == "studentview"
3114
        ) {
3115
            return false;
3116
        } else {
3117
            return true;
3118
        }
3119
    }
3120
3121
    $is_courseAdmin = api_is_course_admin();
3122
3123
    if (!$is_courseAdmin && $tutor) {
3124
        // If we also want to check if the user is a tutor...
3125
        $is_courseAdmin = $is_courseAdmin || api_is_course_tutor();
3126
    }
3127
3128
    if (!$is_courseAdmin && $coach) {
3129
        // If we also want to check if the user is a coach...';
3130
        // Check if session visibility is read only for coaches.
3131
        if ($session_visibility == SESSION_VISIBLE_READ_ONLY) {
3132
            $is_allowed_coach_to_edit = false;
3133
        }
3134
3135
        if (api_get_setting('allow_coach_to_edit_course_session') == 'true') {
3136
            // Check if coach is allowed to edit a course.
3137
            $is_courseAdmin = $is_courseAdmin || $is_allowed_coach_to_edit;
3138
        } else {
3139
            $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...
3140
        }
3141
    }
3142
3143
    if (!$is_courseAdmin && $session_coach) {
3144
        $is_courseAdmin = $is_courseAdmin || $is_allowed_coach_to_edit;
3145
    }
3146
3147
    // Check if the student_view is enabled, and if so, if it is activated.
3148
    if (api_get_setting('student_view_enabled') == 'true') {
3149
        if (!empty($my_session_id)) {
3150
            // Check if session visibility is read only for coaches.
3151
            if ($session_visibility == SESSION_VISIBLE_READ_ONLY) {
3152
                $is_allowed_coach_to_edit = false;
3153
            }
3154
3155
            if (api_get_setting('allow_coach_to_edit_course_session') == 'true') {
3156
                // Check if coach is allowed to edit a course.
3157
                $is_allowed = $is_allowed_coach_to_edit;
3158
            } else {
3159
                $is_allowed = false;
3160
            }
3161
            if ($check_student_view) {
3162
                $is_allowed = $is_allowed && $_SESSION['studentview'] != 'studentview';
3163
            }
3164
        } else {
3165
            if ($check_student_view) {
3166
                $is_allowed = $is_courseAdmin && $_SESSION['studentview'] != 'studentview';
3167
            } else {
3168
                $is_allowed = $is_courseAdmin;
3169
            }
3170
        }
3171
3172
        return $is_allowed;
3173
    } else {
3174
3175
        return $is_courseAdmin;
3176
    }
3177
}
3178
3179
/**
3180
 * @param int $sessionId
3181
 * @return bool
3182
 */
3183
function api_is_coach_of_course_in_session($sessionId)
3184
{
3185
    if (api_is_platform_admin()) {
3186
        return true;
3187
    }
3188
3189
    $userId = api_get_user_id();
3190
    $courseList = UserManager::get_courses_list_by_session(
3191
        $userId,
3192
        $sessionId
3193
    );
3194
3195
    // Session visibility.
3196
    $visibility = api_get_session_visibility(
3197
        $sessionId,
3198
        null,
3199
        false
3200
    );
3201
3202 View Code Duplication
    if ($visibility != SESSION_VISIBLE && !empty($courseList)) {
3203
        // Course Coach session visibility.
3204
        $blockedCourseCount = 0;
3205
        $closedVisibilityList = array(
3206
            COURSE_VISIBILITY_CLOSED,
3207
            COURSE_VISIBILITY_HIDDEN
3208
        );
3209
3210
        foreach ($courseList as $course) {
3211
            // Checking session visibility
3212
            $sessionCourseVisibility = api_get_session_visibility(
3213
                $sessionId,
3214
                $course['real_id'],
3215
                $ignore_visibility_for_admins
0 ignored issues
show
Bug introduced by
The variable $ignore_visibility_for_admins does not exist. Did you mean $visibility?

This check looks for variables that are accessed but have not been defined. It raises an issue if it finds another variable that has a similar name.

The variable may have been renamed without also renaming all references.

Loading history...
3216
            );
3217
3218
            $courseIsVisible = !in_array(
3219
                $course['visibility'],
3220
                $closedVisibilityList
3221
            );
3222
            if ($courseIsVisible === false || $sessionCourseVisibility == SESSION_INVISIBLE) {
3223
                $blockedCourseCount++;
3224
            }
3225
        }
3226
3227
        // If all courses are blocked then no show in the list.
3228
        if ($blockedCourseCount === count($courseList)) {
3229
            $visibility = SESSION_INVISIBLE;
3230
        } else {
3231
            $visibility = SESSION_VISIBLE;
3232
        }
3233
    }
3234
3235
    switch ($visibility) {
3236
        case SESSION_VISIBLE_READ_ONLY:
3237
        case SESSION_VISIBLE:
3238
        case SESSION_AVAILABLE:
3239
            return true;
3240
            break;
3241
        case SESSION_INVISIBLE:
3242
            return false;
3243
    }
3244
3245
    return false;
3246
}
3247
3248
/**
3249
* Checks if a student can edit contents in a session depending
3250
* on the session visibility
3251
* @param bool $tutor  Whether to check if the user has the tutor role
3252
* @param bool  $coach Whether to check if the user has the coach role
3253
* @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...
3254
*/
3255
function api_is_allowed_to_session_edit($tutor = false, $coach = false)
3256
{
3257
    if (api_is_allowed_to_edit($tutor, $coach)) {
3258
        // If I'm a teacher, I will return true in order to not affect the normal behaviour of Chamilo tools.
3259
        return true;
3260
    } else {
3261
        if (api_get_session_id() == 0) {
3262
            // I'm not in a session so i will return true to not affect the normal behaviour of Chamilo tools.
3263
            return true;
3264
        } else {
3265
            // I'm in a session and I'm a student
3266
            $session_id = api_get_session_id();
3267
3268
            // Get the session visibility
3269
            $session_visibility = api_get_session_visibility($session_id);
3270
3271
            switch ($session_visibility) {
3272
                case SESSION_VISIBLE_READ_ONLY: // 1
3273
                    return false;
3274
                case SESSION_VISIBLE:           // 2
3275
                    return true;
3276
                case SESSION_INVISIBLE:         // 3
3277
                    return false;
3278
                case SESSION_AVAILABLE:         //5
3279
                    return true;
3280
            }
3281
3282
        }
3283
    }
3284
}
3285
3286
/**
3287
* Checks whether the user is allowed in a specific tool for a specific action
3288
* @param string $tool the tool we are checking if the user has a certain permission
3289
* @param string $action the action we are checking (add, edit, delete, move, visibility)
3290
* @author Patrick Cool <[email protected]>, Ghent University
3291
* @author Julio Montoya
3292
* @version 1.0
3293
*/
3294
function api_is_allowed($tool, $action, $task_id = 0)
3295
{
3296
    $_user = api_get_user_info();
3297
    $_course = api_get_course_info();
3298
3299
    if (api_is_course_admin()) {
3300
        return true;
3301
    }
3302
    //if (!$_SESSION['total_permissions'][$_course['code']] and $_course)
3303
    if (is_array($_course) and count($_course) > 0) {
3304
        require_once api_get_path(SYS_CODE_PATH).'permissions/permissions_functions.inc.php';
3305
3306
        // Getting the permissions of this user.
3307
        if ($task_id == 0) {
3308
            $user_permissions = get_permissions('user', $_user['user_id']);
3309
            $_SESSION['total_permissions'][$_course['code']] = $user_permissions;
3310
        }
3311
3312
        // Getting the permissions of the task.
3313
        if ($task_id != 0) {
3314
            $task_permissions = get_permissions('task', $task_id);
3315
            /* !!! */$_SESSION['total_permissions'][$_course['code']] = $task_permissions;
3316
        }
3317
        //print_r($_SESSION['total_permissions']);
3318
3319
        // Getting the permissions of the groups of the user
3320
        //$groups_of_user = GroupManager::get_group_ids($_course['db_name'], $_user['user_id']);
3321
3322
        //foreach($groups_of_user as $group)
3323
        //   $this_group_permissions = get_permissions('group', $group);
3324
3325
        // Getting the permissions of the courseroles of the user
3326
        $user_courserole_permissions = get_roles_permissions('user', $_user['user_id']);
3327
3328
        // Getting the permissions of the platformroles of the user
3329
        //$user_platformrole_permissions = get_roles_permissions('user', $_user['user_id'], ', platform');
3330
3331
        // Getting the permissions of the roles of the groups of the user
3332
        //foreach($groups_of_user as $group)
3333
        //    $this_group_courserole_permissions = get_roles_permissions('group', $group);
3334
3335
        // Getting the permissions of the platformroles of the groups of the user
3336
        //foreach($groups_of_user as $group)
3337
        //    $this_group_platformrole_permissions = get_roles_permissions('group', $group, 'platform');
3338
    }
3339
3340
    // If the permissions are limited, we have to map the extended ones to the limited ones.
3341
    if (api_get_setting('permissions') == 'limited') {
3342
        if ($action == 'Visibility') {
3343
            $action = 'Edit';
3344
        }
3345
        if ($action == 'Move') {
3346
            $action = 'Edit';
3347
        }
3348
    }
3349
3350
    // The session that contains all the permissions already exists for this course
3351
    // so there is no need to requery everything.
3352
    //my_print_r($_SESSION['total_permissions'][$_course['code']][$tool]);
3353
    if (is_array($_SESSION['total_permissions'][$_course['code']][$tool])) {
3354
        if (in_array($action, $_SESSION['total_permissions'][$_course['code']][$tool])) {
3355
            return true;
3356
        } else {
3357
            return false;
3358
        }
3359
    }
3360
}
3361
3362
/**
3363
 * Tells whether this user is an anonymous user
3364
 * @param int  $user_id      User ID (optional, will take session ID if not provided)
3365
 * @param bool $db_check     Whether to check in the database (true) or simply in
3366
 * the session (false) to see if the current user is the anonymous user
3367
 * @return bool     true if this user is anonymous, false otherwise
3368
 */
3369
function api_is_anonymous($user_id = null, $db_check = false) {
3370
    if (!isset($user_id)) {
3371
        $user_id = api_get_user_id();
3372
    }
3373
    if ($db_check) {
3374
        $info = api_get_user_info($user_id);
3375
        if ($info['status'] == ANONYMOUS) {
3376
            return true;
3377
        }
3378
    }
3379
3380
    $_user = api_get_user_info();
3381
    if (isset($_user['status']) && $_user['status'] == ANONYMOUS) {
3382
        //if ($_user['user_id'] == 0) {
3383
        // In some cases, api_set_anonymous doesn't seem to be triggered in local.inc.php. Make sure it is.
3384
        // Occurs in agenda for admin links - YW
3385
        global $use_anonymous;
3386
        if (isset($use_anonymous) && $use_anonymous) {
3387
            api_set_anonymous();
3388
        }
3389
3390
        return true;
3391
    }
3392
3393
    return ((isset($_user['is_anonymous']) && $_user['is_anonymous'] === true) || $_user === false);
3394
}
3395
3396
/**
3397
 * Displays message "You are not allowed here..." and exits the entire script.
3398
 * @param bool   $print_headers    Whether or not to print headers (default = false -> does not print them)
3399
 * @param string $message
3400
 */
3401
function api_not_allowed($print_headers = false, $message = null)
3402
{
3403
    if (api_get_setting('sso_authentication') === 'true') {
3404
        global $osso;
3405
        if ($osso) {
3406
            $osso->logout();
3407
        }
3408
    }
3409
    $home_url = api_get_path(WEB_PATH);
3410
    $user_id = api_get_user_id();
3411
    $course = api_get_course_id();
3412
3413
    global $this_section;
3414
3415
    if (CustomPages::enabled() && !isset($user_id)) {
3416
3417
        if (empty($user_id)) {
3418
            // Why the CustomPages::enabled() need to be to set the request_uri
3419
            $_SESSION['request_uri'] = $_SERVER['REQUEST_URI'];
3420
        }
3421
3422
        CustomPages::display(CustomPages::INDEX_UNLOGGED);
3423
    }
3424
3425
    $origin = isset($_GET['origin']) ? $_GET['origin'] : '';
3426
3427
    $msg = null;
3428
    if (isset($message)) {
3429
        $msg = $message;
3430 View Code Duplication
    } else {
3431
        $msg = Display::return_message(
3432
            get_lang('NotAllowedClickBack').'<br/><br/><a href="'.$home_url.'">'.get_lang('ReturnToCourseHomepage').'</a>',
3433
            'error',
3434
            false
3435
        );
3436
    }
3437
3438
    $msg = Display::div($msg, array('align'=>'center'));
3439
3440
    $show_headers = 0;
3441
3442
    if ($print_headers && $origin != 'learnpath') {
3443
        $show_headers = 1;
3444
    }
3445
3446
    $tpl = new Template(null, $show_headers, $show_headers);
3447
    $tpl->assign('hide_login_link', 1);
3448
    $tpl->assign('content', $msg);
3449
3450
    if (($user_id != 0 && !api_is_anonymous()) &&
3451
        (!isset($course) || $course == -1) &&
3452
        empty($_GET['cidReq'])
3453
    ) {
3454
        // if the access is not authorized and there is some login information
3455
        // but the cidReq is not found, assume we are missing course data and send the user
3456
        // to the user_portal
3457
        $tpl->display_one_col_template();
3458
        exit;
3459
    }
3460
3461
    if (!empty($_SERVER['REQUEST_URI']) &&
3462
        (!empty($_GET['cidReq']) ||
3463
            $this_section == SECTION_MYPROFILE ||
3464
            $this_section == SECTION_PLATFORM_ADMIN
3465
        )
3466
    ) {
3467
        $courseCode = api_get_course_id();
3468
        // Only display form and return to the previous URL if there was a course ID included
3469
        if ($user_id != 0 && !api_is_anonymous()) {
3470
            //if there is a user ID, then the user is not allowed but the session is still there. Say so and exit
3471
            $tpl->assign('content', $msg);
3472
            $tpl->display_one_col_template();
3473
            exit;
3474
        }
3475
3476
        if (!is_null($courseCode)) {
3477
            api_set_firstpage_parameter($courseCode);
3478
        }
3479
3480
        // If the user has no user ID, then his session has expired
3481
        $action = api_get_self().'?'.Security::remove_XSS($_SERVER['QUERY_STRING']);
3482
        $action = str_replace('&amp;', '&', $action);
3483
        $form = new FormValidator(
3484
            'formLogin',
3485
            'post',
3486
            $action,
3487
            null,
3488
            array(),
3489
            FormValidator::LAYOUT_BOX_NO_LABEL
3490
        );
3491
        $form->addElement(
3492
            'text',
3493
            'login',
3494
            null,
3495
            array('placeholder' => get_lang('UserName'), 'autocapitalize' => 'none')
3496
        );
3497
        $form->addElement(
3498
            'password',
3499
            'password',
3500
            null,
3501
            array('placeholder' => get_lang('Password'), 'autocapitalize' => 'none')
3502
        );
3503
        $form->addButton('submitAuth', get_lang('LoginEnter'), '', 'primary');
3504
3505
        // see same text in auth/gotocourse.php and main_api.lib.php function api_not_allowed (above)
3506
        $content = Display::return_message(get_lang('NotAllowed'), 'error', false);
3507
3508
        if (!empty($courseCode)) {
3509
            $content .= '<h4>'.get_lang('LoginToGoToThisCourse').'</h4>';
3510
        }
3511
3512
        if (api_is_cas_activated()) {
3513
            $content .= Display::return_message(sprintf(get_lang('YouHaveAnInstitutionalAccount'), api_get_setting("Institution")), '', false);
3514
            $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'));
3515
            $content .= Display::return_message(get_lang('YouDontHaveAnInstitutionAccount'));
3516
            $content .= "<p style='text-align:center'><a href='#' onclick='$(this).parent().next().toggle()'>".get_lang('LoginWithExternalAccount')."</a></p>";
3517
            $content .= "<div style='display:none;'>";
3518
        }
3519
        $content .= '<div class="well_login">';
3520
        $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...
3521
        $content .='</div>';
3522
        if (api_is_cas_activated()) {
3523
            $content .= "</div>";
3524
        }
3525
3526
        if (!empty($courseCode)) {
3527
            $content .= '<hr/><p style="text-align:center"><a href="'.$home_url.'">'.
3528
                get_lang('ReturnToCourseHomepage').'</a></p>';
3529
        } else {
3530
            $content .= '<hr/><p style="text-align:center"><a href="'.$home_url.'">'.
3531
                get_lang('CampusHomepage').'</a></p>';
3532
        }
3533
3534
        $tpl->setLoginBodyClass();
3535
        $tpl->assign('content', $content);
3536
        $tpl->display_one_col_template();
3537
        exit;
3538
    }
3539
3540
    if ($user_id !=0 && !api_is_anonymous()) {
3541
        $tpl->display_one_col_template();
3542
        exit;
3543
    }
3544
3545
    $msg = null;
3546
3547
    // The session is over and we were not in a course,
3548
    // or we try to get directly to a private course without being logged
3549
    if (!is_null(api_get_course_int_id())) {
3550
        api_set_firstpage_parameter(api_get_course_id());
3551
        $tpl->setLoginBodyClass();
3552
        $action = api_get_self().'?'.Security::remove_XSS($_SERVER['QUERY_STRING']);
3553
        $action = str_replace('&amp;', '&', $action);
3554
        $form = new FormValidator('formLogin', 'post', $action, null, array('class'=>'form-stacked'));
3555
        $form->addElement('text', 'login', null, array('autocapitalize' => 'none', 'placeholder' => get_lang('UserName'), 'class' => 'col-md-3'));
3556
        $form->addElement('password', 'password', null, array('placeholder' => get_lang('Password'), 'class' => 'col-md-3')); //new
3557
        $form->addButtonNext(get_lang('LoginEnter'), 'submitAuth');
3558
3559
        // see same text in auth/gotocourse.php and main_api.lib.php function api_not_allowed (bellow)
3560
        $msg = Display::return_message(get_lang('NotAllowed'), 'error', false);
3561
        $msg .= '<h4>'.get_lang('LoginToGoToThisCourse').'</h4>';
3562
        if (api_is_cas_activated()) {
3563
            $msg .= Display::return_message(sprintf(get_lang('YouHaveAnInstitutionalAccount'), api_get_setting("Institution")), '', false);
3564
            $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'));
3565
            $msg .= Display::return_message(get_lang('YouDontHaveAnInstitutionAccount'));
3566
            $msg .= "<p style='text-align:center'><a href='#' onclick='$(this).parent().next().toggle()'>".get_lang('LoginWithExternalAccount')."</a></p>";
3567
            $msg .= "<div style='display:none;'>";
3568
        }
3569
        $msg .= '<div class="well">';
3570
        $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...
3571
        $msg .='</div>';
3572
        if (api_is_cas_activated()) {
3573
            $msg .= "</div>";
3574
        }
3575
        $msg .= '<hr/><p style="text-align:center"><a href="'.$home_url.'">'.get_lang('ReturnToCourseHomepage').'</a></p>';
3576 View Code Duplication
    } else {
3577
        // we were not in a course, return to home page
3578
        $msg = Display::return_message(
3579
            get_lang('NotAllowed').'<br/><br/><a href="'.$home_url.'">'.get_lang('ReturnToCourseHomepage').'</a><br />',
3580
            'error',
3581
            false
3582
        );
3583
    }
3584
3585
    $tpl->assign('content', $msg);
3586
    $tpl->display_one_col_template();
3587
    exit;
3588
}
3589
3590
3591
/* WHAT'S NEW
3592
   functions for the what's new icons
3593
   in the user course list */
3594
3595
/**
3596
 * Gets a UNIX timestamp from a database (MySQL) datetime format string
3597
 * @param $last_post_datetime standard output date in a sql query
3598
 * @return integer timestamp
3599
 * @author Toon Van Hoecke <[email protected]>
3600
 * @version October 2003
3601
 * @desc convert sql date to unix timestamp
3602
 */
3603
function convert_sql_date($last_post_datetime) {
3604
    list ($last_post_date, $last_post_time) = explode(' ', $last_post_datetime);
3605
    list ($year, $month, $day) = explode('-', $last_post_date);
3606
    list ($hour, $min, $sec) = explode(':', $last_post_time);
3607
    return mktime((int)$hour, (int)$min, (int)$sec, (int)$month, (int)$day, (int)$year);
3608
}
3609
3610
/**
3611
 * Gets a database (MySQL) datetime format string from a UNIX timestamp
3612
 * @param   int     UNIX timestamp, as generated by the time() function. Will be generated if parameter not provided
3613
 * @return  string  MySQL datetime format, like '2009-01-30 12:23:34'
3614
 */
3615
function api_get_datetime($time = null) {
3616
    if (!isset($time)) { $time = time(); }
3617
    return date('Y-m-d H:i:s', $time);
3618
}
3619
3620
/**
3621
 * Gets item visibility from the item_property table
3622
 *
3623
 * Getting the visibility is done by getting the last updated visibility entry,
3624
 * using the largest session ID found if session 0 and another was found (meaning
3625
 * the only one that is actually from the session, in case there are results from
3626
 * session 0 *AND* session n).
3627
 * @param array     Course properties array (result of api_get_course_info())
3628
 * @param string    Tool (learnpath, document, etc)
3629
 * @param int       The item ID in the given tool
3630
 * @param int       The session ID (optional)
3631
 * @param string $tool
3632
 * @param integer $user_id
3633
 * @param string $type
3634
 * @return int      -1 on error, 0 if invisible, 1 if visible
3635
 */
3636
function api_get_item_visibility(
3637
    $_course,
3638
    $tool,
3639
    $id,
3640
    $session = 0,
3641
    $user_id = null,
3642
    $type = null,
3643
    $group_id = null
3644
) {
3645
    if (!is_array($_course) || count($_course) == 0 || empty($tool) || empty($id)) {
3646
        return -1;
3647
    }
3648
3649
    $tool = Database::escape_string($tool);
3650
    $id = intval($id);
3651
    $session = (int) $session;
3652
    $TABLE_ITEMPROPERTY = Database::get_course_table(TABLE_ITEM_PROPERTY);
3653
    $course_id = intval($_course['real_id']);
3654
3655
    $userCondition = '';
3656
    if (!empty($user_id)) {
3657
        $user_id = intval($user_id);
3658
        $userCondition = " AND to_user_id = $user_id ";
3659
    }
3660
3661
    $typeCondition = '';
3662
    if (!empty($type)) {
3663
        $type = Database::escape_string($type);
3664
        $typeCondition = " AND lastedit_type = '$type' ";
3665
    }
3666
3667
    $groupCondition = '';
3668
    if (!empty($group_id)) {
3669
        $group_id = intval($group_id);
3670
        $groupCondition = " AND to_group_id = '$group_id' ";
3671
    }
3672
3673
    $sql = "SELECT visibility
3674
            FROM $TABLE_ITEMPROPERTY
3675
            WHERE
3676
                c_id = $course_id AND
3677
                tool = '$tool' AND
3678
                ref = $id AND
3679
                (session_id = $session OR session_id = 0 OR session_id IS NULL)
3680
                $userCondition $typeCondition $groupCondition
3681
            ORDER BY session_id DESC, lastedit_date DESC
3682
            LIMIT 1";
3683
3684
    $res = Database::query($sql);
3685
    if ($res === false || Database::num_rows($res) == 0) {
3686
        return -1;
3687
    }
3688
    $row = Database::fetch_array($res);
3689
3690
    return $row['visibility'];
3691
}
3692
3693
/**
3694
 * Delete a row in the c_item_property table
3695
 *
3696
 * @param array $courseInfo
3697
 * @param string $tool
3698
 * @param int $itemId
3699
 * @param int $userId
3700
 * @param int $groupId
3701
 * @param int $sessionId
3702
 * @return false|null
3703
 */
3704
function api_item_property_delete(
3705
    $courseInfo,
3706
    $tool,
3707
    $itemId,
3708
    $userId,
3709
    $groupId = 0,
3710
    $sessionId = 0
3711
) {
3712
    if (empty($courseInfo)) {
3713
        return false;
3714
    }
3715
3716
    $courseId = intval($courseInfo['real_id']);
3717
3718
    if (empty($courseId) || empty($tool) || empty($itemId)) {
3719
        return false;
3720
    }
3721
3722
    $table = Database::get_course_table(TABLE_ITEM_PROPERTY);
3723
    $tool = Database::escape_string($tool);
3724
    $itemId = intval($itemId);
3725
    $userId = intval($userId);
3726
    $groupId = intval($groupId);
3727
    $sessionId = intval($sessionId);
3728
3729
    $groupCondition = " AND to_group_id = $groupId ";
3730
    if (empty($groupId)) {
3731
        $groupCondition = " AND (to_group_id is NULL OR to_group_id = 0) ";
3732
    }
3733
3734
    $userCondition = " AND to_user_id = $userId ";
3735
    if (empty($userId)) {
3736
        $userCondition = " AND (to_user_id is NULL OR to_user_id = 0) ";
3737
    }
3738
    $sql = "DELETE FROM $table
3739
            WHERE
3740
                c_id = $courseId AND
3741
                tool  = '$tool' AND
3742
                ref = $itemId AND
3743
                session_id = $sessionId
3744
                $userCondition
3745
                $groupCondition
3746
            ";
3747
    Database::query($sql);
3748
}
3749
3750
/**
3751
 * Updates or adds item properties to the Item_propetry table
3752
 * Tool and lastedit_type are language independant strings (langvars->get_lang!)
3753
 *
3754
 * @param array $_course array with course properties
3755
 * @param string $tool tool id, linked to 'rubrique' of the course tool_list (Warning: language sensitive !!)
3756
 * @param int $item_id id of the item itself, linked to key of every tool ('id', ...), "*" = all items of the tool
3757
 * @param string $last_edit_type add or update action
3758
 * (1) message to be translated (in trad4all) : e.g. DocumentAdded, DocumentUpdated;
3759
 * (2) "delete"
3760
 * (3) "visible"
3761
 * (4) "invisible"
3762
 * @param int $user_id : id of the editing/adding user
3763
 * @param int $to_group_id : id of the intended group (0 = for everybody), only relevant for $type (1)
3764
 * @param int $to_user_id : id of the intended user (always has priority over $to_group_id !), only relevant for $type (1)
3765
 * @param string $start_visible 0000-00-00 00:00:00 format
3766
 * @param string $end_visible 0000-00-00 00:00:00 format
3767
 * @param int $session_id The session ID, if any, otherwise will default to 0
3768
 * @return boolean False if update fails.
3769
 * @author Toon Van Hoecke <[email protected]>, Ghent University
3770
 * @version January 2005
3771
 * @desc update the item_properties table (if entry not exists, insert) of the course
3772
 */
3773
function api_item_property_update(
3774
    $_course,
3775
    $tool,
3776
    $item_id,
3777
    $last_edit_type,
3778
    $user_id,
3779
    $to_group_id = 0,
3780
    $to_user_id = null,
3781
    $start_visible = '',
3782
    $end_visible = '',
3783
    $session_id = 0
3784
) {
3785
    if (empty($_course)) {
3786
        return false;
3787
    }
3788
3789
    $course_id = $_course['real_id'];
3790
3791
    if (empty($course_id)) {
3792
        return false;
3793
    }
3794
3795
    // Definition of variables.
3796
    $tool = Database::escape_string($tool);
3797
    $item_id = intval($item_id);
3798
    $lastEditTypeNoFilter = $last_edit_type;
3799
    $last_edit_type = Database::escape_string($last_edit_type);
3800
    $user_id = intval($user_id);
3801
3802
    $startVisible = "NULL";
3803
    if (!empty($start_visible)) {
3804
        $start_visible = Database::escape_string($start_visible);
3805
        $startVisible = "'$start_visible'";
3806
    }
3807
3808
    $endVisible = "NULL";
3809
    if (!empty($end_visible)) {
3810
        $end_visible = Database::escape_string($end_visible);
3811
        $endVisible = "'$end_visible'";
3812
    }
3813
3814
    $to_filter = '';
3815
    $time = api_get_utc_datetime();
3816
3817
    if (!empty($session_id)) {
3818
        $session_id = intval($session_id);
3819
    } else {
3820
        $session_id = api_get_session_id();
3821
    }
3822
3823
    // Definition of tables.
3824
    $tableItemProperty = Database::get_course_table(TABLE_ITEM_PROPERTY);
3825
3826
    if ($to_user_id <= 0) {
3827
        $to_user_id = null; // No to_user_id set
3828
    }
3829
3830
    if (!is_null($to_user_id)) {
3831
        // $to_user_id has more priority than $to_group_id
3832
        $to_user_id = intval($to_user_id);
3833
        $to_field = 'to_user_id';
3834
        $to_value = $to_user_id;
3835
    } else {
3836
        // $to_user_id is not set.
3837
        $to_field = 'to_group_id';
3838
        $to_value = $to_group_id;
3839
    }
3840
3841
    $toValueCondition = empty($to_value) ? "NULL" : "'$to_value'";
3842
3843
    // Set filters for $to_user_id and $to_group_id, with priority for $to_user_id
3844
    $condition_session = " AND session_id = $session_id ";
3845
    if (empty($session_id)) {
3846
        $condition_session = " AND (session_id = 0 OR session_id IS NULL) ";
3847
    }
3848
3849
    $filter = " c_id = $course_id AND tool = '$tool' AND ref = $item_id $condition_session ";
3850
3851
    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...
3852
        // For all (not deleted) items of the tool
3853
        $filter = " c_id = $course_id  AND tool = '$tool' AND visibility <> 2 $condition_session";
3854
    }
3855
3856
    // Check whether $to_user_id and $to_group_id are passed in the function call.
3857
    // If both are not passed (both are null) then it is a message for everybody and $to_group_id should be 0 !
3858
    if (is_null($to_user_id) && is_null($to_group_id)) {
3859
        $to_group_id = 0;
3860
    }
3861
3862
    if (!is_null($to_user_id)) {
3863
        // Set filter to intended user.
3864
        $to_filter = " AND to_user_id = $to_user_id $condition_session";
3865
    } else {
3866
        // Set filter to intended group.
3867
        if (($to_group_id != 0) && $to_group_id == strval(intval($to_group_id))) {
3868
            $to_filter = " AND to_group_id = $to_group_id $condition_session";
3869
        }
3870
    }
3871
3872
    // Adding filter if set.
3873
    $filter .= $to_filter;
3874
3875
    // Update if possible
3876
    $set_type = '';
3877
3878
    switch ($lastEditTypeNoFilter) {
3879 View Code Duplication
        case 'delete':
3880
            // delete = make item only visible for the platform admin.
3881
            $visibility = '2';
3882
            if (!empty($session_id)) {
3883
                // Check whether session id already exist into item_properties for updating visibility or add it.
3884
                $sql = "SELECT session_id FROM $tableItemProperty
3885
                        WHERE
3886
                            c_id = $course_id AND
3887
                            tool = '$tool' AND
3888
                            ref = $item_id AND
3889
                            session_id = $session_id";
3890
                $rs = Database::query($sql);
3891
                if (Database::num_rows($rs) > 0) {
3892
                    $sql = "UPDATE $tableItemProperty
3893
                            SET lastedit_type       = '".str_replace('_', '', ucwords($tool))."Deleted',
3894
                                lastedit_date       = '$time',
3895
                                lastedit_user_id    = $user_id,
3896
                                visibility          = $visibility,
3897
                                session_id          = $session_id $set_type
3898
                            WHERE $filter";
3899
                    $result = Database::query($sql);
3900
                } else {
3901
                    $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)
3902
                            VALUES ($course_id, '$tool',$item_id, '$time', $user_id, '$time', '$last_edit_type',$user_id, $toValueCondition, $visibility, $startVisible, $endVisible, $session_id)";
3903
                    $result = Database::query($sql);
3904
                    $id = Database::insert_id();
3905
                    if ($id) {
3906
                        $sql = "UPDATE $tableItemProperty SET id = iid WHERE iid = $id";
3907
                        Database::query($sql);
3908
                    }
3909
                }
3910
            } else {
3911
                $sql = "UPDATE $tableItemProperty
3912
                        SET
3913
                            lastedit_type='".str_replace('_', '', ucwords($tool))."Deleted',
3914
                            lastedit_date='$time',
3915
                            lastedit_user_id = $user_id,
3916
                            visibility = $visibility $set_type
3917
                        WHERE $filter";
3918
                $result = Database::query($sql);
3919
            }
3920
            break;
3921 View Code Duplication
        case 'visible' : // Change item to visible.
3922
            $visibility = '1';
3923
            if (!empty($session_id)) {
3924
                // Check whether session id already exist into item_properties for updating visibility or add it.
3925
                $sql = "SELECT session_id FROM $tableItemProperty
3926
                        WHERE
3927
                            c_id = $course_id AND
3928
                            tool = '$tool' AND
3929
                            ref = $item_id AND
3930
                            session_id = $session_id";
3931
                $rs = Database::query($sql);
3932
                if (Database::num_rows($rs) > 0) {
3933
                    $sql = "UPDATE $tableItemProperty
3934
                            SET
3935
                                lastedit_type='".str_replace('_', '', ucwords($tool))."Visible',
3936
                                lastedit_date='$time',
3937
                                lastedit_user_id = $user_id,
3938
                                visibility = $visibility,
3939
                                session_id = $session_id $set_type
3940
                            WHERE $filter";
3941
                    $result = Database::query($sql);
3942
                } else {
3943
                    $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)
3944
                            VALUES ($course_id, '$tool', $item_id, '$time', $user_id, '$time', '$last_edit_type', $user_id, $toValueCondition, $visibility, $startVisible, $endVisible, $session_id)";
3945
                    $result = Database::query($sql);
3946
                    $id = Database::insert_id();
3947
                    if ($id) {
3948
                        $sql = "UPDATE $tableItemProperty SET id = iid WHERE iid = $id";
3949
                        Database::query($sql);
3950
                    }
3951
                }
3952
            } else {
3953
                $sql = "UPDATE $tableItemProperty
3954
                        SET
3955
                            lastedit_type='".str_replace('_', '', ucwords($tool))."Visible',
3956
                            lastedit_date='$time',
3957
                            lastedit_user_id = $user_id,
3958
                            visibility = $visibility $set_type
3959
                        WHERE $filter";
3960
                $result = Database::query($sql);
3961
            }
3962
            break;
3963 View Code Duplication
        case 'invisible' : // Change item to invisible.
3964
            $visibility = '0';
3965
            if (!empty($session_id)) {
3966
                // Check whether session id already exist into item_properties for updating visibility or add it
3967
                $sql = "SELECT session_id FROM $tableItemProperty
3968
                        WHERE
3969
                            c_id = $course_id AND
3970
                            tool = '$tool' AND
3971
                            ref = $item_id AND
3972
                            session_id = $session_id";
3973
                $rs = Database::query($sql);
3974
                if (Database::num_rows($rs) > 0) {
3975
                    $sql = "UPDATE $tableItemProperty
3976
                            SET
3977
                                lastedit_type = '".str_replace('_', '', ucwords($tool))."Invisible',
3978
                                lastedit_date = '$time',
3979
                                lastedit_user_id = $user_id,
3980
                                visibility = $visibility,
3981
                                session_id = $session_id $set_type
3982
                            WHERE $filter";
3983
                    $result = Database::query($sql);
3984
                } else {
3985
                    $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)
3986
                            VALUES ($course_id, '$tool', $item_id, '$time', $user_id, '$time', '$last_edit_type', $user_id, $toValueCondition, $visibility, $startVisible, $endVisible, $session_id)";
3987
                    $result = Database::query($sql);
3988
                    $id = Database::insert_id();
3989
                    if ($id) {
3990
                        $sql = "UPDATE $tableItemProperty SET id = iid WHERE iid = $id";
3991
                        Database::query($sql);
3992
                    }
3993
                }
3994
            } else {
3995
                $sql = "UPDATE $tableItemProperty
3996
                        SET
3997
                            lastedit_type = '".str_replace('_', '', ucwords($tool))."Invisible',
3998
                            lastedit_date = '$time',
3999
                            lastedit_user_id = $user_id,
4000
                            visibility = $visibility $set_type
4001
                        WHERE $filter";
4002
                $result = Database::query($sql);
4003
            }
4004
            break;
4005
        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...
4006
            $set_type = ", lastedit_type = '$last_edit_type' ";
4007
            $visibility = '1';
4008
            //$filter .= $to_filter; already added
4009
            $sql = "UPDATE $tableItemProperty
4010
                    SET
4011
                      lastedit_date = '$time',
4012
                      lastedit_user_id = $user_id $set_type
4013
                    WHERE $filter";
4014
            $result = Database::query($sql);
4015
    }
4016
4017
    // Insert if no entries are found (can only happen in case of $last_edit_type switch is 'default').
4018
    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...
4019
        $sessionCondition = empty($session_id) ? "NULL" : "'$session_id'";
4020
        $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)
4021
                VALUES ($course_id, '$tool', $item_id, '$time', $user_id, '$time', '$last_edit_type', $user_id, $toValueCondition, $visibility, $startVisible, $endVisible, $sessionCondition)";
4022
        Database::query($sql);
4023
        $id = Database::insert_id();
4024
        if ($id) {
4025
            $sql = "UPDATE $tableItemProperty SET id = iid WHERE iid = $id";
4026
            Database::query($sql);
4027
            return false;
4028
        }
4029
    }
4030
4031
    return true;
4032
}
4033
4034
/**
4035
 * Gets item property by tool
4036
 * @param string    course code
4037
 * @param string    tool name, linked to 'rubrique' of the course tool_list (Warning: language sensitive !!)
4038
 * @param int       id of the item itself, linked to key of every tool ('id', ...), "*" = all items of the tool
4039
 * @param int $session_id
4040
 * @param string $tool
4041
 * @param string $course_code
4042
 * @return array All fields from c_item_property (all rows found) or empty array
4043
 */
4044
function api_get_item_property_by_tool($tool, $course_code, $session_id = null)
4045
{
4046
    $course_info = api_get_course_info($course_code);
4047
    $tool = Database::escape_string($tool);
4048
4049
    // Definition of tables.
4050
    $item_property_table = Database::get_course_table(TABLE_ITEM_PROPERTY);
4051
    $session_id = intval($session_id);
4052
    $session_condition = ' AND session_id = '.$session_id;
4053
    if (empty($session_id)) {
4054
        $session_condition = " AND (session_id = 0 OR session_id IS NULL) ";
4055
    }
4056
    $course_id = $course_info['real_id'];
4057
4058
    $sql = "SELECT * FROM $item_property_table
4059
            WHERE
4060
                c_id = $course_id AND
4061
                tool = '$tool'
4062
                $session_condition ";
4063
    $rs  = Database::query($sql);
4064
    $list = array();
4065
    if (Database::num_rows($rs) > 0) {
4066
        while ($row = Database::fetch_array($rs, 'ASSOC')) {
4067
            $list[] = $row;
4068
        }
4069
    }
4070
    return $list;
4071
}
4072
4073
/**
4074
 * Gets item property by tool and user
4075
 * @param int $userId
4076
 * @param int $tool
4077
 * @param int $courseId
4078
 * @param int $session_id
4079
 * @return array
4080
 */
4081
function api_get_item_property_list_by_tool_by_user(
4082
    $userId,
4083
    $tool,
4084
    $courseId,
4085
    $session_id = 0
4086
) {
4087
    $userId = intval($userId);
4088
    $tool = Database::escape_string($tool);
4089
    $session_id = intval($session_id);
4090
    $courseId = intval($courseId);
4091
4092
    // Definition of tables.
4093
    $item_property_table = Database::get_course_table(TABLE_ITEM_PROPERTY);
4094
    $session_condition = ' AND session_id = '.$session_id;
4095
    if (empty($session_id)) {
4096
        $session_condition = " AND (session_id = 0 OR session_id IS NULL) ";
4097
    }
4098
    $sql = "SELECT * FROM $item_property_table
4099
            WHERE
4100
                insert_user_id = $userId AND
4101
                c_id = $courseId AND
4102
                tool = '$tool'
4103
                $session_condition ";
4104
4105
    $rs = Database::query($sql);
4106
    $list = array();
4107
    if (Database::num_rows($rs) > 0) {
4108
        while ($row = Database::fetch_array($rs, 'ASSOC')) {
4109
            $list[] = $row;
4110
        }
4111
    }
4112
4113
    return $list;
4114
}
4115
4116
/**
4117
 * Gets item property id from tool of a course
4118
 * @param string $course_code course code
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 $sessionId Session ID (optional)
4122
 * @return int
4123
 */
4124
function api_get_item_property_id($course_code, $tool, $ref, $sessionId = 0)
4125
{
4126
    $course_info = api_get_course_info($course_code);
4127
    $tool = Database::escape_string($tool);
4128
    $ref = intval($ref);
4129
4130
    // Definition of tables.
4131
    $tableItemProperty = Database::get_course_table(TABLE_ITEM_PROPERTY);
4132
    $course_id = $course_info['real_id'];
4133
    $sessionCondition = " AND session_id = $sessionId ";
4134
    if (empty($sessionId)) {
4135
        $sessionCondition = " AND (session_id = 0 OR session_id IS NULL) ";
4136
    }
4137
    $sql = "SELECT id FROM $tableItemProperty
4138
            WHERE
4139
                c_id = $course_id AND
4140
                tool = '$tool' AND
4141
                ref = $ref
4142
                $sessionCondition";
4143
    $rs  = Database::query($sql);
4144
    $item_property_id = '';
4145
    if (Database::num_rows($rs) > 0) {
4146
        $row = Database::fetch_array($rs);
4147
        $item_property_id = $row['id'];
4148
    }
4149
    return $item_property_id;
4150
}
4151
4152
/**
4153
 * Inserts a record in the track_e_item_property table (No update)
4154
 * @param string $tool
4155
 * @param int $ref
4156
 * @param string $title
4157
 * @param string $content
4158
 * @param int $progress
4159
 * @return bool|int
4160
 */
4161
function api_track_item_property_update($tool, $ref, $title, $content, $progress)
4162
{
4163
    $tbl_stats_item_property = Database::get_main_table(TABLE_STATISTIC_TRACK_E_ITEM_PROPERTY);
4164
    $course_id = api_get_real_course_id(); //numeric
4165
    $course_code = api_get_course_id(); //alphanumeric
4166
    $item_property_id = api_get_item_property_id($course_code, $tool, $ref);
4167
    if (!empty($item_property_id)) {
4168
        $sql = "INSERT IGNORE INTO $tbl_stats_item_property SET
4169
                course_id           = '$course_id',
4170
                item_property_id    = '$item_property_id',
4171
                title               = '".Database::escape_string($title)."',
4172
                content             = '".Database::escape_string($content)."',
4173
                progress            = '".intval($progress)."',
4174
                lastedit_date       = '".api_get_utc_datetime()."',
4175
                lastedit_user_id    = '".api_get_user_id()."',
4176
                session_id          = '".api_get_session_id()."'";
4177
        $result = Database::query($sql);
4178
        $affected_rows = Database::affected_rows($result);
4179
4180
        return $affected_rows;
4181
    }
4182
4183
    return false;
4184
}
4185
4186
/**
4187
 * @param string $tool
4188
 * @param int $ref
4189
 * @return array|resource
4190
 */
4191
function api_get_track_item_property_history($tool, $ref)
4192
{
4193
    $tbl_stats_item_property = Database::get_main_table(TABLE_STATISTIC_TRACK_E_ITEM_PROPERTY);
4194
    $course_id = api_get_real_course_id(); //numeric
4195
    $course_code = api_get_course_id(); //alphanumeric
4196
    $item_property_id = api_get_item_property_id($course_code, $tool, $ref);
4197
    $sql = "SELECT * FROM $tbl_stats_item_property
4198
            WHERE item_property_id = $item_property_id AND course_id = $course_id
4199
            ORDER BY lastedit_date DESC";
4200
    $result = Database::query($sql);
4201
    $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...
4202
    return $result;
4203
}
4204
4205
/**
4206
 * Gets item property data from tool of a course id
4207
 * @param int $course_id
4208
 * @param string $tool   tool name, linked to 'rubrique' of the course tool_list (Warning: language sensitive !!)
4209
 * @param int $ref id of the item itself, linked to key of every tool ('id', ...), "*" = all items of the tool
4210
 * @param int $session_id
4211
 * @param int $groupId
4212
 *
4213
 * @return array Array with all fields from c_item_property, empty array if not found or false if course could not be found
4214
 */
4215
function api_get_item_property_info($course_id, $tool, $ref, $session_id = 0, $groupId = 0)
4216
{
4217
    $courseInfo = api_get_course_info_by_id($course_id);
4218
4219
    if (empty($courseInfo)) {
4220
        return false;
4221
    }
4222
4223
    $tool = Database::escape_string($tool);
4224
    $ref = intval($ref);
4225
    $course_id = $courseInfo['real_id'];
4226
    $session_id = intval($session_id);
4227
4228
    $sessionCondition = " session_id = $session_id";
4229
    if (empty($session_id)) {
4230
        $sessionCondition = " (session_id = 0 OR session_id IS NULL) ";
4231
    }
4232
4233
    // Definition of tables.
4234
    $table = Database::get_course_table(TABLE_ITEM_PROPERTY);
4235
4236
    $sql = "SELECT * FROM $table
4237
            WHERE
4238
                c_id = $course_id AND
4239
                tool = '$tool' AND
4240
                ref = $ref AND
4241
                $sessionCondition ";
4242
4243
    if (!empty($groupId)) {
4244
        $groupId = intval($groupId);
4245
        $sql .= " AND to_group_id = $groupId ";
4246
    }
4247
4248
    $rs  = Database::query($sql);
4249
    $row = array();
4250
    if (Database::num_rows($rs) > 0) {
4251
        $row = Database::fetch_array($rs,'ASSOC');
4252
    }
4253
4254
    return $row;
4255
}
4256
4257
/**
4258
 * Displays a combo box so the user can select his/her preferred language.
4259
 * @param string The desired name= value for the select
4260
 * @param bool Whether we use the JQuery Chozen library or not
4261
 * (in some cases, like the indexing language picker, it can alter the presentation)
4262
 * @return string
4263
 */
4264
4265
function api_get_languages_combo($name = 'language')
4266
{
4267
    $ret = '';
4268
    $platformLanguage = api_get_setting('platformLanguage');
4269
4270
    // Retrieve a complete list of all the languages.
4271
    $language_list = api_get_languages();
4272
4273
    if (count($language_list['name']) < 2) {
4274
        return $ret;
4275
    }
4276
4277
    // The the current language of the user so that his/her language occurs as selected in the dropdown menu.
4278
    if (isset($_SESSION['user_language_choice'])) {
4279
        $default = $_SESSION['user_language_choice'];
4280
    } else {
4281
        $default = $platformLanguage;
4282
    }
4283
4284
    $languages  = $language_list['name'];
4285
    $folder     = $language_list['folder'];
4286
4287
    $ret .= '<select name="' . $name . '" id="language_chosen" class="selectpicker show-tick form-control">';
4288
    foreach ($languages as $key => $value) {
4289
        if ($folder[$key] == $default) {
4290
            $selected = ' selected="selected"';
4291
        } else {
4292
            $selected = '';
4293
        }
4294
        $ret .= sprintf('<option value=%s" %s>%s</option>', $folder[$key], $selected, $value);
4295
    }
4296
    $ret .= '</select>';
4297
    return $ret;
4298
}
4299
4300
/**
4301
 * Displays a form (drop down menu) so the user can select his/her preferred language.
4302
 * The form works with or without javascript
4303
 * @param  boolean Hide form if only one language available (defaults to false = show the box anyway)
4304
 * @return null|string Display the box directly
4305
 */
4306
function api_display_language_form($hide_if_no_choice = false)
4307
{
4308
    // Retrieve a complete list of all the languages.
4309
    $language_list = api_get_languages();
4310
    if (count($language_list['name']) <= 1 && $hide_if_no_choice) {
4311
        return; //don't show any form
4312
    }
4313
4314
    // The the current language of the user so that his/her language occurs as selected in the dropdown menu.
4315
    if (isset($_SESSION['user_language_choice'])) {
4316
        $user_selected_language = $_SESSION['user_language_choice'];
4317
    }
4318
    if (empty($user_selected_language)) {
4319
        $user_selected_language = api_get_setting('platformLanguage');
4320
    }
4321
4322
    $original_languages = $language_list['name'];
4323
    $folder = $language_list['folder']; // This line is probably no longer needed.
4324
    $html = '
4325
    <script type="text/javascript">
4326
    <!--
4327
    $(document).ready(function() {
4328
        $("#language_list").change(function() {
4329
            jumpMenu("parent",this,0);
4330
        });
4331
    });
4332
4333
    function jumpMenu(targ,selObj,restore){ // v3.0
4334
        eval(targ+".location=\'"+selObj.options[selObj.selectedIndex].value+"\'");
4335
        if (restore) selObj.selectedIndex=0;
4336
    }
4337
    //-->
4338
    </script>';
4339
    $html .= '<form id="lang_form" name="lang_form" method="post" action="'.api_get_self().'">';
4340
    $html .= '<label style="display: none;" for="language_list">' . get_lang('Language') . '</label>';
4341
    $html .=  '<select id="language_list" class="selectpicker show-tick form-control" name="language_list" >';
4342
4343
    foreach ($original_languages as $key => $value) {
4344
        if ($folder[$key] == $user_selected_language) {
4345
            $option_end = ' selected="selected" >';
4346
        } else {
4347
            $option_end = '>';
4348
        }
4349
        $html .=  '<option value="'.api_get_self().'?language='.$folder[$key].'"'.$option_end;
4350
        //echo substr($value, 0, 16); // Cut string to keep 800x600 aspect.
4351
        $html .=  $value.'</option>';
4352
    }
4353
    $html .=  '</select>';
4354
    $html .=  '<noscript><input type="submit" name="user_select_language" value="'.get_lang('Ok').'" /></noscript>';
4355
    $html .=  '</form>';
4356
    return $html;
4357
}
4358
4359
/**
4360
 * Returns a list of all the languages that are made available by the admin.
4361
 * @return array An array with all languages. Structure of the array is
4362
 *  array['name'] = An array with the name of every language
4363
 *  array['folder'] = An array with the corresponding names of the language-folders in the filesystem
4364
 */
4365
function api_get_languages() {
4366
    $tbl_language = Database::get_main_table(TABLE_MAIN_LANGUAGE);
4367
    $sql = "SELECT * FROM $tbl_language WHERE available='1' ORDER BY original_name ASC";
4368
    $result = Database::query($sql);
4369
    $language_list = array();
4370
    while ($row = Database::fetch_array($result)) {
4371
        $language_list['name'][] = $row['original_name'];
4372
        $language_list['folder'][] = $row['dokeos_folder'];
4373
    }
4374
    return $language_list;
4375
}
4376
4377
/**
4378
 * Returns a list of all the languages that are made available by the admin.
4379
 * @return array
4380
 */
4381
function api_get_languages_to_array() {
4382
    $tbl_language = Database::get_main_table(TABLE_MAIN_LANGUAGE);
4383
    $sql = "SELECT * FROM $tbl_language WHERE available='1' ORDER BY original_name ASC";
4384
    $result = Database::query($sql);
4385
    $languages = array();
4386
    while ($row = Database::fetch_array($result)) {
4387
        $languages[$row['dokeos_folder']] = $row['original_name'];
4388
    }
4389
    return $languages;
4390
}
4391
4392
/**
4393
 * Returns the id (the database id) of a language
4394
 * @param   string  language name (the corresponding name of the language-folder in the filesystem)
4395
 * @return  int     id of the language
4396
 */
4397
function api_get_language_id($language)
4398
{
4399
    $tbl_language = Database::get_main_table(TABLE_MAIN_LANGUAGE);
4400
    if (empty($language)) {
4401
        return null;
4402
    }
4403
    $language = Database::escape_string($language);
4404
    $sql = "SELECT id FROM $tbl_language
4405
            WHERE dokeos_folder = '$language' LIMIT 1";
4406
    $result = Database::query($sql);
4407
    $row = Database::fetch_array($result);
4408
    return $row['id'];
4409
}
4410
4411
/**
4412
 * Gets language of the requested type for the current user. Types are :
4413
 * user_profil_lang : profile language of current user
4414
 * user_select_lang : language selected by user at login
4415
 * course_lang : language of the current course
4416
 * platform_lang : default platform language
4417
 * @param string $lang_type
4418
 * @return string
4419
 **/
4420
function api_get_language_from_type($lang_type)
4421
{
4422
    $return = false;
4423
4424
    switch ($lang_type) {
4425
        case 'platform_lang':
4426
            $temp_lang = api_get_setting('platformLanguage');
4427
            if (!empty($temp_lang))
4428
                $return = $temp_lang;
4429
            break;
4430
        case 'user_profil_lang':
4431
            $_user = api_get_user_info();
4432 View Code Duplication
            if (isset($_user['language']) && !empty($_user['language']))
4433
                $return = $_user['language'];
4434
            break;
4435
        case 'user_selected_lang':
4436
            if (isset($_SESSION['user_language_choice']) && !empty($_SESSION['user_language_choice']))
4437
                $return = $_SESSION['user_language_choice'];
4438
            break;
4439
        case 'course_lang':
4440
            global $_course;
4441
            $cidReq = null;
4442
            if (empty($_course)) {
4443
                // Code modified because the local.inc.php file it's declarated after this work
4444
                // causing the function api_get_course_info() returns a null value
4445
                $cidReq = isset($_GET["cidReq"]) ? Database::escape_string($_GET["cidReq"]) : null;
4446
                $cDir = (!empty($_GET['cDir']) ? $_GET['cDir'] : null);
4447
                if (empty($cidReq) && !empty($cDir)) {
4448
                    $c = CourseManager::get_course_id_from_path($cDir);
4449
                    if ($c) {
4450
                        $cidReq = $c;
4451
                    }
4452
                }
4453
            }
4454
            $_course = api_get_course_info($cidReq);
4455 View Code Duplication
            if (isset($_course['language']) && !empty($_course['language']))
4456
                $return = $_course['language'];
4457
            break;
4458
        default:
4459
            $return = false;
4460
        break;
4461
    }
4462
4463
    return $return;
4464
}
4465
4466
function api_get_language_info($language_id) {
4467
    $tbl_admin_languages = Database :: get_main_table(TABLE_MAIN_LANGUAGE);
4468
    $sql = 'SELECT * FROM '.$tbl_admin_languages.' WHERE id = "'.intval($language_id).'"';
4469
    $rs = Database::query($sql);
4470
    $language_info = array();
4471
    if (Database::num_rows($rs)) {
4472
        $language_info = Database::fetch_array($rs,'ASSOC');
4473
    }
4474
    return $language_info;
4475
}
4476
4477
/**
4478
 * Returns the name of the visual (CSS) theme to be applied on the current page.
4479
 * The returned name depends on the platform, course or user -wide settings.
4480
 * @return string   The visual theme's name, it is the name of a folder inside .../chamilo/main/css/
4481
 */
4482
function api_get_visual_theme()
4483
{
4484
    static $visual_theme;
4485
    if (!isset($visual_theme)) {
4486
4487
        $platform_theme = api_get_setting('stylesheets');
4488
4489
        // Platform's theme.
4490
        $visual_theme = $platform_theme;
4491
4492
        if (api_get_setting('user_selected_theme') == 'true') {
4493
            $user_info = api_get_user_info();
4494
            if (isset($user_info['theme'])) {
4495
                $user_theme = $user_info['theme'];
4496
4497
                if (!empty($user_theme)) {
4498
                    $visual_theme = $user_theme;
4499
                    // User's theme.
4500
                }
4501
            }
4502
        }
4503
4504
        $course_id = api_get_course_id();
4505
4506
        if (!empty($course_id) && $course_id != -1) {
4507
            if (api_get_setting('allow_course_theme') == 'true') {
4508
                $course_theme = api_get_course_setting('course_theme');
4509
4510
                if (!empty($course_theme) && $course_theme != -1) {
4511
                    if (!empty($course_theme)) {
4512
                        // Course's theme.
4513
                        $visual_theme = $course_theme;
4514
                    }
4515
                }
4516
4517
                $allow_lp_theme = api_get_course_setting('allow_learning_path_theme');
4518
                if ($allow_lp_theme == 1) {
4519
                    global $lp_theme_css, $lp_theme_config;
4520
                    // These variables come from the file lp_controller.php.
4521
                    if (!$lp_theme_config) {
4522
                        if (!empty($lp_theme_css)) {
4523
                            // LP's theme.
4524
                            $visual_theme = $lp_theme_css;
4525
                        }
4526
                    }
4527
                }
4528
            }
4529
        }
4530
4531
        if (empty($visual_theme)) {
4532
            $visual_theme = 'chamilo';
4533
        }
4534
4535
        global $lp_theme_log;
4536
        if ($lp_theme_log) {
4537
            $visual_theme = $platform_theme;
4538
        }
4539
    }
4540
4541
    return $visual_theme;
4542
}
4543
4544
/**
4545
 * Returns a list of CSS themes currently available in the CSS folder
4546
 * @return array        List of themes directories from the css folder
4547
 * Note: Directory names (names of themes) in the file system should contain ASCII-characters only.
4548
 */
4549
function api_get_themes() {
4550
    $cssdir = api_get_path(SYS_CSS_PATH) . 'themes/';
4551
    $list_dir = array();
4552
    $list_name = array();
4553
4554
    if (is_dir($cssdir)) {
4555
        $themes = @scandir($cssdir);
4556
4557
        if (is_array($themes)) {
4558
            if ($themes !== false) {
4559
                sort($themes);
4560
4561
                foreach ($themes as & $theme) {
4562
                    if (substr($theme, 0, 1) == '.') {
4563
                        continue;
4564
                    } else {
4565
                        if (is_dir($cssdir.$theme)) {
4566
                            $list_dir[] = $theme;
4567
                            $list_name[] = ucwords(str_replace('_', ' ', $theme));
4568
                        }
4569
                    }
4570
                }
4571
            }
4572
        }
4573
    }
4574
4575
    return array($list_dir, $list_name);
4576
}
4577
4578
/**
4579
 * Find the largest sort value in a given user_course_category
4580
 * This function is used when we are moving a course to a different category
4581
 * and also when a user subscribes to courses (the new course is added at the end of the main category
4582
 * @author Patrick Cool <[email protected]>, Ghent University
4583
 * @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...
4584
 * @param integer $user_id
4585
 * @return int the value of the highest sort of the user_course_category
4586
 */
4587
function api_max_sort_value($user_course_category, $user_id)
4588
{
4589
    $tbl_course_user = Database::get_main_table(TABLE_MAIN_COURSE_USER);
4590
    $sql = "SELECT max(sort) as max_sort FROM $tbl_course_user
4591
            WHERE
4592
                user_id='".intval($user_id)."' AND
4593
                relation_type<>".COURSE_RELATION_TYPE_RRHH." AND
4594
                user_course_cat='".intval($user_course_category)."'";
4595
    $result_max = Database::query($sql);
4596
    if (Database::num_rows($result_max) == 1) {
4597
        $row_max = Database::fetch_array($result_max);
4598
        return $row_max['max_sort'];
4599
    }
4600
    return 0;
4601
}
4602
4603
/**
4604
 * This function converts the string "true" or "false" to a boolean true or false.
4605
 * This function is in the first place written for the Chamilo Config Settings (also named AWACS)
4606
 * @param string "true" or "false"
4607
 * @return boolean true or false
4608
 * @author Patrick Cool <[email protected]>, Ghent University
4609
 */
4610
function api_string_2_boolean($string) {
4611
    if ($string == 'true') {
4612
        return true;
4613
    }
4614
    if ($string == 'false') {
4615
        return false;
4616
    }
4617
    return false;
4618
}
4619
4620
/**
4621
 * Determines the number of plugins installed for a given location
4622
 */
4623
function api_number_of_plugins($location) {
4624
    global $_plugins;
4625
    return isset($_plugins[$location]) && is_array($_plugins[$location]) ? count($_plugins[$location]) : 0;
4626
}
4627
4628
/**
4629
 * Transforms a number of seconds in hh:mm:ss format
4630
 * @author Julian Prud'homme
4631
 * @param integer the number of seconds
4632
 * @return string the formated time
4633
 */
4634
function api_time_to_hms($seconds)
4635
{
4636
    // $seconds = -1 means that we have wrong data in the db.
4637
    if ($seconds == -1) {
4638
        return
4639
            get_lang('Unknown').
4640
            Display::return_icon(
4641
                'info2.gif',
4642
                get_lang('WrongDatasForTimeSpentOnThePlatform'),
4643
                array('align' => 'absmiddle', 'hspace' => '3px')
4644
            );
4645
    }
4646
4647
    // How many hours ?
4648
    $hours = floor($seconds / 3600);
4649
4650
    // How many minutes ?
4651
    $min = floor(($seconds - ($hours * 3600)) / 60);
4652
4653
    // How many seconds
4654
    $sec = floor($seconds - ($hours * 3600) - ($min * 60));
4655
4656
    if ($sec < 10) {
4657
        $sec = "0$sec";
4658
    }
4659
4660
    if ($min < 10) {
4661
        $min = "0$min";
4662
    }
4663
4664
    return "$hours:$min:$sec";
4665
}
4666
4667
/* FILE SYSTEM RELATED FUNCTIONS */
4668
4669
/**
4670
 * Returns the permissions to be assigned to every newly created directory by the web-server.
4671
 * The return value is based on the platform administrator's setting
4672
 * "Administration > Configuration settings > Security > Permissions for new directories".
4673
 * @return int  Returns the permissions in the format "Owner-Group-Others, Read-Write-Execute", as an integer value.
4674
 */
4675 View Code Duplication
function api_get_permissions_for_new_directories() {
4676
    static $permissions;
4677
    if (!isset($permissions)) {
4678
        $permissions = trim(api_get_setting('permissions_for_new_directories'));
4679
        // The default value 0777 is according to that in the platform administration panel after fresh system installation.
4680
        $permissions = octdec(!empty($permissions) ? $permissions : '0777');
4681
    }
4682
    return $permissions;
4683
}
4684
4685
/**
4686
 * Returns the permissions to be assigned to every newly created directory by the web-server.
4687
 * The return value is based on the platform administrator's setting
4688
 * "Administration > Configuration settings > Security > Permissions for new files".
4689
 * @return int Returns the permissions in the format
4690
 * "Owner-Group-Others, Read-Write-Execute", as an integer value.
4691
 */
4692 View Code Duplication
function api_get_permissions_for_new_files() {
4693
    static $permissions;
4694
    if (!isset($permissions)) {
4695
        $permissions = trim(api_get_setting('permissions_for_new_files'));
4696
        // The default value 0666 is according to that in the platform administration panel after fresh system installation.
4697
        $permissions = octdec(!empty($permissions) ? $permissions : '0666');
4698
    }
4699
    return $permissions;
4700
}
4701
4702
/**
4703
 * Deletes a file, or a folder and its contents
4704
 *
4705
 * @author      Aidan Lister <[email protected]>
4706
 * @version     1.0.3
4707
 * @param       string   $dirname    Directory to delete
4708
 * @param       bool     Deletes only the content or not
4709
 * @param       bool     $strict if one folder/file fails stop the loop
4710
 * @return      bool     Returns TRUE on success, FALSE on failure
4711
 * @link http://aidanlister.com/2004/04/recursively-deleting-a-folder-in-php/
4712
 * @author      Yannick Warnier, adaptation for the Chamilo LMS, April, 2008
4713
 * @author      Ivan Tcholakov, a sanity check about Directory class creation has been added, September, 2009
4714
 */
4715
function rmdirr($dirname, $delete_only_content_in_folder = false, $strict = false) {
4716
    $res = true;
4717
4718
    // A sanity check.
4719
    if (!file_exists($dirname)) {
4720
        return false;
4721
    }
4722
    $php_errormsg = '';
4723
    // Simple delete for a file.
4724
    if (is_file($dirname) || is_link($dirname)) {
4725
        $res = unlink($dirname);
4726 View Code Duplication
        if ($res === false) {
4727
            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);
4728
        }
4729
        return $res;
4730
    }
4731
4732
    // Loop through the folder.
4733
    $dir = dir($dirname);
4734
    // A sanity check.
4735
    $is_object_dir = is_object($dir);
4736 View Code Duplication
    if ($is_object_dir) {
4737
        while (false !== $entry = $dir->read()) {
4738
            // Skip pointers.
4739
            if ($entry == '.' || $entry == '..') {
4740
                continue;
4741
            }
4742
4743
            // Recurse.
4744
            if ($strict) {
4745
                $result = rmdirr("$dirname/$entry");
4746
                if ($result == false) {
4747
                    $res = false;
4748
                    break;
4749
                }
4750
            } else {
4751
                rmdirr("$dirname/$entry");
4752
            }
4753
        }
4754
    }
4755
4756
    // Clean up.
4757
    if ($is_object_dir) {
4758
        $dir->close();
4759
    }
4760
4761
    if ($delete_only_content_in_folder == false) {
4762
        $res = rmdir($dirname);
4763 View Code Duplication
        if ($res === false) {
4764
            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);
4765
        }
4766
    }
4767
    return $res;
4768
}
4769
4770
// TODO: This function is to be simplified. File access modes to be implemented.
4771
/**
4772
 * function adapted from a php.net comment
4773
 * copy recursively a folder
4774
 * @param the source folder
4775
 * @param the dest folder
4776
 * @param an array of excluded file_name (without extension)
4777
 * @param copied_files the returned array of copied files
4778
 * @param string $source
4779
 * @param string $dest
4780
 */
4781
function copyr($source, $dest, $exclude = array(), $copied_files = array()) {
4782
    if (empty($dest)) { return false; }
4783
    // Simple copy for a file
4784
    if (is_file($source)) {
4785
        $path_info = pathinfo($source);
4786
        if (!in_array($path_info['filename'], $exclude)) {
4787
            copy($source, $dest);
4788
        }
4789
        return true;
4790
    } elseif (!is_dir($source)) {
4791
        //then source is not a dir nor a file, return
4792
        return false;
4793
    }
4794
4795
    // Make destination directory.
4796
    if (!is_dir($dest)) {
4797
        mkdir($dest, api_get_permissions_for_new_directories());
4798
    }
4799
4800
    // Loop through the folder.
4801
    $dir = dir($source);
4802
    while (false !== $entry = $dir->read()) {
4803
        // Skip pointers
4804
        if ($entry == '.' || $entry == '..') {
4805
            continue;
4806
        }
4807
4808
        // Deep copy directories.
4809
        if ($dest !== "$source/$entry") {
4810
            $files = copyr("$source/$entry", "$dest/$entry", $exclude, $copied_files);
4811
        }
4812
    }
4813
    // Clean up.
4814
    $dir->close();
4815
    return true;
4816
}
4817
4818
// TODO: Using DIRECTORY_SEPARATOR is not recommended, this is an obsolete approach. Documentation header to be added here.
4819
/**
4820
 * @param string $pathname
4821
 * @param string $base_path_document
4822
 * @param integer $session_id
4823
 */
4824
function copy_folder_course_session(
4825
    $pathname,
4826
    $base_path_document,
4827
    $session_id,
4828
    $course_info,
4829
    $document,
4830
    $source_course_id
4831
) {
4832
    $table = Database :: get_course_table(TABLE_DOCUMENT);
4833
    $session_id = intval($session_id);
4834
    $source_course_id = intval($source_course_id);
4835
4836
    // Check whether directory already exists.
4837
    if (is_dir($pathname) || empty($pathname)) {
4838
        return true;
4839
    }
4840
4841
    // Ensure that a file with the same name does not already exist.
4842
    if (is_file($pathname)) {
4843
        trigger_error('copy_folder_course_session(): File exists', E_USER_WARNING);
4844
        return false;
4845
    }
4846
4847
    $course_id = $course_info['real_id'];
4848
4849
    $folders = explode(DIRECTORY_SEPARATOR,str_replace($base_path_document.DIRECTORY_SEPARATOR,'',$pathname));
4850
4851
    $new_pathname = $base_path_document;
4852
    $path = '';
4853
4854
    foreach ($folders as $folder) {
4855
        $new_pathname .= DIRECTORY_SEPARATOR.$folder;
4856
        $path .= DIRECTORY_SEPARATOR.$folder;
4857
4858
        if (!file_exists($new_pathname)) {
4859
            $path = Database::escape_string($path);
4860
4861
            $sql = "SELECT * FROM $table
4862
                    WHERE
4863
                        c_id = $source_course_id AND
4864
                        path = '$path' AND
4865
                        filetype = 'folder' AND
4866
                        session_id = '$session_id'";
4867
            $rs1  = Database::query($sql);
4868
            $num_rows = Database::num_rows($rs1);
4869
4870
            if ($num_rows == 0) {
4871
                mkdir($new_pathname, api_get_permissions_for_new_directories());
4872
4873
                // Insert new folder with destination session_id.
4874
                $params = [
4875
                    'c_id' => $course_id,
4876
                    'path' => $path,
4877
                    'comment' => $document->comment,
4878
                    'title' => basename($new_pathname),
4879
                    'filetype' => 'folder',
4880
                    'size' => '0',
4881
                    'session_id' => $session_id
4882
                ];
4883
                $document_id = Database::insert($table, $params);
4884
                if ($document_id) {
4885
4886
                    $sql = "UPDATE $table SET id = iid WHERE iid = $document_id";
4887
                    Database::query($sql);
4888
4889
                    api_item_property_update(
4890
                        $course_info,
4891
                        TOOL_DOCUMENT,
4892
                        $document_id,
4893
                        'FolderCreated',
4894
                        api_get_user_id(),
4895
                        0,
4896
                        0,
4897
                        null,
4898
                        null,
4899
                        $session_id
4900
                    );
4901
                }
4902
            }
4903
        }
4904
4905
    } // en foreach
4906
}
4907
4908
// TODO: chmodr() is a better name. Some corrections are needed. Documentation header to be added here.
4909
/**
4910
 * @param string $path
4911
 */
4912
function api_chmod_R($path, $filemode) {
4913
    if (!is_dir($path)) {
4914
        return chmod($path, $filemode);
4915
    }
4916
4917
    $handler = opendir($path);
4918
    while ($file = readdir($handler)) {
4919
        if ($file != '.' && $file != '..') {
4920
            $fullpath = "$path/$file";
4921
            if (!is_dir($fullpath)) {
4922
                if (!chmod($fullpath, $filemode)) {
4923
                    return false;
4924
                }
4925
            } else {
4926
                if (!api_chmod_R($fullpath, $filemode)) {
4927
                    return false;
4928
                }
4929
            }
4930
        }
4931
    }
4932
4933
    closedir($handler);
4934
    return chmod($path, $filemode);
4935
}
4936
4937
4938
// TODO: Where the following function has been copy/pased from? There is no information about author and license. Style, coding conventions...
4939
/**
4940
 * Parse info file format. (e.g: file.info)
4941
 *
4942
 * Files should use an ini-like format to specify values.
4943
 * White-space generally doesn't matter, except inside values.
4944
 * e.g.
4945
 *
4946
 * @verbatim
4947
 *   key = value
4948
 *   key = "value"
4949
 *   key = 'value'
4950
 *   key = "multi-line
4951
 *
4952
 *   value"
4953
 *   key = 'multi-line
4954
 *
4955
 *   value'
4956
 *   key
4957
 *   =
4958
 *   'value'
4959
 * @endverbatim
4960
 *
4961
 * Arrays are created using a GET-like syntax:
4962
 *
4963
 * @verbatim
4964
 *   key[] = "numeric array"
4965
 *   key[index] = "associative array"
4966
 *   key[index][] = "nested numeric array"
4967
 *   key[index][index] = "nested associative array"
4968
 * @endverbatim
4969
 *
4970
 * PHP constants are substituted in, but only when used as the entire value:
4971
 *
4972
 * Comments should start with a semi-colon at the beginning of a line.
4973
 *
4974
 * This function is NOT for placing arbitrary module-specific settings. Use
4975
 * variable_get() and variable_set() for that.
4976
 *
4977
 * Information stored in the module.info file:
4978
 * - name: The real name of the module for display purposes.
4979
 * - description: A brief description of the module.
4980
 * - dependencies: An array of shortnames of other modules this module depends on.
4981
 * - package: The name of the package of modules this module belongs to.
4982
 *
4983
 * Example of .info file:
4984
 * <code>
4985
 * @verbatim
4986
 *   name = Forum
4987
 *   description = Enables threaded discussions about general topics.
4988
 *   dependencies[] = taxonomy
4989
 *   dependencies[] = comment
4990
 *   package = Core - optional
4991
 *   version = VERSION
4992
 * @endverbatim
4993
 * </code>
4994
 * @param string $filename
4995
 *   The file we are parsing. Accepts file with relative or absolute path.
4996
 * @return
4997
 *   The info array.
4998
 */
4999
function parse_info_file($filename) {
5000
    $info = array();
5001
5002
    if (!file_exists($filename)) {
5003
        return $info;
5004
    }
5005
5006
    $data = file_get_contents($filename);
5007
    if (preg_match_all('
5008
        @^\s*                           # Start at the beginning of a line, ignoring leading whitespace
5009
        ((?:
5010
          [^=;\[\]]|                    # Key names cannot contain equal signs, semi-colons or square brackets,
5011
          \[[^\[\]]*\]                  # unless they are balanced and not nested
5012
        )+?)
5013
        \s*=\s*                         # Key/value pairs are separated by equal signs (ignoring white-space)
5014
        (?:
5015
          ("(?:[^"]|(?<=\\\\)")*")|     # Double-quoted string, which may contain slash-escaped quotes/slashes
5016
          (\'(?:[^\']|(?<=\\\\)\')*\')| # Single-quoted string, which may contain slash-escaped quotes/slashes
5017
          ([^\r\n]*?)                   # Non-quoted string
5018
        )\s*$                           # Stop at the next end of a line, ignoring trailing whitespace
5019
        @msx', $data, $matches, PREG_SET_ORDER)) {
5020
        $key = $value1 = $value2 = $value3 = '';
5021
        foreach ($matches as $match) {
5022
            // Fetch the key and value string.
5023
            $i = 0;
5024
            foreach (array('key', 'value1', 'value2', 'value3') as $var) {
5025
                $$var = isset($match[++$i]) ? $match[$i] : '';
5026
            }
5027
            $value = stripslashes(substr($value1, 1, -1)) . stripslashes(substr($value2, 1, -1)) . $value3;
5028
5029
            // Parse array syntax.
5030
            $keys = preg_split('/\]?\[/', rtrim($key, ']'));
5031
            $last = array_pop($keys);
5032
            $parent = &$info;
5033
5034
            // Create nested arrays.
5035
            foreach ($keys as $key) {
5036
                if ($key == '') {
5037
                    $key = count($parent);
5038
                }
5039
                if (!isset($parent[$key]) || !is_array($parent[$key])) {
5040
                    $parent[$key] = array();
5041
                }
5042
                $parent = &$parent[$key];
5043
            }
5044
5045
            // Handle PHP constants.
5046
            if (defined($value)) {
5047
                $value = constant($value);
5048
            }
5049
5050
            // Insert actual value.
5051
            if ($last == '') {
5052
                $last = count($parent);
5053
            }
5054
            $parent[$last] = $value;
5055
        }
5056
    }
5057
    return $info;
5058
}
5059
5060
5061
/**
5062
 * Gets Chamilo version from the configuration files
5063
 * @return string   A string of type "1.8.4", or an empty string if the version could not be found
5064
 */
5065
function api_get_version() {
5066
    global $_configuration;
5067
    return (string)$_configuration['system_version'];
5068
}
5069
5070
/**
5071
 * Gets the software name (the name/brand of the Chamilo-based customized system)
5072
 * @return string
5073
 */
5074
function api_get_software_name() {
5075
    $name = api_get_configuration_value('software_name');
5076
    if (!empty($name)) {
5077
        return $name;
5078
    } else {
5079
        return 'Chamilo';
5080
    }
5081
}
5082
5083
/**
5084
 * Checks whether status given in parameter exists in the platform
5085
 * @param mixed the status (can be either int either string)
5086
 * @return boolean if the status exists, else returns false
5087
 */
5088
function api_status_exists($status_asked) {
5089
    global $_status_list;
5090
    return in_array($status_asked, $_status_list) ? true : isset($_status_list[$status_asked]);
5091
}
5092
5093
/**
5094
 * Checks whether status given in parameter exists in the platform. The function
5095
 * returns the status ID or false if it does not exist, but given the fact there
5096
 * is no "0" status, the return value can be checked against
5097
 * if(api_status_key()) to know if it exists.
5098
 * @param   mixed   The status (can be either int or string)
5099
 * @return  mixed   Status ID if exists, false otherwise
5100
 */
5101
function api_status_key($status) {
5102
    global $_status_list;
5103
    return isset($_status_list[$status]) ? $status : array_search($status, $_status_list);
5104
}
5105
5106
/**
5107
 * Gets the status langvars list
5108
 * @return string[] the list of status with their translations
5109
 */
5110
function api_get_status_langvars() {
5111
    return array(
5112
        COURSEMANAGER   => get_lang('Teacher', ''),
5113
        SESSIONADMIN    => get_lang('SessionsAdmin', ''),
5114
        DRH             => get_lang('Drh', ''),
5115
        STUDENT         => get_lang('Student', ''),
5116
        ANONYMOUS       => get_lang('Anonymous', ''),
5117
        STUDENT_BOSS    => get_lang('RoleStudentBoss', ''),
5118
        INVITEE         => get_lang('Invited'),
5119
    );
5120
}
5121
5122
/**
5123
* The function that retrieves all the possible settings for a certain config setting
5124
* @author Patrick Cool <[email protected]>, Ghent University
5125
*/
5126
function api_get_settings_options($var) {
5127
    $table_settings_options = Database :: get_main_table(TABLE_MAIN_SETTINGS_OPTIONS);
5128
    $var = Database::escape_string($var);
5129
    $sql = "SELECT * FROM $table_settings_options
5130
            WHERE variable = '$var'
5131
            ORDER BY id";
5132
    $result = Database::query($sql);
5133
    $settings_options_array = array();
5134
    while ($row = Database::fetch_array($result, 'ASSOC')) {
5135
        $settings_options_array[] = $row;
5136
    }
5137
    return $settings_options_array;
5138
}
5139
5140
/**
5141
 * @param array $params
5142
 */
5143
function api_set_setting_option($params) {
5144
    $table = Database::get_main_table(TABLE_MAIN_SETTINGS_OPTIONS);
5145 View Code Duplication
    if (empty($params['id'])) {
5146
        Database::insert($table, $params);
5147
    } else {
5148
        Database::update($table, $params, array('id = ? '=> $params['id']));
5149
    }
5150
}
5151
5152
/**
5153
 * @param array $params
5154
 */
5155
function api_set_setting_simple($params) {
5156
    $table = Database::get_main_table(TABLE_MAIN_SETTINGS_CURRENT);
5157
    $url_id = api_get_current_access_url_id();
5158
5159 View Code Duplication
    if (empty($params['id'])) {
5160
        $params['access_url'] = $url_id;
5161
        Database::insert($table, $params);
5162
    } else {
5163
        Database::update($table, $params, array('id = ? '=> array($params['id'])));
5164
    }
5165
}
5166
5167
/**
5168
 * @param int $id
5169
 */
5170
function api_delete_setting_option($id) {
5171
    $table = Database::get_main_table(TABLE_MAIN_SETTINGS_OPTIONS);
5172
    if (!empty($id)) {
5173
        Database::delete($table, array('id = ? '=> $id));
5174
    }
5175
}
5176
5177
/**
5178
 * Sets a platform configuration setting to a given value
5179
 * @param string    The variable we want to update
5180
 * @param string    The value we want to record
5181
 * @param string    The sub-variable if any (in most cases, this will remain null)
5182
 * @param string    The category if any (in most cases, this will remain null)
5183
 * @param int       The access_url for which this parameter is valid
5184
 * @param string $cat
5185
 */
5186
function api_set_setting($var, $value, $subvar = null, $cat = null, $access_url = 1)
5187
{
5188
    if (empty($var)) {
5189
        return false;
5190
    }
5191
    $t_settings = Database::get_main_table(TABLE_MAIN_SETTINGS_CURRENT);
5192
    $var = Database::escape_string($var);
5193
    $value = Database::escape_string($value);
5194
    $access_url = (int)$access_url;
5195
    if (empty($access_url)) { $access_url = 1; }
5196
    $select = "SELECT id FROM $t_settings WHERE variable = '$var' ";
5197
    if (!empty($subvar)) {
5198
        $subvar = Database::escape_string($subvar);
5199
        $select .= " AND subkey = '$subvar'";
5200
    }
5201
    if (!empty($cat)) {
5202
        $cat = Database::escape_string($cat);
5203
        $select .= " AND category = '$cat'";
5204
    }
5205
    if ($access_url > 1) {
5206
        $select .= " AND access_url = $access_url";
5207
    } else {
5208
        $select .= " AND access_url = 1 ";
5209
    }
5210
5211
    $res = Database::query($select);
5212
    if (Database::num_rows($res) > 0) {
5213
        // Found item for this access_url.
5214
        $row = Database::fetch_array($res);
5215
        $sql = "UPDATE $t_settings SET selected_value = '$value'
5216
                WHERE id = ".$row['id'] ;
5217
        Database::query($sql);
5218
    } else {
5219
        // Item not found for this access_url, we have to check if it exist with access_url = 1
5220
        $select = "SELECT * FROM $t_settings
5221
                   WHERE variable = '$var' AND access_url = 1 ";
5222
        // Just in case
5223
        if ($access_url == 1) {
5224
            if (!empty($subvar)) {
5225
                $select .= " AND subkey = '$subvar'";
5226
            }
5227
            if (!empty($cat)) {
5228
                $select .= " AND category = '$cat'";
5229
            }
5230
            $res = Database::query($select);
5231
5232
            if (Database::num_rows($res) > 0) {
5233
                // We have a setting for access_url 1, but none for the current one, so create one.
5234
                $row = Database::fetch_array($res);
5235
                $insert = "INSERT INTO $t_settings (variable, subkey, type,category, selected_value, title, comment, scope, subkeytext, access_url)
5236
                        VALUES
5237
                        ('".$row['variable']."',".(!empty($row['subkey']) ? "'".$row['subkey']."'" : "NULL")."," .
5238
                        "'".$row['type']."','".$row['category']."'," .
5239
                        "'$value','".$row['title']."'," .
5240
                        "".(!empty($row['comment']) ? "'".$row['comment']."'" : "NULL").",".(!empty($row['scope']) ? "'".$row['scope']."'" : "NULL")."," .
5241
                        "".(!empty($row['subkeytext'])?"'".$row['subkeytext']."'":"NULL").",$access_url)";
5242
                Database::query($insert);
5243 View Code Duplication
            } else { // Such a setting does not exist.
5244
                error_log(__FILE__.':'.__LINE__.': Attempting to update setting '.$var.' ('.$subvar.') which does not exist at all', 0);
5245
            }
5246
        } else {
5247
            // Other access url.
5248
            if (!empty($subvar)) {
5249
                $select .= " AND subkey = '$subvar'";
5250
            }
5251
            if (!empty($cat)) {
5252
                $select .= " AND category = '$cat'";
5253
            }
5254
            $res = Database::query($select);
5255
5256
            if (Database::num_rows($res) > 0) { // We have a setting for access_url 1, but none for the current one, so create one.
5257
                $row = Database::fetch_array($res);
5258
                if ($row['access_url_changeable'] == 1) {
5259
                    $insert = "INSERT INTO $t_settings (variable,subkey, type,category, selected_value,title, comment,scope, subkeytext,access_url, access_url_changeable) VALUES
5260
                            ('".$row['variable']."',".
5261
                            (!empty($row['subkey']) ? "'".$row['subkey']."'" : "NULL")."," .
5262
                            "'".$row['type']."','".$row['category']."'," .
5263
                            "'$value','".$row['title']."'," .
5264
                            "".(!empty($row['comment']) ? "'".$row['comment']."'" : "NULL").",".
5265
                            (!empty($row['scope']) ? "'".$row['scope']."'" : "NULL")."," .
5266
                            "".(!empty($row['subkeytext']) ? "'".$row['subkeytext']."'" : "NULL").",$access_url,".$row['access_url_changeable'].")";
5267
                    Database::query($insert);
5268
                }
5269 View Code Duplication
            } else { // Such a setting does not exist.
5270
                error_log(__FILE__.':'.__LINE__.': Attempting to update setting '.$var.' ('.$subvar.') which does not exist at all. The access_url is: '.$access_url.' ',0);
5271
            }
5272
        }
5273
    }
5274
}
5275
5276
/**
5277
 * Sets a whole category of settings to one specific value
5278
 * @param string    Category
5279
 * @param string    Value
5280
 * @param int       Access URL. Optional. Defaults to 1
5281
 * @param array     Optional array of filters on field type
5282
 * @param string $category
5283
 * @param string $value
5284
 */
5285
function api_set_settings_category($category, $value = null, $access_url = 1, $fieldtype = array())
5286
{
5287
    if (empty($category)) {
5288
        return false;
5289
    }
5290
    $category = Database::escape_string($category);
5291
    $t_s = Database::get_main_table(TABLE_MAIN_SETTINGS_CURRENT);
5292
    $access_url = (int) $access_url;
5293
    if (empty($access_url)) { $access_url = 1; }
5294
    if (isset($value)) {
5295
        $value = Database::escape_string($value);
5296
        $sql = "UPDATE $t_s SET selected_value = '$value'
5297
                WHERE category = '$category' AND access_url = $access_url";
5298 View Code Duplication
        if (is_array($fieldtype) && count($fieldtype)>0) {
5299
            $sql .= " AND ( ";
5300
            $i = 0;
5301
            foreach ($fieldtype as $type){
5302
                if ($i > 0) {
5303
                    $sql .= ' OR ';
5304
                }
5305
                $type = Database::escape_string($type);
5306
                $sql .= " type='".$type."' ";
5307
                $i++;
5308
            }
5309
            $sql .= ")";
5310
        }
5311
        $res = Database::query($sql);
5312
        return $res !== false;
5313
    } else {
5314
        $sql = "UPDATE $t_s SET selected_value = NULL
5315
                WHERE category = '$category' AND access_url = $access_url";
5316 View Code Duplication
        if (is_array($fieldtype) && count($fieldtype)>0) {
5317
            $sql .= " AND ( ";
5318
            $i = 0;
5319
            foreach ($fieldtype as $type){
5320
                if ($i > 0) {
5321
                    $sql .= ' OR ';
5322
                }
5323
                $type = Database::escape_string($type);
5324
                $sql .= " type='".$type."' ";
5325
                $i++;
5326
            }
5327
            $sql .= ")";
5328
        }
5329
        $res = Database::query($sql);
5330
        return $res !== false;
5331
    }
5332
}
5333
5334
/**
5335
 * Gets all available access urls in an array (as in the database)
5336
 * @return array    An array of database records
5337
 */
5338
function api_get_access_urls($from = 0, $to = 1000000, $order = 'url', $direction = 'ASC')
5339
{
5340
    $table = Database::get_main_table(TABLE_MAIN_ACCESS_URL);
5341
    $from = (int) $from;
5342
    $to = (int) $to;
5343
    $order = Database::escape_string($order, null, false);
5344
    $direction = Database::escape_string($direction, null, false);
5345
    $sql = "SELECT id, url, description, active, created_by, tms
5346
            FROM $table
5347
            ORDER BY $order $direction
5348
            LIMIT $to OFFSET $from";
5349
    $res = Database::query($sql);
5350
    return Database::store_result($res);
5351
}
5352
5353
/**
5354
 * Gets the access url info in an array
5355
 * @param int $id Id of the access url
5356
 * @param bool $returnDefault Set to false if you want the real URL if URL 1 is still 'http://localhost/'
5357
 * @return array All the info (url, description, active, created_by, tms)
5358
 * from the access_url table
5359
 * @author Julio Montoya
5360
 */
5361
function api_get_access_url($id, $returnDefault = true)
5362
{
5363
    $id = intval($id);
5364
    // Calling the Database:: library dont work this is handmade.
5365
    $table_access_url = Database::get_main_table(TABLE_MAIN_ACCESS_URL);
5366
    $sql = "SELECT url, description, active, created_by, tms
5367
            FROM $table_access_url WHERE id = '$id' ";
5368
    $res = Database::query($sql);
5369
    $result = @Database::fetch_array($res);
5370
    // If the result url is 'http://localhost/' (the default) and the root_web
5371
    // (=current url) is different, and the $id is = 1 (which might mean
5372
    // api_get_current_access_url_id() returned 1 by default), then return the
5373
    // root_web setting instead of the current URL
5374
    // This is provided as an option to avoid breaking the storage of URL-specific
5375
    // homepages in home/localhost/
5376
    if ($id === 1 && $returnDefault === false) {
5377
        $currentUrl = api_get_current_access_url_id();
5378
        // only do this if we are on the main URL (=1), otherwise we could get
5379
        // information on another URL instead of the one asked as parameter
5380
        if ($currentUrl === 1) {
5381
            $rootWeb = api_get_path(WEB_PATH);
5382
            $default = 'http://localhost/';
5383
            if ($result['url'] === $default && $rootWeb != $default) {
5384
                $result['url'] = $rootWeb;
5385
            }
5386
        }
5387
    }
5388
5389
    return $result;
5390
}
5391
5392
/**
5393
 * Adds an access URL into the database
5394
 * @param string    URL
5395
 * @param string    Description
5396
 * @param int       Active (1= active, 0=disabled)
5397
 * @return int      The new database id, or the existing database id if this url already exists
5398
 */
5399
function api_add_access_url($u, $d = '', $a = 1) {
5400
    $t_au = Database::get_main_table(TABLE_MAIN_ACCESS_URL);
5401
    $u = Database::escape_string($u);
5402
    $d = Database::escape_string($d);
5403
    $a = (int) $a;
5404
    $sql = "SELECT id FROM $t_au WHERE url LIKE '$u'";
5405
    $res = Database::query($sql);
5406
    if ($res === false) {
5407
        // Problem querying the database - return false.
5408
        return false;
5409
    }
5410
    if (Database::num_rows($res) > 0) {
5411
        return Database::result($res, 0, 'id');
5412
    }
5413
    $ui = api_get_user_id();
5414
5415
    $sql = "INSERT INTO $t_au (url,description,active,created_by,tms) VALUES ('$u','$d',$a,$ui,'')";
5416
    $res = Database::query($sql);
5417
    return ($res === false) ? false : Database::insert_id();
5418
}
5419
5420
/**
5421
 * Gets all the current settings for a specific access url
5422
 * @param string    The category, if any, that we want to get
5423
 * @param string    Whether we want a simple list (display a category) or
5424
 * a grouped list (group by variable as in settings.php default). Values: 'list' or 'group'
5425
 * @param int       Access URL's ID. Optional. Uses 1 by default, which is the unique URL
5426
 * @return array    Array of database results for the current settings of the current access URL
5427
 */
5428
function & api_get_settings($cat = null, $ordering = 'list', $access_url = 1, $url_changeable = 0)
5429
{
5430
    $table = Database::get_main_table(TABLE_MAIN_SETTINGS_CURRENT);
5431
    $access_url = (int) $access_url;
5432
    $where_condition = '';
5433
    if ($url_changeable == 1) {
5434
        $where_condition = " AND access_url_changeable= '1' ";
5435
    }
5436
    if (empty($access_url) || $access_url == -1) {
5437
        $access_url = 1;
5438
    }
5439
    $sql = "SELECT * FROM $table
5440
            WHERE access_url = $access_url  $where_condition ";
5441
5442
    if (!empty($cat)) {
5443
        $cat = Database::escape_string($cat);
5444
        $sql .= " AND category='$cat' ";
5445
    }
5446
    if ($ordering == 'group') {
5447
        $sql .= " ORDER BY id ASC";
5448
    } else {
5449
        $sql .= " ORDER BY 1,2 ASC";
5450
    }
5451
    $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...
5452
    return $result;
5453
}
5454
5455
/**
5456
 * Gets the distinct settings categories
5457
 * @param array     Array of strings giving the categories we want to excluded
5458
 * @param int       Access URL. Optional. Defaults to 1
5459
 * @return array    A list of categories
5460
 */
5461
function & api_get_settings_categories($exceptions = array(), $access_url = 1) {
5462
    $access_url = (int) $access_url;
5463
    $t_cs = Database::get_main_table(TABLE_MAIN_SETTINGS_CURRENT);
5464
    $list = "'".implode("','",$exceptions)."'";
5465
    $sql = "SELECT DISTINCT category FROM $t_cs WHERE category is NOT NULL ";
5466
    if ($list != "'',''" && $list != "''" && !empty($list)) {
5467
        $sql .= " AND category NOT IN ($list) ";
5468
    }
5469
    $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...
5470
    return $result;
5471
}
5472
5473
/**
5474
 * Deletes a setting
5475
 * @param string    Variable
5476
 * @param string    Subkey
5477
 * @param int       Access URL
5478
 * @return boolean  False on failure, true on success
5479
 */
5480
5481
function api_delete_setting($v, $s = null, $a = 1) {
5482
    if (empty($v)) { return false; }
5483
    $t_cs = Database::get_main_table(TABLE_MAIN_SETTINGS_CURRENT);
5484
    $v = Database::escape_string($v);
5485
    $a = (int) $a;
5486
    if (empty($a)) { $a = 1; }
5487
    if (!empty($s)) {
5488
        $s = Database::escape_string($s);
5489
        $sql = "DELETE FROM $t_cs WHERE variable = '$v' AND subkey = '$s' AND access_url = $a";
5490
        $r = Database::query($sql);
5491
        return $r;
5492
    }
5493
    $sql = "DELETE FROM $t_cs WHERE variable = '$v' AND access_url = $a";
5494
    $r = Database::query($sql);
5495
    return $r;
5496
}
5497
5498
/**
5499
 * Deletes all the settings from one category
5500
 * @param string    Subkey
5501
 * @param int       Access URL
5502
 * @return boolean  False on failure, true on success
5503
 */
5504
function api_delete_category_settings_by_subkey($subkey, $access_url_id = 1) {
5505
    if (empty($subkey)) { return false; }
5506
    $t_cs = Database::get_main_table(TABLE_MAIN_SETTINGS_CURRENT);
5507
    $subkey = Database::escape_string($subkey);
5508
    $access_url_id = intval($access_url_id);
5509
    $sql = "DELETE FROM $t_cs WHERE subkey = '$subkey' AND access_url = $access_url_id";
5510
    $r = Database::query($sql);
5511
    return $r;
5512
}
5513
5514
/**
5515
 * Sets a platform configuration setting to a given value
5516
 * @param string    The value we want to record
5517
 * @param string    The variable name we want to insert
5518
 * @param string    The subkey for the variable we want to insert
5519
 * @param string    The type for the variable we want to insert
5520
 * @param string    The category for the variable we want to insert
5521
 * @param string    The title
5522
 * @param string    The comment
5523
 * @param string    The scope
5524
 * @param string    The subkey text
5525
 * @param int       The access_url for which this parameter is valid
5526
 * @param int       The changeability of this setting for non-master urls
5527
 * @param string $val
5528
 * @param string $var
5529
 * @param string $sk
5530
 * @param string $c
5531
 * @return boolean  true on success, false on failure
5532
 */
5533
function api_add_setting($val, $var, $sk = null, $type = 'textfield', $c = null, $title = '', $com = '', $sc = null, $skt = null, $a = 1, $v = 0) {
5534
    if (empty($var) || !isset($val)) { return false; }
5535
    $t_settings = Database::get_main_table(TABLE_MAIN_SETTINGS_CURRENT);
5536
    $var = Database::escape_string($var);
5537
    $val = Database::escape_string($val);
5538
    $a = (int) $a;
5539
    if (empty($a)) { $a = 1; }
5540
    // Check if this variable doesn't exist already
5541
    $select = "SELECT id FROM $t_settings WHERE variable = '$var' ";
5542
    if (!empty($sk)) {
5543
        $sk = Database::escape_string($sk);
5544
        $select .= " AND subkey = '$sk'";
5545
    }
5546
    if ($a > 1) {
5547
        $select .= " AND access_url = $a";
5548
    } else {
5549
        $select .= " AND access_url = 1 ";
5550
    }
5551
    $res = Database::query($select);
5552
    if (Database::num_rows($res) > 0) { // Found item for this access_url.
5553
        $row = Database::fetch_array($res);
5554
        Database::update(
5555
            $t_settings,
5556
            array('selected_value' => $val),
5557
            array('id = ?' => array($row['id']))
5558
        );
5559
        return $row['id'];
5560
    }
5561
5562
    // Item not found for this access_url, we have to check if the whole thing is missing
5563
    // (in which case we ignore the insert) or if there *is* a record but just for access_url = 1
5564
    $insert = "INSERT INTO $t_settings " .
5565
                "(variable,selected_value," .
5566
                "type,category," .
5567
                "subkey,title," .
5568
                "comment,scope," .
5569
                "subkeytext,access_url,access_url_changeable)" .
5570
                " VALUES ('$var','$val',";
5571 View Code Duplication
    if (isset($type)) {
5572
        $type = Database::escape_string($type);
5573
        $insert .= "'$type',";
5574
    } else {
5575
        $insert .= "NULL,";
5576
    }
5577 View Code Duplication
    if (isset($c)) { // Category
5578
        $c = Database::escape_string($c);
5579
        $insert .= "'$c',";
5580
    } else {
5581
        $insert .= "NULL,";
5582
    }
5583 View Code Duplication
    if (isset($sk)) { // Subkey
5584
        $sk = Database::escape_string($sk);
5585
        $insert .= "'$sk',";
5586
    } else {
5587
        $insert .= "NULL,";
5588
    }
5589 View Code Duplication
    if (isset($title)) { // Title
5590
        $title = Database::escape_string($title);
5591
        $insert .= "'$title',";
5592
    } else {
5593
        $insert .= "NULL,";
5594
    }
5595 View Code Duplication
    if (isset($com)) { // Comment
5596
        $com = Database::escape_string($com);
5597
        $insert .= "'$com',";
5598
    } else {
5599
        $insert .= "NULL,";
5600
    }
5601 View Code Duplication
    if (isset($sc)) { // Scope
5602
        $sc = Database::escape_string($sc);
5603
        $insert .= "'$sc',";
5604
    } else {
5605
        $insert .= "NULL,";
5606
    }
5607 View Code Duplication
    if (isset($skt)) { // Subkey text
5608
        $skt = Database::escape_string($skt);
5609
        $insert .= "'$skt',";
5610
    } else {
5611
        $insert .= "NULL,";
5612
    }
5613
    $insert .= "$a,$v)";
5614
    $res = Database::query($insert);
5615
    return $res;
5616
}
5617
5618
/**
5619
 * Checks wether a user can or can't view the contents of a course.
5620
 *
5621
 * @param   int $userid     User id or NULL to get it from $_SESSION
5622
 * @param   int $cid        Course id to check whether the user is allowed.
5623
 * @return  bool
5624
 */
5625
function api_is_course_visible_for_user($userid = null, $cid = null) {
5626
    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...
5627
        $userid = api_get_user_id();
5628
    }
5629
    if (empty($userid) || strval(intval($userid)) != $userid) {
5630
        if (api_is_anonymous()) {
5631
            $userid = api_get_anonymous_id();
5632
        } else {
5633
            return false;
5634
        }
5635
    }
5636
    $cid = Database::escape_string($cid);
5637
5638
    $courseInfo = api_get_course_info($cid);
5639
    $courseId = $courseInfo['real_id'];
5640
5641
    global $is_platformAdmin;
5642
5643
    $course_table = Database::get_main_table(TABLE_MAIN_COURSE);
5644
    $course_cat_table = Database::get_main_table(TABLE_MAIN_CATEGORY);
5645
5646
    $sql = "SELECT
5647
                $course_table.category_code,
5648
                $course_table.visibility,
5649
                $course_table.code,
5650
                $course_cat_table.code
5651
            FROM $course_table
5652
            LEFT JOIN $course_cat_table
5653
                ON $course_table.category_code = $course_cat_table.code
5654
            WHERE
5655
                $course_table.code = '$cid'
5656
            LIMIT 1";
5657
5658
    $result = Database::query($sql);
5659
5660 View Code Duplication
    if (Database::num_rows($result) > 0) {
5661
        $visibility = Database::fetch_array($result);
5662
        $visibility = $visibility['visibility'];
5663
    } else {
5664
        $visibility = 0;
5665
    }
5666
    // Shortcut permissions in case the visibility is "open to the world".
5667
    if ($visibility === COURSE_VISIBILITY_OPEN_WORLD) {
5668
        return true;
5669
    }
5670
5671
    $tbl_course_user = Database :: get_main_table(TABLE_MAIN_COURSE_USER);
5672
5673
    $sql = "SELECT
5674
                is_tutor, status
5675
            FROM $tbl_course_user
5676
            WHERE
5677
                user_id  = '$userid' AND
5678
                relation_type <> '".COURSE_RELATION_TYPE_RRHH."' AND
5679
                c_id = $courseId
5680
            LIMIT 1";
5681
5682
    $result = Database::query($sql);
5683
5684
    if (Database::num_rows($result) > 0) {
5685
        // This user has got a recorded state for this course.
5686
        $cuData = Database::fetch_array($result);
5687
        $is_courseMember = true;
5688
        $is_courseTutor = ($cuData['is_tutor'] == 1);
5689
        $is_courseAdmin = ($cuData['status'] == 1);
5690
    }
5691
5692
    if (!$is_courseAdmin) {
5693
        // This user has no status related to this course.
5694
        // Is it the session coach or the session admin?
5695
        $tbl_session = Database::get_main_table(TABLE_MAIN_SESSION);
5696
        $tbl_session_course = Database::get_main_table(TABLE_MAIN_SESSION_COURSE);
5697
        $tbl_session_course_user = Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER);
5698
5699
        $sql = "SELECT
5700
                    session.id_coach, session_admin_id, session.id
5701
                FROM
5702
                    $tbl_session as session
5703
                INNER JOIN $tbl_session_course
5704
                    ON session_rel_course.session_id = session.id
5705
                    AND session_rel_course.c_id = '$courseId'
5706
                LIMIT 1";
5707
5708
        $result = Database::query($sql);
5709
        $row = Database::store_result($result);
5710
5711
        if ($row[0]['id_coach'] == $userid) {
5712
            $is_courseMember = true;
5713
            $is_courseTutor = true;
5714
            $is_courseAdmin = false;
5715
            $is_courseCoach = true;
5716
            $is_sessionAdmin = false;
5717
        }
5718
        elseif ($row[0]['session_admin_id'] == $userid) {
5719
            $is_courseMember = false;
5720
            $is_courseTutor = false;
5721
            $is_courseAdmin = false;
5722
            $is_courseCoach = false;
5723
            $is_sessionAdmin = true;
5724
        } else {
5725
            // Check if the current user is the course coach.
5726
            $sql = "SELECT 1
5727
                    FROM $tbl_session_course
5728
                    WHERE session_rel_course.c_id = '$courseId'
5729
                    AND session_rel_course.id_coach = '$userid'
5730
                    LIMIT 1";
5731
5732
            $result = Database::query($sql);
5733
5734
            //if ($row = Database::fetch_array($result)) {
5735
            if (Database::num_rows($result) > 0 ) {
5736
                $is_courseMember = true;
5737
                $is_courseTutor = true;
5738
                $is_courseCoach = true;
5739
                $is_sessionAdmin = false;
5740
5741
                $tbl_user = Database :: get_main_table(TABLE_MAIN_USER);
5742
5743
                $sql = "SELECT status FROM $tbl_user
5744
                        WHERE user_id = $userid
5745
                        LIMIT 1";
5746
5747
                $result = Database::query($sql);
5748
5749
                if (Database::result($result, 0, 0) == 1) {
5750
                    $is_courseAdmin = true;
5751
                } else {
5752
                    $is_courseAdmin = false;
5753
                }
5754
            } else {
5755
                // Check if the user is a student is this session.
5756
                $sql = "SELECT  id
5757
                        FROM $tbl_session_course_user
5758
                        WHERE
5759
                            user_id  = '$userid' AND
5760
                            c_id = '$courseId'
5761
                        LIMIT 1";
5762
5763
                if (Database::num_rows($result) > 0) {
5764
                    // This user haa got a recorded state for this course.
5765
                    while ($row = Database::fetch_array($result)) {
5766
                        $is_courseMember = true;
5767
                        $is_courseTutor = false;
5768
                        $is_courseAdmin = false;
5769
                        $is_sessionAdmin = false;
5770
                    }
5771
                }
5772
            }
5773
        }
5774
    }
5775
5776
    switch ($visibility) {
5777
        case COURSE_VISIBILITY_OPEN_WORLD:
5778
            return true;
5779
        case COURSE_VISIBILITY_OPEN_PLATFORM:
5780
            return isset($userid);
5781
        case COURSE_VISIBILITY_REGISTERED:
5782
        case COURSE_VISIBILITY_CLOSED:
5783
            return $is_platformAdmin || $is_courseMember || $is_courseAdmin;
5784
        case COURSE_VISIBILITY_HIDDEN:
5785
            return $is_platformAdmin;
5786
    }
5787
5788
    return false;
5789
}
5790
5791
/**
5792
 * Returns whether an element (forum, message, survey ...) belongs to a session or not
5793
 * @param String the tool of the element
5794
 * @param int the element id in database
5795
 * @param int the session_id to compare with element session id
5796
 * @param string $tool
5797
 * @return boolean true if the element is in the session, false else
5798
 */
5799
function api_is_element_in_the_session($tool, $element_id, $session_id = null) {
5800
    if (is_null($session_id)) {
5801
        $session_id = intval($_SESSION['id_session']);
5802
    }
5803
5804
    // Get information to build query depending of the tool.
5805
    switch ($tool) {
5806
        case TOOL_SURVEY :
5807
            $table_tool = Database::get_course_table(TABLE_SURVEY);
5808
            $key_field = 'survey_id';
5809
            break;
5810
        case TOOL_ANNOUNCEMENT :
5811
            $table_tool = Database::get_course_table(TABLE_ANNOUNCEMENT);
5812
            $key_field = 'id';
5813
            break;
5814
        case TOOL_AGENDA :
5815
            $table_tool = Database::get_course_table(TABLE_AGENDA);
5816
            $key_field = 'id';
5817
            break;
5818
        case TOOL_GROUP :
5819
            $table_tool = Database::get_course_table(TABLE_GROUP);
5820
            $key_field = 'id';
5821
            break;
5822
        default:
5823
            return false;
5824
    }
5825
    $course_id = api_get_course_int_id();
5826
5827
    $sql = "SELECT session_id FROM $table_tool WHERE c_id = $course_id AND $key_field =  ".intval($element_id);
5828
    $rs = Database::query($sql);
5829
    if ($element_session_id = Database::result($rs, 0, 0)) {
5830
        if ($element_session_id == intval($session_id)) {
5831
            // The element belongs to the session.
5832
            return true;
5833
        }
5834
    }
5835
    return false;
5836
}
5837
5838
/**
5839
 * Replaces "forbidden" characters in a filename string.
5840
 *
5841
 * @param string $filename
5842
 *
5843
 * @return string
5844
 */
5845
function api_replace_dangerous_char($filename)
5846
{
5847
    return URLify::filter($filename, 250, '', true, true, false, false);
5848
}
5849
5850
/**
5851
 * Fixes the $_SERVER['REQUEST_URI'] that is empty in IIS6.
5852
 * @author Ivan Tcholakov, 28-JUN-2006.
5853
 */
5854
function api_request_uri() {
5855
    if (!empty($_SERVER['REQUEST_URI'])) {
5856
        return $_SERVER['REQUEST_URI'];
5857
    }
5858
    $uri = $_SERVER['SCRIPT_NAME'];
5859
    if (!empty($_SERVER['QUERY_STRING'])) {
5860
        $uri .= '?'.$_SERVER['QUERY_STRING'];
5861
    }
5862
    $_SERVER['REQUEST_URI'] = $uri;
5863
    return $uri;
5864
}
5865
5866
5867
/** Gets the current access_url id of the Chamilo Platform
5868
 * @author Julio Montoya <[email protected]>
5869
 * @return int access_url_id of the current Chamilo Installation
5870
 */
5871
function api_get_current_access_url_id() {
5872
    $access_url_table = Database :: get_main_table(TABLE_MAIN_ACCESS_URL);
5873
    $path = Database::escape_string(api_get_path(WEB_PATH));
5874
    $sql = "SELECT id FROM $access_url_table WHERE url = '".$path."'";
5875
    $result = Database::query($sql);
5876
    if (Database::num_rows($result) > 0) {
5877
        $access_url_id = Database::result($result, 0, 0);
5878
        return $access_url_id;
5879
    }
5880
    //if the url in WEB_PATH was not found, it can only mean that there is
5881
    // either a configuration problem or the first URL has not been defined yet
5882
    // (by default it is http://localhost/). Thus the more sensible thing we can
5883
    // do is return 1 (the main URL) as the user cannot hack this value anyway
5884
    return 1;
5885
}
5886
5887
/**
5888
 * Gets the registered urls from a given user id
5889
 * @author Julio Montoya <[email protected]>
5890
 * @return int user id
5891
 */
5892
function api_get_access_url_from_user($user_id) {
5893
    $user_id = intval($user_id);
5894
    $table_url_rel_user = Database :: get_main_table(TABLE_MAIN_ACCESS_URL_REL_USER);
5895
    $table_url          = Database :: get_main_table(TABLE_MAIN_ACCESS_URL);
5896
    $sql = "SELECT access_url_id
5897
            FROM $table_url_rel_user url_rel_user
5898
            INNER JOIN $table_url u
5899
            ON (url_rel_user.access_url_id = u.id)
5900
            WHERE user_id = ".intval($user_id);
5901
    $result = Database::query($sql);
5902
    $url_list = array();
5903
    while ($row = Database::fetch_array($result, 'ASSOC')) {
5904
        $url_list[] = $row['access_url_id'];
5905
    }
5906
    return $url_list;
5907
}
5908
5909
/**
5910
 * Gets the status of a user in a course
5911
 * @param int       $user_id
5912
 * @param int    $courseId
5913
 * @return int      user status
5914
 */
5915
function api_get_status_of_user_in_course($user_id, $courseId)
5916
{
5917
    $tbl_rel_course_user = Database :: get_main_table(TABLE_MAIN_COURSE_USER);
5918
    if (!empty($user_id) && !empty($courseId)) {
5919
        $user_id        = intval($user_id);
5920
        $courseId    = intval($courseId);
5921
        $sql = 'SELECT status
5922
                FROM '.$tbl_rel_course_user.'
5923
                WHERE user_id='.$user_id.' AND c_id = '.$courseId;
5924
        $result = Database::query($sql);
5925
        $row_status = Database::fetch_array($result, 'ASSOC');
5926
        return $row_status['status'];
5927
    } else {
5928
        return 0;
5929
    }
5930
}
5931
5932
/**
5933
 * Checks whether the curent user is in a course or not.
5934
 *
5935
 * @param string        The course code - optional (takes it from session if not given)
5936
 * @return boolean
5937
 * @author Yannick Warnier <[email protected]>
5938
 */
5939
function api_is_in_course($course_code = null) {
5940
    if (isset($_SESSION['_course']['sysCode'])) {
5941
        if (!empty($course_code)) {
5942
            return $course_code == $_SESSION['_course']['sysCode'];
5943
        }
5944
        return true;
5945
    }
5946
    return false;
5947
}
5948
5949
/**
5950
 * Checks whether the curent user is in a group or not.
5951
 *
5952
 * @param string        The group id - optional (takes it from session if not given)
5953
 * @param string        The course code - optional (no additional check by course if course code is not given)
5954
 * @return boolean
5955
 * @author Ivan Tcholakov
5956
 */
5957
function api_is_in_group($groupIdParam = null, $courseCodeParam = null)
5958
{
5959
    if (!empty($courseCodeParam)) {
5960
        $courseCode = api_get_course_id();
5961
        if (!empty($courseCode)) {
5962
            if ($courseCodeParam != $courseCode) {
5963
                return false;
5964
            }
5965
        } else {
5966
            return false;
5967
        }
5968
    }
5969
5970
    $groupId = api_get_group_id();
5971
5972
    if (isset($groupId) && $groupId != '') {
5973
        if (!empty($groupIdParam)) {
5974
            return $groupIdParam == $groupId;
5975
        } else {
5976
            return true;
5977
        }
5978
    }
5979
5980
    return false;
5981
}
5982
5983
5984
/**
5985
 * Checks whether a secret key is valid
5986
 * @param string $original_key_secret  - secret key from (webservice) client
5987
 * @param string $security_key - security key from Chamilo
5988
 * @return boolean - true if secret key is valid, false otherwise
5989
 */
5990
function api_is_valid_secret_key($original_key_secret, $security_key) {
5991
    return $original_key_secret == sha1($security_key);
5992
}
5993
5994
/**
5995
 * Checks whether a user is into course
5996
 * @param int $course_id - the course id
5997
 * @param int $user_id - the user id
5998
 */
5999
function api_is_user_of_course($course_id, $user_id) {
6000
    $tbl_course_rel_user = Database::get_main_table(TABLE_MAIN_COURSE_USER);
6001
    $sql = 'SELECT user_id FROM '.$tbl_course_rel_user.'
6002
            WHERE
6003
                c_id ="'.intval($course_id).'" AND
6004
                user_id = "'.intval($user_id).'" AND
6005
                relation_type <> '.COURSE_RELATION_TYPE_RRHH.' ';
6006
    $result = Database::query($sql);
6007
    return Database::num_rows($result) == 1;
6008
}
6009
6010
/**
6011
 * Checks whether the server's operating system is Windows (TM).
6012
 * @return boolean - true if the operating system is Windows, false otherwise
6013
 */
6014
function api_is_windows_os() {
6015
    if (function_exists('php_uname')) {
6016
        // php_uname() exists as of PHP 4.0.2, according to the documentation.
6017
        // We expect that this function will always work for Chamilo 1.8.x.
6018
        $os = php_uname();
6019
    }
6020
    // The following methods are not needed, but let them stay, just in case.
6021
    elseif (isset($_ENV['OS'])) {
6022
        // Sometimes $_ENV['OS'] may not be present (bugs?)
6023
        $os = $_ENV['OS'];
6024
    }
6025
    elseif (defined('PHP_OS')) {
6026
        // PHP_OS means on which OS PHP was compiled, this is why
6027
        // using PHP_OS is the last choice for detection.
6028
        $os = PHP_OS;
6029
    } else {
6030
        return false;
6031
    }
6032
    return strtolower(substr((string)$os, 0, 3 )) == 'win';
6033
}
6034
6035
/**
6036
 * This function informs whether the sent request is XMLHttpRequest
6037
 */
6038
function api_is_xml_http_request() {
6039
    return isset($_SERVER['HTTP_X_REQUESTED_WITH']) && strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest';
6040
}
6041
6042
/**
6043
 * This wrapper function has been implemented for avoiding some known problems about the function getimagesize().
6044
 * @link http://php.net/manual/en/function.getimagesize.php
6045
 * @link http://www.dokeos.com/forum/viewtopic.php?t=12345
6046
 * @link http://www.dokeos.com/forum/viewtopic.php?t=16355
6047
 * @return integer
6048
 */
6049
function api_getimagesize($path) {
6050
    $image = new Image($path);
6051
    return $image->get_image_size();
6052
}
6053
6054
/**
6055
 * This function resizes an image, with preserving its proportions (or aspect ratio).
6056
 * @author Ivan Tcholakov, MAY-2009.
6057
 * @param int $image            System path or URL of the image
6058
 * @param int $target_width     Targeted width
6059
 * @param int $target_height    Targeted height
6060
 * @return array                Calculated new width and height
6061
 */
6062
function api_resize_image($image, $target_width, $target_height) {
6063
    $image_properties = api_getimagesize($image);
6064
    return api_calculate_image_size($image_properties['width'], $image_properties['height'], $target_width, $target_height);
6065
}
6066
6067
/**
6068
 * This function calculates new image size, with preserving image's proportions (or aspect ratio).
6069
 * @author Ivan Tcholakov, MAY-2009.
6070
 * @author The initial idea has been taken from code by Patrick Cool, MAY-2004.
6071
 * @param int $image_width      Initial width
6072
 * @param int $image_height     Initial height
6073
 * @param int $target_width     Targeted width
6074
 * @param int $target_height    Targeted height
6075
 * @return array                Calculated new width and height
6076
 */
6077
function api_calculate_image_size($image_width, $image_height, $target_width, $target_height) {
6078
    // Only maths is here.
6079
    $result = array('width' => $image_width, 'height' => $image_height);
6080
    if ($image_width <= 0 || $image_height <= 0) {
6081
        return $result;
6082
    }
6083
    $resize_factor_width = $target_width / $image_width;
6084
    $resize_factor_height = $target_height / $image_height;
6085
    $delta_width = $target_width - $image_width * $resize_factor_height;
6086
    $delta_height = $target_height - $image_height * $resize_factor_width;
6087
    if ($delta_width > $delta_height) {
6088
        $result['width'] = ceil($image_width * $resize_factor_height);
6089
        $result['height'] = ceil($image_height * $resize_factor_height);
6090
    }
6091
    elseif ($delta_width < $delta_height) {
6092
        $result['width'] = ceil($image_width * $resize_factor_width);
6093
        $result['height'] = ceil($image_height * $resize_factor_width);
6094
    }
6095
    else {
6096
        $result['width'] = ceil($target_width);
6097
        $result['height'] = ceil($target_height);
6098
    }
6099
    return $result;
6100
}
6101
6102
/**
6103
 * Returns a list of Chamilo's tools or
6104
 * checks whether a given identificator is a valid Chamilo's tool.
6105
 * @author Isaac flores paz
6106
 * @param string The tool name to filter
6107
 * @return mixed Filtered string or array
6108
 */
6109
function api_get_tools_lists($my_tool = null) {
6110
    $tools_list = array(
6111
        TOOL_DOCUMENT, TOOL_THUMBNAIL, TOOL_HOTPOTATOES,
6112
        TOOL_CALENDAR_EVENT, TOOL_LINK, TOOL_COURSE_DESCRIPTION, TOOL_SEARCH,
6113
        TOOL_LEARNPATH, TOOL_ANNOUNCEMENT, TOOL_FORUM, TOOL_THREAD, TOOL_POST,
6114
        TOOL_DROPBOX, TOOL_QUIZ, TOOL_USER, TOOL_GROUP, TOOL_BLOGS, TOOL_CHAT,
6115
        TOOL_CONFERENCE, TOOL_STUDENTPUBLICATION, TOOL_TRACKING, TOOL_HOMEPAGE_LINK,
6116
        TOOL_COURSE_SETTING, TOOL_BACKUP, TOOL_COPY_COURSE_CONTENT, TOOL_RECYCLE_COURSE,
6117
        TOOL_COURSE_HOMEPAGE, TOOL_COURSE_RIGHTS_OVERVIEW, TOOL_UPLOAD, TOOL_COURSE_MAINTENANCE,
6118
        TOOL_VISIO, TOOL_VISIO_CONFERENCE, TOOL_VISIO_CLASSROOM, TOOL_SURVEY, TOOL_WIKI,
6119
        TOOL_GLOSSARY, TOOL_GRADEBOOK, TOOL_NOTEBOOK, TOOL_ATTENDANCE, TOOL_COURSE_PROGRESS
6120
    );
6121
    if (empty($my_tool)) {
6122
        return $tools_list;
6123
    }
6124
    return in_array($my_tool, $tools_list) ? $my_tool : '';
6125
}
6126
6127
/**
6128
 * Checks whether we already approved the last version term and condition
6129
 * @param int user id
6130
 * @return bool true if we pass false otherwise
6131
 */
6132
function api_check_term_condition($user_id)
6133
{
6134
    if (api_get_setting('allow_terms_conditions') == 'true') {
6135
        //check if exists terms and conditions
6136
        if (LegalManager::count() == 0) {
6137
            return true;
6138
        }
6139
6140
        $extraFieldValue = new ExtraFieldValue('user');
6141
        $data = $extraFieldValue->get_values_by_handler_and_field_variable(
6142
            $user_id,
6143
            'legal_accept'
6144
        );
6145
6146
        if (!empty($data) && isset($data['value'])) {
6147
            $rowv = $data['value'];
6148
            $user_conditions = explode(':', $rowv);
6149
            $version = $user_conditions[0];
6150
            $lang_id = $user_conditions[1];
6151
            $real_version = LegalManager::get_last_version($lang_id);
6152
6153
            return $version >= $real_version;
6154
        }
6155
        return false;
6156
    }
6157
    return false;
6158
}
6159
6160
/**
6161
 * Gets all information of a tool into course
6162
 * @param int The tool id
6163
 * @return array
6164
 */
6165
function api_get_tool_information($tool_id) {
6166
    $t_tool = Database::get_course_table(TABLE_TOOL_LIST);
6167
    $course_id = api_get_course_int_id();
6168
    $sql = "SELECT * FROM $t_tool WHERE c_id = $course_id AND id = ".intval($tool_id);
6169
    $rs  = Database::query($sql);
6170
    return Database::fetch_array($rs);
6171
}
6172
6173
/**
6174
 * Gets all information of a tool into course
6175
 * @param int The tool id
6176
 * @return array
6177
 */
6178
function api_get_tool_information_by_name($name) {
6179
    $t_tool = Database::get_course_table(TABLE_TOOL_LIST);
6180
    $course_id = api_get_course_int_id();
6181
    $sql = "SELECT * FROM $t_tool
6182
            WHERE c_id = $course_id  AND name = '".Database::escape_string($name)."' ";
6183
    $rs  = Database::query($sql);
6184
    return Database::fetch_array($rs, 'ASSOC');
6185
}
6186
6187
/**
6188
 * @deprecated use api_trunc_str() instead.
6189
 */
6190
function shorten($input, $length = 15, $encoding = null) {
6191
    $length = intval($length);
6192
    if (!$length) {
6193
        $length = 15;
6194
    }
6195
    return api_trunc_str($input, $length, '...', false, $encoding);
6196
}
6197
6198
6199
/**
6200
 * Function used to protect a "global" admin script.
6201
 * The function blocks access when the user has no global platform admin rights.
6202
 * Global admins are the admins that are registered in the main.admin table
6203
 * AND the users who have access to the "principal" portal.
6204
 * That means that there is a record in the main.access_url_rel_user table
6205
 * with his user id and the access_url_id=1
6206
 *
6207
 * @author Julio Montoya
6208
 * @param integer $user_id
6209
 */
6210
function api_is_global_platform_admin($user_id = null)
6211
{
6212
    $user_id = intval($user_id);
6213
    if (empty($user_id)) {
6214
        $user_id = api_get_user_id();
6215
    }
6216
    if (api_is_platform_admin_by_id($user_id)) {
6217
        $urlList = api_get_access_url_from_user($user_id);
6218
        // The admin is registered in the first "main" site with access_url_id = 1
6219
        if (in_array(1, $urlList)) {
6220
            return true;
6221
        } else {
6222
            return false;
6223
        }
6224
    }
6225
    return false;
6226
}
6227
6228
/**
6229
 * @param int $admin_id_to_check
6230
 * @param int  $my_user_id
6231
 * @param bool $allow_session_admin
6232
 * @return bool
6233
 */
6234
function api_global_admin_can_edit_admin($admin_id_to_check, $my_user_id = null, $allow_session_admin = false)
6235
{
6236
    if (empty($my_user_id)) {
6237
        $my_user_id = api_get_user_id();
6238
    }
6239
6240
    $iam_a_global_admin = api_is_global_platform_admin($my_user_id);
6241
    $user_is_global_admin = api_is_global_platform_admin($admin_id_to_check);
6242
6243
    if ($iam_a_global_admin) {
6244
        // Global admin can edit everything
6245
        return true;
6246
    } else {
6247
        // If i'm a simple admin
6248
        $is_platform_admin = api_is_platform_admin_by_id($my_user_id);
6249
6250
        if ($allow_session_admin) {
6251
            $is_platform_admin = api_is_platform_admin_by_id($my_user_id) || (api_get_user_status($my_user_id) == SESSIONADMIN);
6252
        }
6253
6254
        if ($is_platform_admin) {
6255
            if ($user_is_global_admin) {
6256
                return false;
6257
            } else {
6258
                return true;
6259
            }
6260
        } else {
6261
            return false;
6262
        }
6263
    }
6264
}
6265
6266
/**
6267
 * @param int $admin_id_to_check
6268
 * @param int  $my_user_id
6269
 * @param bool $allow_session_admin
6270
 * @return boolean|null
6271
 */
6272
function api_protect_super_admin($admin_id_to_check, $my_user_id = null, $allow_session_admin = false)
6273
{
6274
    if (api_global_admin_can_edit_admin($admin_id_to_check, $my_user_id, $allow_session_admin)) {
6275
        return true;
6276
    } else {
6277
        api_not_allowed();
6278
    }
6279
}
6280
6281
/**
6282
 * Function used to protect a global admin script.
6283
 * The function blocks access when the user has no global platform admin rights.
6284
 * See also the api_is_global_platform_admin() function wich defines who's a "global" admin
6285
 *
6286
 * @author Julio Montoya
6287
 */
6288
function api_protect_global_admin_script() {
6289
    if (!api_is_global_platform_admin()) {
6290
        api_not_allowed();
6291
        return false;
6292
    }
6293
    return true;
6294
}
6295
6296
/**
6297
 * Get active template
6298
 * @param string    theme type (optional: default)
6299
 * @param string    path absolute(abs) or relative(rel) (optional:rel)
6300
 * @return string   actived template path
6301
 */
6302
function api_get_template($path_type = 'rel') {
6303
    $path_types = array('rel', 'abs');
6304
    $template_path = '';
6305
    if (in_array($path_type, $path_types)) {
6306
        if ($path_type == 'rel') {
6307
            $template_path = api_get_path(SYS_TEMPLATE_PATH);
6308
        } else {
6309
            $template_path = api_get_path(WEB_TEMPLATE_PATH);
6310
        }
6311
    }
6312
    $actived_theme = 'default';
6313
    if (api_get_setting('active_template')) {
6314
        $actived_theme = api_get_setting('active_template');
6315
    }
6316
    $actived_theme_path = $template_path.$actived_theme.DIRECTORY_SEPARATOR;
6317
    return $actived_theme_path;
6318
}
6319
6320
/**
6321
 * Check browser support for type files
6322
 * This function check if the users browser support a file format or
6323
 * return the current browser and major ver when $format=check_browser
6324
 * @param string $format
6325
 *
6326
 * @return bool, or return text array if $format=check_browser
6327
 * @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...
6328
 */
6329
6330
function api_browser_support($format = "")
6331
{
6332
    $browser = new Browser();
6333
    $current_browser = $browser->getBrowser();
6334
    $a_versiontemp = explode('.', $browser->getVersion());
6335
    $current_majorver = $a_versiontemp[0];
6336
6337
    // Native svg support
6338
    if ($format == 'svg') {
6339
        if (($current_browser == 'Internet Explorer' && $current_majorver >= 9) ||
6340
            ($current_browser == 'Firefox' && $current_majorver > 1) ||
6341
            ($current_browser == 'Safari' && $current_majorver >= 4) ||
6342
            ($current_browser == 'Chrome' && $current_majorver >= 1) ||
6343
            ($current_browser == 'Opera' && $current_majorver >= 9)
6344
        ) {
6345
            return true;
6346
        } else {
6347
            return false;
6348
        }
6349
    } elseif ($format == 'pdf') {
6350
        //native pdf support
6351
        if ($current_browser == 'Chrome' && $current_majorver >= 6) {
6352
            return true;
6353
        } else {
6354
            return false;
6355
        }
6356
    } elseif ($format == 'tif' || $format == 'tiff') {
6357
        //native tif support
6358
        if ($current_browser == 'Safari' && $current_majorver >= 5) {
6359
            return true;
6360
        } else {
6361
            return false;
6362
        }
6363 View Code Duplication
    } elseif ($format == 'ogg' || $format == 'ogx' || $format == 'ogv' || $format == 'oga') {
6364
        //native ogg, ogv,oga support
6365
        if (($current_browser == 'Firefox' && $current_majorver >= 3) ||
6366
            ($current_browser == 'Chrome' && $current_majorver >= 3) ||
6367
            ($current_browser == 'Opera' && $current_majorver >= 9)) {
6368
            return true;
6369
        } else {
6370
            return false;
6371
        }
6372
    } elseif ($format == 'mpg' || $format == 'mpeg') {
6373
        //native mpg support
6374
        if (($current_browser == 'Safari' && $current_majorver >= 5)) {
6375
            return true;
6376
        } else {
6377
            return false;
6378
        }
6379
    } elseif ($format == 'mp4') {
6380
        //native mp4 support (TODO: Android, iPhone)
6381
        if ($current_browser == 'Android' || $current_browser == 'iPhone') {
6382
            return true;
6383
        } else {
6384
            return false;
6385
        }
6386
    } elseif ($format == 'mov') {
6387
        //native mov support( TODO:check iPhone)
6388
        if ($current_browser == 'Safari' && $current_majorver >= 5 || $current_browser == 'iPhone') {
6389
            return true;
6390
        } else {
6391
            return false;
6392
        }
6393
    } elseif ($format == 'avi') {
6394
        //native avi support
6395
        if ($current_browser == 'Safari' && $current_majorver >= 5) {
6396
            return true;
6397
        } else {
6398
            return false;
6399
        }
6400
    } elseif ($format == 'wmv') {
6401
        //native wmv support
6402
        if ($current_browser == 'Firefox' && $current_majorver >= 4) {
6403
            return true;
6404
        } else {
6405
            return false;
6406
        }
6407 View Code Duplication
    } elseif ($format == 'webm') {
6408
        //native webm support (TODO:check IE9, Chrome9, Android)
6409
        if (($current_browser == 'Firefox' && $current_majorver >= 4) ||
6410
            ($current_browser == 'Opera' && $current_majorver >= 9) ||
6411
            ($current_browser == 'Internet Explorer' && $current_majorver >= 9) ||
6412
            ($current_browser == 'Chrome' && $current_majorver >= 9) ||
6413
            $current_browser == 'Android'
6414
        ) {
6415
            return true;
6416
        } else {
6417
            return false;
6418
        }
6419
    } elseif ($format == 'wav') {
6420
        //native wav support (only some codecs !)
6421
        if (($current_browser == 'Firefox' && $current_majorver >= 4) ||
6422
            ($current_browser == 'Safari' && $current_majorver >= 5) ||
6423
            ($current_browser == 'Opera' && $current_majorver >= 9) ||
6424
            ($current_browser == 'Internet Explorer' && $current_majorver >= 9) ||
6425
            ($current_browser == 'Chrome' && $current_majorver > 9) ||
6426
            $current_browser == 'Android' ||
6427
            $current_browser == 'iPhone'
6428
        ) {
6429
            return true;
6430
        } else {
6431
            return false;
6432
        }
6433
    } elseif ($format == 'mid' || $format == 'kar') {
6434
        //native midi support (TODO:check Android)
6435
        if ($current_browser == 'Opera' && $current_majorver >= 9 || $current_browser == 'Android') {
6436
            return true;
6437
        } else {
6438
            return false;
6439
        }
6440
    } elseif ($format == 'wma') {
6441
        //native wma support
6442
        if ($current_browser == 'Firefox' && $current_majorver >= 4) {
6443
            return true;
6444
        } else {
6445
            return false;
6446
        }
6447
    } elseif ($format == 'au') {
6448
        //native au support
6449
        if ($current_browser == 'Safari' && $current_majorver >= 5) {
6450
            return true;
6451
        } else {
6452
            return false;
6453
        }
6454 View Code Duplication
    } elseif ($format == 'mp3') {
6455
        //native mp3 support (TODO:check Android, iPhone)
6456
        if (($current_browser == 'Safari' && $current_majorver >= 5) ||
6457
            ($current_browser == 'Chrome' && $current_majorver >= 6) ||
6458
            ($current_browser == 'Internet Explorer' && $current_majorver >= 9) ||
6459
            $current_browser == 'Android' ||
6460
            $current_browser == 'iPhone' ||
6461
            $current_browser == 'Firefox'
6462
        ) {
6463
            return true;
6464
        } else {
6465
            return false;
6466
        }
6467
    } elseif ($format == "check_browser") {
6468
        $array_check_browser = array($current_browser, $current_majorver);
6469
        return $array_check_browser;
6470
    } else {
6471
        return false;
6472
    }
6473
}
6474
6475
/**
6476
 * This function checks if exist path and file browscap.ini
6477
 * In order for this to work, your browscap configuration setting in php.ini
6478
 * must point to the correct location of the browscap.ini file on your system
6479
 * http://php.net/manual/en/function.get-browser.php
6480
 *
6481
 * @return bool
6482
 *
6483
 * @author Juan Carlos Raña Trabado
6484
 */
6485
function api_check_browscap() {
6486
    $setting = ini_get('browscap');
6487
    if ($setting) {
6488
        $browser = get_browser($_SERVER['HTTP_USER_AGENT'], true);
6489
        if (strpos($setting, 'browscap.ini') && !empty($browser)) {
6490
            return true;
6491
        }
6492
    }
6493
    return false;
6494
}
6495
6496
/**
6497
 * Returns the <script> HTML tag
6498
 */
6499
function api_get_js($file) {
6500
    return '<script type="text/javascript" src="'.api_get_path(WEB_LIBRARY_PATH).'javascript/'.$file.'"></script>'."\n";
6501
}
6502
6503
/**
6504
 * Returns the <script> HTML tag
6505
 */
6506
function api_get_asset($file) {
6507
    return '<script type="text/javascript" src="'.api_get_path(WEB_PATH).'web/assets/'.$file.'"></script>'."\n";
6508
}
6509
6510
/**
6511
 * Returns the <link> HTML tag
6512
 * @param string $file
6513
 */
6514
function api_get_css($file, $media = 'screen') {
6515
    return '<link href="'.$file.'" rel="stylesheet" media="'.$media.'" type="text/css" />'."\n";
6516
}
6517
6518
/**
6519
 * Returns the js header to include the jquery library
6520
 */
6521
function api_get_jquery_js()
6522
{
6523
    return api_get_asset('jquery/dist/jquery.min.js');
6524
}
6525
6526
/**
6527
 * Returns the jquery path
6528
 * @return string
6529
 */
6530
function api_get_jquery_web_path()
6531
{
6532
    return api_get_path(WEB_PATH).'web/assets/jquery/dist/jquery.min.js';
6533
}
6534
6535
/**
6536
 * @return string
6537
 */
6538
function api_get_jquery_ui_js_web_path()
6539
{
6540
    return api_get_path(WEB_PATH).'web/assets/jquery-ui/jquery-ui.min.js';
6541
}
6542
6543
/**
6544
 * @return string
6545
 */
6546
function api_get_jquery_ui_css_web_path()
6547
{
6548
    return api_get_path(WEB_PATH).'web/assets/jquery-ui/themes/smoothness/jquery-ui.min.css';
6549
}
6550
6551
/**
6552
 * Returns the jquery-ui library js headers
6553
 * @param   bool    add the jqgrid library
6554
 * @return  string  html tags
6555
 *
6556
 */
6557
function api_get_jquery_ui_js($include_jqgrid = false) {
6558
    $libraries = array();
6559
    if ($include_jqgrid) {
6560
       $libraries[]='jqgrid';
6561
    }
6562
    return api_get_jquery_libraries_js($libraries);
6563
}
6564
6565
function api_get_jqgrid_js() {
6566
    return api_get_jquery_libraries_js(array('jqgrid'));
6567
}
6568
6569
6570
/**
6571
 * Returns the jquery library js and css headers
6572
 *
6573
 * @param   array   list of jquery libraries supported jquery-ui, jqgrid
6574
 * @param   bool    add the jquery library
6575
 * @return  string  html tags
6576
 *
6577
 */
6578
function api_get_jquery_libraries_js($libraries) {
6579
    $js = '';
6580
    $js_path = api_get_path(WEB_LIBRARY_PATH).'javascript/';
6581
6582
    //jqgrid js and css
6583
    if (in_array('jqgrid', $libraries)) {
6584
        $languaje   = 'en';
6585
        $platform_isocode = strtolower(api_get_language_isocode());
6586
6587
        //languages supported by jqgrid see files in main/inc/lib/javascript/jqgrid/js/i18n
6588
        $jqgrid_langs = array(
6589
            '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'
6590
        );
6591
6592
        if (in_array($platform_isocode, $jqgrid_langs)) {
6593
            $languaje = $platform_isocode;
6594
        }
6595
        //$js .= '<link rel="stylesheet" href="'.$js_path.'jqgrid/css/ui.jqgrid.css" type="text/css">';
6596
        $js .= api_get_css($js_path.'jqgrid/css/ui.jqgrid.css');
6597
        $js .= api_get_js('jqgrid/js/i18n/grid.locale-'.$languaje.'.js');
6598
        $js .= api_get_js('jqgrid/js/jquery.jqGrid.min.js');
6599
    }
6600
6601
    //Document multiple upload funcionality
6602
    if (in_array('jquery-upload', $libraries)) {
6603
6604
        $js .= api_get_asset('blueimp-load-image/js/load-image.all.min.js');
6605
        $js .= api_get_asset('blueimp-canvas-to-blob/js/canvas-to-blob.min.js');
6606
        $js .= api_get_asset('jquery-file-upload/js/jquery.iframe-transport.js');
6607
        $js .= api_get_asset('jquery-file-upload/js/jquery.fileupload.js');
6608
        $js .= api_get_asset('jquery-file-upload/js/jquery.fileupload-process.js');
6609
        $js .= api_get_asset('jquery-file-upload/js/jquery.fileupload-image.js');
6610
        $js .= api_get_asset('jquery-file-upload/js/jquery.fileupload-audio.js');
6611
        $js .= api_get_asset('jquery-file-upload/js/jquery.fileupload-video.js');
6612
        $js .= api_get_asset('jquery-file-upload/js/jquery.fileupload-validate.js');
6613
6614
        $js .= api_get_css(api_get_path(WEB_PATH).'web/assets/jquery-file-upload/css/jquery.fileupload.css');
6615
        $js .= api_get_css(api_get_path(WEB_PATH).'web/assets/jquery-file-upload/css/jquery.fileupload-ui.css');
6616
    }
6617
6618
    // jquery datepicker
6619
    if (in_array('datepicker', $libraries)) {
6620
        $languaje   = 'en-GB';
6621
        $platform_isocode = strtolower(api_get_language_isocode());
6622
6623
        // languages supported by jqgrid see files in main/inc/lib/javascript/jqgrid/js/i18n
6624
        $datapicker_langs = array(
6625
            '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'
6626
        );
6627
        if (in_array($platform_isocode, $datapicker_langs)) {
6628
            $languaje = $platform_isocode;
6629
        }
6630
6631
        $js .= api_get_js('jquery-ui/jquery-ui-i18n.min.js');
6632
        $script = '<script>
6633
        $(function(){
6634
            $.datepicker.setDefaults($.datepicker.regional["'.$languaje.'"]);
6635
            $.datepicker.regional["local"] = $.datepicker.regional["'.$languaje.'"];
6636
        });
6637
        </script>
6638
        ';
6639
        $js .= $script;
6640
    }
6641
    return $js;
6642
}
6643
6644
/**
6645
 * Returns the course's URL
6646
 *
6647
 * This function relies on api_get_course_info()
6648
 * @param   string  The course code - optional (takes it from session if not given)
6649
 * @param   int     The session id  - optional (takes it from session if not given)
6650
 * @param integer $session_id
6651
 * @return  string|null   The URL of the course or null if something does not work
6652
 * @author  Julio Montoya <[email protected]>
6653
 */
6654
function api_get_course_url($course_code = null, $session_id = null)
6655
{
6656
    if (empty($course_code)) {
6657
        $course_info = api_get_course_info();
6658
    } else {
6659
        $course_info = api_get_course_info($course_code);
6660
    }
6661
    if (empty($session_id)) {
6662
        $session_url = '?id_session='.api_get_session_id();
6663
    } else {
6664
        $session_url = '?id_session='.intval($session_id);
6665
    }
6666
    /*
6667
    if (empty($group_id)) {
6668
        $group_url = '&gidReq='.api_get_group_id();
6669
    } else {
6670
        $group_url = '&gidReq='.intval($group_id);
6671
    }*/
6672
    if (!empty($course_info['path'])) {
6673
        return api_get_path(WEB_COURSE_PATH).$course_info['path'].'/index.php'.$session_url;
6674
    }
6675
    return null;
6676
}
6677
6678
/**
6679
 *
6680
 * Check if the current portal has the $_configuration['multiple_access_urls'] parameter on
6681
 * @return bool true if multi site is enabled
6682
 *
6683
 * */
6684
function api_get_multiple_access_url() {
6685
    global $_configuration;
6686
    if (isset($_configuration['multiple_access_urls']) && $_configuration['multiple_access_urls']) {
6687
        return true;
6688
    }
6689
    return false;
6690
}
6691
6692
/**
6693
 * @return bool
6694
 */
6695
function api_is_multiple_url_enabled() {
6696
    return api_get_multiple_access_url();
6697
}
6698
6699
/**
6700
 * Returns a md5 unique id
6701
 * @todo add more parameters
6702
 */
6703
function api_get_unique_id() {
6704
    $id = md5(time().uniqid().api_get_user_id().api_get_course_id().api_get_session_id());
6705
    return $id;
6706
}
6707
6708
/**
6709
 * Get home path
6710
 * @return string
6711
 */
6712
function api_get_home_path()
6713
{
6714
    $home = 'app/home/';
6715
    if (api_get_multiple_access_url()) {
6716
        $access_url_id = api_get_current_access_url_id();
6717
        $url_info = api_get_access_url($access_url_id);
6718
        $url = api_remove_trailing_slash(preg_replace('/https?:\/\//i', '', $url_info['url']));
6719
        $clean_url = api_replace_dangerous_char($url);
6720
        $clean_url = str_replace('/', '-', $clean_url);
6721
        $clean_url .= '/';
6722
6723
        $home = 'app/home/' . $clean_url;
6724
    }
6725
6726
    return $home;
6727
}
6728
6729
/**
6730
 *
6731
 * @param int Course id
6732
 * @param int tool id: TOOL_QUIZ, TOOL_FORUM, TOOL_STUDENTPUBLICATION, TOOL_LEARNPATH
6733
 * @param int the item id (tool id, exercise id, lp id)
6734
 *
6735
 */
6736
function api_resource_is_locked_by_gradebook($item_id, $link_type, $course_code = null) {
6737
    if (api_is_platform_admin()) {
6738
        return false;
6739
    }
6740
    if (api_get_setting('gradebook_locking_enabled') == 'true') {
6741
        if (empty($course_code)) {
6742
            $course_code = api_get_course_id();
6743
        }
6744
        $table = Database::get_main_table(TABLE_MAIN_GRADEBOOK_LINK);
6745
        $item_id = intval($item_id);
6746
        $link_type = intval($link_type);
6747
        $course_code = Database::escape_string($course_code);
6748
        $sql = "SELECT locked FROM $table
6749
                WHERE locked = 1 AND ref_id = $item_id AND type = $link_type AND course_code = '$course_code' ";
6750
        $result = Database::query($sql);
6751
        if (Database::num_rows($result)) {
6752
            return true;
6753
        }
6754
    }
6755
    return false;
6756
}
6757
6758
/**
6759
 * Blocks a page if the item was added in a gradebook
6760
 *
6761
 * @param int       exercise id, work id, thread id,
6762
 * @param int       LINK_EXERCISE, LINK_STUDENTPUBLICATION, LINK_LEARNPATH LINK_FORUM_THREAD, LINK_ATTENDANCE
6763
 * see gradebook/lib/be/linkfactory
6764
 * @param string    course code
6765
 * @return false|null
6766
 */
6767
function api_block_course_item_locked_by_gradebook($item_id, $link_type, $course_code = null) {
6768
    if (api_is_platform_admin()) {
6769
        return false;
6770
    }
6771
6772
    if (api_resource_is_locked_by_gradebook($item_id, $link_type, $course_code)) {
6773
        $message = Display::return_message(get_lang('ResourceLockedByGradebook'), 'warning');
6774
        api_not_allowed(true, $message);
6775
    }
6776
}
6777
/**
6778
 * Checks the PHP version installed is enough to run Chamilo
6779
 * @param string Include path (used to load the error page)
6780
 * @return void
6781
 */
6782
function api_check_php_version($my_inc_path = null) {
6783
    if (!function_exists('version_compare') || version_compare( phpversion(), REQUIRED_PHP_VERSION, '<')) {
6784
        $global_error_code = 1;
6785
        // Incorrect PHP version
6786
        $global_page = $my_inc_path.'global_error_message.inc.php';
6787
        if (file_exists($global_page)) {
6788
            require $global_page;
6789
        }
6790
        exit;
6791
    }
6792
}
6793
/**
6794
 * Checks whether the Archive directory is present and writeable. If not,
6795
 * prints a warning message.
6796
 */
6797
function api_check_archive_dir() {
6798 View Code Duplication
    if (is_dir(api_get_path(SYS_ARCHIVE_PATH)) && !is_writable(api_get_path(SYS_ARCHIVE_PATH))) {
6799
        $message = Display::return_message(get_lang('ArchivesDirectoryNotWriteableContactAdmin'),'warning');
6800
        api_not_allowed(true, $message);
6801
    }
6802
}
6803
/**
6804
 * Returns an array of global configuration settings which should be ignored
6805
 * when printing the configuration settings screens
6806
 * @return array Array of strings, each identifying one of the excluded settings
6807
 */
6808
function api_get_locked_settings() {
6809
    return array(
6810
        'server_type',
6811
        'permanently_remove_deleted_files',
6812
        'account_valid_duration',
6813
        'service_visio',
6814
        'service_ppt2lp',
6815
        'wcag_anysurfer_public_pages',
6816
        'upload_extensions_list_type',
6817
        'upload_extensions_blacklist',
6818
        'upload_extensions_whitelist',
6819
        'upload_extensions_skip',
6820
        'upload_extensions_replace_by',
6821
        'hide_dltt_markup',
6822
        'split_users_upload_directory',
6823
        'permissions_for_new_directories',
6824
        'permissions_for_new_files',
6825
        'platform_charset',
6826
        'service_visio',
6827
        'ldap_description',
6828
        'cas_activate',
6829
        'cas_server',
6830
        'cas_server_uri',
6831
        'cas_port',
6832
        'cas_protocol',
6833
        'cas_add_user_activate',
6834
        'update_user_info_cas_with_ldap',
6835
        'languagePriority1',
6836
        'languagePriority2',
6837
        'languagePriority3',
6838
        'languagePriority4',
6839
        'login_is_email',
6840
        'chamilo_database_version'
6841
    );
6842
}
6843
6844
/**
6845
 * Checks if the user is corrently logged in. Returns the user ID if he is, or
6846
 * false if he isn't. If the user ID is given and is an integer, then the same
6847
 * ID is simply returned
6848
 * @param  integer User ID
6849
 * @return boolean Integer User ID is logged in, or false otherwise
6850
 */
6851
function api_user_is_login($user_id = null) {
6852
    $user_id = empty($user_id) ? api_get_user_id() : intval($user_id);
6853
    return $user_id && !api_is_anonymous();
6854
}
6855
6856
/**
6857
 * Guess the real ip for register in the database, even in reverse proxy cases.
6858
 * To be recognized, the IP has to be found in either $_SERVER['REMOTE_ADDR'] or
6859
 * in $_SERVER['HTTP_X_FORWARDED_FOR'], which is in common use with rproxies.
6860
 * @return string the user's real ip (unsafe - escape it before inserting to db)
6861
 * @author Jorge Frisancho Jibaja <[email protected]>, USIL - Some changes to allow the use of real IP using reverse proxy
6862
 * @version CEV CHANGE 24APR2012
6863
 */
6864
function api_get_real_ip(){
6865
    // Guess the IP if behind a reverse proxy
6866
    global $debug;
6867
    $ip = trim($_SERVER['REMOTE_ADDR']);
6868
    if (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) {
6869
        if (preg_match('/,/', $_SERVER['HTTP_X_FORWARDED_FOR'])) {
6870
            @list($ip1, $ip2) = @explode(',', $_SERVER['HTTP_X_FORWARDED_FOR']);
6871
        } else {
6872
            $ip1 = $_SERVER['HTTP_X_FORWARDED_FOR'];
6873
        }
6874
        $ip = trim($ip1);
6875
    }
6876
    if (!empty($debug)) error_log('Real IP: '.$ip);
6877
    return $ip;
6878
}
6879
6880
/**
6881
 * Checks whether an IP is included inside an IP range
6882
 * @param string IP address
6883
 * @param string IP range
6884
 * @param string $ip
6885
 * @return bool True if IP is in the range, false otherwise
6886
 * @author claudiu at cnixs dot com  on http://www.php.net/manual/fr/ref.network.php#55230
6887
 * @author Yannick Warnier for improvements and managment of multiple ranges
6888
 * @todo check for IPv6 support
6889
 */
6890
function api_check_ip_in_range($ip,$range)
6891
{
6892
    if (empty($ip) or empty($range)) {
6893
        return false;
6894
    }
6895
    $ip_ip = ip2long ($ip);
6896
    // divide range param into array of elements
6897
    if (strpos($range,',')!==false) {
6898
        $ranges = explode(',',$range);
6899
    } else {
6900
        $ranges = array($range);
6901
    }
6902
    foreach ($ranges as $range) {
6903
        $range = trim($range);
6904
        if (empty($range)) { continue; }
6905
        if (strpos($range,'/')===false) {
6906
            if (strcmp($ip,$range)===0) {
6907
                return true; // there is a direct IP match, return OK
6908
            }
6909
            continue; //otherwise, get to the next range
6910
        }
6911
        // the range contains a "/", so analyse completely
6912
        list ($net, $mask) = explode("/", $range);
6913
6914
        $ip_net = ip2long ($net);
6915
        // mask binary magic
6916
        $ip_mask = ~((1 << (32 - $mask)) - 1);
6917
6918
        $ip_ip_net = $ip_ip & $ip_mask;
6919
        if ($ip_ip_net == $ip_net) {
6920
            return true;
6921
        }
6922
    }
6923
6924
    return false;
6925
}
6926
6927
function api_check_user_access_to_legal($course_visibility) {
6928
    $course_visibility_list = array(COURSE_VISIBILITY_OPEN_WORLD, COURSE_VISIBILITY_OPEN_PLATFORM);
6929
    return in_array($course_visibility, $course_visibility_list) || api_is_drh();
6930
}
6931
6932
/**
6933
 * Checks if the global chat is enabled or not
6934
 *
6935
 * @return bool
6936
 */
6937
function api_is_global_chat_enabled()
6938
{
6939
    return
6940
        !api_is_anonymous() &&
6941
        api_get_setting('allow_global_chat') == 'true' &&
6942
        api_get_setting('allow_social_tool') == 'true';
6943
}
6944
6945
/**
6946
 * @todo Fix tool_visible_by_default_at_creation labels
6947
 * @todo Add sessionId parameter to avoid using context
6948
 *
6949
 * @param int $item_id
6950
 * @param int $tool_id
6951
 * @param int $group_id
6952
 * @param array $courseInfo
6953
 */
6954
function api_set_default_visibility($item_id, $tool_id, $group_id = 0, $courseInfo = array(), $sessionId = 0, $userId = 0)
6955
{
6956
    $courseInfo = empty($courseInfo) ? api_get_course_info() : $courseInfo;
6957
    $courseId = $courseInfo['real_id'];
6958
    $courseCode = $courseInfo['code'];
6959
    $sessionId = empty($sessionId) ? api_get_session_id() : $sessionId;
6960
    $userId = empty($userId) ? api_get_user_id() : $userId;
6961
6962
    $original_tool_id = $tool_id;
6963
6964
    switch ($tool_id) {
6965
        case TOOL_LINK:
6966
        case TOOL_LINK_CATEGORY:
6967
            $tool_id = 'links';
6968
            break;
6969
        case TOOL_DOCUMENT:
6970
            $tool_id = 'documents';
6971
            break;
6972
        case TOOL_LEARNPATH:
6973
            $tool_id = 'learning';
6974
            break;
6975
        case TOOL_ANNOUNCEMENT:
6976
            $tool_id = 'announcements';
6977
            break;
6978
        case TOOL_FORUM:
6979
        case TOOL_FORUM_CATEGORY:
6980
        case TOOL_FORUM_THREAD:
6981
            $tool_id = 'forums';
6982
            break;
6983
        case TOOL_QUIZ:
6984
            $tool_id = 'quiz';
6985
            break;
6986
    }
6987
    $setting = api_get_setting('tool_visible_by_default_at_creation');
6988
6989
    if (isset($setting[$tool_id])) {
6990
        $visibility = 'invisible';
6991
        if ($setting[$tool_id] == 'true') {
6992
            $visibility = 'visible';
6993
        }
6994
6995
        if (empty($group_id)) {
6996
            $group_id = api_get_group_id();
6997
        }
6998
6999
        // Read the portal and course default visibility
7000
        if ($tool_id == 'documents') {
7001
            $visibility = DocumentManager::getDocumentDefaultVisibility($courseCode);
7002
        }
7003
7004
        api_item_property_update(
7005
            $courseInfo,
7006
            $original_tool_id,
7007
            $item_id,
7008
            $visibility,
7009
            $userId,
7010
            $group_id,
7011
            null,
7012
            null,
7013
            null,
7014
            api_get_session_id()
7015
        );
7016
7017
        // Fixes default visibility for tests
7018
7019
        switch ($original_tool_id) {
7020
            case TOOL_QUIZ:
7021
                if (empty($sessionId)) {
7022
                    $objExerciseTmp = new Exercise($courseId);
7023
                    $objExerciseTmp->read($item_id);
7024
                    if ($visibility == 'visible') {
7025
                        $objExerciseTmp->enable();
7026
                        $objExerciseTmp->save();
7027
                    } else {
7028
                        $objExerciseTmp->disable();
7029
                        $objExerciseTmp->save();
7030
                    }
7031
                }
7032
                break;
7033
        }
7034
    }
7035
}
7036
7037
/**
7038
 * @return string
7039
 */
7040
function api_get_security_key() {
7041
    return api_get_configuration_value('security_key');
7042
}
7043
7044
/**
7045
 * @param int $user_id
7046
 * @param int $courseId
7047
 * @param int $session_id
7048
 * @return array
7049
 */
7050
function api_detect_user_roles($user_id, $courseId, $session_id = 0)
7051
{
7052
    $user_roles = array();
7053
    /*$user_info = api_get_user_info($user_id);
7054
    $user_roles[] = $user_info['status'];*/
7055
    $courseInfo = api_get_course_info_by_id($courseId);
7056
    $course_code = $courseInfo['code'];
7057
7058
    $url_id = api_get_current_access_url_id();
7059
    if (api_is_platform_admin_by_id($user_id, $url_id)) {
7060
        $user_roles[] = PLATFORM_ADMIN;
7061
    }
7062
7063
    /*if (api_is_drh()) {
7064
        $user_roles[] = DRH;
7065
    }*/
7066
7067
    if (!empty($session_id)) {
7068
        if (SessionManager::user_is_general_coach($user_id, $session_id)) {
7069
            $user_roles[] = SESSION_GENERAL_COACH;
7070
        }
7071
    }
7072
7073
    if (!empty($course_code)) {
7074
        if (empty($session_id)) {
7075
            if (CourseManager::is_course_teacher($user_id, $course_code)) {
7076
                $user_roles[] = COURSEMANAGER;
7077
            }
7078
            if (CourseManager::get_tutor_in_course_status($user_id, $course_code)) {
7079
                $user_roles[] = COURSE_TUTOR;
7080
            }
7081
7082
            if (CourseManager::is_user_subscribed_in_course($user_id, $course_code)) {
7083
                $user_roles[] = COURSE_STUDENT;
7084
            }
7085
        } else {
7086
            $user_status_in_session = SessionManager::get_user_status_in_course_session(
7087
                $user_id,
7088
                $courseId,
7089
                $session_id
7090
            );
7091
7092
            if (!empty($user_status_in_session)) {
7093
                if ($user_status_in_session == 0) {
7094
                    $user_roles[] = SESSION_STUDENT;
7095
                }
7096
                if ($user_status_in_session == 2) {
7097
                    $user_roles[] = SESSION_COURSE_COACH;
7098
                }
7099
            }
7100
7101
            /*if (api_is_course_session_coach($user_id, $course_code, $session_id)) {
7102
               $user_roles[] = SESSION_COURSE_COACH;
7103
            }*/
7104
        }
7105
    }
7106
    return $user_roles;
7107
}
7108
7109
function api_get_roles_to_string($roles) {
7110
    $role_names = array();
7111
    if (!empty($roles)) {
7112
        foreach ($roles as $role) {
7113
            $role_names[] = get_status_from_code($role);
7114
        }
7115
    }
7116
    if (!empty($role_names)) {
7117
        return implode(', ', $role_names);
7118
    }
7119
    return null;
7120
}
7121
7122
function role_actions() {
7123
    return array(
7124
        'course' => array(
7125
            'create',
7126
            'read',
7127
            'edit',
7128
            'delete'
7129
        ),
7130
        'admin' => array(
7131
            'create',
7132
            'read',
7133
            'edit',
7134
            'delete'
7135
        )
7136
    );
7137
}
7138
7139
/**
7140
 * @param int $courseId
7141
 * @param int $session_id
7142
 * @return bool
7143
 */
7144
function api_coach_can_edit_view_results($courseId = null, $session_id = null)
7145
{
7146
    $user_id = api_get_user_id();
7147
7148
    if (empty($courseId)) {
7149
        $courseId = api_get_course_int_id();
7150
    }
7151
7152
    if (empty($session_id)) {
7153
        $session_id = api_get_session_id();
7154
    }
7155
7156
    if (api_is_platform_admin()) {
7157
        return true;
7158
    }
7159
7160
    $roles = api_detect_user_roles($user_id, $courseId, $session_id);
7161
7162
    if (in_array(SESSION_COURSE_COACH, $roles)) {
7163
        //return api_get_setting('session_tutor_reports_visibility') == 'true';
7164
        return true;
7165
    } else {
7166
        if (in_array(COURSEMANAGER, $roles)) {
7167
            return true;
7168
        }
7169
        return false;
7170
    }
7171
}
7172
7173
function api_get_js_simple($file) {
7174
    return '<script type="text/javascript" src="'.$file.'"></script>'."\n";
7175
}
7176
7177
function api_set_settings_and_plugins() {
7178
    global $_configuration;
7179
    $_setting = array();
7180
    $_plugins = array();
7181
7182
    // access_url == 1 is the default chamilo location
7183
    $settings_by_access_list = array();
7184
    $access_url_id = api_get_current_access_url_id();
7185 View Code Duplication
    if ($access_url_id != 1) {
7186
        $url_info = api_get_access_url($_configuration['access_url']);
7187
        if ($url_info['active'] == 1) {
7188
            $settings_by_access = & api_get_settings(null, 'list', $_configuration['access_url'], 1);
7189
            foreach ($settings_by_access as & $row) {
7190
                if (empty($row['variable'])) {
7191
                    $row['variable'] = 0;
7192
                }
7193
                if (empty($row['subkey'])) {
7194
                    $row['subkey'] = 0;
7195
                }
7196
                if (empty($row['category'])) {
7197
                    $row['category'] = 0;
7198
                }
7199
                $settings_by_access_list[$row['variable']][$row['subkey']][$row['category']] = $row;
7200
            }
7201
        }
7202
    }
7203
7204
    $result = api_get_settings(null, 'list', 1);
7205
7206 View Code Duplication
    foreach ($result as & $row) {
7207
        if ($access_url_id != 1) {
7208
            if ($url_info['active'] == 1) {
7209
                $var = empty($row['variable']) ? 0 : $row['variable'];
7210
                $subkey = empty($row['subkey']) ? 0 : $row['subkey'];
7211
                $category = empty($row['category']) ? 0 : $row['category'];
7212
            }
7213
7214
            if ($row['access_url_changeable'] == 1 && $url_info['active'] == 1) {
7215
                if (isset($settings_by_access_list[$var]) &&
7216
                    $settings_by_access_list[$var][$subkey][$category]['selected_value'] != '') {
7217
                    if ($row['subkey'] == null) {
7218
                        $_setting[$row['variable']] = $settings_by_access_list[$var][$subkey][$category]['selected_value'];
7219
                    } else {
7220
                        $_setting[$row['variable']][$row['subkey']] = $settings_by_access_list[$var][$subkey][$category]['selected_value'];
7221
                    }
7222
                } else {
7223
                    if ($row['subkey'] == null) {
7224
                        $_setting[$row['variable']] = $row['selected_value'];
7225
                    } else {
7226
                        $_setting[$row['variable']][$row['subkey']] = $row['selected_value'];
7227
                    }
7228
                }
7229
            } else {
7230
                if ($row['subkey'] == null) {
7231
                    $_setting[$row['variable']] = $row['selected_value'];
7232
                } else {
7233
                    $_setting[$row['variable']][$row['subkey']] = $row['selected_value'];
7234
                }
7235
            }
7236
        } else {
7237
            if ($row['subkey'] == null) {
7238
                $_setting[$row['variable']] = $row['selected_value'];
7239
            } else {
7240
                $_setting[$row['variable']][$row['subkey']] = $row['selected_value'];
7241
            }
7242
        }
7243
    }
7244
7245
    $result = api_get_settings('Plugins', 'list', $access_url_id);
7246
    $_plugins = array();
7247 View Code Duplication
    foreach ($result as & $row) {
7248
        $key = & $row['variable'];
7249
        if (is_string($_setting[$key])) {
7250
            $_setting[$key] = array();
7251
        }
7252
        $_setting[$key][] = $row['selected_value'];
7253
        $_plugins[$key][] = $row['selected_value'];
7254
    }
7255
7256
    $_SESSION['_setting'] = $_setting;
7257
    $_SESSION['_plugins'] = $_plugins;
7258
}
7259
7260
function api_set_setting_last_update()
7261
{
7262
    // Saving latest refresh.
7263
    api_set_setting('settings_latest_update', api_get_utc_datetime());
7264
}
7265
7266
/**
7267
 * Tries to set memory limit, if authorized and new limit is higher than current
7268
 * @param string New memory limit
7269
 * @param string $mem
7270
 * @return bool True on success, false on failure or current is higher than suggested
7271
 * @assert (null) === false
7272
 * @assert (-1) === false
7273
 * @assert (0) === true
7274
 * @assert ('1G') === true
7275
 */
7276
function api_set_memory_limit($mem){
7277
    //if ini_set() not available, this function is useless
7278
    if (!function_exists('ini_set') || is_null($mem) || $mem == -1) {
7279
        return false;
7280
    }
7281
7282
    $memory_limit = ini_get('memory_limit');
7283
    if (api_get_bytes_memory_limit($mem) > api_get_bytes_memory_limit($memory_limit)){
7284
        ini_set('memory_limit', $mem);
7285
        return true;
7286
    }
7287
    return false;
7288
}
7289
7290
/**
7291
 * Gets memory limit in bytes
7292
 * @param string The memory size (128M, 1G, 1000K, etc)
7293
 * @return int
7294
 * @assert (null) === false
7295
 * @assert ('1t')  === 1099511627776
7296
 * @assert ('1g')  === 1073741824
7297
 * @assert ('1m')  === 1048576
7298
 * @assert ('100k') === 102400
7299
 */
7300
function api_get_bytes_memory_limit($mem){
7301
    $size = strtolower(substr($mem,-1));
7302
7303
    switch ($size) {
7304
        case 't':
7305
            $mem = intval(substr($mem,-1))*1024*1024*1024*1024;
7306
            break;
7307
        case 'g':
7308
            $mem = intval(substr($mem,0,-1))*1024*1024*1024;
7309
            break;
7310
        case 'm':
7311
            $mem = intval(substr($mem,0,-1))*1024*1024;
7312
            break;
7313
        case 'k':
7314
            $mem = intval(substr($mem,0,-1))*1024;
7315
            break;
7316
        default:
7317
            // we assume it's integer only
7318
            $mem = intval($mem);
7319
            break;
7320
    }
7321
    return $mem;
7322
}
7323
7324
/**
7325
 * Finds all the information about a user from username instead of user id
7326
 *
7327
 * @return array $user_info user_id, lastname, firstname, username, email, ...
7328
 * @author Yannick Warnier <[email protected]>
7329
 */
7330 View Code Duplication
function api_get_user_info_from_official_code($official_code = '')
7331
{
7332
    if (empty($official_code)) {
7333
        return false;
7334
    }
7335
    $sql = "SELECT * FROM ".Database :: get_main_table(TABLE_MAIN_USER)."
7336
            WHERE official_code ='".Database::escape_string($official_code)."'";
7337
    $result = Database::query($sql);
7338
    if (Database::num_rows($result) > 0) {
7339
        $result_array = Database::fetch_array($result);
7340
        return _api_format_user($result_array);
7341
    }
7342
    return false;
7343
}
7344
7345
/**
7346
 *
7347
 *
7348
 * @return string
7349
 */
7350
function api_get_password_checker_js($usernameInputId, $passwordInputid)
7351
{
7352
    $checkPass = api_get_setting('allow_strength_pass_checker');
7353
    $useStrengthPassChecker = $checkPass == 'true';
7354
7355
    if ($useStrengthPassChecker == false) {
7356
        return null;
7357
    }
7358
7359
    $verdicts = array(
7360
        get_lang('PasswordWeak'),
7361
        get_lang('PasswordNormal'),
7362
        get_lang('PasswordMedium'),
7363
        get_lang('PasswordStrong'),
7364
        get_lang('PasswordVeryStrong'),
7365
    );
7366
    $js = api_get_js('strength/strength.js');
7367
    $js .=  "<script>
7368
7369
    var verdicts = ['".implode("','", $verdicts)."'];
7370
    var errorMessages = {
7371
        password_to_short : \"" . get_lang('PasswordIsTooShort')."\",
7372
        same_as_username : \"".get_lang('YourPasswordCannotBeTheSameAsYourUsername')."\"
7373
    };
7374
7375
    $(document).ready(function() {
7376
        var options = {
7377
            verdicts: verdicts,
7378
            onLoad : function () {
7379
                //$('#messages').text('Start typing password');
7380
            },
7381
            onKeyUp: function (evt) {
7382
                $(evt.target).pwstrength('outputErrorList');
7383
            },
7384
            errorMessages : errorMessages,
7385
            viewports: {
7386
                progress: '#password_progress',
7387
                verdict: '#password-verdict',
7388
                errors: '#password-errors'
7389
            },
7390
            usernameField: '$usernameInputId'
7391
        };
7392
        $('".$passwordInputid."').pwstrength(options);
7393
    });
7394
    </script>";
7395
    return $js;
7396
}
7397
7398
/**
7399
 * Gets an array with "easy" passwords
7400
 * @return array
7401
 */
7402
function api_get_easy_password_list()
7403
{
7404
    $passwordList = array('123', '1234', '123456', 'admin', 'user', 'student', 'teacher');
7405
    $file = api_get_path(CONFIGURATION_PATH).'easy_password_list.php';
7406
    if (file_exists($file)) {
7407
        $passwordList = require_once $file;
7408
    }
7409
    return $passwordList;
7410
}
7411
7412
/**
7413
 * @param string $username
7414
 * create an user extra field called 'captcha_blocked_until_date'
7415
 */
7416
function api_block_account_captcha($username)
7417
{
7418
    $userInfo = api_get_user_info_from_username($username);
7419
    if (empty($userInfo)) {
7420
        return false;
7421
    }
7422
    $minutesToBlock = api_get_setting('captcha_time_to_block');
7423
    $time = time() + $minutesToBlock*60;
7424
    UserManager::update_extra_field_value(
7425
        $userInfo['user_id'],
7426
        'captcha_blocked_until_date',
7427
        api_get_utc_datetime($time)
7428
    );
7429
}
7430
7431
/**
7432
 * @param string $username
7433
 */
7434
function api_clean_account_captcha($username)
7435
{
7436
    $userInfo = api_get_user_info_from_username($username);
7437
    if (empty($userInfo)) {
7438
        return false;
7439
    }
7440
    Session::erase('loginFailedCount');
7441
    UserManager::update_extra_field_value(
7442
        $userInfo['user_id'],
7443
        'captcha_blocked_until_date',
7444
        null
7445
    );
7446
}
7447
7448
/**
7449
 * @param string $username
7450
 * @return bool
7451
 */
7452
function api_get_user_blocked_by_captcha($username)
7453
{
7454
    $userInfo = api_get_user_info_from_username($username);
7455
    if (empty($userInfo)) {
7456
        return false;
7457
    }
7458
    $data = UserManager::get_extra_user_data_by_field(
7459
        $userInfo['user_id'],
7460
        'captcha_blocked_until_date'
7461
    );
7462
    if (isset($data) && isset($data['captcha_blocked_until_date'])) {
7463
        return $data['captcha_blocked_until_date'];
7464
    }
7465
    return false;
7466
}
7467
7468
/**
7469
 * Remove tags from HTML anf return the $in_number_char first non-HTML char
7470
 * Postfix the text with "..." if it has been truncated.
7471
 * @param integer $in_number_char
7472
 * @return string
7473
 * @author hubert borderiou
7474
 */
7475
function api_get_short_text_from_html($in_html, $in_number_char)
7476
{
7477
    $out_res = api_remove_tags_with_space($in_html, false);
7478
    $postfix = "...";
7479
    if (strlen($out_res) > $in_number_char) {
7480
        $out_res = substr($out_res, 0, $in_number_char).$postfix;
7481
    }
7482
    return $out_res;
7483
}
7484
7485
/**
7486
 * Replace tags with a space in a text.
7487
 * If $in_double_quote_replace, replace " with '' (for HTML attribute purpose, for exemple)
7488
 * @return string
7489
 * @author hubert borderiou
7490
 */
7491
function api_remove_tags_with_space($in_html, $in_double_quote_replace = true) {
7492
    $out_res = $in_html;
7493
    if ($in_double_quote_replace) {
7494
        $out_res = str_replace('"', "''", $out_res);
7495
    }
7496
    // avoid text stuck together when tags are removed, adding a space after >
7497
    $out_res = str_replace (">", "> ", $out_res);
7498
    $out_res = strip_tags($out_res);
7499
7500
    return $out_res;
7501
}
7502
7503
/**
7504
 * If true, the drh can access all content (courses, users) inside a session
7505
 * @return bool
7506
 */
7507
function api_drh_can_access_all_session_content()
7508
{
7509
    $a = api_get_setting('drh_can_access_all_session_content');
7510
    return $a == 'true';
7511
}
7512
7513
/**
7514
 * @param string $tool
7515
 * @param string $setting
7516
 * @param integer $defaultValue
7517
 * @return string
7518
 */
7519
function api_get_default_tool_setting($tool, $setting, $defaultValue)
7520
{
7521
    global $_configuration;
7522
    if (isset($_configuration[$tool]) &&
7523
        isset($_configuration[$tool]['default_settings']) &&
7524
        isset($_configuration[$tool]['default_settings'][$setting])
7525
    ) {
7526
        return $_configuration[$tool]['default_settings'][$setting];
7527
    }
7528
    return $defaultValue;
7529
7530
}
7531
7532
/**
7533
 * Checks if user can login as another user
7534
 *
7535
 * @param int $loginAsUserId the user id to log in
7536
 * @param int $userId my user id
7537
 * @return bool
7538
 */
7539
function api_can_login_as($loginAsUserId, $userId = null)
7540
{
7541
    if (empty($userId)) {
7542
        $userId = api_get_user_id();
7543
    }
7544
    if ($loginAsUserId == $userId) {
7545
        return false;
7546
    }
7547
7548
    if (empty($loginAsUserId)) {
7549
        return false;
7550
    }
7551
7552
    if ($loginAsUserId != strval(intval($loginAsUserId))) {
7553
        return false;
7554
    }
7555
    // Check if the user to login is an admin
7556
7557
    if (api_is_platform_admin_by_id($loginAsUserId)) {
7558
        // Only super admins can login to admin accounts
7559
        if (!api_global_admin_can_edit_admin($loginAsUserId)) {
7560
            return false;
7561
        }
7562
    }
7563
7564
    $userInfo = api_get_user_info($userId);
7565
7566
    $isDrh = function() use($loginAsUserId) {
7567
        if (api_is_drh()) {
7568
            if (api_drh_can_access_all_session_content()) {
7569
                $users = SessionManager::getAllUsersFromCoursesFromAllSessionFromStatus('drh_all', api_get_user_id());
7570
                $userList = array();
7571
                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...
7572
                    $userList[] = $user['user_id'];
7573
                }
7574
                if (in_array($loginAsUserId, $userList)) {
7575
                    return true;
7576
                }
7577
            } else {
7578
                if (api_is_drh() && UserManager::is_user_followed_by_drh($loginAsUserId, api_get_user_id())) {
7579
                    return true;
7580
                }
7581
            }
7582
        }
7583
        return false;
7584
    };
7585
7586
    return api_is_platform_admin() || (api_is_session_admin() && $userInfo['status'] == 5) || $isDrh();
7587
}
7588
7589
/**
7590
 * @return bool
7591
 */
7592
function api_is_allowed_in_course()
7593
{
7594
    return Session::read('is_allowed_in_course');
7595
}
7596
7597
/**
7598
 * Show a string in
7599
 * @param string $string Some string to dump, removing tabs, spaces,
7600
 * newlines, etc (usually most useful for SQL queries)
7601
 * @param int $dump Set to 1 to use print_r()
7602
 */
7603
function api_error_log($string, $dump = 0)
7604
{
7605
    // Clean query
7606
    $bt = debug_backtrace();
7607
    $caller = array_shift($bt);;
7608
    if ($dump == 1) {
7609
        $string = print_r($string, 1);
7610
    } else {
7611
        $string = str_replace(array("\r", "\n", "\t", "\10"), '', $string);
7612
        $string = str_replace('    ',' ', $string);
7613
    }
7614
7615
    error_log("-------------------------------------");
7616
    error_log($string);
7617
    error_log("File: ".$caller['file']." +".$caller['line']);
7618
    error_log("-------------------------------------");
7619
}
7620
7621
/**
7622
 * Set the cookie to go directly to the course code $in_firstpage
7623
 * after login
7624
 * @param string $in_firstpage is the course code of the course to go
7625
 */
7626
function api_set_firstpage_parameter($in_firstpage)
7627
{
7628
    setcookie("GotoCourse", $in_firstpage);
7629
}
7630
7631
/**
7632
 * Delete the cookie to go directly to the course code $in_firstpage
7633
 * after login
7634
 */
7635
function api_delete_firstpage_parameter()
7636
{
7637
    setcookie("GotoCourse", "", time() - 3600);
7638
}
7639
7640
/**
7641
 * @return boolean if course_code for direct course access after login is set
7642
 */
7643
function exist_firstpage_parameter()
7644
{
7645
    return (isset($_COOKIE['GotoCourse']) && $_COOKIE['GotoCourse'] != "");
7646
}
7647
7648
/**
7649
 * @return return the course_code of the course where user login
7650
 */
7651
function api_get_firstpage_parameter()
7652
{
7653
    return $_COOKIE['GotoCourse'];
7654
}
7655
7656
/**
7657
 * Return true on https install
7658
 * @return boolean
7659
 */
7660
function api_is_https()
7661
{
7662
    return (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] != 'off');
7663
}
7664
7665
/**
7666
 * Return protocol (http or https)
7667
 * @return string
7668
 */
7669
function api_get_protocol()
7670
{
7671
    return api_is_https() ? 'https' : 'http';
7672
}
7673
7674
/**
7675
 * Return a string where " are replaced with 2 '
7676
 * It is useful when you pass a PHP variable in a Javascript browser dialog
7677
 * e.g. : alert("<?php get_lang('Message') ?>");
7678
 * and message contains character "
7679
 *
7680
 * @param string $in_text
7681
 * @return string
7682
 */
7683
function convert_double_quote_to_single($in_text) {
7684
    return api_preg_replace('/"/', "''", $in_text);
7685
}
7686
7687
/**
7688
 * Get origin
7689
 *
7690
 * @param string
7691
 * @return string
7692
 **/
7693
function api_get_origin()
7694
{
7695
    if (isset($_REQUEST['origin'])) {
7696
        return $_REQUEST['origin'] == 'learnpath' ? 'learnpath' : null;
7697
    }
7698
7699
    return null;
7700
}
7701
7702
/**
7703
 * Warns an user that the portal reach certain limit.
7704
 * @param string $limitName
7705
 */
7706
function api_warn_hosting_contact($limitName)
7707
{
7708
    $hostingParams = api_get_configuration_value(1);
7709
    $email = null;
7710
7711
    if (!empty($hostingParams)) {
7712
        if (isset($hostingParams['hosting_contact_mail'])) {
7713
            $email = $hostingParams['hosting_contact_mail'];
7714
        }
7715
    }
7716
7717
    if (!empty($email)) {
7718
        $subject = get_lang('HostingWarningReached');
7719
        $body = get_lang('PortalName').': '.api_get_path(WEB_PATH)." \n ";
7720
        $body .= get_lang('PortalLimitType').': '.$limitName." \n ";
7721
        if (isset($hostingParams[$limitName])) {
7722
            $body .= get_lang('Value') . ': ' . $hostingParams[$limitName];
7723
        }
7724
        api_mail_html(null, $email, $subject, $body);
7725
    }
7726
}
7727
7728
/**
7729
 * @param string $variable
7730
 * @return bool|mixed
7731
 */
7732
function api_get_configuration_value($variable)
7733
{
7734
    global $_configuration;
7735
    if (isset($_configuration[$variable])) {
7736
        return $_configuration[$variable];
7737
    }
7738
    return false;
7739
}
7740
7741
/**
7742
 * Returns supported image extensions in the portal
7743
 * @return  array   Supported image extensions in the portal
7744
 */
7745
function api_get_supported_image_extensions()
7746
{
7747
    // jpg can also be called jpeg, jpe, jfif and jif. See https://en.wikipedia.org/wiki/JPEG#JPEG_filename_extensions
7748
    $supportedImageExtensions = array('jpg', 'jpeg', 'png', 'gif', 'svg', 'jpe', 'jfif', 'jif');
7749
    if (version_compare(PHP_VERSION, '5.5.0', '>=')) {
7750
        array_push($supportedImageExtensions, 'webp');
7751
    }
7752
    return $supportedImageExtensions;
7753
}
7754
7755
/**
7756
 * This setting changes the registration status for the campus
7757
 *
7758
 * @author Patrick Cool <[email protected]>, Ghent University
7759
 * @version August 2006
7760
 * @param   bool    $listCampus Whether we authorize
7761
 * @todo the $_settings should be reloaded here. => write api function for this and use this in global.inc.php also.
7762
 */
7763 View Code Duplication
function api_register_campus($listCampus = true) {
7764
    $tbl_settings = Database :: get_main_table(TABLE_MAIN_SETTINGS_CURRENT);
7765
7766
    $sql = "UPDATE $tbl_settings SET selected_value='true' WHERE variable='registered'";
7767
    Database::query($sql);
7768
7769
    if (!$listCampus) {
7770
        $sql = "UPDATE $tbl_settings SET selected_value='true' WHERE variable='donotlistcampus'";
7771
        Database::query($sql);
7772
    }
7773
}
7774
7775
/**
7776
 * Checks whether current user is a student boss
7777
 * @global array $_user
7778
 * @return boolean
7779
 */
7780
function api_is_student_boss()
7781
{
7782
    $_user = api_get_user_info();
7783
7784
    return isset($_user['status']) && $_user['status'] == STUDENT_BOSS;
7785
}
7786
7787
/**
7788
 * Check whether the user type should be exclude.
7789
 * Such as invited or anonymous users
7790
 * @param boolean $checkDB Optional. Whether check the user status
7791
 * @param int $userId Options. The user id
7792
 *
7793
 * @return boolean
7794
 */
7795
function api_is_excluded_user_type($checkDB = false, $userId = 0)
7796
{
7797
    if ($checkDB) {
7798
        $userId = empty($userId) ? api_get_user_id() : intval($userId);
7799
7800
        if ($userId == 0) {
7801
            return true;
7802
        }
7803
7804
        $userInfo = api_get_user_info($userId);
7805
7806
        switch ($userInfo['status']) {
7807
            case INVITEE:
7808
                //no break;
7809
            case ANONYMOUS:
7810
                return true;
7811
            default:
7812
                return false;
7813
        }
7814
    }
7815
7816
    $isInvited = api_is_invitee();
7817
    $isAnonymous = api_is_anonymous();
7818
7819
    if ($isInvited || $isAnonymous) {
7820
        return true;
7821
    }
7822
7823
    return false;
7824
}
7825
7826
/**
7827
 * Get the user status to ignore in reports
7828
 * @param string $format Optional. The result type (array or string)
7829
 * @return array|string
7830
 */
7831
function api_get_users_status_ignored_in_reports($format = 'array')
7832
{
7833
    $excludedTypes = array(
7834
        INVITEE,
7835
        ANONYMOUS
7836
    );
7837
7838
    if ($format == 'string') {
7839
        return implode(', ', $excludedTypes);
7840
    }
7841
7842
    return $excludedTypes;
7843
}
7844
7845
/**
7846
 * Set the Site Use Cookie Warning for 1 year
7847
 */
7848
function api_set_site_use_cookie_warning_cookie()
7849
{
7850
    setcookie("ChamiloUsesCookies", "ok", time()+31556926);
7851
}
7852
7853
/**
7854
 * Return true if the Site Use Cookie Warning Cookie warning exists
7855
 * @return bool
7856
 */
7857
function api_site_use_cookie_warning_cookie_exist()
7858
{
7859
    return isset($_COOKIE['ChamiloUsesCookies']);
7860
}
7861
7862
/**
7863
 * Given a number of seconds, format the time to show hours, minutes and seconds
7864
 * @param int $time The time in seconds
7865
 * @param string $originFormat Optional. PHP o JS
7866
 * @return string (00h00'00")
7867
 */
7868
function api_format_time($time, $originFormat = 'php')
7869
{
7870
    $h = get_lang('h');
7871
    $hours = $time / 3600;
7872
    $mins = ($time % 3600) / 60;
7873
    $secs = ($time % 60);
7874
7875
    if ($originFormat == 'js') {
7876
        $formattedTime = trim(sprintf("%02d : %02d : %02d", $hours, $mins, $secs));
7877
    } else {
7878
        $formattedTime = trim(sprintf("%02d$h%02d'%02d\"", $hours, $mins, $secs));
7879
    }
7880
7881
    return $formattedTime;
7882
}
7883
7884
/**
7885
 * Create a new empty directory with index.html file
7886
 * @param string $name The new directory name
7887
 * @param string $parentDirectory Directory parent directory name
7888
 * @return boolean Return true if the directory was create. Otherwise return false
7889
 */
7890
function api_create_protected_dir($name, $parentDirectory)
7891
{
7892
    $isCreated = false;
7893
7894
    if (!is_writable($parentDirectory)) {
7895
        return false;
7896
    }
7897
7898
    $fullPath = $parentDirectory . api_replace_dangerous_char($name);
7899
7900
    if (mkdir($fullPath, api_get_permissions_for_new_directories(), true)) {
7901
        $fp = fopen($fullPath . '/index.html', 'w');
7902
7903
        if ($fp) {
7904
            if (fwrite($fp, '<html><head></head><body></body></html>')) {
7905
                $isCreated = true;
7906
            }
7907
        }
7908
7909
        fclose($fp);
7910
    }
7911
7912
    return $isCreated;
7913
}
7914
7915
/**
7916
 * Sends an HTML email using the phpmailer class (and multipart/alternative to downgrade gracefully)
7917
 * Sender name and email can be specified, if not specified
7918
 * name and email of the platform admin are used
7919
 *
7920
 * @author Bert Vanderkimpen ICT&O UGent
7921
 * @author Yannick Warnier <[email protected]>
7922
 *
7923
 * @param string    name of recipient
7924
 * @param string    email of recipient
7925
 * @param string    email subject
7926
 * @param string    email body
7927
 * @param string    sender name
7928
 * @param string    sender e-mail
7929
 * @param array     extra headers in form $headers = array($name => $value) to allow parsing
7930
 * @param array     data file (path and filename)
7931
 * @param bool      True for attaching a embedded file inside content html (optional)
7932
 * @param array     Additional parameters
7933
 * @return          integer true if mail was sent
7934
 * @see             class.phpmailer.php
7935
 */
7936
function api_mail_html(
7937
    $recipient_name,
7938
    $recipient_email,
7939
    $subject,
7940
    $message,
7941
    $senderName = '',
7942
    $senderEmail = '',
7943
    $extra_headers = array(),
7944
    $data_file = array(),
7945
    $embedded_image = false,
7946
    $additionalParameters = array()
7947
) {
7948
    global $platform_email;
7949
7950
    $mail = new PHPMailer();
7951
    $mail->Mailer = $platform_email['SMTP_MAILER'];
7952
    $mail->Host = $platform_email['SMTP_HOST'];
7953
    $mail->Port = $platform_email['SMTP_PORT'];
7954
    $mail->CharSet = $platform_email['SMTP_CHARSET'];
7955
    // Stay far below SMTP protocol 980 chars limit.
7956
    $mail->WordWrap = 200;
7957
7958
    if ($platform_email['SMTP_AUTH']) {
7959
        $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...
7960
        $mail->Username = $platform_email['SMTP_USER'];
7961
        $mail->Password = $platform_email['SMTP_PASS'];
7962
        if (isset($platform_email['SMTP_SECURE'])) {
7963
            $mail->SMTPSecure = $platform_email['SMTP_SECURE'];
7964
        }
7965
    }
7966
    $mail->SMTPDebug = isset($platform_email['SMTP_DEBUG'])?$platform_email['SMTP_DEBUG']:0;
7967
7968
    // 5 = low, 1 = high
7969
    $mail->Priority = 3;
7970
    $mail->SMTPKeepAlive = true;
7971
7972
    // Default values
7973
    $notification = new Notification();
7974
    $defaultEmail = $notification->getDefaultPlatformSenderEmail();
7975
    $defaultName = $notification->getDefaultPlatformSenderName();
7976
7977
    // Error to admin.
7978
    $mail->AddCustomHeader('Errors-To: '.$defaultEmail);
7979
7980
    // If the parameter is set don't use the admin.
7981
    $senderName = !empty($senderName) ? $senderName : $defaultName;
7982
    $senderEmail = !empty($senderEmail) ? $senderEmail : $defaultEmail;
7983
7984
    // Reply to first
7985
    if (isset($extra_headers['reply_to'])) {
7986
        $mail->AddReplyTo(
7987
            $extra_headers['reply_to']['mail'],
7988
            $extra_headers['reply_to']['name']
7989
        );
7990
        $mail->Sender = $extra_headers['reply_to']['mail'];
7991
        unset($extra_headers['reply_to']);
7992
    }
7993
    //If the SMTP configuration only accept one sender
7994
    if ($platform_email['SMTP_UNIQUE_SENDER']) {
7995
        $senderName = $platform_email['SMTP_FROM_NAME'];
7996
        $senderEmail = $platform_email['SMTP_FROM_EMAIL'];
7997
    }
7998
    $mail->SetFrom($senderEmail, $senderName);
7999
8000
    $mail->Subject = $subject;
8001
    $mail->AltBody = strip_tags(
8002
        str_replace('<br />', "\n", api_html_entity_decode($message))
8003
    );
8004
8005
    // Send embedded image.
8006
    if ($embedded_image) {
8007
        // Get all images html inside content.
8008
        preg_match_all("/<img\s+.*?src=[\"\']?([^\"\' >]*)[\"\']?[^>]*>/i", $message, $m);
8009
        // Prepare new tag images.
8010
        $new_images_html = array();
8011
        $i = 1;
8012
        if (!empty($m[1])) {
8013
            foreach ($m[1] as $image_path) {
8014
                $real_path = realpath($image_path);
8015
                $filename  = basename($image_path);
8016
                $image_cid = $filename.'_'.$i;
8017
                $encoding = 'base64';
8018
                $image_type = mime_content_type($real_path);
8019
                $mail->AddEmbeddedImage(
8020
                    $real_path,
8021
                    $image_cid,
8022
                    $filename,
8023
                    $encoding,
8024
                    $image_type
0 ignored issues
show
Bug introduced by
It seems like $image_type defined by mime_content_type($real_path) on line 8018 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...
8025
                );
8026
                $new_images_html[] = '<img src="cid:'.$image_cid.'" />';
8027
                $i++;
8028
            }
8029
        }
8030
8031
        // Replace origin image for new embedded image html.
8032
        $x = 0;
8033
        if (!empty($m[0])) {
8034
            foreach ($m[0] as $orig_img) {
8035
                $message = str_replace($orig_img, $new_images_html[$x], $message);
8036
                $x++;
8037
            }
8038
        }
8039
    }
8040
8041
    $mailView = new Template(null, false, false, false, false, false, false);
8042
    $mailView->assign('content', $message);
8043
8044
    if (isset($additionalParameters['link'])) {
8045
        $mailView->assign('link', $additionalParameters['link']);
8046
    }
8047
8048
    $layout = $mailView->get_template('mail/mail.tpl');
8049
    $mail->Body = $mailView->fetch($layout);
8050
8051
    // Attachment ...
8052
    if (!empty($data_file)) {
8053
        $o = 0;
8054 View Code Duplication
        foreach ($data_file as $file_attach) {
8055
            if (!empty($file_attach['path']) && !empty($file_attach['filename'])) {
8056
                $mail->AddAttachment($file_attach['path'], $file_attach['filename']);
8057
            }
8058
            $o++;
8059
        }
8060
    } elseif (is_array($_FILES)) {
8061
        $data_file = $_FILES;
8062
        $o = 0;
8063 View Code Duplication
        foreach ($data_file as $file_attach) {
8064
            if (!empty($file_attach['tmp_name']) && !empty($file_attach['name'])) {
8065
                $mail->AddAttachment($file_attach['tmp_name'], $file_attach['name']);
8066
            }
8067
            $o++;
8068
        }
8069
    }
8070
8071
    // Only valid addresses are accepted.
8072
    if (is_array($recipient_email)) {
8073
        foreach ($recipient_email as $dest) {
8074
            if (api_valid_email($dest)) {
8075
                $mail->AddAddress($dest, $recipient_name);
8076
            }
8077
        }
8078
    } else {
8079
        if (api_valid_email($recipient_email)) {
8080
            $mail->AddAddress($recipient_email, $recipient_name);
8081
        } else {
8082
            return 0;
8083
        }
8084
    }
8085
8086
    if (is_array($extra_headers) && count($extra_headers) > 0) {
8087
        foreach ($extra_headers as $key => $value) {
8088
            switch (strtolower($key)) {
8089
                case 'encoding':
8090
                case 'content-transfer-encoding':
8091
                    $mail->Encoding = $value;
8092
                    break;
8093
                case 'charset':
8094
                    $mail->Charset = $value;
8095
                    break;
8096
                case 'contenttype':
8097
                case 'content-type':
8098
                    $mail->ContentType = $value;
8099
                    break;
8100
                default:
8101
                    $mail->AddCustomHeader($key.':'.$value);
8102
                    break;
8103
            }
8104
        }
8105
    } else {
8106
        if (!empty($extra_headers)) {
8107
            $mail->AddCustomHeader($extra_headers);
8108
        }
8109
    }
8110
8111
    // WordWrap the html body (phpMailer only fixes AltBody) FS#2988
8112
    $mail->Body = $mail->WrapText($mail->Body, $mail->WordWrap);
8113
    // Send the mail message.
8114
    if (!$mail->Send()) {
8115
        error_log('ERROR: mail not sent to '.$recipient_name.' ('.$recipient_email.') because of '.$mail->ErrorInfo.'<br />');
8116
        if ($mail->SMTPDebug) {
8117
            error_log(
8118
                "Connection details :: " .
8119
                "Protocol: " . $mail->Mailer . ' :: ' .
8120
                "Host/Port: " . $mail->Host . ':' . $mail->Port . ' :: ' .
8121
                "Authent/Open: " . ($mail->SMTPAuth?'Authent':'Open') . ' :: ' .
8122
                ($mail->SMTPAuth?"  User/Pass: " . $mail->Username . ':' . $mail->Password:'')
8123
            );
8124
        }
8125
        return 0;
8126
    }
8127
8128
    if (!empty($additionalParameters)) {
8129
        $plugin = new AppPlugin();
8130
        $smsPlugin = $plugin->getSMSPluginLibrary();
8131
        if ($smsPlugin) {
8132
            $smsPlugin->send($additionalParameters);
8133
        }
8134
    }
8135
8136
    // Clear all the addresses.
8137
    $mail->ClearAddresses();
8138
    return 1;
8139
}
8140
8141
/**
8142
 * @param string $tool Possible values:
8143
 * GroupManager::GROUP_TOOL_*
8144
 *
8145
 */
8146
function api_protect_course_group($tool, $showHeader = true)
8147
{
8148
    $userId = api_get_user_id();
8149
    $groupId = api_get_group_id();
8150
8151
    if (!empty($groupId)) {
8152
        $allow = GroupManager::user_has_access(
8153
            $userId,
8154
            $groupId,
8155
            $tool
8156
        );
8157
8158
        if (!$allow) {
8159
            api_not_allowed($showHeader);
8160
        }
8161
    }
8162
}
8163
8164
/**
8165
 * Eliminate the duplicates of a multidimensional array by sending the key
8166
 * @param array $array multidimensional array
8167
 * @param int $key key to find to compare
8168
 *
8169
 */
8170
function api_unique_multidim_array($array, $key){
8171
    $temp_array = array();
8172
    $i = 0;
8173
    $key_array = array();
8174
8175
    foreach($array as $val){
8176
        if(!in_array($val[$key],$key_array)){
8177
            $key_array[$i] = $val[$key];
8178
            $temp_array[$i] = $val;
8179
        }
8180
        $i++;
8181
    }
8182
    return $temp_array;
8183
}
8184
8185
/**
8186
 * Limit the access to Session Admins wheen the limit_session_admin_role
8187
 * configuration variable is set to true
8188
 */
8189
function api_protect_limit_for_session_admin()
8190
{
8191
    $limitAdmin = api_get_setting('limit_session_admin_role');
8192
    if (api_is_session_admin() && $limitAdmin === 'true') {
8193
        api_not_allowed(true);
8194
    }
8195
}
8196
8197
function api_is_student_view_active() {
8198
    return (isset($_SESSION['studentview']) && $_SESSION['studentview'] == "studentview");
8199
}
8200
8201
/**
8202
 * Like strip_tags(), but leaves an additional space and removes only the given tags
8203
 * @param string $string
8204
 * @param array $tags Tags to be removed
8205
 * @return  string The original string without the given tags
8206
 */
8207
function stripGivenTags($string, $tags) {
8208
    foreach ($tags as $tag) {
8209
        $string2 = preg_replace('#</' . $tag . '[^>]*>#i', ' ', $string);
8210
        if ($string2 != $string) {
8211
            $string = preg_replace('/<' . $tag . '[^>]*>/i', ' ', $string2);
8212
        }
8213
    }
8214
    return $string;
8215
}
8216
8217