Completed
Pull Request — 1.10.x (#1499)
by
unknown
52:23 queued 20:38
created

api.lib.php ➔ api_number_format()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

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