Completed
Pull Request — 1.11.x (#1193)
by José
260:58 queued 217:16
created

api.lib.php ➔ apiIsDateInDateRange()   A

Complexity

Conditions 3
Paths 2

Size

Total Lines 12
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Importance

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